#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 TIMER_BASE …
#define PRESCALED_TIMER_BASE …
#define DMA_BUFFER_SIZE …
#define DAC_FIFO_SIZE …
static const int max_counter_value = …;
enum write_only_registers { … };
static inline unsigned int dac_convert_reg(unsigned int channel)
{ … }
static inline unsigned int dac_lsb_4020_reg(unsigned int channel)
{ … }
static inline unsigned int dac_msb_4020_reg(unsigned int channel)
{ … }
enum read_only_registers { … };
enum read_write_registers { … };
enum dio_counter_registers { … };
enum intr_enable_contents { … };
enum hw_config_contents { … };
enum daq_atrig_low_4020_contents { … };
enum adc_control0_contents { … };
enum adc_control1_contents { … };
static inline u16 adc_lo_chan_4020_bits(unsigned int channel)
{
return (channel & 0x3) << 8;
};
static inline u16 adc_hi_chan_4020_bits(unsigned int channel)
{
return (channel & 0x3) << 10;
};
static inline u16 adc_mode_bits(unsigned int mode)
{
return (mode & 0xf) << 12;
};
enum calibration_contents { … };
static inline u16 adc_src_bits(unsigned int source)
{
return (source & 0xf) << 3;
};
static inline u16 adc_convert_chan_4020_bits(unsigned int channel)
{
return (channel & 0x3) << 8;
};
enum adc_queue_load_contents { … };
static inline u16 adc_chan_bits(unsigned int channel)
{
return channel & 0x3f;
};
enum dac_control0_contents { … };
enum dac_control1_contents { … };
enum hw_status_contents { … };
static inline u16 pipe_full_bits(u16 hw_status_bits)
{
return (hw_status_bits >> 10) & 0x3;
};
static inline unsigned int adc_upper_read_ptr_code(u16 prepost_bits)
{ … }
static inline unsigned int adc_upper_write_ptr_code(u16 prepost_bits)
{ … }
enum i2c_addresses { … };
enum range_cal_i2c_contents { … };
static inline u8 adc_src_4020_bits(unsigned int source)
{
return (source << 4) & ADC_SRC_4020_MASK;
};
static inline u8 attenuate_bit(unsigned int channel)
{
return 1 << (channel & 0x3);
};
static const struct comedi_lrange ai_ranges_64xx = …;
static const u8 ai_range_code_64xx[8] = …;
static const struct comedi_lrange ai_ranges_64_mx = …;
static const u8 ai_range_code_64_mx[7] = …;
static const struct comedi_lrange ai_ranges_60xx = …;
static const u8 ai_range_code_60xx[4] = …;
static const struct comedi_lrange ai_ranges_6030 = …;
static const u8 ai_range_code_6030[14] = …;
static const struct comedi_lrange ai_ranges_6052 = …;
static const u8 ai_range_code_6052[15] = …;
static const struct comedi_lrange ai_ranges_4020 = …;
static const struct comedi_lrange ao_ranges_64xx = …;
static const int ao_range_code_64xx[] = …;
static const int ao_range_code_60xx[] = …;
static const struct comedi_lrange ao_ranges_6030 = …;
static const int ao_range_code_6030[] = …;
static const struct comedi_lrange ao_ranges_4020 = …;
static const int ao_range_code_4020[] = …;
enum register_layout { … };
struct hw_fifo_info { … };
enum pcidas64_boardid { … };
struct pcidas64_board { … };
static const struct hw_fifo_info ai_fifo_4020 = …;
static const struct hw_fifo_info ai_fifo_64xx = …;
static const struct hw_fifo_info ai_fifo_60xx = …;
#define MAX_AI_DMA_RING_COUNT …
#define MIN_AI_DMA_RING_COUNT …
#define AO_DMA_RING_COUNT …
static inline unsigned int ai_dma_ring_count(const struct pcidas64_board *board)
{ … }
static const int bytes_in_sample = …;
static const struct pcidas64_board pcidas64_boards[] = …;
static inline unsigned short se_diff_bit_6xxx(struct comedi_device *dev,
int use_differential)
{ … }
struct ext_clock_info { … };
struct pcidas64_private { … };
static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev,
unsigned int range_index)
{ … }
static unsigned int hw_revision(const struct comedi_device *dev,
u16 hw_status_bits)
{ … }
static void set_dac_range_bits(struct comedi_device *dev,
u16 *bits, unsigned int channel,
unsigned int range)
{
const struct pcidas64_board *board = dev->board_ptr;
unsigned int code = board->ao_range_code[range];
if (channel > 1)
dev_err(dev->class_dev, "bug! bad channel?\n");
if (code & ~0x3)
dev_err(dev->class_dev, "bug! bad range code?\n");
*bits &= ~(0x3 << (2 * channel));
*bits |= code << (2 * channel);
};
static inline int ao_cmd_is_supported(const struct pcidas64_board *board)
{ … }
static void abort_dma(struct comedi_device *dev, unsigned int channel)
{ … }
static void disable_plx_interrupts(struct comedi_device *dev)
{ … }
static void disable_ai_interrupts(struct comedi_device *dev)
{ … }
static void enable_ai_interrupts(struct comedi_device *dev,
const struct comedi_cmd *cmd)
{ … }
static void init_plx9080(struct comedi_device *dev)
{ … }
static void disable_ai_pacing(struct comedi_device *dev)
{ … }
static int set_ai_fifo_segment_length(struct comedi_device *dev,
unsigned int num_entries)
{ … }
static int set_ai_fifo_size(struct comedi_device *dev, unsigned int num_samples)
{ … }
static unsigned int ai_fifo_size(struct comedi_device *dev)
{ … }
static void init_stc_registers(struct comedi_device *dev)
{
const struct pcidas64_board *board = dev->board_ptr;
struct pcidas64_private *devpriv = dev->private;
u16 bits;
unsigned long flags;
spin_lock_irqsave(&dev->spinlock, flags);
if (1)
devpriv->adc_control1_bits |= ADC_QUEUE_CONFIG_BIT;
writew(devpriv->adc_control1_bits,
devpriv->main_iobase + ADC_CONTROL1_REG);
writew(0xff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG);
bits = SLOW_DAC_BIT | DMA_CH_SELECT_BIT;
if (board->layout == LAYOUT_4020)
bits |= INTERNAL_CLOCK_4020_BITS;
devpriv->hw_config_bits |= bits;
writew(devpriv->hw_config_bits,
devpriv->main_iobase + HW_CONFIG_REG);
writew(0, devpriv->main_iobase + DAQ_SYNC_REG);
writew(0, devpriv->main_iobase + CALIBRATION_REG);
spin_unlock_irqrestore(&dev->spinlock, flags);
devpriv->fifo_size_bits |= DAC_FIFO_BITS;
set_ai_fifo_segment_length(dev, board->ai_fifo->max_segment_length);
devpriv->dac_control1_bits = DAC_OUTPUT_ENABLE_BIT;
devpriv->intr_enable_bits =
EN_DAC_DONE_INTR_BIT | EN_DAC_UNDERRUN_BIT;
writew(devpriv->intr_enable_bits,
devpriv->main_iobase + INTR_ENABLE_REG);
disable_ai_pacing(dev);
};
static int alloc_and_init_dma_members(struct comedi_device *dev)
{ … }
static void cb_pcidas64_free_dma(struct comedi_device *dev)
{ … }
static inline void warn_external_queue(struct comedi_device *dev)
{ … }
static const int i2c_high_udelay = …;
static const int i2c_low_udelay = …;
static void i2c_set_sda(struct comedi_device *dev, int state)
{ … }
static void i2c_set_scl(struct comedi_device *dev, int state)
{ … }
static void i2c_write_byte(struct comedi_device *dev, u8 byte)
{ … }
static int i2c_read_ack(struct comedi_device *dev)
{ … }
static void i2c_start(struct comedi_device *dev)
{ … }
static void i2c_stop(struct comedi_device *dev)
{ … }
static void i2c_write(struct comedi_device *dev, unsigned int address,
const u8 *data, unsigned int length)
{ … }
static int cb_pcidas64_ai_eoc(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned long context)
{ … }
static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{ … }
static int ai_config_calibration_source(struct comedi_device *dev,
unsigned int *data)
{ … }
static int ai_config_block_size(struct comedi_device *dev, unsigned int *data)
{ … }
static int ai_config_master_clock_4020(struct comedi_device *dev,
unsigned int *data)
{ … }
static int ai_config_master_clock(struct comedi_device *dev, unsigned int *data)
{ … }
static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{ … }
static unsigned int get_divisor(unsigned int ns, unsigned int flags)
{ … }
static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd)
{ … }
static int cb_pcidas64_ai_check_chanlist(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{ … }
static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{ … }
static int use_hw_sample_counter(struct comedi_cmd *cmd)
{ … }
static void setup_sample_counters(struct comedi_device *dev,
struct comedi_cmd *cmd)
{ … }
static inline unsigned int dma_transfer_size(struct comedi_device *dev)
{ … }
static u32 ai_convert_counter_6xxx(const struct comedi_device *dev,
const struct comedi_cmd *cmd)
{ … }
static u32 ai_scan_counter_6xxx(struct comedi_device *dev,
struct comedi_cmd *cmd)
{ … }
static u32 ai_convert_counter_4020(struct comedi_device *dev,
struct comedi_cmd *cmd)
{ … }
static void select_master_clock_4020(struct comedi_device *dev,
const struct comedi_cmd *cmd)
{ … }
static void select_master_clock(struct comedi_device *dev,
const struct comedi_cmd *cmd)
{ … }
static inline void dma_start_sync(struct comedi_device *dev,
unsigned int channel)
{ … }
static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd)
{ … }
static int use_internal_queue_6xxx(const struct comedi_cmd *cmd)
{ … }
static int setup_channel_queue(struct comedi_device *dev,
const struct comedi_cmd *cmd)
{ … }
static inline void load_first_dma_descriptor(struct comedi_device *dev,
unsigned int dma_channel,
unsigned int descriptor_bits)
{ … }
static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{ … }
static void pio_drain_ai_fifo_16(struct comedi_device *dev)
{ … }
static void pio_drain_ai_fifo_32(struct comedi_device *dev)
{ … }
static void pio_drain_ai_fifo(struct comedi_device *dev)
{ … }
static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel)
{ … }
static void handle_ai_interrupt(struct comedi_device *dev,
unsigned short status,
unsigned int plx_status)
{ … }
static inline unsigned int prev_ao_dma_index(struct comedi_device *dev)
{ … }
static int last_ao_dma_load_completed(struct comedi_device *dev)
{ … }
static inline int ao_dma_needs_restart(struct comedi_device *dev,
unsigned short dma_status)
{ … }
static void restart_ao_dma(struct comedi_device *dev)
{ … }
static unsigned int cb_pcidas64_ao_fill_buffer(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned short *dest,
unsigned int max_bytes)
{ … }
static unsigned int load_ao_dma_buffer(struct comedi_device *dev,
const struct comedi_cmd *cmd)
{ … }
static void load_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
{ … }
static void handle_ao_interrupt(struct comedi_device *dev,
unsigned short status, unsigned int plx_status)
{ … }
static irqreturn_t handle_interrupt(int irq, void *d)
{ … }
static int ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
{ … }
static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{ … }
static void set_dac_control0_reg(struct comedi_device *dev,
const struct comedi_cmd *cmd)
{ … }
static void set_dac_control1_reg(struct comedi_device *dev,
const struct comedi_cmd *cmd)
{ … }
static void set_dac_select_reg(struct comedi_device *dev,
const struct comedi_cmd *cmd)
{ … }
static unsigned int get_ao_divisor(unsigned int ns, unsigned int flags)
{ … }
static void set_dac_interval_regs(struct comedi_device *dev,
const struct comedi_cmd *cmd)
{ … }
static int prep_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
{ … }
static inline int external_ai_queue_in_use(struct comedi_device *dev)
{ … }
static int ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
unsigned int trig_num)
{ … }
static int ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{ … }
static int cb_pcidas64_ao_check_chanlist(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{ … }
static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{ … }
static int ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
{ … }
static int dio_callback_4020(struct comedi_device *dev,
int dir, int port, int data, unsigned long iobase)
{ … }
static int di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{ … }
static int do_wbits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static int dio_60xx_config_insn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static int dio_60xx_wbits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static int caldac_8800_write(struct comedi_device *dev, unsigned int address,
u8 value)
{ … }
static int caldac_i2c_write(struct comedi_device *dev,
unsigned int caldac_channel, unsigned int value)
{ … }
static void caldac_write(struct comedi_device *dev, unsigned int channel,
unsigned int value)
{ … }
static int cb_pcidas64_calib_insn_write(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static void ad8402_write(struct comedi_device *dev, unsigned int channel,
unsigned int value)
{ … }
static int cb_pcidas64_ad8402_insn_write(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static u16 read_eeprom(struct comedi_device *dev, u8 address)
{ … }
static int eeprom_read_insn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{ … }
static int setup_subdevices(struct comedi_device *dev)
{ … }
static int auto_attach(struct comedi_device *dev,
unsigned long context)
{ … }
static void detach(struct comedi_device *dev)
{ … }
static struct comedi_driver cb_pcidas64_driver = …;
static int cb_pcidas64_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{ … }
static const struct pci_device_id cb_pcidas64_pci_table[] = …;
MODULE_DEVICE_TABLE(pci, cb_pcidas64_pci_table);
static struct pci_driver cb_pcidas64_pci_driver = …;
module_comedi_pci_driver(…);
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;