linux/drivers/comedi/drivers/daqboard2000.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * comedi/drivers/daqboard2000.c
 * hardware driver for IOtech DAQboard/2000
 *
 * COMEDI - Linux Control and Measurement Device Interface
 * Copyright (C) 1999 Anders Blomdell <[email protected]>
 */
/*
 * Driver: daqboard2000
 * Description: IOTech DAQBoard/2000
 * Author: Anders Blomdell <[email protected]>
 * Status: works
 * Updated: Mon, 14 Apr 2008 15:28:52 +0100
 * Devices: [IOTech] DAQBoard/2000 (daqboard2000)
 *
 * Much of the functionality of this driver was determined from reading
 * the source code for the Windows driver.
 *
 * The FPGA on the board requires firmware, which is available from
 * https://www.comedi.org in the comedi_nonfree_firmware tarball.
 *
 * Configuration options: not applicable, uses PCI auto config
 */
/*
 * This card was obviously never intended to leave the Windows world,
 * since it lacked all kind of hardware documentation (except for cable
 * pinouts, plug and pray has something to catch up with yet).
 *
 * With some help from our swedish distributor, we got the Windows sourcecode
 * for the card, and here are the findings so far.
 *
 * 1. A good document that describes the PCI interface chip is 9080db-106.pdf
 *    available from http://www.plxtech.com/products/io/pci9080
 *
 * 2. The initialization done so far is:
 *      a. program the FPGA (windows code sans a lot of error messages)
 *      b.
 *
 * 3. Analog out seems to work OK with DAC's disabled, if DAC's are enabled,
 *    you have to output values to all enabled DAC's until result appears, I
 *    guess that it has something to do with pacer clocks, but the source
 *    gives me no clues. I'll keep it simple so far.
 *
 * 4. Analog in.
 *    Each channel in the scanlist seems to be controlled by four
 *    control words:
 *
 *	Word0:
 *	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *	  ! | | | ! | | | ! | | | ! | | | !
 *	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
 *	Word1:
 *	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *	  ! | | | ! | | | ! | | | ! | | | !
 *	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *	   |             |       | | | | |
 *	   +------+------+       | | | | +-- Digital input (??)
 *		  |		 | | | +---- 10 us settling time
 *		  |		 | | +------ Suspend acquisition (last to scan)
 *		  |		 | +-------- Simultaneous sample and hold
 *		  |		 +---------- Signed data format
 *		  +------------------------- Correction offset low
 *
 *	Word2:
 *	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *	  ! | | | ! | | | ! | | | ! | | | !
 *	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *	   |     | |     | | | | | |     |
 *	   +-----+ +--+--+ +++ +++ +--+--+
 *	      |       |     |   |     +----- Expansion channel
 *	      |       |     |   +----------- Expansion gain
 *	      |       |     +--------------- Channel (low)
 *	      |       +--------------------- Correction offset high
 *	      +----------------------------- Correction gain low
 *	Word3:
 *	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *	  ! | | | ! | | | ! | | | ! | | | !
 *	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *	   |             | | | |   | | | |
 *	   +------+------+ | | +-+-+ | | +-- Low bank enable
 *		  |	   | |   |   | +---- High bank enable
 *		  |	   | |   |   +------ Hi/low select
 *		  |	   | |   +---------- Gain (1,?,2,4,8,16,32,64)
 *		  |	   | +-------------- differential/single ended
 *		  |	   +---------------- Unipolar
 *		  +------------------------- Correction gain high
 *
 * 999. The card seems to have an incredible amount of capabilities, but
 *      trying to reverse engineer them from the Windows source is beyond my
 *      patience.
 *
 */

#include <linux/module.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/comedi/comedi_pci.h>
#include <linux/comedi/comedi_8255.h>

#include "plx9080.h"

#define DB2K_FIRMWARE

static const struct comedi_lrange db2k_ai_range =;

/*
 * Register Memory Map
 */
#define DB2K_REG_ACQ_CONTROL
#define DB2K_REG_ACQ_STATUS
#define DB2K_REG_ACQ_SCAN_LIST_FIFO
#define DB2K_REG_ACQ_PACER_CLOCK_DIV_LOW
#define DB2K_REG_ACQ_SCAN_COUNTER
#define DB2K_REG_ACQ_PACER_CLOCK_DIV_HIGH
#define DB2K_REG_ACQ_TRIGGER_COUNT
#define DB2K_REG_ACQ_RESULTS_FIFO
#define DB2K_REG_ACQ_RESULTS_SHADOW
#define DB2K_REG_ACQ_ADC_RESULT
#define DB2K_REG_DAC_SCAN_COUNTER
#define DB2K_REG_DAC_CONTROL
#define DB2K_REG_DAC_STATUS
#define DB2K_REG_DAC_FIFO
#define DB2K_REG_DAC_PACER_CLOCK_DIV
#define DB2K_REG_REF_DACS
#define DB2K_REG_DIO_CONTROL
#define DB2K_REG_P3_HSIO_DATA
#define DB2K_REG_P3_CONTROL
#define DB2K_REG_CAL_EEPROM_CONTROL
#define DB2K_REG_DAC_SETTING(x)
#define DB2K_REG_DIO_P2_EXP_IO_8_BIT
#define DB2K_REG_COUNTER_TIMER_CONTROL
#define DB2K_REG_COUNTER_INPUT(x)
#define DB2K_REG_TIMER_DIV(x)
#define DB2K_REG_DMA_CONTROL
#define DB2K_REG_TRIG_CONTROL
#define DB2K_REG_CAL_EEPROM
#define DB2K_REG_ACQ_DIGITAL_MARK
#define DB2K_REG_TRIG_DACS
#define DB2K_REG_DIO_P2_EXP_IO_16_BIT(x)

/* CPLD registers */
#define DB2K_REG_CPLD_STATUS
#define DB2K_REG_CPLD_WDATA

/* Scan Sequencer programming */
#define DB2K_ACQ_CONTROL_SEQ_START_SCAN_LIST
#define DB2K_ACQ_CONTROL_SEQ_STOP_SCAN_LIST

/* Prepare for acquisition */
#define DB2K_ACQ_CONTROL_RESET_SCAN_LIST_FIFO
#define DB2K_ACQ_CONTROL_RESET_RESULTS_FIFO
#define DB2K_ACQ_CONTROL_RESET_CONFIG_PIPE

/* Pacer Clock Control */
#define DB2K_ACQ_CONTROL_ADC_PACER_INTERNAL
#define DB2K_ACQ_CONTROL_ADC_PACER_EXTERNAL
#define DB2K_ACQ_CONTROL_ADC_PACER_ENABLE
#define DB2K_ACQ_CONTROL_ADC_PACER_ENABLE_DAC_PACER
#define DB2K_ACQ_CONTROL_ADC_PACER_DISABLE
#define DB2K_ACQ_CONTROL_ADC_PACER_NORMAL_MODE
#define DB2K_ACQ_CONTROL_ADC_PACER_COMPATIBILITY_MODE
#define DB2K_ACQ_CONTROL_ADC_PACER_INTERNAL_OUT_ENABLE
#define DB2K_ACQ_CONTROL_ADC_PACER_EXTERNAL_RISING

/* Acquisition status bits */
#define DB2K_ACQ_STATUS_RESULTS_FIFO_MORE_1_SAMPLE
#define DB2K_ACQ_STATUS_RESULTS_FIFO_HAS_DATA
#define DB2K_ACQ_STATUS_RESULTS_FIFO_OVERRUN
#define DB2K_ACQ_STATUS_LOGIC_SCANNING
#define DB2K_ACQ_STATUS_CONFIG_PIPE_FULL
#define DB2K_ACQ_STATUS_SCAN_LIST_FIFO_EMPTY
#define DB2K_ACQ_STATUS_ADC_NOT_READY
#define DB2K_ACQ_STATUS_ARBITRATION_FAILURE
#define DB2K_ACQ_STATUS_ADC_PACER_OVERRUN
#define DB2K_ACQ_STATUS_DAC_PACER_OVERRUN

/* DAC status */
#define DB2K_DAC_STATUS_DAC_FULL
#define DB2K_DAC_STATUS_REF_BUSY
#define DB2K_DAC_STATUS_TRIG_BUSY
#define DB2K_DAC_STATUS_CAL_BUSY
#define DB2K_DAC_STATUS_DAC_BUSY(x)

/* DAC control */
#define DB2K_DAC_CONTROL_ENABLE_BIT
#define DB2K_DAC_CONTROL_DATA_IS_SIGNED
#define DB2K_DAC_CONTROL_RESET_FIFO
#define DB2K_DAC_CONTROL_DAC_DISABLE(x)
#define DB2K_DAC_CONTROL_DAC_ENABLE(x)
#define DB2K_DAC_CONTROL_PATTERN_DISABLE
#define DB2K_DAC_CONTROL_PATTERN_ENABLE

/* Trigger Control */
#define DB2K_TRIG_CONTROL_TYPE_ANALOG
#define DB2K_TRIG_CONTROL_TYPE_TTL
#define DB2K_TRIG_CONTROL_EDGE_HI_LO
#define DB2K_TRIG_CONTROL_EDGE_LO_HI
#define DB2K_TRIG_CONTROL_LEVEL_ABOVE
#define DB2K_TRIG_CONTROL_LEVEL_BELOW
#define DB2K_TRIG_CONTROL_SENSE_LEVEL
#define DB2K_TRIG_CONTROL_SENSE_EDGE
#define DB2K_TRIG_CONTROL_ENABLE
#define DB2K_TRIG_CONTROL_DISABLE

/* Reference Dac Selection */
#define DB2K_REF_DACS_SET
#define DB2K_REF_DACS_SELECT_POS_REF
#define DB2K_REF_DACS_SELECT_NEG_REF

/* CPLD status bits */
#define DB2K_CPLD_STATUS_INIT
#define DB2K_CPLD_STATUS_TXREADY
#define DB2K_CPLD_VERSION_MASK
/* "New CPLD" signature. */
#define DB2K_CPLD_VERSION_NEW

enum db2k_boardid {};

struct db2k_boardtype {};

static const struct db2k_boardtype db2k_boardtypes[] =;

struct db2k_private {};

static void db2k_write_acq_scan_list_entry(struct comedi_device *dev, u16 entry)
{}

static void db2k_setup_sampling(struct comedi_device *dev, int chan, int gain)
{}

static int db2k_ai_status(struct comedi_device *dev, struct comedi_subdevice *s,
			  struct comedi_insn *insn, unsigned long context)
{}

static int db2k_ai_insn_read(struct comedi_device *dev,
			     struct comedi_subdevice *s,
			     struct comedi_insn *insn, unsigned int *data)
{}

static int db2k_ao_eoc(struct comedi_device *dev, struct comedi_subdevice *s,
		       struct comedi_insn *insn, unsigned long context)
{}

static int db2k_ao_insn_write(struct comedi_device *dev,
			      struct comedi_subdevice *s,
			      struct comedi_insn *insn, unsigned int *data)
{}

static void db2k_reset_local_bus(struct comedi_device *dev)
{}

static void db2k_reload_plx(struct comedi_device *dev)
{}

static void db2k_pulse_prog_pin(struct comedi_device *dev)
{}

static int db2k_wait_cpld_init(struct comedi_device *dev)
{}

static int db2k_wait_cpld_txready(struct comedi_device *dev)
{}

static int db2k_write_cpld(struct comedi_device *dev, u16 data, bool new_cpld)
{}

static int db2k_wait_fpga_programmed(struct comedi_device *dev)
{}

static int db2k_load_firmware(struct comedi_device *dev, const u8 *cpld_array,
			      size_t len, unsigned long context)
{}

static void db2k_adc_stop_dma_transfer(struct comedi_device *dev)
{}

static void db2k_adc_disarm(struct comedi_device *dev)
{}

static void db2k_activate_reference_dacs(struct comedi_device *dev)
{}

static void db2k_initialize_ctrs(struct comedi_device *dev)
{}

static void db2k_initialize_tmrs(struct comedi_device *dev)
{}

static void db2k_dac_disarm(struct comedi_device *dev)
{}

static void db2k_initialize_adc(struct comedi_device *dev)
{}

static int db2k_8255_cb(struct comedi_device *dev, int dir, int port, int data,
			unsigned long iobase)
{}

static int db2k_auto_attach(struct comedi_device *dev, unsigned long context)
{}

static void db2k_detach(struct comedi_device *dev)
{}

static struct comedi_driver db2k_driver =;

static int db2k_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{}

static const struct pci_device_id db2k_pci_table[] =;
MODULE_DEVICE_TABLE(pci, db2k_pci_table);

static struct pci_driver db2k_pci_driver =;
module_comedi_pci_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_FIRMWARE();