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