1 /* $OpenBSD: scsiconf.c,v 1.96 2005/06/03 15:24:05 krw Exp $ */
2 /* $NetBSD: scsiconf.c,v 1.57 1996/05/02 01:09:01 neil Exp $ */
3
4 /*
5 * Copyright (c) 1994 Charles Hannum. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Charles Hannum.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34 * Originally written by Julian Elischer (julian@tfs.com)
35 * for TRW Financial Systems for use under the MACH(2.5) operating system.
36 *
37 * TRW Financial Systems, in accordance with their agreement with Carnegie
38 * Mellon University, makes this software available to CMU to distribute
39 * or use in any manner that they see fit as long as this message is kept with
40 * the software. For this reason TFS also grants any other persons or
41 * organisations permission to use or modify this software.
42 *
43 * TFS supplies this software to be publicly redistributed
44 * on the understanding that TFS is not responsible for the correct
45 * functioning of this software in any circumstances.
46 *
47 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
48 */
49
50 #include <sys/types.h>
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/malloc.h>
54 #include <sys/device.h>
55
56 #include <scsi/scsi_all.h>
57 #include <scsi/scsiconf.h>
58
59 #if 0
60 #if NCALS > 0
61 { T_PROCESSOR, T_FIXED, 1,
62 0, 0, 0 },
63 #endif /* NCALS */
64 #if NBLL > 0
65 { T_PROCESSOR, T_FIXED, 1,
66 "AEG ", "READER ", "V1.0" },
67 #endif /* NBLL */
68 #if NKIL > 0
69 { T_SCANNER, T_FIXED, 0,
70 "KODAK ", "IL Scanner 900 ", 0 },
71 #endif /* NKIL */
72 #endif
73
74 /*
75 * Declarations
76 */
77 int scsi_probedev(struct scsibus_softc *, struct scsi_inquiry_data *, int,
78 int);
79 int scsi_probe_bus(int bus, int target, int lun);
80
81 struct scsi_device probe_switch = {
82 NULL,
83 NULL,
84 NULL,
85 NULL,
86 };
87
88 int scsibusmatch(struct device *, void *, void *);
89 void scsibusattach(struct device *, struct device *, void *);
90 int scsibusactivate(struct device *, enum devact);
91 int scsibusdetach(struct device *, int);
92 void scsibuszeroref(struct device *);
93
94 int scsibussubmatch(struct device *, void *, void *);
95
96
97
98 struct cfattach scsibus_ca = {
99 sizeof(struct scsibus_softc), scsibusmatch, scsibusattach,
100 scsibusdetach, scsibusactivate, scsibuszeroref
101 };
102
103 struct cfdriver scsibus_cd = {
104 NULL, "scsibus", DV_DULL
105 };
106
107 int scsidebug_buses = SCSIDEBUG_BUSES;
108 int scsidebug_targets = SCSIDEBUG_TARGETS;
109 int scsidebug_luns = SCSIDEBUG_LUNS;
110 int scsidebug_level = SCSIDEBUG_LEVEL;
111
112 int scsiforcelun_buses = SCSIFORCELUN_BUSES;
113 int scsiforcelun_targets = SCSIFORCELUN_TARGETS;
114
115 int scsi_autoconf = SCSI_AUTOCONF;
116
117 int scsibusprint(void *, const char *);
118
119 int
scsiprint(aux,pnp)120 scsiprint(aux, pnp)
121 void *aux;
122 const char *pnp;
123 {
124 /* only "scsibus"es can attach to "scsi"s; easy. */
125 if (pnp)
126 printf("scsibus at %s", pnp);
127
128 return (UNCONF);
129 }
130
131 int
scsibusmatch(parent,match,aux)132 scsibusmatch(parent, match, aux)
133 struct device *parent;
134 void *match, *aux;
135 {
136
137 return 1;
138 }
139
140 /*
141 * The routine called by the adapter boards to get all their
142 * devices configured in.
143 */
144 void
scsibusattach(parent,self,aux)145 scsibusattach(parent, self, aux)
146 struct device *parent, *self;
147 void *aux;
148 {
149 struct scsibus_softc *sb = (struct scsibus_softc *)self;
150 struct scsi_link *sc_link_proto = aux;
151 int nbytes, i;
152
153 if (!cold)
154 scsi_autoconf = 0;
155
156 sc_link_proto->scsibus = sb->sc_dev.dv_unit;
157 sb->adapter_link = sc_link_proto;
158 if (sb->adapter_link->adapter_buswidth == 0)
159 sb->adapter_link->adapter_buswidth = 8;
160 sb->sc_buswidth = sb->adapter_link->adapter_buswidth;
161 if (sb->adapter_link->luns == 0)
162 sb->adapter_link->luns = 8;
163
164 printf(": %d targets\n", sb->sc_buswidth);
165
166 /* Initialize shared data. */
167 scsi_init();
168
169 nbytes = sb->sc_buswidth * sizeof(struct scsi_link **);
170 sb->sc_link = (struct scsi_link ***)malloc(nbytes, M_DEVBUF, M_NOWAIT);
171 if (sb->sc_link == NULL)
172 panic("scsibusattach: can't allocate target links");
173 nbytes = 8 * sizeof(struct scsi_link *);
174 for (i = 0; i < sb->sc_buswidth; i++) {
175 sb->sc_link[i] = (struct scsi_link **)malloc(nbytes,
176 M_DEVBUF, M_NOWAIT);
177 if (sb->sc_link[i] == NULL)
178 panic("scsibusattach: can't allocate lun links");
179 bzero(sb->sc_link[i], nbytes);
180 }
181
182 #if defined(SCSI_DELAY) && SCSI_DELAY > 2
183 printf("%s: waiting for scsi devices to settle\n",
184 sb->sc_dev.dv_xname);
185 #else /* SCSI_DELAY > 2 */
186 #undef SCSI_DELAY
187 #define SCSI_DELAY 2
188 #endif /* SCSI_DELAY */
189 delay(1000000 * SCSI_DELAY);
190
191 scsi_probe_bus(sb->sc_dev.dv_unit, -1, -1);
192 }
193
194
195 int
scsibusactivate(dev,act)196 scsibusactivate(dev, act)
197 struct device *dev;
198 enum devact act;
199 {
200 return (config_activate_children(dev, act));
201 }
202
203 int
scsibusdetach(dev,type)204 scsibusdetach (dev, type)
205 struct device *dev;
206 int type;
207 {
208 return (config_detach_children(dev, type));
209 }
210
211 void
scsibuszeroref(dev)212 scsibuszeroref(dev)
213 struct device *dev;
214 {
215 struct scsibus_softc *sb = (struct scsibus_softc *)dev;
216 int i;
217
218 for (i = 0; i < sb->sc_buswidth; i++) {
219 if (sb->sc_link[i] != NULL)
220 free(sb->sc_link[i], M_DEVBUF);
221 }
222
223 free(sb->sc_link, M_DEVBUF);
224 }
225
226
227
228 int
scsibussubmatch(parent,match,aux)229 scsibussubmatch(parent, match, aux)
230 struct device *parent;
231 void *match, *aux;
232 {
233 struct cfdata *cf = match;
234 struct scsibus_attach_args *sa = aux;
235 struct scsi_link *sc_link = sa->sa_sc_link;
236
237 if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != sc_link->target)
238 return 0;
239 if (cf->cf_loc[1] != -1 && cf->cf_loc[1] != sc_link->lun)
240 return 0;
241 return ((*cf->cf_attach->ca_match)(parent, match, aux));
242 }
243
244 /*
245 * Probe the requested scsi bus. It must be already set up.
246 * -1 requests all set up scsi busses.
247 * target and lun optionally narrow the search if not -1
248 */
249 int
scsi_probe_busses(bus,target,lun)250 scsi_probe_busses(bus, target, lun)
251 int bus, target, lun;
252 {
253
254 if (bus == -1) {
255 for (bus = 0; bus < scsibus_cd.cd_ndevs; bus++)
256 if (scsibus_cd.cd_devs[bus])
257 scsi_probe_bus(bus, target, lun);
258 return 0;
259 } else {
260 return scsi_probe_bus(bus, target, lun);
261 }
262 }
263
264 /*
265 * Probe the requested scsi bus. It must be already set up.
266 * target and lun optionally narrow the search if not -1
267 */
268 int
scsi_probe_bus(bus,target,lun)269 scsi_probe_bus(bus, target, lun)
270 int bus, target, lun;
271 {
272 struct scsi_inquiry_data inqbuflun0;
273 struct scsibus_softc *scsi;
274 u_int16_t scsi_addr;
275 int maxtarget, mintarget, maxlun, minlun;
276
277 if (bus < 0 || bus >= scsibus_cd.cd_ndevs)
278 return ENXIO;
279 scsi = scsibus_cd.cd_devs[bus];
280 if (!scsi)
281 return ENXIO;
282
283 scsi_addr = scsi->adapter_link->adapter_target;
284
285 if (target == -1) {
286 maxtarget = scsi->adapter_link->adapter_buswidth - 1;
287 mintarget = 0;
288 } else {
289 if (target < 0 ||
290 target >= scsi->adapter_link->adapter_buswidth)
291 return EINVAL;
292 maxtarget = mintarget = target;
293 }
294
295 if (lun == -1) {
296 maxlun = scsi->adapter_link->luns - 1;
297 minlun = 0;
298 } else {
299 if (lun < 0 || lun >= scsi->adapter_link->luns)
300 return EINVAL;
301 maxlun = lun;
302 if (lun == 0 || scsi->sc_link[target][0] == NULL)
303 minlun = 0;
304 else
305 minlun = lun;
306 }
307
308 for (target = mintarget; target <= maxtarget; target++)
309 if (target != scsi_addr) {
310 bzero(&inqbuflun0, sizeof inqbuflun0);
311 if (minlun != 0 &&
312 (scsi_inquire(scsi->sc_link[target][0], &inqbuflun0,
313 0) != 0))
314 continue;
315 for (lun = minlun; lun <= maxlun; lun++)
316 if (scsi_probedev(scsi, &inqbuflun0, target,
317 lun) == EINVAL)
318 break;
319 }
320
321 return 0;
322 }
323
324 void
scsi_strvis(dst,src,len)325 scsi_strvis(dst, src, len)
326 u_char *dst, *src;
327 int len;
328 {
329 u_char last;
330
331 /* Trim leading and trailing whitespace and NULs. */
332 while (len > 0 && (src[0] == ' ' || src[0] == '\t' || src[0] == '\n' ||
333 src[0] == '\0' || src[0] == 0xff))
334 ++src, --len;
335 while (len > 0 && (src[len-1] == ' ' || src[len-1] == '\t' ||
336 src[len-1] == '\n' || src[len-1] == '\0' || src[len-1] == 0xff))
337 --len;
338
339 last = 0xff;
340 while (len > 0) {
341 switch (*src) {
342 case ' ':
343 case '\t':
344 case '\n':
345 case '\0':
346 case 0xff:
347 /* collapse whitespace and NULs to a single space */
348 if (last != ' ')
349 *dst++ = ' ';
350 last = ' ';
351 break;
352 case '\\':
353 /* quote characters */
354 *dst++ = '\\';
355 *dst++ = '\\';
356 last = '\\';
357 break;
358 default:
359 if (*src < 0x20 || *src >= 0x80) {
360 /* non-printable characters */
361 *dst++ = '\\';
362 *dst++ = ((*src & 0300) >> 6) + '0';
363 *dst++ = ((*src & 0070) >> 3) + '0';
364 *dst++ = ((*src & 0007) >> 0) + '0';
365 } else {
366 /* normal characters */
367 *dst++ = *src;
368 }
369 last = *src;
370 break;
371 }
372 ++src, --len;
373 }
374
375 *dst++ = 0;
376 }
377
378 struct scsi_quirk_inquiry_pattern {
379 struct scsi_inquiry_pattern pattern;
380 u_int16_t quirks;
381 };
382
383 const struct scsi_quirk_inquiry_pattern scsi_quirk_patterns[] = {
384 {{T_CDROM, T_REMOV,
385 "PLEXTOR", "CD-ROM PX-40TS", "1.01"}, SDEV_NOSYNC},
386
387 {{T_DIRECT, T_FIXED,
388 "MICROP ", "1588-15MBSUN0669", ""}, SDEV_AUTOSAVE},
389 {{T_DIRECT, T_FIXED,
390 "DEC ", "RZ55 (C) DEC", ""}, SDEV_AUTOSAVE},
391 {{T_DIRECT, T_FIXED,
392 "EMULEX ", "MD21/S2 ESDI", "A00"}, SDEV_AUTOSAVE},
393 {{T_DIRECT, T_FIXED,
394 "IBMRAID ", "0662S", ""}, SDEV_AUTOSAVE},
395 {{T_DIRECT, T_FIXED,
396 "IBM ", "0663H", ""}, SDEV_AUTOSAVE},
397 {{T_DIRECT, T_FIXED,
398 "IBM", "0664", ""}, SDEV_AUTOSAVE},
399 {{T_DIRECT, T_FIXED,
400 "IBM ", "H3171-S2", ""}, SDEV_AUTOSAVE},
401 {{T_DIRECT, T_FIXED,
402 "IBM ", "KZ-C", ""}, SDEV_AUTOSAVE},
403 /* Broken IBM disk */
404 {{T_DIRECT, T_FIXED,
405 "" , "DFRSS2F", ""}, SDEV_AUTOSAVE},
406 {{T_DIRECT, T_FIXED,
407 "QUANTUM ", "ELS85S ", ""}, SDEV_AUTOSAVE},
408 {{T_DIRECT, T_REMOV,
409 "iomega", "jaz 1GB", ""}, SDEV_NOTAGS},
410 {{T_DIRECT, T_FIXED,
411 "MICROP", "4421-07", ""}, SDEV_NOTAGS},
412 {{T_DIRECT, T_FIXED,
413 "SEAGATE", "ST150176LW", "0002"}, SDEV_NOTAGS},
414 {{T_DIRECT, T_FIXED,
415 "HP", "C3725S", ""}, SDEV_NOTAGS},
416 {{T_DIRECT, T_FIXED,
417 "IBM", "DCAS", ""}, SDEV_NOTAGS},
418
419 {{T_SEQUENTIAL, T_REMOV,
420 "SONY ", "SDT-5000 ", "3."}, SDEV_NOSYNC|SDEV_NOWIDE},
421 {{T_SEQUENTIAL, T_REMOV,
422 "WangDAT ", "Model 1300 ", "02.4"}, SDEV_NOSYNC|SDEV_NOWIDE},
423 {{T_SEQUENTIAL, T_REMOV,
424 "WangDAT ", "Model 2600 ", "01.7"}, SDEV_NOSYNC|SDEV_NOWIDE},
425 {{T_SEQUENTIAL, T_REMOV,
426 "WangDAT ", "Model 3200 ", "02.2"}, SDEV_NOSYNC|SDEV_NOWIDE},
427
428 /* ATAPI device quirks */
429 {{T_CDROM, T_REMOV,
430 "ALPS ELECTRIC CO.,LTD. DC544C", "", "SW03D"}, ADEV_NOTUR},
431 {{T_CDROM, T_REMOV,
432 "CR-2801TE", "", "1.07"}, ADEV_NOSENSE},
433 {{T_CDROM, T_REMOV,
434 "CREATIVECD3630E", "", "AC101"}, ADEV_NOSENSE},
435 {{T_CDROM, T_REMOV,
436 "FX320S", "", "q01"}, ADEV_NOSENSE},
437 {{T_CDROM, T_REMOV,
438 "GCD-R580B", "", "1.00"}, ADEV_LITTLETOC},
439 {{T_CDROM, T_REMOV,
440 "MATSHITA CR-574", "", "1.02"}, ADEV_NOCAPACITY},
441 {{T_CDROM, T_REMOV,
442 "MATSHITA CR-574", "", "1.06"}, ADEV_NOCAPACITY},
443 {{T_CDROM, T_REMOV,
444 "Memorex CRW-2642", "", "1.0g"}, ADEV_NOSENSE},
445 {{T_CDROM, T_REMOV,
446 "NEC CD-ROM DRIVE:273", "", "4.21"}, ADEV_NOTUR},
447 {{T_CDROM, T_REMOV,
448 "SANYO CRD-256P", "", "1.02"}, ADEV_NOCAPACITY},
449 {{T_CDROM, T_REMOV,
450 "SANYO CRD-254P", "", "1.02"}, ADEV_NOCAPACITY},
451 {{T_CDROM, T_REMOV,
452 "SANYO CRD-S54P", "", "1.08"}, ADEV_NOCAPACITY},
453 {{T_CDROM, T_REMOV,
454 "CD-ROM CDR-S1", "", "1.70"}, ADEV_NOCAPACITY}, /* Sanyo */
455 {{T_CDROM, T_REMOV,
456 "CD-ROM CDR-N16", "", "1.25"}, ADEV_NOCAPACITY}, /* Sanyo */
457 {{T_CDROM, T_REMOV,
458 "UJDCD8730", "", "1.14"}, ADEV_NODOORLOCK}, /* Acer */
459 };
460
461
462 /*
463 * Print out autoconfiguration information for a subdevice.
464 *
465 * This is a slight abuse of 'standard' autoconfiguration semantics,
466 * because 'print' functions don't normally print the colon and
467 * device information. However, in this case that's better than
468 * either printing redundant information before the attach message,
469 * or having the device driver call a special function to print out
470 * the standard device information.
471 */
472 int
scsibusprint(aux,pnp)473 scsibusprint(aux, pnp)
474 void *aux;
475 const char *pnp;
476 {
477 struct scsibus_attach_args *sa = aux;
478 struct scsi_inquiry_data *inqbuf;
479 u_int8_t type;
480 boolean removable;
481 char *dtype, *qtype;
482 char vendor[33], product[65], revision[17];
483 int target, lun;
484
485 if (pnp != NULL)
486 printf("%s", pnp);
487
488 inqbuf = sa->sa_inqbuf;
489
490 target = sa->sa_sc_link->target;
491 lun = sa->sa_sc_link->lun;
492
493 type = inqbuf->device & SID_TYPE;
494 removable = inqbuf->dev_qual2 & SID_REMOVABLE ? 1 : 0;
495
496 /*
497 * Figure out basic device type and qualifier.
498 */
499 dtype = 0;
500 switch (inqbuf->device & SID_QUAL) {
501 case SID_QUAL_LU_OK:
502 qtype = "";
503 break;
504
505 case SID_QUAL_LU_OFFLINE:
506 qtype = " offline";
507 break;
508
509 case SID_QUAL_RSVD:
510 case SID_QUAL_BAD_LU:
511 panic("scsibusprint: impossible qualifier");
512
513 default:
514 qtype = "";
515 dtype = "vendor-unique";
516 break;
517 }
518 if (dtype == 0) {
519 switch (type) {
520 case T_DIRECT:
521 dtype = "direct";
522 break;
523 case T_SEQUENTIAL:
524 dtype = "sequential";
525 break;
526 case T_PRINTER:
527 dtype = "printer";
528 break;
529 case T_PROCESSOR:
530 dtype = "processor";
531 break;
532 case T_CDROM:
533 dtype = "cdrom";
534 break;
535 case T_WORM:
536 dtype = "worm";
537 break;
538 case T_SCANNER:
539 dtype = "scanner";
540 break;
541 case T_OPTICAL:
542 dtype = "optical";
543 break;
544 case T_CHANGER:
545 dtype = "changer";
546 break;
547 case T_COMM:
548 dtype = "communication";
549 break;
550 case T_ENCLOSURE:
551 dtype = "enclosure services";
552 break;
553 case T_RDIRECT:
554 dtype = "simplified direct";
555 break;
556 case T_NODEVICE:
557 panic("scsibusprint: impossible device type");
558 default:
559 dtype = "unknown";
560 break;
561 }
562 }
563
564 scsi_strvis(vendor, inqbuf->vendor, 8);
565 scsi_strvis(product, inqbuf->product, 16);
566 scsi_strvis(revision, inqbuf->revision, 4);
567
568 printf(" targ %d lun %d: <%s, %s, %s> SCSI%d %d/%s %s%s",
569 target, lun, vendor, product, revision,
570 inqbuf->version & SID_ANSII, type, dtype,
571 removable ? "removable" : "fixed", qtype);
572
573 return (UNCONF);
574 }
575
576 /*
577 * Given a target and lun, ask the device what it is, and find the correct
578 * driver table entry.
579 *
580 * Return 0 if further LUNs are possible, EINVAL if not.
581 */
582 int
scsi_probedev(scsi,inqbuflun0,target,lun)583 scsi_probedev(scsi, inqbuflun0, target, lun)
584 struct scsibus_softc *scsi;
585 struct scsi_inquiry_data *inqbuflun0;
586 int target, lun;
587 {
588 struct scsi_link *sc_link;
589 static struct scsi_inquiry_data inqbuf;
590 const struct scsi_quirk_inquiry_pattern *finger;
591 int priority, rslt = 0;
592 struct scsibus_attach_args sa;
593 struct cfdata *cf;
594
595 /* Skip this slot if it is already attached and try the next LUN. */
596 if (scsi->sc_link[target][lun])
597 return (0);
598
599 sc_link = malloc(sizeof(*sc_link), M_DEVBUF, M_NOWAIT);
600 if (sc_link == NULL)
601 return (EINVAL);
602
603 *sc_link = *scsi->adapter_link;
604 sc_link->target = target;
605 sc_link->lun = lun;
606 sc_link->device = &probe_switch;
607 sc_link->inquiry_flags = 0;
608
609 SC_DEBUG(sc_link, SDEV_DB2, ("scsi_link created.\n"));
610
611 /*
612 * Tell drivers that are paying attention to avoid sync/wide/tags until
613 * INQUIRY data has been processed and the quirks information is
614 * complete. Some drivers set bits in quirks before we get here, so
615 * just add NOTAGS, NOWIDE and NOSYNC.
616 */
617 sc_link->quirks |= SDEV_NOSYNC | SDEV_NOWIDE | SDEV_NOTAGS;
618
619 /*
620 * Ask the device what it is
621 */
622 #ifdef SCSIDEBUG
623 if (((1 << sc_link->scsibus) & scsidebug_buses) &&
624 ((1 << target) & scsidebug_targets) &&
625 ((1 << lun) & scsidebug_luns))
626 sc_link->flags |= scsidebug_level;
627 #endif /* SCSIDEBUG */
628
629 #if defined(mvme68k)
630 if (lun == 0) {
631 /* XXX some drivers depend on this */
632 scsi_test_unit_ready(sc_link, TEST_READY_RETRIES_DEFAULT,
633 scsi_autoconf | SCSI_IGNORE_ILLEGAL_REQUEST |
634 SCSI_IGNORE_NOT_READY | SCSI_IGNORE_MEDIA_CHANGE);
635 }
636 #endif
637
638 /* Now go ask the device all about itself. */
639 rslt = scsi_inquire(sc_link, &inqbuf, scsi_autoconf | SCSI_SILENT);
640 if (rslt != 0) {
641 SC_DEBUG(sc_link, SDEV_DB2, ("Bad LUN. rslt = %i\n", rslt));
642 if (lun == 0)
643 rslt = EINVAL;
644 goto bad;
645 }
646
647 switch (inqbuf.device & SID_QUAL) {
648 case SID_QUAL_RSVD:
649 case SID_QUAL_BAD_LU:
650 case SID_QUAL_LU_OFFLINE:
651 SC_DEBUG(sc_link, SDEV_DB1,
652 ("Bad LUN. SID_QUAL = 0x%02x\n", inqbuf.device & SID_QUAL));
653 goto bad;
654
655 case SID_QUAL_LU_OK:
656 if ((inqbuf.device & SID_TYPE) == T_NODEVICE) {
657 SC_DEBUG(sc_link, SDEV_DB1,
658 ("Bad LUN. SID_TYPE = T_NODEVICE\n"));
659 goto bad;
660 }
661 break;
662
663 default:
664 break;
665 }
666
667 if (lun == 0)
668 bcopy(&inqbuf, inqbuflun0, sizeof *inqbuflun0);
669 else if (((1 << sc_link->scsibus) & scsiforcelun_buses) &&
670 ((1 << target) & scsiforcelun_targets))
671 ;
672 else if (sc_link->flags & SDEV_UMASS)
673 ;
674 else if (memcmp(&inqbuf, inqbuflun0, sizeof inqbuf) == 0) {
675 /* The device doesn't distinguish between LUNs. */
676 SC_DEBUG(sc_link, SDEV_DB1, ("IDENTIFY not supported.\n"));
677 rslt = EINVAL;
678 goto bad;
679 }
680
681 finger = (const struct scsi_quirk_inquiry_pattern *)scsi_inqmatch(
682 &inqbuf, scsi_quirk_patterns,
683 sizeof(scsi_quirk_patterns)/sizeof(scsi_quirk_patterns[0]),
684 sizeof(scsi_quirk_patterns[0]), &priority);
685
686 /*
687 * Based upon the inquiry flags we got back, and if we're
688 * at SCSI-2 or better, remove some limiting quirks.
689 */
690 if ((inqbuf.version & SID_ANSII) >= 2) {
691 if ((inqbuf.flags & SID_CmdQue) != 0)
692 sc_link->quirks &= ~SDEV_NOTAGS;
693 if ((inqbuf.flags & SID_Sync) != 0)
694 sc_link->quirks &= ~SDEV_NOSYNC;
695 if ((inqbuf.flags & SID_WBus16) != 0)
696 sc_link->quirks &= ~SDEV_NOWIDE;
697 }
698 /*
699 * Now apply any quirks from the table.
700 */
701 if (priority != 0)
702 sc_link->quirks |= finger->quirks;
703 sc_link->scsi_version = inqbuf.version;
704
705 /*
706 * Save INQUIRY "flags" (SID_Linked, etc.) for low-level drivers.
707 */
708 sc_link->inquiry_flags = inqbuf.flags;
709 memcpy(&sc_link->inqdata, &inqbuf, sizeof(sc_link->inqdata));
710
711 /*
712 * note what BASIC type of device it is
713 */
714 if ((inqbuf.dev_qual2 & SID_REMOVABLE) != 0)
715 sc_link->flags |= SDEV_REMOVABLE;
716
717 sa.sa_sc_link = sc_link;
718 sa.sa_inqbuf = &inqbuf;
719
720 if ((cf = config_search(scsibussubmatch, (struct device *)scsi, &sa)) == 0) {
721 scsibusprint(&sa, scsi->sc_dev.dv_xname);
722 printf(" not configured\n");
723 goto bad;
724 }
725
726 /*
727 * Braindead USB devices, especially some x-in-1 media readers, try to
728 * 'help' by pretending any LUN is actually LUN 0 until they see a
729 * different LUN used in a command. So do an INQUIRY on LUN 1 at this
730 * point (since we are done with the data in inqbuf) to prevent such
731 * helpfulness before it causes confusion.
732 */
733 if (lun == 0 && (sc_link->flags & SDEV_UMASS) &&
734 scsi->sc_link[target][1] == NULL && sc_link->luns > 1) {
735 sc_link->lun = 1;
736 scsi_inquire(sc_link, &inqbuf, scsi_autoconf | SCSI_SILENT);
737 sc_link->lun = 0;
738 }
739
740 scsi->sc_link[target][lun] = sc_link;
741
742 /*
743 * Generate a TEST_UNIT_READY command. This gives drivers waiting for
744 * valid quirks data a chance to set wide/sync/tag options
745 * appropriately. It also clears any outstanding ACA conditions that
746 * INQUIRY may leave behind.
747 *
748 * Do this now so that any messages generated by config_attach() do not
749 * have negotiation messages inserted into their midst.
750 */
751 scsi_test_unit_ready(sc_link, TEST_READY_RETRIES_DEFAULT,
752 scsi_autoconf | SCSI_IGNORE_ILLEGAL_REQUEST |
753 SCSI_IGNORE_NOT_READY | SCSI_IGNORE_MEDIA_CHANGE);
754
755 config_attach((struct device *)scsi, cf, &sa, scsibusprint);
756
757 return (0);
758
759 bad:
760 free(sc_link, M_DEVBUF);
761 return (rslt);
762 }
763
764 /*
765 * Return a priority based on how much of the inquiry data matches
766 * the patterns for the particular driver.
767 */
768 const void *
scsi_inqmatch(inqbuf,base,nmatches,matchsize,bestpriority)769 scsi_inqmatch(inqbuf, base, nmatches, matchsize, bestpriority)
770 struct scsi_inquiry_data *inqbuf;
771 const void *base;
772 int nmatches, matchsize;
773 int *bestpriority;
774 {
775 u_int8_t type;
776 boolean removable;
777 const void *bestmatch;
778
779 /* Include the qualifier to catch vendor-unique types. */
780 type = inqbuf->device;
781 removable = inqbuf->dev_qual2 & SID_REMOVABLE ? T_REMOV : T_FIXED;
782
783 for (*bestpriority = 0, bestmatch = 0; nmatches--; base += matchsize) {
784 struct scsi_inquiry_pattern *match = (void *)base;
785 int priority, len;
786
787 if (type != match->type)
788 continue;
789 if (removable != match->removable)
790 continue;
791 priority = 2;
792 len = strlen(match->vendor);
793 if (bcmp(inqbuf->vendor, match->vendor, len))
794 continue;
795 priority += len;
796 len = strlen(match->product);
797 if (bcmp(inqbuf->product, match->product, len))
798 continue;
799 priority += len;
800 len = strlen(match->revision);
801 if (bcmp(inqbuf->revision, match->revision, len))
802 continue;
803 priority += len;
804
805 #if SCSIDEBUG
806 printf("scsi_inqmatch: %d/%d/%d <%s, %s, %s>\n",
807 priority, match->type, match->removable,
808 match->vendor, match->product, match->revision);
809 #endif
810 if (priority > *bestpriority) {
811 *bestpriority = priority;
812 bestmatch = base;
813 }
814 }
815
816 return (bestmatch);
817 }
818