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 #include <sun_sas.h>
28
29 /*
30 * Retrieves the attributes for a specific discovered port by WWN
31 */
32 HBA_STATUS
Sun_sasGetPortAttributesByWWN(HBA_HANDLE handle,HBA_WWN portWWN,HBA_WWN domainPortWWN,PSMHBA_PORTATTRIBUTES attributes)33 Sun_sasGetPortAttributesByWWN(HBA_HANDLE handle, HBA_WWN portWWN,
34 HBA_WWN domainPortWWN, PSMHBA_PORTATTRIBUTES attributes)
35 {
36 const char ROUTINE[] = "Sun_sasGetPortAttributesByWWN";
37 HBA_STATUS status;
38 struct sun_sas_hba *hba_ptr;
39 struct sun_sas_port *hba_port_ptr, *hba_disco_port;
40 int index, chkDomainPort = 0, domainFound = 0;
41
42 /* Validate the arguments */
43 if (attributes == NULL) {
44 log(LOG_DEBUG, ROUTINE, "NULL port attributes");
45 return (HBA_STATUS_ERROR_ARG);
46 }
47
48 if (wwnConversion(domainPortWWN.wwn) != 0) {
49 chkDomainPort = 1;
50 }
51
52 lock(&all_hbas_lock);
53 index = RetrieveIndex(handle);
54 lock(&open_handles_lock);
55 hba_ptr = RetrieveHandle(index);
56 if (hba_ptr == NULL) {
57 log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx.", handle);
58 unlock(&open_handles_lock);
59 unlock(&all_hbas_lock);
60 return (HBA_STATUS_ERROR_INVALID_HANDLE);
61 }
62
63 /* Check for stale data */
64 status = verifyAdapter(hba_ptr);
65 if (status != HBA_STATUS_OK) {
66 log(LOG_DEBUG, ROUTINE, "Verify adapter failed");
67 unlock(&open_handles_lock);
68 unlock(&all_hbas_lock);
69 return (status);
70 }
71
72 if (hba_ptr->first_port == NULL) {
73 /* This is probably an internal failure of the library */
74 if (hba_ptr->device_path) {
75 log(LOG_DEBUG, ROUTINE,
76 "Internal failure: Adapter %s contains "
77 "no port data", hba_ptr->device_path);
78 } else {
79 log(LOG_DEBUG, ROUTINE,
80 "Internal failure: Adapter at index %d contains "
81 "no port data", hba_ptr->index);
82 }
83 unlock(&open_handles_lock);
84 unlock(&all_hbas_lock);
85 return (HBA_STATUS_ERROR);
86 }
87
88 /* Loop over all Adapter ports */
89 for (hba_port_ptr = hba_ptr->first_port;
90 hba_port_ptr != NULL;
91 hba_port_ptr = hba_port_ptr->next) {
92 if (chkDomainPort) {
93 if (validateDomainAddress(hba_port_ptr,
94 domainPortWWN) != HBA_STATUS_OK) {
95 continue;
96 } else
97 domainFound = 1;
98 }
99
100 if (wwnConversion(hba_port_ptr->port_attributes.
101 PortSpecificAttribute.SASPort->LocalSASAddress.wwn) ==
102 wwnConversion(portWWN.wwn)) {
103 /*
104 * We should indicate an error if we enter here
105 * without domainPortWWN set.
106 */
107 if (chkDomainPort == 0) {
108 log(LOG_DEBUG, ROUTINE,
109 "Domain Port WWN should be set when "
110 "querying HBA port %016llx for "
111 "handle %08lx",
112 wwnConversion(portWWN.wwn), handle);
113 unlock(&open_handles_lock);
114 unlock(&all_hbas_lock);
115 return (HBA_STATUS_ERROR_ARG);
116 }
117 attributes->PortType =
118 hba_port_ptr->port_attributes.PortType;
119 attributes->PortState =
120 hba_port_ptr->port_attributes.PortState;
121 (void) strlcpy(attributes->OSDeviceName,
122 hba_port_ptr->port_attributes.OSDeviceName,
123 sizeof (attributes->OSDeviceName));
124 (void) memcpy(attributes->PortSpecificAttribute.SASPort,
125 hba_port_ptr->port_attributes.PortSpecificAttribute.
126 SASPort, sizeof (struct SMHBA_SAS_Port));
127
128 unlock(&open_handles_lock);
129 unlock(&all_hbas_lock);
130 return (HBA_STATUS_OK);
131 }
132
133 /* check to make sure there are devices attached to this port */
134 if (hba_port_ptr->first_attached_port != NULL) {
135
136 /* Loop over all discovered ports */
137 for (hba_disco_port = hba_port_ptr->first_attached_port;
138 hba_disco_port != NULL;
139 hba_disco_port = hba_disco_port->next) {
140 if (wwnConversion(hba_disco_port->
141 port_attributes.PortSpecificAttribute.
142 SASPort->LocalSASAddress.wwn) ==
143 wwnConversion(portWWN.wwn)) {
144 attributes->PortType =
145 hba_disco_port->port_attributes.
146 PortType;
147 attributes->PortState =
148 hba_disco_port->port_attributes.
149 PortState;
150 (void) strlcpy(attributes->OSDeviceName,
151 hba_disco_port->port_attributes.
152 OSDeviceName,
153 sizeof (attributes->OSDeviceName));
154 (void) memcpy(attributes->
155 PortSpecificAttribute.SASPort,
156 hba_disco_port->port_attributes.
157 PortSpecificAttribute.SASPort,
158 sizeof (struct SMHBA_SAS_Port));
159 unlock(&open_handles_lock);
160 unlock(&all_hbas_lock);
161 return (HBA_STATUS_OK);
162 }
163 }
164 }
165 if (chkDomainPort) {
166 log(LOG_DEBUG, ROUTINE,
167 "Invalid Port WWN %016llx for handle %08lx",
168 wwnConversion(portWWN.wwn), handle);
169 unlock(&open_handles_lock);
170 unlock(&all_hbas_lock);
171 return (HBA_STATUS_ERROR_ILLEGAL_WWN);
172 }
173 }
174 if (chkDomainPort && domainFound == 0) {
175 log(LOG_DEBUG, ROUTINE, "No Matching domain port"
176 " (%16llx) for port (%16llx) for handle %08lx",
177 wwnConversion(domainPortWWN.wwn),
178 wwnConversion(portWWN.wwn),
179 handle);
180 } else {
181 /* We enter here only when chkDomainPort == 0 */
182 log(LOG_DEBUG, ROUTINE,
183 "Invalid Port WWN %016llx for handle %08lx",
184 wwnConversion(portWWN.wwn), handle);
185 }
186 unlock(&open_handles_lock);
187 unlock(&all_hbas_lock);
188 return (HBA_STATUS_ERROR_ILLEGAL_WWN);
189 }
190