aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging/comedi/drivers/cb_pcimdas.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/comedi/drivers/cb_pcimdas.c')
-rw-r--r--drivers/staging/comedi/drivers/cb_pcimdas.c279
1 files changed, 119 insertions, 160 deletions
diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
index c632a89f3ae..9515b692666 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
@@ -119,11 +119,6 @@ static const struct cb_pcimdas_board cb_pcimdas_boards[] = {
};
/*
- * Useful for shorthand access to the particular board structure
- */
-#define thisboard ((const struct cb_pcimdas_board *)dev->board_ptr)
-
-/*
* this structure is for data unique to this hardware driver. If
* several hardware drivers keep similar information in this structure,
* feel free to suggest moving the variable to the struct comedi_device
@@ -138,160 +133,6 @@ struct cb_pcimdas_private {
};
/*
- * most drivers define the following macro to make it easy to
- * access the private structure.
- */
-#define devpriv ((struct cb_pcimdas_private *)dev->private)
-
-static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int cb_pcimdas_ao_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int cb_pcimdas_ao_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-static struct pci_dev *cb_pcimdas_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
- int i;
-
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (bus != pcidev->bus->number ||
- slot != PCI_SLOT(pcidev->devfn))
- continue;
- }
- if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
- continue;
-
- for (i = 0; i < ARRAY_SIZE(cb_pcimdas_boards); i++) {
- if (cb_pcimdas_boards[i].device_id != pcidev->device)
- continue;
-
- dev->board_ptr = cb_pcimdas_boards + i;
- return pcidev;
- }
- }
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
- return NULL;
-}
-
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board. If you specified a board_name array
- * in the driver structure, dev->board_ptr contains that
- * address.
- */
-static int cb_pcimdas_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev;
- struct comedi_subdevice *s;
- unsigned long iobase_8255;
- int ret;
-
-/*
- * Allocate the private structure area.
- */
- if (alloc_private(dev, sizeof(struct cb_pcimdas_private)) < 0)
- return -ENOMEM;
-
- pcidev = cb_pcimdas_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
-
- /* Warn about non-tested features */
- switch (thisboard->device_id) {
- case 0x56:
- break;
- default:
- dev_dbg(dev->class_dev, "THIS CARD IS UNSUPPORTED.\n");
- dev_dbg(dev->class_dev,
- "PLEASE REPORT USAGE TO <mocelet@sucs.org>\n");
- }
-
- if (comedi_pci_enable(pcidev, "cb_pcimdas")) {
- dev_err(dev->class_dev,
- "Failed to enable PCI device and request regions\n");
- return -EIO;
- }
-
- dev->iobase = pci_resource_start(pcidev, 2);
- devpriv->BADR3 = pci_resource_start(pcidev, 3);
- iobase_8255 = pci_resource_start(pcidev, 4);
-
-/* Dont support IRQ yet */
-/* get irq */
-/* if(request_irq(pcidev->irq, cb_pcimdas_interrupt, IRQF_SHARED, "cb_pcimdas", dev )) */
-/* { */
-/* printk(" unable to allocate irq %u\n", pcidev->irq); */
-/* return -EINVAL; */
-/* } */
-/* dev->irq = pcidev->irq; */
-
- /* Initialize dev->board_name */
- dev->board_name = thisboard->name;
-
- ret = comedi_alloc_subdevices(dev, 3);
- if (ret)
- return ret;
-
- s = dev->subdevices + 0;
- /* dev->read_subdev=s; */
- /* analog input subdevice */
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND;
- s->n_chan = thisboard->ai_se_chans;
- s->maxdata = (1 << thisboard->ai_bits) - 1;
- s->range_table = &range_unknown;
- s->len_chanlist = 1; /* This is the maximum chanlist length that */
- /* the board can handle */
- s->insn_read = cb_pcimdas_ai_rinsn;
-
- s = dev->subdevices + 1;
- /* analog output subdevice */
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE;
- s->n_chan = thisboard->ao_nchan;
- s->maxdata = 1 << thisboard->ao_bits;
- /* ranges are hardware settable, but not software readable. */
- s->range_table = &range_unknown;
- s->insn_write = &cb_pcimdas_ao_winsn;
- s->insn_read = &cb_pcimdas_ao_rinsn;
-
- s = dev->subdevices + 2;
- /* digital i/o subdevice */
- if (thisboard->has_dio)
- subdev_8255_init(dev, s, NULL, iobase_8255);
- else
- s->type = COMEDI_SUBD_UNUSED;
-
- return 1;
-}
-
-static void cb_pcimdas_detach(struct comedi_device *dev)
-{
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
- if (dev->irq)
- free_irq(dev->irq, dev);
- if (pcidev) {
- if (dev->iobase)
- comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
- }
-}
-
-/*
* "instructions" read/write data in "one-shot" or "software-triggered"
* mode.
*/
@@ -299,6 +140,8 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ const struct cb_pcimdas_board *thisboard = comedi_board(dev);
+ struct cb_pcimdas_private *devpriv = dev->private;
int n, i;
unsigned int d;
unsigned int busy;
@@ -368,6 +211,7 @@ static int cb_pcimdas_ao_winsn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct cb_pcimdas_private *devpriv = dev->private;
int i;
int chan = CR_CHAN(insn->chanspec);
@@ -397,6 +241,7 @@ static int cb_pcimdas_ao_rinsn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct cb_pcimdas_private *devpriv = dev->private;
int i;
int chan = CR_CHAN(insn->chanspec);
@@ -406,10 +251,124 @@ static int cb_pcimdas_ao_rinsn(struct comedi_device *dev,
return i;
}
+static const void *cb_pcimdas_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
+{
+ const struct cb_pcimdas_board *thisboard;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cb_pcimdas_boards); i++) {
+ thisboard = &cb_pcimdas_boards[i];
+ if (thisboard->device_id == pcidev->device)
+ return thisboard;
+ }
+ return NULL;
+}
+
+static int cb_pcimdas_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
+{
+ const struct cb_pcimdas_board *thisboard;
+ struct cb_pcimdas_private *devpriv;
+ struct comedi_subdevice *s;
+ unsigned long iobase_8255;
+ int ret;
+
+ comedi_set_hw_dev(dev, &pcidev->dev);
+
+ thisboard = cb_pcimdas_find_boardinfo(dev, pcidev);
+ if (!thisboard)
+ return -ENODEV;
+ dev->board_ptr = thisboard;
+ dev->board_name = thisboard->name;
+
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret)
+ return ret;
+ devpriv = dev->private;
+
+ /* Warn about non-tested features */
+ switch (thisboard->device_id) {
+ case 0x56:
+ break;
+ default:
+ dev_dbg(dev->class_dev, "THIS CARD IS UNSUPPORTED.\n");
+ dev_dbg(dev->class_dev,
+ "PLEASE REPORT USAGE TO <mocelet@sucs.org>\n");
+ }
+
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
+
+ dev->iobase = pci_resource_start(pcidev, 2);
+ devpriv->BADR3 = pci_resource_start(pcidev, 3);
+ iobase_8255 = pci_resource_start(pcidev, 4);
+
+/* Dont support IRQ yet */
+/* get irq */
+/* if(request_irq(pcidev->irq, cb_pcimdas_interrupt, IRQF_SHARED, "cb_pcimdas", dev )) */
+/* { */
+/* printk(" unable to allocate irq %u\n", pcidev->irq); */
+/* return -EINVAL; */
+/* } */
+/* dev->irq = pcidev->irq; */
+
+ ret = comedi_alloc_subdevices(dev, 3);
+ if (ret)
+ return ret;
+
+ s = &dev->subdevices[0];
+ /* dev->read_subdev=s; */
+ /* analog input subdevice */
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND;
+ s->n_chan = thisboard->ai_se_chans;
+ s->maxdata = (1 << thisboard->ai_bits) - 1;
+ s->range_table = &range_unknown;
+ s->len_chanlist = 1; /* This is the maximum chanlist length that */
+ /* the board can handle */
+ s->insn_read = cb_pcimdas_ai_rinsn;
+
+ s = &dev->subdevices[1];
+ /* analog output subdevice */
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = thisboard->ao_nchan;
+ s->maxdata = 1 << thisboard->ao_bits;
+ /* ranges are hardware settable, but not software readable. */
+ s->range_table = &range_unknown;
+ s->insn_write = &cb_pcimdas_ao_winsn;
+ s->insn_read = &cb_pcimdas_ao_rinsn;
+
+ s = &dev->subdevices[2];
+ /* digital i/o subdevice */
+ if (thisboard->has_dio)
+ subdev_8255_init(dev, s, NULL, iobase_8255);
+ else
+ s->type = COMEDI_SUBD_UNUSED;
+
+ dev_info(dev->class_dev, "%s attached\n", dev->board_name);
+
+ return 0;
+}
+
+static void cb_pcimdas_detach(struct comedi_device *dev)
+{
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+ if (pcidev) {
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
+ }
+}
+
static struct comedi_driver cb_pcimdas_driver = {
.driver_name = "cb_pcimdas",
.module = THIS_MODULE,
- .attach = cb_pcimdas_attach,
+ .attach_pci = cb_pcimdas_attach_pci,
.detach = cb_pcimdas_detach,
};