1 /*
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. 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 8.1 (Berkeley) 06/16/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
scsi_test_unit_ready(hba,targ,unit)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
scsi_request_sense(hba,targ,unit,buf,len)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
scsi_targprint(aux,hba)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
scsi_unitprint(aux,targ)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
scsi_targmatch(parent,cf,aux)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
scsi_targattach(parent,self,aux)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
scsi_establish(u,dev,unit)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_go = scsi_targgo;
293 t->t_units[t->t_firstunit]->u_rel = scsi_targrel;
294 t->t_units[t->t_firstunit]->u_updev = &t->t_dev;
295 u->u_start = scsi_targstart;
296 u->u_go = scsi_targgo;
297 u->u_rel = scsi_targrel;
298 u->u_updev = &t->t_dev;
299 }
300 t->t_nunits++; /* another unit is alive */
301 u->u_unit = unit;
302 u->u_targ = t->t_targ; /* record target number, */
303 u->u_hba = hba; /* hba ... */
304 u->u_hbd = hbd; /* and driver */
305 }
306
307 /* NO DOUBT SOME OF THE STUFF PRINTED HERE IS USELESS */
308 void
scsi_printinq(inq)309 scsi_printinq(inq)
310 register struct scsi_inquiry *inq;
311 {
312 register int iso, ecma, ansi, t;
313 static char *types[] = { "disk", "tape", "printer", "processor",
314 "WORM", "ROM disk", "scanner", "magneto-optical",
315 "jukebox", "lan" };
316
317 if ((t = (inq->si_type & TYPE_QUAL_MASK)) != 0)
318 printf("type-qual=0x%x ", t);
319 t = inq->si_type & TYPE_TYPE_MASK;
320 if (t < sizeof types / sizeof *types)
321 printf("%s", types[t]);
322 else
323 printf("<type %d>", t);
324 if (inq->si_qual & QUAL_RMB)
325 printf(" (removable)");
326 printf(" qual=0x%x", inq->si_qual & QUAL_MASK);
327 iso = (inq->si_qual >> VER_ISO_SHIFT) & VER_ISO_MASK;
328 ecma = (inq->si_qual >> VER_ECMA_SHIFT) & VER_ECMA_MASK;
329 ansi = (inq->si_qual >> VER_ANSI_SHIFT) & VER_ANSI_MASK;
330 printf(" version=<iso %d, ecma %d, ansi %d>", iso, ecma, ansi);
331 if (ansi == 1 || ansi == 2) {
332 char v[9], p[17], r[5];
333
334 scsi_inq_ansi((struct scsi_inq_ansi *)inq, v, p, r);
335 printf(" vendor %s, product %s, rev %s", v, p, r);
336 }
337 }
338
339 /* copy a counted string but trim trailing blanks; make the dest a C string */
340 static void
scsi_str(src,dst,len)341 scsi_str(src, dst, len)
342 register char *src, *dst;
343 register int len;
344 {
345
346 while (src[len - 1] == ' ') {
347 if (--len == 0) {
348 *dst = 0;
349 return;
350 }
351 }
352 bcopy(src, dst, len);
353 dst[len] = 0;
354 }
355
356 void
scsi_inq_ansi(si,vendor,product,rev)357 scsi_inq_ansi(si, vendor, product, rev)
358 register struct scsi_inq_ansi *si;
359 char *vendor, *product, *rev;
360 {
361 register int i, len;
362
363 /* if too short, extend with blanks */
364 len = si->si_len + 5; /* 5 fixed; len is `additional' */
365 if (len < sizeof(*si))
366 for (i = len; i < sizeof *si; i++)
367 ((char *)si)[i] = ' ';
368 scsi_str(si->si_vendor, vendor, sizeof si->si_vendor);
369 scsi_str(si->si_product, product, sizeof si->si_product);
370 scsi_str(si->si_rev, rev, sizeof si->si_rev);
371 }
372
373 /*
374 * Tell all the devices on the given hba that it has been reset.
375 * SHOULD PROBABLY DO MORE HERE
376 */
377 void
scsi_reset_units(hba)378 scsi_reset_units(hba)
379 register struct hba_softc *hba;
380 {
381 register int targ, unit;
382 register struct targ *t;
383 register struct unit *u;
384
385 for (targ = 0; targ < 8; targ++) {
386 if ((t = hba->hba_targets[targ]) == NULL)
387 continue;
388 for (unit = 0; unit < 8; unit++)
389 if ((u = t->t_units[unit]) != NULL)
390 (*u->u_driver->ud_reset)(u);
391 }
392 }
393
394 /*
395 * Start a unit on a target.
396 * If the target is busy, just enqueue the unit;
397 * once the target becomes free, we will call the hba start routine.
398 * Otherwise, call the hba start routine now, and then when the hba
399 * becomes free it will call the unit's dgo routine.
400 */
401 void
scsi_targstart(self,sq,bp,dgo,dev)402 scsi_targstart(self, sq, bp, dgo, dev)
403 struct device *self;
404 register struct sq *sq;
405 struct buf *bp;
406 scdgo_fn dgo;
407 struct device *dev;
408 {
409 register struct targ *t = (struct targ *)self;
410 register struct hba_softc *hba;
411
412 sq->sq_forw = NULL;
413 if (t->t_head == NULL)
414 t->t_head = sq;
415 else
416 t->t_tail->sq_forw = sq;
417 t->t_tail = sq;
418 if (t->t_busy == 0) {
419 t->t_busy = 1;
420 hba = (struct hba_softc *)t->t_dev.dv_parent;
421 (*hba->hba_driver->hd_start)(&hba->hba_dev, &t->t_forw, bp,
422 dgo, dev);
423 } else {
424 sq->sq_bp = bp;
425 sq->sq_dgo = dgo;
426 sq->sq_dev = dev;
427 }
428 }
429
430 /*
431 * The unit got the bus, and wants the hba to go.
432 * Remember its interrupt handler; substitute ours instead.
433 */
434 int
scsi_targgo(self,targ,intr,dev,bp,pad)435 scsi_targgo(self, targ, intr, dev, bp, pad)
436 struct device *self;
437 int targ;
438 scintr_fn intr;
439 struct device *dev;
440 struct buf *bp;
441 int pad;
442 {
443 register struct targ *t = (struct targ *)self;
444 register struct hba_softc *hba;
445
446 t->t_intr = intr;
447 t->t_intrdev = dev;
448 hba = (struct hba_softc *)t->t_dev.dv_parent;
449 return ((*hba->hba_driver->hd_go)(&hba->hba_dev, targ,
450 scsi_targintr, &t->t_dev, bp, pad));
451 }
452
453 /*
454 * The hba got an interrupt. Dequeue the unit from the target
455 * (the target is already off the hba queue) and then call the
456 * underlying interrupt handler.
457 */
458 void
scsi_targintr(self,stat,resid)459 scsi_targintr(self, stat, resid)
460 struct device *self;
461 int stat, resid;
462 {
463 register struct targ *t = (struct targ *)self;
464 register struct hba_softc *hba;
465 register struct sq *sq;
466
467 sq = t->t_head;
468 if (sq == NULL) panic("scsi_targintr");
469 t->t_head = sq = sq->sq_forw;
470 (*t->t_intr)(t->t_intrdev, stat, resid);
471 if (sq != NULL) {
472 hba = (struct hba_softc *)t->t_dev.dv_parent;
473 (*hba->hba_driver->hd_start)(&hba->hba_dev, &t->t_forw,
474 sq->sq_bp, sq->sq_dgo, sq->sq_dev);
475 } else
476 t->t_busy = 0;
477 }
478
479 /*
480 * The unit decided that it needed to `give up' its hold on the bus early.
481 */
482 void
scsi_targrel(self)483 scsi_targrel(self)
484 struct device *self;
485 {
486 register struct targ *t = (struct targ *)self;
487 register struct hba_softc *hba;
488 register struct sq *sq;
489
490 hba = (struct hba_softc *)t->t_dev.dv_parent;
491 sq = t->t_head;
492 if (sq == NULL) panic("scsi_targrel");
493 /*
494 * This target is at the head of the hba queue.
495 * Remove it by calling hba bus release. Then, if the
496 * target queue is not empty, put it back on the hba queue.
497 * (This produces round robin service.)
498 */
499 (*hba->hba_driver->hd_rel)(&hba->hba_dev);
500 sq = sq->sq_forw;
501 if ((t->t_head = sq) != NULL)
502 (*hba->hba_driver->hd_start)(&hba->hba_dev, &t->t_forw,
503 sq->sq_bp, sq->sq_dgo, sq->sq_dev);
504 else
505 t->t_busy = 0;
506 }
507