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