#ifndef __xpci3009_KAPI__
#define __xpci3009_KAPI__


#ifndef __KERNEL__
	#error This header is intended for use in kernel context only
#endif

/* SHARED MEMORY MANAGEMENT */
int i_xpci3009_AllocateSharedMemory (struct pci_dev * pdev, uint32_t dw_Size);

int i_xpci3009_ReleaseSharedMemory (struct pci_dev * pdev, uint32_t dw_Size);

int i_xpci3009_GetSharedMemoryPointer (struct pci_dev * pdev, uint32_t dw_Size, void **pdw_Value);

/* TTL + DIGITAL INPUT + DIGITAL OUTPUT */
int  i_xpci3009_SetTTLPortConfiguration(struct pci_dev * pdev, uint8_t b_TTLPortConfiguration);

int i_xpci3009_SetDigitalOutputRegister (struct pci_dev * pdev, uint32_t dw_DigitalOutputRegister);

int  i_xpci3009_SetDigitalOutputPort(struct pci_dev * pdev);

int  i_xpci3009_SetTTLOutputPort(struct pci_dev * pdev);

int  i_xpci3009_GetDigitalOutputPort(struct pci_dev * pdev, uint32_t* pdw_DigitalOutputRegister);

int  i_xpci3009_GetTTLOutputPort(struct pci_dev * pdev, uint32_t* pdw_TTLOutputRegister);

int  i_xpci3009_ReadDigitalInputPort(struct pci_dev * pdev, uint32_t* pdw_DigitalInputRegister);

int  i_xpci3009_ReadTTLInputPort(struct pci_dev * pdev, uint32_t* pdw_TTLInputRegister);

int i_xpci3009_InitDigitalInputModuleFilter (struct pci_dev * pdev,
                                                uint8_t                                    b_FilterFlag,
                                                uint32_t                                  dw_ReloadValue);

/* ANALOG INPUT */
int  i_xpci3009_InitAnalogInput (struct pci_dev * pdev,
                                	uint8_t   b_Channel,
                                	uint8_t   b_SingleDiff,
                                	uint8_t   b_Gain,
                                	uint8_t   b_Polarity);

int  i_xpci3009_StartAnalogInput (struct pci_dev * pdev,
	                                uint8_t   b_Channel,
	  		                		uint8_t   b_ConvertTimeUnit,
			                		uint16_t   w_ConvertTime);

int i_xpci3009_ReadAnalogInputBit (struct pci_dev * pdev, uint8_t* pb_AnalogInputConversionFinished);

int i_xpci3009_ReadAnalogInputValue (struct pci_dev * pdev,
                                     uint32_t* pdw_ReadValue);

int i_xpci3009_InitAnalogInputAutoRefresh (struct pci_dev * pdev,
                                            uint8_t    b_NumberOfChannels,
                                            uint8_t*  pb_ChannelList,
			                                uint8_t*  pb_Gain,
			                                uint8_t*  pb_Polarity,
			                                uint8_t    b_SingleDiff,
                                            uint32_t  dw_NumberOfSequence,
                                            uint8_t    b_DelayMode,
                                            uint8_t    b_DelayTimeUnit,
                                            uint16_t    w_DelayTime);

int i_xpci3009_StartAnalogInputAutoRefresh (struct pci_dev * pdev,
												uint8_t   b_ConvertTimeUnit,
                                                uint16_t   w_ConvertTime);

int i_xpci3009_StopAnalogInputAutoRefresh (struct pci_dev * pdev);

int i_xpci3009_ReadAnalogInputAutoRefreshValueAndCounter (struct pci_dev * pdev,
			                                                uint32_t pdw_ReadValue[ADDIDATA_MAX_AI],
			                                                uint32_t* pdw_CycleIndex);

/** Read the specified numbers of auto refresh values.
 *
 * This function doesn't check parameters validity.
 * It is written to have a short execution time.
 * Use it only if you are sure of what you are doing.
 *
 * @param[in] pdev				: PCI Device struct.
 * @param[in] dw_NbrOfChannels	: Specified the channel number up to which is to be read (eg.: 0 to 15 dw_NbrOfChannels = 15).
 * @param[out] pdw_ReadValue	: A buffer of 32 bits unsigned integer of size ADDIDATA_MAX_AI, containing the acquired data.
 * @param[out] pdw_CycleIndex	: Current cycle index.
 *
 * @retval 0 Always 0.
 */
int i_xpci3009_FastReadAnalogInputAutoRefreshValueAndCounter (struct pci_dev * pdev,
															uint32_t dw_NbrOfChannels,
			                                                uint32_t *pdw_ReadValue,
			                                                uint32_t *pdw_CycleIndex);

int i_xpci3009_ReleaseAnalogInputAutoRefresh (struct pci_dev * pdev);

int i_xpci3009_InitAnalogInputSequence (struct pci_dev * pdev,
                                            uint8_t    b_NumberOfChannels,
                                            uint8_t*  pb_ChannelList,
			                                uint8_t*  pb_Gain,
			                                uint8_t*  pb_Polarity,
			                                uint8_t    b_SingleDiff,
                                            uint32_t  dw_NumberOfSequence,
											uint8_t    b_UseDMA,
											uint32_t  dw_NumberOfSequenceForEachInterrupt,
                                            uint8_t    b_DelayMode,
                                            uint8_t    b_DelayTimeUnit,
                                            uint16_t    w_DelayTime);

int i_xpci3009_StartAnalogInputSequence (struct pci_dev * pdev,
												uint8_t   b_ConvertTimeUnit,
                                                uint16_t   w_ConvertTime);

int i_xpci3009_StopAnalogInputSequence (struct pci_dev * pdev);

int i_xpci3009_ReleaseAnalogInputSequence (struct pci_dev * pdev);

int i_xpci3009_InitAnalogInputDMA (struct pci_dev * pdev,
                                     uint32_t                    dw_NbrOfChannel,
									 uint32_t                    dw_SequenceCounter,
									 uint32_t                    dw_InterruptSequenceCounter,
									 uint8_t					   b_AcquisitionMode);

int i_xpci3009_StartAnalogInputDMA (struct pci_dev * pdev);

int i_xpci3009_StopAnalogInputDMA (struct pci_dev * pdev);

int i_xpci3009_ReleaseAnalogInputDMA (struct pci_dev * pdev);

//void v_xpci3009_Free9054DescriptorList (struct pci_dev * pdev);
//
//void v_xpci3009_Set9054DescriptorList (struct pci_dev * pdev, uint8_t b_DMAChannel);
//
void v_xpci3009_Reset9054DescriptorList (struct pci_dev * pdev);

//void v_xpci3009_Enable9054DMATransfer (struct pci_dev * pdev);
//
//void v_xpci3009_Start9054DMATransfer (struct pci_dev * pdev);
//
void v_xpci3009_Pause9054DMATransfer (struct pci_dev * pdev);

//void v_xpci3009_Continue9054DMATransfer
//      (struct pci_dev * pdev,
//       pstr_ScatterGatherInterruptDescriptor ps_ScatterGatherDescriptor);
//
void v_xpci3009_Abort9054DMATransfer (struct pci_dev * pdev);

//void v_xpci3009_Enable9054DMATransferInterrupt
//      (struct pci_dev * pdev,
//       pstr_ScatterGatherInterruptDescriptor ps_ScatterGatherDescriptor);
//
void v_xpci3009_Disable9054DMATransferInterrupt (struct pci_dev * pdev);

int i_xpci3009_EnableDisableAnalogInputHardwareTrigger (struct pci_dev * pdev,
							                                uint8_t   b_HardwareTrigger,
															uint8_t     b_HardwareTriggerLevel,
															uint8_t     b_HardwareTriggerAction,
															uint32_t    dw_HardwareTriggerCount);

int i_xpci3009_GetAnalogInputHardwareTriggerStatus (struct pci_dev * pdev,
										              uint8_t*   pb_HardwareTriggerStatus,
										              uint32_t* pdw_HardwareTriggerCount,
										              uint8_t*   pb_HardwareTriggerState);

int i_xpci3009_EnableDisableAnalogInputSoftwareTrigger (struct pci_dev * pdev,
							                                uint8_t   b_SoftwareTrigger,
											                uint8_t   b_SoftwareTriggerAction);

int i_xpci3009_AnalogInputSoftwareTrigger (struct pci_dev * pdev);

int i_xpci3009_GetAnalogInputSoftwareTriggerStatus (struct pci_dev * pdev,
										              uint8_t*   pb_SoftwareTriggerStatus);

int i_xpci3009_EnableDisableAnalogInputHardwareGate (struct pci_dev * pdev,
							                                uint8_t   b_HardwareGate,
															uint8_t     b_HardwareGateLevel);

int i_xpci3009_GetAnalogInputHardwareGateStatus (struct pci_dev * pdev,
										              uint8_t*   pb_HardwareGateStatus);

/* ANALOG OUTPUT */
int i_xpci3009_InitAnalogOutput (struct pci_dev * pdev,
                                uint8_t   b_Channel,
                                uint8_t   b_VoltageMode);

int i_xpci3009_ReadAnalogOutputBit (struct pci_dev * pdev, uint8_t* pb_AnalogOutputConversionFinished);

int i_xpci3009_WriteAnalogOutputValue (struct pci_dev * pdev,
										uint8_t   b_Channel,
										uint32_t dw_WriteValue);

/** Writes the value of the analog output channel.
 *
 * This function doesn't check parameters validity.
 * It is written to have a short execution time.
 * Use it only if you are sure of what you are doing.
 *
 * @param[in] pdev			: PCI Device struct.
 * @param[in] b_Channel		: channel number of the output to be initialise.
 * @param[in] dw_WriteValue	: Value to write on the analog output channel.

 * @retval 0 Always 0.
 */
int i_xpci3009_FastWriteAnalogOutputValue (struct pci_dev * pdev, uint8_t b_Channel, uint32_t dw_WriteValue);

/* TIMER */
int  i_xpci3009_InitTimer                      (struct pci_dev *pdev,
                                                         uint8_t   b_TimerNumber,
                                                         uint8_t   b_TimerMode,
                                                         uint8_t   b_TimerTimeUnit,
                                                         uint32_t dw_ReloadValue);

int  i_xpci3009_ReleaseTimer                    (struct pci_dev *pdev,
                                                         uint8_t   b_TimerNumber);

int  i_xpci3009_StartTimer                    (struct pci_dev *pdev,
                                                         uint8_t   b_TimerNumber);

int  i_xpci3009_StartAllTimers                    (struct pci_dev *pdev);

int  i_xpci3009_TriggerTimer                    (struct pci_dev *pdev,
                                                         uint8_t   b_TimerNumber);

int  i_xpci3009_TriggerAllTimers                    (struct pci_dev *pdev);

int  i_xpci3009_StopTimer                    (struct pci_dev *pdev,
                                                         uint8_t   b_TimerNumber);

int  i_xpci3009_StopAllTimers                    (struct pci_dev *pdev);

int  i_xpci3009_ReadTimerValue  (struct pci_dev *pdev,
                                    uint8_t     b_TimerNumber,
                                    uint32_t* pdw_TimerValue);

int  i_xpci3009_ReadTimerStatus  (struct pci_dev *pdev,
                                     uint8_t     b_TimerNumber,
                                     uint8_t* pb_TimerStatus,
                                     uint8_t* pb_SoftwareTriggerStatus,
                                     uint8_t* pb_HardwareTriggerStatus);

int  i_xpci3009_EnableDisableTimerInterrupt          (struct pci_dev *pdev,
                                                         uint8_t   b_TimerNumber,
                                                         uint8_t   b_InterruptFlag);

int  i_xpci3009_EnableDisableTimerHardwareOutput     (struct pci_dev *pdev,
                                                        uint8_t   b_TimerNumber,
														uint8_t   b_OutputFlag,
                                                        uint8_t   b_OutputLevel);

int  i_xpci3009_GetTimerHardwareOutputStatus  (struct pci_dev *pdev,
			                                    uint8_t     b_TimerNumber,
			                                    uint8_t*    pb_HardwareOutputStatus);

/* COUNTER */
int  i_xpci3009_InitCounter                      (struct pci_dev *pdev,
						                                uint8_t     b_CounterNumber,
														uint8_t   b_DirectionSelection,
														uint8_t   b_LevelSelection,
														uint32_t dw_ReloadValue);

int  i_xpci3009_ReleaseCounter                    (struct pci_dev *pdev,
                                                         uint8_t   b_CounterNumber);

int  i_xpci3009_StartCounter                    (struct pci_dev *pdev,
                                                         uint8_t   b_CounterNumber);

int  i_xpci3009_StartAllCounters                    (struct pci_dev *pdev);

int  i_xpci3009_TriggerCounter                    (struct pci_dev *pdev,
                                                         uint8_t   b_CounterNumber);

int  i_xpci3009_TriggerAllCounters                    (struct pci_dev *pdev);

int  i_xpci3009_StopCounter                    (struct pci_dev *pdev,
                                                         uint8_t   b_CounterNumber);

int  i_xpci3009_StopAllCounters                    (struct pci_dev *pdev);

int  i_xpci3009_ClearCounter                    (struct pci_dev *pdev,
                                                         uint8_t   b_CounterNumber);

int  i_xpci3009_ReadCounterValue  (struct pci_dev *pdev,
									uint8_t   b_CounterNumber,
                                    uint32_t* pdw_CounterValue);

int  i_xpci3009_ReadCounterStatus  (struct pci_dev *pdev,
										uint8_t   b_CounterNumber,
										uint8_t* pb_CounterStatus,
										uint8_t* pb_SoftwareTriggerStatus,
										uint8_t* pb_HardwareTriggerStatus,
										uint8_t* pb_SoftwareClearStatus);

int  i_xpci3009_EnableDisableCounterInterrupt          (struct pci_dev *pdev,
															uint8_t   b_CounterNumber,
															uint8_t   b_InterruptFlag);

int  i_xpci3009_EnableDisableCounterHardwareOutput     (struct pci_dev *pdev,
                                                        uint8_t   b_CounterNumber,
														uint8_t   b_OutputFlag,
                                                        uint8_t   b_OutputLevel);

int  i_xpci3009_GetCounterHardwareOutputStatus  (struct pci_dev *pdev,
			                                    uint8_t     b_CounterNumber,
			                                    uint8_t*    pb_HardwareOutputStatus);

/* WATCHDOG */
int  i_xpci3009_InitWatchdog                      (struct pci_dev *pdev,
													uint8_t   b_WatchdogNumber,
													uint8_t   b_WatchdogTimeUnit,
													uint32_t dw_ReloadValue);

int  i_xpci3009_ReleaseWatchdog                    (struct pci_dev *pdev,
													uint8_t   b_WatchdogNumber);

int  i_xpci3009_StartWatchdog                    (struct pci_dev *pdev,
													uint8_t   b_WatchdogNumber);

int  i_xpci3009_StartAllWatchdogs                    (struct pci_dev *pdev);

int  i_xpci3009_TriggerWatchdog                    (struct pci_dev *pdev,
													uint8_t   b_WatchdogNumber);

int  i_xpci3009_TriggerAllWatchdogs                    (struct pci_dev *pdev);

int  i_xpci3009_StopWatchdog                    (struct pci_dev *pdev,
													uint8_t   b_WatchdogNumber);

int  i_xpci3009_StopAllWatchdogs                    (struct pci_dev *pdev);

int  i_xpci3009_ReadWatchdogValue  (struct pci_dev *pdev,
										uint8_t   b_WatchdogNumber,
										uint32_t* pdw_WatchdogValue);

int  i_xpci3009_ReadWatchdogStatus  (struct pci_dev *pdev,
										uint8_t   b_WatchdogNumber,
										uint8_t* pb_WatchdogStatus,
										uint8_t* pb_SoftwareTriggerStatus,
										uint8_t* pb_HardwareTriggerStatus);

int  i_xpci3009_EnableDisableWatchdogInterrupt          (struct pci_dev *pdev,
															uint8_t   b_WatchdogNumber,
															uint8_t   b_InterruptFlag);

int  i_xpci3009_EnableDisableWatchdogHardwareOutput     (struct pci_dev *pdev,
                                                        uint8_t   b_WatchdogNumber,
														uint8_t   b_OutputFlag,
                                                        uint8_t   b_OutputLevel);

int  i_xpci3009_GetWatchdogHardwareOutputStatus  (struct pci_dev *pdev,
			                                    uint8_t     b_WatchdogNumber,
			                                    uint8_t*    pb_HardwareOutputStatus);



/** Get interrupt value.
 *
 * @param [in]	mask	Interrupt source has to be given to select the right value management.
 *
 * @param [out]	pdev	The handle of the board that generates the interrupt.
 * @param [out]	mask	The board minor number.<br>
 * 						If 0x7ffffffe, fifo is empty.
 * @param [out]	value	Number of buffer and number of value for each buffer, buffer address.
 * @param [out]	shm		A pointer on the shared memory.
 *
 * @retval	0	No error.
 */
int i_xpci3009_TestInterrupt(struct pci_dev * pdev, uint32_t *mask, uint32_t *value, uint16_t **shm);

int xpci3009_SetIntCallback( void(*InterruptCallback) (struct pci_dev * pdev, uint32_t dw_InterruptSource));

int xpci3009_ResetIntCallback(void);

/** Get the number of analog input channels.
 *
 * @param [in] pdev				: The device to use.
 * @param [in] b_SingleDiff		: The mode of the input channels ADDIDATA_DIFFERENTIAL or ADDIDATA_SINGLE.
 *
 * @param [out] b_NbrChannels	: The number of analog input channels.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 */
int i_xpci3009_GetNumberOfAnalogInputChannels (struct pci_dev *pdev, uint8_t b_SingleDiff, uint8_t *b_NbrChannels);

/** Get the number of analog output channels.
 *
 * @WARNING:	To get the real number of channels of the APCI-3501<br>
 * 				you have to edit _makefile:<br>
 * 				echo "//#define USE_ADDIEEPROM	1" >> xpci3009-options.h; \
 * 				and remove // in the previous line.
 * 				This add functions to read the board header.
 * 				Once USE_ADDIEEPROM is defined you have to load
 * 				AddiEEPROM module before the xpci3009 module.
 *
 * @param [in] pdev				: The device to use.
 * @param [in] b_NbrChannels	: The number of analog output channels.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 */
int i_xpci3009_GetNumberOfAnalogOutputChannels (struct pci_dev *pdev, uint8_t *b_NbrChannels);

/** find a xpci3009 device of a given index in the system PCI device list.
 * @param index The index (!!minor number!!) to lookup
 * @return A pointer to the device or NULL
 *
 * This function is used to map a minor number to an actual device.
 */
extern struct pci_dev * xpci3009_lookup_board_by_index(unsigned int index);

//------------------------------------------------------------------------------
//					APCI 1710 functionalities related
//------------------------------------------------------------------------------

/** Read modules configuration (ID).
 *
 * @param [in] pdev          : The device to read configuration from.
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 *
 * list of module ID
 *
 * list of different types of modules:
 * #define      XPCI3009_INCREMENTAL_COUNTER	0x53430000UL
 * #define      XPCI3009_SSI_COUNTER			0x53490000UL
 * #define      XPCI3009_TTL_IO					0x544C0000UL
 * #define      XPCI3009_DIGITAL_IO				0x44490000UL
 * #define      XPCI3009_82X54_TIMER			0x49430000UL
 * #define      XPCI3009_CHRONOMETER			0x43480000UL
 * #define      XPCI3009_PULSE_ENCODER			0x495A0000UL
 * #define      XPCI3009_TOR_COUNTER			0x544F0000UL
 * #define      XPCI3009_PWM					0x50570000UL
 * #define      XPCI3009_ETM					0x45540000UL
 * #define      XPCI3009_CDA					0x43440000UL
 */
int   i_XPCI3009_ReadModulesConfiguration (struct pci_dev *pdev);

int  i_XPCI3009_DumpModulesFunctionalities (struct pci_dev *pdev);


//------------------------------------------------------------------------------

/** Initialize the counter.
 *
 * Configure the counter operating mode from selected module (b_ModulNbr).
 * You must calling this function be for you call any other function
 * witch access of counters.
   @verbatim
+----------------------------------------------------------------------------+
|                          Counter range                                     |
|                          -------------                                     |
| +------------------------------------+-----------------------------------+ |
| | Parameter       Passed value       |        Description                | |
| |------------------------------------+-----------------------------------| |
| |b_ModulNbr   XPCI3009_16BIT_COUNTER |  The module is configured for     | |
| |                                    |  two 16-bit counter.              | |
| |                                    |  - b_FirstCounterModus and        | |
| |                                    |    b_FirstCounterOption           | |
| |                                    |    configure the first 16 bit     | |
| |                                    |    counter.                       | |
| |                                    |  - b_SecondCounterModus and       | |
| |                                    |    b_SecondCounterOption          | |
| |                                    |    configure the second 16 bit    | |
| |                                    |    counter.                       | |
| |------------------------------------+-----------------------------------| |
| |b_ModulNbr   XPCI3009_32BIT_COUNTER |  The module is configured for one | |
| |                                    |  32-bit counter.                  | |
| |                                    |  - b_FirstCounterModus and        | |
| |                                    |    b_FirstCounterOption           | |
| |                                    |    configure the 32 bit counter.  | |
| |                                    |  - b_SecondCounterModus and       | |
| |                                    |    b_SecondCounterOption          | |
| |                                    |    are not used and have no       | |
| |                                    |    importance.                    | |
| +------------------------------------+-----------------------------------+ |
|                                                                            |
|                      Counter operating mode                                |
|                      ----------------------                                |
|                                                                            |
| +--------------------+-------------------------+-------------------------+ |
| |    Parameter       |     Passed value        |    Description          | |
| |--------------------+-------------------------+-------------------------| |
| |b_FirstCounterModus | XPCI3009_QUADRUPLE_MODE | In the quadruple mode,  | |
| |       or           |                         | the edge analysis       | |
| |b_SecondCounterModus|                         | circuit generates a     | |
| |                    |                         | counting pulse from     | |
| |                    |                         | each edge of 2 signals  | |
| |                    |                         | which are phase shifted | |
| |                    |                         | in relation to each     | |
| |                    |                         | other.                  | |
| |--------------------+-------------------------+-------------------------| |
| |b_FirstCounterModus |   XPCI3009_DOUBLE_MODE  | Functions in the same   | |
| |       or           |                         | way as the quadruple    | |
| |b_SecondCounterModus|                         | mode, except that only  | |
| |                    |                         | two of the four edges   | |
| |                    |                         | are analysed per        | |
| |                    |                         | period                  | |
| |--------------------+-------------------------+-------------------------| |
| |b_FirstCounterModus |   XPCI3009_SIMPLE_MODE  | Functions in the same   | |
| |       or           |                         | way as the quadruple    | |
| |b_SecondCounterModus|                         | mode, except that only  | |
| |                    |                         | one of the four edges   | |
| |                    |                         | is analysed per         | |
| |                    |                         | period.                 | |
| |--------------------+-------------------------+-------------------------| |
| |b_FirstCounterModus |   XPCI3009_DIRECT_MODE  | In the direct mode the  | |
| |       or           |                         | both edge analysis      | |
| |b_SecondCounterModus|                         | circuits are inactive.  | |
| |                    |                         | The inputs A, B in the  | |
| |                    |                         | 32-bit mode or A, B and | |
| |                    |                         | C, D in the 16-bit mode | |
| |                    |                         | represent, each, one    | |
| |                    |                         | clock pulse gate circuit| |
| |                    |                         | There by frequency and  | |
| |                    |                         | pulse duration          | |
| |                    |                         | measurements can be     | |
| |                    |                         | performed.              | |
| +--------------------+-------------------------+-------------------------+ |
|                                                                            |
|                                                                            |
|       IMPORTANT!                                                           |
|       If you have configured the module for two 16-bit counter, a mixed    |
|       mode with a counter in quadruple/double/single mode                  |
|       and the other counter in direct mode is not possible!                |
|                                                                            |
|                                                                            |
|         Counter operating option for quadruple/double/simple mode          |
|         ---------------------------------------------------------          |
|                                                                            |
| +----------------------+-------------------------+------------------------+|
| |       Parameter      |     Passed value        |  Description           ||
| |----------------------+-------------------------+------------------------||
| |b_FirstCounterOption  | XPCI3009_HYSTERESIS_ON  | In both edge analysis  ||
| |        or            |                         | circuits is available  ||
| |b_SecondCounterOption |                         | one hysteresis circuit.||
| |                      |                         | It suppresses each     ||
| |                      |                         | time the first counting||
| |                      |                         | pulse after a change   ||
| |                      |                         | of rotation.           ||
| |----------------------+-------------------------+------------------------||
| |b_FirstCounterOption  | XPCI3009_HYSTERESIS_OFF | The first counting     ||
| |       or             |                         | pulse is not suppress  ||
| |b_SecondCounterOption |                         | after a change of      ||
| |                      |                         | rotation.              ||
| +----------------------+-------------------------+------------------------+|
|                                                                            |
|                                                                            |
|       IMPORTANT!                                                           |
|       This option are only avaible if you have selected the direct mode.   |
|                                                                            |
|                                                                            |
|               Counter operating option for direct mode                     |
|               ----------------------------------------                     |
|                                                                            |
| +----------------------+--------------------+----------------------------+ |
| |      Parameter       |     Passed value   |       Description          | |
| |----------------------+--------------------+----------------------------| |
| |b_FirstCounterOption  | XPCI3009_INCREMENT | The counter increment for  | |
| |       or             |                    | each counting pulse        | |
| |b_SecondCounterOption |                    |                            | |
| |----------------------+--------------------+----------------------------| |
| |b_FirstCounterOption  | XPCI3009_DECREMENT | The counter decrement for  | |
| |       or             |                    | each counting pulse        | |
| |b_SecondCounterOption |                    |                            | |
| +----------------------+--------------------+----------------------------+ |
+----------------------------------------------------------------------------+
   @endverbatim

 * @param [in] pdev                  : The device to initialize.
 * @param [in] b_ModulNbr            : Module number toconfigure (0 to 3).
 * @param [in] b_CounterRange        : Selection form counter range.
 * @param [in] b_FirstCounterModus   : First counter operating mode.
 * @param [in] b_FirstCounterOption  : First counter option.
 * @param [in] b_SecondCounterModus  : Second counter operating mode.
 * @param [in] b_SecondCounterOption : Second counter option.
 *
 * retval 0: No error.
 * retval 1: parameter pdev is NULL.
 * retval 2: The module is not a counter module.
 * retval 3: The selected counter range is wrong.
 * retval 4: The selected first counter operating mode is wrong.
 * retval 5: The selected first counter operating option is wrong.
 * retval 6: The selected second counter operating mode is wrong.
 * retval 7: The selected second counter operating option is wrong.
 */
int   i_XPCI3009_InitCounter (struct pci_dev *pdev,
                              uint8_t b_ModulNbr,
                              uint8_t b_CounterRange,
                              uint8_t b_FirstCounterModus,
                              uint8_t b_FirstCounterOption,
                              uint8_t b_SecondCounterModus,
                              uint8_t b_SecondCounterOption);

//------------------------------------------------------------------------------

/** Clear the counter value.
 *
 * Clear the counter value from selected module (b_ModulNbr)
 *
 * @param [in] pdev          : The device to initialize.
 * @param [in] b_ModulNbr    : Module number to configure (0 to 3).
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: The selected module number parameter is wrong.
 * @retval 3: Counter not initialised see function "i_XPCI3009_InitCounter".
 */
int   i_XPCI3009_ClearCounterValue (struct pci_dev *pdev, uint8_t b_ModulNbr);

//------------------------------------------------------------------------------

/** Clear all counter value.
 *
 * @param [in] pdev          : The device to initialize.
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: No counter module found.
 */
int   i_XPCI3009_ClearAllCounterValue (struct pci_dev *pdev);

//------------------------------------------------------------------------------

/** Latch the value from selected module.
 *
 * Latch the value from selected module (b_ModulNbr)
 * in to the selected latch register (b_LatchReg).
 *
 * @param [in] pdev          : The device to initialize.
 * @param [in] b_ModulNbr    : Module number to configure (0 to 3).
 * @param [in] b_LatchReg    : Selected latch register <br>
 *                             0 : for the first latch register. <br>
 *                             1 : for the second latch register.
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: No counter module found.
 * @retval 3: Counter not initialised see function "i_XPCI3009_InitCounter".
 * @retval 4: The selected latch register parameter is wrong.
 */
int   i_XPCI3009_LatchCounter (struct pci_dev *pdev,
                               uint8_t b_ModulNbr,
                               uint8_t b_LatchReg);

//------------------------------------------------------------------------------

/** Read the latch register status from selected module.
 *
 * Read the latch register status from selected module
 * (b_ModulNbr) and selected latch register (b_LatchReg).
 *
 * @param [in] pdev          : The device to initialize.
 * @param [in] b_ModulNbr    : Module number to configure (0 to 3).
 * @param [in] b_LatchReg    : Selected latch register <br>
 *                             0 : for the first latch register. <br>
 *                             1 : for the second latch register.
 *
 * @param [out] pb_LatchStatus : Latch register status. <br>
 *                               0 : No latch occur.
 *                               1 : A software latch occur.
 *                               2 : A hardware latch occur.
 *                               3 : A software and hardware latch occur.
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: No counter module found.
 * @retval 3: Counter not initialised see function "i_XPCI3009_InitCounter".
 * @retval 4: The selected latch register parameter is wrong.
 */
int   i_XPCI3009_ReadLatchRegisterStatus (struct pci_dev *pdev,
                                          uint8_t b_ModulNbr,
                                          uint8_t b_LatchReg,
                                          uint8_t* pb_LatchStatus);

//------------------------------------------------------------------------------

/** Read the latch register value.
 *
 * Read the latch register value from selected module
 * (b_ModulNbr) and selected latch register (b_LatchReg).
 *
 * @param [in] pdev          : The device to initialize.
 * @param [in] b_ModulNbr    : Module number to configure (0 to 3).
 * @param [in] b_LatchReg    : Selected latch register <br>
 *                             0 : for the first latch register. <br>
 *                             1 : for the second latch register.
 *
 * @param [out] pul_LatchValue : Latch register value.
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: No counter module found.
 * @retval 3: Counter not initialised see function "i_XPCI3009_InitCounter".
 * @retval 4: The selected latch register parameter is wrong.
 */
int   i_XPCI3009_ReadLatchRegisterValue (struct pci_dev *pdev,
                                         uint8_t     b_ModulNbr,
                                         uint8_t     b_LatchReg,
                                         uint32_t * pul_LatchValue);

//------------------------------------------------------------------------------

/** Enable the latch interrupt.
 *
 * Enable the latch interrupt from selected module
 * (b_ModulNbr). Each software or hardware latch occur a interrupt.
 *
 * @param [in] pdev          : The device to initialize.
 * @param [in] b_ModulNbr    : Module number to configure (0 to 3).
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: No counter module found.
 * @retval 3: Counter not initialised see function "i_XPCI3009_InitCounter".
 * @retval 4: Interrupt routine not installed see function "i_XPCI3009_SetBoardIntRoutine".
 */
int   i_XPCI3009_EnableLatchInterrupt (struct pci_dev *pdev, uint8_t b_ModulNbr);

//------------------------------------------------------------------------------

/** Disable the latch interrupt.
 *
 * Disable the latch interrupt from selected module (b_ModulNbr).
 *
 * @param [in] pdev          : The device to initialize.
 * @param [in] b_ModulNbr    : Module number to configure (0 to 3).
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: No counter module found.
 * @retval 3: Counter not initialised see function "i_XPCI3009_InitCounter".
 * @retval 4: Interrupt routine not installed see function "i_XPCI3009_SetBoardIntRoutine".
 */
int   i_XPCI3009_DisableLatchInterrupt (struct pci_dev *pdev, uint8_t b_ModulNbr);

//------------------------------------------------------------------------------

/** Latch the selected 16-Bit counter.
 *
 * Latch the selected 16-Bit counter (b_SelectedCounter)
 * from selected module (b_ModulNbr) in to the first
 * latch register and return the latched value.
 *
 * @param [in] pdev              : The device to initialize.
 * @param [in] b_ModulNbr        : Module number to configure (0 to 3).
 * @param [in] b_SelectedCounter : Selected 16-Bit counter (0 or 1).
 *
 * @param [out] pui_CounterValue : 16-Bit counter value.
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: No counter module found.
 * @retval 3: Counter not initialised see function "i_XPCI3009_InitCounter".
 * @retval 4: The selected 16-Bit counter parameter is wrong.
 */
int   i_XPCI3009_Read16BitCounterValue (struct pci_dev *pdev,
                                        uint8_t    b_ModulNbr,
                                        uint8_t    b_SelectedCounter,
                                        uint32_t * pui_CounterValue);

//------------------------------------------------------------------------------

/** Latch the 32-Bit counter.
 *
 * Latch the 32-Bit counter from selected module
 * (b_ModulNbr) in to the first latch register and return the latched value.
 *
 * @param [in] pdev              : The device to initialize.
 * @param [in] b_ModulNbr        : Module number to configure (0 to 3).
 *
 * @param [out] pui_CounterValue : 32-Bit counter value.
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: No counter module found.
 * @retval 3: Counter not initialised see function "i_XPCI3009_InitCounter".
 */
int   i_XPCI3009_Read32BitCounterValue (struct pci_dev *pdev,
                                        uint8_t      b_ModulNbr,
                                        uint32_t * pul_CounterValue);

//------------------------------------------------------------------------------

/** Write a 16-Bit value.
 *
 * Write a 16-Bit value (ui_WriteValue) in to the selected
 * 16-Bit counter (b_SelectedCounter) from selected module (b_ModulNbr).
 *
 * @param [in] pdev              : The device to initialize.
 * @param [in] b_ModulNbr        : Module number to configure (0 to 3).
 * @param [in] b_SelectedCounter : Selected 16-Bit counter (0 or 1).
 * @param [in] ui_WriteValue     : 16-Bit write value : (0x0 - 0xFFFF)
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: No counter module found.
 * @retval 3: Counter not initialised see function "i_XPCI3009_InitCounter".
 * @retval 4: The selected 16-Bit counter parameter is wrong.
 * @retval 5: The given ui_WriteValue value is not in the correct range.
 */
int   i_XPCI3009_Write16BitCounterValue (struct pci_dev *pdev,
                                         uint8_t  b_ModulNbr,
                                         uint8_t  b_SelectedCounter,
                                         uint32_t ui_WriteValue);

//------------------------------------------------------------------------------

/** Write a 32-Bit value.
 *
 * Write a 32-Bit value (ui_WriteValue) in to the selected module (b_ModulNbr).
 *
 * @param [in] pdev              : The device to initialize.
 * @param [in] b_ModulNbr        : Module number to configure (0 to 3).
 * @param [in] ul_WriteValue     : 32-Bit write value.
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: No counter module found.
 * @retval 3: Counter not initialised see function "i_XPCI3009_InitCounter".
 */
int   i_XPCI3009_Write32BitCounterValue (struct pci_dev *pdev,
                                         uint8_t   b_ModulNbr,
                                         uint32_t ul_WriteValue);

//------------------------------------------------------------------------------

/** Set the 32-Bit compare value.
 *
 * Set the 32-Bit compare value. At that moment that the
 * incremental counter arrive to the compare value
 * (ui_CompareValue) a interrupt is generated.
 *
 * @param [in] pdev              : The device to initialize.
 * @param [in] b_ModulNbr        : Module number to configure (0 to 3).
 * @param [in] ui_CompareValue   : 32-Bit compare value.
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: No counter module found.
 * @retval 3: Counter not initialised see function "i_XPCI3009_InitCounter".
 */
int   i_XPCI3009_InitCompareLogic (struct pci_dev *pdev,
                                   uint8_t   b_ModulNbr,
                                   uint32_t  ui_CompareValue);

//------------------------------------------------------------------------------

/** Enable the 32-Bit compare logic.
 *
 * Enable the 32-Bit compare logic. At that moment that
 * the incremental counter arrive to the compare value a
 * interrupt is generated.
 *
 * @param [in] pdev              : The device to initialize.
 * @param [in] b_ModulNbr        : Module number to configure (0 to 3).
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: No counter module found.
 * @retval 3: Counter not initialised see function "i_XPCI3009_InitCounter".
 * @retval 4: Compare logic not initialised. See function "i_XPCI3009_InitCompareLogic".
 * @retval 5: Interrupt function not initialised. See function "i_XPCI3009_SetBoardIntRoutine".
 */
int   i_XPCI3009_EnableCompareLogic (struct pci_dev *pdev,
                                     uint8_t   b_ModulNbr);

//------------------------------------------------------------------------------

/** Disable the 32-Bit compare logic.
 *
 * @param [in] pdev              : The device to initialize.
 * @param [in] b_ModulNbr        : Module number to configure (0 to 3).
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: No counter module found.
 * @retval 3: Counter not initialised see function "i_XPCI3009_InitCounter".
 * @retval 4: Compare logic not initialised. See function "i_XPCI3009_InitCompareLogic".
 */
int   i_XPCI3009_DisableCompareLogic  (struct pci_dev *pdev,
                                       uint8_t   b_ModulNbr);

//------------------------------------------------------------------------------

/** Set the 32-Bit compare value.
 *
 * Set the 32-Bit compare value. At that moment that the
 * incremental counter arrive to the compare value
 * (ui_CompareValue) a interrupt is generated and the TTL
 * output mask (ui_OutputMask is setting).
 *
 * @param [in] pdev              : The device to initialize.
 * @param [in] b_ModulNbr        : Module number to configure (0 to 3).
 * @param [in] ui_CompareValue   : 32-Bit compare value.
 * @param [in] ui_OutputMask     : TTL output mask.
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: No counter module found.
 * @retval 3: The selected functionality is not available.
 * @retval 4: FIFO full.
 */
int   i_XPCI3009_SetCompareValue (struct pci_dev *pdev,
                                  uint8_t   b_ModulNbr,
                                  uint32_t  ui_CompareValue,
                                  uint32_t  ui_OutputMask);

//------------------------------------------------------------------------------

/** Compare logic TTL port selection.
 *
 * @param [in] pdev              : The device to initialize.
 * @param [in] b_ModulNbr        : Module number to configure (0 to 3).
 * @param [in] b_PortSelection   : 0 : Port 0 selected. <br>
 *                                 1 : Port 1 selected.
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: No counter module found.
 * @retval 3: The selected functionality is not available.
 * @retval 4: Port selection error.
 */
int   i_XPCI3009_SetComparePort	(struct pci_dev *pdev,
                                 uint8_t   b_ModulNbr,
                                 uint8_t   b_PortSelection);

//------------------------------------------------------------------------------

/** Compare logic watchdog initialisation and activation.
 *
 * @param [in] pdev              : The device to initialize.
 * @param [in] b_ModulNbr        : Module number to configure (0 to 3).
 * @param [in] ui_WatchdogTime   : Watchdog time (1 to 65535ms).
 * @param [in] ui_OutputMask     : XPCI3009_ENABLE : Enable the watchdog. <br>
 *                                 XPCI3009_DISABLE: Disable the watchdog.
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: No counter module found.
 * @retval 3: The selected functionality is not available.
 * @retval 4: Selected watchdog time error.
 * @retval 5: Enable/Disable flag selection error.
 */
int   i_XPCI3009_InitCompareWatchdog (struct pci_dev *pdev,
                                      uint8_t   b_ModulNbr,
                                      uint32_t  ui_WatchdogTime,
                                      uint8_t   b_EnableDisable);

//------------------------------------------------------------------------------

/** Get the compare watchdog status.
 *
 * @param [in] pdev              : The device to initialize.
 * @param [in] b_ModulNbr        : Module number to configure (0 to 3).
 *
 * @param pb_Status : 0: No watchdog overflow occur. <br>
 *                    1: Watchdog overflow occur.
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: No counter module found.
 * @retval 3: The selected functionality is not available.
 * @retval 4: Watchdog not active.
 */
int   i_XPCI3009_GetCompareWatchdogStatus (struct pci_dev *pdev,
                                           uint8_t   b_ModulNbr,
                                           uint8_t* pb_Status);

//------------------------------------------------------------------------------

/** Clear the compare FIFO.
 *
 * @param [in] pdev              : The device to initialize.
 * @param [in] b_ModulNbr        : Module number to configure (0 to 3).
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: No counter module found.
 * @retval 3: The selected functionality is not available.
 */
int   i_XPCI3009_ClearCompareFIFO (struct pci_dev *pdev, uint8_t b_ModulNbr);

//------------------------------------------------------------------------------

/** Change the counter direction.
 *
 * @param [in] pdev              : The device to initialize.
 * @param [in] b_ModulNbr        : Module number to configure (0 to 3).
 * @param [in] b_Direction       : 0 : not invert.
 *                                 1 : invert.
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: The selected module number is wrong.
 * @retval 3: The selected functionality is not available.
 * @retval 4: The selected direction is wrong.
 */
int   i_XPCI3009_ChangeCounterDirection (struct pci_dev *pdev,
                                         uint8_t   b_ModulNbr,
                                         uint8_t   b_Direction);

//------------------------------------------------------------------------------

/** Sets the digital output H.
 *
 * Sets the digital output H. Setting an output means setting an ouput high.
 *
 * @param [in] pdev              : The device to initialize.
 * @param [in] b_ModulNbr        : Module number to configure (0 to 3).
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: The selected module number is wrong.
 * @retval 3: Counter not initialised see function "i_XPCI3009_InitCounter".
 */
int	i_XPCI3009_SetDigitalChlOn (struct pci_dev *pdev, uint8_t b_ModulNbr);

//------------------------------------------------------------------------------

/** Resets the digital output H.
 *
 * Resets the digital output H. Resetting an output means setting an ouput low.
 *
 * @param [in] pdev              : The device to initialize.
 * @param [in] b_ModulNbr        : Module number to configure (0 to 3).
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: The selected module number is wrong.
 * @retval 3: Counter not initialised see function "i_XPCI3009_InitCounter".
 */
int	i_XPCI3009_SetDigitalChlOff (struct pci_dev *pdev, uint8_t b_ModulNbr);


//------------------------------------------------------------------------------
/** Returns the counter progress latched status after a index interrupt occur.
 *
 * @param [in] pdev          : The device
 * @param [in] b_ModulNbr    : Module number to configure (0 to 3).
 *
 * @param [out] pul_UDStatus  : 0 : Counter progress in the selected mode down
								1 : Counter progress in the selected mode up
								2 : No index interrupt occur
 *
 * @retval	0: No error
 *			1: parameter pdev is NULL.
 *			2: No counter module found
 *			3: Counter not initialised see function "i_XPCI3009_InitCounter"
 * 			4: Interrupt function not initialised. See function "i_XPCI3009_SetBoardIntRoutine"
 */
int i_XPCI3009_GetInterruptUDLatchedStatus  (	struct pci_dev * pdev, uint8_t b_ModulNbr, uint8_t * pul_UDStatus);

//------------------------------------------------------------------------------
/** Initialise the index corresponding to the selected
module (b_ModulNbr). If a INDEX flag occur, you have
the possibility to clear the 32-Bit counter or to latch
the current 32-Bit value in to the first latch
register. The b_IndexOperation parameter give the
possibility to choice the INDEX action.
If you have enabled the automatic mode, each INDEX
action is cleared automatically, else you must read
the index status ("CMD_XPCI3009_GetIndexStatus")
after each INDEX action.

 *
 * @param [in] b_ModulNbr    : Module number (0 to 3).
 * @param [in] b_ReferenceAction : 	Determine if the reference must set or no for the acceptance from index
 * 									XPCI3009_ENABLE : Reference must be set for accepted the index
 * 									XPCI3009_DISABLE : Reference have no importance
 * @param [in] b_IndexOperation  : (XPCI3009_HIGH_EDGE_LATCH_COUNTER, XPCI3009_LOW_EDGE_LATCH_COUNTER, XPCI3009_HIGH_EDGE_CLEAR_COUNTER, XPCI3009_LOW_EDGE_CLEAR_COUNTER, XPCI3009_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER, XPCI3009_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)
 *
 * @param [in] b_AutoMode : Enable or disable the automatic index reset : (XPCI3009_ENABLE, XPCI3009_DISABLE)
 *
 * @param [in] b_InterruptEnable : Enable or disable the interrupt : (XPCI3009_ENABLE, XPCI3009_DISABLE)
 *
 * @retval 0: No error
 * @retval 1: parameter pdev is NULL.
 * @retval 2: parameter b_ModulNbr is not in the correct range
 * @retval 3: The given b_ModulNbr is not a counter module
 * @retval 4: Counter not initialised see function "i_XPCI3009_InitCounter"
 * @retval 5  The reference action parameter is wrong
 * @retval 6: The index operating mode parameter is wrong
 * @retval 7: The auto mode parameter is wrong
 * @retval 8: Interrupt parameter is wrong
 * @retval 9: Interrupt function not initialised. See function "i_XPCI3009_SetBoardIntRoutineX"
 *
 * @note This function applies to counter modules only
 */
int i_XPCI3009_InitIndex (struct pci_dev * pdev, uint8_t b_ModulNbr, uint8_t b_ReferenceAction, uint8_t b_IndexOperation, uint8_t b_AutoMode, uint8_t b_InterruptEnable );

//------------------------------------------------------------------------------
/** Enable the index corresponding to the selected module (b_ModulNbr).
 *
 * @param [in] b_ModulNbr    : Module number (0 to 3).
 *
 * @retval 0: No error
 * @retval 1: parameter pdev is NULL.
 * @retval 2: parameter b_ModulNbr is not in the correct range
 * @retval 3: The given b_ModulNbr is not a counter module
 * @retval 4: Counter not initialised see command "CMD_XPCI3009_InitCounter"
 * @retval 5: Index not initialised - see function "CMD_XPCI3009_InitIndex"
 *
 * @note This function applies to counter modules only
 */
int i_XPCI3009_EnableIndex (struct pci_dev * pdev, uint8_t b_ModulNbr);

//------------------------------------------------------------------------------
/** Disable the index corresponding to the selected module (b_ModulNbr).
 *
 * @param [in] b_ModulNbr    : Module number (0 to 3).
 *
 * @retval 0: No error
 * @retval 1: parameter pdev is NULL.
 * @retval 2: parameter b_ModulNbr is not in the correct range
 * @retval 3: The given b_ModulNbr is not a counter module
 * @retval 4: Counter not initialised see command "CMD_XPCI3009_InitCounter"
 * @retval 5:  Index not initialised - see function "CMD_XPCI3009_InitIndex"
 *
 * @note This function applies to counter modules only
 */
int i_XPCI3009_DisableIndex (struct pci_dev * pdev, uint8_t b_ModulNbr);

//------------------------------------------------------------------------------
/** Returns the INDEX status.
 *
 * @param [in] b_ModulNbr : Module number (0 to 3).
 * @param [out] pb_IndexStatus : (0,1)
 * 							0 : No INDEX occur
 * 							1 : An INDEX event occured
 *
 * @retval 0: No error
 * @retval 1: parameter pdev is NULL.
 * @retval 2: parameter b_ModulNbr is not in the correct range
 * @retval 3: The given b_ModulNbr is not a counter module
 * @retval 4: Counter not initialised see command "CMD_XPCI3009_InitCounter"
 * @retval 5: Index not initialised - see function "CMD_XPCI3009_InitIndex"
 *
 * @note This function applies to counter modules only
*/
int i_XPCI3009_GetIndexStatus (struct pci_dev * pdev, uint8_t b_ModulNbr, uint8_t * pb_IndexStatus);

//------------------------------------------------------------------------------
/** Determine the hardware source for the index and the reference logic.
 *
 * By default the index logic is connected to the difference input C and the reference
 * logic is connected to the 24V input E
 *
 * @param [in] b_ModulNbr : Module number (0 to 3).
 * @param [in] b_SourceSelection : (XPCI3009_SOURCE_0,XPCI3009_SOURCE_1)
 * 									XPCI3009_SOURCE_0 : The index logic is connected to the difference input C
 * 														and the reference logic is connected to the 24V input E.
 * 														This is the default configuration.
 * 									XPCI3009_SOURCE_1 : The reference logic is connected to the difference
 * 														input C and the index logic is connected to the 24V input E
 *
 * @retval 0: No error
 * @retval 1: parameter pdev is NULL.
 * @retval 2: parameter b_ModulNbr is not in the correct range
 * @retval 3: The given b_ModulNbr is not a counter module
 * @retval 4: The parameter b_SourceSelection is incorrect
 * @retval 5: The board does not support this operation ( firmware revision < 1.5 )
 *
 * @note This function applies to counter modules only
 * @note This function may be applied on unitialised counter/index
 *
 */
int i_XPCI3009_SetIndexAndReferenceSource (struct pci_dev * pdev, uint8_t b_ModulNbr, uint8_t b_SourceSelection );

//------------------------------------------------------------------------------
/** Initialise the reference corresponding to the selected module (b_ModulNbr).
 *
 * @param [in] b_ModulNbr : Module number (0 to 3).
 * @param [in] b_ReferenceLevel : (XPCI3009_LOW,XPCI3009_HIGH)
 * 									XPCI3009_LOW : Reference occur if "0"
 * 									XPCI3009_HIGH : Reference occur if "1"
 *
 * @retval 0: No error
 * @retval 1: parameter pdev is NULL.
 * @retval 2: parameter b_ModulNbr is not in the correct range
 * @retval 3: The given b_ModulNbr is not a counter module
 * @retval 4: Counter not initialised see command "CMD_XPCI3009_InitCounter"
 * @retval 5: The parameter b_ReferenceLevel is incorrect
 *
 * @note This function applies to counter modules only
 */
int i_XPCI3009_InitReference (struct pci_dev * pdev, uint8_t b_ModulNbr, uint8_t b_ReferenceLevel );

//------------------------------------------------------------------------------
/** Return the reference status.
 *
 * @param [in]  b_ModulNbr : Module number (0 to 3).
 * @param [out] pb_ReferenceStatus : (0,1)
 * 										0: No REFERENCE occurs
 * 										1: A REFERENCE occurs
 *
 * @retval 0: No error
 * @retval 1: parameter pdev is NULL.
 * @retval 2: parameter b_ModulNbr is not in the correct range
 * @retval 3: The given b_ModulNbr is not a counter module
 * @retval 4: Counter not initialised see function "CMD_XPCI3009_InitCounter"
 * @retval 5: Reference not initialised see command "CMD_XPCI3009_InitReference"
 *
 * @note This function applies to counter modules only
 */
int i_XPCI3009_GetReferenceStatus (struct pci_dev * pdev, uint8_t b_ModulNbr, uint8_t * pb_ReferenceStatus);

int i_XPCI3009_GetCounterInitialisationStatus(struct pci_dev * pdev, unsigned int ui_ModulNbr, unsigned int ui_ArgArray[6] );

int   i_XPCI3009_GetModuleId (struct pci_dev *pdev,uint8_t  b_ModuleNbr,uint32_t * pui_Id);

int i_XPCI3009_GetBoardType (struct pci_dev *pdev, uint32_t *boardType);

/** Return the module functionality.
 *
 * @param [in] pdev          : The device to initialize.
 * @param [in] b_ModulNbr    : Module number to configure (0 to 3).
 *
 * @param [out] pui_Functionality : Module configuration.
 *
 * @retval 0: No error.
 * @retval 1: pdev is NULL.
 * @retval 2: b_ModuleNbr is incorrect.
 */
int i_XPCI3009_GetFunctionality (struct pci_dev *pdev,uint8_t  b_ModuleNbr,uint32_t * pui_Functionality);




// DIGITAL IO MODULE FUNCTIONALITIES
/** Configure the digital I/O operating mode.
 *
 * Configure the digital I/O operating mode from selected
 * module  (b_ModulNbr). You must calling this function be
 * for you call any other function witch access of digital I/O.
 *
 * @param [in] pdev                  : The device to initialize.
 * @param [in] b_ModulNbr            : Module number to configure (0 to 3).
 * @param [in] b_ChannelAMode        : Channel A mode selection <br>
 *                                     0 : Channel used for digital input <br>
 *                                     1 : Channel used for digital output
 * @param [in] b_ChannelBMode        : Channel B mode selection <br>
 *                                     0 : Channel used for digital input
 *                                     1 : Channel used for digital output
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The module parameter is wrong.
 * @retval 3: The module is not a digital I/O module.
 * @retval 4: Bi-directional channel A configuration error.
 * @retval 5: Bi-directional channel B configuration error.
 */
int   i_XPCI3009_InitDigitalIO (struct pci_dev *pdev,uint8_t b_ModulNbr,uint8_t b_ChannelAMode,uint8_t b_ChannelBMode);

/** Read the status from selected digital I/O digital input (b_InputChannel).
 *
 * @param [in] pdev                  : The device to initialize.
 * @param [in] b_ModulNbr            : Module number to configure (0 to 3).
 * @param [in] b_InputChannel        : Selection from digital input (0 to 6) <br>
 *                                     0 : Channel C <br>
 *                                     1 : Channel D <br>
 *                                     2 : Channel E <br>
 *                                     3 : Channel F <br>
 *                                     4 : Channel G <br>
 *                                     5 : Channel A <br>
 *                                     6 : Channel B
 *
 * @param [out] pb_ChannelStatus     : Digital input channel status <br>
 *                                     0 : Channle is not active <br>
 *                                     1 : Channle is active
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The module parameter is wrong.
 * @retval 3: The module is not a digital I/O module.
 * @retval 4: The selected digital I/O digital input is wrong.
 * @retval 5: Digital I/O not initialised.
 * @retval 6: The digital channel A is used for output.
 * @retval 7: The digital channel B is used for output.
 */
int   i_XPCI3009_ReadDigitalIOChlValue (struct pci_dev *pdev,uint8_t    b_ModulNbr,uint8_t    b_InputChannel,uint8_t *  pb_ChannelStatus);

/** Read the status from digital input port.
 *
 * Read the status from digital input port from selected
 * digital I/O module (b_ModulNbr).
 *
 * @param [in] pdev                  : The device to initialize.
 * @param [in] b_ModulNbr            : Module number to configure (0 to 3).
 *
 * @param [out] pb_PortValue         : Digital I/O inputs port status.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The module parameter is wrong.
 * @retval 3: The module is not a digital I/O module.
 * @retval 4: Digital I/O not initialised.
 */
int   i_XPCI3009_ReadDigitalIOPortValue  (struct pci_dev *pdev,uint8_t     b_ModulNbr,uint8_t *   pb_PortValue);

/** Activates the digital output memory.
 *
 * After having called up this function, the output you have previously
 * activated with the function "i_XPCI3009_SetDigitalIOOutputXOn" are not reset.
 * You can reset them with the function "i_XPCI3009_SetDigitalIOOutputXOff".
 *
 * @param [in] pdev                  : The device to initialize.
 * @param [in] b_ModulNbr            : Module number to configure (0 to 3).
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The module parameter is wrong.
 * @retval 3: The module is not a digital I/O module.
 * @retval 4: Digital I/O not initialised.
 */
int   i_XPCI3009_SetDigitalIOMemoryOn (struct pci_dev *pdev, uint8_t b_ModulNbr);

/** Deactivates the digital output memory.
 *
 * @param [in] pdev                  : The device to initialize.
 * @param [in] b_ModulNbr            : Module number to configure (0 to 3).
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The module parameter is wrong.
 * @retval 3: The module is not a digital I/O module.
 * @retval 4: Digital I/O not initialised.
 */
int   i_XPCI3009_SetDigitalIOMemoryOff (struct pci_dev *pdev, uint8_t b_ModulNbr);

/** Sets the output.
 *
 * Sets the output witch has been passed with the
 * parameter b_Channel. Setting an output means setting
 * an ouput high.
 *
 * @param [in] pdev                  : The device to initialize.
 * @param [in] b_ModulNbr            : Module number to configure (0 to 3).
 * @param [in] b_OutputChannel       : Selection from digital output <br>
 *                                     channel (0 to 2) <br>
 *                                     0 : Channel H <br>
 *                                     1 : Channel A <br>
 *                                     2 : Channel B
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The module parameter is wrong.
 * @retval 3: The module is not a digital I/O module.
 * @retval 4: The selected digital output is wrong.
 * @retval 5: digital I/O not initialised see function "i_XPCI3009_InitDigitalIO".
 * @retval 6: The digital channel A is used for input.
 * @retval 7: The digital channel B is used for input.
 */
int   i_XPCI3009_SetDigitalIOChlOn (struct pci_dev *pdev,uint8_t b_ModulNbr,uint8_t b_OutputChannel);

/** Resets the output.
 *
 * Resets the output witch has been passed with the
 * parameter b_Channel. Resetting an output means setting
 * an ouput low.
 *
 * @param [in] pdev                  : The device to initialize.
 * @param [in] b_ModulNbr            : Module number to configure (0 to 3).
 * @param [in] b_OutputChannel       : Selection from digital output channel (0 to 2) <br>
 *                                     0 : Channel H <br>
 *                                     1 : Channel A <br>
 *                                     2 : Channel B
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The module parameter is wrong.
 * @retval 3: The module is not a digital I/O module.
 * @retval 4: The selected digital output is wrong.
 * @retval 5: digital I/O not initialised see function "i_XPCI3009_InitDigitalIO".
 * @retval 6: The digital channel A is used for input.
 * @retval 7: The digital channel B is used for input.
 * @retval 8: Digital Output Memory OFF Use previously the function "i_XPCI3009_SetDigitalIOMemoryOn".
 */
int   i_XPCI3009_SetDigitalIOChlOff (struct pci_dev *pdev,uint8_t b_ModulNbr,uint8_t b_OutputChannel);

/** Sets one or several outputs from port.
 *
 * Setting an output means setting an output high.
 * If you have switched OFF the digital output memory
 * (OFF), all the other output are set to "0".
 *
 * @param [in] pdev                  : The device to initialize.
 * @param [in] b_ModulNbr            : Module number to configure (0 to 3).
 * @param [in] b_PortValue           : Output Value ( 0 To 7 ).
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The module parameter is wrong.
 * @retval 3: The module is not a digital I/O module.
 * @retval 4: Output value wrong.
 * @retval 5: digital I/O not initialised see function "i_XPCI3009_InitDigitalIO".
 * @retval 6: The digital channel A is used for input.
 * @retval 7: The digital channel B is used for input.
 */
int   i_XPCI3009_SetDigitalIOPortOn (struct pci_dev *pdev,uint8_t b_ModulNbr,uint8_t b_PortValue);

/** Resets one or several output from port.
 *
 * Resetting means setting low.
 *
 * @param [in] pdev                  : The device to initialize.
 * @param [in] b_ModulNbr            : Module number to configure (0 to 3).
 * @param [in] b_PortValue           : Output Value ( 0 To 7 ).
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The module parameter is wrong.
 * @retval 3: The module is not a digital I/O module.
 * @retval 4: Output value wrong.
 * @retval 5: digital I/O not initialised see function "i_XPCI3009_InitDigitalIO".
 * @retval 6: The digital channel A is used for input.
 * @retval 7: The digital channel B is used for input.
 * @retval 8: Digital Output Memory OFF. Use previously the function "i_XPCI3009_SetDigitalIOMemoryOn".
 */
int   i_XPCI3009_SetDigitalIOPortOff (struct pci_dev *pdev,uint8_t b_ModulNbr,uint8_t b_PortValue);


/** Enable and set the interrupt routine.
 *
 *
 * @param [in] pdev              : The device to initialize.
 * @param [in] InterruptCallback : The user interrupt callback.
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 * @retval 2: The interrupt callback is NULL.
 */
int   i_XPCI3009_SetBoardIntRoutine  (struct pci_dev * pdev, void (*InterruptCallback) (struct pci_dev * pdev));

//------------------------------------------------------------------------------

/** Disable and reset the interrupt routine.
 *
 * @param [in] pdev              : The device to initialize.
 *
 * @retval 0: No error.
 * @retval 1: parameter pdev is NULL.
 */
int   i_XPCI3009_ResetBoardIntRoutine     (struct pci_dev * pdev);

/* removes the user handler for a given module */
int i_XPCI3009_ClearUserHandler(struct pci_dev * pdev, uint8_t b_ModulNbr);

//------------------------------------------------------------------------------

/** Return interrupt information.
 *
 * @param [in] pdev                   : The device to initialize.
 * @param [out] pb_ModuleMask         : Mask of the events <br>
 *                                      which have generated the interrupt.
 * @param [out] pul_CounterLatchValue : The latched values of <br>
 *                                      the counter are returned.
 *
 * @retval 1  : No interrupt.
 * @retval >0 : IRQ number
 */
int   i_XPCI3009_TestModuleInterrupt (struct pci_dev *pdev,uint8_t*   pb_ModuleMask,uint32_t* pul_InterruptMask,uint32_t* pul_CounterLatchValue);


/** Initialize chronos functionality.
 *
 * Configure the chronometer operating mode (b_ChronoMode)
 * from selected module (b_ModulNbr).
 * The ul_TimingInterval and ul_TimingUnit determine the
 * timing base for the measurement.
 * The pul_RealTimingInterval return the real timing
 * value. You must calling this function be for you call
 * any other function witch access of the chronometer.
 *
 * Witch this functionality from the XPCI-3009 you have
 * the possibility to measure the timing witch two event.
 *
 * The mode 0 and 1 is appropriate for period measurement.
 * The mode 2 and 3 is appropriate for frequent measurement.
 * The mode 4 to 7 is appropriate for measuring the timing
 * between  two event.
 *
 * @param [in] pdev                   : The device to initialize.
 * @param [in] b_ModulNbr             : Module number to configure (0 to 3).
 * @param [in] b_ChronoMode           : Chronometer action mode (0 to 7).
 * @param [in] b_PCIInputClock        : Selection from PCI bus clock
 *                                      - XPCI3009_30MHZ :
 *                                        The PC have a PCI bus
 *                                        clock from 30 MHz
 *                                        Not available with the APCIe-1711
 *                                      - XPCI3009_33MHZ :
 *                                        The PC have a PCI bus
 *                                        clock from 33 MHz
 *                                        Not available with the APCIe-1711
 *                                      - XPCI3009_40MHZ
 *                                        The XPCI-3009 have a
 *                                        integrated 40Mhz quartz.
 * @param [in] b_TimingUnit           : Base timing unity (0 to 4)
 *                                        0 : ns
 *                                        1 : �s
 *                                        2 : ms
 *                                        3 : s
 *                                        4 : mn
 * @param [in] ul_TimingInterval      : Base timing value.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The selected module is wrong.
 * @retval 3: The module is not a chronos module.
 * @retval 4: Chronometer mode selection is wrong.
 * @retval 5: The selected PCI input clock is wrong.
 * @retval 6: Timing unity selection is wrong.
 * @retval 7: Base timing selection is wrong.
 * @retval 8: You can not used the 40MHz clock selection wich this board.
 * @retval 9: You can not used the 40MHz clock selection wich this CHRONOS version.
 */
int i_XPCI3009_InitChrono (struct pci_dev *pdev,uint8_t b_ModulNbr,uint8_t b_ChronoMode,uint8_t b_PCIInputClock,uint8_t b_TimingUnit,uint32_t ul_TimingInterval);

/** Enable the chronometer.
 *
 * Enable the chronometer from selected module
 * (b_ModulNbr). You must calling the
 * "i_XPCI3009_InitChrono" function be for you call this
 * function.
 * If you enable the chronometer interrupt, the
 * chronometer generate a interrupt after the stop signal.
 * See function "i_XPCI3009_SetBoardIntRoutineX" and the
 * Interrupt mask description chapter from this manual.
 * The b_CycleMode parameter determine if you will
 * measured a single or more cycle.
 *
 * @param [in] pdev                   : The device to initialize.
 * @param [in] b_ModulNbr             : Module number to configure (0 to 3).
 * @param [in] b_CycleMode            : Selected the chronometer acquisition mode.
 * @param [in] b_InterruptEnable      : Enable or disable the chronometer interrupt.
 *                                      XPCI3009_ENABLE: Enable the chronometer interrupt.
 *                                      XPCI3009_DISABLE:Disable the chronometer interrupt.
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The selected module is wrong.
 * @retval 3: The module is not a chronos module.
 * @retval 4: Chronometer not initialised see function "i_XPCI3009_InitChrono".
 * @retval 5: Chronometer acquisition mode cycle is wrong.
 * @retval 6: Interrupt parameter is wrong.
 * @retval 7: Interrupt function not initialised. See function "i_XPCI3009_SetBoardIntRoutineX".
 */
int i_XPCI3009_EnableChrono (struct pci_dev *pdev,uint8_t b_ModulNbr,uint8_t b_CycleMode,uint8_t b_InterruptEnable);

/** Disable the chronometer.
 *
 * Disable the chronometer from selected module
 * (b_ModulNbr). If you disable the chronometer after a
 * start signal occur and you restart the chronometer
 * witch the " i_XPCI3009_EnableChrono" function, if no
 * stop signal occur this start signal is ignored.
 *
 * @param [in] pdev                   : The device to initialize.
 * @param [in] b_ModulNbr             : Module number to configure (0 to 3).
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The selected module is wrong.
 * @retval 3: The module is not a chronos module.
 * @retval 4: Chronometer not initialised see function "i_XPCI3009_InitChrono".
 */
int i_XPCI3009_DisableChrono (struct pci_dev *pdev,uint8_t b_ModulNbr);

/** Get the chronometer status.
 *
 * Return the chronometer status (pb_ChronoStatus) from
 * selected chronometer module (b_ModulNbr).
 *
 * @param [in] pdev                   : The device to initialize.
 * @param [in] b_ModulNbr             : Module number to configure (0 to 3).
 *
 * @param [out] pb_ChronoStatus : Return the chronometer status.
 *                                0 : Measurement not started.
 *                                    No start signal occur.
 *                                1 : Measurement started.
 *                                    A start signal occur.
 *                                2 : Measurement stopped.
 *                                    A stop signal occur.
 *                                    The measurement is terminate.
 *                                3: A overflow occur. You must change the base
 *                                   timing witch the function "i_XPCI3009_InitChrono"
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The selected module is wrong.
 * @retval 3: The module is not a chronos module.
 * @retval 4: Chronometer not initialised see function "i_XPCI3009_InitChrono".
 */
int i_XPCI3009_GetChronoProgressStatus (struct pci_dev *pdev,uint8_t b_ModulNbr,uint8_t  *pb_ChronoStatus);

/** Read the chronometer value.
 *
 * Return the chronometer status (pb_ChronoStatus) and the
 * timing value (pul_ChronoValue) after a stop signal
 * occur from selected chronometer module (b_ModulNbr).
 * This function are only avaible if you have disabled
 * the interrupt functionality. See function
 * "i_XPCI3009_EnableChrono" and the Interrupt mask
 * description chapter.
 * You can test the chronometer status witch the
 * "i_XPCI3009_GetChronoProgressStatus" function.
 *
 * The returned value from pul_ChronoValue parameter is
 * not real measured timing.
 * You must used the "i_XPCI3009_ConvertChronoValue"
 * function or make this operation for calculate the
 * timing:
 *
 * Timing = pul_ChronoValue * pul_RealTimingInterval.
 *
 * pul_RealTimingInterval is the returned parameter from
 * "i_XPCI3009_InitChrono" function and the time unity is
 * the b_TimingUnit from "i_XPCI3009_InitChrono" function
 *
 * @param [in] pdev                   : The device to initialize.
 * @param [in] b_ModulNbr             : Module number to configure (0 to 3).
 * @param [in] ul_TimeOut
 *
 * @param [out] pb_ChronoStatus : Return the chronometer status.
 *                                0 : Measurement not started.
 *                                    No start signal occur.
 *                                1 : Measurement started.
 *                                    A start signal occur.
 *                                2 : Measurement stopped.
 *                                    A stop signal occur.
 *                                    The measurement is terminate.
 *                                3: A overflow occur. You must change the base
 *                                   timing witch the function "i_XPCI3009_InitChrono"
 *
 * @param [out] pul_ChronoValue : Chronometer timing value.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The selected module is wrong.
 * @retval 3: The module is not a chronos module.
 * @retval 4: Chronometer not initialised see function "i_XPCI3009_InitChrono".
 * @retval 5: Timeout parameter is wrong (0 to 65535).
 * @retval 6: Interrupt routine installed.
 *            You can not read directly the chronometer measured timing.
 */
int i_XPCI3009_ReadChronoValue (struct pci_dev *pdev,uint8_t b_ModulNbr,uint32_t ul_TimeOut,uint8_t *pb_ChronoStatus,uint32_t *pul_ChronoValue);

/** Set the selected chronometer channel on.
 *
 * Sets the output witch has been passed with the
 * parameter b_Channel. Setting an output means setting an
 * output high.
 *
 * @param [in] pdev                   : The device to initialize.
 * @param [in] b_ModulNbr             : Module number to configure (0 to 3).
 * @param [in] b_OutputChannel        : Selection from digital output
 *                                      channel (0 to 2)
 *                                      0 : Channel H
 *                                      1 : Channel A
 *                                      2 : Channel B
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The selected module is wrong.
 * @retval 3: The module is not a chronos module.
 * @retval 4: The selected digital output is wrong.
 * @retval 5: Timeout parameter is wrong (0 to 65535).
 */
int i_XPCI3009_SetChronoChlOn (struct pci_dev *pdev,uint8_t b_ModulNbr,uint8_t b_OutputChannel);

/** Set the selected chronometer channel off.
 *
 * Reset the output witch has been passed with the
 * parameter b_Channel. Setting an output means setting an
 * output high.
 *
 * @param [in] pdev                   : The device to initialize.
 * @param [in] b_ModulNbr             : Module number to configure (0 to 3).
 * @param [in] b_OutputChannel        : Selection from digital output
 *                                      channel (0 to 2)
 *                                      0 : Channel H
 *                                      1 : Channel A
 *                                      2 : Channel B
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The selected module is wrong.
 * @retval 3: The module is not a chronos module.
 * @retval 4: The selected digital output is wrong.
 * @retval 5: Chronometer not initialised see function "i_XPCI3009_InitChrono".
 */
int i_XPCI3009_SetChronoChlOff (struct pci_dev *pdev,uint8_t b_ModulNbr,uint8_t b_OutputChannel);

/** Read the selected chronometer channel value.
 *
 * Return the status from selected digital input
 * (b_InputChannel) from selected chronometer
 * module (b_ModulNbr).
 *
 * @param [in] pdev                   : The device to initialize.
 * @param [in] b_ModulNbr             : Module number to configure (0 to 3).
 * @param [in] b_InputChannel         : Selection from digital output
 *                                      channel (0 to 2)
 *                                      0 : Channel E
 *                                      1 : Channel F
 *                                      2 : Channel G
 *
 * @param [out] pb_ChannelStatus      : Digital input channel status.
 *                                      0 : Channel is not active
 *                                      1 : Channel is active
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The selected module is wrong.
 * @retval 3: The module is not a chronos module.
 * @retval 4: The selected digital input is wrong.
 * @retval 5: Chronometer not initialised see function "i_XPCI3009_InitChrono".
 */
int i_XPCI3009_ReadChronoChlValue (struct pci_dev *pdev,uint8_t b_ModulNbr,uint8_t b_InputChannel,uint8_t *pb_ChannelStatus);

/** Read the selected chronometer port value.
 *
 * Return the status from digital inputs port from
 * selected  (b_ModulNbr) chronometer module.
 *
 * @param [in] pdev                   : The device to initialize.
 * @param [in] b_ModulNbr             : Module number to configure (0 to 3).
 *
 * @param [out] pb_PortValue      : Digital inputs port status.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The selected module is wrong.
 * @retval 3: The module is not a chronos module.
 * @retval 4: Chronometer not initialised see function "i_XPCI3009_InitChrono".
 */
int i_XPCI3009_ReadChronoPortValue (struct pci_dev *pdev,uint8_t b_ModulNbr,uint8_t *pb_PortValue);


//----------------------------------------------------------------------------
/** return a pointer to the lock protecting the board */
extern spinlock_t * xpci3009_get_lock(struct pci_dev *pdev);
//----------------------------------------------------------------------------
/** lock the board using spin_lock_irqsave(), disabling local software and hardware interrupts
 * @param[in] pdev The device to acquire.
 * @param[out] flags interuption flag used with unlock()
 *
 * This function is to be used before calling any kAPI function; BUT not in user interrupt handler where the board is already acquired.
 *
 * @warning lock aren't reentrant, that means that you can not nest call to lock()
 *
 */
static inline void xpci3009_lock(struct pci_dev *pdev, unsigned long * flags)
{
    spin_lock_irqsave(xpci3009_get_lock(pdev), *flags);
}

//----------------------------------------------------------------------------
/** unlock the board using spin_lock_irqrestore()
 * @param[in] pdev The device to acquire.
 * @param[out] flags interuption flag initialised by lock()
 *
 * This function is to be used before calling any kAPI function; BUT not in user interrupt handler where the board is already acquired.
 *
 *
 *
 */
static inline void xpci3009_unlock(struct pci_dev *pdev, unsigned long flags)
{
	spin_unlock_irqrestore(xpci3009_get_lock(pdev), flags);
}


#endif

