/** @file ioctl.c
*
* @author Sylvain Nahas
*
* This module implements the watchdog related functions.
*/

/** @par LICENCE
* @verbatim
 Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code and the documentation.
        
        ADDI-DATA GmbH
        Dieselstrasse 3 
        D-77833 Ottersweier
        Tel: +19(0)7223/9493-0
        Fax: +49(0)7223/9493-92
        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 shoud find the complete GPL in the COPYING file accompanying 
    this source code. 
* @endverbatim
*/

/* IOMAPING:
 * access are 16 bits wide on BAR 2. addressing is 8 byte arithmetic
 * APCI2016_WATCHDOG_RELOAD_VALUE_REG (BAR2, offset 4) Write: the reload value (coded on 8 bits)
 * APCI2016_WATCHDOG_CONTROL_REG (BAR2, offset 12) D0 : Write/read: watchdog start/started
 * APCI2016_WATCHDOG_CONTROL_REG (BAR2, offset 12) D9 : Write : software trigger
 * APCI2016_WATCHDOG_STATUS_REG (BAR2, offset 16) D0 : Read : status watchdog (1 = timeout occured)
 * APCI2016_WATCHDOG_STATUS_REG (BAR2, offset 16) D1 : Read : software trigger status (1 = software trigger succeded)
 * */

#include "apci2016-private.h"

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27)
#define __user 
#endif
//------------------------------------------------------------------------------
int do_CMD_APCI2016_InitWatchdog(struct pci_dev * pdev, uint32_t arg)
{

	uint16_t reloadvalue = 0;
	

	/* the argument given by the user is the runout time expressed in ms */
	/* the reload value is this parameter divided by the time quantum of the 
	 * board which is 20 ms. So Reload value = arg / 20*/
	
	reloadvalue = arg / 20;
	
	/* reload value must be between 1 (20 ms) and  255 ( 5100 ms) */	

	switch(arg)
	{
		case 1 ... 5100:
			break;
		default:
			return -EINVAL;	 
	}
	
	{
		unsigned long irqstate;
		APCI2016_LOCK(pdev,&irqstate);
		{
			
			APCI2016_PRIVDATA(pdev)->WatchdogIsConfigured = 1;
			
			/* Disable the watchdog (not implemented ) */
			outw(0x0,GET_BAR2(pdev) + APCI2016_WATCHDOG_CONTROL_REG);
		      
			/* Write reload value */
		    /* low bytes */
		    outw(LOSHORT(reloadvalue),GET_BAR2(pdev) + APCI2016_WATCHDOG_RELOAD_VALUE_REG); 
	
		}APCI2016_UNLOCK(pdev,irqstate);
	}
	
	return 0;
}
//------------------------------------------------------------------------------
int do_CMD_APCI2016_StartWatchdog(struct pci_dev * pdev)
{
	unsigned long irqstate;
	APCI2016_LOCK(pdev,&irqstate);
	{
		if (!APCI2016_PRIVDATA(pdev)->WatchdogIsConfigured)		
		{
			APCI2016_UNLOCK(pdev,irqstate);	
			return -ENODEV;
		}

		outw(0x0001,GET_BAR2(pdev) + APCI2016_WATCHDOG_CONTROL_REG);

	}
	APCI2016_UNLOCK(pdev,irqstate);	
	return 0;
}
//------------------------------------------------------------------------------
int do_CMD_APCI2016_TriggerWatchdog(struct pci_dev * pdev)
{
	unsigned long irqstate;
	APCI2016_LOCK(pdev,&irqstate);
	{
		if (!APCI2016_PRIVDATA(pdev)->WatchdogIsConfigured)		
		{
			APCI2016_UNLOCK(pdev,irqstate);	
			return -ENODEV;
		}
		/* start watchdog + software trigger */
		outw(0x0201,GET_BAR2(pdev) + APCI2016_WATCHDOG_CONTROL_REG);       	
	}
	APCI2016_UNLOCK(pdev,irqstate);		
	return 0;	
}

//------------------------------------------------------------------------------
int do_CMD_APCI2016_ReadWatchdogStatus(struct pci_dev * pdev,unsigned int __user * arg)
{
	unsigned int val = 0;
	
	volatile uint16_t stat =   inw( GET_BAR2(pdev) + APCI2016_WATCHDOG_STATUS_REG) & 0x3; 
		
	val = stat;
		
	if ( copy_to_user(arg, (unsigned int*) &val, sizeof(unsigned int) ) )
		return -EFAULT;
	
	return 0;
	
}
//------------------------------------------------------------------------------
