141480Smckusick /* 241480Smckusick * Copyright (c) 1990 The Regents of the University of California. 341480Smckusick * All rights reserved. 441480Smckusick * 541480Smckusick * This code is derived from software contributed to Berkeley by 641480Smckusick * Van Jacobson of Lawrence Berkeley Laboratory. 741480Smckusick * 841480Smckusick * %sccs.include.redist.c% 941480Smckusick * 10*46285Smckusick * @(#)scsi.c 7.4 (Berkeley) 02/05/91 1141480Smckusick */ 1241480Smckusick 1341480Smckusick /* 1441480Smckusick * HP9000/3xx 98658 SCSI host adaptor driver. 1541480Smckusick */ 1641480Smckusick #include "scsi.h" 1741480Smckusick #if NSCSI > 0 1841480Smckusick 1941480Smckusick #ifndef lint 20*46285Smckusick static char rcsid[] = "$Header: scsi.c,v 1.4 91/01/17 12:50:18 mike Exp $"; 2141480Smckusick #endif 2241480Smckusick 2345788Sbostic #include "sys/param.h" 2445788Sbostic #include "sys/systm.h" 2545788Sbostic #include "sys/buf.h" 2641480Smckusick #include "device.h" 2745788Sbostic 2841480Smckusick #include "scsivar.h" 2941480Smckusick #include "scsireg.h" 3041480Smckusick #include "dmavar.h" 3141480Smckusick 3245788Sbostic #include "../include/cpu.h" 3345788Sbostic #include "../hp300/isr.h" 3441480Smckusick 35*46285Smckusick /* 36*46285Smckusick * SCSI delays 37*46285Smckusick * In u-seconds, primarily for state changes on the SPC. 38*46285Smckusick */ 39*46285Smckusick #define SCSI_CMD_WAIT 1000 /* wait per step of 'immediate' cmds */ 40*46285Smckusick #define SCSI_DATA_WAIT 1000 /* wait per data in/out step */ 41*46285Smckusick #define SCSI_INIT_WAIT 50000 /* wait per step (both) during init */ 42*46285Smckusick 4341480Smckusick extern void isrlink(); 4441480Smckusick extern void printf(); 4541480Smckusick extern void _insque(); 4641480Smckusick extern void _remque(); 4741480Smckusick extern void bzero(); 4841480Smckusick 4941480Smckusick int scsiinit(), scsigo(), scsiintr(), scsixfer(); 5041480Smckusick void scsistart(), scsidone(), scsifree(), scsireset(); 5141480Smckusick struct driver scsidriver = { 5241480Smckusick scsiinit, "scsi", (int (*)())scsistart, scsigo, scsiintr, 5341480Smckusick (int (*)())scsidone, 5441480Smckusick }; 5541480Smckusick 5641480Smckusick struct scsi_softc scsi_softc[NSCSI]; 5741480Smckusick struct isr scsi_isr[NSCSI]; 5841480Smckusick 59*46285Smckusick int scsi_cmd_wait = SCSI_CMD_WAIT; 60*46285Smckusick int scsi_data_wait = SCSI_DATA_WAIT; 61*46285Smckusick int scsi_init_wait = SCSI_INIT_WAIT; 62*46285Smckusick 6341480Smckusick int scsi_nosync = 1; /* inhibit sync xfers if 1 */ 6445514Smckusick int scsi_pridma = 0; /* use "priority" dma */ 6541480Smckusick 6641480Smckusick #ifdef DEBUG 6741480Smckusick int scsi_debug = 0; 6841480Smckusick #define WAITHIST 6941480Smckusick #endif 7041480Smckusick 7141480Smckusick #ifdef WAITHIST 7245514Smckusick #define MAXWAIT 1022 7341480Smckusick u_int ixstart_wait[MAXWAIT+2]; 7441480Smckusick u_int ixin_wait[MAXWAIT+2]; 7541480Smckusick u_int ixout_wait[MAXWAIT+2]; 7641480Smckusick u_int mxin_wait[MAXWAIT+2]; 77*46285Smckusick u_int mxin2_wait[MAXWAIT+2]; 7841480Smckusick u_int cxin_wait[MAXWAIT+2]; 7941480Smckusick u_int fxfr_wait[MAXWAIT+2]; 8041480Smckusick u_int sgo_wait[MAXWAIT+2]; 8141480Smckusick #define HIST(h,w) (++h[((w)>MAXWAIT? MAXWAIT : ((w) < 0 ? -1 : (w))) + 1]); 8241480Smckusick #else 8341480Smckusick #define HIST(h,w) 8441480Smckusick #endif 8541480Smckusick 8641480Smckusick #define b_cylin b_resid 8741480Smckusick 8841480Smckusick static void 8941480Smckusick scsiabort(hs, hd, where) 9041480Smckusick register struct scsi_softc *hs; 9141480Smckusick volatile register struct scsidevice *hd; 9241480Smckusick char *where; 9341480Smckusick { 9441480Smckusick int len; 9541480Smckusick u_char junk; 9641480Smckusick 9741480Smckusick printf("scsi%d: abort from %s: phase=0x%x, ssts=0x%x, ints=0x%x\n", 9841480Smckusick hs->sc_hc->hp_unit, where, hd->scsi_psns, hd->scsi_ssts, 9941480Smckusick hd->scsi_ints); 10041480Smckusick 10141480Smckusick hd->scsi_ints = hd->scsi_ints; 10241480Smckusick hd->scsi_csr = 0; 10341480Smckusick if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0) 10441480Smckusick /* no longer connected to scsi target */ 10541480Smckusick return; 10641480Smckusick 10741480Smckusick /* get the number of bytes remaining in current xfer + fudge */ 10841480Smckusick len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl; 10941480Smckusick 11041480Smckusick /* for that many bus cycles, try to send an abort msg */ 11141480Smckusick for (len += 1024; (hd->scsi_ssts & SSTS_INITIATOR) && --len >= 0; ) { 11241480Smckusick hd->scsi_scmd = SCMD_SET_ATN; 11341480Smckusick while ((hd->scsi_psns & PSNS_REQ) == 0) { 11441480Smckusick if (! (hd->scsi_ssts & SSTS_INITIATOR)) 11541480Smckusick goto out; 11641480Smckusick DELAY(1); 11741480Smckusick } 11841480Smckusick if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE) 11941480Smckusick hd->scsi_scmd = SCMD_RST_ATN; 12041480Smckusick hd->scsi_pctl = hd->scsi_psns & PHASE; 12141480Smckusick if (hd->scsi_psns & PHASE_IO) { 12241480Smckusick /* one of the input phases - read & discard a byte */ 12341480Smckusick hd->scsi_scmd = SCMD_SET_ACK; 12441480Smckusick if (hd->scsi_tmod == 0) 12541480Smckusick while (hd->scsi_psns & PSNS_REQ) 12641480Smckusick DELAY(1); 12741480Smckusick junk = hd->scsi_temp; 12841480Smckusick } else { 12941480Smckusick /* one of the output phases - send an abort msg */ 13041480Smckusick hd->scsi_temp = MSG_ABORT; 13141480Smckusick hd->scsi_scmd = SCMD_SET_ACK; 13241480Smckusick if (hd->scsi_tmod == 0) 13341480Smckusick while (hd->scsi_psns & PSNS_REQ) 13441480Smckusick DELAY(1); 13541480Smckusick } 13641480Smckusick hd->scsi_scmd = SCMD_RST_ACK; 13741480Smckusick } 13841480Smckusick out: 13941480Smckusick /* 14041480Smckusick * Either the abort was successful & the bus is disconnected or 14141480Smckusick * the device didn't listen. If the latter, announce the problem. 14241480Smckusick * Either way, reset the card & the SPC. 14341480Smckusick */ 14441480Smckusick if (len < 0 && hs) 14541480Smckusick printf("scsi%d: abort failed. phase=0x%x, ssts=0x%x\n", 14641480Smckusick hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts); 14741480Smckusick 14841480Smckusick if (! ((junk = hd->scsi_ints) & INTS_RESEL)) { 14941480Smckusick hd->scsi_sctl |= SCTL_CTRLRST; 15041480Smckusick DELAY(1); 15141480Smckusick hd->scsi_sctl &=~ SCTL_CTRLRST; 15241480Smckusick hd->scsi_hconf = 0; 15341480Smckusick hd->scsi_ints = hd->scsi_ints; 15441480Smckusick } 15541480Smckusick } 15641480Smckusick 157*46285Smckusick /* 158*46285Smckusick * XXX Set/reset long delays. 159*46285Smckusick * 160*46285Smckusick * if delay == 0, reset default delays 161*46285Smckusick * if delay < 0, set both delays to default long initialization values 162*46285Smckusick * if delay > 0, set both delays to this value 163*46285Smckusick * 164*46285Smckusick * Used when a devices is expected to respond slowly (e.g. during 165*46285Smckusick * initialization). 166*46285Smckusick */ 167*46285Smckusick void 168*46285Smckusick scsi_delay(delay) 169*46285Smckusick int delay; 170*46285Smckusick { 171*46285Smckusick static int saved_cmd_wait, saved_data_wait; 172*46285Smckusick 173*46285Smckusick if (delay) { 174*46285Smckusick saved_cmd_wait = scsi_cmd_wait; 175*46285Smckusick saved_data_wait = scsi_data_wait; 176*46285Smckusick if (delay > 0) 177*46285Smckusick scsi_cmd_wait = scsi_data_wait = delay; 178*46285Smckusick else 179*46285Smckusick scsi_cmd_wait = scsi_data_wait = scsi_init_wait; 180*46285Smckusick } else { 181*46285Smckusick scsi_cmd_wait = saved_cmd_wait; 182*46285Smckusick scsi_data_wait = saved_data_wait; 183*46285Smckusick } 184*46285Smckusick } 185*46285Smckusick 18641480Smckusick int 18741480Smckusick scsiinit(hc) 18841480Smckusick register struct hp_ctlr *hc; 18941480Smckusick { 19041480Smckusick register struct scsi_softc *hs = &scsi_softc[hc->hp_unit]; 19141480Smckusick register struct scsidevice *hd = (struct scsidevice *)hc->hp_addr; 19241480Smckusick 19341480Smckusick if ((hd->scsi_id & ID_MASK) != SCSI_ID) 19441480Smckusick return(0); 19541480Smckusick hc->hp_ipl = SCSI_IPL(hd->scsi_csr); 19641480Smckusick hs->sc_hc = hc; 19741480Smckusick hs->sc_dq.dq_unit = hc->hp_unit; 19841480Smckusick hs->sc_dq.dq_driver = &scsidriver; 19941480Smckusick hs->sc_sq.dq_forw = hs->sc_sq.dq_back = &hs->sc_sq; 20041480Smckusick scsi_isr[hc->hp_unit].isr_intr = scsiintr; 20141480Smckusick scsi_isr[hc->hp_unit].isr_ipl = hc->hp_ipl; 20241480Smckusick scsi_isr[hc->hp_unit].isr_arg = hc->hp_unit; 20341480Smckusick isrlink(&scsi_isr[hc->hp_unit]); 20441480Smckusick scsireset(hc->hp_unit); 20541480Smckusick return(1); 20641480Smckusick } 20741480Smckusick 20841480Smckusick void 20941480Smckusick scsireset(unit) 21041480Smckusick register int unit; 21141480Smckusick { 21241480Smckusick register struct scsi_softc *hs = &scsi_softc[unit]; 21341480Smckusick volatile register struct scsidevice *hd = 21441480Smckusick (struct scsidevice *)hs->sc_hc->hp_addr; 21541480Smckusick u_int i; 21641480Smckusick 21741480Smckusick if (hs->sc_flags & SCSI_ALIVE) 21841480Smckusick scsiabort(hs, hd, "reset"); 21941480Smckusick 22041480Smckusick printf("scsi%d: ", unit); 22141480Smckusick 22241480Smckusick hd->scsi_id = 0xFF; 22341480Smckusick DELAY(100); 22441480Smckusick /* 22541480Smckusick * Disable interrupts then reset the FUJI chip. 22641480Smckusick */ 22741480Smckusick hd->scsi_csr = 0; 22841480Smckusick hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST; 22941480Smckusick hd->scsi_scmd = 0; 23041480Smckusick hd->scsi_tmod = 0; 23141480Smckusick hd->scsi_pctl = 0; 23241480Smckusick hd->scsi_temp = 0; 23341480Smckusick hd->scsi_tch = 0; 23441480Smckusick hd->scsi_tcm = 0; 23541480Smckusick hd->scsi_tcl = 0; 23641480Smckusick hd->scsi_ints = 0; 23741480Smckusick 23841480Smckusick if ((hd->scsi_id & ID_WORD_DMA) == 0) { 23941480Smckusick hs->sc_flags |= SCSI_DMA32; 24041480Smckusick printf("32 bit dma, "); 24141480Smckusick } 24241480Smckusick 24341480Smckusick /* Determine Max Synchronous Transfer Rate */ 24441480Smckusick if (scsi_nosync) 24541480Smckusick i = 3; 24641480Smckusick else 24741480Smckusick i = SCSI_SYNC_XFER(hd->scsi_hconf); 24841480Smckusick switch (i) { 24941480Smckusick case 0: 25041480Smckusick hs->sc_sync = TMOD_SYNC | 0x3e; /* 250 nsecs */ 25141480Smckusick printf("250ns sync"); 25241480Smckusick break; 25341480Smckusick case 1: 25441480Smckusick hs->sc_sync = TMOD_SYNC | 0x5e; /* 375 nsecs */ 25541480Smckusick printf("375ns sync"); 25641480Smckusick break; 25741480Smckusick case 2: 25841480Smckusick hs->sc_sync = TMOD_SYNC | 0x7d; /* 500 nsecs */ 25941480Smckusick printf("500ns sync"); 26041480Smckusick break; 26141480Smckusick case 3: 26241480Smckusick hs->sc_sync = 0; 26341480Smckusick printf("async"); 26441480Smckusick break; 26541480Smckusick } 26641480Smckusick 26741480Smckusick /* 26841480Smckusick * Configure the FUJI chip with its SCSI address, all 26941480Smckusick * interrupts enabled & appropriate parity. 27041480Smckusick */ 27141480Smckusick i = (~hd->scsi_hconf) & 0x7; 27241480Smckusick hs->sc_scsi_addr = 1 << i; 27341480Smckusick hd->scsi_bdid = i; 27441480Smckusick if (hd->scsi_hconf & HCONF_PARITY) 27541480Smckusick hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB | 27641480Smckusick SCTL_SEL_ENAB | SCTL_RESEL_ENAB | 27741480Smckusick SCTL_INTR_ENAB | SCTL_PARITY_ENAB; 27841480Smckusick else { 27941480Smckusick hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB | 28041480Smckusick SCTL_SEL_ENAB | SCTL_RESEL_ENAB | 28141480Smckusick SCTL_INTR_ENAB; 28241480Smckusick printf(", no parity"); 28341480Smckusick } 28441480Smckusick hd->scsi_sctl &=~ SCTL_DISABLE; 28541480Smckusick 28641480Smckusick printf(", scsi id %d\n", i); 28741480Smckusick hs->sc_flags |= SCSI_ALIVE; 28841480Smckusick } 28941480Smckusick 29041480Smckusick static void 29141480Smckusick scsierror(hs, hd, ints) 29241480Smckusick register struct scsi_softc *hs; 29341480Smckusick volatile register struct scsidevice *hd; 29441480Smckusick u_char ints; 29541480Smckusick { 29641480Smckusick int unit = hs->sc_hc->hp_unit; 29741480Smckusick char *sep = ""; 29841480Smckusick 29941480Smckusick printf("scsi%d: ", unit); 30041480Smckusick if (ints & INTS_RST) { 30141480Smckusick DELAY(100); 30241480Smckusick if (hd->scsi_hconf & HCONF_SD) 30341480Smckusick printf("spurious RST interrupt"); 30441480Smckusick else 30541480Smckusick printf("hardware error - check fuse"); 30641480Smckusick sep = ", "; 30741480Smckusick } 30841480Smckusick if ((ints & INTS_HARD_ERR) || hd->scsi_serr) { 30941480Smckusick if (hd->scsi_serr & SERR_SCSI_PAR) { 31041480Smckusick printf("%sparity err", sep); 31141480Smckusick sep = ", "; 31241480Smckusick } 31341480Smckusick if (hd->scsi_serr & SERR_SPC_PAR) { 31441480Smckusick printf("%sSPC parity err", sep); 31541480Smckusick sep = ", "; 31641480Smckusick } 31741480Smckusick if (hd->scsi_serr & SERR_TC_PAR) { 31841480Smckusick printf("%sTC parity err", sep); 31941480Smckusick sep = ", "; 32041480Smckusick } 32141480Smckusick if (hd->scsi_serr & SERR_PHASE_ERR) { 32241480Smckusick printf("%sphase err", sep); 32341480Smckusick sep = ", "; 32441480Smckusick } 32541480Smckusick if (hd->scsi_serr & SERR_SHORT_XFR) { 32641480Smckusick printf("%ssync short transfer err", sep); 32741480Smckusick sep = ", "; 32841480Smckusick } 32941480Smckusick if (hd->scsi_serr & SERR_OFFSET) { 33041480Smckusick printf("%ssync offset error", sep); 33141480Smckusick sep = ", "; 33241480Smckusick } 33341480Smckusick } 33441480Smckusick if (ints & INTS_TIMEOUT) 33541480Smckusick printf("%sSPC select timeout error", sep); 33641480Smckusick if (ints & INTS_SRV_REQ) 33741480Smckusick printf("%sspurious SRV_REQ interrupt", sep); 33841480Smckusick if (ints & INTS_CMD_DONE) 33941480Smckusick printf("%sspurious CMD_DONE interrupt", sep); 34041480Smckusick if (ints & INTS_DISCON) 34141480Smckusick printf("%sspurious disconnect interrupt", sep); 34241480Smckusick if (ints & INTS_RESEL) 34341480Smckusick printf("%sspurious reselect interrupt", sep); 34441480Smckusick if (ints & INTS_SEL) 34541480Smckusick printf("%sspurious select interrupt", sep); 34641480Smckusick printf("\n"); 34741480Smckusick } 34841480Smckusick 34941480Smckusick static int 35041480Smckusick issue_select(hd, target, our_addr) 35141480Smckusick volatile register struct scsidevice *hd; 35241480Smckusick u_char target, our_addr; 35341480Smckusick { 35441480Smckusick if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY)) 35541480Smckusick return (1); 35641480Smckusick 35741480Smckusick if (hd->scsi_ints & INTS_DISCON) 35841480Smckusick hd->scsi_ints = INTS_DISCON; 35941480Smckusick 36041480Smckusick hd->scsi_pctl = 0; 36141480Smckusick hd->scsi_temp = (1 << target) | our_addr; 36241480Smckusick /* select timeout is hardcoded to 2ms */ 36341480Smckusick hd->scsi_tch = 0; 36441480Smckusick hd->scsi_tcm = 32; 36541480Smckusick hd->scsi_tcl = 4; 36641480Smckusick 36741480Smckusick hd->scsi_scmd = SCMD_SELECT; 36841480Smckusick return (0); 36941480Smckusick } 37041480Smckusick 37141480Smckusick static int 37241480Smckusick wait_for_select(hd) 37341480Smckusick volatile register struct scsidevice *hd; 37441480Smckusick { 37541480Smckusick u_char ints; 37641480Smckusick 37741480Smckusick while ((ints = hd->scsi_ints) == 0) 37841480Smckusick DELAY(1); 37941480Smckusick hd->scsi_ints = ints; 38041480Smckusick return (!(hd->scsi_ssts & SSTS_INITIATOR)); 38141480Smckusick } 38241480Smckusick 38341480Smckusick static int 38441480Smckusick ixfer_start(hd, len, phase, wait) 38541480Smckusick volatile register struct scsidevice *hd; 38641480Smckusick int len; 38741480Smckusick u_char phase; 38841480Smckusick register int wait; 38941480Smckusick { 39041480Smckusick 39141480Smckusick hd->scsi_tch = len >> 16; 39241480Smckusick hd->scsi_tcm = len >> 8; 39341480Smckusick hd->scsi_tcl = len; 39441480Smckusick hd->scsi_pctl = phase; 39541480Smckusick hd->scsi_tmod = 0; /*XXX*/ 39641480Smckusick hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR; 39741480Smckusick 39841480Smckusick /* wait for xfer to start or svc_req interrupt */ 39941480Smckusick while ((hd->scsi_ssts & SSTS_BUSY) == 0) { 40041480Smckusick if (hd->scsi_ints || --wait < 0) { 40141480Smckusick #ifdef DEBUG 40241480Smckusick if (scsi_debug) 40341480Smckusick printf("ixfer_start fail: i%x, w%d\n", 40441480Smckusick hd->scsi_ints, wait); 40541480Smckusick #endif 40641480Smckusick HIST(ixstart_wait, wait) 40741480Smckusick return (0); 40841480Smckusick } 40941480Smckusick DELAY(1); 41041480Smckusick } 41141480Smckusick HIST(ixstart_wait, wait) 41241480Smckusick return (1); 41341480Smckusick } 41441480Smckusick 41541480Smckusick static int 41641480Smckusick ixfer_out(hd, len, buf) 41741480Smckusick volatile register struct scsidevice *hd; 41841480Smckusick int len; 41941480Smckusick register u_char *buf; 42041480Smckusick { 42141480Smckusick register int wait = scsi_data_wait; 42241480Smckusick 42341480Smckusick for (; len > 0; --len) { 42441480Smckusick while (hd->scsi_ssts & SSTS_DREG_FULL) { 42541480Smckusick if (hd->scsi_ints || --wait < 0) { 42641480Smckusick #ifdef DEBUG 42741480Smckusick if (scsi_debug) 42841480Smckusick printf("ixfer_out fail: l%d i%x w%d\n", 42941480Smckusick len, hd->scsi_ints, wait); 43041480Smckusick #endif 43141480Smckusick HIST(ixout_wait, wait) 43241480Smckusick return (len); 43341480Smckusick } 43441480Smckusick DELAY(1); 43541480Smckusick } 43641480Smckusick hd->scsi_dreg = *buf++; 43741480Smckusick } 43841480Smckusick HIST(ixout_wait, wait) 43941480Smckusick return (0); 44041480Smckusick } 44141480Smckusick 44241480Smckusick static void 44341480Smckusick ixfer_in(hd, len, buf) 44441480Smckusick volatile register struct scsidevice *hd; 44541480Smckusick int len; 44641480Smckusick register u_char *buf; 44741480Smckusick { 44841480Smckusick register int wait = scsi_data_wait; 44941480Smckusick 45041480Smckusick for (; len > 0; --len) { 45141480Smckusick while (hd->scsi_ssts & SSTS_DREG_EMPTY) { 45241480Smckusick if (hd->scsi_ints || --wait < 0) { 45341480Smckusick while (! (hd->scsi_ssts & SSTS_DREG_EMPTY)) { 45441480Smckusick *buf++ = hd->scsi_dreg; 45541480Smckusick --len; 45641480Smckusick } 45741480Smckusick #ifdef DEBUG 45841480Smckusick if (scsi_debug) 45941480Smckusick printf("ixfer_in fail: l%d i%x w%d\n", 46041480Smckusick len, hd->scsi_ints, wait); 46141480Smckusick #endif 46241480Smckusick HIST(ixin_wait, wait) 46341480Smckusick return; 46441480Smckusick } 46541480Smckusick DELAY(1); 46641480Smckusick } 46741480Smckusick *buf++ = hd->scsi_dreg; 46841480Smckusick } 46941480Smckusick HIST(ixin_wait, wait) 47041480Smckusick } 47141480Smckusick 47241480Smckusick static int 47341480Smckusick mxfer_in(hd, len, buf, phase) 47441480Smckusick volatile register struct scsidevice *hd; 47541480Smckusick register int len; 47641480Smckusick register u_char *buf; 47741480Smckusick register u_char phase; 47841480Smckusick { 47941480Smckusick register int wait = scsi_cmd_wait; 48041480Smckusick register int i; 48141480Smckusick 48241480Smckusick hd->scsi_tmod = 0; 48341480Smckusick for (i = 0; i < len; ++i) { 48441480Smckusick /* 485*46285Smckusick * manual sez: reset ATN before ACK is sent. 486*46285Smckusick */ 487*46285Smckusick if (hd->scsi_psns & PSNS_ATN) 488*46285Smckusick hd->scsi_scmd = SCMD_RST_ATN; 489*46285Smckusick /* 49041480Smckusick * wait for the request line (which says the target 49141480Smckusick * wants to give us data). If the phase changes while 49241480Smckusick * we're waiting, we're done. 49341480Smckusick */ 49441480Smckusick while ((hd->scsi_psns & PSNS_REQ) == 0) { 49541480Smckusick if (--wait < 0) { 49641480Smckusick HIST(mxin_wait, wait) 49741480Smckusick return (-1); 49841480Smckusick } 49941480Smckusick if ((hd->scsi_psns & PHASE) != phase || 50041480Smckusick (hd->scsi_ssts & SSTS_INITIATOR) == 0) 50141480Smckusick goto out; 50241480Smckusick 50341480Smckusick DELAY(1); 50441480Smckusick } 50541480Smckusick /* 50641480Smckusick * set ack (which says we're ready for the data, wait for 50741480Smckusick * req to go away (target says data is available), grab the 50841480Smckusick * data, then reset ack (say we've got the data). 50941480Smckusick */ 51041480Smckusick hd->scsi_pctl = phase; 51141480Smckusick hd->scsi_scmd = SCMD_SET_ACK; 51241480Smckusick while (hd->scsi_psns & PSNS_REQ) { 51341480Smckusick if (--wait < 0) { 51441480Smckusick HIST(mxin_wait, wait) 51541480Smckusick return (-2); 51641480Smckusick } 51741480Smckusick DELAY(1); 51841480Smckusick } 51941480Smckusick *buf++ = hd->scsi_temp; 52041480Smckusick hd->scsi_scmd = SCMD_RST_ACK; 52141480Smckusick } 52241480Smckusick out: 52341480Smckusick HIST(mxin_wait, wait) 524*46285Smckusick /* 525*46285Smckusick * Wait for manual transfer to finish. 526*46285Smckusick * Avoids occasional "unexpected phase" errors in finishxfer 527*46285Smckusick * formerly addressed by per-slave delays. 528*46285Smckusick */ 529*46285Smckusick wait = scsi_cmd_wait; 530*46285Smckusick while ((hd->scsi_ssts & SSTS_ACTIVE) == SSTS_INITIATOR) { 531*46285Smckusick if (--wait < 0) 532*46285Smckusick break; 533*46285Smckusick DELAY(1); 534*46285Smckusick } 535*46285Smckusick HIST(mxin2_wait, wait) 53641480Smckusick return (i); 53741480Smckusick } 53841480Smckusick 53941480Smckusick /* 54041480Smckusick * SCSI 'immediate' command: issue a command to some SCSI device 54141480Smckusick * and get back an 'immediate' response (i.e., do programmed xfer 54241480Smckusick * to get the response data). 'cbuf' is a buffer containing a scsi 54341480Smckusick * command of length clen bytes. 'buf' is a buffer of length 'len' 54441480Smckusick * bytes for data. The transfer direction is determined by the device 54541480Smckusick * (i.e., by the scsi bus data xfer phase). If 'len' is zero, the 54641480Smckusick * command must supply no data. 'xferphase' is the bus phase the 54741480Smckusick * caller expects to happen after the command is issued. It should 54841480Smckusick * be one of DATA_IN_PHASE, DATA_OUT_PHASE or STATUS_PHASE. 54941480Smckusick */ 55041480Smckusick static int 55141480Smckusick scsiicmd(hs, target, cbuf, clen, buf, len, xferphase) 55241480Smckusick struct scsi_softc *hs; 55341480Smckusick int target; 55441480Smckusick u_char *cbuf; 55541480Smckusick int clen; 55641480Smckusick u_char *buf; 55741480Smckusick int len; 55841480Smckusick u_char xferphase; 55941480Smckusick { 56041480Smckusick volatile register struct scsidevice *hd = 56141480Smckusick (struct scsidevice *)hs->sc_hc->hp_addr; 56241480Smckusick u_char phase, ints; 56341480Smckusick register int wait; 56441480Smckusick 56541480Smckusick /* select the SCSI bus (it's an error if bus isn't free) */ 56641480Smckusick if (issue_select(hd, target, hs->sc_scsi_addr)) 56741480Smckusick return (-1); 56841480Smckusick if (wait_for_select(hd)) 56941480Smckusick return (-1); 57041480Smckusick /* 57141480Smckusick * Wait for a phase change (or error) then let the device 57241480Smckusick * sequence us through the various SCSI phases. 57341480Smckusick */ 57441480Smckusick hs->sc_stat[0] = 0xff; 57541480Smckusick hs->sc_msg[0] = 0xff; 57641480Smckusick phase = CMD_PHASE; 57741480Smckusick while (1) { 57841480Smckusick wait = scsi_cmd_wait; 57941480Smckusick switch (phase) { 58041480Smckusick 58141480Smckusick case CMD_PHASE: 58241480Smckusick if (ixfer_start(hd, clen, phase, wait)) 58341480Smckusick if (ixfer_out(hd, clen, cbuf)) 58441480Smckusick goto abort; 58541480Smckusick phase = xferphase; 58641480Smckusick break; 58741480Smckusick 58841480Smckusick case DATA_IN_PHASE: 58941480Smckusick if (len <= 0) 59041480Smckusick goto abort; 59141480Smckusick wait = scsi_data_wait; 59241480Smckusick if (ixfer_start(hd, len, phase, wait) || 59341480Smckusick !(hd->scsi_ssts & SSTS_DREG_EMPTY)) 59441480Smckusick ixfer_in(hd, len, buf); 59541480Smckusick phase = STATUS_PHASE; 59641480Smckusick break; 59741480Smckusick 59841480Smckusick case DATA_OUT_PHASE: 59941480Smckusick if (len <= 0) 60041480Smckusick goto abort; 60141480Smckusick wait = scsi_data_wait; 60241480Smckusick if (ixfer_start(hd, len, phase, wait)) { 60341480Smckusick if (ixfer_out(hd, len, buf)) 60441480Smckusick goto abort; 60541480Smckusick } 60641480Smckusick phase = STATUS_PHASE; 60741480Smckusick break; 60841480Smckusick 60941480Smckusick case STATUS_PHASE: 61041480Smckusick wait = scsi_data_wait; 61141480Smckusick if (ixfer_start(hd, sizeof(hs->sc_stat), phase, wait) || 61241480Smckusick !(hd->scsi_ssts & SSTS_DREG_EMPTY)) 61341480Smckusick ixfer_in(hd, sizeof(hs->sc_stat), hs->sc_stat); 61441480Smckusick phase = MESG_IN_PHASE; 61541480Smckusick break; 61641480Smckusick 61741480Smckusick case MESG_IN_PHASE: 61841480Smckusick if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait) || 61941480Smckusick !(hd->scsi_ssts & SSTS_DREG_EMPTY)) { 62041480Smckusick ixfer_in(hd, sizeof(hs->sc_msg), hs->sc_msg); 62141480Smckusick hd->scsi_scmd = SCMD_RST_ACK; 62241480Smckusick } 62341480Smckusick phase = BUS_FREE_PHASE; 62441480Smckusick break; 62541480Smckusick 62641480Smckusick case BUS_FREE_PHASE: 62741480Smckusick goto out; 62841480Smckusick 62941480Smckusick default: 63041480Smckusick printf("scsi%d: unexpected phase %d in icmd from %d\n", 63141480Smckusick hs->sc_hc->hp_unit, phase, target); 63241480Smckusick goto abort; 63341480Smckusick } 63441480Smckusick /* wait for last command to complete */ 63541480Smckusick while ((ints = hd->scsi_ints) == 0) { 63641480Smckusick if (--wait < 0) { 63741480Smckusick HIST(cxin_wait, wait) 63841480Smckusick goto abort; 63941480Smckusick } 64041480Smckusick DELAY(1); 64141480Smckusick } 64241480Smckusick HIST(cxin_wait, wait) 64341480Smckusick hd->scsi_ints = ints; 64441480Smckusick if (ints & INTS_SRV_REQ) 64541480Smckusick phase = hd->scsi_psns & PHASE; 64641480Smckusick else if (ints & INTS_DISCON) 64741480Smckusick goto out; 64841480Smckusick else if ((ints & INTS_CMD_DONE) == 0) { 64941480Smckusick scsierror(hs, hd, ints); 65041480Smckusick goto abort; 65141480Smckusick } 65241480Smckusick } 65341480Smckusick abort: 65441480Smckusick scsiabort(hs, hd, "icmd"); 65541480Smckusick out: 65641480Smckusick return (hs->sc_stat[0]); 65741480Smckusick } 65841480Smckusick 65941480Smckusick /* 66041480Smckusick * Finish SCSI xfer command: After the completion interrupt from 66141480Smckusick * a read/write operation, sequence through the final phases in 66241480Smckusick * programmed i/o. This routine is a lot like scsiicmd except we 66341480Smckusick * skip (and don't allow) the select, cmd out and data in/out phases. 66441480Smckusick */ 66541480Smckusick static void 66641480Smckusick finishxfer(hs, hd, target) 66741480Smckusick struct scsi_softc *hs; 66841480Smckusick volatile register struct scsidevice *hd; 66941480Smckusick int target; 67041480Smckusick { 67141480Smckusick u_char phase, ints; 67241480Smckusick 67341480Smckusick /* 67441480Smckusick * We specified padding xfer so we ended with either a phase 67541480Smckusick * change interrupt (normal case) or an error interrupt (handled 67641480Smckusick * elsewhere). Reset the board dma logic then try to get the 67741480Smckusick * completion status & command done msg. The reset confuses 67841480Smckusick * the SPC REQ/ACK logic so we have to do any status/msg input 67941480Smckusick * operations via 'manual xfer'. 68041480Smckusick */ 68141480Smckusick if (hd->scsi_ssts & SSTS_BUSY) { 68241480Smckusick int wait = scsi_cmd_wait; 68341480Smckusick 68441480Smckusick /* wait for dma operation to finish */ 68541480Smckusick while (hd->scsi_ssts & SSTS_BUSY) { 68641480Smckusick if (--wait < 0) { 68741480Smckusick #ifdef DEBUG 68841480Smckusick if (scsi_debug) 68941480Smckusick printf("finishxfer fail: ssts %x\n", 69041480Smckusick hd->scsi_ssts); 69141480Smckusick #endif 69241480Smckusick HIST(fxfr_wait, wait) 69341480Smckusick goto abort; 69441480Smckusick } 69541480Smckusick } 69641480Smckusick HIST(fxfr_wait, wait) 69741480Smckusick } 69841480Smckusick hd->scsi_scmd |= SCMD_PROG_XFR; 69941480Smckusick hd->scsi_sctl |= SCTL_CTRLRST; 70041480Smckusick DELAY(1); 70141480Smckusick hd->scsi_sctl &=~ SCTL_CTRLRST; 70241480Smckusick hd->scsi_hconf = 0; 70341480Smckusick hs->sc_stat[0] = 0xff; 70441480Smckusick hs->sc_msg[0] = 0xff; 70541480Smckusick hd->scsi_csr = 0; 70641480Smckusick hd->scsi_ints = ints = hd->scsi_ints; 70741480Smckusick while (1) { 70841480Smckusick phase = hd->scsi_psns & PHASE; 70941480Smckusick switch (phase) { 71041480Smckusick 71141480Smckusick case STATUS_PHASE: 71241480Smckusick if (mxfer_in(hd, sizeof(hs->sc_stat), hs->sc_stat, 71341480Smckusick phase) <= 0) 71441480Smckusick goto abort; 71541480Smckusick break; 71641480Smckusick 71741480Smckusick case MESG_IN_PHASE: 71841480Smckusick if (mxfer_in(hd, sizeof(hs->sc_msg), hs->sc_msg, 71941480Smckusick phase) < 0) 72041480Smckusick goto abort; 72141480Smckusick break; 72241480Smckusick 72341480Smckusick case BUS_FREE_PHASE: 72441480Smckusick return; 72541480Smckusick 72641480Smckusick default: 72741480Smckusick printf("scsi%d: unexpected phase %d in finishxfer from %d\n", 72841480Smckusick hs->sc_hc->hp_unit, phase, target); 72941480Smckusick goto abort; 73041480Smckusick } 73141480Smckusick if (ints = hd->scsi_ints) { 73241480Smckusick hd->scsi_ints = ints; 73341480Smckusick if (ints & INTS_DISCON) 73441480Smckusick return; 73541480Smckusick else if (ints & ~(INTS_SRV_REQ|INTS_CMD_DONE)) { 73641480Smckusick scsierror(hs, hd, ints); 73741480Smckusick break; 73841480Smckusick } 73941480Smckusick } 74041480Smckusick if ((hd->scsi_ssts & SSTS_INITIATOR) == 0) 74141480Smckusick return; 74241480Smckusick } 74341480Smckusick abort: 74441480Smckusick scsiabort(hs, hd, "finishxfer"); 74541480Smckusick hs->sc_stat[0] = 0xfe; 74641480Smckusick } 74741480Smckusick 74841480Smckusick int 74941480Smckusick scsi_test_unit_rdy(ctlr, slave, unit) 75041480Smckusick int ctlr, slave, unit; 75141480Smckusick { 75241480Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 75341480Smckusick static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY }; 75441480Smckusick 75541480Smckusick cdb.lun = unit; 75641480Smckusick return (scsiicmd(hs, slave, &cdb, sizeof(cdb), (u_char *)0, 0, 75741480Smckusick STATUS_PHASE)); 75841480Smckusick } 75941480Smckusick 76041480Smckusick int 76141480Smckusick scsi_request_sense(ctlr, slave, unit, buf, len) 76241480Smckusick int ctlr, slave, unit; 76341480Smckusick u_char *buf; 76441480Smckusick unsigned len; 76541480Smckusick { 76641480Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 76741480Smckusick static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE }; 76841480Smckusick 76941480Smckusick cdb.lun = unit; 77041480Smckusick cdb.len = len; 77141480Smckusick return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE)); 77241480Smckusick } 77341480Smckusick 77441480Smckusick int 77541480Smckusick scsi_immed_command(ctlr, slave, unit, cdb, buf, len, rd) 77641480Smckusick int ctlr, slave, unit; 77741480Smckusick struct scsi_fmt_cdb *cdb; 77841480Smckusick u_char *buf; 77941480Smckusick unsigned len; 78041480Smckusick { 78141480Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 78241480Smckusick 78341480Smckusick cdb->cdb[1] |= unit << 5; 78441480Smckusick return (scsiicmd(hs, slave, cdb->cdb, cdb->len, buf, len, 78541480Smckusick rd != 0? DATA_IN_PHASE : DATA_OUT_PHASE)); 78641480Smckusick } 78741480Smckusick 78841480Smckusick /* 78941480Smckusick * The following routines are test-and-transfer i/o versions of read/write 79041480Smckusick * for things like reading disk labels and writing core dumps. The 79141480Smckusick * routine scsigo should be used for normal data transfers, NOT these 79241480Smckusick * routines. 79341480Smckusick */ 79441480Smckusick int 79541480Smckusick scsi_tt_read(ctlr, slave, unit, buf, len, blk, bshift) 79641480Smckusick int ctlr, slave, unit; 79741480Smckusick u_char *buf; 79841480Smckusick u_int len; 79941480Smckusick daddr_t blk; 80041480Smckusick int bshift; 80141480Smckusick { 80241480Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 80341480Smckusick struct scsi_cdb10 cdb; 80441480Smckusick int stat; 80541480Smckusick int old_wait = scsi_data_wait; 80641480Smckusick 80741480Smckusick scsi_data_wait = 300000; 80841480Smckusick bzero(&cdb, sizeof(cdb)); 80941480Smckusick cdb.cmd = CMD_READ_EXT; 81041480Smckusick cdb.lun = unit; 81141480Smckusick blk >>= bshift; 81241480Smckusick cdb.lbah = blk >> 24; 81341480Smckusick cdb.lbahm = blk >> 16; 81441480Smckusick cdb.lbalm = blk >> 8; 81541480Smckusick cdb.lbal = blk; 81641480Smckusick cdb.lenh = len >> (8 + DEV_BSHIFT + bshift); 81741480Smckusick cdb.lenl = len >> (DEV_BSHIFT + bshift); 81841480Smckusick stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE); 81941480Smckusick scsi_data_wait = old_wait; 82041480Smckusick return (stat); 82141480Smckusick } 82241480Smckusick 82341480Smckusick int 82441480Smckusick scsi_tt_write(ctlr, slave, unit, buf, len, blk, bshift) 82541480Smckusick int ctlr, slave, unit; 82641480Smckusick u_char *buf; 82741480Smckusick u_int len; 82841480Smckusick daddr_t blk; 82941480Smckusick int bshift; 83041480Smckusick { 83141480Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 83241480Smckusick struct scsi_cdb10 cdb; 83341480Smckusick int stat; 83441480Smckusick int old_wait = scsi_data_wait; 83541480Smckusick 83641480Smckusick scsi_data_wait = 300000; 83741480Smckusick 83841480Smckusick bzero(&cdb, sizeof(cdb)); 83941480Smckusick cdb.cmd = CMD_WRITE_EXT; 84041480Smckusick cdb.lun = unit; 84141480Smckusick blk >>= bshift; 84241480Smckusick cdb.lbah = blk >> 24; 84341480Smckusick cdb.lbahm = blk >> 16; 84441480Smckusick cdb.lbalm = blk >> 8; 84541480Smckusick cdb.lbal = blk; 84641480Smckusick cdb.lenh = len >> (8 + DEV_BSHIFT + bshift); 84741480Smckusick cdb.lenl = len >> (DEV_BSHIFT + bshift); 84841480Smckusick stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_OUT_PHASE); 84941480Smckusick scsi_data_wait = old_wait; 85041480Smckusick return (stat); 85141480Smckusick } 85241480Smckusick 85341480Smckusick int 85441480Smckusick scsireq(dq) 85541480Smckusick register struct devqueue *dq; 85641480Smckusick { 85741480Smckusick register struct devqueue *hq; 85841480Smckusick 85941480Smckusick hq = &scsi_softc[dq->dq_ctlr].sc_sq; 86041480Smckusick insque(dq, hq->dq_back); 86141480Smckusick if (dq->dq_back == hq) 86241480Smckusick return(1); 86341480Smckusick return(0); 86441480Smckusick } 86541480Smckusick 86641480Smckusick int 86741480Smckusick scsiustart(unit) 86841480Smckusick int unit; 86941480Smckusick { 87041480Smckusick register struct scsi_softc *hs = &scsi_softc[unit]; 87141480Smckusick 87241480Smckusick hs->sc_dq.dq_ctlr = DMA0 | DMA1; 87341480Smckusick if (dmareq(&hs->sc_dq)) 87441480Smckusick return(1); 87541480Smckusick return(0); 87641480Smckusick } 87741480Smckusick 87841480Smckusick void 87941480Smckusick scsistart(unit) 88041480Smckusick int unit; 88141480Smckusick { 88241480Smckusick register struct devqueue *dq; 88341480Smckusick 88441480Smckusick dq = scsi_softc[unit].sc_sq.dq_forw; 88541480Smckusick (dq->dq_driver->d_go)(dq->dq_unit); 88641480Smckusick } 88741480Smckusick 88841480Smckusick int 88941480Smckusick scsigo(ctlr, slave, unit, bp, cdb, pad) 89041480Smckusick int ctlr, slave, unit; 89141480Smckusick struct buf *bp; 89241480Smckusick struct scsi_fmt_cdb *cdb; 89341480Smckusick int pad; 89441480Smckusick { 89541480Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 89641480Smckusick volatile register struct scsidevice *hd = 89741480Smckusick (struct scsidevice *)hs->sc_hc->hp_addr; 89841480Smckusick int i, dmaflags; 89941480Smckusick u_char phase, ints, cmd; 90041480Smckusick 90141480Smckusick cdb->cdb[1] |= unit << 5; 90241480Smckusick 90341480Smckusick /* select the SCSI bus (it's an error if bus isn't free) */ 90441480Smckusick if (issue_select(hd, slave, hs->sc_scsi_addr) || wait_for_select(hd)) { 90541480Smckusick dmafree(&hs->sc_dq); 90641480Smckusick return (1); 90741480Smckusick } 90841480Smckusick /* 90941480Smckusick * Wait for a phase change (or error) then let the device 91041480Smckusick * sequence us through command phase (we may have to take 91141480Smckusick * a msg in/out before doing the command). If the disk has 91241480Smckusick * to do a seek, it may be a long time until we get a change 91341480Smckusick * to data phase so, in the absense of an explicit phase 91441480Smckusick * change, we assume data phase will be coming up and tell 91541480Smckusick * the SPC to start a transfer whenever it does. We'll get 91641480Smckusick * a service required interrupt later if this assumption is 91741480Smckusick * wrong. Otherwise we'll get a service required int when 91841480Smckusick * the transfer changes to status phase. 91941480Smckusick */ 92041480Smckusick phase = CMD_PHASE; 92141480Smckusick while (1) { 92241480Smckusick register int wait = scsi_cmd_wait; 92341480Smckusick 92441480Smckusick switch (phase) { 92541480Smckusick 92641480Smckusick case CMD_PHASE: 92741480Smckusick if (ixfer_start(hd, cdb->len, phase, wait)) 92841480Smckusick if (ixfer_out(hd, cdb->len, cdb->cdb)) 92941480Smckusick goto abort; 93041480Smckusick break; 93141480Smckusick 93241480Smckusick case MESG_IN_PHASE: 93341480Smckusick if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait)|| 93441480Smckusick !(hd->scsi_ssts & SSTS_DREG_EMPTY)) { 93541480Smckusick ixfer_in(hd, sizeof(hs->sc_msg), hs->sc_msg); 93641480Smckusick hd->scsi_scmd = SCMD_RST_ACK; 93741480Smckusick } 93841480Smckusick phase = BUS_FREE_PHASE; 93941480Smckusick break; 94041480Smckusick 94141480Smckusick case DATA_IN_PHASE: 94241480Smckusick case DATA_OUT_PHASE: 94341480Smckusick goto out; 94441480Smckusick 94541480Smckusick default: 94641480Smckusick printf("scsi%d: unexpected phase %d in go from %d\n", 94741480Smckusick hs->sc_hc->hp_unit, phase, slave); 94841480Smckusick goto abort; 94941480Smckusick } 95041480Smckusick while ((ints = hd->scsi_ints) == 0) { 95141480Smckusick if (--wait < 0) { 95241480Smckusick HIST(sgo_wait, wait) 95341480Smckusick goto abort; 95441480Smckusick } 95541480Smckusick DELAY(1); 95641480Smckusick } 95741480Smckusick HIST(sgo_wait, wait) 95841480Smckusick hd->scsi_ints = ints; 95941480Smckusick if (ints & INTS_SRV_REQ) 96041480Smckusick phase = hd->scsi_psns & PHASE; 96141480Smckusick else if (ints & INTS_CMD_DONE) 96241480Smckusick goto out; 96341480Smckusick else { 96441480Smckusick scsierror(hs, hd, ints); 96541480Smckusick goto abort; 96641480Smckusick } 96741480Smckusick } 96841480Smckusick out: 96941480Smckusick /* 97041480Smckusick * Reset the card dma logic, setup the dma channel then 97141480Smckusick * get the dio part of the card set for a dma xfer. 97241480Smckusick */ 97341480Smckusick hd->scsi_hconf = 0; 97445514Smckusick cmd = CSR_IE; 97541480Smckusick dmaflags = DMAGO_NOINT; 97645514Smckusick if (scsi_pridma) 97745514Smckusick dmaflags |= DMAGO_PRI; 97841480Smckusick if (bp->b_flags & B_READ) 97941480Smckusick dmaflags |= DMAGO_READ; 98041480Smckusick if ((hs->sc_flags & SCSI_DMA32) && 98141480Smckusick ((int)bp->b_un.b_addr & 3) == 0 && (bp->b_bcount & 3) == 0) { 98241480Smckusick cmd |= CSR_DMA32; 98341480Smckusick dmaflags |= DMAGO_LWORD; 98441480Smckusick } else 98541480Smckusick dmaflags |= DMAGO_WORD; 98641480Smckusick dmago(hs->sc_dq.dq_ctlr, bp->b_un.b_addr, bp->b_bcount, dmaflags); 98741480Smckusick 98841480Smckusick if (bp->b_flags & B_READ) { 98941480Smckusick cmd |= CSR_DMAIN; 99041480Smckusick phase = DATA_IN_PHASE; 99141480Smckusick } else 99241480Smckusick phase = DATA_OUT_PHASE; 99345514Smckusick /* 99445514Smckusick * DMA enable bits must be set after size and direction bits. 99545514Smckusick */ 99641480Smckusick hd->scsi_csr = cmd; 99745514Smckusick hd->scsi_csr |= (CSR_DE0 << hs->sc_dq.dq_ctlr); 99841480Smckusick /* 99941480Smckusick * Setup the SPC for the transfer. We don't want to take 100041480Smckusick * first a command complete then a service required interrupt 100141480Smckusick * at the end of the transfer so we try to disable the cmd 100241480Smckusick * complete by setting the transfer counter to more bytes 100341480Smckusick * than we expect. (XXX - This strategy may have to be 100441480Smckusick * modified to deal with devices that return variable length 100541480Smckusick * blocks, e.g., some tape drives.) 100641480Smckusick */ 100741480Smckusick cmd = SCMD_XFR; 100841480Smckusick i = (unsigned)bp->b_bcount; 100941480Smckusick if (pad) { 101041480Smckusick cmd |= SCMD_PAD; 101141480Smckusick /* 101241480Smckusick * XXX - If we don't do this, the last 2 or 4 bytes 101341480Smckusick * (depending on word/lword DMA) of a read get trashed. 101441480Smckusick * It looks like it is necessary for the DMA to complete 101541480Smckusick * before the SPC goes into "pad mode"??? Note: if we 101641480Smckusick * also do this on a write, the request never completes. 101741480Smckusick */ 101841480Smckusick if (bp->b_flags & B_READ) 101941480Smckusick i += 2; 102041480Smckusick #ifdef DEBUG 102141480Smckusick hs->sc_flags |= SCSI_PAD; 102241480Smckusick if (i & 1) 102341480Smckusick printf("scsi%d: odd byte count: %d bytes @ %d\n", 102441480Smckusick ctlr, i, bp->b_cylin); 102541480Smckusick #endif 102641480Smckusick } else 102741480Smckusick i += 4; 102841480Smckusick hd->scsi_tch = i >> 16; 102941480Smckusick hd->scsi_tcm = i >> 8; 103041480Smckusick hd->scsi_tcl = i; 103141480Smckusick hd->scsi_pctl = phase; 103241480Smckusick hd->scsi_tmod = 0; 103341480Smckusick hd->scsi_scmd = cmd; 103441480Smckusick hs->sc_flags |= SCSI_IO; 103541480Smckusick return (0); 103641480Smckusick abort: 103741480Smckusick scsiabort(hs, hd, "go"); 103841480Smckusick dmafree(&hs->sc_dq); 103941480Smckusick return (1); 104041480Smckusick } 104141480Smckusick 104241480Smckusick void 104341480Smckusick scsidone(unit) 104441480Smckusick register int unit; 104541480Smckusick { 104641480Smckusick volatile register struct scsidevice *hd = 104741480Smckusick (struct scsidevice *)scsi_softc[unit].sc_hc->hp_addr; 104841480Smckusick 104945514Smckusick #ifdef DEBUG 105045514Smckusick if (scsi_debug) 105145514Smckusick printf("scsi%d: done called!\n"); 105245514Smckusick #endif 105341480Smckusick /* dma operation is done -- turn off card dma */ 105441480Smckusick hd->scsi_csr &=~ (CSR_DE1|CSR_DE0); 105541480Smckusick } 105641480Smckusick 105741480Smckusick int 105841480Smckusick scsiintr(unit) 105941480Smckusick register int unit; 106041480Smckusick { 106141480Smckusick register struct scsi_softc *hs = &scsi_softc[unit]; 106241480Smckusick volatile register struct scsidevice *hd = 106341480Smckusick (struct scsidevice *)hs->sc_hc->hp_addr; 106441480Smckusick register u_char ints; 106541480Smckusick register struct devqueue *dq; 106641480Smckusick 106741480Smckusick if ((hd->scsi_csr & (CSR_IE|CSR_IR)) != (CSR_IE|CSR_IR)) 106841480Smckusick return (0); 106941480Smckusick 107041480Smckusick ints = hd->scsi_ints; 107141480Smckusick if ((ints & INTS_SRV_REQ) && (hs->sc_flags & SCSI_IO)) { 107241480Smckusick /* 107341480Smckusick * this should be the normal i/o completion case. 107441480Smckusick * get the status & cmd complete msg then let the 107541480Smckusick * device driver look at what happened. 107641480Smckusick */ 107741480Smckusick #ifdef DEBUG 107841480Smckusick int len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | 107941480Smckusick hd->scsi_tcl; 108041480Smckusick if (!(hs->sc_flags & SCSI_PAD)) 108141480Smckusick len -= 4; 108241480Smckusick hs->sc_flags &=~ SCSI_PAD; 108341480Smckusick #endif 108441480Smckusick dq = hs->sc_sq.dq_forw; 1085*46285Smckusick finishxfer(hs, hd, dq->dq_slave); 108641480Smckusick hs->sc_flags &=~ SCSI_IO; 108741480Smckusick dmafree(&hs->sc_dq); 108841480Smckusick (dq->dq_driver->d_intr)(dq->dq_unit, hs->sc_stat[0]); 108941480Smckusick } else { 109041480Smckusick /* Something unexpected happened -- deal with it. */ 109141480Smckusick hd->scsi_ints = ints; 109241480Smckusick hd->scsi_csr = 0; 109341480Smckusick scsierror(hs, hd, ints); 109441480Smckusick scsiabort(hs, hd, "intr"); 109541480Smckusick if (hs->sc_flags & SCSI_IO) { 109641480Smckusick hs->sc_flags &=~ SCSI_IO; 109741480Smckusick dmafree(&hs->sc_dq); 109841480Smckusick dq = hs->sc_sq.dq_forw; 109941480Smckusick (dq->dq_driver->d_intr)(dq->dq_unit, -1); 110041480Smckusick } 110141480Smckusick } 110241480Smckusick return(1); 110341480Smckusick } 110441480Smckusick 110541480Smckusick void 110641480Smckusick scsifree(dq) 110741480Smckusick register struct devqueue *dq; 110841480Smckusick { 110941480Smckusick register struct devqueue *hq; 111041480Smckusick 111141480Smckusick hq = &scsi_softc[dq->dq_ctlr].sc_sq; 111241480Smckusick remque(dq); 111341480Smckusick if ((dq = hq->dq_forw) != hq) 111441480Smckusick (dq->dq_driver->d_start)(dq->dq_unit); 111541480Smckusick } 1116*46285Smckusick 1117*46285Smckusick /* 1118*46285Smckusick * (XXX) The following routine is needed for the SCSI tape driver 1119*46285Smckusick * to read odd-size records. 1120*46285Smckusick */ 1121*46285Smckusick 1122*46285Smckusick #include "st.h" 1123*46285Smckusick #if NST > 0 1124*46285Smckusick int 1125*46285Smckusick scsi_tt_oddio(ctlr, slave, unit, buf, len, b_flags, freedma) 1126*46285Smckusick int ctlr, slave, unit, b_flags; 1127*46285Smckusick u_char *buf; 1128*46285Smckusick u_int len; 1129*46285Smckusick { 1130*46285Smckusick register struct scsi_softc *hs = &scsi_softc[ctlr]; 1131*46285Smckusick struct scsi_cdb6 cdb; 1132*46285Smckusick u_char iphase; 1133*46285Smckusick int stat; 1134*46285Smckusick 1135*46285Smckusick /* 1136*46285Smckusick * First free any DMA channel that was allocated. 1137*46285Smckusick * We can't use DMA to do this transfer. 1138*46285Smckusick */ 1139*46285Smckusick if (freedma) 1140*46285Smckusick dmafree(hs->sc_dq); 1141*46285Smckusick /* 1142*46285Smckusick * Initialize command block 1143*46285Smckusick */ 1144*46285Smckusick bzero(&cdb, sizeof(cdb)); 1145*46285Smckusick cdb.lun = unit; 1146*46285Smckusick cdb.lbam = (len >> 16) & 0xff; 1147*46285Smckusick cdb.lbal = (len >> 8) & 0xff; 1148*46285Smckusick cdb.len = len & 0xff; 1149*46285Smckusick if (buf == 0) { 1150*46285Smckusick cdb.cmd = CMD_SPACE; 1151*46285Smckusick cdb.lun |= 0x00; 1152*46285Smckusick len = 0; 1153*46285Smckusick iphase = MESG_IN_PHASE; 1154*46285Smckusick } else if (b_flags & B_READ) { 1155*46285Smckusick cdb.cmd = CMD_READ; 1156*46285Smckusick iphase = DATA_IN_PHASE; 1157*46285Smckusick } else { 1158*46285Smckusick cdb.cmd = CMD_WRITE; 1159*46285Smckusick iphase = DATA_OUT_PHASE; 1160*46285Smckusick } 1161*46285Smckusick /* 1162*46285Smckusick * Perform command (with very long delays) 1163*46285Smckusick */ 1164*46285Smckusick scsi_delay(30000000); 1165*46285Smckusick stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, iphase); 1166*46285Smckusick scsi_delay(0); 1167*46285Smckusick return (stat); 1168*46285Smckusick } 116941480Smckusick #endif 1170*46285Smckusick #endif 1171