xref: /original-bsd/sys/dev/scsi/scsi_subr.c (revision 4d63cfed)
1 /*
2  * Copyright (c) 1992 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This software was developed by the Computer Systems Engineering group
6  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
7  * contributed to Berkeley.
8  *
9  * All advertising materials mentioning features or use of this software
10  * must display the following acknowledgement:
11  *	This product includes software developed by the University of
12  *	California, Lawrence Berkeley Laboratories.
13  *
14  * %sccs.include.redist.c%
15  *
16  *	@(#)scsi_subr.c	5.4 (Berkeley) 02/01/93
17  *
18  * from: $Header: scsi_subr.c,v 1.10 93/02/01 19:21:58 torek Exp $ (LBL)
19  */
20 
21 /*
22  * Generic SCSI host adapter driver.
23  * Does almost nothing (most work is relegated to per-hba drivers).
24  */
25 
26 #include <sys/param.h>
27 #include <sys/buf.h>
28 #include <sys/device.h>
29 
30 #include <dev/scsi/scsi.h>
31 #include <dev/scsi/scsivar.h>
32 
33 /*
34  * General subroutines, and scsi data.
35  */
36 
37 /* table of lengths of scsi commands */
38 const char scsicmdlen[8] = { 6, 10, 0, 0, 0, 12, 0, 0 };
39 
40 /* table of lengths of scsi messages */
41 const signed char scsimsglen[0x24] = {
42 	SMLEN_DONE,		/* MSG_CMD_COMPLETE */
43 	SMLEN_EXTENDED,		/* MSG_EXT_MESSAGE */
44 	1,			/* MSG_SAVE_DATA_PTR */
45 	1,			/* MSG_RESTORE_PTR */
46 	1,			/* MSG_DISCONNECT */
47 	1,			/* MSG_INIT_DETECT_ERROR */
48 	1,			/* MSG_ABORT */
49 	1,			/* MSG_REJECT */
50 	1,			/* MSG_NOOP */
51 	1,			/* MSG_PARITY_ERROR */
52 	1,			/* MSG_LCC */
53 	1,			/* MSG_LCCF */
54 	1,			/* MSG_BUS_DEVICE_RESET */
55 	1,			/* MSG_ABORT_TAG */
56 	1,			/* MSG_CLEAR_QUEUE */
57 	1,			/* MSG_INITIATE_RECOVERY */
58 	1,			/* MSG_RELEASE_RECOVERY */
59 	1,			/* MSG_TERMINATE_PROCESS */
60 	SMLEN_UNDEF,		/* 0x12 */
61 	SMLEN_UNDEF,		/* 0x13 */
62 	SMLEN_UNDEF,		/* 0x14 */
63 	SMLEN_UNDEF,		/* 0x15 */
64 	SMLEN_UNDEF,		/* 0x16 */
65 	SMLEN_UNDEF,		/* 0x17 */
66 	SMLEN_UNDEF,		/* 0x18 */
67 	SMLEN_UNDEF,		/* 0x19 */
68 	SMLEN_UNDEF,		/* 0x1a */
69 	SMLEN_UNDEF,		/* 0x1b */
70 	SMLEN_UNDEF,		/* 0x1c */
71 	SMLEN_UNDEF,		/* 0x1d */
72 	SMLEN_UNDEF,		/* 0x1e */
73 	SMLEN_UNDEF,		/* 0x1f */
74 	2,			/* MSG_SIMPLE_QTAG */
75 	2,			/* MSG_HEAD_QTAG */
76 	2,			/* MSG_ORDERED_QTAG */
77 	2,			/* MSG_IGNORE_WIDE_RESID */
78 };
79 
80 /* definition of `tg' target driver for autoconfig */
81 static int scsi_targmatch __P((struct device *, struct cfdata *, void *));
82 static void scsi_targattach __P((struct device *, struct device *, void *));
83 struct cfdriver tgcd =
84     { NULL, "tg", scsi_targmatch, scsi_targattach,
85       DV_DULL, sizeof(struct targ) };
86 
87 void	scsi_targstart __P((struct device *, struct sq *, struct buf *,
88 			scdgo_fn, struct device *));
89 int	scsi_targgo __P((struct device *, int targ,
90 			scintr_fn, struct device *, struct buf *, int));
91 void	scsi_targintr __P((struct device *, int, int));
92 void	scsi_targrel __P((struct device *));
93 
94 #define	NOBUF	((caddr_t)0)
95 
96 /*
97  * Perform a TEST UNIT READY immediate (polled) command
98  * on the given <target,unit> pair.  Return the status byte
99  * returned, or -1 for none.
100  */
101 int
102 scsi_test_unit_ready(hba, targ, unit)
103 	struct hba_softc *hba;
104 	int targ, unit;
105 {
106 	struct scsi_cdb cdb;
107 
108 	CDB6(&cdb)->cdb_cmd = CMD_TEST_UNIT_READY;
109 	CDB6(&cdb)->cdb_lun_lbah = unit << 5;
110 	*(short *)&CDB6(&cdb)->cdb_lbam = 0;
111 	*(short *)&CDB6(&cdb)->cdb_len = 0;
112 	return (hba->hba_driver->hd_icmd(hba, targ, &cdb, NOBUF, 0, 0));
113 }
114 
115 /*
116  * Request sense.  The sense is to be written into the given buffer.
117  * The given length must be < 256.
118  */
119 int
120 scsi_request_sense(hba, targ, unit, buf, len)
121 	struct hba_softc *hba;
122 	int targ, unit;
123 	caddr_t buf;
124 	int len;
125 {
126 	struct scsi_cdb cdb;
127 
128 	CDB6(&cdb)->cdb_cmd = CMD_REQUEST_SENSE;
129 	CDB6(&cdb)->cdb_lun_lbah = unit << 5;
130 	*(short *)&CDB6(&cdb)->cdb_lbam = 0;
131 	CDB6(&cdb)->cdb_len = len;
132 	CDB6(&cdb)->cdb_ctrl = 0;
133 	return (hba->hba_driver->hd_icmd(hba, targ, &cdb, buf, len, B_READ));
134 }
135 
136 /*
137  * Called (indirectly, via config_found) from scsi_hbaattach.
138  * Print target number, and if no device was configured there,
139  * the hba as well.
140  */
141 int
142 scsi_targprint(aux, hba)
143 	void *aux;
144 	char *hba;
145 {
146 
147 	if (hba) {
148 		printf("target %d on %s", *(int *)aux, hba);
149 		return (UNCONF);
150 	}
151 	printf(" target %d", *(int *)aux);
152 	return (QUIET);
153 }
154 
155 /*
156  * Print information about a unit found on some target.
157  * If the unit was not configured, `targ' is the name of the target
158  * on which the unit was found.  If it was, targ is NULL and we
159  * let the unit's attach routine print the INQUIRE result if
160  * appropriate.
161  */
162 static int
163 scsi_unitprint(aux, targ)
164 	void *aux;
165 	char *targ;
166 {
167 	register struct scsi_attach_args *sa = aux;
168 
169 	if (targ) {
170 		printf("unit %d at %s", sa->sa_unit, targ);
171 		if ((sa->sa_inq_status & STS_MASK) == STS_GOOD) {
172 			printf(" (");
173 			scsi_printinq(&sa->sa_si);
174 			printf(")");
175 		}
176 		return (UNCONF);
177 	}
178 	printf(" unit %d", sa->sa_unit);
179 	return (QUIET);
180 }
181 
182 /*
183  * Generic target-match.
184  */
185 static int
186 scsi_targmatch(parent, cf, aux)
187 	struct device *parent;
188 	register struct cfdata *cf;
189 	void *aux;
190 {
191 	int targ = *(int *)aux;
192 
193 	return (cf->cf_loc[0] == targ || cf->cf_loc[0] == -1);
194 }
195 
196 /*
197  * And now, a generic `target attach' routine.
198  * We assume that INQUIRY works.
199  */
200 static void
201 scsi_targattach(parent, self, aux)
202 	struct device *parent, *self;
203 	void *aux;
204 {
205 	register struct targ *t = (struct targ *)self;
206 	register struct hba_softc *hba;
207 	register struct hbadriver *hd;
208 	register int targ, unit;
209 	struct scsi_attach_args sa;
210 	struct scsi_cdb si;
211 
212 	printf("\n");
213 	t->t_targ = targ = *(int *)aux;
214 	hba = (struct hba_softc *)parent;
215 	hba->hba_targets[targ] = t;
216 
217 	/*
218 	 * Probe each of the 8 units using the sequence
219 	 *	TEST UNIT READY
220 	 *	REQUEST SENSE
221 	 *	INQUIRY
222 	 * The first should not be necessary, but some SCSI devices
223 	 * refuse to speak until it is done.  The second is only necessary
224 	 * if the first returns a CHECK CONDITION status, but we do it
225 	 * anyway.
226 	 */
227 	hd = hba->hba_driver;
228 	sa.sa_targ = targ;
229 	CDB6(&si)->cdb_cmd = CMD_INQUIRY;
230 	*(short *)&CDB6(&si)->cdb_lbam = 0;
231 	CDB6(&si)->cdb_len = sizeof sa.sa_si;
232 	CDB6(&si)->cdb_ctrl = 0;
233 	for (unit = 0; unit < 8; unit++) {
234 		if (scsi_test_unit_ready(hba, targ, unit) == -1)
235 			continue;
236 		sa.sa_unit = unit;
237 		sa.sa_req_status = scsi_request_sense(hba, targ, unit,
238 		    (caddr_t)&sa.sa_sn, sizeof sa.sa_sn);
239 		CDB6(&si)->cdb_lun_lbah = unit << 5;
240 		sa.sa_inq_status = (*hd->hd_icmd)(hba, targ, &si,
241 		    (caddr_t)&sa.sa_si, sizeof sa.sa_si, B_READ);
242 		if ((sa.sa_inq_status & STS_MASK) == STS_GOOD &&
243 #ifdef notdef /* XXX don't know if this is a reasonable test */
244 		    (sa.sa_si.si_type & TYPE_QUAL_MASK) == TYPE_QUAL_NOTCONN &&
245 #endif
246 		    (sa.sa_si.si_type & TYPE_TYPE_MASK) == TYPE_NP) {
247 			continue;
248 		}
249 		config_found(&t->t_dev, (void *)&sa, scsi_unitprint);
250 	}
251 }
252 
253 /*
254  * Each unit calls scsi_establish to tell the hba and target of
255  * its existence.
256  */
257 void
258 scsi_establish(u, dev, unit)
259 	register struct unit *u;
260 	struct device *dev;
261 	register int unit;
262 {
263 	register struct targ *t;
264 	register struct hba_softc *hba;
265 	register struct hbadriver *hbd;
266 
267 	u->u_dev = dev;
268 	t = (struct targ *)dev->dv_parent;
269 	hba = (struct hba_softc *)t->t_dev.dv_parent;
270 	hbd = hba->hba_driver;
271 	t->t_units[unit] = u;
272 	if (t->t_nunits == 0) {
273 		/*
274 		 * This is the first unit on the target.  We can
275 		 * probably just call the hba start code, avoiding
276 		 * one level of calls and queueing.  If we attach
277 		 * another target we will fix this in the code below.
278 		 */
279 		u->u_start = hbd->hd_start;
280 		u->u_go = hbd->hd_go;
281 		u->u_rel = hbd->hd_rel;
282 		u->u_updev = &hba->hba_dev;
283 		t->t_firstunit = unit;
284 	} else {
285 		/*
286 		 * This is not the only unit on the target, so we
287 		 * must call the target start code rather than the
288 		 * hba start code.  Fix the linkage on the first
289 		 * target too (possibly for the 2nd, 3rd, ..., time).
290 		 */
291 		t->t_units[t->t_firstunit]->u_start = scsi_targstart;
292 		t->t_units[t->t_firstunit]->u_updev = &t->t_dev;
293 		u->u_start = scsi_targstart;
294 		u->u_go = scsi_targgo;
295 		u->u_rel = scsi_targrel;
296 		u->u_updev = &t->t_dev;
297 	}
298 	t->t_nunits++;			/* another unit is alive */
299 	u->u_unit = unit;
300 	u->u_targ = t->t_targ;		/* record target number, */
301 	u->u_hba = hba;			/* hba ... */
302 	u->u_hbd = hbd;			/* and driver */
303 }
304 
305 /* NO DOUBT SOME OF THE STUFF PRINTED HERE IS USELESS */
306 void
307 scsi_printinq(inq)
308 	register struct scsi_inquiry *inq;
309 {
310 	register int iso, ecma, ansi, t;
311 	static char *types[] = { "disk", "tape", "printer", "processor",
312 	    "WORM", "ROM disk", "scanner", "magneto-optical",
313 	    "jukebox", "lan" };
314 
315 	if ((t = (inq->si_type & TYPE_QUAL_MASK)) != 0)
316 		printf("type-qual=0x%x ", t);
317 	t = inq->si_type & TYPE_TYPE_MASK;
318 	if (t < sizeof types / sizeof *types)
319 		printf("%s", types[t]);
320 	else
321 		printf("<type %d>", t);
322 	if (inq->si_qual & QUAL_RMB)
323 		printf(" (removable)");
324 	printf(" qual=0x%x", inq->si_qual & QUAL_MASK);
325 	iso = (inq->si_qual >> VER_ISO_SHIFT) & VER_ISO_MASK;
326 	ecma = (inq->si_qual >> VER_ECMA_SHIFT) & VER_ECMA_MASK;
327 	ansi = (inq->si_qual >> VER_ANSI_SHIFT) & VER_ANSI_MASK;
328 	printf(" version=<iso %d, ecma %d, ansi %d>", iso, ecma, ansi);
329 	if (ansi == 1 || ansi == 2) {
330 		char v[9], p[17], r[5];
331 
332 		scsi_inq_ansi((struct scsi_inq_ansi *)inq, v, p, r);
333 		printf(" vendor %s, product %s, rev %s", v, p, r);
334 	}
335 }
336 
337 /* copy a counted string but trim trailing blanks; make the dest a C string */
338 static void
339 scsi_str(src, dst, len)
340 	register char *src, *dst;
341 	register int len;
342 {
343 
344 	while (src[len - 1] == ' ') {
345 		if (--len == 0) {
346 			*dst = 0;
347 			return;
348 		}
349 	}
350 	bcopy(src, dst, len);
351 	dst[len] = 0;
352 }
353 
354 void
355 scsi_inq_ansi(si, vendor, product, rev)
356 	register struct scsi_inq_ansi *si;
357 	char *vendor, *product, *rev;
358 {
359 	register int i, len;
360 
361 	/* if too short, extend with blanks */
362 	len = si->si_len + 5;	/* 5 fixed; len is `additional' */
363 	if (len < sizeof(*si))
364 		for (i = len; i < sizeof *si; i++)
365 			((char *)si)[i] = ' ';
366 	scsi_str(si->si_vendor, vendor, sizeof si->si_vendor);
367 	scsi_str(si->si_product, product, sizeof si->si_product);
368 	scsi_str(si->si_rev, rev, sizeof si->si_rev);
369 }
370 
371 /*
372  * Tell all the devices on the given hba that it has been reset.
373  * SHOULD PROBABLY DO MORE HERE
374  */
375 void
376 scsi_reset_units(hba)
377 	register struct hba_softc *hba;
378 {
379 	register int targ, unit;
380 	register struct targ *t;
381 	register struct unit *u;
382 
383 	for (targ = 0; targ < 8; targ++) {
384 		if ((t = hba->hba_targets[targ]) == NULL)
385 			continue;
386 		for (unit = 0; unit < 8; unit++)
387 			if ((u = t->t_units[unit]) != NULL)
388 				(*u->u_driver->ud_reset)(u);
389 	}
390 }
391 
392 /*
393  * Start a unit on a target.
394  * If the target is busy, just enqueue the unit;
395  * once the target becomes free, we will call the hba start routine.
396  * Otherwise, call the hba start routine now, and then when the hba
397  * becomes free it will call the unit's dgo routine.
398  */
399 void
400 scsi_targstart(self, sq, bp, dgo, dev)
401 	struct device *self;
402 	register struct sq *sq;
403 	struct buf *bp;
404 	scdgo_fn dgo;
405 	struct device *dev;
406 {
407 	register struct targ *t = (struct targ *)self;
408 	register struct hba_softc *hba;
409 
410 	sq->sq_forw = NULL;
411 	if (t->t_head == NULL)
412 		t->t_head = sq;
413 	else
414 		t->t_tail->sq_forw = sq;
415 	t->t_tail = sq;
416 	if (t->t_busy == 0) {
417 		t->t_busy = 1;
418 		hba = (struct hba_softc *)t->t_dev.dv_parent;
419 		(*hba->hba_driver->hd_start)(&hba->hba_dev, &t->t_forw, bp,
420 		    dgo, dev);
421 	} else {
422 		sq->sq_bp = bp;
423 		sq->sq_dgo = dgo;
424 		sq->sq_dev = dev;
425 	}
426 }
427 
428 /*
429  * The unit got the bus, and wants the hba to go.
430  * Remember its interrupt handler; substitute ours instead.
431  */
432 int
433 scsi_targgo(self, targ, intr, dev, bp, pad)
434 	struct device *self;
435 	int targ;
436 	scintr_fn intr;
437 	struct device *dev;
438 	struct buf *bp;
439 	int pad;
440 {
441 	register struct targ *t = (struct targ *)self;
442 	register struct hba_softc *hba;
443 
444 	t->t_intr = intr;
445 	t->t_intrdev = dev;
446 	hba = (struct hba_softc *)t->t_dev.dv_parent;
447 	return ((*hba->hba_driver->hd_go)(&hba->hba_dev, targ,
448 	    scsi_targintr, &t->t_dev, bp, pad));
449 }
450 
451 /*
452  * The hba got an interrupt.  Dequeue the unit from the target
453  * (the target is already off the hba queue) and then call the
454  * underlying interrupt handler.
455  */
456 void
457 scsi_targintr(self, stat, resid)
458 	struct device *self;
459 	int stat, resid;
460 {
461 	register struct targ *t = (struct targ *)self;
462 	register struct hba_softc *hba;
463 	register struct sq *sq;
464 
465 	sq = t->t_head;
466 if (sq == NULL) panic("scsi_targintr");
467 	t->t_head = sq = sq->sq_forw;
468 	(*t->t_intr)(t->t_intrdev, stat, resid);
469 	if (sq != NULL) {
470 		hba = (struct hba_softc *)t->t_dev.dv_parent;
471 		(*hba->hba_driver->hd_start)(&hba->hba_dev, &t->t_forw,
472 		    sq->sq_bp, sq->sq_dgo, sq->sq_dev);
473 	} else
474 		t->t_busy = 0;
475 }
476 
477 /*
478  * The unit decided that it needed to `give up' its hold on the bus early.
479  */
480 void
481 scsi_targrel(self)
482 	struct device *self;
483 {
484 	register struct targ *t = (struct targ *)self;
485 	register struct hba_softc *hba;
486 	register struct sq *sq;
487 
488 	hba = (struct hba_softc *)t->t_dev.dv_parent;
489 	sq = t->t_head;
490 if (sq == NULL) panic("scsi_targrel");
491 	/*
492 	 * This target is at the head of the hba queue.
493 	 * Remove it by calling hba bus release.  Then, if the
494 	 * target queue is not empty, put it back on the hba queue.
495 	 * (This produces round robin service.)
496 	 */
497 	(*hba->hba_driver->hd_rel)(&hba->hba_dev);
498 	sq = sq->sq_forw;
499 	if ((t->t_head = sq) != NULL)
500 		(*hba->hba_driver->hd_start)(&hba->hba_dev, &t->t_forw,
501 		    sq->sq_bp, sq->sq_dgo, sq->sq_dev);
502 	else
503 		t->t_busy = 0;
504 }
505