1*10652SHyon.Kim@Sun.COM /*
2*10652SHyon.Kim@Sun.COM * CDDL HEADER START
3*10652SHyon.Kim@Sun.COM *
4*10652SHyon.Kim@Sun.COM * The contents of this file are subject to the terms of the
5*10652SHyon.Kim@Sun.COM * Common Development and Distribution License (the "License").
6*10652SHyon.Kim@Sun.COM * You may not use this file except in compliance with the License.
7*10652SHyon.Kim@Sun.COM *
8*10652SHyon.Kim@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*10652SHyon.Kim@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*10652SHyon.Kim@Sun.COM * See the License for the specific language governing permissions
11*10652SHyon.Kim@Sun.COM * and limitations under the License.
12*10652SHyon.Kim@Sun.COM *
13*10652SHyon.Kim@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*10652SHyon.Kim@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*10652SHyon.Kim@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*10652SHyon.Kim@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*10652SHyon.Kim@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*10652SHyon.Kim@Sun.COM *
19*10652SHyon.Kim@Sun.COM * CDDL HEADER END
20*10652SHyon.Kim@Sun.COM */
21*10652SHyon.Kim@Sun.COM
22*10652SHyon.Kim@Sun.COM /*
23*10652SHyon.Kim@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24*10652SHyon.Kim@Sun.COM * Use is subject to license terms.
25*10652SHyon.Kim@Sun.COM */
26*10652SHyon.Kim@Sun.COM
27*10652SHyon.Kim@Sun.COM
28*10652SHyon.Kim@Sun.COM #include <sys/byteorder.h>
29*10652SHyon.Kim@Sun.COM #include <sun_sas.h>
30*10652SHyon.Kim@Sun.COM
31*10652SHyon.Kim@Sun.COM /*
32*10652SHyon.Kim@Sun.COM * creates a handle each time Sun_sas_OpenAdapter() is called.
33*10652SHyon.Kim@Sun.COM *
34*10652SHyon.Kim@Sun.COM * a open_handle_struct was created to keep track of which handles are currently
35*10652SHyon.Kim@Sun.COM * open. This prevents a user from using an old handle that corresponds to
36*10652SHyon.Kim@Sun.COM * an hba that has already been closed.
37*10652SHyon.Kim@Sun.COM */
38*10652SHyon.Kim@Sun.COM HBA_HANDLE
CreateHandle(int adapterIndex)39*10652SHyon.Kim@Sun.COM CreateHandle(int adapterIndex)
40*10652SHyon.Kim@Sun.COM {
41*10652SHyon.Kim@Sun.COM const char ROUTINE[] = "CreateHandle";
42*10652SHyon.Kim@Sun.COM struct open_handle *new_open_handle;
43*10652SHyon.Kim@Sun.COM HBA_UINT32 new_handle_index;
44*10652SHyon.Kim@Sun.COM HBA_UINT8 max_handle_wrap = 0;
45*10652SHyon.Kim@Sun.COM
46*10652SHyon.Kim@Sun.COM if (global_hba_head == NULL) {
47*10652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
48*10652SHyon.Kim@Sun.COM "an error as occurred. global_hba_head is "
49*10652SHyon.Kim@Sun.COM "NULL. Library may not be loaded yet.");
50*10652SHyon.Kim@Sun.COM return (HANDLE_ERROR);
51*10652SHyon.Kim@Sun.COM }
52*10652SHyon.Kim@Sun.COM
53*10652SHyon.Kim@Sun.COM while (RetrieveIndex(open_handle_index) != -1) {
54*10652SHyon.Kim@Sun.COM open_handle_index = open_handle_index + 1;
55*10652SHyon.Kim@Sun.COM if (open_handle_index == 0) {
56*10652SHyon.Kim@Sun.COM /*
57*10652SHyon.Kim@Sun.COM * If open_handle_index wraps back to zero again,
58*10652SHyon.Kim@Sun.COM * that means all handles are currently in use.
59*10652SHyon.Kim@Sun.COM * Spec only allows for 16 bits of handles
60*10652SHyon.Kim@Sun.COM */
61*10652SHyon.Kim@Sun.COM if (max_handle_wrap == 1) {
62*10652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
63*10652SHyon.Kim@Sun.COM "Max number of handles reached.");
64*10652SHyon.Kim@Sun.COM return (HANDLE_ERROR);
65*10652SHyon.Kim@Sun.COM }
66*10652SHyon.Kim@Sun.COM open_handle_index = 1;
67*10652SHyon.Kim@Sun.COM max_handle_wrap = 1;
68*10652SHyon.Kim@Sun.COM }
69*10652SHyon.Kim@Sun.COM }
70*10652SHyon.Kim@Sun.COM
71*10652SHyon.Kim@Sun.COM new_handle_index = open_handle_index;
72*10652SHyon.Kim@Sun.COM if ((new_open_handle = (struct open_handle *)calloc(1,
73*10652SHyon.Kim@Sun.COM sizeof (struct open_handle))) == NULL) {
74*10652SHyon.Kim@Sun.COM OUT_OF_MEMORY(ROUTINE);
75*10652SHyon.Kim@Sun.COM return (HANDLE_ERROR);
76*10652SHyon.Kim@Sun.COM }
77*10652SHyon.Kim@Sun.COM (void) memset(new_open_handle, 0, sizeof (struct open_handle));
78*10652SHyon.Kim@Sun.COM new_open_handle->adapterIndex = adapterIndex;
79*10652SHyon.Kim@Sun.COM new_open_handle->handle = new_handle_index;
80*10652SHyon.Kim@Sun.COM
81*10652SHyon.Kim@Sun.COM lock(&open_handles_lock);
82*10652SHyon.Kim@Sun.COM
83*10652SHyon.Kim@Sun.COM /* add new open handle struct to the open_handles list */
84*10652SHyon.Kim@Sun.COM if (global_hba_head->open_handles == NULL) {
85*10652SHyon.Kim@Sun.COM global_hba_head->open_handles = new_open_handle;
86*10652SHyon.Kim@Sun.COM } else {
87*10652SHyon.Kim@Sun.COM new_open_handle->next = global_hba_head->open_handles;
88*10652SHyon.Kim@Sun.COM global_hba_head->open_handles = new_open_handle;
89*10652SHyon.Kim@Sun.COM }
90*10652SHyon.Kim@Sun.COM
91*10652SHyon.Kim@Sun.COM unlock(&open_handles_lock);
92*10652SHyon.Kim@Sun.COM open_handle_index = open_handle_index + 1;
93*10652SHyon.Kim@Sun.COM if (open_handle_index == 0) {
94*10652SHyon.Kim@Sun.COM open_handle_index = 1;
95*10652SHyon.Kim@Sun.COM }
96*10652SHyon.Kim@Sun.COM
97*10652SHyon.Kim@Sun.COM return (new_handle_index);
98*10652SHyon.Kim@Sun.COM }
99*10652SHyon.Kim@Sun.COM
100*10652SHyon.Kim@Sun.COM /*
101*10652SHyon.Kim@Sun.COM * given a handle, returns the adapterIndex number.
102*10652SHyon.Kim@Sun.COM *
103*10652SHyon.Kim@Sun.COM * This functions checkes to see if the given handle corresponds to an open
104*10652SHyon.Kim@Sun.COM * HBA. If it does, the adapterIndex is returned.
105*10652SHyon.Kim@Sun.COM */
106*10652SHyon.Kim@Sun.COM int
RetrieveIndex(HBA_HANDLE handle)107*10652SHyon.Kim@Sun.COM RetrieveIndex(HBA_HANDLE handle)
108*10652SHyon.Kim@Sun.COM {
109*10652SHyon.Kim@Sun.COM
110*10652SHyon.Kim@Sun.COM struct open_handle *open_handle_ptr;
111*10652SHyon.Kim@Sun.COM
112*10652SHyon.Kim@Sun.COM lock(&open_handles_lock);
113*10652SHyon.Kim@Sun.COM
114*10652SHyon.Kim@Sun.COM open_handle_ptr = RetrieveOpenHandle(handle);
115*10652SHyon.Kim@Sun.COM
116*10652SHyon.Kim@Sun.COM unlock(&open_handles_lock);
117*10652SHyon.Kim@Sun.COM if (open_handle_ptr == NULL) {
118*10652SHyon.Kim@Sun.COM return (-1);
119*10652SHyon.Kim@Sun.COM }
120*10652SHyon.Kim@Sun.COM
121*10652SHyon.Kim@Sun.COM return (open_handle_ptr->adapterIndex);
122*10652SHyon.Kim@Sun.COM }
123*10652SHyon.Kim@Sun.COM /*
124*10652SHyon.Kim@Sun.COM * Given a handle, returns the open_handle structure
125*10652SHyon.Kim@Sun.COM * The routine assumes that the open_handles_lock has already
126*10652SHyon.Kim@Sun.COM * been taken.
127*10652SHyon.Kim@Sun.COM */
128*10652SHyon.Kim@Sun.COM struct open_handle *
RetrieveOpenHandle(HBA_HANDLE handle)129*10652SHyon.Kim@Sun.COM RetrieveOpenHandle(HBA_HANDLE handle)
130*10652SHyon.Kim@Sun.COM {
131*10652SHyon.Kim@Sun.COM
132*10652SHyon.Kim@Sun.COM const char ROUTINE[] = "RetrieveOpenHandle";
133*10652SHyon.Kim@Sun.COM struct open_handle *open_handle_ptr = NULL;
134*10652SHyon.Kim@Sun.COM
135*10652SHyon.Kim@Sun.COM if (global_hba_head == NULL) {
136*10652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE, "No adpater is found.");
137*10652SHyon.Kim@Sun.COM return (NULL);
138*10652SHyon.Kim@Sun.COM }
139*10652SHyon.Kim@Sun.COM
140*10652SHyon.Kim@Sun.COM for (open_handle_ptr = global_hba_head->open_handles;
141*10652SHyon.Kim@Sun.COM open_handle_ptr != NULL;
142*10652SHyon.Kim@Sun.COM open_handle_ptr = open_handle_ptr->next) {
143*10652SHyon.Kim@Sun.COM if (open_handle_ptr->handle == handle) {
144*10652SHyon.Kim@Sun.COM break;
145*10652SHyon.Kim@Sun.COM }
146*10652SHyon.Kim@Sun.COM }
147*10652SHyon.Kim@Sun.COM
148*10652SHyon.Kim@Sun.COM return (open_handle_ptr);
149*10652SHyon.Kim@Sun.COM }
150*10652SHyon.Kim@Sun.COM
151*10652SHyon.Kim@Sun.COM /*
152*10652SHyon.Kim@Sun.COM * Given an adapterIndex, this functions returns a pointer to the handle
153*10652SHyon.Kim@Sun.COM * structure. This handle structure holds the hba's information
154*10652SHyon.Kim@Sun.COM * Caller must take all_hbas_lock first.
155*10652SHyon.Kim@Sun.COM */
156*10652SHyon.Kim@Sun.COM struct sun_sas_hba *
RetrieveHandle(int index)157*10652SHyon.Kim@Sun.COM RetrieveHandle(int index)
158*10652SHyon.Kim@Sun.COM {
159*10652SHyon.Kim@Sun.COM struct sun_sas_hba *hba_ptr = NULL;
160*10652SHyon.Kim@Sun.COM
161*10652SHyon.Kim@Sun.COM for (hba_ptr = global_hba_head; hba_ptr != NULL;
162*10652SHyon.Kim@Sun.COM hba_ptr = hba_ptr->next) {
163*10652SHyon.Kim@Sun.COM if (hba_ptr->index == index)
164*10652SHyon.Kim@Sun.COM break;
165*10652SHyon.Kim@Sun.COM }
166*10652SHyon.Kim@Sun.COM
167*10652SHyon.Kim@Sun.COM return (hba_ptr);
168*10652SHyon.Kim@Sun.COM }
169*10652SHyon.Kim@Sun.COM
170*10652SHyon.Kim@Sun.COM /*
171*10652SHyon.Kim@Sun.COM * Given an adapterIndex, this functions returns a pointer to the handle
172*10652SHyon.Kim@Sun.COM * structure and extracts it from the global list.
173*10652SHyon.Kim@Sun.COM *
174*10652SHyon.Kim@Sun.COM * all_hbas_lock must be taken already.
175*10652SHyon.Kim@Sun.COM */
176*10652SHyon.Kim@Sun.COM struct sun_sas_hba *
ExtractHandle(int index)177*10652SHyon.Kim@Sun.COM ExtractHandle(int index)
178*10652SHyon.Kim@Sun.COM {
179*10652SHyon.Kim@Sun.COM struct sun_sas_hba *last = NULL;
180*10652SHyon.Kim@Sun.COM struct sun_sas_hba *hba_ptr = NULL;
181*10652SHyon.Kim@Sun.COM
182*10652SHyon.Kim@Sun.COM for (hba_ptr = global_hba_head;
183*10652SHyon.Kim@Sun.COM hba_ptr != NULL;
184*10652SHyon.Kim@Sun.COM last = hba_ptr, hba_ptr = hba_ptr->next) {
185*10652SHyon.Kim@Sun.COM if (hba_ptr->index == index) {
186*10652SHyon.Kim@Sun.COM if (last) {
187*10652SHyon.Kim@Sun.COM last->next = hba_ptr->next;
188*10652SHyon.Kim@Sun.COM } else {
189*10652SHyon.Kim@Sun.COM /* Hmm, must be the head of the list. */
190*10652SHyon.Kim@Sun.COM global_hba_head = hba_ptr->next;
191*10652SHyon.Kim@Sun.COM }
192*10652SHyon.Kim@Sun.COM hba_ptr->next = NULL; /* Zap it to be safe */
193*10652SHyon.Kim@Sun.COM break;
194*10652SHyon.Kim@Sun.COM }
195*10652SHyon.Kim@Sun.COM }
196*10652SHyon.Kim@Sun.COM
197*10652SHyon.Kim@Sun.COM return (hba_ptr);
198*10652SHyon.Kim@Sun.COM }
199*10652SHyon.Kim@Sun.COM
200*10652SHyon.Kim@Sun.COM
201*10652SHyon.Kim@Sun.COM /*
202*10652SHyon.Kim@Sun.COM * Given an handle, this functions returns a pointer to the handle structure
203*10652SHyon.Kim@Sun.COM * for that hba
204*10652SHyon.Kim@Sun.COM *
205*10652SHyon.Kim@Sun.COM * Caller must take all_hbas_lock first.
206*10652SHyon.Kim@Sun.COM */
207*10652SHyon.Kim@Sun.COM struct sun_sas_hba *
Retrieve_Sun_sasHandle(HBA_HANDLE handle)208*10652SHyon.Kim@Sun.COM Retrieve_Sun_sasHandle(HBA_HANDLE handle)
209*10652SHyon.Kim@Sun.COM {
210*10652SHyon.Kim@Sun.COM const char ROUTINE[] = "Retrieve_Sun_sasHandle";
211*10652SHyon.Kim@Sun.COM struct sun_sas_hba *handle_struct = NULL;
212*10652SHyon.Kim@Sun.COM int index;
213*10652SHyon.Kim@Sun.COM
214*10652SHyon.Kim@Sun.COM /* Retrieve fp device path from handle */
215*10652SHyon.Kim@Sun.COM index = RetrieveIndex(handle);
216*10652SHyon.Kim@Sun.COM if (index == -1) {
217*10652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
218*10652SHyon.Kim@Sun.COM "handle could not be found.");
219*10652SHyon.Kim@Sun.COM return (handle_struct);
220*10652SHyon.Kim@Sun.COM }
221*10652SHyon.Kim@Sun.COM lock(&open_handles_lock);
222*10652SHyon.Kim@Sun.COM handle_struct = RetrieveHandle(index);
223*10652SHyon.Kim@Sun.COM if (handle_struct == NULL) {
224*10652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
225*10652SHyon.Kim@Sun.COM "could not find index in the handle list.");
226*10652SHyon.Kim@Sun.COM unlock(&open_handles_lock);
227*10652SHyon.Kim@Sun.COM return (handle_struct);
228*10652SHyon.Kim@Sun.COM }
229*10652SHyon.Kim@Sun.COM unlock(&open_handles_lock);
230*10652SHyon.Kim@Sun.COM
231*10652SHyon.Kim@Sun.COM return (handle_struct);
232*10652SHyon.Kim@Sun.COM }
233*10652SHyon.Kim@Sun.COM
234*10652SHyon.Kim@Sun.COM /*
235*10652SHyon.Kim@Sun.COM * Take a mutex lock. The routine will try, and if it fails,
236*10652SHyon.Kim@Sun.COM * it will loop for a while and retry. If it fails many times,
237*10652SHyon.Kim@Sun.COM * it will start writing to the log file.
238*10652SHyon.Kim@Sun.COM */
239*10652SHyon.Kim@Sun.COM void
lock(mutex_t * mp)240*10652SHyon.Kim@Sun.COM lock(mutex_t *mp)
241*10652SHyon.Kim@Sun.COM {
242*10652SHyon.Kim@Sun.COM int status;
243*10652SHyon.Kim@Sun.COM int loop = 0;
244*10652SHyon.Kim@Sun.COM const char ROUTINE[] = "lock";
245*10652SHyon.Kim@Sun.COM
246*10652SHyon.Kim@Sun.COM do {
247*10652SHyon.Kim@Sun.COM loop++;
248*10652SHyon.Kim@Sun.COM status = mutex_trylock(mp);
249*10652SHyon.Kim@Sun.COM switch (status) {
250*10652SHyon.Kim@Sun.COM case 0:
251*10652SHyon.Kim@Sun.COM break;
252*10652SHyon.Kim@Sun.COM case EFAULT:
253*10652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
254*10652SHyon.Kim@Sun.COM "Lock failed: fault 0x%x", mp);
255*10652SHyon.Kim@Sun.COM break;
256*10652SHyon.Kim@Sun.COM case EINVAL:
257*10652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
258*10652SHyon.Kim@Sun.COM "Lock failed: invalid 0x%x", mp);
259*10652SHyon.Kim@Sun.COM break;
260*10652SHyon.Kim@Sun.COM case EBUSY:
261*10652SHyon.Kim@Sun.COM if (loop > DEADLOCK_WARNING) {
262*10652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
263*10652SHyon.Kim@Sun.COM "Lock busy, possible deadlock:0x%x",
264*10652SHyon.Kim@Sun.COM mp);
265*10652SHyon.Kim@Sun.COM }
266*10652SHyon.Kim@Sun.COM break;
267*10652SHyon.Kim@Sun.COM case EOWNERDEAD:
268*10652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
269*10652SHyon.Kim@Sun.COM "Lock failed: owner dead 0x%x",
270*10652SHyon.Kim@Sun.COM mp);
271*10652SHyon.Kim@Sun.COM break;
272*10652SHyon.Kim@Sun.COM case ELOCKUNMAPPED:
273*10652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
274*10652SHyon.Kim@Sun.COM "Lock failed: unmapped 0x%x",
275*10652SHyon.Kim@Sun.COM mp);
276*10652SHyon.Kim@Sun.COM break;
277*10652SHyon.Kim@Sun.COM case ENOTRECOVERABLE:
278*10652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
279*10652SHyon.Kim@Sun.COM "Lock failed: not recoverable 0x%x", mp);
280*10652SHyon.Kim@Sun.COM default:
281*10652SHyon.Kim@Sun.COM if (loop > DEADLOCK_WARNING) {
282*10652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
283*10652SHyon.Kim@Sun.COM "Lock failed: %s 0x%x",
284*10652SHyon.Kim@Sun.COM strerror(status), mp);
285*10652SHyon.Kim@Sun.COM break;
286*10652SHyon.Kim@Sun.COM }
287*10652SHyon.Kim@Sun.COM }
288*10652SHyon.Kim@Sun.COM
289*10652SHyon.Kim@Sun.COM if (status) {
290*10652SHyon.Kim@Sun.COM (void) sleep(LOCK_SLEEP);
291*10652SHyon.Kim@Sun.COM }
292*10652SHyon.Kim@Sun.COM
293*10652SHyon.Kim@Sun.COM } while (status);
294*10652SHyon.Kim@Sun.COM }
295*10652SHyon.Kim@Sun.COM
296*10652SHyon.Kim@Sun.COM /*
297*10652SHyon.Kim@Sun.COM * Unlock a mutex lock.
298*10652SHyon.Kim@Sun.COM */
299*10652SHyon.Kim@Sun.COM void
unlock(mutex_t * mp)300*10652SHyon.Kim@Sun.COM unlock(mutex_t *mp)
301*10652SHyon.Kim@Sun.COM {
302*10652SHyon.Kim@Sun.COM (void) mutex_unlock(mp);
303*10652SHyon.Kim@Sun.COM }
304*10652SHyon.Kim@Sun.COM
305*10652SHyon.Kim@Sun.COM
306*10652SHyon.Kim@Sun.COM /*
307*10652SHyon.Kim@Sun.COM * Get the Port WWN of the first adapter port. This routine
308*10652SHyon.Kim@Sun.COM * is used by the old V1 interfaces so that they can call
309*10652SHyon.Kim@Sun.COM * the new V2 interfaces and exhibit the same behavior.
310*10652SHyon.Kim@Sun.COM * In the event of error the WWN will be zero.
311*10652SHyon.Kim@Sun.COM *
312*10652SHyon.Kim@Sun.COM * This function will transition to PAA state but it will not
313*10652SHyon.Kim@Sun.COM * verfiy whether data is stale or not
314*10652SHyon.Kim@Sun.COM */
315*10652SHyon.Kim@Sun.COM HBA_WWN
getFirstAdapterPortWWN(HBA_HANDLE handle)316*10652SHyon.Kim@Sun.COM getFirstAdapterPortWWN(HBA_HANDLE handle)
317*10652SHyon.Kim@Sun.COM {
318*10652SHyon.Kim@Sun.COM const char ROUTINE[] = "getFirstAdapterPortWWN";
319*10652SHyon.Kim@Sun.COM HBA_WWN pwwn = {0, 0, 0, 0, 0, 0, 0, 0};
320*10652SHyon.Kim@Sun.COM struct sun_sas_hba *hba_ptr = NULL;
321*10652SHyon.Kim@Sun.COM int index = 0;
322*10652SHyon.Kim@Sun.COM HBA_STATUS status;
323*10652SHyon.Kim@Sun.COM
324*10652SHyon.Kim@Sun.COM lock(&all_hbas_lock);
325*10652SHyon.Kim@Sun.COM index = RetrieveIndex(handle);
326*10652SHyon.Kim@Sun.COM lock(&open_handles_lock);
327*10652SHyon.Kim@Sun.COM hba_ptr = RetrieveHandle(index);
328*10652SHyon.Kim@Sun.COM if (hba_ptr == NULL) {
329*10652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx", handle);
330*10652SHyon.Kim@Sun.COM unlock(&open_handles_lock);
331*10652SHyon.Kim@Sun.COM unlock(&all_hbas_lock);
332*10652SHyon.Kim@Sun.COM return (pwwn); /* zero WWN */
333*10652SHyon.Kim@Sun.COM }
334*10652SHyon.Kim@Sun.COM
335*10652SHyon.Kim@Sun.COM /* Check for stale data */
336*10652SHyon.Kim@Sun.COM status = verifyAdapter(hba_ptr);
337*10652SHyon.Kim@Sun.COM if (status != HBA_STATUS_OK) {
338*10652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE, "Verify adapter failed");
339*10652SHyon.Kim@Sun.COM unlock(&open_handles_lock);
340*10652SHyon.Kim@Sun.COM unlock(&all_hbas_lock);
341*10652SHyon.Kim@Sun.COM return (pwwn);
342*10652SHyon.Kim@Sun.COM }
343*10652SHyon.Kim@Sun.COM
344*10652SHyon.Kim@Sun.COM if (hba_ptr->first_port == NULL) {
345*10652SHyon.Kim@Sun.COM /* This is probably an internal failure of the library */
346*10652SHyon.Kim@Sun.COM if (hba_ptr->device_path) {
347*10652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
348*10652SHyon.Kim@Sun.COM "Internal failure: Adapter %s contains no "
349*10652SHyon.Kim@Sun.COM "port data", hba_ptr->device_path);
350*10652SHyon.Kim@Sun.COM } else {
351*10652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
352*10652SHyon.Kim@Sun.COM "Internal failure: Adapter at index %d contains "
353*10652SHyon.Kim@Sun.COM " no support data", hba_ptr->index);
354*10652SHyon.Kim@Sun.COM }
355*10652SHyon.Kim@Sun.COM unlock(&open_handles_lock);
356*10652SHyon.Kim@Sun.COM unlock(&all_hbas_lock);
357*10652SHyon.Kim@Sun.COM return (pwwn); /* zero WWN */
358*10652SHyon.Kim@Sun.COM }
359*10652SHyon.Kim@Sun.COM /* Set the WWN now and return it */
360*10652SHyon.Kim@Sun.COM pwwn = hba_ptr->first_port->port_attributes.PortSpecificAttribute.\
361*10652SHyon.Kim@Sun.COM SASPort->LocalSASAddress;
362*10652SHyon.Kim@Sun.COM unlock(&open_handles_lock);
363*10652SHyon.Kim@Sun.COM unlock(&all_hbas_lock);
364*10652SHyon.Kim@Sun.COM
365*10652SHyon.Kim@Sun.COM return (pwwn);
366*10652SHyon.Kim@Sun.COM }
367*10652SHyon.Kim@Sun.COM
368*10652SHyon.Kim@Sun.COM u_longlong_t
wwnConversion(uchar_t * wwn)369*10652SHyon.Kim@Sun.COM wwnConversion(uchar_t *wwn)
370*10652SHyon.Kim@Sun.COM {
371*10652SHyon.Kim@Sun.COM u_longlong_t tmp;
372*10652SHyon.Kim@Sun.COM (void) memcpy(&tmp, wwn, sizeof (u_longlong_t));
373*10652SHyon.Kim@Sun.COM tmp = ntohll(tmp);
374*10652SHyon.Kim@Sun.COM return (tmp);
375*10652SHyon.Kim@Sun.COM }
376*10652SHyon.Kim@Sun.COM
377*10652SHyon.Kim@Sun.COM /*
378*10652SHyon.Kim@Sun.COM * Using ioctl to send uscsi command out
379*10652SHyon.Kim@Sun.COM */
380*10652SHyon.Kim@Sun.COM HBA_STATUS
send_uscsi_cmd(const char * devpath,struct uscsi_cmd * ucmd)381*10652SHyon.Kim@Sun.COM send_uscsi_cmd(const char *devpath, struct uscsi_cmd *ucmd)
382*10652SHyon.Kim@Sun.COM {
383*10652SHyon.Kim@Sun.COM const char ROUTINE[] = "send_uscsi_cmd";
384*10652SHyon.Kim@Sun.COM int fd;
385*10652SHyon.Kim@Sun.COM HBA_STATUS ret;
386*10652SHyon.Kim@Sun.COM
387*10652SHyon.Kim@Sun.COM /* set default timeout to 200 */
388*10652SHyon.Kim@Sun.COM ucmd->uscsi_timeout = 200;
389*10652SHyon.Kim@Sun.COM
390*10652SHyon.Kim@Sun.COM /* reset errno. */
391*10652SHyon.Kim@Sun.COM errno = 0;
392*10652SHyon.Kim@Sun.COM if ((fd = open(devpath, O_RDONLY | O_NDELAY)) == -1) {
393*10652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
394*10652SHyon.Kim@Sun.COM "open devpath %s failed: %s", devpath, strerror(errno));
395*10652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
396*10652SHyon.Kim@Sun.COM }
397*10652SHyon.Kim@Sun.COM
398*10652SHyon.Kim@Sun.COM if (ioctl(fd, USCSICMD, ucmd) == -1) {
399*10652SHyon.Kim@Sun.COM if (errno == EBUSY) {
400*10652SHyon.Kim@Sun.COM ret = HBA_STATUS_ERROR_BUSY;
401*10652SHyon.Kim@Sun.COM } else if (errno == EAGAIN) {
402*10652SHyon.Kim@Sun.COM ret = HBA_STATUS_ERROR_TRY_AGAIN;
403*10652SHyon.Kim@Sun.COM } else {
404*10652SHyon.Kim@Sun.COM ret = HBA_STATUS_ERROR;
405*10652SHyon.Kim@Sun.COM }
406*10652SHyon.Kim@Sun.COM log(LOG_DEBUG, ROUTINE,
407*10652SHyon.Kim@Sun.COM "ioctl send uscsi to devpath: %s failed: %s",
408*10652SHyon.Kim@Sun.COM devpath, strerror(errno));
409*10652SHyon.Kim@Sun.COM (void) close(fd);
410*10652SHyon.Kim@Sun.COM return (ret);
411*10652SHyon.Kim@Sun.COM }
412*10652SHyon.Kim@Sun.COM
413*10652SHyon.Kim@Sun.COM (void) close(fd);
414*10652SHyon.Kim@Sun.COM
415*10652SHyon.Kim@Sun.COM return (HBA_STATUS_OK);
416*10652SHyon.Kim@Sun.COM }
417*10652SHyon.Kim@Sun.COM
418*10652SHyon.Kim@Sun.COM /*
419*10652SHyon.Kim@Sun.COM * Check whether the given Domain Address is valid.
420*10652SHyon.Kim@Sun.COM */
421*10652SHyon.Kim@Sun.COM HBA_STATUS
validateDomainAddress(struct sun_sas_port * hba_port_ptr,HBA_WWN DomainAddr)422*10652SHyon.Kim@Sun.COM validateDomainAddress(struct sun_sas_port *hba_port_ptr, HBA_WWN DomainAddr)
423*10652SHyon.Kim@Sun.COM {
424*10652SHyon.Kim@Sun.COM if (hba_port_ptr->first_phy != NULL &&
425*10652SHyon.Kim@Sun.COM wwnConversion(hba_port_ptr->first_phy->
426*10652SHyon.Kim@Sun.COM phy.domainPortWWN.wwn) ==
427*10652SHyon.Kim@Sun.COM wwnConversion(DomainAddr.wwn)) {
428*10652SHyon.Kim@Sun.COM return (HBA_STATUS_OK);
429*10652SHyon.Kim@Sun.COM }
430*10652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR);
431*10652SHyon.Kim@Sun.COM }
432