xref: /illumos-gate/usr/src/lib/hbaapi/common/HBAAPILIB.c (revision 5328fc53d11d7151861fa272e4fb0248b8f0e145)
1 /*************************************************************************
2  * Description
3  *	HBAAPILIB.c - Implements a sample common (wrapper) HBA API library
4  *
5  * License:
6  *	The contents of this file are subject to the SNIA Public License
7  *	Version 1.0 (the "License"); you may not use this file except in
8  *	compliance with the License. You may obtain a copy of the License at
9  *
10  *	/http://www.snia.org/English/Resources/Code/OpenSource.html
11  *
12  *	Software distributed under the License is distributed on an "AS IS"
13  *	basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
14  *	the License for the specific language governing rights and limitations
15  *	under the License.
16  *
17  * The Original Code is  SNIA HBA API Wrapper Library
18  *
19  * The Initial Developer of the Original Code is:
20  *	Benjamin F. Kuo, Troika Networks, Inc. (benk@troikanetworks.com)
21  *
22  * Contributor(s):
23  *	Tuan Lam, QLogic Corp. (t_lam@qlc.com)
24  *	Dan Willie, Emulex Corp. (Dan.Willie@emulex.com)
25  *	Dixon Hutchinson, Legato Systems, Inc. (dhutchin@legato.com)
26  *	David Dillard, VERITAS Software Corp. (david.dillard@veritas.com)
27  *
28  *************************************************************************
29  */
30 
31 #ifdef WIN32
32 #include <windows.h>
33 #include <string.h>
34 /*
35  * Next define forces entry points in the dll to be exported
36  * See hbaapi.h to see what it does.
37  */
38 #define HBAAPI_EXPORTS
39 #else
40 #include <dlfcn.h>
41 #include <strings.h>
42 #endif
43 #include <stdio.h>
44 #include <time.h>
45 #include "hbaapi.h"
46 #include "vendorhbaapi.h"
47 #include <stdlib.h>
48 #ifdef USESYSLOG
49 #include <syslog.h>
50 #endif
51 
52 /*
53  * LIBRARY_NUM is a shortcut to figure out which library we need to call.
54  *  The top 16 bits of handle are the library index
55  */
56 #define LIBRARY_NUM(handle)	((handle)>>16)
57 
58 /*
59  * VENDOR_HANDLE turns a global library handle into a vendor specific handle,
60  * with all upper 16 bits set to 0
61  */
62 #define VENDOR_HANDLE(handle)	((handle)&0xFFFF)
63 
64 #define HBA_HANDLE_FROM_LOCAL(library, vendor) \
65 				(((library)<<16) | ((vendor)&0x0000FFFF))
66 
67 int _hbaapi_debuglevel = 0;
68 #define DEBUG(L, STR, A1, A2, A3)
69 
70 #if defined(USESYSLOG) && defined(USELOGFILE)
71 FILE *_hbaapi_debug_fd = NULL;
72 int _hbaapi_sysloginit = 0;
73 #undef DEBUG
74 #ifdef WIN32
75 #define DEBUG(L, STR, A1, A2, A3)\
76     if ((L) <= _hbaapi_debuglevel) {\
77 	if(_hbaapi_sysloginit == 0) {\
78 	    openlog("HBAAPI", LOG_PID|LOG_ODELAY ,LOG_USER);\
79 	    _hbaapi_sysloginit = 1;\
80 	}\
81 	syslog (LOG_INFO, (STR), (A1), (A2), (A3));\
82 	if(_hbaapi_debug_fd == NULL) {\
83 	    char _logFile[MAX_PATH]; \
84 	    GetTempPath(MAX_PATH, _logFile); \
85 	    strcat(_logFile, "HBAAPI.log"); \
86 	    _hbaapi_debug_fd = fopen(_logFile, "a");\
87 	}\
88         if(_hbaapi_debug_fd != NULL) {\
89 	    fprintf(_hbaapi_debug_fd, (STR ## "\n"), (A1), (A2), (A3));\
90 	}\
91     }
92 #else /* WIN32*/
93 #define DEBUG(L, STR, A1, A2, A3)\
94     if ((L) <= _hbaapi_debuglevel) {\
95 	if(_hbaapi_sysloginit == 0) {\
96 	    openlog("HBAAPI", LOG_PID|LOG_ODELAY ,LOG_USER);\
97 	    _hbaapi_sysloginit = 1;\
98 	}\
99 	syslog (LOG_INFO, (STR), (A1), (A2), (A3));\
100 	if(_hbaapi_debug_fd == NULL) {\
101 	    _hbaapi_debug_fd = fopen("/tmp/HBAAPI.log", "a");\
102 	}\
103         if(_hbaapi_debug_fd != NULL) {\
104 	    fprintf(_hbaapi_debug_fd, (STR ## "\n"), (A1), (A2), (A3));\
105 	}\
106     }
107 #endif /* WIN32*/
108 
109 #else /* Not both USESYSLOG and USELOGFILE */
110 #if defined(USESYSLOG)
111 int _hbaapi_sysloginit = 0;
112 #undef DEBUG
113 #define DEBUG(L, STR, A1, A2, A3) \
114     if ((L) <= _hbaapi_debuglevel) {\
115 	if(_hbaapi_sysloginit == 0) {\
116 	    openlog("HBAAPI", LOG_PID|LOG_ODELAY ,LOG_USER);\
117 	    _hbaapi_sysloginit = 1;\
118 	}\
119 	syslog (LOG_INFO, (STR), (A1), (A2), (A3));\
120     }
121 #endif /* USESYSLOG */
122 #if defined(USELOGFILE)
123 FILE *_hbaapi_debug_fd = NULL;
124 #undef DEBUG
125 #ifdef WIN32
126 #define DEBUG(L, STR, A1, A2, A3) \
127     if((L) <= _hbaapi_debuglevel) {\
128 	if(_hbaapi_debug_fd == NULL) {\
129 	    char _logFile[MAX_PATH]; \
130 	    GetTempPath(MAX_PATH, _logFile); \
131 	    strcat(_logFile, "HBAAPI.log"); \
132 	    _hbaapi_debug_fd = fopen(_logFile, "a");\
133         }\
134     }
135 #else /* WIN32 */
136 #define DEBUG(L, STR, A1, A2, A3) \
137     if((L) <= _hbaapi_debuglevel) {\
138 	if(_hbaapi_debug_fd == NULL) {\
139 	    _hbaapi_debug_fd = fopen("/tmp/HBAAPI.log", "a");\
140 	}\
141 	if(_hbaapi_debug_fd != NULL) { \
142 	    fprintf(_hbaapi_debug_fd, (STR) ## "\n", (A1), (A2), (A3));\
143 	}\
144     }
145 #endif /* WIN32 */
146 #endif /* USELOGFILE */
147 #endif /* Not both USELOGFILE and USESYSLOG */
148 
149 #ifdef POSIX_THREADS
150 #include <pthread.h>
151 /*
152  * When multiple mutex's are grabed, they must be always be grabbed in
153  * the same order, or deadlock can result.  There are three levels
154  * of mutex's involved in this API.  If LL_mutex is grabbed, always grap
155  * it first.  If AL_mutex is grabbed, it may not be grabbed before
156  * LL_mutex.  If grabbed in a multi grab sequence, the mutex's protecting
157  * the callback lists must always be grabbed last and release before calling
158  * a vendor specific library function that might invoke a callback function
159  * on the same thread.
160  */
161 #define GRAB_MUTEX(M)			grab_mutex(M)
162 #define RELEASE_MUTEX(M)		release_mutex(M)
163 #define RELEASE_MUTEX_RETURN(M,RET)	release_mutex(M); return(RET)
164 #elif defined (WIN32)
165 #define GRAB_MUTEX(m)			EnterCriticalSection(m)
166 #define RELEASE_MUTEX(m)		LeaveCriticalSection(m)
167 #define RELEASE_MUTEX_RETURN(m, RET)	LeaveCriticalSection(m); return(RET)
168 #else
169 #define GRAB_MUTEX(M)
170 #define RELEASE_MUTEX(M)
171 #define RELEASE_MUTEX_RETURN(M,RET)	return(RET)
172 #endif
173 
174 /*
175  * Vendor library information
176  */
177 typedef enum {
178     HBA_LIBRARY_UNKNOWN,
179     HBA_LIBRARY_LOADED,
180     HBA_LIBRARY_NOT_LOADED
181 } HBA_LIBRARY_STATUS;
182 
183 typedef struct hba_library_info {
184     struct hba_library_info
185 			*next;
186 #ifdef WIN32
187     HINSTANCE		hLibrary;		/* Handle to a loaded DLL */
188 #else
189     char		*LibraryName;
190     void*		hLibrary;		/* Handle to a loaded DLL */
191 #endif
192     char		*LibraryPath;
193     HBA_ENTRYPOINTSV2	functionTable;		/* Function pointers */
194     HBA_LIBRARY_STATUS	status;			/* info on this library */
195     HBA_UINT32		index;
196 } HBA_LIBRARY_INFO, *PHBA_LIBRARY_INFO;
197 
198 #define ARE_WE_INITED() \
199 	if (_hbaapi_librarylist == NULL) { \
200 		return(HBA_STATUS_ERROR); \
201 	}
202 HBA_LIBRARY_INFO *_hbaapi_librarylist = NULL;
203 HBA_UINT32 _hbaapi_total_library_count = 0;
204 #ifdef POSIX_THREADS
205 pthread_mutex_t _hbaapi_LL_mutex = PTHREAD_MUTEX_INITIALIZER;
206 #elif defined(WIN32)
207 CRITICAL_SECTION _hbaapi_LL_mutex;
208 #endif
209 
210 /*
211  * Individual adapter (hba) information
212  */
213 typedef struct hba_adapter_info {
214     struct hba_adapter_info
215 			*next;
216     HBA_STATUS		GNstatus;	/* status from GetAdapterNameFunc */
217     char		*name;
218     HBA_WWN		nodeWWN;
219     HBA_LIBRARY_INFO	*library;
220     HBA_UINT32		index;
221 } HBA_ADAPTER_INFO;
222 
223 HBA_ADAPTER_INFO *_hbaapi_adapterlist = NULL;
224 HBA_UINT32 _hbaapi_total_adapter_count = 0;
225 #ifdef POSIX_THREADS
226 pthread_mutex_t _hbaapi_AL_mutex = PTHREAD_MUTEX_INITIALIZER;
227 #elif defined(WIN32)
228 CRITICAL_SECTION _hbaapi_AL_mutex;
229 #endif
230 
231 /*
232  * Call back registration
233  */
234 typedef struct hba_vendorcallback_elem {
235     struct hba_vendorcallback_elem
236 				*next;
237     HBA_CALLBACKHANDLE		vendorcbhandle;
238     HBA_LIBRARY_INFO		*lib_info;
239 } HBA_VENDORCALLBACK_ELEM;
240 
241 /*
242  * Each instance of HBA_ADAPTERCALLBACK_ELEM represents a call to one of
243  * "register" functions that apply to a particular adapter.
244  * HBA_ALLADAPTERSCALLBACK_ELEM is used just for HBA_RegisterForAdapterAddEvents
245  */
246 typedef struct hba_adaptercallback_elem {
247     struct hba_adaptercallback_elem
248 			*next;
249     HBA_LIBRARY_INFO	*lib_info;
250     void		*userdata;
251     HBA_CALLBACKHANDLE	vendorcbhandle;
252     void		(*callback)();
253 } HBA_ADAPTERCALLBACK_ELEM;
254 
255 typedef struct hba_alladapterscallback_elem {
256     struct hba_alladapterscallback_elem
257 				*next;
258     void			*userdata;
259     HBA_VENDORCALLBACK_ELEM	*vendorhandlelist;
260     void			(*callback)();
261 } HBA_ALLADAPTERSCALLBACK_ELEM;
262 
263 HBA_ALLADAPTERSCALLBACK_ELEM *_hbaapi_adapteraddevents_callback_list = NULL;
264 HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterevents_callback_list = NULL;
265 HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterportevents_callback_list = NULL;
266 HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterportstatevents_callback_list = NULL;
267 HBA_ADAPTERCALLBACK_ELEM *_hbaapi_targetevents_callback_list = NULL;
268 HBA_ADAPTERCALLBACK_ELEM *_hbaapi_linkevents_callback_list = NULL;
269 HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterdeviceevents_callback_list = NULL;
270 #ifdef POSIX_THREADS
271 /* mutex's to protect each list */
272 pthread_mutex_t _hbaapi_AAE_mutex = PTHREAD_MUTEX_INITIALIZER;
273 pthread_mutex_t _hbaapi_AE_mutex = PTHREAD_MUTEX_INITIALIZER;
274 pthread_mutex_t _hbaapi_APE_mutex = PTHREAD_MUTEX_INITIALIZER;
275 pthread_mutex_t _hbaapi_APSE_mutex = PTHREAD_MUTEX_INITIALIZER;
276 pthread_mutex_t _hbaapi_TE_mutex = PTHREAD_MUTEX_INITIALIZER;
277 pthread_mutex_t _hbaapi_LE_mutex = PTHREAD_MUTEX_INITIALIZER;
278 #elif defined(WIN32)
279 CRITICAL_SECTION _hbaapi_AAE_mutex;
280 CRITICAL_SECTION _hbaapi_AE_mutex;
281 CRITICAL_SECTION _hbaapi_APE_mutex;
282 CRITICAL_SECTION _hbaapi_APSE_mutex;
283 CRITICAL_SECTION _hbaapi_TE_mutex;
284 CRITICAL_SECTION _hbaapi_LE_mutex;
285 #endif
286 
287 HBA_ADAPTERCALLBACK_ELEM **cb_lists_array[] = {
288     &_hbaapi_adapterevents_callback_list,
289     &_hbaapi_adapterportevents_callback_list,
290     &_hbaapi_adapterportstatevents_callback_list,
291     &_hbaapi_targetevents_callback_list,
292     &_hbaapi_linkevents_callback_list,
293     &_hbaapi_adapterdeviceevents_callback_list,
294     NULL};
295 
296 /*
297  * Common library internal. Mutex handling
298  */
299 #ifdef POSIX_THREADS
300 static void
301 grab_mutex(pthread_mutex_t *mp) {
302     int ret;
303     if((ret = pthread_mutex_lock(mp)) != 0) {
304 	perror("pthread_mutex_lock - HBAAPI:");
305 	DEBUG(0, "pthread_mutex_lock returned %d", ret, 0, 0);
306     }
307 }
308 
309 static void
310 release_mutex(pthread_mutex_t *mp) {
311     int ret;
312     if((ret = pthread_mutex_unlock(mp)) != 0) {
313 	perror("pthread_mutex_unlock - HBAAPI:");
314 	DEBUG(0, "pthread_mutex_unlock returned %d", ret, 0, 0);
315     }
316 }
317 #endif
318 
319 /*
320  * Common library internal. Check library and return vendorhandle
321  */
322 static HBA_STATUS
323 HBA_CheckLibrary(HBA_HANDLE handle,
324 		 HBA_LIBRARY_INFO **lib_infopp,
325 		 HBA_HANDLE *vendorhandle) {
326 
327     HBA_UINT32		libraryIndex;
328     HBA_LIBRARY_INFO	*lib_infop;
329 
330     if (vendorhandle == NULL) {
331 	return(HBA_STATUS_ERROR_ARG);
332     }
333     if(_hbaapi_librarylist == NULL) {
334 	return(HBA_STATUS_ERROR);
335     }
336     libraryIndex = LIBRARY_NUM(handle);
337 
338     GRAB_MUTEX(&_hbaapi_LL_mutex);
339     for(lib_infop = _hbaapi_librarylist;
340 	lib_infop != NULL;
341 	lib_infop = lib_infop->next) {
342 	if(lib_infop->index == libraryIndex) {
343 	    if(lib_infop->status != HBA_LIBRARY_LOADED) {
344 		return HBA_STATUS_ERROR;
345 	    }
346 	    *lib_infopp = lib_infop;
347 	    *vendorhandle = VENDOR_HANDLE(handle);
348 	    /* caller will release the mutex */
349 	    return HBA_STATUS_OK;
350 	}
351     }
352     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INVALID_HANDLE);
353 }
354 #define CHECKLIBRARY() \
355 	status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);\
356  	if(status != HBA_STATUS_OK) { \
357 	    return(status); \
358  	}
359 
360 /*
361  *freevendorhandlelist is called with _hbaapi_LL_mutex already held
362  */
363 static void
364 freevendorhandlelist(HBA_VENDORCALLBACK_ELEM *vhlist) {
365     HBA_VENDORCALLBACK_ELEM	*vhlp;
366     HBA_VENDORCALLBACK_ELEM	*vnext;
367     HBARemoveCallbackFunc	registeredfunc;
368 
369     for(vhlp = vhlist; vhlp != NULL; vhlp = vnext) {
370 	vnext = vhlp->next;
371 	registeredfunc =
372 	    vhlp->lib_info->functionTable.RemoveCallbackHandler;
373 	if(registeredfunc == NULL) {
374 	    continue;
375 	}
376 	(registeredfunc)(vhlp->vendorcbhandle);
377 	free(vhlp);
378     }
379 }
380 
381 static
382 HBA_STATUS
383 local_remove_callback(HBA_CALLBACKHANDLE cbhandle) {
384     HBA_ADAPTERCALLBACK_ELEM		***listp;
385     HBA_ADAPTERCALLBACK_ELEM		**lastp;
386     HBA_ALLADAPTERSCALLBACK_ELEM	**lap;
387     HBA_ALLADAPTERSCALLBACK_ELEM	*allcbp;
388     HBA_ADAPTERCALLBACK_ELEM		*cbp;
389     HBARemoveCallbackFunc		registeredfunc;
390     HBA_VENDORCALLBACK_ELEM		*vhlp;
391     HBA_VENDORCALLBACK_ELEM		*vnext;
392     int					found;
393     HBA_STATUS				status = HBA_STATUS_ERROR_INVALID_HANDLE;
394 
395 
396     /* search through the simple lists first */
397     GRAB_MUTEX(&_hbaapi_AAE_mutex);
398     GRAB_MUTEX(&_hbaapi_AE_mutex);
399     GRAB_MUTEX(&_hbaapi_APE_mutex);
400     GRAB_MUTEX(&_hbaapi_APSE_mutex);
401     GRAB_MUTEX(&_hbaapi_TE_mutex);
402     GRAB_MUTEX(&_hbaapi_LE_mutex);
403     for(listp = cb_lists_array, found = 0; found == 0, *listp != NULL; listp++) {
404 	lastp = *listp;
405 	for(cbp=**listp; cbp != NULL; cbp = cbp->next) {
406 	    if(cbhandle != (HBA_CALLBACKHANDLE)cbp) {
407 		lastp = &(cbp->next);
408 		continue;
409 	    }
410 	    found = 1;
411 	    registeredfunc = cbp->lib_info->functionTable.RemoveCallbackHandler;
412 	    if(registeredfunc == NULL) {
413 		break;
414 	    }
415 	    (registeredfunc)(cbp->vendorcbhandle);
416 	    *lastp = cbp->next;
417 	    free(cbp);
418 	    break;
419 	}
420     }
421     RELEASE_MUTEX(&_hbaapi_LE_mutex);
422     RELEASE_MUTEX(&_hbaapi_TE_mutex);
423     RELEASE_MUTEX(&_hbaapi_APSE_mutex);
424     RELEASE_MUTEX(&_hbaapi_APE_mutex);
425     RELEASE_MUTEX(&_hbaapi_AE_mutex);
426     RELEASE_MUTEX(&_hbaapi_AAE_mutex);
427     if(found != 0) {
428 	if(registeredfunc == NULL) {
429 	    return HBA_STATUS_ERROR_NOT_SUPPORTED;
430 	}
431 	return HBA_STATUS_OK;
432     }
433 
434     GRAB_MUTEX(&_hbaapi_AAE_mutex);
435     /* if it wasnt in the simple lists, look in the list for adapteraddevents */
436     lap = &_hbaapi_adapteraddevents_callback_list;
437     for(allcbp = _hbaapi_adapteraddevents_callback_list;
438 	allcbp != NULL;
439 	allcbp = allcbp->next) {
440 	if(cbhandle != (HBA_CALLBACKHANDLE)allcbp) {
441 	    lap = &allcbp->next;
442 	    continue;
443 	}
444 	for(vhlp = allcbp->vendorhandlelist; vhlp != NULL; vhlp = vnext) {
445 	    vnext = vhlp->next;
446 	    registeredfunc =
447 		vhlp->lib_info->functionTable.RemoveCallbackHandler;
448 	    if(registeredfunc == NULL) {
449 		continue;
450 	    }
451 	    (registeredfunc)(vhlp->vendorcbhandle);
452 	    free(vhlp);
453 	}
454 	*lap = allcbp->next;
455 	free(allcbp);
456 	status = HBA_STATUS_OK;
457 	break;
458     }
459     RELEASE_MUTEX(&_hbaapi_AAE_mutex);
460     return(status);
461 }
462 
463 static char wwn_str1[17];
464 static char wwn_str2[17];
465 static char wwn_str3[17];
466 #define WWN2STR1(wwn) WWN2str(wwn_str1, (wwn))
467 #define WWN2STR2(wwn) WWN2str(wwn_str2, (wwn))
468 #define WWN2STR3(wwn) WWN2str(wwn_str3, (wwn))
469 static char *
470 WWN2str(char *buf, HBA_WWN *wwn) {
471     int j;
472     unsigned char *pc = (unsigned char *)&(wwn->wwn[0]);
473     buf[0] = '\0';
474     for (j=0; j<16; j+=2) {
475         sprintf(&buf[j], "%02X", (int)*pc++);
476     }
477     return(buf);
478 }
479 
480 
481 #ifdef WIN32
482 BOOL APIENTRY
483 DllMain( HANDLE hModule,
484 	 DWORD  ul_reason_for_call,
485 	 LPVOID lpReserved
486     )
487 {
488     switch (ul_reason_for_call)
489     {
490     case DLL_PROCESS_ATTACH:
491 	break;
492     case DLL_PROCESS_DETACH:
493 	break;
494     case DLL_THREAD_ATTACH:
495     case DLL_THREAD_DETACH:
496 	break;
497     }
498     return TRUE;
499 }
500 #endif
501 
502 /*
503  * Read in the config file and load all the specified vendor specific
504  * libraries and perform the function registration exercise
505  */
506 HBA_STATUS
507 HBA_LoadLibrary(void) {
508     HBARegisterLibraryFunc
509 			RegisterFunc;
510     HBARegisterLibraryV2Func
511 			RegisterV2Func;
512     HBALoadLibraryFunc	LoadLibraryFunc;
513     HBAGetVersionFunc	GetVersionFunc;
514 #ifdef POSIX_THREADS
515     int			ret;
516 #endif
517     HBA_STATUS		status;
518 #ifdef NOTDEF
519     HBA_UINT32		libversion;
520 #endif
521 
522     /* Open configuration file from known location */
523 #ifdef WIN32
524     LONG		lStatus;
525     HKEY		hkSniaHba, hkVendorLib;
526     FILETIME		ftLastWriteTime;
527     TCHAR		cSubKeyName[256];
528     DWORD		i, dwSize, dwType;
529     BYTE		byFileName[MAX_PATH];
530     HBA_LIBRARY_INFO	*lib_infop;
531 
532     if(_hbaapi_librarylist != NULL) {
533 	/* this is an app programming error */
534 	return HBA_STATUS_ERROR;
535     }
536 
537     lStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\SNIA\\HBA",
538 			   0, KEY_READ, &hkSniaHba);
539     if (lStatus != ERROR_SUCCESS) {
540 	/* ???Opportunity to send error msg, configuration error */
541 	return HBA_STATUS_ERROR;
542     }
543     /*
544      * Enumerate all the subkeys. These have the form:
545      * HKLM\Software\SNIA\HBA\<Vendor id> - note that we don't care
546      * what the vendor id is
547      */
548     for (i = 0; ; i++) {
549 	dwSize = 255;	/* how big the buffer is */
550 	lStatus = RegEnumKeyEx(hkSniaHba, i,
551 			       (char *)&cSubKeyName, &dwSize, NULL,
552 			       NULL, NULL, &ftLastWriteTime);
553 	if (lStatus == ERROR_NO_MORE_ITEMS) {
554 	    break;	/* we're done */
555 	} else if (lStatus == ERROR_MORE_DATA) { /* buffer not big enough */
556 	    /* do whatever */
557 	    ;
558 	}
559 	/* Now open the subkey that pertains to this vendor's library */
560 	lStatus = RegOpenKeyEx(hkSniaHba, cSubKeyName, 0, KEY_READ,
561 			       &hkVendorLib);
562 	if (lStatus != ERROR_SUCCESS) {
563 	    RegCloseKey(hkSniaHba);
564 	    /* ???Opportunity to send error msg, installation error */
565 	    return HBA_STATUS_ERROR; /* you may want to return something
566 				      * else or keep trying */
567 	}
568 	/* The name of the library is contained in a REG_SZ Value
569 	 * keyed to "LibraryFile" */
570 	dwSize = MAX_PATH;
571 	lStatus = RegQueryValueEx(hkVendorLib, "LibraryFile", NULL, &dwType,
572 				  byFileName, &dwSize);
573 	if (lStatus != ERROR_SUCCESS) {
574 	    RegCloseKey(hkVendorLib);
575 	    /* ???Opportunity to send error msg, installation error */
576 	    continue;
577 	}
578 	lib_infop = (HBA_LIBRARY_INFO *)calloc(1, sizeof(HBA_LIBRARY_INFO));
579 	if(lib_infop == NULL) {
580 	    /* what is the right thing to do in MS land??? */
581 	    RegCloseKey(hkVendorLib);
582 	    /* ???Opportunity to send error msg, installation error */
583 	    return(HBA_STATUS_ERROR);
584 	}
585 	lib_infop->status = HBA_LIBRARY_NOT_LOADED;
586 	lib_infop->next = _hbaapi_librarylist;
587 	lib_infop->index = _hbaapi_total_library_count;
588 	_hbaapi_total_library_count++;
589 	_hbaapi_librarylist = lib_infop;
590 
591 	/* Now I can try to load the library */
592 	lib_infop->hLibrary = LoadLibrary(byFileName);
593 	if (lib_infop->hLibrary == NULL){
594 	    /* printf("unable to load library %s\n", librarypath); */
595 	    /* ???Opportunity to send error msg, installation error */
596 	    goto dud_library;
597 	}
598 	lib_infop->LibraryPath = strdup(byFileName);
599 	DEBUG(1, "HBAAPI loading: %s\n", byFileName, 0, 0);
600 
601 	/* Call the registration function to get the list of pointers */
602 	RegisterV2Func = (HBARegisterLibraryV2Func)
603 	    GetProcAddress(lib_infop->hLibrary, "HBA_RegisterLibraryV2");
604 	if (RegisterV2Func != NULL) {
605 	    /* Load the function pointers directly into
606 	     * the table of functions */
607 	    status = ((RegisterV2Func)(&lib_infop->functionTable));
608 	    if (status != HBA_STATUS_OK) {
609 		/* library not loaded */
610 		/* ???Opportunity to send error msg, library error? */
611 		goto dud_library;
612 	    }
613 	} else {
614 	    /* Maybe the vendor library is only Rev1 */
615 	    RegisterFunc = (HBARegisterLibraryFunc)
616 		GetProcAddress(lib_infop->hLibrary, "HBA_RegisterLibrary");
617 	    if(RegisterFunc == NULL) {
618 		/* ???Opportunity to send error msg, library error? */
619 		goto dud_library;
620 	    }
621 	    /* Load the function points directly into
622 	     * the Rev 2 table of functions */
623 	    status = ((RegisterFunc)(
624 		(HBA_ENTRYPOINTS *)(&lib_infop->functionTable)));
625 	    if (status != HBA_STATUS_OK) {
626 		/* library not loaded */
627 		/* ???Opportunity to send error msg, library error? */
628 		goto dud_library;
629 	    }
630 	}
631 
632 	/* successfully loaded library */
633 	GetVersionFunc = lib_infop->functionTable.GetVersionHandler;
634 	if (GetVersionFunc == NULL) {
635 	    /* ???Opportunity to send error msg, library error? */
636 	    goto dud_library;
637 	}
638 #ifdef NOTDEF /* save for a later time... when it matters */
639 	/* Check the version of this library before loading */
640 	/* Actually... This wrapper is compatible with version 1 */
641 	libversion = ((GetVersionFunc)());
642 	if (libversion < HBA_LIBVERSION) {
643 	    goto dud_library;
644 	}
645 #endif
646 	LoadLibraryFunc = lib_infop->functionTable.LoadLibraryHandler;
647 	if (LoadLibraryFunc == NULL) {
648 	    /* Hmmm, dont we need to flag this in a realy big way??? */
649 	    /* How about messages to the system event logger ??? */
650 	    /* ???Opportunity to send error msg, library error? */
651 	    goto dud_library;
652 	}
653 	/* Initialize this library */
654 	status = ((LoadLibraryFunc)());
655 	if (status != HBA_STATUS_OK) {
656 	    /* ???Opportunity to send error msg, library error? */
657 	    continue;
658 	}
659 	/* successfully loaded library */
660 	lib_infop->status = HBA_LIBRARY_LOADED;
661 
662     dud_library: /* its also just the end of the loop */
663 	RegCloseKey(hkVendorLib);
664     }
665     RegCloseKey(hkSniaHba);
666 
667 #else /* Unix as opposed to Win32 */
668     FILE		*hbaconf;
669     char		fullline[512];		/* line read from HBA.conf */
670     char		*libraryname;		/* Read in from file HBA.conf */
671     char		*librarypath;		/* Read in from file HBA.conf */
672     char		hbaConfFilePath[256];
673     char		*charPtr;
674     HBA_LIBRARY_INFO	*lib_infop;
675 
676     if(_hbaapi_librarylist != NULL) {
677 	fprintf(stderr,
678 		"HBA_LoadLibrary: previously unfreed "
679 		"libraries exist, call HBA_FreeLibrary().\n");
680 	return HBA_STATUS_ERROR;
681     }
682 
683     strcpy(hbaConfFilePath, "/etc/hba.conf");
684 
685     if ((hbaconf = fopen(hbaConfFilePath, "r")) == NULL) {
686 	printf("Cannot open %s\n", hbaConfFilePath);
687 	return HBA_STATUS_ERROR;
688     }
689 
690     /* Read in each line and load library */
691     while ((hbaconf != NULL) && (fgets(fullline, sizeof(fullline), hbaconf))) {
692 	/* Skip the comments... */
693 	if ((fullline[0] == '#') || (fullline[0] == '\n')) {
694 	    continue;
695 	}
696 
697 	/* grab first 'thing' in line (if its there)*/
698 	if((libraryname = strtok(fullline, " \t\n")) != NULL) {
699 	    if(strlen(libraryname) >= 64) {
700 		fprintf(stderr, "Library name(%s) in %s is > 64 characters\n",
701 			libraryname, hbaConfFilePath);
702 	    }
703 	}
704 	/* grab second 'thing' in line (if its there)*/
705 	if((librarypath = strtok(NULL, " \t\n")) != NULL) {
706 	    if(strlen(librarypath) >= 256) {
707 		fprintf(stderr, "Library path(%s) in %s is > 256 characters\n",
708 			librarypath, hbaConfFilePath);
709 	    }
710 	}
711 
712 	/* there should be no more 'things' in the line */
713 	if((charPtr = strtok(NULL, " \n\t")) != NULL) {
714 	    fprintf(stderr, "Extraneous characters (\"%s\") in %s\n",
715 		    charPtr, hbaConfFilePath);
716 	}
717 
718 	/* Continue to the next line if library name or path is invalid */
719 	if (libraryname == NULL ||
720 	    strlen(libraryname) == 0 ||
721 	    librarypath == NULL ||
722 	    (strlen(librarypath) == 0)) {
723 	    continue;
724 	}
725 	/*
726 	 * Special case....
727 	 * Look for loglevel
728 	 */
729 	if(strcmp(libraryname, "debuglevel") == 0) {
730 	    _hbaapi_debuglevel = strtol(librarypath, NULL, 10);
731 	    /* error handling does the right thing automagically */
732 	    continue;
733 	}
734 
735 	lib_infop = (HBA_LIBRARY_INFO *)calloc(1, sizeof(HBA_LIBRARY_INFO));
736 	if(lib_infop == NULL) {
737 	    fprintf(stderr, "HBA_LoadLibrary: out of memeory\n");
738 	    return(HBA_STATUS_ERROR);
739 	}
740 	lib_infop->status = HBA_LIBRARY_NOT_LOADED;
741 	lib_infop->LibraryName = strdup(libraryname);
742 	lib_infop->LibraryPath = strdup(librarypath);
743 	lib_infop->index = _hbaapi_total_library_count;
744 	_hbaapi_total_library_count++;
745 	lib_infop->next = _hbaapi_librarylist;
746 	_hbaapi_librarylist = lib_infop;
747 
748 	/* Load the DLL now */
749 	if((lib_infop->hLibrary = dlopen(librarypath,RTLD_LAZY)) == NULL) {
750 	    /*printf("unable to load library %s\n", librarypath); */
751 	    continue;
752 	}
753 	/* Call the registration function to get the list of pointers */
754 	RegisterV2Func = (HBARegisterLibraryV2Func)
755 	    dlsym(lib_infop->hLibrary, "HBA_RegisterLibraryV2");
756 	if (RegisterV2Func != NULL) {
757 	    /* Load the function points directly into
758 	     * the table of functions */
759 	    status = ((RegisterV2Func)(&lib_infop->functionTable));
760 	    if (status != HBA_STATUS_OK) {
761 		/* library not loaded */
762 		continue;
763 	    }
764 	} else {
765 	    /* Maybe the vendor library is only Rev1 */
766 	    RegisterFunc = (HBARegisterLibraryFunc)
767 		dlsym(lib_infop->hLibrary, "HBA_RegisterLibrary");
768 	    if(RegisterFunc == NULL) {
769 		/* This function is required */
770 		fprintf(stderr,
771 			"HBA_LoadLibrary: vendor specific RegisterLibrary "
772 			"function not found.  lib: %s\n", librarypath);
773 		DEBUG(0, "HBA_LoadLibrary: vendor specific RegisterLibrary "
774 		      "function not found.  lib: %s\n", librarypath, 0, 0);
775 		continue;
776 	    }
777 	    /* Load the function points directly into
778 	     * the table of functions */
779 	    status = ((RegisterFunc)
780 		      ((HBA_ENTRYPOINTS *)(&lib_infop->functionTable)));
781 	    if (status != HBA_STATUS_OK) {
782 		/* library not loaded */
783 		fprintf(stderr,
784 			"HBA_LoadLibrary: vendor specific RegisterLibrary "
785 			"function encountered an error.  lib: %s\n", librarypath);
786 		DEBUG(0, "HBA_LoadLibrary: vendor specific RegisterLibrary "
787 		      "function encountered an error. lib: %s\n", librarypath, 0, 0);
788 		continue;
789 	    }
790 	}
791 
792 	/* successfully loaded library */
793 	if((GetVersionFunc = lib_infop->functionTable.GetVersionHandler)
794 	   == NULL) {
795 	    continue;
796 	}
797 #ifdef NOTDEF /* save for a later time... when it matters */
798 	libversion = ((GetVersionFunc)());
799 	/* Check the version of this library before loading */
800 	/* Actually... This wrapper is compatible with version 1 */
801 	if(libversion < HBA_LIBVERSION) {
802 	    printf("Library version mismatch. Got %d expected %d.\n",
803 		   libversion, HBA_LIBVERSION);
804 	    continue;
805 	}
806 	DEBUG(1, "%s libversion = %d", librarypath, libversion, 0);
807 #endif
808 	LoadLibraryFunc = lib_infop->functionTable.LoadLibraryHandler;
809 	if (LoadLibraryFunc == NULL) {
810 	    /* this function is required */
811 	    fprintf(stderr,
812 		    "HBA_LoadLibrary: vendor specific LoadLibrary "
813 		    "function not found.  lib: %s\n", librarypath);
814 	    DEBUG(0, "HBA_LoadLibrary: vendor specific LoadLibrary "
815 		    "function not found.  lib: %s\n", librarypath, 0, 0);
816 	    continue;
817 	}
818 	/* Initialize this library */
819 	if((status = ((LoadLibraryFunc)())) != HBA_STATUS_OK) {
820 	    /* maybe this should be a printf so that we CANNOT miss it */
821 	    fprintf(stderr,
822 		    "HBA_LoadLibrary: Encounterd and error loading: %s",
823 		    librarypath);
824 	    DEBUG(0, "Encounterd and error loading: %s", librarypath, 0, 0);
825 	    DEBUG(0, "  HBA_STATUS: %d", status, 0, 0);
826 	    continue;
827 	}
828 	/* successfully loaded library */
829 	lib_infop->status = HBA_LIBRARY_LOADED;
830     }
831 
832     fclose(hbaconf);
833 #endif /* WIN32 or UNIX */
834 #ifdef POSIX_THREADS
835     ret = pthread_mutex_init(&_hbaapi_LL_mutex, NULL);
836     if(ret == 0) {
837 	ret = pthread_mutex_init(&_hbaapi_AL_mutex, NULL);
838     }
839     if(ret == 0) {
840 	ret = pthread_mutex_init(&_hbaapi_AAE_mutex, NULL);
841     }
842     if(ret == 0) {
843 	ret = pthread_mutex_init(&_hbaapi_AE_mutex, NULL);
844     }
845     if(ret == 0) {
846 	ret = pthread_mutex_init(&_hbaapi_APE_mutex, NULL);
847     }
848     if(ret == 0) {
849 	ret = pthread_mutex_init(&_hbaapi_APSE_mutex, NULL);
850     }
851     if(ret == 0) {
852 	ret = pthread_mutex_init(&_hbaapi_TE_mutex, NULL);
853     }
854     if(ret == 0) {
855 	ret = pthread_mutex_init(&_hbaapi_LE_mutex, NULL);
856     }
857     if(ret != 0) {
858 	perror("pthread_mutec_init - HBA_LoadLibrary");
859 	return(HBA_STATUS_ERROR);
860     }
861 #elif defined(WIN32)
862     InitializeCriticalSection(&_hbaapi_LL_mutex);
863     InitializeCriticalSection(&_hbaapi_AL_mutex);
864     InitializeCriticalSection(&_hbaapi_AAE_mutex);
865     InitializeCriticalSection(&_hbaapi_AE_mutex);
866     InitializeCriticalSection(&_hbaapi_APE_mutex);
867     InitializeCriticalSection(&_hbaapi_APSE_mutex);
868     InitializeCriticalSection(&_hbaapi_TE_mutex);
869     InitializeCriticalSection(&_hbaapi_LE_mutex);
870 #endif
871 
872 
873     return HBA_STATUS_OK;
874 }
875 
876 HBA_STATUS
877 HBA_FreeLibrary(void) {
878     HBAFreeLibraryFunc	FreeLibraryFunc;
879     HBA_LIBRARY_INFO	*lib_infop;
880     HBA_LIBRARY_INFO	*lib_next;
881     HBA_ADAPTERCALLBACK_ELEM
882 			***listp;
883     HBA_ADAPTER_INFO	*adapt_infop;
884     HBA_ADAPTER_INFO	*adapt_next;
885 
886     ARE_WE_INITED();
887     GRAB_MUTEX(&_hbaapi_LL_mutex);
888     GRAB_MUTEX(&_hbaapi_AL_mutex);
889 
890     DEBUG(1, "HBA_FreeLibrary()", 0, 0, 0);
891     for(lib_infop = _hbaapi_librarylist; lib_infop != NULL; lib_infop = lib_next) {
892 	lib_next = lib_infop->next;
893 	if (lib_infop->status == HBA_LIBRARY_LOADED) {
894 	    FreeLibraryFunc = lib_infop->functionTable.FreeLibraryHandler;
895 	    if (FreeLibraryFunc != NULL) {
896 		/* Free this library */
897 		(void)((FreeLibraryFunc)());
898 	    }
899 #ifdef WIN32
900 	    FreeLibrary(lib_infop->hLibrary);	/* Unload DLL from memory */
901 #else
902 	    dlclose(lib_infop->hLibrary);	/* Unload DLL from memory */
903 #endif
904 	}
905 #ifndef WIN32
906 	free(lib_infop->LibraryName);
907 #endif
908 	free(lib_infop->LibraryPath);
909 	free(lib_infop);
910 
911     }
912     _hbaapi_librarylist = NULL;
913     /* OK, now all functions are disabled except for LoadLibrary,
914      * Hope no other thread calls it before we have returned */
915     _hbaapi_total_library_count = 0;
916 
917     for(adapt_infop = _hbaapi_adapterlist;
918 	adapt_infop != NULL;
919 	adapt_infop = adapt_next) {
920 	adapt_next = adapt_infop->next;
921 	free(adapt_infop->name);
922 	free(adapt_infop);
923     }
924     _hbaapi_adapterlist = NULL;
925     _hbaapi_total_adapter_count = 0;
926 
927     /* Free up the callbacks, this is not the most efficient, but it works */
928     while((volatile HBA_ADAPTERCALLBACK_ELEM *)
929 	  _hbaapi_adapteraddevents_callback_list
930 	  != NULL) {
931 	local_remove_callback((HBA_CALLBACKHANDLE)
932 			   _hbaapi_adapteraddevents_callback_list);
933     }
934     for(listp = cb_lists_array; *listp != NULL; listp++) {
935 	while((volatile HBA_ADAPTERCALLBACK_ELEM ***)**listp != NULL) {
936 	    local_remove_callback((HBA_CALLBACKHANDLE)**listp);
937 	}
938     }
939 
940     RELEASE_MUTEX(&_hbaapi_AL_mutex);
941     RELEASE_MUTEX(&_hbaapi_LL_mutex);
942 
943 #ifdef USESYSLOG
944     closelog();
945 #endif
946 #ifdef USELOGFILE
947     if(_hbaapi_debug_fd != NULL) {
948 	fclose(_hbaapi_debug_fd);
949     }
950     _hbaapi_debug_fd = NULL;
951 #endif
952 #ifdef POSIX_THREADS
953     /* this will unlock them as well, but who cares */
954     pthread_mutex_destroy(&_hbaapi_LE_mutex);
955     pthread_mutex_destroy(&_hbaapi_TE_mutex);
956     pthread_mutex_destroy(&_hbaapi_APSE_mutex);
957     pthread_mutex_destroy(&_hbaapi_APE_mutex);
958     pthread_mutex_destroy(&_hbaapi_AE_mutex);
959     pthread_mutex_destroy(&_hbaapi_AAE_mutex);
960     pthread_mutex_destroy(&_hbaapi_AL_mutex);
961     pthread_mutex_destroy(&_hbaapi_LL_mutex);
962 #elif defined(WIN32)
963     DeleteCriticalSection(&_hbaapi_LL_mutex);
964     DeleteCriticalSection(&_hbaapi_AL_mutex);
965     DeleteCriticalSection(&_hbaapi_AAE_mutex);
966     DeleteCriticalSection(&_hbaapi_AE_mutex);
967     DeleteCriticalSection(&_hbaapi_APE_mutex);
968     DeleteCriticalSection(&_hbaapi_APSE_mutex);
969     DeleteCriticalSection(&_hbaapi_TE_mutex);
970     DeleteCriticalSection(&_hbaapi_LE_mutex);
971 #endif
972 
973     return HBA_STATUS_OK;
974 }
975 
976 /*
977  * The API used to use fixed size tables as its primary data structure.
978  * Indexing from 1 to N identified each adapters.  Now the adapters are
979  * on a linked list.  There is a unique "index" foreach each adapter.
980  * Adapters always keep their index, even if they are removed from the
981  * hardware.  The only time the indexing is reset is on HBA_FreeLibrary
982  */
983 HBA_UINT32
984 HBA_GetNumberOfAdapters(void) {
985     int j=0;
986     HBA_LIBRARY_INFO	*lib_infop;
987     HBAGetNumberOfAdaptersFunc
988 			GetNumberOfAdaptersFunc;
989     HBAGetAdapterNameFunc
990 			GetAdapterNameFunc;
991     HBA_BOOLEAN		found_name;
992     HBA_ADAPTER_INFO	*adapt_infop;
993     HBA_STATUS		status;
994 
995     char adaptername[256];
996     int num_adapters; /* local */
997 
998     if(_hbaapi_librarylist == NULL) {
999 	return (0);
1000     }
1001     GRAB_MUTEX(&_hbaapi_LL_mutex); /* pay attention to order */
1002     GRAB_MUTEX(&_hbaapi_AL_mutex);
1003 
1004     for (lib_infop = _hbaapi_librarylist;
1005 	 lib_infop != NULL;
1006 	 lib_infop = lib_infop->next) {
1007 
1008 	if (lib_infop->status != HBA_LIBRARY_LOADED) {
1009 	    continue;
1010 	}
1011 
1012 	GetNumberOfAdaptersFunc =
1013 	    lib_infop->functionTable.GetNumberOfAdaptersHandler;
1014 	if (GetNumberOfAdaptersFunc == NULL)  {
1015 	    continue;
1016 	}
1017 	num_adapters = ((GetNumberOfAdaptersFunc)());
1018 #ifndef WIN32
1019 	DEBUG(1, "HBAAPI: num_adapters for %s = %d\n",
1020 	      lib_infop->LibraryName, num_adapters, 0);
1021 #else
1022 	DEBUG(1, "HBAAPI: num_adapters for %s = %d\n",
1023 	      lib_infop->LibraryPath, num_adapters, 0);
1024 #endif
1025 
1026 	/* Also get the names of all the adapters here and cache */
1027 	GetAdapterNameFunc = lib_infop->functionTable.GetAdapterNameHandler;
1028 	if(GetAdapterNameFunc == NULL) {
1029 	    continue;
1030 	}
1031 
1032 	for (j = 0; j < num_adapters; j++) {
1033 	    found_name = 0;
1034 	    status = (GetAdapterNameFunc)(j, (char *)&adaptername);
1035 	    if(status == HBA_STATUS_OK) {
1036 		for(adapt_infop = _hbaapi_adapterlist;
1037 		    adapt_infop != NULL;
1038 		    adapt_infop = adapt_infop->next) {
1039 		    /*
1040 		     * check for duplicates, really, this may just be a second
1041 		     * call to this function
1042 		     * ??? how do we know when a name becomes stale?
1043 		     */
1044 		    if(strcmp(adaptername, adapt_infop->name) == 0) {
1045 			/* already got this one */
1046 			found_name++;
1047 			break;
1048 		    }
1049 		}
1050 		if(found_name != 0) {
1051 		    continue;
1052 		}
1053 	    }
1054 
1055 	    adapt_infop = (HBA_ADAPTER_INFO *)
1056 		calloc(1, sizeof(HBA_ADAPTER_INFO));
1057 	    if(adapt_infop == NULL) {
1058 #ifndef WIN32
1059 		fprintf(stderr,
1060 			"HBA_GetNumberOfAdapters: calloc failed on sizeof:%d\n",
1061 			sizeof(HBA_ADAPTER_INFO));
1062 #endif
1063 		RELEASE_MUTEX(&_hbaapi_AL_mutex);
1064 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex,
1065 				     _hbaapi_total_adapter_count);
1066 	    }
1067 	    if((adapt_infop->GNstatus = status) == HBA_STATUS_OK) {
1068 		adapt_infop->name = strdup(adaptername);
1069 	    } else {
1070 		char dummyname[512];
1071 		sprintf(dummyname, "NULLADAPTER-%s-%03d",
1072 			lib_infop->LibraryPath, _hbaapi_total_adapter_count);
1073 		dummyname[255] = '\0';
1074 		adapt_infop->name = strdup(dummyname);
1075 	    }
1076 	    adapt_infop->library = lib_infop;
1077 	    adapt_infop->next = _hbaapi_adapterlist;
1078 	    adapt_infop->index = _hbaapi_total_adapter_count;
1079 	    _hbaapi_adapterlist = adapt_infop;
1080 	    _hbaapi_total_adapter_count++;
1081 	}
1082     }
1083     RELEASE_MUTEX(&_hbaapi_AL_mutex);
1084     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, _hbaapi_total_adapter_count);
1085 }
1086 
1087 HBA_STATUS
1088 HBA_GetAdapterName(
1089     HBA_UINT32 adapterindex,
1090     char *adaptername)
1091 {
1092     HBA_ADAPTER_INFO	*adapt_infop;
1093     HBA_STATUS		ret = HBA_STATUS_ERROR_ILLEGAL_INDEX;
1094 
1095     if (adaptername == NULL) {
1096 	    return(HBA_STATUS_ERROR_ARG);
1097     }
1098     /*
1099      * The adapter index is from old code, but we have
1100      * to support it.  Go down the list looking for
1101      * the adapter
1102      */
1103     ARE_WE_INITED();
1104     GRAB_MUTEX(&_hbaapi_AL_mutex);
1105     *adaptername = '\0';
1106     for(adapt_infop = _hbaapi_adapterlist;
1107 	adapt_infop != NULL;
1108 	adapt_infop = adapt_infop->next) {
1109 
1110 	if(adapt_infop->index == adapterindex) {
1111 	    if(adapt_infop->name != NULL &&
1112 	       adapt_infop->GNstatus == HBA_STATUS_OK) {
1113 		strcpy(adaptername, adapt_infop->name);
1114 	    } else {
1115 		*adaptername = '\0';
1116 	    }
1117 	    ret = adapt_infop->GNstatus;
1118 	    break;
1119 	}
1120     }
1121     DEBUG(2, "GetAdapterName for index:%d ->%s", adapterindex, adaptername, 0);
1122     RELEASE_MUTEX_RETURN(&_hbaapi_AL_mutex, ret);
1123 }
1124 
1125 HBA_HANDLE
1126 HBA_OpenAdapter(char* adaptername) {
1127     HBA_HANDLE		handle;
1128     HBAOpenAdapterFunc	OpenAdapterFunc;
1129     HBA_ADAPTER_INFO	*adapt_infop;
1130     HBA_LIBRARY_INFO	*lib_infop;
1131 
1132     DEBUG(2, "OpenAdapter: %s", adaptername, 0, 0);
1133 
1134     if(_hbaapi_librarylist == NULL) {
1135 	return(HBA_HANDLE_INVALID);
1136     }
1137     if (adaptername == NULL) {
1138 	return(HBA_STATUS_ERROR_ARG);
1139     }
1140     handle = HBA_HANDLE_INVALID;
1141     GRAB_MUTEX(&_hbaapi_AL_mutex);
1142     for(adapt_infop = _hbaapi_adapterlist;
1143 	adapt_infop != NULL;
1144 	adapt_infop = adapt_infop->next) {
1145 	if (strcmp(adaptername, adapt_infop->name) != 0) {
1146 	    continue;
1147 	}
1148 	lib_infop = adapt_infop->library;
1149 	OpenAdapterFunc =
1150 	    lib_infop->functionTable.OpenAdapterHandler;
1151 	if (OpenAdapterFunc != NULL) {
1152 	    /* retrieve the vendor handle */
1153 	    handle = (OpenAdapterFunc)(adaptername);
1154 	    if(handle != 0) {
1155 		/* or this with the library index to get the common handle */
1156 		handle = HBA_HANDLE_FROM_LOCAL(lib_infop->index, handle);
1157 	    }
1158 	}
1159 	break;
1160     }
1161     RELEASE_MUTEX_RETURN(&_hbaapi_AL_mutex, handle);
1162 }
1163 /*
1164  * This function ignores the list of known adapters and instead tries
1165  * each vendors open function to see if one of them
1166  * can open an adapter when referenced with a particular WWN
1167  */
1168 HBA_STATUS
1169 HBA_OpenAdapterByWWN(HBA_HANDLE *phandle, HBA_WWN nodeWWN) {
1170     HBA_HANDLE		handle;
1171     HBA_LIBRARY_INFO	*lib_infop;
1172     HBAGetNumberOfAdaptersFunc
1173 			GetNumberOfAdaptersFunc;
1174     HBAOpenAdapterByWWNFunc
1175 			OpenAdapterFunc;
1176     HBA_STATUS		status;
1177 
1178     DEBUG(2, "OpenAdapterByWWN: %s", WWN2STR1(&nodeWWN), 0, 0);
1179 
1180     if (phandle == NULL) {
1181 	    return(HBA_STATUS_ERROR_ARG);
1182     }
1183 
1184     ARE_WE_INITED();
1185 
1186     *phandle = HBA_HANDLE_INVALID;
1187 
1188     GRAB_MUTEX(&_hbaapi_LL_mutex);
1189     for (lib_infop = _hbaapi_librarylist;
1190 	 lib_infop != NULL;
1191 	 lib_infop = lib_infop->next) {
1192 
1193 	status = HBA_STATUS_ERROR_ILLEGAL_WWN;
1194 
1195 	if (lib_infop->status != HBA_LIBRARY_LOADED) {
1196 	    continue;
1197 	}
1198 
1199 	GetNumberOfAdaptersFunc =
1200 	    lib_infop->functionTable.GetNumberOfAdaptersHandler;
1201 	if (GetNumberOfAdaptersFunc == NULL)  {
1202 	    continue;
1203 	}
1204 
1205 	/* look for new hardware */
1206 	(void) ((GetNumberOfAdaptersFunc)());
1207 
1208 	OpenAdapterFunc = lib_infop->functionTable.OpenAdapterByWWNHandler;
1209 	if (OpenAdapterFunc == NULL) {
1210 	    continue;
1211 	}
1212 	/*
1213 	 * We do not know if the WWN is known by this vendor,
1214 	 * just try it
1215 	 */
1216 	if((status = (OpenAdapterFunc)(&handle, nodeWWN)) != HBA_STATUS_OK) {
1217 	    continue;
1218 	}
1219 	/* OK, make a vendor non-specific handle */
1220 	*phandle = HBA_HANDLE_FROM_LOCAL(lib_infop->index, handle);
1221 	status = HBA_STATUS_OK;
1222 	break;
1223     }
1224     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1225 }
1226 
1227 void
1228 HBA_RefreshAdapterConfiguration() {
1229     DEBUG(2, "HBA_RefreshAdapterConfiguration", 0, 0, 0);
1230     (void)HBA_GetNumberOfAdapters();
1231     return;
1232 }
1233 
1234 HBA_UINT32
1235 HBA_GetVersion() {
1236     DEBUG(2, "HBA_GetVersion", 0, 0, 0);
1237     return HBA_LIBVERSION;
1238 }
1239 
1240 /*
1241  * This function is VERY OS dependent.  Wing it as best you can.
1242  */
1243 HBA_UINT32
1244 HBA_GetWrapperLibraryAttributes (
1245     HBA_LIBRARYATTRIBUTES *attributes)
1246 {
1247 
1248     DEBUG(2, "HBA_GetWrapperLibraryAttributes", 0, 0, 0);
1249 
1250     if (attributes == NULL) {
1251 	    return(HBA_STATUS_ERROR_ARG);
1252     }
1253 
1254     memset(attributes, 0, sizeof(HBA_LIBRARYATTRIBUTES));
1255 
1256 #if defined(SOLARIS)
1257     if((handle = dlopen("libHBAAPI.so", RTLD_NOW)) != NULL) {
1258 	if(dlinfo(handle, RTLD_DI_LINKMAP, &map) >= 0) {
1259 	    for(mp = map; mp != NULL; mp = mp->l_next) {
1260 		if(strlen(map->l_name) < 256) {
1261 		    strcpy(attributes->LibPath, map->l_lname);
1262 		}
1263 	    }
1264 	}
1265     }
1266 #elif defined(WIN32)
1267     {
1268 	HMODULE module;
1269 
1270 	/* No need to do anything with the module handle */
1271 	/* It wasn't alloocated so it doesn't need to be freed */
1272 	module = GetModuleHandle("HBAAPI");
1273 	if ( module != NULL ) {
1274 	    if ( GetModuleFileName(module, attributes->LibPath,
1275 				sizeof(attributes->LibPath)) == 0 ) {
1276 	        attributes->LibPath[0] = '\0';
1277 	    }
1278 	}
1279     }
1280 #endif
1281 #if defined(VENDOR)
1282     strcpy(attributes->VName, VENDOR);
1283 #else
1284     attributes->VName[0] = '\0';
1285 #endif
1286 #if defined(VERSION)
1287     strcpy(attributes->VVersion, VERSION);
1288 #else
1289     attributes->VVersion[0] = '\0';
1290 #endif
1291 #if defined(BUILD_DATE)
1292 #if defined(WIN32)
1293     {
1294 	int matchCount;
1295 	matchCount = sscanf(BUILD_DATE, "%u/%u/%u %u:%u:%u",
1296 		&attributes->build_date.tm_year,
1297 		&attributes->build_date.tm_mon,
1298 		&attributes->build_date.tm_mday,
1299 		&attributes->build_date.tm_hour,
1300 		&attributes->build_date.tm_min,
1301 		&attributes->build_date.tm_sec
1302 	);
1303 
1304 	if ( matchCount != 6 ) {
1305 	    memset(&attributes->build_date, 0, sizeof(struct tm));
1306 	} else {
1307 	    attributes->build_date.tm_year -= 1900;
1308 	    attributes->build_date.tm_isdst = -1;
1309 	}
1310 
1311     }
1312 #else
1313     if(strptime(BUILD_DATE, "%Y/%m/%d %T %Z", &(attributes->build_date)) == NULL) {
1314 	memset(&attributes->build_date, 0, sizeof(struct tm));
1315     }
1316 #endif
1317 #else
1318     memset(&attributes->build_date, 0, sizeof(struct tm));
1319 #endif
1320     return 2;
1321 }
1322 
1323 /*
1324  * Callback registation and handling
1325  */
1326 HBA_STATUS
1327 HBA_RemoveCallback (HBA_CALLBACKHANDLE cbhandle) {
1328     HBA_STATUS	status;
1329 
1330     DEBUG(2, "HBA_RemoveCallback", 0, 0, 0);
1331     ARE_WE_INITED();
1332 
1333     GRAB_MUTEX(&_hbaapi_LL_mutex);
1334     status = local_remove_callback(cbhandle);
1335     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1336 }
1337 
1338 /* Adapter Add Events *********************************************************/
1339 static void
1340 adapteraddevents_callback (void *data, HBA_WWN PortWWN, HBA_UINT32 eventType) {
1341     HBA_ALLADAPTERSCALLBACK_ELEM	*cbp;
1342 
1343     DEBUG(3, "AddAdapterEvent, port:%s", WWN2STR1(&PortWWN), 0, 0);
1344 
1345     GRAB_MUTEX(&_hbaapi_AAE_mutex);
1346     for(cbp = _hbaapi_adapteraddevents_callback_list;
1347 	cbp != NULL;
1348 	cbp = cbp->next) {
1349 	(*cbp->callback)(data, PortWWN, HBA_EVENT_ADAPTER_ADD);
1350     }
1351     RELEASE_MUTEX(&_hbaapi_AAE_mutex);
1352 
1353 }
1354 HBA_STATUS
1355 HBA_RegisterForAdapterAddEvents (
1356     void		(*callback) (
1357 	void		*data,
1358 	HBA_WWN		PortWWN,
1359 	HBA_UINT32	eventType
1360 	),
1361     void		*userData,
1362     HBA_CALLBACKHANDLE *callbackHandle) {
1363 
1364     HBA_ALLADAPTERSCALLBACK_ELEM	*cbp;
1365     HBA_VENDORCALLBACK_ELEM		*vcbp;
1366     HBA_VENDORCALLBACK_ELEM		*vendorhandlelist;
1367     HBARegisterForAdapterAddEventsFunc	registeredfunc;
1368     HBA_STATUS				status = HBA_STATUS_OK;
1369     HBA_STATUS				failure = HBA_STATUS_OK;
1370     HBA_LIBRARY_INFO			*lib_infop;
1371     int					registered_cnt = 0;
1372     int					vendor_cnt = 0;
1373     int					not_supported_cnt = 0;
1374     int					status_OK_bar_cnt = 0;
1375     int					status_OK_cnt = 0;
1376 
1377     DEBUG(2, "HBA_RegisterForAdapterAddEvents", 0, 0, 0);
1378 
1379     if (callbackHandle == NULL) {
1380 	    return(HBA_STATUS_ERROR_ARG);
1381     }
1382     ARE_WE_INITED();
1383 
1384     cbp = (HBA_ALLADAPTERSCALLBACK_ELEM *)
1385 	calloc(1, sizeof(HBA_ALLADAPTERSCALLBACK_ELEM));
1386     *callbackHandle = (HBA_CALLBACKHANDLE) cbp;
1387     if(cbp == NULL) {
1388 #ifndef WIN32
1389 	fprintf(stderr,
1390 		"HBA_RegisterForAdapterAddEvents: calloc failed for %d bytes\n",
1391 		sizeof(HBA_ALLADAPTERSCALLBACK_ELEM));
1392 #endif
1393 	return HBA_STATUS_ERROR;
1394     }
1395 
1396     GRAB_MUTEX(&_hbaapi_LL_mutex);
1397     GRAB_MUTEX(&_hbaapi_AAE_mutex);
1398     cbp->callback = callback;
1399     cbp->next = _hbaapi_adapteraddevents_callback_list;
1400     _hbaapi_adapteraddevents_callback_list = cbp;
1401     /* Need to release the mutex now incase the vendor function invokes the
1402      * callback.  We will grap the mutex later to attach the vendor handle list
1403      * to the callback structure */
1404     RELEASE_MUTEX(&_hbaapi_AAE_mutex);
1405 
1406 
1407     /*
1408      * now create a list of vendors (vendor libraryies, NOT ADAPTERS) that have
1409      * successfully registerred
1410      */
1411     vendorhandlelist = NULL;
1412     for(lib_infop = _hbaapi_librarylist;
1413 	lib_infop != NULL;
1414 	lib_infop = lib_infop->next) {
1415 
1416 	vendor_cnt++;
1417 
1418 	registeredfunc =
1419 	    lib_infop->functionTable.RegisterForAdapterAddEventsHandler;
1420 	if(registeredfunc == NULL) {
1421 	    continue;
1422 	}
1423 
1424 	vcbp = (HBA_VENDORCALLBACK_ELEM *)
1425 	    calloc(1, sizeof(HBA_VENDORCALLBACK_ELEM));
1426 	if(vcbp == NULL) {
1427 #ifndef WIN32
1428 	    fprintf(stderr,
1429 		    "HBA_RegisterForAdapterAddEvents: "
1430 		    "calloc failed for %d bytes\n",
1431 		    sizeof(HBA_VENDORCALLBACK_ELEM));
1432 #endif
1433 	    freevendorhandlelist(vendorhandlelist);
1434 	    status = HBA_STATUS_ERROR;
1435 	    break;
1436 	}
1437 
1438 	registered_cnt++;
1439 	status = (registeredfunc)(adapteraddevents_callback,
1440 				  userData, &vcbp->vendorcbhandle);
1441 	if(status == HBA_STATUS_ERROR_NOT_SUPPORTED) {
1442 	    not_supported_cnt++;
1443 	    free(vcbp);
1444 	    continue;
1445 	} else if (status != HBA_STATUS_OK) {
1446 	    status_OK_bar_cnt++;
1447 	    DEBUG(0,
1448 		  "HBA_RegisterForAdapterAddEvents: Library->%s, Error->%d",
1449 		  lib_infop->LibraryPath, status, 0);
1450 #ifndef WIN32
1451 	    fprintf(stderr,
1452 		    "HBA_RegisterForAdapterAddEvents: Library->%s, Error->%d",
1453 		    lib_infop->LibraryPath, status);
1454 #endif
1455 	    failure = status;
1456 	    free(vcbp);
1457 	    continue;
1458 	} else {
1459 	    status_OK_cnt++;
1460 	}
1461 	vcbp->lib_info = lib_infop;
1462 	vcbp->next = vendorhandlelist;
1463 	vendorhandlelist = vcbp;
1464     }
1465     if(registered_cnt == 0) {
1466 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
1467 	freevendorhandlelist(vendorhandlelist);
1468 	local_remove_callback((HBA_CALLBACKHANDLE) cbp);
1469     } else if (status_OK_cnt == 0 && not_supported_cnt != 0) {
1470 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
1471     } else if (status_OK_cnt == 0) {
1472 	/* At least one vendor library registered this function, but no
1473 	 * vendor call succeeded */
1474 	local_remove_callback((HBA_CALLBACKHANDLE) cbp);
1475 	status = failure;
1476     } else {
1477 	/* we have had atleast some success, now finish up */
1478 	GRAB_MUTEX(&_hbaapi_AAE_mutex);
1479 	/* this seems silly, but what if another thread called
1480 	 * the callback remove */
1481 	for(cbp = _hbaapi_adapteraddevents_callback_list;
1482 	    cbp != NULL; cbp = cbp->next) {
1483 	    if((HBA_CALLBACKHANDLE)cbp == *callbackHandle) {
1484 		/* yup, its still there, hooray */
1485 		cbp->vendorhandlelist = vendorhandlelist;
1486 		vendorhandlelist = NULL;
1487 		break;
1488 	    }
1489 	}
1490 	RELEASE_MUTEX(&_hbaapi_AAE_mutex);
1491 	if(vendorhandlelist != NULL) {
1492 	    /* bummer, somebody removed the callback before we finished
1493 	     * registration, probably will never happen */
1494 	    freevendorhandlelist(vendorhandlelist);
1495 	    DEBUG(0,
1496 		  "HBA_RegisterForAdapterAddEvents: HBA_RemoveCallback was "
1497 		  "called for a handle before registration was finished.",
1498 		  0, 0, 0);
1499 	    status = HBA_STATUS_ERROR;
1500 	} else {
1501 	    status = HBA_STATUS_OK;
1502 	}
1503     }
1504     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1505 }
1506 
1507 /* Adapter Events (other than add) ********************************************/
1508 static void
1509 adapterevents_callback (void *data,
1510 			HBA_WWN PortWWN,
1511 			HBA_UINT32 eventType) {
1512     HBA_ADAPTERCALLBACK_ELEM	*acbp;
1513 
1514     DEBUG(3, "AdapterEvent, port:%s, eventType:%d", WWN2STR1(&PortWWN),
1515 	  eventType, 0);
1516 
1517     GRAB_MUTEX(&_hbaapi_AE_mutex);
1518     for(acbp = _hbaapi_adapterevents_callback_list;
1519 	acbp != NULL;
1520 	acbp = acbp->next) {
1521 	if(data == (void *)acbp) {
1522 	    (*acbp->callback)(acbp->userdata, PortWWN, eventType);
1523 	    break;
1524 	}
1525     }
1526     RELEASE_MUTEX(&_hbaapi_AE_mutex);
1527 }
1528 HBA_STATUS
1529 HBA_RegisterForAdapterEvents (
1530     void		(*callback) (
1531 	void		*data,
1532 	HBA_WWN		PortWWN,
1533 	HBA_UINT32	eventType
1534 	),
1535     void		*userData,
1536     HBA_HANDLE		handle,
1537     HBA_CALLBACKHANDLE	*callbackHandle) {
1538 
1539     HBA_ADAPTERCALLBACK_ELEM		*acbp;
1540     HBARegisterForAdapterEventsFunc	registeredfunc;
1541     HBA_STATUS				status;
1542     HBA_LIBRARY_INFO			*lib_infop;
1543     HBA_HANDLE				vendorHandle;
1544 
1545     DEBUG(2, "HBA_RegisterForAdapterEvents", 0, 0, 0);
1546 
1547     if (callbackHandle == NULL) {
1548 	    return(HBA_STATUS_ERROR_ARG);
1549     }
1550 
1551     CHECKLIBRARY();
1552 
1553     /* we now have the _hbaapi_LL_mutex */
1554 
1555     registeredfunc = lib_infop->functionTable.RegisterForAdapterEventsHandler;
1556     if(registeredfunc == NULL) {
1557 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
1558     }
1559 
1560     /*
1561      * that allocated memory is used both as the handle for the
1562      * caller, and as userdata to the vendor call so that on
1563      * callback the specific registration may be recalled
1564      */
1565     acbp = (HBA_ADAPTERCALLBACK_ELEM *)
1566 	calloc(1, sizeof(HBA_ADAPTERCALLBACK_ELEM));
1567     if(acbp == NULL) {
1568 #ifndef WIN32
1569 	fprintf(stderr,
1570 		"HBA_RegisterForAdapterEvents: calloc failed for %d bytes\n",
1571 		sizeof(HBA_ADAPTERCALLBACK_ELEM));
1572 #endif
1573 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
1574     }
1575     *callbackHandle = (HBA_CALLBACKHANDLE) acbp;
1576     acbp->callback = callback;
1577     acbp->userdata = userData;
1578     acbp->lib_info = lib_infop;
1579 
1580     status = (registeredfunc)(adapterevents_callback,
1581 			      (void *)acbp,
1582 			      vendorHandle,
1583 			      &acbp->vendorcbhandle);
1584     if(status != HBA_STATUS_OK) {
1585 	free(acbp);
1586 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1587     }
1588 
1589     GRAB_MUTEX(&_hbaapi_AE_mutex);
1590     acbp->next = _hbaapi_adapterevents_callback_list;
1591     _hbaapi_adapterevents_callback_list = acbp;
1592     RELEASE_MUTEX(&_hbaapi_AE_mutex);
1593 
1594     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
1595 }
1596 
1597 /* Adapter Port Events ********************************************************/
1598 static void
1599 adapterportevents_callback (void *data,
1600 			    HBA_WWN PortWWN,
1601 			    HBA_UINT32 eventType,
1602 			    HBA_UINT32 fabricPortID) {
1603     HBA_ADAPTERCALLBACK_ELEM	*acbp;
1604 
1605     DEBUG(3, "AdapterPortEvent, port:%s, eventType:%d fabricPortID:0X%06x",
1606 	  WWN2STR1(&PortWWN), eventType, fabricPortID);
1607 
1608     GRAB_MUTEX(&_hbaapi_APE_mutex);
1609 
1610     for(acbp = _hbaapi_adapterportevents_callback_list;
1611 	acbp != NULL;
1612 	acbp = acbp->next) {
1613 	if(data == (void *)acbp) {
1614 	    (*acbp->callback)(acbp->userdata, PortWWN, eventType, fabricPortID);
1615 	    break;
1616 	}
1617     }
1618     RELEASE_MUTEX(&_hbaapi_APE_mutex);
1619 }
1620 HBA_STATUS
1621 HBA_RegisterForAdapterPortEvents (
1622     void		(*callback) (
1623 	void		*data,
1624 	HBA_WWN		PortWWN,
1625 	HBA_UINT32	eventType,
1626 	HBA_UINT32	fabricPortID
1627 	),
1628     void		*userData,
1629     HBA_HANDLE		handle,
1630     HBA_WWN		PortWWN,
1631     HBA_CALLBACKHANDLE	*callbackHandle) {
1632 
1633     HBA_ADAPTERCALLBACK_ELEM		*acbp;
1634     HBARegisterForAdapterPortEventsFunc	registeredfunc;
1635     HBA_STATUS				status;
1636     HBA_LIBRARY_INFO			*lib_infop;
1637     HBA_HANDLE				vendorHandle;
1638 
1639     DEBUG(2, "HBA_RegisterForAdapterPortEvents for port: %s",
1640 	  WWN2STR1(&PortWWN), 0, 0);
1641 
1642     if (callbackHandle == NULL) {
1643 	    return(HBA_STATUS_ERROR_ARG);
1644     }
1645 
1646     CHECKLIBRARY();
1647     /* we now have the _hbaapi_LL_mutex */
1648 
1649     registeredfunc =
1650 	lib_infop->functionTable.RegisterForAdapterPortEventsHandler;
1651     if(registeredfunc == NULL) {
1652 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
1653     }
1654 
1655     /*
1656      * that allocated memory is used both as the handle for the
1657      * caller, and as userdata to the vendor call so that on
1658      * callback the specific registration may be recalled
1659      */
1660     acbp = (HBA_ADAPTERCALLBACK_ELEM *)
1661 	calloc(1, sizeof(HBA_ADAPTERCALLBACK_ELEM));
1662     if(acbp == NULL) {
1663 #ifndef WIN32
1664 	fprintf(stderr,
1665 		"HBA_RegisterForAdapterPortEvents: "
1666 		"calloc failed for %d bytes\n",
1667 		sizeof(HBA_ADAPTERCALLBACK_ELEM));
1668 #endif
1669 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
1670 
1671     }
1672     *callbackHandle = (HBA_CALLBACKHANDLE) acbp;
1673     acbp->callback = callback;
1674     acbp->userdata = userData;
1675     acbp->lib_info = lib_infop;
1676 
1677     status = (registeredfunc)(adapterportevents_callback,
1678 			      (void *)acbp,
1679 			      vendorHandle,
1680 			      PortWWN,
1681 			      &acbp->vendorcbhandle);
1682     if(status != HBA_STATUS_OK) {
1683 	free(acbp);
1684 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1685     }
1686 
1687     GRAB_MUTEX(&_hbaapi_APE_mutex);
1688     acbp->next = _hbaapi_adapterportevents_callback_list;
1689     _hbaapi_adapterportevents_callback_list = acbp;
1690     RELEASE_MUTEX(&_hbaapi_APE_mutex);
1691 
1692     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
1693 }
1694 
1695 /* Adapter State Events *******************************************************/
1696 static void
1697 adapterportstatevents_callback (void *data,
1698 				HBA_WWN PortWWN,
1699 				HBA_UINT32 eventType) {
1700     HBA_ADAPTERCALLBACK_ELEM	*acbp;
1701 
1702     DEBUG(3, "AdapterPortStateEvent, port:%s, eventType:%d", WWN2STR1(&PortWWN),
1703 	  eventType, 0);
1704 
1705     GRAB_MUTEX(&_hbaapi_APSE_mutex);
1706     for(acbp = _hbaapi_adapterportstatevents_callback_list;
1707 	acbp != NULL;
1708 	acbp = acbp->next) {
1709 	if(data == (void *)acbp) {
1710 	    (*acbp->callback)(acbp->userdata, PortWWN, eventType);
1711 	    return;
1712 	}
1713     }
1714 }
1715 HBA_STATUS
1716 HBA_RegisterForAdapterPortStatEvents (
1717     void		(*callback) (
1718 	void		*data,
1719 	HBA_WWN		PortWWN,
1720 	HBA_UINT32	eventType
1721 	),
1722     void		*userData,
1723     HBA_HANDLE		handle,
1724     HBA_WWN		PortWWN,
1725     HBA_PORTSTATISTICS	stats,
1726     HBA_UINT32		statType,
1727     HBA_CALLBACKHANDLE	*callbackHandle) {
1728 
1729     HBA_ADAPTERCALLBACK_ELEM	*acbp;
1730     HBARegisterForAdapterPortStatEventsFunc
1731 				registeredfunc;
1732     HBA_STATUS			status;
1733     HBA_LIBRARY_INFO		*lib_infop;
1734     HBA_HANDLE			vendorHandle;
1735 
1736     DEBUG(2, "HBA_RegisterForAdapterPortStatEvents for port: %s",
1737 	  WWN2STR1(&PortWWN), 0, 0);
1738 
1739     if (callbackHandle == NULL) {
1740 	    return(HBA_STATUS_ERROR_ARG);
1741     }
1742 
1743     CHECKLIBRARY();
1744     /* we now have the _hbaapi_LL_mutex */
1745 
1746     registeredfunc =
1747 	lib_infop->functionTable.RegisterForAdapterPortStatEventsHandler;
1748     if(registeredfunc == NULL) {
1749 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
1750     }
1751 
1752     /*
1753      * that allocated memory is used both as the handle for the
1754      * caller, and as userdata to the vendor call so that on
1755      * callback the specific registration may be recalled
1756      */
1757     acbp = (HBA_ADAPTERCALLBACK_ELEM *)
1758 	calloc(1, sizeof(HBA_ADAPTERCALLBACK_ELEM));
1759     if(acbp == NULL) {
1760 #ifndef WIN32
1761 	fprintf(stderr,
1762 		"HBA_RegisterForAdapterPortStatEvents: "
1763 		"calloc failed for %d bytes\n",
1764 		sizeof(HBA_ADAPTERCALLBACK_ELEM));
1765 #endif
1766 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
1767     }
1768     *callbackHandle = (HBA_CALLBACKHANDLE) acbp;
1769     acbp->callback = callback;
1770     acbp->userdata = userData;
1771     acbp->lib_info = lib_infop;
1772 
1773     status = (registeredfunc)(adapterportstatevents_callback,
1774 			      (void *)acbp,
1775 			      vendorHandle,
1776 			      PortWWN,
1777 			      stats,
1778 			      statType,
1779 			      &acbp->vendorcbhandle);
1780     if(status != HBA_STATUS_OK) {
1781 	free(acbp);
1782 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1783     }
1784 
1785     GRAB_MUTEX(&_hbaapi_APSE_mutex);
1786     acbp->next = _hbaapi_adapterportstatevents_callback_list;
1787     _hbaapi_adapterportstatevents_callback_list = acbp;
1788     RELEASE_MUTEX(&_hbaapi_APSE_mutex);
1789 
1790     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
1791 }
1792 
1793 /* Target Events **************************************************************/
1794 static void
1795 targetevents_callback (void *data,
1796 		       HBA_WWN hbaPortWWN,
1797 		       HBA_WWN discoveredPortWWN,
1798 		       HBA_UINT32 eventType) {
1799     HBA_ADAPTERCALLBACK_ELEM	*acbp;
1800 
1801     DEBUG(3, "TargetEvent, hbaPort:%s, discoveredPort:%s eventType:%d",
1802 	  WWN2STR1(&hbaPortWWN), WWN2STR2(&discoveredPortWWN), eventType);
1803 
1804     GRAB_MUTEX(&_hbaapi_TE_mutex);
1805     for(acbp = _hbaapi_targetevents_callback_list;
1806 	acbp != NULL;
1807 	acbp = acbp->next) {
1808 	if(data == (void *)acbp) {
1809 	    (*acbp->callback)(acbp->userdata, hbaPortWWN,
1810 			      discoveredPortWWN, eventType);
1811 	    break;
1812 	}
1813     }
1814     RELEASE_MUTEX(&_hbaapi_TE_mutex);
1815 }
1816 HBA_STATUS
1817 HBA_RegisterForTargetEvents (
1818     void		(*callback) (
1819 	void		*data,
1820 	HBA_WWN		hbaPortWWN,
1821 	HBA_WWN		discoveredPortWWN,
1822 	HBA_UINT32	eventType
1823 	),
1824     void		*userData,
1825     HBA_HANDLE		handle,
1826     HBA_WWN		hbaPortWWN,
1827     HBA_WWN		discoveredPortWWN,
1828     HBA_CALLBACKHANDLE	*callbackHandle,
1829     HBA_UINT32		allTargets) {
1830 
1831     HBA_ADAPTERCALLBACK_ELEM
1832 			*acbp;
1833     HBARegisterForTargetEventsFunc
1834 			registeredfunc;
1835     HBA_STATUS		status;
1836     HBA_LIBRARY_INFO	*lib_infop;
1837     HBA_HANDLE		vendorHandle;
1838 
1839     DEBUG(2, "HBA_RegisterForTargetEvents, hbaPort: %s, discoveredPort: %s",
1840 	  WWN2STR1(&hbaPortWWN), WWN2STR2(&discoveredPortWWN), 0);
1841 
1842     if (callbackHandle == NULL) {
1843 	    return(HBA_STATUS_ERROR_ARG);
1844     }
1845 
1846     CHECKLIBRARY();
1847     /* we now have the _hbaapi_LL_mutex */
1848 
1849     registeredfunc = lib_infop->functionTable.RegisterForTargetEventsHandler;
1850     if(registeredfunc == NULL) {
1851 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
1852     }
1853 
1854     /*
1855      * that allocated memory is used both as the handle for the
1856      * caller, and as userdata to the vendor call so that on
1857      * callback the specific registration may be recalled
1858      */
1859     acbp = (HBA_ADAPTERCALLBACK_ELEM *)
1860 	calloc(1, sizeof(HBA_ADAPTERCALLBACK_ELEM));
1861     if(acbp == NULL) {
1862 #ifndef WIN32
1863 	fprintf(stderr,
1864 		"HBA_RegisterForTargetEvents: calloc failed for %d bytes\n",
1865 		sizeof(HBA_ADAPTERCALLBACK_ELEM));
1866 #endif
1867 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
1868     }
1869     *callbackHandle = (HBA_CALLBACKHANDLE) acbp;
1870     acbp->callback = callback;
1871     acbp->userdata = userData;
1872     acbp->lib_info = lib_infop;
1873 
1874     status = (registeredfunc)(targetevents_callback,
1875 			      (void *)acbp,
1876 			      vendorHandle,
1877 			      hbaPortWWN,
1878 			      discoveredPortWWN,
1879 			      &acbp->vendorcbhandle,
1880 			      allTargets);
1881     if(status != HBA_STATUS_OK) {
1882 	free(acbp);
1883 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1884     }
1885 
1886     GRAB_MUTEX(&_hbaapi_TE_mutex);
1887     acbp->next = _hbaapi_targetevents_callback_list;
1888     _hbaapi_targetevents_callback_list = acbp;
1889     RELEASE_MUTEX(&_hbaapi_TE_mutex);
1890 
1891     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
1892 }
1893 
1894 /* Link Events ****************************************************************/
1895 static void
1896 linkevents_callback (void *data,
1897 		     HBA_WWN adapterWWN,
1898 		     HBA_UINT32 eventType,
1899 		     void *pRLIRBuffer,
1900 		     HBA_UINT32 RLIRBufferSize) {
1901     HBA_ADAPTERCALLBACK_ELEM	*acbp;
1902 
1903     DEBUG(3, "LinkEvent, hbaWWN:%s, eventType:%d",
1904 	  WWN2STR1(&adapterWWN), eventType, 0);
1905 
1906     GRAB_MUTEX(&_hbaapi_LE_mutex);
1907     for(acbp = _hbaapi_linkevents_callback_list;
1908 	acbp != NULL;
1909 	acbp = acbp->next) {
1910 	if(data == (void *)acbp) {
1911 	    (*acbp->callback)(acbp->userdata, adapterWWN,
1912 			      eventType, pRLIRBuffer, RLIRBufferSize);
1913 	    break;
1914 	}
1915     }
1916     RELEASE_MUTEX(&_hbaapi_LE_mutex);
1917 }
1918 HBA_STATUS
1919 HBA_RegisterForLinkEvents (
1920     void		(*callback) (
1921 	void		*data,
1922 	HBA_WWN		adapterWWN,
1923 	HBA_UINT32	eventType,
1924 	void		*pRLIRBuffer,
1925 	HBA_UINT32	RLIRBufferSize),
1926     void		*userData,
1927     void		*pRLIRBuffer,
1928     HBA_UINT32		RLIRBufferSize,
1929     HBA_HANDLE		handle,
1930     HBA_CALLBACKHANDLE	*callbackHandle) {
1931 
1932     HBA_ADAPTERCALLBACK_ELEM	*acbp;
1933     HBARegisterForLinkEventsFunc
1934 				registeredfunc;
1935     HBA_STATUS			status;
1936     HBA_LIBRARY_INFO		*lib_infop;
1937     HBA_HANDLE			vendorHandle;
1938 
1939     DEBUG(2, "HBA_RegisterForLinkEvents", 0, 0, 0);
1940 
1941     if (callbackHandle == NULL) {
1942 	    return(HBA_STATUS_ERROR_ARG);
1943     }
1944 
1945     CHECKLIBRARY();
1946     /* we now have the _hbaapi_LL_mutex */
1947 
1948     registeredfunc = lib_infop->functionTable.RegisterForLinkEventsHandler;
1949     if(registeredfunc == NULL) {
1950 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
1951     }
1952 
1953     /*
1954      * that allocated memory is used both as the handle for the
1955      * caller, and as userdata to the vendor call so that on
1956      * callback the specific registration may be recalled
1957      */
1958     acbp = (HBA_ADAPTERCALLBACK_ELEM *)
1959 	calloc(1, sizeof(HBA_ADAPTERCALLBACK_ELEM));
1960     if(acbp == NULL) {
1961 #ifndef WIN32
1962 	fprintf(stderr,
1963 		"HBA_RegisterForLinkEvents: calloc failed for %d bytes\n",
1964 		sizeof(HBA_ADAPTERCALLBACK_ELEM));
1965 #endif
1966 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
1967     }
1968     *callbackHandle = (HBA_CALLBACKHANDLE) acbp;
1969     acbp->callback = callback;
1970     acbp->userdata = userData;
1971     acbp->lib_info = lib_infop;
1972 
1973     status = (registeredfunc)(linkevents_callback,
1974 			      (void *)acbp,
1975 			      pRLIRBuffer,
1976 			      RLIRBufferSize,
1977 			      vendorHandle,
1978 			      &acbp->vendorcbhandle);
1979     if(status != HBA_STATUS_OK) {
1980 	free(acbp);
1981 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1982     }
1983 
1984     GRAB_MUTEX(&_hbaapi_LE_mutex);
1985     acbp->next = _hbaapi_linkevents_callback_list;
1986     _hbaapi_linkevents_callback_list = acbp;
1987     RELEASE_MUTEX(&_hbaapi_LE_mutex);
1988 
1989     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
1990 }
1991 
1992 
1993 /*
1994  * All of the functions below are almost passthru functions to the
1995  * vendor specific function
1996  */
1997 
1998 void
1999 HBA_CloseAdapter(HBA_HANDLE handle) {
2000     HBA_STATUS		status;
2001     HBA_LIBRARY_INFO	*lib_infop;
2002     HBA_HANDLE		vendorHandle;
2003     HBACloseAdapterFunc CloseAdapterFunc;
2004 
2005     DEBUG(2, "HBA_CloseAdapter", 0, 0, 0);
2006 
2007     status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);
2008     if (status == HBA_STATUS_OK) {
2009 	CloseAdapterFunc = lib_infop->functionTable.CloseAdapterHandler;
2010 	if (CloseAdapterFunc != NULL) {
2011 	    ((CloseAdapterFunc)(vendorHandle));
2012 	}
2013 	RELEASE_MUTEX(&_hbaapi_LL_mutex);
2014     }
2015 }
2016 
2017 HBA_STATUS
2018 HBA_GetAdapterAttributes (
2019     HBA_HANDLE		handle,
2020     HBA_ADAPTERATTRIBUTES
2021 			*hbaattributes)
2022 {
2023     HBA_STATUS		status;
2024     HBA_LIBRARY_INFO	*lib_infop;
2025     HBA_HANDLE		vendorHandle;
2026     HBAGetAdapterAttributesFunc GetAdapterAttributesFunc;
2027 
2028     DEBUG(2, "HBA_GetAdapterAttributes", 0, 0, 0);
2029 
2030     CHECKLIBRARY();
2031     GetAdapterAttributesFunc =
2032 	lib_infop->functionTable.GetAdapterAttributesHandler;
2033     if (GetAdapterAttributesFunc != NULL) {
2034 	status = ((GetAdapterAttributesFunc)(vendorHandle, hbaattributes));
2035     } else {
2036 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2037     }
2038     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2039 }
2040 
2041 HBA_STATUS
2042 HBA_GetAdapterPortAttributes (
2043     HBA_HANDLE		handle,
2044     HBA_UINT32		portindex,
2045     HBA_PORTATTRIBUTES	*portattributes)
2046 {
2047     HBA_STATUS		status;
2048     HBA_LIBRARY_INFO	*lib_infop;
2049     HBA_HANDLE		vendorHandle;
2050     HBAGetAdapterPortAttributesFunc
2051 			GetAdapterPortAttributesFunc;
2052 
2053     DEBUG(2, "HBA_GetAdapterPortAttributes", 0, 0, 0);
2054 
2055     CHECKLIBRARY();
2056     GetAdapterPortAttributesFunc =
2057 	lib_infop->functionTable.GetAdapterPortAttributesHandler;
2058     if (GetAdapterPortAttributesFunc != NULL) {
2059 	status = ((GetAdapterPortAttributesFunc)
2060 		  (vendorHandle, portindex, portattributes));
2061     } else {
2062 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2063     }
2064     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2065 }
2066 
2067 HBA_STATUS
2068 HBA_GetPortStatistics (
2069     HBA_HANDLE		handle,
2070     HBA_UINT32		portindex,
2071     HBA_PORTSTATISTICS	*portstatistics)
2072 {
2073     HBA_STATUS		status;
2074     HBA_LIBRARY_INFO	*lib_infop;
2075     HBA_HANDLE		vendorHandle;
2076     HBAGetPortStatisticsFunc
2077 			GetPortStatisticsFunc;
2078 
2079     DEBUG(2, "HBA_GetPortStatistics", 0, 0, 0);
2080 
2081     CHECKLIBRARY();
2082     GetPortStatisticsFunc =
2083 	lib_infop->functionTable.GetPortStatisticsHandler;
2084     if (GetPortStatisticsFunc != NULL) {
2085 	status = ((GetPortStatisticsFunc)
2086 		  (vendorHandle, portindex, portstatistics));
2087     } else {
2088 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2089     }
2090     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2091 }
2092 
2093 HBA_STATUS
2094 HBA_GetDiscoveredPortAttributes (
2095     HBA_HANDLE		handle,
2096     HBA_UINT32		portindex,
2097     HBA_UINT32		discoveredportindex,
2098     HBA_PORTATTRIBUTES	*portattributes)
2099 {
2100     HBA_STATUS		status;
2101     HBA_LIBRARY_INFO	*lib_infop;
2102     HBA_HANDLE		vendorHandle;
2103     HBAGetDiscoveredPortAttributesFunc
2104 			GetDiscoveredPortAttributesFunc;
2105 
2106     DEBUG(2, "HBA_GetDiscoveredPortAttributes", 0, 0, 0);
2107 
2108     CHECKLIBRARY();
2109     GetDiscoveredPortAttributesFunc =
2110 	lib_infop->functionTable.GetDiscoveredPortAttributesHandler;
2111     if (GetDiscoveredPortAttributesFunc != NULL)  {
2112 	status = ((GetDiscoveredPortAttributesFunc)
2113 		  (vendorHandle, portindex, discoveredportindex,
2114 		   portattributes));
2115     } else {
2116 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2117     }
2118     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2119 }
2120 
2121 HBA_STATUS
2122 HBA_GetPortAttributesByWWN (
2123     HBA_HANDLE		handle,
2124     HBA_WWN		PortWWN,
2125     HBA_PORTATTRIBUTES	*portattributes)
2126 {
2127     HBA_STATUS		status;
2128     HBA_LIBRARY_INFO	*lib_infop;
2129     HBA_HANDLE		vendorHandle;
2130     HBAGetPortAttributesByWWNFunc
2131 			GetPortAttributesByWWNFunc;
2132 
2133     DEBUG(2, "HBA_GetPortAttributesByWWN: %s", WWN2STR1(&PortWWN), 0, 0);
2134 
2135     CHECKLIBRARY();
2136     GetPortAttributesByWWNFunc =
2137 	lib_infop->functionTable.GetPortAttributesByWWNHandler;
2138     if (GetPortAttributesByWWNFunc != NULL) {
2139 	status = ((GetPortAttributesByWWNFunc)
2140 		  (vendorHandle, PortWWN, portattributes));
2141     } else {
2142 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2143     }
2144     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2145 }
2146 
2147 HBA_STATUS
2148 HBA_SendCTPassThru (
2149     HBA_HANDLE		handle,
2150     void		*pReqBuffer,
2151     HBA_UINT32		ReqBufferSize,
2152     void		*pRspBuffer,
2153     HBA_UINT32		RspBufferSize)
2154 {
2155     HBA_STATUS		status;
2156     HBA_LIBRARY_INFO	*lib_infop;
2157     HBA_HANDLE		vendorHandle;
2158     HBASendCTPassThruFunc
2159 			SendCTPassThruFunc;
2160 
2161     DEBUG(2, "HBA_SendCTPassThru", 0, 0, 0);
2162 
2163     CHECKLIBRARY();
2164     SendCTPassThruFunc = lib_infop->functionTable.SendCTPassThruHandler;
2165     if (SendCTPassThruFunc != NULL) {
2166 	status = (SendCTPassThruFunc)
2167 	    (vendorHandle,
2168 	     pReqBuffer, ReqBufferSize,
2169 	     pRspBuffer, RspBufferSize);
2170     } else {
2171 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2172     }
2173     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2174 }
2175 
2176 HBA_STATUS
2177 HBA_SendCTPassThruV2 (
2178     HBA_HANDLE		handle,
2179     HBA_WWN		hbaPortWWN,
2180     void		*pReqBuffer,
2181     HBA_UINT32		ReqBufferSize,
2182     void		*pRspBuffer,
2183     HBA_UINT32		*pRspBufferSize)
2184 {
2185     HBA_STATUS		status;
2186     HBA_LIBRARY_INFO	*lib_infop;
2187     HBA_HANDLE		vendorHandle;
2188     HBASendCTPassThruV2Func
2189 			registeredfunc;
2190 
2191     DEBUG(2, "HBA_SendCTPassThruV2m hbaPortWWN: %s", WWN2STR1(&hbaPortWWN), 0, 0);
2192 
2193     CHECKLIBRARY();
2194     registeredfunc = lib_infop->functionTable.SendCTPassThruV2Handler;
2195     if (registeredfunc != NULL) {
2196 	status = (registeredfunc)
2197 	    (vendorHandle, hbaPortWWN,
2198 	     pReqBuffer, ReqBufferSize,
2199 	     pRspBuffer, pRspBufferSize);
2200     } else {
2201 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2202     }
2203     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2204 }
2205 
2206 HBA_STATUS
2207 HBA_GetEventBuffer (
2208     HBA_HANDLE		handle,
2209     PHBA_EVENTINFO	EventBuffer,
2210     HBA_UINT32		*EventBufferCount)
2211 {
2212     HBA_STATUS		status;
2213     HBA_LIBRARY_INFO	*lib_infop;
2214     HBA_HANDLE		vendorHandle;
2215     HBAGetEventBufferFunc
2216 			GetEventBufferFunc;
2217 
2218     DEBUG(2, "HBA_GetEventBuffer", 0, 0, 0);
2219 
2220     CHECKLIBRARY();
2221     GetEventBufferFunc = lib_infop->functionTable.GetEventBufferHandler;
2222     if (GetEventBufferFunc != NULL) {
2223 	status = (GetEventBufferFunc)
2224 	    (vendorHandle, EventBuffer, EventBufferCount);
2225     } else {
2226 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2227     }
2228     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2229 }
2230 
2231 HBA_STATUS
2232 HBA_SetRNIDMgmtInfo (HBA_HANDLE handle, HBA_MGMTINFO Info) {
2233     HBA_STATUS		status;
2234     HBA_LIBRARY_INFO	*lib_infop;
2235     HBA_HANDLE		vendorHandle;
2236     HBASetRNIDMgmtInfoFunc
2237 			SetRNIDMgmtInfoFunc;
2238 
2239     DEBUG(2, "HBA_SetRNIDMgmtInfo", 0, 0, 0);
2240 
2241     CHECKLIBRARY();
2242     SetRNIDMgmtInfoFunc = lib_infop->functionTable.SetRNIDMgmtInfoHandler;
2243     if (SetRNIDMgmtInfoFunc != NULL) {
2244 	status = (SetRNIDMgmtInfoFunc)(vendorHandle, Info);
2245     } else {
2246 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2247     }
2248     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2249 }
2250 
2251 HBA_STATUS
2252 HBA_GetRNIDMgmtInfo (HBA_HANDLE handle, HBA_MGMTINFO *pInfo) {
2253     HBA_STATUS		status;
2254     HBA_LIBRARY_INFO	*lib_infop;
2255     HBA_HANDLE		vendorHandle;
2256     HBAGetRNIDMgmtInfoFunc
2257 			 GetRNIDMgmtInfoFunc;
2258 
2259     DEBUG(2, "HBA_GetRNIDMgmtInfo", 0, 0, 0);
2260 
2261     CHECKLIBRARY();
2262     GetRNIDMgmtInfoFunc = lib_infop->functionTable.GetRNIDMgmtInfoHandler;
2263     if (GetRNIDMgmtInfoFunc != NULL) {
2264 	status = (GetRNIDMgmtInfoFunc)(vendorHandle, pInfo);
2265     } else {
2266 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2267     }
2268     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2269 }
2270 
2271 HBA_STATUS
2272 HBA_SendRNID (
2273     HBA_HANDLE		handle,
2274     HBA_WWN		wwn,
2275     HBA_WWNTYPE		wwntype,
2276     void		*pRspBuffer,
2277     HBA_UINT32		*pRspBufferSize)
2278 {
2279     HBA_STATUS		status;
2280     HBA_LIBRARY_INFO	*lib_infop;
2281     HBA_HANDLE		vendorHandle;
2282     HBASendRNIDFunc	SendRNIDFunc;
2283 
2284     DEBUG(2, "HBA_SendRNID for wwn: %s", WWN2STR1(&wwn), 0, 0);
2285 
2286     CHECKLIBRARY();
2287     SendRNIDFunc = lib_infop->functionTable.SendRNIDHandler;
2288     if (SendRNIDFunc != NULL) {
2289 	status = ((SendRNIDFunc)(vendorHandle, wwn, wwntype,
2290 				 pRspBuffer, pRspBufferSize));
2291     } else {
2292 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2293     }
2294     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2295 }
2296 
2297 HBA_STATUS
2298 HBA_SendRNIDV2(
2299     HBA_HANDLE		handle,
2300     HBA_WWN		hbaPortWWN,
2301     HBA_WWN		destWWN,
2302     HBA_UINT32		destFCID,
2303     HBA_UINT32		NodeIdDataFormat,
2304     void		*pRspBuffer,
2305     HBA_UINT32		*pRspBufferSize)
2306 {
2307     HBA_STATUS		status;
2308     HBA_LIBRARY_INFO	*lib_infop;
2309     HBA_HANDLE		vendorHandle;
2310     HBASendRNIDV2Func	registeredfunc;
2311 
2312     DEBUG(2, "HBA_SendRNIDV2, hbaPortWWN: %s", WWN2STR1(&hbaPortWWN), 0, 0);
2313 
2314     CHECKLIBRARY();
2315     registeredfunc = lib_infop->functionTable.SendRNIDV2Handler;
2316     if (registeredfunc != NULL) {
2317 	status = (registeredfunc)
2318 	    (vendorHandle, hbaPortWWN, destWWN, destFCID, NodeIdDataFormat,
2319 	     pRspBuffer, pRspBufferSize);
2320     } else {
2321 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2322     }
2323     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2324 }
2325 
2326 void
2327 HBA_RefreshInformation (HBA_HANDLE handle) {
2328     HBA_STATUS		status;
2329     HBA_LIBRARY_INFO	*lib_infop;
2330     HBA_HANDLE		vendorHandle;
2331     HBARefreshInformationFunc
2332 			RefreshInformationFunc;
2333 
2334     DEBUG(2, "HBA_RefreshInformation", 0, 0, 0);
2335 
2336     status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);
2337     if(status == HBA_STATUS_OK) {
2338 	RefreshInformationFunc =
2339 	    lib_infop->functionTable.RefreshInformationHandler;
2340 	if (RefreshInformationFunc != NULL) {
2341 	    ((RefreshInformationFunc)(vendorHandle));
2342 	}
2343 	RELEASE_MUTEX(&_hbaapi_LL_mutex);
2344     }
2345 }
2346 
2347 void
2348 HBA_ResetStatistics (HBA_HANDLE handle, HBA_UINT32 portindex) {
2349     HBA_STATUS		status;
2350     HBA_LIBRARY_INFO	*lib_infop;
2351     HBA_HANDLE		vendorHandle;
2352     HBAResetStatisticsFunc
2353 			ResetStatisticsFunc;
2354 
2355     DEBUG(2, "HBA_ResetStatistics", 0, 0, 0);
2356 
2357     status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);
2358     if(status == HBA_STATUS_OK) {
2359 	ResetStatisticsFunc = lib_infop->functionTable.ResetStatisticsHandler;
2360 	if (ResetStatisticsFunc != NULL) {
2361 	    ((ResetStatisticsFunc)(vendorHandle, portindex));
2362 	}
2363 	RELEASE_MUTEX(&_hbaapi_LL_mutex);
2364     }
2365 }
2366 
2367 HBA_STATUS
2368 HBA_GetFcpTargetMapping (HBA_HANDLE handle, PHBA_FCPTARGETMAPPING mapping) {
2369     HBA_STATUS		status;
2370     HBA_LIBRARY_INFO	*lib_infop;
2371     HBA_HANDLE		vendorHandle;
2372     HBAGetFcpTargetMappingFunc GetFcpTargetMappingFunc;
2373 
2374     DEBUG(2, "HBA_GetFcpTargetMapping", 0, 0, 0);
2375 
2376     CHECKLIBRARY();
2377     GetFcpTargetMappingFunc =
2378 	lib_infop->functionTable.GetFcpTargetMappingHandler;
2379     if (GetFcpTargetMappingFunc != NULL) {
2380 	status = ((GetFcpTargetMappingFunc)(vendorHandle, mapping));
2381     } else {
2382 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2383     }
2384     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2385 }
2386 
2387 HBA_STATUS
2388 HBA_GetFcpTargetMappingV2 (
2389     HBA_HANDLE		handle,
2390     HBA_WWN		hbaPortWWN,
2391     HBA_FCPTARGETMAPPINGV2
2392     			*pmapping)
2393 {
2394     HBA_STATUS		status;
2395     HBA_LIBRARY_INFO	*lib_infop;
2396     HBA_HANDLE		vendorHandle;
2397     HBAGetFcpTargetMappingV2Func
2398 			registeredfunc;
2399 
2400     DEBUG(2, "HBA_GetFcpTargetMapping", 0, 0, 0);
2401 
2402     CHECKLIBRARY();
2403     registeredfunc =
2404 	lib_infop->functionTable.GetFcpTargetMappingV2Handler;
2405     if (registeredfunc != NULL) {
2406 	status = ((registeredfunc)(vendorHandle, hbaPortWWN, pmapping));
2407     } else {
2408 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2409     }
2410     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2411 }
2412 
2413 HBA_STATUS
2414 HBA_GetFcpPersistentBinding (HBA_HANDLE handle, PHBA_FCPBINDING binding) {
2415     HBA_STATUS		status;
2416     HBA_LIBRARY_INFO	*lib_infop;
2417     HBA_HANDLE		vendorHandle;
2418     HBAGetFcpPersistentBindingFunc
2419 			GetFcpPersistentBindingFunc;
2420 
2421     DEBUG(2, "HBA_GetFcpPersistentBinding", 0, 0, 0);
2422 
2423     CHECKLIBRARY();
2424     GetFcpPersistentBindingFunc =
2425 	lib_infop->functionTable.GetFcpPersistentBindingHandler;
2426     if (GetFcpPersistentBindingFunc != NULL) {
2427 	status = ((GetFcpPersistentBindingFunc)(vendorHandle, binding));
2428     } else {
2429 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2430     }
2431     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2432 }
2433 
2434 HBA_STATUS
2435 HBA_ScsiInquiryV2 (
2436     HBA_HANDLE	handle,
2437     HBA_WWN	hbaPortWWN,
2438     HBA_WWN	discoveredPortWWN,
2439     HBA_UINT64	fcLUN,
2440     HBA_UINT8	CDB_Byte1,
2441     HBA_UINT8	CDB_Byte2,
2442     void	*pRspBuffer,
2443     HBA_UINT32	*pRspBufferSize,
2444     HBA_UINT8	*pScsiStatus,
2445     void	*pSenseBuffer,
2446     HBA_UINT32	*pSenseBufferSize)
2447 {
2448     HBA_STATUS		status;
2449     HBA_LIBRARY_INFO	*lib_infop;
2450     HBA_HANDLE		vendorHandle;
2451     HBAScsiInquiryV2Func ScsiInquiryV2Func;
2452 
2453     DEBUG(2, "HBA_ScsiInquiryV2 to discoveredPortWWN: %s",
2454 	  WWN2STR1(&discoveredPortWWN), 0, 0);
2455 
2456     CHECKLIBRARY();
2457     ScsiInquiryV2Func =
2458 	lib_infop->functionTable.ScsiInquiryV2Handler;
2459     if (ScsiInquiryV2Func != NULL) {
2460 	status =((ScsiInquiryV2Func)(
2461 	    vendorHandle, hbaPortWWN, discoveredPortWWN, fcLUN, CDB_Byte1,
2462 	    CDB_Byte2, pRspBuffer, pRspBufferSize, pScsiStatus,
2463 	    pSenseBuffer, pSenseBufferSize));
2464     } else {
2465 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2466     }
2467     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2468 }
2469 
2470 HBA_STATUS
2471 HBA_SendScsiInquiry (
2472     HBA_HANDLE	handle,
2473     HBA_WWN	PortWWN,
2474     HBA_UINT64	fcLUN,
2475     HBA_UINT8	EVPD,
2476     HBA_UINT32	PageCode,
2477     void	*pRspBuffer,
2478     HBA_UINT32	RspBufferSize,
2479     void	*pSenseBuffer,
2480     HBA_UINT32	SenseBufferSize)
2481 {
2482     HBA_STATUS		status;
2483     HBA_LIBRARY_INFO	*lib_infop;
2484     HBA_HANDLE		vendorHandle;
2485     HBASendScsiInquiryFunc SendScsiInquiryFunc;
2486 
2487     DEBUG(2, "HBA_SendScsiInquiry to PortWWN: %s", WWN2STR1(&PortWWN), 0, 0);
2488 
2489     CHECKLIBRARY();
2490     SendScsiInquiryFunc = lib_infop->functionTable.ScsiInquiryHandler;
2491     if (SendScsiInquiryFunc != NULL) {
2492 	status =((SendScsiInquiryFunc)(
2493 	    vendorHandle, PortWWN, fcLUN, EVPD, PageCode, pRspBuffer,
2494 	    RspBufferSize, pSenseBuffer, SenseBufferSize));
2495     } else {
2496 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2497     }
2498     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2499 }
2500 
2501 HBA_STATUS
2502 HBA_ScsiReportLUNsV2 (
2503     HBA_HANDLE		handle,
2504     HBA_WWN		hbaPortWWN,
2505     HBA_WWN		discoveredPortWWN,
2506     void		*pRespBuffer,
2507     HBA_UINT32		*pRespBufferSize,
2508     HBA_UINT8		*pScsiStatus,
2509     void		*pSenseBuffer,
2510     HBA_UINT32		*pSenseBufferSize)
2511 {
2512     HBA_STATUS		status;
2513     HBA_LIBRARY_INFO	*lib_infop;
2514     HBA_HANDLE		vendorHandle;
2515     HBAScsiReportLUNsV2Func ScsiReportLUNsV2Func;
2516 
2517     DEBUG(2, "HBA_ScsiReportLUNsV2 to discoveredPortWWN: %s",
2518 	  WWN2STR1(&discoveredPortWWN), 0, 0);
2519 
2520     CHECKLIBRARY();
2521     ScsiReportLUNsV2Func = lib_infop->functionTable.ScsiReportLUNsV2Handler;
2522     if (ScsiReportLUNsV2Func != NULL) {
2523 	status = ((ScsiReportLUNsV2Func)(
2524 	    vendorHandle, hbaPortWWN, discoveredPortWWN,
2525 	    pRespBuffer, pRespBufferSize,
2526 	    pScsiStatus,
2527 	    pSenseBuffer, pSenseBufferSize));
2528     } else {
2529 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2530     }
2531     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2532 }
2533 
2534 HBA_STATUS
2535 HBA_SendReportLUNs (
2536     HBA_HANDLE handle,
2537     HBA_WWN portWWN,
2538     void *pRspBuffer,
2539     HBA_UINT32 RspBufferSize,
2540     void *pSenseBuffer,
2541     HBA_UINT32 SenseBufferSize)
2542 {
2543     HBA_STATUS		status;
2544     HBA_LIBRARY_INFO	*lib_infop;
2545     HBA_HANDLE		vendorHandle;
2546     HBASendReportLUNsFunc SendReportLUNsFunc;
2547 
2548     DEBUG(2, "HBA_SendReportLUNs to PortWWN: %s", WWN2STR1(&portWWN), 0, 0);
2549 
2550     CHECKLIBRARY();
2551     SendReportLUNsFunc = lib_infop->functionTable.ReportLUNsHandler;
2552     if (SendReportLUNsFunc != NULL) {
2553 	status = ((SendReportLUNsFunc)(
2554 	    vendorHandle, portWWN, pRspBuffer,
2555 	    RspBufferSize, pSenseBuffer, SenseBufferSize));
2556     } else {
2557 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2558     }
2559     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2560 }
2561 
2562 HBA_STATUS
2563 HBA_ScsiReadCapacityV2 (
2564     HBA_HANDLE		handle,
2565     HBA_WWN		hbaPortWWN,
2566     HBA_WWN		discoveredPortWWN,
2567     HBA_UINT64		fcLUN,
2568     void		*pRspBuffer,
2569     HBA_UINT32		*pRspBufferSize,
2570     HBA_UINT8		*pScsiStatus,
2571     void		*pSenseBuffer,
2572     HBA_UINT32		*SenseBufferSize)
2573 {
2574     HBA_STATUS		status;
2575     HBA_LIBRARY_INFO	*lib_infop;
2576     HBA_HANDLE		vendorHandle;
2577     HBAScsiReadCapacityV2Func ScsiReadCapacityV2Func;
2578 
2579     DEBUG(2, "HBA_ScsiReadCapacityV2 to discoveredPortWWN: %s",
2580 	  WWN2STR1(&discoveredPortWWN), 0, 0);
2581 
2582     CHECKLIBRARY();
2583     ScsiReadCapacityV2Func =
2584 	lib_infop->functionTable.ScsiReadCapacityV2Handler;
2585     if (ScsiReadCapacityV2Func != NULL) {
2586 	status =((ScsiReadCapacityV2Func)(
2587 	    vendorHandle, hbaPortWWN, discoveredPortWWN, fcLUN,
2588 	    pRspBuffer, pRspBufferSize,
2589 	    pScsiStatus,
2590 	    pSenseBuffer, SenseBufferSize));
2591     } else {
2592 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2593     }
2594     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2595 }
2596 
2597 HBA_STATUS
2598 HBA_SendReadCapacity (
2599     HBA_HANDLE handle,
2600     HBA_WWN portWWN,
2601     HBA_UINT64 fcLUN,
2602     void *pRspBuffer,
2603     HBA_UINT32 RspBufferSize,
2604     void *pSenseBuffer,
2605     HBA_UINT32 SenseBufferSize)
2606 {
2607     HBA_STATUS		status;
2608     HBA_LIBRARY_INFO	*lib_infop;
2609     HBA_HANDLE		vendorHandle;
2610     HBASendReadCapacityFunc SendReadCapacityFunc;
2611 
2612     DEBUG(2, "HBA_SendReadCapacity to portWWN: %s", WWN2STR1(&portWWN), 0, 0);
2613 
2614     CHECKLIBRARY();
2615     SendReadCapacityFunc = lib_infop->functionTable.ReadCapacityHandler;
2616     if (SendReadCapacityFunc != NULL) {
2617 	status =((SendReadCapacityFunc)
2618 		 (vendorHandle, portWWN, fcLUN, pRspBuffer,
2619 		  RspBufferSize, pSenseBuffer, SenseBufferSize));
2620     } else {
2621 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2622     }
2623     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2624 }
2625 
2626 HBA_STATUS
2627 HBA_SendRLS (
2628     HBA_HANDLE		handle,
2629     HBA_WWN		hbaPortWWN,
2630     HBA_WWN		destWWN,
2631     void		*pRspBuffer,
2632     HBA_UINT32		*pRspBufferSize)
2633 {
2634     HBA_STATUS		status;
2635     HBA_LIBRARY_INFO	*lib_infop;
2636     HBA_HANDLE		vendorHandle;
2637     HBASendRLSFunc registeredfunc;
2638 
2639     DEBUG(2, "HBA_SendRLS to agent_wwn: %s:%d",
2640 	  WWN2STR1(&agent_wwn), agent_domain, 0);
2641 
2642     CHECKLIBRARY();
2643     registeredfunc = lib_infop->functionTable.SendRLSHandler;
2644     if (registeredfunc != NULL) {
2645 	status =(registeredfunc)(
2646 	    vendorHandle, hbaPortWWN, destWWN, pRspBuffer, pRspBufferSize);
2647     } else {
2648 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2649     }
2650     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2651 }
2652 
2653 HBA_STATUS
2654 HBA_SendRPL (
2655     HBA_HANDLE		handle,
2656     HBA_WWN		hbaPortWWN,
2657     HBA_WWN		agent_wwn,
2658     HBA_UINT32		agent_domain,
2659     HBA_UINT32		portindex,
2660     void		*pRspBuffer,
2661     HBA_UINT32		*pRspBufferSize)
2662 {
2663     HBA_STATUS		status;
2664     HBA_LIBRARY_INFO	*lib_infop;
2665     HBA_HANDLE		vendorHandle;
2666     HBASendRPLFunc registeredfunc;
2667 
2668     DEBUG(2, "HBA_SendRPL to agent_wwn: %s:%d",
2669 	  WWN2STR1(&agent_wwn), agent_domain, 0);
2670 
2671     CHECKLIBRARY();
2672     registeredfunc = lib_infop->functionTable.SendRPLHandler;
2673     if (registeredfunc != NULL) {
2674 	status =(registeredfunc)(
2675 	    vendorHandle, hbaPortWWN, agent_wwn, agent_domain, portindex,
2676 	    pRspBuffer, pRspBufferSize);
2677     } else {
2678 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2679     }
2680     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2681 }
2682 
2683 HBA_STATUS
2684 HBA_SendRPS (
2685     HBA_HANDLE		handle,
2686     HBA_WWN		hbaPortWWN,
2687     HBA_WWN		agent_wwn,
2688     HBA_UINT32		agent_domain,
2689     HBA_WWN		object_wwn,
2690     HBA_UINT32		object_port_number,
2691     void		*pRspBuffer,
2692     HBA_UINT32		*pRspBufferSize)
2693 {
2694     HBA_STATUS		status;
2695     HBA_LIBRARY_INFO	*lib_infop;
2696     HBA_HANDLE		vendorHandle;
2697     HBASendRPSFunc registeredfunc;
2698 
2699     DEBUG(2, "HBA_SendRPS  to agent_wwn: %s:%d",
2700 	  WWN2STR1(&agent_wwn), agent_domain, 0);
2701 
2702     CHECKLIBRARY();
2703     registeredfunc = lib_infop->functionTable.SendRPSHandler;
2704     if (registeredfunc != NULL) {
2705 	status =(registeredfunc)(
2706 	    vendorHandle, hbaPortWWN, agent_wwn, agent_domain,
2707 	    object_wwn, object_port_number,
2708 	    pRspBuffer, pRspBufferSize);
2709     } else {
2710 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2711     }
2712     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2713 }
2714 
2715 HBA_STATUS
2716 HBA_SendSRL (
2717     HBA_HANDLE		handle,
2718     HBA_WWN		hbaPortWWN,
2719     HBA_WWN		wwn,
2720     HBA_UINT32		domain,
2721     void		*pRspBuffer,
2722     HBA_UINT32		*pRspBufferSize)
2723 {
2724     HBA_STATUS		status;
2725     HBA_LIBRARY_INFO	*lib_infop;
2726     HBA_HANDLE		vendorHandle;
2727     HBASendSRLFunc registeredfunc;
2728 
2729     DEBUG(2, "HBA_SendSRL to wwn:%s domain:%d", WWN2STR1(&wwn), domain, 0);
2730 
2731     CHECKLIBRARY();
2732     registeredfunc = lib_infop->functionTable.SendSRLHandler;
2733     if (registeredfunc != NULL) {
2734 	status =(registeredfunc)(
2735 	    vendorHandle, hbaPortWWN, wwn, domain,
2736 	    pRspBuffer, pRspBufferSize);
2737     } else {
2738 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2739     }
2740     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2741 }
2742 
2743 HBA_STATUS
2744 HBA_SendLIRR (
2745     HBA_HANDLE		handle,
2746     HBA_WWN		sourceWWN,
2747     HBA_WWN		destWWN,
2748     HBA_UINT8		function,
2749     HBA_UINT8		type,
2750     void		*pRspBuffer,
2751     HBA_UINT32		*pRspBufferSize)
2752 {
2753     HBA_STATUS		status;
2754     HBA_LIBRARY_INFO	*lib_infop;
2755     HBA_HANDLE		vendorHandle;
2756     HBASendLIRRFunc registeredfunc;
2757 
2758     DEBUG(2, "HBA_SendLIRR destWWN:%s", WWN2STR1(&destWWN), 0, 0);
2759 
2760     CHECKLIBRARY();
2761     registeredfunc = lib_infop->functionTable.SendLIRRHandler;
2762     if (registeredfunc != NULL) {
2763 	status =(registeredfunc)(
2764 	    vendorHandle, sourceWWN, destWWN, function, type,
2765 	    pRspBuffer, pRspBufferSize);
2766     } else {
2767 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2768     }
2769     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2770 }
2771 
2772 HBA_STATUS
2773 HBA_GetBindingCapability(
2774     HBA_HANDLE		handle,
2775     HBA_WWN		hbaPortWWN,
2776     HBA_BIND_CAPABILITY *pcapability)
2777 {
2778     HBA_STATUS		status;
2779     HBA_LIBRARY_INFO	*lib_infop;
2780     HBA_HANDLE		vendorHandle;
2781     HBAGetBindingCapabilityFunc
2782 			registeredfunc;
2783 
2784     DEBUG(2, "HBA_GetBindingCapability", 0, 0, 0);
2785 
2786     CHECKLIBRARY();
2787     registeredfunc = lib_infop->functionTable.GetBindingCapabilityHandler;
2788     if (registeredfunc != NULL) {
2789 	status =(registeredfunc)(vendorHandle, hbaPortWWN, pcapability);
2790     } else {
2791 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2792     }
2793     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2794 }
2795 
2796 HBA_STATUS
2797 HBA_GetBindingSupport (
2798     HBA_HANDLE		handle,
2799     HBA_WWN		hbaPortWWN,
2800     HBA_BIND_CAPABILITY *pcapability)
2801 {
2802     HBA_STATUS		status;
2803     HBA_LIBRARY_INFO	*lib_infop;
2804     HBA_HANDLE		vendorHandle;
2805     HBAGetBindingSupportFunc
2806 			registeredfunc;
2807 
2808     DEBUG(2, "HBA_GetBindingSupport", 0, 0, 0);
2809 
2810     CHECKLIBRARY();
2811     registeredfunc = lib_infop->functionTable.GetBindingSupportHandler;
2812     if (registeredfunc != NULL) {
2813 	status =(registeredfunc)(vendorHandle, hbaPortWWN, pcapability);
2814     } else {
2815 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2816     }
2817     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2818 }
2819 
2820 HBA_STATUS
2821 HBA_SetBindingSupport(
2822     HBA_HANDLE		handle,
2823     HBA_WWN		hbaPortWWN,
2824     HBA_BIND_CAPABILITY capability)
2825 {
2826     HBA_STATUS		status;
2827     HBA_LIBRARY_INFO	*lib_infop;
2828     HBA_HANDLE		vendorHandle;
2829     HBASetBindingSupportFunc
2830 			registeredfunc;
2831 
2832     DEBUG(2, "HBA_SetBindingSupport", 0, 0, 0);
2833 
2834     CHECKLIBRARY();
2835     registeredfunc = lib_infop->functionTable.SetBindingSupportHandler;
2836     if (registeredfunc != NULL) {
2837 	status =(registeredfunc)(vendorHandle, hbaPortWWN, capability);
2838     } else {
2839 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2840     }
2841     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2842 }
2843 
2844 HBA_STATUS
2845 HBA_SetPersistentBindingV2 (
2846     HBA_HANDLE		handle,
2847     HBA_WWN		hbaPortWWN,
2848     const HBA_FCPBINDING2
2849     			*pbinding)
2850 {
2851     HBA_STATUS		status;
2852     HBA_LIBRARY_INFO	*lib_infop;
2853     HBA_HANDLE		vendorHandle;
2854     HBASetPersistentBindingV2Func
2855 			registeredfunc;
2856 
2857     DEBUG(2, "HBA_SetPersistentBindingV2 port: %s", WWN2STR1(&hbaPortWWN), 0, 0);
2858 
2859     CHECKLIBRARY();
2860     registeredfunc = lib_infop->functionTable.SetPersistentBindingV2Handler;
2861     if (registeredfunc != NULL) {
2862 	status =(registeredfunc)(vendorHandle, hbaPortWWN, pbinding);
2863     } else {
2864 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2865     }
2866     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2867 }
2868 
2869 HBA_STATUS
2870 HBA_GetPersistentBindingV2 (
2871     HBA_HANDLE		handle,
2872     HBA_WWN		hbaPortWWN,
2873     HBA_FCPBINDING2	*pbinding)
2874 {
2875     HBA_STATUS		status;
2876     HBA_LIBRARY_INFO	*lib_infop;
2877     HBA_HANDLE		vendorHandle;
2878     HBAGetPersistentBindingV2Func
2879 			registeredfunc;
2880 
2881     DEBUG(2, "HBA_GetPersistentBindingV2 port: %s", WWN2STR1(&hbaPortWWN), 0, 0);
2882 
2883     CHECKLIBRARY();
2884     registeredfunc = lib_infop->functionTable.GetPersistentBindingV2Handler;
2885     if (registeredfunc != NULL) {
2886 	status =(registeredfunc)(vendorHandle, hbaPortWWN, pbinding);
2887     } else {
2888 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2889     }
2890     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2891 }
2892 
2893 HBA_STATUS
2894 HBA_RemovePersistentBinding (
2895     HBA_HANDLE		handle,
2896     HBA_WWN		hbaPortWWN,
2897     const HBA_FCPBINDING2
2898 			*pbinding)
2899 {
2900     HBA_STATUS		status;
2901     HBA_LIBRARY_INFO	*lib_infop;
2902     HBA_HANDLE		vendorHandle;
2903     HBARemovePersistentBindingFunc
2904 			registeredfunc;
2905 
2906     DEBUG(2, "HBA_RemovePersistentBinding", 0, 0, 0);
2907 
2908     CHECKLIBRARY();
2909     registeredfunc =
2910 	lib_infop->functionTable.RemovePersistentBindingHandler;
2911     if (registeredfunc != NULL) {
2912 	status =(registeredfunc)(vendorHandle, hbaPortWWN, pbinding);
2913     } else {
2914 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2915     }
2916     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2917 }
2918 
2919 HBA_STATUS
2920 HBA_RemoveAllPersistentBindings (
2921     HBA_HANDLE		handle,
2922     HBA_WWN		hbaPortWWN)
2923 {
2924     HBA_STATUS		status;
2925     HBA_LIBRARY_INFO	*lib_infop;
2926     HBA_HANDLE		vendorHandle;
2927     HBARemoveAllPersistentBindingsFunc
2928 			registeredfunc;
2929 
2930     DEBUG(2, "HBA_RemoveAllPersistentBindings", 0, 0, 0);
2931 
2932     CHECKLIBRARY();
2933     registeredfunc =
2934 	lib_infop->functionTable.RemoveAllPersistentBindingsHandler;
2935     if (registeredfunc != NULL) {
2936 	status =(registeredfunc)(vendorHandle, hbaPortWWN);
2937     } else {
2938 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2939     }
2940     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2941 }
2942 
2943 HBA_STATUS
2944 HBA_GetFC4Statistics (
2945     HBA_HANDLE		handle,
2946     HBA_WWN		portWWN,
2947     HBA_UINT8		FC4type,
2948     HBA_FC4STATISTICS	*pstatistics)
2949 {
2950     HBA_STATUS		status;
2951     HBA_LIBRARY_INFO	*lib_infop;
2952     HBA_HANDLE		vendorHandle;
2953     HBAGetFC4StatisticsFunc
2954 			registeredfunc;
2955 
2956     DEBUG(2, "HBA_GetFC4Statistics port: %s", WWN2STR1(&portWWN), 0, 0);
2957 
2958     CHECKLIBRARY();
2959     registeredfunc =
2960 	lib_infop->functionTable.GetFC4StatisticsHandler;
2961     if (registeredfunc != NULL) {
2962 	status =(registeredfunc)
2963 	    (vendorHandle, portWWN, FC4type, pstatistics);
2964     } else {
2965 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2966     }
2967     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2968 }
2969 
2970 HBA_STATUS
2971 HBA_GetFCPStatistics (
2972     HBA_HANDLE		handle,
2973     const HBA_SCSIID	*lunit,
2974     HBA_FC4STATISTICS	*pstatistics)
2975 {
2976     HBA_STATUS		status;
2977     HBA_LIBRARY_INFO	*lib_infop;
2978     HBA_HANDLE		vendorHandle;
2979     HBAGetFCPStatisticsFunc
2980 			registeredfunc;
2981 
2982     DEBUG(2, "HBA_GetFCPStatistics", 0, 0, 0);
2983 
2984     CHECKLIBRARY();
2985     registeredfunc =
2986 	lib_infop->functionTable.GetFCPStatisticsHandler;
2987     if (registeredfunc != NULL) {
2988 	status =(registeredfunc)(vendorHandle, lunit, pstatistics);
2989     } else {
2990 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2991     }
2992     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2993 }
2994 
2995 HBA_UINT32
2996 HBA_GetVendorLibraryAttributes (
2997     HBA_UINT32 adapter_index,
2998     HBA_LIBRARYATTRIBUTES *attributes)
2999 {
3000     HBA_ADAPTER_INFO	*adapt_infop;
3001     HBAGetVendorLibraryAttributesFunc
3002 			registeredfunc;
3003     HBA_UINT32		ret = 0;
3004 
3005     DEBUG(2, "HBA_GetVendorLibraryAttributes adapterindex:%d",
3006 	  adapter_index, 0, 0);
3007     if(_hbaapi_librarylist == NULL) {
3008 	DEBUG(1, "HBAAPI not loaded yet.", 0, 0, 0);
3009 	return(0);
3010     }
3011 
3012     if (attributes == NULL) {
3013 	    return(HBA_STATUS_ERROR_ARG);
3014     }
3015 
3016     memset(attributes, 0, sizeof(HBA_LIBRARYATTRIBUTES));
3017 
3018     GRAB_MUTEX(&_hbaapi_LL_mutex);
3019     GRAB_MUTEX(&_hbaapi_AL_mutex);
3020     for(adapt_infop = _hbaapi_adapterlist;
3021 	adapt_infop != NULL;
3022 	adapt_infop = adapt_infop->next) {
3023 
3024 	if(adapt_infop->index == adapter_index) {
3025 	    registeredfunc = adapt_infop->library->
3026 		functionTable.GetVendorLibraryAttributesHandler;
3027 	    if(registeredfunc != NULL) {
3028 		ret = (registeredfunc)(attributes);
3029 	    } else {
3030 		/* Version 1 libary? */
3031 		HBAGetVersionFunc	GetVersionFunc;
3032 		GetVersionFunc = adapt_infop->library->
3033 		    functionTable.GetVersionHandler;
3034 		if(GetVersionFunc != NULL) {
3035 		    ret = ((GetVersionFunc)());
3036 		}
3037 #ifdef NOTDEF
3038 		else {
3039 		    /* This should not happen, dont think its going to */
3040 		}
3041 #endif
3042 	    }
3043 	    if (attributes->LibPath[0] == '\0') {
3044 		if(strlen(adapt_infop->library->LibraryPath) < 256) {
3045 		    strcpy(attributes->LibPath,
3046 			   adapt_infop->library->LibraryPath);
3047 		}
3048 	    }
3049 	    break;
3050 	}
3051     }
3052     RELEASE_MUTEX(&_hbaapi_AL_mutex);
3053     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, ret);
3054 }
3055