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 [ 11]; 7759743Sgroudier u32 getjob_begin [ 4]; 7859743Sgroudier u32 _sms_a10 [ 5]; 7959743Sgroudier u32 getjob_end [ 4]; 8059743Sgroudier u32 _sms_a20 [ 4]; 8159743Sgroudier u32 select [ 8]; 8259743Sgroudier u32 _sms_a30 [ 8]; 8359743Sgroudier u32 wf_sel_done [ 2]; 8459743Sgroudier u32 send_ident [ 2]; 8559743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT 8659743Sgroudier u32 select2 [ 8]; 8759743Sgroudier#else 8859743Sgroudier u32 select2 [ 2]; 8959743Sgroudier#endif 9059743Sgroudier u32 command [ 2]; 9159743Sgroudier u32 dispatch [ 28]; 9259743Sgroudier u32 sel_no_cmd [ 10]; 9359743Sgroudier u32 init [ 6]; 9459743Sgroudier u32 clrack [ 4]; 9559743Sgroudier u32 disp_status [ 4]; 9659743Sgroudier u32 datai_done [ 26]; 9759743Sgroudier u32 datao_done [ 12]; 9859743Sgroudier u32 datai_phase [ 2]; 9959743Sgroudier u32 datao_phase [ 2]; 10059743Sgroudier u32 msg_in [ 2]; 10159743Sgroudier u32 msg_in2 [ 10]; 10259743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT 10359743Sgroudier u32 status [ 14]; 10459743Sgroudier#else 10559743Sgroudier u32 status [ 10]; 10659743Sgroudier#endif 10759743Sgroudier u32 complete [ 9]; 10859743Sgroudier u32 complete2 [ 8]; 10959743Sgroudier u32 _sms_a40 [ 12]; 11059743Sgroudier u32 complete_error [ 5]; 11159743Sgroudier u32 done [ 5]; 11259743Sgroudier u32 _sms_a50 [ 5]; 11359743Sgroudier u32 _sms_a60 [ 2]; 11459743Sgroudier u32 done_end [ 4]; 11559743Sgroudier u32 save_dp [ 9]; 11659743Sgroudier u32 restore_dp [ 5]; 11759743Sgroudier u32 disconnect [ 20]; 11859743Sgroudier u32 disconnect2 [ 5]; 11959743Sgroudier u32 _sms_a65 [ 3]; 12059743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT 12159743Sgroudier u32 idle [ 4]; 12259743Sgroudier#else 12359743Sgroudier u32 idle [ 2]; 12459743Sgroudier#endif 12559743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT 12659743Sgroudier u32 ungetjob [ 7]; 12759743Sgroudier#else 12859743Sgroudier u32 ungetjob [ 5]; 12959743Sgroudier#endif 13059743Sgroudier u32 reselect [ 4]; 13159743Sgroudier u32 reselected [ 19]; 13259743Sgroudier u32 _sms_a70 [ 6]; 13359743Sgroudier u32 _sms_a80 [ 4]; 13459743Sgroudier u32 reselected1 [ 25]; 13559743Sgroudier u32 _sms_a90 [ 4]; 13659743Sgroudier u32 resel_lun0 [ 7]; 13759743Sgroudier u32 _sms_a100 [ 4]; 13859743Sgroudier u32 resel_tag [ 8]; 13959743Sgroudier#if SYM_CONF_MAX_TASK*4 > 512 14059743Sgroudier u32 _sms_a110 [ 23]; 14159743Sgroudier#elif SYM_CONF_MAX_TASK*4 > 256 14259743Sgroudier u32 _sms_a110 [ 17]; 14359743Sgroudier#else 14459743Sgroudier u32 _sms_a110 [ 13]; 14559743Sgroudier#endif 14659743Sgroudier u32 _sms_a120 [ 2]; 14759743Sgroudier u32 resel_go [ 4]; 14859743Sgroudier u32 _sms_a130 [ 7]; 14959743Sgroudier u32 resel_dsa [ 2]; 15059743Sgroudier u32 resel_dsa1 [ 4]; 15159743Sgroudier u32 _sms_a140 [ 10]; 15259743Sgroudier u32 resel_no_tag [ 4]; 15359743Sgroudier u32 _sms_a145 [ 7]; 15459743Sgroudier u32 data_in [SYM_CONF_MAX_SG * 2]; 15559743Sgroudier u32 data_in2 [ 4]; 15659743Sgroudier u32 data_out [SYM_CONF_MAX_SG * 2]; 15759743Sgroudier u32 data_out2 [ 4]; 15859743Sgroudier u32 pm0_data [ 12]; 15959743Sgroudier u32 pm0_data_out [ 6]; 16059743Sgroudier u32 pm0_data_end [ 7]; 16159743Sgroudier u32 pm_data_end [ 4]; 16259743Sgroudier u32 _sms_a150 [ 4]; 16359743Sgroudier u32 pm1_data [ 12]; 16459743Sgroudier u32 pm1_data_out [ 6]; 16559743Sgroudier u32 pm1_data_end [ 9]; 16659743Sgroudier}; 16759743Sgroudier 16859743Sgroudier/* 16959743Sgroudier * Script fragments which stay in main memory for all chips 17059743Sgroudier * except for chips that support 8K on-chip RAM. 17159743Sgroudier */ 17259743Sgroudierstruct SYM_FWB_SCR { 17359743Sgroudier u32 no_data [ 2]; 17459743Sgroudier u32 sel_for_abort [ 18]; 17559743Sgroudier u32 sel_for_abort_1 [ 2]; 17659743Sgroudier u32 msg_in_etc [ 12]; 17759743Sgroudier u32 msg_received [ 5]; 17859743Sgroudier u32 msg_weird_seen [ 5]; 17959743Sgroudier u32 msg_extended [ 17]; 18059743Sgroudier u32 _sms_b10 [ 4]; 18159743Sgroudier u32 msg_bad [ 6]; 18259743Sgroudier u32 msg_weird [ 4]; 18359743Sgroudier u32 msg_weird1 [ 8]; 18459743Sgroudier u32 wdtr_resp [ 6]; 18559743Sgroudier u32 send_wdtr [ 4]; 18659743Sgroudier u32 sdtr_resp [ 6]; 18759743Sgroudier u32 send_sdtr [ 4]; 18859743Sgroudier u32 ppr_resp [ 6]; 18959743Sgroudier u32 send_ppr [ 4]; 19059743Sgroudier u32 nego_bad_phase [ 4]; 19159743Sgroudier u32 msg_out [ 4]; 19259743Sgroudier u32 msg_out_done [ 4]; 19359743Sgroudier u32 data_ovrun [ 3]; 19459743Sgroudier u32 data_ovrun1 [ 22]; 19559743Sgroudier u32 data_ovrun2 [ 8]; 19659743Sgroudier u32 abort_resel [ 16]; 19759743Sgroudier u32 resend_ident [ 4]; 19859743Sgroudier u32 ident_break [ 4]; 19959743Sgroudier u32 ident_break_atn [ 4]; 20059743Sgroudier u32 sdata_in [ 6]; 20159743Sgroudier u32 resel_bad_lun [ 4]; 20259743Sgroudier u32 bad_i_t_l [ 4]; 20359743Sgroudier u32 bad_i_t_l_q [ 4]; 20459743Sgroudier u32 bad_status [ 7]; 20559743Sgroudier u32 wsr_ma_helper [ 4]; 20659743Sgroudier 20759743Sgroudier /* Data area */ 20859743Sgroudier u32 zero [ 1]; 20959743Sgroudier u32 scratch [ 1]; 21059743Sgroudier u32 scratch1 [ 1]; 21159743Sgroudier u32 prev_done [ 1]; 21259743Sgroudier u32 done_pos [ 1]; 21359743Sgroudier u32 nextjob [ 1]; 21459743Sgroudier u32 startpos [ 1]; 21559743Sgroudier u32 targtbl [ 1]; 21659743Sgroudier /* End of data area */ 21759743Sgroudier 21859743Sgroudier u32 snooptest [ 9]; 21959743Sgroudier u32 snoopend [ 2]; 22059743Sgroudier}; 22159743Sgroudier 222179029Smariusstatic const struct SYM_FWA_SCR SYM_FWA_SCR = { 22359743Sgroudier/*--------------------------< START >----------------------------*/ { 22459743Sgroudier /* 22559743Sgroudier * Switch the LED on. 22659743Sgroudier * Will be patched with a NO_OP if LED 22759743Sgroudier * not needed or not desired. 22859743Sgroudier */ 22959743Sgroudier SCR_REG_REG (gpreg, SCR_AND, 0xfe), 23059743Sgroudier 0, 23159743Sgroudier /* 23259743Sgroudier * Clear SIGP. 23359743Sgroudier */ 23459743Sgroudier SCR_FROM_REG (ctest2), 23559743Sgroudier 0, 23659743Sgroudier /* 23759743Sgroudier * Stop here if the C code wants to perform 23859743Sgroudier * some error recovery procedure manually. 23959743Sgroudier * (Indicate this by setting SEM in ISTAT) 24059743Sgroudier */ 24159743Sgroudier SCR_FROM_REG (istat), 24259743Sgroudier 0, 24359743Sgroudier /* 24459743Sgroudier * Report to the C code the next position in 24559743Sgroudier * the start queue the SCRIPTS will schedule. 24659743Sgroudier * The C code must not change SCRATCHA. 24759743Sgroudier */ 24859743Sgroudier SCR_COPY (4), 24959743Sgroudier PADDR_B (startpos), 25059743Sgroudier RADDR_1 (scratcha), 25159743Sgroudier SCR_INT ^ IFTRUE (MASK (SEM, SEM)), 25259743Sgroudier SIR_SCRIPT_STOPPED, 25359743Sgroudier /* 25459743Sgroudier * Start the next job. 25559743Sgroudier * 25659743Sgroudier * @DSA = start point for this job. 25759743Sgroudier * SCRATCHA = address of this job in the start queue. 25859743Sgroudier * 25959743Sgroudier * We will restore startpos with SCRATCHA if we fails the 26059743Sgroudier * arbitration or if it is the idle job. 26159743Sgroudier * 26259743Sgroudier * The below GETJOB_BEGIN to GETJOB_END section of SCRIPTS 26359743Sgroudier * is a critical path. If it is partially executed, it then 26459743Sgroudier * may happen that the job address is not yet in the DSA 265218909Sbrucec * and the next queue position points to the next JOB. 26659743Sgroudier */ 26759743Sgroudier}/*-------------------------< GETJOB_BEGIN >---------------------*/,{ 26859743Sgroudier /* 26959743Sgroudier * Copy to a fixed location both the next STARTPOS 27059743Sgroudier * and the current JOB address, using self modifying 27159743Sgroudier * SCRIPTS. 27259743Sgroudier */ 27359743Sgroudier SCR_COPY (4), 27459743Sgroudier RADDR_1 (scratcha), 27559743Sgroudier PADDR_A (_sms_a10), 27659743Sgroudier SCR_COPY (8), 27759743Sgroudier}/*-------------------------< _SMS_A10 >-------------------------*/,{ 27859743Sgroudier 0, 27959743Sgroudier PADDR_B (nextjob), 28059743Sgroudier /* 28159743Sgroudier * Move the start address to TEMP using self- 28259743Sgroudier * modifying SCRIPTS and jump indirectly to 28359743Sgroudier * that address. 28459743Sgroudier */ 28559743Sgroudier SCR_COPY (4), 28659743Sgroudier PADDR_B (nextjob), 28759743Sgroudier RADDR_1 (dsa), 28859743Sgroudier}/*-------------------------< GETJOB_END >-----------------------*/,{ 28959743Sgroudier SCR_COPY (4), 29059743Sgroudier RADDR_1 (dsa), 29159743Sgroudier PADDR_A (_sms_a20), 29259743Sgroudier SCR_COPY (4), 29359743Sgroudier}/*-------------------------< _SMS_A20 >-------------------------*/,{ 29459743Sgroudier 0, 29559743Sgroudier RADDR_1 (temp), 29659743Sgroudier SCR_RETURN, 29759743Sgroudier 0, 29859743Sgroudier}/*-------------------------< SELECT >---------------------------*/,{ 29959743Sgroudier /* 30059743Sgroudier * DSA contains the address of a scheduled 30159743Sgroudier * data structure. 30259743Sgroudier * 30359743Sgroudier * SCRATCHA contains the address of the start queue 30459743Sgroudier * entry which points to the next job. 30559743Sgroudier * 30659743Sgroudier * Set Initiator mode. 30759743Sgroudier * 30859743Sgroudier * (Target mode is left as an exercise for the reader) 30959743Sgroudier */ 31059743Sgroudier SCR_CLR (SCR_TRG), 31159743Sgroudier 0, 31259743Sgroudier /* 31359743Sgroudier * And try to select this target. 31459743Sgroudier */ 31559743Sgroudier SCR_SEL_TBL_ATN ^ offsetof (struct sym_dsb, select), 31659743Sgroudier PADDR_A (ungetjob), 31759743Sgroudier /* 31859743Sgroudier * Now there are 4 possibilities: 31959743Sgroudier * 320160964Syar * (1) The chip loses arbitration. 32159743Sgroudier * This is ok, because it will try again, 32259743Sgroudier * when the bus becomes idle. 32359743Sgroudier * (But beware of the timeout function!) 32459743Sgroudier * 32559743Sgroudier * (2) The chip is reselected. 32659743Sgroudier * Then the script processor takes the jump 32759743Sgroudier * to the RESELECT label. 32859743Sgroudier * 32959743Sgroudier * (3) The chip wins arbitration. 33059743Sgroudier * Then it will execute SCRIPTS instruction until 33159743Sgroudier * the next instruction that checks SCSI phase. 33259743Sgroudier * Then will stop and wait for selection to be 33359743Sgroudier * complete or selection time-out to occur. 33459743Sgroudier * 33559743Sgroudier * After having won arbitration, the SCRIPTS 33659743Sgroudier * processor is able to execute instructions while 33759743Sgroudier * the SCSI core is performing SCSI selection. 33859743Sgroudier */ 33959743Sgroudier 34059743Sgroudier /* 34159743Sgroudier * Copy the CCB header to a fixed location 34259743Sgroudier * in the HCB using self-modifying SCRIPTS. 34359743Sgroudier */ 34459743Sgroudier SCR_COPY (4), 34559743Sgroudier RADDR_1 (dsa), 34659743Sgroudier PADDR_A (_sms_a30), 34759743Sgroudier SCR_COPY (sizeof(struct sym_ccbh)), 34859743Sgroudier}/*-------------------------< _SMS_A30 >-------------------------*/,{ 34959743Sgroudier 0, 35059743Sgroudier HADDR_1 (ccb_head), 35159743Sgroudier /* 35259743Sgroudier * Load the savep (saved data pointer) into 35359743Sgroudier * the actual data pointer. 35459743Sgroudier */ 35559743Sgroudier SCR_COPY (4), 35659743Sgroudier HADDR_1 (ccb_head.savep), 35759743Sgroudier RADDR_1 (temp), 35859743Sgroudier /* 35959743Sgroudier * Initialize the status register 36059743Sgroudier */ 36159743Sgroudier SCR_COPY (4), 36259743Sgroudier HADDR_1 (ccb_head.status), 36359743Sgroudier RADDR_1 (scr0), 36459743Sgroudier}/*-------------------------< WF_SEL_DONE >----------------------*/,{ 36559743Sgroudier SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)), 36659743Sgroudier SIR_SEL_ATN_NO_MSG_OUT, 36759743Sgroudier}/*-------------------------< SEND_IDENT >-----------------------*/,{ 36859743Sgroudier /* 36959743Sgroudier * Selection complete. 37059743Sgroudier * Send the IDENTIFY and possibly the TAG message 37159743Sgroudier * and negotiation message if present. 37259743Sgroudier */ 37359743Sgroudier SCR_MOVE_TBL ^ SCR_MSG_OUT, 37459743Sgroudier offsetof (struct sym_dsb, smsg), 37559743Sgroudier}/*-------------------------< SELECT2 >--------------------------*/,{ 37659743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT 37759743Sgroudier /* 37859743Sgroudier * Set IMMEDIATE ARBITRATION if we have been given 37959743Sgroudier * a hint to do so. (Some job to do after this one). 38059743Sgroudier */ 38159743Sgroudier SCR_FROM_REG (HF_REG), 38259743Sgroudier 0, 38359743Sgroudier SCR_JUMPR ^ IFFALSE (MASK (HF_HINT_IARB, HF_HINT_IARB)), 38459743Sgroudier 8, 38559743Sgroudier SCR_REG_REG (scntl1, SCR_OR, IARB), 38659743Sgroudier 0, 38759743Sgroudier#endif 38859743Sgroudier /* 38959743Sgroudier * Anticipate the COMMAND phase. 39059743Sgroudier * This is the PHASE we expect at this point. 39159743Sgroudier */ 39259743Sgroudier SCR_JUMP ^ IFFALSE (WHEN (SCR_COMMAND)), 39359743Sgroudier PADDR_A (sel_no_cmd), 39459743Sgroudier}/*-------------------------< COMMAND >--------------------------*/,{ 39559743Sgroudier /* 39659743Sgroudier * ... and send the command 39759743Sgroudier */ 39859743Sgroudier SCR_MOVE_TBL ^ SCR_COMMAND, 39959743Sgroudier offsetof (struct sym_dsb, cmd), 40059743Sgroudier}/*-------------------------< DISPATCH >-------------------------*/,{ 40159743Sgroudier /* 40259743Sgroudier * MSG_IN is the only phase that shall be 40359743Sgroudier * entered at least once for each (re)selection. 40459743Sgroudier * So we test it first. 40559743Sgroudier */ 40659743Sgroudier SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)), 40759743Sgroudier PADDR_A (msg_in), 40859743Sgroudier SCR_JUMP ^ IFTRUE (IF (SCR_DATA_OUT)), 40959743Sgroudier PADDR_A (datao_phase), 41059743Sgroudier SCR_JUMP ^ IFTRUE (IF (SCR_DATA_IN)), 41159743Sgroudier PADDR_A (datai_phase), 41259743Sgroudier SCR_JUMP ^ IFTRUE (IF (SCR_STATUS)), 41359743Sgroudier PADDR_A (status), 41459743Sgroudier SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)), 41559743Sgroudier PADDR_A (command), 41659743Sgroudier SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)), 41759743Sgroudier PADDR_B (msg_out), 41859743Sgroudier /* 41959743Sgroudier * Discard as many illegal phases as 42059743Sgroudier * required and tell the C code about. 42159743Sgroudier */ 42259743Sgroudier SCR_JUMPR ^ IFFALSE (WHEN (SCR_ILG_OUT)), 42359743Sgroudier 16, 42459743Sgroudier SCR_MOVE_ABS (1) ^ SCR_ILG_OUT, 42559743Sgroudier HADDR_1 (scratch), 42659743Sgroudier SCR_JUMPR ^ IFTRUE (WHEN (SCR_ILG_OUT)), 42759743Sgroudier -16, 42859743Sgroudier SCR_JUMPR ^ IFFALSE (WHEN (SCR_ILG_IN)), 42959743Sgroudier 16, 43059743Sgroudier SCR_MOVE_ABS (1) ^ SCR_ILG_IN, 43159743Sgroudier HADDR_1 (scratch), 43259743Sgroudier SCR_JUMPR ^ IFTRUE (WHEN (SCR_ILG_IN)), 43359743Sgroudier -16, 43459743Sgroudier SCR_INT, 43559743Sgroudier SIR_BAD_PHASE, 43659743Sgroudier SCR_JUMP, 43759743Sgroudier PADDR_A (dispatch), 43859743Sgroudier}/*-------------------------< SEL_NO_CMD >-----------------------*/,{ 43959743Sgroudier /* 44059743Sgroudier * The target does not switch to command 44159743Sgroudier * phase after IDENTIFY has been sent. 44259743Sgroudier * 44359743Sgroudier * If it stays in MSG OUT phase send it 44459743Sgroudier * the IDENTIFY again. 44559743Sgroudier */ 44659743Sgroudier SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)), 44759743Sgroudier PADDR_B (resend_ident), 44859743Sgroudier /* 44959743Sgroudier * If target does not switch to MSG IN phase 45059743Sgroudier * and we sent a negotiation, assert the 45159743Sgroudier * failure immediately. 45259743Sgroudier */ 45359743Sgroudier SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)), 45459743Sgroudier PADDR_A (dispatch), 45559743Sgroudier SCR_FROM_REG (HS_REG), 45659743Sgroudier 0, 45759743Sgroudier SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)), 45859743Sgroudier SIR_NEGO_FAILED, 45959743Sgroudier /* 46059743Sgroudier * Jump to dispatcher. 46159743Sgroudier */ 46259743Sgroudier SCR_JUMP, 46359743Sgroudier PADDR_A (dispatch), 46459743Sgroudier}/*-------------------------< INIT >-----------------------------*/,{ 46559743Sgroudier /* 46659743Sgroudier * Wait for the SCSI RESET signal to be 46759743Sgroudier * inactive before restarting operations, 46859743Sgroudier * since the chip may hang on SEL_ATN 46959743Sgroudier * if SCSI RESET is active. 47059743Sgroudier */ 47159743Sgroudier SCR_FROM_REG (sstat0), 47259743Sgroudier 0, 47359743Sgroudier SCR_JUMPR ^ IFTRUE (MASK (IRST, IRST)), 47459743Sgroudier -16, 47559743Sgroudier SCR_JUMP, 47659743Sgroudier PADDR_A (start), 47759743Sgroudier}/*-------------------------< CLRACK >---------------------------*/,{ 47859743Sgroudier /* 47959743Sgroudier * Terminate possible pending message phase. 48059743Sgroudier */ 48159743Sgroudier SCR_CLR (SCR_ACK), 48259743Sgroudier 0, 48359743Sgroudier SCR_JUMP, 48459743Sgroudier PADDR_A (dispatch), 48559743Sgroudier}/*-------------------------< DISP_STATUS >----------------------*/,{ 48659743Sgroudier /* 48759743Sgroudier * Anticipate STATUS phase. 48859743Sgroudier * 48959743Sgroudier * Does spare 3 SCRIPTS instructions when we have 49059743Sgroudier * completed the INPUT of the data. 49159743Sgroudier */ 49259743Sgroudier SCR_JUMP ^ IFTRUE (WHEN (SCR_STATUS)), 49359743Sgroudier PADDR_A (status), 49459743Sgroudier SCR_JUMP, 49559743Sgroudier PADDR_A (dispatch), 49659743Sgroudier}/*-------------------------< DATAI_DONE >-----------------------*/,{ 49759743Sgroudier /* 49859743Sgroudier * If the device still wants to send us data, 49959743Sgroudier * we must count the extra bytes. 50059743Sgroudier */ 50159743Sgroudier SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_IN)), 50259743Sgroudier PADDR_B (data_ovrun), 50359743Sgroudier /* 50459743Sgroudier * If the SWIDE is not full, jump to dispatcher. 50559743Sgroudier * We anticipate a STATUS phase. 50659743Sgroudier */ 50759743Sgroudier SCR_FROM_REG (scntl2), 50859743Sgroudier 0, 50959743Sgroudier SCR_JUMP ^ IFFALSE (MASK (WSR, WSR)), 51059743Sgroudier PADDR_A (disp_status), 51159743Sgroudier /* 51259743Sgroudier * The SWIDE is full. 51359743Sgroudier * Clear this condition. 51459743Sgroudier */ 51559743Sgroudier SCR_REG_REG (scntl2, SCR_OR, WSR), 51659743Sgroudier 0, 51759743Sgroudier /* 51859743Sgroudier * We are expecting an IGNORE RESIDUE message 51959743Sgroudier * from the device, otherwise we are in data 52059743Sgroudier * overrun condition. Check against MSG_IN phase. 52159743Sgroudier */ 52259743Sgroudier SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)), 52359743Sgroudier SIR_SWIDE_OVERRUN, 52459743Sgroudier SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), 52559743Sgroudier PADDR_A (disp_status), 52659743Sgroudier /* 52759743Sgroudier * We are in MSG_IN phase, 52859743Sgroudier * Read the first byte of the message. 52959743Sgroudier * If it is not an IGNORE RESIDUE message, 53059743Sgroudier * signal overrun and jump to message 53159743Sgroudier * processing. 53259743Sgroudier */ 53359743Sgroudier SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 53459743Sgroudier HADDR_1 (msgin[0]), 53559743Sgroudier SCR_INT ^ IFFALSE (DATA (M_IGN_RESIDUE)), 53659743Sgroudier SIR_SWIDE_OVERRUN, 53759743Sgroudier SCR_JUMP ^ IFFALSE (DATA (M_IGN_RESIDUE)), 53859743Sgroudier PADDR_A (msg_in2), 53959743Sgroudier /* 54059743Sgroudier * We got the message we expected. 54159743Sgroudier * Read the 2nd byte, and jump to dispatcher. 54259743Sgroudier */ 54359743Sgroudier SCR_CLR (SCR_ACK), 54459743Sgroudier 0, 54559743Sgroudier SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 54659743Sgroudier HADDR_1 (msgin[1]), 54759743Sgroudier SCR_CLR (SCR_ACK), 54859743Sgroudier 0, 54959743Sgroudier SCR_JUMP, 55059743Sgroudier PADDR_A (disp_status), 55159743Sgroudier}/*-------------------------< DATAO_DONE >-----------------------*/,{ 55259743Sgroudier /* 55359743Sgroudier * If the device wants us to send more data, 55459743Sgroudier * we must count the extra bytes. 55559743Sgroudier */ 55659743Sgroudier SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_OUT)), 55759743Sgroudier PADDR_B (data_ovrun), 55859743Sgroudier /* 55959743Sgroudier * If the SODL is not full jump to dispatcher. 56059743Sgroudier * We anticipate a STATUS phase. 56159743Sgroudier */ 56259743Sgroudier SCR_FROM_REG (scntl2), 56359743Sgroudier 0, 56459743Sgroudier SCR_JUMP ^ IFFALSE (MASK (WSS, WSS)), 56559743Sgroudier PADDR_A (disp_status), 56659743Sgroudier /* 56759743Sgroudier * The SODL is full, clear this condition. 56859743Sgroudier */ 56959743Sgroudier SCR_REG_REG (scntl2, SCR_OR, WSS), 57059743Sgroudier 0, 57159743Sgroudier /* 57259743Sgroudier * And signal a DATA UNDERRUN condition 57359743Sgroudier * to the C code. 57459743Sgroudier */ 57559743Sgroudier SCR_INT, 57659743Sgroudier SIR_SODL_UNDERRUN, 57759743Sgroudier SCR_JUMP, 57859743Sgroudier PADDR_A (dispatch), 57959743Sgroudier}/*-------------------------< DATAI_PHASE >----------------------*/,{ 58059743Sgroudier SCR_RETURN, 58159743Sgroudier 0, 58259743Sgroudier}/*-------------------------< DATAO_PHASE >----------------------*/,{ 58359743Sgroudier SCR_RETURN, 58459743Sgroudier 0, 58559743Sgroudier}/*-------------------------< MSG_IN >---------------------------*/,{ 58659743Sgroudier /* 58759743Sgroudier * Get the first byte of the message. 58859743Sgroudier * 58959743Sgroudier * The script processor doesn't negate the 59059743Sgroudier * ACK signal after this transfer. 59159743Sgroudier */ 59259743Sgroudier SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 59359743Sgroudier HADDR_1 (msgin[0]), 59459743Sgroudier}/*-------------------------< MSG_IN2 >--------------------------*/,{ 59559743Sgroudier /* 59659743Sgroudier * Check first against 1 byte messages 59759743Sgroudier * that we handle from SCRIPTS. 59859743Sgroudier */ 59959743Sgroudier SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE)), 60059743Sgroudier PADDR_A (complete), 60159743Sgroudier SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)), 60259743Sgroudier PADDR_A (disconnect), 60359743Sgroudier SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)), 60459743Sgroudier PADDR_A (save_dp), 60559743Sgroudier SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)), 60659743Sgroudier PADDR_A (restore_dp), 60759743Sgroudier /* 60859743Sgroudier * We handle all other messages from the 60959743Sgroudier * C code, so no need to waste on-chip RAM 61059743Sgroudier * for those ones. 61159743Sgroudier */ 61259743Sgroudier SCR_JUMP, 61359743Sgroudier PADDR_B (msg_in_etc), 61459743Sgroudier}/*-------------------------< STATUS >---------------------------*/,{ 61559743Sgroudier /* 61659743Sgroudier * get the status 61759743Sgroudier */ 61859743Sgroudier SCR_MOVE_ABS (1) ^ SCR_STATUS, 61959743Sgroudier HADDR_1 (scratch), 62059743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT 62159743Sgroudier /* 62259743Sgroudier * If STATUS is not GOOD, clear IMMEDIATE ARBITRATION, 62359743Sgroudier * since we may have to tamper the start queue from 62459743Sgroudier * the C code. 62559743Sgroudier */ 62659743Sgroudier SCR_JUMPR ^ IFTRUE (DATA (S_GOOD)), 62759743Sgroudier 8, 62859743Sgroudier SCR_REG_REG (scntl1, SCR_AND, ~IARB), 62959743Sgroudier 0, 63059743Sgroudier#endif 63159743Sgroudier /* 63259743Sgroudier * save status to scsi_status. 63359743Sgroudier * mark as complete. 63459743Sgroudier */ 63559743Sgroudier SCR_TO_REG (SS_REG), 63659743Sgroudier 0, 63759743Sgroudier SCR_LOAD_REG (HS_REG, HS_COMPLETE), 63859743Sgroudier 0, 63959743Sgroudier /* 64059743Sgroudier * Anticipate the MESSAGE PHASE for 64159743Sgroudier * the TASK COMPLETE message. 64259743Sgroudier */ 64359743Sgroudier SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)), 64459743Sgroudier PADDR_A (msg_in), 64559743Sgroudier SCR_JUMP, 64659743Sgroudier PADDR_A (dispatch), 64759743Sgroudier}/*-------------------------< COMPLETE >-------------------------*/,{ 64859743Sgroudier /* 64959743Sgroudier * Complete message. 65059743Sgroudier * 65159743Sgroudier * Copy the data pointer to LASTP. 65259743Sgroudier */ 65359743Sgroudier SCR_COPY (4), 65459743Sgroudier RADDR_1 (temp), 65559743Sgroudier HADDR_1 (ccb_head.lastp), 65659743Sgroudier /* 65759743Sgroudier * When we terminate the cycle by clearing ACK, 65859743Sgroudier * the target may disconnect immediately. 65959743Sgroudier * 66059743Sgroudier * We don't want to be told of an "unexpected disconnect", 66159743Sgroudier * so we disable this feature. 66259743Sgroudier */ 66359743Sgroudier SCR_REG_REG (scntl2, SCR_AND, 0x7f), 66459743Sgroudier 0, 66559743Sgroudier /* 66659743Sgroudier * Terminate cycle ... 66759743Sgroudier */ 66859743Sgroudier SCR_CLR (SCR_ACK|SCR_ATN), 66959743Sgroudier 0, 67059743Sgroudier /* 67159743Sgroudier * ... and wait for the disconnect. 67259743Sgroudier */ 67359743Sgroudier SCR_WAIT_DISC, 67459743Sgroudier 0, 67559743Sgroudier}/*-------------------------< COMPLETE2 >------------------------*/,{ 67659743Sgroudier /* 67759743Sgroudier * Save host status. 67859743Sgroudier */ 67959743Sgroudier SCR_COPY (4), 68059743Sgroudier RADDR_1 (scr0), 68159743Sgroudier HADDR_1 (ccb_head.status), 68259743Sgroudier /* 68359743Sgroudier * Move back the CCB header using self-modifying 68459743Sgroudier * SCRIPTS. 68559743Sgroudier */ 68659743Sgroudier SCR_COPY (4), 68759743Sgroudier RADDR_1 (dsa), 68859743Sgroudier PADDR_A (_sms_a40), 68959743Sgroudier SCR_COPY (sizeof(struct sym_ccbh)), 69059743Sgroudier HADDR_1 (ccb_head), 69159743Sgroudier}/*-------------------------< _SMS_A40 >-------------------------*/,{ 69259743Sgroudier 0, 69359743Sgroudier /* 69459743Sgroudier * Some bridges may reorder DMA writes to memory. 69559743Sgroudier * We donnot want the CPU to deal with completions 69659743Sgroudier * without all the posted write having been flushed 69759743Sgroudier * to memory. This DUMMY READ should flush posted 69859743Sgroudier * buffers prior to the CPU having to deal with 69959743Sgroudier * completions. 70059743Sgroudier */ 70159743Sgroudier SCR_COPY (4), /* DUMMY READ */ 70259743Sgroudier HADDR_1 (ccb_head.status), 70359743Sgroudier RADDR_1 (scr0), 70459743Sgroudier /* 70559743Sgroudier * If command resulted in not GOOD status, 70659743Sgroudier * call the C code if needed. 70759743Sgroudier */ 70859743Sgroudier SCR_FROM_REG (SS_REG), 70959743Sgroudier 0, 71059743Sgroudier SCR_CALL ^ IFFALSE (DATA (S_GOOD)), 71159743Sgroudier PADDR_B (bad_status), 71259743Sgroudier /* 71359743Sgroudier * If we performed an auto-sense, call 71459743Sgroudier * the C code to synchronyze task aborts 71559743Sgroudier * with UNIT ATTENTION conditions. 71659743Sgroudier */ 71759743Sgroudier SCR_FROM_REG (HF_REG), 71859743Sgroudier 0, 71959743Sgroudier SCR_JUMP ^ IFTRUE (MASK (0 ,(HF_SENSE|HF_EXT_ERR))), 72059743Sgroudier PADDR_A (done), 72159743Sgroudier}/*-------------------------< COMPLETE_ERROR >-------------------*/,{ 72259743Sgroudier SCR_COPY (4), 72359743Sgroudier PADDR_B (startpos), 72459743Sgroudier RADDR_1 (scratcha), 72559743Sgroudier SCR_INT, 72659743Sgroudier SIR_COMPLETE_ERROR, 72759743Sgroudier}/*-------------------------< DONE >-----------------------------*/,{ 72859743Sgroudier /* 72959743Sgroudier * Copy the DSA to the DONE QUEUE and 73059743Sgroudier * signal completion to the host. 73159743Sgroudier * If we are interrupted between DONE 73259743Sgroudier * and DONE_END, we must reset, otherwise 73359743Sgroudier * the completed CCB may be lost. 73459743Sgroudier */ 73559743Sgroudier SCR_COPY (4), 73659743Sgroudier PADDR_B (done_pos), 73759743Sgroudier PADDR_A (_sms_a50), 73859743Sgroudier SCR_COPY (4), 73959743Sgroudier RADDR_1 (dsa), 74059743Sgroudier}/*-------------------------< _SMS_A50 >-------------------------*/,{ 74159743Sgroudier 0, 74259743Sgroudier SCR_COPY (4), 74359743Sgroudier PADDR_B (done_pos), 74459743Sgroudier PADDR_A (_sms_a60), 74559743Sgroudier /* 74659743Sgroudier * The instruction below reads the DONE QUEUE next 74759743Sgroudier * free position from memory. 74859743Sgroudier * In addition it ensures that all PCI posted writes 74959743Sgroudier * are flushed and so the DSA value of the done 75059743Sgroudier * CCB is visible by the CPU before INTFLY is raised. 75159743Sgroudier */ 75259743Sgroudier SCR_COPY (8), 75359743Sgroudier}/*-------------------------< _SMS_A60 >-------------------------*/,{ 75459743Sgroudier 0, 75559743Sgroudier PADDR_B (prev_done), 75659743Sgroudier}/*-------------------------< DONE_END >-------------------------*/,{ 75759743Sgroudier SCR_INT_FLY, 75859743Sgroudier 0, 75959743Sgroudier SCR_JUMP, 76059743Sgroudier PADDR_A (start), 76159743Sgroudier}/*-------------------------< SAVE_DP >--------------------------*/,{ 76259743Sgroudier /* 76359743Sgroudier * Clear ACK immediately. 76459743Sgroudier * No need to delay it. 76559743Sgroudier */ 76659743Sgroudier SCR_CLR (SCR_ACK), 76759743Sgroudier 0, 76859743Sgroudier /* 76959743Sgroudier * Keep track we received a SAVE DP, so 77059743Sgroudier * we will switch to the other PM context 77159743Sgroudier * on the next PM since the DP may point 77259743Sgroudier * to the current PM context. 77359743Sgroudier */ 77459743Sgroudier SCR_REG_REG (HF_REG, SCR_OR, HF_DP_SAVED), 77559743Sgroudier 0, 77659743Sgroudier /* 77759743Sgroudier * SAVE_DP message: 77859743Sgroudier * Copy the data pointer to SAVEP. 77959743Sgroudier */ 78059743Sgroudier SCR_COPY (4), 78159743Sgroudier RADDR_1 (temp), 78259743Sgroudier HADDR_1 (ccb_head.savep), 78359743Sgroudier SCR_JUMP, 78459743Sgroudier PADDR_A (dispatch), 78559743Sgroudier}/*-------------------------< RESTORE_DP >-----------------------*/,{ 78659743Sgroudier /* 78759743Sgroudier * RESTORE_DP message: 78859743Sgroudier * Copy SAVEP to actual data pointer. 78959743Sgroudier */ 79059743Sgroudier SCR_COPY (4), 79159743Sgroudier HADDR_1 (ccb_head.savep), 79259743Sgroudier RADDR_1 (temp), 79359743Sgroudier SCR_JUMP, 79459743Sgroudier PADDR_A (clrack), 79559743Sgroudier}/*-------------------------< DISCONNECT >-----------------------*/,{ 79659743Sgroudier /* 79759743Sgroudier * DISCONNECTing ... 79859743Sgroudier * 79959743Sgroudier * disable the "unexpected disconnect" feature, 80059743Sgroudier * and remove the ACK signal. 80159743Sgroudier */ 80259743Sgroudier SCR_REG_REG (scntl2, SCR_AND, 0x7f), 80359743Sgroudier 0, 80459743Sgroudier SCR_CLR (SCR_ACK|SCR_ATN), 80559743Sgroudier 0, 80659743Sgroudier /* 80759743Sgroudier * Wait for the disconnect. 80859743Sgroudier */ 80959743Sgroudier SCR_WAIT_DISC, 81059743Sgroudier 0, 81159743Sgroudier /* 81259743Sgroudier * Status is: DISCONNECTED. 81359743Sgroudier */ 81459743Sgroudier SCR_LOAD_REG (HS_REG, HS_DISCONNECT), 81559743Sgroudier 0, 81659743Sgroudier /* 81759743Sgroudier * Save host status. 81859743Sgroudier */ 81959743Sgroudier SCR_COPY (4), 82059743Sgroudier RADDR_1 (scr0), 82159743Sgroudier HADDR_1 (ccb_head.status), 82259743Sgroudier /* 82359743Sgroudier * If QUIRK_AUTOSAVE is set, 824108470Sschweikh * do a "save pointer" operation. 82559743Sgroudier */ 82659743Sgroudier SCR_FROM_REG (QU_REG), 82759743Sgroudier 0, 82859743Sgroudier SCR_JUMP ^ IFFALSE (MASK (SYM_QUIRK_AUTOSAVE, SYM_QUIRK_AUTOSAVE)), 82959743Sgroudier PADDR_A (disconnect2), 83059743Sgroudier /* 83159743Sgroudier * like SAVE_DP message: 83259743Sgroudier * Remember we saved the data pointer. 83359743Sgroudier * Copy data pointer to SAVEP. 83459743Sgroudier */ 83559743Sgroudier SCR_REG_REG (HF_REG, SCR_OR, HF_DP_SAVED), 83659743Sgroudier 0, 83759743Sgroudier SCR_COPY (4), 83859743Sgroudier RADDR_1 (temp), 83959743Sgroudier HADDR_1 (ccb_head.savep), 84059743Sgroudier}/*-------------------------< DISCONNECT2 >----------------------*/,{ 84159743Sgroudier /* 84259743Sgroudier * Move back the CCB header using self-modifying 84359743Sgroudier * SCRIPTS. 84459743Sgroudier */ 84559743Sgroudier SCR_COPY (4), 84659743Sgroudier RADDR_1 (dsa), 84759743Sgroudier PADDR_A (_sms_a65), 84859743Sgroudier SCR_COPY (sizeof(struct sym_ccbh)), 84959743Sgroudier HADDR_1 (ccb_head), 85059743Sgroudier}/*-------------------------< _SMS_A65 >-------------------------*/,{ 85159743Sgroudier 0, 85259743Sgroudier SCR_JUMP, 85359743Sgroudier PADDR_A (start), 85459743Sgroudier}/*-------------------------< IDLE >-----------------------------*/,{ 85559743Sgroudier /* 85659743Sgroudier * Nothing to do? 85759743Sgroudier * Switch the LED off and wait for reselect. 85859743Sgroudier * Will be patched with a NO_OP if LED 85959743Sgroudier * not needed or not desired. 86059743Sgroudier */ 86159743Sgroudier SCR_REG_REG (gpreg, SCR_OR, 0x01), 86259743Sgroudier 0, 86359743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT 86459743Sgroudier SCR_JUMPR, 86559743Sgroudier 8, 86659743Sgroudier#endif 86759743Sgroudier}/*-------------------------< UNGETJOB >-------------------------*/,{ 86859743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT 86959743Sgroudier /* 87059743Sgroudier * Set IMMEDIATE ARBITRATION, for the next time. 87159743Sgroudier * This will give us better chance to win arbitration 87259743Sgroudier * for the job we just wanted to do. 87359743Sgroudier */ 87459743Sgroudier SCR_REG_REG (scntl1, SCR_OR, IARB), 87559743Sgroudier 0, 87659743Sgroudier#endif 87759743Sgroudier /* 87859743Sgroudier * We are not able to restart the SCRIPTS if we are 87959743Sgroudier * interrupted and these instruction haven't been 88059743Sgroudier * all executed. BTW, this is very unlikely to 88159743Sgroudier * happen, but we check that from the C code. 88259743Sgroudier */ 88359743Sgroudier SCR_LOAD_REG (dsa, 0xff), 88459743Sgroudier 0, 88559743Sgroudier SCR_COPY (4), 88659743Sgroudier RADDR_1 (scratcha), 88759743Sgroudier PADDR_B (startpos), 88859743Sgroudier}/*-------------------------< RESELECT >-------------------------*/,{ 88959743Sgroudier /* 89059743Sgroudier * Make sure we are in initiator mode. 89159743Sgroudier */ 89259743Sgroudier SCR_CLR (SCR_TRG), 89359743Sgroudier 0, 89459743Sgroudier /* 89559743Sgroudier * Sleep waiting for a reselection. 89659743Sgroudier */ 89759743Sgroudier SCR_WAIT_RESEL, 89859743Sgroudier PADDR_A(start), 89959743Sgroudier}/*-------------------------< RESELECTED >-----------------------*/,{ 90059743Sgroudier /* 90159743Sgroudier * Switch the LED on. 90259743Sgroudier * Will be patched with a NO_OP if LED 90359743Sgroudier * not needed or not desired. 90459743Sgroudier */ 90559743Sgroudier SCR_REG_REG (gpreg, SCR_AND, 0xfe), 90659743Sgroudier 0, 90759743Sgroudier /* 90859743Sgroudier * load the target id into the sdid 90959743Sgroudier */ 91059743Sgroudier SCR_REG_SFBR (ssid, SCR_AND, 0x8F), 91159743Sgroudier 0, 91259743Sgroudier SCR_TO_REG (sdid), 91359743Sgroudier 0, 91459743Sgroudier /* 91559743Sgroudier * Load the target control block address 91659743Sgroudier */ 91759743Sgroudier SCR_COPY (4), 91859743Sgroudier PADDR_B (targtbl), 91959743Sgroudier RADDR_1 (dsa), 92059743Sgroudier SCR_SFBR_REG (dsa, SCR_SHL, 0), 92159743Sgroudier 0, 92259743Sgroudier SCR_REG_REG (dsa, SCR_SHL, 0), 92359743Sgroudier 0, 92459743Sgroudier SCR_REG_REG (dsa, SCR_AND, 0x3c), 92559743Sgroudier 0, 92659743Sgroudier SCR_COPY (4), 92759743Sgroudier RADDR_1 (dsa), 92859743Sgroudier PADDR_A (_sms_a70), 92959743Sgroudier SCR_COPY (4), 93059743Sgroudier}/*-------------------------< _SMS_A70 >-------------------------*/,{ 93159743Sgroudier 0, 93259743Sgroudier RADDR_1 (dsa), 93359743Sgroudier /* 93459743Sgroudier * Copy the TCB header to a fixed place in 93559743Sgroudier * the HCB. 93659743Sgroudier */ 93759743Sgroudier SCR_COPY (4), 93859743Sgroudier RADDR_1 (dsa), 93959743Sgroudier PADDR_A (_sms_a80), 94059743Sgroudier SCR_COPY (sizeof(struct sym_tcbh)), 94159743Sgroudier}/*-------------------------< _SMS_A80 >-------------------------*/,{ 94259743Sgroudier 0, 94359743Sgroudier HADDR_1 (tcb_head), 94459743Sgroudier /* 94559743Sgroudier * We expect MESSAGE IN phase. 94659743Sgroudier * If not, get help from the C code. 94759743Sgroudier */ 94859743Sgroudier SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)), 94959743Sgroudier SIR_RESEL_NO_MSG_IN, 95059743Sgroudier}/*-------------------------< RESELECTED1 >----------------------*/,{ 95159743Sgroudier /* 95259743Sgroudier * Load the synchronous transfer registers. 95359743Sgroudier */ 95459743Sgroudier SCR_COPY (1), 95559743Sgroudier HADDR_1 (tcb_head.wval), 95659743Sgroudier RADDR_1 (scntl3), 95759743Sgroudier SCR_COPY (1), 95859743Sgroudier HADDR_1 (tcb_head.sval), 95959743Sgroudier RADDR_1 (sxfer), 96059743Sgroudier /* 96159743Sgroudier * Get the IDENTIFY message. 96259743Sgroudier */ 96359743Sgroudier SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 96459743Sgroudier HADDR_1 (msgin), 96559743Sgroudier /* 96659743Sgroudier * If IDENTIFY LUN #0, use a faster path 96759743Sgroudier * to find the LCB structure. 96859743Sgroudier */ 96959743Sgroudier SCR_JUMP ^ IFTRUE (MASK (0x80, 0xbf)), 97059743Sgroudier PADDR_A (resel_lun0), 97159743Sgroudier /* 97259743Sgroudier * If message isn't an IDENTIFY, 97359743Sgroudier * tell the C code about. 97459743Sgroudier */ 97559743Sgroudier SCR_INT ^ IFFALSE (MASK (0x80, 0x80)), 97659743Sgroudier SIR_RESEL_NO_IDENTIFY, 97759743Sgroudier /* 97859743Sgroudier * It is an IDENTIFY message, 97959743Sgroudier * Load the LUN control block address. 98059743Sgroudier */ 98159743Sgroudier SCR_COPY (4), 98259743Sgroudier HADDR_1 (tcb_head.luntbl_sa), 98359743Sgroudier RADDR_1 (dsa), 98459743Sgroudier SCR_SFBR_REG (dsa, SCR_SHL, 0), 98559743Sgroudier 0, 98659743Sgroudier SCR_REG_REG (dsa, SCR_SHL, 0), 98759743Sgroudier 0, 98859743Sgroudier SCR_REG_REG (dsa, SCR_AND, 0xfc), 98959743Sgroudier 0, 99059743Sgroudier SCR_COPY (4), 99159743Sgroudier RADDR_1 (dsa), 99259743Sgroudier PADDR_A (_sms_a90), 99359743Sgroudier SCR_COPY (4), 99459743Sgroudier}/*-------------------------< _SMS_A90 >-------------------------*/,{ 99559743Sgroudier 0, 99659743Sgroudier RADDR_1 (dsa), 99759743Sgroudier SCR_JUMPR, 99859743Sgroudier 12, 99959743Sgroudier}/*-------------------------< RESEL_LUN0 >-----------------------*/,{ 100059743Sgroudier /* 100159743Sgroudier * LUN 0 special case (but usual one :)) 100259743Sgroudier */ 100359743Sgroudier SCR_COPY (4), 100459743Sgroudier HADDR_1 (tcb_head.lun0_sa), 100559743Sgroudier RADDR_1 (dsa), 100659743Sgroudier /* 100759743Sgroudier * Jump indirectly to the reselect action for this LUN. 100859743Sgroudier * (lcb.head.resel_sa assumed at offset zero of lcb). 100959743Sgroudier */ 101059743Sgroudier SCR_COPY (4), 101159743Sgroudier RADDR_1 (dsa), 101259743Sgroudier PADDR_A (_sms_a100), 101359743Sgroudier SCR_COPY (4), 101459743Sgroudier}/*-------------------------< _SMS_A100 >------------------------*/,{ 101559743Sgroudier 0, 101659743Sgroudier RADDR_1 (temp), 101759743Sgroudier SCR_RETURN, 101859743Sgroudier 0, 101959743Sgroudier /* In normal situations, we jump to RESEL_TAG or RESEL_NO_TAG */ 102059743Sgroudier}/*-------------------------< RESEL_TAG >------------------------*/,{ 102159743Sgroudier /* 102260134Sgroudier * ACK the IDENTIFY previously received. 102359743Sgroudier */ 102459743Sgroudier SCR_CLR (SCR_ACK), 102559743Sgroudier 0, 102659743Sgroudier /* 102759743Sgroudier * It shall be a tagged command. 102859743Sgroudier * Read SIMPLE+TAG. 102959743Sgroudier * The C code will deal with errors. 1030220950Smarius * Aggressive optimization, isn't it? :) 103159743Sgroudier */ 103259743Sgroudier SCR_MOVE_ABS (2) ^ SCR_MSG_IN, 103359743Sgroudier HADDR_1 (msgin), 103459743Sgroudier /* 103559743Sgroudier * Copy the LCB header to a fixed place in 103659743Sgroudier * the HCB using self-modifying SCRIPTS. 103759743Sgroudier */ 103859743Sgroudier SCR_COPY (4), 103959743Sgroudier RADDR_1 (dsa), 104059743Sgroudier PADDR_A (_sms_a110), 104159743Sgroudier SCR_COPY (sizeof(struct sym_lcbh)), 104259743Sgroudier}/*-------------------------< _SMS_A110 >------------------------*/,{ 104359743Sgroudier 0, 104459743Sgroudier HADDR_1 (lcb_head), 104559743Sgroudier /* 104659743Sgroudier * Load the pointer to the tagged task 104759743Sgroudier * table for this LUN. 104859743Sgroudier */ 104959743Sgroudier SCR_COPY (4), 105059743Sgroudier HADDR_1 (lcb_head.itlq_tbl_sa), 105159743Sgroudier RADDR_1 (dsa), 105259743Sgroudier /* 105359743Sgroudier * The SIDL still contains the TAG value. 1054220944Smarius * Aggressive optimization, isn't it? :):) 105559743Sgroudier */ 105659743Sgroudier SCR_REG_SFBR (sidl, SCR_SHL, 0), 105759743Sgroudier 0, 105859743Sgroudier#if SYM_CONF_MAX_TASK*4 > 512 105959743Sgroudier SCR_JUMPR ^ IFFALSE (CARRYSET), 106059743Sgroudier 8, 106159743Sgroudier SCR_REG_REG (dsa1, SCR_OR, 2), 106259743Sgroudier 0, 106359743Sgroudier SCR_REG_REG (sfbr, SCR_SHL, 0), 106459743Sgroudier 0, 106559743Sgroudier SCR_JUMPR ^ IFFALSE (CARRYSET), 106659743Sgroudier 8, 106759743Sgroudier SCR_REG_REG (dsa1, SCR_OR, 1), 106859743Sgroudier 0, 106959743Sgroudier#elif SYM_CONF_MAX_TASK*4 > 256 107059743Sgroudier SCR_JUMPR ^ IFFALSE (CARRYSET), 107159743Sgroudier 8, 107259743Sgroudier SCR_REG_REG (dsa1, SCR_OR, 1), 107359743Sgroudier 0, 107459743Sgroudier#endif 107559743Sgroudier /* 107659743Sgroudier * Retrieve the DSA of this task. 107759743Sgroudier * JUMP indirectly to the restart point of the CCB. 107859743Sgroudier */ 107959743Sgroudier SCR_SFBR_REG (dsa, SCR_AND, 0xfc), 108059743Sgroudier 0, 108159743Sgroudier SCR_COPY (4), 108259743Sgroudier RADDR_1 (dsa), 108359743Sgroudier PADDR_A (_sms_a120), 108459743Sgroudier SCR_COPY (4), 108559743Sgroudier}/*-------------------------< _SMS_A120 >------------------------*/,{ 108659743Sgroudier 0, 108759743Sgroudier RADDR_1 (dsa), 108859743Sgroudier}/*-------------------------< RESEL_GO >-------------------------*/,{ 108959743Sgroudier SCR_COPY (4), 109059743Sgroudier RADDR_1 (dsa), 109159743Sgroudier PADDR_A (_sms_a130), 109259743Sgroudier /* 109359743Sgroudier * Move 'ccb.phys.head.go' action to 109459743Sgroudier * scratch/scratch1. So scratch1 will 109559743Sgroudier * contain the 'restart' field of the 109659743Sgroudier * 'go' structure. 109759743Sgroudier */ 109859743Sgroudier SCR_COPY (8), 109959743Sgroudier}/*-------------------------< _SMS_A130 >------------------------*/,{ 110059743Sgroudier 0, 110159743Sgroudier PADDR_B (scratch), 110259743Sgroudier SCR_COPY (4), 110359743Sgroudier PADDR_B (scratch1), /* phys.head.go.restart */ 110459743Sgroudier RADDR_1 (temp), 110559743Sgroudier SCR_RETURN, 110659743Sgroudier 0, 110759743Sgroudier /* In normal situations we branch to RESEL_DSA */ 110859743Sgroudier}/*-------------------------< RESEL_DSA >------------------------*/,{ 110959743Sgroudier /* 111059743Sgroudier * ACK the IDENTIFY or TAG previously received. 111159743Sgroudier */ 111259743Sgroudier SCR_CLR (SCR_ACK), 111359743Sgroudier 0, 111459743Sgroudier}/*-------------------------< RESEL_DSA1 >-----------------------*/,{ 111559743Sgroudier /* 111659743Sgroudier * Copy the CCB header to a fixed location 111759743Sgroudier * in the HCB using self-modifying SCRIPTS. 111859743Sgroudier */ 111959743Sgroudier SCR_COPY (4), 112059743Sgroudier RADDR_1 (dsa), 112159743Sgroudier PADDR_A (_sms_a140), 112259743Sgroudier SCR_COPY (sizeof(struct sym_ccbh)), 112359743Sgroudier}/*-------------------------< _SMS_A140 >------------------------*/,{ 112459743Sgroudier 0, 112559743Sgroudier HADDR_1 (ccb_head), 112659743Sgroudier /* 112759743Sgroudier * Load the savep (saved data pointer) into 112859743Sgroudier * the actual data pointer. 112959743Sgroudier */ 113059743Sgroudier SCR_COPY (4), 113159743Sgroudier HADDR_1 (ccb_head.savep), 113259743Sgroudier RADDR_1 (temp), 113359743Sgroudier /* 113459743Sgroudier * Initialize the status register 113559743Sgroudier */ 113659743Sgroudier SCR_COPY (4), 113759743Sgroudier HADDR_1 (ccb_head.status), 113859743Sgroudier RADDR_1 (scr0), 113959743Sgroudier /* 114059743Sgroudier * Jump to dispatcher. 114159743Sgroudier */ 114259743Sgroudier SCR_JUMP, 114359743Sgroudier PADDR_A (dispatch), 114459743Sgroudier}/*-------------------------< RESEL_NO_TAG >---------------------*/,{ 114559743Sgroudier /* 114659743Sgroudier * Copy the LCB header to a fixed place in 114759743Sgroudier * the HCB using self-modifying SCRIPTS. 114859743Sgroudier */ 114959743Sgroudier SCR_COPY (4), 115059743Sgroudier RADDR_1 (dsa), 115159743Sgroudier PADDR_A (_sms_a145), 115259743Sgroudier SCR_COPY (sizeof(struct sym_lcbh)), 115359743Sgroudier}/*-------------------------< _SMS_A145 >------------------------*/,{ 115459743Sgroudier 0, 115559743Sgroudier HADDR_1 (lcb_head), 115659743Sgroudier /* 115759743Sgroudier * Load the DSA with the unique ITL task. 115859743Sgroudier */ 115959743Sgroudier SCR_COPY (4), 116059743Sgroudier HADDR_1 (lcb_head.itl_task_sa), 116159743Sgroudier RADDR_1 (dsa), 116259743Sgroudier SCR_JUMP, 116359743Sgroudier PADDR_A (resel_go), 116459743Sgroudier}/*-------------------------< DATA_IN >--------------------------*/,{ 116559743Sgroudier/* 116659743Sgroudier * Because the size depends on the 116759743Sgroudier * #define SYM_CONF_MAX_SG parameter, 116859743Sgroudier * it is filled in at runtime. 116959743Sgroudier * 117059743Sgroudier * ##===========< i=0; i<SYM_CONF_MAX_SG >========= 117159743Sgroudier * || SCR_CHMOV_TBL ^ SCR_DATA_IN, 117259743Sgroudier * || offsetof (struct sym_dsb, data[ i]), 117359743Sgroudier * ##========================================== 117459743Sgroudier */ 117559743Sgroudier0 117659743Sgroudier}/*-------------------------< DATA_IN2 >-------------------------*/,{ 117759743Sgroudier SCR_CALL, 117859743Sgroudier PADDR_A (datai_done), 117959743Sgroudier SCR_JUMP, 118059743Sgroudier PADDR_B (data_ovrun), 118159743Sgroudier}/*-------------------------< DATA_OUT >-------------------------*/,{ 118259743Sgroudier/* 118359743Sgroudier * Because the size depends on the 118459743Sgroudier * #define SYM_CONF_MAX_SG parameter, 118559743Sgroudier * it is filled in at runtime. 118659743Sgroudier * 118759743Sgroudier * ##===========< i=0; i<SYM_CONF_MAX_SG >========= 118859743Sgroudier * || SCR_CHMOV_TBL ^ SCR_DATA_OUT, 118959743Sgroudier * || offsetof (struct sym_dsb, data[ i]), 119059743Sgroudier * ##========================================== 119159743Sgroudier */ 119259743Sgroudier0 119359743Sgroudier}/*-------------------------< DATA_OUT2 >------------------------*/,{ 119459743Sgroudier SCR_CALL, 119559743Sgroudier PADDR_A (datao_done), 119659743Sgroudier SCR_JUMP, 119759743Sgroudier PADDR_B (data_ovrun), 119859743Sgroudier}/*-------------------------< PM0_DATA >-------------------------*/,{ 119959743Sgroudier /* 120059743Sgroudier * Read our host flags to SFBR, so we will be able 120159743Sgroudier * to check against the data direction we expect. 120259743Sgroudier */ 120359743Sgroudier SCR_FROM_REG (HF_REG), 120459743Sgroudier 0, 120559743Sgroudier /* 120659743Sgroudier * Check against actual DATA PHASE. 120759743Sgroudier */ 120859743Sgroudier SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)), 120959743Sgroudier PADDR_A (pm0_data_out), 121059743Sgroudier /* 121159743Sgroudier * Actual phase is DATA IN. 121259743Sgroudier * Check against expected direction. 121359743Sgroudier */ 121459743Sgroudier SCR_JUMP ^ IFFALSE (MASK (HF_DATA_IN, HF_DATA_IN)), 121559743Sgroudier PADDR_B (data_ovrun), 121659743Sgroudier /* 121759743Sgroudier * Keep track we are moving data from the 121859743Sgroudier * PM0 DATA mini-script. 121959743Sgroudier */ 122059743Sgroudier SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM0), 122159743Sgroudier 0, 122259743Sgroudier /* 122359743Sgroudier * Move the data to memory. 122459743Sgroudier */ 122559743Sgroudier SCR_CHMOV_TBL ^ SCR_DATA_IN, 122659743Sgroudier offsetof (struct sym_ccb, phys.pm0.sg), 122759743Sgroudier SCR_JUMP, 122859743Sgroudier PADDR_A (pm0_data_end), 122959743Sgroudier}/*-------------------------< PM0_DATA_OUT >---------------------*/,{ 123059743Sgroudier /* 123159743Sgroudier * Actual phase is DATA OUT. 123259743Sgroudier * Check against expected direction. 123359743Sgroudier */ 123459743Sgroudier SCR_JUMP ^ IFTRUE (MASK (HF_DATA_IN, HF_DATA_IN)), 123559743Sgroudier PADDR_B (data_ovrun), 123659743Sgroudier /* 123759743Sgroudier * Keep track we are moving data from the 123859743Sgroudier * PM0 DATA mini-script. 123959743Sgroudier */ 124059743Sgroudier SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM0), 124159743Sgroudier 0, 124259743Sgroudier /* 124359743Sgroudier * Move the data from memory. 124459743Sgroudier */ 124559743Sgroudier SCR_CHMOV_TBL ^ SCR_DATA_OUT, 124659743Sgroudier offsetof (struct sym_ccb, phys.pm0.sg), 124759743Sgroudier}/*-------------------------< PM0_DATA_END >---------------------*/,{ 124859743Sgroudier /* 124959743Sgroudier * Clear the flag that told we were moving 125059743Sgroudier * data from the PM0 DATA mini-script. 125159743Sgroudier */ 125259743Sgroudier SCR_REG_REG (HF_REG, SCR_AND, (~HF_IN_PM0)), 125359743Sgroudier 0, 125459743Sgroudier /* 125559743Sgroudier * Return to the previous DATA script which 125659743Sgroudier * is guaranteed by design (if no bug) to be 125759743Sgroudier * the main DATA script for this transfer. 125859743Sgroudier */ 125959743Sgroudier SCR_COPY (4), 126059743Sgroudier RADDR_1 (dsa), 126159743Sgroudier RADDR_1 (scratcha), 126259743Sgroudier SCR_REG_REG (scratcha, SCR_ADD, offsetof (struct sym_ccb,phys.pm0.ret)), 126359743Sgroudier 0, 126459743Sgroudier}/*-------------------------< PM_DATA_END >----------------------*/,{ 126559743Sgroudier SCR_COPY (4), 126659743Sgroudier RADDR_1 (scratcha), 126759743Sgroudier PADDR_A (_sms_a150), 126859743Sgroudier SCR_COPY (4), 126959743Sgroudier}/*-------------------------< _SMS_A150 >------------------------*/,{ 127059743Sgroudier 0, 127159743Sgroudier RADDR_1 (temp), 127259743Sgroudier SCR_RETURN, 127359743Sgroudier 0, 127459743Sgroudier}/*-------------------------< PM1_DATA >-------------------------*/,{ 127559743Sgroudier /* 127659743Sgroudier * Read our host flags to SFBR, so we will be able 127759743Sgroudier * to check against the data direction we expect. 127859743Sgroudier */ 127959743Sgroudier SCR_FROM_REG (HF_REG), 128059743Sgroudier 0, 128159743Sgroudier /* 128259743Sgroudier * Check against actual DATA PHASE. 128359743Sgroudier */ 128459743Sgroudier SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)), 128559743Sgroudier PADDR_A (pm1_data_out), 128659743Sgroudier /* 128759743Sgroudier * Actual phase is DATA IN. 128859743Sgroudier * Check against expected direction. 128959743Sgroudier */ 129059743Sgroudier SCR_JUMP ^ IFFALSE (MASK (HF_DATA_IN, HF_DATA_IN)), 129159743Sgroudier PADDR_B (data_ovrun), 129259743Sgroudier /* 129359743Sgroudier * Keep track we are moving data from the 129459743Sgroudier * PM1 DATA mini-script. 129559743Sgroudier */ 129659743Sgroudier SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM1), 129759743Sgroudier 0, 129859743Sgroudier /* 129959743Sgroudier * Move the data to memory. 130059743Sgroudier */ 130159743Sgroudier SCR_CHMOV_TBL ^ SCR_DATA_IN, 130259743Sgroudier offsetof (struct sym_ccb, phys.pm1.sg), 130359743Sgroudier SCR_JUMP, 130459743Sgroudier PADDR_A (pm1_data_end), 130559743Sgroudier}/*-------------------------< PM1_DATA_OUT >---------------------*/,{ 130659743Sgroudier /* 130759743Sgroudier * Actual phase is DATA OUT. 130859743Sgroudier * Check against expected direction. 130959743Sgroudier */ 131059743Sgroudier SCR_JUMP ^ IFTRUE (MASK (HF_DATA_IN, HF_DATA_IN)), 131159743Sgroudier PADDR_B (data_ovrun), 131259743Sgroudier /* 131359743Sgroudier * Keep track we are moving data from the 131459743Sgroudier * PM1 DATA mini-script. 131559743Sgroudier */ 131659743Sgroudier SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM1), 131759743Sgroudier 0, 131859743Sgroudier /* 131959743Sgroudier * Move the data from memory. 132059743Sgroudier */ 132159743Sgroudier SCR_CHMOV_TBL ^ SCR_DATA_OUT, 132259743Sgroudier offsetof (struct sym_ccb, phys.pm1.sg), 132359743Sgroudier}/*-------------------------< PM1_DATA_END >---------------------*/,{ 132459743Sgroudier /* 132559743Sgroudier * Clear the flag that told we were moving 132659743Sgroudier * data from the PM1 DATA mini-script. 132759743Sgroudier */ 132859743Sgroudier SCR_REG_REG (HF_REG, SCR_AND, (~HF_IN_PM1)), 132959743Sgroudier 0, 133059743Sgroudier /* 133159743Sgroudier * Return to the previous DATA script which 133259743Sgroudier * is guaranteed by design (if no bug) to be 133359743Sgroudier * the main DATA script for this transfer. 133459743Sgroudier */ 133559743Sgroudier SCR_COPY (4), 133659743Sgroudier RADDR_1 (dsa), 133759743Sgroudier RADDR_1 (scratcha), 133859743Sgroudier SCR_REG_REG (scratcha, SCR_ADD, offsetof (struct sym_ccb,phys.pm1.ret)), 133959743Sgroudier 0, 134059743Sgroudier SCR_JUMP, 134159743Sgroudier PADDR_A (pm_data_end), 134259743Sgroudier}/*--------------------------<>----------------------------------*/ 134359743Sgroudier}; 134459743Sgroudier 1345179029Smariusstatic const struct SYM_FWB_SCR SYM_FWB_SCR = { 134659743Sgroudier/*-------------------------< NO_DATA >--------------------------*/ { 134759743Sgroudier SCR_JUMP, 134859743Sgroudier PADDR_B (data_ovrun), 134959743Sgroudier}/*-------------------------< SEL_FOR_ABORT >--------------------*/,{ 135059743Sgroudier /* 135159743Sgroudier * We are jumped here by the C code, if we have 135259743Sgroudier * some target to reset or some disconnected 135359743Sgroudier * job to abort. Since error recovery is a serious 135459743Sgroudier * busyness, we will really reset the SCSI BUS, if 1355220944Smarius * case of a SCSI interrupt occurring in this path. 135659743Sgroudier */ 135759743Sgroudier 135859743Sgroudier /* 135959743Sgroudier * Set initiator mode. 136059743Sgroudier */ 136159743Sgroudier SCR_CLR (SCR_TRG), 136259743Sgroudier 0, 136359743Sgroudier /* 136459743Sgroudier * And try to select this target. 136559743Sgroudier */ 136659743Sgroudier SCR_SEL_TBL_ATN ^ offsetof (struct sym_hcb, abrt_sel), 136759743Sgroudier PADDR_A (reselect), 136859743Sgroudier /* 136959743Sgroudier * Wait for the selection to complete or 137059743Sgroudier * the selection to time out. 137159743Sgroudier */ 137259743Sgroudier SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_OUT)), 137359743Sgroudier -8, 137459743Sgroudier /* 137559743Sgroudier * Call the C code. 137659743Sgroudier */ 137759743Sgroudier SCR_INT, 137859743Sgroudier SIR_TARGET_SELECTED, 137959743Sgroudier /* 138059743Sgroudier * The C code should let us continue here. 138159743Sgroudier * Send the 'kiss of death' message. 138259743Sgroudier * We expect an immediate disconnect once 138359743Sgroudier * the target has eaten the message. 138459743Sgroudier */ 138559743Sgroudier SCR_REG_REG (scntl2, SCR_AND, 0x7f), 138659743Sgroudier 0, 138759743Sgroudier SCR_MOVE_TBL ^ SCR_MSG_OUT, 138859743Sgroudier offsetof (struct sym_hcb, abrt_tbl), 138959743Sgroudier SCR_CLR (SCR_ACK|SCR_ATN), 139059743Sgroudier 0, 139159743Sgroudier SCR_WAIT_DISC, 139259743Sgroudier 0, 139359743Sgroudier /* 139459743Sgroudier * Tell the C code that we are done. 139559743Sgroudier */ 139659743Sgroudier SCR_INT, 139759743Sgroudier SIR_ABORT_SENT, 139859743Sgroudier}/*-------------------------< SEL_FOR_ABORT_1 >------------------*/,{ 139959743Sgroudier /* 140059743Sgroudier * Jump at scheduler. 140159743Sgroudier */ 140259743Sgroudier SCR_JUMP, 140359743Sgroudier PADDR_A (start), 140459743Sgroudier}/*-------------------------< MSG_IN_ETC >-----------------------*/,{ 140559743Sgroudier /* 140659743Sgroudier * If it is an EXTENDED (variable size message) 140759743Sgroudier * Handle it. 140859743Sgroudier */ 140959743Sgroudier SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)), 141059743Sgroudier PADDR_B (msg_extended), 141159743Sgroudier /* 141259743Sgroudier * Let the C code handle any other 141359743Sgroudier * 1 byte message. 141459743Sgroudier */ 141559743Sgroudier SCR_JUMP ^ IFTRUE (MASK (0x00, 0xf0)), 141659743Sgroudier PADDR_B (msg_received), 141759743Sgroudier SCR_JUMP ^ IFTRUE (MASK (0x10, 0xf0)), 141859743Sgroudier PADDR_B (msg_received), 141959743Sgroudier /* 142059743Sgroudier * We donnot handle 2 bytes messages from SCRIPTS. 142159743Sgroudier * So, let the C code deal with these ones too. 142259743Sgroudier */ 142362134Sgroudier SCR_JUMP ^ IFFALSE (MASK (0x20, 0xf0)), 142462134Sgroudier PADDR_B (msg_weird_seen), 142559743Sgroudier SCR_CLR (SCR_ACK), 142659743Sgroudier 0, 142759743Sgroudier SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 142859743Sgroudier HADDR_1 (msgin[1]), 142959743Sgroudier}/*-------------------------< MSG_RECEIVED >---------------------*/,{ 143059743Sgroudier SCR_COPY (4), /* DUMMY READ */ 143159743Sgroudier HADDR_1 (cache), 143259743Sgroudier RADDR_1 (scratcha), 143359743Sgroudier SCR_INT, 143459743Sgroudier SIR_MSG_RECEIVED, 143559743Sgroudier}/*-------------------------< MSG_WEIRD_SEEN >-------------------*/,{ 143659743Sgroudier SCR_COPY (4), /* DUMMY READ */ 143759743Sgroudier HADDR_1 (cache), 143859743Sgroudier RADDR_1 (scratcha), 143959743Sgroudier SCR_INT, 144059743Sgroudier SIR_MSG_WEIRD, 144159743Sgroudier}/*-------------------------< MSG_EXTENDED >---------------------*/,{ 144259743Sgroudier /* 144359743Sgroudier * Clear ACK and get the next byte 144459743Sgroudier * assumed to be the message length. 144559743Sgroudier */ 144659743Sgroudier SCR_CLR (SCR_ACK), 144759743Sgroudier 0, 144859743Sgroudier SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 144959743Sgroudier HADDR_1 (msgin[1]), 145059743Sgroudier /* 145159743Sgroudier * Try to catch some unlikely situations as 0 length 145259743Sgroudier * or too large the length. 145359743Sgroudier */ 145459743Sgroudier SCR_JUMP ^ IFTRUE (DATA (0)), 145559743Sgroudier PADDR_B (msg_weird_seen), 145659743Sgroudier SCR_TO_REG (scratcha), 145759743Sgroudier 0, 145859743Sgroudier SCR_REG_REG (sfbr, SCR_ADD, (256-8)), 145959743Sgroudier 0, 146059743Sgroudier SCR_JUMP ^ IFTRUE (CARRYSET), 146159743Sgroudier PADDR_B (msg_weird_seen), 146259743Sgroudier /* 146359743Sgroudier * We donnot handle extended messages from SCRIPTS. 1464220944Smarius * Read the amount of data corresponding to the 146559743Sgroudier * message length and call the C code. 146659743Sgroudier */ 146759743Sgroudier SCR_COPY (1), 146859743Sgroudier RADDR_1 (scratcha), 146959743Sgroudier PADDR_B (_sms_b10), 147059743Sgroudier SCR_CLR (SCR_ACK), 147159743Sgroudier 0, 147259743Sgroudier}/*-------------------------< _SMS_B10 >-------------------------*/,{ 147359743Sgroudier SCR_MOVE_ABS (0) ^ SCR_MSG_IN, 147459743Sgroudier HADDR_1 (msgin[2]), 147559743Sgroudier SCR_JUMP, 147659743Sgroudier PADDR_B (msg_received), 147759743Sgroudier}/*-------------------------< MSG_BAD >--------------------------*/,{ 147859743Sgroudier /* 147959743Sgroudier * unimplemented message - reject it. 148059743Sgroudier */ 148159743Sgroudier SCR_INT, 148259743Sgroudier SIR_REJECT_TO_SEND, 148359743Sgroudier SCR_SET (SCR_ATN), 148459743Sgroudier 0, 148559743Sgroudier SCR_JUMP, 148659743Sgroudier PADDR_A (clrack), 148759743Sgroudier}/*-------------------------< MSG_WEIRD >------------------------*/,{ 148859743Sgroudier /* 148959743Sgroudier * weird message received 149059743Sgroudier * ignore all MSG IN phases and reject it. 149159743Sgroudier */ 149259743Sgroudier SCR_INT, 149359743Sgroudier SIR_REJECT_TO_SEND, 149459743Sgroudier SCR_SET (SCR_ATN), 149559743Sgroudier 0, 149659743Sgroudier}/*-------------------------< MSG_WEIRD1 >-----------------------*/,{ 149759743Sgroudier SCR_CLR (SCR_ACK), 149859743Sgroudier 0, 149959743Sgroudier SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), 150059743Sgroudier PADDR_A (dispatch), 150159743Sgroudier SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 150259743Sgroudier HADDR_1 (scratch), 150359743Sgroudier SCR_JUMP, 150459743Sgroudier PADDR_B (msg_weird1), 150559743Sgroudier}/*-------------------------< WDTR_RESP >------------------------*/,{ 150659743Sgroudier /* 150759743Sgroudier * let the target fetch our answer. 150859743Sgroudier */ 150959743Sgroudier SCR_SET (SCR_ATN), 151059743Sgroudier 0, 151159743Sgroudier SCR_CLR (SCR_ACK), 151259743Sgroudier 0, 151359743Sgroudier SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)), 151459743Sgroudier PADDR_B (nego_bad_phase), 151559743Sgroudier}/*-------------------------< SEND_WDTR >------------------------*/,{ 151659743Sgroudier /* 151759743Sgroudier * Send the M_X_WIDE_REQ 151859743Sgroudier */ 151959743Sgroudier SCR_MOVE_ABS (4) ^ SCR_MSG_OUT, 152059743Sgroudier HADDR_1 (msgout), 152159743Sgroudier SCR_JUMP, 152259743Sgroudier PADDR_B (msg_out_done), 152359743Sgroudier}/*-------------------------< SDTR_RESP >------------------------*/,{ 152459743Sgroudier /* 152559743Sgroudier * let the target fetch our answer. 152659743Sgroudier */ 152759743Sgroudier SCR_SET (SCR_ATN), 152859743Sgroudier 0, 152959743Sgroudier SCR_CLR (SCR_ACK), 153059743Sgroudier 0, 153159743Sgroudier SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)), 153259743Sgroudier PADDR_B (nego_bad_phase), 153359743Sgroudier}/*-------------------------< SEND_SDTR >------------------------*/,{ 153459743Sgroudier /* 153559743Sgroudier * Send the M_X_SYNC_REQ 153659743Sgroudier */ 153759743Sgroudier SCR_MOVE_ABS (5) ^ SCR_MSG_OUT, 153859743Sgroudier HADDR_1 (msgout), 153959743Sgroudier SCR_JUMP, 154059743Sgroudier PADDR_B (msg_out_done), 154159743Sgroudier}/*-------------------------< PPR_RESP >-------------------------*/,{ 154259743Sgroudier /* 154359743Sgroudier * let the target fetch our answer. 154459743Sgroudier */ 154559743Sgroudier SCR_SET (SCR_ATN), 154659743Sgroudier 0, 154759743Sgroudier SCR_CLR (SCR_ACK), 154859743Sgroudier 0, 154959743Sgroudier SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)), 155059743Sgroudier PADDR_B (nego_bad_phase), 155159743Sgroudier}/*-------------------------< SEND_PPR >-------------------------*/,{ 155259743Sgroudier /* 155359743Sgroudier * Send the M_X_PPR_REQ 155459743Sgroudier */ 155559743Sgroudier SCR_MOVE_ABS (8) ^ SCR_MSG_OUT, 155659743Sgroudier HADDR_1 (msgout), 155759743Sgroudier SCR_JUMP, 155859743Sgroudier PADDR_B (msg_out_done), 155959743Sgroudier}/*-------------------------< NEGO_BAD_PHASE >-------------------*/,{ 156059743Sgroudier SCR_INT, 156159743Sgroudier SIR_NEGO_PROTO, 156259743Sgroudier SCR_JUMP, 156359743Sgroudier PADDR_A (dispatch), 156459743Sgroudier}/*-------------------------< MSG_OUT >--------------------------*/,{ 156559743Sgroudier /* 156659743Sgroudier * The target requests a message. 156759743Sgroudier * We donnot send messages that may 156859743Sgroudier * require the device to go to bus free. 156959743Sgroudier */ 157059743Sgroudier SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, 157159743Sgroudier HADDR_1 (msgout), 157259743Sgroudier /* 157359743Sgroudier * ... wait for the next phase 157459743Sgroudier * if it's a message out, send it again, ... 157559743Sgroudier */ 157659743Sgroudier SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)), 157759743Sgroudier PADDR_B (msg_out), 157859743Sgroudier}/*-------------------------< MSG_OUT_DONE >---------------------*/,{ 157959743Sgroudier /* 158059743Sgroudier * Let the C code be aware of the 158159743Sgroudier * sent message and clear the message. 158259743Sgroudier */ 158359743Sgroudier SCR_INT, 158459743Sgroudier SIR_MSG_OUT_DONE, 158559743Sgroudier /* 158659743Sgroudier * ... and process the next phase 158759743Sgroudier */ 158859743Sgroudier SCR_JUMP, 158959743Sgroudier PADDR_A (dispatch), 159059743Sgroudier}/*-------------------------< DATA_OVRUN >-----------------------*/,{ 159159743Sgroudier /* 159259743Sgroudier * Zero scratcha that will count the 159359743Sgroudier * extras bytes. 159459743Sgroudier */ 159559743Sgroudier SCR_COPY (4), 159659743Sgroudier PADDR_B (zero), 159759743Sgroudier RADDR_1 (scratcha), 159859743Sgroudier}/*-------------------------< DATA_OVRUN1 >----------------------*/,{ 159959743Sgroudier /* 160059743Sgroudier * The target may want to transfer too much data. 160159743Sgroudier * 160259743Sgroudier * If phase is DATA OUT write 1 byte and count it. 160359743Sgroudier */ 160459743Sgroudier SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_OUT)), 160559743Sgroudier 16, 160659743Sgroudier SCR_CHMOV_ABS (1) ^ SCR_DATA_OUT, 160759743Sgroudier HADDR_1 (scratch), 160859743Sgroudier SCR_JUMP, 160959743Sgroudier PADDR_B (data_ovrun2), 161059743Sgroudier /* 161159743Sgroudier * If WSR is set, clear this condition, and 161259743Sgroudier * count this byte. 161359743Sgroudier */ 161459743Sgroudier SCR_FROM_REG (scntl2), 161559743Sgroudier 0, 161659743Sgroudier SCR_JUMPR ^ IFFALSE (MASK (WSR, WSR)), 161759743Sgroudier 16, 161859743Sgroudier SCR_REG_REG (scntl2, SCR_OR, WSR), 161959743Sgroudier 0, 162059743Sgroudier SCR_JUMP, 162159743Sgroudier PADDR_B (data_ovrun2), 162259743Sgroudier /* 162359743Sgroudier * Finally check against DATA IN phase. 162459743Sgroudier * Signal data overrun to the C code 162559743Sgroudier * and jump to dispatcher if not so. 162659743Sgroudier * Read 1 byte otherwise and count it. 162759743Sgroudier */ 162859743Sgroudier SCR_JUMPR ^ IFTRUE (WHEN (SCR_DATA_IN)), 162959743Sgroudier 16, 163059743Sgroudier SCR_INT, 163159743Sgroudier SIR_DATA_OVERRUN, 163259743Sgroudier SCR_JUMP, 163359743Sgroudier PADDR_A (dispatch), 163459743Sgroudier SCR_CHMOV_ABS (1) ^ SCR_DATA_IN, 163559743Sgroudier HADDR_1 (scratch), 163659743Sgroudier}/*-------------------------< DATA_OVRUN2 >----------------------*/,{ 163759743Sgroudier /* 163859743Sgroudier * Count this byte. 163959743Sgroudier * This will allow to return a negative 164059743Sgroudier * residual to user. 164159743Sgroudier */ 164259743Sgroudier SCR_REG_REG (scratcha, SCR_ADD, 0x01), 164359743Sgroudier 0, 164459743Sgroudier SCR_REG_REG (scratcha1, SCR_ADDC, 0), 164559743Sgroudier 0, 164659743Sgroudier SCR_REG_REG (scratcha2, SCR_ADDC, 0), 164759743Sgroudier 0, 164859743Sgroudier /* 164959743Sgroudier * .. and repeat as required. 165059743Sgroudier */ 165159743Sgroudier SCR_JUMP, 165259743Sgroudier PADDR_B (data_ovrun1), 165359743Sgroudier}/*-------------------------< ABORT_RESEL >----------------------*/,{ 165459743Sgroudier SCR_SET (SCR_ATN), 165559743Sgroudier 0, 165659743Sgroudier SCR_CLR (SCR_ACK), 165759743Sgroudier 0, 165859743Sgroudier /* 165959743Sgroudier * send the abort/abortag/reset message 166059743Sgroudier * we expect an immediate disconnect 166159743Sgroudier */ 166259743Sgroudier SCR_REG_REG (scntl2, SCR_AND, 0x7f), 166359743Sgroudier 0, 166459743Sgroudier SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, 166559743Sgroudier HADDR_1 (msgout), 166659743Sgroudier SCR_CLR (SCR_ACK|SCR_ATN), 166759743Sgroudier 0, 166859743Sgroudier SCR_WAIT_DISC, 166959743Sgroudier 0, 167059743Sgroudier SCR_INT, 167159743Sgroudier SIR_RESEL_ABORTED, 167259743Sgroudier SCR_JUMP, 167359743Sgroudier PADDR_A (start), 167459743Sgroudier}/*-------------------------< RESEND_IDENT >---------------------*/,{ 167559743Sgroudier /* 167659743Sgroudier * The target stays in MSG OUT phase after having acked 167759743Sgroudier * Identify [+ Tag [+ Extended message ]]. Targets shall 167859743Sgroudier * behave this way on parity error. 167959743Sgroudier * We must send it again all the messages. 168059743Sgroudier */ 168159743Sgroudier SCR_SET (SCR_ATN), /* Shall be asserted 2 deskew delays before the */ 168259743Sgroudier 0, /* 1rst ACK = 90 ns. Hope the chip isn't too fast */ 168359743Sgroudier SCR_JUMP, 168459743Sgroudier PADDR_A (send_ident), 168559743Sgroudier}/*-------------------------< IDENT_BREAK >----------------------*/,{ 168659743Sgroudier SCR_CLR (SCR_ATN), 168759743Sgroudier 0, 168859743Sgroudier SCR_JUMP, 168959743Sgroudier PADDR_A (select2), 169059743Sgroudier}/*-------------------------< IDENT_BREAK_ATN >------------------*/,{ 169159743Sgroudier SCR_SET (SCR_ATN), 169259743Sgroudier 0, 169359743Sgroudier SCR_JUMP, 169459743Sgroudier PADDR_A (select2), 169559743Sgroudier}/*-------------------------< SDATA_IN >-------------------------*/,{ 169659743Sgroudier SCR_CHMOV_TBL ^ SCR_DATA_IN, 169759743Sgroudier offsetof (struct sym_dsb, sense), 169859743Sgroudier SCR_CALL, 169959743Sgroudier PADDR_A (datai_done), 170059743Sgroudier SCR_JUMP, 170159743Sgroudier PADDR_B (data_ovrun), 170259743Sgroudier}/*-------------------------< RESEL_BAD_LUN >--------------------*/,{ 170359743Sgroudier /* 170459743Sgroudier * Message is an IDENTIFY, but lun is unknown. 170559743Sgroudier * Signal problem to C code for logging the event. 170659743Sgroudier * Send a M_ABORT to clear all pending tasks. 170759743Sgroudier */ 170859743Sgroudier SCR_INT, 170959743Sgroudier SIR_RESEL_BAD_LUN, 171059743Sgroudier SCR_JUMP, 171159743Sgroudier PADDR_B (abort_resel), 171259743Sgroudier}/*-------------------------< BAD_I_T_L >------------------------*/,{ 171359743Sgroudier /* 171459743Sgroudier * We donnot have a task for that I_T_L. 171559743Sgroudier * Signal problem to C code for logging the event. 171659743Sgroudier * Send a M_ABORT message. 171759743Sgroudier */ 171859743Sgroudier SCR_INT, 171959743Sgroudier SIR_RESEL_BAD_I_T_L, 172059743Sgroudier SCR_JUMP, 172159743Sgroudier PADDR_B (abort_resel), 172259743Sgroudier}/*-------------------------< BAD_I_T_L_Q >----------------------*/,{ 172359743Sgroudier /* 172459743Sgroudier * We donnot have a task that matches the tag. 172559743Sgroudier * Signal problem to C code for logging the event. 172659743Sgroudier * Send a M_ABORTTAG message. 172759743Sgroudier */ 172859743Sgroudier SCR_INT, 172959743Sgroudier SIR_RESEL_BAD_I_T_L_Q, 173059743Sgroudier SCR_JUMP, 173159743Sgroudier PADDR_B (abort_resel), 173259743Sgroudier}/*-------------------------< BAD_STATUS >-----------------------*/,{ 173359743Sgroudier /* 173459743Sgroudier * Anything different from INTERMEDIATE 173559743Sgroudier * CONDITION MET should be a bad SCSI status, 173659743Sgroudier * given that GOOD status has already been tested. 173759743Sgroudier * Call the C code. 173859743Sgroudier */ 173959743Sgroudier SCR_COPY (4), 174059743Sgroudier PADDR_B (startpos), 174159743Sgroudier RADDR_1 (scratcha), 174259743Sgroudier SCR_INT ^ IFFALSE (DATA (S_COND_MET)), 174359743Sgroudier SIR_BAD_SCSI_STATUS, 174459743Sgroudier SCR_RETURN, 174559743Sgroudier 0, 174659743Sgroudier}/*-------------------------< WSR_MA_HELPER >--------------------*/,{ 174759743Sgroudier /* 174859743Sgroudier * Helper for the C code when WSR bit is set. 174959743Sgroudier * Perform the move of the residual byte. 175059743Sgroudier */ 175159743Sgroudier SCR_CHMOV_TBL ^ SCR_DATA_IN, 175259743Sgroudier offsetof (struct sym_ccb, phys.wresid), 175359743Sgroudier SCR_JUMP, 175459743Sgroudier PADDR_A (dispatch), 175559743Sgroudier}/*-------------------------< ZERO >-----------------------------*/,{ 175659743Sgroudier SCR_DATA_ZERO, 175759743Sgroudier}/*-------------------------< SCRATCH >--------------------------*/,{ 175859743Sgroudier SCR_DATA_ZERO, /* MUST BE BEFORE SCRATCH1 */ 175959743Sgroudier}/*-------------------------< SCRATCH1 >-------------------------*/,{ 176059743Sgroudier SCR_DATA_ZERO, 176159743Sgroudier}/*-------------------------< PREV_DONE >------------------------*/,{ 176259743Sgroudier SCR_DATA_ZERO, /* MUST BE BEFORE DONE_POS ! */ 176359743Sgroudier}/*-------------------------< DONE_POS >-------------------------*/,{ 176459743Sgroudier SCR_DATA_ZERO, 176559743Sgroudier}/*-------------------------< NEXTJOB >--------------------------*/,{ 176659743Sgroudier SCR_DATA_ZERO, /* MUST BE BEFORE STARTPOS ! */ 176759743Sgroudier}/*-------------------------< STARTPOS >-------------------------*/,{ 176859743Sgroudier SCR_DATA_ZERO, 176959743Sgroudier}/*-------------------------< TARGTBL >--------------------------*/,{ 177059743Sgroudier SCR_DATA_ZERO, 177159743Sgroudier 177259743Sgroudier}/*-------------------------< SNOOPTEST >------------------------*/,{ 177359743Sgroudier /* 177459743Sgroudier * Read the variable. 177559743Sgroudier */ 177659743Sgroudier SCR_COPY (4), 177759743Sgroudier HADDR_1 (cache), 177859743Sgroudier RADDR_1 (scratcha), 177959743Sgroudier /* 178059743Sgroudier * Write the variable. 178159743Sgroudier */ 178259743Sgroudier SCR_COPY (4), 178359743Sgroudier RADDR_1 (temp), 178459743Sgroudier HADDR_1 (cache), 178559743Sgroudier /* 178659743Sgroudier * Read back the variable. 178759743Sgroudier */ 178859743Sgroudier SCR_COPY (4), 178959743Sgroudier HADDR_1 (cache), 179059743Sgroudier RADDR_1 (temp), 179159743Sgroudier}/*-------------------------< SNOOPEND >-------------------------*/,{ 179259743Sgroudier /* 179359743Sgroudier * And stop. 179459743Sgroudier */ 179559743Sgroudier SCR_INT, 179659743Sgroudier 99, 179759743Sgroudier}/*--------------------------<>----------------------------------*/ 179859743Sgroudier}; 1799