/* @file privadata.h
 * 
 * @brief Holds definition for driver's private data and its manipulation functions. 
 * 
 * 
 * 
 */

/** @par LICENCE
 * 
 *  @verbatim
  Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
  
         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 library is free software; you can redistribute it and/or modify it under 
 the terms of the GNU Lesser General Public License as published by the 
 Free Software Foundation; either version 2.1 of the License, 
 or (at your option) any later version.
 
 This library 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 Lesser General Public License for more details.
 
 You should have received a copy of the GNU Lesser General Public License 
 along with this library; if not, write to the Free Software Foundation, 
 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
 
 You also shoud find the complete LGPL in the LGPL.txt file accompanying 
 this source code.
 
 @endverbatim
**/

#ifndef __APCI3600_PRIVDATA_H_
#define __APCI3600_PRIVDATA_H_

#include <linux/version.h>

#include <apci3600-events.h>
#include "fifo.h"
#include "fs.h"

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

/* size of the event FIFO */
#define APCI3600_SIZE_EVENT_FIFO 40
DECLARE_NEW_FIFO_TYPE(apci3600_event_fifo_t, APCI3600_SIZE_EVENT_FIFO,apci3600_event_t);

#define	PCI3600_MAX_PROCESS		1
#define	PCI3600_INTERRUPT_FIFO_SIZE	10
#define	PCI3600_MAX_INTERRUPT		255
#define	PCI3600_NBR_OF_ANALOG_INPUT_MODULE	4
#define	PCI3600_NBR_OF_ANALOG_OUTPUT_CHANNEL	2
#define PCI3600_NBR_OF_CHRONOMETER	4
#define	PCI3600_MAX_NUMBER_OF_DESCRIPTOR	128	// 1GB / 8MB -> 128 : 1GB is the maximum RAM Size
#define	PCI3600_MIN_RING_BUFFER_SIZE	1

// who can be use on the board
typedef struct
{
	void *pv_DMABufferRing0[2];
	uint32_t ul_PhysicalAddress[2];
	caddr_t BigphysareaHandle;
	uint32_t ul_BufferSize;
	uint32_t ul_BufferNbr;
	uint32_t ul_Status;
}
str_PCIDMAInformation;

/********************/
/* DMA Buffer infos */
/********************/
typedef struct
{
	uint32_t pdw_DMABuffer[2];	// [0] : DMA Buffer Address for Ring 3 // [1] : DMA Buffer Address for Ring 0
	uint32_t dw_PhysicalAddress;
	uint32_t dw_BufferSize;	// Buffer size in bytes
	uint8_t b_Empty;		// Empty Flag of the analog output buffer
	// 0 : Not empty
	// 1 : Empty
	uint8_t b_Full;			// Full flag of the analog output buffer
	// 0 : Not full
	// 1 : Full
	uint32_t dw_ReadPointer;		// Read pointer of the analog output buffer
	uint32_t dw_WritePointer;	// Write pointer of the analog output buffer
}
str_ComputerDMABufferInformations, *pstr_ComputerDMABufferInformations;

/******************/
/* Hardware infos */
/******************/
typedef struct
{
	uint8_t b_SlotNumber;		// PCI slot number
	uint8_t b_InterruptNbr;		// Board interrupt channel
	uint32_t dw_DeviceID;		// The device ID define the number of functionality of the board
	//uint32_t dw_BoardBaseAddress[4]; /* not used */
	void __iomem * dw_MemBaseAddress0; /* BAR 0 is memory mapped */
	uint32_t dw_IOBaseAddress1; /* BAR 1 is IO port */
	uint32_t dw_IOBaseAddress2; /* BAR 2 is IO port */
	void __iomem * dw_MemBaseAddress3; /* BAR 1 is memory mapped */
	uint8_t b_BoardVersion;	// Version of the board
	uint32_t dw_OnBoardRAMSize;	// Size of the on board RAM in Byte
}
str_HardwareInformations;

/**********************************/
/* Digital external trigger infos */
/**********************************/
typedef struct
{
	uint8_t b_InitStatus;		// dig external trigger initialisation status
	// 0 : dig external trigger not initialised
	// 1 : dig external trigger initialised
	uint8_t b_InitProcessIndex;	// Index of the process who has initialised the channel
}
str_DigExtTriggerInfos;

/**********************/
/* Analog input infos */
/**********************/
typedef struct
{
	uint8_t b_ModuleInitStatus;	// analog input module initialisation status
	// 0 : Module not initialised
	// 1 : Module initialised
	uint8_t b_ModuleInitProcessIndex;	// Index of the process who has initialised the module
	uint8_t b_ModuleCyclicAcquisitionInitStatus;	// analog Input Module cyclic acquisition initialisation status
	// 0 : Module not initialised
	// 1 : Module initialised
	uint8_t b_ModuleCyclicAcquisitionInitProcessIndex;	// Index of the process who has initialised the module in cyclic acquisition mode
	uint8_t b_ModuleCyclicAcquisitionStartStatus;	// analog Input Module cyclic acquisition start status
	// 0 : Module not started
	// 1 : Module started
	uint8_t b_ModuleCyclicAcquisitionStartProcessIndex;	// Index of the process who has started the module in cyclic acquisition mode
	uint8_t b_ModuleCyclicAcquisitionRunMode;	// analog Input Module cyclic acquisition run mode
	// 0 : Auto Stop mode
	// 1 : Ring buffer mode
	uint8_t b_ModuleDigExtTriggerEnable;	// define if the digital external trigger is enabled for this module
	// 0 : Digital external trigger not enabled
	// 1 : Digital external trigger enabled
	uint8_t b_ModuleMasterTriggerEnable;	// define if the master trigger is enabled for this module
	// 0 : Master trigger not enabled
	// 1 : Master trigger enabled
}
str_AnalogInModuleInfos;

/***********************/
/* Analog output infos */
/***********************/
typedef struct
{
	uint8_t b_ChannelInitStatus;	// analog output channel initialisation status
	// 0 : Channel not initialised
	// 1 : Channel initialised
	uint8_t b_ChannelInitProcessIndex;	// Index of the process who has initialised the channel
	uint8_t b_ChannelSignalGeneratorInitStatus;	// analog output channel signal generator initialisation status
	// 0 : Channel not initialised
	// 1 : Channel initialised
	uint8_t b_ChannelSignalGeneratorInitProcessIndex;	// Index of the process who has initialised the channel in signal generator mode
	uint8_t b_ChannelSignalGeneratorStartStatus;	// analog output channel signal generator start status
	// 0 : Channel not started
	// 1 : Channel started
	uint8_t b_ChannelSignalGeneratorStartProcessIndex;	// Index of the process who has started the signal generator
	uint8_t b_ChannelSignalGeneratorRunMode;	// analog Output channel signal generator run mode
	// 0 : free run mode
	// 1 : Ring buffer mode
	uint8_t b_ChannelBufferReserved;	// define if the buffer is reserved for the channel for the signal generator mode
	// 0: Buffer not reserved
	// 1: Buffer reserved
	uint8_t b_ChannelBufferProcessIndex;	// Index of the process who has reserved the buffer for the analog output
	uint8_t b_ChannelDigExtTriggerEnable;	// define if the digital external trigger is enabled for this channel
	// 0 : Digital external trigger not enabled
	// 1 : Digital external trigger enabled
	uint8_t b_ChannelMasterTriggerEnable;
	str_ComputerDMABufferInformations s_AnalogOutPCDMABufferInfos;
}
str_AnalogOutInfos;

/*********************/
/* Chronometer infos */
/*********************/
typedef struct
{
	uint8_t b_ChronometerInitStatus;	// Chronometer initialisation status
	// 0 : Chronometer not initialised
	// 1 : Chronometer initialised
	uint8_t b_ChronometerInitProcessIndex;	// Index of the process who has initialised the chronometer
	uint8_t b_ChronometerCyclicAcquisitionInitStatus;	// Chronometer Module cyclic acquisition initialisation status
	// 0 : Module not initialised
	// 1 : Module initialised
	uint8_t b_ChronometerCyclicAcquisitionInitProcessIndex;	// Index of the process who has initialised the module in cyclic acquisition mode
	uint8_t b_ChronometerCyclicAcquisitionStartStatus;	// Chronometer Module cyclic acquisition start status
	// 0 : Module not started
	// 1 : Module started
	uint8_t b_ChronometerCyclicAcquisitionStartProcessIndex;	// Index of the process who has started the module in cyclic acquisition mode
	uint8_t b_ChronometerCyclicAcquisitionRunMode;	// Chronometer cyclic acquisition run mode
	// 0 : Auto Stop mode
	// 1 : Ring buffer mode
	uint8_t b_ChronometerDigExtTriggerEnable;	// define if the digital external trigger is enabled for this module
	// 0 : Digital external trigger not enabled
	// 1 : Digital external trigger enabled
	uint8_t b_ChronometerMasterTriggerEnable;
}
str_ChronometerInfos;

/************************/
/* Digital output infos */
/************************/
typedef struct
{
	uint8_t b_OutputMemoryStatus[PCI3600_MAX_PROCESS];	/* Output memory status for the process */

	/* PCI3600_ENABLE  : Enabled            */
	/* PCI3600_DISABLE : Disabled           */
	uint8_t b_DigitalOutputValue;	/* Digital output value                 */
}
str_DigitalOutputChannelsInfos;

/************************/
/* DMA Controller infos */
/************************/
typedef struct
{
	uint8_t b_RessourceID;		// ID of the ressource
	// 0 : Analog Output 0
	// 1 : Analog Output 1
	// 2 : Analog Input Module 0
	// 3 : Analog Input Module 1
	// 4 : Analog Input Module 2
	// 5 : Analog Input Module 3
	// 6 : Chronometer 0
	// 7 : Chronometer 1
	// 8 : Chronometer 2
	// 9 : Chronometer 3
	uint32_t dw_NbrOfByteTransfered;	// Number of bytes transfered
	uint8_t b_Mode;			// Define the mode of the interrupt
	// 0 : Compare interrupt
	// 1 : Auto-stop interrupt
	uint8_t b_ProcessIndex;		// Index of the process who has start the DMA transfer
}
str_DMATransferInfos;
typedef struct
{
	uint8_t b_InUse;		// Define if the channel is in use or not
	// 0 : channel free
	// 1 : channel in use
	str_DMATransferInfos ps_DMATransferInfo[18];	// Contains the information of the initialised DMA transfer
	uint8_t b_NbrDMATranfer;		// Define the number of DMA transfer initialised
	uint8_t b_DMATranferIndex;	// Define the index of the actual DMA transfer
}
str_DMAControllerInfos, *pstr_DMAControllerInfos;

/********************************************/
/* Scatter gater initialisation list struct */
/********************************************/
typedef struct
{
	uint32_t dw_BufferPhysicalAddress;	// DMA buffer physical address
	uint32_t dw_LocalBusPhysicalAddress;	// Local bus physical address
	uint32_t dw_BufferSize;		// Acquisition size (byte)
	uint32_t dw_NextDescriptorAddress;	// Next descriptor address
}
str_PCI9054DMADescriptor, *pstr_PCI9054DMADescriptor;

/**************************/
/* Descriptor information */
/**************************/
typedef struct
{
	uint32_t dw_NbrOfDescriptorAllocated;
	uint32_t dw_DescriptorListPhysicalAddress;
	void* pv_DescriptorAddressForFree;
	uint32_t dw_NbrOfDescriptorUsed;	// Use to know how many descriptor are initialised
	pstr_PCI9054DMADescriptor ps_PCI9054DMADescriptor;	// Address of the descriptor list
	// 0 : Address in Ring3
	// 1 : Address in Ring0
}
str_DescriptorInfos, *pstr_DescriptorInfos;

typedef struct
{
	void *pv_DescriptorMemoryAddressForFree;
	void *pv_DescriptorMemoryAddress;
	uint32_t dw_DescriptorMemoryPhysicalAddress;
	uint32_t dw_DescriptorMemorySize;
} str_descriptorMemory;

/***********************/
/* Board configuration */
/***********************/
typedef struct
{
	uint8_t b_MasterSlaveMode;	// Define the mode of the board
	// 0 : Master mode
	// 1 : Slave mode
	uint8_t b_ClockGen1_Divisor;	// define the clock divisor for the generator 1 (if master)
	// or for the ext clock 1 (if slave)
	// PCI3600_DIVISOR_4
	// PCI3600_DIVISOR_5
	// PCI3600_DIVISOR_6
	// PCI3600_DIVISOR_8
	// PCI3600_DIVISOR_10
	// PCI3600_DIVISOR_12
	// PCI3600_DIVISOR_16
	// PCI3600_DIVISOR_20
	// PCI3600_DIVISOR_25
	// PCI3600_DIVISOR_40
	// PCI3600_DIVISOR_50
	// PCI3600_DIVISOR_60
	// PCI3600_DIVISOR_80
	// PCI3600_DIVISOR_100
	uint8_t b_ClockGen2_Divisor;	// define the clock divisor for the generator 2 (if master)
	// or for the ext clock 2 (if slave)
	// PCI3600_DIVISOR_4
	// PCI3600_DIVISOR_5
	// PCI3600_DIVISOR_6
	// PCI3600_DIVISOR_8
	// PCI3600_DIVISOR_10
	// PCI3600_DIVISOR_12
	// PCI3600_DIVISOR_16
	// PCI3600_DIVISOR_20
	// PCI3600_DIVISOR_25
	// PCI3600_DIVISOR_40
	// PCI3600_DIVISOR_50
	// PCI3600_DIVISOR_60
	// PCI3600_DIVISOR_80
	// PCI3600_DIVISOR_100
	uint8_t b_SamplingClock1_Selection;	// define the sampling clock selection for Bus clock 1
	// 0 : PCI3600_CLK_GENERATOR_1
	// 1 : PCI3600_CLK_GENERATOR_2
	// 2 : PCI3600_CHRONOMETER_0_LATCH_INPUT
	// 3 : PCI3600_CHRONOMETER_1_LATCH_INPUT
	uint8_t b_SamplingClock2_Selection;	// define the sampling clock selection for Bus clock 2
	// 0 : PCI3600_CLK_GENERATOR_1
	// 1 : PCI3600_CLK_GENERATOR_2
	// 2 : PCI3600_CHRONOMETER_0_LATCH_INPUT
	// 3 : PCI3600_CHRONOMETER_1_LATCH_INPUT
	uint8_t b_SlaveSamplingClock1_Selection;	// define the sampling clock selection for Bus clock 1
	// 0 : PCI3600_EXT_CLOCK_1
	// 1 : PCI3600_EXT_CLOCK_2
	uint8_t b_SlaveSamplingClock2_Selection;	// define the sampling clock selection for Bus clock 2
	// 0 : PCI3600_EXT_CLOCK_1
	// 1 : PCI3600_EXT_CLOCK_2
	uint8_t b_Chronometer_MasterClock_Divisor;	// define the divisor for the master clock for the chronometer
	// 0 : PCI3600_CHRONOMETER_DIVISOR_1
	// 1 : PCI3600_CHRONOMETER_DIVISOR_10
	// 2 : PCI3600_CHRONOMETER_DIVISOR_100
	uint8_t b_BoardInitialised;	// Define if the board is initialised or not
	// 0 : board not initialised
	// 1 : board initialised
	uint8_t b_BoardInitialisedProcessIndex;	// Define the Process Index who has initialised the board.
	str_PCIDMAInformation s_PCAllocatedMemoryBuffer;
	//BEGIN 18/04/06  BF151
	//// Information about the memory allocated by the ADDI_DMA.SYS
	//Information about the memory allocated by the apci3600.o at init time
	//END 18/04/06  BF151
}
str_BoardInfos;

/*****************************/
/* On board RAM buffer infos */
/*****************************/
typedef struct
{
	uint32_t dw_Address;		// Base Address of the buffer
	uint32_t dw_BufferSize;		// Size of the buffer (in Bytes)
	uint8_t b_Init;
}
str_OnBoardRAMBufferInfos, *pstr_OnBoardRAMBufferInfos;

/**********************************/
/* Save interrupt event structure */
/**********************************/
//typedef struct
//{
//	uint32_t dw_BoardHandle;	// Interrupt board handle
//	uint32_t dw_InterruptSource;	// Interrupt source
//	uint32_t dw_InterruptMask;	// Interrupt mask
//	uint32_t dw_NbrOfComputerBuffer;	// Number of buffer
//	uint32_t pdw_ComputerRAMAddressKernelLevel[PCI3600_MAX_NBR_COMPUTER_BUFFER];
//	uint32_t 
//	pdw_ComputerRAMAddressApplicationLevel[PCI3600_MAX_NBR_COMPUTER_BUFFER];
//}
//str_SaveInterruptEventFIFO;
//typedef struct
//{
//	str_SaveInterruptEventFIFO
//	s_SaveInterruptEventFIFO[PCI3600_INTERRUPT_FIFO_SIZE];
//	uint16_t w_Read;			// FIFO read pointer
//	uint16_t w_Write;			// FIFO write pointer
//}
//str_SaveInterruptEvent;

/*************************************************/
/* Fifo for USR Mode - Informations on interrupt */
/*************************************************/
//BEGIN 18/04/2006  BF151
// typedef struct
// {
// 	uint32_t dw_ReadPointer;
// 
// 	//uint32_t dw_WritePointer;
// 	uint32_t dw_InterruptSource;
// 	uint32_t dw_InterruptMask;
// 	uint32_t dw_NbrOfComputerBuffer;
// }
// str_InterruptInfoUserFifo;
//END 18/04/2006  BF151


/* Interrupt Information */
typedef struct
{

	/**********************************/
	/* Save interrupt event structure */
	/**********************************/
	//str_SaveInterruptEvent s_SaveInterruptEvent;

	/*******************************/
	/* Save user interrupt handler */
	/*******************************/
	v_PCI3600_UserInterruptHandler v_UserInterrupt;
	uint8_t b_UserInterruptHandlerInstalled;
}
str_InterruptInformations;

typedef struct
{

	/******************/
	/* Hardware infos */
	/******************/
	str_HardwareInformations s_HardwareInformations;

	/******************************/
	/* Dig external trigger infos */
	/******************************/
	str_DigExtTriggerInfos s_DigExtTriggerInfos;

	/**********************/
	/* Analog Input Infos */
	/**********************/
	uint8_t b_AnalogInModuleNumber;	// Contains the number of analog inputs module of the board : depend to the board version
	str_AnalogInModuleInfos
	s_AnalogInModuleInfos[PCI3600_NBR_OF_ANALOG_INPUT_MODULE];

	/******************/
	/* Board revision */
	/******************/

	uint8_t b_BoardRevision;
	
	/***********************/
	/* Analog Output Infos */
	/***********************/
	uint8_t b_AnalogOutChannelNumber;	// Contains the number of analog outputs channel of the board : depend to the board version
	str_AnalogOutInfos
	s_AnalogOutInfos[PCI3600_NBR_OF_ANALOG_OUTPUT_CHANNEL];

	/*********************/
	/* Chronometer Infos */
	/*********************/
	uint8_t b_ChronometerNumber;	// Contains the number of chronometer of the board : depend to the board version
	str_ChronometerInfos s_ChronometerInfos[PCI3600_NBR_OF_CHRONOMETER];

	/*******************************************************************/
	/* DMA Buffer information for the analog input and the chronometer */
	/*******************************************************************/
	str_ComputerDMABufferInformations s_AnaInpChronomPCDMABufferInfos;	// Information about the buffer to use for
	// the ring buffer mode from the analog input
	// and the chronometer
	// = Global buffer - reserved buffer for the
	// analog output channel

	/*****************************/
	/* On board RAM buffer infos */
	/*****************************/
	str_OnBoardRAMBufferInfos ps_OnBoardRAMReservedBuffer[PCI3600_NBR_OF_ANALOG_OUTPUT_CHANNEL + PCI3600_NBR_OF_ANALOG_INPUT_MODULE + PCI3600_NBR_OF_CHRONOMETER];	// Index = ID of the ressource
	// 0 : Analog Output 0
	// 1 : Analog Output 1
	// 2 : Analog Input Module 0
	// 3 : Analog Input Module 1
	// 4 : Analog Input Module 2
	// 5 : Analog Input Module 3
	// 6 : Chronometer 0
	// 7 : Chronometer 1
	// 8 : Chronometer 2
	// 9 : Chronometer 3
	uint8_t b_NbrOfReservedBuffer;	// Number of buffer reserved in the On Board RAM
	str_OnBoardRAMBufferInfos
	ps_OnBoardRAMFreeBuffer[PCI3600_NBR_OF_ANALOG_OUTPUT_CHANNEL +
							PCI3600_NBR_OF_ANALOG_INPUT_MODULE +
							PCI3600_NBR_OF_CHRONOMETER + 1];
	uint8_t b_NbrOfFreeBuffer;	// Number of buffer free in the On Board RAM

	/************************/
	/* Digital output infos */
	/************************/
	str_DigitalOutputChannelsInfos s_DigitalOutputChannelsInfos;

	/************************/
	/* DMA Controller infos */
	/************************/
	str_DMAControllerInfos s_DMAControllersInfos[2];	// 2 : there are 2 DMA channels on the board

	/********************/
	/* Descriptor infos */
	/********************/
	str_DescriptorInfos ps_DescriptorsInfos[PCI3600_NBR_OF_ANALOG_OUTPUT_CHANNEL + PCI3600_NBR_OF_ANALOG_INPUT_MODULE + PCI3600_NBR_OF_CHRONOMETER];	//Information about the descriptor list to use for the DMA transfer


	str_descriptorMemory descriptorMemory;

	// 0 : Analog Output 0
	// 1 : Analog Output 1
	// 2 : Analog Input Module 0
	// 3 : Analog Input Module 1
	// 4 : Analog Input Module 2
	// 5 : Analog Input Module 3
	// 6 : Chronometer 0
	// 7 : Chronometer 1
	// 8 : Chronometer 2
	// 9 : Chronometer 3

	/******************************/
	/* Configuration of the board */
	/******************************/
	str_BoardInfos s_BoardInfos;
	str_InterruptInformations s_InterruptInformations;
		
}
str_PCI3600_SingleBoardInformation, *pstr_PCI3600_SingleBoardInformation;

// End 14/09/2005 CG

/* internal driver data */
struct apci3600_str_BoardInformations
{
	spinlock_t lock;	 /**< protect the board data */
	atomic_t process_count; /**< number of processes that have currently opened this board */
	struct fasync_struct *fa;
	apci3600_event_fifo_t evtfifo; /* FIFO of events */
	wait_queue_head_t evt_wq; /* wait queue of process sleeping waiting for event */	
	str_PCI3600_SingleBoardInformation s_PCI3600_BoardInformation;
	struct list_head data_list; /* list of data pending for a read */
};

/** initialise board's private data - fill it when adding new members and ioctl handlers */
static __inline__ void apci3600_init_priv_data (struct apci3600_str_BoardInformations *data)
{
	memset (data, 0, sizeof (struct apci3600_str_BoardInformations));	
	spin_lock_init (&(data->lock));
	atomic_set( &(data->process_count) ,0 );
	init_waitqueue_head( &(data->evt_wq) );
	INIT_LIST_HEAD(&(data->data_list));
}

static inline int apci3600_get_process_count(struct pci_dev *pdev)
{
	return atomic_read( &( ((struct apci3600_str_BoardInformations *) pci_get_drvdata(pdev))->process_count ) );
}

/** process count ++ */
static inline void apci3600_inc_process_count(struct pci_dev *pdev)
{
	atomic_inc( &( ((struct apci3600_str_BoardInformations *) pci_get_drvdata(pdev))->process_count ) );
}

/** process count -- */
static inline void apci3600_dec_process_count(struct pci_dev *pdev)
{
	atomic_dec( &( ((struct apci3600_str_BoardInformations *) pci_get_drvdata(pdev))->process_count ) );
}

/** return the private data field of a pci_dev structure.
 * @note The implementation of this function differs in 2.4 and 2.6 kernel
 */
static __inline__ struct apci3600_str_BoardInformations *
			APCI3600_PRIVDATA (struct pci_dev *pdev)
{
	return (struct apci3600_str_BoardInformations *) pci_get_drvdata(pdev);
}

/** lock the board */
static __inline__ void
APCI3600_LOCK (struct pci_dev *pdev, unsigned long * flags)
{
	spin_lock_irqsave(&(APCI3600_PRIVDATA (pdev)->lock), *flags);
}

/** unlock the board */
static __inline__ void APCI3600_UNLOCK (struct pci_dev *pdev, unsigned long flags)
{
	spin_unlock_irqrestore(&(APCI3600_PRIVDATA (pdev)->lock), flags);
}

/* EVENTS */

static inline int __needlock apci3600_evt_add(struct pci_dev * pdev, apci3600_event_t * evt, int count)
{
	return apci3600_event_fifo_t_add( &(APCI3600_PRIVDATA(pdev)->evtfifo), evt, count );
}

static inline int __needlock apci3600_evt_retrieve(struct pci_dev * pdev, apci3600_event_t * evt, int count)
{
	return apci3600_event_fifo_t_retrieve( &(APCI3600_PRIVDATA(pdev)->evtfifo), evt, count );
}

static inline int __needlock apci3600_evt_count(struct pci_dev * pdev)
{
	return apci3600_event_fifo_t_count( &(APCI3600_PRIVDATA(pdev)->evtfifo));
}

//TODO: optimize
static inline void __needlock apci3600_evt_empty(struct pci_dev * pdev)
{
	apci3600_event_t evt;
	while( apci3600_evt_count(pdev) )
	{
		apci3600_evt_retrieve(pdev,&evt,1); 
	}
}
/* wakeup all (interruptible sleeping) processes waiting for event on this board */
static inline int apci3600_evt_wakeup(struct pci_dev * pdev)
{
	wake_up_interruptible( &(APCI3600_PRIVDATA(pdev)->evt_wq) );
	return 0;
}

/* this function is for processes that want to sleep waiting an for event in the FIFO */
static inline int apci3600_evt_wait(struct pci_dev * pdev)
{
	register struct apci3600_str_BoardInformations * drvdata = APCI3600_PRIVDATA(pdev);
	/* sleep until process interrupted or evtfifo.count is superior to zero */
	if ( wait_event_interruptible( drvdata->evt_wq, (drvdata->evtfifo.count > 0) ) ) 
	{
		/* process has been interrupted */
    	return -ERESTARTSYS;
    }
    return 0;
}

/* SIGIO */

/* send a SIGIO signal to registered  user processes */
static inline void apci3600_kill_fasync(struct pci_dev * pdev)
{
	kill_fasync(&(APCI3600_PRIVDATA (pdev))->fa,SIGIO,POLL_IN);
}

/* there is following subsystems: 
Global Board
Analog Output 0
Analog Output 1
Analog Input Module 0
Analog Input Module 1
Analog Input Module 2
Analog Input Module 3
Chronometer 0
Chronometer 1
Chronometer 2
Chronometer 3
Digital Input
Digital Output
External trigger
 */

/* from index number return base minor number */ 
static inline unsigned int APCI3600_COMPUTE_BASE_MINOR_NUMBER(int apci3600_count)
{
	return ( (apci3600_count-1) * (APCI3600_DEV_MINOR_MAX-1) );
}

/* from minor compute subsystem index */ 
static inline unsigned int APCI3600_COMPUTE_SUBSYS_INDEX(int minor)
{
	return minor % (APCI3600_DEV_MINOR_MAX);
}

/* from minor compute board index */ 
static inline unsigned int APCI3600_FROM_MINOR_GET_BOARD_INDEX(int minor)
{
	return minor / APCI3600_DEV_MINOR_MAX;
}

/* acquired data are stored in a buffer - structure below contains information on one buffer */ 

struct apci3600_data_t
{
	struct list_head list;
	uint32_t* pbuffer; /* pointer of buffer data */
	ssize_t number_of_value; /* amount of data in the buffer in 32-bits unit */
};

#endif // __APCI3600_PRIVDATA_H_
