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