in drivers/das1800.c [1160:1334]
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;
/* waveform 'ao' boards have additional io ports */
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;
}
}
}
/* an irq and one dma channel is required to use dma */
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_init(dev->iobase + DAS1800_COUNTER,
I8254_OSC_BASE_5MHZ, I8254_IO8, 0);
if (!dev->pacer)
return -ENOMEM;
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
return ret;
/*
* Analog Input subdevice
*
* The "hc" type boards have 64 analog input channels and a 64
* entry QRAM fifo.
*
* All the other board types have 16 on-board channels. Each channel
* can be expanded to 16 channels with the addition of an EXP-1800
* expansion board for a total of 256 channels. The QRAM fifo on
* these boards has 256 entries.
*
* From the datasheets it's not clear what the comedi channel to
* actual physical channel mapping is when EXP-1800 boards are used.
*/
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;
}
/* Analog Output subdevice */
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;
/* initialize all channels to 0V */
for (i = 0; i < s->n_chan; i++) {
/* spinlock is not necessary during the attach */
outb(DAC(i), dev->iobase + DAS1800_SELECT);
outw(0, dev->iobase + DAS1800_DAC);
}
} else if (board->id == DAS1800_ID_AO) {
/*
* 'ao' boards have waveform analog outputs that are not
* currently supported.
*/
s->type = COMEDI_SUBD_UNUSED;
} else {
s->type = COMEDI_SUBD_UNUSED;
}
/* Digital Input subdevice */
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;
/* Digital Output subdevice */
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);
/* initialize digital out channels */
outb(0, dev->iobase + DAS1800_DIGITAL);
return 0;
};