xref: /illumos-gate/usr/src/lib/hbaapi/common/HBAAPILIB-sun.c (revision 69a119caa6570c7077699161b7c28b6ee9f8b0f4)
1 /*************************************************************************
2  * Description
3  *	HBAAPILIB-sun.c - Implements the Sun Extention for Target mode
4  *		FCHBA discovery
5  *
6  * License:
7  *	The contents of this file are subject to the SNIA Public License
8  *	Version 1.0 (the "License"); you may not use this file except in
9  *	compliance with the License. You may obtain a copy of the License at
10  *
11  *	http://www.snia.org/English/Resources/Code/OpenSource.html
12  *
13  *	Software distributed under the License is distributed on an "AS IS"
14  *	basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
15  *	the License for the specific language governing rights and limitations
16  *	under the License.
17  *
18  *************************************************************************
19  */
20 /*
21  * 	Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
22  * 	Use is subject to license terms.
23  */
24 
25 #ifdef WIN32
26 #include <windows.h>
27 #include <string.h>
28 /*
29  * Next define forces entry points in the dll to be exported
30  * See hbaapi.h to see what it does.
31  */
32 #define HBAAPI_EXPORTS
33 #else
34 #include <dlfcn.h>
35 #include <strings.h>
36 #endif
37 #include <stdio.h>
38 #include <time.h>
39 #include <dlfcn.h>
40 #include "hbaapi.h"
41 #include "hbaapi-sun.h"
42 #include "vendorhbaapi.h"
43 #include <stdlib.h>
44 #ifdef USESYSLOG
45 #include <syslog.h>
46 #endif
47 
48 
49 /*
50  * LIBRARY_NUM is a shortcut to figure out which library we need to call.
51  *  The top 16 bits of handle are the library index
52  */
53 #define LIBRARY_NUM(handle)	((handle)>>16)
54 
55 /*
56  * VENDOR_HANDLE turns a global library handle into a vendor specific handle,
57  * with all upper 16 bits set to 0
58  */
59 #define VENDOR_HANDLE(handle)	((handle)&0xFFFF)
60 
61 #define HBA_HANDLE_FROM_LOCAL(library, vendor) \
62 				(((library)<<16) | ((vendor)&0x0000FFFF))
63 
64 extern int _hbaapi_debuglevel;
65 #define DEBUG(L, STR, A1, A2, A3)
66 
67 #if defined(USESYSLOG) && defined(USELOGFILE)
68 extern FILE *_hbaapi_debug_fd;
69 extern int _hbaapi_sysloginit;
70 #undef DEBUG
71 #ifdef WIN32
72 #define DEBUG(L, STR, A1, A2, A3)\
73     if ((L) <= _hbaapi_debuglevel) {\
74 	if(_hbaapi_sysloginit == 0) {\
75 	    openlog("HBAAPI", LOG_PID|LOG_ODELAY ,LOG_USER);\
76 	    _hbaapi_sysloginit = 1;\
77 	}\
78 	syslog (LOG_INFO, (STR), (A1), (A2), (A3));\
79 	if(_hbaapi_debug_fd == NULL) {\
80 	    char _logFile[MAX_PATH]; \
81 	    GetTempPath(MAX_PATH, _logFile); \
82 	    strcat(_logFile, "HBAAPI.log"); \
83 	    _hbaapi_debug_fd = fopen(_logFile, "a");\
84 	}\
85         if(_hbaapi_debug_fd != NULL) {\
86 	    fprintf(_hbaapi_debug_fd, (STR ## "\n"), (A1), (A2), (A3));\
87 	}\
88     }
89 #else /* WIN32*/
90 #define DEBUG(L, STR, A1, A2, A3)\
91     if ((L) <= _hbaapi_debuglevel) {\
92 	if(_hbaapi_sysloginit == 0) {\
93 	    openlog("HBAAPI", LOG_PID|LOG_ODELAY ,LOG_USER);\
94 	    _hbaapi_sysloginit = 1;\
95 	}\
96 	syslog (LOG_INFO, (STR), (A1), (A2), (A3));\
97 	if(_hbaapi_debug_fd == NULL) {\
98 	    _hbaapi_debug_fd = fopen("/tmp/HBAAPI.log", "a");\
99 	}\
100         if(_hbaapi_debug_fd != NULL) {\
101 	    fprintf(_hbaapi_debug_fd, (STR ## "\n"), (A1), (A2), (A3));\
102 	}\
103     }
104 #endif /* WIN32*/
105 
106 #else /* Not both USESYSLOG and USELOGFILE */
107 #if defined(USESYSLOG)
108 int _hbaapi_sysloginit = 0;
109 #undef DEBUG
110 #define DEBUG(L, STR, A1, A2, A3) \
111     if ((L) <= _hbaapi_debuglevel) {\
112 	if(_hbaapi_sysloginit == 0) {\
113 	    openlog("HBAAPI", LOG_PID|LOG_ODELAY ,LOG_USER);\
114 	    _hbaapi_sysloginit = 1;\
115 	}\
116 	syslog (LOG_INFO, (STR), (A1), (A2), (A3));\
117     }
118 #endif /* USESYSLOG */
119 #if defined(USELOGFILE)
120 FILE *_hbaapi_debug_fd = NULL;
121 #undef DEBUG
122 #ifdef WIN32
123 #define DEBUG(L, STR, A1, A2, A3) \
124     if((L) <= _hbaapi_debuglevel) {\
125 	if(_hbaapi_debug_fd == NULL) {\
126 	    char _logFile[MAX_PATH]; \
127 	    GetTempPath(MAX_PATH, _logFile); \
128 	    strcat(_logFile, "HBAAPI.log"); \
129 	    _hbaapi_debug_fd = fopen(_logFile, "a");\
130         }\
131     }
132 #else /* WIN32 */
133 #define DEBUG(L, STR, A1, A2, A3) \
134     if((L) <= _hbaapi_debuglevel) {\
135 	if(_hbaapi_debug_fd == NULL) {\
136 	    _hbaapi_debug_fd = fopen("/tmp/HBAAPI.log", "a");\
137 	}\
138 	if(_hbaapi_debug_fd != NULL) { \
139 	    fprintf(_hbaapi_debug_fd, (STR) ## "\n", (A1), (A2), (A3));\
140 	}\
141     }
142 #endif /* WIN32 */
143 #endif /* USELOGFILE */
144 #endif /* Not both USELOGFILE and USESYSLOG */
145 
146 #ifdef POSIX_THREADS
147 #include <pthread.h>
148 /*
149  * When multiple mutex's are grabed, they must be always be grabbed in
150  * the same order, or deadlock can result.  There are three levels
151  * of mutex's involved in this API.  If LL_mutex is grabbed, always grap
152  * it first.  If AL_mutex is grabbed, it may not be grabbed before
153  * LL_mutex.  If grabbed in a multi grab sequence, the mutex's protecting
154  * the callback lists must always be grabbed last and release before calling
155  * a vendor specific library function that might invoke a callback function
156  * on the same thread.
157  */
158 #define GRAB_MUTEX(M)			grab_mutex(M)
159 #define RELEASE_MUTEX(M)		release_mutex(M)
160 #define RELEASE_MUTEX_RETURN(M,RET)	release_mutex(M); return(RET)
161 #elif defined (WIN32)
162 #define GRAB_MUTEX(m)			EnterCriticalSection(m)
163 #define RELEASE_MUTEX(m)		LeaveCriticalSection(m)
164 #define RELEASE_MUTEX_RETURN(m, RET)	LeaveCriticalSection(m); return(RET)
165 #else
166 #define GRAB_MUTEX(M)
167 #define RELEASE_MUTEX(M)
168 #define RELEASE_MUTEX_RETURN(M,RET)	return(RET)
169 #endif
170 
171 /*
172  * HBA_LIBRARY_STATUS and HBA_LIBRARY_INFO are redefined here.
173  * Avoid any change in the common code.
174  */
175 typedef enum {
176     HBA_LIBRARY_UNKNOWN,
177     HBA_LIBRARY_LOADED,
178     HBA_LIBRARY_NOT_LOADED
179 } HBA_LIBRARY_STATUS;
180 
181 typedef struct hba_library_info {
182     struct hba_library_info
183 			*next;
184 #ifdef WIN32
185     HINSTANCE		hLibrary;		/* Handle to a loaded DLL */
186 #else
187     char		*LibraryName;
188     void*		hLibrary;		/* Handle to a loaded DLL */
189 #endif
190     char		*LibraryPath;
191     HBA_ENTRYPOINTSV2	functionTable;		/* Function pointers */
192     HBA_LIBRARY_STATUS	status;			/* info on this library */
193     HBA_UINT32		index;
194 } HBA_LIBRARY_INFO, *PHBA_LIBRARY_INFO;
195 
196 #define ARE_WE_INITED() \
197 	if (_hbaapi_librarylist == NULL) { \
198 		return(HBA_STATUS_ERROR); \
199 	}
200 
201 extern HBA_LIBRARY_INFO *_hbaapi_librarylist;
202 extern HBA_UINT32 _hbaapi_total_library_count;
203 #ifdef POSIX_THREADS
204 extern pthread_mutex_t _hbaapi_LL_mutex;
205 #elif defined(WIN32)
206 extern CRITICAL_SECTION _hbaapi_LL_mutex;
207 #endif
208 
209 /*
210  * Function type def fop Sun extentions.
211  */
212 typedef HBA_UINT32	(* Sun_HBAGetNumberOfTgtAdaptersFunc)();
213 typedef HBA_STATUS	(* Sun_HBAGetTgtAdapterNameFunc)(HBA_UINT32, char *);
214 typedef HBA_HANDLE	(* Sun_HBAOpenTgtAdapterFunc)(char *);
215 typedef HBA_STATUS	(* Sun_HBAOpenTgtAdapterByWWNFunc)
216 			    (HBA_HANDLE *, HBA_WWN);
217 typedef	HBA_STATUS	(* Sun_HBANPIVGetAdapterAttributesFunc)
218 			    (HBA_HANDLE, HBA_ADAPTERATTRIBUTES *);
219 typedef	HBA_STATUS	(* Sun_HBAGetNPIVPortInfoFunc)
220 			    (HBA_HANDLE, HBA_UINT32, HBA_UINT32, HBA_NPIVATTRIBUTES *);
221 typedef HBA_STATUS	(* Sun_HBADeleteNPIVPortFunc)
222 			    (HBA_HANDLE, HBA_UINT32, HBA_WWN);
223 typedef HBA_STATUS	(* Sun_HBACreateNPIVPortFunc)
224 			    (HBA_HANDLE, HBA_UINT32, HBA_WWN, HBA_WWN, HBA_UINT32 *);
225 typedef	HBA_STATUS	(* Sun_HBAAdapterReturnWWNFunc)
226 			    (HBA_HANDLE, HBA_UINT32, HBA_WWN *, HBA_WWN *);
227 typedef	HBA_STATUS	(* Sun_HBAAdapterCreateWWNFunc)
228 			    (HBA_HANDLE, HBA_UINT32, HBA_WWN *, HBA_WWN *, HBA_WWN *,
229 			    HBA_INT32);
230 typedef	HBA_STATUS	(* Sun_HBAGetPortNPIVAttributesFunc)
231 			    (HBA_HANDLE, HBA_UINT32, HBA_PORTNPIVATTRIBUTES *);
232 typedef	HBA_STATUS	(* Sun_HBARegisterForAdapterDeviceEventsFunc)
233 			    (void (*)(void *, HBA_WWN, HBA_UINT32, HBA_UINT32),
234 			    void *, HBA_HANDLE, HBA_WWN, HBA_CALLBACKHANDLE *);
235 typedef	HBA_STATUS	(* Sun_HBADoForceLipFunc)(HBA_HANDLE, int *);
236 
237 /*
238  * Individual adapter (hba) information
239  * Same as hbaadapter with different structure name.
240  */
241 typedef struct hba_tgtadapter_info {
242     struct hba_tgtadapter_info
243 			*next;
244     HBA_STATUS		GNstatus; /* status from GetTgtAdapterNameFunc */
245     char		*name;
246     HBA_WWN		nodeWWN;
247     HBA_LIBRARY_INFO	*library;
248     HBA_UINT32		index;
249 } HBA_TGTADAPTER_INFO;
250 
251 /*
252  * Make the list as an array with max size 16
253  */
254 HBA_TGTADAPTER_INFO *_hbaapi_tgtadapterlist;
255 HBA_UINT32 _hbaapi_total_tgtadapter_count = 0;
256 #ifdef POSIX_THREADS
257 pthread_mutex_t _hbaapi_tgtAL_mutex = PTHREAD_MUTEX_INITIALIZER;
258 #elif defined(WIN32)
259 CRITICAL_SECTION _hbaapi_tgtAL_mutex;
260 #endif
261 
262 /*
263  * Common library internal. Mutex handling
264  */
265 #ifdef POSIX_THREADS
266 static void
267 grab_mutex(pthread_mutex_t *mp) {
268     int ret;
269     if((ret = pthread_mutex_lock(mp)) != 0) {
270 	perror("pthread_mutex_lock - HBAAPI:");
271 	DEBUG(0, "pthread_mutex_lock returned %d", ret, 0, 0);
272     }
273 }
274 
275 static void
276 release_mutex(pthread_mutex_t *mp) {
277     int ret;
278     if((ret = pthread_mutex_unlock(mp)) != 0) {
279 	perror("pthread_mutex_unlock - HBAAPI:");
280 	DEBUG(0, "pthread_mutex_unlock returned %d", ret, 0, 0);
281     }
282 }
283 #endif
284 
285 /*
286  * The API used to use fixed size tables as its primary data structure.
287  * Indexing from 1 to N identified each adapters.  Now the adapters are
288  * on a linked list.  There is a unique "index" foreach each adapter.
289  * Adapters always keep their index, even if they are removed from the
290  * hardware.  The only time the indexing is reset is on HBA_FreeLibrary
291  */
292 HBA_UINT32
293 Sun_HBA_GetNumberOfTgtAdapters()
294 {
295     int j=0;
296     HBA_LIBRARY_INFO	*lib_infop;
297     Sun_HBAGetNumberOfTgtAdaptersFunc
298 			GetNumberOfTgtAdaptersFunc = NULL;
299     Sun_HBAGetTgtAdapterNameFunc
300 			GetTgtAdapterNameFunc = NULL;
301     HBA_BOOLEAN		found_name;
302     HBA_TGTADAPTER_INFO	*adapt_infop;
303     HBA_STATUS		status;
304 
305     char adaptername[256];
306     int num_adapters; /* local */
307 
308     if(_hbaapi_librarylist == NULL) {
309 	return (0);
310     }
311     GRAB_MUTEX(&_hbaapi_LL_mutex); /* pay attention to order */
312     GRAB_MUTEX(&_hbaapi_tgtAL_mutex);
313 
314     for (lib_infop = _hbaapi_librarylist;
315 	 lib_infop != NULL;
316 	 lib_infop = lib_infop->next) {
317 
318 	if (lib_infop->status != HBA_LIBRARY_LOADED) {
319 	    continue;
320 	}
321 
322 	if (lib_infop->hLibrary != NULL) {
323             GetNumberOfTgtAdaptersFunc = (Sun_HBAGetNumberOfTgtAdaptersFunc)
324 		dlsym(lib_infop->hLibrary, "Sun_fcGetNumberOfTgtAdapters");
325             GetTgtAdapterNameFunc = (Sun_HBAGetTgtAdapterNameFunc)
326 		dlsym(lib_infop->hLibrary, "Sun_fcGetTgtAdapterName");
327 	    if (GetNumberOfTgtAdaptersFunc == NULL ||
328 		GetTgtAdapterNameFunc == NULL)	{
329 		GetNumberOfTgtAdaptersFunc = GetTgtAdapterNameFunc = NULL;
330                 continue;
331             }
332 	} else {
333 	    continue;
334 	}
335 
336 	num_adapters = ((GetNumberOfTgtAdaptersFunc)());
337 #ifndef WIN32
338 	DEBUG(1, "HBAAPI: number of target mode adapters for %s = %d\n",
339 	      lib_infop->LibraryName, num_adapters, 0);
340 #else
341 	DEBUG(1, "HBAAPI: number of target mode_adapters for %s = %d\n",
342 	      lib_infop->LibraryPath, num_adapters, 0);
343 #endif
344 
345 	for (j = 0; j < num_adapters; j++) {
346 	    found_name = 0;
347 	    status = (GetTgtAdapterNameFunc)(j, (char *)&adaptername);
348 	    if(status == HBA_STATUS_OK) {
349 		for(adapt_infop = _hbaapi_tgtadapterlist;
350 		    adapt_infop != NULL;
351 		    adapt_infop = adapt_infop->next) {
352 		    /*
353 		     * check for duplicates, really, this may just be a second
354 		     * call to this function
355 		     * ??? how do we know when a name becomes stale?
356 		     */
357 		    if(strcmp(adaptername, adapt_infop->name) == 0) {
358 			/* already got this one */
359 			found_name++;
360 			break;
361 		    }
362 		}
363 		if(found_name != 0) {
364 		    continue;
365 		}
366 	    }
367 
368 	    adapt_infop = (HBA_TGTADAPTER_INFO *)
369 		calloc(1, sizeof(HBA_TGTADAPTER_INFO));
370 	    if(adapt_infop == NULL) {
371 #ifndef WIN32
372 		fprintf(stderr,
373 			"HBA_GetNumberOfAdapters: calloc failed on sizeof:%d\n",
374 			sizeof(HBA_TGTADAPTER_INFO));
375 #endif
376 		RELEASE_MUTEX(&_hbaapi_tgtAL_mutex);
377 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex,
378 				     _hbaapi_total_tgtadapter_count);
379 	    }
380 	    if((adapt_infop->GNstatus = status) == HBA_STATUS_OK) {
381 		adapt_infop->name = strdup(adaptername);
382 	    } else {
383 		char dummyname[512];
384 		sprintf(dummyname, "NULLADAPTER-%s-%03d",
385 			lib_infop->LibraryPath, _hbaapi_total_tgtadapter_count);
386 		dummyname[255] = '\0';
387 		adapt_infop->name = strdup(dummyname);
388 	    }
389 	    adapt_infop->library = lib_infop;
390 	    adapt_infop->next = _hbaapi_tgtadapterlist;
391 	    adapt_infop->index = _hbaapi_total_tgtadapter_count;
392 	    _hbaapi_tgtadapterlist = adapt_infop;
393 	    _hbaapi_total_tgtadapter_count++;
394 	}
395 	GetNumberOfTgtAdaptersFunc = GetTgtAdapterNameFunc = NULL;
396     }
397     RELEASE_MUTEX(&_hbaapi_tgtAL_mutex);
398     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, _hbaapi_total_tgtadapter_count);
399 }
400 
401 HBA_STATUS
402 Sun_HBA_GetTgtAdapterName(
403     HBA_UINT32 adapterindex,
404     char *adaptername)
405 {
406     HBA_TGTADAPTER_INFO	*adapt_infop;
407     HBA_STATUS		ret = HBA_STATUS_ERROR_ILLEGAL_INDEX;
408 
409     if (adaptername == NULL) {
410 	    return(HBA_STATUS_ERROR_ARG);
411     }
412     /*
413      * The adapter index is from old code, but we have
414      * to support it.  Go down the list looking for
415      * the adapter
416      */
417     ARE_WE_INITED();
418     GRAB_MUTEX(&_hbaapi_tgtAL_mutex);
419     *adaptername = '\0';
420     for(adapt_infop = _hbaapi_tgtadapterlist;
421 	adapt_infop != NULL;
422 	adapt_infop = adapt_infop->next) {
423 
424 	if(adapt_infop->index == adapterindex) {
425 	    if(adapt_infop->name != NULL &&
426 	       adapt_infop->GNstatus == HBA_STATUS_OK) {
427 		strcpy(adaptername, adapt_infop->name);
428 	    } else {
429 		*adaptername = '\0';
430 	    }
431 	    ret = adapt_infop->GNstatus;
432 	    break;
433 	}
434     }
435     DEBUG(2, "GetAdapterName for index:%d ->%s", adapterindex, adaptername, 0);
436     RELEASE_MUTEX_RETURN(&_hbaapi_AL_mutex, ret);
437 }
438 
439 HBA_HANDLE
440 Sun_HBA_OpenTgtAdapter(char* adaptername)
441 {
442     HBA_HANDLE		handle;
443     Sun_HBAOpenTgtAdapterFunc	OpenTgtAdapterFunc;
444     HBA_TGTADAPTER_INFO	*adapt_infop;
445     HBA_LIBRARY_INFO	*lib_infop;
446 
447     DEBUG(2, "OpenAdapter: %s", adaptername, 0, 0);
448 
449     if(_hbaapi_librarylist == NULL) {
450 	return(HBA_HANDLE_INVALID);
451     }
452     if (adaptername == NULL) {
453 	return(HBA_STATUS_ERROR_ARG);
454     }
455     handle = HBA_HANDLE_INVALID;
456     GRAB_MUTEX(&_hbaapi_AL_mutex);
457     for(adapt_infop = _hbaapi_tgtadapterlist;
458 	adapt_infop != NULL;
459 	adapt_infop = adapt_infop->next) {
460 	if (strcmp(adaptername, adapt_infop->name) != 0) {
461 	    continue;
462 	}
463 	lib_infop = adapt_infop->library;
464         OpenTgtAdapterFunc = (Sun_HBAOpenTgtAdapterFunc)
465 		dlsym(lib_infop->hLibrary, "Sun_fcOpenTgtAdapter");
466 	if (OpenTgtAdapterFunc != NULL) {
467 	    /* retrieve the vendor handle */
468 	    handle = (OpenTgtAdapterFunc)(adaptername);
469 	    if(handle != 0) {
470 		/* or this with the library index to get the common handle */
471 		handle = HBA_HANDLE_FROM_LOCAL(lib_infop->index, handle);
472 	    }
473 	}
474 	break;
475     }
476     RELEASE_MUTEX_RETURN(&_hbaapi_AL_mutex, handle);
477 }
478 
479 /*
480  * This function ignores the list of known adapters and instead tries
481  * each vendors open function to see if one of them
482  * can open an adapter when referenced with a particular WWN
483  */
484 HBA_STATUS
485 Sun_HBA_OpenTgtAdapterByWWN(HBA_HANDLE *phandle, HBA_WWN nodeWWN)
486 {
487     HBA_HANDLE		handle;
488     HBA_LIBRARY_INFO	*lib_infop;
489     Sun_HBAGetNumberOfTgtAdaptersFunc
490 			GetNumberOfTgtAdaptersFunc;
491     Sun_HBAOpenTgtAdapterByWWNFunc
492 			OpenTgtAdapterByWWNFunc;
493     HBA_STATUS		status;
494 
495     DEBUG(2, "OpenAdapterByWWN: %s", WWN2STR1(&nodeWWN), 0, 0);
496 
497     if (phandle == NULL) {
498 	    return(HBA_STATUS_ERROR_ARG);
499     }
500 
501     ARE_WE_INITED();
502 
503     *phandle = HBA_HANDLE_INVALID;
504 
505     GRAB_MUTEX(&_hbaapi_LL_mutex);
506     for (lib_infop = _hbaapi_librarylist;
507 	 lib_infop != NULL;
508 	 lib_infop = lib_infop->next) {
509 
510 	status = HBA_STATUS_ERROR_ILLEGAL_WWN;
511 
512 	if (lib_infop->status != HBA_LIBRARY_LOADED) {
513 	    continue;
514 	}
515 
516         GetNumberOfTgtAdaptersFunc = (Sun_HBAGetNumberOfTgtAdaptersFunc)
517 		dlsym(lib_infop->hLibrary, "Sun_fcGetNumberOfTgtAdapters");
518         OpenTgtAdapterByWWNFunc = (Sun_HBAOpenTgtAdapterByWWNFunc)
519 		dlsym(lib_infop->hLibrary, "Sun_fcOpenTgtAdapterByWWN");
520 	if (GetNumberOfTgtAdaptersFunc == NULL ||
521 		OpenTgtAdapterByWWNFunc == NULL) {
522 		GetNumberOfTgtAdaptersFunc = OpenTgtAdapterByWWNFunc = NULL;
523                 continue;
524         }
525 
526 	(void) ((GetNumberOfTgtAdaptersFunc)());
527 
528 	if((status = (OpenTgtAdapterByWWNFunc)(&handle, nodeWWN))
529 	    != HBA_STATUS_OK) {
530 	    GetNumberOfTgtAdaptersFunc = OpenTgtAdapterByWWNFunc = NULL;
531 	    continue;
532 	}
533 	/* OK, make a vendor non-specific handle */
534 	*phandle = HBA_HANDLE_FROM_LOCAL(lib_infop->index, handle);
535 	status = HBA_STATUS_OK;
536 	break;
537 
538 	GetNumberOfTgtAdaptersFunc = OpenTgtAdapterByWWNFunc = NULL;
539     }
540     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
541 }
542 
543 static HBA_STATUS
544 HBA_NPIV_CheckLibrary(HBA_HANDLE handle,
545 			HBA_LIBRARY_INFO **lib_infopp,
546 			HBA_HANDLE *vendorhandle) {
547 	HBA_UINT32		libraryIndex;
548 	HBA_LIBRARY_INFO	*lib_infop;
549 
550 	if (vendorhandle == NULL) {
551 		return(HBA_STATUS_ERROR_ARG);
552 	}
553 	if(_hbaapi_librarylist == NULL) {
554 		return(HBA_STATUS_ERROR);
555 	}
556 	libraryIndex = LIBRARY_NUM(handle);
557 
558 	GRAB_MUTEX(&_hbaapi_LL_mutex);
559 	for(lib_infop = _hbaapi_librarylist;
560 	    lib_infop != NULL;
561 	    lib_infop = lib_infop->next) {
562 		if(lib_infop->index == libraryIndex) {
563 			if(lib_infop->status != HBA_LIBRARY_LOADED) {
564 				return HBA_STATUS_ERROR;
565 			}
566 			*lib_infopp = lib_infop;
567 			*vendorhandle = VENDOR_HANDLE(handle);
568 			/* caller will release the mutex */
569 			return HBA_STATUS_OK;
570 		}
571 	}
572 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INVALID_HANDLE);
573 }
574 #define	NPIVCHECKLIBRARY() \
575 	status = HBA_NPIV_CheckLibrary(handle, &lib_infop, &vendorHandle); \
576 	if(status != HBA_STATUS_OK) { \
577 		return(status); \
578 	}
579 
580 HBA_STATUS
581 Sun_HBA_NPIVGetAdapterAttributes (
582     HBA_HANDLE		handle,
583     HBA_ADAPTERATTRIBUTES
584 			*hbaattributes)
585 {
586 	HBA_STATUS		status;
587 	HBA_LIBRARY_INFO	*lib_infop;
588 	HBA_HANDLE		vendorHandle;
589 	Sun_HBANPIVGetAdapterAttributesFunc	NPIVGetAdapterAttributesFunc;
590 
591 	DEBUG(2, "HBA_NPIVGetAdapterAttributes", 0, 0, 0);
592 
593 	NPIVCHECKLIBRARY();
594 	NPIVGetAdapterAttributesFunc = (Sun_HBANPIVGetAdapterAttributesFunc)
595 	    dlsym(lib_infop->hLibrary, "Sun_fcNPIVGetAdapterAttributes");
596 	if (NPIVGetAdapterAttributesFunc != NULL) {
597 		status = ((NPIVGetAdapterAttributesFunc)(vendorHandle,
598 			hbaattributes));
599 	} else {
600 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
601 	}
602 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
603 }
604 
605 HBA_STATUS
606 Sun_HBA_GetNPIVPortInfo (
607     HBA_HANDLE		handle,
608     HBA_UINT32		portindex,
609     HBA_UINT32		vportindex,
610     HBA_NPIVATTRIBUTES	*attributes)
611 {
612 	HBA_STATUS		status;
613 	HBA_LIBRARY_INFO	*lib_infop;
614 	HBA_HANDLE		vendorHandle;
615 	Sun_HBAGetNPIVPortInfoFunc	GetNPIVPortInfoFunc;
616 
617 	NPIVCHECKLIBRARY();
618 	GetNPIVPortInfoFunc = (Sun_HBAGetNPIVPortInfoFunc)
619 		dlsym(lib_infop->hLibrary, "Sun_fcGetNPIVPortInfo");
620 	if (GetNPIVPortInfoFunc != NULL) {
621 		status = ((GetNPIVPortInfoFunc)(vendorHandle, portindex,
622 			vportindex, attributes));
623 	} else {
624 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
625 	}
626 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
627 }
628 
629 HBA_STATUS
630 Sun_HBA_DeleteNPIVPort (
631     HBA_HANDLE		handle,
632     HBA_UINT32		portindex,
633     HBA_WWN		vportWWN)
634 {
635 	HBA_STATUS		status;
636 	HBA_LIBRARY_INFO	*lib_infop;
637 	HBA_HANDLE		vendorHandle;
638 	Sun_HBADeleteNPIVPortFunc	DeleteNPIVPortFunc;
639 
640 	NPIVCHECKLIBRARY();
641 	DeleteNPIVPortFunc = (Sun_HBADeleteNPIVPortFunc)
642 		dlsym(lib_infop->hLibrary, "Sun_fcDeleteNPIVPort");
643 	if (DeleteNPIVPortFunc != NULL) {
644 		status = ((DeleteNPIVPortFunc)(vendorHandle,
645 		    portindex, vportWWN));
646 	} else {
647 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
648 	}
649 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
650 }
651 
652 HBA_STATUS
653 Sun_HBA_CreateNPIVPort (
654     HBA_HANDLE		handle,
655     HBA_UINT32		portindex,
656     HBA_WWN		vnodeWWN,
657     HBA_WWN		vportWWN,
658     HBA_UINT32		*vportindex)
659 {
660 	HBA_STATUS		status;
661 	HBA_LIBRARY_INFO	*lib_infop;
662 	HBA_HANDLE		vendorHandle;
663 	Sun_HBACreateNPIVPortFunc	CreateNPIVPortFunc;
664 
665 	NPIVCHECKLIBRARY();
666 	CreateNPIVPortFunc = (Sun_HBACreateNPIVPortFunc)
667 		dlsym(lib_infop->hLibrary, "Sun_fcCreateNPIVPort");
668 	if (CreateNPIVPortFunc != NULL) {
669 		status = ((CreateNPIVPortFunc)(vendorHandle,
670 		    portindex, vnodeWWN, vportWWN, vportindex));
671 	} else {
672 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
673 	}
674 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
675 }
676 
677 HBA_STATUS
678 Sun_HBA_GetPortNPIVAttributes (
679     HBA_HANDLE		handle,
680     HBA_UINT32		portindex,
681     HBA_PORTNPIVATTRIBUTES	*portnpivattributes)
682 {
683 	HBA_STATUS		status;
684 	HBA_LIBRARY_INFO	*lib_infop;
685 	HBA_HANDLE		vendorHandle;
686 	Sun_HBAGetPortNPIVAttributesFunc	GetPortNPIVAttributesFunc;
687 
688 	NPIVCHECKLIBRARY();
689 	GetPortNPIVAttributesFunc = (Sun_HBAGetPortNPIVAttributesFunc)
690 		dlsym(lib_infop->hLibrary, "Sun_fcGetPortNPIVAttributes");
691 	if (GetPortNPIVAttributesFunc != NULL) {
692 		status = ((GetPortNPIVAttributesFunc)(
693 		    vendorHandle, portindex, portnpivattributes));
694 	} else {
695 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
696 	}
697 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
698 }
699 
700 HBA_STATUS
701 Sun_HBA_AdapterCreateWWN (
702     HBA_HANDLE		handle,
703     HBA_UINT32		portindex,
704     HBA_WWN		*nwwn,
705     HBA_WWN		*pwwn,
706     HBA_WWN		*OUI,
707     HBA_INT32		method)
708 {
709 	HBA_STATUS		status;
710 	HBA_LIBRARY_INFO	*lib_infop;
711 	HBA_HANDLE		vendorHandle;
712 	Sun_HBAAdapterCreateWWNFunc	AdapterCreateWWNFunc;
713 
714 	NPIVCHECKLIBRARY();
715 	AdapterCreateWWNFunc = (Sun_HBAAdapterCreateWWNFunc)
716 		dlsym(lib_infop->hLibrary, "Sun_fcAdapterCreateWWN");
717 	if (AdapterCreateWWNFunc != NULL) {
718 		status = ((AdapterCreateWWNFunc)(vendorHandle,
719 		    portindex, nwwn, pwwn, OUI, method));
720 	} else {
721 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
722 	}
723 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
724 }
725 
726 HBA_STATUS
727 Sun_HBA_AdapterReturnWWN (
728     HBA_HANDLE		handle,
729     HBA_UINT32		portindex,
730     HBA_WWN		*nwwn,
731     HBA_WWN		*pwwn)
732 {
733 	HBA_STATUS		status;
734 	HBA_LIBRARY_INFO	*lib_infop;
735 	HBA_HANDLE		vendorHandle;
736 	Sun_HBAAdapterReturnWWNFunc	AdapterReturnWWNFunc;
737 
738 	NPIVCHECKLIBRARY();
739 	AdapterReturnWWNFunc = (Sun_HBAAdapterReturnWWNFunc)
740 		dlsym(lib_infop->hLibrary, "Sun_fcAdapterReturnWWN");
741 	if (AdapterReturnWWNFunc != NULL) {
742 		status = ((AdapterReturnWWNFunc)(vendorHandle,
743 		    portindex, nwwn, pwwn));
744 	} else {
745 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
746 	}
747 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
748 }
749 
750 typedef struct hba_npivadaptercallback_elem {
751     struct hba_npivadaptercallback_elem
752 			*next;
753     HBA_LIBRARY_INFO	*lib_info;
754     void		*userdata;
755     HBA_CALLBACKHANDLE	vendorcbhandle;
756     void		(*callback)();
757 } HBA_NPIVADAPTERCALLBACK_ELEM;
758 extern HBA_NPIVADAPTERCALLBACK_ELEM *_hbaapi_adapterdeviceevents_callback_list;
759 
760 /* Adapter Device Events ********************************************************/
761 static void
762 adapterdeviceevents_callback (void *data,
763     HBA_WWN	PortWWN,
764     HBA_UINT32	eventType,
765     HBA_UINT32	fabricPortID)
766 {
767 	HBA_NPIVADAPTERCALLBACK_ELEM	*acbp;
768 
769 	DEBUG(3, "AdapterDeviceEvent, port:%s, eventType:%d fabricPortID:0X%06x",
770 	    WWN2STR1(&PortWWN), eventType, fabricPortID);
771 
772 	GRAB_MUTEX(&_hbaapi_APE_mutex);
773 
774 	for(acbp = _hbaapi_adapterdeviceevents_callback_list;
775 	    acbp != NULL;
776 	    acbp = acbp->next) {
777 		if(data == (void *)acbp) {
778 			(*acbp->callback)(acbp->userdata, PortWWN, eventType, fabricPortID);
779 			break;
780 		}
781 	}
782 	RELEASE_MUTEX(&_hbaapi_APE_mutex);
783 }
784 
785 HBA_STATUS
786 Sun_HBA_RegisterForAdapterDeviceEvents (
787     void	(*callback) (
788 	void		*data,
789 	HBA_WWN		PortWWN,
790 	HBA_UINT32	eventType,
791 	HBA_UINT32	fabricPortID
792 	),
793     void		*userData,
794     HBA_HANDLE		handle,
795     HBA_WWN		PortWWN,
796     HBA_CALLBACKHANDLE	*callbackHandle)
797 {
798 	HBA_NPIVADAPTERCALLBACK_ELEM	*acbp;
799 	HBA_STATUS			status;
800 	HBA_LIBRARY_INFO		*lib_infop;
801 	HBA_HANDLE			vendorHandle;
802 	Sun_HBARegisterForAdapterDeviceEventsFunc
803 					registeredfunc;
804 
805 	if (callbackHandle == NULL) {
806 		return(HBA_STATUS_ERROR_ARG);
807 	}
808 
809         NPIVCHECKLIBRARY();
810 	registeredfunc = (Sun_HBARegisterForAdapterDeviceEventsFunc)
811                 dlsym(lib_infop->hLibrary,
812 		    "Sun_fcRegisterForAdapterDeviceEvents");
813 	if (registeredfunc == NULL) {
814 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
815 	}
816 
817 	acbp = (HBA_NPIVADAPTERCALLBACK_ELEM *)
818 		calloc(1, sizeof(HBA_NPIVADAPTERCALLBACK_ELEM));
819 
820 	if(acbp == NULL) {
821 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
822 	}
823 
824 	*callbackHandle = (HBA_CALLBACKHANDLE) acbp;
825 	acbp->callback = callback;
826 	acbp->userdata = userData;
827 	acbp->lib_info = lib_infop;
828 
829 	status = (registeredfunc)(adapterdeviceevents_callback,
830 		(void *)acbp,
831 		vendorHandle,
832 		PortWWN,
833 		&acbp->vendorcbhandle);
834 	if(status != HBA_STATUS_OK) {
835 		free(acbp);
836 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
837 	}
838 
839 	GRAB_MUTEX(&_hbaapi_APE_mutex);
840 	acbp->next = _hbaapi_adapterdeviceevents_callback_list;
841 	_hbaapi_adapterdeviceevents_callback_list = acbp;
842 	RELEASE_MUTEX(&_hbaapi_APE_mutex);
843 
844 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
845 }
846 
847 HBA_STATUS
848 Sun_HBA_ForceLip(HBA_HANDLE handle, int *rval)
849 {
850 	HBA_STATUS		status;
851 	HBA_LIBRARY_INFO	*lib_infop;
852 	HBA_HANDLE		vendorHandle;
853 
854 	Sun_HBADoForceLipFunc	DoForceLipFunc;
855 
856 	DEBUG(2, "Sun_HBA_DoForceLip", 0, 0, 0);
857 
858 	NPIVCHECKLIBRARY();
859 	DoForceLipFunc = (Sun_HBADoForceLipFunc)
860 		dlsym(lib_infop->hLibrary, "Sun_fcDoForceLip");
861 	if (DoForceLipFunc != NULL) {
862 		status = ((DoForceLipFunc)(vendorHandle, rval));
863 	} else {
864 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
865 	}
866 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
867 }
868