1 /*************************************************************************
   2  * Description
   3  *      HBAAPILIB.c - Implements a sample common (wrapper) HBA API library
   4  *
   5  * License:
   6  *      The contents of this file are subject to the SNIA Public License
   7  *      Version 1.0 (the "License"); you may not use this file except in
   8  *      compliance with the License. You may obtain a copy of the License at
   9  *
  10  *      /http://www.snia.org/English/Resources/Code/OpenSource.html
  11  *
  12  *      Software distributed under the License is distributed on an "AS IS"
  13  *      basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  14  *      the License for the specific language governing rights and limitations
  15  *      under the License.
  16  *
  17  * The Original Code is  SNIA HBA API Wrapper Library
  18  *
  19  * The Initial Developer of the Original Code is:
  20  *      Benjamin F. Kuo, Troika Networks, Inc. (benk@troikanetworks.com)
  21  *
  22  * Contributor(s):
  23  *      Tuan Lam, QLogic Corp. (t_lam@qlc.com)
  24  *      Dan Willie, Emulex Corp. (Dan.Willie@emulex.com)
  25  *      Dixon Hutchinson, Legato Systems, Inc. (dhutchin@legato.com)
  26  *      David Dillard, VERITAS Software Corp. (david.dillard@veritas.com)
  27  *
  28  *************************************************************************
  29  */
  30 
  31 #ifdef WIN32
  32 #include <windows.h>
  33 #include <string.h>
  34 /*
  35  * Next define forces entry points in the dll to be exported
  36  * See hbaapi.h to see what it does.
  37  */
  38 #define HBAAPI_EXPORTS
  39 #else
  40 #include <dlfcn.h>
  41 #include <strings.h>
  42 #endif
  43 #include <stdio.h>
  44 #include <time.h>
  45 #include "hbaapi.h"
  46 #include "vendorhbaapi.h"
  47 #include <stdlib.h>
  48 #ifdef USESYSLOG
  49 #include <syslog.h>
  50 #endif
  51 
  52 /*
  53  * LIBRARY_NUM is a shortcut to figure out which library we need to call.
  54  *  The top 16 bits of handle are the library index
  55  */
  56 #define LIBRARY_NUM(handle)     ((handle)>>16)
  57 
  58 /*
  59  * VENDOR_HANDLE turns a global library handle into a vendor specific handle,
  60  * with all upper 16 bits set to 0
  61  */
  62 #define VENDOR_HANDLE(handle)   ((handle)&0xFFFF)
  63 
  64 #define HBA_HANDLE_FROM_LOCAL(library, vendor) \
  65                                 (((library)<<16) | ((vendor)&0x0000FFFF))
  66 
  67 int _hbaapi_debuglevel = 0;
  68 #define DEBUG(L, STR, A1, A2, A3)
  69 
  70 #if defined(USESYSLOG) && defined(USELOGFILE)
  71 FILE *_hbaapi_debug_fd = NULL;
  72 int _hbaapi_sysloginit = 0;
  73 #undef DEBUG
  74 #ifdef WIN32
  75 #define DEBUG(L, STR, A1, A2, A3)\
  76     if ((L) <= _hbaapi_debuglevel) {\
  77         if(_hbaapi_sysloginit == 0) {\
  78             openlog("HBAAPI", LOG_PID|LOG_ODELAY ,LOG_USER);\
  79             _hbaapi_sysloginit = 1;\
  80         }\
  81         syslog (LOG_INFO, (STR), (A1), (A2), (A3));\
  82         if(_hbaapi_debug_fd == NULL) {\
  83             char _logFile[MAX_PATH]; \
  84             GetTempPath(MAX_PATH, _logFile); \
  85             strcat(_logFile, "HBAAPI.log"); \
  86             _hbaapi_debug_fd = fopen(_logFile, "a");\
  87         }\
  88         if(_hbaapi_debug_fd != NULL) {\
  89             fprintf(_hbaapi_debug_fd, (STR ## "\n"), (A1), (A2), (A3));\
  90         }\
  91     }
  92 #else /* WIN32*/
  93 #define DEBUG(L, STR, A1, A2, A3)\
  94     if ((L) <= _hbaapi_debuglevel) {\
  95         if(_hbaapi_sysloginit == 0) {\
  96             openlog("HBAAPI", LOG_PID|LOG_ODELAY ,LOG_USER);\
  97             _hbaapi_sysloginit = 1;\
  98         }\
  99         syslog (LOG_INFO, (STR), (A1), (A2), (A3));\
 100         if(_hbaapi_debug_fd == NULL) {\
 101             _hbaapi_debug_fd = fopen("/tmp/HBAAPI.log", "a");\
 102         }\
 103         if(_hbaapi_debug_fd != NULL) {\
 104             fprintf(_hbaapi_debug_fd, (STR ## "\n"), (A1), (A2), (A3));\
 105         }\
 106     }
 107 #endif /* WIN32*/
 108  
 109 #else /* Not both USESYSLOG and USELOGFILE */
 110 #if defined(USESYSLOG)
 111 int _hbaapi_sysloginit = 0;
 112 #undef DEBUG
 113 #define DEBUG(L, STR, A1, A2, A3) \
 114     if ((L) <= _hbaapi_debuglevel) {\
 115         if(_hbaapi_sysloginit == 0) {\
 116             openlog("HBAAPI", LOG_PID|LOG_ODELAY ,LOG_USER);\
 117             _hbaapi_sysloginit = 1;\
 118         }\
 119         syslog (LOG_INFO, (STR), (A1), (A2), (A3));\
 120     }
 121 #endif /* USESYSLOG */
 122 #if defined(USELOGFILE)
 123 FILE *_hbaapi_debug_fd = NULL;
 124 #undef DEBUG
 125 #ifdef WIN32
 126 #define DEBUG(L, STR, A1, A2, A3) \
 127     if((L) <= _hbaapi_debuglevel) {\
 128         if(_hbaapi_debug_fd == NULL) {\
 129             char _logFile[MAX_PATH]; \
 130             GetTempPath(MAX_PATH, _logFile); \
 131             strcat(_logFile, "HBAAPI.log"); \
 132             _hbaapi_debug_fd = fopen(_logFile, "a");\
 133         }\
 134     }
 135 #else /* WIN32 */
 136 #define DEBUG(L, STR, A1, A2, A3) \
 137     if((L) <= _hbaapi_debuglevel) {\
 138         if(_hbaapi_debug_fd == NULL) {\
 139             _hbaapi_debug_fd = fopen("/tmp/HBAAPI.log", "a");\
 140         }\
 141         if(_hbaapi_debug_fd != NULL) { \
 142             fprintf(_hbaapi_debug_fd, (STR) ## "\n", (A1), (A2), (A3));\
 143         }\
 144     }
 145 #endif /* WIN32 */
 146 #endif /* USELOGFILE */
 147 #endif /* Not both USELOGFILE and USESYSLOG */
 148  
 149 #ifdef POSIX_THREADS
 150 #include <pthread.h>
 151 /*
 152  * When multiple mutex's are grabed, they must be always be grabbed in 
 153  * the same order, or deadlock can result.  There are three levels
 154  * of mutex's involved in this API.  If LL_mutex is grabbed, always grap
 155  * it first.  If AL_mutex is grabbed, it may not be grabbed before
 156  * LL_mutex.  If grabbed in a multi grab sequence, the mutex's protecting
 157  * the callback lists must always be grabbed last and release before calling
 158  * a vendor specific library function that might invoke a callback function
 159  * on the same thread.
 160  */
 161 #define GRAB_MUTEX(M)                   grab_mutex(M)
 162 #define RELEASE_MUTEX(M)                release_mutex(M)
 163 #define RELEASE_MUTEX_RETURN(M,RET)     release_mutex(M); return(RET)
 164 #elif defined (WIN32)
 165 #define GRAB_MUTEX(m)                   EnterCriticalSection(m)
 166 #define RELEASE_MUTEX(m)                LeaveCriticalSection(m)
 167 #define RELEASE_MUTEX_RETURN(m, RET)    LeaveCriticalSection(m); return(RET)
 168 #else
 169 #define GRAB_MUTEX(M)
 170 #define RELEASE_MUTEX(M)
 171 #define RELEASE_MUTEX_RETURN(M,RET)     return(RET)
 172 #endif
 173  
 174 /*
 175  * Vendor library information 
 176  */
 177 typedef enum {
 178     HBA_LIBRARY_UNKNOWN,
 179     HBA_LIBRARY_LOADED,
 180     HBA_LIBRARY_NOT_LOADED
 181 } HBA_LIBRARY_STATUS;
 182  
 183 typedef struct hba_library_info {
 184     struct hba_library_info
 185                         *next;
 186 #ifdef WIN32
 187     HINSTANCE           hLibrary;               /* Handle to a loaded DLL */
 188 #else
 189     char                *LibraryName;
 190     void*               hLibrary;               /* Handle to a loaded DLL */
 191 #endif
 192     char                *LibraryPath;
 193     HBA_ENTRYPOINTSV2   functionTable;          /* Function pointers */
 194     HBA_LIBRARY_STATUS  status;                 /* info on this library */
 195     HBA_UINT32          index;
 196 } HBA_LIBRARY_INFO, *PHBA_LIBRARY_INFO;
 197 
 198 #define ARE_WE_INITED() \
 199         if (_hbaapi_librarylist == NULL) { \
 200                 return(HBA_STATUS_ERROR); \
 201         }
 202 HBA_LIBRARY_INFO *_hbaapi_librarylist = NULL;
 203 HBA_UINT32 _hbaapi_total_library_count = 0;
 204 #ifdef POSIX_THREADS
 205 pthread_mutex_t _hbaapi_LL_mutex = PTHREAD_MUTEX_INITIALIZER;
 206 #elif defined(WIN32)
 207 CRITICAL_SECTION _hbaapi_LL_mutex;
 208 #endif
 209 
 210 /*
 211  * Individual adapter (hba) information
 212  */
 213 typedef struct hba_adapter_info {
 214     struct hba_adapter_info
 215                         *next;
 216     HBA_STATUS          GNstatus;       /* status from GetAdapterNameFunc */
 217     char                *name;
 218     HBA_WWN             nodeWWN;
 219     HBA_LIBRARY_INFO    *library;
 220     HBA_UINT32          index;
 221 } HBA_ADAPTER_INFO;
 222 
 223 HBA_ADAPTER_INFO *_hbaapi_adapterlist = NULL;
 224 HBA_UINT32 _hbaapi_total_adapter_count = 0;
 225 #ifdef POSIX_THREADS
 226 pthread_mutex_t _hbaapi_AL_mutex = PTHREAD_MUTEX_INITIALIZER;
 227 #elif defined(WIN32)
 228 CRITICAL_SECTION _hbaapi_AL_mutex;
 229 #endif
 230 
 231 /*
 232  * Call back registration
 233  */
 234 typedef struct hba_vendorcallback_elem {
 235     struct hba_vendorcallback_elem
 236                                 *next;
 237     HBA_CALLBACKHANDLE          vendorcbhandle;
 238     HBA_LIBRARY_INFO            *lib_info;
 239 } HBA_VENDORCALLBACK_ELEM;
 240 
 241 /*
 242  * Each instance of HBA_ADAPTERCALLBACK_ELEM represents a call to one of
 243  * "register" functions that apply to a particular adapter.
 244  * HBA_ALLADAPTERSCALLBACK_ELEM is used just for HBA_RegisterForAdapterAddEvents
 245  */
 246 typedef struct hba_adaptercallback_elem {
 247     struct hba_adaptercallback_elem
 248                         *next;
 249     HBA_LIBRARY_INFO    *lib_info;
 250     void                *userdata;
 251     HBA_CALLBACKHANDLE  vendorcbhandle;
 252     void                (*callback)();
 253 } HBA_ADAPTERCALLBACK_ELEM;
 254 
 255 typedef struct hba_alladapterscallback_elem {
 256     struct hba_alladapterscallback_elem
 257                                 *next;
 258     void                        *userdata;
 259     HBA_VENDORCALLBACK_ELEM     *vendorhandlelist;
 260     void                        (*callback)();
 261 } HBA_ALLADAPTERSCALLBACK_ELEM;
 262 
 263 HBA_ALLADAPTERSCALLBACK_ELEM *_hbaapi_adapteraddevents_callback_list = NULL;
 264 HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterevents_callback_list = NULL;
 265 HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterportevents_callback_list = NULL;
 266 HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterportstatevents_callback_list = NULL;
 267 HBA_ADAPTERCALLBACK_ELEM *_hbaapi_targetevents_callback_list = NULL;
 268 HBA_ADAPTERCALLBACK_ELEM *_hbaapi_linkevents_callback_list = NULL;
 269 HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterdeviceevents_callback_list = NULL;
 270 #ifdef POSIX_THREADS
 271 /* mutex's to protect each list */
 272 pthread_mutex_t _hbaapi_AAE_mutex = PTHREAD_MUTEX_INITIALIZER;
 273 pthread_mutex_t _hbaapi_AE_mutex = PTHREAD_MUTEX_INITIALIZER;
 274 pthread_mutex_t _hbaapi_APE_mutex = PTHREAD_MUTEX_INITIALIZER;
 275 pthread_mutex_t _hbaapi_APSE_mutex = PTHREAD_MUTEX_INITIALIZER;
 276 pthread_mutex_t _hbaapi_TE_mutex = PTHREAD_MUTEX_INITIALIZER;
 277 pthread_mutex_t _hbaapi_LE_mutex = PTHREAD_MUTEX_INITIALIZER;
 278 #elif defined(WIN32)
 279 CRITICAL_SECTION _hbaapi_AAE_mutex;
 280 CRITICAL_SECTION _hbaapi_AE_mutex;
 281 CRITICAL_SECTION _hbaapi_APE_mutex;
 282 CRITICAL_SECTION _hbaapi_APSE_mutex;
 283 CRITICAL_SECTION _hbaapi_TE_mutex;
 284 CRITICAL_SECTION _hbaapi_LE_mutex;
 285 #endif
 286 
 287 HBA_ADAPTERCALLBACK_ELEM **cb_lists_array[] = {
 288     &_hbaapi_adapterevents_callback_list,
 289     &_hbaapi_adapterportevents_callback_list,
 290     &_hbaapi_adapterportstatevents_callback_list,
 291     &_hbaapi_targetevents_callback_list,
 292     &_hbaapi_linkevents_callback_list,
 293     &_hbaapi_adapterdeviceevents_callback_list,
 294     NULL};
 295 
 296 /*
 297  * Common library internal. Mutex handling
 298  */
 299 #ifdef POSIX_THREADS
 300 static void
 301 grab_mutex(pthread_mutex_t *mp) {
 302     int ret;
 303     if((ret = pthread_mutex_lock(mp)) != 0) {
 304         perror("pthread_mutex_lock - HBAAPI:");
 305         DEBUG(0, "pthread_mutex_lock returned %d", ret, 0, 0);
 306     }
 307 }
 308 
 309 static void
 310 release_mutex(pthread_mutex_t *mp) {
 311     int ret;
 312     if((ret = pthread_mutex_unlock(mp)) != 0) {
 313         perror("pthread_mutex_unlock - HBAAPI:");
 314         DEBUG(0, "pthread_mutex_unlock returned %d", ret, 0, 0);
 315     }
 316 }
 317 #endif
 318 
 319 /*
 320  * Common library internal. Check library and return vendorhandle
 321  */
 322 static HBA_STATUS
 323 HBA_CheckLibrary(HBA_HANDLE handle,
 324                  HBA_LIBRARY_INFO **lib_infopp,
 325                  HBA_HANDLE *vendorhandle) {
 326 
 327     HBA_UINT32          libraryIndex;
 328     HBA_LIBRARY_INFO    *lib_infop;
 329 
 330     if (vendorhandle == NULL) {
 331         return(HBA_STATUS_ERROR_ARG);
 332     }
 333     if(_hbaapi_librarylist == NULL) {
 334         return(HBA_STATUS_ERROR);
 335     }
 336     libraryIndex = LIBRARY_NUM(handle);
 337 
 338     GRAB_MUTEX(&_hbaapi_LL_mutex);
 339     for(lib_infop = _hbaapi_librarylist;
 340         lib_infop != NULL;
 341         lib_infop = lib_infop->next) {
 342         if(lib_infop->index == libraryIndex) {
 343             if(lib_infop->status != HBA_LIBRARY_LOADED) {
 344                 return HBA_STATUS_ERROR;
 345             }
 346             *lib_infopp = lib_infop;
 347             *vendorhandle = VENDOR_HANDLE(handle);
 348             /* caller will release the mutex */
 349             return HBA_STATUS_OK;
 350         }
 351     }
 352     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INVALID_HANDLE);
 353 }
 354 #define CHECKLIBRARY() \
 355         status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);\
 356         if(status != HBA_STATUS_OK) { \
 357             return(status); \
 358         }
 359 
 360 /*
 361  *freevendorhandlelist is called with _hbaapi_LL_mutex already held
 362  */
 363 static void
 364 freevendorhandlelist(HBA_VENDORCALLBACK_ELEM *vhlist) {
 365     HBA_VENDORCALLBACK_ELEM     *vhlp;
 366     HBA_VENDORCALLBACK_ELEM     *vnext;
 367     HBARemoveCallbackFunc       registeredfunc;
 368 
 369     for(vhlp = vhlist; vhlp != NULL; vhlp = vnext) {
 370         vnext = vhlp->next;
 371         registeredfunc = 
 372             vhlp->lib_info->functionTable.RemoveCallbackHandler;
 373         if(registeredfunc == NULL) {
 374             continue;
 375         }
 376         (registeredfunc)(vhlp->vendorcbhandle);
 377         free(vhlp);
 378     }
 379 }
 380 
 381 static
 382 HBA_STATUS
 383 local_remove_callback(HBA_CALLBACKHANDLE cbhandle) {
 384     HBA_ADAPTERCALLBACK_ELEM            ***listp;
 385     HBA_ADAPTERCALLBACK_ELEM            **lastp;
 386     HBA_ALLADAPTERSCALLBACK_ELEM        **lap;
 387     HBA_ALLADAPTERSCALLBACK_ELEM        *allcbp;
 388     HBA_ADAPTERCALLBACK_ELEM            *cbp;
 389     HBARemoveCallbackFunc               registeredfunc;
 390     HBA_VENDORCALLBACK_ELEM             *vhlp;
 391     HBA_VENDORCALLBACK_ELEM             *vnext;
 392     int                                 found;
 393     HBA_STATUS                          status = HBA_STATUS_ERROR_INVALID_HANDLE;
 394 
 395 
 396     /* search through the simple lists first */
 397     GRAB_MUTEX(&_hbaapi_AAE_mutex);
 398     GRAB_MUTEX(&_hbaapi_AE_mutex);
 399     GRAB_MUTEX(&_hbaapi_APE_mutex);
 400     GRAB_MUTEX(&_hbaapi_APSE_mutex);
 401     GRAB_MUTEX(&_hbaapi_TE_mutex);
 402     GRAB_MUTEX(&_hbaapi_LE_mutex);
 403     for(listp = cb_lists_array, found = 0; found == 0, *listp != NULL; listp++) {
 404         lastp = *listp;
 405         for(cbp=**listp; cbp != NULL; cbp = cbp->next) {
 406             if(cbhandle != (HBA_CALLBACKHANDLE)cbp) {
 407                 lastp = &(cbp->next);
 408                 continue;
 409             }
 410             found = 1;
 411             registeredfunc = cbp->lib_info->functionTable.RemoveCallbackHandler;
 412             if(registeredfunc == NULL) {
 413                 break;
 414             }
 415             (registeredfunc)(cbp->vendorcbhandle);
 416             *lastp = cbp->next;
 417             free(cbp);
 418             break;
 419         }
 420     }
 421     RELEASE_MUTEX(&_hbaapi_LE_mutex);
 422     RELEASE_MUTEX(&_hbaapi_TE_mutex);
 423     RELEASE_MUTEX(&_hbaapi_APSE_mutex);
 424     RELEASE_MUTEX(&_hbaapi_APE_mutex);
 425     RELEASE_MUTEX(&_hbaapi_AE_mutex);
 426     RELEASE_MUTEX(&_hbaapi_AAE_mutex);
 427     if(found != 0) {
 428         if(registeredfunc == NULL) {
 429             return HBA_STATUS_ERROR_NOT_SUPPORTED;
 430         }
 431         return HBA_STATUS_OK;
 432     }
 433 
 434     GRAB_MUTEX(&_hbaapi_AAE_mutex);
 435     /* if it wasnt in the simple lists, look in the list for adapteraddevents */
 436     lap = &_hbaapi_adapteraddevents_callback_list;
 437     for(allcbp = _hbaapi_adapteraddevents_callback_list; 
 438         allcbp != NULL;
 439         allcbp = allcbp->next) {
 440         if(cbhandle != (HBA_CALLBACKHANDLE)allcbp) {
 441             lap = &allcbp->next;
 442             continue;
 443         }
 444         for(vhlp = allcbp->vendorhandlelist; vhlp != NULL; vhlp = vnext) {
 445             vnext = vhlp->next;
 446             registeredfunc = 
 447                 vhlp->lib_info->functionTable.RemoveCallbackHandler;
 448             if(registeredfunc == NULL) {
 449                 continue;
 450             }
 451             (registeredfunc)(vhlp->vendorcbhandle);
 452             free(vhlp);
 453         }
 454         *lap = allcbp->next;
 455         free(allcbp);
 456         status = HBA_STATUS_OK;
 457         break;
 458     }
 459     RELEASE_MUTEX(&_hbaapi_AAE_mutex);
 460     return(status);
 461 }
 462 
 463 static char wwn_str1[17];
 464 static char wwn_str2[17];
 465 static char wwn_str3[17];
 466 #define WWN2STR1(wwn) WWN2str(wwn_str1, (wwn))
 467 #define WWN2STR2(wwn) WWN2str(wwn_str2, (wwn))
 468 #define WWN2STR3(wwn) WWN2str(wwn_str3, (wwn))
 469 static char *
 470 WWN2str(char *buf, HBA_WWN *wwn) {
 471     int j;
 472     unsigned char *pc = (unsigned char *)&(wwn->wwn[0]);
 473     buf[0] = '\0';
 474     for (j=0; j<16; j+=2) {
 475         sprintf(&buf[j], "%02X", (int)*pc++);
 476     }
 477     return(buf);
 478 }
 479 
 480 
 481 #ifdef WIN32
 482 BOOL APIENTRY
 483 DllMain( HANDLE hModule,
 484          DWORD  ul_reason_for_call,
 485          LPVOID lpReserved
 486     )
 487 {
 488     switch (ul_reason_for_call)
 489     {
 490     case DLL_PROCESS_ATTACH:
 491         break;
 492     case DLL_PROCESS_DETACH:
 493         break;
 494     case DLL_THREAD_ATTACH:
 495     case DLL_THREAD_DETACH:
 496         break;
 497     }
 498     return TRUE;
 499 }
 500 #endif
 501 
 502 /*
 503  * Read in the config file and load all the specified vendor specific
 504  * libraries and perform the function registration exercise
 505  */
 506 HBA_STATUS
 507 HBA_LoadLibrary(void) {
 508     HBARegisterLibraryFunc
 509                         RegisterFunc;
 510     HBARegisterLibraryV2Func
 511                         RegisterV2Func;
 512     HBALoadLibraryFunc  LoadLibraryFunc;
 513     HBAGetVersionFunc   GetVersionFunc;
 514 #ifdef POSIX_THREADS
 515     int                 ret;
 516 #endif
 517     HBA_STATUS          status;
 518 #ifdef NOTDEF
 519     HBA_UINT32          libversion;
 520 #endif
 521 
 522     /* Open configuration file from known location */
 523 #ifdef WIN32
 524     LONG                lStatus;
 525     HKEY                hkSniaHba, hkVendorLib;
 526     FILETIME            ftLastWriteTime;
 527     TCHAR               cSubKeyName[256];
 528     DWORD               i, dwSize, dwType;
 529     BYTE                byFileName[MAX_PATH];
 530     HBA_LIBRARY_INFO    *lib_infop;
 531 
 532     if(_hbaapi_librarylist != NULL) {
 533         /* this is an app programming error */
 534         return HBA_STATUS_ERROR;
 535     }
 536 
 537     lStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\SNIA\\HBA",
 538                            0, KEY_READ, &hkSniaHba);
 539     if (lStatus != ERROR_SUCCESS) {
 540         /* ???Opportunity to send error msg, configuration error */
 541         return HBA_STATUS_ERROR;
 542     }
 543     /*
 544      * Enumerate all the subkeys. These have the form:
 545      * HKLM\Software\SNIA\HBA\<Vendor id> - note that we don't care
 546      * what the vendor id is
 547      */
 548     for (i = 0; ; i++) {
 549         dwSize = 255;   /* how big the buffer is */
 550         lStatus = RegEnumKeyEx(hkSniaHba, i, 
 551                                (char *)&cSubKeyName, &dwSize, NULL,
 552                                NULL, NULL, &ftLastWriteTime);
 553         if (lStatus == ERROR_NO_MORE_ITEMS) {
 554             break;      /* we're done */
 555         } else if (lStatus == ERROR_MORE_DATA) { /* buffer not big enough */
 556             /* do whatever */
 557             ;
 558         }
 559         /* Now open the subkey that pertains to this vendor's library */
 560         lStatus = RegOpenKeyEx(hkSniaHba, cSubKeyName, 0, KEY_READ,
 561                                &hkVendorLib);
 562         if (lStatus != ERROR_SUCCESS) {
 563             RegCloseKey(hkSniaHba);
 564             /* ???Opportunity to send error msg, installation error */
 565             return HBA_STATUS_ERROR; /* you may want to return something
 566                                       * else or keep trying */
 567         }
 568         /* The name of the library is contained in a REG_SZ Value
 569          * keyed to "LibraryFile" */
 570         dwSize = MAX_PATH;
 571         lStatus = RegQueryValueEx(hkVendorLib, "LibraryFile", NULL, &dwType,
 572                                   byFileName, &dwSize);
 573         if (lStatus != ERROR_SUCCESS) {
 574             RegCloseKey(hkVendorLib);
 575             /* ???Opportunity to send error msg, installation error */
 576             continue;
 577         }
 578         lib_infop = (HBA_LIBRARY_INFO *)calloc(1, sizeof(HBA_LIBRARY_INFO));
 579         if(lib_infop == NULL) {
 580             /* what is the right thing to do in MS land??? */
 581             RegCloseKey(hkVendorLib);
 582             /* ???Opportunity to send error msg, installation error */
 583             return(HBA_STATUS_ERROR);
 584         }
 585         lib_infop->status = HBA_LIBRARY_NOT_LOADED;
 586         lib_infop->next = _hbaapi_librarylist;
 587         lib_infop->index = _hbaapi_total_library_count;
 588         _hbaapi_total_library_count++;
 589         _hbaapi_librarylist = lib_infop;
 590 
 591         /* Now I can try to load the library */
 592         lib_infop->hLibrary = LoadLibrary(byFileName);
 593         if (lib_infop->hLibrary == NULL){
 594             /* printf("unable to load library %s\n", librarypath); */
 595             /* ???Opportunity to send error msg, installation error */
 596             goto dud_library;
 597         }
 598         lib_infop->LibraryPath = strdup(byFileName);
 599         DEBUG(1, "HBAAPI loading: %s\n", byFileName, 0, 0);
 600 
 601         /* Call the registration function to get the list of pointers */
 602         RegisterV2Func = (HBARegisterLibraryV2Func)
 603             GetProcAddress(lib_infop->hLibrary, "HBA_RegisterLibraryV2");
 604         if (RegisterV2Func != NULL) {
 605             /* Load the function pointers directly into
 606              * the table of functions */
 607             status = ((RegisterV2Func)(&lib_infop->functionTable));
 608             if (status != HBA_STATUS_OK) {
 609                 /* library not loaded */
 610                 /* ???Opportunity to send error msg, library error? */
 611                 goto dud_library;
 612             }
 613         } else {
 614             /* Maybe the vendor library is only Rev1 */
 615             RegisterFunc = (HBARegisterLibraryFunc)
 616                 GetProcAddress(lib_infop->hLibrary, "HBA_RegisterLibrary");
 617             if(RegisterFunc == NULL) {
 618                 /* ???Opportunity to send error msg, library error? */
 619                 goto dud_library;
 620             }
 621             /* Load the function points directly into
 622              * the Rev 2 table of functions */
 623             status = ((RegisterFunc)(
 624                 (HBA_ENTRYPOINTS *)(&lib_infop->functionTable)));
 625             if (status != HBA_STATUS_OK) {
 626                 /* library not loaded */
 627                 /* ???Opportunity to send error msg, library error? */
 628                 goto dud_library;
 629             }
 630         }
 631 
 632         /* successfully loaded library */
 633         GetVersionFunc = lib_infop->functionTable.GetVersionHandler;
 634         if (GetVersionFunc == NULL) {
 635             /* ???Opportunity to send error msg, library error? */
 636             goto dud_library;
 637         }
 638 #ifdef NOTDEF /* save for a later time... when it matters */
 639         /* Check the version of this library before loading */
 640         /* Actually... This wrapper is compatible with version 1 */
 641         libversion = ((GetVersionFunc)());
 642         if (libversion < HBA_LIBVERSION) {
 643             goto dud_library;
 644         }
 645 #endif
 646         LoadLibraryFunc = lib_infop->functionTable.LoadLibraryHandler;
 647         if (LoadLibraryFunc == NULL) {
 648             /* Hmmm, dont we need to flag this in a realy big way??? */
 649             /* How about messages to the system event logger ??? */
 650             /* ???Opportunity to send error msg, library error? */
 651             goto dud_library;
 652         }
 653         /* Initialize this library */
 654         status = ((LoadLibraryFunc)());
 655         if (status != HBA_STATUS_OK) {
 656             /* ???Opportunity to send error msg, library error? */
 657             continue;
 658         }
 659         /* successfully loaded library */
 660         lib_infop->status = HBA_LIBRARY_LOADED;
 661 
 662     dud_library: /* its also just the end of the loop */
 663         RegCloseKey(hkVendorLib);
 664     }
 665     RegCloseKey(hkSniaHba);
 666 
 667 #else /* Unix as opposed to Win32 */
 668     FILE                *hbaconf;
 669     char                fullline[512];          /* line read from HBA.conf */
 670     char                *libraryname;           /* Read in from file HBA.conf */
 671     char                *librarypath;           /* Read in from file HBA.conf */
 672     char                hbaConfFilePath[256];
 673     char                *charPtr;
 674     HBA_LIBRARY_INFO    *lib_infop;
 675 
 676     if(_hbaapi_librarylist != NULL) {
 677         fprintf(stderr,
 678                 "HBA_LoadLibrary: previously unfreed "
 679                 "libraries exist, call HBA_FreeLibrary().\n");
 680         return HBA_STATUS_ERROR;
 681     }
 682 
 683     strcpy(hbaConfFilePath, "/etc/hba.conf");
 684 
 685     if ((hbaconf = fopen(hbaConfFilePath, "r")) == NULL) {
 686         printf("Cannot open %s\n", hbaConfFilePath);
 687         return HBA_STATUS_ERROR;
 688     }
 689 
 690     /* Read in each line and load library */
 691     while ((hbaconf != NULL) && (fgets(fullline, sizeof(fullline), hbaconf))) {
 692         /* Skip the comments... */
 693         if ((fullline[0] == '#') || (fullline[0] == '\n')) {
 694             continue;
 695         }
 696 
 697         /* grab first 'thing' in line (if its there)*/
 698         if((libraryname = strtok(fullline, " \t\n")) != NULL) {
 699             if(strlen(libraryname) >= 64) {
 700                 fprintf(stderr, "Library name(%s) in %s is > 64 characters\n",
 701                         libraryname, hbaConfFilePath);
 702             }
 703         }
 704         /* grab second 'thing' in line (if its there)*/
 705         if((librarypath = strtok(NULL, " \t\n")) != NULL) {
 706             if(strlen(librarypath) >= 256) {
 707                 fprintf(stderr, "Library path(%s) in %s is > 256 characters\n",
 708                         librarypath, hbaConfFilePath);
 709             }
 710         }
 711 
 712         /* there should be no more 'things' in the line */
 713         if((charPtr = strtok(NULL, " \n\t")) != NULL) {
 714             fprintf(stderr, "Extraneous characters (\"%s\") in %s\n",
 715                     charPtr, hbaConfFilePath);
 716         }
 717 
 718         /* Continue to the next line if library name or path is invalid */
 719         if (libraryname == NULL ||
 720             strlen(libraryname) == 0 ||
 721             librarypath == NULL ||
 722             (strlen(librarypath) == 0)) {
 723             continue;
 724         }
 725         /* 
 726          * Special case....
 727          * Look for loglevel
 728          */
 729         if(strcmp(libraryname, "debuglevel") == 0) {
 730             _hbaapi_debuglevel = strtol(librarypath, NULL, 10);
 731             /* error handling does the right thing automagically */
 732             continue;
 733         }
 734 
 735         lib_infop = (HBA_LIBRARY_INFO *)calloc(1, sizeof(HBA_LIBRARY_INFO));
 736         if(lib_infop == NULL) {
 737             fprintf(stderr, "HBA_LoadLibrary: out of memeory\n");
 738             return(HBA_STATUS_ERROR);
 739         }
 740         lib_infop->status = HBA_LIBRARY_NOT_LOADED;
 741         lib_infop->LibraryName = strdup(libraryname);
 742         lib_infop->LibraryPath = strdup(librarypath);
 743         lib_infop->index = _hbaapi_total_library_count;
 744         _hbaapi_total_library_count++;
 745         lib_infop->next = _hbaapi_librarylist;
 746         _hbaapi_librarylist = lib_infop;
 747 
 748         /* Load the DLL now */
 749         if((lib_infop->hLibrary = dlopen(librarypath,RTLD_LAZY)) == NULL) {
 750             /*printf("unable to load library %s\n", librarypath); */
 751             continue;
 752         }
 753         /* Call the registration function to get the list of pointers */
 754         RegisterV2Func = (HBARegisterLibraryV2Func)
 755             dlsym(lib_infop->hLibrary, "HBA_RegisterLibraryV2");
 756         if (RegisterV2Func != NULL) {
 757             /* Load the function points directly into
 758              * the table of functions */
 759             status = ((RegisterV2Func)(&lib_infop->functionTable));
 760             if (status != HBA_STATUS_OK) {
 761                 /* library not loaded */
 762                 continue;
 763             }
 764         } else {
 765             /* Maybe the vendor library is only Rev1 */
 766             RegisterFunc = (HBARegisterLibraryFunc)
 767                 dlsym(lib_infop->hLibrary, "HBA_RegisterLibrary");
 768             if(RegisterFunc == NULL) {
 769                 /* This function is required */
 770                 fprintf(stderr,
 771                         "HBA_LoadLibrary: vendor specific RegisterLibrary "
 772                         "function not found.  lib: %s\n", librarypath);
 773                 DEBUG(0, "HBA_LoadLibrary: vendor specific RegisterLibrary "
 774                       "function not found.  lib: %s\n", librarypath, 0, 0);
 775                 continue;
 776             }
 777             /* Load the function points directly into
 778              * the table of functions */
 779             status = ((RegisterFunc)
 780                       ((HBA_ENTRYPOINTS *)(&lib_infop->functionTable)));
 781             if (status != HBA_STATUS_OK) {
 782                 /* library not loaded */
 783                 fprintf(stderr,
 784                         "HBA_LoadLibrary: vendor specific RegisterLibrary "
 785                         "function encountered an error.  lib: %s\n", librarypath);
 786                 DEBUG(0, "HBA_LoadLibrary: vendor specific RegisterLibrary "
 787                       "function encountered an error. lib: %s\n", librarypath, 0, 0);
 788                 continue;
 789             }
 790         }
 791 
 792         /* successfully loaded library */
 793         if((GetVersionFunc = lib_infop->functionTable.GetVersionHandler) 
 794            == NULL) {
 795             continue;
 796         }
 797 #ifdef NOTDEF /* save for a later time... when it matters */
 798         libversion = ((GetVersionFunc)());
 799         /* Check the version of this library before loading */
 800         /* Actually... This wrapper is compatible with version 1 */
 801         if(libversion < HBA_LIBVERSION) {
 802             printf("Library version mismatch. Got %d expected %d.\n",
 803                    libversion, HBA_LIBVERSION);
 804             continue;
 805         }
 806         DEBUG(1, "%s libversion = %d", librarypath, libversion, 0);
 807 #endif
 808         LoadLibraryFunc = lib_infop->functionTable.LoadLibraryHandler;
 809         if (LoadLibraryFunc == NULL) {
 810             /* this function is required */
 811             fprintf(stderr,
 812                     "HBA_LoadLibrary: vendor specific LoadLibrary "
 813                     "function not found.  lib: %s\n", librarypath);
 814             DEBUG(0, "HBA_LoadLibrary: vendor specific LoadLibrary "
 815                     "function not found.  lib: %s\n", librarypath, 0, 0);
 816             continue;
 817         }
 818         /* Initialize this library */
 819         if((status = ((LoadLibraryFunc)())) != HBA_STATUS_OK) {
 820             /* maybe this should be a printf so that we CANNOT miss it */
 821             fprintf(stderr, 
 822                     "HBA_LoadLibrary: Encounterd and error loading: %s",
 823                     librarypath);
 824             DEBUG(0, "Encounterd and error loading: %s", librarypath, 0, 0);
 825             DEBUG(0, "  HBA_STATUS: %d", status, 0, 0);
 826             continue;
 827         }
 828         /* successfully loaded library */
 829         lib_infop->status = HBA_LIBRARY_LOADED;
 830     }
 831 
 832     fclose(hbaconf);
 833 #endif /* WIN32 or UNIX */
 834 #ifdef POSIX_THREADS
 835     ret = pthread_mutex_init(&_hbaapi_LL_mutex, NULL);
 836     if(ret == 0) {
 837         ret = pthread_mutex_init(&_hbaapi_AL_mutex, NULL);
 838     }
 839     if(ret == 0) {
 840         ret = pthread_mutex_init(&_hbaapi_AAE_mutex, NULL);
 841     }
 842     if(ret == 0) {
 843         ret = pthread_mutex_init(&_hbaapi_AE_mutex, NULL);
 844     }
 845     if(ret == 0) {
 846         ret = pthread_mutex_init(&_hbaapi_APE_mutex, NULL);
 847     }
 848     if(ret == 0) {
 849         ret = pthread_mutex_init(&_hbaapi_APSE_mutex, NULL);
 850     }
 851     if(ret == 0) {
 852         ret = pthread_mutex_init(&_hbaapi_TE_mutex, NULL);
 853     }
 854     if(ret == 0) {
 855         ret = pthread_mutex_init(&_hbaapi_LE_mutex, NULL);
 856     }
 857     if(ret != 0) {
 858         perror("pthread_mutec_init - HBA_LoadLibrary");
 859         return(HBA_STATUS_ERROR);
 860     }
 861 #elif defined(WIN32)
 862     InitializeCriticalSection(&_hbaapi_LL_mutex);
 863     InitializeCriticalSection(&_hbaapi_AL_mutex);
 864     InitializeCriticalSection(&_hbaapi_AAE_mutex);
 865     InitializeCriticalSection(&_hbaapi_AE_mutex);
 866     InitializeCriticalSection(&_hbaapi_APE_mutex);
 867     InitializeCriticalSection(&_hbaapi_APSE_mutex);
 868     InitializeCriticalSection(&_hbaapi_TE_mutex);
 869     InitializeCriticalSection(&_hbaapi_LE_mutex);
 870 #endif
 871 
 872 
 873     return HBA_STATUS_OK;
 874 }
 875 
 876 HBA_STATUS
 877 HBA_FreeLibrary(void) {
 878     HBAFreeLibraryFunc  FreeLibraryFunc;
 879     HBA_LIBRARY_INFO    *lib_infop;
 880     HBA_LIBRARY_INFO    *lib_next;
 881     HBA_ADAPTERCALLBACK_ELEM
 882                         ***listp;
 883     HBA_ADAPTER_INFO    *adapt_infop;
 884     HBA_ADAPTER_INFO    *adapt_next;
 885 
 886     ARE_WE_INITED();
 887     GRAB_MUTEX(&_hbaapi_LL_mutex);
 888     GRAB_MUTEX(&_hbaapi_AL_mutex);
 889 
 890     DEBUG(1, "HBA_FreeLibrary()", 0, 0, 0);
 891     for(lib_infop = _hbaapi_librarylist; lib_infop != NULL; lib_infop = lib_next) {
 892         lib_next = lib_infop->next;
 893         if (lib_infop->status == HBA_LIBRARY_LOADED) {
 894             FreeLibraryFunc = lib_infop->functionTable.FreeLibraryHandler;
 895             if (FreeLibraryFunc != NULL) {
 896                 /* Free this library */
 897                 (void)((FreeLibraryFunc)());
 898             }
 899 #ifdef WIN32
 900             FreeLibrary(lib_infop->hLibrary);        /* Unload DLL from memory */
 901 #else
 902             dlclose(lib_infop->hLibrary);    /* Unload DLL from memory */
 903 #endif
 904         }
 905 #ifndef WIN32
 906         free(lib_infop->LibraryName);
 907 #endif
 908         free(lib_infop->LibraryPath);
 909         free(lib_infop);
 910 
 911     }
 912     _hbaapi_librarylist = NULL;
 913     /* OK, now all functions are disabled except for LoadLibrary,
 914      * Hope no other thread calls it before we have returned */
 915     _hbaapi_total_library_count = 0;
 916 
 917     for(adapt_infop = _hbaapi_adapterlist;
 918         adapt_infop != NULL;
 919         adapt_infop = adapt_next) {
 920         adapt_next = adapt_infop->next;
 921         free(adapt_infop->name);
 922         free(adapt_infop);
 923     }
 924     _hbaapi_adapterlist = NULL;
 925     _hbaapi_total_adapter_count = 0;
 926 
 927     /* Free up the callbacks, this is not the most efficient, but it works */
 928     while((volatile HBA_ADAPTERCALLBACK_ELEM *)
 929           _hbaapi_adapteraddevents_callback_list
 930           != NULL) {
 931         local_remove_callback((HBA_CALLBACKHANDLE)
 932                            _hbaapi_adapteraddevents_callback_list);
 933     }
 934     for(listp = cb_lists_array; *listp != NULL; listp++) {
 935         while((volatile HBA_ADAPTERCALLBACK_ELEM ***)**listp != NULL) {
 936             local_remove_callback((HBA_CALLBACKHANDLE)**listp);
 937         }
 938     }
 939 
 940     RELEASE_MUTEX(&_hbaapi_AL_mutex);
 941     RELEASE_MUTEX(&_hbaapi_LL_mutex);
 942     
 943 #ifdef USESYSLOG
 944     closelog();
 945 #endif
 946 #ifdef USELOGFILE
 947     if(_hbaapi_debug_fd != NULL) {
 948         fclose(_hbaapi_debug_fd);
 949     }
 950     _hbaapi_debug_fd = NULL;
 951 #endif
 952 #ifdef POSIX_THREADS
 953     /* this will unlock them as well, but who cares */
 954     pthread_mutex_destroy(&_hbaapi_LE_mutex);
 955     pthread_mutex_destroy(&_hbaapi_TE_mutex);
 956     pthread_mutex_destroy(&_hbaapi_APSE_mutex);
 957     pthread_mutex_destroy(&_hbaapi_APE_mutex);
 958     pthread_mutex_destroy(&_hbaapi_AE_mutex);
 959     pthread_mutex_destroy(&_hbaapi_AAE_mutex);
 960     pthread_mutex_destroy(&_hbaapi_AL_mutex);
 961     pthread_mutex_destroy(&_hbaapi_LL_mutex);
 962 #elif defined(WIN32)
 963     DeleteCriticalSection(&_hbaapi_LL_mutex);
 964     DeleteCriticalSection(&_hbaapi_AL_mutex);
 965     DeleteCriticalSection(&_hbaapi_AAE_mutex);
 966     DeleteCriticalSection(&_hbaapi_AE_mutex);
 967     DeleteCriticalSection(&_hbaapi_APE_mutex);
 968     DeleteCriticalSection(&_hbaapi_APSE_mutex);
 969     DeleteCriticalSection(&_hbaapi_TE_mutex);
 970     DeleteCriticalSection(&_hbaapi_LE_mutex);
 971 #endif
 972     
 973     return HBA_STATUS_OK;
 974 }
 975 
 976 /*
 977  * The API used to use fixed size tables as its primary data structure.
 978  * Indexing from 1 to N identified each adapters.  Now the adapters are
 979  * on a linked list.  There is a unique "index" foreach each adapter.
 980  * Adapters always keep their index, even if they are removed from the
 981  * hardware.  The only time the indexing is reset is on HBA_FreeLibrary
 982  */
 983 HBA_UINT32
 984 HBA_GetNumberOfAdapters(void) {
 985     int j=0;
 986     HBA_LIBRARY_INFO    *lib_infop;
 987     HBAGetNumberOfAdaptersFunc
 988                         GetNumberOfAdaptersFunc;
 989     HBAGetAdapterNameFunc
 990                         GetAdapterNameFunc;
 991     HBA_BOOLEAN         found_name;
 992     HBA_ADAPTER_INFO    *adapt_infop;
 993     HBA_STATUS          status;
 994 
 995     char adaptername[256];
 996     int num_adapters; /* local */
 997 
 998     if(_hbaapi_librarylist == NULL) {
 999         return (0);
1000     }
1001     GRAB_MUTEX(&_hbaapi_LL_mutex); /* pay attention to order */
1002     GRAB_MUTEX(&_hbaapi_AL_mutex);
1003 
1004     for (lib_infop = _hbaapi_librarylist;
1005          lib_infop != NULL;
1006          lib_infop = lib_infop->next) {
1007 
1008         if (lib_infop->status != HBA_LIBRARY_LOADED) {
1009             continue;
1010         }
1011 
1012         GetNumberOfAdaptersFunc =
1013             lib_infop->functionTable.GetNumberOfAdaptersHandler;
1014         if (GetNumberOfAdaptersFunc == NULL)  {
1015             continue;
1016         }
1017         num_adapters = ((GetNumberOfAdaptersFunc)());
1018 #ifndef WIN32
1019         DEBUG(1, "HBAAPI: num_adapters for %s = %d\n", 
1020               lib_infop->LibraryName, num_adapters, 0);
1021 #else
1022         DEBUG(1, "HBAAPI: num_adapters for %s = %d\n", 
1023               lib_infop->LibraryPath, num_adapters, 0);
1024 #endif
1025 
1026         /* Also get the names of all the adapters here and cache */
1027         GetAdapterNameFunc = lib_infop->functionTable.GetAdapterNameHandler;
1028         if(GetAdapterNameFunc == NULL) {
1029             continue;
1030         }
1031 
1032         for (j = 0; j < num_adapters; j++) {
1033             found_name = 0;
1034             status = (GetAdapterNameFunc)(j, (char *)&adaptername);
1035             if(status == HBA_STATUS_OK) {
1036                 for(adapt_infop = _hbaapi_adapterlist;
1037                     adapt_infop != NULL;
1038                     adapt_infop = adapt_infop->next) {
1039                     /*
1040                      * check for duplicates, really, this may just be a second
1041                      * call to this function
1042                      * ??? how do we know when a name becomes stale?
1043                      */
1044                     if(strcmp(adaptername, adapt_infop->name) == 0) {
1045                         /* already got this one */
1046                         found_name++;
1047                         break;
1048                     }
1049                 }
1050                 if(found_name != 0) {
1051                     continue;
1052                 }
1053             }
1054 
1055             adapt_infop = (HBA_ADAPTER_INFO *)
1056                 calloc(1, sizeof(HBA_ADAPTER_INFO));
1057             if(adapt_infop == NULL) {
1058 #ifndef WIN32
1059                 fprintf(stderr,
1060                         "HBA_GetNumberOfAdapters: calloc failed on sizeof:%d\n",
1061                         sizeof(HBA_ADAPTER_INFO));
1062 #endif
1063                 RELEASE_MUTEX(&_hbaapi_AL_mutex);
1064                 RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex,
1065                                      _hbaapi_total_adapter_count);
1066             }
1067             if((adapt_infop->GNstatus = status) == HBA_STATUS_OK) {
1068                 adapt_infop->name = strdup(adaptername);
1069             } else {
1070                 char dummyname[512];
1071                 sprintf(dummyname, "NULLADAPTER-%s-%03d", 
1072                         lib_infop->LibraryPath, _hbaapi_total_adapter_count);
1073                 dummyname[255] = '\0';
1074                 adapt_infop->name = strdup(dummyname);
1075             }
1076             adapt_infop->library = lib_infop;
1077             adapt_infop->next = _hbaapi_adapterlist;
1078             adapt_infop->index = _hbaapi_total_adapter_count;
1079             _hbaapi_adapterlist = adapt_infop;
1080             _hbaapi_total_adapter_count++;
1081         }
1082     }
1083     RELEASE_MUTEX(&_hbaapi_AL_mutex);
1084     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, _hbaapi_total_adapter_count);
1085 }
1086 
1087 HBA_STATUS
1088 HBA_GetAdapterName(
1089     HBA_UINT32 adapterindex,
1090     char *adaptername)
1091 {
1092     HBA_ADAPTER_INFO    *adapt_infop;
1093     HBA_STATUS          ret = HBA_STATUS_ERROR_ILLEGAL_INDEX;
1094 
1095     if (adaptername == NULL) {
1096             return(HBA_STATUS_ERROR_ARG);
1097     }
1098     /*
1099      * The adapter index is from old code, but we have
1100      * to support it.  Go down the list looking for
1101      * the adapter
1102      */
1103     ARE_WE_INITED();
1104     GRAB_MUTEX(&_hbaapi_AL_mutex);
1105     *adaptername = '\0';
1106     for(adapt_infop = _hbaapi_adapterlist;
1107         adapt_infop != NULL;
1108         adapt_infop = adapt_infop->next) {
1109 
1110         if(adapt_infop->index == adapterindex) {
1111             if(adapt_infop->name != NULL && 
1112                adapt_infop->GNstatus == HBA_STATUS_OK) {
1113                 strcpy(adaptername, adapt_infop->name);
1114             } else {
1115                 *adaptername = '\0';
1116             }
1117             ret = adapt_infop->GNstatus;
1118             break;
1119         }
1120     }
1121     DEBUG(2, "GetAdapterName for index:%d ->%s", adapterindex, adaptername, 0);
1122     RELEASE_MUTEX_RETURN(&_hbaapi_AL_mutex, ret);
1123 }
1124 
1125 HBA_HANDLE
1126 HBA_OpenAdapter(char* adaptername) {
1127     HBA_HANDLE          handle;
1128     HBAOpenAdapterFunc  OpenAdapterFunc;
1129     HBA_ADAPTER_INFO    *adapt_infop;
1130     HBA_LIBRARY_INFO    *lib_infop;
1131 
1132     DEBUG(2, "OpenAdapter: %s", adaptername, 0, 0);
1133 
1134     if(_hbaapi_librarylist == NULL) {
1135         return(HBA_HANDLE_INVALID);
1136     }
1137     if (adaptername == NULL) {
1138         return(HBA_STATUS_ERROR_ARG);
1139     }
1140     handle = HBA_HANDLE_INVALID;
1141     GRAB_MUTEX(&_hbaapi_AL_mutex);
1142     for(adapt_infop = _hbaapi_adapterlist;
1143         adapt_infop != NULL;
1144         adapt_infop = adapt_infop->next) {
1145         if (strcmp(adaptername, adapt_infop->name) != 0) {
1146             continue;
1147         }
1148         lib_infop = adapt_infop->library;
1149         OpenAdapterFunc =
1150             lib_infop->functionTable.OpenAdapterHandler;
1151         if (OpenAdapterFunc != NULL) {
1152             /* retrieve the vendor handle */
1153             handle = (OpenAdapterFunc)(adaptername);
1154             if(handle != 0) {
1155                 /* or this with the library index to get the common handle */
1156                 handle = HBA_HANDLE_FROM_LOCAL(lib_infop->index, handle);
1157             }
1158         }
1159         break;
1160     }
1161     RELEASE_MUTEX_RETURN(&_hbaapi_AL_mutex, handle);
1162 }
1163 /*
1164  * This function ignores the list of known adapters and instead tries
1165  * each vendors open function to see if one of them
1166  * can open an adapter when referenced with a particular WWN
1167  */
1168 HBA_STATUS
1169 HBA_OpenAdapterByWWN(HBA_HANDLE *phandle, HBA_WWN nodeWWN) {
1170     HBA_HANDLE          handle;
1171     HBA_LIBRARY_INFO    *lib_infop;
1172     HBAGetNumberOfAdaptersFunc
1173                         GetNumberOfAdaptersFunc;
1174     HBAOpenAdapterByWWNFunc
1175                         OpenAdapterFunc;
1176     HBA_STATUS          status;
1177 
1178     DEBUG(2, "OpenAdapterByWWN: %s", WWN2STR1(&nodeWWN), 0, 0);
1179 
1180     if (phandle == NULL) {
1181             return(HBA_STATUS_ERROR_ARG);
1182     }
1183 
1184     ARE_WE_INITED();
1185 
1186     *phandle = HBA_HANDLE_INVALID;
1187 
1188     GRAB_MUTEX(&_hbaapi_LL_mutex);
1189     for (lib_infop = _hbaapi_librarylist;
1190          lib_infop != NULL;
1191          lib_infop = lib_infop->next) {
1192 
1193         status = HBA_STATUS_ERROR_ILLEGAL_WWN;
1194 
1195         if (lib_infop->status != HBA_LIBRARY_LOADED) {
1196             continue;
1197         }
1198 
1199         GetNumberOfAdaptersFunc =
1200             lib_infop->functionTable.GetNumberOfAdaptersHandler;
1201         if (GetNumberOfAdaptersFunc == NULL)  {
1202             continue;
1203         }
1204 
1205         /* look for new hardware */
1206         (void) ((GetNumberOfAdaptersFunc)());
1207  
1208         OpenAdapterFunc = lib_infop->functionTable.OpenAdapterByWWNHandler;
1209         if (OpenAdapterFunc == NULL) {
1210             continue;
1211         }
1212         /*
1213          * We do not know if the WWN is known by this vendor,
1214          * just try it
1215          */
1216         if((status = (OpenAdapterFunc)(&handle, nodeWWN)) != HBA_STATUS_OK) {
1217             continue;
1218         }
1219         /* OK, make a vendor non-specific handle */
1220         *phandle = HBA_HANDLE_FROM_LOCAL(lib_infop->index, handle);
1221         status = HBA_STATUS_OK;
1222         break;
1223     }
1224     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1225 }
1226 
1227 void
1228 HBA_RefreshAdapterConfiguration() {
1229     DEBUG(2, "HBA_RefreshAdapterConfiguration", 0, 0, 0);
1230     (void)HBA_GetNumberOfAdapters();
1231     return;
1232 }
1233 
1234 HBA_UINT32
1235 HBA_GetVersion() {
1236     DEBUG(2, "HBA_GetVersion", 0, 0, 0);
1237     return HBA_LIBVERSION;
1238 }
1239 
1240 /* 
1241  * This function is VERY OS dependent.  Wing it as best you can.
1242  */
1243 HBA_UINT32
1244 HBA_GetWrapperLibraryAttributes (
1245     HBA_LIBRARYATTRIBUTES *attributes)
1246 {
1247 
1248     DEBUG(2, "HBA_GetWrapperLibraryAttributes", 0, 0, 0);
1249 
1250     if (attributes == NULL) {
1251             return(HBA_STATUS_ERROR_ARG);
1252     }
1253 
1254     memset(attributes, 0, sizeof(HBA_LIBRARYATTRIBUTES));
1255 
1256 #if defined(SOLARIS)
1257     if((handle = dlopen("libHBAAPI.so", RTLD_NOW)) != NULL) {
1258         if(dlinfo(handle, RTLD_DI_LINKMAP, &map) >= 0) {
1259             for(mp = map; mp != NULL; mp = mp->l_next) {
1260                 if(strlen(map->l_name) < 256) {
1261                     strcpy(attributes->LibPath, map->l_lname);
1262                 }
1263             }
1264         }
1265     }
1266 #elif defined(WIN32)
1267     {
1268         HMODULE module;
1269 
1270         /* No need to do anything with the module handle */
1271         /* It wasn't alloocated so it doesn't need to be freed */
1272         module = GetModuleHandle("HBAAPI");
1273         if ( module != NULL ) {
1274             if ( GetModuleFileName(module, attributes->LibPath,
1275                                 sizeof(attributes->LibPath)) == 0 ) {
1276                 attributes->LibPath[0] = '\0';
1277             }
1278         }
1279     }
1280 #endif
1281 #if defined(VENDOR)
1282     strcpy(attributes->VName, VENDOR);
1283 #else
1284     attributes->VName[0] = '\0';
1285 #endif
1286 #if defined(VERSION)
1287     strcpy(attributes->VVersion, VERSION);
1288 #else
1289     attributes->VVersion[0] = '\0';
1290 #endif
1291 #if defined(BUILD_DATE)
1292 #if defined(WIN32)
1293     {
1294         int matchCount;
1295         matchCount = sscanf(BUILD_DATE, "%u/%u/%u %u:%u:%u",
1296                 &attributes->build_date.tm_year,
1297                 &attributes->build_date.tm_mon,
1298                 &attributes->build_date.tm_mday,
1299                 &attributes->build_date.tm_hour,
1300                 &attributes->build_date.tm_min,
1301                 &attributes->build_date.tm_sec
1302         );
1303 
1304         if ( matchCount != 6 ) {
1305             memset(&attributes->build_date, 0, sizeof(struct tm));
1306         } else {
1307             attributes->build_date.tm_year -= 1900;
1308             attributes->build_date.tm_isdst = -1;
1309         }
1310 
1311     }
1312 #else
1313     if(strptime(BUILD_DATE, "%Y/%m/%d %T %Z", &(attributes->build_date)) == NULL) {
1314         memset(&attributes->build_date, 0, sizeof(struct tm));
1315     }
1316 #endif
1317 #else
1318     memset(&attributes->build_date, 0, sizeof(struct tm));
1319 #endif
1320     return 2;
1321 }
1322 
1323 /*
1324  * Callback registation and handling
1325  */
1326 HBA_STATUS
1327 HBA_RemoveCallback (HBA_CALLBACKHANDLE cbhandle) {
1328     HBA_STATUS  status;
1329 
1330     DEBUG(2, "HBA_RemoveCallback", 0, 0, 0);
1331     ARE_WE_INITED();
1332 
1333     GRAB_MUTEX(&_hbaapi_LL_mutex);
1334     status = local_remove_callback(cbhandle);
1335     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1336 }
1337 
1338 /* Adapter Add Events *********************************************************/
1339 static void
1340 adapteraddevents_callback (void *data, HBA_WWN PortWWN, HBA_UINT32 eventType) {
1341     HBA_ALLADAPTERSCALLBACK_ELEM        *cbp;
1342 
1343     DEBUG(3, "AddAdapterEvent, port:%s", WWN2STR1(&PortWWN), 0, 0);
1344 
1345     GRAB_MUTEX(&_hbaapi_AAE_mutex);
1346     for(cbp = _hbaapi_adapteraddevents_callback_list;
1347         cbp != NULL;
1348         cbp = cbp->next) {
1349         (*cbp->callback)(data, PortWWN, HBA_EVENT_ADAPTER_ADD);
1350     }
1351     RELEASE_MUTEX(&_hbaapi_AAE_mutex);
1352 
1353 }
1354 HBA_STATUS
1355 HBA_RegisterForAdapterAddEvents (
1356     void                (*callback) (
1357         void            *data,
1358         HBA_WWN         PortWWN,
1359         HBA_UINT32      eventType
1360         ),
1361     void                *userData,
1362     HBA_CALLBACKHANDLE *callbackHandle) {
1363 
1364     HBA_ALLADAPTERSCALLBACK_ELEM        *cbp;
1365     HBA_VENDORCALLBACK_ELEM             *vcbp;
1366     HBA_VENDORCALLBACK_ELEM             *vendorhandlelist;
1367     HBARegisterForAdapterAddEventsFunc  registeredfunc;
1368     HBA_STATUS                          status = HBA_STATUS_OK;
1369     HBA_STATUS                          failure = HBA_STATUS_OK;
1370     HBA_LIBRARY_INFO                    *lib_infop;
1371     int                                 registered_cnt = 0;
1372     int                                 vendor_cnt = 0;
1373     int                                 not_supported_cnt = 0;
1374     int                                 status_OK_bar_cnt = 0;
1375     int                                 status_OK_cnt = 0;
1376 
1377     DEBUG(2, "HBA_RegisterForAdapterAddEvents", 0, 0, 0);
1378 
1379     if (callbackHandle == NULL) {
1380             return(HBA_STATUS_ERROR_ARG);
1381     }
1382     ARE_WE_INITED();
1383 
1384     cbp = (HBA_ALLADAPTERSCALLBACK_ELEM *)
1385         calloc(1, sizeof(HBA_ALLADAPTERSCALLBACK_ELEM));
1386     *callbackHandle = (HBA_CALLBACKHANDLE) cbp;
1387     if(cbp == NULL) {
1388 #ifndef WIN32
1389         fprintf(stderr,
1390                 "HBA_RegisterForAdapterAddEvents: calloc failed for %d bytes\n",
1391                 sizeof(HBA_ALLADAPTERSCALLBACK_ELEM));
1392 #endif
1393         return HBA_STATUS_ERROR;
1394     }
1395 
1396     GRAB_MUTEX(&_hbaapi_LL_mutex);
1397     GRAB_MUTEX(&_hbaapi_AAE_mutex);
1398     cbp->callback = callback;
1399     cbp->next = _hbaapi_adapteraddevents_callback_list;
1400     _hbaapi_adapteraddevents_callback_list = cbp;
1401     /* Need to release the mutex now incase the vendor function invokes the
1402      * callback.  We will grap the mutex later to attach the vendor handle list
1403      * to the callback structure */
1404     RELEASE_MUTEX(&_hbaapi_AAE_mutex);
1405     
1406 
1407     /*
1408      * now create a list of vendors (vendor libraryies, NOT ADAPTERS) that have
1409      * successfully registerred
1410      */
1411     vendorhandlelist = NULL;
1412     for(lib_infop = _hbaapi_librarylist;
1413         lib_infop != NULL;
1414         lib_infop = lib_infop->next) {
1415 
1416         vendor_cnt++;
1417 
1418         registeredfunc =
1419             lib_infop->functionTable.RegisterForAdapterAddEventsHandler;
1420         if(registeredfunc == NULL) {
1421             continue;
1422         }
1423 
1424         vcbp = (HBA_VENDORCALLBACK_ELEM *)
1425             calloc(1, sizeof(HBA_VENDORCALLBACK_ELEM));
1426         if(vcbp == NULL) {
1427 #ifndef WIN32
1428             fprintf(stderr,
1429                     "HBA_RegisterForAdapterAddEvents: "
1430                     "calloc failed for %d bytes\n",
1431                     sizeof(HBA_VENDORCALLBACK_ELEM));
1432 #endif
1433             freevendorhandlelist(vendorhandlelist);
1434             status = HBA_STATUS_ERROR;
1435             break;
1436         }
1437 
1438         registered_cnt++;
1439         status = (registeredfunc)(adapteraddevents_callback,
1440                                   userData, &vcbp->vendorcbhandle);
1441         if(status == HBA_STATUS_ERROR_NOT_SUPPORTED) {
1442             not_supported_cnt++;
1443             free(vcbp);
1444             continue;
1445         } else if (status != HBA_STATUS_OK) {
1446             status_OK_bar_cnt++;
1447             DEBUG(0,
1448                   "HBA_RegisterForAdapterAddEvents: Library->%s, Error->%d",
1449                   lib_infop->LibraryPath, status, 0);
1450 #ifndef WIN32
1451             fprintf(stderr,
1452                     "HBA_RegisterForAdapterAddEvents: Library->%s, Error->%d",
1453                     lib_infop->LibraryPath, status);
1454 #endif
1455             failure = status;
1456             free(vcbp);
1457             continue;
1458         } else {
1459             status_OK_cnt++;
1460         }
1461         vcbp->lib_info = lib_infop;
1462         vcbp->next = vendorhandlelist;
1463         vendorhandlelist = vcbp;
1464     }
1465     if(registered_cnt == 0) {
1466         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
1467         freevendorhandlelist(vendorhandlelist);
1468         local_remove_callback((HBA_CALLBACKHANDLE) cbp);
1469     } else if (status_OK_cnt == 0 && not_supported_cnt != 0) {
1470         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
1471     } else if (status_OK_cnt == 0) {
1472         /* At least one vendor library registered this function, but no
1473          * vendor call succeeded */
1474         local_remove_callback((HBA_CALLBACKHANDLE) cbp);
1475         status = failure;
1476     } else {
1477         /* we have had atleast some success, now finish up */
1478         GRAB_MUTEX(&_hbaapi_AAE_mutex);
1479         /* this seems silly, but what if another thread called 
1480          * the callback remove */
1481         for(cbp = _hbaapi_adapteraddevents_callback_list;
1482             cbp != NULL; cbp = cbp->next) {
1483             if((HBA_CALLBACKHANDLE)cbp == *callbackHandle) {
1484                 /* yup, its still there, hooray */
1485                 cbp->vendorhandlelist = vendorhandlelist;
1486                 vendorhandlelist = NULL;
1487                 break;
1488             }
1489         }
1490         RELEASE_MUTEX(&_hbaapi_AAE_mutex);
1491         if(vendorhandlelist != NULL) {
1492             /* bummer, somebody removed the callback before we finished
1493              * registration, probably will never happen */
1494             freevendorhandlelist(vendorhandlelist);
1495             DEBUG(0, 
1496                   "HBA_RegisterForAdapterAddEvents: HBA_RemoveCallback was "
1497                   "called for a handle before registration was finished.",
1498                   0, 0, 0);
1499             status = HBA_STATUS_ERROR;
1500         } else {
1501             status = HBA_STATUS_OK;
1502         }
1503     }
1504     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1505 }
1506 
1507 /* Adapter Events (other than add) ********************************************/
1508 static void
1509 adapterevents_callback (void *data,
1510                         HBA_WWN PortWWN,
1511                         HBA_UINT32 eventType) {
1512     HBA_ADAPTERCALLBACK_ELEM    *acbp;
1513 
1514     DEBUG(3, "AdapterEvent, port:%s, eventType:%d", WWN2STR1(&PortWWN),
1515           eventType, 0);
1516     
1517     GRAB_MUTEX(&_hbaapi_AE_mutex);
1518     for(acbp = _hbaapi_adapterevents_callback_list;
1519         acbp != NULL;
1520         acbp = acbp->next) {
1521         if(data == (void *)acbp) {
1522             (*acbp->callback)(acbp->userdata, PortWWN, eventType);
1523             break;
1524         }
1525     }
1526     RELEASE_MUTEX(&_hbaapi_AE_mutex);
1527 }
1528 HBA_STATUS
1529 HBA_RegisterForAdapterEvents (
1530     void                (*callback) (
1531         void            *data,
1532         HBA_WWN         PortWWN,
1533         HBA_UINT32      eventType
1534         ),
1535     void                *userData,
1536     HBA_HANDLE          handle,
1537     HBA_CALLBACKHANDLE  *callbackHandle) {
1538 
1539     HBA_ADAPTERCALLBACK_ELEM            *acbp;
1540     HBARegisterForAdapterEventsFunc     registeredfunc;
1541     HBA_STATUS                          status;
1542     HBA_LIBRARY_INFO                    *lib_infop;
1543     HBA_HANDLE                          vendorHandle;
1544 
1545     DEBUG(2, "HBA_RegisterForAdapterEvents", 0, 0, 0);
1546 
1547     if (callbackHandle == NULL) {
1548             return(HBA_STATUS_ERROR_ARG);
1549     }
1550 
1551     CHECKLIBRARY();
1552 
1553     /* we now have the _hbaapi_LL_mutex */
1554 
1555     registeredfunc = lib_infop->functionTable.RegisterForAdapterEventsHandler;
1556     if(registeredfunc == NULL) {
1557         RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
1558     }
1559 
1560     /*
1561      * that allocated memory is used both as the handle for the
1562      * caller, and as userdata to the vendor call so that on
1563      * callback the specific registration may be recalled
1564      */
1565     acbp = (HBA_ADAPTERCALLBACK_ELEM *) 
1566         calloc(1, sizeof(HBA_ADAPTERCALLBACK_ELEM));
1567     if(acbp == NULL) {
1568 #ifndef WIN32
1569         fprintf(stderr,
1570                 "HBA_RegisterForAdapterEvents: calloc failed for %d bytes\n",
1571                 sizeof(HBA_ADAPTERCALLBACK_ELEM));
1572 #endif
1573         RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
1574     }
1575     *callbackHandle = (HBA_CALLBACKHANDLE) acbp;
1576     acbp->callback = callback;
1577     acbp->userdata = userData;
1578     acbp->lib_info = lib_infop;
1579 
1580     status = (registeredfunc)(adapterevents_callback,
1581                               (void *)acbp,
1582                               vendorHandle,
1583                               &acbp->vendorcbhandle);
1584     if(status != HBA_STATUS_OK) {
1585         free(acbp);
1586         RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1587     }
1588 
1589     GRAB_MUTEX(&_hbaapi_AE_mutex);
1590     acbp->next = _hbaapi_adapterevents_callback_list;
1591     _hbaapi_adapterevents_callback_list = acbp;
1592     RELEASE_MUTEX(&_hbaapi_AE_mutex);
1593 
1594     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
1595 }
1596 
1597 /* Adapter Port Events ********************************************************/
1598 static void
1599 adapterportevents_callback (void *data,
1600                             HBA_WWN PortWWN,
1601                             HBA_UINT32 eventType,
1602                             HBA_UINT32 fabricPortID) {
1603     HBA_ADAPTERCALLBACK_ELEM    *acbp;
1604 
1605     DEBUG(3, "AdapterPortEvent, port:%s, eventType:%d fabricPortID:0X%06x",
1606           WWN2STR1(&PortWWN), eventType, fabricPortID);
1607     
1608     GRAB_MUTEX(&_hbaapi_APE_mutex);
1609 
1610     for(acbp = _hbaapi_adapterportevents_callback_list;
1611         acbp != NULL;
1612         acbp = acbp->next) {
1613         if(data == (void *)acbp) {
1614             (*acbp->callback)(acbp->userdata, PortWWN, eventType, fabricPortID);
1615             break;
1616         }
1617     }
1618     RELEASE_MUTEX(&_hbaapi_APE_mutex);
1619 }
1620 HBA_STATUS
1621 HBA_RegisterForAdapterPortEvents (
1622     void                (*callback) (
1623         void            *data,
1624         HBA_WWN         PortWWN,
1625         HBA_UINT32      eventType,
1626         HBA_UINT32      fabricPortID
1627         ),
1628     void                *userData,
1629     HBA_HANDLE          handle,
1630     HBA_WWN             PortWWN,
1631     HBA_CALLBACKHANDLE  *callbackHandle) {
1632 
1633     HBA_ADAPTERCALLBACK_ELEM            *acbp;
1634     HBARegisterForAdapterPortEventsFunc registeredfunc;
1635     HBA_STATUS                          status;
1636     HBA_LIBRARY_INFO                    *lib_infop;
1637     HBA_HANDLE                          vendorHandle;
1638 
1639     DEBUG(2, "HBA_RegisterForAdapterPortEvents for port: %s",
1640           WWN2STR1(&PortWWN), 0, 0);
1641 
1642     if (callbackHandle == NULL) {
1643             return(HBA_STATUS_ERROR_ARG);
1644     }
1645 
1646     CHECKLIBRARY();
1647     /* we now have the _hbaapi_LL_mutex */
1648 
1649     registeredfunc = 
1650         lib_infop->functionTable.RegisterForAdapterPortEventsHandler;
1651     if(registeredfunc == NULL) {
1652         RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
1653     }
1654 
1655     /*
1656      * that allocated memory is used both as the handle for the
1657      * caller, and as userdata to the vendor call so that on
1658      * callback the specific registration may be recalled
1659      */
1660     acbp = (HBA_ADAPTERCALLBACK_ELEM *) 
1661         calloc(1, sizeof(HBA_ADAPTERCALLBACK_ELEM));
1662     if(acbp == NULL) {
1663 #ifndef WIN32
1664         fprintf(stderr,
1665                 "HBA_RegisterForAdapterPortEvents: "
1666                 "calloc failed for %d bytes\n",
1667                 sizeof(HBA_ADAPTERCALLBACK_ELEM));
1668 #endif
1669         RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
1670 
1671     }
1672     *callbackHandle = (HBA_CALLBACKHANDLE) acbp;
1673     acbp->callback = callback;
1674     acbp->userdata = userData;
1675     acbp->lib_info = lib_infop;
1676 
1677     status = (registeredfunc)(adapterportevents_callback,
1678                               (void *)acbp,
1679                               vendorHandle,
1680                               PortWWN,
1681                               &acbp->vendorcbhandle);
1682     if(status != HBA_STATUS_OK) {
1683         free(acbp);
1684         RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1685     }
1686 
1687     GRAB_MUTEX(&_hbaapi_APE_mutex);
1688     acbp->next = _hbaapi_adapterportevents_callback_list;
1689     _hbaapi_adapterportevents_callback_list = acbp;
1690     RELEASE_MUTEX(&_hbaapi_APE_mutex);
1691 
1692     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
1693 }
1694 
1695 /* Adapter State Events *******************************************************/
1696 static void
1697 adapterportstatevents_callback (void *data,
1698                                 HBA_WWN PortWWN,
1699                                 HBA_UINT32 eventType) {
1700     HBA_ADAPTERCALLBACK_ELEM    *acbp;
1701 
1702     DEBUG(3, "AdapterPortStateEvent, port:%s, eventType:%d", WWN2STR1(&PortWWN),
1703           eventType, 0);
1704     
1705     GRAB_MUTEX(&_hbaapi_APSE_mutex);
1706     for(acbp = _hbaapi_adapterportstatevents_callback_list;
1707         acbp != NULL;
1708         acbp = acbp->next) {
1709         if(data == (void *)acbp) {
1710             (*acbp->callback)(acbp->userdata, PortWWN, eventType);
1711             return;
1712         }
1713     }
1714 }
1715 HBA_STATUS
1716 HBA_RegisterForAdapterPortStatEvents (
1717     void                (*callback) (
1718         void            *data,
1719         HBA_WWN         PortWWN,
1720         HBA_UINT32      eventType
1721         ),
1722     void                *userData,
1723     HBA_HANDLE          handle,
1724     HBA_WWN             PortWWN,
1725     HBA_PORTSTATISTICS  stats,
1726     HBA_UINT32          statType,
1727     HBA_CALLBACKHANDLE  *callbackHandle) {
1728 
1729     HBA_ADAPTERCALLBACK_ELEM    *acbp;
1730     HBARegisterForAdapterPortStatEventsFunc
1731                                 registeredfunc;
1732     HBA_STATUS                  status;
1733     HBA_LIBRARY_INFO            *lib_infop;
1734     HBA_HANDLE                  vendorHandle;
1735 
1736     DEBUG(2, "HBA_RegisterForAdapterPortStatEvents for port: %s", 
1737           WWN2STR1(&PortWWN), 0, 0);
1738 
1739     if (callbackHandle == NULL) {
1740             return(HBA_STATUS_ERROR_ARG);
1741     }
1742 
1743     CHECKLIBRARY();
1744     /* we now have the _hbaapi_LL_mutex */
1745 
1746     registeredfunc =
1747         lib_infop->functionTable.RegisterForAdapterPortStatEventsHandler;
1748     if(registeredfunc == NULL) {
1749         RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
1750     }
1751 
1752     /*
1753      * that allocated memory is used both as the handle for the
1754      * caller, and as userdata to the vendor call so that on
1755      * callback the specific registration may be recalled
1756      */
1757     acbp = (HBA_ADAPTERCALLBACK_ELEM *) 
1758         calloc(1, sizeof(HBA_ADAPTERCALLBACK_ELEM));
1759     if(acbp == NULL) {
1760 #ifndef WIN32
1761         fprintf(stderr,
1762                 "HBA_RegisterForAdapterPortStatEvents: "
1763                 "calloc failed for %d bytes\n",
1764                 sizeof(HBA_ADAPTERCALLBACK_ELEM));
1765 #endif
1766         RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
1767     }
1768     *callbackHandle = (HBA_CALLBACKHANDLE) acbp;
1769     acbp->callback = callback;
1770     acbp->userdata = userData;
1771     acbp->lib_info = lib_infop;
1772 
1773     status = (registeredfunc)(adapterportstatevents_callback,
1774                               (void *)acbp,
1775                               vendorHandle,
1776                               PortWWN,
1777                               stats,
1778                               statType,
1779                               &acbp->vendorcbhandle);
1780     if(status != HBA_STATUS_OK) {
1781         free(acbp);
1782         RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1783     }
1784 
1785     GRAB_MUTEX(&_hbaapi_APSE_mutex);
1786     acbp->next = _hbaapi_adapterportstatevents_callback_list;
1787     _hbaapi_adapterportstatevents_callback_list = acbp;
1788     RELEASE_MUTEX(&_hbaapi_APSE_mutex);
1789 
1790     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
1791 }
1792 
1793 /* Target Events **************************************************************/
1794 static void
1795 targetevents_callback (void *data,
1796                        HBA_WWN hbaPortWWN,
1797                        HBA_WWN discoveredPortWWN,
1798                        HBA_UINT32 eventType) {
1799     HBA_ADAPTERCALLBACK_ELEM    *acbp;
1800 
1801     DEBUG(3, "TargetEvent, hbaPort:%s, discoveredPort:%s eventType:%d",
1802           WWN2STR1(&hbaPortWWN), WWN2STR2(&discoveredPortWWN), eventType);
1803     
1804     GRAB_MUTEX(&_hbaapi_TE_mutex);
1805     for(acbp = _hbaapi_targetevents_callback_list;
1806         acbp != NULL;
1807         acbp = acbp->next) {
1808         if(data == (void *)acbp) {
1809             (*acbp->callback)(acbp->userdata, hbaPortWWN,
1810                               discoveredPortWWN, eventType);
1811             break;
1812         }
1813     }
1814     RELEASE_MUTEX(&_hbaapi_TE_mutex);
1815 }
1816 HBA_STATUS
1817 HBA_RegisterForTargetEvents (
1818     void                (*callback) (
1819         void            *data,
1820         HBA_WWN         hbaPortWWN,
1821         HBA_WWN         discoveredPortWWN,
1822         HBA_UINT32      eventType
1823         ),
1824     void                *userData,
1825     HBA_HANDLE          handle,
1826     HBA_WWN             hbaPortWWN,
1827     HBA_WWN             discoveredPortWWN,
1828     HBA_CALLBACKHANDLE  *callbackHandle,
1829     HBA_UINT32          allTargets) {
1830 
1831     HBA_ADAPTERCALLBACK_ELEM
1832                         *acbp;
1833     HBARegisterForTargetEventsFunc
1834                         registeredfunc;
1835     HBA_STATUS          status;
1836     HBA_LIBRARY_INFO    *lib_infop;
1837     HBA_HANDLE          vendorHandle;
1838     
1839     DEBUG(2, "HBA_RegisterForTargetEvents, hbaPort: %s, discoveredPort: %s",
1840           WWN2STR1(&hbaPortWWN), WWN2STR2(&discoveredPortWWN), 0);
1841 
1842     if (callbackHandle == NULL) {
1843             return(HBA_STATUS_ERROR_ARG);
1844     }
1845 
1846     CHECKLIBRARY();
1847     /* we now have the _hbaapi_LL_mutex */
1848 
1849     registeredfunc = lib_infop->functionTable.RegisterForTargetEventsHandler;
1850     if(registeredfunc == NULL) {
1851         RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
1852     }
1853 
1854     /*
1855      * that allocated memory is used both as the handle for the
1856      * caller, and as userdata to the vendor call so that on
1857      * callback the specific registration may be recalled
1858      */
1859     acbp = (HBA_ADAPTERCALLBACK_ELEM *) 
1860         calloc(1, sizeof(HBA_ADAPTERCALLBACK_ELEM));
1861     if(acbp == NULL) {
1862 #ifndef WIN32
1863         fprintf(stderr,
1864                 "HBA_RegisterForTargetEvents: calloc failed for %d bytes\n",
1865                 sizeof(HBA_ADAPTERCALLBACK_ELEM));
1866 #endif
1867         RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
1868     }
1869     *callbackHandle = (HBA_CALLBACKHANDLE) acbp;
1870     acbp->callback = callback;
1871     acbp->userdata = userData;
1872     acbp->lib_info = lib_infop;
1873 
1874     status = (registeredfunc)(targetevents_callback,
1875                               (void *)acbp,
1876                               vendorHandle,
1877                               hbaPortWWN,
1878                               discoveredPortWWN,
1879                               &acbp->vendorcbhandle,
1880                               allTargets);
1881     if(status != HBA_STATUS_OK) {
1882         free(acbp);
1883         RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1884     }
1885 
1886     GRAB_MUTEX(&_hbaapi_TE_mutex);
1887     acbp->next = _hbaapi_targetevents_callback_list;
1888     _hbaapi_targetevents_callback_list = acbp;
1889     RELEASE_MUTEX(&_hbaapi_TE_mutex);
1890 
1891     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
1892 }
1893 
1894 /* Link Events ****************************************************************/
1895 static void
1896 linkevents_callback (void *data,
1897                      HBA_WWN adapterWWN,
1898                      HBA_UINT32 eventType,
1899                      void *pRLIRBuffer,
1900                      HBA_UINT32 RLIRBufferSize) {
1901     HBA_ADAPTERCALLBACK_ELEM    *acbp;
1902 
1903     DEBUG(3, "LinkEvent, hbaWWN:%s, eventType:%d",
1904           WWN2STR1(&adapterWWN), eventType, 0);
1905     
1906     GRAB_MUTEX(&_hbaapi_LE_mutex);
1907     for(acbp = _hbaapi_linkevents_callback_list;
1908         acbp != NULL;
1909         acbp = acbp->next) {
1910         if(data == (void *)acbp) {
1911             (*acbp->callback)(acbp->userdata, adapterWWN,
1912                               eventType, pRLIRBuffer, RLIRBufferSize);
1913             break;
1914         }
1915     }
1916     RELEASE_MUTEX(&_hbaapi_LE_mutex);
1917 }
1918 HBA_STATUS
1919 HBA_RegisterForLinkEvents (
1920     void                (*callback) (
1921         void            *data,
1922         HBA_WWN         adapterWWN,
1923         HBA_UINT32      eventType,
1924         void            *pRLIRBuffer,
1925         HBA_UINT32      RLIRBufferSize),
1926     void                *userData,
1927     void                *pRLIRBuffer,
1928     HBA_UINT32          RLIRBufferSize,
1929     HBA_HANDLE          handle,
1930     HBA_CALLBACKHANDLE  *callbackHandle) {
1931 
1932     HBA_ADAPTERCALLBACK_ELEM    *acbp;
1933     HBARegisterForLinkEventsFunc
1934                                 registeredfunc;
1935     HBA_STATUS                  status;
1936     HBA_LIBRARY_INFO            *lib_infop;
1937     HBA_HANDLE                  vendorHandle;
1938 
1939     DEBUG(2, "HBA_RegisterForLinkEvents", 0, 0, 0);
1940 
1941     if (callbackHandle == NULL) {
1942             return(HBA_STATUS_ERROR_ARG);
1943     }
1944 
1945     CHECKLIBRARY();
1946     /* we now have the _hbaapi_LL_mutex */
1947 
1948     registeredfunc = lib_infop->functionTable.RegisterForLinkEventsHandler;
1949     if(registeredfunc == NULL) {
1950         RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
1951     }
1952 
1953     /*
1954      * that allocated memory is used both as the handle for the
1955      * caller, and as userdata to the vendor call so that on
1956      * callback the specific registration may be recalled
1957      */
1958     acbp = (HBA_ADAPTERCALLBACK_ELEM *) 
1959         calloc(1, sizeof(HBA_ADAPTERCALLBACK_ELEM));
1960     if(acbp == NULL) {
1961 #ifndef WIN32
1962         fprintf(stderr,
1963                 "HBA_RegisterForLinkEvents: calloc failed for %d bytes\n",
1964                 sizeof(HBA_ADAPTERCALLBACK_ELEM));
1965 #endif
1966         RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
1967     }
1968     *callbackHandle = (HBA_CALLBACKHANDLE) acbp;
1969     acbp->callback = callback;
1970     acbp->userdata = userData;
1971     acbp->lib_info = lib_infop;
1972 
1973     status = (registeredfunc)(linkevents_callback,
1974                               (void *)acbp,
1975                               pRLIRBuffer,
1976                               RLIRBufferSize,
1977                               vendorHandle,
1978                               &acbp->vendorcbhandle);
1979     if(status != HBA_STATUS_OK) {
1980         free(acbp);
1981         RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
1982     }
1983 
1984     GRAB_MUTEX(&_hbaapi_LE_mutex);
1985     acbp->next = _hbaapi_linkevents_callback_list;
1986     _hbaapi_linkevents_callback_list = acbp;
1987     RELEASE_MUTEX(&_hbaapi_LE_mutex);
1988 
1989     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
1990 }
1991 
1992 
1993 /*
1994  * All of the functions below are almost passthru functions to the
1995  * vendor specific function
1996  */
1997 
1998 void
1999 HBA_CloseAdapter(HBA_HANDLE handle) {
2000     HBA_STATUS          status;
2001     HBA_LIBRARY_INFO    *lib_infop;
2002     HBA_HANDLE          vendorHandle;
2003     HBACloseAdapterFunc CloseAdapterFunc;
2004 
2005     DEBUG(2, "HBA_CloseAdapter", 0, 0, 0);
2006 
2007     status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);
2008     if (status == HBA_STATUS_OK) {
2009         CloseAdapterFunc = lib_infop->functionTable.CloseAdapterHandler;
2010         if (CloseAdapterFunc != NULL) {
2011             ((CloseAdapterFunc)(vendorHandle));
2012         }
2013         RELEASE_MUTEX(&_hbaapi_LL_mutex);
2014     }
2015 }
2016 
2017 HBA_STATUS
2018 HBA_GetAdapterAttributes (
2019     HBA_HANDLE          handle,
2020     HBA_ADAPTERATTRIBUTES 
2021                         *hbaattributes)
2022 {
2023     HBA_STATUS          status;
2024     HBA_LIBRARY_INFO    *lib_infop;
2025     HBA_HANDLE          vendorHandle;
2026     HBAGetAdapterAttributesFunc GetAdapterAttributesFunc;
2027 
2028     DEBUG(2, "HBA_GetAdapterAttributes", 0, 0, 0);
2029 
2030     CHECKLIBRARY();
2031     GetAdapterAttributesFunc = 
2032         lib_infop->functionTable.GetAdapterAttributesHandler;
2033     if (GetAdapterAttributesFunc != NULL) {
2034         status = ((GetAdapterAttributesFunc)(vendorHandle, hbaattributes));
2035     } else {
2036         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2037     }
2038     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2039 }
2040 
2041 HBA_STATUS
2042 HBA_GetAdapterPortAttributes (
2043     HBA_HANDLE          handle,
2044     HBA_UINT32          portindex,
2045     HBA_PORTATTRIBUTES  *portattributes)
2046 {
2047     HBA_STATUS          status;
2048     HBA_LIBRARY_INFO    *lib_infop;
2049     HBA_HANDLE          vendorHandle;
2050     HBAGetAdapterPortAttributesFunc
2051                         GetAdapterPortAttributesFunc;
2052 
2053     DEBUG(2, "HBA_GetAdapterPortAttributes", 0, 0, 0);
2054 
2055     CHECKLIBRARY();
2056     GetAdapterPortAttributesFunc = 
2057         lib_infop->functionTable.GetAdapterPortAttributesHandler;
2058     if (GetAdapterPortAttributesFunc != NULL) {
2059         status = ((GetAdapterPortAttributesFunc)
2060                   (vendorHandle, portindex, portattributes));
2061     } else {
2062         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2063     }
2064     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2065 }
2066 
2067 HBA_STATUS
2068 HBA_GetPortStatistics (
2069     HBA_HANDLE          handle, 
2070     HBA_UINT32          portindex,
2071     HBA_PORTSTATISTICS  *portstatistics)
2072 {
2073     HBA_STATUS          status;
2074     HBA_LIBRARY_INFO    *lib_infop;
2075     HBA_HANDLE          vendorHandle;
2076     HBAGetPortStatisticsFunc
2077                         GetPortStatisticsFunc;
2078 
2079     DEBUG(2, "HBA_GetPortStatistics", 0, 0, 0);
2080 
2081     CHECKLIBRARY();
2082     GetPortStatisticsFunc = 
2083         lib_infop->functionTable.GetPortStatisticsHandler;
2084     if (GetPortStatisticsFunc != NULL) {
2085         status = ((GetPortStatisticsFunc)
2086                   (vendorHandle, portindex, portstatistics));
2087     } else {
2088         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2089     }
2090     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2091 }
2092 
2093 HBA_STATUS
2094 HBA_GetDiscoveredPortAttributes (
2095     HBA_HANDLE          handle, 
2096     HBA_UINT32          portindex, 
2097     HBA_UINT32          discoveredportindex, 
2098     HBA_PORTATTRIBUTES  *portattributes)
2099 {
2100     HBA_STATUS          status;
2101     HBA_LIBRARY_INFO    *lib_infop;
2102     HBA_HANDLE          vendorHandle;
2103     HBAGetDiscoveredPortAttributesFunc
2104                         GetDiscoveredPortAttributesFunc;
2105 
2106     DEBUG(2, "HBA_GetDiscoveredPortAttributes", 0, 0, 0);
2107 
2108     CHECKLIBRARY();
2109     GetDiscoveredPortAttributesFunc = 
2110         lib_infop->functionTable.GetDiscoveredPortAttributesHandler;
2111     if (GetDiscoveredPortAttributesFunc != NULL)  {
2112         status = ((GetDiscoveredPortAttributesFunc)
2113                   (vendorHandle, portindex, discoveredportindex, 
2114                    portattributes));
2115     } else {
2116         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2117     }
2118     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2119 }
2120 
2121 HBA_STATUS
2122 HBA_GetPortAttributesByWWN (
2123     HBA_HANDLE          handle,
2124     HBA_WWN             PortWWN,
2125     HBA_PORTATTRIBUTES  *portattributes)
2126 {
2127     HBA_STATUS          status;
2128     HBA_LIBRARY_INFO    *lib_infop;
2129     HBA_HANDLE          vendorHandle;
2130     HBAGetPortAttributesByWWNFunc
2131                         GetPortAttributesByWWNFunc;
2132 
2133     DEBUG(2, "HBA_GetPortAttributesByWWN: %s", WWN2STR1(&PortWWN), 0, 0);
2134 
2135     CHECKLIBRARY();
2136     GetPortAttributesByWWNFunc = 
2137         lib_infop->functionTable.GetPortAttributesByWWNHandler;
2138     if (GetPortAttributesByWWNFunc != NULL) {
2139         status = ((GetPortAttributesByWWNFunc)
2140                   (vendorHandle, PortWWN, portattributes));
2141     } else {
2142         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2143     }
2144     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2145 }
2146 
2147 HBA_STATUS
2148 HBA_SendCTPassThru (
2149     HBA_HANDLE          handle,
2150     void                *pReqBuffer,
2151     HBA_UINT32          ReqBufferSize,
2152     void                *pRspBuffer,
2153     HBA_UINT32          RspBufferSize)
2154 {
2155     HBA_STATUS          status;
2156     HBA_LIBRARY_INFO    *lib_infop;
2157     HBA_HANDLE          vendorHandle;
2158     HBASendCTPassThruFunc
2159                         SendCTPassThruFunc;
2160 
2161     DEBUG(2, "HBA_SendCTPassThru", 0, 0, 0);
2162 
2163     CHECKLIBRARY();
2164     SendCTPassThruFunc = lib_infop->functionTable.SendCTPassThruHandler;
2165     if (SendCTPassThruFunc != NULL) {
2166         status = (SendCTPassThruFunc)
2167             (vendorHandle,
2168              pReqBuffer, ReqBufferSize,
2169              pRspBuffer, RspBufferSize);
2170     } else {
2171         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2172     }
2173     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2174 }
2175 
2176 HBA_STATUS
2177 HBA_SendCTPassThruV2 (
2178     HBA_HANDLE          handle,
2179     HBA_WWN             hbaPortWWN,
2180     void                *pReqBuffer,
2181     HBA_UINT32          ReqBufferSize,
2182     void                *pRspBuffer,
2183     HBA_UINT32          *pRspBufferSize)
2184 {
2185     HBA_STATUS          status;
2186     HBA_LIBRARY_INFO    *lib_infop;
2187     HBA_HANDLE          vendorHandle;
2188     HBASendCTPassThruV2Func
2189                         registeredfunc;
2190 
2191     DEBUG(2, "HBA_SendCTPassThruV2m hbaPortWWN: %s", WWN2STR1(&hbaPortWWN), 0, 0);
2192 
2193     CHECKLIBRARY();
2194     registeredfunc = lib_infop->functionTable.SendCTPassThruV2Handler;
2195     if (registeredfunc != NULL) {
2196         status = (registeredfunc)
2197             (vendorHandle, hbaPortWWN,
2198              pReqBuffer, ReqBufferSize,
2199              pRspBuffer, pRspBufferSize);
2200     } else {
2201         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2202     }
2203     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2204 }
2205 
2206 HBA_STATUS
2207 HBA_GetEventBuffer (
2208     HBA_HANDLE          handle,
2209     PHBA_EVENTINFO      EventBuffer,
2210     HBA_UINT32          *EventBufferCount)
2211 {
2212     HBA_STATUS          status;
2213     HBA_LIBRARY_INFO    *lib_infop;
2214     HBA_HANDLE          vendorHandle;
2215     HBAGetEventBufferFunc
2216                         GetEventBufferFunc;
2217 
2218     DEBUG(2, "HBA_GetEventBuffer", 0, 0, 0);
2219 
2220     CHECKLIBRARY();
2221     GetEventBufferFunc = lib_infop->functionTable.GetEventBufferHandler;
2222     if (GetEventBufferFunc != NULL) {
2223         status = (GetEventBufferFunc)
2224             (vendorHandle, EventBuffer, EventBufferCount);
2225     } else {
2226         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2227     }
2228     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2229 }
2230 
2231 HBA_STATUS
2232 HBA_SetRNIDMgmtInfo (HBA_HANDLE handle, HBA_MGMTINFO Info) {
2233     HBA_STATUS          status;
2234     HBA_LIBRARY_INFO    *lib_infop;
2235     HBA_HANDLE          vendorHandle;
2236     HBASetRNIDMgmtInfoFunc
2237                         SetRNIDMgmtInfoFunc;
2238 
2239     DEBUG(2, "HBA_SetRNIDMgmtInfo", 0, 0, 0);
2240 
2241     CHECKLIBRARY();
2242     SetRNIDMgmtInfoFunc = lib_infop->functionTable.SetRNIDMgmtInfoHandler;
2243     if (SetRNIDMgmtInfoFunc != NULL) {
2244         status = (SetRNIDMgmtInfoFunc)(vendorHandle, Info);
2245     } else {
2246         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2247     }
2248     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2249 }
2250 
2251 HBA_STATUS
2252 HBA_GetRNIDMgmtInfo (HBA_HANDLE handle, HBA_MGMTINFO *pInfo) {
2253     HBA_STATUS          status;
2254     HBA_LIBRARY_INFO    *lib_infop;
2255     HBA_HANDLE          vendorHandle;
2256     HBAGetRNIDMgmtInfoFunc
2257                          GetRNIDMgmtInfoFunc;
2258 
2259     DEBUG(2, "HBA_GetRNIDMgmtInfo", 0, 0, 0);
2260 
2261     CHECKLIBRARY();
2262     GetRNIDMgmtInfoFunc = lib_infop->functionTable.GetRNIDMgmtInfoHandler;
2263     if (GetRNIDMgmtInfoFunc != NULL) {
2264         status = (GetRNIDMgmtInfoFunc)(vendorHandle, pInfo);
2265     } else {
2266         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2267     }
2268     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2269 }
2270 
2271 HBA_STATUS
2272 HBA_SendRNID (
2273     HBA_HANDLE          handle,
2274     HBA_WWN             wwn,
2275     HBA_WWNTYPE         wwntype,
2276     void                *pRspBuffer,
2277     HBA_UINT32          *pRspBufferSize)
2278 {
2279     HBA_STATUS          status;
2280     HBA_LIBRARY_INFO    *lib_infop;
2281     HBA_HANDLE          vendorHandle;
2282     HBASendRNIDFunc     SendRNIDFunc;
2283 
2284     DEBUG(2, "HBA_SendRNID for wwn: %s", WWN2STR1(&wwn), 0, 0);
2285 
2286     CHECKLIBRARY();
2287     SendRNIDFunc = lib_infop->functionTable.SendRNIDHandler;
2288     if (SendRNIDFunc != NULL) {
2289         status = ((SendRNIDFunc)(vendorHandle, wwn, wwntype,
2290                                  pRspBuffer, pRspBufferSize));
2291     } else {
2292         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2293     }
2294     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2295 }
2296 
2297 HBA_STATUS
2298 HBA_SendRNIDV2(
2299     HBA_HANDLE          handle,
2300     HBA_WWN             hbaPortWWN,
2301     HBA_WWN             destWWN,
2302     HBA_UINT32          destFCID,
2303     HBA_UINT32          NodeIdDataFormat,
2304     void                *pRspBuffer,
2305     HBA_UINT32          *pRspBufferSize)
2306 {
2307     HBA_STATUS          status;
2308     HBA_LIBRARY_INFO    *lib_infop;
2309     HBA_HANDLE          vendorHandle;
2310     HBASendRNIDV2Func   registeredfunc;
2311 
2312     DEBUG(2, "HBA_SendRNIDV2, hbaPortWWN: %s", WWN2STR1(&hbaPortWWN), 0, 0);
2313 
2314     CHECKLIBRARY();
2315     registeredfunc = lib_infop->functionTable.SendRNIDV2Handler;
2316     if (registeredfunc != NULL) {
2317         status = (registeredfunc)
2318             (vendorHandle, hbaPortWWN, destWWN, destFCID, NodeIdDataFormat,
2319              pRspBuffer, pRspBufferSize);
2320     } else {
2321         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2322     }
2323     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2324 }
2325 
2326 void
2327 HBA_RefreshInformation (HBA_HANDLE handle) {
2328     HBA_STATUS          status;
2329     HBA_LIBRARY_INFO    *lib_infop;
2330     HBA_HANDLE          vendorHandle;
2331     HBARefreshInformationFunc
2332                         RefreshInformationFunc;
2333 
2334     DEBUG(2, "HBA_RefreshInformation", 0, 0, 0);
2335 
2336     status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);
2337     if(status == HBA_STATUS_OK) {
2338         RefreshInformationFunc = 
2339             lib_infop->functionTable.RefreshInformationHandler;
2340         if (RefreshInformationFunc != NULL) {
2341             ((RefreshInformationFunc)(vendorHandle));
2342         }
2343         RELEASE_MUTEX(&_hbaapi_LL_mutex);
2344     }
2345 }
2346 
2347 void
2348 HBA_ResetStatistics (HBA_HANDLE handle, HBA_UINT32 portindex) {
2349     HBA_STATUS          status;
2350     HBA_LIBRARY_INFO    *lib_infop;
2351     HBA_HANDLE          vendorHandle;
2352     HBAResetStatisticsFunc
2353                         ResetStatisticsFunc;
2354 
2355     DEBUG(2, "HBA_ResetStatistics", 0, 0, 0);
2356 
2357     status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);
2358     if(status == HBA_STATUS_OK) {
2359         ResetStatisticsFunc = lib_infop->functionTable.ResetStatisticsHandler;
2360         if (ResetStatisticsFunc != NULL) {
2361             ((ResetStatisticsFunc)(vendorHandle, portindex));
2362         }
2363         RELEASE_MUTEX(&_hbaapi_LL_mutex);
2364     }
2365 }
2366 
2367 HBA_STATUS
2368 HBA_GetFcpTargetMapping (HBA_HANDLE handle, PHBA_FCPTARGETMAPPING mapping) {
2369     HBA_STATUS          status;
2370     HBA_LIBRARY_INFO    *lib_infop;
2371     HBA_HANDLE          vendorHandle;
2372     HBAGetFcpTargetMappingFunc GetFcpTargetMappingFunc;
2373 
2374     DEBUG(2, "HBA_GetFcpTargetMapping", 0, 0, 0);
2375 
2376     CHECKLIBRARY();
2377     GetFcpTargetMappingFunc =
2378         lib_infop->functionTable.GetFcpTargetMappingHandler;
2379     if (GetFcpTargetMappingFunc != NULL) {
2380         status = ((GetFcpTargetMappingFunc)(vendorHandle, mapping));
2381     } else {
2382         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2383     }
2384     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2385 }
2386 
2387 HBA_STATUS
2388 HBA_GetFcpTargetMappingV2 (
2389     HBA_HANDLE          handle,
2390     HBA_WWN             hbaPortWWN,
2391     HBA_FCPTARGETMAPPINGV2
2392                         *pmapping)
2393 {
2394     HBA_STATUS          status;
2395     HBA_LIBRARY_INFO    *lib_infop;
2396     HBA_HANDLE          vendorHandle;
2397     HBAGetFcpTargetMappingV2Func
2398                         registeredfunc;
2399 
2400     DEBUG(2, "HBA_GetFcpTargetMapping", 0, 0, 0);
2401 
2402     CHECKLIBRARY();
2403     registeredfunc = 
2404         lib_infop->functionTable.GetFcpTargetMappingV2Handler;
2405     if (registeredfunc != NULL) {
2406         status = ((registeredfunc)(vendorHandle, hbaPortWWN, pmapping));
2407     } else {
2408         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2409     }
2410     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2411 }
2412 
2413 HBA_STATUS
2414 HBA_GetFcpPersistentBinding (HBA_HANDLE handle, PHBA_FCPBINDING binding) {
2415     HBA_STATUS          status;
2416     HBA_LIBRARY_INFO    *lib_infop;
2417     HBA_HANDLE          vendorHandle;
2418     HBAGetFcpPersistentBindingFunc
2419                         GetFcpPersistentBindingFunc;
2420 
2421     DEBUG(2, "HBA_GetFcpPersistentBinding", 0, 0, 0);
2422 
2423     CHECKLIBRARY();
2424     GetFcpPersistentBindingFunc =
2425         lib_infop->functionTable.GetFcpPersistentBindingHandler;
2426     if (GetFcpPersistentBindingFunc != NULL) {
2427         status = ((GetFcpPersistentBindingFunc)(vendorHandle, binding));
2428     } else {
2429         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2430     }
2431     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2432 }
2433 
2434 HBA_STATUS
2435 HBA_ScsiInquiryV2 (
2436     HBA_HANDLE  handle,
2437     HBA_WWN     hbaPortWWN,
2438     HBA_WWN     discoveredPortWWN,
2439     HBA_UINT64  fcLUN,
2440     HBA_UINT8   CDB_Byte1,
2441     HBA_UINT8   CDB_Byte2,
2442     void        *pRspBuffer,
2443     HBA_UINT32  *pRspBufferSize,
2444     HBA_UINT8   *pScsiStatus,
2445     void        *pSenseBuffer,
2446     HBA_UINT32  *pSenseBufferSize)
2447 {
2448     HBA_STATUS          status;
2449     HBA_LIBRARY_INFO    *lib_infop;
2450     HBA_HANDLE          vendorHandle;
2451     HBAScsiInquiryV2Func ScsiInquiryV2Func;
2452 
2453     DEBUG(2, "HBA_ScsiInquiryV2 to discoveredPortWWN: %s",
2454           WWN2STR1(&discoveredPortWWN), 0, 0);
2455 
2456     CHECKLIBRARY();
2457     ScsiInquiryV2Func =
2458         lib_infop->functionTable.ScsiInquiryV2Handler;
2459     if (ScsiInquiryV2Func != NULL) {
2460         status =((ScsiInquiryV2Func)(
2461             vendorHandle, hbaPortWWN, discoveredPortWWN, fcLUN, CDB_Byte1,
2462             CDB_Byte2, pRspBuffer, pRspBufferSize, pScsiStatus,
2463             pSenseBuffer, pSenseBufferSize));
2464     } else {
2465         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2466     }
2467     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2468 }
2469 
2470 HBA_STATUS
2471 HBA_SendScsiInquiry (
2472     HBA_HANDLE  handle,
2473     HBA_WWN     PortWWN,
2474     HBA_UINT64  fcLUN,
2475     HBA_UINT8   EVPD,
2476     HBA_UINT32  PageCode,
2477     void        *pRspBuffer,
2478     HBA_UINT32  RspBufferSize,
2479     void        *pSenseBuffer,
2480     HBA_UINT32  SenseBufferSize)
2481 {
2482     HBA_STATUS          status;
2483     HBA_LIBRARY_INFO    *lib_infop;
2484     HBA_HANDLE          vendorHandle;
2485     HBASendScsiInquiryFunc SendScsiInquiryFunc;
2486 
2487     DEBUG(2, "HBA_SendScsiInquiry to PortWWN: %s", WWN2STR1(&PortWWN), 0, 0);
2488 
2489     CHECKLIBRARY();
2490     SendScsiInquiryFunc = lib_infop->functionTable.ScsiInquiryHandler;
2491     if (SendScsiInquiryFunc != NULL) {
2492         status =((SendScsiInquiryFunc)(
2493             vendorHandle, PortWWN, fcLUN, EVPD, PageCode, pRspBuffer,
2494             RspBufferSize, pSenseBuffer, SenseBufferSize));
2495     } else {
2496         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2497     }
2498     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2499 }
2500 
2501 HBA_STATUS
2502 HBA_ScsiReportLUNsV2 (
2503     HBA_HANDLE          handle,
2504     HBA_WWN             hbaPortWWN,
2505     HBA_WWN             discoveredPortWWN,
2506     void                *pRespBuffer,
2507     HBA_UINT32          *pRespBufferSize,
2508     HBA_UINT8           *pScsiStatus,
2509     void                *pSenseBuffer,
2510     HBA_UINT32          *pSenseBufferSize)
2511 {
2512     HBA_STATUS          status;
2513     HBA_LIBRARY_INFO    *lib_infop;
2514     HBA_HANDLE          vendorHandle;
2515     HBAScsiReportLUNsV2Func ScsiReportLUNsV2Func;
2516 
2517     DEBUG(2, "HBA_ScsiReportLUNsV2 to discoveredPortWWN: %s",
2518           WWN2STR1(&discoveredPortWWN), 0, 0);
2519 
2520     CHECKLIBRARY();
2521     ScsiReportLUNsV2Func = lib_infop->functionTable.ScsiReportLUNsV2Handler;
2522     if (ScsiReportLUNsV2Func != NULL) {
2523         status = ((ScsiReportLUNsV2Func)(
2524             vendorHandle, hbaPortWWN, discoveredPortWWN,
2525             pRespBuffer, pRespBufferSize,
2526             pScsiStatus,
2527             pSenseBuffer, pSenseBufferSize));
2528     } else {
2529         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2530     }
2531     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2532 }
2533 
2534 HBA_STATUS
2535 HBA_SendReportLUNs (
2536     HBA_HANDLE handle,
2537     HBA_WWN portWWN,
2538     void *pRspBuffer,
2539     HBA_UINT32 RspBufferSize,
2540     void *pSenseBuffer,
2541     HBA_UINT32 SenseBufferSize)
2542 {
2543     HBA_STATUS          status;
2544     HBA_LIBRARY_INFO    *lib_infop;
2545     HBA_HANDLE          vendorHandle;
2546     HBASendReportLUNsFunc SendReportLUNsFunc;
2547 
2548     DEBUG(2, "HBA_SendReportLUNs to PortWWN: %s", WWN2STR1(&portWWN), 0, 0);
2549 
2550     CHECKLIBRARY();
2551     SendReportLUNsFunc = lib_infop->functionTable.ReportLUNsHandler;
2552     if (SendReportLUNsFunc != NULL) {
2553         status = ((SendReportLUNsFunc)(
2554             vendorHandle, portWWN, pRspBuffer,
2555             RspBufferSize, pSenseBuffer, SenseBufferSize));
2556     } else {
2557         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2558     }
2559     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2560 }
2561 
2562 HBA_STATUS
2563 HBA_ScsiReadCapacityV2 (
2564     HBA_HANDLE          handle,
2565     HBA_WWN             hbaPortWWN,
2566     HBA_WWN             discoveredPortWWN,
2567     HBA_UINT64          fcLUN,
2568     void                *pRspBuffer,
2569     HBA_UINT32          *pRspBufferSize,
2570     HBA_UINT8           *pScsiStatus,
2571     void                *pSenseBuffer,
2572     HBA_UINT32          *SenseBufferSize)
2573 {
2574     HBA_STATUS          status;
2575     HBA_LIBRARY_INFO    *lib_infop;
2576     HBA_HANDLE          vendorHandle;
2577     HBAScsiReadCapacityV2Func ScsiReadCapacityV2Func;
2578 
2579     DEBUG(2, "HBA_ScsiReadCapacityV2 to discoveredPortWWN: %s",
2580           WWN2STR1(&discoveredPortWWN), 0, 0);
2581 
2582     CHECKLIBRARY();
2583     ScsiReadCapacityV2Func =
2584         lib_infop->functionTable.ScsiReadCapacityV2Handler;
2585     if (ScsiReadCapacityV2Func != NULL) {
2586         status =((ScsiReadCapacityV2Func)(
2587             vendorHandle, hbaPortWWN, discoveredPortWWN, fcLUN,
2588             pRspBuffer, pRspBufferSize,
2589             pScsiStatus,
2590             pSenseBuffer, SenseBufferSize));
2591     } else {
2592         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2593     }
2594     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2595 }
2596 
2597 HBA_STATUS
2598 HBA_SendReadCapacity (
2599     HBA_HANDLE handle,
2600     HBA_WWN portWWN,
2601     HBA_UINT64 fcLUN,
2602     void *pRspBuffer,
2603     HBA_UINT32 RspBufferSize,
2604     void *pSenseBuffer,
2605     HBA_UINT32 SenseBufferSize)
2606 {
2607     HBA_STATUS          status;
2608     HBA_LIBRARY_INFO    *lib_infop;
2609     HBA_HANDLE          vendorHandle;
2610     HBASendReadCapacityFunc SendReadCapacityFunc;
2611 
2612     DEBUG(2, "HBA_SendReadCapacity to portWWN: %s", WWN2STR1(&portWWN), 0, 0);
2613 
2614     CHECKLIBRARY();
2615     SendReadCapacityFunc = lib_infop->functionTable.ReadCapacityHandler;
2616     if (SendReadCapacityFunc != NULL) {
2617         status =((SendReadCapacityFunc)
2618                  (vendorHandle, portWWN, fcLUN, pRspBuffer,
2619                   RspBufferSize, pSenseBuffer, SenseBufferSize));
2620     } else {
2621         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2622     }
2623     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2624 }
2625 
2626 HBA_STATUS
2627 HBA_SendRLS (
2628     HBA_HANDLE          handle,
2629     HBA_WWN             hbaPortWWN,
2630     HBA_WWN             destWWN,
2631     void                *pRspBuffer,
2632     HBA_UINT32          *pRspBufferSize)
2633 {
2634     HBA_STATUS          status;
2635     HBA_LIBRARY_INFO    *lib_infop;
2636     HBA_HANDLE          vendorHandle;
2637     HBASendRLSFunc registeredfunc;
2638 
2639     DEBUG(2, "HBA_SendRLS to agent_wwn: %s:%d",
2640           WWN2STR1(&agent_wwn), agent_domain, 0);
2641 
2642     CHECKLIBRARY();
2643     registeredfunc = lib_infop->functionTable.SendRLSHandler;
2644     if (registeredfunc != NULL) {
2645         status =(registeredfunc)(
2646             vendorHandle, hbaPortWWN, destWWN, pRspBuffer, pRspBufferSize);
2647     } else {
2648         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2649     }
2650     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2651 }
2652 
2653 HBA_STATUS
2654 HBA_SendRPL (
2655     HBA_HANDLE          handle,
2656     HBA_WWN             hbaPortWWN,
2657     HBA_WWN             agent_wwn,
2658     HBA_UINT32          agent_domain,
2659     HBA_UINT32          portindex,
2660     void                *pRspBuffer,
2661     HBA_UINT32          *pRspBufferSize)
2662 {
2663     HBA_STATUS          status;
2664     HBA_LIBRARY_INFO    *lib_infop;
2665     HBA_HANDLE          vendorHandle;
2666     HBASendRPLFunc registeredfunc;
2667 
2668     DEBUG(2, "HBA_SendRPL to agent_wwn: %s:%d",
2669           WWN2STR1(&agent_wwn), agent_domain, 0);
2670 
2671     CHECKLIBRARY();
2672     registeredfunc = lib_infop->functionTable.SendRPLHandler;
2673     if (registeredfunc != NULL) {
2674         status =(registeredfunc)(
2675             vendorHandle, hbaPortWWN, agent_wwn, agent_domain, portindex,
2676             pRspBuffer, pRspBufferSize);
2677     } else {
2678         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2679     }
2680     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2681 }
2682 
2683 HBA_STATUS
2684 HBA_SendRPS (
2685     HBA_HANDLE          handle,
2686     HBA_WWN             hbaPortWWN,
2687     HBA_WWN             agent_wwn,
2688     HBA_UINT32          agent_domain,
2689     HBA_WWN             object_wwn,
2690     HBA_UINT32          object_port_number,
2691     void                *pRspBuffer,
2692     HBA_UINT32          *pRspBufferSize)
2693 {
2694     HBA_STATUS          status;
2695     HBA_LIBRARY_INFO    *lib_infop;
2696     HBA_HANDLE          vendorHandle;
2697     HBASendRPSFunc registeredfunc;
2698 
2699     DEBUG(2, "HBA_SendRPS  to agent_wwn: %s:%d",
2700           WWN2STR1(&agent_wwn), agent_domain, 0);
2701 
2702     CHECKLIBRARY();
2703     registeredfunc = lib_infop->functionTable.SendRPSHandler;
2704     if (registeredfunc != NULL) {
2705         status =(registeredfunc)(
2706             vendorHandle, hbaPortWWN, agent_wwn, agent_domain,
2707             object_wwn, object_port_number,
2708             pRspBuffer, pRspBufferSize);
2709     } else {
2710         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2711     }
2712     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2713 }
2714 
2715 HBA_STATUS
2716 HBA_SendSRL (
2717     HBA_HANDLE          handle,
2718     HBA_WWN             hbaPortWWN,
2719     HBA_WWN             wwn,
2720     HBA_UINT32          domain,
2721     void                *pRspBuffer,
2722     HBA_UINT32          *pRspBufferSize)
2723 {
2724     HBA_STATUS          status;
2725     HBA_LIBRARY_INFO    *lib_infop;
2726     HBA_HANDLE          vendorHandle;
2727     HBASendSRLFunc registeredfunc;
2728 
2729     DEBUG(2, "HBA_SendSRL to wwn:%s domain:%d", WWN2STR1(&wwn), domain, 0);
2730 
2731     CHECKLIBRARY();
2732     registeredfunc = lib_infop->functionTable.SendSRLHandler;
2733     if (registeredfunc != NULL) {
2734         status =(registeredfunc)(
2735             vendorHandle, hbaPortWWN, wwn, domain,
2736             pRspBuffer, pRspBufferSize);
2737     } else {
2738         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2739     }
2740     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2741 }
2742 
2743 HBA_STATUS
2744 HBA_SendLIRR (
2745     HBA_HANDLE          handle,
2746     HBA_WWN             sourceWWN,
2747     HBA_WWN             destWWN,
2748     HBA_UINT8           function,
2749     HBA_UINT8           type,
2750     void                *pRspBuffer,
2751     HBA_UINT32          *pRspBufferSize)
2752 {
2753     HBA_STATUS          status;
2754     HBA_LIBRARY_INFO    *lib_infop;
2755     HBA_HANDLE          vendorHandle;
2756     HBASendLIRRFunc registeredfunc;
2757 
2758     DEBUG(2, "HBA_SendLIRR destWWN:%s", WWN2STR1(&destWWN), 0, 0);
2759 
2760     CHECKLIBRARY();
2761     registeredfunc = lib_infop->functionTable.SendLIRRHandler;
2762     if (registeredfunc != NULL) {
2763         status =(registeredfunc)(
2764             vendorHandle, sourceWWN, destWWN, function, type,
2765             pRspBuffer, pRspBufferSize);
2766     } else {
2767         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2768     }
2769     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2770 }
2771 
2772 HBA_STATUS
2773 HBA_GetBindingCapability(
2774     HBA_HANDLE          handle,
2775     HBA_WWN             hbaPortWWN,
2776     HBA_BIND_CAPABILITY *pcapability)
2777 {
2778     HBA_STATUS          status;
2779     HBA_LIBRARY_INFO    *lib_infop;
2780     HBA_HANDLE          vendorHandle;
2781     HBAGetBindingCapabilityFunc
2782                         registeredfunc;
2783 
2784     DEBUG(2, "HBA_GetBindingCapability", 0, 0, 0);
2785 
2786     CHECKLIBRARY();
2787     registeredfunc = lib_infop->functionTable.GetBindingCapabilityHandler;
2788     if (registeredfunc != NULL) {
2789         status =(registeredfunc)(vendorHandle, hbaPortWWN, pcapability);
2790     } else {
2791         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2792     }
2793     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2794 }
2795 
2796 HBA_STATUS
2797 HBA_GetBindingSupport (
2798     HBA_HANDLE          handle,
2799     HBA_WWN             hbaPortWWN,
2800     HBA_BIND_CAPABILITY *pcapability)
2801 {
2802     HBA_STATUS          status;
2803     HBA_LIBRARY_INFO    *lib_infop;
2804     HBA_HANDLE          vendorHandle;
2805     HBAGetBindingSupportFunc
2806                         registeredfunc;
2807 
2808     DEBUG(2, "HBA_GetBindingSupport", 0, 0, 0);
2809 
2810     CHECKLIBRARY();
2811     registeredfunc = lib_infop->functionTable.GetBindingSupportHandler;
2812     if (registeredfunc != NULL) {
2813         status =(registeredfunc)(vendorHandle, hbaPortWWN, pcapability);
2814     } else {
2815         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2816     }
2817     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2818 }
2819 
2820 HBA_STATUS
2821 HBA_SetBindingSupport(
2822     HBA_HANDLE          handle,
2823     HBA_WWN             hbaPortWWN,
2824     HBA_BIND_CAPABILITY capability)
2825 {
2826     HBA_STATUS          status;
2827     HBA_LIBRARY_INFO    *lib_infop;
2828     HBA_HANDLE          vendorHandle;
2829     HBASetBindingSupportFunc
2830                         registeredfunc;
2831 
2832     DEBUG(2, "HBA_SetBindingSupport", 0, 0, 0);
2833 
2834     CHECKLIBRARY();
2835     registeredfunc = lib_infop->functionTable.SetBindingSupportHandler;
2836     if (registeredfunc != NULL) {
2837         status =(registeredfunc)(vendorHandle, hbaPortWWN, capability);
2838     } else {
2839         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2840     }
2841     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2842 }
2843 
2844 HBA_STATUS
2845 HBA_SetPersistentBindingV2 (
2846     HBA_HANDLE          handle,
2847     HBA_WWN             hbaPortWWN,
2848     const HBA_FCPBINDING2
2849                         *pbinding)
2850 {
2851     HBA_STATUS          status;
2852     HBA_LIBRARY_INFO    *lib_infop;
2853     HBA_HANDLE          vendorHandle;
2854     HBASetPersistentBindingV2Func
2855                         registeredfunc;
2856 
2857     DEBUG(2, "HBA_SetPersistentBindingV2 port: %s", WWN2STR1(&hbaPortWWN), 0, 0);
2858 
2859     CHECKLIBRARY();
2860     registeredfunc = lib_infop->functionTable.SetPersistentBindingV2Handler;
2861     if (registeredfunc != NULL) {
2862         status =(registeredfunc)(vendorHandle, hbaPortWWN, pbinding);
2863     } else {
2864         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2865     }
2866     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2867 }
2868 
2869 HBA_STATUS
2870 HBA_GetPersistentBindingV2 (
2871     HBA_HANDLE          handle,
2872     HBA_WWN             hbaPortWWN,
2873     HBA_FCPBINDING2     *pbinding)
2874 {
2875     HBA_STATUS          status;
2876     HBA_LIBRARY_INFO    *lib_infop;
2877     HBA_HANDLE          vendorHandle;
2878     HBAGetPersistentBindingV2Func
2879                         registeredfunc;
2880 
2881     DEBUG(2, "HBA_GetPersistentBindingV2 port: %s", WWN2STR1(&hbaPortWWN), 0, 0);
2882 
2883     CHECKLIBRARY();
2884     registeredfunc = lib_infop->functionTable.GetPersistentBindingV2Handler;
2885     if (registeredfunc != NULL) {
2886         status =(registeredfunc)(vendorHandle, hbaPortWWN, pbinding);
2887     } else {
2888         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2889     }
2890     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2891 }
2892 
2893 HBA_STATUS
2894 HBA_RemovePersistentBinding (
2895     HBA_HANDLE          handle,
2896     HBA_WWN             hbaPortWWN,
2897     const HBA_FCPBINDING2
2898                         *pbinding)
2899 {
2900     HBA_STATUS          status;
2901     HBA_LIBRARY_INFO    *lib_infop;
2902     HBA_HANDLE          vendorHandle;
2903     HBARemovePersistentBindingFunc
2904                         registeredfunc;
2905 
2906     DEBUG(2, "HBA_RemovePersistentBinding", 0, 0, 0);
2907 
2908     CHECKLIBRARY();
2909     registeredfunc = 
2910         lib_infop->functionTable.RemovePersistentBindingHandler;
2911     if (registeredfunc != NULL) {
2912         status =(registeredfunc)(vendorHandle, hbaPortWWN, pbinding);
2913     } else {
2914         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2915     }
2916     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2917 }
2918 
2919 HBA_STATUS
2920 HBA_RemoveAllPersistentBindings (
2921     HBA_HANDLE          handle,
2922     HBA_WWN             hbaPortWWN)
2923 {
2924     HBA_STATUS          status;
2925     HBA_LIBRARY_INFO    *lib_infop;
2926     HBA_HANDLE          vendorHandle;
2927     HBARemoveAllPersistentBindingsFunc
2928                         registeredfunc;
2929 
2930     DEBUG(2, "HBA_RemoveAllPersistentBindings", 0, 0, 0);
2931 
2932     CHECKLIBRARY();
2933     registeredfunc = 
2934         lib_infop->functionTable.RemoveAllPersistentBindingsHandler;
2935     if (registeredfunc != NULL) {
2936         status =(registeredfunc)(vendorHandle, hbaPortWWN);
2937     } else {
2938         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2939     }
2940     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2941 }
2942 
2943 HBA_STATUS
2944 HBA_GetFC4Statistics (
2945     HBA_HANDLE          handle,
2946     HBA_WWN             portWWN,
2947     HBA_UINT8           FC4type,
2948     HBA_FC4STATISTICS   *pstatistics)
2949 {
2950     HBA_STATUS          status;
2951     HBA_LIBRARY_INFO    *lib_infop;
2952     HBA_HANDLE          vendorHandle;
2953     HBAGetFC4StatisticsFunc
2954                         registeredfunc;
2955 
2956     DEBUG(2, "HBA_GetFC4Statistics port: %s", WWN2STR1(&portWWN), 0, 0);
2957 
2958     CHECKLIBRARY();
2959     registeredfunc = 
2960         lib_infop->functionTable.GetFC4StatisticsHandler;
2961     if (registeredfunc != NULL) {
2962         status =(registeredfunc)
2963             (vendorHandle, portWWN, FC4type, pstatistics);
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_GetFCPStatistics (
2972     HBA_HANDLE          handle,
2973     const HBA_SCSIID    *lunit,
2974     HBA_FC4STATISTICS   *pstatistics)
2975 {
2976     HBA_STATUS          status;
2977     HBA_LIBRARY_INFO    *lib_infop;
2978     HBA_HANDLE          vendorHandle;
2979     HBAGetFCPStatisticsFunc
2980                         registeredfunc;
2981 
2982     DEBUG(2, "HBA_GetFCPStatistics", 0, 0, 0);
2983 
2984     CHECKLIBRARY();
2985     registeredfunc = 
2986         lib_infop->functionTable.GetFCPStatisticsHandler;
2987     if (registeredfunc != NULL) {
2988         status =(registeredfunc)(vendorHandle, lunit, pstatistics);
2989     } else {
2990         status = HBA_STATUS_ERROR_NOT_SUPPORTED;
2991     }
2992     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
2993 }
2994 
2995 HBA_UINT32
2996 HBA_GetVendorLibraryAttributes (
2997     HBA_UINT32 adapter_index,
2998     HBA_LIBRARYATTRIBUTES *attributes)
2999 {
3000     HBA_ADAPTER_INFO    *adapt_infop;
3001     HBAGetVendorLibraryAttributesFunc
3002                         registeredfunc;
3003     HBA_UINT32          ret = 0;
3004 
3005     DEBUG(2, "HBA_GetVendorLibraryAttributes adapterindex:%d",
3006           adapter_index, 0, 0);
3007     if(_hbaapi_librarylist == NULL) {
3008         DEBUG(1, "HBAAPI not loaded yet.", 0, 0, 0);
3009         return(0);
3010     }
3011 
3012     if (attributes == NULL) {
3013             return(HBA_STATUS_ERROR_ARG);
3014     }
3015 
3016     memset(attributes, 0, sizeof(HBA_LIBRARYATTRIBUTES));
3017 
3018     GRAB_MUTEX(&_hbaapi_LL_mutex);
3019     GRAB_MUTEX(&_hbaapi_AL_mutex);
3020     for(adapt_infop = _hbaapi_adapterlist;
3021         adapt_infop != NULL;
3022         adapt_infop = adapt_infop->next) {
3023 
3024         if(adapt_infop->index == adapter_index) {
3025             registeredfunc = adapt_infop->library->
3026                 functionTable.GetVendorLibraryAttributesHandler;
3027             if(registeredfunc != NULL) {
3028                 ret = (registeredfunc)(attributes);
3029             } else {
3030                 /* Version 1 libary? */
3031                 HBAGetVersionFunc       GetVersionFunc;
3032                 GetVersionFunc = adapt_infop->library->
3033                     functionTable.GetVersionHandler;
3034                 if(GetVersionFunc != NULL) {
3035                     ret = ((GetVersionFunc)());
3036                 }
3037 #ifdef NOTDEF
3038                 else {
3039                     /* This should not happen, dont think its going to */
3040                 }
3041 #endif
3042             }
3043             if (attributes->LibPath[0] == '\0') {
3044                 if(strlen(adapt_infop->library->LibraryPath) < 256) {
3045                     strcpy(attributes->LibPath, 
3046                            adapt_infop->library->LibraryPath);
3047                 }
3048             }
3049             break;
3050         }
3051     }
3052     RELEASE_MUTEX(&_hbaapi_AL_mutex);
3053     RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, ret);
3054 }