#include <linux/module.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/comedi/comedidev.h>
#include <linux/comedi/comedi_8254.h>
#include <linux/comedi/comedi_isadma.h>
#define A2150_DMA_BUFFER_SIZE …
#define CONFIG_REG …
#define CHANNEL_BITS(x) …
#define CHANNEL_MASK …
#define CLOCK_SELECT_BITS(x) …
#define CLOCK_DIVISOR_BITS(x) …
#define CLOCK_MASK …
#define ENABLE0_BIT …
#define ENABLE1_BIT …
#define AC0_BIT …
#define AC1_BIT …
#define APD_BIT …
#define DPD_BIT …
#define TRIGGER_REG …
#define POST_TRIGGER_BITS …
#define DELAY_TRIGGER_BITS …
#define HW_TRIG_EN …
#define FIFO_START_REG …
#define FIFO_RESET_REG …
#define FIFO_DATA_REG …
#define DMA_TC_CLEAR_REG …
#define STATUS_REG …
#define FNE_BIT …
#define OVFL_BIT …
#define EDAQ_BIT …
#define DCAL_BIT …
#define INTR_BIT …
#define DMA_TC_BIT …
#define ID_BITS(x) …
#define IRQ_DMA_CNTRL_REG …
#define DMA_CHAN_BITS(x) …
#define DMA_EN_BIT …
#define IRQ_LVL_BITS(x) …
#define FIFO_INTR_EN_BIT …
#define FIFO_INTR_FHF_BIT …
#define DMA_INTR_EN_BIT …
#define DMA_DEM_EN_BIT …
#define I8253_BASE_REG …
struct a2150_board { … };
static const struct comedi_lrange range_a2150 = …;
enum { … };
static const struct a2150_board a2150_boards[] = …;
struct a2150_private { … };
static irqreturn_t a2150_interrupt(int irq, void *d)
{ … }
static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
{ … }
static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
unsigned int flags)
{ … }
static int a2150_set_chanlist(struct comedi_device *dev,
unsigned int start_channel,
unsigned int num_channels)
{ … }
static int a2150_ai_check_chanlist(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{ … }
static int a2150_ai_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_cmd *cmd)
{ … }
static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{ … }
static int a2150_ai_eoc(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned long context)
{ … }
static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{ … }
static void a2150_alloc_irq_and_dma(struct comedi_device *dev,
struct comedi_devconfig *it)
{ … }
static void a2150_free_dma(struct comedi_device *dev)
{ … }
static const struct a2150_board *a2150_probe(struct comedi_device *dev)
{ … }
static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
const struct a2150_board *board;
struct a2150_private *devpriv;
struct comedi_subdevice *s;
static const int timeout = 2000;
int i;
int ret;
devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
if (!devpriv)
return -ENOMEM;
ret = comedi_request_region(dev, it->options[0], 0x1c);
if (ret)
return ret;
board = a2150_probe(dev);
if (!board)
return -ENODEV;
dev->board_ptr = board;
dev->board_name = board->name;
a2150_alloc_irq_and_dma(dev, it);
dev->pacer = comedi_8254_io_alloc(dev->iobase + I8253_BASE_REG,
0, I8254_IO8, 0);
if (IS_ERR(dev->pacer))
return PTR_ERR(dev->pacer);
ret = comedi_alloc_subdevices(dev, 1);
if (ret)
return ret;
s = &dev->subdevices[0];
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_OTHER;
s->n_chan = 4;
s->maxdata = 0xffff;
s->range_table = &range_a2150;
s->insn_read = a2150_ai_rinsn;
if (dev->irq) {
dev->read_subdev = s;
s->subdev_flags |= SDF_CMD_READ;
s->len_chanlist = s->n_chan;
s->do_cmd = a2150_ai_cmd;
s->do_cmdtest = a2150_ai_cmdtest;
s->cancel = a2150_cancel;
}
outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
outw_p(DPD_BIT | APD_BIT, dev->iobase + CONFIG_REG);
outw_p(DPD_BIT, dev->iobase + CONFIG_REG);
devpriv->config_bits = 0;
outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
for (i = 0; i < timeout; i++) {
if ((DCAL_BIT & inw(dev->iobase + STATUS_REG)) == 0)
break;
usleep_range(1000, 3000);
}
if (i == timeout) {
dev_err(dev->class_dev,
"timed out waiting for offset calibration to complete\n");
return -ETIME;
}
devpriv->config_bits |= ENABLE0_BIT | ENABLE1_BIT;
outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
return 0;
};
static void a2150_detach(struct comedi_device *dev)
{
if (dev->iobase)
outw(APD_BIT | DPD_BIT, dev->iobase + CONFIG_REG);
a2150_free_dma(dev);
comedi_legacy_detach(dev);
};
static struct comedi_driver ni_at_a2150_driver = …;
module_comedi_driver(…);
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;