/*
    me4000.h
    Register descriptions and defines for the ME-4000 board family

    COMEDI - Linux Control and Measurement Device Interface
    Copyright (C) 1998-9 David A. Schleef <ds@schleef.org>

    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 should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#ifndef _ME4000_H_
#define _ME4000_H_

/*=============================================================================
  Debug section
  ===========================================================================*/

#undef ME4000_CALL_DEBUG	// Debug function entry and exit
#undef ME4000_PORT_DEBUG	// Debug port access
#undef ME4000_ISR_DEBUG		// Debug the interrupt service routine
#undef ME4000_DEBUG		// General purpose debug masseges

#ifdef ME4000_CALL_DEBUG
#undef CALL_PDEBUG
#define CALL_PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor, ##args)
#else
# define CALL_PDEBUG(fmt, args...)	// no debugging, do nothing
#endif

#ifdef ME4000_PORT_DEBUG
#undef PORT_PDEBUG
#define PORT_PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor,  ##args)
#else
#define PORT_PDEBUG(fmt, args...)	// no debugging, do nothing
#endif

#ifdef ME4000_ISR_DEBUG
#undef ISR_PDEBUG
#define ISR_PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor,  ##args)
#else
#define ISR_PDEBUG(fmt, args...)	// no debugging, do nothing
#endif

#ifdef ME4000_DEBUG
#undef PDEBUG
#define PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor,  ##args)
#else
#define PDEBUG(fmt, args...)	// no debugging, do nothing
#endif

/*=============================================================================
  PCI vendor and device IDs
  ===========================================================================*/

#define PCI_VENDOR_ID_MEILHAUS 0x1402

#define PCI_DEVICE_ID_MEILHAUS_ME4650	0x4650	// Low Cost version

#define PCI_DEVICE_ID_MEILHAUS_ME4660	0x4660	// Standard version
#define PCI_DEVICE_ID_MEILHAUS_ME4660I	0x4661	// Isolated version
#define PCI_DEVICE_ID_MEILHAUS_ME4660S	0x4662	// Standard version with Sample and Hold
#define PCI_DEVICE_ID_MEILHAUS_ME4660IS	0x4663	// Isolated version with Sample and Hold

#define PCI_DEVICE_ID_MEILHAUS_ME4670	0x4670	// Standard version
#define PCI_DEVICE_ID_MEILHAUS_ME4670I	0x4671	// Isolated version
#define PCI_DEVICE_ID_MEILHAUS_ME4670S	0x4672	// Standard version with Sample and Hold
#define PCI_DEVICE_ID_MEILHAUS_ME4670IS	0x4673	// Isolated version with Sample and Hold

#define PCI_DEVICE_ID_MEILHAUS_ME4680	0x4680	// Standard version
#define PCI_DEVICE_ID_MEILHAUS_ME4680I	0x4681	// Isolated version
#define PCI_DEVICE_ID_MEILHAUS_ME4680S	0x4682	// Standard version with Sample and Hold
#define PCI_DEVICE_ID_MEILHAUS_ME4680IS	0x4683	// Isolated version with Sample and Hold

/*=============================================================================
  ME-4000 base register offsets
  ===========================================================================*/

#define ME4000_AO_00_CTRL_REG			0x00	// R/W
#define ME4000_AO_00_STATUS_REG			0x04	// R/_
#define ME4000_AO_00_FIFO_REG			0x08	// _/W
#define ME4000_AO_00_SINGLE_REG			0x0C	// R/W
#define ME4000_AO_00_TIMER_REG			0x10	// _/W

#define ME4000_AO_01_CTRL_REG			0x18	// R/W
#define ME4000_AO_01_STATUS_REG			0x1C	// R/_
#define ME4000_AO_01_FIFO_REG			0x20	// _/W
#define ME4000_AO_01_SINGLE_REG			0x24	// R/W
#define ME4000_AO_01_TIMER_REG			0x28	// _/W

#define ME4000_AO_02_CTRL_REG			0x30	// R/W
#define ME4000_AO_02_STATUS_REG			0x34	// R/_
#define ME4000_AO_02_FIFO_REG			0x38	// _/W
#define ME4000_AO_02_SINGLE_REG			0x3C	// R/W
#define ME4000_AO_02_TIMER_REG			0x40	// _/W

#define ME4000_AO_03_CTRL_REG			0x48	// R/W
#define ME4000_AO_03_STATUS_REG			0x4C	// R/_
#define ME4000_AO_03_FIFO_REG			0x50	// _/W
#define ME4000_AO_03_SINGLE_REG			0x54	// R/W
#define ME4000_AO_03_TIMER_REG			0x58	// _/W

#define ME4000_AI_CTRL_REG			0x74	// _/W
#define ME4000_AI_STATUS_REG			0x74	// R/_
#define ME4000_AI_CHANNEL_LIST_REG		0x78	// _/W
#define ME4000_AI_DATA_REG			0x7C	// R/_
#define ME4000_AI_CHAN_TIMER_REG		0x80	// _/W
#define ME4000_AI_CHAN_PRE_TIMER_REG		0x84	// _/W
#define ME4000_AI_SCAN_TIMER_LOW_REG		0x88	// _/W
#define ME4000_AI_SCAN_TIMER_HIGH_REG		0x8C	// _/W
#define ME4000_AI_SCAN_PRE_TIMER_LOW_REG	0x90	// _/W
#define ME4000_AI_SCAN_PRE_TIMER_HIGH_REG	0x94	// _/W
#define ME4000_AI_START_REG			0x98	// R/_

#define ME4000_IRQ_STATUS_REG			0x9C	// R/_

#define ME4000_DIO_PORT_0_REG			0xA0	// R/W
#define ME4000_DIO_PORT_1_REG			0xA4	// R/W
#define ME4000_DIO_PORT_2_REG			0xA8	// R/W
#define ME4000_DIO_PORT_3_REG			0xAC	// R/W
#define ME4000_DIO_DIR_REG			0xB0	// R/W

#define ME4000_AO_LOADSETREG_XX			0xB4	// R/W

#define ME4000_DIO_CTRL_REG			0xB8	// R/W

#define ME4000_AO_DEMUX_ADJUST_REG		0xBC	// -/W

#define ME4000_AI_SAMPLE_COUNTER_REG		0xC0	// _/W

/*=============================================================================
  Value to adjust Demux
  ===========================================================================*/

#define ME4000_AO_DEMUX_ADJUST_VALUE            0x4C

/*=============================================================================
  Counter base register offsets
  ===========================================================================*/

#define ME4000_CNT_COUNTER_0_REG		0x00
#define ME4000_CNT_COUNTER_1_REG		0x01
#define ME4000_CNT_COUNTER_2_REG		0x02
#define ME4000_CNT_CTRL_REG			0x03

/*=============================================================================
  PLX base register offsets
  ===========================================================================*/

#define PLX_INTCSR	0x4C	// Interrupt control and status register
#define PLX_ICR		0x50	// Initialization control register

/*=============================================================================
  Bits for the PLX_ICSR register
  ===========================================================================*/

#define PLX_INTCSR_LOCAL_INT1_EN             0x01	// If set, local interrupt 1 is enabled (r/w)
#define PLX_INTCSR_LOCAL_INT1_POL            0x02	// If set, local interrupt 1 polarity is active high (r/w)
#define PLX_INTCSR_LOCAL_INT1_STATE          0x04	// If set, local interrupt 1 is active (r/_)
#define PLX_INTCSR_LOCAL_INT2_EN             0x08	// If set, local interrupt 2 is enabled (r/w)
#define PLX_INTCSR_LOCAL_INT2_POL            0x10	// If set, local interrupt 2 polarity is active high (r/w)
#define PLX_INTCSR_LOCAL_INT2_STATE          0x20	// If set, local interrupt 2 is active  (r/_)
#define PLX_INTCSR_PCI_INT_EN                0x40	// If set, PCI interrupt is enabled (r/w)
#define PLX_INTCSR_SOFT_INT                  0x80	// If set, a software interrupt is generated (r/w)

/*=============================================================================
  Bits for the PLX_ICR register
  ===========================================================================*/

#define PLX_ICR_BIT_EEPROM_CLOCK_SET		0x01000000
#define PLX_ICR_BIT_EEPROM_CHIP_SELECT		0x02000000
#define PLX_ICR_BIT_EEPROM_WRITE		0x04000000
#define PLX_ICR_BIT_EEPROM_READ			0x08000000
#define PLX_ICR_BIT_EEPROM_VALID		0x10000000

#define PLX_ICR_MASK_EEPROM			0x1F000000

#define EEPROM_DELAY				1

/*=============================================================================
  Bits for the ME4000_AO_CTRL_REG register
  ===========================================================================*/

#define ME4000_AO_CTRL_BIT_MODE_0		0x001
#define ME4000_AO_CTRL_BIT_MODE_1		0x002
#define ME4000_AO_CTRL_MASK_MODE		0x003
#define ME4000_AO_CTRL_BIT_STOP			0x004
#define ME4000_AO_CTRL_BIT_ENABLE_FIFO		0x008
#define ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG	0x010
#define ME4000_AO_CTRL_BIT_EX_TRIG_EDGE		0x020
#define ME4000_AO_CTRL_BIT_IMMEDIATE_STOP	0x080
#define ME4000_AO_CTRL_BIT_ENABLE_DO		0x100
#define ME4000_AO_CTRL_BIT_ENABLE_IRQ		0x200
#define ME4000_AO_CTRL_BIT_RESET_IRQ		0x400

/*=============================================================================
  Bits for the ME4000_AO_STATUS_REG register
  ===========================================================================*/

#define ME4000_AO_STATUS_BIT_FSM		0x01
#define ME4000_AO_STATUS_BIT_FF			0x02
#define ME4000_AO_STATUS_BIT_HF			0x04
#define ME4000_AO_STATUS_BIT_EF			0x08

/*=============================================================================
  Bits for the ME4000_AI_CTRL_REG register
  ===========================================================================*/

#define ME4000_AI_CTRL_BIT_MODE_0		0x00000001
#define ME4000_AI_CTRL_BIT_MODE_1		0x00000002
#define ME4000_AI_CTRL_BIT_MODE_2		0x00000004
#define ME4000_AI_CTRL_BIT_SAMPLE_HOLD		0x00000008
#define ME4000_AI_CTRL_BIT_IMMEDIATE_STOP	0x00000010
#define ME4000_AI_CTRL_BIT_STOP			0x00000020
#define ME4000_AI_CTRL_BIT_CHANNEL_FIFO		0x00000040
#define ME4000_AI_CTRL_BIT_DATA_FIFO		0x00000080
#define ME4000_AI_CTRL_BIT_FULLSCALE		0x00000100
#define ME4000_AI_CTRL_BIT_OFFSET		0x00000200
#define ME4000_AI_CTRL_BIT_EX_TRIG_ANALOG	0x00000400
#define ME4000_AI_CTRL_BIT_EX_TRIG		0x00000800
#define ME4000_AI_CTRL_BIT_EX_TRIG_FALLING	0x00001000
#define ME4000_AI_CTRL_BIT_EX_IRQ		0x00002000
#define ME4000_AI_CTRL_BIT_EX_IRQ_RESET		0x00004000
#define ME4000_AI_CTRL_BIT_LE_IRQ		0x00008000
#define ME4000_AI_CTRL_BIT_LE_IRQ_RESET		0x00010000
#define ME4000_AI_CTRL_BIT_HF_IRQ		0x00020000
#define ME4000_AI_CTRL_BIT_HF_IRQ_RESET		0x00040000
#define ME4000_AI_CTRL_BIT_SC_IRQ		0x00080000
#define ME4000_AI_CTRL_BIT_SC_IRQ_RESET		0x00100000
#define ME4000_AI_CTRL_BIT_SC_RELOAD		0x00200000
#define ME4000_AI_CTRL_BIT_EX_TRIG_BOTH		0x80000000

/*=============================================================================
  Bits for the ME4000_AI_STATUS_REG register
  ===========================================================================*/

#define ME4000_AI_STATUS_BIT_EF_CHANNEL		0x00400000
#define ME4000_AI_STATUS_BIT_HF_CHANNEL		0x00800000
#define ME4000_AI_STATUS_BIT_FF_CHANNEL		0x01000000
#define ME4000_AI_STATUS_BIT_EF_DATA		0x02000000
#define ME4000_AI_STATUS_BIT_HF_DATA		0x04000000
#define ME4000_AI_STATUS_BIT_FF_DATA		0x08000000
#define ME4000_AI_STATUS_BIT_LE			0x10000000
#define ME4000_AI_STATUS_BIT_FSM		0x20000000

/*=============================================================================
  Bits for the ME4000_IRQ_STATUS_REG register
  ===========================================================================*/

#define ME4000_IRQ_STATUS_BIT_EX		0x01
#define ME4000_IRQ_STATUS_BIT_LE		0x02
#define ME4000_IRQ_STATUS_BIT_AI_HF		0x04
#define ME4000_IRQ_STATUS_BIT_AO_0_HF		0x08
#define ME4000_IRQ_STATUS_BIT_AO_1_HF		0x10
#define ME4000_IRQ_STATUS_BIT_AO_2_HF		0x20
#define ME4000_IRQ_STATUS_BIT_AO_3_HF		0x40
#define ME4000_IRQ_STATUS_BIT_SC		0x80

/*=============================================================================
  Bits for the ME4000_DIO_CTRL_REG register
  ===========================================================================*/

#define ME4000_DIO_CTRL_BIT_MODE_0		0x0001
#define ME4000_DIO_CTRL_BIT_MODE_1		0x0002
#define ME4000_DIO_CTRL_BIT_MODE_2		0x0004
#define ME4000_DIO_CTRL_BIT_MODE_3		0x0008
#define ME4000_DIO_CTRL_BIT_MODE_4		0x0010
#define ME4000_DIO_CTRL_BIT_MODE_5		0x0020
#define ME4000_DIO_CTRL_BIT_MODE_6		0x0040
#define ME4000_DIO_CTRL_BIT_MODE_7		0x0080

#define ME4000_DIO_CTRL_BIT_FUNCTION_0		0x0100
#define ME4000_DIO_CTRL_BIT_FUNCTION_1		0x0200

#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_0		0x0400
#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_1		0x0800
#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_2		0x1000
#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_3		0x2000

/*=============================================================================
  Information about the hardware capabilities
  ===========================================================================*/

typedef struct me4000_ao_info {
	int count;
	int fifo_count;
} me4000_ao_info_t;

typedef struct me4000_ai_info {
	int count;
	int sh_count;
	int diff_count;
	int ex_trig_analog;
} me4000_ai_info_t;

typedef struct me4000_dio_info {
	int count;
} me4000_dio_info_t;

typedef struct me4000_cnt_info {
	int count;
} me4000_cnt_info_t;

typedef struct me4000_board {
	const char *name;
	unsigned short device_id;
	me4000_ao_info_t ao;
	me4000_ai_info_t ai;
	me4000_dio_info_t dio;
	me4000_cnt_info_t cnt;
} me4000_board_t;

#define thisboard ((const me4000_board_t *)dev->board_ptr)

/*=============================================================================
  Global board and subdevice information structures
  ===========================================================================*/

typedef struct me4000_ao_context {
	int irq;

	unsigned long mirror;	// Store the last written value

	unsigned long ctrl_reg;
	unsigned long status_reg;
	unsigned long fifo_reg;
	unsigned long single_reg;
	unsigned long timer_reg;
	unsigned long irq_status_reg;
	unsigned long preload_reg;
} me4000_ao_context_t;

typedef struct me4000_ai_context {
	int irq;

	unsigned long ctrl_reg;
	unsigned long status_reg;
	unsigned long channel_list_reg;
	unsigned long data_reg;
	unsigned long chan_timer_reg;
	unsigned long chan_pre_timer_reg;
	unsigned long scan_timer_low_reg;
	unsigned long scan_timer_high_reg;
	unsigned long scan_pre_timer_low_reg;
	unsigned long scan_pre_timer_high_reg;
	unsigned long start_reg;
	unsigned long irq_status_reg;
	unsigned long sample_counter_reg;
} me4000_ai_context_t;

typedef struct me4000_dio_context {
	unsigned long dir_reg;
	unsigned long ctrl_reg;
	unsigned long port_0_reg;
	unsigned long port_1_reg;
	unsigned long port_2_reg;
	unsigned long port_3_reg;
} me4000_dio_context_t;

typedef struct me4000_cnt_context {
	unsigned long ctrl_reg;
	unsigned long counter_0_reg;
	unsigned long counter_1_reg;
	unsigned long counter_2_reg;
} me4000_cnt_context_t;

typedef struct me4000_info {
	unsigned long plx_regbase;	// PLX configuration space base address
	unsigned long me4000_regbase;	// Base address of the ME4000
	unsigned long timer_regbase;	// Base address of the timer circuit
	unsigned long program_regbase;	// Base address to set the program pin for the xilinx

	unsigned long plx_regbase_size;	// PLX register set space
	unsigned long me4000_regbase_size;	// ME4000 register set space
	unsigned long timer_regbase_size;	// Timer circuit register set space
	unsigned long program_regbase_size;	// Size of program base address of the ME4000

	unsigned int serial_no;	// Serial number of the board
	unsigned char hw_revision;	// Hardware revision of the board
	unsigned short vendor_id;	// Meilhaus vendor id
	unsigned short device_id;	// Device id

	struct pci_dev *pci_dev_p;	// General PCI information

	unsigned int irq;	// IRQ assigned from the PCI BIOS

	struct me4000_ai_context ai_context;	// Analog input  specific context
	struct me4000_ao_context ao_context[4];	// Vector with analog output specific context
	struct me4000_dio_context dio_context;	// Digital I/O specific context
	struct me4000_cnt_context cnt_context;	// Counter specific context
} me4000_info_t;

#define info	((me4000_info_t *)dev->private)

/*-----------------------------------------------------------------------------
  Defines for analog input
 ----------------------------------------------------------------------------*/

/* General stuff */
#define ME4000_AI_FIFO_COUNT			2048

#define ME4000_AI_MIN_TICKS			66
#define ME4000_AI_MIN_SAMPLE_TIME		2000	// Minimum sample time [ns]
#define ME4000_AI_BASE_FREQUENCY		(unsigned int) 33E6

/* Channel list defines and masks */
#define ME4000_AI_CHANNEL_LIST_COUNT		1024

#define ME4000_AI_LIST_INPUT_SINGLE_ENDED	0x000
#define ME4000_AI_LIST_INPUT_DIFFERENTIAL	0x020

#define ME4000_AI_LIST_RANGE_BIPOLAR_10		0x000
#define ME4000_AI_LIST_RANGE_BIPOLAR_2_5	0x040
#define ME4000_AI_LIST_RANGE_UNIPOLAR_10	0x080
#define ME4000_AI_LIST_RANGE_UNIPOLAR_2_5	0x0C0

#define ME4000_AI_LIST_LAST_ENTRY		0x100

/*-----------------------------------------------------------------------------
  Defines for counters
 ----------------------------------------------------------------------------*/

#define ME4000_CNT_COUNTER_0  0x00
#define ME4000_CNT_COUNTER_1  0x40
#define ME4000_CNT_COUNTER_2  0x80

#define ME4000_CNT_MODE_0     0x00	// Change state if zero crossing
#define ME4000_CNT_MODE_1     0x02	// Retriggerable One-Shot
#define ME4000_CNT_MODE_2     0x04	// Asymmetrical divider
#define ME4000_CNT_MODE_3     0x06	// Symmetrical divider
#define ME4000_CNT_MODE_4     0x08	// Counter start by software trigger
#define ME4000_CNT_MODE_5     0x0A	// Counter start by hardware trigger

#endif
