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