#ifndef NDTSCOMMONHALINTERNAL_H
#define NDTSCOMMONHALINTERNAL_H

#ifdef __cplusplus
extern "C" {
#endif

#include "NDTSEnums.h"
#include "NDTSCommonHALConstants.h"
#include "NDTSCommonHALErrors.h"

/*
	struct to contain low-level information on each card supported by a HAL
*/
typedef struct
{
	unsigned char busIndex, slotIndex ;
	unsigned short vendorID, deviceID ;
	unsigned long cardIndex, internalCardIndex ;
	NDTS_CardSecondaryIDs secondaryDeviceID ;
	NDTS_Boolean isActive ;
} NDTS_HAL_BoardID ;

/*
	typedefs for the functions pointers for each HAL implementation
*/
typedef NDTS_Boolean (* FPNDTS_HAL_GetBoardsIDs)(unsigned short vendorID, unsigned short deviceID, NDTS_CardSecondaryIDs cardID, NDTS_HAL_BoardID **ppBoardIDs, unsigned long numberOfBufferedBoardIDs, unsigned long *pNumberOfBoards) ;
typedef NDTS_Boolean (* FPNDTS_HAL_AddBoard)(NDTS_HAL_BoardID *pBoardID) ;
typedef NDTS_Boolean (* FPNDTS_HAL_RemoveBoard)(NDTS_HAL_BoardID *pBoardID) ;
typedef NDTS_Boolean (* FPNDTS_HAL_OpenDMAChannel)(unsigned long cardIndex) ;
typedef NDTS_Boolean (* FPNDTS_HAL_CloseDMAChannel)(unsigned long cardIndex) ;
typedef NDTS_Boolean (* FPNDTS_HAL_GetCommonBufferInfo)(unsigned long cardIndex, void **ppPhysicalAddress, unsigned long *pNumberOfBufferBytes) ;
typedef NDTS_Boolean (* FPNDTS_HAL_PerformDMARead)(unsigned long cardIndex, unsigned long localAddress, unsigned long numberOfBytes) ;
typedef NDTS_Boolean (* FPNDTS_HAL_PerformDMAWrite)(unsigned long cardIndex, unsigned long localAddress, unsigned long numberOfBytes) ;
typedef NDTS_Boolean (* FPNDTS_HAL_SetWord)(unsigned long cardIndex, unsigned long address, unsigned long value) ;
typedef NDTS_Boolean (* FPNDTS_HAL_GetWord)(unsigned long cardIndex, unsigned long address, unsigned long *pValue) ;
typedef NDTS_Boolean (* FPNDTS_HAL_BoardByteCopy)(unsigned long cardIndex, unsigned long localAddress, void *pOut, unsigned long numberOfBytes) ;
typedef NDTS_Boolean (* FPNDTS_HAL_WriteSecondaryDeviceID)(unsigned long busIndex, unsigned long slotIndex, NDTS_CardSecondaryIDs cardID) ;

/*
	Important:	ensure that the functions NDTS_HAL_ClearHALFunctionPointers and NDTS_HAL_CheckHALFunctionPointers
				know about any new functions added to this struct.
*/
typedef struct
{
	FPNDTS_HAL_GetBoardsIDs fpNDTS_HAL_GetBoardsIDs ;
	FPNDTS_HAL_AddBoard fpNDTS_HAL_AddBoard ;
	FPNDTS_HAL_RemoveBoard fpNDTS_HAL_RemoveBoard ;

	FPNDTS_HAL_OpenDMAChannel fpNDTS_HAL_OpenDMAChannel ;
	FPNDTS_HAL_CloseDMAChannel fpNDTS_HAL_CloseDMAChannel ;
	FPNDTS_HAL_GetCommonBufferInfo fpNDTS_HAL_GetCommonBufferInfo ;

	FPNDTS_HAL_PerformDMARead fpNDTS_HAL_PerformDMARead ;
	FPNDTS_HAL_PerformDMAWrite fpNDTS_HAL_PerformDMAWrite ;

	FPNDTS_HAL_SetWord fpNDTS_HAL_SetWord ;
	FPNDTS_HAL_GetWord fpNDTS_HAL_GetWord ;

	FPNDTS_HAL_BoardByteCopy fpNDTS_HAL_BoardByteCopy ;

	FPNDTS_HAL_WriteSecondaryDeviceID fpNDTS_HAL_WriteSecondaryDeviceID ;

} NDTS_HAL_Funcs ;

/*
	typedef for HAL implementation entry point function pointer
*/
typedef NDTS_Boolean (* FpNDTS_HAL_InitialiseHAL)(NDTS_HAL_Funcs *pHALFuncs) ;

/*
	struct to contain information on a HAL implementation
*/
#define NDTS_HAL_NAME_STRING_MAXIMUM_LENGTH 32
typedef struct 
{
	char pName[NDTS_HAL_NAME_STRING_MAXIMUM_LENGTH] ;
	unsigned long majorVersionNumber, minorVersionNumber ;
	NDTS_Boolean isAvailable ;
	FpNDTS_HAL_InitialiseHAL fpNDTS_HAL_InitialiseHAL ;
} NDTS_HAL_ID ;

typedef NDTS_Boolean (* FpNDTS_HAL_GetHALID)(NDTS_HAL_ID *pHALID) ;

#define NDTS_HAL_NUMBER_OF_BUFFERED_HALS 8
#define NDTS_HAL_MAXIMUM_NUMBER_OF_BOARDS_PER_HAL 8
#define NDTS_HAL_NUMBER_OF_BUFFERED_BOARD_IDS 8

typedef struct 
{
	NDTS_HAL_ID id ;
	NDTS_HAL_Funcs *pFuncs ;
	NDTS_HAL_BoardID *ppBoardIDs[NDTS_HAL_MAXIMUM_NUMBER_OF_BOARDS_PER_HAL] ;
	unsigned long numberOfActiveCards, numberOfCardsPresent ;
	NDTS_CardSecondaryIDs secondaryDeviceID ;
} NDTS_HAL_Info ;

typedef struct 
{
	NDTS_HAL_Info *ppHALInfos[NDTS_HAL_NUMBER_OF_BUFFERED_HALS] ;
	unsigned long numberOfActiveHALs ;
	NDTS_Boolean isInitialised ;
} NDTS_HAL_GlobalState ;

/*
	The global state instance
*/
extern NDTS_HAL_GlobalState halGlobalState ;

void NDTS_HAL_DLL_Initialise() ;
void NDTS_HAL_DLL_Uninitialise() ;

void NDTS_HAL_ClearHALFunctionPointers(NDTS_HAL_Funcs *pFuncs) ;
NDTS_Boolean NDTS_HAL_CheckHALFunctionPointers(const NDTS_HAL_Funcs *pFuncs) ;

void NDTS_HAL_ClearGlobalState() ;
void NDTS_HAL_FreeGlobalState() ;

NDTS_Boolean CALL_CONV NDTS_HAL_GetHALInfo(NDTS_CardSecondaryIDs cardID, NDTS_HAL_Info **ppHALInfo) ;
NDTS_Boolean CALL_CONV NDTS_HAL_GetCardInternalIndex(NDTS_HAL_Info *pHALInfo, NDTS_CardSecondaryIDs cardID, unsigned long cardIndex, unsigned long *pInternalCardIndex) ;


#ifdef __cplusplus
}
#endif

#endif