New driver from Yoshiya Matsuzaka <matsuzay@mail.tains.tohoku.ac.jp>
authorFrank Mori Hess <fmhess@speakeasy.net>
Tue, 31 Jul 2007 14:08:15 +0000 (14:08 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Tue, 31 Jul 2007 14:08:15 +0000 (14:08 +0000)
for Measurement Computing PCI-DIOxx series.

AUTHORS
comedi/drivers/Kbuild
comedi/drivers/Makefile.am
comedi/drivers/cb_pcidio.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
index 3c9d0a3574e1845280b6a7a1870d009703fa61e7..e428b5e23d8b7473a40c04d1d60b0f0e0f5bcf27 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -29,6 +29,7 @@ Brent Ledvina <bml22@cornell.edu>
 Simone Mannori <smannori@f2n.it>
 Ivan Martinez <ivanmr@altavista.com>
 Luis Martínez <luimarma@marcosa.e.telefonica.net>
+Yoshiya Matsuzaka <matsuzay@mail.tains.tohoku.ac.jp>
 Pablo Mejia <pablo@cctechnol.com>
 J.P. Mellor <jpmellor@rose-hulman.edu>
 Sam Moore <sam@tx.ncsu.edu>
index 57513634a94adcce7be42bd4bc263bb7e7cb1142..500248b93ba1e535f28e1d9b11ff2244dc62f1b3 100644 (file)
@@ -42,6 +42,7 @@ obj-m += c6xdigio.o
 obj-m += cb_pcidas.o
 obj-m += cb_pcidas64.o
 obj-m += cb_pcidda.o
+obj-m += cb_pcidio.o
 obj-m += cb_pcimdas.o
 obj-m += cb_pcimdda.o
 obj-m += comedi_bond.o
index cc3420306995de8e17862bdc0a7cb8b66834fbc8..22bfeb4ecdc16782470c5e8bfd770ba30ab893e2 100644 (file)
@@ -112,6 +112,7 @@ module_PROGRAMS = \
  cb_pcidas.ko \
  cb_pcidas64.ko \
  cb_pcidda.ko \
+ cb_pcidio.ko \
  cb_pcimdas.ko \
  cb_pcimdda.ko \
  comedi_bond.ko \
@@ -203,6 +204,7 @@ c6xdigio_ko_SOURCES = c6xdigio.c
 cb_pcidas_ko_SOURCES = cb_pcidas.c
 cb_pcidas64_ko_SOURCES = cb_pcidas64.c
 cb_pcidda_ko_SOURCES = cb_pcidda.c
+cb_pcidio_ko_SOURCES = cb_pcidio.c
 cb_pcimdas_ko_SOURCES = cb_pcimdas.c
 cb_pcimdda_ko_SOURCES = cb_pcimdda.c
 cb_das16_cs_ko_SOURCES = cb_das16_cs.c
diff --git a/comedi/drivers/cb_pcidio.c b/comedi/drivers/cb_pcidio.c
new file mode 100644 (file)
index 0000000..398a3e9
--- /dev/null
@@ -0,0 +1,387 @@
+/*
+    comedi/drivers/cb_pcidio.c
+    A Comedi driver for PCI-DIO24H & PCI-DIO48H of ComputerBoards (currently MeasurementComputing)
+
+    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: cb_pcidio.o
+Description: ComputerBoards' DIO boards with PCI interface
+Devices: [ComputerBoards (currently MeasurementComputing)]
+       PCI-DIO24H, PCI-DIO48H
+Author: Yoshiya Matsuzaka
+Updated: Wed, 25 Jul 2007 15:15:41 +0900
+Status: experimental
+
+This driver has been modified from skel.c of comedi-0.7.70.
+
+Configuration Options:
+  none
+*/
+
+/*
+ * The previous block comment is used to automatically generate
+ * documentation in Comedi and Comedilib.  The fields:
+ *
+ * Driver: the name of the driver
+ * Description: a short phrase describing the driver.  Don't list boards.
+ * Devices: a full list of the boards that attempt to be supported by
+ *   the driver.  Format is "(manufacturer) board name [comedi name]",
+ *   where comedi_name is the name that is used to configure the board.
+ *   See the comment near board_name: in the comedi_driver structure
+ *   below.  If (manufacturer) or [comedi name] is missing, the previous
+ *   value is used.
+ * Author: you
+ * Updated: date when the _documentation_ was last updated.  Use 'date -R'
+ *   to get a value for this.
+ * Status: a one-word description of the status.  Valid values are:
+ *   works - driver works correctly on most boards supported, and
+ *     passes comedi_test.
+ *   unknown - unknown.  Usually put there by ds.
+ *   experimental - may not work in any particular release.  Author
+ *     probably wants assistance testing it.
+ *   bitrotten - driver has not been update in a long time, probably
+ *     doesn't work, and probably is missing support for significant
+ *     Comedi interface features.
+ *   untested - author probably wrote it "blind", and is believed to
+ *     work, but no confirmation.
+ *
+ * These headers should be followed by a blank line, and any comments
+ * you wish to say about the driver.  The comment area is the place
+ * to put any known bugs, limitations, unsupported features, supported
+ * command triggers, whether or not commands are supported on particular
+ * subdevices, etc.
+ *
+ * Somewhere in the comment should be information about configuration
+ * options that are used with comedi_config.
+ */
+
+
+
+/*------------------------------ HEADER FILES ---------------------------------*/
+#include <linux/comedidev.h>
+#include <linux/pci.h> /* for PCI devices */
+
+
+
+/*-------------------------- MACROS and DATATYPES -----------------------------*/
+#define PCI_VENDOR_ID_CB       0x1307
+
+/*
+ * Board descriptions for two imaginary boards.  Describing the
+ * boards in this way is optional, and completely driver-dependent.
+ * Some drivers use arrays such as this, other do not.
+ */
+typedef struct pcidio_board_struct{
+       char *name;             // anme of the board
+       int n_8255;             // number of 8255 chips on board
+
+       // indices of base address regions      
+       int pcicontroler_badrindex;
+       int dioregs_badrindex;
+} pcidio_board;
+
+
+
+static pcidio_board pcidio_boards[] = {
+       {
+       name:           "pci-dio24h",
+       n_8255:         1,
+       pcicontroler_badrindex: 1,      
+       dioregs_badrindex:              2,
+       },
+       {
+       name:           "pci-dio48h",
+       n_8255:         2,
+       pcicontroler_badrindex: 0,
+       dioregs_badrindex:              1,
+       },
+};
+
+
+
+/* This is used by modprobe to translate PCI IDs to drivers.  Should
+ * only be used for PCI and ISA-PnP devices */
+/* Please add your PCI vendor ID to comedidev.h, and it will be forwarded
+ * upstream. */
+static struct pci_device_id pcidio_pci_table[] __devinitdata = {
+       { PCI_VENDOR_ID_CB, 0x0014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+       { PCI_VENDOR_ID_CB, 0x000b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+       { 0 }
+};
+MODULE_DEVICE_TABLE(pci, pcidio_pci_table);
+
+
+
+/*
+ * Useful for shorthand access to the particular board structure
+ */
+#define thisboard ((pcidio_board *)dev->board_ptr)
+
+
+
+/* this structure is for data unique to this hardware driver.  If
+   several hardware drivers keep similar information in this structure,
+   feel free to suggest moving the variable to the comedi_device struct.  */
+typedef struct{
+       int data;                                               // curently unused
+
+       /* would be useful for a PCI device */
+       struct pci_dev *pci_dev;
+
+       /* used for DO readback, curently unused */
+       lsampl_t do_readback[4];        /* up to 4 lsampl_t suffice to hold 96 bits for PCI-DIO96 */
+         
+       unsigned long dio_reg_base;             // address of port A of the first 8255 chip on board
+} pcidio_private;
+
+
+
+/*
+ * most drivers define the following macro to make it easy to
+ * access the private structure.
+ */
+#define devpriv ((pcidio_private *)dev->private)
+
+
+
+/*
+ * The comedi_driver structure tells the Comedi core module
+ * which functions to call to configure/deconfigure (attach/detach)
+ * the board, and also about the kernel module that contains
+ * the device code.
+ */
+static int pcidio_attach(comedi_device *dev,comedi_devconfig *it);
+static int pcidio_detach(comedi_device *dev);
+static comedi_driver driver_cb_pcidio={
+       driver_name:    "cb_pcidio",
+       module:         THIS_MODULE,
+       attach:         pcidio_attach,
+       detach:         pcidio_detach,
+/* It is not necessary to implement the following members if you are
+ * writing a driver for a ISA PnP or PCI card */
+       /* Most drivers will support multiple types of boards by
+        * having an array of board structures.  These were defined
+        * in pcidio_boards[] above.  Note that the element 'name'
+        * was first in the structure -- Comedi uses this fact to
+        * extract the name of the board without knowing any details
+        * about the structure except for its length.
+        * When a device is attached (by comedi_config), the name
+        * of the device is given to Comedi, and Comedi tries to
+        * match it by going through the list of board names.  If
+        * there is a match, the address of the pointer is put
+        * into dev->board_ptr and driver->attach() is called.
+        *
+        * Note that these are not necessary if you can determine
+        * the type of board in software.  ISA PnP, PCI, and PCMCIA
+        * devices are such boards.
+        */
+// The following fields should NOT be initialized if you are dealing with PCI devices
+//     board_name:     pcidio_boards,
+//     offset:         sizeof(pcidio_board),
+//     num_names:      sizeof(pcidio_boards) / sizeof(pcidio_board),
+};
+
+
+
+/*------------------------------- FUNCTIONS -----------------------------------*/
+
+// The 2 functions below are currently unsed
+static int pcidio_dio_insn_bits(comedi_device *dev,comedi_subdevice *s,
+       comedi_insn *insn,lsampl_t *data);
+static int pcidio_dio_insn_config(comedi_device *dev,comedi_subdevice *s,
+       comedi_insn *insn,lsampl_t *data);
+
+
+
+/*
+ * Attach is called by the Comedi core to configure the driver
+ * for a particular board.  If you specified a board_name array
+ * in the driver structure, dev->board_ptr contains that
+ * address.
+ */
+static int pcidio_attach(comedi_device *dev, comedi_devconfig *it)
+{
+struct pci_dev* pcidev = NULL;
+int index;
+
+       printk("comedi%d: pcidio: \n", dev->minor);
+/*
+ * If you can probe the device to determine what device in a series
+ * it is, this is the place to do it.  Otherwise, dev->board_ptr
+ * should already be initialized.
+ */
+/*
+ * Probe the device to determine what device in the series it is.
+ */
+
+       for(pcidev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, NULL); pcidev != NULL ;
+               pcidev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pcidev))
+       {
+               // is it not a computer boards card?
+               if(pcidev->vendor != PCI_VENDOR_ID_CB)
+                       continue;
+               // loop through cards supported by this driver
+               for(index = 0; index < sizeof pcidio_boards / sizeof(pcidio_board); index++)
+               {
+                       if(pcidio_pci_table[index].device != pcidev->device)
+                               continue;
+
+                       // was a particular bus/slot requested?
+                       if(it->options[0] || it->options[1])
+                       {
+                               // are we on the wrong bus/slot?
+                               if(pcidev->bus->number != it->options[0] ||
+                                  PCI_SLOT(pcidev->devfn) != it->options[1])
+                               {
+                                       continue;
+                               }
+                       }
+                       dev->board_ptr = pcidio_boards + index;
+                       goto found;
+               }
+       }
+
+       printk("No supported ComputerBoards/MeasurementComputing card found on "
+               "requested position\n");
+       return -EIO;
+
+found:
+
+/*
+ * Allocate the private structure area.  alloc_private() is a
+ * convenient macro defined in comedidev.h.
+ */
+       if(alloc_private(dev, sizeof(pcidio_private)) < 0)
+               return -ENOMEM;
+
+       devpriv->pci_dev = pcidev;
+       printk("Found %s on bus %i, slot %i\n", pcidio_boards[index].name,
+               devpriv->pci_dev->bus->number, PCI_SLOT(devpriv->pci_dev->devfn));
+       devpriv->dio_reg_base 
+         = pci_resource_start(devpriv->pci_dev, pcidio_boards[index].dioregs_badrindex);
+
+/*
+ * Initialize dev->board_name.  Note that we can use the "thisboard"
+ * macro now, since we just initialized it in the last line.
+ */
+       dev->board_name = thisboard->name;
+
+/*
+ * Allocate the subdevice structures.  alloc_subdevice() is a
+ * convenient macro defined in comedidev.h.
+ */
+       if(alloc_subdevices(dev, thisboard->n_8255) < 0)
+               return -ENOMEM;
+       
+       int i;
+       for(i = 0; i < thisboard->n_8255; i++)
+       {
+               subdev_8255_init(dev, dev->subdevices + i,
+                       NULL, devpriv->dio_reg_base + i * 4);
+               printk(" subdev %d: base = 0x%lx\n", i, devpriv->dio_reg_base + i * 4);
+       }
+
+       printk("attached\n");
+       return 1;
+}
+
+
+
+/*
+ * _detach is called to deconfigure a device.  It should deallocate
+ * resources.  
+ * This function is also called when _attach() fails, so it should be
+ * careful not to release resources that were not necessarily
+ * allocated by _attach().  dev->private and dev->subdevices are
+ * deallocated automatically by the core.
+ */
+static int pcidio_detach(comedi_device *dev)
+{
+       printk("comedi%d: skel: remove\n",dev->minor);
+       return 0;
+}
+
+
+
+/* DIO devices are slightly special.  Although it is possible to
+ * implement the insn_read/insn_write interface, it is much more
+ * useful to applications if you implement the insn_bits interface.
+ * This allows packed reading/writing of the DIO channels.  The
+ * comedi core can convert between insn_bits and insn_read/write */
+static int pcidio_dio_insn_bits(comedi_device *dev,comedi_subdevice *s,
+       comedi_insn *insn,lsampl_t *data)
+{
+       if(insn->n!=2)return -EINVAL;
+
+       /* The insn data is a mask in data[0] and the new data
+        * in data[1], each channel cooresponding to a bit. */
+       if(data[0]){
+               s->state &= ~data[0];
+               s->state |= data[0]&data[1];
+               /* Write out the new digital output lines */
+               //outw(s->state,dev->iobase + SKEL_DIO);
+       }
+
+       /* on return, data[1] contains the value of the digital
+        * input and output lines. */
+       //data[1]=inw(dev->iobase + SKEL_DIO);
+       /* or we could just return the software copy of the output values if
+        * it was a purely digital output subdevice */
+       //data[1]=s->state;
+
+       return 2;
+}
+
+static int pcidio_dio_insn_config(comedi_device *dev,comedi_subdevice *s,
+       comedi_insn *insn,lsampl_t *data)
+{
+       int chan=CR_CHAN(insn->chanspec);
+
+       /* The input or output configuration of each digital line is
+        * configured by a special insn_config instruction.  chanspec
+        * contains the channel to be changed, and data[0] contains the
+        * value COMEDI_INPUT or COMEDI_OUTPUT. */
+       switch(data[0])
+       {
+       case INSN_CONFIG_DIO_OUTPUT:
+               s->io_bits |= 1<<chan;
+               break;
+       case INSN_CONFIG_DIO_INPUT:
+               s->io_bits &= ~(1<<chan);
+               break;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] = (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
+               return insn->n;
+               break;
+       default:
+               return -EINVAL;
+               break;
+       }
+       //outw(s->io_bits,dev->iobase + SKEL_DIO_CONFIG);
+
+       return insn->n;
+}
+
+/*
+ * A convenient macro that defines init_module() and cleanup_module(),
+ * as necessary.
+ */
+COMEDI_INITCLEANUP(driver_cb_pcidio);
+