Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2bdaef1a authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman
Browse files

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: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 1f021e1f
Loading
Loading
Loading
Loading
+49 −66
Original line number Diff line number Diff line
@@ -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,
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)
{
	const struct das16cs_board *thisboard;
	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)
{
	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;

	/* Do we need to allocate an interrupt? */
	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;

	dev->board_ptr = das16cs_probe(dev, link);
	if (!dev->board_ptr)
		return -EIO;
	thisboard = comedi_board(dev);
	ret = pcmcia_loop_config(link, das16cs_pcmcia_config_loop, NULL);
	if (ret)
		return ret;

	dev->board_name = thisboard->name;
	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>");