xref: /illumos-gate/usr/src/lib/smhba/common/SMHBAAPILIB.c (revision 77c0a660417a046bfab6c8ef58d00c181c0264b3)
1 /*
2  * ************************************************************************
3  * Description
4  *	HBAAPILIB.c - Implements a sample common (wrapper) HBA API library
5  *
6  * License:
7  *	The contents of this file are subject to the SNIA Public License
8  *	Version 1.0 (the "License"); you may not use this file except in
9  *	compliance with the License. You may obtain a copy of the License at
10  *
11  *	/http://www.snia.org/English/Resources/Code/OpenSource.html
12  *
13  *	Software distributed under the License is distributed on an "AS IS"
14  *	basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
15  *	the License for the specific language governing rights and limitations
16  *	under the License.
17  *
18  * The Original Code is  SNIA HBA API Wrapper Library
19  *
20  * The Initial Developer of the Original Code is:
21  *	Benjamin F. Kuo, Troika Networks, Inc. (benk@troikanetworks.com)
22  *
23  * Contributor(s):
24  *	Tuan Lam, QLogic Corp. (t_lam@qlc.com)
25  *	Dan Willie, Emulex Corp. (Dan.Willie@emulex.com)
26  *	Dixon Hutchinson, Legato Systems, Inc. (dhutchin@legato.com)
27  *	David Dillard, VERITAS Software Corp. (david.dillard@veritas.com)
28  *
29  * ************************************************************************
30  *
31  * Adding on SM-HBA support
32  *
33  * The implementation includes Three different categories functions to support
34  * both HBAAPI and SM-HBA through the same library.
35  *
36  * SM-HBA unique interface:
37  *	1. CHECKLIBRARYANDVERSION(SMHBA) : match SMHBA VSL
38  *	   Or checking specifically if version is SMHBA beforehand.
39  *	2. resolved to ftable.smhbafunctiontable.{interface}
40  * HBAAPIV2 unique functions
41  *	1. CHECKLIBRARYANDVERSION(HBAAPIV2) : validate and match HBAAPI V2 VSL.
42  *	   Or checking specifically if version is HBAAPIV2 beforehand.
43  *	2. resolved to ftable.functiontable.{interface}
44  * Common interface between SM-HBA and HBAAPIV2.
45  *	1. CHECKLIBRARY() : to validate the VSL.
46  *	2. FUNCCOMMON macro to map the appropriate entry point table
47  *	    (union ftable).
48  *	3. If the interface is not supported by HBAAPI(Version 1)
49  *	   the funtiion ptr will be set to NULL.
50  * Common interface between HBAAPI and HBAAPIV2.
51  *	1. Check if version is not SMHBA).
52  *	2. ftable.functiontalbe.(interface)
53  *
54  * ************************************************************************
55  */
56 /*
57  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
58  * Use is subject to license terms.
59  */
60 
61 #ifdef WIN32
62 #include <windows.h>
63 #include <string.h>
64 /*
65  * Next define forces entry points in the dll to be exported
66  * See hbaapi.h to see what it does.
67  */
68 #define	HBAAPI_EXPORTS
69 #else
70 #include <dlfcn.h>
71 #include <strings.h>
72 #endif
73 #include <stdio.h>
74 #include <time.h>
75 #include "smhbaapi.h"
76 #include "vendorsmhbaapi.h"
77 #include <stdlib.h>
78 #ifdef USESYSLOG
79 #include <syslog.h>
80 #endif
81 #ifdef SOLARIS
82 #include <link.h>
83 #include <limits.h>
84 static int	*handle;
85 static Link_map *map, *mp;
86 #endif
87 
88 /*
89  * LIBRARY_NUM is a shortcut to figure out which library we need to call.
90  *  The top 16 bits of handle are the library index
91  */
92 #define	LIBRARY_NUM(handle)	((handle)>>16)
93 
94 /*
95  * VENDOR_HANDLE turns a global library handle into a vendor specific handle,
96  * with all upper 16 bits set to 0
97  */
98 #define	VENDOR_HANDLE(handle)	((handle)&0xFFFF)
99 
100 #define	HBA_HANDLE_FROM_LOCAL(library, vendor) \
101 				(((library)<<16) | ((vendor)&0x0000FFFF))
102 
103 int _hbaapi_debuglevel = 0;
104 #define	DEBUG(L, STR, A1, A2, A3)
105 
106 #if defined(USESYSLOG) && defined(USELOGFILE)
107 FILE *_hbaapi_debug_fd = NULL;
108 int _hbaapi_sysloginit = 0;
109 #undef DEBUG
110 #ifdef WIN32
111 #define	DEBUG(L, STR, A1, A2, A3)\
112     if ((L) <= _hbaapi_debuglevel) {\
113 	if (_hbaapi_sysloginit == 0) {\
114 	    openlog("HBAAPI", LOG_PID|LOG_ODELAY, LOG_USER);\
115 	    _hbaapi_sysloginit = 1;\
116 	}\
117 	syslog(LOG_INFO, (STR), (A1), (A2), (A3));\
118 	if (_hbaapi_debug_fd == NULL) {\
119 	    char _logFile[MAX_PATH]; \
120 	    GetTempPath(MAX_PATH, _logFile); \
121 	    strcat(_logFile, "HBAAPI.log"); \
122 	    _hbaapi_debug_fd = fopen(_logFile, "a");\
123 	}\
124 	if (_hbaapi_debug_fd != NULL) {\
125 	    fprintf(_hbaapi_debug_fd, #STR "\n", (A1), (A2), (A3));\
126 	}\
127 	}
128 #else /* WIN32 */
129 #define	DEBUG(L, STR, A1, A2, A3)\
130 	if ((L) <= _hbaapi_debuglevel) {\
131 	if (_hbaapi_sysloginit == 0) {\
132 	    openlog("HBAAPI", LOG_PID|LOG_ODELAY, LOG_USER);\
133 	    _hbaapi_sysloginit = 1;\
134 	}\
135 	syslog(LOG_INFO, (STR), (A1), (A2), (A3));\
136 	if (_hbaapi_debug_fd == NULL) {\
137 	    _hbaapi_debug_fd = fopen("/tmp/HBAAPI.log", "a");\
138 	}\
139 	if (_hbaapi_debug_fd != NULL) {\
140 	    fprintf(_hbaapi_debug_fd, #STR  "\n", (A1), (A2), (A3));\
141 	}\
142 	}
143 #endif /* WIN32 */
144 
145 #else /* Not both USESYSLOG and USELOGFILE */
146 #if defined(USESYSLOG)
147 int _hbaapi_sysloginit = 0;
148 #undef DEBUG
149 #define	DEBUG(L, STR, A1, A2, A3) \
150     if ((L) <= _hbaapi_debuglevel) {\
151 	if (_hbaapi_sysloginit == 0) {\
152 	    openlog("HBAAPI", LOG_PID|LOG_ODELAY, LOG_USER);\
153 	    _hbaapi_sysloginit = 1;\
154 	}\
155 	syslog(LOG_DEBUG, (STR), (A1), (A2), (A3));\
156 	}
157 #endif /* USESYSLOG */
158 #if defined(USELOGFILE)
159 FILE *_hbaapi_debug_fd = NULL;
160 #undef DEBUG
161 #ifdef WIN32
162 #define	DEBUG(L, STR, A1, A2, A3) \
163     if ((L) <= _hbaapi_debuglevel) {\
164 	if (_hbaapi_debug_fd == NULL) {\
165 	    char _logFile[MAX_PATH]; \
166 	    GetTempPath(MAX_PATH, _logFile); \
167 	    strcat(_logFile, "HBAAPI.log"); \
168 	    _hbaapi_debug_fd = fopen(_logFile, "a");\
169 	}\
170 	}
171 #else /* WIN32 */
172 #define	DEBUG(L, STR, A1, A2, A3) \
173     if ((L) <= _hbaapi_debuglevel) {\
174 	if (_hbaapi_debug_fd == NULL) {\
175 	    _hbaapi_debug_fd = fopen("/tmp/HBAAPI.log", "a");\
176 	}\
177 	if (_hbaapi_debug_fd != NULL) { \
178 	    fprintf(_hbaapi_debug_fd, #STR "\n", (A1), (A2), (A3));\
179 	}\
180 	}
181 #endif /* WIN32 */
182 #endif /* USELOGFILE */
183 #endif /* Not both USELOGFILE and USESYSLOG */
184 
185 #ifdef POSIX_THREADS
186 #include <pthread.h>
187 /*
188  * When multiple mutex's are grabed, they must be always be grabbed in
189  * the same order, or deadlock can result.  There are three levels
190  * of mutex's involved in this API.  If LL_mutex is grabbed, always grap
191  * it first.  If AL_mutex is grabbed, it may not be grabbed before
192  * LL_mutex.  If grabbed in a multi grab sequence, the mutex's protecting
193  * the callback lists must always be grabbed last and release before calling
194  * a vendor specific library function that might invoke a callback function
195  * on the same thread.
196  */
197 #define	GRAB_MUTEX(M)			grab_mutex(M)
198 #define	RELEASE_MUTEX(M)		release_mutex(M)
199 #define	RELEASE_MUTEX_RETURN(M, RET)	release_mutex(M); return (RET)
200 #elif defined(WIN32)
201 #define	GRAB_MUTEX(m)			EnterCriticalSection(m)
202 #define	RELEASE_MUTEX(m)		LeaveCriticalSection(m)
203 #define	RELEASE_MUTEX_RETURN(m, RET)	LeaveCriticalSection(m); return (RET)
204 #else
205 #define	GRAB_MUTEX(M)
206 #define	RELEASE_MUTEX(M)
207 #define	RELEASE_MUTEX_RETURN(M, RET)	return (RET)
208 #endif
209 
210 /*
211  * Vendor library information
212  */
213 typedef enum {
214     HBA_LIBRARY_UNKNOWN,
215     HBA_LIBRARY_LOADED,
216     HBA_LIBRARY_NOT_LOADED
217 } HBA_LIBRARY_STATUS;
218 
219 typedef enum {
220     UNKNOWN = 1,
221     SMHBA,
222     HBAAPIV2,
223     HBAAPI
224 } LIBRARY_VERSION;
225 
226 typedef struct hba_library_info {
227     struct hba_library_info
228 			*next;
229 #ifdef WIN32
230     HINSTANCE		hLibrary;		/* Handle to a loaded DLL */
231 #else
232     char		*LibraryName;
233     void*		hLibrary;		/* Handle to a loaded DLL */
234 #endif
235     char		*LibraryPath;
236     LIBRARY_VERSION	version;		/* resolve union */
237     HBA_UINT32		numOfAdapters;
238     union {
239 	SMHBA_ENTRYPOINTS   smhbafunctionTable;	/* smhba function pointers */
240 	HBA_ENTRYPOINTSV2   functionTable;	/* hba api function pointers */
241 	} ftable;
242     HBA_LIBRARY_STATUS	status;			/* info on this library */
243     HBA_UINT32		index;
244 } HBA_LIBRARY_INFO, *PHBA_LIBRARY_INFO;
245 
246 #define	ARE_WE_INITED() \
247 	if (_hbaapi_librarylist == NULL) { \
248 		return (HBA_STATUS_ERROR_NOT_LOADED); \
249 	}
250 HBA_LIBRARY_INFO *_hbaapi_librarylist = NULL;
251 HBA_UINT32 _hbaapi_total_library_count = 0;
252 #ifdef POSIX_THREADS
253 pthread_mutex_t _hbaapi_LL_mutex = PTHREAD_MUTEX_INITIALIZER;
254 #elif defined(WIN32)
255 CRITICAL_SECTION _hbaapi_LL_mutex;
256 #endif
257 
258 /*
259  * Macro to use the right function table between smhba and hbaapi.
260  */
261 #define	FUNCTABLE(lib_infop) \
262 	((lib_infop->version == SMHBA) ? \
263 	lib_infop->ftable.smhbafunctionTable : \
264 	lib_infop->ftable.functionTable);
265 
266 /*
267  * Macro to use the right function ptr between smhba and hbaapi function table.
268  * Should be used for an interface common to SM-HBA and HBAAPIV2.
269  */
270 #define	FUNCCOMMON(lib_infop, func) \
271 	((lib_infop->version == SMHBA) ? \
272 	lib_infop->ftable.smhbafunctionTable.func : \
273 	lib_infop->ftable.functionTable.func)
274 
275 /*
276  * Macro to use the hbaapi function ptr.
277  * Should be used for an interface applicable only HBAAPIV2.
278  */
279 #define	FUNCHBAAPIV2(lib_infop, func) \
280 	lib_infop->ftable.functionTable.func
281 
282 /*
283  * Macro to use the hbaapi function ptr.
284  * Should be used for an interface applicable only HBAAPIV2.
285  */
286 #define	FUNCSMHBA(lib_infop, func) \
287 	lib_infop->ftable.smhbafunctionTable.func
288 
289 /*
290  * Individual adapter (hba) information
291  */
292 typedef struct hba_adapter_info {
293     struct hba_adapter_info
294 			*next;
295     HBA_STATUS		GNstatus;	/* status from GetAdapterNameFunc */
296     char		*name;
297     HBA_WWN		nodeWWN;
298     HBA_LIBRARY_INFO	*library;
299     HBA_UINT32		index;
300 } HBA_ADAPTER_INFO;
301 
302 HBA_ADAPTER_INFO *_hbaapi_adapterlist = NULL;
303 HBA_UINT32 _hbaapi_total_adapter_count = 0;
304 #ifdef POSIX_THREADS
305 pthread_mutex_t _hbaapi_AL_mutex = PTHREAD_MUTEX_INITIALIZER;
306 #elif defined(WIN32)
307 CRITICAL_SECTION _hbaapi_AL_mutex;
308 #endif
309 
310 /*
311  * Call back registration
312  */
313 typedef struct hba_vendorcallback_elem {
314     struct hba_vendorcallback_elem
315 				*next;
316     HBA_CALLBACKHANDLE		vendorcbhandle;
317     HBA_LIBRARY_INFO		*lib_info;
318 } HBA_VENDORCALLBACK_ELEM;
319 
320 /*
321  * Each instance of HBA_ADAPTERCALLBACK_ELEM represents a call to one of
322  * "register" functions that apply to a particular adapter.
323  * HBA_ALLADAPTERSCALLBACK_ELEM is used just for HBA_RegisterForAdapterAddEvents
324  */
325 typedef struct hba_adaptercallback_elem {
326     struct hba_adaptercallback_elem
327 			*next;
328     HBA_LIBRARY_INFO	*lib_info;
329     void		*userdata;
330     HBA_CALLBACKHANDLE	vendorcbhandle;
331     void		(*callback)();
332 } HBA_ADAPTERCALLBACK_ELEM;
333 
334 typedef struct hba_alladapterscallback_elem {
335     struct hba_alladapterscallback_elem
336 				*next;
337     void			*userdata;
338     HBA_VENDORCALLBACK_ELEM	*vendorhandlelist;
339     void			(*callback)();
340 } HBA_ALLADAPTERSCALLBACK_ELEM;
341 
342 HBA_ALLADAPTERSCALLBACK_ELEM *_hbaapi_adapteraddevents_callback_list = NULL;
343 HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterevents_callback_list = NULL;
344 HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterportevents_callback_list = NULL;
345 HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterportstatevents_callback_list = NULL;
346 HBA_ADAPTERCALLBACK_ELEM *_hbaapi_targetevents_callback_list = NULL;
347 HBA_ADAPTERCALLBACK_ELEM *_hbaapi_linkevents_callback_list = NULL;
348 
349 HBA_ALLADAPTERSCALLBACK_ELEM *_smhba_adapteraddevents_callback_list = NULL;
350 HBA_ADAPTERCALLBACK_ELEM *_smhba_adapterevents_callback_list = NULL;
351 HBA_ADAPTERCALLBACK_ELEM *_smhba_adapterportevents_callback_list = NULL;
352 HBA_ADAPTERCALLBACK_ELEM *_smhba_adapterportstatevents_callback_list = NULL;
353 HBA_ADAPTERCALLBACK_ELEM *_smhba_adapterphystatevents_callback_list = NULL;
354 HBA_ADAPTERCALLBACK_ELEM *_smhba_targetevents_callback_list = NULL;
355 
356 #ifdef POSIX_THREADS
357 /* mutex's to protect each list */
358 pthread_mutex_t _hbaapi_AAE_mutex = PTHREAD_MUTEX_INITIALIZER;
359 pthread_mutex_t _hbaapi_AE_mutex = PTHREAD_MUTEX_INITIALIZER;
360 pthread_mutex_t _hbaapi_APE_mutex = PTHREAD_MUTEX_INITIALIZER;
361 pthread_mutex_t _hbaapi_APSE_mutex = PTHREAD_MUTEX_INITIALIZER;
362 pthread_mutex_t _hbaapi_TE_mutex = PTHREAD_MUTEX_INITIALIZER;
363 pthread_mutex_t _hbaapi_LE_mutex = PTHREAD_MUTEX_INITIALIZER;
364 pthread_mutex_t _smhba_AAE_mutex = PTHREAD_MUTEX_INITIALIZER;
365 pthread_mutex_t _smhba_AE_mutex = PTHREAD_MUTEX_INITIALIZER;
366 pthread_mutex_t _smhba_APE_mutex = PTHREAD_MUTEX_INITIALIZER;
367 pthread_mutex_t _smhba_APSE_mutex = PTHREAD_MUTEX_INITIALIZER;
368 pthread_mutex_t _smhba_APHYSE_mutex = PTHREAD_MUTEX_INITIALIZER;
369 pthread_mutex_t _smhba_TE_mutex = PTHREAD_MUTEX_INITIALIZER;
370 pthread_mutex_t _smhba_LE_mutex = PTHREAD_MUTEX_INITIALIZER;
371 #elif defined(WIN32)
372 CRITICAL_SECTION _hbaapi_AAE_mutex;
373 CRITICAL_SECTION _hbaapi_AE_mutex;
374 CRITICAL_SECTION _hbaapi_APE_mutex;
375 CRITICAL_SECTION _hbaapi_APSE_mutex;
376 CRITICAL_SECTION _hbaapi_TE_mutex;
377 CRITICAL_SECTION _smhba_AAE_mutex;
378 CRITICAL_SECTION _smhba_AE_mutex;
379 CRITICAL_SECTION _smhba_APE_mutex;
380 CRITICAL_SECTION _smhba_APSE_mutex;
381 CRITICAL_SECTION _smhba_APHYSE_mutex;
382 CRITICAL_SECTION _smhba_TE_mutex;
383 CRITICAL_SECTION _hbaapi_LE_mutex;
384 #endif
385 
386 HBA_ADAPTERCALLBACK_ELEM **cb_lists_array[] = {
387 	&_hbaapi_adapterevents_callback_list,
388 	&_hbaapi_adapterportevents_callback_list,
389 	&_hbaapi_adapterportstatevents_callback_list,
390 	&_hbaapi_targetevents_callback_list,
391 	&_hbaapi_linkevents_callback_list,
392 	&_smhba_adapterevents_callback_list,
393 	&_smhba_adapterportevents_callback_list,
394 	&_smhba_adapterportstatevents_callback_list,
395 	&_smhba_adapterphystatevents_callback_list,
396 	&_smhba_targetevents_callback_list,
397 	NULL};
398 
399 /*
400  * Common library internal. Mutex handling
401  */
402 #ifdef POSIX_THREADS
403 static void
404 grab_mutex(pthread_mutex_t *mp) {
405 /* LINTED E_FUNC_SET_NOT_USED */
406     int ret;
407     if ((ret = pthread_mutex_lock(mp)) != 0) {
408 	perror("pthread_mutex_lock - HBAAPI:");
409 	DEBUG(1, "pthread_mutex_lock returned %d", ret, 0, 0);
410 	}
411 }
412 
413 static void
414 release_mutex(pthread_mutex_t *mp) {
415 /* LINTED E_FUNC_SET_NOT_USED */
416     int ret;
417     if ((ret = pthread_mutex_unlock(mp)) != 0) {
418 	perror("pthread_mutex_unlock - HBAAPI:");
419 	DEBUG(1, "pthread_mutex_unlock returned %d", ret, 0, 0);
420 	}
421 }
422 #endif
423 
424 /*
425  * Common library internal. Check library and return vendorhandle
426  */
427 static HBA_STATUS
428 HBA_CheckLibrary(HBA_HANDLE handle,
429     HBA_LIBRARY_INFO **lib_infopp,
430     HBA_HANDLE *vendorhandle) {
431 
432     HBA_UINT32		libraryIndex;
433     HBA_LIBRARY_INFO	*lib_infop;
434 
435     if (_hbaapi_librarylist == NULL) {
436 	return (HBA_STATUS_ERROR);
437 	}
438     libraryIndex = LIBRARY_NUM(handle);
439 
440     GRAB_MUTEX(&_hbaapi_LL_mutex);
441     for (lib_infop = _hbaapi_librarylist;
442 	lib_infop != NULL;
443 	lib_infop = lib_infop->next) {
444 	if (lib_infop->index == libraryIndex) {
445 	    if (lib_infop->status != HBA_LIBRARY_LOADED) {
446 		return (HBA_STATUS_ERROR);
447 	    }
448 	    *lib_infopp = lib_infop;
449 	    *vendorhandle = VENDOR_HANDLE(handle);
450 	    /* caller will release the mutex */
451 	    return (HBA_STATUS_OK);
452 	}
453 	}
454     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INVALID_HANDLE);
455 }
456 #define	CHECKLIBRARY() \
457 	status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);\
458 	if (status != HBA_STATUS_OK) { \
459 	    return (status); \
460 	}
461 
462 #define	CHECKLIBRARYANDVERSION(ver) \
463 	status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle); \
464 	if (status != HBA_STATUS_OK) { \
465 	    return (status); \
466 	} else { \
467 	    if (ver != lib_infop->version) { \
468 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, \
469 		    HBA_STATUS_ERROR_INCOMPATIBLE); \
470 	    } \
471 	}
472 
473 /*
474  * freevendorhandlelist is called with _hbaapi_LL_mutex already held
475  */
476 static void
477 freevendorhandlelist(HBA_VENDORCALLBACK_ELEM *vhlist) {
478     HBA_VENDORCALLBACK_ELEM	*vhlp;
479     HBA_VENDORCALLBACK_ELEM	*vnext;
480     HBARemoveCallbackFunc	registeredfunc;
481 
482     for (vhlp = vhlist; vhlp != NULL; vhlp = vnext) {
483 	vnext = vhlp->next;
484 	registeredfunc =
485 	    FUNCCOMMON(vhlp->lib_info, RemoveCallbackHandler);
486 	if (registeredfunc == NULL) {
487 	    continue;
488 	}
489 	(registeredfunc)(vhlp->vendorcbhandle);
490 	free(vhlp);
491 	}
492 }
493 
494 static
495 HBA_STATUS
496 local_remove_callback(HBA_CALLBACKHANDLE cbhandle) {
497     HBA_ADAPTERCALLBACK_ELEM		***listp;
498     HBA_ADAPTERCALLBACK_ELEM		**lastp;
499     HBA_ALLADAPTERSCALLBACK_ELEM	**lap;
500     HBA_ALLADAPTERSCALLBACK_ELEM	*allcbp;
501     HBA_ADAPTERCALLBACK_ELEM		*cbp;
502     HBARemoveCallbackFunc		registeredfunc;
503     HBA_VENDORCALLBACK_ELEM		*vhlp;
504     HBA_VENDORCALLBACK_ELEM		*vnext;
505     int					found;
506     HBA_STATUS			status = HBA_STATUS_ERROR_INVALID_HANDLE;
507 
508 
509 	/* search through the simple lists first */
510     GRAB_MUTEX(&_hbaapi_AAE_mutex);
511     GRAB_MUTEX(&_hbaapi_AE_mutex);
512     GRAB_MUTEX(&_hbaapi_APE_mutex);
513     GRAB_MUTEX(&_hbaapi_APSE_mutex);
514     GRAB_MUTEX(&_hbaapi_TE_mutex);
515     GRAB_MUTEX(&_hbaapi_LE_mutex);
516     GRAB_MUTEX(&_smhba_AAE_mutex);
517     GRAB_MUTEX(&_smhba_AE_mutex);
518     GRAB_MUTEX(&_smhba_APE_mutex);
519     GRAB_MUTEX(&_smhba_APSE_mutex);
520     GRAB_MUTEX(&_smhba_TE_mutex);
521     for (listp = cb_lists_array, found = 0;
522 	    (found == 0 && *listp != NULL); listp++) {
523 	lastp = *listp;
524 	for (cbp = **listp; cbp != NULL; cbp = cbp->next) {
525 	    if (cbhandle != (HBA_CALLBACKHANDLE)cbp) {
526 		lastp = &(cbp->next);
527 		continue;
528 	    }
529 	    found = 1;
530 	    registeredfunc =
531 		FUNCCOMMON(cbp->lib_info, RemoveCallbackHandler);
532 	    if (registeredfunc == NULL) {
533 		break;
534 	    }
535 	    (registeredfunc)(cbp->vendorcbhandle);
536 	    *lastp = cbp->next;
537 	    free(cbp);
538 	    break;
539 	}
540 	}
541     RELEASE_MUTEX(&_hbaapi_LE_mutex);
542     RELEASE_MUTEX(&_hbaapi_TE_mutex);
543     RELEASE_MUTEX(&_hbaapi_APSE_mutex);
544     RELEASE_MUTEX(&_hbaapi_APE_mutex);
545     RELEASE_MUTEX(&_hbaapi_AE_mutex);
546     RELEASE_MUTEX(&_hbaapi_AAE_mutex);
547     RELEASE_MUTEX(&_smhba_AAE_mutex);
548     RELEASE_MUTEX(&_smhba_AE_mutex);
549     RELEASE_MUTEX(&_smhba_APE_mutex);
550     RELEASE_MUTEX(&_smhba_APSE_mutex);
551     RELEASE_MUTEX(&_smhba_TE_mutex);
552 
553     if (found != 0) {
554 	if (registeredfunc == NULL) {
555 	    return (HBA_STATUS_ERROR_NOT_SUPPORTED);
556 	}
557 	return (HBA_STATUS_OK);
558 	}
559 
560     GRAB_MUTEX(&_hbaapi_AAE_mutex);
561 	/*
562 	 * if it wasnt in the simple lists,
563 	 * look in the list for adapteraddevents
564 	 */
565     lap = &_hbaapi_adapteraddevents_callback_list;
566     for (allcbp = _hbaapi_adapteraddevents_callback_list;
567 	    allcbp != NULL;
568 	    allcbp = allcbp->next) {
569 	if (cbhandle != (HBA_CALLBACKHANDLE)allcbp) {
570 	    lap = &allcbp->next;
571 	    continue;
572 	}
573 	for (vhlp = allcbp->vendorhandlelist; vhlp != NULL; vhlp = vnext) {
574 	    vnext = vhlp->next;
575 	    /* should be HBAAPIV2 VSL to get to here */
576 	    registeredfunc =
577 		    vhlp->lib_info->ftable.functionTable.RemoveCallbackHandler;
578 	    if (registeredfunc == NULL) {
579 		continue;
580 	    }
581 	    (registeredfunc)(vhlp->vendorcbhandle);
582 	    free(vhlp);
583 	}
584 	*lap = allcbp->next;
585 	free(allcbp);
586 	status = HBA_STATUS_OK;
587 	break;
588 	}
589     RELEASE_MUTEX(&_hbaapi_AAE_mutex);
590 
591 	/* now search smhba adapteradd events. */
592     GRAB_MUTEX(&_smhba_AAE_mutex);
593     lap = &_smhba_adapteraddevents_callback_list;
594     for (allcbp = _smhba_adapteraddevents_callback_list;
595 	allcbp != NULL;
596 	allcbp = allcbp->next) {
597 	if (cbhandle != (HBA_CALLBACKHANDLE)allcbp) {
598 	    lap = &allcbp->next;
599 	    continue;
600 	}
601 	for (vhlp = allcbp->vendorhandlelist; vhlp != NULL; vhlp = vnext) {
602 	    vnext = vhlp->next;
603 	    /* should be SMHBA VSL to get to here */
604 	    registeredfunc =
605 		    vhlp->lib_info->
606 			ftable.smhbafunctionTable.RemoveCallbackHandler;
607 	    if (registeredfunc == NULL) {
608 		continue;
609 	    }
610 	    (registeredfunc)(vhlp->vendorcbhandle);
611 	    free(vhlp);
612 	}
613 	*lap = allcbp->next;
614 	free(allcbp);
615 	status = HBA_STATUS_OK;
616 	break;
617 	}
618     RELEASE_MUTEX(&_smhba_AAE_mutex);
619 
620     return (status);
621 }
622 
623 /* LINTED E_STATIC_UE_STATIC_UNUSED */
624 static char wwn_str1[17];
625 /* LINTED E_STATIC_UE_STATIC_UNUSED */
626 static char wwn_str2[17];
627 /* LINTED E_STATIC_UE_STATIC_UNUSED */
628 static char wwn_str3[17];
629 #define	WWN2STR1(wwn) WWN2str(wwn_str1, (wwn))
630 #define	WWN2STR2(wwn) WWN2str(wwn_str2, (wwn))
631 #define	WWN2STR3(wwn) WWN2str(wwn_str3, (wwn))
632 static char *
633 /* LINTED E_STATIC_UE_STATIC_UNUSED */
634 WWN2str(char *buf, HBA_WWN *wwn) {
635     int j;
636     unsigned char *pc = (unsigned char *)&(wwn->wwn[0]);
637     buf[0] = '\0';
638     for (j = 0; j < 16; j += 2) {
639 		(void) sprintf(&buf[j], "%02X", (int)*pc++);
640 	}
641     return (buf);
642 }
643 
644 #ifdef WIN32
645 BOOL APIENTRY
646 DllMain(HANDLE hModule,
647     DWORD  ul_reason_for_call,
648     LPVOID lpReserved)
649 {
650 	switch (ul_reason_for_call) {
651 	case DLL_PROCESS_ATTACH:
652 		break;
653 	case DLL_PROCESS_DETACH:
654 		break;
655 	case DLL_THREAD_ATTACH:
656 	case DLL_THREAD_DETACH:
657 		break;
658 	}
659 	return (TRUE);
660 }
661 #endif
662 
663 /*
664  * Read in the config file and load all the specified vendor specific
665  * libraries and perform the function registration exercise
666  */
667 HBA_STATUS
668 HBA_LoadLibrary()
669 {
670 	HBARegisterLibraryFunc RegisterFunc;
671 	HBARegisterLibraryV2Func RegisterV2Func;
672 	SMHBARegisterLibraryFunc RegisterSMHBAFunc;
673 	HBALoadLibraryFunc	LoadLibraryFunc;
674 	HBAGetVersionFunc	GetVersionFunc;
675 #ifdef	POSIX_THREADS
676 	int			ret;
677 #endif
678 	HBA_STATUS		status;
679 	HBA_UINT32		libversion;
680 
681 	/* Open configuration file from known location */
682 #ifdef WIN32
683 	LONG		lStatus;
684 	HKEY		hkSniaHba, hkVendorLib;
685 	FILETIME		ftLastWriteTime;
686 	TCHAR		cSubKeyName[256];
687 	DWORD		i, dwSize, dwType;
688 	BYTE		byFileName[MAX_PATH];
689 	HBA_LIBRARY_INFO	*lib_infop;
690 
691 	if (_hbaapi_librarylist != NULL) {
692 		/* this is an app programming error */
693 		return (HBA_STATUS_ERROR);
694 	}
695 
696 	lStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\SNIA\\HBA",
697 	    0, KEY_READ, &hkSniaHba);
698 	if (lStatus != ERROR_SUCCESS) {
699 		/* ???Opportunity to send error msg, configuration error */
700 		return (HBA_STATUS_ERROR);
701 	}
702 	/*
703 	 * Enumerate all the subkeys. These have the form:
704 	 * HKLM\Software\SNIA\HBA\<Vendor id> - note that we don't care
705 	 * what the vendor id is
706 	 */
707 	for (i = 0; ; i++) {
708 		dwSize = 255;	/* how big the buffer is */
709 		lStatus = RegEnumKeyEx(hkSniaHba, i,
710 		    (char *)&cSubKeyName, &dwSize, NULL,
711 		    NULL, NULL, &ftLastWriteTime);
712 	if (lStatus == ERROR_NO_MORE_ITEMS) {
713 		break;	/* we're done */
714 	} else if (lStatus == ERROR_MORE_DATA) { /* buffer not big enough */
715 		/* do whatever */
716 		;
717 	}
718 	/* Now open the subkey that pertains to this vendor's library */
719 	lStatus = RegOpenKeyEx(hkSniaHba, cSubKeyName, 0, KEY_READ,
720 	    &hkVendorLib);
721 	if (lStatus != ERROR_SUCCESS) {
722 		RegCloseKey(hkSniaHba);
723 	    /* ???Opportunity to send error msg, installation error */
724 		return (HBA_STATUS_ERROR);
725 		/*
726 		 * you may want to return something
727 		 * else or keep trying
728 		 */
729 	}
730 	/*
731 	 * The name of the library is contained in a REG_SZ Value
732 	 * keyed to "LibraryFile"
733 	 */
734 	dwSize = MAX_PATH;
735 	lStatus = RegQueryValueEx(hkVendorLib, "LibraryFile", NULL, &dwType,
736 	    byFileName, &dwSize);
737 	if (lStatus != ERROR_SUCCESS) {
738 		RegCloseKey(hkVendorLib);
739 	    /* ???Opportunity to send error msg, installation error */
740 		continue;
741 	}
742 	lib_infop = (HBA_LIBRARY_INFO *)calloc(1, sizeof (HBA_LIBRARY_INFO));
743 	if (lib_infop == NULL) {
744 	    /* what is the right thing to do in MS land??? */
745 		RegCloseKey(hkVendorLib);
746 		/* ???Opportunity to send error msg, installation error */
747 		return (HBA_STATUS_ERROR);
748 	}
749 	lib_infop->status = HBA_LIBRARY_NOT_LOADED;
750 	lib_infop->next = _hbaapi_librarylist;
751 	lib_infop->index = _hbaapi_total_library_count;
752 	_hbaapi_total_library_count++;
753 	_hbaapi_librarylist = lib_infop;
754 
755 	/* Now I can try to load the library */
756 	lib_infop->hLibrary = LoadLibrary(byFileName);
757 	if (lib_infop->hLibrary == NULL) {
758 	    /* printf("unable to load library %s\n", librarypath); */
759 	    /* ???Opportunity to send error msg, installation error */
760 		goto dud_library;
761 	}
762 	lib_infop->LibraryPath = strdup(byFileName);
763 	DEBUG(1, "HBAAPI loading: %s\n", byFileName, 0, 0);
764 
765 	RegisterSMHBAFunc = (SMHBARegisterLibraryFunc)
766 	    GetProcAddress(lib_infop->hLibrary, "SMHBA_RegisterLibrary");
767 	if (RegisterSMHBAFunc != NULL) {
768 		status = ((RegisterSMHBAFunc)(SMHBA_ENTRYPOINTS *)
769 		    (&lib_infop->ftable.smhbafunctionTable));
770 		if (status != HBA_STATUS_OK) {
771 			/* library not loaded */
772 			/* ???Opportunity to send error msg, library error? */
773 			goto dud_library;
774 		} else {
775 			lib_infop->version = SMHBA;
776 		}
777 	} else {
778 	    /* Call the registration function to get the list of pointers */
779 		RegisterV2Func = (HBARegisterLibraryV2Func)GetProcAddress(
780 		    lib_infop->hLibrary, "HBA_RegisterLibraryV2");
781 		if (RegisterV2Func != NULL) {
782 		/*
783 		 * Load the function pointers directly into
784 		 * the table of functions
785 		 */
786 		status = ((RegisterV2Func)
787 		    (HBA_ENTRYPOINTSV2 *)(&lib_infop->ftable.functionTable));
788 		if (status != HBA_STATUS_OK) {
789 		    /* library not loaded */
790 		    /* ???Opportunity to send error msg, library error? */
791 			goto dud_library;
792 		} else {
793 			lib_infop->version = HBAAPIV2;
794 		}
795 		} else {
796 		/* Maybe the vendor library is only Rev1 */
797 		RegisterFunc = (HBARegisterLibraryFunc)
798 		    GetProcAddress(lib_infop->hLibrary, "HBA_RegisterLibrary");
799 		if (RegisterFunc == NULL) {
800 		    /* ???Opportunity to send error msg, library error? */
801 			goto dud_library;
802 		}
803 		/*
804 		 * Load the function points directly into
805 		 * the Rev 2 table of functions
806 		 */
807 		status = ((RegisterFunc)(
808 		    (HBA_ENTRYPOINTS *)(&lib_infop->ftable.functionTable)));
809 		if (status != HBA_STATUS_OK) {
810 		    /* library not loaded */
811 		    /* ???Opportunity to send error msg, library error? */
812 			goto dud_library;
813 		} else {
814 			lib_infop->version = HBAAPI;
815 		}
816 		}
817 	}
818 
819 	/* successfully loaded library */
820 	/*
821 	 * SM-HBA and HBAAPI has a seperate handler for GetVersion but
822 	 * they have the same function signature so use the same variable here.
823 	 */
824 	GetVersionFunc = FUNCCOMMON(lib_infop, GetVersionHandler);
825 	if (GetVersionFunc != NULL) {
826 		if (lib_infop->version == SMHBA) {
827 		/* Check the version of this library before loading */
828 		libversion = ((GetVersionFunc)());
829 #ifdef NOTDEF /* save for a later time... when it matters */
830 		if (libversion < SMHBA_LIBVERSION) {
831 			goto dud_library;
832 		}
833 #endif
834 		} else {
835 		/* Check the version of this library before loading */
836 	    /* Actually... This wrapper is compatible with version 1 */
837 		libversion = ((GetVersionFunc)());
838 #ifdef NOTDEF /* save for a later time... when it matters */
839 		if (libversion < HBA_LIBVERSION) {
840 			goto dud_library;
841 		}
842 #endif
843 		}
844 	} else {
845 	    /* ???Opportunity to send error msg, library error? */
846 		goto dud_library;
847 	}
848 
849 	LoadLibraryFunc = FUNCCOMMON(lib_infop, LoadLibraryHandler);
850 	if (LoadLibraryFunc == NULL) {
851 	    /* Hmmm, dont we need to flag this in a realy big way??? */
852 	    /* How about messages to the system event logger ??? */
853 	    /* ???Opportunity to send error msg, library error? */
854 		goto dud_library;
855 	}
856 	/* Initialize this library */
857 	status = ((LoadLibraryFunc)());
858 	if (status != HBA_STATUS_OK) {
859 	    /* ???Opportunity to send error msg, library error? */
860 		continue;
861 	}
862 	/* successfully loaded library */
863 	lib_infop->status = HBA_LIBRARY_LOADED;
864 
865 	dud_library: /* its also just the end of the loop */
866 	RegCloseKey(hkVendorLib);
867 	}
868 	RegCloseKey(hkSniaHba);
869 
870 #else /* Unix as opposed to Win32 */
871 	FILE		*hbaconf;
872 	char		fullline[512];		/* line read from HBA.conf */
873 	char		*libraryname;		/* Read in from file HBA.conf */
874 	char		*librarypath;		/* Read in from file HBA.conf */
875 	char		hbaConfFilePath[256];
876 	char		*charPtr;
877 	HBA_LIBRARY_INFO	*lib_infop;
878 
879 	GRAB_MUTEX(&_hbaapi_LL_mutex);
880 	if (_hbaapi_librarylist != NULL) {
881 		(void) fprintf(stderr,
882 		    "HBA_LoadLibrary: previously unfreed "
883 		    "libraries exist, call HBA_FreeLibrary().\n");
884 		RELEASE_MUTEX(&_hbaapi_LL_mutex);
885 		return (HBA_STATUS_ERROR);
886 	}
887 
888 	(void) strcpy(hbaConfFilePath, "/etc/smhba.conf");
889 
890 	if ((hbaconf = fopen(hbaConfFilePath, "r")) == NULL) {
891 		(void) printf("Cannot open %s\n", hbaConfFilePath);
892 		RELEASE_MUTEX(&_hbaapi_LL_mutex);
893 		return (HBA_STATUS_ERROR);
894 	}
895 
896 	/* Read in each line and load library */
897 	while ((hbaconf != NULL) &&
898 	    (fgets(fullline, sizeof (fullline), hbaconf))) {
899 		/* Skip the comments... */
900 		if ((fullline[0] == '#') || (fullline[0] == '\n')) {
901 			continue;
902 		}
903 
904 	/* grab first 'thing' in line (if its there) */
905 	if ((libraryname = strtok(fullline, " \t\n")) != NULL) {
906 		if (strlen(libraryname) >= 64) {
907 			(void) fprintf(stderr,
908 			    "Library name(%s) in %s is > 64 characters\n",
909 			    libraryname, hbaConfFilePath);
910 		}
911 	}
912 	/* grab second 'thing' in line (if its there) */
913 	if ((librarypath = strtok(NULL, " \t\n")) != NULL) {
914 		if (strlen(librarypath) >= 256) {
915 		(void) fprintf(stderr,
916 		    "Library path(%s) in %s is > 256 characters\n",
917 		    librarypath, hbaConfFilePath);
918 		}
919 	}
920 
921 	/* there should be no more 'things' in the line */
922 	if ((charPtr = strtok(NULL, " \n\t")) != NULL) {
923 		(void) fprintf(stderr, "Extraneous characters (\"%s\") in %s\n",
924 		    charPtr, hbaConfFilePath);
925 	}
926 
927 	/* Continue to the next line if library name or path is invalid */
928 	if (libraryname == NULL ||
929 	    strlen(libraryname) == 0 ||
930 	    librarypath == NULL ||
931 	    (strlen(librarypath) == 0)) {
932 		continue;
933 	}
934 
935 	/*
936 	 * Special case....
937 	 * Look for loglevel
938 	 */
939 	if (strcmp(libraryname, "debuglevel") == 0) {
940 		_hbaapi_debuglevel = strtol(librarypath, NULL, 10);
941 	    /* error handling does the right thing automagically */
942 		continue;
943 	}
944 
945 	lib_infop = (HBA_LIBRARY_INFO *)calloc(1, sizeof (HBA_LIBRARY_INFO));
946 	if (lib_infop == NULL) {
947 		(void) fprintf(stderr, "HBA_LoadLibrary: out of memeory\n");
948 		RELEASE_MUTEX(&_hbaapi_LL_mutex);
949 		fclose(hbaconf);
950 		return (HBA_STATUS_ERROR);
951 	}
952 	lib_infop->status = HBA_LIBRARY_NOT_LOADED;
953 	lib_infop->LibraryName = strdup(libraryname);
954 	lib_infop->LibraryPath = strdup(librarypath);
955 	lib_infop->numOfAdapters = 0;
956 	lib_infop->version = UNKNOWN;
957 	lib_infop->index = _hbaapi_total_library_count;
958 	_hbaapi_total_library_count++;
959 	lib_infop->next = _hbaapi_librarylist;
960 	_hbaapi_librarylist = lib_infop;
961 
962 	/* Load the DLL now */
963 	if ((lib_infop->hLibrary = dlopen(librarypath, RTLD_LAZY)) == NULL) {
964 	    /* printf("unable to load library %s\n", librarypath); */
965 		continue;
966 	}
967 	/* Call the registration function to get the list of pointers */
968 	RegisterSMHBAFunc = (SMHBARegisterLibraryFunc)
969 	    dlsym(lib_infop->hLibrary, "SMHBA_RegisterLibrary");
970 	if (RegisterSMHBAFunc != NULL) {
971 		/*
972 		 * Load the function points directly into
973 		 * the table of functions
974 		 */
975 		status = ((RegisterSMHBAFunc)
976 		    (&lib_infop->ftable.smhbafunctionTable));
977 		if (status != HBA_STATUS_OK) {
978 			/* library not loaded */
979 			continue;
980 		} else {
981 			lib_infop->version = SMHBA;
982 		}
983 	} else {
984 		RegisterV2Func = (HBARegisterLibraryV2Func)
985 		    dlsym(lib_infop->hLibrary, "HBA_RegisterLibraryV2");
986 		if (RegisterV2Func != NULL) {
987 		/*
988 		 * Load the function points directly into
989 		 * the table of functions
990 		 */
991 		status = ((RegisterV2Func)((HBA_ENTRYPOINTSV2 *)
992 		    (&lib_infop->ftable.functionTable)));
993 		if (status != HBA_STATUS_OK) {
994 		    /* library not loaded */
995 			continue;
996 		} else {
997 			lib_infop->version = HBAAPIV2;
998 		}
999 		} else {
1000 		/* Maybe the vendor library is only Rev1 */
1001 		RegisterFunc = (HBARegisterLibraryFunc)
1002 		    dlsym(lib_infop->hLibrary, "HBA_RegisterLibrary");
1003 		if (RegisterFunc == NULL) {
1004 		    /* This function is required */
1005 			(void) fprintf(stderr,
1006 			    "HBA_LoadLibrary: vendor specific RegisterLibrary "
1007 			    "function not found.  lib: %s\n", librarypath);
1008 			DEBUG(1, "HBA_LoadLibrary: vendor specific "
1009 			    "RegisterLibrary function not found.  lib: %s\n",
1010 			    librarypath, 0, 0);
1011 			continue;
1012 		}
1013 		/*
1014 		 * Load the function points directly into
1015 		 * the table of functions
1016 		 */
1017 		status = ((RegisterFunc)
1018 		    ((HBA_ENTRYPOINTS *)(&lib_infop->ftable.functionTable)));
1019 		if (status != HBA_STATUS_OK) {
1020 		    /* library not loaded */
1021 			(void) fprintf(stderr,
1022 			    "HBA_LoadLibrary: vendor specific RegisterLibrary "
1023 			    "function encountered an error.  lib: %s\n",
1024 			    librarypath);
1025 			DEBUG(1,
1026 			    "HBA_LoadLibrary: vendor specific RegisterLibrary "
1027 			    "function encountered an error. lib: %s\n",
1028 			    librarypath, 0, 0);
1029 			continue;
1030 		} else {
1031 			lib_infop->version = HBAAPI;
1032 		}
1033 		}
1034 	}
1035 
1036 	/* successfully loaded library */
1037 	/*
1038 	 * SM-HBA and HBAAPI has a seperate handler for GetVersion but
1039 	 * they have the same function signature so use the same variable here.
1040 	 */
1041 	if ((GetVersionFunc = FUNCCOMMON(lib_infop, GetVersionHandler))
1042 	    == NULL) {
1043 		continue;
1044 	}
1045 	if (lib_infop->version == SMHBA) {
1046 		libversion = ((GetVersionFunc)());
1047 		if (libversion < SMHBA_LIBVERSION) {
1048 			(void) printf("Library version mismatch."
1049 			    "Got %d expected %d.\n",
1050 			    libversion, SMHBA_LIBVERSION);
1051 			continue;
1052 		}
1053 	} else {
1054 		libversion = ((GetVersionFunc)());
1055 	    /* Check the version of this library before loading */
1056 	    /* Actually... This wrapper is compatible with version 1 */
1057 		if (libversion < HBA_LIBVERSION) {
1058 			(void) printf("Library version mismatch."
1059 			    "Got %d expected %d.\n",
1060 			    libversion, HBA_LIBVERSION);
1061 			continue;
1062 		}
1063 	}
1064 
1065 	DEBUG(1, "%s libversion = %d", librarypath, libversion, 0);
1066 	LoadLibraryFunc = FUNCCOMMON(lib_infop, LoadLibraryHandler);
1067 	if (LoadLibraryFunc == NULL) {
1068 	    /* this function is required */
1069 		(void) fprintf(stderr,
1070 		    "HBA_LoadLibrary: vendor specific LoadLibrary "
1071 		    "function not found.  lib: %s\n", librarypath);
1072 		DEBUG(1, "HBA_LoadLibrary: vendor specific LoadLibrary "
1073 		    "function not found.  lib: %s\n", librarypath, 0, 0);
1074 		continue;
1075 	}
1076 	/* Initialize this library */
1077 	if ((status = ((LoadLibraryFunc)())) != HBA_STATUS_OK) {
1078 	    /* maybe this should be a printf so that we CANNOT miss it */
1079 		(void) fprintf(stderr,
1080 		    "HBA_LoadLibrary: Encounterd and error loading: %s",
1081 		    librarypath);
1082 		DEBUG(1, "Encounterd and error loading: %s", librarypath, 0, 0);
1083 		DEBUG(1, "  HBA_STATUS: %d", status, 0, 0);
1084 		continue;
1085 	}
1086 	/* successfully loaded library */
1087 	lib_infop->status = HBA_LIBRARY_LOADED;
1088 	}
1089 	fclose(hbaconf);
1090 #endif /* WIN32 or UNIX */
1091 #ifdef POSIX_THREADS
1092 	/*
1093 	 * The _hbaapi_LL_mutex is already grabbed to proctect the caller of
1094 	 * HBA_FreeLibrary() during loading.
1095 	 * The mutexes are already initialized
1096 	 * with PTHREAD_MUTEX_INITIALIZER.  Do we need to init again?
1097 	 * Keeping the code from HBAAPI source...
1098 	 */
1099 	ret = pthread_mutex_init(&_hbaapi_AL_mutex, NULL);
1100 	if (ret == 0) {
1101 		ret = pthread_mutex_init(&_hbaapi_AAE_mutex, NULL);
1102 	}
1103 	if (ret == 0) {
1104 		ret = pthread_mutex_init(&_hbaapi_AE_mutex, NULL);
1105 	}
1106 	if (ret == 0) {
1107 		ret = pthread_mutex_init(&_hbaapi_APE_mutex, NULL);
1108 	}
1109 	if (ret == 0) {
1110 		ret = pthread_mutex_init(&_hbaapi_APSE_mutex, NULL);
1111 	}
1112 	if (ret == 0) {
1113 		ret = pthread_mutex_init(&_hbaapi_TE_mutex, NULL);
1114 	}
1115 	if (ret == 0) {
1116 		ret = pthread_mutex_init(&_smhba_AAE_mutex, NULL);
1117 	}
1118 	if (ret == 0) {
1119 		ret = pthread_mutex_init(&_smhba_AE_mutex, NULL);
1120 	}
1121 	if (ret == 0) {
1122 		ret = pthread_mutex_init(&_smhba_APE_mutex, NULL);
1123 	}
1124 	if (ret == 0) {
1125 		ret = pthread_mutex_init(&_smhba_APSE_mutex, NULL);
1126 	}
1127 	if (ret == 0) {
1128 		ret = pthread_mutex_init(&_smhba_TE_mutex, NULL);
1129 	}
1130 	if (ret == 0) {
1131 		ret = pthread_mutex_init(&_hbaapi_LE_mutex, NULL);
1132 	}
1133 	if (ret != 0) {
1134 		perror("pthread_mutex_init - HBA_LoadLibrary");
1135 		RELEASE_MUTEX(&_hbaapi_LL_mutex);
1136 		return (HBA_STATUS_ERROR);
1137 	}
1138 	RELEASE_MUTEX(&_hbaapi_LL_mutex);
1139 #elif defined(WIN32)
1140 	InitializeCriticalSection(&_hbaapi_LL_mutex);
1141 	InitializeCriticalSection(&_hbaapi_AL_mutex);
1142 	InitializeCriticalSection(&_hbaapi_AAE_mutex);
1143 	InitializeCriticalSection(&_hbaapi_AE_mutex);
1144 	InitializeCriticalSection(&_hbaapi_APE_mutex);
1145 	InitializeCriticalSection(&_hbaapi_APSE_mutex);
1146 	InitializeCriticalSection(&_hbaapi_TE_mutex);
1147 	InitializeCriticalSection(&_hbaapi_LE_mutex);
1148 	InitializeCriticalSection(&_smhba_AAE_mutex);
1149 	InitializeCriticalSection(&_smhba_AE_mutex);
1150 	InitializeCriticalSection(&_smhba_APE_mutex);
1151 	InitializeCriticalSection(&_smhba_APSE_mutex);
1152 	InitializeCriticalSection(&_smhba_TE_mutex);
1153 #endif
1154 
1155 	return (HBA_STATUS_OK);
1156 }
1157 
1158 HBA_STATUS
1159 HBA_FreeLibrary() {
1160     HBAFreeLibraryFunc	FreeLibraryFunc;
1161 /* LINTED E_FUNC_SET_NOT_USED */
1162     HBA_STATUS		status __unused;
1163     HBA_LIBRARY_INFO	*lib_infop;
1164     HBA_LIBRARY_INFO	*lib_next;
1165     HBA_ADAPTERCALLBACK_ELEM
1166 			***listp;
1167     HBA_ADAPTER_INFO	*adapt_infop;
1168     HBA_ADAPTER_INFO	*adapt_next;
1169 
1170     GRAB_MUTEX(&_hbaapi_LL_mutex);
1171     if (_hbaapi_librarylist == NULL) {
1172 	RELEASE_MUTEX(&_hbaapi_LL_mutex);
1173 	return (HBA_STATUS_ERROR_NOT_LOADED);
1174 	}
1175 
1176     GRAB_MUTEX(&_hbaapi_AL_mutex);
1177 
1178     DEBUG(1, "HBA_FreeLibrary()", 0, 0, 0);
1179     for (lib_infop = _hbaapi_librarylist; lib_infop != NULL;
1180 	    lib_infop = lib_next) {
1181 	lib_next = lib_infop->next;
1182 	if (lib_infop->status == HBA_LIBRARY_LOADED) {
1183 	    FreeLibraryFunc = FUNCCOMMON(lib_infop, FreeLibraryHandler);
1184 	    if (FreeLibraryFunc != NULL) {
1185 		/* Free this library */
1186 		status = ((FreeLibraryFunc)());
1187 		DEBUG(1, "HBA_FreeLibrary() Failed %d", status, 0, 0);
1188 	    }
1189 #ifdef WIN32
1190 	    FreeLibrary(lib_infop->hLibrary);	/* Unload DLL from memory */
1191 #else
1192 	    (void) dlclose(lib_infop->hLibrary); /* Unload DLL from memory */
1193 #endif
1194 	}
1195 #ifndef WIN32
1196 	free(lib_infop->LibraryName);
1197 #endif
1198 	free(lib_infop->LibraryPath);
1199 	free(lib_infop);
1200 
1201 	}
1202     _hbaapi_librarylist = NULL;
1203 	/*
1204 	 * OK, now all functions are disabled except for LoadLibrary,
1205 	 * Hope no other thread calls it before we have returned
1206 	 */
1207     _hbaapi_total_library_count = 0;
1208 
1209     for (adapt_infop = _hbaapi_adapterlist;
1210 	    adapt_infop != NULL;
1211 	    adapt_infop = adapt_next) {
1212 		adapt_next = adapt_infop->next;
1213 		free(adapt_infop->name);
1214 		free(adapt_infop);
1215 	}
1216     _hbaapi_adapterlist = NULL;
1217     _hbaapi_total_adapter_count = 0;
1218 
1219 	/*
1220 	 * Free up the callbacks, this is not the most efficient, but it works
1221 	 */
1222 	while ((volatile HBA_ADAPTERCALLBACK_ELEM *)
1223 	    _hbaapi_adapteraddevents_callback_list
1224 	    != NULL) {
1225 	(void) local_remove_callback((HBA_CALLBACKHANDLE)
1226 	    _hbaapi_adapteraddevents_callback_list);
1227 	}
1228 	while ((volatile HBA_ADAPTERCALLBACK_ELEM *)
1229 	    _smhba_adapteraddevents_callback_list
1230 	    != NULL) {
1231 	(void) local_remove_callback((HBA_CALLBACKHANDLE)
1232 	    _smhba_adapteraddevents_callback_list);
1233 	}
1234     for (listp = cb_lists_array; *listp != NULL; listp++) {
1235 	while ((volatile HBA_ADAPTERCALLBACK_ELEM ***)**listp != NULL) {
1236 	    (void) local_remove_callback((HBA_CALLBACKHANDLE)**listp);
1237 	}
1238 	}
1239 
1240     RELEASE_MUTEX(&_hbaapi_AL_mutex);
1241     RELEASE_MUTEX(&_hbaapi_LL_mutex);
1242 
1243 #ifdef USESYSLOG
1244     closelog();
1245 #endif
1246 #ifdef USELOGFILE
1247     if (_hbaapi_debug_fd != NULL) {
1248 	fclose(_hbaapi_debug_fd);
1249 	}
1250     _hbaapi_debug_fd = NULL;
1251 #endif
1252 #ifdef POSIX_THREADS
1253 	/* this will unlock them as well, but who cares */
1254 	(void) pthread_mutex_destroy(&_hbaapi_LE_mutex);
1255 	(void) pthread_mutex_destroy(&_hbaapi_TE_mutex);
1256 	(void) pthread_mutex_destroy(&_hbaapi_APSE_mutex);
1257 	(void) pthread_mutex_destroy(&_hbaapi_APE_mutex);
1258 	(void) pthread_mutex_destroy(&_hbaapi_AE_mutex);
1259 	(void) pthread_mutex_destroy(&_hbaapi_AAE_mutex);
1260 	(void) pthread_mutex_destroy(&_smhba_TE_mutex);
1261 	(void) pthread_mutex_destroy(&_smhba_APSE_mutex);
1262 	(void) pthread_mutex_destroy(&_smhba_APE_mutex);
1263 	(void) pthread_mutex_destroy(&_smhba_AE_mutex);
1264 	(void) pthread_mutex_destroy(&_smhba_AAE_mutex);
1265 	(void) pthread_mutex_destroy(&_hbaapi_AL_mutex);
1266 	(void) pthread_mutex_destroy(&_hbaapi_LL_mutex);
1267 #elif defined(WIN32)
1268     DeleteCriticalSection(&_hbaapi_LL_mutex);
1269     DeleteCriticalSection(&_hbaapi_AL_mutex);
1270     DeleteCriticalSection(&_hbaapi_AAE_mutex);
1271     DeleteCriticalSection(&_hbaapi_AE_mutex);
1272     DeleteCriticalSection(&_hbaapi_APE_mutex);
1273     DeleteCriticalSection(&_hbaapi_APSE_mutex);
1274     DeleteCriticalSection(&_hbaapi_TE_mutex);
1275     DeleteCriticalSection(&_hbaapi_LE_mutex);
1276     DeleteCriticalSection(&_smhba_TE_mutex);
1277     DeleteCriticalSection(&_smhba_APSE_mutex);
1278     DeleteCriticalSection(&_smhba_APE_mutex);
1279     DeleteCriticalSection(&_smhba_AE_mutex);
1280     DeleteCriticalSection(&_smhba_AAE_mutex);
1281 #endif
1282 
1283 	return (HBA_STATUS_OK);
1284 }
1285 
1286 /*
1287  * The API used to use fixed size tables as its primary data structure.
1288  * Indexing from 1 to N identified each adapters.  Now the adapters are
1289  * on a linked list.  There is a unique "index" foreach each adapter.
1290  * Adapters always keep their index, even if they are removed from the
1291  * hardware.  The only time the indexing is reset is on HBA_FreeLibrary
1292  */
1293 HBA_UINT32
1294 HBA_GetNumberOfAdapters()
1295 {
1296 	int j = 0;
1297 	HBA_LIBRARY_INFO	*lib_infop;
1298 	HBAGetNumberOfAdaptersFunc GetNumberOfAdaptersFunc;
1299 	HBAGetAdapterNameFunc GetAdapterNameFunc;
1300 	HBA_BOOLEAN		found_name;
1301 	HBA_ADAPTER_INFO	*adapt_infop;
1302 	HBA_STATUS		status;
1303 
1304 	char adaptername[256];
1305 	int num_adapters; /* local */
1306 
1307 	if (_hbaapi_librarylist == NULL) {
1308 		return (0);
1309 	}
1310 	GRAB_MUTEX(&_hbaapi_LL_mutex); /* pay attention to order */
1311 	GRAB_MUTEX(&_hbaapi_AL_mutex);
1312 
1313 	for (lib_infop = _hbaapi_librarylist;
1314 	    lib_infop != NULL;
1315 	    lib_infop = lib_infop->next) {
1316 
1317 	if (lib_infop->status != HBA_LIBRARY_LOADED) {
1318 		continue;
1319 	}
1320 
1321 	GetNumberOfAdaptersFunc =
1322 	    FUNCCOMMON(lib_infop, GetNumberOfAdaptersHandler);
1323 	if (GetNumberOfAdaptersFunc == NULL)  {
1324 		continue;
1325 	}
1326 	num_adapters = ((GetNumberOfAdaptersFunc)());
1327 #ifndef WIN32
1328 	DEBUG(1, "HBAAPI: num_adapters for %s = %d\n",
1329 	    lib_infop->LibraryName, num_adapters, 0);
1330 #else
1331 	DEBUG(1, "HBAAPI: num_adapters for %s = %d\n",
1332 	    lib_infop->LibraryPath, num_adapters, 0);
1333 #endif
1334 
1335 	/* Also get the names of all the adapters here and cache */
1336 	GetAdapterNameFunc = FUNCCOMMON(lib_infop, GetAdapterNameHandler);
1337 	if (GetAdapterNameFunc == NULL) {
1338 		continue;
1339 	}
1340 
1341 	for (j = 0; j < num_adapters; j++) {
1342 		found_name = 0;
1343 		status = (GetAdapterNameFunc)(j, (char *)&adaptername);
1344 		if (status == HBA_STATUS_OK) {
1345 		for (adapt_infop = _hbaapi_adapterlist;
1346 		    adapt_infop != NULL;
1347 		    adapt_infop = adapt_infop->next) {
1348 			/*
1349 			 * check for duplicates, really,
1350 			 * this may just be a second
1351 			 * call to this function
1352 			 * ??? how do we know when a name becomes stale?
1353 			 */
1354 			if (strcmp(adaptername, adapt_infop->name) == 0) {
1355 				/* already got this one */
1356 				found_name++;
1357 			break;
1358 			}
1359 		}
1360 		if (found_name != 0) {
1361 			continue;
1362 		}
1363 		}
1364 
1365 		adapt_infop = (HBA_ADAPTER_INFO *)
1366 		    calloc(1, sizeof (HBA_ADAPTER_INFO));
1367 		if (adapt_infop == NULL) {
1368 #ifndef WIN32
1369 		(void) fprintf(stderr,
1370 		    "HBA_GetNumberOfAdapters: calloc failed"
1371 		    " on sizeof:%lu\n",
1372 		    (unsigned long)(sizeof (HBA_ADAPTER_INFO)));
1373 #endif
1374 		RELEASE_MUTEX(&_hbaapi_AL_mutex);
1375 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex,
1376 		    _hbaapi_total_adapter_count);
1377 		}
1378 		if ((adapt_infop->GNstatus = status) == HBA_STATUS_OK) {
1379 		adapt_infop->name = strdup(adaptername);
1380 		} else {
1381 		char dummyname[512];
1382 		(void) sprintf(dummyname, "NULLADAPTER-%255s-%03d",
1383 		    lib_infop->LibraryPath, _hbaapi_total_adapter_count);
1384 		dummyname[511] = '\0';
1385 		adapt_infop->name = strdup(dummyname);
1386 		}
1387 		lib_infop->numOfAdapters++;
1388 		adapt_infop->library = lib_infop;
1389 		adapt_infop->next = _hbaapi_adapterlist;
1390 		adapt_infop->index = _hbaapi_total_adapter_count;
1391 		_hbaapi_adapterlist = adapt_infop;
1392 		_hbaapi_total_adapter_count++;
1393 	}
1394 	}
1395 	RELEASE_MUTEX(&_hbaapi_AL_mutex);
1396 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, _hbaapi_total_adapter_count);
1397 }
1398 
1399 HBA_STATUS
1400 HBA_GetAdapterName(
1401     HBA_UINT32 adapterindex,
1402     char *adaptername)
1403 {
1404 	HBA_ADAPTER_INFO	*adapt_infop;
1405 	HBA_STATUS		ret = HBA_STATUS_ERROR_ILLEGAL_INDEX;
1406 
1407 	if (adaptername == NULL) {
1408 		DEBUG(1, "HBA_GetAdapterName: NULL pointer adaptername",
1409 		    0, 0, 0);
1410 		return (HBA_STATUS_ERROR_ARG);
1411 	}
1412 
1413 	/*
1414 	 * The adapter index is from old code, but we have
1415 	 * to support it.  Go down the list looking for
1416 	 * the adapter
1417 	 */
1418 	ARE_WE_INITED();
1419 	GRAB_MUTEX(&_hbaapi_AL_mutex);
1420 	*adaptername = '\0';
1421 	for (adapt_infop = _hbaapi_adapterlist;
1422 	    adapt_infop != NULL;
1423 	    adapt_infop = adapt_infop->next) {
1424 
1425 	if (adapt_infop->index == adapterindex) {
1426 		if (adapt_infop->name != NULL &&
1427 		    adapt_infop->GNstatus == HBA_STATUS_OK) {
1428 		(void) strcpy(adaptername, adapt_infop->name);
1429 		} else {
1430 		*adaptername = '\0';
1431 		}
1432 		ret = adapt_infop->GNstatus;
1433 		break;
1434 	}
1435 	}
1436 	DEBUG(2, "GetAdapterName for index:%d ->%s",
1437 	    adapterindex, adaptername, 0);
1438 	RELEASE_MUTEX_RETURN(&_hbaapi_AL_mutex, ret);
1439 }
1440 
1441 HBA_HANDLE
1442 HBA_OpenAdapter(char *adaptername)
1443 {
1444 	HBA_HANDLE		handle;
1445 	HBAOpenAdapterFunc	OpenAdapterFunc;
1446 	HBA_ADAPTER_INFO	*adapt_infop;
1447 	HBA_LIBRARY_INFO	*lib_infop;
1448 
1449 	DEBUG(2, "OpenAdapter: %s", adaptername, 0, 0);
1450 
1451 	handle = HBA_HANDLE_INVALID;
1452 	if (_hbaapi_librarylist == NULL) {
1453 		return (handle);
1454 	}
1455 	if (adaptername == NULL) {
1456 		DEBUG(1, "HBA_OpenAdapter: NULL pointer adaptername",
1457 		    0, 0, 0);
1458 		return (handle);
1459 	}
1460 	GRAB_MUTEX(&_hbaapi_AL_mutex);
1461 	for (adapt_infop = _hbaapi_adapterlist;
1462 	    adapt_infop != NULL;
1463 	    adapt_infop = adapt_infop->next) {
1464 	if (strcmp(adaptername, adapt_infop->name) != 0) {
1465 		continue;
1466 	}
1467 	lib_infop = adapt_infop->library;
1468 	OpenAdapterFunc = FUNCCOMMON(lib_infop, OpenAdapterHandler);
1469 
1470 	if (OpenAdapterFunc != NULL) {
1471 	    /* retrieve the vendor handle */
1472 		handle = (OpenAdapterFunc)(adaptername);
1473 		if (handle != 0) {
1474 		/* or this with the library index to get the common handle */
1475 		handle = HBA_HANDLE_FROM_LOCAL(lib_infop->index, handle);
1476 		}
1477 	}
1478 	break;
1479 	}
1480 	RELEASE_MUTEX_RETURN(&_hbaapi_AL_mutex, handle);
1481 }
1482 
1483 /*
1484  * Finding an adapter with matching WWN.
1485  */
1486 HBA_STATUS
1487 HBA_OpenAdapterByWWN(HBA_HANDLE *phandle, HBA_WWN nodeWWN) {
1488     HBA_HANDLE		handle;
1489     HBA_LIBRARY_INFO	*lib_infop;
1490     HBAGetNumberOfAdaptersFunc
1491 			GetNumberOfAdaptersFunc;
1492     HBAOpenAdapterByWWNFunc
1493 			OpenAdapterFunc;
1494     HBA_STATUS		status;
1495 
1496     DEBUG(2, "OpenAdapterByWWN: %s", WWN2STR1(&nodeWWN), 0, 0);
1497     ARE_WE_INITED();
1498 
1499 	*phandle = HBA_HANDLE_INVALID;
1500 
1501     GRAB_MUTEX(&_hbaapi_LL_mutex);
1502     for (lib_infop = _hbaapi_librarylist;
1503 	    lib_infop != NULL;
1504 	    lib_infop = lib_infop->next) {
1505 
1506 	status = HBA_STATUS_ERROR_ILLEGAL_WWN;
1507 
1508 	if (lib_infop->status != HBA_LIBRARY_LOADED) {
1509 	    continue;
1510 	}
1511 
1512 	/* only for HBAAPIV2 */
1513 	if (lib_infop->version != HBAAPIV2) {
1514 	    continue;
1515 	}
1516 
1517 	GetNumberOfAdaptersFunc =
1518 		FUNCCOMMON(lib_infop, GetNumberOfAdaptersHandler);
1519 	if (GetNumberOfAdaptersFunc == NULL)  {
1520 	    continue;
1521 	}
1522 
1523 	/* look for new hardware */
1524 	(void) ((GetNumberOfAdaptersFunc)());
1525 
1526 	OpenAdapterFunc =
1527 	    lib_infop->ftable.functionTable.OpenAdapterByWWNHandler;
1528 	if (OpenAdapterFunc == NULL) {
1529 	    continue;
1530 	}
1531 	/*
1532 	 * We do not know if the WWN is known by this vendor,
1533 	 * just try it
1534 	 */
1535 	if ((status = (OpenAdapterFunc)(&handle, nodeWWN)) != HBA_STATUS_OK) {
1536 	    continue;
1537 	}
1538 	/* OK, make a vendor non-specific handle */
1539 	*phandle = HBA_HANDLE_FROM_LOCAL(lib_infop->index, handle);
1540 	status = HBA_STATUS_OK;
1541 	break;
1542 	}
1543     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1544 }
1545 
1546 void
1547 HBA_RefreshAdapterConfiguration() {
1548     DEBUG(2, "HBA_RefreshAdapterConfiguration", 0, 0, 0);
1549 	(void) HBA_GetNumberOfAdapters();
1550 }
1551 
1552 HBA_UINT32
1553 HBA_GetVersion() {
1554     DEBUG(2, "HBA_GetVersion", 0, 0, 0);
1555 	return (HBA_LIBVERSION);
1556 }
1557 
1558 /*
1559  * This function is VERY OS dependent.  Wing it as best you can.
1560  */
1561 HBA_UINT32
1562 HBA_GetWrapperLibraryAttributes(
1563     HBA_LIBRARYATTRIBUTES *attributes)
1564 {
1565 
1566 	DEBUG(2, "HBA_GetWrapperLibraryAttributes", 0, 0, 0);
1567 
1568 	if (attributes == NULL) {
1569 		DEBUG(1, "HBA_GetWrapperLibraryAttributes:"
1570 		    "NULL pointer attributes",
1571 		    0, 0, 0);
1572 		return (HBA_STATUS_ERROR_ARG);
1573 	}
1574 
1575 	(void) memset(attributes, 0, sizeof (HBA_LIBRARYATTRIBUTES));
1576 
1577 #if defined(SOLARIS)
1578 	if ((handle = dlopen("libHBAAPI.so", RTLD_NOW)) != NULL) {
1579 	if (dlinfo(handle, RTLD_DI_LINKMAP, &map) >= 0) {
1580 		for (mp = map; mp != NULL; mp = mp->l_next) {
1581 		if (strlen(map->l_name) < 256) {
1582 			(void) strcpy(attributes->LibPath, map->l_name);
1583 		}
1584 		}
1585 	}
1586 	}
1587 #elif defined(WIN32)
1588 	HMODULE module;
1589 
1590 	/* No need to do anything with the module handle */
1591 	/* It wasn't alloocated so it doesn't need to be freed */
1592 	module = GetModuleHandle("HBAAPI");
1593 	if (module != NULL) {
1594 		if (GetModuleFileName(module, attributes->LibPath,
1595 		    sizeof (attributes->LibPath)) == 0) {
1596 			attributes->LibPath[0] = '\0';
1597 		}
1598 	}
1599 #endif
1600 #if defined(VENDOR)
1601 	(void) strcpy(attributes->VName, VENDOR);
1602 #else
1603 	attributes->VName[0] = '\0';
1604 #endif
1605 #if defined(VERSION)
1606 	(void) strcpy(attributes->VVersion, VERSION);
1607 #else
1608 	attributes->VVersion[0] = '\0';
1609 #endif
1610 #if defined(BUILD_DATE)
1611 #if defined(WIN32)
1612 	int matchCount;
1613 	matchCount = sscanf(BUILD_DATE, "%u/%u/%u %u:%u:%u",
1614 	    &attributes->build_date.tm_year,
1615 	    &attributes->build_date.tm_mon,
1616 	    &attributes->build_date.tm_mday,
1617 	    &attributes->build_date.tm_hour,
1618 	    &attributes->build_date.tm_min,
1619 	    &attributes->build_date.tm_sec);
1620 
1621 	if (matchCount != 6) {
1622 		memset(&attributes->build_date, 0, sizeof (struct tm));
1623 	} else {
1624 		attributes->build_date.tm_year -= 1900;
1625 		attributes->build_date.tm_isdst = -1;
1626 	}
1627 #else
1628 	if (strptime(BUILD_DATE,
1629 	    "%Y/%m/%d %T %Z", &(attributes->build_date)) == NULL) {
1630 		(void) memset(&attributes->build_date, 0, sizeof (struct tm));
1631 	}
1632 #endif
1633 #else
1634 	(void) memset(&attributes->build_date, 0, sizeof (struct tm));
1635 #endif
1636 	return (2);
1637 }
1638 
1639 /*
1640  * Callback registation and handling
1641  */
1642 HBA_STATUS
1643 HBA_RemoveCallback(HBA_CALLBACKHANDLE cbhandle) {
1644     HBA_STATUS	status;
1645 
1646     DEBUG(2, "HBA_RemoveCallback", 0, 0, 0);
1647     ARE_WE_INITED();
1648 
1649     GRAB_MUTEX(&_hbaapi_LL_mutex);
1650     status = local_remove_callback(cbhandle);
1651     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1652 }
1653 
1654 /* Adapter Add Events ************************************************* */
1655 static void
1656 /* LINTED E_FUNC_ARG_UNUSED */
1657 adapteraddevents_callback(void *data, HBA_WWN PortWWN, HBA_UINT32 eventType) {
1658     HBA_ALLADAPTERSCALLBACK_ELEM	*cbp;
1659 
1660     DEBUG(3, "AddAdapterEvent, port: %s", WWN2STR1(&PortWWN), 0, 0);
1661 
1662     GRAB_MUTEX(&_hbaapi_AAE_mutex);
1663     for (cbp = _hbaapi_adapteraddevents_callback_list;
1664 	    cbp != NULL;
1665 	    cbp = cbp->next) {
1666 	(*cbp->callback)(data, PortWWN, HBA_EVENT_ADAPTER_ADD);
1667 	}
1668     RELEASE_MUTEX(&_hbaapi_AAE_mutex);
1669 
1670 }
1671 
1672 HBA_STATUS
1673 HBA_RegisterForAdapterAddEvents(
1674     void		(*callback)(
1675 	void		*data,
1676 	HBA_WWN		PortWWN,
1677 	HBA_UINT32	eventType),
1678 	void		*userData,
1679     HBA_CALLBACKHANDLE *callbackHandle) {
1680 
1681     HBA_ALLADAPTERSCALLBACK_ELEM	*cbp;
1682     HBA_VENDORCALLBACK_ELEM		*vcbp;
1683     HBA_VENDORCALLBACK_ELEM		*vendorhandlelist;
1684     HBARegisterForAdapterAddEventsFunc	registeredfunc;
1685     HBA_STATUS				status = HBA_STATUS_OK;
1686     HBA_STATUS				failure = HBA_STATUS_OK;
1687     HBA_LIBRARY_INFO			*lib_infop;
1688     int					registered_cnt = 0;
1689     int					vendor_cnt = 0;
1690     int					not_supported_cnt = 0;
1691     int					status_OK_bar_cnt = 0;
1692     int					status_OK_cnt = 0;
1693 
1694     DEBUG(2, "HBA_RegisterForAdapterAddEvents", 0, 0, 0);
1695     ARE_WE_INITED();
1696 
1697     cbp = (HBA_ALLADAPTERSCALLBACK_ELEM *)
1698 	calloc(1, sizeof (HBA_ALLADAPTERSCALLBACK_ELEM));
1699 	*callbackHandle = (HBA_CALLBACKHANDLE) cbp;
1700 	if (cbp == NULL) {
1701 #ifndef WIN32
1702 	(void) fprintf(stderr,
1703 		"HBA_RegisterForAdapterAddEvents: calloc failed "
1704 		"for %lu bytes\n",
1705 		(unsigned long)(sizeof (HBA_ALLADAPTERSCALLBACK_ELEM)));
1706 #endif
1707 	return (HBA_STATUS_ERROR);
1708 	}
1709 
1710     GRAB_MUTEX(&_hbaapi_LL_mutex);
1711     GRAB_MUTEX(&_hbaapi_AAE_mutex);
1712     cbp->callback = callback;
1713     cbp->next = _hbaapi_adapteraddevents_callback_list;
1714     _hbaapi_adapteraddevents_callback_list = cbp;
1715 	/*
1716 	 * Need to release the mutex now incase the vendor function invokes the
1717 	 * callback.  We will grap the mutex later to attach the vendor handle
1718 	 * list to the callback structure
1719 	 */
1720     RELEASE_MUTEX(&_hbaapi_AAE_mutex);
1721 
1722 	/*
1723 	 * now create a list of vendors (vendor libraryies, NOT ADAPTERS)
1724 	 * that have successfully registerred
1725 	 */
1726 	vendorhandlelist = NULL;
1727     for (lib_infop = _hbaapi_librarylist;
1728 	    lib_infop != NULL;
1729 	    lib_infop = lib_infop->next) {
1730 
1731 	/* only for HBAAPI V2 */
1732 	if ((lib_infop->version != HBAAPIV2)) {
1733 	    continue;
1734 	} else {
1735 	    vendor_cnt++;
1736 	}
1737 
1738 	registeredfunc =
1739 	    lib_infop->ftable.functionTable.RegisterForAdapterAddEventsHandler;
1740 	if (registeredfunc == NULL) {
1741 	    continue;
1742 	}
1743 
1744 	vcbp = (HBA_VENDORCALLBACK_ELEM *)
1745 	    calloc(1, sizeof (HBA_VENDORCALLBACK_ELEM));
1746 	if (vcbp == NULL) {
1747 #ifndef WIN32
1748 	    (void) fprintf(stderr,
1749 		    "HBA_RegisterForAdapterAddEvents: "
1750 		    "calloc failed for %lu bytes\n",
1751 		    (unsigned long)(sizeof (HBA_VENDORCALLBACK_ELEM)));
1752 #endif
1753 	    freevendorhandlelist(vendorhandlelist);
1754 	    status = HBA_STATUS_ERROR;
1755 	    break;
1756 	}
1757 
1758 	registered_cnt++;
1759 	status = (registeredfunc)(adapteraddevents_callback,
1760 	    userData, &vcbp->vendorcbhandle);
1761 	if (status == HBA_STATUS_ERROR_NOT_SUPPORTED) {
1762 	    not_supported_cnt++;
1763 	    free(vcbp);
1764 	    continue;
1765 	} else if (status != HBA_STATUS_OK) {
1766 	    status_OK_bar_cnt++;
1767 	    DEBUG(1,
1768 		    "HBA_RegisterForAdapterAddEvents: Library->%s, Error->%d",
1769 		    lib_infop->LibraryPath, status, 0);
1770 #ifndef WIN32
1771 	    (void) fprintf(stderr,
1772 		    "HBA_RegisterForAdapterAddEvents: Library->%s, Error->%d",
1773 		    lib_infop->LibraryPath, status);
1774 #endif
1775 	    failure = status;
1776 	    free(vcbp);
1777 	    continue;
1778 	} else {
1779 	    status_OK_cnt++;
1780 	}
1781 	vcbp->lib_info = lib_infop;
1782 	vcbp->next = vendorhandlelist;
1783 	vendorhandlelist = vcbp;
1784 	}
1785     if (vendor_cnt == 0) {
1786 	/* no HBAAPIV2 is deteced.  should be okay? */
1787 	status = HBA_STATUS_ERROR;
1788 	} else if (registered_cnt == 0) {
1789 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
1790 	freevendorhandlelist(vendorhandlelist);
1791 	(void) local_remove_callback((HBA_CALLBACKHANDLE) cbp);
1792 	} else if (status_OK_cnt == 0 && not_supported_cnt != 0) {
1793 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
1794 	} else if (status_OK_cnt == 0) {
1795 	/*
1796 	 * At least one vendor library registered this function, but no
1797 	 * vendor call succeeded
1798 	 */
1799 	(void) local_remove_callback((HBA_CALLBACKHANDLE) cbp);
1800 	status = failure;
1801 	} else {
1802 	/* we have had atleast some success, now finish up */
1803 	GRAB_MUTEX(&_hbaapi_AAE_mutex);
1804 	/*
1805 	 * this seems silly, but what if another thread called
1806 	 * the callback remove
1807 	 */
1808 	for (cbp = _hbaapi_adapteraddevents_callback_list;
1809 	    cbp != NULL; cbp = cbp->next) {
1810 	    if ((HBA_CALLBACKHANDLE)cbp == *callbackHandle) {
1811 		/* yup, its still there, hooray */
1812 		cbp->vendorhandlelist = vendorhandlelist;
1813 		vendorhandlelist = NULL;
1814 		break;
1815 	    }
1816 	}
1817 	RELEASE_MUTEX(&_hbaapi_AAE_mutex);
1818 	if (vendorhandlelist != NULL) {
1819 		/*
1820 		 * bummer, somebody removed the callback before we finished
1821 		 * registration, probably will never happen
1822 		 */
1823 	    freevendorhandlelist(vendorhandlelist);
1824 	    DEBUG(1,
1825 		    "HBA_RegisterForAdapterAddEvents: HBA_RemoveCallback was "
1826 		    "called for a handle before registration was finished.",
1827 		    0, 0, 0);
1828 	    status = HBA_STATUS_ERROR;
1829 	} else {
1830 	    status = HBA_STATUS_OK;
1831 	}
1832 	}
1833     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1834 }
1835 
1836 /* Adapter Events (other than add) ************************************** */
1837 static void
1838 adapterevents_callback(void *data,
1839 			HBA_WWN PortWWN,
1840 			HBA_UINT32 eventType) {
1841     HBA_ADAPTERCALLBACK_ELEM	*acbp;
1842 
1843     DEBUG(3, "AdapterEvent, port:%s, eventType:%d", WWN2STR1(&PortWWN),
1844 	    eventType, 0);
1845 
1846 	GRAB_MUTEX(&_hbaapi_AE_mutex);
1847 	for (acbp = _hbaapi_adapterevents_callback_list;
1848 	acbp != NULL;
1849 	acbp = acbp->next) {
1850 	if (data == (void *)acbp) {
1851 	    (*acbp->callback)(acbp->userdata, PortWWN, eventType);
1852 	    break;
1853 	}
1854 	}
1855     RELEASE_MUTEX(&_hbaapi_AE_mutex);
1856 }
1857 HBA_STATUS
1858 HBA_RegisterForAdapterEvents(
1859     void		(*callback) (
1860 	void		*data,
1861 	HBA_WWN		PortWWN,
1862 	HBA_UINT32	eventType),
1863     void		*userData,
1864     HBA_HANDLE		handle,
1865     HBA_CALLBACKHANDLE	*callbackHandle) {
1866 
1867     HBA_ADAPTERCALLBACK_ELEM		*acbp;
1868     HBARegisterForAdapterEventsFunc	registeredfunc;
1869     HBA_STATUS				status;
1870     HBA_LIBRARY_INFO			*lib_infop;
1871     HBA_HANDLE				vendorHandle;
1872 
1873     DEBUG(2, "HBA_RegisterForAdapterEvents", 0, 0, 0);
1874 
1875     CHECKLIBRARYANDVERSION(HBAAPIV2);
1876 
1877 	/* we now have the _hbaapi_LL_mutex */
1878 
1879     registeredfunc =
1880 	    lib_infop->ftable.functionTable.RegisterForAdapterEventsHandler;
1881     if (registeredfunc == NULL) {
1882 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
1883 	}
1884 
1885 	/*
1886 	 * that allocated memory is used both as the handle for the
1887 	 * caller, and as userdata to the vendor call so that on
1888 	 * callback the specific registration may be recalled
1889 	 */
1890     acbp = (HBA_ADAPTERCALLBACK_ELEM *)
1891 	calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
1892     if (acbp == NULL) {
1893 #ifndef WIN32
1894 	(void) fprintf(stderr,
1895 		"HBA_RegisterForAdapterEvents: calloc failed for %lu bytes\n",
1896 		(unsigned long)(sizeof (HBA_ADAPTERCALLBACK_ELEM)));
1897 #endif
1898 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
1899 	}
1900 	*callbackHandle = (HBA_CALLBACKHANDLE) acbp;
1901     acbp->callback = callback;
1902     acbp->userdata = userData;
1903     acbp->lib_info = lib_infop;
1904 
1905     status = (registeredfunc)(adapterevents_callback,
1906 	    (void *)acbp,
1907 	    vendorHandle,
1908 	    &acbp->vendorcbhandle);
1909     if (status != HBA_STATUS_OK) {
1910 	free(acbp);
1911 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1912 	}
1913 
1914     GRAB_MUTEX(&_hbaapi_AE_mutex);
1915     acbp->next = _hbaapi_adapterevents_callback_list;
1916     _hbaapi_adapterevents_callback_list = acbp;
1917     RELEASE_MUTEX(&_hbaapi_AE_mutex);
1918 
1919     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
1920 }
1921 
1922 /* Adapter Port Events ************************************************** */
1923 static void
1924 adapterportevents_callback(void *data,
1925 			    HBA_WWN PortWWN,
1926 			    HBA_UINT32 eventType,
1927 			    HBA_UINT32 fabricPortID) {
1928     HBA_ADAPTERCALLBACK_ELEM	*acbp;
1929 
1930     DEBUG(3, "AdapterPortEvent, port:%s, eventType:%d fabricPortID:0X%06x",
1931 	    WWN2STR1(&PortWWN), eventType, fabricPortID);
1932 
1933     GRAB_MUTEX(&_hbaapi_APE_mutex);
1934 
1935     for (acbp = _hbaapi_adapterportevents_callback_list;
1936 	acbp != NULL;
1937 	acbp = acbp->next) {
1938 	if (data == (void *)acbp) {
1939 	    (*acbp->callback)(acbp->userdata, PortWWN, eventType, fabricPortID);
1940 	    break;
1941 	}
1942 	}
1943     RELEASE_MUTEX(&_hbaapi_APE_mutex);
1944 }
1945 
1946 HBA_STATUS
1947 HBA_RegisterForAdapterPortEvents(
1948     void		(*callback) (
1949 	void		*data,
1950 	HBA_WWN		PortWWN,
1951 	HBA_UINT32	eventType,
1952 	HBA_UINT32	fabricPortID),
1953     void		*userData,
1954     HBA_HANDLE		handle,
1955     HBA_WWN		PortWWN,
1956     HBA_CALLBACKHANDLE	*callbackHandle) {
1957 
1958     HBA_ADAPTERCALLBACK_ELEM		*acbp;
1959     HBARegisterForAdapterPortEventsFunc	registeredfunc;
1960     HBA_STATUS				status;
1961     HBA_LIBRARY_INFO			*lib_infop;
1962     HBA_HANDLE				vendorHandle;
1963 
1964     DEBUG(2, "HBA_RegisterForAdapterPortEvents for port: %s",
1965 	    WWN2STR1(&PortWWN), 0, 0);
1966 
1967     CHECKLIBRARYANDVERSION(HBAAPIV2);
1968 	/* we now have the _hbaapi_LL_mutex */
1969 
1970 	registeredfunc =
1971 	lib_infop->ftable.functionTable.RegisterForAdapterPortEventsHandler;
1972     if (registeredfunc == NULL) {
1973 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
1974 	}
1975 
1976 	/*
1977 	 * that allocated memory is used both as the handle for the
1978 	 * caller, and as userdata to the vendor call so that on
1979 	 * callback the specific registration may be recalled
1980 	 */
1981 	acbp = (HBA_ADAPTERCALLBACK_ELEM *)
1982 	calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
1983     if (acbp == NULL) {
1984 #ifndef WIN32
1985 	(void) fprintf(stderr,
1986 		"HBA_RegisterForAdapterPortEvents: "
1987 		"calloc failed for %lu bytes\n",
1988 		(unsigned long)(sizeof (HBA_ADAPTERCALLBACK_ELEM)));
1989 #endif
1990 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
1991 
1992 	}
1993 	*callbackHandle = (HBA_CALLBACKHANDLE) acbp;
1994     acbp->callback = callback;
1995     acbp->userdata = userData;
1996     acbp->lib_info = lib_infop;
1997 
1998     status = (registeredfunc)(adapterportevents_callback,
1999 	    (void *)acbp,
2000 	    vendorHandle,
2001 	    PortWWN,
2002 	    &acbp->vendorcbhandle);
2003     if (status != HBA_STATUS_OK) {
2004 	free(acbp);
2005 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2006 	}
2007 
2008     GRAB_MUTEX(&_hbaapi_APE_mutex);
2009     acbp->next = _hbaapi_adapterportevents_callback_list;
2010     _hbaapi_adapterportevents_callback_list = acbp;
2011     RELEASE_MUTEX(&_hbaapi_APE_mutex);
2012 
2013     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
2014 }
2015 
2016 /* Adapter State Events ************************************************ */
2017 static void
2018 adapterportstatevents_callback(void *data,
2019 				HBA_WWN PortWWN,
2020 				HBA_UINT32 eventType) {
2021     HBA_ADAPTERCALLBACK_ELEM	*acbp;
2022 
2023 	DEBUG(3, "AdapterPortStatEvent, port:%s, eventType:%d",
2024 	    WWN2STR1(&PortWWN),
2025 	    eventType, 0);
2026 
2027     GRAB_MUTEX(&_hbaapi_APSE_mutex);
2028     for (acbp = _hbaapi_adapterportstatevents_callback_list;
2029 	acbp != NULL;
2030 	acbp = acbp->next) {
2031 	if (data == (void *)acbp) {
2032 	    (*acbp->callback)(acbp->userdata, PortWWN, eventType);
2033 	    return;
2034 	}
2035 	}
2036     RELEASE_MUTEX(&_hbaapi_APSE_mutex);
2037 }
2038 HBA_STATUS
2039 HBA_RegisterForAdapterPortStatEvents(
2040     void		(*callback) (
2041 	void		*data,
2042 	HBA_WWN		PortWWN,
2043 	HBA_UINT32	eventType),
2044     void		*userData,
2045     HBA_HANDLE		handle,
2046     HBA_WWN		PortWWN,
2047     HBA_PORTSTATISTICS	stats,
2048     HBA_UINT32		statType,
2049     HBA_CALLBACKHANDLE	*callbackHandle) {
2050 
2051     HBA_ADAPTERCALLBACK_ELEM	*acbp;
2052     HBARegisterForAdapterPortStatEventsFunc
2053 				registeredfunc;
2054     HBA_STATUS			status;
2055     HBA_LIBRARY_INFO		*lib_infop;
2056     HBA_HANDLE			vendorHandle;
2057 
2058     DEBUG(2, "HBA_RegisterForAdapterPortStatEvents for port: %s",
2059 	    WWN2STR1(&PortWWN), 0, 0);
2060 
2061     CHECKLIBRARYANDVERSION(HBAAPIV2);
2062 	/* we now have the _hbaapi_LL_mutex */
2063 
2064     registeredfunc =
2065 	lib_infop->ftable.functionTable.RegisterForAdapterPortStatEventsHandler;
2066     if (registeredfunc == NULL) {
2067 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
2068 	}
2069 
2070 	/*
2071 	 * that allocated memory is used both as the handle for the
2072 	 * caller, and as userdata to the vendor call so that on
2073 	 * callback the specific registration may be recalled
2074 	 */
2075     acbp = (HBA_ADAPTERCALLBACK_ELEM *)
2076 	calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
2077     if (acbp == NULL) {
2078 #ifndef WIN32
2079 	(void) fprintf(stderr,
2080 		"HBA_RegisterForAdapterPortStatEvents: "
2081 		"calloc failed for %lu bytes\n",
2082 		(unsigned long)(sizeof (HBA_ADAPTERCALLBACK_ELEM)));
2083 #endif
2084 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
2085 	}
2086 	*callbackHandle = (HBA_CALLBACKHANDLE) acbp;
2087     acbp->callback = callback;
2088     acbp->userdata = userData;
2089     acbp->lib_info = lib_infop;
2090 
2091     status = (registeredfunc)(adapterportstatevents_callback,
2092 	    (void *)acbp,
2093 	    vendorHandle,
2094 	    PortWWN,
2095 	    stats,
2096 	    statType,
2097 	    &acbp->vendorcbhandle);
2098     if (status != HBA_STATUS_OK) {
2099 	free(acbp);
2100 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2101 	}
2102 
2103     GRAB_MUTEX(&_hbaapi_APSE_mutex);
2104     acbp->next = _hbaapi_adapterportstatevents_callback_list;
2105     _hbaapi_adapterportstatevents_callback_list = acbp;
2106     RELEASE_MUTEX(&_hbaapi_APSE_mutex);
2107 
2108     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
2109 }
2110 
2111 /* Target Events ******************************************************* */
2112 static void
2113 targetevents_callback(void *data,
2114     HBA_WWN hbaPortWWN,
2115     HBA_WWN discoveredPortWWN,
2116     HBA_UINT32 eventType) {
2117 
2118 	HBA_ADAPTERCALLBACK_ELEM	*acbp;
2119 
2120     DEBUG(3, "TargetEvent, hbaPort:%s, discoveredPort:%s eventType:%d",
2121 	    WWN2STR1(&hbaPortWWN), WWN2STR2(&discoveredPortWWN), eventType);
2122 
2123     GRAB_MUTEX(&_hbaapi_TE_mutex);
2124     for (acbp = _hbaapi_targetevents_callback_list;
2125 	acbp != NULL;
2126 	acbp = acbp->next) {
2127 	if (data == (void *)acbp) {
2128 	    (*acbp->callback)(acbp->userdata, hbaPortWWN,
2129 	    discoveredPortWWN, eventType);
2130 	    break;
2131 	}
2132 	}
2133     RELEASE_MUTEX(&_hbaapi_TE_mutex);
2134 }
2135 
2136 HBA_STATUS
2137 HBA_RegisterForTargetEvents(
2138     void		(*callback) (
2139 	void		*data,
2140 	HBA_WWN		hbaPortWWN,
2141 	HBA_WWN		discoveredPortWWN,
2142 	HBA_UINT32	eventType),
2143     void		*userData,
2144     HBA_HANDLE		handle,
2145     HBA_WWN		hbaPortWWN,
2146     HBA_WWN		discoveredPortWWN,
2147     HBA_CALLBACKHANDLE	*callbackHandle,
2148     HBA_UINT32		allTargets) {
2149 
2150     HBA_ADAPTERCALLBACK_ELEM
2151 			*acbp;
2152     HBARegisterForTargetEventsFunc
2153 			registeredfunc;
2154     HBA_STATUS		status;
2155     HBA_LIBRARY_INFO	*lib_infop;
2156     HBA_HANDLE		vendorHandle;
2157 
2158     DEBUG(2, "HBA_RegisterForTargetEvents, hbaPort: %s, discoveredPort: %s",
2159 	    WWN2STR1(&hbaPortWWN), WWN2STR2(&discoveredPortWWN), 0);
2160 
2161     CHECKLIBRARYANDVERSION(HBAAPIV2);
2162 	/* we now have the _hbaapi_LL_mutex */
2163 
2164     registeredfunc =
2165 	    lib_infop->ftable.functionTable.RegisterForTargetEventsHandler;
2166     if (registeredfunc == NULL) {
2167 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
2168 	}
2169 
2170 	/*
2171 	 * that allocated memory is used both as the handle for the
2172 	 * caller, and as userdata to the vendor call so that on
2173 	 * callback the specific registration may be recalled
2174 	 */
2175 	acbp = (HBA_ADAPTERCALLBACK_ELEM *)
2176 	calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
2177     if (acbp == NULL) {
2178 #ifndef WIN32
2179 	(void) fprintf(stderr,
2180 		"HBA_RegisterForTargetEvents: calloc failed for %lu bytes\n",
2181 		(unsigned long)(sizeof (HBA_ADAPTERCALLBACK_ELEM)));
2182 #endif
2183 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
2184 	}
2185 	*callbackHandle = (HBA_CALLBACKHANDLE) acbp;
2186     acbp->callback = callback;
2187     acbp->userdata = userData;
2188     acbp->lib_info = lib_infop;
2189 
2190     status = (registeredfunc)(targetevents_callback,
2191 	    (void *)acbp,
2192 	    vendorHandle,
2193 	    hbaPortWWN,
2194 	    discoveredPortWWN,
2195 	    &acbp->vendorcbhandle,
2196 	    allTargets);
2197     if (status != HBA_STATUS_OK) {
2198 	free(acbp);
2199 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2200 	}
2201 
2202     GRAB_MUTEX(&_hbaapi_TE_mutex);
2203     acbp->next = _hbaapi_targetevents_callback_list;
2204     _hbaapi_targetevents_callback_list = acbp;
2205     RELEASE_MUTEX(&_hbaapi_TE_mutex);
2206 
2207     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
2208 }
2209 
2210 /* Link Events ********************************************************* */
2211 static void
2212 linkevents_callback(void *data,
2213     HBA_WWN adapterWWN,
2214     HBA_UINT32 eventType,
2215     void *pRLIRBuffer,
2216     HBA_UINT32 RLIRBufferSize) {
2217 	HBA_ADAPTERCALLBACK_ELEM	*acbp;
2218 
2219     DEBUG(3, "LinkEvent, hbaWWN:%s, eventType:%d",
2220 	    WWN2STR1(&adapterWWN), eventType, 0);
2221 
2222     GRAB_MUTEX(&_hbaapi_LE_mutex);
2223     for (acbp = _hbaapi_linkevents_callback_list;
2224 	acbp != NULL;
2225 	acbp = acbp->next) {
2226 	if (data == (void *)acbp) {
2227 	    (*acbp->callback)(acbp->userdata, adapterWWN,
2228 		eventType, pRLIRBuffer, RLIRBufferSize);
2229 	    break;
2230 	}
2231 	}
2232     RELEASE_MUTEX(&_hbaapi_LE_mutex);
2233 }
2234 HBA_STATUS
2235 HBA_RegisterForLinkEvents(
2236     void		(*callback) (
2237 	void		*data,
2238 	HBA_WWN		adapterWWN,
2239 	HBA_UINT32	eventType,
2240 	void		*pRLIRBuffer,
2241 	HBA_UINT32	RLIRBufferSize),
2242     void		*userData,
2243     void		*pRLIRBuffer,
2244     HBA_UINT32		RLIRBufferSize,
2245     HBA_HANDLE		handle,
2246     HBA_CALLBACKHANDLE	*callbackHandle) {
2247 
2248     HBA_ADAPTERCALLBACK_ELEM	*acbp;
2249     HBARegisterForLinkEventsFunc
2250 				registeredfunc;
2251     HBA_STATUS			status;
2252     HBA_LIBRARY_INFO		*lib_infop;
2253     HBA_HANDLE			vendorHandle;
2254 
2255     DEBUG(2, "HBA_RegisterForLinkEvents", 0, 0, 0);
2256 
2257     CHECKLIBRARY();
2258 	/* we now have the _hbaapi_LL_mutex */
2259 
2260     registeredfunc = FUNCCOMMON(lib_infop, RegisterForLinkEventsHandler);
2261 
2262     if (registeredfunc == NULL) {
2263 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
2264 	}
2265 
2266 	/*
2267 	 * that allocated memory is used both as the handle for the
2268 	 * caller, and as userdata to the vendor call so that on
2269 	 * callback the specific registration may be recalled
2270 	 */
2271     acbp = (HBA_ADAPTERCALLBACK_ELEM *)
2272 	calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
2273     if (acbp == NULL) {
2274 #ifndef WIN32
2275 	(void) fprintf(stderr,
2276 		"HBA_RegisterForLinkEvents: calloc failed for %lu bytes\n",
2277 		(unsigned long)(sizeof (HBA_ADAPTERCALLBACK_ELEM)));
2278 #endif
2279 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
2280 	}
2281 	*callbackHandle = (HBA_CALLBACKHANDLE) acbp;
2282     acbp->callback = callback;
2283     acbp->userdata = userData;
2284     acbp->lib_info = lib_infop;
2285 
2286     status = (registeredfunc)(linkevents_callback,
2287 	    (void *)acbp,
2288 	    pRLIRBuffer,
2289 	    RLIRBufferSize,
2290 	    vendorHandle,
2291 	    &acbp->vendorcbhandle);
2292     if (status != HBA_STATUS_OK) {
2293 	free(acbp);
2294 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2295 	}
2296 
2297     GRAB_MUTEX(&_hbaapi_LE_mutex);
2298     acbp->next = _hbaapi_linkevents_callback_list;
2299     _hbaapi_linkevents_callback_list = acbp;
2300     RELEASE_MUTEX(&_hbaapi_LE_mutex);
2301 
2302     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
2303 }
2304 
2305 /*
2306  * All of the functions below are almost passthru functions to the
2307  * vendor specific function
2308  */
2309 
2310 void
2311 HBA_CloseAdapter(HBA_HANDLE handle) {
2312     HBA_STATUS		status;
2313     HBA_LIBRARY_INFO	*lib_infop;
2314     HBA_HANDLE		vendorHandle;
2315     HBACloseAdapterFunc CloseAdapterFunc;
2316 
2317     DEBUG(2, "HBA_CloseAdapter", 0, 0, 0);
2318 
2319     status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);
2320     if (status == HBA_STATUS_OK) {
2321 	CloseAdapterFunc = FUNCCOMMON(lib_infop, CloseAdapterHandler);
2322 	if (CloseAdapterFunc != NULL) {
2323 	    ((CloseAdapterFunc)(vendorHandle));
2324 	}
2325 	RELEASE_MUTEX(&_hbaapi_LL_mutex);
2326 	}
2327 }
2328 
2329 HBA_STATUS
2330 HBA_GetAdapterAttributes(
2331     HBA_HANDLE		handle,
2332     HBA_ADAPTERATTRIBUTES
2333 			*hbaattributes)
2334 {
2335 	HBA_STATUS		status;
2336 	HBA_LIBRARY_INFO	*lib_infop;
2337 	HBA_HANDLE		vendorHandle;
2338 	HBAGetAdapterAttributesFunc GetAdapterAttributesFunc;
2339 
2340 	DEBUG(2, "HBA_GetAdapterAttributes", 0, 0, 0);
2341 
2342 	CHECKLIBRARY();
2343 
2344 	if (lib_infop->version == SMHBA) {
2345 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2346 	}
2347 
2348 	GetAdapterAttributesFunc =
2349 	    lib_infop->ftable.functionTable.GetAdapterAttributesHandler;
2350 	if (GetAdapterAttributesFunc != NULL) {
2351 	status = ((GetAdapterAttributesFunc)(vendorHandle, hbaattributes));
2352 	} else {
2353 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2354 	}
2355 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2356 }
2357 
2358 HBA_STATUS
2359 HBA_GetAdapterPortAttributes(
2360     HBA_HANDLE		handle,
2361     HBA_UINT32		portindex,
2362     HBA_PORTATTRIBUTES	*portattributes)
2363 {
2364 	HBA_STATUS		status;
2365 	HBA_LIBRARY_INFO	*lib_infop;
2366 	HBA_HANDLE		vendorHandle;
2367 	HBAGetAdapterPortAttributesFunc
2368 	    GetAdapterPortAttributesFunc;
2369 
2370 	DEBUG(2, "HBA_GetAdapterPortAttributes", 0, 0, 0);
2371 
2372 	CHECKLIBRARY();
2373 	if (lib_infop->version == SMHBA) {
2374 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2375 	}
2376 
2377 	GetAdapterPortAttributesFunc =
2378 	    lib_infop->ftable.functionTable.GetAdapterPortAttributesHandler;
2379 	if (GetAdapterPortAttributesFunc != NULL) {
2380 	status = ((GetAdapterPortAttributesFunc)
2381 	    (vendorHandle, portindex, portattributes));
2382 	} else {
2383 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2384 	}
2385 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2386 }
2387 
2388 HBA_STATUS
2389 HBA_GetPortStatistics(
2390     HBA_HANDLE		handle,
2391     HBA_UINT32		portindex,
2392     HBA_PORTSTATISTICS	*portstatistics)
2393 {
2394 	HBA_STATUS		status;
2395 	HBA_LIBRARY_INFO	*lib_infop;
2396 	HBA_HANDLE		vendorHandle;
2397 	HBAGetPortStatisticsFunc
2398 	    GetPortStatisticsFunc;
2399 
2400 	DEBUG(2, "HBA_GetPortStatistics", 0, 0, 0);
2401 
2402 	CHECKLIBRARY();
2403 	if (lib_infop->version == SMHBA) {
2404 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2405 	}
2406 
2407 	GetPortStatisticsFunc =
2408 	    lib_infop->ftable.functionTable.GetPortStatisticsHandler;
2409 	if (GetPortStatisticsFunc != NULL) {
2410 	status = ((GetPortStatisticsFunc)
2411 	    (vendorHandle, portindex, portstatistics));
2412 	} else {
2413 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2414 	}
2415 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2416 }
2417 
2418 HBA_STATUS
2419 HBA_GetDiscoveredPortAttributes(
2420     HBA_HANDLE		handle,
2421     HBA_UINT32		portindex,
2422     HBA_UINT32		discoveredportindex,
2423     HBA_PORTATTRIBUTES	*portattributes)
2424 {
2425 	HBA_STATUS		status;
2426 	HBA_LIBRARY_INFO	*lib_infop;
2427 	HBA_HANDLE		vendorHandle;
2428 	HBAGetDiscoveredPortAttributesFunc
2429 	    GetDiscoveredPortAttributesFunc;
2430 
2431 	DEBUG(2, "HBA_GetDiscoveredPortAttributes", 0, 0, 0);
2432 
2433 	CHECKLIBRARY();
2434 	if (lib_infop->version == SMHBA) {
2435 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2436 	}
2437 
2438 	GetDiscoveredPortAttributesFunc =
2439 	    lib_infop->ftable.functionTable.GetDiscoveredPortAttributesHandler;
2440 	if (GetDiscoveredPortAttributesFunc != NULL)  {
2441 	status = ((GetDiscoveredPortAttributesFunc)
2442 	    (vendorHandle, portindex, discoveredportindex,
2443 	    portattributes));
2444 	} else {
2445 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2446 	}
2447 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2448 }
2449 
2450 HBA_STATUS
2451 HBA_GetPortAttributesByWWN(
2452     HBA_HANDLE		handle,
2453     HBA_WWN		PortWWN,
2454     HBA_PORTATTRIBUTES	*portattributes)
2455 {
2456 	HBA_STATUS		status;
2457 	HBA_LIBRARY_INFO	*lib_infop;
2458 	HBA_HANDLE		vendorHandle;
2459 	HBAGetPortAttributesByWWNFunc
2460 	    GetPortAttributesByWWNFunc;
2461 
2462 	DEBUG(2, "HBA_GetPortAttributesByWWN: %s", WWN2STR1(&PortWWN), 0, 0);
2463 
2464 	CHECKLIBRARY();
2465 	if (lib_infop->version == SMHBA) {
2466 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2467 	}
2468 
2469 	GetPortAttributesByWWNFunc =
2470 	    lib_infop->ftable.functionTable.GetPortAttributesByWWNHandler;
2471 	if (GetPortAttributesByWWNFunc != NULL) {
2472 	status = ((GetPortAttributesByWWNFunc)
2473 	    (vendorHandle, PortWWN, portattributes));
2474 	} else {
2475 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2476 	}
2477 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2478 }
2479 
2480 HBA_STATUS
2481 HBA_SendCTPassThru(
2482     HBA_HANDLE		handle,
2483     void		*pReqBuffer,
2484     HBA_UINT32		ReqBufferSize,
2485     void		*pRspBuffer,
2486     HBA_UINT32		RspBufferSize)
2487 {
2488 	HBA_STATUS		status;
2489 	HBA_LIBRARY_INFO	*lib_infop;
2490 	HBA_HANDLE		vendorHandle;
2491 	HBASendCTPassThruFunc
2492 	    SendCTPassThruFunc;
2493 
2494 	DEBUG(2, "HBA_SendCTPassThru", 0, 0, 0);
2495 
2496 	CHECKLIBRARY();
2497 	if (lib_infop->version == SMHBA) {
2498 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2499 	}
2500 
2501 	SendCTPassThruFunc =
2502 	    lib_infop->ftable.functionTable.SendCTPassThruHandler;
2503 	if (SendCTPassThruFunc != NULL) {
2504 	status = (SendCTPassThruFunc)
2505 	    (vendorHandle,
2506 	    pReqBuffer, ReqBufferSize,
2507 	    pRspBuffer, RspBufferSize);
2508 	} else {
2509 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2510 	}
2511 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2512 }
2513 
2514 HBA_STATUS
2515 HBA_SendCTPassThruV2(
2516     HBA_HANDLE		handle,
2517     HBA_WWN		hbaPortWWN,
2518     void		*pReqBuffer,
2519     HBA_UINT32		ReqBufferSize,
2520     void		*pRspBuffer,
2521     HBA_UINT32		*pRspBufferSize)
2522 {
2523 	HBA_STATUS		status;
2524 	HBA_LIBRARY_INFO	*lib_infop;
2525 	HBA_HANDLE		vendorHandle;
2526 	HBASendCTPassThruV2Func
2527 	    registeredfunc;
2528 
2529 	DEBUG(2, "HBA_SendCTPassThruV2m hbaPortWWN: %s",
2530 	    WWN2STR1(&hbaPortWWN), 0, 0);
2531 
2532 	CHECKLIBRARYANDVERSION(HBAAPIV2);
2533 	registeredfunc = FUNCCOMMON(lib_infop, SendCTPassThruV2Handler);
2534 	if (registeredfunc != NULL) {
2535 	status = (registeredfunc)
2536 	    (vendorHandle, hbaPortWWN,
2537 	    pReqBuffer, ReqBufferSize,
2538 	    pRspBuffer, pRspBufferSize);
2539 	} else {
2540 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2541 	}
2542 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2543 }
2544 
2545 HBA_STATUS
2546 HBA_GetEventBuffer(
2547     HBA_HANDLE		handle,
2548     PHBA_EVENTINFO	EventBuffer,
2549     HBA_UINT32		*EventBufferCount)
2550 {
2551 	HBA_STATUS		status;
2552 	HBA_LIBRARY_INFO	*lib_infop;
2553 	HBA_HANDLE		vendorHandle;
2554 	HBAGetEventBufferFunc
2555 	    GetEventBufferFunc;
2556 
2557 	DEBUG(2, "HBA_GetEventBuffer", 0, 0, 0);
2558 
2559 	CHECKLIBRARY();
2560 	if (lib_infop->version == SMHBA) {
2561 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2562 	}
2563 
2564 	GetEventBufferFunc =
2565 	    lib_infop->ftable.functionTable.GetEventBufferHandler;
2566 	if (GetEventBufferFunc != NULL) {
2567 	status = (GetEventBufferFunc)
2568 	    (vendorHandle, EventBuffer, EventBufferCount);
2569 	} else {
2570 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2571 	}
2572 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2573 }
2574 
2575 HBA_STATUS
2576 HBA_SetRNIDMgmtInfo(HBA_HANDLE handle, HBA_MGMTINFO Info) {
2577     HBA_STATUS		status;
2578     HBA_LIBRARY_INFO	*lib_infop;
2579     HBA_HANDLE		vendorHandle;
2580     HBASetRNIDMgmtInfoFunc
2581 			SetRNIDMgmtInfoFunc;
2582 
2583     DEBUG(2, "HBA_SetRNIDMgmtInfo", 0, 0, 0);
2584 
2585     CHECKLIBRARY();
2586     SetRNIDMgmtInfoFunc = FUNCCOMMON(lib_infop, SetRNIDMgmtInfoHandler);
2587     if (SetRNIDMgmtInfoFunc != NULL) {
2588 	status = (SetRNIDMgmtInfoFunc)(vendorHandle, Info);
2589 	} else {
2590 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2591 	}
2592     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2593 }
2594 
2595 HBA_STATUS
2596 HBA_GetRNIDMgmtInfo(HBA_HANDLE handle, HBA_MGMTINFO *pInfo) {
2597     HBA_STATUS		status;
2598     HBA_LIBRARY_INFO	*lib_infop;
2599     HBA_HANDLE		vendorHandle;
2600     HBAGetRNIDMgmtInfoFunc
2601 	    GetRNIDMgmtInfoFunc;
2602 
2603     DEBUG(2, "HBA_GetRNIDMgmtInfo", 0, 0, 0);
2604 
2605     CHECKLIBRARY();
2606     GetRNIDMgmtInfoFunc = FUNCCOMMON(lib_infop, GetRNIDMgmtInfoHandler);
2607     if (GetRNIDMgmtInfoFunc != NULL) {
2608 	status = (GetRNIDMgmtInfoFunc)(vendorHandle, pInfo);
2609 	} else {
2610 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2611 	}
2612     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2613 }
2614 
2615 HBA_STATUS
2616 HBA_SendRNID(
2617     HBA_HANDLE		handle,
2618     HBA_WWN		wwn,
2619     HBA_WWNTYPE		wwntype,
2620     void		*pRspBuffer,
2621     HBA_UINT32		*pRspBufferSize)
2622 {
2623 	HBA_STATUS		status;
2624 	HBA_LIBRARY_INFO	*lib_infop;
2625 	HBA_HANDLE		vendorHandle;
2626 	HBASendRNIDFunc	SendRNIDFunc;
2627 
2628 	DEBUG(2, "HBA_SendRNID for wwn: %s", WWN2STR1(&wwn), 0, 0);
2629 
2630 	CHECKLIBRARY();
2631 	if (lib_infop->version == SMHBA) {
2632 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2633 	}
2634 
2635 	SendRNIDFunc = lib_infop->ftable.functionTable.SendRNIDHandler;
2636 	if (SendRNIDFunc != NULL) {
2637 	status = ((SendRNIDFunc)(vendorHandle, wwn, wwntype,
2638 	    pRspBuffer, pRspBufferSize));
2639 	} else {
2640 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2641 	}
2642 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2643 }
2644 
2645 HBA_STATUS
2646 HBA_SendRNIDV2(
2647     HBA_HANDLE		handle,
2648     HBA_WWN		hbaPortWWN,
2649     HBA_WWN		destWWN,
2650     HBA_UINT32		destFCID,
2651     HBA_UINT32		NodeIdDataFormat,
2652     void		*pRspBuffer,
2653     HBA_UINT32		*pRspBufferSize)
2654 {
2655 	HBA_STATUS		status;
2656 	HBA_LIBRARY_INFO	*lib_infop;
2657 	HBA_HANDLE		vendorHandle;
2658 	HBASendRNIDV2Func	registeredfunc;
2659 
2660 	DEBUG(2, "HBA_SendRNIDV2, hbaPortWWN: %s", WWN2STR1(&hbaPortWWN), 0, 0);
2661 
2662 	CHECKLIBRARY();
2663 	registeredfunc = FUNCCOMMON(lib_infop, SendRNIDV2Handler);
2664 	if (registeredfunc != NULL) {
2665 	status = (registeredfunc)
2666 	    (vendorHandle, hbaPortWWN, destWWN, destFCID, NodeIdDataFormat,
2667 	    pRspBuffer, pRspBufferSize);
2668 	} else {
2669 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2670 	}
2671 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2672 }
2673 
2674 void
2675 HBA_RefreshInformation(HBA_HANDLE handle) {
2676     HBA_STATUS		status;
2677     HBA_LIBRARY_INFO	*lib_infop;
2678     HBA_HANDLE		vendorHandle;
2679     HBARefreshInformationFunc
2680 	    RefreshInformationFunc;
2681 
2682 	DEBUG(2, "HBA_RefreshInformation", 0, 0, 0);
2683 
2684 	status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);
2685 	if (status == HBA_STATUS_OK) {
2686 	RefreshInformationFunc =
2687 	    FUNCCOMMON(lib_infop, RefreshInformationHandler);
2688 	if (RefreshInformationFunc != NULL) {
2689 	    ((RefreshInformationFunc)(vendorHandle));
2690 	}
2691 	RELEASE_MUTEX(&_hbaapi_LL_mutex);
2692 	}
2693 }
2694 
2695 void
2696 HBA_ResetStatistics(HBA_HANDLE handle, HBA_UINT32 portindex) {
2697     HBA_STATUS		status;
2698     HBA_LIBRARY_INFO	*lib_infop;
2699     HBA_HANDLE		vendorHandle;
2700     HBAResetStatisticsFunc
2701 			ResetStatisticsFunc;
2702 
2703     DEBUG(2, "HBA_ResetStatistics", 0, 0, 0);
2704 
2705     status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);
2706     if (status == HBA_STATUS_OK) {
2707 	if (lib_infop->version == SMHBA) {
2708 		RELEASE_MUTEX(&_hbaapi_LL_mutex);
2709 	}
2710 
2711 	ResetStatisticsFunc =
2712 	    lib_infop->ftable.functionTable.ResetStatisticsHandler;
2713 	if (ResetStatisticsFunc != NULL) {
2714 	    ((ResetStatisticsFunc)(vendorHandle, portindex));
2715 	}
2716 	RELEASE_MUTEX(&_hbaapi_LL_mutex);
2717 	}
2718 }
2719 
2720 HBA_STATUS
2721 HBA_GetFcpTargetMapping(HBA_HANDLE handle, PHBA_FCPTARGETMAPPING mapping) {
2722     HBA_STATUS		status;
2723     HBA_LIBRARY_INFO	*lib_infop;
2724     HBA_HANDLE		vendorHandle;
2725     HBAGetFcpTargetMappingFunc GetFcpTargetMappingFunc;
2726 
2727     DEBUG(2, "HBA_GetFcpTargetMapping", 0, 0, 0);
2728 
2729     CHECKLIBRARY();
2730     if (lib_infop->version == SMHBA) {
2731 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2732 	}
2733 
2734     GetFcpTargetMappingFunc =
2735 	lib_infop->ftable.functionTable.GetFcpTargetMappingHandler;
2736     if (GetFcpTargetMappingFunc != NULL) {
2737 	status = ((GetFcpTargetMappingFunc)(vendorHandle, mapping));
2738 	} else {
2739 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2740 	}
2741     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2742 }
2743 
2744 HBA_STATUS
2745 HBA_GetFcpTargetMappingV2(
2746     HBA_HANDLE		handle,
2747     HBA_WWN		hbaPortWWN,
2748     HBA_FCPTARGETMAPPINGV2 *pmapping)
2749 {
2750 	HBA_STATUS		status;
2751 	HBA_LIBRARY_INFO	*lib_infop;
2752 	HBA_HANDLE		vendorHandle;
2753 	HBAGetFcpTargetMappingV2Func
2754 	    registeredfunc;
2755 
2756 	DEBUG(2, "HBA_GetFcpTargetMapping", 0, 0, 0);
2757 
2758 	CHECKLIBRARYANDVERSION(HBAAPIV2);
2759 
2760 	registeredfunc =
2761 	    lib_infop->ftable.functionTable.GetFcpTargetMappingV2Handler;
2762 	if (registeredfunc != NULL) {
2763 	status = ((registeredfunc)(vendorHandle, hbaPortWWN, pmapping));
2764 	} else {
2765 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2766 	}
2767 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2768 }
2769 
2770 HBA_STATUS
2771 HBA_GetFcpPersistentBinding(HBA_HANDLE handle, PHBA_FCPBINDING binding) {
2772     HBA_STATUS		status;
2773     HBA_LIBRARY_INFO	*lib_infop;
2774     HBA_HANDLE		vendorHandle;
2775     HBAGetFcpPersistentBindingFunc
2776 	    GetFcpPersistentBindingFunc;
2777 
2778 	DEBUG(2, "HBA_GetFcpPersistentBinding", 0, 0, 0);
2779 
2780 	CHECKLIBRARY();
2781 	if (lib_infop->version == SMHBA) {
2782 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2783 	}
2784 
2785 	GetFcpPersistentBindingFunc =
2786 	    lib_infop->ftable.functionTable.GetFcpPersistentBindingHandler;
2787 	if (GetFcpPersistentBindingFunc != NULL) {
2788 	status = ((GetFcpPersistentBindingFunc)(vendorHandle, binding));
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_ScsiInquiryV2(
2797     HBA_HANDLE	handle,
2798     HBA_WWN	hbaPortWWN,
2799     HBA_WWN	discoveredPortWWN,
2800     HBA_UINT64	fcLUN,
2801     HBA_UINT8	CDB_Byte1,
2802     HBA_UINT8	CDB_Byte2,
2803     void	*pRspBuffer,
2804     HBA_UINT32	*pRspBufferSize,
2805     HBA_UINT8	*pScsiStatus,
2806     void	*pSenseBuffer,
2807     HBA_UINT32	*pSenseBufferSize)
2808 {
2809 	HBA_STATUS		status;
2810 	HBA_LIBRARY_INFO	*lib_infop;
2811 	HBA_HANDLE		vendorHandle;
2812 	HBAScsiInquiryV2Func ScsiInquiryV2Func;
2813 
2814 	DEBUG(2, "HBA_ScsiInquiryV2 to discoveredPortWWN: %s",
2815 	    WWN2STR1(&discoveredPortWWN), 0, 0);
2816 
2817 	CHECKLIBRARYANDVERSION(HBAAPIV2);
2818 
2819 	ScsiInquiryV2Func =
2820 	    lib_infop->ftable.functionTable.ScsiInquiryV2Handler;
2821 	if (ScsiInquiryV2Func != NULL) {
2822 	status = ((ScsiInquiryV2Func)(
2823 	    vendorHandle, hbaPortWWN, discoveredPortWWN, fcLUN, CDB_Byte1,
2824 	    CDB_Byte2, pRspBuffer, pRspBufferSize, pScsiStatus,
2825 	    pSenseBuffer, pSenseBufferSize));
2826 	} else {
2827 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2828 	}
2829 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2830 }
2831 
2832 HBA_STATUS
2833 HBA_SendScsiInquiry(
2834     HBA_HANDLE	handle,
2835     HBA_WWN	PortWWN,
2836     HBA_UINT64	fcLUN,
2837     HBA_UINT8	EVPD,
2838     HBA_UINT32	PageCode,
2839     void	*pRspBuffer,
2840     HBA_UINT32	RspBufferSize,
2841     void	*pSenseBuffer,
2842     HBA_UINT32	SenseBufferSize)
2843 {
2844 	HBA_STATUS		status;
2845 	HBA_LIBRARY_INFO	*lib_infop;
2846 	HBA_HANDLE		vendorHandle;
2847 	HBASendScsiInquiryFunc SendScsiInquiryFunc;
2848 
2849 	DEBUG(2, "HBA_SendScsiInquiry to PortWWN: %s",
2850 	    WWN2STR1(&PortWWN), 0, 0);
2851 
2852 	CHECKLIBRARY();
2853 	if (lib_infop->version == SMHBA) {
2854 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2855 	}
2856 
2857 	SendScsiInquiryFunc =
2858 	    lib_infop->ftable.functionTable.ScsiInquiryHandler;
2859 	if (SendScsiInquiryFunc != NULL) {
2860 	status = ((SendScsiInquiryFunc)(
2861 	    vendorHandle, PortWWN, fcLUN, EVPD, PageCode, pRspBuffer,
2862 	    RspBufferSize, pSenseBuffer, SenseBufferSize));
2863 	} else {
2864 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2865 	}
2866 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2867 }
2868 
2869 HBA_STATUS
2870 HBA_ScsiReportLUNsV2(
2871     HBA_HANDLE		handle,
2872     HBA_WWN		hbaPortWWN,
2873     HBA_WWN		discoveredPortWWN,
2874     void		*pRespBuffer,
2875     HBA_UINT32		*pRespBufferSize,
2876     HBA_UINT8		*pScsiStatus,
2877     void		*pSenseBuffer,
2878     HBA_UINT32		*pSenseBufferSize)
2879 {
2880 	HBA_STATUS		status;
2881 	HBA_LIBRARY_INFO	*lib_infop;
2882 	HBA_HANDLE		vendorHandle;
2883 	HBAScsiReportLUNsV2Func ScsiReportLUNsV2Func;
2884 
2885 	DEBUG(2, "HBA_ScsiReportLUNsV2 to discoveredPortWWN: %s",
2886 	    WWN2STR1(&discoveredPortWWN), 0, 0);
2887 
2888 	CHECKLIBRARYANDVERSION(HBAAPIV2);
2889 
2890 	ScsiReportLUNsV2Func =
2891 	    lib_infop->ftable.functionTable.ScsiReportLUNsV2Handler;
2892 	if (ScsiReportLUNsV2Func != NULL) {
2893 	status = ((ScsiReportLUNsV2Func)(
2894 	    vendorHandle, hbaPortWWN, discoveredPortWWN,
2895 	    pRespBuffer, pRespBufferSize,
2896 	    pScsiStatus,
2897 	    pSenseBuffer, pSenseBufferSize));
2898 	} else {
2899 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2900 	}
2901 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2902 }
2903 
2904 HBA_STATUS
2905 HBA_SendReportLUNs(
2906     HBA_HANDLE handle,
2907     HBA_WWN portWWN,
2908     void *pRspBuffer,
2909     HBA_UINT32 RspBufferSize,
2910     void *pSenseBuffer,
2911     HBA_UINT32 SenseBufferSize)
2912 {
2913 	HBA_STATUS		status;
2914 	HBA_LIBRARY_INFO	*lib_infop;
2915 	HBA_HANDLE		vendorHandle;
2916 	HBASendReportLUNsFunc SendReportLUNsFunc;
2917 
2918 	DEBUG(2, "HBA_SendReportLUNs to PortWWN: %s", WWN2STR1(&portWWN), 0, 0);
2919 
2920 	CHECKLIBRARY();
2921 	if (lib_infop->version == SMHBA) {
2922 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2923 	}
2924 
2925 	SendReportLUNsFunc = lib_infop->ftable.functionTable.ReportLUNsHandler;
2926 	if (SendReportLUNsFunc != NULL) {
2927 	status = ((SendReportLUNsFunc)(
2928 	    vendorHandle, portWWN, pRspBuffer,
2929 	    RspBufferSize, pSenseBuffer, SenseBufferSize));
2930 	} else {
2931 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2932 	}
2933 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2934 }
2935 
2936 HBA_STATUS
2937 HBA_ScsiReadCapacityV2(
2938     HBA_HANDLE		handle,
2939     HBA_WWN		hbaPortWWN,
2940     HBA_WWN		discoveredPortWWN,
2941     HBA_UINT64		fcLUN,
2942     void		*pRspBuffer,
2943     HBA_UINT32		*pRspBufferSize,
2944     HBA_UINT8		*pScsiStatus,
2945     void		*pSenseBuffer,
2946     HBA_UINT32		*SenseBufferSize)
2947 {
2948 	HBA_STATUS		status;
2949 	HBA_LIBRARY_INFO	*lib_infop;
2950 	HBA_HANDLE		vendorHandle;
2951 	HBAScsiReadCapacityV2Func ScsiReadCapacityV2Func;
2952 
2953 	DEBUG(2, "HBA_ScsiReadCapacityV2 to discoveredPortWWN: %s",
2954 	    WWN2STR1(&discoveredPortWWN), 0, 0);
2955 
2956 	CHECKLIBRARYANDVERSION(HBAAPIV2);
2957 
2958 	ScsiReadCapacityV2Func =
2959 	    lib_infop->ftable.functionTable.ScsiReadCapacityV2Handler;
2960 	if (ScsiReadCapacityV2Func != NULL) {
2961 	status = ((ScsiReadCapacityV2Func)(
2962 	    vendorHandle, hbaPortWWN, discoveredPortWWN, fcLUN,
2963 	    pRspBuffer, pRspBufferSize,
2964 	    pScsiStatus,
2965 	    pSenseBuffer, SenseBufferSize));
2966 	} else {
2967 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2968 	}
2969 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2970 }
2971 
2972 HBA_STATUS
2973 HBA_SendReadCapacity(
2974     HBA_HANDLE handle,
2975     HBA_WWN portWWN,
2976     HBA_UINT64 fcLUN,
2977     void *pRspBuffer,
2978     HBA_UINT32 RspBufferSize,
2979     void *pSenseBuffer,
2980     HBA_UINT32 SenseBufferSize)
2981 {
2982 	HBA_STATUS		status;
2983 	HBA_LIBRARY_INFO	*lib_infop;
2984 	HBA_HANDLE		vendorHandle;
2985 	HBASendReadCapacityFunc SendReadCapacityFunc;
2986 
2987 	DEBUG(2, "HBA_SendReadCapacity to portWWN: %s",
2988 	    WWN2STR1(&portWWN), 0, 0);
2989 
2990 	CHECKLIBRARY();
2991 	if (lib_infop->version == SMHBA) {
2992 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2993 	}
2994 
2995 	SendReadCapacityFunc =
2996 	    lib_infop->ftable.functionTable.ReadCapacityHandler;
2997 	if (SendReadCapacityFunc != NULL) {
2998 	status = ((SendReadCapacityFunc)
2999 	    (vendorHandle, portWWN, fcLUN, pRspBuffer,
3000 	    RspBufferSize, pSenseBuffer, SenseBufferSize));
3001 	} else {
3002 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3003 	}
3004 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3005 }
3006 
3007 HBA_STATUS
3008 HBA_SendRPL(
3009     HBA_HANDLE		handle,
3010     HBA_WWN		hbaPortWWN,
3011     HBA_WWN		agent_wwn,
3012     HBA_UINT32		agent_domain,
3013     HBA_UINT32		portindex,
3014     void		*pRspBuffer,
3015     HBA_UINT32		*pRspBufferSize)
3016 {
3017 	HBA_STATUS		status;
3018 	HBA_LIBRARY_INFO	*lib_infop;
3019 	HBA_HANDLE		vendorHandle;
3020 	HBASendRPLFunc registeredfunc;
3021 
3022 	DEBUG(2, "HBA_SendRPL to agent_wwn: %s:%d",
3023 	    WWN2STR1(&agent_wwn), agent_domain, 0);
3024 
3025 	CHECKLIBRARY();
3026 	registeredfunc = FUNCCOMMON(lib_infop, SendRPLHandler);
3027 	if (registeredfunc != NULL) {
3028 	status = (registeredfunc)(
3029 	    vendorHandle, hbaPortWWN, agent_wwn, agent_domain, portindex,
3030 	    pRspBuffer, pRspBufferSize);
3031 	} else {
3032 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3033 	}
3034 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3035 }
3036 
3037 HBA_STATUS
3038 HBA_SendRPS(
3039     HBA_HANDLE		handle,
3040     HBA_WWN		hbaPortWWN,
3041     HBA_WWN		agent_wwn,
3042     HBA_UINT32		agent_domain,
3043     HBA_WWN		object_wwn,
3044     HBA_UINT32		object_port_number,
3045     void		*pRspBuffer,
3046     HBA_UINT32		*pRspBufferSize)
3047 {
3048 	HBA_STATUS		status;
3049 	HBA_LIBRARY_INFO	*lib_infop;
3050 	HBA_HANDLE		vendorHandle;
3051 	HBASendRPSFunc registeredfunc;
3052 
3053 	DEBUG(2, "HBA_SendRPS  to agent_wwn: %s:%d",
3054 	    WWN2STR1(&agent_wwn), agent_domain, 0);
3055 
3056 	CHECKLIBRARY();
3057 	registeredfunc = FUNCCOMMON(lib_infop, SendRPSHandler);
3058 	if (registeredfunc != NULL) {
3059 	status = (registeredfunc)(
3060 	    vendorHandle, hbaPortWWN, agent_wwn, agent_domain,
3061 	    object_wwn, object_port_number,
3062 	    pRspBuffer, pRspBufferSize);
3063 	} else {
3064 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3065 	}
3066 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3067 }
3068 
3069 HBA_STATUS
3070 HBA_SendSRL(
3071     HBA_HANDLE		handle,
3072     HBA_WWN		hbaPortWWN,
3073     HBA_WWN		wwn,
3074     HBA_UINT32		domain,
3075     void		*pRspBuffer,
3076     HBA_UINT32		*pRspBufferSize)
3077 {
3078 	HBA_STATUS		status;
3079 	HBA_LIBRARY_INFO	*lib_infop;
3080 	HBA_HANDLE		vendorHandle;
3081 	HBASendSRLFunc registeredfunc;
3082 
3083 	DEBUG(2, "HBA_SendSRL to wwn:%s domain:%d", WWN2STR1(&wwn), domain, 0);
3084 
3085 	CHECKLIBRARY();
3086 	registeredfunc = FUNCCOMMON(lib_infop, SendSRLHandler);
3087 	if (registeredfunc != NULL) {
3088 	status = (registeredfunc)(
3089 	    vendorHandle, hbaPortWWN, wwn, domain,
3090 	    pRspBuffer, pRspBufferSize);
3091 	} else {
3092 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3093 	}
3094 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3095 }
3096 HBA_STATUS
3097 HBA_SendRLS(
3098     HBA_HANDLE		handle,
3099     HBA_WWN		hbaPortWWN,
3100     HBA_WWN		destWWN,
3101     void		*pRspBuffer,
3102     HBA_UINT32		*pRspBufferSize)
3103 {
3104 	HBA_STATUS		status;
3105 	HBA_LIBRARY_INFO	*lib_infop;
3106 	HBA_HANDLE		vendorHandle;
3107 	HBASendRLSFunc registeredfunc;
3108 
3109 	DEBUG(2, "HBA_SendRLS dest_wwn: %s",
3110 	    WWN2STR1(&destWWN), 0, 0);
3111 
3112 	CHECKLIBRARY();
3113 	registeredfunc = FUNCCOMMON(lib_infop, SendRLSHandler);
3114 	if (registeredfunc != NULL) {
3115 	status = (registeredfunc)(
3116 	    vendorHandle, hbaPortWWN, destWWN,
3117 	    pRspBuffer, pRspBufferSize);
3118 	} else {
3119 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3120 	}
3121 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3122 }
3123 
3124 HBA_STATUS
3125 HBA_SendLIRR(
3126     HBA_HANDLE		handle,
3127     HBA_WWN		sourceWWN,
3128     HBA_WWN		destWWN,
3129     HBA_UINT8		function,
3130     HBA_UINT8		type,
3131     void		*pRspBuffer,
3132     HBA_UINT32		*pRspBufferSize)
3133 {
3134 	HBA_STATUS		status;
3135 	HBA_LIBRARY_INFO	*lib_infop;
3136 	HBA_HANDLE		vendorHandle;
3137 	HBASendLIRRFunc registeredfunc;
3138 
3139 	DEBUG(2, "HBA_SendLIRR destWWN:%s", WWN2STR1(&destWWN), 0, 0);
3140 
3141 	CHECKLIBRARY();
3142 	registeredfunc = FUNCCOMMON(lib_infop, SendLIRRHandler);
3143 	if (registeredfunc != NULL) {
3144 	status = (registeredfunc)(
3145 	    vendorHandle, sourceWWN, destWWN, function, type,
3146 	    pRspBuffer, pRspBufferSize);
3147 	} else {
3148 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3149 	}
3150 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3151 }
3152 
3153 HBA_STATUS
3154 HBA_GetBindingCapability(
3155     HBA_HANDLE		handle,
3156     HBA_WWN		hbaPortWWN,
3157     HBA_BIND_CAPABILITY *pcapability)
3158 {
3159 	HBA_STATUS		status;
3160 	HBA_LIBRARY_INFO	*lib_infop;
3161 	HBA_HANDLE		vendorHandle;
3162 	HBAGetBindingCapabilityFunc
3163 	    registeredfunc;
3164 
3165 	DEBUG(2, "HBA_GetBindingCapability", 0, 0, 0);
3166 
3167 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3168 
3169 	registeredfunc =
3170 	    lib_infop->ftable.functionTable.GetBindingCapabilityHandler;
3171 	if (registeredfunc != NULL) {
3172 	status = (registeredfunc)(vendorHandle, hbaPortWWN, pcapability);
3173 	} else {
3174 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3175 	}
3176 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3177 }
3178 
3179 HBA_STATUS
3180 HBA_GetBindingSupport(
3181     HBA_HANDLE		handle,
3182     HBA_WWN		hbaPortWWN,
3183     HBA_BIND_CAPABILITY *pcapability)
3184 {
3185 	HBA_STATUS		status;
3186 	HBA_LIBRARY_INFO	*lib_infop;
3187 	HBA_HANDLE		vendorHandle;
3188 	HBAGetBindingSupportFunc
3189 	    registeredfunc;
3190 
3191 	DEBUG(2, "HBA_GetBindingSupport", 0, 0, 0);
3192 
3193 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3194 
3195 	registeredfunc =
3196 	    lib_infop->ftable.functionTable.GetBindingSupportHandler;
3197 	if (registeredfunc != NULL) {
3198 	status = (registeredfunc)(vendorHandle, hbaPortWWN, pcapability);
3199 	} else {
3200 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3201 	}
3202 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3203 }
3204 
3205 HBA_STATUS
3206 HBA_SetBindingSupport(
3207     HBA_HANDLE		handle,
3208     HBA_WWN		hbaPortWWN,
3209     HBA_BIND_CAPABILITY capability)
3210 {
3211 	HBA_STATUS		status;
3212 	HBA_LIBRARY_INFO	*lib_infop;
3213 	HBA_HANDLE		vendorHandle;
3214 	HBASetBindingSupportFunc
3215 	    registeredfunc;
3216 
3217 	DEBUG(2, "HBA_SetBindingSupport", 0, 0, 0);
3218 
3219 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3220 
3221 	registeredfunc =
3222 	    lib_infop->ftable.functionTable.SetBindingSupportHandler;
3223 	if (registeredfunc != NULL) {
3224 	status = (registeredfunc)(vendorHandle, hbaPortWWN, capability);
3225 	} else {
3226 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3227 	}
3228 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3229 }
3230 
3231 HBA_STATUS
3232 HBA_SetPersistentBindingV2(
3233     HBA_HANDLE		handle,
3234     HBA_WWN		hbaPortWWN,
3235     const HBA_FCPBINDING2 *pbinding)
3236 {
3237 	HBA_STATUS		status;
3238 	HBA_LIBRARY_INFO	*lib_infop;
3239 	HBA_HANDLE		vendorHandle;
3240 	HBASetPersistentBindingV2Func
3241 	    registeredfunc;
3242 
3243 	DEBUG(2, "HBA_SetPersistentBindingV2 port: %s",
3244 	    WWN2STR1(&hbaPortWWN), 0, 0);
3245 
3246 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3247 
3248 	registeredfunc =
3249 	    lib_infop->ftable.functionTable.SetPersistentBindingV2Handler;
3250 	if (registeredfunc != NULL) {
3251 	status = (registeredfunc)(vendorHandle, hbaPortWWN, pbinding);
3252 	} else {
3253 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3254 	}
3255 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3256 }
3257 
3258 HBA_STATUS
3259 HBA_GetPersistentBindingV2(
3260     HBA_HANDLE		handle,
3261     HBA_WWN		hbaPortWWN,
3262     HBA_FCPBINDING2	*pbinding)
3263 {
3264 	HBA_STATUS		status;
3265 	HBA_LIBRARY_INFO	*lib_infop;
3266 	HBA_HANDLE		vendorHandle;
3267 	HBAGetPersistentBindingV2Func
3268 	    registeredfunc;
3269 
3270 	DEBUG(2, "HBA_GetPersistentBindingV2 port: %s",
3271 	    WWN2STR1(&hbaPortWWN), 0, 0);
3272 
3273 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3274 
3275 	registeredfunc =
3276 	    lib_infop->ftable.functionTable.GetPersistentBindingV2Handler;
3277 	if (registeredfunc != NULL) {
3278 	status = (registeredfunc)(vendorHandle, hbaPortWWN, pbinding);
3279 	} else {
3280 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3281 	}
3282 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3283 }
3284 
3285 HBA_STATUS
3286 HBA_RemovePersistentBinding(
3287     HBA_HANDLE		handle,
3288     HBA_WWN		hbaPortWWN,
3289     const HBA_FCPBINDING2
3290 			*pbinding)
3291 {
3292 	HBA_STATUS		status;
3293 	HBA_LIBRARY_INFO	*lib_infop;
3294 	HBA_HANDLE		vendorHandle;
3295 	HBARemovePersistentBindingFunc
3296 	    registeredfunc;
3297 
3298 	DEBUG(2, "HBA_RemovePersistentBinding", 0, 0, 0);
3299 
3300 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3301 
3302 	registeredfunc =
3303 	    lib_infop->ftable.functionTable.RemovePersistentBindingHandler;
3304 	if (registeredfunc != NULL) {
3305 	status = (registeredfunc)(vendorHandle, hbaPortWWN, pbinding);
3306 	} else {
3307 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3308 	}
3309 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3310 }
3311 
3312 HBA_STATUS
3313 HBA_RemoveAllPersistentBindings(
3314     HBA_HANDLE		handle,
3315     HBA_WWN		hbaPortWWN)
3316 {
3317 	HBA_STATUS		status;
3318 	HBA_LIBRARY_INFO	*lib_infop;
3319 	HBA_HANDLE		vendorHandle;
3320 	HBARemoveAllPersistentBindingsFunc
3321 	    registeredfunc;
3322 
3323 	DEBUG(2, "HBA_RemoveAllPersistentBindings", 0, 0, 0);
3324 
3325 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3326 
3327 	registeredfunc =
3328 	    lib_infop->ftable.functionTable.RemoveAllPersistentBindingsHandler;
3329 	if (registeredfunc != NULL) {
3330 	status = (registeredfunc)(vendorHandle, hbaPortWWN);
3331 	} else {
3332 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3333 	}
3334 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3335 }
3336 
3337 HBA_STATUS
3338 HBA_GetFC4Statistics(
3339     HBA_HANDLE		handle,
3340     HBA_WWN		portWWN,
3341     HBA_UINT8		FC4type,
3342     HBA_FC4STATISTICS	*pstatistics)
3343 {
3344 	HBA_STATUS		status;
3345 	HBA_LIBRARY_INFO	*lib_infop;
3346 	HBA_HANDLE		vendorHandle;
3347 	HBAGetFC4StatisticsFunc
3348 	    registeredfunc;
3349 
3350 	DEBUG(2, "HBA_GetFC4Statistics port: %s", WWN2STR1(&portWWN), 0, 0);
3351 
3352 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3353 
3354 	registeredfunc =
3355 	    lib_infop->ftable.functionTable.GetFC4StatisticsHandler;
3356 	if (registeredfunc != NULL) {
3357 	status = (registeredfunc)
3358 	    (vendorHandle, portWWN, FC4type, pstatistics);
3359 	} else {
3360 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3361 	}
3362 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3363 }
3364 
3365 HBA_STATUS
3366 HBA_GetFCPStatistics(
3367     HBA_HANDLE		handle,
3368     const HBA_SCSIID	*lunit,
3369     HBA_FC4STATISTICS	*pstatistics)
3370 {
3371 	HBA_STATUS		status;
3372 	HBA_LIBRARY_INFO	*lib_infop;
3373 	HBA_HANDLE		vendorHandle;
3374 	HBAGetFCPStatisticsFunc
3375 	    registeredfunc;
3376 
3377 	DEBUG(2, "HBA_GetFCPStatistics", 0, 0, 0);
3378 
3379 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3380 
3381 	registeredfunc =
3382 	    lib_infop->ftable.functionTable.GetFCPStatisticsHandler;
3383 	if (registeredfunc != NULL) {
3384 	status = (registeredfunc)(vendorHandle, lunit, pstatistics);
3385 	} else {
3386 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3387 	}
3388 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3389 }
3390 
3391 HBA_UINT32
3392 HBA_GetVendorLibraryAttributes(
3393     HBA_UINT32 adapter_index,
3394     HBA_LIBRARYATTRIBUTES *attributes)
3395 {
3396 	HBA_ADAPTER_INFO	*adapt_infop;
3397 	HBAGetVendorLibraryAttributesFunc
3398 	    registeredfunc;
3399 	HBA_UINT32		ret = 0;
3400 
3401 	DEBUG(2, "HBA_GetVendorLibraryAttributes adapterindex:%d",
3402 	    adapter_index, 0, 0);
3403 	if (_hbaapi_librarylist == NULL) {
3404 	DEBUG(1, "HBAAPI not loaded yet.", 0, 0, 0);
3405 	return (0);
3406 	}
3407 
3408 	if (attributes == NULL) {
3409 		DEBUG(1,
3410 		    "HBA_GetVendorLibraryAttributes: NULL pointer attributes",
3411 		    0, 0, 0);
3412 		return (HBA_STATUS_ERROR_ARG);
3413 	}
3414 
3415 	(void) memset(attributes, 0, sizeof (HBA_LIBRARYATTRIBUTES));
3416 
3417 	GRAB_MUTEX(&_hbaapi_LL_mutex);
3418 	GRAB_MUTEX(&_hbaapi_AL_mutex);
3419 	for (adapt_infop = _hbaapi_adapterlist;
3420 	    adapt_infop != NULL;
3421 	    adapt_infop = adapt_infop->next) {
3422 
3423 	if (adapt_infop->index == adapter_index) {
3424 
3425 		if (adapt_infop->library->version == SMHBA) {
3426 		RELEASE_MUTEX(&_hbaapi_AL_mutex);
3427 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex,
3428 		    HBA_STATUS_ERROR_INCOMPATIBLE);
3429 		}
3430 
3431 		registeredfunc = adapt_infop->library->
3432 		    ftable.functionTable.GetVendorLibraryAttributesHandler;
3433 		if (registeredfunc != NULL) {
3434 		ret = (registeredfunc)(attributes);
3435 		} else {
3436 		/* Version 1 libary? */
3437 		HBAGetVersionFunc	GetVersionFunc;
3438 		GetVersionFunc = adapt_infop->library->
3439 		    ftable.functionTable.GetVersionHandler;
3440 		if (GetVersionFunc != NULL) {
3441 			ret = ((GetVersionFunc)());
3442 		}
3443 #ifdef NOTDEF
3444 		else {
3445 		    /* This should not happen, dont think its going to */
3446 		}
3447 #endif
3448 		}
3449 		if (attributes->LibPath[0] == '\0') {
3450 		if (strlen(adapt_infop->library->LibraryPath) < 256) {
3451 			(void) strcpy(attributes->LibPath,
3452 			    adapt_infop->library->LibraryPath);
3453 		}
3454 		}
3455 		break;
3456 	}
3457 	}
3458 	RELEASE_MUTEX(&_hbaapi_AL_mutex);
3459 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, ret);
3460 }
3461 
3462 
3463 /*
3464  * This function returns SM-HBA version that the warpper library implemented.
3465  */
3466 HBA_UINT32
3467 SMHBA_GetVersion() {
3468     DEBUG(2, "SMHBA_GetVersion", 0, 0, 0);
3469     return (SMHBA_LIBVERSION);
3470 }
3471 
3472 /*
3473  * This function returns the attributes for the warpper library.
3474  */
3475 HBA_UINT32
3476 SMHBA_GetWrapperLibraryAttributes(
3477     SMHBA_LIBRARYATTRIBUTES *attributes)
3478 {
3479 
3480 	struct timeval tv;
3481 	struct tm tp;
3482 
3483 	DEBUG(2, "SMHBA_GetWrapperLibraryAttributes", 0, 0, 0);
3484 
3485 	if (attributes == NULL) {
3486 		DEBUG(1, "SMHBA_GetWrapperLibraryAttributes: "
3487 		    "NULL pointer attributes",
3488 		    0, 0, 0);
3489 		return (HBA_STATUS_ERROR_ARG);
3490 	}
3491 
3492 	(void) memset(attributes, 0, sizeof (SMHBA_LIBRARYATTRIBUTES));
3493 
3494 #if defined(SOLARIS)
3495 	if ((handle = dlopen("libSMHBAAPI.so", RTLD_NOW)) != NULL) {
3496 	if (dlinfo(handle, RTLD_DI_LINKMAP, &map) >= 0) {
3497 		for (mp = map; mp != NULL; mp = mp->l_next) {
3498 		if (strlen(map->l_name) < 256) {
3499 			(void) strcpy(attributes->LibPath, map->l_name);
3500 		}
3501 		}
3502 	}
3503 	}
3504 
3505 #endif
3506 
3507 #if defined(VENDOR)
3508 	(void) strcpy(attributes->VName, VENDOR);
3509 #else
3510 	attributes->VName[0] = '\0';
3511 #endif
3512 #if	defined(VERSION)
3513 	(void) strcpy(attributes->VVersion, VERSION);
3514 #else
3515 	attributes->VVersion[0] = '\0';
3516 #endif
3517 
3518 	if (gettimeofday(&tv, (void *)0) == 0) {
3519 	if (localtime_r(&tv.tv_sec, &tp) != NULL) {
3520 		attributes->build_date.tm_mday = tp.tm_mday;
3521 		attributes->build_date.tm_mon = tp.tm_mon;
3522 		attributes->build_date.tm_year = tp.tm_year;
3523 	} else {
3524 		(void) memset(&attributes->build_date, 0,
3525 		    sizeof (attributes->build_date));
3526 	}
3527 	(void) memset(&attributes->build_date, 0,
3528 	    sizeof (attributes->build_date));
3529 	}
3530 
3531 	return (1);
3532 }
3533 
3534 /*
3535  * This function returns the attributes for the warpper library.
3536  */
3537 HBA_UINT32
3538 SMHBA_GetVendorLibraryAttributes(
3539     HBA_UINT32 adapter_index,
3540     SMHBA_LIBRARYATTRIBUTES *attributes)
3541 {
3542 	HBA_ADAPTER_INFO	*adapt_infop;
3543 	SMHBAGetVendorLibraryAttributesFunc
3544 	    registeredfunc;
3545 	HBA_UINT32		ret = 0;
3546 
3547 	DEBUG(2, "SMHBA_GetVendorLibraryAttributes adapterindex:%d",
3548 	    adapter_index, 0, 0);
3549 	if (_hbaapi_librarylist == NULL) {
3550 	DEBUG(1, "SMHBAAPI not loaded yet.", 0, 0, 0);
3551 	return (0);
3552 	}
3553 
3554 	if (attributes == NULL) {
3555 		DEBUG(1, "SMHBA_GetVendorLibraryAttributes: "
3556 		    "NULL pointer attributes",
3557 		    0, 0, 0);
3558 		return (HBA_STATUS_ERROR_ARG);
3559 	}
3560 
3561 	(void) memset(attributes, 0, sizeof (SMHBA_LIBRARYATTRIBUTES));
3562 
3563 	GRAB_MUTEX(&_hbaapi_LL_mutex);
3564 	GRAB_MUTEX(&_hbaapi_AL_mutex);
3565 	for (adapt_infop = _hbaapi_adapterlist;
3566 	    adapt_infop != NULL;
3567 	    adapt_infop = adapt_infop->next) {
3568 
3569 	if (adapt_infop->index == adapter_index) {
3570 
3571 		if (adapt_infop->library->version != SMHBA) {
3572 		RELEASE_MUTEX(&_hbaapi_AL_mutex);
3573 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex,
3574 		    HBA_STATUS_ERROR_INCOMPATIBLE);
3575 		}
3576 
3577 		registeredfunc = adapt_infop->library->
3578 		    ftable.smhbafunctionTable.GetVendorLibraryAttributesHandler;
3579 		if (registeredfunc != NULL) {
3580 		ret = (registeredfunc)(attributes);
3581 #ifdef NOTDEF
3582 		} else {
3583 		/* This should not happen since the VSL is already loaded. */
3584 #endif
3585 		}
3586 		if (attributes->LibPath[0] == '\0') {
3587 		if (strlen(adapt_infop->library->LibraryPath) < 256) {
3588 			(void) strcpy(attributes->LibPath,
3589 			    adapt_infop->library->LibraryPath);
3590 		}
3591 		}
3592 		break;
3593 	}
3594 	}
3595 	RELEASE_MUTEX(&_hbaapi_AL_mutex);
3596 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, ret);
3597 }
3598 
3599 HBA_STATUS
3600 SMHBA_GetAdapterAttributes(
3601     HBA_HANDLE		handle,
3602     SMHBA_ADAPTERATTRIBUTES *hbaattributes)
3603 {
3604 	HBA_STATUS		status;
3605 	HBA_LIBRARY_INFO	*lib_infop;
3606 	HBA_HANDLE		vendorHandle;
3607 	SMHBAGetAdapterAttributesFunc GetAdapterAttributesFunc;
3608 
3609 	DEBUG(2, "SMHBA_GetAdapterAttributes", 0, 0, 0);
3610 
3611 	CHECKLIBRARYANDVERSION(SMHBA);
3612 
3613 	GetAdapterAttributesFunc =
3614 	    lib_infop->ftable.smhbafunctionTable.GetAdapterAttributesHandler;
3615 	if (GetAdapterAttributesFunc != NULL) {
3616 	status = ((GetAdapterAttributesFunc)(vendorHandle, hbaattributes));
3617 	} else {
3618 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3619 	}
3620 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3621 }
3622 
3623 HBA_STATUS
3624 SMHBA_GetNumberOfPorts(
3625     HBA_HANDLE		handle,
3626     HBA_UINT32		*numberofports)
3627 {
3628 	HBA_STATUS		status;
3629 	HBA_LIBRARY_INFO	*lib_infop;
3630 	HBA_HANDLE		vendorHandle;
3631 	SMHBAGetNumberOfPortsFunc GetNumberOfPortsFunc;
3632 
3633 	DEBUG(2, "SMHBA_GetAdapterAttributes", 0, 0, 0);
3634 
3635 	CHECKLIBRARYANDVERSION(SMHBA);
3636 
3637 	GetNumberOfPortsFunc =
3638 	    lib_infop->ftable.smhbafunctionTable.GetNumberOfPortsHandler;
3639 	if (GetNumberOfPortsFunc != NULL) {
3640 	status = ((GetNumberOfPortsFunc)(vendorHandle, numberofports));
3641 	} else {
3642 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3643 	}
3644 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3645 }
3646 
3647 HBA_STATUS
3648 SMHBA_GetPortType(
3649     HBA_HANDLE		handle,
3650     HBA_UINT32		portindex,
3651     HBA_PORTTYPE	*porttype)
3652 {
3653 	HBA_STATUS		status;
3654 	HBA_LIBRARY_INFO	*lib_infop;
3655 	HBA_HANDLE		vendorHandle;
3656 	SMHBAGetPortTypeFunc GetPortTypeFunc;
3657 
3658 	DEBUG(2, "SMHBA_GetAdapterAttributes", 0, 0, 0);
3659 
3660 	CHECKLIBRARYANDVERSION(SMHBA);
3661 
3662 	GetPortTypeFunc =
3663 	    lib_infop->ftable.smhbafunctionTable.GetPortTypeHandler;
3664 	if (GetPortTypeFunc != NULL) {
3665 	status = ((GetPortTypeFunc)(vendorHandle, portindex, porttype));
3666 	} else {
3667 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3668 	}
3669 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3670 }
3671 
3672 HBA_STATUS
3673 SMHBA_GetAdapterPortAttributes(
3674     HBA_HANDLE		handle,
3675     HBA_UINT32		portindex,
3676     SMHBA_PORTATTRIBUTES	*portattributes)
3677 {
3678 	HBA_STATUS		status;
3679 	HBA_LIBRARY_INFO	*lib_infop;
3680 	HBA_HANDLE		vendorHandle;
3681 	SMHBAGetAdapterPortAttributesFunc
3682 	    GetAdapterPortAttributesFunc;
3683 
3684 	DEBUG(2, "SMHBA_GetAdapterPortAttributes", 0, 0, 0);
3685 
3686 	CHECKLIBRARYANDVERSION(SMHBA);
3687 
3688 	GetAdapterPortAttributesFunc =
3689 	    lib_infop->ftable.smhbafunctionTable.\
3690 	    GetAdapterPortAttributesHandler;
3691 	if (GetAdapterPortAttributesFunc != NULL) {
3692 	status = ((GetAdapterPortAttributesFunc)
3693 	    (vendorHandle, portindex, portattributes));
3694 	} else {
3695 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3696 	}
3697 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3698 }
3699 
3700 HBA_STATUS
3701 SMHBA_GetDiscoveredPortAttributes(
3702     HBA_HANDLE		handle,
3703     HBA_UINT32		portindex,
3704     HBA_UINT32		discoveredportindex,
3705     SMHBA_PORTATTRIBUTES	*portattributes)
3706 {
3707 	HBA_STATUS		status;
3708 	HBA_LIBRARY_INFO	*lib_infop;
3709 	HBA_HANDLE		vendorHandle;
3710 	SMHBAGetDiscoveredPortAttributesFunc
3711 	    GetDiscoveredPortAttributesFunc;
3712 
3713 	DEBUG(2, "SMHBA_GetDiscoveredPortAttributes", 0, 0, 0);
3714 
3715 	CHECKLIBRARYANDVERSION(SMHBA);
3716 
3717 	GetDiscoveredPortAttributesFunc =
3718 	    lib_infop->ftable.smhbafunctionTable.\
3719 	    GetDiscoveredPortAttributesHandler;
3720 	if (GetDiscoveredPortAttributesFunc != NULL)  {
3721 	status = ((GetDiscoveredPortAttributesFunc)
3722 	    (vendorHandle, portindex, discoveredportindex,
3723 	    portattributes));
3724 	} else {
3725 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3726 	}
3727 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3728 }
3729 
3730 HBA_STATUS
3731 SMHBA_GetPortAttributesByWWN(
3732     HBA_HANDLE		handle,
3733     HBA_WWN		portWWN,
3734     HBA_WWN		domainPortWWN,
3735     SMHBA_PORTATTRIBUTES	*portattributes)
3736 {
3737 	HBA_STATUS		status;
3738 	HBA_LIBRARY_INFO	*lib_infop;
3739 	HBA_HANDLE		vendorHandle;
3740 	SMHBAGetPortAttributesByWWNFunc
3741 	    GetPortAttributesByWWNFunc;
3742 
3743 	DEBUG(2, "SMHBA_GetPortAttributesByWWN: %s", WWN2STR1(&portWWN), 0, 0);
3744 
3745 	CHECKLIBRARYANDVERSION(SMHBA);
3746 
3747 	GetPortAttributesByWWNFunc =
3748 	    lib_infop->ftable.smhbafunctionTable.GetPortAttributesByWWNHandler;
3749 	if (GetPortAttributesByWWNFunc != NULL) {
3750 	status = ((GetPortAttributesByWWNFunc)
3751 	    (vendorHandle, portWWN, domainPortWWN, portattributes));
3752 	} else {
3753 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3754 	}
3755 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3756 }
3757 
3758 HBA_STATUS
3759 SMHBA_GetFCPhyAttributes(
3760     HBA_HANDLE		handle,
3761     HBA_UINT32		portindex,
3762     HBA_UINT32		phyindex,
3763     SMHBA_FC_PHY	*phytype)
3764 {
3765 	HBA_STATUS		status;
3766 	HBA_LIBRARY_INFO	*lib_infop;
3767 	HBA_HANDLE		vendorHandle;
3768 	SMHBAGetFCPhyAttributesFunc GetFCPhyAttributesFunc;
3769 
3770 	DEBUG(2, "SMHBA_GetFCPhyAttributesByWWN", 0, 0, 0);
3771 
3772 	CHECKLIBRARYANDVERSION(SMHBA);
3773 
3774 	GetFCPhyAttributesFunc =
3775 	    lib_infop->ftable.smhbafunctionTable.GetFCPhyAttributesHandler;
3776 	if (GetFCPhyAttributesFunc != NULL) {
3777 	status = ((GetFCPhyAttributesFunc)
3778 	    (vendorHandle, portindex, phyindex, phytype));
3779 	} else {
3780 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3781 	}
3782 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3783 }
3784 
3785 HBA_STATUS
3786 SMHBA_GetSASPhyAttributes(
3787     HBA_HANDLE		handle,
3788     HBA_UINT32		portindex,
3789     HBA_UINT32		phyindex,
3790     SMHBA_SAS_PHY	*phytype)
3791 {
3792 	HBA_STATUS		status;
3793 	HBA_LIBRARY_INFO	*lib_infop;
3794 	HBA_HANDLE		vendorHandle;
3795 	SMHBAGetSASPhyAttributesFunc GetSASPhyAttributesFunc;
3796 
3797 	DEBUG(2, "SMHBA_GetFCPhyAttributesByWWN", 0, 0, 0);
3798 
3799 	CHECKLIBRARYANDVERSION(SMHBA);
3800 
3801 	GetSASPhyAttributesFunc =
3802 	    lib_infop->ftable.smhbafunctionTable.GetSASPhyAttributesHandler;
3803 	if (GetSASPhyAttributesFunc != NULL) {
3804 	status = ((GetSASPhyAttributesFunc)
3805 	    (vendorHandle, portindex, phyindex, phytype));
3806 	} else {
3807 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3808 	}
3809 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3810 }
3811 
3812 HBA_STATUS
3813 SMHBA_GetProtocolStatistics(
3814     HBA_HANDLE		handle,
3815     HBA_UINT32		portindex,
3816     HBA_UINT32		protocoltype,
3817     SMHBA_PROTOCOLSTATISTICS *pProtocolStatistics)
3818 {
3819 	HBA_STATUS		status;
3820 	HBA_LIBRARY_INFO	*lib_infop;
3821 	HBA_HANDLE		vendorHandle;
3822 	SMHBAGetProtocolStatisticsFunc
3823 	    GetProtocolStatisticsFunc;
3824 
3825 	DEBUG(2, "SMHBA_GetProtocolStatistics port index: %d protocol type: %d",
3826 	    portindex, protocoltype, 0);
3827 
3828 	CHECKLIBRARYANDVERSION(SMHBA);
3829 
3830 	GetProtocolStatisticsFunc =
3831 	    lib_infop->ftable.smhbafunctionTable.GetProtocolStatisticsHandler;
3832 	if (GetProtocolStatisticsFunc != NULL) {
3833 	status = (GetProtocolStatisticsFunc)
3834 	    (vendorHandle, portindex, protocoltype, pProtocolStatistics);
3835 	} else {
3836 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3837 	}
3838 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3839 }
3840 
3841 HBA_STATUS
3842 SMHBA_GetPhyStatistics(
3843     HBA_HANDLE		handle,
3844     HBA_UINT32		portindex,
3845     HBA_UINT32		phyindex,
3846     SMHBA_PHYSTATISTICS *pPhyStatistics)
3847 {
3848 	HBA_STATUS		status;
3849 	HBA_LIBRARY_INFO	*lib_infop;
3850 	HBA_HANDLE		vendorHandle;
3851 	SMHBAGetPhyStatisticsFunc
3852 	    GetPhyStatisticsFunc;
3853 
3854 	DEBUG(2, "SMHBA_GetPhyStatistics port index: %d phy idex: %d",
3855 	    portindex, phyindex, 0);
3856 
3857 	CHECKLIBRARYANDVERSION(SMHBA);
3858 
3859 	GetPhyStatisticsFunc =
3860 	    lib_infop->ftable.smhbafunctionTable.GetPhyStatisticsHandler;
3861 	if (GetPhyStatisticsFunc != NULL) {
3862 	status = (GetPhyStatisticsFunc)
3863 	    (vendorHandle, portindex, phyindex, pPhyStatistics);
3864 	} else {
3865 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3866 	}
3867 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3868 }
3869 
3870 HBA_STATUS
3871 SMHBA_GetBindingCapability(
3872     HBA_HANDLE		handle,
3873     HBA_WWN		hbaPortWWN,
3874     HBA_WWN		domainPortWWN,
3875     SMHBA_BIND_CAPABILITY *pFlags)
3876 {
3877 	HBA_STATUS		status;
3878 	HBA_LIBRARY_INFO	*lib_infop;
3879 	HBA_HANDLE		vendorHandle;
3880 	SMHBAGetBindingCapabilityFunc GetBindingCapabilityFunc;
3881 
3882 	DEBUG(2, "HBA_GetBindingCapability", 0, 0, 0);
3883 
3884 	CHECKLIBRARYANDVERSION(SMHBA);
3885 
3886 	GetBindingCapabilityFunc =
3887 	    lib_infop->ftable.smhbafunctionTable.GetBindingCapabilityHandler;
3888 	if (GetBindingCapabilityFunc != NULL) {
3889 	status = (GetBindingCapabilityFunc)(vendorHandle, hbaPortWWN,
3890 	    domainPortWWN, pFlags);
3891 	} else {
3892 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3893 	}
3894 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3895 }
3896 
3897 HBA_STATUS
3898 SMHBA_GetBindingSupport(
3899     HBA_HANDLE		handle,
3900     HBA_WWN		hbaPortWWN,
3901     HBA_WWN		domainPortWWN,
3902     SMHBA_BIND_CAPABILITY *pFlags)
3903 {
3904 	HBA_STATUS		status;
3905 	HBA_LIBRARY_INFO	*lib_infop;
3906 	HBA_HANDLE		vendorHandle;
3907 	SMHBAGetBindingSupportFunc
3908 	    GetBindingSupporFunc;
3909 
3910 	DEBUG(2, "SMHBA_GetBindingSupport port: %s",
3911 	    WWN2STR1(&hbaPortWWN), 0, 0);
3912 
3913 	CHECKLIBRARYANDVERSION(SMHBA);
3914 
3915 	GetBindingSupporFunc =
3916 	    lib_infop->ftable.smhbafunctionTable.GetBindingSupportHandler;
3917 	if (GetBindingSupporFunc != NULL) {
3918 	status = (GetBindingSupporFunc)(vendorHandle,
3919 	    hbaPortWWN, domainPortWWN, pFlags);
3920 	} else {
3921 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3922 	}
3923 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3924 }
3925 
3926 HBA_STATUS
3927 SMHBA_SetBindingSupport(
3928     HBA_HANDLE		handle,
3929     HBA_WWN		hbaPortWWN,
3930     HBA_WWN		domainPortWWN,
3931     SMHBA_BIND_CAPABILITY flags)
3932 {
3933 	HBA_STATUS		status;
3934 	HBA_LIBRARY_INFO	*lib_infop;
3935 	HBA_HANDLE		vendorHandle;
3936 	SMHBASetBindingSupportFunc
3937 	    SetBindingSupporFunc;
3938 
3939 	DEBUG(2, "SMHBA_GetBindingSupport port: %s",
3940 	    WWN2STR1(&hbaPortWWN), 0, 0);
3941 
3942 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3943 
3944 	SetBindingSupporFunc =
3945 	    lib_infop->ftable.smhbafunctionTable.SetBindingSupportHandler;
3946 	if (SetBindingSupporFunc != NULL) {
3947 	status = (SetBindingSupporFunc)
3948 	    (vendorHandle, hbaPortWWN, domainPortWWN, flags);
3949 	} else {
3950 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3951 	}
3952 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3953 }
3954 
3955 HBA_STATUS
3956 SMHBA_GetTargetMapping(
3957     HBA_HANDLE		handle,
3958     HBA_WWN		hbaPortWWN,
3959     HBA_WWN		domainPortWWN,
3960     SMHBA_TARGETMAPPING *pMapping)
3961 {
3962 	HBA_STATUS		status;
3963 	HBA_LIBRARY_INFO	*lib_infop;
3964 	HBA_HANDLE		vendorHandle;
3965 	SMHBAGetTargetMappingFunc GetTargetMappingFunc;
3966 
3967 	DEBUG(2, "SMHBA_GetTargetMapping port WWN: %s",
3968 	    WWN2STR1(&hbaPortWWN), 0, 0);
3969 
3970 	CHECKLIBRARYANDVERSION(SMHBA);
3971 
3972 	GetTargetMappingFunc =
3973 	    lib_infop->ftable.smhbafunctionTable.GetTargetMappingHandler;
3974 	if (GetTargetMappingFunc != NULL) {
3975 	status = ((GetTargetMappingFunc)(vendorHandle,
3976 	    hbaPortWWN, domainPortWWN, pMapping));
3977 	} else {
3978 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3979 	}
3980 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3981 }
3982 
3983 HBA_STATUS
3984 SMHBA_GetPersistentBinding(
3985     HBA_HANDLE handle,
3986     HBA_WWN	hbaPortWWN,
3987     HBA_WWN	domainPortWWN,
3988     SMHBA_BINDING *binding)
3989 {
3990 	HBA_STATUS		status;
3991 	HBA_LIBRARY_INFO	*lib_infop;
3992 	HBA_HANDLE		vendorHandle;
3993 	SMHBAGetPersistentBindingFunc
3994 	    GetPersistentBindingFunc;
3995 
3996 	DEBUG(2, "SMHBA_GetPersistentBinding port WWN: %s",
3997 	    WWN2STR1(&hbaPortWWN), 0, 0);
3998 
3999 	CHECKLIBRARYANDVERSION(SMHBA);
4000 
4001 	GetPersistentBindingFunc =
4002 	    lib_infop->ftable.smhbafunctionTable.GetPersistentBindingHandler;
4003 	if (GetPersistentBindingFunc != NULL) {
4004 	status = ((GetPersistentBindingFunc)(vendorHandle,
4005 	    hbaPortWWN, domainPortWWN, binding));
4006 	} else {
4007 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4008 	}
4009 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4010 }
4011 
4012 HBA_STATUS
4013 SMHBA_SetPersistentBinding(
4014     HBA_HANDLE handle,
4015     HBA_WWN	hbaPortWWN,
4016     HBA_WWN	domainPortWWN,
4017     const SMHBA_BINDING *binding)
4018 {
4019 	HBA_STATUS		status;
4020 	HBA_LIBRARY_INFO	*lib_infop;
4021 	HBA_HANDLE		vendorHandle;
4022 	SMHBASetPersistentBindingFunc
4023 	    SetPersistentBindingFunc;
4024 
4025 	DEBUG(2, "SMHBA_SetPersistentBinding port WWN: %s",
4026 	    WWN2STR1(&hbaPortWWN), 0, 0);
4027 
4028 	CHECKLIBRARYANDVERSION(SMHBA);
4029 
4030 	SetPersistentBindingFunc =
4031 	    lib_infop->ftable.smhbafunctionTable.SetPersistentBindingHandler;
4032 	if (SetPersistentBindingFunc != NULL) {
4033 	status = ((SetPersistentBindingFunc)(vendorHandle,
4034 	    hbaPortWWN, domainPortWWN, binding));
4035 	} else {
4036 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4037 	}
4038 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4039 }
4040 
4041 HBA_STATUS
4042 SMHBA_RemovePersistentBinding(
4043     HBA_HANDLE handle,
4044     HBA_WWN	hbaPortWWN,
4045     HBA_WWN	domainPortWWN,
4046     const SMHBA_BINDING *binding)
4047 {
4048 	HBA_STATUS		status;
4049 	HBA_LIBRARY_INFO	*lib_infop;
4050 	HBA_HANDLE		vendorHandle;
4051 	SMHBARemovePersistentBindingFunc
4052 	    RemovePersistentBindingFunc;
4053 
4054 	DEBUG(2, "SMHBA_RemovePersistentBinding port WWN: %s",
4055 	    WWN2STR1(&hbaPortWWN), 0, 0);
4056 
4057 	CHECKLIBRARYANDVERSION(SMHBA);
4058 
4059 	RemovePersistentBindingFunc =
4060 	    lib_infop->ftable.smhbafunctionTable.RemovePersistentBindingHandler;
4061 	if (RemovePersistentBindingFunc != NULL) {
4062 	status = ((RemovePersistentBindingFunc)(vendorHandle,
4063 	    hbaPortWWN, domainPortWWN, binding));
4064 	} else {
4065 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4066 	}
4067 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4068 }
4069 
4070 HBA_STATUS
4071 SMHBA_RemoveAllPersistentBindings(
4072     HBA_HANDLE handle,
4073     HBA_WWN	hbaPortWWN,
4074     HBA_WWN	domainPortWWN)
4075 {
4076 	HBA_STATUS		status;
4077 	HBA_LIBRARY_INFO	*lib_infop;
4078 	HBA_HANDLE		vendorHandle;
4079 	SMHBARemoveAllPersistentBindingsFunc
4080 	    RemoveAllPersistentBindingsFunc;
4081 
4082 	DEBUG(2, "SMHBA_RemoveAllPersistentBinding port WWN: %s",
4083 	    WWN2STR1(&hbaPortWWN), 0, 0);
4084 
4085 	CHECKLIBRARYANDVERSION(SMHBA);
4086 
4087 	RemoveAllPersistentBindingsFunc =
4088 	    lib_infop->ftable.smhbafunctionTable.\
4089 	    RemoveAllPersistentBindingsHandler;
4090 	if (RemoveAllPersistentBindingsFunc != NULL) {
4091 	status = ((RemoveAllPersistentBindingsFunc)(vendorHandle,
4092 	    hbaPortWWN, domainPortWWN));
4093 	} else {
4094 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4095 	}
4096 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4097 }
4098 
4099 HBA_STATUS
4100 SMHBA_GetLUNStatistics(
4101     HBA_HANDLE handle,
4102     const HBA_SCSIID *lunit,
4103     SMHBA_PROTOCOLSTATISTICS *statistics)
4104 {
4105 	HBA_STATUS		status;
4106 	HBA_LIBRARY_INFO	*lib_infop;
4107 	HBA_HANDLE		vendorHandle;
4108 	SMHBAGetLUNStatisticsFunc GetLUNStatisticsFunc;
4109 
4110 	DEBUG(2, "SMHBA_GetLUNStatistics", 0, 0, 0);
4111 
4112 	CHECKLIBRARYANDVERSION(SMHBA);
4113 
4114 	GetLUNStatisticsFunc =
4115 	    lib_infop->ftable.smhbafunctionTable.GetLUNStatisticsHandler;
4116 	if (GetLUNStatisticsFunc != NULL) {
4117 	status = ((GetLUNStatisticsFunc)(vendorHandle, lunit, statistics));
4118 	} else {
4119 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4120 	}
4121 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4122 }
4123 
4124 HBA_STATUS
4125 SMHBA_ScsiInquiry(
4126     HBA_HANDLE	handle,
4127     HBA_WWN	hbaPortWWN,
4128     HBA_WWN	discoveredPortWWN,
4129     HBA_WWN	domainPortWWN,
4130     SMHBA_SCSILUN	smhbaLUN,
4131     HBA_UINT8	CDB_Byte1,
4132     HBA_UINT8	CDB_Byte2,
4133     void	*pRspBuffer,
4134     HBA_UINT32	*pRspBufferSize,
4135     HBA_UINT8	*pScsiStatus,
4136     void	*pSenseBuffer,
4137     HBA_UINT32	*pSenseBufferSize)
4138 {
4139 	HBA_STATUS		status;
4140 	HBA_LIBRARY_INFO	*lib_infop;
4141 	HBA_HANDLE		vendorHandle;
4142 	SMHBAScsiInquiryFunc ScsiInquiryFunc;
4143 
4144 	DEBUG(2, "SMHBA_ScsiInquiry to hba port: %s discoveredPortWWN: %s",
4145 	    WWN2STR1(&hbaPortWWN), WWN2STR1(&discoveredPortWWN), 0);
4146 
4147 	CHECKLIBRARYANDVERSION(SMHBA);
4148 
4149 	ScsiInquiryFunc =
4150 	    lib_infop->ftable.smhbafunctionTable.ScsiInquiryHandler;
4151 	if (ScsiInquiryFunc != NULL) {
4152 	status = ((ScsiInquiryFunc)(
4153 	    vendorHandle, hbaPortWWN, discoveredPortWWN, domainPortWWN,
4154 	    smhbaLUN, CDB_Byte1, CDB_Byte2, pRspBuffer, pRspBufferSize,
4155 	    pScsiStatus, pSenseBuffer, pSenseBufferSize));
4156 	} else {
4157 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4158 	}
4159 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4160 }
4161 
4162 HBA_STATUS
4163 SMHBA_ScsiReportLUNs(
4164     HBA_HANDLE	handle,
4165     HBA_WWN	hbaPortWWN,
4166     HBA_WWN	discoveredPortWWN,
4167     HBA_WWN	domainPortWWN,
4168     void	*pRspBuffer,
4169     HBA_UINT32	*pRspBufferSize,
4170     HBA_UINT8	*pScsiStatus,
4171     void	*pSenseBuffer,
4172     HBA_UINT32	*pSenseBufferSize)
4173 {
4174 	HBA_STATUS		status;
4175 	HBA_LIBRARY_INFO	*lib_infop;
4176 	HBA_HANDLE		vendorHandle;
4177 	SMHBAScsiReportLUNsFunc ScsiReportLUNsFunc;
4178 
4179 	DEBUG(2, "SMHBA_ScsiReportLuns to hba port: %s discoveredPortWWN: %s",
4180 	    WWN2STR1(&hbaPortWWN), WWN2STR1(&discoveredPortWWN), 0);
4181 
4182 	CHECKLIBRARYANDVERSION(SMHBA);
4183 
4184 	ScsiReportLUNsFunc =
4185 	    lib_infop->ftable.smhbafunctionTable.ScsiReportLUNsHandler;
4186 	if (ScsiReportLUNsFunc != NULL) {
4187 	status = ((ScsiReportLUNsFunc)(
4188 	    vendorHandle, hbaPortWWN, discoveredPortWWN, domainPortWWN,
4189 	    pRspBuffer, pRspBufferSize, pScsiStatus, pSenseBuffer,
4190 	    pSenseBufferSize));
4191 	} else {
4192 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4193 	}
4194 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4195 }
4196 
4197 HBA_STATUS
4198 SMHBA_ScsiReadCapacity(
4199     HBA_HANDLE	handle,
4200     HBA_WWN	hbaPortWWN,
4201     HBA_WWN	discoveredPortWWN,
4202     HBA_WWN	domainPortWWN,
4203     SMHBA_SCSILUN	smhbaLUN,
4204     void	*pRspBuffer,
4205     HBA_UINT32	*pRspBufferSize,
4206     HBA_UINT8	*pScsiStatus,
4207     void	*pSenseBuffer,
4208     HBA_UINT32	*pSenseBufferSize)
4209 {
4210 	HBA_STATUS		status;
4211 	HBA_LIBRARY_INFO	*lib_infop;
4212 	HBA_HANDLE		vendorHandle;
4213 	SMHBAScsiReadCapacityFunc ScsiReadCapacityFunc;
4214 
4215 	DEBUG(2, "SMHBA_ScsiReadCapacity to hba port: %s discoveredPortWWN: %s",
4216 	    WWN2STR1(&hbaPortWWN), WWN2STR1(&discoveredPortWWN), 0);
4217 
4218 	CHECKLIBRARYANDVERSION(SMHBA);
4219 
4220 	ScsiReadCapacityFunc =
4221 	    lib_infop->ftable.smhbafunctionTable.ScsiReadCapacityHandler;
4222 	if (ScsiReadCapacityFunc != NULL) {
4223 	status = ((ScsiReadCapacityFunc)(
4224 	    vendorHandle, hbaPortWWN, discoveredPortWWN, domainPortWWN,
4225 	    smhbaLUN, pRspBuffer, pRspBufferSize, pScsiStatus, pSenseBuffer,
4226 	    pSenseBufferSize));
4227 	} else {
4228 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4229 	}
4230 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4231 }
4232 
4233 HBA_STATUS
4234 SMHBA_SendTEST(
4235     HBA_HANDLE		handle,
4236     HBA_WWN		hbaPortWWN,
4237     HBA_WWN		destWWN,
4238     HBA_UINT32		destFCID,
4239     void		*pRspBuffer,
4240     HBA_UINT32		pRspBufferSize)
4241 {
4242 	HBA_STATUS		status;
4243 	HBA_LIBRARY_INFO	*lib_infop;
4244 	HBA_HANDLE		vendorHandle;
4245 	SMHBASendTESTFunc	SendTESTFunc;
4246 
4247 	DEBUG(2, "SMHBA_SendTEST, hbaPortWWN: %s destWWN",
4248 	    WWN2STR1(&hbaPortWWN),
4249 	    WWN2STR1(&destWWN), 0);
4250 
4251 	CHECKLIBRARYANDVERSION(SMHBA);
4252 
4253 	SendTESTFunc = lib_infop->ftable.smhbafunctionTable.SendTESTHandler;
4254 	if (SendTESTFunc != NULL) {
4255 	status = (SendTESTFunc)
4256 	    (vendorHandle, hbaPortWWN, destWWN, destFCID,
4257 	    pRspBuffer, pRspBufferSize);
4258 	} else {
4259 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4260 	}
4261 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4262 }
4263 
4264 HBA_STATUS
4265 SMHBA_SendECHO(
4266     HBA_HANDLE		handle,
4267     HBA_WWN		hbaPortWWN,
4268     HBA_WWN		destWWN,
4269     HBA_UINT32		destFCID,
4270     void		*pReqBuffer,
4271     HBA_UINT32		ReqBufferSize,
4272     void		*pRspBuffer,
4273     HBA_UINT32		*pRspBufferSize)
4274 {
4275 	HBA_STATUS		status;
4276 	HBA_LIBRARY_INFO	*lib_infop;
4277 	HBA_HANDLE		vendorHandle;
4278 	SMHBASendECHOFunc	SendECHOFunc;
4279 
4280 	DEBUG(2, "SMHBA_SendECHO, hbaPortWWN: %s destWWN",
4281 	    WWN2STR1(&hbaPortWWN), WWN2STR1(&destWWN), 0);
4282 
4283 	CHECKLIBRARYANDVERSION(SMHBA);
4284 
4285 	SendECHOFunc = lib_infop->ftable.smhbafunctionTable.SendECHOHandler;
4286 	if (SendECHOFunc != NULL) {
4287 	status = (SendECHOFunc)
4288 	    (vendorHandle, hbaPortWWN, destWWN, destFCID,
4289 	    pReqBuffer, ReqBufferSize, pRspBuffer, pRspBufferSize);
4290 	} else {
4291 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4292 	}
4293 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4294 }
4295 
4296 HBA_STATUS
4297 SMHBA_SendSMPPassThru(
4298     HBA_HANDLE		handle,
4299     HBA_WWN		hbaPortWWN,
4300     HBA_WWN		destWWN,
4301     HBA_WWN		domainPortWWN,
4302     void		*pReqBuffer,
4303     HBA_UINT32		ReqBufferSize,
4304     void		*pRspBuffer,
4305     HBA_UINT32		*pRspBufferSize)
4306 {
4307 	HBA_STATUS		status;
4308 	HBA_LIBRARY_INFO	*lib_infop;
4309 	HBA_HANDLE		vendorHandle;
4310 	SMHBASendSMPPassThruFunc	SendSMPPassThruFunc;
4311 
4312 	DEBUG(2, "SMHBA_SendSMPPassThru, hbaPortWWN: %s destWWN: %s",
4313 	    WWN2STR1(&hbaPortWWN), WWN2STR1(&destWWN), 0);
4314 
4315 	CHECKLIBRARYANDVERSION(SMHBA);
4316 
4317 	SendSMPPassThruFunc = lib_infop->ftable.\
4318 	    smhbafunctionTable.SendSMPPassThruHandler;
4319 
4320 	if (SendSMPPassThruFunc != NULL) {
4321 	status = (SendSMPPassThruFunc)
4322 	    (vendorHandle, hbaPortWWN, destWWN, domainPortWWN,
4323 	    pReqBuffer, ReqBufferSize, pRspBuffer, pRspBufferSize);
4324 	} else {
4325 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4326 	}
4327 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4328 }
4329 
4330 /*
4331  * Following the similar logic of HBAAPI addaspterevents_callback.
4332  *
4333  * Unlike other events Adapter Add Event is not limited to a specific
4334  * adapter(i.e. no adapter handle is passed for registration) so
4335  * the event should be passed to all registrants.  The routine below
4336  * is passed to the VSLs as a callback and when Adapter Add event is detected
4337  * by VSL it will call smhba_adapteraddevents_callback() which in turn check
4338  * if the passed userdata ptr matches with the one stored in the callback list
4339  * and calls the stored callback.
4340  *
4341  * For the situation that multiple clients are registered for Adapter Add event
4342  * each registration is passed to VSLs so VSL may call
4343  * smhba_adapteraddevents_callback() multiple times or it may call only once
4344  * since the callback function is same.  For this implemneation, the userdata
4345  * is stored in HBA_ALLADAPTERSCALLBACK_ELEM so it is expected that VSL call
4346  * smhba_adapteraddevents_callback() only once and
4347  * smhba_adapteraddevents_callback() will call the client callback with proper
4348  * userdata.
4349  */
4350 static void
4351 smhba_adapteraddevents_callback(
4352 /* LINTED E_FUNC_ARG_UNUSED */
4353     void *data,
4354     HBA_WWN PortWWN,
4355 /* LINTED E_FUNC_ARG_UNUSED */
4356     HBA_UINT32 eventType)
4357 {
4358 	HBA_ALLADAPTERSCALLBACK_ELEM	*cbp;
4359 
4360 	DEBUG(3, "AddAdapterEvent, port:%s", WWN2STR1(&PortWWN), 0, 0);
4361 
4362 	GRAB_MUTEX(&_smhba_AAE_mutex);
4363 	for (cbp = _smhba_adapteraddevents_callback_list;
4364 	    cbp != NULL;
4365 	    cbp = cbp->next) {
4366 	(*cbp->callback)(cbp->userdata, PortWWN, HBA_EVENT_ADAPTER_ADD);
4367 	}
4368 	RELEASE_MUTEX(&_smhba_AAE_mutex);
4369 
4370 }
4371 
4372 HBA_STATUS
4373 SMHBA_RegisterForAdapterAddEvents(
4374     void		(*pCallback) (
4375 	void		*data,
4376 	HBA_WWN		PortWWN,
4377 	HBA_UINT32	eventType),
4378     void		*pUserData,
4379     HBA_CALLBACKHANDLE  *pCallbackHandle) {
4380 
4381     HBA_ALLADAPTERSCALLBACK_ELEM	*cbp;
4382     HBA_VENDORCALLBACK_ELEM		*vcbp;
4383     HBA_VENDORCALLBACK_ELEM		*vendorhandlelist;
4384     SMHBARegisterForAdapterAddEventsFunc	registeredfunc;
4385     HBA_STATUS				status = HBA_STATUS_OK;
4386     HBA_STATUS				failure = HBA_STATUS_OK;
4387     HBA_LIBRARY_INFO			*lib_infop;
4388     int					registered_cnt = 0;
4389     int					vendor_cnt = 0;
4390     int					not_supported_cnt = 0;
4391     int					status_OK_bar_cnt = 0;
4392     int					status_OK_cnt = 0;
4393 
4394     DEBUG(2, "SMHBA_RegisterForAdapterAddEvents", 0, 0, 0);
4395     ARE_WE_INITED();
4396 
4397     cbp = (HBA_ALLADAPTERSCALLBACK_ELEM *)
4398 	    calloc(1, sizeof (HBA_ALLADAPTERSCALLBACK_ELEM));
4399 	*pCallbackHandle = (HBA_CALLBACKHANDLE) cbp;
4400     if (cbp == NULL) {
4401 	return (HBA_STATUS_ERROR);
4402 	}
4403 
4404     GRAB_MUTEX(&_hbaapi_LL_mutex);
4405     GRAB_MUTEX(&_smhba_AAE_mutex);
4406     cbp->callback = pCallback;
4407     cbp->userdata = pUserData;
4408     cbp->next = _smhba_adapteraddevents_callback_list;
4409     _smhba_adapteraddevents_callback_list = cbp;
4410 
4411 	/*
4412 	 * Need to release the mutex now incase the vendor function invokes the
4413 	 * callback.  We will grap the mutex later to attach the vendor handle
4414 	 * list to the callback structure
4415 	 */
4416 	RELEASE_MUTEX(&_smhba_AAE_mutex);
4417 
4418 
4419 	/*
4420 	 * now create a list of vendors (vendor libraryies, NOT ADAPTERS)
4421 	 * that have successfully registerred
4422 	 */
4423     vendorhandlelist = NULL;
4424     for (lib_infop = _hbaapi_librarylist;
4425 	lib_infop != NULL;
4426 	lib_infop = lib_infop->next) {
4427 
4428 	/* only for HBAAPI V2 */
4429 	if (lib_infop->version != SMHBA) {
4430 	    continue;
4431 	} else {
4432 	    vendor_cnt++;
4433 	}
4434 
4435 	registeredfunc =
4436 	    lib_infop->ftable.smhbafunctionTable.\
4437 	    RegisterForAdapterAddEventsHandler;
4438 	if (registeredfunc == NULL) {
4439 	    continue;
4440 	}
4441 
4442 	vcbp = (HBA_VENDORCALLBACK_ELEM *)
4443 	    calloc(1, sizeof (HBA_VENDORCALLBACK_ELEM));
4444 	if (vcbp == NULL) {
4445 	    freevendorhandlelist(vendorhandlelist);
4446 	    status = HBA_STATUS_ERROR;
4447 	    break;
4448 	}
4449 
4450 	registered_cnt++;
4451 	status = (registeredfunc)(smhba_adapteraddevents_callback,
4452 	    pUserData, &vcbp->vendorcbhandle);
4453 	if (status == HBA_STATUS_ERROR_NOT_SUPPORTED) {
4454 	    not_supported_cnt++;
4455 	    free(vcbp);
4456 	    continue;
4457 	} else if (status != HBA_STATUS_OK) {
4458 	    status_OK_bar_cnt++;
4459 	    DEBUG(1,
4460 		    "SMHBA_RegisterForAdapterAddEvents: Library->%s, Error->%d",
4461 		    lib_infop->LibraryPath, status, 0);
4462 	    failure = status;
4463 	    free(vcbp);
4464 	    continue;
4465 	} else {
4466 	    status_OK_cnt++;
4467 	}
4468 	vcbp->lib_info = lib_infop;
4469 	vcbp->next = vendorhandlelist;
4470 	vendorhandlelist = vcbp;
4471 	}
4472 
4473     if (vendor_cnt == 0) {
4474 	/* no SMHBA VSL found.  Should be okay?? */
4475 	status = HBA_STATUS_ERROR;
4476 	} else if (registered_cnt == 0) {
4477 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4478 	freevendorhandlelist(vendorhandlelist);
4479 	(void) local_remove_callback((HBA_CALLBACKHANDLE) cbp);
4480 	} else if (status_OK_cnt == 0 && not_supported_cnt != 0) {
4481 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4482 	} else if (status_OK_cnt == 0) {
4483 	/*
4484 	 * At least one vendor library registered this function, but no
4485 	 * vendor call succeeded
4486 	 */
4487 	(void) local_remove_callback((HBA_CALLBACKHANDLE) cbp);
4488 	status = failure;
4489 	} else {
4490 	/* we have had atleast some success, now finish up */
4491 	GRAB_MUTEX(&_smhba_AAE_mutex);
4492 	/*
4493 	 * this seems silly, but what if another thread called
4494 	 * the callback remove
4495 	 */
4496 	for (cbp = _smhba_adapteraddevents_callback_list;
4497 	    cbp != NULL; cbp = cbp->next) {
4498 	    if ((HBA_CALLBACKHANDLE)cbp == *pCallbackHandle) {
4499 		/* yup, its still there, hooray */
4500 		cbp->vendorhandlelist = vendorhandlelist;
4501 		vendorhandlelist = NULL;
4502 		break;
4503 	    }
4504 	}
4505 	RELEASE_MUTEX(&_smhba_AAE_mutex);
4506 	if (vendorhandlelist != NULL) {
4507 		/*
4508 		 * bummer, somebody removed the callback before we finished
4509 		 * registration, probably will never happen
4510 		 */
4511 	    freevendorhandlelist(vendorhandlelist);
4512 	    DEBUG(1,
4513 		    "HBA_RegisterForAdapterAddEvents: HBA_RemoveCallback was "
4514 		    "called for a handle before registration was finished.",
4515 		    0, 0, 0);
4516 	    status = HBA_STATUS_ERROR;
4517 	} else {
4518 	    status = HBA_STATUS_OK;
4519 	}
4520 	}
4521     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4522 }
4523 
4524 /* SMHBA Adapter Events (other than add) ******************************** */
4525 static void
4526 smhba_adapterevents_callback(void *data,
4527 			HBA_WWN PortWWN,
4528 			HBA_UINT32 eventType)
4529 {
4530 	HBA_ADAPTERCALLBACK_ELEM	*acbp;
4531 
4532 	DEBUG(3, "AdapterEvent, port:%s, eventType:%d", WWN2STR1(&PortWWN),
4533 	    eventType, 0);
4534 
4535 	GRAB_MUTEX(&_hbaapi_AE_mutex);
4536 	for (acbp = _smhba_adapterevents_callback_list;
4537 	    acbp != NULL;
4538 	    acbp = acbp->next) {
4539 	if (data == (void *)acbp) {
4540 		(*acbp->callback)(acbp->userdata, PortWWN, eventType);
4541 		break;
4542 	}
4543 	}
4544 	RELEASE_MUTEX(&_hbaapi_AE_mutex);
4545 }
4546 
4547 HBA_STATUS
4548 SMHBA_RegisterForAdapterEvents(
4549     void		(*pCallback) (
4550 	void		*data,
4551 	HBA_WWN		PortWWN,
4552 	HBA_UINT32	eventType),
4553     void		*pUserData,
4554     HBA_HANDLE		handle,
4555     HBA_CALLBACKHANDLE	*pCallbackHandle) {
4556 
4557 	HBA_ADAPTERCALLBACK_ELEM		*acbp;
4558 	SMHBARegisterForAdapterEventsFunc	registeredfunc;
4559 	HBA_STATUS				status;
4560 	HBA_LIBRARY_INFO			*lib_infop;
4561 	HBA_HANDLE				vendorHandle;
4562 
4563 	DEBUG(2, "SMHBA_RegisterForAdapterEvents", 0, 0, 0);
4564 
4565 	CHECKLIBRARYANDVERSION(SMHBA);
4566 
4567 	/* we now have the _hbaapi_LL_mutex */
4568 
4569 	registeredfunc = lib_infop->ftable.smhbafunctionTable.\
4570 	    RegisterForAdapterEventsHandler;
4571     if (registeredfunc == NULL) {
4572 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
4573 	}
4574 
4575 	/*
4576 	 * that allocated memory is used both as the handle for the
4577 	 * caller, and as userdata to the vendor call so that on
4578 	 * callback the specific registration may be recalled
4579 	 */
4580 	acbp = (HBA_ADAPTERCALLBACK_ELEM *)
4581 	    calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
4582 	if (acbp == NULL) {
4583 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
4584 	}
4585 	*pCallbackHandle = (HBA_CALLBACKHANDLE) acbp;
4586 	acbp->callback = pCallback;
4587 	acbp->userdata = pUserData;
4588 	acbp->lib_info = lib_infop;
4589 
4590 	status = (registeredfunc)(smhba_adapterevents_callback,
4591 	    (void *)acbp,
4592 	    vendorHandle,
4593 	    &acbp->vendorcbhandle);
4594     if (status != HBA_STATUS_OK) {
4595 	free(acbp);
4596 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4597 	}
4598 
4599 	GRAB_MUTEX(&_smhba_AE_mutex);
4600 	acbp->next = _smhba_adapterevents_callback_list;
4601 	    _hbaapi_adapterevents_callback_list = acbp;
4602 
4603 	RELEASE_MUTEX(&_smhba_AE_mutex);
4604 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
4605 }
4606 
4607 /* Adapter Port Events *********************************************** */
4608 static void
4609 smhba_adapterportevents_callback(void *data,
4610 			    HBA_WWN PortWWN,
4611 			    HBA_UINT32 eventType,
4612 			    HBA_UINT32 fabricPortID)
4613 {
4614 	HBA_ADAPTERCALLBACK_ELEM	*acbp;
4615 
4616 	DEBUG(3,
4617 	    "SMHBA_AdapterPortEvent, port:%s, eventType:%d fabricPortID:0X%06x",
4618 	    WWN2STR1(&PortWWN), eventType, fabricPortID);
4619 
4620 	GRAB_MUTEX(&_smhba_APE_mutex);
4621 
4622 	for (acbp = _smhba_adapterportevents_callback_list;
4623 	    acbp != NULL;
4624 	    acbp = acbp->next) {
4625 	if (data == (void *)acbp) {
4626 		(*acbp->callback)(acbp->userdata, PortWWN,
4627 		    eventType, fabricPortID);
4628 		break;
4629 	}
4630 	}
4631 	RELEASE_MUTEX(&_smhba_APE_mutex);
4632 }
4633 
4634 HBA_STATUS
4635 SMHBA_RegisterForAdapterPortEvents(
4636     void		(*pCallback) (
4637 	void		*pData,
4638 	HBA_WWN		PortWWN,
4639 	HBA_UINT32	eventType,
4640 	HBA_UINT32	fabricPortID),
4641     void		*pUserData,
4642     HBA_HANDLE		handle,
4643     HBA_WWN		portWWN,
4644     HBA_UINT32		specificEventType,
4645     HBA_CALLBACKHANDLE	*pCallbackHandle) {
4646 
4647 	HBA_ADAPTERCALLBACK_ELEM		*acbp;
4648 	SMHBARegisterForAdapterPortEventsFunc	registeredfunc;
4649 	HBA_STATUS				status;
4650 	HBA_LIBRARY_INFO			*lib_infop;
4651 	HBA_HANDLE				vendorHandle;
4652 
4653 	DEBUG(2, "SMHBA_RegisterForAdapterPortEvents for port: %s",
4654 	    WWN2STR1(&portWWN), 0, 0);
4655 
4656 	CHECKLIBRARYANDVERSION(SMHBA);
4657 	/* we now have the _hbaapi_LL_mutex */
4658 
4659 	registeredfunc =
4660 	    lib_infop->ftable.smhbafunctionTable.\
4661 	    RegisterForAdapterPortEventsHandler;
4662 	if (registeredfunc == NULL) {
4663 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
4664 	}
4665 
4666 	/*
4667 	 * that allocated memory is used both as the handle for the
4668 	 * caller, and as userdata to the vendor call so that on
4669 	 * callback the specific registration may be recalled
4670 	 */
4671 	acbp = (HBA_ADAPTERCALLBACK_ELEM *)
4672 	    calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
4673 	if (acbp == NULL) {
4674 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
4675 	}
4676 	*pCallbackHandle = (HBA_CALLBACKHANDLE) acbp;
4677 	acbp->callback = pCallback;
4678 	acbp->userdata = pUserData;
4679 	acbp->lib_info = lib_infop;
4680 
4681 	status = (registeredfunc)(smhba_adapterportevents_callback,
4682 	    (void *)acbp,
4683 	    vendorHandle,
4684 	    portWWN,
4685 	    specificEventType,
4686 	    &acbp->vendorcbhandle);
4687 	if (status != HBA_STATUS_OK) {
4688 	free(acbp);
4689 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4690 	}
4691 
4692 	GRAB_MUTEX(&_smhba_APE_mutex);
4693 	acbp->next = _smhba_adapterportevents_callback_list;
4694 	_smhba_adapterportevents_callback_list = acbp;
4695 
4696 	RELEASE_MUTEX(&_smhba_APE_mutex);
4697 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
4698 }
4699 
4700 /* SMHBA Adapter Port Stat Events ******************************** */
4701 static void
4702 smhba_adapterportstatevents_callback(void *data,
4703 				HBA_WWN portWWN,
4704 				HBA_UINT32 protocolType,
4705 				HBA_UINT32 eventType)
4706 {
4707 	HBA_ADAPTERCALLBACK_ELEM	*acbp;
4708 
4709 	DEBUG(3,
4710 	    "SMBA_AdapterPortStateEvent, port:%s, eventType:%d",
4711 	    WWN2STR1(&portWWN), eventType, 0);
4712 
4713 	GRAB_MUTEX(&_smhba_APSE_mutex);
4714 	for (acbp = _smhba_adapterportstatevents_callback_list;
4715 	    acbp != NULL;
4716 	    acbp = acbp->next) {
4717 	if (data == (void *)acbp) {
4718 		(*acbp->callback)(acbp->userdata, portWWN,
4719 		    protocolType, eventType);
4720 		return;
4721 	}
4722 	}
4723 	RELEASE_MUTEX(&_smhba_APSE_mutex);
4724 }
4725 
4726 HBA_STATUS
4727 SMHBA_RegisterForAdapterPortStatEvents(
4728     void		(*pCallback) (
4729 	void		*pData,
4730 	HBA_WWN		portWWN,
4731 	HBA_UINT32	protocolType,
4732 	HBA_UINT32	eventType),
4733     void		*pUserData,
4734     HBA_HANDLE		handle,
4735     HBA_WWN		portWWN,
4736     HBA_UINT32		protocolType,
4737     SMHBA_PROTOCOLSTATISTICS	stats,
4738     HBA_UINT32		statType,
4739     HBA_CALLBACKHANDLE	*pCallbackHandle) {
4740 
4741 	HBA_ADAPTERCALLBACK_ELEM	*acbp;
4742 	SMHBARegisterForAdapterPortStatEventsFunc
4743 	    registeredfunc;
4744 	HBA_STATUS			status;
4745 	HBA_LIBRARY_INFO		*lib_infop;
4746 	HBA_HANDLE			vendorHandle;
4747 
4748 	DEBUG(2, "SMHBA_RegisterForAdapterPortStatEvents for port: %s",
4749 	    WWN2STR1(&portWWN), 0, 0);
4750 
4751 	CHECKLIBRARYANDVERSION(SMHBA);
4752 	/* we now have the _hbaapi_LL_mutex */
4753 
4754 	registeredfunc =
4755 	    lib_infop->ftable.smhbafunctionTable.\
4756 	    RegisterForAdapterPortStatEventsHandler;
4757 	if (registeredfunc == NULL) {
4758 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
4759 	}
4760 
4761 	/*
4762 	 * that allocated memory is used both as the handle for the
4763 	 * caller, and as userdata to the vendor call so that on
4764 	 * callback the specific registration may be recalled
4765 	 */
4766 	acbp = (HBA_ADAPTERCALLBACK_ELEM *)
4767 	    calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
4768 	if (acbp == NULL) {
4769 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
4770 	}
4771 	*pCallbackHandle = (HBA_CALLBACKHANDLE) acbp;
4772 	acbp->callback = pCallback;
4773 	acbp->userdata = pUserData;
4774 	acbp->lib_info = lib_infop;
4775 
4776 	status = (registeredfunc)(smhba_adapterportstatevents_callback,
4777 	    (void *)acbp,
4778 	    vendorHandle,
4779 	    portWWN,
4780 	    protocolType,
4781 	    stats,
4782 	    statType,
4783 	    &acbp->vendorcbhandle);
4784 	if (status != HBA_STATUS_OK) {
4785 	free(acbp);
4786 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4787 	}
4788 
4789 	GRAB_MUTEX(&_smhba_APSE_mutex);
4790 	acbp->next = _smhba_adapterportstatevents_callback_list;
4791 	_smhba_adapterportstatevents_callback_list = acbp;
4792 
4793 	RELEASE_MUTEX(&_smhba_APSE_mutex);
4794 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
4795 }
4796 
4797 /* SMHBA Adapter Port Phy Stat Events ************************************ */
4798 static void
4799 smhba_adapterphystatevents_callback(void *data,
4800 				HBA_WWN portWWN,
4801 				HBA_UINT32 phyIndex,
4802 				HBA_UINT32 eventType)
4803 {
4804 	HBA_ADAPTERCALLBACK_ELEM	*acbp;
4805 
4806 	DEBUG(3,
4807 	    "SMBA_AdapterPortStateEvent, port:%s, eventType:%d",
4808 	    WWN2STR1(&portWWN), eventType, 0);
4809 
4810 	GRAB_MUTEX(&_smhba_APHYSE_mutex);
4811 	for (acbp = _smhba_adapterphystatevents_callback_list;
4812 	    acbp != NULL;
4813 	    acbp = acbp->next) {
4814 	if (data == (void *)acbp) {
4815 		(*acbp->callback)(acbp->userdata, portWWN, phyIndex, eventType);
4816 		return;
4817 	}
4818 	}
4819 	RELEASE_MUTEX(&_smhba_APHYSE_mutex);
4820 }
4821 
4822 HBA_STATUS
4823 SMHBA_RegisterForAdapterPhyStatEvents(
4824     void		(*pCallback) (
4825 	void		*pData,
4826 	HBA_WWN		portWWN,
4827 	HBA_UINT32	phyIndex,
4828 	HBA_UINT32	eventType),
4829     void		*pUserData,
4830     HBA_HANDLE		handle,
4831     HBA_WWN		portWWN,
4832     HBA_UINT32		phyIndex,
4833     SMHBA_PHYSTATISTICS	stats,
4834     HBA_UINT32		statType,
4835     HBA_CALLBACKHANDLE	*pCallbackHandle) {
4836 
4837 	HBA_ADAPTERCALLBACK_ELEM	*acbp;
4838 	SMHBARegisterForAdapterPhyStatEventsFunc
4839 	    registeredfunc;
4840 	HBA_STATUS			status;
4841 	HBA_LIBRARY_INFO		*lib_infop;
4842 	HBA_HANDLE			vendorHandle;
4843 
4844 	DEBUG(2, "SMHBA_RegisterForAdapterPhyStatEvents for port: %s",
4845 	    WWN2STR1(&portWWN), 0, 0);
4846 
4847 	CHECKLIBRARYANDVERSION(SMHBA);
4848 	/* we now have the _hbaapi_LL_mutex */
4849 
4850 	registeredfunc =
4851 	    lib_infop->ftable.smhbafunctionTable.\
4852 	    RegisterForAdapterPhyStatEventsHandler;
4853 	if (registeredfunc == NULL) {
4854 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
4855 	}
4856 
4857 	/*
4858 	 * that allocated memory is used both as the handle for the
4859 	 * caller, and as userdata to the vendor call so that on
4860 	 * callback the specific registration may be recalled
4861 	 */
4862 	acbp = (HBA_ADAPTERCALLBACK_ELEM *)
4863 	    calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
4864 	if (acbp == NULL) {
4865 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
4866 	}
4867 	*pCallbackHandle = (HBA_CALLBACKHANDLE) acbp;
4868 	acbp->callback = pCallback;
4869 	acbp->userdata = pUserData;
4870 	acbp->lib_info = lib_infop;
4871 
4872 	status = (registeredfunc)(smhba_adapterphystatevents_callback,
4873 	    (void *)acbp,
4874 	    vendorHandle,
4875 	    portWWN,
4876 	    phyIndex,
4877 	    stats,
4878 	    statType,
4879 	    &acbp->vendorcbhandle);
4880 	if (status != HBA_STATUS_OK) {
4881 	free(acbp);
4882 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4883 	}
4884 
4885 	GRAB_MUTEX(&_smhba_APHYSE_mutex);
4886 	acbp->next = _smhba_adapterphystatevents_callback_list;
4887 	_smhba_adapterphystatevents_callback_list = acbp;
4888 
4889 	RELEASE_MUTEX(&_smhba_APHYSE_mutex);
4890 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
4891 }
4892 
4893 /* SMHBA Target Events ********************************************* */
4894 static void
4895 smhba_targetevents_callback(void *data,
4896 	HBA_WWN hbaPortWWN,
4897 	HBA_WWN discoveredPortWWN,
4898 	HBA_WWN domainPortWWN,
4899 	HBA_UINT32 eventType)
4900 {
4901 	HBA_ADAPTERCALLBACK_ELEM	*acbp;
4902 
4903 	DEBUG(3, "TargetEvent, hbaPort:%s, discoveredPort:%s eventType:%d",
4904 	    WWN2STR1(&hbaPortWWN), WWN2STR2(&discoveredPortWWN), eventType);
4905 
4906 	GRAB_MUTEX(&_smhba_TE_mutex);
4907 	for (acbp = _smhba_targetevents_callback_list;
4908 	    acbp != NULL;
4909 	    acbp = acbp->next) {
4910 	if (data == (void *)acbp) {
4911 		(*acbp->callback)(acbp->userdata, hbaPortWWN,
4912 		    discoveredPortWWN, domainPortWWN, eventType);
4913 		break;
4914 	}
4915 	}
4916 	RELEASE_MUTEX(&_smhba_TE_mutex);
4917 }
4918 
4919 HBA_STATUS
4920 SMHBA_RegisterForTargetEvents(
4921     void		(*pCallback) (
4922 	void		*pData,
4923 	HBA_WWN		hbaPortWWN,
4924 	HBA_WWN		discoveredPortWWN,
4925 	HBA_WWN		domainPortWWN,
4926 	HBA_UINT32	eventType),
4927     void		*pUserData,
4928     HBA_HANDLE		handle,
4929     HBA_WWN		hbaPortWWN,
4930     HBA_WWN		discoveredPortWWN,
4931     HBA_WWN		domainPortWWN,
4932     HBA_CALLBACKHANDLE	*pCallbackHandle,
4933     HBA_UINT32		allTargets) {
4934 
4935 	HBA_ADAPTERCALLBACK_ELEM *acbp;
4936 	SMHBARegisterForTargetEventsFunc
4937 	    registeredfunc;
4938 	HBA_STATUS		status;
4939 	HBA_LIBRARY_INFO	*lib_infop;
4940 	HBA_HANDLE		vendorHandle;
4941 
4942 	DEBUG(2, "SMHBA_RegisterForTargetEvents, hbaPort:"
4943 	    "%s, discoveredPort: %s",
4944 	    WWN2STR1(&hbaPortWWN), WWN2STR2(&discoveredPortWWN), 0);
4945 
4946 	CHECKLIBRARYANDVERSION(SMHBA);
4947 	/* we now have the _hbaapi_LL_mutex */
4948 
4949 	registeredfunc = lib_infop->ftable.smhbafunctionTable.\
4950 	    RegisterForTargetEventsHandler;
4951 
4952 	if (registeredfunc == NULL) {
4953 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
4954 	}
4955 
4956 	/*
4957 	 * that allocated memory is used both as the handle for the
4958 	 * caller, and as userdata to the vendor call so that on
4959 	 * callback the specific registration may be recalled
4960 	 */
4961 	acbp = (HBA_ADAPTERCALLBACK_ELEM *)
4962 	    calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
4963 	if (acbp == NULL) {
4964 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
4965 	}
4966 	*pCallbackHandle = (HBA_CALLBACKHANDLE) acbp;
4967 	acbp->callback = pCallback;
4968 	acbp->userdata = pUserData;
4969 	acbp->lib_info = lib_infop;
4970 
4971 	status = (registeredfunc)(smhba_targetevents_callback,
4972 	    (void *)acbp,
4973 	    vendorHandle,
4974 	    hbaPortWWN,
4975 	    discoveredPortWWN,
4976 	    domainPortWWN,
4977 	    &acbp->vendorcbhandle,
4978 	    allTargets);
4979 	if (status != HBA_STATUS_OK) {
4980 	free(acbp);
4981 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4982 	}
4983 
4984 	GRAB_MUTEX(&_smhba_TE_mutex);
4985 	acbp->next = _smhba_targetevents_callback_list;
4986 	_smhba_targetevents_callback_list = acbp;
4987 
4988 	RELEASE_MUTEX(&_smhba_TE_mutex);
4989 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
4990 }
4991