154004Sfujita /* 254004Sfujita * Copyright (c) 1992 OMRON Corporation. 354004Sfujita * Copyright (c) 1992 The Regents of the University of California. 454004Sfujita * All rights reserved. 554004Sfujita * 654004Sfujita * This code is derived from software contributed to Berkeley by 754004Sfujita * OMRON Corporation. 854004Sfujita * 954004Sfujita * %sccs.include.redist.c% 1054004Sfujita * 11*55175Saki * @(#)sc.c 7.2 (Berkeley) 07/13/92 1254004Sfujita */ 1354004Sfujita 1454004Sfujita /* 1554004Sfujita * sc.c -- FUJITSU MB89352 SCSI Protocole Controller (SPC) Device Driver 1654004Sfujita * 1754004Sfujita * remaked by A.Fujita, Mar-22-1992 1854004Sfujita * remaked again by A.Fujita, Apr-16-1992 1954004Sfujita */ 2054004Sfujita 2154004Sfujita #define DEBUG_FUNC 2254004Sfujita 2354004Sfujita #include "sc.h" 2454004Sfujita #if NSC > 0 2554004Sfujita 2654004Sfujita #include "sys/param.h" 2754004Sfujita #include "sys/systm.h" 2854004Sfujita #include "sys/buf.h" 2954004Sfujita #include "device.h" 3054004Sfujita 3154004Sfujita #include "scsireg.h" 3254004Sfujita #include "scsivar.h" 3354004Sfujita 3454004Sfujita /* 3554004Sfujita * SC Driver Options 3654004Sfujita */ 3754004Sfujita 3854004Sfujita #define QUADBYTES /* 4 bytes access to SPC DREG Reg. */ 3954004Sfujita #define NODISCONNECT /* not used SCSI DISCONNECT Ops. */ 4054004Sfujita #undef XFER_ENABLE /* using interrupt for DREG access */ 4154004Sfujita 4254004Sfujita 4354004Sfujita #define SCSI_IPL 2 4454004Sfujita #define SCSI_ID 7 4554004Sfujita 4654004Sfujita extern char *hexstr(); 4754004Sfujita 4854004Sfujita int scinit(), scstart(), scintr(); 4954004Sfujita void screset(); 5054004Sfujita struct driver scdriver = { 5154004Sfujita scinit, "sc", scstart, (int (*)()) 0, scintr, (int (*)()) 0 5254004Sfujita }; 5354004Sfujita 5454004Sfujita struct scsi_softc scsi_softc[NSC]; 5554004Sfujita 5654004Sfujita 5754004Sfujita #define SC_TIMEOUT 0x01400000 /* (20971520) */ 5854004Sfujita 5954004Sfujita 6054004Sfujita /* 6154004Sfujita * for DEBUG 6254004Sfujita */ 6354004Sfujita 6454004Sfujita char * 6554004Sfujita scsi_status(stat) 6654004Sfujita u_char stat; 6754004Sfujita { 6854004Sfujita if ((stat & 0x1e) == 0) 6954004Sfujita return("Good"); 7054004Sfujita else if ((stat & 0x1e) == STS_CHECKCOND) 7154004Sfujita return("Check Condition"); 7254004Sfujita else if ((stat & 0x1e) == STS_CONDMET) 7354004Sfujita return("Condition Met"); 7454004Sfujita else if ((stat & 0x1e) == STS_BUSY) 7554004Sfujita return("Busy"); 7654004Sfujita else if ((stat & 0x1e) == STS_INTERMED) 7754004Sfujita return("Intermediate status sent"); 7854004Sfujita else if ((stat & 0x1e) == STS_EXT) 7954004Sfujita return("Extended status valid"); 8054004Sfujita else 8154004Sfujita return("Unknown Status"); 8254004Sfujita } 8354004Sfujita 8454004Sfujita #ifdef DEBUG_FUNC 8554004Sfujita 8654004Sfujita char * 8754004Sfujita scsi_command(cmd) 8854004Sfujita u_char cmd; 8954004Sfujita { 9054004Sfujita if (cmd == CMD_TEST_UNIT_READY) 9154004Sfujita return("TEST_UNIT_READY"); 9254004Sfujita else if (cmd == CMD_REQUEST_SENSE) 9354004Sfujita return("REQUEST_SENSE"); 9454004Sfujita else if (cmd == CMD_INQUIRY) 9554004Sfujita return("INQUIRY"); 9654004Sfujita else if (cmd == CMD_READ) 9754004Sfujita return("READ"); 9854004Sfujita else if (cmd == CMD_WRITE) 9954004Sfujita return("WRITE"); 10054004Sfujita else if (cmd == CMD_READ_EXT) 10154004Sfujita return("READ EXT"); 10254004Sfujita else if (cmd == CMD_WRITE_EXT) 10354004Sfujita return("WRITE_EXT"); 10454004Sfujita else if (cmd == CMD_READ_CAPACITY) 10554004Sfujita return("READ_CAPACITY"); 10654004Sfujita else 10754004Sfujita return(hexstr(cmd, 2)); 10854004Sfujita } 10954004Sfujita 11054004Sfujita char * 11154004Sfujita scsi_mesg(mesg) 11254004Sfujita u_char mesg; 11354004Sfujita { 11454004Sfujita if (mesg == MSG_CMD_COMPLETE) 11554004Sfujita return("Command Complete"); 11654004Sfujita else if (mesg == MSG_EXT_MESSAGE) 11754004Sfujita return("Extended Message"); 11854004Sfujita else if (mesg == MSG_SAVE_DATA_PTR) 11954004Sfujita return("Save Data Pointer"); 12054004Sfujita else if (mesg == MSG_RESTORE_PTR) 12154004Sfujita return("Restore Pointer"); 12254004Sfujita else if (mesg == MSG_DISCONNECT) 12354004Sfujita return("Disconnect"); 12454004Sfujita else if (mesg == MSG_INIT_DETECT_ERROR) 12554004Sfujita return("Initiator Detected Error"); 12654004Sfujita else if (mesg == MSG_ABORT) 12754004Sfujita return("Abort"); 12854004Sfujita else if (mesg == MSG_REJECT) 12954004Sfujita return("Message Reject"); 13054004Sfujita else if (mesg == MSG_NOOP) 13154004Sfujita return("No Operation"); 13254004Sfujita else if (mesg == MSG_PARITY_ERROR) 13354004Sfujita return("Message Parity Error"); 13454004Sfujita else if (mesg == MSG_BUS_DEVICE_RESET) 13554004Sfujita return("Bus Device Reset"); 13654004Sfujita else if (mesg == MSG_IDENTIFY) 13754004Sfujita return("Identify"); 13854004Sfujita else if (mesg == MSG_IDENTIFY_DR) 13954004Sfujita return("Identify (Disconnect)"); 14054004Sfujita else 14154004Sfujita return("Unknown Message"); 14254004Sfujita } 14354004Sfujita 14454004Sfujita char * 14554004Sfujita phase_name(phase) 14654004Sfujita u_char phase; 14754004Sfujita { 14854004Sfujita if (phase == DATA_OUT_PHASE) 14954004Sfujita return("Data Out"); 15054004Sfujita else if (phase == DATA_IN_PHASE) 15154004Sfujita return("Data In"); 15254004Sfujita else if (phase == CMD_PHASE) 15354004Sfujita return("Command"); 15454004Sfujita else if (phase == STATUS_PHASE) 15554004Sfujita return("Status"); 15654004Sfujita else if (phase == BUS_FREE_PHASE) 15754004Sfujita return("Bus Free"); 15854004Sfujita else if (phase == ARB_SEL_PHASE) 15954004Sfujita return("Arbitration/Select"); 16054004Sfujita else if (phase == MESG_OUT_PHASE) 16154004Sfujita return("Message Out"); 16254004Sfujita else if (phase == MESG_IN_PHASE) 16354004Sfujita return("Message In"); 16454004Sfujita else 16554004Sfujita return("Unknown"); 16654004Sfujita } 16754004Sfujita #endif 16854004Sfujita 16954004Sfujita /* 17054004Sfujita * Initialize SPC & Data Structure 17154004Sfujita */ 17254004Sfujita 17354004Sfujita int 17454004Sfujita scinit(hc) 17554004Sfujita register struct hp_ctlr *hc; 17654004Sfujita { 17754004Sfujita register struct scsi_softc *hs = &scsi_softc[hc->hp_unit]; 17854004Sfujita register int i; 17954004Sfujita 18054004Sfujita hc->hp_ipl = SCSI_IPL; 18154004Sfujita hs->sc_hc = hc; 18254004Sfujita hs->sc_sq.dq_forw = hs->sc_sq.dq_back = &hs->sc_sq; 18354004Sfujita hs->sc_wq.dq_forw = hs->sc_wq.dq_back = &hs->sc_wq; 18454004Sfujita 18554004Sfujita hs->sc_flags = 0; 18654004Sfujita hs->sc_phase = BUS_FREE_PHASE; 18754004Sfujita 18854004Sfujita hs->sc_stat = 0; 18954004Sfujita hs->sc_msg[0] = 0; 19054004Sfujita 19154004Sfujita scsi_init_buf(); 19254004Sfujita 19354004Sfujita screset(hc->hp_unit); 19454004Sfujita 19554004Sfujita return(1); 19654004Sfujita } 19754004Sfujita 19854004Sfujita void 19954004Sfujita screset(unit) 20054004Sfujita register int unit; 20154004Sfujita { 20254004Sfujita register struct scsi_softc *hs = &scsi_softc[unit]; 20354004Sfujita volatile register struct scsidevice *hd = 20454004Sfujita (struct scsidevice *)hs->sc_hc->hp_addr; 20554004Sfujita 20654004Sfujita printf("sc%d: ", unit); 20754004Sfujita 20854004Sfujita /* 20954004Sfujita * Disable interrupts then reset the FUJI chip. 21054004Sfujita */ 21154004Sfujita 21254004Sfujita hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST; 21354004Sfujita hd->scsi_scmd = 0; 21454004Sfujita hd->scsi_pctl = 0; 21554004Sfujita hd->scsi_temp = 0; 21654004Sfujita hd->scsi_tch = 0; 21754004Sfujita hd->scsi_tcm = 0; 21854004Sfujita hd->scsi_tcl = 0; 21954004Sfujita hd->scsi_ints = 0; 22054004Sfujita 22154004Sfujita /* We can use Asynchronous Transfer only */ 22254004Sfujita printf("async"); 22354004Sfujita 22454004Sfujita /* 22554004Sfujita * Configure MB89352 with its SCSI address, all 22654004Sfujita * interrupts enabled & appropriate parity. 22754004Sfujita */ 22854004Sfujita hd->scsi_bdid = SCSI_ID; 22954004Sfujita hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB| 23054004Sfujita SCTL_PARITY_ENAB | SCTL_RESEL_ENAB | 23154004Sfujita SCTL_INTR_ENAB; 23254004Sfujita printf(", parity"); 23354004Sfujita 23454004Sfujita DELAY(400); 23554004Sfujita hd->scsi_sctl &= ~SCTL_DISABLE; 23654004Sfujita 23754004Sfujita printf(", scsi id %d\n", SCSI_ID); 23854004Sfujita } 23954004Sfujita 24054004Sfujita 24154004Sfujita /* 24254004Sfujita * SPC Arbitration/Selection routine 24354004Sfujita */ 24454004Sfujita 24554004Sfujita int 24654004Sfujita issue_select(hd, target, flags) 24754004Sfujita volatile register struct scsidevice *hd; 24854004Sfujita u_char target; 24954004Sfujita int flags; 25054004Sfujita { 25154004Sfujita #ifndef NODISCONNECT 25254004Sfujita if (flags & DQ_DISCONNECT) { 25354004Sfujita hd->scsi_scmd = SCMD_SET_ATN; 25454004Sfujita } 25554004Sfujita #endif 25654004Sfujita 25754004Sfujita hd->scsi_pctl = 0; 25854004Sfujita hd->scsi_temp = (1 << SCSI_ID) | (1 << target); 25954004Sfujita 26054004Sfujita /* select timeout is hardcoded to 2ms */ 26154004Sfujita hd->scsi_tch = 0; 26254004Sfujita hd->scsi_tcm = 32; 26354004Sfujita hd->scsi_tcl = 4; 26454004Sfujita 26554004Sfujita hd->scsi_scmd = SCMD_SELECT; 26654004Sfujita 26754004Sfujita return (1); 26854004Sfujita } 26954004Sfujita 27054004Sfujita 27154004Sfujita /* 27254004Sfujita * SPC Manual Transfer routines 27354004Sfujita */ 27454004Sfujita 27554004Sfujita /* not yet */ 27654004Sfujita 27754004Sfujita 27854004Sfujita /* 27954004Sfujita * SPC Program Transfer routines 28054004Sfujita */ 28154004Sfujita 28254004Sfujita int 28354004Sfujita ixfer_start(hd, len, phase) 28454004Sfujita volatile register struct scsidevice *hd; 28554004Sfujita register int len; 28654004Sfujita register u_char phase; 28754004Sfujita { 28854004Sfujita register int wait = 0; 28954004Sfujita 29054004Sfujita hd->scsi_sdgc = 0; 29154004Sfujita 29254004Sfujita hd->scsi_tch = ((len & 0xff0000) >> 16); 29354004Sfujita hd->scsi_tcm = ((len & 0x00ff00) >> 8); 29454004Sfujita hd->scsi_tcl = (len & 0x0000ff); 29554004Sfujita hd->scsi_pctl = phase; 29654004Sfujita hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR; 29754004Sfujita 29854004Sfujita while ((hd->scsi_ssts & SSTS_BUSY) == 0) { 29954004Sfujita if (wait > SC_TIMEOUT) { 30054004Sfujita panic("ixfer_start: too long wait"); 30154004Sfujita } 30254004Sfujita wait++; 30354004Sfujita DELAY(1); 30454004Sfujita } 30554004Sfujita } 30654004Sfujita 30754004Sfujita int 30854004Sfujita ixfer_out(hd, len, buf) 30954004Sfujita volatile register struct scsidevice *hd; 31054004Sfujita register int len; 31154004Sfujita register u_char *buf; 31254004Sfujita { 31354004Sfujita u_char *t = buf; 31454004Sfujita register int wait = 0; 31554004Sfujita #ifdef QUADBYTES 31654004Sfujita register int qwait = 0; 31754004Sfujita register int l_len = len >> 3; 31854004Sfujita register u_long * l_buf = (u_long *) buf; 31954004Sfujita 32054004Sfujita for(; l_len > 0; l_len--) { 32154004Sfujita while ((hd->scsi_ssts & SSTS_DREG_EMPTY) == 0) { 32254004Sfujita if (qwait > SC_TIMEOUT) { 32354004Sfujita printf("ixfer_out: quad time out\n"); 32454004Sfujita printf("ixfer_out: %d bytes sended\n", 32554004Sfujita (((u_char *) l_buf) - t)); 32654004Sfujita printf("ixfer_out: TC = %d\n", 32754004Sfujita ( hd->scsi_tch << 16 ) | 32854004Sfujita ( hd->scsi_tcm << 8 ) | 32954004Sfujita ( hd->scsi_tcl )); 33054004Sfujita return(-1); 33154004Sfujita } 33254004Sfujita qwait++; 33354004Sfujita DELAY(1); 33454004Sfujita } 33554004Sfujita *((u_long *) &hd->scsi_dreg) = *l_buf++; 33654004Sfujita *((u_long *) &hd->scsi_dreg) = *l_buf++; 33754004Sfujita } 33854004Sfujita 33954004Sfujita len &= 0x07; 34054004Sfujita buf = (u_char *) l_buf; 34154004Sfujita #endif 34254004Sfujita for(; len > 0; len--) { 34354004Sfujita while (hd->scsi_ssts & SSTS_DREG_FULL) { 34454004Sfujita if (wait > SC_TIMEOUT) { 34554004Sfujita printf("ixfer_out: time out\n"); 34654004Sfujita printf("ixfer_out: %d bytes sended\n", 34754004Sfujita (buf - t)); 34854004Sfujita return(-1); 34954004Sfujita } 35054004Sfujita wait++; 35154004Sfujita DELAY(1); 35254004Sfujita } 35354004Sfujita hd->scsi_dreg = *buf++; 35454004Sfujita } 35554004Sfujita 35654004Sfujita #ifdef QUADBYTES 35754004Sfujita return(qwait); 35854004Sfujita #else 35954004Sfujita return(wait); 36054004Sfujita #endif 36154004Sfujita } 36254004Sfujita 36354004Sfujita int 36454004Sfujita ixfer_in(hd, len, buf) 36554004Sfujita volatile register struct scsidevice *hd; 36654004Sfujita register int len; 36754004Sfujita register u_char *buf; 36854004Sfujita { 36954004Sfujita u_char *t = buf; 37054004Sfujita register int wait = 0; 37154004Sfujita #ifdef QUADBYTES 37254004Sfujita register int qwait = 0; 37354004Sfujita register int l_len = len >> 3; 37454004Sfujita register u_long * l_buf = (u_long *) buf; 37554004Sfujita 37654004Sfujita for(; l_len > 0; l_len--) { 37754004Sfujita while ((hd->scsi_ssts & SSTS_DREG_FULL) == 0) { 37854004Sfujita if (qwait > SC_TIMEOUT) { 37954004Sfujita printf("ixfer_in: quad time out\n"); 38054004Sfujita printf("ixfer_in: %d bytes recieved\n", 38154004Sfujita (((u_char *) l_buf) - t)); 38254004Sfujita return(-1); 38354004Sfujita } 38454004Sfujita qwait++; 38554004Sfujita DELAY(1); 38654004Sfujita } 38754004Sfujita *l_buf++ = *((u_long *) &hd->scsi_dreg); 38854004Sfujita *l_buf++ = *((u_long *) &hd->scsi_dreg); 38954004Sfujita } 39054004Sfujita 39154004Sfujita len &= 0x07; 39254004Sfujita buf = (u_char *) l_buf; 39354004Sfujita #endif 39454004Sfujita for (; len > 0; len--) { 39554004Sfujita while (hd->scsi_ssts & SSTS_DREG_EMPTY) { 39654004Sfujita if (wait > SC_TIMEOUT) { 39754004Sfujita printf("ixfer_in: time out\n"); 39854004Sfujita printf("ixfer_in: %d bytes recieved\n", 39954004Sfujita (buf - t)); 40054004Sfujita return(-1); 40154004Sfujita } 40254004Sfujita wait++; 40354004Sfujita DELAY(1); 40454004Sfujita } 40554004Sfujita *buf++ = hd->scsi_dreg; 40654004Sfujita } 40754004Sfujita 40854004Sfujita 40954004Sfujita #ifdef QUADBYTES 41054004Sfujita return(qwait); 41154004Sfujita #else 41254004Sfujita return(wait); 41354004Sfujita #endif 41454004Sfujita } 41554004Sfujita 41654004Sfujita 41754004Sfujita #ifdef XFER_ENABLE 41854004Sfujita /* 41954004Sfujita * SPC Interrupt base Transfer Routines 42054004Sfujita */ 42154004Sfujita 42254004Sfujita int 42354004Sfujita txfer_start(hd, len, phase) 42454004Sfujita volatile register struct scsidevice *hd; 42554004Sfujita register int len; 42654004Sfujita register u_char phase; 42754004Sfujita { 42854004Sfujita register int wait = 0; 42954004Sfujita 43054004Sfujita hd->scsi_sdgc = SDGC_XFER_ENAB; /* for interrupt */ 43154004Sfujita 43254004Sfujita hd->scsi_tch = ((len & 0xff0000) >> 16); 43354004Sfujita hd->scsi_tcm = ((len & 0x00ff00) >> 8); 43454004Sfujita hd->scsi_tcl = (len & 0x0000ff); 43554004Sfujita hd->scsi_pctl = phase; 43654004Sfujita hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR; 43754004Sfujita 43854004Sfujita while ((hd->scsi_ssts & SSTS_BUSY) == 0) { 43954004Sfujita if (wait > SC_TIMEOUT) { 44054004Sfujita panic("ixfer_start: too long wait"); 44154004Sfujita } 44254004Sfujita wait++; 44354004Sfujita DELAY(1); 44454004Sfujita } 44554004Sfujita } 44654004Sfujita 44754004Sfujita int 44854004Sfujita txfer_in(ctlr) 44954004Sfujita register int ctlr; 45054004Sfujita { 45154004Sfujita register struct scsi_softc *hs = &scsi_softc[ctlr]; 45254004Sfujita volatile register struct scsidevice *hd = (struct scsidevice *) hs->sc_hc->hp_addr; 45354004Sfujita register struct scsi_queue *dq = hs->sc_sq.dq_forw; 45454004Sfujita #ifdef QUADBYTES 45554004Sfujita register u_long *lp; 45654004Sfujita 45754004Sfujita if (hd->scsi_ssts & SSTS_DREG_FULL) { 45854004Sfujita lp = (u_long *) dq->dq_xferp; 45954004Sfujita 46054004Sfujita *lp++ = *((u_long *) &hd->scsi_dreg); 46154004Sfujita *lp++ = *((u_long *) &hd->scsi_dreg); 46254004Sfujita 46354004Sfujita dq->dq_xferp = (u_char *) lp; 46454004Sfujita dq->dq_xfercnt -= 8; 46554004Sfujita 46654004Sfujita goto xfer_done; 46754004Sfujita } 46854004Sfujita #endif 46954004Sfujita 47054004Sfujita *dq->dq_xferp++ = hd->scsi_dreg; 47154004Sfujita dq->dq_xfercnt--; 47254004Sfujita 47354004Sfujita xfer_done: 47454004Sfujita #ifdef DEBUGPRINT 47554004Sfujita if (dq->dq_xfercnt == 0) { 47654004Sfujita dbgprintf("txfer_in: "); 47754004Sfujita dbgprintf("dq->dq_bp->b_un.b_addr = 0x%s, ", hexstr(dq->dq_bp->b_un.b_addr, 8)); 47854004Sfujita dbgprintf("dq->dq_xferp = 0x%s :", hexstr(dq->dq_xferp, 8)); 47954004Sfujita dbgprintf("done\n"); 48054004Sfujita } 48154004Sfujita #endif 48254004Sfujita } 48354004Sfujita #endif 48454004Sfujita 48554004Sfujita /* 48654004Sfujita * SCSI Job Handler 48754004Sfujita */ 48854004Sfujita 48954004Sfujita int 49054004Sfujita scstart(ctlr) 49154004Sfujita int ctlr; 49254004Sfujita { 49354004Sfujita register struct scsi_softc *hs = &scsi_softc[ctlr]; 49454004Sfujita volatile register struct scsidevice *hd = 49554004Sfujita (struct scsidevice *) hs->sc_hc->hp_addr; 49654004Sfujita register struct scsi_queue *dq = hs->sc_sq.dq_forw; 49754004Sfujita 49854004Sfujita dq->dq_imax = 0; 49954004Sfujita dq->dq_imin = -1; 50054004Sfujita dq->dq_omax = 0; 50154004Sfujita dq->dq_omin = -1; 50254004Sfujita 50354004Sfujita hs->sc_flags = 0; 50454004Sfujita hs->sc_phase = ARB_SEL_PHASE; 50554004Sfujita 50654004Sfujita hs->sc_stat = 0; 50754004Sfujita hs->sc_msg[0] = 0; 50854004Sfujita 50954004Sfujita #ifdef DEBUGPRINT 51054004Sfujita dbgprintf("\n"); 51154004Sfujita dbgprintf("scstart: ID = %d\n", dq->dq_slave); 51254004Sfujita dbgprintf("scstart: cdb[0] = %s\n", scsi_command(dq->dq_cdb->cdb[0])); 51354004Sfujita dbgprintf("scstart: cdb[1] = 0x%s\n", hexstr(dq->dq_cdb->cdb[1], 2)); 51454004Sfujita dbgprintf("scstart: cdb[2] = 0x%s\n", hexstr(dq->dq_cdb->cdb[2], 2)); 51554004Sfujita dbgprintf("scstart: cdb[3] = 0x%s\n", hexstr(dq->dq_cdb->cdb[3], 2)); 51654004Sfujita dbgprintf("scstart: cdb[4] = 0x%s\n", hexstr(dq->dq_cdb->cdb[4], 2)); 51754004Sfujita dbgprintf("scstart: cdb[5] = 0x%s\n", hexstr(dq->dq_cdb->cdb[5], 2)); 51854004Sfujita if (dq->dq_cdb->cdb[0] & 0xE0) { 51954004Sfujita dbgprintf("scstart: cdb[6] = 0x%s\n", hexstr(dq->dq_cdb->cdb[6], 2)); 52054004Sfujita dbgprintf("scstart: cdb[7] = 0x%s\n", hexstr(dq->dq_cdb->cdb[7], 2)); 52154004Sfujita dbgprintf("scstart: cdb[8] = 0x%s\n", hexstr(dq->dq_cdb->cdb[8], 2)); 52254004Sfujita dbgprintf("scstart: cdb[9] = 0x%s\n", hexstr(dq->dq_cdb->cdb[9], 2)); 52354004Sfujita } 52454004Sfujita dbgprintf("scstart: bp->b_bcount = %d\n", dq->dq_bp->b_bcount); 52554004Sfujita dbgprintf("scstart: %s\n", phase_name(hs->sc_phase)); 52654004Sfujita #endif 52754004Sfujita 52854004Sfujita issue_select(hd, dq->dq_slave, dq->dq_flags); 52954004Sfujita 53054004Sfujita return(1); 53154004Sfujita } 53254004Sfujita 53354004Sfujita int 53454004Sfujita _scintr() 53554004Sfujita { 53654004Sfujita register struct scsi_softc *hs; 53754004Sfujita volatile register struct scsidevice *hd; 53854004Sfujita register int ctlr; 53954004Sfujita 54054004Sfujita for (ctlr = 0; ctlr < NSC; ctlr++) { 54154004Sfujita hs = &scsi_softc[ctlr]; 54254004Sfujita hd = (struct scsidevice *) hs->sc_hc->hp_addr; 54354004Sfujita 54454004Sfujita #ifdef XFER_ENABLE 54554004Sfujita if (((hd->scsi_psns & PHASE) == DATA_IN_PHASE) && 54654004Sfujita (hd->scsi_serr & SERR_XFER_OUT)) 54754004Sfujita txfer_in(ctlr); 54854004Sfujita #endif 54954004Sfujita 55054004Sfujita if (hd->scsi_ints != 0) 55154004Sfujita scintr(ctlr); 55254004Sfujita } 55354004Sfujita 55454004Sfujita return; 55554004Sfujita } 55654004Sfujita 55754004Sfujita int 55854004Sfujita scintr(ctlr) 55954004Sfujita register int ctlr; 56054004Sfujita { 56154004Sfujita register struct scsi_softc *hs = &scsi_softc[ctlr]; 56254004Sfujita volatile register struct scsidevice *hd = (struct scsidevice *) hs->sc_hc->hp_addr; 56354004Sfujita register struct scsi_queue *dq = hs->sc_sq.dq_forw; 56454004Sfujita register u_char ints, temp; 56554004Sfujita register int i, slave; 56654004Sfujita int wait, len; 56754004Sfujita u_char *buf; 56854004Sfujita 56954004Sfujita ints = hd->scsi_ints; 57054004Sfujita 57154004Sfujita #ifdef DEBUGPRINT 57254004Sfujita dbgprintf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x", 57354004Sfujita ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 57454004Sfujita if (hs->sc_phase == CMD_PHASE) 57554004Sfujita dbgprintf(" [%s]", scsi_command(dq->dq_cdb->cdb[0])); 57654004Sfujita if (hs->sc_phase & PHASE_MSG) 57754004Sfujita dbgprintf(" [%s]", scsi_mesg(hs->sc_msg[0])); 57854004Sfujita dbgprintf("\n"); 57954004Sfujita #endif 58054004Sfujita 58154004Sfujita if (ints & INTS_DISCON) { 58254004Sfujita if (hs->sc_msg[0] == MSG_CMD_COMPLETE) { 58354004Sfujita hd->scsi_ints = ints; 58454004Sfujita 58554004Sfujita if (hs->sc_lock != NULL) { 58654004Sfujita *(hs->sc_lock) = SC_IO_COMPLETE; 58754004Sfujita } else { 58854004Sfujita (dq->dq_driver->d_intr)(dq->dq_unit, hs->sc_stat); 58954004Sfujita } 59054004Sfujita 59154004Sfujita return; 59254004Sfujita #ifndef NODISCONNECT 59354004Sfujita } else if (hs->sc_msg[0] == MSG_DISCONNECT) { 59454004Sfujita #ifdef DEBUGPRINT 59554004Sfujita dbgprintf("scintr: DISCONNECT : ctlr = %d, slave = %d, cdb = %s\n", 59654004Sfujita dq->dq_ctlr, dq->dq_slave, scsi_command(dq->dq_cdb->cdb[0])); 59754004Sfujita #endif 59854004Sfujita 59954004Sfujita hd->scsi_ints = ints; 60054004Sfujita 60154004Sfujita scpend(dq); 60254004Sfujita 60354004Sfujita dq = hs->sc_sq.dq_forw; 60454004Sfujita 60554004Sfujita if (dq != &hs->sc_sq) 60654004Sfujita (dq->dq_driver->d_start)(dq->dq_unit); 60754004Sfujita 60854004Sfujita return; 60954004Sfujita #endif 61054004Sfujita } else 61154004Sfujita goto abort; 61254004Sfujita 61354004Sfujita #ifndef NODISCONNECT 61454004Sfujita } else if (ints & INTS_RESEL) { 61554004Sfujita temp = hd->scsi_temp & ~(1 << SCSI_ID); 61654004Sfujita for (slave = 0; temp != 1; slave++) { 61754004Sfujita temp >>= 1; 61854004Sfujita } 61954004Sfujita 62054004Sfujita hd->scsi_ints = ints; 62154004Sfujita 62254004Sfujita scrschdl(ctlr, slave); 62354004Sfujita 62454004Sfujita dq = hs->sc_sq.dq_forw; 62554004Sfujita #ifdef DEBUGPRINT 62654004Sfujita dbgprintf("\n"); 62754004Sfujita dbgprintf("scintr: RESELECT : ctlr = %d, slave = %d, cdb = %s\n", 62854004Sfujita dq->dq_ctlr, dq->dq_slave, scsi_command(dq->dq_cdb->cdb[0])); 62954004Sfujita #endif 63054004Sfujita #endif 63154004Sfujita } else if (ints & INTS_CMD_DONE) { 63254004Sfujita if (hs->sc_phase == BUS_FREE_PHASE) 63354004Sfujita goto abort; 63454004Sfujita else if (hs->sc_phase == MESG_IN_PHASE) { 63554004Sfujita hd->scsi_scmd = SCMD_RST_ACK; 63654004Sfujita 63754004Sfujita if ((hs->sc_msg[0] == MSG_CMD_COMPLETE) || 63854004Sfujita (hs->sc_msg[0] == MSG_DISCONNECT)) { 63954004Sfujita hd->scsi_ints = ints; 64054004Sfujita 64154004Sfujita hs->sc_phase = BUS_FREE_PHASE; 64254004Sfujita 64354004Sfujita return; 64454004Sfujita } 64554004Sfujita } 64654004Sfujita if (hs->sc_flags & SC_SEL_TIMEOUT) 64754004Sfujita hs->sc_flags &= ~SC_SEL_TIMEOUT; 64854004Sfujita } else if (ints & INTS_SRV_REQ) { 64954004Sfujita if (hs->sc_phase != MESG_IN_PHASE) 65054004Sfujita goto abort; 65154004Sfujita } else if (ints & INTS_TIMEOUT) { 65254004Sfujita if (hs->sc_phase == ARB_SEL_PHASE) { 65354004Sfujita if (hs->sc_flags & SC_SEL_TIMEOUT) { 65454004Sfujita hd->scsi_ints = ints; 65554004Sfujita hs->sc_flags &= ~SC_SEL_TIMEOUT; 65654004Sfujita /* Such SCSI Device is not conected. */ 65754004Sfujita 65854004Sfujita if (hs->sc_lock != NULL) { 65954004Sfujita *(hs->sc_lock) = SC_DEV_NOT_FOUND; 66054004Sfujita } else { 66154004Sfujita (dq->dq_driver->d_intr)(dq->dq_unit, SC_DEV_NOT_FOUND); 66254004Sfujita } 66354004Sfujita 66454004Sfujita return; 66554004Sfujita } else { 66654004Sfujita /* wait more 250 usec */ 66754004Sfujita hs->sc_flags |= SC_SEL_TIMEOUT; 66854004Sfujita hd->scsi_temp = 0; 66954004Sfujita hd->scsi_tch = 0; 67054004Sfujita hd->scsi_tcm = 0x06; 67154004Sfujita hd->scsi_tcl = 0x40; 67254004Sfujita hd->scsi_ints = ints; 67354004Sfujita return; 67454004Sfujita } 67554004Sfujita } else 67654004Sfujita goto abort; 67754004Sfujita } else 67854004Sfujita goto abort; 67954004Sfujita 68054004Sfujita hd->scsi_ints = ints; 68154004Sfujita 68254004Sfujita /* 68354004Sfujita * Next SCSI Transfer 68454004Sfujita */ 68554004Sfujita 68654004Sfujita wait = SC_TIMEOUT; 68754004Sfujita while ((hd->scsi_psns & PSNS_REQ) == 0) { 68854004Sfujita if (wait < 0) { 68954004Sfujita /* hd->scsi_scmd = SCMD_SET_ATN; */ 69054004Sfujita hd->scsi_scmd = SCMD_RST; 69154004Sfujita DELAY(40); /* wait 25 micro sec */ 69254004Sfujita hd->scsi_scmd = 0; 69354004Sfujita 69454004Sfujita wait = SC_TIMEOUT; 69554004Sfujita while (wait-- > 0) 69654004Sfujita DELAY(1); 69754004Sfujita 69854004Sfujita if (hs->sc_lock != NULL) { 69954004Sfujita *(hs->sc_lock) = SC_IO_TIMEOUT; 70054004Sfujita } else { 70154004Sfujita (dq->dq_driver->d_intr)(dq->dq_unit, SC_IO_TIMEOUT); 70254004Sfujita } 70354004Sfujita 70454004Sfujita return; 70554004Sfujita } 70654004Sfujita DELAY(1); 70754004Sfujita wait--; 70854004Sfujita } 70954004Sfujita 71054004Sfujita hs->sc_phase = hd->scsi_psns & PHASE; 71154004Sfujita 71254004Sfujita #ifdef DEBUGPRINT 71354004Sfujita dbgprintf("scintr: %s\n", phase_name(hs->sc_phase)); 71454004Sfujita #endif 71554004Sfujita 71654004Sfujita if ((hs->sc_phase == DATA_OUT_PHASE) || (hs->sc_phase == DATA_IN_PHASE)) { 71754004Sfujita len = ( hs->sc_lock != NULL ? hs->sc_len : dq->dq_bp->b_bcount ); 71854004Sfujita buf = ( hs->sc_lock != NULL ? hs->sc_buf : (u_char *) dq->dq_bp->b_un.b_addr ); 71954004Sfujita } else if (hs->sc_phase == CMD_PHASE) { 72054004Sfujita len = ( hs->sc_lock != NULL ? hs->sc_cdblen : dq->dq_cdb->len ); 72154004Sfujita buf = ( hs->sc_lock != NULL ? hs->sc_cdb : dq->dq_cdb->cdb ); 72254004Sfujita } else if (hs->sc_phase == STATUS_PHASE) { 72354004Sfujita len = 1; 72454004Sfujita buf = &hs->sc_stat; 72554004Sfujita } else { 72654004Sfujita if (hs->sc_phase == MESG_OUT_PHASE) { 72754004Sfujita #ifndef NODISCONNECT 72854004Sfujita hs->sc_msg[0] = MSG_IDENTIFY_DR; 72954004Sfujita #else 73054004Sfujita hs->sc_msg[0] = MSG_IDENTIFY; 73154004Sfujita #endif 73254004Sfujita } 73354004Sfujita len = 1; 73454004Sfujita buf = hs->sc_msg; 73554004Sfujita } 73654004Sfujita 73754004Sfujita #ifdef XFER_ENABLE 73854004Sfujita if ((hs->sc_lock == NULL) && (hs->sc_phase == DATA_IN_PHASE)) { 73954004Sfujita dq->dq_xferp = buf; 74054004Sfujita dq->dq_xfercnt = len; 74154004Sfujita txfer_start(hd, len, hs->sc_phase); 74254004Sfujita return; 74354004Sfujita } 74454004Sfujita #endif 74554004Sfujita 74654004Sfujita ixfer_start(hd, len, hs->sc_phase); 74754004Sfujita if (hs->sc_phase & PHASE_IO) { 74854004Sfujita if ((wait = ixfer_in(hd, len, buf)) == -1) { 74954004Sfujita goto time_out; 75054004Sfujita } 75154004Sfujita if (dq->dq_imin == -1) 75254004Sfujita dq->dq_imin = wait; 75354004Sfujita else 754*55175Saki dq->dq_imin = min(wait, dq->dq_imin); 755*55175Saki dq->dq_imax = max(wait, dq->dq_imax); 75654004Sfujita } else { 75754004Sfujita if ((wait = ixfer_out(hd, len, buf)) == -1) { 75854004Sfujita goto time_out; 75954004Sfujita } 76054004Sfujita if (dq->dq_omin == -1) 76154004Sfujita dq->dq_omin = wait; 76254004Sfujita else 763*55175Saki dq->dq_omin = min(wait, dq->dq_omin); 764*55175Saki dq->dq_omax = max(wait, dq->dq_omax); 76554004Sfujita } 76654004Sfujita 76754004Sfujita return; 76854004Sfujita 76954004Sfujita time_out: 77054004Sfujita scabort(hs, hd); 77154004Sfujita printf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Current Status\n", 77254004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 77354004Sfujita 77454004Sfujita if (hs->sc_lock != NULL) { 77554004Sfujita *(hs->sc_lock) = SC_IO_TIMEOUT; 77654004Sfujita } else { 77754004Sfujita (dq->dq_driver->d_intr)(dq->dq_unit, SC_IO_TIMEOUT); 77854004Sfujita } 77954004Sfujita 78054004Sfujita return; 78154004Sfujita 78254004Sfujita /* 78354004Sfujita * SCSI Abort 78454004Sfujita */ 78554004Sfujita abort: 78654004Sfujita 78754004Sfujita /* SCSI IO failed */ 78854004Sfujita scabort(hs, hd); 78954004Sfujita hd->scsi_ints = ints; 79054004Sfujita 79154004Sfujita if (hs->sc_lock != NULL) { 79254004Sfujita *(hs->sc_lock) = SC_IO_FAILED; 79354004Sfujita } else { 79454004Sfujita (dq->dq_driver->d_intr)(dq->dq_unit, SC_IO_FAILED); 79554004Sfujita } 79654004Sfujita 79754004Sfujita return; 79854004Sfujita } 79954004Sfujita 80054004Sfujita int 80154004Sfujita scabort(hs, hd) 80254004Sfujita register struct scsi_softc *hs; 80354004Sfujita volatile register struct scsidevice *hd; 80454004Sfujita { 80554004Sfujita int len; 80654004Sfujita u_char junk; 80754004Sfujita 80854004Sfujita #ifdef DEBUGPRINT 80954004Sfujita dbgprintall(); 81054004Sfujita printf("\n"); 81154004Sfujita #endif 81254004Sfujita 81354004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Current Status\n", 81454004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 81554004Sfujita 81654004Sfujita if (hd->scsi_ints != 0) 81754004Sfujita hd->scsi_ints = hd->scsi_ints; 81854004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Reset INTS reg.\n", 81954004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 82054004Sfujita 82154004Sfujita if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0) 82254004Sfujita /* no longer connected to scsi target */ 82354004Sfujita return; 82454004Sfujita 82554004Sfujita /* get the number of bytes remaining in current xfer + fudge */ 82654004Sfujita len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl; 82754004Sfujita printf("scabort: Current xfer count = %d\n", len); 82854004Sfujita 82954004Sfujita /* for that many bus cycles, try to send an abort msg */ 83054004Sfujita for (len += 1024; (hd->scsi_ssts & SSTS_INITIATOR) && --len >= 0; ) { 83154004Sfujita /* 83254004Sfujita hd->scsi_scmd = SCMD_SET_ATN; 83354004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Set ATN\n", 83454004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 83554004Sfujita */ 83654004Sfujita while ((hd->scsi_psns & PSNS_REQ) == 0) { 83754004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Wait for REQ\n", 83854004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 83954004Sfujita if (! (hd->scsi_ssts & SSTS_INITIATOR)) 84054004Sfujita goto out; 84154004Sfujita DELAY(1); 84254004Sfujita } 84354004Sfujita /* 84454004Sfujita if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE) { 84554004Sfujita hd->scsi_scmd = SCMD_RST_ATN; 84654004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Reset ATN\n", 84754004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 84854004Sfujita } 84954004Sfujita */ 85054004Sfujita hd->scsi_pctl = hs->sc_phase = hd->scsi_psns & PHASE; 85154004Sfujita printf("scabort: Phase = %s\n", phase_name(hs->sc_phase)); 85254004Sfujita 85354004Sfujita if (hd->scsi_psns & PHASE_IO) { 85454004Sfujita /* one of the input phases - read & discard a byte */ 85554004Sfujita hd->scsi_scmd = SCMD_SET_ACK; 85654004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Set ACK\n", 85754004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 85854004Sfujita 85954004Sfujita while (hd->scsi_psns & PSNS_REQ) { 86054004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Wait for REQ\n", 86154004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 86254004Sfujita DELAY(1); 86354004Sfujita } 86454004Sfujita 86554004Sfujita junk = hd->scsi_temp; 86654004Sfujita printf("scabort: TEMP = 0x%s\n", hexstr(junk, 2)); 86754004Sfujita } else { 86854004Sfujita /* one of the output phases - send an abort msg */ 86954004Sfujita hd->scsi_temp = MSG_ABORT; 87054004Sfujita hd->scsi_scmd = SCMD_SET_ACK; 87154004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Set ACK\n", 87254004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 87354004Sfujita 87454004Sfujita while (hd->scsi_psns & PSNS_REQ) { 87554004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Wait for REQ\n", 87654004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 87754004Sfujita DELAY(1); 87854004Sfujita } 87954004Sfujita } 88054004Sfujita 88154004Sfujita hd->scsi_scmd = SCMD_RST_ACK; 88254004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Reset ACK\n", 88354004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 88454004Sfujita } 88554004Sfujita out: 88654004Sfujita /* 88754004Sfujita * Either the abort was successful & the bus is disconnected or 88854004Sfujita * the device didn't listen. If the latter, announce the problem. 88954004Sfujita * Either way, reset the card & the SPC. 89054004Sfujita */ 89154004Sfujita if (len < 0 && hs) 89254004Sfujita printf("sc%d: abort failed. phase=0x%x, ssts=0x%x\n", 89354004Sfujita hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts); 89454004Sfujita 89554004Sfujita while (hd->scsi_ints == 0) 89654004Sfujita DELAY(1); 89754004Sfujita 89854004Sfujita hd->scsi_ints = hd->scsi_ints; 89954004Sfujita 90054004Sfujita printf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Current Status\n", 90154004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 90254004Sfujita 90354004Sfujita printf("scabort: SCSI abort operation is done\n"); 90454004Sfujita } 90554004Sfujita 90654004Sfujita 90754004Sfujita /* 90854004Sfujita * SPC device queue handling 90954004Sfujita */ 91054004Sfujita 91154004Sfujita int 91254004Sfujita screq(dq) 91354004Sfujita register struct scsi_queue *dq; 91454004Sfujita { 91554004Sfujita register struct scsi_softc *hs = &scsi_softc[dq->dq_ctlr]; 91654004Sfujita register struct scsi_queue *hq = &hs->sc_sq; 91754004Sfujita 91854004Sfujita insque(dq, hq->dq_back); 91954004Sfujita 92054004Sfujita if (dq->dq_back == hq) { 92154004Sfujita #ifdef QUE_DEBUG 92254004Sfujita printf("screq: slave = %d, command = %s\n", 92354004Sfujita hq->dq_forw->dq_slave, 92454004Sfujita scsi_command(hq->dq_forw->dq_cdb->cdb[0])); 92554004Sfujita #endif 92654004Sfujita return(1); 92754004Sfujita } 92854004Sfujita 92954004Sfujita return(0); 93054004Sfujita } 93154004Sfujita 93254004Sfujita #ifndef NODISCONNECT 93354004Sfujita int 93454004Sfujita scpend(dq) 93554004Sfujita register struct scsi_queue *dq; 93654004Sfujita { 93754004Sfujita register struct scsi_softc *hs = &scsi_softc[dq->dq_ctlr]; 93854004Sfujita register struct scsi_queue *hq = &hs->sc_sq; 93954004Sfujita register struct scsi_queue *wq = &hs->sc_wq; 94054004Sfujita 94154004Sfujita remque(dq); 94254004Sfujita 94354004Sfujita insque(dq, wq->dq_back); 94454004Sfujita } 94554004Sfujita 94654004Sfujita int 94754004Sfujita scrschdl(ctlr, slave) 94854004Sfujita register int ctlr; 94954004Sfujita register int slave; 95054004Sfujita { 95154004Sfujita register struct scsi_softc *hs = &scsi_softc[ctlr]; 95254004Sfujita register struct scsi_queue *wq = &hs->sc_wq; 95354004Sfujita register struct scsi_queue *hq = &hs->sc_sq; 95454004Sfujita register struct scsi_queue *dq; 95554004Sfujita 95654004Sfujita for (dq = wq->dq_forw; dq != wq; dq = dq->dq_forw) { 95754004Sfujita if (dq->dq_slave == slave) 95854004Sfujita goto found; 95954004Sfujita } 96054004Sfujita 96154004Sfujita return(0); 96254004Sfujita 96354004Sfujita found: 96454004Sfujita remque(dq); 96554004Sfujita insque(dq, hq); 96654004Sfujita 96754004Sfujita return(1); 96854004Sfujita } 96954004Sfujita #endif 97054004Sfujita 97154004Sfujita int 97254004Sfujita scfree(dq) 97354004Sfujita register struct scsi_queue *dq; 97454004Sfujita { 97554004Sfujita register struct scsi_softc *hs = &scsi_softc[dq->dq_ctlr]; 97654004Sfujita register struct scsi_queue *hq = &hs->sc_sq; 97754004Sfujita int status = hs->sc_stat; 97854004Sfujita 97954004Sfujita remque(dq); 98054004Sfujita 98154004Sfujita hs->sc_flags = 0; 98254004Sfujita hs->sc_phase = BUS_FREE_PHASE; 98354004Sfujita 98454004Sfujita hs->sc_stat = 0; 98554004Sfujita hs->sc_msg[0] = 0; 98654004Sfujita 98754004Sfujita if ((dq = hq->dq_forw) != hq) { 98854004Sfujita #ifdef QUE_DEBUG 98954004Sfujita printf("scfree: slave = %d, command = %s\n", 99054004Sfujita dq->dq_slave, 99154004Sfujita scsi_command(dq->dq_cdb->cdb[0])); 99254004Sfujita #endif 99354004Sfujita (dq->dq_driver->d_start)(dq->dq_unit); 99454004Sfujita } 99554004Sfujita 99654004Sfujita return(status); 99754004Sfujita } 99854004Sfujita 99954004Sfujita /* 100054004Sfujita * SCSI common interface 100154004Sfujita */ 100254004Sfujita 100354004Sfujita int scsi_lock[NSC]; 100454004Sfujita 100554004Sfujita int 100654004Sfujita scsi_result(unit, stat) 100754004Sfujita int unit, stat; 100854004Sfujita { 100954004Sfujita #ifdef SCSI_DEBUG 101054004Sfujita printf("scsi_result: stat = %s\n", scsi_status(stat)); 101154004Sfujita #endif 101254004Sfujita if (stat < 0) 101354004Sfujita scsi_lock[unit] = stat; 101454004Sfujita else 101554004Sfujita scsi_lock[unit] = SC_IO_COMPLETE; 101654004Sfujita } 101754004Sfujita 101854004Sfujita struct driver scsi_driver = { 101954004Sfujita (int (*)()) 0, "scsi", (int (*)()) 0, (int (*)()) 0, scsi_result, (int (*)()) 0 102054004Sfujita }; 102154004Sfujita 102254004Sfujita #define SCSI_BUF 8 102354004Sfujita 102454004Sfujita struct buf scsi_buf[SCSI_BUF]; 102554004Sfujita 102654004Sfujita int 102754004Sfujita scsi_init_buf() 102854004Sfujita { 102954004Sfujita register struct buf *rbp = &scsi_buf[0]; 103054004Sfujita register int i; 103154004Sfujita 103254004Sfujita rbp->av_forw = rbp->av_back = rbp; 103354004Sfujita 103454004Sfujita for(i = 0; i < SCSI_BUF; i++) 103554004Sfujita scsi_free_buf(&scsi_buf[i]); 103654004Sfujita } 103754004Sfujita 103854004Sfujita int 103954004Sfujita scsi_free_buf(bp) 104054004Sfujita register struct buf *bp; 104154004Sfujita { 104254004Sfujita register struct buf *rbp = &scsi_buf[0]; 104354004Sfujita 104454004Sfujita bp->av_forw = rbp; 104554004Sfujita bp->av_back = rbp->av_back; 104654004Sfujita 104754004Sfujita rbp->av_back->av_forw = bp; 104854004Sfujita rbp->av_back = bp; 104954004Sfujita } 105054004Sfujita 105154004Sfujita struct buf * 105254004Sfujita scsi_get_buf() 105354004Sfujita { 105454004Sfujita register struct buf *rbp = &scsi_buf[0]; 105554004Sfujita register struct buf *bp = rbp->av_forw; 105654004Sfujita 105754004Sfujita if (bp == rbp) 105854004Sfujita return((struct buf *) 0); 105954004Sfujita 106054004Sfujita bp->av_forw->av_back = rbp; 106154004Sfujita rbp->av_forw = bp->av_forw; 106254004Sfujita 106354004Sfujita return(bp); 106454004Sfujita } 106554004Sfujita 106654004Sfujita struct scsi_queue scsi_entry[NSC]; 106754004Sfujita 106854004Sfujita int 106954004Sfujita scsi_immed_command(ctlr, slave, lun, cdb, buf, len) 107054004Sfujita int ctlr, slave, lun; 107154004Sfujita struct scsi_fmt_cdb *cdb; 107254004Sfujita u_char *buf; 107354004Sfujita unsigned len; 107454004Sfujita { 107554004Sfujita register struct scsi_softc *hs = &scsi_softc[ctlr]; 107654004Sfujita volatile register struct scsidevice *hd = 107754004Sfujita (struct scsidevice *) hs->sc_hc->hp_addr; 107854004Sfujita register struct scsi_queue *dq = &scsi_entry[ctlr]; 107954004Sfujita register struct buf *bp; 108054004Sfujita int s, status, wait = 30; 108154004Sfujita 108254004Sfujita #ifdef SCSI_DEBUG 108354004Sfujita printf("scsi_immed_command( %d, %d, %d, cdb(%d,%s), buf, %d): Start\n", 108454004Sfujita ctlr, slave, lun, cdb->len, scsi_command(cdb->cdb[0]), len); 108554004Sfujita #endif 108654004Sfujita 108754004Sfujita if ((bp = scsi_get_buf()) == 0) { 108854004Sfujita return(SC_BUSY); 108954004Sfujita } 109054004Sfujita 109154004Sfujita s = splbio(); 109254004Sfujita 109354004Sfujita bp->b_flags = B_BUSY; 109454004Sfujita bp->b_bcount = len; 109554004Sfujita bp->b_un.b_addr = (caddr_t) buf; 109654004Sfujita 109754004Sfujita dq->dq_unit = ctlr; 109854004Sfujita dq->dq_ctlr = ctlr; 109954004Sfujita dq->dq_slave = slave; 110054004Sfujita dq->dq_driver = &scsi_driver; 110154004Sfujita dq->dq_cdb = cdb; 110254004Sfujita dq->dq_bp = bp; 110354004Sfujita 110454004Sfujita scsi_lock[ctlr] = SC_IN_PROGRESS; 110554004Sfujita if (screq(dq)) 110654004Sfujita scstart(ctlr); 110754004Sfujita 110854004Sfujita splx(s); 110954004Sfujita 111054004Sfujita while (scsi_lock[ctlr] == SC_IN_PROGRESS) { 111154004Sfujita if (wait < 0) { 111254004Sfujita scabort(hs, hd); 111354004Sfujita 111454004Sfujita s = splbio(); 111554004Sfujita status = scfree(dq); 111654004Sfujita splx(s); 111754004Sfujita 111854004Sfujita bp->b_flags = 0; 111954004Sfujita 112054004Sfujita return(SC_IO_FAILED); 112154004Sfujita } 112254004Sfujita 112354004Sfujita DELAY(100000); 112454004Sfujita wait--; 112554004Sfujita } 112654004Sfujita 112754004Sfujita s = splbio(); 112854004Sfujita status = scfree(dq); 112954004Sfujita splx(s); 113054004Sfujita 113154004Sfujita if (scsi_lock[ctlr] < 0) 113254004Sfujita status = scsi_lock[ctlr]; 113354004Sfujita 113454004Sfujita scsi_free_buf(bp); 113554004Sfujita 113654004Sfujita #ifdef SCSI_DEBUG 113754004Sfujita printf("scsi_immed_command: Status -- 0x%x\n", status); 113854004Sfujita #endif 113954004Sfujita return(status); 114054004Sfujita } 114154004Sfujita 114254004Sfujita int 114354004Sfujita scsi_test_unit_rdy(ctlr, slave, lun) 114454004Sfujita int ctlr, slave, lun; 114554004Sfujita { 114654004Sfujita static struct scsi_fmt_cdb cdb = { 6, CMD_TEST_UNIT_READY }; 114754004Sfujita int stat; 114854004Sfujita 114954004Sfujita while ((stat = scsi_immed_command(ctlr, slave, lun, 115054004Sfujita &cdb, (u_char *) 0, 0)) == SC_BUSY) { 115154004Sfujita DELAY(10000); 115254004Sfujita } 115354004Sfujita 115454004Sfujita return(stat); 115554004Sfujita } 115654004Sfujita 115754004Sfujita int 115854004Sfujita scsi_request_sense(ctlr, slave, lun, buf, len) 115954004Sfujita int ctlr, slave, lun; 116054004Sfujita u_char *buf; 116154004Sfujita unsigned len; 116254004Sfujita { 116354004Sfujita register struct scsi_softc *hs = &scsi_softc[ctlr]; 116454004Sfujita volatile register struct scsidevice *hd = 116554004Sfujita (struct scsidevice *) hs->sc_hc->hp_addr; 116654004Sfujita static struct scsi_fmt_cdb req_cmd = { 6, CMD_REQUEST_SENSE }; 116754004Sfujita int s, status, lock; 116854004Sfujita 116954004Sfujita #ifdef REQ_DEBUG 117054004Sfujita printf("scsi_request_sense( %d, %d, %d, buf, %d) -- Start\n", 117154004Sfujita ctlr, slave, lun, len); 117254004Sfujita #endif 117354004Sfujita 117454004Sfujita req_cmd.cdb[1] = lun; 117554004Sfujita req_cmd.cdb[4] = len; 117654004Sfujita 117754004Sfujita if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY)) 117854004Sfujita return(0); 117954004Sfujita 118054004Sfujita s = splbio(); 118154004Sfujita 118254004Sfujita hs->sc_flags = 0; 118354004Sfujita hs->sc_phase = ARB_SEL_PHASE; 118454004Sfujita 118554004Sfujita hs->sc_cdb = req_cmd.cdb; 118654004Sfujita hs->sc_cdblen = req_cmd.len; 118754004Sfujita hs->sc_buf = buf; 118854004Sfujita hs->sc_len = len; 118954004Sfujita 119054004Sfujita hs->sc_stat = 0; 119154004Sfujita hs->sc_msg[0] = 0; 119254004Sfujita 119354004Sfujita lock = SC_IN_PROGRESS; 119454004Sfujita hs->sc_lock = &lock; 119554004Sfujita 119654004Sfujita issue_select(hd, slave, 0); 119754004Sfujita 119854004Sfujita spl0(); 119954004Sfujita 120054004Sfujita while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED)) 120154004Sfujita DELAY(10); 120254004Sfujita 120354004Sfujita splbio(); 120454004Sfujita 120554004Sfujita hs->sc_flags = 0; 120654004Sfujita hs->sc_phase = BUS_FREE_PHASE; 120754004Sfujita 120854004Sfujita hs->sc_cdb = NULL; 120954004Sfujita hs->sc_cdblen = 0; 121054004Sfujita hs->sc_buf = NULL; 121154004Sfujita hs->sc_len = 0; 121254004Sfujita hs->sc_lock = NULL; 121354004Sfujita 121454004Sfujita status = hs->sc_stat; 121554004Sfujita 121654004Sfujita hs->sc_stat = 0; 121754004Sfujita hs->sc_msg[0] = 0; 121854004Sfujita 121954004Sfujita splx(s); 122054004Sfujita 122154004Sfujita if (lock == SC_IO_COMPLETE) { 122254004Sfujita #ifdef REQ_DEBUG 122354004Sfujita printf("scsi_request_sense: Status -- 0x%x\n", status); 122454004Sfujita #endif 122554004Sfujita return(status); 122654004Sfujita } else { 122754004Sfujita return(lock); 122854004Sfujita } 122954004Sfujita } 123054004Sfujita #endif 1231