[PATCH] staging: comedi: update adl_pci7296 driver

H Hartley Sweeten hartleys at visionengravers.com
Fri Aug 3 18:33:01 UTC 2012


Currently this driver only supports the 96-channel PCI-7296.
The 24 and 48 channel PCI-7224 and PCI-7248 boards share the
same register map and just have less 8255 devices providing
the i/o channels.

This adds the PCI PnP support for the other boards in the
ADLink PCI-72xx series.

Also, remove the legacy attach using the comedi_config utility.
This driver now supports the comedi PCI auto config attach
mechanism and the legacy attach is not supported or required
by this driver.

Signed-off-by: H Hartley Sweeten <hsweeten at visionengravers.com>
Cc: Ian Abbott <abbotti at mev.co.uk>
Cc: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 drivers/staging/comedi/Kconfig               |   6 +-
 drivers/staging/comedi/drivers/adl_pci7296.c | 220 +++++++++++++++------------
 2 files changed, 123 insertions(+), 103 deletions(-)

diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
index 159de1d..d36486e 100644
--- a/drivers/staging/comedi/Kconfig
+++ b/drivers/staging/comedi/Kconfig
@@ -688,10 +688,12 @@ config COMEDI_ADL_PCI7X3X
 	  called adl_pci7x3x.
 
 config COMEDI_ADL_PCI7296
-	tristate "ADLink PCI-7296 96 ch. digital io board support"
+	tristate "ADLink PCI-72xx opto-22 compatible digital i/o board support"
 	select COMEDI_8255
 	---help---
-	  Enable support for ADlink PCI-7296 96 ch. digital io board support
+	  Enable support for ADlink PCI-72xx opto-22 compatible digital i/o
+	  boards. Supported boards include the 24-channel PCI-7224, 48-channel
+	  PCI-7248, and 96-channel PCI-7296.
 
 	  To compile this driver as a module, choose M here: the module will be
 	  called adl_pci7296.
diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c
index 19b47af..1b9ea54 100644
--- a/drivers/staging/comedi/drivers/adl_pci7296.c
+++ b/drivers/staging/comedi/drivers/adl_pci7296.c
@@ -1,148 +1,163 @@
 /*
-    comedi/drivers/adl_pci7296.c
+ * COMEDI driver for the ADLINK PCI-72xx series boards.
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds at schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
 
-    COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 2000 David A. Schleef <ds at schleef.org>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
 /*
 Driver: adl_pci7296
-Description: Driver for the Adlink PCI-7296 96 ch. digital io board
-Devices: [ADLink] PCI-7296 (adl_pci7296)
+Description: 24/48/96-Channel Opto-22 Compatible Digital I/O Boards
+Devices: (ADLink) PCI-7224 [adl_pci7224] - 24 channels
+	 (ADLink) PCI-7248 [adl_pci7248] - 48 channels
+	 (ADLink) PCI-7296 [adl_pci7296] - 96 channels
 Author: Jon Grierson <jd at renko.co.uk>
 Updated: Mon, 14 Apr 2008 15:05:56 +0100
 Status: testing
 
-Configuration Options:
-  [0] - PCI bus of device (optional)
-  [1] - PCI slot of device (optional)
-  If bus/slot is not specified, the first supported
-  PCI device found will be used.
+This driver only attaches using the PCI PnP auto config support
+in the comedi core. The module parameter 'comedi_autoconfig'
+must be 1 (default) to enable this feature. The COMEDI_DEVCONFIG
+ioctl, used by the comedi_config utility, is not supported by
+this driver.
+
+These boards also have an 8254 programmable timer/counter chip.
+This chip is not currently supported by this driver.
+
+Interrupt support for these boards is also not currently supported.
+
+Configuration Options: not applicable
 */
 
 #include "../comedidev.h"
-#include <linux/kernel.h>
 
 #include "8255.h"
-/* #include "8253.h" */
 
-#define PORT1A 0
-#define PORT2A 4
-#define PORT3A 8
-#define PORT4A 12
+/*
+ * PCI Device ID's supported by this driver
+ */
+#define PCI_DEVICE_ID_PCI7224	0x7224
+#define PCI_DEVICE_ID_PCI7248	0x7248
+#define PCI_DEVICE_ID_PCI7296	0x7296
+
+struct adl_pci7296_boardinfo {
+	const char *name;
+	unsigned short device;
+	int nsubdevs;
+};
 
-#define PCI_DEVICE_ID_PCI7296 0x7296
+static const struct adl_pci7296_boardinfo adl_pci7296_boards[] = {
+	{
+		.name		= "adl_pci7224",
+		.device		= PCI_DEVICE_ID_PCI7224,
+		.nsubdevs	= 1,
+	}, {
+		.name		= "adl_pci7248",
+		.device		= PCI_DEVICE_ID_PCI7248,
+		.nsubdevs	= 2,
+	}, {
+		.name		= "adl_pci7296",
+		.device		= PCI_DEVICE_ID_PCI7296,
+		.nsubdevs	= 4,
+	},
+};
 
-static struct pci_dev *adl_pci7296_find_pci(struct comedi_device *dev,
-					    struct comedi_devconfig *it)
+static const void *adl_pci7296_find_boardinfo(struct comedi_device *dev,
+					      struct pci_dev *pcidev)
 {
-	struct pci_dev *pcidev = NULL;
-	int bus = it->options[0];
-	int slot = it->options[1];
-
-	for_each_pci_dev(pcidev) {
-		if (pcidev->vendor != PCI_VENDOR_ID_ADLINK ||
-		    pcidev->device != PCI_DEVICE_ID_PCI7296)
-			continue;
-		if (bus || slot) {
-			/* requested particular bus/slot */
-			if (pcidev->bus->number != bus ||
-			    PCI_SLOT(pcidev->devfn) != slot)
-				continue;
-		}
-		return pcidev;
+	const struct adl_pci7296_boardinfo *board;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(adl_pci7296_boards); i++) {
+		board = &adl_pci7296_boards[i];
+		if (pcidev->device == board->device)
+			return board;
 	}
-	printk(KERN_ERR
-		"comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
-	       dev->minor, bus, slot);
 	return NULL;
 }
 
-static int adl_pci7296_attach(struct comedi_device *dev,
-			      struct comedi_devconfig *it)
+static int adl_pci7296_attach_pci(struct comedi_device *dev,
+				  struct pci_dev *pcidev)
 {
-	struct pci_dev *pcidev;
+	const struct adl_pci7296_boardinfo *board;
 	struct comedi_subdevice *s;
 	int ret;
+	int i;
 
-	printk(KERN_INFO "comedi%d: attach adl_pci7432\n", dev->minor);
+	comedi_set_hw_dev(dev, &pcidev->dev);
 
-	dev->board_name = "pci7432";
+	board = adl_pci7296_find_boardinfo(dev, pcidev);
+	if (!board)
+		return -ENODEV;
+	dev->board_ptr = board;
+	dev->board_name = board->name;
 
-	ret = comedi_alloc_subdevices(dev, 4);
+	ret = comedi_pci_enable(pcidev, dev->board_name);
 	if (ret)
 		return ret;
-
-	pcidev = adl_pci7296_find_pci(dev, it);
-	if (!pcidev)
-		return -EIO;
-	comedi_set_hw_dev(dev, &pcidev->dev);
-
-	if (comedi_pci_enable(pcidev, "adl_pci7296") < 0) {
-		printk(KERN_ERR
-			"comedi%d: Failed to enable PCI device and request regions\n",
-			dev->minor);
-		return -EIO;
-	}
-
 	dev->iobase = pci_resource_start(pcidev, 2);
-	printk(KERN_INFO "comedi: base addr %4lx\n", dev->iobase);
-
-	/*  four 8255 digital io subdevices */
-	s = dev->subdevices + 0;
-	subdev_8255_init(dev, s, NULL, (unsigned long)(dev->iobase));
 
-	s = dev->subdevices + 1;
-	ret = subdev_8255_init(dev, s, NULL,
-				(unsigned long)(dev->iobase + PORT2A));
-	if (ret < 0)
-		return ret;
-
-	s = dev->subdevices + 2;
-	ret = subdev_8255_init(dev, s, NULL,
-				(unsigned long)(dev->iobase + PORT3A));
-	if (ret < 0)
+	/*
+	 * One, two, or four subdevices are setup by this driver depending
+	 * on the number of channels provided by the board. Each subdevice
+	 * has 24 channels supported by the 8255 module.
+	 */
+	ret = comedi_alloc_subdevices(dev, board->nsubdevs);
+	if (ret)
 		return ret;
 
-	s = dev->subdevices + 3;
-	ret = subdev_8255_init(dev, s, NULL,
-				(unsigned long)(dev->iobase + PORT4A));
-	if (ret < 0)
-		return ret;
+	for (i = 0; i < board->nsubdevs; i++) {
+		s = dev->subdevices + i;
+		ret = subdev_8255_init(dev, s, NULL, dev->iobase + (i * 4));
+		if (ret)
+			return ret;
+	}
 
-	printk(KERN_DEBUG "comedi%d: adl_pci7432 attached\n", dev->minor);
+	dev_info(dev->class_dev, "%s attached (%d digital i/o channels)\n",
+		dev->board_name, board->nsubdevs * 24);
 
 	return 0;
 }
 
+static int adl_pci7296_attach(struct comedi_device *dev,
+			      struct comedi_devconfig *it)
+{
+	dev_warn(dev->class_dev,
+		"This driver does not support attach using comedi_config\n");
+
+	return -ENOSYS;
+}
+
 static void adl_pci7296_detach(struct comedi_device *dev)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	const struct adl_pci7296_boardinfo *board = comedi_board(dev);
+	struct comedi_subdevice *s;
+	int i;
 
+	if (dev->subdevices) {
+		for (i = 0; i < board->nsubdevs; i++) {
+			s = dev->subdevices + i;
+			subdev_8255_cleanup(dev, s);
+		}
+	}
 	if (pcidev) {
 		if (dev->iobase)
 			comedi_pci_disable(pcidev);
-		pci_dev_put(pcidev);
-	}
-	if (dev->subdevices) {
-		subdev_8255_cleanup(dev, dev->subdevices + 0);
-		subdev_8255_cleanup(dev, dev->subdevices + 1);
-		subdev_8255_cleanup(dev, dev->subdevices + 2);
-		subdev_8255_cleanup(dev, dev->subdevices + 3);
 	}
 }
 
@@ -150,6 +165,7 @@ static struct comedi_driver adl_pci7296_driver = {
 	.driver_name	= "adl_pci7296",
 	.module		= THIS_MODULE,
 	.attach		= adl_pci7296_attach,
+	.attach_pci	= adl_pci7296_attach_pci,
 	.detach		= adl_pci7296_detach,
 };
 
@@ -165,6 +181,8 @@ static void __devexit adl_pci7296_pci_remove(struct pci_dev *dev)
 }
 
 static DEFINE_PCI_DEVICE_TABLE(adl_pci7296_pci_table) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7224) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7248) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7296) },
 	{ 0 }
 };
@@ -178,6 +196,6 @@ static struct pci_driver adl_pci7296_pci_driver = {
 };
 module_comedi_pci_driver(adl_pci7296_driver, adl_pci7296_pci_driver);
 
+MODULE_DESCRIPTION("ADLINK PCI-72xx Opto-22 Compatible Digital I/O Boards");
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
 MODULE_LICENSE("GPL");
-- 
1.7.11




More information about the devel mailing list