/*
 * Description
 *         HBAAPILIB.C - Implements a sample common HBA API library
 *
 * Author
 *         Benjamin F. Kuo, Troika Networks, Inc. (benk@troikanetworks.com)
 *         Tuan Lam, QLogic Corp. (t_lam@qlc.com)
 *         Dan Willie, Emulex Corp. (Dan.Willie@emulex.com)
 *
 * License
 *
 *         This software is licensed under the Storage Networking Industry
 *         Association's (SNIA) Public License 1.1. See license.htm for
 *         full license.
    $Id: FcHbaApi.c 8788 2012-06-18 15:19:48Z karen.ortin@hp.com $
    $Date: 2012-06-18 10:19:48 -0500 (Mon, 18 Jun 2012) $
    $Rev: 8788 $
 *
 *************************************************************************** 
 */



#ifdef WIN32
#include <windows.h>
#else  // POSIX
#include <dlfcn.h>
#endif

#include <stdio.h>
#include <string.h>
#include "FcHbaApi.h"

#ifdef VMWARE
//#define HBA_CONFIG_FILE "/etc/cim/hp-smx/hba.conf"
#define HBA_CONFIG_FILE "/opt/hp/hp-smx/hp-hba.conf"
#else
#define HBA_CONFIG_FILE "/etc/hba.conf"
#endif

/* LIBRARY_NUM is a shortcut to figure out which library we need to call.
   The top 32 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))

#define HBA_MAX_NUM_LIBRARIES       32
#define HBA_MAX_NUM_ADAPTERS   64
typedef enum {HBA_LIBRARY_UNKNOWN, HBA_LIBRARY_LOADED, HBA_LIBRARY_NOT_LOADED} HBA_LIBRARY_STATUS;

typedef struct hba_library_info {
	char				LibraryName[64];
	char				LibraryPath[256];
#ifdef WIN32	
	HINSTANCE			hLibrary;			/* Handle to a loaded DLL */
#else
	void*				hLibrary;                       /* Handle to a loaded DLL */
#endif
	HBA_ENTRYPOINTS		functionTable;		 		/* Function pointers */
	HBA_LIBRARY_STATUS	status;					/* info on this library */
} HBA_LIBRARY_INFO, *PHBA_LIBRARY_INFO;

typedef struct {
    unsigned int       HBALibraryCount;      
    HBA_LIBRARY_INFO   Info[1];            
} HBA_LIBRARIES;


typedef struct {
	char name[64];
	HBA_UINT32 libraryindex;
} HBA_ADAPTER_INFO;

HBA_LIBRARY_INFO librarytable[HBA_MAX_NUM_LIBRARIES];
HBA_ADAPTER_INFO adaptertable[HBA_MAX_NUM_ADAPTERS];
HBA_UINT32       number_of_total_adapters;


#ifdef WIN32
/* Begin implementation */
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


HBA_STATUS HBA_LoadLibrary() {
    typedef HBA_STATUS ( * lpFunc1)(PHBA_ENTRYPOINTS);
    lpFunc1 RegisterFunc;
	HBALoadLibraryFunc LoadLibraryFunc;
	HBAGetVersionFunc GetVersionFunc;

	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];

	lStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\SNIA\\HBA",
		0, KEY_READ, &hkSniaHba);
	if (lStatus != ERROR_SUCCESS)
	{
		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);
			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)
		{
			/* Now I can try to load the library */
			librarytable[i].hLibrary = LoadLibrary(byFileName); /* Load the DLL now */
			if (librarytable[i].hLibrary != NULL)
			{
				/* Call the registration function to get the list of pointers */
				RegisterFunc = (lpFunc1) GetProcAddress(librarytable[i].hLibrary, "HBA_RegisterLibrary");
				if (RegisterFunc != NULL) 
				{
					/* Load the function points directly into the table of functions */
					status = ((RegisterFunc)(&librarytable[i].functionTable));
					if (status == HBA_STATUS_OK) {
						// successfully loaded library
						GetVersionFunc = librarytable[i].functionTable.GetVersionHandler;
						if (GetVersionFunc != NULL) 
						{
							/* Check the version of this library before loading! */
							libversion = ((GetVersionFunc)());
							if (libversion >= HBA_LIBVERSION) {
								LoadLibraryFunc = librarytable[i].functionTable.LoadLibraryHandler;
								if (LoadLibraryFunc != NULL) 
								{
									/* Initialize this library */
									status = ((LoadLibraryFunc)());
									if (status == HBA_STATUS_OK) {
										// successfully loaded library
										librarytable[i].status = HBA_LIBRARY_LOADED;
									} else {
										// library not loaded
										librarytable[i].status = HBA_LIBRARY_NOT_LOADED;
									}
								}

							} else {
								// version mismatch -- library not loaded
								librarytable[i].status = HBA_LIBRARY_NOT_LOADED;
//								//printf("Library version mismatch. Got %d expected %d.\n", libversion, HBA_LIBVERSION);
							}
						}

					} else {
						// library not loaded
						librarytable[i].status = HBA_LIBRARY_NOT_LOADED;
					}
				}
			} else {
				////printf("unable to load library %s\n", librarypath);
			}
		}

		RegCloseKey(hkVendorLib);
	}
	RegCloseKey(hkSniaHba);

#else

	int i = 0;
	FILE *hbaconf;
	char fullline[512]; /* Full line read in from HBA.conf */
	char libraryname[64]; /* Read in from file HBA.conf */
	char librarypath[256]; /* Read in from file HBA.conf */
        char hbaConfFilePath[256];
	char *charPtr;
 
 
	//strcpy(hbaConfFilePath, "/etc/hba.conf");  /* common conf file, may not exist! */
        strcpy(hbaConfFilePath, HBA_CONFIG_FILE);  /* common conf file, may not exist! */

	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))) {
		if ((fullline[0] != '#') && (fullline[0] != '\n')) {
			/* Take out the '\n' */
			if ((charPtr = strchr(fullline, '\n')) != NULL)
				*charPtr = '\0';

			/* look for the first tab */
			if ((charPtr = strchr(fullline, '\t')) == NULL)
				charPtr = strchr(fullline, ' ');

			/* Set Null termination for library name if found */
			if (charPtr != NULL) {
				*charPtr++ = '\0';
				/* Skip spaces and tabs until the next character found */
				while ((*charPtr == ' ') || (*charPtr == '\t'))
					charPtr++;
			} else {
				continue;                       /* May be invalid entry */
			}

			/* Copy library name and path */
			strcpy(libraryname, fullline);
			strcpy(librarypath, charPtr);

			/* Continue to the next line if library name or path is invalid */
			if ((strlen(libraryname) == 0) || (strlen(librarypath) == 0))
				continue;

                        //remove trailing spaces & tabs in libraryPath name - causes errors in dlopen (happens on brocade)
                        int len = 0, idx;
                        len = strlen(librarypath);
                        for( idx=0; idx < len; idx++)  {
                          if( (librarypath[idx]!=0x5F) &&                                  /* _ */
                              ((librarypath[idx] < 0x2D) || (librarypath[idx] > 0x39)) &&  /* -./0123456789 */
                              ((librarypath[idx] < 0x41) || (librarypath[idx] > 0x5a)) &&  /* A thru Z */
                              ((librarypath[idx] < 0x61) || (librarypath[idx] > 0x7a))     /* a thru z */
                            )
                              librarypath[idx]=0;
                        }
 
			memcpy((char *)&librarytable[i].LibraryName, (char *)&libraryname, 64);
			memcpy((char *)&librarytable[i].LibraryPath, (char *)&librarypath, 256);

			librarytable[i].hLibrary = dlopen(librarypath,RTLD_LAZY); /* Load the DLL now */
			if (librarytable[i].hLibrary != NULL)
			{
				/* Call the registration function to get the list of pointers */
				RegisterFunc = (lpFunc1) dlsym(librarytable[i].hLibrary, "HBA_RegisterLibrary");
				if (RegisterFunc != NULL) 
				{
					/* Load the function points directly into the table of functions */
					status = ((RegisterFunc)(&librarytable[i].functionTable));
					if (status == HBA_STATUS_OK) {
						/* successfully loaded library */
						GetVersionFunc = librarytable[i].functionTable.GetVersionHandler;
						if (GetVersionFunc != NULL) 
						{
							/* Check the version of this library before loading! */
							libversion = ((GetVersionFunc)());
							//printf("%s libversion = %d",librarypath, libversion);
							if (libversion >= HBA_LIBVERSION) {
								LoadLibraryFunc = librarytable[i].functionTable.LoadLibraryHandler;
								if (LoadLibraryFunc != NULL) 
								{
									/* Initialize this library */
									status = ((LoadLibraryFunc)());
									if (status == HBA_STATUS_OK) {
										/* successfully loaded library */
										librarytable[i].status = HBA_LIBRARY_LOADED;
									} else {
										/* library not loaded */
										librarytable[i].status = HBA_LIBRARY_NOT_LOADED;
									}
								}

							} else {
								/* version mismatch -- library not loaded */
								librarytable[i].status = HBA_LIBRARY_NOT_LOADED;
								//printf("Library version mismatch. Got %d expected %d.\n", libversion, HBA_LIBVERSION);
							}
						}

					} else {
						/* library not loaded */
						librarytable[i].status = HBA_LIBRARY_NOT_LOADED;
					}
				}
			} else {
				/*//printf("unable to load library %s\n", librarypath); */
			}
			i++;
			}
		}

#endif
    fclose(hbaconf);
    return HBA_STATUS_OK;
}



HBA_STATUS HBA_FreeLibrary() {
	HBAFreeLibraryFunc FreeLibraryFunc;
	HBA_STATUS status;
	int i;
	for (i = 0; i < HBA_MAX_NUM_LIBRARIES; i++) {
		if (librarytable[i].status == HBA_LIBRARY_LOADED) {
			FreeLibraryFunc = librarytable[i].functionTable.FreeLibraryHandler;
			if (FreeLibraryFunc != NULL) 
			{
				/* Free this library */
				status = ((FreeLibraryFunc)());
			}
#ifdef WIN32
			FreeLibrary(librarytable[i].hLibrary);         /* Unload DLL from memory */
#else
			dlclose(librarytable[i].hLibrary);         /* Unload DLL from memory */
#endif
			librarytable[i].status = HBA_LIBRARY_NOT_LOADED;
		}
	}
	return HBA_STATUS_OK;
}



HBA_UINT32 HBA_GetNumberOfAdapters() 
{
	int i=0, j=0;
    HBAGetNumberOfAdaptersFunc GetNumberOfAdaptersFunc;
    HBAGetAdapterNameFunc GetAdapterNameFunc;
	char adaptername[256];
	int num_adapters; /* local */
	
	number_of_total_adapters = 0;

	for (i = 0; i < HBA_MAX_NUM_LIBRARIES; i++) {
		
		if (librarytable[i].status == HBA_LIBRARY_LOADED) {

			GetNumberOfAdaptersFunc = librarytable[i].functionTable.GetNumberOfAdaptersHandler;
			if (GetNumberOfAdaptersFunc != NULL) 
			{
				num_adapters = ((GetNumberOfAdaptersFunc)());
				/* Also get the names of all the adapters here and cache */
				GetAdapterNameFunc = librarytable[i].functionTable.GetAdapterNameHandler;
				if (GetAdapterNameFunc != NULL) {
					for (j = 0; j < num_adapters; j++) {
						(GetAdapterNameFunc)(j, (char *)&adaptername);
						strcpy(adaptertable[number_of_total_adapters].name, adaptername);
						adaptertable[number_of_total_adapters].libraryindex = i;
						number_of_total_adapters++;
					}
				}
				

			}

		}
	}
	return number_of_total_adapters;
}

void *HBA_GetLibraryPath(HBA_UINT32 adapterindex, char *librarypath)
{
    memcpy(librarypath, (char *)&librarytable[adaptertable[adapterindex].libraryindex].LibraryPath, 256);

    return ( librarytable[adaptertable[adapterindex].libraryindex].hLibrary );

}

HBA_STATUS HBA_GetAdapterName(HBA_UINT32 adapterindex, char *adaptername)
{
	//int i=0;
	HBA_STATUS status;

	status = HBA_STATUS_OK;

	if (adapterindex < number_of_total_adapters) {
		strcpy(adaptername, adaptertable[adapterindex].name);
	} else {
		status = HBA_STATUS_ERROR_ILLEGAL_INDEX;
	}
	return status;
}

HBA_UINT32 HBA_GetVersion() {
	return 1;
}

HBA_HANDLE HBA_OpenAdapter(
	char* adaptername
	) {
	HBA_HANDLE handle;
	HBAOpenAdapterFunc OpenAdapterFunc;
	int i;
	int libraryindex;

	handle = 0;

	for (i = 0; i < (int)number_of_total_adapters; i++) {
		if (strcmp(adaptername, adaptertable[i].name) == 0) {
			libraryindex = adaptertable[i].libraryindex;
			OpenAdapterFunc = librarytable[libraryindex].functionTable.OpenAdapterHandler;
			if (OpenAdapterFunc != NULL) 
			{
				/* retrieve the vendor handle */
				handle = (OpenAdapterFunc)(adaptername);
				/* or this with the library index to get the common handle */
				handle = HBA_HANDLE_FROM_LOCAL(libraryindex, handle);
			}
			break;
		}
	}
	return handle;
}



/* Common library internal. Check library and return vendorhandle */
HBA_STATUS HBA_CheckLibrary(
	HBA_HANDLE handle,
	int * libraryIndex,
	HBA_HANDLE *vendorhandle
) {
	HBA_STATUS status;

	*libraryIndex = LIBRARY_NUM(handle);
	if (*libraryIndex > HBA_MAX_NUM_LIBRARIES) {
		/* illegal handle */
		status = HBA_STATUS_ERROR_INVALID_HANDLE;
	} else {
		if (librarytable[*libraryIndex].status != HBA_LIBRARY_LOADED) {
			/* library is not loaded or became unloaded */
			status = HBA_STATUS_ERROR;
		} else {
			*vendorhandle = VENDOR_HANDLE(handle);
			status = HBA_STATUS_OK;
		} /* Check for library loaded */
	} /* Check for valid library handle */
	return status;
}

void HBA_CloseAdapter(
	HBA_HANDLE handle
	)
{
	HBA_STATUS status;
	int libraryIndex;
	HBA_UINT32 vendorHandle;

	HBACloseAdapterFunc CloseAdapterFunc;
	status = HBA_CheckLibrary(handle, &libraryIndex, &vendorHandle);
	if (status == HBA_STATUS_OK) {
		CloseAdapterFunc = librarytable[libraryIndex].functionTable.CloseAdapterHandler;
		if (CloseAdapterFunc != NULL) 
		{
			((CloseAdapterFunc)(vendorHandle));		
		}
	}
	


}

HBA_STATUS HBA_GetAdapterAttributes(
	HBA_HANDLE handle, 
	HBA_ADAPTERATTRIBUTES *hbaattributes	
	)
{
	HBA_STATUS status;
	int libraryIndex;
	HBA_UINT32 vendorHandle;

	HBAGetAdapterAttributesFunc GetAdapterAttributesFunc;
	status = HBA_CheckLibrary(handle, &libraryIndex, &vendorHandle);
	if (status == HBA_STATUS_OK) {
		GetAdapterAttributesFunc = librarytable[libraryIndex].functionTable.GetAdapterAttributesHandler;
		if (GetAdapterAttributesFunc != NULL) 
		{
			status = ((GetAdapterAttributesFunc)(vendorHandle, hbaattributes));		
		}
	}
	return status;
}

HBA_STATUS HBA_GetAdapterPortAttributes(
	HBA_HANDLE handle, 
	HBA_UINT32 portindex,
	HBA_PORTATTRIBUTES *portattributes
	)
{
	HBA_STATUS status;
	int libraryIndex;
	HBA_UINT32 vendorHandle;

	HBAGetAdapterPortAttributesFunc GetAdapterPortAttributesFunc;
	status = HBA_CheckLibrary(handle, &libraryIndex, &vendorHandle);
	if (status == HBA_STATUS_OK) {
		GetAdapterPortAttributesFunc = librarytable[libraryIndex].functionTable.GetAdapterPortAttributesHandler;
		if (GetAdapterPortAttributesFunc != NULL) 
		{
			status = ((GetAdapterPortAttributesFunc)(vendorHandle, portindex, portattributes));		
		}
	}
	return status;
}

HBA_STATUS HBA_GetPortStatistics(
	HBA_HANDLE				handle,
	HBA_UINT32				portindex,
	HBA_PORTSTATISTICS			*portstatistics
	)
{
	HBA_STATUS status;
	int libraryIndex;
	HBA_UINT32 vendorHandle;

	HBAGetPortStatisticsFunc GetPortStatisticsFunc;
	status = HBA_CheckLibrary(handle, &libraryIndex, &vendorHandle);
	if (status == HBA_STATUS_OK) {
		GetPortStatisticsFunc = librarytable[libraryIndex].functionTable.GetPortStatisticsHandler;
		if (GetPortStatisticsFunc != NULL) 
		{
			status = ((GetPortStatisticsFunc)(vendorHandle, portindex, portstatistics));		
		}
	}
	return status;
}

HBA_STATUS HBA_GetDiscoveredPortAttributes(
	HBA_HANDLE handle, 
	HBA_UINT32 portindex,
	HBA_UINT32 discoveredportindex,
	HBA_PORTATTRIBUTES *portattributes
	)
{
	HBA_STATUS status;
	int libraryIndex;
	HBA_UINT32 vendorHandle;

	HBAGetDiscoveredPortAttributesFunc GetDiscoveredPortAttributesFunc;
	status = HBA_CheckLibrary(handle, &libraryIndex, &vendorHandle);
	if (status == HBA_STATUS_OK) {
		GetDiscoveredPortAttributesFunc = librarytable[libraryIndex].functionTable.GetDiscoveredPortAttributesHandler;
		if (GetDiscoveredPortAttributesFunc != NULL) 
		{
			status = ((GetDiscoveredPortAttributesFunc)(vendorHandle, portindex, discoveredportindex, portattributes));		
		}
	} 
	return status;
}

HBA_STATUS HBA_GetPortAttributesByWWN(
	HBA_HANDLE handle,
	HBA_WWN PortWWN,
	HBA_PORTATTRIBUTES *portattributes
	)
{
	HBA_STATUS status;
	int libraryIndex;
	HBA_UINT32 vendorHandle;

	HBAGetPortAttributesByWWNFunc GetPortAttributesByWWNFunc;
	status = HBA_CheckLibrary(handle, &libraryIndex, &vendorHandle);
	if (status == HBA_STATUS_OK) {
		GetPortAttributesByWWNFunc = librarytable[libraryIndex].functionTable.GetPortAttributesByWWNHandler;
		if (GetPortAttributesByWWNFunc != NULL) 
		{
			status = ((GetPortAttributesByWWNFunc)(vendorHandle, PortWWN, portattributes));		
		}
	}
	return status;
}

HBA_STATUS HBA_SendCTPassThru(
	HBA_HANDLE handle, 
	void * pReqBuffer,
	HBA_UINT32 ReqBufferSize,
	void * pRspBuffer,  
	HBA_UINT32 RspBufferSize
	)
{
	HBA_STATUS status;
	int libraryIndex;
	HBA_UINT32 vendorHandle;

	HBASendCTPassThruFunc SendCTPassThruFunc;
	status = HBA_CheckLibrary(handle, &libraryIndex, &vendorHandle);
	if (status == HBA_STATUS_OK) {
		SendCTPassThruFunc = librarytable[libraryIndex].functionTable.SendCTPassThruHandler;
		if (SendCTPassThruFunc != NULL) 
		{
			status = ((SendCTPassThruFunc)(vendorHandle, pReqBuffer, ReqBufferSize, pRspBuffer, RspBufferSize));		
		}
	}
	return status;
}


HBA_STATUS HBA_GetEventBuffer(
	HBA_HANDLE handle, 
	PHBA_EVENTINFO EventBuffer, 
	HBA_UINT32 *EventBufferCount)
{
	HBA_STATUS status;
	int libraryIndex;
	HBA_UINT32 vendorHandle;

	HBAGetEventBufferFunc GetEventBufferFunc;
	status = HBA_CheckLibrary(handle, &libraryIndex, &vendorHandle);
	if (status == HBA_STATUS_OK) {
			GetEventBufferFunc = librarytable[libraryIndex].functionTable.GetEventBufferHandler;
			if (GetEventBufferFunc != NULL) 
			{
				status = ((GetEventBufferFunc)(vendorHandle, EventBuffer, EventBufferCount));		
			}
	}
	return status;
}

HBA_STATUS HBA_SetRNIDMgmtInfo(
	HBA_HANDLE handle, 
	HBA_MGMTINFO *pInfo)
{
	HBA_STATUS status;
	int libraryIndex;
	HBA_UINT32 vendorHandle;

	HBASetRNIDMgmtInfoFunc SetRNIDMgmtInfoFunc;
	status = HBA_CheckLibrary(handle, &libraryIndex, &vendorHandle);
	if (status == HBA_STATUS_OK) {
			SetRNIDMgmtInfoFunc = librarytable[libraryIndex].functionTable.SetRNIDMgmtInfoHandler;
			if (SetRNIDMgmtInfoFunc != NULL) 
			{
				status = ((SetRNIDMgmtInfoFunc)(vendorHandle, pInfo));		
			}
	}
	return status;
}

HBA_STATUS HBA_GetRNIDMgmtInfo(
	HBA_HANDLE handle, 
	HBA_MGMTINFO *pInfo)
{
	HBA_STATUS status;
	int libraryIndex;
	HBA_UINT32 vendorHandle;

	HBASetRNIDMgmtInfoFunc GetRNIDMgmtInfoFunc;
	status = HBA_CheckLibrary(handle, &libraryIndex, &vendorHandle);
	if (status == HBA_STATUS_OK) {
			GetRNIDMgmtInfoFunc = librarytable[libraryIndex].functionTable.GetRNIDMgmtInfoHandler;
			if (GetRNIDMgmtInfoFunc != NULL) 
			{
				status = ((GetRNIDMgmtInfoFunc)(vendorHandle, pInfo));		
			}
	}
	return status;
}
	
HBA_STATUS HBA_SendRNID(
	HBA_HANDLE handle,
	HBA_WWN wwn,
	HBA_WWNTYPE wwntype,
	void * pRspBuffer,
	HBA_UINT32 *RspBufferSize
	)
{
	HBA_STATUS status;
	int libraryIndex;
	HBA_UINT32 vendorHandle;

	HBASendRNIDFunc SendRNIDFunc;
	status = HBA_CheckLibrary(handle, &libraryIndex, &vendorHandle);
	if (status == HBA_STATUS_OK) {
			SendRNIDFunc = librarytable[libraryIndex].functionTable.SendRNIDHandler;
			if (SendRNIDFunc != NULL) 
			{
				status = ((SendRNIDFunc)(vendorHandle, wwn, wwntype, pRspBuffer, RspBufferSize));		
			}
	}
	return status;
}


void HBA_RefreshInformation(
	HBA_HANDLE handle)
{
	HBA_STATUS status;
	int libraryIndex;
	HBA_UINT32 vendorHandle;

	HBARefreshInformationFunc RefreshInformationFunc;
	status = HBA_CheckLibrary(handle, &libraryIndex, &vendorHandle);
	if (status == HBA_STATUS_OK) {
			RefreshInformationFunc = librarytable[libraryIndex].functionTable.RefreshInformationHandler;
			if (RefreshInformationFunc != NULL) 
			{
				((RefreshInformationFunc)(vendorHandle));		
			}
	}
}


void HBA_ResetStatistics(
	HBA_HANDLE handle,
	HBA_UINT32 portindex
	)
{
	HBA_STATUS status;
	int libraryIndex;
	HBA_UINT32 vendorHandle;

	HBAResetStatisticsFunc ResetStatisticsFunc;
	status = HBA_CheckLibrary(handle, &libraryIndex, &vendorHandle);
	if (status == HBA_STATUS_OK) {
			ResetStatisticsFunc = librarytable[libraryIndex].functionTable.ResetStatisticsHandler;
			if (ResetStatisticsFunc != NULL) 
			{
				((ResetStatisticsFunc)(vendorHandle, portindex));		
			}
	}
}


HBA_STATUS HBA_GetFcpTargetMapping(
	HBA_HANDLE handle, 
	PHBA_FCPTARGETMAPPING mapping
	)
{
	HBA_STATUS status;
	int libraryIndex;
	HBA_UINT32 vendorHandle;

	HBAGetFcpTargetMappingFunc GetFcpTargetMappingFunc;
	status = HBA_CheckLibrary(handle, &libraryIndex, &vendorHandle);
	if (status == HBA_STATUS_OK) {
			GetFcpTargetMappingFunc = librarytable[libraryIndex].functionTable.GetFcpTargetMappingHandler;
			if (GetFcpTargetMappingFunc != NULL) 
			{
				status = ((GetFcpTargetMappingFunc)(vendorHandle, mapping));		
			}
	}
	return status;
}


HBA_STATUS HBA_GetFcpPersistentBinding(
	HBA_HANDLE handle, 
	PHBA_FCPBINDING binding
	)
{
	HBA_STATUS status;
	int libraryIndex;
	HBA_UINT32 vendorHandle;

	HBAGetFcpPersistentBindingFunc GetFcpPersistentBindingFunc;
	status = HBA_CheckLibrary(handle, &libraryIndex, &vendorHandle);
	if (status == HBA_STATUS_OK) {
			GetFcpPersistentBindingFunc = librarytable[libraryIndex].functionTable.GetFcpPersistentBindingHandler;
			if (GetFcpPersistentBindingFunc != NULL) 
			{
				status = ((GetFcpPersistentBindingFunc)(vendorHandle, binding));		
			}
	}
	return 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;
	int libraryIndex;
	HBA_UINT32 vendorHandle;

	HBASendScsiInquiryFunc SendScsiInquiryFunc;
	status = HBA_CheckLibrary(handle, &libraryIndex, &vendorHandle);
	if (status == HBA_STATUS_OK) {
			SendScsiInquiryFunc = librarytable[libraryIndex].functionTable.ScsiInquiryHandler;
			if (SendScsiInquiryFunc != NULL) 
			{
				status =((SendScsiInquiryFunc)(vendorHandle, PortWWN, fcLUN, EVPD, PageCode, pRspBuffer, RspBufferSize, pSenseBuffer, SenseBufferSize));		
			}
	}
	return status;
}


HBA_STATUS HBA_SendReportLUNs (
	HBA_HANDLE handle,
	HBA_WWN portWWN,
	void * pRspBuffer, 
	HBA_UINT32 RspBufferSize,
	void * pSenseBuffer,
	HBA_UINT32 SenseBufferSize
	)
{
	HBA_STATUS status;
	int libraryIndex;
	HBA_UINT32 vendorHandle;

	HBASendReportLUNsFunc SendReportLUNsFunc;
	status = HBA_CheckLibrary(handle, &libraryIndex, &vendorHandle);
	if (status == HBA_STATUS_OK) {
			SendReportLUNsFunc = librarytable[libraryIndex].functionTable.ReportLUNsHandler;
			if (SendReportLUNsFunc != NULL) 
			{
				status = ((SendReportLUNsFunc)(vendorHandle, portWWN, pRspBuffer, RspBufferSize, pSenseBuffer, SenseBufferSize));		
			}
	}
	return 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; 
	int libraryIndex;
	HBA_UINT32 vendorHandle;

	HBASendReadCapacityFunc SendReadCapacityFunc;
	status = HBA_CheckLibrary(handle, &libraryIndex, &vendorHandle);
	if (status == HBA_STATUS_OK) {
			SendReadCapacityFunc = librarytable[libraryIndex].functionTable.ReadCapacityHandler;
			if (SendReadCapacityFunc != NULL) 
			{
				status =((SendReadCapacityFunc)(vendorHandle, portWWN, fcLUN, pRspBuffer, RspBufferSize, pSenseBuffer, SenseBufferSize));		
			}
	}
	return status;
}

