#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
	#include <linux/config.h>
#else
	#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
		#include <linux/autoconf.h>
	#else
		#include <generated/autoconf.h>
	#endif
#endif

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/pci.h>
#include <asm/io.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)
#include <asm/system.h>
#endif
#include <asm/uaccess.h>
#include <asm/bitops.h>
#include <linux/sched.h>
#include <linux/errno.h>

#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/delay.h>

#include <apci3600.h>

#include "apci3600-private.h"
#include "vtable.h"



#ifdef IOCTL_DEBUG
#define IOCTL_DPRINTK(fmt, args...)	printk("%s: " fmt, __FUNCTION__ , ## args)
#define IOCTL_MARK()	printk("%s:%i\n", __FUNCTION__, __LINE__)
#define IOCTL_RETURN(__ret,__fcn, args...) { __ret = __fcn ( args ) ; printk( #__fcn "() returned %d\n", __ret); }
#else
#define IOCTL_DPRINTK(fmt, args...)
#define IOCTL_MARK()
#define IOCTL_RETURN(__ret,__fcn, args...) __ret = __fcn ( args ) ;
#endif	


//------------------------------------------------------------------------------
int do_CMD_APCI3600_InitAnalogInputModule(struct pci_dev *pdev, unsigned int cmd, unsigned long arg, unsigned long module)
{
	str_InitAnalogInputModuleArg_t p;
	int ret;

	IOCTL_MARK();

	if (copy_from_user  (&p, (const void __user *)arg, sizeof(str_InitAnalogInputModuleArg_t)))
		return -EFAULT;
	
   	IOCTL_DPRINTK ("module=%ld\n",module);
	IOCTL_DPRINTK ("InitAnalogInputModuleArg.pb_SingleDiffMode[0]=%d\n",p.pb_SingleDiffMode[0]);
	IOCTL_DPRINTK ("InitAnalogInputModuleArg.pb_SingleDiffMode[1]=%d\n",p.pb_SingleDiffMode[1]);
	IOCTL_DPRINTK ("InitAnalogInputModuleArg.pb_Coupling[0]=%d\n",p.pb_Coupling[0]);
	IOCTL_DPRINTK ("InitAnalogInputModuleArg.pb_Coupling[1]=%d\n",p.pb_Coupling[1]);
	IOCTL_DPRINTK ("InitAnalogInputModuleArg.pb_EnableCurrentSource[0]=%d\n",p.pb_EnableCurrentSource[0]);
	IOCTL_DPRINTK ("InitAnalogInputModuleArg.pb_EnableCurrentSource[1]=%d\n",p.pb_EnableCurrentSource[1]);
	IOCTL_DPRINTK ("InitAnalogInputModuleArg.pb_GainSelection[0]=%d\n",p.pb_GainSelection[0]);
	IOCTL_DPRINTK ("InitAnalogInputModuleArg.pb_GainSelection[1]=%d\n",p.pb_GainSelection[1]);
	IOCTL_DPRINTK ("InitAnalogInputModuleArg.b_SamplingClockSelection=%d\n",p.b_SamplingClockSelection);
	IOCTL_DPRINTK ("InitAnalogInputModuleArg.b_SpeedMode=%d\n",p.b_SpeedMode);
    
	{
		unsigned long irqstate;
		APCI3600_LOCK(pdev,&irqstate);
		IOCTL_RETURN( ret, 
					i_PCI3600_InitAnalogInModule,
					pdev,	
					module,
					p.pb_SingleDiffMode,
					p.pb_Coupling,
					p.pb_EnableCurrentSource,
					p.pb_GainSelection,
					p.b_SamplingClockSelection,
					p.b_SpeedMode);
		APCI3600_UNLOCK(pdev,irqstate);
	}
	return KAPI2IOCTL(ret);
}

//------------------------------------------------------------------------------
int do_CMD_APCI3600_InitAnalogInputModuleCyclicAcquisition(struct pci_dev *pdev, unsigned int cmd, unsigned long arg, unsigned long module)
{
	str_InitAnalogInputModuleCyclicAcquisitionArg_t p;
	int ret;
	
	IOCTL_MARK();	
	
	if ( copy_from_user  (&p, (const void __user *)arg, sizeof(str_InitAnalogInputModuleCyclicAcquisitionArg_t)) )
		return -EFAULT;

	IOCTL_DPRINTK ("Module=%ld\n",module);
	IOCTL_DPRINTK ("str_InitAnalogInputModuleCyclicAcquisitionArg.b_Mode=%d\n",p.dw_Mode);
	IOCTL_DPRINTK ("str_InitAnalogInputModuleCyclicAcquisitionArg.dw_OnBoardBufferSize=%d\n",p.dw_OnBoardBufferSize);
	IOCTL_DPRINTK ("str_InitAnalogInputModuleCyclicAcquisitionArg.dw_CompareValue=%d\n",p.dw_CompareValue);
	
	{
		unsigned long irqstate;
		APCI3600_LOCK(pdev,&irqstate);
		IOCTL_RETURN(	ret,
					i_PCI3600_InitAnalogInModuleCyclicAcquisition,
					pdev, 
					module, 
					(uint8_t )p.dw_Mode, 
					p.dw_OnBoardBufferSize, 
					p.dw_CompareValue);
		APCI3600_UNLOCK(pdev,irqstate);
	}
	return KAPI2IOCTL(ret);
}
//------------------------------------------------------------------------------
int do_CMD_APCI3600_StartAnalogInputModuleCyclicAcquisition(struct pci_dev *pdev, unsigned int cmd, unsigned long arg, unsigned long module)
{
	int ret;
	
	IOCTL_MARK();	
	
	IOCTL_DPRINTK ("Module=%ld\n",module);
	
	{
		unsigned long irqstate;
		APCI3600_LOCK(pdev,&irqstate);
		IOCTL_RETURN(	ret, 
					i_PCI3600_StartAnalogInModuleCyclicAcquisition, 
					pdev, 
					module);
		APCI3600_UNLOCK(pdev,irqstate);
	}
	return KAPI2IOCTL(ret);
}
//------------------------------------------------------------------------------
/* REMARK: There is no module parameter because it is called as a base function */
int do_CMD_APCI3600_StartMoreAnalogInputModuleCyclicAcquisition(struct pci_dev *pdev, unsigned int cmd, unsigned long arg)
{
	int ret;

	IOCTL_MARK();

	IOCTL_DPRINTK ("Mask=%ld\n",mask);

	{
		unsigned long irqstate;
		APCI3600_LOCK(pdev,&irqstate);
		IOCTL_RETURN(ret, i_PCI3600_StartMoreAnalogInModuleCyclicAcquisition, pdev, (uint8_t)arg);
		APCI3600_UNLOCK(pdev,irqstate);
	}
	return KAPI2IOCTL(ret);
}
//------------------------------------------------------------------------------
int do_CMD_APCI3600_GetAnalogInputModuleCyclicAcquisitionStatus(struct pci_dev *pdev, unsigned int cmd, unsigned long arg, unsigned long module)
{
	/*0 = uint8_t b_Module;
	  1 = uint8_t b_Status;
	  2 = uint32_t dw_NbrOfValue;*/

	GetAnalogInputModuleCyclicAcquisitionStatus_t param;
	int ret;

	IOCTL_MARK();

	if ( copy_from_user( &param, (void __user *)arg, sizeof(GetAnalogInputModuleCyclicAcquisitionStatus_t) ) )
		return -EFAULT;
		
	{
		unsigned long irqstate;
		APCI3600_LOCK(pdev,&irqstate);
		IOCTL_RETURN(	ret, 
					i_PCI3600_GetAnalogInModuleCyclicAcquisitionStatus,
					pdev, module, &(param.b_Status), &(param.dw_NbrOfValue));
		APCI3600_UNLOCK(pdev,irqstate);
	}
	
	if (copy_to_user ((GetAnalogInputModuleCyclicAcquisitionStatus_t __user *) arg,  (const void * )&param, sizeof (GetAnalogInputModuleCyclicAcquisitionStatus_t)))
	{
		return -EFAULT;
	}

	return KAPI2IOCTL(ret);

}

// 		uint8_t b_Module,
// 		uint8_t* pb_Status,
// 		uint32_t* pdw_NbrOfValue)
// 


/*End 02/05/06 FB*/


/** Release the analog input module number arg
* do_CMD_APCI3600_ReleaseAnalogInModuleCyclicAcquisition .
* @param *pdev a struct pci_dev
* @param unsigned int cmd
* @param unsigned long arg
* 
*
*/
//------------------------------------------------------------------------------
int do_CMD_APCI3600_ReleaseAnalogInputModuleCyclicAcquisition(struct pci_dev *pdev, unsigned int cmd, unsigned long arg, unsigned long module)
{
	int ret;
	
	IOCTL_MARK();
	IOCTL_DPRINTK ("Module=%ld\n",module);
		
	{
		unsigned long irqstate;
		APCI3600_LOCK(pdev,&irqstate);
		
		IOCTL_RETURN( 	ret, 
					i_PCI3600_ReleaseAnalogInModuleCyclicAcquisition, pdev, module) ;
		APCI3600_UNLOCK(pdev,irqstate);
	}
	return KAPI2IOCTL(ret);
}


//------------------------------------------------------------------------------
int do_CMD_APCI3600_ReleaseAnalogInputModule(struct pci_dev *pdev, unsigned int cmd, unsigned long arg, unsigned long module)
{
	int ret;
	
	IOCTL_MARK();
	IOCTL_DPRINTK ("Module=%ld\n",module);	
	
	{
		unsigned long irqstate;
		APCI3600_LOCK(pdev,&irqstate);	
	
		IOCTL_RETURN( 	ret,
						i_PCI3600_ReleaseAnalogInModule, 
						pdev, module);
		
		APCI3600_UNLOCK(pdev,irqstate);
	}
	return KAPI2IOCTL(ret);
}

//------------------------------------------------------------------------------
int do_CMD_APCI3600_GetAnalogInputModuleCalibrationStatus(struct pci_dev *pdev, unsigned int cmd, unsigned long arg, unsigned long module)
{
	uint8_t b_Status = 0;
	int ret;
	
	IOCTL_MARK();
	IOCTL_DPRINTK ("Module=%ld\n",module);	
	
	IOCTL_RETURN(	ret, 
					i_PCI3600_GetAnalogInModuleCalibrationStatus,
					pdev, module, &b_Status);
	
	if (copy_to_user ((uint8_t __user *)arg, &b_Status, sizeof (uint8_t)))
		return -EFAULT;

	return KAPI2IOCTL(ret);
}
//------------------------------------------------------------------------------
int do_CMD_APCI3600_AnalogInput_EnableDisableMasterTrigger(struct pci_dev *pdev, unsigned int cmd, unsigned long arg, unsigned long module)
{	
	int ret;

	IOCTL_MARK();
	IOCTL_DPRINTK ("Module=%ld\n",module);
	IOCTL_DPRINTK ("flag=%lu\n",arg);

	{
		unsigned long irqstate;
		APCI3600_LOCK(pdev,&irqstate);
		IOCTL_RETURN( ret, i_PCI3600_AnalogIn_EnableDisableMasterTrigger, pdev, module, arg );
		APCI3600_UNLOCK(pdev,irqstate);
	}
	return KAPI2IOCTL(ret);	
}
//------------------------------------------------------------------------------
int do_CMD_APCI3600_StopAnalogInputModuleCyclicAcquisition (struct pci_dev *pdev, unsigned int cmd, unsigned long arg, unsigned long module)
{
	int ret;
	
	IOCTL_MARK();
	IOCTL_DPRINTK ("Module=%ld\n",module);	
		
	{
		unsigned long irqstate;
		APCI3600_LOCK(pdev,&irqstate);	
		IOCTL_RETURN( ret, 
					i_PCI3600_StopAnalogInModuleCyclicAcquisition, pdev, module);
		APCI3600_UNLOCK(pdev,irqstate);
	}
	return KAPI2IOCTL(ret);
}
//------------------------------------------------------------------------------
int do_CMD_APCI3600_AnalogInput_EnableDisableDigitalInputExternalTrigger(struct pci_dev *pdev, unsigned int cmd, unsigned long arg, unsigned long module)
{
	int ret;
	
	IOCTL_MARK();
	
	IOCTL_DPRINTK ("Module=%ld\n",module);
	IOCTL_DPRINTK ("flag=%lu\n",arg);
	
	{
		unsigned long irqstate;
		APCI3600_LOCK(pdev,&irqstate);	
		IOCTL_RETURN(	ret, 
					i_PCI3600_AnalogIn_EnableDisableDigitalInputExternalTrigger,
					pdev, module, arg );
		APCI3600_UNLOCK(pdev,irqstate);
	}
	return KAPI2IOCTL(ret);
}
