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