#ifndef __PCI17X4_H_INCLUDED__
#define __PCI17X4_H_INCLUDED__

#ifndef  __KERNEL__
#include <stdint.h>
#include <linux/ioctl.h>
#endif

typedef struct pci17x4_register {		/* Structure to read/write an ADC register */
  uint16_t index;				/* Register offset */
  uint8_t size;					/* Size of register I/O in bits: valid values are 8, 16 or 32 */
  uint8_t flags;				/* Flags: See enum below. */
  uint32_t value;				/* Register input/output value */
} pci17x4_register_t;

typedef struct pci17x4_dmasetup {		/* Structure to configure DMA */
  uint32_t numblocks;				/* Total size of the circular buffer (must be multiple of block size) */
  uint8_t blockshift;				/* Log 2 of the size of one buffer block */
  uint8_t armtrigger;				/* If non-zero reset the trigger register every time ADC triggers (used for measuring 1/rev on trigger input) */
  uint16_t timeout;				/* How long to wait for a read request or register I/O ioctl (ms) */
} pci17x4_dmasetup_t;

typedef struct pci17x4_dmastatus {		/* Structure to return DMA status */
  pci17x4_dmasetup_t setup;			/* The setup */
  uint64_t readcount;				/* Number of DMA buffer blocks transferred so far */
  union {
    uint32_t error;				/* Any error */
    struct {					/* Errors by source */
      uint16_t errsys;				/* System generated errors */
      uint16_t erruser;				/* Userspace generated errors */
    };
    struct {					/* Individual error indicators */
      uint8_t errfifo;				/* A/D fifo has overflown */
      uint8_t errtout;				/* Read timeout */
      uint8_t errbuf;				/* Circular buffer overflow error */
      uint8_t errio;				/* I/O error (from ioctl() return code) */
    };
  };
  uint8_t pageshift;				/* Log 2 of system page size */
  uint8_t running;				/* Is the board running? */
  uint8_t ulboard;				/* Is this a 10MHz board? */
  uint8_t unused[1];
} pci17x4_dmastatus_t;

enum {
  /* ---- card types (subsystem IDs) ---- */
  PCI1714_TYPE_ = 0x0000,
  PCI1714_TYPE_U = 0xb100,
  PCI1714_TYPE_UL = 0xa101,
  PCI1714_TYPE_UL_A = 0xa101,
  PCI1714_TYPE_UL_B = 0xb101,
  PCI1744_TYPE = 0xa100,
  /* ---- internal clock generator rate ---- */
  PCI17X4_CLOCKRATE = 60000000,
  PCI1714_CLOCKRATE_UL = 20000000,
  /* ---- FIFO sizes ---- */
  PCI17X4_FIFOSIZE = 32768,
  PCI1714_FIFOSIZE_UL = 8192,
  /* ---- data registers ---- */
  PCI17X4_DATA_0_REG16 = 0,
  PCI17X4_DATA_1_REG16 = 2,
  PCI17X4_DATA_2_REG16 = 4,
  PCI17X4_DATA_3_REG16 = 6,
  PCI17X4_DATA_01_REG32 = 0,
  PCI17X4_DATA_23_REG32 = 4,
  PCI17X4_DATA_SAMPBITS = 12,
  PCI17X4_DATA_SAMPMASK = 0xfff,
  PCI17X4_DATA_SAMPBIAS = 0x800,
  PCI17X4_DATA_RANGEMASK = 0x3000,
  PCI17X4_DATA_RANGESHIFT = 12,
  PCI17X4_DATA_OVFMASK = 0x4000,
  PCI17X4_DATA_TRIGMASK = 0x8000,
  /* ---- range control register ---- */
  PCI17X4_RANGE_REG16 = 8,
  PCI17X4_RANGE_5_0V = 0,
  PCI17X4_RANGE_2_5V = 1,
  PCI17X4_RANGE_1_0V = 2,
  PCI17X4_RANGE_0_5V = 3,
  /* ---- channel enable register ---- */
  PCI17X4_ADCENABLE_REG16 = 10,
  PCI17X4_ADCENABLE_CH0 = 1,
  PCI17X4_ADCENABLE_CH1 = 2,
  PCI17X4_ADCENABLE_CH2 = 4,
  PCI17X4_ADCENABLE_CH3 = 8,
  PCI17X4_ADCENABLE_ALL = 0xf,
  /* ---- clock control register ---- */
  PCI17X4_CLOCK_REG16 = 12,
  PCI17X4_CLOCK_DIVMASK = 0xff,
  PCI17X4_CLOCK_MINDIV = 2,
  PCI17X4_CLOCK_MAXDIV = 256,
  PCI17X4_CLOCK_DIVBIAS = 1,
  PCI17X4_CLOCK_SRCMASK = 0x300,
  PCI17X4_CLOCK_SRCINT = 0,
  PCI17X4_CLOCK_SRCEXT0 = 0x100,
  PCI17X4_CLOCK_SRCEXT1 = 0x200,
  PCI17X4_CLOCK_SRCOFF = 0x300,
  /* ---- sample rate limits ---- */
  PCI17X4_MAXSAMPRATE = (PCI17X4_CLOCKRATE / PCI17X4_CLOCK_MINDIV),
  PCI17X4_MINSAMPRATE = (PCI17X4_CLOCKRATE / PCI17X4_CLOCK_MAXDIV),
  PCI1714_MAXSAMPRATE_UL = (PCI1714_CLOCKRATE_UL / PCI17X4_CLOCK_MINDIV),
  PCI1714_MINSAMPRATE_UL = (PCI1714_CLOCKRATE_UL / PCI17X4_CLOCK_MAXDIV),
  /* ---- trigger control/status register ---- */
  PCI17X4_TRIGGER_REG16 = 14,
  PCI17X4_TRIGGER_MODEMASK = 7,
  PCI17X4_TRIGGER_MODESOFT = 0,
  PCI17X4_TRIGGER_MODEPACER = 1,
  PCI17X4_TRIGGER_MODEPOST = 2,
  PCI17X4_TRIGGER_MODEDELAY = 3,
  PCI17X4_TRIGGER_MODEABOUT = 4,
  PCI17X4_TRIGGER_SRCMASK = 0x70,
  PCI17X4_TRIGGER_SRCCH0 = 0,
  PCI17X4_TRIGGER_SRCCH1 = 0x10,
  PCI17X4_TRIGGER_SRCCH2 = 0x20,
  PCI17X4_TRIGGER_SRCCH3 = 0x30,
  PCI17X4_TRIGGER_SRCEXT = 0x40,
  PCI17X4_TRIGGER_FALLING = 0x80,
  PCI17X4_TRIGGER_DMATC = 0x4000,
  PCI17X4_TRIGGER_FLAG = 0x8000,
  /* ---- FIFO control registers ---- */
  PCI17X4_FIFOCTR_01_REG16 = 16,
  PCI17X4_FIFOCTR_23_REG16 = 18,
  PCI17X4_FIFOCTR_REG32 = 16,
  PCI17X4_FIFOCTR_CLEAR = 1,
  PCI17X4_FIFOCTR_RESET = 2,
  /* ---- FIFO status registers ---- */
  PCI17X4_FIFOSTAT_01_REG16 = 16,
  PCI17X4_FIFOSTAT_23_REG16 = 18,
  PCI17X4_FIFOSTAT_REG32 = 16,
  PCI17X4_FIFOSTAT_EMPTY = 1,
  PCI17X4_FIFOSTAT_HFULL = 2,
  PCI17X4_FIFOSTAT_FULL = 4,
  PCI17X4_FIFOSTAT_AEMPTY = 0x10,
  PCI17X4_FIFOSTAT_AFULL = 0x20,
  /* ---- FIFO almost full/empty level registers ---- */
  PCI17X4_FIFOLEVEL_0_REG16 = 20,
  PCI17X4_FIFOLEVEL_1_REG16 = 22,
  PCI17X4_FIFOLEVEL_2_REG16 = 24,
  PCI17X4_FIFOLEVEL_3_REG16 = 26,
  PCI17X4_FIFOLEVEL_01_REG32 = 20,
  PCI17X4_FIFOLEVEL_23_REG32 = 24,
  /* ---- DMA counter register ---- */
  PCI17X4_DMACOUNTER_REG16 = 28,
  /* ---- DMA counter reset register ---- */
  PCI17X4_DMACRESET_REG16 = 30,
  /* ---- interrupt control/status register ---- */
  PCI17X4_IRQ_REG16 = 32,
  PCI17X4_IRQ_CH0HF = 1,
  PCI17X4_IRQ_CH0AF = 2,
  PCI17X4_IRQ_CH1HF = 4,
  PCI17X4_IRQ_CH1AF = 8,
  PCI17X4_IRQ_CH2HF = 0x10,
  PCI17X4_IRQ_CH2AF = 0x20,
  PCI17X4_IRQ_CH3HF = 0x40,
  PCI17X4_IRQ_CH3AF = 0x80,
  PCI17X4_IRQ_DMATC = 0x100,
  PCI17X4_IRQ_ENABLE = 0x8000,
  PCI17X4_IRQ_REQUEST = 0x8000,
  /* ---- interrupt clear register ---- */
  PCI17X4_IRQCLEAR_REG16 = 34,
  /* ---- analog trigger level register ---- */
  PCI17X4_ATRIGLEVEL_REG16 = 36,
  PCI17X4_ATRIGLEVEL_BITS = 8,
  /* ---- DMA start channel reset register ---- */
  PCI17X4_DMACHRESET_REG16 = 48,
  /* ---- DMA four channel alternating register ---- */
  PCI17X4_DMADATA_REG32 = 48,
  /* ---- DMA request selector register ---- */
  PCI17X4_DMAREQUEST_REG16 = 32,
  PCI17X4_DMAREQUEST_FIFO0 = 0,
  PCI17X4_DMAREQUEST_FIFO2 = 1,
  /* ---- ioctl() codes ---- */
  IOCTL_PCI17X4 = ('A'),
  IOCTL_PCI17X4_REGISTER_IO = _IOWR(IOCTL_PCI17X4, 1, struct pci17x4_register),
  IOCTL_PCI17X4_DMA_SETUP = _IOR(IOCTL_PCI17X4, 2, pci17x4_dmasetup_t),
  IOCTL_PCI17X4_DMA_STATUS = _IOWR(IOCTL_PCI17X4, 3, pci17x4_dmastatus_t),
  IOCTL_PCI17X4_DMA_WAIT = _IOWR(IOCTL_PCI17X4, 4, pci17x4_dmastatus_t),
  IOCTL_PCI17X4_DMA_START = _IO(IOCTL_PCI17X4, 5),
  IOCTL_PCI17X4_DMA_STOP = _IO(IOCTL_PCI17X4, 6),
  /* ---- DMA buffer limits ---- */
  PCI17X4_IOCTL_MIN_NUMBLOCKS = 4,
  PCI17X4_IOCTL_MAX_NUMBLOCKS = (1 << 20),
  /* ---- Register I/O flag bits (set READ, WRITE or both for write and read back, PLX for bridge registers, IMMEDIATE to perform access immediately even when DMA is running) */
  PCI17X4_IOCTL_REGISTER_WRITE = 1,
  PCI17X4_IOCTL_REGISTER_READ = 2,
  PCI17X4_IOCTL_REGISTER_PLX = 4,
  PCI17X4_IOCTL_REGISTER_IMMEDIATE = 64
};

#endif
