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