in drivers/ni_labpc_common.c [1186:1337]
int labpc_common_attach(struct comedi_device *dev,
unsigned int irq, unsigned long isr_flags)
{
const struct labpc_boardinfo *board = dev->board_ptr;
struct labpc_private *devpriv;
struct comedi_subdevice *s;
int ret;
int i;
devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
if (!devpriv)
return -ENOMEM;
if (dev->mmio) {
devpriv->read_byte = labpc_readb;
devpriv->write_byte = labpc_writeb;
} else {
devpriv->read_byte = labpc_inb;
devpriv->write_byte = labpc_outb;
}
/* initialize board's command registers */
devpriv->write_byte(dev, devpriv->cmd1, CMD1_REG);
devpriv->write_byte(dev, devpriv->cmd2, CMD2_REG);
devpriv->write_byte(dev, devpriv->cmd3, CMD3_REG);
devpriv->write_byte(dev, devpriv->cmd4, CMD4_REG);
if (board->is_labpc1200) {
devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
devpriv->write_byte(dev, devpriv->cmd6, CMD6_REG);
}
if (irq) {
ret = request_irq(irq, labpc_interrupt, isr_flags,
dev->board_name, dev);
if (ret == 0)
dev->irq = irq;
}
if (dev->mmio) {
dev->pacer = comedi_8254_mm_init(dev->mmio + COUNTER_B_BASE_REG,
I8254_OSC_BASE_2MHZ,
I8254_IO8, 0);
devpriv->counter = comedi_8254_mm_init(dev->mmio +
COUNTER_A_BASE_REG,
I8254_OSC_BASE_2MHZ,
I8254_IO8, 0);
} else {
dev->pacer = comedi_8254_init(dev->iobase + COUNTER_B_BASE_REG,
I8254_OSC_BASE_2MHZ,
I8254_IO8, 0);
devpriv->counter = comedi_8254_init(dev->iobase +
COUNTER_A_BASE_REG,
I8254_OSC_BASE_2MHZ,
I8254_IO8, 0);
}
if (!dev->pacer || !devpriv->counter)
return -ENOMEM;
ret = comedi_alloc_subdevices(dev, 5);
if (ret)
return ret;
/* analog input subdevice */
s = &dev->subdevices[0];
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF;
s->n_chan = 8;
s->len_chanlist = 8;
s->maxdata = 0x0fff;
s->range_table = board->is_labpc1200 ?
&range_labpc_1200_ai : &range_labpc_plus_ai;
s->insn_read = labpc_ai_insn_read;
if (dev->irq) {
dev->read_subdev = s;
s->subdev_flags |= SDF_CMD_READ;
s->do_cmd = labpc_ai_cmd;
s->do_cmdtest = labpc_ai_cmdtest;
s->cancel = labpc_cancel;
}
/* analog output */
s = &dev->subdevices[1];
if (board->has_ao) {
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
s->n_chan = 2;
s->maxdata = 0x0fff;
s->range_table = &range_labpc_ao;
s->insn_write = labpc_ao_insn_write;
ret = comedi_alloc_subdev_readback(s);
if (ret)
return ret;
/* initialize analog outputs to a known value */
for (i = 0; i < s->n_chan; i++)
labpc_ao_write(dev, s, i, s->maxdata / 2);
} else {
s->type = COMEDI_SUBD_UNUSED;
}
/* 8255 dio */
s = &dev->subdevices[2];
if (dev->mmio)
ret = subdev_8255_mm_init(dev, s, NULL, DIO_BASE_REG);
else
ret = subdev_8255_init(dev, s, NULL, DIO_BASE_REG);
if (ret)
return ret;
/* calibration subdevices for boards that have one */
s = &dev->subdevices[3];
if (board->is_labpc1200) {
s->type = COMEDI_SUBD_CALIB;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
s->n_chan = 16;
s->maxdata = 0xff;
s->insn_write = labpc_calib_insn_write;
ret = comedi_alloc_subdev_readback(s);
if (ret)
return ret;
for (i = 0; i < s->n_chan; i++) {
write_caldac(dev, i, s->maxdata / 2);
s->readback[i] = s->maxdata / 2;
}
} else {
s->type = COMEDI_SUBD_UNUSED;
}
/* EEPROM (256 bytes) */
s = &dev->subdevices[4];
if (board->is_labpc1200) {
s->type = COMEDI_SUBD_MEMORY;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
s->n_chan = 256;
s->maxdata = 0xff;
s->insn_write = labpc_eeprom_insn_write;
ret = comedi_alloc_subdev_readback(s);
if (ret)
return ret;
for (i = 0; i < s->n_chan; i++)
s->readback[i] = labpc_eeprom_read(dev, i);
} else {
s->type = COMEDI_SUBD_UNUSED;
}
return 0;
}