diff options
Diffstat (limited to 'usr/src/lib/hbaapi/common/HBAAPILIB.c')
-rw-r--r-- | usr/src/lib/hbaapi/common/HBAAPILIB.c | 3053 |
1 files changed, 3053 insertions, 0 deletions
diff --git a/usr/src/lib/hbaapi/common/HBAAPILIB.c b/usr/src/lib/hbaapi/common/HBAAPILIB.c new file mode 100644 index 0000000000..9a9c114100 --- /dev/null +++ b/usr/src/lib/hbaapi/common/HBAAPILIB.c @@ -0,0 +1,3053 @@ +/************************************************************************* + * Description + * HBAAPILIB.c - Implements a sample common (wrapper) HBA API library + * + * License: + * The contents of this file are subject to the SNIA Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * /http://www.snia.org/English/Resources/Code/OpenSource.html + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is SNIA HBA API Wrapper Library + * + * The Initial Developer of the Original Code is: + * Benjamin F. Kuo, Troika Networks, Inc. (benk@troikanetworks.com) + * + * Contributor(s): + * Tuan Lam, QLogic Corp. (t_lam@qlc.com) + * Dan Willie, Emulex Corp. (Dan.Willie@emulex.com) + * Dixon Hutchinson, Legato Systems, Inc. (dhutchin@legato.com) + * David Dillard, VERITAS Software Corp. (david.dillard@veritas.com) + * + ************************************************************************* + */ + +#ifdef WIN32 +#include <windows.h> +#include <string.h> +/* + * Next define forces entry points in the dll to be exported + * See hbaapi.h to see what it does. + */ +#define HBAAPI_EXPORTS +#else +#include <dlfcn.h> +#include <strings.h> +#endif +#include <stdio.h> +#include <time.h> +#include "hbaapi.h" +#include "vendorhbaapi.h" +#include <stdlib.h> +#ifdef USESYSLOG +#include <syslog.h> +#endif + +/* + * LIBRARY_NUM is a shortcut to figure out which library we need to call. + * The top 16 bits of handle are the library index + */ +#define LIBRARY_NUM(handle) ((handle)>>16) + +/* + * VENDOR_HANDLE turns a global library handle into a vendor specific handle, + * with all upper 16 bits set to 0 + */ +#define VENDOR_HANDLE(handle) ((handle)&0xFFFF) + +#define HBA_HANDLE_FROM_LOCAL(library, vendor) \ + (((library)<<16) | ((vendor)&0x0000FFFF)) + +int _hbaapi_debuglevel = 0; +#define DEBUG(L, STR, A1, A2, A3) + +#if defined(USESYSLOG) && defined(USELOGFILE) +FILE *_hbaapi_debug_fd = NULL; +int _hbaapi_sysloginit = 0; +#undef DEBUG +#ifdef WIN32 +#define DEBUG(L, STR, A1, A2, A3)\ + if ((L) <= _hbaapi_debuglevel) {\ + if(_hbaapi_sysloginit == 0) {\ + openlog("HBAAPI", LOG_PID|LOG_ODELAY ,LOG_USER);\ + _hbaapi_sysloginit = 1;\ + }\ + syslog (LOG_INFO, (STR), (A1), (A2), (A3));\ + if(_hbaapi_debug_fd == NULL) {\ + char _logFile[MAX_PATH]; \ + GetTempPath(MAX_PATH, _logFile); \ + strcat(_logFile, "HBAAPI.log"); \ + _hbaapi_debug_fd = fopen(_logFile, "a");\ + }\ + if(_hbaapi_debug_fd != NULL) {\ + fprintf(_hbaapi_debug_fd, (STR ## "\n"), (A1), (A2), (A3));\ + }\ + } +#else /* WIN32*/ +#define DEBUG(L, STR, A1, A2, A3)\ + if ((L) <= _hbaapi_debuglevel) {\ + if(_hbaapi_sysloginit == 0) {\ + openlog("HBAAPI", LOG_PID|LOG_ODELAY ,LOG_USER);\ + _hbaapi_sysloginit = 1;\ + }\ + syslog (LOG_INFO, (STR), (A1), (A2), (A3));\ + if(_hbaapi_debug_fd == NULL) {\ + _hbaapi_debug_fd = fopen("/tmp/HBAAPI.log", "a");\ + }\ + if(_hbaapi_debug_fd != NULL) {\ + fprintf(_hbaapi_debug_fd, (STR ## "\n"), (A1), (A2), (A3));\ + }\ + } +#endif /* WIN32*/ + +#else /* Not both USESYSLOG and USELOGFILE */ +#if defined(USESYSLOG) +int _hbaapi_sysloginit = 0; +#undef DEBUG +#define DEBUG(L, STR, A1, A2, A3) \ + if ((L) <= _hbaapi_debuglevel) {\ + if(_hbaapi_sysloginit == 0) {\ + openlog("HBAAPI", LOG_PID|LOG_ODELAY ,LOG_USER);\ + _hbaapi_sysloginit = 1;\ + }\ + syslog (LOG_INFO, (STR), (A1), (A2), (A3));\ + } +#endif /* USESYSLOG */ +#if defined(USELOGFILE) +FILE *_hbaapi_debug_fd = NULL; +#undef DEBUG +#ifdef WIN32 +#define DEBUG(L, STR, A1, A2, A3) \ + if((L) <= _hbaapi_debuglevel) {\ + if(_hbaapi_debug_fd == NULL) {\ + char _logFile[MAX_PATH]; \ + GetTempPath(MAX_PATH, _logFile); \ + strcat(_logFile, "HBAAPI.log"); \ + _hbaapi_debug_fd = fopen(_logFile, "a");\ + }\ + } +#else /* WIN32 */ +#define DEBUG(L, STR, A1, A2, A3) \ + if((L) <= _hbaapi_debuglevel) {\ + if(_hbaapi_debug_fd == NULL) {\ + _hbaapi_debug_fd = fopen("/tmp/HBAAPI.log", "a");\ + }\ + if(_hbaapi_debug_fd != NULL) { \ + fprintf(_hbaapi_debug_fd, (STR) ## "\n", (A1), (A2), (A3));\ + }\ + } +#endif /* WIN32 */ +#endif /* USELOGFILE */ +#endif /* Not both USELOGFILE and USESYSLOG */ + +#ifdef POSIX_THREADS +#include <pthread.h> +/* + * When multiple mutex's are grabed, they must be always be grabbed in + * the same order, or deadlock can result. There are three levels + * of mutex's involved in this API. If LL_mutex is grabbed, always grap + * it first. If AL_mutex is grabbed, it may not be grabbed before + * LL_mutex. If grabbed in a multi grab sequence, the mutex's protecting + * the callback lists must always be grabbed last and release before calling + * a vendor specific library function that might invoke a callback function + * on the same thread. + */ +#define GRAB_MUTEX(M) grab_mutex(M) +#define RELEASE_MUTEX(M) release_mutex(M) +#define RELEASE_MUTEX_RETURN(M,RET) release_mutex(M); return(RET) +#elif defined (WIN32) +#define GRAB_MUTEX(m) EnterCriticalSection(m) +#define RELEASE_MUTEX(m) LeaveCriticalSection(m) +#define RELEASE_MUTEX_RETURN(m, RET) LeaveCriticalSection(m); return(RET) +#else +#define GRAB_MUTEX(M) +#define RELEASE_MUTEX(M) +#define RELEASE_MUTEX_RETURN(M,RET) return(RET) +#endif + +/* + * Vendor library information + */ +typedef enum { + HBA_LIBRARY_UNKNOWN, + HBA_LIBRARY_LOADED, + HBA_LIBRARY_NOT_LOADED +} HBA_LIBRARY_STATUS; + +typedef struct hba_library_info { + struct hba_library_info + *next; +#ifdef WIN32 + HINSTANCE hLibrary; /* Handle to a loaded DLL */ +#else + char *LibraryName; + void* hLibrary; /* Handle to a loaded DLL */ +#endif + char *LibraryPath; + HBA_ENTRYPOINTSV2 functionTable; /* Function pointers */ + HBA_LIBRARY_STATUS status; /* info on this library */ + HBA_UINT32 index; +} HBA_LIBRARY_INFO, *PHBA_LIBRARY_INFO; + +#define ARE_WE_INITED() \ + if (_hbaapi_librarylist == NULL) { \ + return(HBA_STATUS_ERROR); \ + } +HBA_LIBRARY_INFO *_hbaapi_librarylist = NULL; +HBA_UINT32 _hbaapi_total_library_count = 0; +#ifdef POSIX_THREADS +pthread_mutex_t _hbaapi_LL_mutex = PTHREAD_MUTEX_INITIALIZER; +#elif defined(WIN32) +CRITICAL_SECTION _hbaapi_LL_mutex; +#endif + +/* + * Individual adapter (hba) information + */ +typedef struct hba_adapter_info { + struct hba_adapter_info + *next; + HBA_STATUS GNstatus; /* status from GetAdapterNameFunc */ + char *name; + HBA_WWN nodeWWN; + HBA_LIBRARY_INFO *library; + HBA_UINT32 index; +} HBA_ADAPTER_INFO; + +HBA_ADAPTER_INFO *_hbaapi_adapterlist = NULL; +HBA_UINT32 _hbaapi_total_adapter_count = 0; +#ifdef POSIX_THREADS +pthread_mutex_t _hbaapi_AL_mutex = PTHREAD_MUTEX_INITIALIZER; +#elif defined(WIN32) +CRITICAL_SECTION _hbaapi_AL_mutex; +#endif + +/* + * Call back registration + */ +typedef struct hba_vendorcallback_elem { + struct hba_vendorcallback_elem + *next; + HBA_CALLBACKHANDLE vendorcbhandle; + HBA_LIBRARY_INFO *lib_info; +} HBA_VENDORCALLBACK_ELEM; + +/* + * Each instance of HBA_ADAPTERCALLBACK_ELEM represents a call to one of + * "register" functions that apply to a particular adapter. + * HBA_ALLADAPTERSCALLBACK_ELEM is used just for HBA_RegisterForAdapterAddEvents + */ +typedef struct hba_adaptercallback_elem { + struct hba_adaptercallback_elem + *next; + HBA_LIBRARY_INFO *lib_info; + void *userdata; + HBA_CALLBACKHANDLE vendorcbhandle; + void (*callback)(); +} HBA_ADAPTERCALLBACK_ELEM; + +typedef struct hba_alladapterscallback_elem { + struct hba_alladapterscallback_elem + *next; + void *userdata; + HBA_VENDORCALLBACK_ELEM *vendorhandlelist; + void (*callback)(); +} HBA_ALLADAPTERSCALLBACK_ELEM; + +HBA_ALLADAPTERSCALLBACK_ELEM *_hbaapi_adapteraddevents_callback_list = NULL; +HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterevents_callback_list = NULL; +HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterportevents_callback_list = NULL; +HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterportstatevents_callback_list = NULL; +HBA_ADAPTERCALLBACK_ELEM *_hbaapi_targetevents_callback_list = NULL; +HBA_ADAPTERCALLBACK_ELEM *_hbaapi_linkevents_callback_list = NULL; +HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterdeviceevents_callback_list = NULL; +#ifdef POSIX_THREADS +/* mutex's to protect each list */ +pthread_mutex_t _hbaapi_AAE_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t _hbaapi_AE_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t _hbaapi_APE_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t _hbaapi_APSE_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t _hbaapi_TE_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t _hbaapi_LE_mutex = PTHREAD_MUTEX_INITIALIZER; +#elif defined(WIN32) +CRITICAL_SECTION _hbaapi_AAE_mutex; +CRITICAL_SECTION _hbaapi_AE_mutex; +CRITICAL_SECTION _hbaapi_APE_mutex; +CRITICAL_SECTION _hbaapi_APSE_mutex; +CRITICAL_SECTION _hbaapi_TE_mutex; +CRITICAL_SECTION _hbaapi_LE_mutex; +#endif + +HBA_ADAPTERCALLBACK_ELEM **cb_lists_array[] = { + &_hbaapi_adapterevents_callback_list, + &_hbaapi_adapterportevents_callback_list, + &_hbaapi_adapterportstatevents_callback_list, + &_hbaapi_targetevents_callback_list, + &_hbaapi_linkevents_callback_list, + &_hbaapi_adapterdeviceevents_callback_list, + NULL}; + +/* + * Common library internal. Mutex handling + */ +#ifdef POSIX_THREADS +static void +grab_mutex(pthread_mutex_t *mp) { + int ret; + if((ret = pthread_mutex_lock(mp)) != 0) { + perror("pthread_mutex_lock - HBAAPI:"); + DEBUG(0, "pthread_mutex_lock returned %d", ret, 0, 0); + } +} + +static void +release_mutex(pthread_mutex_t *mp) { + int ret; + if((ret = pthread_mutex_unlock(mp)) != 0) { + perror("pthread_mutex_unlock - HBAAPI:"); + DEBUG(0, "pthread_mutex_unlock returned %d", ret, 0, 0); + } +} +#endif + +/* + * Common library internal. Check library and return vendorhandle + */ +static HBA_STATUS +HBA_CheckLibrary(HBA_HANDLE handle, + HBA_LIBRARY_INFO **lib_infopp, + HBA_HANDLE *vendorhandle) { + + HBA_UINT32 libraryIndex; + HBA_LIBRARY_INFO *lib_infop; + + if (vendorhandle == NULL) { + return(HBA_STATUS_ERROR_ARG); + } + if(_hbaapi_librarylist == NULL) { + return(HBA_STATUS_ERROR); + } + libraryIndex = LIBRARY_NUM(handle); + + GRAB_MUTEX(&_hbaapi_LL_mutex); + for(lib_infop = _hbaapi_librarylist; + lib_infop != NULL; + lib_infop = lib_infop->next) { + if(lib_infop->index == libraryIndex) { + if(lib_infop->status != HBA_LIBRARY_LOADED) { + return HBA_STATUS_ERROR; + } + *lib_infopp = lib_infop; + *vendorhandle = VENDOR_HANDLE(handle); + /* caller will release the mutex */ + return HBA_STATUS_OK; + } + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INVALID_HANDLE); +} +#define CHECKLIBRARY() \ + status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);\ + if(status != HBA_STATUS_OK) { \ + return(status); \ + } + +/* + *freevendorhandlelist is called with _hbaapi_LL_mutex already held + */ +static void +freevendorhandlelist(HBA_VENDORCALLBACK_ELEM *vhlist) { + HBA_VENDORCALLBACK_ELEM *vhlp; + HBA_VENDORCALLBACK_ELEM *vnext; + HBARemoveCallbackFunc registeredfunc; + + for(vhlp = vhlist; vhlp != NULL; vhlp = vnext) { + vnext = vhlp->next; + registeredfunc = + vhlp->lib_info->functionTable.RemoveCallbackHandler; + if(registeredfunc == NULL) { + continue; + } + (registeredfunc)(vhlp->vendorcbhandle); + free(vhlp); + } +} + +static +HBA_STATUS +local_remove_callback(HBA_CALLBACKHANDLE cbhandle) { + HBA_ADAPTERCALLBACK_ELEM ***listp; + HBA_ADAPTERCALLBACK_ELEM **lastp; + HBA_ALLADAPTERSCALLBACK_ELEM **lap; + HBA_ALLADAPTERSCALLBACK_ELEM *allcbp; + HBA_ADAPTERCALLBACK_ELEM *cbp; + HBARemoveCallbackFunc registeredfunc; + HBA_VENDORCALLBACK_ELEM *vhlp; + HBA_VENDORCALLBACK_ELEM *vnext; + int found; + HBA_STATUS status = HBA_STATUS_ERROR_INVALID_HANDLE; + + + /* search through the simple lists first */ + GRAB_MUTEX(&_hbaapi_AAE_mutex); + GRAB_MUTEX(&_hbaapi_AE_mutex); + GRAB_MUTEX(&_hbaapi_APE_mutex); + GRAB_MUTEX(&_hbaapi_APSE_mutex); + GRAB_MUTEX(&_hbaapi_TE_mutex); + GRAB_MUTEX(&_hbaapi_LE_mutex); + for(listp = cb_lists_array, found = 0; found == 0, *listp != NULL; listp++) { + lastp = *listp; + for(cbp=**listp; cbp != NULL; cbp = cbp->next) { + if(cbhandle != (HBA_CALLBACKHANDLE)cbp) { + lastp = &(cbp->next); + continue; + } + found = 1; + registeredfunc = cbp->lib_info->functionTable.RemoveCallbackHandler; + if(registeredfunc == NULL) { + break; + } + (registeredfunc)(cbp->vendorcbhandle); + *lastp = cbp->next; + free(cbp); + break; + } + } + RELEASE_MUTEX(&_hbaapi_LE_mutex); + RELEASE_MUTEX(&_hbaapi_TE_mutex); + RELEASE_MUTEX(&_hbaapi_APSE_mutex); + RELEASE_MUTEX(&_hbaapi_APE_mutex); + RELEASE_MUTEX(&_hbaapi_AE_mutex); + RELEASE_MUTEX(&_hbaapi_AAE_mutex); + if(found != 0) { + if(registeredfunc == NULL) { + return HBA_STATUS_ERROR_NOT_SUPPORTED; + } + return HBA_STATUS_OK; + } + + GRAB_MUTEX(&_hbaapi_AAE_mutex); + /* if it wasnt in the simple lists, look in the list for adapteraddevents */ + lap = &_hbaapi_adapteraddevents_callback_list; + for(allcbp = _hbaapi_adapteraddevents_callback_list; + allcbp != NULL; + allcbp = allcbp->next) { + if(cbhandle != (HBA_CALLBACKHANDLE)allcbp) { + lap = &allcbp->next; + continue; + } + for(vhlp = allcbp->vendorhandlelist; vhlp != NULL; vhlp = vnext) { + vnext = vhlp->next; + registeredfunc = + vhlp->lib_info->functionTable.RemoveCallbackHandler; + if(registeredfunc == NULL) { + continue; + } + (registeredfunc)(vhlp->vendorcbhandle); + free(vhlp); + } + *lap = allcbp->next; + free(allcbp); + status = HBA_STATUS_OK; + break; + } + RELEASE_MUTEX(&_hbaapi_AAE_mutex); + return(status); +} + +static char wwn_str1[17]; +static char wwn_str2[17]; +static char wwn_str3[17]; +#define WWN2STR1(wwn) WWN2str(wwn_str1, (wwn)) +#define WWN2STR2(wwn) WWN2str(wwn_str2, (wwn)) +#define WWN2STR3(wwn) WWN2str(wwn_str3, (wwn)) +static char * +WWN2str(char *buf, HBA_WWN *wwn) { + int j; + unsigned char *pc = (unsigned char *)&(wwn->wwn[0]); + buf[0] = '\0'; + for (j=0; j<16; j+=2) { + sprintf(&buf[j], "%02X", (int)*pc++); + } + return(buf); +} + + +#ifdef WIN32 +BOOL APIENTRY +DllMain( HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + break; + case DLL_PROCESS_DETACH: + break; + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + } + return TRUE; +} +#endif + +/* + * Read in the config file and load all the specified vendor specific + * libraries and perform the function registration exercise + */ +HBA_STATUS +HBA_LoadLibrary(void) { + HBARegisterLibraryFunc + RegisterFunc; + HBARegisterLibraryV2Func + RegisterV2Func; + HBALoadLibraryFunc LoadLibraryFunc; + HBAGetVersionFunc GetVersionFunc; +#ifdef POSIX_THREADS + int ret; +#endif + HBA_STATUS status; + HBA_UINT32 libversion; + + /* Open configuration file from known location */ +#ifdef WIN32 + LONG lStatus; + HKEY hkSniaHba, hkVendorLib; + FILETIME ftLastWriteTime; + TCHAR cSubKeyName[256]; + DWORD i, dwSize, dwType; + BYTE byFileName[MAX_PATH]; + HBA_LIBRARY_INFO *lib_infop; + + if(_hbaapi_librarylist != NULL) { + /* this is an app programming error */ + return HBA_STATUS_ERROR; + } + + lStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\SNIA\\HBA", + 0, KEY_READ, &hkSniaHba); + if (lStatus != ERROR_SUCCESS) { + /* ???Opportunity to send error msg, configuration error */ + return HBA_STATUS_ERROR; + } + /* + * Enumerate all the subkeys. These have the form: + * HKLM\Software\SNIA\HBA\<Vendor id> - note that we don't care + * what the vendor id is + */ + for (i = 0; ; i++) { + dwSize = 255; /* how big the buffer is */ + lStatus = RegEnumKeyEx(hkSniaHba, i, + (char *)&cSubKeyName, &dwSize, NULL, + NULL, NULL, &ftLastWriteTime); + if (lStatus == ERROR_NO_MORE_ITEMS) { + break; /* we're done */ + } else if (lStatus == ERROR_MORE_DATA) { /* buffer not big enough */ + /* do whatever */ + ; + } + /* Now open the subkey that pertains to this vendor's library */ + lStatus = RegOpenKeyEx(hkSniaHba, cSubKeyName, 0, KEY_READ, + &hkVendorLib); + if (lStatus != ERROR_SUCCESS) { + RegCloseKey(hkSniaHba); + /* ???Opportunity to send error msg, installation error */ + return HBA_STATUS_ERROR; /* you may want to return something + * else or keep trying */ + } + /* The name of the library is contained in a REG_SZ Value + * keyed to "LibraryFile" */ + dwSize = MAX_PATH; + lStatus = RegQueryValueEx(hkVendorLib, "LibraryFile", NULL, &dwType, + byFileName, &dwSize); + if (lStatus != ERROR_SUCCESS) { + RegCloseKey(hkVendorLib); + /* ???Opportunity to send error msg, installation error */ + continue; + } + lib_infop = (HBA_LIBRARY_INFO *)calloc(1, sizeof(HBA_LIBRARY_INFO)); + if(lib_infop == NULL) { + /* what is the right thing to do in MS land??? */ + RegCloseKey(hkVendorLib); + /* ???Opportunity to send error msg, installation error */ + return(HBA_STATUS_ERROR); + } + lib_infop->status = HBA_LIBRARY_NOT_LOADED; + lib_infop->next = _hbaapi_librarylist; + lib_infop->index = _hbaapi_total_library_count; + _hbaapi_total_library_count++; + _hbaapi_librarylist = lib_infop; + + /* Now I can try to load the library */ + lib_infop->hLibrary = LoadLibrary(byFileName); + if (lib_infop->hLibrary == NULL){ + /* printf("unable to load library %s\n", librarypath); */ + /* ???Opportunity to send error msg, installation error */ + goto dud_library; + } + lib_infop->LibraryPath = strdup(byFileName); + DEBUG(1, "HBAAPI loading: %s\n", byFileName, 0, 0); + + /* Call the registration function to get the list of pointers */ + RegisterV2Func = (HBARegisterLibraryV2Func) + GetProcAddress(lib_infop->hLibrary, "HBA_RegisterLibraryV2"); + if (RegisterV2Func != NULL) { + /* Load the function pointers directly into + * the table of functions */ + status = ((RegisterV2Func)(&lib_infop->functionTable)); + if (status != HBA_STATUS_OK) { + /* library not loaded */ + /* ???Opportunity to send error msg, library error? */ + goto dud_library; + } + } else { + /* Maybe the vendor library is only Rev1 */ + RegisterFunc = (HBARegisterLibraryFunc) + GetProcAddress(lib_infop->hLibrary, "HBA_RegisterLibrary"); + if(RegisterFunc == NULL) { + /* ???Opportunity to send error msg, library error? */ + goto dud_library; + } + /* Load the function points directly into + * the Rev 2 table of functions */ + status = ((RegisterFunc)( + (HBA_ENTRYPOINTS *)(&lib_infop->functionTable))); + if (status != HBA_STATUS_OK) { + /* library not loaded */ + /* ???Opportunity to send error msg, library error? */ + goto dud_library; + } + } + + /* successfully loaded library */ + GetVersionFunc = lib_infop->functionTable.GetVersionHandler; + if (GetVersionFunc == NULL) { + /* ???Opportunity to send error msg, library error? */ + goto dud_library; + } + /* Check the version of this library before loading */ + /* Actually... This wrapper is compatible with version 1 */ + libversion = ((GetVersionFunc)()); +#ifdef NOTDEF /* save for a later time... when it matters */ + if (libversion < HBA_LIBVERSION) { + goto dud_library; + } +#endif + LoadLibraryFunc = lib_infop->functionTable.LoadLibraryHandler; + if (LoadLibraryFunc == NULL) { + /* Hmmm, dont we need to flag this in a realy big way??? */ + /* How about messages to the system event logger ??? */ + /* ???Opportunity to send error msg, library error? */ + goto dud_library; + } + /* Initialize this library */ + status = ((LoadLibraryFunc)()); + if (status != HBA_STATUS_OK) { + /* ???Opportunity to send error msg, library error? */ + continue; + } + /* successfully loaded library */ + lib_infop->status = HBA_LIBRARY_LOADED; + + dud_library: /* its also just the end of the loop */ + RegCloseKey(hkVendorLib); + } + RegCloseKey(hkSniaHba); + +#else /* Unix as opposed to Win32 */ + FILE *hbaconf; + char fullline[512]; /* line read from HBA.conf */ + char *libraryname; /* Read in from file HBA.conf */ + char *librarypath; /* Read in from file HBA.conf */ + char hbaConfFilePath[256]; + char *charPtr; + HBA_LIBRARY_INFO *lib_infop; + + if(_hbaapi_librarylist != NULL) { + fprintf(stderr, + "HBA_LoadLibrary: previously unfreed " + "libraries exist, call HBA_FreeLibrary().\n"); + return HBA_STATUS_ERROR; + } + + strcpy(hbaConfFilePath, "/etc/hba.conf"); + + if ((hbaconf = fopen(hbaConfFilePath, "r")) == NULL) { + printf("Cannot open %s\n", hbaConfFilePath); + return HBA_STATUS_ERROR; + } + + /* Read in each line and load library */ + while ((hbaconf != NULL) && (fgets(fullline, sizeof(fullline), hbaconf))) { + /* Skip the comments... */ + if ((fullline[0] == '#') || (fullline[0] == '\n')) { + continue; + } + + /* grab first 'thing' in line (if its there)*/ + if((libraryname = strtok(fullline, " \t\n")) != NULL) { + if(strlen(libraryname) >= 64) { + fprintf(stderr, "Library name(%s) in %s is > 64 characters\n", + libraryname, hbaConfFilePath); + } + } + /* grab second 'thing' in line (if its there)*/ + if((librarypath = strtok(NULL, " \t\n")) != NULL) { + if(strlen(librarypath) >= 256) { + fprintf(stderr, "Library path(%s) in %s is > 256 characters\n", + librarypath, hbaConfFilePath); + } + } + + /* there should be no more 'things' in the line */ + if((charPtr = strtok(NULL, " \n\t")) != NULL) { + fprintf(stderr, "Extraneous characters (\"%s\") in %s\n", + charPtr, hbaConfFilePath); + } + + /* Continue to the next line if library name or path is invalid */ + if (libraryname == NULL || + strlen(libraryname) == 0 || + librarypath == NULL || + (strlen(librarypath) == 0)) { + continue; + } + /* + * Special case.... + * Look for loglevel + */ + if(strcmp(libraryname, "debuglevel") == 0) { + _hbaapi_debuglevel = strtol(librarypath, NULL, 10); + /* error handling does the right thing automagically */ + continue; + } + + lib_infop = (HBA_LIBRARY_INFO *)calloc(1, sizeof(HBA_LIBRARY_INFO)); + if(lib_infop == NULL) { + fprintf(stderr, "HBA_LoadLibrary: out of memeory\n"); + return(HBA_STATUS_ERROR); + } + lib_infop->status = HBA_LIBRARY_NOT_LOADED; + lib_infop->LibraryName = strdup(libraryname); + lib_infop->LibraryPath = strdup(librarypath); + lib_infop->index = _hbaapi_total_library_count; + _hbaapi_total_library_count++; + lib_infop->next = _hbaapi_librarylist; + _hbaapi_librarylist = lib_infop; + + /* Load the DLL now */ + if((lib_infop->hLibrary = dlopen(librarypath,RTLD_LAZY)) == NULL) { + /*printf("unable to load library %s\n", librarypath); */ + continue; + } + /* Call the registration function to get the list of pointers */ + RegisterV2Func = (HBARegisterLibraryV2Func) + dlsym(lib_infop->hLibrary, "HBA_RegisterLibraryV2"); + if (RegisterV2Func != NULL) { + /* Load the function points directly into + * the table of functions */ + status = ((RegisterV2Func)(&lib_infop->functionTable)); + if (status != HBA_STATUS_OK) { + /* library not loaded */ + continue; + } + } else { + /* Maybe the vendor library is only Rev1 */ + RegisterFunc = (HBARegisterLibraryFunc) + dlsym(lib_infop->hLibrary, "HBA_RegisterLibrary"); + if(RegisterFunc == NULL) { + /* This function is required */ + fprintf(stderr, + "HBA_LoadLibrary: vendor specific RegisterLibrary " + "function not found. lib: %s\n", librarypath); + DEBUG(0, "HBA_LoadLibrary: vendor specific RegisterLibrary " + "function not found. lib: %s\n", librarypath, 0, 0); + continue; + } + /* Load the function points directly into + * the table of functions */ + status = ((RegisterFunc) + ((HBA_ENTRYPOINTS *)(&lib_infop->functionTable))); + if (status != HBA_STATUS_OK) { + /* library not loaded */ + fprintf(stderr, + "HBA_LoadLibrary: vendor specific RegisterLibrary " + "function encountered an error. lib: %s\n", librarypath); + DEBUG(0, "HBA_LoadLibrary: vendor specific RegisterLibrary " + "function encountered an error. lib: %s\n", librarypath, 0, 0); + continue; + } + } + + /* successfully loaded library */ + if((GetVersionFunc = lib_infop->functionTable.GetVersionHandler) + == NULL) { + continue; + } + libversion = ((GetVersionFunc)()); + /* Check the version of this library before loading */ + /* Actually... This wrapper is compatible with version 1 */ +#ifdef NOTDEF /* save for a later time... when it matters */ + if(libversion < HBA_LIBVERSION) { + printf("Library version mismatch. Got %d expected %d.\n", + libversion, HBA_LIBVERSION); + continue; + } +#endif + DEBUG(1, "%s libversion = %d", librarypath, libversion, 0); + LoadLibraryFunc = lib_infop->functionTable.LoadLibraryHandler; + if (LoadLibraryFunc == NULL) { + /* this function is required */ + fprintf(stderr, + "HBA_LoadLibrary: vendor specific LoadLibrary " + "function not found. lib: %s\n", librarypath); + DEBUG(0, "HBA_LoadLibrary: vendor specific LoadLibrary " + "function not found. lib: %s\n", librarypath, 0, 0); + continue; + } + /* Initialize this library */ + if((status = ((LoadLibraryFunc)())) != HBA_STATUS_OK) { + /* maybe this should be a printf so that we CANNOT miss it */ + fprintf(stderr, + "HBA_LoadLibrary: Encounterd and error loading: %s", + librarypath); + DEBUG(0, "Encounterd and error loading: %s", librarypath, 0, 0); + DEBUG(0, " HBA_STATUS: %d", status, 0, 0); + continue; + } + /* successfully loaded library */ + lib_infop->status = HBA_LIBRARY_LOADED; + } + + fclose(hbaconf); +#endif /* WIN32 or UNIX */ +#ifdef POSIX_THREADS + ret = pthread_mutex_init(&_hbaapi_LL_mutex, NULL); + if(ret == 0) { + ret = pthread_mutex_init(&_hbaapi_AL_mutex, NULL); + } + if(ret == 0) { + ret = pthread_mutex_init(&_hbaapi_AAE_mutex, NULL); + } + if(ret == 0) { + ret = pthread_mutex_init(&_hbaapi_AE_mutex, NULL); + } + if(ret == 0) { + ret = pthread_mutex_init(&_hbaapi_APE_mutex, NULL); + } + if(ret == 0) { + ret = pthread_mutex_init(&_hbaapi_APSE_mutex, NULL); + } + if(ret == 0) { + ret = pthread_mutex_init(&_hbaapi_TE_mutex, NULL); + } + if(ret == 0) { + ret = pthread_mutex_init(&_hbaapi_LE_mutex, NULL); + } + if(ret != 0) { + perror("pthread_mutec_init - HBA_LoadLibrary"); + return(HBA_STATUS_ERROR); + } +#elif defined(WIN32) + InitializeCriticalSection(&_hbaapi_LL_mutex); + InitializeCriticalSection(&_hbaapi_AL_mutex); + InitializeCriticalSection(&_hbaapi_AAE_mutex); + InitializeCriticalSection(&_hbaapi_AE_mutex); + InitializeCriticalSection(&_hbaapi_APE_mutex); + InitializeCriticalSection(&_hbaapi_APSE_mutex); + InitializeCriticalSection(&_hbaapi_TE_mutex); + InitializeCriticalSection(&_hbaapi_LE_mutex); +#endif + + + return HBA_STATUS_OK; +} + +HBA_STATUS +HBA_FreeLibrary(void) { + HBAFreeLibraryFunc FreeLibraryFunc; + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_LIBRARY_INFO *lib_next; + HBA_ADAPTERCALLBACK_ELEM + ***listp; + HBA_ADAPTER_INFO *adapt_infop; + HBA_ADAPTER_INFO *adapt_next; + + ARE_WE_INITED(); + GRAB_MUTEX(&_hbaapi_LL_mutex); + GRAB_MUTEX(&_hbaapi_AL_mutex); + + DEBUG(1, "HBA_FreeLibrary()", 0, 0, 0); + for(lib_infop = _hbaapi_librarylist; lib_infop != NULL; lib_infop = lib_next) { + lib_next = lib_infop->next; + if (lib_infop->status == HBA_LIBRARY_LOADED) { + FreeLibraryFunc = lib_infop->functionTable.FreeLibraryHandler; + if (FreeLibraryFunc != NULL) { + /* Free this library */ + status = ((FreeLibraryFunc)()); + } +#ifdef WIN32 + FreeLibrary(lib_infop->hLibrary); /* Unload DLL from memory */ +#else + dlclose(lib_infop->hLibrary); /* Unload DLL from memory */ +#endif + } +#ifndef WIN32 + free(lib_infop->LibraryName); +#endif + free(lib_infop->LibraryPath); + free(lib_infop); + + } + _hbaapi_librarylist = NULL; + /* OK, now all functions are disabled except for LoadLibrary, + * Hope no other thread calls it before we have returned */ + _hbaapi_total_library_count = 0; + + for(adapt_infop = _hbaapi_adapterlist; + adapt_infop != NULL; + adapt_infop = adapt_next) { + adapt_next = adapt_infop->next; + free(adapt_infop->name); + free(adapt_infop); + } + _hbaapi_adapterlist = NULL; + _hbaapi_total_adapter_count = 0; + + /* Free up the callbacks, this is not the most efficient, but it works */ + while((volatile HBA_ADAPTERCALLBACK_ELEM *) + _hbaapi_adapteraddevents_callback_list + != NULL) { + local_remove_callback((HBA_CALLBACKHANDLE) + _hbaapi_adapteraddevents_callback_list); + } + for(listp = cb_lists_array; *listp != NULL; listp++) { + while((volatile HBA_ADAPTERCALLBACK_ELEM ***)**listp != NULL) { + local_remove_callback((HBA_CALLBACKHANDLE)**listp); + } + } + + RELEASE_MUTEX(&_hbaapi_AL_mutex); + RELEASE_MUTEX(&_hbaapi_LL_mutex); + +#ifdef USESYSLOG + closelog(); +#endif +#ifdef USELOGFILE + if(_hbaapi_debug_fd != NULL) { + fclose(_hbaapi_debug_fd); + } + _hbaapi_debug_fd = NULL; +#endif +#ifdef POSIX_THREADS + /* this will unlock them as well, but who cares */ + pthread_mutex_destroy(&_hbaapi_LE_mutex); + pthread_mutex_destroy(&_hbaapi_TE_mutex); + pthread_mutex_destroy(&_hbaapi_APSE_mutex); + pthread_mutex_destroy(&_hbaapi_APE_mutex); + pthread_mutex_destroy(&_hbaapi_AE_mutex); + pthread_mutex_destroy(&_hbaapi_AAE_mutex); + pthread_mutex_destroy(&_hbaapi_AL_mutex); + pthread_mutex_destroy(&_hbaapi_LL_mutex); +#elif defined(WIN32) + DeleteCriticalSection(&_hbaapi_LL_mutex); + DeleteCriticalSection(&_hbaapi_AL_mutex); + DeleteCriticalSection(&_hbaapi_AAE_mutex); + DeleteCriticalSection(&_hbaapi_AE_mutex); + DeleteCriticalSection(&_hbaapi_APE_mutex); + DeleteCriticalSection(&_hbaapi_APSE_mutex); + DeleteCriticalSection(&_hbaapi_TE_mutex); + DeleteCriticalSection(&_hbaapi_LE_mutex); +#endif + + return HBA_STATUS_OK; +} + +/* + * The API used to use fixed size tables as its primary data structure. + * Indexing from 1 to N identified each adapters. Now the adapters are + * on a linked list. There is a unique "index" foreach each adapter. + * Adapters always keep their index, even if they are removed from the + * hardware. The only time the indexing is reset is on HBA_FreeLibrary + */ +HBA_UINT32 +HBA_GetNumberOfAdapters(void) { + int j=0; + HBA_LIBRARY_INFO *lib_infop; + HBAGetNumberOfAdaptersFunc + GetNumberOfAdaptersFunc; + HBAGetAdapterNameFunc + GetAdapterNameFunc; + HBA_BOOLEAN found_name; + HBA_ADAPTER_INFO *adapt_infop; + HBA_STATUS status; + + char adaptername[256]; + int num_adapters; /* local */ + + if(_hbaapi_librarylist == NULL) { + return (0); + } + GRAB_MUTEX(&_hbaapi_LL_mutex); /* pay attention to order */ + GRAB_MUTEX(&_hbaapi_AL_mutex); + + for (lib_infop = _hbaapi_librarylist; + lib_infop != NULL; + lib_infop = lib_infop->next) { + + if (lib_infop->status != HBA_LIBRARY_LOADED) { + continue; + } + + GetNumberOfAdaptersFunc = + lib_infop->functionTable.GetNumberOfAdaptersHandler; + if (GetNumberOfAdaptersFunc == NULL) { + continue; + } + num_adapters = ((GetNumberOfAdaptersFunc)()); +#ifndef WIN32 + DEBUG(1, "HBAAPI: num_adapters for %s = %d\n", + lib_infop->LibraryName, num_adapters, 0); +#else + DEBUG(1, "HBAAPI: num_adapters for %s = %d\n", + lib_infop->LibraryPath, num_adapters, 0); +#endif + + /* Also get the names of all the adapters here and cache */ + GetAdapterNameFunc = lib_infop->functionTable.GetAdapterNameHandler; + if(GetAdapterNameFunc == NULL) { + continue; + } + + for (j = 0; j < num_adapters; j++) { + found_name = 0; + status = (GetAdapterNameFunc)(j, (char *)&adaptername); + if(status == HBA_STATUS_OK) { + for(adapt_infop = _hbaapi_adapterlist; + adapt_infop != NULL; + adapt_infop = adapt_infop->next) { + /* + * check for duplicates, really, this may just be a second + * call to this function + * ??? how do we know when a name becomes stale? + */ + if(strcmp(adaptername, adapt_infop->name) == 0) { + /* already got this one */ + found_name++; + break; + } + } + if(found_name != 0) { + continue; + } + } + + adapt_infop = (HBA_ADAPTER_INFO *) + calloc(1, sizeof(HBA_ADAPTER_INFO)); + if(adapt_infop == NULL) { +#ifndef WIN32 + fprintf(stderr, + "HBA_GetNumberOfAdapters: calloc failed on sizeof:%d\n", + sizeof(HBA_ADAPTER_INFO)); +#endif + RELEASE_MUTEX(&_hbaapi_AL_mutex); + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, + _hbaapi_total_adapter_count); + } + if((adapt_infop->GNstatus = status) == HBA_STATUS_OK) { + adapt_infop->name = strdup(adaptername); + } else { + char dummyname[512]; + sprintf(dummyname, "NULLADAPTER-%s-%03d", + lib_infop->LibraryPath, _hbaapi_total_adapter_count); + dummyname[255] = '\0'; + adapt_infop->name = strdup(dummyname); + } + adapt_infop->library = lib_infop; + adapt_infop->next = _hbaapi_adapterlist; + adapt_infop->index = _hbaapi_total_adapter_count; + _hbaapi_adapterlist = adapt_infop; + _hbaapi_total_adapter_count++; + } + } + RELEASE_MUTEX(&_hbaapi_AL_mutex); + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, _hbaapi_total_adapter_count); +} + +HBA_STATUS +HBA_GetAdapterName( + HBA_UINT32 adapterindex, + char *adaptername) +{ + HBA_ADAPTER_INFO *adapt_infop; + HBA_STATUS ret = HBA_STATUS_ERROR_ILLEGAL_INDEX; + + if (adaptername == NULL) { + return(HBA_STATUS_ERROR_ARG); + } + /* + * The adapter index is from old code, but we have + * to support it. Go down the list looking for + * the adapter + */ + ARE_WE_INITED(); + GRAB_MUTEX(&_hbaapi_AL_mutex); + *adaptername = '\0'; + for(adapt_infop = _hbaapi_adapterlist; + adapt_infop != NULL; + adapt_infop = adapt_infop->next) { + + if(adapt_infop->index == adapterindex) { + if(adapt_infop->name != NULL && + adapt_infop->GNstatus == HBA_STATUS_OK) { + strcpy(adaptername, adapt_infop->name); + } else { + *adaptername = '\0'; + } + ret = adapt_infop->GNstatus; + break; + } + } + DEBUG(2, "GetAdapterName for index:%d ->%s", adapterindex, adaptername, 0); + RELEASE_MUTEX_RETURN(&_hbaapi_AL_mutex, ret); +} + +HBA_HANDLE +HBA_OpenAdapter(char* adaptername) { + HBA_HANDLE handle; + HBAOpenAdapterFunc OpenAdapterFunc; + HBA_ADAPTER_INFO *adapt_infop; + HBA_LIBRARY_INFO *lib_infop; + + DEBUG(2, "OpenAdapter: %s", adaptername, 0, 0); + + if(_hbaapi_librarylist == NULL) { + return(HBA_HANDLE_INVALID); + } + if (adaptername == NULL) { + return(HBA_STATUS_ERROR_ARG); + } + handle = HBA_HANDLE_INVALID; + GRAB_MUTEX(&_hbaapi_AL_mutex); + for(adapt_infop = _hbaapi_adapterlist; + adapt_infop != NULL; + adapt_infop = adapt_infop->next) { + if (strcmp(adaptername, adapt_infop->name) != 0) { + continue; + } + lib_infop = adapt_infop->library; + OpenAdapterFunc = + lib_infop->functionTable.OpenAdapterHandler; + if (OpenAdapterFunc != NULL) { + /* retrieve the vendor handle */ + handle = (OpenAdapterFunc)(adaptername); + if(handle != 0) { + /* or this with the library index to get the common handle */ + handle = HBA_HANDLE_FROM_LOCAL(lib_infop->index, handle); + } + } + break; + } + RELEASE_MUTEX_RETURN(&_hbaapi_AL_mutex, handle); +} +/* + * This function ignores the list of known adapters and instead tries + * each vendors open function to see if one of them + * can open an adapter when referenced with a particular WWN + */ +HBA_STATUS +HBA_OpenAdapterByWWN(HBA_HANDLE *phandle, HBA_WWN nodeWWN) { + HBA_HANDLE handle; + HBA_LIBRARY_INFO *lib_infop; + HBAGetNumberOfAdaptersFunc + GetNumberOfAdaptersFunc; + HBAOpenAdapterByWWNFunc + OpenAdapterFunc; + HBA_STATUS status; + + DEBUG(2, "OpenAdapterByWWN: %s", WWN2STR1(&nodeWWN), 0, 0); + + if (phandle == NULL) { + return(HBA_STATUS_ERROR_ARG); + } + + ARE_WE_INITED(); + + *phandle = HBA_HANDLE_INVALID; + + GRAB_MUTEX(&_hbaapi_LL_mutex); + for (lib_infop = _hbaapi_librarylist; + lib_infop != NULL; + lib_infop = lib_infop->next) { + + status = HBA_STATUS_ERROR_ILLEGAL_WWN; + + if (lib_infop->status != HBA_LIBRARY_LOADED) { + continue; + } + + GetNumberOfAdaptersFunc = + lib_infop->functionTable.GetNumberOfAdaptersHandler; + if (GetNumberOfAdaptersFunc == NULL) { + continue; + } + + /* look for new hardware */ + (void) ((GetNumberOfAdaptersFunc)()); + + OpenAdapterFunc = lib_infop->functionTable.OpenAdapterByWWNHandler; + if (OpenAdapterFunc == NULL) { + continue; + } + /* + * We do not know if the WWN is known by this vendor, + * just try it + */ + if((status = (OpenAdapterFunc)(&handle, nodeWWN)) != HBA_STATUS_OK) { + continue; + } + /* OK, make a vendor non-specific handle */ + *phandle = HBA_HANDLE_FROM_LOCAL(lib_infop->index, handle); + status = HBA_STATUS_OK; + break; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +void +HBA_RefreshAdapterConfiguration() { + DEBUG(2, "HBA_RefreshAdapterConfiguration", 0, 0, 0); + (void)HBA_GetNumberOfAdapters(); + return; +} + +HBA_UINT32 +HBA_GetVersion() { + DEBUG(2, "HBA_GetVersion", 0, 0, 0); + return HBA_LIBVERSION; +} + +/* + * This function is VERY OS dependent. Wing it as best you can. + */ +HBA_UINT32 +HBA_GetWrapperLibraryAttributes ( + HBA_LIBRARYATTRIBUTES *attributes) +{ + + DEBUG(2, "HBA_GetWrapperLibraryAttributes", 0, 0, 0); + + if (attributes == NULL) { + return(HBA_STATUS_ERROR_ARG); + } + + memset(attributes, 0, sizeof(HBA_LIBRARYATTRIBUTES)); + +#if defined(SOLARIS) + if((handle = dlopen("libHBAAPI.so", RTLD_NOW)) != NULL) { + if(dlinfo(handle, RTLD_DI_LINKMAP, &map) >= 0) { + for(mp = map; mp != NULL; mp = mp->l_next) { + if(strlen(map->l_name) < 256) { + strcpy(attributes->LibPath, map->l_lname); + } + } + } + } +#elif defined(WIN32) + { + HMODULE module; + + /* No need to do anything with the module handle */ + /* It wasn't alloocated so it doesn't need to be freed */ + module = GetModuleHandle("HBAAPI"); + if ( module != NULL ) { + if ( GetModuleFileName(module, attributes->LibPath, + sizeof(attributes->LibPath)) == 0 ) { + attributes->LibPath[0] = '\0'; + } + } + } +#endif +#if defined(VENDOR) + strcpy(attributes->VName, VENDOR); +#else + attributes->VName[0] = '\0'; +#endif +#if defined(VERSION) + strcpy(attributes->VVersion, VERSION); +#else + attributes->VVersion[0] = '\0'; +#endif +#if defined(BUILD_DATE) +#if defined(WIN32) + { + int matchCount; + matchCount = sscanf(BUILD_DATE, "%u/%u/%u %u:%u:%u", + &attributes->build_date.tm_year, + &attributes->build_date.tm_mon, + &attributes->build_date.tm_mday, + &attributes->build_date.tm_hour, + &attributes->build_date.tm_min, + &attributes->build_date.tm_sec + ); + + if ( matchCount != 6 ) { + memset(&attributes->build_date, 0, sizeof(struct tm)); + } else { + attributes->build_date.tm_year -= 1900; + attributes->build_date.tm_isdst = -1; + } + + } +#else + if(strptime(BUILD_DATE, "%Y/%m/%d %T %Z", &(attributes->build_date)) == NULL) { + memset(&attributes->build_date, 0, sizeof(struct tm)); + } +#endif +#else + memset(&attributes->build_date, 0, sizeof(struct tm)); +#endif + return 2; +} + +/* + * Callback registation and handling + */ +HBA_STATUS +HBA_RemoveCallback (HBA_CALLBACKHANDLE cbhandle) { + HBA_STATUS status; + + DEBUG(2, "HBA_RemoveCallback", 0, 0, 0); + ARE_WE_INITED(); + + GRAB_MUTEX(&_hbaapi_LL_mutex); + status = local_remove_callback(cbhandle); + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +/* Adapter Add Events *********************************************************/ +static void +adapteraddevents_callback (void *data, HBA_WWN PortWWN, HBA_UINT32 eventType) { + HBA_ALLADAPTERSCALLBACK_ELEM *cbp; + + DEBUG(3, "AddAdapterEvent, port:%s", WWN2STR1(&PortWWN), 0, 0); + + GRAB_MUTEX(&_hbaapi_AAE_mutex); + for(cbp = _hbaapi_adapteraddevents_callback_list; + cbp != NULL; + cbp = cbp->next) { + (*cbp->callback)(data, PortWWN, HBA_EVENT_ADAPTER_ADD); + } + RELEASE_MUTEX(&_hbaapi_AAE_mutex); + +} +HBA_STATUS +HBA_RegisterForAdapterAddEvents ( + void (*callback) ( + void *data, + HBA_WWN PortWWN, + HBA_UINT32 eventType + ), + void *userData, + HBA_CALLBACKHANDLE *callbackHandle) { + + HBA_ALLADAPTERSCALLBACK_ELEM *cbp; + HBA_VENDORCALLBACK_ELEM *vcbp; + HBA_VENDORCALLBACK_ELEM *vendorhandlelist; + HBARegisterForAdapterAddEventsFunc registeredfunc; + HBA_STATUS status = HBA_STATUS_OK; + HBA_STATUS failure = HBA_STATUS_OK; + HBA_LIBRARY_INFO *lib_infop; + int registered_cnt = 0; + int vendor_cnt = 0; + int not_supported_cnt = 0; + int status_OK_bar_cnt = 0; + int status_OK_cnt = 0; + + DEBUG(2, "HBA_RegisterForAdapterAddEvents", 0, 0, 0); + + if (callbackHandle == NULL) { + return(HBA_STATUS_ERROR_ARG); + } + ARE_WE_INITED(); + + cbp = (HBA_ALLADAPTERSCALLBACK_ELEM *) + calloc(1, sizeof(HBA_ALLADAPTERSCALLBACK_ELEM)); + *callbackHandle = (HBA_CALLBACKHANDLE) cbp; + if(cbp == NULL) { +#ifndef WIN32 + fprintf(stderr, + "HBA_RegisterForAdapterAddEvents: calloc failed for %d bytes\n", + sizeof(HBA_ALLADAPTERSCALLBACK_ELEM)); +#endif + return HBA_STATUS_ERROR; + } + + GRAB_MUTEX(&_hbaapi_LL_mutex); + GRAB_MUTEX(&_hbaapi_AAE_mutex); + cbp->callback = callback; + cbp->next = _hbaapi_adapteraddevents_callback_list; + _hbaapi_adapteraddevents_callback_list = cbp; + /* Need to release the mutex now incase the vendor function invokes the + * callback. We will grap the mutex later to attach the vendor handle list + * to the callback structure */ + RELEASE_MUTEX(&_hbaapi_AAE_mutex); + + + /* + * now create a list of vendors (vendor libraryies, NOT ADAPTERS) that have + * successfully registerred + */ + vendorhandlelist = NULL; + for(lib_infop = _hbaapi_librarylist; + lib_infop != NULL; + lib_infop = lib_infop->next) { + + vendor_cnt++; + + registeredfunc = + lib_infop->functionTable.RegisterForAdapterAddEventsHandler; + if(registeredfunc == NULL) { + continue; + } + + vcbp = (HBA_VENDORCALLBACK_ELEM *) + calloc(1, sizeof(HBA_VENDORCALLBACK_ELEM)); + if(vcbp == NULL) { +#ifndef WIN32 + fprintf(stderr, + "HBA_RegisterForAdapterAddEvents: " + "calloc failed for %d bytes\n", + sizeof(HBA_VENDORCALLBACK_ELEM)); +#endif + freevendorhandlelist(vendorhandlelist); + status = HBA_STATUS_ERROR; + break; + } + + registered_cnt++; + status = (registeredfunc)(adapteraddevents_callback, + userData, &vcbp->vendorcbhandle); + if(status == HBA_STATUS_ERROR_NOT_SUPPORTED) { + not_supported_cnt++; + free(vcbp); + continue; + } else if (status != HBA_STATUS_OK) { + status_OK_bar_cnt++; + DEBUG(0, + "HBA_RegisterForAdapterAddEvents: Library->%s, Error->%d", + lib_infop->LibraryPath, status, 0); +#ifndef WIN32 + fprintf(stderr, + "HBA_RegisterForAdapterAddEvents: Library->%s, Error->%d", + lib_infop->LibraryPath, status); +#endif + failure = status; + free(vcbp); + continue; + } else { + status_OK_cnt++; + } + vcbp->lib_info = lib_infop; + vcbp->next = vendorhandlelist; + vendorhandlelist = vcbp; + } + if(registered_cnt == 0) { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + freevendorhandlelist(vendorhandlelist); + local_remove_callback((HBA_CALLBACKHANDLE) cbp); + } else if (status_OK_cnt == 0 && not_supported_cnt != 0) { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } else if (status_OK_cnt == 0) { + /* At least one vendor library registered this function, but no + * vendor call succeeded */ + local_remove_callback((HBA_CALLBACKHANDLE) cbp); + status = failure; + } else { + /* we have had atleast some success, now finish up */ + GRAB_MUTEX(&_hbaapi_AAE_mutex); + /* this seems silly, but what if another thread called + * the callback remove */ + for(cbp = _hbaapi_adapteraddevents_callback_list; + cbp != NULL; cbp = cbp->next) { + if((HBA_CALLBACKHANDLE)cbp == *callbackHandle) { + /* yup, its still there, hooray */ + cbp->vendorhandlelist = vendorhandlelist; + vendorhandlelist = NULL; + break; + } + } + RELEASE_MUTEX(&_hbaapi_AAE_mutex); + if(vendorhandlelist != NULL) { + /* bummer, somebody removed the callback before we finished + * registration, probably will never happen */ + freevendorhandlelist(vendorhandlelist); + DEBUG(0, + "HBA_RegisterForAdapterAddEvents: HBA_RemoveCallback was " + "called for a handle before registration was finished.", + 0, 0, 0); + status = HBA_STATUS_ERROR; + } else { + status = HBA_STATUS_OK; + } + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +/* Adapter Events (other than add) ********************************************/ +static void +adapterevents_callback (void *data, + HBA_WWN PortWWN, + HBA_UINT32 eventType) { + HBA_ADAPTERCALLBACK_ELEM *acbp; + + DEBUG(3, "AdapterEvent, port:%s, eventType:%d", WWN2STR1(&PortWWN), + eventType, 0); + + GRAB_MUTEX(&_hbaapi_AE_mutex); + for(acbp = _hbaapi_adapterevents_callback_list; + acbp != NULL; + acbp = acbp->next) { + if(data == (void *)acbp) { + (*acbp->callback)(acbp->userdata, PortWWN, eventType); + break; + } + } + RELEASE_MUTEX(&_hbaapi_AE_mutex); +} +HBA_STATUS +HBA_RegisterForAdapterEvents ( + void (*callback) ( + void *data, + HBA_WWN PortWWN, + HBA_UINT32 eventType + ), + void *userData, + HBA_HANDLE handle, + HBA_CALLBACKHANDLE *callbackHandle) { + + HBA_ADAPTERCALLBACK_ELEM *acbp; + HBARegisterForAdapterEventsFunc registeredfunc; + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + + DEBUG(2, "HBA_RegisterForAdapterEvents", 0, 0, 0); + + if (callbackHandle == NULL) { + return(HBA_STATUS_ERROR_ARG); + } + + CHECKLIBRARY(); + + /* we now have the _hbaapi_LL_mutex */ + + registeredfunc = lib_infop->functionTable.RegisterForAdapterEventsHandler; + if(registeredfunc == NULL) { + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED); + } + + /* + * that allocated memory is used both as the handle for the + * caller, and as userdata to the vendor call so that on + * callback the specific registration may be recalled + */ + acbp = (HBA_ADAPTERCALLBACK_ELEM *) + calloc(1, sizeof(HBA_ADAPTERCALLBACK_ELEM)); + if(acbp == NULL) { +#ifndef WIN32 + fprintf(stderr, + "HBA_RegisterForAdapterEvents: calloc failed for %d bytes\n", + sizeof(HBA_ADAPTERCALLBACK_ELEM)); +#endif + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR); + } + *callbackHandle = (HBA_CALLBACKHANDLE) acbp; + acbp->callback = callback; + acbp->userdata = userData; + acbp->lib_info = lib_infop; + + status = (registeredfunc)(adapterevents_callback, + (void *)acbp, + vendorHandle, + &acbp->vendorcbhandle); + if(status != HBA_STATUS_OK) { + free(acbp); + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); + } + + GRAB_MUTEX(&_hbaapi_AE_mutex); + acbp->next = _hbaapi_adapterevents_callback_list; + _hbaapi_adapterevents_callback_list = acbp; + RELEASE_MUTEX(&_hbaapi_AE_mutex); + + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK); +} + +/* Adapter Port Events ********************************************************/ +static void +adapterportevents_callback (void *data, + HBA_WWN PortWWN, + HBA_UINT32 eventType, + HBA_UINT32 fabricPortID) { + HBA_ADAPTERCALLBACK_ELEM *acbp; + + DEBUG(3, "AdapterPortEvent, port:%s, eventType:%d fabricPortID:0X%06x", + WWN2STR1(&PortWWN), eventType, fabricPortID); + + GRAB_MUTEX(&_hbaapi_APE_mutex); + + for(acbp = _hbaapi_adapterportevents_callback_list; + acbp != NULL; + acbp = acbp->next) { + if(data == (void *)acbp) { + (*acbp->callback)(acbp->userdata, PortWWN, eventType, fabricPortID); + break; + } + } + RELEASE_MUTEX(&_hbaapi_APE_mutex); +} +HBA_STATUS +HBA_RegisterForAdapterPortEvents ( + void (*callback) ( + void *data, + HBA_WWN PortWWN, + HBA_UINT32 eventType, + HBA_UINT32 fabricPortID + ), + void *userData, + HBA_HANDLE handle, + HBA_WWN PortWWN, + HBA_CALLBACKHANDLE *callbackHandle) { + + HBA_ADAPTERCALLBACK_ELEM *acbp; + HBARegisterForAdapterPortEventsFunc registeredfunc; + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + + DEBUG(2, "HBA_RegisterForAdapterPortEvents for port: %s", + WWN2STR1(&PortWWN), 0, 0); + + if (callbackHandle == NULL) { + return(HBA_STATUS_ERROR_ARG); + } + + CHECKLIBRARY(); + /* we now have the _hbaapi_LL_mutex */ + + registeredfunc = + lib_infop->functionTable.RegisterForAdapterPortEventsHandler; + if(registeredfunc == NULL) { + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED); + } + + /* + * that allocated memory is used both as the handle for the + * caller, and as userdata to the vendor call so that on + * callback the specific registration may be recalled + */ + acbp = (HBA_ADAPTERCALLBACK_ELEM *) + calloc(1, sizeof(HBA_ADAPTERCALLBACK_ELEM)); + if(acbp == NULL) { +#ifndef WIN32 + fprintf(stderr, + "HBA_RegisterForAdapterPortEvents: " + "calloc failed for %d bytes\n", + sizeof(HBA_ADAPTERCALLBACK_ELEM)); +#endif + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR); + + } + *callbackHandle = (HBA_CALLBACKHANDLE) acbp; + acbp->callback = callback; + acbp->userdata = userData; + acbp->lib_info = lib_infop; + + status = (registeredfunc)(adapterportevents_callback, + (void *)acbp, + vendorHandle, + PortWWN, + &acbp->vendorcbhandle); + if(status != HBA_STATUS_OK) { + free(acbp); + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); + } + + GRAB_MUTEX(&_hbaapi_APE_mutex); + acbp->next = _hbaapi_adapterportevents_callback_list; + _hbaapi_adapterportevents_callback_list = acbp; + RELEASE_MUTEX(&_hbaapi_APE_mutex); + + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK); +} + +/* Adapter State Events *******************************************************/ +static void +adapterportstatevents_callback (void *data, + HBA_WWN PortWWN, + HBA_UINT32 eventType) { + HBA_ADAPTERCALLBACK_ELEM *acbp; + + DEBUG(3, "AdapterPortStateEvent, port:%s, eventType:%d", WWN2STR1(&PortWWN), + eventType, 0); + + GRAB_MUTEX(&_hbaapi_APSE_mutex); + for(acbp = _hbaapi_adapterportstatevents_callback_list; + acbp != NULL; + acbp = acbp->next) { + if(data == (void *)acbp) { + (*acbp->callback)(acbp->userdata, PortWWN, eventType); + return; + } + } +} +HBA_STATUS +HBA_RegisterForAdapterPortStatEvents ( + void (*callback) ( + void *data, + HBA_WWN PortWWN, + HBA_UINT32 eventType + ), + void *userData, + HBA_HANDLE handle, + HBA_WWN PortWWN, + HBA_PORTSTATISTICS stats, + HBA_UINT32 statType, + HBA_CALLBACKHANDLE *callbackHandle) { + + HBA_ADAPTERCALLBACK_ELEM *acbp; + HBARegisterForAdapterPortStatEventsFunc + registeredfunc; + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + + DEBUG(2, "HBA_RegisterForAdapterPortStatEvents for port: %s", + WWN2STR1(&PortWWN), 0, 0); + + if (callbackHandle == NULL) { + return(HBA_STATUS_ERROR_ARG); + } + + CHECKLIBRARY(); + /* we now have the _hbaapi_LL_mutex */ + + registeredfunc = + lib_infop->functionTable.RegisterForAdapterPortStatEventsHandler; + if(registeredfunc == NULL) { + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED); + } + + /* + * that allocated memory is used both as the handle for the + * caller, and as userdata to the vendor call so that on + * callback the specific registration may be recalled + */ + acbp = (HBA_ADAPTERCALLBACK_ELEM *) + calloc(1, sizeof(HBA_ADAPTERCALLBACK_ELEM)); + if(acbp == NULL) { +#ifndef WIN32 + fprintf(stderr, + "HBA_RegisterForAdapterPortStatEvents: " + "calloc failed for %d bytes\n", + sizeof(HBA_ADAPTERCALLBACK_ELEM)); +#endif + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR); + } + *callbackHandle = (HBA_CALLBACKHANDLE) acbp; + acbp->callback = callback; + acbp->userdata = userData; + acbp->lib_info = lib_infop; + + status = (registeredfunc)(adapterportstatevents_callback, + (void *)acbp, + vendorHandle, + PortWWN, + stats, + statType, + &acbp->vendorcbhandle); + if(status != HBA_STATUS_OK) { + free(acbp); + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); + } + + GRAB_MUTEX(&_hbaapi_APSE_mutex); + acbp->next = _hbaapi_adapterportstatevents_callback_list; + _hbaapi_adapterportstatevents_callback_list = acbp; + RELEASE_MUTEX(&_hbaapi_APSE_mutex); + + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK); +} + +/* Target Events **************************************************************/ +static void +targetevents_callback (void *data, + HBA_WWN hbaPortWWN, + HBA_WWN discoveredPortWWN, + HBA_UINT32 eventType) { + HBA_ADAPTERCALLBACK_ELEM *acbp; + + DEBUG(3, "TargetEvent, hbaPort:%s, discoveredPort:%s eventType:%d", + WWN2STR1(&hbaPortWWN), WWN2STR2(&discoveredPortWWN), eventType); + + GRAB_MUTEX(&_hbaapi_TE_mutex); + for(acbp = _hbaapi_targetevents_callback_list; + acbp != NULL; + acbp = acbp->next) { + if(data == (void *)acbp) { + (*acbp->callback)(acbp->userdata, hbaPortWWN, + discoveredPortWWN, eventType); + break; + } + } + RELEASE_MUTEX(&_hbaapi_TE_mutex); +} +HBA_STATUS +HBA_RegisterForTargetEvents ( + void (*callback) ( + void *data, + HBA_WWN hbaPortWWN, + HBA_WWN discoveredPortWWN, + HBA_UINT32 eventType + ), + void *userData, + HBA_HANDLE handle, + HBA_WWN hbaPortWWN, + HBA_WWN discoveredPortWWN, + HBA_CALLBACKHANDLE *callbackHandle, + HBA_UINT32 allTargets) { + + HBA_ADAPTERCALLBACK_ELEM + *acbp; + HBARegisterForTargetEventsFunc + registeredfunc; + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + + DEBUG(2, "HBA_RegisterForTargetEvents, hbaPort: %s, discoveredPort: %s", + WWN2STR1(&hbaPortWWN), WWN2STR2(&discoveredPortWWN), 0); + + if (callbackHandle == NULL) { + return(HBA_STATUS_ERROR_ARG); + } + + CHECKLIBRARY(); + /* we now have the _hbaapi_LL_mutex */ + + registeredfunc = lib_infop->functionTable.RegisterForTargetEventsHandler; + if(registeredfunc == NULL) { + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED); + } + + /* + * that allocated memory is used both as the handle for the + * caller, and as userdata to the vendor call so that on + * callback the specific registration may be recalled + */ + acbp = (HBA_ADAPTERCALLBACK_ELEM *) + calloc(1, sizeof(HBA_ADAPTERCALLBACK_ELEM)); + if(acbp == NULL) { +#ifndef WIN32 + fprintf(stderr, + "HBA_RegisterForTargetEvents: calloc failed for %d bytes\n", + sizeof(HBA_ADAPTERCALLBACK_ELEM)); +#endif + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR); + } + *callbackHandle = (HBA_CALLBACKHANDLE) acbp; + acbp->callback = callback; + acbp->userdata = userData; + acbp->lib_info = lib_infop; + + status = (registeredfunc)(targetevents_callback, + (void *)acbp, + vendorHandle, + hbaPortWWN, + discoveredPortWWN, + &acbp->vendorcbhandle, + allTargets); + if(status != HBA_STATUS_OK) { + free(acbp); + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); + } + + GRAB_MUTEX(&_hbaapi_TE_mutex); + acbp->next = _hbaapi_targetevents_callback_list; + _hbaapi_targetevents_callback_list = acbp; + RELEASE_MUTEX(&_hbaapi_TE_mutex); + + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK); +} + +/* Link Events ****************************************************************/ +static void +linkevents_callback (void *data, + HBA_WWN adapterWWN, + HBA_UINT32 eventType, + void *pRLIRBuffer, + HBA_UINT32 RLIRBufferSize) { + HBA_ADAPTERCALLBACK_ELEM *acbp; + + DEBUG(3, "LinkEvent, hbaWWN:%s, eventType:%d", + WWN2STR1(&adapterWWN), eventType, 0); + + GRAB_MUTEX(&_hbaapi_LE_mutex); + for(acbp = _hbaapi_linkevents_callback_list; + acbp != NULL; + acbp = acbp->next) { + if(data == (void *)acbp) { + (*acbp->callback)(acbp->userdata, adapterWWN, + eventType, pRLIRBuffer, RLIRBufferSize); + break; + } + } + RELEASE_MUTEX(&_hbaapi_LE_mutex); +} +HBA_STATUS +HBA_RegisterForLinkEvents ( + void (*callback) ( + void *data, + HBA_WWN adapterWWN, + HBA_UINT32 eventType, + void *pRLIRBuffer, + HBA_UINT32 RLIRBufferSize), + void *userData, + void *pRLIRBuffer, + HBA_UINT32 RLIRBufferSize, + HBA_HANDLE handle, + HBA_CALLBACKHANDLE *callbackHandle) { + + HBA_ADAPTERCALLBACK_ELEM *acbp; + HBARegisterForLinkEventsFunc + registeredfunc; + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + + DEBUG(2, "HBA_RegisterForLinkEvents", 0, 0, 0); + + if (callbackHandle == NULL) { + return(HBA_STATUS_ERROR_ARG); + } + + CHECKLIBRARY(); + /* we now have the _hbaapi_LL_mutex */ + + registeredfunc = lib_infop->functionTable.RegisterForLinkEventsHandler; + if(registeredfunc == NULL) { + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED); + } + + /* + * that allocated memory is used both as the handle for the + * caller, and as userdata to the vendor call so that on + * callback the specific registration may be recalled + */ + acbp = (HBA_ADAPTERCALLBACK_ELEM *) + calloc(1, sizeof(HBA_ADAPTERCALLBACK_ELEM)); + if(acbp == NULL) { +#ifndef WIN32 + fprintf(stderr, + "HBA_RegisterForLinkEvents: calloc failed for %d bytes\n", + sizeof(HBA_ADAPTERCALLBACK_ELEM)); +#endif + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR); + } + *callbackHandle = (HBA_CALLBACKHANDLE) acbp; + acbp->callback = callback; + acbp->userdata = userData; + acbp->lib_info = lib_infop; + + status = (registeredfunc)(linkevents_callback, + (void *)acbp, + pRLIRBuffer, + RLIRBufferSize, + vendorHandle, + &acbp->vendorcbhandle); + if(status != HBA_STATUS_OK) { + free(acbp); + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); + } + + GRAB_MUTEX(&_hbaapi_LE_mutex); + acbp->next = _hbaapi_linkevents_callback_list; + _hbaapi_linkevents_callback_list = acbp; + RELEASE_MUTEX(&_hbaapi_LE_mutex); + + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK); +} + + +/* + * All of the functions below are almost passthru functions to the + * vendor specific function + */ + +void +HBA_CloseAdapter(HBA_HANDLE handle) { + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBACloseAdapterFunc CloseAdapterFunc; + + DEBUG(2, "HBA_CloseAdapter", 0, 0, 0); + + status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle); + if (status == HBA_STATUS_OK) { + CloseAdapterFunc = lib_infop->functionTable.CloseAdapterHandler; + if (CloseAdapterFunc != NULL) { + ((CloseAdapterFunc)(vendorHandle)); + } + RELEASE_MUTEX(&_hbaapi_LL_mutex); + } +} + +HBA_STATUS +HBA_GetAdapterAttributes ( + HBA_HANDLE handle, + HBA_ADAPTERATTRIBUTES + *hbaattributes) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBAGetAdapterAttributesFunc GetAdapterAttributesFunc; + + DEBUG(2, "HBA_GetAdapterAttributes", 0, 0, 0); + + CHECKLIBRARY(); + GetAdapterAttributesFunc = + lib_infop->functionTable.GetAdapterAttributesHandler; + if (GetAdapterAttributesFunc != NULL) { + status = ((GetAdapterAttributesFunc)(vendorHandle, hbaattributes)); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_GetAdapterPortAttributes ( + HBA_HANDLE handle, + HBA_UINT32 portindex, + HBA_PORTATTRIBUTES *portattributes) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBAGetAdapterPortAttributesFunc + GetAdapterPortAttributesFunc; + + DEBUG(2, "HBA_GetAdapterPortAttributes", 0, 0, 0); + + CHECKLIBRARY(); + GetAdapterPortAttributesFunc = + lib_infop->functionTable.GetAdapterPortAttributesHandler; + if (GetAdapterPortAttributesFunc != NULL) { + status = ((GetAdapterPortAttributesFunc) + (vendorHandle, portindex, portattributes)); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_GetPortStatistics ( + HBA_HANDLE handle, + HBA_UINT32 portindex, + HBA_PORTSTATISTICS *portstatistics) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBAGetPortStatisticsFunc + GetPortStatisticsFunc; + + DEBUG(2, "HBA_GetPortStatistics", 0, 0, 0); + + CHECKLIBRARY(); + GetPortStatisticsFunc = + lib_infop->functionTable.GetPortStatisticsHandler; + if (GetPortStatisticsFunc != NULL) { + status = ((GetPortStatisticsFunc) + (vendorHandle, portindex, portstatistics)); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_GetDiscoveredPortAttributes ( + HBA_HANDLE handle, + HBA_UINT32 portindex, + HBA_UINT32 discoveredportindex, + HBA_PORTATTRIBUTES *portattributes) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBAGetDiscoveredPortAttributesFunc + GetDiscoveredPortAttributesFunc; + + DEBUG(2, "HBA_GetDiscoveredPortAttributes", 0, 0, 0); + + CHECKLIBRARY(); + GetDiscoveredPortAttributesFunc = + lib_infop->functionTable.GetDiscoveredPortAttributesHandler; + if (GetDiscoveredPortAttributesFunc != NULL) { + status = ((GetDiscoveredPortAttributesFunc) + (vendorHandle, portindex, discoveredportindex, + portattributes)); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_GetPortAttributesByWWN ( + HBA_HANDLE handle, + HBA_WWN PortWWN, + HBA_PORTATTRIBUTES *portattributes) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBAGetPortAttributesByWWNFunc + GetPortAttributesByWWNFunc; + + DEBUG(2, "HBA_GetPortAttributesByWWN: %s", WWN2STR1(&PortWWN), 0, 0); + + CHECKLIBRARY(); + GetPortAttributesByWWNFunc = + lib_infop->functionTable.GetPortAttributesByWWNHandler; + if (GetPortAttributesByWWNFunc != NULL) { + status = ((GetPortAttributesByWWNFunc) + (vendorHandle, PortWWN, portattributes)); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_SendCTPassThru ( + HBA_HANDLE handle, + void *pReqBuffer, + HBA_UINT32 ReqBufferSize, + void *pRspBuffer, + HBA_UINT32 RspBufferSize) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBASendCTPassThruFunc + SendCTPassThruFunc; + + DEBUG(2, "HBA_SendCTPassThru", 0, 0, 0); + + CHECKLIBRARY(); + SendCTPassThruFunc = lib_infop->functionTable.SendCTPassThruHandler; + if (SendCTPassThruFunc != NULL) { + status = (SendCTPassThruFunc) + (vendorHandle, + pReqBuffer, ReqBufferSize, + pRspBuffer, RspBufferSize); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_SendCTPassThruV2 ( + HBA_HANDLE handle, + HBA_WWN hbaPortWWN, + void *pReqBuffer, + HBA_UINT32 ReqBufferSize, + void *pRspBuffer, + HBA_UINT32 *pRspBufferSize) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBASendCTPassThruV2Func + registeredfunc; + + DEBUG(2, "HBA_SendCTPassThruV2m hbaPortWWN: %s", WWN2STR1(&hbaPortWWN), 0, 0); + + CHECKLIBRARY(); + registeredfunc = lib_infop->functionTable.SendCTPassThruV2Handler; + if (registeredfunc != NULL) { + status = (registeredfunc) + (vendorHandle, hbaPortWWN, + pReqBuffer, ReqBufferSize, + pRspBuffer, pRspBufferSize); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_GetEventBuffer ( + HBA_HANDLE handle, + PHBA_EVENTINFO EventBuffer, + HBA_UINT32 *EventBufferCount) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBAGetEventBufferFunc + GetEventBufferFunc; + + DEBUG(2, "HBA_GetEventBuffer", 0, 0, 0); + + CHECKLIBRARY(); + GetEventBufferFunc = lib_infop->functionTable.GetEventBufferHandler; + if (GetEventBufferFunc != NULL) { + status = (GetEventBufferFunc) + (vendorHandle, EventBuffer, EventBufferCount); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_SetRNIDMgmtInfo (HBA_HANDLE handle, HBA_MGMTINFO Info) { + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBASetRNIDMgmtInfoFunc + SetRNIDMgmtInfoFunc; + + DEBUG(2, "HBA_SetRNIDMgmtInfo", 0, 0, 0); + + CHECKLIBRARY(); + SetRNIDMgmtInfoFunc = lib_infop->functionTable.SetRNIDMgmtInfoHandler; + if (SetRNIDMgmtInfoFunc != NULL) { + status = (SetRNIDMgmtInfoFunc)(vendorHandle, Info); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_GetRNIDMgmtInfo (HBA_HANDLE handle, HBA_MGMTINFO *pInfo) { + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBAGetRNIDMgmtInfoFunc + GetRNIDMgmtInfoFunc; + + DEBUG(2, "HBA_GetRNIDMgmtInfo", 0, 0, 0); + + CHECKLIBRARY(); + GetRNIDMgmtInfoFunc = lib_infop->functionTable.GetRNIDMgmtInfoHandler; + if (GetRNIDMgmtInfoFunc != NULL) { + status = (GetRNIDMgmtInfoFunc)(vendorHandle, pInfo); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_SendRNID ( + HBA_HANDLE handle, + HBA_WWN wwn, + HBA_WWNTYPE wwntype, + void *pRspBuffer, + HBA_UINT32 *pRspBufferSize) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBASendRNIDFunc SendRNIDFunc; + + DEBUG(2, "HBA_SendRNID for wwn: %s", WWN2STR1(&wwn), 0, 0); + + CHECKLIBRARY(); + SendRNIDFunc = lib_infop->functionTable.SendRNIDHandler; + if (SendRNIDFunc != NULL) { + status = ((SendRNIDFunc)(vendorHandle, wwn, wwntype, + pRspBuffer, pRspBufferSize)); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_SendRNIDV2( + HBA_HANDLE handle, + HBA_WWN hbaPortWWN, + HBA_WWN destWWN, + HBA_UINT32 destFCID, + HBA_UINT32 NodeIdDataFormat, + void *pRspBuffer, + HBA_UINT32 *pRspBufferSize) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBASendRNIDV2Func registeredfunc; + + DEBUG(2, "HBA_SendRNIDV2, hbaPortWWN: %s", WWN2STR1(&hbaPortWWN), 0, 0); + + CHECKLIBRARY(); + registeredfunc = lib_infop->functionTable.SendRNIDV2Handler; + if (registeredfunc != NULL) { + status = (registeredfunc) + (vendorHandle, hbaPortWWN, destWWN, destFCID, NodeIdDataFormat, + pRspBuffer, pRspBufferSize); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +void +HBA_RefreshInformation (HBA_HANDLE handle) { + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBARefreshInformationFunc + RefreshInformationFunc; + + DEBUG(2, "HBA_RefreshInformation", 0, 0, 0); + + status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle); + if(status == HBA_STATUS_OK) { + RefreshInformationFunc = + lib_infop->functionTable.RefreshInformationHandler; + if (RefreshInformationFunc != NULL) { + ((RefreshInformationFunc)(vendorHandle)); + } + RELEASE_MUTEX(&_hbaapi_LL_mutex); + } +} + +void +HBA_ResetStatistics (HBA_HANDLE handle, HBA_UINT32 portindex) { + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBAResetStatisticsFunc + ResetStatisticsFunc; + + DEBUG(2, "HBA_ResetStatistics", 0, 0, 0); + + status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle); + if(status == HBA_STATUS_OK) { + ResetStatisticsFunc = lib_infop->functionTable.ResetStatisticsHandler; + if (ResetStatisticsFunc != NULL) { + ((ResetStatisticsFunc)(vendorHandle, portindex)); + } + RELEASE_MUTEX(&_hbaapi_LL_mutex); + } +} + +HBA_STATUS +HBA_GetFcpTargetMapping (HBA_HANDLE handle, PHBA_FCPTARGETMAPPING mapping) { + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBAGetFcpTargetMappingFunc GetFcpTargetMappingFunc; + + DEBUG(2, "HBA_GetFcpTargetMapping", 0, 0, 0); + + CHECKLIBRARY(); + GetFcpTargetMappingFunc = + lib_infop->functionTable.GetFcpTargetMappingHandler; + if (GetFcpTargetMappingFunc != NULL) { + status = ((GetFcpTargetMappingFunc)(vendorHandle, mapping)); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_GetFcpTargetMappingV2 ( + HBA_HANDLE handle, + HBA_WWN hbaPortWWN, + HBA_FCPTARGETMAPPINGV2 + *pmapping) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBAGetFcpTargetMappingV2Func + registeredfunc; + + DEBUG(2, "HBA_GetFcpTargetMapping", 0, 0, 0); + + CHECKLIBRARY(); + registeredfunc = + lib_infop->functionTable.GetFcpTargetMappingV2Handler; + if (registeredfunc != NULL) { + status = ((registeredfunc)(vendorHandle, hbaPortWWN, pmapping)); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_GetFcpPersistentBinding (HBA_HANDLE handle, PHBA_FCPBINDING binding) { + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBAGetFcpPersistentBindingFunc + GetFcpPersistentBindingFunc; + + DEBUG(2, "HBA_GetFcpPersistentBinding", 0, 0, 0); + + CHECKLIBRARY(); + GetFcpPersistentBindingFunc = + lib_infop->functionTable.GetFcpPersistentBindingHandler; + if (GetFcpPersistentBindingFunc != NULL) { + status = ((GetFcpPersistentBindingFunc)(vendorHandle, binding)); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_ScsiInquiryV2 ( + HBA_HANDLE handle, + HBA_WWN hbaPortWWN, + HBA_WWN discoveredPortWWN, + HBA_UINT64 fcLUN, + HBA_UINT8 CDB_Byte1, + HBA_UINT8 CDB_Byte2, + void *pRspBuffer, + HBA_UINT32 *pRspBufferSize, + HBA_UINT8 *pScsiStatus, + void *pSenseBuffer, + HBA_UINT32 *pSenseBufferSize) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBAScsiInquiryV2Func ScsiInquiryV2Func; + + DEBUG(2, "HBA_ScsiInquiryV2 to discoveredPortWWN: %s", + WWN2STR1(&discoveredPortWWN), 0, 0); + + CHECKLIBRARY(); + ScsiInquiryV2Func = + lib_infop->functionTable.ScsiInquiryV2Handler; + if (ScsiInquiryV2Func != NULL) { + status =((ScsiInquiryV2Func)( + vendorHandle, hbaPortWWN, discoveredPortWWN, fcLUN, CDB_Byte1, + CDB_Byte2, pRspBuffer, pRspBufferSize, pScsiStatus, + pSenseBuffer, pSenseBufferSize)); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_SendScsiInquiry ( + HBA_HANDLE handle, + HBA_WWN PortWWN, + HBA_UINT64 fcLUN, + HBA_UINT8 EVPD, + HBA_UINT32 PageCode, + void *pRspBuffer, + HBA_UINT32 RspBufferSize, + void *pSenseBuffer, + HBA_UINT32 SenseBufferSize) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBASendScsiInquiryFunc SendScsiInquiryFunc; + + DEBUG(2, "HBA_SendScsiInquiry to PortWWN: %s", WWN2STR1(&PortWWN), 0, 0); + + CHECKLIBRARY(); + SendScsiInquiryFunc = lib_infop->functionTable.ScsiInquiryHandler; + if (SendScsiInquiryFunc != NULL) { + status =((SendScsiInquiryFunc)( + vendorHandle, PortWWN, fcLUN, EVPD, PageCode, pRspBuffer, + RspBufferSize, pSenseBuffer, SenseBufferSize)); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_ScsiReportLUNsV2 ( + HBA_HANDLE handle, + HBA_WWN hbaPortWWN, + HBA_WWN discoveredPortWWN, + void *pRespBuffer, + HBA_UINT32 *pRespBufferSize, + HBA_UINT8 *pScsiStatus, + void *pSenseBuffer, + HBA_UINT32 *pSenseBufferSize) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBAScsiReportLUNsV2Func ScsiReportLUNsV2Func; + + DEBUG(2, "HBA_ScsiReportLUNsV2 to discoveredPortWWN: %s", + WWN2STR1(&discoveredPortWWN), 0, 0); + + CHECKLIBRARY(); + ScsiReportLUNsV2Func = lib_infop->functionTable.ScsiReportLUNsV2Handler; + if (ScsiReportLUNsV2Func != NULL) { + status = ((ScsiReportLUNsV2Func)( + vendorHandle, hbaPortWWN, discoveredPortWWN, + pRespBuffer, pRespBufferSize, + pScsiStatus, + pSenseBuffer, pSenseBufferSize)); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_SendReportLUNs ( + HBA_HANDLE handle, + HBA_WWN portWWN, + void *pRspBuffer, + HBA_UINT32 RspBufferSize, + void *pSenseBuffer, + HBA_UINT32 SenseBufferSize) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBASendReportLUNsFunc SendReportLUNsFunc; + + DEBUG(2, "HBA_SendReportLUNs to PortWWN: %s", WWN2STR1(&portWWN), 0, 0); + + CHECKLIBRARY(); + SendReportLUNsFunc = lib_infop->functionTable.ReportLUNsHandler; + if (SendReportLUNsFunc != NULL) { + status = ((SendReportLUNsFunc)( + vendorHandle, portWWN, pRspBuffer, + RspBufferSize, pSenseBuffer, SenseBufferSize)); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_ScsiReadCapacityV2 ( + HBA_HANDLE handle, + HBA_WWN hbaPortWWN, + HBA_WWN discoveredPortWWN, + HBA_UINT64 fcLUN, + void *pRspBuffer, + HBA_UINT32 *pRspBufferSize, + HBA_UINT8 *pScsiStatus, + void *pSenseBuffer, + HBA_UINT32 *SenseBufferSize) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBAScsiReadCapacityV2Func ScsiReadCapacityV2Func; + + DEBUG(2, "HBA_ScsiReadCapacityV2 to discoveredPortWWN: %s", + WWN2STR1(&discoveredPortWWN), 0, 0); + + CHECKLIBRARY(); + ScsiReadCapacityV2Func = + lib_infop->functionTable.ScsiReadCapacityV2Handler; + if (ScsiReadCapacityV2Func != NULL) { + status =((ScsiReadCapacityV2Func)( + vendorHandle, hbaPortWWN, discoveredPortWWN, fcLUN, + pRspBuffer, pRspBufferSize, + pScsiStatus, + pSenseBuffer, SenseBufferSize)); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_SendReadCapacity ( + HBA_HANDLE handle, + HBA_WWN portWWN, + HBA_UINT64 fcLUN, + void *pRspBuffer, + HBA_UINT32 RspBufferSize, + void *pSenseBuffer, + HBA_UINT32 SenseBufferSize) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBASendReadCapacityFunc SendReadCapacityFunc; + + DEBUG(2, "HBA_SendReadCapacity to portWWN: %s", WWN2STR1(&portWWN), 0, 0); + + CHECKLIBRARY(); + SendReadCapacityFunc = lib_infop->functionTable.ReadCapacityHandler; + if (SendReadCapacityFunc != NULL) { + status =((SendReadCapacityFunc) + (vendorHandle, portWWN, fcLUN, pRspBuffer, + RspBufferSize, pSenseBuffer, SenseBufferSize)); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_SendRLS ( + HBA_HANDLE handle, + HBA_WWN hbaPortWWN, + HBA_WWN destWWN, + void *pRspBuffer, + HBA_UINT32 *pRspBufferSize) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBASendRLSFunc registeredfunc; + + DEBUG(2, "HBA_SendRLS to agent_wwn: %s:%d", + WWN2STR1(&agent_wwn), agent_domain, 0); + + CHECKLIBRARY(); + registeredfunc = lib_infop->functionTable.SendRLSHandler; + if (registeredfunc != NULL) { + status =(registeredfunc)( + vendorHandle, hbaPortWWN, destWWN, pRspBuffer, pRspBufferSize); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_SendRPL ( + HBA_HANDLE handle, + HBA_WWN hbaPortWWN, + HBA_WWN agent_wwn, + HBA_UINT32 agent_domain, + HBA_UINT32 portindex, + void *pRspBuffer, + HBA_UINT32 *pRspBufferSize) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBASendRPLFunc registeredfunc; + + DEBUG(2, "HBA_SendRPL to agent_wwn: %s:%d", + WWN2STR1(&agent_wwn), agent_domain, 0); + + CHECKLIBRARY(); + registeredfunc = lib_infop->functionTable.SendRPLHandler; + if (registeredfunc != NULL) { + status =(registeredfunc)( + vendorHandle, hbaPortWWN, agent_wwn, agent_domain, portindex, + pRspBuffer, pRspBufferSize); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_SendRPS ( + HBA_HANDLE handle, + HBA_WWN hbaPortWWN, + HBA_WWN agent_wwn, + HBA_UINT32 agent_domain, + HBA_WWN object_wwn, + HBA_UINT32 object_port_number, + void *pRspBuffer, + HBA_UINT32 *pRspBufferSize) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBASendRPSFunc registeredfunc; + + DEBUG(2, "HBA_SendRPS to agent_wwn: %s:%d", + WWN2STR1(&agent_wwn), agent_domain, 0); + + CHECKLIBRARY(); + registeredfunc = lib_infop->functionTable.SendRPSHandler; + if (registeredfunc != NULL) { + status =(registeredfunc)( + vendorHandle, hbaPortWWN, agent_wwn, agent_domain, + object_wwn, object_port_number, + pRspBuffer, pRspBufferSize); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_SendSRL ( + HBA_HANDLE handle, + HBA_WWN hbaPortWWN, + HBA_WWN wwn, + HBA_UINT32 domain, + void *pRspBuffer, + HBA_UINT32 *pRspBufferSize) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBASendSRLFunc registeredfunc; + + DEBUG(2, "HBA_SendSRL to wwn:%s domain:%d", WWN2STR1(&wwn), domain, 0); + + CHECKLIBRARY(); + registeredfunc = lib_infop->functionTable.SendSRLHandler; + if (registeredfunc != NULL) { + status =(registeredfunc)( + vendorHandle, hbaPortWWN, wwn, domain, + pRspBuffer, pRspBufferSize); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_SendLIRR ( + HBA_HANDLE handle, + HBA_WWN sourceWWN, + HBA_WWN destWWN, + HBA_UINT8 function, + HBA_UINT8 type, + void *pRspBuffer, + HBA_UINT32 *pRspBufferSize) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBASendLIRRFunc registeredfunc; + + DEBUG(2, "HBA_SendLIRR destWWN:%s", WWN2STR1(&destWWN), 0, 0); + + CHECKLIBRARY(); + registeredfunc = lib_infop->functionTable.SendLIRRHandler; + if (registeredfunc != NULL) { + status =(registeredfunc)( + vendorHandle, sourceWWN, destWWN, function, type, + pRspBuffer, pRspBufferSize); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_GetBindingCapability( + HBA_HANDLE handle, + HBA_WWN hbaPortWWN, + HBA_BIND_CAPABILITY *pcapability) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBAGetBindingCapabilityFunc + registeredfunc; + + DEBUG(2, "HBA_GetBindingCapability", 0, 0, 0); + + CHECKLIBRARY(); + registeredfunc = lib_infop->functionTable.GetBindingCapabilityHandler; + if (registeredfunc != NULL) { + status =(registeredfunc)(vendorHandle, hbaPortWWN, pcapability); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_GetBindingSupport ( + HBA_HANDLE handle, + HBA_WWN hbaPortWWN, + HBA_BIND_CAPABILITY *pcapability) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBAGetBindingSupportFunc + registeredfunc; + + DEBUG(2, "HBA_GetBindingSupport", 0, 0, 0); + + CHECKLIBRARY(); + registeredfunc = lib_infop->functionTable.GetBindingSupportHandler; + if (registeredfunc != NULL) { + status =(registeredfunc)(vendorHandle, hbaPortWWN, pcapability); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_SetBindingSupport( + HBA_HANDLE handle, + HBA_WWN hbaPortWWN, + HBA_BIND_CAPABILITY capability) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBASetBindingSupportFunc + registeredfunc; + + DEBUG(2, "HBA_SetBindingSupport", 0, 0, 0); + + CHECKLIBRARY(); + registeredfunc = lib_infop->functionTable.SetBindingSupportHandler; + if (registeredfunc != NULL) { + status =(registeredfunc)(vendorHandle, hbaPortWWN, capability); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_SetPersistentBindingV2 ( + HBA_HANDLE handle, + HBA_WWN hbaPortWWN, + const HBA_FCPBINDING2 + *pbinding) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBASetPersistentBindingV2Func + registeredfunc; + + DEBUG(2, "HBA_SetPersistentBindingV2 port: %s", WWN2STR1(&hbaPortWWN), 0, 0); + + CHECKLIBRARY(); + registeredfunc = lib_infop->functionTable.SetPersistentBindingV2Handler; + if (registeredfunc != NULL) { + status =(registeredfunc)(vendorHandle, hbaPortWWN, pbinding); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_GetPersistentBindingV2 ( + HBA_HANDLE handle, + HBA_WWN hbaPortWWN, + HBA_FCPBINDING2 *pbinding) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBAGetPersistentBindingV2Func + registeredfunc; + + DEBUG(2, "HBA_GetPersistentBindingV2 port: %s", WWN2STR1(&hbaPortWWN), 0, 0); + + CHECKLIBRARY(); + registeredfunc = lib_infop->functionTable.GetPersistentBindingV2Handler; + if (registeredfunc != NULL) { + status =(registeredfunc)(vendorHandle, hbaPortWWN, pbinding); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_RemovePersistentBinding ( + HBA_HANDLE handle, + HBA_WWN hbaPortWWN, + const HBA_FCPBINDING2 + *pbinding) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBARemovePersistentBindingFunc + registeredfunc; + + DEBUG(2, "HBA_RemovePersistentBinding", 0, 0, 0); + + CHECKLIBRARY(); + registeredfunc = + lib_infop->functionTable.RemovePersistentBindingHandler; + if (registeredfunc != NULL) { + status =(registeredfunc)(vendorHandle, hbaPortWWN, pbinding); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_RemoveAllPersistentBindings ( + HBA_HANDLE handle, + HBA_WWN hbaPortWWN) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBARemoveAllPersistentBindingsFunc + registeredfunc; + + DEBUG(2, "HBA_RemoveAllPersistentBindings", 0, 0, 0); + + CHECKLIBRARY(); + registeredfunc = + lib_infop->functionTable.RemoveAllPersistentBindingsHandler; + if (registeredfunc != NULL) { + status =(registeredfunc)(vendorHandle, hbaPortWWN); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_GetFC4Statistics ( + HBA_HANDLE handle, + HBA_WWN portWWN, + HBA_UINT8 FC4type, + HBA_FC4STATISTICS *pstatistics) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBAGetFC4StatisticsFunc + registeredfunc; + + DEBUG(2, "HBA_GetFC4Statistics port: %s", WWN2STR1(&portWWN), 0, 0); + + CHECKLIBRARY(); + registeredfunc = + lib_infop->functionTable.GetFC4StatisticsHandler; + if (registeredfunc != NULL) { + status =(registeredfunc) + (vendorHandle, portWWN, FC4type, pstatistics); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_STATUS +HBA_GetFCPStatistics ( + HBA_HANDLE handle, + const HBA_SCSIID *lunit, + HBA_FC4STATISTICS *pstatistics) +{ + HBA_STATUS status; + HBA_LIBRARY_INFO *lib_infop; + HBA_HANDLE vendorHandle; + HBAGetFCPStatisticsFunc + registeredfunc; + + DEBUG(2, "HBA_GetFCPStatistics", 0, 0, 0); + + CHECKLIBRARY(); + registeredfunc = + lib_infop->functionTable.GetFCPStatisticsHandler; + if (registeredfunc != NULL) { + status =(registeredfunc)(vendorHandle, lunit, pstatistics); + } else { + status = HBA_STATUS_ERROR_NOT_SUPPORTED; + } + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status); +} + +HBA_UINT32 +HBA_GetVendorLibraryAttributes ( + HBA_UINT32 adapter_index, + HBA_LIBRARYATTRIBUTES *attributes) +{ + HBA_ADAPTER_INFO *adapt_infop; + HBAGetVendorLibraryAttributesFunc + registeredfunc; + HBA_UINT32 ret = 0; + + DEBUG(2, "HBA_GetVendorLibraryAttributes adapterindex:%d", + adapter_index, 0, 0); + if(_hbaapi_librarylist == NULL) { + DEBUG(1, "HBAAPI not loaded yet.", 0, 0, 0); + return(0); + } + + if (attributes == NULL) { + return(HBA_STATUS_ERROR_ARG); + } + + memset(attributes, 0, sizeof(HBA_LIBRARYATTRIBUTES)); + + GRAB_MUTEX(&_hbaapi_LL_mutex); + GRAB_MUTEX(&_hbaapi_AL_mutex); + for(adapt_infop = _hbaapi_adapterlist; + adapt_infop != NULL; + adapt_infop = adapt_infop->next) { + + if(adapt_infop->index == adapter_index) { + registeredfunc = adapt_infop->library-> + functionTable.GetVendorLibraryAttributesHandler; + if(registeredfunc != NULL) { + ret = (registeredfunc)(attributes); + } else { + /* Version 1 libary? */ + HBAGetVersionFunc GetVersionFunc; + GetVersionFunc = adapt_infop->library-> + functionTable.GetVersionHandler; + if(GetVersionFunc != NULL) { + ret = ((GetVersionFunc)()); + } +#ifdef NOTDEF + else { + /* This should not happen, dont think its going to */ + } +#endif + } + if (attributes->LibPath[0] == '\0') { + if(strlen(adapt_infop->library->LibraryPath) < 256) { + strcpy(attributes->LibPath, + adapt_infop->library->LibraryPath); + } + } + break; + } + } + RELEASE_MUTEX(&_hbaapi_AL_mutex); + RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, ret); +} |