#ifndef __APCI1648KAPI_H__
#define __APCI1648KAPI_H_

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

#include <linux/pci.h>
#include <apci1648.h>
//------------------------------------------------------------------------------

/** Initialize all digital ports of the APCI-1648.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 * @param 			PortsSetting		Function argument. An array of 6 unsigned char that has to be initialized as following.<br>
 *                          Each index of the array is a port e.g.:<br>
 *                          PortsSetting [0]: Port 0 (0: Input direction / 1: Output direction)
 *                          PortsSetting [1]: Port 1 (0: Input direction / 1: Output direction)
 *                          PortsSetting [2]: Port 2 (0: Input direction / 1: Output direction)
 *                          PortsSetting [3]: Port 3 (0: Input direction / 1: Output direction)
 *                          PortsSetting [4]: Port 4 (0: Input direction / 1: Output direction)
 *                          PortsSetting [5]: Port 5 (0: Input direction / 1: Output direction)
 *
 * @retval 0		No error. 
 * @retval -EINVAL	Port settings are incorrect.
 */
int APCI1648_InitAllDigitalPorts(struct pci_dev *pdev, const unsigned char PortsSetting[6]);

/** Get all digital ports settings of the APCI-1648.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 * @param 			PortsSetting		Function argument. An array of 6 unsigned char that will contain ports settings.<br>
 *                          Each index of the array is a port e.g.:<br>
 *                          PortsSetting [0]: Port 0 (0: Input direction / 1: Output direction)
 *                          PortsSetting [1]: Port 1 (0: Input direction / 1: Output direction)
 *                          PortsSetting [2]: Port 2 (0: Input direction / 1: Output direction)
 *                          PortsSetting [3]: Port 3 (0: Input direction / 1: Output direction)
 *                          PortsSetting [4]: Port 4 (0: Input direction / 1: Output direction)
 *                          PortsSetting [5]: Port 5 (0: Input direction / 1: Output direction)
 *
 * @retval 0		No error. 
 */
int APCI1648_GetAllDigitalPortsSetting(struct pci_dev *pdev, unsigned char PortsSetting[6]);

/** Initialize one port of the APCI-1648.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 * @param 			arg		DigitalPortsArg_t
 *
 * @retval 0		No error. 
 * @retval -EINVAL	The port number or the initialization value is incorrect.
 */
int APCI1648_InitDigitalPort(struct pci_dev *pdev, struct DigitalPortsArg_t * arg);

/** Get one port initialization of the APCI-1648.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 * @param 			arg		DigitalPortsArg_t
 *
 * @retval 0		No error. 
 * @retval -EINVAL	The port number is incorrect.
 */
int APCI1648_GetDigitalPortSetting(struct pci_dev *pdev, struct DigitalPortsArg_t * arg);

/** Read all digital inputs of the APCI-1648.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 * @param 			arg		Function argument. An array of 6 unsigned char that will contain ports states.<br>
 *                          Each index of the array is a port e.g.:<br>
 *                          PortsSetting [0]: Port 0, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsSetting [1]: Port 1, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsSetting [2]: Port 2, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsSetting [3]: Port 3, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsSetting [4]: Port 4, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsSetting [5]: Port 5, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *
 * @retval 0		No error. 
 */
int APCI1648_ReadAllDigitalInputs(struct pci_dev *pdev, unsigned char PortsState[6]);

/** Set all digital outputs of the APCI-1648 on.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 * @param 			PortsState		Function argument. An array of 6 unsigned char that has contain ports states.<br>
 *                          Each index of the array is a port e.g.:<br>
 *                          PortsState [0]: Port 0, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsState [1]: Port 1, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsState [2]: Port 2, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsState [3]: Port 3, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsState [4]: Port 4, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsState [5]: Port 5, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *
 * @retval 0		No error. 
 */
int APCI1648_SetAllDigitalOutputsOn(struct pci_dev *pdev, const unsigned char PortsState[6]);

/** Set all digital outputs of the APCI-1648 off.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 * @param 			arg		Function argument. An array of 6 unsigned char that has contain ports states.<br>
 *                          Each index of the array is a port e.g.:<br>
 *                          PortsState [0]: Port 0, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsState [1]: Port 1, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsState [2]: Port 2, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsState [3]: Port 3, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsState [4]: Port 4, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsState [5]: Port 5, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *
 * @retval 0		No error. 
 * @retval -EPERM	Output memory is not activated.
 */
int APCI1648_SetAllDigitalOutputsOff(struct pci_dev *pdev, const unsigned char PortsState[6]);

/** Set the digital output memory on.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 * @param 			arg		Non arg, it can be NULL.
 *
 * @retval 0		No error.
 */
int APCI1648_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 APCI1648_SetDigitalOutputMemoryOff(struct pci_dev *pdev);

/** Get all digital outputs states of the APCI-1648.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 * @param 			arg		Function argument. An array of 6 unsigned char that contain ports states.<br>
 *                          Each index of the array is a port e.g.:<br>
 *                          PortsState [0]: Port 0, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsState [1]: Port 1, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsState [2]: Port 2, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsState [3]: Port 3, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsState [4]: Port 4, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *                          PortsState [5]: Port 5, is composed of 8 channels. One channel can be 1 (high) or 0 (low).
 *
 * @retval 0		No error. 
 */
int APCI1648_GetAllDigitalOutputsStates(struct pci_dev *pdev, unsigned char PortsState[6]);

/** Find a apci 1648 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.
 */
static __inline__  struct pci_dev * apci1648_lookup_board_by_index(unsigned int index)
{
	struct pci_dev * dev = NULL;	
	int i = 0;

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
	while ( (dev = pci_find_device(APCI1648_BOARD_VENDOR_ID,APCI1648_BOARD_DEVICE_ID,dev)) )
#else
	while ( (dev = pci_get_device(APCI1648_BOARD_VENDOR_ID,APCI1648_BOARD_DEVICE_ID,dev)) )
#endif
	{
		if (i == index) return dev;
		i++;
	}      

	return NULL;
}


#endif /*__APCI1648KAPI_H__*/
