xref: /illumos-gate/usr/src/lib/smhba/common/SMHBAAPILIB.c (revision cd3e933325e68e23516a196a8fea7f49b1e497c3)
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 		return (HBA_STATUS_ERROR);
950 	}
951 	lib_infop->status = HBA_LIBRARY_NOT_LOADED;
952 	lib_infop->LibraryName = strdup(libraryname);
953 	lib_infop->LibraryPath = strdup(librarypath);
954 	lib_infop->numOfAdapters = 0;
955 	lib_infop->version = UNKNOWN;
956 	lib_infop->index = _hbaapi_total_library_count;
957 	_hbaapi_total_library_count++;
958 	lib_infop->next = _hbaapi_librarylist;
959 	_hbaapi_librarylist = lib_infop;
960 
961 	/* Load the DLL now */
962 	if ((lib_infop->hLibrary = dlopen(librarypath, RTLD_LAZY)) == NULL) {
963 	    /* printf("unable to load library %s\n", librarypath); */
964 		continue;
965 	}
966 	/* Call the registration function to get the list of pointers */
967 	RegisterSMHBAFunc = (SMHBARegisterLibraryFunc)
968 	    dlsym(lib_infop->hLibrary, "SMHBA_RegisterLibrary");
969 	if (RegisterSMHBAFunc != NULL) {
970 		/*
971 		 * Load the function points directly into
972 		 * the table of functions
973 		 */
974 		status = ((RegisterSMHBAFunc)
975 		    (&lib_infop->ftable.smhbafunctionTable));
976 		if (status != HBA_STATUS_OK) {
977 			/* library not loaded */
978 			continue;
979 		} else {
980 			lib_infop->version = SMHBA;
981 		}
982 	} else {
983 		RegisterV2Func = (HBARegisterLibraryV2Func)
984 		    dlsym(lib_infop->hLibrary, "HBA_RegisterLibraryV2");
985 		if (RegisterV2Func != NULL) {
986 		/*
987 		 * Load the function points directly into
988 		 * the table of functions
989 		 */
990 		status = ((RegisterV2Func)((HBA_ENTRYPOINTSV2 *)
991 		    (&lib_infop->ftable.functionTable)));
992 		if (status != HBA_STATUS_OK) {
993 		    /* library not loaded */
994 			continue;
995 		} else {
996 			lib_infop->version = HBAAPIV2;
997 		}
998 		} else {
999 		/* Maybe the vendor library is only Rev1 */
1000 		RegisterFunc = (HBARegisterLibraryFunc)
1001 		    dlsym(lib_infop->hLibrary, "HBA_RegisterLibrary");
1002 		if (RegisterFunc == NULL) {
1003 		    /* This function is required */
1004 			(void) fprintf(stderr,
1005 			    "HBA_LoadLibrary: vendor specific RegisterLibrary "
1006 			    "function not found.  lib: %s\n", librarypath);
1007 			DEBUG(1, "HBA_LoadLibrary: vendor specific "
1008 			    "RegisterLibrary function not found.  lib: %s\n",
1009 			    librarypath, 0, 0);
1010 			continue;
1011 		}
1012 		/*
1013 		 * Load the function points directly into
1014 		 * the table of functions
1015 		 */
1016 		status = ((RegisterFunc)
1017 		    ((HBA_ENTRYPOINTS *)(&lib_infop->ftable.functionTable)));
1018 		if (status != HBA_STATUS_OK) {
1019 		    /* library not loaded */
1020 			(void) fprintf(stderr,
1021 			    "HBA_LoadLibrary: vendor specific RegisterLibrary "
1022 			    "function encountered an error.  lib: %s\n",
1023 			    librarypath);
1024 			DEBUG(1,
1025 			    "HBA_LoadLibrary: vendor specific RegisterLibrary "
1026 			    "function encountered an error. lib: %s\n",
1027 			    librarypath, 0, 0);
1028 			continue;
1029 		} else {
1030 			lib_infop->version = HBAAPI;
1031 		}
1032 		}
1033 	}
1034 
1035 	/* successfully loaded library */
1036 	/*
1037 	 * SM-HBA and HBAAPI has a seperate handler for GetVersion but
1038 	 * they have the same function signature so use the same variable here.
1039 	 */
1040 	if ((GetVersionFunc = FUNCCOMMON(lib_infop, GetVersionHandler))
1041 	    == NULL) {
1042 		continue;
1043 	}
1044 	if (lib_infop->version == SMHBA) {
1045 		libversion = ((GetVersionFunc)());
1046 		if (libversion < SMHBA_LIBVERSION) {
1047 			(void) printf("Library version mismatch."
1048 			    "Got %d expected %d.\n",
1049 			    libversion, SMHBA_LIBVERSION);
1050 			continue;
1051 		}
1052 	} else {
1053 		libversion = ((GetVersionFunc)());
1054 	    /* Check the version of this library before loading */
1055 	    /* Actually... This wrapper is compatible with version 1 */
1056 		if (libversion < HBA_LIBVERSION) {
1057 			(void) printf("Library version mismatch."
1058 			    "Got %d expected %d.\n",
1059 			    libversion, HBA_LIBVERSION);
1060 			continue;
1061 		}
1062 	}
1063 
1064 	DEBUG(1, "%s libversion = %d", librarypath, libversion, 0);
1065 	LoadLibraryFunc = FUNCCOMMON(lib_infop, LoadLibraryHandler);
1066 	if (LoadLibraryFunc == NULL) {
1067 	    /* this function is required */
1068 		(void) fprintf(stderr,
1069 		    "HBA_LoadLibrary: vendor specific LoadLibrary "
1070 		    "function not found.  lib: %s\n", librarypath);
1071 		DEBUG(1, "HBA_LoadLibrary: vendor specific LoadLibrary "
1072 		    "function not found.  lib: %s\n", librarypath, 0, 0);
1073 		continue;
1074 	}
1075 	/* Initialize this library */
1076 	if ((status = ((LoadLibraryFunc)())) != HBA_STATUS_OK) {
1077 	    /* maybe this should be a printf so that we CANNOT miss it */
1078 		(void) fprintf(stderr,
1079 		    "HBA_LoadLibrary: Encounterd and error loading: %s",
1080 		    librarypath);
1081 		DEBUG(1, "Encounterd and error loading: %s", librarypath, 0, 0);
1082 		DEBUG(1, "  HBA_STATUS: %d", status, 0, 0);
1083 		continue;
1084 	}
1085 	/* successfully loaded library */
1086 	lib_infop->status = HBA_LIBRARY_LOADED;
1087 	}
1088 #endif /* WIN32 or UNIX */
1089 #ifdef POSIX_THREADS
1090 	/*
1091 	 * The _hbaapi_LL_mutex is already grabbed to proctect the caller of
1092 	 * HBA_FreeLibrary() during loading.
1093 	 * The mutexes are already initialized
1094 	 * with PTHREAD_MUTEX_INITIALIZER.  Do we need to init again?
1095 	 * Keeping the code from HBAAPI source...
1096 	 */
1097 	ret = pthread_mutex_init(&_hbaapi_AL_mutex, NULL);
1098 	if (ret == 0) {
1099 		ret = pthread_mutex_init(&_hbaapi_AAE_mutex, NULL);
1100 	}
1101 	if (ret == 0) {
1102 		ret = pthread_mutex_init(&_hbaapi_AE_mutex, NULL);
1103 	}
1104 	if (ret == 0) {
1105 		ret = pthread_mutex_init(&_hbaapi_APE_mutex, NULL);
1106 	}
1107 	if (ret == 0) {
1108 		ret = pthread_mutex_init(&_hbaapi_APSE_mutex, NULL);
1109 	}
1110 	if (ret == 0) {
1111 		ret = pthread_mutex_init(&_hbaapi_TE_mutex, NULL);
1112 	}
1113 	if (ret == 0) {
1114 		ret = pthread_mutex_init(&_smhba_AAE_mutex, NULL);
1115 	}
1116 	if (ret == 0) {
1117 		ret = pthread_mutex_init(&_smhba_AE_mutex, NULL);
1118 	}
1119 	if (ret == 0) {
1120 		ret = pthread_mutex_init(&_smhba_APE_mutex, NULL);
1121 	}
1122 	if (ret == 0) {
1123 		ret = pthread_mutex_init(&_smhba_APSE_mutex, NULL);
1124 	}
1125 	if (ret == 0) {
1126 		ret = pthread_mutex_init(&_smhba_TE_mutex, NULL);
1127 	}
1128 	if (ret == 0) {
1129 		ret = pthread_mutex_init(&_hbaapi_LE_mutex, NULL);
1130 	}
1131 	if (ret != 0) {
1132 		perror("pthread_mutex_init - HBA_LoadLibrary");
1133 		RELEASE_MUTEX(&_hbaapi_LL_mutex);
1134 		return (HBA_STATUS_ERROR);
1135 	}
1136 	RELEASE_MUTEX(&_hbaapi_LL_mutex);
1137 #elif defined(WIN32)
1138 	InitializeCriticalSection(&_hbaapi_LL_mutex);
1139 	InitializeCriticalSection(&_hbaapi_AL_mutex);
1140 	InitializeCriticalSection(&_hbaapi_AAE_mutex);
1141 	InitializeCriticalSection(&_hbaapi_AE_mutex);
1142 	InitializeCriticalSection(&_hbaapi_APE_mutex);
1143 	InitializeCriticalSection(&_hbaapi_APSE_mutex);
1144 	InitializeCriticalSection(&_hbaapi_TE_mutex);
1145 	InitializeCriticalSection(&_hbaapi_LE_mutex);
1146 	InitializeCriticalSection(&_smhba_AAE_mutex);
1147 	InitializeCriticalSection(&_smhba_AE_mutex);
1148 	InitializeCriticalSection(&_smhba_APE_mutex);
1149 	InitializeCriticalSection(&_smhba_APSE_mutex);
1150 	InitializeCriticalSection(&_smhba_TE_mutex);
1151 #endif
1152 
1153 	return (HBA_STATUS_OK);
1154 }
1155 
1156 HBA_STATUS
1157 HBA_FreeLibrary() {
1158     HBAFreeLibraryFunc	FreeLibraryFunc;
1159 /* LINTED E_FUNC_SET_NOT_USED */
1160     HBA_STATUS		status;
1161     HBA_LIBRARY_INFO	*lib_infop;
1162     HBA_LIBRARY_INFO	*lib_next;
1163     HBA_ADAPTERCALLBACK_ELEM
1164 			***listp;
1165     HBA_ADAPTER_INFO	*adapt_infop;
1166     HBA_ADAPTER_INFO	*adapt_next;
1167 
1168     GRAB_MUTEX(&_hbaapi_LL_mutex);
1169     if (_hbaapi_librarylist == NULL) {
1170 	RELEASE_MUTEX(&_hbaapi_LL_mutex);
1171 	return (HBA_STATUS_ERROR_NOT_LOADED);
1172 	}
1173 
1174     GRAB_MUTEX(&_hbaapi_AL_mutex);
1175 
1176     DEBUG(1, "HBA_FreeLibrary()", 0, 0, 0);
1177     for (lib_infop = _hbaapi_librarylist; lib_infop != NULL;
1178 	    lib_infop = lib_next) {
1179 	lib_next = lib_infop->next;
1180 	if (lib_infop->status == HBA_LIBRARY_LOADED) {
1181 	    FreeLibraryFunc = FUNCCOMMON(lib_infop, FreeLibraryHandler);
1182 	    if (FreeLibraryFunc != NULL) {
1183 		/* Free this library */
1184 		status = ((FreeLibraryFunc)());
1185 		DEBUG(1, "HBA_FreeLibrary() Failed %d", status, 0, 0);
1186 	    }
1187 #ifdef WIN32
1188 	    FreeLibrary(lib_infop->hLibrary);	/* Unload DLL from memory */
1189 #else
1190 	    (void) dlclose(lib_infop->hLibrary); /* Unload DLL from memory */
1191 #endif
1192 	}
1193 #ifndef WIN32
1194 	free(lib_infop->LibraryName);
1195 #endif
1196 	free(lib_infop->LibraryPath);
1197 	free(lib_infop);
1198 
1199 	}
1200     _hbaapi_librarylist = NULL;
1201 	/*
1202 	 * OK, now all functions are disabled except for LoadLibrary,
1203 	 * Hope no other thread calls it before we have returned
1204 	 */
1205     _hbaapi_total_library_count = 0;
1206 
1207     for (adapt_infop = _hbaapi_adapterlist;
1208 	    adapt_infop != NULL;
1209 	    adapt_infop = adapt_next) {
1210 		adapt_next = adapt_infop->next;
1211 		free(adapt_infop->name);
1212 		free(adapt_infop);
1213 	}
1214     _hbaapi_adapterlist = NULL;
1215     _hbaapi_total_adapter_count = 0;
1216 
1217 	/*
1218 	 * Free up the callbacks, this is not the most efficient, but it works
1219 	 */
1220 	while ((volatile HBA_ADAPTERCALLBACK_ELEM *)
1221 	    _hbaapi_adapteraddevents_callback_list
1222 	    != NULL) {
1223 	(void) local_remove_callback((HBA_CALLBACKHANDLE)
1224 	    _hbaapi_adapteraddevents_callback_list);
1225 	}
1226 	while ((volatile HBA_ADAPTERCALLBACK_ELEM *)
1227 	    _smhba_adapteraddevents_callback_list
1228 	    != NULL) {
1229 	(void) local_remove_callback((HBA_CALLBACKHANDLE)
1230 	    _smhba_adapteraddevents_callback_list);
1231 	}
1232     for (listp = cb_lists_array; *listp != NULL; listp++) {
1233 	while ((volatile HBA_ADAPTERCALLBACK_ELEM ***)**listp != NULL) {
1234 	    (void) local_remove_callback((HBA_CALLBACKHANDLE)**listp);
1235 	}
1236 	}
1237 
1238     RELEASE_MUTEX(&_hbaapi_AL_mutex);
1239     RELEASE_MUTEX(&_hbaapi_LL_mutex);
1240 
1241 #ifdef USESYSLOG
1242     closelog();
1243 #endif
1244 #ifdef USELOGFILE
1245     if (_hbaapi_debug_fd != NULL) {
1246 	fclose(_hbaapi_debug_fd);
1247 	}
1248     _hbaapi_debug_fd = NULL;
1249 #endif
1250 #ifdef POSIX_THREADS
1251 	/* this will unlock them as well, but who cares */
1252 	(void) pthread_mutex_destroy(&_hbaapi_LE_mutex);
1253 	(void) pthread_mutex_destroy(&_hbaapi_TE_mutex);
1254 	(void) pthread_mutex_destroy(&_hbaapi_APSE_mutex);
1255 	(void) pthread_mutex_destroy(&_hbaapi_APE_mutex);
1256 	(void) pthread_mutex_destroy(&_hbaapi_AE_mutex);
1257 	(void) pthread_mutex_destroy(&_hbaapi_AAE_mutex);
1258 	(void) pthread_mutex_destroy(&_smhba_TE_mutex);
1259 	(void) pthread_mutex_destroy(&_smhba_APSE_mutex);
1260 	(void) pthread_mutex_destroy(&_smhba_APE_mutex);
1261 	(void) pthread_mutex_destroy(&_smhba_AE_mutex);
1262 	(void) pthread_mutex_destroy(&_smhba_AAE_mutex);
1263 	(void) pthread_mutex_destroy(&_hbaapi_AL_mutex);
1264 	(void) pthread_mutex_destroy(&_hbaapi_LL_mutex);
1265 #elif defined(WIN32)
1266     DeleteCriticalSection(&_hbaapi_LL_mutex);
1267     DeleteCriticalSection(&_hbaapi_AL_mutex);
1268     DeleteCriticalSection(&_hbaapi_AAE_mutex);
1269     DeleteCriticalSection(&_hbaapi_AE_mutex);
1270     DeleteCriticalSection(&_hbaapi_APE_mutex);
1271     DeleteCriticalSection(&_hbaapi_APSE_mutex);
1272     DeleteCriticalSection(&_hbaapi_TE_mutex);
1273     DeleteCriticalSection(&_hbaapi_LE_mutex);
1274     DeleteCriticalSection(&_smhba_TE_mutex);
1275     DeleteCriticalSection(&_smhba_APSE_mutex);
1276     DeleteCriticalSection(&_smhba_APE_mutex);
1277     DeleteCriticalSection(&_smhba_AE_mutex);
1278     DeleteCriticalSection(&_smhba_AAE_mutex);
1279 #endif
1280 
1281 	return (HBA_STATUS_OK);
1282 }
1283 
1284 /*
1285  * The API used to use fixed size tables as its primary data structure.
1286  * Indexing from 1 to N identified each adapters.  Now the adapters are
1287  * on a linked list.  There is a unique "index" foreach each adapter.
1288  * Adapters always keep their index, even if they are removed from the
1289  * hardware.  The only time the indexing is reset is on HBA_FreeLibrary
1290  */
1291 HBA_UINT32
1292 HBA_GetNumberOfAdapters()
1293 {
1294 	int j = 0;
1295 	HBA_LIBRARY_INFO	*lib_infop;
1296 	HBAGetNumberOfAdaptersFunc GetNumberOfAdaptersFunc;
1297 	HBAGetAdapterNameFunc GetAdapterNameFunc;
1298 	HBA_BOOLEAN		found_name;
1299 	HBA_ADAPTER_INFO	*adapt_infop;
1300 	HBA_STATUS		status;
1301 
1302 	char adaptername[256];
1303 	int num_adapters; /* local */
1304 
1305 	if (_hbaapi_librarylist == NULL) {
1306 		return (0);
1307 	}
1308 	GRAB_MUTEX(&_hbaapi_LL_mutex); /* pay attention to order */
1309 	GRAB_MUTEX(&_hbaapi_AL_mutex);
1310 
1311 	for (lib_infop = _hbaapi_librarylist;
1312 	    lib_infop != NULL;
1313 	    lib_infop = lib_infop->next) {
1314 
1315 	if (lib_infop->status != HBA_LIBRARY_LOADED) {
1316 		continue;
1317 	}
1318 
1319 	GetNumberOfAdaptersFunc =
1320 	    FUNCCOMMON(lib_infop, GetNumberOfAdaptersHandler);
1321 	if (GetNumberOfAdaptersFunc == NULL)  {
1322 		continue;
1323 	}
1324 	num_adapters = ((GetNumberOfAdaptersFunc)());
1325 #ifndef WIN32
1326 	DEBUG(1, "HBAAPI: num_adapters for %s = %d\n",
1327 	    lib_infop->LibraryName, num_adapters, 0);
1328 #else
1329 	DEBUG(1, "HBAAPI: num_adapters for %s = %d\n",
1330 	    lib_infop->LibraryPath, num_adapters, 0);
1331 #endif
1332 
1333 	/* Also get the names of all the adapters here and cache */
1334 	GetAdapterNameFunc = FUNCCOMMON(lib_infop, GetAdapterNameHandler);
1335 	if (GetAdapterNameFunc == NULL) {
1336 		continue;
1337 	}
1338 
1339 	for (j = 0; j < num_adapters; j++) {
1340 		found_name = 0;
1341 		status = (GetAdapterNameFunc)(j, (char *)&adaptername);
1342 		if (status == HBA_STATUS_OK) {
1343 		for (adapt_infop = _hbaapi_adapterlist;
1344 		    adapt_infop != NULL;
1345 		    adapt_infop = adapt_infop->next) {
1346 			/*
1347 			 * check for duplicates, really,
1348 			 * this may just be a second
1349 			 * call to this function
1350 			 * ??? how do we know when a name becomes stale?
1351 			 */
1352 			if (strcmp(adaptername, adapt_infop->name) == 0) {
1353 				/* already got this one */
1354 				found_name++;
1355 			break;
1356 			}
1357 		}
1358 		if (found_name != 0) {
1359 			continue;
1360 		}
1361 		}
1362 
1363 		adapt_infop = (HBA_ADAPTER_INFO *)
1364 		    calloc(1, sizeof (HBA_ADAPTER_INFO));
1365 		if (adapt_infop == NULL) {
1366 #ifndef WIN32
1367 		(void) fprintf(stderr,
1368 		    "HBA_GetNumberOfAdapters: calloc failed"
1369 		    " on sizeof:%lu\n",
1370 		    (unsigned long)(sizeof (HBA_ADAPTER_INFO)));
1371 #endif
1372 		RELEASE_MUTEX(&_hbaapi_AL_mutex);
1373 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex,
1374 		    _hbaapi_total_adapter_count);
1375 		}
1376 		if ((adapt_infop->GNstatus = status) == HBA_STATUS_OK) {
1377 		adapt_infop->name = strdup(adaptername);
1378 		} else {
1379 		char dummyname[512];
1380 		(void) sprintf(dummyname, "NULLADAPTER-%255s-%03d",
1381 		    lib_infop->LibraryPath, _hbaapi_total_adapter_count);
1382 		dummyname[511] = '\0';
1383 		adapt_infop->name = strdup(dummyname);
1384 		}
1385 		lib_infop->numOfAdapters++;
1386 		adapt_infop->library = lib_infop;
1387 		adapt_infop->next = _hbaapi_adapterlist;
1388 		adapt_infop->index = _hbaapi_total_adapter_count;
1389 		_hbaapi_adapterlist = adapt_infop;
1390 		_hbaapi_total_adapter_count++;
1391 	}
1392 	}
1393 	RELEASE_MUTEX(&_hbaapi_AL_mutex);
1394 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, _hbaapi_total_adapter_count);
1395 }
1396 
1397 HBA_STATUS
1398 HBA_GetAdapterName(
1399     HBA_UINT32 adapterindex,
1400     char *adaptername)
1401 {
1402 	HBA_ADAPTER_INFO	*adapt_infop;
1403 	HBA_STATUS		ret = HBA_STATUS_ERROR_ILLEGAL_INDEX;
1404 
1405 	if (adaptername == NULL) {
1406 		DEBUG(1, "HBA_GetAdapterName: NULL pointer adatpername",
1407 		    0, 0, 0);
1408 		return (HBA_STATUS_ERROR_ARG);
1409 	}
1410 
1411 	/*
1412 	 * The adapter index is from old code, but we have
1413 	 * to support it.  Go down the list looking for
1414 	 * the adapter
1415 	 */
1416 	ARE_WE_INITED();
1417 	GRAB_MUTEX(&_hbaapi_AL_mutex);
1418 	*adaptername = '\0';
1419 	for (adapt_infop = _hbaapi_adapterlist;
1420 	    adapt_infop != NULL;
1421 	    adapt_infop = adapt_infop->next) {
1422 
1423 	if (adapt_infop->index == adapterindex) {
1424 		if (adapt_infop->name != NULL &&
1425 		    adapt_infop->GNstatus == HBA_STATUS_OK) {
1426 		(void) strcpy(adaptername, adapt_infop->name);
1427 		} else {
1428 		*adaptername = '\0';
1429 		}
1430 		ret = adapt_infop->GNstatus;
1431 		break;
1432 	}
1433 	}
1434 	DEBUG(2, "GetAdapterName for index:%d ->%s",
1435 	    adapterindex, adaptername, 0);
1436 	RELEASE_MUTEX_RETURN(&_hbaapi_AL_mutex, ret);
1437 }
1438 
1439 HBA_HANDLE
1440 HBA_OpenAdapter(char *adaptername)
1441 {
1442 	HBA_HANDLE		handle;
1443 	HBAOpenAdapterFunc	OpenAdapterFunc;
1444 	HBA_ADAPTER_INFO	*adapt_infop;
1445 	HBA_LIBRARY_INFO	*lib_infop;
1446 
1447 	DEBUG(2, "OpenAdapter: %s", adaptername, 0, 0);
1448 
1449 	handle = HBA_HANDLE_INVALID;
1450 	if (_hbaapi_librarylist == NULL) {
1451 		return (handle);
1452 	}
1453 	if (adaptername == NULL) {
1454 		DEBUG(1, "HBA_OpenAdapter: NULL pointer adatpername",
1455 		    0, 0, 0);
1456 		return (handle);
1457 	}
1458 	GRAB_MUTEX(&_hbaapi_AL_mutex);
1459 	for (adapt_infop = _hbaapi_adapterlist;
1460 	    adapt_infop != NULL;
1461 	    adapt_infop = adapt_infop->next) {
1462 	if (strcmp(adaptername, adapt_infop->name) != 0) {
1463 		continue;
1464 	}
1465 	lib_infop = adapt_infop->library;
1466 	OpenAdapterFunc = FUNCCOMMON(lib_infop, OpenAdapterHandler);
1467 
1468 	if (OpenAdapterFunc != NULL) {
1469 	    /* retrieve the vendor handle */
1470 		handle = (OpenAdapterFunc)(adaptername);
1471 		if (handle != 0) {
1472 		/* or this with the library index to get the common handle */
1473 		handle = HBA_HANDLE_FROM_LOCAL(lib_infop->index, handle);
1474 		}
1475 	}
1476 	break;
1477 	}
1478 	RELEASE_MUTEX_RETURN(&_hbaapi_AL_mutex, handle);
1479 }
1480 
1481 /*
1482  * Finding an adapter with matching WWN.
1483  */
1484 HBA_STATUS
1485 HBA_OpenAdapterByWWN(HBA_HANDLE *phandle, HBA_WWN nodeWWN) {
1486     HBA_HANDLE		handle;
1487     HBA_LIBRARY_INFO	*lib_infop;
1488     HBAGetNumberOfAdaptersFunc
1489 			GetNumberOfAdaptersFunc;
1490     HBAOpenAdapterByWWNFunc
1491 			OpenAdapterFunc;
1492     HBA_STATUS		status;
1493 
1494     DEBUG(2, "OpenAdapterByWWN: %s", WWN2STR1(&nodeWWN), 0, 0);
1495     ARE_WE_INITED();
1496 
1497 	*phandle = HBA_HANDLE_INVALID;
1498 
1499     GRAB_MUTEX(&_hbaapi_LL_mutex);
1500     for (lib_infop = _hbaapi_librarylist;
1501 	    lib_infop != NULL;
1502 	    lib_infop = lib_infop->next) {
1503 
1504 	status = HBA_STATUS_ERROR_ILLEGAL_WWN;
1505 
1506 	if (lib_infop->status != HBA_LIBRARY_LOADED) {
1507 	    continue;
1508 	}
1509 
1510 	/* only for HBAAPIV2 */
1511 	if (lib_infop->version != HBAAPIV2) {
1512 	    continue;
1513 	}
1514 
1515 	GetNumberOfAdaptersFunc =
1516 		FUNCCOMMON(lib_infop, GetNumberOfAdaptersHandler);
1517 	if (GetNumberOfAdaptersFunc == NULL)  {
1518 	    continue;
1519 	}
1520 
1521 	/* look for new hardware */
1522 	(void) ((GetNumberOfAdaptersFunc)());
1523 
1524 	OpenAdapterFunc =
1525 	    lib_infop->ftable.functionTable.OpenAdapterByWWNHandler;
1526 	if (OpenAdapterFunc == NULL) {
1527 	    continue;
1528 	}
1529 	/*
1530 	 * We do not know if the WWN is known by this vendor,
1531 	 * just try it
1532 	 */
1533 	if ((status = (OpenAdapterFunc)(&handle, nodeWWN)) != HBA_STATUS_OK) {
1534 	    continue;
1535 	}
1536 	/* OK, make a vendor non-specific handle */
1537 	*phandle = HBA_HANDLE_FROM_LOCAL(lib_infop->index, handle);
1538 	status = HBA_STATUS_OK;
1539 	break;
1540 	}
1541     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1542 }
1543 
1544 void
1545 HBA_RefreshAdapterConfiguration() {
1546     DEBUG(2, "HBA_RefreshAdapterConfiguration", 0, 0, 0);
1547 	(void) HBA_GetNumberOfAdapters();
1548 }
1549 
1550 HBA_UINT32
1551 HBA_GetVersion() {
1552     DEBUG(2, "HBA_GetVersion", 0, 0, 0);
1553 	return (HBA_LIBVERSION);
1554 }
1555 
1556 /*
1557  * This function is VERY OS dependent.  Wing it as best you can.
1558  */
1559 HBA_UINT32
1560 HBA_GetWrapperLibraryAttributes(
1561     HBA_LIBRARYATTRIBUTES *attributes)
1562 {
1563 
1564 	DEBUG(2, "HBA_GetWrapperLibraryAttributes", 0, 0, 0);
1565 
1566 	if (attributes == NULL) {
1567 		DEBUG(1, "HBA_GetWrapperLibraryAttributes:"
1568 		    "NULL pointer attributes",
1569 		    0, 0, 0);
1570 		return (HBA_STATUS_ERROR_ARG);
1571 	}
1572 
1573 	(void) memset(attributes, 0, sizeof (HBA_LIBRARYATTRIBUTES));
1574 
1575 #if defined(SOLARIS)
1576 	if ((handle = dlopen("libHBAAPI.so", RTLD_NOW)) != NULL) {
1577 	if (dlinfo(handle, RTLD_DI_LINKMAP, &map) >= 0) {
1578 		for (mp = map; mp != NULL; mp = mp->l_next) {
1579 		if (strlen(map->l_name) < 256) {
1580 			(void) strcpy(attributes->LibPath, map->l_name);
1581 		}
1582 		}
1583 	}
1584 	}
1585 #elif defined(WIN32)
1586 	HMODULE module;
1587 
1588 	/* No need to do anything with the module handle */
1589 	/* It wasn't alloocated so it doesn't need to be freed */
1590 	module = GetModuleHandle("HBAAPI");
1591 	if (module != NULL) {
1592 		if (GetModuleFileName(module, attributes->LibPath,
1593 		    sizeof (attributes->LibPath)) == 0) {
1594 			attributes->LibPath[0] = '\0';
1595 		}
1596 	}
1597 #endif
1598 #if defined(VENDOR)
1599 	(void) strcpy(attributes->VName, VENDOR);
1600 #else
1601 	attributes->VName[0] = '\0';
1602 #endif
1603 #if defined(VERSION)
1604 	(void) strcpy(attributes->VVersion, VERSION);
1605 #else
1606 	attributes->VVersion[0] = '\0';
1607 #endif
1608 #if defined(BUILD_DATE)
1609 #if defined(WIN32)
1610 	int matchCount;
1611 	matchCount = sscanf(BUILD_DATE, "%u/%u/%u %u:%u:%u",
1612 	    &attributes->build_date.tm_year,
1613 	    &attributes->build_date.tm_mon,
1614 	    &attributes->build_date.tm_mday,
1615 	    &attributes->build_date.tm_hour,
1616 	    &attributes->build_date.tm_min,
1617 	    &attributes->build_date.tm_sec);
1618 
1619 	if (matchCount != 6) {
1620 		memset(&attributes->build_date, 0, sizeof (struct tm));
1621 	} else {
1622 		attributes->build_date.tm_year -= 1900;
1623 		attributes->build_date.tm_isdst = -1;
1624 	}
1625 #else
1626 	if (strptime(BUILD_DATE,
1627 	    "%Y/%m/%d %T %Z", &(attributes->build_date)) == NULL) {
1628 		(void) memset(&attributes->build_date, 0, sizeof (struct tm));
1629 	}
1630 #endif
1631 #else
1632 	(void) memset(&attributes->build_date, 0, sizeof (struct tm));
1633 #endif
1634 	return (2);
1635 }
1636 
1637 /*
1638  * Callback registation and handling
1639  */
1640 HBA_STATUS
1641 HBA_RemoveCallback(HBA_CALLBACKHANDLE cbhandle) {
1642     HBA_STATUS	status;
1643 
1644     DEBUG(2, "HBA_RemoveCallback", 0, 0, 0);
1645     ARE_WE_INITED();
1646 
1647     GRAB_MUTEX(&_hbaapi_LL_mutex);
1648     status = local_remove_callback(cbhandle);
1649     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1650 }
1651 
1652 /* Adapter Add Events ************************************************* */
1653 static void
1654 /* LINTED E_FUNC_ARG_UNUSED */
1655 adapteraddevents_callback(void *data, HBA_WWN PortWWN, HBA_UINT32 eventType) {
1656     HBA_ALLADAPTERSCALLBACK_ELEM	*cbp;
1657 
1658     DEBUG(3, "AddAdapterEvent, port: %s", WWN2STR1(&PortWWN), 0, 0);
1659 
1660     GRAB_MUTEX(&_hbaapi_AAE_mutex);
1661     for (cbp = _hbaapi_adapteraddevents_callback_list;
1662 	    cbp != NULL;
1663 	    cbp = cbp->next) {
1664 	(*cbp->callback)(data, PortWWN, HBA_EVENT_ADAPTER_ADD);
1665 	}
1666     RELEASE_MUTEX(&_hbaapi_AAE_mutex);
1667 
1668 }
1669 
1670 HBA_STATUS
1671 HBA_RegisterForAdapterAddEvents(
1672     void		(*callback)(
1673 	void		*data,
1674 	HBA_WWN		PortWWN,
1675 	HBA_UINT32	eventType),
1676 	void		*userData,
1677     HBA_CALLBACKHANDLE *callbackHandle) {
1678 
1679     HBA_ALLADAPTERSCALLBACK_ELEM	*cbp;
1680     HBA_VENDORCALLBACK_ELEM		*vcbp;
1681     HBA_VENDORCALLBACK_ELEM		*vendorhandlelist;
1682     HBARegisterForAdapterAddEventsFunc	registeredfunc;
1683     HBA_STATUS				status = HBA_STATUS_OK;
1684     HBA_STATUS				failure = HBA_STATUS_OK;
1685     HBA_LIBRARY_INFO			*lib_infop;
1686     int					registered_cnt = 0;
1687     int					vendor_cnt = 0;
1688     int					not_supported_cnt = 0;
1689     int					status_OK_bar_cnt = 0;
1690     int					status_OK_cnt = 0;
1691 
1692     DEBUG(2, "HBA_RegisterForAdapterAddEvents", 0, 0, 0);
1693     ARE_WE_INITED();
1694 
1695     cbp = (HBA_ALLADAPTERSCALLBACK_ELEM *)
1696 	calloc(1, sizeof (HBA_ALLADAPTERSCALLBACK_ELEM));
1697 	*callbackHandle = (HBA_CALLBACKHANDLE) cbp;
1698 	if (cbp == NULL) {
1699 #ifndef WIN32
1700 	(void) fprintf(stderr,
1701 		"HBA_RegisterForAdapterAddEvents: calloc failed "
1702 		"for %lu bytes\n",
1703 		(unsigned long)(sizeof (HBA_ALLADAPTERSCALLBACK_ELEM)));
1704 #endif
1705 	return (HBA_STATUS_ERROR);
1706 	}
1707 
1708     GRAB_MUTEX(&_hbaapi_LL_mutex);
1709     GRAB_MUTEX(&_hbaapi_AAE_mutex);
1710     cbp->callback = callback;
1711     cbp->next = _hbaapi_adapteraddevents_callback_list;
1712     _hbaapi_adapteraddevents_callback_list = cbp;
1713 	/*
1714 	 * Need to release the mutex now incase the vendor function invokes the
1715 	 * callback.  We will grap the mutex later to attach the vendor handle
1716 	 * list to the callback structure
1717 	 */
1718     RELEASE_MUTEX(&_hbaapi_AAE_mutex);
1719 
1720 	/*
1721 	 * now create a list of vendors (vendor libraryies, NOT ADAPTERS)
1722 	 * that have successfully registerred
1723 	 */
1724 	vendorhandlelist = NULL;
1725     for (lib_infop = _hbaapi_librarylist;
1726 	    lib_infop != NULL;
1727 	    lib_infop = lib_infop->next) {
1728 
1729 	/* only for HBAAPI V2 */
1730 	if ((lib_infop->version != HBAAPIV2)) {
1731 	    continue;
1732 	} else {
1733 	    vendor_cnt++;
1734 	}
1735 
1736 	registeredfunc =
1737 	    lib_infop->ftable.functionTable.RegisterForAdapterAddEventsHandler;
1738 	if (registeredfunc == NULL) {
1739 	    continue;
1740 	}
1741 
1742 	vcbp = (HBA_VENDORCALLBACK_ELEM *)
1743 	    calloc(1, sizeof (HBA_VENDORCALLBACK_ELEM));
1744 	if (vcbp == NULL) {
1745 #ifndef WIN32
1746 	    (void) fprintf(stderr,
1747 		    "HBA_RegisterForAdapterAddEvents: "
1748 		    "calloc failed for %lu bytes\n",
1749 		    (unsigned long)(sizeof (HBA_VENDORCALLBACK_ELEM)));
1750 #endif
1751 	    freevendorhandlelist(vendorhandlelist);
1752 	    status = HBA_STATUS_ERROR;
1753 	    break;
1754 	}
1755 
1756 	registered_cnt++;
1757 	status = (registeredfunc)(adapteraddevents_callback,
1758 	    userData, &vcbp->vendorcbhandle);
1759 	if (status == HBA_STATUS_ERROR_NOT_SUPPORTED) {
1760 	    not_supported_cnt++;
1761 	    free(vcbp);
1762 	    continue;
1763 	} else if (status != HBA_STATUS_OK) {
1764 	    status_OK_bar_cnt++;
1765 	    DEBUG(1,
1766 		    "HBA_RegisterForAdapterAddEvents: Library->%s, Error->%d",
1767 		    lib_infop->LibraryPath, status, 0);
1768 #ifndef WIN32
1769 	    (void) fprintf(stderr,
1770 		    "HBA_RegisterForAdapterAddEvents: Library->%s, Error->%d",
1771 		    lib_infop->LibraryPath, status);
1772 #endif
1773 	    failure = status;
1774 	    free(vcbp);
1775 	    continue;
1776 	} else {
1777 	    status_OK_cnt++;
1778 	}
1779 	vcbp->lib_info = lib_infop;
1780 	vcbp->next = vendorhandlelist;
1781 	vendorhandlelist = vcbp;
1782 	}
1783     if (vendor_cnt == 0) {
1784 	/* no HBAAPIV2 is deteced.  should be okay? */
1785 	status = HBA_STATUS_ERROR;
1786 	} else if (registered_cnt == 0) {
1787 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
1788 	freevendorhandlelist(vendorhandlelist);
1789 	(void) local_remove_callback((HBA_CALLBACKHANDLE) cbp);
1790 	} else if (status_OK_cnt == 0 && not_supported_cnt != 0) {
1791 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
1792 	} else if (status_OK_cnt == 0) {
1793 	/*
1794 	 * At least one vendor library registered this function, but no
1795 	 * vendor call succeeded
1796 	 */
1797 	(void) local_remove_callback((HBA_CALLBACKHANDLE) cbp);
1798 	status = failure;
1799 	} else {
1800 	/* we have had atleast some success, now finish up */
1801 	GRAB_MUTEX(&_hbaapi_AAE_mutex);
1802 	/*
1803 	 * this seems silly, but what if another thread called
1804 	 * the callback remove
1805 	 */
1806 	for (cbp = _hbaapi_adapteraddevents_callback_list;
1807 	    cbp != NULL; cbp = cbp->next) {
1808 	    if ((HBA_CALLBACKHANDLE)cbp == *callbackHandle) {
1809 		/* yup, its still there, hooray */
1810 		cbp->vendorhandlelist = vendorhandlelist;
1811 		vendorhandlelist = NULL;
1812 		break;
1813 	    }
1814 	}
1815 	RELEASE_MUTEX(&_hbaapi_AAE_mutex);
1816 	if (vendorhandlelist != NULL) {
1817 		/*
1818 		 * bummer, somebody removed the callback before we finished
1819 		 * registration, probably will never happen
1820 		 */
1821 	    freevendorhandlelist(vendorhandlelist);
1822 	    DEBUG(1,
1823 		    "HBA_RegisterForAdapterAddEvents: HBA_RemoveCallback was "
1824 		    "called for a handle before registration was finished.",
1825 		    0, 0, 0);
1826 	    status = HBA_STATUS_ERROR;
1827 	} else {
1828 	    status = HBA_STATUS_OK;
1829 	}
1830 	}
1831     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1832 }
1833 
1834 /* Adapter Events (other than add) ************************************** */
1835 static void
1836 adapterevents_callback(void *data,
1837 			HBA_WWN PortWWN,
1838 			HBA_UINT32 eventType) {
1839     HBA_ADAPTERCALLBACK_ELEM	*acbp;
1840 
1841     DEBUG(3, "AdapterEvent, port:%s, eventType:%d", WWN2STR1(&PortWWN),
1842 	    eventType, 0);
1843 
1844 	GRAB_MUTEX(&_hbaapi_AE_mutex);
1845 	for (acbp = _hbaapi_adapterevents_callback_list;
1846 	acbp != NULL;
1847 	acbp = acbp->next) {
1848 	if (data == (void *)acbp) {
1849 	    (*acbp->callback)(acbp->userdata, PortWWN, eventType);
1850 	    break;
1851 	}
1852 	}
1853     RELEASE_MUTEX(&_hbaapi_AE_mutex);
1854 }
1855 HBA_STATUS
1856 HBA_RegisterForAdapterEvents(
1857     void		(*callback) (
1858 	void		*data,
1859 	HBA_WWN		PortWWN,
1860 	HBA_UINT32	eventType),
1861     void		*userData,
1862     HBA_HANDLE		handle,
1863     HBA_CALLBACKHANDLE	*callbackHandle) {
1864 
1865     HBA_ADAPTERCALLBACK_ELEM		*acbp;
1866     HBARegisterForAdapterEventsFunc	registeredfunc;
1867     HBA_STATUS				status;
1868     HBA_LIBRARY_INFO			*lib_infop;
1869     HBA_HANDLE				vendorHandle;
1870 
1871     DEBUG(2, "HBA_RegisterForAdapterEvents", 0, 0, 0);
1872 
1873     CHECKLIBRARYANDVERSION(HBAAPIV2);
1874 
1875 	/* we now have the _hbaapi_LL_mutex */
1876 
1877     registeredfunc =
1878 	    lib_infop->ftable.functionTable.RegisterForAdapterEventsHandler;
1879     if (registeredfunc == NULL) {
1880 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
1881 	}
1882 
1883 	/*
1884 	 * that allocated memory is used both as the handle for the
1885 	 * caller, and as userdata to the vendor call so that on
1886 	 * callback the specific registration may be recalled
1887 	 */
1888     acbp = (HBA_ADAPTERCALLBACK_ELEM *)
1889 	calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
1890     if (acbp == NULL) {
1891 #ifndef WIN32
1892 	(void) fprintf(stderr,
1893 		"HBA_RegisterForAdapterEvents: calloc failed for %lu bytes\n",
1894 		(unsigned long)(sizeof (HBA_ADAPTERCALLBACK_ELEM)));
1895 #endif
1896 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
1897 	}
1898 	*callbackHandle = (HBA_CALLBACKHANDLE) acbp;
1899     acbp->callback = callback;
1900     acbp->userdata = userData;
1901     acbp->lib_info = lib_infop;
1902 
1903     status = (registeredfunc)(adapterevents_callback,
1904 	    (void *)acbp,
1905 	    vendorHandle,
1906 	    &acbp->vendorcbhandle);
1907     if (status != HBA_STATUS_OK) {
1908 	free(acbp);
1909 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1910 	}
1911 
1912     GRAB_MUTEX(&_hbaapi_AE_mutex);
1913     acbp->next = _hbaapi_adapterevents_callback_list;
1914     _hbaapi_adapterevents_callback_list = acbp;
1915     RELEASE_MUTEX(&_hbaapi_AE_mutex);
1916 
1917     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
1918 }
1919 
1920 /* Adapter Port Events ************************************************** */
1921 static void
1922 adapterportevents_callback(void *data,
1923 			    HBA_WWN PortWWN,
1924 			    HBA_UINT32 eventType,
1925 			    HBA_UINT32 fabricPortID) {
1926     HBA_ADAPTERCALLBACK_ELEM	*acbp;
1927 
1928     DEBUG(3, "AdapterPortEvent, port:%s, eventType:%d fabricPortID:0X%06x",
1929 	    WWN2STR1(&PortWWN), eventType, fabricPortID);
1930 
1931     GRAB_MUTEX(&_hbaapi_APE_mutex);
1932 
1933     for (acbp = _hbaapi_adapterportevents_callback_list;
1934 	acbp != NULL;
1935 	acbp = acbp->next) {
1936 	if (data == (void *)acbp) {
1937 	    (*acbp->callback)(acbp->userdata, PortWWN, eventType, fabricPortID);
1938 	    break;
1939 	}
1940 	}
1941     RELEASE_MUTEX(&_hbaapi_APE_mutex);
1942 }
1943 
1944 HBA_STATUS
1945 HBA_RegisterForAdapterPortEvents(
1946     void		(*callback) (
1947 	void		*data,
1948 	HBA_WWN		PortWWN,
1949 	HBA_UINT32	eventType,
1950 	HBA_UINT32	fabricPortID),
1951     void		*userData,
1952     HBA_HANDLE		handle,
1953     HBA_WWN		PortWWN,
1954     HBA_CALLBACKHANDLE	*callbackHandle) {
1955 
1956     HBA_ADAPTERCALLBACK_ELEM		*acbp;
1957     HBARegisterForAdapterPortEventsFunc	registeredfunc;
1958     HBA_STATUS				status;
1959     HBA_LIBRARY_INFO			*lib_infop;
1960     HBA_HANDLE				vendorHandle;
1961 
1962     DEBUG(2, "HBA_RegisterForAdapterPortEvents for port: %s",
1963 	    WWN2STR1(&PortWWN), 0, 0);
1964 
1965     CHECKLIBRARYANDVERSION(HBAAPIV2);
1966 	/* we now have the _hbaapi_LL_mutex */
1967 
1968 	registeredfunc =
1969 	lib_infop->ftable.functionTable.RegisterForAdapterPortEventsHandler;
1970     if (registeredfunc == NULL) {
1971 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
1972 	}
1973 
1974 	/*
1975 	 * that allocated memory is used both as the handle for the
1976 	 * caller, and as userdata to the vendor call so that on
1977 	 * callback the specific registration may be recalled
1978 	 */
1979 	acbp = (HBA_ADAPTERCALLBACK_ELEM *)
1980 	calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
1981     if (acbp == NULL) {
1982 #ifndef WIN32
1983 	(void) fprintf(stderr,
1984 		"HBA_RegisterForAdapterPortEvents: "
1985 		"calloc failed for %lu bytes\n",
1986 		(unsigned long)(sizeof (HBA_ADAPTERCALLBACK_ELEM)));
1987 #endif
1988 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
1989 
1990 	}
1991 	*callbackHandle = (HBA_CALLBACKHANDLE) acbp;
1992     acbp->callback = callback;
1993     acbp->userdata = userData;
1994     acbp->lib_info = lib_infop;
1995 
1996     status = (registeredfunc)(adapterportevents_callback,
1997 	    (void *)acbp,
1998 	    vendorHandle,
1999 	    PortWWN,
2000 	    &acbp->vendorcbhandle);
2001     if (status != HBA_STATUS_OK) {
2002 	free(acbp);
2003 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2004 	}
2005 
2006     GRAB_MUTEX(&_hbaapi_APE_mutex);
2007     acbp->next = _hbaapi_adapterportevents_callback_list;
2008     _hbaapi_adapterportevents_callback_list = acbp;
2009     RELEASE_MUTEX(&_hbaapi_APE_mutex);
2010 
2011     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
2012 }
2013 
2014 /* Adapter State Events ************************************************ */
2015 static void
2016 adapterportstatevents_callback(void *data,
2017 				HBA_WWN PortWWN,
2018 				HBA_UINT32 eventType) {
2019     HBA_ADAPTERCALLBACK_ELEM	*acbp;
2020 
2021 	DEBUG(3, "AdapterPortStatEvent, port:%s, eventType:%d",
2022 	    WWN2STR1(&PortWWN),
2023 	    eventType, 0);
2024 
2025     GRAB_MUTEX(&_hbaapi_APSE_mutex);
2026     for (acbp = _hbaapi_adapterportstatevents_callback_list;
2027 	acbp != NULL;
2028 	acbp = acbp->next) {
2029 	if (data == (void *)acbp) {
2030 	    (*acbp->callback)(acbp->userdata, PortWWN, eventType);
2031 	    return;
2032 	}
2033 	}
2034     RELEASE_MUTEX(&_hbaapi_APSE_mutex);
2035 }
2036 HBA_STATUS
2037 HBA_RegisterForAdapterPortStatEvents(
2038     void		(*callback) (
2039 	void		*data,
2040 	HBA_WWN		PortWWN,
2041 	HBA_UINT32	eventType),
2042     void		*userData,
2043     HBA_HANDLE		handle,
2044     HBA_WWN		PortWWN,
2045     HBA_PORTSTATISTICS	stats,
2046     HBA_UINT32		statType,
2047     HBA_CALLBACKHANDLE	*callbackHandle) {
2048 
2049     HBA_ADAPTERCALLBACK_ELEM	*acbp;
2050     HBARegisterForAdapterPortStatEventsFunc
2051 				registeredfunc;
2052     HBA_STATUS			status;
2053     HBA_LIBRARY_INFO		*lib_infop;
2054     HBA_HANDLE			vendorHandle;
2055 
2056     DEBUG(2, "HBA_RegisterForAdapterPortStatEvents for port: %s",
2057 	    WWN2STR1(&PortWWN), 0, 0);
2058 
2059     CHECKLIBRARYANDVERSION(HBAAPIV2);
2060 	/* we now have the _hbaapi_LL_mutex */
2061 
2062     registeredfunc =
2063 	lib_infop->ftable.functionTable.RegisterForAdapterPortStatEventsHandler;
2064     if (registeredfunc == NULL) {
2065 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
2066 	}
2067 
2068 	/*
2069 	 * that allocated memory is used both as the handle for the
2070 	 * caller, and as userdata to the vendor call so that on
2071 	 * callback the specific registration may be recalled
2072 	 */
2073     acbp = (HBA_ADAPTERCALLBACK_ELEM *)
2074 	calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
2075     if (acbp == NULL) {
2076 #ifndef WIN32
2077 	(void) fprintf(stderr,
2078 		"HBA_RegisterForAdapterPortStatEvents: "
2079 		"calloc failed for %lu bytes\n",
2080 		(unsigned long)(sizeof (HBA_ADAPTERCALLBACK_ELEM)));
2081 #endif
2082 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
2083 	}
2084 	*callbackHandle = (HBA_CALLBACKHANDLE) acbp;
2085     acbp->callback = callback;
2086     acbp->userdata = userData;
2087     acbp->lib_info = lib_infop;
2088 
2089     status = (registeredfunc)(adapterportstatevents_callback,
2090 	    (void *)acbp,
2091 	    vendorHandle,
2092 	    PortWWN,
2093 	    stats,
2094 	    statType,
2095 	    &acbp->vendorcbhandle);
2096     if (status != HBA_STATUS_OK) {
2097 	free(acbp);
2098 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2099 	}
2100 
2101     GRAB_MUTEX(&_hbaapi_APSE_mutex);
2102     acbp->next = _hbaapi_adapterportstatevents_callback_list;
2103     _hbaapi_adapterportstatevents_callback_list = acbp;
2104     RELEASE_MUTEX(&_hbaapi_APSE_mutex);
2105 
2106     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
2107 }
2108 
2109 /* Target Events ******************************************************* */
2110 static void
2111 targetevents_callback(void *data,
2112     HBA_WWN hbaPortWWN,
2113     HBA_WWN discoveredPortWWN,
2114     HBA_UINT32 eventType) {
2115 
2116 	HBA_ADAPTERCALLBACK_ELEM	*acbp;
2117 
2118     DEBUG(3, "TargetEvent, hbaPort:%s, discoveredPort:%s eventType:%d",
2119 	    WWN2STR1(&hbaPortWWN), WWN2STR2(&discoveredPortWWN), eventType);
2120 
2121     GRAB_MUTEX(&_hbaapi_TE_mutex);
2122     for (acbp = _hbaapi_targetevents_callback_list;
2123 	acbp != NULL;
2124 	acbp = acbp->next) {
2125 	if (data == (void *)acbp) {
2126 	    (*acbp->callback)(acbp->userdata, hbaPortWWN,
2127 	    discoveredPortWWN, eventType);
2128 	    break;
2129 	}
2130 	}
2131     RELEASE_MUTEX(&_hbaapi_TE_mutex);
2132 }
2133 
2134 HBA_STATUS
2135 HBA_RegisterForTargetEvents(
2136     void		(*callback) (
2137 	void		*data,
2138 	HBA_WWN		hbaPortWWN,
2139 	HBA_WWN		discoveredPortWWN,
2140 	HBA_UINT32	eventType),
2141     void		*userData,
2142     HBA_HANDLE		handle,
2143     HBA_WWN		hbaPortWWN,
2144     HBA_WWN		discoveredPortWWN,
2145     HBA_CALLBACKHANDLE	*callbackHandle,
2146     HBA_UINT32		allTargets) {
2147 
2148     HBA_ADAPTERCALLBACK_ELEM
2149 			*acbp;
2150     HBARegisterForTargetEventsFunc
2151 			registeredfunc;
2152     HBA_STATUS		status;
2153     HBA_LIBRARY_INFO	*lib_infop;
2154     HBA_HANDLE		vendorHandle;
2155 
2156     DEBUG(2, "HBA_RegisterForTargetEvents, hbaPort: %s, discoveredPort: %s",
2157 	    WWN2STR1(&hbaPortWWN), WWN2STR2(&discoveredPortWWN), 0);
2158 
2159     CHECKLIBRARYANDVERSION(HBAAPIV2);
2160 	/* we now have the _hbaapi_LL_mutex */
2161 
2162     registeredfunc =
2163 	    lib_infop->ftable.functionTable.RegisterForTargetEventsHandler;
2164     if (registeredfunc == NULL) {
2165 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
2166 	}
2167 
2168 	/*
2169 	 * that allocated memory is used both as the handle for the
2170 	 * caller, and as userdata to the vendor call so that on
2171 	 * callback the specific registration may be recalled
2172 	 */
2173 	acbp = (HBA_ADAPTERCALLBACK_ELEM *)
2174 	calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
2175     if (acbp == NULL) {
2176 #ifndef WIN32
2177 	(void) fprintf(stderr,
2178 		"HBA_RegisterForTargetEvents: calloc failed for %lu bytes\n",
2179 		(unsigned long)(sizeof (HBA_ADAPTERCALLBACK_ELEM)));
2180 #endif
2181 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
2182 	}
2183 	*callbackHandle = (HBA_CALLBACKHANDLE) acbp;
2184     acbp->callback = callback;
2185     acbp->userdata = userData;
2186     acbp->lib_info = lib_infop;
2187 
2188     status = (registeredfunc)(targetevents_callback,
2189 	    (void *)acbp,
2190 	    vendorHandle,
2191 	    hbaPortWWN,
2192 	    discoveredPortWWN,
2193 	    &acbp->vendorcbhandle,
2194 	    allTargets);
2195     if (status != HBA_STATUS_OK) {
2196 	free(acbp);
2197 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2198 	}
2199 
2200     GRAB_MUTEX(&_hbaapi_TE_mutex);
2201     acbp->next = _hbaapi_targetevents_callback_list;
2202     _hbaapi_targetevents_callback_list = acbp;
2203     RELEASE_MUTEX(&_hbaapi_TE_mutex);
2204 
2205     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
2206 }
2207 
2208 /* Link Events ********************************************************* */
2209 static void
2210 linkevents_callback(void *data,
2211     HBA_WWN adapterWWN,
2212     HBA_UINT32 eventType,
2213     void *pRLIRBuffer,
2214     HBA_UINT32 RLIRBufferSize) {
2215 	HBA_ADAPTERCALLBACK_ELEM	*acbp;
2216 
2217     DEBUG(3, "LinkEvent, hbaWWN:%s, eventType:%d",
2218 	    WWN2STR1(&adapterWWN), eventType, 0);
2219 
2220     GRAB_MUTEX(&_hbaapi_LE_mutex);
2221     for (acbp = _hbaapi_linkevents_callback_list;
2222 	acbp != NULL;
2223 	acbp = acbp->next) {
2224 	if (data == (void *)acbp) {
2225 	    (*acbp->callback)(acbp->userdata, adapterWWN,
2226 		eventType, pRLIRBuffer, RLIRBufferSize);
2227 	    break;
2228 	}
2229 	}
2230     RELEASE_MUTEX(&_hbaapi_LE_mutex);
2231 }
2232 HBA_STATUS
2233 HBA_RegisterForLinkEvents(
2234     void		(*callback) (
2235 	void		*data,
2236 	HBA_WWN		adapterWWN,
2237 	HBA_UINT32	eventType,
2238 	void		*pRLIRBuffer,
2239 	HBA_UINT32	RLIRBufferSize),
2240     void		*userData,
2241     void		*pRLIRBuffer,
2242     HBA_UINT32		RLIRBufferSize,
2243     HBA_HANDLE		handle,
2244     HBA_CALLBACKHANDLE	*callbackHandle) {
2245 
2246     HBA_ADAPTERCALLBACK_ELEM	*acbp;
2247     HBARegisterForLinkEventsFunc
2248 				registeredfunc;
2249     HBA_STATUS			status;
2250     HBA_LIBRARY_INFO		*lib_infop;
2251     HBA_HANDLE			vendorHandle;
2252 
2253     DEBUG(2, "HBA_RegisterForLinkEvents", 0, 0, 0);
2254 
2255     CHECKLIBRARY();
2256 	/* we now have the _hbaapi_LL_mutex */
2257 
2258     registeredfunc = FUNCCOMMON(lib_infop, RegisterForLinkEventsHandler);
2259 
2260     if (registeredfunc == NULL) {
2261 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
2262 	}
2263 
2264 	/*
2265 	 * that allocated memory is used both as the handle for the
2266 	 * caller, and as userdata to the vendor call so that on
2267 	 * callback the specific registration may be recalled
2268 	 */
2269     acbp = (HBA_ADAPTERCALLBACK_ELEM *)
2270 	calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
2271     if (acbp == NULL) {
2272 #ifndef WIN32
2273 	(void) fprintf(stderr,
2274 		"HBA_RegisterForLinkEvents: calloc failed for %lu bytes\n",
2275 		(unsigned long)(sizeof (HBA_ADAPTERCALLBACK_ELEM)));
2276 #endif
2277 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
2278 	}
2279 	*callbackHandle = (HBA_CALLBACKHANDLE) acbp;
2280     acbp->callback = callback;
2281     acbp->userdata = userData;
2282     acbp->lib_info = lib_infop;
2283 
2284     status = (registeredfunc)(linkevents_callback,
2285 	    (void *)acbp,
2286 	    pRLIRBuffer,
2287 	    RLIRBufferSize,
2288 	    vendorHandle,
2289 	    &acbp->vendorcbhandle);
2290     if (status != HBA_STATUS_OK) {
2291 	free(acbp);
2292 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2293 	}
2294 
2295     GRAB_MUTEX(&_hbaapi_LE_mutex);
2296     acbp->next = _hbaapi_linkevents_callback_list;
2297     _hbaapi_linkevents_callback_list = acbp;
2298     RELEASE_MUTEX(&_hbaapi_LE_mutex);
2299 
2300     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
2301 }
2302 
2303 /*
2304  * All of the functions below are almost passthru functions to the
2305  * vendor specific function
2306  */
2307 
2308 void
2309 HBA_CloseAdapter(HBA_HANDLE handle) {
2310     HBA_STATUS		status;
2311     HBA_LIBRARY_INFO	*lib_infop;
2312     HBA_HANDLE		vendorHandle;
2313     HBACloseAdapterFunc CloseAdapterFunc;
2314 
2315     DEBUG(2, "HBA_CloseAdapter", 0, 0, 0);
2316 
2317     status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);
2318     if (status == HBA_STATUS_OK) {
2319 	CloseAdapterFunc = FUNCCOMMON(lib_infop, CloseAdapterHandler);
2320 	if (CloseAdapterFunc != NULL) {
2321 	    ((CloseAdapterFunc)(vendorHandle));
2322 	}
2323 	RELEASE_MUTEX(&_hbaapi_LL_mutex);
2324 	}
2325 }
2326 
2327 HBA_STATUS
2328 HBA_GetAdapterAttributes(
2329     HBA_HANDLE		handle,
2330     HBA_ADAPTERATTRIBUTES
2331 			*hbaattributes)
2332 {
2333 	HBA_STATUS		status;
2334 	HBA_LIBRARY_INFO	*lib_infop;
2335 	HBA_HANDLE		vendorHandle;
2336 	HBAGetAdapterAttributesFunc GetAdapterAttributesFunc;
2337 
2338 	DEBUG(2, "HBA_GetAdapterAttributes", 0, 0, 0);
2339 
2340 	CHECKLIBRARY();
2341 
2342 	if (lib_infop->version == SMHBA) {
2343 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2344 	}
2345 
2346 	GetAdapterAttributesFunc =
2347 	    lib_infop->ftable.functionTable.GetAdapterAttributesHandler;
2348 	if (GetAdapterAttributesFunc != NULL) {
2349 	status = ((GetAdapterAttributesFunc)(vendorHandle, hbaattributes));
2350 	} else {
2351 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2352 	}
2353 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2354 }
2355 
2356 HBA_STATUS
2357 HBA_GetAdapterPortAttributes(
2358     HBA_HANDLE		handle,
2359     HBA_UINT32		portindex,
2360     HBA_PORTATTRIBUTES	*portattributes)
2361 {
2362 	HBA_STATUS		status;
2363 	HBA_LIBRARY_INFO	*lib_infop;
2364 	HBA_HANDLE		vendorHandle;
2365 	HBAGetAdapterPortAttributesFunc
2366 	    GetAdapterPortAttributesFunc;
2367 
2368 	DEBUG(2, "HBA_GetAdapterPortAttributes", 0, 0, 0);
2369 
2370 	CHECKLIBRARY();
2371 	if (lib_infop->version == SMHBA) {
2372 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2373 	}
2374 
2375 	GetAdapterPortAttributesFunc =
2376 	    lib_infop->ftable.functionTable.GetAdapterPortAttributesHandler;
2377 	if (GetAdapterPortAttributesFunc != NULL) {
2378 	status = ((GetAdapterPortAttributesFunc)
2379 	    (vendorHandle, portindex, portattributes));
2380 	} else {
2381 		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2382 	}
2383 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2384 }
2385 
2386 HBA_STATUS
2387 HBA_GetPortStatistics(
2388     HBA_HANDLE		handle,
2389     HBA_UINT32		portindex,
2390     HBA_PORTSTATISTICS	*portstatistics)
2391 {
2392 	HBA_STATUS		status;
2393 	HBA_LIBRARY_INFO	*lib_infop;
2394 	HBA_HANDLE		vendorHandle;
2395 	HBAGetPortStatisticsFunc
2396 	    GetPortStatisticsFunc;
2397 
2398 	DEBUG(2, "HBA_GetPortStatistics", 0, 0, 0);
2399 
2400 	CHECKLIBRARY();
2401 	if (lib_infop->version == SMHBA) {
2402 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2403 	}
2404 
2405 	GetPortStatisticsFunc =
2406 	    lib_infop->ftable.functionTable.GetPortStatisticsHandler;
2407 	if (GetPortStatisticsFunc != NULL) {
2408 	status = ((GetPortStatisticsFunc)
2409 	    (vendorHandle, portindex, portstatistics));
2410 	} else {
2411 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2412 	}
2413 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2414 }
2415 
2416 HBA_STATUS
2417 HBA_GetDiscoveredPortAttributes(
2418     HBA_HANDLE		handle,
2419     HBA_UINT32		portindex,
2420     HBA_UINT32		discoveredportindex,
2421     HBA_PORTATTRIBUTES	*portattributes)
2422 {
2423 	HBA_STATUS		status;
2424 	HBA_LIBRARY_INFO	*lib_infop;
2425 	HBA_HANDLE		vendorHandle;
2426 	HBAGetDiscoveredPortAttributesFunc
2427 	    GetDiscoveredPortAttributesFunc;
2428 
2429 	DEBUG(2, "HBA_GetDiscoveredPortAttributes", 0, 0, 0);
2430 
2431 	CHECKLIBRARY();
2432 	if (lib_infop->version == SMHBA) {
2433 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2434 	}
2435 
2436 	GetDiscoveredPortAttributesFunc =
2437 	    lib_infop->ftable.functionTable.GetDiscoveredPortAttributesHandler;
2438 	if (GetDiscoveredPortAttributesFunc != NULL)  {
2439 	status = ((GetDiscoveredPortAttributesFunc)
2440 	    (vendorHandle, portindex, discoveredportindex,
2441 	    portattributes));
2442 	} else {
2443 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2444 	}
2445 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2446 }
2447 
2448 HBA_STATUS
2449 HBA_GetPortAttributesByWWN(
2450     HBA_HANDLE		handle,
2451     HBA_WWN		PortWWN,
2452     HBA_PORTATTRIBUTES	*portattributes)
2453 {
2454 	HBA_STATUS		status;
2455 	HBA_LIBRARY_INFO	*lib_infop;
2456 	HBA_HANDLE		vendorHandle;
2457 	HBAGetPortAttributesByWWNFunc
2458 	    GetPortAttributesByWWNFunc;
2459 
2460 	DEBUG(2, "HBA_GetPortAttributesByWWN: %s", WWN2STR1(&PortWWN), 0, 0);
2461 
2462 	CHECKLIBRARY();
2463 	if (lib_infop->version == SMHBA) {
2464 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2465 	}
2466 
2467 	GetPortAttributesByWWNFunc =
2468 	    lib_infop->ftable.functionTable.GetPortAttributesByWWNHandler;
2469 	if (GetPortAttributesByWWNFunc != NULL) {
2470 	status = ((GetPortAttributesByWWNFunc)
2471 	    (vendorHandle, PortWWN, portattributes));
2472 	} else {
2473 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2474 	}
2475 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2476 }
2477 
2478 HBA_STATUS
2479 HBA_SendCTPassThru(
2480     HBA_HANDLE		handle,
2481     void		*pReqBuffer,
2482     HBA_UINT32		ReqBufferSize,
2483     void		*pRspBuffer,
2484     HBA_UINT32		RspBufferSize)
2485 {
2486 	HBA_STATUS		status;
2487 	HBA_LIBRARY_INFO	*lib_infop;
2488 	HBA_HANDLE		vendorHandle;
2489 	HBASendCTPassThruFunc
2490 	    SendCTPassThruFunc;
2491 
2492 	DEBUG(2, "HBA_SendCTPassThru", 0, 0, 0);
2493 
2494 	CHECKLIBRARY();
2495 	if (lib_infop->version == SMHBA) {
2496 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2497 	}
2498 
2499 	SendCTPassThruFunc =
2500 	    lib_infop->ftable.functionTable.SendCTPassThruHandler;
2501 	if (SendCTPassThruFunc != NULL) {
2502 	status = (SendCTPassThruFunc)
2503 	    (vendorHandle,
2504 	    pReqBuffer, ReqBufferSize,
2505 	    pRspBuffer, RspBufferSize);
2506 	} else {
2507 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2508 	}
2509 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2510 }
2511 
2512 HBA_STATUS
2513 HBA_SendCTPassThruV2(
2514     HBA_HANDLE		handle,
2515     HBA_WWN		hbaPortWWN,
2516     void		*pReqBuffer,
2517     HBA_UINT32		ReqBufferSize,
2518     void		*pRspBuffer,
2519     HBA_UINT32		*pRspBufferSize)
2520 {
2521 	HBA_STATUS		status;
2522 	HBA_LIBRARY_INFO	*lib_infop;
2523 	HBA_HANDLE		vendorHandle;
2524 	HBASendCTPassThruV2Func
2525 	    registeredfunc;
2526 
2527 	DEBUG(2, "HBA_SendCTPassThruV2m hbaPortWWN: %s",
2528 	    WWN2STR1(&hbaPortWWN), 0, 0);
2529 
2530 	CHECKLIBRARYANDVERSION(HBAAPIV2);
2531 	registeredfunc = FUNCCOMMON(lib_infop, SendCTPassThruV2Handler);
2532 	if (registeredfunc != NULL) {
2533 	status = (registeredfunc)
2534 	    (vendorHandle, hbaPortWWN,
2535 	    pReqBuffer, ReqBufferSize,
2536 	    pRspBuffer, pRspBufferSize);
2537 	} else {
2538 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2539 	}
2540 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2541 }
2542 
2543 HBA_STATUS
2544 HBA_GetEventBuffer(
2545     HBA_HANDLE		handle,
2546     PHBA_EVENTINFO	EventBuffer,
2547     HBA_UINT32		*EventBufferCount)
2548 {
2549 	HBA_STATUS		status;
2550 	HBA_LIBRARY_INFO	*lib_infop;
2551 	HBA_HANDLE		vendorHandle;
2552 	HBAGetEventBufferFunc
2553 	    GetEventBufferFunc;
2554 
2555 	DEBUG(2, "HBA_GetEventBuffer", 0, 0, 0);
2556 
2557 	CHECKLIBRARY();
2558 	if (lib_infop->version == SMHBA) {
2559 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2560 	}
2561 
2562 	GetEventBufferFunc =
2563 	    lib_infop->ftable.functionTable.GetEventBufferHandler;
2564 	if (GetEventBufferFunc != NULL) {
2565 	status = (GetEventBufferFunc)
2566 	    (vendorHandle, EventBuffer, EventBufferCount);
2567 	} else {
2568 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2569 	}
2570 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2571 }
2572 
2573 HBA_STATUS
2574 HBA_SetRNIDMgmtInfo(HBA_HANDLE handle, HBA_MGMTINFO Info) {
2575     HBA_STATUS		status;
2576     HBA_LIBRARY_INFO	*lib_infop;
2577     HBA_HANDLE		vendorHandle;
2578     HBASetRNIDMgmtInfoFunc
2579 			SetRNIDMgmtInfoFunc;
2580 
2581     DEBUG(2, "HBA_SetRNIDMgmtInfo", 0, 0, 0);
2582 
2583     CHECKLIBRARY();
2584     SetRNIDMgmtInfoFunc = FUNCCOMMON(lib_infop, SetRNIDMgmtInfoHandler);
2585     if (SetRNIDMgmtInfoFunc != NULL) {
2586 	status = (SetRNIDMgmtInfoFunc)(vendorHandle, Info);
2587 	} else {
2588 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2589 	}
2590     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2591 }
2592 
2593 HBA_STATUS
2594 HBA_GetRNIDMgmtInfo(HBA_HANDLE handle, HBA_MGMTINFO *pInfo) {
2595     HBA_STATUS		status;
2596     HBA_LIBRARY_INFO	*lib_infop;
2597     HBA_HANDLE		vendorHandle;
2598     HBAGetRNIDMgmtInfoFunc
2599 	    GetRNIDMgmtInfoFunc;
2600 
2601     DEBUG(2, "HBA_GetRNIDMgmtInfo", 0, 0, 0);
2602 
2603     CHECKLIBRARY();
2604     GetRNIDMgmtInfoFunc = FUNCCOMMON(lib_infop, GetRNIDMgmtInfoHandler);
2605     if (GetRNIDMgmtInfoFunc != NULL) {
2606 	status = (GetRNIDMgmtInfoFunc)(vendorHandle, pInfo);
2607 	} else {
2608 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2609 	}
2610     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2611 }
2612 
2613 HBA_STATUS
2614 HBA_SendRNID(
2615     HBA_HANDLE		handle,
2616     HBA_WWN		wwn,
2617     HBA_WWNTYPE		wwntype,
2618     void		*pRspBuffer,
2619     HBA_UINT32		*pRspBufferSize)
2620 {
2621 	HBA_STATUS		status;
2622 	HBA_LIBRARY_INFO	*lib_infop;
2623 	HBA_HANDLE		vendorHandle;
2624 	HBASendRNIDFunc	SendRNIDFunc;
2625 
2626 	DEBUG(2, "HBA_SendRNID for wwn: %s", WWN2STR1(&wwn), 0, 0);
2627 
2628 	CHECKLIBRARY();
2629 	if (lib_infop->version == SMHBA) {
2630 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2631 	}
2632 
2633 	SendRNIDFunc = lib_infop->ftable.functionTable.SendRNIDHandler;
2634 	if (SendRNIDFunc != NULL) {
2635 	status = ((SendRNIDFunc)(vendorHandle, wwn, wwntype,
2636 	    pRspBuffer, pRspBufferSize));
2637 	} else {
2638 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2639 	}
2640 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2641 }
2642 
2643 HBA_STATUS
2644 HBA_SendRNIDV2(
2645     HBA_HANDLE		handle,
2646     HBA_WWN		hbaPortWWN,
2647     HBA_WWN		destWWN,
2648     HBA_UINT32		destFCID,
2649     HBA_UINT32		NodeIdDataFormat,
2650     void		*pRspBuffer,
2651     HBA_UINT32		*pRspBufferSize)
2652 {
2653 	HBA_STATUS		status;
2654 	HBA_LIBRARY_INFO	*lib_infop;
2655 	HBA_HANDLE		vendorHandle;
2656 	HBASendRNIDV2Func	registeredfunc;
2657 
2658 	DEBUG(2, "HBA_SendRNIDV2, hbaPortWWN: %s", WWN2STR1(&hbaPortWWN), 0, 0);
2659 
2660 	CHECKLIBRARY();
2661 	registeredfunc = FUNCCOMMON(lib_infop, SendRNIDV2Handler);
2662 	if (registeredfunc != NULL) {
2663 	status = (registeredfunc)
2664 	    (vendorHandle, hbaPortWWN, destWWN, destFCID, NodeIdDataFormat,
2665 	    pRspBuffer, pRspBufferSize);
2666 	} else {
2667 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2668 	}
2669 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2670 }
2671 
2672 void
2673 HBA_RefreshInformation(HBA_HANDLE handle) {
2674     HBA_STATUS		status;
2675     HBA_LIBRARY_INFO	*lib_infop;
2676     HBA_HANDLE		vendorHandle;
2677     HBARefreshInformationFunc
2678 	    RefreshInformationFunc;
2679 
2680 	DEBUG(2, "HBA_RefreshInformation", 0, 0, 0);
2681 
2682 	status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);
2683 	if (status == HBA_STATUS_OK) {
2684 	RefreshInformationFunc =
2685 	    FUNCCOMMON(lib_infop, RefreshInformationHandler);
2686 	if (RefreshInformationFunc != NULL) {
2687 	    ((RefreshInformationFunc)(vendorHandle));
2688 	}
2689 	RELEASE_MUTEX(&_hbaapi_LL_mutex);
2690 	}
2691 }
2692 
2693 void
2694 HBA_ResetStatistics(HBA_HANDLE handle, HBA_UINT32 portindex) {
2695     HBA_STATUS		status;
2696     HBA_LIBRARY_INFO	*lib_infop;
2697     HBA_HANDLE		vendorHandle;
2698     HBAResetStatisticsFunc
2699 			ResetStatisticsFunc;
2700 
2701     DEBUG(2, "HBA_ResetStatistics", 0, 0, 0);
2702 
2703     status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);
2704     if (status == HBA_STATUS_OK) {
2705 	if (lib_infop->version == SMHBA) {
2706 		RELEASE_MUTEX(&_hbaapi_LL_mutex);
2707 	}
2708 
2709 	ResetStatisticsFunc =
2710 	    lib_infop->ftable.functionTable.ResetStatisticsHandler;
2711 	if (ResetStatisticsFunc != NULL) {
2712 	    ((ResetStatisticsFunc)(vendorHandle, portindex));
2713 	}
2714 	RELEASE_MUTEX(&_hbaapi_LL_mutex);
2715 	}
2716 }
2717 
2718 HBA_STATUS
2719 HBA_GetFcpTargetMapping(HBA_HANDLE handle, PHBA_FCPTARGETMAPPING mapping) {
2720     HBA_STATUS		status;
2721     HBA_LIBRARY_INFO	*lib_infop;
2722     HBA_HANDLE		vendorHandle;
2723     HBAGetFcpTargetMappingFunc GetFcpTargetMappingFunc;
2724 
2725     DEBUG(2, "HBA_GetFcpTargetMapping", 0, 0, 0);
2726 
2727     CHECKLIBRARY();
2728     if (lib_infop->version == SMHBA) {
2729 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2730 	}
2731 
2732     GetFcpTargetMappingFunc =
2733 	lib_infop->ftable.functionTable.GetFcpTargetMappingHandler;
2734     if (GetFcpTargetMappingFunc != NULL) {
2735 	status = ((GetFcpTargetMappingFunc)(vendorHandle, mapping));
2736 	} else {
2737 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2738 	}
2739     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2740 }
2741 
2742 HBA_STATUS
2743 HBA_GetFcpTargetMappingV2(
2744     HBA_HANDLE		handle,
2745     HBA_WWN		hbaPortWWN,
2746     HBA_FCPTARGETMAPPINGV2 *pmapping)
2747 {
2748 	HBA_STATUS		status;
2749 	HBA_LIBRARY_INFO	*lib_infop;
2750 	HBA_HANDLE		vendorHandle;
2751 	HBAGetFcpTargetMappingV2Func
2752 	    registeredfunc;
2753 
2754 	DEBUG(2, "HBA_GetFcpTargetMapping", 0, 0, 0);
2755 
2756 	CHECKLIBRARYANDVERSION(HBAAPIV2);
2757 
2758 	registeredfunc =
2759 	    lib_infop->ftable.functionTable.GetFcpTargetMappingV2Handler;
2760 	if (registeredfunc != NULL) {
2761 	status = ((registeredfunc)(vendorHandle, hbaPortWWN, pmapping));
2762 	} else {
2763 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2764 	}
2765 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2766 }
2767 
2768 HBA_STATUS
2769 HBA_GetFcpPersistentBinding(HBA_HANDLE handle, PHBA_FCPBINDING binding) {
2770     HBA_STATUS		status;
2771     HBA_LIBRARY_INFO	*lib_infop;
2772     HBA_HANDLE		vendorHandle;
2773     HBAGetFcpPersistentBindingFunc
2774 	    GetFcpPersistentBindingFunc;
2775 
2776 	DEBUG(2, "HBA_GetFcpPersistentBinding", 0, 0, 0);
2777 
2778 	CHECKLIBRARY();
2779 	if (lib_infop->version == SMHBA) {
2780 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2781 	}
2782 
2783 	GetFcpPersistentBindingFunc =
2784 	    lib_infop->ftable.functionTable.GetFcpPersistentBindingHandler;
2785 	if (GetFcpPersistentBindingFunc != NULL) {
2786 	status = ((GetFcpPersistentBindingFunc)(vendorHandle, binding));
2787 	} else {
2788 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2789 	}
2790 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2791 }
2792 
2793 HBA_STATUS
2794 HBA_ScsiInquiryV2(
2795     HBA_HANDLE	handle,
2796     HBA_WWN	hbaPortWWN,
2797     HBA_WWN	discoveredPortWWN,
2798     HBA_UINT64	fcLUN,
2799     HBA_UINT8	CDB_Byte1,
2800     HBA_UINT8	CDB_Byte2,
2801     void	*pRspBuffer,
2802     HBA_UINT32	*pRspBufferSize,
2803     HBA_UINT8	*pScsiStatus,
2804     void	*pSenseBuffer,
2805     HBA_UINT32	*pSenseBufferSize)
2806 {
2807 	HBA_STATUS		status;
2808 	HBA_LIBRARY_INFO	*lib_infop;
2809 	HBA_HANDLE		vendorHandle;
2810 	HBAScsiInquiryV2Func ScsiInquiryV2Func;
2811 
2812 	DEBUG(2, "HBA_ScsiInquiryV2 to discoveredPortWWN: %s",
2813 	    WWN2STR1(&discoveredPortWWN), 0, 0);
2814 
2815 	CHECKLIBRARYANDVERSION(HBAAPIV2);
2816 
2817 	ScsiInquiryV2Func =
2818 	    lib_infop->ftable.functionTable.ScsiInquiryV2Handler;
2819 	if (ScsiInquiryV2Func != NULL) {
2820 	status = ((ScsiInquiryV2Func)(
2821 	    vendorHandle, hbaPortWWN, discoveredPortWWN, fcLUN, CDB_Byte1,
2822 	    CDB_Byte2, pRspBuffer, pRspBufferSize, pScsiStatus,
2823 	    pSenseBuffer, pSenseBufferSize));
2824 	} else {
2825 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2826 	}
2827 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2828 }
2829 
2830 HBA_STATUS
2831 HBA_SendScsiInquiry(
2832     HBA_HANDLE	handle,
2833     HBA_WWN	PortWWN,
2834     HBA_UINT64	fcLUN,
2835     HBA_UINT8	EVPD,
2836     HBA_UINT32	PageCode,
2837     void	*pRspBuffer,
2838     HBA_UINT32	RspBufferSize,
2839     void	*pSenseBuffer,
2840     HBA_UINT32	SenseBufferSize)
2841 {
2842 	HBA_STATUS		status;
2843 	HBA_LIBRARY_INFO	*lib_infop;
2844 	HBA_HANDLE		vendorHandle;
2845 	HBASendScsiInquiryFunc SendScsiInquiryFunc;
2846 
2847 	DEBUG(2, "HBA_SendScsiInquiry to PortWWN: %s",
2848 	    WWN2STR1(&PortWWN), 0, 0);
2849 
2850 	CHECKLIBRARY();
2851 	if (lib_infop->version == SMHBA) {
2852 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2853 	}
2854 
2855 	SendScsiInquiryFunc =
2856 	    lib_infop->ftable.functionTable.ScsiInquiryHandler;
2857 	if (SendScsiInquiryFunc != NULL) {
2858 	status = ((SendScsiInquiryFunc)(
2859 	    vendorHandle, PortWWN, fcLUN, EVPD, PageCode, pRspBuffer,
2860 	    RspBufferSize, pSenseBuffer, SenseBufferSize));
2861 	} else {
2862 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2863 	}
2864 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2865 }
2866 
2867 HBA_STATUS
2868 HBA_ScsiReportLUNsV2(
2869     HBA_HANDLE		handle,
2870     HBA_WWN		hbaPortWWN,
2871     HBA_WWN		discoveredPortWWN,
2872     void		*pRespBuffer,
2873     HBA_UINT32		*pRespBufferSize,
2874     HBA_UINT8		*pScsiStatus,
2875     void		*pSenseBuffer,
2876     HBA_UINT32		*pSenseBufferSize)
2877 {
2878 	HBA_STATUS		status;
2879 	HBA_LIBRARY_INFO	*lib_infop;
2880 	HBA_HANDLE		vendorHandle;
2881 	HBAScsiReportLUNsV2Func ScsiReportLUNsV2Func;
2882 
2883 	DEBUG(2, "HBA_ScsiReportLUNsV2 to discoveredPortWWN: %s",
2884 	    WWN2STR1(&discoveredPortWWN), 0, 0);
2885 
2886 	CHECKLIBRARYANDVERSION(HBAAPIV2);
2887 
2888 	ScsiReportLUNsV2Func =
2889 	    lib_infop->ftable.functionTable.ScsiReportLUNsV2Handler;
2890 	if (ScsiReportLUNsV2Func != NULL) {
2891 	status = ((ScsiReportLUNsV2Func)(
2892 	    vendorHandle, hbaPortWWN, discoveredPortWWN,
2893 	    pRespBuffer, pRespBufferSize,
2894 	    pScsiStatus,
2895 	    pSenseBuffer, pSenseBufferSize));
2896 	} else {
2897 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2898 	}
2899 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2900 }
2901 
2902 HBA_STATUS
2903 HBA_SendReportLUNs(
2904     HBA_HANDLE handle,
2905     HBA_WWN portWWN,
2906     void *pRspBuffer,
2907     HBA_UINT32 RspBufferSize,
2908     void *pSenseBuffer,
2909     HBA_UINT32 SenseBufferSize)
2910 {
2911 	HBA_STATUS		status;
2912 	HBA_LIBRARY_INFO	*lib_infop;
2913 	HBA_HANDLE		vendorHandle;
2914 	HBASendReportLUNsFunc SendReportLUNsFunc;
2915 
2916 	DEBUG(2, "HBA_SendReportLUNs to PortWWN: %s", WWN2STR1(&portWWN), 0, 0);
2917 
2918 	CHECKLIBRARY();
2919 	if (lib_infop->version == SMHBA) {
2920 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2921 	}
2922 
2923 	SendReportLUNsFunc = lib_infop->ftable.functionTable.ReportLUNsHandler;
2924 	if (SendReportLUNsFunc != NULL) {
2925 	status = ((SendReportLUNsFunc)(
2926 	    vendorHandle, portWWN, pRspBuffer,
2927 	    RspBufferSize, pSenseBuffer, SenseBufferSize));
2928 	} else {
2929 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2930 	}
2931 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2932 }
2933 
2934 HBA_STATUS
2935 HBA_ScsiReadCapacityV2(
2936     HBA_HANDLE		handle,
2937     HBA_WWN		hbaPortWWN,
2938     HBA_WWN		discoveredPortWWN,
2939     HBA_UINT64		fcLUN,
2940     void		*pRspBuffer,
2941     HBA_UINT32		*pRspBufferSize,
2942     HBA_UINT8		*pScsiStatus,
2943     void		*pSenseBuffer,
2944     HBA_UINT32		*SenseBufferSize)
2945 {
2946 	HBA_STATUS		status;
2947 	HBA_LIBRARY_INFO	*lib_infop;
2948 	HBA_HANDLE		vendorHandle;
2949 	HBAScsiReadCapacityV2Func ScsiReadCapacityV2Func;
2950 
2951 	DEBUG(2, "HBA_ScsiReadCapacityV2 to discoveredPortWWN: %s",
2952 	    WWN2STR1(&discoveredPortWWN), 0, 0);
2953 
2954 	CHECKLIBRARYANDVERSION(HBAAPIV2);
2955 
2956 	ScsiReadCapacityV2Func =
2957 	    lib_infop->ftable.functionTable.ScsiReadCapacityV2Handler;
2958 	if (ScsiReadCapacityV2Func != NULL) {
2959 	status = ((ScsiReadCapacityV2Func)(
2960 	    vendorHandle, hbaPortWWN, discoveredPortWWN, fcLUN,
2961 	    pRspBuffer, pRspBufferSize,
2962 	    pScsiStatus,
2963 	    pSenseBuffer, SenseBufferSize));
2964 	} else {
2965 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2966 	}
2967 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2968 }
2969 
2970 HBA_STATUS
2971 HBA_SendReadCapacity(
2972     HBA_HANDLE handle,
2973     HBA_WWN portWWN,
2974     HBA_UINT64 fcLUN,
2975     void *pRspBuffer,
2976     HBA_UINT32 RspBufferSize,
2977     void *pSenseBuffer,
2978     HBA_UINT32 SenseBufferSize)
2979 {
2980 	HBA_STATUS		status;
2981 	HBA_LIBRARY_INFO	*lib_infop;
2982 	HBA_HANDLE		vendorHandle;
2983 	HBASendReadCapacityFunc SendReadCapacityFunc;
2984 
2985 	DEBUG(2, "HBA_SendReadCapacity to portWWN: %s",
2986 	    WWN2STR1(&portWWN), 0, 0);
2987 
2988 	CHECKLIBRARY();
2989 	if (lib_infop->version == SMHBA) {
2990 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
2991 	}
2992 
2993 	SendReadCapacityFunc =
2994 	    lib_infop->ftable.functionTable.ReadCapacityHandler;
2995 	if (SendReadCapacityFunc != NULL) {
2996 	status = ((SendReadCapacityFunc)
2997 	    (vendorHandle, portWWN, fcLUN, pRspBuffer,
2998 	    RspBufferSize, pSenseBuffer, SenseBufferSize));
2999 	} else {
3000 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3001 	}
3002 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3003 }
3004 
3005 HBA_STATUS
3006 HBA_SendRPL(
3007     HBA_HANDLE		handle,
3008     HBA_WWN		hbaPortWWN,
3009     HBA_WWN		agent_wwn,
3010     HBA_UINT32		agent_domain,
3011     HBA_UINT32		portindex,
3012     void		*pRspBuffer,
3013     HBA_UINT32		*pRspBufferSize)
3014 {
3015 	HBA_STATUS		status;
3016 	HBA_LIBRARY_INFO	*lib_infop;
3017 	HBA_HANDLE		vendorHandle;
3018 	HBASendRPLFunc registeredfunc;
3019 
3020 	DEBUG(2, "HBA_SendRPL to agent_wwn: %s:%d",
3021 	    WWN2STR1(&agent_wwn), agent_domain, 0);
3022 
3023 	CHECKLIBRARY();
3024 	registeredfunc = FUNCCOMMON(lib_infop, SendRPLHandler);
3025 	if (registeredfunc != NULL) {
3026 	status = (registeredfunc)(
3027 	    vendorHandle, hbaPortWWN, agent_wwn, agent_domain, portindex,
3028 	    pRspBuffer, pRspBufferSize);
3029 	} else {
3030 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3031 	}
3032 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3033 }
3034 
3035 HBA_STATUS
3036 HBA_SendRPS(
3037     HBA_HANDLE		handle,
3038     HBA_WWN		hbaPortWWN,
3039     HBA_WWN		agent_wwn,
3040     HBA_UINT32		agent_domain,
3041     HBA_WWN		object_wwn,
3042     HBA_UINT32		object_port_number,
3043     void		*pRspBuffer,
3044     HBA_UINT32		*pRspBufferSize)
3045 {
3046 	HBA_STATUS		status;
3047 	HBA_LIBRARY_INFO	*lib_infop;
3048 	HBA_HANDLE		vendorHandle;
3049 	HBASendRPSFunc registeredfunc;
3050 
3051 	DEBUG(2, "HBA_SendRPS  to agent_wwn: %s:%d",
3052 	    WWN2STR1(&agent_wwn), agent_domain, 0);
3053 
3054 	CHECKLIBRARY();
3055 	registeredfunc = FUNCCOMMON(lib_infop, SendRPSHandler);
3056 	if (registeredfunc != NULL) {
3057 	status = (registeredfunc)(
3058 	    vendorHandle, hbaPortWWN, agent_wwn, agent_domain,
3059 	    object_wwn, object_port_number,
3060 	    pRspBuffer, pRspBufferSize);
3061 	} else {
3062 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3063 	}
3064 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3065 }
3066 
3067 HBA_STATUS
3068 HBA_SendSRL(
3069     HBA_HANDLE		handle,
3070     HBA_WWN		hbaPortWWN,
3071     HBA_WWN		wwn,
3072     HBA_UINT32		domain,
3073     void		*pRspBuffer,
3074     HBA_UINT32		*pRspBufferSize)
3075 {
3076 	HBA_STATUS		status;
3077 	HBA_LIBRARY_INFO	*lib_infop;
3078 	HBA_HANDLE		vendorHandle;
3079 	HBASendSRLFunc registeredfunc;
3080 
3081 	DEBUG(2, "HBA_SendSRL to wwn:%s domain:%d", WWN2STR1(&wwn), domain, 0);
3082 
3083 	CHECKLIBRARY();
3084 	registeredfunc = FUNCCOMMON(lib_infop, SendSRLHandler);
3085 	if (registeredfunc != NULL) {
3086 	status = (registeredfunc)(
3087 	    vendorHandle, hbaPortWWN, wwn, domain,
3088 	    pRspBuffer, pRspBufferSize);
3089 	} else {
3090 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3091 	}
3092 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3093 }
3094 HBA_STATUS
3095 HBA_SendRLS(
3096     HBA_HANDLE		handle,
3097     HBA_WWN		hbaPortWWN,
3098     HBA_WWN		destWWN,
3099     void		*pRspBuffer,
3100     HBA_UINT32		*pRspBufferSize)
3101 {
3102 	HBA_STATUS		status;
3103 	HBA_LIBRARY_INFO	*lib_infop;
3104 	HBA_HANDLE		vendorHandle;
3105 	HBASendRLSFunc registeredfunc;
3106 
3107 	DEBUG(2, "HBA_SendRLS dest_wwn: %s",
3108 	    WWN2STR1(&destWWN), 0, 0);
3109 
3110 	CHECKLIBRARY();
3111 	registeredfunc = FUNCCOMMON(lib_infop, SendRLSHandler);
3112 	if (registeredfunc != NULL) {
3113 	status = (registeredfunc)(
3114 	    vendorHandle, hbaPortWWN, destWWN,
3115 	    pRspBuffer, pRspBufferSize);
3116 	} else {
3117 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3118 	}
3119 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3120 }
3121 
3122 HBA_STATUS
3123 HBA_SendLIRR(
3124     HBA_HANDLE		handle,
3125     HBA_WWN		sourceWWN,
3126     HBA_WWN		destWWN,
3127     HBA_UINT8		function,
3128     HBA_UINT8		type,
3129     void		*pRspBuffer,
3130     HBA_UINT32		*pRspBufferSize)
3131 {
3132 	HBA_STATUS		status;
3133 	HBA_LIBRARY_INFO	*lib_infop;
3134 	HBA_HANDLE		vendorHandle;
3135 	HBASendLIRRFunc registeredfunc;
3136 
3137 	DEBUG(2, "HBA_SendLIRR destWWN:%s", WWN2STR1(&destWWN), 0, 0);
3138 
3139 	CHECKLIBRARY();
3140 	registeredfunc = FUNCCOMMON(lib_infop, SendLIRRHandler);
3141 	if (registeredfunc != NULL) {
3142 	status = (registeredfunc)(
3143 	    vendorHandle, sourceWWN, destWWN, function, type,
3144 	    pRspBuffer, pRspBufferSize);
3145 	} else {
3146 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3147 	}
3148 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3149 }
3150 
3151 HBA_STATUS
3152 HBA_GetBindingCapability(
3153     HBA_HANDLE		handle,
3154     HBA_WWN		hbaPortWWN,
3155     HBA_BIND_CAPABILITY *pcapability)
3156 {
3157 	HBA_STATUS		status;
3158 	HBA_LIBRARY_INFO	*lib_infop;
3159 	HBA_HANDLE		vendorHandle;
3160 	HBAGetBindingCapabilityFunc
3161 	    registeredfunc;
3162 
3163 	DEBUG(2, "HBA_GetBindingCapability", 0, 0, 0);
3164 
3165 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3166 
3167 	registeredfunc =
3168 	    lib_infop->ftable.functionTable.GetBindingCapabilityHandler;
3169 	if (registeredfunc != NULL) {
3170 	status = (registeredfunc)(vendorHandle, hbaPortWWN, pcapability);
3171 	} else {
3172 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3173 	}
3174 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3175 }
3176 
3177 HBA_STATUS
3178 HBA_GetBindingSupport(
3179     HBA_HANDLE		handle,
3180     HBA_WWN		hbaPortWWN,
3181     HBA_BIND_CAPABILITY *pcapability)
3182 {
3183 	HBA_STATUS		status;
3184 	HBA_LIBRARY_INFO	*lib_infop;
3185 	HBA_HANDLE		vendorHandle;
3186 	HBAGetBindingSupportFunc
3187 	    registeredfunc;
3188 
3189 	DEBUG(2, "HBA_GetBindingSupport", 0, 0, 0);
3190 
3191 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3192 
3193 	registeredfunc =
3194 	    lib_infop->ftable.functionTable.GetBindingSupportHandler;
3195 	if (registeredfunc != NULL) {
3196 	status = (registeredfunc)(vendorHandle, hbaPortWWN, pcapability);
3197 	} else {
3198 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3199 	}
3200 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3201 }
3202 
3203 HBA_STATUS
3204 HBA_SetBindingSupport(
3205     HBA_HANDLE		handle,
3206     HBA_WWN		hbaPortWWN,
3207     HBA_BIND_CAPABILITY capability)
3208 {
3209 	HBA_STATUS		status;
3210 	HBA_LIBRARY_INFO	*lib_infop;
3211 	HBA_HANDLE		vendorHandle;
3212 	HBASetBindingSupportFunc
3213 	    registeredfunc;
3214 
3215 	DEBUG(2, "HBA_SetBindingSupport", 0, 0, 0);
3216 
3217 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3218 
3219 	registeredfunc =
3220 	    lib_infop->ftable.functionTable.SetBindingSupportHandler;
3221 	if (registeredfunc != NULL) {
3222 	status = (registeredfunc)(vendorHandle, hbaPortWWN, capability);
3223 	} else {
3224 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3225 	}
3226 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3227 }
3228 
3229 HBA_STATUS
3230 HBA_SetPersistentBindingV2(
3231     HBA_HANDLE		handle,
3232     HBA_WWN		hbaPortWWN,
3233     const HBA_FCPBINDING2 *pbinding)
3234 {
3235 	HBA_STATUS		status;
3236 	HBA_LIBRARY_INFO	*lib_infop;
3237 	HBA_HANDLE		vendorHandle;
3238 	HBASetPersistentBindingV2Func
3239 	    registeredfunc;
3240 
3241 	DEBUG(2, "HBA_SetPersistentBindingV2 port: %s",
3242 	    WWN2STR1(&hbaPortWWN), 0, 0);
3243 
3244 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3245 
3246 	registeredfunc =
3247 	    lib_infop->ftable.functionTable.SetPersistentBindingV2Handler;
3248 	if (registeredfunc != NULL) {
3249 	status = (registeredfunc)(vendorHandle, hbaPortWWN, pbinding);
3250 	} else {
3251 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3252 	}
3253 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3254 }
3255 
3256 HBA_STATUS
3257 HBA_GetPersistentBindingV2(
3258     HBA_HANDLE		handle,
3259     HBA_WWN		hbaPortWWN,
3260     HBA_FCPBINDING2	*pbinding)
3261 {
3262 	HBA_STATUS		status;
3263 	HBA_LIBRARY_INFO	*lib_infop;
3264 	HBA_HANDLE		vendorHandle;
3265 	HBAGetPersistentBindingV2Func
3266 	    registeredfunc;
3267 
3268 	DEBUG(2, "HBA_GetPersistentBindingV2 port: %s",
3269 	    WWN2STR1(&hbaPortWWN), 0, 0);
3270 
3271 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3272 
3273 	registeredfunc =
3274 	    lib_infop->ftable.functionTable.GetPersistentBindingV2Handler;
3275 	if (registeredfunc != NULL) {
3276 	status = (registeredfunc)(vendorHandle, hbaPortWWN, pbinding);
3277 	} else {
3278 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3279 	}
3280 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3281 }
3282 
3283 HBA_STATUS
3284 HBA_RemovePersistentBinding(
3285     HBA_HANDLE		handle,
3286     HBA_WWN		hbaPortWWN,
3287     const HBA_FCPBINDING2
3288 			*pbinding)
3289 {
3290 	HBA_STATUS		status;
3291 	HBA_LIBRARY_INFO	*lib_infop;
3292 	HBA_HANDLE		vendorHandle;
3293 	HBARemovePersistentBindingFunc
3294 	    registeredfunc;
3295 
3296 	DEBUG(2, "HBA_RemovePersistentBinding", 0, 0, 0);
3297 
3298 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3299 
3300 	registeredfunc =
3301 	    lib_infop->ftable.functionTable.RemovePersistentBindingHandler;
3302 	if (registeredfunc != NULL) {
3303 	status = (registeredfunc)(vendorHandle, hbaPortWWN, pbinding);
3304 	} else {
3305 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3306 	}
3307 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3308 }
3309 
3310 HBA_STATUS
3311 HBA_RemoveAllPersistentBindings(
3312     HBA_HANDLE		handle,
3313     HBA_WWN		hbaPortWWN)
3314 {
3315 	HBA_STATUS		status;
3316 	HBA_LIBRARY_INFO	*lib_infop;
3317 	HBA_HANDLE		vendorHandle;
3318 	HBARemoveAllPersistentBindingsFunc
3319 	    registeredfunc;
3320 
3321 	DEBUG(2, "HBA_RemoveAllPersistentBindings", 0, 0, 0);
3322 
3323 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3324 
3325 	registeredfunc =
3326 	    lib_infop->ftable.functionTable.RemoveAllPersistentBindingsHandler;
3327 	if (registeredfunc != NULL) {
3328 	status = (registeredfunc)(vendorHandle, hbaPortWWN);
3329 	} else {
3330 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3331 	}
3332 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3333 }
3334 
3335 HBA_STATUS
3336 HBA_GetFC4Statistics(
3337     HBA_HANDLE		handle,
3338     HBA_WWN		portWWN,
3339     HBA_UINT8		FC4type,
3340     HBA_FC4STATISTICS	*pstatistics)
3341 {
3342 	HBA_STATUS		status;
3343 	HBA_LIBRARY_INFO	*lib_infop;
3344 	HBA_HANDLE		vendorHandle;
3345 	HBAGetFC4StatisticsFunc
3346 	    registeredfunc;
3347 
3348 	DEBUG(2, "HBA_GetFC4Statistics port: %s", WWN2STR1(&portWWN), 0, 0);
3349 
3350 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3351 
3352 	registeredfunc =
3353 	    lib_infop->ftable.functionTable.GetFC4StatisticsHandler;
3354 	if (registeredfunc != NULL) {
3355 	status = (registeredfunc)
3356 	    (vendorHandle, portWWN, FC4type, pstatistics);
3357 	} else {
3358 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3359 	}
3360 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3361 }
3362 
3363 HBA_STATUS
3364 HBA_GetFCPStatistics(
3365     HBA_HANDLE		handle,
3366     const HBA_SCSIID	*lunit,
3367     HBA_FC4STATISTICS	*pstatistics)
3368 {
3369 	HBA_STATUS		status;
3370 	HBA_LIBRARY_INFO	*lib_infop;
3371 	HBA_HANDLE		vendorHandle;
3372 	HBAGetFCPStatisticsFunc
3373 	    registeredfunc;
3374 
3375 	DEBUG(2, "HBA_GetFCPStatistics", 0, 0, 0);
3376 
3377 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3378 
3379 	registeredfunc =
3380 	    lib_infop->ftable.functionTable.GetFCPStatisticsHandler;
3381 	if (registeredfunc != NULL) {
3382 	status = (registeredfunc)(vendorHandle, lunit, pstatistics);
3383 	} else {
3384 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3385 	}
3386 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3387 }
3388 
3389 HBA_UINT32
3390 HBA_GetVendorLibraryAttributes(
3391     HBA_UINT32 adapter_index,
3392     HBA_LIBRARYATTRIBUTES *attributes)
3393 {
3394 	HBA_ADAPTER_INFO	*adapt_infop;
3395 	HBAGetVendorLibraryAttributesFunc
3396 	    registeredfunc;
3397 	HBA_UINT32		ret = 0;
3398 
3399 	DEBUG(2, "HBA_GetVendorLibraryAttributes adapterindex:%d",
3400 	    adapter_index, 0, 0);
3401 	if (_hbaapi_librarylist == NULL) {
3402 	DEBUG(1, "HBAAPI not loaded yet.", 0, 0, 0);
3403 	return (0);
3404 	}
3405 
3406 	if (attributes == NULL) {
3407 		DEBUG(1,
3408 		    "HBA_GetVendorLibraryAttributes: NULL pointer attributes",
3409 		    0, 0, 0);
3410 		return (HBA_STATUS_ERROR_ARG);
3411 	}
3412 
3413 	(void) memset(attributes, 0, sizeof (HBA_LIBRARYATTRIBUTES));
3414 
3415 	GRAB_MUTEX(&_hbaapi_LL_mutex);
3416 	GRAB_MUTEX(&_hbaapi_AL_mutex);
3417 	for (adapt_infop = _hbaapi_adapterlist;
3418 	    adapt_infop != NULL;
3419 	    adapt_infop = adapt_infop->next) {
3420 
3421 	if (adapt_infop->index == adapter_index) {
3422 
3423 		if (adapt_infop->library->version == SMHBA) {
3424 		RELEASE_MUTEX(&_hbaapi_AL_mutex);
3425 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex,
3426 		    HBA_STATUS_ERROR_INCOMPATIBLE);
3427 		}
3428 
3429 		registeredfunc = adapt_infop->library->
3430 		    ftable.functionTable.GetVendorLibraryAttributesHandler;
3431 		if (registeredfunc != NULL) {
3432 		ret = (registeredfunc)(attributes);
3433 		} else {
3434 		/* Version 1 libary? */
3435 		HBAGetVersionFunc	GetVersionFunc;
3436 		GetVersionFunc = adapt_infop->library->
3437 		    ftable.functionTable.GetVersionHandler;
3438 		if (GetVersionFunc != NULL) {
3439 			ret = ((GetVersionFunc)());
3440 		}
3441 #ifdef NOTDEF
3442 		else {
3443 		    /* This should not happen, dont think its going to */
3444 		}
3445 #endif
3446 		}
3447 		if (attributes->LibPath[0] == '\0') {
3448 		if (strlen(adapt_infop->library->LibraryPath) < 256) {
3449 			(void) strcpy(attributes->LibPath,
3450 			    adapt_infop->library->LibraryPath);
3451 		}
3452 		}
3453 		break;
3454 	}
3455 	}
3456 	RELEASE_MUTEX(&_hbaapi_AL_mutex);
3457 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, ret);
3458 }
3459 
3460 
3461 /*
3462  * This function returns SM-HBA version that the warpper library implemented.
3463  */
3464 HBA_UINT32
3465 SMHBA_GetVersion() {
3466     DEBUG(2, "SMHBA_GetVersion", 0, 0, 0);
3467     return (SMHBA_LIBVERSION);
3468 }
3469 
3470 /*
3471  * This function returns the attributes for the warpper library.
3472  */
3473 HBA_UINT32
3474 SMHBA_GetWrapperLibraryAttributes(
3475     SMHBA_LIBRARYATTRIBUTES *attributes)
3476 {
3477 
3478 	struct timeval tv;
3479 	struct tm tp;
3480 
3481 	DEBUG(2, "SMHBA_GetWrapperLibraryAttributes", 0, 0, 0);
3482 
3483 	if (attributes == NULL) {
3484 		DEBUG(1, "SMHBA_GetWrapperLibraryAttributes: "
3485 		    "NULL pointer attributes",
3486 		    0, 0, 0);
3487 		return (HBA_STATUS_ERROR_ARG);
3488 	}
3489 
3490 	(void) memset(attributes, 0, sizeof (SMHBA_LIBRARYATTRIBUTES));
3491 
3492 #if defined(SOLARIS)
3493 	if ((handle = dlopen("libSMHBAAPI.so", RTLD_NOW)) != NULL) {
3494 	if (dlinfo(handle, RTLD_DI_LINKMAP, &map) >= 0) {
3495 		for (mp = map; mp != NULL; mp = mp->l_next) {
3496 		if (strlen(map->l_name) < 256) {
3497 			(void) strcpy(attributes->LibPath, map->l_name);
3498 		}
3499 		}
3500 	}
3501 	}
3502 
3503 #endif
3504 
3505 #if defined(VENDOR)
3506 	(void) strcpy(attributes->VName, VENDOR);
3507 #else
3508 	attributes->VName[0] = '\0';
3509 #endif
3510 #if	defined(VERSION)
3511 	(void) strcpy(attributes->VVersion, VERSION);
3512 #else
3513 	attributes->VVersion[0] = '\0';
3514 #endif
3515 
3516 	if (gettimeofday(&tv, (void *)0) == 0) {
3517 	if (localtime_r(&tv.tv_sec, &tp) != NULL) {
3518 		attributes->build_date.tm_mday = tp.tm_mday;
3519 		attributes->build_date.tm_mon = tp.tm_mon;
3520 		attributes->build_date.tm_year = tp.tm_year;
3521 	} else {
3522 		(void) memset(&attributes->build_date, 0,
3523 		    sizeof (attributes->build_date));
3524 	}
3525 	(void) memset(&attributes->build_date, 0,
3526 	    sizeof (attributes->build_date));
3527 	}
3528 
3529 	return (1);
3530 }
3531 
3532 /*
3533  * This function returns the attributes for the warpper library.
3534  */
3535 HBA_UINT32
3536 SMHBA_GetVendorLibraryAttributes(
3537     HBA_UINT32 adapter_index,
3538     SMHBA_LIBRARYATTRIBUTES *attributes)
3539 {
3540 	HBA_ADAPTER_INFO	*adapt_infop;
3541 	SMHBAGetVendorLibraryAttributesFunc
3542 	    registeredfunc;
3543 	HBA_UINT32		ret = 0;
3544 
3545 	DEBUG(2, "SMHBA_GetVendorLibraryAttributes adapterindex:%d",
3546 	    adapter_index, 0, 0);
3547 	if (_hbaapi_librarylist == NULL) {
3548 	DEBUG(1, "SMHBAAPI not loaded yet.", 0, 0, 0);
3549 	return (0);
3550 	}
3551 
3552 	if (attributes == NULL) {
3553 		DEBUG(1, "SMHBA_GetVendorLibraryAttributes: "
3554 		    "NULL pointer attributes",
3555 		    0, 0, 0);
3556 		return (HBA_STATUS_ERROR_ARG);
3557 	}
3558 
3559 	(void) memset(attributes, 0, sizeof (SMHBA_LIBRARYATTRIBUTES));
3560 
3561 	GRAB_MUTEX(&_hbaapi_LL_mutex);
3562 	GRAB_MUTEX(&_hbaapi_AL_mutex);
3563 	for (adapt_infop = _hbaapi_adapterlist;
3564 	    adapt_infop != NULL;
3565 	    adapt_infop = adapt_infop->next) {
3566 
3567 	if (adapt_infop->index == adapter_index) {
3568 
3569 		if (adapt_infop->library->version != SMHBA) {
3570 		RELEASE_MUTEX(&_hbaapi_AL_mutex);
3571 		RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex,
3572 		    HBA_STATUS_ERROR_INCOMPATIBLE);
3573 		}
3574 
3575 		registeredfunc = adapt_infop->library->
3576 		    ftable.smhbafunctionTable.GetVendorLibraryAttributesHandler;
3577 		if (registeredfunc != NULL) {
3578 		ret = (registeredfunc)(attributes);
3579 #ifdef NOTDEF
3580 		} else {
3581 		/* This should not happen since the VSL is already loaded. */
3582 #endif
3583 		}
3584 		if (attributes->LibPath[0] == '\0') {
3585 		if (strlen(adapt_infop->library->LibraryPath) < 256) {
3586 			(void) strcpy(attributes->LibPath,
3587 			    adapt_infop->library->LibraryPath);
3588 		}
3589 		}
3590 		break;
3591 	}
3592 	}
3593 	RELEASE_MUTEX(&_hbaapi_AL_mutex);
3594 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, ret);
3595 }
3596 
3597 HBA_STATUS
3598 SMHBA_GetAdapterAttributes(
3599     HBA_HANDLE		handle,
3600     SMHBA_ADAPTERATTRIBUTES *hbaattributes)
3601 {
3602 	HBA_STATUS		status;
3603 	HBA_LIBRARY_INFO	*lib_infop;
3604 	HBA_HANDLE		vendorHandle;
3605 	SMHBAGetAdapterAttributesFunc GetAdapterAttributesFunc;
3606 
3607 	DEBUG(2, "SMHBA_GetAdapterAttributes", 0, 0, 0);
3608 
3609 	CHECKLIBRARYANDVERSION(SMHBA);
3610 
3611 	GetAdapterAttributesFunc =
3612 	    lib_infop->ftable.smhbafunctionTable.GetAdapterAttributesHandler;
3613 	if (GetAdapterAttributesFunc != NULL) {
3614 	status = ((GetAdapterAttributesFunc)(vendorHandle, hbaattributes));
3615 	} else {
3616 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3617 	}
3618 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3619 }
3620 
3621 HBA_STATUS
3622 SMHBA_GetNumberOfPorts(
3623     HBA_HANDLE		handle,
3624     HBA_UINT32		*numberofports)
3625 {
3626 	HBA_STATUS		status;
3627 	HBA_LIBRARY_INFO	*lib_infop;
3628 	HBA_HANDLE		vendorHandle;
3629 	SMHBAGetNumberOfPortsFunc GetNumberOfPortsFunc;
3630 
3631 	DEBUG(2, "SMHBA_GetAdapterAttributes", 0, 0, 0);
3632 
3633 	CHECKLIBRARYANDVERSION(SMHBA);
3634 
3635 	GetNumberOfPortsFunc =
3636 	    lib_infop->ftable.smhbafunctionTable.GetNumberOfPortsHandler;
3637 	if (GetNumberOfPortsFunc != NULL) {
3638 	status = ((GetNumberOfPortsFunc)(vendorHandle, numberofports));
3639 	} else {
3640 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3641 	}
3642 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3643 }
3644 
3645 HBA_STATUS
3646 SMHBA_GetPortType(
3647     HBA_HANDLE		handle,
3648     HBA_UINT32		portindex,
3649     HBA_PORTTYPE	*porttype)
3650 {
3651 	HBA_STATUS		status;
3652 	HBA_LIBRARY_INFO	*lib_infop;
3653 	HBA_HANDLE		vendorHandle;
3654 	SMHBAGetPortTypeFunc GetPortTypeFunc;
3655 
3656 	DEBUG(2, "SMHBA_GetAdapterAttributes", 0, 0, 0);
3657 
3658 	CHECKLIBRARYANDVERSION(SMHBA);
3659 
3660 	GetPortTypeFunc =
3661 	    lib_infop->ftable.smhbafunctionTable.GetPortTypeHandler;
3662 	if (GetPortTypeFunc != NULL) {
3663 	status = ((GetPortTypeFunc)(vendorHandle, portindex, porttype));
3664 	} else {
3665 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3666 	}
3667 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3668 }
3669 
3670 HBA_STATUS
3671 SMHBA_GetAdapterPortAttributes(
3672     HBA_HANDLE		handle,
3673     HBA_UINT32		portindex,
3674     SMHBA_PORTATTRIBUTES	*portattributes)
3675 {
3676 	HBA_STATUS		status;
3677 	HBA_LIBRARY_INFO	*lib_infop;
3678 	HBA_HANDLE		vendorHandle;
3679 	SMHBAGetAdapterPortAttributesFunc
3680 	    GetAdapterPortAttributesFunc;
3681 
3682 	DEBUG(2, "SMHBA_GetAdapterPortAttributes", 0, 0, 0);
3683 
3684 	CHECKLIBRARYANDVERSION(SMHBA);
3685 
3686 	GetAdapterPortAttributesFunc =
3687 	    lib_infop->ftable.smhbafunctionTable.\
3688 	    GetAdapterPortAttributesHandler;
3689 	if (GetAdapterPortAttributesFunc != NULL) {
3690 	status = ((GetAdapterPortAttributesFunc)
3691 	    (vendorHandle, portindex, portattributes));
3692 	} else {
3693 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3694 	}
3695 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3696 }
3697 
3698 HBA_STATUS
3699 SMHBA_GetDiscoveredPortAttributes(
3700     HBA_HANDLE		handle,
3701     HBA_UINT32		portindex,
3702     HBA_UINT32		discoveredportindex,
3703     SMHBA_PORTATTRIBUTES	*portattributes)
3704 {
3705 	HBA_STATUS		status;
3706 	HBA_LIBRARY_INFO	*lib_infop;
3707 	HBA_HANDLE		vendorHandle;
3708 	SMHBAGetDiscoveredPortAttributesFunc
3709 	    GetDiscoveredPortAttributesFunc;
3710 
3711 	DEBUG(2, "SMHBA_GetDiscoveredPortAttributes", 0, 0, 0);
3712 
3713 	CHECKLIBRARYANDVERSION(SMHBA);
3714 
3715 	GetDiscoveredPortAttributesFunc =
3716 	    lib_infop->ftable.smhbafunctionTable.\
3717 	    GetDiscoveredPortAttributesHandler;
3718 	if (GetDiscoveredPortAttributesFunc != NULL)  {
3719 	status = ((GetDiscoveredPortAttributesFunc)
3720 	    (vendorHandle, portindex, discoveredportindex,
3721 	    portattributes));
3722 	} else {
3723 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3724 	}
3725 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3726 }
3727 
3728 HBA_STATUS
3729 SMHBA_GetPortAttributesByWWN(
3730     HBA_HANDLE		handle,
3731     HBA_WWN		portWWN,
3732     HBA_WWN		domainPortWWN,
3733     SMHBA_PORTATTRIBUTES	*portattributes)
3734 {
3735 	HBA_STATUS		status;
3736 	HBA_LIBRARY_INFO	*lib_infop;
3737 	HBA_HANDLE		vendorHandle;
3738 	SMHBAGetPortAttributesByWWNFunc
3739 	    GetPortAttributesByWWNFunc;
3740 
3741 	DEBUG(2, "SMHBA_GetPortAttributesByWWN: %s", WWN2STR1(&portWWN), 0, 0);
3742 
3743 	CHECKLIBRARYANDVERSION(SMHBA);
3744 
3745 	GetPortAttributesByWWNFunc =
3746 	    lib_infop->ftable.smhbafunctionTable.GetPortAttributesByWWNHandler;
3747 	if (GetPortAttributesByWWNFunc != NULL) {
3748 	status = ((GetPortAttributesByWWNFunc)
3749 	    (vendorHandle, portWWN, domainPortWWN, portattributes));
3750 	} else {
3751 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3752 	}
3753 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3754 }
3755 
3756 HBA_STATUS
3757 SMHBA_GetFCPhyAttributes(
3758     HBA_HANDLE		handle,
3759     HBA_UINT32		portindex,
3760     HBA_UINT32		phyindex,
3761     SMHBA_FC_PHY	*phytype)
3762 {
3763 	HBA_STATUS		status;
3764 	HBA_LIBRARY_INFO	*lib_infop;
3765 	HBA_HANDLE		vendorHandle;
3766 	SMHBAGetFCPhyAttributesFunc GetFCPhyAttributesFunc;
3767 
3768 	DEBUG(2, "SMHBA_GetFCPhyAttributesByWWN", 0, 0, 0);
3769 
3770 	CHECKLIBRARYANDVERSION(SMHBA);
3771 
3772 	GetFCPhyAttributesFunc =
3773 	    lib_infop->ftable.smhbafunctionTable.GetFCPhyAttributesHandler;
3774 	if (GetFCPhyAttributesFunc != NULL) {
3775 	status = ((GetFCPhyAttributesFunc)
3776 	    (vendorHandle, portindex, phyindex, phytype));
3777 	} else {
3778 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3779 	}
3780 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3781 }
3782 
3783 HBA_STATUS
3784 SMHBA_GetSASPhyAttributes(
3785     HBA_HANDLE		handle,
3786     HBA_UINT32		portindex,
3787     HBA_UINT32		phyindex,
3788     SMHBA_SAS_PHY	*phytype)
3789 {
3790 	HBA_STATUS		status;
3791 	HBA_LIBRARY_INFO	*lib_infop;
3792 	HBA_HANDLE		vendorHandle;
3793 	SMHBAGetSASPhyAttributesFunc GetSASPhyAttributesFunc;
3794 
3795 	DEBUG(2, "SMHBA_GetFCPhyAttributesByWWN", 0, 0, 0);
3796 
3797 	CHECKLIBRARYANDVERSION(SMHBA);
3798 
3799 	GetSASPhyAttributesFunc =
3800 	    lib_infop->ftable.smhbafunctionTable.GetSASPhyAttributesHandler;
3801 	if (GetSASPhyAttributesFunc != NULL) {
3802 	status = ((GetSASPhyAttributesFunc)
3803 	    (vendorHandle, portindex, phyindex, phytype));
3804 	} else {
3805 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3806 	}
3807 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3808 }
3809 
3810 HBA_STATUS
3811 SMHBA_GetProtocolStatistics(
3812     HBA_HANDLE		handle,
3813     HBA_UINT32		portindex,
3814     HBA_UINT32		protocoltype,
3815     SMHBA_PROTOCOLSTATISTICS *pProtocolStatistics)
3816 {
3817 	HBA_STATUS		status;
3818 	HBA_LIBRARY_INFO	*lib_infop;
3819 	HBA_HANDLE		vendorHandle;
3820 	SMHBAGetProtocolStatisticsFunc
3821 	    GetProtocolStatisticsFunc;
3822 
3823 	DEBUG(2, "SMHBA_GetProtocolStatistics port index: %d protocol type: %d",
3824 	    portindex, protocoltype, 0);
3825 
3826 	CHECKLIBRARYANDVERSION(SMHBA);
3827 
3828 	GetProtocolStatisticsFunc =
3829 	    lib_infop->ftable.smhbafunctionTable.GetProtocolStatisticsHandler;
3830 	if (GetProtocolStatisticsFunc != NULL) {
3831 	status = (GetProtocolStatisticsFunc)
3832 	    (vendorHandle, portindex, protocoltype, pProtocolStatistics);
3833 	} else {
3834 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3835 	}
3836 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3837 }
3838 
3839 HBA_STATUS
3840 SMHBA_GetPhyStatistics(
3841     HBA_HANDLE		handle,
3842     HBA_UINT32		portindex,
3843     HBA_UINT32		phyindex,
3844     SMHBA_PHYSTATISTICS *pPhyStatistics)
3845 {
3846 	HBA_STATUS		status;
3847 	HBA_LIBRARY_INFO	*lib_infop;
3848 	HBA_HANDLE		vendorHandle;
3849 	SMHBAGetPhyStatisticsFunc
3850 	    GetPhyStatisticsFunc;
3851 
3852 	DEBUG(2, "SMHBA_GetPhyStatistics port index: %d phy idex: %d",
3853 	    portindex, phyindex, 0);
3854 
3855 	CHECKLIBRARYANDVERSION(SMHBA);
3856 
3857 	GetPhyStatisticsFunc =
3858 	    lib_infop->ftable.smhbafunctionTable.GetPhyStatisticsHandler;
3859 	if (GetPhyStatisticsFunc != NULL) {
3860 	status = (GetPhyStatisticsFunc)
3861 	    (vendorHandle, portindex, phyindex, pPhyStatistics);
3862 	} else {
3863 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3864 	}
3865 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3866 }
3867 
3868 HBA_STATUS
3869 SMHBA_GetBindingCapability(
3870     HBA_HANDLE		handle,
3871     HBA_WWN		hbaPortWWN,
3872     HBA_WWN		domainPortWWN,
3873     SMHBA_BIND_CAPABILITY *pFlags)
3874 {
3875 	HBA_STATUS		status;
3876 	HBA_LIBRARY_INFO	*lib_infop;
3877 	HBA_HANDLE		vendorHandle;
3878 	SMHBAGetBindingCapabilityFunc GetBindingCapabilityFunc;
3879 
3880 	DEBUG(2, "HBA_GetBindingCapability", 0, 0, 0);
3881 
3882 	CHECKLIBRARYANDVERSION(SMHBA);
3883 
3884 	GetBindingCapabilityFunc =
3885 	    lib_infop->ftable.smhbafunctionTable.GetBindingCapabilityHandler;
3886 	if (GetBindingCapabilityFunc != NULL) {
3887 	status = (GetBindingCapabilityFunc)(vendorHandle, hbaPortWWN,
3888 	    domainPortWWN, pFlags);
3889 	} else {
3890 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3891 	}
3892 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3893 }
3894 
3895 HBA_STATUS
3896 SMHBA_GetBindingSupport(
3897     HBA_HANDLE		handle,
3898     HBA_WWN		hbaPortWWN,
3899     HBA_WWN		domainPortWWN,
3900     SMHBA_BIND_CAPABILITY *pFlags)
3901 {
3902 	HBA_STATUS		status;
3903 	HBA_LIBRARY_INFO	*lib_infop;
3904 	HBA_HANDLE		vendorHandle;
3905 	SMHBAGetBindingSupportFunc
3906 	    GetBindingSupporFunc;
3907 
3908 	DEBUG(2, "SMHBA_GetBindingSupport port: %s",
3909 	    WWN2STR1(&hbaPortWWN), 0, 0);
3910 
3911 	CHECKLIBRARYANDVERSION(SMHBA);
3912 
3913 	GetBindingSupporFunc =
3914 	    lib_infop->ftable.smhbafunctionTable.GetBindingSupportHandler;
3915 	if (GetBindingSupporFunc != NULL) {
3916 	status = (GetBindingSupporFunc)(vendorHandle,
3917 	    hbaPortWWN, domainPortWWN, pFlags);
3918 	} else {
3919 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3920 	}
3921 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3922 }
3923 
3924 HBA_STATUS
3925 SMHBA_SetBindingSupport(
3926     HBA_HANDLE		handle,
3927     HBA_WWN		hbaPortWWN,
3928     HBA_WWN		domainPortWWN,
3929     SMHBA_BIND_CAPABILITY flags)
3930 {
3931 	HBA_STATUS		status;
3932 	HBA_LIBRARY_INFO	*lib_infop;
3933 	HBA_HANDLE		vendorHandle;
3934 	SMHBASetBindingSupportFunc
3935 	    SetBindingSupporFunc;
3936 
3937 	DEBUG(2, "SMHBA_GetBindingSupport port: %s",
3938 	    WWN2STR1(&hbaPortWWN), 0, 0);
3939 
3940 	CHECKLIBRARYANDVERSION(HBAAPIV2);
3941 
3942 	SetBindingSupporFunc =
3943 	    lib_infop->ftable.smhbafunctionTable.SetBindingSupportHandler;
3944 	if (SetBindingSupporFunc != NULL) {
3945 	status = (SetBindingSupporFunc)
3946 	    (vendorHandle, hbaPortWWN, domainPortWWN, flags);
3947 	} else {
3948 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3949 	}
3950 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3951 }
3952 
3953 HBA_STATUS
3954 SMHBA_GetTargetMapping(
3955     HBA_HANDLE		handle,
3956     HBA_WWN		hbaPortWWN,
3957     HBA_WWN		domainPortWWN,
3958     SMHBA_TARGETMAPPING *pMapping)
3959 {
3960 	HBA_STATUS		status;
3961 	HBA_LIBRARY_INFO	*lib_infop;
3962 	HBA_HANDLE		vendorHandle;
3963 	SMHBAGetTargetMappingFunc GetTargetMappingFunc;
3964 
3965 	DEBUG(2, "SMHBA_GetTargetMapping port WWN: %s",
3966 	    WWN2STR1(&hbaPortWWN), 0, 0);
3967 
3968 	CHECKLIBRARYANDVERSION(SMHBA);
3969 
3970 	GetTargetMappingFunc =
3971 	    lib_infop->ftable.smhbafunctionTable.GetTargetMappingHandler;
3972 	if (GetTargetMappingFunc != NULL) {
3973 	status = ((GetTargetMappingFunc)(vendorHandle,
3974 	    hbaPortWWN, domainPortWWN, pMapping));
3975 	} else {
3976 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
3977 	}
3978 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
3979 }
3980 
3981 HBA_STATUS
3982 SMHBA_GetPersistentBinding(
3983     HBA_HANDLE handle,
3984     HBA_WWN	hbaPortWWN,
3985     HBA_WWN	domainPortWWN,
3986     SMHBA_BINDING *binding)
3987 {
3988 	HBA_STATUS		status;
3989 	HBA_LIBRARY_INFO	*lib_infop;
3990 	HBA_HANDLE		vendorHandle;
3991 	SMHBAGetPersistentBindingFunc
3992 	    GetPersistentBindingFunc;
3993 
3994 	DEBUG(2, "SMHBA_GetPersistentBinding port WWN: %s",
3995 	    WWN2STR1(&hbaPortWWN), 0, 0);
3996 
3997 	CHECKLIBRARYANDVERSION(SMHBA);
3998 
3999 	GetPersistentBindingFunc =
4000 	    lib_infop->ftable.smhbafunctionTable.GetPersistentBindingHandler;
4001 	if (GetPersistentBindingFunc != NULL) {
4002 	status = ((GetPersistentBindingFunc)(vendorHandle,
4003 	    hbaPortWWN, domainPortWWN, binding));
4004 	} else {
4005 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4006 	}
4007 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4008 }
4009 
4010 HBA_STATUS
4011 SMHBA_SetPersistentBinding(
4012     HBA_HANDLE handle,
4013     HBA_WWN	hbaPortWWN,
4014     HBA_WWN	domainPortWWN,
4015     const SMHBA_BINDING *binding)
4016 {
4017 	HBA_STATUS		status;
4018 	HBA_LIBRARY_INFO	*lib_infop;
4019 	HBA_HANDLE		vendorHandle;
4020 	SMHBASetPersistentBindingFunc
4021 	    SetPersistentBindingFunc;
4022 
4023 	DEBUG(2, "SMHBA_SetPersistentBinding port WWN: %s",
4024 	    WWN2STR1(&hbaPortWWN), 0, 0);
4025 
4026 	CHECKLIBRARYANDVERSION(SMHBA);
4027 
4028 	SetPersistentBindingFunc =
4029 	    lib_infop->ftable.smhbafunctionTable.SetPersistentBindingHandler;
4030 	if (SetPersistentBindingFunc != NULL) {
4031 	status = ((SetPersistentBindingFunc)(vendorHandle,
4032 	    hbaPortWWN, domainPortWWN, binding));
4033 	} else {
4034 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4035 	}
4036 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4037 }
4038 
4039 HBA_STATUS
4040 SMHBA_RemovePersistentBinding(
4041     HBA_HANDLE handle,
4042     HBA_WWN	hbaPortWWN,
4043     HBA_WWN	domainPortWWN,
4044     const SMHBA_BINDING *binding)
4045 {
4046 	HBA_STATUS		status;
4047 	HBA_LIBRARY_INFO	*lib_infop;
4048 	HBA_HANDLE		vendorHandle;
4049 	SMHBARemovePersistentBindingFunc
4050 	    RemovePersistentBindingFunc;
4051 
4052 	DEBUG(2, "SMHBA_RemovePersistentBinding port WWN: %s",
4053 	    WWN2STR1(&hbaPortWWN), 0, 0);
4054 
4055 	CHECKLIBRARYANDVERSION(SMHBA);
4056 
4057 	RemovePersistentBindingFunc =
4058 	    lib_infop->ftable.smhbafunctionTable.RemovePersistentBindingHandler;
4059 	if (RemovePersistentBindingFunc != NULL) {
4060 	status = ((RemovePersistentBindingFunc)(vendorHandle,
4061 	    hbaPortWWN, domainPortWWN, binding));
4062 	} else {
4063 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4064 	}
4065 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4066 }
4067 
4068 HBA_STATUS
4069 SMHBA_RemoveAllPersistentBindings(
4070     HBA_HANDLE handle,
4071     HBA_WWN	hbaPortWWN,
4072     HBA_WWN	domainPortWWN)
4073 {
4074 	HBA_STATUS		status;
4075 	HBA_LIBRARY_INFO	*lib_infop;
4076 	HBA_HANDLE		vendorHandle;
4077 	SMHBARemoveAllPersistentBindingsFunc
4078 	    RemoveAllPersistentBindingsFunc;
4079 
4080 	DEBUG(2, "SMHBA_RemoveAllPersistentBinding port WWN: %s",
4081 	    WWN2STR1(&hbaPortWWN), 0, 0);
4082 
4083 	CHECKLIBRARYANDVERSION(SMHBA);
4084 
4085 	RemoveAllPersistentBindingsFunc =
4086 	    lib_infop->ftable.smhbafunctionTable.\
4087 	    RemoveAllPersistentBindingsHandler;
4088 	if (RemoveAllPersistentBindingsFunc != NULL) {
4089 	status = ((RemoveAllPersistentBindingsFunc)(vendorHandle,
4090 	    hbaPortWWN, domainPortWWN));
4091 	} else {
4092 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4093 	}
4094 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4095 }
4096 
4097 HBA_STATUS
4098 SMHBA_GetLUNStatistics(
4099     HBA_HANDLE handle,
4100     const HBA_SCSIID *lunit,
4101     SMHBA_PROTOCOLSTATISTICS *statistics)
4102 {
4103 	HBA_STATUS		status;
4104 	HBA_LIBRARY_INFO	*lib_infop;
4105 	HBA_HANDLE		vendorHandle;
4106 	SMHBAGetLUNStatisticsFunc GetLUNStatisticsFunc;
4107 
4108 	DEBUG(2, "SMHBA_GetLUNStatistics", 0, 0, 0);
4109 
4110 	CHECKLIBRARYANDVERSION(SMHBA);
4111 
4112 	GetLUNStatisticsFunc =
4113 	    lib_infop->ftable.smhbafunctionTable.GetLUNStatisticsHandler;
4114 	if (GetLUNStatisticsFunc != NULL) {
4115 	status = ((GetLUNStatisticsFunc)(vendorHandle, lunit, statistics));
4116 	} else {
4117 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4118 	}
4119 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4120 }
4121 
4122 HBA_STATUS
4123 SMHBA_ScsiInquiry(
4124     HBA_HANDLE	handle,
4125     HBA_WWN	hbaPortWWN,
4126     HBA_WWN	discoveredPortWWN,
4127     HBA_WWN	domainPortWWN,
4128     SMHBA_SCSILUN	smhbaLUN,
4129     HBA_UINT8	CDB_Byte1,
4130     HBA_UINT8	CDB_Byte2,
4131     void	*pRspBuffer,
4132     HBA_UINT32	*pRspBufferSize,
4133     HBA_UINT8	*pScsiStatus,
4134     void	*pSenseBuffer,
4135     HBA_UINT32	*pSenseBufferSize)
4136 {
4137 	HBA_STATUS		status;
4138 	HBA_LIBRARY_INFO	*lib_infop;
4139 	HBA_HANDLE		vendorHandle;
4140 	SMHBAScsiInquiryFunc ScsiInquiryFunc;
4141 
4142 	DEBUG(2, "SMHBA_ScsiInquiry to hba port: %s discoveredPortWWN: %s",
4143 	    WWN2STR1(&hbaPortWWN), WWN2STR1(&discoveredPortWWN), 0);
4144 
4145 	CHECKLIBRARYANDVERSION(SMHBA);
4146 
4147 	ScsiInquiryFunc =
4148 	    lib_infop->ftable.smhbafunctionTable.ScsiInquiryHandler;
4149 	if (ScsiInquiryFunc != NULL) {
4150 	status = ((ScsiInquiryFunc)(
4151 	    vendorHandle, hbaPortWWN, discoveredPortWWN, domainPortWWN,
4152 	    smhbaLUN, CDB_Byte1, CDB_Byte2, pRspBuffer, pRspBufferSize,
4153 	    pScsiStatus, pSenseBuffer, pSenseBufferSize));
4154 	} else {
4155 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4156 	}
4157 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4158 }
4159 
4160 HBA_STATUS
4161 SMHBA_ScsiReportLUNs(
4162     HBA_HANDLE	handle,
4163     HBA_WWN	hbaPortWWN,
4164     HBA_WWN	discoveredPortWWN,
4165     HBA_WWN	domainPortWWN,
4166     void	*pRspBuffer,
4167     HBA_UINT32	*pRspBufferSize,
4168     HBA_UINT8	*pScsiStatus,
4169     void	*pSenseBuffer,
4170     HBA_UINT32	*pSenseBufferSize)
4171 {
4172 	HBA_STATUS		status;
4173 	HBA_LIBRARY_INFO	*lib_infop;
4174 	HBA_HANDLE		vendorHandle;
4175 	SMHBAScsiReportLUNsFunc ScsiReportLUNsFunc;
4176 
4177 	DEBUG(2, "SMHBA_ScsiReportLuns to hba port: %s discoveredPortWWN: %s",
4178 	    WWN2STR1(&hbaPortWWN), WWN2STR1(&discoveredPortWWN), 0);
4179 
4180 	CHECKLIBRARYANDVERSION(SMHBA);
4181 
4182 	ScsiReportLUNsFunc =
4183 	    lib_infop->ftable.smhbafunctionTable.ScsiReportLUNsHandler;
4184 	if (ScsiReportLUNsFunc != NULL) {
4185 	status = ((ScsiReportLUNsFunc)(
4186 	    vendorHandle, hbaPortWWN, discoveredPortWWN, domainPortWWN,
4187 	    pRspBuffer, pRspBufferSize, pScsiStatus, pSenseBuffer,
4188 	    pSenseBufferSize));
4189 	} else {
4190 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4191 	}
4192 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4193 }
4194 
4195 HBA_STATUS
4196 SMHBA_ScsiReadCapacity(
4197     HBA_HANDLE	handle,
4198     HBA_WWN	hbaPortWWN,
4199     HBA_WWN	discoveredPortWWN,
4200     HBA_WWN	domainPortWWN,
4201     SMHBA_SCSILUN	smhbaLUN,
4202     void	*pRspBuffer,
4203     HBA_UINT32	*pRspBufferSize,
4204     HBA_UINT8	*pScsiStatus,
4205     void	*pSenseBuffer,
4206     HBA_UINT32	*pSenseBufferSize)
4207 {
4208 	HBA_STATUS		status;
4209 	HBA_LIBRARY_INFO	*lib_infop;
4210 	HBA_HANDLE		vendorHandle;
4211 	SMHBAScsiReadCapacityFunc ScsiReadCapacityFunc;
4212 
4213 	DEBUG(2, "SMHBA_ScsiReadCapacity to hba port: %s discoveredPortWWN: %s",
4214 	    WWN2STR1(&hbaPortWWN), WWN2STR1(&discoveredPortWWN), 0);
4215 
4216 	CHECKLIBRARYANDVERSION(SMHBA);
4217 
4218 	ScsiReadCapacityFunc =
4219 	    lib_infop->ftable.smhbafunctionTable.ScsiReadCapacityHandler;
4220 	if (ScsiReadCapacityFunc != NULL) {
4221 	status = ((ScsiReadCapacityFunc)(
4222 	    vendorHandle, hbaPortWWN, discoveredPortWWN, domainPortWWN,
4223 	    smhbaLUN, pRspBuffer, pRspBufferSize, pScsiStatus, pSenseBuffer,
4224 	    pSenseBufferSize));
4225 	} else {
4226 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4227 	}
4228 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4229 }
4230 
4231 HBA_STATUS
4232 SMHBA_SendTEST(
4233     HBA_HANDLE		handle,
4234     HBA_WWN		hbaPortWWN,
4235     HBA_WWN		destWWN,
4236     HBA_UINT32		destFCID,
4237     void		*pRspBuffer,
4238     HBA_UINT32		pRspBufferSize)
4239 {
4240 	HBA_STATUS		status;
4241 	HBA_LIBRARY_INFO	*lib_infop;
4242 	HBA_HANDLE		vendorHandle;
4243 	SMHBASendTESTFunc	SendTESTFunc;
4244 
4245 	DEBUG(2, "SMHBA_SendTEST, hbaPortWWN: %s destWWN",
4246 	    WWN2STR1(&hbaPortWWN),
4247 	    WWN2STR1(&destWWN), 0);
4248 
4249 	CHECKLIBRARYANDVERSION(SMHBA);
4250 
4251 	SendTESTFunc = lib_infop->ftable.smhbafunctionTable.SendTESTHandler;
4252 	if (SendTESTFunc != NULL) {
4253 	status = (SendTESTFunc)
4254 	    (vendorHandle, hbaPortWWN, destWWN, destFCID,
4255 	    pRspBuffer, pRspBufferSize);
4256 	} else {
4257 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4258 	}
4259 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4260 }
4261 
4262 HBA_STATUS
4263 SMHBA_SendECHO(
4264     HBA_HANDLE		handle,
4265     HBA_WWN		hbaPortWWN,
4266     HBA_WWN		destWWN,
4267     HBA_UINT32		destFCID,
4268     void		*pReqBuffer,
4269     HBA_UINT32		ReqBufferSize,
4270     void		*pRspBuffer,
4271     HBA_UINT32		*pRspBufferSize)
4272 {
4273 	HBA_STATUS		status;
4274 	HBA_LIBRARY_INFO	*lib_infop;
4275 	HBA_HANDLE		vendorHandle;
4276 	SMHBASendECHOFunc	SendECHOFunc;
4277 
4278 	DEBUG(2, "SMHBA_SendECHO, hbaPortWWN: %s destWWN",
4279 	    WWN2STR1(&hbaPortWWN), WWN2STR1(&destWWN), 0);
4280 
4281 	CHECKLIBRARYANDVERSION(SMHBA);
4282 
4283 	SendECHOFunc = lib_infop->ftable.smhbafunctionTable.SendECHOHandler;
4284 	if (SendECHOFunc != NULL) {
4285 	status = (SendECHOFunc)
4286 	    (vendorHandle, hbaPortWWN, destWWN, destFCID,
4287 	    pReqBuffer, ReqBufferSize, pRspBuffer, pRspBufferSize);
4288 	} else {
4289 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4290 	}
4291 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4292 }
4293 
4294 HBA_STATUS
4295 SMHBA_SendSMPPassThru(
4296     HBA_HANDLE		handle,
4297     HBA_WWN		hbaPortWWN,
4298     HBA_WWN		destWWN,
4299     HBA_WWN		domainPortWWN,
4300     void		*pReqBuffer,
4301     HBA_UINT32		ReqBufferSize,
4302     void		*pRspBuffer,
4303     HBA_UINT32		*pRspBufferSize)
4304 {
4305 	HBA_STATUS		status;
4306 	HBA_LIBRARY_INFO	*lib_infop;
4307 	HBA_HANDLE		vendorHandle;
4308 	SMHBASendSMPPassThruFunc	SendSMPPassThruFunc;
4309 
4310 	DEBUG(2, "SMHBA_SendSMPPassThru, hbaPortWWN: %s destWWN: %s",
4311 	    WWN2STR1(&hbaPortWWN), WWN2STR1(&destWWN), 0);
4312 
4313 	CHECKLIBRARYANDVERSION(SMHBA);
4314 
4315 	SendSMPPassThruFunc = lib_infop->ftable.\
4316 	    smhbafunctionTable.SendSMPPassThruHandler;
4317 
4318 	if (SendSMPPassThruFunc != NULL) {
4319 	status = (SendSMPPassThruFunc)
4320 	    (vendorHandle, hbaPortWWN, destWWN, domainPortWWN,
4321 	    pReqBuffer, ReqBufferSize, pRspBuffer, pRspBufferSize);
4322 	} else {
4323 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4324 	}
4325 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4326 }
4327 
4328 /*
4329  * Following the similar logic of HBAAPI addaspterevents_callback.
4330  *
4331  * Unlike other events Adapter Add Event is not limited to a specific
4332  * adpater(i.e. no adatper handle is passed for registration) so
4333  * the event should be passed to all registrants.  The routine below
4334  * is passed to the VSLs as a callback and when Adapter Add event is detected
4335  * by VSL it will call smhba_adapteraddevents_callback() which in turn check
4336  * if the passed userdata ptr matches with the one stored in the callback list
4337  * and calls the stored callback.
4338  *
4339  * For the situation that multiple clients are registered for Adapter Add event
4340  * each registration is passed to VSLs so VSL may call
4341  * smhba_adapteraddevents_callback() multiple times or it may call only once
4342  * since the callback function is same.  For this implemneation, the userdata
4343  * is stored in HBA_ALLADAPTERSCALLBACK_ELEM so it is expected that VSL call
4344  * smhba_adapteraddevents_callback() only once and
4345  * smhba_adapteraddevents_callback() will call the client callback with proper
4346  * userdata.
4347  */
4348 static void
4349 smhba_adapteraddevents_callback(
4350 /* LINTED E_FUNC_ARG_UNUSED */
4351     void *data,
4352     HBA_WWN PortWWN,
4353 /* LINTED E_FUNC_ARG_UNUSED */
4354     HBA_UINT32 eventType)
4355 {
4356 	HBA_ALLADAPTERSCALLBACK_ELEM	*cbp;
4357 
4358 	DEBUG(3, "AddAdapterEvent, port:%s", WWN2STR1(&PortWWN), 0, 0);
4359 
4360 	GRAB_MUTEX(&_smhba_AAE_mutex);
4361 	for (cbp = _smhba_adapteraddevents_callback_list;
4362 	    cbp != NULL;
4363 	    cbp = cbp->next) {
4364 	(*cbp->callback)(cbp->userdata, PortWWN, HBA_EVENT_ADAPTER_ADD);
4365 	}
4366 	RELEASE_MUTEX(&_smhba_AAE_mutex);
4367 
4368 }
4369 
4370 HBA_STATUS
4371 SMHBA_RegisterForAdapterAddEvents(
4372     void		(*pCallback) (
4373 	void		*data,
4374 	HBA_WWN		PortWWN,
4375 	HBA_UINT32	eventType),
4376     void		*pUserData,
4377     HBA_CALLBACKHANDLE  *pCallbackHandle) {
4378 
4379     HBA_ALLADAPTERSCALLBACK_ELEM	*cbp;
4380     HBA_VENDORCALLBACK_ELEM		*vcbp;
4381     HBA_VENDORCALLBACK_ELEM		*vendorhandlelist;
4382     SMHBARegisterForAdapterAddEventsFunc	registeredfunc;
4383     HBA_STATUS				status = HBA_STATUS_OK;
4384     HBA_STATUS				failure = HBA_STATUS_OK;
4385     HBA_LIBRARY_INFO			*lib_infop;
4386     int					registered_cnt = 0;
4387     int					vendor_cnt = 0;
4388     int					not_supported_cnt = 0;
4389     int					status_OK_bar_cnt = 0;
4390     int					status_OK_cnt = 0;
4391 
4392     DEBUG(2, "SMHBA_RegisterForAdapterAddEvents", 0, 0, 0);
4393     ARE_WE_INITED();
4394 
4395     cbp = (HBA_ALLADAPTERSCALLBACK_ELEM *)
4396 	    calloc(1, sizeof (HBA_ALLADAPTERSCALLBACK_ELEM));
4397 	*pCallbackHandle = (HBA_CALLBACKHANDLE) cbp;
4398     if (cbp == NULL) {
4399 	return (HBA_STATUS_ERROR);
4400 	}
4401 
4402     GRAB_MUTEX(&_hbaapi_LL_mutex);
4403     GRAB_MUTEX(&_smhba_AAE_mutex);
4404     cbp->callback = pCallback;
4405     cbp->userdata = pUserData;
4406     cbp->next = _smhba_adapteraddevents_callback_list;
4407     _smhba_adapteraddevents_callback_list = cbp;
4408 
4409 	/*
4410 	 * Need to release the mutex now incase the vendor function invokes the
4411 	 * callback.  We will grap the mutex later to attach the vendor handle
4412 	 * list to the callback structure
4413 	 */
4414 	RELEASE_MUTEX(&_smhba_AAE_mutex);
4415 
4416 
4417 	/*
4418 	 * now create a list of vendors (vendor libraryies, NOT ADAPTERS)
4419 	 * that have successfully registerred
4420 	 */
4421     vendorhandlelist = NULL;
4422     for (lib_infop = _hbaapi_librarylist;
4423 	lib_infop != NULL;
4424 	lib_infop = lib_infop->next) {
4425 
4426 	/* only for HBAAPI V2 */
4427 	if (lib_infop->version != SMHBA) {
4428 	    continue;
4429 	} else {
4430 	    vendor_cnt++;
4431 	}
4432 
4433 	registeredfunc =
4434 	    lib_infop->ftable.smhbafunctionTable.\
4435 	    RegisterForAdapterAddEventsHandler;
4436 	if (registeredfunc == NULL) {
4437 	    continue;
4438 	}
4439 
4440 	vcbp = (HBA_VENDORCALLBACK_ELEM *)
4441 	    calloc(1, sizeof (HBA_VENDORCALLBACK_ELEM));
4442 	if (vcbp == NULL) {
4443 	    freevendorhandlelist(vendorhandlelist);
4444 	    status = HBA_STATUS_ERROR;
4445 	    break;
4446 	}
4447 
4448 	registered_cnt++;
4449 	status = (registeredfunc)(smhba_adapteraddevents_callback,
4450 	    pUserData, &vcbp->vendorcbhandle);
4451 	if (status == HBA_STATUS_ERROR_NOT_SUPPORTED) {
4452 	    not_supported_cnt++;
4453 	    free(vcbp);
4454 	    continue;
4455 	} else if (status != HBA_STATUS_OK) {
4456 	    status_OK_bar_cnt++;
4457 	    DEBUG(1,
4458 		    "SMHBA_RegisterForAdapterAddEvents: Library->%s, Error->%d",
4459 		    lib_infop->LibraryPath, status, 0);
4460 	    failure = status;
4461 	    free(vcbp);
4462 	    continue;
4463 	} else {
4464 	    status_OK_cnt++;
4465 	}
4466 	vcbp->lib_info = lib_infop;
4467 	vcbp->next = vendorhandlelist;
4468 	vendorhandlelist = vcbp;
4469 	}
4470 
4471     if (vendor_cnt == 0) {
4472 	/* no SMHBA VSL found.  Should be okay?? */
4473 	status = HBA_STATUS_ERROR;
4474 	} else if (registered_cnt == 0) {
4475 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4476 	freevendorhandlelist(vendorhandlelist);
4477 	(void) local_remove_callback((HBA_CALLBACKHANDLE) cbp);
4478 	} else if (status_OK_cnt == 0 && not_supported_cnt != 0) {
4479 	status = HBA_STATUS_ERROR_NOT_SUPPORTED;
4480 	} else if (status_OK_cnt == 0) {
4481 	/*
4482 	 * At least one vendor library registered this function, but no
4483 	 * vendor call succeeded
4484 	 */
4485 	(void) local_remove_callback((HBA_CALLBACKHANDLE) cbp);
4486 	status = failure;
4487 	} else {
4488 	/* we have had atleast some success, now finish up */
4489 	GRAB_MUTEX(&_smhba_AAE_mutex);
4490 	/*
4491 	 * this seems silly, but what if another thread called
4492 	 * the callback remove
4493 	 */
4494 	for (cbp = _smhba_adapteraddevents_callback_list;
4495 	    cbp != NULL; cbp = cbp->next) {
4496 	    if ((HBA_CALLBACKHANDLE)cbp == *pCallbackHandle) {
4497 		/* yup, its still there, hooray */
4498 		cbp->vendorhandlelist = vendorhandlelist;
4499 		vendorhandlelist = NULL;
4500 		break;
4501 	    }
4502 	}
4503 	RELEASE_MUTEX(&_smhba_AAE_mutex);
4504 	if (vendorhandlelist != NULL) {
4505 		/*
4506 		 * bummer, somebody removed the callback before we finished
4507 		 * registration, probably will never happen
4508 		 */
4509 	    freevendorhandlelist(vendorhandlelist);
4510 	    DEBUG(1,
4511 		    "HBA_RegisterForAdapterAddEvents: HBA_RemoveCallback was "
4512 		    "called for a handle before registration was finished.",
4513 		    0, 0, 0);
4514 	    status = HBA_STATUS_ERROR;
4515 	} else {
4516 	    status = HBA_STATUS_OK;
4517 	}
4518 	}
4519     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4520 }
4521 
4522 /* SMHBA Adapter Events (other than add) ******************************** */
4523 static void
4524 smhba_adapterevents_callback(void *data,
4525 			HBA_WWN PortWWN,
4526 			HBA_UINT32 eventType)
4527 {
4528 	HBA_ADAPTERCALLBACK_ELEM	*acbp;
4529 
4530 	DEBUG(3, "AdapterEvent, port:%s, eventType:%d", WWN2STR1(&PortWWN),
4531 	    eventType, 0);
4532 
4533 	GRAB_MUTEX(&_hbaapi_AE_mutex);
4534 	for (acbp = _smhba_adapterevents_callback_list;
4535 	    acbp != NULL;
4536 	    acbp = acbp->next) {
4537 	if (data == (void *)acbp) {
4538 		(*acbp->callback)(acbp->userdata, PortWWN, eventType);
4539 		break;
4540 	}
4541 	}
4542 	RELEASE_MUTEX(&_hbaapi_AE_mutex);
4543 }
4544 
4545 HBA_STATUS
4546 SMHBA_RegisterForAdapterEvents(
4547     void		(*pCallback) (
4548 	void		*data,
4549 	HBA_WWN		PortWWN,
4550 	HBA_UINT32	eventType),
4551     void		*pUserData,
4552     HBA_HANDLE		handle,
4553     HBA_CALLBACKHANDLE	*pCallbackHandle) {
4554 
4555 	HBA_ADAPTERCALLBACK_ELEM		*acbp;
4556 	SMHBARegisterForAdapterEventsFunc	registeredfunc;
4557 	HBA_STATUS				status;
4558 	HBA_LIBRARY_INFO			*lib_infop;
4559 	HBA_HANDLE				vendorHandle;
4560 
4561 	DEBUG(2, "SMHBA_RegisterForAdapterEvents", 0, 0, 0);
4562 
4563 	CHECKLIBRARYANDVERSION(SMHBA);
4564 
4565 	/* we now have the _hbaapi_LL_mutex */
4566 
4567 	registeredfunc = lib_infop->ftable.smhbafunctionTable.\
4568 	    RegisterForAdapterEventsHandler;
4569     if (registeredfunc == NULL) {
4570 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
4571 	}
4572 
4573 	/*
4574 	 * that allocated memory is used both as the handle for the
4575 	 * caller, and as userdata to the vendor call so that on
4576 	 * callback the specific registration may be recalled
4577 	 */
4578 	acbp = (HBA_ADAPTERCALLBACK_ELEM *)
4579 	    calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
4580 	if (acbp == NULL) {
4581 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
4582 	}
4583 	*pCallbackHandle = (HBA_CALLBACKHANDLE) acbp;
4584 	acbp->callback = pCallback;
4585 	acbp->userdata = pUserData;
4586 	acbp->lib_info = lib_infop;
4587 
4588 	status = (registeredfunc)(smhba_adapterevents_callback,
4589 	    (void *)acbp,
4590 	    vendorHandle,
4591 	    &acbp->vendorcbhandle);
4592     if (status != HBA_STATUS_OK) {
4593 	free(acbp);
4594 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4595 	}
4596 
4597 	GRAB_MUTEX(&_smhba_AE_mutex);
4598 	acbp->next = _smhba_adapterevents_callback_list;
4599 	    _hbaapi_adapterevents_callback_list = acbp;
4600 
4601 	RELEASE_MUTEX(&_smhba_AE_mutex);
4602 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
4603 }
4604 
4605 /* Adapter Port Events *********************************************** */
4606 static void
4607 smhba_adapterportevents_callback(void *data,
4608 			    HBA_WWN PortWWN,
4609 			    HBA_UINT32 eventType,
4610 			    HBA_UINT32 fabricPortID)
4611 {
4612 	HBA_ADAPTERCALLBACK_ELEM	*acbp;
4613 
4614 	DEBUG(3,
4615 	    "SMHBA_AdapterPortEvent, port:%s, eventType:%d fabricPortID:0X%06x",
4616 	    WWN2STR1(&PortWWN), eventType, fabricPortID);
4617 
4618 	GRAB_MUTEX(&_smhba_APE_mutex);
4619 
4620 	for (acbp = _smhba_adapterportevents_callback_list;
4621 	    acbp != NULL;
4622 	    acbp = acbp->next) {
4623 	if (data == (void *)acbp) {
4624 		(*acbp->callback)(acbp->userdata, PortWWN,
4625 		    eventType, fabricPortID);
4626 		break;
4627 	}
4628 	}
4629 	RELEASE_MUTEX(&_smhba_APE_mutex);
4630 }
4631 
4632 HBA_STATUS
4633 SMHBA_RegisterForAdapterPortEvents(
4634     void		(*pCallback) (
4635 	void		*pData,
4636 	HBA_WWN		PortWWN,
4637 	HBA_UINT32	eventType,
4638 	HBA_UINT32	fabricPortID),
4639     void		*pUserData,
4640     HBA_HANDLE		handle,
4641     HBA_WWN		portWWN,
4642     HBA_UINT32		specificEventType,
4643     HBA_CALLBACKHANDLE	*pCallbackHandle) {
4644 
4645 	HBA_ADAPTERCALLBACK_ELEM		*acbp;
4646 	SMHBARegisterForAdapterPortEventsFunc	registeredfunc;
4647 	HBA_STATUS				status;
4648 	HBA_LIBRARY_INFO			*lib_infop;
4649 	HBA_HANDLE				vendorHandle;
4650 
4651 	DEBUG(2, "SMHBA_RegisterForAdapterPortEvents for port: %s",
4652 	    WWN2STR1(&portWWN), 0, 0);
4653 
4654 	CHECKLIBRARYANDVERSION(SMHBA);
4655 	/* we now have the _hbaapi_LL_mutex */
4656 
4657 	registeredfunc =
4658 	    lib_infop->ftable.smhbafunctionTable.\
4659 	    RegisterForAdapterPortEventsHandler;
4660 	if (registeredfunc == NULL) {
4661 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
4662 	}
4663 
4664 	/*
4665 	 * that allocated memory is used both as the handle for the
4666 	 * caller, and as userdata to the vendor call so that on
4667 	 * callback the specific registration may be recalled
4668 	 */
4669 	acbp = (HBA_ADAPTERCALLBACK_ELEM *)
4670 	    calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
4671 	if (acbp == NULL) {
4672 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
4673 	}
4674 	*pCallbackHandle = (HBA_CALLBACKHANDLE) acbp;
4675 	acbp->callback = pCallback;
4676 	acbp->userdata = pUserData;
4677 	acbp->lib_info = lib_infop;
4678 
4679 	status = (registeredfunc)(smhba_adapterportevents_callback,
4680 	    (void *)acbp,
4681 	    vendorHandle,
4682 	    portWWN,
4683 	    specificEventType,
4684 	    &acbp->vendorcbhandle);
4685 	if (status != HBA_STATUS_OK) {
4686 	free(acbp);
4687 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4688 	}
4689 
4690 	GRAB_MUTEX(&_smhba_APE_mutex);
4691 	acbp->next = _smhba_adapterportevents_callback_list;
4692 	_smhba_adapterportevents_callback_list = acbp;
4693 
4694 	RELEASE_MUTEX(&_smhba_APE_mutex);
4695 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
4696 }
4697 
4698 /* SMHBA Adapter Port Stat Events ******************************** */
4699 static void
4700 smhba_adapterportstatevents_callback(void *data,
4701 				HBA_WWN portWWN,
4702 				HBA_UINT32 protocolType,
4703 				HBA_UINT32 eventType)
4704 {
4705 	HBA_ADAPTERCALLBACK_ELEM	*acbp;
4706 
4707 	DEBUG(3,
4708 	    "SMBA_AdapterPortStateEvent, port:%s, eventType:%d",
4709 	    WWN2STR1(&portWWN), eventType, 0);
4710 
4711 	GRAB_MUTEX(&_smhba_APSE_mutex);
4712 	for (acbp = _smhba_adapterportstatevents_callback_list;
4713 	    acbp != NULL;
4714 	    acbp = acbp->next) {
4715 	if (data == (void *)acbp) {
4716 		(*acbp->callback)(acbp->userdata, portWWN,
4717 		    protocolType, eventType);
4718 		return;
4719 	}
4720 	}
4721 	RELEASE_MUTEX(&_smhba_APSE_mutex);
4722 }
4723 
4724 HBA_STATUS
4725 SMHBA_RegisterForAdapterPortStatEvents(
4726     void		(*pCallback) (
4727 	void		*pData,
4728 	HBA_WWN		portWWN,
4729 	HBA_UINT32	protocolType,
4730 	HBA_UINT32	eventType),
4731     void		*pUserData,
4732     HBA_HANDLE		handle,
4733     HBA_WWN		portWWN,
4734     HBA_UINT32		protocolType,
4735     SMHBA_PROTOCOLSTATISTICS	stats,
4736     HBA_UINT32		statType,
4737     HBA_CALLBACKHANDLE	*pCallbackHandle) {
4738 
4739 	HBA_ADAPTERCALLBACK_ELEM	*acbp;
4740 	SMHBARegisterForAdapterPortStatEventsFunc
4741 	    registeredfunc;
4742 	HBA_STATUS			status;
4743 	HBA_LIBRARY_INFO		*lib_infop;
4744 	HBA_HANDLE			vendorHandle;
4745 
4746 	DEBUG(2, "SMHBA_RegisterForAdapterPortStatEvents for port: %s",
4747 	    WWN2STR1(&portWWN), 0, 0);
4748 
4749 	CHECKLIBRARYANDVERSION(SMHBA);
4750 	/* we now have the _hbaapi_LL_mutex */
4751 
4752 	registeredfunc =
4753 	    lib_infop->ftable.smhbafunctionTable.\
4754 	    RegisterForAdapterPortStatEventsHandler;
4755 	if (registeredfunc == NULL) {
4756 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
4757 	}
4758 
4759 	/*
4760 	 * that allocated memory is used both as the handle for the
4761 	 * caller, and as userdata to the vendor call so that on
4762 	 * callback the specific registration may be recalled
4763 	 */
4764 	acbp = (HBA_ADAPTERCALLBACK_ELEM *)
4765 	    calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
4766 	if (acbp == NULL) {
4767 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
4768 	}
4769 	*pCallbackHandle = (HBA_CALLBACKHANDLE) acbp;
4770 	acbp->callback = pCallback;
4771 	acbp->userdata = pUserData;
4772 	acbp->lib_info = lib_infop;
4773 
4774 	status = (registeredfunc)(smhba_adapterportstatevents_callback,
4775 	    (void *)acbp,
4776 	    vendorHandle,
4777 	    portWWN,
4778 	    protocolType,
4779 	    stats,
4780 	    statType,
4781 	    &acbp->vendorcbhandle);
4782 	if (status != HBA_STATUS_OK) {
4783 	free(acbp);
4784 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4785 	}
4786 
4787 	GRAB_MUTEX(&_smhba_APSE_mutex);
4788 	acbp->next = _smhba_adapterportstatevents_callback_list;
4789 	_smhba_adapterportstatevents_callback_list = acbp;
4790 
4791 	RELEASE_MUTEX(&_smhba_APSE_mutex);
4792 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
4793 }
4794 
4795 /* SMHBA Adapter Port Phy Stat Events ************************************ */
4796 static void
4797 smhba_adapterphystatevents_callback(void *data,
4798 				HBA_WWN portWWN,
4799 				HBA_UINT32 phyIndex,
4800 				HBA_UINT32 eventType)
4801 {
4802 	HBA_ADAPTERCALLBACK_ELEM	*acbp;
4803 
4804 	DEBUG(3,
4805 	    "SMBA_AdapterPortStateEvent, port:%s, eventType:%d",
4806 	    WWN2STR1(&portWWN), eventType, 0);
4807 
4808 	GRAB_MUTEX(&_smhba_APHYSE_mutex);
4809 	for (acbp = _smhba_adapterphystatevents_callback_list;
4810 	    acbp != NULL;
4811 	    acbp = acbp->next) {
4812 	if (data == (void *)acbp) {
4813 		(*acbp->callback)(acbp->userdata, portWWN, phyIndex, eventType);
4814 		return;
4815 	}
4816 	}
4817 	RELEASE_MUTEX(&_smhba_APHYSE_mutex);
4818 }
4819 
4820 HBA_STATUS
4821 SMHBA_RegisterForAdapterPhyStatEvents(
4822     void		(*pCallback) (
4823 	void		*pData,
4824 	HBA_WWN		portWWN,
4825 	HBA_UINT32	phyIndex,
4826 	HBA_UINT32	eventType),
4827     void		*pUserData,
4828     HBA_HANDLE		handle,
4829     HBA_WWN		portWWN,
4830     HBA_UINT32		phyIndex,
4831     SMHBA_PHYSTATISTICS	stats,
4832     HBA_UINT32		statType,
4833     HBA_CALLBACKHANDLE	*pCallbackHandle) {
4834 
4835 	HBA_ADAPTERCALLBACK_ELEM	*acbp;
4836 	SMHBARegisterForAdapterPhyStatEventsFunc
4837 	    registeredfunc;
4838 	HBA_STATUS			status;
4839 	HBA_LIBRARY_INFO		*lib_infop;
4840 	HBA_HANDLE			vendorHandle;
4841 
4842 	DEBUG(2, "SMHBA_RegisterForAdapterPhyStatEvents for port: %s",
4843 	    WWN2STR1(&portWWN), 0, 0);
4844 
4845 	CHECKLIBRARYANDVERSION(SMHBA);
4846 	/* we now have the _hbaapi_LL_mutex */
4847 
4848 	registeredfunc =
4849 	    lib_infop->ftable.smhbafunctionTable.\
4850 	    RegisterForAdapterPhyStatEventsHandler;
4851 	if (registeredfunc == NULL) {
4852 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
4853 	}
4854 
4855 	/*
4856 	 * that allocated memory is used both as the handle for the
4857 	 * caller, and as userdata to the vendor call so that on
4858 	 * callback the specific registration may be recalled
4859 	 */
4860 	acbp = (HBA_ADAPTERCALLBACK_ELEM *)
4861 	    calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
4862 	if (acbp == NULL) {
4863 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
4864 	}
4865 	*pCallbackHandle = (HBA_CALLBACKHANDLE) acbp;
4866 	acbp->callback = pCallback;
4867 	acbp->userdata = pUserData;
4868 	acbp->lib_info = lib_infop;
4869 
4870 	status = (registeredfunc)(smhba_adapterphystatevents_callback,
4871 	    (void *)acbp,
4872 	    vendorHandle,
4873 	    portWWN,
4874 	    phyIndex,
4875 	    stats,
4876 	    statType,
4877 	    &acbp->vendorcbhandle);
4878 	if (status != HBA_STATUS_OK) {
4879 	free(acbp);
4880 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4881 	}
4882 
4883 	GRAB_MUTEX(&_smhba_APHYSE_mutex);
4884 	acbp->next = _smhba_adapterphystatevents_callback_list;
4885 	_smhba_adapterphystatevents_callback_list = acbp;
4886 
4887 	RELEASE_MUTEX(&_smhba_APHYSE_mutex);
4888 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
4889 }
4890 
4891 /* SMHBA Target Events ********************************************* */
4892 static void
4893 smhba_targetevents_callback(void *data,
4894 	HBA_WWN hbaPortWWN,
4895 	HBA_WWN discoveredPortWWN,
4896 	HBA_WWN domainPortWWN,
4897 	HBA_UINT32 eventType)
4898 {
4899 	HBA_ADAPTERCALLBACK_ELEM	*acbp;
4900 
4901 	DEBUG(3, "TargetEvent, hbaPort:%s, discoveredPort:%s eventType:%d",
4902 	    WWN2STR1(&hbaPortWWN), WWN2STR2(&discoveredPortWWN), eventType);
4903 
4904 	GRAB_MUTEX(&_smhba_TE_mutex);
4905 	for (acbp = _smhba_targetevents_callback_list;
4906 	    acbp != NULL;
4907 	    acbp = acbp->next) {
4908 	if (data == (void *)acbp) {
4909 		(*acbp->callback)(acbp->userdata, hbaPortWWN,
4910 		    discoveredPortWWN, domainPortWWN, eventType);
4911 		break;
4912 	}
4913 	}
4914 	RELEASE_MUTEX(&_smhba_TE_mutex);
4915 }
4916 
4917 HBA_STATUS
4918 SMHBA_RegisterForTargetEvents(
4919     void		(*pCallback) (
4920 	void		*pData,
4921 	HBA_WWN		hbaPortWWN,
4922 	HBA_WWN		discoveredPortWWN,
4923 	HBA_WWN		domainPortWWN,
4924 	HBA_UINT32	eventType),
4925     void		*pUserData,
4926     HBA_HANDLE		handle,
4927     HBA_WWN		hbaPortWWN,
4928     HBA_WWN		discoveredPortWWN,
4929     HBA_WWN		domainPortWWN,
4930     HBA_CALLBACKHANDLE	*pCallbackHandle,
4931     HBA_UINT32		allTargets) {
4932 
4933 	HBA_ADAPTERCALLBACK_ELEM *acbp;
4934 	SMHBARegisterForTargetEventsFunc
4935 	    registeredfunc;
4936 	HBA_STATUS		status;
4937 	HBA_LIBRARY_INFO	*lib_infop;
4938 	HBA_HANDLE		vendorHandle;
4939 
4940 	DEBUG(2, "SMHBA_RegisterForTargetEvents, hbaPort:"
4941 	    "%s, discoveredPort: %s",
4942 	    WWN2STR1(&hbaPortWWN), WWN2STR2(&discoveredPortWWN), 0);
4943 
4944 	CHECKLIBRARYANDVERSION(SMHBA);
4945 	/* we now have the _hbaapi_LL_mutex */
4946 
4947 	registeredfunc = lib_infop->ftable.smhbafunctionTable.\
4948 	    RegisterForTargetEventsHandler;
4949 
4950 	if (registeredfunc == NULL) {
4951 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
4952 	}
4953 
4954 	/*
4955 	 * that allocated memory is used both as the handle for the
4956 	 * caller, and as userdata to the vendor call so that on
4957 	 * callback the specific registration may be recalled
4958 	 */
4959 	acbp = (HBA_ADAPTERCALLBACK_ELEM *)
4960 	    calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
4961 	if (acbp == NULL) {
4962 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
4963 	}
4964 	*pCallbackHandle = (HBA_CALLBACKHANDLE) acbp;
4965 	acbp->callback = pCallback;
4966 	acbp->userdata = pUserData;
4967 	acbp->lib_info = lib_infop;
4968 
4969 	status = (registeredfunc)(smhba_targetevents_callback,
4970 	    (void *)acbp,
4971 	    vendorHandle,
4972 	    hbaPortWWN,
4973 	    discoveredPortWWN,
4974 	    domainPortWWN,
4975 	    &acbp->vendorcbhandle,
4976 	    allTargets);
4977 	if (status != HBA_STATUS_OK) {
4978 	free(acbp);
4979 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
4980 	}
4981 
4982 	GRAB_MUTEX(&_smhba_TE_mutex);
4983 	acbp->next = _smhba_targetevents_callback_list;
4984 	_smhba_targetevents_callback_list = acbp;
4985 
4986 	RELEASE_MUTEX(&_smhba_TE_mutex);
4987 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
4988 }
4989