xref: /titanic_50/usr/src/cmd/luxadm/fchba.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte /*
22*fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*fcf3ce44SJohn Forte  * Use is subject to license terms.
24*fcf3ce44SJohn Forte  */
25*fcf3ce44SJohn Forte 
26*fcf3ce44SJohn Forte 
27*fcf3ce44SJohn Forte 
28*fcf3ce44SJohn Forte #include	<hbaapi.h>
29*fcf3ce44SJohn Forte #include	<stdio.h>
30*fcf3ce44SJohn Forte #include	<unistd.h>
31*fcf3ce44SJohn Forte #include	<stdlib.h>
32*fcf3ce44SJohn Forte #include	<sys/param.h>
33*fcf3ce44SJohn Forte #include	<sys/types.h>
34*fcf3ce44SJohn Forte #include	<sys/stat.h>
35*fcf3ce44SJohn Forte #include	<string.h>
36*fcf3ce44SJohn Forte #include	<strings.h>
37*fcf3ce44SJohn Forte #include	<ctype.h>
38*fcf3ce44SJohn Forte #include	<sys/scsi/generic/sense.h>
39*fcf3ce44SJohn Forte #include	<sys/scsi/generic/mode.h>
40*fcf3ce44SJohn Forte #include	<sys/scsi/generic/inquiry.h>
41*fcf3ce44SJohn Forte #include	<errno.h>
42*fcf3ce44SJohn Forte #include	<libdevice.h>
43*fcf3ce44SJohn Forte #include	<config_admin.h>
44*fcf3ce44SJohn Forte #include	<sys/byteorder.h>
45*fcf3ce44SJohn Forte #include	<sys/fibre-channel/fcio.h>
46*fcf3ce44SJohn Forte #include	"common.h"
47*fcf3ce44SJohn Forte #include	"sun_fc_version.h"
48*fcf3ce44SJohn Forte 
49*fcf3ce44SJohn Forte #define	DEFAULT_LUN_COUNT	1024
50*fcf3ce44SJohn Forte #define	LUN_SIZE		8
51*fcf3ce44SJohn Forte #define	LUN_HEADER_SIZE		8
52*fcf3ce44SJohn Forte #define	DEFAULT_LUN_LENGTH	DEFAULT_LUN_COUNT   *	\
53*fcf3ce44SJohn Forte 				LUN_SIZE	    +	\
54*fcf3ce44SJohn Forte 				LUN_HEADER_SIZE
55*fcf3ce44SJohn Forte struct lun_val {
56*fcf3ce44SJohn Forte 	uchar_t val[8];
57*fcf3ce44SJohn Forte };
58*fcf3ce44SJohn Forte struct rep_luns_rsp {
59*fcf3ce44SJohn Forte 	uint32_t    length;
60*fcf3ce44SJohn Forte 	uint32_t    rsrvd;
61*fcf3ce44SJohn Forte 	struct lun_val  lun[1];
62*fcf3ce44SJohn Forte };
63*fcf3ce44SJohn Forte 
64*fcf3ce44SJohn Forte /* Extracted from the old scsi.h file */
65*fcf3ce44SJohn Forte struct  capacity_data_struct {
66*fcf3ce44SJohn Forte 	uint_t  last_block_addr;
67*fcf3ce44SJohn Forte 	uint_t  block_size;
68*fcf3ce44SJohn Forte };
69*fcf3ce44SJohn Forte 
70*fcf3ce44SJohn Forte 
71*fcf3ce44SJohn Forte /* Structure to handle the inq. page 0x80 serial number */
72*fcf3ce44SJohn Forte struct page80 {
73*fcf3ce44SJohn Forte 	uchar_t inq_dtype;
74*fcf3ce44SJohn Forte 	uchar_t inq_page_code;
75*fcf3ce44SJohn Forte 	uchar_t reserved;
76*fcf3ce44SJohn Forte 	uchar_t inq_page_len;
77*fcf3ce44SJohn Forte 	uchar_t inq_serial[251];
78*fcf3ce44SJohn Forte };
79*fcf3ce44SJohn Forte 
80*fcf3ce44SJohn Forte extern char		*dtype[];
81*fcf3ce44SJohn Forte extern int		Options;
82*fcf3ce44SJohn Forte extern const int	OPTION_P;
83*fcf3ce44SJohn Forte 
84*fcf3ce44SJohn Forte int skip_hba(int i);
85*fcf3ce44SJohn Forte int find_supported_inq_page(HBA_HANDLE handle, HBA_WWN hwwn, HBA_WWN pwwn,
86*fcf3ce44SJohn Forte     uint64_t lun, int page_num);
87*fcf3ce44SJohn Forte /*
88*fcf3ce44SJohn Forte  * The routines within this file operate against the T11
89*fcf3ce44SJohn Forte  * HBA API interface.  In some cases, proprietary Sun driver
90*fcf3ce44SJohn Forte  * interface are also called to add additional information
91*fcf3ce44SJohn Forte  * above what the standard library supports.
92*fcf3ce44SJohn Forte  */
93*fcf3ce44SJohn Forte 
94*fcf3ce44SJohn Forte uint64_t
wwnConversion(uchar_t * wwn)95*fcf3ce44SJohn Forte wwnConversion(uchar_t *wwn) {
96*fcf3ce44SJohn Forte 	uint64_t tmp;
97*fcf3ce44SJohn Forte 	(void) memcpy(&tmp, wwn, sizeof (uint64_t));
98*fcf3ce44SJohn Forte 	return (ntohll(tmp));
99*fcf3ce44SJohn Forte }
100*fcf3ce44SJohn Forte 
printStatus(HBA_STATUS status)101*fcf3ce44SJohn Forte void printStatus(HBA_STATUS status) {
102*fcf3ce44SJohn Forte 	switch (status) {
103*fcf3ce44SJohn Forte 	case HBA_STATUS_OK:
104*fcf3ce44SJohn Forte 	    printf(MSGSTR(2410, "OK"));
105*fcf3ce44SJohn Forte 	    return;
106*fcf3ce44SJohn Forte 	case HBA_STATUS_ERROR:
107*fcf3ce44SJohn Forte 	    printf(MSGSTR(2411, "ERROR"));
108*fcf3ce44SJohn Forte 	    return;
109*fcf3ce44SJohn Forte 	case HBA_STATUS_ERROR_NOT_SUPPORTED:
110*fcf3ce44SJohn Forte 	    printf(MSGSTR(2412, "NOT SUPPORTED"));
111*fcf3ce44SJohn Forte 	    return;
112*fcf3ce44SJohn Forte 	case HBA_STATUS_ERROR_INVALID_HANDLE:
113*fcf3ce44SJohn Forte 	    printf(MSGSTR(2413, "INVALID HANDLE"));
114*fcf3ce44SJohn Forte 	    return;
115*fcf3ce44SJohn Forte 	case HBA_STATUS_ERROR_ARG:
116*fcf3ce44SJohn Forte 	    printf(MSGSTR(2414, "ERROR ARG"));
117*fcf3ce44SJohn Forte 	    return;
118*fcf3ce44SJohn Forte 	case HBA_STATUS_ERROR_ILLEGAL_WWN:
119*fcf3ce44SJohn Forte 	    printf(MSGSTR(2415, "ILLEGAL WWN"));
120*fcf3ce44SJohn Forte 	    return;
121*fcf3ce44SJohn Forte 	case HBA_STATUS_ERROR_ILLEGAL_INDEX:
122*fcf3ce44SJohn Forte 	    printf(MSGSTR(2416, "ILLEGAL INDEX"));
123*fcf3ce44SJohn Forte 	    return;
124*fcf3ce44SJohn Forte 	case HBA_STATUS_ERROR_MORE_DATA:
125*fcf3ce44SJohn Forte 	    printf(MSGSTR(2417, "MORE DATA"));
126*fcf3ce44SJohn Forte 	    return;
127*fcf3ce44SJohn Forte 	case HBA_STATUS_ERROR_STALE_DATA:
128*fcf3ce44SJohn Forte 	    printf(MSGSTR(2418, "STALE DATA"));
129*fcf3ce44SJohn Forte 	    return;
130*fcf3ce44SJohn Forte 	case HBA_STATUS_SCSI_CHECK_CONDITION:
131*fcf3ce44SJohn Forte 	    printf(MSGSTR(2419, "SCSI CHECK CONDITION"));
132*fcf3ce44SJohn Forte 	    return;
133*fcf3ce44SJohn Forte 	case HBA_STATUS_ERROR_BUSY:
134*fcf3ce44SJohn Forte 	    printf(MSGSTR(2420, "BUSY"));
135*fcf3ce44SJohn Forte 	    return;
136*fcf3ce44SJohn Forte 	case HBA_STATUS_ERROR_TRY_AGAIN:
137*fcf3ce44SJohn Forte 	    printf(MSGSTR(2421, "TRY AGAIN"));
138*fcf3ce44SJohn Forte 	    return;
139*fcf3ce44SJohn Forte 	case HBA_STATUS_ERROR_UNAVAILABLE:
140*fcf3ce44SJohn Forte 	    printf(MSGSTR(2422, "UNAVAILABLE"));
141*fcf3ce44SJohn Forte 	    return;
142*fcf3ce44SJohn Forte 	default:
143*fcf3ce44SJohn Forte 	    printf(MSGSTR(2423, "UNKNOWN ERROR TYPE %d"), status);
144*fcf3ce44SJohn Forte 	    return;
145*fcf3ce44SJohn Forte 	    }
146*fcf3ce44SJohn Forte }
147*fcf3ce44SJohn Forte 
148*fcf3ce44SJohn Forte uint32_t
getNumberOfAdapters()149*fcf3ce44SJohn Forte getNumberOfAdapters() {
150*fcf3ce44SJohn Forte 	uint32_t count = HBA_GetNumberOfAdapters();
151*fcf3ce44SJohn Forte 	if (count == 0) {
152*fcf3ce44SJohn Forte 		fprintf(stderr, MSGSTR(2405,
153*fcf3ce44SJohn Forte 			"\nERROR: No Fibre Channel Adapters found.\n"));
154*fcf3ce44SJohn Forte 	}
155*fcf3ce44SJohn Forte 	return (count);
156*fcf3ce44SJohn Forte }
157*fcf3ce44SJohn Forte 
158*fcf3ce44SJohn Forte #define	MAX_RETRIES	10
159*fcf3ce44SJohn Forte 
160*fcf3ce44SJohn Forte /*
161*fcf3ce44SJohn Forte  * Returns non-zero on failure (aka, HBA_STATUS_ERROR_*
162*fcf3ce44SJohn Forte  * Will handle retries if applicable.
163*fcf3ce44SJohn Forte  */
164*fcf3ce44SJohn Forte int
getAdapterAttrs(HBA_HANDLE handle,char * name,HBA_ADAPTERATTRIBUTES * attrs)165*fcf3ce44SJohn Forte getAdapterAttrs(HBA_HANDLE handle, char *name, HBA_ADAPTERATTRIBUTES *attrs) {
166*fcf3ce44SJohn Forte 	int count = 0;
167*fcf3ce44SJohn Forte 	HBA_STATUS status = HBA_STATUS_ERROR_TRY_AGAIN; /* force first pass */
168*fcf3ce44SJohn Forte 
169*fcf3ce44SJohn Forte 	/* Loop as long as we have a retryable error */
170*fcf3ce44SJohn Forte 	while ((status == HBA_STATUS_ERROR_TRY_AGAIN ||
171*fcf3ce44SJohn Forte 		status == HBA_STATUS_ERROR_BUSY) && count++ < MAX_RETRIES) {
172*fcf3ce44SJohn Forte 		status = HBA_GetAdapterAttributes(handle, attrs);
173*fcf3ce44SJohn Forte 		if (status == HBA_STATUS_OK) {
174*fcf3ce44SJohn Forte 			break;
175*fcf3ce44SJohn Forte 		}
176*fcf3ce44SJohn Forte 		(void) sleep(1);
177*fcf3ce44SJohn Forte 	}
178*fcf3ce44SJohn Forte 	if (status != HBA_STATUS_OK) {
179*fcf3ce44SJohn Forte 		/* We encountered a non-retryable error */
180*fcf3ce44SJohn Forte 		fprintf(stderr, MSGSTR(2501,
181*fcf3ce44SJohn Forte 		"\nERROR: Unable to retrieve adapter port details (%s)"),
182*fcf3ce44SJohn Forte 		name);
183*fcf3ce44SJohn Forte 		printStatus(status);
184*fcf3ce44SJohn Forte 		fprintf(stderr, "\n");
185*fcf3ce44SJohn Forte 	}
186*fcf3ce44SJohn Forte 	return (status);
187*fcf3ce44SJohn Forte }
188*fcf3ce44SJohn Forte 
189*fcf3ce44SJohn Forte /*
190*fcf3ce44SJohn Forte  * Returns non-zero on failure (aka, HBA_STATUS_ERROR_*
191*fcf3ce44SJohn Forte  * Will handle retries if applicable.
192*fcf3ce44SJohn Forte  */
193*fcf3ce44SJohn Forte int
getAdapterPortAttrs(HBA_HANDLE handle,char * name,int portIndex,HBA_PORTATTRIBUTES * attrs)194*fcf3ce44SJohn Forte getAdapterPortAttrs(HBA_HANDLE handle, char *name, int portIndex,
195*fcf3ce44SJohn Forte 	    HBA_PORTATTRIBUTES *attrs) {
196*fcf3ce44SJohn Forte 	int count = 0;
197*fcf3ce44SJohn Forte 	HBA_STATUS status = HBA_STATUS_ERROR_TRY_AGAIN; /* force first pass */
198*fcf3ce44SJohn Forte 
199*fcf3ce44SJohn Forte 	/* Loop as long as we have a retryable error */
200*fcf3ce44SJohn Forte 	while ((status == HBA_STATUS_ERROR_TRY_AGAIN ||
201*fcf3ce44SJohn Forte 		status == HBA_STATUS_ERROR_BUSY) && count++ < MAX_RETRIES) {
202*fcf3ce44SJohn Forte 		status = HBA_GetAdapterPortAttributes(handle, portIndex, attrs);
203*fcf3ce44SJohn Forte 		if (status == HBA_STATUS_OK) {
204*fcf3ce44SJohn Forte 			break;
205*fcf3ce44SJohn Forte 		}
206*fcf3ce44SJohn Forte 
207*fcf3ce44SJohn Forte 		/* The odds of this occuring are very slim, but possible. */
208*fcf3ce44SJohn Forte 		if (status == HBA_STATUS_ERROR_STALE_DATA) {
209*fcf3ce44SJohn Forte 			/*
210*fcf3ce44SJohn Forte 			 * If we hit a stale data scenario,
211*fcf3ce44SJohn Forte 			 * we'll just tell the user to try again.
212*fcf3ce44SJohn Forte 			 */
213*fcf3ce44SJohn Forte 			status = HBA_STATUS_ERROR_TRY_AGAIN;
214*fcf3ce44SJohn Forte 			break;
215*fcf3ce44SJohn Forte 		}
216*fcf3ce44SJohn Forte 		sleep(1);
217*fcf3ce44SJohn Forte 	}
218*fcf3ce44SJohn Forte 	if (status != HBA_STATUS_OK) {
219*fcf3ce44SJohn Forte 		/* We encountered a non-retryable error */
220*fcf3ce44SJohn Forte 		fprintf(stderr, MSGSTR(2501,
221*fcf3ce44SJohn Forte 		"\nERROR: Unable to retrieve adapter port details (%s)"),
222*fcf3ce44SJohn Forte 		name);
223*fcf3ce44SJohn Forte 		printStatus(status);
224*fcf3ce44SJohn Forte 		fprintf(stderr, "\n");
225*fcf3ce44SJohn Forte 	}
226*fcf3ce44SJohn Forte 	return (status);
227*fcf3ce44SJohn Forte }
228*fcf3ce44SJohn Forte 
229*fcf3ce44SJohn Forte /*
230*fcf3ce44SJohn Forte  * Returns non-zero on failure (aka, HBA_STATUS_ERROR_*
231*fcf3ce44SJohn Forte  * Will handle retries if applicable.
232*fcf3ce44SJohn Forte  */
233*fcf3ce44SJohn Forte int
getDiscPortAttrs(HBA_HANDLE handle,char * name,int portIndex,int discIndex,HBA_PORTATTRIBUTES * attrs)234*fcf3ce44SJohn Forte getDiscPortAttrs(HBA_HANDLE handle, char *name, int portIndex, int discIndex,
235*fcf3ce44SJohn Forte 	    HBA_PORTATTRIBUTES *attrs) {
236*fcf3ce44SJohn Forte 	int count = 0;
237*fcf3ce44SJohn Forte 	HBA_STATUS status = HBA_STATUS_ERROR_TRY_AGAIN; /* force first pass */
238*fcf3ce44SJohn Forte 
239*fcf3ce44SJohn Forte 	/* Loop as long as we have a retryable error */
240*fcf3ce44SJohn Forte 	while ((status == HBA_STATUS_ERROR_TRY_AGAIN ||
241*fcf3ce44SJohn Forte 		status == HBA_STATUS_ERROR_BUSY) && count++ < MAX_RETRIES) {
242*fcf3ce44SJohn Forte 		status = HBA_GetDiscoveredPortAttributes(handle, portIndex,
243*fcf3ce44SJohn Forte 				discIndex, attrs);
244*fcf3ce44SJohn Forte 		if (status == HBA_STATUS_OK) {
245*fcf3ce44SJohn Forte 			break;
246*fcf3ce44SJohn Forte 		}
247*fcf3ce44SJohn Forte 
248*fcf3ce44SJohn Forte 		/* The odds of this occuring are very slim, but possible. */
249*fcf3ce44SJohn Forte 		if (status == HBA_STATUS_ERROR_STALE_DATA) {
250*fcf3ce44SJohn Forte 			/*
251*fcf3ce44SJohn Forte 			 * If we hit a stale data scenario, we'll just tell the
252*fcf3ce44SJohn Forte 			 * user to try again.
253*fcf3ce44SJohn Forte 			 */
254*fcf3ce44SJohn Forte 			status = HBA_STATUS_ERROR_TRY_AGAIN;
255*fcf3ce44SJohn Forte 			break;
256*fcf3ce44SJohn Forte 		}
257*fcf3ce44SJohn Forte 		sleep(1);
258*fcf3ce44SJohn Forte 	}
259*fcf3ce44SJohn Forte 	if (status != HBA_STATUS_OK) {
260*fcf3ce44SJohn Forte 		/* We encountered a non-retryable error */
261*fcf3ce44SJohn Forte 		fprintf(stderr, MSGSTR(2504,
262*fcf3ce44SJohn Forte 		"\nERROR: Unable to retrieve target port details (%s)"),
263*fcf3ce44SJohn Forte 		name);
264*fcf3ce44SJohn Forte 		printStatus(status);
265*fcf3ce44SJohn Forte 		fprintf(stderr, "\n");
266*fcf3ce44SJohn Forte 	}
267*fcf3ce44SJohn Forte 	return (status);
268*fcf3ce44SJohn Forte }
269*fcf3ce44SJohn Forte 
270*fcf3ce44SJohn Forte 
271*fcf3ce44SJohn Forte /*ARGSUSED*/
272*fcf3ce44SJohn Forte int
fchba_display_port(int verbose)273*fcf3ce44SJohn Forte fchba_display_port(int verbose)
274*fcf3ce44SJohn Forte {
275*fcf3ce44SJohn Forte 	int retval = 0;
276*fcf3ce44SJohn Forte 	HBA_HANDLE handle;
277*fcf3ce44SJohn Forte 	HBA_ADAPTERATTRIBUTES hbaAttrs;
278*fcf3ce44SJohn Forte 	HBA_PORTATTRIBUTES portAttrs;
279*fcf3ce44SJohn Forte 	HBA_STATUS status;
280*fcf3ce44SJohn Forte 	int count, adapterIndex, portIndex;
281*fcf3ce44SJohn Forte 	char name[256];
282*fcf3ce44SJohn Forte 	char *physical = NULL;
283*fcf3ce44SJohn Forte 	char path[MAXPATHLEN];
284*fcf3ce44SJohn Forte 
285*fcf3ce44SJohn Forte 	if ((retval = loadLibrary())) {
286*fcf3ce44SJohn Forte 	    return (retval);
287*fcf3ce44SJohn Forte 	}
288*fcf3ce44SJohn Forte 
289*fcf3ce44SJohn Forte 	count = getNumberOfAdapters();
290*fcf3ce44SJohn Forte 
291*fcf3ce44SJohn Forte 	for (adapterIndex = 0; adapterIndex < count; adapterIndex ++) {
292*fcf3ce44SJohn Forte 	    if (skip_hba(adapterIndex)) {
293*fcf3ce44SJohn Forte 		continue;
294*fcf3ce44SJohn Forte 	    }
295*fcf3ce44SJohn Forte 	    status = HBA_GetAdapterName(adapterIndex, (char *)&name);
296*fcf3ce44SJohn Forte 	    if (status != HBA_STATUS_OK) {
297*fcf3ce44SJohn Forte 		/* Just skip it, maybe it was DR'd */
298*fcf3ce44SJohn Forte 		continue;
299*fcf3ce44SJohn Forte 	    }
300*fcf3ce44SJohn Forte 	    handle = HBA_OpenAdapter(name);
301*fcf3ce44SJohn Forte 	    if (handle == 0) {
302*fcf3ce44SJohn Forte 		/* Just skip it, maybe it was DR'd */
303*fcf3ce44SJohn Forte 		continue;
304*fcf3ce44SJohn Forte 	    }
305*fcf3ce44SJohn Forte 
306*fcf3ce44SJohn Forte 	    if (getAdapterAttrs(handle, name, &hbaAttrs)) {
307*fcf3ce44SJohn Forte 		/* This should never happen, we'll just skip the adapter */
308*fcf3ce44SJohn Forte 		HBA_CloseAdapter(handle);
309*fcf3ce44SJohn Forte 		continue;
310*fcf3ce44SJohn Forte 	    }
311*fcf3ce44SJohn Forte 
312*fcf3ce44SJohn Forte 	    for (portIndex = 0; portIndex < hbaAttrs.NumberOfPorts;
313*fcf3ce44SJohn Forte 		    portIndex++) {
314*fcf3ce44SJohn Forte 		if (getAdapterPortAttrs(handle, name, portIndex,
315*fcf3ce44SJohn Forte 			&portAttrs)) {
316*fcf3ce44SJohn Forte 		    continue;
317*fcf3ce44SJohn Forte 		}
318*fcf3ce44SJohn Forte 		physical = get_slash_devices_from_osDevName(
319*fcf3ce44SJohn Forte 				portAttrs.OSDeviceName,
320*fcf3ce44SJohn Forte 				STANDARD_DEVNAME_HANDLING);
321*fcf3ce44SJohn Forte 		if (physical) {
322*fcf3ce44SJohn Forte 			char *tmp = strstr(physical, ":fc");
323*fcf3ce44SJohn Forte 			if (tmp) {
324*fcf3ce44SJohn Forte 				*tmp = '\0';
325*fcf3ce44SJohn Forte 				(void) snprintf(path, MAXPATHLEN, "%s:devctl",
326*fcf3ce44SJohn Forte 					physical);
327*fcf3ce44SJohn Forte 			} else {
328*fcf3ce44SJohn Forte 				(void) snprintf(path, MAXPATHLEN, "%s",
329*fcf3ce44SJohn Forte 					physical);
330*fcf3ce44SJohn Forte 			}
331*fcf3ce44SJohn Forte 			free(physical);
332*fcf3ce44SJohn Forte 			physical = NULL;
333*fcf3ce44SJohn Forte 			(void) printf("%-65s  ", path);
334*fcf3ce44SJohn Forte 		} else {
335*fcf3ce44SJohn Forte 			(void) printf("%-65s  ", portAttrs.OSDeviceName);
336*fcf3ce44SJohn Forte 		}
337*fcf3ce44SJohn Forte 		if (portAttrs.NumberofDiscoveredPorts > 0) {
338*fcf3ce44SJohn Forte 		    printf(MSGSTR(2233, "CONNECTED\n"));
339*fcf3ce44SJohn Forte 		} else {
340*fcf3ce44SJohn Forte 		    printf(MSGSTR(2234, "NOT CONNECTED\n"));
341*fcf3ce44SJohn Forte 		}
342*fcf3ce44SJohn Forte 	    }
343*fcf3ce44SJohn Forte 	}
344*fcf3ce44SJohn Forte 	(void) HBA_FreeLibrary();
345*fcf3ce44SJohn Forte 	return (retval);
346*fcf3ce44SJohn Forte }
347*fcf3ce44SJohn Forte 
348*fcf3ce44SJohn Forte /*
349*fcf3ce44SJohn Forte  * Internal routines/structure to deal with a path list
350*fcf3ce44SJohn Forte  * so we can ensure uniqueness
351*fcf3ce44SJohn Forte  */
352*fcf3ce44SJohn Forte struct path_entry {
353*fcf3ce44SJohn Forte 	char path[MAXPATHLEN];
354*fcf3ce44SJohn Forte 	HBA_UINT8 wwn[8];
355*fcf3ce44SJohn Forte 	uchar_t dtype;
356*fcf3ce44SJohn Forte 	struct path_entry *next;
357*fcf3ce44SJohn Forte };
add_path(struct path_entry * head,struct path_entry * cur)358*fcf3ce44SJohn Forte void add_path(struct path_entry *head, struct path_entry *cur) {
359*fcf3ce44SJohn Forte 	struct path_entry *tmp;
360*fcf3ce44SJohn Forte 	for (tmp = head; tmp->next != NULL; tmp = tmp->next) { }
361*fcf3ce44SJohn Forte 		tmp->next = cur;
362*fcf3ce44SJohn Forte }
is_duplicate_path(struct path_entry * head,char * path)363*fcf3ce44SJohn Forte struct path_entry *is_duplicate_path(struct path_entry *head, char *path) {
364*fcf3ce44SJohn Forte 	struct path_entry *tmp;
365*fcf3ce44SJohn Forte 	for (tmp = head; tmp != NULL; tmp = tmp->next) {
366*fcf3ce44SJohn Forte 		if (strncmp(tmp->path, path, sizeof (tmp->path)) == 0) {
367*fcf3ce44SJohn Forte 			return (tmp);
368*fcf3ce44SJohn Forte 		}
369*fcf3ce44SJohn Forte 	}
370*fcf3ce44SJohn Forte 	return (NULL);
371*fcf3ce44SJohn Forte }
free_path_list(struct path_entry * head)372*fcf3ce44SJohn Forte void free_path_list(struct path_entry *head) {
373*fcf3ce44SJohn Forte 	struct path_entry *tmp;
374*fcf3ce44SJohn Forte 	struct path_entry *tmp2;
375*fcf3ce44SJohn Forte 	for (tmp = head; tmp != NULL; ) {
376*fcf3ce44SJohn Forte 		tmp2 = tmp->next;
377*fcf3ce44SJohn Forte 		free(tmp);
378*fcf3ce44SJohn Forte 		tmp = tmp2;
379*fcf3ce44SJohn Forte 	}
380*fcf3ce44SJohn Forte }
381*fcf3ce44SJohn Forte 
382*fcf3ce44SJohn Forte 
383*fcf3ce44SJohn Forte int
is_wwn(char * arg)384*fcf3ce44SJohn Forte is_wwn(char *arg) {
385*fcf3ce44SJohn Forte 	int i;
386*fcf3ce44SJohn Forte 	if (strlen(arg) == 16) {
387*fcf3ce44SJohn Forte 		for (i = 0; i < 16; i++) {
388*fcf3ce44SJohn Forte 			if (!isxdigit(arg[i])) {
389*fcf3ce44SJohn Forte 				return (0);
390*fcf3ce44SJohn Forte 			}
391*fcf3ce44SJohn Forte 		}
392*fcf3ce44SJohn Forte 		return (1);
393*fcf3ce44SJohn Forte 	}
394*fcf3ce44SJohn Forte 	return (0);
395*fcf3ce44SJohn Forte }
396*fcf3ce44SJohn Forte 
397*fcf3ce44SJohn Forte int
is_path(char * arg)398*fcf3ce44SJohn Forte is_path(char *arg) {
399*fcf3ce44SJohn Forte 	struct stat buf;
400*fcf3ce44SJohn Forte 	if (stat(arg, &buf)) {
401*fcf3ce44SJohn Forte 		return (0);
402*fcf3ce44SJohn Forte 	}
403*fcf3ce44SJohn Forte 	return (1);
404*fcf3ce44SJohn Forte }
405*fcf3ce44SJohn Forte 
406*fcf3ce44SJohn Forte /* We take a wild guess for our first get target mappings call */
407*fcf3ce44SJohn Forte #define	MAP_GUESS	50
408*fcf3ce44SJohn Forte 
409*fcf3ce44SJohn Forte HBA_STATUS
fetch_mappings(HBA_HANDLE handle,HBA_WWN pwwn,HBA_FCPTARGETMAPPINGV2 ** map)410*fcf3ce44SJohn Forte fetch_mappings(HBA_HANDLE handle, HBA_WWN pwwn, HBA_FCPTARGETMAPPINGV2 **map) {
411*fcf3ce44SJohn Forte 	int loop = 0;
412*fcf3ce44SJohn Forte 	int count = 0;
413*fcf3ce44SJohn Forte 	HBA_STATUS status = HBA_STATUS_ERROR_TRY_AGAIN; /* force first pass */
414*fcf3ce44SJohn Forte 	*map = (HBA_FCPTARGETMAPPINGV2 *) calloc(1,
415*fcf3ce44SJohn Forte 		(sizeof (HBA_FCPSCSIENTRYV2)* (MAP_GUESS-1)) +
416*fcf3ce44SJohn Forte 		sizeof (HBA_FCPTARGETMAPPINGV2));
417*fcf3ce44SJohn Forte 
418*fcf3ce44SJohn Forte 	/* Loop as long as we have a retryable error */
419*fcf3ce44SJohn Forte 	while ((status == HBA_STATUS_ERROR_TRY_AGAIN ||
420*fcf3ce44SJohn Forte 		status == HBA_STATUS_ERROR_BUSY ||
421*fcf3ce44SJohn Forte 		status == HBA_STATUS_ERROR_MORE_DATA) && loop++ < MAX_RETRIES) {
422*fcf3ce44SJohn Forte 	    status = HBA_GetFcpTargetMappingV2(handle, pwwn, *map);
423*fcf3ce44SJohn Forte 	    if (status == HBA_STATUS_OK) {
424*fcf3ce44SJohn Forte 		break;
425*fcf3ce44SJohn Forte 	    } else if (status == HBA_STATUS_ERROR_MORE_DATA) {
426*fcf3ce44SJohn Forte 		count = (*map)->NumberOfEntries;
427*fcf3ce44SJohn Forte 		free(*map);
428*fcf3ce44SJohn Forte 		*map = (HBA_FCPTARGETMAPPINGV2 *) calloc(1,
429*fcf3ce44SJohn Forte 		    (sizeof (HBA_FCPSCSIENTRYV2)* (count-1)) +
430*fcf3ce44SJohn Forte 		    sizeof (HBA_FCPTARGETMAPPINGV2));
431*fcf3ce44SJohn Forte 		(*map)->NumberOfEntries = count;
432*fcf3ce44SJohn Forte 		continue;
433*fcf3ce44SJohn Forte 	    }
434*fcf3ce44SJohn Forte 	    sleep(1);
435*fcf3ce44SJohn Forte 	}
436*fcf3ce44SJohn Forte 	if (status != HBA_STATUS_OK) {
437*fcf3ce44SJohn Forte 	    /* We encountered a non-retryable error */
438*fcf3ce44SJohn Forte 	    fprintf(stderr, MSGSTR(2502,
439*fcf3ce44SJohn Forte 		    "\nERROR: Unable to retrieve SCSI device paths "
440*fcf3ce44SJohn Forte 		    "(HBA Port WWN %016llx)"),
441*fcf3ce44SJohn Forte 		    wwnConversion(pwwn.wwn));
442*fcf3ce44SJohn Forte 	    printStatus(status);
443*fcf3ce44SJohn Forte 	    fprintf(stderr, "\n");
444*fcf3ce44SJohn Forte 	}
445*fcf3ce44SJohn Forte 	return (status);
446*fcf3ce44SJohn Forte }
447*fcf3ce44SJohn Forte 
448*fcf3ce44SJohn Forte /*
449*fcf3ce44SJohn Forte  * Returns the index of the first match, or -1 if no match
450*fcf3ce44SJohn Forte  */
451*fcf3ce44SJohn Forte int
match_mappings(char * compare,HBA_FCPTARGETMAPPINGV2 * map)452*fcf3ce44SJohn Forte match_mappings(char *compare, HBA_FCPTARGETMAPPINGV2 *map) {
453*fcf3ce44SJohn Forte 	int		mapIndex;
454*fcf3ce44SJohn Forte 	char	*physical = NULL;
455*fcf3ce44SJohn Forte 	char	*tmp;
456*fcf3ce44SJohn Forte 	int		wwnCompare = 0;
457*fcf3ce44SJohn Forte 	uint64_t	wwn;
458*fcf3ce44SJohn Forte 
459*fcf3ce44SJohn Forte 	if (map == NULL || compare == NULL) {
460*fcf3ce44SJohn Forte 	    return (-1);
461*fcf3ce44SJohn Forte 	}
462*fcf3ce44SJohn Forte 
463*fcf3ce44SJohn Forte 	if (is_wwn(compare)) {
464*fcf3ce44SJohn Forte 	    wwnCompare = 1;
465*fcf3ce44SJohn Forte 	    (void) sscanf(compare, "%016llx", &wwn);
466*fcf3ce44SJohn Forte 	} else {
467*fcf3ce44SJohn Forte 	    /* Convert the paths to phsyical paths */
468*fcf3ce44SJohn Forte 	    physical = get_slash_devices_from_osDevName(compare,
469*fcf3ce44SJohn Forte 			STANDARD_DEVNAME_HANDLING);
470*fcf3ce44SJohn Forte 	}
471*fcf3ce44SJohn Forte 
472*fcf3ce44SJohn Forte 	for (mapIndex = 0; mapIndex < map->NumberOfEntries; mapIndex ++) {
473*fcf3ce44SJohn Forte 	    if (wwnCompare) {
474*fcf3ce44SJohn Forte 		if (wwn == wwnConversion(
475*fcf3ce44SJohn Forte 			map->entry[mapIndex].FcpId.NodeWWN.wwn) ||
476*fcf3ce44SJohn Forte 			wwn == wwnConversion(
477*fcf3ce44SJohn Forte 			map->entry[mapIndex].FcpId.PortWWN.wwn)) {
478*fcf3ce44SJohn Forte 		    return (mapIndex);
479*fcf3ce44SJohn Forte 		}
480*fcf3ce44SJohn Forte 	    } else {
481*fcf3ce44SJohn Forte 		if (physical != NULL) {
482*fcf3ce44SJohn Forte 		    tmp = get_slash_devices_from_osDevName(
483*fcf3ce44SJohn Forte 			map->entry[mapIndex].ScsiId.OSDeviceName,
484*fcf3ce44SJohn Forte 			STANDARD_DEVNAME_HANDLING);
485*fcf3ce44SJohn Forte 		    if ((tmp != NULL) &&
486*fcf3ce44SJohn Forte 			strncmp(physical, tmp, MAXPATHLEN) == 0) {
487*fcf3ce44SJohn Forte 			free(physical);
488*fcf3ce44SJohn Forte 			return (mapIndex);
489*fcf3ce44SJohn Forte 		    }
490*fcf3ce44SJohn Forte 		}
491*fcf3ce44SJohn Forte 	    }
492*fcf3ce44SJohn Forte 	}
493*fcf3ce44SJohn Forte 	if (physical) {
494*fcf3ce44SJohn Forte 	    free(physical);
495*fcf3ce44SJohn Forte 	}
496*fcf3ce44SJohn Forte 	return (-1);
497*fcf3ce44SJohn Forte }
498*fcf3ce44SJohn Forte 
499*fcf3ce44SJohn Forte 
500*fcf3ce44SJohn Forte /*
501*fcf3ce44SJohn Forte  * returns non-zero on failure (aka HBA_STATUS_ERROR_*
502*fcf3ce44SJohn Forte  */
503*fcf3ce44SJohn Forte int
loadLibrary()504*fcf3ce44SJohn Forte loadLibrary() {
505*fcf3ce44SJohn Forte 	int status = HBA_LoadLibrary();
506*fcf3ce44SJohn Forte 	if (status != HBA_STATUS_OK) {
507*fcf3ce44SJohn Forte 		fprintf(stderr, MSGSTR(2505,
508*fcf3ce44SJohn Forte 			"ERROR: Unable to load HBA API library: "));
509*fcf3ce44SJohn Forte 		printStatus(status);
510*fcf3ce44SJohn Forte 		fprintf(stderr, "\n");
511*fcf3ce44SJohn Forte 	}
512*fcf3ce44SJohn Forte 	return (status);
513*fcf3ce44SJohn Forte }
514*fcf3ce44SJohn Forte 
515*fcf3ce44SJohn Forte int
fchba_non_encl_probe()516*fcf3ce44SJohn Forte fchba_non_encl_probe() {
517*fcf3ce44SJohn Forte 	HBA_HANDLE handle;
518*fcf3ce44SJohn Forte 	HBA_ADAPTERATTRIBUTES hbaAttrs;
519*fcf3ce44SJohn Forte 	HBA_PORTATTRIBUTES portAttrs;
520*fcf3ce44SJohn Forte 	HBA_FCPTARGETMAPPINGV2    *map;
521*fcf3ce44SJohn Forte 	HBA_STATUS status;
522*fcf3ce44SJohn Forte 	int count, adapterIndex, portIndex, mapIndex;
523*fcf3ce44SJohn Forte 	char name[256];
524*fcf3ce44SJohn Forte 	struct path_entry *head = NULL;
525*fcf3ce44SJohn Forte 	uint64_t	lun = 0;
526*fcf3ce44SJohn Forte 	L_inquiry	inq;
527*fcf3ce44SJohn Forte 	struct scsi_extended_sense sense;
528*fcf3ce44SJohn Forte 	HBA_UINT8	scsiStatus;
529*fcf3ce44SJohn Forte 	uint32_t	inquirySize = sizeof (inq), senseSize = sizeof (sense);
530*fcf3ce44SJohn Forte 
531*fcf3ce44SJohn Forte 	if (loadLibrary()) {
532*fcf3ce44SJohn Forte 	    return (-1);
533*fcf3ce44SJohn Forte 	}
534*fcf3ce44SJohn Forte 
535*fcf3ce44SJohn Forte 	count = getNumberOfAdapters();
536*fcf3ce44SJohn Forte 
537*fcf3ce44SJohn Forte 	/* Loop over all HBAs */
538*fcf3ce44SJohn Forte 	for (adapterIndex = 0; adapterIndex < count; adapterIndex ++) {
539*fcf3ce44SJohn Forte 	    if (skip_hba(adapterIndex)) {
540*fcf3ce44SJohn Forte 		continue;
541*fcf3ce44SJohn Forte 	    }
542*fcf3ce44SJohn Forte 	    status = HBA_GetAdapterName(adapterIndex, (char *)&name);
543*fcf3ce44SJohn Forte 	    if (status != HBA_STATUS_OK) {
544*fcf3ce44SJohn Forte 		/* May have been DR'd */
545*fcf3ce44SJohn Forte 		continue;
546*fcf3ce44SJohn Forte 	    }
547*fcf3ce44SJohn Forte 	    handle = HBA_OpenAdapter(name);
548*fcf3ce44SJohn Forte 	    if (handle == 0) {
549*fcf3ce44SJohn Forte 		/* May have been DR'd */
550*fcf3ce44SJohn Forte 		continue;
551*fcf3ce44SJohn Forte 	    }
552*fcf3ce44SJohn Forte 
553*fcf3ce44SJohn Forte 	    if (getAdapterAttrs(handle, name, &hbaAttrs)) {
554*fcf3ce44SJohn Forte 		/* Should not happen, just skip it */
555*fcf3ce44SJohn Forte 		HBA_CloseAdapter(handle);
556*fcf3ce44SJohn Forte 		continue;
557*fcf3ce44SJohn Forte 	    }
558*fcf3ce44SJohn Forte 
559*fcf3ce44SJohn Forte 
560*fcf3ce44SJohn Forte 	    /* Loop over all HBA Ports */
561*fcf3ce44SJohn Forte 	    for (portIndex = 0; portIndex < hbaAttrs.NumberOfPorts;
562*fcf3ce44SJohn Forte 		    portIndex++) {
563*fcf3ce44SJohn Forte 		if (getAdapterPortAttrs(handle, name, portIndex,
564*fcf3ce44SJohn Forte 			&portAttrs)) {
565*fcf3ce44SJohn Forte 		    continue;
566*fcf3ce44SJohn Forte 		}
567*fcf3ce44SJohn Forte 
568*fcf3ce44SJohn Forte 		if (fetch_mappings(handle, portAttrs.PortWWN, &map)) {
569*fcf3ce44SJohn Forte 		    continue;
570*fcf3ce44SJohn Forte 		}
571*fcf3ce44SJohn Forte 
572*fcf3ce44SJohn Forte 		/* Loop over all target Mapping entries */
573*fcf3ce44SJohn Forte 		for (mapIndex = 0; mapIndex < map->NumberOfEntries;
574*fcf3ce44SJohn Forte 		    mapIndex ++) {
575*fcf3ce44SJohn Forte 			struct path_entry *tmpPath = NULL;
576*fcf3ce44SJohn Forte 			int doInquiry = 0;
577*fcf3ce44SJohn Forte 			if (!head) {
578*fcf3ce44SJohn Forte 			head = (struct path_entry *)calloc(1,
579*fcf3ce44SJohn Forte 				sizeof (struct path_entry));
580*fcf3ce44SJohn Forte 			tmpPath = head;
581*fcf3ce44SJohn Forte 			strncpy(head->path,
582*fcf3ce44SJohn Forte 			    map->entry[mapIndex].ScsiId.OSDeviceName,
583*fcf3ce44SJohn Forte 			    sizeof (map->entry[mapIndex].ScsiId.OSDeviceName));
584*fcf3ce44SJohn Forte 			(void) memcpy(tmpPath->wwn,
585*fcf3ce44SJohn Forte 			    map->entry[mapIndex].FcpId.NodeWWN.wwn,
586*fcf3ce44SJohn Forte 			    sizeof (HBA_UINT8) * 8);
587*fcf3ce44SJohn Forte 			doInquiry = 1;
588*fcf3ce44SJohn Forte 			} else if (tmpPath = is_duplicate_path(head,
589*fcf3ce44SJohn Forte 				map->entry[mapIndex].ScsiId.OSDeviceName)) {
590*fcf3ce44SJohn Forte 				if (tmpPath->dtype != 0x1f) {
591*fcf3ce44SJohn Forte 					doInquiry = 0;
592*fcf3ce44SJohn Forte 				} else {
593*fcf3ce44SJohn Forte 					doInquiry = 1;
594*fcf3ce44SJohn Forte 				}
595*fcf3ce44SJohn Forte 			} else {
596*fcf3ce44SJohn Forte 			tmpPath = (struct path_entry *)
597*fcf3ce44SJohn Forte 				calloc(1, sizeof (struct path_entry));
598*fcf3ce44SJohn Forte 			strncpy(tmpPath->path,
599*fcf3ce44SJohn Forte 			    map->entry[mapIndex].ScsiId.OSDeviceName,
600*fcf3ce44SJohn Forte 			    sizeof (map->entry[mapIndex].ScsiId.OSDeviceName));
601*fcf3ce44SJohn Forte 			(void) memcpy(tmpPath->wwn,
602*fcf3ce44SJohn Forte 			    map->entry[mapIndex].FcpId.NodeWWN.wwn,
603*fcf3ce44SJohn Forte 			    sizeof (HBA_UINT8) * 8);
604*fcf3ce44SJohn Forte 			add_path(head, tmpPath);
605*fcf3ce44SJohn Forte 			doInquiry = 1;
606*fcf3ce44SJohn Forte 			}
607*fcf3ce44SJohn Forte 
608*fcf3ce44SJohn Forte 			if (doInquiry) {
609*fcf3ce44SJohn Forte 				lun = map->entry[mapIndex].FcpId.FcpLun;
610*fcf3ce44SJohn Forte 				memset(&inq, 0, sizeof (inq));
611*fcf3ce44SJohn Forte 				memset(&sense, 0, sizeof (sense));
612*fcf3ce44SJohn Forte 				status = HBA_ScsiInquiryV2(handle,
613*fcf3ce44SJohn Forte 				    portAttrs.PortWWN,
614*fcf3ce44SJohn Forte 				    map->entry[mapIndex].FcpId.PortWWN,
615*fcf3ce44SJohn Forte 				    lun, 0, 0,
616*fcf3ce44SJohn Forte 				    &inq, &inquirySize,
617*fcf3ce44SJohn Forte 				    &scsiStatus,
618*fcf3ce44SJohn Forte 				    &sense, &senseSize);
619*fcf3ce44SJohn Forte 				if (status != HBA_STATUS_OK) {
620*fcf3ce44SJohn Forte 					inq.inq_dtype = 0x1f;
621*fcf3ce44SJohn Forte 				}
622*fcf3ce44SJohn Forte 				tmpPath->dtype = inq.inq_dtype;
623*fcf3ce44SJohn Forte 			}
624*fcf3ce44SJohn Forte 		}
625*fcf3ce44SJohn Forte 	}
626*fcf3ce44SJohn Forte 	}
627*fcf3ce44SJohn Forte 	if (head) {
628*fcf3ce44SJohn Forte 		struct path_entry *tmp;
629*fcf3ce44SJohn Forte 		printf(MSGSTR(2098, "\nFound Fibre Channel device(s):\n"));
630*fcf3ce44SJohn Forte 		for (tmp = head; tmp != NULL; tmp = tmp->next) {
631*fcf3ce44SJohn Forte 			printf("  ");
632*fcf3ce44SJohn Forte 			printf(MSGSTR(90, "Node WWN:"));
633*fcf3ce44SJohn Forte 			printf("%016llx  ", wwnConversion(tmp->wwn));
634*fcf3ce44SJohn Forte 			fprintf(stdout, MSGSTR(35, "Device Type:"));
635*fcf3ce44SJohn Forte 			(void) fflush(stdout);
636*fcf3ce44SJohn Forte 
637*fcf3ce44SJohn Forte 			if ((tmp->dtype & DTYPE_MASK) < 0x10) {
638*fcf3ce44SJohn Forte 				fprintf(stdout, "%s",
639*fcf3ce44SJohn Forte 				    dtype[tmp->dtype & DTYPE_MASK]);
640*fcf3ce44SJohn Forte 			} else if ((tmp->dtype & DTYPE_MASK) < 0x1f) {
641*fcf3ce44SJohn Forte 				fprintf(stdout, MSGSTR(2406,
642*fcf3ce44SJohn Forte 				    "Reserved"));
643*fcf3ce44SJohn Forte 			} else {
644*fcf3ce44SJohn Forte 				fprintf(stdout, MSGSTR(2407,
645*fcf3ce44SJohn Forte 				    "Unknown"));
646*fcf3ce44SJohn Forte 			}
647*fcf3ce44SJohn Forte 
648*fcf3ce44SJohn Forte 			printf("\n    ");
649*fcf3ce44SJohn Forte 			printf(MSGSTR(31, "Logical Path:%s"), tmp->path);
650*fcf3ce44SJohn Forte 			printf("\n");
651*fcf3ce44SJohn Forte 
652*fcf3ce44SJohn Forte 		/* We probably shouldn't be using a g_fc interface here */
653*fcf3ce44SJohn Forte 			if (Options & OPTION_P) {
654*fcf3ce44SJohn Forte 				char *phys_path =
655*fcf3ce44SJohn Forte 				get_slash_devices_from_osDevName(
656*fcf3ce44SJohn Forte 				    tmp->path,
657*fcf3ce44SJohn Forte 				    STANDARD_DEVNAME_HANDLING);
658*fcf3ce44SJohn Forte 				if (phys_path != NULL) {
659*fcf3ce44SJohn Forte 				fprintf(stdout, "    ");
660*fcf3ce44SJohn Forte 				fprintf(stdout, MSGSTR(5, "Physical Path:"));
661*fcf3ce44SJohn Forte 				fprintf(stdout, "\n     %s\n", phys_path);
662*fcf3ce44SJohn Forte 				free(phys_path);
663*fcf3ce44SJohn Forte 				}
664*fcf3ce44SJohn Forte 			}
665*fcf3ce44SJohn Forte 		}
666*fcf3ce44SJohn Forte 		free_path_list(head);
667*fcf3ce44SJohn Forte 	}
668*fcf3ce44SJohn Forte 	HBA_FreeLibrary();
669*fcf3ce44SJohn Forte 	return (0);
670*fcf3ce44SJohn Forte }
671*fcf3ce44SJohn Forte 
672*fcf3ce44SJohn Forte 
673*fcf3ce44SJohn Forte int
fchba_inquiry(char ** argv)674*fcf3ce44SJohn Forte fchba_inquiry(char **argv)
675*fcf3ce44SJohn Forte {
676*fcf3ce44SJohn Forte 	int		path_index = 0, found = 0;
677*fcf3ce44SJohn Forte 	uint64_t	wwn;
678*fcf3ce44SJohn Forte 	uint64_t	lun = 0;
679*fcf3ce44SJohn Forte 	HBA_HANDLE handle;
680*fcf3ce44SJohn Forte 	HBA_ADAPTERATTRIBUTES hbaAttrs;
681*fcf3ce44SJohn Forte 	HBA_PORTATTRIBUTES portAttrs;
682*fcf3ce44SJohn Forte 	HBA_FCPTARGETMAPPINGV2    *map;
683*fcf3ce44SJohn Forte 	HBA_STATUS status;
684*fcf3ce44SJohn Forte 	int count, adapterIndex, portIndex, mapIndex;
685*fcf3ce44SJohn Forte 	char name[256];
686*fcf3ce44SJohn Forte 	L_inquiry	inq;
687*fcf3ce44SJohn Forte 	struct page80	serial;
688*fcf3ce44SJohn Forte 	uint32_t	serialSize = sizeof (serial);
689*fcf3ce44SJohn Forte 	struct scsi_extended_sense sense;
690*fcf3ce44SJohn Forte 	HBA_UINT8	scsiStatus;
691*fcf3ce44SJohn Forte 	uint32_t	inquirySize = sizeof (inq), senseSize = sizeof (sense);
692*fcf3ce44SJohn Forte 	boolean_t	goodPath = B_FALSE;
693*fcf3ce44SJohn Forte 	int		matched = 0, wwnCompare = 0;
694*fcf3ce44SJohn Forte 	char		*tmp, *physical = NULL;
695*fcf3ce44SJohn Forte 	int		ret = 0;
696*fcf3ce44SJohn Forte 
697*fcf3ce44SJohn Forte 	if (loadLibrary()) {
698*fcf3ce44SJohn Forte 	    return (-1);
699*fcf3ce44SJohn Forte 	}
700*fcf3ce44SJohn Forte 	for (path_index = 0; argv[path_index] != NULL; path_index++) {
701*fcf3ce44SJohn Forte 	    goodPath = B_FALSE;
702*fcf3ce44SJohn Forte 	    found = 0;
703*fcf3ce44SJohn Forte 
704*fcf3ce44SJohn Forte 	    if (is_wwn(argv[path_index])) {
705*fcf3ce44SJohn Forte 		(void) sscanf(argv[path_index], "%016llx", &wwn);
706*fcf3ce44SJohn Forte 		wwnCompare = 1;
707*fcf3ce44SJohn Forte 	    } else if (!is_path(argv[path_index])) {
708*fcf3ce44SJohn Forte 		fprintf(stderr, MSGSTR(112, "Error: Invalid pathname (%s)"),
709*fcf3ce44SJohn Forte 			argv[path_index]);
710*fcf3ce44SJohn Forte 		fprintf(stderr, "\n");
711*fcf3ce44SJohn Forte 		ret = -1;
712*fcf3ce44SJohn Forte 		continue;
713*fcf3ce44SJohn Forte 	    }
714*fcf3ce44SJohn Forte 	    if (!wwnCompare) {
715*fcf3ce44SJohn Forte 		/* Convert the paths to phsyical paths */
716*fcf3ce44SJohn Forte 		physical = get_slash_devices_from_osDevName(argv[path_index],
717*fcf3ce44SJohn Forte 			STANDARD_DEVNAME_HANDLING);
718*fcf3ce44SJohn Forte 		if (!physical) {
719*fcf3ce44SJohn Forte 		    fprintf(stderr, MSGSTR(112,
720*fcf3ce44SJohn Forte 			"Error: Invalid pathname (%s)"),
721*fcf3ce44SJohn Forte 			argv[path_index]);
722*fcf3ce44SJohn Forte 		    fprintf(stderr, "\n");
723*fcf3ce44SJohn Forte 		    ret = -1;
724*fcf3ce44SJohn Forte 		    continue;
725*fcf3ce44SJohn Forte 		}
726*fcf3ce44SJohn Forte 	    }
727*fcf3ce44SJohn Forte 
728*fcf3ce44SJohn Forte 	    count = getNumberOfAdapters();
729*fcf3ce44SJohn Forte 
730*fcf3ce44SJohn Forte 	    /* Loop over all HBAs */
731*fcf3ce44SJohn Forte 	    for (adapterIndex = 0; adapterIndex < count; adapterIndex ++) {
732*fcf3ce44SJohn Forte 		if (skip_hba(adapterIndex)) {
733*fcf3ce44SJohn Forte 		    continue;
734*fcf3ce44SJohn Forte 		}
735*fcf3ce44SJohn Forte 		status = HBA_GetAdapterName(adapterIndex, (char *)&name);
736*fcf3ce44SJohn Forte 		if (status != HBA_STATUS_OK) {
737*fcf3ce44SJohn Forte 		    /* May have been DR'd */
738*fcf3ce44SJohn Forte 		    continue;
739*fcf3ce44SJohn Forte 		}
740*fcf3ce44SJohn Forte 		handle = HBA_OpenAdapter(name);
741*fcf3ce44SJohn Forte 		if (handle == 0) {
742*fcf3ce44SJohn Forte 		    /* May have been DR'd */
743*fcf3ce44SJohn Forte 		    continue;
744*fcf3ce44SJohn Forte 		}
745*fcf3ce44SJohn Forte 
746*fcf3ce44SJohn Forte 		if (getAdapterAttrs(handle, name, &hbaAttrs)) {
747*fcf3ce44SJohn Forte 		    /* Should never happen */
748*fcf3ce44SJohn Forte 		    HBA_CloseAdapter(handle);
749*fcf3ce44SJohn Forte 		    continue;
750*fcf3ce44SJohn Forte 		}
751*fcf3ce44SJohn Forte 
752*fcf3ce44SJohn Forte 
753*fcf3ce44SJohn Forte 		/* Loop over all HBA Ports */
754*fcf3ce44SJohn Forte 		for (portIndex = 0; portIndex < hbaAttrs.NumberOfPorts;
755*fcf3ce44SJohn Forte 			portIndex++) {
756*fcf3ce44SJohn Forte 		    if (getAdapterPortAttrs(handle, name, portIndex,
757*fcf3ce44SJohn Forte 			    &portAttrs)) {
758*fcf3ce44SJohn Forte 			continue;
759*fcf3ce44SJohn Forte 		    }
760*fcf3ce44SJohn Forte 
761*fcf3ce44SJohn Forte 		    if (fetch_mappings(handle, portAttrs.PortWWN, &map)) {
762*fcf3ce44SJohn Forte 			continue;
763*fcf3ce44SJohn Forte 		    }
764*fcf3ce44SJohn Forte 
765*fcf3ce44SJohn Forte 		    for (mapIndex = 0; mapIndex < map->NumberOfEntries;
766*fcf3ce44SJohn Forte 			    mapIndex ++) {
767*fcf3ce44SJohn Forte 			matched = 0;
768*fcf3ce44SJohn Forte 			if (wwnCompare) {
769*fcf3ce44SJohn Forte 			    if (wwn == wwnConversion(
770*fcf3ce44SJohn Forte 				    map->entry[mapIndex].FcpId.NodeWWN.wwn) ||
771*fcf3ce44SJohn Forte 				    wwn == wwnConversion(
772*fcf3ce44SJohn Forte 				    map->entry[mapIndex].FcpId.PortWWN.wwn)) {
773*fcf3ce44SJohn Forte 				lun = map->entry[mapIndex].FcpId.FcpLun;
774*fcf3ce44SJohn Forte 				matched = 1;
775*fcf3ce44SJohn Forte 			    }
776*fcf3ce44SJohn Forte 			} else {
777*fcf3ce44SJohn Forte 			    tmp = get_slash_devices_from_osDevName(
778*fcf3ce44SJohn Forte 				    map->entry[mapIndex].ScsiId.OSDeviceName,
779*fcf3ce44SJohn Forte 				    STANDARD_DEVNAME_HANDLING);
780*fcf3ce44SJohn Forte 			    if ((tmp != NULL) && (strncmp(physical, tmp,
781*fcf3ce44SJohn Forte 				    MAXPATHLEN) == 0)) {
782*fcf3ce44SJohn Forte 				lun = map->entry[mapIndex].FcpId.FcpLun;
783*fcf3ce44SJohn Forte 				matched = 1;
784*fcf3ce44SJohn Forte 				free(tmp);
785*fcf3ce44SJohn Forte 			    }
786*fcf3ce44SJohn Forte 			}
787*fcf3ce44SJohn Forte 
788*fcf3ce44SJohn Forte 			if (matched) {
789*fcf3ce44SJohn Forte 			    memset(&inq, 0, sizeof (inq));
790*fcf3ce44SJohn Forte 			    memset(&sense, 0, sizeof (sense));
791*fcf3ce44SJohn Forte 			    status = HBA_ScsiInquiryV2(handle,
792*fcf3ce44SJohn Forte 				portAttrs.PortWWN,
793*fcf3ce44SJohn Forte 				map->entry[mapIndex].FcpId.PortWWN,
794*fcf3ce44SJohn Forte 				lun, 0, 0,
795*fcf3ce44SJohn Forte 				&inq, &inquirySize,
796*fcf3ce44SJohn Forte 				&scsiStatus,
797*fcf3ce44SJohn Forte 				&sense, &senseSize);
798*fcf3ce44SJohn Forte 			    if (status == HBA_STATUS_OK) {
799*fcf3ce44SJohn Forte 				goodPath = B_TRUE;
800*fcf3ce44SJohn Forte 				/*
801*fcf3ce44SJohn Forte 				 * Call the inquiry cmd on page 0x80 only if
802*fcf3ce44SJohn Forte 				 * the vendor supports page 0x80
803*fcf3ce44SJohn Forte 				 */
804*fcf3ce44SJohn Forte 				memset(&serial, 0, sizeof (serial));
805*fcf3ce44SJohn Forte 				if ((find_supported_inq_page(handle,
806*fcf3ce44SJohn Forte 					    portAttrs.PortWWN,
807*fcf3ce44SJohn Forte 					    map->entry[mapIndex].FcpId.PortWWN,
808*fcf3ce44SJohn Forte 					    lun, 0x80))) {
809*fcf3ce44SJohn Forte 					status = HBA_ScsiInquiryV2(handle,
810*fcf3ce44SJohn Forte 					    portAttrs.PortWWN,
811*fcf3ce44SJohn Forte 					    map->entry[mapIndex].FcpId.PortWWN,
812*fcf3ce44SJohn Forte 					    lun, 1, 0x80,
813*fcf3ce44SJohn Forte 					    &serial, &serialSize,
814*fcf3ce44SJohn Forte 					    &scsiStatus,
815*fcf3ce44SJohn Forte 					    &sense, &senseSize);
816*fcf3ce44SJohn Forte 					if (status != HBA_STATUS_OK) {
817*fcf3ce44SJohn Forte 						strncpy(
818*fcf3ce44SJohn Forte 						    (char *)serial.inq_serial,
819*fcf3ce44SJohn Forte 						    "Unavailable",
820*fcf3ce44SJohn Forte 						    sizeof (serial.inq_serial));
821*fcf3ce44SJohn Forte 					}
822*fcf3ce44SJohn Forte 				} else {
823*fcf3ce44SJohn Forte 					strncpy((char *)serial.inq_serial,
824*fcf3ce44SJohn Forte 					    "Unsupported",
825*fcf3ce44SJohn Forte 					    sizeof (serial.inq_serial));
826*fcf3ce44SJohn Forte 				}
827*fcf3ce44SJohn Forte 				/*
828*fcf3ce44SJohn Forte 				 * we are adding serial number information
829*fcf3ce44SJohn Forte 				 * from 0x80.  If length is less than 39,
830*fcf3ce44SJohn Forte 				 * then we want to increase length to 52 to
831*fcf3ce44SJohn Forte 				 * reflect the fact that we have serial number
832*fcf3ce44SJohn Forte 				 * information
833*fcf3ce44SJohn Forte 				 */
834*fcf3ce44SJohn Forte 				if (inq.inq_len < 39) {
835*fcf3ce44SJohn Forte 					inq.inq_len = 52;
836*fcf3ce44SJohn Forte 				}
837*fcf3ce44SJohn Forte 				print_inq_data(argv[path_index],
838*fcf3ce44SJohn Forte 				    map->entry[mapIndex].ScsiId.OSDeviceName,
839*fcf3ce44SJohn Forte 				    inq, serial.inq_serial,
840*fcf3ce44SJohn Forte 				    sizeof (serial.inq_serial));
841*fcf3ce44SJohn Forte 				if (! wwnCompare) {
842*fcf3ce44SJohn Forte 					found = 1;
843*fcf3ce44SJohn Forte 					break;
844*fcf3ce44SJohn Forte 				}
845*fcf3ce44SJohn Forte 			    } else {
846*fcf3ce44SJohn Forte 				fprintf(stderr, MSGSTR(2430,
847*fcf3ce44SJohn Forte 				"Error: I/O failure communicating with %s  "),
848*fcf3ce44SJohn Forte 				map->entry[mapIndex].ScsiId.OSDeviceName);
849*fcf3ce44SJohn Forte 				printStatus(status);
850*fcf3ce44SJohn Forte 				fprintf(stderr, "\n");
851*fcf3ce44SJohn Forte 			    }
852*fcf3ce44SJohn Forte 			}
853*fcf3ce44SJohn Forte 		    }
854*fcf3ce44SJohn Forte 		    if (found == 1) {
855*fcf3ce44SJohn Forte 			    break;
856*fcf3ce44SJohn Forte 		    }
857*fcf3ce44SJohn Forte 		}
858*fcf3ce44SJohn Forte 		if (found == 1) {
859*fcf3ce44SJohn Forte 			break;
860*fcf3ce44SJohn Forte 		}
861*fcf3ce44SJohn Forte 	    }
862*fcf3ce44SJohn Forte 
863*fcf3ce44SJohn Forte 	    if (physical) {
864*fcf3ce44SJohn Forte 		free(physical);
865*fcf3ce44SJohn Forte 	    }
866*fcf3ce44SJohn Forte 
867*fcf3ce44SJohn Forte 	    if (!goodPath) {
868*fcf3ce44SJohn Forte 		fprintf(stderr, MSGSTR(112, "Error: Invalid pathname (%s)"),
869*fcf3ce44SJohn Forte 			argv[path_index]);
870*fcf3ce44SJohn Forte 		fprintf(stderr, "\n");
871*fcf3ce44SJohn Forte 		ret = -1;
872*fcf3ce44SJohn Forte 	    }
873*fcf3ce44SJohn Forte 	}
874*fcf3ce44SJohn Forte 	return (ret);
875*fcf3ce44SJohn Forte }
876*fcf3ce44SJohn Forte 
877*fcf3ce44SJohn Forte 
878*fcf3ce44SJohn Forte 
879*fcf3ce44SJohn Forte int
fchba_dump_map(char ** argv)880*fcf3ce44SJohn Forte fchba_dump_map(char **argv)
881*fcf3ce44SJohn Forte {
882*fcf3ce44SJohn Forte 	int		path_index = 0;
883*fcf3ce44SJohn Forte 	uint64_t	wwn;
884*fcf3ce44SJohn Forte 	uint64_t	lun = 0;
885*fcf3ce44SJohn Forte 	HBA_HANDLE handle;
886*fcf3ce44SJohn Forte 	HBA_ADAPTERATTRIBUTES hbaAttrs;
887*fcf3ce44SJohn Forte 	HBA_PORTATTRIBUTES portAttrs;
888*fcf3ce44SJohn Forte 	HBA_PORTATTRIBUTES discPortAttrs;
889*fcf3ce44SJohn Forte 	HBA_FCPTARGETMAPPINGV2    *map;
890*fcf3ce44SJohn Forte 	HBA_STATUS status;
891*fcf3ce44SJohn Forte 	int count, adapterIndex, portIndex, mapIndex, discIndex;
892*fcf3ce44SJohn Forte 	char name[256], *physical, *comp_phys;
893*fcf3ce44SJohn Forte 	L_inquiry	inq;
894*fcf3ce44SJohn Forte 	struct scsi_extended_sense sense;
895*fcf3ce44SJohn Forte 	HBA_UINT8	scsiStatus;
896*fcf3ce44SJohn Forte 	int		matched;
897*fcf3ce44SJohn Forte 	int		done;
898*fcf3ce44SJohn Forte 	uint32_t	inquirySize = sizeof (inq), senseSize = sizeof (sense);
899*fcf3ce44SJohn Forte 	boolean_t	goodPath = B_FALSE;
900*fcf3ce44SJohn Forte 	int		ret = 0;
901*fcf3ce44SJohn Forte 	uint32_t	responseSize = DEFAULT_LUN_LENGTH;
902*fcf3ce44SJohn Forte 	uchar_t		raw_luns[DEFAULT_LUN_LENGTH];
903*fcf3ce44SJohn Forte 	struct rep_luns_rsp	*lun_resp;
904*fcf3ce44SJohn Forte 
905*fcf3ce44SJohn Forte 
906*fcf3ce44SJohn Forte 	if (loadLibrary()) {
907*fcf3ce44SJohn Forte 	    return (-1);
908*fcf3ce44SJohn Forte 	}
909*fcf3ce44SJohn Forte 	for (path_index = 0; argv[path_index] != NULL; path_index++) {
910*fcf3ce44SJohn Forte 	    goodPath = B_FALSE;
911*fcf3ce44SJohn Forte 
912*fcf3ce44SJohn Forte 	    if (is_wwn(argv[path_index])) {
913*fcf3ce44SJohn Forte 		(void) sscanf(argv[path_index], "%016llx", &wwn);
914*fcf3ce44SJohn Forte 	    } else if (!is_path(argv[path_index])) {
915*fcf3ce44SJohn Forte 		fprintf(stderr, MSGSTR(112, "Error: Invalid pathname (%s)"),
916*fcf3ce44SJohn Forte 			argv[path_index]);
917*fcf3ce44SJohn Forte 		fprintf(stderr, "\n");
918*fcf3ce44SJohn Forte 		ret = -1;
919*fcf3ce44SJohn Forte 		continue;
920*fcf3ce44SJohn Forte 	    }
921*fcf3ce44SJohn Forte 
922*fcf3ce44SJohn Forte 	    count = getNumberOfAdapters();
923*fcf3ce44SJohn Forte 
924*fcf3ce44SJohn Forte 	    done = 0;
925*fcf3ce44SJohn Forte 	    /* Loop over all HBAs */
926*fcf3ce44SJohn Forte 	    for (adapterIndex = 0; adapterIndex < count && !done;
927*fcf3ce44SJohn Forte 		    adapterIndex ++) {
928*fcf3ce44SJohn Forte 		if (skip_hba(adapterIndex)) {
929*fcf3ce44SJohn Forte 		    continue;
930*fcf3ce44SJohn Forte 		}
931*fcf3ce44SJohn Forte 		status = HBA_GetAdapterName(adapterIndex, (char *)&name);
932*fcf3ce44SJohn Forte 		if (status != HBA_STATUS_OK) {
933*fcf3ce44SJohn Forte 		    /* May have been DR'd */
934*fcf3ce44SJohn Forte 		    continue;
935*fcf3ce44SJohn Forte 		}
936*fcf3ce44SJohn Forte 		handle = HBA_OpenAdapter(name);
937*fcf3ce44SJohn Forte 		if (handle == 0) {
938*fcf3ce44SJohn Forte 		    /* May have been DR'd */
939*fcf3ce44SJohn Forte 		    continue;
940*fcf3ce44SJohn Forte 		}
941*fcf3ce44SJohn Forte 
942*fcf3ce44SJohn Forte 		if (getAdapterAttrs(handle, name, &hbaAttrs)) {
943*fcf3ce44SJohn Forte 		    /* Should never happen */
944*fcf3ce44SJohn Forte 		    HBA_CloseAdapter(handle);
945*fcf3ce44SJohn Forte 		    continue;
946*fcf3ce44SJohn Forte 		}
947*fcf3ce44SJohn Forte 
948*fcf3ce44SJohn Forte 
949*fcf3ce44SJohn Forte 		/* Loop over all HBA Ports */
950*fcf3ce44SJohn Forte 		for (portIndex = 0; portIndex < hbaAttrs.NumberOfPorts && !done;
951*fcf3ce44SJohn Forte 			portIndex++) {
952*fcf3ce44SJohn Forte 		    if (getAdapterPortAttrs(handle, name, portIndex,
953*fcf3ce44SJohn Forte 			    &portAttrs)) {
954*fcf3ce44SJohn Forte 			continue;
955*fcf3ce44SJohn Forte 		    }
956*fcf3ce44SJohn Forte 
957*fcf3ce44SJohn Forte 
958*fcf3ce44SJohn Forte 		    matched = 0;
959*fcf3ce44SJohn Forte 		    if (is_wwn(argv[path_index])) {
960*fcf3ce44SJohn Forte 			if (wwn == wwnConversion(
961*fcf3ce44SJohn Forte 				portAttrs.NodeWWN.wwn) ||
962*fcf3ce44SJohn Forte 				wwn == wwnConversion(
963*fcf3ce44SJohn Forte 				portAttrs.PortWWN.wwn)) {
964*fcf3ce44SJohn Forte 			    matched = 1;
965*fcf3ce44SJohn Forte 			}
966*fcf3ce44SJohn Forte 		    } else {
967*fcf3ce44SJohn Forte 			if (is_path(argv[path_index]) &&
968*fcf3ce44SJohn Forte 			    ((physical = get_slash_devices_from_osDevName(
969*fcf3ce44SJohn Forte 				argv[path_index],
970*fcf3ce44SJohn Forte 				STANDARD_DEVNAME_HANDLING)) != NULL) &&
971*fcf3ce44SJohn Forte 			    ((comp_phys = get_slash_devices_from_osDevName(
972*fcf3ce44SJohn Forte 				portAttrs.OSDeviceName,
973*fcf3ce44SJohn Forte 				STANDARD_DEVNAME_HANDLING)) != NULL)) {
974*fcf3ce44SJohn Forte 			    char *tmp = strstr(physical, ":devctl");
975*fcf3ce44SJohn Forte 			    if (tmp) {
976*fcf3ce44SJohn Forte 				*tmp = '\0';
977*fcf3ce44SJohn Forte 			    } else {
978*fcf3ce44SJohn Forte 				tmp = strstr(physical, ":fc");
979*fcf3ce44SJohn Forte 				if (tmp) {
980*fcf3ce44SJohn Forte 					*tmp = '\0';
981*fcf3ce44SJohn Forte 				}
982*fcf3ce44SJohn Forte 			    }
983*fcf3ce44SJohn Forte 			    if (strstr(comp_phys, physical)) {
984*fcf3ce44SJohn Forte 				matched = 1;
985*fcf3ce44SJohn Forte 			    }
986*fcf3ce44SJohn Forte 			}
987*fcf3ce44SJohn Forte 			if (physical) {
988*fcf3ce44SJohn Forte 			    free(physical);
989*fcf3ce44SJohn Forte 			    physical = NULL;
990*fcf3ce44SJohn Forte 			}
991*fcf3ce44SJohn Forte 			if (comp_phys) {
992*fcf3ce44SJohn Forte 			    free(comp_phys);
993*fcf3ce44SJohn Forte 			    comp_phys = NULL;
994*fcf3ce44SJohn Forte 			}
995*fcf3ce44SJohn Forte 		    }
996*fcf3ce44SJohn Forte 
997*fcf3ce44SJohn Forte 		    if (!fetch_mappings(handle, portAttrs.PortWWN, &map)) {
998*fcf3ce44SJohn Forte 			mapIndex = match_mappings(argv[path_index], map);
999*fcf3ce44SJohn Forte 			if (mapIndex >= 0) {
1000*fcf3ce44SJohn Forte 			    matched = 1;
1001*fcf3ce44SJohn Forte 			}
1002*fcf3ce44SJohn Forte 		    } else {
1003*fcf3ce44SJohn Forte 			continue;
1004*fcf3ce44SJohn Forte 		    }
1005*fcf3ce44SJohn Forte 
1006*fcf3ce44SJohn Forte 		    if (matched) {
1007*fcf3ce44SJohn Forte 			goodPath = B_TRUE;
1008*fcf3ce44SJohn Forte 			printf(MSGSTR(2095,
1009*fcf3ce44SJohn Forte 				"Pos  Port_ID Hard_Addr Port WWN"
1010*fcf3ce44SJohn Forte 				"         Node WWN         Type\n"));
1011*fcf3ce44SJohn Forte 			for (discIndex = 0;
1012*fcf3ce44SJohn Forte 				discIndex < portAttrs.NumberofDiscoveredPorts;
1013*fcf3ce44SJohn Forte 				discIndex++) {
1014*fcf3ce44SJohn Forte 			    if (getDiscPortAttrs(handle, name, portIndex,
1015*fcf3ce44SJohn Forte 				    discIndex, &discPortAttrs)) {
1016*fcf3ce44SJohn Forte 				/* Move on to the next target */
1017*fcf3ce44SJohn Forte 				continue;
1018*fcf3ce44SJohn Forte 			    }
1019*fcf3ce44SJohn Forte 
1020*fcf3ce44SJohn Forte 			    printf("%-4d %-6x  %-6x   %016llx %016llx",
1021*fcf3ce44SJohn Forte 				    discIndex,
1022*fcf3ce44SJohn Forte 				    discPortAttrs.PortFcId, 0,
1023*fcf3ce44SJohn Forte 				    wwnConversion(discPortAttrs.PortWWN.wwn),
1024*fcf3ce44SJohn Forte 				    wwnConversion(discPortAttrs.NodeWWN.wwn));
1025*fcf3ce44SJohn Forte 
1026*fcf3ce44SJohn Forte 				/*
1027*fcf3ce44SJohn Forte 				 * devices are not all required to respond to
1028*fcf3ce44SJohn Forte 				 * Scsi Inquiry calls sent to LUN 0.  We must
1029*fcf3ce44SJohn Forte 				 * fisrt issue a ReportLUN and then send the
1030*fcf3ce44SJohn Forte 				 * SCSI Inquiry call to the first LUN Returned
1031*fcf3ce44SJohn Forte 				 * from the ReportLUN call
1032*fcf3ce44SJohn Forte 				 */
1033*fcf3ce44SJohn Forte 			    memset(&sense, 0, sizeof (sense));
1034*fcf3ce44SJohn Forte 			    status = HBA_ScsiReportLUNsV2(handle,
1035*fcf3ce44SJohn Forte 				portAttrs.PortWWN,
1036*fcf3ce44SJohn Forte 				discPortAttrs.PortWWN,
1037*fcf3ce44SJohn Forte 				(void *)raw_luns, &responseSize, &scsiStatus,
1038*fcf3ce44SJohn Forte 				(void *)&sense, &senseSize);
1039*fcf3ce44SJohn Forte 			    if (status == HBA_STATUS_OK) {
1040*fcf3ce44SJohn Forte 				    lun_resp =
1041*fcf3ce44SJohn Forte 					(struct rep_luns_rsp *)
1042*fcf3ce44SJohn Forte 					(unsigned long)raw_luns;
1043*fcf3ce44SJohn Forte 				    lun = ntohll(
1044*fcf3ce44SJohn Forte 					wwnConversion(lun_resp->lun[0].val));
1045*fcf3ce44SJohn Forte 			    } else {
1046*fcf3ce44SJohn Forte 				/*
1047*fcf3ce44SJohn Forte 				 * in case we are unable to retrieve report
1048*fcf3ce44SJohn Forte 				 * LUN data, we will blindly try sending the
1049*fcf3ce44SJohn Forte 				 * INQUIRY to lun 0.
1050*fcf3ce44SJohn Forte 				 */
1051*fcf3ce44SJohn Forte 				lun = 0;
1052*fcf3ce44SJohn Forte 			    }
1053*fcf3ce44SJohn Forte 			    memset(&sense, 0, sizeof (sense));
1054*fcf3ce44SJohn Forte 			    status = HBA_ScsiInquiryV2(handle,
1055*fcf3ce44SJohn Forte 				    portAttrs.PortWWN,
1056*fcf3ce44SJohn Forte 				    discPortAttrs.PortWWN,
1057*fcf3ce44SJohn Forte 				    lun, 0, 0,
1058*fcf3ce44SJohn Forte 				    &inq, &inquirySize,
1059*fcf3ce44SJohn Forte 				    &scsiStatus,
1060*fcf3ce44SJohn Forte 				    &sense, &senseSize);
1061*fcf3ce44SJohn Forte 			    if (status != HBA_STATUS_OK) {
1062*fcf3ce44SJohn Forte 				inq.inq_dtype = 0x1f;
1063*fcf3ce44SJohn Forte 			    }
1064*fcf3ce44SJohn Forte 			    print_fabric_dtype_prop(portAttrs.PortWWN.wwn,
1065*fcf3ce44SJohn Forte 				map->entry[mapIndex].FcpId.PortWWN.wwn,
1066*fcf3ce44SJohn Forte 				inq.inq_dtype);
1067*fcf3ce44SJohn Forte 			}
1068*fcf3ce44SJohn Forte 			/* Now dump this HBA's stats */
1069*fcf3ce44SJohn Forte 			printf("%-4d %-6x  %-6x   %016llx %016llx",
1070*fcf3ce44SJohn Forte 			    discIndex,
1071*fcf3ce44SJohn Forte 			    portAttrs.PortFcId, 0,
1072*fcf3ce44SJohn Forte 			    wwnConversion(portAttrs.PortWWN.wwn),
1073*fcf3ce44SJohn Forte 			    wwnConversion(portAttrs.NodeWWN.wwn));
1074*fcf3ce44SJohn Forte 			print_fabric_dtype_prop(portAttrs.PortWWN.wwn,
1075*fcf3ce44SJohn Forte 			    portAttrs.PortWWN.wwn, 0x1f);
1076*fcf3ce44SJohn Forte 			done = 1;
1077*fcf3ce44SJohn Forte 		    }
1078*fcf3ce44SJohn Forte 		}
1079*fcf3ce44SJohn Forte 	    }
1080*fcf3ce44SJohn Forte 	    if (!goodPath) {
1081*fcf3ce44SJohn Forte 		fprintf(stderr, MSGSTR(112, "Error: Invalid pathname (%s)"),
1082*fcf3ce44SJohn Forte 			argv[path_index]);
1083*fcf3ce44SJohn Forte 		fprintf(stderr, "\n");
1084*fcf3ce44SJohn Forte 		ret = -1;
1085*fcf3ce44SJohn Forte 	    }
1086*fcf3ce44SJohn Forte 	}
1087*fcf3ce44SJohn Forte 	return (ret);
1088*fcf3ce44SJohn Forte }
1089*fcf3ce44SJohn Forte 
1090*fcf3ce44SJohn Forte int
fchba_display_link_status(char ** argv)1091*fcf3ce44SJohn Forte fchba_display_link_status(char **argv)
1092*fcf3ce44SJohn Forte {
1093*fcf3ce44SJohn Forte 	int		path_index = 0;
1094*fcf3ce44SJohn Forte 	uint64_t	wwn;
1095*fcf3ce44SJohn Forte 	HBA_HANDLE handle;
1096*fcf3ce44SJohn Forte 	HBA_ADAPTERATTRIBUTES hbaAttrs;
1097*fcf3ce44SJohn Forte 	HBA_PORTATTRIBUTES portAttrs;
1098*fcf3ce44SJohn Forte 	HBA_PORTATTRIBUTES discPortAttrs;
1099*fcf3ce44SJohn Forte 	HBA_FCPTARGETMAPPINGV2    *map;
1100*fcf3ce44SJohn Forte 	HBA_STATUS status;
1101*fcf3ce44SJohn Forte 	int count, adapterIndex, portIndex, discIndex;
1102*fcf3ce44SJohn Forte 	char name[256], *physical, *comp_phys;
1103*fcf3ce44SJohn Forte 	int		matched;
1104*fcf3ce44SJohn Forte 	struct fc_rls_acc_params	rls;
1105*fcf3ce44SJohn Forte 	uint32_t	rls_size = sizeof (rls);
1106*fcf3ce44SJohn Forte 	boolean_t	goodPath = B_FALSE;
1107*fcf3ce44SJohn Forte 	int		ret = 0;
1108*fcf3ce44SJohn Forte 
1109*fcf3ce44SJohn Forte 	if (loadLibrary()) {
1110*fcf3ce44SJohn Forte 	    return (-1);
1111*fcf3ce44SJohn Forte 	}
1112*fcf3ce44SJohn Forte 	for (path_index = 0; argv[path_index] != NULL; path_index++) {
1113*fcf3ce44SJohn Forte 	    goodPath = B_FALSE;
1114*fcf3ce44SJohn Forte 
1115*fcf3ce44SJohn Forte 	    if (is_wwn(argv[path_index])) {
1116*fcf3ce44SJohn Forte 		(void) sscanf(argv[path_index], "%016llx", &wwn);
1117*fcf3ce44SJohn Forte 	    } else if (!is_path(argv[path_index])) {
1118*fcf3ce44SJohn Forte 		fprintf(stderr, MSGSTR(112, "Error: Invalid pathname (%s)"),
1119*fcf3ce44SJohn Forte 			argv[path_index]);
1120*fcf3ce44SJohn Forte 		fprintf(stderr, "\n");
1121*fcf3ce44SJohn Forte 		ret = -1;
1122*fcf3ce44SJohn Forte 		continue;
1123*fcf3ce44SJohn Forte 	    }
1124*fcf3ce44SJohn Forte 
1125*fcf3ce44SJohn Forte 	    count = getNumberOfAdapters();
1126*fcf3ce44SJohn Forte 
1127*fcf3ce44SJohn Forte 	    /* Loop over all HBAs */
1128*fcf3ce44SJohn Forte 	    for (adapterIndex = 0; adapterIndex < count; adapterIndex ++) {
1129*fcf3ce44SJohn Forte 		if (skip_hba(adapterIndex)) {
1130*fcf3ce44SJohn Forte 		    continue;
1131*fcf3ce44SJohn Forte 		}
1132*fcf3ce44SJohn Forte 		status = HBA_GetAdapterName(adapterIndex, (char *)&name);
1133*fcf3ce44SJohn Forte 		if (status != HBA_STATUS_OK) {
1134*fcf3ce44SJohn Forte 		    /* May have been DR'd */
1135*fcf3ce44SJohn Forte 		    continue;
1136*fcf3ce44SJohn Forte 		}
1137*fcf3ce44SJohn Forte 		handle = HBA_OpenAdapter(name);
1138*fcf3ce44SJohn Forte 		if (handle == 0) {
1139*fcf3ce44SJohn Forte 		    /* May have been DR'd */
1140*fcf3ce44SJohn Forte 		    continue;
1141*fcf3ce44SJohn Forte 		}
1142*fcf3ce44SJohn Forte 
1143*fcf3ce44SJohn Forte 		if (getAdapterAttrs(handle, name, &hbaAttrs)) {
1144*fcf3ce44SJohn Forte 		    /* Should never happen */
1145*fcf3ce44SJohn Forte 		    HBA_CloseAdapter(handle);
1146*fcf3ce44SJohn Forte 		    continue;
1147*fcf3ce44SJohn Forte 		}
1148*fcf3ce44SJohn Forte 
1149*fcf3ce44SJohn Forte 
1150*fcf3ce44SJohn Forte 		/* Loop over all HBA Ports */
1151*fcf3ce44SJohn Forte 		for (portIndex = 0; portIndex < hbaAttrs.NumberOfPorts;
1152*fcf3ce44SJohn Forte 			portIndex++) {
1153*fcf3ce44SJohn Forte 		    if (getAdapterPortAttrs(handle, name, portIndex,
1154*fcf3ce44SJohn Forte 			    &portAttrs)) {
1155*fcf3ce44SJohn Forte 			continue;
1156*fcf3ce44SJohn Forte 		    }
1157*fcf3ce44SJohn Forte 
1158*fcf3ce44SJohn Forte 		    matched = 0;
1159*fcf3ce44SJohn Forte 		    if (is_wwn(argv[path_index])) {
1160*fcf3ce44SJohn Forte 			if (wwn == wwnConversion(
1161*fcf3ce44SJohn Forte 				portAttrs.NodeWWN.wwn) ||
1162*fcf3ce44SJohn Forte 				wwn == wwnConversion(
1163*fcf3ce44SJohn Forte 				portAttrs.PortWWN.wwn)) {
1164*fcf3ce44SJohn Forte 			    matched = 1;
1165*fcf3ce44SJohn Forte 			}
1166*fcf3ce44SJohn Forte 		    } else {
1167*fcf3ce44SJohn Forte 			if (is_path(argv[path_index]) &&
1168*fcf3ce44SJohn Forte 			    ((physical = get_slash_devices_from_osDevName(
1169*fcf3ce44SJohn Forte 				argv[path_index],
1170*fcf3ce44SJohn Forte 				STANDARD_DEVNAME_HANDLING)) != NULL) &&
1171*fcf3ce44SJohn Forte 			    ((comp_phys = get_slash_devices_from_osDevName(
1172*fcf3ce44SJohn Forte 				portAttrs.OSDeviceName,
1173*fcf3ce44SJohn Forte 				STANDARD_DEVNAME_HANDLING)) != NULL)) {
1174*fcf3ce44SJohn Forte 			    char *tmp = strstr(physical, ":devctl");
1175*fcf3ce44SJohn Forte 			    if (tmp) {
1176*fcf3ce44SJohn Forte 				*tmp = '\0';
1177*fcf3ce44SJohn Forte 			    } else {
1178*fcf3ce44SJohn Forte 				tmp = strstr(physical, ":fc");
1179*fcf3ce44SJohn Forte 				if (tmp) {
1180*fcf3ce44SJohn Forte 					*tmp = '\0';
1181*fcf3ce44SJohn Forte 				}
1182*fcf3ce44SJohn Forte 			    }
1183*fcf3ce44SJohn Forte 			    if (strstr(comp_phys, physical)) {
1184*fcf3ce44SJohn Forte 				matched = 1;
1185*fcf3ce44SJohn Forte 			    }
1186*fcf3ce44SJohn Forte 			}
1187*fcf3ce44SJohn Forte 			if (physical) {
1188*fcf3ce44SJohn Forte 			    free(physical);
1189*fcf3ce44SJohn Forte 			    physical = NULL;
1190*fcf3ce44SJohn Forte 			}
1191*fcf3ce44SJohn Forte 			if (comp_phys) {
1192*fcf3ce44SJohn Forte 			    free(comp_phys);
1193*fcf3ce44SJohn Forte 			    comp_phys = NULL;
1194*fcf3ce44SJohn Forte 			}
1195*fcf3ce44SJohn Forte 		    }
1196*fcf3ce44SJohn Forte 
1197*fcf3ce44SJohn Forte 		    if (!matched) {
1198*fcf3ce44SJohn Forte 			if (fetch_mappings(handle, portAttrs.PortWWN, &map)) {
1199*fcf3ce44SJohn Forte 			    continue;
1200*fcf3ce44SJohn Forte 			}
1201*fcf3ce44SJohn Forte 		    }
1202*fcf3ce44SJohn Forte 
1203*fcf3ce44SJohn Forte 		    if (matched || match_mappings(argv[path_index], map) >= 0) {
1204*fcf3ce44SJohn Forte 			goodPath = B_TRUE;
1205*fcf3ce44SJohn Forte 			fprintf(stdout,
1206*fcf3ce44SJohn Forte 				MSGSTR(2007, "\nLink Error Status "
1207*fcf3ce44SJohn Forte 				"information for loop:%s\n"), argv[path_index]);
1208*fcf3ce44SJohn Forte 			fprintf(stdout, MSGSTR(2008, "al_pa   lnk fail "
1209*fcf3ce44SJohn Forte 				"   sync loss   signal loss   sequence err"
1210*fcf3ce44SJohn Forte 				"   invalid word   CRC\n"));
1211*fcf3ce44SJohn Forte 
1212*fcf3ce44SJohn Forte 			for (discIndex = 0;
1213*fcf3ce44SJohn Forte 				discIndex < portAttrs.NumberofDiscoveredPorts;
1214*fcf3ce44SJohn Forte 				discIndex++) {
1215*fcf3ce44SJohn Forte 
1216*fcf3ce44SJohn Forte 
1217*fcf3ce44SJohn Forte 			    if (getDiscPortAttrs(handle, name, portIndex,
1218*fcf3ce44SJohn Forte 				    discIndex, &discPortAttrs)) {
1219*fcf3ce44SJohn Forte 				continue;
1220*fcf3ce44SJohn Forte 			    }
1221*fcf3ce44SJohn Forte 
1222*fcf3ce44SJohn Forte 			    status = HBA_SendRLS(handle, portAttrs.PortWWN,
1223*fcf3ce44SJohn Forte 					discPortAttrs.PortWWN,
1224*fcf3ce44SJohn Forte 					&rls, &rls_size);
1225*fcf3ce44SJohn Forte 			    if (status != HBA_STATUS_OK) {
1226*fcf3ce44SJohn Forte 				memset(&rls, 0xff, sizeof (rls));
1227*fcf3ce44SJohn Forte 			    }
1228*fcf3ce44SJohn Forte 
1229*fcf3ce44SJohn Forte 			    if ((rls.rls_link_fail == 0xffffffff) &&
1230*fcf3ce44SJohn Forte 				(rls.rls_sync_loss == 0xffffffff) &&
1231*fcf3ce44SJohn Forte 				(rls.rls_sig_loss == 0xffffffff) &&
1232*fcf3ce44SJohn Forte 				(rls.rls_prim_seq_err == 0xffffffff) &&
1233*fcf3ce44SJohn Forte 				(rls.rls_invalid_word == 0xffffffff) &&
1234*fcf3ce44SJohn Forte 				(rls.rls_invalid_crc == 0xffffffff)) {
1235*fcf3ce44SJohn Forte 				    fprintf(stdout,
1236*fcf3ce44SJohn Forte 					"%x\t%-12d%-12d%-14d%-15d%-15d%-12d\n",
1237*fcf3ce44SJohn Forte 					    discPortAttrs.PortFcId,
1238*fcf3ce44SJohn Forte 					    rls.rls_link_fail,
1239*fcf3ce44SJohn Forte 					    rls.rls_sync_loss,
1240*fcf3ce44SJohn Forte 					    rls.rls_sig_loss,
1241*fcf3ce44SJohn Forte 					    rls.rls_prim_seq_err,
1242*fcf3ce44SJohn Forte 					    rls.rls_invalid_word,
1243*fcf3ce44SJohn Forte 					    rls.rls_invalid_crc);
1244*fcf3ce44SJohn Forte 			    } else {
1245*fcf3ce44SJohn Forte 				    fprintf(stdout,
1246*fcf3ce44SJohn Forte 					"%x\t%-12u%-12u%-14u%-15u%-15u%-12u\n",
1247*fcf3ce44SJohn Forte 					    discPortAttrs.PortFcId,
1248*fcf3ce44SJohn Forte 					    rls.rls_link_fail,
1249*fcf3ce44SJohn Forte 					    rls.rls_sync_loss,
1250*fcf3ce44SJohn Forte 					    rls.rls_sig_loss,
1251*fcf3ce44SJohn Forte 					    rls.rls_prim_seq_err,
1252*fcf3ce44SJohn Forte 					    rls.rls_invalid_word,
1253*fcf3ce44SJohn Forte 					    rls.rls_invalid_crc);
1254*fcf3ce44SJohn Forte 			    }
1255*fcf3ce44SJohn Forte 
1256*fcf3ce44SJohn Forte 
1257*fcf3ce44SJohn Forte 			}
1258*fcf3ce44SJohn Forte 			/* Now dump this HBA's stats */
1259*fcf3ce44SJohn Forte 			status = HBA_SendRLS(handle, portAttrs.PortWWN,
1260*fcf3ce44SJohn Forte 				portAttrs.PortWWN,
1261*fcf3ce44SJohn Forte 				&rls, &rls_size);
1262*fcf3ce44SJohn Forte 			if (status != HBA_STATUS_OK) {
1263*fcf3ce44SJohn Forte 			    memset(&rls, 0xff, sizeof (rls));
1264*fcf3ce44SJohn Forte 			}
1265*fcf3ce44SJohn Forte 
1266*fcf3ce44SJohn Forte 			if ((rls.rls_link_fail == 0xffffffff) &&
1267*fcf3ce44SJohn Forte 				(rls.rls_sync_loss == 0xffffffff) &&
1268*fcf3ce44SJohn Forte 				(rls.rls_sig_loss == 0xffffffff) &&
1269*fcf3ce44SJohn Forte 				(rls.rls_prim_seq_err == 0xffffffff) &&
1270*fcf3ce44SJohn Forte 				(rls.rls_invalid_word == 0xffffffff) &&
1271*fcf3ce44SJohn Forte 				(rls.rls_invalid_crc == 0xffffffff)) {
1272*fcf3ce44SJohn Forte 			    fprintf(stdout,
1273*fcf3ce44SJohn Forte 				    "%x\t%-12d%-12d%-14d%-15d%-15d%-12d\n",
1274*fcf3ce44SJohn Forte 				    portAttrs.PortFcId,
1275*fcf3ce44SJohn Forte 				    rls.rls_link_fail,
1276*fcf3ce44SJohn Forte 				    rls.rls_sync_loss,
1277*fcf3ce44SJohn Forte 				    rls.rls_sig_loss,
1278*fcf3ce44SJohn Forte 				    rls.rls_prim_seq_err,
1279*fcf3ce44SJohn Forte 				    rls.rls_invalid_word,
1280*fcf3ce44SJohn Forte 				    rls.rls_invalid_crc);
1281*fcf3ce44SJohn Forte 			} else {
1282*fcf3ce44SJohn Forte 			    fprintf(stdout,
1283*fcf3ce44SJohn Forte 				    "%x\t%-12u%-12u%-14u%-15u%-15u%-12u\n",
1284*fcf3ce44SJohn Forte 				    portAttrs.PortFcId,
1285*fcf3ce44SJohn Forte 				    rls.rls_link_fail,
1286*fcf3ce44SJohn Forte 				    rls.rls_sync_loss,
1287*fcf3ce44SJohn Forte 				    rls.rls_sig_loss,
1288*fcf3ce44SJohn Forte 				    rls.rls_prim_seq_err,
1289*fcf3ce44SJohn Forte 				    rls.rls_invalid_word,
1290*fcf3ce44SJohn Forte 				    rls.rls_invalid_crc);
1291*fcf3ce44SJohn Forte 			}
1292*fcf3ce44SJohn Forte 		    }
1293*fcf3ce44SJohn Forte 		}
1294*fcf3ce44SJohn Forte 	    }
1295*fcf3ce44SJohn Forte 	    if (!goodPath) {
1296*fcf3ce44SJohn Forte 		fprintf(stderr, MSGSTR(112, "Error: Invalid pathname (%s)"),
1297*fcf3ce44SJohn Forte 			argv[path_index]);
1298*fcf3ce44SJohn Forte 		fprintf(stderr, "\n");
1299*fcf3ce44SJohn Forte 		ret = -1;
1300*fcf3ce44SJohn Forte 	    }
1301*fcf3ce44SJohn Forte 	}
1302*fcf3ce44SJohn Forte 	(void) fprintf(stdout,
1303*fcf3ce44SJohn Forte 		MSGSTR(2009, "NOTE: These LESB counts are not"
1304*fcf3ce44SJohn Forte 		" cleared by a reset, only power cycles.\n"
1305*fcf3ce44SJohn Forte 		"These counts must be compared"
1306*fcf3ce44SJohn Forte 		" to previously read counts.\n"));
1307*fcf3ce44SJohn Forte 	return (ret);
1308*fcf3ce44SJohn Forte }
1309*fcf3ce44SJohn Forte 
1310*fcf3ce44SJohn Forte typedef struct _PathInformation {
1311*fcf3ce44SJohn Forte 	char	pathClass[MAXPATHLEN];
1312*fcf3ce44SJohn Forte 	char	pathState[MAXPATHLEN];
1313*fcf3ce44SJohn Forte 	int32_t	pathInfoState;
1314*fcf3ce44SJohn Forte 	int32_t	pathInfoExternalState;
1315*fcf3ce44SJohn Forte } PathInformation;
1316*fcf3ce44SJohn Forte 
1317*fcf3ce44SJohn Forte struct lun_tracking {
1318*fcf3ce44SJohn Forte 	HBA_FCPSCSIENTRYV2  map;
1319*fcf3ce44SJohn Forte 	HBA_WWN	hba_pwwn;
1320*fcf3ce44SJohn Forte 	char	hba_path[MAXPATHLEN];
1321*fcf3ce44SJohn Forte 	PathInformation info;
1322*fcf3ce44SJohn Forte 
1323*fcf3ce44SJohn Forte 	/* Points to another lun_tracking instance with the same map->LUID */
1324*fcf3ce44SJohn Forte 	struct lun_tracking	*next_path;
1325*fcf3ce44SJohn Forte 
1326*fcf3ce44SJohn Forte 	/* Points to next lun_tracking with a different map->LUID */
1327*fcf3ce44SJohn Forte 	struct lun_tracking *next_lun;
1328*fcf3ce44SJohn Forte };
1329*fcf3ce44SJohn Forte 
1330*fcf3ce44SJohn Forte 
1331*fcf3ce44SJohn Forte static const char VHCI_COMPONENT[] = "scsi_vhci";
1332*fcf3ce44SJohn Forte static void
scsi_vhci_details(struct lun_tracking * lun)1333*fcf3ce44SJohn Forte scsi_vhci_details(struct lun_tracking *lun)
1334*fcf3ce44SJohn Forte {
1335*fcf3ce44SJohn Forte 	HBA_FCPSCSIENTRYV2 entry = lun->map;
1336*fcf3ce44SJohn Forte 	int		retval = 0;
1337*fcf3ce44SJohn Forte 	int		pathcnt, i, count, found = 0;
1338*fcf3ce44SJohn Forte 	char		temppath[MAXPATHLEN];
1339*fcf3ce44SJohn Forte 	char		buf[MAXPATHLEN];
1340*fcf3ce44SJohn Forte 	char	*path_state[5];
1341*fcf3ce44SJohn Forte 
1342*fcf3ce44SJohn Forte 	char	*phys_path = get_slash_devices_from_osDevName(
1343*fcf3ce44SJohn Forte 				entry.ScsiId.OSDeviceName,
1344*fcf3ce44SJohn Forte 				STANDARD_DEVNAME_HANDLING);
1345*fcf3ce44SJohn Forte 	char	*devPath = NULL;
1346*fcf3ce44SJohn Forte 	char	*trailingCruft = NULL;
1347*fcf3ce44SJohn Forte 	char	devaddr[MAXPATHLEN];
1348*fcf3ce44SJohn Forte 	sv_iocdata_t	ioc;
1349*fcf3ce44SJohn Forte 	int	prop_buf_size = SV_PROP_MAX_BUF_SIZE;
1350*fcf3ce44SJohn Forte 	char	*path_class_val = NULL;
1351*fcf3ce44SJohn Forte 	char	client_path[MAXPATHLEN];
1352*fcf3ce44SJohn Forte 	char	phci_path[MAXPATHLEN];
1353*fcf3ce44SJohn Forte 
1354*fcf3ce44SJohn Forte 	/* Only proceed if we are an mpxio path */
1355*fcf3ce44SJohn Forte 	if (phys_path == NULL || strstr(phys_path, VHCI_COMPONENT) == NULL) {
1356*fcf3ce44SJohn Forte 	    return;
1357*fcf3ce44SJohn Forte 	}
1358*fcf3ce44SJohn Forte 
1359*fcf3ce44SJohn Forte 	path_state[0] = MSGSTR(2400, "INIT");
1360*fcf3ce44SJohn Forte 	path_state[1] = MSGSTR(2401, "ONLINE");
1361*fcf3ce44SJohn Forte 	path_state[2] = MSGSTR(2402, "STANDBY");
1362*fcf3ce44SJohn Forte 	path_state[3] = MSGSTR(2403, "FAULT");
1363*fcf3ce44SJohn Forte 	path_state[4] = MSGSTR(2404, "OFFLINE");
1364*fcf3ce44SJohn Forte 
1365*fcf3ce44SJohn Forte 	sprintf(devaddr, "%016llx,%x", wwnConversion(
1366*fcf3ce44SJohn Forte 		entry.FcpId.PortWWN.wwn),
1367*fcf3ce44SJohn Forte 		entry.ScsiId.ScsiOSLun);
1368*fcf3ce44SJohn Forte 
1369*fcf3ce44SJohn Forte 	/* First get the controller path */
1370*fcf3ce44SJohn Forte 	sprintf(temppath, "/dev/cfg/c%d", entry.ScsiId.ScsiBusNumber);
1371*fcf3ce44SJohn Forte 	if ((count = readlink(temppath, buf, sizeof (buf)))) {
1372*fcf3ce44SJohn Forte 	    buf[count] = '\0';
1373*fcf3ce44SJohn Forte 	    /* Now skip over the leading "../.." */
1374*fcf3ce44SJohn Forte 	    devPath = strstr(buf, "/devices/");
1375*fcf3ce44SJohn Forte 	    if (devPath == NULL) {
1376*fcf3ce44SJohn Forte 		strcpy(lun->info.pathClass, "Unavailable");
1377*fcf3ce44SJohn Forte 		strcpy(lun->info.pathState, "Unavailable");
1378*fcf3ce44SJohn Forte 		free(phys_path);
1379*fcf3ce44SJohn Forte 		return;
1380*fcf3ce44SJohn Forte 	    }
1381*fcf3ce44SJohn Forte 
1382*fcf3ce44SJohn Forte 	    /* Now chop off the trailing ":xxx" portion if present */
1383*fcf3ce44SJohn Forte 	    trailingCruft = strrchr(buf, ':');
1384*fcf3ce44SJohn Forte 	    if (trailingCruft) {
1385*fcf3ce44SJohn Forte 		trailingCruft[0] = '\0';
1386*fcf3ce44SJohn Forte 	    }
1387*fcf3ce44SJohn Forte 	} else {
1388*fcf3ce44SJohn Forte 	    strcpy(lun->info.pathClass, "Unavailable");
1389*fcf3ce44SJohn Forte 	    strcpy(lun->info.pathState, "Unavailable");
1390*fcf3ce44SJohn Forte 	    free(phys_path);
1391*fcf3ce44SJohn Forte 	    return;
1392*fcf3ce44SJohn Forte 	}
1393*fcf3ce44SJohn Forte 
1394*fcf3ce44SJohn Forte 	ioc.client = client_path;
1395*fcf3ce44SJohn Forte 	ioc.phci = phci_path;
1396*fcf3ce44SJohn Forte 
1397*fcf3ce44SJohn Forte 	retval = get_scsi_vhci_pathinfo(phys_path, &ioc, &pathcnt);
1398*fcf3ce44SJohn Forte 	if (retval != 0) {
1399*fcf3ce44SJohn Forte 	    print_errString(retval, NULL);
1400*fcf3ce44SJohn Forte 	    exit(-1);
1401*fcf3ce44SJohn Forte 	}
1402*fcf3ce44SJohn Forte 
1403*fcf3ce44SJohn Forte 	for (i = 0; i < pathcnt; i++) {
1404*fcf3ce44SJohn Forte 	    nvlist_t *nvl;
1405*fcf3ce44SJohn Forte 	    if (strstr(devPath, ioc.ret_buf[i].device.ret_phci)) {
1406*fcf3ce44SJohn Forte 		/* This could break someday if MPxIO changes devaddr */
1407*fcf3ce44SJohn Forte 		if (strstr(ioc.ret_buf[i].ret_addr, devaddr)) {
1408*fcf3ce44SJohn Forte 		    retval = nvlist_unpack(ioc.ret_buf[i].ret_prop.buf,
1409*fcf3ce44SJohn Forte 			prop_buf_size, &nvl, 0);
1410*fcf3ce44SJohn Forte 		    if (retval != 0) {
1411*fcf3ce44SJohn Forte 			strcpy(lun->info.pathClass,
1412*fcf3ce44SJohn Forte 			    "UNKNOWN PROB");
1413*fcf3ce44SJohn Forte 		    } else {
1414*fcf3ce44SJohn Forte 			strcpy(lun->info.pathState,
1415*fcf3ce44SJohn Forte 			    path_state[ioc.ret_buf[i].ret_state]);
1416*fcf3ce44SJohn Forte 			lun->info.pathInfoState = ioc.ret_buf[i].ret_state;
1417*fcf3ce44SJohn Forte 			lun->info.pathInfoExternalState =
1418*fcf3ce44SJohn Forte 			    ioc.ret_buf[i].ret_ext_state;
1419*fcf3ce44SJohn Forte 			if (nvlist_lookup_string(nvl, "path-class",
1420*fcf3ce44SJohn Forte 				&path_class_val) == 0) {
1421*fcf3ce44SJohn Forte 			    strcpy(lun->info.pathClass, path_class_val);
1422*fcf3ce44SJohn Forte 			} else {
1423*fcf3ce44SJohn Forte 			    strcpy(lun->info.pathClass, "UNKNOWN");
1424*fcf3ce44SJohn Forte 			}
1425*fcf3ce44SJohn Forte 		    }
1426*fcf3ce44SJohn Forte 		    nvlist_free(nvl);
1427*fcf3ce44SJohn Forte 		    found++;
1428*fcf3ce44SJohn Forte 		    break;
1429*fcf3ce44SJohn Forte 		}
1430*fcf3ce44SJohn Forte 	    }
1431*fcf3ce44SJohn Forte 
1432*fcf3ce44SJohn Forte 	}
1433*fcf3ce44SJohn Forte 
1434*fcf3ce44SJohn Forte 	if (!found) {
1435*fcf3ce44SJohn Forte 	    strcpy(lun->info.pathClass, "Unavailable");
1436*fcf3ce44SJohn Forte 	    strcpy(lun->info.pathState, "Unavailable");
1437*fcf3ce44SJohn Forte 	}
1438*fcf3ce44SJohn Forte 	free(phys_path);
1439*fcf3ce44SJohn Forte 
1440*fcf3ce44SJohn Forte 	/* free everything we alloced */
1441*fcf3ce44SJohn Forte 	for (i = 0; i < ioc.buf_elem; i++) {
1442*fcf3ce44SJohn Forte 		free(ioc.ret_buf[i].ret_prop.buf);
1443*fcf3ce44SJohn Forte 		free(ioc.ret_buf[i].ret_prop.ret_buf_size);
1444*fcf3ce44SJohn Forte 	}
1445*fcf3ce44SJohn Forte 	free(ioc.ret_buf);
1446*fcf3ce44SJohn Forte 
1447*fcf3ce44SJohn Forte }
1448*fcf3ce44SJohn Forte 
1449*fcf3ce44SJohn Forte /* Utility routine to add new entries to the list (ignores dups) */
1450*fcf3ce44SJohn Forte static void
add_lun_path(struct lun_tracking * head,HBA_FCPSCSIENTRYV2 * map,HBA_WWN pwwn,char * path)1451*fcf3ce44SJohn Forte add_lun_path(struct lun_tracking *head, HBA_FCPSCSIENTRYV2  *map,
1452*fcf3ce44SJohn Forte 	    HBA_WWN pwwn, char *path)
1453*fcf3ce44SJohn Forte {
1454*fcf3ce44SJohn Forte 	struct lun_tracking *tmp = NULL, *cmp = NULL;
1455*fcf3ce44SJohn Forte 
1456*fcf3ce44SJohn Forte 	for (tmp = head; tmp != NULL; tmp = tmp->next_lun) {
1457*fcf3ce44SJohn Forte 	    if (memcmp(&tmp->map.LUID, &map->LUID,
1458*fcf3ce44SJohn Forte 		    sizeof (HBA_LUID)) == 0) {
1459*fcf3ce44SJohn Forte 
1460*fcf3ce44SJohn Forte 		/* Ensure this isn't a duplicate */
1461*fcf3ce44SJohn Forte 		for (cmp = tmp; cmp->next_path != NULL;
1462*fcf3ce44SJohn Forte 			    cmp = cmp->next_path) {
1463*fcf3ce44SJohn Forte 		    if (memcmp(&cmp->map, map, sizeof (cmp->map)) == 0) {
1464*fcf3ce44SJohn Forte 			return;
1465*fcf3ce44SJohn Forte 		    }
1466*fcf3ce44SJohn Forte 		}
1467*fcf3ce44SJohn Forte 		if (memcmp(&cmp->map, map, sizeof (cmp->map)) == 0) {
1468*fcf3ce44SJohn Forte 		    return;
1469*fcf3ce44SJohn Forte 		}
1470*fcf3ce44SJohn Forte 
1471*fcf3ce44SJohn Forte 		/* We have a new entry to add */
1472*fcf3ce44SJohn Forte 		cmp->next_path = (struct lun_tracking *)calloc(1,
1473*fcf3ce44SJohn Forte 		    sizeof (struct lun_tracking));
1474*fcf3ce44SJohn Forte 		cmp = cmp->next_path;
1475*fcf3ce44SJohn Forte 		(void) memcpy(&cmp->map, map,
1476*fcf3ce44SJohn Forte 		    sizeof (cmp->map));
1477*fcf3ce44SJohn Forte 		(void) memcpy(&cmp->hba_pwwn, &pwwn,
1478*fcf3ce44SJohn Forte 			sizeof (cmp->hba_pwwn));
1479*fcf3ce44SJohn Forte 		(void) snprintf(cmp->hba_path, MAXPATHLEN,
1480*fcf3ce44SJohn Forte 		    path);
1481*fcf3ce44SJohn Forte 		scsi_vhci_details(cmp);
1482*fcf3ce44SJohn Forte 		return;
1483*fcf3ce44SJohn Forte 	    }
1484*fcf3ce44SJohn Forte 	}
1485*fcf3ce44SJohn Forte 	/* Append a new LUN at the end of the list */
1486*fcf3ce44SJohn Forte 	for (tmp = head; tmp->next_lun != NULL; tmp = tmp->next_lun) {}
1487*fcf3ce44SJohn Forte 	tmp->next_lun = (struct lun_tracking *)calloc(1,
1488*fcf3ce44SJohn Forte 		sizeof (struct lun_tracking));
1489*fcf3ce44SJohn Forte 	tmp = tmp->next_lun;
1490*fcf3ce44SJohn Forte 	(void) memcpy(&tmp->map, map,
1491*fcf3ce44SJohn Forte 		sizeof (tmp->map));
1492*fcf3ce44SJohn Forte 	(void) memcpy(&tmp->hba_pwwn, &pwwn,
1493*fcf3ce44SJohn Forte 		sizeof (tmp->hba_pwwn));
1494*fcf3ce44SJohn Forte 	(void) snprintf(tmp->hba_path, MAXPATHLEN,
1495*fcf3ce44SJohn Forte 		path);
1496*fcf3ce44SJohn Forte 	scsi_vhci_details(tmp);
1497*fcf3ce44SJohn Forte }
1498*fcf3ce44SJohn Forte 
1499*fcf3ce44SJohn Forte /*ARGSUSED*/
1500*fcf3ce44SJohn Forte int
fchba_display_config(char ** argv,int option_t_input,int argc)1501*fcf3ce44SJohn Forte fchba_display_config(char **argv, int option_t_input, int argc)
1502*fcf3ce44SJohn Forte {
1503*fcf3ce44SJohn Forte 	int		path_index = 0;
1504*fcf3ce44SJohn Forte 	uint64_t	wwn;
1505*fcf3ce44SJohn Forte 	uint64_t	lun = 0;
1506*fcf3ce44SJohn Forte 	HBA_HANDLE handle;
1507*fcf3ce44SJohn Forte 	HBA_ADAPTERATTRIBUTES hbaAttrs;
1508*fcf3ce44SJohn Forte 	HBA_PORTATTRIBUTES portAttrs;
1509*fcf3ce44SJohn Forte 	HBA_FCPTARGETMAPPINGV2    *map;
1510*fcf3ce44SJohn Forte 	HBA_STATUS status;
1511*fcf3ce44SJohn Forte 	int count, adapterIndex, portIndex;
1512*fcf3ce44SJohn Forte 	char name[256];
1513*fcf3ce44SJohn Forte 	L_inquiry	inq;
1514*fcf3ce44SJohn Forte 	struct scsi_extended_sense sense;
1515*fcf3ce44SJohn Forte 	struct page80	serial;
1516*fcf3ce44SJohn Forte 	HBA_UINT8	scsiStatus;
1517*fcf3ce44SJohn Forte 	uint32_t	inquirySize = sizeof (inq), senseSize = sizeof (sense);
1518*fcf3ce44SJohn Forte 	uint32_t	serialSize = sizeof (serial);
1519*fcf3ce44SJohn Forte 	struct mode_page	*pg_hdr;
1520*fcf3ce44SJohn Forte 	uchar_t		*pg_buf;
1521*fcf3ce44SJohn Forte 	float		lunMbytes;
1522*fcf3ce44SJohn Forte 	struct capacity_data_struct cap_data;
1523*fcf3ce44SJohn Forte 	uint32_t	    cap_data_size = sizeof (cap_data);
1524*fcf3ce44SJohn Forte 	struct mode_header_g1	*mode_header_ptr;
1525*fcf3ce44SJohn Forte 	int		offset;
1526*fcf3ce44SJohn Forte 	char *phys_path = NULL;
1527*fcf3ce44SJohn Forte 	int		mpxio = 0;
1528*fcf3ce44SJohn Forte 	int		wwnCompare = 0;
1529*fcf3ce44SJohn Forte 	char	    *physical = NULL;
1530*fcf3ce44SJohn Forte 	struct lun_tracking	*head = NULL;
1531*fcf3ce44SJohn Forte 	boolean_t	goodPath = B_FALSE;
1532*fcf3ce44SJohn Forte 	int		ret = 0;
1533*fcf3ce44SJohn Forte 
1534*fcf3ce44SJohn Forte 
1535*fcf3ce44SJohn Forte 
1536*fcf3ce44SJohn Forte 	if ((status = loadLibrary())) {
1537*fcf3ce44SJohn Forte 	    return (-1);
1538*fcf3ce44SJohn Forte 	}
1539*fcf3ce44SJohn Forte 	for (path_index = 0; argv[path_index] != NULL; path_index++) {
1540*fcf3ce44SJohn Forte 	    goodPath = B_FALSE;
1541*fcf3ce44SJohn Forte 
1542*fcf3ce44SJohn Forte 	    if (is_wwn(argv[path_index])) {
1543*fcf3ce44SJohn Forte 		(void) sscanf(argv[path_index], "%016llx", &wwn);
1544*fcf3ce44SJohn Forte 		wwnCompare = 1;
1545*fcf3ce44SJohn Forte 	    } else if (!is_path(argv[path_index])) {
1546*fcf3ce44SJohn Forte 		fprintf(stderr, MSGSTR(112, "Error: Invalid pathname (%s)"),
1547*fcf3ce44SJohn Forte 			argv[path_index]);
1548*fcf3ce44SJohn Forte 		fprintf(stderr, "\n");
1549*fcf3ce44SJohn Forte 		ret = -1;
1550*fcf3ce44SJohn Forte 		continue;
1551*fcf3ce44SJohn Forte 	    }
1552*fcf3ce44SJohn Forte 	    if (!wwnCompare) {
1553*fcf3ce44SJohn Forte 		/* Convert the paths to phsyical paths */
1554*fcf3ce44SJohn Forte 		physical = get_slash_devices_from_osDevName(argv[path_index],
1555*fcf3ce44SJohn Forte 			STANDARD_DEVNAME_HANDLING);
1556*fcf3ce44SJohn Forte 		if (!physical) {
1557*fcf3ce44SJohn Forte 		    fprintf(stderr, MSGSTR(112,
1558*fcf3ce44SJohn Forte 			"Error: Invalid pathname (%s)"),
1559*fcf3ce44SJohn Forte 			argv[path_index]);
1560*fcf3ce44SJohn Forte 		    fprintf(stderr, "\n");
1561*fcf3ce44SJohn Forte 		    ret = -1;
1562*fcf3ce44SJohn Forte 		    continue;
1563*fcf3ce44SJohn Forte 		}
1564*fcf3ce44SJohn Forte 	    }
1565*fcf3ce44SJohn Forte 
1566*fcf3ce44SJohn Forte 	    count = getNumberOfAdapters();
1567*fcf3ce44SJohn Forte 
1568*fcf3ce44SJohn Forte 
1569*fcf3ce44SJohn Forte 		/*
1570*fcf3ce44SJohn Forte 		 * We have to loop twice to ensure we don't miss any
1571*fcf3ce44SJohn Forte 		 * extra paths for other targets in a multi-target device
1572*fcf3ce44SJohn Forte 		 */
1573*fcf3ce44SJohn Forte 
1574*fcf3ce44SJohn Forte 	    /* First check WWN/path comparisons */
1575*fcf3ce44SJohn Forte 	    for (adapterIndex = 0; adapterIndex < count; adapterIndex ++) {
1576*fcf3ce44SJohn Forte 		if (skip_hba(adapterIndex)) {
1577*fcf3ce44SJohn Forte 		    continue;
1578*fcf3ce44SJohn Forte 		}
1579*fcf3ce44SJohn Forte 		status = HBA_GetAdapterName(adapterIndex, (char *)&name);
1580*fcf3ce44SJohn Forte 		if (status != HBA_STATUS_OK) {
1581*fcf3ce44SJohn Forte 		    /* May have been DR'd */
1582*fcf3ce44SJohn Forte 		    continue;
1583*fcf3ce44SJohn Forte 		}
1584*fcf3ce44SJohn Forte 		handle = HBA_OpenAdapter(name);
1585*fcf3ce44SJohn Forte 		if (handle == 0) {
1586*fcf3ce44SJohn Forte 		    /* May have been DR'd */
1587*fcf3ce44SJohn Forte 		    continue;
1588*fcf3ce44SJohn Forte 		}
1589*fcf3ce44SJohn Forte 		if (getAdapterAttrs(handle, name, &hbaAttrs)) {
1590*fcf3ce44SJohn Forte 		    /* Should never happen */
1591*fcf3ce44SJohn Forte 		    HBA_CloseAdapter(handle);
1592*fcf3ce44SJohn Forte 		    continue;
1593*fcf3ce44SJohn Forte 		}
1594*fcf3ce44SJohn Forte 
1595*fcf3ce44SJohn Forte 		/* Loop over all HBA Ports */
1596*fcf3ce44SJohn Forte 		for (portIndex = 0; portIndex < hbaAttrs.NumberOfPorts;
1597*fcf3ce44SJohn Forte 			portIndex++) {
1598*fcf3ce44SJohn Forte 		    int	    matched = 0;
1599*fcf3ce44SJohn Forte 		    int	    mapIndex;
1600*fcf3ce44SJohn Forte 		    char	    *tmp;
1601*fcf3ce44SJohn Forte 		    if (getAdapterPortAttrs(handle, name, portIndex,
1602*fcf3ce44SJohn Forte 			    &portAttrs)) {
1603*fcf3ce44SJohn Forte 			continue;
1604*fcf3ce44SJohn Forte 		    }
1605*fcf3ce44SJohn Forte 
1606*fcf3ce44SJohn Forte 		    if (fetch_mappings(handle, portAttrs.PortWWN, &map)) {
1607*fcf3ce44SJohn Forte 			continue;
1608*fcf3ce44SJohn Forte 		    }
1609*fcf3ce44SJohn Forte 
1610*fcf3ce44SJohn Forte 
1611*fcf3ce44SJohn Forte 
1612*fcf3ce44SJohn Forte 		    for (mapIndex = 0; mapIndex < map->NumberOfEntries;
1613*fcf3ce44SJohn Forte 			    mapIndex ++) {
1614*fcf3ce44SJohn Forte 			matched = 0;
1615*fcf3ce44SJohn Forte 			if (wwnCompare) {
1616*fcf3ce44SJohn Forte 			    if (wwn == wwnConversion(
1617*fcf3ce44SJohn Forte 				    map->entry[mapIndex].FcpId.NodeWWN.wwn) ||
1618*fcf3ce44SJohn Forte 				    wwn == wwnConversion(
1619*fcf3ce44SJohn Forte 				    map->entry[mapIndex].FcpId.PortWWN.wwn)) {
1620*fcf3ce44SJohn Forte 				matched = 1;
1621*fcf3ce44SJohn Forte 			    }
1622*fcf3ce44SJohn Forte 			} else {
1623*fcf3ce44SJohn Forte 			    tmp = get_slash_devices_from_osDevName(
1624*fcf3ce44SJohn Forte 				    map->entry[mapIndex].ScsiId.OSDeviceName,
1625*fcf3ce44SJohn Forte 				    STANDARD_DEVNAME_HANDLING);
1626*fcf3ce44SJohn Forte 			    if ((tmp != NULL) && (strncmp(physical, tmp,
1627*fcf3ce44SJohn Forte 				    MAXPATHLEN) == 0)) {
1628*fcf3ce44SJohn Forte 				matched = 1;
1629*fcf3ce44SJohn Forte 				free(tmp);
1630*fcf3ce44SJohn Forte 			    }
1631*fcf3ce44SJohn Forte 			}
1632*fcf3ce44SJohn Forte 			if (matched && head == NULL) {
1633*fcf3ce44SJohn Forte 			    goodPath = B_TRUE;
1634*fcf3ce44SJohn Forte 			    head  = (struct lun_tracking *)calloc(1,
1635*fcf3ce44SJohn Forte 				    sizeof (struct lun_tracking));
1636*fcf3ce44SJohn Forte 			    (void) memcpy(&head->map, &map->entry[mapIndex],
1637*fcf3ce44SJohn Forte 				    sizeof (head->map));
1638*fcf3ce44SJohn Forte 			    (void) memcpy(&head->hba_pwwn, &portAttrs.PortWWN,
1639*fcf3ce44SJohn Forte 				    sizeof (head->hba_pwwn));
1640*fcf3ce44SJohn Forte 			    (void) snprintf(head->hba_path, MAXPATHLEN,
1641*fcf3ce44SJohn Forte 				portAttrs.OSDeviceName);
1642*fcf3ce44SJohn Forte 			    scsi_vhci_details(head);
1643*fcf3ce44SJohn Forte 			} else if (matched) {
1644*fcf3ce44SJohn Forte 			    goodPath = B_TRUE;
1645*fcf3ce44SJohn Forte 			    add_lun_path(head, &map->entry[mapIndex],
1646*fcf3ce44SJohn Forte 				portAttrs.PortWWN, portAttrs.OSDeviceName);
1647*fcf3ce44SJohn Forte 			}
1648*fcf3ce44SJohn Forte 		    }
1649*fcf3ce44SJohn Forte 		}
1650*fcf3ce44SJohn Forte 	    }
1651*fcf3ce44SJohn Forte 
1652*fcf3ce44SJohn Forte 	    if (physical) {
1653*fcf3ce44SJohn Forte 		free(physical);
1654*fcf3ce44SJohn Forte 	    }
1655*fcf3ce44SJohn Forte 
1656*fcf3ce44SJohn Forte 	    /* Now do it again and look for matching LUIDs (aka GUIDs) */
1657*fcf3ce44SJohn Forte 	    for (adapterIndex = 0; adapterIndex < count; adapterIndex ++) {
1658*fcf3ce44SJohn Forte 		if (skip_hba(adapterIndex)) {
1659*fcf3ce44SJohn Forte 		    continue;
1660*fcf3ce44SJohn Forte 		}
1661*fcf3ce44SJohn Forte 		status = HBA_GetAdapterName(adapterIndex, (char *)&name);
1662*fcf3ce44SJohn Forte 		if (status != HBA_STATUS_OK) {
1663*fcf3ce44SJohn Forte 		    /* May have been DR'd */
1664*fcf3ce44SJohn Forte 		    continue;
1665*fcf3ce44SJohn Forte 		}
1666*fcf3ce44SJohn Forte 		handle = HBA_OpenAdapter(name);
1667*fcf3ce44SJohn Forte 		if (handle == 0) {
1668*fcf3ce44SJohn Forte 		    /* May have been DR'd */
1669*fcf3ce44SJohn Forte 		    continue;
1670*fcf3ce44SJohn Forte 		}
1671*fcf3ce44SJohn Forte 
1672*fcf3ce44SJohn Forte 		if (getAdapterAttrs(handle, name, &hbaAttrs)) {
1673*fcf3ce44SJohn Forte 		    /* Should never happen */
1674*fcf3ce44SJohn Forte 		    HBA_CloseAdapter(handle);
1675*fcf3ce44SJohn Forte 		    continue;
1676*fcf3ce44SJohn Forte 		}
1677*fcf3ce44SJohn Forte 
1678*fcf3ce44SJohn Forte 
1679*fcf3ce44SJohn Forte 		/* Loop over all HBA Ports */
1680*fcf3ce44SJohn Forte 		for (portIndex = 0; portIndex < hbaAttrs.NumberOfPorts;
1681*fcf3ce44SJohn Forte 			portIndex++) {
1682*fcf3ce44SJohn Forte 		    int	    matched = 0;
1683*fcf3ce44SJohn Forte 		    int	    mapIndex;
1684*fcf3ce44SJohn Forte 		    if (getAdapterPortAttrs(handle, name, portIndex,
1685*fcf3ce44SJohn Forte 			    &portAttrs)) {
1686*fcf3ce44SJohn Forte 			continue;
1687*fcf3ce44SJohn Forte 		    }
1688*fcf3ce44SJohn Forte 
1689*fcf3ce44SJohn Forte 		    if (fetch_mappings(handle, portAttrs.PortWWN, &map)) {
1690*fcf3ce44SJohn Forte 			continue;
1691*fcf3ce44SJohn Forte 		    }
1692*fcf3ce44SJohn Forte 
1693*fcf3ce44SJohn Forte 
1694*fcf3ce44SJohn Forte 		    for (mapIndex = 0; mapIndex < map->NumberOfEntries;
1695*fcf3ce44SJohn Forte 			    mapIndex ++) {
1696*fcf3ce44SJohn Forte 			struct lun_tracking *outer;
1697*fcf3ce44SJohn Forte 			matched = 0;
1698*fcf3ce44SJohn Forte 			for (outer = head; outer != NULL;
1699*fcf3ce44SJohn Forte 				    outer = outer->next_lun) {
1700*fcf3ce44SJohn Forte 			    struct lun_tracking *inner;
1701*fcf3ce44SJohn Forte 			    for (inner = outer; inner != NULL;
1702*fcf3ce44SJohn Forte 				    inner = inner->next_path) {
1703*fcf3ce44SJohn Forte 				if (memcmp(&inner->map.LUID,
1704*fcf3ce44SJohn Forte 					&map->entry[mapIndex].LUID,
1705*fcf3ce44SJohn Forte 					sizeof (HBA_LUID)) == 0) {
1706*fcf3ce44SJohn Forte 				    matched = 1;
1707*fcf3ce44SJohn Forte 				    break;
1708*fcf3ce44SJohn Forte 				}
1709*fcf3ce44SJohn Forte 			    }
1710*fcf3ce44SJohn Forte 			    if (matched) {
1711*fcf3ce44SJohn Forte 				break;
1712*fcf3ce44SJohn Forte 			    }
1713*fcf3ce44SJohn Forte 			}
1714*fcf3ce44SJohn Forte 			if (matched && head == NULL) {
1715*fcf3ce44SJohn Forte 			    goodPath = B_TRUE;
1716*fcf3ce44SJohn Forte 			    head  = (struct lun_tracking *)calloc(1,
1717*fcf3ce44SJohn Forte 				    sizeof (struct lun_tracking));
1718*fcf3ce44SJohn Forte 			    (void) memcpy(&head->map, &map->entry[mapIndex],
1719*fcf3ce44SJohn Forte 				    sizeof (head->map));
1720*fcf3ce44SJohn Forte 			    (void) memcpy(&head->hba_pwwn, &portAttrs.PortWWN,
1721*fcf3ce44SJohn Forte 				    sizeof (head->hba_pwwn));
1722*fcf3ce44SJohn Forte 			    (void) snprintf(head->hba_path, MAXPATHLEN,
1723*fcf3ce44SJohn Forte 				portAttrs.OSDeviceName);
1724*fcf3ce44SJohn Forte 			    scsi_vhci_details(head);
1725*fcf3ce44SJohn Forte 			} else if (matched) {
1726*fcf3ce44SJohn Forte 			    goodPath = B_TRUE;
1727*fcf3ce44SJohn Forte 			    add_lun_path(head, &map->entry[mapIndex],
1728*fcf3ce44SJohn Forte 				portAttrs.PortWWN, portAttrs.OSDeviceName);
1729*fcf3ce44SJohn Forte 			}
1730*fcf3ce44SJohn Forte 		    }
1731*fcf3ce44SJohn Forte 		}
1732*fcf3ce44SJohn Forte 	    }
1733*fcf3ce44SJohn Forte 	    if (!goodPath) {
1734*fcf3ce44SJohn Forte 		fprintf(stderr, MSGSTR(112, "Error: Invalid pathname (%s)"),
1735*fcf3ce44SJohn Forte 			argv[path_index]);
1736*fcf3ce44SJohn Forte 		fprintf(stderr, "\n");
1737*fcf3ce44SJohn Forte 		ret = -1;
1738*fcf3ce44SJohn Forte 		/* Just bomb out instead of going on */
1739*fcf3ce44SJohn Forte 		return (ret);
1740*fcf3ce44SJohn Forte 	    }
1741*fcf3ce44SJohn Forte 	}
1742*fcf3ce44SJohn Forte 
1743*fcf3ce44SJohn Forte 	/* Now display all the LUNs that we found that matched */
1744*fcf3ce44SJohn Forte 	{
1745*fcf3ce44SJohn Forte 	    struct lun_tracking *first_time;
1746*fcf3ce44SJohn Forte 	    struct lun_tracking *tmp_path;
1747*fcf3ce44SJohn Forte 	    for (first_time = head; first_time != NULL;
1748*fcf3ce44SJohn Forte 		    first_time = first_time->next_lun) {
1749*fcf3ce44SJohn Forte 		struct lun_tracking *path;
1750*fcf3ce44SJohn Forte 		phys_path = get_slash_devices_from_osDevName(
1751*fcf3ce44SJohn Forte 		    first_time->map.ScsiId.OSDeviceName,
1752*fcf3ce44SJohn Forte 		    STANDARD_DEVNAME_HANDLING);
1753*fcf3ce44SJohn Forte 		/* Change behavior if this is an MPxIO device */
1754*fcf3ce44SJohn Forte 		if (phys_path != NULL) {
1755*fcf3ce44SJohn Forte 		    if (strstr(phys_path, VHCI_COMPONENT) != NULL) {
1756*fcf3ce44SJohn Forte 			mpxio = 1;
1757*fcf3ce44SJohn Forte 		    }
1758*fcf3ce44SJohn Forte 		}
1759*fcf3ce44SJohn Forte 
1760*fcf3ce44SJohn Forte 		for (tmp_path = first_time; tmp_path != NULL;
1761*fcf3ce44SJohn Forte 			tmp_path = tmp_path->next_path) {
1762*fcf3ce44SJohn Forte 			if (mpxio && (strncmp(tmp_path->info.pathState,
1763*fcf3ce44SJohn Forte 			    "ONLINE", strlen(tmp_path->info.pathState)))) {
1764*fcf3ce44SJohn Forte 				/* continue to next online path */
1765*fcf3ce44SJohn Forte 				continue;
1766*fcf3ce44SJohn Forte 			}
1767*fcf3ce44SJohn Forte 			status = HBA_OpenAdapterByWWN(&handle,
1768*fcf3ce44SJohn Forte 			    tmp_path->hba_pwwn);
1769*fcf3ce44SJohn Forte 			if (status != HBA_STATUS_OK) {
1770*fcf3ce44SJohn Forte 				fprintf(stderr, MSGSTR(2431,
1771*fcf3ce44SJohn Forte 				    "Error: Failed to get handle for %s  "),
1772*fcf3ce44SJohn Forte 				    tmp_path->hba_path);
1773*fcf3ce44SJohn Forte 				printStatus(status);
1774*fcf3ce44SJohn Forte 				fprintf(stderr, "\n");
1775*fcf3ce44SJohn Forte 				/* continue to next path */
1776*fcf3ce44SJohn Forte 				continue;
1777*fcf3ce44SJohn Forte 			}
1778*fcf3ce44SJohn Forte 
1779*fcf3ce44SJohn Forte 			lun = tmp_path->map.FcpId.FcpLun;
1780*fcf3ce44SJohn Forte 			memset(&inq, 0, sizeof (inq));
1781*fcf3ce44SJohn Forte 			memset(&sense, 0, sizeof (sense));
1782*fcf3ce44SJohn Forte 
1783*fcf3ce44SJohn Forte 			status = HBA_ScsiInquiryV2(handle,
1784*fcf3ce44SJohn Forte 				tmp_path->hba_pwwn,
1785*fcf3ce44SJohn Forte 				tmp_path->map.FcpId.PortWWN,
1786*fcf3ce44SJohn Forte 				lun, 0, 0,
1787*fcf3ce44SJohn Forte 				&inq, &inquirySize,
1788*fcf3ce44SJohn Forte 				&scsiStatus,
1789*fcf3ce44SJohn Forte 				&sense, &senseSize);
1790*fcf3ce44SJohn Forte 
1791*fcf3ce44SJohn Forte 			if (status == HBA_STATUS_OK) {
1792*fcf3ce44SJohn Forte 				break;
1793*fcf3ce44SJohn Forte 			}
1794*fcf3ce44SJohn Forte 			HBA_CloseAdapter(handle);
1795*fcf3ce44SJohn Forte 		}
1796*fcf3ce44SJohn Forte 
1797*fcf3ce44SJohn Forte 		if (tmp_path == NULL) {
1798*fcf3ce44SJohn Forte 			fprintf(stderr, MSGSTR(2430,
1799*fcf3ce44SJohn Forte 			    "Error: I/O failure communicating with %s  "),
1800*fcf3ce44SJohn Forte 			    first_time->map.ScsiId.OSDeviceName);
1801*fcf3ce44SJohn Forte 			printStatus(status);
1802*fcf3ce44SJohn Forte 			fprintf(stderr, "\n");
1803*fcf3ce44SJohn Forte 			continue;
1804*fcf3ce44SJohn Forte 		}
1805*fcf3ce44SJohn Forte 
1806*fcf3ce44SJohn Forte 		switch ((inq.inq_dtype & DTYPE_MASK)) {
1807*fcf3ce44SJohn Forte 		case DTYPE_DIRECT:
1808*fcf3ce44SJohn Forte 		    fprintf(stdout, MSGSTR(121,
1809*fcf3ce44SJohn Forte 			    "DEVICE PROPERTIES for disk: %s\n"),
1810*fcf3ce44SJohn Forte 			    first_time->map.ScsiId.OSDeviceName);
1811*fcf3ce44SJohn Forte 		    break;
1812*fcf3ce44SJohn Forte 		case DTYPE_SEQUENTIAL: /* Tape */
1813*fcf3ce44SJohn Forte 		    fprintf(stdout, MSGSTR(2249,
1814*fcf3ce44SJohn Forte 			    "DEVICE PROPERTIES for tape: %s\n"),
1815*fcf3ce44SJohn Forte 			    first_time->map.ScsiId.OSDeviceName);
1816*fcf3ce44SJohn Forte 		    break;
1817*fcf3ce44SJohn Forte 		default:
1818*fcf3ce44SJohn Forte 		    fprintf(stdout, MSGSTR(2250,
1819*fcf3ce44SJohn Forte 			    "DEVICE PROPERTIES for: %s\n"),
1820*fcf3ce44SJohn Forte 			    first_time->map.ScsiId.OSDeviceName);
1821*fcf3ce44SJohn Forte 		    break;
1822*fcf3ce44SJohn Forte 		}
1823*fcf3ce44SJohn Forte 		fprintf(stdout, "  ");
1824*fcf3ce44SJohn Forte 		fprintf(stdout, MSGSTR(3, "Vendor:"));
1825*fcf3ce44SJohn Forte 		fprintf(stdout, "\t\t");
1826*fcf3ce44SJohn Forte 		print_chars(inq.inq_vid, sizeof (inq.inq_vid), 0);
1827*fcf3ce44SJohn Forte 		fprintf(stdout, MSGSTR(2115, "\n  Product ID:\t\t"));
1828*fcf3ce44SJohn Forte 		print_chars(inq.inq_pid, sizeof (inq.inq_pid), 0);
1829*fcf3ce44SJohn Forte 
1830*fcf3ce44SJohn Forte 		fprintf(stdout, "\n  ");
1831*fcf3ce44SJohn Forte 		fprintf(stdout, MSGSTR(2119, "Revision:"));
1832*fcf3ce44SJohn Forte 		fprintf(stdout, "\t\t");
1833*fcf3ce44SJohn Forte 		print_chars(inq.inq_revision, sizeof (inq.inq_revision), 0);
1834*fcf3ce44SJohn Forte 
1835*fcf3ce44SJohn Forte 		fprintf(stdout, "\n  ");
1836*fcf3ce44SJohn Forte 		fprintf(stdout, MSGSTR(17, "Serial Num:"));
1837*fcf3ce44SJohn Forte 		fprintf(stdout, "\t\t");
1838*fcf3ce44SJohn Forte 		(void) fflush(stdout);
1839*fcf3ce44SJohn Forte 		/*
1840*fcf3ce44SJohn Forte 		 * Call the inquiry cmd on page 0x80 only if the vendor
1841*fcf3ce44SJohn Forte 		 * supports page 0x80.
1842*fcf3ce44SJohn Forte 		 */
1843*fcf3ce44SJohn Forte 		if ((find_supported_inq_page(handle, first_time->hba_pwwn,
1844*fcf3ce44SJohn Forte 		    first_time->map.FcpId.PortWWN, lun, 0x80))) {
1845*fcf3ce44SJohn Forte 			memset(&serial, 0, sizeof (serial));
1846*fcf3ce44SJohn Forte 			status = HBA_ScsiInquiryV2(handle,
1847*fcf3ce44SJohn Forte 			    first_time->hba_pwwn,
1848*fcf3ce44SJohn Forte 			    first_time->map.FcpId.PortWWN,
1849*fcf3ce44SJohn Forte 			    lun, 1, 0x80,
1850*fcf3ce44SJohn Forte 			    &serial, &serialSize,
1851*fcf3ce44SJohn Forte 			    &scsiStatus,
1852*fcf3ce44SJohn Forte 			    &sense, &senseSize);
1853*fcf3ce44SJohn Forte 			if (status == HBA_STATUS_OK) {
1854*fcf3ce44SJohn Forte 				print_chars(serial.inq_serial,
1855*fcf3ce44SJohn Forte 				    sizeof (serial.inq_serial), 0);
1856*fcf3ce44SJohn Forte 			} else {
1857*fcf3ce44SJohn Forte 				fprintf(stdout, MSGSTR(2506, "Unsupported"));
1858*fcf3ce44SJohn Forte 			}
1859*fcf3ce44SJohn Forte 		} else {
1860*fcf3ce44SJohn Forte 			fprintf(stdout, MSGSTR(2506, "Unsupported"));
1861*fcf3ce44SJohn Forte 		}
1862*fcf3ce44SJohn Forte 		HBA_CloseAdapter(handle);
1863*fcf3ce44SJohn Forte 		if ((inq.inq_dtype & DTYPE_MASK) == DTYPE_DIRECT) {
1864*fcf3ce44SJohn Forte 		/* Read capacity wont work on standby paths, so try till OK */
1865*fcf3ce44SJohn Forte 		    for (tmp_path = first_time; tmp_path != NULL;
1866*fcf3ce44SJohn Forte 			tmp_path = tmp_path->next_path) {
1867*fcf3ce44SJohn Forte 			if (mpxio && (strncmp(tmp_path->info.pathState,
1868*fcf3ce44SJohn Forte 			    "ONLINE", strlen(tmp_path->info.pathState)))) {
1869*fcf3ce44SJohn Forte 			    /* continue to next online path */
1870*fcf3ce44SJohn Forte 			    continue;
1871*fcf3ce44SJohn Forte 			}
1872*fcf3ce44SJohn Forte 			status = HBA_OpenAdapterByWWN(&handle,
1873*fcf3ce44SJohn Forte 						tmp_path->hba_pwwn);
1874*fcf3ce44SJohn Forte 			if (status != HBA_STATUS_OK) {
1875*fcf3ce44SJohn Forte 			    /* continue to next path */
1876*fcf3ce44SJohn Forte 			    continue;
1877*fcf3ce44SJohn Forte 			}
1878*fcf3ce44SJohn Forte 
1879*fcf3ce44SJohn Forte 			status = HBA_ScsiReadCapacityV2(handle,
1880*fcf3ce44SJohn Forte 			    tmp_path->hba_pwwn,
1881*fcf3ce44SJohn Forte 			    tmp_path->map.FcpId.PortWWN,
1882*fcf3ce44SJohn Forte 			    tmp_path->map.FcpId.FcpLun,
1883*fcf3ce44SJohn Forte 			    &cap_data, &cap_data_size,
1884*fcf3ce44SJohn Forte 			    &scsiStatus,
1885*fcf3ce44SJohn Forte 			    &sense, &senseSize);
1886*fcf3ce44SJohn Forte 			if (status == HBA_STATUS_OK) {
1887*fcf3ce44SJohn Forte 			    break;
1888*fcf3ce44SJohn Forte 			} else if (status == HBA_STATUS_SCSI_CHECK_CONDITION &&
1889*fcf3ce44SJohn Forte 			    sense.es_key == KEY_UNIT_ATTENTION) {
1890*fcf3ce44SJohn Forte 			/*
1891*fcf3ce44SJohn Forte 			 * retry for check-condition state when unit attention
1892*fcf3ce44SJohn Forte 			 * condition has been established
1893*fcf3ce44SJohn Forte 			 */
1894*fcf3ce44SJohn Forte 			    status =  HBA_ScsiReadCapacityV2(handle,
1895*fcf3ce44SJohn Forte 				tmp_path->hba_pwwn,
1896*fcf3ce44SJohn Forte 				tmp_path->map.FcpId.PortWWN,
1897*fcf3ce44SJohn Forte 				tmp_path->map.FcpId.FcpLun,
1898*fcf3ce44SJohn Forte 				&cap_data, &cap_data_size,
1899*fcf3ce44SJohn Forte 				&scsiStatus,
1900*fcf3ce44SJohn Forte 				&sense, &senseSize);
1901*fcf3ce44SJohn Forte 			    if (status == HBA_STATUS_OK) {
1902*fcf3ce44SJohn Forte 				break;
1903*fcf3ce44SJohn Forte 			    }
1904*fcf3ce44SJohn Forte 			}
1905*fcf3ce44SJohn Forte 			HBA_CloseAdapter(handle);
1906*fcf3ce44SJohn Forte 		    }
1907*fcf3ce44SJohn Forte 		}
1908*fcf3ce44SJohn Forte 		if (handle != HBA_HANDLE_INVALID) {
1909*fcf3ce44SJohn Forte 			HBA_CloseAdapter(handle);
1910*fcf3ce44SJohn Forte 		}
1911*fcf3ce44SJohn Forte 		if (status != HBA_STATUS_OK) {
1912*fcf3ce44SJohn Forte 		    /* Make sure we don't display garbage */
1913*fcf3ce44SJohn Forte 		    cap_data.block_size = 0;
1914*fcf3ce44SJohn Forte 		    cap_data.last_block_addr = 0;
1915*fcf3ce44SJohn Forte 		}
1916*fcf3ce44SJohn Forte 
1917*fcf3ce44SJohn Forte 		if (cap_data.block_size > 0 &&
1918*fcf3ce44SJohn Forte 			cap_data.last_block_addr > 0) {
1919*fcf3ce44SJohn Forte 		    lunMbytes = ntohl(cap_data.last_block_addr) + 1;
1920*fcf3ce44SJohn Forte 		    lunMbytes *= ntohl(cap_data.block_size);
1921*fcf3ce44SJohn Forte 		    lunMbytes /= (float)(1024*1024);
1922*fcf3ce44SJohn Forte 		    fprintf(stdout, "\n  ");
1923*fcf3ce44SJohn Forte 		    fprintf(stdout, MSGSTR(60,
1924*fcf3ce44SJohn Forte 			    "Unformatted capacity:\t%6.3f MBytes"), lunMbytes);
1925*fcf3ce44SJohn Forte 		}
1926*fcf3ce44SJohn Forte 		fprintf(stdout, "\n");
1927*fcf3ce44SJohn Forte 
1928*fcf3ce44SJohn Forte 		/*
1929*fcf3ce44SJohn Forte 		 * get mode page information for FC device.
1930*fcf3ce44SJohn Forte 		 * do not do mode sense if this is a tape device.
1931*fcf3ce44SJohn Forte 		 * mode sense will rewind the tape
1932*fcf3ce44SJohn Forte 		 */
1933*fcf3ce44SJohn Forte 		if ((inq.inq_dtype & DTYPE_MASK) != DTYPE_SEQUENTIAL) {
1934*fcf3ce44SJohn Forte 		    if (get_mode_page(first_time->map.ScsiId.OSDeviceName,
1935*fcf3ce44SJohn Forte 			&pg_buf) == 0) {
1936*fcf3ce44SJohn Forte 			mode_header_ptr = (struct mode_header_g1 *)
1937*fcf3ce44SJohn Forte 				(void *)pg_buf;
1938*fcf3ce44SJohn Forte 			offset = sizeof (struct mode_header_g1) +
1939*fcf3ce44SJohn Forte 			    ntohs(mode_header_ptr->bdesc_length);
1940*fcf3ce44SJohn Forte 			pg_hdr = (struct mode_page *)&pg_buf[offset];
1941*fcf3ce44SJohn Forte 
1942*fcf3ce44SJohn Forte 			while (offset < (ntohs(mode_header_ptr->length) +
1943*fcf3ce44SJohn Forte 			    sizeof (mode_header_ptr->length))) {
1944*fcf3ce44SJohn Forte 			    if (pg_hdr->code == MODEPAGE_CACHING) {
1945*fcf3ce44SJohn Forte 				struct	mode_caching	*pg8_buf;
1946*fcf3ce44SJohn Forte 				pg8_buf = (struct mode_caching *)
1947*fcf3ce44SJohn Forte 				    (void *)pg_hdr;
1948*fcf3ce44SJohn Forte 				if (pg8_buf->wce) {
1949*fcf3ce44SJohn Forte 				    fprintf(stdout, MSGSTR(2122,
1950*fcf3ce44SJohn Forte 					"  Write Cache:\t\t"
1951*fcf3ce44SJohn Forte 					"Enabled\n"));
1952*fcf3ce44SJohn Forte 				}
1953*fcf3ce44SJohn Forte 				if (pg8_buf->rcd == 0) {
1954*fcf3ce44SJohn Forte 				    fprintf(stdout, MSGSTR(2123,
1955*fcf3ce44SJohn Forte 					"  Read Cache:\t\t"
1956*fcf3ce44SJohn Forte 					"Enabled\n"));
1957*fcf3ce44SJohn Forte 				    fprintf(stdout, MSGSTR(2509,
1958*fcf3ce44SJohn Forte 					"    Minimum prefetch:\t0x%x\n"
1959*fcf3ce44SJohn Forte 					"    Maximum prefetch:\t0x%x\n"),
1960*fcf3ce44SJohn Forte 					pg8_buf->min_prefetch,
1961*fcf3ce44SJohn Forte 					pg8_buf->max_prefetch);
1962*fcf3ce44SJohn Forte 				}
1963*fcf3ce44SJohn Forte 				break;
1964*fcf3ce44SJohn Forte 			    }
1965*fcf3ce44SJohn Forte 			    offset += pg_hdr->length +
1966*fcf3ce44SJohn Forte 				sizeof (struct mode_page);
1967*fcf3ce44SJohn Forte 			    pg_hdr = (struct mode_page *)&pg_buf[offset];
1968*fcf3ce44SJohn Forte 			}
1969*fcf3ce44SJohn Forte 		    }
1970*fcf3ce44SJohn Forte 		}
1971*fcf3ce44SJohn Forte 
1972*fcf3ce44SJohn Forte 		fprintf(stdout, "  %s\t\t", MSGSTR(35, "Device Type:"));
1973*fcf3ce44SJohn Forte 		if ((inq.inq_dtype & DTYPE_MASK) < 0x10) {
1974*fcf3ce44SJohn Forte 			fprintf(stdout, "%s\n",
1975*fcf3ce44SJohn Forte 			    dtype[inq.inq_dtype & DTYPE_MASK]);
1976*fcf3ce44SJohn Forte 		} else if ((inq.inq_dtype & DTYPE_MASK) < 0x1f) {
1977*fcf3ce44SJohn Forte 			fprintf(stdout, MSGSTR(2432, "Reserved"));
1978*fcf3ce44SJohn Forte 		} else {
1979*fcf3ce44SJohn Forte 			/* dtype of 0x1f is returned */
1980*fcf3ce44SJohn Forte 			fprintf(stdout, MSGSTR(2433, "Unknown"));
1981*fcf3ce44SJohn Forte 		}
1982*fcf3ce44SJohn Forte 
1983*fcf3ce44SJohn Forte 		fprintf(stdout, MSGSTR(2128, "  Path(s):\n"));
1984*fcf3ce44SJohn Forte 		fprintf(stdout, "\n");
1985*fcf3ce44SJohn Forte 		fprintf(stdout, "  %s\n",
1986*fcf3ce44SJohn Forte 		    first_time->map.ScsiId.OSDeviceName);
1987*fcf3ce44SJohn Forte 		if (phys_path != NULL) {
1988*fcf3ce44SJohn Forte 		    fprintf(stdout, "  %s\n", phys_path);
1989*fcf3ce44SJohn Forte 		}
1990*fcf3ce44SJohn Forte 
1991*fcf3ce44SJohn Forte 		/* Now display all paths to this LUN */
1992*fcf3ce44SJohn Forte 		for (path = first_time; path != NULL;
1993*fcf3ce44SJohn Forte 		    path = path->next_path) {
1994*fcf3ce44SJohn Forte 		    /* Display the controller information */
1995*fcf3ce44SJohn Forte 		    fprintf(stdout, MSGSTR(2303, "   Controller      \t%s\n"),
1996*fcf3ce44SJohn Forte 			    path->hba_path);
1997*fcf3ce44SJohn Forte 
1998*fcf3ce44SJohn Forte 		    fprintf(stdout, MSGSTR(2507,
1999*fcf3ce44SJohn Forte 			    "    Device Address\t\t%016llx,%x\n"),
2000*fcf3ce44SJohn Forte 			    wwnConversion(
2001*fcf3ce44SJohn Forte 			    path->map.FcpId.PortWWN.wwn),
2002*fcf3ce44SJohn Forte 			    path->map.ScsiId.ScsiOSLun);
2003*fcf3ce44SJohn Forte 
2004*fcf3ce44SJohn Forte 		    fprintf(stdout, MSGSTR(2508,
2005*fcf3ce44SJohn Forte 			    "    Host controller port WWN\t%016llx\n"),
2006*fcf3ce44SJohn Forte 			    wwnConversion(path->hba_pwwn.wwn));
2007*fcf3ce44SJohn Forte 
2008*fcf3ce44SJohn Forte 		    if (mpxio) {
2009*fcf3ce44SJohn Forte 			fprintf(stdout, MSGSTR(2305,
2010*fcf3ce44SJohn Forte 				"    Class\t\t\t%s\n"), path->info.pathClass);
2011*fcf3ce44SJohn Forte 			fprintf(stdout, MSGSTR(2306,
2012*fcf3ce44SJohn Forte 				"    State\t\t\t%s\n"), path->info.pathState);
2013*fcf3ce44SJohn Forte 		    }
2014*fcf3ce44SJohn Forte 		    if (phys_path != NULL) {
2015*fcf3ce44SJohn Forte 			free(phys_path);
2016*fcf3ce44SJohn Forte 			phys_path = NULL;
2017*fcf3ce44SJohn Forte 		    }
2018*fcf3ce44SJohn Forte 		}
2019*fcf3ce44SJohn Forte 		printf("\n");
2020*fcf3ce44SJohn Forte 	    }
2021*fcf3ce44SJohn Forte 	}
2022*fcf3ce44SJohn Forte 	return (ret);
2023*fcf3ce44SJohn Forte }
2024*fcf3ce44SJohn Forte 
2025*fcf3ce44SJohn Forte /*
2026*fcf3ce44SJohn Forte  * handle expert-mode hotplug commands
2027*fcf3ce44SJohn Forte  *
2028*fcf3ce44SJohn Forte  * return 0 iff all is okay
2029*fcf3ce44SJohn Forte  */
2030*fcf3ce44SJohn Forte int
fchba_hotplug_e(int todo,char ** argv,int verbose_flag,int force_flag)2031*fcf3ce44SJohn Forte fchba_hotplug_e(int todo, char **argv, int verbose_flag, int force_flag)
2032*fcf3ce44SJohn Forte {
2033*fcf3ce44SJohn Forte char		*path_phys = NULL;
2034*fcf3ce44SJohn Forte int		exit_code;
2035*fcf3ce44SJohn Forte devctl_hdl_t	dcp;
2036*fcf3ce44SJohn Forte 
2037*fcf3ce44SJohn Forte 	if (todo != DEV_ONLINE &&
2038*fcf3ce44SJohn Forte 	    todo != DEV_OFFLINE) {
2039*fcf3ce44SJohn Forte 	    fprintf(stderr, "%s\n", strerror(ENOTSUP));
2040*fcf3ce44SJohn Forte 	    return (-1);
2041*fcf3ce44SJohn Forte 	}
2042*fcf3ce44SJohn Forte 
2043*fcf3ce44SJohn Forte 	/* Convert the paths to phsyical paths */
2044*fcf3ce44SJohn Forte 	path_phys = get_slash_devices_from_osDevName(argv[0],
2045*fcf3ce44SJohn Forte 		NOT_IGNORE_DANGLING_LINK);
2046*fcf3ce44SJohn Forte 	if (!path_phys) {
2047*fcf3ce44SJohn Forte 	    fprintf(stderr, MSGSTR(112,
2048*fcf3ce44SJohn Forte 		"Error: Invalid pathname (%s)"),
2049*fcf3ce44SJohn Forte 		argv[0]);
2050*fcf3ce44SJohn Forte 	    fprintf(stderr, "\n");
2051*fcf3ce44SJohn Forte 	    return (-1);
2052*fcf3ce44SJohn Forte 	}
2053*fcf3ce44SJohn Forte 	if (verbose_flag) {
2054*fcf3ce44SJohn Forte 		(void) fprintf(stdout,
2055*fcf3ce44SJohn Forte 				MSGSTR(5516,
2056*fcf3ce44SJohn Forte 				"phys path = \"%s\"\n"),
2057*fcf3ce44SJohn Forte 				path_phys);
2058*fcf3ce44SJohn Forte 	}
2059*fcf3ce44SJohn Forte 	/* acquire rights to hack on device */
2060*fcf3ce44SJohn Forte 	if ((dcp = devctl_device_acquire(path_phys,
2061*fcf3ce44SJohn Forte 		force_flag ? 0 : DC_EXCL)) == NULL) {
2062*fcf3ce44SJohn Forte 
2063*fcf3ce44SJohn Forte 		(void) fprintf(stderr, MSGSTR(5517,
2064*fcf3ce44SJohn Forte 		    "Error: can't acquire \"%s\": %s\n"),
2065*fcf3ce44SJohn Forte 		    path_phys, strerror(errno));
2066*fcf3ce44SJohn Forte 		return (1);
2067*fcf3ce44SJohn Forte 	}
2068*fcf3ce44SJohn Forte 
2069*fcf3ce44SJohn Forte 	switch (todo) {
2070*fcf3ce44SJohn Forte 	case DEV_ONLINE:
2071*fcf3ce44SJohn Forte 		exit_code = devctl_device_online(dcp);
2072*fcf3ce44SJohn Forte 		break;
2073*fcf3ce44SJohn Forte 	case DEV_OFFLINE:
2074*fcf3ce44SJohn Forte 		exit_code = devctl_device_offline(dcp);
2075*fcf3ce44SJohn Forte 		break;
2076*fcf3ce44SJohn Forte 	}
2077*fcf3ce44SJohn Forte 
2078*fcf3ce44SJohn Forte 	if (exit_code != 0) {
2079*fcf3ce44SJohn Forte 		perror(MSGSTR(5518, "devctl"));
2080*fcf3ce44SJohn Forte 	}
2081*fcf3ce44SJohn Forte 
2082*fcf3ce44SJohn Forte 	/* all done now -- release device */
2083*fcf3ce44SJohn Forte 	devctl_release(dcp);
2084*fcf3ce44SJohn Forte 
2085*fcf3ce44SJohn Forte 	if (path_phys) {
2086*fcf3ce44SJohn Forte 	    free(path_phys);
2087*fcf3ce44SJohn Forte 	}
2088*fcf3ce44SJohn Forte 
2089*fcf3ce44SJohn Forte 	return (exit_code);
2090*fcf3ce44SJohn Forte }
2091*fcf3ce44SJohn Forte 
2092*fcf3ce44SJohn Forte /*
2093*fcf3ce44SJohn Forte  * Returns non zero if we should use FC-HBA.
2094*fcf3ce44SJohn Forte  * For x86, luxadm uses FC-HBA.
2095*fcf3ce44SJohn Forte  */
2096*fcf3ce44SJohn Forte int
use_fchba()2097*fcf3ce44SJohn Forte use_fchba()
2098*fcf3ce44SJohn Forte {
2099*fcf3ce44SJohn Forte 
2100*fcf3ce44SJohn Forte #ifdef __x86
2101*fcf3ce44SJohn Forte 	return (1);
2102*fcf3ce44SJohn Forte #else
2103*fcf3ce44SJohn Forte 	return (0);
2104*fcf3ce44SJohn Forte #endif
2105*fcf3ce44SJohn Forte 
2106*fcf3ce44SJohn Forte }
2107*fcf3ce44SJohn Forte 
2108*fcf3ce44SJohn Forte /*
2109*fcf3ce44SJohn Forte  * Returns non-zero if we should skip the HBA at index "i"
2110*fcf3ce44SJohn Forte  */
2111*fcf3ce44SJohn Forte int
skip_hba(int i)2112*fcf3ce44SJohn Forte skip_hba(int i) {
2113*fcf3ce44SJohn Forte 	HBA_LIBRARYATTRIBUTES lib_attrs;
2114*fcf3ce44SJohn Forte 	(void) HBA_GetVendorLibraryAttributes(i, &lib_attrs);
2115*fcf3ce44SJohn Forte 	if (strncmp(lib_attrs.VName, VSL_NAME,
2116*fcf3ce44SJohn Forte 		sizeof (lib_attrs.VName)) == 0) {
2117*fcf3ce44SJohn Forte 	    return (0);
2118*fcf3ce44SJohn Forte 	}
2119*fcf3ce44SJohn Forte 	return (1);
2120*fcf3ce44SJohn Forte }
2121*fcf3ce44SJohn Forte 
2122*fcf3ce44SJohn Forte /*
2123*fcf3ce44SJohn Forte  * Function to determine if the given page is supported by vendor.
2124*fcf3ce44SJohn Forte  */
2125*fcf3ce44SJohn Forte int
find_supported_inq_page(HBA_HANDLE handle,HBA_WWN hwwn,HBA_WWN pwwn,uint64_t lun,int page_num)2126*fcf3ce44SJohn Forte find_supported_inq_page(HBA_HANDLE handle, HBA_WWN hwwn, HBA_WWN pwwn,
2127*fcf3ce44SJohn Forte     uint64_t lun, int page_num)
2128*fcf3ce44SJohn Forte {
2129*fcf3ce44SJohn Forte 	struct	scsi_extended_sense	sense;
2130*fcf3ce44SJohn Forte 	L_inquiry00			inq00;
2131*fcf3ce44SJohn Forte 	uchar_t				*data;
2132*fcf3ce44SJohn Forte 	HBA_STATUS			status = HBA_STATUS_ERROR;
2133*fcf3ce44SJohn Forte 	int				index;
2134*fcf3ce44SJohn Forte 	HBA_UINT8			scsiStatus;
2135*fcf3ce44SJohn Forte 	uint32_t			inqSize = sizeof (inq00);
2136*fcf3ce44SJohn Forte 	uint32_t			senseSize = sizeof (sense);
2137*fcf3ce44SJohn Forte 
2138*fcf3ce44SJohn Forte 	status = HBA_ScsiInquiryV2(handle, hwwn, pwwn, lun, 1, 0x00,
2139*fcf3ce44SJohn Forte 	    &inq00, &inqSize, &scsiStatus, &sense, &senseSize);
2140*fcf3ce44SJohn Forte 
2141*fcf3ce44SJohn Forte 	if (status == HBA_STATUS_OK) {
2142*fcf3ce44SJohn Forte 		data = (uchar_t *)&inq00;
2143*fcf3ce44SJohn Forte 		for (index = 4; (index <= inq00.len+3)&&
2144*fcf3ce44SJohn Forte 		    (data[index] <= page_num); index ++) {
2145*fcf3ce44SJohn Forte 			if (data[index] == page_num) {
2146*fcf3ce44SJohn Forte 				return (1);
2147*fcf3ce44SJohn Forte 			}
2148*fcf3ce44SJohn Forte 		}
2149*fcf3ce44SJohn Forte 	}
2150*fcf3ce44SJohn Forte 	return (0);
2151*fcf3ce44SJohn Forte }
2152