#include <linux/module.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 DAS1800_SIZE …
#define FIFO_SIZE …
#define DMA_BUF_SIZE …
#define DAS1800_FIFO …
#define DAS1800_QRAM …
#define DAS1800_DAC …
#define DAS1800_SELECT …
#define ADC …
#define QRAM …
#define DAC(a) …
#define DAS1800_DIGITAL …
#define DAS1800_CONTROL_A …
#define FFEN …
#define CGEN …
#define CGSL …
#define TGEN …
#define TGSL …
#define TGPL …
#define ATEN …
#define DAS1800_CONTROL_B …
#define DMA_CH5 …
#define DMA_CH6 …
#define DMA_CH7 …
#define DMA_CH5_CH6 …
#define DMA_CH6_CH7 …
#define DMA_CH7_CH5 …
#define DMA_ENABLED …
#define DMA_DUAL …
#define IRQ3 …
#define IRQ5 …
#define IRQ7 …
#define IRQ10 …
#define IRQ11 …
#define IRQ15 …
#define FIMD …
#define DAS1800_CONTROL_C …
#define IPCLK …
#define XPCLK …
#define BMDE …
#define CMEN …
#define UQEN …
#define SD …
#define UB …
#define DAS1800_STATUS …
#define INT …
#define DMATC …
#define CT0TC …
#define OVF …
#define FHF …
#define FNE …
#define CVEN …
#define CVEN_MASK …
#define CLEAR_INTR_MASK …
#define DAS1800_BURST_LENGTH …
#define DAS1800_BURST_RATE …
#define DAS1800_QRAM_ADDRESS …
#define DAS1800_COUNTER …
#define IOBASE2 …
static const struct comedi_lrange das1801_ai_range = …;
static const struct comedi_lrange das1802_ai_range = …;
enum das1800_boardid { … };
#define DAS1800_ID_ST_DA …
#define DAS1800_ID_HR_DA …
#define DAS1800_ID_AO …
#define DAS1800_ID_HR …
#define DAS1800_ID_ST …
#define DAS1800_ID_HC …
struct das1800_board { … };
static const struct das1800_board das1800_boards[] = …;
struct das1800_private { … };
static void das1800_ai_munge(struct comedi_device *dev,
struct comedi_subdevice *s,
void *data, unsigned int num_bytes,
unsigned int start_chan_index)
{ … }
static void das1800_handle_fifo_half_full(struct comedi_device *dev,
struct comedi_subdevice *s)
{ … }
static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
struct comedi_subdevice *s)
{ … }
static void das1800_flush_dma_channel(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_isadma_desc *desc)
{ … }
static void das1800_flush_dma(struct comedi_device *dev,
struct comedi_subdevice *s)
{ … }
static void das1800_handle_dma(struct comedi_device *dev,
struct comedi_subdevice *s, unsigned int status)
{ … }
static int das1800_ai_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{ … }
static void das1800_ai_handler(struct comedi_device *dev)
{ … }
static int das1800_ai_poll(struct comedi_device *dev,
struct comedi_subdevice *s)
{ … }
static irqreturn_t das1800_interrupt(int irq, void *d)
{ … }
static int das1800_ai_fixup_paced_timing(struct comedi_device *dev,
struct comedi_cmd *cmd)
{ … }
static int das1800_ai_fixup_burst_timing(struct comedi_device *dev,
struct comedi_cmd *cmd)
{ … }
static int das1800_ai_check_chanlist(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{ … }
static int das1800_ai_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{ … }
static unsigned char das1800_ai_chanspec_bits(struct comedi_subdevice *s,
unsigned int chanspec)
{ … }
static unsigned int das1800_ai_transfer_size(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned int maxbytes,
unsigned int ns)
{ … }
static void das1800_ai_setup_dma(struct comedi_device *dev,
struct comedi_subdevice *s)
{ … }
static void das1800_ai_set_chanlist(struct comedi_device *dev,
unsigned int *chanlist, unsigned int len)
{ … }
static int das1800_ai_cmd(struct comedi_device *dev,
struct comedi_subdevice *s)
{ … }
static int das1800_ai_eoc(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned long context)
{ … }
static int das1800_ai_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static int das1800_ao_insn_write(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static int das1800_di_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static int das1800_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{ … }
static void das1800_init_dma(struct comedi_device *dev,
struct comedi_devconfig *it)
{ … }
static void das1800_free_dma(struct comedi_device *dev)
{ … }
static int das1800_probe(struct comedi_device *dev)
{ … }
static int das1800_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
const struct das1800_board *board;
struct das1800_private *devpriv;
struct comedi_subdevice *s;
unsigned int irq = it->options[1];
bool is_16bit;
int ret;
int i;
devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
if (!devpriv)
return -ENOMEM;
ret = comedi_request_region(dev, it->options[0], DAS1800_SIZE);
if (ret)
return ret;
ret = das1800_probe(dev);
if (ret)
return ret;
board = dev->board_ptr;
is_16bit = board->id == DAS1800_ID_HR || board->id == DAS1800_ID_HR_DA;
if (board->id == DAS1800_ID_AO) {
unsigned long iobase2 = dev->iobase + IOBASE2;
ret = __comedi_request_region(dev, iobase2, DAS1800_SIZE);
if (ret)
return ret;
devpriv->iobase2 = iobase2;
}
if (irq == 3 || irq == 5 || irq == 7 || irq == 10 || irq == 11 ||
irq == 15) {
ret = request_irq(irq, das1800_interrupt, 0,
dev->board_name, dev);
if (ret == 0) {
dev->irq = irq;
switch (irq) {
case 3:
devpriv->irq_dma_bits |= 0x8;
break;
case 5:
devpriv->irq_dma_bits |= 0x10;
break;
case 7:
devpriv->irq_dma_bits |= 0x18;
break;
case 10:
devpriv->irq_dma_bits |= 0x28;
break;
case 11:
devpriv->irq_dma_bits |= 0x30;
break;
case 15:
devpriv->irq_dma_bits |= 0x38;
break;
}
}
}
if (dev->irq & it->options[2])
das1800_init_dma(dev, it);
devpriv->fifo_buf = kmalloc_array(FIFO_SIZE,
sizeof(*devpriv->fifo_buf),
GFP_KERNEL);
if (!devpriv->fifo_buf)
return -ENOMEM;
dev->pacer = comedi_8254_io_alloc(dev->iobase + DAS1800_COUNTER,
I8254_OSC_BASE_5MHZ, I8254_IO8, 0);
if (IS_ERR(dev->pacer))
return PTR_ERR(dev->pacer);
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
return ret;
s = &dev->subdevices[0];
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;
if (board->id != DAS1800_ID_HC)
s->subdev_flags |= SDF_COMMON;
s->n_chan = (board->id == DAS1800_ID_HC) ? 64 : 256;
s->maxdata = is_16bit ? 0xffff : 0x0fff;
s->range_table = board->is_01_series ? &das1801_ai_range
: &das1802_ai_range;
s->insn_read = das1800_ai_insn_read;
if (dev->irq) {
dev->read_subdev = s;
s->subdev_flags |= SDF_CMD_READ;
s->len_chanlist = s->n_chan;
s->do_cmd = das1800_ai_cmd;
s->do_cmdtest = das1800_ai_cmdtest;
s->poll = das1800_ai_poll;
s->cancel = das1800_ai_cancel;
s->munge = das1800_ai_munge;
}
s = &dev->subdevices[1];
if (board->id == DAS1800_ID_ST_DA || board->id == DAS1800_ID_HR_DA) {
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
s->n_chan = (board->id == DAS1800_ID_ST_DA) ? 4 : 2;
s->maxdata = is_16bit ? 0xffff : 0x0fff;
s->range_table = &range_bipolar10;
s->insn_write = das1800_ao_insn_write;
ret = comedi_alloc_subdev_readback(s);
if (ret)
return ret;
for (i = 0; i < s->n_chan; i++) {
outb(DAC(i), dev->iobase + DAS1800_SELECT);
outw(0, dev->iobase + DAS1800_DAC);
}
} else if (board->id == DAS1800_ID_AO) {
s->type = COMEDI_SUBD_UNUSED;
} else {
s->type = COMEDI_SUBD_UNUSED;
}
s = &dev->subdevices[2];
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
s->n_chan = 4;
s->maxdata = 1;
s->range_table = &range_digital;
s->insn_bits = das1800_di_insn_bits;
s = &dev->subdevices[3];
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE;
s->n_chan = (board->id == DAS1800_ID_HC) ? 8 : 4;
s->maxdata = 1;
s->range_table = &range_digital;
s->insn_bits = das1800_do_insn_bits;
das1800_ai_cancel(dev, dev->read_subdev);
outb(0, dev->iobase + DAS1800_DIGITAL);
return 0;
};
static void das1800_detach(struct comedi_device *dev)
{ … }
static struct comedi_driver das1800_driver = …;
module_comedi_driver(…);
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;