xref: /onnv-gate/usr/src/lib/sun_sas/common/sun_sas.c (revision 10652:9d0aff74d6fd)
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