#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/comedi/comedi_8255.h>
#include "mite.h"
#ifdef PCIDMA
#define IS_PCIMIO …
#else
#define IS_PCIMIO …
#endif
#define NI_TIMEOUT …
static const short ni_gainlkup[][16] = …;
static const struct comedi_lrange range_ni_E_ai = …;
static const struct comedi_lrange range_ni_E_ai_limited = …;
static const struct comedi_lrange range_ni_E_ai_limited14 = …;
static const struct comedi_lrange range_ni_E_ai_bipolar4 = …;
static const struct comedi_lrange range_ni_E_ai_611x = …;
static const struct comedi_lrange range_ni_M_ai_622x = …;
static const struct comedi_lrange range_ni_M_ai_628x = …;
static const struct comedi_lrange *const ni_range_lkup[] = …;
enum aimodes { … };
enum ni_common_subdevices { … };
#define NI_GPCT_SUBDEV(x) …
enum timebase_nanoseconds { … };
#define SERIAL_DISABLED …
#define SERIAL_600NS …
#define SERIAL_1_2US …
#define SERIAL_10US …
static const int num_adc_stages_611x = …;
#ifdef PCIDMA
static void ni_writel(struct comedi_device *dev, unsigned int data, int reg)
{
writel(data, dev->mmio + reg);
}
static void ni_writew(struct comedi_device *dev, unsigned int data, int reg)
{
writew(data, dev->mmio + reg);
}
static void ni_writeb(struct comedi_device *dev, unsigned int data, int reg)
{
writeb(data, dev->mmio + reg);
}
static unsigned int ni_readl(struct comedi_device *dev, int reg)
{
return readl(dev->mmio + reg);
}
static unsigned int ni_readw(struct comedi_device *dev, int reg)
{
return readw(dev->mmio + reg);
}
static unsigned int ni_readb(struct comedi_device *dev, int reg)
{
return readb(dev->mmio + reg);
}
#else
static void ni_writel(struct comedi_device *dev, unsigned int data, int reg)
{ … }
static void ni_writew(struct comedi_device *dev, unsigned int data, int reg)
{ … }
static void ni_writeb(struct comedi_device *dev, unsigned int data, int reg)
{ … }
static unsigned int ni_readl(struct comedi_device *dev, int reg)
{ … }
static unsigned int ni_readw(struct comedi_device *dev, int reg)
{ … }
static unsigned int ni_readb(struct comedi_device *dev, int reg)
{ … }
#endif
struct mio_regmap { … };
static const struct mio_regmap m_series_stc_write_regmap[] = …;
static void m_series_stc_write(struct comedi_device *dev,
unsigned int data, unsigned int reg)
{ … }
static const struct mio_regmap m_series_stc_read_regmap[] = …;
static unsigned int m_series_stc_read(struct comedi_device *dev,
unsigned int reg)
{ … }
static void ni_stc_writew(struct comedi_device *dev,
unsigned int data, int reg)
{ … }
static void ni_stc_writel(struct comedi_device *dev,
unsigned int data, int reg)
{ … }
static unsigned int ni_stc_readw(struct comedi_device *dev, int reg)
{ … }
static unsigned int ni_stc_readl(struct comedi_device *dev, int reg)
{ … }
static inline void ni_set_bitfield(struct comedi_device *dev, int reg,
unsigned int bit_mask,
unsigned int bit_values)
{ … }
#ifdef PCIDMA
#define NI_STC_DMA_CHAN_SEL …
static int ni_request_ai_mite_channel(struct comedi_device *dev)
{
struct ni_private *devpriv = dev->private;
struct mite_channel *mite_chan;
unsigned long flags;
unsigned int bits;
spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
mite_chan = mite_request_channel(devpriv->mite, devpriv->ai_mite_ring);
if (!mite_chan) {
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
dev_err(dev->class_dev,
"failed to reserve mite dma channel for analog input\n");
return -EBUSY;
}
mite_chan->dir = COMEDI_INPUT;
devpriv->ai_mite_chan = mite_chan;
bits = NI_STC_DMA_CHAN_SEL(mite_chan->channel);
ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG,
NI_E_DMA_AI_SEL_MASK, NI_E_DMA_AI_SEL(bits));
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
return 0;
}
static int ni_request_ao_mite_channel(struct comedi_device *dev)
{
struct ni_private *devpriv = dev->private;
struct mite_channel *mite_chan;
unsigned long flags;
unsigned int bits;
spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
mite_chan = mite_request_channel(devpriv->mite, devpriv->ao_mite_ring);
if (!mite_chan) {
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
dev_err(dev->class_dev,
"failed to reserve mite dma channel for analog output\n");
return -EBUSY;
}
mite_chan->dir = COMEDI_OUTPUT;
devpriv->ao_mite_chan = mite_chan;
bits = NI_STC_DMA_CHAN_SEL(mite_chan->channel);
ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG,
NI_E_DMA_AO_SEL_MASK, NI_E_DMA_AO_SEL(bits));
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
return 0;
}
static int ni_request_gpct_mite_channel(struct comedi_device *dev,
unsigned int gpct_index,
enum comedi_io_direction direction)
{
struct ni_private *devpriv = dev->private;
struct ni_gpct *counter = &devpriv->counter_dev->counters[gpct_index];
struct mite_channel *mite_chan;
unsigned long flags;
unsigned int bits;
spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
mite_chan = mite_request_channel(devpriv->mite,
devpriv->gpct_mite_ring[gpct_index]);
if (!mite_chan) {
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
dev_err(dev->class_dev,
"failed to reserve mite dma channel for counter\n");
return -EBUSY;
}
mite_chan->dir = direction;
ni_tio_set_mite_channel(counter, mite_chan);
bits = NI_STC_DMA_CHAN_SEL(mite_chan->channel);
ni_set_bitfield(dev, NI_E_DMA_G0_G1_SEL_REG,
NI_E_DMA_G0_G1_SEL_MASK(gpct_index),
NI_E_DMA_G0_G1_SEL(gpct_index, bits));
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
return 0;
}
static int ni_request_cdo_mite_channel(struct comedi_device *dev)
{
struct ni_private *devpriv = dev->private;
struct mite_channel *mite_chan;
unsigned long flags;
unsigned int bits;
spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
mite_chan = mite_request_channel(devpriv->mite, devpriv->cdo_mite_ring);
if (!mite_chan) {
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
dev_err(dev->class_dev,
"failed to reserve mite dma channel for correlated digital output\n");
return -EBUSY;
}
mite_chan->dir = COMEDI_OUTPUT;
devpriv->cdo_mite_chan = mite_chan;
bits = NI_STC_DMA_CHAN_SEL(mite_chan->channel);
ni_set_bitfield(dev, NI_M_CDIO_DMA_SEL_REG,
NI_M_CDIO_DMA_SEL_CDO_MASK,
NI_M_CDIO_DMA_SEL_CDO(bits));
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
return 0;
}
#endif
static void ni_release_ai_mite_channel(struct comedi_device *dev)
{ … }
static void ni_release_ao_mite_channel(struct comedi_device *dev)
{ … }
#ifdef PCIDMA
static void ni_release_gpct_mite_channel(struct comedi_device *dev,
unsigned int gpct_index)
{
struct ni_private *devpriv = dev->private;
unsigned long flags;
spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
if (devpriv->counter_dev->counters[gpct_index].mite_chan) {
struct mite_channel *mite_chan =
devpriv->counter_dev->counters[gpct_index].mite_chan;
ni_set_bitfield(dev, NI_E_DMA_G0_G1_SEL_REG,
NI_E_DMA_G0_G1_SEL_MASK(gpct_index), 0);
ni_tio_set_mite_channel(&devpriv->counter_dev->counters[gpct_index],
NULL);
mite_release_channel(mite_chan);
}
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
}
static void ni_release_cdo_mite_channel(struct comedi_device *dev)
{
struct ni_private *devpriv = dev->private;
unsigned long flags;
spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
if (devpriv->cdo_mite_chan) {
ni_set_bitfield(dev, NI_M_CDIO_DMA_SEL_REG,
NI_M_CDIO_DMA_SEL_CDO_MASK, 0);
mite_release_channel(devpriv->cdo_mite_chan);
devpriv->cdo_mite_chan = NULL;
}
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
}
static void ni_e_series_enable_second_irq(struct comedi_device *dev,
unsigned int gpct_index, short enable)
{
struct ni_private *devpriv = dev->private;
unsigned int val = 0;
int reg;
if (devpriv->is_m_series || gpct_index > 1)
return;
if (gpct_index == 0) {
reg = NISTC_INTA2_ENA_REG;
if (enable)
val = NISTC_INTA_ENA_G0_GATE;
} else {
reg = NISTC_INTB2_ENA_REG;
if (enable)
val = NISTC_INTB_ENA_G1_GATE;
}
ni_stc_writew(dev, val, reg);
}
#endif
static void ni_clear_ai_fifo(struct comedi_device *dev)
{ … }
static inline void ni_ao_win_outw(struct comedi_device *dev,
unsigned int data, int addr)
{ … }
static inline void ni_ao_win_outl(struct comedi_device *dev,
unsigned int data, int addr)
{ … }
static inline unsigned short ni_ao_win_inw(struct comedi_device *dev, int addr)
{ … }
static inline void ni_set_bits(struct comedi_device *dev, int reg,
unsigned int bits, unsigned int value)
{ … }
#ifdef PCIDMA
static void ni_sync_ai_dma(struct comedi_device *dev)
{
struct ni_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
unsigned long flags;
spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
if (devpriv->ai_mite_chan)
mite_sync_dma(devpriv->ai_mite_chan, s);
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
}
static int ni_ai_drain_dma(struct comedi_device *dev)
{
struct ni_private *devpriv = dev->private;
int i;
static const int timeout = 10000;
unsigned long flags;
int retval = 0;
spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
if (devpriv->ai_mite_chan) {
for (i = 0; i < timeout; i++) {
if ((ni_stc_readw(dev, NISTC_AI_STATUS1_REG) &
NISTC_AI_STATUS1_FIFO_E) &&
mite_bytes_in_transit(devpriv->ai_mite_chan) == 0)
break;
udelay(5);
}
if (i == timeout) {
dev_err(dev->class_dev, "timed out\n");
dev_err(dev->class_dev,
"mite_bytes_in_transit=%i, AI_Status1_Register=0x%x\n",
mite_bytes_in_transit(devpriv->ai_mite_chan),
ni_stc_readw(dev, NISTC_AI_STATUS1_REG));
retval = -1;
}
}
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
ni_sync_ai_dma(dev);
return retval;
}
static int ni_ao_wait_for_dma_load(struct comedi_device *dev)
{
static const int timeout = 10000;
int i;
for (i = 0; i < timeout; i++) {
unsigned short b_status;
b_status = ni_stc_readw(dev, NISTC_AO_STATUS1_REG);
if (b_status & NISTC_AO_STATUS1_FIFO_HF)
break;
usleep_range(10, 100);
}
if (i == timeout) {
dev_err(dev->class_dev, "timed out waiting for dma load\n");
return -EPIPE;
}
return 0;
}
#endif
#ifndef PCIDMA
static void ni_ao_fifo_load(struct comedi_device *dev,
struct comedi_subdevice *s, int n)
{ … }
static int ni_ao_fifo_half_empty(struct comedi_device *dev,
struct comedi_subdevice *s)
{ … }
static int ni_ao_prep_fifo(struct comedi_device *dev,
struct comedi_subdevice *s)
{ … }
static void ni_ai_fifo_read(struct comedi_device *dev,
struct comedi_subdevice *s, int n)
{ … }
static void ni_handle_fifo_half_full(struct comedi_device *dev)
{ … }
#endif
static void ni_handle_fifo_dregs(struct comedi_device *dev)
{ … }
static void get_last_sample_611x(struct comedi_device *dev)
{ … }
static void get_last_sample_6143(struct comedi_device *dev)
{ … }
static void shutdown_ai_command(struct comedi_device *dev)
{ … }
static void ni_handle_eos(struct comedi_device *dev, struct comedi_subdevice *s)
{ … }
static void handle_gpct_interrupt(struct comedi_device *dev,
unsigned short counter_index)
{ … }
static void ack_a_interrupt(struct comedi_device *dev, unsigned short a_status)
{ … }
static void handle_a_interrupt(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned short status)
{ … }
static void ack_b_interrupt(struct comedi_device *dev, unsigned short b_status)
{ … }
static void handle_b_interrupt(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned short b_status)
{ … }
static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
void *data, unsigned int num_bytes,
unsigned int chan_index)
{ … }
#ifdef PCIDMA
static int ni_ai_setup_MITE_dma(struct comedi_device *dev)
{
struct ni_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
int retval;
unsigned long flags;
retval = ni_request_ai_mite_channel(dev);
if (retval)
return retval;
comedi_buf_write_alloc(s, s->async->prealloc_bufsz);
spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
if (!devpriv->ai_mite_chan) {
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
return -EIO;
}
if (devpriv->is_611x || devpriv->is_6143)
mite_prep_dma(devpriv->ai_mite_chan, 32, 16);
else if (devpriv->is_628x)
mite_prep_dma(devpriv->ai_mite_chan, 32, 32);
else
mite_prep_dma(devpriv->ai_mite_chan, 16, 16);
mite_dma_arm(devpriv->ai_mite_chan);
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
return 0;
}
static int ni_ao_setup_MITE_dma(struct comedi_device *dev)
{
struct ni_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->write_subdev;
int retval;
unsigned long flags;
retval = ni_request_ao_mite_channel(dev);
if (retval)
return retval;
comedi_buf_read_alloc(s, s->async->prealloc_bufsz);
spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
if (devpriv->ao_mite_chan) {
if (devpriv->is_611x || devpriv->is_6713) {
mite_prep_dma(devpriv->ao_mite_chan, 32, 32);
} else {
mite_prep_dma(devpriv->ao_mite_chan, 16, 32);
}
mite_dma_arm(devpriv->ao_mite_chan);
} else {
retval = -EIO;
}
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
return retval;
}
#endif
static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s)
{ … }
static int ni_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
{ … }
static void ni_prime_channelgain_list(struct comedi_device *dev)
{ … }
static void ni_m_series_load_channelgain_list(struct comedi_device *dev,
unsigned int n_chan,
unsigned int *list)
{ … }
static void ni_load_channelgain_list(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned int n_chan, unsigned int *list)
{ … }
static int ni_ai_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static int ni_ns_to_timer(const struct comedi_device *dev,
unsigned int nanosec, unsigned int flags)
{ … }
static unsigned int ni_timer_to_ns(const struct comedi_device *dev, int timer)
{ … }
static void ni_cmd_set_mite_transfer(struct mite_ring *ring,
struct comedi_subdevice *sdev,
const struct comedi_cmd *cmd,
unsigned int max_count)
{ … }
static unsigned int ni_min_ai_scan_period_ns(struct comedi_device *dev,
unsigned int num_channels)
{ … }
static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{ … }
static int ni_ai_inttrig(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned int trig_num)
{ … }
static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{ … }
static int ni_ai_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{ … }
static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s,
void *data, unsigned int num_bytes,
unsigned int chan_index)
{ … }
static int ni_m_series_ao_config_chanlist(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned int chanspec[],
unsigned int n_chans, int timed)
{ … }
static int ni_old_ao_config_chanlist(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned int chanspec[],
unsigned int n_chans)
{ … }
static int ni_ao_config_chanlist(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned int chanspec[], unsigned int n_chans,
int timed)
{ … }
static int ni_ao_insn_write(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static int ni_ao_arm(struct comedi_device *dev,
struct comedi_subdevice *s)
{ … }
static int ni_ao_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{ … }
static int ni_ao_inttrig(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned int trig_num)
{ … }
static void ni_ao_cmd_personalize(struct comedi_device *dev,
const struct comedi_cmd *cmd)
{ … }
static void ni_ao_cmd_set_trigger(struct comedi_device *dev,
const struct comedi_cmd *cmd)
{ … }
static void ni_ao_cmd_set_counters(struct comedi_device *dev,
const struct comedi_cmd *cmd)
{ … }
static void ni_ao_cmd_set_update(struct comedi_device *dev,
const struct comedi_cmd *cmd)
{ … }
static void ni_ao_cmd_set_channels(struct comedi_device *dev,
struct comedi_subdevice *s)
{ … }
static void ni_ao_cmd_set_stop_conditions(struct comedi_device *dev,
const struct comedi_cmd *cmd)
{ … }
static void ni_ao_cmd_set_fifo_mode(struct comedi_device *dev)
{ … }
static void ni_ao_cmd_set_interrupts(struct comedi_device *dev,
struct comedi_subdevice *s)
{ … }
static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{ … }
static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{ … }
static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s)
{ … }
static int ni_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static int ni_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
#ifdef PCIDMA
static int ni_m_series_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
int ret;
if (data[0] == INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS) {
const struct ni_board_struct *board = dev->board_ptr;
data[1] = board->dio_speed;
data[2] = 0;
return 0;
}
ret = comedi_dio_insn_config(dev, s, insn, data, 0);
if (ret)
return ret;
ni_writel(dev, s->io_bits, NI_M_DIO_DIR_REG);
return insn->n;
}
static int ni_m_series_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
if (comedi_dio_update_state(s, data))
ni_writel(dev, s->state, NI_M_DIO_REG);
data[1] = ni_readl(dev, NI_M_DIO_REG);
return insn->n;
}
static int ni_cdio_check_chanlist(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{
int i;
for (i = 0; i < cmd->chanlist_len; ++i) {
unsigned int chan = CR_CHAN(cmd->chanlist[i]);
if (chan != i)
return -EINVAL;
}
return 0;
}
static int ni_cdio_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_cmd *cmd)
{
struct ni_private *devpriv = dev->private;
unsigned int bytes_per_scan;
int err = 0;
err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT);
err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW);
err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE);
if (err)
return 1;
err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
err |= ni_check_trigger_arg(CR_CHAN(cmd->scan_begin_arg),
NI_DO_SampleClock,
&devpriv->routing_tables);
if (CR_RANGE(cmd->scan_begin_arg) != 0 ||
CR_AREF(cmd->scan_begin_arg) != 0)
err |= -EINVAL;
err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
cmd->chanlist_len);
bytes_per_scan = comedi_bytes_per_scan_cmd(s, cmd);
if (bytes_per_scan) {
err |= comedi_check_trigger_arg_max(&cmd->stop_arg,
s->async->prealloc_bufsz /
bytes_per_scan);
}
if (err)
return 3;
if (cmd->chanlist && cmd->chanlist_len > 0)
err |= ni_cdio_check_chanlist(dev, s, cmd);
if (err)
return 5;
return 0;
}
static int ni_cdo_inttrig(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned int trig_num)
{
struct comedi_cmd *cmd = &s->async->cmd;
const unsigned int timeout = 1000;
int retval = 0;
unsigned int i;
struct ni_private *devpriv = dev->private;
unsigned long flags;
if (trig_num != cmd->start_arg)
return -EINVAL;
s->async->inttrig = NULL;
comedi_buf_read_alloc(s, s->async->prealloc_bufsz);
spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
if (devpriv->cdo_mite_chan) {
mite_prep_dma(devpriv->cdo_mite_chan, 32, 32);
mite_dma_arm(devpriv->cdo_mite_chan);
} else {
dev_err(dev->class_dev, "BUG: no cdo mite channel?\n");
retval = -EIO;
}
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
if (retval < 0)
return retval;
for (i = 0; i < timeout; ++i) {
if (ni_readl(dev, NI_M_CDIO_STATUS_REG) &
NI_M_CDIO_STATUS_CDO_FIFO_FULL)
break;
usleep_range(10, 100);
}
if (i == timeout) {
dev_err(dev->class_dev, "dma failed to fill cdo fifo!\n");
s->cancel(dev, s);
return -EIO;
}
ni_writel(dev, NI_M_CDO_CMD_ARM |
NI_M_CDO_CMD_ERR_INT_ENA_SET |
NI_M_CDO_CMD_F_E_INT_ENA_SET,
NI_M_CDIO_CMD_REG);
return retval;
}
static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
struct ni_private *devpriv = dev->private;
const struct comedi_cmd *cmd = &s->async->cmd;
unsigned int cdo_mode_bits;
int retval;
ni_writel(dev, NI_M_CDO_CMD_RESET, NI_M_CDIO_CMD_REG);
cdo_mode_bits = NI_M_CDO_MODE_FIFO_MODE |
NI_M_CDO_MODE_HALT_ON_ERROR |
NI_M_CDO_MODE_SAMPLE_SRC(
ni_get_reg_value(
CR_CHAN(cmd->scan_begin_arg),
NI_DO_SampleClock,
&devpriv->routing_tables));
if (cmd->scan_begin_arg & CR_INVERT)
cdo_mode_bits |= NI_M_CDO_MODE_POLARITY;
ni_writel(dev, cdo_mode_bits, NI_M_CDO_MODE_REG);
if (s->io_bits) {
ni_writel(dev, s->state, NI_M_CDO_FIFO_DATA_REG);
ni_writel(dev, NI_M_CDO_CMD_SW_UPDATE, NI_M_CDIO_CMD_REG);
ni_writel(dev, s->io_bits, NI_M_CDO_MASK_ENA_REG);
} else {
dev_err(dev->class_dev,
"attempted to run digital output command with no lines configured as outputs\n");
return -EIO;
}
retval = ni_request_cdo_mite_channel(dev);
if (retval < 0)
return retval;
ni_cmd_set_mite_transfer(devpriv->cdo_mite_ring, s, cmd,
s->async->prealloc_bufsz /
comedi_bytes_per_scan(s));
s->async->inttrig = ni_cdo_inttrig;
return 0;
}
static int ni_cdio_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
{
ni_writel(dev, NI_M_CDO_CMD_DISARM |
NI_M_CDO_CMD_ERR_INT_ENA_CLR |
NI_M_CDO_CMD_F_E_INT_ENA_CLR |
NI_M_CDO_CMD_F_REQ_INT_ENA_CLR,
NI_M_CDIO_CMD_REG);
ni_writel(dev, 0, NI_M_CDO_MASK_ENA_REG);
ni_release_cdo_mite_channel(dev);
return 0;
}
static void handle_cdio_interrupt(struct comedi_device *dev)
{
struct ni_private *devpriv = dev->private;
unsigned int cdio_status;
struct comedi_subdevice *s = &dev->subdevices[NI_DIO_SUBDEV];
unsigned long flags;
spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
if (devpriv->cdo_mite_chan)
mite_ack_linkc(devpriv->cdo_mite_chan, s, true);
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
cdio_status = ni_readl(dev, NI_M_CDIO_STATUS_REG);
if (cdio_status & NI_M_CDIO_STATUS_CDO_ERROR) {
ni_writel(dev, NI_M_CDO_CMD_ERR_INT_CONFIRM,
NI_M_CDIO_CMD_REG);
s->async->events |= COMEDI_CB_OVERFLOW;
}
if (cdio_status & NI_M_CDIO_STATUS_CDO_FIFO_EMPTY) {
ni_writel(dev, NI_M_CDO_CMD_F_E_INT_ENA_CLR,
NI_M_CDIO_CMD_REG);
}
comedi_handle_events(dev, s);
}
#endif
static int ni_serial_hw_readwrite8(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned char data_out,
unsigned char *data_in)
{ … }
static int ni_serial_sw_readwrite8(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned char data_out,
unsigned char *data_in)
{ … }
static int ni_serial_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static void init_ao_67xx(struct comedi_device *dev, struct comedi_subdevice *s)
{ … }
static const struct mio_regmap ni_gpct_to_stc_regmap[] = …;
static unsigned int ni_gpct_to_stc_register(struct comedi_device *dev,
enum ni_gpct_register reg)
{ … }
static void ni_gpct_write_register(struct ni_gpct *counter, unsigned int bits,
enum ni_gpct_register reg)
{ … }
static unsigned int ni_gpct_read_register(struct ni_gpct *counter,
enum ni_gpct_register reg)
{ … }
static int ni_freq_out_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static int ni_freq_out_insn_write(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static int ni_freq_out_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static int ni_8255_callback(struct comedi_device *dev,
int dir, int port, int data, unsigned long iobase)
{ … }
static int ni_get_pwm_config(struct comedi_device *dev, unsigned int *data)
{ … }
static int ni_m_series_pwm_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static int ni_6143_pwm_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static int pack_mb88341(int addr, int val, int *bitstring)
{ … }
static int pack_dac8800(int addr, int val, int *bitstring)
{ … }
static int pack_dac8043(int addr, int val, int *bitstring)
{ … }
static int pack_ad8522(int addr, int val, int *bitstring)
{ … }
static int pack_ad8804(int addr, int val, int *bitstring)
{ … }
static int pack_ad8842(int addr, int val, int *bitstring)
{ … }
struct caldac_struct { … };
static struct caldac_struct caldacs[] = …;
static void ni_write_caldac(struct comedi_device *dev, int addr, int val)
{ … }
static int ni_calib_insn_write(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static int ni_calib_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s)
{ … }
static int ni_read_eeprom(struct comedi_device *dev, int addr)
{ … }
static int ni_eeprom_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static int ni_m_series_eeprom_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static unsigned int ni_old_get_pfi_routing(struct comedi_device *dev,
unsigned int chan)
{ … }
static int ni_old_set_pfi_routing(struct comedi_device *dev,
unsigned int chan, unsigned int source)
{ … }
static unsigned int ni_m_series_get_pfi_routing(struct comedi_device *dev,
unsigned int chan)
{ … }
static int ni_m_series_set_pfi_routing(struct comedi_device *dev,
unsigned int chan, unsigned int source)
{ … }
static unsigned int ni_get_pfi_routing(struct comedi_device *dev,
unsigned int chan)
{ … }
static int ni_set_pfi_routing(struct comedi_device *dev,
unsigned int chan, unsigned int source)
{ … }
static int ni_config_pfi_filter(struct comedi_device *dev,
unsigned int chan,
enum ni_pfi_filter_select filter)
{ … }
static void ni_set_pfi_direction(struct comedi_device *dev, int chan,
unsigned int direction)
{ … }
static int ni_get_pfi_direction(struct comedi_device *dev, int chan)
{ … }
static int ni_pfi_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static int ni_pfi_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static int cs5529_wait_for_idle(struct comedi_device *dev)
{ … }
static void cs5529_command(struct comedi_device *dev, unsigned short value)
{ … }
static int cs5529_do_conversion(struct comedi_device *dev,
unsigned short *data)
{ … }
static int cs5529_ai_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static void cs5529_config_write(struct comedi_device *dev, unsigned int value,
unsigned int reg_select_bits)
{ … }
static int init_cs5529(struct comedi_device *dev)
{ … }
static int ni_mseries_get_pll_parameters(unsigned int reference_period_ns,
unsigned int *freq_divider,
unsigned int *freq_multiplier,
unsigned int *actual_period_ns)
{ … }
static int ni_mseries_set_pll_master_clock(struct comedi_device *dev,
unsigned int source,
unsigned int period_ns)
{ … }
static int ni_set_master_clock(struct comedi_device *dev,
unsigned int source, unsigned int period_ns)
{ … }
static int ni_valid_rtsi_output_source(struct comedi_device *dev,
unsigned int chan, unsigned int source)
{ … }
static int ni_set_rtsi_routing(struct comedi_device *dev,
unsigned int chan, unsigned int src)
{ … }
static unsigned int ni_get_rtsi_routing(struct comedi_device *dev,
unsigned int chan)
{ … }
static void ni_set_rtsi_direction(struct comedi_device *dev, int chan,
unsigned int direction)
{ … }
static int ni_get_rtsi_direction(struct comedi_device *dev, int chan)
{ … }
static int ni_rtsi_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static int ni_rtsi_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static const int default_rtsi_routing[] = …;
static void set_rgout0_reg(int reg, struct comedi_device *dev)
{ … }
static int get_rgout0_reg(struct comedi_device *dev)
{ … }
static inline int get_rgout0_src(struct comedi_device *dev)
{ … }
static int incr_rgout0_src_use(int src, struct comedi_device *dev)
{ … }
static int decr_rgout0_src_use(int src, struct comedi_device *dev)
{ … }
static void set_ith_rtsi_brd_reg(int i, int reg, struct comedi_device *dev)
{ … }
static int get_ith_rtsi_brd_reg(int i, struct comedi_device *dev)
{ … }
static inline int get_rtsi_brd_src(int brd, struct comedi_device *dev)
{ … }
static int incr_rtsi_brd_src_use(int src, struct comedi_device *dev)
{ … }
static int decr_rtsi_brd_src_use(int src, int rtsi_brd,
struct comedi_device *dev)
{ … }
static void ni_rtsi_init(struct comedi_device *dev)
{ … }
static inline int ni_get_gout_routing(unsigned int dest,
struct comedi_device *dev)
{ … }
static inline int ni_disable_gout_routing(unsigned int dest,
struct comedi_device *dev)
{ … }
static inline int ni_set_gout_routing(unsigned int src, unsigned int dest,
struct comedi_device *dev)
{ … }
static int get_output_select_source(int dest, struct comedi_device *dev)
{ … }
static int test_route(unsigned int src, unsigned int dest,
struct comedi_device *dev)
{ … }
static int connect_route(unsigned int src, unsigned int dest,
struct comedi_device *dev)
{ … }
static int disconnect_route(unsigned int src, unsigned int dest,
struct comedi_device *dev)
{ … }
static int ni_global_insn_config(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{ … }
#ifdef PCIDMA
static int ni_gpct_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
struct ni_gpct *counter = s->private;
int retval;
retval = ni_request_gpct_mite_channel(dev, counter->counter_index,
COMEDI_INPUT);
if (retval) {
dev_err(dev->class_dev,
"no dma channel available for use by counter\n");
return retval;
}
ni_tio_acknowledge(counter);
ni_e_series_enable_second_irq(dev, counter->counter_index, 1);
return ni_tio_cmd(dev, s);
}
static int ni_gpct_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
{
struct ni_gpct *counter = s->private;
int retval;
retval = ni_tio_cancel(counter);
ni_e_series_enable_second_irq(dev, counter->counter_index, 0);
ni_release_gpct_mite_channel(dev, counter->counter_index);
return retval;
}
#endif
static irqreturn_t ni_E_interrupt(int irq, void *d)
{ … }
static int ni_alloc_private(struct comedi_device *dev)
{ … }
static unsigned int _ni_get_valid_routes(struct comedi_device *dev,
unsigned int n_pairs,
unsigned int *pair_data)
{ … }
static int ni_E_init(struct comedi_device *dev,
unsigned int interrupt_pin, unsigned int irq_polarity)
{ … }
static void mio_common_detach(struct comedi_device *dev)
{ … }