/** @file primary_tcw.h
*
* @author Rodolphe Hilpert
*
* @date 05.01.06
*
* @version  $LastChangedRevision$
* @version $LastChangedDate$
*
* 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 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
*/

#ifndef __XPCI3009_PRIVDATA_H_
#define __XPCI3009_PRIVDATA_H_

//#define DMA_MAX_SCATTER_GATHER_BUFFER          10000
//#define ADDIDATA_MAX_SCATTER_GATHER_SUB_BUFFER 10000
//#define ADDIDATA_MAX_DESCRIPTORS_LIST          10000
#define DMA_MAX_SCATTER_GATHER_BUFFER          100
#define ADDIDATA_MAX_SCATTER_GATHER_SUB_BUFFER 100
#define ADDIDATA_MAX_DESCRIPTORS_LIST          100

//#define ADDIDATA_RING_3 				0
//#define ADDIDATA_RING_0 				1
//
#include <linux/version.h>

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

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

typedef struct
{
	struct
	{
		struct
		{
			caddr_t BigphysareaHandle;
			void * pv_DMABuffer;
			uint32_t  ul_PhysicalAddress;
			uint32_t  ul_BufferSize;
		} s_ScatterGather [DMA_MAX_SCATTER_GATHER_BUFFER];
		uint32_t  ul_ScatterGatherNbr;
	} s_BufferInformations [2];
	uint32_t  ul_BufferSize;
	uint32_t  ul_BufferNbr;
	uint32_t  ul_Status;
}
str_ScatterGatherPCIDMAInformation;

/* struct definition */
typedef struct
{
	uint8_t   b_Interrupt;                   // 0 : Buffer interrupt not generated
	// 1 : Buffer interrupt generated
	uint32_t dw_Size;                        // Single scatter gather buffer size
	uint32_t dw_PhysicalAddress;             // Single scatter gather buffer address
	caddr_t BigphysareaHandle;
	union
	{
		uint8_t  *  pb_DMABuffer;             // buffer address (byte)
		uint16_t  *  pw_DMABuffer;             // buffer address (word)
		uint32_t * pdw_DMABuffer;             // buffer address (dword)
	}s_Buffer;
}str_ScatterGatherSingleBuffer,*pstr_ScatterGatherSingleBuffer;

typedef struct
{
	uint32_t dw_AquisitionTotalSize;		// Acquisition total buffer size
	uint8_t   b_AcquisitionMode;			// Acquisition mode
	//   0 : Single acquisition
	//   1 : Continuous acquisition
	uint8_t   b_LocalBusWidth;				// Local bus width
	// 8  :  8-bit access
	// 16 : 16-bit access
	// 32 : 32-bit access
	uint8_t   b_DMAChannel;				// Selected DMA channel
	uint8_t   b_TransferStatus;			// 0 : Not selected
	// 1 : Disabled
	// 2 : Enabled
	// 3 : Started
	// 4 : Pause
	uint32_t dw_FisrtDescriptorAddress;									// First descriptor physical address
	void* pv_FreeDescriptorArrayAddress[ADDIDATA_MAX_DESCRIPTORS_LIST];	// Free descriptor address
	uint32_t dw_FreeDescriptorArraySize[ADDIDATA_MAX_DESCRIPTORS_LIST];	// Free descriptor size
	uint8_t   b_NumberOfDescriptorsList;									// Number of Descriptors list
	uint32_t dw_NumberOfScatterGatherBuffer;								// Number of scatter gather buffers
	str_ScatterGatherSingleBuffer s_ScatterGatherSingleBuffer [1];
}
str_ScatterGatherInterruptDescriptor,*pstr_ScatterGatherInterruptDescriptor;



// ----------------------------------------------------------
// 				APCI 1710 inside related

/* Interrupt functionality: Timer, counter... */
typedef void (*v_XPCI3009_InterruptFunctionality) (void *, uint8_t, uint8_t *);

/* User kernel callback interrupt */
typedef void (*v_XPCI3009_UserInterruptCallback) (struct pci_dev * pdev);

typedef struct
{
   uint32_t dw_Functionality;									/* The associated functionality */
   v_XPCI3009_InterruptFunctionality v_InterruptFunction;	/* The interrupt function associated to the module (e.g.: Counter, Timer, SSI...) */
}
str_InterruptFunctionality;

typedef struct
{
   v_XPCI3009_UserInterruptCallback v_UserInterruptFunction;
}
str_UserInterruptCallback;

/* Interrupt infos */
typedef struct
{
	uint32_t ul_InterruptOccur;  /*   0 : No interrupt occur  */
                             /* > 0 : Interrupt occur     */
	unsigned int ui_Read;             /* Read FIFO                 */
	unsigned int ui_Write;            /* Write FIFO                */

	struct
    {
		uint8_t   b_OldModuleMask;
		uint32_t ul_OldInterruptMask;         /* Interrupt mask          */
		uint32_t ul_OldCounterLatchValue;     /* Interrupt counter value */
    }
    s_FIFOInterruptParameters [XPCI3009_SAVE_INTERRUPT];

}
str_InterruptParameters;

typedef union
{
	 /* Chronometer infos */

	 struct
	 {
		 uint8_t    b_ChronoInit;
		 uint8_t    b_InterruptMask;
		 uint8_t    b_PCIInputClock;
		 uint8_t    b_TimingUnit;
		 uint8_t    b_CycleMode;
		 uint32_t  dw_ConfigReg;
	 }s_ChronoModuleInfo;

	/* Incremental counter infos */

	struct
	{
    	union
        {
        	struct
            {
		        uint8_t  b_ModeRegister1;
		        uint8_t  b_ModeRegister2;
		        uint8_t  b_ModeRegister3;
		        uint8_t  b_ModeRegister4;
            }s_ByteModeRegister;

			uint32_t dw_ModeRegister1_2_3_4;

		}s_ModeRegister;

		struct
	    {
			unsigned int b_IndexInit	              : 1;
			unsigned int b_CounterInit	              : 1;
			unsigned int b_ReferenceInit              : 1;
			unsigned int b_IndexInterruptOccur        : 1;
			unsigned int b_CompareLogicInit           : 1;
			unsigned int b_FrequencyMeasurementInit   : 1;
			unsigned int b_FrequencyMeasurementEnable : 1;
		}s_InitFlag;

		union
	    {
	    	struct
	        {
	        	unsigned int b_EnableTimer	         : 1;
	            unsigned int b_TriggerTimer	         : 1;
	            unsigned int b_Port0Selection        : 1;
	            unsigned int b_Port1Selection        : 1;
	        }s_BitRegister;

			uint32_t dw_DWordRegister;

		}s_InitCompare;

	}s_SiemensCounterInfo;

	/* TTL I/O infos */
    struct
    {
		uint8_t  b_TTLInit;
		uint8_t  b_PortConfiguration [4];
	}s_TTLIOInfo;

	/* Digital I/O infos */
	struct
	{
		uint8_t    b_DigitalInit;
		uint8_t    b_ChannelAMode;
		uint8_t    b_ChannelBMode;
		uint8_t    b_OutputMemoryEnabled;
        uint32_t  dw_OutputMemory; /* 32-bit, written in memory */
	}s_DigitalIOInfo;

	/* SSI */
	struct
	{
	uint8_t b_SSIProfile;
	uint8_t b_PositionTurnLength;
	uint8_t b_TurnCptLength;
	uint8_t b_SSIInit;
	uint8_t b_SSICountingMode;
	}s_SSICounterInfo;


      /* Pulse encoder infos */

      struct
	 {
	 struct
	    {
	    uint8_t    b_PulseEncoderInit;
	    }s_PulseEncoderInfo [4];
	 uint32_t  dw_SetRegister;
	 uint32_t  dw_ControlRegister;
	 uint32_t  dw_StatusRegister;
	 }s_PulseEncoderModuleInfo;

} str_ModuleInfo;

typedef struct
{
	uint8_t   b_NumberOfModule;
	uint32_t dw_MolduleConfiguration [4]; /* Module configuration (also known as ID)  */

	struct
	{
    	uint8_t b_TimeBase;
		uint8_t b_Filter;
	}s_FilterInfo[4];

}str_BoardInfos;

typedef struct
{
   uint8_t b_InterruptInitialized;
}str_InterruptInfos;
// ----------------------------------------------------------



/* internal driver data */
struct xpci3009_str_BoardInformations
{
	spinlock_t lock; /**< protect the board data */

	/* field used to implement linked list */
	struct pci_dev * previous; /**< previous in known-devices linked list */
	struct pci_dev * next; /**< next in known-devices linked list */

	int	    i_MinorNumber;
	uint8_t    b_InterruptInstalled;

	uint32_t	dw_InterruptSource[ADDIDATA_MAX_EVENT_COUNTER]; /* store the source of interrupt */
	uint32_t	dw_ChannelValue[ADDIDATA_MAX_EVENT_COUNTER][ADDIDATA_MAX_AI + 1];
	uint32_t	dw_SequenceArray[ADDIDATA_MAX_EVENT_COUNTER][ADDIDATA_MAX_INTERRUPT_ANALOG_INPUT_VALUE];
	uint32_t	dw_EventCounterWrite;
	uint32_t	dw_EventCounterRead;

	uint8_t	b_DigitalOutputMemoryState;
	uint32_t	dw_DigitalOutputRegister;

	void __iomem * dw_MemBaseAddress0;
	void __iomem * dw_MemBaseAddress3;

	uint8_t	b_TimerCounterWatchdogConfigurableAsTimer[ADDIDATA_MAX_TCW];
	uint8_t	b_TimerCounterWatchdogConfigurableAsCounter[ADDIDATA_MAX_TCW];
	uint8_t	b_TimerCounterWatchdogConfigurableAsWatchdog[ADDIDATA_MAX_TCW];

	uint8_t	b_TimerCounterWatchdogConfiguration[ADDIDATA_MAX_TCW];
	uint32_t	dw_TimerCounterWatchdogOffsetAdress[ADDIDATA_MAX_TCW];

	uint8_t	b_DigitalInOutputSupported; /* 24V dig I/O  0 : boolean */
	uint32_t	dw_DigitalInputOffsetAdress;
	uint32_t	dw_DigitalOutputOffsetAdress;

	uint8_t	b_TTLSupported; /* TTL I/O  0 : boolean */
	uint32_t	dw_TTLOffsetAdress;
	uint8_t	b_TTLConfiguration;

	uint8_t   	b_NumberOfAnalogInput; /* analog input number : (0,ADDIDATA_MAX_AI) */
	uint8_t 	b_AnalogInputChannelInitialised[ADDIDATA_MAX_AI];

	uint8_t   	b_AnalogInputSeDiffConfigurationSupported; /* is configuration of single/differential is supported by the board ? */
	uint8_t   	b_AnalogInputSeDiffConfiguration; /* current configuration (constant if b_AnalogInputSeDiffConfigurationSupported is false) */

	uint32_t 	dw_AnalogInputOffsetAdress;
	uint32_t 	dw_MaxConvertTimeForNanoSecond;
	uint32_t 	dw_MinConvertTimeForNanoSecond;
	uint32_t 	dw_MaxConvertTimeForMicroSecond;
	uint32_t 	dw_MinConvertTimeForMicroSecond;
	uint32_t 	dw_MaxConvertTimeForMilliSecond;
	uint32_t 	dw_MinConvertTimeForMilliSecond;

	uint32_t 	dw_MaxDelayTimeForMicroSecond;
	uint32_t 	dw_MinDelayTimeForMicroSecond;
	uint32_t 	dw_MaxDelayTimeForMilliSecond;
	uint32_t 	dw_MinDelayTimeForMilliSecond;
	uint32_t 	dw_MaxDelayTimeForSecond;
	uint32_t 	dw_MinDelayTimeForSecond;

	uint8_t	b_AnalogInputAutoRefreshInitialised;
	uint8_t	b_NumberOfAutoRefreshChannels;

	uint8_t	b_AnalogInputSequenceInitialised;
	uint8_t	b_AnalogInputSequenceStarted;
	uint8_t	b_NumberOfSequenceChannels;

	uint8_t	b_AnalogInputDMASupported; /* analog input support DMA */
	uint8_t	b_AnalogInputDMA;
	str_ScatterGatherPCIDMAInformation     s_ScatterGatherPCIDMAInformation;
	str_ScatterGatherInterruptDescriptor  *ps_ScatterGatherDescriptor;
	uint32_t	dw_LastScatterGatherBuffer;
	uint32_t	dw_NumberOfSequenceForEachInterrupt;

	/* Variable for the shared memory */
	//struct fasync_struct * fa;
	char* kmalloc_area;
	char* kmalloc_ptr;

	uint8_t 	b_NumberOfAnalogOutput;	/* number of analog outputs */
	uint32_t	dw_AnalogOutputOffsetAdress;
	uint8_t 	b_NumberOfAnalogOutputVoltageMode;
	uint8_t 	b_AnalogOutputInitialisedVoltageMode;

	struct fasync_struct * async_queue; /* asynchronous readers */


	// APCI 1710 inside related
	str_BoardInfos s_BoardInfos;
	str_ModuleInfo s_ModuleInfo[4];

	str_InterruptInfos s_InterruptInfos;
	str_UserInterruptCallback s_UserInterruptCallback; /* One user interrupt for each board */
	str_InterruptFunctionality  s_InterruptFunctionality [4];
	str_InterruptParameters s_InterruptParameters;
};

/** initialise board's private data - fill it when adding new members and ioctl handlers */
static __inline__ void print_capability(struct pci_dev *pdev, char* str)
{
	printk(KERN_INFO "%s: board %s: capability %s\n", __DRIVER_NAME, pci_name(pdev), str );
}

static __inline__ void xpci3009_init_priv_data(struct pci_dev * pdev, struct xpci3009_str_BoardInformations * data)
{
	memset(data,0,sizeof(data));

	spin_lock_init(& (data->lock) );

	// FILLME
	data->async_queue = NULL;

	data->previous = NULL;
	data->next = NULL;

	data->i_MinorNumber = 0;
	data->b_InterruptInstalled = 0;

	memset (&data->dw_InterruptSource, 0, sizeof (data->dw_InterruptSource));
	memset (&data->dw_ChannelValue, 0, sizeof (data->dw_ChannelValue));
	memset (&data->dw_SequenceArray, 0, sizeof (data->dw_SequenceArray));
	data->dw_EventCounterWrite = 0;
	data->dw_EventCounterRead = 0;

	data->b_DigitalOutputMemoryState = 0;
	data->dw_DigitalOutputRegister = 0;

	data->dw_MemBaseAddress0 = NULL;
	data->dw_MemBaseAddress3 = NULL;

	memset (&data->b_AnalogInputChannelInitialised, 0, sizeof (data->b_AnalogInputChannelInitialised));
	memset (&data->b_TimerCounterWatchdogConfiguration, 0, sizeof (data->b_TimerCounterWatchdogConfiguration));

	data->b_AnalogInputAutoRefreshInitialised = 0;
	data->b_NumberOfAutoRefreshChannels = 0;

	data->b_AnalogInputSequenceInitialised = 0;
	data->b_AnalogInputSequenceStarted = 0;
	data->b_NumberOfSequenceChannels = 0;

	data->b_AnalogInputDMASupported = ADDIDATA_DISABLE;
	data->dw_LastScatterGatherBuffer = 0;
	data->dw_NumberOfSequenceForEachInterrupt = 0;

	//data->fa = NULL;
	data->kmalloc_area = NULL;
	data->kmalloc_ptr = NULL;
	data->ps_ScatterGatherDescriptor = NULL;
	memset (&data->s_ScatterGatherPCIDMAInformation, 0, sizeof (data->s_ScatterGatherPCIDMAInformation));

	print_capability(pdev, "xPCI-3009");
	//for (b_TCWCounter = 0 ; b_TCWCounter < ADDIDATA_MAX_TCW ; b_TCWCounter++)
	//	data->dw_TimerCounterWatchdogOffsetAdress[b_TCWCounter] = 128 + (b_TCWCounter * 32);

	data->dw_TimerCounterWatchdogOffsetAdress[0] = 128;
	data->b_TimerCounterWatchdogConfigurableAsTimer[0] = ADDIDATA_ENABLE;
	data->b_TimerCounterWatchdogConfigurableAsCounter[0] = ADDIDATA_ENABLE;
	data->b_TimerCounterWatchdogConfigurableAsWatchdog[0] = ADDIDATA_DISABLE;

	data->dw_TimerCounterWatchdogOffsetAdress[1] = 160;
	data->b_TimerCounterWatchdogConfigurableAsTimer[1] = ADDIDATA_ENABLE;
	data->b_TimerCounterWatchdogConfigurableAsCounter[1] = ADDIDATA_ENABLE;
	data->b_TimerCounterWatchdogConfigurableAsWatchdog[1] = ADDIDATA_ENABLE;

	data->dw_TimerCounterWatchdogOffsetAdress[2] = 192;
	data->b_TimerCounterWatchdogConfigurableAsTimer[2] = ADDIDATA_ENABLE;
	data->b_TimerCounterWatchdogConfigurableAsCounter[2] =ADDIDATA_ENABLE;
	data->b_TimerCounterWatchdogConfigurableAsWatchdog[2] = ADDIDATA_ENABLE;

	data->b_DigitalInOutputSupported = ADDIDATA_ENABLE;
	data->dw_DigitalInputOffsetAdress = 32; // Ok, look in the io mapping
	data->dw_DigitalOutputOffsetAdress = 48;

	data->b_TTLSupported = ADDIDATA_DISABLE;
	data->dw_TTLOffsetAdress = 0;
	data->b_TTLConfiguration = 0;

	data->b_NumberOfAnalogInput = 16;

	data->b_AnalogInputSeDiffConfigurationSupported = ADDIDATA_ENABLE;
	data->b_AnalogInputSeDiffConfiguration = ADDIDATA_SINGLE;

	data->dw_AnalogInputOffsetAdress = 0;
	data->dw_MaxConvertTimeForNanoSecond  = 0;
	data->dw_MinConvertTimeForNanoSecond  = 0;
	data->dw_MaxConvertTimeForMicroSecond = 65535; // 16 bit resolution
	data->dw_MinConvertTimeForMicroSecond = 5;
	data->dw_MaxConvertTimeForMilliSecond = 65535; // 16 bit resolution
	data->dw_MinConvertTimeForMilliSecond = 1;

	data->dw_MaxDelayTimeForMicroSecond = 65535; // 16 bit resolution
	data->dw_MinDelayTimeForMicroSecond = 1;
	data->dw_MaxDelayTimeForMilliSecond = 65535; // 16 bit resolution
	data->dw_MinDelayTimeForMilliSecond = 1;
	data->dw_MaxDelayTimeForSecond  = 0;
	data->dw_MinDelayTimeForSecond  = 0;

	data->b_AnalogInputDMASupported = ADDIDATA_ENABLE;

	data->b_NumberOfAnalogOutput = 4;
	data->dw_AnalogOutputOffsetAdress = 96;
	data->b_NumberOfAnalogOutputVoltageMode = 2; // Bipolar 12 bit, Unipolar 11 bit
	data->b_AnalogOutputInitialisedVoltageMode = 0;

	// APCI 1710 inside related
	data->s_BoardInfos.b_NumberOfModule = 1;

	data->s_InterruptFunctionality[0].v_InterruptFunction = NULL;
	data->s_InterruptFunctionality[1].v_InterruptFunction = NULL;
	data->s_InterruptFunctionality[2].v_InterruptFunction = NULL;
	data->s_InterruptFunctionality[3].v_InterruptFunction = NULL;
	data->s_UserInterruptCallback.v_UserInterruptFunction = NULL;

	memset(&data->s_InterruptParameters, 0, sizeof(data->s_InterruptParameters));
}

/** 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 xpci3009_str_BoardInformations * XPCI3009_PRIVDATA(struct pci_dev * pdev)
{
	return (struct xpci3009_str_BoardInformations *) pci_get_drvdata(pdev);
}

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

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

// ----------------------------------------------------------
// 				APCI 1710 inside related

/* returns 1 if the module index is not in the range of the board */
static inline int NUMBER_OF_MODULE(struct pci_dev * pdev)
{
	return (XPCI3009_PRIVDATA(pdev)->s_BoardInfos.b_NumberOfModule);
}

/* returns 1 if the module index is not in the range of the board */
static inline int NOT_A_MODULE(struct pci_dev * pdev, uint8_t b_ModulNbr)
{
	return (b_ModulNbr >= NUMBER_OF_MODULE(pdev));
}

/* returns the ID ( = CONFIGURATION) of a module (FUNCTIONALITY/VERSION) */
static inline uint32_t XPCI3009_MODULE_ID(struct pci_dev * pdev, unsigned char module)
{
	return (XPCI3009_PRIVDATA(pdev)->s_BoardInfos.dw_MolduleConfiguration [(int)module]);
}

/* returns the functionality of a module (first 2 bytes of configuration) */
static inline uint32_t XPCI3009_MODULE_FUNCTIONALITY(struct pci_dev * pdev, unsigned char module)
{
	return ( (XPCI3009_PRIVDATA(pdev)->s_BoardInfos.dw_MolduleConfiguration [(int)module]) >> 16) & 0x0000FFFFUL;
}

/* returns the version (revision) of the firmware of a module (last 2 bytes of configuration) */
static inline uint32_t XPCI3009_MODULE_VERSION(struct pci_dev * pdev, unsigned char module)
{
	return (XPCI3009_PRIVDATA(pdev)->s_BoardInfos.dw_MolduleConfiguration [(int)module]) & 0x0000FFFFUL;
}

/* offset to access module b_ModulNbr */
static inline uint32_t MODULE_OFFSET(uint8_t b_ModulNbr)
{
	return ((uint32_t) b_ModulNbr) * 64;
}

/* returns 1 if given module _is_ an incremental counter */
static inline int IS_A_COUNTER(struct pci_dev * pdev, uint8_t b_ModulNbr)
{
	return (XPCI3009_MODULE_FUNCTIONALITY(pdev,b_ModulNbr) == XPCI3009_INCREMENTAL_COUNTER) ;
}

/* returns 1 if given module is _not_ an incremental counter */
static inline int NOT_A_COUNTER(struct pci_dev * pdev, uint8_t b_ModulNbr)
{
	return ! IS_A_COUNTER(pdev, b_ModulNbr);
}

/* returns 1 if the interrupt function has not been initialised yet */
static inline int INTERRUPT_FUNCTION_NOT_INITIALISED(struct pci_dev * pdev)
{
	return ( (XPCI3009_PRIVDATA(pdev)->s_InterruptInfos.b_InterruptInitialized) == 0 );
}

/* returns 1 if a user handler has been installed for a given module */
static inline int MODULE_HAS_USER_HANDLER(struct pci_dev * pdev, uint8_t b_ModulNbr)
{
	return (XPCI3009_PRIVDATA(pdev)->s_InterruptFunctionality [b_ModulNbr].v_InterruptFunction != NULL);
}

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

// append to the list of known devices
extern void xpci3009_known_dev_append(struct pci_dev * pdev);
// remove from the list of known devices
extern void xpci3009_known_dev_remove(struct pci_dev * pdev);

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

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

#ifdef CONFIG_XPCI3009_DEBUG
#warning Compiled with debug !
#define XPCI3009_DEBUG(args...) printk(KERN_DEBUG ## args)
#define XPCI3009_DEBUG_FCN() XPCI3009_DEBUG("%s\n",__FUNCTION__);
#define XPCI3009_DEBUG_INTARRAY(__name,__from, __to,__array) { int i; for(i=__from;i<__to;i++) XPCI3009_DEBUG("%s %d: %d\n",__name, i, __array[i]); }
#define XPCI3009_DEBUG_CALLRET(__call...) printk(KERN_DEBUG "%s returned %d\n", #__call, __call)
#else
#define XPCI3009_DEBUG(args...)
#define XPCI3009_DEBUG_FCN()
#define XPCI3009_DEBUG_INTARRAY(__name,__from, __to,__array)
#define XPCI3009_DEBUG_CALLRET(__call...) __call
#endif

#endif // __XPCI3009_PRIVDATA_H_
