in drivers/adl_pci9118.c [1504:1646]
static int pci9118_common_attach(struct comedi_device *dev,
int ext_mux, int softsshdelay)
{
const struct pci9118_boardinfo *board = dev->board_ptr;
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
struct pci9118_private *devpriv;
struct comedi_subdevice *s;
int ret;
int i;
u16 u16w;
devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
if (!devpriv)
return -ENOMEM;
ret = comedi_pci_enable(dev);
if (ret)
return ret;
pci_set_master(pcidev);
devpriv->iobase_a = pci_resource_start(pcidev, 0);
dev->iobase = pci_resource_start(pcidev, 2);
dev->pacer = comedi_8254_init(dev->iobase + PCI9118_TIMER_BASE,
I8254_OSC_BASE_4MHZ, I8254_IO32, 0);
if (!dev->pacer)
return -ENOMEM;
pci9118_reset(dev);
if (pcidev->irq) {
ret = request_irq(pcidev->irq, pci9118_interrupt, IRQF_SHARED,
dev->board_name, dev);
if (ret == 0) {
dev->irq = pcidev->irq;
pci9118_alloc_dma(dev);
}
}
if (ext_mux > 0) {
if (ext_mux > 256)
ext_mux = 256; /* max 256 channels! */
if (softsshdelay > 0)
if (ext_mux > 128)
ext_mux = 128;
devpriv->usemux = 1;
} else {
devpriv->usemux = 0;
}
if (softsshdelay < 0) {
/* select sample&hold signal polarity */
devpriv->softsshdelay = -softsshdelay;
devpriv->softsshsample = 0x80;
devpriv->softsshhold = 0x00;
} else {
devpriv->softsshdelay = softsshdelay;
devpriv->softsshsample = 0x00;
devpriv->softsshhold = 0x80;
}
pci_read_config_word(pcidev, PCI_COMMAND, &u16w);
pci_write_config_word(pcidev, PCI_COMMAND, u16w | 64);
/* Enable parity check for parity error */
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
return ret;
/* Analog Input subdevice */
s = &dev->subdevices[0];
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
s->n_chan = (devpriv->usemux) ? ext_mux : 16;
s->maxdata = board->ai_is_16bit ? 0xffff : 0x0fff;
s->range_table = board->is_hg ? &pci9118hg_ai_range
: &pci9118_ai_range;
s->insn_read = pci9118_ai_insn_read;
if (dev->irq) {
dev->read_subdev = s;
s->subdev_flags |= SDF_CMD_READ;
s->len_chanlist = 255;
s->do_cmdtest = pci9118_ai_cmdtest;
s->do_cmd = pci9118_ai_cmd;
s->cancel = pci9118_ai_cancel;
s->munge = pci9118_ai_munge;
}
if (s->maxdata == 0xffff) {
/*
* 16-bit samples are from an ADS7805 A/D converter.
* Minimum sampling rate is 10us.
*/
devpriv->ai_ns_min = 10000;
} else {
/*
* 12-bit samples are from an ADS7800 A/D converter.
* Minimum sampling rate is 3us.
*/
devpriv->ai_ns_min = 3000;
}
/* Analog Output subdevice */
s = &dev->subdevices[1];
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
s->n_chan = 2;
s->maxdata = 0x0fff;
s->range_table = &range_bipolar10;
s->insn_write = pci9118_ao_insn_write;
ret = comedi_alloc_subdev_readback(s);
if (ret)
return ret;
/* the analog outputs were reset to 0V, make the readback match */
for (i = 0; i < s->n_chan; i++)
s->readback[i] = 2047;
/* 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 = pci9118_di_insn_bits;
/* Digital Output subdevice */
s = &dev->subdevices[3];
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE;
s->n_chan = 4;
s->maxdata = 1;
s->range_table = &range_digital;
s->insn_bits = pci9118_do_insn_bits;
/* get the current state of the digital outputs */
s->state = inl(dev->iobase + PCI9118_DIO_REG) >> 4;
return 0;
}