Merge branch 'next/drivers' into HEAD
[deliverable/linux.git] / drivers / staging / comedi / drivers / cb_pcimdas.c
index c632a89f3ae974aa21af4679127117fd1837359f..9515b6926662cab66eca241f9b6e0cc8da1f3fd8 100644 (file)
@@ -118,11 +118,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,
@@ -137,160 +132,6 @@ struct cb_pcimdas_private {
        unsigned int ao_readback[2];
 };
 
-/*
- * 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,
 };
 
This page took 0.031256 seconds and 5 git commands to generate.