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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 #pragma ident "%Z%%M% %I% %E% SMI" 26 27 /* 28 * These functions are used to encode SCSI INQUIRY data into 29 * Solaris devid / guid values. 30 */ 31 32 #include <sys/types.h> 33 #include <sys/stropts.h> 34 #include <sys/debug.h> 35 #include <sys/isa_defs.h> 36 #include <sys/dditypes.h> 37 #include <sys/ddi_impldefs.h> 38 #include <sys/scsi/scsi.h> 39 #include "devid_impl.h" 40 41 #define SCSI_INQUIRY_VID_POS 9 42 #define SCSI_INQUIRY_VID_SUN "SUN" 43 #define SCSI_INQUIRY_VID_SUN_LEN 3 44 #define SCSI_INQUIRY_VID_HITACHI "HITACHI" 45 #define SCSI_INQUIRY_VID_HITACHI_LEN 7 46 #define SCSI_INQUIRY_PID_HITACHI_OPEN "OPEN-" 47 #define SCSI_INQUIRY_PID_HITACHI_OPEN_LEN 5 48 #define SCSI_INQUIRY_VID_EMC "EMC " 49 #define SCSI_INQUIRY_VID_EMC_LEN 8 50 #define SCSI_INQUIRY_PID_EMC_SYMMETRIX "SYMMETRIX " 51 #define SCSI_INQUIRY_PID_EMC_SYMMETRIX_LEN 16 52 53 #define MSG_NOT_STANDARDS_COMPLIANT "!Page83 data not standards compliant " 54 #define MSG_NOT_STANDARDS_COMPLIANT_SIZE ( \ 55 sizeof (MSG_NOT_STANDARDS_COMPLIANT) + \ 56 sizeof (((struct scsi_inquiry *)NULL)->inq_vid) + \ 57 sizeof (((struct scsi_inquiry *)NULL)->inq_pid) + \ 58 sizeof (((struct scsi_inquiry *)NULL)->inq_revision) + 4) 59 60 #define IS_DEVID_GUID_TYPE(type) ((type == DEVID_SCSI3_WWN) || \ 61 (IS_DEVID_SCSI3_VPD_TYPE(type))) 62 63 #define IS_DEVID_SCSI_TYPE(type) ((IS_DEVID_GUID_TYPE(type)) || \ 64 (type == DEVID_SCSI_SERIAL)) 65 66 /* 67 * The max inquiry page 83 size as expected in the code today 68 * is 0xf0 bytes. Defining a constant to make it easy incase 69 * this needs to be changed at a later time. 70 */ 71 72 #define SCMD_MAX_INQUIRY_PAGE83_SIZE 0xFF 73 #define SCMD_MIN_INQUIRY_PAGE83_SIZE 0x08 74 #define SCMD_INQUIRY_PAGE83_HDR_SIZE 4 75 #define SCSI_INQUIRY_PAGE83_EMC_SYMMETRIX_ID_LEN 16 76 77 #define SCMD_MAX_INQUIRY_PAGE80_SIZE 0xFF 78 #define SCMD_MIN_INQUIRY_PAGE80_SIZE 0x04 79 80 #define SCMD_MIN_STANDARD_INQUIRY_SIZE 0x04 81 82 #define SCMD_INQUIRY_PAGE83_IDENT_DESC_HDR_SIZE 4 83 84 #define SCMD_INQUIRY_VPD_TYPE_T10 0x01 85 #define SCMD_INQUIRY_VPD_TYPE_EUI 0x02 86 #define SCMD_INQUIRY_VPD_TYPE_NAA 0x03 87 #define SCMD_INQUIRY_VPD_TYPE_RTP 0x04 88 #define SCMD_INQUIRY_VPD_TYPE_TPG 0x05 89 #define SCMD_INQUIRY_VPD_TYPE_LUG 0x06 90 #define SCMD_INQUIRY_VPD_TYPE_MD5 0x07 91 #define SCMD_INQUIRY_VPD_TYPE_SSN 0x08 92 93 static int is_page83_data_valid(uchar_t *inq83, size_t inq83_len); 94 static int is_page80_data_valid(uchar_t *inq80, size_t inq80_len); 95 static int is_initialized_id(uchar_t *id, size_t id_len); 96 97 static void encode_scsi3_page83(int version, uchar_t *inq83, 98 size_t inq83_len, uchar_t **id, size_t *id_len, ushort_t *id_type); 99 static void encode_scsi3_page83_emc(int version, uchar_t *inq83, 100 size_t inq83_len, uchar_t **id, size_t *id_len, ushort_t *id_type); 101 static void encode_serialnum(int version, uchar_t *inq, uchar_t *inq80, 102 size_t inq80_len, uchar_t **id, size_t *id_len, ushort_t *id_type); 103 static void encode_sun_serialnum(int version, uchar_t *inq, 104 size_t inq_len, uchar_t **id, size_t *id_len, ushort_t *id_type); 105 106 static int devid_scsi_init(char *driver_name, 107 uchar_t *raw_id, size_t raw_id_len, ushort_t raw_id_type, 108 ddi_devid_t *ret_devid); 109 110 /* 111 * Function: ddi_/devid_scsi_encode 112 * 113 * Description: This routine finds and encodes a unique devid 114 * 115 * Arguments: version - id encode algorithm version 116 * driver_name - binding driver name (if ! known use NULL) 117 * inq - standard inquiry buffer 118 * inq_len - standard inquiry buffer length 119 * inq80 - serial number inquiry buffer 120 * inq80_len - serial number inquiry buffer length 121 * inq83 - vpd inquiry buffer 122 * inq83_len - vpd inquiry buffer length 123 * devid - id returned 124 * 125 * Return Code: DEVID_SUCCESS - success 126 * DEVID_FAILURE - failure 127 * DEVID_RETRY - LUN is in a transitional state. A delay should 128 * occur and then this inquiry data should be re-acquired and 129 * this function should be called again. 130 */ 131 int 132 #ifdef _KERNEL 133 ddi_devid_scsi_encode( 134 #else /* ! _KERNEL */ 135 devid_scsi_encode( 136 #endif /* _KERNEL */ 137 int version, /* IN */ 138 char *driver_name, /* IN */ 139 uchar_t *inq, /* IN */ 140 size_t inq_len, /* IN */ 141 uchar_t *inq80, /* IN */ 142 size_t inq80_len, /* IN */ 143 uchar_t *inq83, /* IN */ 144 size_t inq83_len, /* IN */ 145 ddi_devid_t *devid) /* OUT */ 146 { 147 int rval = DEVID_FAILURE; 148 uchar_t *id = NULL; 149 size_t id_len = 0; 150 ushort_t id_type = DEVID_NONE; 151 struct scsi_inquiry *inq_std = (struct scsi_inquiry *)inq; 152 #ifdef _KERNEL 153 char *msg = NULL; 154 #endif /* _KERNEL */ 155 156 DEVID_ASSERT(devid != NULL); 157 158 /* verify valid version */ 159 if (version > DEVID_SCSI_ENCODE_VERSION_LATEST) { 160 return (rval); 161 } 162 163 /* make sure minimum inquiry bytes are available */ 164 if (inq_len < SCMD_MIN_STANDARD_INQUIRY_SIZE) { 165 return (rval); 166 } 167 168 /* 169 * If 0x83 is availible, that is the best choice. Our next choice is 170 * 0x80. If neither are availible, we leave it to the caller to 171 * determine possible alternate ID, although discouraged. In the 172 * case of the target drivers they create a fabricated id which is 173 * stored in the acyl. The HBA drivers should avoid using an 174 * alternate id. Although has already created a hack of using the 175 * node wwn in some cases. Which needs to be carried forward for 176 * legacy reasons. 177 */ 178 if (inq83 != NULL) { 179 /* 180 * Perform page 83 validation tests and report offenders. 181 * We cannot enforce the page 83 specification because 182 * many Sun partners (ex. HDS) do not conform to the 183 * standards yet. 184 */ 185 if (is_page83_data_valid(inq83, inq83_len) == 186 DEVID_RET_INVALID) { 187 /* 188 * invalid page 83 data. bug 4939576 introduced 189 * handling for EMC non-standard data. 190 */ 191 if ((bcmp(inq_std->inq_vid, SCSI_INQUIRY_VID_EMC, 192 SCSI_INQUIRY_VID_EMC_LEN) == 0) && 193 (bcmp(inq_std->inq_pid, 194 SCSI_INQUIRY_PID_EMC_SYMMETRIX, 195 SCSI_INQUIRY_PID_EMC_SYMMETRIX_LEN) == 0)) { 196 encode_scsi3_page83_emc(version, inq83, 197 inq83_len, &id, &id_len, &id_type); 198 } 199 #ifdef _KERNEL 200 /* 201 * invalid page 83 data. Special hack for HDS 202 * specific device, to suppress the warning msg. 203 */ 204 if ((bcmp(inq_std->inq_vid, SCSI_INQUIRY_VID_HITACHI, 205 SCSI_INQUIRY_VID_HITACHI_LEN) != 0) || 206 (bcmp(inq_std->inq_pid, 207 SCSI_INQUIRY_PID_HITACHI_OPEN, 208 SCSI_INQUIRY_PID_HITACHI_OPEN_LEN) != 0)) { 209 /* 210 * report the page 0x83 standards violation. 211 */ 212 msg = kmem_alloc( 213 MSG_NOT_STANDARDS_COMPLIANT_SIZE, 214 KM_SLEEP); 215 (void) strcpy(msg, MSG_NOT_STANDARDS_COMPLIANT); 216 (void) strncat(msg, inq_std->inq_vid, 217 sizeof (inq_std->inq_vid)); 218 (void) strcat(msg, " "); 219 (void) strncat(msg, inq_std->inq_pid, 220 sizeof (inq_std->inq_pid)); 221 (void) strcat(msg, " "); 222 (void) strncat(msg, inq_std->inq_revision, 223 sizeof (inq_std->inq_revision)); 224 (void) strcat(msg, "\n"); 225 cmn_err(CE_WARN, msg); 226 kmem_free(msg, 227 MSG_NOT_STANDARDS_COMPLIANT_SIZE); 228 } 229 #endif /* _KERNEL */ 230 } 231 232 if (id_type == DEVID_NONE) { 233 encode_scsi3_page83(version, inq83, 234 inq83_len, &id, &id_len, &id_type); 235 } 236 } 237 238 /* 239 * If no vpd page is available at this point then we 240 * attempt to use a SCSI serial number from page 0x80. 241 */ 242 if ((id_type == DEVID_NONE) && 243 (inq != NULL) && 244 (inq80 != NULL)) { 245 if (is_page80_data_valid(inq80, inq80_len) == DEVID_RET_VALID) { 246 encode_serialnum(version, inq, inq80, 247 inq80_len, &id, &id_len, &id_type); 248 } 249 } 250 251 /* 252 * If no vpd page or serial is available at this point and 253 * it's a SUN disk it conforms to the disk qual. 850 specifications 254 * and we can fabricate a serial number id based on the standard 255 * inquiry page. 256 */ 257 if ((id_type == DEVID_NONE) && 258 (inq != NULL)) { 259 encode_sun_serialnum(version, inq, inq_len, 260 &id, &id_len, &id_type); 261 } 262 263 if (id_type != DEVID_NONE) { 264 if (is_initialized_id(id, id_len) == DEVID_RET_VALID) { 265 rval = devid_scsi_init(driver_name, 266 id, id_len, id_type, devid); 267 } else { 268 rval = DEVID_RETRY; 269 } 270 DEVID_FREE(id, id_len); 271 } 272 273 return (rval); 274 } 275 276 277 /* 278 * Function: is_page83_data_valid 279 * 280 * Description: This routine is used to validate the page 0x83 data 281 * passed in valid based on the standards specification. 282 * 283 * Arguments: inq83 - 284 * inq83_len - 285 * 286 * Return Code: DEVID_RET_VALID 287 * DEVID_RET_INVALID 288 * 289 */ 290 static int 291 is_page83_data_valid(uchar_t *inq83, size_t inq83_len) 292 { 293 294 int covered_desc_len = 0; 295 int dlen = 0; 296 uchar_t *dblk = NULL; 297 298 DEVID_ASSERT(inq83 != NULL); 299 300 /* if not large enough fail */ 301 if (inq83_len < SCMD_MIN_INQUIRY_PAGE83_SIZE) 302 return (DEVID_RET_INVALID); 303 304 /* 305 * Ensuring that the Peripheral device type(bits 0 - 4) has 306 * the valid settings - the value 0x1f indicates no device type. 307 * Only this value can be validated since all other fields are 308 * either used or reserved. 309 */ 310 if ((inq83[0] & DTYPE_MASK) == DTYPE_UNKNOWN) { 311 /* failed-peripheral devtype */ 312 return (DEVID_RET_INVALID); 313 } 314 315 /* 316 * Ensure that the page length field - third and 4th bytes 317 * contain a non zero length value. Our implementation 318 * does not seem to expect more that 255 bytes of data... 319 * what is to be done if the reported size is > 255 bytes? 320 * Yes the device will return only 255 bytes as we provide 321 * buffer to house only that much data but the standards 322 * prevent the targets from reporting the truncated size 323 * in this field. 324 * 325 * Currently reporting sizes more than 255 as failure. 326 * 327 */ 328 329 if ((inq83[2] == 0) && (inq83[3] == 0)) { 330 /* length field is 0! */ 331 return (DEVID_RET_INVALID); 332 } 333 if (inq83[3] > (SCMD_MAX_INQUIRY_PAGE83_SIZE - 3)) { 334 /* length field exceeds expected size of 255 bytes */ 335 return (DEVID_RET_INVALID); 336 } 337 338 /* 339 * Validation of individual descriptor blocks are done in the 340 * following while loop. It is possible to have multiple 341 * descriptor blocks. 342 * the 'dblk' pointer will be pointing to the start of 343 * each entry of the descriptor block. 344 */ 345 covered_desc_len = 0; 346 dblk = &inq83[4]; /* start of first decriptor blk */ 347 while (covered_desc_len < inq83[3]) { 348 349 /* 350 * Ensure that the length field is non zero 351 * Further length validations will be done 352 * along with the 'identifier type' as some of 353 * the lengths are dependent on it. 354 */ 355 dlen = dblk[3]; 356 if (dlen == 0) { 357 /* descr length is 0 */ 358 return (DEVID_RET_INVALID); 359 } 360 361 /* 362 * ensure that the size of the descriptor block does 363 * not claim to be larger than the entire page83 364 * data that has been received. 365 */ 366 if ((covered_desc_len + dlen) > inq83[3]) { 367 /* failed-descr length */ 368 return (DEVID_RET_INVALID); 369 } 370 371 /* 372 * The spec says that if the PIV field is 0 OR the 373 * association field contains value other than 1 and 2, 374 * then the protocol identifier field should be ignored. 375 * If association field contains a value of 1 or 2 376 * and the PIV field is set, then the protocol identifier 377 * field has to be validated. 378 * The protocol identifier values 0 - f are either assigned 379 * or reserved. Nothing to validate here, hence skipping 380 * over to the next check. 381 */ 382 383 /* 384 * Check for valid code set values. 385 * All possible values are reserved or assigned. Nothing 386 * to validate - skipping over. 387 */ 388 389 /* 390 * Identifier Type validation 391 * All SPC3rev22 identified types and the expected lengths 392 * are validated. 393 */ 394 switch (dblk[1] & 0x0f) { 395 case SCMD_INQUIRY_VPD_TYPE_T10: /* T10 vendor Id */ 396 /* No specific length validation required */ 397 break; 398 399 case SCMD_INQUIRY_VPD_TYPE_EUI: /* EUI 64 ID */ 400 /* EUI-64: size is expected to be 8, 12, or 16 bytes */ 401 if ((dlen != 8) && (dlen != 12) && (dlen != 16)) { 402 /* page83 validation failed-EIU64 */ 403 return (DEVID_RET_INVALID); 404 } 405 break; 406 407 case SCMD_INQUIRY_VPD_TYPE_NAA: /* NAA Id type */ 408 409 /* 410 * the size for this varies - 411 * IEEE extended/registered is 8 bytes 412 * IEEE Registered extended is 16 bytes 413 */ 414 switch (dblk[4] & 0xf0) { 415 416 case 0x20: /* IEEE Ext */ 417 case 0x50: /* IEEE Reg */ 418 if (dlen != 8) { 419 /* failed-IEE E/R len */ 420 return (DEVID_RET_INVALID); 421 } 422 /* 423 * the codeSet for this MUST 424 * be set to 1 425 */ 426 if ((dblk[0] & 0x0f) != 1) { 427 /* 428 * failed-IEEE E/R 429 * codeSet != 1. 430 */ 431 return (DEVID_RET_INVALID); 432 } 433 break; 434 435 case 0x60: /* IEEE EXT REG */ 436 if (dlen != 16) { 437 /* failed-IEEE ER len */ 438 return (DEVID_RET_INVALID); 439 } 440 /* 441 * the codeSet for this MUST 442 * be set to 1 443 */ 444 if ((dblk[0] & 0x0f) != 1) { 445 /* 446 * failed-IEEE ER 447 * codeSet != 1. 448 */ 449 return (DEVID_RET_INVALID); 450 } 451 break; 452 453 default: 454 /* reserved values */ 455 break; 456 } 457 break; 458 459 case SCMD_INQUIRY_VPD_TYPE_RTP: /* Relative Target port */ 460 if (dlen != 4) { 461 /* failed-Rel target Port length */ 462 return (DEVID_RET_INVALID); 463 } 464 break; 465 466 case SCMD_INQUIRY_VPD_TYPE_TPG: /* Target port group */ 467 if (dlen != 4) { 468 /* failed-target Port group length */ 469 return (DEVID_RET_INVALID); 470 } 471 break; 472 473 case SCMD_INQUIRY_VPD_TYPE_LUG: /* Logical unit group */ 474 if (dlen != 4) { 475 /* failed-Logical Unit group length */ 476 return (DEVID_RET_INVALID); 477 } 478 break; 479 480 case SCMD_INQUIRY_VPD_TYPE_MD5: /* MD5 unit group */ 481 if (dlen != 16) { 482 /* failed-MD5 Unit grp */ 483 return (DEVID_RET_INVALID); 484 } 485 break; 486 487 default: 488 break; 489 } 490 491 /* 492 * Now lets advance to the next descriptor block 493 * and validate it. 494 * the descriptor block size is <descr Header> + <descr Data> 495 * <descr Header> is equal to 4 bytes 496 * <descr Data> is available in dlen or dblk[3]. 497 */ 498 dblk = &dblk[4 + dlen]; 499 500 /* 501 * update the covered_desc_len so that we can ensure that 502 * the 'while' loop terminates. 503 */ 504 covered_desc_len += (dlen + 4); 505 } 506 return (DEVID_RET_VALID); 507 } 508 509 510 /* 511 * Function: is_initialized_id 512 * 513 * Description: Routine to ensure that the ID calculated is not a 514 * space or zero filled ID. Returning a space / zero 515 * filled ID when the luns on the target are not fully 516 * initialized is a valid response from the target as 517 * per the T10 spec. When a space/zero filled ID is 518 * found its information needs to be polled again 519 * after sometime time to see if the luns are fully 520 * initialized to return a valid guid information. 521 * 522 * Arguments: id - raw id 523 * id_len - raw id len 524 * 525 * Return Code: DEVID_VALID - indicates a non space/zero filled id 526 * DEVID_INVALID - indicates id contains uninitialized data 527 * and suggests retry of the collection commands. 528 */ 529 static int 530 is_initialized_id(uchar_t *id, size_t id_len) 531 { 532 int idx; 533 534 if ((id == NULL) || 535 (id_len == 0)) { 536 /* got id length as 0 fetch info again */ 537 return (DEVID_RET_INVALID); 538 } 539 540 /* First lets check if the guid is filled with spaces */ 541 for (idx = 0; idx < id_len; idx++) { 542 if (id[idx] != ' ') { 543 break; 544 } 545 } 546 547 /* 548 * Lets exit if we find that it contains ALL spaces 549 * saying that it has an uninitialized guid 550 */ 551 if (idx >= id_len) { 552 /* guid filled with spaces found */ 553 return (DEVID_RET_INVALID); 554 } 555 556 /* 557 * Since we have found that it is not filled with spaces 558 * now lets ensure that the guid is not filled with only 559 * zeros. 560 */ 561 for (idx = 0; idx < id_len; idx ++) { 562 if (id[idx] != 0) { 563 return (DEVID_RET_VALID); 564 } 565 } 566 567 /* guid filled with zeros found */ 568 return (DEVID_RET_INVALID); 569 } 570 571 572 /* 573 * Function: is_page80_data_valid 574 * 575 * Description: This routine is used to validate the page 0x80 data 576 * passed in valid based on the standards specification. 577 * 578 * Arguments: inq80 - 579 * inq80_len - 580 * 581 * Return Code: DEVID_RET_VALID 582 * DEVID_RET_INVALID 583 * 584 */ 585 /* ARGSUSED */ 586 static int 587 is_page80_data_valid(uchar_t *inq80, size_t inq80_len) 588 { 589 DEVID_ASSERT(inq80); 590 591 /* if not large enough fail */ 592 if (inq80_len < SCMD_MIN_INQUIRY_PAGE80_SIZE) { 593 return (DEVID_RET_INVALID); 594 } 595 596 /* 597 * (inq80_len - 4) is the size of the buffer space available 598 * for the product serial number. So inq80[3] (ie. product 599 * serial number) should be <= (inq80_len -4). 600 */ 601 if (inq80[3] > (inq80_len - 4)) { 602 return (DEVID_RET_INVALID); 603 } 604 605 return (DEVID_RET_VALID); 606 } 607 608 609 /* 610 * Function: encode_devid_page 611 * 612 * Description: This routine finds the unique devid if available and 613 * fills the devid and length parameters. 614 * 615 * Arguments: version - encode version 616 * inq83 - driver soft state (unit) structure 617 * inq83_len - length of raw inq83 data 618 * id - raw id 619 * id_len - len of raw id 620 * id_type - type of id 621 * 622 * Note: DEVID_NONE is returned in the id_type field 623 * if no supported page 83 id is found. 624 */ 625 static void 626 encode_scsi3_page83(int version, uchar_t *inq83, size_t inq83_len, 627 uchar_t **id, size_t *id_len, ushort_t *id_type) 628 { 629 size_t descriptor_bytes_left = 0; 630 size_t offset = 0; 631 int idx = 0; 632 size_t offset_id_type[4]; 633 634 DEVID_ASSERT(inq83 != NULL); 635 /* inq83 length was already validate in is_page83_valid */ 636 DEVID_ASSERT(id != NULL); 637 DEVID_ASSERT(id_len != NULL); 638 DEVID_ASSERT(id_type != NULL); 639 640 /* preset defaults */ 641 *id = NULL; 642 *id_len = 0; 643 *id_type = DEVID_NONE; 644 645 /* verify we have enough memory for a ident header */ 646 if (inq83_len < SCMD_INQUIRY_PAGE83_HDR_SIZE) { 647 return; 648 } 649 650 /* 651 * Attempt to validate the page data. Once validated, we'll walk 652 * the descriptors, looking for certain identifier types that will 653 * mark this device with a unique id/wwn. Note the comment below 654 * for what we really want to receive. 655 */ 656 657 /* 658 * The format of the inq83 data (Device Identification VPD page) is 659 * a header (containing the total length of the page, from which 660 * descriptor_bytes_left is calculated), followed by a list of 661 * identification descriptors. Each identifcation descriptor has a 662 * header which includes the length of the individual identification 663 * descriptor). 664 * 665 * Set the offset to the beginning byte of the first identification 666 * descriptor. We'll index everything from there. 667 */ 668 offset = SCMD_INQUIRY_PAGE83_HDR_SIZE; 669 descriptor_bytes_left = (size_t)((inq83[2] << 8) | inq83[3]); 670 671 /* 672 * If the raw data states that the data is larger 673 * than what is actually received abort encode. 674 * Otherwise we will run off into unknown memory 675 * on the decode. 676 */ 677 if ((descriptor_bytes_left + offset) > inq83_len) { 678 return; 679 } 680 681 682 /* Zero out our offset array */ 683 bzero(offset_id_type, sizeof (offset_id_type)); 684 685 /* 686 * According to the scsi spec 8.4.3 SPC-2, there could be several 687 * descriptors associated with each lun. Some we care about and some 688 * we don't. This loop is set up to iterate through the descriptors. 689 * We want the 0x03 case which represents an FC-PH, FC-PH3 or FC-FS 690 * Name_Identifier. The spec mentions nothing about ordering, so we 691 * don't assume any. 692 * 693 * We need to check if we've finished walking the list of descriptors, 694 * we also perform additional checks to be sure the newly calculated 695 * offset is within the bounds of the buffer, and the identifier length 696 * (as calculated by the length field in the header) is valid. This is 697 * done to protect against devices which return bad page83 data. 698 */ 699 while ((descriptor_bytes_left > 0) && (offset_id_type[3] == 0) && 700 (offset + SCMD_INQUIRY_PAGE83_IDENT_DESC_HDR_SIZE <= inq83_len) && 701 (offset + SCMD_INQUIRY_PAGE83_IDENT_DESC_HDR_SIZE + 702 (size_t)inq83[offset + 3] <= inq83_len)) { 703 /* 704 * Inspect the Identification descriptor list. Store the 705 * offsets in the devid page separately for 0x03, 0x01 and 706 * 0x02. Identifiers 0x00 and 0x04 are not useful as they 707 * don't represent unique identifiers for a lun. We also 708 * check the association by masking with 0x3f because we want 709 * an association of 0x0 - indicating the identifier field is 710 * associated with the addressed physical or logical device 711 * and not the port. 712 */ 713 switch ((inq83[offset + 1] & 0x3f)) { 714 case SCMD_INQUIRY_VPD_TYPE_T10: 715 offset_id_type[SCMD_INQUIRY_VPD_TYPE_T10] = offset; 716 break; 717 case SCMD_INQUIRY_VPD_TYPE_EUI: 718 offset_id_type[SCMD_INQUIRY_VPD_TYPE_EUI] = offset; 719 break; 720 case SCMD_INQUIRY_VPD_TYPE_NAA: 721 offset_id_type[SCMD_INQUIRY_VPD_TYPE_NAA] = offset; 722 break; 723 default: 724 /* Devid page undesired id type */ 725 break; 726 } 727 /* 728 * Calculate the descriptor bytes left and move to 729 * the beginning byte of the next id descriptor. 730 */ 731 descriptor_bytes_left -= (size_t)(inq83[offset + 3] + 732 SCMD_INQUIRY_PAGE83_IDENT_DESC_HDR_SIZE); 733 offset += (SCMD_INQUIRY_PAGE83_IDENT_DESC_HDR_SIZE + 734 (size_t)inq83[offset + 3]); 735 } 736 737 offset = 0; 738 739 /* 740 * We can't depend on an order from a device by identifier type, but 741 * once we have them, we'll walk them in the same order to prevent a 742 * firmware upgrade from breaking our algorithm. Start with the one 743 * we want the most: id_offset_type[3]. 744 */ 745 for (idx = 3; idx > 0; idx--) { 746 if (offset_id_type[idx] > 0) { 747 offset = offset_id_type[idx]; 748 break; 749 } 750 } 751 752 /* 753 * We have a valid Device ID page, set the length of the 754 * identifier and copy the value into the wwn. 755 */ 756 if (offset > 0) { 757 *id_len = (size_t)inq83[offset + 3]; 758 if ((*id = DEVID_MALLOC(*id_len)) == NULL) { 759 *id_len = 0; 760 return; 761 } 762 bcopy(&inq83[offset + SCMD_INQUIRY_PAGE83_IDENT_DESC_HDR_SIZE], 763 *id, *id_len); 764 765 /* set devid type */ 766 switch (version) { 767 /* In version 1 all page 83 types were grouped */ 768 case DEVID_SCSI_ENCODE_VERSION1: 769 *id_type = DEVID_SCSI3_WWN; 770 break; 771 /* In version 2 we break page 83 apart to be unique */ 772 case DEVID_SCSI_ENCODE_VERSION2: 773 switch (idx) { 774 case 3: 775 *id_type = DEVID_SCSI3_VPD_NAA; 776 break; 777 case 2: 778 *id_type = DEVID_SCSI3_VPD_EUI; 779 break; 780 case 1: 781 *id_type = DEVID_SCSI3_VPD_T10; 782 break; 783 default: 784 DEVID_FREE(*id, *id_len); 785 *id_len = 0; 786 break; 787 } 788 break; 789 default: 790 DEVID_FREE(*id, *id_len); 791 *id_len = 0; 792 break; 793 } 794 } 795 } 796 797 798 /* 799 * Function: encode_scsi3_page83_emc 800 * 801 * Description: Routine to handle proprietary page 83 of EMC Symmetrix 802 * device. Called by ssfcp_handle_page83() 803 * 804 * Arguments: version - encode version 805 * inq83 - scsi page 83 buffer 806 * inq83_len - scsi page 83 buffer size 807 * id - raw emc id 808 * id_len - len of raw emc id 809 * id_type - type of emc id 810 */ 811 static void 812 encode_scsi3_page83_emc(int version, uchar_t *inq83, 813 size_t inq83_len, uchar_t **id, size_t *id_len, ushort_t *id_type) 814 { 815 uchar_t *guidp = NULL; 816 817 DEVID_ASSERT(inq83 != NULL); 818 DEVID_ASSERT(id != NULL); 819 DEVID_ASSERT(id_len != NULL); 820 DEVID_ASSERT(id_type != NULL); 821 822 /* preset defaults */ 823 *id = NULL; 824 *id_len = 0; 825 *id_type = DEVID_NONE; 826 827 /* The initial devid algorithm didn't use EMC page 83 data */ 828 if (version == DEVID_SCSI_ENCODE_VERSION1) { 829 return; 830 } 831 832 /* EMC page 83 requires atleast 20 bytes */ 833 if (inq83_len < (SCMD_INQUIRY_PAGE83_HDR_SIZE + 834 SCSI_INQUIRY_PAGE83_EMC_SYMMETRIX_ID_LEN)) { 835 return; 836 } 837 838 /* 839 * The 4th byte in the page 83 info returned is most likely 840 * indicating the length of the id - which 0x10(16 bytes) 841 * and the 5th byte is indicating that the id is of 842 * IEEE Registered Extended Name format(6). Validate 843 * these code prints before proceeding further as the 844 * following proprietary approach is tied to the specific 845 * device type and incase the EMC firmware changes, we will 846 * have to validate for the changed device before we start 847 * supporting such a device. 848 */ 849 if ((inq83[3] != 0x10) || (inq83[4] != 0x60)) { 850 /* unsupported emc symtx device type */ 851 return; 852 } else { 853 guidp = &inq83[SCMD_INQUIRY_PAGE83_HDR_SIZE]; 854 /* 855 * The GUID returned by the EMC device is 856 * in the IEEE Registered Extended Name format(6) 857 * as a result it is of 16 bytes in length. 858 * An IEEE Registered Name format(5) will be of 859 * 8 bytes which is NOT what is being returned 860 * by the device type for which we are providing 861 * the support. 862 */ 863 *id_len = SCSI_INQUIRY_PAGE83_EMC_SYMMETRIX_ID_LEN; 864 if ((*id = DEVID_MALLOC(*id_len)) == NULL) { 865 *id_len = 0; 866 return; 867 } 868 bcopy(guidp, *id, *id_len); 869 870 /* emc id matches type 3 */ 871 *id_type = DEVID_SCSI3_VPD_NAA; 872 } 873 } 874 875 876 /* 877 * Function: encode_serialnum 878 * 879 * Description: This routine finds the unique devid from the inquiry page 880 * 0x80, serial number page. If available and fills the wwn 881 * and length parameters. 882 * 883 * Arguments: version - encode version 884 * inq - standard inquiry data 885 * inq80 - serial inquiry data 886 * inq80_len - serial inquiry data len 887 * id - raw id 888 * id_len - raw id len 889 * id_type - raw id type 890 */ 891 /* ARGSUSED */ 892 static void 893 encode_serialnum(int version, uchar_t *inq, uchar_t *inq80, 894 size_t inq80_len, uchar_t **id, size_t *id_len, ushort_t *id_type) 895 { 896 struct scsi_inquiry *inq_std = (struct scsi_inquiry *)inq; 897 int idx = 0; 898 899 DEVID_ASSERT(inq != NULL); 900 DEVID_ASSERT(inq80 != NULL); 901 DEVID_ASSERT(id != NULL); 902 DEVID_ASSERT(id_len != NULL); 903 DEVID_ASSERT(id_type != NULL); 904 905 /* preset defaults */ 906 *id = NULL; 907 *id_len = 0; 908 *id_type = DEVID_NONE; 909 910 /* verify inq80 buffer is large enough for a header */ 911 if (inq80_len < SCMD_MIN_INQUIRY_PAGE80_SIZE) { 912 return; 913 } 914 915 /* 916 * Attempt to validate the page data. Once validated, we'll check 917 * the serial number. 918 */ 919 *id_len = (size_t)inq80[3]; /* Store Product Serial Number length */ 920 921 /* verify buffer is large enough for serial number */ 922 if (inq80_len < (*id_len + SCMD_MIN_INQUIRY_PAGE80_SIZE)) { 923 return; 924 } 925 926 /* 927 * Device returns ASCII space (20h) in all the bytes of successful data 928 * transfer, if the product serial number is not available. So we end 929 * up having to check all the bytes for a space until we reach 930 * something else. 931 */ 932 for (idx = 0; idx < *id_len; idx++) { 933 if (inq80[4 + idx] == ' ') { 934 continue; 935 } 936 /* 937 * The serial number is valid, but since this is only vendor 938 * unique, we'll combine the inquiry vid and pid with the 939 * serial number. 940 */ 941 *id_len += sizeof (inq_std->inq_vid); 942 *id_len += sizeof (inq_std->inq_pid); 943 944 if ((*id = DEVID_MALLOC(*id_len)) == NULL) { 945 *id_len = 0; 946 return; 947 } 948 949 bcopy(&inq_std->inq_vid, *id, sizeof (inq_std->inq_vid)); 950 bcopy(&inq_std->inq_pid, &(*id)[sizeof (inq_std->inq_vid)], 951 sizeof (inq_std->inq_pid)); 952 bcopy(&inq80[4], &(*id)[sizeof (inq_std->inq_vid) + 953 sizeof (inq_std->inq_pid)], inq80[3]); 954 955 *id_type = DEVID_SCSI_SERIAL; 956 break; 957 } 958 959 /* 960 * The spec suggests that the command could succeed but return all 961 * spaces if the product serial number is not available. In this case 962 * we need to fail this routine. To accomplish this, we compare our 963 * length to the serial number length. If they are the same, then we 964 * never copied in the vid and updated the length. That being the case, 965 * we must not have found a valid serial number. 966 */ 967 if (*id_len == (size_t)inq80[3]) { 968 /* empty unit serial number */ 969 if (*id != NULL) { 970 DEVID_FREE(*id, *id_len); 971 } 972 *id = NULL; 973 *id_len = 0; 974 } 975 } 976 977 978 /* 979 * Function: encode_sun_serialnum 980 * 981 * Description: This routine finds the unique devid from the inquiry page 982 * 0x80, serial number page. If available and fills the wwn 983 * and length parameters. 984 * 985 * Arguments: version - encode version 986 * inq - standard inquiry data 987 * inq_len - standard inquiry data len 988 * id - raw id 989 * id_len - raw id len 990 * id_type - raw id type 991 * 992 * Return Code: DEVID_SUCCESS 993 * DEVID_FAILURE 994 */ 995 /* ARGSUSED */ 996 static void 997 encode_sun_serialnum(int version, uchar_t *inq, 998 size_t inq_len, uchar_t **id, size_t *id_len, ushort_t *id_type) 999 { 1000 struct scsi_inquiry *inq_std = (struct scsi_inquiry *)inq; 1001 1002 DEVID_ASSERT(inq != NULL); 1003 DEVID_ASSERT(id != NULL); 1004 DEVID_ASSERT(id_len != NULL); 1005 DEVID_ASSERT(id_type != NULL); 1006 1007 /* verify enough buffer is available */ 1008 if (inq_len < SCMD_MIN_STANDARD_INQUIRY_SIZE) { 1009 return; 1010 } 1011 1012 /* sun qual drive */ 1013 if ((inq_std != NULL) && 1014 (bcmp(&inq_std->inq_pid[SCSI_INQUIRY_VID_POS], 1015 SCSI_INQUIRY_VID_SUN, SCSI_INQUIRY_VID_SUN_LEN) == 0)) { 1016 /* 1017 * VPD pages 0x83 and 0x80 are unavailable. This 1018 * is a Sun qualified disks as indicated by 1019 * "SUN" in bytes 25-27 of the inquiry data 1020 * (bytes 9-11 of the pid). Devid's are created 1021 * for Sun qualified disks by combining the 1022 * vendor id with the product id with the serial 1023 * number located in bytes 36-47 of the inquiry data. 1024 */ 1025 1026 /* get data size */ 1027 *id_len = sizeof (inq_std->inq_vid) + 1028 sizeof (inq_std->inq_pid) + 1029 sizeof (inq_std->inq_serial); 1030 1031 if ((*id = DEVID_MALLOC(*id_len)) == NULL) { 1032 *id_len = 0; 1033 return; 1034 } 1035 1036 /* copy the vid at the beginning */ 1037 bcopy(&inq_std->inq_vid, *id, 1038 sizeof (inq_std->inq_vid)); 1039 /* copy the pid after the vid */ 1040 bcopy(&inq_std->inq_pid, 1041 &(*id)[sizeof (inq_std->inq_vid)], 1042 sizeof (inq_std->inq_pid)); 1043 /* copy the serial number after the vid and pid */ 1044 bcopy(&inq_std->inq_serial, 1045 &(*id)[sizeof (inq_std->inq_vid) + 1046 sizeof (inq_std->inq_pid)], 1047 sizeof (inq_std->inq_serial)); 1048 /* devid formed from inquiry data */ 1049 *id_type = DEVID_SCSI_SERIAL; 1050 } 1051 } 1052 1053 1054 /* 1055 * Function: devid_scsi_init 1056 * 1057 * Description: This routine is used to create a devid for a scsi 1058 * devid type. 1059 * 1060 * Arguments: hint - driver soft state (unit) structure 1061 * raw_id - pass by reference variable to hold wwn 1062 * raw_id_len - wwn length 1063 * raw_id_type - 1064 * ret_devid - 1065 * 1066 * Return Code: DEVID_SUCCESS 1067 * DEVID_FAILURE 1068 * 1069 */ 1070 static int 1071 devid_scsi_init( 1072 char *driver_name, 1073 uchar_t *raw_id, 1074 size_t raw_id_len, 1075 ushort_t raw_id_type, 1076 ddi_devid_t *ret_devid) 1077 { 1078 impl_devid_t *i_devid = NULL; 1079 int i_devid_len = 0; 1080 int driver_name_len = 0; 1081 ushort_t u_raw_id_len = 0; 1082 1083 DEVID_ASSERT(raw_id != NULL); 1084 DEVID_ASSERT(ret_devid != NULL); 1085 1086 if (!IS_DEVID_SCSI_TYPE(raw_id_type)) { 1087 *ret_devid = NULL; 1088 return (DEVID_FAILURE); 1089 } 1090 1091 i_devid_len = sizeof (*i_devid) + raw_id_len - sizeof (i_devid->did_id); 1092 if ((i_devid = DEVID_MALLOC(i_devid_len)) == NULL) { 1093 *ret_devid = NULL; 1094 return (DEVID_FAILURE); 1095 } 1096 1097 i_devid->did_magic_hi = DEVID_MAGIC_MSB; 1098 i_devid->did_magic_lo = DEVID_MAGIC_LSB; 1099 i_devid->did_rev_hi = DEVID_REV_MSB; 1100 i_devid->did_rev_lo = DEVID_REV_LSB; 1101 DEVID_FORMTYPE(i_devid, raw_id_type); 1102 u_raw_id_len = raw_id_len; 1103 DEVID_FORMLEN(i_devid, u_raw_id_len); 1104 1105 /* Fill in driver name hint */ 1106 if (driver_name != NULL) { 1107 driver_name_len = strlen(driver_name); 1108 if (driver_name_len > DEVID_HINT_SIZE) { 1109 /* Pick up last four characters of driver name */ 1110 driver_name += driver_name_len - DEVID_HINT_SIZE; 1111 driver_name_len = DEVID_HINT_SIZE; 1112 } 1113 bcopy(driver_name, i_devid->did_driver, driver_name_len); 1114 } else { 1115 bzero(i_devid->did_driver, DEVID_HINT_SIZE); 1116 } 1117 1118 bcopy(raw_id, i_devid->did_id, raw_id_len); 1119 1120 /* return device id */ 1121 *ret_devid = (ddi_devid_t)i_devid; 1122 return (DEVID_SUCCESS); 1123 } 1124 1125 1126 /* 1127 * Function: devid_to_guid 1128 * 1129 * Description: This routine extracts a guid string form a devid. 1130 * The common use of this guid is for a HBA driver 1131 * to pass into mdi_pi_alloc(). 1132 * 1133 * Arguments: devid - devid to extract guid from 1134 * 1135 * Return Code: guid string - success 1136 * NULL - failure 1137 */ 1138 char * 1139 #ifdef _KERNEL 1140 ddi_devid_to_guid(ddi_devid_t devid) 1141 #else /* !_KERNEL */ 1142 devid_to_guid(ddi_devid_t devid) 1143 #endif /* _KERNEL */ 1144 { 1145 impl_devid_t *id = (impl_devid_t *)devid; 1146 int len = 0; 1147 int idx = 0; 1148 int num = 0; 1149 char *guid = NULL; 1150 char *ptr = NULL; 1151 char *dp = NULL; 1152 1153 DEVID_ASSERT(devid != NULL); 1154 1155 /* NULL devid -> NULL guid */ 1156 if (devid == NULL) 1157 return (NULL); 1158 1159 if (!IS_DEVID_GUID_TYPE(DEVID_GETTYPE(id))) 1160 return (NULL); 1161 1162 /* guid is always converted to ascii, append NULL */ 1163 len = DEVID_GETLEN(id); 1164 1165 /* allocate guid string */ 1166 if ((guid = DEVID_MALLOC((len * 2) + 1)) == NULL) 1167 return (NULL); 1168 1169 /* perform encode of id to hex string */ 1170 ptr = guid; 1171 for (idx = 0, dp = &id->did_id[0]; idx < len; idx++, dp++) { 1172 num = ((*dp) >> 4) & 0xF; 1173 *ptr++ = (num < 10) ? (num + '0') : (num + ('a' - 10)); 1174 num = (*dp) & 0xF; 1175 *ptr++ = (num < 10) ? (num + '0') : (num + ('a' - 10)); 1176 } 1177 *ptr = 0; 1178 1179 return (guid); 1180 } 1181 1182 /* 1183 * Function: devid_free_guid 1184 * 1185 * Description: This routine frees a guid allocated by 1186 * devid_to_guid(). 1187 * 1188 * Arguments: guid - guid to free 1189 */ 1190 void 1191 #ifdef _KERNEL 1192 ddi_devid_free_guid(char *guid) 1193 #else /* !_KERNEL */ 1194 devid_free_guid(char *guid) 1195 #endif /* _KERNEL */ 1196 { 1197 if (guid != NULL) { 1198 DEVID_FREE(guid, strlen(guid) + 1); 1199 } 1200 } 1201