/** @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 <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 <apcie2200-kapi.h>
#include "apcie2200-private.h"
#include "tcw.h"

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

EXPORT_NO_SYMBOLS;


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

int do_CMD_APCIE2200_TimerWatchdogInitAndStart (struct pci_dev *pdev, unsigned int cmd, unsigned long arg)
{	
	struct
	{
		uint32_t ressourceType;
		uint32_t mode;
		uint32_t timeBaseUnit;
		uint32_t timeBaseValue;
		uint32_t irq;
	} params;
	
	if (copy_from_user (&params, (void __user *) arg, sizeof (params)))
		return -EFAULT;
	
	/* the code below doesn't need locking since no private data is accessed by APCIE2200_TimerInitAndStart */
	return APCIE2200_TimerWatchdogInitAndStart (pdev, params.ressourceType, params.mode, params.timeBaseUnit, params.timeBaseValue, params.irq);
}

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

int do_CMD_APCIE2200_TimerWatchdogStopAndRelease (struct pci_dev *pdev, unsigned int cmd, unsigned long arg)
{
	return APCIE2200_TimerWatchdogStopAndRelease (pdev, arg);
}

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

int do_CMD_APCIE2200_TimerWatchdogTrigger (struct pci_dev *pdev, unsigned int cmd, unsigned long arg)
{
	return APCIE2200_TimerWatchdogTrigger (pdev, arg);
}

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

int do_CMD_APCIE2200_TimerWatchdogRead (struct pci_dev *pdev, unsigned int cmd, unsigned long arg)
{
	struct
	{
		uint32_t ressourceType;
		uint32_t value;
	} params;

	if (copy_from_user (&params, (void __user *) arg, sizeof (params)))
		return -EFAULT;

	/* the code below doesn't need locking since no private data is accessed by APCIE2200_TimerGetStatus */
	{
		int ret = APCIE2200_TimerWatchdogRead (pdev, params.ressourceType, &(params.value));
		if (ret != 0)
			return ret;
	}

	if (copy_to_user ((void __user *) arg, &params, sizeof (params)))
		return -EFAULT;

	return 0;
}

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

int do_CMD_APCIE2200_TimerWatchdogGetStatus (struct pci_dev *pdev, unsigned int cmd, unsigned long arg)
{
	struct
	{
		uint32_t ressourceType;
		uint8_t overflow;
		uint8_t softTrigger;
	} params;

	if (copy_from_user (&params, (void __user *) arg, sizeof (params)))
		return -EFAULT;

	/* the code below doesn't need locking since no private data is accessed by APCIE2200_TimerGetStatus */
	{
		uint32_t status = 0;
		int ret = APCIE2200_TimerWatchdogGetStatus (pdev, params.ressourceType, &status);
		if (ret != 0)
			return ret;

		params.overflow = (status | 1);
		params.softTrigger = (status | 2);
	}

	if (copy_to_user ((void __user *) arg, &params, sizeof (params)))
		return -EFAULT;

	return 0;
}

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

