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