diff options
Diffstat (limited to 'drivers/staging/comedi/drivers/adl_pci6208.c')
-rw-r--r-- | drivers/staging/comedi/drivers/adl_pci6208.c | 183 |
1 files changed, 87 insertions, 96 deletions
diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index 3bec0f6e4a8c..3492ce1156e0 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -27,14 +27,14 @@ */ /* Driver: adl_pci6208 -Description: ADLink PCI-6208A -Devices: [ADLink] PCI-6208A (adl_pci6208) +Description: ADLink PCI-6208/6216 Series Multi-channel Analog Output Cards +Devices: (ADLink) PCI-6208 [adl_pci6208] + (ADLink) PCI-6216 [adl_pci6216] Author: nsyeow <nsyeow@pd.jaring.my> Updated: Fri, 30 Jan 2004 14:44:27 +0800 Status: untested -Configuration Options: - none +Configuration Options: not applicable, uses PCI auto config References: - ni_660x.c @@ -45,6 +45,12 @@ References: #include "../comedidev.h" /* + * ADLINK PCI Device ID's supported by this driver + */ +#define PCI_DEVICE_ID_PCI6208 0x6208 +#define PCI_DEVICE_ID_PCI6216 0x6216 + +/* * PCI-6208/6216-GL register map */ #define PCI6208_AO_CONTROL(x) (0x00 + (2 * (x))) @@ -56,7 +62,7 @@ References: #define PCI6208_DIO_DI_MASK (0xf0) #define PCI6208_DIO_DI_SHIFT (4) -#define PCI6208_MAX_AO_CHANNELS 8 +#define PCI6208_MAX_AO_CHANNELS 16 struct pci6208_board { const char *name; @@ -66,9 +72,13 @@ struct pci6208_board { static const struct pci6208_board pci6208_boards[] = { { - .name = "pci6208a", - .dev_id = 0x6208, + .name = "adl_pci6208", + .dev_id = PCI_DEVICE_ID_PCI6208, .ao_chans = 8, + }, { + .name = "adl_pci6216", + .dev_id = PCI_DEVICE_ID_PCI6216, + .ao_chans = 16, }, }; @@ -115,141 +125,122 @@ static int pci6208_ao_rinsn(struct comedi_device *dev, return insn->n; } -static int pci6208_dio_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) +static int pci6208_di_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned int val; + + val = inw(dev->iobase + PCI6208_DIO); + val = (val & PCI6208_DIO_DI_MASK) >> PCI6208_DIO_DI_SHIFT; + + data[1] = val; + + return insn->n; +} + +static int pci6208_do_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - unsigned int mask = data[0] & PCI6208_DIO_DO_MASK; + unsigned int mask = data[0]; unsigned int bits = data[1]; if (mask) { s->state &= ~mask; - s->state |= bits & mask; + s->state |= (bits & mask); outw(s->state, dev->iobase + PCI6208_DIO); } - s->state = inw(dev->iobase + PCI6208_DIO); data[1] = s->state; return insn->n; } -static int pci6208_dio_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - int chan = CR_CHAN(insn->chanspec); - unsigned int mask = 1 << chan; - - switch (data[0]) { - case INSN_CONFIG_DIO_QUERY: - data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT; - break; - default: - return -EINVAL; - } - - return insn->n; -} - -static struct pci_dev *pci6208_find_device(struct comedi_device *dev, - struct comedi_devconfig *it) +static const void *pci6208_find_boardinfo(struct comedi_device *dev, + struct pci_dev *pcidev) { - const struct pci6208_board *thisboard; - struct pci_dev *pci_dev = NULL; - int bus = it->options[0]; - int slot = it->options[1]; + const struct pci6208_board *boardinfo; int i; - for_each_pci_dev(pci_dev) { - if (pci_dev->vendor != PCI_VENDOR_ID_ADLINK) - continue; - for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) { - thisboard = &pci6208_boards[i]; - if (thisboard->dev_id != pci_dev->device) - continue; - /* was a particular bus/slot requested? */ - if (bus || slot) { - /* are we on the wrong bus/slot? */ - if (pci_dev->bus->number != bus || - PCI_SLOT(pci_dev->devfn) != slot) - continue; - } - dev_dbg(dev->class_dev, - "Found %s on bus %d, slot, %d, irq=%d\n", - thisboard->name, - pci_dev->bus->number, - PCI_SLOT(pci_dev->devfn), - pci_dev->irq); - dev->board_ptr = thisboard; - return pci_dev; - } + for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) { + boardinfo = &pci6208_boards[i]; + if (boardinfo->dev_id == pcidev->device) + return boardinfo; } - dev_err(dev->class_dev, - "No supported board found! (req. bus %d, slot %d)\n", - bus, slot); return NULL; } -static int pci6208_attach(struct comedi_device *dev, - struct comedi_devconfig *it) +static int pci6208_attach_pci(struct comedi_device *dev, + struct pci_dev *pcidev) { - const struct pci6208_board *thisboard; + const struct pci6208_board *boardinfo; struct pci6208_private *devpriv; - struct pci_dev *pcidev; struct comedi_subdevice *s; + unsigned int val; int ret; + comedi_set_hw_dev(dev, &pcidev->dev); + + boardinfo = pci6208_find_boardinfo(dev, pcidev); + if (!boardinfo) + return -ENODEV; + dev->board_ptr = boardinfo; + dev->board_name = boardinfo->name; + ret = alloc_private(dev, sizeof(*devpriv)); if (ret < 0) return ret; devpriv = dev->private; - pcidev = pci6208_find_device(dev, it); - if (!pcidev) - return -EIO; - comedi_set_hw_dev(dev, &pcidev->dev); - thisboard = comedi_board(dev); - - dev->board_name = thisboard->name; - - ret = comedi_pci_enable(pcidev, dev->driver->driver_name); - if (ret) { - dev_err(dev->class_dev, - "Failed to enable PCI device and request regions\n"); + ret = comedi_pci_enable(pcidev, dev->board_name); + if (ret) return ret; - } dev->iobase = pci_resource_start(pcidev, 2); - ret = comedi_alloc_subdevices(dev, 2); + ret = comedi_alloc_subdevices(dev, 3); if (ret) return ret; - s = dev->subdevices + 0; + s = &dev->subdevices[0]; /* analog output subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = thisboard->ao_chans; + s->n_chan = boardinfo->ao_chans; s->maxdata = 0xffff; s->range_table = &range_bipolar10; s->insn_write = pci6208_ao_winsn; s->insn_read = pci6208_ao_rinsn; - s = dev->subdevices + 1; - /* digital i/o subdevice */ - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 8; + s = &dev->subdevices[1]; + /* digital input subdevice */ + 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 = pci6208_dio_insn_bits; - s->insn_config = pci6208_dio_insn_config; + s->insn_bits = pci6208_di_insn_bits; + s = &dev->subdevices[2]; + /* digital output subdevice */ + 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 = pci6208_do_insn_bits; + + /* + * Get the read back signals from the digital outputs + * and save it as the initial state for the subdevice. + */ + val = inw(dev->iobase + PCI6208_DIO); + val = (val & PCI6208_DIO_DO_MASK) >> PCI6208_DIO_DO_SHIFT; + s->state = val; s->io_bits = 0x0f; - s->state = inw(dev->iobase + PCI6208_DIO); dev_info(dev->class_dev, "%s: %s, I/O base=0x%04lx\n", dev->driver->driver_name, dev->board_name, dev->iobase); @@ -264,14 +255,13 @@ static void pci6208_detach(struct comedi_device *dev) if (pcidev) { if (dev->iobase) comedi_pci_disable(pcidev); - pci_dev_put(pcidev); } } static struct comedi_driver adl_pci6208_driver = { .driver_name = "adl_pci6208", .module = THIS_MODULE, - .attach = pci6208_attach, + .attach_pci = pci6208_attach_pci, .detach = pci6208_detach, }; @@ -287,7 +277,8 @@ static void __devexit adl_pci6208_pci_remove(struct pci_dev *dev) } static DEFINE_PCI_DEVICE_TABLE(adl_pci6208_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x6208) }, + { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI6208) }, + { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI6216) }, { 0 } }; MODULE_DEVICE_TABLE(pci, adl_pci6208_pci_table); |