1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-or-later */ 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family 4*4882a593Smuzhiyun * of PCI-SCSI IO processors. 5*4882a593Smuzhiyun * 6*4882a593Smuzhiyun * Copyright (C) 1999-2001 Gerard Roudier <groudier@free.fr> 7*4882a593Smuzhiyun * 8*4882a593Smuzhiyun * This driver is derived from the Linux sym53c8xx driver. 9*4882a593Smuzhiyun * Copyright (C) 1998-2000 Gerard Roudier 10*4882a593Smuzhiyun * 11*4882a593Smuzhiyun * The sym53c8xx driver is derived from the ncr53c8xx driver that had been 12*4882a593Smuzhiyun * a port of the FreeBSD ncr driver to Linux-1.2.13. 13*4882a593Smuzhiyun * 14*4882a593Smuzhiyun * The original ncr driver has been written for 386bsd and FreeBSD by 15*4882a593Smuzhiyun * Wolfgang Stanglmeier <wolf@cologne.de> 16*4882a593Smuzhiyun * Stefan Esser <se@mi.Uni-Koeln.de> 17*4882a593Smuzhiyun * Copyright (C) 1994 Wolfgang Stanglmeier 18*4882a593Smuzhiyun * 19*4882a593Smuzhiyun * Other major contributions: 20*4882a593Smuzhiyun * 21*4882a593Smuzhiyun * NVRAM detection and reading. 22*4882a593Smuzhiyun * Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk> 23*4882a593Smuzhiyun * 24*4882a593Smuzhiyun *----------------------------------------------------------------------------- 25*4882a593Smuzhiyun */ 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun /* 28*4882a593Smuzhiyun * Scripts for SYMBIOS-Processor 29*4882a593Smuzhiyun * 30*4882a593Smuzhiyun * We have to know the offsets of all labels before we reach 31*4882a593Smuzhiyun * them (for forward jumps). Therefore we declare a struct 32*4882a593Smuzhiyun * here. If you make changes inside the script, 33*4882a593Smuzhiyun * 34*4882a593Smuzhiyun * DONT FORGET TO CHANGE THE LENGTHS HERE! 35*4882a593Smuzhiyun */ 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun /* 38*4882a593Smuzhiyun * Script fragments which are loaded into the on-chip RAM 39*4882a593Smuzhiyun * of 825A, 875, 876, 895, 895A, 896 and 1010 chips. 40*4882a593Smuzhiyun * Must not exceed 4K bytes. 41*4882a593Smuzhiyun */ 42*4882a593Smuzhiyun struct SYM_FWA_SCR { 43*4882a593Smuzhiyun u32 start [ 11]; 44*4882a593Smuzhiyun u32 getjob_begin [ 4]; 45*4882a593Smuzhiyun u32 _sms_a10 [ 5]; 46*4882a593Smuzhiyun u32 getjob_end [ 4]; 47*4882a593Smuzhiyun u32 _sms_a20 [ 4]; 48*4882a593Smuzhiyun #ifdef SYM_CONF_TARGET_ROLE_SUPPORT 49*4882a593Smuzhiyun u32 select [ 8]; 50*4882a593Smuzhiyun #else 51*4882a593Smuzhiyun u32 select [ 6]; 52*4882a593Smuzhiyun #endif 53*4882a593Smuzhiyun u32 _sms_a30 [ 5]; 54*4882a593Smuzhiyun u32 wf_sel_done [ 2]; 55*4882a593Smuzhiyun u32 send_ident [ 2]; 56*4882a593Smuzhiyun #ifdef SYM_CONF_IARB_SUPPORT 57*4882a593Smuzhiyun u32 select2 [ 8]; 58*4882a593Smuzhiyun #else 59*4882a593Smuzhiyun u32 select2 [ 2]; 60*4882a593Smuzhiyun #endif 61*4882a593Smuzhiyun u32 command [ 2]; 62*4882a593Smuzhiyun u32 dispatch [ 28]; 63*4882a593Smuzhiyun u32 sel_no_cmd [ 10]; 64*4882a593Smuzhiyun u32 init [ 6]; 65*4882a593Smuzhiyun u32 clrack [ 4]; 66*4882a593Smuzhiyun u32 datai_done [ 11]; 67*4882a593Smuzhiyun u32 datai_done_wsr [ 20]; 68*4882a593Smuzhiyun u32 datao_done [ 11]; 69*4882a593Smuzhiyun u32 datao_done_wss [ 6]; 70*4882a593Smuzhiyun u32 datai_phase [ 5]; 71*4882a593Smuzhiyun u32 datao_phase [ 5]; 72*4882a593Smuzhiyun u32 msg_in [ 2]; 73*4882a593Smuzhiyun u32 msg_in2 [ 10]; 74*4882a593Smuzhiyun #ifdef SYM_CONF_IARB_SUPPORT 75*4882a593Smuzhiyun u32 status [ 14]; 76*4882a593Smuzhiyun #else 77*4882a593Smuzhiyun u32 status [ 10]; 78*4882a593Smuzhiyun #endif 79*4882a593Smuzhiyun u32 complete [ 6]; 80*4882a593Smuzhiyun u32 complete2 [ 8]; 81*4882a593Smuzhiyun u32 _sms_a40 [ 12]; 82*4882a593Smuzhiyun u32 done [ 5]; 83*4882a593Smuzhiyun u32 _sms_a50 [ 5]; 84*4882a593Smuzhiyun u32 _sms_a60 [ 2]; 85*4882a593Smuzhiyun u32 done_end [ 4]; 86*4882a593Smuzhiyun u32 complete_error [ 5]; 87*4882a593Smuzhiyun u32 save_dp [ 11]; 88*4882a593Smuzhiyun u32 restore_dp [ 7]; 89*4882a593Smuzhiyun u32 disconnect [ 11]; 90*4882a593Smuzhiyun u32 disconnect2 [ 5]; 91*4882a593Smuzhiyun u32 _sms_a65 [ 3]; 92*4882a593Smuzhiyun #ifdef SYM_CONF_IARB_SUPPORT 93*4882a593Smuzhiyun u32 idle [ 4]; 94*4882a593Smuzhiyun #else 95*4882a593Smuzhiyun u32 idle [ 2]; 96*4882a593Smuzhiyun #endif 97*4882a593Smuzhiyun #ifdef SYM_CONF_IARB_SUPPORT 98*4882a593Smuzhiyun u32 ungetjob [ 7]; 99*4882a593Smuzhiyun #else 100*4882a593Smuzhiyun u32 ungetjob [ 5]; 101*4882a593Smuzhiyun #endif 102*4882a593Smuzhiyun #ifdef SYM_CONF_TARGET_ROLE_SUPPORT 103*4882a593Smuzhiyun u32 reselect [ 4]; 104*4882a593Smuzhiyun #else 105*4882a593Smuzhiyun u32 reselect [ 2]; 106*4882a593Smuzhiyun #endif 107*4882a593Smuzhiyun u32 reselected [ 19]; 108*4882a593Smuzhiyun u32 _sms_a70 [ 6]; 109*4882a593Smuzhiyun u32 _sms_a80 [ 4]; 110*4882a593Smuzhiyun u32 reselected1 [ 25]; 111*4882a593Smuzhiyun u32 _sms_a90 [ 4]; 112*4882a593Smuzhiyun u32 resel_lun0 [ 7]; 113*4882a593Smuzhiyun u32 _sms_a100 [ 4]; 114*4882a593Smuzhiyun u32 resel_tag [ 8]; 115*4882a593Smuzhiyun #if SYM_CONF_MAX_TASK*4 > 512 116*4882a593Smuzhiyun u32 _sms_a110 [ 23]; 117*4882a593Smuzhiyun #elif SYM_CONF_MAX_TASK*4 > 256 118*4882a593Smuzhiyun u32 _sms_a110 [ 17]; 119*4882a593Smuzhiyun #else 120*4882a593Smuzhiyun u32 _sms_a110 [ 13]; 121*4882a593Smuzhiyun #endif 122*4882a593Smuzhiyun u32 _sms_a120 [ 2]; 123*4882a593Smuzhiyun u32 resel_go [ 4]; 124*4882a593Smuzhiyun u32 _sms_a130 [ 7]; 125*4882a593Smuzhiyun u32 resel_dsa [ 2]; 126*4882a593Smuzhiyun u32 resel_dsa1 [ 4]; 127*4882a593Smuzhiyun u32 _sms_a140 [ 7]; 128*4882a593Smuzhiyun u32 resel_no_tag [ 4]; 129*4882a593Smuzhiyun u32 _sms_a145 [ 7]; 130*4882a593Smuzhiyun u32 data_in [SYM_CONF_MAX_SG * 2]; 131*4882a593Smuzhiyun u32 data_in2 [ 4]; 132*4882a593Smuzhiyun u32 data_out [SYM_CONF_MAX_SG * 2]; 133*4882a593Smuzhiyun u32 data_out2 [ 4]; 134*4882a593Smuzhiyun u32 pm0_data [ 12]; 135*4882a593Smuzhiyun u32 pm0_data_out [ 6]; 136*4882a593Smuzhiyun u32 pm0_data_end [ 7]; 137*4882a593Smuzhiyun u32 pm_data_end [ 4]; 138*4882a593Smuzhiyun u32 _sms_a150 [ 4]; 139*4882a593Smuzhiyun u32 pm1_data [ 12]; 140*4882a593Smuzhiyun u32 pm1_data_out [ 6]; 141*4882a593Smuzhiyun u32 pm1_data_end [ 9]; 142*4882a593Smuzhiyun }; 143*4882a593Smuzhiyun 144*4882a593Smuzhiyun /* 145*4882a593Smuzhiyun * Script fragments which stay in main memory for all chips 146*4882a593Smuzhiyun * except for chips that support 8K on-chip RAM. 147*4882a593Smuzhiyun */ 148*4882a593Smuzhiyun struct SYM_FWB_SCR { 149*4882a593Smuzhiyun u32 no_data [ 2]; 150*4882a593Smuzhiyun #ifdef SYM_CONF_TARGET_ROLE_SUPPORT 151*4882a593Smuzhiyun u32 sel_for_abort [ 18]; 152*4882a593Smuzhiyun #else 153*4882a593Smuzhiyun u32 sel_for_abort [ 16]; 154*4882a593Smuzhiyun #endif 155*4882a593Smuzhiyun u32 sel_for_abort_1 [ 2]; 156*4882a593Smuzhiyun u32 msg_in_etc [ 12]; 157*4882a593Smuzhiyun u32 msg_received [ 5]; 158*4882a593Smuzhiyun u32 msg_weird_seen [ 5]; 159*4882a593Smuzhiyun u32 msg_extended [ 17]; 160*4882a593Smuzhiyun u32 _sms_b10 [ 4]; 161*4882a593Smuzhiyun u32 msg_bad [ 6]; 162*4882a593Smuzhiyun u32 msg_weird [ 4]; 163*4882a593Smuzhiyun u32 msg_weird1 [ 8]; 164*4882a593Smuzhiyun u32 wdtr_resp [ 6]; 165*4882a593Smuzhiyun u32 send_wdtr [ 4]; 166*4882a593Smuzhiyun u32 sdtr_resp [ 6]; 167*4882a593Smuzhiyun u32 send_sdtr [ 4]; 168*4882a593Smuzhiyun u32 ppr_resp [ 6]; 169*4882a593Smuzhiyun u32 send_ppr [ 4]; 170*4882a593Smuzhiyun u32 nego_bad_phase [ 4]; 171*4882a593Smuzhiyun u32 msg_out [ 4]; 172*4882a593Smuzhiyun u32 msg_out_done [ 4]; 173*4882a593Smuzhiyun u32 data_ovrun [ 3]; 174*4882a593Smuzhiyun u32 data_ovrun1 [ 22]; 175*4882a593Smuzhiyun u32 data_ovrun2 [ 8]; 176*4882a593Smuzhiyun u32 abort_resel [ 16]; 177*4882a593Smuzhiyun u32 resend_ident [ 4]; 178*4882a593Smuzhiyun u32 ident_break [ 4]; 179*4882a593Smuzhiyun u32 ident_break_atn [ 4]; 180*4882a593Smuzhiyun u32 sdata_in [ 6]; 181*4882a593Smuzhiyun u32 resel_bad_lun [ 4]; 182*4882a593Smuzhiyun u32 bad_i_t_l [ 4]; 183*4882a593Smuzhiyun u32 bad_i_t_l_q [ 4]; 184*4882a593Smuzhiyun u32 bad_status [ 7]; 185*4882a593Smuzhiyun u32 wsr_ma_helper [ 4]; 186*4882a593Smuzhiyun 187*4882a593Smuzhiyun /* Data area */ 188*4882a593Smuzhiyun u32 zero [ 1]; 189*4882a593Smuzhiyun u32 scratch [ 1]; 190*4882a593Smuzhiyun u32 scratch1 [ 1]; 191*4882a593Smuzhiyun u32 prev_done [ 1]; 192*4882a593Smuzhiyun u32 done_pos [ 1]; 193*4882a593Smuzhiyun u32 nextjob [ 1]; 194*4882a593Smuzhiyun u32 startpos [ 1]; 195*4882a593Smuzhiyun u32 targtbl [ 1]; 196*4882a593Smuzhiyun }; 197*4882a593Smuzhiyun 198*4882a593Smuzhiyun /* 199*4882a593Smuzhiyun * Script fragments used at initialisations. 200*4882a593Smuzhiyun * Only runs out of main memory. 201*4882a593Smuzhiyun */ 202*4882a593Smuzhiyun struct SYM_FWZ_SCR { 203*4882a593Smuzhiyun u32 snooptest [ 9]; 204*4882a593Smuzhiyun u32 snoopend [ 2]; 205*4882a593Smuzhiyun }; 206*4882a593Smuzhiyun 207*4882a593Smuzhiyun static struct SYM_FWA_SCR SYM_FWA_SCR = { 208*4882a593Smuzhiyun /*--------------------------< START >----------------------------*/ { 209*4882a593Smuzhiyun /* 210*4882a593Smuzhiyun * Switch the LED on. 211*4882a593Smuzhiyun * Will be patched with a NO_OP if LED 212*4882a593Smuzhiyun * not needed or not desired. 213*4882a593Smuzhiyun */ 214*4882a593Smuzhiyun SCR_REG_REG (gpreg, SCR_AND, 0xfe), 215*4882a593Smuzhiyun 0, 216*4882a593Smuzhiyun /* 217*4882a593Smuzhiyun * Clear SIGP. 218*4882a593Smuzhiyun */ 219*4882a593Smuzhiyun SCR_FROM_REG (ctest2), 220*4882a593Smuzhiyun 0, 221*4882a593Smuzhiyun /* 222*4882a593Smuzhiyun * Stop here if the C code wants to perform 223*4882a593Smuzhiyun * some error recovery procedure manually. 224*4882a593Smuzhiyun * (Indicate this by setting SEM in ISTAT) 225*4882a593Smuzhiyun */ 226*4882a593Smuzhiyun SCR_FROM_REG (istat), 227*4882a593Smuzhiyun 0, 228*4882a593Smuzhiyun /* 229*4882a593Smuzhiyun * Report to the C code the next position in 230*4882a593Smuzhiyun * the start queue the SCRIPTS will schedule. 231*4882a593Smuzhiyun * The C code must not change SCRATCHA. 232*4882a593Smuzhiyun */ 233*4882a593Smuzhiyun SCR_COPY (4), 234*4882a593Smuzhiyun PADDR_B (startpos), 235*4882a593Smuzhiyun RADDR_1 (scratcha), 236*4882a593Smuzhiyun SCR_INT ^ IFTRUE (MASK (SEM, SEM)), 237*4882a593Smuzhiyun SIR_SCRIPT_STOPPED, 238*4882a593Smuzhiyun /* 239*4882a593Smuzhiyun * Start the next job. 240*4882a593Smuzhiyun * 241*4882a593Smuzhiyun * @DSA = start point for this job. 242*4882a593Smuzhiyun * SCRATCHA = address of this job in the start queue. 243*4882a593Smuzhiyun * 244*4882a593Smuzhiyun * We will restore startpos with SCRATCHA if we fails the 245*4882a593Smuzhiyun * arbitration or if it is the idle job. 246*4882a593Smuzhiyun * 247*4882a593Smuzhiyun * The below GETJOB_BEGIN to GETJOB_END section of SCRIPTS 248*4882a593Smuzhiyun * is a critical path. If it is partially executed, it then 249*4882a593Smuzhiyun * may happen that the job address is not yet in the DSA 250*4882a593Smuzhiyun * and the next queue position points to the next JOB. 251*4882a593Smuzhiyun */ 252*4882a593Smuzhiyun }/*-------------------------< GETJOB_BEGIN >---------------------*/,{ 253*4882a593Smuzhiyun /* 254*4882a593Smuzhiyun * Copy to a fixed location both the next STARTPOS 255*4882a593Smuzhiyun * and the current JOB address, using self modifying 256*4882a593Smuzhiyun * SCRIPTS. 257*4882a593Smuzhiyun */ 258*4882a593Smuzhiyun SCR_COPY (4), 259*4882a593Smuzhiyun RADDR_1 (scratcha), 260*4882a593Smuzhiyun PADDR_A (_sms_a10), 261*4882a593Smuzhiyun SCR_COPY (8), 262*4882a593Smuzhiyun }/*-------------------------< _SMS_A10 >-------------------------*/,{ 263*4882a593Smuzhiyun 0, 264*4882a593Smuzhiyun PADDR_B (nextjob), 265*4882a593Smuzhiyun /* 266*4882a593Smuzhiyun * Move the start address to TEMP using self- 267*4882a593Smuzhiyun * modifying SCRIPTS and jump indirectly to 268*4882a593Smuzhiyun * that address. 269*4882a593Smuzhiyun */ 270*4882a593Smuzhiyun SCR_COPY (4), 271*4882a593Smuzhiyun PADDR_B (nextjob), 272*4882a593Smuzhiyun RADDR_1 (dsa), 273*4882a593Smuzhiyun }/*-------------------------< GETJOB_END >-----------------------*/,{ 274*4882a593Smuzhiyun SCR_COPY (4), 275*4882a593Smuzhiyun RADDR_1 (dsa), 276*4882a593Smuzhiyun PADDR_A (_sms_a20), 277*4882a593Smuzhiyun SCR_COPY (4), 278*4882a593Smuzhiyun }/*-------------------------< _SMS_A20 >-------------------------*/,{ 279*4882a593Smuzhiyun 0, 280*4882a593Smuzhiyun RADDR_1 (temp), 281*4882a593Smuzhiyun SCR_RETURN, 282*4882a593Smuzhiyun 0, 283*4882a593Smuzhiyun }/*-------------------------< SELECT >---------------------------*/,{ 284*4882a593Smuzhiyun /* 285*4882a593Smuzhiyun * DSA contains the address of a scheduled 286*4882a593Smuzhiyun * data structure. 287*4882a593Smuzhiyun * 288*4882a593Smuzhiyun * SCRATCHA contains the address of the start queue 289*4882a593Smuzhiyun * entry which points to the next job. 290*4882a593Smuzhiyun * 291*4882a593Smuzhiyun * Set Initiator mode. 292*4882a593Smuzhiyun * 293*4882a593Smuzhiyun * (Target mode is left as an exercise for the reader) 294*4882a593Smuzhiyun */ 295*4882a593Smuzhiyun #ifdef SYM_CONF_TARGET_ROLE_SUPPORT 296*4882a593Smuzhiyun SCR_CLR (SCR_TRG), 297*4882a593Smuzhiyun 0, 298*4882a593Smuzhiyun #endif 299*4882a593Smuzhiyun /* 300*4882a593Smuzhiyun * And try to select this target. 301*4882a593Smuzhiyun */ 302*4882a593Smuzhiyun SCR_SEL_TBL_ATN ^ offsetof (struct sym_dsb, select), 303*4882a593Smuzhiyun PADDR_A (ungetjob), 304*4882a593Smuzhiyun /* 305*4882a593Smuzhiyun * Now there are 4 possibilities: 306*4882a593Smuzhiyun * 307*4882a593Smuzhiyun * (1) The chip loses arbitration. 308*4882a593Smuzhiyun * This is ok, because it will try again, 309*4882a593Smuzhiyun * when the bus becomes idle. 310*4882a593Smuzhiyun * (But beware of the timeout function!) 311*4882a593Smuzhiyun * 312*4882a593Smuzhiyun * (2) The chip is reselected. 313*4882a593Smuzhiyun * Then the script processor takes the jump 314*4882a593Smuzhiyun * to the RESELECT label. 315*4882a593Smuzhiyun * 316*4882a593Smuzhiyun * (3) The chip wins arbitration. 317*4882a593Smuzhiyun * Then it will execute SCRIPTS instruction until 318*4882a593Smuzhiyun * the next instruction that checks SCSI phase. 319*4882a593Smuzhiyun * Then will stop and wait for selection to be 320*4882a593Smuzhiyun * complete or selection time-out to occur. 321*4882a593Smuzhiyun * 322*4882a593Smuzhiyun * After having won arbitration, the SCRIPTS 323*4882a593Smuzhiyun * processor is able to execute instructions while 324*4882a593Smuzhiyun * the SCSI core is performing SCSI selection. 325*4882a593Smuzhiyun */ 326*4882a593Smuzhiyun 327*4882a593Smuzhiyun /* 328*4882a593Smuzhiyun * Copy the CCB header to a fixed location 329*4882a593Smuzhiyun * in the HCB using self-modifying SCRIPTS. 330*4882a593Smuzhiyun */ 331*4882a593Smuzhiyun SCR_COPY (4), 332*4882a593Smuzhiyun RADDR_1 (dsa), 333*4882a593Smuzhiyun PADDR_A (_sms_a30), 334*4882a593Smuzhiyun SCR_COPY (sizeof(struct sym_ccbh)), 335*4882a593Smuzhiyun }/*-------------------------< _SMS_A30 >-------------------------*/,{ 336*4882a593Smuzhiyun 0, 337*4882a593Smuzhiyun HADDR_1 (ccb_head), 338*4882a593Smuzhiyun /* 339*4882a593Smuzhiyun * Initialize the status register 340*4882a593Smuzhiyun */ 341*4882a593Smuzhiyun SCR_COPY (4), 342*4882a593Smuzhiyun HADDR_1 (ccb_head.status), 343*4882a593Smuzhiyun RADDR_1 (scr0), 344*4882a593Smuzhiyun }/*-------------------------< WF_SEL_DONE >----------------------*/,{ 345*4882a593Smuzhiyun SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)), 346*4882a593Smuzhiyun SIR_SEL_ATN_NO_MSG_OUT, 347*4882a593Smuzhiyun }/*-------------------------< SEND_IDENT >-----------------------*/,{ 348*4882a593Smuzhiyun /* 349*4882a593Smuzhiyun * Selection complete. 350*4882a593Smuzhiyun * Send the IDENTIFY and possibly the TAG message 351*4882a593Smuzhiyun * and negotiation message if present. 352*4882a593Smuzhiyun */ 353*4882a593Smuzhiyun SCR_MOVE_TBL ^ SCR_MSG_OUT, 354*4882a593Smuzhiyun offsetof (struct sym_dsb, smsg), 355*4882a593Smuzhiyun }/*-------------------------< SELECT2 >--------------------------*/,{ 356*4882a593Smuzhiyun #ifdef SYM_CONF_IARB_SUPPORT 357*4882a593Smuzhiyun /* 358*4882a593Smuzhiyun * Set IMMEDIATE ARBITRATION if we have been given 359*4882a593Smuzhiyun * a hint to do so. (Some job to do after this one). 360*4882a593Smuzhiyun */ 361*4882a593Smuzhiyun SCR_FROM_REG (HF_REG), 362*4882a593Smuzhiyun 0, 363*4882a593Smuzhiyun SCR_JUMPR ^ IFFALSE (MASK (HF_HINT_IARB, HF_HINT_IARB)), 364*4882a593Smuzhiyun 8, 365*4882a593Smuzhiyun SCR_REG_REG (scntl1, SCR_OR, IARB), 366*4882a593Smuzhiyun 0, 367*4882a593Smuzhiyun #endif 368*4882a593Smuzhiyun /* 369*4882a593Smuzhiyun * Anticipate the COMMAND phase. 370*4882a593Smuzhiyun * This is the PHASE we expect at this point. 371*4882a593Smuzhiyun */ 372*4882a593Smuzhiyun SCR_JUMP ^ IFFALSE (WHEN (SCR_COMMAND)), 373*4882a593Smuzhiyun PADDR_A (sel_no_cmd), 374*4882a593Smuzhiyun }/*-------------------------< COMMAND >--------------------------*/,{ 375*4882a593Smuzhiyun /* 376*4882a593Smuzhiyun * ... and send the command 377*4882a593Smuzhiyun */ 378*4882a593Smuzhiyun SCR_MOVE_TBL ^ SCR_COMMAND, 379*4882a593Smuzhiyun offsetof (struct sym_dsb, cmd), 380*4882a593Smuzhiyun }/*-------------------------< DISPATCH >-------------------------*/,{ 381*4882a593Smuzhiyun /* 382*4882a593Smuzhiyun * MSG_IN is the only phase that shall be 383*4882a593Smuzhiyun * entered at least once for each (re)selection. 384*4882a593Smuzhiyun * So we test it first. 385*4882a593Smuzhiyun */ 386*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)), 387*4882a593Smuzhiyun PADDR_A (msg_in), 388*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (IF (SCR_DATA_OUT)), 389*4882a593Smuzhiyun PADDR_A (datao_phase), 390*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (IF (SCR_DATA_IN)), 391*4882a593Smuzhiyun PADDR_A (datai_phase), 392*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (IF (SCR_STATUS)), 393*4882a593Smuzhiyun PADDR_A (status), 394*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)), 395*4882a593Smuzhiyun PADDR_A (command), 396*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)), 397*4882a593Smuzhiyun PADDR_B (msg_out), 398*4882a593Smuzhiyun /* 399*4882a593Smuzhiyun * Discard as many illegal phases as 400*4882a593Smuzhiyun * required and tell the C code about. 401*4882a593Smuzhiyun */ 402*4882a593Smuzhiyun SCR_JUMPR ^ IFFALSE (WHEN (SCR_ILG_OUT)), 403*4882a593Smuzhiyun 16, 404*4882a593Smuzhiyun SCR_MOVE_ABS (1) ^ SCR_ILG_OUT, 405*4882a593Smuzhiyun HADDR_1 (scratch), 406*4882a593Smuzhiyun SCR_JUMPR ^ IFTRUE (WHEN (SCR_ILG_OUT)), 407*4882a593Smuzhiyun -16, 408*4882a593Smuzhiyun SCR_JUMPR ^ IFFALSE (WHEN (SCR_ILG_IN)), 409*4882a593Smuzhiyun 16, 410*4882a593Smuzhiyun SCR_MOVE_ABS (1) ^ SCR_ILG_IN, 411*4882a593Smuzhiyun HADDR_1 (scratch), 412*4882a593Smuzhiyun SCR_JUMPR ^ IFTRUE (WHEN (SCR_ILG_IN)), 413*4882a593Smuzhiyun -16, 414*4882a593Smuzhiyun SCR_INT, 415*4882a593Smuzhiyun SIR_BAD_PHASE, 416*4882a593Smuzhiyun SCR_JUMP, 417*4882a593Smuzhiyun PADDR_A (dispatch), 418*4882a593Smuzhiyun }/*-------------------------< SEL_NO_CMD >-----------------------*/,{ 419*4882a593Smuzhiyun /* 420*4882a593Smuzhiyun * The target does not switch to command 421*4882a593Smuzhiyun * phase after IDENTIFY has been sent. 422*4882a593Smuzhiyun * 423*4882a593Smuzhiyun * If it stays in MSG OUT phase send it 424*4882a593Smuzhiyun * the IDENTIFY again. 425*4882a593Smuzhiyun */ 426*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)), 427*4882a593Smuzhiyun PADDR_B (resend_ident), 428*4882a593Smuzhiyun /* 429*4882a593Smuzhiyun * If target does not switch to MSG IN phase 430*4882a593Smuzhiyun * and we sent a negotiation, assert the 431*4882a593Smuzhiyun * failure immediately. 432*4882a593Smuzhiyun */ 433*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)), 434*4882a593Smuzhiyun PADDR_A (dispatch), 435*4882a593Smuzhiyun SCR_FROM_REG (HS_REG), 436*4882a593Smuzhiyun 0, 437*4882a593Smuzhiyun SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)), 438*4882a593Smuzhiyun SIR_NEGO_FAILED, 439*4882a593Smuzhiyun /* 440*4882a593Smuzhiyun * Jump to dispatcher. 441*4882a593Smuzhiyun */ 442*4882a593Smuzhiyun SCR_JUMP, 443*4882a593Smuzhiyun PADDR_A (dispatch), 444*4882a593Smuzhiyun }/*-------------------------< INIT >-----------------------------*/,{ 445*4882a593Smuzhiyun /* 446*4882a593Smuzhiyun * Wait for the SCSI RESET signal to be 447*4882a593Smuzhiyun * inactive before restarting operations, 448*4882a593Smuzhiyun * since the chip may hang on SEL_ATN 449*4882a593Smuzhiyun * if SCSI RESET is active. 450*4882a593Smuzhiyun */ 451*4882a593Smuzhiyun SCR_FROM_REG (sstat0), 452*4882a593Smuzhiyun 0, 453*4882a593Smuzhiyun SCR_JUMPR ^ IFTRUE (MASK (IRST, IRST)), 454*4882a593Smuzhiyun -16, 455*4882a593Smuzhiyun SCR_JUMP, 456*4882a593Smuzhiyun PADDR_A (start), 457*4882a593Smuzhiyun }/*-------------------------< CLRACK >---------------------------*/,{ 458*4882a593Smuzhiyun /* 459*4882a593Smuzhiyun * Terminate possible pending message phase. 460*4882a593Smuzhiyun */ 461*4882a593Smuzhiyun SCR_CLR (SCR_ACK), 462*4882a593Smuzhiyun 0, 463*4882a593Smuzhiyun SCR_JUMP, 464*4882a593Smuzhiyun PADDR_A (dispatch), 465*4882a593Smuzhiyun }/*-------------------------< DATAI_DONE >-----------------------*/,{ 466*4882a593Smuzhiyun /* 467*4882a593Smuzhiyun * Save current pointer to LASTP. 468*4882a593Smuzhiyun */ 469*4882a593Smuzhiyun SCR_COPY (4), 470*4882a593Smuzhiyun RADDR_1 (temp), 471*4882a593Smuzhiyun HADDR_1 (ccb_head.lastp), 472*4882a593Smuzhiyun /* 473*4882a593Smuzhiyun * If the SWIDE is not full, jump to dispatcher. 474*4882a593Smuzhiyun * We anticipate a STATUS phase. 475*4882a593Smuzhiyun */ 476*4882a593Smuzhiyun SCR_FROM_REG (scntl2), 477*4882a593Smuzhiyun 0, 478*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (MASK (WSR, WSR)), 479*4882a593Smuzhiyun PADDR_A (datai_done_wsr), 480*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (WHEN (SCR_STATUS)), 481*4882a593Smuzhiyun PADDR_A (status), 482*4882a593Smuzhiyun SCR_JUMP, 483*4882a593Smuzhiyun PADDR_A (dispatch), 484*4882a593Smuzhiyun }/*-------------------------< DATAI_DONE_WSR >-------------------*/,{ 485*4882a593Smuzhiyun /* 486*4882a593Smuzhiyun * The SWIDE is full. 487*4882a593Smuzhiyun * Clear this condition. 488*4882a593Smuzhiyun */ 489*4882a593Smuzhiyun SCR_REG_REG (scntl2, SCR_OR, WSR), 490*4882a593Smuzhiyun 0, 491*4882a593Smuzhiyun /* 492*4882a593Smuzhiyun * We are expecting an IGNORE RESIDUE message 493*4882a593Smuzhiyun * from the device, otherwise we are in data 494*4882a593Smuzhiyun * overrun condition. Check against MSG_IN phase. 495*4882a593Smuzhiyun */ 496*4882a593Smuzhiyun SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)), 497*4882a593Smuzhiyun SIR_SWIDE_OVERRUN, 498*4882a593Smuzhiyun SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), 499*4882a593Smuzhiyun PADDR_A (dispatch), 500*4882a593Smuzhiyun /* 501*4882a593Smuzhiyun * We are in MSG_IN phase, 502*4882a593Smuzhiyun * Read the first byte of the message. 503*4882a593Smuzhiyun * If it is not an IGNORE RESIDUE message, 504*4882a593Smuzhiyun * signal overrun and jump to message 505*4882a593Smuzhiyun * processing. 506*4882a593Smuzhiyun */ 507*4882a593Smuzhiyun SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 508*4882a593Smuzhiyun HADDR_1 (msgin[0]), 509*4882a593Smuzhiyun SCR_INT ^ IFFALSE (DATA (M_IGN_RESIDUE)), 510*4882a593Smuzhiyun SIR_SWIDE_OVERRUN, 511*4882a593Smuzhiyun SCR_JUMP ^ IFFALSE (DATA (M_IGN_RESIDUE)), 512*4882a593Smuzhiyun PADDR_A (msg_in2), 513*4882a593Smuzhiyun /* 514*4882a593Smuzhiyun * We got the message we expected. 515*4882a593Smuzhiyun * Read the 2nd byte, and jump to dispatcher. 516*4882a593Smuzhiyun */ 517*4882a593Smuzhiyun SCR_CLR (SCR_ACK), 518*4882a593Smuzhiyun 0, 519*4882a593Smuzhiyun SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 520*4882a593Smuzhiyun HADDR_1 (msgin[1]), 521*4882a593Smuzhiyun SCR_CLR (SCR_ACK), 522*4882a593Smuzhiyun 0, 523*4882a593Smuzhiyun SCR_JUMP, 524*4882a593Smuzhiyun PADDR_A (dispatch), 525*4882a593Smuzhiyun }/*-------------------------< DATAO_DONE >-----------------------*/,{ 526*4882a593Smuzhiyun /* 527*4882a593Smuzhiyun * Save current pointer to LASTP. 528*4882a593Smuzhiyun */ 529*4882a593Smuzhiyun SCR_COPY (4), 530*4882a593Smuzhiyun RADDR_1 (temp), 531*4882a593Smuzhiyun HADDR_1 (ccb_head.lastp), 532*4882a593Smuzhiyun /* 533*4882a593Smuzhiyun * If the SODL is not full jump to dispatcher. 534*4882a593Smuzhiyun * We anticipate a STATUS phase. 535*4882a593Smuzhiyun */ 536*4882a593Smuzhiyun SCR_FROM_REG (scntl2), 537*4882a593Smuzhiyun 0, 538*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (MASK (WSS, WSS)), 539*4882a593Smuzhiyun PADDR_A (datao_done_wss), 540*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (WHEN (SCR_STATUS)), 541*4882a593Smuzhiyun PADDR_A (status), 542*4882a593Smuzhiyun SCR_JUMP, 543*4882a593Smuzhiyun PADDR_A (dispatch), 544*4882a593Smuzhiyun }/*-------------------------< DATAO_DONE_WSS >-------------------*/,{ 545*4882a593Smuzhiyun /* 546*4882a593Smuzhiyun * The SODL is full, clear this condition. 547*4882a593Smuzhiyun */ 548*4882a593Smuzhiyun SCR_REG_REG (scntl2, SCR_OR, WSS), 549*4882a593Smuzhiyun 0, 550*4882a593Smuzhiyun /* 551*4882a593Smuzhiyun * And signal a DATA UNDERRUN condition 552*4882a593Smuzhiyun * to the C code. 553*4882a593Smuzhiyun */ 554*4882a593Smuzhiyun SCR_INT, 555*4882a593Smuzhiyun SIR_SODL_UNDERRUN, 556*4882a593Smuzhiyun SCR_JUMP, 557*4882a593Smuzhiyun PADDR_A (dispatch), 558*4882a593Smuzhiyun }/*-------------------------< DATAI_PHASE >----------------------*/,{ 559*4882a593Smuzhiyun /* 560*4882a593Smuzhiyun * Jump to current pointer. 561*4882a593Smuzhiyun */ 562*4882a593Smuzhiyun SCR_COPY (4), 563*4882a593Smuzhiyun HADDR_1 (ccb_head.lastp), 564*4882a593Smuzhiyun RADDR_1 (temp), 565*4882a593Smuzhiyun SCR_RETURN, 566*4882a593Smuzhiyun 0, 567*4882a593Smuzhiyun }/*-------------------------< DATAO_PHASE >----------------------*/,{ 568*4882a593Smuzhiyun /* 569*4882a593Smuzhiyun * Jump to current pointer. 570*4882a593Smuzhiyun */ 571*4882a593Smuzhiyun SCR_COPY (4), 572*4882a593Smuzhiyun HADDR_1 (ccb_head.lastp), 573*4882a593Smuzhiyun RADDR_1 (temp), 574*4882a593Smuzhiyun SCR_RETURN, 575*4882a593Smuzhiyun 0, 576*4882a593Smuzhiyun }/*-------------------------< MSG_IN >---------------------------*/,{ 577*4882a593Smuzhiyun /* 578*4882a593Smuzhiyun * Get the first byte of the message. 579*4882a593Smuzhiyun * 580*4882a593Smuzhiyun * The script processor doesn't negate the 581*4882a593Smuzhiyun * ACK signal after this transfer. 582*4882a593Smuzhiyun */ 583*4882a593Smuzhiyun SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 584*4882a593Smuzhiyun HADDR_1 (msgin[0]), 585*4882a593Smuzhiyun }/*-------------------------< MSG_IN2 >--------------------------*/,{ 586*4882a593Smuzhiyun /* 587*4882a593Smuzhiyun * Check first against 1 byte messages 588*4882a593Smuzhiyun * that we handle from SCRIPTS. 589*4882a593Smuzhiyun */ 590*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE)), 591*4882a593Smuzhiyun PADDR_A (complete), 592*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)), 593*4882a593Smuzhiyun PADDR_A (disconnect), 594*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)), 595*4882a593Smuzhiyun PADDR_A (save_dp), 596*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)), 597*4882a593Smuzhiyun PADDR_A (restore_dp), 598*4882a593Smuzhiyun /* 599*4882a593Smuzhiyun * We handle all other messages from the 600*4882a593Smuzhiyun * C code, so no need to waste on-chip RAM 601*4882a593Smuzhiyun * for those ones. 602*4882a593Smuzhiyun */ 603*4882a593Smuzhiyun SCR_JUMP, 604*4882a593Smuzhiyun PADDR_B (msg_in_etc), 605*4882a593Smuzhiyun }/*-------------------------< STATUS >---------------------------*/,{ 606*4882a593Smuzhiyun /* 607*4882a593Smuzhiyun * get the status 608*4882a593Smuzhiyun */ 609*4882a593Smuzhiyun SCR_MOVE_ABS (1) ^ SCR_STATUS, 610*4882a593Smuzhiyun HADDR_1 (scratch), 611*4882a593Smuzhiyun #ifdef SYM_CONF_IARB_SUPPORT 612*4882a593Smuzhiyun /* 613*4882a593Smuzhiyun * If STATUS is not GOOD, clear IMMEDIATE ARBITRATION, 614*4882a593Smuzhiyun * since we may have to tamper the start queue from 615*4882a593Smuzhiyun * the C code. 616*4882a593Smuzhiyun */ 617*4882a593Smuzhiyun SCR_JUMPR ^ IFTRUE (DATA (S_GOOD)), 618*4882a593Smuzhiyun 8, 619*4882a593Smuzhiyun SCR_REG_REG (scntl1, SCR_AND, ~IARB), 620*4882a593Smuzhiyun 0, 621*4882a593Smuzhiyun #endif 622*4882a593Smuzhiyun /* 623*4882a593Smuzhiyun * save status to scsi_status. 624*4882a593Smuzhiyun * mark as complete. 625*4882a593Smuzhiyun */ 626*4882a593Smuzhiyun SCR_TO_REG (SS_REG), 627*4882a593Smuzhiyun 0, 628*4882a593Smuzhiyun SCR_LOAD_REG (HS_REG, HS_COMPLETE), 629*4882a593Smuzhiyun 0, 630*4882a593Smuzhiyun /* 631*4882a593Smuzhiyun * Anticipate the MESSAGE PHASE for 632*4882a593Smuzhiyun * the TASK COMPLETE message. 633*4882a593Smuzhiyun */ 634*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)), 635*4882a593Smuzhiyun PADDR_A (msg_in), 636*4882a593Smuzhiyun SCR_JUMP, 637*4882a593Smuzhiyun PADDR_A (dispatch), 638*4882a593Smuzhiyun }/*-------------------------< COMPLETE >-------------------------*/,{ 639*4882a593Smuzhiyun /* 640*4882a593Smuzhiyun * Complete message. 641*4882a593Smuzhiyun * 642*4882a593Smuzhiyun * When we terminate the cycle by clearing ACK, 643*4882a593Smuzhiyun * the target may disconnect immediately. 644*4882a593Smuzhiyun * 645*4882a593Smuzhiyun * We don't want to be told of an "unexpected disconnect", 646*4882a593Smuzhiyun * so we disable this feature. 647*4882a593Smuzhiyun */ 648*4882a593Smuzhiyun SCR_REG_REG (scntl2, SCR_AND, 0x7f), 649*4882a593Smuzhiyun 0, 650*4882a593Smuzhiyun /* 651*4882a593Smuzhiyun * Terminate cycle ... 652*4882a593Smuzhiyun */ 653*4882a593Smuzhiyun SCR_CLR (SCR_ACK|SCR_ATN), 654*4882a593Smuzhiyun 0, 655*4882a593Smuzhiyun /* 656*4882a593Smuzhiyun * ... and wait for the disconnect. 657*4882a593Smuzhiyun */ 658*4882a593Smuzhiyun SCR_WAIT_DISC, 659*4882a593Smuzhiyun 0, 660*4882a593Smuzhiyun }/*-------------------------< COMPLETE2 >------------------------*/,{ 661*4882a593Smuzhiyun /* 662*4882a593Smuzhiyun * Save host status. 663*4882a593Smuzhiyun */ 664*4882a593Smuzhiyun SCR_COPY (4), 665*4882a593Smuzhiyun RADDR_1 (scr0), 666*4882a593Smuzhiyun HADDR_1 (ccb_head.status), 667*4882a593Smuzhiyun /* 668*4882a593Smuzhiyun * Move back the CCB header using self-modifying 669*4882a593Smuzhiyun * SCRIPTS. 670*4882a593Smuzhiyun */ 671*4882a593Smuzhiyun SCR_COPY (4), 672*4882a593Smuzhiyun RADDR_1 (dsa), 673*4882a593Smuzhiyun PADDR_A (_sms_a40), 674*4882a593Smuzhiyun SCR_COPY (sizeof(struct sym_ccbh)), 675*4882a593Smuzhiyun HADDR_1 (ccb_head), 676*4882a593Smuzhiyun }/*-------------------------< _SMS_A40 >-------------------------*/,{ 677*4882a593Smuzhiyun 0, 678*4882a593Smuzhiyun /* 679*4882a593Smuzhiyun * Some bridges may reorder DMA writes to memory. 680*4882a593Smuzhiyun * We donnot want the CPU to deal with completions 681*4882a593Smuzhiyun * without all the posted write having been flushed 682*4882a593Smuzhiyun * to memory. This DUMMY READ should flush posted 683*4882a593Smuzhiyun * buffers prior to the CPU having to deal with 684*4882a593Smuzhiyun * completions. 685*4882a593Smuzhiyun */ 686*4882a593Smuzhiyun SCR_COPY (4), /* DUMMY READ */ 687*4882a593Smuzhiyun HADDR_1 (ccb_head.status), 688*4882a593Smuzhiyun RADDR_1 (scr0), 689*4882a593Smuzhiyun /* 690*4882a593Smuzhiyun * If command resulted in not GOOD status, 691*4882a593Smuzhiyun * call the C code if needed. 692*4882a593Smuzhiyun */ 693*4882a593Smuzhiyun SCR_FROM_REG (SS_REG), 694*4882a593Smuzhiyun 0, 695*4882a593Smuzhiyun SCR_CALL ^ IFFALSE (DATA (S_GOOD)), 696*4882a593Smuzhiyun PADDR_B (bad_status), 697*4882a593Smuzhiyun /* 698*4882a593Smuzhiyun * If we performed an auto-sense, call 699*4882a593Smuzhiyun * the C code to synchronyze task aborts 700*4882a593Smuzhiyun * with UNIT ATTENTION conditions. 701*4882a593Smuzhiyun */ 702*4882a593Smuzhiyun SCR_FROM_REG (HF_REG), 703*4882a593Smuzhiyun 0, 704*4882a593Smuzhiyun SCR_JUMP ^ IFFALSE (MASK (0 ,(HF_SENSE|HF_EXT_ERR))), 705*4882a593Smuzhiyun PADDR_A (complete_error), 706*4882a593Smuzhiyun }/*-------------------------< DONE >-----------------------------*/,{ 707*4882a593Smuzhiyun /* 708*4882a593Smuzhiyun * Copy the DSA to the DONE QUEUE and 709*4882a593Smuzhiyun * signal completion to the host. 710*4882a593Smuzhiyun * If we are interrupted between DONE 711*4882a593Smuzhiyun * and DONE_END, we must reset, otherwise 712*4882a593Smuzhiyun * the completed CCB may be lost. 713*4882a593Smuzhiyun */ 714*4882a593Smuzhiyun SCR_COPY (4), 715*4882a593Smuzhiyun PADDR_B (done_pos), 716*4882a593Smuzhiyun PADDR_A (_sms_a50), 717*4882a593Smuzhiyun SCR_COPY (4), 718*4882a593Smuzhiyun RADDR_1 (dsa), 719*4882a593Smuzhiyun }/*-------------------------< _SMS_A50 >-------------------------*/,{ 720*4882a593Smuzhiyun 0, 721*4882a593Smuzhiyun SCR_COPY (4), 722*4882a593Smuzhiyun PADDR_B (done_pos), 723*4882a593Smuzhiyun PADDR_A (_sms_a60), 724*4882a593Smuzhiyun /* 725*4882a593Smuzhiyun * The instruction below reads the DONE QUEUE next 726*4882a593Smuzhiyun * free position from memory. 727*4882a593Smuzhiyun * In addition it ensures that all PCI posted writes 728*4882a593Smuzhiyun * are flushed and so the DSA value of the done 729*4882a593Smuzhiyun * CCB is visible by the CPU before INTFLY is raised. 730*4882a593Smuzhiyun */ 731*4882a593Smuzhiyun SCR_COPY (8), 732*4882a593Smuzhiyun }/*-------------------------< _SMS_A60 >-------------------------*/,{ 733*4882a593Smuzhiyun 0, 734*4882a593Smuzhiyun PADDR_B (prev_done), 735*4882a593Smuzhiyun }/*-------------------------< DONE_END >-------------------------*/,{ 736*4882a593Smuzhiyun SCR_INT_FLY, 737*4882a593Smuzhiyun 0, 738*4882a593Smuzhiyun SCR_JUMP, 739*4882a593Smuzhiyun PADDR_A (start), 740*4882a593Smuzhiyun }/*-------------------------< COMPLETE_ERROR >-------------------*/,{ 741*4882a593Smuzhiyun SCR_COPY (4), 742*4882a593Smuzhiyun PADDR_B (startpos), 743*4882a593Smuzhiyun RADDR_1 (scratcha), 744*4882a593Smuzhiyun SCR_INT, 745*4882a593Smuzhiyun SIR_COMPLETE_ERROR, 746*4882a593Smuzhiyun }/*-------------------------< SAVE_DP >--------------------------*/,{ 747*4882a593Smuzhiyun /* 748*4882a593Smuzhiyun * Clear ACK immediately. 749*4882a593Smuzhiyun * No need to delay it. 750*4882a593Smuzhiyun */ 751*4882a593Smuzhiyun SCR_CLR (SCR_ACK), 752*4882a593Smuzhiyun 0, 753*4882a593Smuzhiyun /* 754*4882a593Smuzhiyun * Keep track we received a SAVE DP, so 755*4882a593Smuzhiyun * we will switch to the other PM context 756*4882a593Smuzhiyun * on the next PM since the DP may point 757*4882a593Smuzhiyun * to the current PM context. 758*4882a593Smuzhiyun */ 759*4882a593Smuzhiyun SCR_REG_REG (HF_REG, SCR_OR, HF_DP_SAVED), 760*4882a593Smuzhiyun 0, 761*4882a593Smuzhiyun /* 762*4882a593Smuzhiyun * SAVE_DP message: 763*4882a593Smuzhiyun * Copy LASTP to SAVEP. 764*4882a593Smuzhiyun */ 765*4882a593Smuzhiyun SCR_COPY (4), 766*4882a593Smuzhiyun HADDR_1 (ccb_head.lastp), 767*4882a593Smuzhiyun HADDR_1 (ccb_head.savep), 768*4882a593Smuzhiyun /* 769*4882a593Smuzhiyun * Anticipate the MESSAGE PHASE for 770*4882a593Smuzhiyun * the DISCONNECT message. 771*4882a593Smuzhiyun */ 772*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)), 773*4882a593Smuzhiyun PADDR_A (msg_in), 774*4882a593Smuzhiyun SCR_JUMP, 775*4882a593Smuzhiyun PADDR_A (dispatch), 776*4882a593Smuzhiyun }/*-------------------------< RESTORE_DP >-----------------------*/,{ 777*4882a593Smuzhiyun /* 778*4882a593Smuzhiyun * Clear ACK immediately. 779*4882a593Smuzhiyun * No need to delay it. 780*4882a593Smuzhiyun */ 781*4882a593Smuzhiyun SCR_CLR (SCR_ACK), 782*4882a593Smuzhiyun 0, 783*4882a593Smuzhiyun /* 784*4882a593Smuzhiyun * Copy SAVEP to LASTP. 785*4882a593Smuzhiyun */ 786*4882a593Smuzhiyun SCR_COPY (4), 787*4882a593Smuzhiyun HADDR_1 (ccb_head.savep), 788*4882a593Smuzhiyun HADDR_1 (ccb_head.lastp), 789*4882a593Smuzhiyun SCR_JUMP, 790*4882a593Smuzhiyun PADDR_A (dispatch), 791*4882a593Smuzhiyun }/*-------------------------< DISCONNECT >-----------------------*/,{ 792*4882a593Smuzhiyun /* 793*4882a593Smuzhiyun * DISCONNECTing ... 794*4882a593Smuzhiyun * 795*4882a593Smuzhiyun * disable the "unexpected disconnect" feature, 796*4882a593Smuzhiyun * and remove the ACK signal. 797*4882a593Smuzhiyun */ 798*4882a593Smuzhiyun SCR_REG_REG (scntl2, SCR_AND, 0x7f), 799*4882a593Smuzhiyun 0, 800*4882a593Smuzhiyun SCR_CLR (SCR_ACK|SCR_ATN), 801*4882a593Smuzhiyun 0, 802*4882a593Smuzhiyun /* 803*4882a593Smuzhiyun * Wait for the disconnect. 804*4882a593Smuzhiyun */ 805*4882a593Smuzhiyun SCR_WAIT_DISC, 806*4882a593Smuzhiyun 0, 807*4882a593Smuzhiyun /* 808*4882a593Smuzhiyun * Status is: DISCONNECTED. 809*4882a593Smuzhiyun */ 810*4882a593Smuzhiyun SCR_LOAD_REG (HS_REG, HS_DISCONNECT), 811*4882a593Smuzhiyun 0, 812*4882a593Smuzhiyun /* 813*4882a593Smuzhiyun * Save host status. 814*4882a593Smuzhiyun */ 815*4882a593Smuzhiyun SCR_COPY (4), 816*4882a593Smuzhiyun RADDR_1 (scr0), 817*4882a593Smuzhiyun HADDR_1 (ccb_head.status), 818*4882a593Smuzhiyun }/*-------------------------< DISCONNECT2 >----------------------*/,{ 819*4882a593Smuzhiyun /* 820*4882a593Smuzhiyun * Move back the CCB header using self-modifying 821*4882a593Smuzhiyun * SCRIPTS. 822*4882a593Smuzhiyun */ 823*4882a593Smuzhiyun SCR_COPY (4), 824*4882a593Smuzhiyun RADDR_1 (dsa), 825*4882a593Smuzhiyun PADDR_A (_sms_a65), 826*4882a593Smuzhiyun SCR_COPY (sizeof(struct sym_ccbh)), 827*4882a593Smuzhiyun HADDR_1 (ccb_head), 828*4882a593Smuzhiyun }/*-------------------------< _SMS_A65 >-------------------------*/,{ 829*4882a593Smuzhiyun 0, 830*4882a593Smuzhiyun SCR_JUMP, 831*4882a593Smuzhiyun PADDR_A (start), 832*4882a593Smuzhiyun }/*-------------------------< IDLE >-----------------------------*/,{ 833*4882a593Smuzhiyun /* 834*4882a593Smuzhiyun * Nothing to do? 835*4882a593Smuzhiyun * Switch the LED off and wait for reselect. 836*4882a593Smuzhiyun * Will be patched with a NO_OP if LED 837*4882a593Smuzhiyun * not needed or not desired. 838*4882a593Smuzhiyun */ 839*4882a593Smuzhiyun SCR_REG_REG (gpreg, SCR_OR, 0x01), 840*4882a593Smuzhiyun 0, 841*4882a593Smuzhiyun #ifdef SYM_CONF_IARB_SUPPORT 842*4882a593Smuzhiyun SCR_JUMPR, 843*4882a593Smuzhiyun 8, 844*4882a593Smuzhiyun #endif 845*4882a593Smuzhiyun }/*-------------------------< UNGETJOB >-------------------------*/,{ 846*4882a593Smuzhiyun #ifdef SYM_CONF_IARB_SUPPORT 847*4882a593Smuzhiyun /* 848*4882a593Smuzhiyun * Set IMMEDIATE ARBITRATION, for the next time. 849*4882a593Smuzhiyun * This will give us better chance to win arbitration 850*4882a593Smuzhiyun * for the job we just wanted to do. 851*4882a593Smuzhiyun */ 852*4882a593Smuzhiyun SCR_REG_REG (scntl1, SCR_OR, IARB), 853*4882a593Smuzhiyun 0, 854*4882a593Smuzhiyun #endif 855*4882a593Smuzhiyun /* 856*4882a593Smuzhiyun * We are not able to restart the SCRIPTS if we are 857*4882a593Smuzhiyun * interrupted and these instruction haven't been 858*4882a593Smuzhiyun * all executed. BTW, this is very unlikely to 859*4882a593Smuzhiyun * happen, but we check that from the C code. 860*4882a593Smuzhiyun */ 861*4882a593Smuzhiyun SCR_LOAD_REG (dsa, 0xff), 862*4882a593Smuzhiyun 0, 863*4882a593Smuzhiyun SCR_COPY (4), 864*4882a593Smuzhiyun RADDR_1 (scratcha), 865*4882a593Smuzhiyun PADDR_B (startpos), 866*4882a593Smuzhiyun }/*-------------------------< RESELECT >-------------------------*/,{ 867*4882a593Smuzhiyun #ifdef SYM_CONF_TARGET_ROLE_SUPPORT 868*4882a593Smuzhiyun /* 869*4882a593Smuzhiyun * Make sure we are in initiator mode. 870*4882a593Smuzhiyun */ 871*4882a593Smuzhiyun SCR_CLR (SCR_TRG), 872*4882a593Smuzhiyun 0, 873*4882a593Smuzhiyun #endif 874*4882a593Smuzhiyun /* 875*4882a593Smuzhiyun * Sleep waiting for a reselection. 876*4882a593Smuzhiyun */ 877*4882a593Smuzhiyun SCR_WAIT_RESEL, 878*4882a593Smuzhiyun PADDR_A(start), 879*4882a593Smuzhiyun }/*-------------------------< RESELECTED >-----------------------*/,{ 880*4882a593Smuzhiyun /* 881*4882a593Smuzhiyun * Switch the LED on. 882*4882a593Smuzhiyun * Will be patched with a NO_OP if LED 883*4882a593Smuzhiyun * not needed or not desired. 884*4882a593Smuzhiyun */ 885*4882a593Smuzhiyun SCR_REG_REG (gpreg, SCR_AND, 0xfe), 886*4882a593Smuzhiyun 0, 887*4882a593Smuzhiyun /* 888*4882a593Smuzhiyun * load the target id into the sdid 889*4882a593Smuzhiyun */ 890*4882a593Smuzhiyun SCR_REG_SFBR (ssid, SCR_AND, 0x8F), 891*4882a593Smuzhiyun 0, 892*4882a593Smuzhiyun SCR_TO_REG (sdid), 893*4882a593Smuzhiyun 0, 894*4882a593Smuzhiyun /* 895*4882a593Smuzhiyun * Load the target control block address 896*4882a593Smuzhiyun */ 897*4882a593Smuzhiyun SCR_COPY (4), 898*4882a593Smuzhiyun PADDR_B (targtbl), 899*4882a593Smuzhiyun RADDR_1 (dsa), 900*4882a593Smuzhiyun SCR_SFBR_REG (dsa, SCR_SHL, 0), 901*4882a593Smuzhiyun 0, 902*4882a593Smuzhiyun SCR_REG_REG (dsa, SCR_SHL, 0), 903*4882a593Smuzhiyun 0, 904*4882a593Smuzhiyun SCR_REG_REG (dsa, SCR_AND, 0x3c), 905*4882a593Smuzhiyun 0, 906*4882a593Smuzhiyun SCR_COPY (4), 907*4882a593Smuzhiyun RADDR_1 (dsa), 908*4882a593Smuzhiyun PADDR_A (_sms_a70), 909*4882a593Smuzhiyun SCR_COPY (4), 910*4882a593Smuzhiyun }/*-------------------------< _SMS_A70 >-------------------------*/,{ 911*4882a593Smuzhiyun 0, 912*4882a593Smuzhiyun RADDR_1 (dsa), 913*4882a593Smuzhiyun /* 914*4882a593Smuzhiyun * Copy the TCB header to a fixed place in 915*4882a593Smuzhiyun * the HCB. 916*4882a593Smuzhiyun */ 917*4882a593Smuzhiyun SCR_COPY (4), 918*4882a593Smuzhiyun RADDR_1 (dsa), 919*4882a593Smuzhiyun PADDR_A (_sms_a80), 920*4882a593Smuzhiyun SCR_COPY (sizeof(struct sym_tcbh)), 921*4882a593Smuzhiyun }/*-------------------------< _SMS_A80 >-------------------------*/,{ 922*4882a593Smuzhiyun 0, 923*4882a593Smuzhiyun HADDR_1 (tcb_head), 924*4882a593Smuzhiyun /* 925*4882a593Smuzhiyun * We expect MESSAGE IN phase. 926*4882a593Smuzhiyun * If not, get help from the C code. 927*4882a593Smuzhiyun */ 928*4882a593Smuzhiyun SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)), 929*4882a593Smuzhiyun SIR_RESEL_NO_MSG_IN, 930*4882a593Smuzhiyun }/*-------------------------< RESELECTED1 >----------------------*/,{ 931*4882a593Smuzhiyun /* 932*4882a593Smuzhiyun * Load the synchronous transfer registers. 933*4882a593Smuzhiyun */ 934*4882a593Smuzhiyun SCR_COPY (1), 935*4882a593Smuzhiyun HADDR_1 (tcb_head.wval), 936*4882a593Smuzhiyun RADDR_1 (scntl3), 937*4882a593Smuzhiyun SCR_COPY (1), 938*4882a593Smuzhiyun HADDR_1 (tcb_head.sval), 939*4882a593Smuzhiyun RADDR_1 (sxfer), 940*4882a593Smuzhiyun /* 941*4882a593Smuzhiyun * Get the IDENTIFY message. 942*4882a593Smuzhiyun */ 943*4882a593Smuzhiyun SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 944*4882a593Smuzhiyun HADDR_1 (msgin), 945*4882a593Smuzhiyun /* 946*4882a593Smuzhiyun * If IDENTIFY LUN #0, use a faster path 947*4882a593Smuzhiyun * to find the LCB structure. 948*4882a593Smuzhiyun */ 949*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (MASK (0x80, 0xbf)), 950*4882a593Smuzhiyun PADDR_A (resel_lun0), 951*4882a593Smuzhiyun /* 952*4882a593Smuzhiyun * If message isn't an IDENTIFY, 953*4882a593Smuzhiyun * tell the C code about. 954*4882a593Smuzhiyun */ 955*4882a593Smuzhiyun SCR_INT ^ IFFALSE (MASK (0x80, 0x80)), 956*4882a593Smuzhiyun SIR_RESEL_NO_IDENTIFY, 957*4882a593Smuzhiyun /* 958*4882a593Smuzhiyun * It is an IDENTIFY message, 959*4882a593Smuzhiyun * Load the LUN control block address. 960*4882a593Smuzhiyun */ 961*4882a593Smuzhiyun SCR_COPY (4), 962*4882a593Smuzhiyun HADDR_1 (tcb_head.luntbl_sa), 963*4882a593Smuzhiyun RADDR_1 (dsa), 964*4882a593Smuzhiyun SCR_SFBR_REG (dsa, SCR_SHL, 0), 965*4882a593Smuzhiyun 0, 966*4882a593Smuzhiyun SCR_REG_REG (dsa, SCR_SHL, 0), 967*4882a593Smuzhiyun 0, 968*4882a593Smuzhiyun SCR_REG_REG (dsa, SCR_AND, 0xfc), 969*4882a593Smuzhiyun 0, 970*4882a593Smuzhiyun SCR_COPY (4), 971*4882a593Smuzhiyun RADDR_1 (dsa), 972*4882a593Smuzhiyun PADDR_A (_sms_a90), 973*4882a593Smuzhiyun SCR_COPY (4), 974*4882a593Smuzhiyun }/*-------------------------< _SMS_A90 >-------------------------*/,{ 975*4882a593Smuzhiyun 0, 976*4882a593Smuzhiyun RADDR_1 (dsa), 977*4882a593Smuzhiyun SCR_JUMPR, 978*4882a593Smuzhiyun 12, 979*4882a593Smuzhiyun }/*-------------------------< RESEL_LUN0 >-----------------------*/,{ 980*4882a593Smuzhiyun /* 981*4882a593Smuzhiyun * LUN 0 special case (but usual one :)) 982*4882a593Smuzhiyun */ 983*4882a593Smuzhiyun SCR_COPY (4), 984*4882a593Smuzhiyun HADDR_1 (tcb_head.lun0_sa), 985*4882a593Smuzhiyun RADDR_1 (dsa), 986*4882a593Smuzhiyun /* 987*4882a593Smuzhiyun * Jump indirectly to the reselect action for this LUN. 988*4882a593Smuzhiyun * (lcb.head.resel_sa assumed at offset zero of lcb). 989*4882a593Smuzhiyun */ 990*4882a593Smuzhiyun SCR_COPY (4), 991*4882a593Smuzhiyun RADDR_1 (dsa), 992*4882a593Smuzhiyun PADDR_A (_sms_a100), 993*4882a593Smuzhiyun SCR_COPY (4), 994*4882a593Smuzhiyun }/*-------------------------< _SMS_A100 >------------------------*/,{ 995*4882a593Smuzhiyun 0, 996*4882a593Smuzhiyun RADDR_1 (temp), 997*4882a593Smuzhiyun SCR_RETURN, 998*4882a593Smuzhiyun 0, 999*4882a593Smuzhiyun /* In normal situations, we jump to RESEL_TAG or RESEL_NO_TAG */ 1000*4882a593Smuzhiyun }/*-------------------------< RESEL_TAG >------------------------*/,{ 1001*4882a593Smuzhiyun /* 1002*4882a593Smuzhiyun * ACK the IDENTIFY previously received. 1003*4882a593Smuzhiyun */ 1004*4882a593Smuzhiyun SCR_CLR (SCR_ACK), 1005*4882a593Smuzhiyun 0, 1006*4882a593Smuzhiyun /* 1007*4882a593Smuzhiyun * It shall be a tagged command. 1008*4882a593Smuzhiyun * Read SIMPLE+TAG. 1009*4882a593Smuzhiyun * The C code will deal with errors. 1010*4882a593Smuzhiyun * Aggressive optimization, isn't it? :) 1011*4882a593Smuzhiyun */ 1012*4882a593Smuzhiyun SCR_MOVE_ABS (2) ^ SCR_MSG_IN, 1013*4882a593Smuzhiyun HADDR_1 (msgin), 1014*4882a593Smuzhiyun /* 1015*4882a593Smuzhiyun * Copy the LCB header to a fixed place in 1016*4882a593Smuzhiyun * the HCB using self-modifying SCRIPTS. 1017*4882a593Smuzhiyun */ 1018*4882a593Smuzhiyun SCR_COPY (4), 1019*4882a593Smuzhiyun RADDR_1 (dsa), 1020*4882a593Smuzhiyun PADDR_A (_sms_a110), 1021*4882a593Smuzhiyun SCR_COPY (sizeof(struct sym_lcbh)), 1022*4882a593Smuzhiyun }/*-------------------------< _SMS_A110 >------------------------*/,{ 1023*4882a593Smuzhiyun 0, 1024*4882a593Smuzhiyun HADDR_1 (lcb_head), 1025*4882a593Smuzhiyun /* 1026*4882a593Smuzhiyun * Load the pointer to the tagged task 1027*4882a593Smuzhiyun * table for this LUN. 1028*4882a593Smuzhiyun */ 1029*4882a593Smuzhiyun SCR_COPY (4), 1030*4882a593Smuzhiyun HADDR_1 (lcb_head.itlq_tbl_sa), 1031*4882a593Smuzhiyun RADDR_1 (dsa), 1032*4882a593Smuzhiyun /* 1033*4882a593Smuzhiyun * The SIDL still contains the TAG value. 1034*4882a593Smuzhiyun * Aggressive optimization, isn't it? :):) 1035*4882a593Smuzhiyun */ 1036*4882a593Smuzhiyun SCR_REG_SFBR (sidl, SCR_SHL, 0), 1037*4882a593Smuzhiyun 0, 1038*4882a593Smuzhiyun #if SYM_CONF_MAX_TASK*4 > 512 1039*4882a593Smuzhiyun SCR_JUMPR ^ IFFALSE (CARRYSET), 1040*4882a593Smuzhiyun 8, 1041*4882a593Smuzhiyun SCR_REG_REG (dsa1, SCR_OR, 2), 1042*4882a593Smuzhiyun 0, 1043*4882a593Smuzhiyun SCR_REG_REG (sfbr, SCR_SHL, 0), 1044*4882a593Smuzhiyun 0, 1045*4882a593Smuzhiyun SCR_JUMPR ^ IFFALSE (CARRYSET), 1046*4882a593Smuzhiyun 8, 1047*4882a593Smuzhiyun SCR_REG_REG (dsa1, SCR_OR, 1), 1048*4882a593Smuzhiyun 0, 1049*4882a593Smuzhiyun #elif SYM_CONF_MAX_TASK*4 > 256 1050*4882a593Smuzhiyun SCR_JUMPR ^ IFFALSE (CARRYSET), 1051*4882a593Smuzhiyun 8, 1052*4882a593Smuzhiyun SCR_REG_REG (dsa1, SCR_OR, 1), 1053*4882a593Smuzhiyun 0, 1054*4882a593Smuzhiyun #endif 1055*4882a593Smuzhiyun /* 1056*4882a593Smuzhiyun * Retrieve the DSA of this task. 1057*4882a593Smuzhiyun * JUMP indirectly to the restart point of the CCB. 1058*4882a593Smuzhiyun */ 1059*4882a593Smuzhiyun SCR_SFBR_REG (dsa, SCR_AND, 0xfc), 1060*4882a593Smuzhiyun 0, 1061*4882a593Smuzhiyun SCR_COPY (4), 1062*4882a593Smuzhiyun RADDR_1 (dsa), 1063*4882a593Smuzhiyun PADDR_A (_sms_a120), 1064*4882a593Smuzhiyun SCR_COPY (4), 1065*4882a593Smuzhiyun }/*-------------------------< _SMS_A120 >------------------------*/,{ 1066*4882a593Smuzhiyun 0, 1067*4882a593Smuzhiyun RADDR_1 (dsa), 1068*4882a593Smuzhiyun }/*-------------------------< RESEL_GO >-------------------------*/,{ 1069*4882a593Smuzhiyun SCR_COPY (4), 1070*4882a593Smuzhiyun RADDR_1 (dsa), 1071*4882a593Smuzhiyun PADDR_A (_sms_a130), 1072*4882a593Smuzhiyun /* 1073*4882a593Smuzhiyun * Move 'ccb.phys.head.go' action to 1074*4882a593Smuzhiyun * scratch/scratch1. So scratch1 will 1075*4882a593Smuzhiyun * contain the 'restart' field of the 1076*4882a593Smuzhiyun * 'go' structure. 1077*4882a593Smuzhiyun */ 1078*4882a593Smuzhiyun SCR_COPY (8), 1079*4882a593Smuzhiyun }/*-------------------------< _SMS_A130 >------------------------*/,{ 1080*4882a593Smuzhiyun 0, 1081*4882a593Smuzhiyun PADDR_B (scratch), 1082*4882a593Smuzhiyun SCR_COPY (4), 1083*4882a593Smuzhiyun PADDR_B (scratch1), /* phys.head.go.restart */ 1084*4882a593Smuzhiyun RADDR_1 (temp), 1085*4882a593Smuzhiyun SCR_RETURN, 1086*4882a593Smuzhiyun 0, 1087*4882a593Smuzhiyun /* In normal situations we branch to RESEL_DSA */ 1088*4882a593Smuzhiyun }/*-------------------------< RESEL_DSA >------------------------*/,{ 1089*4882a593Smuzhiyun /* 1090*4882a593Smuzhiyun * ACK the IDENTIFY or TAG previously received. 1091*4882a593Smuzhiyun */ 1092*4882a593Smuzhiyun SCR_CLR (SCR_ACK), 1093*4882a593Smuzhiyun 0, 1094*4882a593Smuzhiyun }/*-------------------------< RESEL_DSA1 >-----------------------*/,{ 1095*4882a593Smuzhiyun /* 1096*4882a593Smuzhiyun * Copy the CCB header to a fixed location 1097*4882a593Smuzhiyun * in the HCB using self-modifying SCRIPTS. 1098*4882a593Smuzhiyun */ 1099*4882a593Smuzhiyun SCR_COPY (4), 1100*4882a593Smuzhiyun RADDR_1 (dsa), 1101*4882a593Smuzhiyun PADDR_A (_sms_a140), 1102*4882a593Smuzhiyun SCR_COPY (sizeof(struct sym_ccbh)), 1103*4882a593Smuzhiyun }/*-------------------------< _SMS_A140 >------------------------*/,{ 1104*4882a593Smuzhiyun 0, 1105*4882a593Smuzhiyun HADDR_1 (ccb_head), 1106*4882a593Smuzhiyun /* 1107*4882a593Smuzhiyun * Initialize the status register 1108*4882a593Smuzhiyun */ 1109*4882a593Smuzhiyun SCR_COPY (4), 1110*4882a593Smuzhiyun HADDR_1 (ccb_head.status), 1111*4882a593Smuzhiyun RADDR_1 (scr0), 1112*4882a593Smuzhiyun /* 1113*4882a593Smuzhiyun * Jump to dispatcher. 1114*4882a593Smuzhiyun */ 1115*4882a593Smuzhiyun SCR_JUMP, 1116*4882a593Smuzhiyun PADDR_A (dispatch), 1117*4882a593Smuzhiyun }/*-------------------------< RESEL_NO_TAG >---------------------*/,{ 1118*4882a593Smuzhiyun /* 1119*4882a593Smuzhiyun * Copy the LCB header to a fixed place in 1120*4882a593Smuzhiyun * the HCB using self-modifying SCRIPTS. 1121*4882a593Smuzhiyun */ 1122*4882a593Smuzhiyun SCR_COPY (4), 1123*4882a593Smuzhiyun RADDR_1 (dsa), 1124*4882a593Smuzhiyun PADDR_A (_sms_a145), 1125*4882a593Smuzhiyun SCR_COPY (sizeof(struct sym_lcbh)), 1126*4882a593Smuzhiyun }/*-------------------------< _SMS_A145 >------------------------*/,{ 1127*4882a593Smuzhiyun 0, 1128*4882a593Smuzhiyun HADDR_1 (lcb_head), 1129*4882a593Smuzhiyun /* 1130*4882a593Smuzhiyun * Load the DSA with the unique ITL task. 1131*4882a593Smuzhiyun */ 1132*4882a593Smuzhiyun SCR_COPY (4), 1133*4882a593Smuzhiyun HADDR_1 (lcb_head.itl_task_sa), 1134*4882a593Smuzhiyun RADDR_1 (dsa), 1135*4882a593Smuzhiyun SCR_JUMP, 1136*4882a593Smuzhiyun PADDR_A (resel_go), 1137*4882a593Smuzhiyun }/*-------------------------< DATA_IN >--------------------------*/,{ 1138*4882a593Smuzhiyun /* 1139*4882a593Smuzhiyun * Because the size depends on the 1140*4882a593Smuzhiyun * #define SYM_CONF_MAX_SG parameter, 1141*4882a593Smuzhiyun * it is filled in at runtime. 1142*4882a593Smuzhiyun * 1143*4882a593Smuzhiyun * ##===========< i=0; i<SYM_CONF_MAX_SG >========= 1144*4882a593Smuzhiyun * || SCR_CHMOV_TBL ^ SCR_DATA_IN, 1145*4882a593Smuzhiyun * || offsetof (struct sym_dsb, data[ i]), 1146*4882a593Smuzhiyun * ##========================================== 1147*4882a593Smuzhiyun */ 1148*4882a593Smuzhiyun 0 1149*4882a593Smuzhiyun }/*-------------------------< DATA_IN2 >-------------------------*/,{ 1150*4882a593Smuzhiyun SCR_CALL, 1151*4882a593Smuzhiyun PADDR_A (datai_done), 1152*4882a593Smuzhiyun SCR_JUMP, 1153*4882a593Smuzhiyun PADDR_B (data_ovrun), 1154*4882a593Smuzhiyun }/*-------------------------< DATA_OUT >-------------------------*/,{ 1155*4882a593Smuzhiyun /* 1156*4882a593Smuzhiyun * Because the size depends on the 1157*4882a593Smuzhiyun * #define SYM_CONF_MAX_SG parameter, 1158*4882a593Smuzhiyun * it is filled in at runtime. 1159*4882a593Smuzhiyun * 1160*4882a593Smuzhiyun * ##===========< i=0; i<SYM_CONF_MAX_SG >========= 1161*4882a593Smuzhiyun * || SCR_CHMOV_TBL ^ SCR_DATA_OUT, 1162*4882a593Smuzhiyun * || offsetof (struct sym_dsb, data[ i]), 1163*4882a593Smuzhiyun * ##========================================== 1164*4882a593Smuzhiyun */ 1165*4882a593Smuzhiyun 0 1166*4882a593Smuzhiyun }/*-------------------------< DATA_OUT2 >------------------------*/,{ 1167*4882a593Smuzhiyun SCR_CALL, 1168*4882a593Smuzhiyun PADDR_A (datao_done), 1169*4882a593Smuzhiyun SCR_JUMP, 1170*4882a593Smuzhiyun PADDR_B (data_ovrun), 1171*4882a593Smuzhiyun }/*-------------------------< PM0_DATA >-------------------------*/,{ 1172*4882a593Smuzhiyun /* 1173*4882a593Smuzhiyun * Read our host flags to SFBR, so we will be able 1174*4882a593Smuzhiyun * to check against the data direction we expect. 1175*4882a593Smuzhiyun */ 1176*4882a593Smuzhiyun SCR_FROM_REG (HF_REG), 1177*4882a593Smuzhiyun 0, 1178*4882a593Smuzhiyun /* 1179*4882a593Smuzhiyun * Check against actual DATA PHASE. 1180*4882a593Smuzhiyun */ 1181*4882a593Smuzhiyun SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)), 1182*4882a593Smuzhiyun PADDR_A (pm0_data_out), 1183*4882a593Smuzhiyun /* 1184*4882a593Smuzhiyun * Actual phase is DATA IN. 1185*4882a593Smuzhiyun * Check against expected direction. 1186*4882a593Smuzhiyun */ 1187*4882a593Smuzhiyun SCR_JUMP ^ IFFALSE (MASK (HF_DATA_IN, HF_DATA_IN)), 1188*4882a593Smuzhiyun PADDR_B (data_ovrun), 1189*4882a593Smuzhiyun /* 1190*4882a593Smuzhiyun * Keep track we are moving data from the 1191*4882a593Smuzhiyun * PM0 DATA mini-script. 1192*4882a593Smuzhiyun */ 1193*4882a593Smuzhiyun SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM0), 1194*4882a593Smuzhiyun 0, 1195*4882a593Smuzhiyun /* 1196*4882a593Smuzhiyun * Move the data to memory. 1197*4882a593Smuzhiyun */ 1198*4882a593Smuzhiyun SCR_CHMOV_TBL ^ SCR_DATA_IN, 1199*4882a593Smuzhiyun offsetof (struct sym_ccb, phys.pm0.sg), 1200*4882a593Smuzhiyun SCR_JUMP, 1201*4882a593Smuzhiyun PADDR_A (pm0_data_end), 1202*4882a593Smuzhiyun }/*-------------------------< PM0_DATA_OUT >---------------------*/,{ 1203*4882a593Smuzhiyun /* 1204*4882a593Smuzhiyun * Actual phase is DATA OUT. 1205*4882a593Smuzhiyun * Check against expected direction. 1206*4882a593Smuzhiyun */ 1207*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (MASK (HF_DATA_IN, HF_DATA_IN)), 1208*4882a593Smuzhiyun PADDR_B (data_ovrun), 1209*4882a593Smuzhiyun /* 1210*4882a593Smuzhiyun * Keep track we are moving data from the 1211*4882a593Smuzhiyun * PM0 DATA mini-script. 1212*4882a593Smuzhiyun */ 1213*4882a593Smuzhiyun SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM0), 1214*4882a593Smuzhiyun 0, 1215*4882a593Smuzhiyun /* 1216*4882a593Smuzhiyun * Move the data from memory. 1217*4882a593Smuzhiyun */ 1218*4882a593Smuzhiyun SCR_CHMOV_TBL ^ SCR_DATA_OUT, 1219*4882a593Smuzhiyun offsetof (struct sym_ccb, phys.pm0.sg), 1220*4882a593Smuzhiyun }/*-------------------------< PM0_DATA_END >---------------------*/,{ 1221*4882a593Smuzhiyun /* 1222*4882a593Smuzhiyun * Clear the flag that told we were moving 1223*4882a593Smuzhiyun * data from the PM0 DATA mini-script. 1224*4882a593Smuzhiyun */ 1225*4882a593Smuzhiyun SCR_REG_REG (HF_REG, SCR_AND, (~HF_IN_PM0)), 1226*4882a593Smuzhiyun 0, 1227*4882a593Smuzhiyun /* 1228*4882a593Smuzhiyun * Return to the previous DATA script which 1229*4882a593Smuzhiyun * is guaranteed by design (if no bug) to be 1230*4882a593Smuzhiyun * the main DATA script for this transfer. 1231*4882a593Smuzhiyun */ 1232*4882a593Smuzhiyun SCR_COPY (4), 1233*4882a593Smuzhiyun RADDR_1 (dsa), 1234*4882a593Smuzhiyun RADDR_1 (scratcha), 1235*4882a593Smuzhiyun SCR_REG_REG (scratcha, SCR_ADD, offsetof (struct sym_ccb,phys.pm0.ret)), 1236*4882a593Smuzhiyun 0, 1237*4882a593Smuzhiyun }/*-------------------------< PM_DATA_END >----------------------*/,{ 1238*4882a593Smuzhiyun SCR_COPY (4), 1239*4882a593Smuzhiyun RADDR_1 (scratcha), 1240*4882a593Smuzhiyun PADDR_A (_sms_a150), 1241*4882a593Smuzhiyun SCR_COPY (4), 1242*4882a593Smuzhiyun }/*-------------------------< _SMS_A150 >------------------------*/,{ 1243*4882a593Smuzhiyun 0, 1244*4882a593Smuzhiyun RADDR_1 (temp), 1245*4882a593Smuzhiyun SCR_RETURN, 1246*4882a593Smuzhiyun 0, 1247*4882a593Smuzhiyun }/*-------------------------< PM1_DATA >-------------------------*/,{ 1248*4882a593Smuzhiyun /* 1249*4882a593Smuzhiyun * Read our host flags to SFBR, so we will be able 1250*4882a593Smuzhiyun * to check against the data direction we expect. 1251*4882a593Smuzhiyun */ 1252*4882a593Smuzhiyun SCR_FROM_REG (HF_REG), 1253*4882a593Smuzhiyun 0, 1254*4882a593Smuzhiyun /* 1255*4882a593Smuzhiyun * Check against actual DATA PHASE. 1256*4882a593Smuzhiyun */ 1257*4882a593Smuzhiyun SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)), 1258*4882a593Smuzhiyun PADDR_A (pm1_data_out), 1259*4882a593Smuzhiyun /* 1260*4882a593Smuzhiyun * Actual phase is DATA IN. 1261*4882a593Smuzhiyun * Check against expected direction. 1262*4882a593Smuzhiyun */ 1263*4882a593Smuzhiyun SCR_JUMP ^ IFFALSE (MASK (HF_DATA_IN, HF_DATA_IN)), 1264*4882a593Smuzhiyun PADDR_B (data_ovrun), 1265*4882a593Smuzhiyun /* 1266*4882a593Smuzhiyun * Keep track we are moving data from the 1267*4882a593Smuzhiyun * PM1 DATA mini-script. 1268*4882a593Smuzhiyun */ 1269*4882a593Smuzhiyun SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM1), 1270*4882a593Smuzhiyun 0, 1271*4882a593Smuzhiyun /* 1272*4882a593Smuzhiyun * Move the data to memory. 1273*4882a593Smuzhiyun */ 1274*4882a593Smuzhiyun SCR_CHMOV_TBL ^ SCR_DATA_IN, 1275*4882a593Smuzhiyun offsetof (struct sym_ccb, phys.pm1.sg), 1276*4882a593Smuzhiyun SCR_JUMP, 1277*4882a593Smuzhiyun PADDR_A (pm1_data_end), 1278*4882a593Smuzhiyun }/*-------------------------< PM1_DATA_OUT >---------------------*/,{ 1279*4882a593Smuzhiyun /* 1280*4882a593Smuzhiyun * Actual phase is DATA OUT. 1281*4882a593Smuzhiyun * Check against expected direction. 1282*4882a593Smuzhiyun */ 1283*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (MASK (HF_DATA_IN, HF_DATA_IN)), 1284*4882a593Smuzhiyun PADDR_B (data_ovrun), 1285*4882a593Smuzhiyun /* 1286*4882a593Smuzhiyun * Keep track we are moving data from the 1287*4882a593Smuzhiyun * PM1 DATA mini-script. 1288*4882a593Smuzhiyun */ 1289*4882a593Smuzhiyun SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM1), 1290*4882a593Smuzhiyun 0, 1291*4882a593Smuzhiyun /* 1292*4882a593Smuzhiyun * Move the data from memory. 1293*4882a593Smuzhiyun */ 1294*4882a593Smuzhiyun SCR_CHMOV_TBL ^ SCR_DATA_OUT, 1295*4882a593Smuzhiyun offsetof (struct sym_ccb, phys.pm1.sg), 1296*4882a593Smuzhiyun }/*-------------------------< PM1_DATA_END >---------------------*/,{ 1297*4882a593Smuzhiyun /* 1298*4882a593Smuzhiyun * Clear the flag that told we were moving 1299*4882a593Smuzhiyun * data from the PM1 DATA mini-script. 1300*4882a593Smuzhiyun */ 1301*4882a593Smuzhiyun SCR_REG_REG (HF_REG, SCR_AND, (~HF_IN_PM1)), 1302*4882a593Smuzhiyun 0, 1303*4882a593Smuzhiyun /* 1304*4882a593Smuzhiyun * Return to the previous DATA script which 1305*4882a593Smuzhiyun * is guaranteed by design (if no bug) to be 1306*4882a593Smuzhiyun * the main DATA script for this transfer. 1307*4882a593Smuzhiyun */ 1308*4882a593Smuzhiyun SCR_COPY (4), 1309*4882a593Smuzhiyun RADDR_1 (dsa), 1310*4882a593Smuzhiyun RADDR_1 (scratcha), 1311*4882a593Smuzhiyun SCR_REG_REG (scratcha, SCR_ADD, offsetof (struct sym_ccb,phys.pm1.ret)), 1312*4882a593Smuzhiyun 0, 1313*4882a593Smuzhiyun SCR_JUMP, 1314*4882a593Smuzhiyun PADDR_A (pm_data_end), 1315*4882a593Smuzhiyun }/*--------------------------<>----------------------------------*/ 1316*4882a593Smuzhiyun }; 1317*4882a593Smuzhiyun 1318*4882a593Smuzhiyun static struct SYM_FWB_SCR SYM_FWB_SCR = { 1319*4882a593Smuzhiyun /*-------------------------< NO_DATA >--------------------------*/ { 1320*4882a593Smuzhiyun SCR_JUMP, 1321*4882a593Smuzhiyun PADDR_B (data_ovrun), 1322*4882a593Smuzhiyun }/*-------------------------< SEL_FOR_ABORT >--------------------*/,{ 1323*4882a593Smuzhiyun /* 1324*4882a593Smuzhiyun * We are jumped here by the C code, if we have 1325*4882a593Smuzhiyun * some target to reset or some disconnected 1326*4882a593Smuzhiyun * job to abort. Since error recovery is a serious 1327*4882a593Smuzhiyun * busyness, we will really reset the SCSI BUS, if 1328*4882a593Smuzhiyun * case of a SCSI interrupt occurring in this path. 1329*4882a593Smuzhiyun */ 1330*4882a593Smuzhiyun 1331*4882a593Smuzhiyun #ifdef SYM_CONF_TARGET_ROLE_SUPPORT 1332*4882a593Smuzhiyun /* 1333*4882a593Smuzhiyun * Set initiator mode. 1334*4882a593Smuzhiyun */ 1335*4882a593Smuzhiyun SCR_CLR (SCR_TRG), 1336*4882a593Smuzhiyun 0, 1337*4882a593Smuzhiyun #endif 1338*4882a593Smuzhiyun /* 1339*4882a593Smuzhiyun * And try to select this target. 1340*4882a593Smuzhiyun */ 1341*4882a593Smuzhiyun SCR_SEL_TBL_ATN ^ offsetof (struct sym_hcb, abrt_sel), 1342*4882a593Smuzhiyun PADDR_A (reselect), 1343*4882a593Smuzhiyun /* 1344*4882a593Smuzhiyun * Wait for the selection to complete or 1345*4882a593Smuzhiyun * the selection to time out. 1346*4882a593Smuzhiyun */ 1347*4882a593Smuzhiyun SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_OUT)), 1348*4882a593Smuzhiyun -8, 1349*4882a593Smuzhiyun /* 1350*4882a593Smuzhiyun * Call the C code. 1351*4882a593Smuzhiyun */ 1352*4882a593Smuzhiyun SCR_INT, 1353*4882a593Smuzhiyun SIR_TARGET_SELECTED, 1354*4882a593Smuzhiyun /* 1355*4882a593Smuzhiyun * The C code should let us continue here. 1356*4882a593Smuzhiyun * Send the 'kiss of death' message. 1357*4882a593Smuzhiyun * We expect an immediate disconnect once 1358*4882a593Smuzhiyun * the target has eaten the message. 1359*4882a593Smuzhiyun */ 1360*4882a593Smuzhiyun SCR_REG_REG (scntl2, SCR_AND, 0x7f), 1361*4882a593Smuzhiyun 0, 1362*4882a593Smuzhiyun SCR_MOVE_TBL ^ SCR_MSG_OUT, 1363*4882a593Smuzhiyun offsetof (struct sym_hcb, abrt_tbl), 1364*4882a593Smuzhiyun SCR_CLR (SCR_ACK|SCR_ATN), 1365*4882a593Smuzhiyun 0, 1366*4882a593Smuzhiyun SCR_WAIT_DISC, 1367*4882a593Smuzhiyun 0, 1368*4882a593Smuzhiyun /* 1369*4882a593Smuzhiyun * Tell the C code that we are done. 1370*4882a593Smuzhiyun */ 1371*4882a593Smuzhiyun SCR_INT, 1372*4882a593Smuzhiyun SIR_ABORT_SENT, 1373*4882a593Smuzhiyun }/*-------------------------< SEL_FOR_ABORT_1 >------------------*/,{ 1374*4882a593Smuzhiyun /* 1375*4882a593Smuzhiyun * Jump at scheduler. 1376*4882a593Smuzhiyun */ 1377*4882a593Smuzhiyun SCR_JUMP, 1378*4882a593Smuzhiyun PADDR_A (start), 1379*4882a593Smuzhiyun }/*-------------------------< MSG_IN_ETC >-----------------------*/,{ 1380*4882a593Smuzhiyun /* 1381*4882a593Smuzhiyun * If it is an EXTENDED (variable size message) 1382*4882a593Smuzhiyun * Handle it. 1383*4882a593Smuzhiyun */ 1384*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)), 1385*4882a593Smuzhiyun PADDR_B (msg_extended), 1386*4882a593Smuzhiyun /* 1387*4882a593Smuzhiyun * Let the C code handle any other 1388*4882a593Smuzhiyun * 1 byte message. 1389*4882a593Smuzhiyun */ 1390*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (MASK (0x00, 0xf0)), 1391*4882a593Smuzhiyun PADDR_B (msg_received), 1392*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (MASK (0x10, 0xf0)), 1393*4882a593Smuzhiyun PADDR_B (msg_received), 1394*4882a593Smuzhiyun /* 1395*4882a593Smuzhiyun * We donnot handle 2 bytes messages from SCRIPTS. 1396*4882a593Smuzhiyun * So, let the C code deal with these ones too. 1397*4882a593Smuzhiyun */ 1398*4882a593Smuzhiyun SCR_JUMP ^ IFFALSE (MASK (0x20, 0xf0)), 1399*4882a593Smuzhiyun PADDR_B (msg_weird_seen), 1400*4882a593Smuzhiyun SCR_CLR (SCR_ACK), 1401*4882a593Smuzhiyun 0, 1402*4882a593Smuzhiyun SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 1403*4882a593Smuzhiyun HADDR_1 (msgin[1]), 1404*4882a593Smuzhiyun }/*-------------------------< MSG_RECEIVED >---------------------*/,{ 1405*4882a593Smuzhiyun SCR_COPY (4), /* DUMMY READ */ 1406*4882a593Smuzhiyun HADDR_1 (scratch), 1407*4882a593Smuzhiyun RADDR_1 (scratcha), 1408*4882a593Smuzhiyun SCR_INT, 1409*4882a593Smuzhiyun SIR_MSG_RECEIVED, 1410*4882a593Smuzhiyun }/*-------------------------< MSG_WEIRD_SEEN >-------------------*/,{ 1411*4882a593Smuzhiyun SCR_COPY (4), /* DUMMY READ */ 1412*4882a593Smuzhiyun HADDR_1 (scratch), 1413*4882a593Smuzhiyun RADDR_1 (scratcha), 1414*4882a593Smuzhiyun SCR_INT, 1415*4882a593Smuzhiyun SIR_MSG_WEIRD, 1416*4882a593Smuzhiyun }/*-------------------------< MSG_EXTENDED >---------------------*/,{ 1417*4882a593Smuzhiyun /* 1418*4882a593Smuzhiyun * Clear ACK and get the next byte 1419*4882a593Smuzhiyun * assumed to be the message length. 1420*4882a593Smuzhiyun */ 1421*4882a593Smuzhiyun SCR_CLR (SCR_ACK), 1422*4882a593Smuzhiyun 0, 1423*4882a593Smuzhiyun SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 1424*4882a593Smuzhiyun HADDR_1 (msgin[1]), 1425*4882a593Smuzhiyun /* 1426*4882a593Smuzhiyun * Try to catch some unlikely situations as 0 length 1427*4882a593Smuzhiyun * or too large the length. 1428*4882a593Smuzhiyun */ 1429*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (DATA (0)), 1430*4882a593Smuzhiyun PADDR_B (msg_weird_seen), 1431*4882a593Smuzhiyun SCR_TO_REG (scratcha), 1432*4882a593Smuzhiyun 0, 1433*4882a593Smuzhiyun SCR_REG_REG (sfbr, SCR_ADD, (256-8)), 1434*4882a593Smuzhiyun 0, 1435*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (CARRYSET), 1436*4882a593Smuzhiyun PADDR_B (msg_weird_seen), 1437*4882a593Smuzhiyun /* 1438*4882a593Smuzhiyun * We donnot handle extended messages from SCRIPTS. 1439*4882a593Smuzhiyun * Read the amount of data corresponding to the 1440*4882a593Smuzhiyun * message length and call the C code. 1441*4882a593Smuzhiyun */ 1442*4882a593Smuzhiyun SCR_COPY (1), 1443*4882a593Smuzhiyun RADDR_1 (scratcha), 1444*4882a593Smuzhiyun PADDR_B (_sms_b10), 1445*4882a593Smuzhiyun SCR_CLR (SCR_ACK), 1446*4882a593Smuzhiyun 0, 1447*4882a593Smuzhiyun }/*-------------------------< _SMS_B10 >-------------------------*/,{ 1448*4882a593Smuzhiyun SCR_MOVE_ABS (0) ^ SCR_MSG_IN, 1449*4882a593Smuzhiyun HADDR_1 (msgin[2]), 1450*4882a593Smuzhiyun SCR_JUMP, 1451*4882a593Smuzhiyun PADDR_B (msg_received), 1452*4882a593Smuzhiyun }/*-------------------------< MSG_BAD >--------------------------*/,{ 1453*4882a593Smuzhiyun /* 1454*4882a593Smuzhiyun * unimplemented message - reject it. 1455*4882a593Smuzhiyun */ 1456*4882a593Smuzhiyun SCR_INT, 1457*4882a593Smuzhiyun SIR_REJECT_TO_SEND, 1458*4882a593Smuzhiyun SCR_SET (SCR_ATN), 1459*4882a593Smuzhiyun 0, 1460*4882a593Smuzhiyun SCR_JUMP, 1461*4882a593Smuzhiyun PADDR_A (clrack), 1462*4882a593Smuzhiyun }/*-------------------------< MSG_WEIRD >------------------------*/,{ 1463*4882a593Smuzhiyun /* 1464*4882a593Smuzhiyun * weird message received 1465*4882a593Smuzhiyun * ignore all MSG IN phases and reject it. 1466*4882a593Smuzhiyun */ 1467*4882a593Smuzhiyun SCR_INT, 1468*4882a593Smuzhiyun SIR_REJECT_TO_SEND, 1469*4882a593Smuzhiyun SCR_SET (SCR_ATN), 1470*4882a593Smuzhiyun 0, 1471*4882a593Smuzhiyun }/*-------------------------< MSG_WEIRD1 >-----------------------*/,{ 1472*4882a593Smuzhiyun SCR_CLR (SCR_ACK), 1473*4882a593Smuzhiyun 0, 1474*4882a593Smuzhiyun SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), 1475*4882a593Smuzhiyun PADDR_A (dispatch), 1476*4882a593Smuzhiyun SCR_MOVE_ABS (1) ^ SCR_MSG_IN, 1477*4882a593Smuzhiyun HADDR_1 (scratch), 1478*4882a593Smuzhiyun SCR_JUMP, 1479*4882a593Smuzhiyun PADDR_B (msg_weird1), 1480*4882a593Smuzhiyun }/*-------------------------< WDTR_RESP >------------------------*/,{ 1481*4882a593Smuzhiyun /* 1482*4882a593Smuzhiyun * let the target fetch our answer. 1483*4882a593Smuzhiyun */ 1484*4882a593Smuzhiyun SCR_SET (SCR_ATN), 1485*4882a593Smuzhiyun 0, 1486*4882a593Smuzhiyun SCR_CLR (SCR_ACK), 1487*4882a593Smuzhiyun 0, 1488*4882a593Smuzhiyun SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)), 1489*4882a593Smuzhiyun PADDR_B (nego_bad_phase), 1490*4882a593Smuzhiyun }/*-------------------------< SEND_WDTR >------------------------*/,{ 1491*4882a593Smuzhiyun /* 1492*4882a593Smuzhiyun * Send the M_X_WIDE_REQ 1493*4882a593Smuzhiyun */ 1494*4882a593Smuzhiyun SCR_MOVE_ABS (4) ^ SCR_MSG_OUT, 1495*4882a593Smuzhiyun HADDR_1 (msgout), 1496*4882a593Smuzhiyun SCR_JUMP, 1497*4882a593Smuzhiyun PADDR_B (msg_out_done), 1498*4882a593Smuzhiyun }/*-------------------------< SDTR_RESP >------------------------*/,{ 1499*4882a593Smuzhiyun /* 1500*4882a593Smuzhiyun * let the target fetch our answer. 1501*4882a593Smuzhiyun */ 1502*4882a593Smuzhiyun SCR_SET (SCR_ATN), 1503*4882a593Smuzhiyun 0, 1504*4882a593Smuzhiyun SCR_CLR (SCR_ACK), 1505*4882a593Smuzhiyun 0, 1506*4882a593Smuzhiyun SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)), 1507*4882a593Smuzhiyun PADDR_B (nego_bad_phase), 1508*4882a593Smuzhiyun }/*-------------------------< SEND_SDTR >------------------------*/,{ 1509*4882a593Smuzhiyun /* 1510*4882a593Smuzhiyun * Send the M_X_SYNC_REQ 1511*4882a593Smuzhiyun */ 1512*4882a593Smuzhiyun SCR_MOVE_ABS (5) ^ SCR_MSG_OUT, 1513*4882a593Smuzhiyun HADDR_1 (msgout), 1514*4882a593Smuzhiyun SCR_JUMP, 1515*4882a593Smuzhiyun PADDR_B (msg_out_done), 1516*4882a593Smuzhiyun }/*-------------------------< PPR_RESP >-------------------------*/,{ 1517*4882a593Smuzhiyun /* 1518*4882a593Smuzhiyun * let the target fetch our answer. 1519*4882a593Smuzhiyun */ 1520*4882a593Smuzhiyun SCR_SET (SCR_ATN), 1521*4882a593Smuzhiyun 0, 1522*4882a593Smuzhiyun SCR_CLR (SCR_ACK), 1523*4882a593Smuzhiyun 0, 1524*4882a593Smuzhiyun SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)), 1525*4882a593Smuzhiyun PADDR_B (nego_bad_phase), 1526*4882a593Smuzhiyun }/*-------------------------< SEND_PPR >-------------------------*/,{ 1527*4882a593Smuzhiyun /* 1528*4882a593Smuzhiyun * Send the M_X_PPR_REQ 1529*4882a593Smuzhiyun */ 1530*4882a593Smuzhiyun SCR_MOVE_ABS (8) ^ SCR_MSG_OUT, 1531*4882a593Smuzhiyun HADDR_1 (msgout), 1532*4882a593Smuzhiyun SCR_JUMP, 1533*4882a593Smuzhiyun PADDR_B (msg_out_done), 1534*4882a593Smuzhiyun }/*-------------------------< NEGO_BAD_PHASE >-------------------*/,{ 1535*4882a593Smuzhiyun SCR_INT, 1536*4882a593Smuzhiyun SIR_NEGO_PROTO, 1537*4882a593Smuzhiyun SCR_JUMP, 1538*4882a593Smuzhiyun PADDR_A (dispatch), 1539*4882a593Smuzhiyun }/*-------------------------< MSG_OUT >--------------------------*/,{ 1540*4882a593Smuzhiyun /* 1541*4882a593Smuzhiyun * The target requests a message. 1542*4882a593Smuzhiyun * We donnot send messages that may 1543*4882a593Smuzhiyun * require the device to go to bus free. 1544*4882a593Smuzhiyun */ 1545*4882a593Smuzhiyun SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, 1546*4882a593Smuzhiyun HADDR_1 (msgout), 1547*4882a593Smuzhiyun /* 1548*4882a593Smuzhiyun * ... wait for the next phase 1549*4882a593Smuzhiyun * if it's a message out, send it again, ... 1550*4882a593Smuzhiyun */ 1551*4882a593Smuzhiyun SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)), 1552*4882a593Smuzhiyun PADDR_B (msg_out), 1553*4882a593Smuzhiyun }/*-------------------------< MSG_OUT_DONE >---------------------*/,{ 1554*4882a593Smuzhiyun /* 1555*4882a593Smuzhiyun * Let the C code be aware of the 1556*4882a593Smuzhiyun * sent message and clear the message. 1557*4882a593Smuzhiyun */ 1558*4882a593Smuzhiyun SCR_INT, 1559*4882a593Smuzhiyun SIR_MSG_OUT_DONE, 1560*4882a593Smuzhiyun /* 1561*4882a593Smuzhiyun * ... and process the next phase 1562*4882a593Smuzhiyun */ 1563*4882a593Smuzhiyun SCR_JUMP, 1564*4882a593Smuzhiyun PADDR_A (dispatch), 1565*4882a593Smuzhiyun }/*-------------------------< DATA_OVRUN >-----------------------*/,{ 1566*4882a593Smuzhiyun /* 1567*4882a593Smuzhiyun * Zero scratcha that will count the 1568*4882a593Smuzhiyun * extras bytes. 1569*4882a593Smuzhiyun */ 1570*4882a593Smuzhiyun SCR_COPY (4), 1571*4882a593Smuzhiyun PADDR_B (zero), 1572*4882a593Smuzhiyun RADDR_1 (scratcha), 1573*4882a593Smuzhiyun }/*-------------------------< DATA_OVRUN1 >----------------------*/,{ 1574*4882a593Smuzhiyun /* 1575*4882a593Smuzhiyun * The target may want to transfer too much data. 1576*4882a593Smuzhiyun * 1577*4882a593Smuzhiyun * If phase is DATA OUT write 1 byte and count it. 1578*4882a593Smuzhiyun */ 1579*4882a593Smuzhiyun SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_OUT)), 1580*4882a593Smuzhiyun 16, 1581*4882a593Smuzhiyun SCR_CHMOV_ABS (1) ^ SCR_DATA_OUT, 1582*4882a593Smuzhiyun HADDR_1 (scratch), 1583*4882a593Smuzhiyun SCR_JUMP, 1584*4882a593Smuzhiyun PADDR_B (data_ovrun2), 1585*4882a593Smuzhiyun /* 1586*4882a593Smuzhiyun * If WSR is set, clear this condition, and 1587*4882a593Smuzhiyun * count this byte. 1588*4882a593Smuzhiyun */ 1589*4882a593Smuzhiyun SCR_FROM_REG (scntl2), 1590*4882a593Smuzhiyun 0, 1591*4882a593Smuzhiyun SCR_JUMPR ^ IFFALSE (MASK (WSR, WSR)), 1592*4882a593Smuzhiyun 16, 1593*4882a593Smuzhiyun SCR_REG_REG (scntl2, SCR_OR, WSR), 1594*4882a593Smuzhiyun 0, 1595*4882a593Smuzhiyun SCR_JUMP, 1596*4882a593Smuzhiyun PADDR_B (data_ovrun2), 1597*4882a593Smuzhiyun /* 1598*4882a593Smuzhiyun * Finally check against DATA IN phase. 1599*4882a593Smuzhiyun * Signal data overrun to the C code 1600*4882a593Smuzhiyun * and jump to dispatcher if not so. 1601*4882a593Smuzhiyun * Read 1 byte otherwise and count it. 1602*4882a593Smuzhiyun */ 1603*4882a593Smuzhiyun SCR_JUMPR ^ IFTRUE (WHEN (SCR_DATA_IN)), 1604*4882a593Smuzhiyun 16, 1605*4882a593Smuzhiyun SCR_INT, 1606*4882a593Smuzhiyun SIR_DATA_OVERRUN, 1607*4882a593Smuzhiyun SCR_JUMP, 1608*4882a593Smuzhiyun PADDR_A (dispatch), 1609*4882a593Smuzhiyun SCR_CHMOV_ABS (1) ^ SCR_DATA_IN, 1610*4882a593Smuzhiyun HADDR_1 (scratch), 1611*4882a593Smuzhiyun }/*-------------------------< DATA_OVRUN2 >----------------------*/,{ 1612*4882a593Smuzhiyun /* 1613*4882a593Smuzhiyun * Count this byte. 1614*4882a593Smuzhiyun * This will allow to return a negative 1615*4882a593Smuzhiyun * residual to user. 1616*4882a593Smuzhiyun */ 1617*4882a593Smuzhiyun SCR_REG_REG (scratcha, SCR_ADD, 0x01), 1618*4882a593Smuzhiyun 0, 1619*4882a593Smuzhiyun SCR_REG_REG (scratcha1, SCR_ADDC, 0), 1620*4882a593Smuzhiyun 0, 1621*4882a593Smuzhiyun SCR_REG_REG (scratcha2, SCR_ADDC, 0), 1622*4882a593Smuzhiyun 0, 1623*4882a593Smuzhiyun /* 1624*4882a593Smuzhiyun * .. and repeat as required. 1625*4882a593Smuzhiyun */ 1626*4882a593Smuzhiyun SCR_JUMP, 1627*4882a593Smuzhiyun PADDR_B (data_ovrun1), 1628*4882a593Smuzhiyun }/*-------------------------< ABORT_RESEL >----------------------*/,{ 1629*4882a593Smuzhiyun SCR_SET (SCR_ATN), 1630*4882a593Smuzhiyun 0, 1631*4882a593Smuzhiyun SCR_CLR (SCR_ACK), 1632*4882a593Smuzhiyun 0, 1633*4882a593Smuzhiyun /* 1634*4882a593Smuzhiyun * send the abort/abortag/reset message 1635*4882a593Smuzhiyun * we expect an immediate disconnect 1636*4882a593Smuzhiyun */ 1637*4882a593Smuzhiyun SCR_REG_REG (scntl2, SCR_AND, 0x7f), 1638*4882a593Smuzhiyun 0, 1639*4882a593Smuzhiyun SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, 1640*4882a593Smuzhiyun HADDR_1 (msgout), 1641*4882a593Smuzhiyun SCR_CLR (SCR_ACK|SCR_ATN), 1642*4882a593Smuzhiyun 0, 1643*4882a593Smuzhiyun SCR_WAIT_DISC, 1644*4882a593Smuzhiyun 0, 1645*4882a593Smuzhiyun SCR_INT, 1646*4882a593Smuzhiyun SIR_RESEL_ABORTED, 1647*4882a593Smuzhiyun SCR_JUMP, 1648*4882a593Smuzhiyun PADDR_A (start), 1649*4882a593Smuzhiyun }/*-------------------------< RESEND_IDENT >---------------------*/,{ 1650*4882a593Smuzhiyun /* 1651*4882a593Smuzhiyun * The target stays in MSG OUT phase after having acked 1652*4882a593Smuzhiyun * Identify [+ Tag [+ Extended message ]]. Targets shall 1653*4882a593Smuzhiyun * behave this way on parity error. 1654*4882a593Smuzhiyun * We must send it again all the messages. 1655*4882a593Smuzhiyun */ 1656*4882a593Smuzhiyun SCR_SET (SCR_ATN), /* Shall be asserted 2 deskew delays before the */ 1657*4882a593Smuzhiyun 0, /* 1rst ACK = 90 ns. Hope the chip isn't too fast */ 1658*4882a593Smuzhiyun SCR_JUMP, 1659*4882a593Smuzhiyun PADDR_A (send_ident), 1660*4882a593Smuzhiyun }/*-------------------------< IDENT_BREAK >----------------------*/,{ 1661*4882a593Smuzhiyun SCR_CLR (SCR_ATN), 1662*4882a593Smuzhiyun 0, 1663*4882a593Smuzhiyun SCR_JUMP, 1664*4882a593Smuzhiyun PADDR_A (select2), 1665*4882a593Smuzhiyun }/*-------------------------< IDENT_BREAK_ATN >------------------*/,{ 1666*4882a593Smuzhiyun SCR_SET (SCR_ATN), 1667*4882a593Smuzhiyun 0, 1668*4882a593Smuzhiyun SCR_JUMP, 1669*4882a593Smuzhiyun PADDR_A (select2), 1670*4882a593Smuzhiyun }/*-------------------------< SDATA_IN >-------------------------*/,{ 1671*4882a593Smuzhiyun SCR_CHMOV_TBL ^ SCR_DATA_IN, 1672*4882a593Smuzhiyun offsetof (struct sym_dsb, sense), 1673*4882a593Smuzhiyun SCR_CALL, 1674*4882a593Smuzhiyun PADDR_A (datai_done), 1675*4882a593Smuzhiyun SCR_JUMP, 1676*4882a593Smuzhiyun PADDR_B (data_ovrun), 1677*4882a593Smuzhiyun }/*-------------------------< RESEL_BAD_LUN >--------------------*/,{ 1678*4882a593Smuzhiyun /* 1679*4882a593Smuzhiyun * Message is an IDENTIFY, but lun is unknown. 1680*4882a593Smuzhiyun * Signal problem to C code for logging the event. 1681*4882a593Smuzhiyun * Send a M_ABORT to clear all pending tasks. 1682*4882a593Smuzhiyun */ 1683*4882a593Smuzhiyun SCR_INT, 1684*4882a593Smuzhiyun SIR_RESEL_BAD_LUN, 1685*4882a593Smuzhiyun SCR_JUMP, 1686*4882a593Smuzhiyun PADDR_B (abort_resel), 1687*4882a593Smuzhiyun }/*-------------------------< BAD_I_T_L >------------------------*/,{ 1688*4882a593Smuzhiyun /* 1689*4882a593Smuzhiyun * We donnot have a task for that I_T_L. 1690*4882a593Smuzhiyun * Signal problem to C code for logging the event. 1691*4882a593Smuzhiyun * Send a M_ABORT message. 1692*4882a593Smuzhiyun */ 1693*4882a593Smuzhiyun SCR_INT, 1694*4882a593Smuzhiyun SIR_RESEL_BAD_I_T_L, 1695*4882a593Smuzhiyun SCR_JUMP, 1696*4882a593Smuzhiyun PADDR_B (abort_resel), 1697*4882a593Smuzhiyun }/*-------------------------< BAD_I_T_L_Q >----------------------*/,{ 1698*4882a593Smuzhiyun /* 1699*4882a593Smuzhiyun * We donnot have a task that matches the tag. 1700*4882a593Smuzhiyun * Signal problem to C code for logging the event. 1701*4882a593Smuzhiyun * Send a M_ABORTTAG message. 1702*4882a593Smuzhiyun */ 1703*4882a593Smuzhiyun SCR_INT, 1704*4882a593Smuzhiyun SIR_RESEL_BAD_I_T_L_Q, 1705*4882a593Smuzhiyun SCR_JUMP, 1706*4882a593Smuzhiyun PADDR_B (abort_resel), 1707*4882a593Smuzhiyun }/*-------------------------< BAD_STATUS >-----------------------*/,{ 1708*4882a593Smuzhiyun /* 1709*4882a593Smuzhiyun * Anything different from INTERMEDIATE 1710*4882a593Smuzhiyun * CONDITION MET should be a bad SCSI status, 1711*4882a593Smuzhiyun * given that GOOD status has already been tested. 1712*4882a593Smuzhiyun * Call the C code. 1713*4882a593Smuzhiyun */ 1714*4882a593Smuzhiyun SCR_COPY (4), 1715*4882a593Smuzhiyun PADDR_B (startpos), 1716*4882a593Smuzhiyun RADDR_1 (scratcha), 1717*4882a593Smuzhiyun SCR_INT ^ IFFALSE (DATA (S_COND_MET)), 1718*4882a593Smuzhiyun SIR_BAD_SCSI_STATUS, 1719*4882a593Smuzhiyun SCR_RETURN, 1720*4882a593Smuzhiyun 0, 1721*4882a593Smuzhiyun }/*-------------------------< WSR_MA_HELPER >--------------------*/,{ 1722*4882a593Smuzhiyun /* 1723*4882a593Smuzhiyun * Helper for the C code when WSR bit is set. 1724*4882a593Smuzhiyun * Perform the move of the residual byte. 1725*4882a593Smuzhiyun */ 1726*4882a593Smuzhiyun SCR_CHMOV_TBL ^ SCR_DATA_IN, 1727*4882a593Smuzhiyun offsetof (struct sym_ccb, phys.wresid), 1728*4882a593Smuzhiyun SCR_JUMP, 1729*4882a593Smuzhiyun PADDR_A (dispatch), 1730*4882a593Smuzhiyun 1731*4882a593Smuzhiyun }/*-------------------------< ZERO >-----------------------------*/,{ 1732*4882a593Smuzhiyun SCR_DATA_ZERO, 1733*4882a593Smuzhiyun }/*-------------------------< SCRATCH >--------------------------*/,{ 1734*4882a593Smuzhiyun SCR_DATA_ZERO, /* MUST BE BEFORE SCRATCH1 */ 1735*4882a593Smuzhiyun }/*-------------------------< SCRATCH1 >-------------------------*/,{ 1736*4882a593Smuzhiyun SCR_DATA_ZERO, 1737*4882a593Smuzhiyun }/*-------------------------< PREV_DONE >------------------------*/,{ 1738*4882a593Smuzhiyun SCR_DATA_ZERO, /* MUST BE BEFORE DONE_POS ! */ 1739*4882a593Smuzhiyun }/*-------------------------< DONE_POS >-------------------------*/,{ 1740*4882a593Smuzhiyun SCR_DATA_ZERO, 1741*4882a593Smuzhiyun }/*-------------------------< NEXTJOB >--------------------------*/,{ 1742*4882a593Smuzhiyun SCR_DATA_ZERO, /* MUST BE BEFORE STARTPOS ! */ 1743*4882a593Smuzhiyun }/*-------------------------< STARTPOS >-------------------------*/,{ 1744*4882a593Smuzhiyun SCR_DATA_ZERO, 1745*4882a593Smuzhiyun }/*-------------------------< TARGTBL >--------------------------*/,{ 1746*4882a593Smuzhiyun SCR_DATA_ZERO, 1747*4882a593Smuzhiyun }/*--------------------------<>----------------------------------*/ 1748*4882a593Smuzhiyun }; 1749*4882a593Smuzhiyun 1750*4882a593Smuzhiyun static struct SYM_FWZ_SCR SYM_FWZ_SCR = { 1751*4882a593Smuzhiyun /*-------------------------< SNOOPTEST >------------------------*/{ 1752*4882a593Smuzhiyun /* 1753*4882a593Smuzhiyun * Read the variable. 1754*4882a593Smuzhiyun */ 1755*4882a593Smuzhiyun SCR_COPY (4), 1756*4882a593Smuzhiyun HADDR_1 (scratch), 1757*4882a593Smuzhiyun RADDR_1 (scratcha), 1758*4882a593Smuzhiyun /* 1759*4882a593Smuzhiyun * Write the variable. 1760*4882a593Smuzhiyun */ 1761*4882a593Smuzhiyun SCR_COPY (4), 1762*4882a593Smuzhiyun RADDR_1 (temp), 1763*4882a593Smuzhiyun HADDR_1 (scratch), 1764*4882a593Smuzhiyun /* 1765*4882a593Smuzhiyun * Read back the variable. 1766*4882a593Smuzhiyun */ 1767*4882a593Smuzhiyun SCR_COPY (4), 1768*4882a593Smuzhiyun HADDR_1 (scratch), 1769*4882a593Smuzhiyun RADDR_1 (temp), 1770*4882a593Smuzhiyun }/*-------------------------< SNOOPEND >-------------------------*/,{ 1771*4882a593Smuzhiyun /* 1772*4882a593Smuzhiyun * And stop. 1773*4882a593Smuzhiyun */ 1774*4882a593Smuzhiyun SCR_INT, 1775*4882a593Smuzhiyun 99, 1776*4882a593Smuzhiyun }/*--------------------------<>----------------------------------*/ 1777*4882a593Smuzhiyun }; 1778