153019Smarc #ifndef DEBUG 253019Smarc #define DEBUG 353019Smarc #endif 441480Smckusick /* 541480Smckusick * Copyright (c) 1990 The Regents of the University of California. 641480Smckusick * All rights reserved. 741480Smckusick * 841480Smckusick * This code is derived from software contributed to Berkeley by 941480Smckusick * Van Jacobson of Lawrence Berkeley Laboratory. 1041480Smckusick * 1141480Smckusick * %sccs.include.redist.c% 1241480Smckusick * 13*53930Shibler * @(#)scsi.c 7.7 (Berkeley) 06/05/92 1441480Smckusick */ 1541480Smckusick 1641480Smckusick /* 1741480Smckusick * HP9000/3xx 98658 SCSI host adaptor driver. 1841480Smckusick */ 1941480Smckusick #include "scsi.h" 2041480Smckusick #if NSCSI > 0 2141480Smckusick 2241480Smckusick #ifndef lint 23*53930Shibler static char rcsid[] = "$Header: /usr/src/sys/hp300/dev/RCS/scsi.c,v 1.2 92/04/10 20:48:29 mike Exp $"; 2441480Smckusick #endif 2541480Smckusick 2645788Sbostic #include "sys/param.h" 2745788Sbostic #include "sys/systm.h" 2845788Sbostic #include "sys/buf.h" 29*53930Shibler #include "hp/dev/device.h" 3045788Sbostic 3141480Smckusick #include "scsivar.h" 3241480Smckusick #include "scsireg.h" 3341480Smckusick #include "dmavar.h" 3441480Smckusick 3545788Sbostic #include "../include/cpu.h" 3645788Sbostic #include "../hp300/isr.h" 3741480Smckusick 3846285Smckusick /* 3946285Smckusick * SCSI delays 4046285Smckusick * In u-seconds, primarily for state changes on the SPC. 4146285Smckusick */ 4246285Smckusick #define SCSI_CMD_WAIT 1000 /* wait per step of 'immediate' cmds */ 4346285Smckusick #define SCSI_DATA_WAIT 1000 /* wait per data in/out step */ 4446285Smckusick #define SCSI_INIT_WAIT 50000 /* wait per step (both) during init */ 4546285Smckusick 4641480Smckusick extern void isrlink(); 4741480Smckusick extern void _insque(); 4841480Smckusick extern void _remque(); 4941480Smckusick 5041480Smckusick int scsiinit(), scsigo(), scsiintr(), scsixfer(); 5141480Smckusick void scsistart(), scsidone(), scsifree(), scsireset(); 5241480Smckusick struct driver scsidriver = { 5341480Smckusick scsiinit, "scsi", (int (*)())scsistart, scsigo, scsiintr, 5441480Smckusick (int (*)())scsidone, 5541480Smckusick }; 5641480Smckusick 5741480Smckusick struct scsi_softc scsi_softc[NSCSI]; 5841480Smckusick struct isr scsi_isr[NSCSI]; 5941480Smckusick 6046285Smckusick int scsi_cmd_wait = SCSI_CMD_WAIT; 6146285Smckusick int scsi_data_wait = SCSI_DATA_WAIT; 6246285Smckusick int scsi_init_wait = SCSI_INIT_WAIT; 6346285Smckusick 6441480Smckusick int scsi_nosync = 1; /* inhibit sync xfers if 1 */ 6545514Smckusick int scsi_pridma = 0; /* use "priority" dma */ 6641480Smckusick 6741480Smckusick #ifdef DEBUG 6841480Smckusick int scsi_debug = 0; 6941480Smckusick #define WAITHIST 7041480Smckusick #endif 7141480Smckusick 7241480Smckusick #ifdef WAITHIST 7345514Smckusick #define MAXWAIT 1022 7441480Smckusick u_int ixstart_wait[MAXWAIT+2]; 7541480Smckusick u_int ixin_wait[MAXWAIT+2]; 7641480Smckusick u_int ixout_wait[MAXWAIT+2]; 7741480Smckusick u_int mxin_wait[MAXWAIT+2]; 7846285Smckusick u_int mxin2_wait[MAXWAIT+2]; 7941480Smckusick u_int cxin_wait[MAXWAIT+2]; 8041480Smckusick u_int fxfr_wait[MAXWAIT+2]; 8141480Smckusick u_int sgo_wait[MAXWAIT+2]; 8241480Smckusick #define HIST(h,w) (++h[((w)>MAXWAIT? MAXWAIT : ((w) < 0 ? -1 : (w))) + 1]); 8341480Smckusick #else 8441480Smckusick #define HIST(h,w) 8541480Smckusick #endif 8641480Smckusick 8741480Smckusick #define b_cylin b_resid 8841480Smckusick 8941480Smckusick static void 9041480Smckusick scsiabort(hs, hd, where) 9141480Smckusick register struct scsi_softc *hs; 9241480Smckusick volatile register struct scsidevice *hd; 9341480Smckusick char *where; 9441480Smckusick { 9541480Smckusick int len; 9653019Smarc int maxtries; /* XXX - kludge till I understand whats *supposed* to happen */ 9753019Smarc int startlen; /* XXX - kludge till I understand whats *supposed* to happen */ 9841480Smckusick u_char junk; 9941480Smckusick 10041480Smckusick printf("scsi%d: abort from %s: phase=0x%x, ssts=0x%x, ints=0x%x\n", 10141480Smckusick hs->sc_hc->hp_unit, where, hd->scsi_psns, hd->scsi_ssts, 10241480Smckusick hd->scsi_ints); 10341480Smckusick 10441480Smckusick hd->scsi_ints = hd->scsi_ints; 10541480Smckusick hd->scsi_csr = 0; 10641480Smckusick if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0) 10741480Smckusick /* no longer connected to scsi target */ 10841480Smckusick return; 10941480Smckusick 11041480Smckusick /* get the number of bytes remaining in current xfer + fudge */ 11141480Smckusick len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl; 11241480Smckusick 11341480Smckusick /* for that many bus cycles, try to send an abort msg */ 11453019Smarc for (startlen = (len += 1024); (hd->scsi_ssts & SSTS_INITIATOR) && --len >= 0; ) { 11541480Smckusick hd->scsi_scmd = SCMD_SET_ATN; 11653019Smarc maxtries = 1000; 11741480Smckusick while ((hd->scsi_psns & PSNS_REQ) == 0) { 11841480Smckusick if (! (hd->scsi_ssts & SSTS_INITIATOR)) 11941480Smckusick goto out; 12041480Smckusick DELAY(1); 12153019Smarc if (--maxtries == 0) { 12253019Smarc printf("-- scsiabort gave up after 1000 tries (startlen = %d len = %d)\n", 12353019Smarc startlen, len); 12453019Smarc goto out2; 12553019Smarc } 12653019Smarc 12741480Smckusick } 12853019Smarc out2: 12941480Smckusick if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE) 13041480Smckusick hd->scsi_scmd = SCMD_RST_ATN; 13141480Smckusick hd->scsi_pctl = hd->scsi_psns & PHASE; 13241480Smckusick if (hd->scsi_psns & PHASE_IO) { 13341480Smckusick /* one of the input phases - read & discard a byte */ 13441480Smckusick hd->scsi_scmd = SCMD_SET_ACK; 13541480Smckusick if (hd->scsi_tmod == 0) 13641480Smckusick while (hd->scsi_psns & PSNS_REQ) 13741480Smckusick DELAY(1); 13841480Smckusick junk = hd->scsi_temp; 13941480Smckusick } else { 14041480Smckusick /* one of the output phases - send an abort msg */ 14141480Smckusick hd->scsi_temp = MSG_ABORT; 14241480Smckusick hd->scsi_scmd = SCMD_SET_ACK; 14341480Smckusick if (hd->scsi_tmod == 0) 14441480Smckusick while (hd->scsi_psns & PSNS_REQ) 14541480Smckusick DELAY(1); 14641480Smckusick } 14741480Smckusick hd->scsi_scmd = SCMD_RST_ACK; 14841480Smckusick } 14941480Smckusick out: 15041480Smckusick /* 15141480Smckusick * Either the abort was successful & the bus is disconnected or 15241480Smckusick * the device didn't listen. If the latter, announce the problem. 15341480Smckusick * Either way, reset the card & the SPC. 15441480Smckusick */ 15541480Smckusick if (len < 0 && hs) 15641480Smckusick printf("scsi%d: abort failed. phase=0x%x, ssts=0x%x\n", 15741480Smckusick hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts); 15841480Smckusick 15941480Smckusick if (! ((junk = hd->scsi_ints) & INTS_RESEL)) { 16041480Smckusick hd->scsi_sctl |= SCTL_CTRLRST; 16141480Smckusick DELAY(1); 16241480Smckusick hd->scsi_sctl &=~ SCTL_CTRLRST; 16341480Smckusick hd->scsi_hconf = 0; 16441480Smckusick hd->scsi_ints = hd->scsi_ints; 16541480Smckusick } 16641480Smckusick } 16741480Smckusick 16846285Smckusick /* 16946285Smckusick * XXX Set/reset long delays. 17046285Smckusick * 17146285Smckusick * if delay == 0, reset default delays 17246285Smckusick * if delay < 0, set both delays to default long initialization values 17346285Smckusick * if delay > 0, set both delays to this value 17446285Smckusick * 17546285Smckusick * Used when a devices is expected to respond slowly (e.g. during 17646285Smckusick * initialization). 17746285Smckusick */ 17846285Smckusick void 17946285Smckusick scsi_delay(delay) 18046285Smckusick int delay; 18146285Smckusick { 18246285Smckusick static int saved_cmd_wait, saved_data_wait; 18346285Smckusick 18446285Smckusick if (delay) { 18546285Smckusick saved_cmd_wait = scsi_cmd_wait; 18646285Smckusick saved_data_wait = scsi_data_wait; 18746285Smckusick if (delay > 0) 18846285Smckusick scsi_cmd_wait = scsi_data_wait = delay; 18946285Smckusick else 19046285Smckusick scsi_cmd_wait = scsi_data_wait = scsi_init_wait; 19146285Smckusick } else { 19246285Smckusick scsi_cmd_wait = saved_cmd_wait; 19346285Smckusick scsi_data_wait = saved_data_wait; 19446285Smckusick } 19546285Smckusick } 19646285Smckusick 19741480Smckusick int 19841480Smckusick scsiinit(hc) 19941480Smckusick register struct hp_ctlr *hc; 20041480Smckusick { 20141480Smckusick register struct scsi_softc *hs = &scsi_softc[hc->hp_unit]; 20241480Smckusick register struct scsidevice *hd = (struct scsidevice *)hc->hp_addr; 20341480Smckusick 20441480Smckusick if ((hd->scsi_id & ID_MASK) != SCSI_ID) 20541480Smckusick return(0); 20641480Smckusick hc->hp_ipl = SCSI_IPL(hd->scsi_csr); 20741480Smckusick hs->sc_hc = hc; 20841480Smckusick hs->sc_dq.dq_unit = hc->hp_unit; 20941480Smckusick hs->sc_dq.dq_driver = &scsidriver; 21041480Smckusick hs->sc_sq.dq_forw = hs->sc_sq.dq_back = &hs->sc_sq; 21141480Smckusick scsi_isr[hc->hp_unit].isr_intr = scsiintr; 21241480Smckusick scsi_isr[hc->hp_unit].isr_ipl = hc->hp_ipl; 21341480Smckusick scsi_isr[hc->hp_unit].isr_arg = hc->hp_unit; 21441480Smckusick isrlink(&scsi_isr[hc->hp_unit]); 21541480Smckusick scsireset(hc->hp_unit); 216*53930Shibler /* 217*53930Shibler * XXX scale initialization wait according to CPU speed. 218*53930Shibler * Should we do this for all wait? Should we do this at all? 219*53930Shibler */ 220*53930Shibler scsi_init_wait *= cpuspeed; 22141480Smckusick return(1); 22241480Smckusick } 22341480Smckusick 22441480Smckusick void 22541480Smckusick scsireset(unit) 22641480Smckusick register int unit; 22741480Smckusick { 22841480Smckusick register struct scsi_softc *hs = &scsi_softc[unit]; 22941480Smckusick volatile register struct scsidevice *hd = 23041480Smckusick (struct scsidevice *)hs->sc_hc->hp_addr; 23141480Smckusick u_int i; 23241480Smckusick 23341480Smckusick if (hs->sc_flags & SCSI_ALIVE) 23441480Smckusick scsiabort(hs, hd, "reset"); 23541480Smckusick 23641480Smckusick printf("scsi%d: ", unit); 23741480Smckusick 23841480Smckusick hd->scsi_id = 0xFF; 23941480Smckusick DELAY(100); 24041480Smckusick /* 24141480Smckusick * Disable interrupts then reset the FUJI chip. 24241480Smckusick */ 24341480Smckusick hd->scsi_csr = 0; 24441480Smckusick hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST; 24541480Smckusick hd->scsi_scmd = 0; 24641480Smckusick hd->scsi_tmod = 0; 24741480Smckusick hd->scsi_pctl = 0; 24841480Smckusick hd->scsi_temp = 0; 24941480Smckusick hd->scsi_tch = 0; 25041480Smckusick hd->scsi_tcm = 0; 25141480Smckusick hd->scsi_tcl = 0; 25241480Smckusick hd->scsi_ints = 0; 25341480Smckusick 25441480Smckusick if ((hd->scsi_id & ID_WORD_DMA) == 0) { 25541480Smckusick hs->sc_flags |= SCSI_DMA32; 25641480Smckusick printf("32 bit dma, "); 25741480Smckusick } 25841480Smckusick 25941480Smckusick /* Determine Max Synchronous Transfer Rate */ 26041480Smckusick if (scsi_nosync) 26141480Smckusick i = 3; 26241480Smckusick else 26341480Smckusick i = SCSI_SYNC_XFER(hd->scsi_hconf); 26441480Smckusick switch (i) { 26541480Smckusick case 0: 26641480Smckusick hs->sc_sync = TMOD_SYNC | 0x3e; /* 250 nsecs */ 26741480Smckusick printf("250ns sync"); 26841480Smckusick break; 26941480Smckusick case 1: 27041480Smckusick hs->sc_sync = TMOD_SYNC | 0x5e; /* 375 nsecs */ 27141480Smckusick printf("375ns sync"); 27241480Smckusick break; 27341480Smckusick case 2: 27441480Smckusick hs->sc_sync = TMOD_SYNC | 0x7d; /* 500 nsecs */ 27541480Smckusick printf("500ns sync"); 27641480Smckusick break; 27741480Smckusick case 3: 27841480Smckusick hs->sc_sync = 0; 27941480Smckusick printf("async"); 28041480Smckusick break; 28141480Smckusick } 28241480Smckusick 28341480Smckusick /* 28441480Smckusick * Configure the FUJI chip with its SCSI address, all 28541480Smckusick * interrupts enabled & appropriate parity. 28641480Smckusick */ 28741480Smckusick i = (~hd->scsi_hconf) & 0x7; 28841480Smckusick hs->sc_scsi_addr = 1 << i; 28941480Smckusick hd->scsi_bdid = i; 29041480Smckusick if (hd->scsi_hconf & HCONF_PARITY) 29141480Smckusick hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB | 29241480Smckusick SCTL_SEL_ENAB | SCTL_RESEL_ENAB | 29341480Smckusick SCTL_INTR_ENAB | SCTL_PARITY_ENAB; 29441480Smckusick else { 29541480Smckusick hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB | 29641480Smckusick SCTL_SEL_ENAB | SCTL_RESEL_ENAB | 29741480Smckusick SCTL_INTR_ENAB; 29841480Smckusick printf(", no parity"); 29941480Smckusick } 30041480Smckusick hd->scsi_sctl &=~ SCTL_DISABLE; 30141480Smckusick 30241480Smckusick printf(", scsi id %d\n", i); 30341480Smckusick hs->sc_flags |= SCSI_ALIVE; 30441480Smckusick } 30541480Smckusick 30641480Smckusick static void 30741480Smckusick scsierror(hs, hd, ints) 30841480Smckusick register struct scsi_softc *hs; 30941480Smckusick volatile register struct scsidevice *hd; 31041480Smckusick u_char ints; 31141480Smckusick { 31241480Smckusick int unit = hs->sc_hc->hp_unit; 31341480Smckusick char *sep = ""; 31441480Smckusick 31541480Smckusick printf("scsi%d: ", unit); 31641480Smckusick if (ints & INTS_RST) { 31741480Smckusick DELAY(100); 31841480Smckusick if (hd->scsi_hconf & HCONF_SD) 31941480Smckusick printf("spurious RST interrupt"); 32041480Smckusick else 32141480Smckusick printf("hardware error - check fuse"); 32241480Smckusick sep = ", "; 32341480Smckusick } 32441480Smckusick if ((ints & INTS_HARD_ERR) || hd->scsi_serr) { 32541480Smckusick if (hd->scsi_serr & SERR_SCSI_PAR) { 32641480Smckusick printf("%sparity err", sep); 32741480Smckusick sep = ", "; 32841480Smckusick } 32941480Smckusick if (hd->scsi_serr & SERR_SPC_PAR) { 33041480Smckusick printf("%sSPC parity err", sep); 33141480Smckusick sep = ", "; 33241480Smckusick } 33341480Smckusick if (hd->scsi_serr & SERR_TC_PAR) { 33441480Smckusick printf("%sTC parity err", sep); 33541480Smckusick sep = ", "; 33641480Smckusick } 33741480Smckusick if (hd->scsi_serr & SERR_PHASE_ERR) { 33841480Smckusick printf("%sphase err", sep); 33941480Smckusick sep = ", "; 34041480Smckusick } 34141480Smckusick if (hd->scsi_serr & SERR_SHORT_XFR) { 34241480Smckusick printf("%ssync short transfer err", sep); 34341480Smckusick sep = ", "; 34441480Smckusick } 34541480Smckusick if (hd->scsi_serr & SERR_OFFSET) { 34641480Smckusick printf("%ssync offset error", sep); 34741480Smckusick sep = ", "; 34841480Smckusick } 34941480Smckusick } 35041480Smckusick if (ints & INTS_TIMEOUT) 35141480Smckusick printf("%sSPC select timeout error", sep); 35241480Smckusick if (ints & INTS_SRV_REQ) 35341480Smckusick printf("%sspurious SRV_REQ interrupt", sep); 35441480Smckusick if (ints & INTS_CMD_DONE) 35541480Smckusick printf("%sspurious CMD_DONE interrupt", sep); 35641480Smckusick if (ints & INTS_DISCON) 35741480Smckusick printf("%sspurious disconnect interrupt", sep); 35841480Smckusick if (ints & INTS_RESEL) 35941480Smckusick printf("%sspurious reselect interrupt", sep); 36041480Smckusick if (ints & INTS_SEL) 36141480Smckusick printf("%sspurious select interrupt", sep); 36241480Smckusick printf("\n"); 36341480Smckusick } 36441480Smckusick 36541480Smckusick static int 36641480Smckusick issue_select(hd, target, our_addr) 36741480Smckusick volatile register struct scsidevice *hd; 36841480Smckusick u_char target, our_addr; 36941480Smckusick { 37041480Smckusick if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY)) 37141480Smckusick return (1); 37241480Smckusick 37341480Smckusick if (hd->scsi_ints & INTS_DISCON) 37441480Smckusick hd->scsi_ints = INTS_DISCON; 37541480Smckusick 37641480Smckusick hd->scsi_pctl = 0; 37741480Smckusick hd->scsi_temp = (1 << target) | our_addr; 37841480Smckusick /* select timeout is hardcoded to 2ms */ 37941480Smckusick hd->scsi_tch = 0; 38041480Smckusick hd->scsi_tcm = 32; 38141480Smckusick hd->scsi_tcl = 4; 38241480Smckusick 38341480Smckusick hd->scsi_scmd = SCMD_SELECT; 38441480Smckusick return (0); 38541480Smckusick } 38641480Smckusick 38741480Smckusick static int 38841480Smckusick wait_for_select(hd) 38941480Smckusick volatile register struct scsidevice *hd; 39041480Smckusick { 39141480Smckusick u_char ints; 39241480Smckusick 39341480Smckusick while ((ints = hd->scsi_ints) == 0) 39441480Smckusick DELAY(1); 39541480Smckusick hd->scsi_ints = ints; 39641480Smckusick return (!(hd->scsi_ssts & SSTS_INITIATOR)); 39741480Smckusick } 39841480Smckusick 39941480Smckusick static int 40041480Smckusick ixfer_start(hd, len, phase, wait) 40141480Smckusick volatile register struct scsidevice *hd; 40241480Smckusick int len; 40341480Smckusick u_char phase; 40441480Smckusick register int wait; 40541480Smckusick { 40641480Smckusick 40741480Smckusick hd->scsi_tch = len >> 16; 40841480Smckusick hd->scsi_tcm = len >> 8; 40941480Smckusick hd->scsi_tcl = len; 41041480Smckusick hd->scsi_pctl = phase; 41141480Smckusick hd->scsi_tmod = 0; /*XXX*/ 41241480Smckusick hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR; 41341480Smckusick 41441480Smckusick /* wait for xfer to start or svc_req interrupt */ 41541480Smckusick while ((hd->scsi_ssts & SSTS_BUSY) == 0) { 41641480Smckusick if (hd->scsi_ints || --wait < 0) { 41741480Smckusick #ifdef DEBUG 41841480Smckusick if (scsi_debug) 41941480Smckusick printf("ixfer_start fail: i%x, w%d\n", 42041480Smckusick hd->scsi_ints, wait); 42141480Smckusick #endif 42241480Smckusick HIST(ixstart_wait, wait) 42341480Smckusick return (0); 42441480Smckusick } 42541480Smckusick DELAY(1); 42641480Smckusick } 42741480Smckusick HIST(ixstart_wait, wait) 42841480Smckusick return (1); 42941480Smckusick } 43041480Smckusick 43141480Smckusick static int 43241480Smckusick ixfer_out(hd, len, buf) 43341480Smckusick volatile register struct scsidevice *hd; 43441480Smckusick int len; 43541480Smckusick register u_char *buf; 43641480Smckusick { 43741480Smckusick register int wait = scsi_data_wait; 43841480Smckusick 43941480Smckusick for (; len > 0; --len) { 44041480Smckusick while (hd->scsi_ssts & SSTS_DREG_FULL) { 44141480Smckusick if (hd->scsi_ints || --wait < 0) { 44241480Smckusick #ifdef DEBUG 44341480Smckusick if (scsi_debug) 44441480Smckusick printf("ixfer_out fail: l%d i%x w%d\n", 44541480Smckusick len, hd->scsi_ints, wait); 44641480Smckusick #endif 44741480Smckusick HIST(ixout_wait, wait) 44841480Smckusick return (len); 44941480Smckusick } 45041480Smckusick DELAY(1); 45141480Smckusick } 45241480Smckusick hd->scsi_dreg = *buf++; 45341480Smckusick } 45441480Smckusick HIST(ixout_wait, wait) 45541480Smckusick return (0); 45641480Smckusick } 45741480Smckusick 45841480Smckusick static void 45941480Smckusick ixfer_in(hd, len, buf) 46041480Smckusick volatile register struct scsidevice *hd; 46141480Smckusick int len; 46241480Smckusick register u_char *buf; 46341480Smckusick { 46441480Smckusick register int wait = scsi_data_wait; 46541480Smckusick 46641480Smckusick for (; len > 0; --len) { 46741480Smckusick while (hd->scsi_ssts & SSTS_DREG_EMPTY) { 46841480Smckusick if (hd->scsi_ints || --wait < 0) { 46941480Smckusick while (! (hd->scsi_ssts & SSTS_DREG_EMPTY)) { 47041480Smckusick *buf++ = hd->scsi_dreg; 47141480Smckusick --len; 47241480Smckusick } 47341480Smckusick #ifdef DEBUG 47441480Smckusick if (scsi_debug) 47541480Smckusick printf("ixfer_in fail: l%d i%x w%d\n", 47641480Smckusick len, hd->scsi_ints, wait); 47741480Smckusick #endif 47841480Smckusick HIST(ixin_wait, wait) 47941480Smckusick return; 48041480Smckusick } 48141480Smckusick DELAY(1); 48241480Smckusick } 48341480Smckusick *buf++ = hd->scsi_dreg; 48441480Smckusick } 48541480Smckusick HIST(ixin_wait, wait) 48641480Smckusick } 48741480Smckusick 48841480Smckusick static int 48941480Smckusick mxfer_in(hd, len, buf, phase) 49041480Smckusick volatile register struct scsidevice *hd; 49141480Smckusick register int len; 49241480Smckusick register u_char *buf; 49341480Smckusick register u_char phase; 49441480Smckusick { 49541480Smckusick register int wait = scsi_cmd_wait; 49641480Smckusick register int i; 49741480Smckusick 49841480Smckusick hd->scsi_tmod = 0; 49941480Smckusick for (i = 0; i < len; ++i) { 50041480Smckusick /* 50146285Smckusick * manual sez: reset ATN before ACK is sent. 50246285Smckusick */ 50346285Smckusick if (hd->scsi_psns & PSNS_ATN) 50446285Smckusick hd->scsi_scmd = SCMD_RST_ATN; 50546285Smckusick /* 50641480Smckusick * wait for the request line (which says the target 50741480Smckusick * wants to give us data). If the phase changes while 50841480Smckusick * we're waiting, we're done. 50941480Smckusick */ 51041480Smckusick while ((hd->scsi_psns & PSNS_REQ) == 0) { 51141480Smckusick if (--wait < 0) { 51241480Smckusick HIST(mxin_wait, wait) 51341480Smckusick return (-1); 51441480Smckusick } 51541480Smckusick if ((hd->scsi_psns & PHASE) != phase || 51641480Smckusick (hd->scsi_ssts & SSTS_INITIATOR) == 0) 51741480Smckusick goto out; 51841480Smckusick 51941480Smckusick DELAY(1); 52041480Smckusick } 52141480Smckusick /* 52241480Smckusick * set ack (which says we're ready for the data, wait for 52341480Smckusick * req to go away (target says data is available), grab the 52441480Smckusick * data, then reset ack (say we've got the data). 52541480Smckusick */ 52641480Smckusick hd->scsi_pctl = phase; 52741480Smckusick hd->scsi_scmd = SCMD_SET_ACK; 52841480Smckusick while (hd->scsi_psns & PSNS_REQ) { 52941480Smckusick if (--wait < 0) { 53041480Smckusick HIST(mxin_wait, wait) 53141480Smckusick return (-2); 53241480Smckusick } 53341480Smckusick DELAY(1); 53441480Smckusick } 53541480Smckusick *buf++ = hd->scsi_temp; 53641480Smckusick hd->scsi_scmd = SCMD_RST_ACK; 53741480Smckusick } 53841480Smckusick out: 53941480Smckusick HIST(mxin_wait, wait) 54046285Smckusick /* 54146285Smckusick * Wait for manual transfer to finish. 54246285Smckusick * Avoids occasional "unexpected phase" errors in finishxfer 54346285Smckusick * formerly addressed by per-slave delays. 54446285Smckusick */ 54546285Smckusick wait = scsi_cmd_wait; 54646285Smckusick while ((hd->scsi_ssts & SSTS_ACTIVE) == SSTS_INITIATOR) { 54746285Smckusick if (--wait < 0) 54846285Smckusick break; 54946285Smckusick DELAY(1); 55046285Smckusick } 55146285Smckusick HIST(mxin2_wait, wait) 55241480Smckusick return (i); 55341480Smckusick } 55441480Smckusick 55541480Smckusick /* 55641480Smckusick * SCSI 'immediate' command: issue a command to some SCSI device 55741480Smckusick * and get back an 'immediate' response (i.e., do programmed xfer 55841480Smckusick * to get the response data). 'cbuf' is a buffer containing a scsi 55941480Smckusick * command of length clen bytes. 'buf' is a buffer of length 'len' 56041480Smckusick * bytes for data. The transfer direction is determined by the device 56141480Smckusick * (i.e., by the scsi bus data xfer phase). If 'len' is zero, the 56241480Smckusick * command must supply no data. 'xferphase' is the bus phase the 56341480Smckusick * caller expects to happen after the command is issued. It should 56441480Smckusick * be one of DATA_IN_PHASE, DATA_OUT_PHASE or STATUS_PHASE. 56541480Smckusick */ 56641480Smckusick static int 56741480Smckusick scsiicmd(hs, target, cbuf, clen, buf, len, xferphase) 56841480Smckusick struct scsi_softc *hs; 56941480Smckusick int target; 57041480Smckusick u_char *cbuf; 57141480Smckusick int clen; 57241480Smckusick u_char *buf; 57341480Smckusick int len; 57441480Smckusick u_char xferphase; 57541480Smckusick { 57641480Smckusick volatile register struct scsidevice *hd = 57741480Smckusick (struct scsidevice *)hs->sc_hc->hp_addr; 57841480Smckusick u_char phase, ints; 57941480Smckusick register int wait; 58041480Smckusick 58141480Smckusick /* select the SCSI bus (it's an error if bus isn't free) */ 58241480Smckusick if (issue_select(hd, target, hs->sc_scsi_addr)) 58341480Smckusick return (-1); 58441480Smckusick if (wait_for_select(hd)) 58541480Smckusick return (-1); 58641480Smckusick /* 58741480Smckusick * Wait for a phase change (or error) then let the device 58841480Smckusick * sequence us through the various SCSI phases. 58941480Smckusick */ 59041480Smckusick hs->sc_stat[0] = 0xff; 59141480Smckusick hs->sc_msg[0] = 0xff; 59241480Smckusick phase = CMD_PHASE; 59341480Smckusick while (1) { 59441480Smckusick wait = scsi_cmd_wait; 59541480Smckusick switch (phase) { 59641480Smckusick 59741480Smckusick case CMD_PHASE: 59841480Smckusick if (ixfer_start(hd, clen, phase, wait)) 59941480Smckusick if (ixfer_out(hd, clen, cbuf)) 60041480Smckusick goto abort; 60141480Smckusick phase = xferphase; 60241480Smckusick break; 60341480Smckusick 60441480Smckusick case DATA_IN_PHASE: 60541480Smckusick if (len <= 0) 60641480Smckusick goto abort; 60741480Smckusick wait = scsi_data_wait; 60841480Smckusick if (ixfer_start(hd, len, phase, wait) || 60941480Smckusick !(hd->scsi_ssts & SSTS_DREG_EMPTY)) 61041480Smckusick ixfer_in(hd, len, buf); 61141480Smckusick phase = STATUS_PHASE; 61241480Smckusick break; 61341480Smckusick 61441480Smckusick case DATA_OUT_PHASE: 61541480Smckusick if (len <= 0) 61641480Smckusick goto abort; 61741480Smckusick wait = scsi_data_wait; 61841480Smckusick if (ixfer_start(hd, len, phase, wait)) { 61941480Smckusick if (ixfer_out(hd, len, buf)) 62041480Smckusick goto abort; 62141480Smckusick } 62241480Smckusick phase = STATUS_PHASE; 62341480Smckusick break; 62441480Smckusick 62541480Smckusick case STATUS_PHASE: 62641480Smckusick wait = scsi_data_wait; 62741480Smckusick if (ixfer_start(hd, sizeof(hs->sc_stat), phase, wait) || 62841480Smckusick !(hd->scsi_ssts & SSTS_DREG_EMPTY)) 62941480Smckusick ixfer_in(hd, sizeof(hs->sc_stat), hs->sc_stat); 63041480Smckusick phase = MESG_IN_PHASE; 63141480Smckusick break; 63241480Smckusick 63341480Smckusick case MESG_IN_PHASE: 63441480Smckusick if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait) || 63541480Smckusick !(hd->scsi_ssts & SSTS_DREG_EMPTY)) { 63641480Smckusick ixfer_in(hd, sizeof(hs->sc_msg), hs->sc_msg); 63741480Smckusick hd->scsi_scmd = SCMD_RST_ACK; 63841480Smckusick } 63941480Smckusick phase = BUS_FREE_PHASE; 64041480Smckusick break; 64141480Smckusick 64241480Smckusick case BUS_FREE_PHASE: 64341480Smckusick goto out; 64441480Smckusick 64541480Smckusick default: 64641480Smckusick printf("scsi%d: unexpected phase %d in icmd from %d\n", 64741480Smckusick hs->sc_hc->hp_unit, phase, target); 64841480Smckusick goto abort; 64941480Smckusick } 65041480Smckusick /* wait for last command to complete */ 65141480Smckusick while ((ints = hd->scsi_ints) == 0) { 65241480Smckusick if (--wait < 0) { 65341480Smckusick HIST(cxin_wait, wait) 65441480Smckusick goto abort; 65541480Smckusick } 65641480Smckusick DELAY(1); 65741480Smckusick } 65841480Smckusick HIST(cxin_wait, wait) 65941480Smckusick hd->scsi_ints = ints; 66041480Smckusick if (ints & INTS_SRV_REQ) 66141480Smckusick phase = hd->scsi_psns & PHASE; 66241480Smckusick else if (ints & INTS_DISCON) 66341480Smckusick goto out; 66441480Smckusick else if ((ints & INTS_CMD_DONE) == 0) { 66541480Smckusick scsierror(hs, hd, ints); 66641480Smckusick goto abort; 66741480Smckusick } 66841480Smckusick } 66941480Smckusick abort: 67041480Smckusick scsiabort(hs, hd, "icmd"); 67141480Smckusick out: 67241480Smckusick return (hs->sc_stat[0]); 67341480Smckusick } 67441480Smckusick 67541480Smckusick /* 67641480Smckusick * Finish SCSI xfer command: After the completion interrupt from 67741480Smckusick * a read/write operation, sequence through the final phases in 67841480Smckusick * programmed i/o. This routine is a lot like scsiicmd except we 67941480Smckusick * skip (and don't allow) the select, cmd out and data in/out phases. 68041480Smckusick */ 68141480Smckusick static void 68241480Smckusick finishxfer(hs, hd, target) 68341480Smckusick struct scsi_softc *hs; 68441480Smckusick volatile register struct scsidevice *hd; 68541480Smckusick int target; 68641480Smckusick { 68741480Smckusick u_char phase, ints; 68841480Smckusick 68941480Smckusick /* 69041480Smckusick * We specified padding xfer so we ended with either a phase 69141480Smckusick * change interrupt (normal case) or an error interrupt (handled 69241480Smckusick * elsewhere). Reset the board dma logic then try to get the 69341480Smckusick * completion status & command done msg. The reset confuses 69441480Smckusick * the SPC REQ/ACK logic so we have to do any status/msg input 69541480Smckusick * operations via 'manual xfer'. 69641480Smckusick */ 69741480Smckusick if (hd->scsi_ssts & SSTS_BUSY) { 69841480Smckusick int wait = scsi_cmd_wait; 69941480Smckusick 70041480Smckusick /* wait for dma operation to finish */ 70141480Smckusick while (hd->scsi_ssts & SSTS_BUSY) { 70241480Smckusick if (--wait < 0) { 70341480Smckusick #ifdef DEBUG 70441480Smckusick if (scsi_debug) 70541480Smckusick printf("finishxfer fail: ssts %x\n", 70641480Smckusick hd->scsi_ssts); 70741480Smckusick #endif 70841480Smckusick HIST(fxfr_wait, wait) 70941480Smckusick goto abort; 71041480Smckusick } 71141480Smckusick } 71241480Smckusick HIST(fxfr_wait, wait) 71341480Smckusick } 71441480Smckusick hd->scsi_scmd |= SCMD_PROG_XFR; 71541480Smckusick hd->scsi_sctl |= SCTL_CTRLRST; 71641480Smckusick DELAY(1); 71741480Smckusick hd->scsi_sctl &=~ SCTL_CTRLRST; 71841480Smckusick hd->scsi_hconf = 0; 71953019Smarc /* 72053019Smarc * The following delay is definitely needed when trying to 72153019Smarc * write on a write protected disk (in the optical jukebox anyways), 72253019Smarc * but we shall see if other unexplained machine freezeups 72353019Smarc * also stop occuring... A value of 5 seems to work but 72453019Smarc * 10 seems safer considering the potential consequences. 72553019Smarc */ 72653019Smarc DELAY(10); 72741480Smckusick hs->sc_stat[0] = 0xff; 72841480Smckusick hs->sc_msg[0] = 0xff; 72941480Smckusick hd->scsi_csr = 0; 73041480Smckusick hd->scsi_ints = ints = hd->scsi_ints; 73141480Smckusick while (1) { 73241480Smckusick phase = hd->scsi_psns & PHASE; 73341480Smckusick switch (phase) { 73441480Smckusick 73541480Smckusick case STATUS_PHASE: 73641480Smckusick if (mxfer_in(hd, sizeof(hs->sc_stat), hs->sc_stat, 73741480Smckusick phase) <= 0) 73841480Smckusick goto abort; 73941480Smckusick break; 74041480Smckusick 74141480Smckusick case MESG_IN_PHASE: 74241480Smckusick if (mxfer_in(hd, sizeof(hs->sc_msg), hs->sc_msg, 74341480Smckusick phase) < 0) 74441480Smckusick goto abort; 74541480Smckusick break; 74641480Smckusick 74741480Smckusick case BUS_FREE_PHASE: 74841480Smckusick return; 74941480Smckusick 75041480Smckusick default: 75141480Smckusick printf("scsi%d: unexpected phase %d in finishxfer from %d\n", 75241480Smckusick hs->sc_hc->hp_unit, phase, target); 75341480Smckusick goto abort; 75441480Smckusick } 75541480Smckusick if (ints = hd->scsi_ints) { 75641480Smckusick hd->scsi_ints = ints; 75741480Smckusick if (ints & INTS_DISCON) 75841480Smckusick return; 75941480Smckusick else if (ints & ~(INTS_SRV_REQ|INTS_CMD_DONE)) { 76041480Smckusick scsierror(hs, hd, ints); 76141480Smckusick break; 76241480Smckusick } 76341480Smckusick } 76441480Smckusick if ((hd->scsi_ssts & SSTS_INITIATOR) == 0) 76541480Smckusick return; 76641480Smckusick } 76741480Smckusick abort: 76841480Smckusick scsiabort(hs, hd, "finishxfer"); 76941480Smckusick hs->sc_stat[0] = 0xfe; 77041480Smckusick } 77141480Smckusick 77241480Smckusick int 77341480Smckusick scsi_test_unit_rdy(ctlr, slave, unit) 77441480Smckusick int ctlr, slave, unit; 77541480Smckusick { 77641480Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 77741480Smckusick static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY }; 77841480Smckusick 77941480Smckusick cdb.lun = unit; 78041480Smckusick return (scsiicmd(hs, slave, &cdb, sizeof(cdb), (u_char *)0, 0, 78141480Smckusick STATUS_PHASE)); 78241480Smckusick } 78341480Smckusick 78441480Smckusick int 78541480Smckusick scsi_request_sense(ctlr, slave, unit, buf, len) 78641480Smckusick int ctlr, slave, unit; 78741480Smckusick u_char *buf; 78841480Smckusick unsigned len; 78941480Smckusick { 79041480Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 79141480Smckusick static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE }; 79241480Smckusick 79341480Smckusick cdb.lun = unit; 79441480Smckusick cdb.len = len; 79541480Smckusick return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE)); 79641480Smckusick } 79741480Smckusick 79841480Smckusick int 79941480Smckusick scsi_immed_command(ctlr, slave, unit, cdb, buf, len, rd) 80041480Smckusick int ctlr, slave, unit; 80141480Smckusick struct scsi_fmt_cdb *cdb; 80241480Smckusick u_char *buf; 80341480Smckusick unsigned len; 80441480Smckusick { 80541480Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 80641480Smckusick 80741480Smckusick cdb->cdb[1] |= unit << 5; 80841480Smckusick return (scsiicmd(hs, slave, cdb->cdb, cdb->len, buf, len, 80941480Smckusick rd != 0? DATA_IN_PHASE : DATA_OUT_PHASE)); 81041480Smckusick } 81141480Smckusick 81241480Smckusick /* 81341480Smckusick * The following routines are test-and-transfer i/o versions of read/write 81441480Smckusick * for things like reading disk labels and writing core dumps. The 81541480Smckusick * routine scsigo should be used for normal data transfers, NOT these 81641480Smckusick * routines. 81741480Smckusick */ 81841480Smckusick int 81941480Smckusick scsi_tt_read(ctlr, slave, unit, buf, len, blk, bshift) 82041480Smckusick int ctlr, slave, unit; 82141480Smckusick u_char *buf; 82241480Smckusick u_int len; 82341480Smckusick daddr_t blk; 82441480Smckusick int bshift; 82541480Smckusick { 82641480Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 82741480Smckusick struct scsi_cdb10 cdb; 82841480Smckusick int stat; 82941480Smckusick int old_wait = scsi_data_wait; 83041480Smckusick 83141480Smckusick scsi_data_wait = 300000; 83241480Smckusick bzero(&cdb, sizeof(cdb)); 83341480Smckusick cdb.cmd = CMD_READ_EXT; 83441480Smckusick cdb.lun = unit; 83541480Smckusick blk >>= bshift; 83641480Smckusick cdb.lbah = blk >> 24; 83741480Smckusick cdb.lbahm = blk >> 16; 83841480Smckusick cdb.lbalm = blk >> 8; 83941480Smckusick cdb.lbal = blk; 84041480Smckusick cdb.lenh = len >> (8 + DEV_BSHIFT + bshift); 84141480Smckusick cdb.lenl = len >> (DEV_BSHIFT + bshift); 84241480Smckusick stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE); 84341480Smckusick scsi_data_wait = old_wait; 84441480Smckusick return (stat); 84541480Smckusick } 84641480Smckusick 84741480Smckusick int 84841480Smckusick scsi_tt_write(ctlr, slave, unit, buf, len, blk, bshift) 84941480Smckusick int ctlr, slave, unit; 85041480Smckusick u_char *buf; 85141480Smckusick u_int len; 85241480Smckusick daddr_t blk; 85341480Smckusick int bshift; 85441480Smckusick { 85541480Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 85641480Smckusick struct scsi_cdb10 cdb; 85741480Smckusick int stat; 85841480Smckusick int old_wait = scsi_data_wait; 85941480Smckusick 86041480Smckusick scsi_data_wait = 300000; 86141480Smckusick 86241480Smckusick bzero(&cdb, sizeof(cdb)); 86341480Smckusick cdb.cmd = CMD_WRITE_EXT; 86441480Smckusick cdb.lun = unit; 86541480Smckusick blk >>= bshift; 86641480Smckusick cdb.lbah = blk >> 24; 86741480Smckusick cdb.lbahm = blk >> 16; 86841480Smckusick cdb.lbalm = blk >> 8; 86941480Smckusick cdb.lbal = blk; 87041480Smckusick cdb.lenh = len >> (8 + DEV_BSHIFT + bshift); 87141480Smckusick cdb.lenl = len >> (DEV_BSHIFT + bshift); 87241480Smckusick stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_OUT_PHASE); 87341480Smckusick scsi_data_wait = old_wait; 87441480Smckusick return (stat); 87541480Smckusick } 87641480Smckusick 87741480Smckusick int 87841480Smckusick scsireq(dq) 87941480Smckusick register struct devqueue *dq; 88041480Smckusick { 88141480Smckusick register struct devqueue *hq; 88241480Smckusick 88341480Smckusick hq = &scsi_softc[dq->dq_ctlr].sc_sq; 88441480Smckusick insque(dq, hq->dq_back); 88541480Smckusick if (dq->dq_back == hq) 88641480Smckusick return(1); 88741480Smckusick return(0); 88841480Smckusick } 88941480Smckusick 89041480Smckusick int 89141480Smckusick scsiustart(unit) 89241480Smckusick int unit; 89341480Smckusick { 89441480Smckusick register struct scsi_softc *hs = &scsi_softc[unit]; 89541480Smckusick 89641480Smckusick hs->sc_dq.dq_ctlr = DMA0 | DMA1; 897*53930Shibler hs->sc_flags |= SCSI_HAVEDMA; 89841480Smckusick if (dmareq(&hs->sc_dq)) 89941480Smckusick return(1); 90041480Smckusick return(0); 90141480Smckusick } 90241480Smckusick 90341480Smckusick void 90441480Smckusick scsistart(unit) 90541480Smckusick int unit; 90641480Smckusick { 90741480Smckusick register struct devqueue *dq; 90841480Smckusick 90941480Smckusick dq = scsi_softc[unit].sc_sq.dq_forw; 91041480Smckusick (dq->dq_driver->d_go)(dq->dq_unit); 91141480Smckusick } 91241480Smckusick 91341480Smckusick int 91441480Smckusick scsigo(ctlr, slave, unit, bp, cdb, pad) 91541480Smckusick int ctlr, slave, unit; 91641480Smckusick struct buf *bp; 91741480Smckusick struct scsi_fmt_cdb *cdb; 91841480Smckusick int pad; 91941480Smckusick { 92041480Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 92141480Smckusick volatile register struct scsidevice *hd = 92241480Smckusick (struct scsidevice *)hs->sc_hc->hp_addr; 92341480Smckusick int i, dmaflags; 92441480Smckusick u_char phase, ints, cmd; 92541480Smckusick 92641480Smckusick cdb->cdb[1] |= unit << 5; 92741480Smckusick 92841480Smckusick /* select the SCSI bus (it's an error if bus isn't free) */ 92941480Smckusick if (issue_select(hd, slave, hs->sc_scsi_addr) || wait_for_select(hd)) { 930*53930Shibler if (hs->sc_flags & SCSI_HAVEDMA) { 931*53930Shibler hs->sc_flags &=~ SCSI_HAVEDMA; 932*53930Shibler dmafree(&hs->sc_dq); 933*53930Shibler } 93441480Smckusick return (1); 93541480Smckusick } 93641480Smckusick /* 93741480Smckusick * Wait for a phase change (or error) then let the device 93841480Smckusick * sequence us through command phase (we may have to take 93941480Smckusick * a msg in/out before doing the command). If the disk has 94041480Smckusick * to do a seek, it may be a long time until we get a change 94141480Smckusick * to data phase so, in the absense of an explicit phase 94241480Smckusick * change, we assume data phase will be coming up and tell 94341480Smckusick * the SPC to start a transfer whenever it does. We'll get 94441480Smckusick * a service required interrupt later if this assumption is 94541480Smckusick * wrong. Otherwise we'll get a service required int when 94641480Smckusick * the transfer changes to status phase. 94741480Smckusick */ 94841480Smckusick phase = CMD_PHASE; 94941480Smckusick while (1) { 95041480Smckusick register int wait = scsi_cmd_wait; 95141480Smckusick 95241480Smckusick switch (phase) { 95341480Smckusick 95441480Smckusick case CMD_PHASE: 95541480Smckusick if (ixfer_start(hd, cdb->len, phase, wait)) 95641480Smckusick if (ixfer_out(hd, cdb->len, cdb->cdb)) 95741480Smckusick goto abort; 95841480Smckusick break; 95941480Smckusick 96041480Smckusick case MESG_IN_PHASE: 96141480Smckusick if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait)|| 96241480Smckusick !(hd->scsi_ssts & SSTS_DREG_EMPTY)) { 96341480Smckusick ixfer_in(hd, sizeof(hs->sc_msg), hs->sc_msg); 96441480Smckusick hd->scsi_scmd = SCMD_RST_ACK; 96541480Smckusick } 96641480Smckusick phase = BUS_FREE_PHASE; 96741480Smckusick break; 96841480Smckusick 96941480Smckusick case DATA_IN_PHASE: 97041480Smckusick case DATA_OUT_PHASE: 97141480Smckusick goto out; 97241480Smckusick 97341480Smckusick default: 97441480Smckusick printf("scsi%d: unexpected phase %d in go from %d\n", 97541480Smckusick hs->sc_hc->hp_unit, phase, slave); 97641480Smckusick goto abort; 97741480Smckusick } 97841480Smckusick while ((ints = hd->scsi_ints) == 0) { 97941480Smckusick if (--wait < 0) { 98041480Smckusick HIST(sgo_wait, wait) 98141480Smckusick goto abort; 98241480Smckusick } 98341480Smckusick DELAY(1); 98441480Smckusick } 98541480Smckusick HIST(sgo_wait, wait) 98641480Smckusick hd->scsi_ints = ints; 98741480Smckusick if (ints & INTS_SRV_REQ) 98841480Smckusick phase = hd->scsi_psns & PHASE; 98941480Smckusick else if (ints & INTS_CMD_DONE) 99041480Smckusick goto out; 99141480Smckusick else { 99241480Smckusick scsierror(hs, hd, ints); 99341480Smckusick goto abort; 99441480Smckusick } 99541480Smckusick } 99641480Smckusick out: 99741480Smckusick /* 99841480Smckusick * Reset the card dma logic, setup the dma channel then 99941480Smckusick * get the dio part of the card set for a dma xfer. 100041480Smckusick */ 100141480Smckusick hd->scsi_hconf = 0; 100245514Smckusick cmd = CSR_IE; 100341480Smckusick dmaflags = DMAGO_NOINT; 100445514Smckusick if (scsi_pridma) 100545514Smckusick dmaflags |= DMAGO_PRI; 100641480Smckusick if (bp->b_flags & B_READ) 100741480Smckusick dmaflags |= DMAGO_READ; 100841480Smckusick if ((hs->sc_flags & SCSI_DMA32) && 100941480Smckusick ((int)bp->b_un.b_addr & 3) == 0 && (bp->b_bcount & 3) == 0) { 101041480Smckusick cmd |= CSR_DMA32; 101141480Smckusick dmaflags |= DMAGO_LWORD; 101241480Smckusick } else 101341480Smckusick dmaflags |= DMAGO_WORD; 101441480Smckusick dmago(hs->sc_dq.dq_ctlr, bp->b_un.b_addr, bp->b_bcount, dmaflags); 101541480Smckusick 101641480Smckusick if (bp->b_flags & B_READ) { 101741480Smckusick cmd |= CSR_DMAIN; 101841480Smckusick phase = DATA_IN_PHASE; 101941480Smckusick } else 102041480Smckusick phase = DATA_OUT_PHASE; 102145514Smckusick /* 102245514Smckusick * DMA enable bits must be set after size and direction bits. 102345514Smckusick */ 102441480Smckusick hd->scsi_csr = cmd; 102545514Smckusick hd->scsi_csr |= (CSR_DE0 << hs->sc_dq.dq_ctlr); 102641480Smckusick /* 102741480Smckusick * Setup the SPC for the transfer. We don't want to take 102841480Smckusick * first a command complete then a service required interrupt 102941480Smckusick * at the end of the transfer so we try to disable the cmd 103041480Smckusick * complete by setting the transfer counter to more bytes 103141480Smckusick * than we expect. (XXX - This strategy may have to be 103241480Smckusick * modified to deal with devices that return variable length 103341480Smckusick * blocks, e.g., some tape drives.) 103441480Smckusick */ 103541480Smckusick cmd = SCMD_XFR; 103641480Smckusick i = (unsigned)bp->b_bcount; 103741480Smckusick if (pad) { 103841480Smckusick cmd |= SCMD_PAD; 103941480Smckusick /* 104041480Smckusick * XXX - If we don't do this, the last 2 or 4 bytes 104141480Smckusick * (depending on word/lword DMA) of a read get trashed. 104241480Smckusick * It looks like it is necessary for the DMA to complete 104341480Smckusick * before the SPC goes into "pad mode"??? Note: if we 104441480Smckusick * also do this on a write, the request never completes. 104541480Smckusick */ 104641480Smckusick if (bp->b_flags & B_READ) 104741480Smckusick i += 2; 104841480Smckusick #ifdef DEBUG 104941480Smckusick hs->sc_flags |= SCSI_PAD; 105041480Smckusick if (i & 1) 105141480Smckusick printf("scsi%d: odd byte count: %d bytes @ %d\n", 105241480Smckusick ctlr, i, bp->b_cylin); 105341480Smckusick #endif 105441480Smckusick } else 105541480Smckusick i += 4; 105641480Smckusick hd->scsi_tch = i >> 16; 105741480Smckusick hd->scsi_tcm = i >> 8; 105841480Smckusick hd->scsi_tcl = i; 105941480Smckusick hd->scsi_pctl = phase; 106041480Smckusick hd->scsi_tmod = 0; 106141480Smckusick hd->scsi_scmd = cmd; 106241480Smckusick hs->sc_flags |= SCSI_IO; 106341480Smckusick return (0); 106441480Smckusick abort: 106541480Smckusick scsiabort(hs, hd, "go"); 1066*53930Shibler hs->sc_flags &=~ SCSI_HAVEDMA; 106741480Smckusick dmafree(&hs->sc_dq); 106841480Smckusick return (1); 106941480Smckusick } 107041480Smckusick 107141480Smckusick void 107241480Smckusick scsidone(unit) 107341480Smckusick register int unit; 107441480Smckusick { 107541480Smckusick volatile register struct scsidevice *hd = 107641480Smckusick (struct scsidevice *)scsi_softc[unit].sc_hc->hp_addr; 107741480Smckusick 107845514Smckusick #ifdef DEBUG 107945514Smckusick if (scsi_debug) 108045514Smckusick printf("scsi%d: done called!\n"); 108145514Smckusick #endif 108241480Smckusick /* dma operation is done -- turn off card dma */ 108341480Smckusick hd->scsi_csr &=~ (CSR_DE1|CSR_DE0); 108441480Smckusick } 108541480Smckusick 108641480Smckusick int 108741480Smckusick scsiintr(unit) 108841480Smckusick register int unit; 108941480Smckusick { 109041480Smckusick register struct scsi_softc *hs = &scsi_softc[unit]; 109141480Smckusick volatile register struct scsidevice *hd = 109241480Smckusick (struct scsidevice *)hs->sc_hc->hp_addr; 109341480Smckusick register u_char ints; 109441480Smckusick register struct devqueue *dq; 109541480Smckusick 109641480Smckusick if ((hd->scsi_csr & (CSR_IE|CSR_IR)) != (CSR_IE|CSR_IR)) 109741480Smckusick return (0); 109841480Smckusick 109941480Smckusick ints = hd->scsi_ints; 110041480Smckusick if ((ints & INTS_SRV_REQ) && (hs->sc_flags & SCSI_IO)) { 110141480Smckusick /* 110241480Smckusick * this should be the normal i/o completion case. 110341480Smckusick * get the status & cmd complete msg then let the 110441480Smckusick * device driver look at what happened. 110541480Smckusick */ 110641480Smckusick #ifdef DEBUG 110741480Smckusick int len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | 110841480Smckusick hd->scsi_tcl; 110941480Smckusick if (!(hs->sc_flags & SCSI_PAD)) 111041480Smckusick len -= 4; 111141480Smckusick hs->sc_flags &=~ SCSI_PAD; 111241480Smckusick #endif 111341480Smckusick dq = hs->sc_sq.dq_forw; 111446285Smckusick finishxfer(hs, hd, dq->dq_slave); 1115*53930Shibler hs->sc_flags &=~ (SCSI_IO|SCSI_HAVEDMA); 111641480Smckusick dmafree(&hs->sc_dq); 111741480Smckusick (dq->dq_driver->d_intr)(dq->dq_unit, hs->sc_stat[0]); 111841480Smckusick } else { 111941480Smckusick /* Something unexpected happened -- deal with it. */ 112041480Smckusick hd->scsi_ints = ints; 112141480Smckusick hd->scsi_csr = 0; 112241480Smckusick scsierror(hs, hd, ints); 112341480Smckusick scsiabort(hs, hd, "intr"); 112441480Smckusick if (hs->sc_flags & SCSI_IO) { 1125*53930Shibler hs->sc_flags &=~ (SCSI_IO|SCSI_HAVEDMA); 112641480Smckusick dmafree(&hs->sc_dq); 112741480Smckusick dq = hs->sc_sq.dq_forw; 112841480Smckusick (dq->dq_driver->d_intr)(dq->dq_unit, -1); 112941480Smckusick } 113041480Smckusick } 113141480Smckusick return(1); 113241480Smckusick } 113341480Smckusick 113441480Smckusick void 113541480Smckusick scsifree(dq) 113641480Smckusick register struct devqueue *dq; 113741480Smckusick { 113841480Smckusick register struct devqueue *hq; 113941480Smckusick 114041480Smckusick hq = &scsi_softc[dq->dq_ctlr].sc_sq; 114141480Smckusick remque(dq); 114241480Smckusick if ((dq = hq->dq_forw) != hq) 114341480Smckusick (dq->dq_driver->d_start)(dq->dq_unit); 114441480Smckusick } 114546285Smckusick 114646285Smckusick /* 114746285Smckusick * (XXX) The following routine is needed for the SCSI tape driver 114846285Smckusick * to read odd-size records. 114946285Smckusick */ 115046285Smckusick 115146285Smckusick #include "st.h" 115246285Smckusick #if NST > 0 115346285Smckusick int 115446285Smckusick scsi_tt_oddio(ctlr, slave, unit, buf, len, b_flags, freedma) 115546285Smckusick int ctlr, slave, unit, b_flags; 115646285Smckusick u_char *buf; 115746285Smckusick u_int len; 115846285Smckusick { 115946285Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 116046285Smckusick struct scsi_cdb6 cdb; 116146285Smckusick u_char iphase; 116246285Smckusick int stat; 116346285Smckusick 1164*53930Shibler #ifdef DEBUG 1165*53930Shibler if (freedma && (hs->sc_flags & SCSI_HAVEDMA) == 0 || 1166*53930Shibler !freedma && (hs->sc_flags & SCSI_HAVEDMA)) 1167*53930Shibler printf("oddio: freedma (%d) inconsistency (flags=%x)\n", 1168*53930Shibler freedma, hs->sc_flags); 1169*53930Shibler #endif 117046285Smckusick /* 117146285Smckusick * First free any DMA channel that was allocated. 117246285Smckusick * We can't use DMA to do this transfer. 117346285Smckusick */ 1174*53930Shibler if (freedma) { 1175*53930Shibler hs->sc_flags &=~ SCSI_HAVEDMA; 117646285Smckusick dmafree(hs->sc_dq); 1177*53930Shibler } 117846285Smckusick /* 117946285Smckusick * Initialize command block 118046285Smckusick */ 118146285Smckusick bzero(&cdb, sizeof(cdb)); 118246285Smckusick cdb.lun = unit; 118346285Smckusick cdb.lbam = (len >> 16) & 0xff; 118446285Smckusick cdb.lbal = (len >> 8) & 0xff; 118546285Smckusick cdb.len = len & 0xff; 118646285Smckusick if (buf == 0) { 118746285Smckusick cdb.cmd = CMD_SPACE; 118846285Smckusick cdb.lun |= 0x00; 118946285Smckusick len = 0; 119046285Smckusick iphase = MESG_IN_PHASE; 119146285Smckusick } else if (b_flags & B_READ) { 119246285Smckusick cdb.cmd = CMD_READ; 119346285Smckusick iphase = DATA_IN_PHASE; 119446285Smckusick } else { 119546285Smckusick cdb.cmd = CMD_WRITE; 119646285Smckusick iphase = DATA_OUT_PHASE; 119746285Smckusick } 119846285Smckusick /* 119946285Smckusick * Perform command (with very long delays) 120046285Smckusick */ 120146285Smckusick scsi_delay(30000000); 120246285Smckusick stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, iphase); 120346285Smckusick scsi_delay(0); 120446285Smckusick return (stat); 120546285Smckusick } 120641480Smckusick #endif 120746285Smckusick #endif 1208