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 }