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