xref: /csrg-svn/sys/hp300/stand/scsi.c (revision 41488)
1*41488Smckusick /*
2*41488Smckusick  * Copyright (c) 1988 University of Utah.
3*41488Smckusick  * Copyright (c) 1990 The Regents of the University of California.
4*41488Smckusick  * All rights reserved.
5*41488Smckusick  *
6*41488Smckusick  * This code is derived from software contributed to Berkeley by
7*41488Smckusick  * Van Jacobson of Lawrence Berkeley Laboratory and the Systems
8*41488Smckusick  * Programming Group of the University of Utah Computer Science Department.
9*41488Smckusick  *
10*41488Smckusick  * %sccs.include.redist.c%
11*41488Smckusick  *
12*41488Smckusick  * from: Utah $Hdr: scsi.c 1.3 90/01/27$
13*41488Smckusick  *
14*41488Smckusick  *	@(#)scsi.c	7.1 (Berkeley) 05/08/90
15*41488Smckusick  */
16*41488Smckusick 
17*41488Smckusick /*
18*41488Smckusick  * SCSI bus driver for standalone programs.
19*41488Smckusick  */
20*41488Smckusick 
21*41488Smckusick #include "../sys/types.h"
22*41488Smckusick #include "../sys/reboot.h"
23*41488Smckusick #include "../hpdev/device.h"
24*41488Smckusick #include "../hpdev/scsireg.h"
25*41488Smckusick #include "scsivar.h"
26*41488Smckusick 
27*41488Smckusick #include "saio.h"
28*41488Smckusick #include "samachdep.h"
29*41488Smckusick 
30*41488Smckusick struct	scsi_softc scsi_softc[NSCSI];
31*41488Smckusick 
32*41488Smckusick #define	scsiunit(x)	((x) >> 3)
33*41488Smckusick #define	scsislave(x)	((x) & 7)
34*41488Smckusick 
35*41488Smckusick void scsireset();
36*41488Smckusick int scsi_cmd_wait = 500;
37*41488Smckusick int scsi_data_wait = 300000;
38*41488Smckusick 
39*41488Smckusick scsiinit()
40*41488Smckusick {
41*41488Smckusick 	extern struct hp_hw sc_table[];
42*41488Smckusick 	register struct hp_hw *hw;
43*41488Smckusick 	register struct scsi_softc *hs;
44*41488Smckusick 	register int i, addr;
45*41488Smckusick 	static int first = 1;
46*41488Smckusick 
47*41488Smckusick 	i = 0;
48*41488Smckusick 	for (hw = sc_table; i < NSCSI && hw < &sc_table[MAX_CTLR]; hw++) {
49*41488Smckusick 		if (hw->hw_type != SCSI)
50*41488Smckusick 			continue;
51*41488Smckusick 		hs = &scsi_softc[i];
52*41488Smckusick 		hs->sc_addr = hw->hw_addr;
53*41488Smckusick 		scsireset(i);
54*41488Smckusick 		if (howto & RB_ASKNAME)
55*41488Smckusick 			printf("scsi%d at sc%d\n", i, hw->hw_sc);
56*41488Smckusick 		/*
57*41488Smckusick 		 * Adjust devtype on first call.  This routine assumes that
58*41488Smckusick 		 * adaptor is in the high byte of devtype.
59*41488Smckusick 		 */
60*41488Smckusick 		if (first && ((devtype >> 24) & 0xff) == hw->hw_sc) {
61*41488Smckusick 			devtype = (devtype & 0x00ffffff) | (i << 24);
62*41488Smckusick 			first = 0;
63*41488Smckusick 		}
64*41488Smckusick 		hs->sc_alive = 1;
65*41488Smckusick 		i++;
66*41488Smckusick 	}
67*41488Smckusick }
68*41488Smckusick 
69*41488Smckusick scsialive(unit)
70*41488Smckusick 	register int unit;
71*41488Smckusick {
72*41488Smckusick 	unit = scsiunit(unit);
73*41488Smckusick 	if (unit >= NSCSI || scsi_softc[unit].sc_alive == 0)
74*41488Smckusick 		return (0);
75*41488Smckusick 	return (1);
76*41488Smckusick }
77*41488Smckusick 
78*41488Smckusick void
79*41488Smckusick scsireset(unit)
80*41488Smckusick 	register int unit;
81*41488Smckusick {
82*41488Smckusick 	volatile register struct scsidevice *hd;
83*41488Smckusick 	register struct scsi_softc *hs;
84*41488Smckusick 	u_int i;
85*41488Smckusick 
86*41488Smckusick 	unit = scsiunit(unit);
87*41488Smckusick 	hs = &scsi_softc[unit];
88*41488Smckusick 	hd = (struct scsidevice *)hs->sc_addr;
89*41488Smckusick 	hd->scsi_id = 0xFF;
90*41488Smckusick 	DELAY(100);
91*41488Smckusick 	/*
92*41488Smckusick 	 * Disable interrupts then reset the FUJI chip.
93*41488Smckusick 	 */
94*41488Smckusick 	hd->scsi_csr  = 0;
95*41488Smckusick 	hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST;
96*41488Smckusick 	hd->scsi_scmd = 0;
97*41488Smckusick 	hd->scsi_tmod = 0;
98*41488Smckusick 	hd->scsi_pctl = 0;
99*41488Smckusick 	hd->scsi_temp = 0;
100*41488Smckusick 	hd->scsi_tch  = 0;
101*41488Smckusick 	hd->scsi_tcm  = 0;
102*41488Smckusick 	hd->scsi_tcl  = 0;
103*41488Smckusick 	hd->scsi_ints = 0;
104*41488Smckusick 
105*41488Smckusick 	/*
106*41488Smckusick 	 * Configure the FUJI chip with its SCSI address, all
107*41488Smckusick 	 * interrupts enabled & appropriate parity.
108*41488Smckusick 	 */
109*41488Smckusick 	i = (~hd->scsi_hconf) & 0x7;
110*41488Smckusick 	hs->sc_scsi_addr = 1 << i;
111*41488Smckusick 	hd->scsi_bdid = i;
112*41488Smckusick 	if (hd->scsi_hconf & HCONF_PARITY)
113*41488Smckusick 		hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB |
114*41488Smckusick 				SCTL_SEL_ENAB | SCTL_RESEL_ENAB |
115*41488Smckusick 				SCTL_INTR_ENAB | SCTL_PARITY_ENAB;
116*41488Smckusick 	else
117*41488Smckusick 		hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB |
118*41488Smckusick 				SCTL_SEL_ENAB | SCTL_RESEL_ENAB |
119*41488Smckusick 				SCTL_INTR_ENAB;
120*41488Smckusick 	hd->scsi_sctl &=~ SCTL_DISABLE;
121*41488Smckusick }
122*41488Smckusick 
123*41488Smckusick 
124*41488Smckusick int
125*41488Smckusick scsiabort(hs, hd)
126*41488Smckusick 	register struct scsi_softc *hs;
127*41488Smckusick 	volatile register struct scsidevice *hd;
128*41488Smckusick {
129*41488Smckusick 	printf("scsi error: scsiabort\n");
130*41488Smckusick 	return (0);
131*41488Smckusick }
132*41488Smckusick 
133*41488Smckusick static int
134*41488Smckusick issue_select(hd, target, our_addr)
135*41488Smckusick 	volatile register struct scsidevice *hd;
136*41488Smckusick 	u_char target, our_addr;
137*41488Smckusick {
138*41488Smckusick 	if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY))
139*41488Smckusick 		return (1);
140*41488Smckusick 
141*41488Smckusick 	if (hd->scsi_ints & INTS_DISCON)
142*41488Smckusick 		hd->scsi_ints = INTS_DISCON;
143*41488Smckusick 
144*41488Smckusick 	hd->scsi_pctl = 0;
145*41488Smckusick 	hd->scsi_temp = (1 << target) | our_addr;
146*41488Smckusick 	/* select timeout is hardcoded to 2ms */
147*41488Smckusick 	hd->scsi_tch = 0;
148*41488Smckusick 	hd->scsi_tcm = 32;
149*41488Smckusick 	hd->scsi_tcl = 4;
150*41488Smckusick 
151*41488Smckusick 	hd->scsi_scmd = SCMD_SELECT;
152*41488Smckusick 	return (0);
153*41488Smckusick }
154*41488Smckusick 
155*41488Smckusick static int
156*41488Smckusick wait_for_select(hd)
157*41488Smckusick 	volatile register struct scsidevice *hd;
158*41488Smckusick {
159*41488Smckusick 	u_char ints;
160*41488Smckusick 
161*41488Smckusick 	while ((ints = hd->scsi_ints) == 0)
162*41488Smckusick 		DELAY(1);
163*41488Smckusick 	hd->scsi_ints = ints;
164*41488Smckusick 	return (!(hd->scsi_ssts & SSTS_INITIATOR));
165*41488Smckusick }
166*41488Smckusick 
167*41488Smckusick static int
168*41488Smckusick ixfer_start(hd, len, phase, wait)
169*41488Smckusick 	volatile register struct scsidevice *hd;
170*41488Smckusick 	int len;
171*41488Smckusick 	u_char phase;
172*41488Smckusick 	register int wait;
173*41488Smckusick {
174*41488Smckusick 
175*41488Smckusick 	hd->scsi_tch = len >> 16;
176*41488Smckusick 	hd->scsi_tcm = len >> 8;
177*41488Smckusick 	hd->scsi_tcl = len;
178*41488Smckusick 	hd->scsi_pctl = phase;
179*41488Smckusick 	hd->scsi_tmod = 0; /*XXX*/
180*41488Smckusick 	hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
181*41488Smckusick 
182*41488Smckusick 	/* wait for xfer to start or svc_req interrupt */
183*41488Smckusick 	while ((hd->scsi_ssts & SSTS_BUSY) == 0) {
184*41488Smckusick 		if (hd->scsi_ints || --wait < 0)
185*41488Smckusick 			return (0);
186*41488Smckusick 		DELAY(1);
187*41488Smckusick 	}
188*41488Smckusick 	return (1);
189*41488Smckusick }
190*41488Smckusick 
191*41488Smckusick static int
192*41488Smckusick ixfer_out(hd, len, buf)
193*41488Smckusick 	volatile register struct scsidevice *hd;
194*41488Smckusick 	int len;
195*41488Smckusick 	register u_char *buf;
196*41488Smckusick {
197*41488Smckusick 	register int wait = scsi_data_wait;
198*41488Smckusick 
199*41488Smckusick 	for (; len > 0; --len) {
200*41488Smckusick 		while (hd->scsi_ssts & SSTS_DREG_FULL) {
201*41488Smckusick 			if (hd->scsi_ints || --wait < 0)
202*41488Smckusick 				return (len);
203*41488Smckusick 			DELAY(1);
204*41488Smckusick 		}
205*41488Smckusick 		hd->scsi_dreg = *buf++;
206*41488Smckusick 	}
207*41488Smckusick 	return (0);
208*41488Smckusick }
209*41488Smckusick 
210*41488Smckusick static int
211*41488Smckusick ixfer_in(hd, len, buf)
212*41488Smckusick 	volatile register struct scsidevice *hd;
213*41488Smckusick 	int len;
214*41488Smckusick 	register u_char *buf;
215*41488Smckusick {
216*41488Smckusick 	register int wait = scsi_data_wait;
217*41488Smckusick 
218*41488Smckusick 	for (; len > 0; --len) {
219*41488Smckusick 		while (hd->scsi_ssts & SSTS_DREG_EMPTY) {
220*41488Smckusick 			if (hd->scsi_ints || --wait < 0) {
221*41488Smckusick 				while (! (hd->scsi_ssts & SSTS_DREG_EMPTY)) {
222*41488Smckusick 					*buf++ = hd->scsi_dreg;
223*41488Smckusick 					--len;
224*41488Smckusick 				}
225*41488Smckusick 				return (len);
226*41488Smckusick 			}
227*41488Smckusick 			DELAY(1);
228*41488Smckusick 		}
229*41488Smckusick 		*buf++ = hd->scsi_dreg;
230*41488Smckusick 	}
231*41488Smckusick 	return (len);
232*41488Smckusick }
233*41488Smckusick 
234*41488Smckusick static int
235*41488Smckusick scsiicmd(hs, target, cbuf, clen, buf, len, xferphase)
236*41488Smckusick 	struct scsi_softc *hs;
237*41488Smckusick 	int target;
238*41488Smckusick 	u_char *cbuf;
239*41488Smckusick 	int clen;
240*41488Smckusick 	u_char *buf;
241*41488Smckusick 	int len;
242*41488Smckusick 	u_char xferphase;
243*41488Smckusick {
244*41488Smckusick 	volatile register struct scsidevice *hd =
245*41488Smckusick 				(struct scsidevice *)hs->sc_addr;
246*41488Smckusick 	int i;
247*41488Smckusick 	u_char phase, ints;
248*41488Smckusick 	register int wait;
249*41488Smckusick 
250*41488Smckusick 	/* select the SCSI bus (it's an error if bus isn't free) */
251*41488Smckusick 	if (issue_select(hd, target, hs->sc_scsi_addr))
252*41488Smckusick 		return (0);
253*41488Smckusick 	if (wait_for_select(hd))
254*41488Smckusick 		return (0);
255*41488Smckusick 	/*
256*41488Smckusick 	 * Wait for a phase change (or error) then let the device
257*41488Smckusick 	 * sequence us through the various SCSI phases.
258*41488Smckusick 	 */
259*41488Smckusick 	phase = CMD_PHASE;
260*41488Smckusick 	while (1) {
261*41488Smckusick 		wait = scsi_cmd_wait;
262*41488Smckusick 		switch (phase) {
263*41488Smckusick 
264*41488Smckusick 		case CMD_PHASE:
265*41488Smckusick 			if (ixfer_start(hd, clen, phase, wait))
266*41488Smckusick 				if (ixfer_out(hd, clen, cbuf))
267*41488Smckusick 					goto abort;
268*41488Smckusick 			phase = xferphase;
269*41488Smckusick 			break;
270*41488Smckusick 
271*41488Smckusick 		case DATA_IN_PHASE:
272*41488Smckusick 			if (len <= 0)
273*41488Smckusick 				goto abort;
274*41488Smckusick 			wait = scsi_data_wait;
275*41488Smckusick 			if (ixfer_start(hd, len, phase, wait) ||
276*41488Smckusick 			    !(hd->scsi_ssts & SSTS_DREG_EMPTY))
277*41488Smckusick 				ixfer_in(hd, len, buf);
278*41488Smckusick 			phase = STATUS_PHASE;
279*41488Smckusick 			break;
280*41488Smckusick 
281*41488Smckusick 		case DATA_OUT_PHASE:
282*41488Smckusick 			if (len <= 0)
283*41488Smckusick 				goto abort;
284*41488Smckusick 			wait = scsi_data_wait;
285*41488Smckusick 			if (ixfer_start(hd, len, phase, wait))
286*41488Smckusick 				if (ixfer_out(hd, len, buf))
287*41488Smckusick 					goto abort;
288*41488Smckusick 			phase = STATUS_PHASE;
289*41488Smckusick 			break;
290*41488Smckusick 
291*41488Smckusick 		case STATUS_PHASE:
292*41488Smckusick 			wait = scsi_data_wait;
293*41488Smckusick 			if (ixfer_start(hd, sizeof(hs->sc_stat), phase, wait) ||
294*41488Smckusick 			    !(hd->scsi_ssts & SSTS_DREG_EMPTY))
295*41488Smckusick 				ixfer_in(hd, sizeof(hs->sc_stat), &hs->sc_stat);
296*41488Smckusick 			phase = MESG_IN_PHASE;
297*41488Smckusick 			break;
298*41488Smckusick 
299*41488Smckusick 		case MESG_IN_PHASE:
300*41488Smckusick 			if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait) ||
301*41488Smckusick 			    !(hd->scsi_ssts & SSTS_DREG_EMPTY)) {
302*41488Smckusick 				ixfer_in(hd, sizeof(hs->sc_msg), &hs->sc_msg);
303*41488Smckusick 				hd->scsi_scmd = SCMD_RST_ACK;
304*41488Smckusick 			}
305*41488Smckusick 			phase = BUS_FREE_PHASE;
306*41488Smckusick 			break;
307*41488Smckusick 
308*41488Smckusick 		case BUS_FREE_PHASE:
309*41488Smckusick 			return (1);
310*41488Smckusick 
311*41488Smckusick 		default:
312*41488Smckusick 			printf("unexpected scsi phase %d\n", phase);
313*41488Smckusick 			goto abort;
314*41488Smckusick 		}
315*41488Smckusick 		/* wait for last command to complete */
316*41488Smckusick 		while ((ints = hd->scsi_ints) == 0) {
317*41488Smckusick 			if (--wait < 0)
318*41488Smckusick 				goto abort;
319*41488Smckusick 			DELAY(1);
320*41488Smckusick 		}
321*41488Smckusick 		hd->scsi_ints = ints;
322*41488Smckusick 		if (ints & INTS_SRV_REQ)
323*41488Smckusick 			phase = hd->scsi_psns & PHASE;
324*41488Smckusick 		else if (ints & INTS_DISCON)
325*41488Smckusick 			return (1);
326*41488Smckusick 		else if ((ints & INTS_CMD_DONE) == 0) {
327*41488Smckusick 			goto abort;
328*41488Smckusick 		}
329*41488Smckusick 	}
330*41488Smckusick abort:
331*41488Smckusick 	scsiabort(hs, hd);
332*41488Smckusick 	return (0);
333*41488Smckusick }
334*41488Smckusick 
335*41488Smckusick int
336*41488Smckusick scsi_test_unit_rdy(unit)
337*41488Smckusick {
338*41488Smckusick 	int ctlr = scsiunit(unit);
339*41488Smckusick 	int slave = scsislave(unit);
340*41488Smckusick 	register struct scsi_softc *hs = &scsi_softc[ctlr];
341*41488Smckusick 	static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };
342*41488Smckusick 
343*41488Smckusick 	if (scsiicmd(hs, slave, &cdb, sizeof(cdb), (u_char *)0, 0,
344*41488Smckusick 		     STATUS_PHASE) == 0)
345*41488Smckusick 		return (0);
346*41488Smckusick 
347*41488Smckusick 	return (hs->sc_stat == 0);
348*41488Smckusick }
349*41488Smckusick 
350*41488Smckusick int
351*41488Smckusick scsi_request_sense(unit, buf, len)
352*41488Smckusick 	int unit;
353*41488Smckusick 	u_char *buf;
354*41488Smckusick 	unsigned len;
355*41488Smckusick {
356*41488Smckusick 	int ctlr = scsiunit(unit);
357*41488Smckusick 	int slave = scsislave(unit);
358*41488Smckusick 	register struct scsi_softc *hs = &scsi_softc[ctlr];
359*41488Smckusick 	static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE };
360*41488Smckusick 
361*41488Smckusick 	cdb.len = len;
362*41488Smckusick 	return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE));
363*41488Smckusick }
364*41488Smckusick 
365*41488Smckusick int
366*41488Smckusick scsi_read_capacity(unit, buf, len)
367*41488Smckusick 	int unit;
368*41488Smckusick 	u_char *buf;
369*41488Smckusick 	unsigned len;
370*41488Smckusick {
371*41488Smckusick 	int ctlr = scsiunit(unit);
372*41488Smckusick 	int slave = scsislave(unit);
373*41488Smckusick 	register struct scsi_softc *hs = &scsi_softc[ctlr];
374*41488Smckusick 	static struct scsi_cdb10 cdb = { CMD_READ_CAPACITY };
375*41488Smckusick 
376*41488Smckusick 	return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE));
377*41488Smckusick }
378*41488Smckusick 
379*41488Smckusick int
380*41488Smckusick scsi_tt_read(unit, buf, len, blk, nblk)
381*41488Smckusick 	int unit;
382*41488Smckusick 	u_char *buf;
383*41488Smckusick 	u_int len;
384*41488Smckusick 	daddr_t blk;
385*41488Smckusick 	u_int nblk;
386*41488Smckusick {
387*41488Smckusick 	int ctlr = scsiunit(unit);
388*41488Smckusick 	int slave = scsislave(unit);
389*41488Smckusick 	register struct scsi_softc *hs = &scsi_softc[ctlr];
390*41488Smckusick 	struct scsi_cdb10 cdb;
391*41488Smckusick 	int stat;
392*41488Smckusick 
393*41488Smckusick 	bzero(&cdb, sizeof(cdb));
394*41488Smckusick 	cdb.cmd = CMD_READ_EXT;
395*41488Smckusick 	cdb.lbah = blk >> 24;
396*41488Smckusick 	cdb.lbahm = blk >> 16;
397*41488Smckusick 	cdb.lbalm = blk >> 8;
398*41488Smckusick 	cdb.lbal = blk;
399*41488Smckusick 	cdb.lenh = nblk >> (8 + DEV_BSHIFT);
400*41488Smckusick 	cdb.lenl = nblk >> DEV_BSHIFT;
401*41488Smckusick 	stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE);
402*41488Smckusick 	if (stat == 0)
403*41488Smckusick 		return (1);
404*41488Smckusick 	return (hs->sc_stat);
405*41488Smckusick }
406*41488Smckusick 
407*41488Smckusick int
408*41488Smckusick scsi_tt_write(unit, buf, len, blk, nblk)
409*41488Smckusick 	int unit;
410*41488Smckusick 	u_char *buf;
411*41488Smckusick 	u_int len;
412*41488Smckusick 	daddr_t blk;
413*41488Smckusick 	u_int nblk;
414*41488Smckusick {
415*41488Smckusick 	int ctlr = scsiunit(unit);
416*41488Smckusick 	int slave = scsislave(unit);
417*41488Smckusick 	register struct scsi_softc *hs = &scsi_softc[ctlr];
418*41488Smckusick 	struct scsi_cdb10 cdb;
419*41488Smckusick 	int stat;
420*41488Smckusick 
421*41488Smckusick 	bzero(&cdb, sizeof(cdb));
422*41488Smckusick 	cdb.cmd = CMD_WRITE_EXT;
423*41488Smckusick 	cdb.lbah = blk >> 24;
424*41488Smckusick 	cdb.lbahm = blk >> 16;
425*41488Smckusick 	cdb.lbalm = blk >> 8;
426*41488Smckusick 	cdb.lbal = blk;
427*41488Smckusick 	cdb.lenh = nblk >> (8 + DEV_BSHIFT);
428*41488Smckusick 	cdb.lenl = nblk >> DEV_BSHIFT;
429*41488Smckusick 	stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_OUT_PHASE);
430*41488Smckusick 	if (stat == 0)
431*41488Smckusick 		return (1);
432*41488Smckusick 	return (hs->sc_stat);
433*41488Smckusick }
434