154004Sfujita /* 254004Sfujita * Copyright (c) 1992 OMRON Corporation. 3*63192Sbostic * Copyright (c) 1992, 1993 4*63192Sbostic * The Regents of the University of California. 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*63192Sbostic * @(#)sc.c 8.1 (Berkeley) 06/10/93 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 2656519Sbostic #include <sys/param.h> 2756519Sbostic #include <sys/systm.h> 2856519Sbostic #include <sys/buf.h> 2954004Sfujita 3056519Sbostic #include <luna68k/dev/device.h> 3156519Sbostic #include <luna68k/dev/scsireg.h> 3256519Sbostic #include <luna68k/dev/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 screset(hc->hp_unit); 19254004Sfujita 19354004Sfujita return(1); 19454004Sfujita } 19554004Sfujita 19654004Sfujita void 19754004Sfujita screset(unit) 19854004Sfujita register int unit; 19954004Sfujita { 20054004Sfujita register struct scsi_softc *hs = &scsi_softc[unit]; 20154004Sfujita volatile register struct scsidevice *hd = 20254004Sfujita (struct scsidevice *)hs->sc_hc->hp_addr; 20354004Sfujita 20454004Sfujita printf("sc%d: ", unit); 20554004Sfujita 20654004Sfujita /* 20754004Sfujita * Disable interrupts then reset the FUJI chip. 20854004Sfujita */ 20954004Sfujita 21054004Sfujita hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST; 21154004Sfujita hd->scsi_scmd = 0; 21254004Sfujita hd->scsi_pctl = 0; 21354004Sfujita hd->scsi_temp = 0; 21454004Sfujita hd->scsi_tch = 0; 21554004Sfujita hd->scsi_tcm = 0; 21654004Sfujita hd->scsi_tcl = 0; 21754004Sfujita hd->scsi_ints = 0; 21854004Sfujita 21954004Sfujita /* We can use Asynchronous Transfer only */ 22054004Sfujita printf("async"); 22154004Sfujita 22254004Sfujita /* 22354004Sfujita * Configure MB89352 with its SCSI address, all 22454004Sfujita * interrupts enabled & appropriate parity. 22554004Sfujita */ 22654004Sfujita hd->scsi_bdid = SCSI_ID; 22754004Sfujita hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB| 22854004Sfujita SCTL_PARITY_ENAB | SCTL_RESEL_ENAB | 22954004Sfujita SCTL_INTR_ENAB; 23054004Sfujita printf(", parity"); 23154004Sfujita 23254004Sfujita DELAY(400); 23354004Sfujita hd->scsi_sctl &= ~SCTL_DISABLE; 23454004Sfujita 23554004Sfujita printf(", scsi id %d\n", SCSI_ID); 23654004Sfujita } 23754004Sfujita 23854004Sfujita 23954004Sfujita /* 24054004Sfujita * SPC Arbitration/Selection routine 24154004Sfujita */ 24254004Sfujita 24354004Sfujita int 24454004Sfujita issue_select(hd, target, flags) 24554004Sfujita volatile register struct scsidevice *hd; 24654004Sfujita u_char target; 24754004Sfujita int flags; 24854004Sfujita { 24954004Sfujita #ifndef NODISCONNECT 25054004Sfujita if (flags & DQ_DISCONNECT) { 25154004Sfujita hd->scsi_scmd = SCMD_SET_ATN; 25254004Sfujita } 25354004Sfujita #endif 25454004Sfujita 25554004Sfujita hd->scsi_pctl = 0; 25654004Sfujita hd->scsi_temp = (1 << SCSI_ID) | (1 << target); 25754004Sfujita 25854004Sfujita /* select timeout is hardcoded to 2ms */ 25954004Sfujita hd->scsi_tch = 0; 26054004Sfujita hd->scsi_tcm = 32; 26154004Sfujita hd->scsi_tcl = 4; 26254004Sfujita 26354004Sfujita hd->scsi_scmd = SCMD_SELECT; 26454004Sfujita 26554004Sfujita return (1); 26654004Sfujita } 26754004Sfujita 26854004Sfujita 26954004Sfujita /* 27054004Sfujita * SPC Manual Transfer routines 27154004Sfujita */ 27254004Sfujita 27354004Sfujita /* not yet */ 27454004Sfujita 27554004Sfujita 27654004Sfujita /* 27754004Sfujita * SPC Program Transfer routines 27854004Sfujita */ 27954004Sfujita 28054004Sfujita int 28154004Sfujita ixfer_start(hd, len, phase) 28254004Sfujita volatile register struct scsidevice *hd; 28354004Sfujita register int len; 28454004Sfujita register u_char phase; 28554004Sfujita { 28654004Sfujita register int wait = 0; 28754004Sfujita 28854004Sfujita hd->scsi_sdgc = 0; 28954004Sfujita 29054004Sfujita hd->scsi_tch = ((len & 0xff0000) >> 16); 29154004Sfujita hd->scsi_tcm = ((len & 0x00ff00) >> 8); 29254004Sfujita hd->scsi_tcl = (len & 0x0000ff); 29354004Sfujita hd->scsi_pctl = phase; 29454004Sfujita hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR; 29554004Sfujita 29654004Sfujita while ((hd->scsi_ssts & SSTS_BUSY) == 0) { 29754004Sfujita if (wait > SC_TIMEOUT) { 29854004Sfujita panic("ixfer_start: too long wait"); 29954004Sfujita } 30054004Sfujita wait++; 30154004Sfujita DELAY(1); 30254004Sfujita } 30354004Sfujita } 30454004Sfujita 30554004Sfujita int 30654004Sfujita ixfer_out(hd, len, buf) 30754004Sfujita volatile register struct scsidevice *hd; 30854004Sfujita register int len; 30954004Sfujita register u_char *buf; 31054004Sfujita { 31154004Sfujita u_char *t = buf; 31254004Sfujita register int wait = 0; 31354004Sfujita #ifdef QUADBYTES 31454004Sfujita register int qwait = 0; 31554004Sfujita register int l_len = len >> 3; 31654004Sfujita register u_long * l_buf = (u_long *) buf; 31754004Sfujita 31854004Sfujita for(; l_len > 0; l_len--) { 31954004Sfujita while ((hd->scsi_ssts & SSTS_DREG_EMPTY) == 0) { 32054004Sfujita if (qwait > SC_TIMEOUT) { 32154004Sfujita printf("ixfer_out: quad time out\n"); 32254004Sfujita printf("ixfer_out: %d bytes sended\n", 32354004Sfujita (((u_char *) l_buf) - t)); 32454004Sfujita printf("ixfer_out: TC = %d\n", 32554004Sfujita ( hd->scsi_tch << 16 ) | 32654004Sfujita ( hd->scsi_tcm << 8 ) | 32754004Sfujita ( hd->scsi_tcl )); 32854004Sfujita return(-1); 32954004Sfujita } 33054004Sfujita qwait++; 33154004Sfujita DELAY(1); 33254004Sfujita } 33354004Sfujita *((u_long *) &hd->scsi_dreg) = *l_buf++; 33454004Sfujita *((u_long *) &hd->scsi_dreg) = *l_buf++; 33554004Sfujita } 33654004Sfujita 33754004Sfujita len &= 0x07; 33854004Sfujita buf = (u_char *) l_buf; 33954004Sfujita #endif 34054004Sfujita for(; len > 0; len--) { 34154004Sfujita while (hd->scsi_ssts & SSTS_DREG_FULL) { 34254004Sfujita if (wait > SC_TIMEOUT) { 34354004Sfujita printf("ixfer_out: time out\n"); 34454004Sfujita printf("ixfer_out: %d bytes sended\n", 34554004Sfujita (buf - t)); 34654004Sfujita return(-1); 34754004Sfujita } 34854004Sfujita wait++; 34954004Sfujita DELAY(1); 35054004Sfujita } 35154004Sfujita hd->scsi_dreg = *buf++; 35254004Sfujita } 35354004Sfujita 35454004Sfujita #ifdef QUADBYTES 35554004Sfujita return(qwait); 35654004Sfujita #else 35754004Sfujita return(wait); 35854004Sfujita #endif 35954004Sfujita } 36054004Sfujita 36154004Sfujita int 36254004Sfujita ixfer_in(hd, len, buf) 36354004Sfujita volatile register struct scsidevice *hd; 36454004Sfujita register int len; 36554004Sfujita register u_char *buf; 36654004Sfujita { 36754004Sfujita u_char *t = buf; 36854004Sfujita register int wait = 0; 36954004Sfujita #ifdef QUADBYTES 37054004Sfujita register int qwait = 0; 37154004Sfujita register int l_len = len >> 3; 37254004Sfujita register u_long * l_buf = (u_long *) buf; 37354004Sfujita 37454004Sfujita for(; l_len > 0; l_len--) { 37554004Sfujita while ((hd->scsi_ssts & SSTS_DREG_FULL) == 0) { 37654004Sfujita if (qwait > SC_TIMEOUT) { 37754004Sfujita printf("ixfer_in: quad time out\n"); 37854004Sfujita printf("ixfer_in: %d bytes recieved\n", 37954004Sfujita (((u_char *) l_buf) - t)); 38054004Sfujita return(-1); 38154004Sfujita } 38254004Sfujita qwait++; 38354004Sfujita DELAY(1); 38454004Sfujita } 38554004Sfujita *l_buf++ = *((u_long *) &hd->scsi_dreg); 38654004Sfujita *l_buf++ = *((u_long *) &hd->scsi_dreg); 38754004Sfujita } 38854004Sfujita 38954004Sfujita len &= 0x07; 39054004Sfujita buf = (u_char *) l_buf; 39154004Sfujita #endif 39254004Sfujita for (; len > 0; len--) { 39354004Sfujita while (hd->scsi_ssts & SSTS_DREG_EMPTY) { 39454004Sfujita if (wait > SC_TIMEOUT) { 39554004Sfujita printf("ixfer_in: time out\n"); 39654004Sfujita printf("ixfer_in: %d bytes recieved\n", 39754004Sfujita (buf - t)); 39854004Sfujita return(-1); 39954004Sfujita } 40054004Sfujita wait++; 40154004Sfujita DELAY(1); 40254004Sfujita } 40354004Sfujita *buf++ = hd->scsi_dreg; 40454004Sfujita } 40554004Sfujita 40654004Sfujita 40754004Sfujita #ifdef QUADBYTES 40854004Sfujita return(qwait); 40954004Sfujita #else 41054004Sfujita return(wait); 41154004Sfujita #endif 41254004Sfujita } 41354004Sfujita 41454004Sfujita 41554004Sfujita #ifdef XFER_ENABLE 41654004Sfujita /* 41754004Sfujita * SPC Interrupt base Transfer Routines 41854004Sfujita */ 41954004Sfujita 42054004Sfujita int 42154004Sfujita txfer_start(hd, len, phase) 42254004Sfujita volatile register struct scsidevice *hd; 42354004Sfujita register int len; 42454004Sfujita register u_char phase; 42554004Sfujita { 42654004Sfujita register int wait = 0; 42754004Sfujita 42854004Sfujita hd->scsi_sdgc = SDGC_XFER_ENAB; /* for interrupt */ 42954004Sfujita 43054004Sfujita hd->scsi_tch = ((len & 0xff0000) >> 16); 43154004Sfujita hd->scsi_tcm = ((len & 0x00ff00) >> 8); 43254004Sfujita hd->scsi_tcl = (len & 0x0000ff); 43354004Sfujita hd->scsi_pctl = phase; 43454004Sfujita hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR; 43554004Sfujita 43654004Sfujita while ((hd->scsi_ssts & SSTS_BUSY) == 0) { 43754004Sfujita if (wait > SC_TIMEOUT) { 43854004Sfujita panic("ixfer_start: too long wait"); 43954004Sfujita } 44054004Sfujita wait++; 44154004Sfujita DELAY(1); 44254004Sfujita } 44354004Sfujita } 44454004Sfujita 44554004Sfujita int 44654004Sfujita txfer_in(ctlr) 44754004Sfujita register int ctlr; 44854004Sfujita { 44954004Sfujita register struct scsi_softc *hs = &scsi_softc[ctlr]; 45054004Sfujita volatile register struct scsidevice *hd = (struct scsidevice *) hs->sc_hc->hp_addr; 45154004Sfujita register struct scsi_queue *dq = hs->sc_sq.dq_forw; 45254004Sfujita #ifdef QUADBYTES 45354004Sfujita register u_long *lp; 45454004Sfujita 45554004Sfujita if (hd->scsi_ssts & SSTS_DREG_FULL) { 45654004Sfujita lp = (u_long *) dq->dq_xferp; 45754004Sfujita 45854004Sfujita *lp++ = *((u_long *) &hd->scsi_dreg); 45954004Sfujita *lp++ = *((u_long *) &hd->scsi_dreg); 46054004Sfujita 46154004Sfujita dq->dq_xferp = (u_char *) lp; 46254004Sfujita dq->dq_xfercnt -= 8; 46354004Sfujita 46454004Sfujita goto xfer_done; 46554004Sfujita } 46654004Sfujita #endif 46754004Sfujita 46854004Sfujita *dq->dq_xferp++ = hd->scsi_dreg; 46954004Sfujita dq->dq_xfercnt--; 47054004Sfujita 47154004Sfujita xfer_done: 47254004Sfujita #ifdef DEBUGPRINT 47354004Sfujita if (dq->dq_xfercnt == 0) { 47454004Sfujita dbgprintf("txfer_in: "); 47554004Sfujita dbgprintf("dq->dq_bp->b_un.b_addr = 0x%s, ", hexstr(dq->dq_bp->b_un.b_addr, 8)); 47654004Sfujita dbgprintf("dq->dq_xferp = 0x%s :", hexstr(dq->dq_xferp, 8)); 47754004Sfujita dbgprintf("done\n"); 47854004Sfujita } 47954004Sfujita #endif 48054004Sfujita } 48154004Sfujita #endif 48254004Sfujita 48354004Sfujita /* 48454004Sfujita * SCSI Job Handler 48554004Sfujita */ 48654004Sfujita 48754004Sfujita int 48854004Sfujita scstart(ctlr) 48954004Sfujita int ctlr; 49054004Sfujita { 49154004Sfujita register struct scsi_softc *hs = &scsi_softc[ctlr]; 49254004Sfujita volatile register struct scsidevice *hd = 49354004Sfujita (struct scsidevice *) hs->sc_hc->hp_addr; 49454004Sfujita register struct scsi_queue *dq = hs->sc_sq.dq_forw; 49554004Sfujita 49654004Sfujita dq->dq_imax = 0; 49754004Sfujita dq->dq_imin = -1; 49854004Sfujita dq->dq_omax = 0; 49954004Sfujita dq->dq_omin = -1; 50054004Sfujita 50154004Sfujita hs->sc_flags = 0; 50254004Sfujita hs->sc_phase = ARB_SEL_PHASE; 50354004Sfujita 50454004Sfujita hs->sc_stat = 0; 50554004Sfujita hs->sc_msg[0] = 0; 50654004Sfujita 50754004Sfujita #ifdef DEBUGPRINT 50854004Sfujita dbgprintf("\n"); 50954004Sfujita dbgprintf("scstart: ID = %d\n", dq->dq_slave); 51054004Sfujita dbgprintf("scstart: cdb[0] = %s\n", scsi_command(dq->dq_cdb->cdb[0])); 51154004Sfujita dbgprintf("scstart: cdb[1] = 0x%s\n", hexstr(dq->dq_cdb->cdb[1], 2)); 51254004Sfujita dbgprintf("scstart: cdb[2] = 0x%s\n", hexstr(dq->dq_cdb->cdb[2], 2)); 51354004Sfujita dbgprintf("scstart: cdb[3] = 0x%s\n", hexstr(dq->dq_cdb->cdb[3], 2)); 51454004Sfujita dbgprintf("scstart: cdb[4] = 0x%s\n", hexstr(dq->dq_cdb->cdb[4], 2)); 51554004Sfujita dbgprintf("scstart: cdb[5] = 0x%s\n", hexstr(dq->dq_cdb->cdb[5], 2)); 51654004Sfujita if (dq->dq_cdb->cdb[0] & 0xE0) { 51754004Sfujita dbgprintf("scstart: cdb[6] = 0x%s\n", hexstr(dq->dq_cdb->cdb[6], 2)); 51854004Sfujita dbgprintf("scstart: cdb[7] = 0x%s\n", hexstr(dq->dq_cdb->cdb[7], 2)); 51954004Sfujita dbgprintf("scstart: cdb[8] = 0x%s\n", hexstr(dq->dq_cdb->cdb[8], 2)); 52054004Sfujita dbgprintf("scstart: cdb[9] = 0x%s\n", hexstr(dq->dq_cdb->cdb[9], 2)); 52154004Sfujita } 52254004Sfujita dbgprintf("scstart: bp->b_bcount = %d\n", dq->dq_bp->b_bcount); 52354004Sfujita dbgprintf("scstart: %s\n", phase_name(hs->sc_phase)); 52454004Sfujita #endif 52554004Sfujita 52654004Sfujita issue_select(hd, dq->dq_slave, dq->dq_flags); 52754004Sfujita 52854004Sfujita return(1); 52954004Sfujita } 53054004Sfujita 53154004Sfujita int 53254004Sfujita _scintr() 53354004Sfujita { 53454004Sfujita register struct scsi_softc *hs; 53554004Sfujita volatile register struct scsidevice *hd; 53654004Sfujita register int ctlr; 53754004Sfujita 53854004Sfujita for (ctlr = 0; ctlr < NSC; ctlr++) { 53954004Sfujita hs = &scsi_softc[ctlr]; 54054004Sfujita hd = (struct scsidevice *) hs->sc_hc->hp_addr; 54154004Sfujita 54254004Sfujita #ifdef XFER_ENABLE 54354004Sfujita if (((hd->scsi_psns & PHASE) == DATA_IN_PHASE) && 54454004Sfujita (hd->scsi_serr & SERR_XFER_OUT)) 54554004Sfujita txfer_in(ctlr); 54654004Sfujita #endif 54754004Sfujita 54854004Sfujita if (hd->scsi_ints != 0) 54954004Sfujita scintr(ctlr); 55054004Sfujita } 55154004Sfujita 55254004Sfujita return; 55354004Sfujita } 55454004Sfujita 55554004Sfujita int 55654004Sfujita scintr(ctlr) 55754004Sfujita register int ctlr; 55854004Sfujita { 55954004Sfujita register struct scsi_softc *hs = &scsi_softc[ctlr]; 56054004Sfujita volatile register struct scsidevice *hd = (struct scsidevice *) hs->sc_hc->hp_addr; 56154004Sfujita register struct scsi_queue *dq = hs->sc_sq.dq_forw; 56254004Sfujita register u_char ints, temp; 56354004Sfujita register int i, slave; 56454004Sfujita int wait, len; 56554004Sfujita u_char *buf; 56654004Sfujita 56754004Sfujita ints = hd->scsi_ints; 56854004Sfujita 56954004Sfujita #ifdef DEBUGPRINT 57054004Sfujita dbgprintf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x", 57154004Sfujita ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 57254004Sfujita if (hs->sc_phase == CMD_PHASE) 57354004Sfujita dbgprintf(" [%s]", scsi_command(dq->dq_cdb->cdb[0])); 57454004Sfujita if (hs->sc_phase & PHASE_MSG) 57554004Sfujita dbgprintf(" [%s]", scsi_mesg(hs->sc_msg[0])); 57654004Sfujita dbgprintf("\n"); 57754004Sfujita #endif 57854004Sfujita 57954004Sfujita if (ints & INTS_DISCON) { 58054004Sfujita if (hs->sc_msg[0] == MSG_CMD_COMPLETE) { 58154004Sfujita hd->scsi_ints = ints; 58254004Sfujita 58354004Sfujita if (hs->sc_lock != NULL) { 58454004Sfujita *(hs->sc_lock) = SC_IO_COMPLETE; 58554004Sfujita } else { 58654004Sfujita (dq->dq_driver->d_intr)(dq->dq_unit, hs->sc_stat); 58754004Sfujita } 58854004Sfujita 58954004Sfujita return; 59054004Sfujita #ifndef NODISCONNECT 59154004Sfujita } else if (hs->sc_msg[0] == MSG_DISCONNECT) { 59254004Sfujita #ifdef DEBUGPRINT 59354004Sfujita dbgprintf("scintr: DISCONNECT : ctlr = %d, slave = %d, cdb = %s\n", 59454004Sfujita dq->dq_ctlr, dq->dq_slave, scsi_command(dq->dq_cdb->cdb[0])); 59554004Sfujita #endif 59654004Sfujita 59754004Sfujita hd->scsi_ints = ints; 59854004Sfujita 59954004Sfujita scpend(dq); 60054004Sfujita 60154004Sfujita dq = hs->sc_sq.dq_forw; 60254004Sfujita 60354004Sfujita if (dq != &hs->sc_sq) 60454004Sfujita (dq->dq_driver->d_start)(dq->dq_unit); 60554004Sfujita 60654004Sfujita return; 60754004Sfujita #endif 60854004Sfujita } else 60954004Sfujita goto abort; 61054004Sfujita 61154004Sfujita #ifndef NODISCONNECT 61254004Sfujita } else if (ints & INTS_RESEL) { 61354004Sfujita temp = hd->scsi_temp & ~(1 << SCSI_ID); 61454004Sfujita for (slave = 0; temp != 1; slave++) { 61554004Sfujita temp >>= 1; 61654004Sfujita } 61754004Sfujita 61854004Sfujita hd->scsi_ints = ints; 61954004Sfujita 62054004Sfujita scrschdl(ctlr, slave); 62154004Sfujita 62254004Sfujita dq = hs->sc_sq.dq_forw; 62354004Sfujita #ifdef DEBUGPRINT 62454004Sfujita dbgprintf("\n"); 62554004Sfujita dbgprintf("scintr: RESELECT : ctlr = %d, slave = %d, cdb = %s\n", 62654004Sfujita dq->dq_ctlr, dq->dq_slave, scsi_command(dq->dq_cdb->cdb[0])); 62754004Sfujita #endif 62854004Sfujita #endif 62954004Sfujita } else if (ints & INTS_CMD_DONE) { 63054004Sfujita if (hs->sc_phase == BUS_FREE_PHASE) 63154004Sfujita goto abort; 63254004Sfujita else if (hs->sc_phase == MESG_IN_PHASE) { 63354004Sfujita hd->scsi_scmd = SCMD_RST_ACK; 63454004Sfujita 63554004Sfujita if ((hs->sc_msg[0] == MSG_CMD_COMPLETE) || 63654004Sfujita (hs->sc_msg[0] == MSG_DISCONNECT)) { 63754004Sfujita hd->scsi_ints = ints; 63854004Sfujita 63954004Sfujita hs->sc_phase = BUS_FREE_PHASE; 64054004Sfujita 64154004Sfujita return; 64254004Sfujita } 64354004Sfujita } 64454004Sfujita if (hs->sc_flags & SC_SEL_TIMEOUT) 64554004Sfujita hs->sc_flags &= ~SC_SEL_TIMEOUT; 64654004Sfujita } else if (ints & INTS_SRV_REQ) { 64754004Sfujita if (hs->sc_phase != MESG_IN_PHASE) 64854004Sfujita goto abort; 64954004Sfujita } else if (ints & INTS_TIMEOUT) { 65054004Sfujita if (hs->sc_phase == ARB_SEL_PHASE) { 65154004Sfujita if (hs->sc_flags & SC_SEL_TIMEOUT) { 65254004Sfujita hd->scsi_ints = ints; 65354004Sfujita hs->sc_flags &= ~SC_SEL_TIMEOUT; 65454004Sfujita /* Such SCSI Device is not conected. */ 65554004Sfujita 65654004Sfujita if (hs->sc_lock != NULL) { 65754004Sfujita *(hs->sc_lock) = SC_DEV_NOT_FOUND; 65854004Sfujita } else { 65954004Sfujita (dq->dq_driver->d_intr)(dq->dq_unit, SC_DEV_NOT_FOUND); 66054004Sfujita } 66154004Sfujita 66254004Sfujita return; 66354004Sfujita } else { 66454004Sfujita /* wait more 250 usec */ 66554004Sfujita hs->sc_flags |= SC_SEL_TIMEOUT; 66654004Sfujita hd->scsi_temp = 0; 66754004Sfujita hd->scsi_tch = 0; 66854004Sfujita hd->scsi_tcm = 0x06; 66954004Sfujita hd->scsi_tcl = 0x40; 67054004Sfujita hd->scsi_ints = ints; 67154004Sfujita return; 67254004Sfujita } 67354004Sfujita } else 67454004Sfujita goto abort; 67554004Sfujita } else 67654004Sfujita goto abort; 67754004Sfujita 67854004Sfujita hd->scsi_ints = ints; 67954004Sfujita 68054004Sfujita /* 68154004Sfujita * Next SCSI Transfer 68254004Sfujita */ 68354004Sfujita 68454004Sfujita wait = SC_TIMEOUT; 68554004Sfujita while ((hd->scsi_psns & PSNS_REQ) == 0) { 68654004Sfujita if (wait < 0) { 68754004Sfujita /* hd->scsi_scmd = SCMD_SET_ATN; */ 68854004Sfujita hd->scsi_scmd = SCMD_RST; 68954004Sfujita DELAY(40); /* wait 25 micro sec */ 69054004Sfujita hd->scsi_scmd = 0; 69154004Sfujita 69254004Sfujita wait = SC_TIMEOUT; 69354004Sfujita while (wait-- > 0) 69454004Sfujita DELAY(1); 69554004Sfujita 69654004Sfujita if (hs->sc_lock != NULL) { 69754004Sfujita *(hs->sc_lock) = SC_IO_TIMEOUT; 69854004Sfujita } else { 69954004Sfujita (dq->dq_driver->d_intr)(dq->dq_unit, SC_IO_TIMEOUT); 70054004Sfujita } 70154004Sfujita 70254004Sfujita return; 70354004Sfujita } 70454004Sfujita DELAY(1); 70554004Sfujita wait--; 70654004Sfujita } 70754004Sfujita 70854004Sfujita hs->sc_phase = hd->scsi_psns & PHASE; 70954004Sfujita 71054004Sfujita #ifdef DEBUGPRINT 71154004Sfujita dbgprintf("scintr: %s\n", phase_name(hs->sc_phase)); 71254004Sfujita #endif 71354004Sfujita 71454004Sfujita if ((hs->sc_phase == DATA_OUT_PHASE) || (hs->sc_phase == DATA_IN_PHASE)) { 71554004Sfujita len = ( hs->sc_lock != NULL ? hs->sc_len : dq->dq_bp->b_bcount ); 71654004Sfujita buf = ( hs->sc_lock != NULL ? hs->sc_buf : (u_char *) dq->dq_bp->b_un.b_addr ); 71754004Sfujita } else if (hs->sc_phase == CMD_PHASE) { 71854004Sfujita len = ( hs->sc_lock != NULL ? hs->sc_cdblen : dq->dq_cdb->len ); 71954004Sfujita buf = ( hs->sc_lock != NULL ? hs->sc_cdb : dq->dq_cdb->cdb ); 72054004Sfujita } else if (hs->sc_phase == STATUS_PHASE) { 72154004Sfujita len = 1; 72254004Sfujita buf = &hs->sc_stat; 72354004Sfujita } else { 72454004Sfujita if (hs->sc_phase == MESG_OUT_PHASE) { 72554004Sfujita #ifndef NODISCONNECT 72654004Sfujita hs->sc_msg[0] = MSG_IDENTIFY_DR; 72754004Sfujita #else 72854004Sfujita hs->sc_msg[0] = MSG_IDENTIFY; 72954004Sfujita #endif 73054004Sfujita } 73154004Sfujita len = 1; 73254004Sfujita buf = hs->sc_msg; 73354004Sfujita } 73454004Sfujita 73554004Sfujita #ifdef XFER_ENABLE 73654004Sfujita if ((hs->sc_lock == NULL) && (hs->sc_phase == DATA_IN_PHASE)) { 73754004Sfujita dq->dq_xferp = buf; 73854004Sfujita dq->dq_xfercnt = len; 73954004Sfujita txfer_start(hd, len, hs->sc_phase); 74054004Sfujita return; 74154004Sfujita } 74254004Sfujita #endif 74354004Sfujita 74454004Sfujita ixfer_start(hd, len, hs->sc_phase); 74554004Sfujita if (hs->sc_phase & PHASE_IO) { 74654004Sfujita if ((wait = ixfer_in(hd, len, buf)) == -1) { 74754004Sfujita goto time_out; 74854004Sfujita } 74954004Sfujita if (dq->dq_imin == -1) 75054004Sfujita dq->dq_imin = wait; 75154004Sfujita else 75255175Saki dq->dq_imin = min(wait, dq->dq_imin); 75355175Saki dq->dq_imax = max(wait, dq->dq_imax); 75454004Sfujita } else { 75554004Sfujita if ((wait = ixfer_out(hd, len, buf)) == -1) { 75654004Sfujita goto time_out; 75754004Sfujita } 75854004Sfujita if (dq->dq_omin == -1) 75954004Sfujita dq->dq_omin = wait; 76054004Sfujita else 76155175Saki dq->dq_omin = min(wait, dq->dq_omin); 76255175Saki dq->dq_omax = max(wait, dq->dq_omax); 76354004Sfujita } 76454004Sfujita 76554004Sfujita return; 76654004Sfujita 76754004Sfujita time_out: 76854004Sfujita scabort(hs, hd); 76954004Sfujita printf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Current Status\n", 77054004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 77154004Sfujita 77254004Sfujita if (hs->sc_lock != NULL) { 77354004Sfujita *(hs->sc_lock) = SC_IO_TIMEOUT; 77454004Sfujita } else { 77554004Sfujita (dq->dq_driver->d_intr)(dq->dq_unit, SC_IO_TIMEOUT); 77654004Sfujita } 77754004Sfujita 77854004Sfujita return; 77954004Sfujita 78054004Sfujita /* 78154004Sfujita * SCSI Abort 78254004Sfujita */ 78354004Sfujita abort: 78454004Sfujita 78554004Sfujita /* SCSI IO failed */ 78654004Sfujita scabort(hs, hd); 78754004Sfujita hd->scsi_ints = ints; 78854004Sfujita 78954004Sfujita if (hs->sc_lock != NULL) { 79054004Sfujita *(hs->sc_lock) = SC_IO_FAILED; 79154004Sfujita } else { 79254004Sfujita (dq->dq_driver->d_intr)(dq->dq_unit, SC_IO_FAILED); 79354004Sfujita } 79454004Sfujita 79554004Sfujita return; 79654004Sfujita } 79754004Sfujita 79854004Sfujita int 79954004Sfujita scabort(hs, hd) 80054004Sfujita register struct scsi_softc *hs; 80154004Sfujita volatile register struct scsidevice *hd; 80254004Sfujita { 80354004Sfujita int len; 80454004Sfujita u_char junk; 80554004Sfujita 80654004Sfujita #ifdef DEBUGPRINT 80754004Sfujita dbgprintall(); 80854004Sfujita printf("\n"); 80954004Sfujita #endif 81054004Sfujita 81154004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Current Status\n", 81254004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 81354004Sfujita 81454004Sfujita if (hd->scsi_ints != 0) 81554004Sfujita hd->scsi_ints = hd->scsi_ints; 81654004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Reset INTS reg.\n", 81754004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 81854004Sfujita 81954004Sfujita if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0) 82054004Sfujita /* no longer connected to scsi target */ 82154004Sfujita return; 82254004Sfujita 82354004Sfujita /* get the number of bytes remaining in current xfer + fudge */ 82454004Sfujita len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl; 82554004Sfujita printf("scabort: Current xfer count = %d\n", len); 82654004Sfujita 82754004Sfujita /* for that many bus cycles, try to send an abort msg */ 82854004Sfujita for (len += 1024; (hd->scsi_ssts & SSTS_INITIATOR) && --len >= 0; ) { 82954004Sfujita /* 83054004Sfujita hd->scsi_scmd = SCMD_SET_ATN; 83154004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Set ATN\n", 83254004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 83354004Sfujita */ 83454004Sfujita while ((hd->scsi_psns & PSNS_REQ) == 0) { 83554004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Wait for REQ\n", 83654004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 83754004Sfujita if (! (hd->scsi_ssts & SSTS_INITIATOR)) 83854004Sfujita goto out; 83954004Sfujita DELAY(1); 84054004Sfujita } 84154004Sfujita /* 84254004Sfujita if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE) { 84354004Sfujita hd->scsi_scmd = SCMD_RST_ATN; 84454004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Reset ATN\n", 84554004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 84654004Sfujita } 84754004Sfujita */ 84854004Sfujita hd->scsi_pctl = hs->sc_phase = hd->scsi_psns & PHASE; 84954004Sfujita printf("scabort: Phase = %s\n", phase_name(hs->sc_phase)); 85054004Sfujita 85154004Sfujita if (hd->scsi_psns & PHASE_IO) { 85254004Sfujita /* one of the input phases - read & discard a byte */ 85354004Sfujita hd->scsi_scmd = SCMD_SET_ACK; 85454004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Set ACK\n", 85554004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 85654004Sfujita 85754004Sfujita while (hd->scsi_psns & PSNS_REQ) { 85854004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Wait for REQ\n", 85954004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 86054004Sfujita DELAY(1); 86154004Sfujita } 86254004Sfujita 86354004Sfujita junk = hd->scsi_temp; 86454004Sfujita printf("scabort: TEMP = 0x%s\n", hexstr(junk, 2)); 86554004Sfujita } else { 86654004Sfujita /* one of the output phases - send an abort msg */ 86754004Sfujita hd->scsi_temp = MSG_ABORT; 86854004Sfujita hd->scsi_scmd = SCMD_SET_ACK; 86954004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Set ACK\n", 87054004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 87154004Sfujita 87254004Sfujita while (hd->scsi_psns & PSNS_REQ) { 87354004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Wait for REQ\n", 87454004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 87554004Sfujita DELAY(1); 87654004Sfujita } 87754004Sfujita } 87854004Sfujita 87954004Sfujita hd->scsi_scmd = SCMD_RST_ACK; 88054004Sfujita printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Reset ACK\n", 88154004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 88254004Sfujita } 88354004Sfujita out: 88454004Sfujita /* 88554004Sfujita * Either the abort was successful & the bus is disconnected or 88654004Sfujita * the device didn't listen. If the latter, announce the problem. 88754004Sfujita * Either way, reset the card & the SPC. 88854004Sfujita */ 88954004Sfujita if (len < 0 && hs) 89054004Sfujita printf("sc%d: abort failed. phase=0x%x, ssts=0x%x\n", 89154004Sfujita hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts); 89254004Sfujita 89354004Sfujita while (hd->scsi_ints == 0) 89454004Sfujita DELAY(1); 89554004Sfujita 89654004Sfujita hd->scsi_ints = hd->scsi_ints; 89754004Sfujita 89854004Sfujita printf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Current Status\n", 89954004Sfujita hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns); 90054004Sfujita 90154004Sfujita printf("scabort: SCSI abort operation is done\n"); 90254004Sfujita } 90354004Sfujita 90454004Sfujita 90554004Sfujita /* 90654004Sfujita * SPC device queue handling 90754004Sfujita */ 90854004Sfujita 90954004Sfujita int 91054004Sfujita screq(dq) 91154004Sfujita register struct scsi_queue *dq; 91254004Sfujita { 91354004Sfujita register struct scsi_softc *hs = &scsi_softc[dq->dq_ctlr]; 91454004Sfujita register struct scsi_queue *hq = &hs->sc_sq; 91554004Sfujita 91654004Sfujita insque(dq, hq->dq_back); 91754004Sfujita 91854004Sfujita if (dq->dq_back == hq) { 91954004Sfujita #ifdef QUE_DEBUG 92054004Sfujita printf("screq: slave = %d, command = %s\n", 92154004Sfujita hq->dq_forw->dq_slave, 92254004Sfujita scsi_command(hq->dq_forw->dq_cdb->cdb[0])); 92354004Sfujita #endif 92454004Sfujita return(1); 92554004Sfujita } 92654004Sfujita 92754004Sfujita return(0); 92854004Sfujita } 92954004Sfujita 93054004Sfujita #ifndef NODISCONNECT 93154004Sfujita int 93254004Sfujita scpend(dq) 93354004Sfujita register struct scsi_queue *dq; 93454004Sfujita { 93554004Sfujita register struct scsi_softc *hs = &scsi_softc[dq->dq_ctlr]; 93654004Sfujita register struct scsi_queue *hq = &hs->sc_sq; 93754004Sfujita register struct scsi_queue *wq = &hs->sc_wq; 93854004Sfujita 93954004Sfujita remque(dq); 94054004Sfujita 94154004Sfujita insque(dq, wq->dq_back); 94254004Sfujita } 94354004Sfujita 94454004Sfujita int 94554004Sfujita scrschdl(ctlr, slave) 94654004Sfujita register int ctlr; 94754004Sfujita register int slave; 94854004Sfujita { 94954004Sfujita register struct scsi_softc *hs = &scsi_softc[ctlr]; 95054004Sfujita register struct scsi_queue *wq = &hs->sc_wq; 95154004Sfujita register struct scsi_queue *hq = &hs->sc_sq; 95254004Sfujita register struct scsi_queue *dq; 95354004Sfujita 95454004Sfujita for (dq = wq->dq_forw; dq != wq; dq = dq->dq_forw) { 95554004Sfujita if (dq->dq_slave == slave) 95654004Sfujita goto found; 95754004Sfujita } 95854004Sfujita 95954004Sfujita return(0); 96054004Sfujita 96154004Sfujita found: 96254004Sfujita remque(dq); 96354004Sfujita insque(dq, hq); 96454004Sfujita 96554004Sfujita return(1); 96654004Sfujita } 96754004Sfujita #endif 96854004Sfujita 96954004Sfujita int 97054004Sfujita scfree(dq) 97154004Sfujita register struct scsi_queue *dq; 97254004Sfujita { 97354004Sfujita register struct scsi_softc *hs = &scsi_softc[dq->dq_ctlr]; 97454004Sfujita register struct scsi_queue *hq = &hs->sc_sq; 97554004Sfujita int status = hs->sc_stat; 97654004Sfujita 97754004Sfujita remque(dq); 97854004Sfujita 97954004Sfujita hs->sc_flags = 0; 98054004Sfujita hs->sc_phase = BUS_FREE_PHASE; 98154004Sfujita 98254004Sfujita hs->sc_stat = 0; 98354004Sfujita hs->sc_msg[0] = 0; 98454004Sfujita 98554004Sfujita if ((dq = hq->dq_forw) != hq) { 98654004Sfujita #ifdef QUE_DEBUG 98754004Sfujita printf("scfree: slave = %d, command = %s\n", 98854004Sfujita dq->dq_slave, 98954004Sfujita scsi_command(dq->dq_cdb->cdb[0])); 99054004Sfujita #endif 99154004Sfujita (dq->dq_driver->d_start)(dq->dq_unit); 99254004Sfujita } 99354004Sfujita 99454004Sfujita return(status); 99554004Sfujita } 99654004Sfujita 99754004Sfujita /* 99854004Sfujita * SCSI common interface 99954004Sfujita */ 100054004Sfujita 100154004Sfujita int scsi_lock[NSC]; 100254004Sfujita 100354004Sfujita int 100454004Sfujita scsi_result(unit, stat) 100554004Sfujita int unit, stat; 100654004Sfujita { 100754004Sfujita #ifdef SCSI_DEBUG 100854004Sfujita printf("scsi_result: stat = %s\n", scsi_status(stat)); 100954004Sfujita #endif 101054004Sfujita if (stat < 0) 101154004Sfujita scsi_lock[unit] = stat; 101254004Sfujita else 101354004Sfujita scsi_lock[unit] = SC_IO_COMPLETE; 101454004Sfujita } 101554004Sfujita 101654004Sfujita struct driver scsi_driver = { 101754004Sfujita (int (*)()) 0, "scsi", (int (*)()) 0, (int (*)()) 0, scsi_result, (int (*)()) 0 101854004Sfujita }; 101954004Sfujita 102054004Sfujita struct scsi_queue scsi_entry[NSC]; 102154004Sfujita 102254004Sfujita int 102354004Sfujita scsi_immed_command(ctlr, slave, lun, cdb, buf, len) 102454004Sfujita int ctlr, slave, lun; 102554004Sfujita struct scsi_fmt_cdb *cdb; 102654004Sfujita u_char *buf; 102754004Sfujita unsigned len; 102854004Sfujita { 102954004Sfujita register struct scsi_softc *hs = &scsi_softc[ctlr]; 103054004Sfujita volatile register struct scsidevice *hd = 103154004Sfujita (struct scsidevice *) hs->sc_hc->hp_addr; 103254004Sfujita register struct scsi_queue *dq = &scsi_entry[ctlr]; 103354004Sfujita register struct buf *bp; 103454004Sfujita int s, status, wait = 30; 103554004Sfujita 103654004Sfujita #ifdef SCSI_DEBUG 103754004Sfujita printf("scsi_immed_command( %d, %d, %d, cdb(%d,%s), buf, %d): Start\n", 103854004Sfujita ctlr, slave, lun, cdb->len, scsi_command(cdb->cdb[0]), len); 103954004Sfujita #endif 104057057Sakito bp = geteblk(len); 104157057Sakito bp->b_flags = B_BUSY; 104254004Sfujita 104354004Sfujita s = splbio(); 104454004Sfujita 104554004Sfujita dq->dq_unit = ctlr; 104654004Sfujita dq->dq_ctlr = ctlr; 104754004Sfujita dq->dq_slave = slave; 104854004Sfujita dq->dq_driver = &scsi_driver; 104954004Sfujita dq->dq_cdb = cdb; 105054004Sfujita dq->dq_bp = bp; 105154004Sfujita 105254004Sfujita scsi_lock[ctlr] = SC_IN_PROGRESS; 105354004Sfujita if (screq(dq)) 105454004Sfujita scstart(ctlr); 105554004Sfujita 105654004Sfujita splx(s); 105754004Sfujita 105854004Sfujita while (scsi_lock[ctlr] == SC_IN_PROGRESS) { 105954004Sfujita if (wait < 0) { 106054004Sfujita scabort(hs, hd); 106154004Sfujita 106254004Sfujita s = splbio(); 106354004Sfujita status = scfree(dq); 106454004Sfujita splx(s); 106554004Sfujita 106654004Sfujita bp->b_flags = 0; 106754004Sfujita 106854004Sfujita return(SC_IO_FAILED); 106954004Sfujita } 107054004Sfujita 107154004Sfujita DELAY(100000); 107254004Sfujita wait--; 107354004Sfujita } 107454004Sfujita 107554004Sfujita s = splbio(); 107654004Sfujita status = scfree(dq); 107754004Sfujita splx(s); 107854004Sfujita 107954004Sfujita if (scsi_lock[ctlr] < 0) 108054004Sfujita status = scsi_lock[ctlr]; 108154004Sfujita 108257057Sakito bcopy(bp->b_un.b_addr, buf, len); 108354004Sfujita 108457057Sakito brelse(bp); 108557057Sakito 108654004Sfujita #ifdef SCSI_DEBUG 108754004Sfujita printf("scsi_immed_command: Status -- 0x%x\n", status); 108854004Sfujita #endif 108954004Sfujita return(status); 109054004Sfujita } 109154004Sfujita 109254004Sfujita int 109354004Sfujita scsi_test_unit_rdy(ctlr, slave, lun) 109454004Sfujita int ctlr, slave, lun; 109554004Sfujita { 109654004Sfujita static struct scsi_fmt_cdb cdb = { 6, CMD_TEST_UNIT_READY }; 109754004Sfujita int stat; 109854004Sfujita 109954004Sfujita while ((stat = scsi_immed_command(ctlr, slave, lun, 110054004Sfujita &cdb, (u_char *) 0, 0)) == SC_BUSY) { 110154004Sfujita DELAY(10000); 110254004Sfujita } 110354004Sfujita 110454004Sfujita return(stat); 110554004Sfujita } 110654004Sfujita 110754004Sfujita int 110854004Sfujita scsi_request_sense(ctlr, slave, lun, buf, len) 110954004Sfujita int ctlr, slave, lun; 111054004Sfujita u_char *buf; 111154004Sfujita unsigned len; 111254004Sfujita { 111354004Sfujita register struct scsi_softc *hs = &scsi_softc[ctlr]; 111454004Sfujita volatile register struct scsidevice *hd = 111554004Sfujita (struct scsidevice *) hs->sc_hc->hp_addr; 111654004Sfujita static struct scsi_fmt_cdb req_cmd = { 6, CMD_REQUEST_SENSE }; 111754004Sfujita int s, status, lock; 111854004Sfujita 111954004Sfujita #ifdef REQ_DEBUG 112054004Sfujita printf("scsi_request_sense( %d, %d, %d, buf, %d) -- Start\n", 112154004Sfujita ctlr, slave, lun, len); 112254004Sfujita #endif 112354004Sfujita 112454004Sfujita req_cmd.cdb[1] = lun; 112554004Sfujita req_cmd.cdb[4] = len; 112654004Sfujita 112754004Sfujita if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY)) 112854004Sfujita return(0); 112954004Sfujita 113054004Sfujita s = splbio(); 113154004Sfujita 113254004Sfujita hs->sc_flags = 0; 113354004Sfujita hs->sc_phase = ARB_SEL_PHASE; 113454004Sfujita 113554004Sfujita hs->sc_cdb = req_cmd.cdb; 113654004Sfujita hs->sc_cdblen = req_cmd.len; 113754004Sfujita hs->sc_buf = buf; 113854004Sfujita hs->sc_len = len; 113954004Sfujita 114054004Sfujita hs->sc_stat = 0; 114154004Sfujita hs->sc_msg[0] = 0; 114254004Sfujita 114354004Sfujita lock = SC_IN_PROGRESS; 114454004Sfujita hs->sc_lock = &lock; 114554004Sfujita 114654004Sfujita issue_select(hd, slave, 0); 114754004Sfujita 114854004Sfujita spl0(); 114954004Sfujita 115054004Sfujita while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED)) 115154004Sfujita DELAY(10); 115254004Sfujita 115354004Sfujita splbio(); 115454004Sfujita 115554004Sfujita hs->sc_flags = 0; 115654004Sfujita hs->sc_phase = BUS_FREE_PHASE; 115754004Sfujita 115854004Sfujita hs->sc_cdb = NULL; 115954004Sfujita hs->sc_cdblen = 0; 116054004Sfujita hs->sc_buf = NULL; 116154004Sfujita hs->sc_len = 0; 116254004Sfujita hs->sc_lock = NULL; 116354004Sfujita 116454004Sfujita status = hs->sc_stat; 116554004Sfujita 116654004Sfujita hs->sc_stat = 0; 116754004Sfujita hs->sc_msg[0] = 0; 116854004Sfujita 116954004Sfujita splx(s); 117054004Sfujita 117154004Sfujita if (lock == SC_IO_COMPLETE) { 117254004Sfujita #ifdef REQ_DEBUG 117354004Sfujita printf("scsi_request_sense: Status -- 0x%x\n", status); 117454004Sfujita #endif 117554004Sfujita return(status); 117654004Sfujita } else { 117754004Sfujita return(lock); 117854004Sfujita } 117954004Sfujita } 118054004Sfujita #endif 1181