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