#ifndef __APCI3600_PRIVATE__
#define __APCI3600_PRIVATE__

/** @file apci3600-private.h
*
* @author Sylvain Nahas
*
* This header contains private definitions (not to be seen by external code)
*/

/** @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
*/

#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
	#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
		#include <linux/smp_lock.h>
	#endif
#endif

#include <linux/spinlock.h>
#include <linux/ioctl.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/pci.h>		// struct pci_dev
#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/interrupt.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
	
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mman.h>


/*#include <rtai.h>
#include <rtai_fifos.h>
*/
#include <apci.h>
#include <apci3600.h>


#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
#include <linux/wrapper.h>
#endif

#if LINUX_VERSION_CODE > KERNEL_VERSION(4,9,2)
#include <linux/uaccess.h>
#endif

/** ressources of a board */
static inline unsigned long
GET_BAR0 (struct pci_dev *dev)
{
	return dev->resource[0].start;
}
static inline unsigned long
GET_BAR1 (struct pci_dev *dev)
{
	return dev->resource[1].start;
}
static inline unsigned long
GET_BAR2 (struct pci_dev *dev)
{
	return dev->resource[2].start;
}
static inline unsigned long GET_BAR3 (struct pci_dev *dev)
{
	return dev->resource[3].start;
}


/* number of board detected by the kernel */
extern atomic_t apci3600_count;

extern char __APCI3600_DRIVER_NAME[];

/* major number (attributed by the OS) */
extern unsigned int apci3600_majornumber;


// Begin 26/09/05 CG
#include "apci3600-kapi.h"
// End 26/09/05 CG
#include "api.h"
#include "privdata.h"

// OFFSET DEFINE
#include "iomapping.h"

/*******************/
/* Time out define */
/*******************/
#define PCI3600_ANALOG_INPUT_CONVERSION_TIMEOUT 2000	// 2s.
#define PCI3600_ANALOG_OUTPUT_READY_BIT_TIMEOUT 2000	// 2s.
#define PCI3600_DMA_TRANSFER_TIMEOUT 10000	// 10s.
#define PCI3600_DMA_ABORT_TIMEOUT 3000	// 3s.


/*********************************/
/* DMA transfer direction define */
/*********************************/
#define PCI3600_DMA_PC_TO_BOARD 0
#define PCI3600_DMA_BOARD_TO_PC 1

#define PCI3600_DMA_CHANNEL_0 0
#define PCI3600_DMA_CHANNEL_1 1

#define PCI3600_DESCRIPTOR_MEM_SIZE (((sizeof(str_PCI9054DMADescriptor) * PCI3600_MAX_NUMBER_OF_DESCRIPTOR) + 0x10) * (PCI3600_NBR_OF_ANALOG_OUTPUT_CHANNEL + PCI3600_NBR_OF_ANALOG_INPUT_MODULE + PCI3600_NBR_OF_CHRONOMETER))

#include "intern_include.h"
#include "primary_include.h"
#include "util_include.h"

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
	#ifndef __iomem
		#define __iomem
	#endif
#endif

/* BAR0 is memory mapped */
static inline void __iomem * GET_MEM_BAR0 (struct pci_dev *dev)
{ 
	return (APCI3600_PRIVDATA (dev)->s_PCI3600_BoardInformation.s_HardwareInformations.dw_MemBaseAddress0);
}

/* BAR3 is memory mapped */
static inline void __iomem * GET_MEM_BAR3 (struct pci_dev *dev)
{
	return (APCI3600_PRIVDATA (dev)->s_PCI3600_BoardInformation.s_HardwareInformations.dw_MemBaseAddress3);
}
int apci3600_initialize (struct pci_dev *pdev);

int __needlock i_PCI3600_Intern_InterruptFunction (struct pci_dev *pdev);

// #define ANA_OUT_DEBUG
// #define MAIN_DEBUG
// #define IOCTL_DEBUG
// #define BUFF_ALLOC_DEBUG
// #define FS_DEBUG
// #define _3600INT_DEBUG
// #define INTERRUPT_DEBUG

/*Number of pages used for the ring buffer of the kernel*/
//extern int buffer_size;

/* return 1 if the minor number is incorrect */ 
static __inline__ int apci3600_INDEX_NOT_VALID(atomic_t * count , unsigned int minor )
{
	return ( (minor >= (APCI3600_COMPUTE_BASE_MINOR_NUMBER(atomic_read(count)) + APCI3600_DEV_MINOR_MAX) ) ? 1 : 0 );
}	

/* the return convention for the KAPI and the IOCTL are inversed.
 * KAPI functions return a negative number when an error happens, 
 * whereas IOCTL must return positive value for custom erros and a negative value when
 * for system error
 * 
 * The macro KAPI2IOCTL makes this explicit. 
 */  

#define KAPI2IOCTL(__expr)	( (__expr) ? -(__expr) : 0)

#endif //__APCI3600_PRIVATE__
