 /* @file apcie2200-kapi.h
  * 
  * @brief Define the kernel API for the apcie2200 ADDI-DATA board.
  * 
  * @author Sylvain Nahas, Julien Krauth
  * 
  */

/** @par LICENCE
 * 
 *  @verbatim
   Copyright (C) 2009  ADDI-DATA GmbH for the source code of this module.
        
        ADDI-DATA GmbH
        Airpark Business Center
        Airport Boulevard B210
        77836 Rheinmuenster
        Germany
        Tel: +49(0)7229/1847-0
        Fax: +49(0)7229/1847-200
        http://www.addi-data-com
        info@addi-data.com
 
 This library is free software; you can redistribute it and/or modify it under 
 the terms of the GNU Lesser General Public License as published by the 
 Free Software Foundation; either version 2.1 of the License, 
 or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful, 
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 or FITNESS FOR A PARTICULAR PURPOSE. 
 See the GNU Lesser General Public License for more details.
 
 You should have received a copy of the GNU Lesser General Public License 
 along with this library; if not, write to the Free Software Foundation, 
 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
 
 You also shoud find the complete LGPL in the LGPL.txt file accompanying 
 this source code.
 
 @endverbatim
**/


#ifndef __APCIE2200KAPI_H__
#define __APCIE2200KAPI_H__

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

#ifdef __KERNEL__

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

/** Read all digital inputs of the APCIE-2200.
 *
 * @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 APCIE2200_Read16DigitalInputs(struct pci_dev *pdev, uint32_t * PortState);

/** Get the number of digital inputs of the APCIE-2200.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 *
 * @retval Number of inputs.
 */
int APCIE2200_GetNumberOfDigitalInputs (struct pci_dev *pdev);

/** Set all digital outputs of the APCIE-2200 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 APCIE2200_Set16DigitalOutputsOn(struct pci_dev *pdev, uint32_t arg);

 /** Set all digital outputs of the APCIE-2200 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 APCIE2200_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 APCIE2200_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 APCIE2200_SetDigitalOutputMemoryOff(struct pci_dev *pdev);

/** Get all digital outputs states of the APCIE-2200.
 *
 * @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 APCIE2200_Get16DigitalOutputStatus(struct pci_dev *pdev, uint32_t * PortState);

/** Get the number of digital outputs of the APCIE-2200.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 *
 * @retval Number of outputs.
 */
int APCIE2200_GetNumberOfDigitalOutputs (struct pci_dev *pdev);

/** find a apci 2200 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 * apcie2200_lookup_board_by_index(unsigned int index);

typedef void APCIE2200_user_interrupt_t(struct pci_dev *pdev, apcie2200_event_t* evt);

/** Set the user interrupt callback  
 *
 * User interrupt callback is function of type APCIE2200_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 APCIE2200_SetInterruptCallback(struct pci_dev *pdev, APCIE2200_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 APCIE2200_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-2200.
 * @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 APCIE2200_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 APCIE2200_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 APCIE2200_GetDigitalInputInterruptConfig (struct pci_dev *pdev, int * Enabled, int * InterruptLogic, uint32_t * InterruptMaskMode1, uint32_t * InterruptMaskMode2);

/** Configure the timer / watchdog, then start it.
 *
 * @param [in] pdev: Device to manage.
 *
 * @param [in] ressourceType:	0: Watchdog
 *								1: Timer
 *
 * @param [in] mode: At this time only mode 2 is available (value 2).
 *
 * @param [in] timeBaseUnit: Unit for the time base.
 * 							us: 1
 *							ms: 2
 *							s:  3
 *
 * @param [in] timeBaseValue: Timer / Watchdog reload value.
 * 								12 Bit for Watchdog.
 * 								16 Bit for Timer.
 *
 * @param [in] irq: 1: Enable interrupt
 * 					0: Disable interrupt
 *
 * @retval 0: No error.
 * @retval -EINVAL: Error.
 */
int APCIE2200_TimerWatchdogInitAndStart (struct pci_dev *pdev, uint32_t ressourceType, uint32_t mode, uint32_t timeBaseUnit, uint32_t timeBaseValue, uint32_t irq);

/** Release the timer / watchdog
 *
 * @param [in] pdev: Device to manage.
 *
 * @param [in] ressourceType:	0: Watchdog
 *								1: Timer
 *
 * @retval 0: No error.
 * @retval -EINVAL: Error.
 */
int APCIE2200_TimerWatchdogStopAndRelease (struct pci_dev *pdev, uint32_t ressourceType);

/** Trigger the timer / watchdog
 *
 * @param [in] pdev: Device to manage.
 *
 * @param [in] ressourceType:	0: Watchdog
 *								1: Timer
 *
 * @retval 0: No error.
 * @retval -EINVAL: Error.
 */
int APCIE2200_TimerWatchdogTrigger (struct pci_dev *pdev, uint32_t ressourceType);

/** Read the timer / watchdog value
 *
 * @param [in] pdev: Device to manage.
 *
 * @param [in] ressourceType:	0: Watchdog
 *								1: Timer
 *
 * @param [out] Value: Read value.
 *
 * @retval 0: No error.
 * @retval -EINVAL: Error.
 */
int APCIE2200_TimerWatchdogRead (struct pci_dev *pdev, uint32_t ressourceType, uint32_t *value);

/** Get the timer / watchdog status
 *
 * @param [in] pdev: Device to manage.
 *
 * @param [in] ressourceType:	0: Watchdog
 *								1: Timer
 *
 * @param [out] status: D[0]: 1: Timer overflow
 * 						D[1]: 1: Software trigger
 *
 * @retval 0: No error.
 * @retval -EINVAL: Error.
 */
int APCIE2200_TimerWatchdogGetStatus (struct pci_dev *pdev, uint32_t ressourceType, uint32_t *status);

#endif// __KERNEL__


#endif /*__APCIE2200KAPI_H__*/
