110652SHyon.Kim@Sun.COM /*
210652SHyon.Kim@Sun.COM * CDDL HEADER START
310652SHyon.Kim@Sun.COM *
410652SHyon.Kim@Sun.COM * The contents of this file are subject to the terms of the
510652SHyon.Kim@Sun.COM * Common Development and Distribution License (the "License").
610652SHyon.Kim@Sun.COM * You may not use this file except in compliance with the License.
710652SHyon.Kim@Sun.COM *
810652SHyon.Kim@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910652SHyon.Kim@Sun.COM * or http://www.opensolaris.org/os/licensing.
1010652SHyon.Kim@Sun.COM * See the License for the specific language governing permissions
1110652SHyon.Kim@Sun.COM * and limitations under the License.
1210652SHyon.Kim@Sun.COM *
1310652SHyon.Kim@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1410652SHyon.Kim@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510652SHyon.Kim@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1610652SHyon.Kim@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1710652SHyon.Kim@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1810652SHyon.Kim@Sun.COM *
1910652SHyon.Kim@Sun.COM * CDDL HEADER END
2010652SHyon.Kim@Sun.COM */
2110652SHyon.Kim@Sun.COM
2210652SHyon.Kim@Sun.COM /*
2310652SHyon.Kim@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
2410652SHyon.Kim@Sun.COM * Use is subject to license terms.
2510652SHyon.Kim@Sun.COM */
2610652SHyon.Kim@Sun.COM
2710652SHyon.Kim@Sun.COM #include <sun_sas.h>
2810652SHyon.Kim@Sun.COM #include <sys/types.h>
2910652SHyon.Kim@Sun.COM #include <netinet/in.h>
3010652SHyon.Kim@Sun.COM #include <inttypes.h>
3110652SHyon.Kim@Sun.COM #include <ctype.h>
3210652SHyon.Kim@Sun.COM #include <sys/scsi/scsi_address.h>
3310652SHyon.Kim@Sun.COM #include <libdevid.h>
3410652SHyon.Kim@Sun.COM
3510652SHyon.Kim@Sun.COM /*
3610652SHyon.Kim@Sun.COM * Get the preferred minor node for the given path.
3710652SHyon.Kim@Sun.COM * ":n" for tapes, ":c,raw" for disks,
3810652SHyon.Kim@Sun.COM * and ":0" for enclosures.
3910652SHyon.Kim@Sun.COM */
4010652SHyon.Kim@Sun.COM static void
get_minor(char * devpath,char * minor)4110652SHyon.Kim@Sun.COM get_minor(char *devpath, char *minor)
4210652SHyon.Kim@Sun.COM {
4310652SHyon.Kim@Sun.COM const char ROUTINE[] = "get_minor";
4410652SHyon.Kim@Sun.COM char fullpath[MAXPATHLEN];
4510652SHyon.Kim@Sun.COM int fd;
4610652SHyon.Kim@Sun.COM
4710652SHyon.Kim@Sun.COM if ((strstr(devpath, "/st@")) || (strstr(devpath, "/tape@"))) {
4810652SHyon.Kim@Sun.COM (void) strcpy(minor, ":n");
4910652SHyon.Kim@Sun.COM } else if (strstr(devpath, "/smp@")) {
5010652SHyon.Kim@Sun.COM (void) strcpy(minor, ":smp");
5110652SHyon.Kim@Sun.COM } else if ((strstr(devpath, "/ssd@")) || (strstr(devpath, "/sd@")) ||
5210652SHyon.Kim@Sun.COM (strstr(devpath, "/disk@"))) {
5310652SHyon.Kim@Sun.COM (void) strcpy(minor, ":c,raw");
5410652SHyon.Kim@Sun.COM } else if ((strstr(devpath, "/ses@")) || (strstr(devpath,
5510652SHyon.Kim@Sun.COM "/enclosure@"))) {
5610652SHyon.Kim@Sun.COM (void) snprintf(fullpath, MAXPATHLEN, "%s%s%s", DEVICES_DIR,
5710652SHyon.Kim@Sun.COM devpath, ":0");
5810652SHyon.Kim@Sun.COM /* reset errno to 0 */
5910652SHyon.Kim@Sun.COM errno = 0;
6010652SHyon.Kim@Sun.COM if ((fd = open(fullpath, O_RDONLY)) == -1) {
6110652SHyon.Kim@Sun.COM /*
6210652SHyon.Kim@Sun.COM * :0 minor doesn't exist. assume bound to sgen driver
6310652SHyon.Kim@Sun.COM * and :ses minor exist.
6410652SHyon.Kim@Sun.COM */
6510652SHyon.Kim@Sun.COM if (errno == ENOENT) {
6610652SHyon.Kim@Sun.COM (void) strcpy(minor, ":ses");
6710652SHyon.Kim@Sun.COM }
6810652SHyon.Kim@Sun.COM } else {
6910652SHyon.Kim@Sun.COM (void) strcpy(minor, ":0");
7010652SHyon.Kim@Sun.COM (void) close(fd);
7110652SHyon.Kim@Sun.COM }
7210652SHyon.Kim@Sun.COM } else {
7310652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE, "Unrecognized target (%s)",
7410652SHyon.Kim@Sun.COM devpath);
7510652SHyon.Kim@Sun.COM minor[0] = '\0';
7610652SHyon.Kim@Sun.COM }
7710652SHyon.Kim@Sun.COM
7810652SHyon.Kim@Sun.COM }
7910652SHyon.Kim@Sun.COM
8010652SHyon.Kim@Sun.COM /*
8110652SHyon.Kim@Sun.COM * Free the attached port allocation.
8210652SHyon.Kim@Sun.COM */
8310652SHyon.Kim@Sun.COM static void
free_attached_port(struct sun_sas_port * port_ptr)8410652SHyon.Kim@Sun.COM free_attached_port(struct sun_sas_port *port_ptr)
8510652SHyon.Kim@Sun.COM {
8610652SHyon.Kim@Sun.COM struct sun_sas_port *tgt_port, *last_tgt_port;
8710652SHyon.Kim@Sun.COM struct ScsiEntryList *scsi_info = NULL, *last_scsi_info = NULL;
8810652SHyon.Kim@Sun.COM
8910652SHyon.Kim@Sun.COM tgt_port = port_ptr->first_attached_port;
9010652SHyon.Kim@Sun.COM while (tgt_port != NULL) {
9110652SHyon.Kim@Sun.COM /* Free target mapping data list first. */
9210652SHyon.Kim@Sun.COM scsi_info = tgt_port->scsiInfo;
9310652SHyon.Kim@Sun.COM while (scsi_info != NULL) {
9410652SHyon.Kim@Sun.COM last_scsi_info = scsi_info;
9510652SHyon.Kim@Sun.COM scsi_info = scsi_info->next;
9610652SHyon.Kim@Sun.COM free(last_scsi_info);
9710652SHyon.Kim@Sun.COM }
9810652SHyon.Kim@Sun.COM last_tgt_port = tgt_port;
9910652SHyon.Kim@Sun.COM tgt_port = tgt_port->next;
10010652SHyon.Kim@Sun.COM free(last_tgt_port->port_attributes.\
10110652SHyon.Kim@Sun.COM PortSpecificAttribute.SASPort);
10210652SHyon.Kim@Sun.COM free(last_tgt_port);
10310652SHyon.Kim@Sun.COM }
10410652SHyon.Kim@Sun.COM
10510652SHyon.Kim@Sun.COM port_ptr->first_attached_port = NULL;
10610652SHyon.Kim@Sun.COM port_ptr->port_attributes.PortSpecificAttribute.\
10710652SHyon.Kim@Sun.COM SASPort->NumberofDiscoveredPorts = 0;
10810652SHyon.Kim@Sun.COM }
10910652SHyon.Kim@Sun.COM
11010652SHyon.Kim@Sun.COM /*
11110652SHyon.Kim@Sun.COM * Fill domainPortWWN.
11210652SHyon.Kim@Sun.COM * should be called after completing discovered port discovery.
11310652SHyon.Kim@Sun.COM */
11410652SHyon.Kim@Sun.COM void
fillDomainPortWWN(struct sun_sas_port * port_ptr)11510652SHyon.Kim@Sun.COM fillDomainPortWWN(struct sun_sas_port *port_ptr)
11610652SHyon.Kim@Sun.COM {
11710652SHyon.Kim@Sun.COM const char ROUTINE[] = "fillDomainPortWWN";
11810652SHyon.Kim@Sun.COM struct sun_sas_port *disco_port_ptr;
11910652SHyon.Kim@Sun.COM struct phy_info *phy_ptr;
12010652SHyon.Kim@Sun.COM uint64_t domainPort = 0;
12110652SHyon.Kim@Sun.COM struct ScsiEntryList *mapping_ptr;
12210652SHyon.Kim@Sun.COM
12310652SHyon.Kim@Sun.COM for (disco_port_ptr = port_ptr->first_attached_port;
12410652SHyon.Kim@Sun.COM disco_port_ptr != NULL; disco_port_ptr = disco_port_ptr->next) {
12510652SHyon.Kim@Sun.COM if (disco_port_ptr->port_attributes.PortType ==
12610652SHyon.Kim@Sun.COM HBA_PORTTYPE_SASEXPANDER &&
12710652SHyon.Kim@Sun.COM wwnConversion(disco_port_ptr->port_attributes.
12810652SHyon.Kim@Sun.COM PortSpecificAttribute.SASPort->
12910652SHyon.Kim@Sun.COM AttachedSASAddress.wwn) ==
13010652SHyon.Kim@Sun.COM wwnConversion(port_ptr->port_attributes.
13110652SHyon.Kim@Sun.COM PortSpecificAttribute.SASPort->
13210652SHyon.Kim@Sun.COM LocalSASAddress.wwn)) {
13310652SHyon.Kim@Sun.COM (void) memcpy(&domainPort,
13410652SHyon.Kim@Sun.COM disco_port_ptr->port_attributes.
13510652SHyon.Kim@Sun.COM PortSpecificAttribute.
13610652SHyon.Kim@Sun.COM SASPort->LocalSASAddress.wwn, 8);
13710652SHyon.Kim@Sun.COM break;
13810652SHyon.Kim@Sun.COM }
13910652SHyon.Kim@Sun.COM }
14010652SHyon.Kim@Sun.COM
14110652SHyon.Kim@Sun.COM if (domainPort == 0) {
14210652SHyon.Kim@Sun.COM if (port_ptr->first_attached_port) {
14310652SHyon.Kim@Sun.COM /*
14410652SHyon.Kim@Sun.COM * there is no expander device attached on an HBA port
14510652SHyon.Kim@Sun.COM * domainPortWWN should not stay to 0 since multiple
14610652SHyon.Kim@Sun.COM * hba ports can have the same LocalSASAddres within
14710652SHyon.Kim@Sun.COM * the same HBA.
14810652SHyon.Kim@Sun.COM * Set the SAS address of direct attached target.
14910652SHyon.Kim@Sun.COM */
15010652SHyon.Kim@Sun.COM if (wwnConversion(port_ptr->port_attributes.
15110652SHyon.Kim@Sun.COM PortSpecificAttribute.SASPort->
15210652SHyon.Kim@Sun.COM LocalSASAddress.wwn) ==
15310652SHyon.Kim@Sun.COM wwnConversion(port_ptr->first_attached_port->
15410652SHyon.Kim@Sun.COM port_attributes.PortSpecificAttribute.
15510652SHyon.Kim@Sun.COM SASPort->AttachedSASAddress.wwn)) {
15610652SHyon.Kim@Sun.COM (void) memcpy(&domainPort,
15710652SHyon.Kim@Sun.COM port_ptr->first_attached_port->
15810652SHyon.Kim@Sun.COM port_attributes.PortSpecificAttribute.
15910652SHyon.Kim@Sun.COM SASPort->LocalSASAddress.wwn, 8);
16010652SHyon.Kim@Sun.COM } else {
16110652SHyon.Kim@Sun.COM /*
16210652SHyon.Kim@Sun.COM * SAS address is not upstream connected.
16310652SHyon.Kim@Sun.COM * domainPortWWN stays as 0.
16410652SHyon.Kim@Sun.COM */
16510652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
16610652SHyon.Kim@Sun.COM "DomainPortWWN is not set. "
16710652SHyon.Kim@Sun.COM "Device(s) are visible on the HBA port "
16810652SHyon.Kim@Sun.COM "but there is no expander or directly "
16910652SHyon.Kim@Sun.COM "attached port with matching upsteam "
17010652SHyon.Kim@Sun.COM "attached SAS address for "
17110652SHyon.Kim@Sun.COM "HBA port (Local SAS Address: %016llx).",
17210652SHyon.Kim@Sun.COM wwnConversion(port_ptr->port_attributes.
17310652SHyon.Kim@Sun.COM PortSpecificAttribute.
17410652SHyon.Kim@Sun.COM SASPort->LocalSASAddress.wwn));
17510652SHyon.Kim@Sun.COM return;
17610652SHyon.Kim@Sun.COM }
17710652SHyon.Kim@Sun.COM } else {
17810652SHyon.Kim@Sun.COM /*
17910652SHyon.Kim@Sun.COM * There existss an iport without properly configured
18010652SHyon.Kim@Sun.COM * child smp ndoes or child node or pathinfo.
18110652SHyon.Kim@Sun.COM * domainPortWWN stays as 0.
18210652SHyon.Kim@Sun.COM */
18310652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
18410652SHyon.Kim@Sun.COM "DomainPortWWN is not set. No properly "
18510652SHyon.Kim@Sun.COM "configured smp or directly attached port "
18610652SHyon.Kim@Sun.COM "found on HBA port(Local SAS Address: %016llx).",
18710652SHyon.Kim@Sun.COM wwnConversion(port_ptr->port_attributes.
18810652SHyon.Kim@Sun.COM PortSpecificAttribute.
18910652SHyon.Kim@Sun.COM SASPort->LocalSASAddress.wwn));
19010652SHyon.Kim@Sun.COM return;
19110652SHyon.Kim@Sun.COM }
19210652SHyon.Kim@Sun.COM }
19310652SHyon.Kim@Sun.COM
19410652SHyon.Kim@Sun.COM /* fill up phy info */
19510652SHyon.Kim@Sun.COM for (phy_ptr = port_ptr->first_phy; phy_ptr != NULL;
19610652SHyon.Kim@Sun.COM phy_ptr = phy_ptr->next) {
19710652SHyon.Kim@Sun.COM (void) memcpy(phy_ptr->phy.domainPortWWN.wwn, &domainPort, 8);
19810652SHyon.Kim@Sun.COM }
19910652SHyon.Kim@Sun.COM
20010652SHyon.Kim@Sun.COM /* fill up target mapping */
20110652SHyon.Kim@Sun.COM for (disco_port_ptr = port_ptr->first_attached_port;
20210652SHyon.Kim@Sun.COM disco_port_ptr != NULL; disco_port_ptr = disco_port_ptr->next) {
20310652SHyon.Kim@Sun.COM for (mapping_ptr = disco_port_ptr->scsiInfo;
20410652SHyon.Kim@Sun.COM mapping_ptr != NULL;
20510652SHyon.Kim@Sun.COM mapping_ptr = mapping_ptr->next) {
20610652SHyon.Kim@Sun.COM (void) memcpy(mapping_ptr->entry.PortLun.
20710652SHyon.Kim@Sun.COM domainPortWWN.wwn, &domainPort, 8);
20810652SHyon.Kim@Sun.COM }
20910652SHyon.Kim@Sun.COM }
21010652SHyon.Kim@Sun.COM }
21110652SHyon.Kim@Sun.COM
21210652SHyon.Kim@Sun.COM /*
21310652SHyon.Kim@Sun.COM * Finds attached device(target) from devinfo node.
21410652SHyon.Kim@Sun.COM */
21510652SHyon.Kim@Sun.COM static HBA_STATUS
get_attached_devices_info(di_node_t node,struct sun_sas_port * port_ptr)21610652SHyon.Kim@Sun.COM get_attached_devices_info(di_node_t node, struct sun_sas_port *port_ptr)
21710652SHyon.Kim@Sun.COM {
21810652SHyon.Kim@Sun.COM const char ROUTINE[] = "get_attached_devices_info";
21910652SHyon.Kim@Sun.COM char *propStringData = NULL;
22010652SHyon.Kim@Sun.COM int *propIntData = NULL;
22110652SHyon.Kim@Sun.COM int64_t *propInt64Data = NULL;
22210652SHyon.Kim@Sun.COM scsi_lun_t samLun;
223*11243SHyon.Kim@Sun.COM ddi_devid_t devid;
224*11243SHyon.Kim@Sun.COM char *guidStr;
22510652SHyon.Kim@Sun.COM char *unit_address;
22610652SHyon.Kim@Sun.COM char *charptr;
22710652SHyon.Kim@Sun.COM char *devpath, link[MAXNAMELEN];
22810652SHyon.Kim@Sun.COM char fullpath[MAXPATHLEN+1];
22910652SHyon.Kim@Sun.COM char minorname[MAXNAMELEN+1];
23010652SHyon.Kim@Sun.COM struct ScsiEntryList *mapping_ptr;
23110652SHyon.Kim@Sun.COM HBA_WWN SASAddress, AttachedSASAddress;
23210652SHyon.Kim@Sun.COM struct sun_sas_port *disco_port_ptr;
23310652SHyon.Kim@Sun.COM uint_t state = 0;
234*11243SHyon.Kim@Sun.COM int portfound, rval, size;
23510652SHyon.Kim@Sun.COM int port_state = HBA_PORTSTATE_ONLINE;
23610652SHyon.Kim@Sun.COM uint64_t tmpAddr;
23710652SHyon.Kim@Sun.COM
23810652SHyon.Kim@Sun.COM if (port_ptr == NULL) {
23910652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE, "NULL port_ptr argument");
24010652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
24110652SHyon.Kim@Sun.COM }
24210652SHyon.Kim@Sun.COM
24310652SHyon.Kim@Sun.COM if ((devpath = di_devfs_path(node)) == NULL) {
24410652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
24510652SHyon.Kim@Sun.COM "Device in device tree has no path. Skipping.");
24610652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
24710652SHyon.Kim@Sun.COM }
24810652SHyon.Kim@Sun.COM
24910652SHyon.Kim@Sun.COM if ((di_instance(node) == -1) || di_retired(node)) {
25010652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
25110652SHyon.Kim@Sun.COM "dev node (%s) returned instance of -1 or is retired. "
25210652SHyon.Kim@Sun.COM " Skipping.", devpath);
25310652SHyon.Kim@Sun.COM di_devfs_path_free(devpath);
25410652SHyon.Kim@Sun.COM return (HBA_STATUS_OK);
25510652SHyon.Kim@Sun.COM }
25610652SHyon.Kim@Sun.COM state = di_state(node);
25710652SHyon.Kim@Sun.COM /* when node is not attached and online, set the state to offline. */
25810652SHyon.Kim@Sun.COM if (((state & DI_DRIVER_DETACHED) == DI_DRIVER_DETACHED) ||
25910652SHyon.Kim@Sun.COM ((state & DI_DEVICE_OFFLINE) == DI_DEVICE_OFFLINE)) {
26010652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
26110652SHyon.Kim@Sun.COM "dev node (%s) is either OFFLINE or DETACHED",
26210652SHyon.Kim@Sun.COM devpath);
26310652SHyon.Kim@Sun.COM port_state = HBA_PORTSTATE_OFFLINE;
26410652SHyon.Kim@Sun.COM }
26510652SHyon.Kim@Sun.COM
26610652SHyon.Kim@Sun.COM /* add the "/devices" in the begining at the end */
26710652SHyon.Kim@Sun.COM (void) snprintf(fullpath, sizeof (fullpath), "%s%s",
26810652SHyon.Kim@Sun.COM DEVICES_DIR, devpath);
26910652SHyon.Kim@Sun.COM
27010652SHyon.Kim@Sun.COM (void) memset(&SASAddress, 0, sizeof (SASAddress));
27110652SHyon.Kim@Sun.COM if ((unit_address = di_bus_addr(node)) != NULL) {
27210652SHyon.Kim@Sun.COM if ((charptr = strchr(unit_address, ',')) != NULL) {
27310652SHyon.Kim@Sun.COM *charptr = '\0';
27410652SHyon.Kim@Sun.COM }
27510652SHyon.Kim@Sun.COM for (charptr = unit_address; *charptr != '\0'; charptr++) {
27610652SHyon.Kim@Sun.COM if (isxdigit(*charptr)) {
27710652SHyon.Kim@Sun.COM break;
27810652SHyon.Kim@Sun.COM }
27910652SHyon.Kim@Sun.COM }
28010652SHyon.Kim@Sun.COM if (*charptr != '\0') {
28110652SHyon.Kim@Sun.COM tmpAddr = htonll(strtoll(charptr, NULL, 16));
28210652SHyon.Kim@Sun.COM (void) memcpy(&SASAddress.wwn[0], &tmpAddr, 8);
28310652SHyon.Kim@Sun.COM } else {
28410652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
28510652SHyon.Kim@Sun.COM "No proper target port info on unit address of %s",
28610652SHyon.Kim@Sun.COM fullpath);
28710652SHyon.Kim@Sun.COM di_devfs_path_free(devpath);
28810652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
28910652SHyon.Kim@Sun.COM }
29010652SHyon.Kim@Sun.COM } else {
29110652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
29210652SHyon.Kim@Sun.COM "Fail to get unit address of %s.",
29310652SHyon.Kim@Sun.COM fullpath);
29410652SHyon.Kim@Sun.COM di_devfs_path_free(devpath);
29510652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
29610652SHyon.Kim@Sun.COM }
29710652SHyon.Kim@Sun.COM
29810652SHyon.Kim@Sun.COM (void) memset(&AttachedSASAddress, 0, sizeof (AttachedSASAddress));
29910652SHyon.Kim@Sun.COM if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "attached-port",
30010652SHyon.Kim@Sun.COM &propStringData) != -1) {
30110652SHyon.Kim@Sun.COM for (charptr = propStringData; *charptr != '\0'; charptr++) {
30210652SHyon.Kim@Sun.COM if (isxdigit(*charptr)) {
30310652SHyon.Kim@Sun.COM break;
30410652SHyon.Kim@Sun.COM }
30510652SHyon.Kim@Sun.COM }
30610652SHyon.Kim@Sun.COM if (*charptr != '\0') {
30710652SHyon.Kim@Sun.COM tmpAddr = htonll(strtoll(charptr, NULL, 16));
30810652SHyon.Kim@Sun.COM (void) memcpy(AttachedSASAddress.wwn, &tmpAddr, 8);
30910652SHyon.Kim@Sun.COM /* check the attached address of hba port. */
31010652SHyon.Kim@Sun.COM if (memcmp(port_ptr->port_attributes.
31110652SHyon.Kim@Sun.COM PortSpecificAttribute.SASPort->LocalSASAddress.wwn,
31210652SHyon.Kim@Sun.COM &tmpAddr, 8) == 0) {
31310652SHyon.Kim@Sun.COM /*
31410652SHyon.Kim@Sun.COM * When attached-port is set from iport
31510652SHyon.Kim@Sun.COM * attached-port prop, we do the cross check
31610652SHyon.Kim@Sun.COM * with device's own SAS address.
31710652SHyon.Kim@Sun.COM *
31810652SHyon.Kim@Sun.COM * If not set, we store device's own SAS
31910652SHyon.Kim@Sun.COM * address to iport attached SAS address.
32010652SHyon.Kim@Sun.COM */
32110652SHyon.Kim@Sun.COM if (wwnConversion(port_ptr->port_attributes.
32210652SHyon.Kim@Sun.COM PortSpecificAttribute.SASPort->
32310652SHyon.Kim@Sun.COM AttachedSASAddress.wwn)) {
32410652SHyon.Kim@Sun.COM /* verify the Attaached SAS Addr. */
32510652SHyon.Kim@Sun.COM if (memcmp(port_ptr->port_attributes.
32610652SHyon.Kim@Sun.COM PortSpecificAttribute.SASPort->
32710652SHyon.Kim@Sun.COM AttachedSASAddress.wwn,
32810652SHyon.Kim@Sun.COM SASAddress.wwn, 8) != 0) {
32910652SHyon.Kim@Sun.COM /* indentation move begin. */
33010652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
33110652SHyon.Kim@Sun.COM "iport attached-port(%016llx) do not"
33210652SHyon.Kim@Sun.COM " match with level 1 Local"
33310652SHyon.Kim@Sun.COM " SAS address(%016llx).",
33410652SHyon.Kim@Sun.COM wwnConversion(port_ptr->port_attributes.
33510652SHyon.Kim@Sun.COM PortSpecificAttribute.
33610652SHyon.Kim@Sun.COM SASPort->AttachedSASAddress.wwn),
33710652SHyon.Kim@Sun.COM wwnConversion(SASAddress.wwn));
33810652SHyon.Kim@Sun.COM di_devfs_path_free(devpath);
33910652SHyon.Kim@Sun.COM free_attached_port(port_ptr);
34010652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
34110652SHyon.Kim@Sun.COM /* indentation move ends. */
34210652SHyon.Kim@Sun.COM }
34310652SHyon.Kim@Sun.COM } else {
34410652SHyon.Kim@Sun.COM (void) memcpy(port_ptr->port_attributes.
34510652SHyon.Kim@Sun.COM PortSpecificAttribute.
34610652SHyon.Kim@Sun.COM SASPort->AttachedSASAddress.wwn,
34710652SHyon.Kim@Sun.COM &SASAddress.wwn[0], 8);
34810652SHyon.Kim@Sun.COM }
34910652SHyon.Kim@Sun.COM }
35010652SHyon.Kim@Sun.COM } else {
35110652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
35210652SHyon.Kim@Sun.COM "No proper attached SAS address value on device %s",
35310652SHyon.Kim@Sun.COM fullpath);
35410652SHyon.Kim@Sun.COM di_devfs_path_free(devpath);
35510652SHyon.Kim@Sun.COM free_attached_port(port_ptr);
35610652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
35710652SHyon.Kim@Sun.COM }
35810652SHyon.Kim@Sun.COM } else {
35910652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
36010652SHyon.Kim@Sun.COM "Property AttachedSASAddress not found for device \"%s\"",
36110652SHyon.Kim@Sun.COM fullpath);
36210652SHyon.Kim@Sun.COM di_devfs_path_free(devpath);
36310652SHyon.Kim@Sun.COM free_attached_port(port_ptr);
36410652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
36510652SHyon.Kim@Sun.COM }
36610652SHyon.Kim@Sun.COM
36710652SHyon.Kim@Sun.COM /*
36810652SHyon.Kim@Sun.COM * walk the disco list to make sure that there isn't a matching
36910652SHyon.Kim@Sun.COM * port and node wwn or a matching device path
37010652SHyon.Kim@Sun.COM */
37110652SHyon.Kim@Sun.COM portfound = 0;
37210652SHyon.Kim@Sun.COM for (disco_port_ptr = port_ptr->first_attached_port;
37310652SHyon.Kim@Sun.COM disco_port_ptr != NULL;
37410652SHyon.Kim@Sun.COM disco_port_ptr = disco_port_ptr->next) {
37510652SHyon.Kim@Sun.COM if ((disco_port_ptr->port_attributes.PortState !=
37610652SHyon.Kim@Sun.COM HBA_PORTSTATE_ERROR) && (memcmp(disco_port_ptr->
37710652SHyon.Kim@Sun.COM port_attributes.PortSpecificAttribute.
37810652SHyon.Kim@Sun.COM SASPort->LocalSASAddress.wwn, SASAddress.wwn, 8) == 0)) {
37910652SHyon.Kim@Sun.COM /*
38010652SHyon.Kim@Sun.COM * found matching disco_port
38110652SHyon.Kim@Sun.COM * look for matching device path
38210652SHyon.Kim@Sun.COM */
38310652SHyon.Kim@Sun.COM portfound = 1;
38410652SHyon.Kim@Sun.COM for (mapping_ptr = disco_port_ptr->scsiInfo;
38510652SHyon.Kim@Sun.COM mapping_ptr != NULL;
38610652SHyon.Kim@Sun.COM mapping_ptr = mapping_ptr->next) {
38710652SHyon.Kim@Sun.COM if (strstr(mapping_ptr-> entry.ScsiId.
38810652SHyon.Kim@Sun.COM OSDeviceName, devpath) != 0) {
38910652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
39010652SHyon.Kim@Sun.COM "Found an already discovered "
39110652SHyon.Kim@Sun.COM "device %s.", fullpath);
39210652SHyon.Kim@Sun.COM di_devfs_path_free(devpath);
39310652SHyon.Kim@Sun.COM return (HBA_STATUS_OK);
39410652SHyon.Kim@Sun.COM }
39510652SHyon.Kim@Sun.COM }
39610652SHyon.Kim@Sun.COM if (portfound == 1) {
39710652SHyon.Kim@Sun.COM break;
39810652SHyon.Kim@Sun.COM }
39910652SHyon.Kim@Sun.COM }
40010652SHyon.Kim@Sun.COM }
40110652SHyon.Kim@Sun.COM
40210652SHyon.Kim@Sun.COM if (portfound == 0) {
40310652SHyon.Kim@Sun.COM /*
40410652SHyon.Kim@Sun.COM * there are no matching SAS address.
40510652SHyon.Kim@Sun.COM * this must be a new device
40610652SHyon.Kim@Sun.COM */
40710652SHyon.Kim@Sun.COM if ((disco_port_ptr = (struct sun_sas_port *)calloc(1,
40810652SHyon.Kim@Sun.COM sizeof (struct sun_sas_port))) == NULL) {
40910652SHyon.Kim@Sun.COM OUT_OF_MEMORY(ROUTINE);
41010652SHyon.Kim@Sun.COM di_devfs_path_free(devpath);
41110652SHyon.Kim@Sun.COM free_attached_port(port_ptr);
41210652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
41310652SHyon.Kim@Sun.COM }
41410652SHyon.Kim@Sun.COM
41510652SHyon.Kim@Sun.COM if ((disco_port_ptr->port_attributes.PortSpecificAttribute.\
41610652SHyon.Kim@Sun.COM SASPort = (struct SMHBA_SAS_Port *)calloc(1,
41710652SHyon.Kim@Sun.COM sizeof (struct SMHBA_SAS_Port))) == NULL) {
41810652SHyon.Kim@Sun.COM OUT_OF_MEMORY("add_hba_port_info");
41910652SHyon.Kim@Sun.COM di_devfs_path_free(devpath);
42010652SHyon.Kim@Sun.COM free_attached_port(port_ptr);
42110652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
42210652SHyon.Kim@Sun.COM }
42310652SHyon.Kim@Sun.COM
42410652SHyon.Kim@Sun.COM (void) memcpy(disco_port_ptr->port_attributes.
42510652SHyon.Kim@Sun.COM PortSpecificAttribute.SASPort->LocalSASAddress.wwn,
42610652SHyon.Kim@Sun.COM SASAddress.wwn, 8);
42710652SHyon.Kim@Sun.COM (void) memcpy(disco_port_ptr->port_attributes.
42810652SHyon.Kim@Sun.COM PortSpecificAttribute.SASPort->AttachedSASAddress.wwn,
42910652SHyon.Kim@Sun.COM AttachedSASAddress.wwn, 8);
43010652SHyon.Kim@Sun.COM
43110652SHyon.Kim@Sun.COM /* Default to unknown until we figure out otherwise */
43210652SHyon.Kim@Sun.COM rval = di_prop_lookup_strings(DDI_DEV_T_ANY, node,
43310652SHyon.Kim@Sun.COM "variant", &propStringData);
43410652SHyon.Kim@Sun.COM if (rval < 0) {
43510652SHyon.Kim@Sun.COM /* check if it is SMP target */
43610652SHyon.Kim@Sun.COM charptr = di_driver_name(node);
43710652SHyon.Kim@Sun.COM if (charptr != NULL && (strncmp(charptr, "smp",
43810652SHyon.Kim@Sun.COM strlen(charptr)) == 0)) {
43910652SHyon.Kim@Sun.COM disco_port_ptr->port_attributes.PortType =
44010652SHyon.Kim@Sun.COM HBA_PORTTYPE_SASEXPANDER;
44110652SHyon.Kim@Sun.COM disco_port_ptr->port_attributes.
44210652SHyon.Kim@Sun.COM PortSpecificAttribute.
44310652SHyon.Kim@Sun.COM SASPort->PortProtocol =
44410652SHyon.Kim@Sun.COM HBA_SASPORTPROTOCOL_SMP;
44510652SHyon.Kim@Sun.COM if (lookupSMPLink(devpath, (char *)link) ==
44610652SHyon.Kim@Sun.COM HBA_STATUS_OK) {
44710652SHyon.Kim@Sun.COM /* indentation changed here. */
44810652SHyon.Kim@Sun.COM (void) strlcpy(disco_port_ptr->port_attributes.
44910652SHyon.Kim@Sun.COM OSDeviceName, link,
45010652SHyon.Kim@Sun.COM sizeof (disco_port_ptr->port_attributes.OSDeviceName));
45110652SHyon.Kim@Sun.COM /* indentation change ends here. */
45210652SHyon.Kim@Sun.COM } else {
45310652SHyon.Kim@Sun.COM /* indentation changed here. */
45410652SHyon.Kim@Sun.COM get_minor(devpath, minorname);
45510652SHyon.Kim@Sun.COM (void) snprintf(fullpath, sizeof (fullpath), "%s%s%s",
45610652SHyon.Kim@Sun.COM DEVICES_DIR, devpath, minorname);
45710652SHyon.Kim@Sun.COM (void) strlcpy(disco_port_ptr->port_attributes.
45810652SHyon.Kim@Sun.COM OSDeviceName, fullpath,
45910652SHyon.Kim@Sun.COM sizeof (disco_port_ptr->port_attributes.OSDeviceName));
46010652SHyon.Kim@Sun.COM /* indentation change ends here. */
46110652SHyon.Kim@Sun.COM }
46210652SHyon.Kim@Sun.COM } else {
46310652SHyon.Kim@Sun.COM disco_port_ptr->port_attributes.PortType =
46410652SHyon.Kim@Sun.COM HBA_PORTTYPE_SASDEVICE;
46510652SHyon.Kim@Sun.COM disco_port_ptr->port_attributes.\
46610652SHyon.Kim@Sun.COM PortSpecificAttribute.\
46710652SHyon.Kim@Sun.COM SASPort->PortProtocol =
46810652SHyon.Kim@Sun.COM HBA_SASPORTPROTOCOL_SSP;
46910652SHyon.Kim@Sun.COM }
47010652SHyon.Kim@Sun.COM } else {
47110652SHyon.Kim@Sun.COM if ((strcmp(propStringData, "sata") == 0) ||
47210652SHyon.Kim@Sun.COM (strcmp(propStringData, "atapi") == 0)) {
47310652SHyon.Kim@Sun.COM disco_port_ptr->port_attributes.PortType =
47410652SHyon.Kim@Sun.COM HBA_PORTTYPE_SATADEVICE;
47510652SHyon.Kim@Sun.COM disco_port_ptr->port_attributes.\
47610652SHyon.Kim@Sun.COM PortSpecificAttribute.SASPort->PortProtocol
47710652SHyon.Kim@Sun.COM = HBA_SASPORTPROTOCOL_SATA;
47810652SHyon.Kim@Sun.COM } else {
47910652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
48010652SHyon.Kim@Sun.COM "Unexpected variant prop value %s found on",
48110652SHyon.Kim@Sun.COM " device %s", propStringData, fullpath);
48210652SHyon.Kim@Sun.COM /*
48310652SHyon.Kim@Sun.COM * Port type will be 0
48410652SHyon.Kim@Sun.COM * which is not valid type.
48510652SHyon.Kim@Sun.COM */
48610652SHyon.Kim@Sun.COM }
48710652SHyon.Kim@Sun.COM }
48810652SHyon.Kim@Sun.COM
48910652SHyon.Kim@Sun.COM /* SMP device was handled already */
49010652SHyon.Kim@Sun.COM if (disco_port_ptr->port_attributes.OSDeviceName[0] == '\0') {
49110652SHyon.Kim@Sun.COM /* indentation change due to ctysle check on sizeof. */
49210652SHyon.Kim@Sun.COM size = sizeof (disco_port_ptr->port_attributes.OSDeviceName);
49310652SHyon.Kim@Sun.COM (void) strlcpy(disco_port_ptr->port_attributes.
49410652SHyon.Kim@Sun.COM OSDeviceName, fullpath, size);
49510652SHyon.Kim@Sun.COM }
49610652SHyon.Kim@Sun.COM
49710652SHyon.Kim@Sun.COM /* add new discovered port into the list */
49810652SHyon.Kim@Sun.COM
49910652SHyon.Kim@Sun.COM if (port_ptr->first_attached_port == NULL) {
50010652SHyon.Kim@Sun.COM port_ptr->first_attached_port = disco_port_ptr;
50110652SHyon.Kim@Sun.COM disco_port_ptr->index = 0;
50210652SHyon.Kim@Sun.COM port_ptr->port_attributes.PortSpecificAttribute.\
50310652SHyon.Kim@Sun.COM SASPort->NumberofDiscoveredPorts = 1;
50410652SHyon.Kim@Sun.COM } else {
50510652SHyon.Kim@Sun.COM disco_port_ptr->next = port_ptr->first_attached_port;
50610652SHyon.Kim@Sun.COM port_ptr->first_attached_port = disco_port_ptr;
50710652SHyon.Kim@Sun.COM disco_port_ptr->index = port_ptr->port_attributes.\
50810652SHyon.Kim@Sun.COM PortSpecificAttribute.\
50910652SHyon.Kim@Sun.COM SASPort->NumberofDiscoveredPorts;
51010652SHyon.Kim@Sun.COM port_ptr->port_attributes.PortSpecificAttribute.\
51110652SHyon.Kim@Sun.COM SASPort->NumberofDiscoveredPorts++;
51210652SHyon.Kim@Sun.COM }
51310652SHyon.Kim@Sun.COM disco_port_ptr->port_attributes.PortState = port_state;
51410652SHyon.Kim@Sun.COM }
51510652SHyon.Kim@Sun.COM
51610652SHyon.Kim@Sun.COM if (disco_port_ptr->port_attributes.PortType ==
51710652SHyon.Kim@Sun.COM HBA_PORTTYPE_SASEXPANDER) {
51810652SHyon.Kim@Sun.COM /* No mapping data for expander device. return ok here. */
51910652SHyon.Kim@Sun.COM di_devfs_path_free(devpath);
52010652SHyon.Kim@Sun.COM return (HBA_STATUS_OK);
52110652SHyon.Kim@Sun.COM }
52210652SHyon.Kim@Sun.COM
52310652SHyon.Kim@Sun.COM if ((mapping_ptr = (struct ScsiEntryList *)calloc
52410652SHyon.Kim@Sun.COM (1, sizeof (struct ScsiEntryList))) == NULL) {
52510652SHyon.Kim@Sun.COM OUT_OF_MEMORY(ROUTINE);
52610652SHyon.Kim@Sun.COM di_devfs_path_free(devpath);
52710652SHyon.Kim@Sun.COM free_attached_port(port_ptr);
52810652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
52910652SHyon.Kim@Sun.COM }
53010652SHyon.Kim@Sun.COM
53110652SHyon.Kim@Sun.COM if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "lun",
53210652SHyon.Kim@Sun.COM &propIntData) != -1) {
53310652SHyon.Kim@Sun.COM mapping_ptr->entry.ScsiId.ScsiOSLun = *propIntData;
53410652SHyon.Kim@Sun.COM } else {
53510652SHyon.Kim@Sun.COM if ((charptr = strchr(unit_address, ',')) != NULL) {
53610652SHyon.Kim@Sun.COM charptr++;
53710652SHyon.Kim@Sun.COM mapping_ptr->entry.ScsiId.ScsiOSLun =
53810652SHyon.Kim@Sun.COM strtoull(charptr, NULL, 10);
53910652SHyon.Kim@Sun.COM } else {
54010652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
54110652SHyon.Kim@Sun.COM "Failed to get LUN from the unit address of device "
54210652SHyon.Kim@Sun.COM " %s.", fullpath);
54310652SHyon.Kim@Sun.COM di_devfs_path_free(devpath);
54410652SHyon.Kim@Sun.COM free_attached_port(port_ptr);
54510652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
54610652SHyon.Kim@Sun.COM }
54710652SHyon.Kim@Sun.COM }
54810652SHyon.Kim@Sun.COM
54910652SHyon.Kim@Sun.COM /* get TargetLun(SAM-LUN). */
55010652SHyon.Kim@Sun.COM if (di_prop_lookup_int64(DDI_DEV_T_ANY, node, "lun64",
55110652SHyon.Kim@Sun.COM &propInt64Data) != -1) {
55210652SHyon.Kim@Sun.COM samLun = scsi_lun64_to_lun(*propInt64Data);
55310652SHyon.Kim@Sun.COM (void) memcpy(&mapping_ptr->entry.PortLun.TargetLun,
55410652SHyon.Kim@Sun.COM &samLun, 8);
55510652SHyon.Kim@Sun.COM } else {
55610652SHyon.Kim@Sun.COM log(LOG_DEBUG, "get_attached_devices_info",
55710652SHyon.Kim@Sun.COM "No lun64 prop found on device %s.", fullpath);
55810652SHyon.Kim@Sun.COM di_devfs_path_free(devpath);
55910652SHyon.Kim@Sun.COM free_attached_port(port_ptr);
56010652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
56110652SHyon.Kim@Sun.COM }
56210652SHyon.Kim@Sun.COM
56310652SHyon.Kim@Sun.COM if (di_prop_lookup_ints(DDI_DEV_T_ANY, node,
56410652SHyon.Kim@Sun.COM "target", &propIntData) != -1) {
56510652SHyon.Kim@Sun.COM mapping_ptr->entry.ScsiId.ScsiTargetNumber = *propIntData;
56610652SHyon.Kim@Sun.COM } else {
56710652SHyon.Kim@Sun.COM mapping_ptr->entry.ScsiId.ScsiTargetNumber = di_instance(node);
56810652SHyon.Kim@Sun.COM }
56910652SHyon.Kim@Sun.COM
57010652SHyon.Kim@Sun.COM /* get ScsiBusNumber */
57110652SHyon.Kim@Sun.COM mapping_ptr->entry.ScsiId.ScsiBusNumber = port_ptr->cntlNumber;
57210652SHyon.Kim@Sun.COM
57310652SHyon.Kim@Sun.COM (void) memcpy(mapping_ptr->entry.PortLun.PortWWN.wwn,
57410652SHyon.Kim@Sun.COM SASAddress.wwn, 8);
57510652SHyon.Kim@Sun.COM
57610652SHyon.Kim@Sun.COM /* Store the devices path for now. We'll convert to /dev later */
57710652SHyon.Kim@Sun.COM get_minor(devpath, minorname);
57810652SHyon.Kim@Sun.COM (void) snprintf(mapping_ptr->entry.ScsiId.OSDeviceName,
57910652SHyon.Kim@Sun.COM sizeof (mapping_ptr->entry.ScsiId.OSDeviceName),
58010652SHyon.Kim@Sun.COM "%s%s%s", DEVICES_DIR, devpath, minorname);
58110652SHyon.Kim@Sun.COM
582*11243SHyon.Kim@Sun.COM /* reset errno to 0 */
583*11243SHyon.Kim@Sun.COM errno = 0;
584*11243SHyon.Kim@Sun.COM if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "devid",
585*11243SHyon.Kim@Sun.COM &propStringData) != -1) {
586*11243SHyon.Kim@Sun.COM if (devid_str_decode(propStringData, &devid, NULL) != -1) {
587*11243SHyon.Kim@Sun.COM guidStr = devid_to_guid(devid);
588*11243SHyon.Kim@Sun.COM if (guidStr != NULL) {
589*11243SHyon.Kim@Sun.COM (void) strlcpy(mapping_ptr->entry.LUID.buffer,
590*11243SHyon.Kim@Sun.COM guidStr, 256);
591*11243SHyon.Kim@Sun.COM devid_free_guid(guidStr);
592*11243SHyon.Kim@Sun.COM } else {
593*11243SHyon.Kim@Sun.COM /*
594*11243SHyon.Kim@Sun.COM * Note:
595*11243SHyon.Kim@Sun.COM * if logical unit associated page 83 id
596*11243SHyon.Kim@Sun.COM * descriptor is not avaialble for the device
597*11243SHyon.Kim@Sun.COM * devid_to_guid returns NULl with errno 0.
598*11243SHyon.Kim@Sun.COM */
599*11243SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
600*11243SHyon.Kim@Sun.COM "failed to get devid guid on (%s) : %s",
601*11243SHyon.Kim@Sun.COM devpath, strerror(errno));
602*11243SHyon.Kim@Sun.COM }
603*11243SHyon.Kim@Sun.COM } else {
604*11243SHyon.Kim@Sun.COM /*
605*11243SHyon.Kim@Sun.COM * device may not support proper page 83 id descriptor.
606*11243SHyon.Kim@Sun.COM * leave LUID attribute to NULL and continue.
607*11243SHyon.Kim@Sun.COM */
608*11243SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
609*11243SHyon.Kim@Sun.COM "failed to decode devid prop on (%s) : %s",
610*11243SHyon.Kim@Sun.COM devpath, strerror(errno));
611*11243SHyon.Kim@Sun.COM }
61210652SHyon.Kim@Sun.COM } else {
613*11243SHyon.Kim@Sun.COM /* leave LUID attribute to NULL and continue. */
614*11243SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
615*11243SHyon.Kim@Sun.COM "failed to get devid prop on (%s) : %s",
616*11243SHyon.Kim@Sun.COM devpath, strerror(errno));
61710652SHyon.Kim@Sun.COM }
61810652SHyon.Kim@Sun.COM
61910652SHyon.Kim@Sun.COM if (disco_port_ptr->scsiInfo == NULL) {
62010652SHyon.Kim@Sun.COM disco_port_ptr->scsiInfo = mapping_ptr;
62110652SHyon.Kim@Sun.COM } else {
62210652SHyon.Kim@Sun.COM mapping_ptr->next = disco_port_ptr->scsiInfo;
62310652SHyon.Kim@Sun.COM disco_port_ptr->scsiInfo = mapping_ptr;
62410652SHyon.Kim@Sun.COM }
62510652SHyon.Kim@Sun.COM
62610652SHyon.Kim@Sun.COM di_devfs_path_free(devpath);
62710652SHyon.Kim@Sun.COM
62810652SHyon.Kim@Sun.COM return (HBA_STATUS_OK);
62910652SHyon.Kim@Sun.COM }
63010652SHyon.Kim@Sun.COM
63110652SHyon.Kim@Sun.COM /*
63210652SHyon.Kim@Sun.COM * Finds attached device(target) from pathinfo node.
63310652SHyon.Kim@Sun.COM */
63410652SHyon.Kim@Sun.COM static HBA_STATUS
get_attached_paths_info(di_path_t path,struct sun_sas_port * port_ptr)63510652SHyon.Kim@Sun.COM get_attached_paths_info(di_path_t path, struct sun_sas_port *port_ptr)
63610652SHyon.Kim@Sun.COM {
63710652SHyon.Kim@Sun.COM char ROUTINE[] = "get_attached_paths_info";
63810652SHyon.Kim@Sun.COM char *propStringData = NULL;
63910652SHyon.Kim@Sun.COM int *propIntData = NULL;
64010652SHyon.Kim@Sun.COM int64_t *propInt64Data = NULL;
64110652SHyon.Kim@Sun.COM scsi_lun_t samLun;
642*11243SHyon.Kim@Sun.COM ddi_devid_t devid;
643*11243SHyon.Kim@Sun.COM char *guidStr;
64410652SHyon.Kim@Sun.COM char *unit_address;
64510652SHyon.Kim@Sun.COM char *charptr;
64610652SHyon.Kim@Sun.COM char *clientdevpath = NULL;
64710652SHyon.Kim@Sun.COM char *pathdevpath = NULL;
64810652SHyon.Kim@Sun.COM char fullpath[MAXPATHLEN+1];
64910652SHyon.Kim@Sun.COM char minorname[MAXNAMELEN+1];
65010652SHyon.Kim@Sun.COM struct ScsiEntryList *mapping_ptr;
65110652SHyon.Kim@Sun.COM HBA_WWN SASAddress, AttachedSASAddress;
65210652SHyon.Kim@Sun.COM struct sun_sas_port *disco_port_ptr;
65310652SHyon.Kim@Sun.COM di_path_state_t state = 0;
65410652SHyon.Kim@Sun.COM di_node_t clientnode;
65510652SHyon.Kim@Sun.COM int portfound, size;
65610652SHyon.Kim@Sun.COM int port_state = HBA_PORTSTATE_ONLINE;
65710652SHyon.Kim@Sun.COM uint64_t tmpAddr;
65810652SHyon.Kim@Sun.COM
65910652SHyon.Kim@Sun.COM if (port_ptr == NULL) {
66010652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE, "NULL port_ptr argument");
66110652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
66210652SHyon.Kim@Sun.COM }
66310652SHyon.Kim@Sun.COM
66410652SHyon.Kim@Sun.COM /* if not null, free before return. */
66510652SHyon.Kim@Sun.COM pathdevpath = di_path_devfs_path(path);
66610652SHyon.Kim@Sun.COM
66710652SHyon.Kim@Sun.COM state = di_path_state(path);
66810652SHyon.Kim@Sun.COM /* when node is not attached and online, set the state to offline. */
66910652SHyon.Kim@Sun.COM if ((state == DI_PATH_STATE_OFFLINE) ||
67010652SHyon.Kim@Sun.COM (state == DI_PATH_STATE_FAULT)) {
67110652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
67210652SHyon.Kim@Sun.COM "path node (%s) is either OFFLINE or FAULT state",
67310652SHyon.Kim@Sun.COM pathdevpath ? pathdevpath : "(missing device path)");
67410652SHyon.Kim@Sun.COM port_state = HBA_PORTSTATE_OFFLINE;
67510652SHyon.Kim@Sun.COM }
67610652SHyon.Kim@Sun.COM
67710652SHyon.Kim@Sun.COM if (clientnode = di_path_client_node(path)) {
67810652SHyon.Kim@Sun.COM if (di_retired(clientnode)) {
67910652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
68010652SHyon.Kim@Sun.COM "client node of path (%s) is retired. Skipping.",
68110652SHyon.Kim@Sun.COM pathdevpath ? pathdevpath :
68210652SHyon.Kim@Sun.COM "(missing device path)");
68310652SHyon.Kim@Sun.COM if (pathdevpath) di_devfs_path_free(pathdevpath);
68410652SHyon.Kim@Sun.COM return (HBA_STATUS_OK);
68510652SHyon.Kim@Sun.COM }
68610652SHyon.Kim@Sun.COM if ((clientdevpath = di_devfs_path(clientnode)) == NULL) {
68710652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
68810652SHyon.Kim@Sun.COM "Client device of path (%s) has no path. Skipping.",
68910652SHyon.Kim@Sun.COM pathdevpath ? pathdevpath :
69010652SHyon.Kim@Sun.COM "(missing device path)");
69110652SHyon.Kim@Sun.COM if (pathdevpath) di_devfs_path_free(pathdevpath);
69210652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
69310652SHyon.Kim@Sun.COM }
69410652SHyon.Kim@Sun.COM } else {
69510652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
69610652SHyon.Kim@Sun.COM "Failed to get client device from a path (%s).",
69710652SHyon.Kim@Sun.COM pathdevpath ? pathdevpath :
69810652SHyon.Kim@Sun.COM "(missing device path)");
69910652SHyon.Kim@Sun.COM if (pathdevpath) di_devfs_path_free(pathdevpath);
70010652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
70110652SHyon.Kim@Sun.COM }
70210652SHyon.Kim@Sun.COM
70310652SHyon.Kim@Sun.COM /* add the "/devices" in the begining and the :devctl at the end */
70410652SHyon.Kim@Sun.COM (void) snprintf(fullpath, sizeof (fullpath), "%s%s", DEVICES_DIR,
70510652SHyon.Kim@Sun.COM clientdevpath);
70610652SHyon.Kim@Sun.COM
70710652SHyon.Kim@Sun.COM (void) memset(&SASAddress, 0, sizeof (SASAddress));
70810652SHyon.Kim@Sun.COM if ((unit_address = di_path_bus_addr(path)) != NULL) {
70910652SHyon.Kim@Sun.COM if ((charptr = strchr(unit_address, ',')) != NULL) {
71010652SHyon.Kim@Sun.COM *charptr = '\0';
71110652SHyon.Kim@Sun.COM }
71210652SHyon.Kim@Sun.COM for (charptr = unit_address; *charptr != '\0'; charptr++) {
71310652SHyon.Kim@Sun.COM if (isxdigit(*charptr)) {
71410652SHyon.Kim@Sun.COM break;
71510652SHyon.Kim@Sun.COM }
71610652SHyon.Kim@Sun.COM }
71710652SHyon.Kim@Sun.COM if (charptr != '\0') {
71810652SHyon.Kim@Sun.COM tmpAddr = htonll(strtoll(charptr, NULL, 16));
71910652SHyon.Kim@Sun.COM (void) memcpy(&SASAddress.wwn[0], &tmpAddr, 8);
72010652SHyon.Kim@Sun.COM } else {
72110652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
72210652SHyon.Kim@Sun.COM "No proper target port info on unit address of "
72310652SHyon.Kim@Sun.COM "path (%s).", pathdevpath ? pathdevpath :
72410652SHyon.Kim@Sun.COM "(missing device path)");
72510652SHyon.Kim@Sun.COM if (pathdevpath) di_devfs_path_free(pathdevpath);
72610652SHyon.Kim@Sun.COM di_devfs_path_free(clientdevpath);
72710652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
72810652SHyon.Kim@Sun.COM }
72910652SHyon.Kim@Sun.COM } else {
73010652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE, "Fail to get unit address of path(%s).",
73110652SHyon.Kim@Sun.COM "path (%s).", pathdevpath ? pathdevpath :
73210652SHyon.Kim@Sun.COM "(missing device path)");
73310652SHyon.Kim@Sun.COM if (pathdevpath) di_devfs_path_free(pathdevpath);
73410652SHyon.Kim@Sun.COM di_devfs_path_free(clientdevpath);
73510652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
73610652SHyon.Kim@Sun.COM }
73710652SHyon.Kim@Sun.COM
73810652SHyon.Kim@Sun.COM (void) memset(&AttachedSASAddress, 0, sizeof (AttachedSASAddress));
73910652SHyon.Kim@Sun.COM if (di_path_prop_lookup_strings(path, "attached-port",
74010652SHyon.Kim@Sun.COM &propStringData) != -1) {
74110652SHyon.Kim@Sun.COM for (charptr = propStringData; *charptr != '\0'; charptr++) {
74210652SHyon.Kim@Sun.COM if (isxdigit(*charptr)) {
74310652SHyon.Kim@Sun.COM break;
74410652SHyon.Kim@Sun.COM }
74510652SHyon.Kim@Sun.COM }
74610652SHyon.Kim@Sun.COM if (*charptr != '\0') {
74710652SHyon.Kim@Sun.COM tmpAddr = htonll(strtoll(charptr, NULL, 16));
74810652SHyon.Kim@Sun.COM (void) memcpy(AttachedSASAddress.wwn, &tmpAddr, 8);
74910652SHyon.Kim@Sun.COM /* check the attached address of hba port. */
75010652SHyon.Kim@Sun.COM if (memcmp(port_ptr->port_attributes.
75110652SHyon.Kim@Sun.COM PortSpecificAttribute.SASPort->
75210652SHyon.Kim@Sun.COM LocalSASAddress.wwn, &tmpAddr, 8) == 0) {
75310652SHyon.Kim@Sun.COM if (wwnConversion(port_ptr->port_attributes.
75410652SHyon.Kim@Sun.COM PortSpecificAttribute.SASPort->
75510652SHyon.Kim@Sun.COM AttachedSASAddress.wwn)) {
75610652SHyon.Kim@Sun.COM /* verify the attaached SAS Addr. */
75710652SHyon.Kim@Sun.COM if (memcmp(port_ptr->port_attributes.
75810652SHyon.Kim@Sun.COM PortSpecificAttribute.SASPort->
75910652SHyon.Kim@Sun.COM AttachedSASAddress.wwn,
76010652SHyon.Kim@Sun.COM SASAddress.wwn, 8) != 0) {
76110652SHyon.Kim@Sun.COM /* indentation move begin. */
76210652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
76310652SHyon.Kim@Sun.COM "iport attached-port(%016llx) do not"
76410652SHyon.Kim@Sun.COM " match with level 1 Local"
76510652SHyon.Kim@Sun.COM " SAS address(%016llx).",
76610652SHyon.Kim@Sun.COM wwnConversion(port_ptr->port_attributes.
76710652SHyon.Kim@Sun.COM PortSpecificAttribute.
76810652SHyon.Kim@Sun.COM SASPort->AttachedSASAddress.wwn),
76910652SHyon.Kim@Sun.COM wwnConversion(SASAddress.wwn));
77010652SHyon.Kim@Sun.COM if (pathdevpath)
77110652SHyon.Kim@Sun.COM di_devfs_path_free(pathdevpath);
77210652SHyon.Kim@Sun.COM di_devfs_path_free(clientdevpath);
77310652SHyon.Kim@Sun.COM free_attached_port(port_ptr);
77410652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
77510652SHyon.Kim@Sun.COM /* indentation move ends. */
77610652SHyon.Kim@Sun.COM }
77710652SHyon.Kim@Sun.COM } else {
77810652SHyon.Kim@Sun.COM /* store the Attaached SAS Addr. */
77910652SHyon.Kim@Sun.COM (void) memcpy(port_ptr->port_attributes.
78010652SHyon.Kim@Sun.COM PortSpecificAttribute.
78110652SHyon.Kim@Sun.COM SASPort->AttachedSASAddress.wwn,
78210652SHyon.Kim@Sun.COM &SASAddress.wwn[0], 8);
78310652SHyon.Kim@Sun.COM }
78410652SHyon.Kim@Sun.COM }
78510652SHyon.Kim@Sun.COM } else {
78610652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
78710652SHyon.Kim@Sun.COM "No proper attached SAS address value of path (%s)",
78810652SHyon.Kim@Sun.COM pathdevpath ? pathdevpath :
78910652SHyon.Kim@Sun.COM "(missing device path)");
79010652SHyon.Kim@Sun.COM if (pathdevpath) di_devfs_path_free(pathdevpath);
79110652SHyon.Kim@Sun.COM di_devfs_path_free(clientdevpath);
79210652SHyon.Kim@Sun.COM free_attached_port(port_ptr);
79310652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
79410652SHyon.Kim@Sun.COM }
79510652SHyon.Kim@Sun.COM } else {
79610652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
79710652SHyon.Kim@Sun.COM "Property attached-port not found for path (%s)",
79810652SHyon.Kim@Sun.COM pathdevpath ? pathdevpath :
79910652SHyon.Kim@Sun.COM "(missing device path)");
80010652SHyon.Kim@Sun.COM if (pathdevpath) di_devfs_path_free(pathdevpath);
80110652SHyon.Kim@Sun.COM di_devfs_path_free(clientdevpath);
80210652SHyon.Kim@Sun.COM free_attached_port(port_ptr);
80310652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
80410652SHyon.Kim@Sun.COM }
80510652SHyon.Kim@Sun.COM
80610652SHyon.Kim@Sun.COM /*
80710652SHyon.Kim@Sun.COM * walk the disco list to make sure that there isn't a matching
80810652SHyon.Kim@Sun.COM * port and node wwn or a matching device path
80910652SHyon.Kim@Sun.COM */
81010652SHyon.Kim@Sun.COM portfound = 0;
81110652SHyon.Kim@Sun.COM for (disco_port_ptr = port_ptr->first_attached_port;
81210652SHyon.Kim@Sun.COM disco_port_ptr != NULL;
81310652SHyon.Kim@Sun.COM disco_port_ptr = disco_port_ptr->next) {
81410652SHyon.Kim@Sun.COM if ((disco_port_ptr->port_attributes.PortState !=
81510652SHyon.Kim@Sun.COM HBA_PORTSTATE_ERROR) &&
81610652SHyon.Kim@Sun.COM (memcmp(disco_port_ptr->port_attributes.
81710652SHyon.Kim@Sun.COM PortSpecificAttribute.SASPort->LocalSASAddress.wwn,
81810652SHyon.Kim@Sun.COM SASAddress.wwn, 8) == 0)) {
81910652SHyon.Kim@Sun.COM /*
82010652SHyon.Kim@Sun.COM * found matching disco_port
82110652SHyon.Kim@Sun.COM * look for matching device path
82210652SHyon.Kim@Sun.COM */
82310652SHyon.Kim@Sun.COM portfound = 1;
82410652SHyon.Kim@Sun.COM for (mapping_ptr = disco_port_ptr->scsiInfo;
82510652SHyon.Kim@Sun.COM mapping_ptr != NULL;
82610652SHyon.Kim@Sun.COM mapping_ptr = mapping_ptr->next) {
82710652SHyon.Kim@Sun.COM if (strstr(mapping_ptr-> entry.ScsiId.
82810652SHyon.Kim@Sun.COM OSDeviceName, clientdevpath) != 0) {
82910652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
83010652SHyon.Kim@Sun.COM "Found an already discovered "
83110652SHyon.Kim@Sun.COM "device %s.", clientdevpath);
83210652SHyon.Kim@Sun.COM if (pathdevpath)
83310652SHyon.Kim@Sun.COM di_devfs_path_free(pathdevpath);
83410652SHyon.Kim@Sun.COM di_devfs_path_free(clientdevpath);
83510652SHyon.Kim@Sun.COM return (HBA_STATUS_OK);
83610652SHyon.Kim@Sun.COM }
83710652SHyon.Kim@Sun.COM }
83810652SHyon.Kim@Sun.COM if (portfound == 1) {
83910652SHyon.Kim@Sun.COM break;
84010652SHyon.Kim@Sun.COM }
84110652SHyon.Kim@Sun.COM }
84210652SHyon.Kim@Sun.COM }
84310652SHyon.Kim@Sun.COM
84410652SHyon.Kim@Sun.COM if (portfound == 0) {
84510652SHyon.Kim@Sun.COM /*
84610652SHyon.Kim@Sun.COM * there are no matching SAS address.
84710652SHyon.Kim@Sun.COM * this must be a new device
84810652SHyon.Kim@Sun.COM */
84910652SHyon.Kim@Sun.COM if ((disco_port_ptr = (struct sun_sas_port *)calloc(1,
85010652SHyon.Kim@Sun.COM sizeof (struct sun_sas_port))) == NULL) {
85110652SHyon.Kim@Sun.COM OUT_OF_MEMORY(ROUTINE);
85210652SHyon.Kim@Sun.COM if (pathdevpath) di_devfs_path_free(pathdevpath);
85310652SHyon.Kim@Sun.COM di_devfs_path_free(clientdevpath);
85410652SHyon.Kim@Sun.COM free_attached_port(port_ptr);
85510652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
85610652SHyon.Kim@Sun.COM }
85710652SHyon.Kim@Sun.COM
85810652SHyon.Kim@Sun.COM if ((disco_port_ptr->port_attributes.PortSpecificAttribute.\
85910652SHyon.Kim@Sun.COM SASPort = (struct SMHBA_SAS_Port *)calloc(1,
86010652SHyon.Kim@Sun.COM sizeof (struct SMHBA_SAS_Port))) == NULL) {
86110652SHyon.Kim@Sun.COM OUT_OF_MEMORY("add_hba_port_info");
86210652SHyon.Kim@Sun.COM if (pathdevpath) di_devfs_path_free(pathdevpath);
86310652SHyon.Kim@Sun.COM di_devfs_path_free(clientdevpath);
86410652SHyon.Kim@Sun.COM free_attached_port(port_ptr);
86510652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
86610652SHyon.Kim@Sun.COM }
86710652SHyon.Kim@Sun.COM
86810652SHyon.Kim@Sun.COM (void) memcpy(disco_port_ptr->port_attributes.
86910652SHyon.Kim@Sun.COM PortSpecificAttribute.
87010652SHyon.Kim@Sun.COM SASPort->LocalSASAddress.wwn, SASAddress.wwn, 8);
87110652SHyon.Kim@Sun.COM (void) memcpy(disco_port_ptr->port_attributes.
87210652SHyon.Kim@Sun.COM PortSpecificAttribute.
87310652SHyon.Kim@Sun.COM SASPort->AttachedSASAddress.wwn, AttachedSASAddress.wwn, 8);
87410652SHyon.Kim@Sun.COM
87510652SHyon.Kim@Sun.COM /* Default to unknown until we figure out otherwise */
87610652SHyon.Kim@Sun.COM if (di_path_prop_lookup_strings(path, "variant",
87710652SHyon.Kim@Sun.COM &propStringData) != -1) {
87810652SHyon.Kim@Sun.COM if ((strcmp(propStringData, "sata") == 0) ||
87910652SHyon.Kim@Sun.COM (strcmp(propStringData, "atapi") == 0)) {
88010652SHyon.Kim@Sun.COM disco_port_ptr->port_attributes.PortType =
88110652SHyon.Kim@Sun.COM HBA_PORTTYPE_SATADEVICE;
88210652SHyon.Kim@Sun.COM disco_port_ptr->port_attributes.\
88310652SHyon.Kim@Sun.COM PortSpecificAttribute.SASPort->PortProtocol
88410652SHyon.Kim@Sun.COM = HBA_SASPORTPROTOCOL_SATA;
88510652SHyon.Kim@Sun.COM } else {
88610652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
88710652SHyon.Kim@Sun.COM "Unexpected variant prop value %s found on",
88810652SHyon.Kim@Sun.COM " path (%s)", propStringData,
88910652SHyon.Kim@Sun.COM pathdevpath ? pathdevpath :
89010652SHyon.Kim@Sun.COM "(missing device path)");
89110652SHyon.Kim@Sun.COM /*
89210652SHyon.Kim@Sun.COM * Port type will be 0
89310652SHyon.Kim@Sun.COM * which is not valid type.
89410652SHyon.Kim@Sun.COM */
89510652SHyon.Kim@Sun.COM }
89610652SHyon.Kim@Sun.COM } else {
89710652SHyon.Kim@Sun.COM disco_port_ptr->port_attributes.PortType =
89810652SHyon.Kim@Sun.COM HBA_PORTTYPE_SASDEVICE;
89910652SHyon.Kim@Sun.COM disco_port_ptr->port_attributes.PortSpecificAttribute.\
90010652SHyon.Kim@Sun.COM SASPort->PortProtocol = HBA_SASPORTPROTOCOL_SSP;
90110652SHyon.Kim@Sun.COM }
90210652SHyon.Kim@Sun.COM
90310652SHyon.Kim@Sun.COM if (disco_port_ptr->port_attributes.OSDeviceName[0] == '\0') {
90410652SHyon.Kim@Sun.COM /* indentation change due to ctysle check on sizeof. */
90510652SHyon.Kim@Sun.COM size = sizeof (disco_port_ptr->port_attributes.OSDeviceName);
90610652SHyon.Kim@Sun.COM if (pathdevpath != NULL) {
90710652SHyon.Kim@Sun.COM (void) strlcpy(disco_port_ptr->port_attributes.
90810652SHyon.Kim@Sun.COM OSDeviceName, pathdevpath, size);
90910652SHyon.Kim@Sun.COM }
91010652SHyon.Kim@Sun.COM }
91110652SHyon.Kim@Sun.COM
91210652SHyon.Kim@Sun.COM /* add new discovered port into the list */
91310652SHyon.Kim@Sun.COM if (port_ptr->first_attached_port == NULL) {
91410652SHyon.Kim@Sun.COM port_ptr->first_attached_port = disco_port_ptr;
91510652SHyon.Kim@Sun.COM disco_port_ptr->index = 0;
91610652SHyon.Kim@Sun.COM port_ptr->port_attributes.PortSpecificAttribute.\
91710652SHyon.Kim@Sun.COM SASPort->NumberofDiscoveredPorts = 1;
91810652SHyon.Kim@Sun.COM } else {
91910652SHyon.Kim@Sun.COM disco_port_ptr->next = port_ptr->first_attached_port;
92010652SHyon.Kim@Sun.COM port_ptr->first_attached_port = disco_port_ptr;
92110652SHyon.Kim@Sun.COM disco_port_ptr->index = port_ptr->port_attributes.\
92210652SHyon.Kim@Sun.COM PortSpecificAttribute.\
92310652SHyon.Kim@Sun.COM SASPort->NumberofDiscoveredPorts;
92410652SHyon.Kim@Sun.COM port_ptr->port_attributes.PortSpecificAttribute.\
92510652SHyon.Kim@Sun.COM SASPort->NumberofDiscoveredPorts++;
92610652SHyon.Kim@Sun.COM }
92710652SHyon.Kim@Sun.COM disco_port_ptr->port_attributes.PortState = port_state;
92810652SHyon.Kim@Sun.COM }
92910652SHyon.Kim@Sun.COM
93010652SHyon.Kim@Sun.COM if ((mapping_ptr = (struct ScsiEntryList *)calloc
93110652SHyon.Kim@Sun.COM (1, sizeof (struct ScsiEntryList))) == NULL) {
93210652SHyon.Kim@Sun.COM OUT_OF_MEMORY(ROUTINE);
93310652SHyon.Kim@Sun.COM if (pathdevpath) di_devfs_path_free(pathdevpath);
93410652SHyon.Kim@Sun.COM di_devfs_path_free(clientdevpath);
93510652SHyon.Kim@Sun.COM free_attached_port(port_ptr);
93610652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
93710652SHyon.Kim@Sun.COM }
93810652SHyon.Kim@Sun.COM
93910652SHyon.Kim@Sun.COM if (di_path_prop_lookup_ints(path, "lun", &propIntData) != -1) {
94010652SHyon.Kim@Sun.COM mapping_ptr->entry.ScsiId.ScsiOSLun = *propIntData;
94110652SHyon.Kim@Sun.COM } else {
94210652SHyon.Kim@Sun.COM if ((charptr = strchr(unit_address, ',')) != NULL) {
94310652SHyon.Kim@Sun.COM charptr++;
94410652SHyon.Kim@Sun.COM mapping_ptr->entry.ScsiId.ScsiOSLun =
94510652SHyon.Kim@Sun.COM strtoull(charptr, NULL, 10);
94610652SHyon.Kim@Sun.COM } else {
94710652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
94810652SHyon.Kim@Sun.COM "Failed to get LUN from unit address of path(%s).",
94910652SHyon.Kim@Sun.COM pathdevpath ? pathdevpath :
95010652SHyon.Kim@Sun.COM "(missing device path)");
95110652SHyon.Kim@Sun.COM if (pathdevpath) di_devfs_path_free(pathdevpath);
95210652SHyon.Kim@Sun.COM di_devfs_path_free(clientdevpath);
95310652SHyon.Kim@Sun.COM free_attached_port(port_ptr);
95410652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
95510652SHyon.Kim@Sun.COM }
95610652SHyon.Kim@Sun.COM }
95710652SHyon.Kim@Sun.COM
95810652SHyon.Kim@Sun.COM /* Get TargetLun(SAM LUN). */
95910652SHyon.Kim@Sun.COM if (di_path_prop_lookup_int64s(path, "lun64", &propInt64Data) != -1) {
96010652SHyon.Kim@Sun.COM samLun = scsi_lun64_to_lun(*propInt64Data);
96110652SHyon.Kim@Sun.COM (void) memcpy(&mapping_ptr->entry.PortLun.TargetLun,
96210652SHyon.Kim@Sun.COM &samLun, 8);
96310652SHyon.Kim@Sun.COM } else {
96410652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE, "No lun64 prop found on path (%s)",
96510652SHyon.Kim@Sun.COM pathdevpath ? pathdevpath :
96610652SHyon.Kim@Sun.COM "(missing device path)");
96710652SHyon.Kim@Sun.COM if (pathdevpath) di_devfs_path_free(pathdevpath);
96810652SHyon.Kim@Sun.COM di_devfs_path_free(clientdevpath);
96910652SHyon.Kim@Sun.COM free_attached_port(port_ptr);
97010652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
97110652SHyon.Kim@Sun.COM }
97210652SHyon.Kim@Sun.COM
97310652SHyon.Kim@Sun.COM if (di_path_prop_lookup_ints(path, "target", &propIntData) != -1) {
97410652SHyon.Kim@Sun.COM mapping_ptr->entry.ScsiId.ScsiTargetNumber = *propIntData;
97510652SHyon.Kim@Sun.COM } else {
97610652SHyon.Kim@Sun.COM mapping_ptr->entry.ScsiId.ScsiTargetNumber =
97710652SHyon.Kim@Sun.COM di_path_instance(path);
97810652SHyon.Kim@Sun.COM }
97910652SHyon.Kim@Sun.COM
98010652SHyon.Kim@Sun.COM /* get ScsiBusNumber */
98110652SHyon.Kim@Sun.COM mapping_ptr->entry.ScsiId.ScsiBusNumber = port_ptr->cntlNumber;
98210652SHyon.Kim@Sun.COM
98310652SHyon.Kim@Sun.COM (void) memcpy(mapping_ptr->entry.PortLun.PortWWN.wwn,
98410652SHyon.Kim@Sun.COM SASAddress.wwn, 8);
98510652SHyon.Kim@Sun.COM
98610652SHyon.Kim@Sun.COM /* Store the devices path for now. We'll convert to /dev later */
98710652SHyon.Kim@Sun.COM get_minor(clientdevpath, minorname);
98810652SHyon.Kim@Sun.COM (void) snprintf(mapping_ptr->entry.ScsiId.OSDeviceName,
98910652SHyon.Kim@Sun.COM sizeof (mapping_ptr->entry.ScsiId.OSDeviceName),
99010652SHyon.Kim@Sun.COM "%s%s%s", DEVICES_DIR, clientdevpath, minorname);
99110652SHyon.Kim@Sun.COM
99210652SHyon.Kim@Sun.COM /* get luid. */
993*11243SHyon.Kim@Sun.COM errno = 0; /* reset errno to 0 */
994*11243SHyon.Kim@Sun.COM if (di_prop_lookup_strings(DDI_DEV_T_ANY, clientnode, "devid",
995*11243SHyon.Kim@Sun.COM &propStringData) != -1) {
996*11243SHyon.Kim@Sun.COM if (devid_str_decode(propStringData, &devid, NULL) != -1) {
997*11243SHyon.Kim@Sun.COM guidStr = devid_to_guid(devid);
998*11243SHyon.Kim@Sun.COM if (guidStr != NULL) {
999*11243SHyon.Kim@Sun.COM (void) strlcpy(mapping_ptr->entry.LUID.buffer,
1000*11243SHyon.Kim@Sun.COM guidStr,
1001*11243SHyon.Kim@Sun.COM sizeof (mapping_ptr->entry.LUID.buffer));
1002*11243SHyon.Kim@Sun.COM devid_free_guid(guidStr);
1003*11243SHyon.Kim@Sun.COM } else {
1004*11243SHyon.Kim@Sun.COM /*
1005*11243SHyon.Kim@Sun.COM * Note:
1006*11243SHyon.Kim@Sun.COM * if logical unit associated page 83 id
1007*11243SHyon.Kim@Sun.COM * descriptor is not avaialble for the device
1008*11243SHyon.Kim@Sun.COM * devid_to_guid returns NULl with errno 0.
1009*11243SHyon.Kim@Sun.COM */
1010*11243SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
1011*11243SHyon.Kim@Sun.COM "failed to get devid guid on (%s)",
1012*11243SHyon.Kim@Sun.COM " associated with path(%s) : %s",
1013*11243SHyon.Kim@Sun.COM clientdevpath,
1014*11243SHyon.Kim@Sun.COM pathdevpath ? pathdevpath :
1015*11243SHyon.Kim@Sun.COM "(missing device path)",
1016*11243SHyon.Kim@Sun.COM strerror(errno));
1017*11243SHyon.Kim@Sun.COM }
1018*11243SHyon.Kim@Sun.COM } else {
1019*11243SHyon.Kim@Sun.COM /*
1020*11243SHyon.Kim@Sun.COM * device may not support proper page 83 id descriptor.
1021*11243SHyon.Kim@Sun.COM * leave LUID attribute to NULL and continue.
1022*11243SHyon.Kim@Sun.COM */
1023*11243SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
1024*11243SHyon.Kim@Sun.COM "failed to decode devid prop on (%s)",
1025*11243SHyon.Kim@Sun.COM " associated with path(%s) : %s",
1026*11243SHyon.Kim@Sun.COM clientdevpath,
1027*11243SHyon.Kim@Sun.COM pathdevpath ? pathdevpath :
1028*11243SHyon.Kim@Sun.COM "(missing device path)",
1029*11243SHyon.Kim@Sun.COM strerror(errno));
1030*11243SHyon.Kim@Sun.COM }
103110652SHyon.Kim@Sun.COM } else {
1032*11243SHyon.Kim@Sun.COM /* leave LUID attribute to NULL and continue. */
1033*11243SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE, "Failed to get devid on %s"
1034*11243SHyon.Kim@Sun.COM " associated with path(%s) : %s", clientdevpath,
1035*11243SHyon.Kim@Sun.COM pathdevpath ? pathdevpath : "(missing device path)",
1036*11243SHyon.Kim@Sun.COM strerror(errno));
103710652SHyon.Kim@Sun.COM }
103810652SHyon.Kim@Sun.COM
103910652SHyon.Kim@Sun.COM if (disco_port_ptr->scsiInfo == NULL) {
104010652SHyon.Kim@Sun.COM disco_port_ptr->scsiInfo = mapping_ptr;
104110652SHyon.Kim@Sun.COM } else {
104210652SHyon.Kim@Sun.COM mapping_ptr->next = disco_port_ptr->scsiInfo;
104310652SHyon.Kim@Sun.COM disco_port_ptr->scsiInfo = mapping_ptr;
104410652SHyon.Kim@Sun.COM }
104510652SHyon.Kim@Sun.COM
104610652SHyon.Kim@Sun.COM if (pathdevpath) di_devfs_path_free(pathdevpath);
104710652SHyon.Kim@Sun.COM di_devfs_path_free(clientdevpath);
104810652SHyon.Kim@Sun.COM
104910652SHyon.Kim@Sun.COM return (HBA_STATUS_OK);
105010652SHyon.Kim@Sun.COM }
105110652SHyon.Kim@Sun.COM
105210652SHyon.Kim@Sun.COM /*
105310652SHyon.Kim@Sun.COM * walks the devinfo tree retrieving all hba information
105410652SHyon.Kim@Sun.COM */
105510652SHyon.Kim@Sun.COM extern HBA_STATUS
devtree_attached_devices(di_node_t node,struct sun_sas_port * port_ptr)105610652SHyon.Kim@Sun.COM devtree_attached_devices(di_node_t node, struct sun_sas_port *port_ptr)
105710652SHyon.Kim@Sun.COM {
105810652SHyon.Kim@Sun.COM const char ROUTINE[] = "devtree_attached_devices";
105910652SHyon.Kim@Sun.COM di_node_t nodechild = DI_NODE_NIL;
106010652SHyon.Kim@Sun.COM di_path_t path = DI_PATH_NIL;
106110652SHyon.Kim@Sun.COM
106210652SHyon.Kim@Sun.COM /* child should be device */
106310652SHyon.Kim@Sun.COM if ((nodechild = di_child_node(node)) == DI_NODE_NIL) {
106410652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
106510652SHyon.Kim@Sun.COM "No devinfo child on the HBA port node.");
106610652SHyon.Kim@Sun.COM }
106710652SHyon.Kim@Sun.COM
106810652SHyon.Kim@Sun.COM if ((path = di_path_phci_next_path(node, path)) ==
106910652SHyon.Kim@Sun.COM DI_PATH_NIL) {
107010652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
107110652SHyon.Kim@Sun.COM "No pathinfo node on the HBA port node.");
107210652SHyon.Kim@Sun.COM }
107310652SHyon.Kim@Sun.COM
107410652SHyon.Kim@Sun.COM if ((nodechild == DI_NODE_NIL) && (path == DI_PATH_NIL)) {
107510652SHyon.Kim@Sun.COM return (HBA_STATUS_OK);
107610652SHyon.Kim@Sun.COM }
107710652SHyon.Kim@Sun.COM
107810652SHyon.Kim@Sun.COM while (nodechild != DI_NODE_NIL) {
107910652SHyon.Kim@Sun.COM if (get_attached_devices_info(nodechild, port_ptr)
108010652SHyon.Kim@Sun.COM != HBA_STATUS_OK) {
108110652SHyon.Kim@Sun.COM break;
108210652SHyon.Kim@Sun.COM }
108310652SHyon.Kim@Sun.COM nodechild = di_sibling_node(nodechild);
108410652SHyon.Kim@Sun.COM }
108510652SHyon.Kim@Sun.COM
108610652SHyon.Kim@Sun.COM
108710652SHyon.Kim@Sun.COM while (path != DI_PATH_NIL) {
108810652SHyon.Kim@Sun.COM if (get_attached_paths_info(path, port_ptr)
108910652SHyon.Kim@Sun.COM != HBA_STATUS_OK) {
109010652SHyon.Kim@Sun.COM break;
109110652SHyon.Kim@Sun.COM }
109210652SHyon.Kim@Sun.COM path = di_path_phci_next_path(node, path);
109310652SHyon.Kim@Sun.COM }
109410652SHyon.Kim@Sun.COM
109510652SHyon.Kim@Sun.COM return (HBA_STATUS_OK);
109610652SHyon.Kim@Sun.COM }
1097