1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Utility SCSI configuration routines 31 */ 32 /* 33 * Many routines in this file have built in parallel bus assumption 34 * which might need to change as other interconnect evolve. 35 */ 36 37 38 #include <sys/scsi/scsi.h> 39 #include <sys/modctl.h> 40 41 /* 42 * macro for filling in lun value for scsi-1 support 43 */ 44 45 #define FILL_SCSI1_LUN(devp, pkt) \ 46 if ((devp->sd_address.a_lun > 0) && \ 47 (devp->sd_inq->inq_ansi == 0x1)) { \ 48 ((union scsi_cdb *)(pkt)->pkt_cdbp)->scc_lun = \ 49 devp->sd_address.a_lun; \ 50 } 51 52 extern struct mod_ops mod_miscops; 53 54 static struct modlmisc modlmisc = { 55 &mod_miscops, /* Type of module */ 56 "SCSI Bus Utility Routines" 57 }; 58 59 static struct modlinkage modlinkage = { 60 MODREV_1, (void *)&modlmisc, NULL 61 }; 62 63 static void create_inquiry_props(struct scsi_device *); 64 static void create_inquiry_property(dev_info_t *, char *, char *, uint_t); 65 static int get_inquiry_prop_len(char *, int); 66 67 static int scsi_check_ss2_LUN_limit(struct scsi_device *); 68 static void scsi_establish_LUN_limit(struct scsi_device *); 69 static void scsi_update_parent_ss2_prop(dev_info_t *, int, int); 70 71 /* 72 * this int-array HBA-node property keeps track of strictly SCSI-2 73 * target IDs 74 */ 75 #define SS2_LUN0_TGT_LIST_PROP "ss2-targets" 76 77 /* 78 * for keeping track of nodes for which we do *NOT* want to probe above LUN 7 79 * (i.e. strict SCSI-2 targets) 80 * 81 * note that we could also keep track of dtype (SCSI device type) and 82 * ANSI (SCSI standard conformance level), but all currently-known cases of 83 * this problem are on SCSI-2 PROCESSOR device types 84 */ 85 typedef struct ss2_lun0_info { 86 const char *sli_vid; /* SCSI inquiry VID */ 87 const char *sli_pid; /* SCSI inquiry PID */ 88 const char *sli_rev; /* SCSI inquiry REV */ 89 } ss2_lun0_info_t; 90 91 /* 92 * these two workarounds are for the SCSI-2 GEM2* chips used in the 93 * D1000 and D240 94 */ 95 #define SES_D1000_VID "SYMBIOS" 96 #define SES_D1000_PID "D1000" /* the D1000 */ 97 #define SES_D1000_REV "2" 98 99 #define SES_D240_VID "SUN" 100 #define SES_D240_PID "D240" /* the D240 */ 101 #define SES_D240_REV "2" 102 103 /* 104 * a static list of targets where we do *not* want to probe above LUN 7 105 */ 106 static const ss2_lun0_info_t scsi_probe_strict_s2_list[] = { 107 {SES_D1000_VID, SES_D1000_PID, SES_D1000_REV}, 108 {SES_D240_VID, SES_D240_PID, SES_D240_REV}, 109 }; 110 111 static const int scsi_probe_strict_s2_size = 112 sizeof (scsi_probe_strict_s2_list) / sizeof (struct ss2_lun0_info); 113 114 115 #ifdef DEBUG 116 117 int scsi_probe_debug = 0; 118 119 #define SCSI_PROBE_DEBUG0(l, s) \ 120 if (scsi_probe_debug >= (l)) printf(s) 121 #define SCSI_PROBE_DEBUG1(l, s, a1) \ 122 if (scsi_probe_debug >= (l)) printf(s, a1) 123 #define SCSI_PROBE_DEBUG2(l, s, a1, a2) \ 124 if (scsi_probe_debug >= (l)) printf(s, a1, a2) 125 #define SCSI_PROBE_DEBUG3(l, s, a1, a2, a3) \ 126 if (scsi_probe_debug >= (l)) printf(s, a1, a2, a3) 127 128 #else /* DEBUG */ 129 130 #define SCSI_PROBE_DEBUG0(l, s) 131 #define SCSI_PROBE_DEBUG1(l, s, a1) 132 #define SCSI_PROBE_DEBUG2(l, s, a1, a2) 133 #define SCSI_PROBE_DEBUG3(l, s, a1, a2, a3) 134 135 #endif /* DEBUG */ 136 137 int scsi_test_busy_timeout = SCSI_POLL_TIMEOUT; /* in seconds */ 138 int scsi_test_busy_delay = 10000; /* 10msec in usec */ 139 140 int 141 _init() 142 { 143 scsi_initialize_hba_interface(); 144 scsi_watch_init(); 145 return (mod_install(&modlinkage)); 146 } 147 148 /* 149 * there is no _fini() routine because this module is never unloaded 150 */ 151 152 int 153 _info(struct modinfo *modinfop) 154 { 155 return (mod_info(&modlinkage, modinfop)); 156 } 157 158 #define ROUTE (&devp->sd_address) 159 160 static int 161 scsi_slave_do_rqsense(struct scsi_device *devp, int (*callback)()) 162 { 163 struct scsi_pkt *rq_pkt = NULL; 164 struct buf *rq_bp = NULL; 165 int rval = SCSIPROBE_EXISTS; 166 167 /* 168 * prepare rqsense packet 169 */ 170 rq_bp = scsi_alloc_consistent_buf(ROUTE, 171 (struct buf *)NULL, 172 (uint_t)SENSE_LENGTH, B_READ, callback, NULL); 173 if (rq_bp == NULL) { 174 rval = SCSIPROBE_NOMEM; 175 goto out; 176 } 177 178 rq_pkt = scsi_init_pkt(ROUTE, (struct scsi_pkt *)NULL, 179 rq_bp, CDB_GROUP0, 1, 0, PKT_CONSISTENT, 180 callback, NULL); 181 182 if (rq_pkt == NULL) { 183 if (rq_bp->b_error == 0) 184 rval = SCSIPROBE_NOMEM_CB; 185 else 186 rval = SCSIPROBE_NOMEM; 187 goto out; 188 } 189 ASSERT(rq_bp->b_error == 0); 190 191 (void) scsi_setup_cdb((union scsi_cdb *)rq_pkt-> 192 pkt_cdbp, SCMD_REQUEST_SENSE, 0, SENSE_LENGTH, 0); 193 FILL_SCSI1_LUN(devp, rq_pkt); 194 rq_pkt->pkt_flags = FLAG_NOINTR|FLAG_NOPARITY|FLAG_SENSING; 195 196 /* 197 * The controller type is as yet unknown, so we 198 * have to do a throwaway non-extended request sense, 199 * and hope that that clears the check condition 200 * for that unit until we can find out what kind 201 * of drive it is. A non-extended request sense 202 * is specified by stating that the sense block 203 * has 0 length, which is taken to mean that it 204 * is four bytes in length. 205 */ 206 if (scsi_poll(rq_pkt) < 0) { 207 rval = SCSIPROBE_FAILURE; 208 } 209 210 out: 211 if (rq_pkt) { 212 scsi_destroy_pkt(rq_pkt); 213 } 214 if (rq_bp) { 215 scsi_free_consistent_buf(rq_bp); 216 } 217 218 return (rval); 219 } 220 221 /* 222 * 223 * SCSI slave probe routine - provided as a service to target drivers 224 * 225 * Mostly attempts to allocate and fill devp inquiry data.. 226 */ 227 228 int 229 scsi_slave(struct scsi_device *devp, int (*callback)()) 230 { 231 struct scsi_pkt *pkt; 232 int rval = SCSIPROBE_EXISTS; 233 234 /* 235 * the first test unit ready will tell us whether a target 236 * responded and if there was one, it will clear the unit attention 237 * condition 238 */ 239 pkt = scsi_init_pkt(ROUTE, (struct scsi_pkt *)NULL, NULL, 240 CDB_GROUP0, sizeof (struct scsi_arq_status), 0, 0, callback, NULL); 241 242 if (pkt == NULL) { 243 return (SCSIPROBE_NOMEM_CB); 244 } 245 246 (void) scsi_setup_cdb((union scsi_cdb *)pkt->pkt_cdbp, 247 SCMD_TEST_UNIT_READY, 0, 0, 0); 248 FILL_SCSI1_LUN(devp, pkt); 249 pkt->pkt_flags = FLAG_NOINTR|FLAG_NOPARITY; 250 251 if (scsi_poll(pkt) < 0) { 252 if (pkt->pkt_reason == CMD_INCOMPLETE) 253 rval = SCSIPROBE_NORESP; 254 else 255 rval = SCSIPROBE_FAILURE; 256 257 if ((pkt->pkt_state & STATE_ARQ_DONE) == 0) { 258 if (((struct scsi_status *)pkt->pkt_scbp)->sts_chk) 259 /* 260 * scanner and processor devices can return a 261 * check condition here 262 */ 263 rval = scsi_slave_do_rqsense(devp, callback); 264 } 265 266 if (rval != SCSIPROBE_EXISTS) { 267 scsi_destroy_pkt(pkt); 268 return (rval); 269 } 270 } 271 272 /* 273 * the second test unit ready, allows the host adapter to negotiate 274 * synchronous transfer period and offset 275 */ 276 if (scsi_poll(pkt) < 0) { 277 if (pkt->pkt_reason == CMD_INCOMPLETE) 278 rval = SCSIPROBE_NORESP; 279 else 280 rval = SCSIPROBE_FAILURE; 281 } 282 283 /* 284 * do a rqsense if there was a check condition and ARQ was not done 285 */ 286 if ((pkt->pkt_state & STATE_ARQ_DONE) == 0) { 287 if (((struct scsi_status *)pkt->pkt_scbp)->sts_chk) { 288 rval = scsi_slave_do_rqsense(devp, callback); 289 } 290 } 291 292 /* 293 * call scsi_probe to do the inquiry 294 * XXX there is minor difference with the old scsi_slave implementation: 295 * busy conditions are not handled in scsi_probe. 296 */ 297 scsi_destroy_pkt(pkt); 298 if (rval == SCSIPROBE_EXISTS) { 299 return (scsi_probe(devp, callback)); 300 } else { 301 return (rval); 302 } 303 } 304 305 306 /* 307 * Undo scsi_slave - older interface, but still supported 308 */ 309 void 310 scsi_unslave(struct scsi_device *devp) 311 { 312 if (devp->sd_inq) { 313 kmem_free((caddr_t)devp->sd_inq, SUN_INQSIZE); 314 devp->sd_inq = (struct scsi_inquiry *)NULL; 315 } 316 } 317 318 319 /* 320 * Undo scsi_probe 321 */ 322 void 323 scsi_unprobe(struct scsi_device *devp) 324 { 325 if (devp->sd_inq) { 326 kmem_free((caddr_t)devp->sd_inq, SUN_INQSIZE); 327 devp->sd_inq = (struct scsi_inquiry *)NULL; 328 } 329 } 330 331 /* 332 * This is like scsi_poll, but only does retry for TRAN_BUSY. 333 */ 334 static int 335 scsi_test(struct scsi_pkt *pkt) 336 { 337 int rval = -1; 338 int wait_usec; 339 int rc; 340 extern int do_polled_io; 341 342 pkt->pkt_flags |= FLAG_NOINTR; 343 pkt->pkt_time = SCSI_POLL_TIMEOUT; /* in seconds */ 344 345 if (scsi_ifgetcap(&pkt->pkt_address, "tagged-qing", 1) == 1) { 346 pkt->pkt_flags |= FLAG_STAG; 347 } 348 349 /* 350 * Each TRAN_BUSY response waits scsi_test_busy_delay usec up to a 351 * maximum of scsi_test_busy_timeout. 352 */ 353 for (wait_usec = 0; (wait_usec / 1000000) <= scsi_test_busy_timeout; 354 wait_usec += scsi_test_busy_delay) { 355 356 /* Initialize pkt status variables */ 357 *pkt->pkt_scbp = pkt->pkt_reason = pkt->pkt_state = 0; 358 359 rc = scsi_transport(pkt); 360 if ((rc != TRAN_BUSY) || (scsi_test_busy_delay == 0) || 361 (scsi_test_busy_timeout == 0)) 362 break; 363 364 /* transport busy, wait */ 365 if ((curthread->t_flag & T_INTR_THREAD) == 0 && !do_polled_io) { 366 delay(drv_usectohz(scsi_test_busy_delay)); 367 } else { 368 /* we busy wait during cpr_dump or interrupt threads */ 369 drv_usecwait(scsi_test_busy_delay); 370 } 371 } 372 373 if (rc != TRAN_ACCEPT) { 374 goto exit; 375 } else if (pkt->pkt_reason == CMD_INCOMPLETE && pkt->pkt_state == 0) { 376 goto exit; 377 } else if (pkt->pkt_reason != CMD_CMPLT) { 378 goto exit; 379 } else if (((*pkt->pkt_scbp) & STATUS_MASK) == STATUS_BUSY) { 380 rval = 0; 381 } else { 382 rval = 0; 383 } 384 385 exit: 386 return (rval); 387 } 388 389 /* 390 * The implementation of scsi_probe now allows a particular 391 * HBA to intercept the call, for any post- or pre-processing 392 * it may need. The default, if the HBA does not override it, 393 * is to call scsi_hba_probe(), which retains the old functionality 394 * intact. 395 */ 396 int 397 scsi_probe(struct scsi_device *devp, int (*callback)()) 398 { 399 int ret; 400 scsi_hba_tran_t *hba_tran = devp->sd_address.a_hba_tran; 401 402 403 if (scsi_check_ss2_LUN_limit(devp) != 0) { 404 /* 405 * caller is trying to probe a strictly-SCSI-2 device 406 * with a LUN that is too large, so do not allow it 407 */ 408 return (SCSIPROBE_NORESP); /* skip probing this one */ 409 } 410 411 if (hba_tran->tran_tgt_probe != NULL) { 412 ret = (*hba_tran->tran_tgt_probe)(devp, callback); 413 } else { 414 ret = scsi_hba_probe(devp, callback); 415 } 416 417 if (ret == SCSIPROBE_EXISTS) { 418 create_inquiry_props(devp); 419 /* is this a strictly-SCSI-2 node ?? */ 420 scsi_establish_LUN_limit(devp); 421 } 422 423 return (ret); 424 } 425 426 /* 427 * scsi_hba_probe does not do any test unit ready's which access the medium 428 * and could cause busy or not ready conditions. 429 * scsi_hba_probe does 2 inquiries and a rqsense to clear unit attention 430 * and to allow sync negotiation to take place 431 * finally, scsi_hba_probe does one more inquiry which should 432 * reliably tell us what kind of target we have. 433 * A scsi-2 compliant target should be able to return inquiry with 250ms 434 * and we actually wait more than a second after reset. 435 */ 436 int 437 scsi_hba_probe(struct scsi_device *devp, int (*callback)()) 438 { 439 struct scsi_pkt *inq_pkt = NULL; 440 struct scsi_pkt *rq_pkt = NULL; 441 int rval = SCSIPROBE_NOMEM; 442 struct buf *inq_bp = NULL; 443 struct buf *rq_bp = NULL; 444 int (*cb_flag)(); 445 int pass = 1; 446 447 if (devp->sd_inq == NULL) { 448 devp->sd_inq = (struct scsi_inquiry *) 449 kmem_alloc(SUN_INQSIZE, ((callback == SLEEP_FUNC) ? 450 KM_SLEEP : KM_NOSLEEP)); 451 if (devp->sd_inq == NULL) { 452 goto out; 453 } 454 } 455 456 if (callback != SLEEP_FUNC && callback != NULL_FUNC) { 457 cb_flag = NULL_FUNC; 458 } else { 459 cb_flag = callback; 460 } 461 inq_bp = scsi_alloc_consistent_buf(ROUTE, 462 (struct buf *)NULL, SUN_INQSIZE, B_READ, cb_flag, NULL); 463 if (inq_bp == NULL) { 464 goto out; 465 } 466 467 inq_pkt = scsi_init_pkt(ROUTE, (struct scsi_pkt *)NULL, 468 inq_bp, CDB_GROUP0, sizeof (struct scsi_arq_status), 469 0, PKT_CONSISTENT, callback, NULL); 470 if (inq_pkt == NULL) { 471 if (inq_bp->b_error == 0) 472 rval = SCSIPROBE_NOMEM_CB; 473 goto out; 474 } 475 ASSERT(inq_bp->b_error == 0); 476 477 (void) scsi_setup_cdb((union scsi_cdb *)inq_pkt->pkt_cdbp, 478 SCMD_INQUIRY, 0, SUN_INQSIZE, 0); 479 inq_pkt->pkt_flags = FLAG_NOINTR|FLAG_NOPARITY; 480 481 /* 482 * the first inquiry will tell us whether a target 483 * responded 484 * 485 * The FILL_SCSI1_LUN below will find "ansi_ver != 1" on first pass 486 * because of bzero initilization. If this assumption turns out to be 487 * incorrect after we have real sd_inq data (for lun0) we will do a 488 * second pass during which FILL_SCSI1_LUN will place lun in CDB. 489 */ 490 bzero((caddr_t)devp->sd_inq, SUN_INQSIZE); 491 again: FILL_SCSI1_LUN(devp, inq_pkt); 492 493 if (scsi_test(inq_pkt) < 0) { 494 if (inq_pkt->pkt_reason == CMD_INCOMPLETE) { 495 rval = SCSIPROBE_NORESP; 496 goto out; 497 } else { 498 /* 499 * retry one more time 500 */ 501 if (scsi_test(inq_pkt) < 0) { 502 rval = SCSIPROBE_FAILURE; 503 goto out; 504 } 505 } 506 } 507 508 /* 509 * if we are lucky, this inquiry succeeded 510 */ 511 if ((inq_pkt->pkt_reason == CMD_CMPLT) && 512 (((*inq_pkt->pkt_scbp) & STATUS_MASK) == 0)) { 513 goto done; 514 } 515 516 /* 517 * the second inquiry, allows the host adapter to negotiate 518 * synchronous transfer period and offset 519 */ 520 if (scsi_test(inq_pkt) < 0) { 521 if (inq_pkt->pkt_reason == CMD_INCOMPLETE) 522 rval = SCSIPROBE_NORESP; 523 else 524 rval = SCSIPROBE_FAILURE; 525 goto out; 526 } 527 528 /* 529 * if target is still busy, give up now 530 */ 531 if (((struct scsi_status *)inq_pkt->pkt_scbp)->sts_busy) { 532 rval = SCSIPROBE_BUSY; 533 goto out; 534 } 535 536 /* 537 * do a rqsense if there was a check condition and ARQ was not done 538 */ 539 if ((inq_pkt->pkt_state & STATE_ARQ_DONE) == 0) { 540 if (((struct scsi_status *)inq_pkt->pkt_scbp)->sts_chk) { 541 542 /* 543 * prepare rqsense packet 544 * there is no real need for this because the 545 * check condition should have been cleared by now. 546 */ 547 rq_bp = scsi_alloc_consistent_buf(ROUTE, 548 (struct buf *)NULL, 549 (uint_t)SENSE_LENGTH, B_READ, cb_flag, NULL); 550 if (rq_bp == NULL) { 551 goto out; 552 } 553 554 rq_pkt = scsi_init_pkt(ROUTE, (struct scsi_pkt *)NULL, 555 rq_bp, CDB_GROUP0, 1, 0, PKT_CONSISTENT, callback, 556 NULL); 557 558 if (rq_pkt == NULL) { 559 if (rq_bp->b_error == 0) 560 rval = SCSIPROBE_NOMEM_CB; 561 goto out; 562 } 563 ASSERT(rq_bp->b_error == 0); 564 565 (void) scsi_setup_cdb((union scsi_cdb *)rq_pkt-> 566 pkt_cdbp, SCMD_REQUEST_SENSE, 0, SENSE_LENGTH, 0); 567 FILL_SCSI1_LUN(devp, rq_pkt); 568 rq_pkt->pkt_flags = FLAG_NOINTR|FLAG_NOPARITY; 569 570 /* 571 * The FILL_SCSI1_LUN above will find "inq_ansi != 1" 572 * on first pass, see "again" comment above. 573 * 574 * The controller type is as yet unknown, so we 575 * have to do a throwaway non-extended request sense, 576 * and hope that that clears the check condition for 577 * that unit until we can find out what kind of drive 578 * it is. A non-extended request sense is specified 579 * by stating that the sense block has 0 length, 580 * which is taken to mean that it is four bytes in 581 * length. 582 */ 583 if (scsi_test(rq_pkt) < 0) { 584 rval = SCSIPROBE_FAILURE; 585 goto out; 586 } 587 } 588 } 589 590 /* 591 * At this point, we are guaranteed that something responded 592 * to this scsi bus target id. We don't know yet what 593 * kind of device it is, or even whether there really is 594 * a logical unit attached (as some SCSI target controllers 595 * lie about a unit being ready, e.g., the Emulex MD21). 596 */ 597 598 if (scsi_test(inq_pkt) < 0) { 599 rval = SCSIPROBE_FAILURE; 600 goto out; 601 } 602 603 if (((struct scsi_status *)inq_pkt->pkt_scbp)->sts_busy) { 604 rval = SCSIPROBE_BUSY; 605 goto out; 606 } 607 608 /* 609 * Okay we sent the INQUIRY command. 610 * 611 * If enough data was transferred, we count that the 612 * Inquiry command succeeded, else we have to assume 613 * that this is a non-CCS scsi target (or a nonexistent 614 * target/lun). 615 */ 616 617 if (((struct scsi_status *)inq_pkt->pkt_scbp)->sts_chk) { 618 /* 619 * try a request sense if we have a pkt, otherwise 620 * just retry the inquiry one more time 621 */ 622 if (rq_pkt) { 623 (void) scsi_test(rq_pkt); 624 } 625 626 /* 627 * retry inquiry 628 */ 629 if (scsi_test(inq_pkt) < 0) { 630 rval = SCSIPROBE_FAILURE; 631 goto out; 632 } 633 if (((struct scsi_status *)inq_pkt->pkt_scbp)->sts_chk) { 634 rval = SCSIPROBE_FAILURE; 635 goto out; 636 } 637 } 638 639 done: 640 /* 641 * If we got a parity error on receive of inquiry data, 642 * we're just plain out of luck because we told the host 643 * adapter to not watch for parity errors. 644 */ 645 if ((inq_pkt->pkt_state & STATE_XFERRED_DATA) == 0 || 646 ((SUN_INQSIZE - inq_pkt->pkt_resid) < SUN_MIN_INQLEN)) { 647 rval = SCSIPROBE_NONCCS; 648 } else { 649 bcopy((caddr_t)inq_bp->b_un.b_addr, 650 (caddr_t)devp->sd_inq, SUN_INQSIZE); 651 rval = SCSIPROBE_EXISTS; 652 } 653 654 out: 655 /* 656 * If lun > 0 we need to figure out if this is a scsi-1 device where 657 * the "real" lun needs to be embeded into the cdb. 658 */ 659 if ((rval == SCSIPROBE_EXISTS) && (pass == 1) && 660 (devp->sd_address.a_lun > 0) && (devp->sd_inq->inq_ansi == 0x1)) { 661 pass++; 662 if (devp->sd_address.a_lun <= 7) 663 goto again; 664 665 /* 666 * invalid lun for scsi-1, 667 * return probe failure. 668 */ 669 rval = SCSIPROBE_FAILURE; 670 } 671 672 if (rq_pkt) { 673 scsi_destroy_pkt(rq_pkt); 674 } 675 if (inq_pkt) { 676 scsi_destroy_pkt(inq_pkt); 677 } 678 if (rq_bp) { 679 scsi_free_consistent_buf(rq_bp); 680 } 681 if (inq_bp) { 682 scsi_free_consistent_buf(inq_bp); 683 } 684 return (rval); 685 } 686 687 688 #define A_TO_TRAN(ap) (ap->a_hba_tran) 689 690 /* 691 * Function to get target and lun identifiers from HBA driver. 692 */ 693 int 694 scsi_get_bus_addr(struct scsi_device *devp, char *name, int len) 695 { 696 struct scsi_address *ap = &devp->sd_address; 697 698 if ((A_TO_TRAN(ap)->tran_get_bus_addr) == NULL) { 699 (void) sprintf(name, "%x,%x", ap->a_target, ap->a_lun); 700 return (1); 701 } 702 return (*A_TO_TRAN(ap)->tran_get_bus_addr)(devp, name, len); 703 } 704 705 /* 706 * Function to get name from HBA driver. 707 */ 708 int 709 scsi_get_name(struct scsi_device *devp, char *name, int len) 710 { 711 struct scsi_address *ap = &devp->sd_address; 712 713 if ((A_TO_TRAN(ap)->tran_get_name) == NULL) { 714 (void) sprintf(name, "%x,%x", ap->a_target, ap->a_lun); 715 return (1); 716 } 717 return (*A_TO_TRAN(ap)->tran_get_name)(devp, name, len); 718 } 719 720 void 721 create_inquiry_props(struct scsi_device *devp) 722 { 723 dev_info_t *devi = devp->sd_dev; 724 struct scsi_inquiry *inq = devp->sd_inq; 725 726 (void) ndi_prop_update_int(DDI_DEV_T_NONE, devi, 727 INQUIRY_DEVICE_TYPE, (int)inq->inq_dtype); 728 729 /* 730 * Create the following properties: 731 * 732 * inquiry-vendor-id Vendor id (INQUIRY data bytes 8-15) 733 * inquiry-product-id Product id (INQUIRY data bytes 16-31) 734 * inquiry-revision-id Product Rev level (INQUIRY data bytes 32-35) 735 * 736 * Note we don't support creation of these properties for scsi-1 737 * devices (as the vid, pid and revision were not defined) and we 738 * don't create the property if they are of zero length when 739 * stripped of Nulls and spaces. 740 */ 741 if (inq->inq_ansi != 1) { 742 create_inquiry_property(devi, INQUIRY_VENDOR_ID, 743 inq->inq_vid, (uint_t)sizeof (inq->inq_vid)); 744 745 create_inquiry_property(devi, INQUIRY_PRODUCT_ID, 746 inq->inq_pid, (uint_t)sizeof (inq->inq_pid)); 747 748 create_inquiry_property(devi, INQUIRY_REVISION_ID, 749 inq->inq_revision, (uint_t)sizeof (inq->inq_revision)); 750 } 751 } 752 753 /* 754 * Create individual inquiry properties 755 */ 756 static void 757 create_inquiry_property(dev_info_t *devi, char *name, char *data, 758 uint_t length) 759 { 760 int data_len; 761 762 if ((data_len = get_inquiry_prop_len(data, length)) > 0) { 763 char *data_string; 764 765 ASSERT(data_len <= length); 766 767 /* ensure null termination */ 768 data_string = kmem_zalloc(data_len + 1, KM_SLEEP); 769 bcopy(data, data_string, data_len); 770 771 (void) ndi_prop_update_string(DDI_DEV_T_NONE, devi, 772 name, data_string); 773 774 kmem_free(data_string, data_len + 1); 775 } 776 } 777 778 /* 779 * This routine returns the true length of the inquiry properties that are to 780 * be created by removing the padded spaces at the end of the inquiry data. 781 * This routine was designed for trimming spaces from the vid, pid and revision 782 * which are defined as being left aligned. In addition, we return 0 length 783 * if the property is full of all 0's or spaces, indicating to the caller that 784 * the device was not ready to return the proper inquiry data as per note 65 in 785 * the scsi-2 spec. 786 */ 787 static int 788 get_inquiry_prop_len(char *property, int length) 789 { 790 int retval; 791 int trailer; 792 char *p; 793 794 retval = length; 795 796 /* 797 * The vid, pid and revision are left-aligned ascii fields within the 798 * inquiry data. Here we trim the end of these fields by discounting 799 * length associated with trailing spaces or NULL bytes. The remaining 800 * bytes shall be only graphics codes - 0x20 through 0x7e as per the 801 * scsi spec definition. If we have all 0's or spaces, we return 0 802 * length. For devices that store inquiry data on the device, they 803 * can return 0's or spaces in these fields until the data is avail- 804 * able from the device (See NOTE 65 in the scsi-2 specification 805 * around the inquiry command.) We don't want to create a property in 806 * the case of a device not able to return valid data. 807 */ 808 trailer = 1; 809 for (p = property + length - 1; p >= property; p--) { 810 if (trailer) { 811 if ((*p == ' ') || (*p == '\0')) { 812 retval--; 813 continue; 814 } 815 trailer = 0; 816 } 817 818 /* each char must be within 0x20 - 0x7e */ 819 if (*p < 0x20 || *p > 0x7e) { 820 retval = -1; 821 break; 822 } 823 824 } 825 826 return (retval); 827 } 828 829 830 /* 831 * this routine is called from the start of scsi_probe() if a tgt/LUN to be 832 * probed *may* be a request to probe a strictly SCSI-2 target (with respect 833 * to LUNs) -- and this probe may be for a LUN number greater than 7, 834 * which can cause a hardware hang 835 * 836 * return 0 if the probe can proceed, 837 * else return 1, meaning do *NOT* probe this target/LUN 838 */ 839 static int 840 scsi_check_ss2_LUN_limit(struct scsi_device *devp) 841 { 842 struct scsi_address *ap = &(devp->sd_address); 843 dev_info_t *pdevi = 844 (dev_info_t *)DEVI(devp->sd_dev)->devi_parent; 845 int ret_val = 0; /* default return value */ 846 uchar_t *tgt_list; 847 uint_t tgt_nelements; 848 int i; 849 850 851 /* 852 * check for what *might* be a problem probe, only we don't 853 * know yet what's really at the destination target/LUN 854 */ 855 if ((ap->a_target >= NTARGETS_WIDE) || 856 (ap->a_lun < NLUNS_PER_TARGET)) { 857 return (0); /* okay to probe this target */ 858 } 859 860 /* 861 * this *might* be a problematic probe, so look to see 862 * if the inquiry data matches 863 */ 864 SCSI_PROBE_DEBUG2(1, "SCSA pre-probe: checking tgt.LUN=%d.%d\n", 865 ap->a_target, ap->a_lun); 866 SCSI_PROBE_DEBUG1(2, 867 "SCSA pre-probe: scanning parent node name: %s ...\n", 868 ddi_node_name(pdevi)); 869 870 /* 871 * look for a special property of our parent node that lists 872 * the targets under it for which we do *NOT* want to probe 873 * if LUN>7 -- if the property is found, look to see if our 874 * target ID is on that list 875 */ 876 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, 877 pdevi, DDI_PROP_DONTPASS, SS2_LUN0_TGT_LIST_PROP, 878 &tgt_list, &tgt_nelements) != DDI_PROP_SUCCESS) { 879 /* 880 * no list, so it must be okay to probe this target.LUN 881 */ 882 SCSI_PROBE_DEBUG0(3, 883 "SCSA pre-probe: NO parent prop found\n"); 884 } else { 885 for (i = 0; i < tgt_nelements; i++) { 886 if (tgt_list[i] == ap->a_target) { 887 /* 888 * we found a match, which means we do *NOT* 889 * want to probe the specified target.LUN 890 */ 891 ret_val = 1; 892 break; 893 } 894 } 895 ddi_prop_free(tgt_list); 896 #ifdef DEBUG 897 if (ret_val == 1) { 898 SCSI_PROBE_DEBUG2(1, 899 "SCSA pre-probe: marker node FOUND for " 900 "tgt.LUN=%d.%d, so SKIPPING it\n", 901 ap->a_target, ap->a_lun); 902 } else { 903 SCSI_PROBE_DEBUG0(2, 904 "SCSA pre-probe: NO marker node found" 905 " -- OK to probe\n"); 906 } 907 #endif 908 } 909 return (ret_val); 910 } 911 912 913 /* 914 * this routine is called from near the end of scsi_probe(), 915 * to see if the just-probed node is on our list of strictly-SCSI-2 nodes, 916 * and if it is we mark our parent node with this information 917 */ 918 static void 919 scsi_establish_LUN_limit(struct scsi_device *devp) 920 { 921 struct scsi_address *ap = &(devp->sd_address); 922 struct scsi_inquiry *inq = devp->sd_inq; 923 dev_info_t *devi = devp->sd_dev; 924 char *vid = NULL; 925 char *pid = NULL; 926 char *rev = NULL; 927 int i; 928 const ss2_lun0_info_t *p; 929 int bad_target_found = 0; 930 931 932 /* 933 * if this inquiry data shows that we have a strictly-SCSI-2 device 934 * at LUN 0, then add it to our list of strictly-SCSI-2 devices, 935 * so that we can avoid probes where LUN>7 on this device later 936 */ 937 if ((ap->a_lun != 0) || 938 (ap->a_target >= NTARGETS_WIDE) || 939 (inq->inq_dtype != DTYPE_PROCESSOR) || 940 (inq->inq_ansi != 2)) { 941 /* 942 * this can't possibly be a node we want to look at, since 943 * either LUN is greater than 0, target is greater than or 944 * eqaual to 16, device type 945 * is not processor, or SCSI level is not SCSI-2, 946 * so don't bother checking for a strictly SCSI-2 947 * (only 8 LUN) target 948 */ 949 return; /* don't care */ 950 } 951 952 SCSI_PROBE_DEBUG2(1, "SCSA post-probe: LUN limit on tgt.LUN=%d.%d, " 953 "SCSI-2 PROCESSOR?\n", ap->a_target, ap->a_lun); 954 955 ASSERT(devi != NULL); 956 957 /* 958 * we have a node that has been probed that is: LUN=0, target<16, 959 * PROCESSOR-type SCSI target, and at the SCSI-2 level, so 960 * check INQ properties to see if it's in our list of strictly 961 * SCSI-2 targets 962 * 963 * first we have to get the VID/PID/REV INQUIRY properties for 964 * comparison 965 */ 966 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, 967 INQUIRY_VENDOR_ID, &vid) != DDI_PROP_SUCCESS) { 968 SCSI_PROBE_DEBUG1(2, "SCSA post-probe: prop \"%s\" missing\n", 969 INQUIRY_VENDOR_ID); 970 goto dun; 971 } 972 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, 973 INQUIRY_PRODUCT_ID, &pid) != DDI_PROP_SUCCESS) { 974 SCSI_PROBE_DEBUG1(2, "SCSA post-probe: prop \"%s\" missing\n", 975 INQUIRY_PRODUCT_ID); 976 goto dun; 977 } 978 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, 979 INQUIRY_REVISION_ID, &rev) != DDI_PROP_SUCCESS) { 980 SCSI_PROBE_DEBUG1(2, "SCSA post-probe: prop \"%s\" missing\n", 981 INQUIRY_REVISION_ID); 982 goto dun; 983 } 984 985 SCSI_PROBE_DEBUG3(3, "SCSA post-probe: looking for vid/pid/rev = " 986 "\"%s\"/\"%s\"/\"%s\"\n", vid, pid, rev); 987 988 /* 989 * now that we have the INQUIRY properties from the device node, 990 * compare them with our known offenders 991 * 992 * Note: comparison is *CASE* *SENSITIVE* 993 */ 994 for (i = 0; i < scsi_probe_strict_s2_size; i++) { 995 p = &scsi_probe_strict_s2_list[i]; 996 997 if ((strcmp(p->sli_vid, vid) == 0) && 998 (strcmp(p->sli_pid, pid) == 0) && 999 (strcmp(p->sli_rev, rev) == 0)) { 1000 /* 1001 * we found a match -- do NOT want to probe this one 1002 */ 1003 SCSI_PROBE_DEBUG3(1, 1004 "SCSA post-probe: recording strict SCSI-2 node " 1005 "vid/pid/rev = \"%s\"/\"%s\"/\"%s\"\n", 1006 vid, pid, rev); 1007 1008 /* 1009 * set/update private parent-node property, 1010 * so we can find out about this node later 1011 */ 1012 bad_target_found = 1; 1013 break; 1014 } 1015 } 1016 1017 /* 1018 * either add remove target number from parent property 1019 */ 1020 scsi_update_parent_ss2_prop(devi, ap->a_target, bad_target_found); 1021 1022 dun: 1023 if (vid != NULL) { 1024 ddi_prop_free(vid); 1025 } 1026 if (pid != NULL) { 1027 ddi_prop_free(pid); 1028 } 1029 if (rev != NULL) { 1030 ddi_prop_free(rev); 1031 } 1032 } 1033 1034 1035 /* 1036 * update the parent node to add in the supplied tgt number to the target 1037 * list property already present (if any) 1038 * 1039 * since the target list can never be longer than 16, and each target 1040 * number is also small, we can save having to alloc memory by putting 1041 * a 16-byte array on the stack and using it for property memory 1042 * 1043 * if "add_tgt" is set then add the target to the parent's property, else 1044 * remove it (if present) 1045 */ 1046 static void 1047 scsi_update_parent_ss2_prop(dev_info_t *devi, int tgt, int add_tgt) 1048 { 1049 dev_info_t *pdevi = (dev_info_t *)DEVI(devi)->devi_parent; 1050 uchar_t *tgt_list; 1051 uint_t nelements; 1052 uint_t new_nelements; 1053 int i; 1054 int update_result; 1055 uchar_t new_tgt_list[NTARGETS_WIDE]; 1056 1057 1058 ASSERT(pdevi != NULL); 1059 1060 SCSI_PROBE_DEBUG3(3, 1061 "SCSA post-probe: updating parent=%s property to %s tgt=%d\n", 1062 ddi_node_name(pdevi), add_tgt ? "add" : "remove", tgt); 1063 1064 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, pdevi, DDI_PROP_DONTPASS, 1065 SS2_LUN0_TGT_LIST_PROP, &tgt_list, &nelements) == 1066 DDI_PROP_SUCCESS) { 1067 1068 if (add_tgt) { 1069 /* 1070 * we found an existing property -- we might need 1071 * to add to it 1072 */ 1073 for (i = 0; i < nelements; i++) { 1074 if (tgt_list[i] == tgt) { 1075 /* target already in list */ 1076 SCSI_PROBE_DEBUG1(2, "SCSA post-probe:" 1077 " tgt %d already listed\n", tgt); 1078 ddi_prop_free(tgt_list); 1079 return; 1080 } 1081 } 1082 1083 /* 1084 * need to append our target number to end of list 1085 * (no need sorting list, as it's so short) 1086 */ 1087 1088 /* 1089 * will this new entry fit ?? -- it should, since 1090 * the array is 16-wide and only keep track of 1091 * 16 targets, but check just in case 1092 */ 1093 new_nelements = nelements + 1; 1094 if (new_nelements >= NTARGETS_WIDE) { 1095 SCSI_PROBE_DEBUG0(1, "SCSA post-probe: " 1096 "internal error: no room " 1097 "for more targets?\n"); 1098 ddi_prop_free(tgt_list); 1099 return; 1100 } 1101 1102 /* copy existing list then add our tgt number to end */ 1103 bcopy((void *)tgt_list, (void *)new_tgt_list, 1104 sizeof (uchar_t) * nelements); 1105 new_tgt_list[new_nelements - 1] = (uchar_t)tgt; 1106 } else { 1107 /* 1108 * we need to remove our target number from the list, 1109 * so copy all of the other target numbers, 1110 * skipping ours 1111 */ 1112 int tgt_removed = 0; 1113 1114 new_nelements = 0; 1115 for (i = 0; i < nelements; i++) { 1116 if (tgt_list[i] != tgt) { 1117 new_tgt_list[new_nelements++] = 1118 tgt_list[i]; 1119 } else { 1120 /* skip this target */ 1121 tgt_removed++; 1122 } 1123 } 1124 1125 if (!tgt_removed) { 1126 SCSI_PROBE_DEBUG1(2, "SCSA post-probe:" 1127 " no need to remove tgt %d\n", tgt); 1128 ddi_prop_free(tgt_list); 1129 return; 1130 } 1131 } 1132 1133 update_result = ddi_prop_update_byte_array(DDI_DEV_T_NONE, 1134 pdevi, SS2_LUN0_TGT_LIST_PROP, new_tgt_list, 1135 new_nelements); 1136 1137 ddi_prop_free(tgt_list); 1138 } else { 1139 /* 1140 * no property yet 1141 */ 1142 if (add_tgt) { 1143 /* 1144 * create a property with just our tgt 1145 */ 1146 new_tgt_list[0] = (uchar_t)tgt; 1147 new_nelements = 1; /* just one element */ 1148 1149 update_result = ddi_prop_update_byte_array( 1150 DDI_DEV_T_NONE, pdevi, SS2_LUN0_TGT_LIST_PROP, 1151 new_tgt_list, new_nelements); 1152 } else { 1153 /* 1154 * no list so no need to remove tgt from that list 1155 */ 1156 return; 1157 } 1158 } 1159 1160 #ifdef DEBUG 1161 /* 1162 * if we get here we have tried to add/update properties 1163 */ 1164 if (update_result != DDI_PROP_SUCCESS) { 1165 SCSI_PROBE_DEBUG2(1, "SCSA post-probe: can't update parent " 1166 "property with tgt=%d (%d)\n", tgt, update_result); 1167 } else { 1168 if (add_tgt) { 1169 SCSI_PROBE_DEBUG3(2, 1170 "SCSA post-probe: added tgt=%d to parent " 1171 "prop=\"%s\" (now %d entries)\n", 1172 tgt, SS2_LUN0_TGT_LIST_PROP, new_nelements); 1173 } else { 1174 SCSI_PROBE_DEBUG3(2, 1175 "SCSA post-probe: removed tgt=%d from parent " 1176 "prop=\"%s\" (now %d entries)\n", 1177 tgt, SS2_LUN0_TGT_LIST_PROP, new_nelements); 1178 } 1179 } 1180 #endif 1181 } 1182