xref: /onnv-gate/usr/src/cmd/fcinfo/fcinfo-list.c (revision 9087:79961490b734)
17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM  * CDDL HEADER START
37836SJohn.Forte@Sun.COM  *
47836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM  *
87836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM  * and limitations under the License.
127836SJohn.Forte@Sun.COM  *
137836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM  *
197836SJohn.Forte@Sun.COM  * CDDL HEADER END
207836SJohn.Forte@Sun.COM  */
217836SJohn.Forte@Sun.COM /*
22*9087SZhong.Wang@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237836SJohn.Forte@Sun.COM  * Use is subject to license terms.
247836SJohn.Forte@Sun.COM  */
257836SJohn.Forte@Sun.COM 
267836SJohn.Forte@Sun.COM 
277836SJohn.Forte@Sun.COM #include "fcinfo.h"
287836SJohn.Forte@Sun.COM #include <libintl.h>
297836SJohn.Forte@Sun.COM 
307836SJohn.Forte@Sun.COM struct lun {
317836SJohn.Forte@Sun.COM 	uchar_t val[8];
327836SJohn.Forte@Sun.COM };
337836SJohn.Forte@Sun.COM 
347836SJohn.Forte@Sun.COM typedef enum {
357836SJohn.Forte@Sun.COM     HBA_PORT,
367836SJohn.Forte@Sun.COM     REMOTE_PORT,
377836SJohn.Forte@Sun.COM     LOGICAL_UNIT
387836SJohn.Forte@Sun.COM } resource_type;
397836SJohn.Forte@Sun.COM 
407836SJohn.Forte@Sun.COM typedef struct rep_luns_rsp {
417836SJohn.Forte@Sun.COM 	uint32_t    length;
427836SJohn.Forte@Sun.COM 	uint32_t    rsrvd;
437836SJohn.Forte@Sun.COM 	struct lun  lun[1];
447836SJohn.Forte@Sun.COM } rep_luns_rsp_t;
457836SJohn.Forte@Sun.COM 
467836SJohn.Forte@Sun.COM static int getTargetMapping(HBA_HANDLE, HBA_WWN myhbaPortWWN,
477836SJohn.Forte@Sun.COM     HBA_FCPTARGETMAPPINGV2 **mapping);
487836SJohn.Forte@Sun.COM static int processHBA(HBA_HANDLE handle, HBA_ADAPTERATTRIBUTES attrs,
497836SJohn.Forte@Sun.COM     int portIndex, HBA_PORTATTRIBUTES port, HBA_FCPTARGETMAPPINGV2 *map,
507836SJohn.Forte@Sun.COM     int resourceType, int flags, int mode);
517836SJohn.Forte@Sun.COM static void processRemotePort(HBA_HANDLE handle, HBA_WWN portWWN,
527836SJohn.Forte@Sun.COM     HBA_FCPTARGETMAPPINGV2 *map, int wwnCount, char **wwn_argv, int flags);
537836SJohn.Forte@Sun.COM static void handleRemotePort(HBA_HANDLE handle, HBA_WWN portWWN,
547836SJohn.Forte@Sun.COM     HBA_WWN myRemotePortWWN, HBA_PORTATTRIBUTES *discPort);
557836SJohn.Forte@Sun.COM static void printLinkStat(HBA_HANDLE handle, HBA_WWN hbaportWWN,
567836SJohn.Forte@Sun.COM     HBA_WWN destWWN);
577836SJohn.Forte@Sun.COM static void handleScsiTarget(HBA_HANDLE handle, HBA_WWN hbaPortWWN,
587836SJohn.Forte@Sun.COM     HBA_WWN scsiTargetWWN, HBA_FCPTARGETMAPPINGV2 *map);
597836SJohn.Forte@Sun.COM static int retrieveAttrs(HBA_HANDLE handle, HBA_WWN hbaPortWWN,
607836SJohn.Forte@Sun.COM     HBA_ADAPTERATTRIBUTES *attrs, HBA_PORTATTRIBUTES *port, int *portIndex);
617836SJohn.Forte@Sun.COM static void searchDevice(discoveredDevice **devList, HBA_FCPSCSIENTRYV2 entry,
627836SJohn.Forte@Sun.COM     HBA_WWN initiatorPortWWN, HBA_HANDLE handle, boolean_t verbose);
637836SJohn.Forte@Sun.COM 
647836SJohn.Forte@Sun.COM /*
657836SJohn.Forte@Sun.COM  * This function retrieve the adapater attributes, port attributes, and
667836SJohn.Forte@Sun.COM  * portIndex for the given handle and hba port WWN.
677836SJohn.Forte@Sun.COM  *
687836SJohn.Forte@Sun.COM  * Arguments:
697836SJohn.Forte@Sun.COM  *	handle	    an HBA_HANDLE to a adapter
707836SJohn.Forte@Sun.COM  *	hbaPortWWN  WWN of the port on the adapter to which to retrieve
717836SJohn.Forte@Sun.COM  *			HBA_PORTATTRIBUTES from
727836SJohn.Forte@Sun.COM  *	attrs	    pointer to a HBA_ADAPTERATTRIBUTES structure.  Upon
737836SJohn.Forte@Sun.COM  *			successful completion, this structure will be filled in
747836SJohn.Forte@Sun.COM  *	port	    pointer to a HBA_PORTATTRIBUTES structure.  Upon successful
757836SJohn.Forte@Sun.COM  *			completion, this structure will be fill in
767836SJohn.Forte@Sun.COM  *	portIndex   the Index count of the port on the adapter that is
777836SJohn.Forte@Sun.COM  *			associated with the WWN.
787836SJohn.Forte@Sun.COM  *
797836SJohn.Forte@Sun.COM  * Returns
807836SJohn.Forte@Sun.COM  *	0	    successfully retrieve all information
817836SJohn.Forte@Sun.COM  *	>0	    otherwise
827836SJohn.Forte@Sun.COM  */
837836SJohn.Forte@Sun.COM static int
retrieveAttrs(HBA_HANDLE handle,HBA_WWN hbaPortWWN,HBA_ADAPTERATTRIBUTES * attrs,HBA_PORTATTRIBUTES * port,int * portIndex)847836SJohn.Forte@Sun.COM retrieveAttrs(HBA_HANDLE handle, HBA_WWN hbaPortWWN,
857836SJohn.Forte@Sun.COM     HBA_ADAPTERATTRIBUTES *attrs, HBA_PORTATTRIBUTES *port, int *portIndex)
867836SJohn.Forte@Sun.COM {
877836SJohn.Forte@Sun.COM 	HBA_STATUS		status;
887836SJohn.Forte@Sun.COM 	int			portCtr;
897836SJohn.Forte@Sun.COM 	int			times;
907836SJohn.Forte@Sun.COM 
917836SJohn.Forte@Sun.COM 	/* argument checking */
927836SJohn.Forte@Sun.COM 	if (attrs == NULL || port == NULL || portIndex == NULL) {
937836SJohn.Forte@Sun.COM 		fprintf(stderr, gettext("Error: Invalid arguments to "
947836SJohn.Forte@Sun.COM 			    "retreiveAttrs\n"));
957836SJohn.Forte@Sun.COM 		return (1);
967836SJohn.Forte@Sun.COM 	}
977836SJohn.Forte@Sun.COM 
987836SJohn.Forte@Sun.COM 	/* retrieve Adapter attributes */
997836SJohn.Forte@Sun.COM 	memset(attrs, 0, sizeof (HBA_ADAPTERATTRIBUTES));
1007836SJohn.Forte@Sun.COM 	status = HBA_GetAdapterAttributes(handle, attrs);
1017836SJohn.Forte@Sun.COM 	times = 0;
1027836SJohn.Forte@Sun.COM 	while ((status == HBA_STATUS_ERROR_TRY_AGAIN ||
1037836SJohn.Forte@Sun.COM 	    status == HBA_STATUS_ERROR_BUSY) &&
1047836SJohn.Forte@Sun.COM 	    times++ < HBA_MAX_RETRIES) {
1057836SJohn.Forte@Sun.COM 		(void) sleep(1);
1067836SJohn.Forte@Sun.COM 		status = HBA_GetAdapterAttributes(handle, attrs);
1077836SJohn.Forte@Sun.COM 		if (status == HBA_STATUS_OK) {
1087836SJohn.Forte@Sun.COM 			break;
1097836SJohn.Forte@Sun.COM 		}
1107836SJohn.Forte@Sun.COM 	}
1117836SJohn.Forte@Sun.COM 	if (status != HBA_STATUS_OK) {
1127836SJohn.Forte@Sun.COM 		fprintf(stderr, gettext("Failed to get adapter "
1137836SJohn.Forte@Sun.COM 		    "attributes handle(%d) Reason: "), handle);
1147836SJohn.Forte@Sun.COM 		printStatus(status);
1157836SJohn.Forte@Sun.COM 		fprintf(stderr, "\n");
1167836SJohn.Forte@Sun.COM 		return (1);
1177836SJohn.Forte@Sun.COM 	}
1187836SJohn.Forte@Sun.COM 
1197836SJohn.Forte@Sun.COM 	/*
1207836SJohn.Forte@Sun.COM 	 * find the corresponding port on the adapter and retrieve
1217836SJohn.Forte@Sun.COM 	 * port attributes as well as the port index
1227836SJohn.Forte@Sun.COM 	 */
1237836SJohn.Forte@Sun.COM 	memset(port,  0, sizeof (HBA_PORTATTRIBUTES));
1247836SJohn.Forte@Sun.COM 	for (portCtr = 0; portCtr < attrs->NumberOfPorts; portCtr++) {
1257836SJohn.Forte@Sun.COM 		if ((status = HBA_GetAdapterPortAttributes(handle,
1267836SJohn.Forte@Sun.COM 				    portCtr, port)) != HBA_STATUS_OK) {
1277836SJohn.Forte@Sun.COM 			fprintf(stderr,
1287836SJohn.Forte@Sun.COM 			    gettext("Error: Failed to get port (%d) "
1297836SJohn.Forte@Sun.COM 				    "attributes reason: "), portCtr);
1307836SJohn.Forte@Sun.COM 			printStatus(status);
1317836SJohn.Forte@Sun.COM 			fprintf(stderr, "\n");
1327836SJohn.Forte@Sun.COM 			return (1);
1337836SJohn.Forte@Sun.COM 		}
1347836SJohn.Forte@Sun.COM 		if (memcmp(hbaPortWWN.wwn, port->PortWWN.wwn,
1357836SJohn.Forte@Sun.COM 			    sizeof (port->PortWWN.wwn)) == 0) {
1367836SJohn.Forte@Sun.COM 			break;
1377836SJohn.Forte@Sun.COM 		}
1387836SJohn.Forte@Sun.COM 	}
1397836SJohn.Forte@Sun.COM 	if (portCtr >= attrs->NumberOfPorts) {
1407836SJohn.Forte@Sun.COM 		/*
1417836SJohn.Forte@Sun.COM 		 * not able to find corresponding port WWN
1427836SJohn.Forte@Sun.COM 		 * returning an error
1437836SJohn.Forte@Sun.COM 		 */
1447836SJohn.Forte@Sun.COM 		*portIndex = 0;
1457836SJohn.Forte@Sun.COM 		return (1);
1467836SJohn.Forte@Sun.COM 	}
1477836SJohn.Forte@Sun.COM 	*portIndex = portCtr;
1487836SJohn.Forte@Sun.COM 	return (0);
1497836SJohn.Forte@Sun.COM }
1507836SJohn.Forte@Sun.COM 
1517836SJohn.Forte@Sun.COM /*
1527836SJohn.Forte@Sun.COM  * This function retrieves target mapping information for the HBA port WWN.
1537836SJohn.Forte@Sun.COM  * This function will allocate space for the mapping structure which the caller
1547836SJohn.Forte@Sun.COM  * must free when they are finished
1557836SJohn.Forte@Sun.COM  *
1567836SJohn.Forte@Sun.COM  * Arguments:
1577836SJohn.Forte@Sun.COM  *	handle - a handle to a HBA that we will be processing
1587836SJohn.Forte@Sun.COM  *	hbaPortWWN - the port WWN for the HBA port to retrieve the mappings for
1597836SJohn.Forte@Sun.COM  *	mapping - a pointer to a pointer for the target mapping structure
1607836SJohn.Forte@Sun.COM  *	    Upon successful completion of this function, *mapping will contain
1617836SJohn.Forte@Sun.COM  *	    the target mapping information
1627836SJohn.Forte@Sun.COM  *
1637836SJohn.Forte@Sun.COM  * returns:
1647836SJohn.Forte@Sun.COM  *	0	if successful
1657836SJohn.Forte@Sun.COM  *	1	otherwise
1667836SJohn.Forte@Sun.COM  */
1677836SJohn.Forte@Sun.COM static int
getTargetMapping(HBA_HANDLE handle,HBA_WWN hbaPortWWN,HBA_FCPTARGETMAPPINGV2 ** mapping)1687836SJohn.Forte@Sun.COM getTargetMapping(HBA_HANDLE handle, HBA_WWN hbaPortWWN,
1697836SJohn.Forte@Sun.COM     HBA_FCPTARGETMAPPINGV2 **mapping)
1707836SJohn.Forte@Sun.COM {
1717836SJohn.Forte@Sun.COM 	HBA_FCPTARGETMAPPINGV2	*map;
1727836SJohn.Forte@Sun.COM 	HBA_STATUS		status;
1737836SJohn.Forte@Sun.COM 	int			count;
1747836SJohn.Forte@Sun.COM 
1757836SJohn.Forte@Sun.COM 	/* argument sanity checking */
1767836SJohn.Forte@Sun.COM 	if (mapping == NULL) {
1777836SJohn.Forte@Sun.COM 		fprintf(stderr, gettext("Internal Error: mapping is NULL"));
1787836SJohn.Forte@Sun.COM 		return (1);
1797836SJohn.Forte@Sun.COM 	}
1807836SJohn.Forte@Sun.COM 	*mapping = NULL;
1817836SJohn.Forte@Sun.COM 	if ((map = calloc(1, sizeof (HBA_FCPTARGETMAPPINGV2))) == NULL) {
1827836SJohn.Forte@Sun.COM 		fprintf(stderr,
1837836SJohn.Forte@Sun.COM 		    gettext("Internal Error: Unable to calloc map"));
1847836SJohn.Forte@Sun.COM 		return (1);
1857836SJohn.Forte@Sun.COM 	}
1867836SJohn.Forte@Sun.COM 	status = HBA_GetFcpTargetMappingV2(handle, hbaPortWWN, map);
1877836SJohn.Forte@Sun.COM 	count = map->NumberOfEntries;
1887836SJohn.Forte@Sun.COM 	if (status == HBA_STATUS_ERROR_MORE_DATA) {
1897836SJohn.Forte@Sun.COM 		free(map);
1907836SJohn.Forte@Sun.COM 		if ((map = calloc(1, (sizeof (HBA_FCPSCSIENTRYV2)*(count-1)) +
1917836SJohn.Forte@Sun.COM 				    sizeof (HBA_FCPTARGETMAPPINGV2))) == NULL) {
1927836SJohn.Forte@Sun.COM 			fprintf(stderr,
1937836SJohn.Forte@Sun.COM 			    gettext("Unable to calloc map of size: %d"), count);
1947836SJohn.Forte@Sun.COM 			return (1);
1957836SJohn.Forte@Sun.COM 		}
1967836SJohn.Forte@Sun.COM 		map->NumberOfEntries = count;
1977836SJohn.Forte@Sun.COM 		status = HBA_GetFcpTargetMappingV2(handle, hbaPortWWN, map);
1987836SJohn.Forte@Sun.COM 	}
1997836SJohn.Forte@Sun.COM 	if (status != HBA_STATUS_OK) {
2007836SJohn.Forte@Sun.COM 		fprintf(stderr,
2017836SJohn.Forte@Sun.COM 		    gettext("Error: Unable to get Target Mapping\n"));
2027836SJohn.Forte@Sun.COM 		printStatus(status);
2037836SJohn.Forte@Sun.COM 		fprintf(stderr, "\n");
2047836SJohn.Forte@Sun.COM 		free(map);
2057836SJohn.Forte@Sun.COM 		return (1);
2067836SJohn.Forte@Sun.COM 	}
2077836SJohn.Forte@Sun.COM 	*mapping = map;
2087836SJohn.Forte@Sun.COM 	return (0);
2097836SJohn.Forte@Sun.COM }
2107836SJohn.Forte@Sun.COM 
2117836SJohn.Forte@Sun.COM /*
2127836SJohn.Forte@Sun.COM  * This function handles the remoteport object.  It will issue a report lun
2137836SJohn.Forte@Sun.COM  * to determine whether it is a scsi-target and then print the information.
2147836SJohn.Forte@Sun.COM  *
2157836SJohn.Forte@Sun.COM  * Arguments:
2167836SJohn.Forte@Sun.COM  *	handle - a handle to a HBA that we will be processing
2177836SJohn.Forte@Sun.COM  *	portWWN - the port WWN for the HBA port we will be issuing the SCSI
2187836SJohn.Forte@Sun.COM  *	    ReportLUNS through
2197836SJohn.Forte@Sun.COM  *	remotePortWWN - the port WWN we will be issuing the report lun call to
2207836SJohn.Forte@Sun.COM  *	discPort - PORTATTRIBUTES structure for the remotePortWWN
2217836SJohn.Forte@Sun.COM  */
2227836SJohn.Forte@Sun.COM static void
handleRemotePort(HBA_HANDLE handle,HBA_WWN portWWN,HBA_WWN remotePortWWN,HBA_PORTATTRIBUTES * discPort)2237836SJohn.Forte@Sun.COM handleRemotePort(HBA_HANDLE handle, HBA_WWN portWWN, HBA_WWN remotePortWWN,
2247836SJohn.Forte@Sun.COM     HBA_PORTATTRIBUTES *discPort)
2257836SJohn.Forte@Sun.COM {
2267836SJohn.Forte@Sun.COM 	HBA_STATUS		status;
2277836SJohn.Forte@Sun.COM 	int			scsiTargetType;
2287836SJohn.Forte@Sun.COM 	uchar_t			raw_luns[LUN_LENGTH];
2297836SJohn.Forte@Sun.COM 	HBA_UINT32		responseSize = LUN_LENGTH;
2307836SJohn.Forte@Sun.COM 	struct scsi_extended_sense  sense;
2317836SJohn.Forte@Sun.COM 	HBA_UINT32		senseSize = sizeof (struct scsi_extended_sense);
2327836SJohn.Forte@Sun.COM 	HBA_UINT8		rep_luns_status;
2337836SJohn.Forte@Sun.COM 
2347836SJohn.Forte@Sun.COM 	/* argument checking */
2357836SJohn.Forte@Sun.COM 	if (discPort == NULL) {
2367836SJohn.Forte@Sun.COM 		return;
2377836SJohn.Forte@Sun.COM 	}
2387836SJohn.Forte@Sun.COM 
2397836SJohn.Forte@Sun.COM 	memset(raw_luns, 0, sizeof (raw_luns));
2407836SJohn.Forte@Sun.COM 	/* going to issue a report lun to check if this is a scsi-target */
2417836SJohn.Forte@Sun.COM 	status = HBA_ScsiReportLUNsV2(handle, portWWN, remotePortWWN,
2427836SJohn.Forte@Sun.COM 	    (void *)raw_luns, &responseSize, &rep_luns_status,
2437836SJohn.Forte@Sun.COM 	    (void *)&sense, &senseSize);
2447836SJohn.Forte@Sun.COM 	if (status == HBA_STATUS_OK) {
2457836SJohn.Forte@Sun.COM 		scsiTargetType = SCSI_TARGET_TYPE_YES;
2467836SJohn.Forte@Sun.COM 	} else if (status == HBA_STATUS_ERROR_NOT_A_TARGET) {
2477836SJohn.Forte@Sun.COM 		scsiTargetType = SCSI_TARGET_TYPE_NO;
2487836SJohn.Forte@Sun.COM 	} else {
2497836SJohn.Forte@Sun.COM 		scsiTargetType = SCSI_TARGET_TYPE_UNKNOWN;
2507836SJohn.Forte@Sun.COM 	}
2517836SJohn.Forte@Sun.COM 	printDiscoPortInfo(discPort, scsiTargetType);
2527836SJohn.Forte@Sun.COM }
2537836SJohn.Forte@Sun.COM 
2547836SJohn.Forte@Sun.COM /*
2557836SJohn.Forte@Sun.COM  * This function will issue the RLS and print out the port statistics for
2567836SJohn.Forte@Sun.COM  * the given destWWN
2577836SJohn.Forte@Sun.COM  *
2587836SJohn.Forte@Sun.COM  * Arguments
2597836SJohn.Forte@Sun.COM  *	handle - a handle to a HBA that we will be processing
2607836SJohn.Forte@Sun.COM  *	hbaPortWWN - the hba port WWN through which the RLS will be sent
2617836SJohn.Forte@Sun.COM  *	destWWN - the remote port to which the RLS will be sent
2627836SJohn.Forte@Sun.COM  */
2637836SJohn.Forte@Sun.COM static void
printLinkStat(HBA_HANDLE handle,HBA_WWN hbaPortWWN,HBA_WWN destWWN)2647836SJohn.Forte@Sun.COM printLinkStat(HBA_HANDLE handle, HBA_WWN hbaPortWWN, HBA_WWN destWWN)
2657836SJohn.Forte@Sun.COM {
2667836SJohn.Forte@Sun.COM 	HBA_STATUS		status;
2677836SJohn.Forte@Sun.COM 	fc_rls_acc_t		rls_payload;
2687836SJohn.Forte@Sun.COM 	uint32_t		rls_payload_size;
2697836SJohn.Forte@Sun.COM 
2707836SJohn.Forte@Sun.COM 	memset(&rls_payload, 0, sizeof (rls_payload));
2717836SJohn.Forte@Sun.COM 	rls_payload_size = sizeof (rls_payload);
2727836SJohn.Forte@Sun.COM 	status = HBA_SendRLS(handle, hbaPortWWN, destWWN,
2737836SJohn.Forte@Sun.COM 	    &rls_payload, &rls_payload_size);
2747836SJohn.Forte@Sun.COM 	if (status != HBA_STATUS_OK) {
2757836SJohn.Forte@Sun.COM 		fprintf(stderr, gettext("Error: SendRLS failed for %016llx\n"),
2767836SJohn.Forte@Sun.COM 		    wwnConversion(destWWN.wwn));
2777836SJohn.Forte@Sun.COM 	} else {
2787836SJohn.Forte@Sun.COM 		printPortStat(&rls_payload);
2797836SJohn.Forte@Sun.COM 	}
2807836SJohn.Forte@Sun.COM }
2817836SJohn.Forte@Sun.COM 
2827836SJohn.Forte@Sun.COM int
printHBANPIVPortInfo(HBA_HANDLE handle,int portindex)2837836SJohn.Forte@Sun.COM printHBANPIVPortInfo(HBA_HANDLE handle, int portindex)
2847836SJohn.Forte@Sun.COM {
2857836SJohn.Forte@Sun.COM 	HBA_PORTNPIVATTRIBUTES	portattrs;
2867836SJohn.Forte@Sun.COM 	HBA_NPIVATTRIBUTES	npivattrs;
2877836SJohn.Forte@Sun.COM 	HBA_STATUS		status;
2887836SJohn.Forte@Sun.COM 	int			index;
2897836SJohn.Forte@Sun.COM 	int			times = 0;
2907836SJohn.Forte@Sun.COM 
2917836SJohn.Forte@Sun.COM 	status = Sun_HBA_GetPortNPIVAttributes(handle, portindex, &portattrs);
2927836SJohn.Forte@Sun.COM 	while (status == HBA_STATUS_ERROR_TRY_AGAIN ||
2937836SJohn.Forte@Sun.COM 	    status == HBA_STATUS_ERROR_BUSY) {
2947836SJohn.Forte@Sun.COM 		(void) sleep(1);
2957836SJohn.Forte@Sun.COM 		status = Sun_HBA_GetPortNPIVAttributes(
2967836SJohn.Forte@Sun.COM 		    handle, portindex, &portattrs);
2977836SJohn.Forte@Sun.COM 		if (times++ > HBA_MAX_RETRIES) {
2987836SJohn.Forte@Sun.COM 			break;
2997836SJohn.Forte@Sun.COM 		}
3007836SJohn.Forte@Sun.COM 	}
3017836SJohn.Forte@Sun.COM 
3027836SJohn.Forte@Sun.COM 	if (status == HBA_STATUS_ERROR_NOT_SUPPORTED) {
3037836SJohn.Forte@Sun.COM 		fprintf(stdout, gettext("\tNPIV Not Supported\n"));
3047836SJohn.Forte@Sun.COM 		return (0);
3057836SJohn.Forte@Sun.COM 	}
3067836SJohn.Forte@Sun.COM 
3077836SJohn.Forte@Sun.COM 	if (status != HBA_STATUS_OK) {
3087836SJohn.Forte@Sun.COM 		fprintf(stderr,
3097836SJohn.Forte@Sun.COM 		    gettext("Error: Failed to get port (%d) "
3107836SJohn.Forte@Sun.COM 		    "npiv attributes reason: "), portindex);
3117836SJohn.Forte@Sun.COM 		printStatus(status);
3127836SJohn.Forte@Sun.COM 		fprintf(stderr, "\n");
3137836SJohn.Forte@Sun.COM 		return (1);
3147836SJohn.Forte@Sun.COM 	}
3157836SJohn.Forte@Sun.COM 	if (portattrs.MaxNumberOfNPIVPorts) {
3167836SJohn.Forte@Sun.COM 		fprintf(stdout, gettext("\tMax NPIV Ports: %d\n"),
3177836SJohn.Forte@Sun.COM 		    portattrs.MaxNumberOfNPIVPorts);
3187836SJohn.Forte@Sun.COM 	} else {
3197836SJohn.Forte@Sun.COM 		fprintf(stdout, gettext("\tNPIV Not Supported\n"));
3207836SJohn.Forte@Sun.COM 		return (0);
3217836SJohn.Forte@Sun.COM 	}
3227836SJohn.Forte@Sun.COM 	fprintf(stdout, gettext("\tNPIV port list:\n"));
3237836SJohn.Forte@Sun.COM 	for (index = 0; index < portattrs.NumberOfNPIVPorts; index++) {
3247836SJohn.Forte@Sun.COM 		int times = 0;
3257836SJohn.Forte@Sun.COM 		status = Sun_HBA_GetNPIVPortInfo(handle,
3267836SJohn.Forte@Sun.COM 		    portindex, index, &npivattrs);
3277836SJohn.Forte@Sun.COM 		while (status == HBA_STATUS_ERROR_TRY_AGAIN ||
3287836SJohn.Forte@Sun.COM 		    status == HBA_STATUS_ERROR_BUSY) {
3297836SJohn.Forte@Sun.COM 			(void) sleep(1);
3307836SJohn.Forte@Sun.COM 			status = Sun_HBA_GetNPIVPortInfo(handle,
3317836SJohn.Forte@Sun.COM 			    portindex, index, &npivattrs);
3327836SJohn.Forte@Sun.COM 			if (times++ > HBA_MAX_RETRIES) {
3337836SJohn.Forte@Sun.COM 				break;
3347836SJohn.Forte@Sun.COM 			}
3357836SJohn.Forte@Sun.COM 		}
3367836SJohn.Forte@Sun.COM 
3377836SJohn.Forte@Sun.COM 		if (status != HBA_STATUS_OK) {
3387836SJohn.Forte@Sun.COM 			fprintf(stderr,
3397836SJohn.Forte@Sun.COM 			    gettext("Error: Failed to get npiv port (%d) "
3407836SJohn.Forte@Sun.COM 			    "attributes reason: "), index);
3417836SJohn.Forte@Sun.COM 			printStatus(status);
3427836SJohn.Forte@Sun.COM 			fprintf(stderr, "\n");
3437836SJohn.Forte@Sun.COM 			return (1);
3447836SJohn.Forte@Sun.COM 		} else {
3457836SJohn.Forte@Sun.COM 			fprintf(stdout,
3467836SJohn.Forte@Sun.COM 			    gettext("\t  Virtual Port%d:\n"), index+1);
3477836SJohn.Forte@Sun.COM 			fprintf(stdout, gettext("\t\tNode WWN: %016llx\n"),
3487836SJohn.Forte@Sun.COM 			    wwnConversion(npivattrs.NodeWWN.wwn));
3497836SJohn.Forte@Sun.COM 			fprintf(stdout, gettext("\t\tPort WWN: %016llx\n"),
3507836SJohn.Forte@Sun.COM 			    wwnConversion(npivattrs.PortWWN.wwn));
3517836SJohn.Forte@Sun.COM 		}
3527836SJohn.Forte@Sun.COM 	}
3537836SJohn.Forte@Sun.COM 	return (0);
3547836SJohn.Forte@Sun.COM }
3557836SJohn.Forte@Sun.COM 
3567836SJohn.Forte@Sun.COM /*
3577836SJohn.Forte@Sun.COM  * This function will process hba port, remote port and scsi-target information
3587836SJohn.Forte@Sun.COM  * for the given handle.
3597836SJohn.Forte@Sun.COM  *
3607836SJohn.Forte@Sun.COM  * Arguments:
3617836SJohn.Forte@Sun.COM  *	handle - a handle to a HBA that we will be processing
3627836SJohn.Forte@Sun.COM  *	resourceType - resourceType flag
3637836SJohn.Forte@Sun.COM  *		possible values include: HBA_PORT, REMOTE_PORT
3647836SJohn.Forte@Sun.COM  *	flags - represents options passed in by the user
3657836SJohn.Forte@Sun.COM  *
3667836SJohn.Forte@Sun.COM  *  Return Value:
3677836SJohn.Forte@Sun.COM  *	    0		sucessfully processed handle
3687836SJohn.Forte@Sun.COM  *	    1		error has occured
3697836SJohn.Forte@Sun.COM  */
3707836SJohn.Forte@Sun.COM static int
processHBA(HBA_HANDLE handle,HBA_ADAPTERATTRIBUTES attrs,int portIndex,HBA_PORTATTRIBUTES port,HBA_FCPTARGETMAPPINGV2 * map,int resourceType,int flags,int mode)3717836SJohn.Forte@Sun.COM processHBA(HBA_HANDLE handle, HBA_ADAPTERATTRIBUTES attrs, int portIndex,
3727836SJohn.Forte@Sun.COM     HBA_PORTATTRIBUTES port, HBA_FCPTARGETMAPPINGV2 *map,
3737836SJohn.Forte@Sun.COM     int resourceType, int flags, int mode)
3747836SJohn.Forte@Sun.COM {
3757836SJohn.Forte@Sun.COM 	HBA_PORTATTRIBUTES	discPort;
3767836SJohn.Forte@Sun.COM 	HBA_STATUS		status;
3777836SJohn.Forte@Sun.COM 	int			discPortCount;
3787836SJohn.Forte@Sun.COM 
3797836SJohn.Forte@Sun.COM 	if (resourceType == HBA_PORT) {
380*9087SZhong.Wang@Sun.COM 		if ((flags & PRINT_FCOE) == PRINT_FCOE &&
381*9087SZhong.Wang@Sun.COM 		    attrs.VendorSpecificID != 0xFC0E) {
382*9087SZhong.Wang@Sun.COM 			return (0);
383*9087SZhong.Wang@Sun.COM 		}
3847836SJohn.Forte@Sun.COM 		printHBAPortInfo(&port, &attrs, mode);
3857836SJohn.Forte@Sun.COM 		if ((flags & PRINT_LINKSTAT) == PRINT_LINKSTAT) {
3867836SJohn.Forte@Sun.COM 			printLinkStat(handle, port.PortWWN, port.PortWWN);
3877836SJohn.Forte@Sun.COM 		}
3887836SJohn.Forte@Sun.COM 		return (0);
3897836SJohn.Forte@Sun.COM 	}
3907836SJohn.Forte@Sun.COM 	/*
3917836SJohn.Forte@Sun.COM 	 * process each of the remote targets from this hba port
3927836SJohn.Forte@Sun.COM 	 */
3937836SJohn.Forte@Sun.COM 	for (discPortCount = 0;
3947836SJohn.Forte@Sun.COM 	    discPortCount < port.NumberofDiscoveredPorts;
3957836SJohn.Forte@Sun.COM 	    discPortCount++) {
3967836SJohn.Forte@Sun.COM 		status = HBA_GetDiscoveredPortAttributes(handle,
3977836SJohn.Forte@Sun.COM 		    portIndex, discPortCount, &discPort);
3987836SJohn.Forte@Sun.COM 		if (status != HBA_STATUS_OK) {
3997836SJohn.Forte@Sun.COM 			fprintf(stderr,
4007836SJohn.Forte@Sun.COM 			    gettext("Failed to get discovered port (%d)"
4017836SJohn.Forte@Sun.COM 				    " attributes reason :"), discPortCount);
4027836SJohn.Forte@Sun.COM 			printStatus(status);
4037836SJohn.Forte@Sun.COM 			fprintf(stderr, "\n");
4047836SJohn.Forte@Sun.COM 			continue;
4057836SJohn.Forte@Sun.COM 		}
4067836SJohn.Forte@Sun.COM 		if (resourceType == REMOTE_PORT) {
4077836SJohn.Forte@Sun.COM 			handleRemotePort(handle, port.PortWWN, discPort.PortWWN,
4087836SJohn.Forte@Sun.COM 			    &discPort);
4097836SJohn.Forte@Sun.COM 			if ((flags & PRINT_LINKSTAT) == PRINT_LINKSTAT) {
4107836SJohn.Forte@Sun.COM 			    printLinkStat(handle, port.PortWWN,
4117836SJohn.Forte@Sun.COM 				discPort.PortWWN);
4127836SJohn.Forte@Sun.COM 			}
4137836SJohn.Forte@Sun.COM 			if ((flags & PRINT_SCSI_TARGET) == PRINT_SCSI_TARGET) {
4147836SJohn.Forte@Sun.COM 				handleScsiTarget(handle, port.PortWWN,
4157836SJohn.Forte@Sun.COM 				    discPort.PortWWN, map);
4167836SJohn.Forte@Sun.COM 			}
4177836SJohn.Forte@Sun.COM 		}
4187836SJohn.Forte@Sun.COM 	}
4197836SJohn.Forte@Sun.COM 	return (0);
4207836SJohn.Forte@Sun.COM }
4217836SJohn.Forte@Sun.COM 
4227836SJohn.Forte@Sun.COM /*
4237836SJohn.Forte@Sun.COM  * This function will process remote port information for the given handle.
4247836SJohn.Forte@Sun.COM  *
4257836SJohn.Forte@Sun.COM  * Arguments:
4267836SJohn.Forte@Sun.COM  *	handle - a handle to a HBA that we will be processing
4277836SJohn.Forte@Sun.COM  *	portWWN - the port WWN for the HBA port we will be issuing the SCSI
4287836SJohn.Forte@Sun.COM  *	    ReportLUNS through
4297836SJohn.Forte@Sun.COM  *	wwnCount - the number of wwns in wwn_argv
4307836SJohn.Forte@Sun.COM  *	wwn_argv - argument vector of WWNs
4317836SJohn.Forte@Sun.COM  */
4327836SJohn.Forte@Sun.COM static void
processRemotePort(HBA_HANDLE handle,HBA_WWN portWWN,HBA_FCPTARGETMAPPINGV2 * map,int wwnCount,char ** wwn_argv,int flags)4337836SJohn.Forte@Sun.COM processRemotePort(HBA_HANDLE handle, HBA_WWN portWWN,
4347836SJohn.Forte@Sun.COM     HBA_FCPTARGETMAPPINGV2 *map, int wwnCount, char **wwn_argv, int flags)
4357836SJohn.Forte@Sun.COM {
4367836SJohn.Forte@Sun.COM 	int			remote_wwn_counter;
4377836SJohn.Forte@Sun.COM 	uint64_t		remotePortWWN;
4387836SJohn.Forte@Sun.COM 	HBA_WWN			myremotePortWWN;
4397836SJohn.Forte@Sun.COM 	HBA_PORTATTRIBUTES	discPort;
4407836SJohn.Forte@Sun.COM 	HBA_STATUS		status;
4417836SJohn.Forte@Sun.COM 
4427836SJohn.Forte@Sun.COM 	for (remote_wwn_counter = 0;
4437836SJohn.Forte@Sun.COM 	    remote_wwn_counter < wwnCount;
4447836SJohn.Forte@Sun.COM 	    remote_wwn_counter++) {
4457836SJohn.Forte@Sun.COM 		int times = 0;
4467836SJohn.Forte@Sun.COM 		sscanf(wwn_argv[remote_wwn_counter], "%016llx",
4477836SJohn.Forte@Sun.COM 		    &remotePortWWN);
4487836SJohn.Forte@Sun.COM 		remotePortWWN = htonll(remotePortWWN);
4497836SJohn.Forte@Sun.COM 		memcpy(myremotePortWWN.wwn, &remotePortWWN,
4507836SJohn.Forte@Sun.COM 		    sizeof (remotePortWWN));
4517836SJohn.Forte@Sun.COM 		memset(&discPort, 0, sizeof (discPort));
4527836SJohn.Forte@Sun.COM 		status = HBA_GetPortAttributesByWWN(handle, myremotePortWWN,
4537836SJohn.Forte@Sun.COM 		    &discPort);
4547836SJohn.Forte@Sun.COM 		while (status == HBA_STATUS_ERROR_TRY_AGAIN ||
4557836SJohn.Forte@Sun.COM 		    status == HBA_STATUS_ERROR_BUSY) {
4567836SJohn.Forte@Sun.COM 			(void) sleep(1);
4577836SJohn.Forte@Sun.COM 			status = HBA_GetPortAttributesByWWN(handle,
4587836SJohn.Forte@Sun.COM 			    myremotePortWWN, &discPort);
4597836SJohn.Forte@Sun.COM 			if (times++ > HBA_MAX_RETRIES) {
4607836SJohn.Forte@Sun.COM 				break;
4617836SJohn.Forte@Sun.COM 			}
4627836SJohn.Forte@Sun.COM 		}
4637836SJohn.Forte@Sun.COM 		if (status != HBA_STATUS_OK) {
4647836SJohn.Forte@Sun.COM 			fprintf(stderr, gettext("HBA_GetPortAttributesByWWN "
4657836SJohn.Forte@Sun.COM 				    "failed: reason: "));
4667836SJohn.Forte@Sun.COM 			printStatus(status);
4677836SJohn.Forte@Sun.COM 			fprintf(stderr, "\n");
4687836SJohn.Forte@Sun.COM 			continue;
4697836SJohn.Forte@Sun.COM 		}
4707836SJohn.Forte@Sun.COM 		handleRemotePort(handle, portWWN, myremotePortWWN, &discPort);
4717836SJohn.Forte@Sun.COM 		if ((flags & PRINT_LINKSTAT) == PRINT_LINKSTAT) {
4727836SJohn.Forte@Sun.COM 			printLinkStat(handle, portWWN, myremotePortWWN);
4737836SJohn.Forte@Sun.COM 		}
4747836SJohn.Forte@Sun.COM 		if ((flags & PRINT_SCSI_TARGET) == PRINT_SCSI_TARGET) {
4757836SJohn.Forte@Sun.COM 			handleScsiTarget(handle, portWWN,
4767836SJohn.Forte@Sun.COM 			    myremotePortWWN, map);
4777836SJohn.Forte@Sun.COM 		}
4787836SJohn.Forte@Sun.COM 	}
4797836SJohn.Forte@Sun.COM }
4807836SJohn.Forte@Sun.COM 
4817836SJohn.Forte@Sun.COM /*
4827836SJohn.Forte@Sun.COM  * This function handles printing Scsi target information for remote ports
4837836SJohn.Forte@Sun.COM  *
4847836SJohn.Forte@Sun.COM  * Arguments:
4857836SJohn.Forte@Sun.COM  *	handle - a handle to a HBA that we will be processing
4867836SJohn.Forte@Sun.COM  *	hbaPortWWN - the port WWN for the HBA port through which the SCSI call
4877836SJohn.Forte@Sun.COM  *	    is being sent
4887836SJohn.Forte@Sun.COM  *	scsiTargetWWN - target port WWN of the remote target the SCSI call is
4897836SJohn.Forte@Sun.COM  *	    being sent to
4907836SJohn.Forte@Sun.COM  *	map - a pointer to the target mapping structure for the given HBA port
4917836SJohn.Forte@Sun.COM  */
4927836SJohn.Forte@Sun.COM static void
handleScsiTarget(HBA_HANDLE handle,HBA_WWN hbaPortWWN,HBA_WWN scsiTargetWWN,HBA_FCPTARGETMAPPINGV2 * map)4937836SJohn.Forte@Sun.COM handleScsiTarget(HBA_HANDLE handle, HBA_WWN hbaPortWWN, HBA_WWN scsiTargetWWN,
4947836SJohn.Forte@Sun.COM     HBA_FCPTARGETMAPPINGV2 *map)
4957836SJohn.Forte@Sun.COM {
4967836SJohn.Forte@Sun.COM 	HBA_STATUS		    status;
4977836SJohn.Forte@Sun.COM 	struct scsi_inquiry	    inq;
4987836SJohn.Forte@Sun.COM 	struct scsi_extended_sense  sense;
4997836SJohn.Forte@Sun.COM 	HBA_UINT32		    responseSize, senseSize = 0;
5007836SJohn.Forte@Sun.COM 	HBA_UINT8		    inq_status;
5017836SJohn.Forte@Sun.COM 	uchar_t			    raw_luns[DEFAULT_LUN_LENGTH], *lun_string;
5027836SJohn.Forte@Sun.COM 	HBA_UINT8		    rep_luns_status;
5037836SJohn.Forte@Sun.COM 	rep_luns_rsp_t		    *lun_resp;
5047836SJohn.Forte@Sun.COM 	uint64_t		    fcLUN;
5057836SJohn.Forte@Sun.COM 	int			    lunNum, numberOfLun, lunCount, count;
5067836SJohn.Forte@Sun.COM 	uint32_t		    lunlength, tmp_lunlength;
5077836SJohn.Forte@Sun.COM 
5087836SJohn.Forte@Sun.COM 	responseSize = DEFAULT_LUN_LENGTH;
5097836SJohn.Forte@Sun.COM 	senseSize = sizeof (struct scsi_extended_sense);
5107836SJohn.Forte@Sun.COM 	memset(&sense, 0, sizeof (sense));
5117836SJohn.Forte@Sun.COM 	status = HBA_ScsiReportLUNsV2(handle, hbaPortWWN,
5127836SJohn.Forte@Sun.COM 	    scsiTargetWWN, (void *)raw_luns, &responseSize,
5137836SJohn.Forte@Sun.COM 	    &rep_luns_status, (void *)&sense, &senseSize);
5147836SJohn.Forte@Sun.COM 	/*
5157836SJohn.Forte@Sun.COM 	 * if HBA_STATUS_ERROR_NOT_A_TARGET is return, we can assume this is
5167836SJohn.Forte@Sun.COM 	 * a remote HBA and move on
5177836SJohn.Forte@Sun.COM 	 */
5187836SJohn.Forte@Sun.COM 	if (status == HBA_STATUS_ERROR_NOT_A_TARGET) {
5197836SJohn.Forte@Sun.COM 		return;
5207836SJohn.Forte@Sun.COM 	} else if (status != HBA_STATUS_OK) {
5217836SJohn.Forte@Sun.COM 		fprintf(stderr, gettext("Error has occured. "
5227836SJohn.Forte@Sun.COM 			    "HBA_ScsiReportLUNsV2 failed.  reason "));
5237836SJohn.Forte@Sun.COM 		printStatus(status);
5247836SJohn.Forte@Sun.COM 		fprintf(stderr, "\n");
5257836SJohn.Forte@Sun.COM 		return;
5267836SJohn.Forte@Sun.COM 	}
5277836SJohn.Forte@Sun.COM 	lun_resp = (rep_luns_rsp_t *)raw_luns;
5287836SJohn.Forte@Sun.COM 	memcpy(&tmp_lunlength, &(lun_resp->length), sizeof (tmp_lunlength));
5297836SJohn.Forte@Sun.COM 	lunlength = htonl(tmp_lunlength);
5307836SJohn.Forte@Sun.COM 	memcpy(&numberOfLun, &lunlength, sizeof (numberOfLun));
5317836SJohn.Forte@Sun.COM 	for (lunCount = 0; lunCount < (numberOfLun / 8); lunCount++) {
5327836SJohn.Forte@Sun.COM 		/*
5337836SJohn.Forte@Sun.COM 		 * now issue standard inquiry to get Vendor
5347836SJohn.Forte@Sun.COM 		 * and product information
5357836SJohn.Forte@Sun.COM 		 */
5367836SJohn.Forte@Sun.COM 		responseSize = sizeof (struct scsi_inquiry);
5377836SJohn.Forte@Sun.COM 		senseSize = sizeof (struct scsi_extended_sense);
5387836SJohn.Forte@Sun.COM 		memset(&inq, 0, sizeof (struct scsi_inquiry));
5397836SJohn.Forte@Sun.COM 		memset(&sense, 0, sizeof (sense));
5407836SJohn.Forte@Sun.COM 		fcLUN = ntohll(wwnConversion(lun_resp->lun[lunCount].val));
5417836SJohn.Forte@Sun.COM 		status = HBA_ScsiInquiryV2(
5427836SJohn.Forte@Sun.COM 			handle,
5437836SJohn.Forte@Sun.COM 			hbaPortWWN,
5447836SJohn.Forte@Sun.COM 			scsiTargetWWN,
5457836SJohn.Forte@Sun.COM 			fcLUN,
5467836SJohn.Forte@Sun.COM 			0, /* EVPD */
5477836SJohn.Forte@Sun.COM 			0,
5487836SJohn.Forte@Sun.COM 			&inq, &responseSize,
5497836SJohn.Forte@Sun.COM 			&inq_status,
5507836SJohn.Forte@Sun.COM 			&sense, &senseSize);
5517836SJohn.Forte@Sun.COM 		if (status != HBA_STATUS_OK) {
5527836SJohn.Forte@Sun.COM 		    fprintf(stderr, gettext("Not able to issue Inquiry.\n"));
5537836SJohn.Forte@Sun.COM 		    printStatus(status);
5547836SJohn.Forte@Sun.COM 		    fprintf(stderr, "\n");
5557836SJohn.Forte@Sun.COM 		    strcpy(inq.inq_vid, "Unknown");
5567836SJohn.Forte@Sun.COM 		    strcpy(inq.inq_pid, "Unknown");
5577836SJohn.Forte@Sun.COM 		}
5587836SJohn.Forte@Sun.COM 		if (map != NULL) {
5597836SJohn.Forte@Sun.COM 			for (count = 0; count < map->NumberOfEntries; count++) {
5607836SJohn.Forte@Sun.COM 			    if ((memcmp(map->entry[count].FcpId.PortWWN.wwn,
5617836SJohn.Forte@Sun.COM 						    scsiTargetWWN.wwn,
5627836SJohn.Forte@Sun.COM 						    sizeof (scsiTargetWWN.wwn))
5637836SJohn.Forte@Sun.COM 					    == 0) &&
5647836SJohn.Forte@Sun.COM 				    (memcmp(&(map->entry[count].FcpId.FcpLun),
5657836SJohn.Forte@Sun.COM 					    &fcLUN, sizeof (fcLUN)) == 0)) {
5667836SJohn.Forte@Sun.COM 				printLUNInfo(&inq,
5677836SJohn.Forte@Sun.COM 				    map->entry[count].ScsiId.ScsiOSLun,
5687836SJohn.Forte@Sun.COM 				    map->entry[count].ScsiId.OSDeviceName);
5697836SJohn.Forte@Sun.COM 				    break;
5707836SJohn.Forte@Sun.COM 			    }
5717836SJohn.Forte@Sun.COM 			}
5727836SJohn.Forte@Sun.COM 			if (count == map->NumberOfEntries) {
5737836SJohn.Forte@Sun.COM 				lun_string = lun_resp->lun[lunCount].val;
5747836SJohn.Forte@Sun.COM 				lunNum = ((lun_string[0] & 0x3F) << 8) |
5757836SJohn.Forte@Sun.COM 				    lun_string[1];
5767836SJohn.Forte@Sun.COM 				printLUNInfo(&inq, lunNum, "Unknown");
5777836SJohn.Forte@Sun.COM 			}
5787836SJohn.Forte@Sun.COM 		} else {
5797836SJohn.Forte@Sun.COM 			/* Not able to get any target mapping information */
5807836SJohn.Forte@Sun.COM 			lun_string = lun_resp->lun[lunCount].val;
5817836SJohn.Forte@Sun.COM 			lunNum = ((lun_string[0] & 0x3F) << 8) |
5827836SJohn.Forte@Sun.COM 			    lun_string[1];
5837836SJohn.Forte@Sun.COM 			printLUNInfo(&inq, lunNum, "Unknown");
5847836SJohn.Forte@Sun.COM 		}
5857836SJohn.Forte@Sun.COM 	}
5867836SJohn.Forte@Sun.COM }
5877836SJohn.Forte@Sun.COM 
5887836SJohn.Forte@Sun.COM /*
5897836SJohn.Forte@Sun.COM  * function to handle the list remoteport command
5907836SJohn.Forte@Sun.COM  *
5917836SJohn.Forte@Sun.COM  * Arguments:
5927836SJohn.Forte@Sun.COM  *	wwnCount - the number of wwns in wwn_argv
5937836SJohn.Forte@Sun.COM  *	    if wwnCount == 0, then print information on all
5947836SJohn.Forte@Sun.COM  *		remote ports.  wwn_argv will not be used in this case
5957836SJohn.Forte@Sun.COM  *	    if wwnCount > 0, then print information for the WWNs
5967836SJohn.Forte@Sun.COM  *		given in wwn_argv
5977836SJohn.Forte@Sun.COM  *	wwn_argv - argument vector of WWNs
5987836SJohn.Forte@Sun.COM  *	options - any options specified by the caller
5997836SJohn.Forte@Sun.COM  *
6007836SJohn.Forte@Sun.COM  * returns:
6017836SJohn.Forte@Sun.COM  *	0	if successful
6027836SJohn.Forte@Sun.COM  *	1	otherwise
6037836SJohn.Forte@Sun.COM  */
6047836SJohn.Forte@Sun.COM int
fc_util_list_remoteport(int wwnCount,char ** wwn_argv,cmdOptions_t * options)6057836SJohn.Forte@Sun.COM fc_util_list_remoteport(int wwnCount, char **wwn_argv, cmdOptions_t *options)
6067836SJohn.Forte@Sun.COM {
6077836SJohn.Forte@Sun.COM 	HBA_STATUS		status;
6087836SJohn.Forte@Sun.COM 	HBA_FCPTARGETMAPPINGV2	*map = NULL;
6097836SJohn.Forte@Sun.COM 	HBA_PORTATTRIBUTES	port;
6107836SJohn.Forte@Sun.COM 	HBA_ADAPTERATTRIBUTES	attrs;
6117836SJohn.Forte@Sun.COM 	HBA_HANDLE		handle;
6127836SJohn.Forte@Sun.COM 	uint64_t		hbaPortWWN;
6137836SJohn.Forte@Sun.COM 	HBA_WWN			myhbaPortWWN;
6147836SJohn.Forte@Sun.COM 	int			processHBA_flags = 0, portCount = 0;
6157836SJohn.Forte@Sun.COM 	int			mode;
6167836SJohn.Forte@Sun.COM 
6177836SJohn.Forte@Sun.COM 	/* grab the hba port wwn from the -p option */
6187836SJohn.Forte@Sun.COM 	for (; options->optval; options++) {
6197836SJohn.Forte@Sun.COM 		if (options->optval == 'p') {
6207836SJohn.Forte@Sun.COM 			sscanf(options->optarg, "%016llx",
6217836SJohn.Forte@Sun.COM 			    &hbaPortWWN);
6227836SJohn.Forte@Sun.COM 		} else if (options->optval == 's') {
6237836SJohn.Forte@Sun.COM 			processHBA_flags |= PRINT_SCSI_TARGET;
6247836SJohn.Forte@Sun.COM 		} else if (options->optval == 'l') {
6257836SJohn.Forte@Sun.COM 			processHBA_flags |= PRINT_LINKSTAT;
6267836SJohn.Forte@Sun.COM 		} else {
6277836SJohn.Forte@Sun.COM 			fprintf(stderr, gettext("Error: Illegal option: %c.\n"),
6287836SJohn.Forte@Sun.COM 			    options->optval);
6297836SJohn.Forte@Sun.COM 			return (1);
6307836SJohn.Forte@Sun.COM 		}
6317836SJohn.Forte@Sun.COM 	}
6327836SJohn.Forte@Sun.COM 	/*
6337836SJohn.Forte@Sun.COM 	 * -h option was not specified, this should not happen either.
6347836SJohn.Forte@Sun.COM 	 * cmdparse should catch this problem, but checking anyways
6357836SJohn.Forte@Sun.COM 	 */
6367836SJohn.Forte@Sun.COM 	if (hbaPortWWN == 0) {
6377836SJohn.Forte@Sun.COM 		fprintf(stderr,
6387836SJohn.Forte@Sun.COM 		    gettext("Error: -p option was not specified.\n"));
6397836SJohn.Forte@Sun.COM 		return (1);
6407836SJohn.Forte@Sun.COM 	}
6417836SJohn.Forte@Sun.COM 	if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) {
6427836SJohn.Forte@Sun.COM 		fprintf(stderr,
6437836SJohn.Forte@Sun.COM 		    gettext("Failed to load FC-HBA common library\n"));
6447836SJohn.Forte@Sun.COM 		printStatus(status);
6457836SJohn.Forte@Sun.COM 		fprintf(stderr, "\n");
6467836SJohn.Forte@Sun.COM 		return (1);
6477836SJohn.Forte@Sun.COM 	}
6487836SJohn.Forte@Sun.COM 	hbaPortWWN = htonll(hbaPortWWN);
6497836SJohn.Forte@Sun.COM 	memcpy(myhbaPortWWN.wwn, &hbaPortWWN, sizeof (hbaPortWWN));
6507836SJohn.Forte@Sun.COM 	if ((status = HBA_OpenAdapterByWWN(&handle, myhbaPortWWN))
6517836SJohn.Forte@Sun.COM 	    != HBA_STATUS_OK) {
6527836SJohn.Forte@Sun.COM 		status = Sun_HBA_OpenTgtAdapterByWWN(&handle, myhbaPortWWN);
6537836SJohn.Forte@Sun.COM 		if (status != HBA_STATUS_OK) {
6547836SJohn.Forte@Sun.COM 		    fprintf(stderr,
6557836SJohn.Forte@Sun.COM 			gettext("Error: Failed to open adapter port. Reason "));
6567836SJohn.Forte@Sun.COM 			printStatus(status);
6577836SJohn.Forte@Sun.COM 		    fprintf(stderr, "\n");
6587836SJohn.Forte@Sun.COM 		    HBA_FreeLibrary();
6597836SJohn.Forte@Sun.COM 		    return (1);
6607836SJohn.Forte@Sun.COM 		} else {
6617836SJohn.Forte@Sun.COM 		    if ((processHBA_flags & PRINT_SCSI_TARGET) ==
6627836SJohn.Forte@Sun.COM 			PRINT_SCSI_TARGET) {
6637836SJohn.Forte@Sun.COM 			fprintf(stderr, gettext(
6647836SJohn.Forte@Sun.COM 			    "Error: Unsupported option for target mode: %c.\n"),
6657836SJohn.Forte@Sun.COM 			    's');
6667836SJohn.Forte@Sun.COM 			HBA_FreeLibrary();
6677836SJohn.Forte@Sun.COM 			return (1);
6687836SJohn.Forte@Sun.COM 		    }
6697836SJohn.Forte@Sun.COM 		    mode = TARGET_MODE;
6707836SJohn.Forte@Sun.COM 		}
6717836SJohn.Forte@Sun.COM 	} else {
6727836SJohn.Forte@Sun.COM 	    mode = INITIATOR_MODE;
6737836SJohn.Forte@Sun.COM 	}
6747836SJohn.Forte@Sun.COM 
6757836SJohn.Forte@Sun.COM 	if ((processHBA_flags & PRINT_SCSI_TARGET) == PRINT_SCSI_TARGET) {
6767836SJohn.Forte@Sun.COM 		getTargetMapping(handle, myhbaPortWWN, &map);
6777836SJohn.Forte@Sun.COM 	}
6787836SJohn.Forte@Sun.COM 	if (wwnCount == 0) {
6797836SJohn.Forte@Sun.COM 		/* get adapater attributes for the given handle */
6807836SJohn.Forte@Sun.COM 		memset(&attrs, 0, sizeof (attrs));
6817836SJohn.Forte@Sun.COM 		memset(&port, 0, sizeof (port));
6827836SJohn.Forte@Sun.COM 		if (retrieveAttrs(handle, myhbaPortWWN, &attrs, &port,
6837836SJohn.Forte@Sun.COM 			    &portCount) != 0) {
6847836SJohn.Forte@Sun.COM 			if (map != NULL) {
6857836SJohn.Forte@Sun.COM 				free(map);
6867836SJohn.Forte@Sun.COM 			}
6877836SJohn.Forte@Sun.COM 			HBA_CloseAdapter(handle);
6887836SJohn.Forte@Sun.COM 			HBA_FreeLibrary();
6897836SJohn.Forte@Sun.COM 			return (1);
6907836SJohn.Forte@Sun.COM 		}
6917836SJohn.Forte@Sun.COM 		processHBA(handle, attrs, portCount, port, map, REMOTE_PORT,
6927836SJohn.Forte@Sun.COM 		    processHBA_flags, mode);
6937836SJohn.Forte@Sun.COM 	} else {
6947836SJohn.Forte@Sun.COM 		processRemotePort(handle, myhbaPortWWN, map, wwnCount,
6957836SJohn.Forte@Sun.COM 		    wwn_argv, processHBA_flags);
6967836SJohn.Forte@Sun.COM 	}
6977836SJohn.Forte@Sun.COM 	if (map != NULL) {
6987836SJohn.Forte@Sun.COM 		free(map);
6997836SJohn.Forte@Sun.COM 	}
7007836SJohn.Forte@Sun.COM 	HBA_CloseAdapter(handle);
7017836SJohn.Forte@Sun.COM 	HBA_FreeLibrary();
7027836SJohn.Forte@Sun.COM 	return (0);
7037836SJohn.Forte@Sun.COM }
7047836SJohn.Forte@Sun.COM 
7057836SJohn.Forte@Sun.COM /*
7067836SJohn.Forte@Sun.COM  * process the hbaport object
7077836SJohn.Forte@Sun.COM  *
7087836SJohn.Forte@Sun.COM  * Arguments:
7097836SJohn.Forte@Sun.COM  *	wwnCount - count of the number of WWNs in wwn_argv
7107836SJohn.Forte@Sun.COM  *	    if wwnCount > 0, then we will only print information for
7117836SJohn.Forte@Sun.COM  *		the hba ports listed in wwn_argv
7127836SJohn.Forte@Sun.COM  *	    if wwnCount == 0, then we will print information on all hba ports
7137836SJohn.Forte@Sun.COM  *	wwn_argv - argument array of hba port WWNs
7147836SJohn.Forte@Sun.COM  *	options - any options specified by the caller
7157836SJohn.Forte@Sun.COM  *
7167836SJohn.Forte@Sun.COM  * returns:
7177836SJohn.Forte@Sun.COM  *	0	if successful
7187836SJohn.Forte@Sun.COM  *	1	otherwise
7197836SJohn.Forte@Sun.COM  */
7207836SJohn.Forte@Sun.COM int
fc_util_list_hbaport(int wwnCount,char ** wwn_argv,cmdOptions_t * options)7217836SJohn.Forte@Sun.COM fc_util_list_hbaport(int wwnCount, char **wwn_argv, cmdOptions_t *options)
7227836SJohn.Forte@Sun.COM {
7237836SJohn.Forte@Sun.COM 	int	port_wwn_counter, numAdapters = 0, numTgtAdapters = 0, i;
7247836SJohn.Forte@Sun.COM 	HBA_STATUS		status;
7257836SJohn.Forte@Sun.COM 	char			adapterName[256];
7267836SJohn.Forte@Sun.COM 	HBA_HANDLE		handle;
7277836SJohn.Forte@Sun.COM 	uint64_t		hbaWWN;
7287836SJohn.Forte@Sun.COM 	HBA_WWN			myWWN;
7297836SJohn.Forte@Sun.COM 	int			processHBA_flags = 0;
7307836SJohn.Forte@Sun.COM 	HBA_PORTATTRIBUTES	port;
7317836SJohn.Forte@Sun.COM 	HBA_ADAPTERATTRIBUTES	attrs;
7327836SJohn.Forte@Sun.COM 	int			portIndex = 0, err_cnt = 0;
7337836SJohn.Forte@Sun.COM 	int			mode;
7347836SJohn.Forte@Sun.COM 
7357836SJohn.Forte@Sun.COM 	/* process each of the options */
7367836SJohn.Forte@Sun.COM 	for (; options->optval; options++) {
7377836SJohn.Forte@Sun.COM 		if (options->optval == 'l') {
7387836SJohn.Forte@Sun.COM 			processHBA_flags |= PRINT_LINKSTAT;
7397836SJohn.Forte@Sun.COM 		} else if (options->optval == 'i') {
7407836SJohn.Forte@Sun.COM 			processHBA_flags |= PRINT_INITIATOR;
7417836SJohn.Forte@Sun.COM 		} else if (options->optval == 't') {
7427836SJohn.Forte@Sun.COM 			processHBA_flags |= PRINT_TARGET;
743*9087SZhong.Wang@Sun.COM 		} else if (options->optval == 'e') {
744*9087SZhong.Wang@Sun.COM 			processHBA_flags |= PRINT_FCOE;
7457836SJohn.Forte@Sun.COM 		}
7467836SJohn.Forte@Sun.COM 	}
7477836SJohn.Forte@Sun.COM 
7487836SJohn.Forte@Sun.COM 	/*
7497836SJohn.Forte@Sun.COM 	 * Print both initiator and target if no initiator/target flag
7507836SJohn.Forte@Sun.COM 	 * specified.
7517836SJohn.Forte@Sun.COM 	 */
7527836SJohn.Forte@Sun.COM 	if (((processHBA_flags & PRINT_INITIATOR) == 0) &&
7537836SJohn.Forte@Sun.COM 	    ((processHBA_flags & PRINT_TARGET) == 0)) {
7547836SJohn.Forte@Sun.COM 	    processHBA_flags |= PRINT_INITIATOR | PRINT_TARGET;
7557836SJohn.Forte@Sun.COM 	}
7567836SJohn.Forte@Sun.COM 
7577836SJohn.Forte@Sun.COM 	if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) {
7587836SJohn.Forte@Sun.COM 		fprintf(stderr,
7597836SJohn.Forte@Sun.COM 		    gettext("Failed to load FC-HBA common library\n"));
7607836SJohn.Forte@Sun.COM 		printStatus(status);
7617836SJohn.Forte@Sun.COM 		fprintf(stderr, "\n");
7627836SJohn.Forte@Sun.COM 		return (1);
7637836SJohn.Forte@Sun.COM 	}
7647836SJohn.Forte@Sun.COM 	if (wwnCount > 0) {
7657836SJohn.Forte@Sun.COM 		/* list only ports given in wwn_argv */
7667836SJohn.Forte@Sun.COM 		for (port_wwn_counter = 0;
7677836SJohn.Forte@Sun.COM 		    port_wwn_counter < wwnCount;
7687836SJohn.Forte@Sun.COM 		    port_wwn_counter++) {
7697836SJohn.Forte@Sun.COM 			sscanf(wwn_argv[port_wwn_counter], "%016llx", &hbaWWN);
7707836SJohn.Forte@Sun.COM 			hbaWWN = htonll(hbaWWN);
7717836SJohn.Forte@Sun.COM 			memcpy(myWWN.wwn, &hbaWWN, sizeof (hbaWWN));
7727836SJohn.Forte@Sun.COM 			/* first check to see if it is an initiator port. */
7737836SJohn.Forte@Sun.COM 			if ((processHBA_flags & PRINT_INITIATOR) ==
7747836SJohn.Forte@Sun.COM 			    PRINT_INITIATOR) {
7757836SJohn.Forte@Sun.COM 			    int times = 0;
7767836SJohn.Forte@Sun.COM 			    status = HBA_OpenAdapterByWWN(&handle, myWWN);
7777836SJohn.Forte@Sun.COM 			    while (status == HBA_STATUS_ERROR_TRY_AGAIN ||
7787836SJohn.Forte@Sun.COM 				status == HBA_STATUS_ERROR_BUSY) {
7797836SJohn.Forte@Sun.COM 				(void) sleep(1);
7807836SJohn.Forte@Sun.COM 				status = HBA_OpenAdapterByWWN(&handle, myWWN);
7817836SJohn.Forte@Sun.COM 				if (times++ > HBA_MAX_RETRIES) {
7827836SJohn.Forte@Sun.COM 					break;
7837836SJohn.Forte@Sun.COM 				}
7847836SJohn.Forte@Sun.COM 			    }
7857836SJohn.Forte@Sun.COM 			    if (status != HBA_STATUS_OK) {
7867836SJohn.Forte@Sun.COM 				/* now see if it is a target mode FC port */
7877836SJohn.Forte@Sun.COM 				if ((processHBA_flags & PRINT_TARGET) ==
7887836SJohn.Forte@Sun.COM 				    PRINT_TARGET) {
7897836SJohn.Forte@Sun.COM 				    status =
7907836SJohn.Forte@Sun.COM 				    Sun_HBA_OpenTgtAdapterByWWN(&handle, myWWN);
7917836SJohn.Forte@Sun.COM 				    if (status != HBA_STATUS_OK) {
7927836SJohn.Forte@Sun.COM 					fprintf(stderr,
7937836SJohn.Forte@Sun.COM 					    gettext(
7947836SJohn.Forte@Sun.COM 					    "Error: HBA port %s: not found\n"),
7957836SJohn.Forte@Sun.COM 					    wwn_argv[port_wwn_counter]);
7967836SJohn.Forte@Sun.COM 					    err_cnt++;
7977836SJohn.Forte@Sun.COM 					continue;
7987836SJohn.Forte@Sun.COM 				    } else {
7997836SJohn.Forte@Sun.COM 					/* set the port mode. */
8007836SJohn.Forte@Sun.COM 					mode = TARGET_MODE;
8017836SJohn.Forte@Sun.COM 				    }
8027836SJohn.Forte@Sun.COM 				} else {
8037836SJohn.Forte@Sun.COM 				    fprintf(stderr,
8047836SJohn.Forte@Sun.COM 					gettext(
8057836SJohn.Forte@Sun.COM 					    "Error: HBA port %s: not found\n"),
8067836SJohn.Forte@Sun.COM 					    wwn_argv[port_wwn_counter]);
8077836SJohn.Forte@Sun.COM 					    err_cnt++;
8087836SJohn.Forte@Sun.COM 					continue;
8097836SJohn.Forte@Sun.COM 				}
8107836SJohn.Forte@Sun.COM 			    } else {
8117836SJohn.Forte@Sun.COM 				/* set the port mode. */
8127836SJohn.Forte@Sun.COM 				mode = INITIATOR_MODE;
8137836SJohn.Forte@Sun.COM 			    }
8147836SJohn.Forte@Sun.COM 			/* try target mode discovery if print target is set. */
8157836SJohn.Forte@Sun.COM 			} else if ((processHBA_flags & PRINT_TARGET) ==
8167836SJohn.Forte@Sun.COM 				PRINT_TARGET) {
8177836SJohn.Forte@Sun.COM 			    status =
8187836SJohn.Forte@Sun.COM 				Sun_HBA_OpenTgtAdapterByWWN(&handle, myWWN);
8197836SJohn.Forte@Sun.COM 			    if (status != HBA_STATUS_OK) {
8207836SJohn.Forte@Sun.COM 				fprintf(stderr, gettext(
8217836SJohn.Forte@Sun.COM 				    "Error: HBA port %s: not found\n"),
8227836SJohn.Forte@Sun.COM 				    wwn_argv[port_wwn_counter]);
8237836SJohn.Forte@Sun.COM 				    err_cnt++;
8247836SJohn.Forte@Sun.COM 				continue;
8257836SJohn.Forte@Sun.COM 			    } else {
8267836SJohn.Forte@Sun.COM 				/* set the port mode. */
8277836SJohn.Forte@Sun.COM 				mode = TARGET_MODE;
8287836SJohn.Forte@Sun.COM 			    }
8297836SJohn.Forte@Sun.COM 			} else {
8307836SJohn.Forte@Sun.COM 			    /* should not get here. */
8317836SJohn.Forte@Sun.COM 			    fprintf(stderr, gettext(
8327836SJohn.Forte@Sun.COM 				"Error: HBA port %s: not found\n"),
8337836SJohn.Forte@Sun.COM 				wwn_argv[port_wwn_counter]);
8347836SJohn.Forte@Sun.COM 			    err_cnt++;
8357836SJohn.Forte@Sun.COM 			    continue;
8367836SJohn.Forte@Sun.COM 			}
8377836SJohn.Forte@Sun.COM 			memset(&attrs, 0, sizeof (attrs));
8387836SJohn.Forte@Sun.COM 			memset(&port, 0, sizeof (port));
8397836SJohn.Forte@Sun.COM 			if (retrieveAttrs(handle, myWWN, &attrs, &port,
8407836SJohn.Forte@Sun.COM 				    &portIndex) != 0) {
8417836SJohn.Forte@Sun.COM 				HBA_CloseAdapter(handle);
8427836SJohn.Forte@Sun.COM 				continue;
8437836SJohn.Forte@Sun.COM 			}
8447836SJohn.Forte@Sun.COM 			processHBA(handle, attrs, portIndex, port, NULL,
8457836SJohn.Forte@Sun.COM 			    HBA_PORT, processHBA_flags, mode);
846*9087SZhong.Wang@Sun.COM 			if ((processHBA_flags & PRINT_FCOE) != PRINT_FCOE &&
847*9087SZhong.Wang@Sun.COM 			    attrs.VendorSpecificID != 0xFC0E &&
848*9087SZhong.Wang@Sun.COM 			    printHBANPIVPortInfo(handle, portIndex) != 0) {
8497836SJohn.Forte@Sun.COM 				err_cnt++;
8507836SJohn.Forte@Sun.COM 			}
8517836SJohn.Forte@Sun.COM 			HBA_CloseAdapter(handle);
8527836SJohn.Forte@Sun.COM 		}
8537836SJohn.Forte@Sun.COM 	} else {
8547836SJohn.Forte@Sun.COM 		/*
8557836SJohn.Forte@Sun.COM 		 * if PRINT_INITIATOR is specified, get the list of initiator
8567836SJohn.Forte@Sun.COM 		 * mod port.
8577836SJohn.Forte@Sun.COM 		 */
8587836SJohn.Forte@Sun.COM 		if ((processHBA_flags & PRINT_INITIATOR) == PRINT_INITIATOR) {
8597836SJohn.Forte@Sun.COM 		    numAdapters = HBA_GetNumberOfAdapters();
8607836SJohn.Forte@Sun.COM 		    if ((numAdapters == 0) &&
8617836SJohn.Forte@Sun.COM 			((processHBA_flags & ~PRINT_INITIATOR) == 0)) {
8627836SJohn.Forte@Sun.COM 			fprintf(stdout, gettext("No Adapters Found.\n"));
8637836SJohn.Forte@Sun.COM 		    }
8647836SJohn.Forte@Sun.COM 		    for (i = 0; i < numAdapters; i++) {
8657836SJohn.Forte@Sun.COM 			int times = 0;
8667836SJohn.Forte@Sun.COM 			status = HBA_GetAdapterName(i, adapterName);
8677836SJohn.Forte@Sun.COM 			if (status != HBA_STATUS_OK) {
8687836SJohn.Forte@Sun.COM 				fprintf(stderr, gettext(
8697836SJohn.Forte@Sun.COM 				    "failed to get adapter %d. Reason: "), i);
8707836SJohn.Forte@Sun.COM 				printStatus(status);
8717836SJohn.Forte@Sun.COM 				fprintf(stderr, "\n");
8727836SJohn.Forte@Sun.COM 				continue;
8737836SJohn.Forte@Sun.COM 			}
8747836SJohn.Forte@Sun.COM 			if ((handle = HBA_OpenAdapter(adapterName)) == 0) {
8757836SJohn.Forte@Sun.COM 				fprintf(stderr, gettext(
8767836SJohn.Forte@Sun.COM 					    "Failed to open adapter %s.\n"),
8777836SJohn.Forte@Sun.COM 				    adapterName);
8787836SJohn.Forte@Sun.COM 				continue;
8797836SJohn.Forte@Sun.COM 			}
8807836SJohn.Forte@Sun.COM 			/* get adapater attributes for the given handle */
8817836SJohn.Forte@Sun.COM 			memset(&attrs, 0, sizeof (attrs));
8827836SJohn.Forte@Sun.COM 			status =
8837836SJohn.Forte@Sun.COM 			    Sun_HBA_NPIVGetAdapterAttributes(handle,
8847836SJohn.Forte@Sun.COM 			    &attrs);
8857836SJohn.Forte@Sun.COM 			while ((status == HBA_STATUS_ERROR_TRY_AGAIN ||
8867836SJohn.Forte@Sun.COM 			    status == HBA_STATUS_ERROR_BUSY) &&
8877836SJohn.Forte@Sun.COM 			    times++ < HBA_MAX_RETRIES) {
8887836SJohn.Forte@Sun.COM 				(void) sleep(1);
8897836SJohn.Forte@Sun.COM 				status =
8907836SJohn.Forte@Sun.COM 				    Sun_HBA_NPIVGetAdapterAttributes(handle,
8917836SJohn.Forte@Sun.COM 				    &attrs);
8927836SJohn.Forte@Sun.COM 				if (status == HBA_STATUS_OK) {
8937836SJohn.Forte@Sun.COM 					break;
8947836SJohn.Forte@Sun.COM 				}
8957836SJohn.Forte@Sun.COM 			}
8967836SJohn.Forte@Sun.COM 			if (status != HBA_STATUS_OK) {
8977836SJohn.Forte@Sun.COM 				fprintf(stderr,
8987836SJohn.Forte@Sun.COM 				    gettext("Failed to get adapter attributes "
8997836SJohn.Forte@Sun.COM 					    "handle(%d) Reason: "), handle);
9007836SJohn.Forte@Sun.COM 				printStatus(status);
9017836SJohn.Forte@Sun.COM 				fprintf(stderr, "\n");
9028507SRaghuram.Prahlada@Sun.COM 				HBA_CloseAdapter(handle);
9037836SJohn.Forte@Sun.COM 				continue;
9047836SJohn.Forte@Sun.COM 			}
9057836SJohn.Forte@Sun.COM 
9067836SJohn.Forte@Sun.COM 			/* process each port on the given adatpter */
9077836SJohn.Forte@Sun.COM 			for (portIndex = 0;
9087836SJohn.Forte@Sun.COM 			    portIndex < attrs.NumberOfPorts;
9097836SJohn.Forte@Sun.COM 			    portIndex++) {
9107836SJohn.Forte@Sun.COM 				memset(&port, 0, sizeof (port));
9117836SJohn.Forte@Sun.COM 				if ((status = HBA_GetAdapterPortAttributes(
9127836SJohn.Forte@Sun.COM 						    handle, portIndex, &port))
9137836SJohn.Forte@Sun.COM 				    != HBA_STATUS_OK) {
9147836SJohn.Forte@Sun.COM 					/*
9157836SJohn.Forte@Sun.COM 					 * not able to get port attributes.
9167836SJohn.Forte@Sun.COM 					 * print out error * message and move
9177836SJohn.Forte@Sun.COM 					 * on to the next port
9187836SJohn.Forte@Sun.COM 					 */
9197836SJohn.Forte@Sun.COM 					fprintf(stderr,
9207836SJohn.Forte@Sun.COM 					    gettext("Error: Failed to get port "
9217836SJohn.Forte@Sun.COM 						    "(%d) attributes reason: "),
9227836SJohn.Forte@Sun.COM 					    portIndex);
9237836SJohn.Forte@Sun.COM 					printStatus(status);
9247836SJohn.Forte@Sun.COM 					fprintf(stderr, "\n");
9257836SJohn.Forte@Sun.COM 					continue;
9267836SJohn.Forte@Sun.COM 				}
9277836SJohn.Forte@Sun.COM 				processHBA(handle, attrs, portIndex, port,
9287836SJohn.Forte@Sun.COM 				    NULL, HBA_PORT, processHBA_flags,
9297836SJohn.Forte@Sun.COM 				    INITIATOR_MODE);
930*9087SZhong.Wang@Sun.COM 				if ((processHBA_flags & PRINT_FCOE) !=
931*9087SZhong.Wang@Sun.COM 				    PRINT_FCOE &&
932*9087SZhong.Wang@Sun.COM 				    attrs.VendorSpecificID != 0xFC0E &&
933*9087SZhong.Wang@Sun.COM 				    printHBANPIVPortInfo(handle,
934*9087SZhong.Wang@Sun.COM 				    portIndex) != 0) {
9357836SJohn.Forte@Sun.COM 					err_cnt++;
9367836SJohn.Forte@Sun.COM 				}
9377836SJohn.Forte@Sun.COM 			}
9387836SJohn.Forte@Sun.COM 			HBA_CloseAdapter(handle);
9397836SJohn.Forte@Sun.COM 		    }
9407836SJohn.Forte@Sun.COM 		}
9417836SJohn.Forte@Sun.COM 
9427836SJohn.Forte@Sun.COM 		/*
9437836SJohn.Forte@Sun.COM 		 * Get the info on the target mode FC port if PRINT_TARGET
9447836SJohn.Forte@Sun.COM 		 * is specified.
9457836SJohn.Forte@Sun.COM 		 */
9467836SJohn.Forte@Sun.COM 		if ((processHBA_flags & PRINT_TARGET) == PRINT_TARGET) {
9477836SJohn.Forte@Sun.COM 		    numTgtAdapters = Sun_HBA_GetNumberOfTgtAdapters();
9487836SJohn.Forte@Sun.COM 		    if (numTgtAdapters == 0 && numAdapters == 0) {
9497836SJohn.Forte@Sun.COM 			fprintf(stdout,
9507836SJohn.Forte@Sun.COM 			    gettext("No Adapters Found.\n"));
9517836SJohn.Forte@Sun.COM 		    }
9527836SJohn.Forte@Sun.COM 		    for (i = 0; i < numTgtAdapters; i++) {
9537836SJohn.Forte@Sun.COM 			status = Sun_HBA_GetTgtAdapterName(i, adapterName);
9547836SJohn.Forte@Sun.COM 			if (status != HBA_STATUS_OK) {
9557836SJohn.Forte@Sun.COM 			    fprintf(stderr, gettext(
9567836SJohn.Forte@Sun.COM 				"failed to get adapter %d. Reason: "), i);
9577836SJohn.Forte@Sun.COM 			    printStatus(status);
9587836SJohn.Forte@Sun.COM 			    fprintf(stderr, "\n");
9597836SJohn.Forte@Sun.COM 			    continue;
9607836SJohn.Forte@Sun.COM 			}
9617836SJohn.Forte@Sun.COM 			if ((handle = Sun_HBA_OpenTgtAdapter(adapterName))
9627836SJohn.Forte@Sun.COM 			    == 0) {
9637836SJohn.Forte@Sun.COM 			    fprintf(stderr, gettext(
9647836SJohn.Forte@Sun.COM 				"Failed to open adapter %s.\n"), adapterName);
9657836SJohn.Forte@Sun.COM 			    continue;
9667836SJohn.Forte@Sun.COM 			}
9677836SJohn.Forte@Sun.COM 			/* get adapater attributes for the given handle */
9687836SJohn.Forte@Sun.COM 			memset(&attrs, 0, sizeof (attrs));
9697836SJohn.Forte@Sun.COM 			if ((status = HBA_GetAdapterAttributes(handle, &attrs))
9707836SJohn.Forte@Sun.COM 			    != HBA_STATUS_OK) {
9717836SJohn.Forte@Sun.COM 				fprintf(stderr,
9727836SJohn.Forte@Sun.COM 				    gettext("Failed to get target mode adapter"
9737836SJohn.Forte@Sun.COM 					"attributes handle(%d) Reason: "),
9747836SJohn.Forte@Sun.COM 					handle);
9757836SJohn.Forte@Sun.COM 				printStatus(status);
9767836SJohn.Forte@Sun.COM 				fprintf(stderr, "\n");
9777836SJohn.Forte@Sun.COM 				continue;
9787836SJohn.Forte@Sun.COM 			}
9797836SJohn.Forte@Sun.COM 
9807836SJohn.Forte@Sun.COM 			/* process each port on the given adatpter */
9817836SJohn.Forte@Sun.COM 			for (portIndex = 0;
9827836SJohn.Forte@Sun.COM 			    portIndex < attrs.NumberOfPorts;
9837836SJohn.Forte@Sun.COM 			    portIndex++) {
9847836SJohn.Forte@Sun.COM 				memset(&port, 0, sizeof (port));
9857836SJohn.Forte@Sun.COM 				if ((status = HBA_GetAdapterPortAttributes(
9867836SJohn.Forte@Sun.COM 						    handle, portIndex, &port))
9877836SJohn.Forte@Sun.COM 				    != HBA_STATUS_OK) {
9887836SJohn.Forte@Sun.COM 					/*
9897836SJohn.Forte@Sun.COM 					 * not able to get port attributes.
9907836SJohn.Forte@Sun.COM 					 * print out error * message and move
9917836SJohn.Forte@Sun.COM 					 * on to the next port
9927836SJohn.Forte@Sun.COM 					 */
9937836SJohn.Forte@Sun.COM 					fprintf(stderr,
9947836SJohn.Forte@Sun.COM 					    gettext("Error: Failed to get port "
9957836SJohn.Forte@Sun.COM 						    "(%d) attributes reason: "),
9967836SJohn.Forte@Sun.COM 					    portIndex);
9977836SJohn.Forte@Sun.COM 					printStatus(status);
9987836SJohn.Forte@Sun.COM 					fprintf(stderr, "\n");
9997836SJohn.Forte@Sun.COM 					continue;
10007836SJohn.Forte@Sun.COM 				}
10017836SJohn.Forte@Sun.COM 				processHBA(handle, attrs, portIndex, port,
10027836SJohn.Forte@Sun.COM 				    NULL, HBA_PORT, processHBA_flags,
10037836SJohn.Forte@Sun.COM 				    TARGET_MODE);
10047836SJohn.Forte@Sun.COM 			}
10057836SJohn.Forte@Sun.COM 		    HBA_CloseAdapter(handle);
10067836SJohn.Forte@Sun.COM 		}
10077836SJohn.Forte@Sun.COM 	    }
10087836SJohn.Forte@Sun.COM 	}
10097836SJohn.Forte@Sun.COM 
10107836SJohn.Forte@Sun.COM 	HBA_FreeLibrary();
10117836SJohn.Forte@Sun.COM 
10127836SJohn.Forte@Sun.COM 	/*
10137836SJohn.Forte@Sun.COM 	 * print additional error msg for partial failure when more than
10147836SJohn.Forte@Sun.COM 	 * one wwn is specified.
10157836SJohn.Forte@Sun.COM 	 */
10167836SJohn.Forte@Sun.COM 	if (err_cnt != 0) {
10177836SJohn.Forte@Sun.COM 	    if (wwnCount > 1) {
10187836SJohn.Forte@Sun.COM 		if (err_cnt == wwnCount) {
10197836SJohn.Forte@Sun.COM 		    fprintf(stderr, gettext(
10207836SJohn.Forte@Sun.COM 		    "Error: All specified HBA ports are not found\n"));
10217836SJohn.Forte@Sun.COM 		} else {
10227836SJohn.Forte@Sun.COM 		    fprintf(stderr, gettext(
10237836SJohn.Forte@Sun.COM 		    "Error: Some of specified HBA ports are not found\n"));
10247836SJohn.Forte@Sun.COM 		}
10257836SJohn.Forte@Sun.COM 	    }
10267836SJohn.Forte@Sun.COM 	    return (1);
10277836SJohn.Forte@Sun.COM 	}
10287836SJohn.Forte@Sun.COM 
10297836SJohn.Forte@Sun.COM 	return (0);
10307836SJohn.Forte@Sun.COM }
10317836SJohn.Forte@Sun.COM 
10327836SJohn.Forte@Sun.COM /*
10337836SJohn.Forte@Sun.COM  * Search the existing device list
10347836SJohn.Forte@Sun.COM  *
10357836SJohn.Forte@Sun.COM  * Take one of two actions:
10367836SJohn.Forte@Sun.COM  *
10377836SJohn.Forte@Sun.COM  * Add an entry if an entry doesn't exist
10387836SJohn.Forte@Sun.COM  * Add WWN data to it if an entry does exist
10397836SJohn.Forte@Sun.COM  *
10407836SJohn.Forte@Sun.COM  * Arguments:
10417836SJohn.Forte@Sun.COM  *	devList - OS device path list
10427836SJohn.Forte@Sun.COM  *	map - target mapping data
10437836SJohn.Forte@Sun.COM  *	index - index into target mapping data
10447836SJohn.Forte@Sun.COM  *	initiatorPortWWN - HBA port WWN
10457836SJohn.Forte@Sun.COM  *	verbose - boolean indicating whether to get additional data
10467836SJohn.Forte@Sun.COM  *
10477836SJohn.Forte@Sun.COM  * returns:
10487836SJohn.Forte@Sun.COM  *	none
10497836SJohn.Forte@Sun.COM  */
10507836SJohn.Forte@Sun.COM static void
searchDevice(discoveredDevice ** devList,HBA_FCPSCSIENTRYV2 entry,HBA_WWN initiatorPortWWN,HBA_HANDLE handle,boolean_t verbose)10517836SJohn.Forte@Sun.COM searchDevice(discoveredDevice **devList, HBA_FCPSCSIENTRYV2 entry,
10527836SJohn.Forte@Sun.COM HBA_WWN initiatorPortWWN, HBA_HANDLE handle, boolean_t verbose)
10537836SJohn.Forte@Sun.COM {
10547836SJohn.Forte@Sun.COM 	discoveredDevice *discoveredDevList, *newDevice;
10557836SJohn.Forte@Sun.COM 	portWWNList *WWNList, *newWWN;
10567836SJohn.Forte@Sun.COM 	tgtPortWWNList *newTgtWWN;
10577836SJohn.Forte@Sun.COM 	boolean_t foundDevice = B_FALSE, foundWWN;
10587836SJohn.Forte@Sun.COM 	struct scsi_inquiry	    inq;
10597836SJohn.Forte@Sun.COM 	struct scsi_extended_sense  sense;
10607836SJohn.Forte@Sun.COM 	HBA_UINT32		    responseSize, senseSize = 0;
10617836SJohn.Forte@Sun.COM 	HBA_UINT8		    inq_status;
10627836SJohn.Forte@Sun.COM 	HBA_STATUS		status;
10637836SJohn.Forte@Sun.COM 
10647836SJohn.Forte@Sun.COM 	for (discoveredDevList = *devList; discoveredDevList != NULL;
10657836SJohn.Forte@Sun.COM 	    discoveredDevList = discoveredDevList->next) {
10667836SJohn.Forte@Sun.COM 		if (strcmp(entry.ScsiId.OSDeviceName,
10677836SJohn.Forte@Sun.COM 		    discoveredDevList->OSDeviceName) == 0) {
10687836SJohn.Forte@Sun.COM 			/*
10697836SJohn.Forte@Sun.COM 			 * if only device names are requested,
10707836SJohn.Forte@Sun.COM 			 * no reason to go any further
10717836SJohn.Forte@Sun.COM 			 */
10727836SJohn.Forte@Sun.COM 			if (verbose == B_FALSE) {
10737836SJohn.Forte@Sun.COM 				return;
10747836SJohn.Forte@Sun.COM 			}
10757836SJohn.Forte@Sun.COM 			foundDevice = B_TRUE;
10767836SJohn.Forte@Sun.COM 			break;
10777836SJohn.Forte@Sun.COM 		}
10787836SJohn.Forte@Sun.COM 	}
10797836SJohn.Forte@Sun.COM 	if (foundDevice == B_TRUE) {
10807836SJohn.Forte@Sun.COM 		/* add initiator Port WWN if it doesn't exist */
10817836SJohn.Forte@Sun.COM 		for (WWNList = discoveredDevList->HBAPortWWN,
10827836SJohn.Forte@Sun.COM 		    foundWWN = B_FALSE; WWNList != NULL;
10837836SJohn.Forte@Sun.COM 		    WWNList = WWNList->next) {
10847836SJohn.Forte@Sun.COM 			if (memcmp((void *)&(WWNList->portWWN),
10857836SJohn.Forte@Sun.COM 			    (void *)&initiatorPortWWN,
10867836SJohn.Forte@Sun.COM 			    sizeof (HBA_WWN)) == 0) {
10877836SJohn.Forte@Sun.COM 				foundWWN = B_TRUE;
10887836SJohn.Forte@Sun.COM 				break;
10897836SJohn.Forte@Sun.COM 			}
10907836SJohn.Forte@Sun.COM 		}
10917836SJohn.Forte@Sun.COM 		if (discoveredDevList->inqSuccess == B_FALSE) {
10927836SJohn.Forte@Sun.COM 			responseSize = sizeof (struct scsi_inquiry);
10937836SJohn.Forte@Sun.COM 			senseSize = sizeof (struct scsi_extended_sense);
10947836SJohn.Forte@Sun.COM 			memset(&inq, 0, sizeof (struct scsi_inquiry));
10957836SJohn.Forte@Sun.COM 			memset(&sense, 0, sizeof (sense));
10967836SJohn.Forte@Sun.COM 			status = HBA_ScsiInquiryV2(
10977836SJohn.Forte@Sun.COM 			    handle,
10987836SJohn.Forte@Sun.COM 			    initiatorPortWWN,
10997836SJohn.Forte@Sun.COM 			    entry.FcpId.PortWWN,
11007836SJohn.Forte@Sun.COM 			    entry.FcpId.FcpLun,
11017836SJohn.Forte@Sun.COM 			    0, /* CDB Byte 1 */
11027836SJohn.Forte@Sun.COM 			    0, /* CDB Byte 2 */
11037836SJohn.Forte@Sun.COM 			    &inq, &responseSize,
11047836SJohn.Forte@Sun.COM 			    &inq_status,
11057836SJohn.Forte@Sun.COM 			    &sense, &senseSize);
11067836SJohn.Forte@Sun.COM 			if (status == HBA_STATUS_OK) {
11077836SJohn.Forte@Sun.COM 				memcpy(discoveredDevList->VID, inq.inq_vid,
11087836SJohn.Forte@Sun.COM 				    sizeof (discoveredDevList->VID));
11097836SJohn.Forte@Sun.COM 				memcpy(discoveredDevList->PID, inq.inq_pid,
11107836SJohn.Forte@Sun.COM 				    sizeof (discoveredDevList->PID));
11117836SJohn.Forte@Sun.COM 				discoveredDevList->dType = inq.inq_dtype;
11127836SJohn.Forte@Sun.COM 				discoveredDevList->inqSuccess = B_TRUE;
11137836SJohn.Forte@Sun.COM 			}
11147836SJohn.Forte@Sun.COM 		}
11157836SJohn.Forte@Sun.COM 
11167836SJohn.Forte@Sun.COM 		if (foundWWN == B_FALSE) {
11177836SJohn.Forte@Sun.COM 			newWWN = (portWWNList *)calloc(1, sizeof (portWWNList));
11187836SJohn.Forte@Sun.COM 			if (newWWN == NULL) {
11197836SJohn.Forte@Sun.COM 				perror("Out of memory");
11207836SJohn.Forte@Sun.COM 				exit(1);
11217836SJohn.Forte@Sun.COM 			}
11227836SJohn.Forte@Sun.COM 
11237836SJohn.Forte@Sun.COM 			/* insert at head */
11247836SJohn.Forte@Sun.COM 			newWWN->next = discoveredDevList->HBAPortWWN;
11257836SJohn.Forte@Sun.COM 			discoveredDevList->HBAPortWWN = newWWN;
11267836SJohn.Forte@Sun.COM 			memcpy((void *)&(newWWN->portWWN),
11277836SJohn.Forte@Sun.COM 			    (void *)&initiatorPortWWN,
11287836SJohn.Forte@Sun.COM 			    sizeof (newWWN->portWWN));
11297836SJohn.Forte@Sun.COM 			/* add Target Port */
11307836SJohn.Forte@Sun.COM 			newWWN->tgtPortWWN = (tgtPortWWNList *)calloc(1,
11317836SJohn.Forte@Sun.COM 			    sizeof (tgtPortWWNList));
11327836SJohn.Forte@Sun.COM 			if (newWWN->tgtPortWWN == NULL) {
11337836SJohn.Forte@Sun.COM 				perror("Out of memory");
11347836SJohn.Forte@Sun.COM 				exit(1);
11357836SJohn.Forte@Sun.COM 			}
11367836SJohn.Forte@Sun.COM 
11377836SJohn.Forte@Sun.COM 			memcpy((void *)&(newWWN->tgtPortWWN->portWWN),
11387836SJohn.Forte@Sun.COM 			    (void *)&(entry.FcpId.PortWWN),
11397836SJohn.Forte@Sun.COM 			    sizeof (newWWN->tgtPortWWN->portWWN));
11407836SJohn.Forte@Sun.COM 			/* Set LUN data */
11417836SJohn.Forte@Sun.COM 			newWWN->tgtPortWWN->scsiOSLun = entry.ScsiId.ScsiOSLun;
11427836SJohn.Forte@Sun.COM 		} else { /* add it to existing */
11437836SJohn.Forte@Sun.COM 			newTgtWWN = (tgtPortWWNList *)calloc(1,
11447836SJohn.Forte@Sun.COM 			    sizeof (tgtPortWWNList));
11457836SJohn.Forte@Sun.COM 			if (newTgtWWN == NULL) {
11467836SJohn.Forte@Sun.COM 				perror("Out of memory");
11477836SJohn.Forte@Sun.COM 				exit(1);
11487836SJohn.Forte@Sun.COM 			}
11497836SJohn.Forte@Sun.COM 			/* insert at head */
11507836SJohn.Forte@Sun.COM 			newTgtWWN->next = WWNList->tgtPortWWN;
11517836SJohn.Forte@Sun.COM 			WWNList->tgtPortWWN = newTgtWWN;
11527836SJohn.Forte@Sun.COM 			memcpy((void *)&(newTgtWWN->portWWN),
11537836SJohn.Forte@Sun.COM 			    (void *)&(entry.FcpId.PortWWN),
11547836SJohn.Forte@Sun.COM 			    sizeof (newTgtWWN->portWWN));
11557836SJohn.Forte@Sun.COM 			/* Set LUN data */
11567836SJohn.Forte@Sun.COM 			newTgtWWN->scsiOSLun = entry.ScsiId.ScsiOSLun;
11577836SJohn.Forte@Sun.COM 		}
11587836SJohn.Forte@Sun.COM 	} else { /* add new entry */
11597836SJohn.Forte@Sun.COM 		newDevice = (discoveredDevice *)calloc(1,
11607836SJohn.Forte@Sun.COM 		    sizeof (discoveredDevice));
11617836SJohn.Forte@Sun.COM 		if (newDevice == NULL) {
11627836SJohn.Forte@Sun.COM 			perror("Out of memory");
11637836SJohn.Forte@Sun.COM 			exit(1);
11647836SJohn.Forte@Sun.COM 		}
11657836SJohn.Forte@Sun.COM 		newDevice->next = *devList; /* insert at head */
11667836SJohn.Forte@Sun.COM 		*devList = newDevice; /* set new head */
11677836SJohn.Forte@Sun.COM 
11687836SJohn.Forte@Sun.COM 		/* Copy device name */
11697836SJohn.Forte@Sun.COM 		strncpy(newDevice->OSDeviceName, entry.ScsiId.OSDeviceName,
11707836SJohn.Forte@Sun.COM 		    sizeof (newDevice->OSDeviceName) - 1);
11717836SJohn.Forte@Sun.COM 
11727836SJohn.Forte@Sun.COM 		/*
11737836SJohn.Forte@Sun.COM 		 * if only device names are requested,
11747836SJohn.Forte@Sun.COM 		 * no reason to go any further
11757836SJohn.Forte@Sun.COM 		 */
11767836SJohn.Forte@Sun.COM 		if (verbose == B_FALSE) {
11777836SJohn.Forte@Sun.COM 			return;
11787836SJohn.Forte@Sun.COM 		}
11797836SJohn.Forte@Sun.COM 
11807836SJohn.Forte@Sun.COM 		/*
11817836SJohn.Forte@Sun.COM 		 * copy WWN data
11827836SJohn.Forte@Sun.COM 		 */
11837836SJohn.Forte@Sun.COM 		newDevice->HBAPortWWN = (portWWNList *)calloc(1,
11847836SJohn.Forte@Sun.COM 		    sizeof (portWWNList));
11857836SJohn.Forte@Sun.COM 		if (newDevice->HBAPortWWN == NULL) {
11867836SJohn.Forte@Sun.COM 			perror("Out of memory");
11877836SJohn.Forte@Sun.COM 			exit(1);
11887836SJohn.Forte@Sun.COM 		}
11897836SJohn.Forte@Sun.COM 		memcpy((void *)&(newDevice->HBAPortWWN->portWWN),
11907836SJohn.Forte@Sun.COM 		    (void *)&initiatorPortWWN, sizeof (newWWN->portWWN));
11917836SJohn.Forte@Sun.COM 
11927836SJohn.Forte@Sun.COM 		newDevice->HBAPortWWN->tgtPortWWN =
11937836SJohn.Forte@Sun.COM 		    (tgtPortWWNList *)calloc(1, sizeof (tgtPortWWNList));
11947836SJohn.Forte@Sun.COM 		if (newDevice->HBAPortWWN->tgtPortWWN == NULL) {
11957836SJohn.Forte@Sun.COM 			perror("Out of memory");
11967836SJohn.Forte@Sun.COM 			exit(1);
11977836SJohn.Forte@Sun.COM 		}
11987836SJohn.Forte@Sun.COM 
11997836SJohn.Forte@Sun.COM 		memcpy((void *)&(newDevice->HBAPortWWN->tgtPortWWN->portWWN),
12007836SJohn.Forte@Sun.COM 		    (void *)&(entry.FcpId.PortWWN),
12017836SJohn.Forte@Sun.COM 		    sizeof (newDevice->HBAPortWWN->tgtPortWWN->portWWN));
12027836SJohn.Forte@Sun.COM 
12037836SJohn.Forte@Sun.COM 		/* Set LUN data */
12047836SJohn.Forte@Sun.COM 		newDevice->HBAPortWWN->tgtPortWWN->scsiOSLun =
12057836SJohn.Forte@Sun.COM 		    entry.ScsiId.ScsiOSLun;
12067836SJohn.Forte@Sun.COM 
12077836SJohn.Forte@Sun.COM 		responseSize = sizeof (struct scsi_inquiry);
12087836SJohn.Forte@Sun.COM 		senseSize = sizeof (struct scsi_extended_sense);
12097836SJohn.Forte@Sun.COM 		memset(&inq, 0, sizeof (struct scsi_inquiry));
12107836SJohn.Forte@Sun.COM 		memset(&sense, 0, sizeof (sense));
12117836SJohn.Forte@Sun.COM 		status = HBA_ScsiInquiryV2(
12127836SJohn.Forte@Sun.COM 		    handle,
12137836SJohn.Forte@Sun.COM 		    initiatorPortWWN,
12147836SJohn.Forte@Sun.COM 		    entry.FcpId.PortWWN,
12157836SJohn.Forte@Sun.COM 		    entry.FcpId.FcpLun,
12167836SJohn.Forte@Sun.COM 		    0, /* CDB Byte 1 */
12177836SJohn.Forte@Sun.COM 		    0, /* CDB Byte 2 */
12187836SJohn.Forte@Sun.COM 		    &inq, &responseSize,
12197836SJohn.Forte@Sun.COM 		    &inq_status,
12207836SJohn.Forte@Sun.COM 		    &sense, &senseSize);
12217836SJohn.Forte@Sun.COM 		if (status != HBA_STATUS_OK) {
12227836SJohn.Forte@Sun.COM 			/* initialize VID/PID/dType as "Unknown" */
12237836SJohn.Forte@Sun.COM 			strcpy(newDevice->VID, "Unknown");
12247836SJohn.Forte@Sun.COM 			strcpy(newDevice->PID, "Unknown");
12257836SJohn.Forte@Sun.COM 			newDevice->dType = DTYPE_UNKNOWN;
12267836SJohn.Forte@Sun.COM 			/* initialize inq status */
12277836SJohn.Forte@Sun.COM 			newDevice->inqSuccess = B_FALSE;
12287836SJohn.Forte@Sun.COM 		} else {
12297836SJohn.Forte@Sun.COM 			memcpy(newDevice->VID, inq.inq_vid,
12307836SJohn.Forte@Sun.COM 			    sizeof (newDevice->VID));
12317836SJohn.Forte@Sun.COM 			memcpy(newDevice->PID, inq.inq_pid,
12327836SJohn.Forte@Sun.COM 			    sizeof (newDevice->PID));
12337836SJohn.Forte@Sun.COM 			newDevice->dType = inq.inq_dtype;
12347836SJohn.Forte@Sun.COM 			/* initialize inq status */
12357836SJohn.Forte@Sun.COM 			newDevice->inqSuccess = B_TRUE;
12367836SJohn.Forte@Sun.COM 		}
12377836SJohn.Forte@Sun.COM 	}
12387836SJohn.Forte@Sun.COM }
12397836SJohn.Forte@Sun.COM 
12407836SJohn.Forte@Sun.COM 
12417836SJohn.Forte@Sun.COM /*
12427836SJohn.Forte@Sun.COM  * process the logical-unit object
12437836SJohn.Forte@Sun.COM  *
12447836SJohn.Forte@Sun.COM  * Arguments:
12457836SJohn.Forte@Sun.COM  *	luCount - count of the number of device paths in paths_argv
12467836SJohn.Forte@Sun.COM  *	    if pathCount > 0, then we will only print information for
12477836SJohn.Forte@Sun.COM  *		the device paths listed in paths_argv
12487836SJohn.Forte@Sun.COM  *	    if pathCount == 0, then we will print information on all device
12497836SJohn.Forte@Sun.COM  *	        paths
12507836SJohn.Forte@Sun.COM  *	luArgv - argument array of device paths
12517836SJohn.Forte@Sun.COM  *	options - any options specified by the caller
12527836SJohn.Forte@Sun.COM  *
12537836SJohn.Forte@Sun.COM  * returns:
12547836SJohn.Forte@Sun.COM  *	0	if successful
12557836SJohn.Forte@Sun.COM  *	> 0	otherwise
12567836SJohn.Forte@Sun.COM  */
12577836SJohn.Forte@Sun.COM int
fc_util_list_logicalunit(int luCount,char ** luArgv,cmdOptions_t * options)12587836SJohn.Forte@Sun.COM fc_util_list_logicalunit(int luCount, char **luArgv, cmdOptions_t *options)
12597836SJohn.Forte@Sun.COM {
12607836SJohn.Forte@Sun.COM 	int			pathCtr, numAdapters, i, count;
12617836SJohn.Forte@Sun.COM 	HBA_STATUS		status;
12627836SJohn.Forte@Sun.COM 	char			adapterName[256];
12637836SJohn.Forte@Sun.COM 	HBA_HANDLE		handle;
12647836SJohn.Forte@Sun.COM 	HBA_PORTATTRIBUTES	port;
12657836SJohn.Forte@Sun.COM 	HBA_ADAPTERATTRIBUTES	attrs;
12667836SJohn.Forte@Sun.COM 	int			portIndex = 0;
12677836SJohn.Forte@Sun.COM 	int			ret = 0;
12687836SJohn.Forte@Sun.COM 	boolean_t		verbose = B_FALSE;
12697836SJohn.Forte@Sun.COM 	HBA_FCPTARGETMAPPINGV2	*map = NULL;
12707836SJohn.Forte@Sun.COM 	discoveredDevice	*devListWalk, *devList = NULL;
12717836SJohn.Forte@Sun.COM 	boolean_t		pathFound;
12727836SJohn.Forte@Sun.COM 
12737836SJohn.Forte@Sun.COM 	/* process each of the options */
12747836SJohn.Forte@Sun.COM 	for (; options->optval; options++) {
12757836SJohn.Forte@Sun.COM 		if (options->optval == 'v') {
12767836SJohn.Forte@Sun.COM 			verbose = B_TRUE;
12777836SJohn.Forte@Sun.COM 		}
12787836SJohn.Forte@Sun.COM 	}
12797836SJohn.Forte@Sun.COM 
12807836SJohn.Forte@Sun.COM 	if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) {
12817836SJohn.Forte@Sun.COM 		fprintf(stderr,
12827836SJohn.Forte@Sun.COM 		    gettext("Failed to load FC-HBA common library\n"));
12837836SJohn.Forte@Sun.COM 		printStatus(status);
12847836SJohn.Forte@Sun.COM 		fprintf(stderr, "\n");
12857836SJohn.Forte@Sun.COM 		return (1);
12867836SJohn.Forte@Sun.COM 	}
12877836SJohn.Forte@Sun.COM 	/*
12887836SJohn.Forte@Sun.COM 	 * Retrieve all device paths. We'll need to traverse the list
12897836SJohn.Forte@Sun.COM 	 * until we find the input paths or all paths if none were given. We
12907836SJohn.Forte@Sun.COM 	 * cannot print as we go since there can be duplicate paths returned
12917836SJohn.Forte@Sun.COM 	 */
12927836SJohn.Forte@Sun.COM 	numAdapters = HBA_GetNumberOfAdapters();
12937836SJohn.Forte@Sun.COM 	if (numAdapters == 0) {
12947836SJohn.Forte@Sun.COM 		return (0);
12957836SJohn.Forte@Sun.COM 	}
12967836SJohn.Forte@Sun.COM 	for (i = 0; i < numAdapters; i++) {
12977836SJohn.Forte@Sun.COM 		int times;
12987836SJohn.Forte@Sun.COM 		status = HBA_GetAdapterName(i, adapterName);
12997836SJohn.Forte@Sun.COM 		if (status != HBA_STATUS_OK) {
13007836SJohn.Forte@Sun.COM 			fprintf(stderr, gettext(
13017836SJohn.Forte@Sun.COM 			    "Failed to get adapter %d. Reason: "), i);
13027836SJohn.Forte@Sun.COM 			printStatus(status);
13037836SJohn.Forte@Sun.COM 			fprintf(stderr, "\n");
13047836SJohn.Forte@Sun.COM 			ret++;
13057836SJohn.Forte@Sun.COM 			continue;
13067836SJohn.Forte@Sun.COM 		}
13077836SJohn.Forte@Sun.COM 		if ((handle = HBA_OpenAdapter(adapterName)) == 0) {
13087836SJohn.Forte@Sun.COM 			fprintf(stderr, gettext("Failed to open adapter %s\n"),
13097836SJohn.Forte@Sun.COM 			    adapterName);
13107836SJohn.Forte@Sun.COM 			ret++;
13117836SJohn.Forte@Sun.COM 			continue;
13127836SJohn.Forte@Sun.COM 		}
13137836SJohn.Forte@Sun.COM 		/* get adapter attributes for the given handle */
13147836SJohn.Forte@Sun.COM 		memset(&attrs, 0, sizeof (attrs));
13157836SJohn.Forte@Sun.COM 		times = 0;
13167836SJohn.Forte@Sun.COM 		status = HBA_GetAdapterAttributes(handle, &attrs);
13177836SJohn.Forte@Sun.COM 		while ((status == HBA_STATUS_ERROR_TRY_AGAIN ||
13187836SJohn.Forte@Sun.COM 		    status == HBA_STATUS_ERROR_BUSY) &&
13197836SJohn.Forte@Sun.COM 		    times++ < HBA_MAX_RETRIES) {
13207836SJohn.Forte@Sun.COM 			(void) sleep(1);
13217836SJohn.Forte@Sun.COM 			status = HBA_GetAdapterAttributes(handle, &attrs);
13227836SJohn.Forte@Sun.COM 			if (status == HBA_STATUS_OK) {
13237836SJohn.Forte@Sun.COM 				break;
13247836SJohn.Forte@Sun.COM 			}
13257836SJohn.Forte@Sun.COM 		}
13267836SJohn.Forte@Sun.COM 		if (status != HBA_STATUS_OK) {
13277836SJohn.Forte@Sun.COM 			fprintf(stderr,
13287836SJohn.Forte@Sun.COM 			    gettext("Failed to get adapter attributes "
13298507SRaghuram.Prahlada@Sun.COM 				    "handle(%d) Reason: "), handle);
13307836SJohn.Forte@Sun.COM 			printStatus(status);
13317836SJohn.Forte@Sun.COM 			fprintf(stderr, "\n");
13327836SJohn.Forte@Sun.COM 			ret++;
13338507SRaghuram.Prahlada@Sun.COM 			HBA_CloseAdapter(handle);
13347836SJohn.Forte@Sun.COM 			continue;
13357836SJohn.Forte@Sun.COM 		}
13367836SJohn.Forte@Sun.COM 
13377836SJohn.Forte@Sun.COM 		/* process each port on adapter */
13387836SJohn.Forte@Sun.COM 		for (portIndex = 0; portIndex < attrs.NumberOfPorts;
13397836SJohn.Forte@Sun.COM 		    portIndex++) {
13407836SJohn.Forte@Sun.COM 			memset(&port, 0, sizeof (port));
13417836SJohn.Forte@Sun.COM 			if ((status = HBA_GetAdapterPortAttributes(handle,
13427836SJohn.Forte@Sun.COM 			    portIndex, &port)) != HBA_STATUS_OK) {
13437836SJohn.Forte@Sun.COM 				/*
13447836SJohn.Forte@Sun.COM 				 * not able to get port attributes.
13457836SJohn.Forte@Sun.COM 				 * print out error message and move
13467836SJohn.Forte@Sun.COM 				 * on to the next port
13477836SJohn.Forte@Sun.COM 				 */
13487836SJohn.Forte@Sun.COM 				fprintf(stderr, gettext("Failed to get port "
13497836SJohn.Forte@Sun.COM 				    "(%d) attributes reason: "),
13507836SJohn.Forte@Sun.COM 				    portIndex);
13517836SJohn.Forte@Sun.COM 				printStatus(status);
13527836SJohn.Forte@Sun.COM 				fprintf(stderr, "\n");
13537836SJohn.Forte@Sun.COM 				ret++;
13547836SJohn.Forte@Sun.COM 				continue;
13557836SJohn.Forte@Sun.COM 			}
13567836SJohn.Forte@Sun.COM 
13577836SJohn.Forte@Sun.COM 			/* get OS Device Paths */
13587836SJohn.Forte@Sun.COM 			getTargetMapping(handle, port.PortWWN, &map);
13597836SJohn.Forte@Sun.COM 			if (map != NULL) {
13607836SJohn.Forte@Sun.COM 				for (count = 0; count < map->NumberOfEntries;
13617836SJohn.Forte@Sun.COM 				    count++) {
13627836SJohn.Forte@Sun.COM 					searchDevice(&devList,
13637836SJohn.Forte@Sun.COM 					    map->entry[count], port.PortWWN,
13647836SJohn.Forte@Sun.COM 					    handle, verbose);
13657836SJohn.Forte@Sun.COM 				}
13667836SJohn.Forte@Sun.COM 			}
13677836SJohn.Forte@Sun.COM 		}
13687836SJohn.Forte@Sun.COM 		HBA_CloseAdapter(handle);
13697836SJohn.Forte@Sun.COM 	}
13707836SJohn.Forte@Sun.COM 	HBA_FreeLibrary();
13717836SJohn.Forte@Sun.COM 
13727836SJohn.Forte@Sun.COM 	if (luCount == 0) {
13737836SJohn.Forte@Sun.COM 		/* list all paths */
13747836SJohn.Forte@Sun.COM 		for (devListWalk = devList; devListWalk != NULL;
13757836SJohn.Forte@Sun.COM 		    devListWalk = devListWalk->next) {
13767836SJohn.Forte@Sun.COM 			printOSDeviceNameInfo(devListWalk, verbose);
13777836SJohn.Forte@Sun.COM 		}
13787836SJohn.Forte@Sun.COM 	} else {
13797836SJohn.Forte@Sun.COM 		/*
13807836SJohn.Forte@Sun.COM 		 * list any paths not found first
13817836SJohn.Forte@Sun.COM 		 * this gives the user cleaner output
13827836SJohn.Forte@Sun.COM 		 */
13837836SJohn.Forte@Sun.COM 		for (pathCtr = 0; pathCtr < luCount; pathCtr++) {
13847836SJohn.Forte@Sun.COM 			for (devListWalk = devList, pathFound = B_FALSE;
13857836SJohn.Forte@Sun.COM 			    devListWalk != NULL;
13867836SJohn.Forte@Sun.COM 			    devListWalk = devListWalk->next) {
13877836SJohn.Forte@Sun.COM 				if (strcmp(devListWalk->OSDeviceName,
13887836SJohn.Forte@Sun.COM 				    luArgv[pathCtr]) == 0) {
13897836SJohn.Forte@Sun.COM 					pathFound = B_TRUE;
13907836SJohn.Forte@Sun.COM 				}
13917836SJohn.Forte@Sun.COM 			}
13927836SJohn.Forte@Sun.COM 			if (pathFound == B_FALSE) {
13937836SJohn.Forte@Sun.COM 				fprintf(stderr, "%s: no such path\n",
13947836SJohn.Forte@Sun.COM 				    luArgv[pathCtr]);
13957836SJohn.Forte@Sun.COM 				ret++;
13967836SJohn.Forte@Sun.COM 			}
13977836SJohn.Forte@Sun.COM 		}
13987836SJohn.Forte@Sun.COM 		/* list all paths requested in order requested */
13997836SJohn.Forte@Sun.COM 		for (pathCtr = 0; pathCtr < luCount; pathCtr++) {
14007836SJohn.Forte@Sun.COM 			for (devListWalk = devList; devListWalk != NULL;
14017836SJohn.Forte@Sun.COM 			    devListWalk = devListWalk->next) {
14027836SJohn.Forte@Sun.COM 				if (strcmp(devListWalk->OSDeviceName,
14037836SJohn.Forte@Sun.COM 				    luArgv[pathCtr]) == 0) {
14047836SJohn.Forte@Sun.COM 					printOSDeviceNameInfo(devListWalk,
14057836SJohn.Forte@Sun.COM 					    verbose);
14067836SJohn.Forte@Sun.COM 				}
14077836SJohn.Forte@Sun.COM 			}
14087836SJohn.Forte@Sun.COM 		}
14097836SJohn.Forte@Sun.COM 	}
14107836SJohn.Forte@Sun.COM 	return (ret);
14117836SJohn.Forte@Sun.COM }
1412