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