xref: /illumos-gate/usr/src/lib/sun_sas/common/devtree_device_disco.c (revision 00f453f4ebc211cb928f19a54d3f4edd61f43279)
19e86db79SHyon Kim /*
29e86db79SHyon Kim  * CDDL HEADER START
39e86db79SHyon Kim  *
49e86db79SHyon Kim  * The contents of this file are subject to the terms of the
59e86db79SHyon Kim  * Common Development and Distribution License (the "License").
69e86db79SHyon Kim  * You may not use this file except in compliance with the License.
79e86db79SHyon Kim  *
89e86db79SHyon Kim  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99e86db79SHyon Kim  * or http://www.opensolaris.org/os/licensing.
109e86db79SHyon Kim  * See the License for the specific language governing permissions
119e86db79SHyon Kim  * and limitations under the License.
129e86db79SHyon Kim  *
139e86db79SHyon Kim  * When distributing Covered Code, include this CDDL HEADER in each
149e86db79SHyon Kim  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159e86db79SHyon Kim  * If applicable, add the following below this CDDL HEADER, with the
169e86db79SHyon Kim  * fields enclosed by brackets "[]" replaced with your own identifying
179e86db79SHyon Kim  * information: Portions Copyright [yyyy] [name of copyright owner]
189e86db79SHyon Kim  *
199e86db79SHyon Kim  * CDDL HEADER END
209e86db79SHyon Kim  */
219e86db79SHyon Kim 
229e86db79SHyon Kim /*
239e86db79SHyon Kim  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
249e86db79SHyon Kim  * Use is subject to license terms.
25b0459908SJosef 'Jeff' Sipek  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
26*00f453f4SRob Johnston  * Copyright 2019 Joyent, Inc.
279e86db79SHyon Kim  */
289e86db79SHyon Kim 
299e86db79SHyon Kim #include	<sun_sas.h>
309e86db79SHyon Kim #include	<sys/types.h>
319e86db79SHyon Kim #include	<netinet/in.h>
329e86db79SHyon Kim #include	<inttypes.h>
339e86db79SHyon Kim #include	<ctype.h>
349e86db79SHyon Kim #include	<sys/scsi/scsi_address.h>
359e86db79SHyon Kim #include	<libdevid.h>
369e86db79SHyon Kim 
379e86db79SHyon Kim /*
389e86db79SHyon Kim  * Get the preferred minor node for the given path.
399e86db79SHyon Kim  * ":n" for tapes, ":c,raw" for disks,
409e86db79SHyon Kim  * and ":0" for enclosures.
419e86db79SHyon Kim  */
429e86db79SHyon Kim static void
get_minor(char * devpath,char * minor)439e86db79SHyon Kim get_minor(char *devpath, char *minor)
449e86db79SHyon Kim {
459e86db79SHyon Kim 	const char	ROUTINE[] = "get_minor";
469e86db79SHyon Kim 	char	fullpath[MAXPATHLEN];
479e86db79SHyon Kim 	int	fd;
489e86db79SHyon Kim 
499e86db79SHyon Kim 	if ((strstr(devpath, "/st@")) || (strstr(devpath, "/tape@"))) {
509e86db79SHyon Kim 		(void) strcpy(minor, ":n");
519e86db79SHyon Kim 	} else if (strstr(devpath, "/smp@")) {
529e86db79SHyon Kim 		(void) strcpy(minor, ":smp");
539e86db79SHyon Kim 	} else if ((strstr(devpath, "/ssd@")) || (strstr(devpath, "/sd@")) ||
549e86db79SHyon Kim 	    (strstr(devpath, "/disk@"))) {
559e86db79SHyon Kim 		(void) strcpy(minor, ":c,raw");
569e86db79SHyon Kim 	} else if ((strstr(devpath, "/ses@")) || (strstr(devpath,
579e86db79SHyon Kim 	    "/enclosure@"))) {
589e86db79SHyon Kim 		(void) snprintf(fullpath, MAXPATHLEN, "%s%s%s", DEVICES_DIR,
599e86db79SHyon Kim 		    devpath, ":0");
609e86db79SHyon Kim 		/* reset errno to 0 */
619e86db79SHyon Kim 		errno = 0;
629e86db79SHyon Kim 		if ((fd = open(fullpath, O_RDONLY)) == -1) {
639e86db79SHyon Kim 			/*
649e86db79SHyon Kim 			 * :0 minor doesn't exist. assume bound to sgen driver
659e86db79SHyon Kim 			 * and :ses minor exist.
669e86db79SHyon Kim 			 */
679e86db79SHyon Kim 			if (errno == ENOENT) {
689e86db79SHyon Kim 				(void) strcpy(minor, ":ses");
699e86db79SHyon Kim 			}
709e86db79SHyon Kim 		} else {
719e86db79SHyon Kim 			(void) strcpy(minor, ":0");
729e86db79SHyon Kim 			(void) close(fd);
739e86db79SHyon Kim 		}
749e86db79SHyon Kim 	} else {
759e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE, "Unrecognized target (%s)",
769e86db79SHyon Kim 		    devpath);
779e86db79SHyon Kim 		minor[0] = '\0';
789e86db79SHyon Kim 	}
799e86db79SHyon Kim 
809e86db79SHyon Kim }
819e86db79SHyon Kim 
829e86db79SHyon Kim /*
839e86db79SHyon Kim  * Free the attached port allocation.
849e86db79SHyon Kim  */
859e86db79SHyon Kim static void
free_attached_port(struct sun_sas_port * port_ptr)869e86db79SHyon Kim free_attached_port(struct sun_sas_port *port_ptr)
879e86db79SHyon Kim {
889e86db79SHyon Kim 	struct sun_sas_port *tgt_port, *last_tgt_port;
899e86db79SHyon Kim 	struct ScsiEntryList *scsi_info = NULL, *last_scsi_info = NULL;
909e86db79SHyon Kim 
919e86db79SHyon Kim 	tgt_port = port_ptr->first_attached_port;
929e86db79SHyon Kim 	while (tgt_port != NULL) {
939e86db79SHyon Kim 		/* Free target mapping data list first. */
949e86db79SHyon Kim 		scsi_info = tgt_port->scsiInfo;
959e86db79SHyon Kim 		while (scsi_info != NULL) {
969e86db79SHyon Kim 			last_scsi_info = scsi_info;
979e86db79SHyon Kim 			scsi_info = scsi_info->next;
989e86db79SHyon Kim 			free(last_scsi_info);
999e86db79SHyon Kim 		}
1009e86db79SHyon Kim 		last_tgt_port = tgt_port;
1019e86db79SHyon Kim 		tgt_port = tgt_port->next;
1029e86db79SHyon Kim 		free(last_tgt_port->port_attributes.\
1039e86db79SHyon Kim 		    PortSpecificAttribute.SASPort);
1049e86db79SHyon Kim 		free(last_tgt_port);
1059e86db79SHyon Kim 	}
1069e86db79SHyon Kim 
1079e86db79SHyon Kim 	port_ptr->first_attached_port = NULL;
1089e86db79SHyon Kim 	port_ptr->port_attributes.PortSpecificAttribute.\
1099e86db79SHyon Kim 	    SASPort->NumberofDiscoveredPorts = 0;
1109e86db79SHyon Kim }
1119e86db79SHyon Kim 
1129e86db79SHyon Kim /*
1139e86db79SHyon Kim  * Fill domainPortWWN.
1149e86db79SHyon Kim  * should be called after completing discovered port discovery.
1159e86db79SHyon Kim  */
1169e86db79SHyon Kim void
fillDomainPortWWN(struct sun_sas_port * port_ptr)1179e86db79SHyon Kim fillDomainPortWWN(struct sun_sas_port *port_ptr)
1189e86db79SHyon Kim {
1199e86db79SHyon Kim 	const char    ROUTINE[] = "fillDomainPortWWN";
1209e86db79SHyon Kim 	struct sun_sas_port *disco_port_ptr;
1219e86db79SHyon Kim 	struct phy_info *phy_ptr;
1229e86db79SHyon Kim 	uint64_t    domainPort = 0;
1239e86db79SHyon Kim 	struct ScsiEntryList	    *mapping_ptr;
1249e86db79SHyon Kim 
1259e86db79SHyon Kim 	for (disco_port_ptr = port_ptr->first_attached_port;
1269e86db79SHyon Kim 	    disco_port_ptr != NULL; disco_port_ptr = disco_port_ptr->next) {
1279e86db79SHyon Kim 		if (disco_port_ptr->port_attributes.PortType ==
1289e86db79SHyon Kim 		    HBA_PORTTYPE_SASEXPANDER &&
1299e86db79SHyon Kim 		    wwnConversion(disco_port_ptr->port_attributes.
1309e86db79SHyon Kim 		    PortSpecificAttribute.SASPort->
1319e86db79SHyon Kim 		    AttachedSASAddress.wwn) ==
1329e86db79SHyon Kim 		    wwnConversion(port_ptr->port_attributes.
1339e86db79SHyon Kim 		    PortSpecificAttribute.SASPort->
1349e86db79SHyon Kim 		    LocalSASAddress.wwn)) {
1359e86db79SHyon Kim 			(void) memcpy(&domainPort,
1369e86db79SHyon Kim 			    disco_port_ptr->port_attributes.
1379e86db79SHyon Kim 			    PortSpecificAttribute.
1389e86db79SHyon Kim 			    SASPort->LocalSASAddress.wwn, 8);
1399e86db79SHyon Kim 			break;
1409e86db79SHyon Kim 		}
1419e86db79SHyon Kim 	}
1429e86db79SHyon Kim 
1439e86db79SHyon Kim 	if (domainPort == 0) {
1449e86db79SHyon Kim 		if (port_ptr->first_attached_port) {
1459e86db79SHyon Kim 			/*
1469e86db79SHyon Kim 			 * there is no expander device attached on an HBA port
1479e86db79SHyon Kim 			 * domainPortWWN should not stay to 0 since multiple
1489e86db79SHyon Kim 			 * hba ports can have the same LocalSASAddres within
1499e86db79SHyon Kim 			 * the same HBA.
1509e86db79SHyon Kim 			 * Set the SAS address of direct attached target.
1519e86db79SHyon Kim 			 */
1529e86db79SHyon Kim 			if (wwnConversion(port_ptr->port_attributes.
1539e86db79SHyon Kim 			    PortSpecificAttribute.SASPort->
1549e86db79SHyon Kim 			    LocalSASAddress.wwn) ==
1559e86db79SHyon Kim 			    wwnConversion(port_ptr->first_attached_port->
1569e86db79SHyon Kim 			    port_attributes.PortSpecificAttribute.
1579e86db79SHyon Kim 			    SASPort->AttachedSASAddress.wwn)) {
1589e86db79SHyon Kim 				(void) memcpy(&domainPort,
1599e86db79SHyon Kim 				    port_ptr->first_attached_port->
1609e86db79SHyon Kim 				    port_attributes.PortSpecificAttribute.
1619e86db79SHyon Kim 				    SASPort->LocalSASAddress.wwn, 8);
1629e86db79SHyon Kim 			} else {
1639e86db79SHyon Kim 				/*
1649e86db79SHyon Kim 				 * SAS address is not upstream connected.
1659e86db79SHyon Kim 				 * domainPortWWN stays as 0.
1669e86db79SHyon Kim 				 */
1679e86db79SHyon Kim 				log(LOG_DEBUG, ROUTINE,
1689e86db79SHyon Kim 				    "DomainPortWWN is not set. "
1699e86db79SHyon Kim 				    "Device(s) are visible on the HBA port "
1709e86db79SHyon Kim 				    "but there is no expander or directly "
1719e86db79SHyon Kim 				    "attached port with matching upsteam "
1729e86db79SHyon Kim 				    "attached SAS address for "
1739e86db79SHyon Kim 				    "HBA port (Local SAS Address: %016llx).",
1749e86db79SHyon Kim 				    wwnConversion(port_ptr->port_attributes.
1759e86db79SHyon Kim 				    PortSpecificAttribute.
1769e86db79SHyon Kim 				    SASPort->LocalSASAddress.wwn));
1779e86db79SHyon Kim 				return;
1789e86db79SHyon Kim 			}
1799e86db79SHyon Kim 		} else {
1809e86db79SHyon Kim 			/*
1819e86db79SHyon Kim 			 * There existss an iport without properly configured
1829e86db79SHyon Kim 			 * child smp ndoes or  child node or pathinfo.
1839e86db79SHyon Kim 			 * domainPortWWN stays as 0.
1849e86db79SHyon Kim 			 */
1859e86db79SHyon Kim 			log(LOG_DEBUG, ROUTINE,
1869e86db79SHyon Kim 			    "DomainPortWWN is not set.  No properly "
1879e86db79SHyon Kim 			    "configured smp or directly attached port "
1889e86db79SHyon Kim 			    "found on HBA port(Local SAS Address: %016llx).",
1899e86db79SHyon Kim 			    wwnConversion(port_ptr->port_attributes.
1909e86db79SHyon Kim 			    PortSpecificAttribute.
1919e86db79SHyon Kim 			    SASPort->LocalSASAddress.wwn));
1929e86db79SHyon Kim 			return;
1939e86db79SHyon Kim 		}
1949e86db79SHyon Kim 	}
1959e86db79SHyon Kim 
1969e86db79SHyon Kim 	/* fill up phy info */
1979e86db79SHyon Kim 	for (phy_ptr = port_ptr->first_phy; phy_ptr != NULL;
1989e86db79SHyon Kim 	    phy_ptr = phy_ptr->next) {
1999e86db79SHyon Kim 		(void) memcpy(phy_ptr->phy.domainPortWWN.wwn, &domainPort, 8);
2009e86db79SHyon Kim 	}
2019e86db79SHyon Kim 
2029e86db79SHyon Kim 	/* fill up target mapping */
2039e86db79SHyon Kim 	for (disco_port_ptr = port_ptr->first_attached_port;
2049e86db79SHyon Kim 	    disco_port_ptr != NULL; disco_port_ptr = disco_port_ptr->next) {
2059e86db79SHyon Kim 		for (mapping_ptr = disco_port_ptr->scsiInfo;
2069e86db79SHyon Kim 		    mapping_ptr != NULL;
2079e86db79SHyon Kim 		    mapping_ptr = mapping_ptr->next) {
2089e86db79SHyon Kim 			(void) memcpy(mapping_ptr->entry.PortLun.
2099e86db79SHyon Kim 			    domainPortWWN.wwn, &domainPort, 8);
2109e86db79SHyon Kim 		}
2119e86db79SHyon Kim 	}
2129e86db79SHyon Kim }
2139e86db79SHyon Kim 
2149e86db79SHyon Kim /*
2159e86db79SHyon Kim  * Finds attached device(target) from devinfo node.
2169e86db79SHyon Kim  */
2179e86db79SHyon Kim static HBA_STATUS
get_attached_devices_info(di_node_t node,struct sun_sas_port * port_ptr)2189e86db79SHyon Kim get_attached_devices_info(di_node_t node, struct sun_sas_port *port_ptr)
2199e86db79SHyon Kim {
2209e86db79SHyon Kim 	const char		    ROUTINE[] = "get_attached_devices_info";
2219e86db79SHyon Kim 	char			    *propStringData = NULL;
2229e86db79SHyon Kim 	int			    *propIntData = NULL;
2239e86db79SHyon Kim 	int64_t			    *propInt64Data = NULL;
2249e86db79SHyon Kim 	scsi_lun_t		    samLun;
225f94d63efSHyon Kim 	ddi_devid_t		    devid;
226f94d63efSHyon Kim 	char			    *guidStr;
2279e86db79SHyon Kim 	char			    *unit_address;
2289e86db79SHyon Kim 	char			    *charptr;
2299e86db79SHyon Kim 	char			    *devpath, link[MAXNAMELEN];
2309e86db79SHyon Kim 	char			    fullpath[MAXPATHLEN+1];
2319e86db79SHyon Kim 	char			    minorname[MAXNAMELEN+1];
232*00f453f4SRob Johnston 	SMHBA_PORTATTRIBUTES	    *portattrs;
2339e86db79SHyon Kim 	struct ScsiEntryList	    *mapping_ptr;
2349e86db79SHyon Kim 	HBA_WWN			    SASAddress, AttachedSASAddress;
2359e86db79SHyon Kim 	struct sun_sas_port	    *disco_port_ptr;
2369e86db79SHyon Kim 	uint_t			    state = 0;
237f94d63efSHyon Kim 	int			    portfound, rval, size;
2389e86db79SHyon Kim 	int			    port_state = HBA_PORTSTATE_ONLINE;
2399e86db79SHyon Kim 	uint64_t		    tmpAddr;
2409e86db79SHyon Kim 
2419e86db79SHyon Kim 	if (port_ptr == NULL) {
2429e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE, "NULL port_ptr argument");
2439e86db79SHyon Kim 		return (HBA_STATUS_ERROR);
2449e86db79SHyon Kim 	}
2459e86db79SHyon Kim 
2469e86db79SHyon Kim 	if ((devpath = di_devfs_path(node)) == NULL) {
2479e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
2489e86db79SHyon Kim 		    "Device in device tree has no path. Skipping.");
2499e86db79SHyon Kim 		return (HBA_STATUS_ERROR);
2509e86db79SHyon Kim 	}
2519e86db79SHyon Kim 
2529e86db79SHyon Kim 	if ((di_instance(node) == -1) || di_retired(node)) {
2539e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
2549e86db79SHyon Kim 		    "dev node (%s) returned instance of -1 or is retired. "
2559e86db79SHyon Kim 		    " Skipping.", devpath);
2569e86db79SHyon Kim 		di_devfs_path_free(devpath);
2579e86db79SHyon Kim 		return (HBA_STATUS_OK);
2589e86db79SHyon Kim 	}
2599e86db79SHyon Kim 	state = di_state(node);
2609e86db79SHyon Kim 	/* when node is not attached and online, set the state to offline. */
2619e86db79SHyon Kim 	if (((state & DI_DRIVER_DETACHED) == DI_DRIVER_DETACHED) ||
2629e86db79SHyon Kim 	    ((state & DI_DEVICE_OFFLINE) == DI_DEVICE_OFFLINE)) {
2639e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
2649e86db79SHyon Kim 		    "dev node (%s) is either OFFLINE or DETACHED",
2659e86db79SHyon Kim 		    devpath);
2669e86db79SHyon Kim 		port_state = HBA_PORTSTATE_OFFLINE;
2679e86db79SHyon Kim 	}
2689e86db79SHyon Kim 
2699e86db79SHyon Kim 	/* add the "/devices" in the begining at the end */
2709e86db79SHyon Kim 	(void) snprintf(fullpath, sizeof (fullpath), "%s%s",
2719e86db79SHyon Kim 	    DEVICES_DIR, devpath);
2729e86db79SHyon Kim 
2739e86db79SHyon Kim 	(void) memset(&SASAddress, 0, sizeof (SASAddress));
2749e86db79SHyon Kim 	if ((unit_address = di_bus_addr(node)) != NULL) {
2759e86db79SHyon Kim 		if ((charptr = strchr(unit_address, ',')) != NULL) {
2769e86db79SHyon Kim 			*charptr = '\0';
2779e86db79SHyon Kim 		}
2789e86db79SHyon Kim 		for (charptr = unit_address; *charptr != '\0'; charptr++) {
2799e86db79SHyon Kim 			if (isxdigit(*charptr)) {
2809e86db79SHyon Kim 				break;
2819e86db79SHyon Kim 			}
2829e86db79SHyon Kim 		}
2839e86db79SHyon Kim 		if (*charptr != '\0') {
2849e86db79SHyon Kim 			tmpAddr = htonll(strtoll(charptr, NULL, 16));
2859e86db79SHyon Kim 			(void) memcpy(&SASAddress.wwn[0], &tmpAddr, 8);
2869e86db79SHyon Kim 		} else {
2879e86db79SHyon Kim 			log(LOG_DEBUG, ROUTINE,
2889e86db79SHyon Kim 			    "No proper target port info on unit address of %s",
2899e86db79SHyon Kim 			    fullpath);
2909e86db79SHyon Kim 			di_devfs_path_free(devpath);
2919e86db79SHyon Kim 			return (HBA_STATUS_ERROR);
2929e86db79SHyon Kim 		}
2939e86db79SHyon Kim 	} else {
2949e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
2959e86db79SHyon Kim 		    "Fail to get unit address of %s.",
2969e86db79SHyon Kim 		    fullpath);
2979e86db79SHyon Kim 		di_devfs_path_free(devpath);
2989e86db79SHyon Kim 		return (HBA_STATUS_ERROR);
2999e86db79SHyon Kim 	}
3009e86db79SHyon Kim 
3019e86db79SHyon Kim 	(void) memset(&AttachedSASAddress, 0, sizeof (AttachedSASAddress));
3029e86db79SHyon Kim 	if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "attached-port",
3039e86db79SHyon Kim 	    &propStringData) != -1) {
3049e86db79SHyon Kim 		for (charptr = propStringData; *charptr != '\0'; charptr++) {
3059e86db79SHyon Kim 			if (isxdigit(*charptr)) {
3069e86db79SHyon Kim 				break;
3079e86db79SHyon Kim 			}
3089e86db79SHyon Kim 		}
3099e86db79SHyon Kim 		if (*charptr != '\0') {
3109e86db79SHyon Kim 			tmpAddr = htonll(strtoll(charptr, NULL, 16));
3119e86db79SHyon Kim 			(void) memcpy(AttachedSASAddress.wwn, &tmpAddr, 8);
3129e86db79SHyon Kim 			/* check the attached address of hba port. */
3139e86db79SHyon Kim 			if (memcmp(port_ptr->port_attributes.
3149e86db79SHyon Kim 			    PortSpecificAttribute.SASPort->LocalSASAddress.wwn,
3159e86db79SHyon Kim 			    &tmpAddr, 8) == 0) {
3169e86db79SHyon Kim 				/*
3179e86db79SHyon Kim 				 * When attached-port is set from iport
3189e86db79SHyon Kim 				 * attached-port prop, we do the cross check
3199e86db79SHyon Kim 				 * with device's own SAS address.
3209e86db79SHyon Kim 				 *
3219e86db79SHyon Kim 				 * If not set, we store device's own SAS
3229e86db79SHyon Kim 				 * address to iport attached SAS address.
3239e86db79SHyon Kim 				 */
3249e86db79SHyon Kim 				if (wwnConversion(port_ptr->port_attributes.
3259e86db79SHyon Kim 				    PortSpecificAttribute.SASPort->
3269e86db79SHyon Kim 				    AttachedSASAddress.wwn)) {
3279e86db79SHyon Kim 					/* verify the Attaached SAS Addr. */
3289e86db79SHyon Kim 					if (memcmp(port_ptr->port_attributes.
3299e86db79SHyon Kim 					    PortSpecificAttribute.SASPort->
3309e86db79SHyon Kim 					    AttachedSASAddress.wwn,
3319e86db79SHyon Kim 					    SASAddress.wwn, 8) != 0) {
3329e86db79SHyon Kim 				/* indentation move begin. */
3339e86db79SHyon Kim 				log(LOG_DEBUG, ROUTINE,
3349e86db79SHyon Kim 				    "iport attached-port(%016llx) do not"
3359e86db79SHyon Kim 				    " match with level 1 Local"
3369e86db79SHyon Kim 				    " SAS address(%016llx).",
3379e86db79SHyon Kim 				    wwnConversion(port_ptr->port_attributes.
3389e86db79SHyon Kim 				    PortSpecificAttribute.
3399e86db79SHyon Kim 				    SASPort->AttachedSASAddress.wwn),
3409e86db79SHyon Kim 				    wwnConversion(SASAddress.wwn));
3419e86db79SHyon Kim 				di_devfs_path_free(devpath);
3429e86db79SHyon Kim 				free_attached_port(port_ptr);
3439e86db79SHyon Kim 				return (HBA_STATUS_ERROR);
3449e86db79SHyon Kim 				/* indentation move ends. */
3459e86db79SHyon Kim 					}
3469e86db79SHyon Kim 				} else {
3479e86db79SHyon Kim 					(void) memcpy(port_ptr->port_attributes.
3489e86db79SHyon Kim 					    PortSpecificAttribute.
3499e86db79SHyon Kim 					    SASPort->AttachedSASAddress.wwn,
3509e86db79SHyon Kim 					    &SASAddress.wwn[0], 8);
3519e86db79SHyon Kim 				}
3529e86db79SHyon Kim 			}
3539e86db79SHyon Kim 		} else {
3549e86db79SHyon Kim 			log(LOG_DEBUG, ROUTINE,
3559e86db79SHyon Kim 			    "No proper attached SAS address value on device %s",
3569e86db79SHyon Kim 			    fullpath);
3579e86db79SHyon Kim 			di_devfs_path_free(devpath);
3589e86db79SHyon Kim 			free_attached_port(port_ptr);
3599e86db79SHyon Kim 			return (HBA_STATUS_ERROR);
3609e86db79SHyon Kim 		}
3619e86db79SHyon Kim 	} else {
3629e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
3639e86db79SHyon Kim 		    "Property AttachedSASAddress not found for device \"%s\"",
3649e86db79SHyon Kim 		    fullpath);
3659e86db79SHyon Kim 		di_devfs_path_free(devpath);
3669e86db79SHyon Kim 		free_attached_port(port_ptr);
3679e86db79SHyon Kim 		return (HBA_STATUS_ERROR);
3689e86db79SHyon Kim 	}
3699e86db79SHyon Kim 
3709e86db79SHyon Kim 	/*
3719e86db79SHyon Kim 	 * walk the disco list to make sure that there isn't a matching
3729e86db79SHyon Kim 	 * port and node wwn or a matching device path
3739e86db79SHyon Kim 	 */
3749e86db79SHyon Kim 	portfound = 0;
3759e86db79SHyon Kim 	for (disco_port_ptr = port_ptr->first_attached_port;
3769e86db79SHyon Kim 	    disco_port_ptr != NULL;
3779e86db79SHyon Kim 	    disco_port_ptr = disco_port_ptr->next) {
3789e86db79SHyon Kim 		if ((disco_port_ptr->port_attributes.PortState !=
3799e86db79SHyon Kim 		    HBA_PORTSTATE_ERROR) && (memcmp(disco_port_ptr->
3809e86db79SHyon Kim 		    port_attributes.PortSpecificAttribute.
3819e86db79SHyon Kim 		    SASPort->LocalSASAddress.wwn, SASAddress.wwn, 8) == 0)) {
3829e86db79SHyon Kim 			/*
3839e86db79SHyon Kim 			 * found matching disco_port
3849e86db79SHyon Kim 			 * look for matching device path
3859e86db79SHyon Kim 			 */
3869e86db79SHyon Kim 			portfound = 1;
3879e86db79SHyon Kim 			for (mapping_ptr = disco_port_ptr->scsiInfo;
3889e86db79SHyon Kim 			    mapping_ptr != NULL;
3899e86db79SHyon Kim 			    mapping_ptr = mapping_ptr->next) {
3909e86db79SHyon Kim 				if (strstr(mapping_ptr-> entry.ScsiId.
3919e86db79SHyon Kim 				    OSDeviceName, devpath) != 0) {
3929e86db79SHyon Kim 					log(LOG_DEBUG, ROUTINE,
3939e86db79SHyon Kim 					    "Found an already discovered "
3949e86db79SHyon Kim 					    "device %s.", fullpath);
3959e86db79SHyon Kim 					di_devfs_path_free(devpath);
3969e86db79SHyon Kim 					return (HBA_STATUS_OK);
3979e86db79SHyon Kim 				}
3989e86db79SHyon Kim 			}
3999e86db79SHyon Kim 			if (portfound == 1) {
4009e86db79SHyon Kim 				break;
4019e86db79SHyon Kim 			}
4029e86db79SHyon Kim 		}
4039e86db79SHyon Kim 	}
4049e86db79SHyon Kim 
4059e86db79SHyon Kim 	if (portfound == 0) {
4069e86db79SHyon Kim 		/*
4079e86db79SHyon Kim 		 * there are no matching SAS address.
4089e86db79SHyon Kim 		 * this must be a new device
4099e86db79SHyon Kim 		 */
4109e86db79SHyon Kim 		if ((disco_port_ptr = (struct sun_sas_port *)calloc(1,
4119e86db79SHyon Kim 		    sizeof (struct sun_sas_port))) == NULL)  {
4129e86db79SHyon Kim 			OUT_OF_MEMORY(ROUTINE);
4139e86db79SHyon Kim 			di_devfs_path_free(devpath);
4149e86db79SHyon Kim 			free_attached_port(port_ptr);
4159e86db79SHyon Kim 			return (HBA_STATUS_ERROR);
4169e86db79SHyon Kim 		}
4179e86db79SHyon Kim 
4189e86db79SHyon Kim 		if ((disco_port_ptr->port_attributes.PortSpecificAttribute.\
4199e86db79SHyon Kim 		    SASPort = (struct SMHBA_SAS_Port *)calloc(1,
4209e86db79SHyon Kim 		    sizeof (struct SMHBA_SAS_Port))) == NULL) {
4219e86db79SHyon Kim 			OUT_OF_MEMORY("add_hba_port_info");
4229e86db79SHyon Kim 			di_devfs_path_free(devpath);
4239e86db79SHyon Kim 			free_attached_port(port_ptr);
4249e86db79SHyon Kim 			return (HBA_STATUS_ERROR);
4259e86db79SHyon Kim 		}
4269e86db79SHyon Kim 
4279e86db79SHyon Kim 		(void) memcpy(disco_port_ptr->port_attributes.
4289e86db79SHyon Kim 		    PortSpecificAttribute.SASPort->LocalSASAddress.wwn,
4299e86db79SHyon Kim 		    SASAddress.wwn, 8);
4309e86db79SHyon Kim 		(void) memcpy(disco_port_ptr->port_attributes.
4319e86db79SHyon Kim 		    PortSpecificAttribute.SASPort->AttachedSASAddress.wwn,
4329e86db79SHyon Kim 		    AttachedSASAddress.wwn, 8);
4339e86db79SHyon Kim 
4349e86db79SHyon Kim 		/* Default to unknown until we figure out otherwise */
4359e86db79SHyon Kim 		rval = di_prop_lookup_strings(DDI_DEV_T_ANY, node,
4369e86db79SHyon Kim 		    "variant", &propStringData);
4379e86db79SHyon Kim 		if (rval < 0) {
4389e86db79SHyon Kim 			/* check if it is SMP target */
4399e86db79SHyon Kim 			charptr = di_driver_name(node);
4409e86db79SHyon Kim 			if (charptr != NULL && (strncmp(charptr, "smp",
4419e86db79SHyon Kim 			    strlen(charptr)) == 0)) {
4429e86db79SHyon Kim 				disco_port_ptr->port_attributes.PortType =
4439e86db79SHyon Kim 				    HBA_PORTTYPE_SASEXPANDER;
4449e86db79SHyon Kim 				disco_port_ptr->port_attributes.
4459e86db79SHyon Kim 				    PortSpecificAttribute.
4469e86db79SHyon Kim 				    SASPort->PortProtocol =
4479e86db79SHyon Kim 				    HBA_SASPORTPROTOCOL_SMP;
4489e86db79SHyon Kim 				if (lookupSMPLink(devpath, (char *)link) ==
4499e86db79SHyon Kim 				    HBA_STATUS_OK) {
4509e86db79SHyon Kim 		/* indentation changed here. */
4519e86db79SHyon Kim 		(void) strlcpy(disco_port_ptr->port_attributes.
4529e86db79SHyon Kim 		    OSDeviceName, link,
4539e86db79SHyon Kim 		    sizeof (disco_port_ptr->port_attributes.OSDeviceName));
4549e86db79SHyon Kim 		/* indentation change ends here. */
4559e86db79SHyon Kim 				} else {
4569e86db79SHyon Kim 		/* indentation changed here. */
4579e86db79SHyon Kim 		get_minor(devpath, minorname);
4589e86db79SHyon Kim 		(void) snprintf(fullpath, sizeof (fullpath), "%s%s%s",
4599e86db79SHyon Kim 		    DEVICES_DIR, devpath, minorname);
4609e86db79SHyon Kim 		(void) strlcpy(disco_port_ptr->port_attributes.
4619e86db79SHyon Kim 		    OSDeviceName, fullpath,
4629e86db79SHyon Kim 		    sizeof (disco_port_ptr->port_attributes.OSDeviceName));
4639e86db79SHyon Kim 		/* indentation change ends here. */
4649e86db79SHyon Kim 				}
4659e86db79SHyon Kim 			} else {
4669e86db79SHyon Kim 				disco_port_ptr->port_attributes.PortType =
4679e86db79SHyon Kim 				    HBA_PORTTYPE_SASDEVICE;
4689e86db79SHyon Kim 				disco_port_ptr->port_attributes.\
4699e86db79SHyon Kim 				    PortSpecificAttribute.\
4709e86db79SHyon Kim 				    SASPort->PortProtocol =
4719e86db79SHyon Kim 				    HBA_SASPORTPROTOCOL_SSP;
4729e86db79SHyon Kim 			}
4739e86db79SHyon Kim 		} else {
4749e86db79SHyon Kim 			if ((strcmp(propStringData, "sata") == 0) ||
4759e86db79SHyon Kim 			    (strcmp(propStringData, "atapi") == 0)) {
4769e86db79SHyon Kim 				disco_port_ptr->port_attributes.PortType =
4779e86db79SHyon Kim 				    HBA_PORTTYPE_SATADEVICE;
4789e86db79SHyon Kim 				disco_port_ptr->port_attributes.\
4799e86db79SHyon Kim 				    PortSpecificAttribute.SASPort->PortProtocol
4809e86db79SHyon Kim 				    = HBA_SASPORTPROTOCOL_SATA;
4819e86db79SHyon Kim 			} else {
4829e86db79SHyon Kim 				log(LOG_DEBUG, ROUTINE,
4839e86db79SHyon Kim 				    "Unexpected variant prop value %s found on",
4849e86db79SHyon Kim 				    " device %s", propStringData, fullpath);
4859e86db79SHyon Kim 				/*
4869e86db79SHyon Kim 				 * Port type will be 0
4879e86db79SHyon Kim 				 * which is not valid type.
4889e86db79SHyon Kim 				 */
4899e86db79SHyon Kim 			}
4909e86db79SHyon Kim 		}
4919e86db79SHyon Kim 
4929e86db79SHyon Kim 		/* SMP device was handled already */
493*00f453f4SRob Johnston 		portattrs = &disco_port_ptr->port_attributes;
494*00f453f4SRob Johnston 		if (portattrs->OSDeviceName[0] == '\0') {
495*00f453f4SRob Johnston 			size = sizeof (portattrs->OSDeviceName);
496*00f453f4SRob Johnston 			(void) strlcpy(portattrs->OSDeviceName,
497*00f453f4SRob Johnston 			    fullpath, size);
4989e86db79SHyon Kim 		}
4999e86db79SHyon Kim 
5009e86db79SHyon Kim 		/* add new discovered port into the list */
5019e86db79SHyon Kim 
5029e86db79SHyon Kim 		if (port_ptr->first_attached_port == NULL) {
5039e86db79SHyon Kim 			port_ptr->first_attached_port = disco_port_ptr;
5049e86db79SHyon Kim 			disco_port_ptr->index = 0;
5059e86db79SHyon Kim 			port_ptr->port_attributes.PortSpecificAttribute.\
5069e86db79SHyon Kim 			    SASPort->NumberofDiscoveredPorts = 1;
5079e86db79SHyon Kim 		} else {
5089e86db79SHyon Kim 			disco_port_ptr->next = port_ptr->first_attached_port;
5099e86db79SHyon Kim 			port_ptr->first_attached_port = disco_port_ptr;
5109e86db79SHyon Kim 			disco_port_ptr->index = port_ptr->port_attributes.\
5119e86db79SHyon Kim 			    PortSpecificAttribute.\
5129e86db79SHyon Kim 			    SASPort->NumberofDiscoveredPorts;
5139e86db79SHyon Kim 			port_ptr->port_attributes.PortSpecificAttribute.\
5149e86db79SHyon Kim 			    SASPort->NumberofDiscoveredPorts++;
5159e86db79SHyon Kim 		}
5169e86db79SHyon Kim 		disco_port_ptr->port_attributes.PortState = port_state;
5179e86db79SHyon Kim 	}
5189e86db79SHyon Kim 
5199e86db79SHyon Kim 	if (disco_port_ptr->port_attributes.PortType ==
5209e86db79SHyon Kim 	    HBA_PORTTYPE_SASEXPANDER) {
5219e86db79SHyon Kim 	    /* No mapping data for expander device.  return ok here. */
5229e86db79SHyon Kim 		di_devfs_path_free(devpath);
5239e86db79SHyon Kim 		return (HBA_STATUS_OK);
5249e86db79SHyon Kim 	}
5259e86db79SHyon Kim 
5269e86db79SHyon Kim 	if ((mapping_ptr = (struct ScsiEntryList *)calloc
5279e86db79SHyon Kim 		    (1, sizeof (struct ScsiEntryList))) == NULL) {
5289e86db79SHyon Kim 		OUT_OF_MEMORY(ROUTINE);
5299e86db79SHyon Kim 		di_devfs_path_free(devpath);
5309e86db79SHyon Kim 		free_attached_port(port_ptr);
5319e86db79SHyon Kim 		return (HBA_STATUS_ERROR);
5329e86db79SHyon Kim 	}
5339e86db79SHyon Kim 
5349e86db79SHyon Kim 	if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "lun",
5359e86db79SHyon Kim 	    &propIntData) != -1) {
5369e86db79SHyon Kim 		mapping_ptr->entry.ScsiId.ScsiOSLun = *propIntData;
5379e86db79SHyon Kim 	} else {
5389e86db79SHyon Kim 		if ((charptr = strchr(unit_address, ',')) != NULL) {
5399e86db79SHyon Kim 			charptr++;
5409e86db79SHyon Kim 			mapping_ptr->entry.ScsiId.ScsiOSLun =
5419e86db79SHyon Kim 			    strtoull(charptr, NULL, 10);
5429e86db79SHyon Kim 		} else {
5439e86db79SHyon Kim 			log(LOG_DEBUG, ROUTINE,
5449e86db79SHyon Kim 			    "Failed to get LUN from the unit address of device "
5459e86db79SHyon Kim 			    " %s.", fullpath);
5469e86db79SHyon Kim 			di_devfs_path_free(devpath);
5479e86db79SHyon Kim 			free_attached_port(port_ptr);
5489e86db79SHyon Kim 			return (HBA_STATUS_ERROR);
5499e86db79SHyon Kim 		}
5509e86db79SHyon Kim 	}
5519e86db79SHyon Kim 
5529e86db79SHyon Kim 	/* get TargetLun(SAM-LUN). */
5539e86db79SHyon Kim 	if (di_prop_lookup_int64(DDI_DEV_T_ANY, node, "lun64",
5549e86db79SHyon Kim 	    &propInt64Data) != -1) {
5559e86db79SHyon Kim 		samLun = scsi_lun64_to_lun(*propInt64Data);
5569e86db79SHyon Kim 		(void) memcpy(&mapping_ptr->entry.PortLun.TargetLun,
5579e86db79SHyon Kim 		    &samLun, 8);
5589e86db79SHyon Kim 	} else {
5599e86db79SHyon Kim 		log(LOG_DEBUG, "get_attached_devices_info",
5609e86db79SHyon Kim 		    "No lun64 prop found on device %s.", fullpath);
5619e86db79SHyon Kim 		di_devfs_path_free(devpath);
5629e86db79SHyon Kim 		free_attached_port(port_ptr);
5639e86db79SHyon Kim 		return (HBA_STATUS_ERROR);
5649e86db79SHyon Kim 	}
5659e86db79SHyon Kim 
5669e86db79SHyon Kim 	if (di_prop_lookup_ints(DDI_DEV_T_ANY, node,
5679e86db79SHyon Kim 	    "target", &propIntData) != -1) {
5689e86db79SHyon Kim 		mapping_ptr->entry.ScsiId.ScsiTargetNumber = *propIntData;
5699e86db79SHyon Kim 	} else {
5709e86db79SHyon Kim 		mapping_ptr->entry.ScsiId.ScsiTargetNumber = di_instance(node);
5719e86db79SHyon Kim 	}
5729e86db79SHyon Kim 
5739e86db79SHyon Kim 	/* get ScsiBusNumber */
5749e86db79SHyon Kim 	mapping_ptr->entry.ScsiId.ScsiBusNumber = port_ptr->cntlNumber;
5759e86db79SHyon Kim 
5769e86db79SHyon Kim 	(void) memcpy(mapping_ptr->entry.PortLun.PortWWN.wwn,
5779e86db79SHyon Kim 	    SASAddress.wwn, 8);
5789e86db79SHyon Kim 
5799e86db79SHyon Kim 	/* Store the devices path for now.  We'll convert to /dev later */
5809e86db79SHyon Kim 	get_minor(devpath, minorname);
5819e86db79SHyon Kim 	(void) snprintf(mapping_ptr->entry.ScsiId.OSDeviceName,
5829e86db79SHyon Kim 	    sizeof (mapping_ptr->entry.ScsiId.OSDeviceName),
5839e86db79SHyon Kim 	    "%s%s%s", DEVICES_DIR, devpath, minorname);
5849e86db79SHyon Kim 
585f94d63efSHyon Kim 	/* reset errno to 0 */
586f94d63efSHyon Kim 	errno = 0;
587f94d63efSHyon Kim 	if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "devid",
588f94d63efSHyon Kim 	    &propStringData) != -1) {
589f94d63efSHyon Kim 		if (devid_str_decode(propStringData, &devid, NULL) != -1) {
590f94d63efSHyon Kim 			guidStr = devid_to_guid(devid);
591f94d63efSHyon Kim 			if (guidStr != NULL) {
592f94d63efSHyon Kim 				(void) strlcpy(mapping_ptr->entry.LUID.buffer,
593b0459908SJosef 'Jeff' Sipek 				    guidStr,
594b0459908SJosef 'Jeff' Sipek 				    sizeof (mapping_ptr->entry.LUID.buffer));
595f94d63efSHyon Kim 				devid_free_guid(guidStr);
5969e86db79SHyon Kim 			} else {
597f94d63efSHyon Kim 				/*
598f94d63efSHyon Kim 				 * Note:
599f94d63efSHyon Kim 				 * if logical unit associated page 83 id
600f94d63efSHyon Kim 				 * descriptor is not avaialble for the device
601b0459908SJosef 'Jeff' Sipek 				 * devid_to_guid returns NULL with errno 0.
602f94d63efSHyon Kim 				 */
603f94d63efSHyon Kim 				log(LOG_DEBUG, ROUTINE,
604f94d63efSHyon Kim 				    "failed to get devid guid on (%s) : %s",
605f94d63efSHyon Kim 				    devpath, strerror(errno));
6069e86db79SHyon Kim 			}
607b0459908SJosef 'Jeff' Sipek 
608b0459908SJosef 'Jeff' Sipek 			devid_free(devid);
609f94d63efSHyon Kim 		} else {
610f94d63efSHyon Kim 			/*
611f94d63efSHyon Kim 			 * device may not support proper page 83 id descriptor.
612f94d63efSHyon Kim 			 * leave LUID attribute to NULL and continue.
613f94d63efSHyon Kim 			 */
614f94d63efSHyon Kim 			log(LOG_DEBUG, ROUTINE,
615f94d63efSHyon Kim 			    "failed to decode devid prop on (%s) : %s",
616f94d63efSHyon Kim 			    devpath, strerror(errno));
617f94d63efSHyon Kim 		}
618f94d63efSHyon Kim 	} else {
619f94d63efSHyon Kim 		/* leave LUID attribute to NULL and continue. */
620f94d63efSHyon Kim 		log(LOG_DEBUG, ROUTINE,
621f94d63efSHyon Kim 		    "failed to get devid prop on (%s) : %s",
622f94d63efSHyon Kim 		    devpath, strerror(errno));
6239e86db79SHyon Kim 	}
6249e86db79SHyon Kim 
6259e86db79SHyon Kim 	if (disco_port_ptr->scsiInfo == NULL) {
6269e86db79SHyon Kim 		disco_port_ptr->scsiInfo = mapping_ptr;
6279e86db79SHyon Kim 	} else {
6289e86db79SHyon Kim 		mapping_ptr->next = disco_port_ptr->scsiInfo;
6299e86db79SHyon Kim 		disco_port_ptr->scsiInfo = mapping_ptr;
6309e86db79SHyon Kim 	}
6319e86db79SHyon Kim 
6329e86db79SHyon Kim 	di_devfs_path_free(devpath);
6339e86db79SHyon Kim 
6349e86db79SHyon Kim 	return (HBA_STATUS_OK);
6359e86db79SHyon Kim }
6369e86db79SHyon Kim 
6379e86db79SHyon Kim /*
6389e86db79SHyon Kim  * Finds attached device(target) from pathinfo node.
6399e86db79SHyon Kim  */
6409e86db79SHyon Kim static HBA_STATUS
get_attached_paths_info(di_path_t path,struct sun_sas_port * port_ptr)6419e86db79SHyon Kim get_attached_paths_info(di_path_t path, struct sun_sas_port *port_ptr)
6429e86db79SHyon Kim {
6439e86db79SHyon Kim 	char			    ROUTINE[] = "get_attached_paths_info";
6449e86db79SHyon Kim 	char			    *propStringData = NULL;
6459e86db79SHyon Kim 	int			    *propIntData = NULL;
6469e86db79SHyon Kim 	int64_t			    *propInt64Data = NULL;
6479e86db79SHyon Kim 	scsi_lun_t		    samLun;
648f94d63efSHyon Kim 	ddi_devid_t		    devid;
649f94d63efSHyon Kim 	char			    *guidStr;
6509e86db79SHyon Kim 	char			    *unit_address;
6519e86db79SHyon Kim 	char			    *charptr;
6529e86db79SHyon Kim 	char			    *clientdevpath = NULL;
6539e86db79SHyon Kim 	char			    *pathdevpath = NULL;
6549e86db79SHyon Kim 	char			    fullpath[MAXPATHLEN+1];
6559e86db79SHyon Kim 	char			    minorname[MAXNAMELEN+1];
656*00f453f4SRob Johnston 	SMHBA_PORTATTRIBUTES	    *portattrs;
6579e86db79SHyon Kim 	struct ScsiEntryList	    *mapping_ptr;
6589e86db79SHyon Kim 	HBA_WWN			    SASAddress, AttachedSASAddress;
6599e86db79SHyon Kim 	struct sun_sas_port	    *disco_port_ptr;
6609e86db79SHyon Kim 	di_path_state_t		    state = 0;
6619e86db79SHyon Kim 	di_node_t		    clientnode;
6629e86db79SHyon Kim 	int			    portfound, size;
6639e86db79SHyon Kim 	int			    port_state = HBA_PORTSTATE_ONLINE;
6649e86db79SHyon Kim 	uint64_t		    tmpAddr;
6659e86db79SHyon Kim 
6669e86db79SHyon Kim 	if (port_ptr == NULL) {
6679e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE, "NULL port_ptr argument");
6689e86db79SHyon Kim 		return (HBA_STATUS_ERROR);
6699e86db79SHyon Kim 	}
6709e86db79SHyon Kim 
6719e86db79SHyon Kim 	/* if not null, free before return. */
6729e86db79SHyon Kim 	pathdevpath = di_path_devfs_path(path);
6739e86db79SHyon Kim 
6749e86db79SHyon Kim 	state = di_path_state(path);
6759e86db79SHyon Kim 	/* when node is not attached and online, set the state to offline. */
6769e86db79SHyon Kim 	if ((state == DI_PATH_STATE_OFFLINE) ||
6779e86db79SHyon Kim 	    (state == DI_PATH_STATE_FAULT)) {
6789e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
6799e86db79SHyon Kim 		    "path node (%s) is either OFFLINE or FAULT state",
6809e86db79SHyon Kim 		    pathdevpath ?  pathdevpath : "(missing device path)");
6819e86db79SHyon Kim 		port_state = HBA_PORTSTATE_OFFLINE;
6829e86db79SHyon Kim 	}
6839e86db79SHyon Kim 
684*00f453f4SRob Johnston 	if ((clientnode = di_path_client_node(path)) != DI_NODE_NIL) {
6859e86db79SHyon Kim 		if (di_retired(clientnode)) {
6869e86db79SHyon Kim 			log(LOG_DEBUG, ROUTINE,
6879e86db79SHyon Kim 			    "client node of path (%s) is retired. Skipping.",
6889e86db79SHyon Kim 			    pathdevpath ?  pathdevpath :
6899e86db79SHyon Kim 			    "(missing device path)");
6909e86db79SHyon Kim 			if (pathdevpath) di_devfs_path_free(pathdevpath);
6919e86db79SHyon Kim 			return (HBA_STATUS_OK);
6929e86db79SHyon Kim 		}
6939e86db79SHyon Kim 		if ((clientdevpath = di_devfs_path(clientnode)) == NULL) {
6949e86db79SHyon Kim 			log(LOG_DEBUG, ROUTINE,
6959e86db79SHyon Kim 			    "Client device of path (%s) has no path. Skipping.",
6969e86db79SHyon Kim 			    pathdevpath ?  pathdevpath :
6979e86db79SHyon Kim 			    "(missing device path)");
6989e86db79SHyon Kim 			if (pathdevpath) di_devfs_path_free(pathdevpath);
6999e86db79SHyon Kim 			return (HBA_STATUS_ERROR);
7009e86db79SHyon Kim 		}
7019e86db79SHyon Kim 	} else {
7029e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
7039e86db79SHyon Kim 		    "Failed to get client device from a path (%s).",
7049e86db79SHyon Kim 		    pathdevpath ?  pathdevpath :
7059e86db79SHyon Kim 		    "(missing device path)");
7069e86db79SHyon Kim 		if (pathdevpath) di_devfs_path_free(pathdevpath);
7079e86db79SHyon Kim 		return (HBA_STATUS_ERROR);
7089e86db79SHyon Kim 	}
7099e86db79SHyon Kim 
7109e86db79SHyon Kim 	/* add the "/devices" in the begining and the :devctl at the end */
7119e86db79SHyon Kim 	(void) snprintf(fullpath, sizeof (fullpath), "%s%s", DEVICES_DIR,
7129e86db79SHyon Kim 	    clientdevpath);
7139e86db79SHyon Kim 
7149e86db79SHyon Kim 	(void) memset(&SASAddress, 0, sizeof (SASAddress));
7159e86db79SHyon Kim 	if ((unit_address = di_path_bus_addr(path)) != NULL) {
7169e86db79SHyon Kim 		if ((charptr = strchr(unit_address, ',')) != NULL) {
7179e86db79SHyon Kim 			*charptr = '\0';
7189e86db79SHyon Kim 		}
7199e86db79SHyon Kim 		for (charptr = unit_address; *charptr != '\0'; charptr++) {
7209e86db79SHyon Kim 			if (isxdigit(*charptr)) {
7219e86db79SHyon Kim 				break;
7229e86db79SHyon Kim 			}
7239e86db79SHyon Kim 		}
72469b2e41eSToomas Soome 		if (*charptr != '\0') {
7259e86db79SHyon Kim 			tmpAddr = htonll(strtoll(charptr, NULL, 16));
7269e86db79SHyon Kim 			(void) memcpy(&SASAddress.wwn[0], &tmpAddr, 8);
7279e86db79SHyon Kim 		} else {
7289e86db79SHyon Kim 			log(LOG_DEBUG, ROUTINE,
7299e86db79SHyon Kim 			    "No proper target port info on unit address of "
7309e86db79SHyon Kim 			    "path (%s).", pathdevpath ?  pathdevpath :
7319e86db79SHyon Kim 			    "(missing device path)");
7329e86db79SHyon Kim 			if (pathdevpath) di_devfs_path_free(pathdevpath);
7339e86db79SHyon Kim 			di_devfs_path_free(clientdevpath);
7349e86db79SHyon Kim 			return (HBA_STATUS_ERROR);
7359e86db79SHyon Kim 		}
7369e86db79SHyon Kim 	} else {
7379e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE, "Fail to get unit address of path(%s).",
7389e86db79SHyon Kim 		    "path (%s).", pathdevpath ?  pathdevpath :
7399e86db79SHyon Kim 		    "(missing device path)");
7409e86db79SHyon Kim 		if (pathdevpath) di_devfs_path_free(pathdevpath);
7419e86db79SHyon Kim 		di_devfs_path_free(clientdevpath);
7429e86db79SHyon Kim 		return (HBA_STATUS_ERROR);
7439e86db79SHyon Kim 	}
7449e86db79SHyon Kim 
7459e86db79SHyon Kim 	(void) memset(&AttachedSASAddress, 0, sizeof (AttachedSASAddress));
7469e86db79SHyon Kim 	if (di_path_prop_lookup_strings(path, "attached-port",
7479e86db79SHyon Kim 	    &propStringData) != -1) {
7489e86db79SHyon Kim 		for (charptr = propStringData; *charptr != '\0'; charptr++) {
7499e86db79SHyon Kim 			if (isxdigit(*charptr)) {
7509e86db79SHyon Kim 				break;
7519e86db79SHyon Kim 			}
7529e86db79SHyon Kim 		}
7539e86db79SHyon Kim 		if (*charptr != '\0') {
7549e86db79SHyon Kim 			tmpAddr = htonll(strtoll(charptr, NULL, 16));
7559e86db79SHyon Kim 			(void) memcpy(AttachedSASAddress.wwn, &tmpAddr, 8);
7569e86db79SHyon Kim 			/*  check the attached address of hba port. */
7579e86db79SHyon Kim 			if (memcmp(port_ptr->port_attributes.
7589e86db79SHyon Kim 			    PortSpecificAttribute.SASPort->
7599e86db79SHyon Kim 			    LocalSASAddress.wwn, &tmpAddr, 8) == 0) {
7609e86db79SHyon Kim 				if (wwnConversion(port_ptr->port_attributes.
7619e86db79SHyon Kim 				    PortSpecificAttribute.SASPort->
7629e86db79SHyon Kim 				    AttachedSASAddress.wwn)) {
7639e86db79SHyon Kim 					/* verify the attaached SAS Addr. */
7649e86db79SHyon Kim 					if (memcmp(port_ptr->port_attributes.
7659e86db79SHyon Kim 					    PortSpecificAttribute.SASPort->
7669e86db79SHyon Kim 					    AttachedSASAddress.wwn,
7679e86db79SHyon Kim 					    SASAddress.wwn, 8) != 0) {
7689e86db79SHyon Kim 				/* indentation move begin. */
7699e86db79SHyon Kim 				log(LOG_DEBUG, ROUTINE,
7709e86db79SHyon Kim 				    "iport attached-port(%016llx) do not"
7719e86db79SHyon Kim 				    " match with level 1 Local"
7729e86db79SHyon Kim 				    " SAS address(%016llx).",
7739e86db79SHyon Kim 				    wwnConversion(port_ptr->port_attributes.
7749e86db79SHyon Kim 				    PortSpecificAttribute.
7759e86db79SHyon Kim 				    SASPort->AttachedSASAddress.wwn),
7769e86db79SHyon Kim 				    wwnConversion(SASAddress.wwn));
7779e86db79SHyon Kim 				if (pathdevpath)
7789e86db79SHyon Kim 					di_devfs_path_free(pathdevpath);
7799e86db79SHyon Kim 				di_devfs_path_free(clientdevpath);
7809e86db79SHyon Kim 				free_attached_port(port_ptr);
7819e86db79SHyon Kim 				return (HBA_STATUS_ERROR);
7829e86db79SHyon Kim 				/* indentation move ends. */
7839e86db79SHyon Kim 					}
7849e86db79SHyon Kim 				} else {
7859e86db79SHyon Kim 					/* store the Attaached SAS Addr. */
7869e86db79SHyon Kim 					(void) memcpy(port_ptr->port_attributes.
7879e86db79SHyon Kim 					    PortSpecificAttribute.
7889e86db79SHyon Kim 					    SASPort->AttachedSASAddress.wwn,
7899e86db79SHyon Kim 					    &SASAddress.wwn[0], 8);
7909e86db79SHyon Kim 				}
7919e86db79SHyon Kim 			}
7929e86db79SHyon Kim 		} else {
7939e86db79SHyon Kim 			log(LOG_DEBUG, ROUTINE,
7949e86db79SHyon Kim 			    "No proper attached SAS address value of path (%s)",
7959e86db79SHyon Kim 			    pathdevpath ?  pathdevpath :
7969e86db79SHyon Kim 			    "(missing device path)");
7979e86db79SHyon Kim 			if (pathdevpath) di_devfs_path_free(pathdevpath);
7989e86db79SHyon Kim 			di_devfs_path_free(clientdevpath);
7999e86db79SHyon Kim 			free_attached_port(port_ptr);
8009e86db79SHyon Kim 			return (HBA_STATUS_ERROR);
8019e86db79SHyon Kim 		}
8029e86db79SHyon Kim 	} else {
8039e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
8049e86db79SHyon Kim 		    "Property attached-port not found for path (%s)",
8059e86db79SHyon Kim 		    pathdevpath ?  pathdevpath :
8069e86db79SHyon Kim 		    "(missing device path)");
8079e86db79SHyon Kim 		if (pathdevpath) di_devfs_path_free(pathdevpath);
8089e86db79SHyon Kim 		di_devfs_path_free(clientdevpath);
8099e86db79SHyon Kim 		free_attached_port(port_ptr);
8109e86db79SHyon Kim 		return (HBA_STATUS_ERROR);
8119e86db79SHyon Kim 	}
8129e86db79SHyon Kim 
8139e86db79SHyon Kim 	/*
8149e86db79SHyon Kim 	 * walk the disco list to make sure that there isn't a matching
8159e86db79SHyon Kim 	 * port and node wwn or a matching device path
8169e86db79SHyon Kim 	 */
8179e86db79SHyon Kim 	portfound = 0;
8189e86db79SHyon Kim 	for (disco_port_ptr = port_ptr->first_attached_port;
8199e86db79SHyon Kim 	    disco_port_ptr != NULL;
8209e86db79SHyon Kim 	    disco_port_ptr = disco_port_ptr->next) {
8219e86db79SHyon Kim 		if ((disco_port_ptr->port_attributes.PortState !=
8229e86db79SHyon Kim 		    HBA_PORTSTATE_ERROR) &&
8239e86db79SHyon Kim 		    (memcmp(disco_port_ptr->port_attributes.
8249e86db79SHyon Kim 		    PortSpecificAttribute.SASPort->LocalSASAddress.wwn,
8259e86db79SHyon Kim 		    SASAddress.wwn, 8) == 0)) {
8269e86db79SHyon Kim 			/*
8279e86db79SHyon Kim 			 * found matching disco_port
8289e86db79SHyon Kim 			 * look for matching device path
8299e86db79SHyon Kim 			 */
8309e86db79SHyon Kim 			portfound = 1;
8319e86db79SHyon Kim 			for (mapping_ptr = disco_port_ptr->scsiInfo;
8329e86db79SHyon Kim 			    mapping_ptr != NULL;
8339e86db79SHyon Kim 			    mapping_ptr = mapping_ptr->next) {
8349e86db79SHyon Kim 				if (strstr(mapping_ptr-> entry.ScsiId.
8359e86db79SHyon Kim 				    OSDeviceName, clientdevpath) != 0) {
8369e86db79SHyon Kim 					log(LOG_DEBUG, ROUTINE,
8379e86db79SHyon Kim 					    "Found an already discovered "
8389e86db79SHyon Kim 					    "device %s.", clientdevpath);
8399e86db79SHyon Kim 					if (pathdevpath)
8409e86db79SHyon Kim 						di_devfs_path_free(pathdevpath);
8419e86db79SHyon Kim 					di_devfs_path_free(clientdevpath);
8429e86db79SHyon Kim 					return (HBA_STATUS_OK);
8439e86db79SHyon Kim 				}
8449e86db79SHyon Kim 			}
8459e86db79SHyon Kim 			if (portfound == 1) {
8469e86db79SHyon Kim 				break;
8479e86db79SHyon Kim 			}
8489e86db79SHyon Kim 		}
8499e86db79SHyon Kim 	}
8509e86db79SHyon Kim 
8519e86db79SHyon Kim 	if (portfound == 0) {
8529e86db79SHyon Kim 		/*
8539e86db79SHyon Kim 		 * there are no matching SAS address.
8549e86db79SHyon Kim 		 * this must be a new device
8559e86db79SHyon Kim 		 */
8569e86db79SHyon Kim 		if ((disco_port_ptr = (struct sun_sas_port *)calloc(1,
8579e86db79SHyon Kim 				    sizeof (struct sun_sas_port))) == NULL)  {
8589e86db79SHyon Kim 			OUT_OF_MEMORY(ROUTINE);
8599e86db79SHyon Kim 			if (pathdevpath) di_devfs_path_free(pathdevpath);
8609e86db79SHyon Kim 			di_devfs_path_free(clientdevpath);
8619e86db79SHyon Kim 			free_attached_port(port_ptr);
8629e86db79SHyon Kim 			return (HBA_STATUS_ERROR);
8639e86db79SHyon Kim 		}
8649e86db79SHyon Kim 
8659e86db79SHyon Kim 		if ((disco_port_ptr->port_attributes.PortSpecificAttribute.\
8669e86db79SHyon Kim 		    SASPort = (struct SMHBA_SAS_Port *)calloc(1,
8679e86db79SHyon Kim 		    sizeof (struct SMHBA_SAS_Port))) == NULL) {
8689e86db79SHyon Kim 			OUT_OF_MEMORY("add_hba_port_info");
8699e86db79SHyon Kim 			if (pathdevpath) di_devfs_path_free(pathdevpath);
8709e86db79SHyon Kim 			di_devfs_path_free(clientdevpath);
8719e86db79SHyon Kim 			free_attached_port(port_ptr);
8729e86db79SHyon Kim 			return (HBA_STATUS_ERROR);
8739e86db79SHyon Kim 		}
8749e86db79SHyon Kim 
8759e86db79SHyon Kim 		(void) memcpy(disco_port_ptr->port_attributes.
8769e86db79SHyon Kim 		    PortSpecificAttribute.
8779e86db79SHyon Kim 		    SASPort->LocalSASAddress.wwn, SASAddress.wwn, 8);
8789e86db79SHyon Kim 		(void) memcpy(disco_port_ptr->port_attributes.
8799e86db79SHyon Kim 		    PortSpecificAttribute.
8809e86db79SHyon Kim 		    SASPort->AttachedSASAddress.wwn, AttachedSASAddress.wwn, 8);
8819e86db79SHyon Kim 
8829e86db79SHyon Kim 		/* Default to unknown until we figure out otherwise */
8839e86db79SHyon Kim 		if (di_path_prop_lookup_strings(path, "variant",
8849e86db79SHyon Kim 		    &propStringData) != -1) {
8859e86db79SHyon Kim 			if ((strcmp(propStringData, "sata") == 0) ||
8869e86db79SHyon Kim 			    (strcmp(propStringData, "atapi") == 0)) {
8879e86db79SHyon Kim 				disco_port_ptr->port_attributes.PortType =
8889e86db79SHyon Kim 				    HBA_PORTTYPE_SATADEVICE;
8899e86db79SHyon Kim 				disco_port_ptr->port_attributes.\
8909e86db79SHyon Kim 				    PortSpecificAttribute.SASPort->PortProtocol
8919e86db79SHyon Kim 				    = HBA_SASPORTPROTOCOL_SATA;
8929e86db79SHyon Kim 			} else {
8939e86db79SHyon Kim 				log(LOG_DEBUG, ROUTINE,
8949e86db79SHyon Kim 				    "Unexpected variant prop value %s found on",
8959e86db79SHyon Kim 				    " path (%s)", propStringData,
8969e86db79SHyon Kim 				    pathdevpath ?  pathdevpath :
8979e86db79SHyon Kim 				    "(missing device path)");
8989e86db79SHyon Kim 				/*
8999e86db79SHyon Kim 				 * Port type will be 0
9009e86db79SHyon Kim 				 * which is not valid type.
9019e86db79SHyon Kim 				 */
9029e86db79SHyon Kim 			}
9039e86db79SHyon Kim 		} else {
9049e86db79SHyon Kim 			disco_port_ptr->port_attributes.PortType =
9059e86db79SHyon Kim 			    HBA_PORTTYPE_SASDEVICE;
9069e86db79SHyon Kim 			disco_port_ptr->port_attributes.PortSpecificAttribute.\
9079e86db79SHyon Kim 			    SASPort->PortProtocol = HBA_SASPORTPROTOCOL_SSP;
9089e86db79SHyon Kim 		}
9099e86db79SHyon Kim 
910*00f453f4SRob Johnston 		portattrs = &disco_port_ptr->port_attributes;
911*00f453f4SRob Johnston 		if (portattrs->OSDeviceName[0] == '\0') {
912*00f453f4SRob Johnston 			size = sizeof (portattrs->OSDeviceName);
9139e86db79SHyon Kim 			if (pathdevpath != NULL) {
914*00f453f4SRob Johnston 				(void) strlcpy(portattrs->OSDeviceName,
915*00f453f4SRob Johnston 				    pathdevpath, size);
9169e86db79SHyon Kim 			}
9179e86db79SHyon Kim 		}
9189e86db79SHyon Kim 
9199e86db79SHyon Kim 		/* add new discovered port into the list */
9209e86db79SHyon Kim 		if (port_ptr->first_attached_port == NULL) {
9219e86db79SHyon Kim 			port_ptr->first_attached_port = disco_port_ptr;
9229e86db79SHyon Kim 			disco_port_ptr->index = 0;
9239e86db79SHyon Kim 			port_ptr->port_attributes.PortSpecificAttribute.\
9249e86db79SHyon Kim 			    SASPort->NumberofDiscoveredPorts = 1;
9259e86db79SHyon Kim 		} else {
9269e86db79SHyon Kim 			disco_port_ptr->next = port_ptr->first_attached_port;
9279e86db79SHyon Kim 			port_ptr->first_attached_port = disco_port_ptr;
9289e86db79SHyon Kim 			disco_port_ptr->index = port_ptr->port_attributes.\
9299e86db79SHyon Kim 			    PortSpecificAttribute.\
9309e86db79SHyon Kim 			    SASPort->NumberofDiscoveredPorts;
9319e86db79SHyon Kim 			port_ptr->port_attributes.PortSpecificAttribute.\
9329e86db79SHyon Kim 			    SASPort->NumberofDiscoveredPorts++;
9339e86db79SHyon Kim 		}
9349e86db79SHyon Kim 		disco_port_ptr->port_attributes.PortState = port_state;
9359e86db79SHyon Kim 	}
9369e86db79SHyon Kim 
9379e86db79SHyon Kim 	if ((mapping_ptr = (struct ScsiEntryList *)calloc
9389e86db79SHyon Kim 		    (1, sizeof (struct ScsiEntryList))) == NULL) {
9399e86db79SHyon Kim 		OUT_OF_MEMORY(ROUTINE);
9409e86db79SHyon Kim 		if (pathdevpath) di_devfs_path_free(pathdevpath);
9419e86db79SHyon Kim 		di_devfs_path_free(clientdevpath);
9429e86db79SHyon Kim 		free_attached_port(port_ptr);
9439e86db79SHyon Kim 		return (HBA_STATUS_ERROR);
9449e86db79SHyon Kim 	}
9459e86db79SHyon Kim 
9469e86db79SHyon Kim 	if (di_path_prop_lookup_ints(path, "lun", &propIntData) != -1) {
9479e86db79SHyon Kim 		mapping_ptr->entry.ScsiId.ScsiOSLun = *propIntData;
9489e86db79SHyon Kim 	} else {
9499e86db79SHyon Kim 		if ((charptr = strchr(unit_address, ',')) != NULL) {
9509e86db79SHyon Kim 			charptr++;
9519e86db79SHyon Kim 			mapping_ptr->entry.ScsiId.ScsiOSLun =
9529e86db79SHyon Kim 			    strtoull(charptr, NULL, 10);
9539e86db79SHyon Kim 		} else {
9549e86db79SHyon Kim 			log(LOG_DEBUG, ROUTINE,
9559e86db79SHyon Kim 			    "Failed to get LUN from unit address of path(%s).",
9569e86db79SHyon Kim 			    pathdevpath ?  pathdevpath :
9579e86db79SHyon Kim 			    "(missing device path)");
9589e86db79SHyon Kim 			if (pathdevpath) di_devfs_path_free(pathdevpath);
9599e86db79SHyon Kim 			di_devfs_path_free(clientdevpath);
9609e86db79SHyon Kim 			free_attached_port(port_ptr);
9619e86db79SHyon Kim 			return (HBA_STATUS_ERROR);
9629e86db79SHyon Kim 		}
9639e86db79SHyon Kim 	}
9649e86db79SHyon Kim 
9659e86db79SHyon Kim 	/* Get TargetLun(SAM LUN). */
9669e86db79SHyon Kim 	if (di_path_prop_lookup_int64s(path, "lun64", &propInt64Data) != -1) {
9679e86db79SHyon Kim 		samLun = scsi_lun64_to_lun(*propInt64Data);
9689e86db79SHyon Kim 		(void) memcpy(&mapping_ptr->entry.PortLun.TargetLun,
9699e86db79SHyon Kim 		    &samLun, 8);
9709e86db79SHyon Kim 	} else {
9719e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE, "No lun64 prop found on path (%s)",
9729e86db79SHyon Kim 		    pathdevpath ?  pathdevpath :
9739e86db79SHyon Kim 		    "(missing device path)");
9749e86db79SHyon Kim 		if (pathdevpath) di_devfs_path_free(pathdevpath);
9759e86db79SHyon Kim 		di_devfs_path_free(clientdevpath);
9769e86db79SHyon Kim 		free_attached_port(port_ptr);
9779e86db79SHyon Kim 		return (HBA_STATUS_ERROR);
9789e86db79SHyon Kim 	}
9799e86db79SHyon Kim 
9809e86db79SHyon Kim 	if (di_path_prop_lookup_ints(path, "target", &propIntData) != -1) {
9819e86db79SHyon Kim 		mapping_ptr->entry.ScsiId.ScsiTargetNumber = *propIntData;
9829e86db79SHyon Kim 	} else {
9839e86db79SHyon Kim 		mapping_ptr->entry.ScsiId.ScsiTargetNumber =
9849e86db79SHyon Kim 		    di_path_instance(path);
9859e86db79SHyon Kim 	}
9869e86db79SHyon Kim 
9879e86db79SHyon Kim 	/* get ScsiBusNumber */
9889e86db79SHyon Kim 	mapping_ptr->entry.ScsiId.ScsiBusNumber = port_ptr->cntlNumber;
9899e86db79SHyon Kim 
9909e86db79SHyon Kim 	(void) memcpy(mapping_ptr->entry.PortLun.PortWWN.wwn,
9919e86db79SHyon Kim 	    SASAddress.wwn, 8);
9929e86db79SHyon Kim 
9939e86db79SHyon Kim 	/* Store the devices path for now.  We'll convert to /dev later */
9949e86db79SHyon Kim 	get_minor(clientdevpath, minorname);
9959e86db79SHyon Kim 	(void) snprintf(mapping_ptr->entry.ScsiId.OSDeviceName,
9969e86db79SHyon Kim 	    sizeof (mapping_ptr->entry.ScsiId.OSDeviceName),
9979e86db79SHyon Kim 	    "%s%s%s", DEVICES_DIR, clientdevpath, minorname);
9989e86db79SHyon Kim 
9999e86db79SHyon Kim 	/* get luid. */
1000f94d63efSHyon Kim 	errno = 0; /* reset errno to 0 */
1001f94d63efSHyon Kim 	if (di_prop_lookup_strings(DDI_DEV_T_ANY, clientnode, "devid",
1002f94d63efSHyon Kim 	    &propStringData) != -1) {
1003f94d63efSHyon Kim 		if (devid_str_decode(propStringData, &devid, NULL) != -1) {
1004f94d63efSHyon Kim 			guidStr = devid_to_guid(devid);
1005f94d63efSHyon Kim 			if (guidStr != NULL) {
1006f94d63efSHyon Kim 				(void) strlcpy(mapping_ptr->entry.LUID.buffer,
1007f94d63efSHyon Kim 				    guidStr,
10089e86db79SHyon Kim 				    sizeof (mapping_ptr->entry.LUID.buffer));
1009f94d63efSHyon Kim 				devid_free_guid(guidStr);
10109e86db79SHyon Kim 			} else {
1011f94d63efSHyon Kim 				/*
1012f94d63efSHyon Kim 				 * Note:
1013f94d63efSHyon Kim 				 * if logical unit associated page 83 id
1014f94d63efSHyon Kim 				 * descriptor is not avaialble for the device
1015b0459908SJosef 'Jeff' Sipek 				 * devid_to_guid returns NULL with errno 0.
1016f94d63efSHyon Kim 				 */
1017f94d63efSHyon Kim 				log(LOG_DEBUG, ROUTINE,
1018f94d63efSHyon Kim 				    "failed to get devid guid on (%s)",
1019f94d63efSHyon Kim 				    " associated with path(%s) : %s",
1020f94d63efSHyon Kim 				    clientdevpath,
10219e86db79SHyon Kim 				    pathdevpath ?  pathdevpath :
1022f94d63efSHyon Kim 				    "(missing device path)",
1023f94d63efSHyon Kim 				    strerror(errno));
1024f94d63efSHyon Kim 			}
1025b0459908SJosef 'Jeff' Sipek 
1026b0459908SJosef 'Jeff' Sipek 			devid_free(devid);
1027f94d63efSHyon Kim 		} else {
1028f94d63efSHyon Kim 			/*
1029f94d63efSHyon Kim 			 * device may not support proper page 83 id descriptor.
1030f94d63efSHyon Kim 			 * leave LUID attribute to NULL and continue.
1031f94d63efSHyon Kim 			 */
1032f94d63efSHyon Kim 			log(LOG_DEBUG, ROUTINE,
1033f94d63efSHyon Kim 			    "failed to decode devid prop on (%s)",
1034f94d63efSHyon Kim 			    " associated with path(%s) : %s",
1035f94d63efSHyon Kim 			    clientdevpath,
1036f94d63efSHyon Kim 			    pathdevpath ?  pathdevpath :
1037f94d63efSHyon Kim 			    "(missing device path)",
1038f94d63efSHyon Kim 			    strerror(errno));
1039f94d63efSHyon Kim 		}
1040f94d63efSHyon Kim 	} else {
1041f94d63efSHyon Kim 		/* leave LUID attribute to NULL and continue. */
1042f94d63efSHyon Kim 		log(LOG_DEBUG, ROUTINE, "Failed to get devid on %s"
1043f94d63efSHyon Kim 		    " associated with path(%s) : %s", clientdevpath,
1044f94d63efSHyon Kim 		    pathdevpath ?  pathdevpath : "(missing device path)",
1045f94d63efSHyon Kim 		    strerror(errno));
10469e86db79SHyon Kim 	}
10479e86db79SHyon Kim 
10489e86db79SHyon Kim 	if (disco_port_ptr->scsiInfo == NULL) {
10499e86db79SHyon Kim 		disco_port_ptr->scsiInfo = mapping_ptr;
10509e86db79SHyon Kim 	} else {
10519e86db79SHyon Kim 		mapping_ptr->next = disco_port_ptr->scsiInfo;
10529e86db79SHyon Kim 		disco_port_ptr->scsiInfo = mapping_ptr;
10539e86db79SHyon Kim 	}
10549e86db79SHyon Kim 
10559e86db79SHyon Kim 	if (pathdevpath) di_devfs_path_free(pathdevpath);
10569e86db79SHyon Kim 	di_devfs_path_free(clientdevpath);
10579e86db79SHyon Kim 
10589e86db79SHyon Kim 	return (HBA_STATUS_OK);
10599e86db79SHyon Kim }
10609e86db79SHyon Kim 
10619e86db79SHyon Kim /*
10629e86db79SHyon Kim  * walks the devinfo tree retrieving all hba information
10639e86db79SHyon Kim  */
10649e86db79SHyon Kim extern HBA_STATUS
devtree_attached_devices(di_node_t node,struct sun_sas_port * port_ptr)10659e86db79SHyon Kim devtree_attached_devices(di_node_t node, struct sun_sas_port *port_ptr)
10669e86db79SHyon Kim {
10679e86db79SHyon Kim 	const char		ROUTINE[] = "devtree_attached_devices";
10689e86db79SHyon Kim 	di_node_t		nodechild = DI_NODE_NIL;
10699e86db79SHyon Kim 	di_path_t		path = DI_PATH_NIL;
10709e86db79SHyon Kim 
10719e86db79SHyon Kim 	/* child should be device */
10729e86db79SHyon Kim 	if ((nodechild = di_child_node(node)) == DI_NODE_NIL) {
10739e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
10749e86db79SHyon Kim 		    "No devinfo child on the HBA port node.");
10759e86db79SHyon Kim 	}
10769e86db79SHyon Kim 
10779e86db79SHyon Kim 	if ((path = di_path_phci_next_path(node, path)) ==
10789e86db79SHyon Kim 	    DI_PATH_NIL) {
10799e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
10809e86db79SHyon Kim 		    "No pathinfo node on the HBA port node.");
10819e86db79SHyon Kim 	}
10829e86db79SHyon Kim 
10839e86db79SHyon Kim 	if ((nodechild == DI_NODE_NIL) && (path == DI_PATH_NIL)) {
10849e86db79SHyon Kim 		return (HBA_STATUS_OK);
10859e86db79SHyon Kim 	}
10869e86db79SHyon Kim 
10879e86db79SHyon Kim 	while (nodechild != DI_NODE_NIL) {
10889e86db79SHyon Kim 		if (get_attached_devices_info(nodechild, port_ptr)
10899e86db79SHyon Kim 		    != HBA_STATUS_OK) {
10909e86db79SHyon Kim 			break;
10919e86db79SHyon Kim 		}
10929e86db79SHyon Kim 		nodechild = di_sibling_node(nodechild);
10939e86db79SHyon Kim 	}
10949e86db79SHyon Kim 
10959e86db79SHyon Kim 
10969e86db79SHyon Kim 	while (path != DI_PATH_NIL) {
10979e86db79SHyon Kim 		if (get_attached_paths_info(path, port_ptr)
10989e86db79SHyon Kim 		    != HBA_STATUS_OK) {
10999e86db79SHyon Kim 			break;
11009e86db79SHyon Kim 		}
11019e86db79SHyon Kim 		path = di_path_phci_next_path(node, path);
11029e86db79SHyon Kim 	}
11039e86db79SHyon Kim 
11049e86db79SHyon Kim 	return (HBA_STATUS_OK);
11059e86db79SHyon Kim }
1106