xref: /csrg-svn/sys/hp300/dev/scsi.c (revision 41480)
1*41480Smckusick /*
2*41480Smckusick  * Copyright (c) 1990 The Regents of the University of California.
3*41480Smckusick  * All rights reserved.
4*41480Smckusick  *
5*41480Smckusick  * This code is derived from software contributed to Berkeley by
6*41480Smckusick  * Van Jacobson of Lawrence Berkeley Laboratory.
7*41480Smckusick  *
8*41480Smckusick  * %sccs.include.redist.c%
9*41480Smckusick  *
10*41480Smckusick  *	@(#)scsi.c	7.1 (Berkeley) 05/08/90
11*41480Smckusick  */
12*41480Smckusick 
13*41480Smckusick /*
14*41480Smckusick  * HP9000/3xx 98658 SCSI host adaptor driver.
15*41480Smckusick  */
16*41480Smckusick #include "scsi.h"
17*41480Smckusick #if NSCSI > 0
18*41480Smckusick 
19*41480Smckusick #ifndef lint
20*41480Smckusick static char rcsid[] = "$Header: scsi.c,v 1.3 90/01/06 04:56:50 van Exp $";
21*41480Smckusick #endif
22*41480Smckusick 
23*41480Smckusick #include "param.h"
24*41480Smckusick #include "systm.h"
25*41480Smckusick #include "buf.h"
26*41480Smckusick #include "device.h"
27*41480Smckusick #include "scsivar.h"
28*41480Smckusick #include "scsireg.h"
29*41480Smckusick #include "dmavar.h"
30*41480Smckusick 
31*41480Smckusick #include "machine/cpu.h"
32*41480Smckusick #include "machine/isr.h"
33*41480Smckusick 
34*41480Smckusick extern void isrlink();
35*41480Smckusick extern void printf();
36*41480Smckusick extern void _insque();
37*41480Smckusick extern void _remque();
38*41480Smckusick extern void bzero();
39*41480Smckusick 
40*41480Smckusick int	scsiinit(), scsigo(), scsiintr(), scsixfer();
41*41480Smckusick void	scsistart(), scsidone(), scsifree(), scsireset();
42*41480Smckusick struct	driver scsidriver = {
43*41480Smckusick 	scsiinit, "scsi", (int (*)())scsistart, scsigo, scsiintr,
44*41480Smckusick 	(int (*)())scsidone,
45*41480Smckusick };
46*41480Smckusick 
47*41480Smckusick struct	scsi_softc scsi_softc[NSCSI];
48*41480Smckusick struct	isr scsi_isr[NSCSI];
49*41480Smckusick 
50*41480Smckusick int scsi_cmd_wait = 512;	/* microsec wait per step of 'immediate' cmds */
51*41480Smckusick int scsi_data_wait = 512;	/* wait per data in/out step */
52*41480Smckusick int scsi_nosync = 1;		/* inhibit sync xfers if 1 */
53*41480Smckusick 
54*41480Smckusick #ifdef DEBUG
55*41480Smckusick int	scsi_debug = 0;
56*41480Smckusick #define WAITHIST
57*41480Smckusick #endif
58*41480Smckusick 
59*41480Smckusick #ifdef WAITHIST
60*41480Smckusick #define MAXWAIT	2048
61*41480Smckusick u_int	ixstart_wait[MAXWAIT+2];
62*41480Smckusick u_int	ixin_wait[MAXWAIT+2];
63*41480Smckusick u_int	ixout_wait[MAXWAIT+2];
64*41480Smckusick u_int	mxin_wait[MAXWAIT+2];
65*41480Smckusick u_int	cxin_wait[MAXWAIT+2];
66*41480Smckusick u_int	fxfr_wait[MAXWAIT+2];
67*41480Smckusick u_int	sgo_wait[MAXWAIT+2];
68*41480Smckusick #define HIST(h,w) (++h[((w)>MAXWAIT? MAXWAIT : ((w) < 0 ? -1 : (w))) + 1]);
69*41480Smckusick #else
70*41480Smckusick #define HIST(h,w)
71*41480Smckusick #endif
72*41480Smckusick 
73*41480Smckusick #define	b_cylin		b_resid
74*41480Smckusick 
75*41480Smckusick static void
76*41480Smckusick scsiabort(hs, hd, where)
77*41480Smckusick 	register struct scsi_softc *hs;
78*41480Smckusick 	volatile register struct scsidevice *hd;
79*41480Smckusick 	char *where;
80*41480Smckusick {
81*41480Smckusick 	int len;
82*41480Smckusick 	u_char junk;
83*41480Smckusick 
84*41480Smckusick 	printf("scsi%d: abort from %s: phase=0x%x, ssts=0x%x, ints=0x%x\n",
85*41480Smckusick 		hs->sc_hc->hp_unit, where, hd->scsi_psns, hd->scsi_ssts,
86*41480Smckusick 		hd->scsi_ints);
87*41480Smckusick 
88*41480Smckusick 	hd->scsi_ints = hd->scsi_ints;
89*41480Smckusick 	hd->scsi_csr = 0;
90*41480Smckusick 	if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0)
91*41480Smckusick 		/* no longer connected to scsi target */
92*41480Smckusick 		return;
93*41480Smckusick 
94*41480Smckusick 	/* get the number of bytes remaining in current xfer + fudge */
95*41480Smckusick 	len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl;
96*41480Smckusick 
97*41480Smckusick 	/* for that many bus cycles, try to send an abort msg */
98*41480Smckusick 	for (len += 1024; (hd->scsi_ssts & SSTS_INITIATOR) && --len >= 0; ) {
99*41480Smckusick 		hd->scsi_scmd = SCMD_SET_ATN;
100*41480Smckusick 		while ((hd->scsi_psns & PSNS_REQ) == 0) {
101*41480Smckusick 			if (! (hd->scsi_ssts & SSTS_INITIATOR))
102*41480Smckusick 				goto out;
103*41480Smckusick 			DELAY(1);
104*41480Smckusick 		}
105*41480Smckusick 		if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE)
106*41480Smckusick 			hd->scsi_scmd = SCMD_RST_ATN;
107*41480Smckusick 		hd->scsi_pctl = hd->scsi_psns & PHASE;
108*41480Smckusick 		if (hd->scsi_psns & PHASE_IO) {
109*41480Smckusick 			/* one of the input phases - read & discard a byte */
110*41480Smckusick 			hd->scsi_scmd = SCMD_SET_ACK;
111*41480Smckusick 			if (hd->scsi_tmod == 0)
112*41480Smckusick 				while (hd->scsi_psns & PSNS_REQ)
113*41480Smckusick 					DELAY(1);
114*41480Smckusick 			junk = hd->scsi_temp;
115*41480Smckusick 		} else {
116*41480Smckusick 			/* one of the output phases - send an abort msg */
117*41480Smckusick 			hd->scsi_temp = MSG_ABORT;
118*41480Smckusick 			hd->scsi_scmd = SCMD_SET_ACK;
119*41480Smckusick 			if (hd->scsi_tmod == 0)
120*41480Smckusick 				while (hd->scsi_psns & PSNS_REQ)
121*41480Smckusick 					DELAY(1);
122*41480Smckusick 		}
123*41480Smckusick 		hd->scsi_scmd = SCMD_RST_ACK;
124*41480Smckusick 	}
125*41480Smckusick out:
126*41480Smckusick 	/*
127*41480Smckusick 	 * Either the abort was successful & the bus is disconnected or
128*41480Smckusick 	 * the device didn't listen.  If the latter, announce the problem.
129*41480Smckusick 	 * Either way, reset the card & the SPC.
130*41480Smckusick 	 */
131*41480Smckusick 	if (len < 0 && hs)
132*41480Smckusick 		printf("scsi%d: abort failed.  phase=0x%x, ssts=0x%x\n",
133*41480Smckusick 			hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts);
134*41480Smckusick 
135*41480Smckusick 	if (! ((junk = hd->scsi_ints) & INTS_RESEL)) {
136*41480Smckusick 		hd->scsi_sctl |= SCTL_CTRLRST;
137*41480Smckusick 		DELAY(1);
138*41480Smckusick 		hd->scsi_sctl &=~ SCTL_CTRLRST;
139*41480Smckusick 		hd->scsi_hconf = 0;
140*41480Smckusick 		hd->scsi_ints = hd->scsi_ints;
141*41480Smckusick 	}
142*41480Smckusick }
143*41480Smckusick 
144*41480Smckusick int
145*41480Smckusick scsiinit(hc)
146*41480Smckusick 	register struct hp_ctlr *hc;
147*41480Smckusick {
148*41480Smckusick 	register struct scsi_softc *hs = &scsi_softc[hc->hp_unit];
149*41480Smckusick 	register struct scsidevice *hd = (struct scsidevice *)hc->hp_addr;
150*41480Smckusick 
151*41480Smckusick 	if ((hd->scsi_id & ID_MASK) != SCSI_ID)
152*41480Smckusick 		return(0);
153*41480Smckusick 	hc->hp_ipl = SCSI_IPL(hd->scsi_csr);
154*41480Smckusick 	hs->sc_hc = hc;
155*41480Smckusick 	hs->sc_dq.dq_unit = hc->hp_unit;
156*41480Smckusick 	hs->sc_dq.dq_driver = &scsidriver;
157*41480Smckusick 	hs->sc_sq.dq_forw = hs->sc_sq.dq_back = &hs->sc_sq;
158*41480Smckusick 	scsi_isr[hc->hp_unit].isr_intr = scsiintr;
159*41480Smckusick 	scsi_isr[hc->hp_unit].isr_ipl = hc->hp_ipl;
160*41480Smckusick 	scsi_isr[hc->hp_unit].isr_arg = hc->hp_unit;
161*41480Smckusick 	isrlink(&scsi_isr[hc->hp_unit]);
162*41480Smckusick 	scsireset(hc->hp_unit);
163*41480Smckusick 	return(1);
164*41480Smckusick }
165*41480Smckusick 
166*41480Smckusick void
167*41480Smckusick scsireset(unit)
168*41480Smckusick 	register int unit;
169*41480Smckusick {
170*41480Smckusick 	register struct scsi_softc *hs = &scsi_softc[unit];
171*41480Smckusick 	volatile register struct scsidevice *hd =
172*41480Smckusick 				(struct scsidevice *)hs->sc_hc->hp_addr;
173*41480Smckusick 	u_int i;
174*41480Smckusick 
175*41480Smckusick 	if (hs->sc_flags & SCSI_ALIVE)
176*41480Smckusick 		scsiabort(hs, hd, "reset");
177*41480Smckusick 
178*41480Smckusick 	printf("scsi%d: ", unit);
179*41480Smckusick 
180*41480Smckusick 	hd->scsi_id = 0xFF;
181*41480Smckusick 	DELAY(100);
182*41480Smckusick 	/*
183*41480Smckusick 	 * Disable interrupts then reset the FUJI chip.
184*41480Smckusick 	 */
185*41480Smckusick 	hd->scsi_csr  = 0;
186*41480Smckusick 	hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST;
187*41480Smckusick 	hd->scsi_scmd = 0;
188*41480Smckusick 	hd->scsi_tmod = 0;
189*41480Smckusick 	hd->scsi_pctl = 0;
190*41480Smckusick 	hd->scsi_temp = 0;
191*41480Smckusick 	hd->scsi_tch  = 0;
192*41480Smckusick 	hd->scsi_tcm  = 0;
193*41480Smckusick 	hd->scsi_tcl  = 0;
194*41480Smckusick 	hd->scsi_ints = 0;
195*41480Smckusick 
196*41480Smckusick 	if ((hd->scsi_id & ID_WORD_DMA) == 0) {
197*41480Smckusick 		hs->sc_flags |= SCSI_DMA32;
198*41480Smckusick 		printf("32 bit dma, ");
199*41480Smckusick 	}
200*41480Smckusick 
201*41480Smckusick 	/* Determine Max Synchronous Transfer Rate */
202*41480Smckusick 	if (scsi_nosync)
203*41480Smckusick 		i = 3;
204*41480Smckusick 	else
205*41480Smckusick 		i = SCSI_SYNC_XFER(hd->scsi_hconf);
206*41480Smckusick 	switch (i) {
207*41480Smckusick 		case 0:
208*41480Smckusick 			hs->sc_sync = TMOD_SYNC | 0x3e; /* 250 nsecs */
209*41480Smckusick 			printf("250ns sync");
210*41480Smckusick 			break;
211*41480Smckusick 		case 1:
212*41480Smckusick 			hs->sc_sync = TMOD_SYNC | 0x5e; /* 375 nsecs */
213*41480Smckusick 			printf("375ns sync");
214*41480Smckusick 			break;
215*41480Smckusick 		case 2:
216*41480Smckusick 			hs->sc_sync = TMOD_SYNC | 0x7d; /* 500 nsecs */
217*41480Smckusick 			printf("500ns sync");
218*41480Smckusick 			break;
219*41480Smckusick 		case 3:
220*41480Smckusick 			hs->sc_sync = 0;
221*41480Smckusick 			printf("async");
222*41480Smckusick 			break;
223*41480Smckusick 		}
224*41480Smckusick 
225*41480Smckusick 	/*
226*41480Smckusick 	 * Configure the FUJI chip with its SCSI address, all
227*41480Smckusick 	 * interrupts enabled & appropriate parity.
228*41480Smckusick 	 */
229*41480Smckusick 	i = (~hd->scsi_hconf) & 0x7;
230*41480Smckusick 	hs->sc_scsi_addr = 1 << i;
231*41480Smckusick 	hd->scsi_bdid = i;
232*41480Smckusick 	if (hd->scsi_hconf & HCONF_PARITY)
233*41480Smckusick 		hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB |
234*41480Smckusick 				SCTL_SEL_ENAB | SCTL_RESEL_ENAB |
235*41480Smckusick 				SCTL_INTR_ENAB | SCTL_PARITY_ENAB;
236*41480Smckusick 	else {
237*41480Smckusick 		hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB |
238*41480Smckusick 				SCTL_SEL_ENAB | SCTL_RESEL_ENAB |
239*41480Smckusick 				SCTL_INTR_ENAB;
240*41480Smckusick 		printf(", no parity");
241*41480Smckusick 	}
242*41480Smckusick 	hd->scsi_sctl &=~ SCTL_DISABLE;
243*41480Smckusick 
244*41480Smckusick 	printf(", scsi id %d\n", i);
245*41480Smckusick 	hs->sc_flags |= SCSI_ALIVE;
246*41480Smckusick }
247*41480Smckusick 
248*41480Smckusick static void
249*41480Smckusick scsierror(hs, hd, ints)
250*41480Smckusick 	register struct scsi_softc *hs;
251*41480Smckusick 	volatile register struct scsidevice *hd;
252*41480Smckusick 	u_char ints;
253*41480Smckusick {
254*41480Smckusick 	int unit = hs->sc_hc->hp_unit;
255*41480Smckusick 	char *sep = "";
256*41480Smckusick 
257*41480Smckusick 	printf("scsi%d: ", unit);
258*41480Smckusick 	if (ints & INTS_RST) {
259*41480Smckusick 		DELAY(100);
260*41480Smckusick 		if (hd->scsi_hconf & HCONF_SD)
261*41480Smckusick 			printf("spurious RST interrupt");
262*41480Smckusick 		else
263*41480Smckusick 			printf("hardware error - check fuse");
264*41480Smckusick 		sep = ", ";
265*41480Smckusick 	}
266*41480Smckusick 	if ((ints & INTS_HARD_ERR) || hd->scsi_serr) {
267*41480Smckusick 		if (hd->scsi_serr & SERR_SCSI_PAR) {
268*41480Smckusick 			printf("%sparity err", sep);
269*41480Smckusick 			sep = ", ";
270*41480Smckusick 		}
271*41480Smckusick 		if (hd->scsi_serr & SERR_SPC_PAR) {
272*41480Smckusick 			printf("%sSPC parity err", sep);
273*41480Smckusick 			sep = ", ";
274*41480Smckusick 		}
275*41480Smckusick 		if (hd->scsi_serr & SERR_TC_PAR) {
276*41480Smckusick 			printf("%sTC parity err", sep);
277*41480Smckusick 			sep = ", ";
278*41480Smckusick 		}
279*41480Smckusick 		if (hd->scsi_serr & SERR_PHASE_ERR) {
280*41480Smckusick 			printf("%sphase err", sep);
281*41480Smckusick 			sep = ", ";
282*41480Smckusick 		}
283*41480Smckusick 		if (hd->scsi_serr & SERR_SHORT_XFR) {
284*41480Smckusick 			printf("%ssync short transfer err", sep);
285*41480Smckusick 			sep = ", ";
286*41480Smckusick 		}
287*41480Smckusick 		if (hd->scsi_serr & SERR_OFFSET) {
288*41480Smckusick 			printf("%ssync offset error", sep);
289*41480Smckusick 			sep = ", ";
290*41480Smckusick 		}
291*41480Smckusick 	}
292*41480Smckusick 	if (ints & INTS_TIMEOUT)
293*41480Smckusick 		printf("%sSPC select timeout error", sep);
294*41480Smckusick 	if (ints & INTS_SRV_REQ)
295*41480Smckusick 		printf("%sspurious SRV_REQ interrupt", sep);
296*41480Smckusick 	if (ints & INTS_CMD_DONE)
297*41480Smckusick 		printf("%sspurious CMD_DONE interrupt", sep);
298*41480Smckusick 	if (ints & INTS_DISCON)
299*41480Smckusick 		printf("%sspurious disconnect interrupt", sep);
300*41480Smckusick 	if (ints & INTS_RESEL)
301*41480Smckusick 		printf("%sspurious reselect interrupt", sep);
302*41480Smckusick 	if (ints & INTS_SEL)
303*41480Smckusick 		printf("%sspurious select interrupt", sep);
304*41480Smckusick 	printf("\n");
305*41480Smckusick }
306*41480Smckusick 
307*41480Smckusick static int
308*41480Smckusick issue_select(hd, target, our_addr)
309*41480Smckusick 	volatile register struct scsidevice *hd;
310*41480Smckusick 	u_char target, our_addr;
311*41480Smckusick {
312*41480Smckusick 	if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY))
313*41480Smckusick 		return (1);
314*41480Smckusick 
315*41480Smckusick 	if (hd->scsi_ints & INTS_DISCON)
316*41480Smckusick 		hd->scsi_ints = INTS_DISCON;
317*41480Smckusick 
318*41480Smckusick 	hd->scsi_pctl = 0;
319*41480Smckusick 	hd->scsi_temp = (1 << target) | our_addr;
320*41480Smckusick 	/* select timeout is hardcoded to 2ms */
321*41480Smckusick 	hd->scsi_tch = 0;
322*41480Smckusick 	hd->scsi_tcm = 32;
323*41480Smckusick 	hd->scsi_tcl = 4;
324*41480Smckusick 
325*41480Smckusick 	hd->scsi_scmd = SCMD_SELECT;
326*41480Smckusick 	return (0);
327*41480Smckusick }
328*41480Smckusick 
329*41480Smckusick static int
330*41480Smckusick wait_for_select(hd)
331*41480Smckusick 	volatile register struct scsidevice *hd;
332*41480Smckusick {
333*41480Smckusick 	u_char ints;
334*41480Smckusick 
335*41480Smckusick 	while ((ints = hd->scsi_ints) == 0)
336*41480Smckusick 		DELAY(1);
337*41480Smckusick 	hd->scsi_ints = ints;
338*41480Smckusick 	return (!(hd->scsi_ssts & SSTS_INITIATOR));
339*41480Smckusick }
340*41480Smckusick 
341*41480Smckusick static int
342*41480Smckusick ixfer_start(hd, len, phase, wait)
343*41480Smckusick 	volatile register struct scsidevice *hd;
344*41480Smckusick 	int len;
345*41480Smckusick 	u_char phase;
346*41480Smckusick 	register int wait;
347*41480Smckusick {
348*41480Smckusick 
349*41480Smckusick 	hd->scsi_tch = len >> 16;
350*41480Smckusick 	hd->scsi_tcm = len >> 8;
351*41480Smckusick 	hd->scsi_tcl = len;
352*41480Smckusick 	hd->scsi_pctl = phase;
353*41480Smckusick 	hd->scsi_tmod = 0; /*XXX*/
354*41480Smckusick 	hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
355*41480Smckusick 
356*41480Smckusick 	/* wait for xfer to start or svc_req interrupt */
357*41480Smckusick 	while ((hd->scsi_ssts & SSTS_BUSY) == 0) {
358*41480Smckusick 		if (hd->scsi_ints || --wait < 0) {
359*41480Smckusick #ifdef DEBUG
360*41480Smckusick 			if (scsi_debug)
361*41480Smckusick 				printf("ixfer_start fail: i%x, w%d\n",
362*41480Smckusick 				       hd->scsi_ints, wait);
363*41480Smckusick #endif
364*41480Smckusick 			HIST(ixstart_wait, wait)
365*41480Smckusick 			return (0);
366*41480Smckusick 		}
367*41480Smckusick 		DELAY(1);
368*41480Smckusick 	}
369*41480Smckusick 	HIST(ixstart_wait, wait)
370*41480Smckusick 	return (1);
371*41480Smckusick }
372*41480Smckusick 
373*41480Smckusick static int
374*41480Smckusick ixfer_out(hd, len, buf)
375*41480Smckusick 	volatile register struct scsidevice *hd;
376*41480Smckusick 	int len;
377*41480Smckusick 	register u_char *buf;
378*41480Smckusick {
379*41480Smckusick 	register int wait = scsi_data_wait;
380*41480Smckusick 
381*41480Smckusick 	for (; len > 0; --len) {
382*41480Smckusick 		while (hd->scsi_ssts & SSTS_DREG_FULL) {
383*41480Smckusick 			if (hd->scsi_ints || --wait < 0) {
384*41480Smckusick #ifdef DEBUG
385*41480Smckusick 				if (scsi_debug)
386*41480Smckusick 					printf("ixfer_out fail: l%d i%x w%d\n",
387*41480Smckusick 					       len, hd->scsi_ints, wait);
388*41480Smckusick #endif
389*41480Smckusick 				HIST(ixout_wait, wait)
390*41480Smckusick 				return (len);
391*41480Smckusick 			}
392*41480Smckusick 			DELAY(1);
393*41480Smckusick 		}
394*41480Smckusick 		hd->scsi_dreg = *buf++;
395*41480Smckusick 	}
396*41480Smckusick 	HIST(ixout_wait, wait)
397*41480Smckusick 	return (0);
398*41480Smckusick }
399*41480Smckusick 
400*41480Smckusick static void
401*41480Smckusick ixfer_in(hd, len, buf)
402*41480Smckusick 	volatile register struct scsidevice *hd;
403*41480Smckusick 	int len;
404*41480Smckusick 	register u_char *buf;
405*41480Smckusick {
406*41480Smckusick 	register int wait = scsi_data_wait;
407*41480Smckusick 
408*41480Smckusick 	for (; len > 0; --len) {
409*41480Smckusick 		while (hd->scsi_ssts & SSTS_DREG_EMPTY) {
410*41480Smckusick 			if (hd->scsi_ints || --wait < 0) {
411*41480Smckusick 				while (! (hd->scsi_ssts & SSTS_DREG_EMPTY)) {
412*41480Smckusick 					*buf++ = hd->scsi_dreg;
413*41480Smckusick 					--len;
414*41480Smckusick 				}
415*41480Smckusick #ifdef DEBUG
416*41480Smckusick 				if (scsi_debug)
417*41480Smckusick 					printf("ixfer_in fail: l%d i%x w%d\n",
418*41480Smckusick 					       len, hd->scsi_ints, wait);
419*41480Smckusick #endif
420*41480Smckusick 				HIST(ixin_wait, wait)
421*41480Smckusick 				return;
422*41480Smckusick 			}
423*41480Smckusick 			DELAY(1);
424*41480Smckusick 		}
425*41480Smckusick 		*buf++ = hd->scsi_dreg;
426*41480Smckusick 	}
427*41480Smckusick 	HIST(ixin_wait, wait)
428*41480Smckusick }
429*41480Smckusick 
430*41480Smckusick static int
431*41480Smckusick mxfer_in(hd, len, buf, phase)
432*41480Smckusick 	volatile register struct scsidevice *hd;
433*41480Smckusick 	register int len;
434*41480Smckusick 	register u_char *buf;
435*41480Smckusick 	register u_char phase;
436*41480Smckusick {
437*41480Smckusick 	register int wait = scsi_cmd_wait;
438*41480Smckusick 	register int i;
439*41480Smckusick 
440*41480Smckusick 	hd->scsi_tmod = 0;
441*41480Smckusick 	for (i = 0; i < len; ++i) {
442*41480Smckusick 		/*
443*41480Smckusick 		 * wait for the request line (which says the target
444*41480Smckusick 		 * wants to give us data).  If the phase changes while
445*41480Smckusick 		 * we're waiting, we're done.
446*41480Smckusick 		 */
447*41480Smckusick 		while ((hd->scsi_psns & PSNS_REQ) == 0) {
448*41480Smckusick 			if (--wait < 0) {
449*41480Smckusick 				HIST(mxin_wait, wait)
450*41480Smckusick 				return (-1);
451*41480Smckusick 			}
452*41480Smckusick 			if ((hd->scsi_psns & PHASE) != phase ||
453*41480Smckusick 			    (hd->scsi_ssts & SSTS_INITIATOR) == 0)
454*41480Smckusick 				goto out;
455*41480Smckusick 
456*41480Smckusick 			DELAY(1);
457*41480Smckusick 		}
458*41480Smckusick 		/*
459*41480Smckusick 		 * set ack (which says we're ready for the data, wait for
460*41480Smckusick 		 * req to go away (target says data is available), grab the
461*41480Smckusick 		 * data, then reset ack (say we've got the data).
462*41480Smckusick 		 */
463*41480Smckusick 		hd->scsi_pctl = phase;
464*41480Smckusick 		hd->scsi_scmd = SCMD_SET_ACK;
465*41480Smckusick 		while (hd->scsi_psns & PSNS_REQ) {
466*41480Smckusick 			if (--wait < 0) {
467*41480Smckusick 				HIST(mxin_wait, wait)
468*41480Smckusick 				return (-2);
469*41480Smckusick 			}
470*41480Smckusick 			DELAY(1);
471*41480Smckusick 		}
472*41480Smckusick 		*buf++ = hd->scsi_temp;
473*41480Smckusick 		hd->scsi_scmd = SCMD_RST_ACK;
474*41480Smckusick 		if (hd->scsi_psns & PSNS_ATN)
475*41480Smckusick 			hd->scsi_scmd = SCMD_RST_ATN;
476*41480Smckusick 	}
477*41480Smckusick out:
478*41480Smckusick 	HIST(mxin_wait, wait)
479*41480Smckusick 	return (i);
480*41480Smckusick }
481*41480Smckusick 
482*41480Smckusick /*
483*41480Smckusick  * SCSI 'immediate' command:  issue a command to some SCSI device
484*41480Smckusick  * and get back an 'immediate' response (i.e., do programmed xfer
485*41480Smckusick  * to get the response data).  'cbuf' is a buffer containing a scsi
486*41480Smckusick  * command of length clen bytes.  'buf' is a buffer of length 'len'
487*41480Smckusick  * bytes for data.  The transfer direction is determined by the device
488*41480Smckusick  * (i.e., by the scsi bus data xfer phase).  If 'len' is zero, the
489*41480Smckusick  * command must supply no data.  'xferphase' is the bus phase the
490*41480Smckusick  * caller expects to happen after the command is issued.  It should
491*41480Smckusick  * be one of DATA_IN_PHASE, DATA_OUT_PHASE or STATUS_PHASE.
492*41480Smckusick  */
493*41480Smckusick static int
494*41480Smckusick scsiicmd(hs, target, cbuf, clen, buf, len, xferphase)
495*41480Smckusick 	struct scsi_softc *hs;
496*41480Smckusick 	int target;
497*41480Smckusick 	u_char *cbuf;
498*41480Smckusick 	int clen;
499*41480Smckusick 	u_char *buf;
500*41480Smckusick 	int len;
501*41480Smckusick 	u_char xferphase;
502*41480Smckusick {
503*41480Smckusick 	volatile register struct scsidevice *hd =
504*41480Smckusick 				(struct scsidevice *)hs->sc_hc->hp_addr;
505*41480Smckusick 	u_char phase, ints;
506*41480Smckusick 	register int wait;
507*41480Smckusick 
508*41480Smckusick 	/* select the SCSI bus (it's an error if bus isn't free) */
509*41480Smckusick 	if (issue_select(hd, target, hs->sc_scsi_addr))
510*41480Smckusick 		return (-1);
511*41480Smckusick 	if (wait_for_select(hd))
512*41480Smckusick 		return (-1);
513*41480Smckusick 	/*
514*41480Smckusick 	 * Wait for a phase change (or error) then let the device
515*41480Smckusick 	 * sequence us through the various SCSI phases.
516*41480Smckusick 	 */
517*41480Smckusick 	hs->sc_stat[0] = 0xff;
518*41480Smckusick 	hs->sc_msg[0] = 0xff;
519*41480Smckusick 	phase = CMD_PHASE;
520*41480Smckusick 	while (1) {
521*41480Smckusick 		wait = scsi_cmd_wait;
522*41480Smckusick 		switch (phase) {
523*41480Smckusick 
524*41480Smckusick 		case CMD_PHASE:
525*41480Smckusick 			if (ixfer_start(hd, clen, phase, wait))
526*41480Smckusick 				if (ixfer_out(hd, clen, cbuf))
527*41480Smckusick 					goto abort;
528*41480Smckusick 			phase = xferphase;
529*41480Smckusick 			break;
530*41480Smckusick 
531*41480Smckusick 		case DATA_IN_PHASE:
532*41480Smckusick 			if (len <= 0)
533*41480Smckusick 				goto abort;
534*41480Smckusick 			wait = scsi_data_wait;
535*41480Smckusick 			if (ixfer_start(hd, len, phase, wait) ||
536*41480Smckusick 			    !(hd->scsi_ssts & SSTS_DREG_EMPTY))
537*41480Smckusick 				ixfer_in(hd, len, buf);
538*41480Smckusick 			phase = STATUS_PHASE;
539*41480Smckusick 			break;
540*41480Smckusick 
541*41480Smckusick 		case DATA_OUT_PHASE:
542*41480Smckusick 			if (len <= 0)
543*41480Smckusick 				goto abort;
544*41480Smckusick 			wait = scsi_data_wait;
545*41480Smckusick 			if (ixfer_start(hd, len, phase, wait)) {
546*41480Smckusick 				if (ixfer_out(hd, len, buf))
547*41480Smckusick 					goto abort;
548*41480Smckusick 			}
549*41480Smckusick 			phase = STATUS_PHASE;
550*41480Smckusick 			break;
551*41480Smckusick 
552*41480Smckusick 		case STATUS_PHASE:
553*41480Smckusick 			wait = scsi_data_wait;
554*41480Smckusick 			if (ixfer_start(hd, sizeof(hs->sc_stat), phase, wait) ||
555*41480Smckusick 			    !(hd->scsi_ssts & SSTS_DREG_EMPTY))
556*41480Smckusick 				ixfer_in(hd, sizeof(hs->sc_stat), hs->sc_stat);
557*41480Smckusick 			phase = MESG_IN_PHASE;
558*41480Smckusick 			break;
559*41480Smckusick 
560*41480Smckusick 		case MESG_IN_PHASE:
561*41480Smckusick 			if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait) ||
562*41480Smckusick 			    !(hd->scsi_ssts & SSTS_DREG_EMPTY)) {
563*41480Smckusick 				ixfer_in(hd, sizeof(hs->sc_msg), hs->sc_msg);
564*41480Smckusick 				hd->scsi_scmd = SCMD_RST_ACK;
565*41480Smckusick 			}
566*41480Smckusick 			phase = BUS_FREE_PHASE;
567*41480Smckusick 			break;
568*41480Smckusick 
569*41480Smckusick 		case BUS_FREE_PHASE:
570*41480Smckusick 			goto out;
571*41480Smckusick 
572*41480Smckusick 		default:
573*41480Smckusick 			printf("scsi%d: unexpected phase %d in icmd from %d\n",
574*41480Smckusick 				hs->sc_hc->hp_unit, phase, target);
575*41480Smckusick 			goto abort;
576*41480Smckusick 		}
577*41480Smckusick 		/* wait for last command to complete */
578*41480Smckusick 		while ((ints = hd->scsi_ints) == 0) {
579*41480Smckusick 			if (--wait < 0) {
580*41480Smckusick 				HIST(cxin_wait, wait)
581*41480Smckusick 				goto abort;
582*41480Smckusick 			}
583*41480Smckusick 			DELAY(1);
584*41480Smckusick 		}
585*41480Smckusick 		HIST(cxin_wait, wait)
586*41480Smckusick 		hd->scsi_ints = ints;
587*41480Smckusick 		if (ints & INTS_SRV_REQ)
588*41480Smckusick 			phase = hd->scsi_psns & PHASE;
589*41480Smckusick 		else if (ints & INTS_DISCON)
590*41480Smckusick 			goto out;
591*41480Smckusick 		else if ((ints & INTS_CMD_DONE) == 0) {
592*41480Smckusick 			scsierror(hs, hd, ints);
593*41480Smckusick 			goto abort;
594*41480Smckusick 		}
595*41480Smckusick 	}
596*41480Smckusick abort:
597*41480Smckusick 	scsiabort(hs, hd, "icmd");
598*41480Smckusick out:
599*41480Smckusick 	return (hs->sc_stat[0]);
600*41480Smckusick }
601*41480Smckusick 
602*41480Smckusick /*
603*41480Smckusick  * Finish SCSI xfer command:  After the completion interrupt from
604*41480Smckusick  * a read/write operation, sequence through the final phases in
605*41480Smckusick  * programmed i/o.  This routine is a lot like scsiicmd except we
606*41480Smckusick  * skip (and don't allow) the select, cmd out and data in/out phases.
607*41480Smckusick  */
608*41480Smckusick static void
609*41480Smckusick finishxfer(hs, hd, target)
610*41480Smckusick 	struct scsi_softc *hs;
611*41480Smckusick 	volatile register struct scsidevice *hd;
612*41480Smckusick 	int target;
613*41480Smckusick {
614*41480Smckusick 	u_char phase, ints;
615*41480Smckusick 
616*41480Smckusick 	/*
617*41480Smckusick 	 * We specified padding xfer so we ended with either a phase
618*41480Smckusick 	 * change interrupt (normal case) or an error interrupt (handled
619*41480Smckusick 	 * elsewhere).  Reset the board dma logic then try to get the
620*41480Smckusick 	 * completion status & command done msg.  The reset confuses
621*41480Smckusick 	 * the SPC REQ/ACK logic so we have to do any status/msg input
622*41480Smckusick 	 * operations via 'manual xfer'.
623*41480Smckusick 	 */
624*41480Smckusick 	if (hd->scsi_ssts & SSTS_BUSY) {
625*41480Smckusick 		int wait = scsi_cmd_wait;
626*41480Smckusick 
627*41480Smckusick 		/* wait for dma operation to finish */
628*41480Smckusick 		while (hd->scsi_ssts & SSTS_BUSY) {
629*41480Smckusick 			if (--wait < 0) {
630*41480Smckusick #ifdef DEBUG
631*41480Smckusick 				if (scsi_debug)
632*41480Smckusick 					printf("finishxfer fail: ssts %x\n",
633*41480Smckusick 					       hd->scsi_ssts);
634*41480Smckusick #endif
635*41480Smckusick 				HIST(fxfr_wait, wait)
636*41480Smckusick 				goto abort;
637*41480Smckusick 			}
638*41480Smckusick 		}
639*41480Smckusick 		HIST(fxfr_wait, wait)
640*41480Smckusick 	}
641*41480Smckusick 	hd->scsi_scmd |= SCMD_PROG_XFR;
642*41480Smckusick 	hd->scsi_sctl |= SCTL_CTRLRST;
643*41480Smckusick 	DELAY(1);
644*41480Smckusick 	hd->scsi_sctl &=~ SCTL_CTRLRST;
645*41480Smckusick 	hd->scsi_hconf = 0;
646*41480Smckusick 	hs->sc_stat[0] = 0xff;
647*41480Smckusick 	hs->sc_msg[0] = 0xff;
648*41480Smckusick 	hd->scsi_csr = 0;
649*41480Smckusick 	hd->scsi_ints = ints = hd->scsi_ints;
650*41480Smckusick 	while (1) {
651*41480Smckusick 		phase = hd->scsi_psns & PHASE;
652*41480Smckusick 		switch (phase) {
653*41480Smckusick 
654*41480Smckusick 		case STATUS_PHASE:
655*41480Smckusick 			if (mxfer_in(hd, sizeof(hs->sc_stat), hs->sc_stat,
656*41480Smckusick 				     phase) <= 0)
657*41480Smckusick 				goto abort;
658*41480Smckusick 			break;
659*41480Smckusick 
660*41480Smckusick 		case MESG_IN_PHASE:
661*41480Smckusick 			if (mxfer_in(hd, sizeof(hs->sc_msg), hs->sc_msg,
662*41480Smckusick 				     phase) < 0)
663*41480Smckusick 				goto abort;
664*41480Smckusick 			break;
665*41480Smckusick 
666*41480Smckusick 		case BUS_FREE_PHASE:
667*41480Smckusick 			return;
668*41480Smckusick 
669*41480Smckusick 		default:
670*41480Smckusick 			printf("scsi%d: unexpected phase %d in finishxfer from %d\n",
671*41480Smckusick 				hs->sc_hc->hp_unit, phase, target);
672*41480Smckusick 			goto abort;
673*41480Smckusick 		}
674*41480Smckusick 		if (ints = hd->scsi_ints) {
675*41480Smckusick 			hd->scsi_ints = ints;
676*41480Smckusick 			if (ints & INTS_DISCON)
677*41480Smckusick 				return;
678*41480Smckusick 			else if (ints & ~(INTS_SRV_REQ|INTS_CMD_DONE)) {
679*41480Smckusick 				scsierror(hs, hd, ints);
680*41480Smckusick 				break;
681*41480Smckusick 			}
682*41480Smckusick 		}
683*41480Smckusick 		if ((hd->scsi_ssts & SSTS_INITIATOR) == 0)
684*41480Smckusick 			return;
685*41480Smckusick 	}
686*41480Smckusick abort:
687*41480Smckusick 	scsiabort(hs, hd, "finishxfer");
688*41480Smckusick 	hs->sc_stat[0] = 0xfe;
689*41480Smckusick }
690*41480Smckusick 
691*41480Smckusick int
692*41480Smckusick scsi_test_unit_rdy(ctlr, slave, unit)
693*41480Smckusick 	int ctlr, slave, unit;
694*41480Smckusick {
695*41480Smckusick 	register struct scsi_softc *hs = &scsi_softc[ctlr];
696*41480Smckusick 	static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };
697*41480Smckusick 
698*41480Smckusick 	cdb.lun = unit;
699*41480Smckusick 	return (scsiicmd(hs, slave, &cdb, sizeof(cdb), (u_char *)0, 0,
700*41480Smckusick 			 STATUS_PHASE));
701*41480Smckusick }
702*41480Smckusick 
703*41480Smckusick int
704*41480Smckusick scsi_request_sense(ctlr, slave, unit, buf, len)
705*41480Smckusick 	int ctlr, slave, unit;
706*41480Smckusick 	u_char *buf;
707*41480Smckusick 	unsigned len;
708*41480Smckusick {
709*41480Smckusick 	register struct scsi_softc *hs = &scsi_softc[ctlr];
710*41480Smckusick 	static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE };
711*41480Smckusick 
712*41480Smckusick 	cdb.lun = unit;
713*41480Smckusick 	cdb.len = len;
714*41480Smckusick 	return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE));
715*41480Smckusick }
716*41480Smckusick 
717*41480Smckusick int
718*41480Smckusick scsi_immed_command(ctlr, slave, unit, cdb, buf, len, rd)
719*41480Smckusick 	int ctlr, slave, unit;
720*41480Smckusick 	struct scsi_fmt_cdb *cdb;
721*41480Smckusick 	u_char *buf;
722*41480Smckusick 	unsigned len;
723*41480Smckusick {
724*41480Smckusick 	register struct scsi_softc *hs = &scsi_softc[ctlr];
725*41480Smckusick 
726*41480Smckusick 	cdb->cdb[1] |= unit << 5;
727*41480Smckusick 	return (scsiicmd(hs, slave, cdb->cdb, cdb->len, buf, len,
728*41480Smckusick 			 rd != 0? DATA_IN_PHASE : DATA_OUT_PHASE));
729*41480Smckusick }
730*41480Smckusick 
731*41480Smckusick /*
732*41480Smckusick  * The following routines are test-and-transfer i/o versions of read/write
733*41480Smckusick  * for things like reading disk labels and writing core dumps.  The
734*41480Smckusick  * routine scsigo should be used for normal data transfers, NOT these
735*41480Smckusick  * routines.
736*41480Smckusick  */
737*41480Smckusick int
738*41480Smckusick scsi_tt_read(ctlr, slave, unit, buf, len, blk, bshift)
739*41480Smckusick 	int ctlr, slave, unit;
740*41480Smckusick 	u_char *buf;
741*41480Smckusick 	u_int len;
742*41480Smckusick 	daddr_t blk;
743*41480Smckusick 	int bshift;
744*41480Smckusick {
745*41480Smckusick 	register struct scsi_softc *hs = &scsi_softc[ctlr];
746*41480Smckusick 	struct scsi_cdb10 cdb;
747*41480Smckusick 	int stat;
748*41480Smckusick 	int old_wait = scsi_data_wait;
749*41480Smckusick 
750*41480Smckusick 	scsi_data_wait = 300000;
751*41480Smckusick 	bzero(&cdb, sizeof(cdb));
752*41480Smckusick 	cdb.cmd = CMD_READ_EXT;
753*41480Smckusick 	cdb.lun = unit;
754*41480Smckusick 	blk >>= bshift;
755*41480Smckusick 	cdb.lbah = blk >> 24;
756*41480Smckusick 	cdb.lbahm = blk >> 16;
757*41480Smckusick 	cdb.lbalm = blk >> 8;
758*41480Smckusick 	cdb.lbal = blk;
759*41480Smckusick 	cdb.lenh = len >> (8 + DEV_BSHIFT + bshift);
760*41480Smckusick 	cdb.lenl = len >> (DEV_BSHIFT + bshift);
761*41480Smckusick 	stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE);
762*41480Smckusick 	scsi_data_wait = old_wait;
763*41480Smckusick 	return (stat);
764*41480Smckusick }
765*41480Smckusick 
766*41480Smckusick int
767*41480Smckusick scsi_tt_write(ctlr, slave, unit, buf, len, blk, bshift)
768*41480Smckusick 	int ctlr, slave, unit;
769*41480Smckusick 	u_char *buf;
770*41480Smckusick 	u_int len;
771*41480Smckusick 	daddr_t blk;
772*41480Smckusick 	int bshift;
773*41480Smckusick {
774*41480Smckusick 	register struct scsi_softc *hs = &scsi_softc[ctlr];
775*41480Smckusick 	struct scsi_cdb10 cdb;
776*41480Smckusick 	int stat;
777*41480Smckusick 	int old_wait = scsi_data_wait;
778*41480Smckusick 
779*41480Smckusick 	scsi_data_wait = 300000;
780*41480Smckusick 
781*41480Smckusick 	bzero(&cdb, sizeof(cdb));
782*41480Smckusick 	cdb.cmd = CMD_WRITE_EXT;
783*41480Smckusick 	cdb.lun = unit;
784*41480Smckusick 	blk >>= bshift;
785*41480Smckusick 	cdb.lbah = blk >> 24;
786*41480Smckusick 	cdb.lbahm = blk >> 16;
787*41480Smckusick 	cdb.lbalm = blk >> 8;
788*41480Smckusick 	cdb.lbal = blk;
789*41480Smckusick 	cdb.lenh = len >> (8 + DEV_BSHIFT + bshift);
790*41480Smckusick 	cdb.lenl = len >> (DEV_BSHIFT + bshift);
791*41480Smckusick 	stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_OUT_PHASE);
792*41480Smckusick 	scsi_data_wait = old_wait;
793*41480Smckusick 	return (stat);
794*41480Smckusick }
795*41480Smckusick 
796*41480Smckusick 
797*41480Smckusick int
798*41480Smckusick scsireq(dq)
799*41480Smckusick 	register struct devqueue *dq;
800*41480Smckusick {
801*41480Smckusick 	register struct devqueue *hq;
802*41480Smckusick 
803*41480Smckusick 	hq = &scsi_softc[dq->dq_ctlr].sc_sq;
804*41480Smckusick 	insque(dq, hq->dq_back);
805*41480Smckusick 	if (dq->dq_back == hq)
806*41480Smckusick 		return(1);
807*41480Smckusick 	return(0);
808*41480Smckusick }
809*41480Smckusick 
810*41480Smckusick int
811*41480Smckusick scsiustart(unit)
812*41480Smckusick 	int unit;
813*41480Smckusick {
814*41480Smckusick 	register struct scsi_softc *hs = &scsi_softc[unit];
815*41480Smckusick 
816*41480Smckusick 	hs->sc_dq.dq_ctlr = DMA0 | DMA1;
817*41480Smckusick 	if (dmareq(&hs->sc_dq))
818*41480Smckusick 		return(1);
819*41480Smckusick 	return(0);
820*41480Smckusick }
821*41480Smckusick 
822*41480Smckusick void
823*41480Smckusick scsistart(unit)
824*41480Smckusick 	int unit;
825*41480Smckusick {
826*41480Smckusick 	register struct devqueue *dq;
827*41480Smckusick 
828*41480Smckusick 	dq = scsi_softc[unit].sc_sq.dq_forw;
829*41480Smckusick 	(dq->dq_driver->d_go)(dq->dq_unit);
830*41480Smckusick }
831*41480Smckusick 
832*41480Smckusick int
833*41480Smckusick scsigo(ctlr, slave, unit, bp, cdb, pad)
834*41480Smckusick 	int ctlr, slave, unit;
835*41480Smckusick 	struct buf *bp;
836*41480Smckusick 	struct scsi_fmt_cdb *cdb;
837*41480Smckusick 	int pad;
838*41480Smckusick {
839*41480Smckusick 	register struct scsi_softc *hs = &scsi_softc[ctlr];
840*41480Smckusick 	volatile register struct scsidevice *hd =
841*41480Smckusick 				(struct scsidevice *)hs->sc_hc->hp_addr;
842*41480Smckusick 	int i, dmaflags;
843*41480Smckusick 	u_char phase, ints, cmd;
844*41480Smckusick 
845*41480Smckusick 	cdb->cdb[1] |= unit << 5;
846*41480Smckusick 
847*41480Smckusick 	/* select the SCSI bus (it's an error if bus isn't free) */
848*41480Smckusick 	if (issue_select(hd, slave, hs->sc_scsi_addr) || wait_for_select(hd)) {
849*41480Smckusick 		dmafree(&hs->sc_dq);
850*41480Smckusick 		return (1);
851*41480Smckusick 	}
852*41480Smckusick 	/*
853*41480Smckusick 	 * Wait for a phase change (or error) then let the device
854*41480Smckusick 	 * sequence us through command phase (we may have to take
855*41480Smckusick 	 * a msg in/out before doing the command).  If the disk has
856*41480Smckusick 	 * to do a seek, it may be a long time until we get a change
857*41480Smckusick 	 * to data phase so, in the absense of an explicit phase
858*41480Smckusick 	 * change, we assume data phase will be coming up and tell
859*41480Smckusick 	 * the SPC to start a transfer whenever it does.  We'll get
860*41480Smckusick 	 * a service required interrupt later if this assumption is
861*41480Smckusick 	 * wrong.  Otherwise we'll get a service required int when
862*41480Smckusick 	 * the transfer changes to status phase.
863*41480Smckusick 	 */
864*41480Smckusick 	phase = CMD_PHASE;
865*41480Smckusick 	while (1) {
866*41480Smckusick 		register int wait = scsi_cmd_wait;
867*41480Smckusick 
868*41480Smckusick 		switch (phase) {
869*41480Smckusick 
870*41480Smckusick 		case CMD_PHASE:
871*41480Smckusick 			if (ixfer_start(hd, cdb->len, phase, wait))
872*41480Smckusick 				if (ixfer_out(hd, cdb->len, cdb->cdb))
873*41480Smckusick 					goto abort;
874*41480Smckusick 			break;
875*41480Smckusick 
876*41480Smckusick 		case MESG_IN_PHASE:
877*41480Smckusick 			if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait)||
878*41480Smckusick 			    !(hd->scsi_ssts & SSTS_DREG_EMPTY)) {
879*41480Smckusick 				ixfer_in(hd, sizeof(hs->sc_msg), hs->sc_msg);
880*41480Smckusick 				hd->scsi_scmd = SCMD_RST_ACK;
881*41480Smckusick 			}
882*41480Smckusick 			phase = BUS_FREE_PHASE;
883*41480Smckusick 			break;
884*41480Smckusick 
885*41480Smckusick 		case DATA_IN_PHASE:
886*41480Smckusick 		case DATA_OUT_PHASE:
887*41480Smckusick 			goto out;
888*41480Smckusick 
889*41480Smckusick 		default:
890*41480Smckusick 			printf("scsi%d: unexpected phase %d in go from %d\n",
891*41480Smckusick 				hs->sc_hc->hp_unit, phase, slave);
892*41480Smckusick 			goto abort;
893*41480Smckusick 		}
894*41480Smckusick 		while ((ints = hd->scsi_ints) == 0) {
895*41480Smckusick 			if (--wait < 0) {
896*41480Smckusick 				HIST(sgo_wait, wait)
897*41480Smckusick 				goto abort;
898*41480Smckusick 			}
899*41480Smckusick 			DELAY(1);
900*41480Smckusick 		}
901*41480Smckusick 		HIST(sgo_wait, wait)
902*41480Smckusick 		hd->scsi_ints = ints;
903*41480Smckusick 		if (ints & INTS_SRV_REQ)
904*41480Smckusick 			phase = hd->scsi_psns & PHASE;
905*41480Smckusick 		else if (ints & INTS_CMD_DONE)
906*41480Smckusick 			goto out;
907*41480Smckusick 		else {
908*41480Smckusick 			scsierror(hs, hd, ints);
909*41480Smckusick 			goto abort;
910*41480Smckusick 		}
911*41480Smckusick 	}
912*41480Smckusick out:
913*41480Smckusick 	/*
914*41480Smckusick 	 * Reset the card dma logic, setup the dma channel then
915*41480Smckusick 	 * get the dio part of the card set for a dma xfer.
916*41480Smckusick 	 */
917*41480Smckusick 	hd->scsi_hconf = 0;
918*41480Smckusick 	cmd = CSR_IE | (CSR_DE0 << hs->sc_dq.dq_ctlr);
919*41480Smckusick 	dmaflags = DMAGO_NOINT;
920*41480Smckusick 	if (bp->b_flags & B_READ)
921*41480Smckusick 		dmaflags |= DMAGO_READ;
922*41480Smckusick 	if ((hs->sc_flags & SCSI_DMA32) &&
923*41480Smckusick 	    ((int)bp->b_un.b_addr & 3) == 0 && (bp->b_bcount & 3) == 0) {
924*41480Smckusick 		cmd |= CSR_DMA32;
925*41480Smckusick 		dmaflags |= DMAGO_LWORD;
926*41480Smckusick 	} else
927*41480Smckusick 		dmaflags |= DMAGO_WORD;
928*41480Smckusick 	dmago(hs->sc_dq.dq_ctlr, bp->b_un.b_addr, bp->b_bcount, dmaflags);
929*41480Smckusick 
930*41480Smckusick 	if (bp->b_flags & B_READ) {
931*41480Smckusick 		cmd |= CSR_DMAIN;
932*41480Smckusick 		phase = DATA_IN_PHASE;
933*41480Smckusick 	} else
934*41480Smckusick 		phase = DATA_OUT_PHASE;
935*41480Smckusick 	hd->scsi_csr = cmd;
936*41480Smckusick 	/*
937*41480Smckusick 	 * Setup the SPC for the transfer.  We don't want to take
938*41480Smckusick 	 * first a command complete then a service required interrupt
939*41480Smckusick 	 * at the end of the transfer so we try to disable the cmd
940*41480Smckusick 	 * complete by setting the transfer counter to more bytes
941*41480Smckusick 	 * than we expect.  (XXX - This strategy may have to be
942*41480Smckusick 	 * modified to deal with devices that return variable length
943*41480Smckusick 	 * blocks, e.g., some tape drives.)
944*41480Smckusick 	 */
945*41480Smckusick 	cmd = SCMD_XFR;
946*41480Smckusick 	i = (unsigned)bp->b_bcount;
947*41480Smckusick 	if (pad) {
948*41480Smckusick 		cmd |= SCMD_PAD;
949*41480Smckusick 		/*
950*41480Smckusick 		 * XXX - If we don't do this, the last 2 or 4 bytes
951*41480Smckusick 		 * (depending on word/lword DMA) of a read get trashed.
952*41480Smckusick 		 * It looks like it is necessary for the DMA to complete
953*41480Smckusick 		 * before the SPC goes into "pad mode"???  Note: if we
954*41480Smckusick 		 * also do this on a write, the request never completes.
955*41480Smckusick 		 */
956*41480Smckusick 		if (bp->b_flags & B_READ)
957*41480Smckusick 			i += 2;
958*41480Smckusick #ifdef DEBUG
959*41480Smckusick 		hs->sc_flags |= SCSI_PAD;
960*41480Smckusick 		if (i & 1)
961*41480Smckusick 			printf("scsi%d: odd byte count: %d bytes @ %d\n",
962*41480Smckusick 				ctlr, i, bp->b_cylin);
963*41480Smckusick #endif
964*41480Smckusick 	} else
965*41480Smckusick 		i += 4;
966*41480Smckusick 	hd->scsi_tch = i >> 16;
967*41480Smckusick 	hd->scsi_tcm = i >> 8;
968*41480Smckusick 	hd->scsi_tcl = i;
969*41480Smckusick 	hd->scsi_pctl = phase;
970*41480Smckusick 	hd->scsi_tmod = 0;
971*41480Smckusick 	hd->scsi_scmd = cmd;
972*41480Smckusick 	hs->sc_flags |= SCSI_IO;
973*41480Smckusick 	return (0);
974*41480Smckusick abort:
975*41480Smckusick 	scsiabort(hs, hd, "go");
976*41480Smckusick 	dmafree(&hs->sc_dq);
977*41480Smckusick 	return (1);
978*41480Smckusick }
979*41480Smckusick 
980*41480Smckusick void
981*41480Smckusick scsidone(unit)
982*41480Smckusick 	register int unit;
983*41480Smckusick {
984*41480Smckusick 	volatile register struct scsidevice *hd =
985*41480Smckusick 			(struct scsidevice *)scsi_softc[unit].sc_hc->hp_addr;
986*41480Smckusick 
987*41480Smckusick 	/* dma operation is done -- turn off card dma */
988*41480Smckusick 	hd->scsi_csr &=~ (CSR_DE1|CSR_DE0);
989*41480Smckusick }
990*41480Smckusick 
991*41480Smckusick int
992*41480Smckusick scsiintr(unit)
993*41480Smckusick 	register int unit;
994*41480Smckusick {
995*41480Smckusick 	register struct scsi_softc *hs = &scsi_softc[unit];
996*41480Smckusick 	volatile register struct scsidevice *hd =
997*41480Smckusick 				(struct scsidevice *)hs->sc_hc->hp_addr;
998*41480Smckusick 	register u_char ints;
999*41480Smckusick 	register struct devqueue *dq;
1000*41480Smckusick 
1001*41480Smckusick 	if ((hd->scsi_csr & (CSR_IE|CSR_IR)) != (CSR_IE|CSR_IR))
1002*41480Smckusick 		return (0);
1003*41480Smckusick 
1004*41480Smckusick 	ints = hd->scsi_ints;
1005*41480Smckusick 	if ((ints & INTS_SRV_REQ) && (hs->sc_flags & SCSI_IO)) {
1006*41480Smckusick 		/*
1007*41480Smckusick 		 * this should be the normal i/o completion case.
1008*41480Smckusick 		 * get the status & cmd complete msg then let the
1009*41480Smckusick 		 * device driver look at what happened.
1010*41480Smckusick 		 */
1011*41480Smckusick #ifdef DEBUG
1012*41480Smckusick 		int len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) |
1013*41480Smckusick 			  hd->scsi_tcl;
1014*41480Smckusick 		if (!(hs->sc_flags & SCSI_PAD))
1015*41480Smckusick 			len -= 4;
1016*41480Smckusick 		if (len)
1017*41480Smckusick 			printf("scsi%d: transfer length error %d\n", unit, len);
1018*41480Smckusick 		hs->sc_flags &=~ SCSI_PAD;
1019*41480Smckusick #endif
1020*41480Smckusick 		dq = hs->sc_sq.dq_forw;
1021*41480Smckusick 		finishxfer(hs, hd, dq->dq_unit);
1022*41480Smckusick 		hs->sc_flags &=~ SCSI_IO;
1023*41480Smckusick 		dmafree(&hs->sc_dq);
1024*41480Smckusick 		(dq->dq_driver->d_intr)(dq->dq_unit, hs->sc_stat[0]);
1025*41480Smckusick 	} else {
1026*41480Smckusick 		/* Something unexpected happened -- deal with it. */
1027*41480Smckusick 		hd->scsi_ints = ints;
1028*41480Smckusick 		hd->scsi_csr = 0;
1029*41480Smckusick 		scsierror(hs, hd, ints);
1030*41480Smckusick 		scsiabort(hs, hd, "intr");
1031*41480Smckusick 		if (hs->sc_flags & SCSI_IO) {
1032*41480Smckusick 			hs->sc_flags &=~ SCSI_IO;
1033*41480Smckusick 			dmafree(&hs->sc_dq);
1034*41480Smckusick 			dq = hs->sc_sq.dq_forw;
1035*41480Smckusick 			(dq->dq_driver->d_intr)(dq->dq_unit, -1);
1036*41480Smckusick 		}
1037*41480Smckusick 	}
1038*41480Smckusick 	return(1);
1039*41480Smckusick }
1040*41480Smckusick 
1041*41480Smckusick void
1042*41480Smckusick scsifree(dq)
1043*41480Smckusick 	register struct devqueue *dq;
1044*41480Smckusick {
1045*41480Smckusick 	register struct devqueue *hq;
1046*41480Smckusick 
1047*41480Smckusick 	hq = &scsi_softc[dq->dq_ctlr].sc_sq;
1048*41480Smckusick 	remque(dq);
1049*41480Smckusick 	if ((dq = hq->dq_forw) != hq)
1050*41480Smckusick 		(dq->dq_driver->d_start)(dq->dq_unit);
1051*41480Smckusick }
1052*41480Smckusick #endif
1053