#ifndef __APCIE1532KAPI_H__
#define __APCIE1532KAPI_H__

#ifndef __KERNEL__
#error This header is intended to be used in kernel context only.
#endif

#ifdef __KERNEL__

#include <linux/pci.h>
#include <apcie1532.h>
#include <apcie1532-events.h>

/** Read all digital inputs of the APCIE-1532.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 * @param [out]		arg		Port state (0 to 65535).
 *
 * @retval 0		No error. 
 * @retval -EFAULT	Can't return parameters.
 */
int APCIE1532_Read16DigitalInputs(struct pci_dev *pdev, uint32_t * PortState);

/** Set all digital outputs of the APCIE-1532 on.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 * @param [in]		arg		Port state to set (0 to 65535).
 *
 * @retval 0		No error. 
 * @retval -EFAULT	Can't return parameters.
 */
int APCIE1532_Set16DigitalOutputsOn(struct pci_dev *pdev, uint32_t arg);

 /** Set all digital outputs of the APCIE-1532 on.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 * @param [in]		arg		Port state to reset (0 to 65535).
 *
 * @retval 0		No error. 
 * @retval -EPERM	Output memory is not activated.
 * @retval -EFAULT	Can't return parameters.
 */
int APCIE1532_Set16DigitalOutputsOff(struct pci_dev *pdev, uint32_t arg);

/** Set the digital output memory on.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 * @retval 0		No error.
 */
int APCIE1532_SetDigitalOutputMemoryOn(struct pci_dev *pdev);

/** Set the digital output memory off.
 *
 * @param [in,out]	pdev	Pointer on the device structure.

 * @retval 0		No error.
 */
int APCIE1532_SetDigitalOutputMemoryOff(struct pci_dev *pdev);

/** Get all digital outputs states of the APCIE-1532.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 * @param [out]		arg		Port state (0 to 65535).
 *
 * @retval 0		No error. 
 * @retval -EFAULT	Can't return parameters.
 */
int APCIE1532_Get16DigitalOutputStatus(struct pci_dev *pdev, uint32_t * PortState);

/** find a apci 1532 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.
 */
struct pci_dev * apcie1532_lookup_board_by_index(unsigned int index);

typedef void APCIE1532_user_interrupt_t(struct pci_dev *pdev, apcie1532_event_t* evt);

/** Set the user interrupt callback  
 *
 * User interrupt callback is function of type APCIE1532_user_interrupt_t called when an event ( an interrupt )
 * happens. This function registers the user function in the board.
 *    
 * @param[in] pdev Pointer to the PCI device to access. 
 * 
 * @return 0 on success, -EINVAL if a parameter is incorrect, -EBUSY if an was interrupt already registered in the board 
 */
extern int APCIE1532_SetInterruptCallback(struct pci_dev *pdev, APCIE1532_user_interrupt_t user_interrupt);

/** Clear the user interrupt callback reference in the driver.  
 *  
 * @param[in] pdev Pointer to the PCI device to access. 
 * 
 * @return 0 on success, -EINVAL if a parameter is incorrect
 */
extern int APCIE1532_ClearInterruptCallback(struct pci_dev *pdev);

/** Setup the digital input interrupt.
 * 
 * @param[in] pdev Pointer to the PCI device to access.
 * @param[in] InterruptLogic : (0,1) - 0: OR, 1: AND. Only OR (0) logic is supported by the APCIE-1532.
 * @param[in] InterruptMaskMode1 : only setting bit D1-D15 is legal ( each bit is an interruptible input ) - condition: InterruptMaskMode1 & (~0x0000FFFE) != 0 
 * @param[in] InterruptMaskMode2 : only setting bit D1-D15 is legal ( each bit is an interruptible input ) - condition: InterruptMaskMode2 & (~0x0000FFFE) != 0
 * 
 * @return 0 on success,  -EINVAL if parameters are incorrects
 */
extern int APCIE1532_InitAndStartDigitalInputInterrupt (struct pci_dev *pdev, int InterruptLogic, uint32_t InterruptMaskMode1,uint32_t InterruptMaskMode2);  

/** Reset the digital input interrupt
 * 
 * previous parameter is cleared and interrupt deactivated 
 *  
 * @return 0 on success,  -EINVAL if parameters are incorrects
 */
extern int APCIE1532_ClearAndStopDigitalInputInterrupt (struct pci_dev *pdev);

/** Get the digital input interrupt configuration.
 * 
 * @param[in] pdev Pointer to the PCI device to access.
 * @param[in] Enabled : (0,1) - 0: interruption is enabled, 1: interruption is disabled
 * @param[in] InterruptLogic : (0,1) - 0: OR, 1: AND
 * @param[in] InterruptMaskMode1 : (0,0x0000FFFE) 
 * @param[in] InterruptMaskMode2 : (0,0x0000FFFE)
 * 
 * @return 0 on success,  -EINVAL if parameters are incorrects
 */
 
extern int APCIE1532_GetDigitalInputInterruptConfig (struct pci_dev *pdev, int * Enabled, int * InterruptLogic, uint32_t * InterruptMaskMode1, uint32_t * InterruptMaskMode2);

 /** Initialise and start a counter. 
  * 
  * Interrupt is enabled.
  * 
 * @param[in] pdev Pointer to the PCI device to access. 
 * @param[in] Counter ReloadValue: (1,0xFFFF) 
 * @param[in] DirectionSelection: (0,1) 0: down count 1: up count
 * @param[in] LevelSelection: (1,2,3)  
 * 		1 : Counter count each low level \n
 *      2 : Counter count each high level \n
 *      3 : Counter count each high and low level \n 
 */
extern int APCIE1532_CounterInitAndStart(struct pci_dev *pdev, uint32_t ReloadValue, unsigned long DirectionSelection, unsigned long LevelSelection);

/** Get current counter value
 * 
 * @param[in] pdev Pointer to the PCI device to access.
 * @param[out] Value Counter value
 * 
 * @return 0 on success, -EINVAL if a parameter is incorrect
 */ 
extern int APCIE1532_ReadCounterValue(struct pci_dev *pdev, uint32_t * Value);

/** Stop the counter.
 * 
 * Interrupt from this counter is disabled.
 * 
 * @param[in] pdev Pointer to the PCI device to access.
 * 
 * @return 0 on success, -EINVAL if a parameter is incorrect
 */
extern int APCIE1532_CounterStop(struct pci_dev *pdev);

/** Trigger the counter
 * 
 * if counter direction is 0 (down) the counter is reset to reload value
 * if counter direction is 1 (up) the counter is reset to 0
 *  
 * @param[in] pdev Pointer to the PCI device to access.
 * 
 * @return 0 on success, -EINVAL if a parameter is incorrect
 */
extern int APCIE1532_CounterTrigger(struct pci_dev *pdev);

/** Get current counter status.
 *  
 * @param[in] pdev Pointer to the PCI device to access.
 * @param[out] SoftwareTriggerStatus ( not relevant for counter ) 
 * @param[out] SoftwareClearStatus ( not relevant for counter )
 * @param[out] OverflowStatus 1 if the counter has overflowed 
 *  
 * @return 0 on success, -EINVAL if a parameter is incorrect
 */

extern int APCIE1532_CounterGetStatus(struct pci_dev *pdev, uint32_t * SoftwareTriggerStatus, uint32_t * SoftwareClearStatus, uint32_t * OverflowStatus);

/** Returns the config register of the given counter
 *  
 * @param[in] pdev Pointer to the PCI device to access.
 * @param[out] CounterConfig Configuration register 
 * 
 * @return 0 on success, -EINVAL if a parameter is incorrect
 */
extern int APCIE1532_CounterGetConfigRegister(struct pci_dev *pdev, uint32_t * CounterConfig);

/** Reset the counter configuration  
 *  
 * Stop the counter and clear the configuration
 * 
 * @param[in] pdev Pointer to the PCI device to access.
 * 
 * @return 0 on success, -EINVAL if a parameter is incorrect
 */

extern int APCIE1532_CounterReset(struct pci_dev *pdev);

/** Permits to initialise and start the timer/watchdog of the board xPCIe-1532
*
* @param[in] pdev               : Handle of the board
* @param[in] timerIndex         : Timer to use (0,1 or 2 for watchdog)
* @param[in] timeBase           : Time base of the timer (0->us, 1->ms, 2->s)
* @param[in] reloadValue        : Timer reload value (maximum 4095)
* @param[in] interruptFlag      : Enable: 1, Disable: 0
* @return     <0 : see errno errors \n
*              0 : No Error \n
*              1 : The device handle parameter is wrong \n
*              2 : The timer parameter is wrong \n
*              3 : The time base value is wrong \n
*              4 : The reload value is wrong \n
*              5 : The interrupt flag is wrong \n */
extern int APCIE1532_TimerWatchdogInitAndStart(struct pci_dev *pdev,
					                              uint8_t timerIndex,
                                        uint8_t timeBase,
                                        uint32_t reloadValue,
                                        uint8_t interruptFlag);

/** Read the value of the timer of the board xPCIe-1532
*
* @param[in] pdev             : Handle of the board
* @param[in] timerIndex       : Timer to use (0,1 or 2 for watchdog)
* @param[out] value           : Current timer value
* @return            0 : No Error \n
*              -EINVAL : The timer parameter is wrong \n
*/
extern int APCIE1532_ReadTimerWatchdogValue(struct pci_dev *pdev, uint8_t timerIndex, uint32_t * value);

/** Permits to stop and release the timer/watchdog of the board xPCIe-1532
*
* @param[in] pdev            : Handle of the board
* @param[in] timerIndex      : Timer to use (0,1 or 2 for watchdog)
*
* @return            0 : No Error \n
*              -EINVAL : The timer parameter is wrong \n
*/
extern int APCIE1532_TimerWatchdogStop(struct pci_dev *pdev, uint8_t timerIndex);

/**  Enables to trigger and reload the timer/watchdog of the board by software.
*
* @param[in] pdev            : Handle of the board
* @param[in] timerIndex      : Timer to use (0,1 or 2 for watchdog)
*
* @return            0 : No Error \n
*              -EINVAL : The timer parameter is wrong \n
*/
extern int APCIE1532_TimerWatchdogTrigger(struct pci_dev *pdev, uint8_t timerIndex);

#endif// __KERNEL__


#endif /*__APCIE1532KAPI_H__*/
