|
@@ -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@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@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@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");
|