#ifndef _D64H_PRIVATE_H_
#define _D64H_PRIVATE_H_

/**********************************************
 *               GUID
 *********************************************/
// {0E66463A-B8F0-4421-B89B-89FBC6248E5E}
//DEFINE_GUID(GUID_D64H, 0xe66463a, 0xb8f0, 0x4421, 0xb8, 0x9b, 0x89, 0xfb, 0xc6, 0x24, 0x8e, 0x5e);
//#define MAX_PATH 1024 //moki

#ifdef __cplusplus
extern "C" {
#endif

/**********************************************************
 * Note: Codes 0-2047 (0-7FFh) are reserved by Microsoft
 *       Coded 2048-4095 (800h-FFFh) are reserved for OEMs
  *********************************************************/
#define D64H_IOCTL_CODE_BASE      0x864

/*
#define IOCTL_MSG( code )        CTL_CODE(                \
                                     FILE_DEVICE_UNKNOWN, \
                                     code,                \
                                     METHOD_BUFFERED,     \
                                     FILE_ANY_ACCESS      \
                                     )
*/



typedef enum _DRIVER_MSGS
{
    MSG_BOARD_RESET       = D64H_IOCTL_CODE_BASE,
    MSG_CARDID_GET,
    MSG_MAP_VIEW,
    MSG_UNMAP_VIEW,
    MSG_DI_EVENT_ATTACH,
    MSG_DI_EVENT_DETACH,
    MSG_DO_EVENT_ATTACH,
    MSG_DO_EVENT_DETACH,    
    MSG_DMA_CHANNEL_SWAP,
    MSG_DI_CONFIG,
    MSG_DO_CONFIG,    
    MSG_DI_DBL_BUF_MODE,
    MSG_DO_DBL_BUF_MODE,    
    MSG_CONTINUE_DI,
    MSG_CONTINUE_DO,    
    MSG_DI_DBL_BUF_HALF_READY,
    MSG_DO_DBL_BUF_HALF_READY,      
    MSG_DI_ASYNC_CHECK,
    MSG_DO_ASYNC_CHECK,
    MSG_DO_STATUS_CHECK,
    MSG_DI_ASYNC_CLEAR,
    MSG_DO_ASYNC_CLEAR,
    MSG_DI_PIO_READ,
    MSG_DO_PIO_WRITE,
    MSG_DO_PIO_READ,
    MSG_DO_PIO_LINE_WRITE,
    MSG_CONTINUE_PATTERN_OUT,
    MSG_DO_EXT_TRIGLINE_WRITE,
    MSG_FIFO_STATUS_GET,
    MSG_DI_COUNTER_GET,
    MSG_DI_COUNTER_SET,
    MSG_DO_COUNTER_GET,
    MSG_DO_COUNTER_SET,
    MSG_ONESHOT_DI,
    MSG_ONESHOT_DO,
    MSG_DI_DMA_STATUS,
    MSG_DO_DMA_STATUS,
    MSG_DIGITAL_FILTER_SET,           
    MSG_PLX9054_RESET,
    MSG_DMA_CONTROL,
    MSG_DMA_STATUS,
    MSG_DMA_BLOCK_CHANNEL_OPEN,
    MSG_DMA_BLOCK_TRANSFER,
    MSG_DMA_BLOCK_CHANNEL_CLOSE,
    MSG_DMA_SGL_OPEN,
    MSG_DMA_SGL_TRANSFER,
    MSG_DMA_SGL_CLOSE
} DRIVER_MSGS;


/*
#define D64H_IOCTL_BOARD_RESET                  IOCTL_MSG( MSG_BOARD_RESET )
#define D64H_ICOTL_CARDID_GET                   IOCTL_MSG( MSG_CARDID_GET )
#define D64H_IOCTL_MAP_VIEW                     IOCTL_MSG( MSG_MAP_VIEW )
#define D64H_IOCTL_UNMAP_VIEW                   IOCTL_MSG( MSG_UNMAP_VIEW )

#define D64H_IOCTL_DI_EVENT_ATTACH              IOCTL_MSG( MSG_DI_EVENT_ATTACH )
#define D64H_IOCTL_DI_EVENT_DETACH              IOCTL_MSG( MSG_DI_EVENT_DETACH )
#define D64H_IOCTL_DO_EVENT_ATTACH              IOCTL_MSG( MSG_DO_EVENT_ATTACH )
#define D64H_IOCTL_DO_EVENT_DETACH              IOCTL_MSG( MSG_DO_EVENT_DETACH )

#define D64H_IOCTL_DMA_CHANNEL_SWAP             IOCTL_MSG( MSG_DMA_CHANNEL_SWAP )

#define D64H_IOCTL_DI_CONFIG                    IOCTL_MSG( MSG_DI_CONFIG )               
#define D64H_IOCTL_DO_CONFIG                    IOCTL_MSG( MSG_DO_CONFIG )

#define D64H_IOCTL_DI_DBL_BUF_MODE       			  IOCTL_MSG( MSG_DI_DBL_BUF_MODE )
#define D64H_IOCTL_DO_DBL_BUF_MODE        			IOCTL_MSG( MSG_DO_DBL_BUF_MODE )

#define D64H_IOCTL_CONTINUE_DI                  IOCTL_MSG( MSG_CONTINUE_DI )
#define D64H_IOCTL_CONTINUE_DO                  IOCTL_MSG( MSG_CONTINUE_DO )

#define D64H_IOCTL_DI_DBL_BUF_HALF_READY        IOCTL_MSG( MSG_DI_DBL_BUF_HALF_READY )               
#define D64H_IOCTL_DO_DBL_BUF_HALF_READY        IOCTL_MSG( MSG_DO_DBL_BUF_HALF_READY )

#define D64H_IOCTL_DI_ASYNC_CHECK               IOCTL_MSG( MSG_DI_ASYNC_CHECK )
#define D64H_IOCTL_DO_ASYNC_CHECK               IOCTL_MSG( MSG_DO_ASYNC_CHECK )
#define D64H_IOCTL_DO_STATUS_CHECK              IOCTL_MSG( MSG_DO_STATUS_CHECK )

#define D64H_IOCTL_DI_ASYNC_CLEAR               IOCTL_MSG( MSG_DI_ASYNC_CLEAR )
#define D64H_IOCTL_DO_ASYNC_CLEAR               IOCTL_MSG( MSG_DO_ASYNC_CLEAR )

#define D64H_IOCTL_DI_PIO_READ                  IOCTL_MSG( MSG_DI_PIO_READ )
#define D64H_IOCTL_DO_PIO_WRITE                 IOCTL_MSG( MSG_DO_PIO_WRITE )
#define D64H_IOCTL_DO_PIO_READ                  IOCTL_MSG( MSG_DO_PIO_READ )            
#define D64H_IOCTL_DO_PIO_LINE_WRITE            IOCTL_MSG( MSG_DO_PIO_LINE_WRITE )

#define D64H_IOCTL_CONTINUE_PATTERN_OUT         IOCTL_MSG( MSG_CONTINUE_PATTERN_OUT )

#define D64H_IOCTL_DO_EXT_TRIGLINE_WRITE        IOCTL_MSG( MSG_DO_EXT_TRIGLINE_WRITE )

#define D64H_IOCTL_FIFO_STATUS_GET              IOCTL_MSG( MSG_FIFO_STATUS_GET )

#define D64H_IOCTL_DI_COUNTER_GET               IOCTL_MSG( MSG_DI_COUNTER_GET )               
#define D64H_IOCTL_DI_COUNTER_SET               IOCTL_MSG( MSG_DI_COUNTER_SET ) 

#define D64H_IOCTL_DO_COUNTER_GET               IOCTL_MSG( MSG_DO_COUNTER_GET )               
#define D64H_IOCTL_DO_COUNTER_SET               IOCTL_MSG( MSG_DO_COUNTER_SET ) 

#define D64H_IOCTL_ONESHOT_DI                   IOCTL_MSG( MSG_ONESHOT_DI )
#define D64H_IOCTL_ONESHOT_DO                   IOCTL_MSG( MSG_ONESHOT_DO )

#define D64H_IOCTL_DI_DMA_STATUS                IOCTL_MSG( MSG_DI_DMA_STATUS )
#define D64H_IOCTL_DO_DMA_STATUS                IOCTL_MSG( MSG_DO_DMA_STATUS )

#define D64H_IOCTL_DIGITAL_FILTER_SET           IOCTL_MSG( MSG_DIGITAL_FILTER_SET )

#define D64H_IOCTL_PLX9054_RESET                IOCTL_MSG( MSG_PLX9054_RESET )

#define D64H_IOCTL_DMA_CONTROL                  IOCTL_MSG( MSG_DMA_CONTROL )
#define D64H_IOCTL_DMA_STATUS                   IOCTL_MSG( MSG_DMA_STATUS )

#define D64H_IOCTL_DMA_BLOCK_CHANNEL_OPEN       IOCTL_MSG( MSG_DMA_BLOCK_CHANNEL_OPEN )
#define D64H_IOCTL_DMA_BLOCK_TRANSFER           IOCTL_MSG( MSG_DMA_BLOCK_TRANSFER )
#define D64H_IOCTL_DMA_BLOCK_CHANNEL_CLOSE      IOCTL_MSG( MSG_DMA_BLOCK_CHANNEL_CLOSE )

#define D64H_IOCTL_DMA_SGL_OPEN                 IOCTL_MSG( MSG_DMA_SGL_OPEN )
#define D64H_IOCTL_DMA_SGL_TRANSFER             IOCTL_MSG( MSG_DMA_SGL_TRANSFER )
#define D64H_IOCTL_DMA_SGL_CLOSE                IOCTL_MSG( MSG_DMA_SGL_CLOSE )
*/

#ifdef __cplusplus
}
#endif

// Event type for the event message
#ifndef DIEnd

#define DIEnd       0
#define DOEnd       0
#define DBEvent     1
#define TrigEvent   2

#endif

#ifdef _10MHz_BASE_CLOCK_
	#define D64H_BASE_CLOCK                    20000000.0
#else
	#define D64H_BASE_CLOCK                     4000000.0
#endif

#define D64H_BYTES_PER_DATA                4

#define DAQ_OPERATION_DI                   0
#define DAQ_OPERATION_DO                   1

#define DI_END_THREAD                      DIEnd    // ( (DAQ_OPERATION_DI << 4) | DIEnd )
#define DI_DBBUF_THREAD                    DBEvent  // ( (DAQ_OPERATION_DI << 4) | DBEvent )
#define DO_END_THREAD                      ( (DAQ_OPERATION_DO << 4) | DOEnd )
#define DO_DBBUF_THREAD                    ( (DAQ_OPERATION_DO << 4) | DBEvent )

#define PIOD64H_DI_USE_DMA0                0x00000000L
#define PIOD64H_DO_USE_DMA0                0x00010000L

#define CHECK_DI_BUFFER                    1
#define IGNORE_DI_BUFFER                   0

#define CHECK_DO_BUFFER                    1
#define IGNORE_DO_BUFFER                   0

#define D64HKE_RETURN_CODE_STARTS          0x9000   /* Starting D64HKE_xxx return code (-32768) */

typedef enum _D64HKE_RETURN_CODE
{
    D64HKE_ApiSuccess = D64HKE_RETURN_CODE_STARTS,
    D64HKE_ApiPowerDown,
    D64HKE_ApiDmaChannelInvalid,
    D64HKE_ApiDmaChannelUnavailable,
    D64HKE_ApiDmaDone,
    D64HKE_ApiDmaNotPaused,
    D64HKE_ApiDmaPaused,
    D64HKE_ApiDmaCommandInvalid,
    D64HKE_ApiDmaInProgress,
    D64HKE_ApiTrigSrcInvalid,
    D64HKE_ApiUnsupportedSetting,
    D64HKE_ApiUnexceptedStatus,
    D64HKE_ApiDmaIsOnPendingMode,
    D64HKE_ApiUnsupportedEventID,    
    D64HKE_ApiInvalidEventHandle, 
    D64HKE_ApiSyncModeFailed,
    D64HKE_IsOnPendingMode,
    D64HKE_ApiFifoLoopInProgress,
    D64HKE_ApiCascadedTimer2Set,      
    D64HKE_LastError               // Do not add API errors below this line
} D64HKE_RETURN_CODE;



// DMA Channel Priority Definitions
typedef enum _DMA_CHANNEL_PRIORITY
{
    Channel0Highest,
    Channel1Highest,
    Channel2Highest,
    Channel3Highest,
    Rotational
} DMA_CHANNEL_PRIORITY;

// DMA Command Definitions
/*
typedef enum _DMA_COMMAND
{
    DmaStart,
    DmaPause,
    DmaResume,
    DmaAbort,
    DmaStatus
} DMA_COMMAND;

// DMA Channel Definitions
typedef enum _DMA_CHANNEL
{
    IopChannel0,
    IopChannel1,
    IopChannel2,
    PrimaryPciChannel0,
    PrimaryPciChannel1,
    PrimaryPciChannel2,
    PrimaryPciChannel3
} DMA_CHANNEL;

// Device Management functions parameters
typedef struct _MANAGEMENTDATA
{
    U32 offset;
    U32 value;
    U32 value2;
    U32 value3;
    U32 value4;
    U32 value5;
    U32 value6;
    U32 value7;
    U32 value8;
    U32 value9;
    U32 valueA;
    U32 valueB;				

} MANAGEMENTDATA;
*/

// This structure will hold all other datatypes
typedef struct _MISCDATA
{
    U32 data[12];
} MISCDATA;

typedef struct _EVENTDATA
{
    HANDLE KeEvent[4];
    U32    dwEventID;
    U32    EventReserved[7];

} EVENTDATA;


/*
//  Used to pass all arguments down to the driver
typedef struct _IOCTLDATA
{
    U16 ReturnCode;
    union
    {
        MANAGEMENTDATA MgmtData;       
        MISCDATA       MiscData;
        EVENTDATA      EventData;         
    } u;
} IOCTLDATA;
*/

typedef struct _EVENT_CALLBACK_CFG_
{
#ifdef _WINDOWS_MESSAGE_SUPPORT_
    HANDLE             hWindowHandle;
    U32                dwMessage;
#endif

    HANDLE             hEvent;	
    HANDLE             hThread;
    U8                 bEnabled;
    U8                 bCompleted;
    void             (*CallbackAddr)(void);
} EVENT_CALLBACK_CFG;
                
typedef struct _D64H_CARD_INFO
{
	// Device specific Information
	HANDLE        hDevDriver;			     // Handle of PIO-D64H driver
	U16        wCardType;			     // Card Type: CARD_TYPE_PISO_VS600 (0x600), CARD_TYPE_PISO_PS400 (0x400), CARD_TYPE_PISO_PS200(0x200) 
	//USHORT        wCardType;			     // Card Type: CARD_TYPE_PISO_VS600 (0x600), CARD_TYPE_PISO_PS400 (0x400), CARD_TYPE_PISO_PS200(0x200) 
	U8            bCardID;			         // Card ID configured with onboard DIP-Switch
	U8            bFWMajorVer;
	U8            bFWMinorVer;	
	//char          DevName[MAX_PATH];	     // Device node name
#if 0
	S32		DevNum;
	PLX_DEVICE_OBJECT Device;
	PLX_DEVICE_KEY    DevKey_DMA;
	ULONG		dwIntCtrlReg;
	ULONG		dwDioCtrlReg;
	U32		cpldAddress;
#endif

	// settings of DI operation 
	U16           wDIDblBufMode;
	PVOID         pDIMapView[2];		     // Mapped view of DI buffer
	U32           dwDILen;               // Actual size in each Mapped buffer
	
	PVOID         pDIBuffer;
	U16           wDIAvailBufIdx;
	U32           dwDISampleCount;
	U16           wDITrigSource;
	U8            bRecodeToFile;

	// settings of DO operation
	U16           wDODblBufMode;
	PVOID         pDOMapView[2];		     // Mapped view of DO buffer	
	U32           dwDOLen;               // Actual size in each Mapped buffer	
	
	PVOID         pDOBuffer;
	U16           wDOAvailBufIdx;
	U32           dwDOSampleCount;
	U16           wDOTrigSource;

	// Event Callback Settings
	EVENT_CALLBACK_CFG DIEndEventCfg;
	EVENT_CALLBACK_CFG DIDblEventCfg;
    
	EVENT_CALLBACK_CFG DOEndEventCfg;
	EVENT_CALLBACK_CFG DODblEventCfg;
	
} D64H_CARD_INFO, *PD64H_CARD_INFO;

static short d64h_dma_channel_swap( BYTE bCardID, LONG WhoUseDMA0 );
static short d64h_foundation_check( BYTE bCardID, U16 wCheckBufDI, U16 wCheckBufDO );
static short d64h_foundation_check_with_param( BYTE bCardID, U16 wFunctionMsg, U16 wParam1, U16 wParam2, U16 wParam3, U16 wParam4, PVOID pAddress );
static short d64h_daq_setting_check( BYTE bCardID, U16 DAQOpearion, U32 dwSampleCount, double fSampleRate, U32 *pPacerValue, F64* pActualRate );
static short d64h_kernel_error_transfer( U16 wKerError );
static short d64h_get_pacervalue( double fSampleRate, U32 *pPacerValue, F64* pActualRate);
static DWORD WINAPI EventThread( PVOID pParam );
static short terminate_event_thread( BYTE bCardID, U16 wEventType );
static short d64h_do_status_check( BYTE bCardID );

#endif // _D64H_PRIVATE_H_
