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 * Copyright 2019 Joyent, Inc. 29 */ 30 31 /* 32 * These functions are used to encode SCSI INQUIRY data into 33 * Solaris devid / guid values. 34 */ 35 36 #ifndef _KERNEL 37 #include <stdio.h> 38 #endif /* _KERNEL */ 39 40 #include <sys/inttypes.h> 41 #include <sys/types.h> 42 #include <sys/stropts.h> 43 #include <sys/debug.h> 44 #include <sys/isa_defs.h> 45 #include <sys/dditypes.h> 46 #include <sys/ddi_impldefs.h> 47 #include <sys/scsi/scsi.h> 48 #ifndef _KERNEL 49 #include <sys/libdevid.h> 50 #endif /* !_KERNEL */ 51 #include "devid_impl.h" 52 53 #define SCSI_INQUIRY_VID_POS 9 54 #define SCSI_INQUIRY_VID_SUN "SUN" 55 #define SCSI_INQUIRY_VID_SUN_LEN 3 56 #define SCSI_INQUIRY_VID_HITACHI "HITACHI" 57 #define SCSI_INQUIRY_VID_HITACHI_LEN 7 58 #define SCSI_INQUIRY_PID_HITACHI_OPEN "OPEN-" 59 #define SCSI_INQUIRY_PID_HITACHI_OPEN_LEN 5 60 #define SCSI_INQUIRY_VID_EMC "EMC " 61 #define SCSI_INQUIRY_VID_EMC_LEN 8 62 #define SCSI_INQUIRY_PID_EMC_SYMMETRIX "SYMMETRIX " 63 #define SCSI_INQUIRY_PID_EMC_SYMMETRIX_LEN 16 64 65 #define MSG_NOT_STANDARDS_COMPLIANT "!Page83 data not standards compliant " 66 #define MSG_NOT_STANDARDS_COMPLIANT_SIZE ( \ 67 sizeof (MSG_NOT_STANDARDS_COMPLIANT) + \ 68 sizeof (((struct scsi_inquiry *)NULL)->inq_vid) + \ 69 sizeof (((struct scsi_inquiry *)NULL)->inq_pid) + \ 70 sizeof (((struct scsi_inquiry *)NULL)->inq_revision) + 4) 71 72 #define IS_DEVID_GUID_TYPE(type) ((type == DEVID_SCSI3_WWN) || \ 73 (IS_DEVID_SCSI3_VPD_TYPE(type))) 74 75 #define IS_DEVID_SCSI_TYPE(type) ((IS_DEVID_GUID_TYPE(type)) || \ 76 (type == DEVID_SCSI_SERIAL)) 77 78 /* 79 * The max inquiry page 83 size as expected in the code today 80 * is 0xf0 bytes. Defining a constant to make it easy incase 81 * this needs to be changed at a later time. 82 */ 83 84 #define SCMD_MAX_INQUIRY_PAGE83_SIZE 0xFF 85 #define SCMD_MIN_INQUIRY_PAGE83_SIZE 0x08 86 #define SCMD_INQUIRY_PAGE83_HDR_SIZE 4 87 #define SCSI_INQUIRY_PAGE83_EMC_SYMMETRIX_ID_LEN 16 88 89 #define SCMD_MAX_INQUIRY_PAGE80_SIZE 0xFF 90 #define SCMD_MIN_INQUIRY_PAGE80_SIZE 0x04 91 92 #define SCMD_MIN_STANDARD_INQUIRY_SIZE 0x04 93 94 #define SCMD_INQUIRY_PAGE83_IDENT_DESC_HDR_SIZE 4 95 96 #define SCMD_INQUIRY_VPD_TYPE_T10 0x01 97 #define SCMD_INQUIRY_VPD_TYPE_EUI 0x02 98 #define SCMD_INQUIRY_VPD_TYPE_NAA 0x03 99 #define SCMD_INQUIRY_VPD_TYPE_RTP 0x04 100 #define SCMD_INQUIRY_VPD_TYPE_TPG 0x05 101 #define SCMD_INQUIRY_VPD_TYPE_LUG 0x06 102 #define SCMD_INQUIRY_VPD_TYPE_MD5 0x07 103 #define SCMD_INQUIRY_VPD_TYPE_SSN 0x08 104 105 static int is_page83_data_valid(uchar_t *inq83, size_t inq83_len); 106 static int is_page80_data_valid(uchar_t *inq80, size_t inq80_len); 107 static int is_initialized_id(uchar_t *id, size_t id_len); 108 109 static void encode_scsi3_page83(int version, uchar_t *inq83, 110 size_t inq83_len, uchar_t **id, size_t *id_len, ushort_t *id_type); 111 static void encode_scsi3_page83_emc(int version, uchar_t *inq83, 112 size_t inq83_len, uchar_t **id, size_t *id_len, ushort_t *id_type); 113 static void encode_serialnum(int version, uchar_t *inq, uchar_t *inq80, 114 size_t inq80_len, uchar_t **id, size_t *id_len, ushort_t *id_type); 115 static void encode_sun_serialnum(int version, uchar_t *inq, 116 size_t inq_len, uchar_t **id, size_t *id_len, ushort_t *id_type); 117 118 static int devid_scsi_init(char *driver_name, 119 uchar_t *raw_id, size_t raw_id_len, ushort_t raw_id_type, 120 ddi_devid_t *ret_devid); 121 122 static char ctoi(char c); 123 124 /* 125 * Function: ddi_/devid_scsi_encode 126 * 127 * Description: This routine finds and encodes a unique devid 128 * 129 * Arguments: version - id encode algorithm version 130 * driver_name - binding driver name (if ! known use NULL) 131 * inq - standard inquiry buffer 132 * inq_len - standard inquiry buffer length 133 * inq80 - serial number inquiry buffer 134 * inq80_len - serial number inquiry buffer length 135 * inq83 - vpd inquiry buffer 136 * inq83_len - vpd inquiry buffer length 137 * devid - id returned 138 * 139 * Return Code: DEVID_SUCCESS - success 140 * DEVID_FAILURE - failure 141 * DEVID_RETRY - LUN is in a transitional state. A delay should 142 * occur and then this inquiry data should be re-acquired and 143 * this function should be called again. 144 */ 145 int 146 #ifdef _KERNEL 147 ddi_devid_scsi_encode( 148 #else /* ! _KERNEL */ 149 devid_scsi_encode( 150 #endif /* _KERNEL */ 151 int version, /* IN */ 152 char *driver_name, /* IN */ 153 uchar_t *inq, /* IN */ 154 size_t inq_len, /* IN */ 155 uchar_t *inq80, /* IN */ 156 size_t inq80_len, /* IN */ 157 uchar_t *inq83, /* IN */ 158 size_t inq83_len, /* IN */ 159 ddi_devid_t *devid) /* OUT */ 160 { 161 int rval = DEVID_FAILURE; 162 uchar_t *id = NULL; 163 size_t id_len = 0; 164 ushort_t id_type = DEVID_NONE; 165 struct scsi_inquiry *inq_std = (struct scsi_inquiry *)inq; 166 #ifdef _KERNEL 167 char *msg = NULL; 168 #endif /* _KERNEL */ 169 170 DEVID_ASSERT(devid != NULL); 171 172 /* verify valid version */ 173 if (version > DEVID_SCSI_ENCODE_VERSION_LATEST) { 174 return (rval); 175 } 176 177 /* make sure minimum inquiry bytes are available */ 178 if (inq_len < SCMD_MIN_STANDARD_INQUIRY_SIZE) { 179 return (rval); 180 } 181 182 /* 183 * If 0x83 is availible, that is the best choice. Our next choice is 184 * 0x80. If neither are availible, we leave it to the caller to 185 * determine possible alternate ID, although discouraged. In the 186 * case of the target drivers they create a fabricated id which is 187 * stored in the acyl. The HBA drivers should avoid using an 188 * alternate id. Although has already created a hack of using the 189 * node wwn in some cases. Which needs to be carried forward for 190 * legacy reasons. 191 */ 192 if (inq83 != NULL) { 193 /* 194 * Perform page 83 validation tests and report offenders. 195 * We cannot enforce the page 83 specification because 196 * many Sun partners (ex. HDS) do not conform to the 197 * standards yet. 198 */ 199 if (is_page83_data_valid(inq83, inq83_len) == 200 DEVID_RET_INVALID) { 201 /* 202 * invalid page 83 data. bug 4939576 introduced 203 * handling for EMC non-standard data. 204 */ 205 if ((bcmp(inq_std->inq_vid, SCSI_INQUIRY_VID_EMC, 206 SCSI_INQUIRY_VID_EMC_LEN) == 0) && 207 (bcmp(inq_std->inq_pid, 208 SCSI_INQUIRY_PID_EMC_SYMMETRIX, 209 SCSI_INQUIRY_PID_EMC_SYMMETRIX_LEN) == 0)) { 210 encode_scsi3_page83_emc(version, inq83, 211 inq83_len, &id, &id_len, &id_type); 212 } 213 #ifdef _KERNEL 214 /* 215 * invalid page 83 data. Special hack for HDS 216 * specific device, to suppress the warning msg. 217 */ 218 if ((bcmp(inq_std->inq_vid, SCSI_INQUIRY_VID_HITACHI, 219 SCSI_INQUIRY_VID_HITACHI_LEN) != 0) || 220 (bcmp(inq_std->inq_pid, 221 SCSI_INQUIRY_PID_HITACHI_OPEN, 222 SCSI_INQUIRY_PID_HITACHI_OPEN_LEN) != 0)) { 223 /* 224 * report the page 0x83 standards violation. 225 */ 226 msg = kmem_alloc( 227 MSG_NOT_STANDARDS_COMPLIANT_SIZE, 228 KM_SLEEP); 229 (void) strcpy(msg, MSG_NOT_STANDARDS_COMPLIANT); 230 (void) strncat(msg, inq_std->inq_vid, 231 sizeof (inq_std->inq_vid)); 232 (void) strcat(msg, " "); 233 (void) strncat(msg, inq_std->inq_pid, 234 sizeof (inq_std->inq_pid)); 235 (void) strcat(msg, " "); 236 (void) strncat(msg, inq_std->inq_revision, 237 sizeof (inq_std->inq_revision)); 238 (void) strcat(msg, "\n"); 239 cmn_err(CE_WARN, "%s", msg); 240 kmem_free(msg, 241 MSG_NOT_STANDARDS_COMPLIANT_SIZE); 242 } 243 #endif /* _KERNEL */ 244 } 245 246 if (id_type == DEVID_NONE) { 247 encode_scsi3_page83(version, inq83, 248 inq83_len, &id, &id_len, &id_type); 249 } 250 } 251 252 /* 253 * If no vpd page is available at this point then we 254 * attempt to use a SCSI serial number from page 0x80. 255 */ 256 if ((id_type == DEVID_NONE) && 257 (inq != NULL) && 258 (inq80 != NULL)) { 259 if (is_page80_data_valid(inq80, inq80_len) == DEVID_RET_VALID) { 260 encode_serialnum(version, inq, inq80, 261 inq80_len, &id, &id_len, &id_type); 262 } 263 } 264 265 /* 266 * If no vpd page or serial is available at this point and 267 * it's a SUN disk it conforms to the disk qual. 850 specifications 268 * and we can fabricate a serial number id based on the standard 269 * inquiry page. 270 */ 271 if ((id_type == DEVID_NONE) && 272 (inq != NULL)) { 273 encode_sun_serialnum(version, inq, inq_len, 274 &id, &id_len, &id_type); 275 } 276 277 if (id_type != DEVID_NONE) { 278 if (is_initialized_id(id, id_len) == DEVID_RET_VALID) { 279 rval = devid_scsi_init(driver_name, 280 id, id_len, id_type, devid); 281 } else { 282 rval = DEVID_RETRY; 283 } 284 DEVID_FREE(id, id_len); 285 } 286 287 return (rval); 288 } 289 290 291 /* 292 * Function: is_page83_data_valid 293 * 294 * Description: This routine is used to validate the page 0x83 data 295 * passed in valid based on the standards specification. 296 * 297 * Arguments: inq83 - 298 * inq83_len - 299 * 300 * Return Code: DEVID_RET_VALID 301 * DEVID_RET_INVALID 302 * 303 */ 304 static int 305 is_page83_data_valid(uchar_t *inq83, size_t inq83_len) 306 { 307 308 int covered_desc_len = 0; 309 int dlen = 0; 310 uchar_t *dblk = NULL; 311 312 DEVID_ASSERT(inq83 != NULL); 313 314 /* if not large enough fail */ 315 if (inq83_len < SCMD_MIN_INQUIRY_PAGE83_SIZE) 316 return (DEVID_RET_INVALID); 317 318 /* 319 * Ensuring that the Peripheral device type(bits 0 - 4) has 320 * the valid settings - the value 0x1f indicates no device type. 321 * Only this value can be validated since all other fields are 322 * either used or reserved. 323 */ 324 if ((inq83[0] & DTYPE_MASK) == DTYPE_UNKNOWN) { 325 /* failed-peripheral devtype */ 326 return (DEVID_RET_INVALID); 327 } 328 329 /* 330 * Ensure that the page length field - third and 4th bytes 331 * contain a non zero length value. Our implementation 332 * does not seem to expect more that 255 bytes of data... 333 * what is to be done if the reported size is > 255 bytes? 334 * Yes the device will return only 255 bytes as we provide 335 * buffer to house only that much data but the standards 336 * prevent the targets from reporting the truncated size 337 * in this field. 338 * 339 * Currently reporting sizes more than 255 as failure. 340 * 341 */ 342 343 if ((inq83[2] == 0) && (inq83[3] == 0)) { 344 /* length field is 0! */ 345 return (DEVID_RET_INVALID); 346 } 347 if (inq83[3] > (SCMD_MAX_INQUIRY_PAGE83_SIZE - 3)) { 348 /* length field exceeds expected size of 255 bytes */ 349 return (DEVID_RET_INVALID); 350 } 351 352 /* 353 * Validation of individual descriptor blocks are done in the 354 * following while loop. It is possible to have multiple 355 * descriptor blocks. 356 * the 'dblk' pointer will be pointing to the start of 357 * each entry of the descriptor block. 358 */ 359 covered_desc_len = 0; 360 dblk = &inq83[4]; /* start of first decriptor blk */ 361 while (covered_desc_len < inq83[3]) { 362 363 /* 364 * Ensure that the length field is non zero 365 * Further length validations will be done 366 * along with the 'identifier type' as some of 367 * the lengths are dependent on it. 368 */ 369 dlen = dblk[3]; 370 if (dlen == 0) { 371 /* descr length is 0 */ 372 return (DEVID_RET_INVALID); 373 } 374 375 /* 376 * ensure that the size of the descriptor block does 377 * not claim to be larger than the entire page83 378 * data that has been received. 379 */ 380 if ((covered_desc_len + dlen) > inq83[3]) { 381 /* failed-descr length */ 382 return (DEVID_RET_INVALID); 383 } 384 385 /* 386 * The spec says that if the PIV field is 0 OR the 387 * association field contains value other than 1 and 2, 388 * then the protocol identifier field should be ignored. 389 * If association field contains a value of 1 or 2 390 * and the PIV field is set, then the protocol identifier 391 * field has to be validated. 392 * The protocol identifier values 0 - f are either assigned 393 * or reserved. Nothing to validate here, hence skipping 394 * over to the next check. 395 */ 396 397 /* 398 * Check for valid code set values. 399 * All possible values are reserved or assigned. Nothing 400 * to validate - skipping over. 401 */ 402 403 /* 404 * Identifier Type validation 405 * All SPC3rev22 identified types and the expected lengths 406 * are validated. 407 */ 408 switch (dblk[1] & 0x0f) { 409 case SCMD_INQUIRY_VPD_TYPE_T10: /* T10 vendor Id */ 410 /* No specific length validation required */ 411 break; 412 413 case SCMD_INQUIRY_VPD_TYPE_EUI: /* EUI 64 ID */ 414 /* EUI-64: size is expected to be 8, 12, or 16 bytes */ 415 if ((dlen != 8) && (dlen != 12) && (dlen != 16)) { 416 /* page83 validation failed-EIU64 */ 417 return (DEVID_RET_INVALID); 418 } 419 break; 420 421 case SCMD_INQUIRY_VPD_TYPE_NAA: /* NAA Id type */ 422 423 /* 424 * the size for this varies - 425 * IEEE extended/registered is 8 bytes 426 * IEEE Registered extended is 16 bytes 427 */ 428 switch (dblk[4] & 0xf0) { 429 430 case 0x20: /* IEEE Ext */ 431 case 0x50: /* IEEE Reg */ 432 if (dlen != 8) { 433 /* failed-IEE E/R len */ 434 return (DEVID_RET_INVALID); 435 } 436 /* 437 * the codeSet for this MUST 438 * be set to 1 439 */ 440 if ((dblk[0] & 0x0f) != 1) { 441 /* 442 * failed-IEEE E/R 443 * codeSet != 1. 444 */ 445 return (DEVID_RET_INVALID); 446 } 447 break; 448 449 case 0x60: /* IEEE EXT REG */ 450 if (dlen != 16) { 451 /* failed-IEEE ER len */ 452 return (DEVID_RET_INVALID); 453 } 454 /* 455 * the codeSet for this MUST 456 * be set to 1 457 */ 458 if ((dblk[0] & 0x0f) != 1) { 459 /* 460 * failed-IEEE ER 461 * codeSet != 1. 462 */ 463 return (DEVID_RET_INVALID); 464 } 465 break; 466 467 default: 468 /* reserved values */ 469 break; 470 } 471 break; 472 473 case SCMD_INQUIRY_VPD_TYPE_RTP: /* Relative Target port */ 474 if (dlen != 4) { 475 /* failed-Rel target Port length */ 476 return (DEVID_RET_INVALID); 477 } 478 break; 479 480 case SCMD_INQUIRY_VPD_TYPE_TPG: /* Target port group */ 481 if (dlen != 4) { 482 /* failed-target Port group length */ 483 return (DEVID_RET_INVALID); 484 } 485 break; 486 487 case SCMD_INQUIRY_VPD_TYPE_LUG: /* Logical unit group */ 488 if (dlen != 4) { 489 /* failed-Logical Unit group length */ 490 return (DEVID_RET_INVALID); 491 } 492 break; 493 494 case SCMD_INQUIRY_VPD_TYPE_MD5: /* MD5 unit group */ 495 if (dlen != 16) { 496 /* failed-MD5 Unit grp */ 497 return (DEVID_RET_INVALID); 498 } 499 break; 500 501 default: 502 break; 503 } 504 505 /* 506 * Now lets advance to the next descriptor block 507 * and validate it. 508 * the descriptor block size is <descr Header> + <descr Data> 509 * <descr Header> is equal to 4 bytes 510 * <descr Data> is available in dlen or dblk[3]. 511 */ 512 dblk = &dblk[4 + dlen]; 513 514 /* 515 * update the covered_desc_len so that we can ensure that 516 * the 'while' loop terminates. 517 */ 518 covered_desc_len += (dlen + 4); 519 } 520 return (DEVID_RET_VALID); 521 } 522 523 524 /* 525 * Function: is_initialized_id 526 * 527 * Description: Routine to ensure that the ID calculated is not a 528 * space or zero filled ID. Returning a space / zero 529 * filled ID when the luns on the target are not fully 530 * initialized is a valid response from the target as 531 * per the T10 spec. When a space/zero filled ID is 532 * found its information needs to be polled again 533 * after sometime time to see if the luns are fully 534 * initialized to return a valid guid information. 535 * 536 * Arguments: id - raw id 537 * id_len - raw id len 538 * 539 * Return Code: DEVID_VALID - indicates a non space/zero filled id 540 * DEVID_INVALID - indicates id contains uninitialized data 541 * and suggests retry of the collection commands. 542 */ 543 static int 544 is_initialized_id(uchar_t *id, size_t id_len) 545 { 546 int idx; 547 548 if ((id == NULL) || 549 (id_len == 0)) { 550 /* got id length as 0 fetch info again */ 551 return (DEVID_RET_INVALID); 552 } 553 554 /* First lets check if the guid is filled with spaces */ 555 for (idx = 0; idx < id_len; idx++) { 556 if (id[idx] != ' ') { 557 break; 558 } 559 } 560 561 /* 562 * Lets exit if we find that it contains ALL spaces 563 * saying that it has an uninitialized guid 564 */ 565 if (idx >= id_len) { 566 /* guid filled with spaces found */ 567 return (DEVID_RET_INVALID); 568 } 569 570 /* 571 * Since we have found that it is not filled with spaces 572 * now lets ensure that the guid is not filled with only 573 * zeros. 574 */ 575 for (idx = 0; idx < id_len; idx ++) { 576 if (id[idx] != 0) { 577 return (DEVID_RET_VALID); 578 } 579 } 580 581 /* guid filled with zeros found */ 582 return (DEVID_RET_INVALID); 583 } 584 585 586 /* 587 * Function: is_page80_data_valid 588 * 589 * Description: This routine is used to validate the page 0x80 data 590 * passed in valid based on the standards specification. 591 * 592 * Arguments: inq80 - 593 * inq80_len - 594 * 595 * Return Code: DEVID_RET_VALID 596 * DEVID_RET_INVALID 597 * 598 */ 599 /* ARGSUSED */ 600 static int 601 is_page80_data_valid(uchar_t *inq80, size_t inq80_len) 602 { 603 DEVID_ASSERT(inq80); 604 605 /* if not large enough fail */ 606 if (inq80_len < SCMD_MIN_INQUIRY_PAGE80_SIZE) { 607 return (DEVID_RET_INVALID); 608 } 609 610 /* 611 * (inq80_len - 4) is the size of the buffer space available 612 * for the product serial number. So inq80[3] (ie. product 613 * serial number) should be <= (inq80_len -4). 614 */ 615 if (inq80[3] > (inq80_len - 4)) { 616 return (DEVID_RET_INVALID); 617 } 618 619 return (DEVID_RET_VALID); 620 } 621 622 623 /* 624 * Function: encode_devid_page 625 * 626 * Description: This routine finds the unique devid if available and 627 * fills the devid and length parameters. 628 * 629 * Arguments: version - encode version 630 * inq83 - driver soft state (unit) structure 631 * inq83_len - length of raw inq83 data 632 * id - raw id 633 * id_len - len of raw id 634 * id_type - type of id 635 * 636 * Note: DEVID_NONE is returned in the id_type field 637 * if no supported page 83 id is found. 638 */ 639 static void 640 encode_scsi3_page83(int version, uchar_t *inq83, size_t inq83_len, 641 uchar_t **id, size_t *id_len, ushort_t *id_type) 642 { 643 size_t descriptor_bytes_left = 0; 644 size_t offset = 0; 645 int idx = 0; 646 size_t offset_id_type[4]; 647 648 DEVID_ASSERT(inq83 != NULL); 649 /* inq83 length was already validate in is_page83_valid */ 650 DEVID_ASSERT(id != NULL); 651 DEVID_ASSERT(id_len != NULL); 652 DEVID_ASSERT(id_type != NULL); 653 654 /* preset defaults */ 655 *id = NULL; 656 *id_len = 0; 657 *id_type = DEVID_NONE; 658 659 /* verify we have enough memory for a ident header */ 660 if (inq83_len < SCMD_INQUIRY_PAGE83_HDR_SIZE) { 661 return; 662 } 663 664 /* 665 * Attempt to validate the page data. Once validated, we'll walk 666 * the descriptors, looking for certain identifier types that will 667 * mark this device with a unique id/wwn. Note the comment below 668 * for what we really want to receive. 669 */ 670 671 /* 672 * The format of the inq83 data (Device Identification VPD page) is 673 * a header (containing the total length of the page, from which 674 * descriptor_bytes_left is calculated), followed by a list of 675 * identification descriptors. Each identifcation descriptor has a 676 * header which includes the length of the individual identification 677 * descriptor). 678 * 679 * Set the offset to the beginning byte of the first identification 680 * descriptor. We'll index everything from there. 681 */ 682 offset = SCMD_INQUIRY_PAGE83_HDR_SIZE; 683 descriptor_bytes_left = (size_t)((inq83[2] << 8) | inq83[3]); 684 685 /* 686 * If the raw data states that the data is larger 687 * than what is actually received abort encode. 688 * Otherwise we will run off into unknown memory 689 * on the decode. 690 */ 691 if ((descriptor_bytes_left + offset) > inq83_len) { 692 return; 693 } 694 695 696 /* Zero out our offset array */ 697 bzero(offset_id_type, sizeof (offset_id_type)); 698 699 /* 700 * According to the scsi spec 8.4.3 SPC-2, there could be several 701 * descriptors associated with each lun. Some we care about and some 702 * we don't. This loop is set up to iterate through the descriptors. 703 * We want the 0x03 case which represents an FC-PH, FC-PH3 or FC-FS 704 * Name_Identifier. The spec mentions nothing about ordering, so we 705 * don't assume any. 706 * 707 * We need to check if we've finished walking the list of descriptors, 708 * we also perform additional checks to be sure the newly calculated 709 * offset is within the bounds of the buffer, and the identifier length 710 * (as calculated by the length field in the header) is valid. This is 711 * done to protect against devices which return bad page83 data. 712 */ 713 while ((descriptor_bytes_left > 0) && (offset_id_type[3] == 0) && 714 (offset + SCMD_INQUIRY_PAGE83_IDENT_DESC_HDR_SIZE <= inq83_len) && 715 (offset + SCMD_INQUIRY_PAGE83_IDENT_DESC_HDR_SIZE + 716 (size_t)inq83[offset + 3] <= inq83_len)) { 717 /* 718 * Inspect the Identification descriptor list. Store the 719 * offsets in the devid page separately for 0x03, 0x01 and 720 * 0x02. Identifiers 0x00 and 0x04 are not useful as they 721 * don't represent unique identifiers for a lun. We also 722 * check the association by masking with 0x3f because we want 723 * an association of 0x0 - indicating the identifier field is 724 * associated with the addressed physical or logical device 725 * and not the port. 726 */ 727 switch ((inq83[offset + 1] & 0x3f)) { 728 case SCMD_INQUIRY_VPD_TYPE_T10: 729 offset_id_type[SCMD_INQUIRY_VPD_TYPE_T10] = offset; 730 break; 731 case SCMD_INQUIRY_VPD_TYPE_EUI: 732 offset_id_type[SCMD_INQUIRY_VPD_TYPE_EUI] = offset; 733 break; 734 case SCMD_INQUIRY_VPD_TYPE_NAA: 735 offset_id_type[SCMD_INQUIRY_VPD_TYPE_NAA] = offset; 736 break; 737 default: 738 /* Devid page undesired id type */ 739 break; 740 } 741 /* 742 * Calculate the descriptor bytes left and move to 743 * the beginning byte of the next id descriptor. 744 */ 745 descriptor_bytes_left -= (size_t)(inq83[offset + 3] + 746 SCMD_INQUIRY_PAGE83_IDENT_DESC_HDR_SIZE); 747 offset += (SCMD_INQUIRY_PAGE83_IDENT_DESC_HDR_SIZE + 748 (size_t)inq83[offset + 3]); 749 } 750 751 offset = 0; 752 753 /* 754 * We can't depend on an order from a device by identifier type, but 755 * once we have them, we'll walk them in the same order to prevent a 756 * firmware upgrade from breaking our algorithm. Start with the one 757 * we want the most: id_offset_type[3]. 758 */ 759 for (idx = 3; idx > 0; idx--) { 760 if (offset_id_type[idx] > 0) { 761 offset = offset_id_type[idx]; 762 break; 763 } 764 } 765 766 /* 767 * We have a valid Device ID page, set the length of the 768 * identifier and copy the value into the wwn. 769 */ 770 if (offset > 0) { 771 *id_len = (size_t)inq83[offset + 3]; 772 if ((*id = DEVID_MALLOC(*id_len)) == NULL) { 773 *id_len = 0; 774 return; 775 } 776 bcopy(&inq83[offset + SCMD_INQUIRY_PAGE83_IDENT_DESC_HDR_SIZE], 777 *id, *id_len); 778 779 /* set devid type */ 780 switch (version) { 781 /* In version 1 all page 83 types were grouped */ 782 case DEVID_SCSI_ENCODE_VERSION1: 783 *id_type = DEVID_SCSI3_WWN; 784 break; 785 /* In version 2 we break page 83 apart to be unique */ 786 case DEVID_SCSI_ENCODE_VERSION2: 787 switch (idx) { 788 case 3: 789 *id_type = DEVID_SCSI3_VPD_NAA; 790 break; 791 case 2: 792 *id_type = DEVID_SCSI3_VPD_EUI; 793 break; 794 case 1: 795 *id_type = DEVID_SCSI3_VPD_T10; 796 break; 797 default: 798 DEVID_FREE(*id, *id_len); 799 *id_len = 0; 800 break; 801 } 802 break; 803 default: 804 DEVID_FREE(*id, *id_len); 805 *id_len = 0; 806 break; 807 } 808 } 809 } 810 811 812 /* 813 * Function: encode_scsi3_page83_emc 814 * 815 * Description: Routine to handle proprietary page 83 of EMC Symmetrix 816 * device. Called by ssfcp_handle_page83() 817 * 818 * Arguments: version - encode version 819 * inq83 - scsi page 83 buffer 820 * inq83_len - scsi page 83 buffer size 821 * id - raw emc id 822 * id_len - len of raw emc id 823 * id_type - type of emc id 824 */ 825 static void 826 encode_scsi3_page83_emc(int version, uchar_t *inq83, 827 size_t inq83_len, uchar_t **id, size_t *id_len, ushort_t *id_type) 828 { 829 uchar_t *guidp = NULL; 830 831 DEVID_ASSERT(inq83 != NULL); 832 DEVID_ASSERT(id != NULL); 833 DEVID_ASSERT(id_len != NULL); 834 DEVID_ASSERT(id_type != NULL); 835 836 /* preset defaults */ 837 *id = NULL; 838 *id_len = 0; 839 *id_type = DEVID_NONE; 840 841 /* The initial devid algorithm didn't use EMC page 83 data */ 842 if (version == DEVID_SCSI_ENCODE_VERSION1) { 843 return; 844 } 845 846 /* EMC page 83 requires atleast 20 bytes */ 847 if (inq83_len < (SCMD_INQUIRY_PAGE83_HDR_SIZE + 848 SCSI_INQUIRY_PAGE83_EMC_SYMMETRIX_ID_LEN)) { 849 return; 850 } 851 852 /* 853 * The 4th byte in the page 83 info returned is most likely 854 * indicating the length of the id - which 0x10(16 bytes) 855 * and the 5th byte is indicating that the id is of 856 * IEEE Registered Extended Name format(6). Validate 857 * these code prints before proceeding further as the 858 * following proprietary approach is tied to the specific 859 * device type and incase the EMC firmware changes, we will 860 * have to validate for the changed device before we start 861 * supporting such a device. 862 */ 863 if ((inq83[3] != 0x10) || (inq83[4] != 0x60)) { 864 /* unsupported emc symtx device type */ 865 return; 866 } else { 867 guidp = &inq83[SCMD_INQUIRY_PAGE83_HDR_SIZE]; 868 /* 869 * The GUID returned by the EMC device is 870 * in the IEEE Registered Extended Name format(6) 871 * as a result it is of 16 bytes in length. 872 * An IEEE Registered Name format(5) will be of 873 * 8 bytes which is NOT what is being returned 874 * by the device type for which we are providing 875 * the support. 876 */ 877 *id_len = SCSI_INQUIRY_PAGE83_EMC_SYMMETRIX_ID_LEN; 878 if ((*id = DEVID_MALLOC(*id_len)) == NULL) { 879 *id_len = 0; 880 return; 881 } 882 bcopy(guidp, *id, *id_len); 883 884 /* emc id matches type 3 */ 885 *id_type = DEVID_SCSI3_VPD_NAA; 886 } 887 } 888 889 890 /* 891 * Function: encode_serialnum 892 * 893 * Description: This routine finds the unique devid from the inquiry page 894 * 0x80, serial number page. If available and fills the wwn 895 * and length parameters. 896 * 897 * Arguments: version - encode version 898 * inq - standard inquiry data 899 * inq80 - serial inquiry data 900 * inq80_len - serial inquiry data len 901 * id - raw id 902 * id_len - raw id len 903 * id_type - raw id type 904 */ 905 /* ARGSUSED */ 906 static void 907 encode_serialnum(int version, uchar_t *inq, uchar_t *inq80, 908 size_t inq80_len, uchar_t **id, size_t *id_len, ushort_t *id_type) 909 { 910 struct scsi_inquiry *inq_std = (struct scsi_inquiry *)inq; 911 int idx = 0; 912 913 DEVID_ASSERT(inq != NULL); 914 DEVID_ASSERT(inq80 != NULL); 915 DEVID_ASSERT(id != NULL); 916 DEVID_ASSERT(id_len != NULL); 917 DEVID_ASSERT(id_type != NULL); 918 919 /* preset defaults */ 920 *id = NULL; 921 *id_len = 0; 922 *id_type = DEVID_NONE; 923 924 /* verify inq80 buffer is large enough for a header */ 925 if (inq80_len < SCMD_MIN_INQUIRY_PAGE80_SIZE) { 926 return; 927 } 928 929 /* 930 * Attempt to validate the page data. Once validated, we'll check 931 * the serial number. 932 */ 933 *id_len = (size_t)inq80[3]; /* Store Product Serial Number length */ 934 935 /* verify buffer is large enough for serial number */ 936 if (inq80_len < (*id_len + SCMD_MIN_INQUIRY_PAGE80_SIZE)) { 937 return; 938 } 939 940 /* 941 * Device returns ASCII space (20h) in all the bytes of successful data 942 * transfer, if the product serial number is not available. So we end 943 * up having to check all the bytes for a space until we reach 944 * something else. 945 */ 946 for (idx = 0; idx < *id_len; idx++) { 947 if (inq80[4 + idx] == ' ') { 948 continue; 949 } 950 /* 951 * The serial number is valid, but since this is only vendor 952 * unique, we'll combine the inquiry vid and pid with the 953 * serial number. 954 */ 955 *id_len += sizeof (inq_std->inq_vid); 956 *id_len += sizeof (inq_std->inq_pid); 957 958 if ((*id = DEVID_MALLOC(*id_len)) == NULL) { 959 *id_len = 0; 960 return; 961 } 962 963 bcopy(&inq_std->inq_vid, *id, sizeof (inq_std->inq_vid)); 964 bcopy(&inq_std->inq_pid, &(*id)[sizeof (inq_std->inq_vid)], 965 sizeof (inq_std->inq_pid)); 966 bcopy(&inq80[4], &(*id)[sizeof (inq_std->inq_vid) + 967 sizeof (inq_std->inq_pid)], inq80[3]); 968 969 *id_type = DEVID_SCSI_SERIAL; 970 break; 971 } 972 973 /* 974 * The spec suggests that the command could succeed but return all 975 * spaces if the product serial number is not available. In this case 976 * we need to fail this routine. To accomplish this, we compare our 977 * length to the serial number length. If they are the same, then we 978 * never copied in the vid and updated the length. That being the case, 979 * we must not have found a valid serial number. 980 */ 981 if (*id_len == (size_t)inq80[3]) { 982 /* empty unit serial number */ 983 if (*id != NULL) { 984 DEVID_FREE(*id, *id_len); 985 } 986 *id = NULL; 987 *id_len = 0; 988 } 989 } 990 991 992 /* 993 * Function: encode_sun_serialnum 994 * 995 * Description: This routine finds the unique devid from the inquiry page 996 * 0x80, serial number page. If available and fills the wwn 997 * and length parameters. 998 * 999 * Arguments: version - encode version 1000 * inq - standard inquiry data 1001 * inq_len - standard inquiry data len 1002 * id - raw id 1003 * id_len - raw id len 1004 * id_type - raw id type 1005 * 1006 * Return Code: DEVID_SUCCESS 1007 * DEVID_FAILURE 1008 */ 1009 /* ARGSUSED */ 1010 static void 1011 encode_sun_serialnum(int version, uchar_t *inq, 1012 size_t inq_len, uchar_t **id, size_t *id_len, ushort_t *id_type) 1013 { 1014 struct scsi_inquiry *inq_std = (struct scsi_inquiry *)inq; 1015 1016 DEVID_ASSERT(inq != NULL); 1017 DEVID_ASSERT(id != NULL); 1018 DEVID_ASSERT(id_len != NULL); 1019 DEVID_ASSERT(id_type != NULL); 1020 1021 /* verify enough buffer is available */ 1022 if (inq_len < SCMD_MIN_STANDARD_INQUIRY_SIZE) { 1023 return; 1024 } 1025 1026 /* sun qual drive */ 1027 if ((inq_std != NULL) && 1028 (bcmp(&inq_std->inq_pid[SCSI_INQUIRY_VID_POS], 1029 SCSI_INQUIRY_VID_SUN, SCSI_INQUIRY_VID_SUN_LEN) == 0)) { 1030 /* 1031 * VPD pages 0x83 and 0x80 are unavailable. This 1032 * is a Sun qualified disk as indicated by 1033 * "SUN" in bytes 25-27 of the inquiry data 1034 * (bytes 9-11 of the pid). Devid's are created 1035 * for Sun qualified disks by combining the 1036 * vendor id with the product id with the serial 1037 * number located in bytes 36-47 of the inquiry data. 1038 */ 1039 1040 /* get data size */ 1041 *id_len = sizeof (inq_std->inq_vid) + 1042 sizeof (inq_std->inq_pid) + 1043 sizeof (inq_std->inq_serial); 1044 1045 if ((*id = DEVID_MALLOC(*id_len)) == NULL) { 1046 *id_len = 0; 1047 return; 1048 } 1049 1050 /* copy the vid at the beginning */ 1051 bcopy(&inq_std->inq_vid, *id, 1052 sizeof (inq_std->inq_vid)); 1053 1054 /* copy the pid after the vid */ 1055 bcopy(&inq_std->inq_pid, 1056 &(*id)[sizeof (inq_std->inq_vid)], 1057 sizeof (inq_std->inq_pid)); 1058 1059 /* copy the serial number after the vid and pid */ 1060 bcopy(&inq_std->inq_serial, 1061 &(*id)[sizeof (inq_std->inq_vid) + 1062 sizeof (inq_std->inq_pid)], 1063 sizeof (inq_std->inq_serial)); 1064 1065 /* devid formed from inquiry data */ 1066 *id_type = DEVID_SCSI_SERIAL; 1067 } 1068 } 1069 1070 1071 /* 1072 * Function: devid_scsi_init 1073 * 1074 * Description: This routine is used to create a devid for a scsi 1075 * devid type. 1076 * 1077 * Arguments: hint - driver soft state (unit) structure 1078 * raw_id - pass by reference variable to hold wwn 1079 * raw_id_len - wwn length 1080 * raw_id_type - 1081 * ret_devid - 1082 * 1083 * Return Code: DEVID_SUCCESS 1084 * DEVID_FAILURE 1085 * 1086 */ 1087 static int 1088 devid_scsi_init( 1089 char *driver_name, 1090 uchar_t *raw_id, 1091 size_t raw_id_len, 1092 ushort_t raw_id_type, 1093 ddi_devid_t *ret_devid) 1094 { 1095 impl_devid_t *i_devid = NULL; 1096 int i_devid_len = 0; 1097 int driver_name_len = 0; 1098 ushort_t u_raw_id_len = 0; 1099 1100 DEVID_ASSERT(raw_id != NULL); 1101 DEVID_ASSERT(ret_devid != NULL); 1102 1103 if (!IS_DEVID_SCSI_TYPE(raw_id_type)) { 1104 *ret_devid = NULL; 1105 return (DEVID_FAILURE); 1106 } 1107 1108 i_devid_len = sizeof (*i_devid) + raw_id_len - sizeof (i_devid->did_id); 1109 if ((i_devid = DEVID_MALLOC(i_devid_len)) == NULL) { 1110 *ret_devid = NULL; 1111 return (DEVID_FAILURE); 1112 } 1113 1114 i_devid->did_magic_hi = DEVID_MAGIC_MSB; 1115 i_devid->did_magic_lo = DEVID_MAGIC_LSB; 1116 i_devid->did_rev_hi = DEVID_REV_MSB; 1117 i_devid->did_rev_lo = DEVID_REV_LSB; 1118 DEVID_FORMTYPE(i_devid, raw_id_type); 1119 u_raw_id_len = raw_id_len; 1120 DEVID_FORMLEN(i_devid, u_raw_id_len); 1121 1122 /* Fill in driver name hint */ 1123 bzero(i_devid->did_driver, DEVID_HINT_SIZE); 1124 if (driver_name != NULL) { 1125 driver_name_len = strlen(driver_name); 1126 if (driver_name_len > DEVID_HINT_SIZE) { 1127 /* Pick up last four characters of driver name */ 1128 driver_name += driver_name_len - DEVID_HINT_SIZE; 1129 driver_name_len = DEVID_HINT_SIZE; 1130 } 1131 bcopy(driver_name, i_devid->did_driver, driver_name_len); 1132 } 1133 1134 bcopy(raw_id, i_devid->did_id, raw_id_len); 1135 1136 /* return device id */ 1137 *ret_devid = (ddi_devid_t)i_devid; 1138 return (DEVID_SUCCESS); 1139 } 1140 1141 1142 /* 1143 * Function: devid_to_guid 1144 * 1145 * Description: This routine extracts a guid string form a devid. 1146 * The common use of this guid is for a HBA driver 1147 * to pass into mdi_pi_alloc(). 1148 * 1149 * Arguments: devid - devid to extract guid from 1150 * 1151 * Return Code: guid string - success 1152 * NULL - failure 1153 */ 1154 char * 1155 #ifdef _KERNEL 1156 ddi_devid_to_guid(ddi_devid_t devid) 1157 #else /* !_KERNEL */ 1158 devid_to_guid(ddi_devid_t devid) 1159 #endif /* _KERNEL */ 1160 { 1161 impl_devid_t *id = (impl_devid_t *)devid; 1162 int len = 0; 1163 int idx = 0; 1164 int num = 0; 1165 char *guid = NULL; 1166 char *ptr = NULL; 1167 char *dp = NULL; 1168 1169 DEVID_ASSERT(devid != NULL); 1170 1171 /* NULL devid -> NULL guid */ 1172 if (devid == NULL) 1173 return (NULL); 1174 1175 if (!IS_DEVID_GUID_TYPE(DEVID_GETTYPE(id))) 1176 return (NULL); 1177 1178 /* guid is always converted to ascii, append NULL */ 1179 len = DEVID_GETLEN(id); 1180 1181 /* allocate guid string */ 1182 if ((guid = DEVID_MALLOC((len * 2) + 1)) == NULL) 1183 return (NULL); 1184 1185 /* perform encode of id to hex string */ 1186 ptr = guid; 1187 for (idx = 0, dp = &id->did_id[0]; idx < len; idx++, dp++) { 1188 num = ((*dp) >> 4) & 0xF; 1189 *ptr++ = (num < 10) ? (num + '0') : (num + ('a' - 10)); 1190 num = (*dp) & 0xF; 1191 *ptr++ = (num < 10) ? (num + '0') : (num + ('a' - 10)); 1192 } 1193 *ptr = 0; 1194 1195 return (guid); 1196 } 1197 1198 /* 1199 * Function: devid_free_guid 1200 * 1201 * Description: This routine frees a guid allocated by 1202 * devid_to_guid(). 1203 * 1204 * Arguments: guid - guid to free 1205 */ 1206 void 1207 #ifdef _KERNEL 1208 ddi_devid_free_guid(char *guid) 1209 #else /* !_KERNEL */ 1210 devid_free_guid(char *guid) 1211 #endif /* _KERNEL */ 1212 { 1213 if (guid != NULL) { 1214 DEVID_FREE(guid, strlen(guid) + 1); 1215 } 1216 } 1217 1218 static char 1219 ctoi(char c) 1220 { 1221 if ((c >= '0') && (c <= '9')) 1222 c -= '0'; 1223 else if ((c >= 'A') && (c <= 'F')) 1224 c = c - 'A' + 10; 1225 else if ((c >= 'a') && (c <= 'f')) 1226 c = c - 'a' + 10; 1227 else 1228 c = -1; 1229 return (c); 1230 } 1231 1232 /* ====NOTE: The scsi_* interfaces are not related to devids :NOTE==== */ 1233 1234 /* 1235 * Function: scsi_wwnstr_to_wwn 1236 * 1237 * Description: This routine translates wwn from wwnstr string to uint64 wwn. 1238 * 1239 * Arguments: wwnstr - the string wwn to be transformed 1240 * wwnp - the pointer to 64 bit wwn 1241 */ 1242 int 1243 scsi_wwnstr_to_wwn(const char *wwnstr, uint64_t *wwnp) 1244 { 1245 int i; 1246 char cl, ch; 1247 uint64_t tmp; 1248 1249 if (wwnp == NULL) 1250 return (DDI_FAILURE); 1251 *wwnp = 0; 1252 1253 if (wwnstr == NULL) 1254 return (DDI_FAILURE); 1255 1256 /* Skip leading 'w' if wwnstr is in unit-address form */ 1257 wwnstr = scsi_wwnstr_skip_ua_prefix(wwnstr); 1258 1259 if (strlen(wwnstr) != 16) 1260 return (DDI_FAILURE); 1261 1262 for (i = 0; i < 8; i++) { 1263 ch = ctoi(*wwnstr++); 1264 cl = ctoi(*wwnstr++); 1265 if (cl == -1 || ch == -1) { 1266 return (DDI_FAILURE); 1267 } 1268 tmp = (ch << 4) + cl; 1269 *wwnp = (*wwnp << 8) | tmp; 1270 } 1271 return (DDI_SUCCESS); 1272 } 1273 1274 /* 1275 * Function: scsi_wwn_to_wwnstr 1276 * 1277 * Description: This routine translates from a uint64 wwn to a wwnstr 1278 * 1279 * Arguments: 1280 * wwn - the 64 bit wwn 1281 * unit_address_form - do we want a leading 'w'? 1282 * wwnstr - allow caller to perform wwnstr allocation. 1283 * If non-NULL, don't use scsi_free_wwnstr(), 1284 * and make sure you provide 18/17 bytes of space. 1285 */ 1286 char * 1287 scsi_wwn_to_wwnstr(uint64_t wwn, int unit_address_form, char *wwnstr) 1288 { 1289 int len; 1290 1291 /* make space for leading 'w' */ 1292 if (unit_address_form) 1293 len = 1 + 16 + 1; /* "w0123456789abcdef\0" */ 1294 else 1295 len = 16 + 1; /* "0123456789abcdef\0" */ 1296 1297 if (wwnstr == NULL) { 1298 /* We allocate, caller uses scsi_free_wwnstr(). */ 1299 if ((wwnstr = DEVID_MALLOC(len)) == NULL) 1300 return (NULL); 1301 } 1302 1303 if (unit_address_form) 1304 (void) snprintf(wwnstr, len, "w%016" PRIx64, wwn); 1305 else 1306 (void) snprintf(wwnstr, len, "%016" PRIx64, wwn); 1307 return (wwnstr); 1308 } 1309 1310 /* 1311 * Function: scsi_wwnstr_hexcase 1312 * 1313 * Description: This routine switches a wwnstr to upper/lower case hex 1314 * (a wwnstr uses lower-case hex by default). 1315 * 1316 * Arguments: 1317 * wwnstr - the pointer to the wwnstr string. 1318 * upper_case_hex - non-zero will convert to upper_case hex 1319 * zero will convert to lower case hex. 1320 */ 1321 void 1322 scsi_wwnstr_hexcase(char *wwnstr, int upper_case_hex) 1323 { 1324 char *s; 1325 char c; 1326 1327 for (s = wwnstr; *s; s++) { 1328 c = *s; 1329 if ((upper_case_hex != 0) && 1330 ((c >= 'a') && (c <= 'f'))) 1331 c -= ('a' - 'A'); /* lower to upper */ 1332 else if ((upper_case_hex == 0) && 1333 ((c >= 'A') && (c <= 'F'))) 1334 c += ('a' - 'A'); /* upper to lower */ 1335 *s = c; 1336 } 1337 } 1338 1339 /* 1340 * Function: scsi_wwnstr_skip_ua_prefix 1341 * 1342 * Description: This routine removes the leading 'w' in wwnstr, 1343 * if its in unit-address form. 1344 * 1345 * Arguments: wwnstr - the string wwn to be transformed 1346 * 1347 */ 1348 const char * 1349 scsi_wwnstr_skip_ua_prefix(const char *wwnstr) 1350 { 1351 if (*wwnstr == 'w') 1352 wwnstr++; 1353 return (wwnstr); 1354 } 1355 1356 /* 1357 * Function: scsi_wwnstr_free 1358 * 1359 * Description: This routine frees a wwnstr returned by a call 1360 * to scsi_wwn_to_strwwn with a NULL wwnstr argument. 1361 * 1362 * Arguments: 1363 * wwnstr - the pointer to the wwnstr string to free. 1364 */ 1365 void 1366 scsi_free_wwnstr(char *wwnstr) 1367 { 1368 #ifdef _KERNEL 1369 kmem_free(wwnstr, strlen(wwnstr) + 1); 1370 #else /* _KERNEL */ 1371 free(wwnstr); 1372 #endif /* _KERNEL */ 1373 } 1374 1375 /* 1376 * Function: scsi_lun_to_lun64/scsi_lun64_to_lun 1377 * 1378 * Description: Convert between normalized (SCSI-3) LUN format, as 1379 * described by scsi_lun_t, and a normalized lun64_t 1380 * representation (used by Solaris SCSI_ADDR_PROP_LUN64 1381 * "lun64" property). The normalized representation maps 1382 * in a compatible way to SCSI-2 LUNs. See scsi_address.h 1383 * 1384 * SCSI-3 LUNs are 64 bits. SCSI-2 LUNs are 3 bits (up to 1385 * 5 bits in non-compliant implementations). SCSI-3 will 1386 * pass a (64-bit) scsi_lun_t, but we need a 1387 * representation from which we can for example, make 1388 * device names. For unit-address compatibility, we represent 1389 * 64-bit LUN numbers in such a way that they appear like they 1390 * would have under SCSI-2. This means that the single level 1391 * LUN number is in the lowest byte with the second, 1392 * third, and fourth level LUNs represented in 1393 * successively higher bytes. In particular, if (and only 1394 * if) the first byte of a 64 bit LUN is zero, denoting 1395 * "Peripheral Device Addressing Method" and "Bus 1396 * Identifier" zero, then the target implements LUNs 1397 * compatible in spirit with SCSI-2 LUNs (although under 1398 * SCSI-3 there may be up to 256 of them). Under SCSI-3 1399 * rules, a target is *required* to use this format if it 1400 * contains 256 or fewer Logical Units, none of which are 1401 * dependent logical units. These routines have knowledge 1402 * of the structure and size of a scsi_lun_t. 1403 * 1404 * NOTE: We tolerate vendors that use "Single level LUN structure using 1405 * peripheral device addressing method" with a non-zero bus identifier 1406 * (spec says bus identifier must be zero). Described another way, we let 1407 * the non-'addressing method' bits of sl_lun1_msb contribute to our lun64 1408 * value). 1409 */ 1410 scsi_lun64_t 1411 scsi_lun_to_lun64(scsi_lun_t lun) 1412 { 1413 scsi_lun64_t lun64; 1414 1415 /* 1416 * Check to see if we have a single level lun that uses the 1417 * "Peripheral Device" addressing method. If so, the lun64 value is 1418 * kept in Solaris 'unit-address compatibility' form. 1419 */ 1420 if (((lun.sl_lun2_msb == 0) && (lun.sl_lun2_lsb == 0) && 1421 (lun.sl_lun3_msb == 0) && (lun.sl_lun3_lsb == 0) && 1422 (lun.sl_lun4_msb == 0) && (lun.sl_lun4_lsb == 0)) && 1423 ((lun.sl_lun1_msb & SCSI_LUN_AM_MASK) == SCSI_LUN_AM_PDEV)) { 1424 /* 1425 * LUN has Solaris 'unit-address compatibility' form, construct 1426 * lun64 value from non-'addressing method' bits of msb and lsb. 1427 */ 1428 lun64 = ((lun.sl_lun1_msb & ~SCSI_LUN_AM_MASK) << 8) | 1429 lun.sl_lun1_lsb; 1430 } else { 1431 /* 1432 * LUN does not have a Solaris 'unit-address compatibility' 1433 * form, construct lun64 value in full 64 bit LUN format. 1434 */ 1435 lun64 = 1436 ((scsi_lun64_t)lun.sl_lun1_msb << 56) | 1437 ((scsi_lun64_t)lun.sl_lun1_lsb << 48) | 1438 ((scsi_lun64_t)lun.sl_lun2_msb << 40) | 1439 ((scsi_lun64_t)lun.sl_lun2_lsb << 32) | 1440 ((scsi_lun64_t)lun.sl_lun3_msb << 24) | 1441 ((scsi_lun64_t)lun.sl_lun3_lsb << 16) | 1442 ((scsi_lun64_t)lun.sl_lun4_msb << 8) | 1443 (scsi_lun64_t)lun.sl_lun4_lsb; 1444 } 1445 return (lun64); 1446 } 1447 1448 scsi_lun_t 1449 scsi_lun64_to_lun(scsi_lun64_t lun64) 1450 { 1451 scsi_lun_t lun; 1452 1453 if (lun64 <= (((0xFF & ~SCSI_LUN_AM_MASK) << 8) | 0xFF)) { 1454 /* 1455 * lun64 is in Solaris 'unit-address compatibility' form. 1456 */ 1457 lun.sl_lun1_msb = SCSI_LUN_AM_PDEV | (lun64 >> 8); 1458 lun.sl_lun1_lsb = (uchar_t)lun64; 1459 lun.sl_lun2_msb = 0; 1460 lun.sl_lun2_lsb = 0; 1461 lun.sl_lun3_msb = 0; 1462 lun.sl_lun3_lsb = 0; 1463 lun.sl_lun4_msb = 0; 1464 lun.sl_lun4_lsb = 0; 1465 } else { 1466 /* lun64 is in full 64 bit LUN format. */ 1467 lun.sl_lun1_msb = (uchar_t)(lun64 >> 56); 1468 lun.sl_lun1_lsb = (uchar_t)(lun64 >> 48); 1469 lun.sl_lun2_msb = (uchar_t)(lun64 >> 40); 1470 lun.sl_lun2_lsb = (uchar_t)(lun64 >> 32); 1471 lun.sl_lun3_msb = (uchar_t)(lun64 >> 24); 1472 lun.sl_lun3_lsb = (uchar_t)(lun64 >> 16); 1473 lun.sl_lun4_msb = (uchar_t)(lun64 >> 8); 1474 lun.sl_lun4_lsb = (uchar_t)(lun64); 1475 } 1476 return (lun); 1477 } 1478 1479 /* 1480 * This routine returns the true length of the ascii inquiry fields that are to 1481 * be created by removing the padded spaces at the end of the inquiry data. 1482 * This routine was designed for trimming spaces from the vid, pid and revision 1483 * which are defined as being left aligned. In addition, we return 0 length 1484 * if the field is full of all 0's or spaces, indicating to the caller that 1485 * the device was not ready to return the inquiry data as per note 65 in 1486 * the scsi-2 spec. 1487 */ 1488 int 1489 scsi_ascii_inquiry_len(char *field, size_t length) 1490 { 1491 int retval; 1492 int trailer; 1493 char *p; 1494 1495 retval = length; 1496 1497 /* 1498 * The vid, pid and revision are left-aligned ascii fields within the 1499 * inquiry data. Here we trim the end of these fields by discounting 1500 * length associated with trailing spaces or NULL bytes. The remaining 1501 * bytes shall be only graphics codes - 0x20 through 0x7e as per the 1502 * scsi spec definition. If we have all 0's or spaces, we return 0 1503 * length. For devices that store inquiry data on the device, they 1504 * can return 0's or spaces in these fields until the data is avail- 1505 * able from the device (See NOTE 65 in the scsi-2 specification 1506 * around the inquiry command.) We don't want to create a field in 1507 * the case of a device not able to return valid data. 1508 */ 1509 trailer = 1; 1510 for (p = field + length - 1; p >= field; p--) { 1511 if (trailer) { 1512 if ((*p == ' ') || (*p == '\0')) { 1513 retval--; 1514 continue; 1515 } 1516 trailer = 0; 1517 } 1518 1519 /* each char must be within 0x20 - 0x7e */ 1520 if (*p < 0x20 || *p > 0x7e) { 1521 retval = -1; 1522 break; 1523 } 1524 1525 } 1526 1527 return (retval); 1528 } 1529