diff options
author | H Hartley Sweeten <hsweeten@visionengravers.com> | 2013-01-30 15:23:27 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-01-31 10:40:41 +0100 |
commit | 2bdaef1afc15ae675a1d26e19d2b77bde215ef4a (patch) | |
tree | 2cf778a2cff894093589e3095a12e7b5d8d941a3 | |
parent | 1f021e1f3b187586e457b4584d0e5f0f5ca5fa15 (diff) | |
download | linux-2bdaef1afc15ae675a1d26e19d2b77bde215ef4a.tar.gz |
staging: comedi: cb_das16_cs: convert to auto attach
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.
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>
-rw-r--r-- | drivers/staging/comedi/drivers/cb_das16_cs.c | 115 |
1 files changed, 49 insertions, 66 deletions
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index e253fc03cefa..efff05954133 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -40,9 +40,10 @@ Status: experimental #include <linux/interrupt.h> #include <linux/slab.h> -#include "../comedidev.h" #include <linux/delay.h> +#include "../comedidev.h" + #include <pcmcia/cistpl.h> #include <pcmcia/ds.h> @@ -89,8 +90,6 @@ struct das16cs_private { unsigned short status2; }; -static struct pcmcia_device *cur_dev; - static const struct comedi_lrange das16cs_ai_range = { 4, { BIP_RANGE(10), @@ -383,45 +382,62 @@ static int das16cs_dio_insn_config(struct comedi_device *dev, return insn->n; } -static const struct das16cs_board *das16cs_probe(struct comedi_device *dev, - struct pcmcia_device *link) +static const void *das16cs_find_boardinfo(struct comedi_device *dev, + struct pcmcia_device *link) { + const struct das16cs_board *board; int i; for (i = 0; i < ARRAY_SIZE(das16cs_boards); i++) { - if (das16cs_boards[i].device_id == link->card_id) - return das16cs_boards + i; + board = &das16cs_boards[i]; + if (board->device_id == link->card_id) + return board; } - dev_dbg(dev->class_dev, "unknown board!\n"); - return NULL; } -static int das16cs_attach(struct comedi_device *dev, - struct comedi_devconfig *it) +static int das16cs_pcmcia_config_loop(struct pcmcia_device *p_dev, + void *priv_data) +{ + if (p_dev->config_index == 0) + return -EINVAL; + + return pcmcia_request_io(p_dev); +} + +static int das16cs_auto_attach(struct comedi_device *dev, + unsigned long context) { - const struct das16cs_board *thisboard; + struct pcmcia_device *link = comedi_to_pcmcia_dev(dev); + const struct das16cs_board *board; struct das16cs_private *devpriv; - struct pcmcia_device *link; struct comedi_subdevice *s; int ret; - link = cur_dev; /* XXX hack */ - if (!link) - return -EIO; + board = das16cs_find_boardinfo(dev, link); + if (!board) + return -ENODEV; + dev->board_ptr = board; + dev->board_name = board->name; - dev->board_ptr = das16cs_probe(dev, link); - if (!dev->board_ptr) - return -EIO; - thisboard = comedi_board(dev); + /* Do we need to allocate an interrupt? */ + link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; - dev->board_name = thisboard->name; + ret = pcmcia_loop_config(link, das16cs_pcmcia_config_loop, NULL); + if (ret) + return ret; + + if (!link->irq) + return -EINVAL; + ret = pcmcia_enable_device(link); + if (ret) + return ret; dev->iobase = link->resource[0]->start; - ret = request_irq(link->irq, das16cs_interrupt, - IRQF_SHARED, "cb_das16_cs", dev); + ret = request_irq(link->irq, das16cs_interrupt, IRQF_SHARED, + dev->board_name, dev); if (ret < 0) return ret; dev->irq = link->irq; @@ -450,10 +466,10 @@ static int das16cs_attach(struct comedi_device *dev, s = &dev->subdevices[1]; /* analog output subdevice */ - if (thisboard->n_ao_chans) { + if (board->n_ao_chans) { s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = thisboard->n_ao_chans; + s->n_chan = board->n_ao_chans; s->maxdata = 0xffff; s->range_table = &range_bipolar10; s->insn_write = &das16cs_ao_winsn; @@ -481,56 +497,24 @@ static int das16cs_attach(struct comedi_device *dev, static void das16cs_detach(struct comedi_device *dev) { + struct pcmcia_device *link = comedi_to_pcmcia_dev(dev); + if (dev->irq) free_irq(dev->irq, dev); + if (dev->iobase) + pcmcia_disable_device(link); } static struct comedi_driver driver_das16cs = { .driver_name = "cb_das16_cs", .module = THIS_MODULE, - .attach = das16cs_attach, + .auto_attach = das16cs_auto_attach, .detach = das16cs_detach, }; -static int das16cs_pcmcia_config_loop(struct pcmcia_device *p_dev, - void *priv_data) -{ - if (p_dev->config_index == 0) - return -EINVAL; - - return pcmcia_request_io(p_dev); -} - static int das16cs_pcmcia_attach(struct pcmcia_device *link) { - int ret; - - /* Do we need to allocate an interrupt? */ - link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; - - ret = pcmcia_loop_config(link, das16cs_pcmcia_config_loop, NULL); - if (ret) - goto failed; - - if (!link->irq) - goto failed; - - ret = pcmcia_enable_device(link); - if (ret) - goto failed; - - cur_dev = link; - return 0; - -failed: - pcmcia_disable_device(link); - return ret; -} - -static void das16cs_pcmcia_detach(struct pcmcia_device *link) -{ - pcmcia_disable_device(link); - cur_dev = NULL; + return comedi_pcmcia_auto_config(link, &driver_das16cs); } static const struct pcmcia_device_id das16cs_id_table[] = { @@ -543,11 +527,10 @@ MODULE_DEVICE_TABLE(pcmcia, das16cs_id_table); static struct pcmcia_driver das16cs_driver = { .name = "cb_das16_cs", .owner = THIS_MODULE, - .probe = das16cs_pcmcia_attach, - .remove = das16cs_pcmcia_detach, .id_table = das16cs_id_table, + .probe = das16cs_pcmcia_attach, + .remove = comedi_pcmcia_auto_unconfig, }; - module_comedi_pcmcia_driver(driver_das16cs, das16cs_driver); MODULE_AUTHOR("David A. Schleef <ds@schleef.org>"); |