staging: comedi: ni_mio_cs: convert to auto attach
authorH Hartley Sweeten <hsweeten@visionengravers.com>
Thu, 31 Jan 2013 00:38:02 +0000 (17:38 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 4 Feb 2013 01:29:47 +0000 (17:29 -0800)
Convert this pcmcia driver to the comedi auto attach mechanism.

This allows getting rid of the "hack" needed to pass the pcmcia_device
pointer from the pcmcia_driver to the comedi_driver.

We still need the boardinfo because ni_mio_common.c uses it. Cleanup
ni_getboardtype() so it returns a pointer to the boardinto instead
of the index.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/comedi/drivers/ni_mio_cs.c

index 07e4bd8..4151aba 100644 (file)
@@ -207,37 +207,62 @@ static uint16_t mio_cs_win_in(struct comedi_device *dev, int addr)
 
 #include "ni_mio_common.c"
 
-static struct pcmcia_device *cur_dev;
-
-static int ni_getboardtype(struct comedi_device *dev,
-                          struct pcmcia_device *link)
+static const void *ni_getboardtype(struct comedi_device *dev,
+                                  struct pcmcia_device *link)
 {
+       static const struct ni_board_struct *board;
        int i;
 
-       for (i = 0; i < n_ni_boards; i++) {
-               if (ni_boards[i].device_id == link->card_id)
-                       return i;
+       for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
+               board = &ni_boards[i];
+               if (board->device_id == link->card_id)
+                       return board;
        }
+       return NULL;
+}
+
+static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data)
+{
+       int base, ret;
 
-       dev_err(dev->class_dev,
-               "unknown board 0x%04x -- pretend it is a ", link->card_id);
+       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
 
-       return 0;
+       for (base = 0x000; base < 0x400; base += 0x20) {
+               p_dev->resource[0]->start = base;
+               ret = pcmcia_request_io(p_dev);
+               if (!ret)
+                       return 0;
+       }
+       return -ENODEV;
 }
 
-static int mio_cs_attach(struct comedi_device *dev,
-                        struct comedi_devconfig *it)
+static int mio_cs_auto_attach(struct comedi_device *dev,
+                             unsigned long context)
 {
+       struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
+       static const struct ni_board_struct *board;
        struct ni_private *devpriv;
-       struct pcmcia_device *link;
        int ret;
 
-       link = cur_dev;         /* XXX hack */
-       if (!link)
-               return -EIO;
+       board = ni_getboardtype(dev, link);
+       if (!board)
+               return -ENODEV;
+       dev->board_ptr = board;
+       dev->board_name = board->name;
+
+       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
+       ret = pcmcia_loop_config(link, mio_pcmcia_config_loop, NULL);
+       if (ret)
+               return ret;
+
+       if (!link->irq)
+               return -EINVAL;
 
-       dev->board_ptr = ni_boards + ni_getboardtype(dev, link);
-       dev->board_name = boardtype.name;
+       ret = pcmcia_enable_device(link);
+       if (ret)
+               return ret;
        dev->iobase = link->resource[0]->start;
 
        ret = request_irq(link->irq, ni_E_interrupt, NI_E_IRQ_FLAGS,
@@ -261,57 +286,25 @@ static int mio_cs_attach(struct comedi_device *dev,
 
 static void mio_cs_detach(struct comedi_device *dev)
 {
+       struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
+
        mio_common_detach(dev);
        if (dev->irq)
                free_irq(dev->irq, dev);
+       if (dev->iobase)
+               pcmcia_disable_device(link);
 }
 
 static struct comedi_driver driver_ni_mio_cs = {
        .driver_name    = "ni_mio_cs",
        .module         = THIS_MODULE,
-       .attach         = mio_cs_attach,
+       .auto_attach    = mio_cs_auto_attach,
        .detach         = mio_cs_detach,
 };
 
-static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data)
-{
-       int base, ret;
-
-       p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-       p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
-
-       for (base = 0x000; base < 0x400; base += 0x20) {
-               p_dev->resource[0]->start = base;
-               ret = pcmcia_request_io(p_dev);
-               if (!ret)
-                       return 0;
-       }
-       return -ENODEV;
-}
-
 static int cs_attach(struct pcmcia_device *link)
 {
-       int ret;
-
-       cur_dev = link;
-
-       link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
-
-       ret = pcmcia_loop_config(link, mio_pcmcia_config_loop, NULL);
-       if (ret) {
-               dev_warn(&link->dev, "no configuration found\n");
-               return ret;
-       }
-
-       if (!link->irq)
-               dev_info(&link->dev, "no IRQ available\n");
-
-       return pcmcia_enable_device(link);
-}
-
-static void cs_detach(struct pcmcia_device *link)
-{
-       pcmcia_disable_device(link);
+       return comedi_pcmcia_auto_config(link, &driver_ni_mio_cs);
 }
 
 static const struct pcmcia_device_id ni_mio_cs_ids[] = {
@@ -329,7 +322,7 @@ static struct pcmcia_driver ni_mio_cs_driver = {
        .owner          = THIS_MODULE,
        .id_table       = ni_mio_cs_ids,
        .probe          = cs_attach,
-       .remove         = cs_detach,
+       .remove         = comedi_pcmcia_auto_unconfig,
 };
 module_comedi_pcmcia_driver(driver_ni_mio_cs, ni_mio_cs_driver);