1139749Simp/*- 259743Sgroudier * Device driver optimized for the Symbios/LSI 53C896/53C895A/53C1010 359743Sgroudier * PCI-SCSI controllers. 459743Sgroudier * 586266Sgroudier * Copyright (C) 1999-2001 Gerard Roudier <groudier@free.fr> 659743Sgroudier * 759743Sgroudier * This driver also supports the following Symbios/LSI PCI-SCSI chips: 859743Sgroudier * 53C810A, 53C825A, 53C860, 53C875, 53C876, 53C885, 53C895, 959743Sgroudier * 53C810, 53C815, 53C825 and the 53C1510D is 53C8XX mode. 1059743Sgroudier * 1159743Sgroudier * 1259743Sgroudier * This driver for FreeBSD-CAM is derived from the Linux sym53c8xx driver. 1359743Sgroudier * Copyright (C) 1998-1999 Gerard Roudier 1459743Sgroudier * 1559743Sgroudier * The sym53c8xx driver is derived from the ncr53c8xx driver that had been 1659743Sgroudier * a port of the FreeBSD ncr driver to Linux-1.2.13. 1759743Sgroudier * 1859743Sgroudier * The original ncr driver has been written for 386bsd and FreeBSD by 1959743Sgroudier * Wolfgang Stanglmeier <wolf@cologne.de> 2059743Sgroudier * Stefan Esser <se@mi.Uni-Koeln.de> 2159743Sgroudier * Copyright (C) 1994 Wolfgang Stanglmeier 2259743Sgroudier * 2359743Sgroudier * The initialisation code, and part of the code that addresses 2459743Sgroudier * FreeBSD-CAM services is based on the aic7xxx driver for FreeBSD-CAM 2559743Sgroudier * written by Justin T. Gibbs. 2659743Sgroudier * 2759743Sgroudier * Other major contributions: 2859743Sgroudier * 2959743Sgroudier * NVRAM detection and reading. 3059743Sgroudier * Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk> 3159743Sgroudier * 3259743Sgroudier *----------------------------------------------------------------------------- 3359743Sgroudier * 3459743Sgroudier * Redistribution and use in source and binary forms, with or without 3559743Sgroudier * modification, are permitted provided that the following conditions 3659743Sgroudier * are met: 3759743Sgroudier * 1. Redistributions of source code must retain the above copyright 3859743Sgroudier * notice, this list of conditions and the following disclaimer. 3959743Sgroudier * 2. Redistributions in binary form must reproduce the above copyright 4059743Sgroudier * notice, this list of conditions and the following disclaimer in the 4159743Sgroudier * documentation and/or other materials provided with the distribution. 4259743Sgroudier * 3. The name of the author may not be used to endorse or promote products 4359743Sgroudier * derived from this software without specific prior written permission. 4459743Sgroudier * 4559743Sgroudier * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 4659743Sgroudier * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4759743Sgroudier * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4859743Sgroudier * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 4959743Sgroudier * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 5059743Sgroudier * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 5159743Sgroudier * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5259743Sgroudier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 5359743Sgroudier * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5459743Sgroudier * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5559743Sgroudier * SUCH DAMAGE. 5659743Sgroudier */ 5759743Sgroudier 5859743Sgroudier/* $FreeBSD$ */ 5959743Sgroudier 6059743Sgroudier/* 6159743Sgroudier * Scripts for SYMBIOS-Processor 6259743Sgroudier * 6359743Sgroudier * We have to know the offsets of all labels before we reach 6459743Sgroudier * them (for forward jumps). Therefore we declare a struct 6559743Sgroudier * here. If you make changes inside the script, 6659743Sgroudier * 6759743Sgroudier * DONT FORGET TO CHANGE THE LENGTHS HERE! 6859743Sgroudier */ 6959743Sgroudier 7059743Sgroudier/* 7159743Sgroudier * Script fragments which are loaded into the on-chip RAM 7259743Sgroudier * of 825A, 875, 876, 895, 895A, 896 and 1010 chips. 7359743Sgroudier * Must not exceed 4K bytes. 7459743Sgroudier */ 7559743Sgroudierstruct SYM_FWA_SCR { 7659743Sgroudier u32 start [ 14]; 7759743Sgroudier u32 getjob_begin [ 4]; 7859743Sgroudier u32 getjob_end [ 4]; 7959743Sgroudier u32 select [ 8]; 8059743Sgroudier u32 wf_sel_done [ 2]; 8160134Sgroudier u32 sel_done [ 2]; 8259743Sgroudier u32 send_ident [ 2]; 8359743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT 8459743Sgroudier u32 select2 [ 8]; 8559743Sgroudier#else 8659743Sgroudier u32 select2 [ 2]; 8759743Sgroudier#endif 8859743Sgroudier u32 command [ 2]; 8959743Sgroudier u32 dispatch [ 28]; 9059743Sgroudier u32 sel_no_cmd [ 10]; 9159743Sgroudier u32 init [ 6]; 9259743Sgroudier u32 clrack [ 4]; 9359743Sgroudier u32 disp_status [ 4]; 9459743Sgroudier u32 datai_done [ 26]; 9559743Sgroudier u32 datao_done [ 12]; 9659743Sgroudier u32 datai_phase [ 2]; 9760134Sgroudier u32 datao_phase [ 4]; 9859743Sgroudier u32 msg_in [ 2]; 9959743Sgroudier u32 msg_in2 [ 10]; 10059743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT 10159743Sgroudier u32 status [ 14]; 10259743Sgroudier#else 10359743Sgroudier u32 status [ 10]; 10459743Sgroudier#endif 10559743Sgroudier u32 complete [ 8]; 10659743Sgroudier u32 complete2 [ 12]; 10759743Sgroudier u32 complete_error [ 4]; 10859743Sgroudier u32 done [ 14]; 10959743Sgroudier u32 done_end [ 2]; 11059743Sgroudier u32 save_dp [ 8]; 11159743Sgroudier u32 restore_dp [ 4]; 11259743Sgroudier u32 disconnect [ 20]; 11359743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT 11459743Sgroudier u32 idle [ 4]; 11559743Sgroudier#else 11659743Sgroudier u32 idle [ 2]; 11759743Sgroudier#endif 11859743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT 11959743Sgroudier u32 ungetjob [ 6]; 12059743Sgroudier#else 12159743Sgroudier u32 ungetjob [ 4]; 12259743Sgroudier#endif 12359743Sgroudier u32 reselect [ 4]; 12459743Sgroudier u32 reselected [ 22]; 12559743Sgroudier u32 resel_scntl4 [ 20]; 12659743Sgroudier u32 resel_lun0 [ 6]; 12759743Sgroudier#if SYM_CONF_MAX_TASK*4 > 512 12859743Sgroudier u32 resel_tag [ 26]; 12959743Sgroudier#elif SYM_CONF_MAX_TASK*4 > 256 13059743Sgroudier u32 resel_tag [ 20]; 13159743Sgroudier#else 13259743Sgroudier u32 resel_tag [ 16]; 13359743Sgroudier#endif 13459743Sgroudier u32 resel_dsa [ 2]; 13559743Sgroudier u32 resel_dsa1 [ 6]; 13659743Sgroudier u32 resel_no_tag [ 6]; 13759743Sgroudier u32 data_in [SYM_CONF_MAX_SG * 2]; 13859743Sgroudier u32 data_in2 [ 4]; 13959743Sgroudier u32 data_out [SYM_CONF_MAX_SG * 2]; 14059743Sgroudier u32 data_out2 [ 4]; 14159743Sgroudier u32 pm0_data [ 12]; 14259743Sgroudier u32 pm0_data_out [ 6]; 14359743Sgroudier u32 pm0_data_end [ 6]; 14459743Sgroudier u32 pm1_data [ 12]; 14559743Sgroudier u32 pm1_data_out [ 6]; 14659743Sgroudier u32 pm1_data_end [ 6]; 14759743Sgroudier}; 14859743Sgroudier 14959743Sgroudier/* 15059743Sgroudier * Script fragments which stay in main memory for all chips 15159743Sgroudier * except for chips that support 8K on-chip RAM. 15259743Sgroudier */ 15359743Sgroudierstruct SYM_FWB_SCR { 15459743Sgroudier u32 start64 [ 2]; 15559743Sgroudier u32 no_data [ 2]; 15659743Sgroudier u32 sel_for_abort [ 18]; 15759743Sgroudier u32 sel_for_abort_1 [ 2]; 15859743Sgroudier u32 msg_in_etc [ 12]; 15959743Sgroudier u32 msg_received [ 4]; 16059743Sgroudier u32 msg_weird_seen [ 4]; 16159743Sgroudier u32 msg_extended [ 20]; 16259743Sgroudier u32 msg_bad [ 6]; 16359743Sgroudier u32 msg_weird [ 4]; 16459743Sgroudier u32 msg_weird1 [ 8]; 16559743Sgroudier 16659743Sgroudier u32 wdtr_resp [ 6]; 16759743Sgroudier u32 send_wdtr [ 4]; 16859743Sgroudier u32 sdtr_resp [ 6]; 16959743Sgroudier u32 send_sdtr [ 4]; 17059743Sgroudier u32 ppr_resp [ 6]; 17159743Sgroudier u32 send_ppr [ 4]; 17259743Sgroudier u32 nego_bad_phase [ 4]; 17359743Sgroudier u32 msg_out [ 4]; 17459743Sgroudier u32 msg_out_done [ 4]; 17559743Sgroudier u32 data_ovrun [ 2]; 17659743Sgroudier u32 data_ovrun1 [ 22]; 17759743Sgroudier u32 data_ovrun2 [ 8]; 17859743Sgroudier u32 abort_resel [ 16]; 17959743Sgroudier u32 resend_ident [ 4]; 18059743Sgroudier u32 ident_break [ 4]; 18159743Sgroudier u32 ident_break_atn [ 4]; 18259743Sgroudier u32 sdata_in [ 6]; 18359743Sgroudier u32 resel_bad_lun [ 4]; 18459743Sgroudier u32 bad_i_t_l [ 4]; 18559743Sgroudier u32 bad_i_t_l_q [ 4]; 18659743Sgroudier u32 bad_status [ 6]; 18759743Sgroudier u32 pm_handle [ 20]; 18859743Sgroudier u32 pm_handle1 [ 4]; 18959743Sgroudier u32 pm_save [ 4]; 19059743Sgroudier u32 pm0_save [ 14]; 19159743Sgroudier u32 pm1_save [ 14]; 19259743Sgroudier 19359743Sgroudier /* WSR handling */ 19459743Sgroudier u32 pm_wsr_handle [ 42]; 19559743Sgroudier u32 wsr_ma_helper [ 4]; 19659743Sgroudier 19759743Sgroudier /* Data area */ 19859743Sgroudier u32 zero [ 1]; 19959743Sgroudier u32 scratch [ 1]; 20059743Sgroudier u32 pm0_data_addr [ 1]; 20159743Sgroudier u32 pm1_data_addr [ 1]; 20259743Sgroudier u32 saved_dsa [ 1]; 20359743Sgroudier u32 saved_drs [ 1]; 20459743Sgroudier u32 done_pos [ 1]; 20559743Sgroudier u32 startpos [ 1]; 20659743Sgroudier u32 targtbl [ 1]; 20759743Sgroudier /* End of data area */ 20859743Sgroudier 20959743Sgroudier u32 snooptest [ 6]; 21059743Sgroudier u32 snoopend [ 2]; 21159743Sgroudier}; 21259743Sgroudier 213179029Smariusstatic const struct SYM_FWA_SCR SYM_FWA_SCR = { 21459743Sgroudier/*--------------------------< START >----------------------------*/ { 21559743Sgroudier /* 21659743Sgroudier * Switch the LED on. 21759743Sgroudier * Will be patched with a NO_OP if LED 21859743Sgroudier * not needed or not desired. 21959743Sgroudier */ 22059743Sgroudier SCR_REG_REG (gpreg, SCR_AND, 0xfe), 22159743Sgroudier 0, 22259743Sgroudier /* 22359743Sgroudier * Clear SIGP. 22459743Sgroudier */ 22559743Sgroudier SCR_FROM_REG (ctest2), 22659743Sgroudier 0, 22759743Sgroudier /* 22859743Sgroudier * Stop here if the C code wants to perform 22959743Sgroudier * some error recovery procedure manually. 23059743Sgroudier * (Indicate this by setting SEM in ISTAT) 23159743Sgroudier */ 23259743Sgroudier SCR_FROM_REG (istat), 23359743Sgroudier 0, 23459743Sgroudier /* 23559743Sgroudier * Report to the C code the next position in 23659743Sgroudier * the start queue the SCRIPTS will schedule. 23759743Sgroudier * The C code must not change SCRATCHA. 23859743Sgroudier */ 23959743Sgroudier SCR_LOAD_ABS (scratcha, 4), 24059743Sgroudier PADDR_B (startpos), 24159743Sgroudier SCR_INT ^ IFTRUE (MASK (SEM, SEM)), 24259743Sgroudier SIR_SCRIPT_STOPPED, 24359743Sgroudier /* 24459743Sgroudier * Start the next job. 24559743Sgroudier * 24659743Sgroudier * @DSA = start point for this job. 24759743Sgroudier * SCRATCHA = address of this job in the start queue. 24859743Sgroudier * 24959743Sgroudier * We will restore startpos with SCRATCHA if we fails the 25059743Sgroudier * arbitration or if it is the idle job. 25159743Sgroudier * 25259743Sgroudier * The below GETJOB_BEGIN to GETJOB_END section of SCRIPTS 25359743Sgroudier * is a critical path. If it is partially executed, it then 25459743Sgroudier * may happen that the job address is not yet in the DSA 255218909Sbrucec * and the next queue position points to the next JOB. 25659743Sgroudier */ 25759743Sgroudier SCR_LOAD_ABS (dsa, 4), 25859743Sgroudier PADDR_B (startpos), 25959743Sgroudier SCR_LOAD_REL (temp, 4), 26059743Sgroudier 4, 26159743Sgroudier}/*-------------------------< GETJOB_BEGIN >---------------------*/,{ 26259743Sgroudier SCR_STORE_ABS (temp, 4), 26359743Sgroudier PADDR_B (startpos), 26459743Sgroudier SCR_LOAD_REL (dsa, 4), 26559743Sgroudier 0, 26659743Sgroudier}/*-------------------------< GETJOB_END >-----------------------*/,{ 26759743Sgroudier SCR_LOAD_REL (temp, 4), 26859743Sgroudier 0, 26959743Sgroudier SCR_RETURN, 27059743Sgroudier 0, 27159743Sgroudier}/*-------------------------< SELECT >---------------------------*/,{ 27259743Sgroudier /* 27359743Sgroudier * DSA contains the address of a scheduled 27459743Sgroudier * data structure. 27559743Sgroudier * 27659743Sgroudier * SCRATCHA contains the address of the start queue 27759743Sgroudier * entry which points to the next job. 27859743Sgroudier * 27959743Sgroudier * Set Initiator mode. 28059743Sgroudier * 28159743Sgroudier * (Target mode is left as an exercise for the reader) 28259743Sgroudier */ 28359743Sgroudier SCR_CLR (SCR_TRG), 28459743Sgroudier 0, 28559743Sgroudier /* 28659743Sgroudier * And try to select this target. 28759743Sgroudier */ 28859743Sgroudier SCR_SEL_TBL_ATN ^ offsetof (struct sym_dsb, select), 28959743Sgroudier PADDR_A (ungetjob), 29059743Sgroudier /* 29159743Sgroudier * Now there are 4 possibilities: 29259743Sgroudier * 293160964Syar * (1) The chip loses arbitration. 29459743Sgroudier * This is ok, because it will try again, 29559743Sgroudier * when the bus becomes idle. 29659743Sgroudier * (But beware of the timeout function!) 29759743Sgroudier * 29859743Sgroudier * (2) The chip is reselected. 29959743Sgroudier * Then the script processor takes the jump 30059743Sgroudier * to the RESELECT label. 30159743Sgroudier * 30259743Sgroudier * (3) The chip wins arbitration. 30359743Sgroudier * Then it will execute SCRIPTS instruction until 30459743Sgroudier * the next instruction that checks SCSI phase. 30559743Sgroudier * Then will stop and wait for selection to be 30659743Sgroudier * complete or selection time-out to occur. 30759743Sgroudier * 30859743Sgroudier * After having won arbitration, the SCRIPTS 30959743Sgroudier * processor is able to execute instructions while 31059743Sgroudier * the SCSI core is performing SCSI selection. 31159743Sgroudier */ 31259743Sgroudier /* 31359743Sgroudier * load the savep (saved data pointer) into 31459743Sgroudier * the actual data pointer. 31559743Sgroudier */ 31659743Sgroudier SCR_LOAD_REL (temp, 4), 31759743Sgroudier offsetof (struct sym_ccb, phys.head.savep), 31859743Sgroudier /* 31959743Sgroudier * Initialize the status registers 32059743Sgroudier */ 32159743Sgroudier SCR_LOAD_REL (scr0, 4), 32259743Sgroudier offsetof (struct sym_ccb, phys.head.status), 32359743Sgroudier}/*-------------------------< WF_SEL_DONE >----------------------*/,{ 32459743Sgroudier SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)), 32559743Sgroudier SIR_SEL_ATN_NO_MSG_OUT, 32660134Sgroudier}/*-------------------------< SEL_DONE >-------------------------*/,{ 32760134Sgroudier /* 32860134Sgroudier * C1010-33 errata work-around. 32960134Sgroudier * Due to a race, the SCSI core may not have 33060134Sgroudier * loaded SCNTL3 on SEL_TBL instruction. 33160134Sgroudier * We reload it once phase is stable. 33260134Sgroudier * Patched with a NOOP for other chips. 33360134Sgroudier */ 33460134Sgroudier SCR_LOAD_REL (scntl3, 1), 33560134Sgroudier offsetof(struct sym_dsb, select.sel_scntl3), 33659743Sgroudier}/*-------------------------< SEND_IDENT >-----------------------*/,{ 33759743Sgroudier /* 33859743Sgroudier * Selection complete. 33959743Sgroudier * Send the IDENTIFY and possibly the TAG message 34059743Sgroudier * and negotiation message if present. 34159743Sgroudier */ 34259743Sgroudier SCR_MOVE_TBL ^ SCR_MSG_OUT, 34359743Sgroudier offsetof (struct sym_dsb, smsg), 34459743Sgroudier}/*-------------------------< SELECT2 >--------------------------*/,{ 34559743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT 34659743Sgroudier /* 34759743Sgroudier * Set IMMEDIATE ARBITRATION if we have been given 34859743Sgroudier * a hint to do so. (Some job to do after this one). 34959743Sgroudier */ 35059743Sgroudier SCR_FROM_REG (HF_REG), 35159743Sgroudier 0, 35259743Sgroudier SCR_JUMPR ^ IFFALSE (MASK (HF_HINT_IARB, HF_HINT_IARB)), 35359743Sgroudier 8, 35459743Sgroudier SCR_REG_REG (scntl1, SCR_OR, IARB), 35559743Sgroudier 0, 35659743Sgroudier#endif 35759743Sgroudier /* 35859743Sgroudier * Anticipate the COMMAND phase. 35959743Sgroudier * This is the PHASE we expect at this point. 36059743Sgroudier */ 36159743Sgroudier SCR_JUMP ^ IFFALSE (WHEN (SCR_COMMAND)), 36259743Sgroudier PADDR_A (sel_no_cmd), 36359743Sgroudier}/*-------------------------< COMMAND >--------------------------*/,{ 36459743Sgroudier /* 36559743Sgroudier * ... and send the command 36659743Sgroudier */ 36759743Sgroudier SCR_MOVE_TBL ^ SCR_COMMAND, 36859743Sgroudier offsetof (struct sym_dsb, cmd), 36959743Sgroudier}/*-------------------------< DISPATCH >-------------------------*/,{ 37059743Sgroudier /* 37159743Sgroudier * MSG_IN is the only phase that shall be 37259743Sgroudier * entered at least once for each (re)selection. 37359743Sgroudier * So we test it first. 37459743Sgroudier */ 37559743Sgroudier SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)), 37659743Sgroudier PADDR_A (msg_in), 37759743Sgroudier SCR_JUMP ^ IFTRUE (IF (SCR_DATA_OUT)), 37859743Sgroudier PADDR_A (datao_phase), 37959743Sgroudier SCR_JUMP ^ IFTRUE (IF (SCR_DATA_IN)), 38059743Sgroudier PADDR_A (datai_phase), 38159743Sgroudier SCR_JUMP ^ IFTRUE (IF (SCR_STATUS)), 38259743Sgroudier PADDR_A (status), 38359743Sgroudier SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)), 38459743Sgroudier PADDR_A (command), 38559743Sgroudier SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)), 38659743Sgroudier PADDR_B (msg_out), 38759743Sgroudier /* 38859743Sgroudier * Discard as many illegal phases as 38959743Sgroudier * required and tell the C code about. 39059743Sgroudier */ 39159743Sgroudier SCR_JUMPR ^ IFFALSE (WHEN (SCR_ILG_OUT)), 39259743Sgroudier 16, 39359743Sgroudier SCR_MOVE_ABS (1) ^ SCR_ILG_OUT, 39459743Sgroudier HADDR_1 (scratch), 39559743Sgroudier SCR_JUMPR ^ IFTRUE (WHEN (SCR_ILG_OUT)), 39659743Sgroudier -16, 39759743Sgroudier SCR_JUMPR ^ IFFALSE (WHEN (SCR_ILG_IN)), 39859743Sgroudier 16, 39959743Sgroudier SCR_MOVE_ABS (1) ^ SCR_ILG_IN, 40059743Sgroudier HADDR_1 (scratch), 40159743Sgroudier SCR_JUMPR ^ IFTRUE (WHEN (SCR_ILG_IN)), 40259743Sgroudier -16, 40359743Sgroudier SCR_INT, 40459743Sgroudier SIR_BAD_PHASE, 40559743Sgroudier SCR_JUMP, 40659743Sgroudier PADDR_A (dispatch), 40759743Sgroudier}/*-------------------------< SEL_NO_CMD >-----------------------*/,{ 40859743Sgroudier /* 40959743Sgroudier * The target does not switch to command 41059743Sgroudier * phase after IDENTIFY has been sent. 41159743Sgroudier * 41259743Sgroudier * If it stays in MSG OUT phase send it 41359743Sgroudier * the IDENTIFY again. 41459743Sgroudier */ 41559743Sgroudier SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)), 41659743Sgroudier PADDR_B (resend_ident), 41759743Sgroudier /* 41859743Sgroudier * If target does not switch to MSG IN phase 41959743Sgroudier * and we sent a negotiation, assert the 42059743Sgroudier * failure immediately. 42159743Sgroudier */ 42259743Sgroudier SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)), 42359743Sgroudier PADDR_A (dispatch), 42459743Sgroudier SCR_FROM_REG (HS_REG), 42559743Sgroudier 0, 42659743Sgroudier SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)), 42759743Sgroudier SIR_NEGO_FAILED, 42859743Sgroudier /* 42959743Sgroudier * Jump to dispatcher. 43059743Sgroudier */ 43159743Sgroudier SCR_JUMP, 43259743Sgroudier PADDR_A (dispatch), 43359743Sgroudier}/*-------------------------< INIT >-----------------------------*/,{ 43459743Sgroudier /* 43559743Sgroudier * Wait for the SCSI RESET signal to be 43659743Sgroudier * inactive before restarting operations, 43759743Sgroudier * since the chip may hang on SEL_ATN 43859743Sgroudier * if SCSI RESET is active. 43959743Sgroudier */ 44059743Sgroudier SCR_FROM_REG (sstat0), 44159743Sgroudier 0, 44259743Sgroudier SCR_JUMPR ^ IFTRUE (MASK (IRST, IRST)), 44359743Sgroudier -16, 44459743Sgroudier SCR_JUMP, 44559743Sgroudier PADDR_A (start), 44659743Sgroudier}/*-------------------------< CLRACK >---------------------------*/,{ 44759743Sgroudier /* 44859743Sgroudier * Terminate possible pending message phase. 44959743Sgroudier */ 45059743Sgroudier SCR_CLR (SCR_ACK), 45159743Sgroudier 0, 45259743Sgroudier SCR_JUMP, 45359743Sgroudier PADDR_A (dispatch), 45459743Sgroudier}/*-------------------------< DISP_STATUS >----------------------*/,{ 45559743Sgroudier /* 45659743Sgroudier * Anticipate STATUS phase. 45759743Sgroudier * 45859743Sgroudier * Does spare 3 SCRIPTS instructions when we have 45959743Sgroudier * completed the INPUT of the data. 46059743Sgroudier */ 46159743Sgroudier SCR_JUMP ^ IFTRUE (WHEN (SCR_STATUS)), 46259743Sgroudier PADDR_A (status), 46359743Sgroudier SCR_JUMP, 46459743Sgroudier PADDR_A (dispatch), 46559743Sgroudier}/*-------------------------< DATAI_DONE >-----------------------*/,{ 46659743Sgroudier /* 46759743Sgroudier * If the device still wants to send us data, 46859743Sgroudier * we must count the extra bytes. 46959743Sgroudier */ 47059743Sgroudier SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_IN)), 47159743Sgroudier PADDR_B (data_ovrun), 47259743Sgroudier /* 47359743Sgroudier * If the SWIDE is not full, jump to dispatcher. 47459743Sgroudier * We anticipate a STATUS phase. 47559743Sgroudier */ 47659743Sgroudier SCR_FROM_REG (scntl2), 47759743Sgroudier 0, 47859743Sgroudier SCR_JUMP ^ IFFALSE (MASK (WSR, WSR)), 47959743Sgroudier PADDR_A (disp_status), 48059743Sgroudier /* 48159743Sgroudier * The SWIDE is full. 48259743Sgroudier * Clear this condition. 48359743Sgroudier */ 48459743Sgroudier SCR_REG_REG (scntl2, SCR_OR, WSR), 48559743Sgroudier 0, 48659743Sgroudier /* 48759743Sgroudier * We are expecting an IGNORE RESIDUE message 48859743Sgroudier * from the device, otherwise we are in data 48959743Sgroudier * overrun condition. Check against MSG_IN phase. 49059743Sgroudier */ 49159743Sgroudier SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)), 49259743Sgroudier SIR_SWIDE_OVERRUN, 49359743Sgroudier SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), 49459743Sgroudier PADDR_A (disp_status), 49559743Sgroudier /* 49659743Sgroudier * We are in MSG_IN phase, 49759743Sgroudier * Read the first byte of the message. 49859743Sgroudier * If it is not an IGNORE RESIDUE message, 49959743Sgroudier * signal overrun and jump to message 50059743Sgroudier * processing. 50159743Sgroudier */ 50259743Sgroudier SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 50359743Sgroudier HADDR_1 (msgin[0]), 50459743Sgroudier SCR_INT ^ IFFALSE (DATA (M_IGN_RESIDUE)), 50559743Sgroudier SIR_SWIDE_OVERRUN, 50659743Sgroudier SCR_JUMP ^ IFFALSE (DATA (M_IGN_RESIDUE)), 50759743Sgroudier PADDR_A (msg_in2), 50859743Sgroudier /* 50959743Sgroudier * We got the message we expected. 51059743Sgroudier * Read the 2nd byte, and jump to dispatcher. 51159743Sgroudier */ 51259743Sgroudier SCR_CLR (SCR_ACK), 51359743Sgroudier 0, 51459743Sgroudier SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 51559743Sgroudier HADDR_1 (msgin[1]), 51659743Sgroudier SCR_CLR (SCR_ACK), 51759743Sgroudier 0, 51859743Sgroudier SCR_JUMP, 51959743Sgroudier PADDR_A (disp_status), 52059743Sgroudier}/*-------------------------< DATAO_DONE >-----------------------*/,{ 52159743Sgroudier /* 52259743Sgroudier * If the device wants us to send more data, 52359743Sgroudier * we must count the extra bytes. 52459743Sgroudier */ 52559743Sgroudier SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_OUT)), 52659743Sgroudier PADDR_B (data_ovrun), 52759743Sgroudier /* 52859743Sgroudier * If the SODL is not full jump to dispatcher. 52959743Sgroudier * We anticipate a STATUS phase. 53059743Sgroudier */ 53159743Sgroudier SCR_FROM_REG (scntl2), 53259743Sgroudier 0, 53359743Sgroudier SCR_JUMP ^ IFFALSE (MASK (WSS, WSS)), 53459743Sgroudier PADDR_A (disp_status), 53559743Sgroudier /* 53659743Sgroudier * The SODL is full, clear this condition. 53759743Sgroudier */ 53859743Sgroudier SCR_REG_REG (scntl2, SCR_OR, WSS), 53959743Sgroudier 0, 54059743Sgroudier /* 54159743Sgroudier * And signal a DATA UNDERRUN condition 54259743Sgroudier * to the C code. 54359743Sgroudier */ 54459743Sgroudier SCR_INT, 54559743Sgroudier SIR_SODL_UNDERRUN, 54659743Sgroudier SCR_JUMP, 54759743Sgroudier PADDR_A (dispatch), 54859743Sgroudier}/*-------------------------< DATAI_PHASE >----------------------*/,{ 54959743Sgroudier SCR_RETURN, 55059743Sgroudier 0, 55159743Sgroudier}/*-------------------------< DATAO_PHASE >----------------------*/,{ 55260134Sgroudier /* 55360134Sgroudier * C1010-66 errata work-around. 55461051Sgroudier * Extra clocks of data hold must be inserted 55561051Sgroudier * in DATA OUT phase on 33 MHz PCI BUS. 55660134Sgroudier * Patched with a NOOP for other chips. 55760134Sgroudier */ 55861051Sgroudier SCR_REG_REG (scntl4, SCR_OR, (XCLKH_DT|XCLKH_ST)), 55961051Sgroudier 0, 56059743Sgroudier SCR_RETURN, 56159743Sgroudier 0, 56259743Sgroudier}/*-------------------------< MSG_IN >---------------------------*/,{ 56359743Sgroudier /* 56459743Sgroudier * Get the first byte of the message. 56559743Sgroudier * 56659743Sgroudier * The script processor doesn't negate the 56759743Sgroudier * ACK signal after this transfer. 56859743Sgroudier */ 56959743Sgroudier SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 57059743Sgroudier HADDR_1 (msgin[0]), 57159743Sgroudier}/*-------------------------< MSG_IN2 >--------------------------*/,{ 57259743Sgroudier /* 57359743Sgroudier * Check first against 1 byte messages 57459743Sgroudier * that we handle from SCRIPTS. 57559743Sgroudier */ 57659743Sgroudier SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE)), 57759743Sgroudier PADDR_A (complete), 57859743Sgroudier SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)), 57959743Sgroudier PADDR_A (disconnect), 58059743Sgroudier SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)), 58159743Sgroudier PADDR_A (save_dp), 58259743Sgroudier SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)), 58359743Sgroudier PADDR_A (restore_dp), 58459743Sgroudier /* 58559743Sgroudier * We handle all other messages from the 58659743Sgroudier * C code, so no need to waste on-chip RAM 58759743Sgroudier * for those ones. 58859743Sgroudier */ 58959743Sgroudier SCR_JUMP, 59059743Sgroudier PADDR_B (msg_in_etc), 59159743Sgroudier}/*-------------------------< STATUS >---------------------------*/,{ 59259743Sgroudier /* 59359743Sgroudier * get the status 59459743Sgroudier */ 59559743Sgroudier SCR_MOVE_ABS (1) ^ SCR_STATUS, 59659743Sgroudier HADDR_1 (scratch), 59759743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT 59859743Sgroudier /* 59959743Sgroudier * If STATUS is not GOOD, clear IMMEDIATE ARBITRATION, 60059743Sgroudier * since we may have to tamper the start queue from 60159743Sgroudier * the C code. 60259743Sgroudier */ 60359743Sgroudier SCR_JUMPR ^ IFTRUE (DATA (S_GOOD)), 60459743Sgroudier 8, 60559743Sgroudier SCR_REG_REG (scntl1, SCR_AND, ~IARB), 60659743Sgroudier 0, 60759743Sgroudier#endif 60859743Sgroudier /* 60959743Sgroudier * save status to scsi_status. 61059743Sgroudier * mark as complete. 61159743Sgroudier */ 61259743Sgroudier SCR_TO_REG (SS_REG), 61359743Sgroudier 0, 61459743Sgroudier SCR_LOAD_REG (HS_REG, HS_COMPLETE), 61559743Sgroudier 0, 61659743Sgroudier /* 61759743Sgroudier * Anticipate the MESSAGE PHASE for 61859743Sgroudier * the TASK COMPLETE message. 61959743Sgroudier */ 62059743Sgroudier SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)), 62159743Sgroudier PADDR_A (msg_in), 62259743Sgroudier SCR_JUMP, 62359743Sgroudier PADDR_A (dispatch), 62459743Sgroudier}/*-------------------------< COMPLETE >-------------------------*/,{ 62559743Sgroudier /* 62659743Sgroudier * Complete message. 62759743Sgroudier * 62859743Sgroudier * Copy the data pointer to LASTP. 62959743Sgroudier */ 63059743Sgroudier SCR_STORE_REL (temp, 4), 63159743Sgroudier offsetof (struct sym_ccb, phys.head.lastp), 63259743Sgroudier /* 63359743Sgroudier * When we terminate the cycle by clearing ACK, 63459743Sgroudier * the target may disconnect immediately. 63559743Sgroudier * 63659743Sgroudier * We don't want to be told of an "unexpected disconnect", 63759743Sgroudier * so we disable this feature. 63859743Sgroudier */ 63959743Sgroudier SCR_REG_REG (scntl2, SCR_AND, 0x7f), 64059743Sgroudier 0, 64159743Sgroudier /* 64259743Sgroudier * Terminate cycle ... 64359743Sgroudier */ 64459743Sgroudier SCR_CLR (SCR_ACK|SCR_ATN), 64559743Sgroudier 0, 64659743Sgroudier /* 64759743Sgroudier * ... and wait for the disconnect. 64859743Sgroudier */ 64959743Sgroudier SCR_WAIT_DISC, 65059743Sgroudier 0, 65159743Sgroudier}/*-------------------------< COMPLETE2 >------------------------*/,{ 65259743Sgroudier /* 65359743Sgroudier * Save host status. 65459743Sgroudier */ 65559743Sgroudier SCR_STORE_REL (scr0, 4), 65659743Sgroudier offsetof (struct sym_ccb, phys.head.status), 65759743Sgroudier /* 65859743Sgroudier * Some bridges may reorder DMA writes to memory. 65959743Sgroudier * We donnot want the CPU to deal with completions 66059743Sgroudier * without all the posted write having been flushed 66159743Sgroudier * to memory. This DUMMY READ should flush posted 66259743Sgroudier * buffers prior to the CPU having to deal with 66359743Sgroudier * completions. 66459743Sgroudier */ 66559743Sgroudier SCR_LOAD_REL (scr0, 4), /* DUMMY READ */ 66659743Sgroudier offsetof (struct sym_ccb, phys.head.status), 66759743Sgroudier 66859743Sgroudier /* 66959743Sgroudier * If command resulted in not GOOD status, 67059743Sgroudier * call the C code if needed. 67159743Sgroudier */ 67259743Sgroudier SCR_FROM_REG (SS_REG), 67359743Sgroudier 0, 67459743Sgroudier SCR_CALL ^ IFFALSE (DATA (S_GOOD)), 67559743Sgroudier PADDR_B (bad_status), 67659743Sgroudier /* 67759743Sgroudier * If we performed an auto-sense, call 67859743Sgroudier * the C code to synchronyze task aborts 67959743Sgroudier * with UNIT ATTENTION conditions. 68059743Sgroudier */ 68159743Sgroudier SCR_FROM_REG (HF_REG), 68259743Sgroudier 0, 68359743Sgroudier SCR_JUMPR ^ IFTRUE (MASK (0 ,(HF_SENSE|HF_EXT_ERR))), 68459743Sgroudier 16, 68559743Sgroudier}/*-------------------------< COMPLETE_ERROR >-------------------*/,{ 68659743Sgroudier SCR_LOAD_ABS (scratcha, 4), 68759743Sgroudier PADDR_B (startpos), 68859743Sgroudier SCR_INT, 68959743Sgroudier SIR_COMPLETE_ERROR, 69059743Sgroudier}/*-------------------------< DONE >-----------------------------*/,{ 69159743Sgroudier /* 69259743Sgroudier * Copy the DSA to the DONE QUEUE and 69359743Sgroudier * signal completion to the host. 69459743Sgroudier * If we are interrupted between DONE 69559743Sgroudier * and DONE_END, we must reset, otherwise 69659743Sgroudier * the completed CCB may be lost. 69759743Sgroudier */ 69859743Sgroudier SCR_STORE_ABS (dsa, 4), 69959743Sgroudier PADDR_B (saved_dsa), 70059743Sgroudier SCR_LOAD_ABS (dsa, 4), 70159743Sgroudier PADDR_B (done_pos), 70259743Sgroudier SCR_LOAD_ABS (scratcha, 4), 70359743Sgroudier PADDR_B (saved_dsa), 70459743Sgroudier SCR_STORE_REL (scratcha, 4), 70559743Sgroudier 0, 70659743Sgroudier /* 70759743Sgroudier * The instruction below reads the DONE QUEUE next 70859743Sgroudier * free position from memory. 70959743Sgroudier * In addition it ensures that all PCI posted writes 71059743Sgroudier * are flushed and so the DSA value of the done 71159743Sgroudier * CCB is visible by the CPU before INTFLY is raised. 71259743Sgroudier */ 71359743Sgroudier SCR_LOAD_REL (temp, 4), 71459743Sgroudier 4, 71559743Sgroudier SCR_INT_FLY, 71659743Sgroudier 0, 71759743Sgroudier SCR_STORE_ABS (temp, 4), 71859743Sgroudier PADDR_B (done_pos), 71959743Sgroudier}/*-------------------------< DONE_END >-------------------------*/,{ 72059743Sgroudier SCR_JUMP, 72159743Sgroudier PADDR_A (start), 72259743Sgroudier}/*-------------------------< SAVE_DP >--------------------------*/,{ 72359743Sgroudier /* 72459743Sgroudier * Clear ACK immediately. 72559743Sgroudier * No need to delay it. 72659743Sgroudier */ 72759743Sgroudier SCR_CLR (SCR_ACK), 72859743Sgroudier 0, 72959743Sgroudier /* 73059743Sgroudier * Keep track we received a SAVE DP, so 73159743Sgroudier * we will switch to the other PM context 73259743Sgroudier * on the next PM since the DP may point 73359743Sgroudier * to the current PM context. 73459743Sgroudier */ 73559743Sgroudier SCR_REG_REG (HF_REG, SCR_OR, HF_DP_SAVED), 73659743Sgroudier 0, 73759743Sgroudier /* 73859743Sgroudier * SAVE_DP message: 73959743Sgroudier * Copy the data pointer to SAVEP. 74059743Sgroudier */ 74159743Sgroudier SCR_STORE_REL (temp, 4), 74259743Sgroudier offsetof (struct sym_ccb, phys.head.savep), 74359743Sgroudier SCR_JUMP, 74459743Sgroudier PADDR_A (dispatch), 74559743Sgroudier}/*-------------------------< RESTORE_DP >-----------------------*/,{ 74659743Sgroudier /* 74759743Sgroudier * RESTORE_DP message: 74859743Sgroudier * Copy SAVEP to actual data pointer. 74959743Sgroudier */ 75059743Sgroudier SCR_LOAD_REL (temp, 4), 75159743Sgroudier offsetof (struct sym_ccb, phys.head.savep), 75259743Sgroudier SCR_JUMP, 75359743Sgroudier PADDR_A (clrack), 75459743Sgroudier}/*-------------------------< DISCONNECT >-----------------------*/,{ 75559743Sgroudier /* 75659743Sgroudier * DISCONNECTing ... 75759743Sgroudier * 75859743Sgroudier * disable the "unexpected disconnect" feature, 75959743Sgroudier * and remove the ACK signal. 76059743Sgroudier */ 76159743Sgroudier SCR_REG_REG (scntl2, SCR_AND, 0x7f), 76259743Sgroudier 0, 76359743Sgroudier SCR_CLR (SCR_ACK|SCR_ATN), 76459743Sgroudier 0, 76559743Sgroudier /* 76659743Sgroudier * Wait for the disconnect. 76759743Sgroudier */ 76859743Sgroudier SCR_WAIT_DISC, 76959743Sgroudier 0, 77059743Sgroudier /* 77159743Sgroudier * Status is: DISCONNECTED. 77259743Sgroudier */ 77359743Sgroudier SCR_LOAD_REG (HS_REG, HS_DISCONNECT), 77459743Sgroudier 0, 77559743Sgroudier /* 77659743Sgroudier * Save host status. 77759743Sgroudier */ 77859743Sgroudier SCR_STORE_REL (scr0, 4), 77959743Sgroudier offsetof (struct sym_ccb, phys.head.status), 78059743Sgroudier /* 78159743Sgroudier * If QUIRK_AUTOSAVE is set, 782108470Sschweikh * do a "save pointer" operation. 78359743Sgroudier */ 78459743Sgroudier SCR_FROM_REG (QU_REG), 78559743Sgroudier 0, 78659743Sgroudier SCR_JUMP ^ IFFALSE (MASK (SYM_QUIRK_AUTOSAVE, SYM_QUIRK_AUTOSAVE)), 78759743Sgroudier PADDR_A (start), 78859743Sgroudier /* 78959743Sgroudier * like SAVE_DP message: 79059743Sgroudier * Remember we saved the data pointer. 79159743Sgroudier * Copy data pointer to SAVEP. 79259743Sgroudier */ 79359743Sgroudier SCR_REG_REG (HF_REG, SCR_OR, HF_DP_SAVED), 79459743Sgroudier 0, 79559743Sgroudier SCR_STORE_REL (temp, 4), 79659743Sgroudier offsetof (struct sym_ccb, phys.head.savep), 79759743Sgroudier SCR_JUMP, 79859743Sgroudier PADDR_A (start), 79959743Sgroudier}/*-------------------------< IDLE >-----------------------------*/,{ 80059743Sgroudier /* 80159743Sgroudier * Nothing to do? 80259743Sgroudier * Switch the LED off and wait for reselect. 80359743Sgroudier * Will be patched with a NO_OP if LED 80459743Sgroudier * not needed or not desired. 80559743Sgroudier */ 80659743Sgroudier SCR_REG_REG (gpreg, SCR_OR, 0x01), 80759743Sgroudier 0, 80859743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT 80959743Sgroudier SCR_JUMPR, 81059743Sgroudier 8, 81159743Sgroudier#endif 81259743Sgroudier}/*-------------------------< UNGETJOB >-------------------------*/,{ 81359743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT 81459743Sgroudier /* 81559743Sgroudier * Set IMMEDIATE ARBITRATION, for the next time. 81659743Sgroudier * This will give us better chance to win arbitration 81759743Sgroudier * for the job we just wanted to do. 81859743Sgroudier */ 81959743Sgroudier SCR_REG_REG (scntl1, SCR_OR, IARB), 82059743Sgroudier 0, 82159743Sgroudier#endif 82259743Sgroudier /* 82359743Sgroudier * We are not able to restart the SCRIPTS if we are 82459743Sgroudier * interrupted and these instruction haven't been 82559743Sgroudier * all executed. BTW, this is very unlikely to 82659743Sgroudier * happen, but we check that from the C code. 82759743Sgroudier */ 82859743Sgroudier SCR_LOAD_REG (dsa, 0xff), 82959743Sgroudier 0, 83059743Sgroudier SCR_STORE_ABS (scratcha, 4), 83159743Sgroudier PADDR_B (startpos), 83259743Sgroudier}/*-------------------------< RESELECT >-------------------------*/,{ 83359743Sgroudier /* 83459743Sgroudier * Make sure we are in initiator mode. 83559743Sgroudier */ 83659743Sgroudier SCR_CLR (SCR_TRG), 83759743Sgroudier 0, 83859743Sgroudier /* 83959743Sgroudier * Sleep waiting for a reselection. 84059743Sgroudier */ 84159743Sgroudier SCR_WAIT_RESEL, 84259743Sgroudier PADDR_A(start), 84359743Sgroudier}/*-------------------------< RESELECTED >-----------------------*/,{ 84459743Sgroudier /* 84559743Sgroudier * Switch the LED on. 84659743Sgroudier * Will be patched with a NO_OP if LED 84759743Sgroudier * not needed or not desired. 84859743Sgroudier */ 84959743Sgroudier SCR_REG_REG (gpreg, SCR_AND, 0xfe), 85059743Sgroudier 0, 85159743Sgroudier /* 85259743Sgroudier * load the target id into the sdid 85359743Sgroudier */ 85459743Sgroudier SCR_REG_SFBR (ssid, SCR_AND, 0x8F), 85559743Sgroudier 0, 85659743Sgroudier SCR_TO_REG (sdid), 85759743Sgroudier 0, 85859743Sgroudier /* 85959743Sgroudier * Load the target control block address 86059743Sgroudier */ 86159743Sgroudier SCR_LOAD_ABS (dsa, 4), 86259743Sgroudier PADDR_B (targtbl), 86359743Sgroudier SCR_SFBR_REG (dsa, SCR_SHL, 0), 86459743Sgroudier 0, 86559743Sgroudier SCR_REG_REG (dsa, SCR_SHL, 0), 86659743Sgroudier 0, 86759743Sgroudier SCR_REG_REG (dsa, SCR_AND, 0x3c), 86859743Sgroudier 0, 86959743Sgroudier SCR_LOAD_REL (dsa, 4), 87059743Sgroudier 0, 87159743Sgroudier /* 87259743Sgroudier * We expect MESSAGE IN phase. 87359743Sgroudier * If not, get help from the C code. 87459743Sgroudier */ 87559743Sgroudier SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)), 87659743Sgroudier SIR_RESEL_NO_MSG_IN, 87759743Sgroudier /* 87859743Sgroudier * Load the legacy synchronous transfer registers. 87959743Sgroudier */ 88059743Sgroudier SCR_LOAD_REL (scntl3, 1), 88159743Sgroudier offsetof(struct sym_tcb, head.wval), 88259743Sgroudier SCR_LOAD_REL (sxfer, 1), 88359743Sgroudier offsetof(struct sym_tcb, head.sval), 88459743Sgroudier}/*-------------------------< RESEL_SCNTL4 >---------------------*/,{ 88559743Sgroudier /* 88659743Sgroudier * The C1010 uses a new synchronous timing scheme. 88759743Sgroudier * Will be patched with a NO_OP if not a C1010. 88859743Sgroudier */ 88959743Sgroudier SCR_LOAD_REL (scntl4, 1), 89059743Sgroudier offsetof(struct sym_tcb, head.uval), 89159743Sgroudier /* 89259743Sgroudier * Get the IDENTIFY message. 89359743Sgroudier */ 89459743Sgroudier SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 89559743Sgroudier HADDR_1 (msgin), 89659743Sgroudier /* 89759743Sgroudier * If IDENTIFY LUN #0, use a faster path 89859743Sgroudier * to find the LCB structure. 89959743Sgroudier */ 90059743Sgroudier SCR_JUMP ^ IFTRUE (MASK (0x80, 0xbf)), 90159743Sgroudier PADDR_A (resel_lun0), 90259743Sgroudier /* 90359743Sgroudier * If message isn't an IDENTIFY, 90459743Sgroudier * tell the C code about. 90559743Sgroudier */ 90659743Sgroudier SCR_INT ^ IFFALSE (MASK (0x80, 0x80)), 90759743Sgroudier SIR_RESEL_NO_IDENTIFY, 90859743Sgroudier /* 90959743Sgroudier * It is an IDENTIFY message, 91059743Sgroudier * Load the LUN control block address. 91159743Sgroudier */ 91259743Sgroudier SCR_LOAD_REL (dsa, 4), 91359743Sgroudier offsetof(struct sym_tcb, head.luntbl_sa), 91459743Sgroudier SCR_SFBR_REG (dsa, SCR_SHL, 0), 91559743Sgroudier 0, 91659743Sgroudier SCR_REG_REG (dsa, SCR_SHL, 0), 91759743Sgroudier 0, 91859743Sgroudier SCR_REG_REG (dsa, SCR_AND, 0xfc), 91959743Sgroudier 0, 92059743Sgroudier SCR_LOAD_REL (dsa, 4), 92159743Sgroudier 0, 92259743Sgroudier SCR_JUMPR, 92359743Sgroudier 8, 92459743Sgroudier}/*-------------------------< RESEL_LUN0 >-----------------------*/,{ 92559743Sgroudier /* 92659743Sgroudier * LUN 0 special case (but usual one :)) 92759743Sgroudier */ 92859743Sgroudier SCR_LOAD_REL (dsa, 4), 92959743Sgroudier offsetof(struct sym_tcb, head.lun0_sa), 93059743Sgroudier /* 93159743Sgroudier * Jump indirectly to the reselect action for this LUN. 93259743Sgroudier */ 93359743Sgroudier SCR_LOAD_REL (temp, 4), 93459743Sgroudier offsetof(struct sym_lcb, head.resel_sa), 93559743Sgroudier SCR_RETURN, 93659743Sgroudier 0, 93759743Sgroudier /* In normal situations, we jump to RESEL_TAG or RESEL_NO_TAG */ 93859743Sgroudier}/*-------------------------< RESEL_TAG >------------------------*/,{ 93959743Sgroudier /* 94060134Sgroudier * ACK the IDENTIFY previously received. 94159743Sgroudier */ 94259743Sgroudier SCR_CLR (SCR_ACK), 94359743Sgroudier 0, 94459743Sgroudier /* 94559743Sgroudier * It shall be a tagged command. 94659743Sgroudier * Read SIMPLE+TAG. 94759743Sgroudier * The C code will deal with errors. 948220950Smarius * Aggressive optimization, isn't it? :) 94959743Sgroudier */ 95059743Sgroudier SCR_MOVE_ABS (2) ^ SCR_MSG_IN, 95159743Sgroudier HADDR_1 (msgin), 95259743Sgroudier /* 95359743Sgroudier * Load the pointer to the tagged task 95459743Sgroudier * table for this LUN. 95559743Sgroudier */ 95659743Sgroudier SCR_LOAD_REL (dsa, 4), 95759743Sgroudier offsetof(struct sym_lcb, head.itlq_tbl_sa), 95859743Sgroudier /* 95959743Sgroudier * The SIDL still contains the TAG value. 960220944Smarius * Aggressive optimization, isn't it? :):) 96159743Sgroudier */ 96259743Sgroudier SCR_REG_SFBR (sidl, SCR_SHL, 0), 96359743Sgroudier 0, 96459743Sgroudier#if SYM_CONF_MAX_TASK*4 > 512 96559743Sgroudier SCR_JUMPR ^ IFFALSE (CARRYSET), 96659743Sgroudier 8, 96759743Sgroudier SCR_REG_REG (dsa1, SCR_OR, 2), 96859743Sgroudier 0, 96959743Sgroudier SCR_REG_REG (sfbr, SCR_SHL, 0), 97059743Sgroudier 0, 97159743Sgroudier SCR_JUMPR ^ IFFALSE (CARRYSET), 97259743Sgroudier 8, 97359743Sgroudier SCR_REG_REG (dsa1, SCR_OR, 1), 97459743Sgroudier 0, 97559743Sgroudier#elif SYM_CONF_MAX_TASK*4 > 256 97659743Sgroudier SCR_JUMPR ^ IFFALSE (CARRYSET), 97759743Sgroudier 8, 97859743Sgroudier SCR_REG_REG (dsa1, SCR_OR, 1), 97959743Sgroudier 0, 98059743Sgroudier#endif 98159743Sgroudier /* 98259743Sgroudier * Retrieve the DSA of this task. 98359743Sgroudier * JUMP indirectly to the restart point of the CCB. 98459743Sgroudier */ 98559743Sgroudier SCR_SFBR_REG (dsa, SCR_AND, 0xfc), 98659743Sgroudier 0, 98759743Sgroudier SCR_LOAD_REL (dsa, 4), 98859743Sgroudier 0, 98959743Sgroudier SCR_LOAD_REL (temp, 4), 99059743Sgroudier offsetof(struct sym_ccb, phys.head.go.restart), 99159743Sgroudier SCR_RETURN, 99259743Sgroudier 0, 99359743Sgroudier /* In normal situations we branch to RESEL_DSA */ 99459743Sgroudier}/*-------------------------< RESEL_DSA >------------------------*/,{ 99559743Sgroudier /* 99659743Sgroudier * ACK the IDENTIFY or TAG previously received. 99759743Sgroudier */ 99859743Sgroudier SCR_CLR (SCR_ACK), 99959743Sgroudier 0, 100059743Sgroudier}/*-------------------------< RESEL_DSA1 >-----------------------*/,{ 100159743Sgroudier /* 100259743Sgroudier * load the savep (saved pointer) into 100359743Sgroudier * the actual data pointer. 100459743Sgroudier */ 100559743Sgroudier SCR_LOAD_REL (temp, 4), 100659743Sgroudier offsetof (struct sym_ccb, phys.head.savep), 100759743Sgroudier /* 100859743Sgroudier * Initialize the status registers 100959743Sgroudier */ 101059743Sgroudier SCR_LOAD_REL (scr0, 4), 101159743Sgroudier offsetof (struct sym_ccb, phys.head.status), 101259743Sgroudier /* 101359743Sgroudier * Jump to dispatcher. 101459743Sgroudier */ 101559743Sgroudier SCR_JUMP, 101659743Sgroudier PADDR_A (dispatch), 101759743Sgroudier}/*-------------------------< RESEL_NO_TAG >---------------------*/,{ 101859743Sgroudier /* 101959743Sgroudier * Load the DSA with the unique ITL task. 102059743Sgroudier */ 102159743Sgroudier SCR_LOAD_REL (dsa, 4), 102259743Sgroudier offsetof(struct sym_lcb, head.itl_task_sa), 102359743Sgroudier /* 102459743Sgroudier * JUMP indirectly to the restart point of the CCB. 102559743Sgroudier */ 102659743Sgroudier SCR_LOAD_REL (temp, 4), 102759743Sgroudier offsetof(struct sym_ccb, phys.head.go.restart), 102859743Sgroudier SCR_RETURN, 102959743Sgroudier 0, 103059743Sgroudier /* In normal situations we branch to RESEL_DSA */ 103159743Sgroudier}/*-------------------------< DATA_IN >--------------------------*/,{ 103259743Sgroudier/* 103359743Sgroudier * Because the size depends on the 103459743Sgroudier * #define SYM_CONF_MAX_SG parameter, 103559743Sgroudier * it is filled in at runtime. 103659743Sgroudier * 103759743Sgroudier * ##===========< i=0; i<SYM_CONF_MAX_SG >========= 103859743Sgroudier * || SCR_CHMOV_TBL ^ SCR_DATA_IN, 103959743Sgroudier * || offsetof (struct sym_dsb, data[ i]), 104059743Sgroudier * ##========================================== 104159743Sgroudier */ 104259743Sgroudier0 104359743Sgroudier}/*-------------------------< DATA_IN2 >-------------------------*/,{ 104459743Sgroudier SCR_CALL, 104559743Sgroudier PADDR_A (datai_done), 104659743Sgroudier SCR_JUMP, 104759743Sgroudier PADDR_B (data_ovrun), 104859743Sgroudier}/*-------------------------< DATA_OUT >-------------------------*/,{ 104959743Sgroudier/* 105059743Sgroudier * Because the size depends on the 105159743Sgroudier * #define SYM_CONF_MAX_SG parameter, 105259743Sgroudier * it is filled in at runtime. 105359743Sgroudier * 105459743Sgroudier * ##===========< i=0; i<SYM_CONF_MAX_SG >========= 105559743Sgroudier * || SCR_CHMOV_TBL ^ SCR_DATA_OUT, 105659743Sgroudier * || offsetof (struct sym_dsb, data[ i]), 105759743Sgroudier * ##========================================== 105859743Sgroudier */ 105959743Sgroudier0 106059743Sgroudier}/*-------------------------< DATA_OUT2 >------------------------*/,{ 106159743Sgroudier SCR_CALL, 106259743Sgroudier PADDR_A (datao_done), 106359743Sgroudier SCR_JUMP, 106459743Sgroudier PADDR_B (data_ovrun), 106559743Sgroudier}/*-------------------------< PM0_DATA >-------------------------*/,{ 106659743Sgroudier /* 106759743Sgroudier * Read our host flags to SFBR, so we will be able 106859743Sgroudier * to check against the data direction we expect. 106959743Sgroudier */ 107059743Sgroudier SCR_FROM_REG (HF_REG), 107159743Sgroudier 0, 107259743Sgroudier /* 107359743Sgroudier * Check against actual DATA PHASE. 107459743Sgroudier */ 107559743Sgroudier SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)), 107659743Sgroudier PADDR_A (pm0_data_out), 107759743Sgroudier /* 107859743Sgroudier * Actual phase is DATA IN. 107959743Sgroudier * Check against expected direction. 108059743Sgroudier */ 108159743Sgroudier SCR_JUMP ^ IFFALSE (MASK (HF_DATA_IN, HF_DATA_IN)), 108259743Sgroudier PADDR_B (data_ovrun), 108359743Sgroudier /* 108459743Sgroudier * Keep track we are moving data from the 108559743Sgroudier * PM0 DATA mini-script. 108659743Sgroudier */ 108759743Sgroudier SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM0), 108859743Sgroudier 0, 108959743Sgroudier /* 109059743Sgroudier * Move the data to memory. 109159743Sgroudier */ 109259743Sgroudier SCR_CHMOV_TBL ^ SCR_DATA_IN, 109359743Sgroudier offsetof (struct sym_ccb, phys.pm0.sg), 109459743Sgroudier SCR_JUMP, 109559743Sgroudier PADDR_A (pm0_data_end), 109659743Sgroudier}/*-------------------------< PM0_DATA_OUT >---------------------*/,{ 109759743Sgroudier /* 109859743Sgroudier * Actual phase is DATA OUT. 109959743Sgroudier * Check against expected direction. 110059743Sgroudier */ 110159743Sgroudier SCR_JUMP ^ IFTRUE (MASK (HF_DATA_IN, HF_DATA_IN)), 110259743Sgroudier PADDR_B (data_ovrun), 110359743Sgroudier /* 110459743Sgroudier * Keep track we are moving data from the 110559743Sgroudier * PM0 DATA mini-script. 110659743Sgroudier */ 110759743Sgroudier SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM0), 110859743Sgroudier 0, 110959743Sgroudier /* 111059743Sgroudier * Move the data from memory. 111159743Sgroudier */ 111259743Sgroudier SCR_CHMOV_TBL ^ SCR_DATA_OUT, 111359743Sgroudier offsetof (struct sym_ccb, phys.pm0.sg), 111459743Sgroudier}/*-------------------------< PM0_DATA_END >---------------------*/,{ 111559743Sgroudier /* 111659743Sgroudier * Clear the flag that told we were moving 111759743Sgroudier * data from the PM0 DATA mini-script. 111859743Sgroudier */ 111959743Sgroudier SCR_REG_REG (HF_REG, SCR_AND, (~HF_IN_PM0)), 112059743Sgroudier 0, 112159743Sgroudier /* 112259743Sgroudier * Return to the previous DATA script which 112359743Sgroudier * is guaranteed by design (if no bug) to be 112459743Sgroudier * the main DATA script for this transfer. 112559743Sgroudier */ 112659743Sgroudier SCR_LOAD_REL (temp, 4), 112759743Sgroudier offsetof (struct sym_ccb, phys.pm0.ret), 112859743Sgroudier SCR_RETURN, 112959743Sgroudier 0, 113059743Sgroudier}/*-------------------------< PM1_DATA >-------------------------*/,{ 113159743Sgroudier /* 113259743Sgroudier * Read our host flags to SFBR, so we will be able 113359743Sgroudier * to check against the data direction we expect. 113459743Sgroudier */ 113559743Sgroudier SCR_FROM_REG (HF_REG), 113659743Sgroudier 0, 113759743Sgroudier /* 113859743Sgroudier * Check against actual DATA PHASE. 113959743Sgroudier */ 114059743Sgroudier SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)), 114159743Sgroudier PADDR_A (pm1_data_out), 114259743Sgroudier /* 114359743Sgroudier * Actual phase is DATA IN. 114459743Sgroudier * Check against expected direction. 114559743Sgroudier */ 114659743Sgroudier SCR_JUMP ^ IFFALSE (MASK (HF_DATA_IN, HF_DATA_IN)), 114759743Sgroudier PADDR_B (data_ovrun), 114859743Sgroudier /* 114959743Sgroudier * Keep track we are moving data from the 115059743Sgroudier * PM1 DATA mini-script. 115159743Sgroudier */ 115259743Sgroudier SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM1), 115359743Sgroudier 0, 115459743Sgroudier /* 115559743Sgroudier * Move the data to memory. 115659743Sgroudier */ 115759743Sgroudier SCR_CHMOV_TBL ^ SCR_DATA_IN, 115859743Sgroudier offsetof (struct sym_ccb, phys.pm1.sg), 115959743Sgroudier SCR_JUMP, 116059743Sgroudier PADDR_A (pm1_data_end), 116159743Sgroudier}/*-------------------------< PM1_DATA_OUT >---------------------*/,{ 116259743Sgroudier /* 116359743Sgroudier * Actual phase is DATA OUT. 116459743Sgroudier * Check against expected direction. 116559743Sgroudier */ 116659743Sgroudier SCR_JUMP ^ IFTRUE (MASK (HF_DATA_IN, HF_DATA_IN)), 116759743Sgroudier PADDR_B (data_ovrun), 116859743Sgroudier /* 116959743Sgroudier * Keep track we are moving data from the 117059743Sgroudier * PM1 DATA mini-script. 117159743Sgroudier */ 117259743Sgroudier SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM1), 117359743Sgroudier 0, 117459743Sgroudier /* 117559743Sgroudier * Move the data from memory. 117659743Sgroudier */ 117759743Sgroudier SCR_CHMOV_TBL ^ SCR_DATA_OUT, 117859743Sgroudier offsetof (struct sym_ccb, phys.pm1.sg), 117959743Sgroudier}/*-------------------------< PM1_DATA_END >---------------------*/,{ 118059743Sgroudier /* 118159743Sgroudier * Clear the flag that told we were moving 118259743Sgroudier * data from the PM1 DATA mini-script. 118359743Sgroudier */ 118459743Sgroudier SCR_REG_REG (HF_REG, SCR_AND, (~HF_IN_PM1)), 118559743Sgroudier 0, 118659743Sgroudier /* 118759743Sgroudier * Return to the previous DATA script which 118859743Sgroudier * is guaranteed by design (if no bug) to be 118959743Sgroudier * the main DATA script for this transfer. 119059743Sgroudier */ 119159743Sgroudier SCR_LOAD_REL (temp, 4), 119259743Sgroudier offsetof (struct sym_ccb, phys.pm1.ret), 119359743Sgroudier SCR_RETURN, 119459743Sgroudier 0, 119559743Sgroudier}/*-------------------------<>-----------------------------------*/ 119659743Sgroudier}; 119759743Sgroudier 1198179029Smariusstatic const struct SYM_FWB_SCR SYM_FWB_SCR = { 119959743Sgroudier/*--------------------------< START64 >--------------------------*/ { 120059743Sgroudier /* 120159743Sgroudier * SCRIPT entry point for the 895A, 896 and 1010. 120259743Sgroudier * For now, there is no specific stuff for those 120359743Sgroudier * chips at this point, but this may come. 120459743Sgroudier */ 120559743Sgroudier SCR_JUMP, 120659743Sgroudier PADDR_A (init), 120759743Sgroudier}/*-------------------------< NO_DATA >--------------------------*/,{ 120859743Sgroudier SCR_JUMP, 120959743Sgroudier PADDR_B (data_ovrun), 121059743Sgroudier}/*-------------------------< SEL_FOR_ABORT >--------------------*/,{ 121159743Sgroudier /* 121259743Sgroudier * We are jumped here by the C code, if we have 121359743Sgroudier * some target to reset or some disconnected 121459743Sgroudier * job to abort. Since error recovery is a serious 121559743Sgroudier * busyness, we will really reset the SCSI BUS, if 1216220944Smarius * case of a SCSI interrupt occurring in this path. 121759743Sgroudier */ 121859743Sgroudier 121959743Sgroudier /* 122059743Sgroudier * Set initiator mode. 122159743Sgroudier */ 122259743Sgroudier SCR_CLR (SCR_TRG), 122359743Sgroudier 0, 122459743Sgroudier /* 122559743Sgroudier * And try to select this target. 122659743Sgroudier */ 122759743Sgroudier SCR_SEL_TBL_ATN ^ offsetof (struct sym_hcb, abrt_sel), 122859743Sgroudier PADDR_A (reselect), 122959743Sgroudier /* 123059743Sgroudier * Wait for the selection to complete or 123159743Sgroudier * the selection to time out. 123259743Sgroudier */ 123359743Sgroudier SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_OUT)), 123459743Sgroudier -8, 123559743Sgroudier /* 123659743Sgroudier * Call the C code. 123759743Sgroudier */ 123859743Sgroudier SCR_INT, 123959743Sgroudier SIR_TARGET_SELECTED, 124059743Sgroudier /* 124159743Sgroudier * The C code should let us continue here. 124259743Sgroudier * Send the 'kiss of death' message. 124359743Sgroudier * We expect an immediate disconnect once 124459743Sgroudier * the target has eaten the message. 124559743Sgroudier */ 124659743Sgroudier SCR_REG_REG (scntl2, SCR_AND, 0x7f), 124759743Sgroudier 0, 124859743Sgroudier SCR_MOVE_TBL ^ SCR_MSG_OUT, 124959743Sgroudier offsetof (struct sym_hcb, abrt_tbl), 125059743Sgroudier SCR_CLR (SCR_ACK|SCR_ATN), 125159743Sgroudier 0, 125259743Sgroudier SCR_WAIT_DISC, 125359743Sgroudier 0, 125459743Sgroudier /* 125559743Sgroudier * Tell the C code that we are done. 125659743Sgroudier */ 125759743Sgroudier SCR_INT, 125859743Sgroudier SIR_ABORT_SENT, 125959743Sgroudier}/*-------------------------< SEL_FOR_ABORT_1 >------------------*/,{ 126059743Sgroudier /* 126159743Sgroudier * Jump at scheduler. 126259743Sgroudier */ 126359743Sgroudier SCR_JUMP, 126459743Sgroudier PADDR_A (start), 126559743Sgroudier}/*-------------------------< MSG_IN_ETC >-----------------------*/,{ 126659743Sgroudier /* 126759743Sgroudier * If it is an EXTENDED (variable size message) 126859743Sgroudier * Handle it. 126959743Sgroudier */ 127059743Sgroudier SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)), 127159743Sgroudier PADDR_B (msg_extended), 127259743Sgroudier /* 127359743Sgroudier * Let the C code handle any other 127459743Sgroudier * 1 byte message. 127559743Sgroudier */ 127659743Sgroudier SCR_JUMP ^ IFTRUE (MASK (0x00, 0xf0)), 127759743Sgroudier PADDR_B (msg_received), 127859743Sgroudier SCR_JUMP ^ IFTRUE (MASK (0x10, 0xf0)), 127959743Sgroudier PADDR_B (msg_received), 128059743Sgroudier /* 128159743Sgroudier * We donnot handle 2 bytes messages from SCRIPTS. 128259743Sgroudier * So, let the C code deal with these ones too. 128359743Sgroudier */ 128462134Sgroudier SCR_JUMP ^ IFFALSE (MASK (0x20, 0xf0)), 128562134Sgroudier PADDR_B (msg_weird_seen), 128659743Sgroudier SCR_CLR (SCR_ACK), 128759743Sgroudier 0, 128859743Sgroudier SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 128959743Sgroudier HADDR_1 (msgin[1]), 129059743Sgroudier}/*-------------------------< MSG_RECEIVED >---------------------*/,{ 129159743Sgroudier SCR_LOAD_REL (scratcha, 4), /* DUMMY READ */ 129259743Sgroudier 0, 129359743Sgroudier SCR_INT, 129459743Sgroudier SIR_MSG_RECEIVED, 129559743Sgroudier}/*-------------------------< MSG_WEIRD_SEEN >-------------------*/,{ 129659743Sgroudier SCR_LOAD_REL (scratcha, 4), /* DUMMY READ */ 129759743Sgroudier 0, 129859743Sgroudier SCR_INT, 129959743Sgroudier SIR_MSG_WEIRD, 130059743Sgroudier}/*-------------------------< MSG_EXTENDED >---------------------*/,{ 130159743Sgroudier /* 130259743Sgroudier * Clear ACK and get the next byte 130359743Sgroudier * assumed to be the message length. 130459743Sgroudier */ 130559743Sgroudier SCR_CLR (SCR_ACK), 130659743Sgroudier 0, 130759743Sgroudier SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 130859743Sgroudier HADDR_1 (msgin[1]), 130959743Sgroudier /* 131059743Sgroudier * Try to catch some unlikely situations as 0 length 131159743Sgroudier * or too large the length. 131259743Sgroudier */ 131359743Sgroudier SCR_JUMP ^ IFTRUE (DATA (0)), 131459743Sgroudier PADDR_B (msg_weird_seen), 131559743Sgroudier SCR_TO_REG (scratcha), 131659743Sgroudier 0, 131759743Sgroudier SCR_REG_REG (sfbr, SCR_ADD, (256-8)), 131859743Sgroudier 0, 131959743Sgroudier SCR_JUMP ^ IFTRUE (CARRYSET), 132059743Sgroudier PADDR_B (msg_weird_seen), 132159743Sgroudier /* 132259743Sgroudier * We donnot handle extended messages from SCRIPTS. 1323220944Smarius * Read the amount of data corresponding to the 132459743Sgroudier * message length and call the C code. 132559743Sgroudier */ 132659743Sgroudier SCR_STORE_REL (scratcha, 1), 132759743Sgroudier offsetof (struct sym_dsb, smsg_ext.size), 132859743Sgroudier SCR_CLR (SCR_ACK), 132959743Sgroudier 0, 133059743Sgroudier SCR_MOVE_TBL ^ SCR_MSG_IN, 133159743Sgroudier offsetof (struct sym_dsb, smsg_ext), 133259743Sgroudier SCR_JUMP, 133359743Sgroudier PADDR_B (msg_received), 133459743Sgroudier}/*-------------------------< MSG_BAD >--------------------------*/,{ 133559743Sgroudier /* 133659743Sgroudier * unimplemented message - reject it. 133759743Sgroudier */ 133859743Sgroudier SCR_INT, 133959743Sgroudier SIR_REJECT_TO_SEND, 134059743Sgroudier SCR_SET (SCR_ATN), 134159743Sgroudier 0, 134259743Sgroudier SCR_JUMP, 134359743Sgroudier PADDR_A (clrack), 134459743Sgroudier}/*-------------------------< MSG_WEIRD >------------------------*/,{ 134559743Sgroudier /* 134659743Sgroudier * weird message received 134759743Sgroudier * ignore all MSG IN phases and reject it. 134859743Sgroudier */ 134959743Sgroudier SCR_INT, 135059743Sgroudier SIR_REJECT_TO_SEND, 135159743Sgroudier SCR_SET (SCR_ATN), 135259743Sgroudier 0, 135359743Sgroudier}/*-------------------------< MSG_WEIRD1 >-----------------------*/,{ 135459743Sgroudier SCR_CLR (SCR_ACK), 135559743Sgroudier 0, 135659743Sgroudier SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), 135759743Sgroudier PADDR_A (dispatch), 135859743Sgroudier SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 135959743Sgroudier HADDR_1 (scratch), 136059743Sgroudier SCR_JUMP, 136159743Sgroudier PADDR_B (msg_weird1), 136259743Sgroudier}/*-------------------------< WDTR_RESP >------------------------*/,{ 136359743Sgroudier /* 136459743Sgroudier * let the target fetch our answer. 136559743Sgroudier */ 136659743Sgroudier SCR_SET (SCR_ATN), 136759743Sgroudier 0, 136859743Sgroudier SCR_CLR (SCR_ACK), 136959743Sgroudier 0, 137059743Sgroudier SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)), 137159743Sgroudier PADDR_B (nego_bad_phase), 137259743Sgroudier}/*-------------------------< SEND_WDTR >------------------------*/,{ 137359743Sgroudier /* 137459743Sgroudier * Send the M_X_WIDE_REQ 137559743Sgroudier */ 137659743Sgroudier SCR_MOVE_ABS (4) ^ SCR_MSG_OUT, 137759743Sgroudier HADDR_1 (msgout), 137859743Sgroudier SCR_JUMP, 137959743Sgroudier PADDR_B (msg_out_done), 138059743Sgroudier}/*-------------------------< SDTR_RESP >------------------------*/,{ 138159743Sgroudier /* 138259743Sgroudier * let the target fetch our answer. 138359743Sgroudier */ 138459743Sgroudier SCR_SET (SCR_ATN), 138559743Sgroudier 0, 138659743Sgroudier SCR_CLR (SCR_ACK), 138759743Sgroudier 0, 138859743Sgroudier SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)), 138959743Sgroudier PADDR_B (nego_bad_phase), 139059743Sgroudier}/*-------------------------< SEND_SDTR >------------------------*/,{ 139159743Sgroudier /* 139259743Sgroudier * Send the M_X_SYNC_REQ 139359743Sgroudier */ 139459743Sgroudier SCR_MOVE_ABS (5) ^ SCR_MSG_OUT, 139559743Sgroudier HADDR_1 (msgout), 139659743Sgroudier SCR_JUMP, 139759743Sgroudier PADDR_B (msg_out_done), 139859743Sgroudier}/*-------------------------< PPR_RESP >-------------------------*/,{ 139959743Sgroudier /* 140059743Sgroudier * let the target fetch our answer. 140159743Sgroudier */ 140259743Sgroudier SCR_SET (SCR_ATN), 140359743Sgroudier 0, 140459743Sgroudier SCR_CLR (SCR_ACK), 140559743Sgroudier 0, 140659743Sgroudier SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)), 140759743Sgroudier PADDR_B (nego_bad_phase), 140859743Sgroudier}/*-------------------------< SEND_PPR >-------------------------*/,{ 140959743Sgroudier /* 141059743Sgroudier * Send the M_X_PPR_REQ 141159743Sgroudier */ 141259743Sgroudier SCR_MOVE_ABS (8) ^ SCR_MSG_OUT, 141359743Sgroudier HADDR_1 (msgout), 141459743Sgroudier SCR_JUMP, 141559743Sgroudier PADDR_B (msg_out_done), 141659743Sgroudier}/*-------------------------< NEGO_BAD_PHASE >-------------------*/,{ 141759743Sgroudier SCR_INT, 141859743Sgroudier SIR_NEGO_PROTO, 141959743Sgroudier SCR_JUMP, 142059743Sgroudier PADDR_A (dispatch), 142159743Sgroudier}/*-------------------------< MSG_OUT >--------------------------*/,{ 142259743Sgroudier /* 142359743Sgroudier * The target requests a message. 142459743Sgroudier * We donnot send messages that may 142559743Sgroudier * require the device to go to bus free. 142659743Sgroudier */ 142759743Sgroudier SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, 142859743Sgroudier HADDR_1 (msgout), 142959743Sgroudier /* 143059743Sgroudier * ... wait for the next phase 143159743Sgroudier * if it's a message out, send it again, ... 143259743Sgroudier */ 143359743Sgroudier SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)), 143459743Sgroudier PADDR_B (msg_out), 143559743Sgroudier}/*-------------------------< MSG_OUT_DONE >---------------------*/,{ 143659743Sgroudier /* 143759743Sgroudier * Let the C code be aware of the 143859743Sgroudier * sent message and clear the message. 143959743Sgroudier */ 144059743Sgroudier SCR_INT, 144159743Sgroudier SIR_MSG_OUT_DONE, 144259743Sgroudier /* 144359743Sgroudier * ... and process the next phase 144459743Sgroudier */ 144559743Sgroudier SCR_JUMP, 144659743Sgroudier PADDR_A (dispatch), 144759743Sgroudier}/*-------------------------< DATA_OVRUN >-----------------------*/,{ 144859743Sgroudier /* 144959743Sgroudier * Use scratcha to count the extra bytes. 145059743Sgroudier */ 145159743Sgroudier SCR_LOAD_ABS (scratcha, 4), 145259743Sgroudier PADDR_B (zero), 145359743Sgroudier}/*-------------------------< DATA_OVRUN1 >----------------------*/,{ 145459743Sgroudier /* 145559743Sgroudier * The target may want to transfer too much data. 145659743Sgroudier * 145759743Sgroudier * If phase is DATA OUT write 1 byte and count it. 145859743Sgroudier */ 145959743Sgroudier SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_OUT)), 146059743Sgroudier 16, 146159743Sgroudier SCR_CHMOV_ABS (1) ^ SCR_DATA_OUT, 146259743Sgroudier HADDR_1 (scratch), 146359743Sgroudier SCR_JUMP, 146459743Sgroudier PADDR_B (data_ovrun2), 146559743Sgroudier /* 146659743Sgroudier * If WSR is set, clear this condition, and 146759743Sgroudier * count this byte. 146859743Sgroudier */ 146959743Sgroudier SCR_FROM_REG (scntl2), 147059743Sgroudier 0, 147159743Sgroudier SCR_JUMPR ^ IFFALSE (MASK (WSR, WSR)), 147259743Sgroudier 16, 147359743Sgroudier SCR_REG_REG (scntl2, SCR_OR, WSR), 147459743Sgroudier 0, 147559743Sgroudier SCR_JUMP, 147659743Sgroudier PADDR_B (data_ovrun2), 147759743Sgroudier /* 147859743Sgroudier * Finally check against DATA IN phase. 147959743Sgroudier * Signal data overrun to the C code 148059743Sgroudier * and jump to dispatcher if not so. 148159743Sgroudier * Read 1 byte otherwise and count it. 148259743Sgroudier */ 148359743Sgroudier SCR_JUMPR ^ IFTRUE (WHEN (SCR_DATA_IN)), 148459743Sgroudier 16, 148559743Sgroudier SCR_INT, 148659743Sgroudier SIR_DATA_OVERRUN, 148759743Sgroudier SCR_JUMP, 148859743Sgroudier PADDR_A (dispatch), 148959743Sgroudier SCR_CHMOV_ABS (1) ^ SCR_DATA_IN, 149059743Sgroudier HADDR_1 (scratch), 149159743Sgroudier}/*-------------------------< DATA_OVRUN2 >----------------------*/,{ 149259743Sgroudier /* 149359743Sgroudier * Count this byte. 149459743Sgroudier * This will allow to return a negative 149559743Sgroudier * residual to user. 149659743Sgroudier */ 149759743Sgroudier SCR_REG_REG (scratcha, SCR_ADD, 0x01), 149859743Sgroudier 0, 149959743Sgroudier SCR_REG_REG (scratcha1, SCR_ADDC, 0), 150059743Sgroudier 0, 150159743Sgroudier SCR_REG_REG (scratcha2, SCR_ADDC, 0), 150259743Sgroudier 0, 150359743Sgroudier /* 150459743Sgroudier * .. and repeat as required. 150559743Sgroudier */ 150659743Sgroudier SCR_JUMP, 150759743Sgroudier PADDR_B (data_ovrun1), 150859743Sgroudier}/*-------------------------< ABORT_RESEL >----------------------*/,{ 150959743Sgroudier SCR_SET (SCR_ATN), 151059743Sgroudier 0, 151159743Sgroudier SCR_CLR (SCR_ACK), 151259743Sgroudier 0, 151359743Sgroudier /* 151459743Sgroudier * send the abort/abortag/reset message 151559743Sgroudier * we expect an immediate disconnect 151659743Sgroudier */ 151759743Sgroudier SCR_REG_REG (scntl2, SCR_AND, 0x7f), 151859743Sgroudier 0, 151959743Sgroudier SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, 152059743Sgroudier HADDR_1 (msgout), 152159743Sgroudier SCR_CLR (SCR_ACK|SCR_ATN), 152259743Sgroudier 0, 152359743Sgroudier SCR_WAIT_DISC, 152459743Sgroudier 0, 152559743Sgroudier SCR_INT, 152659743Sgroudier SIR_RESEL_ABORTED, 152759743Sgroudier SCR_JUMP, 152859743Sgroudier PADDR_A (start), 152959743Sgroudier}/*-------------------------< RESEND_IDENT >---------------------*/,{ 153059743Sgroudier /* 153159743Sgroudier * The target stays in MSG OUT phase after having acked 153259743Sgroudier * Identify [+ Tag [+ Extended message ]]. Targets shall 153359743Sgroudier * behave this way on parity error. 153459743Sgroudier * We must send it again all the messages. 153559743Sgroudier */ 153659743Sgroudier SCR_SET (SCR_ATN), /* Shall be asserted 2 deskew delays before the */ 153759743Sgroudier 0, /* 1rst ACK = 90 ns. Hope the chip isn't too fast */ 153859743Sgroudier SCR_JUMP, 153959743Sgroudier PADDR_A (send_ident), 154059743Sgroudier}/*-------------------------< IDENT_BREAK >----------------------*/,{ 154159743Sgroudier SCR_CLR (SCR_ATN), 154259743Sgroudier 0, 154359743Sgroudier SCR_JUMP, 154459743Sgroudier PADDR_A (select2), 154559743Sgroudier}/*-------------------------< IDENT_BREAK_ATN >------------------*/,{ 154659743Sgroudier SCR_SET (SCR_ATN), 154759743Sgroudier 0, 154859743Sgroudier SCR_JUMP, 154959743Sgroudier PADDR_A (select2), 155059743Sgroudier}/*-------------------------< SDATA_IN >-------------------------*/,{ 155159743Sgroudier SCR_CHMOV_TBL ^ SCR_DATA_IN, 155259743Sgroudier offsetof (struct sym_dsb, sense), 155359743Sgroudier SCR_CALL, 155459743Sgroudier PADDR_A (datai_done), 155559743Sgroudier SCR_JUMP, 155659743Sgroudier PADDR_B (data_ovrun), 155759743Sgroudier}/*-------------------------< RESEL_BAD_LUN >--------------------*/,{ 155859743Sgroudier /* 155959743Sgroudier * Message is an IDENTIFY, but lun is unknown. 156059743Sgroudier * Signal problem to C code for logging the event. 156159743Sgroudier * Send a M_ABORT to clear all pending tasks. 156259743Sgroudier */ 156359743Sgroudier SCR_INT, 156459743Sgroudier SIR_RESEL_BAD_LUN, 156559743Sgroudier SCR_JUMP, 156659743Sgroudier PADDR_B (abort_resel), 156759743Sgroudier}/*-------------------------< BAD_I_T_L >------------------------*/,{ 156859743Sgroudier /* 156959743Sgroudier * We donnot have a task for that I_T_L. 157059743Sgroudier * Signal problem to C code for logging the event. 157159743Sgroudier * Send a M_ABORT message. 157259743Sgroudier */ 157359743Sgroudier SCR_INT, 157459743Sgroudier SIR_RESEL_BAD_I_T_L, 157559743Sgroudier SCR_JUMP, 157659743Sgroudier PADDR_B (abort_resel), 157759743Sgroudier}/*-------------------------< BAD_I_T_L_Q >----------------------*/,{ 157859743Sgroudier /* 157959743Sgroudier * We donnot have a task that matches the tag. 158059743Sgroudier * Signal problem to C code for logging the event. 158159743Sgroudier * Send a M_ABORTTAG message. 158259743Sgroudier */ 158359743Sgroudier SCR_INT, 158459743Sgroudier SIR_RESEL_BAD_I_T_L_Q, 158559743Sgroudier SCR_JUMP, 158659743Sgroudier PADDR_B (abort_resel), 158759743Sgroudier}/*-------------------------< BAD_STATUS >-----------------------*/,{ 158859743Sgroudier /* 158959743Sgroudier * Anything different from INTERMEDIATE 159059743Sgroudier * CONDITION MET should be a bad SCSI status, 159159743Sgroudier * given that GOOD status has already been tested. 159259743Sgroudier * Call the C code. 159359743Sgroudier */ 159459743Sgroudier SCR_LOAD_ABS (scratcha, 4), 159559743Sgroudier PADDR_B (startpos), 159659743Sgroudier SCR_INT ^ IFFALSE (DATA (S_COND_MET)), 159759743Sgroudier SIR_BAD_SCSI_STATUS, 159859743Sgroudier SCR_RETURN, 159959743Sgroudier 0, 160059743Sgroudier}/*-------------------------< PM_HANDLE >------------------------*/,{ 160159743Sgroudier /* 160259743Sgroudier * Phase mismatch handling. 160359743Sgroudier * 160459743Sgroudier * Since we have to deal with 2 SCSI data pointers 160559743Sgroudier * (current and saved), we need at least 2 contexts. 160659743Sgroudier * Each context (pm0 and pm1) has a saved area, a 160759743Sgroudier * SAVE mini-script and a DATA phase mini-script. 160859743Sgroudier */ 160959743Sgroudier /* 161059743Sgroudier * Get the PM handling flags. 161159743Sgroudier */ 161259743Sgroudier SCR_FROM_REG (HF_REG), 161359743Sgroudier 0, 161459743Sgroudier /* 161559743Sgroudier * If no flags (1rst PM for example), avoid 161659743Sgroudier * all the below heavy flags testing. 161759743Sgroudier * This makes the normal case a bit faster. 161859743Sgroudier */ 161959743Sgroudier SCR_JUMP ^ IFTRUE (MASK (0, (HF_IN_PM0 | HF_IN_PM1 | HF_DP_SAVED))), 162059743Sgroudier PADDR_B (pm_handle1), 162159743Sgroudier /* 162259743Sgroudier * If we received a SAVE DP, switch to the 162359743Sgroudier * other PM context since the savep may point 162459743Sgroudier * to the current PM context. 162559743Sgroudier */ 162659743Sgroudier SCR_JUMPR ^ IFFALSE (MASK (HF_DP_SAVED, HF_DP_SAVED)), 162759743Sgroudier 8, 162859743Sgroudier SCR_REG_REG (sfbr, SCR_XOR, HF_ACT_PM), 162959743Sgroudier 0, 163059743Sgroudier /* 163159743Sgroudier * If we have been interrupt in a PM DATA mini-script, 163259743Sgroudier * we take the return address from the corresponding 163359743Sgroudier * saved area. 163459743Sgroudier * This ensure the return address always points to the 163559743Sgroudier * main DATA script for this transfer. 163659743Sgroudier */ 163759743Sgroudier SCR_JUMP ^ IFTRUE (MASK (0, (HF_IN_PM0 | HF_IN_PM1))), 163859743Sgroudier PADDR_B (pm_handle1), 163959743Sgroudier SCR_JUMPR ^ IFFALSE (MASK (HF_IN_PM0, HF_IN_PM0)), 164059743Sgroudier 16, 164159743Sgroudier SCR_LOAD_REL (ia, 4), 164259743Sgroudier offsetof(struct sym_ccb, phys.pm0.ret), 164359743Sgroudier SCR_JUMP, 164459743Sgroudier PADDR_B (pm_save), 164559743Sgroudier SCR_LOAD_REL (ia, 4), 164659743Sgroudier offsetof(struct sym_ccb, phys.pm1.ret), 164759743Sgroudier SCR_JUMP, 164859743Sgroudier PADDR_B (pm_save), 164959743Sgroudier}/*-------------------------< PM_HANDLE1 >-----------------------*/,{ 165059743Sgroudier /* 165159743Sgroudier * Normal case. 165259743Sgroudier * Update the return address so that it 165359743Sgroudier * will point after the interrupted MOVE. 165459743Sgroudier */ 165559743Sgroudier SCR_REG_REG (ia, SCR_ADD, 8), 165659743Sgroudier 0, 165759743Sgroudier SCR_REG_REG (ia1, SCR_ADDC, 0), 165859743Sgroudier 0, 165959743Sgroudier}/*-------------------------< PM_SAVE >--------------------------*/,{ 166059743Sgroudier /* 166159743Sgroudier * Clear all the flags that told us if we were 166259743Sgroudier * interrupted in a PM DATA mini-script and/or 166359743Sgroudier * we received a SAVE DP. 166459743Sgroudier */ 166559743Sgroudier SCR_SFBR_REG (HF_REG, SCR_AND, (~(HF_IN_PM0|HF_IN_PM1|HF_DP_SAVED))), 166659743Sgroudier 0, 166759743Sgroudier /* 166859743Sgroudier * Choose the current PM context. 166959743Sgroudier */ 167059743Sgroudier SCR_JUMP ^ IFTRUE (MASK (HF_ACT_PM, HF_ACT_PM)), 167159743Sgroudier PADDR_B (pm1_save), 167259743Sgroudier}/*-------------------------< PM0_SAVE >-------------------------*/,{ 167359743Sgroudier SCR_STORE_REL (ia, 4), 167459743Sgroudier offsetof(struct sym_ccb, phys.pm0.ret), 167559743Sgroudier /* 167659743Sgroudier * If WSR bit is set, either UA and RBC may 167759743Sgroudier * have to be changed whether the device wants 167859743Sgroudier * to ignore this residue or not. 167959743Sgroudier */ 168059743Sgroudier SCR_FROM_REG (scntl2), 168159743Sgroudier 0, 168259743Sgroudier SCR_CALL ^ IFTRUE (MASK (WSR, WSR)), 168359743Sgroudier PADDR_B (pm_wsr_handle), 168459743Sgroudier /* 168559743Sgroudier * Save the remaining byte count, the updated 168659743Sgroudier * address and the return address. 168759743Sgroudier */ 168859743Sgroudier SCR_STORE_REL (rbc, 4), 168959743Sgroudier offsetof(struct sym_ccb, phys.pm0.sg.size), 169059743Sgroudier SCR_STORE_REL (ua, 4), 169159743Sgroudier offsetof(struct sym_ccb, phys.pm0.sg.addr), 169259743Sgroudier /* 169359743Sgroudier * Set the current pointer at the PM0 DATA mini-script. 169459743Sgroudier */ 169559743Sgroudier SCR_LOAD_ABS (temp, 4), 169659743Sgroudier PADDR_B (pm0_data_addr), 169759743Sgroudier SCR_JUMP, 169859743Sgroudier PADDR_A (dispatch), 169959743Sgroudier}/*-------------------------< PM1_SAVE >-------------------------*/,{ 170059743Sgroudier SCR_STORE_REL (ia, 4), 170159743Sgroudier offsetof(struct sym_ccb, phys.pm1.ret), 170259743Sgroudier /* 170359743Sgroudier * If WSR bit is set, either UA and RBC may 170459743Sgroudier * have to be changed whether the device wants 170559743Sgroudier * to ignore this residue or not. 170659743Sgroudier */ 170759743Sgroudier SCR_FROM_REG (scntl2), 170859743Sgroudier 0, 170959743Sgroudier SCR_CALL ^ IFTRUE (MASK (WSR, WSR)), 171059743Sgroudier PADDR_B (pm_wsr_handle), 171159743Sgroudier /* 171259743Sgroudier * Save the remaining byte count, the updated 171359743Sgroudier * address and the return address. 171459743Sgroudier */ 171559743Sgroudier SCR_STORE_REL (rbc, 4), 171659743Sgroudier offsetof(struct sym_ccb, phys.pm1.sg.size), 171759743Sgroudier SCR_STORE_REL (ua, 4), 171859743Sgroudier offsetof(struct sym_ccb, phys.pm1.sg.addr), 171959743Sgroudier /* 172059743Sgroudier * Set the current pointer at the PM1 DATA mini-script. 172159743Sgroudier */ 172259743Sgroudier SCR_LOAD_ABS (temp, 4), 172359743Sgroudier PADDR_B (pm1_data_addr), 172459743Sgroudier SCR_JUMP, 172559743Sgroudier PADDR_A (dispatch), 172659743Sgroudier}/*-------------------------< PM_WSR_HANDLE >--------------------*/,{ 172759743Sgroudier /* 172859743Sgroudier * Phase mismatch handling from SCRIPT with WSR set. 172959743Sgroudier * Such a condition can occur if the chip wants to 173059743Sgroudier * execute a CHMOV(size > 1) when the WSR bit is 173159743Sgroudier * set and the target changes PHASE. 173259743Sgroudier * 173359743Sgroudier * We must move the residual byte to memory. 173459743Sgroudier * 173559743Sgroudier * UA contains bit 0..31 of the address to 173659743Sgroudier * move the residual byte. 173759743Sgroudier * Move it to the table indirect. 173859743Sgroudier */ 173959743Sgroudier SCR_STORE_REL (ua, 4), 174059743Sgroudier offsetof (struct sym_ccb, phys.wresid.addr), 174159743Sgroudier /* 174259743Sgroudier * Increment UA (move address to next position). 174359743Sgroudier */ 174459743Sgroudier SCR_REG_REG (ua, SCR_ADD, 1), 174559743Sgroudier 0, 174659743Sgroudier SCR_REG_REG (ua1, SCR_ADDC, 0), 174759743Sgroudier 0, 174859743Sgroudier SCR_REG_REG (ua2, SCR_ADDC, 0), 174959743Sgroudier 0, 175059743Sgroudier SCR_REG_REG (ua3, SCR_ADDC, 0), 175159743Sgroudier 0, 175259743Sgroudier /* 175359743Sgroudier * Compute SCRATCHA as: 175459743Sgroudier * - size to transfer = 1 byte. 175559743Sgroudier * - bit 24..31 = high address bit [32...39]. 175659743Sgroudier */ 175759743Sgroudier SCR_LOAD_ABS (scratcha, 4), 175859743Sgroudier PADDR_B (zero), 175959743Sgroudier SCR_REG_REG (scratcha, SCR_OR, 1), 176059743Sgroudier 0, 176159743Sgroudier SCR_FROM_REG (rbc3), 176259743Sgroudier 0, 176359743Sgroudier SCR_TO_REG (scratcha3), 176459743Sgroudier 0, 176559743Sgroudier /* 176659743Sgroudier * Move this value to the table indirect. 176759743Sgroudier */ 176859743Sgroudier SCR_STORE_REL (scratcha, 4), 176959743Sgroudier offsetof (struct sym_ccb, phys.wresid.size), 177059743Sgroudier /* 177159743Sgroudier * Wait for a valid phase. 177259743Sgroudier * While testing with bogus QUANTUM drives, the C1010 177359743Sgroudier * sometimes raised a spurious phase mismatch with 177459743Sgroudier * WSR and the CHMOV(1) triggered another PM. 177559743Sgroudier * Waiting explicitely for the PHASE seemed to avoid 177659743Sgroudier * the nested phase mismatch. Btw, this didn't happen 177759743Sgroudier * using my IBM drives. 177859743Sgroudier */ 177959743Sgroudier SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_IN)), 178059743Sgroudier 0, 178159743Sgroudier /* 178259743Sgroudier * Perform the move of the residual byte. 178359743Sgroudier */ 178459743Sgroudier SCR_CHMOV_TBL ^ SCR_DATA_IN, 178559743Sgroudier offsetof (struct sym_ccb, phys.wresid), 178659743Sgroudier /* 178759743Sgroudier * We can now handle the phase mismatch with UA fixed. 178859743Sgroudier * RBC[0..23]=0 is a special case that does not require 178959743Sgroudier * a PM context. The C code also checks against this. 179059743Sgroudier */ 179159743Sgroudier SCR_FROM_REG (rbc), 179259743Sgroudier 0, 179359743Sgroudier SCR_RETURN ^ IFFALSE (DATA (0)), 179459743Sgroudier 0, 179559743Sgroudier SCR_FROM_REG (rbc1), 179659743Sgroudier 0, 179759743Sgroudier SCR_RETURN ^ IFFALSE (DATA (0)), 179859743Sgroudier 0, 179959743Sgroudier SCR_FROM_REG (rbc2), 180059743Sgroudier 0, 180159743Sgroudier SCR_RETURN ^ IFFALSE (DATA (0)), 180259743Sgroudier 0, 180359743Sgroudier /* 180459743Sgroudier * RBC[0..23]=0. 180559743Sgroudier * Not only we donnot need a PM context, but this would 180659743Sgroudier * lead to a bogus CHMOV(0). This condition means that 180759743Sgroudier * the residual was the last byte to move from this CHMOV. 180859743Sgroudier * So, we just have to move the current data script pointer 180959743Sgroudier * (i.e. TEMP) to the SCRIPTS address following the 181059743Sgroudier * interrupted CHMOV and jump to dispatcher. 181159743Sgroudier */ 181259743Sgroudier SCR_STORE_ABS (ia, 4), 181359743Sgroudier PADDR_B (scratch), 181459743Sgroudier SCR_LOAD_ABS (temp, 4), 181559743Sgroudier PADDR_B (scratch), 181659743Sgroudier SCR_JUMP, 181759743Sgroudier PADDR_A (dispatch), 181859743Sgroudier}/*-------------------------< WSR_MA_HELPER >--------------------*/,{ 181959743Sgroudier /* 182059743Sgroudier * Helper for the C code when WSR bit is set. 182159743Sgroudier * Perform the move of the residual byte. 182259743Sgroudier */ 182359743Sgroudier SCR_CHMOV_TBL ^ SCR_DATA_IN, 182459743Sgroudier offsetof (struct sym_ccb, phys.wresid), 182559743Sgroudier SCR_JUMP, 182659743Sgroudier PADDR_A (dispatch), 182759743Sgroudier}/*-------------------------< ZERO >-----------------------------*/,{ 182859743Sgroudier SCR_DATA_ZERO, 182959743Sgroudier}/*-------------------------< SCRATCH >--------------------------*/,{ 183059743Sgroudier SCR_DATA_ZERO, 183159743Sgroudier}/*-------------------------< PM0_DATA_ADDR >--------------------*/,{ 183259743Sgroudier SCR_DATA_ZERO, 183359743Sgroudier}/*-------------------------< PM1_DATA_ADDR >--------------------*/,{ 183459743Sgroudier SCR_DATA_ZERO, 183559743Sgroudier}/*-------------------------< SAVED_DSA >------------------------*/,{ 183659743Sgroudier SCR_DATA_ZERO, 183759743Sgroudier}/*-------------------------< SAVED_DRS >------------------------*/,{ 183859743Sgroudier SCR_DATA_ZERO, 183959743Sgroudier}/*-------------------------< DONE_POS >-------------------------*/,{ 184059743Sgroudier SCR_DATA_ZERO, 184159743Sgroudier}/*-------------------------< STARTPOS >-------------------------*/,{ 184259743Sgroudier SCR_DATA_ZERO, 184359743Sgroudier}/*-------------------------< TARGTBL >--------------------------*/,{ 184459743Sgroudier SCR_DATA_ZERO, 184559743Sgroudier 184659743Sgroudier}/*-------------------------< SNOOPTEST >------------------------*/,{ 184759743Sgroudier /* 184859743Sgroudier * Read the variable from memory. 184959743Sgroudier */ 185059743Sgroudier SCR_LOAD_REL (scratcha, 4), 185159743Sgroudier offsetof(struct sym_hcb, cache), 185259743Sgroudier /* 185359743Sgroudier * Write the variable to memory. 185459743Sgroudier */ 185559743Sgroudier SCR_STORE_REL (temp, 4), 185659743Sgroudier offsetof(struct sym_hcb, cache), 185759743Sgroudier /* 185859743Sgroudier * Read back the variable from memory. 185959743Sgroudier */ 186059743Sgroudier SCR_LOAD_REL (temp, 4), 186159743Sgroudier offsetof(struct sym_hcb, cache), 186259743Sgroudier}/*-------------------------< SNOOPEND >-------------------------*/,{ 186359743Sgroudier /* 186459743Sgroudier * And stop. 186559743Sgroudier */ 186659743Sgroudier SCR_INT, 186759743Sgroudier 99, 186859743Sgroudier}/*-------------------------<>-----------------------------------*/ 186959743Sgroudier}; 1870