/** 82C54.c
 *
 *  Author: P. Ferkous 
 *  Creation: 27.06.2019
 *  $LastChangedDate: 2017-04-28 15:16:10 +0100 (Fri, 28 Apr 2017) $
 *  $LastChangedRevision: 1495 $
 *
 *  Copyright (C) 2019 ADDI-DATA GmbH
 *
 *  ADDI-DATA GmbH
 *  Airpark Business Center
 *  Airport Boulevard B210
 *  77836 Rheinmünster
 *  Germany
 *  Tel: +49(0)7229/1847-0    |  Fax: +49(0)7229/1847-200
 *  http://www.addi-data-com  |  info@addi-data.com
 **/

/***********************************************/

#include "apci1710-private.h"
/**@def EXPORT_NO_SYMBOLS
 * Function in this file are not exported.
 */
EXPORT_NO_SYMBOLS;

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27)
#define __user 
#endif
/***********************************************/

int do_CMD_APCI1710_ReadInterruptMask(struct pci_dev *pdev,unsigned int cdm, unsigned long arg)
{
  int i_ErrorCode = 0;
  uint32_t ui_ArgArray[2];
  if ( copy_from_user( ui_ArgArray, (uint32_t __user *)arg, sizeof(ui_ArgArray)))
    return -EFAULT;
  {
    unsigned long irqstate;
    APCI1710_LOCK(pdev,&irqstate);
    {        
        i_ErrorCode = i_APCI1710_ReadInterruptMask(pdev,
                                                  (uint8_t)ui_ArgArray[0],    // ui_ModulNbr
                                                  &ui_ArgArray[1]);    //dw_interruptMask 
    }
    APCI1710_UNLOCK(pdev,irqstate);
  } 
  return i_ErrorCode;

  if (i_ErrorCode)
    return i_ErrorCode;

  if ( copy_to_user( (uint32_t __user *)arg , &ui_ArgArray[1], sizeof(ui_ArgArray[1]) ) )
    return -EFAULT;

  return 0;
}

/***********************************************/

int do_CMD_APCI1710_InitTimer(struct pci_dev *pdev, unsigned int cdm, unsigned long arg)
{
  int i_ErrorCode = 0;
  uint32_t ui_ArgArray[8];
  if ( copy_from_user( ui_ArgArray, (uint32_t __user *)arg, sizeof(ui_ArgArray)))
    return -EFAULT;
  {
    unsigned long irqstate;
    APCI1710_LOCK(pdev,&irqstate);
    {        
        i_ErrorCode = i_APCI1710_InitTimer (pdev,
                                                  (uint8_t)ui_ArgArray[0],    // ui_ModulNbr
                                                  (uint8_t)ui_ArgArray[1],    // ui_timerNbr
                                                  (uint8_t)ui_ArgArray[2],    // ui_timerMode
                                                  (uint8_t)ui_ArgArray[3],    // ui_inputClk
                                                  (uint8_t)ui_ArgArray[4],    // ui_inputClkLevel
                                                  (uint8_t)ui_ArgArray[5],    // ui_outputLevel  
                                                  (uint8_t)ui_ArgArray[6],    // ui_hardGate
                                                  ui_ArgArray[7]);            // dw_reloadValue
    }
    APCI1710_UNLOCK(pdev,irqstate);
  } 
  return i_ErrorCode;
}

/***********************************************/
int do_CMD_APCI1710_EnableTimer(struct pci_dev *pdev, unsigned int cdm, unsigned long arg)
{
  int i_ErrorCode = 0;
  uint8_t ui_ArgArray[3];
  if ( copy_from_user( ui_ArgArray, (uint8_t __user *)arg, sizeof(ui_ArgArray)))
    return -EFAULT;
  {
    unsigned long irqstate;
    APCI1710_LOCK(pdev,&irqstate);
    {        
        i_ErrorCode = i_APCI1710_EnableTimer(pdev,
                                                  ui_ArgArray[0],    // ui_ModulNbr
                                                  ui_ArgArray[1],    // ui_timerNbr
                                                  ui_ArgArray[2]);   // ui_interruptFlag
    }
    APCI1710_UNLOCK(pdev,irqstate);
  } 
  return i_ErrorCode;
}

int do_CMD_APCI1710_DisableTimer(struct pci_dev *pdev, unsigned int cdm, unsigned long arg)
{
  int i_ErrorCode = 0;
  uint8_t ui_ArgArray[2];
  if ( copy_from_user( ui_ArgArray, (uint8_t __user *)arg, sizeof(ui_ArgArray)))
    return -EFAULT;
  {
    unsigned long irqstate;
    APCI1710_LOCK(pdev,&irqstate);
    {        
        i_ErrorCode = i_APCI1710_DisableTimer(pdev,
                                                  ui_ArgArray[0],    // ui_ModulNbr
                                                  ui_ArgArray[1]);   // ui_timerNbr
    }
    APCI1710_UNLOCK(pdev,irqstate);
  } 
  return i_ErrorCode;
}

int do_CMD_APCI1710_ReadTimerValue(struct pci_dev *pdev, unsigned int cdm, unsigned long arg)
{
  int i_ErrorCode = 0;
  uint32_t ui_ArgArray[3];
  if ( copy_from_user( ui_ArgArray, (uint32_t __user *)arg, sizeof(ui_ArgArray)))
    return -EFAULT;
  {
    unsigned long irqstate;
    APCI1710_LOCK(pdev,&irqstate);
    {        
        i_ErrorCode = i_APCI1710_ReadTimerValue(pdev,
                                                  (uint8_t)ui_ArgArray[0],    // ui_ModulNbr
                                                  (uint8_t)ui_ArgArray[1],    // ui_timerNbr
                                                  &ui_ArgArray[2]);   // ui_value 
    }
    APCI1710_UNLOCK(pdev,irqstate);
  } 

  if (i_ErrorCode)
    return i_ErrorCode;
  if ( copy_to_user( (uint32_t __user *)arg+2 , &ui_ArgArray[2], sizeof(ui_ArgArray[2]) ) )
    return -EFAULT;

  return 0;
}
int do_CMD_APCI1710_ReadAllTimerValues(struct pci_dev *pdev, unsigned int cdm, unsigned long arg)
{
  int i_ErrorCode = 0;
  uint32_t ui_ArgArray[4];
  if ( copy_from_user( ui_ArgArray, (uint32_t __user *)arg, sizeof(ui_ArgArray)))
    return -EFAULT;
  {
    unsigned long irqstate;
    APCI1710_LOCK(pdev,&irqstate);
    {        
        i_ErrorCode = i_APCI1710_ReadAllTimerValues(pdev,
                                                    (uint8_t)ui_ArgArray[0],    // ui_ModulNbr
                                                    &ui_ArgArray[1]);   // ui_outputLevel 
    }
    APCI1710_UNLOCK(pdev,irqstate);
  } 

  if (i_ErrorCode)
    return i_ErrorCode;

  if ( copy_to_user( (uint32_t __user *)arg+1 , &ui_ArgArray[1], sizeof(ui_ArgArray[1])*3 ) )
    return -EFAULT;

  return 0;
}
/***********************************************/
int do_CMD_APCI1710_GetTimerOutputLevel(struct pci_dev *pdev, unsigned int cdm, unsigned long arg)
{
  int i_ErrorCode = 0;
  uint8_t ui_ArgArray[3];
  if ( copy_from_user( ui_ArgArray, (uint8_t __user *)arg, sizeof(ui_ArgArray)))
    return -EFAULT;
  {
    unsigned long irqstate;
    APCI1710_LOCK(pdev,&irqstate);
    {        
        i_ErrorCode = i_APCI1710_GetTimerOutputLevel(pdev,
                                                  ui_ArgArray[0],    // ui_ModulNbr
                                                  ui_ArgArray[1],    // ui_timerNbr
                                                  &ui_ArgArray[2]);   // ui_outputLevel 
    }
    APCI1710_UNLOCK(pdev,irqstate);
  } 

  if (i_ErrorCode)
    return i_ErrorCode;

  if ( copy_to_user( (uint8_t __user *)arg+2 , &ui_ArgArray[2], sizeof(ui_ArgArray[2]) ) )
    return -EFAULT;

  return 0;
}

/***********************************************/
int do_CMD_APCI1710_WriteTimerValue(struct pci_dev *pdev, unsigned int cdm, unsigned long arg)
{
  int i_ErrorCode = 0;
  uint32_t ui_ArgArray[3];
  if ( copy_from_user( ui_ArgArray, (uint32_t __user *)arg, sizeof(ui_ArgArray)))
    return -EFAULT;
  {
    unsigned long irqstate;
    APCI1710_LOCK(pdev,&irqstate);
    {        
        i_ErrorCode = i_APCI1710_WriteTimerValue(pdev,
                                                        (uint8_t)ui_ArgArray[0],    // ui_ModulNbr
                                                        (uint8_t)ui_ArgArray[1],    // ui_timerNbr
                                                        ui_ArgArray[2]);            // ui_value
    }
    APCI1710_UNLOCK(pdev,irqstate);
  } 
  return i_ErrorCode;
}

/***********************************************/
int do_CMD_APCI1710_GetTimerProgressStatus(struct pci_dev *pdev, unsigned int cdm, unsigned long arg)
{
  int i_ErrorCode = 0;
  uint8_t ui_ArgArray[3];
  if ( copy_from_user( ui_ArgArray, (uint32_t __user *)arg, sizeof(ui_ArgArray)))
    return -EFAULT;
  {
    unsigned long irqstate;
    APCI1710_LOCK(pdev,&irqstate);
    {        
        i_ErrorCode = i_APCI1710_GetTimerProgressStatus(pdev,
                                                        (uint8_t)ui_ArgArray[0],    // ui_ModulNbr
                                                        (uint8_t)ui_ArgArray[1],    // ui_timerNbr
                                                        &ui_ArgArray[2]);           // ui_value
    }
    APCI1710_UNLOCK(pdev,irqstate);
  }
  if (i_ErrorCode)
    return i_ErrorCode;

  if ( copy_to_user( (uint8_t __user *)arg+2 , &ui_ArgArray[2], sizeof(ui_ArgArray[2]) ) )
    return -EFAULT;

  return i_ErrorCode;
}

/***********************************************/
int do_CMD_APCI1710_GetTimerProgressStatusEx(struct pci_dev *pdev, unsigned int cdm, unsigned long arg)
{
  int i_ErrorCode = 0;
  uint8_t ui_ArgArray[3];
  if ( copy_from_user( ui_ArgArray, (uint32_t __user *)arg, sizeof(ui_ArgArray)))
    return -EFAULT;
  {
    unsigned long irqstate;
    APCI1710_LOCK(pdev,&irqstate);
    {        
        i_ErrorCode = i_APCI1710_GetTimerProgressStatusEx(pdev,
                                                          (uint8_t)ui_ArgArray[0],    // ui_ModulNbr
                                                          (uint8_t)ui_ArgArray[1],    // ui_timerNbr
                                                          &ui_ArgArray[2]);           // ui_value
    }
    APCI1710_UNLOCK(pdev,irqstate);
  }
  if (i_ErrorCode)
    return i_ErrorCode;

  if ( copy_to_user( (uint8_t __user *)arg+2 , &ui_ArgArray[2], sizeof(ui_ArgArray[2]) ) )
    return -EFAULT;

  return i_ErrorCode;
}
