staging: comedi: adl_pci9118: split pci9118_attach()
authorIan Abbott <abbotti@mev.co.uk>
Fri, 2 Nov 2012 13:52:30 +0000 (13:52 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 2 Nov 2012 18:39:37 +0000 (11:39 -0700)
Split most of the functionality of the attach routine `pci9118_attach()`
into a new function `pci9118_common_attach()` that can be called when
auto-attachment of devices is supported.  Move the enabling of the PCI
device and its i/o regions into this function.  Do the requesting of the
interrupt near the end of the function so it doesn't get enabled before
the device is ready.

Note that auto-attachment of PCI devices is currently broken in this
driver because the list of board names referred to by the `struct
comedi_driver` does not contain a "wildcard" entry matching the comedi
driver name.  This won't be a problem once support for the
`auto_attach()` method is added.

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/comedi/drivers/adl_pci9118.c

index 01c9ba3..cc46d64 100644 (file)
@@ -1873,12 +1873,6 @@ static struct pci_dev *pci9118_find_pci(struct comedi_device *dev,
                            PCI_SLOT(pcidev->devfn) != slot)
                                continue;
                }
-               /*
-                * Look for device that isn't in use.
-                * Enable PCI device and request regions.
-                */
-               if (comedi_pci_enable(pcidev, "adl_pci9118"))
-                       continue;
                return pcidev;
        }
        dev_err(dev->class_dev,
@@ -1909,56 +1903,33 @@ static void pci9118_report_attach(struct comedi_device *dev, unsigned int irq)
                 (devpriv->master ? "" : "no "), muxbuf);
 }
 
-static int pci9118_attach(struct comedi_device *dev,
-                         struct comedi_devconfig *it)
+static int pci9118_common_attach(struct comedi_device *dev, int disable_irq,
+                                int master, int ext_mux, int softsshdelay,
+                                int hw_err_mask)
 {
        const struct boardtype *this_board = comedi_board(dev);
-       struct pci9118_private *devpriv;
-       struct pci_dev *pcidev;
+       struct pci9118_private *devpriv = dev->private;
+       struct pci_dev *pcidev = comedi_to_pci_dev(dev);
        struct comedi_subdevice *s;
        int ret, pages, i;
-       unsigned short master;
        unsigned int irq;
        u16 u16w;
 
-       if (it->options[3] & 1)
-               master = 0;     /* user don't want use bus master */
-       else
-               master = 1;
-
-       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
-       if (!devpriv)
-               return -ENOMEM;
-       dev->private = devpriv;
-
-       pcidev = pci9118_find_pci(dev, it);
-       if (!pcidev)
-               return -EIO;
-       comedi_set_hw_dev(dev, &pcidev->dev);
-
+       dev->board_name = this_board->name;
+       ret = comedi_pci_enable(pcidev, dev->board_name);
+       if (ret) {
+               dev_err(dev->class_dev,
+                       "cannot enable PCI device %s\n", pci_name(pcidev));
+               return ret;
+       }
        if (master)
                pci_set_master(pcidev);
 
-       irq = pcidev->irq;
        devpriv->iobase_a = pci_resource_start(pcidev, 0);
        dev->iobase = pci_resource_start(pcidev, 2);
 
-       dev->board_name = this_board->name;
-
        pci9118_reset(dev);
 
-       if (it->options[3] & 2)
-               irq = 0;        /* user don't want use IRQ */
-       if (irq > 0) {
-               if (request_irq(irq, interrupt_pci9118, IRQF_SHARED,
-                               "ADLink PCI-9118", dev))
-                       dev_warn(dev->class_dev,
-                                "unable to allocate IRQ %u, DISABLING IT\n",
-                                irq);
-               else
-                       dev->irq = irq;
-       }
-
        if (master) {           /* alloc DMA buffers */
                devpriv->dma_doublebuf = 0;
                for (i = 0; i < 2; i++) {
@@ -1984,32 +1955,29 @@ static int pci9118_attach(struct comedi_device *dev,
                                 "Can't allocate DMA buffer, DMA disabled!\n");
                        master = 0;
                }
-
                if (devpriv->dmabuf_virt[1])
                        devpriv->dma_doublebuf = 1;
-
        }
-
        devpriv->master = master;
-       devpriv->usemux = 0;
-       if (it->options[2] > 0) {
-               devpriv->usemux = it->options[2];
-               if (devpriv->usemux > 256)
-                       devpriv->usemux = 256;  /* max 256 channels! */
-               if (it->options[4] > 0)
-                       if (devpriv->usemux > 128) {
-                               devpriv->usemux = 128;
-                                       /* max 128 channels with softare S&H! */
-                       }
+
+       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 = ext_mux;
+       } else {
+               devpriv->usemux = 0;
        }
 
-       devpriv->softsshdelay = it->options[4];
-       if (devpriv->softsshdelay < 0) {
-                                       /* select sample&hold signal polarity */
-               devpriv->softsshdelay = -devpriv->softsshdelay;
+       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;
        }
@@ -2036,12 +2004,7 @@ static int pci9118_attach(struct comedi_device *dev,
        s->range_table = this_board->rangelist_ai;
        s->cancel = pci9118_ai_cancel;
        s->insn_read = pci9118_insn_read_ai;
-       if (dev->irq) {
-               s->subdev_flags |= SDF_CMD_READ;
-               s->do_cmdtest = pci9118_ai_cmdtest;
-               s->do_cmd = pci9118_ai_cmd;
-               s->munge = pci9118_ai_munge;
-       }
+       s->munge = pci9118_ai_munge;
 
        s = &dev->subdevices[1];
        s->type = COMEDI_SUBD_AO;
@@ -2077,8 +2040,8 @@ static int pci9118_attach(struct comedi_device *dev,
        devpriv->i8254_osc_base = 250;  /* 250ns=4MHz */
        devpriv->ai_maskharderr = 0x10a;
                                        /* default measure crash condition */
-       if (it->options[5])             /* disable some requested */
-               devpriv->ai_maskharderr &= ~it->options[5];
+       if (hw_err_mask)                /* disable some requested */
+               devpriv->ai_maskharderr &= ~hw_err_mask;
 
        switch (this_board->ai_maxdata) {
        case 0xffff:
@@ -2088,10 +2051,58 @@ static int pci9118_attach(struct comedi_device *dev,
                devpriv->ai16bits = 0;
                break;
        }
+
+       if (disable_irq)
+               irq = 0;
+       else
+               irq = pcidev->irq;
+       if (irq > 0) {
+               if (request_irq(irq, interrupt_pci9118, IRQF_SHARED,
+                               dev->board_name, dev)) {
+                       dev_warn(dev->class_dev,
+                                "unable to allocate IRQ %u, DISABLING IT\n",
+                                irq);
+               } else {
+                       dev->irq = irq;
+                       /* Enable AI commands */
+                       s = &dev->subdevices[0];
+                       s->subdev_flags |= SDF_CMD_READ;
+                       s->do_cmdtest = pci9118_ai_cmdtest;
+                       s->do_cmd = pci9118_ai_cmd;
+               }
+       }
+
        pci9118_report_attach(dev, irq);
        return 0;
 }
 
+static int pci9118_attach(struct comedi_device *dev,
+                         struct comedi_devconfig *it)
+{
+       struct pci9118_private *devpriv;
+       struct pci_dev *pcidev;
+       int ext_mux, disable_irq, master, softsshdelay, hw_err_mask;
+
+       ext_mux = it->options[2];
+       master = ((it->options[3] & 1) == 0);
+       disable_irq = ((it->options[3] & 2) != 0);
+       softsshdelay = it->options[4];
+       hw_err_mask = it->options[5];
+
+       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+       if (!devpriv)
+               return -ENOMEM;
+       dev->private = devpriv;
+
+       pcidev = pci9118_find_pci(dev, it);
+       if (!pcidev)
+               return -EIO;
+       comedi_set_hw_dev(dev, &pcidev->dev);
+
+       return pci9118_common_attach(dev, disable_irq, master, ext_mux,
+                                    softsshdelay, hw_err_mask);
+}
+
 static void pci9118_detach(struct comedi_device *dev)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);