/** @file pwm.c

   Contains PWM ioctl functions.

   @par CREATION
   @author Pravin
   @date   1.12.2015

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

   @par LICENCE
   @verbatim
    Copyright (C) 2013  ADDI-DATA GmbH for the source code of this module.

    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

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

EXPORT_NO_SYMBOLS;

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

/*
+----------------------------------------------------------------------------+
| Function Name     : int i_APCI1710_InitPWM                               |
|                                       (uint8_t_     b_BoardHandle,            |
|                                        uint8_t_     b_ModulNbr,               |
|                                        uint8_t_     b_PWM,                    |
|                                        uint8_t_     b_ClockSelection,         |
|                                        uint8_t_     b_TimingUnit,             |
|                                        uint32_t   ul_LowTiming,              |
|                                        uint32_t   ul_HighTiming)         |
+----------------------------------------------------------------------------+
| Task              : Configure the selected PWM (b_PWM) from selected module|
|                     (b_ModulNbr). The ul_LowTiming, ul_HighTiming and      |
|                     ul_TimingUnit determine the low/high timing base for   |
|                     the period. pul_RealLowTiming, pul_RealHighTiming      |
|                     return the real timing value.                          |
|                     You must calling this function be for you call any     |
|                     other function witch access of the PWM.                |
+----------------------------------------------------------------------------+
| Input Parameters  : uint8_t_     b_BoardHandle    : Handle of board APCI-1710 |
|                     uint8_t_     b_ModulNbr       : Module number to configure|
|                                                  (0 to 3)                  |
|                     uint8_t_     b_PWM            : Selected PWM (0 or 1).    |
|                     uint8_t_     b_ClockSelection : Selection from PCI bus    |
|                                                  clock                     |
|                                                   - APCI1710_30MHZ :       |
|                                                     The PC have a 30 MHz   |
|                                                     PCI bus clock          |
|                                                   - APCI1710_33MHZ :       |
|                                                     The PC have a 33 MHz   |
|                                                     PCI bus clock          |
|                                                   - APCI1710_40MHZ         |
|                                                     The APCI-1710 have a   |
|                                                     integrated 40Mhz       |
|                                                     quartz.                |
|                     uint8_t_     b_TimingUnit     : Base timing Unit (0 to 4) |
|                                                       0 : ns               |
|                                                       1 : �s               |
|                                                       2 : ms               |
|                                                       3 : s                |
|                                                       4 : mn               |
|                     uint32_t    ul_LowTiming     : Low base timing value.    |
|                     uint32_t    ul_HighTiming    : High base timing value.   |
+----------------------------------------------------------------------------+
| Output Parameters :                   								     |
+----------------------------------------------------------------------------+
| Return Value     : 0: No error                                            |
|                    1: Module selection wrong                              |
|                    2: The module is not a PWM module                      |
|                    3: PWM selection is wrong                              |
|                    4: The selected input clock is wrong                   |
|                    5: Timing Unit selection is wrong                      |
|                    6: Low base timing selection is wrong                  |
|                    7: High base timing selection is wrong                 |
|                    8: You can not used the 40MHz clock selection with     |
|                        this board                                          |
+----------------------------------------------------------------------------+
*/

int do_CMD_APCI1710_InitPWM(struct pci_dev *pdev, unsigned int cmd, unsigned long arg)
{
	uint32_t argArray[6]= {0};
	int i_ErrorCode = 0;

	if (copy_from_user(argArray, (uint32_t __user *)arg, sizeof(argArray)))
		return -EFAULT;

	{
		unsigned long irqstate;
		APCI1710_LOCK(pdev,&irqstate);

		i_ErrorCode = i_APCI1710_InitPWM(pdev,
									  (uint8_t)argArray[0],  // ModulNbr
									  (uint8_t)argArray[1],  // PWM Module
									  (uint8_t)argArray[2],  // clock selection
									  (uint8_t)argArray[3],  // Timing unit
									  (uint32_t)argArray[4],  // Low_timing
									  (uint32_t)argArray[5]); // High_timing

		APCI1710_UNLOCK(pdev,irqstate);
	}
	if (i_ErrorCode != 0)
		return (i_ErrorCode);


	return 0;
}


/*
+----------------------------------------------------------------------------+
| Function Name     : int i_APCI1710_SetNewPWMTiming                           |
|                                       (uint8_t_     b_BoardHandle,           |
|                                        uint8_t_     b_ModulNbr,              |
|                                        uint8_t_     b_PWM,                   |
|                                        uint8_t_     b_ClockSelection,        |
|                                        uint8_t_     b_TimingUnit,            |
|                                        uint32_t   ul_LowTiming,              |
|                                        uint32_t   ul_HighTiming)             |
+----------------------------------------------------------------------------+
| Task              : Set a new timing. The ul_LowTiming, ul_HighTiming and  |
|                     ul_TimingUnit determine the low/high timing base for   |
|                     the period.                                            |
+----------------------------------------------------------------------------+
| Input Parameters  : uint8_t_     b_BoardHandle    : Handle of board APCI-1710 |
|                     uint8_t_     b_ModulNbr       : Module number to configure|
|                                                  (0 to 3)                  |
|                     uint8_t_     b_PWM            : Selected PWM (0 or 1).    |
|                     uint8_t_     b_TimingUnit     : Base timing Unit (0 to 4) |
|                                                       0 : ns               |
|                                                       1 : �s               |
|                                                       2 : ms               |
|                                                       3 : s                |
|                                                       4 : mn               |
|                     uint32_t    ul_LowTiming     : Low base timing value.    |
|                     uint32_t    ul_HighTiming    : High base timing value.   |
+----------------------------------------------------------------------------+
| Output Parameters : -                                                      |
+----------------------------------------------------------------------------+
| Return Value     : 0: No error                                            |
|                    1: Module selection wrong                              |
|                    2: The module is not a PWM module                      |
|                    3: PWM selection is wrong                              |
|                    4: PWM not initialised                                 |
|                    5: Timing Unit selection is wrong                      |
|                    6: Low base timing selection is wrong                  |
|                    7: High base timing selection is wrong                 |
+----------------------------------------------------------------------------+
*/
int do_CMD_APCI1710_SetNewPWMTiming(struct pci_dev *pdev, unsigned int cmd, unsigned long arg)
{
	uint32_t argArray[5]= {0};
	int i_ErrorCode = 0;

	if (copy_from_user(argArray, (uint32_t __user *)arg, sizeof(argArray)))
		return -EFAULT;

	{
		unsigned long irqstate;
		APCI1710_LOCK(pdev,&irqstate);

		i_ErrorCode = i_APCI1710_SetNewPWMTiming(pdev,
		                          (uint8_t)argArray[0],   // ModulNbr
		                          (uint8_t)argArray[1],   // b_PWM
		                          (uint8_t)argArray[2],   // b_Timingunit
		                          (uint32_t)argArray[3],  // ul_Lowtiming
                                          (uint32_t)argArray[4]); // ul_Hightiming


		APCI1710_UNLOCK(pdev,irqstate);
	}
	if (i_ErrorCode != 0)
		return (i_ErrorCode);

	return 0;
}
/*
+----------------------------------------------------------------------------+
| Function Name     : int     i_APCI1710_EnablePWM                         |
|                                       (uint8_t_  b_BoardHandle,               |
|                                        uint8_t_  b_ModulNbr,                  |
|                                        uint8_t_  b_PWM,                       |
|                                        uint8_t_  b_StartLevel,                |
|                                        uint8_t_  b_StopMode,                  |
|                                        uint8_t_  b_StopLevel,                 |
|                                        uint8_t_  b_ExternGate,                |
|                                        uint8_t_  b_InterruptEnable)           |
+----------------------------------------------------------------------------+
| Task              : Enable the selected PWM (b_PWM) from selected module   |
|                     (b_ModulNbr). You must calling the "i_APCI1710_InitPWM"|
|                     function be for you call this function.                |
|                     If you enable the PWM interrupt, the PWM generate a    |
|                     interrupt after each period.                           |
|                     See function "i_APCI1710_SetBoardIntRoutineX" and the  |
|                     Interrupt mask description chapter.                    |
+----------------------------------------------------------------------------+
| Input Parameters  : uint8_t_ b_BoardHandle     : Handle of board APCI-1710    |
|                     uint8_t_ b_ModulNbr        : Selected module number       |
|                                               (0 to 3)                     |
|                     uint8_t_ b_PWM             : Selected PWM (0 or 1)        |
|                     uint8_t_ b_StartLevel      : Start period level selection |
|                                                0 : The period start with a |
|                                                    low level               |
|                                                1 : The period start with a |
|                                                    high level              |
|                     uint8_t_ b_StopMode        : Stop mode selection          |
|                                                0 : The PWM is stopped      |
|                                                    directly after the      |
|                                                    "i_APCI1710_DisablePWM" |
|                                                    function and break the  |
|                                                    last period             |
|                                                1 : After the               |
|                                                    "i_APCI1710_DisablePWM" |
|                                                     function the PWM is    |
|                                                     stopped at the end from|
|                                                     last period cycle.     |
|                     uint8_t_ b_StopLevel       : Stop PWM level selection     |
|                                                0 : The output signal keep  |
|                                                    the level after the     |
|                                                    "i_APCI1710_DisablePWM" |
|                                                    function                |
|                                                1 : The output signal is set|
|                                                    to low after the        |
|                                                    "i_APCI1710_DisablePWM" |
|                                                    function                |
|                                                2 : The output signal is set|
|                                                    to high after the       |
|                                                    "i_APCI1710_DisablePWM" |
|                                                    function                |
|                     uint8_t_ b_ExternGate      : Extern gate action selection |
|                                                0 : Extern gate signal not  |
|                                                    used.                   |
|                                                1 : Extern gate signal used.|
|                     uint8_t_ b_InterruptEnable : Enable or disable the PWM    |
|                                               interrupt.                   |
|                                               - APCI1710_ENABLE :          |
|                                                 Enable the PWM interrupt   |
|                                                 A interrupt occur after    |
|                                                 each period                |
|                                               - APCI1710_DISABLE :         |
|                                                 Disable the PWM interrupt  |
+----------------------------------------------------------------------------+
| Output Parameters : -                                                      |
+----------------------------------------------------------------------------+
| Return Value      : 0:  No error                                           |
|                    1:  Module selection wrong                             |
|                    2:  The module is not a PWM module                     |
|                    3:  PWM selection is wrong                             |
|                    4:  PWM not initialised see function                   |
|                         "i_APCI1710_InitPWM"                               |
|                    5:  PWM start level selection is wrong                 |
|                    6:  PWM stop mode selection is wrong                   |
|                    7:  PWM stop level selection is wrong                  |
|                    8:  Extern gate signal selection is wrong              |
|                    9: Interrupt parameter is wrong                       |
|                    10: Interrupt function not initialised.                |
|                         See function "i_APCI1710_SetBoardIntRoutineX"      |
+----------------------------------------------------------------------------+
*/
int do_CMD_APCI1710_EnablePWM(struct pci_dev *pdev, unsigned int cmd, unsigned long arg)
{
	uint32_t argArray[7]= {0};
	int i_ErrorCode = 0;

	if (copy_from_user(argArray, (uint32_t __user *)arg, sizeof(argArray)))
		return -EFAULT;

	i_ErrorCode = i_APCI1710_EnablePWM(pdev,
	                          (uint8_t)argArray[0],   // ModulNbr
	                          (uint8_t)argArray[1],   // b_PWM
	                          (uint8_t)argArray[2],   // b_startlvl
                                  (uint8_t)argArray[3],   // b_stopmode
                                 (uint8_t)argArray[4],   // b_stoplvl
	                          (uint8_t)argArray[5],  // b_ExternGate
                                 (uint8_t)argArray[6]); // b_InterruptEnable

	if (i_ErrorCode != 0)
		return (i_ErrorCode);

	return 0;

}

/*
+----------------------------------------------------------------------------+
| Function Name     : int i_APCI1710_DisablePWM (uint8_t_  b_BoardHandle,     |
|                                                  uint8_t_  b_ModulNbr,        |
|                                                  uint8_t_  b_PWM)             |
+----------------------------------------------------------------------------+
| Task              : Disable the selected PWM (b_PWM) from selected module  |
|                     (b_ModulNbr). The output signal level depend of the    |
|                     initialisation by the "i_APCI1710_EnablePWM".          |
|                     See the b_StartLevel, b_StopMode and b_StopLevel       |
|                     parameters from this function.                         |
+----------------------------------------------------------------------------+
| Input Parameters  :uint8_t_ b_BoardHandle : Handle of board APCI-1710         |
|                    uint8_t_ b_ModulNbr    : Selected module number (0 to 3)   |
|                    uint8_t_ b_PWM         : Selected PWM (0 or 1)             |
+----------------------------------------------------------------------------+
| Output Parameters : -                                                      |
+----------------------------------------------------------------------------+
| Return Value      :  0: No error                                           |
|                     1: Module selection wrong                             |
|                     2: The module is not a PWM module                     |
|                     3: PWM selection is wrong                             |
|                     4: PWM not initialised see function                   |
|                         "i_APCI1710_InitPWM"                               |
|                     5: PWM not enabled see function                       |
|                         "i_APCI1710_EnablePWM"                             |
+----------------------------------------------------------------------------+
*/
int do_CMD_APCI1710_DisablePWM(struct pci_dev *pdev, unsigned int cmd, unsigned long arg)
{
	uint32_t argArray[2]= {0};
	int i_ErrorCode = 0;

	if (copy_from_user(argArray, (uint32_t __user *)arg, sizeof(argArray)))
		return -EFAULT;

	i_ErrorCode = i_APCI1710_DisablePWM(pdev,
								  (uint8_t) argArray[0],   // ModulNbr
								  (uint8_t) argArray[1]);  // b_PWM

	if (i_ErrorCode != 0)
		return (i_ErrorCode);

	return 0;

}


/*
+----------------------------------------------------------------------------+
| Function Name     : int i_APCI1710_GetPWMInitialisation                  |
|                                       (uint8_t_     b_BoardHandle,            |
|                                        uint8_t_     b_ModulNbr,               |
|                                        uint8_t_     b_PWM,                    |
|                                        Puint8_t_   pb_TimingUnit,             |
|                                        Puint32_t pul_LowTiming,              |
|                                        Puint32_t pul_HighTiming,             |
|                                        Puint8_t_   pb_StartLevel,             |
|                                        Puint8_t_   pb_StopMode,               |
|                                        Puint8_t_   pb_StopLevel,              |
|                                        Puint8_t_   pb_ExternGate,             |
|                                        Puint8_t_   pb_InterruptEnable,        |
|                                        Puint8_t_   pb_Enable)                 |
+----------------------------------------------------------------------------+
| Task              : Return the PWM (b_PWM) initialisation from selected    |
|                     module (b_ModulNbr). You must calling the              |
|                     "i_APCI1710_InitPWM" function be for you call this     |
|                     function.                                              |
+----------------------------------------------------------------------------+
| Input Parameters  : uint8_t_ b_BoardHandle : Handle of board APCI-1710        |
|                     uint8_t_ b_ModulNbr    : Selected module number (0 to 3)  |
|                     uint8_t_ b_PWM         : Selected PWM (0 or 1)            |
+----------------------------------------------------------------------------+
| Output Parameters : Puint8_t_  pb_TimingUnit      : Base timing Unit (0 to 4) |
|                                                       0 : ns               |
|                                                       1 : �s               |
|                                                       2 : ms               |
|                                                       3 : s                |
|                                                       4 : mn               |
|                     Puint32_t pul_LowTiming      : Low base timing value.    |
|                     Puint32_t pul_HighTiming     : High base timing value.   |
|                     Puint8_t_  pb_StartLevel      : Start period level        |
|                                                  selection                 |
|                                                       0 : The period start |
|                                                           with a low level |
|                                                       1 : The period start |
|                                                           with a high level|
|                     Puint8_t_  pb_StopMode        : Stop mode selection       |
|                                                  0 : The PWM is stopped    |
|                                                      directly after the    |
|                                                     "i_APCI1710_DisablePWM"|
|                                                      function and break the|
|                                                      last period           |
|                                                  1 : After the             |
|                                                     "i_APCI1710_DisablePWM"|
|                                                      function the PWM is   |
|                                                      stopped at the end    |
|                                                      from last period cycle|
|                     Puint8_t_  pb_StopLevel        : Stop PWM level selection |
|                                                    0 : The output signal   |
|                                                        keep the level after|
|                                                        the                 |
|                                                     "i_APCI1710_DisablePWM"|
|                                                        function            |
|                                                    1 : The output signal is|
|                                                        set to low after the|
|                                                     "i_APCI1710_DisablePWM"|
|                                                        function            |
|                                                    2 : The output signal is|
|                                                        set to high after   |
|                                                        the                 |
|                                                     "i_APCI1710_DisablePWM"|
|                                                        function            |
|                     Puint8_t_  pb_ExternGate      : Extern gate action        |
|                                                  selection                 |
|                                                   0 : Extern gate signal   |
|                                                       not used.            |
|                                                   1 : Extern gate signal   |
|                                                       used.                |
|                     Puint8_t_  pb_InterruptEnable : Enable or disable the PWM |
|                                                  interrupt.                |
|                                                  - APCI1710_ENABLE :       |
|                                                    Enable the PWM interrupt|
|                                                    A interrupt occur after |
|                                                    each period             |
|                                                  - APCI1710_DISABLE :      |
|                                                    Disable the PWM         |
|                                                    interrupt               |
|                     Puint8_t_  pb_Enable          : Indicate if the PWM is    |
|                                                  enabled or no             |
|                                                       0 : PWM not enabled  |
|                                                       1 : PWM enabled      |
+----------------------------------------------------------------------------+
| Return Value      :  0: No error                                           |
|                     1: Module selection wrong                             |
|                     2: The module is not a PWM module                     |
|                     3: PWM selection is wrong                             |
|                     4: PWM not initialised see function                   |
|                         "i_APCI1710_InitPWM"                               |
+----------------------------------------------------------------------------+
*/

int do_CMD_APCI1710_GetPWMInitialisation(struct pci_dev *pdev, unsigned int cmd, unsigned long arg)
{
	uint32_t argArray[2]= {0};
	uint32_t tmp[8]= {0};
	int i_ErrorCode = 0;

	if (copy_from_user(argArray, (uint32_t __user *)arg, sizeof(argArray)))
		return -EFAULT;

	i_ErrorCode = i_APCI1710_GetPWMInitialisation(pdev,
								  (uint8_t) argArray[0],   // ModulNbr
								  (uint8_t) argArray[1],   // B_PWM
								  (uint8_t*)  &tmp[0],       // Timing_unit
		                          &tmp[1],   	 // * pul_RealLowTiming
		                          &tmp[2],       // * pul_RealHighTiming
								  (uint8_t*) &tmp[3],		//pb_StartLevel
								  (uint8_t*) &tmp[4],		//pb_StopMode
								  (uint8_t*) &tmp[5],		//pb_StopLevel
								  (uint8_t*) &tmp[6],		//pb_ExternGate
								  (uint8_t*) &tmp[7],		//pb_InterruptEnable
								  (uint8_t*) &tmp[8]);		//pb_Enable


	if (i_ErrorCode != 0)
		return (i_ErrorCode);

	if ( copy_to_user( (uint32_t __user *)arg , tmp, sizeof(tmp) ) )
		return -EFAULT;

	return 0;
}

/*
+----------------------------------------------------------------------------+
| Function Name     : int i_APCI1710_GetPWMStatus                          |
|                               (uint8_t_    b_BoardHandle,                     |
|                                uint8_t_    b_ModulNbr,                        |
|                                uint8_t_    b_PWM,                             |
|                                Puint8_t_  pb_PWMOutputStatus,                 |
|                                Puint8_t_  pb_ExternGateStatus)                |
+----------------------------------------------------------------------------+
| Task              : Return the status from selected PWM (b_PWM) from       |
|                     selected module (b_ModulNbr).                          |
+----------------------------------------------------------------------------+
| Input Parameters  : uint8_t_  b_BoardHandle : Handle of board APCI-1710       |
|                     uint8_t_  b_PWM         : Selected PWM (0 or 1)           |
|                     uint8_t_  b_ModulNbr    : Selected module number (0 to 3) |
+----------------------------------------------------------------------------+
| Output Parameters : Puint8_t_  pb_PWMOutputStatus  : Return the PWM output    |
|                                                   level status.            |
|                                                    0 : The PWM output level|
|                                                        is low.             |
|                                                    1 : The PWM output level|
|                                                        is high.            |
|                     Puint8_t_  pb_ExternGateStatus : Return the extern gate   |
|                                                   level status.            |
|                                                    0 : The extern gate is  |
|                                                        low.                |
|                                                    1 : The extern gate is  |
|                                                        high.               |
+----------------------------------------------------------------------------+
| Return Value      :  0: No error                                           |
|                     1: Module selection wrong                             |
|                     2: The module is not a PWM module                     |
|                     3: PWM selection is wrong                             |
|                     4: PWM not initialised see function                   |
|                         "i_APCI1710_InitPWM"                               |
|                     5: PWM not enabled see function "i_APCI1710_EnablePWM"|
+----------------------------------------------------------------------------+
*/
int do_CMD_APCI1710_GetPWMStatus(struct pci_dev *pdev, unsigned int cmd, unsigned long arg)
{
	uint32_t argArray[2]= {0};
	uint32_t tmp[1]= {0};
	int i_ErrorCode = 0;

	if (copy_from_user(argArray, (uint32_t __user *)arg, sizeof(argArray)))
		return -EFAULT;

	i_ErrorCode = i_APCI1710_GetPWMStatus(pdev,
												  (uint8_t) argArray[0],  	// ModulNbr
												  (uint8_t) argArray[1],  	// b_pwm
												  (uint8_t*) &tmp[0],  		// *PWMoutputstatus
												  (uint8_t*) &tmp[1]);  	// *ExternalgateStatus

	if (i_ErrorCode != 0)
		return (i_ErrorCode);

	if ( copy_to_user( (uint32_t __user *)arg , tmp, sizeof(tmp) ) )
		return -EFAULT;

	return 0;

}

/*
+----------------------------------------------------------------------------+
| Function Name     : int   i_APCI1710_ReadPWM1DigitalInput                |
|                                       (uint8_t_     b_BoardHandle,            |
|                                        uint8_t_     b_ModulNbr,               |
|                                        uint8_t_     b_InputChannel,           |
|                                        Puint8_t_   pb_ChannelStatus)          |
+----------------------------------------------------------------------------+
| Task              : Read the status from selected PWM digital input        |
|                     (b_InputChannel)                                       |
+----------------------------------------------------------------------------+
| Input Parameters  : uint8_t_ b_BoardHandle         : Handle of board APCI-1710|
|                     uint8_t_ b_ModulNbr            : Module number to         |
|                                                   configure (0 to 3)       |
|                     uint8_t_ b_InputChannel        : Selection from digital   |
|                                                   input ( 0 to 2)          |
+----------------------------------------------------------------------------+
| Output Parameters : Puint8_t_  pb_ChannelStatus    : Digital input channel    |
|                                                   status                   |
|                                                   0 : Channle is not active|
|                                                   1 : Channle is active    |
+----------------------------------------------------------------------------+
| Return Value      : 0: No error                                            |
|                    1: The module parameter is wrong                       |
|                    2: The module is not a PWM module                      |
|                    3: Firmware revision error                             |
|                    4: The selected PWM digital input is wrong             |
+----------------------------------------------------------------------------+
*/

int do_CMD_APCI1710_ReadPWM1DigitalInput(struct pci_dev *pdev, unsigned int cmd, unsigned long arg)
{
	uint32_t argArray[2]= {0};
	uint32_t tmp = 0;
	int i_ErrorCode = 0;

	if (copy_from_user(argArray, (uint32_t __user *)arg, sizeof(argArray)))
		return -EFAULT;

	i_ErrorCode =  i_APCI1710_ReadPWM1DigitalInput(pdev,
											  (uint8_t) argArray[0],      // ModulNbr
											  (uint8_t) argArray[1],  	// Input_Channel
											  (uint8_t*) &tmp);
	if (i_ErrorCode != 0)
		return (i_ErrorCode);

	if ( copy_to_user( (uint32_t __user *)arg , &tmp, sizeof(tmp) ) )
		return -EFAULT;

	return 0;

}


/*
+--------------------------------------------uint8_t--------------------------------+
| Function Name     : int   i_APCI1710_ReadPWMAllDigitalInput              |
|                                       (uint8_t_     b_BoardHandle,            |
|                                        uint8_t_     b_ModulNbr,               |
|                                        Puint8_t_   pb_InputStatus)            |
+----------------------------------------------------------------------------+
| Task              : Read the status from all PWM digital inputs from       |
|                     selected PWM module (b_ModulNbr)                       |
+----------------------------------------------------------------------------+
| Input Parameters  : uint8_t_ b_BoardHandle         : Handle of board APCI-1710|
|                     uint8_t_ b_ModulNbr            : Module number to         |
|                                                   configure (0 to 3)       |
+----------------------------------------------------------------------------+
| Output Parameters : Puint8_t_  pb_InputStatus      : Digital inputs channel   |
|                                                   status                   |
+----------------------------------------------------------------------------+
| Return Value      : 0: No error                                            |
|                    1: The module parameter is wrong                       |
|                    2: The module is not a PWM module                      |
|                    3: Firmware revision error                             |
+----------------------------------------------------------------------------+
*/
int do_CMD_APCI1710_ReadPWMAllDigitalInput(struct pci_dev *pdev, unsigned int cmd, unsigned long arg)
{
	uint32_t argArray= 0;
	int i_ErrorCode = 0;
	uint32_t tmp= 0;

	if (copy_from_user(&argArray, (uint32_t __user *)arg, sizeof(argArray)))
		return -EFAULT;

	i_ErrorCode = i_APCI1710_ReadPWMAllDigitalInput(pdev,
												  (uint8_t) argArray,     // ModulNbr
		        		                          (uint8_t*) &tmp);   // * InputStatus

	if (i_ErrorCode != 0)
		return (i_ErrorCode);

	if ( copy_to_user( (uint32_t __user *)arg , &tmp, sizeof(tmp) ) )
		return -EFAULT;

	return 0;

}

/*
+----------------------------------------------------------------------------+
| Function Name     : int                                                  |
|                      i_APCI1710_EnableDisablePWMDigitalOutputManualSetting |
|                                      (uint8_t_     b_BoardHandle,             |
|                                       uint8_t_     b_ModulNbr,                |
|                                       uint8_t_     b_Flag)                    |
+----------------------------------------------------------------------------+
| Task              : Enable or disable the manually settings from output H  |
+----------------------------------------------------------------------------+
| Input Parameters  : uint8_t_ b_BoardHandle : Handle of board APCI-1710        |
|                     uint8_t_ b_ModulNbr    : Module number to configure       |
|                     uint8_t_ b_Flag        : APCI1710_DISABLE : Disable the   |
|                                              manually settings.            |
|					       This is the default state.    |
|					       Output H is parallel connected|
|					       to the output A (PWM0)        |
|				            APCI1710_ENABLE  : Enable the    |
|					       manually seting from output H |
|					       vi the functions              |
|					  - i_APCI1710_SetPWMDigitalOutputOn |
|					  - i_APCI1710_SetPWMDigitalOutputOff|
+----------------------------------------------------------------------------+
| Output Parameters : -                                                      |
+----------------------------------------------------------------------------+
| Return Value      : 0: No error                                            |
|                    1: The module is not a PWM module                      |
|                    2: Firmware revision error                             |
|                    3: Flag parameter is wrong                             |
+----------------------------------------------------------------------------+
*/
int do_CMD_APCI1710_EnableDisablePWMDigitalOutputManualSetting(struct pci_dev *pdev, unsigned int cmd, unsigned long arg)
{
	uint32_t argArray[2]= {0};
	int i_ErrorCode = 0;


	if (copy_from_user(argArray, (uint32_t __user *)arg, sizeof(argArray)))
		return -EFAULT;

	i_ErrorCode = i_APCI1710_EnableDisablePWMDigitalOutputManualSetting(pdev,
										(uint8_t) argArray[0],   // ModulNbr
										(uint8_t) argArray[1]); // b_flag
	if (i_ErrorCode != 0)
		return (i_ErrorCode);

	return 0;

}


/*
+----------------------------------------------------------------------------+
| Function Name     : int   i_APCI1710_SetPWMDigitalOutputOn               |
|                                       (uint8_t_     b_BoardHandle,            |
|                                        uint8_t_     b_ModulNbr)               |
+----------------------------------------------------------------------------+
| Task              : Set the digital output from selected PWM moule         |
|                     (b_ModuleNbr) ON                                       |
+----------------------------------------------------------------------------+
| Input Parameters  : uint8_t_ b_BoardHandle         : Handle of board APCI-1710|
|                     uint8_t_ b_ModulNbr            : Module number to         |
|                                                   configure (0 to 3)       |
+----------------------------------------------------------------------------+
| Output Parameters : -                                                      |
+----------------------------------------------------------------------------+
| Return Value      : 0: No error                                            |
|                    1: The module is not a PWM module                      |
|                    2: Firmware revision error                             |
|                    3: Manually settings option not active                 |
+----------------------------------------------------------------------------+
*/


int do_CMD_APCI1710_SetPWMDigitalOutputOn(struct pci_dev *pdev, unsigned int cmd, unsigned long arg)
{
	uint32_t argArray = 0;
	int i_ErrorCode = 0;


	if (copy_from_user(&argArray, (uint32_t __user *)arg, sizeof(argArray)))
		return -EFAULT;

	i_ErrorCode = i_APCI1710_SetPWMDigitalOutputOn(pdev,
												   (uint8_t) argArray);    // Module_Nbr

	if (i_ErrorCode != 0)
		return (i_ErrorCode);

	return 0;

}


/*
+----------------------------------------------------------------------------+
| Function Name     : int   i_APCI1710_SetPWMDigitalOutputOff              |
|                                       (uint8_t_     b_BoardHandle,            |
|                                        uint8_t_     b_ModulNbr)               |
+----------------------------------------------------------------------------+
| Task              : Set the digital output from selected PWM moule         |
|                     (b_ModuleNbr) OFF                                      |
+----------------------------------------------------------------------------+
| Input Parameters  : uint8_t_ b_BoardHandle         : Handle of board APCI-1710|
|                     uint8_t_ b_ModulNbr            : Module number to         |
|                                                   configure (0 to 3)       |
+----------------------------------------------------------------------------+
| Output Parameters : -                                                      |
+----------------------------------------------------------------------------+
| Return Value      : 0: No error                                            |
|                    1: The module is not a PWM module                      |
|                    2: Firmware revision error                             |
|                    3: Manually settings option not active                 |
+----------------------------------------------------------------------------+
*/

int do_CMD_APCI1710_SetPWMDigitalOutputOff(struct pci_dev *pdev, unsigned int cmd, unsigned long arg)
{
	uint32_t argArray= 0;
	int i_ErrorCode = 0;

	if (copy_from_user(&argArray, (uint32_t __user *)arg, sizeof(argArray)))
		return -EFAULT;

	i_ErrorCode = i_APCI1710_SetPWMDigitalOutputOff(pdev,
													(uint8_t) argArray);  // ModulNbr


	if (i_ErrorCode != 0)
		return (i_ErrorCode);

	return 0;

}
