xref: /titanic_44/usr/src/lib/hbaapi/common/HBAAPILIB-sun.c (revision a1e9eea083a8f257157edb8a1efb5bbd300eb4bf)
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 2008 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 
236 /*
237  * Individual adapter (hba) information
238  * Same as hbaadapter with different structure name.
239  */
240 typedef struct hba_tgtadapter_info {
241     struct hba_tgtadapter_info
242 			*next;
243     HBA_STATUS		GNstatus; /* status from GetTgtAdapterNameFunc */
244     char		*name;
245     HBA_WWN		nodeWWN;
246     HBA_LIBRARY_INFO	*library;
247     HBA_UINT32		index;
248 } HBA_TGTADAPTER_INFO;
249 
250 /*
251  * Make the list as an array with max size 16
252  */
253 HBA_TGTADAPTER_INFO *_hbaapi_tgtadapterlist;
254 HBA_UINT32 _hbaapi_total_tgtadapter_count = 0;
255 #ifdef POSIX_THREADS
256 pthread_mutex_t _hbaapi_tgtAL_mutex = PTHREAD_MUTEX_INITIALIZER;
257 #elif defined(WIN32)
258 CRITICAL_SECTION _hbaapi_tgtAL_mutex;
259 #endif
260 
261 /*
262  * Common library internal. Mutex handling
263  */
264 #ifdef POSIX_THREADS
265 static void
266 grab_mutex(pthread_mutex_t *mp) {
267     int ret;
268     if((ret = pthread_mutex_lock(mp)) != 0) {
269 	perror("pthread_mutex_lock - HBAAPI:");
270 	DEBUG(0, "pthread_mutex_lock returned %d", ret, 0, 0);
271     }
272 }
273 
274 static void
275 release_mutex(pthread_mutex_t *mp) {
276     int ret;
277     if((ret = pthread_mutex_unlock(mp)) != 0) {
278 	perror("pthread_mutex_unlock - HBAAPI:");
279 	DEBUG(0, "pthread_mutex_unlock returned %d", ret, 0, 0);
280     }
281 }
282 #endif
283 
284 /*
285  * The API used to use fixed size tables as its primary data structure.
286  * Indexing from 1 to N identified each adapters.  Now the adapters are
287  * on a linked list.  There is a unique "index" foreach each adapter.
288  * Adapters always keep their index, even if they are removed from the
289  * hardware.  The only time the indexing is reset is on HBA_FreeLibrary
290  */
291 HBA_UINT32
292 Sun_HBA_GetNumberOfTgtAdapters()
293 {
294     int j=0;
295     HBA_LIBRARY_INFO	*lib_infop;
296     Sun_HBAGetNumberOfTgtAdaptersFunc
297 			GetNumberOfTgtAdaptersFunc = NULL;
298     Sun_HBAGetTgtAdapterNameFunc
299 			GetTgtAdapterNameFunc = NULL;
300     HBA_BOOLEAN		found_name;
301     HBA_TGTADAPTER_INFO	*adapt_infop;
302     HBA_STATUS		status;
303 
304     char adaptername[256];
305     int num_adapters; /* local */
306 
307     if(_hbaapi_librarylist == NULL) {
308 	return (0);
309     }
310     GRAB_MUTEX(&_hbaapi_LL_mutex); /* pay attention to order */
311     GRAB_MUTEX(&_hbaapi_tgtAL_mutex);
312 
313     for (lib_infop = _hbaapi_librarylist;
314 	 lib_infop != NULL;
315 	 lib_infop = lib_infop->next) {
316 
317 	if (lib_infop->status != HBA_LIBRARY_LOADED) {
318 	    continue;
319 	}
320 
321 	if (lib_infop->hLibrary != NULL) {
322             GetNumberOfTgtAdaptersFunc = (Sun_HBAGetNumberOfTgtAdaptersFunc)
323 		dlsym(lib_infop->hLibrary, "Sun_fcGetNumberOfTgtAdapters");
324             GetTgtAdapterNameFunc = (Sun_HBAGetTgtAdapterNameFunc)
325 		dlsym(lib_infop->hLibrary, "Sun_fcGetTgtAdapterName");
326 	    if (GetNumberOfTgtAdaptersFunc == NULL ||
327 		GetTgtAdapterNameFunc == NULL)	{
328 		GetNumberOfTgtAdaptersFunc = GetTgtAdapterNameFunc = NULL;
329                 continue;
330             }
331 	} else {
332 	    continue;
333 	}
334 
335 	num_adapters = ((GetNumberOfTgtAdaptersFunc)());
336 #ifndef WIN32
337 	DEBUG(1, "HBAAPI: number of target mode adapters for %s = %d\n",
338 	      lib_infop->LibraryName, num_adapters, 0);
339 #else
340 	DEBUG(1, "HBAAPI: number of target mode_adapters for %s = %d\n",
341 	      lib_infop->LibraryPath, num_adapters, 0);
342 #endif
343 
344 	for (j = 0; j < num_adapters; j++) {
345 	    found_name = 0;
346 	    status = (GetTgtAdapterNameFunc)(j, (char *)&adaptername);
347 	    if(status == HBA_STATUS_OK) {
348 		for(adapt_infop = _hbaapi_tgtadapterlist;
349 		    adapt_infop != NULL;
350 		    adapt_infop = adapt_infop->next) {
351 		    /*
352 		     * check for duplicates, really, this may just be a second
353 		     * call to this function
354 		     * ??? how do we know when a name becomes stale?
355 		     */
356 		    if(strcmp(adaptername, adapt_infop->name) == 0) {
357 			/* already got this one */
358 			found_name++;
359 			break;
360 		    }
361 		}
362 		if(found_name != 0) {
363 		    continue;
364 		}
365 	    }
366 
367 	    adapt_infop = (HBA_TGTADAPTER_INFO *)
368 		calloc(1, sizeof(HBA_TGTADAPTER_INFO));
369 	    if(adapt_infop == NULL) {
370 #ifndef WIN32
371 		fprintf(stderr,
372 			"HBA_GetNumberOfAdapters: calloc failed on sizeof:%d\n",
373 			sizeof(HBA_TGTADAPTER_INFO));
374 #endif
375 		RELEASE_MUTEX(&_hbaapi_tgtAL_mutex);
376 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex,
377 				     _hbaapi_total_tgtadapter_count);
378 	    }
379 	    if((adapt_infop->GNstatus = status) == HBA_STATUS_OK) {
380 		adapt_infop->name = strdup(adaptername);
381 	    } else {
382 		char dummyname[512];
383 		sprintf(dummyname, "NULLADAPTER-%s-%03d",
384 			lib_infop->LibraryPath, _hbaapi_total_tgtadapter_count);
385 		dummyname[255] = '\0';
386 		adapt_infop->name = strdup(dummyname);
387 	    }
388 	    adapt_infop->library = lib_infop;
389 	    adapt_infop->next = _hbaapi_tgtadapterlist;
390 	    adapt_infop->index = _hbaapi_total_tgtadapter_count;
391 	    _hbaapi_tgtadapterlist = adapt_infop;
392 	    _hbaapi_total_tgtadapter_count++;
393 	}
394 	GetNumberOfTgtAdaptersFunc = GetTgtAdapterNameFunc = NULL;
395     }
396     RELEASE_MUTEX(&_hbaapi_tgtAL_mutex);
397     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, _hbaapi_total_tgtadapter_count);
398 }
399 
400 HBA_STATUS
401 Sun_HBA_GetTgtAdapterName(
402     HBA_UINT32 adapterindex,
403     char *adaptername)
404 {
405     HBA_TGTADAPTER_INFO	*adapt_infop;
406     HBA_STATUS		ret = HBA_STATUS_ERROR_ILLEGAL_INDEX;
407 
408     if (adaptername == NULL) {
409 	    return(HBA_STATUS_ERROR_ARG);
410     }
411     /*
412      * The adapter index is from old code, but we have
413      * to support it.  Go down the list looking for
414      * the adapter
415      */
416     ARE_WE_INITED();
417     GRAB_MUTEX(&_hbaapi_tgtAL_mutex);
418     *adaptername = '\0';
419     for(adapt_infop = _hbaapi_tgtadapterlist;
420 	adapt_infop != NULL;
421 	adapt_infop = adapt_infop->next) {
422 
423 	if(adapt_infop->index == adapterindex) {
424 	    if(adapt_infop->name != NULL &&
425 	       adapt_infop->GNstatus == HBA_STATUS_OK) {
426 		strcpy(adaptername, adapt_infop->name);
427 	    } else {
428 		*adaptername = '\0';
429 	    }
430 	    ret = adapt_infop->GNstatus;
431 	    break;
432 	}
433     }
434     DEBUG(2, "GetAdapterName for index:%d ->%s", adapterindex, adaptername, 0);
435     RELEASE_MUTEX_RETURN(&_hbaapi_AL_mutex, ret);
436 }
437 
438 HBA_HANDLE
439 Sun_HBA_OpenTgtAdapter(char* adaptername)
440 {
441     HBA_HANDLE		handle;
442     Sun_HBAOpenTgtAdapterFunc	OpenTgtAdapterFunc;
443     HBA_TGTADAPTER_INFO	*adapt_infop;
444     HBA_LIBRARY_INFO	*lib_infop;
445 
446     DEBUG(2, "OpenAdapter: %s", adaptername, 0, 0);
447 
448     if(_hbaapi_librarylist == NULL) {
449 	return(HBA_HANDLE_INVALID);
450     }
451     if (adaptername == NULL) {
452 	return(HBA_STATUS_ERROR_ARG);
453     }
454     handle = HBA_HANDLE_INVALID;
455     GRAB_MUTEX(&_hbaapi_AL_mutex);
456     for(adapt_infop = _hbaapi_tgtadapterlist;
457 	adapt_infop != NULL;
458 	adapt_infop = adapt_infop->next) {
459 	if (strcmp(adaptername, adapt_infop->name) != 0) {
460 	    continue;
461 	}
462 	lib_infop = adapt_infop->library;
463         OpenTgtAdapterFunc = (Sun_HBAOpenTgtAdapterFunc)
464 		dlsym(lib_infop->hLibrary, "Sun_fcOpenTgtAdapter");
465 	if (OpenTgtAdapterFunc != NULL) {
466 	    /* retrieve the vendor handle */
467 	    handle = (OpenTgtAdapterFunc)(adaptername);
468 	    if(handle != 0) {
469 		/* or this with the library index to get the common handle */
470 		handle = HBA_HANDLE_FROM_LOCAL(lib_infop->index, handle);
471 	    }
472 	}
473 	break;
474     }
475     RELEASE_MUTEX_RETURN(&_hbaapi_AL_mutex, handle);
476 }
477 
478 /*
479  * This function ignores the list of known adapters and instead tries
480  * each vendors open function to see if one of them
481  * can open an adapter when referenced with a particular WWN
482  */
483 HBA_STATUS
484 Sun_HBA_OpenTgtAdapterByWWN(HBA_HANDLE *phandle, HBA_WWN nodeWWN)
485 {
486     HBA_HANDLE		handle;
487     HBA_LIBRARY_INFO	*lib_infop;
488     Sun_HBAGetNumberOfTgtAdaptersFunc
489 			GetNumberOfTgtAdaptersFunc;
490     Sun_HBAOpenTgtAdapterByWWNFunc
491 			OpenTgtAdapterByWWNFunc;
492     HBA_STATUS		status;
493 
494     DEBUG(2, "OpenAdapterByWWN: %s", WWN2STR1(&nodeWWN), 0, 0);
495 
496     if (phandle == NULL) {
497 	    return(HBA_STATUS_ERROR_ARG);
498     }
499 
500     ARE_WE_INITED();
501 
502     *phandle = HBA_HANDLE_INVALID;
503 
504     GRAB_MUTEX(&_hbaapi_LL_mutex);
505     for (lib_infop = _hbaapi_librarylist;
506 	 lib_infop != NULL;
507 	 lib_infop = lib_infop->next) {
508 
509 	status = HBA_STATUS_ERROR_ILLEGAL_WWN;
510 
511 	if (lib_infop->status != HBA_LIBRARY_LOADED) {
512 	    continue;
513 	}
514 
515         GetNumberOfTgtAdaptersFunc = (Sun_HBAGetNumberOfTgtAdaptersFunc)
516 		dlsym(lib_infop->hLibrary, "Sun_fcGetNumberOfTgtAdapters");
517         OpenTgtAdapterByWWNFunc = (Sun_HBAOpenTgtAdapterByWWNFunc)
518 		dlsym(lib_infop->hLibrary, "Sun_fcOpenTgtAdapterByWWN");
519 	if (GetNumberOfTgtAdaptersFunc == NULL ||
520 		OpenTgtAdapterByWWNFunc == NULL) {
521 		GetNumberOfTgtAdaptersFunc = OpenTgtAdapterByWWNFunc = NULL;
522                 continue;
523         }
524 
525 	(void) ((GetNumberOfTgtAdaptersFunc)());
526 
527 	if((status = (OpenTgtAdapterByWWNFunc)(&handle, nodeWWN))
528 	    != HBA_STATUS_OK) {
529 	    GetNumberOfTgtAdaptersFunc = OpenTgtAdapterByWWNFunc = NULL;
530 	    continue;
531 	}
532 	/* OK, make a vendor non-specific handle */
533 	*phandle = HBA_HANDLE_FROM_LOCAL(lib_infop->index, handle);
534 	status = HBA_STATUS_OK;
535 	break;
536 
537 	GetNumberOfTgtAdaptersFunc = OpenTgtAdapterByWWNFunc = NULL;
538     }
539     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
540 }
541 
542 static HBA_STATUS
543 HBA_NPIV_CheckLibrary(HBA_HANDLE handle,
544 			HBA_LIBRARY_INFO **lib_infopp,
545 			HBA_HANDLE *vendorhandle) {
546 	HBA_UINT32		libraryIndex;
547 	HBA_LIBRARY_INFO	*lib_infop;
548 
549 	if (vendorhandle == NULL) {
550 		return(HBA_STATUS_ERROR_ARG);
551 	}
552 	if(_hbaapi_librarylist == NULL) {
553 		return(HBA_STATUS_ERROR);
554 	}
555 	libraryIndex = LIBRARY_NUM(handle);
556 
557 	GRAB_MUTEX(&_hbaapi_LL_mutex);
558 	for(lib_infop = _hbaapi_librarylist;
559 	    lib_infop != NULL;
560 	    lib_infop = lib_infop->next) {
561 		if(lib_infop->index == libraryIndex) {
562 			if(lib_infop->status != HBA_LIBRARY_LOADED) {
563 				return HBA_STATUS_ERROR;
564 			}
565 			*lib_infopp = lib_infop;
566 			*vendorhandle = VENDOR_HANDLE(handle);
567 			/* caller will release the mutex */
568 			return HBA_STATUS_OK;
569 		}
570 	}
571 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INVALID_HANDLE);
572 }
573 #define	NPIVCHECKLIBRARY() \
574 	status = HBA_NPIV_CheckLibrary(handle, &lib_infop, &vendorHandle); \
575 	if(status != HBA_STATUS_OK) { \
576 		return(status); \
577 	}
578 
579 HBA_STATUS
580 Sun_HBA_NPIVGetAdapterAttributes (
581     HBA_HANDLE		handle,
582     HBA_ADAPTERATTRIBUTES
583 			*hbaattributes)
584 {
585 	HBA_STATUS		status;
586 	HBA_LIBRARY_INFO	*lib_infop;
587 	HBA_HANDLE		vendorHandle;
588 	Sun_HBANPIVGetAdapterAttributesFunc	NPIVGetAdapterAttributesFunc;
589 
590 	DEBUG(2, "HBA_NPIVGetAdapterAttributes", 0, 0, 0);
591 
592 	NPIVCHECKLIBRARY();
593 	NPIVGetAdapterAttributesFunc = (Sun_HBANPIVGetAdapterAttributesFunc)
594 	    dlsym(lib_infop->hLibrary, "Sun_fcNPIVGetAdapterAttributes");
595 	if (NPIVGetAdapterAttributesFunc != NULL) {
596 		status = ((NPIVGetAdapterAttributesFunc)(vendorHandle,
597 			hbaattributes));
598 	} else {
599 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
600 	}
601 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
602 }
603 
604 HBA_STATUS
605 Sun_HBA_GetNPIVPortInfo (
606     HBA_HANDLE		handle,
607     HBA_UINT32		portindex,
608     HBA_UINT32		vportindex,
609     HBA_NPIVATTRIBUTES	*attributes)
610 {
611 	HBA_STATUS		status;
612 	HBA_LIBRARY_INFO	*lib_infop;
613 	HBA_HANDLE		vendorHandle;
614 	Sun_HBAGetNPIVPortInfoFunc	GetNPIVPortInfoFunc;
615 
616 	NPIVCHECKLIBRARY();
617 	GetNPIVPortInfoFunc = (Sun_HBAGetNPIVPortInfoFunc)
618 		dlsym(lib_infop->hLibrary, "Sun_fcGetNPIVPortInfo");
619 	if (GetNPIVPortInfoFunc != NULL) {
620 		status = ((GetNPIVPortInfoFunc)(vendorHandle, portindex,
621 			vportindex, attributes));
622 	} else {
623 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
624 	}
625 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
626 }
627 
628 HBA_STATUS
629 Sun_HBA_DeleteNPIVPort (
630     HBA_HANDLE		handle,
631     HBA_UINT32		portindex,
632     HBA_WWN		vportWWN)
633 {
634 	HBA_STATUS		status;
635 	HBA_LIBRARY_INFO	*lib_infop;
636 	HBA_HANDLE		vendorHandle;
637 	Sun_HBADeleteNPIVPortFunc	DeleteNPIVPortFunc;
638 
639 	NPIVCHECKLIBRARY();
640 	DeleteNPIVPortFunc = (Sun_HBADeleteNPIVPortFunc)
641 		dlsym(lib_infop->hLibrary, "Sun_fcDeleteNPIVPort");
642 	if (DeleteNPIVPortFunc != NULL) {
643 		status = ((DeleteNPIVPortFunc)(vendorHandle,
644 		    portindex, vportWWN));
645 	} else {
646 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
647 	}
648 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
649 }
650 
651 HBA_STATUS
652 Sun_HBA_CreateNPIVPort (
653     HBA_HANDLE		handle,
654     HBA_UINT32		portindex,
655     HBA_WWN		vnodeWWN,
656     HBA_WWN		vportWWN,
657     HBA_UINT32		*vportindex)
658 {
659 	HBA_STATUS		status;
660 	HBA_LIBRARY_INFO	*lib_infop;
661 	HBA_HANDLE		vendorHandle;
662 	Sun_HBACreateNPIVPortFunc	CreateNPIVPortFunc;
663 
664 	NPIVCHECKLIBRARY();
665 	CreateNPIVPortFunc = (Sun_HBACreateNPIVPortFunc)
666 		dlsym(lib_infop->hLibrary, "Sun_fcCreateNPIVPort");
667 	if (CreateNPIVPortFunc != NULL) {
668 		status = ((CreateNPIVPortFunc)(vendorHandle,
669 		    portindex, vnodeWWN, vportWWN, vportindex));
670 	} else {
671 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
672 	}
673 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
674 }
675 
676 HBA_STATUS
677 Sun_HBA_GetPortNPIVAttributes (
678     HBA_HANDLE		handle,
679     HBA_UINT32		portindex,
680     HBA_PORTNPIVATTRIBUTES	*portnpivattributes)
681 {
682 	HBA_STATUS		status;
683 	HBA_LIBRARY_INFO	*lib_infop;
684 	HBA_HANDLE		vendorHandle;
685 	Sun_HBAGetPortNPIVAttributesFunc	GetPortNPIVAttributesFunc;
686 
687 	NPIVCHECKLIBRARY();
688 	GetPortNPIVAttributesFunc = (Sun_HBAGetPortNPIVAttributesFunc)
689 		dlsym(lib_infop->hLibrary, "Sun_fcGetPortNPIVAttributes");
690 	if (GetPortNPIVAttributesFunc != NULL) {
691 		status = ((GetPortNPIVAttributesFunc)(
692 		    vendorHandle, portindex, portnpivattributes));
693 	} else {
694 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
695 	}
696 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
697 }
698 
699 HBA_STATUS
700 Sun_HBA_AdapterCreateWWN (
701     HBA_HANDLE		handle,
702     HBA_UINT32		portindex,
703     HBA_WWN		*nwwn,
704     HBA_WWN		*pwwn,
705     HBA_WWN		*OUI,
706     HBA_INT32		method)
707 {
708 	HBA_STATUS		status;
709 	HBA_LIBRARY_INFO	*lib_infop;
710 	HBA_HANDLE		vendorHandle;
711 	Sun_HBAAdapterCreateWWNFunc	AdapterCreateWWNFunc;
712 
713 	NPIVCHECKLIBRARY();
714 	AdapterCreateWWNFunc = (Sun_HBAAdapterCreateWWNFunc)
715 		dlsym(lib_infop->hLibrary, "Sun_fcAdapterCreateWWN");
716 	if (AdapterCreateWWNFunc != NULL) {
717 		status = ((AdapterCreateWWNFunc)(vendorHandle,
718 		    portindex, nwwn, pwwn, OUI, method));
719 	} else {
720 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
721 	}
722 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
723 }
724 
725 HBA_STATUS
726 Sun_HBA_AdapterReturnWWN (
727     HBA_HANDLE		handle,
728     HBA_UINT32		portindex,
729     HBA_WWN		*nwwn,
730     HBA_WWN		*pwwn)
731 {
732 	HBA_STATUS		status;
733 	HBA_LIBRARY_INFO	*lib_infop;
734 	HBA_HANDLE		vendorHandle;
735 	Sun_HBAAdapterReturnWWNFunc	AdapterReturnWWNFunc;
736 
737 	NPIVCHECKLIBRARY();
738 	AdapterReturnWWNFunc = (Sun_HBAAdapterReturnWWNFunc)
739 		dlsym(lib_infop->hLibrary, "Sun_fcAdapterReturnWWN");
740 	if (AdapterReturnWWNFunc != NULL) {
741 		status = ((AdapterReturnWWNFunc)(vendorHandle,
742 		    portindex, nwwn, pwwn));
743 	} else {
744 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
745 	}
746 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
747 }
748 
749 typedef struct hba_npivadaptercallback_elem {
750     struct hba_npivadaptercallback_elem
751 			*next;
752     HBA_LIBRARY_INFO	*lib_info;
753     void		*userdata;
754     HBA_CALLBACKHANDLE	vendorcbhandle;
755     void		(*callback)();
756 } HBA_NPIVADAPTERCALLBACK_ELEM;
757 extern HBA_NPIVADAPTERCALLBACK_ELEM *_hbaapi_adapterdeviceevents_callback_list;
758 
759 /* Adapter Device Events ********************************************************/
760 static void
761 adapterdeviceevents_callback (void *data,
762     HBA_WWN	PortWWN,
763     HBA_UINT32	eventType,
764     HBA_UINT32	fabricPortID)
765 {
766 	HBA_NPIVADAPTERCALLBACK_ELEM	*acbp;
767 
768 	DEBUG(3, "AdapterDeviceEvent, port:%s, eventType:%d fabricPortID:0X%06x",
769 	    WWN2STR1(&PortWWN), eventType, fabricPortID);
770 
771 	GRAB_MUTEX(&_hbaapi_APE_mutex);
772 
773 	for(acbp = _hbaapi_adapterdeviceevents_callback_list;
774 	    acbp != NULL;
775 	    acbp = acbp->next) {
776 		if(data == (void *)acbp) {
777 			(*acbp->callback)(acbp->userdata, PortWWN, eventType, fabricPortID);
778 			break;
779 		}
780 	}
781 	RELEASE_MUTEX(&_hbaapi_APE_mutex);
782 }
783 
784 HBA_STATUS
785 Sun_HBA_RegisterForAdapterDeviceEvents (
786     void	(*callback) (
787 	void		*data,
788 	HBA_WWN		PortWWN,
789 	HBA_UINT32	eventType,
790 	HBA_UINT32	fabricPortID
791 	),
792     void		*userData,
793     HBA_HANDLE		handle,
794     HBA_WWN		PortWWN,
795     HBA_CALLBACKHANDLE	*callbackHandle)
796 {
797 	HBA_NPIVADAPTERCALLBACK_ELEM	*acbp;
798 	HBA_STATUS			status;
799 	HBA_LIBRARY_INFO		*lib_infop;
800 	HBA_HANDLE			vendorHandle;
801 	Sun_HBARegisterForAdapterDeviceEventsFunc
802 					registeredfunc;
803 
804 	if (callbackHandle == NULL) {
805 		return(HBA_STATUS_ERROR_ARG);
806 	}
807 
808         NPIVCHECKLIBRARY();
809 	registeredfunc = (Sun_HBARegisterForAdapterDeviceEventsFunc)
810                 dlsym(lib_infop->hLibrary,
811 		    "Sun_fcRegisterForAdapterDeviceEvents");
812 	if (registeredfunc == NULL) {
813 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
814 	}
815 
816 	acbp = (HBA_NPIVADAPTERCALLBACK_ELEM *)
817 		calloc(1, sizeof(HBA_NPIVADAPTERCALLBACK_ELEM));
818 
819 	if(acbp == NULL) {
820 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
821 	}
822 
823 	*callbackHandle = (HBA_CALLBACKHANDLE) acbp;
824 	acbp->callback = callback;
825 	acbp->userdata = userData;
826 	acbp->lib_info = lib_infop;
827 
828 	status = (registeredfunc)(adapterdeviceevents_callback,
829 		(void *)acbp,
830 		vendorHandle,
831 		PortWWN,
832 		&acbp->vendorcbhandle);
833 	if(status != HBA_STATUS_OK) {
834 		free(acbp);
835 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
836 	}
837 
838 	GRAB_MUTEX(&_hbaapi_APE_mutex);
839 	acbp->next = _hbaapi_adapterdeviceevents_callback_list;
840 	_hbaapi_adapterdeviceevents_callback_list = acbp;
841 	RELEASE_MUTEX(&_hbaapi_APE_mutex);
842 
843 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
844 }
845