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