SMHBAAPILIB.c revision 10652:9d0aff74d6fd
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>
84static int	*handle;
85static 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
103int _hbaapi_debuglevel = 0;
104#define	DEBUG(L, STR, A1, A2, A3)
105
106#if defined(USESYSLOG) && defined(USELOGFILE)
107FILE *_hbaapi_debug_fd = NULL;
108int _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)
147int _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)
159FILE *_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 */
213typedef enum {
214    HBA_LIBRARY_UNKNOWN,
215    HBA_LIBRARY_LOADED,
216    HBA_LIBRARY_NOT_LOADED
217} HBA_LIBRARY_STATUS;
218
219typedef enum {
220    UNKNOWN = 1,
221    SMHBA,
222    HBAAPIV2,
223    HBAAPI
224} LIBRARY_VERSION;
225
226typedef 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	}
250HBA_LIBRARY_INFO *_hbaapi_librarylist = NULL;
251HBA_UINT32 _hbaapi_total_library_count = 0;
252#ifdef POSIX_THREADS
253pthread_mutex_t _hbaapi_LL_mutex = PTHREAD_MUTEX_INITIALIZER;
254#elif defined(WIN32)
255CRITICAL_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 */
292typedef 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
302HBA_ADAPTER_INFO *_hbaapi_adapterlist = NULL;
303HBA_UINT32 _hbaapi_total_adapter_count = 0;
304#ifdef POSIX_THREADS
305pthread_mutex_t _hbaapi_AL_mutex = PTHREAD_MUTEX_INITIALIZER;
306#elif defined(WIN32)
307CRITICAL_SECTION _hbaapi_AL_mutex;
308#endif
309
310/*
311 * Call back registration
312 */
313typedef 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 */
325typedef 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
334typedef 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
342HBA_ALLADAPTERSCALLBACK_ELEM *_hbaapi_adapteraddevents_callback_list = NULL;
343HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterevents_callback_list = NULL;
344HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterportevents_callback_list = NULL;
345HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterportstatevents_callback_list = NULL;
346HBA_ADAPTERCALLBACK_ELEM *_hbaapi_targetevents_callback_list = NULL;
347HBA_ADAPTERCALLBACK_ELEM *_hbaapi_linkevents_callback_list = NULL;
348
349HBA_ALLADAPTERSCALLBACK_ELEM *_smhba_adapteraddevents_callback_list = NULL;
350HBA_ADAPTERCALLBACK_ELEM *_smhba_adapterevents_callback_list = NULL;
351HBA_ADAPTERCALLBACK_ELEM *_smhba_adapterportevents_callback_list = NULL;
352HBA_ADAPTERCALLBACK_ELEM *_smhba_adapterportstatevents_callback_list = NULL;
353HBA_ADAPTERCALLBACK_ELEM *_smhba_adapterphystatevents_callback_list = NULL;
354HBA_ADAPTERCALLBACK_ELEM *_smhba_targetevents_callback_list = NULL;
355
356#ifdef POSIX_THREADS
357/* mutex's to protect each list */
358pthread_mutex_t _hbaapi_AAE_mutex = PTHREAD_MUTEX_INITIALIZER;
359pthread_mutex_t _hbaapi_AE_mutex = PTHREAD_MUTEX_INITIALIZER;
360pthread_mutex_t _hbaapi_APE_mutex = PTHREAD_MUTEX_INITIALIZER;
361pthread_mutex_t _hbaapi_APSE_mutex = PTHREAD_MUTEX_INITIALIZER;
362pthread_mutex_t _hbaapi_TE_mutex = PTHREAD_MUTEX_INITIALIZER;
363pthread_mutex_t _hbaapi_LE_mutex = PTHREAD_MUTEX_INITIALIZER;
364pthread_mutex_t _smhba_AAE_mutex = PTHREAD_MUTEX_INITIALIZER;
365pthread_mutex_t _smhba_AE_mutex = PTHREAD_MUTEX_INITIALIZER;
366pthread_mutex_t _smhba_APE_mutex = PTHREAD_MUTEX_INITIALIZER;
367pthread_mutex_t _smhba_APSE_mutex = PTHREAD_MUTEX_INITIALIZER;
368pthread_mutex_t _smhba_APHYSE_mutex = PTHREAD_MUTEX_INITIALIZER;
369pthread_mutex_t _smhba_TE_mutex = PTHREAD_MUTEX_INITIALIZER;
370pthread_mutex_t _smhba_LE_mutex = PTHREAD_MUTEX_INITIALIZER;
371#elif defined(WIN32)
372CRITICAL_SECTION _hbaapi_AAE_mutex;
373CRITICAL_SECTION _hbaapi_AE_mutex;
374CRITICAL_SECTION _hbaapi_APE_mutex;
375CRITICAL_SECTION _hbaapi_APSE_mutex;
376CRITICAL_SECTION _hbaapi_TE_mutex;
377CRITICAL_SECTION _smhba_AAE_mutex;
378CRITICAL_SECTION _smhba_AE_mutex;
379CRITICAL_SECTION _smhba_APE_mutex;
380CRITICAL_SECTION _smhba_APSE_mutex;
381CRITICAL_SECTION _smhba_APHYSE_mutex;
382CRITICAL_SECTION _smhba_TE_mutex;
383CRITICAL_SECTION _hbaapi_LE_mutex;
384#endif
385
386HBA_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
403static void
404grab_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
413static void
414release_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 */
427static HBA_STATUS
428HBA_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 */
476static void
477freevendorhandlelist(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
494static
495HBA_STATUS
496local_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 */
624static char wwn_str1[17];
625/* LINTED E_STATIC_UE_STATIC_UNUSED */
626static char wwn_str2[17];
627/* LINTED E_STATIC_UE_STATIC_UNUSED */
628static 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))
632static char *
633/* LINTED E_STATIC_UE_STATIC_UNUSED */
634WWN2str(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
645BOOL APIENTRY
646DllMain(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 */
667HBA_STATUS
668HBA_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
1156HBA_STATUS
1157HBA_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 */
1291HBA_UINT32
1292HBA_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
1397HBA_STATUS
1398HBA_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
1439HBA_HANDLE
1440HBA_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 */
1484HBA_STATUS
1485HBA_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
1544void
1545HBA_RefreshAdapterConfiguration() {
1546    DEBUG(2, "HBA_RefreshAdapterConfiguration", 0, 0, 0);
1547	(void) HBA_GetNumberOfAdapters();
1548}
1549
1550HBA_UINT32
1551HBA_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 */
1559HBA_UINT32
1560HBA_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 */
1640HBA_STATUS
1641HBA_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 ************************************************* */
1653static void
1654/* LINTED E_FUNC_ARG_UNUSED */
1655adapteraddevents_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
1670HBA_STATUS
1671HBA_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) ************************************** */
1835static void
1836adapterevents_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}
1855HBA_STATUS
1856HBA_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 ************************************************** */
1921static void
1922adapterportevents_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
1944HBA_STATUS
1945HBA_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 ************************************************ */
2015static void
2016adapterportstatevents_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}
2036HBA_STATUS
2037HBA_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 ******************************************************* */
2110static void
2111targetevents_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
2134HBA_STATUS
2135HBA_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 ********************************************************* */
2209static void
2210linkevents_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}
2232HBA_STATUS
2233HBA_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
2308void
2309HBA_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
2327HBA_STATUS
2328HBA_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
2356HBA_STATUS
2357HBA_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
2386HBA_STATUS
2387HBA_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
2416HBA_STATUS
2417HBA_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
2448HBA_STATUS
2449HBA_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
2478HBA_STATUS
2479HBA_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
2512HBA_STATUS
2513HBA_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
2543HBA_STATUS
2544HBA_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
2573HBA_STATUS
2574HBA_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
2593HBA_STATUS
2594HBA_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
2613HBA_STATUS
2614HBA_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
2643HBA_STATUS
2644HBA_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
2672void
2673HBA_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
2693void
2694HBA_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
2718HBA_STATUS
2719HBA_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
2742HBA_STATUS
2743HBA_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
2768HBA_STATUS
2769HBA_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
2793HBA_STATUS
2794HBA_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
2830HBA_STATUS
2831HBA_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
2867HBA_STATUS
2868HBA_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
2902HBA_STATUS
2903HBA_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
2934HBA_STATUS
2935HBA_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
2970HBA_STATUS
2971HBA_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
3005HBA_STATUS
3006HBA_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
3035HBA_STATUS
3036HBA_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
3067HBA_STATUS
3068HBA_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}
3094HBA_STATUS
3095HBA_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
3122HBA_STATUS
3123HBA_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
3151HBA_STATUS
3152HBA_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
3177HBA_STATUS
3178HBA_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
3203HBA_STATUS
3204HBA_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
3229HBA_STATUS
3230HBA_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
3256HBA_STATUS
3257HBA_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
3283HBA_STATUS
3284HBA_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
3310HBA_STATUS
3311HBA_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
3335HBA_STATUS
3336HBA_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
3363HBA_STATUS
3364HBA_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
3389HBA_UINT32
3390HBA_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 */
3464HBA_UINT32
3465SMHBA_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 */
3473HBA_UINT32
3474SMHBA_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 */
3535HBA_UINT32
3536SMHBA_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
3597HBA_STATUS
3598SMHBA_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
3621HBA_STATUS
3622SMHBA_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
3645HBA_STATUS
3646SMHBA_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
3670HBA_STATUS
3671SMHBA_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
3698HBA_STATUS
3699SMHBA_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
3728HBA_STATUS
3729SMHBA_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
3756HBA_STATUS
3757SMHBA_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
3783HBA_STATUS
3784SMHBA_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
3810HBA_STATUS
3811SMHBA_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
3839HBA_STATUS
3840SMHBA_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
3868HBA_STATUS
3869SMHBA_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
3895HBA_STATUS
3896SMHBA_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
3924HBA_STATUS
3925SMHBA_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
3953HBA_STATUS
3954SMHBA_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
3981HBA_STATUS
3982SMHBA_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
4010HBA_STATUS
4011SMHBA_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
4039HBA_STATUS
4040SMHBA_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
4068HBA_STATUS
4069SMHBA_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
4097HBA_STATUS
4098SMHBA_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
4122HBA_STATUS
4123SMHBA_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
4160HBA_STATUS
4161SMHBA_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
4195HBA_STATUS
4196SMHBA_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
4231HBA_STATUS
4232SMHBA_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
4262HBA_STATUS
4263SMHBA_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
4294HBA_STATUS
4295SMHBA_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 */
4348static void
4349smhba_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
4370HBA_STATUS
4371SMHBA_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) ******************************** */
4523static void
4524smhba_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
4545HBA_STATUS
4546SMHBA_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 *********************************************** */
4606static void
4607smhba_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
4632HBA_STATUS
4633SMHBA_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 ******************************** */
4699static void
4700smhba_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
4724HBA_STATUS
4725SMHBA_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 ************************************ */
4796static void
4797smhba_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
4820HBA_STATUS
4821SMHBA_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 ********************************************* */
4892static void
4893smhba_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
4917HBA_STATUS
4918SMHBA_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