aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/comedi/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/comedi/drivers')
-rw-r--r--drivers/staging/comedi/drivers/8253.h5
-rw-r--r--drivers/staging/comedi/drivers/8255.c11
-rw-r--r--drivers/staging/comedi/drivers/8255.h5
-rw-r--r--drivers/staging/comedi/drivers/8255_pci.c7
-rw-r--r--drivers/staging/comedi/drivers/Makefile5
-rw-r--r--drivers/staging/comedi/drivers/acl7225b.c136
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c4
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c4
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c4
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c4
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c4
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c4
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c4
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c4
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.c61
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.h44
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_eeprom.c9
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c4
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c4
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c4
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c4
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c10
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c4
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c1376
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1032.c7
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1516.c8
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_16xx.c7
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_2032.c8
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_2200.c8
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3120.c5
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3501.c7
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3xxx.c1409
-rw-r--r--drivers/staging/comedi/drivers/addi_watchdog.c8
-rw-r--r--drivers/staging/comedi/drivers/adl_pci6208.c4
-rw-r--r--drivers/staging/comedi/drivers/adl_pci7x3x.c4
-rw-r--r--drivers/staging/comedi/drivers/adl_pci8164.c4
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9111.c4
-rw-r--r--drivers/staging/comedi/drivers/adq12b.c5
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1723.c9
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1724.c7
-rw-r--r--drivers/staging/comedi/drivers/adv_pci_dio.c8
-rw-r--r--drivers/staging/comedi/drivers/aio_aio12_8.c12
-rw-r--r--drivers/staging/comedi/drivers/aio_iiro_16.c4
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200.c5
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200.h5
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200_common.c33
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200_pci.c5
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc236.c6
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc263.c5
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci224.c5
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci230.c5
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci263.c5
-rw-r--r--drivers/staging/comedi/drivers/c6xdigio.c5
-rw-r--r--drivers/staging/comedi/drivers/cb_das16_cs.c4
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas.c7
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas64.c8
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidda.c13
-rw-r--r--drivers/staging/comedi/drivers/cb_pcimdas.c5
-rw-r--r--drivers/staging/comedi/drivers/cb_pcimdda.c13
-rw-r--r--drivers/staging/comedi/drivers/comedi_bond.c5
-rw-r--r--drivers/staging/comedi/drivers/comedi_fc.c7
-rw-r--r--drivers/staging/comedi/drivers/comedi_fc.h7
-rw-r--r--drivers/staging/comedi/drivers/comedi_parport.c5
-rw-r--r--drivers/staging/comedi/drivers/comedi_test.c7
-rw-r--r--drivers/staging/comedi/drivers/contec_pci_dio.c5
-rw-r--r--drivers/staging/comedi/drivers/daqboard2000.c30
-rw-r--r--drivers/staging/comedi/drivers/das08.c12
-rw-r--r--drivers/staging/comedi/drivers/das08.h6
-rw-r--r--drivers/staging/comedi/drivers/das08_cs.c15
-rw-r--r--drivers/staging/comedi/drivers/das08_isa.c12
-rw-r--r--drivers/staging/comedi/drivers/das08_pci.c12
-rw-r--r--drivers/staging/comedi/drivers/das16.c7
-rw-r--r--drivers/staging/comedi/drivers/das16m1.c7
-rw-r--r--drivers/staging/comedi/drivers/das1800.c6
-rw-r--r--drivers/staging/comedi/drivers/das6402.c5
-rw-r--r--drivers/staging/comedi/drivers/das800.c6
-rw-r--r--drivers/staging/comedi/drivers/dmm32at.c5
-rw-r--r--drivers/staging/comedi/drivers/dt2811.c4
-rw-r--r--drivers/staging/comedi/drivers/dt2814.c5
-rw-r--r--drivers/staging/comedi/drivers/dt2815.c5
-rw-r--r--drivers/staging/comedi/drivers/dt2817.c5
-rw-r--r--drivers/staging/comedi/drivers/dt282x.c5
-rw-r--r--drivers/staging/comedi/drivers/dt3000.c5
-rw-r--r--drivers/staging/comedi/drivers/dt9812.c1031
-rw-r--r--drivers/staging/comedi/drivers/dyna_pci10xx.c4
-rw-r--r--drivers/staging/comedi/drivers/gsc_hpdi.c7
-rw-r--r--drivers/staging/comedi/drivers/icp_multi.c5
-rw-r--r--drivers/staging/comedi/drivers/jr3_pci.c51
-rw-r--r--drivers/staging/comedi/drivers/ke_counter.c5
-rw-r--r--drivers/staging/comedi/drivers/me4000.c5
-rw-r--r--drivers/staging/comedi/drivers/me_daq.c28
-rw-r--r--drivers/staging/comedi/drivers/mite.c5
-rw-r--r--drivers/staging/comedi/drivers/mite.h5
-rw-r--r--drivers/staging/comedi/drivers/mpc624.c5
-rw-r--r--drivers/staging/comedi/drivers/multiq3.c5
-rw-r--r--drivers/staging/comedi/drivers/ni_6527.c5
-rw-r--r--drivers/staging/comedi/drivers/ni_65xx.c36
-rw-r--r--drivers/staging/comedi/drivers/ni_660x.c4
-rw-r--r--drivers/staging/comedi/drivers/ni_670x.c5
-rw-r--r--drivers/staging/comedi/drivers/ni_at_a2150.c6
-rw-r--r--drivers/staging/comedi/drivers/ni_at_ao.c5
-rw-r--r--drivers/staging/comedi/drivers/ni_atmio.c4
-rw-r--r--drivers/staging/comedi/drivers/ni_atmio16d.c6
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_700.c9
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_dio24.c14
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc.c74
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc.h29
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc_cs.c19
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc_pci.c12
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_common.c6
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_cs.c5
-rw-r--r--drivers/staging/comedi/drivers/ni_pcidio.c30
-rw-r--r--drivers/staging/comedi/drivers/ni_pcimio.c4
-rw-r--r--drivers/staging/comedi/drivers/ni_stc.h5
-rw-r--r--drivers/staging/comedi/drivers/ni_tio.c4
-rw-r--r--drivers/staging/comedi/drivers/ni_tio.h5
-rw-r--r--drivers/staging/comedi/drivers/ni_tio_internal.h5
-rw-r--r--drivers/staging/comedi/drivers/ni_tiocmd.c4
-rw-r--r--drivers/staging/comedi/drivers/pcl711.c5
-rw-r--r--drivers/staging/comedi/drivers/pcl724.c219
-rw-r--r--drivers/staging/comedi/drivers/pcl725.c91
-rw-r--r--drivers/staging/comedi/drivers/pcl726.c5
-rw-r--r--drivers/staging/comedi/drivers/pcl730.c332
-rw-r--r--drivers/staging/comedi/drivers/pcm3724.c11
-rw-r--r--drivers/staging/comedi/drivers/pcm3730.c136
-rw-r--r--drivers/staging/comedi/drivers/pcmad.c197
-rw-r--r--drivers/staging/comedi/drivers/pcmda12.c245
-rw-r--r--drivers/staging/comedi/drivers/pcmmio.c4
-rw-r--r--drivers/staging/comedi/drivers/pcmuio.c961
-rw-r--r--drivers/staging/comedi/drivers/plx9052.h5
-rw-r--r--drivers/staging/comedi/drivers/poc.c58
-rw-r--r--drivers/staging/comedi/drivers/rtd520.c4
-rw-r--r--drivers/staging/comedi/drivers/rti800.c4
-rw-r--r--drivers/staging/comedi/drivers/rti802.c5
-rw-r--r--drivers/staging/comedi/drivers/s526.c5
-rw-r--r--drivers/staging/comedi/drivers/s626.c5
-rw-r--r--drivers/staging/comedi/drivers/s626.h5
-rw-r--r--drivers/staging/comedi/drivers/serial2002.c5
-rw-r--r--drivers/staging/comedi/drivers/skel.c5
-rw-r--r--drivers/staging/comedi/drivers/ssv_dnp.c5
-rw-r--r--drivers/staging/comedi/drivers/unioxx5.c25
-rw-r--r--drivers/staging/comedi/drivers/usbdux.c236
-rw-r--r--drivers/staging/comedi/drivers/usbduxfast.c1282
-rw-r--r--drivers/staging/comedi/drivers/usbduxsigma.c2958
-rw-r--r--drivers/staging/comedi/drivers/vmk80xx.c88
145 files changed, 3742 insertions, 8177 deletions
diff --git a/drivers/staging/comedi/drivers/8253.h b/drivers/staging/comedi/drivers/8253.h
index 429e0d60c0a3..3abedcd2527b 100644
--- a/drivers/staging/comedi/drivers/8253.h
+++ b/drivers/staging/comedi/drivers/8253.h
@@ -14,11 +14,6 @@
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.
-
*/
#ifndef _8253_H
diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
index 1d48aa602ece..94e17500150f 100644
--- a/drivers/staging/comedi/drivers/8255.c
+++ b/drivers/staging/comedi/drivers/8255.c
@@ -14,11 +14,6 @@
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: 8255
@@ -81,7 +76,6 @@ I/O port base address can be found in the output of 'lspci -v'.
#include "../comedidev.h"
#include <linux/ioport.h>
-#include <linux/slab.h>
#include "comedi_fc.h"
#include "8255.h"
@@ -290,15 +284,13 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s,
{
struct subdev_8255_private *spriv;
- spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
+ spriv = comedi_alloc_spriv(s, sizeof(*spriv));
if (!spriv)
return -ENOMEM;
spriv->iobase = iobase;
spriv->io = io ? io : subdev_8255_io;
- s->private = spriv;
-
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 24;
@@ -391,7 +383,6 @@ static void dev_8255_detach(struct comedi_device *dev)
spriv = s->private;
release_region(spriv->iobase, _8255_SIZE);
}
- comedi_spriv_free(dev, i);
}
}
diff --git a/drivers/staging/comedi/drivers/8255.h b/drivers/staging/comedi/drivers/8255.h
index 0f6e7492b7db..4f16ea78f86a 100644
--- a/drivers/staging/comedi/drivers/8255.h
+++ b/drivers/staging/comedi/drivers/8255.h
@@ -14,11 +14,6 @@
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.
-
*/
#ifndef _8255_H
diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c
index 76dec96aeb2a..3d3547c19480 100644
--- a/drivers/staging/comedi/drivers/8255_pci.c
+++ b/drivers/staging/comedi/drivers/8255_pci.c
@@ -19,10 +19,6 @@
* 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.
*/
/*
@@ -242,10 +238,7 @@ static int pci_8255_auto_attach(struct comedi_device *dev,
static void pci_8255_detach(struct comedi_device *dev)
{
struct pci_8255_private *devpriv = dev->private;
- int i;
- for (i = 0; i < dev->n_subdevices; i++)
- comedi_spriv_free(dev, i);
if (devpriv && devpriv->mmio_base)
iounmap(devpriv->mmio_base);
comedi_pci_disable(dev);
diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile
index 57e984f0f462..dbb93e332487 100644
--- a/drivers/staging/comedi/drivers/Makefile
+++ b/drivers/staging/comedi/drivers/Makefile
@@ -11,19 +11,16 @@ obj-$(CONFIG_COMEDI_SERIAL2002) += serial2002.o
obj-$(CONFIG_COMEDI_SKEL) += skel.o
# Comedi ISA drivers
-obj-$(CONFIG_COMEDI_ACL7225B) += acl7225b.o
obj-$(CONFIG_COMEDI_AMPLC_DIO200_ISA) += amplc_dio200.o
obj-$(CONFIG_COMEDI_AMPLC_PC263_ISA) += amplc_pc263.o
obj-$(CONFIG_COMEDI_PCL711) += pcl711.o
obj-$(CONFIG_COMEDI_PCL724) += pcl724.o
-obj-$(CONFIG_COMEDI_PCL725) += pcl725.o
obj-$(CONFIG_COMEDI_PCL726) += pcl726.o
obj-$(CONFIG_COMEDI_PCL730) += pcl730.o
obj-$(CONFIG_COMEDI_PCL812) += pcl812.o
obj-$(CONFIG_COMEDI_PCL816) += pcl816.o
obj-$(CONFIG_COMEDI_PCL818) += pcl818.o
obj-$(CONFIG_COMEDI_PCM3724) += pcm3724.o
-obj-$(CONFIG_COMEDI_PCM3730) += pcm3730.o
obj-$(CONFIG_COMEDI_RTI800) += rti800.o
obj-$(CONFIG_COMEDI_RTI802) += rti802.o
obj-$(CONFIG_COMEDI_DAS16M1) += das16m1.o
@@ -55,6 +52,7 @@ obj-$(CONFIG_COMEDI_PCMMIO) += pcmmio.o
obj-$(CONFIG_COMEDI_PCMUIO) += pcmuio.o
obj-$(CONFIG_COMEDI_MULTIQ3) += multiq3.o
obj-$(CONFIG_COMEDI_POC) += poc.o
+obj-$(CONFIG_COMEDI_S526) += s526.o
# Comedi PCI drivers
obj-$(CONFIG_COMEDI_8255_PCI) += 8255_pci.o
@@ -110,7 +108,6 @@ obj-$(CONFIG_COMEDI_NI_LABPC_PCI) += ni_labpc_pci.o
obj-$(CONFIG_COMEDI_NI_PCIDIO) += ni_pcidio.o
obj-$(CONFIG_COMEDI_NI_PCIMIO) += ni_pcimio.o
obj-$(CONFIG_COMEDI_RTD520) += rtd520.o
-obj-$(CONFIG_COMEDI_S526) += s526.o
obj-$(CONFIG_COMEDI_S626) += s626.o
obj-$(CONFIG_COMEDI_SSV_DNP) += ssv_dnp.o
diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c
deleted file mode 100644
index 9e2c7aeea535..000000000000
--- a/drivers/staging/comedi/drivers/acl7225b.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * comedi/drivers/acl7225b.c
- * Driver for Adlink NuDAQ ACL-7225b and clones
- * José Luis Sánchez
- */
-/*
-Driver: acl7225b
-Description: Adlink NuDAQ ACL-7225b & compatibles
-Author: José Luis Sánchez (jsanchezv@teleline.es)
-Status: testing
-Devices: [Adlink] ACL-7225b (acl7225b), [ICP] P16R16DIO (p16r16dio)
-*/
-
-#include "../comedidev.h"
-
-#include <linux/ioport.h>
-
-#define ACL7225_RIO_LO 0 /* Relays input/output low byte (R0-R7) */
-#define ACL7225_RIO_HI 1 /* Relays input/output high byte (R8-R15) */
-#define ACL7225_DI_LO 2 /* Digital input low byte (DI0-DI7) */
-#define ACL7225_DI_HI 3 /* Digital input high byte (DI8-DI15) */
-
-struct acl7225b_boardinfo {
- const char *name;
- int io_range;
-};
-
-static const struct acl7225b_boardinfo acl7225b_boards[] = {
- {
- .name = "acl7225b",
- .io_range = 8, /* only 4 are used */
- }, {
- .name = "p16r16dio",
- .io_range = 4,
- },
-};
-
-static int acl7225b_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- unsigned long reg = (unsigned long)s->private;
- unsigned int mask = data[0];
- unsigned int bits = data[1];
-
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
-
- if (mask & 0x00ff)
- outb(s->state & 0xff, dev->iobase + reg);
- if (mask & 0xff00)
- outb((s->state >> 8), dev->iobase + reg + 1);
- }
-
- data[1] = s->state;
-
- return insn->n;
-}
-
-static int acl7225b_di_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- unsigned long reg = (unsigned long)s->private;
-
- data[1] = inb(dev->iobase + reg) |
- (inb(dev->iobase + reg + 1) << 8);
-
- return insn->n;
-}
-
-static int acl7225b_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- const struct acl7225b_boardinfo *board = comedi_board(dev);
- struct comedi_subdevice *s;
- int ret;
-
- ret = comedi_request_region(dev, it->options[0], board->io_range);
- if (ret)
- return ret;
-
- ret = comedi_alloc_subdevices(dev, 3);
- if (ret)
- return ret;
-
- s = &dev->subdevices[0];
- /* Relays outputs */
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE;
- s->maxdata = 1;
- s->n_chan = 16;
- s->insn_bits = acl7225b_do_insn_bits;
- s->range_table = &range_digital;
- s->private = (void *)ACL7225_RIO_LO;
-
- s = &dev->subdevices[1];
- /* Relays status */
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE;
- s->maxdata = 1;
- s->n_chan = 16;
- s->insn_bits = acl7225b_di_insn_bits;
- s->range_table = &range_digital;
- s->private = (void *)ACL7225_RIO_LO;
-
- s = &dev->subdevices[2];
- /* Isolated digital inputs */
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE;
- s->maxdata = 1;
- s->n_chan = 16;
- s->insn_bits = acl7225b_di_insn_bits;
- s->range_table = &range_digital;
- s->private = (void *)ACL7225_DI_LO;
-
- return 0;
-}
-
-static struct comedi_driver acl7225b_driver = {
- .driver_name = "acl7225b",
- .module = THIS_MODULE,
- .attach = acl7225b_attach,
- .detach = comedi_legacy_detach,
- .board_name = &acl7225b_boards[0].name,
- .num_names = ARRAY_SIZE(acl7225b_boards),
- .offset = sizeof(struct acl7225b_boardinfo),
-};
-module_comedi_driver(acl7225b_driver);
-
-MODULE_DESCRIPTION("Comedi: NuDAQ ACL-7225B, 16 Relay & 16 Isolated DI Card");
-MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
index 5bd7fe64637c..d91f586fdd26 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
@@ -15,10 +15,6 @@ This program is free software; you can redistribute it and/or modify it under th
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this source code.
-
@endverbatim
*/
/*
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
index 6b38ce7a275b..27de18e79895 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
@@ -15,10 +15,6 @@ This program is free software; you can redistribute it and/or modify it under th
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this source code.
-
@endverbatim
*/
/*
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
index 70a7f953fa2f..c9db601da2c9 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
@@ -15,10 +15,6 @@ This program is free software; you can redistribute it and/or modify it under th
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this source code.
-
@endverbatim
*/
/*
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
index be0c6adbdc94..6bbcb06cc279 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
@@ -15,10 +15,6 @@ This program is free software; you can redistribute it and/or modify it under th
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this source code.
-
@endverbatim
*/
/*
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
index a211e78dd3ba..5c830337db85 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
@@ -15,10 +15,6 @@ This program is free software; you can redistribute it and/or modify it under th
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this source code.
-
@endverbatim
*/
/*
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
index 97e7eec343d7..6ef1d6a434d9 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
@@ -15,10 +15,6 @@ This program is free software; you can redistribute it and/or modify it under th
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this source code.
-
@endverbatim
*/
/*
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
index 3bc9826ce40b..0b79531ac24b 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
@@ -15,10 +15,6 @@ This program is free software; you can redistribute it and/or modify it under th
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this source code.
-
@endverbatim
*/
/*
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
index c8238b8921cd..fb56360444ee 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
@@ -15,10 +15,6 @@ This program is free software; you can redistribute it and/or modify it under th
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this source code.
-
@endverbatim
*/
/*
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
index 0c3db57a50f4..f25e0085219d 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
@@ -20,13 +20,6 @@ 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.,
-59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this
-source code.
-
@endverbatim
*/
/*
@@ -46,10 +39,6 @@ source code.
+-----------------------------------------------------------------------+
*/
-#ifndef COMEDI_SUBD_TTLIO
-#define COMEDI_SUBD_TTLIO 11 /* Digital Input Output But TTL */
-#endif
-
static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
@@ -105,23 +94,14 @@ static int addi_auto_attach(struct comedi_device *dev,
if (ret)
return ret;
- if (!this_board->pc_EepromChip ||
- strcmp(this_board->pc_EepromChip, ADDIDATA_9054)) {
- /* board does not have an eeprom or is not ADDIDATA_9054 */
- if (this_board->i_IorangeBase1)
- dev->iobase = pci_resource_start(pcidev, 1);
- else
- dev->iobase = pci_resource_start(pcidev, 0);
-
- devpriv->iobase = dev->iobase;
- devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0);
- devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2);
- } else {
- /* board has an ADDIDATA_9054 eeprom */
- dev->iobase = pci_resource_start(pcidev, 2);
- devpriv->iobase = pci_resource_start(pcidev, 2);
- devpriv->dw_AiBase = pci_ioremap_bar(pcidev, 3);
- }
+ if (this_board->i_IorangeBase1)
+ dev->iobase = pci_resource_start(pcidev, 1);
+ else
+ dev->iobase = pci_resource_start(pcidev, 0);
+
+ devpriv->iobase = dev->iobase;
+ devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0);
+ devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2);
devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3);
/* Initialize parameters that can be overridden in EEPROM */
@@ -132,7 +112,6 @@ static int addi_auto_attach(struct comedi_device *dev,
devpriv->s_EeParameters.i_NbrDiChannel = this_board->i_NbrDiChannel;
devpriv->s_EeParameters.i_NbrDoChannel = this_board->i_NbrDoChannel;
devpriv->s_EeParameters.i_DoMaxdata = this_board->i_DoMaxdata;
- devpriv->s_EeParameters.i_Dma = this_board->i_Dma;
devpriv->s_EeParameters.i_Timer = this_board->i_Timer;
devpriv->s_EeParameters.ui_MinAcquisitiontimeNs =
this_board->ui_MinAcquisitiontimeNs;
@@ -191,9 +170,6 @@ static int addi_auto_attach(struct comedi_device *dev,
s->len_chanlist = this_board->i_AiChannelList;
s->range_table = this_board->pr_AiRangelist;
- /* Set the initialisation flag */
- devpriv->b_AiInitialisation = 1;
-
s->insn_config = this_board->ai_config;
s->insn_read = this_board->ai_read;
s->insn_write = this_board->ai_write;
@@ -215,8 +191,6 @@ static int addi_auto_attach(struct comedi_device *dev,
s->maxdata = devpriv->s_EeParameters.i_AoMaxdata;
s->len_chanlist =
devpriv->s_EeParameters.i_NbrAoChannel;
- s->range_table = this_board->pr_AoRangelist;
- s->insn_config = this_board->ao_config;
s->insn_write = this_board->ao_write;
} else {
s->type = COMEDI_SUBD_UNUSED;
@@ -281,22 +255,7 @@ static int addi_auto_attach(struct comedi_device *dev,
/* Allocate and Initialise TTL */
s = &dev->subdevices[5];
- if (this_board->i_NbrTTLChannel) {
- s->type = COMEDI_SUBD_TTLIO;
- s->subdev_flags =
- SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = this_board->i_NbrTTLChannel;
- s->maxdata = 1;
- s->io_bits = 0; /* all bits input */
- s->len_chanlist = this_board->i_NbrTTLChannel;
- s->range_table = &range_digital;
- s->insn_config = this_board->ttl_config;
- s->insn_bits = this_board->ttl_bits;
- s->insn_read = this_board->ttl_read;
- s->insn_write = this_board->ttl_write;
- } else {
- s->type = COMEDI_SUBD_UNUSED;
- }
+ s->type = COMEDI_SUBD_UNUSED;
/* EEPROM */
s = &dev->subdevices[6];
@@ -323,8 +282,6 @@ static void i_ADDI_Detach(struct comedi_device *dev)
i_ADDI_Reset(dev);
if (dev->irq)
free_irq(dev->irq, dev);
- if (devpriv->dw_AiBase)
- iounmap(devpriv->dw_AiBase);
}
comedi_pci_disable(dev);
}
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
index c034bf1426eb..f1be5ade9962 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
@@ -18,12 +18,8 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
-#define LOBYTE(W) (unsigned char)((W) & 0xFF)
-#define HIBYTE(W) (unsigned char)(((W) >> 8) & 0xFF)
-#define MAKEWORD(H, L) (unsigned short)((L) | ((H) << 8))
#define LOWORD(W) (unsigned short)((W) & 0xFFFF)
#define HIWORD(W) (unsigned short)(((W) >> 16) & 0xFFFF)
-#define MAKEDWORD(H, L) (unsigned int)((L) | ((H) << 16))
#define ADDI_ENABLE 1
#define ADDI_DISABLE 0
@@ -33,8 +29,6 @@
#define ADDIDATA_NO_EEPROM 0
#define ADDIDATA_93C76 "93C76"
#define ADDIDATA_S5920 "S5920"
-#define ADDIDATA_S5933 "S5933"
-#define ADDIDATA_9054 "9054"
/* ADDIDATA Enable Disable */
#define ADDIDATA_ENABLE 1
@@ -55,17 +49,12 @@ struct addi_board {
int i_AiMaxdata; /* resolution of A/D */
int i_AoMaxdata; /* resolution of D/A */
const struct comedi_lrange *pr_AiRangelist; /* rangelist for A/D */
- const struct comedi_lrange *pr_AoRangelist; /* rangelist for D/A */
int i_NbrDiChannel; /* Number of DI channels */
int i_NbrDoChannel; /* Number of DO channels */
int i_DoMaxdata; /* data to set all channels high */
- int i_NbrTTLChannel; /* Number of TTL channels */
-
- int i_Dma; /* dma present or not */
int i_Timer; /* timer subdevice present or not */
- unsigned char b_AvailableConvertUnit;
unsigned int ui_MinAcquisitiontimeNs; /* Minimum Acquisition in Nano secs */
unsigned int ui_MinDelaytimeNs; /* Minimum Delay in Nano secs */
@@ -90,12 +79,8 @@ struct addi_board {
int (*ai_cancel)(struct comedi_device *, struct comedi_subdevice *);
/* Analog Output */
- int (*ao_config)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
int (*ao_write)(struct comedi_device *, struct comedi_subdevice *,
struct comedi_insn *, unsigned int *);
- int (*ao_bits)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
/* Digital Input */
int (*di_config)(struct comedi_device *, struct comedi_subdevice *,
@@ -126,16 +111,6 @@ struct addi_board {
struct comedi_insn *, unsigned int *);
int (*timer_bits)(struct comedi_device *, struct comedi_subdevice *,
struct comedi_insn *, unsigned int *);
-
- /* TTL IO */
- int (*ttl_config)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
- int (*ttl_bits)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
- int (*ttl_read)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
- int (*ttl_write)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
};
/* MODULE INFO STRUCTURE */
@@ -283,58 +258,41 @@ union str_ModuleInfo {
/* Private structure for the addi_apci3120 driver */
struct addi_private {
-
int iobase;
int i_IobaseAmcc; /* base+size for AMCC chip */
int i_IobaseAddon; /* addon base address */
int i_IobaseReserved;
- void __iomem *dw_AiBase;
unsigned char b_AiContinuous; /* we do unlimited AI */
- unsigned char b_AiInitialisation;
unsigned int ui_AiActualScan; /* how many scans we finished */
- unsigned int ui_AiBufferPtr; /* data buffer ptr in samples */
unsigned int ui_AiNbrofChannels; /* how many channels is measured */
unsigned int ui_AiScanLength; /* Length of actual scanlist */
- unsigned int ui_AiActualScanPosition; /* position in actual scan */
unsigned int *pui_AiChannelList; /* actual chanlist */
unsigned int ui_AiChannelList[32]; /* actual chanlist */
- unsigned char b_AiChannelConfiguration[32]; /* actual chanlist */
unsigned int ui_AiReadData[32];
- unsigned int dw_AiInitialised;
unsigned int ui_AiTimer0; /* Timer Constant for Timer0 */
unsigned int ui_AiTimer1; /* Timer constant for Timer1 */
unsigned int ui_AiFlags;
unsigned int ui_AiDataLength;
- short *AiData; /* Pointer to sample data */
unsigned int ui_AiNbrofScans; /* number of scans to do */
unsigned short us_UseDma; /* To use Dma or not */
unsigned char b_DmaDoubleBuffer; /* we can use double buffering */
unsigned int ui_DmaActualBuffer; /* which buffer is used now */
- /* UPDATE-0.7.57->0.7.68 */
- /* unsigned int ul_DmaBufferVirtual[2]; pointers to begin of DMA buffer */
short *ul_DmaBufferVirtual[2]; /* pointers to begin of DMA buffer */
unsigned int ul_DmaBufferHw[2]; /* hw address of DMA buff */
unsigned int ui_DmaBufferSize[2]; /* size of dma buffer in bytes */
unsigned int ui_DmaBufferUsesize[2]; /* which size we may now used for transfer */
- unsigned int ui_DmaBufferSamples[2]; /* size in samples */
unsigned int ui_DmaBufferPages[2]; /* number of pages in buffer */
unsigned char b_DigitalOutputRegister; /* Digital Output Register */
unsigned char b_OutputMemoryStatus;
- unsigned char b_AnalogInputChannelNbr; /* Analog input channel Nbr */
- unsigned char b_AnalogOutputChannelNbr; /* Analog input Output Nbr */
unsigned char b_TimerSelectMode; /* Contain data written at iobase + 0C */
unsigned char b_ModeSelectRegister; /* Contain data written at iobase + 0E */
unsigned short us_OutputRegister; /* Contain data written at iobase + 0 */
- unsigned char b_InterruptState;
- unsigned char b_TimerInit; /* Specify if InitTimerWatchdog was load */
- unsigned char b_TimerStarted; /* Specify if timer 2 is running or not */
unsigned char b_Timer2Mode; /* Specify the timer 2 mode */
unsigned char b_Timer2Interrupt; /* Timer2 interrupt enable or disable */
unsigned char b_AiCyclicAcquisition; /* indicate cyclic acquisition */
unsigned char b_InterruptMode; /* eoc eos or dma */
unsigned char b_EocEosInterrupt; /* Enable disable eoc eos interrupt */
unsigned int ui_EocEosConversionTime;
- unsigned char b_EocEosConversionTimeBase;
unsigned char b_SingelDiff;
unsigned char b_ExttrigEnable; /* To enable or disable external trigger */
@@ -365,7 +323,6 @@ struct addi_private {
} s_InterruptParameters;
union str_ModuleInfo s_ModuleInfo[4];
- unsigned int ul_TTLPortConfiguration[10];
/* Parameters read from EEPROM overriding static board info */
struct {
@@ -376,7 +333,6 @@ struct addi_private {
int i_NbrDiChannel; /* Number of DI channels */
int i_NbrDoChannel; /* Number of DO channels */
int i_DoMaxdata; /* data to set all channels high */
- int i_Dma; /* dma present or not */
int i_Timer; /* timer subdevice present or not */
unsigned int ui_MinAcquisitiontimeNs;
/* Minimum Acquisition in Nano secs */
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
index 5124ac9f1818..dc031c494a27 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
@@ -20,13 +20,6 @@
* 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.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * You should also find the complete GPL in the COPYING file accompanying
- * this source code.
*/
#define NVRAM_USER_DATA_START 0x100
@@ -302,7 +295,7 @@ static void addi_eeprom_read_ai_info(struct comedi_device *dev,
devpriv->s_EeParameters.ui_MinDelaytimeNs = tmp * 1000;
tmp = addi_eeprom_readw(iobase, type, addr + 20);
- devpriv->s_EeParameters.i_Dma = (tmp >> 13) & 0x01;
+ /* dma = (tmp >> 13) & 0x01; */
tmp = addi_eeprom_readw(iobase, type, addr + 72) & 0xff;
if (tmp) { /* > 0 */
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
index b05f8505c894..b1a7ec1035e1 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
@@ -15,10 +15,6 @@ This program is free software; you can redistribute it and/or modify it under th
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this source code.
-
@endverbatim
*/
/*
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
index 3d66e48e0cf7..1128c22e7517 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
@@ -15,10 +15,6 @@ This program is free software; you can redistribute it and/or modify it under th
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this source code.
-
@endverbatim
*/
/*
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
index 24c4c983db38..054910511e9e 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
@@ -15,10 +15,6 @@ This program is free software; you can redistribute it and/or modify it under th
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this source code.
-
@endverbatim
*/
/*
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
index fc31c4b93407..e3cc429403c0 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
@@ -15,10 +15,6 @@ This program is free software; you can redistribute it and/or modify it under th
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this source code.
-
@endverbatim
*/
/*
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
index 74065baa3c08..a89e505c8a3a 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
@@ -15,10 +15,6 @@ This program is free software; you can redistribute it and/or modify it under th
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this source code.
-
@endverbatim
*/
/*
@@ -724,9 +720,7 @@ static int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev,
inb(dev->iobase + APCI3120_RESET_FIFO);
inw(dev->iobase + APCI3120_RD_STATUS);
devpriv->ui_AiActualScan = 0;
- devpriv->ui_AiActualScanPosition = 0;
s->async->cur_chan = 0;
- devpriv->ui_AiBufferPtr = 0;
devpriv->b_AiContinuous = 0;
devpriv->ui_DmaActualBuffer = 0;
@@ -895,9 +889,7 @@ static int i_APCI3120_CyclicAnalogInput(int mode,
/* END JK 07.05.04: Comparison between WIN32 and Linux driver */
devpriv->ui_AiActualScan = 0;
- devpriv->ui_AiActualScanPosition = 0;
s->async->cur_chan = 0;
- devpriv->ui_AiBufferPtr = 0;
devpriv->ui_DmaActualBuffer = 0;
/* value for timer2 minus -2 has to be done .....dunno y?? */
@@ -1351,8 +1343,6 @@ static int i_APCI3120_CommandAnalogInput(struct comedi_device *dev,
devpriv->ui_AiScanLength = cmd->scan_end_arg;
devpriv->pui_AiChannelList = cmd->chanlist;
- /* UPDATE-0.7.57->0.7.68devpriv->AiData=s->async->data; */
- devpriv->AiData = s->async->prealloc_buf;
/* UPDATE-0.7.57->0.7.68devpriv->ui_AiDataLength=s->async->data_len; */
devpriv->ui_AiDataLength = s->async->prealloc_bufsz;
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
index c7908730caa5..32dce0329fd5 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
@@ -15,10 +15,6 @@ This program is free software; you can redistribute it and/or modify it under th
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this source code.
-
@endverbatim
*/
/*
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
deleted file mode 100644
index a45a2a26e0da..000000000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+++ /dev/null
@@ -1,1376 +0,0 @@
-/**
-@verbatim
-
-Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
-
- ADDI-DATA GmbH
- Dieselstrasse 3
- D-77833 Ottersweier
- Tel: +19(0)7223/9493-0
- Fax: +49(0)7223/9493-92
- http://www.addi-data.com
- info@addi-data.com
-
-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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this source code.
-
-@endverbatim
-*/
-/*
- +-----------------------------------------------------------------------+
- | (C) ADDI-DATA GmbH Dieselstrasse 3 D-77833 Ottersweier |
- +-----------------------------------------------------------------------+
- | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
- | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
- +-----------------------------------------------------------------------+
- | Project : APCI-3XXX | Compiler : GCC |
- | Module name : hwdrv_apci3xxx.c| Version : 2.96 |
- +-------------------------------+---------------------------------------+
- | Project manager: S. Weber | Date : 15/09/2005 |
- +-----------------------------------------------------------------------+
- | Description :APCI3XXX Module. Hardware abstraction Layer for APCI3XXX|
- +-----------------------------------------------------------------------+
- | UPDATE'S |
- +-----------------------------------------------------------------------+
- | Date | Author | Description of updates |
- +----------+-----------+------------------------------------------------+
- | | | |
- | | | |
- +----------+-----------+------------------------------------------------+
-*/
-
-#ifndef COMEDI_SUBD_TTLIO
-#define COMEDI_SUBD_TTLIO 11 /* Digital Input Output But TTL */
-#endif
-
-#define APCI3XXX_SINGLE 0
-#define APCI3XXX_DIFF 1
-#define APCI3XXX_CONFIGURATION 0
-
-#define APCI3XXX_TTL_INIT_DIRECTION_PORT2 0
-
-static const struct comedi_lrange range_apci3XXX_ai = {
- 8, {
- BIP_RANGE(10),
- BIP_RANGE(5),
- BIP_RANGE(2),
- BIP_RANGE(1),
- UNI_RANGE(10),
- UNI_RANGE(5),
- UNI_RANGE(2),
- UNI_RANGE(1)
- }
-};
-
-static const struct comedi_lrange range_apci3XXX_ao = {
- 2, {
- BIP_RANGE(10),
- UNI_RANGE(10)
- }
-};
-
-/*
-+----------------------------------------------------------------------------+
-| ANALOG INPUT FUNCTIONS |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI3XXX_TestConversionStarted |
-| (struct comedi_device *dev) |
-+----------------------------------------------------------------------------+
-| Task Test if any conversion started |
-+----------------------------------------------------------------------------+
-| Input Parameters : - |
-+----------------------------------------------------------------------------+
-| Output Parameters : - |
-+----------------------------------------------------------------------------+
-| Return Value : 0 : Conversion not started |
-| 1 : Conversion started |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI3XXX_TestConversionStarted(struct comedi_device *dev)
-{
- struct addi_private *devpriv = dev->private;
-
- if ((readl(devpriv->dw_AiBase + 8) & 0x80000UL) == 0x80000UL)
- return 1;
- else
- return 0;
-
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI3XXX_AnalogInputConfigOperatingMode |
-| (struct comedi_device *dev, |
-| struct comedi_subdevice *s, |
-| struct comedi_insn *insn, |
-| unsigned int *data) |
-+----------------------------------------------------------------------------+
-| Task Converting mode and convert time selection |
-+----------------------------------------------------------------------------+
-| Input Parameters : b_SingleDiff = (unsigned char) data[1]; |
-| b_TimeBase = (unsigned char) data[2]; (0: ns, 1:micros 2:ms)|
-| dw_ReloadValue = (unsigned int) data[3]; |
-| ........ |
-+----------------------------------------------------------------------------+
-| Output Parameters : - |
-+----------------------------------------------------------------------------+
-| Return Value :>0 : No error |
-| -1 : Single/Diff selection error |
-| -2 : Convert time base unity selection error |
-| -3 : Convert time value selection error |
-| -10: Any conversion started |
-| .... |
-| -100 : Config command error |
-| -101 : Data size error |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- const struct addi_board *this_board = comedi_board(dev);
- struct addi_private *devpriv = dev->private;
- int i_ReturnValue = insn->n;
- unsigned char b_TimeBase = 0;
- unsigned char b_SingleDiff = 0;
- unsigned int dw_ReloadValue = 0;
- unsigned int dw_TestReloadValue = 0;
-
- /************************/
- /* Test the buffer size */
- /************************/
-
- if (insn->n == 4) {
- /****************************/
- /* Get the Singel/Diff flag */
- /****************************/
-
- b_SingleDiff = (unsigned char) data[1];
-
- /****************************/
- /* Get the time base unitiy */
- /****************************/
-
- b_TimeBase = (unsigned char) data[2];
-
- /*************************************/
- /* Get the convert time reload value */
- /*************************************/
-
- dw_ReloadValue = (unsigned int) data[3];
-
- /**********************/
- /* Test the time base */
- /**********************/
-
- if ((this_board->b_AvailableConvertUnit & (1 << b_TimeBase)) !=
- 0) {
- /*******************************/
- /* Test the convert time value */
- /*******************************/
-
- if (dw_ReloadValue <= 65535) {
- dw_TestReloadValue = dw_ReloadValue;
-
- if (b_TimeBase == 1) {
- dw_TestReloadValue =
- dw_TestReloadValue * 1000UL;
- }
- if (b_TimeBase == 2) {
- dw_TestReloadValue =
- dw_TestReloadValue * 1000000UL;
- }
-
- /*******************************/
- /* Test the convert time value */
- /*******************************/
-
- if (dw_TestReloadValue >=
- devpriv->s_EeParameters.
- ui_MinAcquisitiontimeNs) {
- if ((b_SingleDiff == APCI3XXX_SINGLE)
- || (b_SingleDiff ==
- APCI3XXX_DIFF)) {
- if (((b_SingleDiff == APCI3XXX_SINGLE)
- && (devpriv->s_EeParameters.i_NbrAiChannel == 0))
- || ((b_SingleDiff == APCI3XXX_DIFF)
- && (this_board->i_NbrAiChannelDiff == 0))
- ) {
- /*******************************/
- /* Single/Diff selection error */
- /*******************************/
-
- printk("Single/Diff selection error\n");
- i_ReturnValue = -1;
- } else {
- /**********************************/
- /* Test if conversion not started */
- /**********************************/
-
- if (i_APCI3XXX_TestConversionStarted(dev) == 0) {
- devpriv->
- ui_EocEosConversionTime
- =
- (unsigned int)
- dw_ReloadValue;
- devpriv->
- b_EocEosConversionTimeBase
- =
- b_TimeBase;
- devpriv->
- b_SingelDiff
- =
- b_SingleDiff;
- devpriv->
- b_AiInitialisation
- = 1;
-
- /*******************************/
- /* Set the convert timing unit */
- /*******************************/
-
- writel((unsigned int)b_TimeBase,
- devpriv->dw_AiBase + 36);
-
- /**************************/
- /* Set the convert timing */
- /*************************/
-
- writel(dw_ReloadValue, devpriv->dw_AiBase + 32);
- } else {
- /**************************/
- /* Any conversion started */
- /**************************/
-
- printk("Any conversion started\n");
- i_ReturnValue =
- -10;
- }
- }
- } else {
- /*******************************/
- /* Single/Diff selection error */
- /*******************************/
-
- printk("Single/Diff selection error\n");
- i_ReturnValue = -1;
- }
- } else {
- /************************/
- /* Time selection error */
- /************************/
-
- printk("Convert time value selection error\n");
- i_ReturnValue = -3;
- }
- } else {
- /************************/
- /* Time selection error */
- /************************/
-
- printk("Convert time value selection error\n");
- i_ReturnValue = -3;
- }
- } else {
- /*****************************/
- /* Time base selection error */
- /*****************************/
-
- printk("Convert time base unity selection error\n");
- i_ReturnValue = -2;
- }
- } else {
- /*******************/
- /* Data size error */
- /*******************/
-
- printk("Buffer size error\n");
- i_ReturnValue = -101;
- }
-
- return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI3XXX_InsnConfigAnalogInput |
-| (struct comedi_device *dev, |
-| struct comedi_subdevice *s, |
-| struct comedi_insn *insn, |
-| unsigned int *data) |
-+----------------------------------------------------------------------------+
-| Task Converting mode and convert time selection |
-+----------------------------------------------------------------------------+
-| Input Parameters : b_ConvertMode = (unsigned char) data[0]; |
-| b_TimeBase = (unsigned char) data[1]; (0: ns, 1:micros 2:ms)|
-| dw_ReloadValue = (unsigned int) data[2]; |
-| ........ |
-+----------------------------------------------------------------------------+
-| Output Parameters : - |
-+----------------------------------------------------------------------------+
-| Return Value :>0: No error |
-| .... |
-| -100 : Config command error |
-| -101 : Data size error |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- int i_ReturnValue = insn->n;
-
- /************************/
- /* Test the buffer size */
- /************************/
-
- if (insn->n >= 1) {
- switch ((unsigned char) data[0]) {
- case APCI3XXX_CONFIGURATION:
- i_ReturnValue =
- i_APCI3XXX_AnalogInputConfigOperatingMode(dev,
- s, insn, data);
- break;
-
- default:
- i_ReturnValue = -100;
- printk("Config command error %d\n", data[0]);
- break;
- }
- } else {
- /*******************/
- /* Data size error */
- /*******************/
-
- printk("Buffer size error\n");
- i_ReturnValue = -101;
- }
-
- return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI3XXX_InsnReadAnalogInput |
-| (struct comedi_device *dev, |
-| struct comedi_subdevice *s, |
-| struct comedi_insn *insn, |
-| unsigned int *data) |
-+----------------------------------------------------------------------------+
-| Task Read 1 analog input |
-+----------------------------------------------------------------------------+
-| Input Parameters : b_Range = CR_RANGE(insn->chanspec); |
-| b_Channel = CR_CHAN(insn->chanspec); |
-| dw_NbrOfAcquisition = insn->n; |
-+----------------------------------------------------------------------------+
-| Output Parameters : - |
-+----------------------------------------------------------------------------+
-| Return Value :>0: No error |
-| -3 : Channel selection error |
-| -4 : Configuration selelection error |
-| -10: Any conversion started |
-| .... |
-| -100 : Config command error |
-| -101 : Data size error |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- const struct addi_board *this_board = comedi_board(dev);
- struct addi_private *devpriv = dev->private;
- int i_ReturnValue = insn->n;
- unsigned char b_Configuration = (unsigned char) CR_RANGE(insn->chanspec);
- unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
- unsigned int dw_Temp = 0;
- unsigned int dw_Configuration = 0;
- unsigned int dw_AcquisitionCpt = 0;
- unsigned char b_Interrupt = 0;
-
- /*************************************/
- /* Test if operating mode configured */
- /*************************************/
-
- if (devpriv->b_AiInitialisation) {
- /***************************/
- /* Test the channel number */
- /***************************/
-
- if (((b_Channel < devpriv->s_EeParameters.i_NbrAiChannel)
- && (devpriv->b_SingelDiff == APCI3XXX_SINGLE))
- || ((b_Channel < this_board->i_NbrAiChannelDiff)
- && (devpriv->b_SingelDiff == APCI3XXX_DIFF))) {
- /**********************************/
- /* Test the channel configuration */
- /**********************************/
-
- if (b_Configuration > 7) {
- /***************************/
- /* Channel not initialised */
- /***************************/
-
- i_ReturnValue = -4;
- printk("Channel %d range %d selection error\n",
- b_Channel, b_Configuration);
- }
- } else {
- /***************************/
- /* Channel selection error */
- /***************************/
-
- i_ReturnValue = -3;
- printk("Channel %d selection error\n", b_Channel);
- }
-
- /**************************/
- /* Test if no error occur */
- /**************************/
-
- if (i_ReturnValue >= 0) {
- /************************/
- /* Test the buffer size */
- /************************/
-
- if ((b_Interrupt != 0) || ((b_Interrupt == 0)
- && (insn->n >= 1))) {
- /**********************************/
- /* Test if conversion not started */
- /**********************************/
-
- if (i_APCI3XXX_TestConversionStarted(dev) == 0) {
- /******************/
- /* Clear the FIFO */
- /******************/
-
- writel(0x10000UL, devpriv->dw_AiBase + 12);
-
- /*******************************/
- /* Get and save the delay mode */
- /*******************************/
-
- dw_Temp = readl(devpriv->dw_AiBase + 4);
- dw_Temp = dw_Temp & 0xFFFFFEF0UL;
-
- /***********************************/
- /* Channel configuration selection */
- /***********************************/
-
- writel(dw_Temp, devpriv->dw_AiBase + 4);
-
- /**************************/
- /* Make the configuration */
- /**************************/
-
- dw_Configuration =
- (b_Configuration & 3) |
- ((unsigned int) (b_Configuration >> 2)
- << 6) | ((unsigned int) devpriv->
- b_SingelDiff << 7);
-
- /***************************/
- /* Write the configuration */
- /***************************/
-
- writel(dw_Configuration,
- devpriv->dw_AiBase + 0);
-
- /*********************/
- /* Channel selection */
- /*********************/
-
- writel(dw_Temp | 0x100UL,
- devpriv->dw_AiBase + 4);
- writel((unsigned int) b_Channel,
- devpriv->dw_AiBase + 0);
-
- /***********************/
- /* Restaure delay mode */
- /***********************/
-
- writel(dw_Temp, devpriv->dw_AiBase + 4);
-
- /***********************************/
- /* Set the number of sequence to 1 */
- /***********************************/
-
- writel(1, devpriv->dw_AiBase + 48);
-
- /***************************/
- /* Save the interrupt flag */
- /***************************/
-
- devpriv->b_EocEosInterrupt =
- b_Interrupt;
-
- /*******************************/
- /* Save the number of channels */
- /*******************************/
-
- devpriv->ui_AiNbrofChannels = 1;
-
- /******************************/
- /* Test if interrupt not used */
- /******************************/
-
- if (b_Interrupt == 0) {
- for (dw_AcquisitionCpt = 0;
- dw_AcquisitionCpt <
- insn->n;
- dw_AcquisitionCpt++) {
- /************************/
- /* Start the conversion */
- /************************/
-
- writel(0x80000UL, devpriv->dw_AiBase + 8);
-
- /****************/
- /* Wait the EOS */
- /****************/
-
- do {
- dw_Temp = readl(devpriv->dw_AiBase + 20);
- dw_Temp = dw_Temp & 1;
- } while (dw_Temp != 1);
-
- /*************************/
- /* Read the analog value */
- /*************************/
-
- data[dw_AcquisitionCpt] = (unsigned int)readl(devpriv->dw_AiBase + 28);
- }
- } else {
- /************************/
- /* Start the conversion */
- /************************/
-
- writel(0x180000UL, devpriv->dw_AiBase + 8);
- }
- } else {
- /**************************/
- /* Any conversion started */
- /**************************/
-
- printk("Any conversion started\n");
- i_ReturnValue = -10;
- }
- } else {
- /*******************/
- /* Data size error */
- /*******************/
-
- printk("Buffer size error\n");
- i_ReturnValue = -101;
- }
- }
- } else {
- /***************************/
- /* Channel selection error */
- /***************************/
-
- printk("Operating mode not configured\n");
- i_ReturnValue = -1;
- }
- return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function name : void v_APCI3XXX_Interrupt (int irq, |
-| void *d) |
-+----------------------------------------------------------------------------+
-| Task :Interrupt handler for APCI3XXX |
-| When interrupt occurs this gets called. |
-| First it finds which interrupt has been generated and |
-| handles corresponding interrupt |
-+----------------------------------------------------------------------------+
-| Input Parameters : - |
-+----------------------------------------------------------------------------+
-| Return Value : - |
-+----------------------------------------------------------------------------+
-*/
-
-static void v_APCI3XXX_Interrupt(int irq, void *d)
-{
- struct comedi_device *dev = d;
- struct addi_private *devpriv = dev->private;
- unsigned char b_CopyCpt = 0;
- unsigned int dw_Status = 0;
-
- /***************************/
- /* Test if interrupt occur */
- /***************************/
-
- dw_Status = readl(devpriv->dw_AiBase + 16);
- if ( (dw_Status & 0x2UL) == 0x2UL) {
- /***********************/
- /* Reset the interrupt */
- /***********************/
-
- writel(dw_Status, devpriv->dw_AiBase + 16);
-
- /*****************************/
- /* Test if interrupt enabled */
- /*****************************/
-
- if (devpriv->b_EocEosInterrupt == 1) {
- /********************************/
- /* Read all analog inputs value */
- /********************************/
-
- for (b_CopyCpt = 0;
- b_CopyCpt < devpriv->ui_AiNbrofChannels;
- b_CopyCpt++) {
- devpriv->ui_AiReadData[b_CopyCpt] =
- (unsigned int)readl(devpriv->dw_AiBase + 28);
- }
-
- /**************************/
- /* Set the interrupt flag */
- /**************************/
-
- devpriv->b_EocEosInterrupt = 2;
-
- /**********************************************/
- /* Send a signal to from kernel to user space */
- /**********************************************/
-
- send_sig(SIGIO, devpriv->tsk_Current, 0);
- }
- }
-}
-
-/*
-+----------------------------------------------------------------------------+
-| ANALOG OUTPUT SUBDEVICE |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI3XXX_InsnWriteAnalogOutput |
-| (struct comedi_device *dev, |
-| struct comedi_subdevice *s, |
-| struct comedi_insn *insn, |
-| unsigned int *data) |
-+----------------------------------------------------------------------------+
-| Task Read 1 analog input |
-+----------------------------------------------------------------------------+
-| Input Parameters : b_Range = CR_RANGE(insn->chanspec); |
-| b_Channel = CR_CHAN(insn->chanspec); |
-| data[0] = analog value; |
-+----------------------------------------------------------------------------+
-| Output Parameters : - |
-+----------------------------------------------------------------------------+
-| Return Value :>0: No error |
-| -3 : Channel selection error |
-| -4 : Configuration selelection error |
-| .... |
-| -101 : Data size error |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned char b_Range = (unsigned char) CR_RANGE(insn->chanspec);
- unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
- unsigned int dw_Status = 0;
- int i_ReturnValue = insn->n;
-
- /************************/
- /* Test the buffer size */
- /************************/
-
- if (insn->n >= 1) {
- /***************************/
- /* Test the channel number */
- /***************************/
-
- if (b_Channel < devpriv->s_EeParameters.i_NbrAoChannel) {
- /**********************************/
- /* Test the channel configuration */
- /**********************************/
-
- if (b_Range < 2) {
- /***************************/
- /* Set the range selection */
- /***************************/
-
- writel(b_Range, devpriv->dw_AiBase + 96);
-
- /**************************************************/
- /* Write the analog value to the selected channel */
- /**************************************************/
-
- writel((data[0] << 8) | b_Channel,
- devpriv->dw_AiBase + 100);
-
- /****************************/
- /* Wait the end of transfer */
- /****************************/
-
- do {
- dw_Status = readl(devpriv->dw_AiBase + 96);
- } while ((dw_Status & 0x100) != 0x100);
- } else {
- /***************************/
- /* Channel not initialised */
- /***************************/
-
- i_ReturnValue = -4;
- printk("Channel %d range %d selection error\n",
- b_Channel, b_Range);
- }
- } else {
- /***************************/
- /* Channel selection error */
- /***************************/
-
- i_ReturnValue = -3;
- printk("Channel %d selection error\n", b_Channel);
- }
- } else {
- /*******************/
- /* Data size error */
- /*******************/
-
- printk("Buffer size error\n");
- i_ReturnValue = -101;
- }
-
- return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| TTL FUNCTIONS |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI3XXX_InsnConfigInitTTLIO |
-| (struct comedi_device *dev, |
-| struct comedi_subdevice *s, |
-| struct comedi_insn *insn, |
-| unsigned int *data) |
-+----------------------------------------------------------------------------+
-| Task You must calling this function be |
-| for you call any other function witch access of TTL. |
-| APCI3XXX_TTL_INIT_DIRECTION_PORT2(user inputs for direction)|
-+----------------------------------------------------------------------------+
-| Input Parameters : b_InitType = (unsigned char) data[0]; |
-| b_Port2Mode = (unsigned char) data[1]; |
-+----------------------------------------------------------------------------+
-| Output Parameters : - |
-+----------------------------------------------------------------------------+
-| Return Value :>0: No error |
-| -1: Port 2 mode selection is wrong |
-| .... |
-| -100 : Config command error |
-| -101 : Data size error |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- int i_ReturnValue = insn->n;
- unsigned char b_Command = 0;
-
- /************************/
- /* Test the buffer size */
- /************************/
-
- if (insn->n >= 1) {
- /*******************/
- /* Get the command */
- /* **************** */
-
- b_Command = (unsigned char) data[0];
-
- /********************/
- /* Test the command */
- /********************/
-
- if (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2) {
- /***************************************/
- /* Test the initialisation buffer size */
- /***************************************/
-
- if ((b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2)
- && (insn->n != 2)) {
- /*******************/
- /* Data size error */
- /*******************/
-
- printk("Buffer size error\n");
- i_ReturnValue = -101;
- }
- } else {
- /************************/
- /* Config command error */
- /************************/
-
- printk("Command selection error\n");
- i_ReturnValue = -100;
- }
- } else {
- /*******************/
- /* Data size error */
- /*******************/
-
- printk("Buffer size error\n");
- i_ReturnValue = -101;
- }
-
- /*********************************************************************************/
- /* Test if no error occur and APCI3XXX_TTL_INIT_DIRECTION_PORT2 command selected */
- /*********************************************************************************/
-
- if ((i_ReturnValue >= 0)
- && (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2)) {
- /**********************/
- /* Test the direction */
- /**********************/
-
- if ((data[1] == 0) || (data[1] == 0xFF)) {
- /**************************/
- /* Save the configuration */
- /**************************/
-
- devpriv->ul_TTLPortConfiguration[0] =
- devpriv->ul_TTLPortConfiguration[0] | data[1];
- } else {
- /************************/
- /* Port direction error */
- /************************/
-
- printk("Port 2 direction selection error\n");
- i_ReturnValue = -1;
- }
- }
-
- /**************************/
- /* Test if no error occur */
- /**************************/
-
- if (i_ReturnValue >= 0) {
- /***********************************/
- /* Test if TTL port initilaisation */
- /***********************************/
-
- if (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2) {
- /*************************/
- /* Set the configuration */
- /*************************/
-
- outl(data[1], devpriv->iobase + 224);
- }
- }
-
- return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| TTL INPUT FUNCTIONS |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI3XXX_InsnBitsTTLIO |
-| (struct comedi_device *dev, |
-| struct comedi_subdevice *s, |
-| struct comedi_insn *insn, |
-| unsigned int *data) |
-+----------------------------------------------------------------------------+
-| Task : Write the selected output mask and read the status from|
-| all TTL channles |
-+----------------------------------------------------------------------------+
-| Input Parameters : dw_ChannelMask = data [0]; |
-| dw_BitMask = data [1]; |
-+----------------------------------------------------------------------------+
-| Output Parameters : data[1] : All TTL channles states |
-+----------------------------------------------------------------------------+
-| Return Value : >0 : No error |
-| -4 : Channel mask error |
-| -101 : Data size error |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- int i_ReturnValue = insn->n;
- unsigned char b_ChannelCpt = 0;
- unsigned int dw_ChannelMask = 0;
- unsigned int dw_BitMask = 0;
- unsigned int dw_Status = 0;
-
- /************************/
- /* Test the buffer size */
- /************************/
-
- if (insn->n >= 2) {
- /*******************************/
- /* Get the channe and bit mask */
- /*******************************/
-
- dw_ChannelMask = data[0];
- dw_BitMask = data[1];
-
- /*************************/
- /* Test the channel mask */
- /*************************/
-
- if (((dw_ChannelMask & 0XFF00FF00) == 0) &&
- (((devpriv->ul_TTLPortConfiguration[0] & 0xFF) == 0xFF)
- || (((devpriv->ul_TTLPortConfiguration[0] &
- 0xFF) == 0)
- && ((dw_ChannelMask & 0XFF0000) ==
- 0)))) {
- /*********************************/
- /* Test if set/reset any channel */
- /*********************************/
-
- if (dw_ChannelMask) {
- /****************************************/
- /* Test if set/rest any port 0 channels */
- /****************************************/
-
- if (dw_ChannelMask & 0xFF) {
- /*******************************************/
- /* Read port 0 (first digital output port) */
- /*******************************************/
-
- dw_Status = inl(devpriv->iobase + 80);
-
- for (b_ChannelCpt = 0; b_ChannelCpt < 8;
- b_ChannelCpt++) {
- if ((dw_ChannelMask >>
- b_ChannelCpt) &
- 1) {
- dw_Status =
- (dw_Status &
- (0xFF - (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt));
- }
- }
-
- outl(dw_Status, devpriv->iobase + 80);
- }
-
- /****************************************/
- /* Test if set/rest any port 2 channels */
- /****************************************/
-
- if (dw_ChannelMask & 0xFF0000) {
- dw_BitMask = dw_BitMask >> 16;
- dw_ChannelMask = dw_ChannelMask >> 16;
-
- /********************************************/
- /* Read port 2 (second digital output port) */
- /********************************************/
-
- dw_Status = inl(devpriv->iobase + 112);
-
- for (b_ChannelCpt = 0; b_ChannelCpt < 8;
- b_ChannelCpt++) {
- if ((dw_ChannelMask >>
- b_ChannelCpt) &
- 1) {
- dw_Status =
- (dw_Status &
- (0xFF - (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt));
- }
- }
-
- outl(dw_Status, devpriv->iobase + 112);
- }
- }
-
- /*******************************************/
- /* Read port 0 (first digital output port) */
- /*******************************************/
-
- data[1] = inl(devpriv->iobase + 80);
-
- /******************************************/
- /* Read port 1 (first digital input port) */
- /******************************************/
-
- data[1] = data[1] | (inl(devpriv->iobase + 64) << 8);
-
- /************************/
- /* Test if port 2 input */
- /************************/
-
- if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF) == 0) {
- data[1] =
- data[1] | (inl(devpriv->iobase +
- 96) << 16);
- } else {
- data[1] =
- data[1] | (inl(devpriv->iobase +
- 112) << 16);
- }
- } else {
- /************************/
- /* Config command error */
- /************************/
-
- printk("Channel mask error\n");
- i_ReturnValue = -4;
- }
- } else {
- /*******************/
- /* Data size error */
- /*******************/
-
- printk("Buffer size error\n");
- i_ReturnValue = -101;
- }
-
- return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI3XXX_InsnReadTTLIO |
-| (struct comedi_device *dev, |
-| struct comedi_subdevice *s, |
-| struct comedi_insn *insn, |
-| unsigned int *data) |
-+----------------------------------------------------------------------------+
-| Task : Read the status from selected channel |
-+----------------------------------------------------------------------------+
-| Input Parameters : b_Channel = CR_CHAN(insn->chanspec) |
-+----------------------------------------------------------------------------+
-| Output Parameters : data[0] : Selected TTL channel state |
-+----------------------------------------------------------------------------+
-| Return Value : 0 : No error |
-| -3 : Channel selection error |
-| -101 : Data size error |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI3XXX_InsnReadTTLIO(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
- int i_ReturnValue = insn->n;
- unsigned int *pls_ReadData = data;
-
- /************************/
- /* Test the buffer size */
- /************************/
-
- if (insn->n >= 1) {
- /***********************/
- /* Test if read port 0 */
- /***********************/
-
- if (b_Channel < 8) {
- /*******************************************/
- /* Read port 0 (first digital output port) */
- /*******************************************/
-
- pls_ReadData[0] = inl(devpriv->iobase + 80);
- pls_ReadData[0] = (pls_ReadData[0] >> b_Channel) & 1;
- } else {
- /***********************/
- /* Test if read port 1 */
- /***********************/
-
- if ((b_Channel > 7) && (b_Channel < 16)) {
- /******************************************/
- /* Read port 1 (first digital input port) */
- /******************************************/
-
- pls_ReadData[0] = inl(devpriv->iobase + 64);
- pls_ReadData[0] =
- (pls_ReadData[0] >> (b_Channel -
- 8)) & 1;
- } else {
- /***********************/
- /* Test if read port 2 */
- /***********************/
-
- if ((b_Channel > 15) && (b_Channel < 24)) {
- /************************/
- /* Test if port 2 input */
- /************************/
-
- if ((devpriv->ul_TTLPortConfiguration[0]
- & 0xFF) == 0) {
- pls_ReadData[0] =
- inl(devpriv->iobase +
- 96);
- pls_ReadData[0] =
- (pls_ReadData[0] >>
- (b_Channel - 16)) & 1;
- } else {
- pls_ReadData[0] =
- inl(devpriv->iobase +
- 112);
- pls_ReadData[0] =
- (pls_ReadData[0] >>
- (b_Channel - 16)) & 1;
- }
- } else {
- /***************************/
- /* Channel selection error */
- /***************************/
-
- i_ReturnValue = -3;
- printk("Channel %d selection error\n",
- b_Channel);
- }
- }
- }
- } else {
- /*******************/
- /* Data size error */
- /*******************/
-
- printk("Buffer size error\n");
- i_ReturnValue = -101;
- }
-
- return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| TTL OUTPUT FUNCTIONS |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI3XXX_InsnWriteTTLIO |
-| (struct comedi_device *dev, |
-| struct comedi_subdevice *s, |
-| struct comedi_insn *insn, |
-| unsigned int *data) |
-+----------------------------------------------------------------------------+
-| Task : Set the state from TTL output channel |
-+----------------------------------------------------------------------------+
-| Input Parameters : b_Channel = CR_CHAN(insn->chanspec) |
-| b_State = data [0] |
-+----------------------------------------------------------------------------+
-| Output Parameters : - |
-+----------------------------------------------------------------------------+
-| Return Value : 0 : No error |
-| -3 : Channel selection error |
-| -101 : Data size error |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- int i_ReturnValue = insn->n;
- unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
- unsigned char b_State = 0;
- unsigned int dw_Status = 0;
-
- /************************/
- /* Test the buffer size */
- /************************/
-
- if (insn->n >= 1) {
- b_State = (unsigned char) data[0];
-
- /***********************/
- /* Test if read port 0 */
- /***********************/
-
- if (b_Channel < 8) {
- /*****************************************************************************/
- /* Read port 0 (first digital output port) and set/reset the selected channel */
- /*****************************************************************************/
-
- dw_Status = inl(devpriv->iobase + 80);
- dw_Status =
- (dw_Status & (0xFF -
- (1 << b_Channel))) | ((b_State & 1) <<
- b_Channel);
- outl(dw_Status, devpriv->iobase + 80);
- } else {
- /***********************/
- /* Test if read port 2 */
- /***********************/
-
- if ((b_Channel > 15) && (b_Channel < 24)) {
- /*************************/
- /* Test if port 2 output */
- /*************************/
-
- if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF)
- == 0xFF) {
- /*****************************************************************************/
- /* Read port 2 (first digital output port) and set/reset the selected channel */
- /*****************************************************************************/
-
- dw_Status = inl(devpriv->iobase + 112);
- dw_Status =
- (dw_Status & (0xFF -
- (1 << (b_Channel -
- 16)))) |
- ((b_State & 1) << (b_Channel -
- 16));
- outl(dw_Status, devpriv->iobase + 112);
- } else {
- /***************************/
- /* Channel selection error */
- /***************************/
-
- i_ReturnValue = -3;
- printk("Channel %d selection error\n",
- b_Channel);
- }
- } else {
- /***************************/
- /* Channel selection error */
- /***************************/
-
- i_ReturnValue = -3;
- printk("Channel %d selection error\n",
- b_Channel);
- }
- }
- } else {
- /*******************/
- /* Data size error */
- /*******************/
-
- printk("Buffer size error\n");
- i_ReturnValue = -101;
- }
-
- return i_ReturnValue;
-}
-
-static int apci3xxx_di_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
-
- data[1] = inl(devpriv->iobase + 32) & 0xf;
-
- return insn->n;
-}
-
-static int apci3xxx_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int mask = data[0];
- unsigned int bits = data[1];
-
- s->state = inl(devpriv->iobase + 48) & 0xf;
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
-
- outl(s->state, devpriv->iobase + 48);
- }
-
- data[1] = s->state;
-
- return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI3XXX_Reset(struct comedi_device *dev) | +----------------------------------------------------------------------------+
-| Task :resets all the registers |
-+----------------------------------------------------------------------------+
-| Input Parameters : struct comedi_device *dev |
-+----------------------------------------------------------------------------+
-| Output Parameters : - |
-+----------------------------------------------------------------------------+
-| Return Value : - |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI3XXX_Reset(struct comedi_device *dev)
-{
- struct addi_private *devpriv = dev->private;
- unsigned char b_Cpt = 0;
-
- /*************************/
- /* Disable the interrupt */
- /*************************/
-
- disable_irq(dev->irq);
-
- /****************************/
- /* Reset the interrupt flag */
- /****************************/
-
- devpriv->b_EocEosInterrupt = 0;
-
- /***************************/
- /* Clear the start command */
- /***************************/
-
- writel(0, devpriv->dw_AiBase + 8);
-
- /*****************************/
- /* Reset the interrupt flags */
- /*****************************/
-
- writel(readl(devpriv->dw_AiBase + 16), devpriv->dw_AiBase + 16);
-
- /*****************/
- /* clear the EOS */
- /*****************/
-
- readl(devpriv->dw_AiBase + 20);
-
- /******************/
- /* Clear the FIFO */
- /******************/
-
- for (b_Cpt = 0; b_Cpt < 16; b_Cpt++) {
- readl(devpriv->dw_AiBase + 28);
- }
-
- /************************/
- /* Enable the interrupt */
- /************************/
-
- enable_irq(dev->irq);
-
- return 0;
-}
diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c
index 3d4878facc26..8a93542faedc 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1032.c
@@ -20,13 +20,6 @@
* 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., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * You should also find the complete GPL in the COPYING file accompanying this
- * source code.
*/
#include <linux/pci.h>
diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c
index ed01c56630bb..b626738bb73c 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1516.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1516.c
@@ -20,13 +20,6 @@
* 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.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * You should also find the complete GPL in the COPYING file accompanying
- * this source code.
*/
#include <linux/pci.h>
@@ -203,7 +196,6 @@ static void apci1516_detach(struct comedi_device *dev)
{
if (dev->iobase)
apci1516_reset(dev);
- comedi_spriv_free(dev, 2);
comedi_pci_disable(dev);
}
diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c
index 4c6a9b5a06ae..1f7bed9a3f7f 100644
--- a/drivers/staging/comedi/drivers/addi_apci_16xx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c
@@ -20,13 +20,6 @@
* 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.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * You should also find the complete GPL in the COPYING file accompanying
- * this source code.
*/
#include <linux/pci.h>
diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c
index b666637f61be..89ead8eb3c70 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2032.c
@@ -20,13 +20,6 @@
* 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.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * You should also find the complete GPL in the COPYING file accompanying
- * this source code.
*/
#include <linux/pci.h>
@@ -354,7 +347,6 @@ static void apci2032_detach(struct comedi_device *dev)
free_irq(dev->irq, dev);
if (dev->read_subdev)
kfree(dev->read_subdev->private);
- comedi_spriv_free(dev, 1);
comedi_pci_disable(dev);
}
diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c
index 1cdc08d79792..ca1bd92ecb17 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2200.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2200.c
@@ -20,13 +20,6 @@
* 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.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * You should also find the complete GPL in the COPYING file accompanying
- * this source code.
*/
#include <linux/pci.h>
@@ -130,7 +123,6 @@ static void apci2200_detach(struct comedi_device *dev)
{
if (dev->iobase)
apci2200_reset(dev);
- comedi_spriv_free(dev, 2);
comedi_pci_disable(dev);
}
diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c
index 317a26d97c2e..61452848510f 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3120.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3120.c
@@ -103,8 +103,6 @@ static int apci3120_auto_attach(struct comedi_device *dev,
if (devpriv->ul_DmaBufferVirtual[i]) {
devpriv->ui_DmaBufferPages[i] = pages;
devpriv->ui_DmaBufferSize[i] = PAGE_SIZE * pages;
- devpriv->ui_DmaBufferSamples[i] =
- devpriv->ui_DmaBufferSize[i] >> 1;
devpriv->ul_DmaBufferHw[i] =
virt_to_bus((void *)devpriv->
ul_DmaBufferVirtual[i]);
@@ -138,9 +136,6 @@ static int apci3120_auto_attach(struct comedi_device *dev,
s->len_chanlist = this_board->i_AiChannelList;
s->range_table = &range_apci3120_ai;
- /* Set the initialisation flag */
- devpriv->b_AiInitialisation = 1;
-
s->insn_config = i_APCI3120_InsnConfigAnalogInput;
s->insn_read = i_APCI3120_InsnReadAnalogInput;
s->do_cmdtest = i_APCI3120_CommandTestAnalogInput;
diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c
index a0cf6ecdef0e..f9b63689a12a 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3501.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3501.c
@@ -20,13 +20,6 @@
* 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.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * You should also find the complete GPL in the COPYING file accompanying
- * this source code.
*/
#include <linux/pci.h>
diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
index ec4d6ca6863f..5b37cbf9228e 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
@@ -1,14 +1,57 @@
+/*
+ * addi_apci_3xxx.c
+ * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+ * Project manager: S. Weber
+ *
+ * ADDI-DATA GmbH
+ * Dieselstrasse 3
+ * D-77833 Ottersweier
+ * Tel: +19(0)7223/9493-0
+ * Fax: +49(0)7223/9493-92
+ * http://www.addi-data.com
+ * info@addi-data.com
+ *
+ * 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.
+ */
+
#include <linux/pci.h>
+#include <linux/interrupt.h>
#include "../comedidev.h"
+
#include "comedi_fc.h"
-#include "amcc_s5933.h"
-#include "addi-data/addi_common.h"
+#define CONV_UNIT_NS (1 << 0)
+#define CONV_UNIT_US (1 << 1)
+#define CONV_UNIT_MS (1 << 2)
-#include "addi-data/addi_eeprom.c"
-#include "addi-data/hwdrv_apci3xxx.c"
-#include "addi-data/addi_common.c"
+static const struct comedi_lrange apci3xxx_ai_range = {
+ 8, {
+ BIP_RANGE(10),
+ BIP_RANGE(5),
+ BIP_RANGE(2),
+ BIP_RANGE(1),
+ UNI_RANGE(10),
+ UNI_RANGE(5),
+ UNI_RANGE(2),
+ UNI_RANGE(1)
+ }
+};
+
+static const struct comedi_lrange apci3xxx_ao_range = {
+ 2, {
+ BIP_RANGE(10),
+ UNI_RANGE(10)
+ }
+};
enum apci3xxx_boardid {
BOARD_APCI3000_16,
@@ -38,651 +81,853 @@ enum apci3xxx_boardid {
BOARD_APCI3500,
};
-static const struct addi_board apci3xxx_boardtypes[] = {
+struct apci3xxx_boardinfo {
+ const char *name;
+ int ai_subdev_flags;
+ int ai_n_chan;
+ unsigned int ai_maxdata;
+ unsigned char ai_conv_units;
+ unsigned int ai_min_acq_ns;
+ unsigned int has_ao:1;
+ unsigned int has_dig_in:1;
+ unsigned int has_dig_out:1;
+ unsigned int has_ttl_io:1;
+};
+
+static const struct apci3xxx_boardinfo apci3xxx_boardtypes[] = {
[BOARD_APCI3000_16] = {
- .pc_DriverName = "apci3000-16",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 16,
- .i_NbrAiChannelDiff = 8,
- .i_AiChannelList = 16,
- .i_AiMaxdata = 4095,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 10000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3000-16",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 16,
+ .ai_maxdata = 0x0fff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 10000,
+ .has_ttl_io = 1,
},
[BOARD_APCI3000_8] = {
- .pc_DriverName = "apci3000-8",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 8,
- .i_NbrAiChannelDiff = 4,
- .i_AiChannelList = 8,
- .i_AiMaxdata = 4095,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 10000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3000-8",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 8,
+ .ai_maxdata = 0x0fff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 10000,
+ .has_ttl_io = 1,
},
[BOARD_APCI3000_4] = {
- .pc_DriverName = "apci3000-4",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 4,
- .i_NbrAiChannelDiff = 2,
- .i_AiChannelList = 4,
- .i_AiMaxdata = 4095,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 10000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3000-4",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 4,
+ .ai_maxdata = 0x0fff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 10000,
+ .has_ttl_io = 1,
},
[BOARD_APCI3006_16] = {
- .pc_DriverName = "apci3006-16",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 16,
- .i_NbrAiChannelDiff = 8,
- .i_AiChannelList = 16,
- .i_AiMaxdata = 65535,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 10000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3006-16",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 16,
+ .ai_maxdata = 0xffff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 10000,
+ .has_ttl_io = 1,
},
[BOARD_APCI3006_8] = {
- .pc_DriverName = "apci3006-8",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 8,
- .i_NbrAiChannelDiff = 4,
- .i_AiChannelList = 8,
- .i_AiMaxdata = 65535,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 10000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3006-8",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 8,
+ .ai_maxdata = 0xffff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 10000,
+ .has_ttl_io = 1,
},
[BOARD_APCI3006_4] = {
- .pc_DriverName = "apci3006-4",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 4,
- .i_NbrAiChannelDiff = 2,
- .i_AiChannelList = 4,
- .i_AiMaxdata = 65535,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 10000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3006-4",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 4,
+ .ai_maxdata = 0xffff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 10000,
+ .has_ttl_io = 1,
},
[BOARD_APCI3010_16] = {
- .pc_DriverName = "apci3010-16",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 16,
- .i_NbrAiChannelDiff = 8,
- .i_AiChannelList = 16,
- .i_AiMaxdata = 4095,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .i_NbrDiChannel = 4,
- .i_NbrDoChannel = 4,
- .i_DoMaxdata = 1,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 5000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .di_bits = apci3xxx_di_insn_bits,
- .do_bits = apci3xxx_do_insn_bits,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3010-16",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 16,
+ .ai_maxdata = 0x0fff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 5000,
+ .has_dig_in = 1,
+ .has_dig_out = 1,
+ .has_ttl_io = 1,
},
[BOARD_APCI3010_8] = {
- .pc_DriverName = "apci3010-8",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 8,
- .i_NbrAiChannelDiff = 4,
- .i_AiChannelList = 8,
- .i_AiMaxdata = 4095,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .i_NbrDiChannel = 4,
- .i_NbrDoChannel = 4,
- .i_DoMaxdata = 1,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 5000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .di_bits = apci3xxx_di_insn_bits,
- .do_bits = apci3xxx_do_insn_bits,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3010-8",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 8,
+ .ai_maxdata = 0x0fff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 5000,
+ .has_dig_in = 1,
+ .has_dig_out = 1,
+ .has_ttl_io = 1,
},
[BOARD_APCI3010_4] = {
- .pc_DriverName = "apci3010-4",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 4,
- .i_NbrAiChannelDiff = 2,
- .i_AiChannelList = 4,
- .i_AiMaxdata = 4095,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .i_NbrDiChannel = 4,
- .i_NbrDoChannel = 4,
- .i_DoMaxdata = 1,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 5000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .di_bits = apci3xxx_di_insn_bits,
- .do_bits = apci3xxx_do_insn_bits,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3010-4",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 4,
+ .ai_maxdata = 0x0fff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 5000,
+ .has_dig_in = 1,
+ .has_dig_out = 1,
+ .has_ttl_io = 1,
},
[BOARD_APCI3016_16] = {
- .pc_DriverName = "apci3016-16",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 16,
- .i_NbrAiChannelDiff = 8,
- .i_AiChannelList = 16,
- .i_AiMaxdata = 65535,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .i_NbrDiChannel = 4,
- .i_NbrDoChannel = 4,
- .i_DoMaxdata = 1,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 5000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .di_bits = apci3xxx_di_insn_bits,
- .do_bits = apci3xxx_do_insn_bits,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3016-16",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 16,
+ .ai_maxdata = 0xffff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 5000,
+ .has_dig_in = 1,
+ .has_dig_out = 1,
+ .has_ttl_io = 1,
},
[BOARD_APCI3016_8] = {
- .pc_DriverName = "apci3016-8",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 8,
- .i_NbrAiChannelDiff = 4,
- .i_AiChannelList = 8,
- .i_AiMaxdata = 65535,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .i_NbrDiChannel = 4,
- .i_NbrDoChannel = 4,
- .i_DoMaxdata = 1,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 5000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .di_bits = apci3xxx_di_insn_bits,
- .do_bits = apci3xxx_do_insn_bits,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3016-8",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 8,
+ .ai_maxdata = 0xffff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 5000,
+ .has_dig_in = 1,
+ .has_dig_out = 1,
+ .has_ttl_io = 1,
},
[BOARD_APCI3016_4] = {
- .pc_DriverName = "apci3016-4",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 4,
- .i_NbrAiChannelDiff = 2,
- .i_AiChannelList = 4,
- .i_AiMaxdata = 65535,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .i_NbrDiChannel = 4,
- .i_NbrDoChannel = 4,
- .i_DoMaxdata = 1,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 5000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .di_bits = apci3xxx_di_insn_bits,
- .do_bits = apci3xxx_do_insn_bits,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3016-4",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 4,
+ .ai_maxdata = 0xffff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 5000,
+ .has_dig_in = 1,
+ .has_dig_out = 1,
+ .has_ttl_io = 1,
},
[BOARD_APCI3100_16_4] = {
- .pc_DriverName = "apci3100-16-4",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 16,
- .i_NbrAiChannelDiff = 8,
- .i_AiChannelList = 16,
- .i_NbrAoChannel = 4,
- .i_AiMaxdata = 4095,
- .i_AoMaxdata = 4095,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .pr_AoRangelist = &range_apci3XXX_ao,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 10000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .ao_write = i_APCI3XXX_InsnWriteAnalogOutput,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3100-16-4",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 16,
+ .ai_maxdata = 0x0fff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 10000,
+ .has_ao = 1,
+ .has_ttl_io = 1,
},
[BOARD_APCI3100_8_4] = {
- .pc_DriverName = "apci3100-8-4",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 8,
- .i_NbrAiChannelDiff = 4,
- .i_AiChannelList = 8,
- .i_NbrAoChannel = 4,
- .i_AiMaxdata = 4095,
- .i_AoMaxdata = 4095,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .pr_AoRangelist = &range_apci3XXX_ao,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 10000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .ao_write = i_APCI3XXX_InsnWriteAnalogOutput,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3100-8-4",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 8,
+ .ai_maxdata = 0x0fff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 10000,
+ .has_ao = 1,
+ .has_ttl_io = 1,
},
[BOARD_APCI3106_16_4] = {
- .pc_DriverName = "apci3106-16-4",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 16,
- .i_NbrAiChannelDiff = 8,
- .i_AiChannelList = 16,
- .i_NbrAoChannel = 4,
- .i_AiMaxdata = 65535,
- .i_AoMaxdata = 4095,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .pr_AoRangelist = &range_apci3XXX_ao,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 10000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .ao_write = i_APCI3XXX_InsnWriteAnalogOutput,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3106-16-4",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 16,
+ .ai_maxdata = 0xffff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 10000,
+ .has_ao = 1,
+ .has_ttl_io = 1,
},
[BOARD_APCI3106_8_4] = {
- .pc_DriverName = "apci3106-8-4",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 8,
- .i_NbrAiChannelDiff = 4,
- .i_AiChannelList = 8,
- .i_NbrAoChannel = 4,
- .i_AiMaxdata = 65535,
- .i_AoMaxdata = 4095,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .pr_AoRangelist = &range_apci3XXX_ao,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 10000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .ao_write = i_APCI3XXX_InsnWriteAnalogOutput,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3106-8-4",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 8,
+ .ai_maxdata = 0xffff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 10000,
+ .has_ao = 1,
+ .has_ttl_io = 1,
},
[BOARD_APCI3110_16_4] = {
- .pc_DriverName = "apci3110-16-4",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 16,
- .i_NbrAiChannelDiff = 8,
- .i_AiChannelList = 16,
- .i_NbrAoChannel = 4,
- .i_AiMaxdata = 4095,
- .i_AoMaxdata = 4095,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .pr_AoRangelist = &range_apci3XXX_ao,
- .i_NbrDiChannel = 4,
- .i_NbrDoChannel = 4,
- .i_DoMaxdata = 1,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 5000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .ao_write = i_APCI3XXX_InsnWriteAnalogOutput,
- .di_bits = apci3xxx_di_insn_bits,
- .do_bits = apci3xxx_do_insn_bits,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3110-16-4",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 16,
+ .ai_maxdata = 0x0fff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 5000,
+ .has_ao = 1,
+ .has_dig_in = 1,
+ .has_dig_out = 1,
+ .has_ttl_io = 1,
},
[BOARD_APCI3110_8_4] = {
- .pc_DriverName = "apci3110-8-4",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 8,
- .i_NbrAiChannelDiff = 4,
- .i_AiChannelList = 8,
- .i_NbrAoChannel = 4,
- .i_AiMaxdata = 4095,
- .i_AoMaxdata = 4095,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .pr_AoRangelist = &range_apci3XXX_ao,
- .i_NbrDiChannel = 4,
- .i_NbrDoChannel = 4,
- .i_DoMaxdata = 1,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 5000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .ao_write = i_APCI3XXX_InsnWriteAnalogOutput,
- .di_bits = apci3xxx_di_insn_bits,
- .do_bits = apci3xxx_do_insn_bits,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3110-8-4",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 8,
+ .ai_maxdata = 0x0fff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 5000,
+ .has_ao = 1,
+ .has_dig_in = 1,
+ .has_dig_out = 1,
+ .has_ttl_io = 1,
},
[BOARD_APCI3116_16_4] = {
- .pc_DriverName = "apci3116-16-4",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 16,
- .i_NbrAiChannelDiff = 8,
- .i_AiChannelList = 16,
- .i_NbrAoChannel = 4,
- .i_AiMaxdata = 65535,
- .i_AoMaxdata = 4095,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .pr_AoRangelist = &range_apci3XXX_ao,
- .i_NbrDiChannel = 4,
- .i_NbrDoChannel = 4,
- .i_DoMaxdata = 1,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 5000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .ao_write = i_APCI3XXX_InsnWriteAnalogOutput,
- .di_bits = apci3xxx_di_insn_bits,
- .do_bits = apci3xxx_do_insn_bits,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3116-16-4",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 16,
+ .ai_maxdata = 0xffff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 5000,
+ .has_ao = 1,
+ .has_dig_in = 1,
+ .has_dig_out = 1,
+ .has_ttl_io = 1,
},
[BOARD_APCI3116_8_4] = {
- .pc_DriverName = "apci3116-8-4",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannel = 8,
- .i_NbrAiChannelDiff = 4,
- .i_AiChannelList = 8,
- .i_NbrAoChannel = 4,
- .i_AiMaxdata = 65535,
- .i_AoMaxdata = 4095,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .pr_AoRangelist = &range_apci3XXX_ao,
- .i_NbrDiChannel = 4,
- .i_NbrDoChannel = 4,
- .i_DoMaxdata = 1,
- .i_NbrTTLChannel = 24,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 5000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .ao_write = i_APCI3XXX_InsnWriteAnalogOutput,
- .di_bits = apci3xxx_di_insn_bits,
- .do_bits = apci3xxx_do_insn_bits,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3116-8-4",
+ .ai_subdev_flags = SDF_COMMON | SDF_GROUND | SDF_DIFF,
+ .ai_n_chan = 8,
+ .ai_maxdata = 0xffff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 5000,
+ .has_ao = 1,
+ .has_dig_in = 1,
+ .has_dig_out = 1,
+ .has_ttl_io = 1,
},
[BOARD_APCI3003] = {
- .pc_DriverName = "apci3003",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannelDiff = 4,
- .i_AiChannelList = 4,
- .i_AiMaxdata = 65535,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .i_NbrDiChannel = 4,
- .i_NbrDoChannel = 4,
- .i_DoMaxdata = 1,
- .b_AvailableConvertUnit = 7,
- .ui_MinAcquisitiontimeNs = 2500,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .di_bits = apci3xxx_di_insn_bits,
- .do_bits = apci3xxx_do_insn_bits,
+ .name = "apci3003",
+ .ai_subdev_flags = SDF_DIFF,
+ .ai_n_chan = 4,
+ .ai_maxdata = 0xffff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US |
+ CONV_UNIT_NS,
+ .ai_min_acq_ns = 2500,
+ .has_dig_in = 1,
+ .has_dig_out = 1,
},
[BOARD_APCI3002_16] = {
- .pc_DriverName = "apci3002-16",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannelDiff = 16,
- .i_AiChannelList = 16,
- .i_AiMaxdata = 65535,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .i_NbrDiChannel = 4,
- .i_NbrDoChannel = 4,
- .i_DoMaxdata = 1,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 5000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .di_bits = apci3xxx_di_insn_bits,
- .do_bits = apci3xxx_do_insn_bits,
+ .name = "apci3002-16",
+ .ai_subdev_flags = SDF_DIFF,
+ .ai_n_chan = 16,
+ .ai_maxdata = 0xffff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 5000,
+ .has_dig_in = 1,
+ .has_dig_out = 1,
},
[BOARD_APCI3002_8] = {
- .pc_DriverName = "apci3002-8",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannelDiff = 8,
- .i_AiChannelList = 8,
- .i_AiMaxdata = 65535,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .i_NbrDiChannel = 4,
- .i_NbrDoChannel = 4,
- .i_DoMaxdata = 1,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 5000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .di_bits = apci3xxx_di_insn_bits,
- .do_bits = apci3xxx_do_insn_bits,
+ .name = "apci3002-8",
+ .ai_subdev_flags = SDF_DIFF,
+ .ai_n_chan = 8,
+ .ai_maxdata = 0xffff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 5000,
+ .has_dig_in = 1,
+ .has_dig_out = 1,
},
[BOARD_APCI3002_4] = {
- .pc_DriverName = "apci3002-4",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAiChannelDiff = 4,
- .i_AiChannelList = 4,
- .i_AiMaxdata = 65535,
- .pr_AiRangelist = &range_apci3XXX_ai,
- .i_NbrDiChannel = 4,
- .i_NbrDoChannel = 4,
- .i_DoMaxdata = 1,
- .b_AvailableConvertUnit = 6,
- .ui_MinAcquisitiontimeNs = 5000,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ai_config = i_APCI3XXX_InsnConfigAnalogInput,
- .ai_read = i_APCI3XXX_InsnReadAnalogInput,
- .di_bits = apci3xxx_di_insn_bits,
- .do_bits = apci3xxx_do_insn_bits,
+ .name = "apci3002-4",
+ .ai_subdev_flags = SDF_DIFF,
+ .ai_n_chan = 4,
+ .ai_maxdata = 0xffff,
+ .ai_conv_units = CONV_UNIT_MS | CONV_UNIT_US,
+ .ai_min_acq_ns = 5000,
+ .has_dig_in = 1,
+ .has_dig_out = 1,
},
[BOARD_APCI3500] = {
- .pc_DriverName = "apci3500",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .pc_EepromChip = ADDIDATA_9054,
- .i_NbrAoChannel = 4,
- .i_AoMaxdata = 4095,
- .pr_AoRangelist = &range_apci3XXX_ao,
- .i_NbrTTLChannel = 24,
- .interrupt = v_APCI3XXX_Interrupt,
- .reset = i_APCI3XXX_Reset,
- .ao_write = i_APCI3XXX_InsnWriteAnalogOutput,
- .ttl_config = i_APCI3XXX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI3XXX_InsnBitsTTLIO,
- .ttl_read = i_APCI3XXX_InsnReadTTLIO,
- .ttl_write = i_APCI3XXX_InsnWriteTTLIO,
+ .name = "apci3500",
+ .has_ao = 1,
+ .has_ttl_io = 1,
},
};
+struct apci3xxx_private {
+ void __iomem *mmio;
+ unsigned int ai_timer;
+ unsigned char ai_time_base;
+};
+
+static irqreturn_t apci3xxx_irq_handler(int irq, void *d)
+{
+ struct comedi_device *dev = d;
+ struct apci3xxx_private *devpriv = dev->private;
+ struct comedi_subdevice *s = dev->read_subdev;
+ unsigned int status;
+ unsigned int val;
+
+ /* Test if interrupt occur */
+ status = readl(devpriv->mmio + 16);
+ if ((status & 0x2) == 0x2) {
+ /* Reset the interrupt */
+ writel(status, devpriv->mmio + 16);
+
+ val = readl(devpriv->mmio + 28);
+ comedi_buf_put(s->async, val);
+
+ s->async->events |= COMEDI_CB_EOA;
+ comedi_event(dev, s);
+
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+static int apci3xxx_ai_started(struct comedi_device *dev)
+{
+ struct apci3xxx_private *devpriv = dev->private;
+
+ if ((readl(devpriv->mmio + 8) & 0x80000) == 0x80000)
+ return 1;
+ else
+ return 0;
+
+}
+
+static int apci3xxx_ai_setup(struct comedi_device *dev, unsigned int chanspec)
+{
+ struct apci3xxx_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(chanspec);
+ unsigned int range = CR_RANGE(chanspec);
+ unsigned int aref = CR_AREF(chanspec);
+ unsigned int delay_mode;
+ unsigned int val;
+
+ if (apci3xxx_ai_started(dev))
+ return -EBUSY;
+
+ /* Clear the FIFO */
+ writel(0x10000, devpriv->mmio + 12);
+
+ /* Get and save the delay mode */
+ delay_mode = readl(devpriv->mmio + 4);
+ delay_mode &= 0xfffffef0;
+
+ /* Channel configuration selection */
+ writel(delay_mode, devpriv->mmio + 4);
+
+ /* Make the configuration */
+ val = (range & 3) | ((range >> 2) << 6) |
+ ((aref == AREF_DIFF) << 7);
+ writel(val, devpriv->mmio + 0);
+
+ /* Channel selection */
+ writel(delay_mode | 0x100, devpriv->mmio + 4);
+ writel(chan, devpriv->mmio + 0);
+
+ /* Restore delay mode */
+ writel(delay_mode, devpriv->mmio + 4);
+
+ /* Set the number of sequence to 1 */
+ writel(1, devpriv->mmio + 48);
+
+ return 0;
+}
+
+static int apci3xxx_ai_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ struct apci3xxx_private *devpriv = dev->private;
+ unsigned int val;
+ int ret;
+ int i;
+
+ ret = apci3xxx_ai_setup(dev, insn->chanspec);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < insn->n; i++) {
+ /* Start the conversion */
+ writel(0x80000, devpriv->mmio + 8);
+
+ /* Wait the EOS */
+ do {
+ val = readl(devpriv->mmio + 20);
+ val &= 0x1;
+ } while (!val);
+
+ /* Read the analog value */
+ data[i] = readl(devpriv->mmio + 28);
+ }
+
+ return insn->n;
+}
+
+static int apci3xxx_ai_ns_to_timer(struct comedi_device *dev,
+ unsigned int *ns, int round_mode)
+{
+ const struct apci3xxx_boardinfo *board = comedi_board(dev);
+ struct apci3xxx_private *devpriv = dev->private;
+ unsigned int base;
+ unsigned int timer;
+ int time_base;
+
+ /* time_base: 0 = ns, 1 = us, 2 = ms */
+ for (time_base = 0; time_base < 3; time_base++) {
+ /* skip unsupported time bases */
+ if (!(board->ai_conv_units & (1 << time_base)))
+ continue;
+
+ switch (time_base) {
+ case 0:
+ base = 1;
+ break;
+ case 1:
+ base = 1000;
+ break;
+ case 2:
+ base = 1000000;
+ break;
+ }
+
+ switch (round_mode) {
+ case TRIG_ROUND_NEAREST:
+ default:
+ timer = (*ns + base / 2) / base;
+ break;
+ case TRIG_ROUND_DOWN:
+ timer = *ns / base;
+ break;
+ case TRIG_ROUND_UP:
+ timer = (*ns + base - 1) / base;
+ break;
+ }
+
+ if (timer < 0x10000) {
+ devpriv->ai_time_base = time_base;
+ devpriv->ai_timer = timer;
+ *ns = timer * time_base;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+static int apci3xxx_ai_cmdtest(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_cmd *cmd)
+{
+ const struct apci3xxx_boardinfo *board = comedi_board(dev);
+ int err = 0;
+ unsigned int tmp;
+
+ /* Step 1 : check if triggers are trivially valid */
+
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+
+ if (err)
+ return 1;
+
+ /* Step 2a : make sure trigger sources are unique */
+
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
+
+ if (err)
+ return 2;
+
+ /* Step 3: check if arguments are trivially valid */
+
+ err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+ err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+ err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+ board->ai_min_acq_ns);
+ err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+ if (cmd->stop_src == TRIG_COUNT)
+ err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+ else /* TRIG_NONE */
+ err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+
+ if (err)
+ return 3;
+
+ /* step 4: fix up any arguments */
+
+ /*
+ * FIXME: The hardware supports multiple scan modes but the original
+ * addi-data driver only supported reading a single channel with
+ * interrupts. Need a proper datasheet to fix this.
+ *
+ * The following scan modes are supported by the hardware:
+ * 1) Single software scan
+ * 2) Single hardware triggered scan
+ * 3) Continuous software scan
+ * 4) Continuous software scan with timer delay
+ * 5) Continuous hardware triggered scan
+ * 6) Continuous hardware triggered scan with timer delay
+ *
+ * For now, limit the chanlist to a single channel.
+ */
+ if (cmd->chanlist_len > 1) {
+ cmd->chanlist_len = 1;
+ err |= -EINVAL;
+ }
+
+ tmp = cmd->convert_arg;
+ err |= apci3xxx_ai_ns_to_timer(dev, &cmd->convert_arg,
+ cmd->flags & TRIG_ROUND_MASK);
+ if (tmp != cmd->convert_arg)
+ err |= -EINVAL;
+
+ if (err)
+ return 4;
+
+ return 0;
+}
+
+static int apci3xxx_ai_cmd(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ struct apci3xxx_private *devpriv = dev->private;
+ struct comedi_cmd *cmd = &s->async->cmd;
+ int ret;
+
+ ret = apci3xxx_ai_setup(dev, cmd->chanlist[0]);
+ if (ret)
+ return ret;
+
+ /* Set the convert timing unit */
+ writel(devpriv->ai_time_base, devpriv->mmio + 36);
+
+ /* Set the convert timing */
+ writel(devpriv->ai_timer, devpriv->mmio + 32);
+
+ /* Start the conversion */
+ writel(0x180000, devpriv->mmio + 8);
+
+ return 0;
+}
+
+static int apci3xxx_ai_cancel(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ return 0;
+}
+
+static int apci3xxx_ao_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ struct apci3xxx_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int range = CR_RANGE(insn->chanspec);
+ unsigned int status;
+ int i;
+
+ for (i = 0; i < insn->n; i++) {
+ /* Set the range selection */
+ writel(range, devpriv->mmio + 96);
+
+ /* Write the analog value to the selected channel */
+ writel((data[i] << 8) | chan, devpriv->mmio + 100);
+
+ /* Wait the end of transfer */
+ do {
+ status = readl(devpriv->mmio + 96);
+ } while ((status & 0x100) != 0x100);
+ }
+
+ return insn->n;
+}
+
+static int apci3xxx_di_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ data[1] = inl(dev->iobase + 32) & 0xf;
+
+ return insn->n;
+}
+
+static int apci3xxx_do_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ unsigned int mask = data[0];
+ unsigned int bits = data[1];
+
+ s->state = inl(dev->iobase + 48) & 0xf;
+ if (mask) {
+ s->state &= ~mask;
+ s->state |= (bits & mask);
+
+ outl(s->state, dev->iobase + 48);
+ }
+
+ data[1] = s->state;
+
+ return insn->n;
+}
+
+static int apci3xxx_dio_insn_config(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int mask = 1 << chan;
+ unsigned int bits;
+
+ /*
+ * Port 0 (channels 0-7) are always inputs
+ * Port 1 (channels 8-15) are always outputs
+ * Port 2 (channels 16-23) are programmable i/o
+ *
+ * Changing any channel in port 2 changes the entire port.
+ */
+ if (mask & 0xff0000)
+ bits = 0xff0000;
+ else
+ bits = 0;
+
+ switch (data[0]) {
+ case INSN_CONFIG_DIO_INPUT:
+ s->io_bits &= ~bits;
+ break;
+ case INSN_CONFIG_DIO_OUTPUT:
+ s->io_bits |= bits;
+ break;
+ case INSN_CONFIG_DIO_QUERY:
+ data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
+ return insn->n;
+ default:
+ return -EINVAL;
+ }
+
+ /* update port 2 configuration */
+ if (bits)
+ outl((s->io_bits >> 24) & 0xff, dev->iobase + 224);
+
+ return insn->n;
+}
+
+static int apci3xxx_dio_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ unsigned int mask = data[0];
+ unsigned int bits = data[1];
+ unsigned int val;
+
+ /* only update output channels */
+ mask &= s->io_bits;
+ if (mask) {
+ s->state &= ~mask;
+ s->state |= (bits & mask);
+
+ if (mask & 0xff)
+ outl(s->state & 0xff, dev->iobase + 80);
+ if (mask & 0xff0000)
+ outl((s->state >> 16) & 0xff, dev->iobase + 112);
+ }
+
+ val = inl(dev->iobase + 80);
+ val |= (inl(dev->iobase + 64) << 8);
+ if (s->io_bits & 0xff0000)
+ val |= (inl(dev->iobase + 112) << 16);
+ else
+ val |= (inl(dev->iobase + 96) << 16);
+
+ data[1] = val;
+
+ return insn->n;
+}
+
+static int apci3xxx_reset(struct comedi_device *dev)
+{
+ struct apci3xxx_private *devpriv = dev->private;
+ unsigned int val;
+ int i;
+
+ /* Disable the interrupt */
+ disable_irq(dev->irq);
+
+ /* Clear the start command */
+ writel(0, devpriv->mmio + 8);
+
+ /* Reset the interrupt flags */
+ val = readl(devpriv->mmio + 16);
+ writel(val, devpriv->mmio + 16);
+
+ /* clear the EOS */
+ readl(devpriv->mmio + 20);
+
+ /* Clear the FIFO */
+ for (i = 0; i < 16; i++)
+ val = readl(devpriv->mmio + 28);
+
+ /* Enable the interrupt */
+ enable_irq(dev->irq);
+
+ return 0;
+}
+
static int apci3xxx_auto_attach(struct comedi_device *dev,
unsigned long context)
{
- const struct addi_board *board = NULL;
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ const struct apci3xxx_boardinfo *board = NULL;
+ struct apci3xxx_private *devpriv;
+ struct comedi_subdevice *s;
+ int n_subdevices;
+ int subdev;
+ int ret;
if (context < ARRAY_SIZE(apci3xxx_boardtypes))
board = &apci3xxx_boardtypes[context];
if (!board)
return -ENODEV;
dev->board_ptr = board;
+ dev->board_name = board->name;
+
+ devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+ if (!devpriv)
+ return -ENOMEM;
+ dev->private = devpriv;
+
+ ret = comedi_pci_enable(dev);
+ if (ret)
+ return ret;
+
+ dev->iobase = pci_resource_start(pcidev, 2);
+ devpriv->mmio = pci_ioremap_bar(pcidev, 3);
+
+ if (pcidev->irq > 0) {
+ ret = request_irq(pcidev->irq, apci3xxx_irq_handler,
+ IRQF_SHARED, dev->board_name, dev);
+ if (ret == 0)
+ dev->irq = pcidev->irq;
+ }
+
+ n_subdevices = (board->ai_n_chan ? 0 : 1) + board->has_ao +
+ board->has_dig_in + board->has_dig_out +
+ board->has_ttl_io;
+ ret = comedi_alloc_subdevices(dev, n_subdevices);
+ if (ret)
+ return ret;
+
+ subdev = 0;
+
+ /* Analog Input subdevice */
+ if (board->ai_n_chan) {
+ s = &dev->subdevices[subdev];
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | board->ai_subdev_flags;
+ s->n_chan = board->ai_n_chan;
+ s->maxdata = board->ai_maxdata;
+ s->len_chanlist = s->n_chan;
+ s->range_table = &apci3xxx_ai_range;
+ s->insn_read = apci3xxx_ai_insn_read;
+ if (dev->irq) {
+ dev->read_subdev = s;
+ s->subdev_flags |= SDF_CMD_READ;
+ s->do_cmdtest = apci3xxx_ai_cmdtest;
+ s->do_cmd = apci3xxx_ai_cmd;
+ s->cancel = apci3xxx_ai_cancel;
+ }
+
+ subdev++;
+ }
+
+ /* Analog Output subdevice */
+ if (board->has_ao) {
+ s = &dev->subdevices[subdev];
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
+ s->n_chan = 4;
+ s->maxdata = 0x0fff;
+ s->range_table = &apci3xxx_ao_range;
+ s->insn_write = apci3xxx_ao_insn_write;
+
+ subdev++;
+ }
+
+ /* Digital Input subdevice */
+ if (board->has_dig_in) {
+ s = &dev->subdevices[subdev];
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 4;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = apci3xxx_di_insn_bits;
+
+ subdev++;
+ }
+
+ /* Digital Output subdevice */
+ if (board->has_dig_out) {
+ s = &dev->subdevices[subdev];
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITEABLE;
+ s->n_chan = 4;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = apci3xxx_do_insn_bits;
+
+ subdev++;
+ }
+
+ /* TTL Digital I/O subdevice */
+ if (board->has_ttl_io) {
+ s = &dev->subdevices[subdev];
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITEABLE;
+ s->n_chan = 24;
+ s->maxdata = 1;
+ s->io_bits = 0xff; /* channels 0-7 are always outputs */
+ s->range_table = &range_digital;
+ s->insn_config = apci3xxx_dio_insn_config;
+ s->insn_bits = apci3xxx_dio_insn_bits;
+
+ subdev++;
+ }
+
+ apci3xxx_reset(dev);
+ return 0;
+}
+
+static void apci3xxx_detach(struct comedi_device *dev)
+{
+ struct apci3xxx_private *devpriv = dev->private;
- return addi_auto_attach(dev, context);
+ if (devpriv) {
+ if (dev->iobase)
+ apci3xxx_reset(dev);
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+ if (devpriv->mmio)
+ iounmap(devpriv->mmio);
+ }
+ comedi_pci_disable(dev);
}
static struct comedi_driver apci3xxx_driver = {
.driver_name = "addi_apci_3xxx",
.module = THIS_MODULE,
.auto_attach = apci3xxx_auto_attach,
- .detach = i_ADDI_Detach,
+ .detach = apci3xxx_detach,
};
static int apci3xxx_pci_probe(struct pci_dev *dev,
diff --git a/drivers/staging/comedi/drivers/addi_watchdog.c b/drivers/staging/comedi/drivers/addi_watchdog.c
index 1666b5f510d3..7b21acc93929 100644
--- a/drivers/staging/comedi/drivers/addi_watchdog.c
+++ b/drivers/staging/comedi/drivers/addi_watchdog.c
@@ -16,10 +16,6 @@
* 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.
*/
#include "../comedidev.h"
@@ -130,14 +126,12 @@ int addi_watchdog_init(struct comedi_subdevice *s, unsigned long iobase)
{
struct addi_watchdog_private *spriv;
- spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
+ spriv = comedi_alloc_spriv(s, sizeof(*spriv));
if (!spriv)
return -ENOMEM;
spriv->iobase = iobase;
- s->private = spriv;
-
s->type = COMEDI_SUBD_TIMER;
s->subdev_flags = SDF_WRITEABLE;
s->n_chan = 1;
diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
index 8a438ff1bd45..b5e4e53f737f 100644
--- a/drivers/staging/comedi/drivers/adl_pci6208.c
+++ b/drivers/staging/comedi/drivers/adl_pci6208.c
@@ -20,10 +20,6 @@
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_pci6208
diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c
index e3960745f506..0d9243a5f495 100644
--- a/drivers/staging/comedi/drivers/adl_pci7x3x.c
+++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c
@@ -19,10 +19,6 @@
* 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.
*/
/*
diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
index b3ec60afe3a0..0b591b0b5501 100644
--- a/drivers/staging/comedi/drivers/adl_pci8164.c
+++ b/drivers/staging/comedi/drivers/adl_pci8164.c
@@ -13,10 +13,6 @@
* 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.
*/
/*
diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
index 6247fdcedcbf..af51c7460048 100644
--- a/drivers/staging/comedi/drivers/adl_pci9111.c
+++ b/drivers/staging/comedi/drivers/adl_pci9111.c
@@ -17,10 +17,6 @@ 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.
*/
/*
diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
index 71142e36e7fb..d187a7bf0a55 100644
--- a/drivers/staging/comedi/drivers/adq12b.c
+++ b/drivers/staging/comedi/drivers/adq12b.c
@@ -14,11 +14,6 @@
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: adq12b
diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
index ccc114d6c08b..8430a27ec1b5 100644
--- a/drivers/staging/comedi/drivers/adv_pci1723.c
+++ b/drivers/staging/comedi/drivers/adv_pci1723.c
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*
comedi/drivers/pci1723.c
COMEDI - Linux Control and Measurement Device Interface
@@ -13,12 +13,7 @@
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: adv_pci1723
Description: Advantech PCI-1723
diff --git a/drivers/staging/comedi/drivers/adv_pci1724.c b/drivers/staging/comedi/drivers/adv_pci1724.c
index e60f12578d44..da7462e01faa 100644
--- a/drivers/staging/comedi/drivers/adv_pci1724.c
+++ b/drivers/staging/comedi/drivers/adv_pci1724.c
@@ -17,12 +17,7 @@
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.
-
-************************************************************************/
+*/
/*
diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
index f70c67471c13..8e6ec75bd294 100644
--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
+++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
@@ -1173,19 +1173,11 @@ static int pci_dio_auto_attach(struct comedi_device *dev,
static void pci_dio_detach(struct comedi_device *dev)
{
struct pci_dio_private *devpriv = dev->private;
- struct comedi_subdevice *s;
- int i;
if (devpriv) {
if (devpriv->valid)
pci_dio_reset(dev);
}
- for (i = 0; i < dev->n_subdevices; i++) {
- s = &dev->subdevices[i];
- if (s->type == COMEDI_SUBD_DIO)
- comedi_spriv_free(dev, i);
- s->private = NULL; /* some private data is static */
- }
comedi_pci_disable(dev);
}
diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c
index e2dc08a058bc..279dfe8951f7 100644
--- a/drivers/staging/comedi/drivers/aio_aio12_8.c
+++ b/drivers/staging/comedi/drivers/aio_aio12_8.c
@@ -14,10 +14,6 @@
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.
*/
/*
@@ -259,17 +255,11 @@ static int aio_aio12_8_attach(struct comedi_device *dev,
return 0;
}
-static void aio_aio12_8_detach(struct comedi_device *dev)
-{
- comedi_spriv_free(dev, 2);
- comedi_legacy_detach(dev);
-}
-
static struct comedi_driver aio_aio12_8_driver = {
.driver_name = "aio_aio12_8",
.module = THIS_MODULE,
.attach = aio_aio12_8_attach,
- .detach = aio_aio12_8_detach,
+ .detach = comedi_legacy_detach,
.board_name = &board_types[0].name,
.num_names = ARRAY_SIZE(board_types),
.offset = sizeof(struct aio12_8_boardtype),
diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
index 126854c05093..029834d0ff1f 100644
--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
+++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
@@ -14,10 +14,6 @@
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.
*/
/*
diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
index 297750bef0f7..e2478105ac1a 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200.c
@@ -17,11 +17,6 @@
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: amplc_dio200
diff --git a/drivers/staging/comedi/drivers/amplc_dio200.h b/drivers/staging/comedi/drivers/amplc_dio200.h
index cf2e7261740e..43160b9944bb 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200.h
+++ b/drivers/staging/comedi/drivers/amplc_dio200.h
@@ -18,11 +18,6 @@
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.
-
*/
#ifndef AMPLC_DIO200_H_INCLUDED
diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c
index 3403e5ccfa93..649fc69724fb 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200_common.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c
@@ -17,11 +17,6 @@
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.
-
*/
#include <linux/interrupt.h>
@@ -561,7 +556,7 @@ dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
const struct dio200_layout *layout = dio200_dev_layout(dev);
struct dio200_subdev_intr *subpriv;
- subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
+ subpriv = comedi_alloc_spriv(s, sizeof(*subpriv));
if (!subpriv)
return -ENOMEM;
@@ -573,7 +568,6 @@ dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
/* Disable interrupt sources. */
dio200_write8(dev, subpriv->ofs, 0);
- s->private = subpriv;
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
if (layout->has_int_sce) {
@@ -888,11 +882,10 @@ dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
struct dio200_subdev_8254 *subpriv;
unsigned int chan;
- subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
+ subpriv = comedi_alloc_spriv(s, sizeof(*subpriv));
if (!subpriv)
return -ENOMEM;
- s->private = subpriv;
s->type = COMEDI_SUBD_COUNTER;
s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
s->n_chan = 3;
@@ -1024,11 +1017,12 @@ static int dio200_subdev_8255_init(struct comedi_device *dev,
{
struct dio200_subdev_8255 *subpriv;
- subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
+ subpriv = comedi_alloc_spriv(s, sizeof(*subpriv));
if (!subpriv)
return -ENOMEM;
+
subpriv->ofs = offset;
- s->private = subpriv;
+
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 24;
@@ -1230,28 +1224,11 @@ void amplc_dio200_common_detach(struct comedi_device *dev)
{
const struct dio200_board *thisboard = comedi_board(dev);
struct dio200_private *devpriv = dev->private;
- const struct dio200_layout *layout;
- unsigned n;
if (!thisboard || !devpriv)
return;
if (dev->irq)
free_irq(dev->irq, dev);
- if (dev->subdevices) {
- layout = dio200_board_layout(thisboard);
- for (n = 0; n < dev->n_subdevices; n++) {
- switch (layout->sdtype[n]) {
- case sd_8254:
- case sd_8255:
- case sd_intr:
- comedi_spriv_free(dev, n);
- break;
- case sd_timer:
- default:
- break;
- }
- }
- }
}
EXPORT_SYMBOL_GPL(amplc_dio200_common_detach);
diff --git a/drivers/staging/comedi/drivers/amplc_dio200_pci.c b/drivers/staging/comedi/drivers/amplc_dio200_pci.c
index 4be44e877373..d7d9f5cc3ab4 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200_pci.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200_pci.c
@@ -16,11 +16,6 @@
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: amplc_dio200_pci
diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
index 115ecd51677e..4e889b82cbf2 100644
--- a/drivers/staging/comedi/drivers/amplc_pc236.c
+++ b/drivers/staging/comedi/drivers/amplc_pc236.c
@@ -16,11 +16,6 @@
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: amplc_pc236
@@ -543,7 +538,6 @@ static void pc236_detach(struct comedi_device *dev)
return;
if (dev->iobase)
pc236_intr_disable(dev);
- comedi_spriv_free(dev, 0);
if (is_isa_board(thisboard)) {
comedi_legacy_detach(dev);
} else if (is_pci_board(thisboard)) {
diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
index 94a752d852bb..6546095e7a45 100644
--- a/drivers/staging/comedi/drivers/amplc_pc263.c
+++ b/drivers/staging/comedi/drivers/amplc_pc263.c
@@ -16,11 +16,6 @@
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: amplc_pc263
diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
index 4d7eab9b5565..f1e36f08b103 100644
--- a/drivers/staging/comedi/drivers/amplc_pci224.c
+++ b/drivers/staging/comedi/drivers/amplc_pci224.c
@@ -16,11 +16,6 @@
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: amplc_pci224
diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
index 49200fbd60b9..846d6448fa4d 100644
--- a/drivers/staging/comedi/drivers/amplc_pci230.c
+++ b/drivers/staging/comedi/drivers/amplc_pci230.c
@@ -16,10 +16,6 @@
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: amplc_pci230
@@ -2834,7 +2830,6 @@ static void pci230_detach(struct comedi_device *dev)
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- comedi_spriv_free(dev, 2);
if (dev->irq)
free_irq(dev->irq, dev);
comedi_pci_disable(dev);
diff --git a/drivers/staging/comedi/drivers/amplc_pci263.c b/drivers/staging/comedi/drivers/amplc_pci263.c
index 8b57533bf406..4da900cc5845 100644
--- a/drivers/staging/comedi/drivers/amplc_pci263.c
+++ b/drivers/staging/comedi/drivers/amplc_pci263.c
@@ -16,11 +16,6 @@
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: amplc_pci263
diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
index 92376dc86dd8..929218a35975 100644
--- a/drivers/staging/comedi/drivers/c6xdigio.c
+++ b/drivers/staging/comedi/drivers/c6xdigio.c
@@ -16,11 +16,6 @@
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: c6xdigio
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index f874fff44523..ae9a2082b5a4 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -15,10 +15,6 @@
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.
-
PCMCIA support code for this driver is adapted from the dummy_cs.c
driver of the Linux PCMCIA Card Services package.
diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
index 53dd298d2b54..58bca184bf22 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas.c
@@ -19,12 +19,6 @@
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_pcidas
@@ -1608,7 +1602,6 @@ static void cb_pcidas_detach(struct comedi_device *dev)
}
if (dev->irq)
free_irq(dev->irq, dev);
- comedi_spriv_free(dev, 2);
comedi_pci_disable(dev);
}
diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
index c3e5495b4f06..43c0bf58771a 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
@@ -28,12 +28,7 @@
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_pcidas64
@@ -4163,7 +4158,6 @@ static void detach(struct comedi_device *dev)
devpriv->ao_dma_desc_bus_addr);
}
}
- comedi_spriv_free(dev, 4);
comedi_pci_disable(dev);
}
diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
index f9b459888b8b..2d3e920e5987 100644
--- a/drivers/staging/comedi/drivers/cb_pcidda.c
+++ b/drivers/staging/comedi/drivers/cb_pcidda.c
@@ -17,10 +17,6 @@
* 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.
*/
/*
@@ -397,18 +393,11 @@ static int cb_pcidda_auto_attach(struct comedi_device *dev,
return 0;
}
-static void cb_pcidda_detach(struct comedi_device *dev)
-{
- comedi_spriv_free(dev, 1);
- comedi_spriv_free(dev, 2);
- comedi_pci_disable(dev);
-}
-
static struct comedi_driver cb_pcidda_driver = {
.driver_name = "cb_pcidda",
.module = THIS_MODULE,
.auto_attach = cb_pcidda_auto_attach,
- .detach = cb_pcidda_detach,
+ .detach = comedi_pci_disable,
};
static int cb_pcidda_pci_probe(struct pci_dev *dev,
diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
index 29813c9d4a2a..8b5c198862a1 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
@@ -14,11 +14,6 @@
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_pcimdas
diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
index 88f03ae6f3e6..406cba8cba88 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
@@ -15,11 +15,6 @@
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_pcimdda
@@ -197,17 +192,11 @@ static int cb_pcimdda_auto_attach(struct comedi_device *dev,
return 1;
}
-static void cb_pcimdda_detach(struct comedi_device *dev)
-{
- comedi_spriv_free(dev, 1);
- comedi_pci_disable(dev);
-}
-
static struct comedi_driver cb_pcimdda_driver = {
.driver_name = "cb_pcimdda",
.module = THIS_MODULE,
.auto_attach = cb_pcimdda_auto_attach,
- .detach = cb_pcimdda_detach,
+ .detach = comedi_pci_disable,
};
static int cb_pcimdda_pci_probe(struct pci_dev *dev,
diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c
index 1bb53816eca3..1a51866be6f7 100644
--- a/drivers/staging/comedi/drivers/comedi_bond.c
+++ b/drivers/staging/comedi/drivers/comedi_bond.c
@@ -15,11 +15,6 @@
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: comedi_bond
diff --git a/drivers/staging/comedi/drivers/comedi_fc.c b/drivers/staging/comedi/drivers/comedi_fc.c
index 37dc79637d2a..b3d89c82d087 100644
--- a/drivers/staging/comedi/drivers/comedi_fc.c
+++ b/drivers/staging/comedi/drivers/comedi_fc.c
@@ -17,12 +17,7 @@
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.
-
-************************************************************************/
+*/
#include "../comedidev.h"
diff --git a/drivers/staging/comedi/drivers/comedi_fc.h b/drivers/staging/comedi/drivers/comedi_fc.h
index 31afab79f39a..a4dea7cb86be 100644
--- a/drivers/staging/comedi/drivers/comedi_fc.h
+++ b/drivers/staging/comedi/drivers/comedi_fc.h
@@ -17,12 +17,7 @@
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.
-
-************************************************************************/
+*/
#ifndef _COMEDI_FC_H
#define _COMEDI_FC_H
diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c
index 3e061cc9b48e..772a8f5f0c1c 100644
--- a/drivers/staging/comedi/drivers/comedi_parport.c
+++ b/drivers/staging/comedi/drivers/comedi_parport.c
@@ -14,11 +14,6 @@
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: comedi_parport
diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
index c1d8e86f53a2..907e7a3822f5 100644
--- a/drivers/staging/comedi/drivers/comedi_test.c
+++ b/drivers/staging/comedi/drivers/comedi_test.c
@@ -21,12 +21,7 @@
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: comedi_test
Description: generates fake waveforms
diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
index f2230bfd4eb9..0fb9027dde2d 100644
--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
+++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
@@ -13,11 +13,6 @@
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: contec_pci_dio
diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
index b87f95c3e17d..44c912b48b6e 100644
--- a/drivers/staging/comedi/drivers/daqboard2000.c
+++ b/drivers/staging/comedi/drivers/daqboard2000.c
@@ -14,11 +14,6 @@
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: daqboard2000
@@ -110,7 +105,6 @@ Configuration options: not applicable, uses PCI auto config
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
-#include <linux/firmware.h>
#include "../comedidev.h"
@@ -524,7 +518,8 @@ static int daqboard2000_writeCPLD(struct comedi_device *dev, int data)
}
static int initialize_daqboard2000(struct comedi_device *dev,
- const u8 *cpld_array, size_t len)
+ const u8 *cpld_array, size_t len,
+ unsigned long context)
{
struct daqboard2000_private *devpriv = dev->private;
int result = -EIO;
@@ -565,22 +560,6 @@ static int initialize_daqboard2000(struct comedi_device *dev,
return result;
}
-static int daqboard2000_upload_firmware(struct comedi_device *dev)
-{
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- const struct firmware *fw;
- int ret;
-
- ret = request_firmware(&fw, DAQBOARD2000_FIRMWARE, &pcidev->dev);
- if (ret)
- return ret;
-
- ret = initialize_daqboard2000(dev, fw->data, fw->size);
- release_firmware(fw);
-
- return ret;
-}
-
static void daqboard2000_adcStopDmaTransfer(struct comedi_device *dev)
{
}
@@ -724,7 +703,9 @@ static int daqboard2000_auto_attach(struct comedi_device *dev,
readl(devpriv->plx + 0x6c);
- result = daqboard2000_upload_firmware(dev);
+ result = comedi_load_firmware(dev, &comedi_to_pci_dev(dev)->dev,
+ DAQBOARD2000_FIRMWARE,
+ initialize_daqboard2000, 0);
if (result < 0)
return result;
@@ -766,7 +747,6 @@ static void daqboard2000_detach(struct comedi_device *dev)
{
struct daqboard2000_private *devpriv = dev->private;
- comedi_spriv_free(dev, 2);
if (dev->irq)
free_irq(dev->irq, dev);
if (devpriv) {
diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
index ba12c1d605fb..2e7e3e202390 100644
--- a/drivers/staging/comedi/drivers/das08.c
+++ b/drivers/staging/comedi/drivers/das08.c
@@ -16,12 +16,6 @@
* 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.
- *
- *****************************************************************
*/
/*
@@ -566,12 +560,6 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
}
EXPORT_SYMBOL_GPL(das08_common_attach);
-void das08_common_detach(struct comedi_device *dev)
-{
- comedi_spriv_free(dev, 4);
-}
-EXPORT_SYMBOL_GPL(das08_common_detach);
-
static int __init das08_init(void)
{
return 0;
diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h
index 89bb8d6fdfc6..cce1b584200a 100644
--- a/drivers/staging/comedi/drivers/das08.h
+++ b/drivers/staging/comedi/drivers/das08.h
@@ -14,11 +14,6 @@
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.
-
*/
#ifndef _DAS08_H
@@ -52,6 +47,5 @@ struct das08_private_struct {
};
int das08_common_attach(struct comedi_device *dev, unsigned long iobase);
-void das08_common_detach(struct comedi_device *dev);
#endif /* _DAS08_H */
diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
index d9f3e92317d3..885fb179c9b4 100644
--- a/drivers/staging/comedi/drivers/das08_cs.c
+++ b/drivers/staging/comedi/drivers/das08_cs.c
@@ -16,19 +16,12 @@
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.
-
PCMCIA support code for this driver is adapted from the dummy_cs.c
driver of the Linux PCMCIA Card Services package.
The initial developer of the original code is David A. Hinds
<dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
-
-*****************************************************************
-
*/
/*
Driver: das08_cs
@@ -93,17 +86,11 @@ static int das08_cs_auto_attach(struct comedi_device *dev,
return das08_common_attach(dev, iobase);
}
-static void das08_cs_detach(struct comedi_device *dev)
-{
- das08_common_detach(dev);
- comedi_pcmcia_disable(dev);
-}
-
static struct comedi_driver driver_das08_cs = {
.driver_name = "das08_cs",
.module = THIS_MODULE,
.auto_attach = das08_cs_auto_attach,
- .detach = das08_cs_detach,
+ .detach = comedi_pcmcia_disable,
};
static int das08_pcmcia_attach(struct pcmcia_device *link)
diff --git a/drivers/staging/comedi/drivers/das08_isa.c b/drivers/staging/comedi/drivers/das08_isa.c
index f09f6966ed65..21a94389b8b2 100644
--- a/drivers/staging/comedi/drivers/das08_isa.c
+++ b/drivers/staging/comedi/drivers/das08_isa.c
@@ -16,10 +16,6 @@
* 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.
*/
/*
@@ -193,17 +189,11 @@ static int das08_isa_attach(struct comedi_device *dev,
return das08_common_attach(dev, dev->iobase);
}
-static void das08_isa_detach(struct comedi_device *dev)
-{
- das08_common_detach(dev);
- comedi_legacy_detach(dev);
-}
-
static struct comedi_driver das08_isa_driver = {
.driver_name = "isa-das08",
.module = THIS_MODULE,
.attach = das08_isa_attach,
- .detach = das08_isa_detach,
+ .detach = comedi_legacy_detach,
.board_name = &das08_isa_boards[0].name,
.num_names = ARRAY_SIZE(das08_isa_boards),
.offset = sizeof(das08_isa_boards[0]),
diff --git a/drivers/staging/comedi/drivers/das08_pci.c b/drivers/staging/comedi/drivers/das08_pci.c
index 53fa943dd0b7..9c5d234e063f 100644
--- a/drivers/staging/comedi/drivers/das08_pci.c
+++ b/drivers/staging/comedi/drivers/das08_pci.c
@@ -16,10 +16,6 @@
* 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.
*/
/*
@@ -79,17 +75,11 @@ static int das08_pci_auto_attach(struct comedi_device *dev,
return das08_common_attach(dev, dev->iobase);
}
-static void das08_pci_detach(struct comedi_device *dev)
-{
- das08_common_detach(dev);
- comedi_pci_disable(dev);
-}
-
static struct comedi_driver das08_pci_comedi_driver = {
.driver_name = "pci-das08",
.module = THIS_MODULE,
.auto_attach = das08_pci_auto_attach,
- .detach = das08_pci_detach,
+ .detach = comedi_pci_disable,
};
static int das08_pci_probe(struct pci_dev *dev,
diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
index 762b5a6eac5a..dbec3ba99548 100644
--- a/drivers/staging/comedi/drivers/das16.c
+++ b/drivers/staging/comedi/drivers/das16.c
@@ -16,12 +16,6 @@
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: das16
@@ -1339,7 +1333,6 @@ static void das16_detach(struct comedi_device *dev)
struct das16_private_struct *devpriv = dev->private;
das16_reset(dev);
- comedi_spriv_free(dev, 4);
if (devpriv) {
int i;
for (i = 0; i < 2; i++) {
diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
index 9cb9c3b04797..0b33808c3a7d 100644
--- a/drivers/staging/comedi/drivers/das16m1.c
+++ b/drivers/staging/comedi/drivers/das16m1.c
@@ -17,12 +17,6 @@
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: das16m1
@@ -672,7 +666,6 @@ static void das16m1_detach(struct comedi_device *dev)
{
struct das16m1_private_struct *devpriv = dev->private;
- comedi_spriv_free(dev, 3);
if (devpriv && devpriv->extra_iobase)
release_region(devpriv->extra_iobase, DAS16M1_SIZE2);
comedi_legacy_detach(dev);
diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
index abf7638a9f71..23b4a661eb1a 100644
--- a/drivers/staging/comedi/drivers/das1800.c
+++ b/drivers/staging/comedi/drivers/das1800.c
@@ -15,12 +15,6 @@
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: das1800
diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
index 11424fb5b4d4..f0530778bb3b 100644
--- a/drivers/staging/comedi/drivers/das6402.c
+++ b/drivers/staging/comedi/drivers/das6402.c
@@ -22,11 +22,6 @@
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: das6402
diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
index 9ce6cbcc7ee8..091cd911b38a 100644
--- a/drivers/staging/comedi/drivers/das800.c
+++ b/drivers/staging/comedi/drivers/das800.c
@@ -15,12 +15,6 @@
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: das800
diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
index 6c85dd2d549b..e29847d73b43 100644
--- a/drivers/staging/comedi/drivers/dmm32at.c
+++ b/drivers/staging/comedi/drivers/dmm32at.c
@@ -14,11 +14,6 @@
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: dmm32at
diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
index 8757b54ad4ac..5348cdae408a 100644
--- a/drivers/staging/comedi/drivers/dt2811.c
+++ b/drivers/staging/comedi/drivers/dt2811.c
@@ -18,10 +18,6 @@
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: dt2811
diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c
index 7c95b3b68131..87e9749c4be7 100644
--- a/drivers/staging/comedi/drivers/dt2814.c
+++ b/drivers/staging/comedi/drivers/dt2814.c
@@ -14,11 +14,6 @@
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: dt2814
diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c
index b24e87681fe3..0fcd4fe7acdc 100644
--- a/drivers/staging/comedi/drivers/dt2815.c
+++ b/drivers/staging/comedi/drivers/dt2815.c
@@ -14,11 +14,6 @@
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: dt2815
diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c
index b5c8e8213faf..2f46be715f79 100644
--- a/drivers/staging/comedi/drivers/dt2817.c
+++ b/drivers/staging/comedi/drivers/dt2817.c
@@ -14,11 +14,6 @@
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: dt2817
diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
index 90f2de9bc402..c1950e3b19a2 100644
--- a/drivers/staging/comedi/drivers/dt282x.c
+++ b/drivers/staging/comedi/drivers/dt282x.c
@@ -14,11 +14,6 @@
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: dt282x
diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
index 7e03929c9a14..01a2f889d5b0 100644
--- a/drivers/staging/comedi/drivers/dt3000.c
+++ b/drivers/staging/comedi/drivers/dt3000.c
@@ -14,11 +14,6 @@
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: dt3000
diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
index 81eb5ed6ec97..6c60949d9193 100644
--- a/drivers/staging/comedi/drivers/dt9812.c
+++ b/drivers/staging/comedi/drivers/dt9812.c
@@ -15,11 +15,6 @@
* 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.
- *
*/
/*
@@ -43,14 +38,11 @@ for my needs.
* says P1).
*/
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
-#include <linux/kref.h>
#include <linux/uaccess.h>
#include <linux/usb.h>
@@ -60,6 +52,9 @@ for my needs.
#define DT9812_MAX_WRITE_CMD_PIPE_SIZE 32
#define DT9812_MAX_READ_CMD_PIPE_SIZE 32
+/* usb_bulk_msg() timout in milliseconds */
+#define DT9812_USB_TIMEOUT 1000
+
/*
* See Silican Laboratories C8051F020/1/2/3 manual
*/
@@ -242,87 +237,25 @@ struct dt9812_usb_cmd {
struct dt9812_write_multi write_multi_info;
struct dt9812_rmw_multi rmw_multi_info;
} u;
-#if 0
- WRITE_BYTE_INFO WriteByteInfo;
- READ_BYTE_INFO ReadByteInfo;
- WRITE_MULTI_INFO WriteMultiInfo;
- READ_MULTI_INFO ReadMultiInfo;
- RMW_BYTE_INFO RMWByteInfo;
- RMW_MULTI_INFO RMWMultiInfo;
- DAC_THRESHOLD_INFO DacThresholdInfo;
- INT_ON_CHANGE_MASK_INFO IntOnChangeMaskInfo;
- CGL_INFO CglInfo;
- SUBSYSTEM_INFO SubsystemInfo;
- CAL_POT_CMD CalPotCmd;
- WRITE_DEV_BYTE_INFO WriteDevByteInfo;
- READ_DEV_BYTE_INFO ReadDevByteInfo;
- WRITE_DEV_MULTI_INFO WriteDevMultiInfo;
- READ_DEV_MULTI_INFO ReadDevMultiInfo;
- READ_SINGLE_VALUE_INFO ReadSingleValueInfo;
- WRITE_SINGLE_VALUE_INFO WriteSingleValueInfo;
-#endif
};
-#define DT9812_NUM_SLOTS 16
-
-static DEFINE_SEMAPHORE(dt9812_mutex);
-
-static const struct usb_device_id dt9812_table[] = {
- {USB_DEVICE(0x0867, 0x9812)},
- {} /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, dt9812_table);
-
-struct usb_dt9812 {
- struct slot_dt9812 *slot;
- struct usb_device *udev;
- struct usb_interface *interface;
- u16 vendor;
- u16 product;
- u16 device;
- u32 serial;
+struct dt9812_private {
+ struct semaphore sem;
struct {
__u8 addr;
size_t size;
- } message_pipe, command_write, command_read, write_stream, read_stream;
- struct kref kref;
- u16 analog_out_shadow[2];
- u8 digital_out_shadow;
-};
-
-struct comedi_dt9812 {
- struct slot_dt9812 *slot;
- u32 serial;
-};
-
-struct slot_dt9812 {
- struct semaphore mutex;
- u32 serial;
- struct usb_dt9812 *usb;
- struct comedi_dt9812 *comedi;
+ } cmd_wr, cmd_rd;
+ u16 device;
+ u16 ao_shadow[2];
};
-static struct slot_dt9812 dt9812[DT9812_NUM_SLOTS];
-
-static inline struct usb_dt9812 *to_dt9812_dev(struct kref *d)
-{
- return container_of(d, struct usb_dt9812, kref);
-}
-
-static void dt9812_delete(struct kref *kref)
-{
- struct usb_dt9812 *dev = to_dt9812_dev(kref);
-
- usb_put_dev(dev->udev);
- kfree(dev);
-}
-
-static int dt9812_read_info(struct usb_dt9812 *dev, int offset, void *buf,
- size_t buf_size)
+static int dt9812_read_info(struct comedi_device *dev,
+ int offset, void *buf, size_t buf_size)
{
+ struct usb_device *usb = comedi_to_usb_dev(dev);
+ struct dt9812_private *devpriv = dev->private;
struct dt9812_usb_cmd cmd;
- int count, retval;
+ int count, ret;
cmd.cmd = cpu_to_le32(DT9812_R_FLASH_DATA);
cmd.u.flash_data_info.address =
@@ -330,25 +263,23 @@ static int dt9812_read_info(struct usb_dt9812 *dev, int offset, void *buf,
cmd.u.flash_data_info.numbytes = cpu_to_le16(buf_size);
/* DT9812 only responds to 32 byte writes!! */
- count = 32;
- retval = usb_bulk_msg(dev->udev,
- usb_sndbulkpipe(dev->udev,
- dev->command_write.addr),
- &cmd, 32, &count, HZ * 1);
- if (retval)
- return retval;
- retval = usb_bulk_msg(dev->udev,
- usb_rcvbulkpipe(dev->udev,
- dev->command_read.addr),
- buf, buf_size, &count, HZ * 1);
- return retval;
+ ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr),
+ &cmd, 32, &count, DT9812_USB_TIMEOUT);
+ if (ret)
+ return ret;
+
+ return usb_bulk_msg(usb, usb_rcvbulkpipe(usb, devpriv->cmd_rd.addr),
+ buf, buf_size, &count, DT9812_USB_TIMEOUT);
}
-static int dt9812_read_multiple_registers(struct usb_dt9812 *dev, int reg_count,
- u8 *address, u8 *value)
+static int dt9812_read_multiple_registers(struct comedi_device *dev,
+ int reg_count, u8 *address,
+ u8 *value)
{
+ struct usb_device *usb = comedi_to_usb_dev(dev);
+ struct dt9812_private *devpriv = dev->private;
struct dt9812_usb_cmd cmd;
- int i, count, retval;
+ int i, count, ret;
cmd.cmd = cpu_to_le32(DT9812_R_MULTI_BYTE_REG);
cmd.u.read_multi_info.count = reg_count;
@@ -356,26 +287,23 @@ static int dt9812_read_multiple_registers(struct usb_dt9812 *dev, int reg_count,
cmd.u.read_multi_info.address[i] = address[i];
/* DT9812 only responds to 32 byte writes!! */
- count = 32;
- retval = usb_bulk_msg(dev->udev,
- usb_sndbulkpipe(dev->udev,
- dev->command_write.addr),
- &cmd, 32, &count, HZ * 1);
- if (retval)
- return retval;
- retval = usb_bulk_msg(dev->udev,
- usb_rcvbulkpipe(dev->udev,
- dev->command_read.addr),
- value, reg_count, &count, HZ * 1);
- return retval;
+ ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr),
+ &cmd, 32, &count, DT9812_USB_TIMEOUT);
+ if (ret)
+ return ret;
+
+ return usb_bulk_msg(usb, usb_rcvbulkpipe(usb, devpriv->cmd_rd.addr),
+ value, reg_count, &count, DT9812_USB_TIMEOUT);
}
-static int dt9812_write_multiple_registers(struct usb_dt9812 *dev,
+static int dt9812_write_multiple_registers(struct comedi_device *dev,
int reg_count, u8 *address,
u8 *value)
{
+ struct usb_device *usb = comedi_to_usb_dev(dev);
+ struct dt9812_private *devpriv = dev->private;
struct dt9812_usb_cmd cmd;
- int i, count, retval;
+ int i, count;
cmd.cmd = cpu_to_le32(DT9812_W_MULTI_BYTE_REG);
cmd.u.read_multi_info.count = reg_count;
@@ -383,19 +311,20 @@ static int dt9812_write_multiple_registers(struct usb_dt9812 *dev,
cmd.u.write_multi_info.write[i].address = address[i];
cmd.u.write_multi_info.write[i].value = value[i];
}
+
/* DT9812 only responds to 32 byte writes!! */
- retval = usb_bulk_msg(dev->udev,
- usb_sndbulkpipe(dev->udev,
- dev->command_write.addr),
- &cmd, 32, &count, HZ * 1);
- return retval;
+ return usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr),
+ &cmd, 32, &count, DT9812_USB_TIMEOUT);
}
-static int dt9812_rmw_multiple_registers(struct usb_dt9812 *dev, int reg_count,
+static int dt9812_rmw_multiple_registers(struct comedi_device *dev,
+ int reg_count,
struct dt9812_rmw_byte *rmw)
{
+ struct usb_device *usb = comedi_to_usb_dev(dev);
+ struct dt9812_private *devpriv = dev->private;
struct dt9812_usb_cmd cmd;
- int i, count, retval;
+ int i, count;
cmd.cmd = cpu_to_le32(DT9812_RMW_MULTI_BYTE_REG);
cmd.u.rmw_multi_info.count = reg_count;
@@ -403,76 +332,52 @@ static int dt9812_rmw_multiple_registers(struct usb_dt9812 *dev, int reg_count,
cmd.u.rmw_multi_info.rmw[i] = rmw[i];
/* DT9812 only responds to 32 byte writes!! */
- retval = usb_bulk_msg(dev->udev,
- usb_sndbulkpipe(dev->udev,
- dev->command_write.addr),
- &cmd, 32, &count, HZ * 1);
- return retval;
+ return usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr),
+ &cmd, 32, &count, DT9812_USB_TIMEOUT);
}
-static int dt9812_digital_in(struct slot_dt9812 *slot, u8 *bits)
+static int dt9812_digital_in(struct comedi_device *dev, u8 *bits)
{
- int result = -ENODEV;
-
- down(&slot->mutex);
- if (slot->usb) {
- u8 reg[2] = { F020_SFR_P3, F020_SFR_P1 };
- u8 value[2];
+ struct dt9812_private *devpriv = dev->private;
+ u8 reg[2] = { F020_SFR_P3, F020_SFR_P1 };
+ u8 value[2];
+ int ret;
- result = dt9812_read_multiple_registers(slot->usb, 2, reg,
- value);
- if (result == 0) {
- /*
- * bits 0-6 in F020_SFR_P3 are bits 0-6 in the digital
- * input port bit 3 in F020_SFR_P1 is bit 7 in the
- * digital input port
- */
- *bits = (value[0] & 0x7f) | ((value[1] & 0x08) << 4);
- /* printk("%2.2x, %2.2x -> %2.2x\n",
- value[0], value[1], *bits); */
- }
+ down(&devpriv->sem);
+ ret = dt9812_read_multiple_registers(dev, 2, reg, value);
+ if (ret == 0) {
+ /*
+ * bits 0-6 in F020_SFR_P3 are bits 0-6 in the digital
+ * input port bit 3 in F020_SFR_P1 is bit 7 in the
+ * digital input port
+ */
+ *bits = (value[0] & 0x7f) | ((value[1] & 0x08) << 4);
}
- up(&slot->mutex);
+ up(&devpriv->sem);
- return result;
+ return ret;
}
-static int dt9812_digital_out(struct slot_dt9812 *slot, u8 bits)
+static int dt9812_digital_out(struct comedi_device *dev, u8 bits)
{
- int result = -ENODEV;
-
- down(&slot->mutex);
- if (slot->usb) {
- u8 reg[1];
- u8 value[1];
-
- reg[0] = F020_SFR_P2;
- value[0] = bits;
- result = dt9812_write_multiple_registers(slot->usb, 1, reg,
- value);
- slot->usb->digital_out_shadow = bits;
- }
- up(&slot->mutex);
- return result;
-}
+ struct dt9812_private *devpriv = dev->private;
+ u8 reg[1] = { F020_SFR_P2 };
+ u8 value[1] = { bits };
+ int ret;
-static int dt9812_digital_out_shadow(struct slot_dt9812 *slot, u8 *bits)
-{
- int result = -ENODEV;
+ down(&devpriv->sem);
+ ret = dt9812_write_multiple_registers(dev, 1, reg, value);
+ up(&devpriv->sem);
- down(&slot->mutex);
- if (slot->usb) {
- *bits = slot->usb->digital_out_shadow;
- result = 0;
- }
- up(&slot->mutex);
- return result;
+ return ret;
}
-static void dt9812_configure_mux(struct usb_dt9812 *dev,
+static void dt9812_configure_mux(struct comedi_device *dev,
struct dt9812_rmw_byte *rmw, int channel)
{
- if (dev->device == DT9812_DEVID_DT9812_10) {
+ struct dt9812_private *devpriv = dev->private;
+
+ if (devpriv->device == DT9812_DEVID_DT9812_10) {
/* In the DT9812/10V MUX is selected by P1.5-7 */
rmw->address = F020_SFR_P1;
rmw->and_mask = 0xe0;
@@ -485,18 +390,21 @@ static void dt9812_configure_mux(struct usb_dt9812 *dev,
}
}
-static void dt9812_configure_gain(struct usb_dt9812 *dev,
+static void dt9812_configure_gain(struct comedi_device *dev,
struct dt9812_rmw_byte *rmw,
enum dt9812_gain gain)
{
- if (dev->device == DT9812_DEVID_DT9812_10) {
- /* In the DT9812/10V, there is an external gain of 0.5 */
+ struct dt9812_private *devpriv = dev->private;
+
+ /* In the DT9812/10V, there is an external gain of 0.5 */
+ if (devpriv->device == DT9812_DEVID_DT9812_10)
gain <<= 1;
- }
rmw->address = F020_SFR_ADC0CF;
rmw->and_mask = F020_MASK_ADC0CF_AMP0GN2 |
- F020_MASK_ADC0CF_AMP0GN1 | F020_MASK_ADC0CF_AMP0GN0;
+ F020_MASK_ADC0CF_AMP0GN1 |
+ F020_MASK_ADC0CF_AMP0GN0;
+
switch (gain) {
/*
* 000 -> Gain = 1
@@ -508,8 +416,10 @@ static void dt9812_configure_gain(struct usb_dt9812 *dev,
*/
case DT9812_GAIN_0PT5:
rmw->or_value = F020_MASK_ADC0CF_AMP0GN2 |
- F020_MASK_ADC0CF_AMP0GN1;
+ F020_MASK_ADC0CF_AMP0GN1;
break;
+ default:
+ /* this should never happen, just use a gain of 1 */
case DT9812_GAIN_1:
rmw->or_value = 0x00;
break;
@@ -521,20 +431,18 @@ static void dt9812_configure_gain(struct usb_dt9812 *dev,
break;
case DT9812_GAIN_8:
rmw->or_value = F020_MASK_ADC0CF_AMP0GN1 |
- F020_MASK_ADC0CF_AMP0GN0;
+ F020_MASK_ADC0CF_AMP0GN0;
break;
case DT9812_GAIN_16:
rmw->or_value = F020_MASK_ADC0CF_AMP0GN2;
break;
- default:
- dev_err(&dev->interface->dev, "Illegal gain %d\n", gain);
-
}
}
-static int dt9812_analog_in(struct slot_dt9812 *slot, int channel, u16 *value,
- enum dt9812_gain gain)
+static int dt9812_analog_in(struct comedi_device *dev,
+ int channel, u16 *value, enum dt9812_gain gain)
{
+ struct dt9812_private *devpriv = dev->private;
struct dt9812_rmw_byte rmw[3];
u8 reg[3] = {
F020_SFR_ADC0CN,
@@ -542,31 +450,30 @@ static int dt9812_analog_in(struct slot_dt9812 *slot, int channel, u16 *value,
F020_SFR_ADC0L
};
u8 val[3];
- int result = -ENODEV;
+ int ret;
- down(&slot->mutex);
- if (!slot->usb)
- goto exit;
+ down(&devpriv->sem);
/* 1 select the gain */
- dt9812_configure_gain(slot->usb, &rmw[0], gain);
+ dt9812_configure_gain(dev, &rmw[0], gain);
/* 2 set the MUX to select the channel */
- dt9812_configure_mux(slot->usb, &rmw[1], channel);
+ dt9812_configure_mux(dev, &rmw[1], channel);
/* 3 start conversion */
rmw[2].address = F020_SFR_ADC0CN;
rmw[2].and_mask = 0xff;
rmw[2].or_value = F020_MASK_ADC0CN_AD0EN | F020_MASK_ADC0CN_AD0BUSY;
- result = dt9812_rmw_multiple_registers(slot->usb, 3, rmw);
- if (result)
+ ret = dt9812_rmw_multiple_registers(dev, 3, rmw);
+ if (ret)
goto exit;
/* read the status and ADC */
- result = dt9812_read_multiple_registers(slot->usb, 3, reg, val);
- if (result)
+ ret = dt9812_read_multiple_registers(dev, 3, reg, val);
+ if (ret)
goto exit;
+
/*
* An ADC conversion takes 16 SAR clocks cycles, i.e. about 9us.
* Therefore, between the instant that AD0BUSY was set via
@@ -578,7 +485,7 @@ static int dt9812_analog_in(struct slot_dt9812 *slot, int channel, u16 *value,
*/
if ((val[0] & (F020_MASK_ADC0CN_AD0INT | F020_MASK_ADC0CN_AD0BUSY)) ==
F020_MASK_ADC0CN_AD0INT) {
- switch (slot->usb->device) {
+ switch (devpriv->device) {
case DT9812_DEVID_DT9812_10:
/*
* For DT9812-10V the personality module set the
@@ -594,422 +501,284 @@ static int dt9812_analog_in(struct slot_dt9812 *slot, int channel, u16 *value,
}
exit:
- up(&slot->mutex);
- return result;
+ up(&devpriv->sem);
+
+ return ret;
}
-static int dt9812_analog_out_shadow(struct slot_dt9812 *slot, int channel,
- u16 *value)
+static int dt9812_analog_out(struct comedi_device *dev, int channel, u16 value)
{
- int result = -ENODEV;
+ struct dt9812_private *devpriv = dev->private;
+ struct dt9812_rmw_byte rmw[3];
+ int ret;
- down(&slot->mutex);
- if (slot->usb) {
- *value = slot->usb->analog_out_shadow[channel];
- result = 0;
+ down(&devpriv->sem);
+
+ switch (channel) {
+ case 0:
+ /* 1. Set DAC mode */
+ rmw[0].address = F020_SFR_DAC0CN;
+ rmw[0].and_mask = 0xff;
+ rmw[0].or_value = F020_MASK_DACxCN_DACxEN;
+
+ /* 2 load low byte of DAC value first */
+ rmw[1].address = F020_SFR_DAC0L;
+ rmw[1].and_mask = 0xff;
+ rmw[1].or_value = value & 0xff;
+
+ /* 3 load high byte of DAC value next to latch the
+ 12-bit value */
+ rmw[2].address = F020_SFR_DAC0H;
+ rmw[2].and_mask = 0xff;
+ rmw[2].or_value = (value >> 8) & 0xf;
+ break;
+
+ case 1:
+ /* 1. Set DAC mode */
+ rmw[0].address = F020_SFR_DAC1CN;
+ rmw[0].and_mask = 0xff;
+ rmw[0].or_value = F020_MASK_DACxCN_DACxEN;
+
+ /* 2 load low byte of DAC value first */
+ rmw[1].address = F020_SFR_DAC1L;
+ rmw[1].and_mask = 0xff;
+ rmw[1].or_value = value & 0xff;
+
+ /* 3 load high byte of DAC value next to latch the
+ 12-bit value */
+ rmw[2].address = F020_SFR_DAC1H;
+ rmw[2].and_mask = 0xff;
+ rmw[2].or_value = (value >> 8) & 0xf;
+ break;
}
- up(&slot->mutex);
+ ret = dt9812_rmw_multiple_registers(dev, 3, rmw);
+ devpriv->ao_shadow[channel] = value;
- return result;
+ up(&devpriv->sem);
+
+ return ret;
}
-static int dt9812_analog_out(struct slot_dt9812 *slot, int channel, u16 value)
+static int dt9812_di_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- int result = -ENODEV;
+ u8 bits = 0;
+ int ret;
- down(&slot->mutex);
- if (slot->usb) {
- struct dt9812_rmw_byte rmw[3];
+ ret = dt9812_digital_in(dev, &bits);
+ if (ret)
+ return ret;
- switch (channel) {
- case 0:
- /* 1. Set DAC mode */
- rmw[0].address = F020_SFR_DAC0CN;
- rmw[0].and_mask = 0xff;
- rmw[0].or_value = F020_MASK_DACxCN_DACxEN;
-
- /* 2 load low byte of DAC value first */
- rmw[1].address = F020_SFR_DAC0L;
- rmw[1].and_mask = 0xff;
- rmw[1].or_value = value & 0xff;
-
- /* 3 load high byte of DAC value next to latch the
- 12-bit value */
- rmw[2].address = F020_SFR_DAC0H;
- rmw[2].and_mask = 0xff;
- rmw[2].or_value = (value >> 8) & 0xf;
- break;
+ data[1] = bits;
- case 1:
- /* 1. Set DAC mode */
- rmw[0].address = F020_SFR_DAC1CN;
- rmw[0].and_mask = 0xff;
- rmw[0].or_value = F020_MASK_DACxCN_DACxEN;
-
- /* 2 load low byte of DAC value first */
- rmw[1].address = F020_SFR_DAC1L;
- rmw[1].and_mask = 0xff;
- rmw[1].or_value = value & 0xff;
-
- /* 3 load high byte of DAC value next to latch the
- 12-bit value */
- rmw[2].address = F020_SFR_DAC1H;
- rmw[2].and_mask = 0xff;
- rmw[2].or_value = (value >> 8) & 0xf;
- break;
- }
- result = dt9812_rmw_multiple_registers(slot->usb, 3, rmw);
- slot->usb->analog_out_shadow[channel] = value;
+ return insn->n;
+}
+
+static int dt9812_do_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ unsigned int mask = data[0];
+ unsigned int bits = data[1];
+
+ if (mask) {
+ s->state &= ~mask;
+ s->state |= (bits & mask);
+
+ dt9812_digital_out(dev, s->state);
}
- up(&slot->mutex);
- return result;
+ data[1] = s->state;
+
+ return insn->n;
}
-/*
- * USB framework functions
- */
+static int dt9812_ai_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ u16 val = 0;
+ int ret;
+ int i;
-static int dt9812_probe(struct usb_interface *interface,
- const struct usb_device_id *id)
+ for (i = 0; i < insn->n; i++) {
+ ret = dt9812_analog_in(dev, chan, &val, DT9812_GAIN_1);
+ if (ret)
+ return ret;
+ data[i] = val;
+ }
+
+ return insn->n;
+}
+
+static int dt9812_ao_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- int retval = -ENOMEM;
- struct usb_dt9812 *dev = NULL;
- struct usb_host_interface *iface_desc;
- struct usb_endpoint_descriptor *endpoint;
+ struct dt9812_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
int i;
- u8 fw;
- /* allocate memory for our device state and initialize it */
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (dev == NULL)
- goto error;
+ down(&devpriv->sem);
+ for (i = 0; i < insn->n; i++)
+ data[i] = devpriv->ao_shadow[chan];
+ up(&devpriv->sem);
+
+ return insn->n;
+}
+
+static int dt9812_ao_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ int ret;
+ int i;
- kref_init(&dev->kref);
+ for (i = 0; i < insn->n; i++) {
+ ret = dt9812_analog_out(dev, chan, data[i]);
+ if (ret)
+ return ret;
+ }
- dev->udev = usb_get_dev(interface_to_usbdev(interface));
- dev->interface = interface;
+ return insn->n;
+}
- /* Check endpoints */
- iface_desc = interface->cur_altsetting;
+static int dt9812_find_endpoints(struct comedi_device *dev)
+{
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
+ struct usb_host_interface *host = intf->cur_altsetting;
+ struct dt9812_private *devpriv = dev->private;
+ struct usb_endpoint_descriptor *ep;
+ int i;
- if (iface_desc->desc.bNumEndpoints != 5) {
- dev_err(&interface->dev, "Wrong number of endpoints.\n");
- retval = -ENODEV;
- goto error;
+ if (host->desc.bNumEndpoints != 5) {
+ dev_err(dev->class_dev, "Wrong number of endpoints\n");
+ return -ENODEV;
}
- for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
- int direction = -1;
- endpoint = &iface_desc->endpoint[i].desc;
+ for (i = 0; i < host->desc.bNumEndpoints; ++i) {
+ int dir = -1;
+ ep = &host->endpoint[i].desc;
switch (i) {
case 0:
- direction = USB_DIR_IN;
- dev->message_pipe.addr = endpoint->bEndpointAddress;
- dev->message_pipe.size =
- le16_to_cpu(endpoint->wMaxPacketSize);
-
+ /* unused message pipe */
+ dir = USB_DIR_IN;
break;
case 1:
- direction = USB_DIR_OUT;
- dev->command_write.addr = endpoint->bEndpointAddress;
- dev->command_write.size =
- le16_to_cpu(endpoint->wMaxPacketSize);
+ dir = USB_DIR_OUT;
+ devpriv->cmd_wr.addr = ep->bEndpointAddress;
+ devpriv->cmd_wr.size = le16_to_cpu(ep->wMaxPacketSize);
break;
case 2:
- direction = USB_DIR_IN;
- dev->command_read.addr = endpoint->bEndpointAddress;
- dev->command_read.size =
- le16_to_cpu(endpoint->wMaxPacketSize);
+ dir = USB_DIR_IN;
+ devpriv->cmd_rd.addr = ep->bEndpointAddress;
+ devpriv->cmd_rd.size = le16_to_cpu(ep->wMaxPacketSize);
break;
case 3:
- direction = USB_DIR_OUT;
- dev->write_stream.addr = endpoint->bEndpointAddress;
- dev->write_stream.size =
- le16_to_cpu(endpoint->wMaxPacketSize);
+ /* unused write stream */
+ dir = USB_DIR_OUT;
break;
case 4:
- direction = USB_DIR_IN;
- dev->read_stream.addr = endpoint->bEndpointAddress;
- dev->read_stream.size =
- le16_to_cpu(endpoint->wMaxPacketSize);
+ /* unused read stream */
+ dir = USB_DIR_IN;
break;
}
- if ((endpoint->bEndpointAddress & USB_DIR_IN) != direction) {
- dev_err(&interface->dev,
- "Endpoint has wrong direction.\n");
- retval = -ENODEV;
- goto error;
+ if ((ep->bEndpointAddress & USB_DIR_IN) != dir) {
+ dev_err(dev->class_dev,
+ "Endpoint has wrong direction\n");
+ return -ENODEV;
}
}
- if (dt9812_read_info(dev, 0, &fw, sizeof(fw)) != 0) {
+ return 0;
+}
+
+static int dt9812_reset_device(struct comedi_device *dev)
+{
+ struct usb_device *usb = comedi_to_usb_dev(dev);
+ struct dt9812_private *devpriv = dev->private;
+ u32 serial;
+ u16 vendor;
+ u16 product;
+ u16 tmp16;
+ u8 tmp8;
+ int ret;
+ int i;
+
+ ret = dt9812_read_info(dev, 0, &tmp8, sizeof(tmp8));
+ if (ret) {
/*
* Seems like a configuration reset is necessary if driver is
* reloaded while device is attached
*/
- usb_reset_configuration(dev->udev);
+ usb_reset_configuration(usb);
for (i = 0; i < 10; i++) {
- retval = dt9812_read_info(dev, 1, &fw, sizeof(fw));
- if (retval == 0) {
- dev_info(&interface->dev,
- "usb_reset_configuration succeeded "
- "after %d iterations\n", i);
+ ret = dt9812_read_info(dev, 1, &tmp8, sizeof(tmp8));
+ if (ret == 0)
break;
- }
}
- }
-
- if (dt9812_read_info(dev, 1, &dev->vendor, sizeof(dev->vendor)) != 0) {
- dev_err(&interface->dev, "Failed to read vendor.\n");
- retval = -ENODEV;
- goto error;
- }
- if (dt9812_read_info(dev, 3, &dev->product, sizeof(dev->product)) != 0) {
- dev_err(&interface->dev, "Failed to read product.\n");
- retval = -ENODEV;
- goto error;
- }
- if (dt9812_read_info(dev, 5, &dev->device, sizeof(dev->device)) != 0) {
- dev_err(&interface->dev, "Failed to read device.\n");
- retval = -ENODEV;
- goto error;
- }
- if (dt9812_read_info(dev, 7, &dev->serial, sizeof(dev->serial)) != 0) {
- dev_err(&interface->dev, "Failed to read serial.\n");
- retval = -ENODEV;
- goto error;
- }
-
- dev->vendor = le16_to_cpu(dev->vendor);
- dev->product = le16_to_cpu(dev->product);
- dev->device = le16_to_cpu(dev->device);
- dev->serial = le32_to_cpu(dev->serial);
- switch (dev->device) {
- case DT9812_DEVID_DT9812_10:
- dev->analog_out_shadow[0] = 0x0800;
- dev->analog_out_shadow[1] = 0x800;
- break;
- case DT9812_DEVID_DT9812_2PT5:
- dev->analog_out_shadow[0] = 0x0000;
- dev->analog_out_shadow[1] = 0x0000;
- break;
- }
- dev->digital_out_shadow = 0;
-
- /* save our data pointer in this interface device */
- usb_set_intfdata(interface, dev);
-
- /* let the user know what node this device is now attached to */
- dev_info(&interface->dev, "USB DT9812 (%4.4x.%4.4x.%4.4x) #0x%8.8x\n",
- dev->vendor, dev->product, dev->device, dev->serial);
-
- down(&dt9812_mutex);
- {
- /* Find a slot for the USB device */
- struct slot_dt9812 *first = NULL;
- struct slot_dt9812 *best = NULL;
-
- for (i = 0; i < DT9812_NUM_SLOTS; i++) {
- if (!first && !dt9812[i].usb && dt9812[i].serial == 0)
- first = &dt9812[i];
- if (!best && dt9812[i].serial == dev->serial)
- best = &dt9812[i];
- }
-
- if (!best)
- best = first;
-
- if (best) {
- down(&best->mutex);
- best->usb = dev;
- dev->slot = best;
- up(&best->mutex);
+ if (ret) {
+ dev_err(dev->class_dev,
+ "unable to reset configuration\n");
+ return ret;
}
}
- up(&dt9812_mutex);
-
- return 0;
-error:
- if (dev)
- kref_put(&dev->kref, dt9812_delete);
- return retval;
-}
-
-static void dt9812_disconnect(struct usb_interface *interface)
-{
- struct usb_dt9812 *dev;
- int minor = interface->minor;
-
- down(&dt9812_mutex);
- dev = usb_get_intfdata(interface);
- if (dev->slot) {
- down(&dev->slot->mutex);
- dev->slot->usb = NULL;
- up(&dev->slot->mutex);
- dev->slot = NULL;
+ ret = dt9812_read_info(dev, 1, &vendor, sizeof(vendor));
+ if (ret) {
+ dev_err(dev->class_dev, "failed to read vendor id\n");
+ return ret;
}
- usb_set_intfdata(interface, NULL);
- up(&dt9812_mutex);
-
- /* queue final destruction */
- kref_put(&dev->kref, dt9812_delete);
-
- dev_info(&interface->dev, "USB Dt9812 #%d now disconnected\n", minor);
-}
+ vendor = le16_to_cpu(vendor);
-static struct usb_driver dt9812_usb_driver = {
- .name = "dt9812",
- .probe = dt9812_probe,
- .disconnect = dt9812_disconnect,
- .id_table = dt9812_table,
-};
-
-/*
- * Comedi functions
- */
-
-static int dt9812_comedi_open(struct comedi_device *dev)
-{
- struct comedi_dt9812 *devpriv = dev->private;
- int result = -ENODEV;
-
- down(&devpriv->slot->mutex);
- if (devpriv->slot->usb) {
- /* We have an attached device, fill in current range info */
- struct comedi_subdevice *s;
-
- s = &dev->subdevices[0];
- s->n_chan = 8;
- s->maxdata = 1;
-
- s = &dev->subdevices[1];
- s->n_chan = 8;
- s->maxdata = 1;
-
- s = &dev->subdevices[2];
- s->n_chan = 8;
- switch (devpriv->slot->usb->device) {
- case 0:{
- s->maxdata = 4095;
- s->range_table = &range_bipolar10;
- }
- break;
- case 1:{
- s->maxdata = 4095;
- s->range_table = &range_unipolar2_5;
- }
- break;
- }
-
- s = &dev->subdevices[3];
- s->n_chan = 2;
- switch (devpriv->slot->usb->device) {
- case 0:{
- s->maxdata = 4095;
- s->range_table = &range_bipolar10;
- }
- break;
- case 1:{
- s->maxdata = 4095;
- s->range_table = &range_unipolar2_5;
- }
- break;
- }
- result = 0;
+ ret = dt9812_read_info(dev, 3, &product, sizeof(product));
+ if (ret) {
+ dev_err(dev->class_dev, "failed to read product id\n");
+ return ret;
}
- up(&devpriv->slot->mutex);
- return result;
-}
-
-static int dt9812_di_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data)
-{
- struct comedi_dt9812 *devpriv = dev->private;
- unsigned int channel = CR_CHAN(insn->chanspec);
- int n;
- u8 bits = 0;
-
- dt9812_digital_in(devpriv->slot, &bits);
- for (n = 0; n < insn->n; n++)
- data[n] = ((1 << channel) & bits) != 0;
- return n;
-}
+ product = le16_to_cpu(product);
-static int dt9812_do_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data)
-{
- struct comedi_dt9812 *devpriv = dev->private;
- unsigned int channel = CR_CHAN(insn->chanspec);
- int n;
- u8 bits = 0;
-
- dt9812_digital_out_shadow(devpriv->slot, &bits);
- for (n = 0; n < insn->n; n++) {
- u8 mask = 1 << channel;
-
- bits &= ~mask;
- if (data[n])
- bits |= mask;
+ ret = dt9812_read_info(dev, 5, &tmp16, sizeof(tmp16));
+ if (ret) {
+ dev_err(dev->class_dev, "failed to read device id\n");
+ return ret;
}
- dt9812_digital_out(devpriv->slot, bits);
- return n;
-}
+ devpriv->device = le16_to_cpu(tmp16);
-static int dt9812_ai_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data)
-{
- struct comedi_dt9812 *devpriv = dev->private;
- unsigned int channel = CR_CHAN(insn->chanspec);
- int n;
-
- for (n = 0; n < insn->n; n++) {
- u16 value = 0;
-
- dt9812_analog_in(devpriv->slot, channel, &value, DT9812_GAIN_1);
- data[n] = value;
+ ret = dt9812_read_info(dev, 7, &serial, sizeof(serial));
+ if (ret) {
+ dev_err(dev->class_dev, "failed to read serial number\n");
+ return ret;
}
- return n;
-}
+ serial = le32_to_cpu(serial);
-static int dt9812_ao_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data)
-{
- struct comedi_dt9812 *devpriv = dev->private;
- unsigned int channel = CR_CHAN(insn->chanspec);
- int n;
- u16 value;
-
- for (n = 0; n < insn->n; n++) {
- value = 0;
- dt9812_analog_out_shadow(devpriv->slot, channel, &value);
- data[n] = value;
- }
- return n;
-}
+ /* let the user know what node this device is now attached to */
+ dev_info(dev->class_dev, "USB DT9812 (%4.4x.%4.4x.%4.4x) #0x%8.8x\n",
+ vendor, product, devpriv->device, serial);
-static int dt9812_ao_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data)
-{
- struct comedi_dt9812 *devpriv = dev->private;
- unsigned int channel = CR_CHAN(insn->chanspec);
- int n;
+ if (devpriv->device != DT9812_DEVID_DT9812_10 &&
+ devpriv->device != DT9812_DEVID_DT9812_2PT5) {
+ dev_err(dev->class_dev, "Unsupported device!\n");
+ return -EINVAL;
+ }
- for (n = 0; n < insn->n; n++)
- dt9812_analog_out(devpriv->slot, channel, data[n]);
- return n;
+ return 0;
}
-static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int dt9812_auto_attach(struct comedi_device *dev,
+ unsigned long context)
{
- struct comedi_dt9812 *devpriv;
- int i;
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
+ struct dt9812_private *devpriv;
struct comedi_subdevice *s;
+ bool is_unipolar;
int ret;
devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
@@ -1017,125 +786,107 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return -ENOMEM;
dev->private = devpriv;
- /*
- * Special open routine, since USB unit may be unattached at
- * comedi_config time, hence range can not be determined
- */
- dev->open = dt9812_comedi_open;
+ sema_init(&devpriv->sem, 1);
+ usb_set_intfdata(intf, devpriv);
- devpriv->serial = it->options[0];
+ ret = dt9812_find_endpoints(dev);
+ if (ret)
+ return ret;
+
+ ret = dt9812_reset_device(dev);
+ if (ret)
+ return ret;
+
+ is_unipolar = (devpriv->device == DT9812_DEVID_DT9812_2PT5);
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
return ret;
- /* digital input subdevice */
+ /* Digital Input subdevice */
s = &dev->subdevices[0];
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE;
- s->n_chan = 0;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_read = &dt9812_di_rinsn;
-
- /* digital output subdevice */
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 8;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = dt9812_di_insn_bits;
+
+ /* Digital Output subdevice */
s = &dev->subdevices[1];
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITEABLE;
- s->n_chan = 0;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_write = &dt9812_do_winsn;
-
- /* analog input subdevice */
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITEABLE;
+ s->n_chan = 8;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = dt9812_do_insn_bits;
+
+ /* Analog Input subdevice */
s = &dev->subdevices[2];
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND;
- s->n_chan = 0;
- s->maxdata = 1;
- s->range_table = NULL;
- s->insn_read = &dt9812_ai_rinsn;
-
- /* analog output subdevice */
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND;
+ s->n_chan = 8;
+ s->maxdata = 0x0fff;
+ s->range_table = is_unipolar ? &range_unipolar2_5 : &range_bipolar10;
+ s->insn_read = dt9812_ai_insn_read;
+
+ /* Analog Output subdevice */
s = &dev->subdevices[3];
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE;
- s->n_chan = 0;
- s->maxdata = 1;
- s->range_table = NULL;
- s->insn_write = &dt9812_ao_winsn;
- s->insn_read = &dt9812_ao_rinsn;
-
- dev_info(dev->class_dev, "successfully attached to dt9812.\n");
-
- down(&dt9812_mutex);
- /* Find a slot for the comedi device */
- {
- struct slot_dt9812 *first = NULL;
- struct slot_dt9812 *best = NULL;
- for (i = 0; i < DT9812_NUM_SLOTS; i++) {
- if (!first && !dt9812[i].comedi) {
- /* First free slot from comedi side */
- first = &dt9812[i];
- }
- if (!best &&
- dt9812[i].usb &&
- dt9812[i].usb->serial == devpriv->serial) {
- /* We have an attaced device with matching ID */
- best = &dt9812[i];
- }
- }
- if (!best)
- best = first;
- if (best) {
- down(&best->mutex);
- best->comedi = devpriv;
- best->serial = devpriv->serial;
- devpriv->slot = best;
- up(&best->mutex);
- }
- }
- up(&dt9812_mutex);
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITEABLE;
+ s->n_chan = 2;
+ s->maxdata = 0x0fff;
+ s->range_table = is_unipolar ? &range_unipolar2_5 : &range_bipolar10;
+ s->insn_write = dt9812_ao_insn_write;
+ s->insn_read = dt9812_ao_insn_read;
+
+ devpriv->ao_shadow[0] = is_unipolar ? 0x0000 : 0x0800;
+ devpriv->ao_shadow[1] = is_unipolar ? 0x0000 : 0x0800;
return 0;
}
static void dt9812_detach(struct comedi_device *dev)
{
- /* Nothing to cleanup */
-}
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
+ struct dt9812_private *devpriv = dev->private;
-static struct comedi_driver dt9812_comedi_driver = {
- .module = THIS_MODULE,
- .driver_name = "dt9812",
- .attach = dt9812_attach,
- .detach = dt9812_detach,
-};
+ if (!devpriv)
+ return;
-static int __init usb_dt9812_init(void)
-{
- int i;
+ down(&devpriv->sem);
- /* Initialize all driver slots */
- for (i = 0; i < DT9812_NUM_SLOTS; i++) {
- sema_init(&dt9812[i].mutex, 1);
- dt9812[i].serial = 0;
- dt9812[i].usb = NULL;
- dt9812[i].comedi = NULL;
- }
- dt9812[12].serial = 0x0;
+ usb_set_intfdata(intf, NULL);
- return comedi_usb_driver_register(&dt9812_comedi_driver,
- &dt9812_usb_driver);
+ up(&devpriv->sem);
}
-static void __exit usb_dt9812_exit(void)
+static struct comedi_driver dt9812_driver = {
+ .driver_name = "dt9812",
+ .module = THIS_MODULE,
+ .auto_attach = dt9812_auto_attach,
+ .detach = dt9812_detach,
+};
+
+static int dt9812_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
{
- comedi_usb_driver_unregister(&dt9812_comedi_driver, &dt9812_usb_driver);
+ return comedi_usb_auto_config(intf, &dt9812_driver, id->driver_info);
}
-module_init(usb_dt9812_init);
-module_exit(usb_dt9812_exit);
+static const struct usb_device_id dt9812_usb_table[] = {
+ { USB_DEVICE(0x0867, 0x9812) },
+ { }
+};
+MODULE_DEVICE_TABLE(usb, dt9812_usb_table);
+
+static struct usb_driver dt9812_usb_driver = {
+ .name = "dt9812",
+ .id_table = dt9812_usb_table,
+ .probe = dt9812_usb_probe,
+ .disconnect = comedi_usb_auto_unconfig,
+};
+module_comedi_usb_driver(dt9812_driver, dt9812_usb_driver);
MODULE_AUTHOR("Anders Blomdell <anders.blomdell@control.lth.se>");
MODULE_DESCRIPTION("Comedi DT9812 driver");
diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c
index 93ec8e492ccc..e14dd3ae9ec6 100644
--- a/drivers/staging/comedi/drivers/dyna_pci10xx.c
+++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c
@@ -11,10 +11,6 @@
* 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.
*/
/*
diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
index 0c061df0978c..2fceff93867b 100644
--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
+++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
@@ -18,12 +18,7 @@
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: gsc_hpdi
diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
index 08ab9d6e7190..a11e015dc03d 100644
--- a/drivers/staging/comedi/drivers/icp_multi.c
+++ b/drivers/staging/comedi/drivers/icp_multi.c
@@ -13,11 +13,6 @@
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.
-
*/
/*
diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
index 90b303ab2300..94609f4aa4c9 100644
--- a/drivers/staging/comedi/drivers/jr3_pci.c
+++ b/drivers/staging/comedi/drivers/jr3_pci.c
@@ -14,11 +14,6 @@
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: jr3_pci
@@ -46,7 +41,6 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/ctype.h>
-#include <linux/firmware.h>
#include <linux/jiffies.h>
#include <linux/slab.h>
#include <linux/timer.h>
@@ -97,37 +91,6 @@ struct jr3_pci_subdev_private {
int retries;
};
-/* Hotplug firmware loading stuff */
-static int comedi_load_firmware(struct comedi_device *dev, const char *name,
- int (*cb)(struct comedi_device *dev,
- const u8 *data, size_t size))
-{
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- int result = 0;
- const struct firmware *fw;
- char *firmware_path;
- static const char *prefix = "comedi/";
-
- firmware_path = kmalloc(strlen(prefix) + strlen(name) + 1, GFP_KERNEL);
- if (!firmware_path) {
- result = -ENOMEM;
- } else {
- firmware_path[0] = '\0';
- strcat(firmware_path, prefix);
- strcat(firmware_path, name);
- result = request_firmware(&fw, firmware_path, &pcidev->dev);
- if (result == 0) {
- if (!cb)
- result = -EINVAL;
- else
- result = cb(dev, fw->data, fw->size);
- release_firmware(fw);
- }
- kfree(firmware_path);
- }
- return result;
-}
-
static struct poll_delay_t poll_delay_min_max(int min, int max)
{
struct poll_delay_t result;
@@ -362,8 +325,9 @@ static int read_idm_word(const u8 *data, size_t size, int *pos,
return result;
}
-static int jr3_download_firmware(struct comedi_device *dev, const u8 *data,
- size_t size)
+static int jr3_download_firmware(struct comedi_device *dev,
+ const u8 *data, size_t size,
+ unsigned long context)
{
/*
* IDM file format is:
@@ -768,7 +732,9 @@ static int jr3_pci_auto_attach(struct comedi_device *dev,
/* Reset DSP card */
writel(0, &devpriv->iobase->channel[0].reset);
- result = comedi_load_firmware(dev, "jr3pci.idm", jr3_download_firmware);
+ result = comedi_load_firmware(dev, &comedi_to_pci_dev(dev)->dev,
+ "comedi/jr3pci.idm",
+ jr3_download_firmware, 0);
dev_dbg(dev->class_dev, "Firmare load %d\n", result);
if (result < 0)
@@ -778,8 +744,9 @@ static int jr3_pci_auto_attach(struct comedi_device *dev,
* format:
* model serial Fx Fy Fz Mx My Mz\n
*
- * comedi_load_firmware(dev, "jr3_offsets_table",
- * jr3_download_firmware);
+ * comedi_load_firmware(dev, &comedi_to_pci_dev(dev)->dev,
+ * "comedi/jr3_offsets_table",
+ * jr3_download_firmware, 1);
*/
/*
diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
index e0e64752e310..f10cf10e5fe3 100644
--- a/drivers/staging/comedi/drivers/ke_counter.c
+++ b/drivers/staging/comedi/drivers/ke_counter.c
@@ -14,11 +14,6 @@
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: ke_counter
diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
index 641e693d5d0e..c2308fd24d6a 100644
--- a/drivers/staging/comedi/drivers/me4000.c
+++ b/drivers/staging/comedi/drivers/me4000.c
@@ -14,11 +14,6 @@
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: me4000
diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
index 09f2a9feaf7c..7533ece3670e 100644
--- a/drivers/staging/comedi/drivers/me_daq.c
+++ b/drivers/staging/comedi/drivers/me_daq.c
@@ -14,10 +14,6 @@
* 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.
*/
/*
@@ -37,7 +33,6 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
-#include <linux/firmware.h>
#include "../comedidev.h"
@@ -391,7 +386,8 @@ static int me_ao_insn_read(struct comedi_device *dev,
}
static int me2600_xilinx_download(struct comedi_device *dev,
- const u8 *data, size_t size)
+ const u8 *data, size_t size,
+ unsigned long context)
{
struct me_private_data *dev_private = dev->private;
unsigned int value;
@@ -460,22 +456,6 @@ static int me2600_xilinx_download(struct comedi_device *dev,
return 0;
}
-static int me2600_upload_firmware(struct comedi_device *dev)
-{
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- const struct firmware *fw;
- int ret;
-
- ret = request_firmware(&fw, ME2600_FIRMWARE, &pcidev->dev);
- if (ret)
- return ret;
-
- ret = me2600_xilinx_download(dev, fw->data, fw->size);
- release_firmware(fw);
-
- return ret;
-}
-
static int me_reset(struct comedi_device *dev)
{
struct me_private_data *dev_private = dev->private;
@@ -529,7 +509,9 @@ static int me_auto_attach(struct comedi_device *dev,
/* Download firmware and reset card */
if (board->needs_firmware) {
- ret = me2600_upload_firmware(dev);
+ ret = comedi_load_firmware(dev, &comedi_to_pci_dev(dev)->dev,
+ ME2600_FIRMWARE,
+ me2600_xilinx_download, 0);
if (ret < 0)
return ret;
}
diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c
index 523c6564ffca..12c34db61d63 100644
--- a/drivers/staging/comedi/drivers/mite.c
+++ b/drivers/staging/comedi/drivers/mite.c
@@ -14,11 +14,6 @@
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.
-
*/
/*
diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h
index 255b8ba9c917..d4487e888e64 100644
--- a/drivers/staging/comedi/drivers/mite.h
+++ b/drivers/staging/comedi/drivers/mite.h
@@ -14,11 +14,6 @@
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.
-
*/
#ifndef _MITE_H_
diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
index 4717be4ad268..713842ad6ff6 100644
--- a/drivers/staging/comedi/drivers/mpc624.c
+++ b/drivers/staging/comedi/drivers/mpc624.c
@@ -14,11 +14,6 @@
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: mpc624
diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c
index 7a8292086e18..5ecd1b1666fb 100644
--- a/drivers/staging/comedi/drivers/multiq3.c
+++ b/drivers/staging/comedi/drivers/multiq3.c
@@ -14,11 +14,6 @@
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: multiq3
diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
index d10f777b7f17..903c2ef5dd9a 100644
--- a/drivers/staging/comedi/drivers/ni_6527.c
+++ b/drivers/staging/comedi/drivers/ni_6527.c
@@ -14,11 +14,6 @@
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: ni_6527
diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
index 3f71f0f54d3c..42a78de47316 100644
--- a/drivers/staging/comedi/drivers/ni_65xx.c
+++ b/drivers/staging/comedi/drivers/ni_65xx.c
@@ -17,11 +17,6 @@
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: ni_65xx
@@ -286,15 +281,6 @@ static inline struct ni_65xx_subdevice_private *sprivate(struct comedi_subdevice
return subdev->private;
}
-static struct ni_65xx_subdevice_private *ni_65xx_alloc_subdevice_private(void)
-{
- struct ni_65xx_subdevice_private *subdev_private =
- kzalloc(sizeof(struct ni_65xx_subdevice_private), GFP_KERNEL);
- if (subdev_private == NULL)
- return NULL;
- return subdev_private;
-}
-
static int ni_65xx_config_filter(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
@@ -589,6 +575,7 @@ static int ni_65xx_auto_attach(struct comedi_device *dev,
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
const struct ni_65xx_board *board = NULL;
struct ni_65xx_private *devpriv;
+ struct ni_65xx_subdevice_private *spriv;
struct comedi_subdevice *s;
unsigned i;
int ret;
@@ -637,10 +624,10 @@ static int ni_65xx_auto_attach(struct comedi_device *dev,
s->maxdata = 1;
s->insn_config = ni_65xx_dio_insn_config;
s->insn_bits = ni_65xx_dio_insn_bits;
- s->private = ni_65xx_alloc_subdevice_private();
- if (s->private == NULL)
+ spriv = comedi_alloc_spriv(s, sizeof(*spriv));
+ if (!spriv)
return -ENOMEM;
- sprivate(s)->base_port = 0;
+ spriv->base_port = 0;
} else {
s->type = COMEDI_SUBD_UNUSED;
}
@@ -654,10 +641,10 @@ static int ni_65xx_auto_attach(struct comedi_device *dev,
s->range_table = &range_digital;
s->maxdata = 1;
s->insn_bits = ni_65xx_dio_insn_bits;
- s->private = ni_65xx_alloc_subdevice_private();
- if (s->private == NULL)
+ spriv = comedi_alloc_spriv(s, sizeof(*spriv));
+ if (!spriv)
return -ENOMEM;
- sprivate(s)->base_port = board->num_di_ports;
+ spriv->base_port = board->num_di_ports;
} else {
s->type = COMEDI_SUBD_UNUSED;
}
@@ -672,10 +659,10 @@ static int ni_65xx_auto_attach(struct comedi_device *dev,
s->maxdata = 1;
s->insn_config = ni_65xx_dio_insn_config;
s->insn_bits = ni_65xx_dio_insn_bits;
- s->private = ni_65xx_alloc_subdevice_private();
- if (s->private == NULL)
+ spriv = comedi_alloc_spriv(s, sizeof(*spriv));
+ if (!spriv)
return -ENOMEM;
- sprivate(s)->base_port = 0;
+ spriv->base_port = 0;
for (i = 0; i < board->num_dio_ports; ++i) {
/* configure all ports for input */
writeb(0x1,
@@ -730,7 +717,6 @@ static int ni_65xx_auto_attach(struct comedi_device *dev,
static void ni_65xx_detach(struct comedi_device *dev)
{
struct ni_65xx_private *devpriv = dev->private;
- int i;
if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr) {
writeb(0x00,
@@ -739,8 +725,6 @@ static void ni_65xx_detach(struct comedi_device *dev)
}
if (dev->irq)
free_irq(dev->irq, dev);
- for (i = 0; i < dev->n_subdevices; ++i)
- comedi_spriv_free(dev, i);
if (devpriv) {
if (devpriv->mite) {
mite_unsetup(devpriv->mite);
diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
index 5cdda7fe97a7..a9e000461ec7 100644
--- a/drivers/staging/comedi/drivers/ni_660x.c
+++ b/drivers/staging/comedi/drivers/ni_660x.c
@@ -11,10 +11,6 @@
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.
*/
/*
diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
index 42ab6dbf9d39..1a185b9c529f 100644
--- a/drivers/staging/comedi/drivers/ni_670x.c
+++ b/drivers/staging/comedi/drivers/ni_670x.c
@@ -14,11 +14,6 @@
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: ni_670x
diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
index 2d375168f36d..7ea5aa32e9d2 100644
--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
+++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
@@ -15,12 +15,6 @@
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: ni_at_a2150
diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
index 7e5783a4f4e7..e080053c697b 100644
--- a/drivers/staging/comedi/drivers/ni_at_ao.c
+++ b/drivers/staging/comedi/drivers/ni_at_ao.c
@@ -14,11 +14,6 @@
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: ni_at_ao
diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c
index 4ced7ba119b0..713edd55a91b 100644
--- a/drivers/staging/comedi/drivers/ni_atmio.c
+++ b/drivers/staging/comedi/drivers/ni_atmio.c
@@ -14,10 +14,6 @@
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: ni_atmio
diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
index 6c97a0925aad..da7396f94297 100644
--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
+++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
@@ -12,11 +12,6 @@
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: ni_atmio16d
@@ -767,7 +762,6 @@ static int atmio16d_attach(struct comedi_device *dev,
static void atmio16d_detach(struct comedi_device *dev)
{
- comedi_spriv_free(dev, 3);
reset_atmio16d(dev);
comedi_legacy_detach(dev);
}
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index d067ef70e194..3c50e31ecc60 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -15,11 +15,6 @@
* 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.
- *
*/
/*
@@ -40,7 +35,7 @@ port, bit 0; channel 8 corresponds to the input port, bit 0.
Digital direction configuration: channels 0-7 output, 8-15 input (8225 device
emu as port A output, port B input, port C N/A).
-Analog: The input range is 0 to 4095 for -10 to +10 volts
+Analog: The input range is 0 to 4095 for -10 to +10 volts
IRQ is assigned but not used.
Version 0.1 Original DIO only driver
@@ -183,7 +178,7 @@ static int daq700_ai_rinsn(struct comedi_device *dev,
*/
static void daq700_ai_config(struct comedi_device *dev,
struct comedi_subdevice *s)
-{
+{
unsigned long iobase = dev->iobase;
outb(0x80, iobase + CMD_R1); /* disable scanning, ADC to chan 0 */
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index 9b7805fda932..d3d4eb9356a7 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -18,12 +18,6 @@
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: ni_daq_dio24
@@ -71,17 +65,11 @@ static int dio24_auto_attach(struct comedi_device *dev,
return 0;
}
-static void dio24_detach(struct comedi_device *dev)
-{
- comedi_spriv_free(dev, 0);
- comedi_pcmcia_disable(dev);
-}
-
static struct comedi_driver driver_dio24 = {
.driver_name = "ni_daq_dio24",
.module = THIS_MODULE,
.auto_attach = dio24_auto_attach,
- .detach = dio24_detach,
+ .detach = comedi_pcmcia_disable,
};
static int dio24_cs_attach(struct pcmcia_device *link)
diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
index 77a7bb632580..f161e70b3a0d 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.c
+++ b/drivers/staging/comedi/drivers/ni_labpc.c
@@ -12,10 +12,6 @@
* 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.
*/
/*
@@ -88,7 +84,7 @@
#define CMD1_REG 0x00 /* W: Command 1 reg */
#define CMD1_MA(x) (((x) & 0x7) << 0)
#define CMD1_TWOSCMP (1 << 3)
-#define CMD1_GAIN_MASK (7 << 4)
+#define CMD1_GAIN(x) (((x) & 0x7) << 4)
#define CMD1_SCANEN (1 << 7)
#define CMD2_REG 0x01 /* W: Command 2 reg */
#define CMD2_PRETRIG (1 << 0)
@@ -153,11 +149,6 @@ enum scan_mode {
MODE_MULT_CHAN_DOWN,
};
-static const int labpc_plus_ai_gain_bits[] = {
- 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
- 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
-};
-
static const struct comedi_lrange range_labpc_plus_ai = {
16, {
BIP_RANGE(5),
@@ -179,13 +170,7 @@ static const struct comedi_lrange range_labpc_plus_ai = {
}
};
-const int labpc_1200_ai_gain_bits[] = {
- 0x00, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
- 0x00, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
-};
-EXPORT_SYMBOL_GPL(labpc_1200_ai_gain_bits);
-
-const struct comedi_lrange range_labpc_1200_ai = {
+static const struct comedi_lrange range_labpc_1200_ai = {
14, {
BIP_RANGE(5),
BIP_RANGE(2.5),
@@ -203,7 +188,6 @@ const struct comedi_lrange range_labpc_1200_ai = {
UNI_RANGE(0.1)
}
};
-EXPORT_SYMBOL_GPL(range_labpc_1200_ai);
static const struct comedi_lrange range_labpc_ao = {
2, {
@@ -239,25 +223,18 @@ static const struct labpc_boardinfo labpc_boards[] = {
{
.name = "lab-pc-1200",
.ai_speed = 10000,
- .register_layout = labpc_1200_layout,
- .has_ao = 1,
- .ai_range_table = &range_labpc_1200_ai,
- .ai_range_code = labpc_1200_ai_gain_bits,
.ai_scan_up = 1,
+ .has_ao = 1,
+ .is_labpc1200 = 1,
}, {
.name = "lab-pc-1200ai",
.ai_speed = 10000,
- .register_layout = labpc_1200_layout,
- .ai_range_table = &range_labpc_1200_ai,
- .ai_range_code = labpc_1200_ai_gain_bits,
.ai_scan_up = 1,
+ .is_labpc1200 = 1,
}, {
.name = "lab-pc+",
.ai_speed = 12000,
- .register_layout = labpc_plus_layout,
.has_ao = 1,
- .ai_range_table = &range_labpc_plus_ai,
- .ai_range_code = labpc_plus_ai_gain_bits,
},
};
#endif
@@ -326,12 +303,21 @@ static void labpc_ai_set_chan_and_gain(struct comedi_device *dev,
const struct labpc_boardinfo *board = comedi_board(dev);
struct labpc_private *devpriv = dev->private;
+ if (board->is_labpc1200) {
+ /*
+ * The LabPC-1200 boards do not have a gain
+ * of '0x10'. Skip the range values that would
+ * result in this gain.
+ */
+ range += (range > 0) + (range > 7);
+ }
+
/* munge channel bits for differential/scan disabled mode */
if ((mode == MODE_SINGLE_CHAN || mode == MODE_SINGLE_CHAN_INTERVAL) &&
aref == AREF_DIFF)
chan *= 2;
devpriv->cmd1 = CMD1_MA(chan);
- devpriv->cmd1 |= board->ai_range_code[range];
+ devpriv->cmd1 |= CMD1_GAIN(range);
devpriv->write_byte(devpriv->cmd1, dev->iobase + CMD1_REG);
}
@@ -347,7 +333,7 @@ static void labpc_setup_cmd6_reg(struct comedi_device *dev,
const struct labpc_boardinfo *board = comedi_board(dev);
struct labpc_private *devpriv = dev->private;
- if (board->register_layout != labpc_1200_layout)
+ if (!board->is_labpc1200)
return;
/* reference inputs to ground or common? */
@@ -759,7 +745,7 @@ static int labpc_ai_cmdtest(struct comedi_device *dev,
err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
stop_mask = TRIG_COUNT | TRIG_NONE;
- if (board->register_layout == labpc_1200_layout)
+ if (board->is_labpc1200)
stop_mask |= TRIG_EXT;
err |= cfc_check_trigger_src(&cmd->stop_src, stop_mask);
@@ -895,7 +881,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
/* pc-plus has no fifo-half full interrupt */
} else
#endif
- if (board->register_layout == labpc_1200_layout &&
+ if (board->is_labpc1200 &&
/* wake-end-of-scan should interrupt on fifo not empty */
(cmd->flags & TRIG_WAKE_EOS) == 0 &&
/* make sure we are taking more than just a few points */
@@ -1175,7 +1161,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d)
/* read board status */
devpriv->stat1 = devpriv->read_byte(dev->iobase + STAT1_REG);
- if (board->register_layout == labpc_1200_layout)
+ if (board->is_labpc1200)
devpriv->stat2 = devpriv->read_byte(dev->iobase + STAT2_REG);
if ((devpriv->stat1 & (STAT1_GATA0 | STAT1_CNTINT | STAT1_OVERFLOW |
@@ -1201,8 +1187,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d)
* has occurred
*/
if (devpriv->stat1 & STAT1_GATA0 ||
- (board->register_layout == labpc_1200_layout
- && devpriv->stat2 & STAT2_OUTA1)) {
+ (board->is_labpc1200 && devpriv->stat2 & STAT2_OUTA1)) {
handle_isa_dma(dev);
}
} else
@@ -1266,7 +1251,7 @@ static int labpc_ao_insn_write(struct comedi_device *dev,
spin_unlock_irqrestore(&dev->spinlock, flags);
/* set range */
- if (board->register_layout == labpc_1200_layout) {
+ if (board->is_labpc1200) {
range = CR_RANGE(insn->chanspec);
if (labpc_range_is_unipolar(s, range))
devpriv->cmd6 |= CMD6_DACUNI(channel);
@@ -1603,7 +1588,7 @@ int labpc_common_attach(struct comedi_device *dev,
devpriv->write_byte(devpriv->cmd2, dev->iobase + CMD2_REG);
devpriv->write_byte(devpriv->cmd3, dev->iobase + CMD3_REG);
devpriv->write_byte(devpriv->cmd4, dev->iobase + CMD4_REG);
- if (board->register_layout == labpc_1200_layout) {
+ if (board->is_labpc1200) {
devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG);
devpriv->write_byte(devpriv->cmd6, dev->iobase + CMD6_REG);
}
@@ -1626,7 +1611,8 @@ int labpc_common_attach(struct comedi_device *dev,
s->n_chan = 8;
s->len_chanlist = 8;
s->maxdata = 0x0fff;
- s->range_table = board->ai_range_table;
+ s->range_table = board->is_labpc1200
+ ? &range_labpc_1200_ai : &range_labpc_plus_ai;
s->insn_read = labpc_ai_insn_read;
if (dev->irq) {
dev->read_subdev = s;
@@ -1671,7 +1657,7 @@ int labpc_common_attach(struct comedi_device *dev,
/* calibration subdevices for boards that have one */
s = &dev->subdevices[3];
- if (board->register_layout == labpc_1200_layout) {
+ if (board->is_labpc1200) {
s->type = COMEDI_SUBD_CALIB;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
s->n_chan = 16;
@@ -1686,7 +1672,7 @@ int labpc_common_attach(struct comedi_device *dev,
/* EEPROM */
s = &dev->subdevices[4];
- if (board->register_layout == labpc_1200_layout) {
+ if (board->is_labpc1200) {
s->type = COMEDI_SUBD_MEMORY;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
s->n_chan = EEPROM_SIZE;
@@ -1703,12 +1689,6 @@ int labpc_common_attach(struct comedi_device *dev,
}
EXPORT_SYMBOL_GPL(labpc_common_attach);
-void labpc_common_detach(struct comedi_device *dev)
-{
- comedi_spriv_free(dev, 2);
-}
-EXPORT_SYMBOL_GPL(labpc_common_detach);
-
#if IS_ENABLED(CONFIG_COMEDI_NI_LABPC_ISA)
static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
@@ -1761,8 +1741,6 @@ static void labpc_detach(struct comedi_device *dev)
{
struct labpc_private *devpriv = dev->private;
- labpc_common_detach(dev);
-
if (devpriv) {
kfree(devpriv->dma_buffer);
if (devpriv->dma_chan)
diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h
index 4b691f5a9965..486589fa6fd8 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.h
+++ b/drivers/staging/comedi/drivers/ni_labpc.h
@@ -14,11 +14,6 @@
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.
-
*/
#ifndef _NI_LABPC_H
@@ -27,27 +22,17 @@
#define EEPROM_SIZE 256 /* 256 byte eeprom */
#define NUM_AO_CHAN 2 /* boards have two analog output channels */
-enum labpc_register_layout { labpc_plus_layout, labpc_1200_layout };
enum transfer_type { fifo_not_empty_transfer, fifo_half_full_transfer,
isa_dma_transfer
};
struct labpc_boardinfo {
const char *name;
- int device_id; /* device id for pci and pcmcia boards */
- int ai_speed; /* maximum input speed in nanoseconds */
-
- /* 1200 has extra registers compared to pc+ */
- enum labpc_register_layout register_layout;
- int has_ao; /* has analog output true/false */
- const struct comedi_lrange *ai_range_table;
- const int *ai_range_code;
-
- /* board can auto scan up in ai channels, not just down */
- unsigned ai_scan_up:1;
-
- /* uses memory mapped io instead of ioports */
- unsigned has_mmio:1;
+ int ai_speed; /* maximum input speed in ns */
+ unsigned ai_scan_up:1; /* can auto scan up in ai channels */
+ unsigned has_ao:1; /* has analog outputs */
+ unsigned is_labpc1200:1; /* has extra regs compared to pc+ */
+ unsigned has_mmio:1; /* uses memory mapped io */
};
struct labpc_private {
@@ -101,9 +86,5 @@ struct labpc_private {
int labpc_common_attach(struct comedi_device *dev,
unsigned int irq, unsigned long isr_flags);
-void labpc_common_detach(struct comedi_device *dev);
-
-extern const int labpc_1200_ai_gain_bits[];
-extern const struct comedi_lrange range_labpc_1200_ai;
#endif /* _NI_LABPC_H */
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index 9e3737c6918d..ce67f4bbb1f5 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -18,12 +18,6 @@
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: ni_labpc_cs
@@ -76,12 +70,9 @@ NI manuals:
static const struct labpc_boardinfo labpc_cs_boards[] = {
{
.name = "daqcard-1200",
- .device_id = 0x103,
.ai_speed = 10000,
- .register_layout = labpc_1200_layout,
.has_ao = 1,
- .ai_range_table = &range_labpc_1200_ai,
- .ai_range_code = labpc_1200_ai_gain_bits,
+ .is_labpc1200 = 1,
},
};
@@ -113,17 +104,11 @@ static int labpc_auto_attach(struct comedi_device *dev,
return labpc_common_attach(dev, link->irq, IRQF_SHARED);
}
-static void labpc_detach(struct comedi_device *dev)
-{
- labpc_common_detach(dev);
- comedi_pcmcia_disable(dev);
-}
-
static struct comedi_driver driver_labpc_cs = {
.driver_name = "ni_labpc_cs",
.module = THIS_MODULE,
.auto_attach = labpc_auto_attach,
- .detach = labpc_detach,
+ .detach = comedi_pcmcia_disable,
};
static int labpc_cs_attach(struct pcmcia_device *link)
diff --git a/drivers/staging/comedi/drivers/ni_labpc_pci.c b/drivers/staging/comedi/drivers/ni_labpc_pci.c
index 8e916f86ccea..6c79237b2b5c 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_pci.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_pci.c
@@ -12,10 +12,6 @@
* 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.
*/
/*
@@ -50,11 +46,9 @@ static const struct labpc_boardinfo labpc_pci_boards[] = {
[BOARD_NI_PCI1200] = {
.name = "ni_pci-1200",
.ai_speed = 10000,
- .register_layout = labpc_1200_layout,
- .has_ao = 1,
- .ai_range_table = &range_labpc_1200_ai,
- .ai_range_code = labpc_1200_ai_gain_bits,
.ai_scan_up = 1,
+ .has_ao = 1,
+ .is_labpc1200 = 1,
.has_mmio = 1,
},
};
@@ -98,8 +92,6 @@ static void labpc_pci_detach(struct comedi_device *dev)
{
struct labpc_private *devpriv = dev->private;
- labpc_common_detach(dev);
-
if (devpriv && devpriv->mite) {
mite_unsetup(devpriv->mite);
mite_free(devpriv->mite);
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index 8c5dee9b3b05..3e9f544e67fc 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -15,11 +15,6 @@
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.
-
*/
/*
@@ -4077,7 +4072,6 @@ static void mio_common_detach(struct comedi_device *dev)
ni_gpct_device_destroy(devpriv->counter_dev);
}
}
- comedi_spriv_free(dev, NI_8255_DIO_SUBDEV);
}
static void init_ao_67xx(struct comedi_device *dev, struct comedi_subdevice *s)
diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
index 888be7b89d2d..f813f5763671 100644
--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
+++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
@@ -14,11 +14,6 @@
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: ni_mio_cs
diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
index b5f340c186ec..5b2f72e102e1 100644
--- a/drivers/staging/comedi/drivers/ni_pcidio.c
+++ b/drivers/staging/comedi/drivers/ni_pcidio.c
@@ -14,11 +14,6 @@
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: ni_pcidio
@@ -58,7 +53,6 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
-#include <linux/firmware.h>
#include "../comedidev.h"
@@ -971,11 +965,13 @@ static int ni_pcidio_change(struct comedi_device *dev,
return 0;
}
-static int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index,
- const u8 *data, size_t data_len)
+static int pci_6534_load_fpga(struct comedi_device *dev,
+ const u8 *data, size_t data_len,
+ unsigned long context)
{
struct nidio96_private *devpriv = dev->private;
static const int timeout = 1000;
+ int fpga_index = context;
int i;
size_t j;
@@ -1033,7 +1029,7 @@ static int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index,
static int pci_6534_reset_fpga(struct comedi_device *dev, int fpga_index)
{
- return pci_6534_load_fpga(dev, fpga_index, NULL, 0);
+ return pci_6534_load_fpga(dev, NULL, 0, fpga_index);
}
static int pci_6534_reset_fpgas(struct comedi_device *dev)
@@ -1067,13 +1063,12 @@ static void pci_6534_init_main_fpga(struct comedi_device *dev)
static int pci_6534_upload_firmware(struct comedi_device *dev)
{
struct nidio96_private *devpriv = dev->private;
- int ret;
- const struct firmware *fw;
static const char *const fw_file[3] = {
FW_PCI_6534_SCARAB_DI, /* loaded into scarab A for DI */
FW_PCI_6534_SCARAB_DO, /* loaded into scarab B for DO */
FW_PCI_6534_MAIN, /* loaded into main FPGA */
};
+ int ret;
int n;
ret = pci_6534_reset_fpgas(dev);
@@ -1081,14 +1076,11 @@ static int pci_6534_upload_firmware(struct comedi_device *dev)
return ret;
/* load main FPGA first, then the two scarabs */
for (n = 2; n >= 0; n--) {
- ret = request_firmware(&fw, fw_file[n],
- &devpriv->mite->pcidev->dev);
- if (ret == 0) {
- ret = pci_6534_load_fpga(dev, n, fw->data, fw->size);
- if (ret == 0 && n == 2)
- pci_6534_init_main_fpga(dev);
- release_firmware(fw);
- }
+ ret = comedi_load_firmware(dev, &devpriv->mite->pcidev->dev,
+ fw_file[n],
+ pci_6534_load_fpga, n);
+ if (ret == 0 && n == 2)
+ pci_6534_init_main_fpga(dev);
if (ret < 0)
break;
}
diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
index 634d02303aa0..35681ba1f369 100644
--- a/drivers/staging/comedi/drivers/ni_pcimio.c
+++ b/drivers/staging/comedi/drivers/ni_pcimio.c
@@ -14,10 +14,6 @@
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: ni_pcimio
diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h
index 0a613c077608..11bf0aab82ea 100644
--- a/drivers/staging/comedi/drivers/ni_stc.h
+++ b/drivers/staging/comedi/drivers/ni_stc.h
@@ -14,11 +14,6 @@
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.
-
*/
/*
diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c
index 225287769dc1..f2cf76d15d78 100644
--- a/drivers/staging/comedi/drivers/ni_tio.c
+++ b/drivers/staging/comedi/drivers/ni_tio.c
@@ -13,10 +13,6 @@
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.
*/
/*
diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h
index 8572996539fa..7e13697b3254 100644
--- a/drivers/staging/comedi/drivers/ni_tio.h
+++ b/drivers/staging/comedi/drivers/ni_tio.h
@@ -13,11 +13,6 @@
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.
-
*/
#ifndef _COMEDI_NI_TIO_H
diff --git a/drivers/staging/comedi/drivers/ni_tio_internal.h b/drivers/staging/comedi/drivers/ni_tio_internal.h
index 5e00212aa022..b009876754a8 100644
--- a/drivers/staging/comedi/drivers/ni_tio_internal.h
+++ b/drivers/staging/comedi/drivers/ni_tio_internal.h
@@ -14,11 +14,6 @@
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.
-
*/
#ifndef _COMEDI_NI_TIO_INTERNAL_H
diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c
index 13747f324936..cff50bc45bcd 100644
--- a/drivers/staging/comedi/drivers/ni_tiocmd.c
+++ b/drivers/staging/comedi/drivers/ni_tiocmd.c
@@ -13,10 +13,6 @@
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.
*/
/*
diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
index 8be2a4c503cc..7abf3f74144e 100644
--- a/drivers/staging/comedi/drivers/pcl711.c
+++ b/drivers/staging/comedi/drivers/pcl711.c
@@ -17,11 +17,6 @@
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: pcl711
diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c
index 4f033d88eeca..cea657c7801d 100644
--- a/drivers/staging/comedi/drivers/pcl724.c
+++ b/drivers/staging/comedi/drivers/pcl724.c
@@ -1,42 +1,28 @@
/*
- comedi/drivers/pcl724.c
-
- Michal Dobes <dobes@tesnet.cz>
-
- hardware driver for Advantech cards:
- card: PCL-724, PCL-722, PCL-731
- driver: pcl724, pcl722, pcl731
- and ADLink cards:
- card: ACL-7122, ACL-7124, PET-48DIO
- driver: acl7122, acl7124, pet48dio
-
- Options for PCL-724, PCL-731, ACL-7124 and PET-48DIO:
- [0] - IO Base
-
- Options for PCL-722 and ACL-7122:
- [0] - IO Base
- [1] - IRQ (0=disable IRQ) IRQ isn't supported at this time!
- [2] -number of DIO:
- 0, 144: 144 DIO configuration
- 1, 96: 96 DIO configuration
-*/
-/*
-Driver: pcl724
-Description: Advantech PCL-724, PCL-722, PCL-731 ADLink ACL-7122, ACL-7124,
- PET-48DIO
-Author: Michal Dobes <dobes@tesnet.cz>
-Devices: [Advantech] PCL-724 (pcl724), PCL-722 (pcl722), PCL-731 (pcl731),
- [ADLink] ACL-7122 (acl7122), ACL-7124 (acl7124), PET-48DIO (pet48dio)
-Status: untested
-
-This is driver for digital I/O boards PCL-722/724/731 with 144/24/48 DIO
-and for digital I/O boards ACL-7122/7124/PET-48DIO with 144/24/48 DIO.
-It need 8255.o for operations and only immediate mode is supported.
-See the source for configuration details.
-*/
+ * pcl724.c
+ * Comedi driver for 8255 based ISA DIO boards
+ *
+ * Michal Dobes <dobes@tesnet.cz>
+ */
+
/*
- * check_driver overrides:
- * struct comedi_insn
+ * Driver: pcl724
+ * Description: Comedi driver for 8255 based ISA DIO boards
+ * Devices: (Advantech) PCL-724 [pcl724]
+ * (Advantech) PCL-722 [pcl722]
+ * (Advantech) PCL-731 [pcl731]
+ * (ADLink) ACL-7122 [acl7122]
+ * (ADLink) ACL-7124 [acl7124]
+ * (ADLink) PET-48DIO [pet48dio]
+ * Author: Michal Dobes <dobes@tesnet.cz>
+ * Status: untested
+ *
+ * Configuration options:
+ * [0] - IO Base
+ * [1] - IRQ (not supported)
+ * [2] - number of DIO (pcl722 and acl7122 boards)
+ * 0, 144: 144 DIO configuration
+ * 1, 96: 96 DIO configuration
*/
#include "../comedidev.h"
@@ -46,40 +32,48 @@ See the source for configuration details.
#include "8255.h"
-#define PCL722_SIZE 32
-#define PCL722_96_SIZE 16
-#define PCL724_SIZE 4
-#define PCL731_SIZE 8
-#define PET48_SIZE 2
-
#define SIZE_8255 4
-/* #define PCL724_IRQ 1 no IRQ support now */
-
struct pcl724_board {
-
- const char *name; /* board name */
- int dio; /* num of DIO */
- int numofports; /* num of 8255 subdevices */
- unsigned int IRQbits; /* allowed interrupts */
- unsigned int io_range; /* len of IO space */
- char can_have96;
- char is_pet48;
+ const char *name;
+ unsigned int io_range;
+ unsigned int can_have96:1;
+ unsigned int is_pet48:1;
+ int numofports;
};
-static int subdev_8255_cb(int dir, int port, int data, unsigned long arg)
-{
- unsigned long iobase = arg;
-
- if (dir) {
- outb(data, iobase + port);
- return 0;
- } else {
- return inb(iobase + port);
- }
-}
+static const struct pcl724_board boardtypes[] = {
+ {
+ .name = "pcl724",
+ .io_range = 0x04,
+ .numofports = 1, /* 24 DIO channels */
+ }, {
+ .name = "pcl722",
+ .io_range = 0x20,
+ .can_have96 = 1,
+ .numofports = 6, /* 144 (or 96) DIO channels */
+ }, {
+ .name = "pcl731",
+ .io_range = 0x08,
+ .numofports = 2, /* 48 DIO channels */
+ }, {
+ .name = "acl7122",
+ .io_range = 0x20,
+ .can_have96 = 1,
+ .numofports = 6, /* 144 (or 96) DIO channels */
+ }, {
+ .name = "acl7124",
+ .io_range = 0x04,
+ .numofports = 1, /* 24 DIO channels */
+ }, {
+ .name = "pet48dio",
+ .io_range = 0x02,
+ .is_pet48 = 1,
+ .numofports = 2, /* 48 DIO channels */
+ },
+};
-static int subdev_8255mapped_cb(int dir, int port, int data,
+static int pcl724_8255mapped_io(int dir, int port, int data,
unsigned long iobase)
{
int movport = SIZE_8255 * (iobase >> 12);
@@ -96,57 +90,30 @@ static int subdev_8255mapped_cb(int dir, int port, int data,
}
}
-static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int pcl724_attach(struct comedi_device *dev,
+ struct comedi_devconfig *it)
{
const struct pcl724_board *board = comedi_board(dev);
struct comedi_subdevice *s;
+ unsigned long iobase;
unsigned int iorange;
- int ret, i, n_subdevices;
-#ifdef PCL724_IRQ
- unsigned int irq;
-#endif
+ int n_subdevices;
+ int ret;
+ int i;
iorange = board->io_range;
- if ((board->can_have96) &&
- ((it->options[1] == 1) || (it->options[1] == 96)))
- iorange = PCL722_96_SIZE; /* PCL-724 in 96 DIO configuration */
- ret = comedi_request_region(dev, it->options[0], iorange);
- if (ret)
- return ret;
+ n_subdevices = board->numofports;
-#ifdef PCL724_IRQ
- irq = 0;
- if (board->IRQbits != 0) { /* board support IRQ */
- irq = it->options[1];
- if (irq) { /* we want to use IRQ */
- if (((1 << irq) & board->IRQbits) == 0) {
- printk(KERN_WARNING
- ", IRQ %u is out of allowed range, "
- "DISABLING IT", irq);
- irq = 0; /* Bad IRQ */
- } else {
- if (request_irq(irq, interrupt_pcl724, 0,
- dev->board_name, dev)) {
- printk(KERN_WARNING
- ", unable to allocate IRQ %u, "
- "DISABLING IT", irq);
- irq = 0; /* Can't use IRQ */
- } else {
- printk(", irq=%u", irq);
- }
- }
- }
+ /* Handle PCL-724 in 96 DIO configuration */
+ if (board->can_have96 &&
+ (it->options[2] == 1 || it->options[2] == 96)) {
+ iorange = 0x10;
+ n_subdevices = 4;
}
- dev->irq = irq;
-#endif
-
- printk("\n");
-
- n_subdevices = board->numofports;
- if ((board->can_have96) && ((it->options[1] == 1)
- || (it->options[1] == 96)))
- n_subdevices = 4; /* PCL-724 in 96 DIO configuration */
+ ret = comedi_request_region(dev, it->options[0], iorange);
+ if (ret)
+ return ret;
ret = comedi_alloc_subdevices(dev, n_subdevices);
if (ret)
@@ -155,41 +122,25 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it)
for (i = 0; i < dev->n_subdevices; i++) {
s = &dev->subdevices[i];
if (board->is_pet48) {
- subdev_8255_init(dev, s, subdev_8255mapped_cb,
- (unsigned long)(dev->iobase +
- i * 0x1000));
- } else
- subdev_8255_init(dev, s, subdev_8255_cb,
- (unsigned long)(dev->iobase +
- SIZE_8255 * i));
+ iobase = dev->iobase + (i * 0x1000);
+ ret = subdev_8255_init(dev, s, pcl724_8255mapped_io,
+ iobase);
+ } else {
+ iobase = dev->iobase + (i * SIZE_8255);
+ ret = subdev_8255_init(dev, s, NULL, iobase);
+ }
+ if (ret)
+ return ret;
}
return 0;
}
-static void pcl724_detach(struct comedi_device *dev)
-{
- int i;
-
- for (i = 0; i < dev->n_subdevices; i++)
- comedi_spriv_free(dev, i);
- comedi_legacy_detach(dev);
-}
-
-static const struct pcl724_board boardtypes[] = {
- { "pcl724", 24, 1, 0x00fc, PCL724_SIZE, 0, 0, },
- { "pcl722", 144, 6, 0x00fc, PCL722_SIZE, 1, 0, },
- { "pcl731", 48, 2, 0x9cfc, PCL731_SIZE, 0, 0, },
- { "acl7122", 144, 6, 0x9ee8, PCL722_SIZE, 1, 0, },
- { "acl7124", 24, 1, 0x00fc, PCL724_SIZE, 0, 0, },
- { "pet48dio", 48, 2, 0x9eb8, PET48_SIZE, 0, 1, },
-};
-
static struct comedi_driver pcl724_driver = {
.driver_name = "pcl724",
.module = THIS_MODULE,
.attach = pcl724_attach,
- .detach = pcl724_detach,
+ .detach = comedi_legacy_detach,
.board_name = &boardtypes[0].name,
.num_names = ARRAY_SIZE(boardtypes),
.offset = sizeof(struct pcl724_board),
@@ -197,5 +148,5 @@ static struct comedi_driver pcl724_driver = {
module_comedi_driver(pcl724_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for 8255 based ISA DIO boards");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c
deleted file mode 100644
index 6b02f0631b4c..000000000000
--- a/drivers/staging/comedi/drivers/pcl725.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * comedi/drivers/pcl725.c
- * Driver for PCL725 and clones
- * David A. Schleef
- */
-/*
-Driver: pcl725
-Description: Advantech PCL-725 (& compatibles)
-Author: ds
-Status: unknown
-Devices: [Advantech] PCL-725 (pcl725)
-*/
-
-#include "../comedidev.h"
-
-#include <linux/ioport.h>
-
-#define PCL725_SIZE 2
-
-#define PCL725_DO 0
-#define PCL725_DI 1
-
-static int pcl725_do_insn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
- outb(s->state, dev->iobase + PCL725_DO);
- }
-
- data[1] = s->state;
-
- return insn->n;
-}
-
-static int pcl725_di_insn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- data[1] = inb(dev->iobase + PCL725_DI);
-
- return insn->n;
-}
-
-static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it)
-{
- struct comedi_subdevice *s;
- int ret;
-
- ret = comedi_request_region(dev, it->options[0], PCL725_SIZE);
- if (ret)
- return ret;
-
- ret = comedi_alloc_subdevices(dev, 2);
- if (ret)
- return ret;
-
- s = &dev->subdevices[0];
- /* do */
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE;
- s->maxdata = 1;
- s->n_chan = 8;
- s->insn_bits = pcl725_do_insn;
- s->range_table = &range_digital;
-
- s = &dev->subdevices[1];
- /* di */
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE;
- s->maxdata = 1;
- s->n_chan = 8;
- s->insn_bits = pcl725_di_insn;
- s->range_table = &range_digital;
-
- printk(KERN_INFO "\n");
-
- return 0;
-}
-
-static struct comedi_driver pcl725_driver = {
- .driver_name = "pcl725",
- .module = THIS_MODULE,
- .attach = pcl725_attach,
- .detach = comedi_legacy_detach,
-};
-module_comedi_driver(pcl725_driver);
-
-MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
index 4aa994393fae..893f012a1b7a 100644
--- a/drivers/staging/comedi/drivers/pcl726.c
+++ b/drivers/staging/comedi/drivers/pcl726.c
@@ -20,11 +20,6 @@
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: pcl726
diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c
index 2879db75da3e..862e75fd68fd 100644
--- a/drivers/staging/comedi/drivers/pcl730.c
+++ b/drivers/staging/comedi/drivers/pcl730.c
@@ -3,135 +3,299 @@
* Driver for Advantech PCL-730 and clones
* José Luis Sánchez
*/
-/*
-Driver: pcl730
-Description: Advantech PCL-730 (& compatibles)
-Author: José Luis Sánchez (jsanchezv@teleline.es)
-Status: untested
-Devices: [Advantech] PCL-730 (pcl730), [ICP] ISO-730 (iso730),
- [Adlink] ACL-7130 (acl7130)
-Interrupts are not supported.
-The ACL-7130 card have an 8254 timer/counter not supported by this driver.
-*/
+/*
+ * Driver: pcl730
+ * Description: Advantech PCL-730 (& compatibles)
+ * Devices: (Advantech) PCL-730 [pcl730]
+ * (ICP) ISO-730 [iso730]
+ * (Adlink) ACL-7130 [acl7130]
+ * (Advantech) PCM-3730 [pcm3730]
+ * (Advantech) PCL-725 [pcl725]
+ * (ICP) P8R8-DIO [p16r16dio]
+ * (Adlink) ACL-7225b [acl7225b]
+ * (ICP) P16R16-DIO [p16r16dio]
+ * (Advantech) PCL-733 [pcl733]
+ * (Advantech) PCL-734 [pcl734]
+ * Author: José Luis Sánchez (jsanchezv@teleline.es)
+ * Status: untested
+ *
+ * Configuration options:
+ * [0] - I/O port base
+ *
+ * Interrupts are not supported.
+ * The ACL-7130 card has an 8254 timer/counter not supported by this driver.
+ */
#include "../comedidev.h"
#include <linux/ioport.h>
-#define PCL730_SIZE 4
-#define ACL7130_SIZE 8
-#define PCL730_IDIO_LO 0 /* Isolated Digital I/O low byte (ID0-ID7) */
-#define PCL730_IDIO_HI 1 /* Isolated Digital I/O high byte (ID8-ID15) */
-#define PCL730_DIO_LO 2 /* TTL Digital I/O low byte (D0-D7) */
-#define PCL730_DIO_HI 3 /* TTL Digital I/O high byte (D8-D15) */
+/*
+ * Register map
+ *
+ * The register map varies slightly depending on the board type but
+ * all registers are 8-bit.
+ *
+ * The boardinfo 'io_range' is used to allow comedi to request the
+ * proper range required by the board.
+ *
+ * The comedi_subdevice 'private' data is used to pass the register
+ * offset to the (*insn_bits) functions to read/write the correct
+ * registers.
+ *
+ * The basic register mapping looks like this:
+ *
+ * BASE+0 Isolated outputs 0-7 (write) / inputs 0-7 (read)
+ * BASE+1 Isolated outputs 8-15 (write) / inputs 8-15 (read)
+ * BASE+2 TTL outputs 0-7 (write) / inputs 0-7 (read)
+ * BASE+3 TTL outputs 8-15 (write) / inputs 8-15 (read)
+ *
+ * The pcm3730 board does not have register BASE+1.
+ *
+ * The pcl725 and p8r8dio only have registers BASE+0 and BASE+1:
+ *
+ * BASE+0 Isolated outputs 0-7 (write) (read back on p8r8dio)
+ * BASE+1 Isolated inputs 0-7 (read)
+ *
+ * The acl7225b and p16r16dio boards have this register mapping:
+ *
+ * BASE+0 Isolated outputs 0-7 (write) (read back)
+ * BASE+1 Isolated outputs 8-15 (write) (read back)
+ * BASE+2 Isolated inputs 0-7 (read)
+ * BASE+3 Isolated inputs 8-15 (read)
+ *
+ * The pcl733 and pcl733 boards have this register mapping:
+ *
+ * BASE+0 Isolated outputs 0-7 (write) or inputs 0-7 (read)
+ * BASE+1 Isolated outputs 8-15 (write) or inputs 8-15 (read)
+ * BASE+2 Isolated outputs 16-23 (write) or inputs 16-23 (read)
+ * BASE+3 Isolated outputs 24-31 (write) or inputs 24-31 (read)
+ */
struct pcl730_board {
+ const char *name;
+ unsigned int io_range;
+ unsigned is_pcl725:1;
+ unsigned is_acl7225b:1;
+ unsigned has_readback:1;
+ unsigned has_ttl_io:1;
+ int n_subdevs;
+ int n_iso_out_chan;
+ int n_iso_in_chan;
+ int n_ttl_chan;
+};
- const char *name; /* board name */
- unsigned int io_range; /* len of I/O space */
+static const struct pcl730_board pcl730_boards[] = {
+ {
+ .name = "pcl730",
+ .io_range = 0x04,
+ .has_ttl_io = 1,
+ .n_subdevs = 4,
+ .n_iso_out_chan = 16,
+ .n_iso_in_chan = 16,
+ .n_ttl_chan = 16,
+ }, {
+ .name = "iso730",
+ .io_range = 0x04,
+ .n_subdevs = 4,
+ .n_iso_out_chan = 16,
+ .n_iso_in_chan = 16,
+ .n_ttl_chan = 16,
+ }, {
+ .name = "acl7130",
+ .io_range = 0x08,
+ .has_ttl_io = 1,
+ .n_subdevs = 4,
+ .n_iso_out_chan = 16,
+ .n_iso_in_chan = 16,
+ .n_ttl_chan = 16,
+ }, {
+ .name = "pcm3730",
+ .io_range = 0x04,
+ .has_ttl_io = 1,
+ .n_subdevs = 4,
+ .n_iso_out_chan = 8,
+ .n_iso_in_chan = 8,
+ .n_ttl_chan = 16,
+ }, {
+ .name = "pcl725",
+ .io_range = 0x02,
+ .is_pcl725 = 1,
+ .n_subdevs = 2,
+ .n_iso_out_chan = 8,
+ .n_iso_in_chan = 8,
+ }, {
+ .name = "p8r8dio",
+ .io_range = 0x02,
+ .is_pcl725 = 1,
+ .has_readback = 1,
+ .n_subdevs = 2,
+ .n_iso_out_chan = 8,
+ .n_iso_in_chan = 8,
+ }, {
+ .name = "acl7225b",
+ .io_range = 0x08, /* only 4 are used */
+ .is_acl7225b = 1,
+ .has_readback = 1,
+ .n_subdevs = 2,
+ .n_iso_out_chan = 16,
+ .n_iso_in_chan = 16,
+ }, {
+ .name = "p16r16dio",
+ .io_range = 0x04,
+ .is_acl7225b = 1,
+ .has_readback = 1,
+ .n_subdevs = 2,
+ .n_iso_out_chan = 16,
+ .n_iso_in_chan = 16,
+ }, {
+ .name = "pcl733",
+ .io_range = 0x04,
+ .n_subdevs = 1,
+ .n_iso_in_chan = 32,
+ }, {
+ .name = "pcl734",
+ .io_range = 0x04,
+ .n_subdevs = 1,
+ .n_iso_out_chan = 32,
+ },
};
-static int pcl730_do_insn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int pcl730_do_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
+ unsigned long reg = (unsigned long)s->private;
+ unsigned int mask = data[0];
+ unsigned int bits = data[1];
+
+ if (mask) {
+ s->state &= ~mask;
+ s->state |= (bits & mask);
+
+ if (mask & 0x00ff)
+ outb(s->state & 0xff, dev->iobase + reg);
+ if ((mask & 0xff00) && (s->n_chan > 8))
+ outb((s->state >> 8) & 0xff, dev->iobase + reg + 1);
+ if ((mask & 0xff0000) && (s->n_chan > 16))
+ outb((s->state >> 16) & 0xff, dev->iobase + reg + 2);
+ if ((mask & 0xff000000) && (s->n_chan > 24))
+ outb((s->state >> 24) & 0xff, dev->iobase + reg + 3);
}
- if (data[0] & 0x00ff)
- outb(s->state & 0xff,
- dev->iobase + ((unsigned long)s->private));
- if (data[0] & 0xff00)
- outb((s->state >> 8),
- dev->iobase + ((unsigned long)s->private) + 1);
data[1] = s->state;
return insn->n;
}
-static int pcl730_di_insn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static unsigned int pcl730_get_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s)
{
- data[1] = inb(dev->iobase + ((unsigned long)s->private)) |
- (inb(dev->iobase + ((unsigned long)s->private) + 1) << 8);
+ unsigned long reg = (unsigned long)s->private;
+ unsigned int val;
+
+ val = inb(dev->iobase + reg);
+ if (s->n_chan > 8)
+ val |= (inb(dev->iobase + reg + 1) << 8);
+ if (s->n_chan > 16)
+ val |= (inb(dev->iobase + reg + 2) << 16);
+ if (s->n_chan > 24)
+ val |= (inb(dev->iobase + reg + 3) << 24);
+
+ return val;
+}
+
+static int pcl730_di_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ data[1] = pcl730_get_bits(dev, s);
return insn->n;
}
-static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int pcl730_attach(struct comedi_device *dev,
+ struct comedi_devconfig *it)
{
const struct pcl730_board *board = comedi_board(dev);
struct comedi_subdevice *s;
+ int subdev;
int ret;
ret = comedi_request_region(dev, it->options[0], board->io_range);
if (ret)
return ret;
- ret = comedi_alloc_subdevices(dev, 4);
+ ret = comedi_alloc_subdevices(dev, board->n_subdevs);
if (ret)
return ret;
- s = &dev->subdevices[0];
- /* Isolated do */
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE;
- s->maxdata = 1;
- s->n_chan = 16;
- s->insn_bits = pcl730_do_insn;
- s->range_table = &range_digital;
- s->private = (void *)PCL730_IDIO_LO;
-
- s = &dev->subdevices[1];
- /* Isolated di */
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE;
- s->maxdata = 1;
- s->n_chan = 16;
- s->insn_bits = pcl730_di_insn;
- s->range_table = &range_digital;
- s->private = (void *)PCL730_IDIO_LO;
-
- s = &dev->subdevices[2];
- /* TTL do */
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE;
- s->maxdata = 1;
- s->n_chan = 16;
- s->insn_bits = pcl730_do_insn;
- s->range_table = &range_digital;
- s->private = (void *)PCL730_DIO_LO;
-
- s = &dev->subdevices[3];
- /* TTL di */
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE;
- s->maxdata = 1;
- s->n_chan = 16;
- s->insn_bits = pcl730_di_insn;
- s->range_table = &range_digital;
- s->private = (void *)PCL730_DIO_LO;
-
- printk(KERN_INFO "\n");
+ subdev = 0;
+
+ if (board->n_iso_out_chan) {
+ /* Isolated Digital Outputs */
+ s = &dev->subdevices[subdev++];
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = board->n_iso_out_chan;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = pcl730_do_insn_bits;
+ s->private = (void *)0;
+
+ /* get the initial state if supported */
+ if (board->has_readback)
+ s->state = pcl730_get_bits(dev, s);
+ }
+
+ if (board->n_iso_in_chan) {
+ /* Isolated Digital Inputs */
+ s = &dev->subdevices[subdev++];
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = board->n_iso_in_chan;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = pcl730_di_insn_bits;
+ s->private = board->is_acl7225b ? (void *)2 :
+ board->is_pcl725 ? (void *)1 : (void *)0;
+ }
+
+ if (board->has_ttl_io) {
+ /* TTL Digital Outputs */
+ s = &dev->subdevices[subdev++];
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = board->n_ttl_chan;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = pcl730_do_insn_bits;
+ s->private = (void *)2;
+
+ /* TTL Digital Inputs */
+ s = &dev->subdevices[subdev++];
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = board->n_ttl_chan;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = pcl730_di_insn_bits;
+ s->private = (void *)2;
+ }
return 0;
}
-static const struct pcl730_board boardtypes[] = {
- { "pcl730", PCL730_SIZE, },
- { "iso730", PCL730_SIZE, },
- { "acl7130", ACL7130_SIZE, },
-};
-
static struct comedi_driver pcl730_driver = {
.driver_name = "pcl730",
.module = THIS_MODULE,
.attach = pcl730_attach,
.detach = comedi_legacy_detach,
- .board_name = &boardtypes[0].name,
- .num_names = ARRAY_SIZE(boardtypes),
+ .board_name = &pcl730_boards[0].name,
+ .num_names = ARRAY_SIZE(pcl730_boards),
.offset = sizeof(struct pcl730_board),
};
module_comedi_driver(pcl730_driver);
diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
index 4ef0df30b07a..5a9cd38e15f2 100644
--- a/drivers/staging/comedi/drivers/pcm3724.c
+++ b/drivers/staging/comedi/drivers/pcm3724.c
@@ -250,20 +250,11 @@ static int pcm3724_attach(struct comedi_device *dev,
return 0;
}
-static void pcm3724_detach(struct comedi_device *dev)
-{
- int i;
-
- for (i = 0; i < dev->n_subdevices; i++)
- comedi_spriv_free(dev, i);
- comedi_legacy_detach(dev);
-}
-
static struct comedi_driver pcm3724_driver = {
.driver_name = "pcm3724",
.module = THIS_MODULE,
.attach = pcm3724_attach,
- .detach = pcm3724_detach,
+ .detach = comedi_legacy_detach,
};
module_comedi_driver(pcm3724_driver);
diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c
deleted file mode 100644
index 3a3ce2c769a2..000000000000
--- a/drivers/staging/comedi/drivers/pcm3730.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * comedi/drivers/pcm3730.c
- * Driver for PCM3730 and clones
- * Blaine Lee
- * from pcl725 by David S.
- */
-/*
-Driver: pcm3730
-Description: PCM3730
-Author: Blaine Lee
-Devices: [Advantech] PCM-3730 (pcm3730)
-Status: unknown
-
-Configuration options:
- [0] - I/O port base
-*/
-
-#include "../comedidev.h"
-
-#include <linux/ioport.h>
-
-#define PCM3730_SIZE 4 /* consecutive io port addresses */
-
-#define PCM3730_DOA 0 /* offsets for each port */
-#define PCM3730_DOB 2
-#define PCM3730_DOC 3
-#define PCM3730_DIA 0
-#define PCM3730_DIB 2
-#define PCM3730_DIC 3
-
-static int pcm3730_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
- outb(s->state, dev->iobase + (unsigned long)(s->private));
- }
- data[1] = s->state;
-
- return insn->n;
-}
-
-static int pcm3730_di_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- data[1] = inb(dev->iobase + (unsigned long)(s->private));
- return insn->n;
-}
-
-static int pcm3730_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct comedi_subdevice *s;
- int ret;
-
- ret = comedi_request_region(dev, it->options[0], PCM3730_SIZE);
- if (ret)
- return ret;
-
- ret = comedi_alloc_subdevices(dev, 6);
- if (ret)
- return ret;
-
- s = &dev->subdevices[0];
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE;
- s->maxdata = 1;
- s->n_chan = 8;
- s->insn_bits = pcm3730_do_insn_bits;
- s->range_table = &range_digital;
- s->private = (void *)PCM3730_DOA;
-
- s = &dev->subdevices[1];
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE;
- s->maxdata = 1;
- s->n_chan = 8;
- s->insn_bits = pcm3730_do_insn_bits;
- s->range_table = &range_digital;
- s->private = (void *)PCM3730_DOB;
-
- s = &dev->subdevices[2];
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE;
- s->maxdata = 1;
- s->n_chan = 8;
- s->insn_bits = pcm3730_do_insn_bits;
- s->range_table = &range_digital;
- s->private = (void *)PCM3730_DOC;
-
- s = &dev->subdevices[3];
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE;
- s->maxdata = 1;
- s->n_chan = 8;
- s->insn_bits = pcm3730_di_insn_bits;
- s->range_table = &range_digital;
- s->private = (void *)PCM3730_DIA;
-
- s = &dev->subdevices[4];
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE;
- s->maxdata = 1;
- s->n_chan = 8;
- s->insn_bits = pcm3730_di_insn_bits;
- s->range_table = &range_digital;
- s->private = (void *)PCM3730_DIB;
-
- s = &dev->subdevices[5];
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE;
- s->maxdata = 1;
- s->n_chan = 8;
- s->insn_bits = pcm3730_di_insn_bits;
- s->range_table = &range_digital;
- s->private = (void *)PCM3730_DIC;
-
- printk(KERN_INFO "\n");
-
- return 0;
-}
-
-static struct comedi_driver pcm3730_driver = {
- .driver_name = "pcm3730",
- .module = THIS_MODULE,
- .attach = pcm3730_attach,
- .detach = comedi_legacy_detach,
-};
-module_comedi_driver(pcm3730_driver);
-
-MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
index b7c932e152e0..d5c728dc6192 100644
--- a/drivers/staging/comedi/drivers/pcmad.c
+++ b/drivers/staging/comedi/drivers/pcmad.c
@@ -1,52 +1,44 @@
/*
- comedi/drivers/pcmad.c
- Hardware driver for Winsystems PCM-A/D12 and PCM-A/D16
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 2000,2001 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.
+ * pcmad.c
+ * Hardware driver for Winsystems PCM-A/D12 and PCM-A/D16
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000,2001 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.
+ */
-*/
/*
-Driver: pcmad
-Description: Winsystems PCM-A/D12, PCM-A/D16
-Author: ds
-Devices: [Winsystems] PCM-A/D12 (pcmad12), PCM-A/D16 (pcmad16)
-Status: untested
-
-This driver was written on a bet that I couldn't write a driver
-in less than 2 hours. I won the bet, but never got paid. =(
-
-Configuration options:
- [0] - I/O port base
- [1] - unused
- [2] - Analog input reference
- 0 = single ended
- 1 = differential
- [3] - Analog input encoding (must match jumpers)
- 0 = straight binary
- 1 = two's complement
-*/
-
-#include <linux/interrupt.h>
-#include "../comedidev.h"
-
-#include <linux/ioport.h>
+ * Driver: pcmad
+ * Description: Winsystems PCM-A/D12, PCM-A/D16
+ * Devices: (Winsystems) PCM-A/D12 [pcmad12]
+ * (Winsystems) PCM-A/D16 [pcmad16]
+ * Author: ds
+ * Status: untested
+ *
+ * This driver was written on a bet that I couldn't write a driver
+ * in less than 2 hours. I won the bet, but never got paid. =(
+ *
+ * Configuration options:
+ * [0] - I/O port base
+ * [1] - IRQ (unused)
+ * [2] - Analog input reference (must match jumpers)
+ * 0 = single-ended (16 channels)
+ * 1 = differential (8 channels)
+ * [3] - Analog input encoding (must match jumpers)
+ * 0 = straight binary (0-5V input range)
+ * 1 = two's complement (+-10V input range)
+ */
-#define PCMAD_SIZE 4
+#include "../comedidev.h"
#define PCMAD_STATUS 0
#define PCMAD_LSB 1
@@ -55,60 +47,82 @@ Configuration options:
struct pcmad_board_struct {
const char *name;
- int n_ai_bits;
+ unsigned int ai_maxdata;
};
-struct pcmad_priv_struct {
- int differential;
- int twos_comp;
+static const struct pcmad_board_struct pcmad_boards[] = {
+ {
+ .name = "pcmad12",
+ .ai_maxdata = 0x0fff,
+ }, {
+ .name = "pcmad16",
+ .ai_maxdata = 0xffff,
+ },
};
#define TIMEOUT 100
+static int pcmad_ai_wait_for_eoc(struct comedi_device *dev,
+ int timeout)
+{
+ int i;
+
+ for (i = 0; i < timeout; i++) {
+ if ((inb(dev->iobase + PCMAD_STATUS) & 0x3) == 0x3)
+ return 0;
+ }
+ return -ETIME;
+}
+
+static bool pcmad_range_is_bipolar(struct comedi_subdevice *s,
+ unsigned int range)
+{
+ return s->range_table->range[range].min < 0;
+}
+
static int pcmad_ai_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- const struct pcmad_board_struct *board = comedi_board(dev);
- struct pcmad_priv_struct *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int range = CR_RANGE(insn->chanspec);
+ unsigned int val;
+ int ret;
int i;
- int chan;
- int n;
- chan = CR_CHAN(insn->chanspec);
-
- for (n = 0; n < insn->n; n++) {
+ for (i = 0; i < insn->n; i++) {
outb(chan, dev->iobase + PCMAD_CONVERT);
- for (i = 0; i < TIMEOUT; i++) {
- if ((inb(dev->iobase + PCMAD_STATUS) & 0x3) == 0x3)
- break;
+ ret = pcmad_ai_wait_for_eoc(dev, TIMEOUT);
+ if (ret)
+ return ret;
+
+ val = inb(dev->iobase + PCMAD_LSB) |
+ (inb(dev->iobase + PCMAD_MSB) << 8);
+
+ /* data is shifted on the pcmad12, fix it */
+ if (s->maxdata == 0x0fff)
+ val >>= 4;
+
+ if (pcmad_range_is_bipolar(s, range)) {
+ /* munge the two's complement value */
+ val ^= ((s->maxdata + 1) >> 1);
}
- data[n] = inb(dev->iobase + PCMAD_LSB);
- data[n] |= (inb(dev->iobase + PCMAD_MSB) << 8);
- if (devpriv->twos_comp)
- data[n] ^= (1 << (board->n_ai_bits - 1));
+ data[i] = val;
}
- return n;
+ return insn->n;
}
-/*
- * options:
- * 0 i/o base
- * 1 unused
- * 2 0=single ended 1=differential
- * 3 0=straight binary 1=two's comp
- */
static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
const struct pcmad_board_struct *board = comedi_board(dev);
- struct pcmad_priv_struct *devpriv;
struct comedi_subdevice *s;
int ret;
- ret = comedi_request_region(dev, it->options[0], PCMAD_SIZE);
+ ret = comedi_request_region(dev, it->options[0], 0x04);
if (ret)
return ret;
@@ -116,32 +130,25 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret)
return ret;
- devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
- if (!devpriv)
- return -ENOMEM;
- dev->private = devpriv;
-
s = &dev->subdevices[0];
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | AREF_GROUND;
- s->n_chan = 16; /* XXX */
- s->len_chanlist = 1;
- s->insn_read = pcmad_ai_insn_read;
- s->maxdata = (1 << board->n_ai_bits) - 1;
- s->range_table = &range_unknown;
+ s->type = COMEDI_SUBD_AI;
+ if (it->options[1]) {
+ /* 8 differential channels */
+ s->subdev_flags = SDF_READABLE | AREF_DIFF;
+ s->n_chan = 8;
+ } else {
+ /* 16 single-ended channels */
+ s->subdev_flags = SDF_READABLE | AREF_GROUND;
+ s->n_chan = 16;
+ }
+ s->len_chanlist = 1;
+ s->maxdata = board->ai_maxdata;
+ s->range_table = it->options[2] ? &range_bipolar10 : &range_unipolar5;
+ s->insn_read = pcmad_ai_insn_read;
return 0;
}
-static const struct pcmad_board_struct pcmad_boards[] = {
- {
- .name = "pcmad12",
- .n_ai_bits = 12,
- }, {
- .name = "pcmad16",
- .n_ai_bits = 16,
- },
-};
static struct comedi_driver pcmad_driver = {
.driver_name = "pcmad",
.module = THIS_MODULE,
diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
index 61e7fd14a1e8..774a63dfe040 100644
--- a/drivers/staging/comedi/drivers/pcmda12.c
+++ b/drivers/staging/comedi/drivers/pcmda12.c
@@ -1,152 +1,130 @@
/*
- comedi/drivers/pcmda12.c
- Driver for Winsystems PC-104 based PCM-D/A-12 8-channel AO board.
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 2006 Calin A. Culianu <calin@ajvar.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.
-*/
+ * pcmda12.c
+ * Driver for Winsystems PC-104 based PCM-D/A-12 8-channel AO board.
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2006 Calin A. Culianu <calin@ajvar.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.
+ */
+
/*
-Driver: pcmda12
-Description: A driver for the Winsystems PCM-D/A-12
-Devices: [Winsystems] PCM-D/A-12 (pcmda12)
-Author: Calin Culianu <calin@ajvar.org>
-Updated: Fri, 13 Jan 2006 12:01:01 -0500
-Status: works
-
-A driver for the relatively straightforward-to-program PCM-D/A-12.
-This board doesn't support commands, and the only way to set its
-analog output range is to jumper the board. As such,
-comedi_data_write() ignores the range value specified.
-
-The board uses 16 consecutive I/O addresses starting at the I/O port
-base address. Each address corresponds to the LSB then MSB of a
-particular channel from 0-7.
-
-Note that the board is not ISA-PNP capable and thus
-needs the I/O port comedi_config parameter.
-
-Note that passing a nonzero value as the second config option will
-enable "simultaneous xfer" mode for this board, in which AO writes
-will not take effect until a subsequent read of any AO channel. This
-is so that one can speed up programming by preloading all AO registers
-with values before simultaneously setting them to take effect with one
-read command.
-
-Configuration Options:
- [0] - I/O port base address
- [1] - Do Simultaneous Xfer (see description)
-*/
+ * Driver: pcmda12
+ * Description: A driver for the Winsystems PCM-D/A-12
+ * Devices: (Winsystems) PCM-D/A-12 [pcmda12]
+ * Author: Calin Culianu <calin@ajvar.org>
+ * Updated: Fri, 13 Jan 2006 12:01:01 -0500
+ * Status: works
+ *
+ * A driver for the relatively straightforward-to-program PCM-D/A-12.
+ * This board doesn't support commands, and the only way to set its
+ * analog output range is to jumper the board. As such,
+ * comedi_data_write() ignores the range value specified.
+ *
+ * The board uses 16 consecutive I/O addresses starting at the I/O port
+ * base address. Each address corresponds to the LSB then MSB of a
+ * particular channel from 0-7.
+ *
+ * Note that the board is not ISA-PNP capable and thus needs the I/O
+ * port comedi_config parameter.
+ *
+ * Note that passing a nonzero value as the second config option will
+ * enable "simultaneous xfer" mode for this board, in which AO writes
+ * will not take effect until a subsequent read of any AO channel. This
+ * is so that one can speed up programming by preloading all AO registers
+ * with values before simultaneously setting them to take effect with one
+ * read command.
+ *
+ * Configuration Options:
+ * [0] - I/O port base address
+ * [1] - Do Simultaneous Xfer (see description)
+ */
#include "../comedidev.h"
-#define CHANS 8
-#define IOSIZE 16
-#define LSB(x) ((unsigned char)((x) & 0xff))
-#define MSB(x) ((unsigned char)((((unsigned short)(x))>>8) & 0xff))
-#define LSB_PORT(chan) (dev->iobase + (chan)*2)
-#define MSB_PORT(chan) (LSB_PORT(chan)+1)
-#define BITS 12
-
-/* note these have no effect and are merely here for reference..
- these are configured by jumpering the board! */
+/* AI range is not configurable, it's set by jumpers on the board */
static const struct comedi_lrange pcmda12_ranges = {
- 3,
- {
- UNI_RANGE(5), UNI_RANGE(10), BIP_RANGE(5)
- }
+ 3, {
+ UNI_RANGE(5),
+ UNI_RANGE(10),
+ BIP_RANGE(5)
+ }
};
struct pcmda12_private {
-
- unsigned int ao_readback[CHANS];
+ unsigned int ao_readback[8];
int simultaneous_xfer_mode;
};
-static void zero_chans(struct comedi_device *dev)
-{ /* sets up an
- ASIC chip to defaults */
- int i;
- for (i = 0; i < CHANS; ++i) {
-/* /\* do this as one instruction?? *\/ */
-/* outw(0, LSB_PORT(chan)); */
- outb(0, LSB_PORT(i));
- outb(0, MSB_PORT(i));
- }
- inb(LSB_PORT(0)); /* update chans. */
-}
-
-static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int pcmda12_ao_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct pcmda12_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int val = devpriv->ao_readback[chan];
+ unsigned long ioreg = dev->iobase + (chan * 2);
int i;
- int chan = CR_CHAN(insn->chanspec);
- /* Writing a list of values to an AO channel is probably not
- * very useful, but that's how the interface is defined. */
for (i = 0; i < insn->n; ++i) {
-
-/* /\* do this as one instruction?? *\/ */
-/* outw(data[i], LSB_PORT(chan)); */
-
- /* Need to do this as two instructions due to 8-bit bus?? */
- /* first, load the low byte */
- outb(LSB(data[i]), LSB_PORT(chan));
- /* next, write the high byte */
- outb(MSB(data[i]), MSB_PORT(chan));
-
- /* save shadow register */
- devpriv->ao_readback[chan] = data[i];
-
+ val = data[i];
+ outb(val & 0xff, ioreg);
+ outb((val >> 8) & 0xff, ioreg + 1);
+
+ /*
+ * Initiate transfer if not in simultaneaous xfer
+ * mode by reading one of the AO registers.
+ */
if (!devpriv->simultaneous_xfer_mode)
- inb(LSB_PORT(chan));
+ inb(ioreg);
}
+ devpriv->ao_readback[chan] = val;
- /* return the number of samples written */
- return i;
+ return insn->n;
}
-/* AO subdevices should have a read insn as well as a write insn.
-
- Usually this means copying a value stored in devpriv->ao_readback.
- However, since this driver supports simultaneous xfer then sometimes
- this function actually accomplishes work.
-
- Simultaneaous xfer mode is accomplished by loading ALL the values
- you want for AO in all the channels, then READing off one of the AO
- registers to initiate the instantaneous simultaneous update of all
- DAC outputs, which makes all AO channels update simultaneously.
- This is useful for some control applications, I would imagine.
-*/
-static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int pcmda12_ao_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct pcmda12_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
int i;
- int chan = CR_CHAN(insn->chanspec);
- for (i = 0; i < insn->n; i++) {
- if (devpriv->simultaneous_xfer_mode)
- inb(LSB_PORT(chan));
- /* read back shadow register */
+ /*
+ * Initiate simultaneaous xfer mode by reading one of the
+ * AO registers. All analog outputs will then be updated.
+ */
+ if (devpriv->simultaneous_xfer_mode)
+ inb(dev->iobase);
+
+ for (i = 0; i < insn->n; i++)
data[i] = devpriv->ao_readback[chan];
- }
- return i;
+ return insn->n;
+}
+
+static void pcmda12_ao_reset(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ int i;
+
+ for (i = 0; i < s->n_chan; ++i) {
+ outb(0, dev->iobase + (i * 2));
+ outb(0, dev->iobase + (i * 2) + 1);
+ }
+ /* Initiate transfer by reading one of the AO registers. */
+ inb(dev->iobase);
}
static int pcmda12_attach(struct comedi_device *dev,
@@ -156,7 +134,7 @@ static int pcmda12_attach(struct comedi_device *dev,
struct comedi_subdevice *s;
int ret;
- ret = comedi_request_region(dev, it->options[0], IOSIZE);
+ ret = comedi_request_region(dev, it->options[0], 0x10);
if (ret)
return ret;
@@ -172,18 +150,17 @@ static int pcmda12_attach(struct comedi_device *dev,
return ret;
s = &dev->subdevices[0];
- s->private = NULL;
- s->maxdata = (0x1 << BITS) - 1;
- s->range_table = &pcmda12_ranges;
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = CHANS;
- s->insn_write = &ao_winsn;
- s->insn_read = &ao_rinsn;
-
- zero_chans(dev); /* clear out all the registers, basically */
-
- return 1;
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 8;
+ s->maxdata = 0x0fff;
+ s->range_table = &pcmda12_ranges;
+ s->insn_write = pcmda12_ao_insn_write;
+ s->insn_read = pcmda12_ao_insn_read;
+
+ pcmda12_ao_reset(dev, s);
+
+ return 0;
}
static struct comedi_driver pcmda12_driver = {
diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
index 5a236cd5b33d..9f76b1f59983 100644
--- a/drivers/staging/comedi/drivers/pcmmio.c
+++ b/drivers/staging/comedi/drivers/pcmmio.c
@@ -14,10 +14,6 @@
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: pcmmio
diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
index 0c98e26bbba1..c43b6334ceae 100644
--- a/drivers/staging/comedi/drivers/pcmuio.c
+++ b/drivers/staging/comedi/drivers/pcmuio.c
@@ -1,79 +1,77 @@
/*
- comedi/drivers/pcmuio.c
- Driver for Winsystems PC-104 based 48-channel and 96-channel DIO boards.
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 2006 Calin A. Culianu <calin@ajvar.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.
-*/
+ * pcmuio.c
+ * Comedi driver for Winsystems PC-104 based 48/96-channel DIO boards.
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2006 Calin A. Culianu <calin@ajvar.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.
+ */
+
/*
-Driver: pcmuio
-Description: A driver for the PCM-UIO48A and PCM-UIO96A boards from Winsystems.
-Devices: [Winsystems] PCM-UIO48A (pcmuio48), PCM-UIO96A (pcmuio96)
-Author: Calin Culianu <calin@ajvar.org>
-Updated: Fri, 13 Jan 2006 12:01:01 -0500
-Status: works
-
-A driver for the relatively straightforward-to-program PCM-UIO48A and
-PCM-UIO96A boards from Winsystems. These boards use either one or two
-(in the 96-DIO version) WS16C48 ASIC HighDensity I/O Chips (HDIO).
-This chip is interesting in that each I/O line is individually
-programmable for INPUT or OUTPUT (thus comedi_dio_config can be done
-on a per-channel basis). Also, each chip supports edge-triggered
-interrupts for the first 24 I/O lines. Of course, since the
-96-channel version of the board has two ASICs, it can detect polarity
-changes on up to 48 I/O lines. Since this is essentially an (non-PnP)
-ISA board, I/O Address and IRQ selection are done through jumpers on
-the board. You need to pass that information to this driver as the
-first and second comedi_config option, respectively. Note that the
-48-channel version uses 16 bytes of IO memory and the 96-channel
-version uses 32-bytes (in case you are worried about conflicts). The
-48-channel board is split into two 24-channel comedi subdevices.
-The 96-channel board is split into 4 24-channel DIO subdevices.
-
-Note that IRQ support has been added, but it is untested.
-
-To use edge-detection IRQ support, pass the IRQs of both ASICS
-(for the 96 channel version) or just 1 ASIC (for 48-channel version).
-Then, use use comedi_commands with TRIG_NOW.
-Your callback will be called each time an edge is triggered, and the data
-values will be two sample_t's, which should be concatenated to form one
-32-bit unsigned int. This value is the mask of channels that had
-edges detected from your channel list. Note that the bits positions
-in the mask correspond to positions in your chanlist when you specified
-the command and *not* channel id's!
-
-To set the polarity of the edge-detection interrupts pass a nonzero value for
-either CR_RANGE or CR_AREF for edge-up polarity, or a zero value for both
-CR_RANGE and CR_AREF if you want edge-down polarity.
-
-In the 48-channel version:
-
-On subdev 0, the first 24 channels channels are edge-detect channels.
-
-In the 96-channel board you have the collowing channels that can do edge detection:
-
-subdev 0, channels 0-24 (first 24 channels of 1st ASIC)
-subdev 2, channels 0-24 (first 24 channels of 2nd ASIC)
-
-Configuration Options:
- [0] - I/O port base address
- [1] - IRQ (for first ASIC, or first 24 channels)
- [2] - IRQ for second ASIC (pcmuio96 only - IRQ for chans 48-72 .. can be the same as first irq!)
-*/
+ * Driver: pcmuio
+ * Description: Winsystems PC-104 based 48/96-channel DIO boards.
+ * Devices: (Winsystems) PCM-UIO48A [pcmuio48]
+ * (Winsystems) PCM-UIO96A [pcmuio96]
+ * Author: Calin Culianu <calin@ajvar.org>
+ * Updated: Fri, 13 Jan 2006 12:01:01 -0500
+ * Status: works
+ *
+ * A driver for the relatively straightforward-to-program PCM-UIO48A and
+ * PCM-UIO96A boards from Winsystems. These boards use either one or two
+ * (in the 96-DIO version) WS16C48 ASIC HighDensity I/O Chips (HDIO). This
+ * chip is interesting in that each I/O line is individually programmable
+ * for INPUT or OUTPUT (thus comedi_dio_config can be done on a per-channel
+ * basis). Also, each chip supports edge-triggered interrupts for the first
+ * 24 I/O lines. Of course, since the 96-channel version of the board has
+ * two ASICs, it can detect polarity changes on up to 48 I/O lines. Since
+ * this is essentially an (non-PnP) ISA board, I/O Address and IRQ selection
+ * are done through jumpers on the board. You need to pass that information
+ * to this driver as the first and second comedi_config option, respectively.
+ * Note that the 48-channel version uses 16 bytes of IO memory and the 96-
+ * channel version uses 32-bytes (in case you are worried about conflicts).
+ * The 48-channel board is split into two 24-channel comedi subdevices. The
+ * 96-channel board is split into 4 24-channel DIO subdevices.
+ *
+ * Note that IRQ support has been added, but it is untested.
+ *
+ * To use edge-detection IRQ support, pass the IRQs of both ASICS (for the
+ * 96 channel version) or just 1 ASIC (for 48-channel version). Then, use
+ * comedi_commands with TRIG_NOW. Your callback will be called each time an
+ * edge is triggered, and the data values will be two sample_t's, which
+ * should be concatenated to form one 32-bit unsigned int. This value is
+ * the mask of channels that had edges detected from your channel list. Note
+ * that the bits positions in the mask correspond to positions in your
+ * chanlist when you specified the command and *not* channel id's!
+ *
+ * To set the polarity of the edge-detection interrupts pass a nonzero value
+ * for either CR_RANGE or CR_AREF for edge-up polarity, or a zero value for
+ * both CR_RANGE and CR_AREF if you want edge-down polarity.
+ *
+ * In the 48-channel version:
+ *
+ * On subdev 0, the first 24 channels channels are edge-detect channels.
+ *
+ * In the 96-channel board you have the following channels that can do edge
+ * detection:
+ *
+ * subdev 0, channels 0-24 (first 24 channels of 1st ASIC)
+ * subdev 2, channels 0-24 (first 24 channels of 2nd ASIC)
+ *
+ * Configuration Options:
+ * [0] - I/O port base address
+ * [1] - IRQ (for first ASIC, or first 24 channels)
+ * [2] - IRQ (for second ASIC, pcmuio96 only - IRQ for chans 48-72
+ * can be the same as first irq!)
+ */
#include <linux/interrupt.h>
#include <linux/slab.h>
@@ -82,94 +80,62 @@ Configuration Options:
#include "comedi_fc.h"
-#define CHANS_PER_PORT 8
-#define PORTS_PER_ASIC 6
-#define INTR_PORTS_PER_ASIC 3
-#define MAX_CHANS_PER_SUBDEV 24 /* number of channels per comedi subdevice */
-#define PORTS_PER_SUBDEV (MAX_CHANS_PER_SUBDEV/CHANS_PER_PORT)
-#define CHANS_PER_ASIC (CHANS_PER_PORT*PORTS_PER_ASIC)
-#define INTR_CHANS_PER_ASIC 24
-#define INTR_PORTS_PER_SUBDEV (INTR_CHANS_PER_ASIC/CHANS_PER_PORT)
-#define MAX_DIO_CHANS (PORTS_PER_ASIC*2*CHANS_PER_PORT)
-#define MAX_ASICS (MAX_DIO_CHANS/CHANS_PER_ASIC)
-#define CALC_N_SUBDEVS(nchans) ((nchans)/MAX_CHANS_PER_SUBDEV + (!!((nchans)%MAX_CHANS_PER_SUBDEV)) /*+ (nchans > INTR_CHANS_PER_ASIC ? 2 : 1)*/)
-/* IO Memory sizes */
-#define ASIC_IOSIZE (0x10)
-#define PCMUIO48_IOSIZE ASIC_IOSIZE
-#define PCMUIO96_IOSIZE (ASIC_IOSIZE*2)
-
-/* Some offsets - these are all in the 16byte IO memory offset from
- the base address. Note that there is a paging scheme to swap out
- offsets 0x8-0xA using the PAGELOCK register. See the table below.
-
- Register(s) Pages R/W? Description
- --------------------------------------------------------------
- REG_PORTx All R/W Read/Write/Configure IO
- REG_INT_PENDING All ReadOnly Quickly see which INT_IDx has int.
- REG_PAGELOCK All WriteOnly Select a page
- REG_POLx Pg. 1 only WriteOnly Select edge-detection polarity
- REG_ENABx Pg. 2 only WriteOnly Enable/Disable edge-detect. int.
- REG_INT_IDx Pg. 3 only R/W See which ports/bits have ints.
- */
-#define REG_PORT0 0x0
-#define REG_PORT1 0x1
-#define REG_PORT2 0x2
-#define REG_PORT3 0x3
-#define REG_PORT4 0x4
-#define REG_PORT5 0x5
-#define REG_INT_PENDING 0x6
-#define REG_PAGELOCK 0x7 /* page selector register, upper 2 bits select a page
- and bits 0-5 are used to 'lock down' a particular
- port above to make it readonly. */
-#define REG_POL0 0x8
-#define REG_POL1 0x9
-#define REG_POL2 0xA
-#define REG_ENAB0 0x8
-#define REG_ENAB1 0x9
-#define REG_ENAB2 0xA
-#define REG_INT_ID0 0x8
-#define REG_INT_ID1 0x9
-#define REG_INT_ID2 0xA
-
-#define NUM_PAGED_REGS 3
-#define NUM_PAGES 4
-#define FIRST_PAGED_REG 0x8
-#define REG_PAGE_BITOFFSET 6
-#define REG_LOCK_BITOFFSET 0
-#define REG_PAGE_MASK (~((0x1<<REG_PAGE_BITOFFSET)-1))
-#define REG_LOCK_MASK ~(REG_PAGE_MASK)
-#define PAGE_POL 1
-#define PAGE_ENAB 2
-#define PAGE_INT_ID 3
-
/*
- * 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.
+ * Register I/O map
+ *
+ * Offset Page 0 Page 1 Page 2 Page 3
+ * ------ ----------- ----------- ----------- -----------
+ * 0x00 Port 0 I/O Port 0 I/O Port 0 I/O Port 0 I/O
+ * 0x01 Port 1 I/O Port 1 I/O Port 1 I/O Port 1 I/O
+ * 0x02 Port 2 I/O Port 2 I/O Port 2 I/O Port 2 I/O
+ * 0x03 Port 3 I/O Port 3 I/O Port 3 I/O Port 3 I/O
+ * 0x04 Port 4 I/O Port 4 I/O Port 4 I/O Port 4 I/O
+ * 0x05 Port 5 I/O Port 5 I/O Port 5 I/O Port 5 I/O
+ * 0x06 INT_PENDING INT_PENDING INT_PENDING INT_PENDING
+ * 0x07 Page/Lock Page/Lock Page/Lock Page/Lock
+ * 0x08 N/A POL_0 ENAB_0 INT_ID0
+ * 0x09 N/A POL_1 ENAB_1 INT_ID1
+ * 0x0a N/A POL_2 ENAB_2 INT_ID2
*/
+#define PCMUIO_PORT_REG(x) (0x00 + (x))
+#define PCMUIO_INT_PENDING_REG 0x06
+#define PCMUIO_PAGE_LOCK_REG 0x07
+#define PCMUIO_LOCK_PORT(x) ((1 << (x)) & 0x3f)
+#define PCMUIO_PAGE(x) (((x) & 0x3) << 6)
+#define PCMUIO_PAGE_MASK PCMUIO_PAGE(3)
+#define PCMUIO_PAGE_POL 1
+#define PCMUIO_PAGE_ENAB 2
+#define PCMUIO_PAGE_INT_ID 3
+#define PCMUIO_PAGE_REG(x) (0x08 + (x))
+
+#define PCMUIO_ASIC_IOSIZE 0x10
+#define PCMUIO_MAX_ASICS 2
+
struct pcmuio_board {
const char *name;
const int num_asics;
- const int num_channels_per_port;
- const int num_ports;
};
-/* this structure is for data unique to this subdevice. */
-struct pcmuio_subdev_private {
- /* mapping of halfwords (bytes) in port/chanarray to iobase */
- unsigned long iobases[PORTS_PER_SUBDEV];
+static const struct pcmuio_board pcmuio_boards[] = {
+ {
+ .name = "pcmuio48",
+ .num_asics = 1,
+ }, {
+ .name = "pcmuio96",
+ .num_asics = 2,
+ },
+};
+struct pcmuio_subdev_private {
/* The below is only used for intr subdevices */
struct {
- int asic; /* if non-negative, this subdev has an interrupt asic */
- int first_chan; /* if nonnegative, the first channel id for
- interrupts. */
- int num_asic_chans; /* the number of asic channels in this subdev
- that have interrutps */
- int asic_chan; /* if nonnegative, the first channel id with
- respect to the asic that has interrupts */
- int enabled_mask; /* subdev-relative channel mask for channels
- we are interested in */
+ /* if non-negative, this subdev has an interrupt asic */
+ int asic;
+ /*
+ * subdev-relative channel mask for channels
+ * we are interested in
+ */
+ int enabled_mask;
int active;
int stop_count;
int continuous;
@@ -177,160 +143,112 @@ struct pcmuio_subdev_private {
} intr;
};
-/* 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 struct comedi_device struct. */
struct pcmuio_private {
struct {
- unsigned char pagelock; /* current page and lock */
- unsigned char pol[NUM_PAGED_REGS]; /* shadow of POLx registers */
- unsigned char enab[NUM_PAGED_REGS]; /* shadow of ENABx registers */
- int num;
- unsigned long iobase;
unsigned int irq;
spinlock_t spinlock;
- } asics[MAX_ASICS];
+ } asics[PCMUIO_MAX_ASICS];
struct pcmuio_subdev_private *sprivs;
};
-#define subpriv ((struct pcmuio_subdev_private *)s->private)
+static void pcmuio_write(struct comedi_device *dev, unsigned int val,
+ int asic, int page, int port)
+{
+ unsigned long iobase = dev->iobase + (asic * PCMUIO_ASIC_IOSIZE);
+
+ if (page == 0) {
+ /* Port registers are valid for any page */
+ outb(val & 0xff, iobase + PCMUIO_PORT_REG(port + 0));
+ outb((val >> 8) & 0xff, iobase + PCMUIO_PORT_REG(port + 1));
+ outb((val >> 16) & 0xff, iobase + PCMUIO_PORT_REG(port + 2));
+ } else {
+ outb(PCMUIO_PAGE(page), iobase + PCMUIO_PAGE_LOCK_REG);
+ outb(val & 0xff, iobase + PCMUIO_PAGE_REG(0));
+ outb((val >> 8) & 0xff, iobase + PCMUIO_PAGE_REG(1));
+ outb((val >> 16) & 0xff, iobase + PCMUIO_PAGE_REG(2));
+ }
+}
+
+static unsigned int pcmuio_read(struct comedi_device *dev,
+ int asic, int page, int port)
+{
+ unsigned long iobase = dev->iobase + (asic * PCMUIO_ASIC_IOSIZE);
+ unsigned int val;
+
+ if (page == 0) {
+ /* Port registers are valid for any page */
+ val = inb(iobase + PCMUIO_PORT_REG(port + 0));
+ val |= (inb(iobase + PCMUIO_PORT_REG(port + 1)) << 8);
+ val |= (inb(iobase + PCMUIO_PORT_REG(port + 2)) << 16);
+ } else {
+ outb(PCMUIO_PAGE(page), iobase + PCMUIO_PAGE_LOCK_REG);
+ val = inb(iobase + PCMUIO_PAGE_REG(0));
+ val |= (inb(iobase + PCMUIO_PAGE_REG(1)) << 8);
+ val |= (inb(iobase + PCMUIO_PAGE_REG(2)) << 16);
+ }
-/* 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 */
+ return val;
+}
+
+/*
+ * Each channel can be individually programmed for input or output.
+ * Writing a '0' to a channel causes the corresponding output pin
+ * to go to a high-z state (pulled high by an external 10K resistor).
+ * This allows it to be used as an input. When used in the input mode,
+ * a read reflects the inverted state of the I/O pin, such that a
+ * high on the pin will read as a '0' in the register. Writing a '1'
+ * to a bit position causes the pin to sink current (up to 12mA),
+ * effectively pulling it low.
+ */
static int pcmuio_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
- int byte_no;
-
- /* NOTE:
- reading a 0 means this channel was high
- writine a 0 sets the channel high
- reading a 1 means this channel was low
- writing a 1 means set this channel low
-
- Therefore everything is always inverted. */
-
- /* The insn data is a mask in data[0] and the new data
- * in data[1], each channel cooresponding to a bit. */
-
-#ifdef DAMMIT_ITS_BROKEN
- /* DEBUG */
- dev_dbg(dev->class_dev, "write mask: %08x data: %08x\n", data[0],
- data[1]);
-#endif
-
- s->state = 0;
-
- for (byte_no = 0; byte_no < s->n_chan / CHANS_PER_PORT; ++byte_no) {
- /* address of 8-bit port */
- unsigned long ioaddr = subpriv->iobases[byte_no],
- /* bit offset of port in 32-bit doubleword */
- offset = byte_no * 8;
- /* this 8-bit port's data */
- unsigned char byte = 0,
- /* The write mask for this port (if any) */
- write_mask_byte = (data[0] >> offset) & 0xff,
- /* The data byte for this port */
- data_byte = (data[1] >> offset) & 0xff;
-
- byte = inb(ioaddr); /* read all 8-bits for this port */
-
-#ifdef DAMMIT_ITS_BROKEN
- /* DEBUG */
- printk
- ("byte %d wmb %02x db %02x offset %02d io %04x, data_in %02x ",
- byte_no, (unsigned)write_mask_byte, (unsigned)data_byte,
- offset, ioaddr, (unsigned)byte);
-#endif
-
- if (write_mask_byte) {
- /* this byte has some write_bits -- so set the output lines */
- byte &= ~write_mask_byte; /* clear bits for write mask */
- byte |= ~data_byte & write_mask_byte; /* set to inverted data_byte */
- /* Write out the new digital output state */
- outb(byte, ioaddr);
- }
-#ifdef DAMMIT_ITS_BROKEN
- /* DEBUG */
- dev_dbg(dev->class_dev, "data_out_byte %02x\n", (unsigned)byte);
-#endif
- /* save the digital input lines for this byte.. */
- s->state |= ((unsigned int)byte) << offset;
- }
+ unsigned int mask = data[0] & s->io_bits; /* outputs only */
+ unsigned int bits = data[1];
+ int asic = s->index / 2;
+ int port = (s->index % 2) ? 3 : 0;
+ unsigned int val;
+
+ /* get inverted state of the channels from the port */
+ val = pcmuio_read(dev, asic, 0, port);
+
+ /* get the true state of the channels */
+ s->state = val ^ ((0x1 << s->n_chan) - 1);
- /* now return the DIO lines to data[1] - note they came inverted! */
- data[1] = ~s->state;
+ if (mask) {
+ s->state &= ~mask;
+ s->state |= (mask & bits);
-#ifdef DAMMIT_ITS_BROKEN
- /* DEBUG */
- dev_dbg(dev->class_dev, "s->state %08x data_out %08x\n", s->state,
- data[1]);
-#endif
+ /* invert the state and update the channels */
+ val = s->state ^ ((0x1 << s->n_chan) - 1);
+ pcmuio_write(dev, val, asic, 0, port);
+ }
+
+ data[1] = s->state;
return insn->n;
}
-/* 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. */
static int pcmuio_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
- int chan = CR_CHAN(insn->chanspec), byte_no = chan / 8, bit_no =
- chan % 8;
- unsigned long ioaddr;
- unsigned char byte;
-
- /* Compute ioaddr for this channel */
- ioaddr = subpriv->iobases[byte_no];
-
- /* NOTE:
- writing a 0 an IO channel's bit sets the channel to INPUT
- and pulls the line high as well
-
- writing a 1 to an IO channel's bit pulls the line low
-
- All channels are implicitly always in OUTPUT mode -- but when
- they are high they can be considered to be in INPUT mode..
-
- Thus, we only force channels low if the config request was INPUT,
- otherwise we do nothing to the hardware. */
+ unsigned int chan_mask = 1 << CR_CHAN(insn->chanspec);
+ int asic = s->index / 2;
+ int port = (s->index % 2) ? 3 : 0;
switch (data[0]) {
case INSN_CONFIG_DIO_OUTPUT:
- /* save to io_bits -- don't actually do anything since
- all input channels are also output channels... */
- s->io_bits |= 1 << chan;
+ s->io_bits |= chan_mask;
break;
case INSN_CONFIG_DIO_INPUT:
- /* write a 0 to the actual register representing the channel
- to set it to 'input'. 0 means "float high". */
- byte = inb(ioaddr);
- byte &= ~(1 << bit_no);
- /**< set input channel to '0' */
-
- /* write out byte -- this is the only time we actually affect the
- hardware as all channels are implicitly output -- but input
- channels are set to float-high */
- outb(byte, ioaddr);
-
- /* save to io_bits */
- s->io_bits &= ~(1 << chan);
+ s->io_bits &= ~chan_mask;
+ pcmuio_write(dev, s->io_bits, asic, 0, port);
break;
-
case INSN_CONFIG_DIO_QUERY:
- /* retrieve from shadow register */
- data[1] =
- (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
- return insn->n;
+ data[1] = (s->io_bits & chan_mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
break;
-
default:
return -EINVAL;
break;
@@ -339,263 +257,154 @@ static int pcmuio_dio_insn_config(struct comedi_device *dev,
return insn->n;
}
-static void switch_page(struct comedi_device *dev, int asic, int page)
+static void pcmuio_reset(struct comedi_device *dev)
{
const struct pcmuio_board *board = comedi_board(dev);
- struct pcmuio_private *devpriv = dev->private;
-
- if (asic < 0 || asic >= board->num_asics)
- return; /* paranoia */
- if (page < 0 || page >= NUM_PAGES)
- return; /* more paranoia */
+ int asic;
- devpriv->asics[asic].pagelock &= ~REG_PAGE_MASK;
- devpriv->asics[asic].pagelock |= page << REG_PAGE_BITOFFSET;
+ for (asic = 0; asic < board->num_asics; ++asic) {
+ /* first, clear all the DIO port bits */
+ pcmuio_write(dev, 0, asic, 0, 0);
+ pcmuio_write(dev, 0, asic, 0, 3);
- /* now write out the shadow register */
- outb(devpriv->asics[asic].pagelock,
- dev->iobase + ASIC_IOSIZE * asic + REG_PAGELOCK);
+ /* Next, clear all the paged registers for each page */
+ pcmuio_write(dev, 0, asic, PCMUIO_PAGE_POL, 0);
+ pcmuio_write(dev, 0, asic, PCMUIO_PAGE_ENAB, 0);
+ pcmuio_write(dev, 0, asic, PCMUIO_PAGE_INT_ID, 0);
+ }
}
-static void init_asics(struct comedi_device *dev)
-{ /* sets up an
- ASIC chip to defaults */
- const struct pcmuio_board *board = comedi_board(dev);
+static void pcmuio_stop_intr(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ struct pcmuio_subdev_private *subpriv = s->private;
int asic;
- for (asic = 0; asic < board->num_asics; ++asic) {
- int port, page;
- unsigned long baseaddr = dev->iobase + asic * ASIC_IOSIZE;
+ asic = subpriv->intr.asic;
+ if (asic < 0)
+ return; /* not an interrupt subdev */
- switch_page(dev, asic, 0); /* switch back to page 0 */
+ subpriv->intr.enabled_mask = 0;
+ subpriv->intr.active = 0;
+ s->async->inttrig = NULL;
- /* first, clear all the DIO port bits */
- for (port = 0; port < PORTS_PER_ASIC; ++port)
- outb(0, baseaddr + REG_PORT0 + port);
+ /* disable all intrs for this subdev.. */
+ pcmuio_write(dev, 0, asic, PCMUIO_PAGE_ENAB, 0);
+}
- /* Next, clear all the paged registers for each page */
- for (page = 1; page < NUM_PAGES; ++page) {
- int reg;
- /* now clear all the paged registers */
- switch_page(dev, asic, page);
- for (reg = FIRST_PAGED_REG;
- reg < FIRST_PAGED_REG + NUM_PAGED_REGS; ++reg)
- outb(0, baseaddr + reg);
- }
+static void pcmuio_handle_intr_subdev(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned triggered)
+{
+ struct pcmuio_subdev_private *subpriv = s->private;
+ unsigned int len = s->async->cmd.chanlist_len;
+ unsigned oldevents = s->async->events;
+ unsigned int val = 0;
+ unsigned long flags;
+ unsigned mytrig;
+ unsigned int i;
- /* DEBUG set rising edge interrupts on port0 of both asics */
- /*switch_page(dev, asic, PAGE_POL);
- outb(0xff, baseaddr + REG_POL0);
- switch_page(dev, asic, PAGE_ENAB);
- outb(0xff, baseaddr + REG_ENAB0); */
- /* END DEBUG */
+ spin_lock_irqsave(&subpriv->intr.spinlock, flags);
- switch_page(dev, asic, 0); /* switch back to default page 0 */
+ if (!subpriv->intr.active)
+ goto done;
+ mytrig = triggered;
+ mytrig &= ((0x1 << s->n_chan) - 1);
+
+ if (!(mytrig & subpriv->intr.enabled_mask))
+ goto done;
+
+ for (i = 0; i < len; i++) {
+ unsigned int chan = CR_CHAN(s->async->cmd.chanlist[i]);
+ if (mytrig & (1U << chan))
+ val |= (1U << i);
}
-}
-#ifdef notused
-static void lock_port(struct comedi_device *dev, int asic, int port)
-{
- const struct pcmuio_board *board = comedi_board(dev);
- struct pcmuio_private *devpriv = dev->private;
+ /* Write the scan to the buffer. */
+ if (comedi_buf_put(s->async, ((short *)&val)[0]) &&
+ comedi_buf_put(s->async, ((short *)&val)[1])) {
+ s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
+ } else {
+ /* Overflow! Stop acquisition!! */
+ /* TODO: STOP_ACQUISITION_CALL_HERE!! */
+ pcmuio_stop_intr(dev, s);
+ }
- if (asic < 0 || asic >= board->num_asics)
- return; /* paranoia */
- if (port < 0 || port >= PORTS_PER_ASIC)
- return; /* more paranoia */
+ /* Check for end of acquisition. */
+ if (!subpriv->intr.continuous) {
+ /* stop_src == TRIG_COUNT */
+ if (subpriv->intr.stop_count > 0) {
+ subpriv->intr.stop_count--;
+ if (subpriv->intr.stop_count == 0) {
+ s->async->events |= COMEDI_CB_EOA;
+ /* TODO: STOP_ACQUISITION_CALL_HERE!! */
+ pcmuio_stop_intr(dev, s);
+ }
+ }
+ }
+
+done:
+ spin_unlock_irqrestore(&subpriv->intr.spinlock, flags);
- devpriv->asics[asic].pagelock |= 0x1 << port;
- /* now write out the shadow register */
- outb(devpriv->asics[asic].pagelock,
- dev->iobase + ASIC_IOSIZE * asic + REG_PAGELOCK);
+ if (oldevents != s->async->events)
+ comedi_event(dev, s);
}
-static void unlock_port(struct comedi_device *dev, int asic, int port)
+static int pcmuio_handle_asic_interrupt(struct comedi_device *dev, int asic)
{
- const struct pcmuio_board *board = comedi_board(dev);
struct pcmuio_private *devpriv = dev->private;
+ struct pcmuio_subdev_private *subpriv;
+ unsigned long iobase = dev->iobase + (asic * PCMUIO_ASIC_IOSIZE);
+ unsigned int triggered = 0;
+ int got1 = 0;
+ unsigned long flags;
+ unsigned char int_pend;
+ int i;
- if (asic < 0 || asic >= board->num_asics)
- return; /* paranoia */
- if (port < 0 || port >= PORTS_PER_ASIC)
- return; /* more paranoia */
- devpriv->asics[asic].pagelock &= ~(0x1 << port) | REG_LOCK_MASK;
- /* now write out the shadow register */
- outb(devpriv->asics[asic].pagelock,
- dev->iobase + ASIC_IOSIZE * asic + REG_PAGELOCK);
-}
-#endif /* notused */
+ spin_lock_irqsave(&devpriv->asics[asic].spinlock, flags);
-static void pcmuio_stop_intr(struct comedi_device *dev,
- struct comedi_subdevice *s)
-{
- int nports, firstport, asic, port;
- struct pcmuio_private *devpriv = dev->private;
+ int_pend = inb(iobase + PCMUIO_INT_PENDING_REG) & 0x07;
+ if (int_pend) {
+ triggered = pcmuio_read(dev, asic, PCMUIO_PAGE_INT_ID, 0);
+ pcmuio_write(dev, 0, asic, PCMUIO_PAGE_INT_ID, 0);
- asic = subpriv->intr.asic;
- if (asic < 0)
- return; /* not an interrupt subdev */
+ ++got1;
+ }
- subpriv->intr.enabled_mask = 0;
- subpriv->intr.active = 0;
- s->async->inttrig = NULL;
- nports = subpriv->intr.num_asic_chans / CHANS_PER_PORT;
- firstport = subpriv->intr.asic_chan / CHANS_PER_PORT;
- switch_page(dev, asic, PAGE_ENAB);
- for (port = firstport; port < firstport + nports; ++port) {
- /* disable all intrs for this subdev.. */
- outb(0, devpriv->asics[asic].iobase + REG_ENAB0 + port);
+ spin_unlock_irqrestore(&devpriv->asics[asic].spinlock, flags);
+
+ if (triggered) {
+ struct comedi_subdevice *s;
+ /* TODO here: dispatch io lines to subdevs with commands.. */
+ for (i = 0; i < dev->n_subdevices; i++) {
+ s = &dev->subdevices[i];
+ subpriv = s->private;
+ if (subpriv->intr.asic == asic) {
+ /*
+ * This is an interrupt subdev, and it
+ * matches this asic!
+ */
+ pcmuio_handle_intr_subdev(dev, s,
+ triggered);
+ }
+ }
}
+ return got1;
}
-static irqreturn_t interrupt_pcmuio(int irq, void *d)
+static irqreturn_t pcmuio_interrupt(int irq, void *d)
{
- int asic, got1 = 0;
- struct comedi_device *dev = (struct comedi_device *)d;
+ struct comedi_device *dev = d;
struct pcmuio_private *devpriv = dev->private;
- int i;
+ int got1 = 0;
+ int asic;
- for (asic = 0; asic < MAX_ASICS; ++asic) {
+ for (asic = 0; asic < PCMUIO_MAX_ASICS; ++asic) {
if (irq == devpriv->asics[asic].irq) {
- unsigned long flags;
- unsigned triggered = 0;
- unsigned long iobase = devpriv->asics[asic].iobase;
/* it is an interrupt for ASIC #asic */
- unsigned char int_pend;
-
- spin_lock_irqsave(&devpriv->asics[asic].spinlock,
- flags);
-
- int_pend = inb(iobase + REG_INT_PENDING) & 0x07;
-
- if (int_pend) {
- int port;
- for (port = 0; port < INTR_PORTS_PER_ASIC;
- ++port) {
- if (int_pend & (0x1 << port)) {
- unsigned char
- io_lines_with_edges = 0;
- switch_page(dev, asic,
- PAGE_INT_ID);
- io_lines_with_edges =
- inb(iobase +
- REG_INT_ID0 + port);
-
- if (io_lines_with_edges)
- /* clear pending interrupt */
- outb(0, iobase +
- REG_INT_ID0 +
- port);
-
- triggered |=
- io_lines_with_edges <<
- port * 8;
- }
- }
-
- ++got1;
- }
-
- spin_unlock_irqrestore(&devpriv->asics[asic].spinlock,
- flags);
-
- if (triggered) {
- struct comedi_subdevice *s;
- /* TODO here: dispatch io lines to subdevs with commands.. */
- printk
- ("PCMUIO DEBUG: got edge detect interrupt %d asic %d which_chans: %06x\n",
- irq, asic, triggered);
- for (i = 0; i < dev->n_subdevices; i++) {
- s = &dev->subdevices[i];
- if (subpriv->intr.asic == asic) { /* this is an interrupt subdev, and it matches this asic! */
- unsigned long flags;
- unsigned oldevents;
-
- spin_lock_irqsave(&subpriv->
- intr.spinlock,
- flags);
-
- oldevents = s->async->events;
-
- if (subpriv->intr.active) {
- unsigned mytrig =
- ((triggered >>
- subpriv->intr.asic_chan)
- &
- ((0x1 << subpriv->
- intr.
- num_asic_chans) -
- 1)) << subpriv->
- intr.first_chan;
- if (mytrig &
- subpriv->intr.enabled_mask)
- {
- unsigned int val
- = 0;
- unsigned int n,
- ch, len;
-
- len =
- s->
- async->cmd.chanlist_len;
- for (n = 0;
- n < len;
- n++) {
- ch = CR_CHAN(s->async->cmd.chanlist[n]);
- if (mytrig & (1U << ch)) {
- val |= (1U << n);
- }
- }
- /* Write the scan to the buffer. */
- if (comedi_buf_put(s->async, ((short *)&val)[0])
- &&
- comedi_buf_put
- (s->async,
- ((short *)
- &val)[1]))
- {
- s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
- } else {
- /* Overflow! Stop acquisition!! */
- /* TODO: STOP_ACQUISITION_CALL_HERE!! */
- pcmuio_stop_intr
- (dev,
- s);
- }
-
- /* Check for end of acquisition. */
- if (!subpriv->intr.continuous) {
- /* stop_src == TRIG_COUNT */
- if (subpriv->intr.stop_count > 0) {
- subpriv->intr.stop_count--;
- if (subpriv->intr.stop_count == 0) {
- s->async->events |= COMEDI_CB_EOA;
- /* TODO: STOP_ACQUISITION_CALL_HERE!! */
- pcmuio_stop_intr
- (dev,
- s);
- }
- }
- }
- }
- }
-
- spin_unlock_irqrestore
- (&subpriv->intr.spinlock,
- flags);
-
- if (oldevents !=
- s->async->events) {
- comedi_event(dev, s);
- }
-
- }
-
- }
- }
-
+ if (pcmuio_handle_asic_interrupt(dev, asic))
+ got1++;
}
}
if (!got1)
@@ -606,7 +415,7 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d)
static int pcmuio_start_intr(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- struct pcmuio_private *devpriv = dev->private;
+ struct pcmuio_subdev_private *subpriv = s->private;
if (!subpriv->intr.continuous && subpriv->intr.stop_count == 0) {
/* An empty acquisition! */
@@ -615,7 +424,7 @@ static int pcmuio_start_intr(struct comedi_device *dev,
return 1;
} else {
unsigned bits = 0, pol_bits = 0, n;
- int nports, firstport, asic, port;
+ int asic;
struct comedi_cmd *cmd = &s->async->cmd;
asic = subpriv->intr.asic;
@@ -624,8 +433,6 @@ static int pcmuio_start_intr(struct comedi_device *dev,
subdev */
subpriv->intr.enabled_mask = 0;
subpriv->intr.active = 1;
- nports = subpriv->intr.num_asic_chans / CHANS_PER_PORT;
- firstport = subpriv->intr.asic_chan / CHANS_PER_PORT;
if (cmd->chanlist) {
for (n = 0; n < cmd->chanlist_len; n++) {
bits |= (1U << CR_CHAN(cmd->chanlist[n]));
@@ -635,31 +442,19 @@ static int pcmuio_start_intr(struct comedi_device *dev,
<< CR_CHAN(cmd->chanlist[n]);
}
}
- bits &= ((0x1 << subpriv->intr.num_asic_chans) -
- 1) << subpriv->intr.first_chan;
+ bits &= ((0x1 << s->n_chan) - 1);
subpriv->intr.enabled_mask = bits;
- switch_page(dev, asic, PAGE_ENAB);
- for (port = firstport; port < firstport + nports; ++port) {
- unsigned enab =
- bits >> (subpriv->intr.first_chan + (port -
- firstport) *
- 8) & 0xff, pol =
- pol_bits >> (subpriv->intr.first_chan +
- (port - firstport) * 8) & 0xff;
- /* set enab intrs for this subdev.. */
- outb(enab,
- devpriv->asics[asic].iobase + REG_ENAB0 + port);
- switch_page(dev, asic, PAGE_POL);
- outb(pol,
- devpriv->asics[asic].iobase + REG_ENAB0 + port);
- }
+ /* set pol and enab intrs for this subdev.. */
+ pcmuio_write(dev, pol_bits, asic, PCMUIO_PAGE_POL, 0);
+ pcmuio_write(dev, bits, asic, PCMUIO_PAGE_ENAB, 0);
}
return 0;
}
static int pcmuio_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
{
+ struct pcmuio_subdev_private *subpriv = s->private;
unsigned long flags;
spin_lock_irqsave(&subpriv->intr.spinlock, flags);
@@ -677,6 +472,7 @@ static int
pcmuio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
unsigned int trignum)
{
+ struct pcmuio_subdev_private *subpriv = s->private;
unsigned long flags;
int event = 0;
@@ -701,6 +497,7 @@ pcmuio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
*/
static int pcmuio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
+ struct pcmuio_subdev_private *subpriv = s->private;
struct comedi_cmd *cmd = &s->async->cmd;
unsigned long flags;
int event = 0;
@@ -797,17 +594,18 @@ static int pcmuio_cmdtest(struct comedi_device *dev,
static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
const struct pcmuio_board *board = comedi_board(dev);
- struct pcmuio_private *devpriv;
struct comedi_subdevice *s;
- int sdev_no, chans_left, n_subdevs, port, asic, thisasic_chanct = 0;
- unsigned int irq[MAX_ASICS];
+ struct pcmuio_private *devpriv;
+ struct pcmuio_subdev_private *subpriv;
+ int sdev_no, n_subdevs, asic;
+ unsigned int irq[PCMUIO_MAX_ASICS];
int ret;
irq[0] = it->options[1];
irq[1] = it->options[2];
ret = comedi_request_region(dev, it->options[0],
- board->num_asics * ASIC_IOSIZE);
+ board->num_asics * PCMUIO_ASIC_IOSIZE);
if (ret)
return ret;
@@ -816,20 +614,11 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return -ENOMEM;
dev->private = devpriv;
- for (asic = 0; asic < MAX_ASICS; ++asic) {
- devpriv->asics[asic].num = asic;
- devpriv->asics[asic].iobase = dev->iobase + asic * ASIC_IOSIZE;
- devpriv->asics[asic].irq = 0; /* this gets actually set at the end of
- this function when we
- request_irqs */
+ for (asic = 0; asic < PCMUIO_MAX_ASICS; ++asic)
spin_lock_init(&devpriv->asics[asic].spinlock);
- }
- chans_left = CHANS_PER_ASIC * board->num_asics;
- n_subdevs = CALC_N_SUBDEVS(chans_left);
- devpriv->sprivs = kcalloc(n_subdevs,
- sizeof(struct pcmuio_subdev_private),
- GFP_KERNEL);
+ n_subdevs = board->num_asics * 2;
+ devpriv->sprivs = kcalloc(n_subdevs, sizeof(*subpriv), GFP_KERNEL);
if (!devpriv->sprivs)
return -ENOMEM;
@@ -837,74 +626,40 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret)
return ret;
- port = 0;
- asic = 0;
for (sdev_no = 0; sdev_no < (int)dev->n_subdevices; ++sdev_no) {
- int byte_no;
-
s = &dev->subdevices[sdev_no];
- s->private = &devpriv->sprivs[sdev_no];
+ subpriv = &devpriv->sprivs[sdev_no];
+ s->private = subpriv;
s->maxdata = 1;
s->range_table = &range_digital;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->type = COMEDI_SUBD_DIO;
s->insn_bits = pcmuio_dio_insn_bits;
s->insn_config = pcmuio_dio_insn_config;
- s->n_chan = min(chans_left, MAX_CHANS_PER_SUBDEV);
- subpriv->intr.asic = -1;
- subpriv->intr.first_chan = -1;
- subpriv->intr.asic_chan = -1;
- subpriv->intr.num_asic_chans = -1;
- subpriv->intr.active = 0;
- s->len_chanlist = 1;
-
- /* save the ioport address for each 'port' of 8 channels in the
- subdevice */
- for (byte_no = 0; byte_no < PORTS_PER_SUBDEV; ++byte_no, ++port) {
- if (port >= PORTS_PER_ASIC) {
- port = 0;
- ++asic;
- thisasic_chanct = 0;
- }
- subpriv->iobases[byte_no] =
- devpriv->asics[asic].iobase + port;
-
- if (thisasic_chanct <
- CHANS_PER_PORT * INTR_PORTS_PER_ASIC
- && subpriv->intr.asic < 0) {
- /* this is an interrupt subdevice, so setup the struct */
- subpriv->intr.asic = asic;
- subpriv->intr.active = 0;
- subpriv->intr.stop_count = 0;
- subpriv->intr.first_chan = byte_no * 8;
- subpriv->intr.asic_chan = thisasic_chanct;
- subpriv->intr.num_asic_chans =
- s->n_chan - subpriv->intr.first_chan;
- dev->read_subdev = s;
- s->subdev_flags |= SDF_CMD_READ;
- s->cancel = pcmuio_cancel;
- s->do_cmd = pcmuio_cmd;
- s->do_cmdtest = pcmuio_cmdtest;
- s->len_chanlist = subpriv->intr.num_asic_chans;
- }
- thisasic_chanct += CHANS_PER_PORT;
+ s->n_chan = 24;
+
+ /* subdevices 0 and 2 suppport interrupts */
+ if ((sdev_no % 2) == 0) {
+ /* setup the interrupt subdevice */
+ subpriv->intr.asic = sdev_no / 2;
+ dev->read_subdev = s;
+ s->subdev_flags |= SDF_CMD_READ;
+ s->cancel = pcmuio_cancel;
+ s->do_cmd = pcmuio_cmd;
+ s->do_cmdtest = pcmuio_cmdtest;
+ s->len_chanlist = s->n_chan;
+ } else {
+ subpriv->intr.asic = -1;
+ s->len_chanlist = 1;
}
spin_lock_init(&subpriv->intr.spinlock);
-
- chans_left -= s->n_chan;
-
- if (!chans_left) {
- asic = 0; /* reset the asic to our first asic, to do intr subdevs */
- port = 0;
- }
-
}
- init_asics(dev); /* clear out all the registers, basically */
+ pcmuio_reset(dev);
- for (asic = 0; irq[0] && asic < MAX_ASICS; ++asic) {
+ for (asic = 0; irq[0] && asic < PCMUIO_MAX_ASICS; ++asic) {
if (irq[asic]
- && request_irq(irq[asic], interrupt_pcmuio,
+ && request_irq(irq[asic], pcmuio_interrupt,
IRQF_SHARED, board->name, dev)) {
int i;
/* unroll the allocated irqs.. */
@@ -917,17 +672,7 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
devpriv->asics[asic].irq = irq[asic];
}
- if (irq[0]) {
- dev_dbg(dev->class_dev, "irq: %u\n", irq[0]);
- if (irq[1] && board->num_asics == 2)
- dev_dbg(dev->class_dev, "second ASIC irq: %u\n",
- irq[1]);
- } else {
- dev_dbg(dev->class_dev, "(IRQ mode disabled)\n");
- }
-
-
- return 1;
+ return 0;
}
static void pcmuio_detach(struct comedi_device *dev)
@@ -935,7 +680,7 @@ static void pcmuio_detach(struct comedi_device *dev)
struct pcmuio_private *devpriv = dev->private;
int i;
- for (i = 0; i < MAX_ASICS; ++i) {
+ for (i = 0; i < PCMUIO_MAX_ASICS; ++i) {
if (devpriv->asics[i].irq)
free_irq(devpriv->asics[i].irq, dev);
}
@@ -944,18 +689,6 @@ static void pcmuio_detach(struct comedi_device *dev)
comedi_legacy_detach(dev);
}
-static const struct pcmuio_board pcmuio_boards[] = {
- {
- .name = "pcmuio48",
- .num_asics = 1,
- .num_ports = 6,
- }, {
- .name = "pcmuio96",
- .num_asics = 2,
- .num_ports = 12,
- },
-};
-
static struct comedi_driver pcmuio_driver = {
.driver_name = "pcmuio",
.module = THIS_MODULE,
diff --git a/drivers/staging/comedi/drivers/plx9052.h b/drivers/staging/comedi/drivers/plx9052.h
index ff76fbb4b3ef..fbcf25069807 100644
--- a/drivers/staging/comedi/drivers/plx9052.h
+++ b/drivers/staging/comedi/drivers/plx9052.h
@@ -16,11 +16,6 @@
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.
-
*/
#ifndef _PLX9052_H_
diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c
index b55a16baeb14..005fbefae295 100644
--- a/drivers/staging/comedi/drivers/poc.c
+++ b/drivers/staging/comedi/drivers/poc.c
@@ -13,25 +13,18 @@
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: poc
Description: Generic driver for very simple devices
Author: ds
-Devices: [Keithley Metrabyte] DAC-02 (dac02), [Advantech] PCL-733 (pcl733),
- PCL-734 (pcl734)
+Devices: [Keithley Metrabyte] DAC-02 (dac02)
Updated: Sat, 16 Mar 2002 17:34:48 -0800
Status: unknown
This driver is indended to support very simple ISA-based devices,
including:
dac02 - Keithley DAC-02 analog output board
- pcl733 - Advantech PCL-733
- pcl734 - Advantech PCL-734
Configuration options:
[0] - I/O port base
@@ -101,39 +94,6 @@ static int dac02_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
return 1;
}
-static int pcl733_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- data[1] = inb(dev->iobase + 0);
- data[1] |= (inb(dev->iobase + 1) << 8);
- data[1] |= (inb(dev->iobase + 2) << 16);
- data[1] |= (inb(dev->iobase + 3) << 24);
-
- return insn->n;
-}
-
-static int pcl734_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
- if ((data[0] >> 0) & 0xff)
- outb((s->state >> 0) & 0xff, dev->iobase + 0);
- if ((data[0] >> 8) & 0xff)
- outb((s->state >> 8) & 0xff, dev->iobase + 1);
- if ((data[0] >> 16) & 0xff)
- outb((s->state >> 16) & 0xff, dev->iobase + 2);
- if ((data[0] >> 24) & 0xff)
- outb((s->state >> 24) & 0xff, dev->iobase + 3);
- }
- data[1] = s->state;
-
- return insn->n;
-}
-
static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
const struct boarddef_struct *board = comedi_board(dev);
@@ -180,22 +140,6 @@ static const struct boarddef_struct boards[] = {
.winsn = dac02_ao_winsn,
.rinsn = readback_insn,
.range = &range_unknown,
- }, {
- .name = "pcl733",
- .iosize = 4,
- .type = COMEDI_SUBD_DI,
- .n_chan = 32,
- .n_bits = 1,
- .insnbits = pcl733_insn_bits,
- .range = &range_digital,
- }, {
- .name = "pcl734",
- .iosize = 4,
- .type = COMEDI_SUBD_DO,
- .n_chan = 32,
- .n_bits = 1,
- .insnbits = pcl734_insn_bits,
- .range = &range_digital,
},
};
diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
index 30a17284fac9..9b93a1fc4a59 100644
--- a/drivers/staging/comedi/drivers/rtd520.c
+++ b/drivers/staging/comedi/drivers/rtd520.c
@@ -14,10 +14,6 @@
* 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.
*/
/*
diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
index f4163fd35a00..f698c7fc5726 100644
--- a/drivers/staging/comedi/drivers/rti800.c
+++ b/drivers/staging/comedi/drivers/rti800.c
@@ -14,10 +14,6 @@
* 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.
*/
/*
diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c
index 46dbbe6cdd76..9e7445055482 100644
--- a/drivers/staging/comedi/drivers/rti802.c
+++ b/drivers/staging/comedi/drivers/rti802.c
@@ -14,11 +14,6 @@
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: rti802
diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
index d240ce87bd68..e1587e58a732 100644
--- a/drivers/staging/comedi/drivers/s526.c
+++ b/drivers/staging/comedi/drivers/s526.c
@@ -14,11 +14,6 @@
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: s526
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index 0cf4b3d1279a..48c4b70b736a 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -17,11 +17,6 @@
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.
-
*/
/*
diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h
index 99cd57b092ea..d2756b83b62d 100644
--- a/drivers/staging/comedi/drivers/s626.h
+++ b/drivers/staging/comedi/drivers/s626.h
@@ -17,11 +17,6 @@
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.
-
*/
/*
diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
index 8900086374db..b4f5fe35b0fa 100644
--- a/drivers/staging/comedi/drivers/serial2002.c
+++ b/drivers/staging/comedi/drivers/serial2002.c
@@ -14,11 +14,6 @@
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.
-
*/
/*
diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
index dbc8c54d6da7..06aee302bbc2 100644
--- a/drivers/staging/comedi/drivers/skel.c
+++ b/drivers/staging/comedi/drivers/skel.c
@@ -14,11 +14,6 @@
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: skel
diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
index a76df092a57b..45c661cbdbb9 100644
--- a/drivers/staging/comedi/drivers/ssv_dnp.c
+++ b/drivers/staging/comedi/drivers/ssv_dnp.c
@@ -15,11 +15,6 @@
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: ssv_dnp
diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c
index 0c243477cbe5..c9201d821fbc 100644
--- a/drivers/staging/comedi/drivers/unioxx5.c
+++ b/drivers/staging/comedi/drivers/unioxx5.c
@@ -18,10 +18,6 @@
* 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. *
- * *
***************************************************************************/
/*
@@ -375,15 +371,13 @@ static int __unioxx5_subdev_init(struct comedi_device *dev,
int i, to, ndef_flag = 0;
int ret;
- usp = kzalloc(sizeof(*usp), GFP_KERNEL);
- if (usp == NULL)
+ usp = comedi_alloc_spriv(s, sizeof(*usp));
+ if (!usp)
return -ENOMEM;
ret = __comedi_request_region(dev, iobase, UNIOXX5_SIZE);
- if (ret) {
- kfree(usp);
+ if (ret)
return ret;
- }
usp->usp_iobase = iobase;
/* defining modules types */
@@ -417,7 +411,6 @@ static int __unioxx5_subdev_init(struct comedi_device *dev,
/* initial subdevice for digital or analog i/o */
s->type = COMEDI_SUBD_DIO;
- s->private = usp;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = UNIOXX5_NUM_OF_CHANS;
s->maxdata = 0xFFF;
@@ -478,15 +471,15 @@ static int unioxx5_attach(struct comedi_device *dev,
static void unioxx5_detach(struct comedi_device *dev)
{
+ struct comedi_subdevice *s;
+ struct unioxx5_subd_priv *spriv;
int i;
- struct comedi_subdevice *subdev;
- struct unioxx5_subd_priv *usp;
for (i = 0; i < dev->n_subdevices; i++) {
- subdev = &dev->subdevices[i];
- usp = subdev->private;
- release_region(usp->usp_iobase, UNIOXX5_SIZE);
- kfree(subdev->private);
+ s = &dev->subdevices[i];
+ spriv = s->private;
+ if (spriv && spriv->usp_iobase)
+ release_region(spriv->usp_iobase, UNIOXX5_SIZE);
}
}
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index 6f5da67e26cb..279e5bd493fa 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -11,11 +11,6 @@
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: usbdux
@@ -94,7 +89,6 @@ sampling rate. If you sample two channels you get 4kHz and so on.
#include <linux/usb.h>
#include <linux/fcntl.h>
#include <linux/compiler.h>
-#include <linux/firmware.h>
#include "../comedidev.h"
@@ -727,154 +721,82 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb)
}
}
-static int usbduxsub_start(struct usbduxsub *usbduxsub)
-{
- int errcode = 0;
- uint8_t *local_transfer_buffer;
-
- local_transfer_buffer = kmalloc(1, GFP_KERNEL);
- if (!local_transfer_buffer)
- return -ENOMEM;
-
- /* 7f92 to zero */
- *local_transfer_buffer = 0;
- errcode = usb_control_msg(usbduxsub->usbdev,
- /* create a pipe for a control transfer */
- usb_sndctrlpipe(usbduxsub->usbdev, 0),
- /* bRequest, "Firmware" */
- USBDUXSUB_FIRMWARE,
- /* bmRequestType */
- VENDOR_DIR_OUT,
- /* Value */
- USBDUXSUB_CPUCS,
- /* Index */
- 0x0000,
- /* address of the transfer buffer */
- local_transfer_buffer,
- /* Length */
- 1,
- /* Timeout */
- BULK_TIMEOUT);
- if (errcode < 0)
- dev_err(&usbduxsub->interface->dev,
- "comedi_: control msg failed (start)\n");
-
- kfree(local_transfer_buffer);
- return errcode;
-}
-
-static int usbduxsub_stop(struct usbduxsub *usbduxsub)
-{
- int errcode = 0;
- uint8_t *local_transfer_buffer;
-
- local_transfer_buffer = kmalloc(1, GFP_KERNEL);
- if (!local_transfer_buffer)
- return -ENOMEM;
-
- /* 7f92 to one */
- *local_transfer_buffer = 1;
- errcode = usb_control_msg(usbduxsub->usbdev,
- usb_sndctrlpipe(usbduxsub->usbdev, 0),
- /* bRequest, "Firmware" */
- USBDUXSUB_FIRMWARE,
- /* bmRequestType */
- VENDOR_DIR_OUT,
- /* Value */
- USBDUXSUB_CPUCS,
- /* Index */
- 0x0000, local_transfer_buffer,
- /* Length */
- 1,
- /* Timeout */
- BULK_TIMEOUT);
- if (errcode < 0)
- dev_err(&usbduxsub->interface->dev,
- "comedi_: control msg failed (stop)\n");
-
- kfree(local_transfer_buffer);
- return errcode;
-}
-
-static int usbduxsub_upload(struct usbduxsub *usbduxsub,
- uint8_t *local_transfer_buffer,
- unsigned int start_addr, unsigned int len)
-{
- int errcode;
-
- errcode = usb_control_msg(usbduxsub->usbdev,
- usb_sndctrlpipe(usbduxsub->usbdev, 0),
- /* brequest, firmware */
- USBDUXSUB_FIRMWARE,
- /* bmRequestType */
- VENDOR_DIR_OUT,
- /* value */
- start_addr,
- /* index */
- 0x0000,
- /* our local safe buffer */
- local_transfer_buffer,
- /* length */
- len,
- /* timeout */
- BULK_TIMEOUT);
- dev_dbg(&usbduxsub->interface->dev, "comedi_: result=%d\n", errcode);
- if (errcode < 0) {
- dev_err(&usbduxsub->interface->dev, "comedi_: upload failed\n");
- return errcode;
- }
- return 0;
-}
-
#define FIRMWARE_MAX_LEN 0x2000
-static int firmware_upload(struct usbduxsub *usbduxsub,
- const u8 *firmware_binary, int size_firmware)
+static int usbdux_firmware_upload(struct comedi_device *dev,
+ const u8 *data, size_t size,
+ unsigned long context)
{
+ struct usbduxsub *usbduxsub = dev->private;
+ struct usb_device *usb = usbduxsub->usbdev;
+ uint8_t *buf;
+ uint8_t *tmp;
int ret;
- uint8_t *fw_buf;
- if (!firmware_binary)
+ if (!data)
return 0;
- if (size_firmware > FIRMWARE_MAX_LEN) {
+ if (size > FIRMWARE_MAX_LEN) {
dev_err(&usbduxsub->interface->dev,
"usbdux firmware binary it too large for FX2.\n");
return -ENOMEM;
}
/* we generate a local buffer for the firmware */
- fw_buf = kmemdup(firmware_binary, size_firmware, GFP_KERNEL);
- if (!fw_buf) {
- dev_err(&usbduxsub->interface->dev,
- "comedi_: mem alloc for firmware failed\n");
+ buf = kmemdup(data, size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ /* we need a malloc'ed buffer for usb_control_msg() */
+ tmp = kmalloc(1, GFP_KERNEL);
+ if (!tmp) {
+ kfree(buf);
return -ENOMEM;
}
- ret = usbduxsub_stop(usbduxsub);
+ /* stop the current firmware on the device */
+ *tmp = 1; /* 7f92 to one */
+ ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
+ USBDUXSUB_FIRMWARE,
+ VENDOR_DIR_OUT,
+ USBDUXSUB_CPUCS, 0x0000,
+ tmp, 1,
+ BULK_TIMEOUT);
if (ret < 0) {
dev_err(&usbduxsub->interface->dev,
"comedi_: can not stop firmware\n");
- kfree(fw_buf);
- return ret;
+ goto done;
}
- ret = usbduxsub_upload(usbduxsub, fw_buf, 0, size_firmware);
+ /* upload the new firmware to the device */
+ ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
+ USBDUXSUB_FIRMWARE,
+ VENDOR_DIR_OUT,
+ 0, 0x0000,
+ buf, size,
+ BULK_TIMEOUT);
if (ret < 0) {
dev_err(&usbduxsub->interface->dev,
"comedi_: firmware upload failed\n");
- kfree(fw_buf);
- return ret;
+ goto done;
}
- ret = usbduxsub_start(usbduxsub);
- if (ret < 0) {
+
+ /* start the new firmware on the device */
+ *tmp = 0; /* 7f92 to zero */
+ ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
+ USBDUXSUB_FIRMWARE,
+ VENDOR_DIR_OUT,
+ USBDUXSUB_CPUCS, 0x0000,
+ tmp, 1,
+ BULK_TIMEOUT);
+ if (ret < 0)
dev_err(&usbduxsub->interface->dev,
"comedi_: can not start firmware\n");
- kfree(fw_buf);
- return ret;
- }
- kfree(fw_buf);
- return 0;
+
+done:
+ kfree(tmp);
+ kfree(buf);
+ return ret;
}
static int usbduxsub_submit_inurbs(struct usbduxsub *usbduxsub)
@@ -2328,13 +2250,21 @@ static int usbdux_auto_attach(struct comedi_device *dev,
unsigned long context_unused)
{
struct usb_interface *uinterf = comedi_to_usb_interface(dev);
+ struct usbduxsub *this_usbduxsub = usb_get_intfdata(uinterf);
+ struct usb_device *usb = usbduxsub->usbdev;
int ret;
- struct usbduxsub *this_usbduxsub;
+
+ dev->private = this_usbduxsub; /* This is temporary... */
+ ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE,
+ usbdux_firmware_upload, 0);
+ if (ret < 0) {
+ dev->private = NULL;
+ return ret;
+ }
dev->private = NULL;
down(&start_stop_sem);
- this_usbduxsub = usb_get_intfdata(uinterf);
if (!this_usbduxsub || !this_usbduxsub->probed) {
dev_err(dev->class_dev,
"usbdux: error: auto_attach failed, not connected\n");
@@ -2369,35 +2299,6 @@ static struct comedi_driver usbdux_driver = {
.detach = usbdux_detach,
};
-static void usbdux_firmware_request_complete_handler(const struct firmware *fw,
- void *context)
-{
- struct usbduxsub *usbduxsub_tmp = context;
- struct usb_interface *uinterf = usbduxsub_tmp->interface;
- int ret;
-
- if (fw == NULL) {
- dev_err(&uinterf->dev,
- "Firmware complete handler without firmware!\n");
- return;
- }
-
- /*
- * we need to upload the firmware here because fw will be
- * freed once we've left this function
- */
- ret = firmware_upload(usbduxsub_tmp, fw->data, fw->size);
-
- if (ret) {
- dev_err(&uinterf->dev,
- "Could not upload firmware (err=%d)\n", ret);
- goto out;
- }
- comedi_usb_auto_config(uinterf, &usbdux_driver, 0);
- out:
- release_firmware(fw);
-}
-
static int usbdux_usb_probe(struct usb_interface *uinterf,
const struct usb_device_id *id)
{
@@ -2405,7 +2306,6 @@ static int usbdux_usb_probe(struct usb_interface *uinterf,
struct device *dev = &uinterf->dev;
int i;
int index;
- int ret;
dev_dbg(dev, "comedi_: usbdux_: "
"finding a free structure for the usb-device\n");
@@ -2622,23 +2522,7 @@ static int usbdux_usb_probe(struct usb_interface *uinterf,
usbduxsub[index].probed = 1;
up(&start_stop_sem);
- ret = request_firmware_nowait(THIS_MODULE,
- FW_ACTION_HOTPLUG,
- FIRMWARE,
- &udev->dev,
- GFP_KERNEL,
- usbduxsub + index,
- usbdux_firmware_request_complete_handler);
-
- if (ret) {
- dev_err(dev, "Could not load firmware (err=%d)\n", ret);
- return ret;
- }
-
- dev_info(dev, "comedi_: usbdux%d "
- "has been successfully initialised.\n", index);
- /* success */
- return 0;
+ return comedi_usb_auto_config(uinterf, &usbdux_driver, 0);
}
static void usbdux_usb_disconnect(struct usb_interface *intf)
diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
index 7f95af33085d..27898c44e543 100644
--- a/drivers/staging/comedi/drivers/usbduxfast.c
+++ b/drivers/staging/comedi/drivers/usbduxfast.c
@@ -10,10 +10,6 @@
* 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.
*/
/*
@@ -40,7 +36,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
-#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -60,6 +55,7 @@
* constants for "firmware" upload and download
*/
#define FIRMWARE "usbduxfast_firmware.bin"
+#define FIRMWARE_MAX_LEN 0x2000
#define USBDUXFASTSUB_FIRMWARE 0xA0
#define VENDOR_DIR_IN 0xC0
#define VENDOR_DIR_OUT 0x40
@@ -112,7 +108,7 @@
/*
* size of the buffer for the dux commands in bytes
*/
-#define SIZEOFDUXBUFFER 256
+#define SIZEOFDUXBUF 256
/*
* number of in-URBs which receive the data: min=5
@@ -120,16 +116,6 @@
#define NUMOFINBUFFERSHIGH 10
/*
- * total number of usbduxfast devices
- */
-#define NUMUSBDUXFAST 16
-
-/*
- * analogue in subdevice
- */
-#define SUBDEV_AD 0
-
-/*
* min delay steps for more than one channel
* basically when the mux gives up ;-)
*
@@ -161,143 +147,83 @@ static const struct comedi_lrange range_usbduxfast_ai_range = {
* this is the structure which holds all the data of this driver
* one sub device just now: A/D
*/
-struct usbduxfastsub_s {
- int attached; /* is attached? */
- int probed; /* is it associated with a subdevice? */
- struct usb_device *usbdev; /* pointer to the usb-device */
- struct urb *urbIn; /* BULK-transfer handling: urb */
- int8_t *transfer_buffer;
- int16_t *insnBuffer; /* input buffer for single insn */
- int ifnum; /* interface number */
- struct usb_interface *interface; /* interface structure */
- /* comedi device for the interrupt context */
- struct comedi_device *comedidev;
+struct usbduxfast_private {
+ struct urb *urb; /* BULK-transfer handling: urb */
+ uint8_t *duxbuf;
+ int8_t *inbuf;
short int ai_cmd_running; /* asynchronous command is running */
short int ai_continous; /* continous acquisition */
long int ai_sample_count; /* number of samples to acquire */
- uint8_t *dux_commands; /* commands */
int ignore; /* counter which ignores the first
buffers */
struct semaphore sem;
};
/*
- * The pointer to the private usb-data of the driver
- * is also the private data for the comedi-device.
- * This has to be global as the usb subsystem needs
- * global variables. The other reason is that this
- * structure must be there _before_ any comedi
- * command is issued. The usb subsystem must be
- * initialised before comedi can access it.
- */
-static struct usbduxfastsub_s usbduxfastsub[NUMUSBDUXFAST];
-
-static DEFINE_SEMAPHORE(start_stop_sem);
-
-/*
* bulk transfers to usbduxfast
*/
#define SENDADCOMMANDS 0
#define SENDINITEP6 1
-static int send_dux_commands(struct usbduxfastsub_s *udfs, int cmd_type)
+static int usbduxfast_send_cmd(struct comedi_device *dev, int cmd_type)
{
- int tmp, nsent;
-
- udfs->dux_commands[0] = cmd_type;
-
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi%d: usbduxfast: dux_commands: ",
- udfs->comedidev->minor);
- for (tmp = 0; tmp < SIZEOFDUXBUFFER; tmp++)
- printk(" %02x", udfs->dux_commands[tmp]);
- printk("\n");
-#endif
-
- tmp = usb_bulk_msg(udfs->usbdev,
- usb_sndbulkpipe(udfs->usbdev, CHANNELLISTEP),
- udfs->dux_commands, SIZEOFDUXBUFFER, &nsent, 10000);
- if (tmp < 0)
- dev_err(&udfs->interface->dev,
- "could not transmit dux_commands to the usb-device, err=%d\n",
- tmp);
- return tmp;
+ struct usb_device *usb = comedi_to_usb_dev(dev);
+ struct usbduxfast_private *devpriv = dev->private;
+ int nsent;
+ int ret;
+
+ devpriv->duxbuf[0] = cmd_type;
+
+ ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, CHANNELLISTEP),
+ devpriv->duxbuf, SIZEOFDUXBUF,
+ &nsent, 10000);
+ if (ret < 0)
+ dev_err(dev->class_dev,
+ "could not transmit command to the usb-device, err=%d\n",
+ ret);
+ return ret;
}
-/*
- * Stops the data acquision.
- * It should be safe to call this function from any context.
- */
-static int usbduxfastsub_unlink_InURBs(struct usbduxfastsub_s *udfs)
+static void usbduxfast_cmd_data(struct comedi_device *dev, int index,
+ uint8_t len, uint8_t op, uint8_t out,
+ uint8_t log)
{
- int j = 0;
- int err = 0;
+ struct usbduxfast_private *devpriv = dev->private;
- if (udfs && udfs->urbIn) {
- udfs->ai_cmd_running = 0;
- /* waits until a running transfer is over */
- usb_kill_urb(udfs->urbIn);
- j = 0;
- }
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi: usbduxfast: unlinked InURB: res=%d\n", j);
-#endif
- return err;
+ /* Set the GPIF bytes, the first byte is the command byte */
+ devpriv->duxbuf[1 + 0x00 + index] = len;
+ devpriv->duxbuf[1 + 0x08 + index] = op;
+ devpriv->duxbuf[1 + 0x10 + index] = out;
+ devpriv->duxbuf[1 + 0x18 + index] = log;
}
-/*
- * This will stop a running acquisition operation.
- * Is called from within this driver from both the
- * interrupt context and from comedi.
- */
-static int usbduxfast_ai_stop(struct usbduxfastsub_s *udfs, int do_unlink)
+static int usbduxfast_ai_stop(struct comedi_device *dev, int do_unlink)
{
- int ret = 0;
+ struct usbduxfast_private *devpriv = dev->private;
- if (!udfs) {
- pr_err("%s: udfs=NULL!\n", __func__);
- return -EFAULT;
- }
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi: usbduxfast_ai_stop\n");
-#endif
+ /* stop aquistion */
+ devpriv->ai_cmd_running = 0;
- udfs->ai_cmd_running = 0;
-
- if (do_unlink)
- /* stop aquistion */
- ret = usbduxfastsub_unlink_InURBs(udfs);
+ if (do_unlink && devpriv->urb) {
+ /* kill the running transfer */
+ usb_kill_urb(devpriv->urb);
+ }
- return ret;
+ return 0;
}
-/*
- * This will cancel a running acquisition operation.
- * This is called by comedi but never from inside the driver.
- */
static int usbduxfast_ai_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- struct usbduxfastsub_s *udfs;
+ struct usbduxfast_private *devpriv = dev->private;
int ret;
- /* force unlink of all urbs */
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi: usbduxfast_ai_cancel\n");
-#endif
- udfs = dev->private;
- if (!udfs) {
- dev_err(dev->class_dev, "%s: udfs=NULL\n", __func__);
+ if (!devpriv)
return -EFAULT;
- }
- down(&udfs->sem);
- if (!udfs->probed) {
- up(&udfs->sem);
- return -ENODEV;
- }
- /* unlink */
- ret = usbduxfast_ai_stop(udfs, 1);
- up(&udfs->sem);
+
+ down(&devpriv->sem);
+ ret = usbduxfast_ai_stop(dev, 1);
+ up(&devpriv->sem);
return ret;
}
@@ -306,32 +232,17 @@ static int usbduxfast_ai_cancel(struct comedi_device *dev,
* analogue IN
* interrupt service routine
*/
-static void usbduxfastsub_ai_Irq(struct urb *urb)
+static void usbduxfast_ai_interrupt(struct urb *urb)
{
+ struct comedi_device *dev = urb->context;
+ struct comedi_subdevice *s = dev->read_subdev;
+ struct comedi_async *async = s->async;
+ struct usb_device *usb = comedi_to_usb_dev(dev);
+ struct usbduxfast_private *devpriv = dev->private;
int n, err;
- struct usbduxfastsub_s *udfs;
- struct comedi_device *this_comedidev;
- struct comedi_subdevice *s;
- /* sanity checks - is the urb there? */
- if (!urb) {
- pr_err("ao int-handler called with urb=NULL!\n");
- return;
- }
- /* the context variable points to the subdevice */
- this_comedidev = urb->context;
- if (!this_comedidev) {
- pr_err("urb context is a NULL pointer!\n");
- return;
- }
- /* the private structure of the subdevice is usbduxfastsub_s */
- udfs = this_comedidev->private;
- if (!udfs) {
- pr_err("private of comedi subdev is a NULL pointer!\n");
- return;
- }
/* are we running a command? */
- if (unlikely(!udfs->ai_cmd_running)) {
+ if (unlikely(!devpriv->ai_cmd_running)) {
/*
* not running a command
* do not continue execution if no asynchronous command
@@ -340,13 +251,6 @@ static void usbduxfastsub_ai_Irq(struct urb *urb)
return;
}
- if (unlikely(!udfs->attached)) {
- /* no comedi device there */
- return;
- }
- /* subdevice which is the AD converter */
- s = &this_comedidev->subdevices[SUBDEV_AD];
-
/* first we test if something unusual has just happened */
switch (urb->status) {
case 0:
@@ -361,189 +265,93 @@ static void usbduxfastsub_ai_Irq(struct urb *urb)
case -ESHUTDOWN:
case -ECONNABORTED:
/* tell this comedi */
- s->async->events |= COMEDI_CB_EOA;
- s->async->events |= COMEDI_CB_ERROR;
- comedi_event(udfs->comedidev, s);
+ async->events |= COMEDI_CB_EOA;
+ async->events |= COMEDI_CB_ERROR;
+ comedi_event(dev, s);
/* stop the transfer w/o unlink */
- usbduxfast_ai_stop(udfs, 0);
+ usbduxfast_ai_stop(dev, 0);
return;
default:
pr_err("non-zero urb status received in ai intr context: %d\n",
urb->status);
- s->async->events |= COMEDI_CB_EOA;
- s->async->events |= COMEDI_CB_ERROR;
- comedi_event(udfs->comedidev, s);
- usbduxfast_ai_stop(udfs, 0);
+ async->events |= COMEDI_CB_EOA;
+ async->events |= COMEDI_CB_ERROR;
+ comedi_event(dev, s);
+ usbduxfast_ai_stop(dev, 0);
return;
}
- if (!udfs->ignore) {
- if (!udfs->ai_continous) {
+ if (!devpriv->ignore) {
+ if (!devpriv->ai_continous) {
/* not continuous, fixed number of samples */
n = urb->actual_length / sizeof(uint16_t);
- if (unlikely(udfs->ai_sample_count < n)) {
- /*
- * we have send only a fraction of the bytes
- * received
- */
+ if (unlikely(devpriv->ai_sample_count < n)) {
+ unsigned int num_bytes;
+
+ /* partial sample received */
+ num_bytes = devpriv->ai_sample_count *
+ sizeof(uint16_t);
cfc_write_array_to_buffer(s,
urb->transfer_buffer,
- udfs->ai_sample_count
- * sizeof(uint16_t));
- usbduxfast_ai_stop(udfs, 0);
+ num_bytes);
+ usbduxfast_ai_stop(dev, 0);
/* tell comedi that the acquistion is over */
- s->async->events |= COMEDI_CB_EOA;
- comedi_event(udfs->comedidev, s);
+ async->events |= COMEDI_CB_EOA;
+ comedi_event(dev, s);
return;
}
- udfs->ai_sample_count -= n;
+ devpriv->ai_sample_count -= n;
}
/* write the full buffer to comedi */
err = cfc_write_array_to_buffer(s, urb->transfer_buffer,
urb->actual_length);
if (unlikely(err == 0)) {
/* buffer overflow */
- usbduxfast_ai_stop(udfs, 0);
+ usbduxfast_ai_stop(dev, 0);
return;
}
/* tell comedi that data is there */
- comedi_event(udfs->comedidev, s);
-
+ comedi_event(dev, s);
} else {
/* ignore this packet */
- udfs->ignore--;
+ devpriv->ignore--;
}
/*
* command is still running
* resubmit urb for BULK transfer
*/
- urb->dev = udfs->usbdev;
+ urb->dev = usb;
urb->status = 0;
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err < 0) {
- dev_err(&urb->dev->dev,
+ dev_err(dev->class_dev,
"urb resubm failed: %d", err);
- s->async->events |= COMEDI_CB_EOA;
- s->async->events |= COMEDI_CB_ERROR;
- comedi_event(udfs->comedidev, s);
- usbduxfast_ai_stop(udfs, 0);
- }
-}
-
-static int usbduxfastsub_start(struct usbduxfastsub_s *udfs)
-{
- int ret;
- unsigned char *local_transfer_buffer;
-
- local_transfer_buffer = kmalloc(1, GFP_KERNEL);
- if (!local_transfer_buffer)
- return -ENOMEM;
-
- /* 7f92 to zero */
- *local_transfer_buffer = 0;
- /* bRequest, "Firmware" */
- ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0),
- USBDUXFASTSUB_FIRMWARE,
- VENDOR_DIR_OUT, /* bmRequestType */
- USBDUXFASTSUB_CPUCS, /* Value */
- 0x0000, /* Index */
- /* address of the transfer buffer */
- local_transfer_buffer,
- 1, /* Length */
- EZTIMEOUT); /* Timeout */
- if (ret < 0)
- dev_err(&udfs->interface->dev,
- "control msg failed (start)\n");
-
- kfree(local_transfer_buffer);
- return ret;
-}
-
-static int usbduxfastsub_stop(struct usbduxfastsub_s *udfs)
-{
- int ret;
- unsigned char *local_transfer_buffer;
-
- local_transfer_buffer = kmalloc(1, GFP_KERNEL);
- if (!local_transfer_buffer)
- return -ENOMEM;
-
- /* 7f92 to one */
- *local_transfer_buffer = 1;
- /* bRequest, "Firmware" */
- ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0),
- USBDUXFASTSUB_FIRMWARE,
- VENDOR_DIR_OUT, /* bmRequestType */
- USBDUXFASTSUB_CPUCS, /* Value */
- 0x0000, /* Index */
- local_transfer_buffer, 1, /* Length */
- EZTIMEOUT); /* Timeout */
- if (ret < 0)
- dev_err(&udfs->interface->dev,
- "control msg failed (stop)\n");
-
- kfree(local_transfer_buffer);
- return ret;
-}
-
-static int usbduxfastsub_upload(struct usbduxfastsub_s *udfs,
- unsigned char *local_transfer_buffer,
- unsigned int startAddr, unsigned int len)
-{
- int ret;
-
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi: usbduxfast: uploading %d bytes", len);
- printk(KERN_DEBUG " to addr %d, first byte=%d.\n",
- startAddr, local_transfer_buffer[0]);
-#endif
- /* brequest, firmware */
- ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0),
- USBDUXFASTSUB_FIRMWARE,
- VENDOR_DIR_OUT, /* bmRequestType */
- startAddr, /* value */
- 0x0000, /* index */
- /* our local safe buffer */
- local_transfer_buffer,
- len, /* length */
- EZTIMEOUT); /* timeout */
-
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi_: usbduxfast: result=%d\n", ret);
-#endif
-
- if (ret < 0) {
- dev_err(&udfs->interface->dev, "uppload failed\n");
- return ret;
+ async->events |= COMEDI_CB_EOA;
+ async->events |= COMEDI_CB_ERROR;
+ comedi_event(dev, s);
+ usbduxfast_ai_stop(dev, 0);
}
-
- return 0;
}
-static int usbduxfastsub_submit_InURBs(struct usbduxfastsub_s *udfs)
+static int usbduxfast_submit_urb(struct comedi_device *dev)
{
+ struct usb_device *usb = comedi_to_usb_dev(dev);
+ struct usbduxfast_private *devpriv = dev->private;
int ret;
- if (!udfs)
+ if (!devpriv)
return -EFAULT;
- usb_fill_bulk_urb(udfs->urbIn, udfs->usbdev,
- usb_rcvbulkpipe(udfs->usbdev, BULKINEP),
- udfs->transfer_buffer,
- SIZEINBUF, usbduxfastsub_ai_Irq, udfs->comedidev);
-
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi%d: usbduxfast: submitting in-urb: "
- "0x%p,0x%p\n", udfs->comedidev->minor, udfs->urbIn->context,
- udfs->urbIn->dev);
-#endif
- ret = usb_submit_urb(udfs->urbIn, GFP_ATOMIC);
+ usb_fill_bulk_urb(devpriv->urb, usb, usb_rcvbulkpipe(usb, BULKINEP),
+ devpriv->inbuf, SIZEINBUF,
+ usbduxfast_ai_interrupt, dev);
+
+ ret = usb_submit_urb(devpriv->urb, GFP_ATOMIC);
if (ret) {
- dev_err(&udfs->interface->dev,
- "ai: usb_submit_urb error %d\n", ret);
+ dev_err(dev->class_dev, "usb_submit_urb error %d\n", ret);
return ret;
}
return 0;
@@ -553,13 +361,9 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{
- struct usbduxfastsub_s *udfs = dev->private;
int err = 0;
long int steps, tmp;
- int minSamplPer;
-
- if (!udfs->probed)
- return -ENODEV;
+ int min_sample_period;
/* Step 1 : check if triggers are trivially valid */
@@ -601,14 +405,14 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
if (cmd->chanlist_len == 1)
- minSamplPer = 1;
+ min_sample_period = 1;
else
- minSamplPer = MIN_SAMPLING_PERIOD;
+ min_sample_period = MIN_SAMPLING_PERIOD;
if (cmd->convert_src == TRIG_TIMER) {
steps = cmd->convert_arg * 30;
- if (steps < (minSamplPer * 1000))
- steps = minSamplPer * 1000;
+ if (steps < (min_sample_period * 1000))
+ steps = min_sample_period * 1000;
if (steps > (MAX_SAMPLING_PERIOD * 1000))
steps = MAX_SAMPLING_PERIOD * 1000;
@@ -650,80 +454,53 @@ static int usbduxfast_ai_inttrig(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned int trignum)
{
+ struct usbduxfast_private *devpriv = dev->private;
int ret;
- struct usbduxfastsub_s *udfs = dev->private;
- if (!udfs)
+ if (!devpriv)
return -EFAULT;
- down(&udfs->sem);
- if (!udfs->probed) {
- up(&udfs->sem);
- return -ENODEV;
- }
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi%d: usbduxfast_ai_inttrig\n", dev->minor);
-#endif
+ down(&devpriv->sem);
if (trignum != 0) {
- dev_err(dev->class_dev, "%s: invalid trignum\n", __func__);
- up(&udfs->sem);
+ dev_err(dev->class_dev, "invalid trignum\n");
+ up(&devpriv->sem);
return -EINVAL;
}
- if (!udfs->ai_cmd_running) {
- udfs->ai_cmd_running = 1;
- ret = usbduxfastsub_submit_InURBs(udfs);
+ if (!devpriv->ai_cmd_running) {
+ devpriv->ai_cmd_running = 1;
+ ret = usbduxfast_submit_urb(dev);
if (ret < 0) {
- dev_err(dev->class_dev,
- "%s: urbSubmit: err=%d\n", __func__, ret);
- udfs->ai_cmd_running = 0;
- up(&udfs->sem);
+ dev_err(dev->class_dev, "urbSubmit: err=%d\n", ret);
+ devpriv->ai_cmd_running = 0;
+ up(&devpriv->sem);
return ret;
}
s->async->inttrig = NULL;
} else {
- dev_err(dev->class_dev,
- "ai_inttrig but acqu is already running\n");
+ dev_err(dev->class_dev, "ai is already running\n");
}
- up(&udfs->sem);
+ up(&devpriv->sem);
return 1;
}
-/*
- * offsets for the GPIF bytes
- * the first byte is the command byte
- */
-#define LENBASE (1+0x00)
-#define OPBASE (1+0x08)
-#define OUTBASE (1+0x10)
-#define LOGBASE (1+0x18)
-
static int usbduxfast_ai_cmd(struct comedi_device *dev,
struct comedi_subdevice *s)
{
+ struct usbduxfast_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
unsigned int chan, gain, rngmask = 0xff;
int i, j, ret;
- struct usbduxfastsub_s *udfs;
int result;
long steps, steps_tmp;
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi%d: usbduxfast_ai_cmd\n", dev->minor);
-#endif
- udfs = dev->private;
- if (!udfs)
+ if (!devpriv)
return -EFAULT;
- down(&udfs->sem);
- if (!udfs->probed) {
- up(&udfs->sem);
- return -ENODEV;
- }
- if (udfs->ai_cmd_running) {
- dev_err(dev->class_dev,
- "ai_cmd not possible. Another ai_cmd is running.\n");
- up(&udfs->sem);
+ down(&devpriv->sem);
+ if (devpriv->ai_cmd_running) {
+ dev_err(dev->class_dev, "ai_cmd not possible\n");
+ up(&devpriv->sem);
return -EBUSY;
}
/* set current channel of the running acquisition to zero */
@@ -733,7 +510,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
* ignore the first buffers from the device if there
* is an error condition
*/
- udfs->ignore = PACKETS_TO_IGNORE;
+ devpriv->ignore = PACKETS_TO_IGNORE;
if (cmd->chanlist_len > 0) {
gain = CR_RANGE(cmd->chanlist[0]);
@@ -741,20 +518,19 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
chan = CR_CHAN(cmd->chanlist[i]);
if (chan != i) {
dev_err(dev->class_dev,
- "cmd is accepting only consecutive channels.\n");
- up(&udfs->sem);
+ "channels are not consecutive\n");
+ up(&devpriv->sem);
return -EINVAL;
}
if ((gain != CR_RANGE(cmd->chanlist[i]))
&& (cmd->chanlist_len > 3)) {
dev_err(dev->class_dev,
- "the gain must be the same for all channels.\n");
- up(&udfs->sem);
+ "gain must be the same for all channels\n");
+ up(&devpriv->sem);
return -EINVAL;
}
if (i >= NUMCHANNELS) {
- dev_err(dev->class_dev,
- "channel list too long\n");
+ dev_err(dev->class_dev, "chanlist too long\n");
break;
}
}
@@ -762,8 +538,8 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
steps = 0;
if (cmd->scan_begin_src == TRIG_TIMER) {
dev_err(dev->class_dev,
- "scan_begin_src==TRIG_TIMER not valid.\n");
- up(&udfs->sem);
+ "scan_begin_src==TRIG_TIMER not valid\n");
+ up(&devpriv->sem);
return -EINVAL;
}
if (cmd->convert_src == TRIG_TIMER)
@@ -771,27 +547,23 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
if ((steps < MIN_SAMPLING_PERIOD) && (cmd->chanlist_len != 1)) {
dev_err(dev->class_dev,
- "ai_cmd: steps=%ld, scan_begin_arg=%d. Not properly tested by cmdtest?\n",
+ "steps=%ld, scan_begin_arg=%d. Not properly tested by cmdtest?\n",
steps, cmd->scan_begin_arg);
- up(&udfs->sem);
+ up(&devpriv->sem);
return -EINVAL;
}
if (steps > MAX_SAMPLING_PERIOD) {
- dev_err(dev->class_dev, "ai_cmd: sampling rate too low.\n");
- up(&udfs->sem);
+ dev_err(dev->class_dev, "sampling rate too low\n");
+ up(&devpriv->sem);
return -EINVAL;
}
if ((cmd->start_src == TRIG_EXT) && (cmd->chanlist_len != 1)
&& (cmd->chanlist_len != 16)) {
dev_err(dev->class_dev,
- "ai_cmd: TRIG_EXT only with 1 or 16 channels possible.\n");
- up(&udfs->sem);
+ "TRIG_EXT only with 1 or 16 channels possible\n");
+ up(&devpriv->sem);
return -EINVAL;
}
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi%d: usbduxfast: steps=%ld, convert_arg=%u\n",
- dev->minor, steps, cmd->convert_arg);
-#endif
switch (cmd->chanlist_len) {
case 1:
@@ -812,17 +584,11 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
/* we loop here until ready has been set */
if (cmd->start_src == TRIG_EXT) {
/* branch back to state 0 */
- udfs->dux_commands[LENBASE + 0] = 0x01;
/* deceision state w/o data */
- udfs->dux_commands[OPBASE + 0] = 0x01;
- udfs->dux_commands[OUTBASE + 0] = 0xFF & rngmask;
/* RDY0 = 0 */
- udfs->dux_commands[LOGBASE + 0] = 0x00;
+ usbduxfast_cmd_data(dev, 0, 0x01, 0x01, rngmask, 0x00);
} else { /* we just proceed to state 1 */
- udfs->dux_commands[LENBASE + 0] = 1;
- udfs->dux_commands[OPBASE + 0] = 0;
- udfs->dux_commands[OUTBASE + 0] = 0xFF & rngmask;
- udfs->dux_commands[LOGBASE + 0] = 0;
+ usbduxfast_cmd_data(dev, 0, 0x01, 0x00, rngmask, 0x00);
}
if (steps < MIN_SAMPLING_PERIOD) {
@@ -835,33 +601,25 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
*/
/* branch back to state 1 */
- udfs->dux_commands[LENBASE + 1] = 0x89;
/* deceision state with data */
- udfs->dux_commands[OPBASE + 1] = 0x03;
- udfs->dux_commands[OUTBASE + 1] =
- 0xFF & rngmask;
/* doesn't matter */
- udfs->dux_commands[LOGBASE + 1] = 0xFF;
+ usbduxfast_cmd_data(dev, 1,
+ 0x89, 0x03, rngmask, 0xff);
} else {
/*
* we loop through two states: data and delay
* max rate is 15MHz
*/
- udfs->dux_commands[LENBASE + 1] = steps - 1;
/* data */
- udfs->dux_commands[OPBASE + 1] = 0x02;
- udfs->dux_commands[OUTBASE + 1] =
- 0xFF & rngmask;
/* doesn't matter */
- udfs->dux_commands[LOGBASE + 1] = 0;
+ usbduxfast_cmd_data(dev, 1, steps - 1,
+ 0x02, rngmask, 0x00);
+
/* branch back to state 1 */
- udfs->dux_commands[LENBASE + 2] = 0x09;
/* deceision state w/o data */
- udfs->dux_commands[OPBASE + 2] = 0x01;
- udfs->dux_commands[OUTBASE + 2] =
- 0xFF & rngmask;
/* doesn't matter */
- udfs->dux_commands[LOGBASE + 2] = 0xFF;
+ usbduxfast_cmd_data(dev, 2,
+ 0x09, 0x01, rngmask, 0xff);
}
} else {
/*
@@ -873,26 +631,20 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
steps = steps - 1;
/* do the first part of the delay */
- udfs->dux_commands[LENBASE + 1] = steps / 2;
- udfs->dux_commands[OPBASE + 1] = 0;
- udfs->dux_commands[OUTBASE + 1] = 0xFF & rngmask;
- udfs->dux_commands[LOGBASE + 1] = 0;
+ usbduxfast_cmd_data(dev, 1,
+ steps / 2, 0x00, rngmask, 0x00);
/* and the second part */
- udfs->dux_commands[LENBASE + 2] = steps - steps / 2;
- udfs->dux_commands[OPBASE + 2] = 0;
- udfs->dux_commands[OUTBASE + 2] = 0xFF & rngmask;
- udfs->dux_commands[LOGBASE + 2] = 0;
+ usbduxfast_cmd_data(dev, 2, steps - steps / 2,
+ 0x00, rngmask, 0x00);
/* get the data and branch back */
/* branch back to state 1 */
- udfs->dux_commands[LENBASE + 3] = 0x09;
/* deceision state w data */
- udfs->dux_commands[OPBASE + 3] = 0x03;
- udfs->dux_commands[OUTBASE + 3] = 0xFF & rngmask;
/* doesn't matter */
- udfs->dux_commands[LOGBASE + 3] = 0xFF;
+ usbduxfast_cmd_data(dev, 3,
+ 0x09, 0x03, rngmask, 0xff);
}
break;
@@ -907,11 +659,8 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
else
rngmask = 0xff;
- udfs->dux_commands[LENBASE + 0] = 1;
/* data */
- udfs->dux_commands[OPBASE + 0] = 0x02;
- udfs->dux_commands[OUTBASE + 0] = 0xFF & rngmask;
- udfs->dux_commands[LOGBASE + 0] = 0;
+ usbduxfast_cmd_data(dev, 0, 0x01, 0x02, rngmask, 0x00);
/* we have 1 state with duration 1: state 0 */
steps_tmp = steps - 1;
@@ -922,23 +671,16 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
rngmask = 0xff;
/* do the first part of the delay */
- udfs->dux_commands[LENBASE + 1] = steps_tmp / 2;
- udfs->dux_commands[OPBASE + 1] = 0;
/* count */
- udfs->dux_commands[OUTBASE + 1] = 0xFE & rngmask;
- udfs->dux_commands[LOGBASE + 1] = 0;
+ usbduxfast_cmd_data(dev, 1, steps_tmp / 2,
+ 0x00, 0xfe & rngmask, 0x00);
/* and the second part */
- udfs->dux_commands[LENBASE + 2] = steps_tmp - steps_tmp / 2;
- udfs->dux_commands[OPBASE + 2] = 0;
- udfs->dux_commands[OUTBASE + 2] = 0xFF & rngmask;
- udfs->dux_commands[LOGBASE + 2] = 0;
+ usbduxfast_cmd_data(dev, 2, steps_tmp - steps_tmp / 2,
+ 0x00, rngmask, 0x00);
- udfs->dux_commands[LENBASE + 3] = 1;
/* data */
- udfs->dux_commands[OPBASE + 3] = 0x02;
- udfs->dux_commands[OUTBASE + 3] = 0xFF & rngmask;
- udfs->dux_commands[LOGBASE + 3] = 0;
+ usbduxfast_cmd_data(dev, 3, 0x01, 0x02, rngmask, 0x00);
/*
* we have 2 states with duration 1: step 6 and
@@ -952,22 +694,15 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
rngmask = 0xff;
/* do the first part of the delay */
- udfs->dux_commands[LENBASE + 4] = steps_tmp / 2;
- udfs->dux_commands[OPBASE + 4] = 0;
/* reset */
- udfs->dux_commands[OUTBASE + 4] = (0xFF - 0x02) & rngmask;
- udfs->dux_commands[LOGBASE + 4] = 0;
+ usbduxfast_cmd_data(dev, 4, steps_tmp / 2,
+ 0x00, (0xff - 0x02) & rngmask, 0x00);
/* and the second part */
- udfs->dux_commands[LENBASE + 5] = steps_tmp - steps_tmp / 2;
- udfs->dux_commands[OPBASE + 5] = 0;
- udfs->dux_commands[OUTBASE + 5] = 0xFF & rngmask;
- udfs->dux_commands[LOGBASE + 5] = 0;
-
- udfs->dux_commands[LENBASE + 6] = 1;
- udfs->dux_commands[OPBASE + 6] = 0;
- udfs->dux_commands[OUTBASE + 6] = 0xFF & rngmask;
- udfs->dux_commands[LOGBASE + 6] = 0;
+ usbduxfast_cmd_data(dev, 5, steps_tmp - steps_tmp / 2,
+ 0x00, rngmask, 0x00);
+
+ usbduxfast_cmd_data(dev, 6, 0x01, 0x00, rngmask, 0x00);
break;
case 3:
@@ -975,6 +710,8 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
* three channels
*/
for (j = 0; j < 1; j++) {
+ int index = j * 2;
+
if (CR_RANGE(cmd->chanlist[j]) > 0)
rngmask = 0xff - 0x04;
else
@@ -983,12 +720,10 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
* commit data to the FIFO and do the first part
* of the delay
*/
- udfs->dux_commands[LENBASE + j * 2] = steps / 2;
/* data */
- udfs->dux_commands[OPBASE + j * 2] = 0x02;
/* no change */
- udfs->dux_commands[OUTBASE + j * 2] = 0xFF & rngmask;
- udfs->dux_commands[LOGBASE + j * 2] = 0;
+ usbduxfast_cmd_data(dev, index, steps / 2,
+ 0x02, rngmask, 0x00);
if (CR_RANGE(cmd->chanlist[j + 1]) > 0)
rngmask = 0xff - 0x04;
@@ -996,25 +731,19 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
rngmask = 0xff;
/* do the second part of the delay */
- udfs->dux_commands[LENBASE + j * 2 + 1] =
- steps - steps / 2;
/* no data */
- udfs->dux_commands[OPBASE + j * 2 + 1] = 0;
/* count */
- udfs->dux_commands[OUTBASE + j * 2 + 1] =
- 0xFE & rngmask;
- udfs->dux_commands[LOGBASE + j * 2 + 1] = 0;
+ usbduxfast_cmd_data(dev, index + 1, steps - steps / 2,
+ 0x00, 0xfe & rngmask, 0x00);
}
/* 2 steps with duration 1: the idele step and step 6: */
steps_tmp = steps - 2;
/* commit data to the FIFO and do the first part of the delay */
- udfs->dux_commands[LENBASE + 4] = steps_tmp / 2;
/* data */
- udfs->dux_commands[OPBASE + 4] = 0x02;
- udfs->dux_commands[OUTBASE + 4] = 0xFF & rngmask;
- udfs->dux_commands[LOGBASE + 4] = 0;
+ usbduxfast_cmd_data(dev, 4, steps_tmp / 2,
+ 0x02, rngmask, 0x00);
if (CR_RANGE(cmd->chanlist[0]) > 0)
rngmask = 0xff - 0x04;
@@ -1022,17 +751,12 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
rngmask = 0xff;
/* do the second part of the delay */
- udfs->dux_commands[LENBASE + 5] = steps_tmp - steps_tmp / 2;
/* no data */
- udfs->dux_commands[OPBASE + 5] = 0;
/* reset */
- udfs->dux_commands[OUTBASE + 5] = (0xFF - 0x02) & rngmask;
- udfs->dux_commands[LOGBASE + 5] = 0;
+ usbduxfast_cmd_data(dev, 5, steps_tmp - steps_tmp / 2,
+ 0x00, (0xff - 0x02) & rngmask, 0x00);
- udfs->dux_commands[LENBASE + 6] = 1;
- udfs->dux_commands[OPBASE + 6] = 0;
- udfs->dux_commands[OUTBASE + 6] = 0xFF & rngmask;
- udfs->dux_commands[LOGBASE + 6] = 0;
+ usbduxfast_cmd_data(dev, 6, 0x01, 0x00, rngmask, 0x00);
case 16:
if (CR_RANGE(cmd->chanlist[0]) > 0)
@@ -1046,101 +770,79 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
*/
/* branch back to state 0 */
- udfs->dux_commands[LENBASE + 0] = 0x01;
/* deceision state w/o data */
- udfs->dux_commands[OPBASE + 0] = 0x01;
/* reset */
- udfs->dux_commands[OUTBASE + 0] =
- (0xFF - 0x02) & rngmask;
/* RDY0 = 0 */
- udfs->dux_commands[LOGBASE + 0] = 0x00;
+ usbduxfast_cmd_data(dev, 0, 0x01, 0x01,
+ (0xff - 0x02) & rngmask, 0x00);
} else {
/*
* we just proceed to state 1
*/
/* 30us reset pulse */
- udfs->dux_commands[LENBASE + 0] = 255;
- udfs->dux_commands[OPBASE + 0] = 0;
/* reset */
- udfs->dux_commands[OUTBASE + 0] =
- (0xFF - 0x02) & rngmask;
- udfs->dux_commands[LOGBASE + 0] = 0;
+ usbduxfast_cmd_data(dev, 0, 0xff, 0x00,
+ (0xff - 0x02) & rngmask, 0x00);
}
/* commit data to the FIFO */
- udfs->dux_commands[LENBASE + 1] = 1;
/* data */
- udfs->dux_commands[OPBASE + 1] = 0x02;
- udfs->dux_commands[OUTBASE + 1] = 0xFF & rngmask;
- udfs->dux_commands[LOGBASE + 1] = 0;
+ usbduxfast_cmd_data(dev, 1, 0x01, 0x02, rngmask, 0x00);
/* we have 2 states with duration 1 */
steps = steps - 2;
/* do the first part of the delay */
- udfs->dux_commands[LENBASE + 2] = steps / 2;
- udfs->dux_commands[OPBASE + 2] = 0;
- udfs->dux_commands[OUTBASE + 2] = 0xFE & rngmask;
- udfs->dux_commands[LOGBASE + 2] = 0;
+ usbduxfast_cmd_data(dev, 2, steps / 2,
+ 0x00, 0xfe & rngmask, 0x00);
/* and the second part */
- udfs->dux_commands[LENBASE + 3] = steps - steps / 2;
- udfs->dux_commands[OPBASE + 3] = 0;
- udfs->dux_commands[OUTBASE + 3] = 0xFF & rngmask;
- udfs->dux_commands[LOGBASE + 3] = 0;
+ usbduxfast_cmd_data(dev, 3, steps - steps / 2,
+ 0x00, rngmask, 0x00);
/* branch back to state 1 */
- udfs->dux_commands[LENBASE + 4] = 0x09;
/* deceision state w/o data */
- udfs->dux_commands[OPBASE + 4] = 0x01;
- udfs->dux_commands[OUTBASE + 4] = 0xFF & rngmask;
/* doesn't matter */
- udfs->dux_commands[LOGBASE + 4] = 0xFF;
+ usbduxfast_cmd_data(dev, 4, 0x09, 0x01, rngmask, 0xff);
break;
default:
dev_err(dev->class_dev, "unsupported combination of channels\n");
- up(&udfs->sem);
+ up(&devpriv->sem);
return -EFAULT;
}
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi %d: sending commands to the usb device\n",
- dev->minor);
-#endif
/* 0 means that the AD commands are sent */
- result = send_dux_commands(udfs, SENDADCOMMANDS);
+ result = usbduxfast_send_cmd(dev, SENDADCOMMANDS);
if (result < 0) {
- dev_err(dev->class_dev,
- "adc command could not be submitted. Aborting...\n");
- up(&udfs->sem);
+ up(&devpriv->sem);
return result;
}
if (cmd->stop_src == TRIG_COUNT) {
- udfs->ai_sample_count = cmd->stop_arg * cmd->scan_end_arg;
- if (udfs->ai_sample_count < 1) {
+ devpriv->ai_sample_count = cmd->stop_arg * cmd->scan_end_arg;
+ if (devpriv->ai_sample_count < 1) {
dev_err(dev->class_dev,
- "(cmd->stop_arg)*(cmd->scan_end_arg)<1, aborting.\n");
- up(&udfs->sem);
+ "(cmd->stop_arg)*(cmd->scan_end_arg)<1, aborting\n");
+ up(&devpriv->sem);
return -EFAULT;
}
- udfs->ai_continous = 0;
+ devpriv->ai_continous = 0;
} else {
/* continous acquisition */
- udfs->ai_continous = 1;
- udfs->ai_sample_count = 0;
+ devpriv->ai_continous = 1;
+ devpriv->ai_sample_count = 0;
}
if ((cmd->start_src == TRIG_NOW) || (cmd->start_src == TRIG_EXT)) {
/* enable this acquisition operation */
- udfs->ai_cmd_running = 1;
- ret = usbduxfastsub_submit_InURBs(udfs);
+ devpriv->ai_cmd_running = 1;
+ ret = usbduxfast_submit_urb(dev);
if (ret < 0) {
- udfs->ai_cmd_running = 0;
+ devpriv->ai_cmd_running = 0;
/* fixme: unlink here?? */
- up(&udfs->sem);
+ up(&devpriv->sem);
return ret;
}
s->async->inttrig = NULL;
@@ -1152,7 +854,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
*/
s->async->inttrig = usbduxfast_ai_inttrig;
}
- up(&udfs->sem);
+ up(&devpriv->sem);
return 0;
}
@@ -1162,490 +864,283 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
*/
static int usbduxfast_ai_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
+ struct usb_device *usb = comedi_to_usb_dev(dev);
+ struct usbduxfast_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int range = CR_RANGE(insn->chanspec);
+ uint8_t rngmask = range ? (0xff - 0x04) : 0xff;
int i, j, n, actual_length;
- int chan, range, rngmask;
- int err;
- struct usbduxfastsub_s *udfs;
+ int ret;
- udfs = dev->private;
- if (!udfs) {
- dev_err(dev->class_dev, "%s: no usb dev.\n", __func__);
- return -ENODEV;
- }
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi%d: ai_insn_read, insn->n=%d, "
- "insn->subdev=%d\n", dev->minor, insn->n, insn->subdev);
-#endif
- down(&udfs->sem);
- if (!udfs->probed) {
- up(&udfs->sem);
- return -ENODEV;
- }
- if (udfs->ai_cmd_running) {
+ down(&devpriv->sem);
+
+ if (devpriv->ai_cmd_running) {
dev_err(dev->class_dev,
- "ai_insn_read not possible. Async Command is running.\n");
- up(&udfs->sem);
+ "ai_insn_read not possible, async cmd is running\n");
+ up(&devpriv->sem);
return -EBUSY;
}
- /* sample one channel */
- chan = CR_CHAN(insn->chanspec);
- range = CR_RANGE(insn->chanspec);
- /* set command for the first channel */
- if (range > 0)
- rngmask = 0xff - 0x04;
- else
- rngmask = 0xff;
+ /* set command for the first channel */
/* commit data to the FIFO */
- udfs->dux_commands[LENBASE + 0] = 1;
/* data */
- udfs->dux_commands[OPBASE + 0] = 0x02;
- udfs->dux_commands[OUTBASE + 0] = 0xFF & rngmask;
- udfs->dux_commands[LOGBASE + 0] = 0;
+ usbduxfast_cmd_data(dev, 0, 0x01, 0x02, rngmask, 0x00);
/* do the first part of the delay */
- udfs->dux_commands[LENBASE + 1] = 12;
- udfs->dux_commands[OPBASE + 1] = 0;
- udfs->dux_commands[OUTBASE + 1] = 0xFE & rngmask;
- udfs->dux_commands[LOGBASE + 1] = 0;
-
- udfs->dux_commands[LENBASE + 2] = 1;
- udfs->dux_commands[OPBASE + 2] = 0;
- udfs->dux_commands[OUTBASE + 2] = 0xFE & rngmask;
- udfs->dux_commands[LOGBASE + 2] = 0;
-
- udfs->dux_commands[LENBASE + 3] = 1;
- udfs->dux_commands[OPBASE + 3] = 0;
- udfs->dux_commands[OUTBASE + 3] = 0xFE & rngmask;
- udfs->dux_commands[LOGBASE + 3] = 0;
-
- udfs->dux_commands[LENBASE + 4] = 1;
- udfs->dux_commands[OPBASE + 4] = 0;
- udfs->dux_commands[OUTBASE + 4] = 0xFE & rngmask;
- udfs->dux_commands[LOGBASE + 4] = 0;
+ usbduxfast_cmd_data(dev, 1, 0x0c, 0x00, 0xfe & rngmask, 0x00);
+ usbduxfast_cmd_data(dev, 2, 0x01, 0x00, 0xfe & rngmask, 0x00);
+ usbduxfast_cmd_data(dev, 3, 0x01, 0x00, 0xfe & rngmask, 0x00);
+ usbduxfast_cmd_data(dev, 4, 0x01, 0x00, 0xfe & rngmask, 0x00);
/* second part */
- udfs->dux_commands[LENBASE + 5] = 12;
- udfs->dux_commands[OPBASE + 5] = 0;
- udfs->dux_commands[OUTBASE + 5] = 0xFF & rngmask;
- udfs->dux_commands[LOGBASE + 5] = 0;
-
- udfs->dux_commands[LENBASE + 6] = 1;
- udfs->dux_commands[OPBASE + 6] = 0;
- udfs->dux_commands[OUTBASE + 6] = 0xFF & rngmask;
- udfs->dux_commands[LOGBASE + 0] = 0;
-
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi %d: sending commands to the usb device\n",
- dev->minor);
-#endif
- /* 0 means that the AD commands are sent */
- err = send_dux_commands(udfs, SENDADCOMMANDS);
- if (err < 0) {
- dev_err(dev->class_dev,
- "adc command could not be submitted. Aborting...\n");
- up(&udfs->sem);
- return err;
+ usbduxfast_cmd_data(dev, 5, 0x0c, 0x00, rngmask, 0x00);
+ usbduxfast_cmd_data(dev, 6, 0x01, 0x00, rngmask, 0x00);
+
+ ret = usbduxfast_send_cmd(dev, SENDADCOMMANDS);
+ if (ret < 0) {
+ up(&devpriv->sem);
+ return ret;
}
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi%d: usbduxfast: submitting in-urb: "
- "0x%p,0x%p\n", udfs->comedidev->minor, udfs->urbIn->context,
- udfs->urbIn->dev);
-#endif
+
for (i = 0; i < PACKETS_TO_IGNORE; i++) {
- err = usb_bulk_msg(udfs->usbdev,
- usb_rcvbulkpipe(udfs->usbdev, BULKINEP),
- udfs->transfer_buffer, SIZEINBUF,
+ ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, BULKINEP),
+ devpriv->inbuf, SIZEINBUF,
&actual_length, 10000);
- if (err < 0) {
- dev_err(dev->class_dev, "insn timeout. No data.\n");
- up(&udfs->sem);
- return err;
+ if (ret < 0) {
+ dev_err(dev->class_dev, "insn timeout, no data\n");
+ up(&devpriv->sem);
+ return ret;
}
}
- /* data points */
+
for (i = 0; i < insn->n;) {
- err = usb_bulk_msg(udfs->usbdev,
- usb_rcvbulkpipe(udfs->usbdev, BULKINEP),
- udfs->transfer_buffer, SIZEINBUF,
+ ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, BULKINEP),
+ devpriv->inbuf, SIZEINBUF,
&actual_length, 10000);
- if (err < 0) {
- dev_err(dev->class_dev, "insn data error: %d\n", err);
- up(&udfs->sem);
- return err;
+ if (ret < 0) {
+ dev_err(dev->class_dev, "insn data error: %d\n", ret);
+ up(&devpriv->sem);
+ return ret;
}
n = actual_length / sizeof(uint16_t);
if ((n % 16) != 0) {
- dev_err(dev->class_dev, "insn data packet corrupted.\n");
- up(&udfs->sem);
+ dev_err(dev->class_dev, "insn data packet corrupted\n");
+ up(&devpriv->sem);
return -EINVAL;
}
for (j = chan; (j < n) && (i < insn->n); j = j + 16) {
- data[i] = ((uint16_t *) (udfs->transfer_buffer))[j];
+ data[i] = ((uint16_t *) (devpriv->inbuf))[j];
i++;
}
}
- up(&udfs->sem);
- return i;
-}
-
-#define FIRMWARE_MAX_LEN 0x2000
-
-static int firmwareUpload(struct usbduxfastsub_s *usbduxfastsub,
- const u8 *firmwareBinary, int sizeFirmware)
-{
- int ret;
- uint8_t *fwBuf;
-
- if (!firmwareBinary)
- return 0;
-
- if (sizeFirmware > FIRMWARE_MAX_LEN) {
- dev_err(&usbduxfastsub->interface->dev,
- "comedi_: usbduxfast firmware binary it too large for FX2.\n");
- return -ENOMEM;
- }
-
- /* we generate a local buffer for the firmware */
- fwBuf = kmemdup(firmwareBinary, sizeFirmware, GFP_KERNEL);
- if (!fwBuf) {
- dev_err(&usbduxfastsub->interface->dev,
- "comedi_: mem alloc for firmware failed\n");
- return -ENOMEM;
- }
-
- ret = usbduxfastsub_stop(usbduxfastsub);
- if (ret < 0) {
- dev_err(&usbduxfastsub->interface->dev,
- "comedi_: can not stop firmware\n");
- kfree(fwBuf);
- return ret;
- }
-
- ret = usbduxfastsub_upload(usbduxfastsub, fwBuf, 0, sizeFirmware);
- if (ret < 0) {
- dev_err(&usbduxfastsub->interface->dev,
- "comedi_: firmware upload failed\n");
- kfree(fwBuf);
- return ret;
- }
- ret = usbduxfastsub_start(usbduxfastsub);
- if (ret < 0) {
- dev_err(&usbduxfastsub->interface->dev,
- "comedi_: can not start firmware\n");
- kfree(fwBuf);
- return ret;
- }
- kfree(fwBuf);
- return 0;
-}
-
-static void tidy_up(struct usbduxfastsub_s *udfs)
-{
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi_: usbduxfast: tiding up\n");
-#endif
-
- if (!udfs)
- return;
- /* shows the usb subsystem that the driver is down */
- if (udfs->interface)
- usb_set_intfdata(udfs->interface, NULL);
+ up(&devpriv->sem);
- udfs->probed = 0;
-
- if (udfs->urbIn) {
- /* waits until a running transfer is over */
- usb_kill_urb(udfs->urbIn);
-
- kfree(udfs->transfer_buffer);
- udfs->transfer_buffer = NULL;
-
- usb_free_urb(udfs->urbIn);
- udfs->urbIn = NULL;
- }
-
- kfree(udfs->insnBuffer);
- udfs->insnBuffer = NULL;
-
- kfree(udfs->dux_commands);
- udfs->dux_commands = NULL;
-
- udfs->ai_cmd_running = 0;
+ return insn->n;
}
-static int usbduxfast_attach_common(struct comedi_device *dev,
- struct usbduxfastsub_s *udfs)
+static int usbduxfast_attach_common(struct comedi_device *dev)
{
- int ret;
+ struct usbduxfast_private *devpriv = dev->private;
struct comedi_subdevice *s;
+ int ret;
- down(&udfs->sem);
- /* pointer back to the corresponding comedi device */
- udfs->comedidev = dev;
+ down(&devpriv->sem);
ret = comedi_alloc_subdevices(dev, 1);
if (ret) {
- up(&udfs->sem);
+ up(&devpriv->sem);
return ret;
}
- /* private structure is also simply the usb-structure */
- dev->private = udfs;
- /* the first subdevice is the A/D converter */
- s = &dev->subdevices[SUBDEV_AD];
- /*
- * the URBs get the comedi subdevice which is responsible for reading
- * this is the subdevice which reads data
- */
+
+ /* Analog Input subdevice */
+ s = &dev->subdevices[0];
dev->read_subdev = s;
- /* the subdevice receives as private structure the usb-structure */
- s->private = NULL;
- /* analog input */
- s->type = COMEDI_SUBD_AI;
- /* readable and ref is to ground */
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
- /* 16 channels */
- s->n_chan = 16;
- /* length of the channellist */
- s->len_chanlist = 16;
- /* callback functions */
- s->insn_read = usbduxfast_ai_insn_read;
- s->do_cmdtest = usbduxfast_ai_cmdtest;
- s->do_cmd = usbduxfast_ai_cmd;
- s->cancel = usbduxfast_ai_cancel;
- /* max value from the A/D converter (12bit+1 bit for overflow) */
- s->maxdata = 0x1000;
- /* range table to convert to physical units */
- s->range_table = &range_usbduxfast_ai_range;
- /* finally decide that it's attached */
- udfs->attached = 1;
- up(&udfs->sem);
- dev_info(dev->class_dev, "successfully attached to usbduxfast.\n");
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
+ s->n_chan = 16;
+ s->len_chanlist = 16;
+ s->insn_read = usbduxfast_ai_insn_read;
+ s->do_cmdtest = usbduxfast_ai_cmdtest;
+ s->do_cmd = usbduxfast_ai_cmd;
+ s->cancel = usbduxfast_ai_cancel;
+ s->maxdata = 0x1000;
+ s->range_table = &range_usbduxfast_ai_range;
+
+ up(&devpriv->sem);
+
return 0;
}
-static int usbduxfast_auto_attach(struct comedi_device *dev,
- unsigned long context_unused)
+static int usbduxfast_upload_firmware(struct comedi_device *dev,
+ const u8 *data, size_t size,
+ unsigned long context)
{
- struct usb_interface *uinterf = comedi_to_usb_interface(dev);
+ struct usb_device *usb = comedi_to_usb_dev(dev);
+ uint8_t *buf;
+ unsigned char *tmp;
int ret;
- struct usbduxfastsub_s *udfs;
- dev->private = NULL;
- down(&start_stop_sem);
- udfs = usb_get_intfdata(uinterf);
- if (!udfs || !udfs->probed) {
- dev_err(dev->class_dev,
- "usbduxfast: error: auto_attach failed, not connected\n");
- ret = -ENODEV;
- } else if (udfs->attached) {
- dev_err(dev->class_dev,
- "usbduxfast: error: auto_attach failed, already attached\n");
- ret = -ENODEV;
- } else
- ret = usbduxfast_attach_common(dev, udfs);
- up(&start_stop_sem);
- return ret;
-}
+ if (!data)
+ return 0;
-static void usbduxfast_detach(struct comedi_device *dev)
-{
- struct usbduxfastsub_s *usb = dev->private;
-
- if (usb) {
- down(&usb->sem);
- down(&start_stop_sem);
- dev->private = NULL;
- usb->attached = 0;
- usb->comedidev = NULL;
- up(&start_stop_sem);
- up(&usb->sem);
+ if (size > FIRMWARE_MAX_LEN) {
+ dev_err(dev->class_dev, "firmware binary too large for FX2\n");
+ return -ENOMEM;
}
-}
-
-static struct comedi_driver usbduxfast_driver = {
- .driver_name = "usbduxfast",
- .module = THIS_MODULE,
- .auto_attach = usbduxfast_auto_attach,
- .detach = usbduxfast_detach,
-};
-static void usbduxfast_firmware_request_complete_handler(const struct firmware
- *fw, void *context)
-{
- struct usbduxfastsub_s *usbduxfastsub_tmp = context;
- struct usb_interface *uinterf = usbduxfastsub_tmp->interface;
- int ret;
+ /* we generate a local buffer for the firmware */
+ buf = kmemdup(data, size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
- if (fw == NULL)
- return;
+ /* we need a malloc'ed buffer for usb_control_msg() */
+ tmp = kmalloc(1, GFP_KERNEL);
+ if (!tmp) {
+ kfree(buf);
+ return -ENOMEM;
+ }
- /*
- * we need to upload the firmware here because fw will be
- * freed once we've left this function
- */
- ret = firmwareUpload(usbduxfastsub_tmp, fw->data, fw->size);
+ /* stop the current firmware on the device */
+ *tmp = 1; /* 7f92 to one */
+ ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
+ USBDUXFASTSUB_FIRMWARE,
+ VENDOR_DIR_OUT,
+ USBDUXFASTSUB_CPUCS, 0x0000,
+ tmp, 1,
+ EZTIMEOUT);
+ if (ret < 0) {
+ dev_err(dev->class_dev, "can not stop firmware\n");
+ goto done;
+ }
- if (ret) {
- dev_err(&uinterf->dev,
- "Could not upload firmware (err=%d)\n", ret);
- goto out;
+ /* upload the new firmware to the device */
+ ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
+ USBDUXFASTSUB_FIRMWARE,
+ VENDOR_DIR_OUT,
+ 0, 0x0000,
+ buf, size,
+ EZTIMEOUT);
+ if (ret < 0) {
+ dev_err(dev->class_dev, "firmware upload failed\n");
+ goto done;
}
- comedi_usb_auto_config(uinterf, &usbduxfast_driver, 0);
- out:
- release_firmware(fw);
+ /* start the new firmware on the device */
+ *tmp = 0; /* 7f92 to zero */
+ ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
+ USBDUXFASTSUB_FIRMWARE,
+ VENDOR_DIR_OUT,
+ USBDUXFASTSUB_CPUCS, 0x0000,
+ tmp, 1,
+ EZTIMEOUT);
+ if (ret < 0)
+ dev_err(dev->class_dev, "can not start firmware\n");
+
+done:
+ kfree(tmp);
+ kfree(buf);
+ return ret;
}
-static int usbduxfast_usb_probe(struct usb_interface *uinterf,
- const struct usb_device_id *id)
+static int usbduxfast_auto_attach(struct comedi_device *dev,
+ unsigned long context_unused)
{
- struct usb_device *udev = interface_to_usbdev(uinterf);
- int i;
- int index;
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
+ struct usb_device *usb = comedi_to_usb_dev(dev);
+ struct usbduxfast_private *devpriv;
int ret;
- if (udev->speed != USB_SPEED_HIGH) {
- dev_err(&uinterf->dev,
+ if (usb->speed != USB_SPEED_HIGH) {
+ dev_err(dev->class_dev,
"This driver needs USB 2.0 to operate. Aborting...\n");
return -ENODEV;
}
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi_: usbduxfast_: finding a free structure for "
- "the usb-device\n");
-#endif
- down(&start_stop_sem);
- /* look for a free place in the usbduxfast array */
- index = -1;
- for (i = 0; i < NUMUSBDUXFAST; i++) {
- if (!usbduxfastsub[i].probed) {
- index = i;
- break;
- }
- }
- /* no more space */
- if (index == -1) {
- dev_err(&uinterf->dev,
- "Too many usbduxfast-devices connected.\n");
- up(&start_stop_sem);
- return -EMFILE;
- }
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi_: usbduxfast: usbduxfastsub[%d] is ready to "
- "connect to comedi.\n", index);
-#endif
-
- sema_init(&(usbduxfastsub[index].sem), 1);
- /* save a pointer to the usb device */
- usbduxfastsub[index].usbdev = udev;
-
- /* save the interface itself */
- usbduxfastsub[index].interface = uinterf;
- /* get the interface number from the interface */
- usbduxfastsub[index].ifnum = uinterf->altsetting->desc.bInterfaceNumber;
- /*
- * hand the private data over to the usb subsystem
- * will be needed for disconnect
- */
- usb_set_intfdata(uinterf, &(usbduxfastsub[index]));
-
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi_: usbduxfast: ifnum=%d\n",
- usbduxfastsub[index].ifnum);
-#endif
- /* create space for the commands going to the usb device */
- usbduxfastsub[index].dux_commands = kmalloc(SIZEOFDUXBUFFER,
- GFP_KERNEL);
- if (!usbduxfastsub[index].dux_commands) {
- tidy_up(&(usbduxfastsub[index]));
- up(&start_stop_sem);
+ devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+ if (!devpriv)
return -ENOMEM;
- }
- /* create space of the instruction buffer */
- usbduxfastsub[index].insnBuffer = kmalloc(SIZEINSNBUF, GFP_KERNEL);
- if (!usbduxfastsub[index].insnBuffer) {
- tidy_up(&(usbduxfastsub[index]));
- up(&start_stop_sem);
+ dev->private = devpriv;
+
+ sema_init(&devpriv->sem, 1);
+ usb_set_intfdata(intf, devpriv);
+
+ devpriv->duxbuf = kmalloc(SIZEOFDUXBUF, GFP_KERNEL);
+ if (!devpriv->duxbuf)
return -ENOMEM;
- }
- /* setting to alternate setting 1: enabling bulk ep */
- i = usb_set_interface(usbduxfastsub[index].usbdev,
- usbduxfastsub[index].ifnum, 1);
- if (i < 0) {
- dev_err(&uinterf->dev,
- "usbduxfast%d: could not switch to alternate setting 1.\n",
- index);
- tidy_up(&(usbduxfastsub[index]));
- up(&start_stop_sem);
+
+ ret = usb_set_interface(usb,
+ intf->altsetting->desc.bInterfaceNumber, 1);
+ if (ret < 0) {
+ dev_err(dev->class_dev,
+ "could not switch to alternate setting 1\n");
return -ENODEV;
}
- usbduxfastsub[index].urbIn = usb_alloc_urb(0, GFP_KERNEL);
- if (!usbduxfastsub[index].urbIn) {
- dev_err(&uinterf->dev,
- "usbduxfast%d: Could not alloc. urb\n", index);
- tidy_up(&(usbduxfastsub[index]));
- up(&start_stop_sem);
+
+ devpriv->urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!devpriv->urb) {
+ dev_err(dev->class_dev, "Could not alloc. urb\n");
return -ENOMEM;
}
- usbduxfastsub[index].transfer_buffer = kmalloc(SIZEINBUF, GFP_KERNEL);
- if (!usbduxfastsub[index].transfer_buffer) {
- tidy_up(&(usbduxfastsub[index]));
- up(&start_stop_sem);
+
+ devpriv->inbuf = kmalloc(SIZEINBUF, GFP_KERNEL);
+ if (!devpriv->inbuf)
return -ENOMEM;
- }
- /* we've reached the bottom of the function */
- usbduxfastsub[index].probed = 1;
- up(&start_stop_sem);
-
- ret = request_firmware_nowait(THIS_MODULE,
- FW_ACTION_HOTPLUG,
- FIRMWARE,
- &udev->dev,
- GFP_KERNEL,
- usbduxfastsub + index,
- usbduxfast_firmware_request_complete_handler);
- if (ret) {
- dev_err(&uinterf->dev, "could not load firmware (err=%d)\n", ret);
+ ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE,
+ usbduxfast_upload_firmware, 0);
+ if (ret)
return ret;
- }
- dev_info(&uinterf->dev,
- "usbduxfast%d has been successfully initialized.\n", index);
- /* success */
- return 0;
+ return usbduxfast_attach_common(dev);
}
-static void usbduxfast_usb_disconnect(struct usb_interface *intf)
+static void usbduxfast_detach(struct comedi_device *dev)
{
- struct usbduxfastsub_s *udfs = usb_get_intfdata(intf);
- struct usb_device *udev = interface_to_usbdev(intf);
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
+ struct usbduxfast_private *devpriv = dev->private;
- if (!udfs) {
- dev_err(&intf->dev, "disconnect called with null pointer.\n");
- return;
- }
- if (udfs->usbdev != udev) {
- dev_err(&intf->dev, "BUG! called with wrong ptr!!!\n");
+ if (!devpriv)
return;
+
+ down(&devpriv->sem);
+
+ usb_set_intfdata(intf, NULL);
+
+ if (devpriv->urb) {
+ /* waits until a running transfer is over */
+ usb_kill_urb(devpriv->urb);
+
+ kfree(devpriv->inbuf);
+ devpriv->inbuf = NULL;
+
+ usb_free_urb(devpriv->urb);
+ devpriv->urb = NULL;
}
- comedi_usb_auto_unconfig(intf);
+ kfree(devpriv->duxbuf);
+ devpriv->duxbuf = NULL;
- down(&start_stop_sem);
- down(&udfs->sem);
- tidy_up(udfs);
- up(&udfs->sem);
- up(&start_stop_sem);
+ devpriv->ai_cmd_running = 0;
-#ifdef CONFIG_COMEDI_DEBUG
- printk(KERN_DEBUG "comedi_: usbduxfast: disconnected from the usb\n");
-#endif
+ up(&devpriv->sem);
+}
+
+static struct comedi_driver usbduxfast_driver = {
+ .driver_name = "usbduxfast",
+ .module = THIS_MODULE,
+ .auto_attach = usbduxfast_auto_attach,
+ .detach = usbduxfast_detach,
+};
+
+static int usbduxfast_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return comedi_usb_auto_config(intf, &usbduxfast_driver, 0);
}
static const struct usb_device_id usbduxfast_usb_table[] = {
@@ -1657,12 +1152,9 @@ static const struct usb_device_id usbduxfast_usb_table[] = {
MODULE_DEVICE_TABLE(usb, usbduxfast_usb_table);
static struct usb_driver usbduxfast_usb_driver = {
-#ifdef COMEDI_HAVE_USB_DRIVER_OWNER
- .owner = THIS_MODULE,
-#endif
.name = "usbduxfast",
.probe = usbduxfast_usb_probe,
- .disconnect = usbduxfast_usb_disconnect,
+ .disconnect = comedi_usb_auto_unconfig,
.id_table = usbduxfast_usb_table,
};
module_comedi_usb_driver(usbduxfast_driver, usbduxfast_usb_driver);
diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c
index d3bc1b9910a7..898c3c450406 100644
--- a/drivers/staging/comedi/drivers/usbduxsigma.c
+++ b/drivers/staging/comedi/drivers/usbduxsigma.c
@@ -1,30 +1,27 @@
/*
- comedi/drivers/usbdux.c
- Copyright (C) 2011 Bernd Porr, Bernd.Porr@f2s.com
-
- 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.
-
+ * usbduxsigma.c
+ * Copyright (C) 2011 Bernd Porr, Bernd.Porr@f2s.com
+ *
+ * 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.
*/
+
/*
-Driver: usbduxsigma
-Description: University of Stirling USB DAQ & INCITE Technology Limited
-Devices: [ITL] USB-DUX (usbduxsigma.o)
-Author: Bernd Porr <BerndPorr@f2s.com>
-Updated: 8 Nov 2011
-Status: testing
-*/
+ * Driver: usbduxsigma
+ * Description: University of Stirling USB DAQ & INCITE Technology Limited
+ * Devices: (ITL) USB-DUX [usbduxsigma]
+ * Author: Bernd Porr <BerndPorr@f2s.com>
+ * Updated: 8 Nov 2011
+ * Status: testing
+ */
+
/*
* I must give credit here to Chris Baugher who
* wrote the driver for AT-MIO-16d. I used some parts of this
@@ -44,9 +41,6 @@ Status: testing
* 0.6: corrected wrong input range
*/
-/* generates loads of debug info */
-/* #define NOISY_DUX_DEBUGBUG */
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -55,7 +49,7 @@ Status: testing
#include <linux/usb.h>
#include <linux/fcntl.h>
#include <linux/compiler.h>
-#include <linux/firmware.h>
+
#include "comedi_fc.h"
#include "../comedidev.h"
@@ -63,38 +57,21 @@ Status: testing
#define BULK_TIMEOUT 1000
/* constants for "firmware" upload and download */
-#define FIRMWARE "usbduxsigma_firmware.bin"
-#define USBDUXSUB_FIRMWARE 0xA0
-#define VENDOR_DIR_IN 0xC0
-#define VENDOR_DIR_OUT 0x40
+#define FIRMWARE "usbduxsigma_firmware.bin"
+#define FIRMWARE_MAX_LEN 0x4000
+#define USBDUXSUB_FIRMWARE 0xa0
+#define VENDOR_DIR_IN 0xc0
+#define VENDOR_DIR_OUT 0x40
/* internal addresses of the 8051 processor */
#define USBDUXSUB_CPUCS 0xE600
-/*
- * the minor device number, major is 180 only for debugging purposes and to
- * upload special firmware (programming the eeprom etc) which is not
- * compatible with the comedi framwork
- */
-#define USBDUXSUB_MINOR 32
-
-/* max lenghth of the transfer-buffer for software upload */
-#define TB_LEN 0x2000
-
-/* Input endpoint number: ISO/IRQ */
-#define ISOINEP 6
-
-/* Output endpoint number: ISO/IRQ */
-#define ISOOUTEP 2
-
-/* This EP sends DUX commands to USBDUX */
-#define COMMAND_OUT_EP 1
-
-/* This EP receives the DUX commands from USBDUX */
-#define COMMAND_IN_EP 8
-
-/* Output endpoint for PWM */
-#define PWM_EP 4
+/* USB endpoints */
+#define USBDUXSIGMA_CMD_OUT_EP 1 /* command output */
+#define USBDUXSIGMA_ISO_OUT_EP 2 /* analog output ISO/IRQ */
+#define USBDUXSIGMA_PWM_OUT_EP 4 /* pwm output */
+#define USBDUXSIGMA_ISO_IN_EP 6 /* analog input ISO/IRQ */
+#define USBDUXSIGMA_CMD_IN_EP 8 /* command input */
/* 300Hz max frequ under PWM */
#define MIN_PWM_PERIOD ((long)(1E9/300))
@@ -105,6 +82,8 @@ Status: testing
/* Number of channels (16 AD and offset)*/
#define NUMCHANNELS 16
+#define USBDUXSIGMA_NUM_AO_CHAN 4
+
/* Size of one A/D value */
#define SIZEADIN ((sizeof(int32_t)))
@@ -150,84 +129,54 @@ Status: testing
/* must have more buffers due to buggy USB ctr */
#define NUMOFOUTBUFFERSHIGH 10
-/* Total number of usbdux devices */
-#define NUMUSBDUX 16
-
-/* Analogue in subdevice */
-#define SUBDEV_AD 0
-
-/* Analogue out subdevice */
-#define SUBDEV_DA 1
-
-/* Digital I/O */
-#define SUBDEV_DIO 2
-
-/* timer aka pwm output */
-#define SUBDEV_PWM 3
-
/* number of retries to get the right dux command */
#define RETRIES 10
-/**************************************************/
-/* comedi constants */
-static const struct comedi_lrange range_usbdux_ai_range = { 1, {
- BIP_RANGE
- (2.65/2.0)
- }
-};
+/* bulk transfer commands to usbduxsigma */
+#define USBBUXSIGMA_AD_CMD 0
+#define USBDUXSIGMA_DA_CMD 1
+#define USBDUXSIGMA_DIO_CFG_CMD 2
+#define USBDUXSIGMA_DIO_BITS_CMD 3
+#define USBDUXSIGMA_SINGLE_AD_CMD 4
+#define USBDUXSIGMA_PWM_ON_CMD 7
+#define USBDUXSIGMA_PWM_OFF_CMD 8
-/*
- * private structure of one subdevice
- */
+static const struct comedi_lrange usbduxsigma_ai_range = {
+ 1, {
+ BIP_RANGE(2.65 / 2.0)
+ }
+};
-/*
- * This is the structure which holds all the data of
- * this driver one sub device just now: A/D
- */
-struct usbduxsub {
- /* attached? */
- int attached;
- /* is it associated with a subdevice? */
- int probed;
- /* pointer to the usb-device */
- struct usb_device *usbdev;
+struct usbduxsigma_private {
/* actual number of in-buffers */
- int numOfInBuffers;
+ int n_ai_urbs;
/* actual number of out-buffers */
- int numOfOutBuffers;
+ int n_ao_urbs;
/* ISO-transfer handling: buffers */
- struct urb **urbIn;
- struct urb **urbOut;
+ struct urb **ai_urbs;
+ struct urb **ao_urbs;
/* pwm-transfer handling */
- struct urb *urbPwm;
+ struct urb *pwm_urb;
/* PWM period */
- unsigned int pwmPeriod;
+ unsigned int pwm_period;
/* PWM internal delay for the GPIF in the FX2 */
- uint8_t pwmDelay;
+ uint8_t pwm_delay;
/* size of the PWM buffer which holds the bit pattern */
- int sizePwmBuf;
+ int pwm_buf_sz;
/* input buffer for the ISO-transfer */
- int32_t *inBuffer;
+ int32_t *in_buf;
/* input buffer for single insn */
- int8_t *insnBuffer;
- /* output buffer for single DA outputs */
- int16_t *outBuffer;
- /* interface number */
- int ifnum;
- /* interface structure in 2.6 */
- struct usb_interface *interface;
- /* comedi device for the interrupt context */
- struct comedi_device *comedidev;
- /* is it USB_SPEED_HIGH or not? */
- short int high_speed;
- /* asynchronous command is running */
- short int ai_cmd_running;
- short int ao_cmd_running;
- /* pwm is running */
- short int pwm_cmd_running;
- /* continuous acquisition */
- short int ai_continuous;
- short int ao_continuous;
+ int8_t *insn_buf;
+
+ unsigned int ao_readback[USBDUXSIGMA_NUM_AO_CHAN];
+
+ unsigned high_speed:1;
+ unsigned ai_cmd_running:1;
+ unsigned ai_continuous:1;
+ unsigned ao_cmd_running:1;
+ unsigned ao_continuous:1;
+ unsigned pwm_cmd_running:1;
+
/* number of samples to acquire */
int ai_sample_count;
int ao_sample_count;
@@ -246,126 +195,58 @@ struct usbduxsub {
struct semaphore sem;
};
-/*
- * The pointer to the private usb-data of the driver is also the private data
- * for the comedi-device. This has to be global as the usb subsystem needs
- * global variables. The other reason is that this structure must be there
- * _before_ any comedi command is issued. The usb subsystem must be initialised
- * before comedi can access it.
- */
-static struct usbduxsub usbduxsub[NUMUSBDUX];
-
-static DEFINE_SEMAPHORE(start_stop_sem);
-
-/*
- * Stops the data acquision
- * It should be safe to call this function from any context
- */
-static int usbduxsub_unlink_InURBs(struct usbduxsub *usbduxsub_tmp)
+static void usbduxsigma_ai_stop(struct comedi_device *dev, int do_unlink)
{
- int i = 0;
- int err = 0;
-
- if (usbduxsub_tmp && usbduxsub_tmp->urbIn) {
- for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) {
- if (usbduxsub_tmp->urbIn[i]) {
- /* We wait here until all transfers have been
- * cancelled. */
- usb_kill_urb(usbduxsub_tmp->urbIn[i]);
- }
- dev_dbg(&usbduxsub_tmp->interface->dev,
- "comedi: usbdux: unlinked InURB %d, err=%d\n",
- i, err);
- }
- }
- return err;
-}
-
-/*
- * This will stop a running acquisition operation
- * Is called from within this driver from both the
- * interrupt context and from comedi
- */
-static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
-{
- int ret = 0;
-
- if (!this_usbduxsub) {
- pr_err("comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n");
- return -EFAULT;
- }
- dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_stop\n");
+ struct usbduxsigma_private *devpriv = dev->private;
if (do_unlink) {
- /* stop aquistion */
- ret = usbduxsub_unlink_InURBs(this_usbduxsub);
- }
+ int i;
- this_usbduxsub->ai_cmd_running = 0;
+ for (i = 0; i < devpriv->n_ai_urbs; i++) {
+ if (devpriv->ai_urbs[i])
+ usb_kill_urb(devpriv->ai_urbs[i]);
+ }
+ }
- return ret;
+ devpriv->ai_cmd_running = 0;
}
-/*
- * This will cancel a running acquisition operation.
- * This is called by comedi but never from inside the driver.
- */
-static int usbdux_ai_cancel(struct comedi_device *dev,
- struct comedi_subdevice *s)
+static int usbduxsigma_ai_cancel(struct comedi_device *dev,
+ struct comedi_subdevice *s)
{
- struct usbduxsub *this_usbduxsub;
- int res = 0;
-
- /* force unlink of all urbs */
- this_usbduxsub = dev->private;
- if (!this_usbduxsub)
- return -EFAULT;
+ struct usbduxsigma_private *devpriv = dev->private;
- dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_cancel\n");
+ down(&devpriv->sem);
+ /* unlink only if it is really running */
+ usbduxsigma_ai_stop(dev, devpriv->ai_cmd_running);
+ up(&devpriv->sem);
- /* prevent other CPUs from submitting new commands just now */
- down(&this_usbduxsub->sem);
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
- /* unlink only if the urb really has been submitted */
- res = usbdux_ai_stop(this_usbduxsub, this_usbduxsub->ai_cmd_running);
- up(&this_usbduxsub->sem);
- return res;
+ return 0;
}
-/* analogue IN - interrupt service routine */
-static void usbduxsub_ai_IsocIrq(struct urb *urb)
+static void usbduxsigma_ai_urb_complete(struct urb *urb)
{
- int i, err, n;
- struct usbduxsub *this_usbduxsub;
- struct comedi_device *this_comedidev;
- struct comedi_subdevice *s;
- int32_t v;
+ struct comedi_device *dev = urb->context;
+ struct usbduxsigma_private *devpriv = dev->private;
+ struct comedi_subdevice *s = dev->read_subdev;
unsigned int dio_state;
-
- /* the context variable points to the comedi device */
- this_comedidev = urb->context;
- /* the private structure of the subdevice is struct usbduxsub */
- this_usbduxsub = this_comedidev->private;
- /* subdevice which is the AD converter */
- s = &this_comedidev->subdevices[SUBDEV_AD];
+ int32_t val;
+ int ret;
+ int i;
/* first we test if something unusual has just happened */
switch (urb->status) {
case 0:
/* copy the result in the transfer buffer */
- memcpy(this_usbduxsub->inBuffer,
- urb->transfer_buffer, SIZEINBUF);
+ memcpy(devpriv->in_buf, urb->transfer_buffer, SIZEINBUF);
break;
case -EILSEQ:
- /* error in the ISOchronous data */
- /* we don't copy the data into the transfer buffer */
- /* and recycle the last data byte */
- dev_dbg(&urb->dev->dev,
- "comedi%d: usbdux: CRC error in ISO IN stream.\n",
- this_usbduxsub->comedidev->minor);
+ /*
+ * error in the ISOchronous data
+ * we don't copy the data into the transfer buffer
+ * and recycle the last data byte
+ */
+ dev_dbg(dev->class_dev, "CRC error in ISO IN stream\n");
break;
@@ -374,185 +255,127 @@ static void usbduxsub_ai_IsocIrq(struct urb *urb)
case -ESHUTDOWN:
case -ECONNABORTED:
/* happens after an unlink command */
- if (this_usbduxsub->ai_cmd_running) {
- /* we are still running a command */
- /* tell this comedi */
- s->async->events |= COMEDI_CB_EOA;
- s->async->events |= COMEDI_CB_ERROR;
- comedi_event(this_usbduxsub->comedidev, s);
- /* stop the transfer w/o unlink */
- usbdux_ai_stop(this_usbduxsub, 0);
+ if (devpriv->ai_cmd_running) {
+ usbduxsigma_ai_stop(dev, 0); /* w/o unlink */
+ /* we are still running a command, tell comedi */
+ s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
+ comedi_event(dev, s);
}
return;
default:
- /* a real error on the bus */
- /* pass error to comedi if we are really running a command */
- if (this_usbduxsub->ai_cmd_running) {
- dev_err(&urb->dev->dev,
- "Non-zero urb status received in ai intr "
- "context: %d\n", urb->status);
- s->async->events |= COMEDI_CB_EOA;
- s->async->events |= COMEDI_CB_ERROR;
- comedi_event(this_usbduxsub->comedidev, s);
- /* don't do an unlink here */
- usbdux_ai_stop(this_usbduxsub, 0);
+ /*
+ * a real error on the bus
+ * pass error to comedi if we are really running a command
+ */
+ if (devpriv->ai_cmd_running) {
+ dev_err(dev->class_dev,
+ "%s: non-zero urb status (%d)\n",
+ __func__, urb->status);
+ usbduxsigma_ai_stop(dev, 0); /* w/o unlink */
+ s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
+ comedi_event(dev, s);
}
return;
}
- /*
- * at this point we are reasonably sure that nothing dodgy has happened
- * are we running a command?
- */
- if (unlikely((!(this_usbduxsub->ai_cmd_running)))) {
- /*
- * not running a command, do not continue execution if no
- * asynchronous command is running in particular not resubmit
- */
+ if (unlikely(!devpriv->ai_cmd_running))
return;
- }
- urb->dev = this_usbduxsub->usbdev;
-
- /* resubmit the urb */
- err = usb_submit_urb(urb, GFP_ATOMIC);
- if (unlikely(err < 0)) {
- dev_err(&urb->dev->dev,
- "comedi_: urb resubmit failed in int-context!"
- "err=%d\n",
- err);
- if (err == -EL2NSYNC)
- dev_err(&urb->dev->dev,
- "buggy USB host controller or bug in IRQ "
- "handler!\n");
- s->async->events |= COMEDI_CB_EOA;
- s->async->events |= COMEDI_CB_ERROR;
- comedi_event(this_usbduxsub->comedidev, s);
- /* don't do an unlink here */
- usbdux_ai_stop(this_usbduxsub, 0);
+ urb->dev = comedi_to_usb_dev(dev);
+
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (unlikely(ret < 0)) {
+ dev_err(dev->class_dev, "%s: urb resubmit failed (%d)\n",
+ __func__, ret);
+ if (ret == -EL2NSYNC)
+ dev_err(dev->class_dev,
+ "buggy USB host controller or bug in IRQ handler\n");
+ usbduxsigma_ai_stop(dev, 0); /* w/o unlink */
+ s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
+ comedi_event(dev, s);
return;
}
/* get the state of the dio pins to allow external trigger */
- dio_state = be32_to_cpu(this_usbduxsub->inBuffer[0]);
+ dio_state = be32_to_cpu(devpriv->in_buf[0]);
- this_usbduxsub->ai_counter--;
- if (likely(this_usbduxsub->ai_counter > 0))
+ devpriv->ai_counter--;
+ if (likely(devpriv->ai_counter > 0))
return;
/* timer zero, transfer measurements to comedi */
- this_usbduxsub->ai_counter = this_usbduxsub->ai_timer;
+ devpriv->ai_counter = devpriv->ai_timer;
- /* test, if we transmit only a fixed number of samples */
- if (!(this_usbduxsub->ai_continuous)) {
+ if (!devpriv->ai_continuous) {
/* not continuous, fixed number of samples */
- this_usbduxsub->ai_sample_count--;
- /* all samples received? */
- if (this_usbduxsub->ai_sample_count < 0) {
- /* prevent a resubmit next time */
- usbdux_ai_stop(this_usbduxsub, 0);
- /* say comedi that the acquistion is over */
+ devpriv->ai_sample_count--;
+ if (devpriv->ai_sample_count < 0) {
+ usbduxsigma_ai_stop(dev, 0); /* w/o unlink */
+ /* acquistion is over, tell comedi */
s->async->events |= COMEDI_CB_EOA;
- comedi_event(this_usbduxsub->comedidev, s);
+ comedi_event(dev, s);
return;
}
}
+
/* get the data from the USB bus and hand it over to comedi */
- n = s->async->cmd.chanlist_len;
- for (i = 0; i < n; i++) {
+ for (i = 0; i < s->async->cmd.chanlist_len; i++) {
/* transfer data, note first byte is the DIO state */
- v = be32_to_cpu(this_usbduxsub->inBuffer[i+1]);
- /* strip status byte */
- v = v & 0x00ffffff;
- /* convert to unsigned */
- v = v ^ 0x00800000;
- /* write the byte to the buffer */
- err = cfc_write_array_to_buffer(s, &v, sizeof(uint32_t));
- if (unlikely(err == 0)) {
+ val = be32_to_cpu(devpriv->in_buf[i+1]);
+ val &= 0x00ffffff; /* strip status byte */
+ val ^= 0x00800000; /* convert to unsigned */
+
+ ret = cfc_write_array_to_buffer(s, &val, sizeof(uint32_t));
+ if (unlikely(ret == 0)) {
/* buffer overflow */
- usbdux_ai_stop(this_usbduxsub, 0);
+ usbduxsigma_ai_stop(dev, 0); /* w/o unlink */
return;
}
}
/* tell comedi that data is there */
- s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
- comedi_event(this_usbduxsub->comedidev, s);
+ s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
+ comedi_event(dev, s);
}
-static int usbduxsub_unlink_OutURBs(struct usbduxsub *usbduxsub_tmp)
+static void usbduxsigma_ao_stop(struct comedi_device *dev, int do_unlink)
{
- int i = 0;
- int err = 0;
+ struct usbduxsigma_private *devpriv = dev->private;
- if (usbduxsub_tmp && usbduxsub_tmp->urbOut) {
- for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) {
- if (usbduxsub_tmp->urbOut[i])
- usb_kill_urb(usbduxsub_tmp->urbOut[i]);
+ if (do_unlink) {
+ int i;
- dev_dbg(&usbduxsub_tmp->interface->dev,
- "comedi: usbdux: unlinked OutURB %d: res=%d\n",
- i, err);
+ for (i = 0; i < devpriv->n_ao_urbs; i++) {
+ if (devpriv->ao_urbs[i])
+ usb_kill_urb(devpriv->ao_urbs[i]);
}
}
- return err;
-}
-/* This will cancel a running acquisition operation
- * in any context.
- */
-static int usbdux_ao_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
-{
- int ret = 0;
-
- if (!this_usbduxsub)
- return -EFAULT;
- dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ao_cancel\n");
-
- if (do_unlink)
- ret = usbduxsub_unlink_OutURBs(this_usbduxsub);
-
- this_usbduxsub->ao_cmd_running = 0;
-
- return ret;
+ devpriv->ao_cmd_running = 0;
}
-/* force unlink, is called by comedi */
-static int usbdux_ao_cancel(struct comedi_device *dev,
- struct comedi_subdevice *s)
+static int usbduxsigma_ao_cancel(struct comedi_device *dev,
+ struct comedi_subdevice *s)
{
- struct usbduxsub *this_usbduxsub = dev->private;
- int res = 0;
+ struct usbduxsigma_private *devpriv = dev->private;
- if (!this_usbduxsub)
- return -EFAULT;
-
- /* prevent other CPUs from submitting a command just now */
- down(&this_usbduxsub->sem);
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
+ down(&devpriv->sem);
/* unlink only if it is really running */
- res = usbdux_ao_stop(this_usbduxsub, this_usbduxsub->ao_cmd_running);
- up(&this_usbduxsub->sem);
- return res;
+ usbduxsigma_ao_stop(dev, devpriv->ao_cmd_running);
+ up(&devpriv->sem);
+
+ return 0;
}
-static void usbduxsub_ao_IsocIrq(struct urb *urb)
+static void usbduxsigma_ao_urb_complete(struct urb *urb)
{
- int i, ret;
+ struct comedi_device *dev = urb->context;
+ struct usbduxsigma_private *devpriv = dev->private;
+ struct comedi_subdevice *s = dev->write_subdev;
uint8_t *datap;
- struct usbduxsub *this_usbduxsub;
- struct comedi_device *this_comedidev;
- struct comedi_subdevice *s;
-
- /* the context variable points to the subdevice */
- this_comedidev = urb->context;
- /* the private structure of the subdevice is struct usbduxsub */
- this_usbduxsub = this_comedidev->private;
-
- s = &this_comedidev->subdevices[SUBDEV_DA];
+ int len;
+ int ret;
+ int i;
switch (urb->status) {
case 0:
@@ -563,347 +386,141 @@ static void usbduxsub_ao_IsocIrq(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
case -ECONNABORTED:
- /* after an unlink command, unplug, ... etc */
- /* no unlink needed here. Already shutting down. */
- if (this_usbduxsub->ao_cmd_running) {
+ /* happens after an unlink command */
+ if (devpriv->ao_cmd_running) {
+ usbduxsigma_ao_stop(dev, 0); /* w/o unlink */
s->async->events |= COMEDI_CB_EOA;
- comedi_event(this_usbduxsub->comedidev, s);
- usbdux_ao_stop(this_usbduxsub, 0);
+ comedi_event(dev, s);
}
return;
default:
/* a real error */
- if (this_usbduxsub->ao_cmd_running) {
- dev_err(&urb->dev->dev,
- "comedi_: Non-zero urb status received in ao "
- "intr context: %d\n", urb->status);
- s->async->events |= COMEDI_CB_ERROR;
- s->async->events |= COMEDI_CB_EOA;
- comedi_event(this_usbduxsub->comedidev, s);
- /* we do an unlink if we are in the high speed mode */
- usbdux_ao_stop(this_usbduxsub, 0);
+ if (devpriv->ao_cmd_running) {
+ dev_err(dev->class_dev,
+ "%s: non-zero urb status (%d)\n",
+ __func__, urb->status);
+ usbduxsigma_ao_stop(dev, 0); /* w/o unlink */
+ s->async->events |= (COMEDI_CB_ERROR | COMEDI_CB_EOA);
+ comedi_event(dev, s);
}
return;
}
- /* are we actually running? */
- if (!(this_usbduxsub->ao_cmd_running))
+ if (!devpriv->ao_cmd_running)
return;
- /* normal operation: executing a command in this subdevice */
- this_usbduxsub->ao_counter--;
- if ((int)this_usbduxsub->ao_counter <= 0) {
- /* timer zero */
- this_usbduxsub->ao_counter = this_usbduxsub->ao_timer;
-
- /* handle non continuous acquisition */
- if (!(this_usbduxsub->ao_continuous)) {
- /* fixed number of samples */
- this_usbduxsub->ao_sample_count--;
- if (this_usbduxsub->ao_sample_count < 0) {
- /* all samples transmitted */
- usbdux_ao_stop(this_usbduxsub, 0);
+ devpriv->ao_counter--;
+ if ((int)devpriv->ao_counter <= 0) {
+ /* timer zero, transfer from comedi */
+ devpriv->ao_counter = devpriv->ao_timer;
+
+ if (!devpriv->ao_continuous) {
+ /* not continuous, fixed number of samples */
+ devpriv->ao_sample_count--;
+ if (devpriv->ao_sample_count < 0) {
+ usbduxsigma_ao_stop(dev, 0); /* w/o unlink */
+ /* acquistion is over, tell comedi */
s->async->events |= COMEDI_CB_EOA;
- comedi_event(this_usbduxsub->comedidev, s);
- /* no resubmit of the urb */
+ comedi_event(dev, s);
return;
}
}
+
/* transmit data to the USB bus */
- ((uint8_t *) (urb->transfer_buffer))[0] =
- s->async->cmd.chanlist_len;
- for (i = 0; i < s->async->cmd.chanlist_len; i++) {
- short temp;
- if (i >= NUMOUTCHANNELS)
- break;
-
- /* pointer to the DA */
- datap =
- (&(((uint8_t *) urb->transfer_buffer)[i * 2 + 1]));
- /* get the data from comedi */
- ret = comedi_buf_get(s->async, &temp);
- datap[0] = temp;
- datap[1] = this_usbduxsub->dac_commands[i];
- /* printk("data[0]=%x, data[1]=%x, data[2]=%x\n", */
- /* datap[0],datap[1],datap[2]); */
+ datap = urb->transfer_buffer;
+ len = s->async->cmd.chanlist_len;
+ *datap++ = len;
+ for (i = 0; i < len; i++) {
+ unsigned int chan = devpriv->dac_commands[i];
+ short val;
+
+ ret = comedi_buf_get(s->async, &val);
if (ret < 0) {
- dev_err(&urb->dev->dev,
- "comedi: buffer underflow\n");
- s->async->events |= COMEDI_CB_EOA;
- s->async->events |= COMEDI_CB_OVERFLOW;
+ dev_err(dev->class_dev, "buffer underflow\n");
+ s->async->events |= (COMEDI_CB_EOA |
+ COMEDI_CB_OVERFLOW);
}
- /* transmit data to comedi */
+ *datap++ = val;
+ *datap++ = chan;
+ devpriv->ao_readback[chan] = val;
+
s->async->events |= COMEDI_CB_BLOCK;
- comedi_event(this_usbduxsub->comedidev, s);
+ comedi_event(dev, s);
}
}
+
urb->transfer_buffer_length = SIZEOUTBUF;
- urb->dev = this_usbduxsub->usbdev;
+ urb->dev = comedi_to_usb_dev(dev);
urb->status = 0;
- if (this_usbduxsub->ao_cmd_running) {
- if (this_usbduxsub->high_speed) {
- /* uframes */
- urb->interval = 8;
- } else {
- /* frames */
- urb->interval = 1;
- }
- urb->number_of_packets = 1;
- urb->iso_frame_desc[0].offset = 0;
- urb->iso_frame_desc[0].length = SIZEOUTBUF;
- urb->iso_frame_desc[0].status = 0;
- ret = usb_submit_urb(urb, GFP_ATOMIC);
- if (ret < 0) {
- dev_err(&urb->dev->dev,
- "comedi_: ao urb resubm failed in int-cont. "
- "ret=%d", ret);
- if (ret == EL2NSYNC)
- dev_err(&urb->dev->dev,
- "buggy USB host controller or bug in "
- "IRQ handling!\n");
-
- s->async->events |= COMEDI_CB_EOA;
- s->async->events |= COMEDI_CB_ERROR;
- comedi_event(this_usbduxsub->comedidev, s);
- /* don't do an unlink here */
- usbdux_ao_stop(this_usbduxsub, 0);
- }
- }
-}
-
-static int usbduxsub_start(struct usbduxsub *usbduxsub)
-{
- int errcode = 0;
- uint8_t *local_transfer_buffer;
-
- local_transfer_buffer = kmalloc(16, GFP_KERNEL);
- if (!local_transfer_buffer)
- return -ENOMEM;
-
- /* 7f92 to zero */
- local_transfer_buffer[0] = 0;
- errcode = usb_control_msg(usbduxsub->usbdev,
- /* create a pipe for a control transfer */
- usb_sndctrlpipe(usbduxsub->usbdev, 0),
- /* bRequest, "Firmware" */
- USBDUXSUB_FIRMWARE,
- /* bmRequestType */
- VENDOR_DIR_OUT,
- /* Value */
- USBDUXSUB_CPUCS,
- /* Index */
- 0x0000,
- /* address of the transfer buffer */
- local_transfer_buffer,
- /* Length */
- 1,
- /* Timeout */
- BULK_TIMEOUT);
- if (errcode < 0)
- dev_err(&usbduxsub->interface->dev,
- "comedi_: control msg failed (start)\n");
-
- kfree(local_transfer_buffer);
- return errcode;
-}
-
-static int usbduxsub_stop(struct usbduxsub *usbduxsub)
-{
- int errcode = 0;
- uint8_t *local_transfer_buffer;
-
- local_transfer_buffer = kmalloc(16, GFP_KERNEL);
- if (!local_transfer_buffer)
- return -ENOMEM;
-
- /* 7f92 to one */
- local_transfer_buffer[0] = 1;
- errcode = usb_control_msg(usbduxsub->usbdev,
- usb_sndctrlpipe(usbduxsub->usbdev, 0),
- /* bRequest, "Firmware" */
- USBDUXSUB_FIRMWARE,
- /* bmRequestType */
- VENDOR_DIR_OUT,
- /* Value */
- USBDUXSUB_CPUCS,
- /* Index */
- 0x0000, local_transfer_buffer,
- /* Length */
- 1,
- /* Timeout */
- BULK_TIMEOUT);
- if (errcode < 0)
- dev_err(&usbduxsub->interface->dev,
- "comedi_: control msg failed (stop)\n");
-
- kfree(local_transfer_buffer);
- return errcode;
-}
-
-static int usbduxsub_upload(struct usbduxsub *usbduxsub,
- uint8_t *local_transfer_buffer,
- unsigned int startAddr, unsigned int len)
-{
- int errcode;
-
- errcode = usb_control_msg(usbduxsub->usbdev,
- usb_sndctrlpipe(usbduxsub->usbdev, 0),
- /* brequest, firmware */
- USBDUXSUB_FIRMWARE,
- /* bmRequestType */
- VENDOR_DIR_OUT,
- /* value */
- startAddr,
- /* index */
- 0x0000,
- /* our local safe buffer */
- local_transfer_buffer,
- /* length */
- len,
- /* timeout */
- BULK_TIMEOUT);
- dev_dbg(&usbduxsub->interface->dev, "comedi_: result=%d\n", errcode);
- if (errcode < 0) {
- dev_err(&usbduxsub->interface->dev,
- "comedi_: upload failed\n");
- return errcode;
- }
- return 0;
-}
-
-/* the FX2LP has twice as much as the standard FX2 */
-#define FIRMWARE_MAX_LEN 0x4000
-
-static int firmwareUpload(struct usbduxsub *usbduxsub,
- const u8 *firmwareBinary, int sizeFirmware)
-{
- int ret;
- uint8_t *fwBuf;
-
- if (!firmwareBinary)
- return 0;
-
- if (sizeFirmware > FIRMWARE_MAX_LEN) {
- dev_err(&usbduxsub->interface->dev,
- "usbduxsigma firmware binary it too large for FX2.\n");
- return -ENOMEM;
- }
-
- /* we generate a local buffer for the firmware */
- fwBuf = kmemdup(firmwareBinary, sizeFirmware, GFP_KERNEL);
- if (!fwBuf) {
- dev_err(&usbduxsub->interface->dev,
- "comedi_: mem alloc for firmware failed\n");
- return -ENOMEM;
- }
-
- ret = usbduxsub_stop(usbduxsub);
- if (ret < 0) {
- dev_err(&usbduxsub->interface->dev,
- "comedi_: can not stop firmware\n");
- kfree(fwBuf);
- return ret;
- }
-
- ret = usbduxsub_upload(usbduxsub, fwBuf, 0, sizeFirmware);
- if (ret < 0) {
- dev_err(&usbduxsub->interface->dev,
- "comedi_: firmware upload failed\n");
- kfree(fwBuf);
- return ret;
- }
- ret = usbduxsub_start(usbduxsub);
+ if (devpriv->high_speed)
+ urb->interval = 8; /* uframes */
+ else
+ urb->interval = 1; /* frames */
+ urb->number_of_packets = 1;
+ urb->iso_frame_desc[0].offset = 0;
+ urb->iso_frame_desc[0].length = SIZEOUTBUF;
+ urb->iso_frame_desc[0].status = 0;
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret < 0) {
- dev_err(&usbduxsub->interface->dev,
- "comedi_: can not start firmware\n");
- kfree(fwBuf);
- return ret;
+ dev_err(dev->class_dev,
+ "%s: urb resubmit failed (%d)\n",
+ __func__, ret);
+ if (ret == EL2NSYNC)
+ dev_err(dev->class_dev,
+ "buggy USB host controller or bug in IRQ handler\n");
+ usbduxsigma_ao_stop(dev, 0); /* w/o unlink */
+ s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
+ comedi_event(dev, s);
}
- kfree(fwBuf);
- return 0;
}
-static int usbduxsub_submit_InURBs(struct usbduxsub *usbduxsub)
+static int usbduxsigma_submit_urbs(struct comedi_device *dev,
+ struct urb **urbs, int num_urbs,
+ int input_urb)
{
- int i, errFlag;
-
- if (!usbduxsub)
- return -EFAULT;
+ struct usb_device *usb = comedi_to_usb_dev(dev);
+ struct usbduxsigma_private *devpriv = dev->private;
+ struct urb *urb;
+ int ret;
+ int i;
/* Submit all URBs and start the transfer on the bus */
- for (i = 0; i < usbduxsub->numOfInBuffers; i++) {
- /* in case of a resubmission after an unlink... */
- usbduxsub->urbIn[i]->interval = usbduxsub->ai_interval;
- usbduxsub->urbIn[i]->context = usbduxsub->comedidev;
- usbduxsub->urbIn[i]->dev = usbduxsub->usbdev;
- usbduxsub->urbIn[i]->status = 0;
- usbduxsub->urbIn[i]->transfer_flags = URB_ISO_ASAP;
- dev_dbg(&usbduxsub->interface->dev,
- "comedi%d: submitting in-urb[%d]: %p,%p intv=%d\n",
- usbduxsub->comedidev->minor, i,
- (usbduxsub->urbIn[i]->context),
- (usbduxsub->urbIn[i]->dev),
- (usbduxsub->urbIn[i]->interval));
- errFlag = usb_submit_urb(usbduxsub->urbIn[i], GFP_ATOMIC);
- if (errFlag) {
- dev_err(&usbduxsub->interface->dev,
- "comedi_: ai: usb_submit_urb(%d) error %d\n",
- i, errFlag);
- return errFlag;
- }
- }
- return 0;
-}
-
-static int usbduxsub_submit_OutURBs(struct usbduxsub *usbduxsub)
-{
- int i, errFlag;
-
- if (!usbduxsub)
- return -EFAULT;
+ for (i = 0; i < num_urbs; i++) {
+ urb = urbs[i];
- for (i = 0; i < usbduxsub->numOfOutBuffers; i++) {
- dev_dbg(&usbduxsub->interface->dev,
- "comedi_: submitting out-urb[%d]\n", i);
/* in case of a resubmission after an unlink... */
- usbduxsub->urbOut[i]->context = usbduxsub->comedidev;
- usbduxsub->urbOut[i]->dev = usbduxsub->usbdev;
- usbduxsub->urbOut[i]->status = 0;
- usbduxsub->urbOut[i]->transfer_flags = URB_ISO_ASAP;
- errFlag = usb_submit_urb(usbduxsub->urbOut[i], GFP_ATOMIC);
- if (errFlag) {
- dev_err(&usbduxsub->interface->dev,
- "comedi_: ao: usb_submit_urb(%d) error %d\n",
- i, errFlag);
- return errFlag;
- }
+ if (input_urb)
+ urb->interval = devpriv->ai_interval;
+ urb->context = dev;
+ urb->dev = usb;
+ urb->status = 0;
+ urb->transfer_flags = URB_ISO_ASAP;
+
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret)
+ return ret;
}
return 0;
}
-static int chanToInterval(int nChannels)
+static int usbduxsigma_chans_to_interval(int num_chan)
{
- if (nChannels <= 2)
- /* 4kHz */
- return 2;
- if (nChannels <= 8)
- /* 2kHz */
- return 4;
- /* 1kHz */
- return 8;
+ if (num_chan <= 2)
+ return 2; /* 4kHz */
+ if (num_chan <= 8)
+ return 4; /* 2kHz */
+ return 8; /* 1kHz */
}
-static int usbdux_ai_cmdtest(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_cmd *cmd)
+static int usbduxsigma_ai_cmdtest(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_cmd *cmd)
{
- struct usbduxsub *this_usbduxsub = dev->private;
- int err = 0, i;
- unsigned int tmpTimer;
-
- if (!(this_usbduxsub->probed))
- return -ENODEV;
+ struct usbduxsigma_private *devpriv = dev->private;
+ int high_speed = devpriv->high_speed;
+ int interval = usbduxsigma_chans_to_interval(cmd->chanlist_len);
+ int err = 0;
/* Step 1 : check if triggers are trivially valid */
@@ -934,34 +551,28 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev,
err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
if (cmd->scan_begin_src == TRIG_TIMER) {
- if (this_usbduxsub->high_speed) {
+ unsigned int tmp;
+
+ if (high_speed) {
/*
* In high speed mode microframes are possible.
* However, during one microframe we can roughly
* sample two channels. Thus, the more channels
* are in the channel list the more time we need.
*/
- i = chanToInterval(cmd->chanlist_len);
err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
- (1000000 / 8 * i));
- /* now calc the real sampling rate with all the
- * rounding errors */
- tmpTimer =
- ((unsigned int)(cmd->scan_begin_arg / 125000)) *
- 125000;
+ (1000000 / 8 * interval));
+
+ tmp = (cmd->scan_begin_arg / 125000) * 125000;
} else {
/* full speed */
/* 1kHz scans every USB frame */
err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
1000000);
- /*
- * calc the real sampling rate with the rounding errors
- */
- tmpTimer = ((unsigned int)(cmd->scan_begin_arg /
- 1000000)) * 1000000;
+
+ tmp = (cmd->scan_begin_arg / 1000000) * 1000000;
}
- err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg,
- tmpTimer);
+ err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, tmp);
}
err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
@@ -976,6 +587,37 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev,
if (err)
return 3;
+ /* Step 4: fix up any arguments */
+
+ if (high_speed) {
+ /*
+ * every 2 channels get a time window of 125us. Thus, if we
+ * sample all 16 channels we need 1ms. If we sample only one
+ * channel we need only 125us
+ */
+ devpriv->ai_interval = interval;
+ devpriv->ai_timer = cmd->scan_begin_arg / (125000 * interval);
+ } else {
+ /* interval always 1ms */
+ devpriv->ai_interval = 1;
+ devpriv->ai_timer = cmd->scan_begin_arg / 1000000;
+ }
+ if (devpriv->ai_timer < 1)
+ err |= -EINVAL;
+
+ if (cmd->stop_src == TRIG_COUNT) {
+ /* data arrives as one packet */
+ devpriv->ai_sample_count = cmd->stop_arg;
+ devpriv->ai_continuous = 0;
+ } else {
+ /* continuous acquisition */
+ devpriv->ai_continuous = 1;
+ devpriv->ai_sample_count = 0;
+ }
+
+ if (err)
+ return 4;
+
return 0;
}
@@ -993,536 +635,278 @@ static void create_adc_command(unsigned int chan,
(*muxsg1) = (*muxsg1) | (1 << (chan-8));
}
+static int usbbuxsigma_send_cmd(struct comedi_device *dev, int cmd_type)
+{
+ struct usb_device *usb = comedi_to_usb_dev(dev);
+ struct usbduxsigma_private *devpriv = dev->private;
+ int nsent;
-/* bulk transfers to usbdux */
-
-#define SENDADCOMMANDS 0
-#define SENDDACOMMANDS 1
-#define SENDDIOCONFIGCOMMAND 2
-#define SENDDIOBITSCOMMAND 3
-#define SENDSINGLEAD 4
-#define SENDPWMON 7
-#define SENDPWMOFF 8
+ devpriv->dux_commands[0] = cmd_type;
-static int send_dux_commands(struct usbduxsub *this_usbduxsub, int cmd_type)
-{
- int result, nsent;
-
- this_usbduxsub->dux_commands[0] = cmd_type;
-#ifdef NOISY_DUX_DEBUGBUG
- printk(KERN_DEBUG "comedi%d: usbdux: dux_commands: ",
- this_usbduxsub->comedidev->minor);
- for (result = 0; result < SIZEOFDUXBUFFER; result++)
- printk(" %02x", this_usbduxsub->dux_commands[result]);
- printk("\n");
-#endif
- result = usb_bulk_msg(this_usbduxsub->usbdev,
- usb_sndbulkpipe(this_usbduxsub->usbdev,
- COMMAND_OUT_EP),
- this_usbduxsub->dux_commands, SIZEOFDUXBUFFER,
- &nsent, BULK_TIMEOUT);
- if (result < 0)
- dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
- "could not transmit dux_command to the usb-device, "
- "err=%d\n", this_usbduxsub->comedidev->minor, result);
-
- return result;
+ return usb_bulk_msg(usb, usb_sndbulkpipe(usb, USBDUXSIGMA_CMD_OUT_EP),
+ devpriv->dux_commands, SIZEOFDUXBUFFER,
+ &nsent, BULK_TIMEOUT);
}
-static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command)
+static int usbduxsigma_receive_cmd(struct comedi_device *dev, int command)
{
- int result = (-EFAULT);
+ struct usb_device *usb = comedi_to_usb_dev(dev);
+ struct usbduxsigma_private *devpriv = dev->private;
int nrec;
+ int ret;
int i;
for (i = 0; i < RETRIES; i++) {
- result = usb_bulk_msg(this_usbduxsub->usbdev,
- usb_rcvbulkpipe(this_usbduxsub->usbdev,
- COMMAND_IN_EP),
- this_usbduxsub->insnBuffer, SIZEINSNBUF,
- &nrec, BULK_TIMEOUT);
- if (result < 0) {
- dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
- "insn: USB error %d "
- "while receiving DUX command"
- "\n", this_usbduxsub->comedidev->minor,
- result);
- return result;
- }
- if (this_usbduxsub->insnBuffer[0] == command)
- return result;
+ ret = usb_bulk_msg(usb,
+ usb_rcvbulkpipe(usb, USBDUXSIGMA_CMD_IN_EP),
+ devpriv->insn_buf, SIZEINSNBUF,
+ &nrec, BULK_TIMEOUT);
+ if (ret < 0)
+ return ret;
+
+ if (devpriv->insn_buf[0] == command)
+ return 0;
}
- /* this is only reached if the data has been requested a couple of
- * times */
- dev_err(&this_usbduxsub->interface->dev, "comedi%d: insn: "
- "wrong data returned from firmware: want %d, got %d.\n",
- this_usbduxsub->comedidev->minor, command,
- this_usbduxsub->insnBuffer[0]);
+ /*
+ * This is only reached if the data has been requested a
+ * couple of times and the command was not received.
+ */
return -EFAULT;
}
-static int usbdux_ai_inttrig(struct comedi_device *dev,
- struct comedi_subdevice *s, unsigned int trignum)
+static int usbduxsigma_ai_inttrig(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned int trignum)
{
+ struct usbduxsigma_private *devpriv = dev->private;
int ret;
- struct usbduxsub *this_usbduxsub = dev->private;
- if (!this_usbduxsub)
- return -EFAULT;
- down(&this_usbduxsub->sem);
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
- dev_dbg(&this_usbduxsub->interface->dev,
- "comedi%d: usbdux_ai_inttrig\n", dev->minor);
-
- if (trignum != 0) {
- dev_err(&this_usbduxsub->interface->dev,
- "comedi%d: usbdux_ai_inttrig: invalid trignum\n",
- dev->minor);
- up(&this_usbduxsub->sem);
+ if (trignum != 0)
return -EINVAL;
- }
- if (!(this_usbduxsub->ai_cmd_running)) {
- this_usbduxsub->ai_cmd_running = 1;
- ret = usbduxsub_submit_InURBs(this_usbduxsub);
+
+ down(&devpriv->sem);
+ if (!devpriv->ai_cmd_running) {
+ ret = usbduxsigma_submit_urbs(dev, devpriv->ai_urbs,
+ devpriv->n_ai_urbs, 1);
if (ret < 0) {
- dev_err(&this_usbduxsub->interface->dev,
- "comedi%d: usbdux_ai_inttrig: "
- "urbSubmit: err=%d\n", dev->minor, ret);
- this_usbduxsub->ai_cmd_running = 0;
- up(&this_usbduxsub->sem);
+ up(&devpriv->sem);
return ret;
}
+ devpriv->ai_cmd_running = 1;
s->async->inttrig = NULL;
- } else {
- dev_err(&this_usbduxsub->interface->dev,
- "comedi%d: ai_inttrig but acqu is already running\n",
- dev->minor);
}
- up(&this_usbduxsub->sem);
+ up(&devpriv->sem);
+
return 1;
}
-static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+static int usbduxsigma_ai_cmd(struct comedi_device *dev,
+ struct comedi_subdevice *s)
{
+ struct usbduxsigma_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
- unsigned int chan;
- int i, ret;
- struct usbduxsub *this_usbduxsub = dev->private;
- int result;
+ unsigned int len = cmd->chanlist_len;
uint8_t muxsg0 = 0;
uint8_t muxsg1 = 0;
uint8_t sysred = 0;
+ int ret;
+ int i;
- if (!this_usbduxsub)
- return -EFAULT;
-
- dev_dbg(&this_usbduxsub->interface->dev,
- "comedi%d: usbdux_ai_cmd\n", dev->minor);
-
- /* block other CPUs from starting an ai_cmd */
- down(&this_usbduxsub->sem);
+ down(&devpriv->sem);
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
- if (this_usbduxsub->ai_cmd_running) {
- dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
- "ai_cmd not possible. Another ai_cmd is running.\n",
- dev->minor);
- up(&this_usbduxsub->sem);
- return -EBUSY;
- }
/* set current channel of the running acquisition to zero */
s->async->cur_chan = 0;
+ for (i = 0; i < len; i++) {
+ unsigned int chan = CR_CHAN(cmd->chanlist[i]);
- /* first the number of channels per time step */
- this_usbduxsub->dux_commands[1] = cmd->chanlist_len;
-
- /* CONFIG0 */
- this_usbduxsub->dux_commands[2] = 0x12;
-
- /* CONFIG1: 23kHz sampling rate, delay = 0us, */
- this_usbduxsub->dux_commands[3] = 0x03;
-
- /* CONFIG3: differential channels off */
- this_usbduxsub->dux_commands[4] = 0x00;
-
- for (i = 0; i < cmd->chanlist_len; i++) {
- chan = CR_CHAN(cmd->chanlist[i]);
create_adc_command(chan, &muxsg0, &muxsg1);
- if (i >= NUMCHANNELS) {
- dev_err(&this_usbduxsub->interface->dev,
- "comedi%d: channel list too long\n",
- dev->minor);
- break;
- }
- }
- this_usbduxsub->dux_commands[5] = muxsg0;
- this_usbduxsub->dux_commands[6] = muxsg1;
- this_usbduxsub->dux_commands[7] = sysred;
-
- dev_dbg(&this_usbduxsub->interface->dev,
- "comedi %d: sending commands to the usb device: size=%u\n",
- dev->minor, NUMCHANNELS);
-
- result = send_dux_commands(this_usbduxsub, SENDADCOMMANDS);
- if (result < 0) {
- up(&this_usbduxsub->sem);
- return result;
}
- if (this_usbduxsub->high_speed) {
- /*
- * every 2 channels get a time window of 125us. Thus, if we
- * sample all 16 channels we need 1ms. If we sample only one
- * channel we need only 125us
- */
- this_usbduxsub->ai_interval =
- chanToInterval(cmd->chanlist_len);
- this_usbduxsub->ai_timer = cmd->scan_begin_arg / (125000 *
- (this_usbduxsub->
- ai_interval));
- } else {
- /* interval always 1ms */
- this_usbduxsub->ai_interval = 1;
- this_usbduxsub->ai_timer = cmd->scan_begin_arg / 1000000;
- }
- if (this_usbduxsub->ai_timer < 1) {
- dev_err(&this_usbduxsub->interface->dev, "comedi%d: ai_cmd: "
- "timer=%d, scan_begin_arg=%d. "
- "Not properly tested by cmdtest?\n", dev->minor,
- this_usbduxsub->ai_timer, cmd->scan_begin_arg);
- up(&this_usbduxsub->sem);
- return -EINVAL;
- }
- this_usbduxsub->ai_counter = this_usbduxsub->ai_timer;
+ devpriv->dux_commands[1] = len; /* num channels per time step */
+ devpriv->dux_commands[2] = 0x12; /* CONFIG0 */
+ devpriv->dux_commands[3] = 0x03; /* CONFIG1: 23kHz sample, delay 0us */
+ devpriv->dux_commands[4] = 0x00; /* CONFIG3: diff. channels off */
+ devpriv->dux_commands[5] = muxsg0;
+ devpriv->dux_commands[6] = muxsg1;
+ devpriv->dux_commands[7] = sysred;
- if (cmd->stop_src == TRIG_COUNT) {
- /* data arrives as one packet */
- this_usbduxsub->ai_sample_count = cmd->stop_arg;
- this_usbduxsub->ai_continuous = 0;
- } else {
- /* continuous acquisition */
- this_usbduxsub->ai_continuous = 1;
- this_usbduxsub->ai_sample_count = 0;
+ ret = usbbuxsigma_send_cmd(dev, USBBUXSIGMA_AD_CMD);
+ if (ret < 0) {
+ up(&devpriv->sem);
+ return ret;
}
+ devpriv->ai_counter = devpriv->ai_timer;
+
if (cmd->start_src == TRIG_NOW) {
/* enable this acquisition operation */
- this_usbduxsub->ai_cmd_running = 1;
- ret = usbduxsub_submit_InURBs(this_usbduxsub);
+ ret = usbduxsigma_submit_urbs(dev, devpriv->ai_urbs,
+ devpriv->n_ai_urbs, 1);
if (ret < 0) {
- this_usbduxsub->ai_cmd_running = 0;
- /* fixme: unlink here?? */
- up(&this_usbduxsub->sem);
+ up(&devpriv->sem);
return ret;
}
s->async->inttrig = NULL;
- } else {
- /* TRIG_INT */
- /* don't enable the acquision operation */
- /* wait for an internal signal */
- s->async->inttrig = usbdux_ai_inttrig;
+ devpriv->ai_cmd_running = 1;
+ } else { /* TRIG_INT */
+ /* wait for an internal signal and submit the urbs later */
+ s->async->inttrig = usbduxsigma_ai_inttrig;
}
- up(&this_usbduxsub->sem);
+
+ up(&devpriv->sem);
+
return 0;
}
-/* Mode 0 is used to get a single conversion on demand */
-static int usbdux_ai_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int usbduxsigma_ai_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- int i;
- int32_t one = 0;
- int chan;
- int err;
- struct usbduxsub *this_usbduxsub = dev->private;
+ struct usbduxsigma_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
uint8_t muxsg0 = 0;
uint8_t muxsg1 = 0;
uint8_t sysred = 0;
+ int ret;
+ int i;
- if (!this_usbduxsub)
- return 0;
-
- dev_dbg(&this_usbduxsub->interface->dev,
- "comedi%d: ai_insn_read, insn->n=%d, insn->subdev=%d\n",
- dev->minor, insn->n, insn->subdev);
-
- down(&this_usbduxsub->sem);
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
- if (this_usbduxsub->ai_cmd_running) {
- dev_err(&this_usbduxsub->interface->dev,
- "comedi%d: ai_insn_read not possible. "
- "Async Command is running.\n", dev->minor);
- up(&this_usbduxsub->sem);
- return 0;
+ down(&devpriv->sem);
+ if (devpriv->ai_cmd_running) {
+ up(&devpriv->sem);
+ return -EBUSY;
}
- /* sample one channel */
- /* CONFIG0: chopper on */
- this_usbduxsub->dux_commands[1] = 0x16;
-
- /* CONFIG1: 2kHz sampling rate */
- this_usbduxsub->dux_commands[2] = 0x80;
-
- /* CONFIG3: differential channels off */
- this_usbduxsub->dux_commands[3] = 0x00;
-
- chan = CR_CHAN(insn->chanspec);
create_adc_command(chan, &muxsg0, &muxsg1);
- this_usbduxsub->dux_commands[4] = muxsg0;
- this_usbduxsub->dux_commands[5] = muxsg1;
- this_usbduxsub->dux_commands[6] = sysred;
+ /* Mode 0 is used to get a single conversion on demand */
+ devpriv->dux_commands[1] = 0x16; /* CONFIG0: chopper on */
+ devpriv->dux_commands[2] = 0x80; /* CONFIG1: 2kHz sampling rate */
+ devpriv->dux_commands[3] = 0x00; /* CONFIG3: diff. channels off */
+ devpriv->dux_commands[4] = muxsg0;
+ devpriv->dux_commands[5] = muxsg1;
+ devpriv->dux_commands[6] = sysred;
/* adc commands */
- err = send_dux_commands(this_usbduxsub, SENDSINGLEAD);
- if (err < 0) {
- up(&this_usbduxsub->sem);
- return err;
+ ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD);
+ if (ret < 0) {
+ up(&devpriv->sem);
+ return ret;
}
for (i = 0; i < insn->n; i++) {
- err = receive_dux_commands(this_usbduxsub, SENDSINGLEAD);
- if (err < 0) {
- up(&this_usbduxsub->sem);
- return 0;
- }
- /* 32 bits big endian from the A/D converter */
- one = be32_to_cpu(*((int32_t *)
- ((this_usbduxsub->insnBuffer)+1)));
- /* mask out the status byte */
- one = one & 0x00ffffff;
- /* turn it into an unsigned integer */
- one = one ^ 0x00800000;
- data[i] = one;
- }
- up(&this_usbduxsub->sem);
- return i;
-}
-
-
-
+ int32_t val;
-static int usbdux_getstatusinfo(struct comedi_device *dev, int chan)
-{
- struct usbduxsub *this_usbduxsub = dev->private;
- uint8_t sysred = 0;
- uint32_t one;
- int err;
-
- if (!this_usbduxsub)
- return 0;
+ ret = usbduxsigma_receive_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD);
+ if (ret < 0) {
+ up(&devpriv->sem);
+ return ret;
+ }
- if (this_usbduxsub->ai_cmd_running) {
- dev_err(&this_usbduxsub->interface->dev,
- "comedi%d: status read not possible. "
- "Async Command is running.\n", dev->minor);
- return 0;
- }
+ /* 32 bits big endian from the A/D converter */
+ val = be32_to_cpu(*((int32_t *)((devpriv->insn_buf) + 1)));
+ val &= 0x00ffffff; /* strip status byte */
+ val ^= 0x00800000; /* convert to unsigned */
- /* CONFIG0 */
- this_usbduxsub->dux_commands[1] = 0x12;
-
- /* CONFIG1: 2kHz sampling rate */
- this_usbduxsub->dux_commands[2] = 0x80;
-
- /* CONFIG3: differential channels off */
- this_usbduxsub->dux_commands[3] = 0x00;
-
- if (chan == 1) {
- /* ADC offset */
- sysred = sysred | 1;
- } else if (chan == 2) {
- /* VCC */
- sysred = sysred | 4;
- } else if (chan == 3) {
- /* temperature */
- sysred = sysred | 8;
- } else if (chan == 4) {
- /* gain */
- sysred = sysred | 16;
- } else if (chan == 5) {
- /* ref */
- sysred = sysred | 32;
+ data[i] = val;
}
+ up(&devpriv->sem);
- this_usbduxsub->dux_commands[4] = 0;
- this_usbduxsub->dux_commands[5] = 0;
- this_usbduxsub->dux_commands[6] = sysred;
-
- /* adc commands */
- err = send_dux_commands(this_usbduxsub, SENDSINGLEAD);
- if (err < 0)
- return err;
-
- err = receive_dux_commands(this_usbduxsub, SENDSINGLEAD);
- if (err < 0)
- return err;
-
- /* 32 bits big endian from the A/D converter */
- one = be32_to_cpu(*((int32_t *)((this_usbduxsub->insnBuffer)+1)));
- /* mask out the status byte */
- one = one & 0x00ffffff;
- one = one ^ 0x00800000;
-
- return (int)one;
+ return insn->n;
}
-
-
-
-
-
-/************************************/
-/* analog out */
-
-static int usbdux_ao_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int usbduxsigma_ao_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
+ struct usbduxsigma_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
int i;
- int chan = CR_CHAN(insn->chanspec);
- struct usbduxsub *this_usbduxsub = dev->private;
-
- if (!this_usbduxsub)
- return -EFAULT;
- down(&this_usbduxsub->sem);
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
+ down(&devpriv->sem);
for (i = 0; i < insn->n; i++)
- data[i] = this_usbduxsub->outBuffer[chan];
+ data[i] = devpriv->ao_readback[chan];
+ up(&devpriv->sem);
- up(&this_usbduxsub->sem);
- return i;
+ return insn->n;
}
-static int usbdux_ao_insn_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int usbduxsigma_ao_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- int i, err;
- int chan = CR_CHAN(insn->chanspec);
- struct usbduxsub *this_usbduxsub = dev->private;
-
- if (!this_usbduxsub)
- return -EFAULT;
-
- dev_dbg(&this_usbduxsub->interface->dev,
- "comedi%d: ao_insn_write\n", dev->minor);
+ struct usbduxsigma_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ int ret;
+ int i;
- down(&this_usbduxsub->sem);
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
- if (this_usbduxsub->ao_cmd_running) {
- dev_err(&this_usbduxsub->interface->dev,
- "comedi%d: ao_insn_write: "
- "ERROR: asynchronous ao_cmd is running\n", dev->minor);
- up(&this_usbduxsub->sem);
- return 0;
+ down(&devpriv->sem);
+ if (devpriv->ao_cmd_running) {
+ up(&devpriv->sem);
+ return -EBUSY;
}
for (i = 0; i < insn->n; i++) {
- dev_dbg(&this_usbduxsub->interface->dev,
- "comedi%d: ao_insn_write: data[chan=%d,i=%d]=%d\n",
- dev->minor, chan, i, data[i]);
-
- /* number of channels: 1 */
- this_usbduxsub->dux_commands[1] = 1;
- /* channel number */
- this_usbduxsub->dux_commands[2] = data[i];
- this_usbduxsub->outBuffer[chan] = data[i];
- this_usbduxsub->dux_commands[3] = chan;
- err = send_dux_commands(this_usbduxsub, SENDDACOMMANDS);
- if (err < 0) {
- up(&this_usbduxsub->sem);
- return err;
+ devpriv->dux_commands[1] = 1; /* num channels */
+ devpriv->dux_commands[2] = data[i]; /* value */
+ devpriv->dux_commands[3] = chan; /* channel number */
+ ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_DA_CMD);
+ if (ret < 0) {
+ up(&devpriv->sem);
+ return ret;
}
+ devpriv->ao_readback[chan] = data[i];
}
- up(&this_usbduxsub->sem);
+ up(&devpriv->sem);
- return i;
+ return insn->n;
}
-static int usbdux_ao_inttrig(struct comedi_device *dev,
- struct comedi_subdevice *s, unsigned int trignum)
+static int usbduxsigma_ao_inttrig(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned int trignum)
{
+ struct usbduxsigma_private *devpriv = dev->private;
int ret;
- struct usbduxsub *this_usbduxsub = dev->private;
- if (!this_usbduxsub)
- return -EFAULT;
-
- down(&this_usbduxsub->sem);
+ if (trignum != 0)
+ return -EINVAL;
- if (!(this_usbduxsub->probed)) {
- ret = -ENODEV;
- goto out;
- }
- if (trignum != 0) {
- dev_err(&this_usbduxsub->interface->dev,
- "comedi%d: usbdux_ao_inttrig: invalid trignum\n",
- dev->minor);
- ret = -EINVAL;
- goto out;
- }
- if (!(this_usbduxsub->ao_cmd_running)) {
- this_usbduxsub->ao_cmd_running = 1;
- ret = usbduxsub_submit_OutURBs(this_usbduxsub);
+ down(&devpriv->sem);
+ if (!devpriv->ao_cmd_running) {
+ ret = usbduxsigma_submit_urbs(dev, devpriv->ao_urbs,
+ devpriv->n_ao_urbs, 0);
if (ret < 0) {
- dev_err(&this_usbduxsub->interface->dev,
- "comedi%d: usbdux_ao_inttrig: submitURB: "
- "err=%d\n", dev->minor, ret);
- this_usbduxsub->ao_cmd_running = 0;
- goto out;
+ up(&devpriv->sem);
+ return ret;
}
+ devpriv->ao_cmd_running = 1;
s->async->inttrig = NULL;
- } else {
- dev_err(&this_usbduxsub->interface->dev,
- "comedi%d: ao_inttrig but acqu is already running.\n",
- dev->minor);
}
- ret = 1;
-out:
- up(&this_usbduxsub->sem);
- return ret;
+ up(&devpriv->sem);
+
+ return 1;
}
-static int usbdux_ao_cmdtest(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_cmd *cmd)
+static int usbduxsigma_ao_cmdtest(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_cmd *cmd)
{
- struct usbduxsub *this_usbduxsub = dev->private;
+ struct usbduxsigma_private *devpriv = dev->private;
int err = 0;
+ int high_speed;
unsigned int flags;
- if (!this_usbduxsub)
- return -EFAULT;
-
- if (!(this_usbduxsub->probed))
- return -ENODEV;
-
- dev_dbg(&this_usbduxsub->interface->dev,
- "comedi%d: usbdux_ao_cmdtest\n", dev->minor);
+ /* high speed conversions are not used yet */
+ high_speed = 0; /* (devpriv->high_speed) */
/* Step 1 : check if triggers are trivially valid */
err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
- if (0) { /* (this_usbduxsub->high_speed) */
+ if (high_speed) {
/*
* start immediately a new scan
* the sampling rate is set by the coversion rate
@@ -1538,8 +922,10 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev,
err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
- if (err)
+ if (err) {
+ up(&devpriv->sem);
return 1;
+ }
/* Step 2a : make sure trigger sources are unique */
@@ -1578,272 +964,186 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev,
if (err)
return 3;
- return 0;
-}
-
-static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
-{
- struct comedi_cmd *cmd = &s->async->cmd;
- unsigned int chan, gain;
- int i, ret;
- struct usbduxsub *this_usbduxsub = dev->private;
-
- if (!this_usbduxsub)
- return -EFAULT;
+ /* Step 4: fix up any arguments */
- down(&this_usbduxsub->sem);
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
- dev_dbg(&this_usbduxsub->interface->dev,
- "comedi%d: %s\n", dev->minor, __func__);
-
- /* set current channel of the running acquisition to zero */
- s->async->cur_chan = 0;
- for (i = 0; i < cmd->chanlist_len; ++i) {
- chan = CR_CHAN(cmd->chanlist[i]);
- gain = CR_RANGE(cmd->chanlist[i]);
- if (i >= NUMOUTCHANNELS) {
- dev_err(&this_usbduxsub->interface->dev,
- "comedi%d: %s: channel list too long\n",
- dev->minor, __func__);
- break;
- }
- this_usbduxsub->dac_commands[i] = chan;
- dev_dbg(&this_usbduxsub->interface->dev,
- "comedi%d: dac command for ch %d is %x\n",
- dev->minor, i, this_usbduxsub->dac_commands[i]);
- }
-
- /* we count in steps of 1ms (125us) */
- /* 125us mode not used yet */
- if (0) { /* (this_usbduxsub->high_speed) */
- /* 125us */
+ /* we count in timer steps */
+ if (high_speed) {
/* timing of the conversion itself: every 125 us */
- this_usbduxsub->ao_timer = cmd->convert_arg / 125000;
+ devpriv->ao_timer = cmd->convert_arg / 125000;
} else {
- /* 1ms */
- /* timing of the scan: we get all channels at once */
- this_usbduxsub->ao_timer = cmd->scan_begin_arg / 1000000;
- dev_dbg(&this_usbduxsub->interface->dev,
- "comedi%d: scan_begin_src=%d, scan_begin_arg=%d, "
- "convert_src=%d, convert_arg=%d\n", dev->minor,
- cmd->scan_begin_src, cmd->scan_begin_arg,
- cmd->convert_src, cmd->convert_arg);
- dev_dbg(&this_usbduxsub->interface->dev,
- "comedi%d: ao_timer=%d (ms)\n",
- dev->minor, this_usbduxsub->ao_timer);
- if (this_usbduxsub->ao_timer < 1) {
- dev_err(&this_usbduxsub->interface->dev,
- "comedi%d: usbdux: ao_timer=%d, "
- "scan_begin_arg=%d. "
- "Not properly tested by cmdtest?\n",
- dev->minor, this_usbduxsub->ao_timer,
- cmd->scan_begin_arg);
- up(&this_usbduxsub->sem);
- return -EINVAL;
- }
+ /*
+ * timing of the scan: every 1ms
+ * we get all channels at once
+ */
+ devpriv->ao_timer = cmd->scan_begin_arg / 1000000;
}
- this_usbduxsub->ao_counter = this_usbduxsub->ao_timer;
+ if (devpriv->ao_timer < 1)
+ err |= -EINVAL;
if (cmd->stop_src == TRIG_COUNT) {
- /* not continuous */
- /* counter */
- /* high speed also scans everything at once */
- if (0) { /* (this_usbduxsub->high_speed) */
- this_usbduxsub->ao_sample_count =
- (cmd->stop_arg) * (cmd->scan_end_arg);
+ /* not continuous, use counter */
+ if (high_speed) {
+ /* high speed also scans everything at once */
+ devpriv->ao_sample_count = cmd->stop_arg *
+ cmd->scan_end_arg;
} else {
- /* there's no scan as the scan has been */
- /* perf inside the FX2 */
- /* data arrives as one packet */
- this_usbduxsub->ao_sample_count = cmd->stop_arg;
+ /*
+ * There's no scan as the scan has been
+ * handled inside the FX2. Data arrives as
+ * one packet.
+ */
+ devpriv->ao_sample_count = cmd->stop_arg;
}
- this_usbduxsub->ao_continuous = 0;
+ devpriv->ao_continuous = 0;
} else {
/* continuous acquisition */
- this_usbduxsub->ao_continuous = 1;
- this_usbduxsub->ao_sample_count = 0;
+ devpriv->ao_continuous = 1;
+ devpriv->ao_sample_count = 0;
}
+ if (err)
+ return 4;
+
+ return 0;
+}
+
+static int usbduxsigma_ao_cmd(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ struct usbduxsigma_private *devpriv = dev->private;
+ struct comedi_cmd *cmd = &s->async->cmd;
+ int ret;
+ int i;
+
+ down(&devpriv->sem);
+
+ /* set current channel of the running acquisition to zero */
+ s->async->cur_chan = 0;
+ for (i = 0; i < cmd->chanlist_len; ++i)
+ devpriv->dac_commands[i] = CR_CHAN(cmd->chanlist[i]);
+
+ devpriv->ao_counter = devpriv->ao_timer;
+
if (cmd->start_src == TRIG_NOW) {
/* enable this acquisition operation */
- this_usbduxsub->ao_cmd_running = 1;
- ret = usbduxsub_submit_OutURBs(this_usbduxsub);
+ ret = usbduxsigma_submit_urbs(dev, devpriv->ao_urbs,
+ devpriv->n_ao_urbs, 0);
if (ret < 0) {
- this_usbduxsub->ao_cmd_running = 0;
- /* fixme: unlink here?? */
- up(&this_usbduxsub->sem);
+ up(&devpriv->sem);
return ret;
}
s->async->inttrig = NULL;
- } else {
- /* TRIG_INT */
- /* submit the urbs later */
- /* wait for an internal signal */
- s->async->inttrig = usbdux_ao_inttrig;
+ devpriv->ao_cmd_running = 1;
+ } else { /* TRIG_INT */
+ /* wait for an internal signal and submit the urbs later */
+ s->async->inttrig = usbduxsigma_ao_inttrig;
}
- up(&this_usbduxsub->sem);
+ up(&devpriv->sem);
+
return 0;
}
-static int usbdux_dio_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int usbduxsigma_dio_insn_config(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *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. */
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int mask = 1 << chan;
switch (data[0]) {
case INSN_CONFIG_DIO_OUTPUT:
- s->io_bits |= 1 << chan; /* 1 means Out */
+ s->io_bits |= mask;
break;
case INSN_CONFIG_DIO_INPUT:
- s->io_bits &= ~(1 << chan);
+ s->io_bits &= ~mask;
break;
case INSN_CONFIG_DIO_QUERY:
- data[1] =
- (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
+ data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
break;
default:
return -EINVAL;
break;
}
- /* we don't tell the firmware here as it would take 8 frames */
- /* to submit the information. We do it in the insn_bits. */
+
+ /*
+ * We don't tell the firmware here as it would take 8 frames
+ * to submit the information. We do it in the (*insn_bits).
+ */
return insn->n;
}
-static int usbdux_dio_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
+static int usbduxsigma_dio_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
+ struct usbduxsigma_private *devpriv = dev->private;
+ unsigned int mask = data[0];
+ unsigned int bits = data[1];
+ int ret;
- struct usbduxsub *this_usbduxsub = dev->private;
- int err;
+ down(&devpriv->sem);
- if (!this_usbduxsub)
- return -EFAULT;
+ s->state &= ~mask;
+ s->state |= (bits & mask);
- down(&this_usbduxsub->sem);
+ devpriv->dux_commands[1] = s->io_bits & 0xff;
+ devpriv->dux_commands[4] = s->state & 0xff;
+ devpriv->dux_commands[2] = (s->io_bits >> 8) & 0xff;
+ devpriv->dux_commands[5] = (s->state >> 8) & 0xff;
+ devpriv->dux_commands[3] = (s->io_bits >> 16) & 0xff;
+ devpriv->dux_commands[6] = (s->state >> 16) & 0xff;
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
+ ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_DIO_BITS_CMD);
+ if (ret < 0)
+ goto done;
+ ret = usbduxsigma_receive_cmd(dev, USBDUXSIGMA_DIO_BITS_CMD);
+ if (ret < 0)
+ goto done;
- /* The insn data is a mask in data[0] and the new data
- * in data[1], each channel cooresponding to a bit. */
- s->state &= ~data[0];
- s->state |= data[0] & data[1];
- /* The commands are 8 bits wide */
- this_usbduxsub->dux_commands[1] = (s->io_bits) & 0x000000FF;
- this_usbduxsub->dux_commands[4] = (s->state) & 0x000000FF;
- this_usbduxsub->dux_commands[2] = ((s->io_bits) & 0x0000FF00) >> 8;
- this_usbduxsub->dux_commands[5] = ((s->state) & 0x0000FF00) >> 8;
- this_usbduxsub->dux_commands[3] = ((s->io_bits) & 0x00FF0000) >> 16;
- this_usbduxsub->dux_commands[6] = ((s->state) & 0x00FF0000) >> 16;
-
- /* This command also tells the firmware to return */
- /* the digital input lines */
- err = send_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND);
- if (err < 0) {
- up(&this_usbduxsub->sem);
- return err;
- }
- err = receive_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND);
- if (err < 0) {
- up(&this_usbduxsub->sem);
- return err;
- }
+ s->state = devpriv->insn_buf[1] |
+ (devpriv->insn_buf[2] << 8) |
+ (devpriv->insn_buf[3] << 16);
- data[1] = (((unsigned int)(this_usbduxsub->insnBuffer[1]))&0xff) |
- ((((unsigned int)(this_usbduxsub->insnBuffer[2]))&0xff) << 8) |
- ((((unsigned int)(this_usbduxsub->insnBuffer[3]))&0xff) << 16);
+ data[1] = s->state;
+ ret = insn->n;
- s->state = data[1];
+done:
+ up(&devpriv->sem);
- up(&this_usbduxsub->sem);
- return insn->n;
+ return ret;
}
-/***********************************/
-/* PWM */
-
-static int usbduxsub_unlink_PwmURBs(struct usbduxsub *usbduxsub_tmp)
+static void usbduxsigma_pwm_stop(struct comedi_device *dev, int do_unlink)
{
- int err = 0;
+ struct usbduxsigma_private *devpriv = dev->private;
- if (usbduxsub_tmp && usbduxsub_tmp->urbPwm) {
- if (usbduxsub_tmp->urbPwm)
- usb_kill_urb(usbduxsub_tmp->urbPwm);
- dev_dbg(&usbduxsub_tmp->interface->dev,
- "comedi: unlinked PwmURB: res=%d\n", err);
+ if (do_unlink) {
+ if (devpriv->pwm_urb)
+ usb_kill_urb(devpriv->pwm_urb);
}
- return err;
-}
-
-/* This cancels a running acquisition operation
- * in any context.
- */
-static int usbdux_pwm_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
-{
- int ret = 0;
- if (!this_usbduxsub)
- return -EFAULT;
-
- dev_dbg(&this_usbduxsub->interface->dev, "comedi: %s\n", __func__);
- if (do_unlink)
- ret = usbduxsub_unlink_PwmURBs(this_usbduxsub);
-
- this_usbduxsub->pwm_cmd_running = 0;
-
- return ret;
+ devpriv->pwm_cmd_running = 0;
}
-/* force unlink - is called by comedi */
-static int usbdux_pwm_cancel(struct comedi_device *dev,
- struct comedi_subdevice *s)
+static int usbduxsigma_pwm_cancel(struct comedi_device *dev,
+ struct comedi_subdevice *s)
{
- struct usbduxsub *this_usbduxsub = dev->private;
- int res = 0;
+ struct usbduxsigma_private *devpriv = dev->private;
/* unlink only if it is really running */
- res = usbdux_pwm_stop(this_usbduxsub, this_usbduxsub->pwm_cmd_running);
+ usbduxsigma_pwm_stop(dev, devpriv->pwm_cmd_running);
- dev_dbg(&this_usbduxsub->interface->dev,
- "comedi %d: sending pwm off command to the usb device.\n",
- dev->minor);
- res = send_dux_commands(this_usbduxsub, SENDPWMOFF);
- if (res < 0)
- return res;
-
- return res;
+ return usbbuxsigma_send_cmd(dev, USBDUXSIGMA_PWM_OFF_CMD);
}
-static void usbduxsub_pwm_irq(struct urb *urb)
+static void usbduxsigma_pwm_urb_complete(struct urb *urb)
{
+ struct comedi_device *dev = urb->context;
+ struct usbduxsigma_private *devpriv = dev->private;
int ret;
- struct usbduxsub *this_usbduxsub;
- struct comedi_device *this_comedidev;
- struct comedi_subdevice *s;
-
- /* printk(KERN_DEBUG "PWM: IRQ\n"); */
-
- /* the context variable points to the subdevice */
- this_comedidev = urb->context;
- /* the private structure of the subdevice is struct usbduxsub */
- this_usbduxsub = this_comedidev->private;
-
- s = &this_comedidev->subdevices[SUBDEV_DA];
switch (urb->status) {
case 0:
@@ -1854,260 +1154,180 @@ static void usbduxsub_pwm_irq(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
case -ECONNABORTED:
- /*
- * after an unlink command, unplug, ... etc
- * no unlink needed here. Already shutting down.
- */
- if (this_usbduxsub->pwm_cmd_running)
- usbdux_pwm_stop(this_usbduxsub, 0);
-
+ /* happens after an unlink command */
+ if (devpriv->pwm_cmd_running)
+ usbduxsigma_pwm_stop(dev, 0); /* w/o unlink */
return;
default:
/* a real error */
- if (this_usbduxsub->pwm_cmd_running) {
- dev_err(&this_usbduxsub->interface->dev,
- "comedi_: Non-zero urb status received in "
- "pwm intr context: %d\n", urb->status);
- usbdux_pwm_stop(this_usbduxsub, 0);
+ if (devpriv->pwm_cmd_running) {
+ dev_err(dev->class_dev,
+ "%s: non-zero urb status (%d)\n",
+ __func__, urb->status);
+ usbduxsigma_pwm_stop(dev, 0); /* w/o unlink */
}
return;
}
- /* are we actually running? */
- if (!(this_usbduxsub->pwm_cmd_running))
+ if (!devpriv->pwm_cmd_running)
return;
- urb->transfer_buffer_length = this_usbduxsub->sizePwmBuf;
- urb->dev = this_usbduxsub->usbdev;
+ urb->transfer_buffer_length = devpriv->pwm_buf_sz;
+ urb->dev = comedi_to_usb_dev(dev);
urb->status = 0;
- if (this_usbduxsub->pwm_cmd_running) {
- ret = usb_submit_urb(urb, GFP_ATOMIC);
- if (ret < 0) {
- dev_err(&this_usbduxsub->interface->dev,
- "comedi_: pwm urb resubm failed in int-cont. "
- "ret=%d", ret);
- if (ret == EL2NSYNC)
- dev_err(&this_usbduxsub->interface->dev,
- "buggy USB host controller or bug in "
- "IRQ handling!\n");
-
- /* don't do an unlink here */
- usbdux_pwm_stop(this_usbduxsub, 0);
- }
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret < 0) {
+ dev_err(dev->class_dev, "%s: urb resubmit failed (%d)\n",
+ __func__, ret);
+ if (ret == EL2NSYNC)
+ dev_err(dev->class_dev,
+ "buggy USB host controller or bug in IRQ handler\n");
+ usbduxsigma_pwm_stop(dev, 0); /* w/o unlink */
}
}
-static int usbduxsub_submit_PwmURBs(struct usbduxsub *usbduxsub)
+static int usbduxsigma_submit_pwm_urb(struct comedi_device *dev)
{
- int errFlag;
-
- if (!usbduxsub)
- return -EFAULT;
-
- dev_dbg(&usbduxsub->interface->dev, "comedi_: submitting pwm-urb\n");
+ struct usb_device *usb = comedi_to_usb_dev(dev);
+ struct usbduxsigma_private *devpriv = dev->private;
+ struct urb *urb = devpriv->pwm_urb;
/* in case of a resubmission after an unlink... */
- usb_fill_bulk_urb(usbduxsub->urbPwm,
- usbduxsub->usbdev,
- usb_sndbulkpipe(usbduxsub->usbdev, PWM_EP),
- usbduxsub->urbPwm->transfer_buffer,
- usbduxsub->sizePwmBuf, usbduxsub_pwm_irq,
- usbduxsub->comedidev);
-
- errFlag = usb_submit_urb(usbduxsub->urbPwm, GFP_ATOMIC);
- if (errFlag) {
- dev_err(&usbduxsub->interface->dev,
- "comedi_: usbduxsigma: pwm: usb_submit_urb error %d\n",
- errFlag);
- return errFlag;
- }
- return 0;
+ usb_fill_bulk_urb(urb,
+ usb, usb_sndbulkpipe(usb, USBDUXSIGMA_PWM_OUT_EP),
+ urb->transfer_buffer, devpriv->pwm_buf_sz,
+ usbduxsigma_pwm_urb_complete, dev);
+
+ return usb_submit_urb(urb, GFP_ATOMIC);
}
-static int usbdux_pwm_period(struct comedi_device *dev,
- struct comedi_subdevice *s, unsigned int period)
+static int usbduxsigma_pwm_period(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned int period)
{
- struct usbduxsub *this_usbduxsub = dev->private;
+ struct usbduxsigma_private *devpriv = dev->private;
int fx2delay = 255;
if (period < MIN_PWM_PERIOD) {
- dev_err(&this_usbduxsub->interface->dev,
- "comedi%d: illegal period setting for pwm.\n",
- dev->minor);
return -EAGAIN;
} else {
- fx2delay = period / ((int)(6 * 512 * (1.0 / 0.033))) - 6;
- if (fx2delay > 255) {
- dev_err(&this_usbduxsub->interface->dev,
- "comedi%d: period %d for pwm is too low.\n",
- dev->minor, period);
+ fx2delay = (period / (6 * 512 * 1000 / 33)) - 6;
+ if (fx2delay > 255)
return -EAGAIN;
- }
}
- this_usbduxsub->pwmDelay = fx2delay;
- this_usbduxsub->pwmPeriod = period;
- dev_dbg(&this_usbduxsub->interface->dev, "%s: frequ=%d, period=%d\n",
- __func__, period, fx2delay);
+ devpriv->pwm_delay = fx2delay;
+ devpriv->pwm_period = period;
return 0;
}
-/* is called from insn so there's no need to do all the sanity checks */
-static int usbdux_pwm_start(struct comedi_device *dev,
- struct comedi_subdevice *s)
+static int usbduxsigma_pwm_start(struct comedi_device *dev,
+ struct comedi_subdevice *s)
{
- int ret, i;
- struct usbduxsub *this_usbduxsub = dev->private;
-
- dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: %s\n",
- dev->minor, __func__);
+ struct usbduxsigma_private *devpriv = dev->private;
+ int ret;
- if (this_usbduxsub->pwm_cmd_running) {
- /* already running */
+ if (devpriv->pwm_cmd_running)
return 0;
- }
- this_usbduxsub->dux_commands[1] = ((uint8_t) this_usbduxsub->pwmDelay);
- ret = send_dux_commands(this_usbduxsub, SENDPWMON);
+ devpriv->dux_commands[1] = devpriv->pwm_delay;
+ ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_PWM_ON_CMD);
if (ret < 0)
return ret;
- /* initialise the buffer */
- for (i = 0; i < this_usbduxsub->sizePwmBuf; i++)
- ((char *)(this_usbduxsub->urbPwm->transfer_buffer))[i] = 0;
+ memset(devpriv->pwm_urb->transfer_buffer, 0, devpriv->pwm_buf_sz);
- this_usbduxsub->pwm_cmd_running = 1;
- ret = usbduxsub_submit_PwmURBs(this_usbduxsub);
- if (ret < 0) {
- this_usbduxsub->pwm_cmd_running = 0;
+ ret = usbduxsigma_submit_pwm_urb(dev);
+ if (ret < 0)
return ret;
- }
+ devpriv->pwm_cmd_running = 1;
+
return 0;
}
-/* generates the bit pattern for PWM with the optional sign bit */
-static int usbdux_pwm_pattern(struct comedi_device *dev,
- struct comedi_subdevice *s, int channel,
- unsigned int value, unsigned int sign)
+static int usbduxsigma_pwm_pattern(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned int chan,
+ unsigned int value,
+ unsigned int sign)
{
- struct usbduxsub *this_usbduxsub = dev->private;
- int i, szbuf;
- char *pBuf;
- char pwm_mask;
- char sgn_mask;
- char c;
-
- if (!this_usbduxsub)
- return -EFAULT;
-
- /* this is the DIO bit which carries the PWM data */
- pwm_mask = (1 << channel);
- /* this is the DIO bit which carries the optional direction bit */
- sgn_mask = (16 << channel);
- /* this is the buffer which will be filled with the with bit */
- /* pattern for one period */
- szbuf = this_usbduxsub->sizePwmBuf;
- pBuf = (char *)(this_usbduxsub->urbPwm->transfer_buffer);
+ struct usbduxsigma_private *devpriv = dev->private;
+ char pwm_mask = (1 << chan); /* DIO bit for the PWM data */
+ char sgn_mask = (16 << chan); /* DIO bit for the sign */
+ char *buf = (char *)(devpriv->pwm_urb->transfer_buffer);
+ int szbuf = devpriv->pwm_buf_sz;
+ int i;
+
for (i = 0; i < szbuf; i++) {
- c = *pBuf;
- /* reset bits */
- c = c & (~pwm_mask);
- /* set the bit as long as the index is lower than the value */
+ char c = *buf;
+
+ c &= ~pwm_mask;
if (i < value)
- c = c | pwm_mask;
- /* set the optional sign bit for a relay */
- if (!sign) {
- /* positive value */
- c = c & (~sgn_mask);
- } else {
- /* negative value */
- c = c | sgn_mask;
- }
- *(pBuf++) = c;
+ c |= pwm_mask;
+ if (!sign)
+ c &= ~sgn_mask;
+ else
+ c |= sgn_mask;
+ *buf++ = c;
}
return 1;
}
-static int usbdux_pwm_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int usbduxsigma_pwm_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct usbduxsub *this_usbduxsub = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
- if (!this_usbduxsub)
- return -EFAULT;
-
- if ((insn->n) != 1) {
- /*
- * doesn't make sense to have more than one value here because
- * it would just overwrite the PWM buffer a couple of times
- */
+ /*
+ * It doesn't make sense to support more than one value here
+ * because it would just overwrite the PWM buffer.
+ */
+ if (insn->n != 1)
return -EINVAL;
- }
/*
- * the sign is set via a special INSN only, this gives us 8 bits for
- * normal operation
- * relay sign 0 by default
+ * The sign is set via a special INSN only, this gives us 8 bits
+ * for normal operation, sign is 0 by default.
*/
- return usbdux_pwm_pattern(dev, s, CR_CHAN(insn->chanspec), data[0], 0);
+ return usbduxsigma_pwm_pattern(dev, s, chan, data[0], 0);
}
-static int usbdux_pwm_read(struct comedi_device *x1,
- struct comedi_subdevice *x2, struct comedi_insn *x3,
- unsigned int *x4)
+static int usbduxsigma_pwm_config(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- /* not needed */
- return -EINVAL;
-};
+ struct usbduxsigma_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
-/* switches on/off PWM */
-static int usbdux_pwm_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- struct usbduxsub *this_usbduxsub = dev->private;
switch (data[0]) {
case INSN_CONFIG_ARM:
- /* switch it on */
- dev_dbg(&this_usbduxsub->interface->dev,
- "comedi%d: %s: pwm on\n", dev->minor, __func__);
/*
* if not zero the PWM is limited to a certain time which is
* not supported here
*/
if (data[1] != 0)
return -EINVAL;
- return usbdux_pwm_start(dev, s);
+ return usbduxsigma_pwm_start(dev, s);
case INSN_CONFIG_DISARM:
- dev_dbg(&this_usbduxsub->interface->dev,
- "comedi%d: %s: pwm off\n", dev->minor, __func__);
- return usbdux_pwm_cancel(dev, s);
+ return usbduxsigma_pwm_cancel(dev, s);
case INSN_CONFIG_GET_PWM_STATUS:
- /*
- * to check if the USB transmission has failed or in case PWM
- * was limited to n cycles to check if it has terminated
- */
- data[1] = this_usbduxsub->pwm_cmd_running;
+ data[1] = devpriv->pwm_cmd_running;
return 0;
case INSN_CONFIG_PWM_SET_PERIOD:
- dev_dbg(&this_usbduxsub->interface->dev,
- "comedi%d: %s: setting period\n", dev->minor,
- __func__);
- return usbdux_pwm_period(dev, s, data[1]);
+ return usbduxsigma_pwm_period(dev, s, data[1]);
case INSN_CONFIG_PWM_GET_PERIOD:
- data[1] = this_usbduxsub->pwmPeriod;
+ data[1] = devpriv->pwm_period;
return 0;
case INSN_CONFIG_PWM_SET_H_BRIDGE:
- /* value in the first byte and the sign in the second for a
- relay */
- return usbdux_pwm_pattern(dev, s,
- /* the channel number */
- CR_CHAN(insn->chanspec),
- /* actual PWM data */
- data[1],
- /* just a sign */
- (data[2] != 0));
+ /*
+ * data[1] = value
+ * data[2] = sign (for a relay)
+ */
+ return usbduxsigma_pwm_pattern(dev, s, chan,
+ data[1], (data[2] != 0));
case INSN_CONFIG_PWM_GET_H_BRIDGE:
/* values are not kept in this driver, nothing to return */
return -EINVAL;
@@ -2115,542 +1335,412 @@ static int usbdux_pwm_config(struct comedi_device *dev,
return -EINVAL;
}
-/* end of PWM */
-/*****************************************************************/
-
-static void tidy_up(struct usbduxsub *usbduxsub_tmp)
+static int usbduxsigma_getstatusinfo(struct comedi_device *dev, int chan)
{
- int i;
+ struct usbduxsigma_private *devpriv = dev->private;
+ uint8_t sysred;
+ uint32_t val;
+ int ret;
- if (!usbduxsub_tmp)
- return;
- dev_dbg(&usbduxsub_tmp->interface->dev, "comedi_: tiding up\n");
+ switch (chan) {
+ default:
+ case 0:
+ sysred = 0; /* ADC zero */
+ break;
+ case 1:
+ sysred = 1; /* ADC offset */
+ break;
+ case 2:
+ sysred = 4; /* VCC */
+ break;
+ case 3:
+ sysred = 8; /* temperature */
+ break;
+ case 4:
+ sysred = 16; /* gain */
+ break;
+ case 5:
+ sysred = 32; /* ref */
+ break;
+ }
- /* shows the usb subsystem that the driver is down */
- if (usbduxsub_tmp->interface)
- usb_set_intfdata(usbduxsub_tmp->interface, NULL);
+ devpriv->dux_commands[1] = 0x12; /* CONFIG0 */
+ devpriv->dux_commands[2] = 0x80; /* CONFIG1: 2kHz sampling rate */
+ devpriv->dux_commands[3] = 0x00; /* CONFIG3: diff. channels off */
+ devpriv->dux_commands[4] = 0;
+ devpriv->dux_commands[5] = 0;
+ devpriv->dux_commands[6] = sysred;
+ ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD);
+ if (ret < 0)
+ return ret;
- usbduxsub_tmp->probed = 0;
+ ret = usbduxsigma_receive_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD);
+ if (ret < 0)
+ return ret;
- if (usbduxsub_tmp->urbIn) {
- if (usbduxsub_tmp->ai_cmd_running) {
- usbduxsub_tmp->ai_cmd_running = 0;
- usbduxsub_unlink_InURBs(usbduxsub_tmp);
- }
- for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) {
- kfree(usbduxsub_tmp->urbIn[i]->transfer_buffer);
- usbduxsub_tmp->urbIn[i]->transfer_buffer = NULL;
- usb_kill_urb(usbduxsub_tmp->urbIn[i]);
- usb_free_urb(usbduxsub_tmp->urbIn[i]);
- usbduxsub_tmp->urbIn[i] = NULL;
- }
- kfree(usbduxsub_tmp->urbIn);
- usbduxsub_tmp->urbIn = NULL;
- }
- if (usbduxsub_tmp->urbOut) {
- if (usbduxsub_tmp->ao_cmd_running) {
- usbduxsub_tmp->ao_cmd_running = 0;
- usbduxsub_unlink_OutURBs(usbduxsub_tmp);
- }
- for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) {
- if (usbduxsub_tmp->urbOut[i]->transfer_buffer) {
- kfree(usbduxsub_tmp->
- urbOut[i]->transfer_buffer);
- usbduxsub_tmp->urbOut[i]->transfer_buffer =
- NULL;
- }
- if (usbduxsub_tmp->urbOut[i]) {
- usb_kill_urb(usbduxsub_tmp->urbOut[i]);
- usb_free_urb(usbduxsub_tmp->urbOut[i]);
- usbduxsub_tmp->urbOut[i] = NULL;
- }
- }
- kfree(usbduxsub_tmp->urbOut);
- usbduxsub_tmp->urbOut = NULL;
- }
- if (usbduxsub_tmp->urbPwm) {
- if (usbduxsub_tmp->pwm_cmd_running) {
- usbduxsub_tmp->pwm_cmd_running = 0;
- usbduxsub_unlink_PwmURBs(usbduxsub_tmp);
- }
- kfree(usbduxsub_tmp->urbPwm->transfer_buffer);
- usbduxsub_tmp->urbPwm->transfer_buffer = NULL;
- usb_kill_urb(usbduxsub_tmp->urbPwm);
- usb_free_urb(usbduxsub_tmp->urbPwm);
- usbduxsub_tmp->urbPwm = NULL;
- }
- kfree(usbduxsub_tmp->inBuffer);
- usbduxsub_tmp->inBuffer = NULL;
- kfree(usbduxsub_tmp->insnBuffer);
- usbduxsub_tmp->insnBuffer = NULL;
- kfree(usbduxsub_tmp->outBuffer);
- usbduxsub_tmp->outBuffer = NULL;
- kfree(usbduxsub_tmp->dac_commands);
- usbduxsub_tmp->dac_commands = NULL;
- kfree(usbduxsub_tmp->dux_commands);
- usbduxsub_tmp->dux_commands = NULL;
- usbduxsub_tmp->ai_cmd_running = 0;
- usbduxsub_tmp->ao_cmd_running = 0;
- usbduxsub_tmp->pwm_cmd_running = 0;
+ /* 32 bits big endian from the A/D converter */
+ val = be32_to_cpu(*((int32_t *)((devpriv->insn_buf)+1)));
+ val &= 0x00ffffff; /* strip status byte */
+ val ^= 0x00800000; /* convert to unsigned */
+
+ return (int)val;
}
-static int usbduxsigma_attach_common(struct comedi_device *dev,
- struct usbduxsub *uds)
+static int usbduxsigma_attach_common(struct comedi_device *dev)
{
- int ret;
+ struct usbduxsigma_private *devpriv = dev->private;
struct comedi_subdevice *s;
int n_subdevs;
int offset;
+ int ret;
- down(&uds->sem);
- /* pointer back to the corresponding comedi device */
- uds->comedidev = dev;
+ down(&devpriv->sem);
- /* set number of subdevices */
- if (uds->high_speed)
+ if (devpriv->high_speed)
n_subdevs = 4; /* with pwm */
else
n_subdevs = 3; /* without pwm */
ret = comedi_alloc_subdevices(dev, n_subdevs);
if (ret) {
- up(&uds->sem);
+ up(&devpriv->sem);
return ret;
}
- /* private structure is also simply the usb-structure */
- dev->private = uds;
- /* the first subdevice is the A/D converter */
- s = &dev->subdevices[SUBDEV_AD];
- /* the URBs get the comedi subdevice */
- /* which is responsible for reading */
- /* this is the subdevice which reads data */
+
+ /* Analog Input subdevice */
+ s = &dev->subdevices[0];
dev->read_subdev = s;
- /* the subdevice receives as private structure the */
- /* usb-structure */
- s->private = NULL;
- /* analog input */
- s->type = COMEDI_SUBD_AI;
- /* readable and ref is to ground, 32 bit wide data! */
- s->subdev_flags = SDF_READABLE | SDF_GROUND |
- SDF_CMD_READ | SDF_LSAMPL;
- /* 16 A/D channels */
- s->n_chan = NUMCHANNELS;
- /* length of the channellist */
- s->len_chanlist = NUMCHANNELS;
- /* callback functions */
- s->insn_read = usbdux_ai_insn_read;
- s->do_cmdtest = usbdux_ai_cmdtest;
- s->do_cmd = usbdux_ai_cmd;
- s->cancel = usbdux_ai_cancel;
- /* max value from the A/D converter (24bit) */
- s->maxdata = 0x00FFFFFF;
- /* range table to convert to physical units */
- s->range_table = (&range_usbdux_ai_range);
- /* analog output subdevice */
- s = &dev->subdevices[SUBDEV_DA];
- /* analog out */
- s->type = COMEDI_SUBD_AO;
- /* backward pointer */
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ | SDF_LSAMPL;
+ s->n_chan = NUMCHANNELS;
+ s->len_chanlist = NUMCHANNELS;
+ s->maxdata = 0x00ffffff;
+ s->range_table = &usbduxsigma_ai_range;
+ s->insn_read = usbduxsigma_ai_insn_read;
+ s->do_cmdtest = usbduxsigma_ai_cmdtest;
+ s->do_cmd = usbduxsigma_ai_cmd;
+ s->cancel = usbduxsigma_ai_cancel;
+
+ /* Analog Output subdevice */
+ s = &dev->subdevices[1];
dev->write_subdev = s;
- /* the subdevice receives as private structure the */
- /* usb-structure */
- s->private = NULL;
- /* are writable */
- s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
- /* 4 channels */
- s->n_chan = 4;
- /* length of the channellist */
- s->len_chanlist = 4;
- /* 8 bit resolution */
- s->maxdata = 0x00ff;
- /* unipolar range */
- s->range_table = &range_unipolar2_5;
- /* callback */
- s->do_cmdtest = usbdux_ao_cmdtest;
- s->do_cmd = usbdux_ao_cmd;
- s->cancel = usbdux_ao_cancel;
- s->insn_read = usbdux_ao_insn_read;
- s->insn_write = usbdux_ao_insn_write;
- /* digital I/O subdevice */
- s = &dev->subdevices[SUBDEV_DIO];
- s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- /* 8 external and 16 internal channels */
- s->n_chan = 24;
- s->maxdata = 1;
- s->range_table = (&range_digital);
- s->insn_bits = usbdux_dio_insn_bits;
- s->insn_config = usbdux_dio_insn_config;
- /* we don't use it */
- s->private = NULL;
- if (uds->high_speed) {
- /* timer / pwm subdevice */
- s = &dev->subdevices[SUBDEV_PWM];
- s->type = COMEDI_SUBD_PWM;
- s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE;
- s->n_chan = 8;
- /* this defines the max duty cycle resolution */
- s->maxdata = uds->sizePwmBuf;
- s->insn_write = usbdux_pwm_write;
- s->insn_read = usbdux_pwm_read;
- s->insn_config = usbdux_pwm_config;
- usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
- }
- /* finally decide that it's attached */
- uds->attached = 1;
- up(&uds->sem);
- offset = usbdux_getstatusinfo(dev, 0);
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
+ s->n_chan = USBDUXSIGMA_NUM_AO_CHAN;
+ s->len_chanlist = s->n_chan;
+ s->maxdata = 0x00ff;
+ s->range_table = &range_unipolar2_5;
+ s->insn_write = usbduxsigma_ao_insn_write;
+ s->insn_read = usbduxsigma_ao_insn_read;
+ s->do_cmdtest = usbduxsigma_ao_cmdtest;
+ s->do_cmd = usbduxsigma_ao_cmd;
+ s->cancel = usbduxsigma_ao_cancel;
+
+ /* Digital I/O subdevice */
+ s = &dev->subdevices[2];
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 24;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = usbduxsigma_dio_insn_bits;
+ s->insn_config = usbduxsigma_dio_insn_config;
+
+ if (devpriv->high_speed) {
+ /* Timer / pwm subdevice */
+ s = &dev->subdevices[3];
+ s->type = COMEDI_SUBD_PWM;
+ s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE;
+ s->n_chan = 8;
+ s->maxdata = devpriv->pwm_buf_sz;
+ s->insn_write = usbduxsigma_pwm_write;
+ s->insn_config = usbduxsigma_pwm_config;
+
+ usbduxsigma_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
+ }
+
+ up(&devpriv->sem);
+
+ offset = usbduxsigma_getstatusinfo(dev, 0);
if (offset < 0)
- dev_err(&uds->interface->dev,
- "Communication to USBDUXSIGMA failed! Check firmware and cabling.");
- dev_info(&uds->interface->dev,
- "comedi%d: attached, ADC_zero = %x\n", dev->minor, offset);
+ dev_err(dev->class_dev,
+ "Communication to USBDUXSIGMA failed! Check firmware and cabling\n");
+
+ dev_info(dev->class_dev, "attached, ADC_zero = %x\n", offset);
+
return 0;
}
-static int usbduxsigma_auto_attach(struct comedi_device *dev,
- unsigned long context_unused)
+static int usbduxsigma_firmware_upload(struct comedi_device *dev,
+ const u8 *data, size_t size,
+ unsigned long context)
{
- struct usb_interface *uinterf = comedi_to_usb_interface(dev);
+ struct usb_device *usb = comedi_to_usb_dev(dev);
+ uint8_t *buf;
+ uint8_t *tmp;
int ret;
- struct usbduxsub *uds;
- dev->private = NULL;
- down(&start_stop_sem);
- uds = usb_get_intfdata(uinterf);
- if (!uds || !uds->probed) {
- dev_err(dev->class_dev,
- "usbduxsigma: error: auto_attach failed, not connected\n");
- ret = -ENODEV;
- } else if (uds->attached) {
- dev_err(dev->class_dev,
- "usbduxsigma: error: auto_attach failed, already attached\n");
- ret = -ENODEV;
- } else
- ret = usbduxsigma_attach_common(dev, uds);
- up(&start_stop_sem);
- return ret;
-}
+ if (!data)
+ return 0;
-static void usbduxsigma_detach(struct comedi_device *dev)
-{
- struct usbduxsub *usb = dev->private;
-
- if (usb) {
- down(&usb->sem);
- dev->private = NULL;
- usb->attached = 0;
- usb->comedidev = NULL;
- up(&usb->sem);
+ if (size > FIRMWARE_MAX_LEN) {
+ dev_err(dev->class_dev, "firmware binary too large for FX2\n");
+ return -ENOMEM;
}
-}
-static struct comedi_driver usbduxsigma_driver = {
- .driver_name = "usbduxsigma",
- .module = THIS_MODULE,
- .auto_attach = usbduxsigma_auto_attach,
- .detach = usbduxsigma_detach,
-};
+ /* we generate a local buffer for the firmware */
+ buf = kmemdup(data, size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
-static void usbdux_firmware_request_complete_handler(const struct firmware *fw,
- void *context)
-{
- struct usbduxsub *usbduxsub_tmp = context;
- struct usb_interface *uinterf = usbduxsub_tmp->interface;
- int ret;
+ /* we need a malloc'ed buffer for usb_control_msg() */
+ tmp = kmalloc(1, GFP_KERNEL);
+ if (!tmp) {
+ kfree(buf);
+ return -ENOMEM;
+ }
- if (fw == NULL) {
- dev_err(&uinterf->dev,
- "Firmware complete handler without firmware!\n");
- return;
+ /* stop the current firmware on the device */
+ *tmp = 1; /* 7f92 to one */
+ ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
+ USBDUXSUB_FIRMWARE,
+ VENDOR_DIR_OUT,
+ USBDUXSUB_CPUCS, 0x0000,
+ tmp, 1,
+ BULK_TIMEOUT);
+ if (ret < 0) {
+ dev_err(dev->class_dev, "can not stop firmware\n");
+ goto done;
}
- /*
- * we need to upload the firmware here because fw will be
- * freed once we've left this function
- */
- ret = firmwareUpload(usbduxsub_tmp, fw->data, fw->size);
+ /* upload the new firmware to the device */
+ ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
+ USBDUXSUB_FIRMWARE,
+ VENDOR_DIR_OUT,
+ 0, 0x0000,
+ buf, size,
+ BULK_TIMEOUT);
+ if (ret < 0) {
+ dev_err(dev->class_dev, "firmware upload failed\n");
+ goto done;
+ }
+
+ /* start the new firmware on the device */
+ *tmp = 0; /* 7f92 to zero */
+ ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
+ USBDUXSUB_FIRMWARE,
+ VENDOR_DIR_OUT,
+ USBDUXSUB_CPUCS, 0x0000,
+ tmp, 1,
+ BULK_TIMEOUT);
+ if (ret < 0)
+ dev_err(dev->class_dev, "can not start firmware\n");
- if (ret) {
- dev_err(&uinterf->dev,
- "Could not upload firmware (err=%d)\n", ret);
- goto out;
- }
- comedi_usb_auto_config(uinterf, &usbduxsigma_driver, 0);
-out:
- release_firmware(fw);
+done:
+ kfree(tmp);
+ kfree(buf);
+ return ret;
}
-static int usbduxsigma_usb_probe(struct usb_interface *uinterf,
- const struct usb_device_id *id)
+static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev)
{
- struct usb_device *udev = interface_to_usbdev(uinterf);
- struct device *dev = &uinterf->dev;
+ struct usb_device *usb = comedi_to_usb_dev(dev);
+ struct usbduxsigma_private *devpriv = dev->private;
+ struct urb *urb;
int i;
- int index;
- int ret;
-
- dev_dbg(dev, "comedi_: usbdux_: "
- "finding a free structure for the usb-device\n");
-
- down(&start_stop_sem);
- /* look for a free place in the usbdux array */
- index = -1;
- for (i = 0; i < NUMUSBDUX; i++) {
- if (!(usbduxsub[i].probed)) {
- index = i;
- break;
- }
- }
-
- /* no more space */
- if (index == -1) {
- dev_err(dev, "Too many usbduxsigma-devices connected.\n");
- up(&start_stop_sem);
- return -EMFILE;
- }
- dev_dbg(dev, "comedi_: usbdux: "
- "usbduxsub[%d] is ready to connect to comedi.\n", index);
-
- sema_init(&(usbduxsub[index].sem), 1);
- /* save a pointer to the usb device */
- usbduxsub[index].usbdev = udev;
- /* save the interface itself */
- usbduxsub[index].interface = uinterf;
- /* get the interface number from the interface */
- usbduxsub[index].ifnum = uinterf->altsetting->desc.bInterfaceNumber;
- /* hand the private data over to the usb subsystem */
- /* will be needed for disconnect */
- usb_set_intfdata(uinterf, &(usbduxsub[index]));
-
- dev_dbg(dev, "comedi_: usbdux: ifnum=%d\n", usbduxsub[index].ifnum);
-
- /* test if it is high speed (USB 2.0) */
- usbduxsub[index].high_speed =
- (usbduxsub[index].usbdev->speed == USB_SPEED_HIGH);
-
- /* create space for the commands of the DA converter */
- usbduxsub[index].dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL);
- if (!usbduxsub[index].dac_commands) {
- tidy_up(&(usbduxsub[index]));
- up(&start_stop_sem);
- return -ENOMEM;
- }
- /* create space for the commands going to the usb device */
- usbduxsub[index].dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
- if (!usbduxsub[index].dux_commands) {
- tidy_up(&(usbduxsub[index]));
- up(&start_stop_sem);
- return -ENOMEM;
- }
- /* create space for the in buffer and set it to zero */
- usbduxsub[index].inBuffer = kzalloc(SIZEINBUF, GFP_KERNEL);
- if (!(usbduxsub[index].inBuffer)) {
- tidy_up(&(usbduxsub[index]));
- up(&start_stop_sem);
- return -ENOMEM;
- }
- /* create space of the instruction buffer */
- usbduxsub[index].insnBuffer = kzalloc(SIZEINSNBUF, GFP_KERNEL);
- if (!(usbduxsub[index].insnBuffer)) {
- tidy_up(&(usbduxsub[index]));
- up(&start_stop_sem);
+ devpriv->dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL);
+ devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
+ devpriv->in_buf = kzalloc(SIZEINBUF, GFP_KERNEL);
+ devpriv->insn_buf = kzalloc(SIZEINSNBUF, GFP_KERNEL);
+ devpriv->ai_urbs = kcalloc(devpriv->n_ai_urbs, sizeof(*urb),
+ GFP_KERNEL);
+ devpriv->ao_urbs = kcalloc(devpriv->n_ao_urbs, sizeof(*urb),
+ GFP_KERNEL);
+ if (!devpriv->dac_commands || !devpriv->dux_commands ||
+ !devpriv->in_buf || !devpriv->insn_buf ||
+ !devpriv->ai_urbs || !devpriv->ao_urbs)
return -ENOMEM;
- }
- /* create space for the outbuffer */
- usbduxsub[index].outBuffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
- if (!(usbduxsub[index].outBuffer)) {
- tidy_up(&(usbduxsub[index]));
- up(&start_stop_sem);
- return -ENOMEM;
- }
- /* setting to alternate setting 3: enabling iso ep and bulk ep. */
- i = usb_set_interface(usbduxsub[index].usbdev,
- usbduxsub[index].ifnum, 3);
- if (i < 0) {
- dev_err(dev, "comedi_: usbduxsigma%d: "
- "could not set alternate setting 3 in high speed.\n",
- index);
- tidy_up(&(usbduxsub[index]));
- up(&start_stop_sem);
- return -ENODEV;
- }
- if (usbduxsub[index].high_speed)
- usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSHIGH;
- else
- usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSFULL;
-
- usbduxsub[index].urbIn = kcalloc(usbduxsub[index].numOfInBuffers,
- sizeof(struct urb *),
- GFP_KERNEL);
- if (!(usbduxsub[index].urbIn)) {
- tidy_up(&(usbduxsub[index]));
- up(&start_stop_sem);
- return -ENOMEM;
- }
- for (i = 0; i < usbduxsub[index].numOfInBuffers; i++) {
+
+ for (i = 0; i < devpriv->n_ai_urbs; i++) {
/* one frame: 1ms */
- usbduxsub[index].urbIn[i] = usb_alloc_urb(1, GFP_KERNEL);
- if (usbduxsub[index].urbIn[i] == NULL) {
- dev_err(dev, "comedi_: usbduxsigma%d: "
- "Could not alloc. urb(%d)\n", index, i);
- tidy_up(&(usbduxsub[index]));
- up(&start_stop_sem);
+ urb = usb_alloc_urb(1, GFP_KERNEL);
+ if (!urb)
return -ENOMEM;
- }
- usbduxsub[index].urbIn[i]->dev = usbduxsub[index].usbdev;
+ devpriv->ai_urbs[i] = urb;
+ urb->dev = usb;
/* will be filled later with a pointer to the comedi-device */
/* and ONLY then the urb should be submitted */
- usbduxsub[index].urbIn[i]->context = NULL;
- usbduxsub[index].urbIn[i]->pipe =
- usb_rcvisocpipe(usbduxsub[index].usbdev, ISOINEP);
- usbduxsub[index].urbIn[i]->transfer_flags = URB_ISO_ASAP;
- usbduxsub[index].urbIn[i]->transfer_buffer =
- kzalloc(SIZEINBUF, GFP_KERNEL);
- if (!(usbduxsub[index].urbIn[i]->transfer_buffer)) {
- tidy_up(&(usbduxsub[index]));
- up(&start_stop_sem);
+ urb->context = NULL;
+ urb->pipe = usb_rcvisocpipe(usb, USBDUXSIGMA_ISO_IN_EP);
+ urb->transfer_flags = URB_ISO_ASAP;
+ urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
+ if (!urb->transfer_buffer)
return -ENOMEM;
- }
- usbduxsub[index].urbIn[i]->complete = usbduxsub_ai_IsocIrq;
- usbduxsub[index].urbIn[i]->number_of_packets = 1;
- usbduxsub[index].urbIn[i]->transfer_buffer_length = SIZEINBUF;
- usbduxsub[index].urbIn[i]->iso_frame_desc[0].offset = 0;
- usbduxsub[index].urbIn[i]->iso_frame_desc[0].length =
- SIZEINBUF;
+ urb->complete = usbduxsigma_ai_urb_complete;
+ urb->number_of_packets = 1;
+ urb->transfer_buffer_length = SIZEINBUF;
+ urb->iso_frame_desc[0].offset = 0;
+ urb->iso_frame_desc[0].length = SIZEINBUF;
}
- /* out */
- if (usbduxsub[index].high_speed)
- usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSHIGH;
- else
- usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSFULL;
-
- usbduxsub[index].urbOut = kcalloc(usbduxsub[index].numOfOutBuffers,
- sizeof(struct urb *), GFP_KERNEL);
- if (!(usbduxsub[index].urbOut)) {
- tidy_up(&(usbduxsub[index]));
- up(&start_stop_sem);
- return -ENOMEM;
- }
- for (i = 0; i < usbduxsub[index].numOfOutBuffers; i++) {
+ for (i = 0; i < devpriv->n_ao_urbs; i++) {
/* one frame: 1ms */
- usbduxsub[index].urbOut[i] = usb_alloc_urb(1, GFP_KERNEL);
- if (usbduxsub[index].urbOut[i] == NULL) {
- dev_err(dev, "comedi_: usbduxsigma%d: "
- "Could not alloc. urb(%d)\n", index, i);
- tidy_up(&(usbduxsub[index]));
- up(&start_stop_sem);
+ urb = usb_alloc_urb(1, GFP_KERNEL);
+ if (!urb)
return -ENOMEM;
- }
- usbduxsub[index].urbOut[i]->dev = usbduxsub[index].usbdev;
+ devpriv->ao_urbs[i] = urb;
+ urb->dev = usb;
/* will be filled later with a pointer to the comedi-device */
/* and ONLY then the urb should be submitted */
- usbduxsub[index].urbOut[i]->context = NULL;
- usbduxsub[index].urbOut[i]->pipe =
- usb_sndisocpipe(usbduxsub[index].usbdev, ISOOUTEP);
- usbduxsub[index].urbOut[i]->transfer_flags = URB_ISO_ASAP;
- usbduxsub[index].urbOut[i]->transfer_buffer =
- kzalloc(SIZEOUTBUF, GFP_KERNEL);
- if (!(usbduxsub[index].urbOut[i]->transfer_buffer)) {
- tidy_up(&(usbduxsub[index]));
- up(&start_stop_sem);
+ urb->context = NULL;
+ urb->pipe = usb_sndisocpipe(usb, USBDUXSIGMA_ISO_OUT_EP);
+ urb->transfer_flags = URB_ISO_ASAP;
+ urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
+ if (!urb->transfer_buffer)
return -ENOMEM;
- }
- usbduxsub[index].urbOut[i]->complete = usbduxsub_ao_IsocIrq;
- usbduxsub[index].urbOut[i]->number_of_packets = 1;
- usbduxsub[index].urbOut[i]->transfer_buffer_length =
- SIZEOUTBUF;
- usbduxsub[index].urbOut[i]->iso_frame_desc[0].offset = 0;
- usbduxsub[index].urbOut[i]->iso_frame_desc[0].length =
- SIZEOUTBUF;
- if (usbduxsub[index].high_speed) {
- /* uframes */
- usbduxsub[index].urbOut[i]->interval = 8;
- } else {
- /* frames */
- usbduxsub[index].urbOut[i]->interval = 1;
- }
+ urb->complete = usbduxsigma_ao_urb_complete;
+ urb->number_of_packets = 1;
+ urb->transfer_buffer_length = SIZEOUTBUF;
+ urb->iso_frame_desc[0].offset = 0;
+ urb->iso_frame_desc[0].length = SIZEOUTBUF;
+ if (devpriv->high_speed)
+ urb->interval = 8; /* uframes */
+ else
+ urb->interval = 1; /* frames */
}
- /* pwm */
- if (usbduxsub[index].high_speed) {
+ if (devpriv->high_speed) {
/* max bulk ep size in high speed */
- usbduxsub[index].sizePwmBuf = 512;
- usbduxsub[index].urbPwm = usb_alloc_urb(0, GFP_KERNEL);
- if (usbduxsub[index].urbPwm == NULL) {
- dev_err(dev, "comedi_: usbduxsigma%d: "
- "Could not alloc. pwm urb\n", index);
- tidy_up(&(usbduxsub[index]));
- up(&start_stop_sem);
+ devpriv->pwm_buf_sz = 512;
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb)
return -ENOMEM;
- }
- usbduxsub[index].urbPwm->transfer_buffer =
- kzalloc(usbduxsub[index].sizePwmBuf, GFP_KERNEL);
- if (!(usbduxsub[index].urbPwm->transfer_buffer)) {
- tidy_up(&(usbduxsub[index]));
- up(&start_stop_sem);
+ devpriv->pwm_urb = urb;
+ urb->transfer_buffer = kzalloc(devpriv->pwm_buf_sz, GFP_KERNEL);
+ if (!urb->transfer_buffer)
return -ENOMEM;
- }
} else {
- usbduxsub[index].urbPwm = NULL;
- usbduxsub[index].sizePwmBuf = 0;
+ devpriv->pwm_urb = NULL;
+ devpriv->pwm_buf_sz = 0;
}
- usbduxsub[index].ai_cmd_running = 0;
- usbduxsub[index].ao_cmd_running = 0;
- usbduxsub[index].pwm_cmd_running = 0;
+ return 0;
+}
- /* we've reached the bottom of the function */
- usbduxsub[index].probed = 1;
- up(&start_stop_sem);
+static void usbduxsigma_free_usb_buffers(struct comedi_device *dev)
+{
+ struct usbduxsigma_private *devpriv = dev->private;
+ struct urb *urb;
+ int i;
- ret = request_firmware_nowait(THIS_MODULE,
- FW_ACTION_HOTPLUG,
- FIRMWARE,
- &udev->dev,
- GFP_KERNEL,
- usbduxsub + index,
- usbdux_firmware_request_complete_handler
- );
+ /* force unlink all urbs */
+ usbduxsigma_ai_stop(dev, 1);
+ usbduxsigma_ao_stop(dev, 1);
+ usbduxsigma_pwm_stop(dev, 1);
+
+ urb = devpriv->pwm_urb;
+ if (urb) {
+ kfree(urb->transfer_buffer);
+ usb_free_urb(urb);
+ }
+ if (devpriv->ao_urbs) {
+ for (i = 0; i < devpriv->n_ao_urbs; i++) {
+ urb = devpriv->ao_urbs[i];
+ if (urb) {
+ kfree(urb->transfer_buffer);
+ usb_free_urb(urb);
+ }
+ }
+ kfree(devpriv->ao_urbs);
+ }
+ if (devpriv->ai_urbs) {
+ for (i = 0; i < devpriv->n_ai_urbs; i++) {
+ urb = devpriv->ai_urbs[i];
+ if (urb) {
+ kfree(urb->transfer_buffer);
+ usb_free_urb(urb);
+ }
+ }
+ kfree(devpriv->ai_urbs);
+ }
+ kfree(devpriv->insn_buf);
+ kfree(devpriv->in_buf);
+ kfree(devpriv->dux_commands);
+ kfree(devpriv->dac_commands);
+}
- if (ret) {
- dev_err(dev, "Could not load firmware (err=%d)\n", ret);
- return ret;
+static int usbduxsigma_auto_attach(struct comedi_device *dev,
+ unsigned long context_unused)
+{
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
+ struct usb_device *usb = comedi_to_usb_dev(dev);
+ struct usbduxsigma_private *devpriv;
+ int ret;
+
+ devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+ if (!devpriv)
+ return -ENOMEM;
+ dev->private = devpriv;
+
+ sema_init(&devpriv->sem, 1);
+ usb_set_intfdata(intf, devpriv);
+
+ ret = usb_set_interface(usb,
+ intf->altsetting->desc.bInterfaceNumber, 3);
+ if (ret < 0) {
+ dev_err(dev->class_dev,
+ "could not set alternate setting 3 in high speed\n");
+ return -ENODEV;
}
- dev_info(dev, "comedi_: successfully initialised.\n");
- /* success */
- return 0;
+ /* test if it is high speed (USB 2.0) */
+ devpriv->high_speed = (usb->speed == USB_SPEED_HIGH);
+ if (devpriv->high_speed) {
+ devpriv->n_ai_urbs = NUMOFINBUFFERSHIGH;
+ devpriv->n_ao_urbs = NUMOFOUTBUFFERSHIGH;
+ } else {
+ devpriv->n_ai_urbs = NUMOFINBUFFERSFULL;
+ devpriv->n_ao_urbs = NUMOFOUTBUFFERSFULL;
+ }
+
+ ret = usbduxsigma_alloc_usb_buffers(dev);
+ if (ret)
+ return ret;
+
+ ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE,
+ usbduxsigma_firmware_upload, 0);
+ if (ret)
+ return ret;
+
+ return usbduxsigma_attach_common(dev);
}
-static void usbduxsigma_usb_disconnect(struct usb_interface *intf)
+static void usbduxsigma_detach(struct comedi_device *dev)
{
- struct usbduxsub *usbduxsub_tmp = usb_get_intfdata(intf);
- struct usb_device *udev = interface_to_usbdev(intf);
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
+ struct usbduxsigma_private *devpriv = dev->private;
- if (!usbduxsub_tmp) {
- dev_err(&intf->dev,
- "comedi_: disconnect called with null pointer.\n");
+ if (!devpriv)
return;
- }
- if (usbduxsub_tmp->usbdev != udev) {
- dev_err(&intf->dev, "comedi_: BUG! wrong ptr!\n");
- return;
- }
- if (usbduxsub_tmp->ai_cmd_running)
- /* we are still running a command */
- usbdux_ai_stop(usbduxsub_tmp, 1);
- if (usbduxsub_tmp->ao_cmd_running)
- /* we are still running a command */
- usbdux_ao_stop(usbduxsub_tmp, 1);
- comedi_usb_auto_unconfig(intf);
- down(&start_stop_sem);
- down(&usbduxsub_tmp->sem);
- tidy_up(usbduxsub_tmp);
- up(&usbduxsub_tmp->sem);
- up(&start_stop_sem);
- dev_info(&intf->dev, "comedi_: disconnected from the usb\n");
+
+ usb_set_intfdata(intf, NULL);
+
+ down(&devpriv->sem);
+ usbduxsigma_free_usb_buffers(dev);
+ up(&devpriv->sem);
+}
+
+static struct comedi_driver usbduxsigma_driver = {
+ .driver_name = "usbduxsigma",
+ .module = THIS_MODULE,
+ .auto_attach = usbduxsigma_auto_attach,
+ .detach = usbduxsigma_detach,
+};
+
+static int usbduxsigma_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return comedi_usb_auto_config(intf, &usbduxsigma_driver, 0);
}
static const struct usb_device_id usbduxsigma_usb_table[] = {
@@ -2664,7 +1754,7 @@ MODULE_DEVICE_TABLE(usb, usbduxsigma_usb_table);
static struct usb_driver usbduxsigma_usb_driver = {
.name = "usbduxsigma",
.probe = usbduxsigma_usb_probe,
- .disconnect = usbduxsigma_usb_disconnect,
+ .disconnect = comedi_usb_auto_unconfig,
.id_table = usbduxsigma_usb_table,
};
module_comedi_usb_driver(usbduxsigma_driver, usbduxsigma_usb_driver);
diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c
index 2be5087414f6..0ab04c0dd410 100644
--- a/drivers/staging/comedi/drivers/vmk80xx.c
+++ b/drivers/staging/comedi/drivers/vmk80xx.c
@@ -16,11 +16,6 @@
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: vmk80xx
@@ -159,8 +154,6 @@ static const struct vmk80xx_board vmk80xx_boardinfo[] = {
};
struct vmk80xx_private {
- struct usb_device *usb;
- struct usb_interface *intf;
struct usb_endpoint_descriptor *ep_rx;
struct usb_endpoint_descriptor *ep_tx;
struct firmware_version fw;
@@ -170,9 +163,10 @@ struct vmk80xx_private {
enum vmk80xx_model model;
};
-static int vmk80xx_check_data_link(struct vmk80xx_private *devpriv)
+static int vmk80xx_check_data_link(struct comedi_device *dev)
{
- struct usb_device *usb = devpriv->usb;
+ struct vmk80xx_private *devpriv = dev->private;
+ struct usb_device *usb = comedi_to_usb_dev(dev);
unsigned int tx_pipe;
unsigned int rx_pipe;
unsigned char tx[1];
@@ -194,9 +188,10 @@ static int vmk80xx_check_data_link(struct vmk80xx_private *devpriv)
return (int)rx[1];
}
-static void vmk80xx_read_eeprom(struct vmk80xx_private *devpriv, int flag)
+static void vmk80xx_read_eeprom(struct comedi_device *dev, int flag)
{
- struct usb_device *usb = devpriv->usb;
+ struct vmk80xx_private *devpriv = dev->private;
+ struct usb_device *usb = comedi_to_usb_dev(dev);
unsigned int tx_pipe;
unsigned int rx_pipe;
unsigned char tx[1];
@@ -223,9 +218,10 @@ static void vmk80xx_read_eeprom(struct vmk80xx_private *devpriv, int flag)
strncpy(devpriv->fw.ic6_vers, rx + 25, 24);
}
-static void vmk80xx_do_bulk_msg(struct vmk80xx_private *devpriv)
+static void vmk80xx_do_bulk_msg(struct comedi_device *dev)
{
- struct usb_device *usb = devpriv->usb;
+ struct vmk80xx_private *devpriv = dev->private;
+ struct usb_device *usb = comedi_to_usb_dev(dev);
__u8 tx_addr;
__u8 rx_addr;
unsigned int tx_pipe;
@@ -248,21 +244,18 @@ static void vmk80xx_do_bulk_msg(struct vmk80xx_private *devpriv)
usb_bulk_msg(usb, rx_pipe, devpriv->usb_rx_buf, size, NULL, HZ * 10);
}
-static int vmk80xx_read_packet(struct vmk80xx_private *devpriv)
+static int vmk80xx_read_packet(struct comedi_device *dev)
{
- struct usb_device *usb;
+ struct vmk80xx_private *devpriv = dev->private;
+ struct usb_device *usb = comedi_to_usb_dev(dev);
struct usb_endpoint_descriptor *ep;
unsigned int pipe;
- if (!devpriv->intf)
- return -ENODEV;
-
if (devpriv->model == VMK8061_MODEL) {
- vmk80xx_do_bulk_msg(devpriv);
+ vmk80xx_do_bulk_msg(dev);
return 0;
}
- usb = devpriv->usb;
ep = devpriv->ep_rx;
pipe = usb_rcvintpipe(usb, ep->bEndpointAddress);
return usb_interrupt_msg(usb, pipe, devpriv->usb_rx_buf,
@@ -270,23 +263,20 @@ static int vmk80xx_read_packet(struct vmk80xx_private *devpriv)
HZ * 10);
}
-static int vmk80xx_write_packet(struct vmk80xx_private *devpriv, int cmd)
+static int vmk80xx_write_packet(struct comedi_device *dev, int cmd)
{
- struct usb_device *usb;
+ struct vmk80xx_private *devpriv = dev->private;
+ struct usb_device *usb = comedi_to_usb_dev(dev);
struct usb_endpoint_descriptor *ep;
unsigned int pipe;
- if (!devpriv->intf)
- return -ENODEV;
-
devpriv->usb_tx_buf[0] = cmd;
if (devpriv->model == VMK8061_MODEL) {
- vmk80xx_do_bulk_msg(devpriv);
+ vmk80xx_do_bulk_msg(dev);
return 0;
}
- usb = devpriv->usb;
ep = devpriv->ep_tx;
pipe = usb_sndintpipe(usb, ep->bEndpointAddress);
return usb_interrupt_msg(usb, pipe, devpriv->usb_tx_buf,
@@ -294,18 +284,19 @@ static int vmk80xx_write_packet(struct vmk80xx_private *devpriv, int cmd)
HZ * 10);
}
-static int vmk80xx_reset_device(struct vmk80xx_private *devpriv)
+static int vmk80xx_reset_device(struct comedi_device *dev)
{
+ struct vmk80xx_private *devpriv = dev->private;
size_t size;
int retval;
size = le16_to_cpu(devpriv->ep_tx->wMaxPacketSize);
memset(devpriv->usb_tx_buf, 0, size);
- retval = vmk80xx_write_packet(devpriv, VMK8055_CMD_RST);
+ retval = vmk80xx_write_packet(dev, VMK8055_CMD_RST);
if (retval)
return retval;
/* set outputs to known state as we cannot read them */
- return vmk80xx_write_packet(devpriv, VMK8055_CMD_WRT_AD);
+ return vmk80xx_write_packet(dev, VMK8055_CMD_WRT_AD);
}
static int vmk80xx_ai_insn_read(struct comedi_device *dev,
@@ -338,7 +329,7 @@ static int vmk80xx_ai_insn_read(struct comedi_device *dev,
}
for (n = 0; n < insn->n; n++) {
- if (vmk80xx_read_packet(devpriv))
+ if (vmk80xx_read_packet(dev))
break;
if (devpriv->model == VMK8055_MODEL) {
@@ -388,7 +379,7 @@ static int vmk80xx_ao_insn_write(struct comedi_device *dev,
for (n = 0; n < insn->n; n++) {
devpriv->usb_tx_buf[reg] = data[n];
- if (vmk80xx_write_packet(devpriv, cmd))
+ if (vmk80xx_write_packet(dev, cmd))
break;
}
@@ -415,7 +406,7 @@ static int vmk80xx_ao_insn_read(struct comedi_device *dev,
devpriv->usb_tx_buf[0] = VMK8061_CMD_RD_AO;
for (n = 0; n < insn->n; n++) {
- if (vmk80xx_read_packet(devpriv))
+ if (vmk80xx_read_packet(dev))
break;
data[n] = devpriv->usb_rx_buf[reg + chan];
@@ -447,7 +438,7 @@ static int vmk80xx_di_insn_bits(struct comedi_device *dev,
reg = VMK8055_DI_REG;
}
- retval = vmk80xx_read_packet(devpriv);
+ retval = vmk80xx_read_packet(dev);
if (!retval) {
if (devpriv->model == VMK8055_MODEL)
@@ -492,7 +483,7 @@ static int vmk80xx_do_insn_bits(struct comedi_device *dev,
tx_buf[reg] &= ~data[0];
tx_buf[reg] |= (data[0] & data[1]);
- retval = vmk80xx_write_packet(devpriv, cmd);
+ retval = vmk80xx_write_packet(dev, cmd);
if (retval)
goto out;
@@ -501,7 +492,7 @@ static int vmk80xx_do_insn_bits(struct comedi_device *dev,
if (devpriv->model == VMK8061_MODEL) {
tx_buf[0] = VMK8061_CMD_RD_DO;
- retval = vmk80xx_read_packet(devpriv);
+ retval = vmk80xx_read_packet(dev);
if (!retval) {
data[1] = rx_buf[reg];
@@ -547,7 +538,7 @@ static int vmk80xx_cnt_insn_read(struct comedi_device *dev,
}
for (n = 0; n < insn->n; n++) {
- if (vmk80xx_read_packet(devpriv))
+ if (vmk80xx_read_packet(dev))
break;
if (devpriv->model == VMK8055_MODEL)
@@ -597,7 +588,7 @@ static int vmk80xx_cnt_insn_config(struct comedi_device *dev,
}
for (n = 0; n < insn->n; n++)
- if (vmk80xx_write_packet(devpriv, cmd))
+ if (vmk80xx_write_packet(dev, cmd))
break;
up(&devpriv->limit_sem);
@@ -640,7 +631,7 @@ static int vmk80xx_cnt_insn_write(struct comedi_device *dev,
devpriv->usb_tx_buf[6 + chan] = val;
- if (vmk80xx_write_packet(devpriv, cmd))
+ if (vmk80xx_write_packet(dev, cmd))
break;
}
@@ -671,7 +662,7 @@ static int vmk80xx_pwm_insn_read(struct comedi_device *dev,
tx_buf[0] = VMK8061_CMD_RD_PWM;
for (n = 0; n < insn->n; n++) {
- if (vmk80xx_read_packet(devpriv))
+ if (vmk80xx_read_packet(dev))
break;
data[n] = rx_buf[reg[0]] + 4 * rx_buf[reg[1]];
@@ -719,7 +710,7 @@ static int vmk80xx_pwm_insn_write(struct comedi_device *dev,
tx_buf[reg[0]] = (unsigned char)(data[n] & 0x03);
tx_buf[reg[1]] = (unsigned char)(data[n] >> 2) & 0xff;
- if (vmk80xx_write_packet(devpriv, cmd))
+ if (vmk80xx_write_packet(dev, cmd))
break;
}
@@ -731,7 +722,7 @@ static int vmk80xx_pwm_insn_write(struct comedi_device *dev,
static int vmk80xx_find_usb_endpoints(struct comedi_device *dev)
{
struct vmk80xx_private *devpriv = dev->private;
- struct usb_interface *intf = devpriv->intf;
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
struct usb_host_interface *iface_desc = intf->cur_altsetting;
struct usb_endpoint_descriptor *ep_desc;
int i;
@@ -889,8 +880,6 @@ static int vmk80xx_auto_attach(struct comedi_device *dev,
return -ENOMEM;
dev->private = devpriv;
- devpriv->usb = interface_to_usbdev(intf);
- devpriv->intf = intf;
devpriv->model = boardinfo->model;
ret = vmk80xx_find_usb_endpoints(dev);
@@ -906,23 +895,24 @@ static int vmk80xx_auto_attach(struct comedi_device *dev,
usb_set_intfdata(intf, devpriv);
if (devpriv->model == VMK8061_MODEL) {
- vmk80xx_read_eeprom(devpriv, IC3_VERSION);
+ vmk80xx_read_eeprom(dev, IC3_VERSION);
dev_info(&intf->dev, "%s\n", devpriv->fw.ic3_vers);
- if (vmk80xx_check_data_link(devpriv)) {
- vmk80xx_read_eeprom(devpriv, IC6_VERSION);
+ if (vmk80xx_check_data_link(dev)) {
+ vmk80xx_read_eeprom(dev, IC6_VERSION);
dev_info(&intf->dev, "%s\n", devpriv->fw.ic6_vers);
}
}
if (devpriv->model == VMK8055_MODEL)
- vmk80xx_reset_device(devpriv);
+ vmk80xx_reset_device(dev);
return vmk80xx_init_subdevices(dev);
}
static void vmk80xx_detach(struct comedi_device *dev)
{
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
struct vmk80xx_private *devpriv = dev->private;
if (!devpriv)
@@ -930,7 +920,7 @@ static void vmk80xx_detach(struct comedi_device *dev)
down(&devpriv->limit_sem);
- usb_set_intfdata(devpriv->intf, NULL);
+ usb_set_intfdata(intf, NULL);
kfree(devpriv->usb_rx_buf);
kfree(devpriv->usb_tx_buf);