1*54004Sfujita /* 2*54004Sfujita * Copyright (c) 1992 OMRON Corporation. 3*54004Sfujita * Copyright (c) 1992 The Regents of the University of California. 4*54004Sfujita * All rights reserved. 5*54004Sfujita * 6*54004Sfujita * This code is derived from software contributed to Berkeley by 7*54004Sfujita * OMRON Corporation. 8*54004Sfujita * 9*54004Sfujita * %sccs.include.redist.c% 10*54004Sfujita * 11*54004Sfujita * @(#)sc.c 7.1 (Berkeley) 06/15/92 12*54004Sfujita */ 13*54004Sfujita 14*54004Sfujita /* 15*54004Sfujita * sc.c -- FUJITSU MB89352 SCSI Protocole Controller (SPC) Device Driver 16*54004Sfujita * 17*54004Sfujita * remaked by A.Fujita, Mar-22-1992 18*54004Sfujita * remaked again by A.Fujita, Apr-16-1992 19*54004Sfujita */ 20*54004Sfujita 21*54004Sfujita #define DEBUG_FUNC 22*54004Sfujita 23*54004Sfujita #include "sc.h" 24*54004Sfujita #if NSC > 0 25*54004Sfujita 26*54004Sfujita #include "sys/param.h" 27*54004Sfujita #include "sys/systm.h" 28*54004Sfujita #include "sys/buf.h" 29*54004Sfujita #include "device.h" 30*54004Sfujita 31*54004Sfujita #include "scsireg.h" 32*54004Sfujita #include "scsivar.h" 33*54004Sfujita 34*54004Sfujita /* 35*54004Sfujita * SC Driver Options 36*54004Sfujita */ 37*54004Sfujita 38*54004Sfujita #define QUADBYTES /* 4 bytes access to SPC DREG Reg. */ 39*54004Sfujita #define NODISCONNECT /* not used SCSI DISCONNECT Ops. */ 40*54004Sfujita #undef XFER_ENABLE /* using interrupt for DREG access */ 41*54004Sfujita 42*54004Sfujita 43*54004Sfujita #define SCSI_IPL 2 44*54004Sfujita #define SCSI_ID 7 45*54004Sfujita 46*54004Sfujita extern char *hexstr(); 47*54004Sfujita 48*54004Sfujita int scinit(), scstart(), scintr(); 49*54004Sfujita void screset(); 50*54004Sfujita struct driver scdriver = { 51*54004Sfujita scinit, "sc", scstart, (int (*)()) 0, scintr, (int (*)()) 0 52*54004Sfujita }; 53*54004Sfujita 54*54004Sfujita struct scsi_softc scsi_softc[NSC]; 55*54004Sfujita 56*54004Sfujita 57*54004Sfujita #define SC_TIMEOUT 0x01400000 /* (20971520) */ 58*54004Sfujita 59*54004Sfujita 60*54004Sfujita /* 61*54004Sfujita * for DEBUG 62*54004Sfujita */ 63*54004Sfujita 64*54004Sfujita char * 65*54004Sfujita scsi_status(stat) 66*54004Sfujita u_char stat; 67*54004Sfujita { 68*54004Sfujita if ((stat & 0x1e) == 0) 69*54004Sfujita return("Good"); 70*54004Sfujita else if ((stat & 0x1e) == STS_CHECKCOND) 71*54004Sfujita return("Check Condition"); 72*54004Sfujita else if ((stat & 0x1e) == STS_CONDMET) 73*54004Sfujita return("Condition Met"); 74*54004Sfujita else if ((stat & 0x1e) == STS_BUSY) 75*54004Sfujita return("Busy"); 76*54004Sfujita else if ((stat & 0x1e) == STS_INTERMED) 77*54004Sfujita return("Intermediate status sent"); 78*54004Sfujita else if ((stat & 0x1e) == STS_EXT) 79*54004Sfujita return("Extended status valid"); 80*54004Sfujita else 81*54004Sfujita return("Unknown Status"); 82*54004Sfujita } 83*54004Sfujita 84*54004Sfujita #ifdef DEBUG_FUNC 85*54004Sfujita 86*54004Sfujita char * 87*54004Sfujita scsi_command(cmd) 88*54004Sfujita u_char cmd; 89*54004Sfujita { 90*54004Sfujita if (cmd == CMD_TEST_UNIT_READY) 91*54004Sfujita return("TEST_UNIT_READY"); 92*54004Sfujita else if (cmd == CMD_REQUEST_SENSE) 93*54004Sfujita return("REQUEST_SENSE"); 94*54004Sfujita else if (cmd == CMD_INQUIRY) 95*54004Sfujita return("INQUIRY"); 96*54004Sfujita else if (cmd == CMD_READ) 97*54004Sfujita return("READ"); 98*54004Sfujita else if (cmd == CMD_WRITE) 99*54004Sfujita return("WRITE"); 100*54004Sfujita else if (cmd == CMD_READ_EXT) 101*54004Sfujita return("READ EXT"); 102*54004Sfujita else if (cmd == CMD_WRITE_EXT) 103*54004Sfujita return("WRITE_EXT"); 104*54004Sfujita else if (cmd == CMD_READ_CAPACITY) 105*54004Sfujita return("READ_CAPACITY"); 106*54004Sfujita else 107*54004Sfujita return(hexstr(cmd, 2)); 108*54004Sfujita } 109*54004Sfujita 110*54004Sfujita char * 111*54004Sfujita scsi_mesg(mesg) 112*54004Sfujita u_char mesg; 113*54004Sfujita { 114*54004Sfujita if (mesg == MSG_CMD_COMPLETE) 115*54004Sfujita return("Command Complete"); 116*54004Sfujita else if (mesg == MSG_EXT_MESSAGE) 117*54004Sfujita return("Extended Message"); 118*54004Sfujita else if (mesg == MSG_SAVE_DATA_PTR) 119*54004Sfujita return("Save Data Pointer"); 120*54004Sfujita else if (mesg == MSG_RESTORE_PTR) 121*54004Sfujita return("Restore Pointer"); 122*54004Sfujita else if (mesg == MSG_DISCONNECT) 123*54004Sfujita return("Disconnect"); 124*54004Sfujita else if (mesg == MSG_INIT_DETECT_ERROR) 125*54004Sfujita return("Initiator Detected Error"); 126*54004Sfujita else if (mesg == MSG_ABORT) 127*54004Sfujita return("Abort"); 128*54004Sfujita else if (mesg == MSG_REJECT) 129*54004Sfujita return("Message Reject"); 130*54004Sfujita else if (mesg == MSG_NOOP) 131*54004Sfujita return("No Operation"); 132*54004Sfujita else if (mesg == MSG_PARITY_ERROR) 133*54004Sfujita return("Message Parity Error"); 134*54004Sfujita else if (mesg == MSG_BUS_DEVICE_RESET) 135*54004Sfujita return("Bus Device Reset"); 136*54004Sfujita else if (mesg == MSG_IDENTIFY) 137*54004Sfujita return("Identify"); 138*54004Sfujita else if (mesg == MSG_IDENTIFY_DR) 139*54004Sfujita return("Identify (Disconnect)"); 140*54004Sfujita else 141*54004Sfujita return("Unknown Message"); 142*54004Sfujita } 143*54004Sfujita 144*54004Sfujita char * 145*54004Sfujita phase_name(phase) 146*54004Sfujita u_char phase; 147*54004Sfujita { 148*54004Sfujita if (phase == DATA_OUT_PHASE) 149*54004Sfujita return("Data Out"); 150*54004Sfujita else if (phase == DATA_IN_PHASE) 151*54004Sfujita return("Data In"); 152*54004Sfujita else if (phase == CMD_PHASE) 153*54004Sfujita return("Command"); 154*54004Sfujita else if (phase == STATUS_PHASE) 155*54004Sfujita return("Status"); 156*54004Sfujita else if (phase == BUS_FREE_PHASE) 157*54004Sfujita return("Bus Free"); 158*54004Sfujita else if (phase == ARB_SEL_PHASE) 159*54004Sfujita return("Arbitration/Select"); 160*54004Sfujita else if (phase == MESG_OUT_PHASE) 161*54004Sfujita return("Message Out"); 162*54004Sfujita else if (phase == MESG_IN_PHASE) 163*54004Sfujita return("Message In"); 164*54004Sfujita else 165*54004Sfujita return("Unknown"); 166*54004Sfujita } 167*54004Sfujita #endif 168*54004Sfujita 169*54004Sfujita /* 170*54004Sfujita * Initialize SPC & Data Structure 171*54004Sfujita */ 172*54004Sfujita 173*54004Sfujita int 174*54004Sfujita scinit(hc) 175*54004Sfujita register struct hp_ctlr *hc; 176*54004Sfujita { 177*54004Sfujita register struct scsi_softc *hs = &scsi_softc[hc->hp_unit]; 178*54004Sfujita register int i; 179*54004Sfujita 180*54004Sfujita hc->hp_ipl = SCSI_IPL; 181*54004Sfujita hs->sc_hc = hc; 182*54004Sfujita hs->sc_sq.dq_forw = hs->sc_sq.dq_back = &hs->sc_sq; 183*54004Sfujita hs->sc_wq.dq_forw = hs->sc_wq.dq_back = &hs->sc_wq; 184*54004Sfujita 185*54004Sfujita hs->sc_flags = 0; 186*54004Sfujita hs->sc_phase = BUS_FREE_PHASE; 187*54004Sfujita 188*54004Sfujita hs->sc_stat = 0; 189*54004Sfujita hs->sc_msg[0] = 0; 190*54004Sfujita 191*54004Sfujita scsi_init_buf(); 192*54004Sfujita 193*54004Sfujita screset(hc->hp_unit); 194*54004Sfujita 195*54004Sfujita return(1); 196*54004Sfujita } 197*54004Sfujita 198*54004Sfujita void 199*54004Sfujita screset(unit) 200*54004Sfujita register int unit; 201*54004Sfujita { 202*54004Sfujita register struct scsi_softc *hs = &scsi_softc[unit]; 203*54004Sfujita volatile register struct scsidevice *hd = 204*54004Sfujita (struct scsidevice *)hs->sc_hc->hp_addr; 205*54004Sfujita 206*54004Sfujita printf("sc%d: ", unit); 207*54004Sfujita 208*54004Sfujita /* 209*54004Sfujita * Disable interrupts then reset the FUJI chip. 210*54004Sfujita */ 211*54004Sfujita 212*54004Sfujita hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST; 213*54004Sfujita hd->scsi_scmd = 0; 214*54004Sfujita hd->scsi_pctl = 0; 215*54004Sfujita hd->scsi_temp = 0; 216*54004Sfujita hd->scsi_tch = 0; 217*54004Sfujita hd->scsi_tcm = 0; 218*54004Sfujita hd->scsi_tcl = 0; 219*54004Sfujita hd->scsi_ints = 0; 220*54004Sfujita 221*54004Sfujita /* We can use Asynchronous Transfer only */ 222*54004Sfujita printf("async"); 223*54004Sfujita 224*54004Sfujita /* 225*54004Sfujita * Configure MB89352 with its SCSI address, all 226*54004Sfujita * interrupts enabled & appropriate parity. 227*54004Sfujita */ 228*54004Sfujita hd->scsi_bdid = SCSI_ID; 229*54004Sfujita hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB| 230*54004Sfujita SCTL_PARITY_ENAB | SCTL_RESEL_ENAB | 231*54004Sfujita SCTL_INTR_ENAB; 232*54004Sfujita printf(", parity"); 233*54004Sfujita 234*54004Sfujita DELAY(400); 235*54004Sfujita hd->scsi_sctl &= ~SCTL_DISABLE; 236*54004Sfujita 237*54004Sfujita printf(", scsi id %d\n", SCSI_ID); 238*54004Sfujita } 239*54004Sfujita 240*54004Sfujita 241*54004Sfujita /* 242*54004Sfujita * SPC Arbitration/Selection routine 243*54004Sfujita */ 244*54004Sfujita 245*54004Sfujita int 246*54004Sfujita issue_select(hd, target, flags) 247*54004Sfujita volatile register struct scsidevice *hd; 248*54004Sfujita u_char target; 249*54004Sfujita int flags; 250*54004Sfujita { 251*54004Sfujita #ifndef NODISCONNECT 252*54004Sfujita if (flags & DQ_DISCONNECT) { 253*54004Sfujita hd->scsi_scmd = SCMD_SET_ATN; 254*54004Sfujita } 255*54004Sfujita #endif 256*54004Sfujita 257*54004Sfujita hd->scsi_pctl = 0; 258*54004Sfujita hd->scsi_temp = (1 << SCSI_ID) | (1 << target); 259*54004Sfujita 260*54004Sfujita /* select timeout is hardcoded to 2ms */ 261*54004Sfujita hd->scsi_tch = 0; 262*54004Sfujita hd->scsi_tcm = 32; 263*54004Sfujita hd->scsi_tcl = 4; 264*54004Sfujita 265*54004Sfujita hd->scsi_scmd = SCMD_SELECT; 266*54004Sfujita 267*54004Sfujita return (1); 268*54004Sfujita } 269*54004Sfujita 270*54004Sfujita 271*54004Sfujita /* 272*54004Sfujita * SPC Manual Transfer routines 273*54004Sfujita */ 274*54004Sfujita 275*54004Sfujita /* not yet */ 276*54004Sfujita 277*54004Sfujita 278*54004Sfujita /* 279*54004Sfujita * SPC Program Transfer routines 280*54004Sfujita */ 281*54004Sfujita 282*54004Sfujita int 283*54004Sfujita ixfer_start(hd, len, phase) 284*54004Sfujita volatile register struct scsidevice *hd; 285*54004Sfujita register int len; 286*54004Sfujita register u_char phase; 287*54004Sfujita { 288*54004Sfujita register int wait = 0; 289*54004Sfujita 290*54004Sfujita hd->scsi_sdgc = 0; 291*54004Sfujita 292*54004Sfujita hd->scsi_tch = ((len & 0xff0000) >> 16); 293*54004Sfujita hd->scsi_tcm = ((len & 0x00ff00) >> 8); 294*54004Sfujita hd->scsi_tcl = (len & 0x0000ff); 295*54004Sfujita hd->scsi_pctl = phase; 296*54004Sfujita hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR; 297*54004Sfujita 298*54004Sfujita while ((hd->scsi_ssts & SSTS_BUSY) == 0) { 299*54004Sfujita if (wait > SC_TIMEOUT) { 300*54004Sfujita panic("ixfer_start: too long wait"); 301*54004Sfujita } 302*54004Sfujita wait++; 303*54004Sfujita DELAY(1); 304*54004Sfujita } 305*54004Sfujita } 306*54004Sfujita 307*54004Sfujita int 308*54004Sfujita ixfer_out(hd, len, buf) 309*54004Sfujita volatile register struct scsidevice *hd; 310*54004Sfujita register int len; 311*54004Sfujita register u_char *buf; 312*54004Sfujita { 313*54004Sfujita u_char *t = buf; 314*54004Sfujita register int wait = 0; 315*54004Sfujita #ifdef QUADBYTES 316*54004Sfujita register int qwait = 0; 317*54004Sfujita register int l_len = len >> 3; 318*54004Sfujita register u_long * l_buf = (u_long *) buf; 319*54004Sfujita 320*54004Sfujita for(; l_len > 0; l_len--) { 321*54004Sfujita while ((hd->scsi_ssts & SSTS_DREG_EMPTY) == 0) { 322*54004Sfujita if (qwait > SC_TIMEOUT) { 323*54004Sfujita printf("ixfer_out: quad time out\n"); 324*54004Sfujita printf("ixfer_out: %d bytes sended\n", 325*54004Sfujita (((u_char *) l_buf) - t)); 326*54004Sfujita printf("ixfer_out: TC = %d\n", 327*54004Sfujita ( hd->scsi_tch << 16 ) | 328*54004Sfujita ( hd->scsi_tcm << 8 ) | 329*54004Sfujita ( hd->scsi_tcl )); 330*54004Sfujita return(-1); 331*54004Sfujita } 332*54004Sfujita qwait++; 333*54004Sfujita DELAY(1); 334*54004Sfujita } 335*54004Sfujita *((u_long *) &hd->scsi_dreg) = *l_buf++; 336*54004Sfujita *((u_long *) &hd->scsi_dreg) = *l_buf++; 337*54004Sfujita } 338*54004Sfujita 339*54004Sfujita len &= 0x07; 340*54004Sfujita buf = (u_char *) l_buf; 341*54004Sfujita #endif 342*54004Sfujita for(; len > 0; len--) { 343*54004Sfujita while (hd->scsi_ssts & SSTS_DREG_FULL) { 344*54004Sfujita if (wait > SC_TIMEOUT) { 345*54004Sfujita printf("ixfer_out: time out\n"); 346*54004Sfujita printf("ixfer_out: %d bytes sended\n", 347*54004Sfujita (buf - t)); 348*54004Sfujita return(-1); 349*54004Sfujita } 350*54004Sfujita wait++; 351*54004Sfujita DELAY(1); 352*54004Sfujita } 353*54004Sfujita hd->scsi_dreg = *buf++; 354*54004Sfujita } 355*54004Sfujita 356*54004Sfujita #ifdef QUADBYTES 357*54004Sfujita return(qwait); 358*54004Sfujita #else 359*54004Sfujita return(wait); 360*54004Sfujita #endif 361*54004Sfujita } 362*54004Sfujita 363*54004Sfujita int 364*54004Sfujita ixfer_in(hd, len, buf) 365*54004Sfujita volatile register struct scsidevice *hd; 366*54004Sfujita register int len; 367*54004Sfujita register u_char *buf; 368*54004Sfujita { 369*54004Sfujita u_char *t = buf; 370*54004Sfujita register int wait = 0; 371*54004Sfujita #ifdef QUADBYTES 372*54004Sfujita register int qwait = 0; 373*54004Sfujita register int l_len = len >> 3; 374*54004Sfujita register u_long * l_buf = (u_long *) buf; 375*54004Sfujita 376*54004Sfujita for(; l_len > 0; l_len--) { 377*54004Sfujita while ((hd->scsi_ssts & SSTS_DREG_FULL) == 0) { 378*54004Sfujita if (qwait > SC_TIMEOUT) { 379*54004Sfujita printf("ixfer_in: quad time out\n"); 380*54004Sfujita printf("ixfer_in: %d bytes recieved\n", 381*54004Sfujita (((u_char *) l_buf) - t)); 382*54004Sfujita return(-1); 383*54004Sfujita } 384*54004Sfujita qwait++; 385*54004Sfujita DELAY(1); 386*54004Sfujita } 387*54004Sfujita *l_buf++ = *((u_long *) &hd->scsi_dreg); 388*54004Sfujita *l_buf++ = *((u_long *) &hd->scsi_dreg); 389*54004Sfujita } 390*54004Sfujita 391*54004Sfujita len &= 0x07; 392*54004Sfujita buf = (u_char *) l_buf; 393*54004Sfujita #endif 394*54004Sfujita for (; len > 0; len--) { 395*54004Sfujita while (hd->scsi_ssts & SSTS_DREG_EMPTY) { 396*54004Sfujita if (wait > SC_TIMEOUT) { 397*54004Sfujita printf("ixfer_in: time out\n"); 398*54004Sfujita printf("ixfer_in: %d bytes recieved\n", 399*54004Sfujita (buf - t)); 400*54004Sfujita return(-1); 401*54004Sfujita } 402*54004Sfujita wait++; 403*54004Sfujita DELAY(1); 404*54004Sfujita } 405*54004Sfujita *buf++ = hd->scsi_dreg; 406*54004Sfujita } 407*54004Sfujita 408*54004Sfujita 409*54004Sfujita #ifdef QUADBYTES 410*54004Sfujita return(qwait); 411*54004Sfujita #else 412*54004Sfujita return(wait); 413*54004Sfujita #endif 414*54004Sfujita } 415*54004Sfujita 416*54004Sfujita 417*54004Sfujita #ifdef XFER_ENABLE 418*54004Sfujita /* 419*54004Sfujita * SPC Interrupt base Transfer Routines 420*54004Sfujita */ 421*54004Sfujita 422*54004Sfujita int 423*54004Sfujita txfer_start(hd, len, phase) 424*54004Sfujita volatile register struct scsidevice *hd; 425*54004Sfujita register int len; 426*54004Sfujita register u_char phase; 427*54004Sfujita { 428*54004Sfujita register int wait = 0; 429*54004Sfujita 430*54004Sfujita hd->scsi_sdgc = SDGC_XFER_ENAB; /* for interrupt */ 431*54004Sfujita 432*54004Sfujita hd->scsi_tch = ((len & 0xff0000) >> 16); 433*54004Sfujita hd->scsi_tcm = ((len & 0x00ff00) >> 8); 434*54004Sfujita hd->scsi_tcl = (len & 0x0000ff); 435*54004Sfujita hd->scsi_pctl = phase; 436*54004Sfujita hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR; 437*54004Sfujita 438*54004Sfujita while ((hd->scsi_ssts & SSTS_BUSY) == 0) { 439*54004Sfujita if (wait > SC_TIMEOUT) { 440*54004Sfujita panic("ixfer_start: too long wait"); 441*54004Sfujita } 442*54004Sfujita wait++; 443*54004Sfujita DELAY(1); 444*54004Sfujita } 445*54004Sfujita } 446*54004Sfujita 447*54004Sfujita int 448*54004Sfujita txfer_in(ctlr) 449*54004Sfujita register int ctlr; 450*54004Sfujita { 451*54004Sfujita register struct scsi_softc *hs = &scsi_softc[ctlr]; 452*54004Sfujita volatile register struct scsidevice *hd = (struct scsidevice *) hs->sc_hc->hp_addr; 453*54004Sfujita register struct scsi_queue *dq = hs->sc_sq.dq_forw; 454*54004Sfujita #ifdef QUADBYTES 455*54004Sfujita register u_long *lp; 456*54004Sfujita 457*54004Sfujita if (hd->scsi_ssts & SSTS_DREG_FULL) { 458*54004Sfujita lp = (u_long *) dq->dq_xferp; 459*54004Sfujita 460*54004Sfujita *lp++ = *((u_long *) &hd->scsi_dreg); 461*54004Sfujita *lp++ = *((u_long *) &hd->scsi_dreg); 462*54004Sfujita 463*54004Sfujita dq->dq_xferp = (u_char *) lp; 464*54004Sfujita dq->dq_xfercnt -= 8; 465*54004Sfujita 466*54004Sfujita goto xfer_done; 467*54004Sfujita } 468*54004Sfujita #endif 469*54004Sfujita 470*54004Sfujita *dq->dq_xferp++ = hd->scsi_dreg; 471*54004Sfujita dq->dq_xfercnt--; 472*54004Sfujita 473*54004Sfujita xfer_done: 474*54004Sfujita #ifdef DEBUGPRINT 475*54004Sfujita if (dq->dq_xfercnt == 0) { 476*54004Sfujita dbgprintf("txfer_in: "); 477*54004Sfujita dbgprintf("dq->dq_bp->b_un.b_addr = 0x%s, ", hexstr(dq->dq_bp->b_un.b_addr, 8)); 478*54004Sfujita dbgprintf("dq->dq_xferp = 0x%s :", hexstr(dq->dq_xferp, 8)); 479*54004Sfujita dbgprintf("done\n"); 480*54004Sfujita } 481*54004Sfujita #endif 482*54004Sfujita } 483*54004Sfujita #endif 484*54004Sfujita 485*54004Sfujita /* 486*54004Sfujita * SCSI Job Handler 487*54004Sfujita */ 488*54004Sfujita 489*54004Sfujita int 490*54004Sfujita scstart(ctlr) 491*54004Sfujita int ctlr; 492*54004Sfujita { 493*54004Sfujita register struct scsi_softc *hs = &scsi_softc[ctlr]; 494*54004Sfujita volatile register struct scsidevice *hd = 495*54004Sfujita (struct scsidevice *) hs->sc_hc->hp_addr; 496*54004Sfujita register struct scsi_queue *dq = hs->sc_sq.dq_forw; 497*54004Sfujita 498*54004Sfujita dq->dq_imax = 0; 499*54004Sfujita dq->dq_imin = -1; 500*54004Sfujita dq->dq_omax = 0; 501*54004Sfujita dq->dq_omin = -1; 502*54004Sfujita 503*54004Sfujita hs->sc_flags = 0; 504*54004Sfujita hs->sc_phase = ARB_SEL_PHASE; 505*54004Sfujita 506*54004Sfujita hs->sc_stat = 0; 507*54004Sfujita hs->sc_msg[0] = 0; 508*54004Sfujita 509*54004Sfujita #ifdef DEBUGPRINT 510*54004Sfujita dbgprintf("\n"); 511*54004Sfujita dbgprintf("scstart: ID = %d\n", dq->dq_slave); 512*54004Sfujita dbgprintf("scstart: cdb[0] = %s\n", scsi_command(dq->dq_cdb->cdb[0])); 513*54004Sfujita dbgprintf("scstart: cdb[1] = 0x%s\n", hexstr(dq->dq_cdb->cdb[1], 2)); 514*54004Sfujita dbgprintf("scstart: cdb[2] = 0x%s\n", hexstr(dq->dq_cdb->cdb[2], 2)); 515*54004Sfujita dbgprintf("scstart: cdb[3] = 0x%s\n", hexstr(dq->dq_cdb->cdb[3], 2)); 516*54004Sfujita dbgprintf("scstart: cdb[4] = 0x%s\n", hexstr(dq->dq_cdb->cdb[4], 2)); 517*54004Sfujita dbgprintf("scstart: cdb[5] = 0x%s\n", hexstr(dq->dq_cdb->cdb[5], 2)); 518*54004Sfujita if (dq->dq_cdb->cdb[0] & 0xE0) { 519*54004Sfujita dbgprintf("scstart: cdb[6] = 0x%s\n", hexstr(dq->dq_cdb->cdb[6], 2)); 520*54004Sfujita dbgprintf("scstart: cdb[7] = 0x%s\n", hexstr(dq->dq_cdb->cdb[7], 2)); 521*54004Sfujita dbgprintf("scstart: cdb[8] = 0x%s\n", hexstr(dq->dq_cdb->cdb[8], 2)); 522*54004Sfujita dbgprintf("scstart: cdb[9] = 0x%s\n", hexstr(dq->dq_cdb->cdb[9], 2)); 523*54004Sfujita } 524*54004Sfujita dbgprintf("scstart: bp->b_bcount = %d\n", dq->dq_bp->b_bcount); 525*54004Sfujita dbgprintf("scstart: %s\n", phase_name(hs->sc_phase)); 526*54004Sfujita #endif 527*54004Sfujita 528*54004Sfujita issue_select(hd, dq->dq_slave, dq->dq_flags); 529*54004Sfujita 530*54004Sfujita return(1); 531*54004Sfujita } 532*54004Sfujita 533*54004Sfujita int 534*54004Sfujita _scintr() 535*54004Sfujita { 536*54004Sfujita register struct scsi_softc *hs; 537*54004Sfujita volatile register struct scsidevice *hd; 538*54004Sfujita register int ctlr; 539*54004Sfujita 540*54004Sfujita for (ctlr = 0; ctlr < NSC; ctlr++) { 541*54004Sfujita hs = &scsi_softc[ctlr]; 542*54004Sfujita hd = (struct scsidevice *) hs->sc_hc->hp_addr; 543*54004Sfujita 544*54004Sfujita #ifdef XFER_ENABLE 545*54004Sfujita if (((hd->scsi_psns & PHASE) == DATA_IN_PHASE) && 546*54004Sfujita (hd->scsi_serr & SERR_XFER_OUT)) 547*54004Sfujita txfer_in(ctlr); 548*54004Sfujita #endif 549*54004Sfujita 550*54004Sfujita if (hd->scsi_ints != 0) 551*54004Sfujita scintr(ctlr); 552*54004Sfujita } 553*54004Sfujita 554*54004Sfujita return; 555*54004Sfujita } 556*54004Sfujita 557*54004Sfujita int 558*54004Sfujita scintr(ctlr) 559*54004Sfujita register int ctlr; 560*54004Sfujita { 561*54004Sfujita register struct scsi_softc *hs = &scsi_softc[ctlr]; 562*54004Sfujita volatile register struct scsidevice *hd = (struct scsidevice *) hs->sc_hc->hp_addr; 563*54004Sfujita register struct scsi_queue *dq = hs->sc_sq.dq_forw; 564*54004Sfujita register u_char ints, temp; 565*54004Sfujita register int i, slave; 566*54004Sfujita int wait, len; 567*54004Sfujita u_char *buf; 568*54004Sfujita 569*54004Sfujita ints = hd->scsi_ints; 570*54004Sfujita 571*54004Sfujita #ifdef DEBUGPRINT 572*54004Sfujita dbgprintf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x", 573*54004Sfujita ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 574*54004Sfujita if (hs->sc_phase == CMD_PHASE) 575*54004Sfujita dbgprintf(" [%s]", scsi_command(dq->dq_cdb->cdb[0])); 576*54004Sfujita if (hs->sc_phase & PHASE_MSG) 577*54004Sfujita dbgprintf(" [%s]", scsi_mesg(hs->sc_msg[0])); 578*54004Sfujita dbgprintf("\n"); 579*54004Sfujita #endif 580*54004Sfujita 581*54004Sfujita if (ints & INTS_DISCON) { 582*54004Sfujita if (hs->sc_msg[0] == MSG_CMD_COMPLETE) { 583*54004Sfujita hd->scsi_ints = ints; 584*54004Sfujita 585*54004Sfujita if (hs->sc_lock != NULL) { 586*54004Sfujita *(hs->sc_lock) = SC_IO_COMPLETE; 587*54004Sfujita } else { 588*54004Sfujita (dq->dq_driver->d_intr)(dq->dq_unit, hs->sc_stat); 589*54004Sfujita } 590*54004Sfujita 591*54004Sfujita return; 592*54004Sfujita #ifndef NODISCONNECT 593*54004Sfujita } else if (hs->sc_msg[0] == MSG_DISCONNECT) { 594*54004Sfujita #ifdef DEBUGPRINT 595*54004Sfujita dbgprintf("scintr: DISCONNECT : ctlr = %d, slave = %d, cdb = %s\n", 596*54004Sfujita dq->dq_ctlr, dq->dq_slave, scsi_command(dq->dq_cdb->cdb[0])); 597*54004Sfujita #endif 598*54004Sfujita 599*54004Sfujita hd->scsi_ints = ints; 600*54004Sfujita 601*54004Sfujita scpend(dq); 602*54004Sfujita 603*54004Sfujita dq = hs->sc_sq.dq_forw; 604*54004Sfujita 605*54004Sfujita if (dq != &hs->sc_sq) 606*54004Sfujita (dq->dq_driver->d_start)(dq->dq_unit); 607*54004Sfujita 608*54004Sfujita return; 609*54004Sfujita #endif 610*54004Sfujita } else 611*54004Sfujita goto abort; 612*54004Sfujita 613*54004Sfujita #ifndef NODISCONNECT 614*54004Sfujita } else if (ints & INTS_RESEL) { 615*54004Sfujita temp = hd->scsi_temp & ~(1 << SCSI_ID); 616*54004Sfujita for (slave = 0; temp != 1; slave++) { 617*54004Sfujita temp >>= 1; 618*54004Sfujita } 619*54004Sfujita 620*54004Sfujita hd->scsi_ints = ints; 621*54004Sfujita 622*54004Sfujita scrschdl(ctlr, slave); 623*54004Sfujita 624*54004Sfujita dq = hs->sc_sq.dq_forw; 625*54004Sfujita #ifdef DEBUGPRINT 626*54004Sfujita dbgprintf("\n"); 627*54004Sfujita dbgprintf("scintr: RESELECT : ctlr = %d, slave = %d, cdb = %s\n", 628*54004Sfujita dq->dq_ctlr, dq->dq_slave, scsi_command(dq->dq_cdb->cdb[0])); 629*54004Sfujita #endif 630*54004Sfujita #endif 631*54004Sfujita } else if (ints & INTS_CMD_DONE) { 632*54004Sfujita if (hs->sc_phase == BUS_FREE_PHASE) 633*54004Sfujita goto abort; 634*54004Sfujita else if (hs->sc_phase == MESG_IN_PHASE) { 635*54004Sfujita hd->scsi_scmd = SCMD_RST_ACK; 636*54004Sfujita 637*54004Sfujita if ((hs->sc_msg[0] == MSG_CMD_COMPLETE) || 638*54004Sfujita (hs->sc_msg[0] == MSG_DISCONNECT)) { 639*54004Sfujita hd->scsi_ints = ints; 640*54004Sfujita 641*54004Sfujita hs->sc_phase = BUS_FREE_PHASE; 642*54004Sfujita 643*54004Sfujita return; 644*54004Sfujita } 645*54004Sfujita } 646*54004Sfujita if (hs->sc_flags & SC_SEL_TIMEOUT) 647*54004Sfujita hs->sc_flags &= ~SC_SEL_TIMEOUT; 648*54004Sfujita } else if (ints & INTS_SRV_REQ) { 649*54004Sfujita if (hs->sc_phase != MESG_IN_PHASE) 650*54004Sfujita goto abort; 651*54004Sfujita } else if (ints & INTS_TIMEOUT) { 652*54004Sfujita if (hs->sc_phase == ARB_SEL_PHASE) { 653*54004Sfujita if (hs->sc_flags & SC_SEL_TIMEOUT) { 654*54004Sfujita hd->scsi_ints = ints; 655*54004Sfujita hs->sc_flags &= ~SC_SEL_TIMEOUT; 656*54004Sfujita /* Such SCSI Device is not conected. */ 657*54004Sfujita 658*54004Sfujita if (hs->sc_lock != NULL) { 659*54004Sfujita *(hs->sc_lock) = SC_DEV_NOT_FOUND; 660*54004Sfujita } else { 661*54004Sfujita (dq->dq_driver->d_intr)(dq->dq_unit, SC_DEV_NOT_FOUND); 662*54004Sfujita } 663*54004Sfujita 664*54004Sfujita return; 665*54004Sfujita } else { 666*54004Sfujita /* wait more 250 usec */ 667*54004Sfujita hs->sc_flags |= SC_SEL_TIMEOUT; 668*54004Sfujita hd->scsi_temp = 0; 669*54004Sfujita hd->scsi_tch = 0; 670*54004Sfujita hd->scsi_tcm = 0x06; 671*54004Sfujita hd->scsi_tcl = 0x40; 672*54004Sfujita hd->scsi_ints = ints; 673*54004Sfujita return; 674*54004Sfujita } 675*54004Sfujita } else 676*54004Sfujita goto abort; 677*54004Sfujita } else 678*54004Sfujita goto abort; 679*54004Sfujita 680*54004Sfujita hd->scsi_ints = ints; 681*54004Sfujita 682*54004Sfujita /* 683*54004Sfujita * Next SCSI Transfer 684*54004Sfujita */ 685*54004Sfujita 686*54004Sfujita wait = SC_TIMEOUT; 687*54004Sfujita while ((hd->scsi_psns & PSNS_REQ) == 0) { 688*54004Sfujita if (wait < 0) { 689*54004Sfujita /* hd->scsi_scmd = SCMD_SET_ATN; */ 690*54004Sfujita hd->scsi_scmd = SCMD_RST; 691*54004Sfujita DELAY(40); /* wait 25 micro sec */ 692*54004Sfujita hd->scsi_scmd = 0; 693*54004Sfujita 694*54004Sfujita wait = SC_TIMEOUT; 695*54004Sfujita while (wait-- > 0) 696*54004Sfujita DELAY(1); 697*54004Sfujita 698*54004Sfujita if (hs->sc_lock != NULL) { 699*54004Sfujita *(hs->sc_lock) = SC_IO_TIMEOUT; 700*54004Sfujita } else { 701*54004Sfujita (dq->dq_driver->d_intr)(dq->dq_unit, SC_IO_TIMEOUT); 702*54004Sfujita } 703*54004Sfujita 704*54004Sfujita return; 705*54004Sfujita } 706*54004Sfujita DELAY(1); 707*54004Sfujita wait--; 708*54004Sfujita } 709*54004Sfujita 710*54004Sfujita hs->sc_phase = hd->scsi_psns & PHASE; 711*54004Sfujita 712*54004Sfujita #ifdef DEBUGPRINT 713*54004Sfujita dbgprintf("scintr: %s\n", phase_name(hs->sc_phase)); 714*54004Sfujita #endif 715*54004Sfujita 716*54004Sfujita if ((hs->sc_phase == DATA_OUT_PHASE) || (hs->sc_phase == DATA_IN_PHASE)) { 717*54004Sfujita len = ( hs->sc_lock != NULL ? hs->sc_len : dq->dq_bp->b_bcount ); 718*54004Sfujita buf = ( hs->sc_lock != NULL ? hs->sc_buf : (u_char *) dq->dq_bp->b_un.b_addr ); 719*54004Sfujita } else if (hs->sc_phase == CMD_PHASE) { 720*54004Sfujita len = ( hs->sc_lock != NULL ? hs->sc_cdblen : dq->dq_cdb->len ); 721*54004Sfujita buf = ( hs->sc_lock != NULL ? hs->sc_cdb : dq->dq_cdb->cdb ); 722*54004Sfujita } else if (hs->sc_phase == STATUS_PHASE) { 723*54004Sfujita len = 1; 724*54004Sfujita buf = &hs->sc_stat; 725*54004Sfujita } else { 726*54004Sfujita if (hs->sc_phase == MESG_OUT_PHASE) { 727*54004Sfujita #ifndef NODISCONNECT 728*54004Sfujita hs->sc_msg[0] = MSG_IDENTIFY_DR; 729*54004Sfujita #else 730*54004Sfujita hs->sc_msg[0] = MSG_IDENTIFY; 731*54004Sfujita #endif 732*54004Sfujita } 733*54004Sfujita len = 1; 734*54004Sfujita buf = hs->sc_msg; 735*54004Sfujita } 736*54004Sfujita 737*54004Sfujita #ifdef XFER_ENABLE 738*54004Sfujita if ((hs->sc_lock == NULL) && (hs->sc_phase == DATA_IN_PHASE)) { 739*54004Sfujita dq->dq_xferp = buf; 740*54004Sfujita dq->dq_xfercnt = len; 741*54004Sfujita txfer_start(hd, len, hs->sc_phase); 742*54004Sfujita return; 743*54004Sfujita } 744*54004Sfujita #endif 745*54004Sfujita 746*54004Sfujita ixfer_start(hd, len, hs->sc_phase); 747*54004Sfujita if (hs->sc_phase & PHASE_IO) { 748*54004Sfujita if ((wait = ixfer_in(hd, len, buf)) == -1) { 749*54004Sfujita goto time_out; 750*54004Sfujita } 751*54004Sfujita if (dq->dq_imin == -1) 752*54004Sfujita dq->dq_imin = wait; 753*54004Sfujita else 754*54004Sfujita dq->dq_imin = MIN(wait, dq->dq_imin); 755*54004Sfujita dq->dq_imax = MAX(wait, dq->dq_imax); 756*54004Sfujita } else { 757*54004Sfujita if ((wait = ixfer_out(hd, len, buf)) == -1) { 758*54004Sfujita goto time_out; 759*54004Sfujita } 760*54004Sfujita if (dq->dq_omin == -1) 761*54004Sfujita dq->dq_omin = wait; 762*54004Sfujita else 763*54004Sfujita dq->dq_omin = MIN(wait, dq->dq_omin); 764*54004Sfujita dq->dq_omax = MAX(wait, dq->dq_omax); 765*54004Sfujita } 766*54004Sfujita 767*54004Sfujita return; 768*54004Sfujita 769*54004Sfujita time_out: 770*54004Sfujita scabort(hs, hd); 771*54004Sfujita printf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Current Status\n", 772*54004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 773*54004Sfujita 774*54004Sfujita if (hs->sc_lock != NULL) { 775*54004Sfujita *(hs->sc_lock) = SC_IO_TIMEOUT; 776*54004Sfujita } else { 777*54004Sfujita (dq->dq_driver->d_intr)(dq->dq_unit, SC_IO_TIMEOUT); 778*54004Sfujita } 779*54004Sfujita 780*54004Sfujita return; 781*54004Sfujita 782*54004Sfujita /* 783*54004Sfujita * SCSI Abort 784*54004Sfujita */ 785*54004Sfujita abort: 786*54004Sfujita 787*54004Sfujita /* SCSI IO failed */ 788*54004Sfujita scabort(hs, hd); 789*54004Sfujita hd->scsi_ints = ints; 790*54004Sfujita 791*54004Sfujita if (hs->sc_lock != NULL) { 792*54004Sfujita *(hs->sc_lock) = SC_IO_FAILED; 793*54004Sfujita } else { 794*54004Sfujita (dq->dq_driver->d_intr)(dq->dq_unit, SC_IO_FAILED); 795*54004Sfujita } 796*54004Sfujita 797*54004Sfujita return; 798*54004Sfujita } 799*54004Sfujita 800*54004Sfujita int 801*54004Sfujita scabort(hs, hd) 802*54004Sfujita register struct scsi_softc *hs; 803*54004Sfujita volatile register struct scsidevice *hd; 804*54004Sfujita { 805*54004Sfujita int len; 806*54004Sfujita u_char junk; 807*54004Sfujita 808*54004Sfujita #ifdef DEBUGPRINT 809*54004Sfujita dbgprintall(); 810*54004Sfujita printf("\n"); 811*54004Sfujita #endif 812*54004Sfujita 813*54004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Current Status\n", 814*54004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 815*54004Sfujita 816*54004Sfujita if (hd->scsi_ints != 0) 817*54004Sfujita hd->scsi_ints = hd->scsi_ints; 818*54004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Reset INTS reg.\n", 819*54004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 820*54004Sfujita 821*54004Sfujita if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0) 822*54004Sfujita /* no longer connected to scsi target */ 823*54004Sfujita return; 824*54004Sfujita 825*54004Sfujita /* get the number of bytes remaining in current xfer + fudge */ 826*54004Sfujita len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl; 827*54004Sfujita printf("scabort: Current xfer count = %d\n", len); 828*54004Sfujita 829*54004Sfujita /* for that many bus cycles, try to send an abort msg */ 830*54004Sfujita for (len += 1024; (hd->scsi_ssts & SSTS_INITIATOR) && --len >= 0; ) { 831*54004Sfujita /* 832*54004Sfujita hd->scsi_scmd = SCMD_SET_ATN; 833*54004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Set ATN\n", 834*54004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 835*54004Sfujita */ 836*54004Sfujita while ((hd->scsi_psns & PSNS_REQ) == 0) { 837*54004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Wait for REQ\n", 838*54004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 839*54004Sfujita if (! (hd->scsi_ssts & SSTS_INITIATOR)) 840*54004Sfujita goto out; 841*54004Sfujita DELAY(1); 842*54004Sfujita } 843*54004Sfujita /* 844*54004Sfujita if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE) { 845*54004Sfujita hd->scsi_scmd = SCMD_RST_ATN; 846*54004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Reset ATN\n", 847*54004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 848*54004Sfujita } 849*54004Sfujita */ 850*54004Sfujita hd->scsi_pctl = hs->sc_phase = hd->scsi_psns & PHASE; 851*54004Sfujita printf("scabort: Phase = %s\n", phase_name(hs->sc_phase)); 852*54004Sfujita 853*54004Sfujita if (hd->scsi_psns & PHASE_IO) { 854*54004Sfujita /* one of the input phases - read & discard a byte */ 855*54004Sfujita hd->scsi_scmd = SCMD_SET_ACK; 856*54004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Set ACK\n", 857*54004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 858*54004Sfujita 859*54004Sfujita while (hd->scsi_psns & PSNS_REQ) { 860*54004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Wait for REQ\n", 861*54004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 862*54004Sfujita DELAY(1); 863*54004Sfujita } 864*54004Sfujita 865*54004Sfujita junk = hd->scsi_temp; 866*54004Sfujita printf("scabort: TEMP = 0x%s\n", hexstr(junk, 2)); 867*54004Sfujita } else { 868*54004Sfujita /* one of the output phases - send an abort msg */ 869*54004Sfujita hd->scsi_temp = MSG_ABORT; 870*54004Sfujita hd->scsi_scmd = SCMD_SET_ACK; 871*54004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Set ACK\n", 872*54004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 873*54004Sfujita 874*54004Sfujita while (hd->scsi_psns & PSNS_REQ) { 875*54004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Wait for REQ\n", 876*54004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 877*54004Sfujita DELAY(1); 878*54004Sfujita } 879*54004Sfujita } 880*54004Sfujita 881*54004Sfujita hd->scsi_scmd = SCMD_RST_ACK; 882*54004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Reset ACK\n", 883*54004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 884*54004Sfujita } 885*54004Sfujita out: 886*54004Sfujita /* 887*54004Sfujita * Either the abort was successful & the bus is disconnected or 888*54004Sfujita * the device didn't listen. If the latter, announce the problem. 889*54004Sfujita * Either way, reset the card & the SPC. 890*54004Sfujita */ 891*54004Sfujita if (len < 0 && hs) 892*54004Sfujita printf("sc%d: abort failed. phase=0x%x, ssts=0x%x\n", 893*54004Sfujita hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts); 894*54004Sfujita 895*54004Sfujita while (hd->scsi_ints == 0) 896*54004Sfujita DELAY(1); 897*54004Sfujita 898*54004Sfujita hd->scsi_ints = hd->scsi_ints; 899*54004Sfujita 900*54004Sfujita printf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Current Status\n", 901*54004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 902*54004Sfujita 903*54004Sfujita printf("scabort: SCSI abort operation is done\n"); 904*54004Sfujita } 905*54004Sfujita 906*54004Sfujita 907*54004Sfujita /* 908*54004Sfujita * SPC device queue handling 909*54004Sfujita */ 910*54004Sfujita 911*54004Sfujita int 912*54004Sfujita screq(dq) 913*54004Sfujita register struct scsi_queue *dq; 914*54004Sfujita { 915*54004Sfujita register struct scsi_softc *hs = &scsi_softc[dq->dq_ctlr]; 916*54004Sfujita register struct scsi_queue *hq = &hs->sc_sq; 917*54004Sfujita 918*54004Sfujita insque(dq, hq->dq_back); 919*54004Sfujita 920*54004Sfujita if (dq->dq_back == hq) { 921*54004Sfujita #ifdef QUE_DEBUG 922*54004Sfujita printf("screq: slave = %d, command = %s\n", 923*54004Sfujita hq->dq_forw->dq_slave, 924*54004Sfujita scsi_command(hq->dq_forw->dq_cdb->cdb[0])); 925*54004Sfujita #endif 926*54004Sfujita return(1); 927*54004Sfujita } 928*54004Sfujita 929*54004Sfujita return(0); 930*54004Sfujita } 931*54004Sfujita 932*54004Sfujita #ifndef NODISCONNECT 933*54004Sfujita int 934*54004Sfujita scpend(dq) 935*54004Sfujita register struct scsi_queue *dq; 936*54004Sfujita { 937*54004Sfujita register struct scsi_softc *hs = &scsi_softc[dq->dq_ctlr]; 938*54004Sfujita register struct scsi_queue *hq = &hs->sc_sq; 939*54004Sfujita register struct scsi_queue *wq = &hs->sc_wq; 940*54004Sfujita 941*54004Sfujita remque(dq); 942*54004Sfujita 943*54004Sfujita insque(dq, wq->dq_back); 944*54004Sfujita } 945*54004Sfujita 946*54004Sfujita int 947*54004Sfujita scrschdl(ctlr, slave) 948*54004Sfujita register int ctlr; 949*54004Sfujita register int slave; 950*54004Sfujita { 951*54004Sfujita register struct scsi_softc *hs = &scsi_softc[ctlr]; 952*54004Sfujita register struct scsi_queue *wq = &hs->sc_wq; 953*54004Sfujita register struct scsi_queue *hq = &hs->sc_sq; 954*54004Sfujita register struct scsi_queue *dq; 955*54004Sfujita 956*54004Sfujita for (dq = wq->dq_forw; dq != wq; dq = dq->dq_forw) { 957*54004Sfujita if (dq->dq_slave == slave) 958*54004Sfujita goto found; 959*54004Sfujita } 960*54004Sfujita 961*54004Sfujita return(0); 962*54004Sfujita 963*54004Sfujita found: 964*54004Sfujita remque(dq); 965*54004Sfujita insque(dq, hq); 966*54004Sfujita 967*54004Sfujita return(1); 968*54004Sfujita } 969*54004Sfujita #endif 970*54004Sfujita 971*54004Sfujita int 972*54004Sfujita scfree(dq) 973*54004Sfujita register struct scsi_queue *dq; 974*54004Sfujita { 975*54004Sfujita register struct scsi_softc *hs = &scsi_softc[dq->dq_ctlr]; 976*54004Sfujita register struct scsi_queue *hq = &hs->sc_sq; 977*54004Sfujita int status = hs->sc_stat; 978*54004Sfujita 979*54004Sfujita remque(dq); 980*54004Sfujita 981*54004Sfujita hs->sc_flags = 0; 982*54004Sfujita hs->sc_phase = BUS_FREE_PHASE; 983*54004Sfujita 984*54004Sfujita hs->sc_stat = 0; 985*54004Sfujita hs->sc_msg[0] = 0; 986*54004Sfujita 987*54004Sfujita if ((dq = hq->dq_forw) != hq) { 988*54004Sfujita #ifdef QUE_DEBUG 989*54004Sfujita printf("scfree: slave = %d, command = %s\n", 990*54004Sfujita dq->dq_slave, 991*54004Sfujita scsi_command(dq->dq_cdb->cdb[0])); 992*54004Sfujita #endif 993*54004Sfujita (dq->dq_driver->d_start)(dq->dq_unit); 994*54004Sfujita } 995*54004Sfujita 996*54004Sfujita return(status); 997*54004Sfujita } 998*54004Sfujita 999*54004Sfujita /* 1000*54004Sfujita * SCSI common interface 1001*54004Sfujita */ 1002*54004Sfujita 1003*54004Sfujita int scsi_lock[NSC]; 1004*54004Sfujita 1005*54004Sfujita int 1006*54004Sfujita scsi_result(unit, stat) 1007*54004Sfujita int unit, stat; 1008*54004Sfujita { 1009*54004Sfujita #ifdef SCSI_DEBUG 1010*54004Sfujita printf("scsi_result: stat = %s\n", scsi_status(stat)); 1011*54004Sfujita #endif 1012*54004Sfujita if (stat < 0) 1013*54004Sfujita scsi_lock[unit] = stat; 1014*54004Sfujita else 1015*54004Sfujita scsi_lock[unit] = SC_IO_COMPLETE; 1016*54004Sfujita } 1017*54004Sfujita 1018*54004Sfujita struct driver scsi_driver = { 1019*54004Sfujita (int (*)()) 0, "scsi", (int (*)()) 0, (int (*)()) 0, scsi_result, (int (*)()) 0 1020*54004Sfujita }; 1021*54004Sfujita 1022*54004Sfujita #define SCSI_BUF 8 1023*54004Sfujita 1024*54004Sfujita struct buf scsi_buf[SCSI_BUF]; 1025*54004Sfujita 1026*54004Sfujita int 1027*54004Sfujita scsi_init_buf() 1028*54004Sfujita { 1029*54004Sfujita register struct buf *rbp = &scsi_buf[0]; 1030*54004Sfujita register int i; 1031*54004Sfujita 1032*54004Sfujita rbp->av_forw = rbp->av_back = rbp; 1033*54004Sfujita 1034*54004Sfujita for(i = 0; i < SCSI_BUF; i++) 1035*54004Sfujita scsi_free_buf(&scsi_buf[i]); 1036*54004Sfujita } 1037*54004Sfujita 1038*54004Sfujita int 1039*54004Sfujita scsi_free_buf(bp) 1040*54004Sfujita register struct buf *bp; 1041*54004Sfujita { 1042*54004Sfujita register struct buf *rbp = &scsi_buf[0]; 1043*54004Sfujita 1044*54004Sfujita bp->av_forw = rbp; 1045*54004Sfujita bp->av_back = rbp->av_back; 1046*54004Sfujita 1047*54004Sfujita rbp->av_back->av_forw = bp; 1048*54004Sfujita rbp->av_back = bp; 1049*54004Sfujita } 1050*54004Sfujita 1051*54004Sfujita struct buf * 1052*54004Sfujita scsi_get_buf() 1053*54004Sfujita { 1054*54004Sfujita register struct buf *rbp = &scsi_buf[0]; 1055*54004Sfujita register struct buf *bp = rbp->av_forw; 1056*54004Sfujita 1057*54004Sfujita if (bp == rbp) 1058*54004Sfujita return((struct buf *) 0); 1059*54004Sfujita 1060*54004Sfujita bp->av_forw->av_back = rbp; 1061*54004Sfujita rbp->av_forw = bp->av_forw; 1062*54004Sfujita 1063*54004Sfujita return(bp); 1064*54004Sfujita } 1065*54004Sfujita 1066*54004Sfujita struct scsi_queue scsi_entry[NSC]; 1067*54004Sfujita 1068*54004Sfujita int 1069*54004Sfujita scsi_immed_command(ctlr, slave, lun, cdb, buf, len) 1070*54004Sfujita int ctlr, slave, lun; 1071*54004Sfujita struct scsi_fmt_cdb *cdb; 1072*54004Sfujita u_char *buf; 1073*54004Sfujita unsigned len; 1074*54004Sfujita { 1075*54004Sfujita register struct scsi_softc *hs = &scsi_softc[ctlr]; 1076*54004Sfujita volatile register struct scsidevice *hd = 1077*54004Sfujita (struct scsidevice *) hs->sc_hc->hp_addr; 1078*54004Sfujita register struct scsi_queue *dq = &scsi_entry[ctlr]; 1079*54004Sfujita register struct buf *bp; 1080*54004Sfujita int s, status, wait = 30; 1081*54004Sfujita 1082*54004Sfujita #ifdef SCSI_DEBUG 1083*54004Sfujita printf("scsi_immed_command( %d, %d, %d, cdb(%d,%s), buf, %d): Start\n", 1084*54004Sfujita ctlr, slave, lun, cdb->len, scsi_command(cdb->cdb[0]), len); 1085*54004Sfujita #endif 1086*54004Sfujita 1087*54004Sfujita if ((bp = scsi_get_buf()) == 0) { 1088*54004Sfujita return(SC_BUSY); 1089*54004Sfujita } 1090*54004Sfujita 1091*54004Sfujita s = splbio(); 1092*54004Sfujita 1093*54004Sfujita bp->b_flags = B_BUSY; 1094*54004Sfujita bp->b_bcount = len; 1095*54004Sfujita bp->b_un.b_addr = (caddr_t) buf; 1096*54004Sfujita 1097*54004Sfujita dq->dq_unit = ctlr; 1098*54004Sfujita dq->dq_ctlr = ctlr; 1099*54004Sfujita dq->dq_slave = slave; 1100*54004Sfujita dq->dq_driver = &scsi_driver; 1101*54004Sfujita dq->dq_cdb = cdb; 1102*54004Sfujita dq->dq_bp = bp; 1103*54004Sfujita 1104*54004Sfujita scsi_lock[ctlr] = SC_IN_PROGRESS; 1105*54004Sfujita if (screq(dq)) 1106*54004Sfujita scstart(ctlr); 1107*54004Sfujita 1108*54004Sfujita splx(s); 1109*54004Sfujita 1110*54004Sfujita while (scsi_lock[ctlr] == SC_IN_PROGRESS) { 1111*54004Sfujita if (wait < 0) { 1112*54004Sfujita scabort(hs, hd); 1113*54004Sfujita 1114*54004Sfujita s = splbio(); 1115*54004Sfujita status = scfree(dq); 1116*54004Sfujita splx(s); 1117*54004Sfujita 1118*54004Sfujita bp->b_flags = 0; 1119*54004Sfujita 1120*54004Sfujita return(SC_IO_FAILED); 1121*54004Sfujita } 1122*54004Sfujita 1123*54004Sfujita DELAY(100000); 1124*54004Sfujita wait--; 1125*54004Sfujita } 1126*54004Sfujita 1127*54004Sfujita s = splbio(); 1128*54004Sfujita status = scfree(dq); 1129*54004Sfujita splx(s); 1130*54004Sfujita 1131*54004Sfujita if (scsi_lock[ctlr] < 0) 1132*54004Sfujita status = scsi_lock[ctlr]; 1133*54004Sfujita 1134*54004Sfujita scsi_free_buf(bp); 1135*54004Sfujita 1136*54004Sfujita #ifdef SCSI_DEBUG 1137*54004Sfujita printf("scsi_immed_command: Status -- 0x%x\n", status); 1138*54004Sfujita #endif 1139*54004Sfujita return(status); 1140*54004Sfujita } 1141*54004Sfujita 1142*54004Sfujita int 1143*54004Sfujita scsi_test_unit_rdy(ctlr, slave, lun) 1144*54004Sfujita int ctlr, slave, lun; 1145*54004Sfujita { 1146*54004Sfujita static struct scsi_fmt_cdb cdb = { 6, CMD_TEST_UNIT_READY }; 1147*54004Sfujita int stat; 1148*54004Sfujita 1149*54004Sfujita while ((stat = scsi_immed_command(ctlr, slave, lun, 1150*54004Sfujita &cdb, (u_char *) 0, 0)) == SC_BUSY) { 1151*54004Sfujita DELAY(10000); 1152*54004Sfujita } 1153*54004Sfujita 1154*54004Sfujita return(stat); 1155*54004Sfujita } 1156*54004Sfujita 1157*54004Sfujita int 1158*54004Sfujita scsi_request_sense(ctlr, slave, lun, buf, len) 1159*54004Sfujita int ctlr, slave, lun; 1160*54004Sfujita u_char *buf; 1161*54004Sfujita unsigned len; 1162*54004Sfujita { 1163*54004Sfujita register struct scsi_softc *hs = &scsi_softc[ctlr]; 1164*54004Sfujita volatile register struct scsidevice *hd = 1165*54004Sfujita (struct scsidevice *) hs->sc_hc->hp_addr; 1166*54004Sfujita static struct scsi_fmt_cdb req_cmd = { 6, CMD_REQUEST_SENSE }; 1167*54004Sfujita int s, status, lock; 1168*54004Sfujita 1169*54004Sfujita #ifdef REQ_DEBUG 1170*54004Sfujita printf("scsi_request_sense( %d, %d, %d, buf, %d) -- Start\n", 1171*54004Sfujita ctlr, slave, lun, len); 1172*54004Sfujita #endif 1173*54004Sfujita 1174*54004Sfujita req_cmd.cdb[1] = lun; 1175*54004Sfujita req_cmd.cdb[4] = len; 1176*54004Sfujita 1177*54004Sfujita if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY)) 1178*54004Sfujita return(0); 1179*54004Sfujita 1180*54004Sfujita s = splbio(); 1181*54004Sfujita 1182*54004Sfujita hs->sc_flags = 0; 1183*54004Sfujita hs->sc_phase = ARB_SEL_PHASE; 1184*54004Sfujita 1185*54004Sfujita hs->sc_cdb = req_cmd.cdb; 1186*54004Sfujita hs->sc_cdblen = req_cmd.len; 1187*54004Sfujita hs->sc_buf = buf; 1188*54004Sfujita hs->sc_len = len; 1189*54004Sfujita 1190*54004Sfujita hs->sc_stat = 0; 1191*54004Sfujita hs->sc_msg[0] = 0; 1192*54004Sfujita 1193*54004Sfujita lock = SC_IN_PROGRESS; 1194*54004Sfujita hs->sc_lock = &lock; 1195*54004Sfujita 1196*54004Sfujita issue_select(hd, slave, 0); 1197*54004Sfujita 1198*54004Sfujita spl0(); 1199*54004Sfujita 1200*54004Sfujita while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED)) 1201*54004Sfujita DELAY(10); 1202*54004Sfujita 1203*54004Sfujita splbio(); 1204*54004Sfujita 1205*54004Sfujita hs->sc_flags = 0; 1206*54004Sfujita hs->sc_phase = BUS_FREE_PHASE; 1207*54004Sfujita 1208*54004Sfujita hs->sc_cdb = NULL; 1209*54004Sfujita hs->sc_cdblen = 0; 1210*54004Sfujita hs->sc_buf = NULL; 1211*54004Sfujita hs->sc_len = 0; 1212*54004Sfujita hs->sc_lock = NULL; 1213*54004Sfujita 1214*54004Sfujita status = hs->sc_stat; 1215*54004Sfujita 1216*54004Sfujita hs->sc_stat = 0; 1217*54004Sfujita hs->sc_msg[0] = 0; 1218*54004Sfujita 1219*54004Sfujita splx(s); 1220*54004Sfujita 1221*54004Sfujita if (lock == SC_IO_COMPLETE) { 1222*54004Sfujita #ifdef REQ_DEBUG 1223*54004Sfujita printf("scsi_request_sense: Status -- 0x%x\n", status); 1224*54004Sfujita #endif 1225*54004Sfujita return(status); 1226*54004Sfujita } else { 1227*54004Sfujita return(lock); 1228*54004Sfujita } 1229*54004Sfujita } 1230*54004Sfujita #endif 1231