1 /* $NetBSD: scsiconf.c,v 1.83 1997/04/24 00:49:14 mycroft Exp $ */ 2 3 /* 4 * Copyright (c) 1994 Charles Hannum. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Charles Hannum. 17 * 4. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Originally written by Julian Elischer (julian@tfs.com) 34 * for TRW Financial Systems for use under the MACH(2.5) operating system. 35 * 36 * TRW Financial Systems, in accordance with their agreement with Carnegie 37 * Mellon University, makes this software available to CMU to distribute 38 * or use in any manner that they see fit as long as this message is kept with 39 * the software. For this reason TFS also grants any other persons or 40 * organisations permission to use or modify this software. 41 * 42 * TFS supplies this software to be publicly redistributed 43 * on the understanding that TFS is not responsible for the correct 44 * functioning of this software in any circumstances. 45 * 46 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 47 */ 48 49 #include <sys/types.h> 50 #include <sys/param.h> 51 #include <sys/systm.h> 52 #include <sys/malloc.h> 53 #include <sys/device.h> 54 55 #include <scsi/scsi_all.h> 56 #include <scsi/scsiconf.h> 57 58 #if 0 59 #if NCALS > 0 60 { T_PROCESSOR, T_FIXED, 1, 61 0, 0, 0 }, 62 #endif /* NCALS */ 63 #if NBLL > 0 64 { T_PROCESSOR, T_FIXED, 1, 65 "AEG ", "READER ", "V1.0" }, 66 #endif /* NBLL */ 67 #if NKIL > 0 68 { T_SCANNER, T_FIXED, 0, 69 "KODAK ", "IL Scanner 900 ", 0 }, 70 #endif /* NKIL */ 71 #endif 72 73 /* 74 * Declarations 75 */ 76 void scsi_probedev __P((struct scsibus_softc *, int, int)); 77 int scsi_probe_bus __P((int bus, int target, int lun)); 78 79 struct scsi_device probe_switch = { 80 NULL, 81 NULL, 82 NULL, 83 NULL, 84 }; 85 86 #ifdef __BROKEN_INDIRECT_CONFIG 87 int scsibusmatch __P((struct device *, void *, void *)); 88 #else 89 int scsibusmatch __P((struct device *, struct cfdata *, void *)); 90 #endif 91 void scsibusattach __P((struct device *, struct device *, void *)); 92 #ifdef __BROKEN_INDIRECT_CONFIG 93 int scsibussubmatch __P((struct device *, void *, void *)); 94 #else 95 int scsibussubmatch __P((struct device *, struct cfdata *, void *)); 96 #endif 97 98 struct cfattach scsibus_ca = { 99 sizeof(struct scsibus_softc), scsibusmatch, scsibusattach 100 }; 101 102 struct cfdriver scsibus_cd = { 103 NULL, "scsibus", DV_DULL 104 }; 105 106 int scsibusprint __P((void *, const char *)); 107 108 int 109 scsiprint(aux, pnp) 110 void *aux; 111 const char *pnp; 112 { 113 struct scsi_link *l = aux; 114 115 /* only "scsibus"es can attach to "scsi"s; easy. */ 116 if (pnp) 117 printf("scsibus at %s", pnp); 118 119 /* don't print channel if the controller says there can be only one. */ 120 if (l->channel != SCSI_CHANNEL_ONLY_ONE) 121 printf(" channel %d", l->channel); 122 123 return (UNCONF); 124 } 125 126 int 127 #ifdef __BROKEN_INDIRECT_CONFIG 128 scsibusmatch(parent, match, aux) 129 #else 130 scsibusmatch(parent, cf, aux) 131 #endif 132 struct device *parent; 133 #ifdef __BROKEN_INDIRECT_CONFIG 134 void *match; 135 #else 136 struct cfdata *cf; 137 #endif 138 void *aux; 139 { 140 #ifdef __BROKEN_INDIRECT_CONFIG 141 struct cfdata *cf = match; 142 #endif 143 struct scsi_link *l = aux; 144 int channel; 145 146 /* 147 * Allow single-channel controllers to specify their channel 148 * in a special way, so that it's not printed. 149 */ 150 channel = (l->channel != SCSI_CHANNEL_ONLY_ONE) ? l->channel : 0; 151 152 if (cf->scsicf_channel != channel && 153 cf->scsicf_channel != SCSI_CHANNEL_UNKNOWN) 154 return (0); 155 156 return (1); 157 } 158 159 /* 160 * The routine called by the adapter boards to get all their 161 * devices configured in. 162 */ 163 void 164 scsibusattach(parent, self, aux) 165 struct device *parent, *self; 166 void *aux; 167 { 168 struct scsibus_softc *sb = (struct scsibus_softc *)self; 169 struct scsi_link *sc_link_proto = aux; 170 size_t nbytes; 171 int i; 172 173 sc_link_proto->scsibus = sb->sc_dev.dv_unit; 174 sb->adapter_link = sc_link_proto; 175 sb->sc_maxtarget = sc_link_proto->max_target; 176 printf(": %d targets\n", sb->sc_maxtarget + 1); 177 178 nbytes = sb->sc_maxtarget * sizeof(struct scsi_link **); 179 sb->sc_link = (struct scsi_link ***)malloc(nbytes, M_DEVBUF, 180 M_NOWAIT); 181 if (sb->sc_link == NULL) 182 panic("scsibusattach: can't allocate target links"); 183 184 nbytes = 8 * sizeof(struct scsi_link *); 185 for (i = 0; i <= sb->sc_maxtarget; i++) { 186 sb->sc_link[i] = (struct scsi_link **)malloc(nbytes, 187 M_DEVBUF, M_NOWAIT); 188 if (sb->sc_link[i] == NULL) 189 panic("scsibusattach: can't allocate lun links"); 190 bzero(sb->sc_link[i], nbytes); 191 } 192 193 #if defined(SCSI_DELAY) && SCSI_DELAY > 2 194 printf("%s: waiting for scsi devices to settle\n", 195 sb->sc_dev.dv_xname); 196 #else /* SCSI_DELAY > 2 */ 197 #undef SCSI_DELAY 198 #define SCSI_DELAY 2 199 #endif /* SCSI_DELAY */ 200 delay(1000000 * SCSI_DELAY); 201 202 scsi_probe_bus(sb->sc_dev.dv_unit, -1, -1); 203 } 204 205 int 206 #ifdef __BROKEN_INDIRECT_CONFIG 207 scsibussubmatch(parent, match, aux) 208 #else 209 scsibussubmatch(parent, cf, aux) 210 #endif 211 struct device *parent; 212 #ifdef __BROKEN_INDIRECT_CONFIG 213 void *match; 214 #else 215 struct cfdata *cf; 216 #endif 217 void *aux; 218 { 219 #ifdef __BROKEN_INDIRECT_CONFIG 220 struct cfdata *cf = match; 221 #endif 222 struct scsibus_attach_args *sa = aux; 223 struct scsi_link *sc_link = sa->sa_sc_link; 224 225 if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != sc_link->target) 226 return 0; 227 if (cf->cf_loc[1] != -1 && cf->cf_loc[1] != sc_link->lun) 228 return 0; 229 return ((*cf->cf_attach->ca_match)(parent, cf, aux)); 230 } 231 232 /* 233 * Probe the requested scsi bus. It must be already set up. 234 * -1 requests all set up scsi busses. 235 * target and lun optionally narrow the search if not -1 236 */ 237 int 238 scsi_probe_busses(bus, target, lun) 239 int bus, target, lun; 240 { 241 242 if (bus == -1) { 243 for (bus = 0; bus < scsibus_cd.cd_ndevs; bus++) 244 if (scsibus_cd.cd_devs[bus]) 245 scsi_probe_bus(bus, target, lun); 246 return 0; 247 } else { 248 return scsi_probe_bus(bus, target, lun); 249 } 250 } 251 252 /* 253 * Probe the requested scsi bus. It must be already set up. 254 * target and lun optionally narrow the search if not -1 255 */ 256 int 257 scsi_probe_bus(bus, target, lun) 258 int bus, target, lun; 259 { 260 struct scsibus_softc *scsi; 261 int maxtarget, mintarget, maxlun, minlun; 262 u_int8_t scsi_addr; 263 264 if (bus < 0 || bus >= scsibus_cd.cd_ndevs) 265 return ENXIO; 266 scsi = scsibus_cd.cd_devs[bus]; 267 if (!scsi) 268 return ENXIO; 269 270 scsi_addr = scsi->adapter_link->adapter_target; 271 272 if (target == -1) { 273 maxtarget = scsi->sc_maxtarget; 274 mintarget = 0; 275 } else { 276 if (target < 0 || target > scsi->sc_maxtarget) 277 return EINVAL; 278 maxtarget = mintarget = target; 279 } 280 281 if (lun == -1) { 282 maxlun = 7; 283 minlun = 0; 284 } else { 285 if (lun < 0 || lun > 7) 286 return EINVAL; 287 maxlun = minlun = lun; 288 } 289 290 for (target = mintarget; target <= maxtarget; target++) { 291 if (target == scsi_addr) 292 continue; 293 for (lun = minlun; lun <= maxlun; lun++) { 294 /* 295 * See if there's a device present, and configure it. 296 */ 297 scsi_probedev(scsi, target, lun); 298 if ((scsi->moreluns & (1 << target)) == 0) 299 break; 300 /* otherwise something says we should look further */ 301 } 302 } 303 return 0; 304 } 305 306 void 307 scsi_strvis(dst, src, len) 308 u_char *dst, *src; 309 int len; 310 { 311 312 /* Trim leading and trailing blanks and NULs. */ 313 while (len > 0 && (src[0] == ' ' || src[0] == '\0')) 314 ++src, --len; 315 while (len > 0 && (src[len-1] == ' ' || src[len-1] == '\0')) 316 --len; 317 318 while (len > 0) { 319 if (*src < 0x20 || *src >= 0x80) { 320 /* non-printable characters */ 321 *dst++ = '\\'; 322 *dst++ = ((*src & 0300) >> 6) + '0'; 323 *dst++ = ((*src & 0070) >> 3) + '0'; 324 *dst++ = ((*src & 0007) >> 0) + '0'; 325 } else if (*src == '\\') { 326 /* quote characters */ 327 *dst++ = '\\'; 328 *dst++ = '\\'; 329 } else { 330 /* normal characters */ 331 *dst++ = *src; 332 } 333 ++src, --len; 334 } 335 336 *dst++ = 0; 337 } 338 339 struct scsi_quirk_inquiry_pattern { 340 struct scsi_inquiry_pattern pattern; 341 u_int8_t quirks; 342 }; 343 344 struct scsi_quirk_inquiry_pattern scsi_quirk_patterns[] = { 345 {{T_CDROM, T_REMOV, 346 "CHINON ", "CD-ROM CDS-431 ", ""}, SDEV_NOLUNS}, 347 {{T_CDROM, T_REMOV, 348 "Chinon ", "CD-ROM CDS-525 ", ""}, SDEV_NOLUNS}, 349 {{T_CDROM, T_REMOV, 350 "CHINON ", "CD-ROM CDS-535 ", ""}, SDEV_NOLUNS}, 351 {{T_CDROM, T_REMOV, 352 "DENON ", "DRD-25X ", "V"}, SDEV_NOLUNS}, 353 {{T_CDROM, T_REMOV, 354 "HP ", "C4324/C4325 ", ""}, SDEV_NOLUNS}, 355 {{T_CDROM, T_REMOV, 356 "IMS ", "CDD521/10 ", "2.06"}, SDEV_NOLUNS}, 357 {{T_CDROM, T_REMOV, 358 "MATSHITA", "CD-ROM CR-5XX ", "1.0b"}, SDEV_NOLUNS}, 359 {{T_CDROM, T_REMOV, 360 "MEDIAVIS", "CDR-H93MV ", "1.3"}, SDEV_NOLUNS}, 361 {{T_CDROM, T_REMOV, 362 "NEC ", "CD-ROM DRIVE:55 ", ""}, SDEV_NOLUNS}, 363 {{T_CDROM, T_REMOV, 364 "NEC ", "CD-ROM DRIVE:83 ", ""}, SDEV_NOLUNS}, 365 {{T_CDROM, T_REMOV, 366 "NEC ", "CD-ROM DRIVE:84 ", ""}, SDEV_NOLUNS}, 367 {{T_CDROM, T_REMOV, 368 "NEC ", "CD-ROM DRIVE:841", ""}, SDEV_NOLUNS}, 369 {{T_CDROM, T_REMOV, 370 "PIONEER ", "CD-ROM DR-124X ", "1.01"}, SDEV_NOLUNS}, 371 {{T_CDROM, T_REMOV, 372 "SONY ", "CD-ROM CDU-541 ", ""}, SDEV_NOLUNS}, 373 {{T_CDROM, T_REMOV, 374 "SONY ", "CD-ROM CDU-55S ", ""}, SDEV_NOLUNS}, 375 {{T_CDROM, T_REMOV, 376 "SONY ", "CD-ROM CDU-8003A", ""}, SDEV_NOLUNS}, 377 {{T_CDROM, T_REMOV, 378 "SONY ", "CD-ROM CDU-8012 ", ""}, SDEV_NOLUNS}, 379 {{T_CDROM, T_REMOV, 380 "TEAC ", "CD-ROM ", "1.06"}, SDEV_NOLUNS}, 381 {{T_CDROM, T_REMOV, 382 "TEAC ", "CD-ROM CD-56S ", "1.0B"}, SDEV_NOLUNS}, 383 {{T_CDROM, T_REMOV, 384 "TEXEL ", "CD-ROM ", "1.06"}, SDEV_NOLUNS}, 385 {{T_CDROM, T_REMOV, 386 "TEXEL ", "CD-ROM DM-XX24 K", "1.10"}, SDEV_NOLUNS}, 387 {{T_CDROM, T_REMOV, 388 "ShinaKen", "CD-ROM DM-3x1S", "1.04"}, SDEV_NOLUNS}, 389 {{T_DIRECT, T_FIXED, 390 "MICROP ", "1588-15MBSUN0669", ""}, SDEV_AUTOSAVE}, 391 {{T_OPTICAL, T_REMOV, 392 "EPSON ", "OMD-5010 ", "3.08"}, SDEV_NOLUNS}, 393 394 {{T_DIRECT, T_FIXED, 395 "DEC ", "RZ55 (C) DEC", ""}, SDEV_AUTOSAVE}, 396 {{T_DIRECT, T_FIXED, 397 "EMULEX ", "MD21/S2 ESDI", "A00"}, SDEV_FORCELUNS|SDEV_AUTOSAVE}, 398 {{T_DIRECT, T_FIXED, 399 "IBMRAID ", "0662S", ""}, SDEV_AUTOSAVE}, 400 {{T_DIRECT, T_FIXED, 401 "IBM ", "0663H", ""}, SDEV_AUTOSAVE}, 402 {{T_DIRECT, T_FIXED, 403 "IBM", "0664", ""}, SDEV_AUTOSAVE}, 404 /* Broken IBM disk */ 405 {{T_DIRECT, T_FIXED, 406 "" , "DFRSS2F", ""}, SDEV_AUTOSAVE}, 407 {{T_DIRECT, T_FIXED, 408 "MAXTOR ", "XT-3280 ", ""}, SDEV_NOLUNS}, 409 {{T_DIRECT, T_FIXED, 410 "MAXTOR ", "XT-4380S ", ""}, SDEV_NOLUNS}, 411 {{T_DIRECT, T_FIXED, 412 "MAXTOR ", "MXT-1240S ", ""}, SDEV_NOLUNS}, 413 {{T_DIRECT, T_FIXED, 414 "MAXTOR ", "XT-4170S ", ""}, SDEV_NOLUNS}, 415 {{T_DIRECT, T_FIXED, 416 "MAXTOR ", "XT-8760S", ""}, SDEV_NOLUNS}, 417 {{T_DIRECT, T_FIXED, 418 "MAXTOR ", "LXT-213S ", ""}, SDEV_NOLUNS}, 419 {{T_DIRECT, T_FIXED, 420 "MAXTOR ", "LXT-213S SUN0207", ""}, SDEV_NOLUNS}, 421 {{T_DIRECT, T_FIXED, 422 "MAXTOR ", "LXT-200S ", ""}, SDEV_NOLUNS}, 423 {{T_DIRECT, T_FIXED, 424 "MST ", "SnapLink ", ""}, SDEV_NOLUNS}, 425 {{T_DIRECT, T_FIXED, 426 "NEC ", "D3847 ", "0307"}, SDEV_NOLUNS}, 427 {{T_DIRECT, T_FIXED, 428 "QUANTUM ", "LPS525S ", ""}, SDEV_NOLUNS}, 429 {{T_DIRECT, T_FIXED, 430 "QUANTUM ", "P105S 910-10-94x", ""}, SDEV_NOLUNS}, 431 {{T_DIRECT, T_FIXED, 432 "QUANTUM ", "PD1225S ", ""}, SDEV_NOLUNS}, 433 {{T_DIRECT, T_FIXED, 434 "QUANTUM ", "PD210S SUN0207", ""}, SDEV_NOLUNS}, 435 {{T_DIRECT, T_FIXED, 436 "RODIME ", "RO3000S ", ""}, SDEV_NOLUNS}, 437 {{T_DIRECT, T_FIXED, 438 "SEAGATE ", "ST125N ", ""}, SDEV_NOLUNS}, 439 {{T_DIRECT, T_FIXED, 440 "SEAGATE ", "ST157N ", ""}, SDEV_NOLUNS}, 441 {{T_DIRECT, T_FIXED, 442 "SEAGATE ", "ST296 ", ""}, SDEV_NOLUNS}, 443 {{T_DIRECT, T_FIXED, 444 "SEAGATE ", "ST296N ", ""}, SDEV_NOLUNS}, 445 {{T_DIRECT, T_FIXED, 446 "TOSHIBA ", "MK538FB ", "6027"}, SDEV_NOLUNS}, 447 {{T_DIRECT, T_REMOV, 448 "iomega", "jaz 1GB", ""}, SDEV_NOMODESENSE}, 449 {{T_DIRECT, T_REMOV, 450 "IOMEGA", "ZIP 100", ""}, SDEV_NOMODESENSE}, 451 /* Letting the motor run kills floppy drives and disks quit fast. */ 452 {{T_DIRECT, T_REMOV, 453 "TEAC", "FC-1", ""}, SDEV_NOSTARTUNIT}, 454 455 /* XXX: QIC-36 tape behind Emulex adapter. Very broken. */ 456 {{T_SEQUENTIAL, T_REMOV, 457 " ", " ", " "}, SDEV_NOLUNS}, 458 {{T_SEQUENTIAL, T_REMOV, 459 "CALIPER ", "CP150 ", ""}, SDEV_NOLUNS}, 460 {{T_SEQUENTIAL, T_REMOV, 461 "EXABYTE ", "EXB-8200 ", ""}, SDEV_NOLUNS}, 462 {{T_SEQUENTIAL, T_REMOV, 463 "SONY ", "SDT-2000 ", "2.09"}, SDEV_NOLUNS}, 464 {{T_SEQUENTIAL, T_REMOV, 465 "SONY ", "SDT-5000 ", "3."}, SDEV_NOSYNCWIDE}, 466 {{T_SEQUENTIAL, T_REMOV, 467 "SONY ", "SDT-5200 ", "3."}, SDEV_NOLUNS}, 468 {{T_SEQUENTIAL, T_REMOV, 469 "TANDBERG", " TDC 3600 ", ""}, SDEV_NOLUNS}, 470 /* Following entry reported as a Tandberg 3600; ref. PR1933 */ 471 {{T_SEQUENTIAL, T_REMOV, 472 "ARCHIVE ", "VIPER 150 21247", ""}, SDEV_NOLUNS}, 473 {{T_SEQUENTIAL, T_REMOV, 474 "ARCHIVE ", "Python 28454-XXX", ""}, SDEV_NOLUNS}, 475 {{T_SEQUENTIAL, T_REMOV, 476 "WANGTEK ", "5099ES SCSI", ""}, SDEV_NOLUNS}, 477 {{T_SEQUENTIAL, T_REMOV, 478 "WANGTEK ", "5150ES SCSI", ""}, SDEV_NOLUNS}, 479 {{T_SEQUENTIAL, T_REMOV, 480 "WangDAT ", "Model 1300 ", "02.4"}, SDEV_NOSYNCWIDE}, 481 {{T_SEQUENTIAL, T_REMOV, 482 "WangDAT ", "Model 2600 ", "01.7"}, SDEV_NOSYNCWIDE}, 483 {{T_SEQUENTIAL, T_REMOV, 484 "WangDAT ", "Model 3200 ", "02.2"}, SDEV_NOSYNCWIDE}, 485 }; 486 487 /* 488 * Print out autoconfiguration information for a subdevice. 489 * 490 * This is a slight abuse of 'standard' autoconfiguration semantics, 491 * because 'print' functions don't normally print the colon and 492 * device information. However, in this case that's better than 493 * either printing redundant information before the attach message, 494 * or having the device driver call a special function to print out 495 * the standard device information. 496 */ 497 int 498 scsibusprint(aux, pnp) 499 void *aux; 500 const char *pnp; 501 { 502 struct scsibus_attach_args *sa = aux; 503 struct scsi_inquiry_data *inqbuf; 504 u_int8_t type; 505 boolean removable; 506 char *dtype, *qtype; 507 char vendor[33], product[65], revision[17]; 508 int target, lun; 509 510 if (pnp != NULL) 511 printf("%s", pnp); 512 513 inqbuf = sa->sa_inqbuf; 514 515 target = sa->sa_sc_link->target; 516 lun = sa->sa_sc_link->lun; 517 518 type = inqbuf->device & SID_TYPE; 519 removable = inqbuf->dev_qual2 & SID_REMOVABLE ? 1 : 0; 520 521 /* 522 * Figure out basic device type and qualifier. 523 */ 524 dtype = 0; 525 switch (inqbuf->device & SID_QUAL) { 526 case SID_QUAL_LU_OK: 527 qtype = ""; 528 break; 529 530 case SID_QUAL_LU_OFFLINE: 531 qtype = " offline"; 532 break; 533 534 case SID_QUAL_RSVD: 535 case SID_QUAL_BAD_LU: 536 panic("scsibusprint: impossible qualifier"); 537 538 default: 539 qtype = ""; 540 dtype = "vendor-unique"; 541 break; 542 } 543 if (dtype == 0) { 544 switch (type) { 545 case T_DIRECT: 546 dtype = "direct"; 547 break; 548 case T_SEQUENTIAL: 549 dtype = "sequential"; 550 break; 551 case T_PRINTER: 552 dtype = "printer"; 553 break; 554 case T_PROCESSOR: 555 dtype = "processor"; 556 break; 557 case T_CDROM: 558 dtype = "cdrom"; 559 break; 560 case T_WORM: 561 dtype = "worm"; 562 break; 563 case T_SCANNER: 564 dtype = "scanner"; 565 break; 566 case T_OPTICAL: 567 dtype = "optical"; 568 break; 569 case T_CHANGER: 570 dtype = "changer"; 571 break; 572 case T_COMM: 573 dtype = "communication"; 574 break; 575 case T_NODEVICE: 576 panic("scsibusprint: impossible device type"); 577 default: 578 dtype = "unknown"; 579 break; 580 } 581 } 582 583 scsi_strvis(vendor, inqbuf->vendor, 8); 584 scsi_strvis(product, inqbuf->product, 16); 585 scsi_strvis(revision, inqbuf->revision, 4); 586 587 printf(" targ %d lun %d: <%s, %s, %s> SCSI%d %d/%s %s%s", 588 target, lun, vendor, product, revision, 589 inqbuf->version & SID_ANSII, type, dtype, 590 removable ? "removable" : "fixed", qtype); 591 592 return (UNCONF); 593 } 594 595 /* 596 * given a target and lu, ask the device what 597 * it is, and find the correct driver table 598 * entry. 599 */ 600 void 601 scsi_probedev(scsi, target, lun) 602 struct scsibus_softc *scsi; 603 int target, lun; 604 { 605 struct scsi_link *sc_link; 606 static struct scsi_inquiry_data inqbuf; 607 struct scsi_quirk_inquiry_pattern *finger; 608 int checkdtype, priority; 609 struct scsibus_attach_args sa; 610 struct cfdata *cf; 611 612 /* Skip this slot if it is already attached. */ 613 if (scsi->sc_link[target][lun]) 614 return; 615 616 sc_link = malloc(sizeof(*sc_link), M_DEVBUF, M_NOWAIT); 617 *sc_link = *scsi->adapter_link; 618 sc_link->target = target; 619 sc_link->lun = lun; 620 sc_link->device = &probe_switch; 621 622 /* 623 * Ask the device what it is 624 */ 625 #ifdef SCSIDEBUG 626 if (target == DEBUGTARGET && lun == DEBUGLUN) 627 sc_link->flags |= DEBUGLEVEL; 628 #endif /* SCSIDEBUG */ 629 630 (void) scsi_test_unit_ready(sc_link, 631 SCSI_AUTOCONF | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY | SCSI_IGNORE_MEDIA_CHANGE); 632 633 #ifdef SCSI_2_DEF 634 /* some devices need to be told to go to SCSI2 */ 635 /* However some just explode if you tell them this.. leave it out */ 636 scsi_change_def(sc_link, SCSI_AUTOCONF | SCSI_SILENT); 637 #endif /* SCSI_2_DEF */ 638 639 /* Now go ask the device all about itself. */ 640 bzero(&inqbuf, sizeof(inqbuf)); 641 if (scsi_inquire(sc_link, &inqbuf, SCSI_AUTOCONF) != 0) 642 goto bad; 643 644 { 645 int len = inqbuf.additional_length; 646 while (len < 3) 647 inqbuf.unused[len++] = '\0'; 648 while (len < 3 + 28) 649 inqbuf.unused[len++] = ' '; 650 } 651 652 finger = (struct scsi_quirk_inquiry_pattern *)scsi_inqmatch(&inqbuf, 653 (caddr_t)scsi_quirk_patterns, 654 sizeof(scsi_quirk_patterns)/sizeof(scsi_quirk_patterns[0]), 655 sizeof(scsi_quirk_patterns[0]), &priority); 656 if (priority != 0) 657 sc_link->quirks |= finger->quirks; 658 if ((inqbuf.version & SID_ANSII) == 0 && 659 (sc_link->quirks & SDEV_FORCELUNS) == 0) 660 sc_link->quirks |= SDEV_NOLUNS; 661 sc_link->scsi_version = inqbuf.version; 662 663 if ((sc_link->quirks & SDEV_NOLUNS) == 0) 664 scsi->moreluns |= (1 << target); 665 666 /* 667 * note what BASIC type of device it is 668 */ 669 if ((inqbuf.dev_qual2 & SID_REMOVABLE) != 0) 670 sc_link->flags |= SDEV_REMOVABLE; 671 672 /* 673 * Any device qualifier that has the top bit set (qualifier&4 != 0) 674 * is vendor specific and won't match in this switch. 675 * All we do here is throw out bad/negative responses. 676 */ 677 checkdtype = 0; 678 switch (inqbuf.device & SID_QUAL) { 679 case SID_QUAL_LU_OK: 680 case SID_QUAL_LU_OFFLINE: 681 checkdtype = 1; 682 break; 683 684 case SID_QUAL_RSVD: 685 case SID_QUAL_BAD_LU: 686 goto bad; 687 688 default: 689 break; 690 } 691 if (checkdtype) { 692 switch (inqbuf.device & SID_TYPE) { 693 case T_DIRECT: 694 case T_SEQUENTIAL: 695 case T_PRINTER: 696 case T_PROCESSOR: 697 case T_CDROM: 698 case T_WORM: 699 case T_SCANNER: 700 case T_OPTICAL: 701 case T_CHANGER: 702 case T_COMM: 703 default: 704 break; 705 case T_NODEVICE: 706 goto bad; 707 } 708 } 709 710 sa.sa_sc_link = sc_link; 711 sa.sa_inqbuf = &inqbuf; 712 713 if ((cf = config_search(scsibussubmatch, (struct device *)scsi, &sa)) != 0) { 714 scsi->sc_link[target][lun] = sc_link; 715 config_attach((struct device *)scsi, cf, &sa, scsibusprint); 716 } else { 717 scsibusprint(&sa, scsi->sc_dev.dv_xname); 718 printf(" not configured\n"); 719 goto bad; 720 } 721 722 return; 723 724 bad: 725 free(sc_link, M_DEVBUF); 726 return; 727 } 728 729 /* 730 * Return a priority based on how much of the inquiry data matches 731 * the patterns for the particular driver. 732 */ 733 caddr_t 734 scsi_inqmatch(inqbuf, base, nmatches, matchsize, bestpriority) 735 struct scsi_inquiry_data *inqbuf; 736 caddr_t base; 737 int nmatches, matchsize; 738 int *bestpriority; 739 { 740 u_int8_t type; 741 boolean removable; 742 caddr_t bestmatch; 743 744 /* Include the qualifier to catch vendor-unique types. */ 745 type = inqbuf->device; 746 removable = inqbuf->dev_qual2 & SID_REMOVABLE ? T_REMOV : T_FIXED; 747 748 for (*bestpriority = 0, bestmatch = 0; nmatches--; base += matchsize) { 749 struct scsi_inquiry_pattern *match = (void *)base; 750 int priority, len; 751 752 if (type != match->type) 753 continue; 754 if (removable != match->removable) 755 continue; 756 priority = 2; 757 len = strlen(match->vendor); 758 if (bcmp(inqbuf->vendor, match->vendor, len)) 759 continue; 760 priority += len; 761 len = strlen(match->product); 762 if (bcmp(inqbuf->product, match->product, len)) 763 continue; 764 priority += len; 765 len = strlen(match->revision); 766 if (bcmp(inqbuf->revision, match->revision, len)) 767 continue; 768 priority += len; 769 770 #if SCSIDEBUG 771 printf("scsi_inqmatch: %d/%d/%d <%s, %s, %s>\n", 772 priority, match->type, match->removable, 773 match->vendor, match->product, match->revision); 774 #endif 775 if (priority > *bestpriority) { 776 *bestpriority = priority; 777 bestmatch = base; 778 } 779 } 780 781 return (bestmatch); 782 } 783