/** @file fs.c
*
* @author Sylvain Nahas
*
* This module provides FS related function implementation.
*/

/** @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 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 shoud find the complete GPL in the COPYING file accompanying
    this source code.
* @endverbatim
*/

#include <apcie2200-kapi.h>
#include "apcie2200-private.h"



EXPORT_NO_SYMBOLS;
//------------------------------------------------------------------------------
/** open() function of the module for the APCIE-2200, with lookup though global OS PCI list
* this is for files unmanaged by the driver itself and use the minor device number to identify the board.
*
* When opening, the pci_dev associated to the minor number is looked up
* and associated with the file structure. It avoid further lookup when calling ioctl()
*
*
*/
int apcie2200_open_lookup (struct inode *inode, struct file *filp)
{
	if (apcie2200_INDEX_NOT_VALID(&apcie2200_count, MINOR(inode->i_rdev)))
	{
		return -ENODEV;
	}

	filp->private_data = apcie2200_lookup_board_by_index(MINOR(inode->i_rdev));

	MOD_INC_USE_COUNT;
	return 0;
}

//------------------------------------------------------------------------------
/** release() function of the module for the APCIE-2200, with lookup though global OS PCI list
* this is for files unmanaged by the driver itself and use the minor device number to identify the board
*/
int apcie2200_release_lookup (struct inode *inode,struct file *filp)
{
	if ( apcie2200_INDEX_NOT_VALID(&apcie2200_count, MINOR(inode->i_rdev) ) )
	{
		return -ENODEV;
	}

	MOD_DEC_USE_COUNT;
	return 0;
}

//------------------------------------------------------------------------------
/** ioctl() function of the module for the APCIE-2200, with lookup though global OS PCI list
* this is for files unmanaged by the driver itself and use the minor device number to identify the board
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
int apcie2200_ioctl_lookup (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
#else
long apcie2200_ioctl_lookup (struct file *filp, unsigned int cmd, unsigned long arg)
#endif
{
	int ret = 0;

//#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
//	struct inode *inode = filp->f_dentry->d_inode;
//#endif

//	if (apcie2200_INDEX_NOT_VALID(&apcie2200_count, MINOR(inode->i_rdev)))
//	{
//		return -ENODEV;
//	}

	if (!filp->private_data) // private data is initialised to NULL
	{
		printk(KERN_CRIT "%s: %s: board data should be affected but is not (did you call open() before ioctl() ?) \n",__DRIVER_NAME, __FUNCTION__);
		return -EBADFD;
	}

	#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
		lock_kernel();
	#endif

	ret = apcie2200_do_ioctl((struct pci_dev *)filp->private_data, cmd, arg);

	#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
		unlock_kernel();
	#endif

	return ret;
}
