/** @file dig_io-kapi.c
 
   Contains digital input functions.
 
   @par CREATION  
   @author Krauth Julien
   @date   03.04.2007
   
   @par VERSION
   @verbatim
   $LastChangedRevision:$
   $LastChangedDate:$
   @endverbatim   
   
   @par LICENCE
   @verbatim
   Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
        
        ADDI-DATA GmbH 
        Dieselstrasse 3 
        D-77833 Ottersweier 
        Tel: +19(0)7223/9493-0 
        Fax: +49(0)7223/9493-92 
        http://www.addi-data-com 
        info@addi-data.com 
        
   This program is free software; you can redistribute it and/or modify it under 
   the terms of the GNU General Public License as published by the Free Software 
   Foundation; either version 2 of the License, or (at your option) any later version.

   This program 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 General Public License for more details.

   You should have received a copy of the GNU General Public License along with 
   this program; if not, write to the Free Software Foundation, 
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

   You shoud also find the complete GPL in the COPYING file 
   accompanying this source code.
   @endverbatim   
 */ 

#include "apci2200-private.h"

EXPORT_SYMBOL(i_APCI2200_Read8DigitalInput);
EXPORT_SYMBOL(i_APCI2200_SetDigitalOutputMemoryOn);
EXPORT_SYMBOL(i_APCI2200_SetDigitalOutputMemoryOff);
EXPORT_SYMBOL(i_APCI2200_Set1DigitalOutputOn);
EXPORT_SYMBOL(i_APCI2200_Set1DigitalOutputOff);
EXPORT_SYMBOL(i_APCI2200_Set8DigitalOutputOn);
EXPORT_SYMBOL(i_APCI2200_Set8DigitalOutputOff);
EXPORT_SYMBOL(i_APCI2200_Set16DigitalOutputOn);
EXPORT_SYMBOL(i_APCI2200_Set16DigitalOutputOff);
EXPORT_SYMBOL(i_APCI2200_Read16DigitalOutput);

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

/** Read 8 digital input.                                                 
 * 
 * @param [in] pdev                 : The device to initialize.
 * @param [out] b_DigitalInputValue : Digital input value.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 */
int   i_APCI2200_Read8DigitalInput (struct pci_dev *pdev, uint8_t *b_DigitalInputValue)
	{

    if (!pdev) return 1;
    
    *b_DigitalInputValue = (uint8_t) (inb((GET_BAR1(pdev) + APCI2200_DIGITAL_INPUT)) & 0xFF);

	return 0;
}    

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

/** Set digital ouptput memory on.          
 * 
 * After having called up this function, the output you have previously
 * activated with the function "i_APCI2200_SetXDigitalOutputOn" are not reset.
 * You can reset them with the function "i_APCI2200_SetXDigitalOutputOff".                                         
 * 
 * @param [in] pdev                 : The device to initialize.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: Output memory is already set on.
 */
int   i_APCI2200_SetDigitalOutputMemoryOn (struct pci_dev *pdev)
	{

    if (!pdev) return 1;
    
    if (APCI2200_PRIVDATA(pdev)->OutputMemoryStatus == APCI2200_ENABLE)
    	return 2;  	
    	
    APCI2200_PRIVDATA(pdev)->OutputMemoryStatus = APCI2200_ENABLE;

	return 0;
} 

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

/** Set digital ouptput memory off.                                                 
 * 
 * @param [in] pdev                 : The device to initialize.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: Output memory is already set off.
 */
int   i_APCI2200_SetDigitalOutputMemoryOff (struct pci_dev *pdev)
	{

    if (!pdev) return 1;
    
    if (APCI2200_PRIVDATA(pdev)->OutputMemoryStatus == APCI2200_DISABLE)
    	return 2;
    	
    APCI2200_PRIVDATA(pdev)->OutputMemoryStatus = APCI2200_DISABLE;
      
	return 0;
}   

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

/** Set 1 digital output on.                                                 
 * 
 * @param [in] pdev            : The device to initialize.
 * @param [in] b_DigitalOutput : Digital output channel.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: Wrong digital output (0 to 15).
 */
int i_APCI2200_Set1DigitalOutputOn (struct pci_dev *pdev, uint8_t b_DigitalOutput)
{
    uint16_t tmp = 0;

    if (!pdev) return 1;
    
    if (b_DigitalOutput > 15)
    	return 2;
    
    if (APCI2200_PRIVDATA(pdev)->OutputMemoryStatus == APCI2200_ENABLE)
    {
	tmp = (uint16_t) (inw((GET_BAR1(pdev) + APCI2200_DIGITAL_OUTPUT)) & 0xFFFF);
	tmp = tmp | (1 << b_DigitalOutput); 
    } 
    else
    {
	tmp = (1 << b_DigitalOutput);
    }
 
    outw(tmp, (GET_BAR1(pdev) + APCI2200_DIGITAL_OUTPUT));

    return 0;
}    

//----------------------------------------------------------------------------
      
/** Set 1 digital output off.                                                 
 * 
 * @param [in] pdev            : The device to initialize.
 * @param [in] b_DigitalOutput : Digital output channel.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: Digital output memory is not activated.
 * @retval 3: Wrong digital output (0 to 15).
 */
int i_APCI2200_Set1DigitalOutputOff (struct pci_dev *pdev, uint8_t b_DigitalOutput)
{
    uint16_t tmp = 0;

    if (!pdev) return 1;
       
    if (APCI2200_PRIVDATA(pdev)->OutputMemoryStatus == APCI2200_DISABLE)
        return 2;
		
    if (b_DigitalOutput > 15)
    	return 3;		

    tmp = (uint16_t) (inw((GET_BAR1(pdev) + APCI2200_DIGITAL_OUTPUT)) & 0xFFFF);
    tmp = tmp & (0xFFFF - (1 << b_DigitalOutput));
    outw(tmp, (GET_BAR1(pdev) + APCI2200_DIGITAL_OUTPUT));
     
    return 0;
} 

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

/** Set 8 digital output on.                                                 
 * 
 * @param [in] pdev        : The device to initialize.
 * @param [in] b_Port      : The port to set (0: Port 1, 1: Port 2).
 * @param [in] b_PortValue : Port value (0 to 0xFF).
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The port parameter of the board is wrong (has to be 0: Port 1, 1: Port 2).
 */
int   i_APCI2200_Set8DigitalOutputOn (struct pci_dev *pdev, uint8_t b_Port, uint8_t b_PortValue)
{
	uint16_t tmp = 0;

    if (!pdev) return 1;
    
    if (b_Port > 1) return 2;   
    
	if (APCI2200_PRIVDATA(pdev)->OutputMemoryStatus == APCI2200_ENABLE)
	{
		tmp = (uint16_t) (inw((GET_BAR1(pdev) + APCI2200_DIGITAL_OUTPUT)) & 0xFFFF);
		tmp = tmp | (b_PortValue << (8 * b_Port)); 
	}
	else 
		tmp = (b_PortValue << (8 * b_Port));
     
    outw(tmp, (GET_BAR1(pdev) + APCI2200_DIGITAL_OUTPUT));

	return 0;
}    

//----------------------------------------------------------------------------
      
/** Set 8 digital output off.                                                 
 * 
 * @param [in] pdev        : The device to initialize.
 * @param [in] b_Port      : The port to set (0: Port 1, 1: Port 2).
 * @param [in] b_PortValue : Port value (0 to 0xFF).
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The port parameter of the board is wrong (has to be 0: Port 1, 1: Port 2).
 * @retval 3: Digital output memory is not activated.
 */
int   i_APCI2200_Set8DigitalOutputOff (struct pci_dev *pdev, uint8_t b_Port, uint8_t b_PortValue)
{
	uint16_t tmp = 0;

    if (!pdev) return 1;
    
    if (b_Port > 1) return 2;   
    
	if (APCI2200_PRIVDATA(pdev)->OutputMemoryStatus == APCI2200_DISABLE)
		return 3;
	
	tmp = (uint16_t) (inw((GET_BAR1(pdev) + APCI2200_DIGITAL_OUTPUT)) & 0xFFFF);
	tmp = tmp & (0xFFFF - (b_PortValue << (8 * b_Port))); 
    outw(tmp, (GET_BAR1(pdev) + APCI2200_DIGITAL_OUTPUT));

	return 0;
}  

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

/** Set 16 digital output on.                                                 
 * 
 * @param [in] pdev                 : The device to initialize.
 * @param [in] w_DigitalOutputValue : Digital output value.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 */
int   i_APCI2200_Set16DigitalOutputOn (struct pci_dev *pdev, uint16_t w_DigitalOutputValue)
{
	uint16_t tmp = 0;

    if (!pdev) return 1;
    
	if (APCI2200_PRIVDATA(pdev)->OutputMemoryStatus == APCI2200_ENABLE)
	{
		tmp = (uint16_t) (inw((GET_BAR1(pdev) + APCI2200_DIGITAL_OUTPUT)) & 0xFFFF);
		tmp = tmp | (w_DigitalOutputValue & 0xFFFF); 
	}
	else 
		tmp = (w_DigitalOutputValue & 0xFFFF); 
     
    outw(tmp, (GET_BAR1(pdev) + APCI2200_DIGITAL_OUTPUT));

	return 0;
}    

//----------------------------------------------------------------------------
      
/** Set 16 digital output off.                                                 
 * 
 * @param [in] pdev                 : The device to initialize.
 * @param [in] w_DigitalOutputValue : Digital output value.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: Digital output memory is not activated.
 */
int   i_APCI2200_Set16DigitalOutputOff (struct pci_dev *pdev, uint16_t w_DigitalOutputValue)
{
	uint16_t tmp = 0;

    if (!pdev) return 1;
    
	if (APCI2200_PRIVDATA(pdev)->OutputMemoryStatus == APCI2200_DISABLE)
		return 2;
		
	tmp = (uint16_t) (inw((GET_BAR1(pdev) + APCI2200_DIGITAL_OUTPUT)) & 0xFFFF);
	tmp = tmp & (~(w_DigitalOutputValue & 0xFFFF)); 
    outw(tmp, (GET_BAR1(pdev) + APCI2200_DIGITAL_OUTPUT));

	return 0;
}  

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

/** Read 16 digital output.                                                 
 * 
 * @param [in] pdev                 : The device to initialize.
 * @param [in] w_DigitalOutputValue : Digital output value.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 */
int   i_APCI2200_Read16DigitalOutput (struct pci_dev *pdev, uint16_t *w_DigitalOutputValue)
	{

    if (!pdev) return 1;
      
    *w_DigitalOutputValue = (uint16_t) (inw((GET_BAR1(pdev) + APCI2200_DIGITAL_OUTPUT)) & 0xFFFF);

	return 0;
}    

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



