1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 /*
27  * Copyright 2019 Joyent, Inc.
28  */
29 
30 #include    <sun_sas.h>
31 
32 /*
33  * Retrieves the attributes for a specified port discovered in the network
34  */
35 HBA_STATUS
Sun_sasGetDiscoveredPortAttributes(HBA_HANDLE handle,HBA_UINT32 port,HBA_UINT32 discoveredport,SMHBA_PORTATTRIBUTES * attributes)36 Sun_sasGetDiscoveredPortAttributes(HBA_HANDLE handle,
37     HBA_UINT32 port, HBA_UINT32 discoveredport,
38     SMHBA_PORTATTRIBUTES *attributes)
39 {
40 	const char		ROUTINE[] =
41 	    "Sun_sasGetDiscoveredPortAttributes";
42 	HBA_STATUS		status;
43 	HBA_STATUS		ret = HBA_STATUS_OK;
44 	struct sun_sas_hba	*hba_ptr;
45 	struct sun_sas_port	*hba_port_ptr, *hba_disco_port;
46 	int			index;
47 
48 	if (attributes == NULL) {
49 		log(LOG_DEBUG, ROUTINE,
50 		    "NULL attributes argument. Handle %08lx, port %d, "
51 		    "discovered port %d", handle, port, discoveredport);
52 		return (HBA_STATUS_ERROR_ARG);
53 	}
54 
55 	lock(&all_hbas_lock);
56 	index = RetrieveIndex(handle);
57 	lock(&open_handles_lock);
58 	hba_ptr = RetrieveHandle(index);
59 	if (hba_ptr == NULL) {
60 		log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx.", handle);
61 		unlock(&open_handles_lock);
62 		unlock(&all_hbas_lock);
63 		return (HBA_STATUS_ERROR_INVALID_HANDLE);
64 	}
65 
66 	/* Check for stale data */
67 	status = verifyAdapter(hba_ptr);
68 	if (status != HBA_STATUS_OK) {
69 		log(LOG_DEBUG, ROUTINE, "Verify Adapter failed");
70 		unlock(&open_handles_lock);
71 		unlock(&all_hbas_lock);
72 		return (status);
73 	}
74 
75 
76 	if (hba_ptr->first_port == NULL) {
77 		/* This is probably an internal failure of the library */
78 		if (hba_ptr->device_path[0] != '\0') {
79 			log(LOG_DEBUG, ROUTINE, "Internal failure:  Adapter %s"
80 			    " contains no port data", hba_ptr->device_path);
81 		} else {
82 			log(LOG_DEBUG, ROUTINE, "Internal failure:  Adapter at"
83 			    " index %d contains no port data", hba_ptr->index);
84 		}
85 		unlock(&open_handles_lock);
86 		unlock(&all_hbas_lock);
87 		return (HBA_STATUS_ERROR);
88 	}
89 
90 	for (hba_port_ptr = hba_ptr->first_port;
91 	    hba_port_ptr != NULL; hba_port_ptr = hba_port_ptr->next) {
92 		if (hba_port_ptr->index == port) {
93 			break;
94 		}
95 	}
96 
97 	if (hba_port_ptr == NULL) {
98 		log(LOG_DEBUG, ROUTINE,
99 		    "Invalid port index %d for handle %08lx",
100 		    port, handle);
101 		unlock(&open_handles_lock);
102 		unlock(&all_hbas_lock);
103 		return (HBA_STATUS_ERROR_ILLEGAL_INDEX);
104 	}
105 
106 	/* check to make sure there are devices attached to this port */
107 	if (hba_port_ptr->first_attached_port != NULL) {
108 		for (hba_disco_port = hba_port_ptr->first_attached_port;
109 		    hba_disco_port != NULL;
110 		    hba_disco_port = hba_disco_port->next) {
111 			if (hba_disco_port->index == discoveredport) {
112 				break;
113 			}
114 		}
115 		if (hba_disco_port == NULL) {
116 			log(LOG_DEBUG, ROUTINE,
117 			    "Invalid discovered port index %d for hba port "
118 			    "index %d on handle %08lx.",
119 			    discoveredport, port, handle);
120 			ret = HBA_STATUS_ERROR_ILLEGAL_INDEX;
121 		} else {
122 			attributes->PortType =
123 			    hba_disco_port->port_attributes.PortType;
124 			attributes->PortState =
125 			    hba_disco_port->port_attributes.PortState;
126 			(void) strlcpy(attributes->OSDeviceName,
127 			    hba_disco_port->port_attributes.OSDeviceName,
128 			    sizeof (attributes->OSDeviceName));
129 			(void) memcpy(attributes->PortSpecificAttribute.SASPort,
130 			    hba_disco_port->port_attributes.\
131 			    PortSpecificAttribute.SASPort,
132 			    sizeof (struct SMHBA_SAS_Port));
133 		}
134 	} else {
135 		/* No ports, so we can't possibly return anything */
136 		log(LOG_DEBUG, ROUTINE,
137 		    "No discovered port on HBA port index %d for handle %08lx",
138 		    port, handle);
139 		ret = HBA_STATUS_ERROR;
140 	}
141 	unlock(&open_handles_lock);
142 	unlock(&all_hbas_lock);
143 
144 	return (ret);
145 }
146