/** @file dig_io-kapi.c

   Contains digital I/O kernel functions.

   @par CREATION
   @author Krauth Julien
   @date   13.07.2007

   @par VERSION
   @verbatim
   $LastChangedRevision:$
   $LastChangedDate:$
   @endverbatim

   @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 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 "apci3120-private.h"

EXPORT_SYMBOL(i_APCI3120_Read4DigitalInput);
EXPORT_SYMBOL(i_APCI3120_SetOutputMemoryOn);
EXPORT_SYMBOL(i_APCI3120_SetOutputMemoryOff);
EXPORT_SYMBOL(i_APCI3120_Set4DigitalOutputOn);
EXPORT_SYMBOL(i_APCI3120_Set4DigitalOutputOff);

/**@def EXPORT_NO_SYMBOLS
 * Function in this file are not exported.
 */
EXPORT_NO_SYMBOLS;

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

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

    if (!pdev) return 1;

    *b_DigitalInputValue = (XPCI3120_INW(pdev, (GET_BASE_IO(pdev) + APCI3120_REG_DIGITAL_INPUT)) >> 8) & 0xF;

    return 0;
}

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

/** Set digital output memory on.
 *
 * When output memory is setting on. Output state is holding, and <br>
 * the new output(s) is(are) set or reset.
 *
 * @param [in] pdev                 : The device to manage.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 */
int i_APCI3120_SetOutputMemoryOn (struct pci_dev *pdev)
{
    if (!pdev) return 1;

		APCI3120_PRIVDATA(pdev)->crt0.digOutReg = 0;
      APCI3120_PRIVDATA(pdev)->digOutMem = APCI3120_ENABLE;

    return 0;
}

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

/** Set digital output memory off.
 *
 * @param [in] pdev                 : The device to manage.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 */
int i_APCI3120_SetOutputMemoryOff (struct pci_dev *pdev)
{
    if (!pdev) return 1;

      APCI3120_PRIVDATA(pdev)->digOutMem = APCI3120_DISABLE;
		APCI3120_PRIVDATA(pdev)->crt0.digOutReg = 0;

    return 0;
}

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

/** Set 4 digital output on.
 *
 * @param [in] pdev                 : The device to manage.
 * @param [in] b_DigitalOutputValue : Digital output value.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The digital output value is wrong.
 */
int i_APCI3120_Set4DigitalOutputOn (struct pci_dev *pdev, uint8_t b_DigitalOutputValue)
{

    if (!pdev) return 1;

    if (b_DigitalOutputValue > 0xF) return 2;

    if (APCI3120_PRIVDATA(pdev)->digOutMem == APCI3120_ENABLE)
    {
       APCI3120_PRIVDATA(pdev)->crt0.digOutReg |= b_DigitalOutputValue;
    }
    else
    {
       APCI3120_PRIVDATA(pdev)->crt0.digOutReg = b_DigitalOutputValue;
    }

    outb(APCI3120_PRIVDATA(pdev)->crt0.raw, (GET_BASE_IO(pdev) + APCI3120_REG_DIGITAL_OUTPUT));

    return 0;
}

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

/** Set 4 digital output off.
 *
 * Can only be used when i_APCI3120_SetOutputMemoryOn has been called.
 *
 * @param [in] pdev                 : The device to manage.
 * @param [in] b_DigitalOutputValue : Digital output value.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The digital output value is wrong.
 * @retval 3: Output memory is not activated (please use i_APCI3120_SetOutputMemoryOn).
 */
int i_APCI3120_Set4DigitalOutputOff (struct pci_dev *pdev, uint8_t b_DigitalOutputValue)
{
    if (!pdev) return 1;

    if (b_DigitalOutputValue > 0xF) return 2;

    if (APCI3120_PRIVDATA(pdev)->digOutMem != APCI3120_ENABLE) return 3;

    APCI3120_PRIVDATA(pdev)->crt0.digOutReg &= (0xF-b_DigitalOutputValue);

    outb(APCI3120_PRIVDATA(pdev)->crt0.raw, (GET_BASE_IO(pdev) + APCI3120_REG_DIGITAL_OUTPUT));

    return 0;
}

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

