linux/drivers/comedi/drivers/ni_mio_common.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * Hardware driver for DAQ-STC based boards
 *
 * COMEDI - Linux Control and Measurement Device Interface
 * Copyright (C) 1997-2001 David A. Schleef <[email protected]>
 * Copyright (C) 2002-2006 Frank Mori Hess <[email protected]>
 */

/*
 * This file is meant to be included by another file, e.g.,
 * ni_atmio.c or ni_pcimio.c.
 *
 * Interrupt support originally added by Truxton Fulton <[email protected]>
 *
 * References (ftp://ftp.natinst.com/support/manuals):
 *   340747b.pdf  AT-MIO E series Register Level Programmer Manual
 *   341079b.pdf  PCI E Series RLPM
 *   340934b.pdf  DAQ-STC reference manual
 *
 * 67xx and 611x registers (ftp://ftp.ni.com/support/daq/mhddk/documentation/)
 *   release_ni611x.pdf
 *   release_ni67xx.pdf
 *
 * Other possibly relevant info:
 *   320517c.pdf  User manual (obsolete)
 *   320517f.pdf  User manual (new)
 *   320889a.pdf  delete
 *   320906c.pdf  maximum signal ratings
 *   321066a.pdf  about 16x
 *   321791a.pdf  discontinuation of at-mio-16e-10 rev. c
 *   321808a.pdf  about at-mio-16e-10 rev P
 *   321837a.pdf  discontinuation of at-mio-16de-10 rev d
 *   321838a.pdf  about at-mio-16de-10 rev N
 *
 * ISSUES:
 *   - the interrupt routine needs to be cleaned up
 *
 * 2006-02-07: S-Series PCI-6143: Support has been added but is not
 * fully tested as yet. Terry Barnaby, BEAM Ltd.
 */

#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

/* A timeout count */
#define NI_TIMEOUT

/* Note: this table must match the ai_gain_* definitions */
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 range_ni_E_ao_ext =;

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 /* PCIDMA */

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 /* PCIDMA */

/*
 * We automatically take advantage of STC registers that can be
 * read/written directly in the I/O space of the board.
 *
 * The AT-MIO and DAQCard devices map the low 8 STC registers to
 * iobase+reg*2.
 *
 * Most PCIMIO devices also map the low 8 STC registers but the
 * 611x devices map the read registers to iobase+(addr-1)*2.
 * For now non-windowed STC access is disabled if a PCIMIO device
 * is detected (devpriv->mite has been initialized).
 *
 * The M series devices do not used windowed registers for the
 * STC registers. The functions below handle the mapping of the
 * windowed STC registers to the m series register offsets.
 */

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

/* selects the MITE channel to use for DMA */
#define NI_STC_DMA_CHAN_SEL

/* DMA channel setup */
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;

	/*
	 * XXX just guessing NI_STC_DMA_CHAN_SEL()
	 * returns the right bits, under the assumption the cdio dma
	 * selection works just like ai/ao/gpct.
	 * Definitely works for dma channels 0 and 1.
	 */
	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 /*  PCIDMA */

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;

	/*
	 * e-series boards use the second irq signals to generate
	 * dma requests for their counters
	 */
	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 /*  PCIDMA */

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)
{}

/*
 * ni_set_bits( ) allows different parts of the ni_mio_common driver to
 * share registers (such as Interrupt_A_Register) without interfering with
 * each other.
 *
 * NOTE: the switch/case statements are optimized out for a constant argument
 * so this is actually quite fast---  If you must wrap another function around
 * this make it inline to avoid a large speed penalty.
 *
 * value should only be 1 or 0.
 */
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;
		/*
		 * If we poll too often, the pci bus activity seems
		 * to slow the dma transfer down.
		 */
		usleep_range(10, 100);
	}
	if (i == timeout) {
		dev_err(dev->class_dev, "timed out waiting for dma load\n");
		return -EPIPE;
	}
	return 0;
}
#endif /* PCIDMA */

#ifndef PCIDMA

static void ni_ao_fifo_load(struct comedi_device *dev,
			    struct comedi_subdevice *s, int n)
{}

/*
 *  There's a small problem if the FIFO gets really low and we
 *  don't have the data to fill it.  Basically, if after we fill
 *  the FIFO with all the data available, the FIFO is _still_
 *  less than half full, we never clear the interrupt.  If the
 *  IRQ is in edge mode, we never get another interrupt, because
 *  this one wasn't cleared.  If in level mode, we get flooded
 *  with interrupts that we can't fulfill, because nothing ever
 *  gets put into the buffer.
 *
 *  This kind of situation is recoverable, but it is easier to
 *  just pretend we had a FIFO underrun, since there is a good
 *  chance it will happen anyway.  This is _not_ the case for
 *  RT code, as RT code might purposely be running close to the
 *  metal.  Needs to be fixed eventually.
 */
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

/* Empties the AI fifo */
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;

	/* write alloc the entire buffer */
	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);

	/*start the MITE */
	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;

	/* read alloc the entire buffer */
	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 {
			/*
			 * Doing 32 instead of 16 bit wide transfers from
			 * memory makes the mite do 32 bit pci transfers,
			 * doubling pci bandwidth.
			 */
			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 /*  PCIDMA */

/*
 * used for both cancel ioctl and board initialization
 *
 * this is pretty harsh for a cancel, but it works...
 */
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)
{}

/*
 * Notes on the 6110 and 6111:
 * These boards a slightly different than the rest of the series, since
 * they have multiple A/D converters.
 * From the driver side, the configuration memory is a
 * little different.
 * Configuration Memory Low:
 *   bits 15-9: same
 *   bit 8: unipolar/bipolar (should be 0 for bipolar)
 *   bits 0-3: gain.  This is 4 bits instead of 3 for the other boards
 *       1001 gain=0.1 (+/- 50)
 *       1010 0.2
 *       1011 0.1
 *       0001 1
 *       0010 2
 *       0011 5
 *       0100 10
 *       0101 20
 *       0110 50
 * Configuration Memory High:
 *   bits 12-14: Channel Type
 *       001 for differential
 *       000 for calibration
 *   bit 11: coupling  (this is not currently handled)
 *       1 AC coupling
 *       0 DC coupling
 *   bits 0-2: channel
 *       valid channels are 0-3
 */
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)
{}

/*
 * Arms the AO device in preparation for a trigger event.
 * This function also allocates and prepares a DMA channel (or FIFO if DMA is
 * not used).  As a part of this preparation, this function preloads the DAC
 * registers with the first values of the output stream.  This ensures that the
 * first clock cycle after the trigger can be used for output.
 *
 * Note that this function _must_ happen after a user has written data to the
 * output buffers via either mmap or write(fileno,...).
 */
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)
{}

/*
 * begin ni_ao_cmd.
 * Organized similar to NI-STC and MHDDK examples.
 * ni_ao_cmd is broken out into configuration sub-routines for clarity.
 */

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)
{}

/* end ni_ao_cmd */

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)
{}

/* digital io */

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;

		/* we don't care about actual channels */
		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;

	/* Step 1 : check if triggers are trivially valid */

	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;

	/* Step 2a : make sure trigger sources are unique */
	/* Step 2b : and mutually compatible */

	/* Step 3: check if arguments are trivially valid */

	err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);

	/*
	 * Although NI_D[IO]_SampleClock are the same, perhaps we should still,
	 * for completeness, test whether the cmd is output or input?
	 */
	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;

	/* Step 4: fix up any arguments */

	/* Step 5: check channel list if it exists */

	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;

	/* read alloc the entire buffer */
	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;

	/*
	 * XXX not sure what interrupt C group does
	 * wait for dma to fill output fifo
	 * ni_writeb(dev, NI_M_INTC_ENA, NI_M_INTC_ENA_REG);
	 */
	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);
	/*
	 * Although NI_D[IO]_SampleClock are the same, perhaps we should still,
	 * for completeness, test whether the cmd is output or input(?)
	 */
	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);
	/*
	 * XXX not sure what interrupt C group does
	 * ni_writeb(dev, 0, NI_M_INTC_ENA_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) {
		/* XXX just guessing this is needed and does something useful */
		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);
		/* s->async->events |= COMEDI_CB_EOA; */
	}
	comedi_handle_events(dev, s);
}
#endif /*  PCIDMA */

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)
{}

/* Sets the output mux for the specified PFI channel. */
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)
{}

/*
 * Find best multiplier/divider to try and get the PLL running at 80 MHz
 * given an arbitrary frequency input clock.
 */
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)
{}

/*
 * Default routing for RTSI trigger lines.
 *
 * These values are used here in the init function, as well as in the
 * disconnect_route function, after a RTSI route has been disconnected.
 */
static const int default_rtsi_routing[] =;

/*
 * Route signals through RGOUT0 terminal.
 * @reg: raw register value of RGOUT0 bits (only bit0 is important).
 * @dev: comedi device handle.
 */
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)
{}

/*
 * Route signals through RGOUT0 terminal and increment the RGOUT0 use for this
 * particular route.
 * @src: device-global signal name
 * @dev: comedi device handle
 *
 * Return: -EINVAL if the source is not valid to route to RGOUT0;
 *	   -EBUSY if the RGOUT0 is already used;
 *	   0 if successful.
 */
static int incr_rgout0_src_use(int src, struct comedi_device *dev)
{}

/*
 * Unroute signals through RGOUT0 terminal and deccrement the RGOUT0 use for
 * this particular source.  This function does not actually unroute anything
 * with respect to RGOUT0.  It does, on the other hand, decrement the usage
 * counter for the current src->RGOUT0 mapping.
 *
 * Return: -EINVAL if the source is not already routed to RGOUT0 (or usage is
 *	already at zero); 0 if successful.
 */
static int decr_rgout0_src_use(int src, struct comedi_device *dev)
{}

/*
 * Route signals through given NI_RTSI_BRD mux.
 * @i: index of mux to route
 * @reg: raw register value of RTSI_BRD bits
 * @dev: comedi device handle
 */
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)
{}

/*
 * Route signals through NI_RTSI_BRD mux and increment the use counter for this
 * particular route.
 *
 * Return: -EINVAL if the source is not valid to route to NI_RTSI_BRD(i);
 *	   -EBUSY if all NI_RTSI_BRD muxes are already used;
 *	   NI_RTSI_BRD(i) of allocated ith mux if successful.
 */
static int incr_rtsi_brd_src_use(int src, struct comedi_device *dev)
{}

/*
 * Unroute signals through NI_RTSI_BRD mux and decrement the user counter for
 * this particular route.
 *
 * Return: -EINVAL if the source is not already routed to rtsi_brd(i) (or usage
 *	is already at zero); 0 if successful.
 */
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)
{}

/* Get route of GPFO_i/CtrOut pins */
static inline int ni_get_gout_routing(unsigned int dest,
				      struct comedi_device *dev)
{}

/* Set route of GPFO_i/CtrOut pins */
static inline int ni_disable_gout_routing(unsigned int dest,
					  struct comedi_device *dev)
{}

/* Set route of GPFO_i/CtrOut pins */
static inline int ni_set_gout_routing(unsigned int src, unsigned int dest,
				      struct comedi_device *dev)
{}

/*
 * Retrieves the current source of the output selector for the given
 * destination.  If the terminal for the destination is not already configured
 * as an output, this function returns -EINVAL as error.
 *
 * Return: the register value of the destination output selector;
 *	   -EINVAL if terminal is not configured for output.
 */
static int get_output_select_source(int dest, struct comedi_device *dev)
{}

/*
 * Test a route:
 *
 * Return: -1 if not connectible;
 *	    0 if connectible and not connected;
 *	    1 if connectible and connected.
 */
static int test_route(unsigned int src, unsigned int dest,
		      struct comedi_device *dev)
{}

/* Connect the actual route.  */
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)
{}