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