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.h15
-rw-r--r--drivers/staging/comedi/drivers/8255.c41
-rw-r--r--drivers/staging/comedi/drivers/8255_pci.c353
-rw-r--r--drivers/staging/comedi/drivers/Makefile6
-rw-r--r--drivers/staging/comedi/drivers/acl7225b.c6
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c195
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h27
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.c14
-rw-r--r--drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h453
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c18
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c61
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c81
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_all.c18
-rw-r--r--drivers/staging/comedi/drivers/adl_pci6208.c183
-rw-r--r--drivers/staging/comedi/drivers/adl_pci7230.c190
-rw-r--r--drivers/staging/comedi/drivers/adl_pci7296.c183
-rw-r--r--drivers/staging/comedi/drivers/adl_pci7432.c200
-rw-r--r--drivers/staging/comedi/drivers/adl_pci7x3x.c332
-rw-r--r--drivers/staging/comedi/drivers/adl_pci8164.c73
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9111.c973
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9118.c961
-rw-r--r--drivers/staging/comedi/drivers/adq12b.c29
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1710.c766
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1723.c222
-rw-r--r--drivers/staging/comedi/drivers/adv_pci_dio.c473
-rw-r--r--drivers/staging/comedi/drivers/aio_aio12_8.c218
-rw-r--r--drivers/staging/comedi/drivers/aio_iiro_16.c4
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200.c121
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc236.c115
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc263.c61
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci224.c71
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci230.c161
-rw-r--r--drivers/staging/comedi/drivers/c6xdigio.c6
-rw-r--r--drivers/staging/comedi/drivers/cb_das16_cs.c56
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas.c202
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas64.c128
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidda.c441
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidio.c211
-rw-r--r--drivers/staging/comedi/drivers/cb_pcimdas.c279
-rw-r--r--drivers/staging/comedi/drivers/cb_pcimdda.c393
-rw-r--r--drivers/staging/comedi/drivers/comedi_bond.c110
-rw-r--r--drivers/staging/comedi/drivers/comedi_fc.h32
-rw-r--r--drivers/staging/comedi/drivers/comedi_parport.c86
-rw-r--r--drivers/staging/comedi/drivers/comedi_test.c108
-rw-r--r--drivers/staging/comedi/drivers/contec_pci_dio.c146
-rw-r--r--drivers/staging/comedi/drivers/daqboard2000.c466
-rw-r--r--drivers/staging/comedi/drivers/das08.c477
-rw-r--r--drivers/staging/comedi/drivers/das08.h15
-rw-r--r--drivers/staging/comedi/drivers/das08_cs.c26
-rw-r--r--drivers/staging/comedi/drivers/das16.c82
-rw-r--r--drivers/staging/comedi/drivers/das16m1.c54
-rw-r--r--drivers/staging/comedi/drivers/das1800.c145
-rw-r--r--drivers/staging/comedi/drivers/das6402.c4
-rw-r--r--drivers/staging/comedi/drivers/das800.c52
-rw-r--r--drivers/staging/comedi/drivers/dmm32at.c57
-rw-r--r--drivers/staging/comedi/drivers/dt2801.c12
-rw-r--r--drivers/staging/comedi/drivers/dt2811.c8
-rw-r--r--drivers/staging/comedi/drivers/dt2814.c46
-rw-r--r--drivers/staging/comedi/drivers/dt2815.c2
-rw-r--r--drivers/staging/comedi/drivers/dt2817.c2
-rw-r--r--drivers/staging/comedi/drivers/dt282x.c103
-rw-r--r--drivers/staging/comedi/drivers/dt3000.c48
-rw-r--r--drivers/staging/comedi/drivers/dt9812.c8
-rw-r--r--drivers/staging/comedi/drivers/dyna_pci10xx.c161
-rw-r--r--drivers/staging/comedi/drivers/fl512.c4
-rw-r--r--drivers/staging/comedi/drivers/gsc_hpdi.c43
-rw-r--r--drivers/staging/comedi/drivers/icp_multi.c692
-rw-r--r--drivers/staging/comedi/drivers/icp_multi.h297
-rw-r--r--drivers/staging/comedi/drivers/ii_pci20kc.c4
-rw-r--r--drivers/staging/comedi/drivers/jr3_pci.c9
-rw-r--r--drivers/staging/comedi/drivers/jr3_pci.h4
-rw-r--r--drivers/staging/comedi/drivers/ke_counter.c103
-rw-r--r--drivers/staging/comedi/drivers/me4000.c1636
-rw-r--r--drivers/staging/comedi/drivers/me4000.h409
-rw-r--r--drivers/staging/comedi/drivers/me_daq.c221
-rw-r--r--drivers/staging/comedi/drivers/mite.c285
-rw-r--r--drivers/staging/comedi/drivers/mite.h66
-rw-r--r--drivers/staging/comedi/drivers/mpc624.c2
-rw-r--r--drivers/staging/comedi/drivers/mpc8260cpm.c2
-rw-r--r--drivers/staging/comedi/drivers/multiq3.c14
-rw-r--r--drivers/staging/comedi/drivers/ni_6527.c171
-rw-r--r--drivers/staging/comedi/drivers/ni_65xx.c181
-rw-r--r--drivers/staging/comedi/drivers/ni_660x.c133
-rw-r--r--drivers/staging/comedi/drivers/ni_670x.c62
-rw-r--r--drivers/staging/comedi/drivers/ni_at_a2150.c46
-rw-r--r--drivers/staging/comedi/drivers/ni_at_ao.c8
-rw-r--r--drivers/staging/comedi/drivers/ni_atmio.c2
-rw-r--r--drivers/staging/comedi/drivers/ni_atmio16d.c67
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_700.c212
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_dio24.c12
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc.c467
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc_cs.c6
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_common.c240
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_cs.c4
-rw-r--r--drivers/staging/comedi/drivers/ni_pcidio.c472
-rw-r--r--drivers/staging/comedi/drivers/ni_pcimio.c70
-rw-r--r--drivers/staging/comedi/drivers/ni_tiocmd.c61
-rw-r--r--drivers/staging/comedi/drivers/pcl711.c53
-rw-r--r--drivers/staging/comedi/drivers/pcl724.c15
-rw-r--r--drivers/staging/comedi/drivers/pcl725.c4
-rw-r--r--drivers/staging/comedi/drivers/pcl726.c6
-rw-r--r--drivers/staging/comedi/drivers/pcl730.c8
-rw-r--r--drivers/staging/comedi/drivers/pcl812.c57
-rw-r--r--drivers/staging/comedi/drivers/pcl816.c52
-rw-r--r--drivers/staging/comedi/drivers/pcl818.c59
-rw-r--r--drivers/staging/comedi/drivers/pcm3724.c26
-rw-r--r--drivers/staging/comedi/drivers/pcm3730.c12
-rw-r--r--drivers/staging/comedi/drivers/pcm_common.c56
-rw-r--r--drivers/staging/comedi/drivers/pcmad.c2
-rw-r--r--drivers/staging/comedi/drivers/pcmda12.c2
-rw-r--r--drivers/staging/comedi/drivers/pcmmio.c32
-rw-r--r--drivers/staging/comedi/drivers/pcmuio.c14
-rw-r--r--drivers/staging/comedi/drivers/poc.c2
-rw-r--r--drivers/staging/comedi/drivers/quatech_daqp_cs.c63
-rw-r--r--drivers/staging/comedi/drivers/rtd520.c67
-rw-r--r--drivers/staging/comedi/drivers/rti800.c10
-rw-r--r--drivers/staging/comedi/drivers/rti802.c2
-rw-r--r--drivers/staging/comedi/drivers/s526.c602
-rw-r--r--drivers/staging/comedi/drivers/s626.c755
-rw-r--r--drivers/staging/comedi/drivers/s626.h1
-rw-r--r--drivers/staging/comedi/drivers/serial2002.c14
-rw-r--r--drivers/staging/comedi/drivers/skel.c74
-rw-r--r--drivers/staging/comedi/drivers/ssv_dnp.c7
-rw-r--r--drivers/staging/comedi/drivers/usbdux.c201
-rw-r--r--drivers/staging/comedi/drivers/usbduxfast.c120
-rw-r--r--drivers/staging/comedi/drivers/usbduxsigma.c192
-rw-r--r--drivers/staging/comedi/drivers/vmk80xx.c14
127 files changed, 6653 insertions, 12464 deletions
diff --git a/drivers/staging/comedi/drivers/8253.h b/drivers/staging/comedi/drivers/8253.h
index 3eb45d46e05b..429e0d60c0a3 100644
--- a/drivers/staging/comedi/drivers/8253.h
+++ b/drivers/staging/comedi/drivers/8253.h
@@ -262,8 +262,10 @@ static inline int i8254_load(unsigned long base_address, unsigned int regshift,
return 0;
}
-static inline int i8254_mm_load(void *base_address, unsigned int regshift,
- unsigned int counter_number, unsigned int count,
+static inline int i8254_mm_load(void __iomem *base_address,
+ unsigned int regshift,
+ unsigned int counter_number,
+ unsigned int count,
unsigned int mode)
{
unsigned int byte;
@@ -311,7 +313,8 @@ static inline int i8254_read(unsigned long base_address, unsigned int regshift,
return ret;
}
-static inline int i8254_mm_read(void *base_address, unsigned int regshift,
+static inline int i8254_mm_read(void __iomem *base_address,
+ unsigned int regshift,
unsigned int counter_number)
{
unsigned int byte;
@@ -348,7 +351,7 @@ static inline void i8254_write(unsigned long base_address,
outb(byte, base_address + (counter_number << regshift));
}
-static inline void i8254_mm_write(void *base_address,
+static inline void i8254_mm_write(void __iomem *base_address,
unsigned int regshift,
unsigned int counter_number,
unsigned int count)
@@ -390,7 +393,7 @@ static inline int i8254_set_mode(unsigned long base_address,
return 0;
}
-static inline int i8254_mm_set_mode(void *base_address,
+static inline int i8254_mm_set_mode(void __iomem *base_address,
unsigned int regshift,
unsigned int counter_number,
unsigned int mode)
@@ -419,7 +422,7 @@ static inline int i8254_status(unsigned long base_address,
return inb(base_address + (counter_number << regshift));
}
-static inline int i8254_mm_status(void *base_address,
+static inline int i8254_mm_status(void __iomem *base_address,
unsigned int regshift,
unsigned int counter_number)
{
diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
index 4c9977b8a5ae..a256622e2dd7 100644
--- a/drivers/staging/comedi/drivers/8255.c
+++ b/drivers/staging/comedi/drivers/8255.c
@@ -82,6 +82,8 @@ I/O port base address can be found in the output of 'lspci -v'.
#include <linux/ioport.h>
#include <linux/slab.h>
+
+#include "comedi_fc.h"
#include "8255.h"
#define _8255_SIZE 4
@@ -229,39 +231,20 @@ static int subdev_8255_cmdtest(struct comedi_device *dev,
struct comedi_cmd *cmd)
{
int err = 0;
- unsigned int tmp;
-
- /* step 1 */
-
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_FOLLOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
if (err)
return 1;
- /* step 2 */
+ /* Step 2a : make sure trigger sources are unique */
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -403,7 +386,7 @@ static int dev_8255_attach(struct comedi_device *dev,
return ret;
for (i = 0; i < dev->n_subdevices; i++) {
- s = dev->subdevices + i;
+ s = &dev->subdevices[i];
iobase = it->options[i];
if (!request_region(iobase, _8255_SIZE, "8255")) {
@@ -429,7 +412,7 @@ static void dev_8255_detach(struct comedi_device *dev)
int i;
for (i = 0; i < dev->n_subdevices; i++) {
- s = dev->subdevices + i;
+ s = &dev->subdevices[i];
if (s->type != COMEDI_SUBD_UNUSED) {
spriv = s->private;
release_region(spriv->iobase, _8255_SIZE);
diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c
new file mode 100644
index 000000000000..7dff3c01dc29
--- /dev/null
+++ b/drivers/staging/comedi/drivers/8255_pci.c
@@ -0,0 +1,353 @@
+/*
+ * COMEDI driver for generic PCI based 8255 digital i/o boards
+ * Copyright (C) 2012 H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * Based on the tested adl_pci7296 driver written by:
+ * Jon Grierson <jd@renko.co.uk>
+ * and the experimental cb_pcidio driver written by:
+ * Yoshiya Matsuzaka
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+Driver: 8255_pci
+Description: Generic PCI based 8255 Digital I/O boards
+Devices: (ADLink) PCI-7224 [adl_pci-7224] - 24 channels
+ (ADLink) PCI-7248 [adl_pci-7248] - 48 channels
+ (ADLink) PCI-7296 [adl_pci-7296] - 96 channels
+ (Measurement Computing) PCI-DIO24 [cb_pci-dio24] - 24 channels
+ (Measurement Computing) PCI-DIO24H [cb_pci-dio24h] - 24 channels
+ (Measurement Computing) PCI-DIO48H [cb_pci-dio48h] - 48 channels
+ (Measurement Computing) PCI-DIO96H [cb_pci-dio96h] - 96 channels
+ (National Instruments) PCI-DIO-96 [ni_pci-dio-96] - 96 channels
+ (National Instruments) PCI-DIO-96B [ni_pci-dio-96b] - 96 channels
+ (National Instruments) PXI-6508 [ni_pxi-6508] - 96 channels
+ (National Instruments) PCI-6503 [ni_pci-6503] - 24 channels
+ (National Instruments) PCI-6503B [ni_pci-6503b] - 24 channels
+ (National Instruments) PCI-6503X [ni_pci-6503x] - 24 channels
+ (National Instruments) PXI-6503 [ni_pxi-6503] - 24 channels
+Author: H Hartley Sweeten <hsweeten@visionengravers.com>
+Updated: Wed, 12 Sep 2012 11:52:01 -0700
+Status: untested
+
+Some of these boards also have an 8254 programmable timer/counter
+chip. This chip is not currently supported by this driver.
+
+Interrupt support for these boards is also not currently supported.
+
+Configuration Options: not applicable, uses PCI auto config
+*/
+
+#include "../comedidev.h"
+
+#include "8255.h"
+
+/*
+ * PCI Device ID's supported by this driver
+ */
+#define PCI_DEVICE_ID_ADLINK_PCI7224 0x7224
+#define PCI_DEVICE_ID_ADLINK_PCI7248 0x7248
+#define PCI_DEVICE_ID_ADLINK_PCI7296 0x7296
+
+/* ComputerBoards is now known as Measurement Computing */
+#define PCI_VENDOR_ID_CB 0x1307
+
+#define PCI_DEVICE_ID_CB_PCIDIO48H 0x000b
+#define PCI_DEVICE_ID_CB_PCIDIO24H 0x0014
+#define PCI_DEVICE_ID_CB_PCIDIO96H 0x0017
+#define PCI_DEVICE_ID_CB_PCIDIO24 0x0028
+
+#define PCI_DEVICE_ID_NI_PCIDIO96 0x0160
+#define PCI_DEVICE_ID_NI_PCI6503 0x0400
+#define PCI_DEVICE_ID_NI_PCI6503B 0x1250
+#define PCI_DEVICE_ID_NI_PXI6508 0x13c0
+#define PCI_DEVICE_ID_NI_PCIDIO96B 0x1630
+#define PCI_DEVICE_ID_NI_PCI6503X 0x17d0
+#define PCI_DEVICE_ID_NI_PXI_6503 0x1800
+
+struct pci_8255_boardinfo {
+ const char *name;
+ unsigned short vendor;
+ unsigned short device;
+ int dio_badr;
+ int is_mmio;
+ int n_8255;
+};
+
+static const struct pci_8255_boardinfo pci_8255_boards[] = {
+ {
+ .name = "adl_pci-7224",
+ .vendor = PCI_VENDOR_ID_ADLINK,
+ .device = PCI_DEVICE_ID_ADLINK_PCI7224,
+ .dio_badr = 2,
+ .n_8255 = 1,
+ }, {
+ .name = "adl_pci-7248",
+ .vendor = PCI_VENDOR_ID_ADLINK,
+ .device = PCI_DEVICE_ID_ADLINK_PCI7248,
+ .dio_badr = 2,
+ .n_8255 = 2,
+ }, {
+ .name = "adl_pci-7296",
+ .vendor = PCI_VENDOR_ID_ADLINK,
+ .device = PCI_DEVICE_ID_ADLINK_PCI7296,
+ .dio_badr = 2,
+ .n_8255 = 4,
+ }, {
+ .name = "cb_pci-dio24",
+ .vendor = PCI_VENDOR_ID_CB,
+ .device = PCI_DEVICE_ID_CB_PCIDIO24,
+ .dio_badr = 2,
+ .n_8255 = 1,
+ }, {
+ .name = "cb_pci-dio24h",
+ .vendor = PCI_VENDOR_ID_CB,
+ .device = PCI_DEVICE_ID_CB_PCIDIO24H,
+ .dio_badr = 2,
+ .n_8255 = 1,
+ }, {
+ .name = "cb_pci-dio48h",
+ .vendor = PCI_VENDOR_ID_CB,
+ .device = PCI_DEVICE_ID_CB_PCIDIO48H,
+ .dio_badr = 1,
+ .n_8255 = 2,
+ }, {
+ .name = "cb_pci-dio96h",
+ .vendor = PCI_VENDOR_ID_CB,
+ .device = PCI_DEVICE_ID_CB_PCIDIO96H,
+ .dio_badr = 2,
+ .n_8255 = 4,
+ }, {
+ .name = "ni_pci-dio-96",
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PCIDIO96,
+ .dio_badr = 1,
+ .is_mmio = 1,
+ .n_8255 = 4,
+ }, {
+ .name = "ni_pci-dio-96b",
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PCIDIO96B,
+ .dio_badr = 1,
+ .is_mmio = 1,
+ .n_8255 = 4,
+ }, {
+ .name = "ni_pxi-6508",
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PXI6508,
+ .dio_badr = 1,
+ .is_mmio = 1,
+ .n_8255 = 4,
+ }, {
+ .name = "ni_pci-6503",
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PCI6503,
+ .dio_badr = 1,
+ .is_mmio = 1,
+ .n_8255 = 1,
+ }, {
+ .name = "ni_pci-6503b",
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PCI6503B,
+ .dio_badr = 1,
+ .is_mmio = 1,
+ .n_8255 = 1,
+ }, {
+ .name = "ni_pci-6503x",
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PCI6503X,
+ .dio_badr = 1,
+ .is_mmio = 1,
+ .n_8255 = 1,
+ }, {
+ .name = "ni_pxi-6503",
+ .vendor = PCI_VENDOR_ID_NI,
+ .device = PCI_DEVICE_ID_NI_PXI_6503,
+ .dio_badr = 1,
+ .is_mmio = 1,
+ .n_8255 = 1,
+ },
+};
+
+struct pci_8255_private {
+ void __iomem *mmio_base;
+};
+
+static int pci_8255_mmio(int dir, int port, int data, unsigned long iobase)
+{
+ void __iomem *mmio_base = (void __iomem *)iobase;
+
+ if (dir) {
+ writeb(data, mmio_base + port);
+ return 0;
+ } else {
+ return readb(mmio_base + port);
+ }
+}
+
+static const void *pci_8255_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
+{
+ const struct pci_8255_boardinfo *board;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pci_8255_boards); i++) {
+ board = &pci_8255_boards[i];
+ if (pcidev->vendor == board->vendor &&
+ pcidev->device == board->device)
+ return board;
+ }
+ return NULL;
+}
+
+static int pci_8255_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
+{
+ const struct pci_8255_boardinfo *board;
+ struct pci_8255_private *devpriv;
+ struct comedi_subdevice *s;
+ resource_size_t iobase;
+ unsigned long len;
+ int ret;
+ int i;
+
+ comedi_set_hw_dev(dev, &pcidev->dev);
+
+ board = pci_8255_find_boardinfo(dev, pcidev);
+ if (!board)
+ return -ENODEV;
+ dev->board_ptr = board;
+ dev->board_name = board->name;
+
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret < 0)
+ return ret;
+ devpriv = dev->private;
+
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
+ iobase = pci_resource_start(pcidev, board->dio_badr);
+ len = pci_resource_len(pcidev, board->dio_badr);
+
+ if (board->is_mmio) {
+ devpriv->mmio_base = ioremap(iobase, len);
+ if (!devpriv->mmio_base)
+ return -ENOMEM;
+ }
+ dev->iobase = iobase;
+
+ /*
+ * One, two, or four subdevices are setup by this driver depending
+ * on the number of channels provided by the board. Each subdevice
+ * has 24 channels supported by the 8255 module.
+ */
+ ret = comedi_alloc_subdevices(dev, board->n_8255);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < board->n_8255; i++) {
+ s = &dev->subdevices[i];
+ if (board->is_mmio) {
+ iobase = (unsigned long)(devpriv->mmio_base + (i * 4));
+ ret = subdev_8255_init(dev, s, pci_8255_mmio, iobase);
+ } else {
+ iobase = dev->iobase + (i * 4);
+ ret = subdev_8255_init(dev, s, NULL, iobase);
+ }
+ if (ret)
+ return ret;
+ }
+
+ dev_info(dev->class_dev, "%s attached (%d digital i/o channels)\n",
+ dev->board_name, board->n_8255 * 24);
+
+ return 0;
+}
+
+static void pci_8255_detach(struct comedi_device *dev)
+{
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ const struct pci_8255_boardinfo *board = comedi_board(dev);
+ struct pci_8255_private *devpriv = dev->private;
+ struct comedi_subdevice *s;
+ int i;
+
+ if (dev->subdevices) {
+ for (i = 0; i < board->n_8255; i++) {
+ s = &dev->subdevices[i];
+ subdev_8255_cleanup(dev, s);
+ }
+ }
+ if (pcidev) {
+ if (devpriv->mmio_base)
+ iounmap(devpriv->mmio_base);
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
+ }
+}
+
+static struct comedi_driver pci_8255_driver = {
+ .driver_name = "8255_pci",
+ .module = THIS_MODULE,
+ .attach_pci = pci_8255_attach_pci,
+ .detach = pci_8255_detach,
+};
+
+static int __devinit pci_8255_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ return comedi_pci_auto_config(dev, &pci_8255_driver);
+}
+
+static void __devexit pci_8255_pci_remove(struct pci_dev *dev)
+{
+ comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(pci_8255_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_ADLINK_PCI7224) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_ADLINK_PCI7248) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_ADLINK_PCI7296) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_CB_PCIDIO24) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_CB_PCIDIO24H) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_CB_PCIDIO48H) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_CB_PCIDIO96H) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCIDIO96) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCIDIO96B) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI6508) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI6503) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI6503B) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI6503X) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI_6503) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, pci_8255_pci_table);
+
+static struct pci_driver pci_8255_pci_driver = {
+ .name = "8255_pci",
+ .id_table = pci_8255_pci_table,
+ .probe = pci_8255_pci_probe,
+ .remove = __devexit_p(pci_8255_pci_remove),
+};
+module_comedi_pci_driver(pci_8255_driver, pci_8255_pci_driver);
+
+MODULE_DESCRIPTION("COMEDI - Generic PCI based 8255 Digital I/O boards");
+MODULE_AUTHOR("Comedi http://www.comedi.org");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile
index 57b19e44d867..a2787c0ca327 100644
--- a/drivers/staging/comedi/drivers/Makefile
+++ b/drivers/staging/comedi/drivers/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_COMEDI_MULTIQ3) += multiq3.o
obj-$(CONFIG_COMEDI_POC) += poc.o
# Comedi PCI drivers
+obj-$(CONFIG_COMEDI_8255_PCI) += 8255_pci.o
obj-$(CONFIG_COMEDI_ADDI_APCI_035) += addi_apci_035.o
obj-$(CONFIG_COMEDI_ADDI_APCI_1032) += addi_apci_1032.o
obj-$(CONFIG_COMEDI_ADDI_APCI_1500) += addi_apci_1500.o
@@ -69,9 +70,7 @@ obj-$(CONFIG_COMEDI_ADDI_APCI_3120) += addi_apci_3120.o
obj-$(CONFIG_COMEDI_ADDI_APCI_3501) += addi_apci_3501.o
obj-$(CONFIG_COMEDI_ADDI_APCI_3XXX) += addi_apci_3xxx.o
obj-$(CONFIG_COMEDI_ADL_PCI6208) += adl_pci6208.o
-obj-$(CONFIG_COMEDI_ADL_PCI7230) += adl_pci7230.o
-obj-$(CONFIG_COMEDI_ADL_PCI7296) += adl_pci7296.o
-obj-$(CONFIG_COMEDI_ADL_PCI7432) += adl_pci7432.o
+obj-$(CONFIG_COMEDI_ADL_PCI7X3X) += adl_pci7x3x.o
obj-$(CONFIG_COMEDI_ADL_PCI8164) += adl_pci8164.o
obj-$(CONFIG_COMEDI_ADL_PCI9111) += adl_pci9111.o
obj-$(CONFIG_COMEDI_ADL_PCI9118) += adl_pci9118.o
@@ -96,7 +95,6 @@ obj-$(CONFIG_COMEDI_KE_COUNTER) += ke_counter.o
obj-$(CONFIG_COMEDI_CB_PCIDAS64) += cb_pcidas64.o
obj-$(CONFIG_COMEDI_CB_PCIDAS) += cb_pcidas.o
obj-$(CONFIG_COMEDI_CB_PCIDDA) += cb_pcidda.o
-obj-$(CONFIG_COMEDI_CB_PCIDIO) += cb_pcidio.o
obj-$(CONFIG_COMEDI_CB_PCIMDAS) += cb_pcimdas.o
obj-$(CONFIG_COMEDI_CB_PCIMDDA) += cb_pcimdda.o
obj-$(CONFIG_COMEDI_ME4000) += me4000.o
diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c
index ddba5db1e2e1..28c7fd3a96b6 100644
--- a/drivers/staging/comedi/drivers/acl7225b.c
+++ b/drivers/staging/comedi/drivers/acl7225b.c
@@ -81,7 +81,7 @@ static int acl7225b_attach(struct comedi_device *dev,
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* Relays outputs */
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE;
@@ -91,7 +91,7 @@ static int acl7225b_attach(struct comedi_device *dev,
s->range_table = &range_digital;
s->private = (void *)ACL7225_RIO_LO;
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* Relays status */
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
@@ -101,7 +101,7 @@ static int acl7225b_attach(struct comedi_device *dev,
s->range_table = &range_digital;
s->private = (void *)ACL7225_RIO_LO;
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
/* Isolated digital inputs */
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
deleted file mode 100644
index b973095146f9..000000000000
--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+++ /dev/null
@@ -1,195 +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 Dieselstraße 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 : ADDI HEADER READ WRITER | Compiler : Visual C++ |
- | Module name : S5920.cpp | Version : 6.0 |
- +-------------------------------+---------------------------------------+
- | Author : E. LIBS Date : 02/05/2002 |
- +-----------------------------------------------------------------------+
- | Description : DLL with the S5920 PCI Controller functions |
- +-----------------------------------------------------------------------+
- | UPDATE'S |
- +-----------------------------------------------------------------------+
- | Date | Author | Description of updates |
- +----------+-----------+------------------------------------------------+
- | 28/08/02 | LIBS Eric | Add return codes each time a function of the |
- | | | Addi Library is called |
- +-----------------------------------------------------------------------+
- | 31/07/03 | KRAUTH J. | Changes for the MSX-Box |
- +-----------------------------------------------------------------------+
-*/
-
-#include "addi_amcc_S5920.h"
-
-/*+----------------------------------------------------------------------------+*/
-/*| Function Name : int i_AddiHeaderRW_ReadEeprom |*/
-/*| (int i_NbOfWordsToRead, |*/
-/*| unsigned int dw_PCIBoardEepromAddress, |*/
-/*| unsigned short w_EepromStartAddress, |*/
-/*| unsigned short * pw_DataRead) |*/
-/*+----------------------------------------------------------------------------+*/
-/*| Task : Read word from the 5920 eeprom. |*/
-/*+----------------------------------------------------------------------------+*/
-/*| Input Parameters : int i_NbOfWordsToRead : Nbr. of word to read |*/
-/*| unsigned int dw_PCIBoardEepromAddress : Address of the eeprom |*/
-/*| unsigned short w_EepromStartAddress : Eeprom start address |*/
-/*+----------------------------------------------------------------------------+*/
-/*| Output Parameters : unsigned short * pw_DataRead : Read data |*/
-/*+----------------------------------------------------------------------------+*/
-/*| Return Value : - |*/
-/*+----------------------------------------------------------------------------+*/
-
-int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
- unsigned int dw_PCIBoardEepromAddress,
- unsigned short w_EepromStartAddress, unsigned short *pw_DataRead)
-{
- unsigned int dw_eeprom_busy = 0;
- int i_Counter = 0;
- int i_WordCounter;
- int i;
- unsigned char pb_ReadByte[1];
- unsigned char b_ReadLowByte = 0;
- unsigned char b_ReadHighByte = 0;
- unsigned char b_SelectedAddressLow = 0;
- unsigned char b_SelectedAddressHigh = 0;
- unsigned short w_ReadWord = 0;
-
- for (i_WordCounter = 0; i_WordCounter < i_NbOfWordsToRead;
- i_WordCounter++) {
- do {
- dw_eeprom_busy =
- inl(dw_PCIBoardEepromAddress +
- AMCC_OP_REG_MCSR);
- dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
- } while (dw_eeprom_busy == EEPROM_BUSY);
-
- for (i_Counter = 0; i_Counter < 2; i_Counter++) {
- b_SelectedAddressLow = (w_EepromStartAddress + i_Counter) % 256; /* Read the low 8 bit part */
- b_SelectedAddressHigh = (w_EepromStartAddress + i_Counter) / 256; /* Read the high 8 bit part */
-
- /* Select the load low address mode */
- outb(NVCMD_LOAD_LOW,
- dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
- 3);
-
- /* Wait on busy */
- do {
- dw_eeprom_busy =
- inl(dw_PCIBoardEepromAddress +
- AMCC_OP_REG_MCSR);
- dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
- } while (dw_eeprom_busy == EEPROM_BUSY);
-
- /* Load the low address */
- outb(b_SelectedAddressLow,
- dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
- 2);
-
- /* Wait on busy */
- do {
- dw_eeprom_busy =
- inl(dw_PCIBoardEepromAddress +
- AMCC_OP_REG_MCSR);
- dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
- } while (dw_eeprom_busy == EEPROM_BUSY);
-
- /* Select the load high address mode */
- outb(NVCMD_LOAD_HIGH,
- dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
- 3);
-
- /* Wait on busy */
- do {
- dw_eeprom_busy =
- inl(dw_PCIBoardEepromAddress +
- AMCC_OP_REG_MCSR);
- dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
- } while (dw_eeprom_busy == EEPROM_BUSY);
-
- /* Load the high address */
- outb(b_SelectedAddressHigh,
- dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
- 2);
-
- /* Wait on busy */
- do {
- dw_eeprom_busy =
- inl(dw_PCIBoardEepromAddress +
- AMCC_OP_REG_MCSR);
- dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
- } while (dw_eeprom_busy == EEPROM_BUSY);
-
- /* Select the READ mode */
- outb(NVCMD_BEGIN_READ,
- dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
- 3);
-
- /* Wait on busy */
- do {
- dw_eeprom_busy =
- inl(dw_PCIBoardEepromAddress +
- AMCC_OP_REG_MCSR);
- dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
- } while (dw_eeprom_busy == EEPROM_BUSY);
-
- /* Read data into the EEPROM */
- *pb_ReadByte =
- inb(dw_PCIBoardEepromAddress +
- AMCC_OP_REG_MCSR + 2);
-
- /* Wait on busy */
- do {
- dw_eeprom_busy =
- inl(dw_PCIBoardEepromAddress +
- AMCC_OP_REG_MCSR);
- dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
- } while (dw_eeprom_busy == EEPROM_BUSY);
-
- /* Select the upper address part */
- if (i_Counter == 0)
- b_ReadLowByte = pb_ReadByte[0];
- else
- b_ReadHighByte = pb_ReadByte[0];
-
- /* Sleep */
- msleep(1);
-
- }
- w_ReadWord =
- (b_ReadLowByte | (((unsigned short)b_ReadHighByte) *
- 256));
-
- pw_DataRead[i_WordCounter] = w_ReadWord;
-
- w_EepromStartAddress += 2; /* to read the next word */
-
- } /* for (...) i_NbOfWordsToRead */
- return 0;
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h
deleted file mode 100644
index 9afdb1357aa9..000000000000
--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.
- */
-
-#define AMCC_OP_REG_MCSR 0x3c
-#define EEPROM_BUSY 0x80000000
-#define NVCMD_LOAD_LOW (0x4 << 5) /* nvRam load low command */
-#define NVCMD_LOAD_HIGH (0x5 << 5) /* nvRam load high command */
-#define NVCMD_BEGIN_READ (0x7 << 5) /* nvRam begin read command */
-#define NVCMD_BEGIN_WRITE (0x6 << 5) /* EEPROM begin write command */
-
-int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
- unsigned int dw_PCIBoardEepromAddress,
- unsigned short w_EepromStartAddress, unsigned short *pw_DataRead);
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
index a3d4ed25fb0d..99a96bd96716 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
@@ -1669,7 +1669,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
return ret;
/* Allocate and Initialise AI Subdevice Structures */
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
if ((devpriv->s_EeParameters.i_NbrAiChannel)
|| (this_board->i_NbrAiChannelDiff)) {
dev->read_subdev = s;
@@ -1705,7 +1705,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
/* Allocate and Initialise AO Subdevice Structures */
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
if (devpriv->s_EeParameters.i_NbrAoChannel) {
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
@@ -1720,7 +1720,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->type = COMEDI_SUBD_UNUSED;
}
/* Allocate and Initialise DI Subdevice Structures */
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
if (devpriv->s_EeParameters.i_NbrDiChannel) {
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
@@ -1738,7 +1738,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->type = COMEDI_SUBD_UNUSED;
}
/* Allocate and Initialise DO Subdevice Structures */
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
if (devpriv->s_EeParameters.i_NbrDoChannel) {
s->type = COMEDI_SUBD_DO;
s->subdev_flags =
@@ -1760,7 +1760,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
/* Allocate and Initialise Timer Subdevice Structures */
- s = dev->subdevices + 4;
+ s = &dev->subdevices[4];
if (devpriv->s_EeParameters.i_Timer) {
s->type = COMEDI_SUBD_TIMER;
s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
@@ -1778,7 +1778,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
/* Allocate and Initialise TTL */
- s = dev->subdevices + 5;
+ s = &dev->subdevices[5];
if (this_board->i_NbrTTLChannel) {
s->type = COMEDI_SUBD_TTLIO;
s->subdev_flags =
@@ -1797,7 +1797,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
/* EEPROM */
- s = dev->subdevices + 6;
+ s = &dev->subdevices[6];
if (this_board->i_PCIEeprom) {
s->type = COMEDI_SUBD_MEMORY;
s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
diff --git a/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h b/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h
deleted file mode 100644
index c26c28c31b97..000000000000
--- a/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- Modified by umesh on 16th may 2001
- Modified by sarath on 22nd may 2001
-*/
-
-/*
- comedi/drivers/amcc_s5933_v_58.h
-
- Stuff for AMCC S5933 PCI Controller
-
- Author: Michal Dobes <majkl@tesnet.cz>
-
- Inspirated from general-purpose AMCC S5933 PCI Matchmaker driver
- made by Andrea Cisternino <acister@pcape1.pi.infn.it>
- and as result of espionage from MITE code made by David A. Schleef.
- Thanks to AMCC for their on-line documentation and bus master DMA
- example.
-*/
-
-#ifndef _AMCC_S5933_H_
-#define _AMCC_S5933_H_
-
-#include <linux/pci.h>
-#include "../../comedidev.h"
-
-/***********Added by sarath for compatibility with APCI3120
-
-*************************/
-
-#define FIFO_ADVANCE_ON_BYTE_2 0x20000000 /* written on base0 */
-
-#define AMWEN_ENABLE 0x02 /* added for step 6 dma written on base2 */
-#define A2P_FIFO_WRITE_ENABLE 0x01
-
-#define AGCSTS_TC_ENABLE 0x10000000 /* Added for transfer count enable bit */
-
-/* ADDON RELATED ADDITIONS */
-/* Constant */
-#define APCI3120_ENABLE_TRANSFER_ADD_ON_LOW 0x00
-#define APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH 0x1200
-#define APCI3120_A2P_FIFO_MANAGEMENT 0x04000400L
-#define APCI3120_AMWEN_ENABLE 0x02
-#define APCI3120_A2P_FIFO_WRITE_ENABLE 0x01
-#define APCI3120_FIFO_ADVANCE_ON_BYTE_2 0x20000000L
-#define APCI3120_ENABLE_WRITE_TC_INT 0x00004000L
-#define APCI3120_CLEAR_WRITE_TC_INT 0x00040000L
-#define APCI3120_DISABLE_AMWEN_AND_A2P_FIFO_WRITE 0x0
-#define APCI3120_DISABLE_BUS_MASTER_ADD_ON 0x0
-#define APCI3120_DISABLE_BUS_MASTER_PCI 0x0
-
- /* ADD_ON ::: this needed since apci supports 16 bit interface to add on */
-#define APCI3120_ADD_ON_AGCSTS_LOW 0x3C
-#define APCI3120_ADD_ON_AGCSTS_HIGH APCI3120_ADD_ON_AGCSTS_LOW + 2
-#define APCI3120_ADD_ON_MWAR_LOW 0x24
-#define APCI3120_ADD_ON_MWAR_HIGH APCI3120_ADD_ON_MWAR_LOW + 2
-#define APCI3120_ADD_ON_MWTC_LOW 0x058
-#define APCI3120_ADD_ON_MWTC_HIGH APCI3120_ADD_ON_MWTC_LOW + 2
-
-/* AMCC */
-#define APCI3120_AMCC_OP_MCSR 0x3C
-#define APCI3120_AMCC_OP_REG_INTCSR 0x38
-
-/*******from here all upward definitions are added by sarath */
-
-/****************************************************************************/
-/* AMCC Operation Register Offsets - PCI */
-/****************************************************************************/
-
-#define AMCC_OP_REG_OMB1 0x00
-#define AMCC_OP_REG_OMB2 0x04
-#define AMCC_OP_REG_OMB3 0x08
-#define AMCC_OP_REG_OMB4 0x0c
-#define AMCC_OP_REG_IMB1 0x10
-#define AMCC_OP_REG_IMB2 0x14
-#define AMCC_OP_REG_IMB3 0x18
-#define AMCC_OP_REG_IMB4 0x1c
-#define AMCC_OP_REG_FIFO 0x20
-#define AMCC_OP_REG_MWAR 0x24
-#define AMCC_OP_REG_MWTC 0x28
-#define AMCC_OP_REG_MRAR 0x2c
-#define AMCC_OP_REG_MRTC 0x30
-#define AMCC_OP_REG_MBEF 0x34
-#define AMCC_OP_REG_INTCSR 0x38
-#define AMCC_OP_REG_INTCSR_SRC (AMCC_OP_REG_INTCSR + 2) /* int source */
-#define AMCC_OP_REG_INTCSR_FEC (AMCC_OP_REG_INTCSR + 3) /* FIFO ctrl */
-#define AMCC_OP_REG_MCSR 0x3c
-#define AMCC_OP_REG_MCSR_NVDATA (AMCC_OP_REG_MCSR + 2) /* Data in byte 2 */
-#define AMCC_OP_REG_MCSR_NVCMD (AMCC_OP_REG_MCSR + 3) /* Command in byte 3 */
-
-#define AMCC_FIFO_DEPTH_DWORD 8
-#define AMCC_FIFO_DEPTH_BYTES (8 * sizeof (u32))
-
-/****************************************************************************/
-/* AMCC Operation Registers Size - PCI */
-/****************************************************************************/
-
-#define AMCC_OP_REG_SIZE 64 /* in bytes */
-
-/****************************************************************************/
-/* AMCC Operation Register Offsets - Add-on */
-/****************************************************************************/
-
-#define AMCC_OP_REG_AIMB1 0x00
-#define AMCC_OP_REG_AIMB2 0x04
-#define AMCC_OP_REG_AIMB3 0x08
-#define AMCC_OP_REG_AIMB4 0x0c
-#define AMCC_OP_REG_AOMB1 0x10
-#define AMCC_OP_REG_AOMB2 0x14
-#define AMCC_OP_REG_AOMB3 0x18
-#define AMCC_OP_REG_AOMB4 0x1c
-#define AMCC_OP_REG_AFIFO 0x20
-#define AMCC_OP_REG_AMWAR 0x24
-#define AMCC_OP_REG_APTA 0x28
-#define AMCC_OP_REG_APTD 0x2c
-#define AMCC_OP_REG_AMRAR 0x30
-#define AMCC_OP_REG_AMBEF 0x34
-#define AMCC_OP_REG_AINT 0x38
-#define AMCC_OP_REG_AGCSTS 0x3c
-#define AMCC_OP_REG_AMWTC 0x58
-#define AMCC_OP_REG_AMRTC 0x5c
-
-/****************************************************************************/
-/* AMCC - Add-on General Control/Status Register */
-/****************************************************************************/
-
-#define AGCSTS_CONTROL_MASK 0xfffff000
-#define AGCSTS_NV_ACC_MASK 0xe0000000
-#define AGCSTS_RESET_MASK 0x0e000000
-#define AGCSTS_NV_DA_MASK 0x00ff0000
-#define AGCSTS_BIST_MASK 0x0000f000
-#define AGCSTS_STATUS_MASK 0x000000ff
-#define AGCSTS_TCZERO_MASK 0x000000c0
-#define AGCSTS_FIFO_ST_MASK 0x0000003f
-
-#define AGCSTS_RESET_MBFLAGS 0x08000000
-#define AGCSTS_RESET_P2A_FIFO 0x04000000
-#define AGCSTS_RESET_A2P_FIFO 0x02000000
-#define AGCSTS_RESET_FIFOS (AGCSTS_RESET_A2P_FIFO | AGCSTS_RESET_P2A_FIFO)
-
-#define AGCSTS_A2P_TCOUNT 0x00000080
-#define AGCSTS_P2A_TCOUNT 0x00000040
-
-#define AGCSTS_FS_P2A_EMPTY 0x00000020
-#define AGCSTS_FS_P2A_HALF 0x00000010
-#define AGCSTS_FS_P2A_FULL 0x00000008
-
-#define AGCSTS_FS_A2P_EMPTY 0x00000004
-#define AGCSTS_FS_A2P_HALF 0x00000002
-#define AGCSTS_FS_A2P_FULL 0x00000001
-
-/****************************************************************************/
-/* AMCC - Add-on Interrupt Control/Status Register */
-/****************************************************************************/
-
-#define AINT_INT_MASK 0x00ff0000
-#define AINT_SEL_MASK 0x0000ffff
-#define AINT_IS_ENSEL_MASK 0x00001f1f
-
-#define AINT_INT_ASSERTED 0x00800000
-#define AINT_BM_ERROR 0x00200000
-#define AINT_BIST_INT 0x00100000
-
-#define AINT_RT_COMPLETE 0x00080000
-#define AINT_WT_COMPLETE 0x00040000
-
-#define AINT_OUT_MB_INT 0x00020000
-#define AINT_IN_MB_INT 0x00010000
-
-#define AINT_READ_COMPL 0x00008000
-#define AINT_WRITE_COMPL 0x00004000
-
-#define AINT_OMB_ENABLE 0x00001000
-#define AINT_OMB_SELECT 0x00000c00
-#define AINT_OMB_BYTE 0x00000300
-
-#define AINT_IMB_ENABLE 0x00000010
-#define AINT_IMB_SELECT 0x0000000c
-#define AINT_IMB_BYTE 0x00000003
-
-/* Enable Bus Mastering */
-#define EN_A2P_TRANSFERS 0x00000400
-/* FIFO Flag Reset */
-#define RESET_A2P_FLAGS 0x04000000L
-/* FIFO Relative Priority */
-#define A2P_HI_PRIORITY 0x00000100L
-/* Identify Interrupt Sources */
-#define ANY_S593X_INT 0x00800000L
-#define READ_TC_INT 0x00080000L
-#define WRITE_TC_INT 0x00040000L
-#define IN_MB_INT 0x00020000L
-#define MASTER_ABORT_INT 0x00100000L
-#define TARGET_ABORT_INT 0x00200000L
-#define BUS_MASTER_INT 0x00200000L
-
-/****************************************************************************/
-
-struct pcilst_struct {
- struct pcilst_struct *next;
- int used;
- struct pci_dev *pcidev;
- unsigned short vendor;
- unsigned short device;
- unsigned int master;
- unsigned char pci_bus;
- unsigned char pci_slot;
- unsigned char pci_func;
- unsigned int io_addr[5];
- unsigned int irq;
-};
-
-struct pcilst_struct *amcc_devices; /* ptr to root list of all amcc devices */
-
-/****************************************************************************/
-
-void v_pci_card_list_init(unsigned short pci_vendor, char display);
-void v_pci_card_list_cleanup(unsigned short pci_vendor);
-struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id,
- unsigned short
- device_id);
-int i_find_free_pci_card_by_position(unsigned short vendor_id,
- unsigned short device_id,
- unsigned short pci_bus,
- unsigned short pci_slot,
- struct pcilst_struct **card);
-struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id,
- unsigned short device_id,
- unsigned short pci_bus,
- unsigned short pci_slot);
-
-int i_pci_card_alloc(struct pcilst_struct *amcc);
-int i_pci_card_free(struct pcilst_struct *amcc);
-void v_pci_card_list_display(void);
-int i_pci_card_data(struct pcilst_struct *amcc,
- unsigned char *pci_bus, unsigned char *pci_slot,
- unsigned char *pci_func, unsigned short *io_addr,
- unsigned short *irq, unsigned short *master);
-
-/****************************************************************************/
-
-/* build list of amcc cards in this system */
-void v_pci_card_list_init(unsigned short pci_vendor, char display)
-{
- struct pci_dev *pcidev;
- struct pcilst_struct *amcc, *last;
- int i;
-
- amcc_devices = NULL;
- last = NULL;
-
- pci_for_each_dev(pcidev) {
- if (pcidev->vendor == pci_vendor) {
- amcc = kzalloc(sizeof(*amcc), GFP_KERNEL);
- if (amcc == NULL)
- continue;
-
- amcc->pcidev = pcidev;
- if (last) {
- last->next = amcc;
- } else {
- amcc_devices = amcc;
- }
- last = amcc;
-
- amcc->vendor = pcidev->vendor;
- amcc->device = pcidev->device;
-#if 0
- amcc->master = pcidev->master; /* how get this information under 2.4 kernels? */
-#endif
- amcc->pci_bus = pcidev->bus->number;
- amcc->pci_slot = PCI_SLOT(pcidev->devfn);
- amcc->pci_func = PCI_FUNC(pcidev->devfn);
- for (i = 0; i < 5; i++)
- amcc->io_addr[i] =
- pcidev->resource[i].start & ~3UL;
- amcc->irq = pcidev->irq;
- }
- }
-
- if (display)
- v_pci_card_list_display();
-}
-
-/****************************************************************************/
-/* free up list of amcc cards in this system */
-void v_pci_card_list_cleanup(unsigned short pci_vendor)
-{
- struct pcilst_struct *amcc, *next;
-
- for (amcc = amcc_devices; amcc; amcc = next) {
- next = amcc->next;
- kfree(amcc);
- }
-
- amcc_devices = NULL;
-}
-
-/****************************************************************************/
-/* find first unused card with this device_id */
-struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id,
- unsigned short device_id)
-{
- struct pcilst_struct *amcc, *next;
-
- for (amcc = amcc_devices; amcc; amcc = next) {
- next = amcc->next;
- if ((!amcc->used) && (amcc->device == device_id)
- && (amcc->vendor == vendor_id))
- return amcc;
-
- }
-
- return NULL;
-}
-
-/****************************************************************************/
-/* find card on requested position */
-int i_find_free_pci_card_by_position(unsigned short vendor_id,
- unsigned short device_id,
- unsigned short pci_bus,
- unsigned short pci_slot,
- struct pcilst_struct **card)
-{
- struct pcilst_struct *amcc, *next;
-
- *card = NULL;
- for (amcc = amcc_devices; amcc; amcc = next) {
- next = amcc->next;
- if ((amcc->vendor == vendor_id) && (amcc->device == device_id)
- && (amcc->pci_bus == pci_bus)
- && (amcc->pci_slot == pci_slot)) {
- if (!(amcc->used)) {
- *card = amcc;
- return 0; /* ok, card is found */
- } else {
- printk
- (" - \nCard on requested position is used b:s %d:%d!\n",
- pci_bus, pci_slot);
- return 2; /* card exist but is used */
- }
- }
- }
-
- return 1; /* no card found */
-}
-
-/****************************************************************************/
-/* mark card as used */
-int i_pci_card_alloc(struct pcilst_struct *amcc)
-{
- if (!amcc)
- return -1;
-
- if (amcc->used)
- return 1;
- amcc->used = 1;
- return 0;
-}
-
-/****************************************************************************/
-/* mark card as free */
-int i_pci_card_free(struct pcilst_struct *amcc)
-{
- if (!amcc)
- return -1;
-
- if (!amcc->used)
- return 1;
- amcc->used = 0;
- return 0;
-}
-
-/****************************************************************************/
-/* display list of found cards */
-void v_pci_card_list_display(void)
-{
- struct pcilst_struct *amcc, *next;
-
- printk("List of pci cards\n");
- printk("bus:slot:func vendor device master io_amcc io_daq irq used\n");
-
- for (amcc = amcc_devices; amcc; amcc = next) {
- next = amcc->next;
- printk
- ("%2d %2d %2d 0x%4x 0x%4x %3s 0x%4x 0x%4x %2d %2d\n",
- amcc->pci_bus, amcc->pci_slot, amcc->pci_func,
- amcc->vendor, amcc->device, amcc->master ? "yes" : "no",
- amcc->io_addr[0], amcc->io_addr[2], amcc->irq, amcc->used);
-
- }
-}
-
-/****************************************************************************/
-/* return all card information for driver */
-int i_pci_card_data(struct pcilst_struct *amcc,
- unsigned char *pci_bus, unsigned char *pci_slot,
- unsigned char *pci_func, unsigned short *io_addr,
- unsigned short *irq, unsigned short *master)
-{
- int i;
-
- if (!amcc)
- return -1;
- *pci_bus = amcc->pci_bus;
- *pci_slot = amcc->pci_slot;
- *pci_func = amcc->pci_func;
- for (i = 0; i < 5; i++)
- io_addr[i] = amcc->io_addr[i];
- *irq = amcc->irq;
- *master = amcc->master;
- return 0;
-}
-
-/****************************************************************************/
-/* select and alloc card */
-struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id,
- unsigned short device_id,
- unsigned short pci_bus,
- unsigned short pci_slot)
-{
- struct pcilst_struct *card;
-
- if ((pci_bus < 1) & (pci_slot < 1)) { /* use autodetection */
- card = ptr_find_free_pci_card_by_device(vendor_id, device_id);
- if (card == NULL) {
- printk(" - Unused card not found in system!\n");
- return NULL;
- }
- } else {
- switch (i_find_free_pci_card_by_position(vendor_id, device_id,
- pci_bus, pci_slot,
- &card)) {
- case 1:
- printk
- (" - Card not found on requested position b:s %d:%d!\n",
- pci_bus, pci_slot);
- return NULL;
- case 2:
- printk
- (" - Card on requested position is used b:s %d:%d!\n",
- pci_bus, pci_slot);
- return NULL;
- }
- }
-
- if (i_pci_card_alloc(card) != 0) {
- printk(" - Can't allocate card!\n");
- return NULL;
- }
-
- return card;
-}
-
-#endif
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
index 595238feaf42..f9a8937be8ed 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
@@ -67,7 +67,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev)
return;
/* Allocate and Initialise Timer Subdevice Structures */
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
s->type = COMEDI_SUBD_TIMER;
s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
@@ -81,7 +81,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev)
s->insn_bits = i_APCI1710_InsnBitsTimer;
/* Allocate and Initialise DIO Subdevice Structures */
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
s->type = COMEDI_SUBD_DIO;
s->subdev_flags =
@@ -96,7 +96,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev)
s->insn_write = i_APCI1710_InsnWriteDigitalIOChlOnOff;
/* Allocate and Initialise Chrono Subdevice Structures */
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
s->type = COMEDI_SUBD_CHRONO;
s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
@@ -110,7 +110,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev)
s->insn_bits = i_APCI1710_InsnBitsChronoDigitalIO;
/* Allocate and Initialise PWM Subdevice Structures */
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
s->type = COMEDI_SUBD_PWM;
s->subdev_flags =
SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON;
@@ -125,7 +125,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev)
s->insn_bits = i_APCI1710_InsnBitsReadPWMInterrupt;
/* Allocate and Initialise TTLIO Subdevice Structures */
- s = dev->subdevices + 4;
+ s = &dev->subdevices[4];
s->type = COMEDI_SUBD_TTLIO;
s->subdev_flags =
SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON;
@@ -139,7 +139,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev)
s->insn_read = i_APCI1710_InsnReadTTLIOAllPortValue;
/* Allocate and Initialise TOR Subdevice Structures */
- s = dev->subdevices + 5;
+ s = &dev->subdevices[5];
s->type = COMEDI_SUBD_TOR;
s->subdev_flags =
SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON;
@@ -154,7 +154,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev)
s->insn_bits = i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue;
/* Allocate and Initialise SSI Subdevice Structures */
- s = dev->subdevices + 6;
+ s = &dev->subdevices[6];
s->type = COMEDI_SUBD_SSI;
s->subdev_flags =
SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON;
@@ -167,7 +167,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev)
s->insn_bits = i_APCI1710_InsnBitsSSIDigitalIO;
/* Allocate and Initialise PULSEENCODER Subdevice Structures */
- s = dev->subdevices + 7;
+ s = &dev->subdevices[7];
s->type = COMEDI_SUBD_PULSEENCODER;
s->subdev_flags =
SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON;
@@ -181,7 +181,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev)
s->insn_read = i_APCI1710_InsnReadInterruptPulseEncoder;
/* Allocate and Initialise INCREMENTALCOUNTER Subdevice Structures */
- s = dev->subdevices + 8;
+ s = &dev->subdevices[8];
s->type = COMEDI_SUBD_INCREMENTALCOUNTER;
s->subdev_flags =
SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON;
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
index ffe390c6da83..f406dfb2a677 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
@@ -479,57 +479,26 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_s
struct comedi_cmd *cmd)
{
int err = 0;
- int tmp; /* divisor1,divisor2; */
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_EXT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_TIMER | 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 2: make sure trigger sources are unique and mutually compatible */
+ /* Step 2a : make sure trigger sources are unique */
- if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
- err++;
-
- if (cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_FOLLOW)
- err++;
-
- if (cmd->convert_src != TRIG_TIMER)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
- if (cmd->scan_end_src != TRIG_COUNT) {
- cmd->scan_end_src = TRIG_COUNT;
- err++;
- }
-
- if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
- err++;
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -1451,7 +1420,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
unsigned short us_TmpValue;
unsigned char b_DummyRead;
- struct comedi_subdevice *s = dev->subdevices + 0;
+ struct comedi_subdevice *s = &dev->subdevices[0];
ui_Check = 1;
int_daq = inw(dev->iobase + APCI3120_RD_STATUS) & 0xf000; /* get IRQ reasons */
@@ -1656,7 +1625,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
int i_APCI3120_InterruptHandleEos(struct comedi_device *dev)
{
int n_chan, i;
- struct comedi_subdevice *s = dev->subdevices + 0;
+ struct comedi_subdevice *s = &dev->subdevices[0];
int err = 1;
n_chan = devpriv->ui_AiNbrofChannels;
@@ -1698,7 +1667,7 @@ int i_APCI3120_InterruptHandleEos(struct comedi_device *dev)
void v_APCI3120_InterruptDma(int irq, void *d)
{
struct comedi_device *dev = d;
- struct comedi_subdevice *s = dev->subdevices + 0;
+ struct comedi_subdevice *s = &dev->subdevices[0];
unsigned int next_dma_buf, samplesinbuf;
unsigned long low_word, high_word, var;
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
index f9545b064eaf..38ab49917d7e 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
@@ -57,11 +57,8 @@ You should also find the complete GPL in the COPYING file accompanying this sour
+----------------------------------------------------------------------------+
*/
#include "hwdrv_apci3200.h"
-/* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-#include "addi_amcc_S5920.h"
-/* #define PRINT_INFO */
-/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+/* #define PRINT_INFO */
/* BEGIN JK 06.07.04: Management of sevrals boards */
/*
@@ -90,7 +87,12 @@ You should also find the complete GPL in the COPYING file accompanying this sour
struct str_BoardInfos s_BoardInfos[100]; /* 100 will be the max number of boards to be used */
/* END JK 06.07.04: Management of sevrals boards */
-/* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+#define AMCC_OP_REG_MCSR 0x3c
+#define EEPROM_BUSY 0x80000000
+#define NVCMD_LOAD_LOW (0x4 << 5) /* nvRam load low command */
+#define NVCMD_LOAD_HIGH (0x5 << 5) /* nvRam load high command */
+#define NVCMD_BEGIN_READ (0x7 << 5) /* nvRam begin read command */
+#define NVCMD_BEGIN_WRITE (0x6 << 5) /* EEPROM begin write command */
/*+----------------------------------------------------------------------------+*/
/*| Function Name : int i_AddiHeaderRW_ReadEeprom |*/
@@ -2558,7 +2560,6 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_s
{
int err = 0;
- int tmp; /* divisor1,divisor2; */
unsigned int ui_ConvertTime = 0;
unsigned int ui_ConvertTimeBase = 0;
unsigned int ui_DelayTime = 0;
@@ -2569,41 +2570,32 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_s
int i_Cpt = 0;
double d_ConversionTimeForAllChannels = 0.0;
double d_SCANTimeNewUnit = 0.0;
- /* step 1: make sure trigger sources are trivially valid */
-
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_EXT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
- /* if(i_InterruptFlag==0) */
- if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) {
- err++;
- /* printk("\nThe interrupt should be enabled\n"); */
- }
+
+ /* Step 1 : check if triggers are trivially valid */
+
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_TIMER | 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 (s_BoardInfos[dev->minor].i_InterruptFlag == 0)
+ err |= -EINVAL;
+
if (err) {
i_APCI3200_Reset(dev);
return 1;
}
- if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) {
- err++;
- }
+ /* Step 2a : make sure trigger sources are unique */
+
+ err |= cfc_check_trigger_is_unique(&cmd->start_src);
+ err |= cfc_check_trigger_is_unique(&cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(&cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
+
if (cmd->start_src == TRIG_EXT) {
i_TriggerEdge = cmd->start_arg & 0xFFFF;
i_Triggermode = cmd->start_arg >> 16;
@@ -2617,21 +2609,6 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_s
}
}
- if (cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_FOLLOW)
- err++;
-
- if (cmd->convert_src != TRIG_TIMER)
- err++;
-
- if (cmd->scan_end_src != TRIG_COUNT) {
- cmd->scan_end_src = TRIG_COUNT;
- err++;
- }
-
- if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
- err++;
-
if (err) {
i_APCI3200_Reset(dev);
return 2;
@@ -3495,7 +3472,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
int i_APCI3200_InterruptHandleEos(struct comedi_device *dev)
{
unsigned int ui_StatusRegister = 0;
- struct comedi_subdevice *s = dev->subdevices + 0;
+ struct comedi_subdevice *s = &dev->subdevices[0];
/* BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
/* comedi_async *async = s->async; */
diff --git a/drivers/staging/comedi/drivers/addi_apci_all.c b/drivers/staging/comedi/drivers/addi_apci_all.c
deleted file mode 100644
index aeb1b2688f3d..000000000000
--- a/drivers/staging/comedi/drivers/addi_apci_all.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#define CONFIG_APCI_035 1
-#define CONFIG_APCI_1032 1
-#define CONFIG_APCI_1500 1
-#define CONFIG_APCI_1516 1
-#define CONFIG_APCI_1564 1
-#define CONFIG_APCI_16XX 1
-#define CONFIG_APCI_1710 1
-#define CONFIG_APCI_2016 1
-#define CONFIG_APCI_2032 1
-#define CONFIG_APCI_2200 1
-#define CONFIG_APCI_3001 1
-#define CONFIG_APCI_3120 1
-#define CONFIG_APCI_3200 1
-#define CONFIG_APCI_3300 1
-#define CONFIG_APCI_3501 1
-#define CONFIG_APCI_3XXX 1
-
-#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
index 3bec0f6e4a8c..3492ce1156e0 100644
--- a/drivers/staging/comedi/drivers/adl_pci6208.c
+++ b/drivers/staging/comedi/drivers/adl_pci6208.c
@@ -27,14 +27,14 @@
*/
/*
Driver: adl_pci6208
-Description: ADLink PCI-6208A
-Devices: [ADLink] PCI-6208A (adl_pci6208)
+Description: ADLink PCI-6208/6216 Series Multi-channel Analog Output Cards
+Devices: (ADLink) PCI-6208 [adl_pci6208]
+ (ADLink) PCI-6216 [adl_pci6216]
Author: nsyeow <nsyeow@pd.jaring.my>
Updated: Fri, 30 Jan 2004 14:44:27 +0800
Status: untested
-Configuration Options:
- none
+Configuration Options: not applicable, uses PCI auto config
References:
- ni_660x.c
@@ -45,6 +45,12 @@ References:
#include "../comedidev.h"
/*
+ * ADLINK PCI Device ID's supported by this driver
+ */
+#define PCI_DEVICE_ID_PCI6208 0x6208
+#define PCI_DEVICE_ID_PCI6216 0x6216
+
+/*
* PCI-6208/6216-GL register map
*/
#define PCI6208_AO_CONTROL(x) (0x00 + (2 * (x)))
@@ -56,7 +62,7 @@ References:
#define PCI6208_DIO_DI_MASK (0xf0)
#define PCI6208_DIO_DI_SHIFT (4)
-#define PCI6208_MAX_AO_CHANNELS 8
+#define PCI6208_MAX_AO_CHANNELS 16
struct pci6208_board {
const char *name;
@@ -66,9 +72,13 @@ struct pci6208_board {
static const struct pci6208_board pci6208_boards[] = {
{
- .name = "pci6208a",
- .dev_id = 0x6208,
+ .name = "adl_pci6208",
+ .dev_id = PCI_DEVICE_ID_PCI6208,
.ao_chans = 8,
+ }, {
+ .name = "adl_pci6216",
+ .dev_id = PCI_DEVICE_ID_PCI6216,
+ .ao_chans = 16,
},
};
@@ -115,141 +125,122 @@ static int pci6208_ao_rinsn(struct comedi_device *dev,
return insn->n;
}
-static int pci6208_dio_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
+static int pci6208_di_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ unsigned int val;
+
+ val = inw(dev->iobase + PCI6208_DIO);
+ val = (val & PCI6208_DIO_DI_MASK) >> PCI6208_DIO_DI_SHIFT;
+
+ data[1] = val;
+
+ return insn->n;
+}
+
+static int pci6208_do_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- unsigned int mask = data[0] & PCI6208_DIO_DO_MASK;
+ unsigned int mask = data[0];
unsigned int bits = data[1];
if (mask) {
s->state &= ~mask;
- s->state |= bits & mask;
+ s->state |= (bits & mask);
outw(s->state, dev->iobase + PCI6208_DIO);
}
- s->state = inw(dev->iobase + PCI6208_DIO);
data[1] = s->state;
return insn->n;
}
-static int pci6208_dio_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- int chan = CR_CHAN(insn->chanspec);
- unsigned int mask = 1 << chan;
-
- switch (data[0]) {
- case INSN_CONFIG_DIO_QUERY:
- data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
- break;
- default:
- return -EINVAL;
- }
-
- return insn->n;
-}
-
-static struct pci_dev *pci6208_find_device(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static const void *pci6208_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- const struct pci6208_board *thisboard;
- struct pci_dev *pci_dev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
+ const struct pci6208_board *boardinfo;
int i;
- for_each_pci_dev(pci_dev) {
- if (pci_dev->vendor != PCI_VENDOR_ID_ADLINK)
- continue;
- for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) {
- thisboard = &pci6208_boards[i];
- if (thisboard->dev_id != pci_dev->device)
- continue;
- /* was a particular bus/slot requested? */
- if (bus || slot) {
- /* are we on the wrong bus/slot? */
- if (pci_dev->bus->number != bus ||
- PCI_SLOT(pci_dev->devfn) != slot)
- continue;
- }
- dev_dbg(dev->class_dev,
- "Found %s on bus %d, slot, %d, irq=%d\n",
- thisboard->name,
- pci_dev->bus->number,
- PCI_SLOT(pci_dev->devfn),
- pci_dev->irq);
- dev->board_ptr = thisboard;
- return pci_dev;
- }
+ for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) {
+ boardinfo = &pci6208_boards[i];
+ if (boardinfo->dev_id == pcidev->device)
+ return boardinfo;
}
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
return NULL;
}
-static int pci6208_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int pci6208_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- const struct pci6208_board *thisboard;
+ const struct pci6208_board *boardinfo;
struct pci6208_private *devpriv;
- struct pci_dev *pcidev;
struct comedi_subdevice *s;
+ unsigned int val;
int ret;
+ comedi_set_hw_dev(dev, &pcidev->dev);
+
+ boardinfo = pci6208_find_boardinfo(dev, pcidev);
+ if (!boardinfo)
+ return -ENODEV;
+ dev->board_ptr = boardinfo;
+ dev->board_name = boardinfo->name;
+
ret = alloc_private(dev, sizeof(*devpriv));
if (ret < 0)
return ret;
devpriv = dev->private;
- pcidev = pci6208_find_device(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
- thisboard = comedi_board(dev);
-
- dev->board_name = thisboard->name;
-
- ret = comedi_pci_enable(pcidev, dev->driver->driver_name);
- if (ret) {
- dev_err(dev->class_dev,
- "Failed to enable PCI device and request regions\n");
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
return ret;
- }
dev->iobase = pci_resource_start(pcidev, 2);
- ret = comedi_alloc_subdevices(dev, 2);
+ ret = comedi_alloc_subdevices(dev, 3);
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* analog output subdevice */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
- s->n_chan = thisboard->ao_chans;
+ s->n_chan = boardinfo->ao_chans;
s->maxdata = 0xffff;
s->range_table = &range_bipolar10;
s->insn_write = pci6208_ao_winsn;
s->insn_read = pci6208_ao_rinsn;
- s = dev->subdevices + 1;
- /* digital i/o subdevice */
- s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = 8;
+ s = &dev->subdevices[1];
+ /* digital input subdevice */
+ 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 = pci6208_dio_insn_bits;
- s->insn_config = pci6208_dio_insn_config;
+ s->insn_bits = pci6208_di_insn_bits;
+ s = &dev->subdevices[2];
+ /* digital output subdevice */
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = 4;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = pci6208_do_insn_bits;
+
+ /*
+ * Get the read back signals from the digital outputs
+ * and save it as the initial state for the subdevice.
+ */
+ val = inw(dev->iobase + PCI6208_DIO);
+ val = (val & PCI6208_DIO_DO_MASK) >> PCI6208_DIO_DO_SHIFT;
+ s->state = val;
s->io_bits = 0x0f;
- s->state = inw(dev->iobase + PCI6208_DIO);
dev_info(dev->class_dev, "%s: %s, I/O base=0x%04lx\n",
dev->driver->driver_name, dev->board_name, dev->iobase);
@@ -264,14 +255,13 @@ static void pci6208_detach(struct comedi_device *dev)
if (pcidev) {
if (dev->iobase)
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
}
}
static struct comedi_driver adl_pci6208_driver = {
.driver_name = "adl_pci6208",
.module = THIS_MODULE,
- .attach = pci6208_attach,
+ .attach_pci = pci6208_attach_pci,
.detach = pci6208_detach,
};
@@ -287,7 +277,8 @@ static void __devexit adl_pci6208_pci_remove(struct pci_dev *dev)
}
static DEFINE_PCI_DEVICE_TABLE(adl_pci6208_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x6208) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI6208) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI6216) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, adl_pci6208_pci_table);
diff --git a/drivers/staging/comedi/drivers/adl_pci7230.c b/drivers/staging/comedi/drivers/adl_pci7230.c
deleted file mode 100644
index 7df4c960d5e4..000000000000
--- a/drivers/staging/comedi/drivers/adl_pci7230.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- comedi/drivers/adl_pci7230.c
-
- Hardware comedi driver fot PCI7230 Adlink card
- Copyright (C) 2010 David Fernandez <dfcastelao@gmail.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.
-
-*/
-/*
-Driver: adl_pci7230
-Description: Driver for the Adlink PCI-7230 32 ch. isolated digital io board
-Devices: [ADLink] PCI-7230 (adl_pci7230)
-Author: David Fernandez <dfcastelao@gmail.com>
-Status: experimental
-Updated: Mon, 14 Apr 2008 15:08:14 +0100
-
-Configuration Options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
- If bus/slot is not specified, the first supported
- PCI device found will be used.
-*/
-
-#include "../comedidev.h"
-#include <linux/kernel.h>
-
-#define PCI7230_DI 0x00
-#define PCI7230_DO 0x00
-
-#define PCI_DEVICE_ID_PCI7230 0x7230
-
-static int adl_pci7230_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]);
-
- outl((s->state << 16) & 0xffffffff, dev->iobase + PCI7230_DO);
- }
-
- return insn->n;
-}
-
-static int adl_pci7230_di_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- data[1] = inl(dev->iobase + PCI7230_DI) & 0xffffffff;
-
- return insn->n;
-}
-
-static struct pci_dev *adl_pci7230_find_pci(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
-
- for_each_pci_dev(pcidev) {
- if (pcidev->vendor != PCI_VENDOR_ID_ADLINK ||
- pcidev->device != PCI_DEVICE_ID_PCI7230)
- continue;
- if (bus || slot) {
- /* requested particular bus/slot */
- if (pcidev->bus->number != bus ||
- PCI_SLOT(pcidev->devfn) != slot)
- continue;
- }
- return pcidev;
- }
- printk(KERN_ERR "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
- dev->minor, bus, slot);
- return NULL;
-}
-
-static int adl_pci7230_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct comedi_subdevice *s;
- struct pci_dev *pcidev;
- int ret;
-
- printk(KERN_INFO "comedi%d: adl_pci7230\n", dev->minor);
-
- dev->board_name = "pci7230";
-
- ret = comedi_alloc_subdevices(dev, 2);
- if (ret)
- return ret;
-
- pcidev = adl_pci7230_find_pci(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
-
- if (comedi_pci_enable(pcidev, "adl_pci7230") < 0) {
- printk(KERN_ERR "comedi%d: Failed to enable PCI device and request regions\n",
- dev->minor);
- return -EIO;
- }
- dev->iobase = pci_resource_start(pcidev, 2);
- printk(KERN_DEBUG "comedi: base addr %4lx\n", dev->iobase);
-
- s = dev->subdevices + 0;
- /* Isolated do */
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = 16;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = adl_pci7230_do_insn_bits;
-
- s = dev->subdevices + 1;
- /* Isolated di */
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = 16;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = adl_pci7230_di_insn_bits;
-
- printk(KERN_DEBUG "comedi: attached\n");
-
- return 1;
-}
-
-static void adl_pci7230_detach(struct comedi_device *dev)
-{
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
- if (pcidev) {
- if (dev->iobase)
- comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
- }
-}
-
-static struct comedi_driver adl_pci7230_driver = {
- .driver_name = "adl_pci7230",
- .module = THIS_MODULE,
- .attach = adl_pci7230_attach,
- .detach = adl_pci7230_detach,
-};
-
-static int __devinit adl_pci7230_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- return comedi_pci_auto_config(dev, &adl_pci7230_driver);
-}
-
-static void __devexit adl_pci7230_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static DEFINE_PCI_DEVICE_TABLE(adl_pci7230_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7230) },
- { 0 }
-};
-MODULE_DEVICE_TABLE(pci, adl_pci7230_pci_table);
-
-static struct pci_driver adl_pci7230_pci_driver = {
- .name = "adl_pci7230",
- .id_table = adl_pci7230_pci_table,
- .probe = adl_pci7230_pci_probe,
- .remove = __devexit_p(adl_pci7230_pci_remove),
-};
-module_comedi_pci_driver(adl_pci7230_driver, adl_pci7230_pci_driver);
-
-MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c
deleted file mode 100644
index 19b47af9c10e..000000000000
--- a/drivers/staging/comedi/drivers/adl_pci7296.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- comedi/drivers/adl_pci7296.c
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 2000 David A. Schleef <ds@schleef.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-/*
-Driver: adl_pci7296
-Description: Driver for the Adlink PCI-7296 96 ch. digital io board
-Devices: [ADLink] PCI-7296 (adl_pci7296)
-Author: Jon Grierson <jd@renko.co.uk>
-Updated: Mon, 14 Apr 2008 15:05:56 +0100
-Status: testing
-
-Configuration Options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
- If bus/slot is not specified, the first supported
- PCI device found will be used.
-*/
-
-#include "../comedidev.h"
-#include <linux/kernel.h>
-
-#include "8255.h"
-/* #include "8253.h" */
-
-#define PORT1A 0
-#define PORT2A 4
-#define PORT3A 8
-#define PORT4A 12
-
-#define PCI_DEVICE_ID_PCI7296 0x7296
-
-static struct pci_dev *adl_pci7296_find_pci(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
-
- for_each_pci_dev(pcidev) {
- if (pcidev->vendor != PCI_VENDOR_ID_ADLINK ||
- pcidev->device != PCI_DEVICE_ID_PCI7296)
- continue;
- if (bus || slot) {
- /* requested particular bus/slot */
- if (pcidev->bus->number != bus ||
- PCI_SLOT(pcidev->devfn) != slot)
- continue;
- }
- return pcidev;
- }
- printk(KERN_ERR
- "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
- dev->minor, bus, slot);
- return NULL;
-}
-
-static int adl_pci7296_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev;
- struct comedi_subdevice *s;
- int ret;
-
- printk(KERN_INFO "comedi%d: attach adl_pci7432\n", dev->minor);
-
- dev->board_name = "pci7432";
-
- ret = comedi_alloc_subdevices(dev, 4);
- if (ret)
- return ret;
-
- pcidev = adl_pci7296_find_pci(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
-
- if (comedi_pci_enable(pcidev, "adl_pci7296") < 0) {
- printk(KERN_ERR
- "comedi%d: Failed to enable PCI device and request regions\n",
- dev->minor);
- return -EIO;
- }
-
- dev->iobase = pci_resource_start(pcidev, 2);
- printk(KERN_INFO "comedi: base addr %4lx\n", dev->iobase);
-
- /* four 8255 digital io subdevices */
- s = dev->subdevices + 0;
- subdev_8255_init(dev, s, NULL, (unsigned long)(dev->iobase));
-
- s = dev->subdevices + 1;
- ret = subdev_8255_init(dev, s, NULL,
- (unsigned long)(dev->iobase + PORT2A));
- if (ret < 0)
- return ret;
-
- s = dev->subdevices + 2;
- ret = subdev_8255_init(dev, s, NULL,
- (unsigned long)(dev->iobase + PORT3A));
- if (ret < 0)
- return ret;
-
- s = dev->subdevices + 3;
- ret = subdev_8255_init(dev, s, NULL,
- (unsigned long)(dev->iobase + PORT4A));
- if (ret < 0)
- return ret;
-
- printk(KERN_DEBUG "comedi%d: adl_pci7432 attached\n", dev->minor);
-
- return 0;
-}
-
-static void adl_pci7296_detach(struct comedi_device *dev)
-{
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
- if (pcidev) {
- if (dev->iobase)
- comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
- }
- if (dev->subdevices) {
- subdev_8255_cleanup(dev, dev->subdevices + 0);
- subdev_8255_cleanup(dev, dev->subdevices + 1);
- subdev_8255_cleanup(dev, dev->subdevices + 2);
- subdev_8255_cleanup(dev, dev->subdevices + 3);
- }
-}
-
-static struct comedi_driver adl_pci7296_driver = {
- .driver_name = "adl_pci7296",
- .module = THIS_MODULE,
- .attach = adl_pci7296_attach,
- .detach = adl_pci7296_detach,
-};
-
-static int __devinit adl_pci7296_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- return comedi_pci_auto_config(dev, &adl_pci7296_driver);
-}
-
-static void __devexit adl_pci7296_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static DEFINE_PCI_DEVICE_TABLE(adl_pci7296_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7296) },
- { 0 }
-};
-MODULE_DEVICE_TABLE(pci, adl_pci7296_pci_table);
-
-static struct pci_driver adl_pci7296_pci_driver = {
- .name = "adl_pci7296",
- .id_table = adl_pci7296_pci_table,
- .probe = adl_pci7296_pci_probe,
- .remove = __devexit_p(adl_pci7296_pci_remove),
-};
-module_comedi_pci_driver(adl_pci7296_driver, adl_pci7296_pci_driver);
-
-MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c
deleted file mode 100644
index 6b8d9408e3bc..000000000000
--- a/drivers/staging/comedi/drivers/adl_pci7432.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- comedi/drivers/adl_pci7432.c
-
- Hardware comedi driver fot PCI7432 Adlink card
- Copyright (C) 2004 Michel Lachine <mike@mikelachaine.ca>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-/*
-Driver: adl_pci7432
-Description: Driver for the Adlink PCI-7432 64 ch. isolated digital io board
-Devices: [ADLink] PCI-7432 (adl_pci7432)
-Author: Michel Lachaine <mike@mikelachaine.ca>
-Status: experimental
-Updated: Mon, 14 Apr 2008 15:08:14 +0100
-
-Configuration Options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
- If bus/slot is not specified, the first supported
- PCI device found will be used.
-*/
-
-#include "../comedidev.h"
-#include <linux/kernel.h>
-
-#define PCI7432_DI 0x00
-#define PCI7432_DO 0x00
-
-#define PCI_DEVICE_ID_PCI7432 0x7432
-
-static int adl_pci7432_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- printk(KERN_DEBUG "comedi: pci7432_do_insn_bits called\n");
- printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]);
-
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
-
- printk(KERN_DEBUG "comedi: out: %8x on iobase %4lx\n", s->state,
- dev->iobase + PCI7432_DO);
- outl(s->state & 0xffffffff, dev->iobase + PCI7432_DO);
- }
- return insn->n;
-}
-
-static int adl_pci7432_di_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- printk(KERN_DEBUG "comedi: pci7432_di_insn_bits called\n");
- printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]);
-
- data[1] = inl(dev->iobase + PCI7432_DI) & 0xffffffff;
- printk(KERN_DEBUG "comedi: data1 %8x\n", data[1]);
-
- return insn->n;
-}
-
-static struct pci_dev *adl_pci7432_find_pci(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
-
- for_each_pci_dev(pcidev) {
- if (pcidev->vendor != PCI_VENDOR_ID_ADLINK ||
- pcidev->device != PCI_DEVICE_ID_PCI7432)
- continue;
- if (bus || slot) {
- /* requested particular bus/slot */
- if (pcidev->bus->number != bus ||
- PCI_SLOT(pcidev->devfn) != slot)
- continue;
- }
- return pcidev;
- }
- printk(KERN_ERR
- "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
- dev->minor, bus, slot);
- return NULL;
-}
-
-static int adl_pci7432_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev;
- struct comedi_subdevice *s;
- int ret;
-
- printk(KERN_INFO "comedi%d: attach adl_pci7432\n", dev->minor);
-
- dev->board_name = "pci7432";
-
- ret = comedi_alloc_subdevices(dev, 2);
- if (ret)
- return ret;
-
- pcidev = adl_pci7432_find_pci(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
-
- if (comedi_pci_enable(pcidev, "adl_pci7432") < 0) {
- printk(KERN_ERR "comedi%d: Failed to enable PCI device and request regions\n",
- dev->minor);
- return -EIO;
- }
- dev->iobase = pci_resource_start(pcidev, 2);
- printk(KERN_INFO "comedi: base addr %4lx\n", dev->iobase);
-
- s = dev->subdevices + 0;
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = 32;
- s->maxdata = 1;
- s->len_chanlist = 32;
- s->io_bits = 0x00000000;
- s->range_table = &range_digital;
- s->insn_bits = adl_pci7432_di_insn_bits;
-
- s = dev->subdevices + 1;
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = 32;
- s->maxdata = 1;
- s->len_chanlist = 32;
- s->io_bits = 0xffffffff;
- s->range_table = &range_digital;
- s->insn_bits = adl_pci7432_do_insn_bits;
-
- printk(KERN_DEBUG "comedi%d: adl_pci7432 attached\n", dev->minor);
- return 0;
-}
-
-static void adl_pci7432_detach(struct comedi_device *dev)
-{
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
- if (pcidev) {
- if (dev->iobase)
- comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
- }
-}
-
-static struct comedi_driver adl_pci7432_driver = {
- .driver_name = "adl_pci7432",
- .module = THIS_MODULE,
- .attach = adl_pci7432_attach,
- .detach = adl_pci7432_detach,
-};
-
-static int __devinit adl_pci7432_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- return comedi_pci_auto_config(dev, &adl_pci7432_driver);
-}
-
-static void __devexit adl_pci7432_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static DEFINE_PCI_DEVICE_TABLE(adl_pci7432_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7432) },
- { 0 }
-};
-MODULE_DEVICE_TABLE(pci, adl_pci7432_pci_table);
-
-static struct pci_driver adl_pci7432_pci_driver = {
- .name = "adl_pci7432",
- .id_table = adl_pci7432_pci_table,
- .probe = adl_pci7432_pci_probe,
- .remove = __devexit_p(adl_pci7432_pci_remove),
-};
-module_comedi_pci_driver(adl_pci7432_driver, adl_pci7432_pci_driver);
-
-MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c
new file mode 100644
index 000000000000..599714e978b5
--- /dev/null
+++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c
@@ -0,0 +1,332 @@
+/*
+ * COMEDI driver for the ADLINK PCI-723x/743x series boards.
+ * Copyright (C) 2012 H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * Based on the adl_pci7230 driver written by:
+ * David Fernandez <dfcastelao@gmail.com>
+ * and the adl_pci7432 driver written by:
+ * Michel Lachaine <mike@mikelachaine.ca>
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+Driver: adl_pci7x3x
+Description: 32/64-Channel Isolated Digital I/O Boards
+Devices: (ADLink) PCI-7230 [adl_pci7230] - 16 input / 16 output
+ (ADLink) PCI-7233 [adl_pci7233] - 32 input
+ (ADLink) PCI-7234 [adl_pci7234] - 32 output
+ (ADLink) PCI-7432 [adl_pci7432] - 32 input / 32 output
+ (ADLink) PCI-7433 [adl_pci7433] - 64 input
+ (ADLink) PCI-7434 [adl_pci7434] - 64 output
+Author: H Hartley Sweeten <hsweeten@visionengravers.com>
+Updated: Thu, 02 Aug 2012 14:27:46 -0700
+Status: untested
+
+This driver only attaches using the PCI PnP auto config support
+in the comedi core. The module parameter 'comedi_autoconfig'
+must be 1 (default) to enable this feature. The COMEDI_DEVCONFIG
+ioctl, used by the comedi_config utility, is not supported by
+this driver.
+
+The PCI-7230, PCI-7432 and PCI-7433 boards also support external
+interrupt signals on digital input channels 0 and 1. The PCI-7233
+has dual-interrupt sources for change-of-state (COS) on any 16
+digital input channels of LSB and for COS on any 16 digital input
+lines of MSB. Interrupts are not currently supported by this
+driver.
+
+Configuration Options: not applicable
+*/
+
+#include "../comedidev.h"
+
+/*
+ * PCI Device ID's supported by this driver
+ */
+#define PCI_DEVICE_ID_PCI7230 0x7230
+#define PCI_DEVICE_ID_PCI7233 0x7233
+#define PCI_DEVICE_ID_PCI7234 0x7234
+#define PCI_DEVICE_ID_PCI7432 0x7432
+#define PCI_DEVICE_ID_PCI7433 0x7433
+#define PCI_DEVICE_ID_PCI7434 0x7434
+
+/*
+ * Register I/O map (32-bit access only)
+ */
+#define PCI7X3X_DIO_REG 0x00
+#define PCI743X_DIO_REG 0x04
+
+struct adl_pci7x3x_boardinfo {
+ const char *name;
+ unsigned short device;
+ int nsubdevs;
+ int di_nchan;
+ int do_nchan;
+};
+
+static const struct adl_pci7x3x_boardinfo adl_pci7x3x_boards[] = {
+ {
+ .name = "adl_pci7230",
+ .device = PCI_DEVICE_ID_PCI7230,
+ .nsubdevs = 2,
+ .di_nchan = 16,
+ .do_nchan = 16,
+ }, {
+ .name = "adl_pci7233",
+ .device = PCI_DEVICE_ID_PCI7233,
+ .nsubdevs = 1,
+ .di_nchan = 32,
+ }, {
+ .name = "adl_pci7234",
+ .device = PCI_DEVICE_ID_PCI7234,
+ .nsubdevs = 1,
+ .do_nchan = 32,
+ }, {
+ .name = "adl_pci7432",
+ .device = PCI_DEVICE_ID_PCI7432,
+ .nsubdevs = 2,
+ .di_nchan = 32,
+ .do_nchan = 32,
+ }, {
+ .name = "adl_pci7433",
+ .device = PCI_DEVICE_ID_PCI7433,
+ .nsubdevs = 2,
+ .di_nchan = 64,
+ }, {
+ .name = "adl_pci7434",
+ .device = PCI_DEVICE_ID_PCI7434,
+ .nsubdevs = 2,
+ .do_nchan = 64,
+ }
+};
+
+static int adl_pci7x3x_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);
+
+ outl(s->state, dev->iobase + reg);
+ }
+
+ /*
+ * NOTE: The output register is not readable.
+ * This returned state will not be correct until all the
+ * outputs have been updated.
+ */
+ data[1] = s->state;
+
+ return insn->n;
+}
+
+static int adl_pci7x3x_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] = inl(dev->iobase + reg);
+
+ return insn->n;
+}
+
+static const void *adl_pci7x3x_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
+{
+ const struct adl_pci7x3x_boardinfo *board;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(adl_pci7x3x_boards); i++) {
+ board = &adl_pci7x3x_boards[i];
+ if (pcidev->device == board->device)
+ return board;
+ }
+ return NULL;
+}
+
+static int adl_pci7x3x_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
+{
+ const struct adl_pci7x3x_boardinfo *board;
+ struct comedi_subdevice *s;
+ int subdev;
+ int nchan;
+ int ret;
+
+ comedi_set_hw_dev(dev, &pcidev->dev);
+
+ board = adl_pci7x3x_find_boardinfo(dev, pcidev);
+ if (!board)
+ return -ENODEV;
+ dev->board_ptr = board;
+ dev->board_name = board->name;
+
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
+ dev->iobase = pci_resource_start(pcidev, 2);
+
+ /*
+ * One or two subdevices are setup by this driver depending on
+ * the number of digital inputs and/or outputs provided by the
+ * board. Each subdevice has a maximum of 32 channels.
+ *
+ * PCI-7230 - 2 subdevices: 0 - 16 input, 1 - 16 output
+ * PCI-7233 - 1 subdevice: 0 - 32 input
+ * PCI-7234 - 1 subdevice: 0 - 32 output
+ * PCI-7432 - 2 subdevices: 0 - 32 input, 1 - 32 output
+ * PCI-7433 - 2 subdevices: 0 - 32 input, 1 - 32 input
+ * PCI-7434 - 2 subdevices: 0 - 32 output, 1 - 32 output
+ */
+ ret = comedi_alloc_subdevices(dev, board->nsubdevs);
+ if (ret)
+ return ret;
+
+ subdev = 0;
+
+ if (board->di_nchan) {
+ nchan = min(board->di_nchan, 32);
+
+ s = &dev->subdevices[subdev];
+ /* Isolated digital inputs 0 to 15/31 */
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = nchan;
+ s->maxdata = 1;
+ s->insn_bits = adl_pci7x3x_di_insn_bits;
+ s->range_table = &range_digital;
+
+ s->private = (void *)PCI7X3X_DIO_REG;
+
+ subdev++;
+
+ nchan = board->di_nchan - nchan;
+ if (nchan) {
+ s = &dev->subdevices[subdev];
+ /* Isolated digital inputs 32 to 63 */
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = nchan;
+ s->maxdata = 1;
+ s->insn_bits = adl_pci7x3x_di_insn_bits;
+ s->range_table = &range_digital;
+
+ s->private = (void *)PCI743X_DIO_REG;
+
+ subdev++;
+ }
+ }
+
+ if (board->do_nchan) {
+ nchan = min(board->do_nchan, 32);
+
+ s = &dev->subdevices[subdev];
+ /* Isolated digital outputs 0 to 15/31 */
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = nchan;
+ s->maxdata = 1;
+ s->insn_bits = adl_pci7x3x_do_insn_bits;
+ s->range_table = &range_digital;
+
+ s->private = (void *)PCI7X3X_DIO_REG;
+
+ subdev++;
+
+ nchan = board->do_nchan - nchan;
+ if (nchan) {
+ s = &dev->subdevices[subdev];
+ /* Isolated digital outputs 32 to 63 */
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = nchan;
+ s->maxdata = 1;
+ s->insn_bits = adl_pci7x3x_do_insn_bits;
+ s->range_table = &range_digital;
+
+ s->private = (void *)PCI743X_DIO_REG;
+
+ subdev++;
+ }
+ }
+
+ dev_info(dev->class_dev, "%s attached (%d inputs/%d outputs)\n",
+ dev->board_name, board->di_nchan, board->do_nchan);
+
+ return 0;
+}
+
+static void adl_pci7x3x_detach(struct comedi_device *dev)
+{
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+
+ if (pcidev) {
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
+ }
+}
+
+static struct comedi_driver adl_pci7x3x_driver = {
+ .driver_name = "adl_pci7x3x",
+ .module = THIS_MODULE,
+ .attach_pci = adl_pci7x3x_attach_pci,
+ .detach = adl_pci7x3x_detach,
+};
+
+static int __devinit adl_pci7x3x_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ return comedi_pci_auto_config(dev, &adl_pci7x3x_driver);
+}
+
+static void __devexit adl_pci7x3x_pci_remove(struct pci_dev *dev)
+{
+ comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(adl_pci7x3x_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7230) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7233) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7234) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7432) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7433) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7434) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, adl_pci7x3x_pci_table);
+
+static struct pci_driver adl_pci7x3x_pci_driver = {
+ .name = "adl_pci7x3x",
+ .id_table = adl_pci7x3x_pci_table,
+ .probe = adl_pci7x3x_pci_probe,
+ .remove = __devexit_p(adl_pci7x3x_pci_remove),
+};
+module_comedi_pci_driver(adl_pci7x3x_driver, adl_pci7x3x_pci_driver);
+
+MODULE_DESCRIPTION("ADLINK PCI-723x/743x Isolated Digital I/O boards");
+MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
index 247ef00a7c6c..05e06e7ba9f7 100644
--- a/drivers/staging/comedi/drivers/adl_pci8164.c
+++ b/drivers/staging/comedi/drivers/adl_pci8164.c
@@ -27,11 +27,7 @@ Author: Michel Lachaine <mike@mikelachaine.ca>
Status: experimental
Updated: Mon, 14 Apr 2008 15:10:32 +0100
-Configuration Options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
- If bus/slot is not specified, the first supported
- PCI device found will be used.
+Configuration Options: not applicable, uses PCI auto config
*/
#include "../comedidev.h"
@@ -216,61 +212,26 @@ static int adl_pci8164_insn_write_buf1(struct comedi_device *dev,
return 2;
}
-static struct pci_dev *adl_pci8164_find_pci(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int adl_pci8164_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
-
- for_each_pci_dev(pcidev) {
- if (pcidev->vendor != PCI_VENDOR_ID_ADLINK ||
- pcidev->device != PCI_DEVICE_ID_PCI8164)
- continue;
- if (bus || slot) {
- /* requested particular bus/slot */
- if (pcidev->bus->number != bus ||
- PCI_SLOT(pcidev->devfn) != slot)
- continue;
- }
- return pcidev;
- }
- printk(KERN_ERR
- "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
- dev->minor, bus, slot);
- return NULL;
-}
-
-static int adl_pci8164_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev;
struct comedi_subdevice *s;
int ret;
- printk(KERN_INFO "comedi: attempt to attach...\n");
- printk(KERN_INFO "comedi%d: adl_pci8164\n", dev->minor);
+ comedi_set_hw_dev(dev, &pcidev->dev);
- dev->board_name = "pci8164";
+ dev->board_name = dev->driver->driver_name;
- ret = comedi_alloc_subdevices(dev, 4);
+ ret = comedi_pci_enable(pcidev, dev->board_name);
if (ret)
return ret;
-
- pcidev = adl_pci8164_find_pci(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
-
- if (comedi_pci_enable(pcidev, "adl_pci8164") < 0) {
- printk(KERN_ERR "comedi%d: Failed to enable "
- "PCI device and request regions\n", dev->minor);
- return -EIO;
- }
dev->iobase = pci_resource_start(pcidev, 2);
- printk(KERN_DEBUG "comedi: base addr %4lx\n", dev->iobase);
- s = dev->subdevices + 0;
+ ret = comedi_alloc_subdevices(dev, 4);
+ if (ret)
+ return ret;
+
+ s = &dev->subdevices[0];
s->type = COMEDI_SUBD_PROC;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 4;
@@ -280,7 +241,7 @@ static int adl_pci8164_attach(struct comedi_device *dev,
s->insn_read = adl_pci8164_insn_read_msts;
s->insn_write = adl_pci8164_insn_write_cmd;
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
s->type = COMEDI_SUBD_PROC;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 4;
@@ -290,7 +251,7 @@ static int adl_pci8164_attach(struct comedi_device *dev,
s->insn_read = adl_pci8164_insn_read_ssts;
s->insn_write = adl_pci8164_insn_write_otp;
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
s->type = COMEDI_SUBD_PROC;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 4;
@@ -300,7 +261,7 @@ static int adl_pci8164_attach(struct comedi_device *dev,
s->insn_read = adl_pci8164_insn_read_buf0;
s->insn_write = adl_pci8164_insn_write_buf0;
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
s->type = COMEDI_SUBD_PROC;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 4;
@@ -310,7 +271,8 @@ static int adl_pci8164_attach(struct comedi_device *dev,
s->insn_read = adl_pci8164_insn_read_buf1;
s->insn_write = adl_pci8164_insn_write_buf1;
- printk(KERN_INFO "comedi: attached\n");
+ dev_info(dev->class_dev, "%s attached\n", dev->board_name);
+
return 0;
}
@@ -321,14 +283,13 @@ static void adl_pci8164_detach(struct comedi_device *dev)
if (pcidev) {
if (dev->iobase)
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
}
}
static struct comedi_driver adl_pci8164_driver = {
.driver_name = "adl_pci8164",
.module = THIS_MODULE,
- .attach = adl_pci8164_attach,
+ .attach_pci = adl_pci8164_attach_pci,
.detach = adl_pci8164_detach,
};
diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
index a31dae6e07df..a87192ac2846 100644
--- a/drivers/staging/comedi/drivers/adl_pci9111.c
+++ b/drivers/staging/comedi/drivers/adl_pci9111.c
@@ -47,14 +47,7 @@ Supports:
The scanned channels must be consecutive and start from 0. They must
all have the same range and aref.
-Configuration options:
-
- [0] - PCI bus number (optional)
- [1] - PCI slot number (optional)
-
-If bus/slot is not specified, the first available PCI
-device will be used.
-
+Configuration options: not applicable, uses PCI auto config
*/
/*
@@ -86,29 +79,9 @@ TODO:
#define PCI9111_DRIVER_NAME "adl_pci9111"
#define PCI9111_HR_DEVICE_ID 0x9111
-/* TODO: Add other pci9111 board id */
-
-#define PCI9111_IO_RANGE 0x0100
-
#define PCI9111_FIFO_HALF_SIZE 512
-#define PCI9111_AI_CHANNEL_NBR 16
-
-#define PCI9111_AI_RESOLUTION 12
-#define PCI9111_AI_RESOLUTION_MASK 0x0FFF
-#define PCI9111_AI_RESOLUTION_2_CMP_BIT 0x0800
-
-#define PCI9111_HR_AI_RESOLUTION 16
-#define PCI9111_HR_AI_RESOLUTION_MASK 0xFFFF
-#define PCI9111_HR_AI_RESOLUTION_2_CMP_BIT 0x8000
-
#define PCI9111_AI_ACQUISITION_PERIOD_MIN_NS 10000
-#define PCI9111_AO_CHANNEL_NBR 1
-#define PCI9111_AO_RESOLUTION 12
-#define PCI9111_AO_RESOLUTION_MASK 0x0FFF
-#define PCI9111_DI_CHANNEL_NBR 16
-#define PCI9111_DO_CHANNEL_NBR 16
-#define PCI9111_DO_MASK 0xFFFF
#define PCI9111_RANGE_SETTING_DELAY 10
#define PCI9111_AI_INSTANT_READ_UDELAY_US 2
@@ -116,233 +89,49 @@ TODO:
#define PCI9111_8254_CLOCK_PERIOD_NS 500
-#define PCI9111_8254_COUNTER_0 0x00
-#define PCI9111_8254_COUNTER_1 0x40
-#define PCI9111_8254_COUNTER_2 0x80
-#define PCI9111_8254_COUNTER_LATCH 0x00
-#define PCI9111_8254_READ_LOAD_LSB_ONLY 0x10
-#define PCI9111_8254_READ_LOAD_MSB_ONLY 0x20
-#define PCI9111_8254_READ_LOAD_LSB_MSB 0x30
-#define PCI9111_8254_MODE_0 0x00
-#define PCI9111_8254_MODE_1 0x02
-#define PCI9111_8254_MODE_2 0x04
-#define PCI9111_8254_MODE_3 0x06
-#define PCI9111_8254_MODE_4 0x08
-#define PCI9111_8254_MODE_5 0x0A
-#define PCI9111_8254_BINARY_COUNTER 0x00
-#define PCI9111_8254_BCD_COUNTER 0x01
-
-/* IO address map */
-
-#define PCI9111_REGISTER_AD_FIFO_VALUE 0x00 /* AD Data stored
- in FIFO */
-#define PCI9111_REGISTER_DA_OUTPUT 0x00
-#define PCI9111_REGISTER_DIGITAL_IO 0x02
-#define PCI9111_REGISTER_EXTENDED_IO_PORTS 0x04
-#define PCI9111_REGISTER_AD_CHANNEL_CONTROL 0x06 /* Channel
- selection */
-#define PCI9111_REGISTER_AD_CHANNEL_READBACK 0x06
-#define PCI9111_REGISTER_INPUT_SIGNAL_RANGE 0x08
-#define PCI9111_REGISTER_RANGE_STATUS_READBACK 0x08
-#define PCI9111_REGISTER_TRIGGER_MODE_CONTROL 0x0A
-#define PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK 0x0A
-#define PCI9111_REGISTER_SOFTWARE_TRIGGER 0x0E
-#define PCI9111_REGISTER_INTERRUPT_CONTROL 0x0C
-#define PCI9111_REGISTER_8254_COUNTER_0 0x40
-#define PCI9111_REGISTER_8254_COUNTER_1 0x42
-#define PCI9111_REGISTER_8254_COUNTER_2 0X44
-#define PCI9111_REGISTER_8254_CONTROL 0x46
-#define PCI9111_REGISTER_INTERRUPT_CLEAR 0x48
-
-#define PCI9111_TRIGGER_MASK 0x0F
-#define PCI9111_PTRG_OFF (0 << 3)
-#define PCI9111_PTRG_ON (1 << 3)
-#define PCI9111_EITS_EXTERNAL (1 << 2)
-#define PCI9111_EITS_INTERNAL (0 << 2)
-#define PCI9111_TPST_SOFTWARE_TRIGGER (0 << 1)
-#define PCI9111_TPST_TIMER_PACER (1 << 1)
-#define PCI9111_ASCAN_ON (1 << 0)
-#define PCI9111_ASCAN_OFF (0 << 0)
-
-#define PCI9111_ISC0_SET_IRQ_ON_ENDING_OF_AD_CONVERSION (0 << 0)
-#define PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL (1 << 0)
-#define PCI9111_ISC1_SET_IRQ_ON_TIMER_TICK (0 << 1)
-#define PCI9111_ISC1_SET_IRQ_ON_EXT_TRG (1 << 1)
-#define PCI9111_FFEN_SET_FIFO_ENABLE (0 << 2)
-#define PCI9111_FFEN_SET_FIFO_DISABLE (1 << 2)
-
-#define PCI9111_CHANNEL_MASK 0x0F
-
-#define PCI9111_RANGE_MASK 0x07
-#define PCI9111_FIFO_EMPTY_MASK 0x10
-#define PCI9111_FIFO_HALF_FULL_MASK 0x20
-#define PCI9111_FIFO_FULL_MASK 0x40
-#define PCI9111_AD_BUSY_MASK 0x80
-
-#define PCI9111_IO_BASE (dev->iobase)
-
/*
- * Define inlined function
+ * IO address map and bit defines
*/
-
-#define pci9111_trigger_and_autoscan_get() \
- (inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK)&0x0F)
-
-#define pci9111_trigger_and_autoscan_set(flags) \
- outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_TRIGGER_MODE_CONTROL)
-
-#define pci9111_interrupt_and_fifo_get() \
- ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) \
- >> 4) & 0x03)
-
-#define pci9111_interrupt_and_fifo_set(flags) \
- outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL)
-
-#define pci9111_interrupt_clear() \
- outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CLEAR)
-
-#define pci9111_software_trigger() \
- outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_SOFTWARE_TRIGGER)
-
-#define pci9111_fifo_reset() do { \
- outb(PCI9111_FFEN_SET_FIFO_ENABLE, \
- PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
- outb(PCI9111_FFEN_SET_FIFO_DISABLE, \
- PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
- outb(PCI9111_FFEN_SET_FIFO_ENABLE, \
- PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
- } while (0)
-
-#define pci9111_is_fifo_full() \
- ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
- PCI9111_FIFO_FULL_MASK) == 0)
-
-#define pci9111_is_fifo_half_full() \
- ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
- PCI9111_FIFO_HALF_FULL_MASK) == 0)
-
-#define pci9111_is_fifo_empty() \
- ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
- PCI9111_FIFO_EMPTY_MASK) == 0)
-
-#define pci9111_ai_channel_set(channel) \
- outb((channel)&PCI9111_CHANNEL_MASK, \
- PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_CONTROL)
-
-#define pci9111_ai_channel_get() \
- (inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_READBACK) \
- &PCI9111_CHANNEL_MASK)
-
-#define pci9111_ai_range_set(range) \
- outb((range)&PCI9111_RANGE_MASK, \
- PCI9111_IO_BASE+PCI9111_REGISTER_INPUT_SIGNAL_RANGE)
-
-#define pci9111_ai_range_get() \
- (inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK) \
- &PCI9111_RANGE_MASK)
-
-#define pci9111_ai_get_data() \
- (((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE)>>4) \
- &PCI9111_AI_RESOLUTION_MASK) \
- ^ PCI9111_AI_RESOLUTION_2_CMP_BIT)
-
-#define pci9111_hr_ai_get_data() \
- ((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE) \
- &PCI9111_HR_AI_RESOLUTION_MASK) \
- ^ PCI9111_HR_AI_RESOLUTION_2_CMP_BIT)
-
-#define pci9111_ao_set_data(data) \
- outw(data&PCI9111_AO_RESOLUTION_MASK, \
- PCI9111_IO_BASE+PCI9111_REGISTER_DA_OUTPUT)
-
-#define pci9111_di_get_bits() \
- inw(PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO)
-
-#define pci9111_do_set_bits(bits) \
- outw(bits, PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO)
-
-#define pci9111_8254_control_set(flags) \
- outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_8254_CONTROL)
-
-#define pci9111_8254_counter_0_set(data) \
- do { \
- outb(data & 0xFF, \
- PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0); \
- outb((data >> 8) & 0xFF, \
- PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0); \
- } while (0)
-
-#define pci9111_8254_counter_1_set(data) \
- do { \
- outb(data & 0xFF, \
- PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1); \
- outb((data >> 8) & 0xFF, \
- PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1); \
- } while (0)
-
-#define pci9111_8254_counter_2_set(data) \
- do { \
- outb(data & 0xFF, \
- PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2); \
- outb((data >> 8) & 0xFF, \
- PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2); \
- } while (0)
-
-static const struct comedi_lrange pci9111_hr_ai_range = {
+#define PCI9111_AI_FIFO_REG 0x00
+#define PCI9111_AO_REG 0x00
+#define PCI9111_DIO_REG 0x02
+#define PCI9111_EDIO_REG 0x04
+#define PCI9111_AI_CHANNEL_REG 0x06
+#define PCI9111_AI_RANGE_STAT_REG 0x08
+#define PCI9111_AI_STAT_AD_BUSY (1 << 7)
+#define PCI9111_AI_STAT_FF_FF (1 << 6)
+#define PCI9111_AI_STAT_FF_HF (1 << 5)
+#define PCI9111_AI_STAT_FF_EF (1 << 4)
+#define PCI9111_AI_RANGE_MASK (7 << 0)
+#define PCI9111_AI_TRIG_CTRL_REG 0x0a
+#define PCI9111_AI_TRIG_CTRL_TRGEVENT (1 << 5)
+#define PCI9111_AI_TRIG_CTRL_POTRG (1 << 4)
+#define PCI9111_AI_TRIG_CTRL_PTRG (1 << 3)
+#define PCI9111_AI_TRIG_CTRL_ETIS (1 << 2)
+#define PCI9111_AI_TRIG_CTRL_TPST (1 << 1)
+#define PCI9111_AI_TRIG_CTRL_ASCAN (1 << 0)
+#define PCI9111_INT_CTRL_REG 0x0c
+#define PCI9111_INT_CTRL_ISC2 (1 << 3)
+#define PCI9111_INT_CTRL_FFEN (1 << 2)
+#define PCI9111_INT_CTRL_ISC1 (1 << 1)
+#define PCI9111_INT_CTRL_ISC0 (1 << 0)
+#define PCI9111_SOFT_TRIG_REG 0x0e
+#define PCI9111_8254_BASE_REG 0x40
+#define PCI9111_INT_CLR_REG 0x48
+
+static const struct comedi_lrange pci9111_ai_range = {
5,
{
- BIP_RANGE(10),
- BIP_RANGE(5),
- BIP_RANGE(2.5),
- BIP_RANGE(1.25),
- BIP_RANGE(0.625)
- }
-};
-
-/* */
-/* Board specification structure */
-/* */
-
-struct pci9111_board {
- const char *name; /* driver name */
- int device_id;
- int ai_channel_nbr; /* num of A/D chans */
- int ao_channel_nbr; /* num of D/A chans */
- int ai_resolution; /* resolution of A/D */
- int ai_resolution_mask;
- int ao_resolution; /* resolution of D/A */
- int ao_resolution_mask;
- const struct comedi_lrange *ai_range_list; /* rangelist for A/D */
- const struct comedi_lrange *ao_range_list; /* rangelist for D/A */
- unsigned int ai_acquisition_period_min_ns;
-};
-
-static const struct pci9111_board pci9111_boards[] = {
- {
- .name = "pci9111_hr",
- .device_id = PCI9111_HR_DEVICE_ID,
- .ai_channel_nbr = PCI9111_AI_CHANNEL_NBR,
- .ao_channel_nbr = PCI9111_AO_CHANNEL_NBR,
- .ai_resolution = PCI9111_HR_AI_RESOLUTION,
- .ai_resolution_mask = PCI9111_HR_AI_RESOLUTION_MASK,
- .ao_resolution = PCI9111_AO_RESOLUTION,
- .ao_resolution_mask = PCI9111_AO_RESOLUTION_MASK,
- .ai_range_list = &pci9111_hr_ai_range,
- .ao_range_list = &range_bipolar10,
- .ai_acquisition_period_min_ns = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS}
+ BIP_RANGE(10),
+ BIP_RANGE(5),
+ BIP_RANGE(2.5),
+ BIP_RANGE(1.25),
+ BIP_RANGE(0.625)
+ }
};
-#define pci9111_board_nbr \
- (sizeof(pci9111_boards)/sizeof(struct pci9111_board))
-
-/* Private data structure */
-
struct pci9111_private_data {
- unsigned long io_range; /* PCI6503 io range */
-
- unsigned long lcr_io_base; /* Local configuration register base
- * address */
- unsigned long lcr_io_range;
+ unsigned long lcr_io_base;
int stop_counter;
int stop_is_none;
@@ -352,23 +141,14 @@ struct pci9111_private_data {
unsigned int chunk_counter;
unsigned int chunk_num_samples;
- int ao_readback; /* Last written analog output data */
+ int ao_readback;
- unsigned int timer_divisor_1; /* Divisor values for the 8254 timer
- * pacer */
- unsigned int timer_divisor_2;
-
- int is_valid; /* Is device valid */
+ unsigned int div1;
+ unsigned int div2;
short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
};
-#define dev_private ((struct pci9111_private_data *)dev->private)
-
-/* ------------------------------------------------------------------ */
-/* PLX9050 SECTION */
-/* ------------------------------------------------------------------ */
-
#define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c
#define PLX9050_LINTI1_ENABLE (1 << 0)
@@ -404,33 +184,19 @@ static void plx9050_interrupt_control(unsigned long io_base,
outb(flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL);
}
-/* ------------------------------------------------------------------ */
-/* MISCELLANEOUS SECTION */
-/* ------------------------------------------------------------------ */
-
-/* 8254 timer */
-
static void pci9111_timer_set(struct comedi_device *dev)
{
- pci9111_8254_control_set(PCI9111_8254_COUNTER_0 |
- PCI9111_8254_READ_LOAD_LSB_MSB |
- PCI9111_8254_MODE_0 |
- PCI9111_8254_BINARY_COUNTER);
+ struct pci9111_private_data *dev_private = dev->private;
+ unsigned long timer_base = dev->iobase + PCI9111_8254_BASE_REG;
- pci9111_8254_control_set(PCI9111_8254_COUNTER_1 |
- PCI9111_8254_READ_LOAD_LSB_MSB |
- PCI9111_8254_MODE_2 |
- PCI9111_8254_BINARY_COUNTER);
-
- pci9111_8254_control_set(PCI9111_8254_COUNTER_2 |
- PCI9111_8254_READ_LOAD_LSB_MSB |
- PCI9111_8254_MODE_2 |
- PCI9111_8254_BINARY_COUNTER);
+ i8254_set_mode(timer_base, 1, 0, I8254_MODE0 | I8254_BINARY);
+ i8254_set_mode(timer_base, 1, 1, I8254_MODE2 | I8254_BINARY);
+ i8254_set_mode(timer_base, 1, 2, I8254_MODE2 | I8254_BINARY);
udelay(1);
- pci9111_8254_counter_2_set(dev_private->timer_divisor_2);
- pci9111_8254_counter_1_set(dev_private->timer_divisor_1);
+ i8254_write(timer_base, 1, 2, dev_private->div2);
+ i8254_write(timer_base, 1, 1, dev_private->div1);
}
enum pci9111_trigger_sources {
@@ -444,47 +210,55 @@ static void pci9111_trigger_source_set(struct comedi_device *dev,
{
int flags;
- flags = pci9111_trigger_and_autoscan_get() & 0x09;
+ /* Read the current trigger mode control bits */
+ flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
+ /* Mask off the EITS and TPST bits */
+ flags &= 0x9;
switch (source) {
case software:
- flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_SOFTWARE_TRIGGER;
break;
case timer_pacer:
- flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_TIMER_PACER;
+ flags |= PCI9111_AI_TRIG_CTRL_TPST;
break;
case external:
- flags |= PCI9111_EITS_EXTERNAL;
+ flags |= PCI9111_AI_TRIG_CTRL_ETIS;
break;
}
- pci9111_trigger_and_autoscan_set(flags);
+ outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
}
static void pci9111_pretrigger_set(struct comedi_device *dev, bool pretrigger)
{
int flags;
- flags = pci9111_trigger_and_autoscan_get() & 0x07;
+ /* Read the current trigger mode control bits */
+ flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
+ /* Mask off the PTRG bit */
+ flags &= 0x7;
if (pretrigger)
- flags |= PCI9111_PTRG_ON;
+ flags |= PCI9111_AI_TRIG_CTRL_PTRG;
- pci9111_trigger_and_autoscan_set(flags);
+ outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
}
static void pci9111_autoscan_set(struct comedi_device *dev, bool autoscan)
{
int flags;
- flags = pci9111_trigger_and_autoscan_get() & 0x0e;
+ /* Read the current trigger mode control bits */
+ flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
+ /* Mask off the ASCAN bit */
+ flags &= 0xe;
if (autoscan)
- flags |= PCI9111_ASCAN_ON;
+ flags |= PCI9111_AI_TRIG_CTRL_ASCAN;
- pci9111_trigger_and_autoscan_set(flags);
+ outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
}
enum pci9111_ISC0_sources {
@@ -503,30 +277,39 @@ static void pci9111_interrupt_source_set(struct comedi_device *dev,
{
int flags;
- flags = pci9111_interrupt_and_fifo_get() & 0x04;
+ /* Read the current interrupt control bits */
+ flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
+ /* Shift the bits so they are compatible with the write register */
+ flags >>= 4;
+ /* Mask off the ISCx bits */
+ flags &= 0xc0;
+ /* Now set the new ISCx bits */
if (irq_0_source == irq_on_fifo_half_full)
- flags |= PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL;
+ flags |= PCI9111_INT_CTRL_ISC0;
if (irq_1_source == irq_on_external_trigger)
- flags |= PCI9111_ISC1_SET_IRQ_ON_EXT_TRG;
+ flags |= PCI9111_INT_CTRL_ISC1;
- pci9111_interrupt_and_fifo_set(flags);
+ outb(flags, dev->iobase + PCI9111_INT_CTRL_REG);
}
-/* ------------------------------------------------------------------ */
-/* HARDWARE TRIGGERED ANALOG INPUT SECTION */
-/* ------------------------------------------------------------------ */
-
-/* Cancel analog input autoscan */
+static void pci9111_fifo_reset(struct comedi_device *dev)
+{
+ unsigned long int_ctrl_reg = dev->iobase + PCI9111_INT_CTRL_REG;
-#undef AI_DO_CMD_DEBUG
+ /* To reset the FIFO, set FFEN sequence as 0 -> 1 -> 0 */
+ outb(0, int_ctrl_reg);
+ outb(PCI9111_INT_CTRL_FFEN, int_ctrl_reg);
+ outb(0, int_ctrl_reg);
+}
static int pci9111_ai_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- /* Disable interrupts */
+ struct pci9111_private_data *dev_private = dev->private;
+ /* Disable interrupts */
plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
true, false);
@@ -534,97 +317,65 @@ static int pci9111_ai_cancel(struct comedi_device *dev,
pci9111_autoscan_set(dev, false);
- pci9111_fifo_reset();
-
-#ifdef AI_DO_CMD_DEBUG
- printk(PCI9111_DRIVER_NAME ": ai_cancel\n");
-#endif
+ pci9111_fifo_reset(dev);
return 0;
}
-/* Test analog input command */
-
-#define pci9111_check_trigger_src(src, flags) do { \
- tmp = src; \
- src &= flags; \
- if (!src || tmp != src) \
- error++; \
- } while (false);
-
-static int
-pci9111_ai_do_cmd_test(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_cmd *cmd)
+static int pci9111_ai_do_cmd_test(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_cmd *cmd)
{
+ struct pci9111_private_data *dev_private = dev->private;
int tmp;
int error = 0;
int range, reference;
int i;
- struct pci9111_board *board = (struct pci9111_board *)dev->board_ptr;
- /* Step 1 : check if trigger are trivialy valid */
+ /* Step 1 : check if triggers are trivially valid */
- pci9111_check_trigger_src(cmd->start_src, TRIG_NOW);
- pci9111_check_trigger_src(cmd->scan_begin_src,
- TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
- pci9111_check_trigger_src(cmd->convert_src, TRIG_TIMER | TRIG_EXT);
- pci9111_check_trigger_src(cmd->scan_end_src, TRIG_COUNT);
- pci9111_check_trigger_src(cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+ error |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ error |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
+ error |= cfc_check_trigger_src(&cmd->convert_src,
+ TRIG_TIMER | TRIG_EXT);
+ error |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ error |= cfc_check_trigger_src(&cmd->stop_src,
+ TRIG_COUNT | TRIG_NONE);
if (error)
return 1;
- /* step 2 : make sure trigger sources are unique and mutually
- * compatible */
+ /* Step 2a : make sure trigger sources are unique */
- if (cmd->start_src != TRIG_NOW)
- error++;
+ error |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ error |= cfc_check_trigger_is_unique(cmd->convert_src);
+ error |= cfc_check_trigger_is_unique(cmd->stop_src);
- if ((cmd->scan_begin_src != TRIG_TIMER) &&
- (cmd->scan_begin_src != TRIG_FOLLOW) &&
- (cmd->scan_begin_src != TRIG_EXT))
- error++;
+ /* Step 2b : and mutually compatible */
- if ((cmd->convert_src != TRIG_TIMER) && (cmd->convert_src != TRIG_EXT))
- error++;
if ((cmd->convert_src == TRIG_TIMER) &&
!((cmd->scan_begin_src == TRIG_TIMER) ||
(cmd->scan_begin_src == TRIG_FOLLOW)))
- error++;
+ error |= -EINVAL;
if ((cmd->convert_src == TRIG_EXT) &&
!((cmd->scan_begin_src == TRIG_EXT) ||
(cmd->scan_begin_src == TRIG_FOLLOW)))
- error++;
-
-
- if (cmd->scan_end_src != TRIG_COUNT)
- error++;
- if ((cmd->stop_src != TRIG_COUNT) && (cmd->stop_src != TRIG_NONE))
- error++;
+ error |= -EINVAL;
if (error)
return 2;
/* Step 3 : make sure arguments are trivialy compatible */
- if (cmd->chanlist_len < 1) {
- cmd->chanlist_len = 1;
- error++;
- }
-
- if (cmd->chanlist_len > board->ai_channel_nbr) {
- cmd->chanlist_len = board->ai_channel_nbr;
- error++;
- }
-
if ((cmd->start_src == TRIG_NOW) && (cmd->start_arg != 0)) {
cmd->start_arg = 0;
error++;
}
if ((cmd->convert_src == TRIG_TIMER) &&
- (cmd->convert_arg < board->ai_acquisition_period_min_ns)) {
- cmd->convert_arg = board->ai_acquisition_period_min_ns;
+ (cmd->convert_arg < PCI9111_AI_ACQUISITION_PERIOD_MIN_NS)) {
+ cmd->convert_arg = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS;
error++;
}
if ((cmd->convert_src == TRIG_EXT) && (cmd->convert_arg != 0)) {
@@ -633,8 +384,8 @@ pci9111_ai_do_cmd_test(struct comedi_device *dev,
}
if ((cmd->scan_begin_src == TRIG_TIMER) &&
- (cmd->scan_begin_arg < board->ai_acquisition_period_min_ns)) {
- cmd->scan_begin_arg = board->ai_acquisition_period_min_ns;
+ (cmd->scan_begin_arg < PCI9111_AI_ACQUISITION_PERIOD_MIN_NS)) {
+ cmd->scan_begin_arg = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS;
error++;
}
if ((cmd->scan_begin_src == TRIG_FOLLOW)
@@ -670,9 +421,9 @@ pci9111_ai_do_cmd_test(struct comedi_device *dev,
if (cmd->convert_src == TRIG_TIMER) {
tmp = cmd->convert_arg;
i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
- &(dev_private->timer_divisor_1),
- &(dev_private->timer_divisor_2),
- &(cmd->convert_arg),
+ &dev_private->div1,
+ &dev_private->div2,
+ &cmd->convert_arg,
cmd->flags & TRIG_ROUND_MASK);
if (tmp != cmd->convert_arg)
error++;
@@ -733,14 +484,6 @@ pci9111_ai_do_cmd_test(struct comedi_device *dev,
error++;
}
}
- } else {
- if ((CR_CHAN(cmd->chanlist[0]) >
- (board->ai_channel_nbr - 1))
- || (CR_CHAN(cmd->chanlist[0]) < 0)) {
- comedi_error(dev,
- "channel number is out of limits\n");
- error++;
- }
}
}
@@ -751,12 +494,11 @@ pci9111_ai_do_cmd_test(struct comedi_device *dev,
}
-/* Analog input command */
-
static int pci9111_ai_do_cmd(struct comedi_device *dev,
- struct comedi_subdevice *subdevice)
+ struct comedi_subdevice *s)
{
- struct comedi_cmd *async_cmd = &subdevice->async->cmd;
+ struct pci9111_private_data *dev_private = dev->private;
+ struct comedi_cmd *async_cmd = &s->async->cmd;
if (!dev->irq) {
comedi_error(dev,
@@ -768,17 +510,20 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
/* TODO: handle the case of an external multiplexer */
if (async_cmd->chanlist_len > 1) {
- pci9111_ai_channel_set((async_cmd->chanlist_len) - 1);
+ outb(async_cmd->chanlist_len - 1,
+ dev->iobase + PCI9111_AI_CHANNEL_REG);
pci9111_autoscan_set(dev, true);
} else {
- pci9111_ai_channel_set(CR_CHAN(async_cmd->chanlist[0]));
+ outb(CR_CHAN(async_cmd->chanlist[0]),
+ dev->iobase + PCI9111_AI_CHANNEL_REG);
pci9111_autoscan_set(dev, false);
}
/* Set gain */
/* This is the same gain on every channel */
- pci9111_ai_range_set(CR_RANGE(async_cmd->chanlist[0]));
+ outb(CR_RANGE(async_cmd->chanlist[0]) & PCI9111_AI_RANGE_MASK,
+ dev->iobase + PCI9111_AI_RANGE_STAT_REG);
/* Set counter */
@@ -804,21 +549,9 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
dev_private->scan_delay = 0;
switch (async_cmd->convert_src) {
case TRIG_TIMER:
- i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
- &(dev_private->timer_divisor_1),
- &(dev_private->timer_divisor_2),
- &(async_cmd->convert_arg),
- async_cmd->
- flags & TRIG_ROUND_MASK);
-#ifdef AI_DO_CMD_DEBUG
- printk(PCI9111_DRIVER_NAME ": divisors = %d, %d\n",
- dev_private->timer_divisor_1,
- dev_private->timer_divisor_2);
-#endif
-
pci9111_trigger_source_set(dev, software);
pci9111_timer_set(dev);
- pci9111_fifo_reset();
+ pci9111_fifo_reset(dev);
pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
irq_on_timer_tick);
pci9111_trigger_source_set(dev, timer_pacer);
@@ -837,7 +570,7 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
case TRIG_EXT:
pci9111_trigger_source_set(dev, external);
- pci9111_fifo_reset();
+ pci9111_fifo_reset(dev);
pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
irq_on_timer_tick);
plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
@@ -856,23 +589,6 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
dev_private->chunk_num_samples =
dev_private->chanlist_len * (1 + dev_private->scan_delay);
-#ifdef AI_DO_CMD_DEBUG
- printk(PCI9111_DRIVER_NAME ": start interruptions!\n");
- printk(PCI9111_DRIVER_NAME ": trigger source = %2x\n",
- pci9111_trigger_and_autoscan_get());
- printk(PCI9111_DRIVER_NAME ": irq source = %2x\n",
- pci9111_interrupt_and_fifo_get());
- printk(PCI9111_DRIVER_NAME ": ai_do_cmd\n");
- printk(PCI9111_DRIVER_NAME ": stop counter = %d\n",
- dev_private->stop_counter);
- printk(PCI9111_DRIVER_NAME ": scan delay = %d\n",
- dev_private->scan_delay);
- printk(PCI9111_DRIVER_NAME ": chanlist_len = %d\n",
- dev_private->chanlist_len);
- printk(PCI9111_DRIVER_NAME ": chunk num samples = %d\n",
- dev_private->chunk_num_samples);
-#endif
-
return 0;
}
@@ -881,34 +597,24 @@ static void pci9111_ai_munge(struct comedi_device *dev,
unsigned int num_bytes,
unsigned int start_chan_index)
{
- unsigned int i, num_samples = num_bytes / sizeof(short);
short *array = data;
- int resolution =
- ((struct pci9111_board *)dev->board_ptr)->ai_resolution;
-
- for (i = 0; i < num_samples; i++) {
- if (resolution == PCI9111_HR_AI_RESOLUTION)
- array[i] =
- (array[i] & PCI9111_HR_AI_RESOLUTION_MASK) ^
- PCI9111_HR_AI_RESOLUTION_2_CMP_BIT;
- else
- array[i] =
- ((array[i] >> 4) & PCI9111_AI_RESOLUTION_MASK) ^
- PCI9111_AI_RESOLUTION_2_CMP_BIT;
- }
+ unsigned int maxdata = s->maxdata;
+ unsigned int invert = (maxdata + 1) >> 1;
+ unsigned int shift = (maxdata == 0xffff) ? 0 : 4;
+ unsigned int num_samples = num_bytes / sizeof(short);
+ unsigned int i;
+
+ for (i = 0; i < num_samples; i++)
+ array[i] = ((array[i] >> shift) & maxdata) ^ invert;
}
-/* ------------------------------------------------------------------ */
-/* INTERRUPT SECTION */
-/* ------------------------------------------------------------------ */
-
-#undef INTERRUPT_DEBUG
-
static irqreturn_t pci9111_interrupt(int irq, void *p_device)
{
struct comedi_device *dev = p_device;
- struct comedi_subdevice *subdevice = dev->read_subdev;
+ struct pci9111_private_data *dev_private = dev->private;
+ struct comedi_subdevice *s = dev->read_subdev;
struct comedi_async *async;
+ unsigned int status;
unsigned long irq_flags;
unsigned char intcsr;
@@ -918,7 +624,7 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device)
return IRQ_NONE;
}
- async = subdevice->async;
+ async = s->async;
spin_lock_irqsave(&dev->spinlock, irq_flags);
@@ -940,37 +646,37 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device)
(PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) {
/* Interrupt comes from fifo_half-full signal */
- if (pci9111_is_fifo_full()) {
+ status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG);
+
+ /* '0' means FIFO is full, data may have been lost */
+ if (!(status & PCI9111_AI_STAT_FF_FF)) {
spin_unlock_irqrestore(&dev->spinlock, irq_flags);
comedi_error(dev, PCI9111_DRIVER_NAME " fifo overflow");
- pci9111_interrupt_clear();
- pci9111_ai_cancel(dev, subdevice);
+ outb(0, dev->iobase + PCI9111_INT_CLR_REG);
+ pci9111_ai_cancel(dev, s);
async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
- comedi_event(dev, subdevice);
+ comedi_event(dev, s);
return IRQ_HANDLED;
}
- if (pci9111_is_fifo_half_full()) {
+ /* '0' means FIFO is half-full */
+ if (!(status & PCI9111_AI_STAT_FF_HF)) {
unsigned int num_samples;
unsigned int bytes_written = 0;
-#ifdef INTERRUPT_DEBUG
- printk(PCI9111_DRIVER_NAME ": fifo is half full\n");
-#endif
-
num_samples =
PCI9111_FIFO_HALF_SIZE >
dev_private->stop_counter
&& !dev_private->
stop_is_none ? dev_private->stop_counter :
PCI9111_FIFO_HALF_SIZE;
- insw(PCI9111_IO_BASE + PCI9111_REGISTER_AD_FIFO_VALUE,
+ insw(dev->iobase + PCI9111_AI_FIFO_REG,
dev_private->ai_bounce_buffer, num_samples);
if (dev_private->scan_delay < 1) {
bytes_written =
- cfc_write_array_to_buffer(subdevice,
+ cfc_write_array_to_buffer(s,
dev_private->
ai_bounce_buffer,
num_samples *
@@ -994,7 +700,7 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device)
bytes_written +=
cfc_write_array_to_buffer
- (subdevice,
+ (s,
dev_private->ai_bounce_buffer
+ position,
to_read * sizeof(short));
@@ -1029,168 +735,135 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device)
if ((dev_private->stop_counter == 0) && (!dev_private->stop_is_none)) {
async->events |= COMEDI_CB_EOA;
- pci9111_ai_cancel(dev, subdevice);
+ pci9111_ai_cancel(dev, s);
}
- /* Very important, otherwise another interrupt request will be inserted
- * and will cause driver hangs on processing interrupt event. */
-
- pci9111_interrupt_clear();
+ outb(0, dev->iobase + PCI9111_INT_CLR_REG);
spin_unlock_irqrestore(&dev->spinlock, irq_flags);
- comedi_event(dev, subdevice);
+ comedi_event(dev, s);
return IRQ_HANDLED;
}
-/* ------------------------------------------------------------------ */
-/* INSTANT ANALOG INPUT OUTPUT SECTION */
-/* ------------------------------------------------------------------ */
-
-/* analog instant input */
-
-#undef AI_INSN_DEBUG
-
static int pci9111_ai_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *subdevice,
+ struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
- int resolution =
- ((struct pci9111_board *)dev->board_ptr)->ai_resolution;
-
- int timeout, i;
-
-#ifdef AI_INSN_DEBUG
- printk(PCI9111_DRIVER_NAME ": ai_insn set c/r/n = %2x/%2x/%2x\n",
- CR_CHAN((&insn->chanspec)[0]),
- CR_RANGE((&insn->chanspec)[0]), insn->n);
-#endif
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int range = CR_RANGE(insn->chanspec);
+ unsigned int maxdata = s->maxdata;
+ unsigned int invert = (maxdata + 1) >> 1;
+ unsigned int shift = (maxdata == 0xffff) ? 0 : 4;
+ unsigned int status;
+ int timeout;
+ int i;
- pci9111_ai_channel_set(CR_CHAN((&insn->chanspec)[0]));
+ outb(chan, dev->iobase + PCI9111_AI_CHANNEL_REG);
- if ((pci9111_ai_range_get()) != CR_RANGE((&insn->chanspec)[0]))
- pci9111_ai_range_set(CR_RANGE((&insn->chanspec)[0]));
+ status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG);
+ if ((status & PCI9111_AI_RANGE_MASK) != range) {
+ outb(range & PCI9111_AI_RANGE_MASK,
+ dev->iobase + PCI9111_AI_RANGE_STAT_REG);
+ }
- pci9111_fifo_reset();
+ pci9111_fifo_reset(dev);
for (i = 0; i < insn->n; i++) {
- pci9111_software_trigger();
+ /* Generate a software trigger */
+ outb(0, dev->iobase + PCI9111_SOFT_TRIG_REG);
timeout = PCI9111_AI_INSTANT_READ_TIMEOUT;
while (timeout--) {
- if (!pci9111_is_fifo_empty())
+ status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG);
+ /* '1' means FIFO is not empty */
+ if (status & PCI9111_AI_STAT_FF_EF)
goto conversion_done;
}
comedi_error(dev, "A/D read timeout");
data[i] = 0;
- pci9111_fifo_reset();
+ pci9111_fifo_reset(dev);
return -ETIME;
conversion_done:
- if (resolution == PCI9111_HR_AI_RESOLUTION)
- data[i] = pci9111_hr_ai_get_data();
- else
- data[i] = pci9111_ai_get_data();
+ data[i] = inw(dev->iobase + PCI9111_AI_FIFO_REG);
+ data[i] = ((data[i] >> shift) & maxdata) ^ invert;
}
-#ifdef AI_INSN_DEBUG
- printk(PCI9111_DRIVER_NAME ": ai_insn get c/r/t = %2x/%2x/%2x\n",
- pci9111_ai_channel_get(),
- pci9111_ai_range_get(), pci9111_trigger_and_autoscan_get());
-#endif
-
return i;
}
-/* Analog instant output */
-
-static int
-pci9111_ao_insn_write(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data)
+static int pci9111_ao_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
+ struct pci9111_private_data *dev_private = dev->private;
+ unsigned int val = 0;
int i;
for (i = 0; i < insn->n; i++) {
- pci9111_ao_set_data(data[i]);
- dev_private->ao_readback = data[i];
+ val = data[i];
+ outw(val, dev->iobase + PCI9111_AO_REG);
}
+ dev_private->ao_readback = val;
- return i;
+ return insn->n;
}
-/* Analog output readback */
-
static int pci9111_ao_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 pci9111_private_data *dev_private = dev->private;
int i;
for (i = 0; i < insn->n; i++)
- data[i] = dev_private->ao_readback & PCI9111_AO_RESOLUTION_MASK;
+ data[i] = dev_private->ao_readback;
- return i;
+ return insn->n;
}
-/* ------------------------------------------------------------------ */
-/* DIGITAL INPUT OUTPUT SECTION */
-/* ------------------------------------------------------------------ */
-
-/* Digital inputs */
-
static int pci9111_di_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *subdevice,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- unsigned int bits;
-
- bits = pci9111_di_get_bits();
- data[1] = bits;
+ data[1] = inw(dev->iobase + PCI9111_DIO_REG);
return insn->n;
}
-/* Digital outputs */
-
static int pci9111_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *subdevice,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- unsigned int bits;
-
- /* Only set bits that have been masked */
- /* data[0] = mask */
- /* data[1] = bit state */
+ unsigned int mask = data[0];
+ unsigned int bits = data[1];
- data[0] &= PCI9111_DO_MASK;
+ if (mask) {
+ s->state &= ~mask;
+ s->state |= (bits & mask);
- bits = subdevice->state;
- bits &= ~data[0];
- bits |= data[0] & data[1];
- subdevice->state = bits;
-
- pci9111_do_set_bits(bits);
+ outw(s->state, dev->iobase + PCI9111_DIO_REG);
+ }
- data[1] = bits;
+ data[1] = s->state;
return insn->n;
}
-/* ------------------------------------------------------------------ */
-/* INITIALISATION SECTION */
-/* ------------------------------------------------------------------ */
-
-/* Reset device */
-
static int pci9111_reset(struct comedi_device *dev)
{
- /* Set trigger source to software */
+ struct pci9111_private_data *dev_private = dev->private;
+ /* Set trigger source to software */
plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
true, false);
@@ -1198,177 +871,90 @@ static int pci9111_reset(struct comedi_device *dev)
pci9111_pretrigger_set(dev, false);
pci9111_autoscan_set(dev, false);
- /* Reset 8254 chip */
-
- dev_private->timer_divisor_1 = 0;
- dev_private->timer_divisor_2 = 0;
-
+ /* Reset 8254 chip */
+ dev_private->div1 = 0;
+ dev_private->div2 = 0;
pci9111_timer_set(dev);
return 0;
}
-static struct pci_dev *pci9111_find_pci(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int pci9111_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
- int i;
-
- for_each_pci_dev(pcidev) {
- if (pcidev->vendor != PCI_VENDOR_ID_ADLINK)
- continue;
- for (i = 0; i < pci9111_board_nbr; i++) {
- if (pcidev->device != pci9111_boards[i].device_id)
- continue;
- if (bus || slot) {
- /* requested particular bus/slot */
- if (pcidev->bus->number != bus ||
- PCI_SLOT(pcidev->devfn) != slot)
- continue;
- }
- dev->board_ptr = pci9111_boards + i;
- printk(KERN_ERR
- "comedi%d: found %s (b:s:f=%d:%d:%d), irq=%d\n",
- dev->minor, pci9111_boards[i].name,
- pcidev->bus->number, PCI_SLOT(pcidev->devfn),
- PCI_FUNC(pcidev->devfn), pcidev->irq);
- return pcidev;
- }
- }
- printk(KERN_ERR
- "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
- dev->minor, bus, slot);
- return NULL;
-}
+ struct pci9111_private_data *dev_private;
+ struct comedi_subdevice *s;
+ int ret;
-static int pci9111_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev;
- struct comedi_subdevice *subdevice;
- unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
- int error;
- const struct pci9111_board *board;
-
- if (alloc_private(dev, sizeof(struct pci9111_private_data)) < 0)
- return -ENOMEM;
- /* Probe the device to determine what device in the series it is. */
-
- printk(KERN_ERR "comedi%d: " PCI9111_DRIVER_NAME " driver\n",
- dev->minor);
-
- pcidev = pci9111_find_pci(dev, it);
- if (!pcidev)
- return -EIO;
comedi_set_hw_dev(dev, &pcidev->dev);
- board = (struct pci9111_board *)dev->board_ptr;
-
- /* TODO: Warn about non-tested boards. */
-
- /* Read local configuration register base address
- * [PCI_BASE_ADDRESS #1]. */
-
- lcr_io_base = pci_resource_start(pcidev, 1);
- lcr_io_range = pci_resource_len(pcidev, 1);
-
- printk
- ("comedi%d: local configuration registers at address 0x%4lx [0x%4lx]\n",
- dev->minor, lcr_io_base, lcr_io_range);
-
- /* Enable PCI device and request regions */
- if (comedi_pci_enable(pcidev, PCI9111_DRIVER_NAME) < 0) {
- printk
- ("comedi%d: Failed to enable PCI device and request regions\n",
- dev->minor);
- return -EIO;
- }
- /* Read PCI6308 register base address [PCI_BASE_ADDRESS #2]. */
+ dev->board_name = dev->driver->driver_name;
- io_base = pci_resource_start(pcidev, 2);
- io_range = pci_resource_len(pcidev, 2);
+ ret = alloc_private(dev, sizeof(*dev_private));
+ if (ret)
+ return ret;
+ dev_private = dev->private;
- printk(KERN_ERR "comedi%d: 6503 registers at address 0x%4lx [0x%4lx]\n",
- dev->minor, io_base, io_range);
-
- dev->iobase = io_base;
- dev->board_name = board->name;
- dev_private->io_range = io_range;
- dev_private->is_valid = 0;
- dev_private->lcr_io_base = lcr_io_base;
- dev_private->lcr_io_range = lcr_io_range;
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
+ dev_private->lcr_io_base = pci_resource_start(pcidev, 1);
+ dev->iobase = pci_resource_start(pcidev, 2);
pci9111_reset(dev);
- /* Irq setup */
-
- dev->irq = 0;
if (pcidev->irq > 0) {
+ ret = request_irq(dev->irq, pci9111_interrupt,
+ IRQF_SHARED, dev->board_name, dev);
+ if (ret)
+ return ret;
dev->irq = pcidev->irq;
-
- if (request_irq(dev->irq, pci9111_interrupt,
- IRQF_SHARED, PCI9111_DRIVER_NAME, dev) != 0) {
- printk(KERN_ERR
- "comedi%d: unable to allocate irq %u\n",
- dev->minor, dev->irq);
- return -EINVAL;
- }
}
- /* TODO: Add external multiplexer setup (according to option[2]). */
-
- error = comedi_alloc_subdevices(dev, 4);
- if (error)
- return error;
-
- subdevice = dev->subdevices + 0;
- dev->read_subdev = subdevice;
-
- subdevice->type = COMEDI_SUBD_AI;
- subdevice->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
-
- /* TODO: Add external multiplexer data */
- /* if (devpriv->usemux) { subdevice->n_chan = devpriv->usemux; } */
- /* else { subdevice->n_chan = this_board->n_aichan; } */
-
- subdevice->n_chan = board->ai_channel_nbr;
- subdevice->maxdata = board->ai_resolution_mask;
- subdevice->len_chanlist = board->ai_channel_nbr;
- subdevice->range_table = board->ai_range_list;
- subdevice->cancel = pci9111_ai_cancel;
- subdevice->insn_read = pci9111_ai_insn_read;
- subdevice->do_cmdtest = pci9111_ai_do_cmd_test;
- subdevice->do_cmd = pci9111_ai_do_cmd;
- subdevice->munge = pci9111_ai_munge;
-
- subdevice = dev->subdevices + 1;
- subdevice->type = COMEDI_SUBD_AO;
- subdevice->subdev_flags = SDF_WRITABLE | SDF_COMMON;
- subdevice->n_chan = board->ao_channel_nbr;
- subdevice->maxdata = board->ao_resolution_mask;
- subdevice->len_chanlist = board->ao_channel_nbr;
- subdevice->range_table = board->ao_range_list;
- subdevice->insn_write = pci9111_ao_insn_write;
- subdevice->insn_read = pci9111_ao_insn_read;
-
- subdevice = dev->subdevices + 2;
- subdevice->type = COMEDI_SUBD_DI;
- subdevice->subdev_flags = SDF_READABLE;
- subdevice->n_chan = PCI9111_DI_CHANNEL_NBR;
- subdevice->maxdata = 1;
- subdevice->range_table = &range_digital;
- subdevice->insn_bits = pci9111_di_insn_bits;
-
- subdevice = dev->subdevices + 3;
- subdevice->type = COMEDI_SUBD_DO;
- subdevice->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- subdevice->n_chan = PCI9111_DO_CHANNEL_NBR;
- subdevice->maxdata = 1;
- subdevice->range_table = &range_digital;
- subdevice->insn_bits = pci9111_do_insn_bits;
-
- dev_private->is_valid = 1;
+ ret = comedi_alloc_subdevices(dev, 4);
+ if (ret)
+ return ret;
+
+ s = &dev->subdevices[0];
+ dev->read_subdev = s;
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
+ s->n_chan = 16;
+ s->maxdata = 0xffff;
+ s->len_chanlist = 16;
+ s->range_table = &pci9111_ai_range;
+ s->cancel = pci9111_ai_cancel;
+ s->insn_read = pci9111_ai_insn_read;
+ s->do_cmdtest = pci9111_ai_do_cmd_test;
+ s->do_cmd = pci9111_ai_do_cmd;
+ s->munge = pci9111_ai_munge;
+
+ s = &dev->subdevices[1];
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE | SDF_COMMON;
+ s->n_chan = 1;
+ s->maxdata = 0x0fff;
+ s->len_chanlist = 1;
+ s->range_table = &range_bipolar10;
+ s->insn_write = pci9111_ao_insn_write;
+ s->insn_read = pci9111_ao_insn_read;
+
+ s = &dev->subdevices[2];
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 16;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = pci9111_di_insn_bits;
+
+ s = &dev->subdevices[3];
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 16;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = pci9111_do_insn_bits;
+
+ dev_info(dev->class_dev, "%s attached\n", dev->board_name);
return 0;
}
@@ -1377,23 +963,20 @@ static void pci9111_detach(struct comedi_device *dev)
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- if (dev->private != NULL) {
- if (dev_private->is_valid)
- pci9111_reset(dev);
- }
+ if (dev->iobase)
+ pci9111_reset(dev);
if (dev->irq != 0)
free_irq(dev->irq, dev);
if (pcidev) {
if (dev->iobase)
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
}
}
static struct comedi_driver adl_pci9111_driver = {
.driver_name = "adl_pci9111",
.module = THIS_MODULE,
- .attach = pci9111_attach,
+ .attach_pci = pci9111_attach_pci,
.detach = pci9111_detach,
};
diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
index a1f74c2590e8..06ff65c85c9f 100644
--- a/drivers/staging/comedi/drivers/adl_pci9118.c
+++ b/drivers/staging/comedi/drivers/adl_pci9118.c
@@ -81,18 +81,6 @@ Configuration options:
* correct channel number on every 12 bit sample
*/
-#undef PCI9118_EXTDEBUG /*
- * if defined then driver prints
- * a lot of messages
- */
-
-#undef DPRINTK
-#ifdef PCI9118_EXTDEBUG
-#define DPRINTK(fmt, args...) printk(fmt, ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
#define IORANGE_9118 64 /* I hope */
#define PCI9118_CHANLEN 255 /*
* len of chanlist, some source say 256,
@@ -356,43 +344,170 @@ struct pci9118_private {
unsigned int ai_inttrig_start; /* TRIG_INT for start */
};
-#define devpriv ((struct pci9118_private *)dev->private)
-#define this_board ((struct boardtype *)dev->board_ptr)
-
-/*
-==============================================================================
-*/
-
static int check_channel_list(struct comedi_device *dev,
struct comedi_subdevice *s, int n_chan,
- unsigned int *chanlist, int frontadd,
- int backadd);
+ unsigned int *chanlist, int frontadd, int backadd)
+{
+ const struct boardtype *this_board = comedi_board(dev);
+ struct pci9118_private *devpriv = dev->private;
+ unsigned int i, differencial = 0, bipolar = 0;
+
+ /* correct channel and range number check itself comedi/range.c */
+ if (n_chan < 1) {
+ comedi_error(dev, "range/channel list is empty!");
+ return 0;
+ }
+ if ((frontadd + n_chan + backadd) > s->len_chanlist) {
+ printk
+ ("comedi%d: range/channel list is too long for "
+ "actual configuration (%d>%d)!",
+ dev->minor, n_chan, s->len_chanlist - frontadd - backadd);
+ return 0;
+ }
+
+ if (CR_AREF(chanlist[0]) == AREF_DIFF)
+ differencial = 1; /* all input must be diff */
+ if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
+ bipolar = 1; /* all input must be bipolar */
+ if (n_chan > 1)
+ for (i = 1; i < n_chan; i++) { /* check S.E/diff */
+ if ((CR_AREF(chanlist[i]) == AREF_DIFF) !=
+ (differencial)) {
+ comedi_error(dev,
+ "Differencial and single ended "
+ "inputs can't be mixtured!");
+ return 0;
+ }
+ if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) !=
+ (bipolar)) {
+ comedi_error(dev,
+ "Bipolar and unipolar ranges "
+ "can't be mixtured!");
+ return 0;
+ }
+ if (!devpriv->usemux && differencial &&
+ (CR_CHAN(chanlist[i]) >= this_board->n_aichand)) {
+ comedi_error(dev,
+ "If AREF_DIFF is used then is "
+ "available only first 8 channels!");
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
static int setup_channel_list(struct comedi_device *dev,
struct comedi_subdevice *s, int n_chan,
unsigned int *chanlist, int rot, int frontadd,
- int backadd, int usedma, char eoshandle);
-static void start_pacer(struct comedi_device *dev, int mode,
- unsigned int divisor1, unsigned int divisor2);
-static int pci9118_reset(struct comedi_device *dev);
-static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source);
-static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source);
-static int pci9118_ai_cancel(struct comedi_device *dev,
- struct comedi_subdevice *s);
-static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
- struct comedi_subdevice *s,
- unsigned int *tim1, unsigned int *tim2,
- unsigned int flags, int chans,
- unsigned int *div1, unsigned int *div2,
- char usessh, unsigned int chnsshfront);
+ int backadd, int usedma, char useeos)
+{
+ struct pci9118_private *devpriv = dev->private;
+ unsigned int i, differencial = 0, bipolar = 0;
+ unsigned int scanquad, gain, ssh = 0x00;
+
+ if (usedma == 1) {
+ rot = 8;
+ usedma = 0;
+ }
+
+ if (CR_AREF(chanlist[0]) == AREF_DIFF)
+ differencial = 1; /* all input must be diff */
+ if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
+ bipolar = 1; /* all input must be bipolar */
+
+ /* All is ok, so we can setup channel/range list */
+
+ if (!bipolar) {
+ devpriv->AdControlReg |= AdControl_UniP;
+ /* set unibipolar */
+ } else {
+ devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff);
+ /* enable bipolar */
+ }
+
+ if (differencial) {
+ devpriv->AdControlReg |= AdControl_Diff;
+ /* enable diff inputs */
+ } else {
+ devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff);
+ /* set single ended inputs */
+ }
+
+ outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
+ /* setup mode */
+
+ outl(2, dev->iobase + PCI9118_SCANMOD);
+ /* gods know why this sequence! */
+ outl(0, dev->iobase + PCI9118_SCANMOD);
+ outl(1, dev->iobase + PCI9118_SCANMOD);
+
+#ifdef PCI9118_PARANOIDCHECK
+ devpriv->chanlistlen = n_chan;
+ for (i = 0; i < (PCI9118_CHANLEN + 1); i++)
+ devpriv->chanlist[i] = 0x55aa;
+#endif
+
+ if (frontadd) { /* insert channels for S&H */
+ ssh = devpriv->softsshsample;
+ for (i = 0; i < frontadd; i++) {
+ /* store range list to card */
+ scanquad = CR_CHAN(chanlist[0]);
+ /* get channel number; */
+ gain = CR_RANGE(chanlist[0]);
+ /* get gain number */
+ scanquad |= ((gain & 0x03) << 8);
+ outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
+ ssh = devpriv->softsshhold;
+ }
+ }
+
+ for (i = 0; i < n_chan; i++) { /* store range list to card */
+ scanquad = CR_CHAN(chanlist[i]); /* get channel number */
+#ifdef PCI9118_PARANOIDCHECK
+ devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot;
+#endif
+ gain = CR_RANGE(chanlist[i]); /* get gain number */
+ scanquad |= ((gain & 0x03) << 8);
+ outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
+ }
+
+ if (backadd) { /* insert channels for fit onto 32bit DMA */
+ for (i = 0; i < backadd; i++) { /* store range list to card */
+ scanquad = CR_CHAN(chanlist[0]);
+ /* get channel number */
+ gain = CR_RANGE(chanlist[0]); /* get gain number */
+ scanquad |= ((gain & 0x03) << 8);
+ outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
+ }
+ }
+#ifdef PCI9118_PARANOIDCHECK
+ devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma];
+ /* for 32bit operations */
+ if (useeos) {
+ for (i = 1; i < n_chan; i++) { /* store range list to card */
+ devpriv->chanlist[(n_chan + i) ^ usedma] =
+ (CR_CHAN(chanlist[i]) & 0xf) << rot;
+ }
+ devpriv->chanlist[(2 * n_chan) ^ usedma] =
+ devpriv->chanlist[0 ^ usedma];
+ /* for 32bit operations */
+ useeos = 2;
+ } else {
+ useeos = 1;
+ }
+#endif
+ outl(0, dev->iobase + PCI9118_SCANMOD); /* close scan queue */
+ /* udelay(100); important delay, or first sample will be crippled */
+
+ return 1; /* we can serve this with scan logic */
+}
-/*
-==============================================================================
-*/
static int pci9118_insn_read_ai(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
-
+ struct pci9118_private *devpriv = dev->private;
int n, timeout;
devpriv->AdControlReg = AdControl_Int & 0xff;
@@ -442,13 +557,11 @@ conv_finish:
}
-/*
-==============================================================================
-*/
static int pci9118_insn_write_ao(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct pci9118_private *devpriv = dev->private;
int n, chanreg, ch;
ch = CR_CHAN(insn->chanspec);
@@ -466,13 +579,11 @@ static int pci9118_insn_write_ao(struct comedi_device *dev,
return n;
}
-/*
-==============================================================================
-*/
static int pci9118_insn_read_ao(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct pci9118_private *devpriv = dev->private;
int n, chan;
chan = CR_CHAN(insn->chanspec);
@@ -482,9 +593,6 @@ static int pci9118_insn_read_ao(struct comedi_device *dev,
return n;
}
-/*
-==============================================================================
-*/
static int pci9118_insn_bits_di(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
@@ -494,9 +602,6 @@ static int pci9118_insn_bits_di(struct comedi_device *dev,
return insn->n;
}
-/*
-==============================================================================
-*/
static int pci9118_insn_bits_do(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
@@ -511,11 +616,10 @@ static int pci9118_insn_bits_do(struct comedi_device *dev,
return insn->n;
}
-/*
-==============================================================================
-*/
static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev)
{
+ struct pci9118_private *devpriv = dev->private;
+
devpriv->AdFunctionReg =
AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
@@ -533,6 +637,7 @@ static unsigned int defragment_dma_buffer(struct comedi_device *dev,
short *dma_buffer,
unsigned int num_samples)
{
+ struct pci9118_private *devpriv = dev->private;
unsigned int i = 0, j = 0;
unsigned int start_pos = devpriv->ai_add_front,
stop_pos = devpriv->ai_add_front + devpriv->ai_n_chan;
@@ -551,14 +656,12 @@ static unsigned int defragment_dma_buffer(struct comedi_device *dev,
return j;
}
-/*
-==============================================================================
-*/
static int move_block_from_dma(struct comedi_device *dev,
struct comedi_subdevice *s,
short *dma_buffer,
unsigned int num_samples)
{
+ struct pci9118_private *devpriv = dev->private;
unsigned int num_bytes;
num_samples = defragment_dma_buffer(dev, s, dma_buffer, num_samples);
@@ -574,13 +677,153 @@ static int move_block_from_dma(struct comedi_device *dev,
return 0;
}
-/*
-==============================================================================
-*/
+static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source)
+{
+ struct pci9118_private *devpriv = dev->private;
+
+ if (source > 3)
+ return -1; /* incorrect source */
+ devpriv->exttrg_users |= (1 << source);
+ devpriv->IntControlReg |= Int_DTrg;
+ outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
+ outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
+ devpriv->iobase_a + AMCC_OP_REG_INTCSR);
+ /* allow INT in AMCC */
+ return 0;
+}
+
+static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source)
+{
+ struct pci9118_private *devpriv = dev->private;
+
+ if (source > 3)
+ return -1; /* incorrect source */
+ devpriv->exttrg_users &= ~(1 << source);
+ if (!devpriv->exttrg_users) { /* shutdown ext trg intterrupts */
+ devpriv->IntControlReg &= ~Int_DTrg;
+ if (!devpriv->IntControlReg) /* all IRQ disabled */
+ outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) &
+ (~0x00001f00),
+ devpriv->iobase_a + AMCC_OP_REG_INTCSR);
+ /* disable int in AMCC */
+ outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
+ }
+ return 0;
+}
+
+static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned int *tim1, unsigned int *tim2,
+ unsigned int flags, int chans,
+ unsigned int *div1, unsigned int *div2,
+ char usessh, unsigned int chnsshfront)
+{
+ const struct boardtype *this_board = comedi_board(dev);
+ struct pci9118_private *devpriv = dev->private;
+
+ switch (mode) {
+ case 1:
+ case 4:
+ if (*tim2 < this_board->ai_ns_min)
+ *tim2 = this_board->ai_ns_min;
+ i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, div1, div2,
+ tim2, flags & TRIG_ROUND_NEAREST);
+ break;
+ case 2:
+ if (*tim2 < this_board->ai_ns_min)
+ *tim2 = this_board->ai_ns_min;
+ *div1 = *tim2 / devpriv->i8254_osc_base;
+ /* convert timer (burst) */
+ if (*div1 < this_board->ai_pacer_min)
+ *div1 = this_board->ai_pacer_min;
+ *div2 = *tim1 / devpriv->i8254_osc_base; /* scan timer */
+ *div2 = *div2 / *div1; /* major timer is c1*c2 */
+ if (*div2 < chans)
+ *div2 = chans;
+
+ *tim2 = *div1 * devpriv->i8254_osc_base;
+ /* real convert timer */
+
+ if (usessh & (chnsshfront == 0)) /* use BSSH signal */
+ if (*div2 < (chans + 2))
+ *div2 = chans + 2;
+
+ *tim1 = *div1 * *div2 * devpriv->i8254_osc_base;
+ break;
+ }
+}
+
+static void start_pacer(struct comedi_device *dev, int mode,
+ unsigned int divisor1, unsigned int divisor2)
+{
+ outl(0x74, dev->iobase + PCI9118_CNTCTRL);
+ outl(0xb4, dev->iobase + PCI9118_CNTCTRL);
+/* outl(0x30, dev->iobase + PCI9118_CNTCTRL); */
+ udelay(1);
+
+ if ((mode == 1) || (mode == 2) || (mode == 4)) {
+ outl(divisor2 & 0xff, dev->iobase + PCI9118_CNT2);
+ outl((divisor2 >> 8) & 0xff, dev->iobase + PCI9118_CNT2);
+ outl(divisor1 & 0xff, dev->iobase + PCI9118_CNT1);
+ outl((divisor1 >> 8) & 0xff, dev->iobase + PCI9118_CNT1);
+ }
+}
+
+static int pci9118_ai_cancel(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ struct pci9118_private *devpriv = dev->private;
+
+ if (devpriv->usedma)
+ outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) &
+ (~EN_A2P_TRANSFERS),
+ devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
+ pci9118_exttrg_del(dev, EXTTRG_AI);
+ start_pacer(dev, 0, 0, 0); /* stop 8254 counters */
+ devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
+ outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
+ /*
+ * positive triggers, no S&H, no burst,
+ * burst stop, no post trigger,
+ * no about trigger, trigger stop
+ */
+ devpriv->AdControlReg = 0x00;
+ outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
+ /*
+ * bipolar, S.E., use 8254, stop 8354,
+ * internal trigger, soft trigger,
+ * disable INT and DMA
+ */
+ outl(0, dev->iobase + PCI9118_BURST);
+ outl(1, dev->iobase + PCI9118_SCANMOD);
+ outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
+ outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
+
+ devpriv->ai_do = 0;
+ devpriv->usedma = 0;
+
+ devpriv->ai_act_scan = 0;
+ devpriv->ai_act_dmapos = 0;
+ s->async->cur_chan = 0;
+ s->async->inttrig = NULL;
+ devpriv->ai_buf_ptr = 0;
+ devpriv->ai_neverending = 0;
+ devpriv->dma_actbuf = 0;
+
+ if (!devpriv->IntControlReg)
+ outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
+ devpriv->iobase_a + AMCC_OP_REG_INTCSR);
+ /* allow INT in AMCC */
+
+ return 0;
+}
+
static char pci9118_decode_error_status(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned char m)
{
+ struct pci9118_private *devpriv = dev->private;
+
if (m & 0x100) {
comedi_error(dev, "A/D FIFO Full status (Fatal Error!)");
devpriv->ai_maskerr &= ~0x100L;
@@ -613,6 +856,7 @@ static void pci9118_ai_munge(struct comedi_device *dev,
unsigned int num_bytes,
unsigned int start_chan_index)
{
+ struct pci9118_private *devpriv = dev->private;
unsigned int i, num_samples = num_bytes / sizeof(short);
short *array = data;
@@ -627,15 +871,13 @@ static void pci9118_ai_munge(struct comedi_device *dev,
}
}
-/*
-==============================================================================
-*/
static void interrupt_pci9118_ai_onesample(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned short int_adstat,
unsigned int int_amcc,
unsigned short int_daq)
{
+ struct pci9118_private *devpriv = dev->private;
register short sampl;
s->async->events = 0;
@@ -680,15 +922,13 @@ static void interrupt_pci9118_ai_onesample(struct comedi_device *dev,
comedi_event(dev, s);
}
-/*
-==============================================================================
-*/
static void interrupt_pci9118_ai_dma(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned short int_adstat,
unsigned int int_amcc,
unsigned short int_daq)
{
+ struct pci9118_private *devpriv = dev->private;
unsigned int next_dma_buf, samplesinbuf, sampls, m;
if (int_amcc & MASTER_ABORT_INT) {
@@ -713,7 +953,6 @@ static void interrupt_pci9118_ai_dma(struct comedi_device *dev,
samplesinbuf = devpriv->dmabuf_use_size[devpriv->dma_actbuf] >> 1;
/* number of received real samples */
-/* DPRINTK("dma_actbuf=%d\n",devpriv->dma_actbuf); */
if (devpriv->dma_doublebuf) { /*
* switch DMA buffers if is used
@@ -735,17 +974,12 @@ static void interrupt_pci9118_ai_dma(struct comedi_device *dev,
* how many samples is to
* end of buffer
*/
-/*
- * DPRINTK("samps=%d m=%d %d %d\n",
- * samplesinbuf,m,s->async->buf_int_count,s->async->buf_int_ptr);
- */
sampls = m;
move_block_from_dma(dev, s,
devpriv->dmabuf_virt[devpriv->dma_actbuf],
samplesinbuf);
m = m - sampls; /* m= how many samples was transferred */
}
-/* DPRINTK("YYY\n"); */
if (!devpriv->ai_neverending)
if (devpriv->ai_act_scan >= devpriv->ai_scans) {
@@ -768,12 +1002,10 @@ static void interrupt_pci9118_ai_dma(struct comedi_device *dev,
comedi_event(dev, s);
}
-/*
-==============================================================================
-*/
static irqreturn_t interrupt_pci9118(int irq, void *d)
{
struct comedi_device *dev = d;
+ struct pci9118_private *devpriv = dev->private;
unsigned int int_daq = 0, int_amcc, int_adstat;
if (!dev->attached)
@@ -784,14 +1016,6 @@ static irqreturn_t interrupt_pci9118(int irq, void *d)
int_amcc = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR);
/* get INT register from AMCC chip */
-/*
- * DPRINTK("INT daq=0x%01x amcc=0x%08x MWAR=0x%08x
- * MWTC=0x%08x ADSTAT=0x%02x ai_do=%d\n",
- * int_daq, int_amcc, inl(devpriv->iobase_a+AMCC_OP_REG_MWAR),
- * inl(devpriv->iobase_a+AMCC_OP_REG_MWTC),
- * inw(dev->iobase+PCI9118_ADSTAT)&0x1ff,devpriv->ai_do);
- */
-
if ((!int_daq) && (!(int_amcc & ANY_S593X_INT)))
return IRQ_NONE; /* interrupt from other source */
@@ -837,19 +1061,18 @@ static irqreturn_t interrupt_pci9118(int irq, void *d)
}
}
- (devpriv->int_ai_func) (dev, dev->subdevices + 0, int_adstat,
+ (devpriv->int_ai_func) (dev, &dev->subdevices[0], int_adstat,
int_amcc, int_daq);
}
return IRQ_HANDLED;
}
-/*
-==============================================================================
-*/
static int pci9118_ai_inttrig(struct comedi_device *dev,
struct comedi_subdevice *s, unsigned int trignum)
{
+ struct pci9118_private *devpriv = dev->private;
+
if (trignum != devpriv->ai_inttrig_start)
return -EINVAL;
@@ -868,119 +1091,64 @@ static int pci9118_ai_inttrig(struct comedi_device *dev,
return 1;
}
-/*
-==============================================================================
-*/
static int pci9118_ai_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{
+ const struct boardtype *this_board = comedi_board(dev);
+ struct pci9118_private *devpriv = dev->private;
int err = 0;
+ unsigned int flags;
int tmp;
unsigned int divisor1 = 0, divisor2 = 0;
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_EXT | TRIG_INT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src,
+ TRIG_NOW | TRIG_EXT | TRIG_INT);
- tmp = cmd->scan_begin_src;
+ flags = TRIG_FOLLOW;
if (devpriv->master)
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW;
- else
- cmd->scan_begin_src &= TRIG_FOLLOW;
+ flags |= TRIG_TIMER | TRIG_EXT;
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags);
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
+ flags = TRIG_TIMER | TRIG_EXT;
if (devpriv->master)
- cmd->convert_src &= TRIG_TIMER | TRIG_EXT | TRIG_NOW;
- else
- cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
-
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
+ flags |= TRIG_NOW;
+ err |= cfc_check_trigger_src(&cmd->convert_src, flags);
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE | TRIG_EXT;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ err |= cfc_check_trigger_src(&cmd->stop_src,
+ TRIG_COUNT | TRIG_NONE | TRIG_EXT);
if (err)
return 1;
- /*
- * step 2:
- * make sure trigger sources are
- * unique and mutually compatible
- */
+ /* Step 2a : make sure trigger sources are unique */
- if (cmd->start_src != TRIG_NOW &&
- cmd->start_src != TRIG_INT && cmd->start_src != TRIG_EXT) {
- cmd->start_src = TRIG_NOW;
- err++;
- }
-
- if (cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_EXT &&
- cmd->scan_begin_src != TRIG_INT &&
- cmd->scan_begin_src != TRIG_FOLLOW) {
- cmd->scan_begin_src = TRIG_FOLLOW;
- err++;
- }
-
- if (cmd->convert_src != TRIG_TIMER &&
- cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) {
- cmd->convert_src = TRIG_TIMER;
- err++;
- }
-
- if (cmd->scan_end_src != TRIG_COUNT) {
- cmd->scan_end_src = TRIG_COUNT;
- err++;
- }
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
- if (cmd->stop_src != TRIG_NONE &&
- cmd->stop_src != TRIG_COUNT &&
- cmd->stop_src != TRIG_INT && cmd->stop_src != TRIG_EXT) {
- cmd->stop_src = TRIG_COUNT;
- err++;
- }
+ /* Step 2b : and mutually compatible */
- if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) {
- cmd->start_src = TRIG_NOW;
- err++;
- }
+ if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT)
+ err |= -EINVAL;
- if (cmd->start_src == TRIG_INT && cmd->scan_begin_src == TRIG_INT) {
- cmd->start_src = TRIG_NOW;
- err++;
- }
+ if (cmd->start_src == TRIG_INT && cmd->scan_begin_src == TRIG_INT)
+ err |= -EINVAL;
if ((cmd->scan_begin_src & (TRIG_TIMER | TRIG_EXT)) &&
- (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW)))) {
- cmd->convert_src = TRIG_TIMER;
- err++;
- }
+ (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW))))
+ err |= -EINVAL;
if ((cmd->scan_begin_src == TRIG_FOLLOW) &&
- (!(cmd->convert_src & (TRIG_TIMER | TRIG_EXT)))) {
- cmd->convert_src = TRIG_TIMER;
- err++;
- }
+ (!(cmd->convert_src & (TRIG_TIMER | TRIG_EXT))))
+ err |= -EINVAL;
- if (cmd->stop_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) {
- cmd->stop_src = TRIG_COUNT;
- err++;
- }
+ if (cmd->stop_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT)
+ err |= -EINVAL;
if (err)
return 2;
@@ -1074,11 +1242,9 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev,
if (cmd->scan_begin_src == TRIG_TIMER) {
tmp = cmd->scan_begin_arg;
-/* printk("S1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
&divisor2, &cmd->scan_begin_arg,
cmd->flags & TRIG_ROUND_MASK);
-/* printk("S2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
if (cmd->scan_begin_arg < this_board->ai_ns_min)
cmd->scan_begin_arg = this_board->ai_ns_min;
if (tmp != cmd->scan_begin_arg)
@@ -1090,7 +1256,6 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev,
i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
&divisor2, &cmd->convert_arg,
cmd->flags & TRIG_ROUND_MASK);
-/* printk("s1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
if (cmd->convert_arg < this_board->ai_ns_min)
cmd->convert_arg = this_board->ai_ns_min;
if (tmp != cmd->convert_arg)
@@ -1104,7 +1269,6 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev,
cmd->scan_begin_arg =
this_board->ai_ns_min *
(cmd->scan_end_arg + 2);
-/* printk("s2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
err++;
}
} else {
@@ -1113,7 +1277,6 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev,
cmd->scan_begin_arg =
cmd->convert_arg *
cmd->chanlist_len;
-/* printk("s3 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
err++;
}
}
@@ -1131,18 +1294,13 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev,
return 0;
}
-/*
-==============================================================================
-*/
static int Compute_and_setup_dma(struct comedi_device *dev)
{
+ struct pci9118_private *devpriv = dev->private;
unsigned int dmalen0, dmalen1, i;
- DPRINTK("adl_pci9118 EDBG: BGN: Compute_and_setup_dma()\n");
dmalen0 = devpriv->dmabuf_size[0];
dmalen1 = devpriv->dmabuf_size[1];
- DPRINTK("1 dmalen0=%d dmalen1=%d ai_data_len=%d\n", dmalen0, dmalen1,
- devpriv->ai_data_len);
/* isn't output buff smaller that our DMA buff? */
if (dmalen0 > (devpriv->ai_data_len)) {
dmalen0 = devpriv->ai_data_len & ~3L; /*
@@ -1154,7 +1312,6 @@ static int Compute_and_setup_dma(struct comedi_device *dev)
* align to 32bit down
*/
}
- DPRINTK("2 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
/* we want wake up every scan? */
if (devpriv->ai_flags & TRIG_WAKE_EOS) {
@@ -1169,11 +1326,6 @@ static int Compute_and_setup_dma(struct comedi_device *dev)
} else {
/* short first DMA buffer to one scan */
dmalen0 = devpriv->ai_n_realscanlen << 1;
- DPRINTK
- ("21 dmalen0=%d ai_n_realscanlen=%d "
- "useeoshandle=%d\n",
- dmalen0, devpriv->ai_n_realscanlen,
- devpriv->useeoshandle);
if (devpriv->useeoshandle)
dmalen0 += 2;
if (dmalen0 < 4) {
@@ -1197,11 +1349,6 @@ static int Compute_and_setup_dma(struct comedi_device *dev)
} else {
/* short second DMA buffer to one scan */
dmalen1 = devpriv->ai_n_realscanlen << 1;
- DPRINTK
- ("22 dmalen1=%d ai_n_realscanlen=%d "
- "useeoshandle=%d\n",
- dmalen1, devpriv->ai_n_realscanlen,
- devpriv->useeoshandle);
if (devpriv->useeoshandle)
dmalen1 -= 2;
if (dmalen1 < 4) {
@@ -1214,7 +1361,6 @@ static int Compute_and_setup_dma(struct comedi_device *dev)
}
}
- DPRINTK("3 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
/* transfer without TRIG_WAKE_EOS */
if (!(devpriv->ai_flags & TRIG_WAKE_EOS)) {
/* if it's possible then align DMA buffers to length of scan */
@@ -1241,15 +1387,9 @@ static int Compute_and_setup_dma(struct comedi_device *dev)
if (dmalen0 >
((devpriv->ai_n_realscanlen << 1) *
devpriv->ai_scans)) {
- DPRINTK
- ("3.0 ai_n_realscanlen=%d ai_scans=%d\n",
- devpriv->ai_n_realscanlen,
- devpriv->ai_scans);
dmalen0 =
(devpriv->ai_n_realscanlen << 1) *
devpriv->ai_scans;
- DPRINTK("3.1 dmalen0=%d dmalen1=%d\n", dmalen0,
- dmalen1);
dmalen0 &= ~3L;
} else { /*
* fits whole measure into
@@ -1261,21 +1401,16 @@ static int Compute_and_setup_dma(struct comedi_device *dev)
dmalen1 =
(devpriv->ai_n_realscanlen << 1) *
devpriv->ai_scans - dmalen0;
- DPRINTK("3.2 dmalen0=%d dmalen1=%d\n", dmalen0,
- dmalen1);
dmalen1 &= ~3L;
}
}
}
- DPRINTK("4 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
-
/* these DMA buffer size will be used */
devpriv->dma_actbuf = 0;
devpriv->dmabuf_use_size[0] = dmalen0;
devpriv->dmabuf_use_size[1] = dmalen1;
- DPRINTK("5 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
#if 0
if (devpriv->ai_n_scanlen < this_board->half_fifo_size) {
devpriv->dmabuf_panic_size[0] =
@@ -1308,18 +1443,14 @@ static int Compute_and_setup_dma(struct comedi_device *dev)
devpriv->iobase_a + AMCC_OP_REG_INTCSR);
/* allow bus mastering */
- DPRINTK("adl_pci9118 EDBG: END: Compute_and_setup_dma()\n");
return 0;
}
-/*
-==============================================================================
-*/
static int pci9118_ai_docmd_sampl(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_sampl(%d,) [%d]\n",
- dev->minor, devpriv->ai_do);
+ struct pci9118_private *devpriv = dev->private;
+
switch (devpriv->ai_do) {
case 1:
devpriv->AdControlReg |= AdControl_TmrTr;
@@ -1366,18 +1497,14 @@ static int pci9118_ai_docmd_sampl(struct comedi_device *dev,
outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
}
- DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_docmd_sampl()\n");
return 0;
}
-/*
-==============================================================================
-*/
static int pci9118_ai_docmd_dma(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma(%d,) [%d,%d]\n",
- dev->minor, devpriv->ai_do, devpriv->usedma);
+ struct pci9118_private *devpriv = dev->private;
+
Compute_and_setup_dma(dev);
switch (devpriv->ai_do) {
@@ -1440,20 +1567,17 @@ static int pci9118_ai_docmd_dma(struct comedi_device *dev,
outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
}
- DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma()\n");
return 0;
}
-/*
-==============================================================================
-*/
static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
+ const struct boardtype *this_board = comedi_board(dev);
+ struct pci9118_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
unsigned int addchans = 0;
int ret = 0;
- DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_cmd(%d,)\n", dev->minor);
devpriv->ai12_startstop = 0;
devpriv->ai_flags = cmd->flags;
devpriv->ai_n_chan = cmd->chanlist_len;
@@ -1502,10 +1626,6 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->usessh = 0;
/* no */
- DPRINTK("1 neverending=%d scans=%u usessh=%d ai_startstop=0x%2x\n",
- devpriv->ai_neverending, devpriv->ai_scans, devpriv->usessh,
- devpriv->ai12_startstop);
-
/*
* use additional sample at end of every scan
* to satisty DMA 32 bit transfer?
@@ -1586,12 +1706,6 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->ai_add_back) * (devpriv->ai_n_scanlen /
devpriv->ai_n_chan);
- DPRINTK("2 usedma=%d realscan=%d af=%u n_chan=%d ab=%d n_scanlen=%d\n",
- devpriv->usedma,
- devpriv->ai_n_realscanlen, devpriv->ai_add_front,
- devpriv->ai_n_chan, devpriv->ai_add_back,
- devpriv->ai_n_scanlen);
-
/* check and setup channel list */
if (!check_channel_list(dev, s, devpriv->ai_n_chan,
devpriv->ai_chanlist, devpriv->ai_add_front,
@@ -1688,371 +1802,13 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
else
ret = pci9118_ai_docmd_sampl(dev, s);
- DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_cmd()\n");
return ret;
}
-/*
-==============================================================================
-*/
-static int check_channel_list(struct comedi_device *dev,
- struct comedi_subdevice *s, int n_chan,
- unsigned int *chanlist, int frontadd, int backadd)
-{
- unsigned int i, differencial = 0, bipolar = 0;
-
- /* correct channel and range number check itself comedi/range.c */
- if (n_chan < 1) {
- comedi_error(dev, "range/channel list is empty!");
- return 0;
- }
- if ((frontadd + n_chan + backadd) > s->len_chanlist) {
- printk
- ("comedi%d: range/channel list is too long for "
- "actual configuration (%d>%d)!",
- dev->minor, n_chan, s->len_chanlist - frontadd - backadd);
- return 0;
- }
-
- if (CR_AREF(chanlist[0]) == AREF_DIFF)
- differencial = 1; /* all input must be diff */
- if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
- bipolar = 1; /* all input must be bipolar */
- if (n_chan > 1)
- for (i = 1; i < n_chan; i++) { /* check S.E/diff */
- if ((CR_AREF(chanlist[i]) == AREF_DIFF) !=
- (differencial)) {
- comedi_error(dev,
- "Differencial and single ended "
- "inputs can't be mixtured!");
- return 0;
- }
- if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) !=
- (bipolar)) {
- comedi_error(dev,
- "Bipolar and unipolar ranges "
- "can't be mixtured!");
- return 0;
- }
- if (!devpriv->usemux && differencial &&
- (CR_CHAN(chanlist[i]) >= this_board->n_aichand)) {
- comedi_error(dev,
- "If AREF_DIFF is used then is "
- "available only first 8 channels!");
- return 0;
- }
- }
-
- return 1;
-}
-
-/*
-==============================================================================
-*/
-static int setup_channel_list(struct comedi_device *dev,
- struct comedi_subdevice *s, int n_chan,
- unsigned int *chanlist, int rot, int frontadd,
- int backadd, int usedma, char useeos)
-{
- unsigned int i, differencial = 0, bipolar = 0;
- unsigned int scanquad, gain, ssh = 0x00;
-
- DPRINTK
- ("adl_pci9118 EDBG: BGN: setup_channel_list"
- "(%d,.,%d,.,%d,%d,%d,%d)\n",
- dev->minor, n_chan, rot, frontadd, backadd, usedma);
-
- if (usedma == 1) {
- rot = 8;
- usedma = 0;
- }
-
- if (CR_AREF(chanlist[0]) == AREF_DIFF)
- differencial = 1; /* all input must be diff */
- if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
- bipolar = 1; /* all input must be bipolar */
-
- /* All is ok, so we can setup channel/range list */
-
- if (!bipolar) {
- devpriv->AdControlReg |= AdControl_UniP;
- /* set unibipolar */
- } else {
- devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff);
- /* enable bipolar */
- }
-
- if (differencial) {
- devpriv->AdControlReg |= AdControl_Diff;
- /* enable diff inputs */
- } else {
- devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff);
- /* set single ended inputs */
- }
-
- outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
- /* setup mode */
-
- outl(2, dev->iobase + PCI9118_SCANMOD);
- /* gods know why this sequence! */
- outl(0, dev->iobase + PCI9118_SCANMOD);
- outl(1, dev->iobase + PCI9118_SCANMOD);
-
-#ifdef PCI9118_PARANOIDCHECK
- devpriv->chanlistlen = n_chan;
- for (i = 0; i < (PCI9118_CHANLEN + 1); i++)
- devpriv->chanlist[i] = 0x55aa;
-#endif
-
- if (frontadd) { /* insert channels for S&H */
- ssh = devpriv->softsshsample;
- DPRINTK("FA: %04x: ", ssh);
- for (i = 0; i < frontadd; i++) {
- /* store range list to card */
- scanquad = CR_CHAN(chanlist[0]);
- /* get channel number; */
- gain = CR_RANGE(chanlist[0]);
- /* get gain number */
- scanquad |= ((gain & 0x03) << 8);
- outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
- DPRINTK("%02x ", scanquad | ssh);
- ssh = devpriv->softsshhold;
- }
- DPRINTK("\n ");
- }
-
- DPRINTK("SL: ", ssh);
- for (i = 0; i < n_chan; i++) { /* store range list to card */
- scanquad = CR_CHAN(chanlist[i]); /* get channel number */
-#ifdef PCI9118_PARANOIDCHECK
- devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot;
-#endif
- gain = CR_RANGE(chanlist[i]); /* get gain number */
- scanquad |= ((gain & 0x03) << 8);
- outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
- DPRINTK("%02x ", scanquad | ssh);
- }
- DPRINTK("\n ");
-
- if (backadd) { /* insert channels for fit onto 32bit DMA */
- DPRINTK("BA: %04x: ", ssh);
- for (i = 0; i < backadd; i++) { /* store range list to card */
- scanquad = CR_CHAN(chanlist[0]);
- /* get channel number */
- gain = CR_RANGE(chanlist[0]); /* get gain number */
- scanquad |= ((gain & 0x03) << 8);
- outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
- DPRINTK("%02x ", scanquad | ssh);
- }
- DPRINTK("\n ");
- }
-#ifdef PCI9118_PARANOIDCHECK
- devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma];
- /* for 32bit operations */
- if (useeos) {
- for (i = 1; i < n_chan; i++) { /* store range list to card */
- devpriv->chanlist[(n_chan + i) ^ usedma] =
- (CR_CHAN(chanlist[i]) & 0xf) << rot;
- }
- devpriv->chanlist[(2 * n_chan) ^ usedma] =
- devpriv->chanlist[0 ^ usedma];
- /* for 32bit operations */
- useeos = 2;
- } else {
- useeos = 1;
- }
-#ifdef PCI9118_EXTDEBUG
- DPRINTK("CHL: ");
- for (i = 0; i <= (useeos * n_chan); i++)
- DPRINTK("%04x ", devpriv->chanlist[i]);
-
- DPRINTK("\n ");
-#endif
-#endif
- outl(0, dev->iobase + PCI9118_SCANMOD); /* close scan queue */
- /* udelay(100); important delay, or first sample will be crippled */
-
- DPRINTK("adl_pci9118 EDBG: END: setup_channel_list()\n");
- return 1; /* we can serve this with scan logic */
-}
-
-/*
-==============================================================================
- calculate 8254 divisors if they are used for dual timing
-*/
-static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
- struct comedi_subdevice *s,
- unsigned int *tim1, unsigned int *tim2,
- unsigned int flags, int chans,
- unsigned int *div1, unsigned int *div2,
- char usessh, unsigned int chnsshfront)
-{
- DPRINTK
- ("adl_pci9118 EDBG: BGN: pci9118_calc_divisors"
- "(%d,%d,.,%u,%u,%u,%d,.,.,,%u,%u)\n",
- mode, dev->minor, *tim1, *tim2, flags, chans, usessh, chnsshfront);
- switch (mode) {
- case 1:
- case 4:
- if (*tim2 < this_board->ai_ns_min)
- *tim2 = this_board->ai_ns_min;
- i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, div1, div2,
- tim2, flags & TRIG_ROUND_NEAREST);
- DPRINTK("OSC base=%u div1=%u div2=%u timer1=%u\n",
- devpriv->i8254_osc_base, *div1, *div2, *tim1);
- break;
- case 2:
- if (*tim2 < this_board->ai_ns_min)
- *tim2 = this_board->ai_ns_min;
- DPRINTK("1 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
- *tim1, *tim2);
- *div1 = *tim2 / devpriv->i8254_osc_base;
- /* convert timer (burst) */
- DPRINTK("2 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
- *tim1, *tim2);
- if (*div1 < this_board->ai_pacer_min)
- *div1 = this_board->ai_pacer_min;
- DPRINTK("3 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
- *tim1, *tim2);
- *div2 = *tim1 / devpriv->i8254_osc_base; /* scan timer */
- DPRINTK("4 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
- *tim1, *tim2);
- *div2 = *div2 / *div1; /* major timer is c1*c2 */
- DPRINTK("5 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
- *tim1, *tim2);
- if (*div2 < chans)
- *div2 = chans;
- DPRINTK("6 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
- *tim1, *tim2);
-
- *tim2 = *div1 * devpriv->i8254_osc_base;
- /* real convert timer */
-
- if (usessh & (chnsshfront == 0)) /* use BSSH signal */
- if (*div2 < (chans + 2))
- *div2 = chans + 2;
-
- DPRINTK("7 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
- *tim1, *tim2);
- *tim1 = *div1 * *div2 * devpriv->i8254_osc_base;
- DPRINTK("OSC base=%u div1=%u div2=%u timer1=%u timer2=%u\n",
- devpriv->i8254_osc_base, *div1, *div2, *tim1, *tim2);
- break;
- }
- DPRINTK("adl_pci9118 EDBG: END: pci9118_calc_divisors(%u,%u)\n",
- *div1, *div2);
-}
-
-/*
-==============================================================================
-*/
-static void start_pacer(struct comedi_device *dev, int mode,
- unsigned int divisor1, unsigned int divisor2)
-{
- outl(0x74, dev->iobase + PCI9118_CNTCTRL);
- outl(0xb4, dev->iobase + PCI9118_CNTCTRL);
-/* outl(0x30, dev->iobase + PCI9118_CNTCTRL); */
- udelay(1);
-
- if ((mode == 1) || (mode == 2) || (mode == 4)) {
- outl(divisor2 & 0xff, dev->iobase + PCI9118_CNT2);
- outl((divisor2 >> 8) & 0xff, dev->iobase + PCI9118_CNT2);
- outl(divisor1 & 0xff, dev->iobase + PCI9118_CNT1);
- outl((divisor1 >> 8) & 0xff, dev->iobase + PCI9118_CNT1);
- }
-}
-
-/*
-==============================================================================
-*/
-static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source)
-{
- if (source > 3)
- return -1; /* incorrect source */
- devpriv->exttrg_users |= (1 << source);
- devpriv->IntControlReg |= Int_DTrg;
- outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
- outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
- devpriv->iobase_a + AMCC_OP_REG_INTCSR);
- /* allow INT in AMCC */
- return 0;
-}
-
-/*
-==============================================================================
-*/
-static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source)
-{
- if (source > 3)
- return -1; /* incorrect source */
- devpriv->exttrg_users &= ~(1 << source);
- if (!devpriv->exttrg_users) { /* shutdown ext trg intterrupts */
- devpriv->IntControlReg &= ~Int_DTrg;
- if (!devpriv->IntControlReg) /* all IRQ disabled */
- outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) &
- (~0x00001f00),
- devpriv->iobase_a + AMCC_OP_REG_INTCSR);
- /* disable int in AMCC */
- outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
- }
- return 0;
-}
-
-/*
-==============================================================================
-*/
-static int pci9118_ai_cancel(struct comedi_device *dev,
- struct comedi_subdevice *s)
-{
- if (devpriv->usedma)
- outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) &
- (~EN_A2P_TRANSFERS),
- devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
- pci9118_exttrg_del(dev, EXTTRG_AI);
- start_pacer(dev, 0, 0, 0); /* stop 8254 counters */
- devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
- outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
- /*
- * positive triggers, no S&H, no burst,
- * burst stop, no post trigger,
- * no about trigger, trigger stop
- */
- devpriv->AdControlReg = 0x00;
- outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
- /*
- * bipolar, S.E., use 8254, stop 8354,
- * internal trigger, soft trigger,
- * disable INT and DMA
- */
- outl(0, dev->iobase + PCI9118_BURST);
- outl(1, dev->iobase + PCI9118_SCANMOD);
- outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
- outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
-
- devpriv->ai_do = 0;
- devpriv->usedma = 0;
-
- devpriv->ai_act_scan = 0;
- devpriv->ai_act_dmapos = 0;
- s->async->cur_chan = 0;
- s->async->inttrig = NULL;
- devpriv->ai_buf_ptr = 0;
- devpriv->ai_neverending = 0;
- devpriv->dma_actbuf = 0;
-
- if (!devpriv->IntControlReg)
- outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
- devpriv->iobase_a + AMCC_OP_REG_INTCSR);
- /* allow INT in AMCC */
-
- return 0;
-}
-
-/*
-==============================================================================
-*/
static int pci9118_reset(struct comedi_device *dev)
{
+ struct pci9118_private *devpriv = dev->private;
+
devpriv->IntControlReg = 0;
devpriv->exttrg_users = 0;
inl(dev->iobase + PCI9118_INTCTRL);
@@ -2112,6 +1868,7 @@ static int pci9118_reset(struct comedi_device *dev)
static struct pci_dev *pci9118_find_pci(struct comedi_device *dev,
struct comedi_devconfig *it)
{
+ const struct boardtype *this_board = comedi_board(dev);
struct pci_dev *pcidev = NULL;
int bus = it->options[0];
int slot = it->options[1];
@@ -2150,6 +1907,8 @@ static struct pci_dev *pci9118_find_pci(struct comedi_device *dev,
static int pci9118_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
+ const struct boardtype *this_board = comedi_board(dev);
+ struct pci9118_private *devpriv;
struct pci_dev *pcidev;
struct comedi_subdevice *s;
int ret, pages, i;
@@ -2164,11 +1923,12 @@ static int pci9118_attach(struct comedi_device *dev,
else
master = 1;
- ret = alloc_private(dev, sizeof(struct pci9118_private));
+ ret = alloc_private(dev, sizeof(*devpriv));
if (ret < 0) {
printk(" - Allocation failed!\n");
return -ENOMEM;
}
+ devpriv = dev->private;
pcidev = pci9118_find_pci(dev, it);
if (!pcidev)
@@ -2273,7 +2033,7 @@ static int pci9118_attach(struct comedi_device *dev,
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
dev->read_subdev = s;
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
@@ -2294,7 +2054,7 @@ static int pci9118_attach(struct comedi_device *dev,
s->munge = pci9118_ai_munge;
}
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
s->n_chan = this_board->n_aochan;
@@ -2304,7 +2064,7 @@ static int pci9118_attach(struct comedi_device *dev,
s->insn_write = pci9118_insn_write_ao;
s->insn_read = pci9118_insn_read_ao;
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
s->n_chan = 4;
@@ -2314,7 +2074,7 @@ static int pci9118_attach(struct comedi_device *dev,
s->io_bits = 0; /* all bits input */
s->insn_bits = pci9118_insn_bits_di;
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
s->n_chan = 4;
@@ -2345,8 +2105,9 @@ static int pci9118_attach(struct comedi_device *dev,
static void pci9118_detach(struct comedi_device *dev)
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ struct pci9118_private *devpriv = dev->private;
- if (dev->private) {
+ if (devpriv) {
if (devpriv->valid)
pci9118_reset(dev);
if (dev->irq)
diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
index 6df51c8a602a..3a2aa5628be3 100644
--- a/drivers/staging/comedi/drivers/adq12b.c
+++ b/drivers/staging/comedi/drivers/adq12b.c
@@ -133,8 +133,6 @@ struct adq12b_private {
unsigned int digital_state;
};
-#define devpriv ((struct adq12b_private *)dev->private)
-
/*
* "instructions" read/write data in "one-shot" or "software-triggered"
* mode.
@@ -144,6 +142,7 @@ static int adq12b_ai_rinsn(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn,
unsigned int *data)
{
+ struct adq12b_private *devpriv = dev->private;
int n, i;
int range, channel;
unsigned char hi, lo, status;
@@ -200,6 +199,7 @@ static int adq12b_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct adq12b_private *devpriv = dev->private;
int channel;
for (channel = 0; channel < 8; channel++)
@@ -221,6 +221,7 @@ static int adq12b_do_insn_bits(struct comedi_device *dev,
static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
const struct adq12b_board *board = comedi_board(dev);
+ struct adq12b_private *devpriv;
struct comedi_subdevice *s;
unsigned long iobase;
int unipolar, differential;
@@ -252,19 +253,18 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
dev->board_name = board->name;
-/*
- * Allocate the private structure area. alloc_private() is a
- * convenient macro defined in comedidev.h.
- */
- if (alloc_private(dev, sizeof(struct adq12b_private)) < 0)
- return -ENOMEM;
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret)
+ return ret;
+ devpriv = dev->private;
-/* fill in devpriv structure */
devpriv->unipolar = unipolar;
devpriv->differential = differential;
devpriv->digital_state = 0;
-/* initialize channel and range to -1 so we make sure we always write
- at least once to the CTREG in the instruction */
+ /*
+ * initialize channel and range to -1 so we make sure we
+ * always write at least once to the CTREG in the instruction
+ */
devpriv->last_channel = -1;
devpriv->last_range = -1;
@@ -272,7 +272,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* analog input subdevice */
s->type = COMEDI_SUBD_AI;
if (differential) {
@@ -294,7 +294,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
the board can handle */
s->insn_read = adq12b_ai_rinsn;
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* digital input subdevice */
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
@@ -303,7 +303,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->range_table = &range_digital;
s->insn_bits = adq12b_di_insn_bits;
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
/* digital output subdevice */
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE;
@@ -321,7 +321,6 @@ static void adq12b_detach(struct comedi_device *dev)
{
if (dev->iobase)
release_region(dev->iobase, ADQ12B_SIZE);
- kfree(devpriv);
}
static const struct adq12b_board adq12b_boards[] = {
diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
index 6b4d0d68e637..def37bcc2a66 100644
--- a/drivers/staging/comedi/drivers/adv_pci1710.c
+++ b/drivers/staging/comedi/drivers/adv_pci1710.c
@@ -45,6 +45,7 @@ Configuration options:
#include "../comedidev.h"
+#include "comedi_fc.h"
#include "8253.h"
#include "amcc_s5933.h"
@@ -52,17 +53,6 @@ Configuration options:
* correct channel number on every 12 bit
* sample */
-#undef PCI171X_EXTDEBUG
-
-#define DRV_NAME "adv_pci1710"
-
-#undef DPRINTK
-#ifdef PCI171X_EXTDEBUG
-#define DPRINTK(fmt, args...) printk(fmt, ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
#define PCI_VENDOR_ID_ADVANTECH 0x13fe
/* hardware types of the cards */
@@ -211,44 +201,101 @@ struct boardtype {
};
static const struct boardtype boardtypes[] = {
- {"pci1710", 0x1710,
- IORANGE_171x, 1, TYPE_PCI171X,
- 16, 8, 2, 16, 16, 1, 0x0fff, 0x0fff,
- &range_pci1710_3, range_codes_pci1710_3,
- &range_pci171x_da,
- 10000, 2048},
- {"pci1710hg", 0x1710,
- IORANGE_171x, 1, TYPE_PCI171X,
- 16, 8, 2, 16, 16, 1, 0x0fff, 0x0fff,
- &range_pci1710hg, range_codes_pci1710hg,
- &range_pci171x_da,
- 10000, 2048},
- {"pci1711", 0x1711,
- IORANGE_171x, 1, TYPE_PCI171X,
- 16, 0, 2, 16, 16, 1, 0x0fff, 0x0fff,
- &range_pci17x1, range_codes_pci17x1, &range_pci171x_da,
- 10000, 512},
- {"pci1713", 0x1713,
- IORANGE_171x, 1, TYPE_PCI1713,
- 32, 16, 0, 0, 0, 0, 0x0fff, 0x0000,
- &range_pci1710_3, range_codes_pci1710_3, NULL,
- 10000, 2048},
- {"pci1720", 0x1720,
- IORANGE_1720, 0, TYPE_PCI1720,
- 0, 0, 4, 0, 0, 0, 0x0000, 0x0fff,
- NULL, NULL, &range_pci1720,
- 0, 0},
- {"pci1731", 0x1731,
- IORANGE_171x, 1, TYPE_PCI171X,
- 16, 0, 0, 16, 16, 0, 0x0fff, 0x0000,
- &range_pci17x1, range_codes_pci17x1, NULL,
- 10000, 512},
- /* dummy entry corresponding to driver name */
- {.name = DRV_NAME},
+ {
+ .name = "pci1710",
+ .device_id = 0x1710,
+ .iorange = IORANGE_171x,
+ .have_irq = 1,
+ .cardtype = TYPE_PCI171X,
+ .n_aichan = 16,
+ .n_aichand = 8,
+ .n_aochan = 2,
+ .n_dichan = 16,
+ .n_dochan = 16,
+ .n_counter = 1,
+ .ai_maxdata = 0x0fff,
+ .ao_maxdata = 0x0fff,
+ .rangelist_ai = &range_pci1710_3,
+ .rangecode_ai = range_codes_pci1710_3,
+ .rangelist_ao = &range_pci171x_da,
+ .ai_ns_min = 10000,
+ .fifo_half_size = 2048,
+ }, {
+ .name = "pci1710hg",
+ .device_id = 0x1710,
+ .iorange = IORANGE_171x,
+ .have_irq = 1,
+ .cardtype = TYPE_PCI171X,
+ .n_aichan = 16,
+ .n_aichand = 8,
+ .n_aochan = 2,
+ .n_dichan = 16,
+ .n_dochan = 16,
+ .n_counter = 1,
+ .ai_maxdata = 0x0fff,
+ .ao_maxdata = 0x0fff,
+ .rangelist_ai = &range_pci1710hg,
+ .rangecode_ai = range_codes_pci1710hg,
+ .rangelist_ao = &range_pci171x_da,
+ .ai_ns_min = 10000,
+ .fifo_half_size = 2048,
+ }, {
+ .name = "pci1711",
+ .device_id = 0x1711,
+ .iorange = IORANGE_171x,
+ .have_irq = 1,
+ .cardtype = TYPE_PCI171X,
+ .n_aichan = 16,
+ .n_aochan = 2,
+ .n_dichan = 16,
+ .n_dochan = 16,
+ .n_counter = 1,
+ .ai_maxdata = 0x0fff,
+ .ao_maxdata = 0x0fff,
+ .rangelist_ai = &range_pci17x1,
+ .rangecode_ai = range_codes_pci17x1,
+ .rangelist_ao = &range_pci171x_da,
+ .ai_ns_min = 10000,
+ .fifo_half_size = 512,
+ }, {
+ .name = "pci1713",
+ .device_id = 0x1713,
+ .iorange = IORANGE_171x,
+ .have_irq = 1,
+ .cardtype = TYPE_PCI1713,
+ .n_aichan = 32,
+ .n_aichand = 16,
+ .ai_maxdata = 0x0fff,
+ .rangelist_ai = &range_pci1710_3,
+ .rangecode_ai = range_codes_pci1710_3,
+ .ai_ns_min = 10000,
+ .fifo_half_size = 2048,
+ }, {
+ .name = "pci1720",
+ .device_id = 0x1720,
+ .iorange = IORANGE_1720,
+ .cardtype = TYPE_PCI1720,
+ .n_aochan = 4,
+ .ao_maxdata = 0x0fff,
+ .rangelist_ao = &range_pci1720,
+ }, {
+ .name = "pci1731",
+ .device_id = 0x1731,
+ .iorange = IORANGE_171x,
+ .have_irq = 1,
+ .cardtype = TYPE_PCI171X,
+ .n_aichan = 16,
+ .n_dichan = 16,
+ .n_dochan = 16,
+ .ai_maxdata = 0x0fff,
+ .rangelist_ai = &range_pci17x1,
+ .rangecode_ai = range_codes_pci17x1,
+ .ai_ns_min = 10000,
+ .fifo_half_size = 512,
+ },
};
struct pci1710_private {
- char valid; /* card is usable */
char neverending_ai; /* we do unlimited AI */
unsigned int CntrlReg; /* Control register */
unsigned int i8254_osc_base; /* frequence of onboard oscilator */
@@ -278,33 +325,108 @@ struct pci1710_private {
* internal state */
};
-#define devpriv ((struct pci1710_private *)dev->private)
-#define this_board ((const struct boardtype *)dev->board_ptr)
+/* used for gain list programming */
+static const unsigned int muxonechan[] = {
+ 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707,
+ 0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f,
+ 0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717,
+ 0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f
+};
/*
==============================================================================
+ Check if channel list from user is builded correctly
+ If it's ok, then program scan/gain logic.
+ This works for all cards.
*/
-
static int check_channel_list(struct comedi_device *dev,
struct comedi_subdevice *s,
- unsigned int *chanlist, unsigned int n_chan);
+ unsigned int *chanlist, unsigned int n_chan)
+{
+ unsigned int chansegment[32];
+ unsigned int i, nowmustbechan, seglen, segpos;
+
+ /* correct channel and range number check itself comedi/range.c */
+ if (n_chan < 1) {
+ comedi_error(dev, "range/channel list is empty!");
+ return 0;
+ }
+
+ if (n_chan == 1)
+ return 1; /* seglen=1 */
+
+ chansegment[0] = chanlist[0]; /* first channel is every time ok */
+ for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
+ if (chanlist[0] == chanlist[i])
+ break; /* we detected a loop, stop */
+ if ((CR_CHAN(chanlist[i]) & 1) &&
+ (CR_AREF(chanlist[i]) == AREF_DIFF)) {
+ comedi_error(dev, "Odd channel cannot be differential input!\n");
+ return 0;
+ }
+ nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
+ if (CR_AREF(chansegment[i - 1]) == AREF_DIFF)
+ nowmustbechan = (nowmustbechan + 1) % s->n_chan;
+ if (nowmustbechan != CR_CHAN(chanlist[i])) {
+ printk("channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n",
+ i, CR_CHAN(chanlist[i]), nowmustbechan,
+ CR_CHAN(chanlist[0]));
+ return 0;
+ }
+ chansegment[i] = chanlist[i]; /* next correct channel in list */
+ }
+
+ for (i = 0, segpos = 0; i < n_chan; i++) {
+ if (chanlist[i] != chansegment[i % seglen]) {
+ printk("bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
+ i, CR_CHAN(chansegment[i]),
+ CR_RANGE(chansegment[i]),
+ CR_AREF(chansegment[i]),
+ CR_CHAN(chanlist[i % seglen]),
+ CR_RANGE(chanlist[i % seglen]),
+ CR_AREF(chansegment[i % seglen]));
+ return 0;
+ }
+ }
+ return seglen;
+}
+
static void setup_channel_list(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned int *chanlist, unsigned int n_chan,
- unsigned int seglen);
-static void start_pacer(struct comedi_device *dev, int mode,
- unsigned int divisor1, unsigned int divisor2);
-static int pci1710_reset(struct comedi_device *dev);
-static int pci171x_ai_cancel(struct comedi_device *dev,
- struct comedi_subdevice *s);
+ unsigned int seglen)
+{
+ const struct boardtype *this_board = comedi_board(dev);
+ struct pci1710_private *devpriv = dev->private;
+ unsigned int i, range, chanprog;
-/* used for gain list programming */
-static const unsigned int muxonechan[] = {
- 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707,
- 0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f,
- 0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717,
- 0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f
-};
+ devpriv->act_chanlist_len = seglen;
+ devpriv->act_chanlist_pos = 0;
+
+ for (i = 0; i < seglen; i++) { /* store range list to card */
+ chanprog = muxonechan[CR_CHAN(chanlist[i])];
+ outw(chanprog, dev->iobase + PCI171x_MUX); /* select channel */
+ range = this_board->rangecode_ai[CR_RANGE(chanlist[i])];
+ if (CR_AREF(chanlist[i]) == AREF_DIFF)
+ range |= 0x0020;
+ outw(range, dev->iobase + PCI171x_RANGE); /* select gain */
+#ifdef PCI171x_PARANOIDCHECK
+ devpriv->act_chanlist[i] =
+ (CR_CHAN(chanlist[i]) << 12) & 0xf000;
+#endif
+ }
+#ifdef PCI171x_PARANOIDCHECK
+ for ( ; i < n_chan; i++) { /* store remainder of channel list */
+ devpriv->act_chanlist[i] =
+ (CR_CHAN(chanlist[i]) << 12) & 0xf000;
+ }
+#endif
+
+ devpriv->ai_et_MuxVal =
+ CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8);
+ /* select channel interval to scan */
+ outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX);
+}
/*
==============================================================================
@@ -313,12 +435,13 @@ static int pci171x_insn_read_ai(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct pci1710_private *devpriv = dev->private;
int n, timeout;
#ifdef PCI171x_PARANOIDCHECK
+ const struct boardtype *this_board = comedi_board(dev);
unsigned int idata;
#endif
- DPRINTK("adv_pci1710 EDBG: BGN: pci171x_insn_read_ai(...)\n");
devpriv->CntrlReg &= Control_CNT0;
devpriv->CntrlReg |= Control_SW; /* set software trigger */
outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
@@ -327,32 +450,18 @@ static int pci171x_insn_read_ai(struct comedi_device *dev,
setup_channel_list(dev, s, &insn->chanspec, 1, 1);
- DPRINTK("adv_pci1710 A ST=%4x IO=%x\n",
- inw(dev->iobase + PCI171x_STATUS),
- dev->iobase + PCI171x_STATUS);
for (n = 0; n < insn->n; n++) {
outw(0, dev->iobase + PCI171x_SOFTTRG); /* start conversion */
- DPRINTK("adv_pci1710 B n=%d ST=%4x\n", n,
- inw(dev->iobase + PCI171x_STATUS));
/* udelay(1); */
- DPRINTK("adv_pci1710 C n=%d ST=%4x\n", n,
- inw(dev->iobase + PCI171x_STATUS));
timeout = 100;
while (timeout--) {
if (!(inw(dev->iobase + PCI171x_STATUS) & Status_FE))
goto conv_finish;
- if (!(timeout % 10))
- DPRINTK("adv_pci1710 D n=%d tm=%d ST=%4x\n", n,
- timeout,
- inw(dev->iobase + PCI171x_STATUS));
}
comedi_error(dev, "A/D insn timeout");
outb(0, dev->iobase + PCI171x_CLRFIFO);
outb(0, dev->iobase + PCI171x_CLRINT);
data[n] = 0;
- DPRINTK
- ("adv_pci1710 EDBG: END: pci171x_insn_read_ai(...) n=%d\n",
- n);
return -ETIME;
conv_finish:
@@ -373,7 +482,6 @@ conv_finish:
outb(0, dev->iobase + PCI171x_CLRFIFO);
outb(0, dev->iobase + PCI171x_CLRINT);
- DPRINTK("adv_pci1710 EDBG: END: pci171x_insn_read_ai(...) n=%d\n", n);
return n;
}
@@ -384,6 +492,7 @@ static int pci171x_insn_write_ao(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct pci1710_private *devpriv = dev->private;
int n, chan, range, ofs;
chan = CR_CHAN(insn->chanspec);
@@ -416,6 +525,7 @@ static int pci171x_insn_read_ao(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct pci1710_private *devpriv = dev->private;
int n, chan;
chan = CR_CHAN(insn->chanspec);
@@ -457,6 +567,23 @@ static int pci171x_insn_bits_do(struct comedi_device *dev,
/*
==============================================================================
*/
+static void start_pacer(struct comedi_device *dev, int mode,
+ unsigned int divisor1, unsigned int divisor2)
+{
+ outw(0xb4, dev->iobase + PCI171x_CNTCTRL);
+ outw(0x74, dev->iobase + PCI171x_CNTCTRL);
+
+ if (mode == 1) {
+ outw(divisor2 & 0xff, dev->iobase + PCI171x_CNT2);
+ outw((divisor2 >> 8) & 0xff, dev->iobase + PCI171x_CNT2);
+ outw(divisor1 & 0xff, dev->iobase + PCI171x_CNT1);
+ outw((divisor1 >> 8) & 0xff, dev->iobase + PCI171x_CNT1);
+ }
+}
+
+/*
+==============================================================================
+*/
static int pci171x_insn_counter_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
@@ -486,6 +613,7 @@ static int pci171x_insn_counter_write(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
+ struct pci1710_private *devpriv = dev->private;
uint msb, lsb, ccntrl, status;
lsb = data[0] & 0x00FF;
@@ -517,6 +645,7 @@ static int pci171x_insn_counter_config(struct comedi_device *dev,
{
#ifdef unused
/* This doesn't work like a normal Comedi counter config */
+ struct pci1710_private *devpriv = dev->private;
uint ccntrl = 0;
devpriv->cnt0_write_wait = data[0] & 0x20;
@@ -552,6 +681,7 @@ static int pci1720_insn_write_ao(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct pci1710_private *devpriv = dev->private;
int n, rangereg, chan;
chan = CR_CHAN(insn->chanspec);
@@ -575,16 +705,47 @@ static int pci1720_insn_write_ao(struct comedi_device *dev,
/*
==============================================================================
*/
+static int pci171x_ai_cancel(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ const struct boardtype *this_board = comedi_board(dev);
+ struct pci1710_private *devpriv = dev->private;
+
+ switch (this_board->cardtype) {
+ default:
+ devpriv->CntrlReg &= Control_CNT0;
+ devpriv->CntrlReg |= Control_SW;
+
+ outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */
+ start_pacer(dev, -1, 0, 0);
+ outb(0, dev->iobase + PCI171x_CLRFIFO);
+ outb(0, dev->iobase + PCI171x_CLRINT);
+ break;
+ }
+
+ devpriv->ai_do = 0;
+ devpriv->ai_act_scan = 0;
+ s->async->cur_chan = 0;
+ devpriv->ai_buf_ptr = 0;
+ devpriv->neverending_ai = 0;
+
+ return 0;
+}
+
+/*
+==============================================================================
+*/
static void interrupt_pci1710_every_sample(void *d)
{
struct comedi_device *dev = d;
- struct comedi_subdevice *s = dev->subdevices + 0;
+ struct pci1710_private *devpriv = dev->private;
+ struct comedi_subdevice *s = &dev->subdevices[0];
int m;
#ifdef PCI171x_PARANOIDCHECK
+ const struct boardtype *this_board = comedi_board(dev);
short sampl;
#endif
- DPRINTK("adv_pci1710 EDBG: BGN: interrupt_pci1710_every_sample(...)\n");
m = inw(dev->iobase + PCI171x_STATUS);
if (m & Status_FE) {
printk("comedi%d: A/D FIFO empty (%4x)\n", dev->minor, m);
@@ -605,11 +766,9 @@ static void interrupt_pci1710_every_sample(void *d)
outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */
- DPRINTK("FOR ");
for (; !(inw(dev->iobase + PCI171x_STATUS) & Status_FE);) {
#ifdef PCI171x_PARANOIDCHECK
sampl = inw(dev->iobase + PCI171x_AD_DATA);
- DPRINTK("%04x:", sampl);
if (this_board->cardtype != TYPE_PCI1713)
if ((sampl & 0xf000) !=
devpriv->act_chanlist[s->async->cur_chan]) {
@@ -626,8 +785,6 @@ static void interrupt_pci1710_every_sample(void *d)
comedi_event(dev, s);
return;
}
- DPRINTK("%8d %2d %8d~", s->async->buf_int_ptr,
- s->async->cur_chan, s->async->buf_int_count);
comedi_buf_put(s->async, sampl & 0x0fff);
#else
comedi_buf_put(s->async,
@@ -641,11 +798,6 @@ static void interrupt_pci1710_every_sample(void *d)
if (s->async->cur_chan == 0) { /* one scan done */
devpriv->ai_act_scan++;
- DPRINTK
- ("adv_pci1710 EDBG: EOS1 bic %d bip %d buc %d bup %d\n",
- s->async->buf_int_count, s->async->buf_int_ptr,
- s->async->buf_user_count, s->async->buf_user_ptr);
- DPRINTK("adv_pci1710 EDBG: EOS2\n");
if ((!devpriv->neverending_ai) &&
(devpriv->ai_act_scan >= devpriv->ai_scans)) {
/* all data sampled */
@@ -658,7 +810,6 @@ static void interrupt_pci1710_every_sample(void *d)
}
outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */
- DPRINTK("adv_pci1710 EDBG: END: interrupt_pci1710_every_sample(...)\n");
comedi_event(dev, s);
}
@@ -669,12 +820,13 @@ static void interrupt_pci1710_every_sample(void *d)
static int move_block_from_fifo(struct comedi_device *dev,
struct comedi_subdevice *s, int n, int turn)
{
+ struct pci1710_private *devpriv = dev->private;
int i, j;
#ifdef PCI171x_PARANOIDCHECK
+ const struct boardtype *this_board = comedi_board(dev);
int sampl;
#endif
- DPRINTK("adv_pci1710 EDBG: BGN: move_block_from_fifo(...,%d,%d)\n", n,
- turn);
+
j = s->async->cur_chan;
for (i = 0; i < n; i++) {
#ifdef PCI171x_PARANOIDCHECK
@@ -705,7 +857,6 @@ static int move_block_from_fifo(struct comedi_device *dev,
}
}
s->async->cur_chan = j;
- DPRINTK("adv_pci1710 EDBG: END: move_block_from_fifo(...)\n");
return 0;
}
@@ -715,10 +866,11 @@ static int move_block_from_fifo(struct comedi_device *dev,
static void interrupt_pci1710_half_fifo(void *d)
{
struct comedi_device *dev = d;
- struct comedi_subdevice *s = dev->subdevices + 0;
+ const struct boardtype *this_board = comedi_board(dev);
+ struct pci1710_private *devpriv = dev->private;
+ struct comedi_subdevice *s = &dev->subdevices[0];
int m, samplesinbuf;
- DPRINTK("adv_pci1710 EDBG: BGN: interrupt_pci1710_half_fifo(...)\n");
m = inw(dev->iobase + PCI171x_STATUS);
if (!(m & Status_FH)) {
printk("comedi%d: A/D FIFO not half full! (%4x)\n",
@@ -760,7 +912,6 @@ static void interrupt_pci1710_half_fifo(void *d)
return;
}
outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */
- DPRINTK("adv_pci1710 EDBG: END: interrupt_pci1710_half_fifo(...)\n");
comedi_event(dev, s);
}
@@ -771,18 +922,14 @@ static void interrupt_pci1710_half_fifo(void *d)
static irqreturn_t interrupt_service_pci1710(int irq, void *d)
{
struct comedi_device *dev = d;
+ struct pci1710_private *devpriv = dev->private;
- DPRINTK("adv_pci1710 EDBG: BGN: interrupt_service_pci1710(%d,...)\n",
- irq);
if (!dev->attached) /* is device attached? */
return IRQ_NONE; /* no, exit */
/* is this interrupt from our board? */
if (!(inw(dev->iobase + PCI171x_STATUS) & Status_IRQ))
return IRQ_NONE; /* no, exit */
- DPRINTK("adv_pci1710 EDBG: interrupt_service_pci1710() ST: %4x\n",
- inw(dev->iobase + PCI171x_STATUS));
-
if (devpriv->ai_et) { /* Switch from initial TRIG_EXT to TRIG_xxx. */
devpriv->ai_et = 0;
devpriv->CntrlReg &= Control_CNT0;
@@ -802,7 +949,6 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d)
} else {
interrupt_pci1710_half_fifo(d);
}
- DPRINTK("adv_pci1710 EDBG: END: interrupt_service_pci1710(...)\n");
return IRQ_HANDLED;
}
@@ -812,11 +958,11 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d)
static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev,
struct comedi_subdevice *s)
{
+ const struct boardtype *this_board = comedi_board(dev);
+ struct pci1710_private *devpriv = dev->private;
unsigned int divisor1 = 0, divisor2 = 0;
unsigned int seglen;
- DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_docmd_and_mode(%d,...)\n",
- mode);
start_pacer(dev, -1, 0, 0); /* stop pacer */
seglen = check_channel_list(dev, s, devpriv->ai_chanlist,
@@ -869,10 +1015,6 @@ static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev,
i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
&divisor2, &devpriv->ai_timer1,
devpriv->ai_flags & TRIG_ROUND_MASK);
- DPRINTK
- ("adv_pci1710 EDBG: OSC base=%u div1=%u div2=%u timer=%u\n",
- devpriv->i8254_osc_base, divisor1, divisor2,
- devpriv->ai_timer1);
outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
if (mode != 2) {
/* start pacer */
@@ -888,27 +1030,9 @@ static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev,
break;
}
- DPRINTK("adv_pci1710 EDBG: END: pci171x_ai_docmd_and_mode(...)\n");
return 0;
}
-#ifdef PCI171X_EXTDEBUG
-/*
-==============================================================================
-*/
-static void pci171x_cmdtest_out(int e, struct comedi_cmd *cmd)
-{
- printk("adv_pci1710 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e,
- cmd->start_src, cmd->scan_begin_src, cmd->convert_src);
- printk("adv_pci1710 e=%d startarg=%d scanarg=%d convarg=%d\n", e,
- cmd->start_arg, cmd->scan_begin_arg, cmd->convert_arg);
- printk("adv_pci1710 e=%d stopsrc=%x scanend=%x\n", e, cmd->stop_src,
- cmd->scan_end_src);
- printk("adv_pci1710 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n",
- e, cmd->stop_arg, cmd->scan_end_arg, cmd->chanlist_len);
-}
-#endif
-
/*
==============================================================================
*/
@@ -916,83 +1040,33 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{
+ const struct boardtype *this_board = comedi_board(dev);
+ struct pci1710_private *devpriv = dev->private;
int err = 0;
int tmp;
unsigned int divisor1 = 0, divisor2 = 0;
- DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...)\n");
-#ifdef PCI171X_EXTDEBUG
- pci171x_cmdtest_out(-1, cmd);
-#endif
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_EXT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_FOLLOW;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
-
- if (err) {
-#ifdef PCI171X_EXTDEBUG
- pci171x_cmdtest_out(1, cmd);
-#endif
- DPRINTK(
- "adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=1\n",
- err);
+ if (err)
return 1;
- }
-
- /* step2: make sure trigger srcs are unique and mutually compatible */
-
- if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) {
- cmd->start_src = TRIG_NOW;
- err++;
- }
- if (cmd->scan_begin_src != TRIG_FOLLOW) {
- cmd->scan_begin_src = TRIG_FOLLOW;
- err++;
- }
+ /* step 2a: make sure trigger sources are unique */
- if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
- if (cmd->scan_end_src != TRIG_COUNT) {
- cmd->scan_end_src = TRIG_COUNT;
- err++;
- }
-
- if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
- err++;
+ /* step 2b: and mutually compatible */
- if (err) {
-#ifdef PCI171X_EXTDEBUG
- pci171x_cmdtest_out(2, cmd);
-#endif
- DPRINTK(
- "adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=2\n",
- err);
+ if (err)
return 2;
- }
/* step 3: make sure arguments are trivially compatible */
@@ -1034,15 +1108,8 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
}
}
- if (err) {
-#ifdef PCI171X_EXTDEBUG
- pci171x_cmdtest_out(3, cmd);
-#endif
- DPRINTK(
- "adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=3\n",
- err);
+ if (err)
return 3;
- }
/* step 4: fix up any arguments */
@@ -1057,12 +1124,8 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
err++;
}
- if (err) {
- DPRINTK
- ("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=4\n",
- err);
+ if (err)
return 4;
- }
/* step 5: complain about special chanlist considerations */
@@ -1072,7 +1135,6 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
return 5; /* incorrect channels list */
}
- DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) ret=0\n");
return 0;
}
@@ -1081,9 +1143,9 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
*/
static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
+ struct pci1710_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
- DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmd(...)\n");
devpriv->ai_n_chan = cmd->chanlist_len;
devpriv->ai_chanlist = cmd->chanlist;
devpriv->ai_flags = cmd->flags;
@@ -1115,162 +1177,12 @@ static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
/*
==============================================================================
- Check if channel list from user is builded correctly
- If it's ok, then program scan/gain logic.
- This works for all cards.
-*/
-static int check_channel_list(struct comedi_device *dev,
- struct comedi_subdevice *s,
- unsigned int *chanlist, unsigned int n_chan)
-{
- unsigned int chansegment[32];
- unsigned int i, nowmustbechan, seglen, segpos;
-
- DPRINTK("adv_pci1710 EDBG: check_channel_list(...,%d)\n", n_chan);
- /* correct channel and range number check itself comedi/range.c */
- if (n_chan < 1) {
- comedi_error(dev, "range/channel list is empty!");
- return 0;
- }
-
- if (n_chan == 1)
- return 1; /* seglen=1 */
-
- chansegment[0] = chanlist[0]; /* first channel is every time ok */
- for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
- if (chanlist[0] == chanlist[i])
- break; /* we detected a loop, stop */
- if ((CR_CHAN(chanlist[i]) & 1) &&
- (CR_AREF(chanlist[i]) == AREF_DIFF)) {
- comedi_error(dev, "Odd channel cannot be differential input!\n");
- return 0;
- }
- nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
- if (CR_AREF(chansegment[i - 1]) == AREF_DIFF)
- nowmustbechan = (nowmustbechan + 1) % s->n_chan;
- if (nowmustbechan != CR_CHAN(chanlist[i])) {
- printk("channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n",
- i, CR_CHAN(chanlist[i]), nowmustbechan,
- CR_CHAN(chanlist[0]));
- return 0;
- }
- chansegment[i] = chanlist[i]; /* next correct channel in list */
- }
-
- for (i = 0, segpos = 0; i < n_chan; i++) {
- if (chanlist[i] != chansegment[i % seglen]) {
- printk("bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
- i, CR_CHAN(chansegment[i]),
- CR_RANGE(chansegment[i]),
- CR_AREF(chansegment[i]),
- CR_CHAN(chanlist[i % seglen]),
- CR_RANGE(chanlist[i % seglen]),
- CR_AREF(chansegment[i % seglen]));
- return 0;
- }
- }
- return seglen;
-}
-
-static void setup_channel_list(struct comedi_device *dev,
- struct comedi_subdevice *s,
- unsigned int *chanlist, unsigned int n_chan,
- unsigned int seglen)
-{
- unsigned int i, range, chanprog;
-
- DPRINTK("adv_pci1710 EDBG: setup_channel_list(...,%d,%d)\n", n_chan,
- seglen);
- devpriv->act_chanlist_len = seglen;
- devpriv->act_chanlist_pos = 0;
-
- DPRINTK("SegLen: %d\n", seglen);
- for (i = 0; i < seglen; i++) { /* store range list to card */
- chanprog = muxonechan[CR_CHAN(chanlist[i])];
- outw(chanprog, dev->iobase + PCI171x_MUX); /* select channel */
- range = this_board->rangecode_ai[CR_RANGE(chanlist[i])];
- if (CR_AREF(chanlist[i]) == AREF_DIFF)
- range |= 0x0020;
- outw(range, dev->iobase + PCI171x_RANGE); /* select gain */
-#ifdef PCI171x_PARANOIDCHECK
- devpriv->act_chanlist[i] =
- (CR_CHAN(chanlist[i]) << 12) & 0xf000;
-#endif
- DPRINTK("GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range,
- devpriv->act_chanlist[i]);
- }
-#ifdef PCI171x_PARANOIDCHECK
- for ( ; i < n_chan; i++) { /* store remainder of channel list */
- devpriv->act_chanlist[i] =
- (CR_CHAN(chanlist[i]) << 12) & 0xf000;
- }
-#endif
-
- devpriv->ai_et_MuxVal =
- CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8);
- /* select channel interval to scan */
- outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX);
- DPRINTK("MUX: %4x L%4x.H%4x\n",
- CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8),
- CR_CHAN(chanlist[0]), CR_CHAN(chanlist[seglen - 1]));
-}
-
-/*
-==============================================================================
-*/
-static void start_pacer(struct comedi_device *dev, int mode,
- unsigned int divisor1, unsigned int divisor2)
-{
- DPRINTK("adv_pci1710 EDBG: BGN: start_pacer(%d,%u,%u)\n", mode,
- divisor1, divisor2);
- outw(0xb4, dev->iobase + PCI171x_CNTCTRL);
- outw(0x74, dev->iobase + PCI171x_CNTCTRL);
-
- if (mode == 1) {
- outw(divisor2 & 0xff, dev->iobase + PCI171x_CNT2);
- outw((divisor2 >> 8) & 0xff, dev->iobase + PCI171x_CNT2);
- outw(divisor1 & 0xff, dev->iobase + PCI171x_CNT1);
- outw((divisor1 >> 8) & 0xff, dev->iobase + PCI171x_CNT1);
- }
- DPRINTK("adv_pci1710 EDBG: END: start_pacer(...)\n");
-}
-
-/*
-==============================================================================
-*/
-static int pci171x_ai_cancel(struct comedi_device *dev,
- struct comedi_subdevice *s)
-{
- DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cancel(...)\n");
-
- switch (this_board->cardtype) {
- default:
- devpriv->CntrlReg &= Control_CNT0;
- devpriv->CntrlReg |= Control_SW;
-
- outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */
- start_pacer(dev, -1, 0, 0);
- outb(0, dev->iobase + PCI171x_CLRFIFO);
- outb(0, dev->iobase + PCI171x_CLRINT);
- break;
- }
-
- devpriv->ai_do = 0;
- devpriv->ai_act_scan = 0;
- s->async->cur_chan = 0;
- devpriv->ai_buf_ptr = 0;
- devpriv->neverending_ai = 0;
-
- DPRINTK("adv_pci1710 EDBG: END: pci171x_ai_cancel(...)\n");
- return 0;
-}
-
-/*
-==============================================================================
*/
static int pci171x_reset(struct comedi_device *dev)
{
- DPRINTK("adv_pci1710 EDBG: BGN: pci171x_reset(...)\n");
+ const struct boardtype *this_board = comedi_board(dev);
+ struct pci1710_private *devpriv = dev->private;
+
outw(0x30, dev->iobase + PCI171x_CNTCTRL);
devpriv->CntrlReg = Control_SW | Control_CNT0; /* Software trigger, CNT0=external */
outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */
@@ -1291,7 +1203,6 @@ static int pci171x_reset(struct comedi_device *dev)
outb(0, dev->iobase + PCI171x_CLRFIFO); /* clear FIFO */
outb(0, dev->iobase + PCI171x_CLRINT); /* clear INT request */
- DPRINTK("adv_pci1710 EDBG: END: pci171x_reset(...)\n");
return 0;
}
@@ -1300,7 +1211,8 @@ static int pci171x_reset(struct comedi_device *dev)
*/
static int pci1720_reset(struct comedi_device *dev)
{
- DPRINTK("adv_pci1710 EDBG: BGN: pci1720_reset(...)\n");
+ struct pci1710_private *devpriv = dev->private;
+
outb(Syncont_SC0, dev->iobase + PCI1720_SYNCONT); /* set synchronous output mode */
devpriv->da_ranges = 0xAA;
outb(devpriv->da_ranges, dev->iobase + PCI1720_RANGE); /* set all ranges to +/-5V */
@@ -1313,7 +1225,6 @@ static int pci1720_reset(struct comedi_device *dev)
devpriv->ao_data[1] = 0x0800;
devpriv->ao_data[2] = 0x0800;
devpriv->ao_data[3] = 0x0800;
- DPRINTK("adv_pci1710 EDBG: END: pci1720_reset(...)\n");
return 0;
}
@@ -1322,82 +1233,55 @@ static int pci1720_reset(struct comedi_device *dev)
*/
static int pci1710_reset(struct comedi_device *dev)
{
- DPRINTK("adv_pci1710 EDBG: BGN: pci1710_reset(...)\n");
+ const struct boardtype *this_board = comedi_board(dev);
+
switch (this_board->cardtype) {
case TYPE_PCI1720:
return pci1720_reset(dev);
default:
return pci171x_reset(dev);
}
- DPRINTK("adv_pci1710 EDBG: END: pci1710_reset(...)\n");
}
-static struct pci_dev *pci1710_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static const void *pci1710_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
- int board_index = this_board - boardtypes;
+ const struct boardtype *this_board;
int i;
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (bus != pcidev->bus->number ||
- slot != PCI_SLOT(pcidev->devfn))
- continue;
- }
- if (pcidev->vendor != PCI_VENDOR_ID_ADVANTECH)
- continue;
- if (strcmp(this_board->name, DRV_NAME) == 0) {
- for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) {
- if (pcidev->device == boardtypes[i].device_id) {
- board_index = i;
- break;
- }
- }
- if (i == ARRAY_SIZE(boardtypes))
- continue;
- } else {
- if (pcidev->device != boardtypes[board_index].device_id)
- continue;
- }
- dev->board_ptr = &boardtypes[board_index];
- return pcidev;
+ for (i = 0; i < ARRAY_SIZE(boardtypes); i++) {
+ this_board = &boardtypes[i];
+ if (pcidev->device == this_board->device_id)
+ return this_board;
}
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
return NULL;
}
-static int pci1710_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int pci1710_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev;
+ const struct boardtype *this_board;
+ struct pci1710_private *devpriv;
struct comedi_subdevice *s;
int ret, subdev, n_subdevices;
- unsigned int irq;
- dev_info(dev->class_dev, DRV_NAME ": attach\n");
+ comedi_set_hw_dev(dev, &pcidev->dev);
- ret = alloc_private(dev, sizeof(struct pci1710_private));
- if (ret < 0)
- return -ENOMEM;
+ this_board = pci1710_find_boardinfo(dev, pcidev);
+ if (!this_board)
+ return -ENODEV;
+ dev->board_ptr = this_board;
+ dev->board_name = this_board->name;
- pcidev = pci1710_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret < 0)
+ return ret;
+ devpriv = dev->private;
- ret = comedi_pci_enable(pcidev, DRV_NAME);
+ ret = comedi_pci_enable(pcidev, dev->board_name);
if (ret)
return ret;
-
dev->iobase = pci_resource_start(pcidev, 2);
- irq = pcidev->irq;
-
- dev->board_name = this_board->name;
n_subdevices = 0;
if (this_board->n_aichan)
@@ -1417,30 +1301,17 @@ static int pci1710_attach(struct comedi_device *dev,
pci1710_reset(dev);
- if (this_board->have_irq) {
- if (irq) {
- if (request_irq(irq, interrupt_service_pci1710,
- IRQF_SHARED, "Advantech PCI-1710",
- dev)) {
- dev_dbg(dev->class_dev,
- "unable to allocate IRQ %d, DISABLING IT",
- irq);
- irq = 0; /* Can't use IRQ */
- } else {
- dev_dbg(dev->class_dev, "irq=%u", irq);
- }
- } else {
- dev_dbg(dev->class_dev, "IRQ disabled");
- }
- } else {
- irq = 0;
+ if (this_board->have_irq && pcidev->irq) {
+ ret = request_irq(pcidev->irq, interrupt_service_pci1710,
+ IRQF_SHARED, dev->board_name, dev);
+ if (ret == 0)
+ dev->irq = pcidev->irq;
}
- dev->irq = irq;
subdev = 0;
if (this_board->n_aichan) {
- s = dev->subdevices + subdev;
+ s = &dev->subdevices[subdev];
dev->read_subdev = s;
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND;
@@ -1452,7 +1323,7 @@ static int pci1710_attach(struct comedi_device *dev,
s->range_table = this_board->rangelist_ai;
s->cancel = pci171x_ai_cancel;
s->insn_read = pci171x_insn_read_ai;
- if (irq) {
+ if (dev->irq) {
s->subdev_flags |= SDF_CMD_READ;
s->do_cmdtest = pci171x_ai_cmdtest;
s->do_cmd = pci171x_ai_cmd;
@@ -1462,7 +1333,7 @@ static int pci1710_attach(struct comedi_device *dev,
}
if (this_board->n_aochan) {
- s = dev->subdevices + subdev;
+ s = &dev->subdevices[subdev];
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
s->n_chan = this_board->n_aochan;
@@ -1482,7 +1353,7 @@ static int pci1710_attach(struct comedi_device *dev,
}
if (this_board->n_dichan) {
- s = dev->subdevices + subdev;
+ s = &dev->subdevices[subdev];
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
s->n_chan = this_board->n_dichan;
@@ -1495,7 +1366,7 @@ static int pci1710_attach(struct comedi_device *dev,
}
if (this_board->n_dochan) {
- s = dev->subdevices + subdev;
+ s = &dev->subdevices[subdev];
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
s->n_chan = this_board->n_dochan;
@@ -1510,7 +1381,7 @@ static int pci1710_attach(struct comedi_device *dev,
}
if (this_board->n_counter) {
- s = dev->subdevices + subdev;
+ s = &dev->subdevices[subdev];
s->type = COMEDI_SUBD_COUNTER;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = this_board->n_counter;
@@ -1523,7 +1394,8 @@ static int pci1710_attach(struct comedi_device *dev,
subdev++;
}
- devpriv->valid = 1;
+ dev_info(dev->class_dev, "%s attached, irq %sabled\n",
+ dev->board_name, dev->irq ? "en" : "dis");
return 0;
}
@@ -1532,27 +1404,21 @@ static void pci1710_detach(struct comedi_device *dev)
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- if (dev->private) {
- if (devpriv->valid)
- pci1710_reset(dev);
- if (dev->irq)
- free_irq(dev->irq, dev);
- }
+ if (dev->iobase)
+ pci1710_reset(dev);
+ if (dev->irq)
+ free_irq(dev->irq, dev);
if (pcidev) {
if (dev->iobase)
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
}
}
static struct comedi_driver adv_pci1710_driver = {
.driver_name = "adv_pci1710",
.module = THIS_MODULE,
- .attach = pci1710_attach,
+ .attach_pci = pci1710_attach_pci,
.detach = pci1710_detach,
- .num_names = ARRAY_SIZE(boardtypes),
- .board_name = &boardtypes[0].name,
- .offset = sizeof(struct boardtype),
};
static int __devinit adv_pci1710_pci_probe(struct pci_dev *dev,
diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
index dfde0f6328dd..df4efc0606de 100644
--- a/drivers/staging/comedi/drivers/adv_pci1723.c
+++ b/drivers/staging/comedi/drivers/adv_pci1723.c
@@ -52,11 +52,6 @@ TODO:
#define PCI_VENDOR_ID_ADVANTECH 0x13fe /* Advantech PCI vendor ID */
-/* hardware types of the cards */
-#define TYPE_PCI1723 0
-
-#define IORANGE_1723 0x2A
-
/* all the registers for the pci1723 board */
#define PCI1723_DA(N) ((N)<<1) /* W: D/A register N (0 to 7) */
@@ -112,63 +107,18 @@ TODO:
#define PCI1723_SELECT_CALIBRATION 0x28 /* Select the calibration Ref_V */
-/* static unsigned short pci_list_builded=0; =1 list of card is know */
-
-static const struct comedi_lrange range_pci1723 = { 1, {
- BIP_RANGE(10)
- }
-};
-
-/*
- * Board descriptions for pci1723 boards.
- */
-struct pci1723_board {
- const char *name;
- int vendor_id; /* PCI vendor a device ID of card */
- int device_id;
- int iorange;
- char cardtype;
- int n_aochan; /* num of D/A chans */
- int n_diochan; /* num of DIO chans */
- int ao_maxdata; /* resolution of D/A */
- const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */
-};
-
-static const struct pci1723_board boardtypes[] = {
- {
- .name = "pci1723",
- .vendor_id = PCI_VENDOR_ID_ADVANTECH,
- .device_id = 0x1723,
- .iorange = IORANGE_1723,
- .cardtype = TYPE_PCI1723,
- .n_aochan = 8,
- .n_diochan = 16,
- .ao_maxdata = 0xffff,
- .rangelist_ao = &range_pci1723,
- },
-};
-
-/* This structure is for data unique to this hardware driver. */
struct pci1723_private {
- int valid; /* card is usable; */
-
unsigned char da_range[8]; /* D/A output range for each channel */
-
short ao_data[8]; /* data output buffer */
};
-/* The following macro to make it easy to access the private structure. */
-#define devpriv ((struct pci1723_private *)dev->private)
-
-#define this_board boardtypes
-
/*
* The pci1723 card reset;
*/
static int pci1723_reset(struct comedi_device *dev)
{
+ struct pci1723_private *devpriv = dev->private;
int i;
- DPRINTK("adv_pci1723 EDBG: BGN: pci1723_reset(...)\n");
outw(0x01, dev->iobase + PCI1723_SYN_SET);
/* set synchronous output mode */
@@ -190,7 +140,6 @@ static int pci1723_reset(struct comedi_device *dev)
/* set asynchronous output mode */
outw(0, dev->iobase + PCI1723_SYN_SET);
- DPRINTK("adv_pci1723 EDBG: END: pci1723_reset(...)\n");
return 0;
}
@@ -198,10 +147,10 @@ static int pci1723_insn_read_ao(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct pci1723_private *devpriv = dev->private;
int n, chan;
chan = CR_CHAN(insn->chanspec);
- DPRINTK(" adv_PCI1723 DEBUG: pci1723_insn_read_ao() -----\n");
for (n = 0; n < insn->n; n++)
data[n] = devpriv->ao_data[chan];
@@ -215,11 +164,10 @@ static int pci1723_ao_write_winsn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct pci1723_private *devpriv = dev->private;
int n, chan;
chan = CR_CHAN(insn->chanspec);
- DPRINTK("PCI1723: the pci1723_ao_write_winsn() ------\n");
-
for (n = 0; n < insn->n; n++) {
devpriv->ao_data[chan] = data[n];
@@ -286,124 +234,73 @@ static int pci1723_dio_insn_bits(struct comedi_device *dev,
return insn->n;
}
-static struct pci_dev *pci1723_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int pci1723_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
-
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (bus != pcidev->bus->number ||
- slot != PCI_SLOT(pcidev->devfn))
- continue;
- }
- if (pcidev->vendor != PCI_VENDOR_ID_ADVANTECH)
- continue;
- return pcidev;
- }
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
- return NULL;
-}
-
-static int pci1723_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev;
+ struct pci1723_private *devpriv;
struct comedi_subdevice *s;
- int ret, subdev, n_subdevices;
+ int ret;
- printk(KERN_ERR "comedi%d: adv_pci1723: board=%s",
- dev->minor, this_board->name);
-
- ret = alloc_private(dev, sizeof(struct pci1723_private));
- if (ret < 0) {
- printk(" - Allocation failed!\n");
- return -ENOMEM;
- }
-
- pcidev = pci1723_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
comedi_set_hw_dev(dev, &pcidev->dev);
+ dev->board_name = dev->driver->driver_name;
- ret = comedi_pci_enable(pcidev, "adv_pci1723");
- if (ret)
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret < 0)
return ret;
+ devpriv = dev->private;
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
dev->iobase = pci_resource_start(pcidev, 2);
- dev->board_name = this_board->name;
-
- n_subdevices = 0;
-
- if (this_board->n_aochan)
- n_subdevices++;
- if (this_board->n_diochan)
- n_subdevices++;
-
- ret = comedi_alloc_subdevices(dev, n_subdevices);
+ ret = comedi_alloc_subdevices(dev, 2);
if (ret)
return ret;
- pci1723_reset(dev);
- subdev = 0;
- if (this_board->n_aochan) {
- s = dev->subdevices + subdev;
- dev->write_subdev = s;
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = this_board->n_aochan;
- s->maxdata = this_board->ao_maxdata;
- s->len_chanlist = this_board->n_aochan;
- s->range_table = this_board->rangelist_ao;
-
- s->insn_write = pci1723_ao_write_winsn;
- s->insn_read = pci1723_insn_read_ao;
-
- /* read DIO config */
- switch (inw(dev->iobase + PCI1723_DIGITAL_IO_PORT_MODE)
- & 0x03) {
- case 0x00: /* low byte output, high byte output */
- s->io_bits = 0xFFFF;
- break;
- case 0x01: /* low byte input, high byte output */
- s->io_bits = 0xFF00;
- break;
- case 0x02: /* low byte output, high byte input */
- s->io_bits = 0x00FF;
- break;
- case 0x03: /* low byte input, high byte input */
- s->io_bits = 0x0000;
- break;
- }
- /* read DIO port state */
- s->state = inw(dev->iobase + PCI1723_READ_DIGITAL_INPUT_DATA);
-
- subdev++;
- }
-
- if (this_board->n_diochan) {
- s = dev->subdevices + subdev;
- s->type = COMEDI_SUBD_DIO;
- s->subdev_flags =
- SDF_READABLE | SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = this_board->n_diochan;
- s->maxdata = 1;
- s->len_chanlist = this_board->n_diochan;
- s->range_table = &range_digital;
- s->insn_config = pci1723_dio_insn_config;
- s->insn_bits = pci1723_dio_insn_bits;
- subdev++;
+ s = &dev->subdevices[0];
+ dev->write_subdev = s;
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
+ s->n_chan = 8;
+ s->maxdata = 0xffff;
+ s->len_chanlist = 8;
+ s->range_table = &range_bipolar10;
+ s->insn_write = pci1723_ao_write_winsn;
+ s->insn_read = pci1723_insn_read_ao;
+
+ s = &dev->subdevices[1];
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 16;
+ s->maxdata = 1;
+ s->len_chanlist = 16;
+ s->range_table = &range_digital;
+ s->insn_config = pci1723_dio_insn_config;
+ s->insn_bits = pci1723_dio_insn_bits;
+
+ /* read DIO config */
+ switch (inw(dev->iobase + PCI1723_DIGITAL_IO_PORT_MODE) & 0x03) {
+ case 0x00: /* low byte output, high byte output */
+ s->io_bits = 0xFFFF;
+ break;
+ case 0x01: /* low byte input, high byte output */
+ s->io_bits = 0xFF00;
+ break;
+ case 0x02: /* low byte output, high byte input */
+ s->io_bits = 0x00FF;
+ break;
+ case 0x03: /* low byte input, high byte input */
+ s->io_bits = 0x0000;
+ break;
}
-
- devpriv->valid = 1;
+ /* read DIO port state */
+ s->state = inw(dev->iobase + PCI1723_READ_DIGITAL_INPUT_DATA);
pci1723_reset(dev);
+ dev_info(dev->class_dev, "%s attached\n", dev->board_name);
+
return 0;
}
@@ -411,21 +308,18 @@ static void pci1723_detach(struct comedi_device *dev)
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- if (dev->private) {
- if (devpriv->valid)
- pci1723_reset(dev);
- }
if (pcidev) {
- if (dev->iobase)
+ if (dev->iobase) {
+ pci1723_reset(dev);
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
+ }
}
}
static struct comedi_driver adv_pci1723_driver = {
.driver_name = "adv_pci1723",
.module = THIS_MODULE,
- .attach = pci1723_attach,
+ .attach_pci = pci1723_attach_pci,
.detach = pci1723_detach,
};
diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
index 2d4cb7f638b2..a3c22419cd5f 100644
--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
+++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
@@ -36,15 +36,6 @@ Configuration options:
#include "8255.h"
#include "8253.h"
-#undef PCI_DIO_EXTDEBUG /* if defined, enable extensive debug logging */
-
-#undef DPRINTK
-#ifdef PCI_DIO_EXTDEBUG
-#define DPRINTK(fmt, args...) printk(fmt, ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
#define PCI_VENDOR_ID_ADVANTECH 0x13fe
/* hardware types of the cards */
@@ -250,6 +241,7 @@ struct dio_boardtype {
int device_id;
int main_pci_region; /* main I/O PCI region */
enum hw_cards_id cardtype;
+ int nsubdevs;
struct diosubd_data sdi[MAX_DI_SUBDEVS]; /* DI chans */
struct diosubd_data sdo[MAX_DO_SUBDEVS]; /* DO chans */
struct diosubd_data sdio[MAX_DIO_SUBDEVG]; /* DIO 8255 chans */
@@ -259,126 +251,164 @@ struct dio_boardtype {
};
static const struct dio_boardtype boardtypes[] = {
- {"pci1730", PCI_VENDOR_ID_ADVANTECH, 0x1730, PCIDIO_MAINREG,
- TYPE_PCI1730,
- { {16, PCI1730_DI, 2, 0}, {16, PCI1730_IDI, 2, 0} },
- { {16, PCI1730_DO, 2, 0}, {16, PCI1730_IDO, 2, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
- { {0, 0, 0, 0} },
- IO_8b},
- {"pci1733", PCI_VENDOR_ID_ADVANTECH, 0x1733, PCIDIO_MAINREG,
- TYPE_PCI1733,
- { {0, 0, 0, 0}, {32, PCI1733_IDI, 4, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
- { {0, 0, 0, 0} },
- IO_8b},
- {"pci1734", PCI_VENDOR_ID_ADVANTECH, 0x1734, PCIDIO_MAINREG,
- TYPE_PCI1734,
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {0, 0, 0, 0}, {32, PCI1734_IDO, 4, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
- { {0, 0, 0, 0} },
- IO_8b},
- {"pci1735", PCI_VENDOR_ID_ADVANTECH, 0x1735, PCIDIO_MAINREG,
- TYPE_PCI1735,
- { {32, PCI1735_DI, 4, 0}, {0, 0, 0, 0} },
- { {32, PCI1735_DO, 4, 0}, {0, 0, 0, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { 4, PCI1735_BOARDID, 1, SDF_INTERNAL},
- { {3, PCI1735_C8254, 1, 0} },
- IO_8b},
- {"pci1736", PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI1736_MAINREG,
- TYPE_PCI1736,
- { {0, 0, 0, 0}, {16, PCI1736_IDI, 2, 0} },
- { {0, 0, 0, 0}, {16, PCI1736_IDO, 2, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {4, PCI1736_BOARDID, 1, SDF_INTERNAL},
- { {0, 0, 0, 0} },
- IO_8b},
- {"pci1739", PCI_VENDOR_ID_ADVANTECH, 0x1739, PCIDIO_MAINREG,
- TYPE_PCI1739,
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {48, PCI1739_DIO, 2, 0}, {0, 0, 0, 0} },
- {0, 0, 0, 0},
- { {0, 0, 0, 0} },
- IO_8b},
- {"pci1750", PCI_VENDOR_ID_ADVANTECH, 0x1750, PCIDIO_MAINREG,
- TYPE_PCI1750,
- { {0, 0, 0, 0}, {16, PCI1750_IDI, 2, 0} },
- { {0, 0, 0, 0}, {16, PCI1750_IDO, 2, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {0, 0, 0, 0},
- { {0, 0, 0, 0} },
- IO_8b},
- {"pci1751", PCI_VENDOR_ID_ADVANTECH, 0x1751, PCIDIO_MAINREG,
- TYPE_PCI1751,
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {48, PCI1751_DIO, 2, 0}, {0, 0, 0, 0} },
- {0, 0, 0, 0},
- { {3, PCI1751_CNT, 1, 0} },
- IO_8b},
- {"pci1752", PCI_VENDOR_ID_ADVANTECH, 0x1752, PCIDIO_MAINREG,
- TYPE_PCI1752,
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {32, PCI1752_IDO, 2, 0}, {32, PCI1752_IDO2, 2, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
- { {0, 0, 0, 0} },
- IO_16b},
- {"pci1753", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
- TYPE_PCI1753,
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {96, PCI1753_DIO, 4, 0}, {0, 0, 0, 0} },
- {0, 0, 0, 0},
- { {0, 0, 0, 0} },
- IO_8b},
- {"pci1753e", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
- TYPE_PCI1753E,
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {96, PCI1753_DIO, 4, 0}, {96, PCI1753E_DIO, 4, 0} },
- {0, 0, 0, 0},
- { {0, 0, 0, 0} },
- IO_8b},
- {"pci1754", PCI_VENDOR_ID_ADVANTECH, 0x1754, PCIDIO_MAINREG,
- TYPE_PCI1754,
- { {32, PCI1754_IDI, 2, 0}, {32, PCI1754_IDI2, 2, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
- { {0, 0, 0, 0} },
- IO_16b},
- {"pci1756", PCI_VENDOR_ID_ADVANTECH, 0x1756, PCIDIO_MAINREG,
- TYPE_PCI1756,
- { {0, 0, 0, 0}, {32, PCI1756_IDI, 2, 0} },
- { {0, 0, 0, 0}, {32, PCI1756_IDO, 2, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
- { {0, 0, 0, 0} },
- IO_16b},
- {"pci1760", PCI_VENDOR_ID_ADVANTECH, 0x1760, 0,
- TYPE_PCI1760,
- { {0, 0, 0, 0}, {0, 0, 0, 0} }, /* This card have own setup work */
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {0, 0, 0, 0},
- { {0, 0, 0, 0} },
- IO_8b},
- {"pci1762", PCI_VENDOR_ID_ADVANTECH, 0x1762, PCIDIO_MAINREG,
- TYPE_PCI1762,
- { {0, 0, 0, 0}, {16, PCI1762_IDI, 1, 0} },
- { {0, 0, 0, 0}, {16, PCI1762_RO, 1, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {4, PCI1762_BOARDID, 1, SDF_INTERNAL},
- { {0, 0, 0, 0} },
- IO_16b}
+ {
+ .name = "pci1730",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1730,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1730,
+ .nsubdevs = 5,
+ .sdi[0] = { 16, PCI1730_DI, 2, 0, },
+ .sdi[1] = { 16, PCI1730_IDI, 2, 0, },
+ .sdo[0] = { 16, PCI1730_DO, 2, 0, },
+ .sdo[1] = { 16, PCI1730_IDO, 2, 0, },
+ .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1733",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1733,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1733,
+ .nsubdevs = 2,
+ .sdi[1] = { 32, PCI1733_IDI, 4, 0, },
+ .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1734",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1734,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1734,
+ .nsubdevs = 2,
+ .sdo[1] = { 32, PCI1734_IDO, 4, 0, },
+ .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1735",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1735,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1735,
+ .nsubdevs = 4,
+ .sdi[0] = { 32, PCI1735_DI, 4, 0, },
+ .sdo[0] = { 32, PCI1735_DO, 4, 0, },
+ .boardid = { 4, PCI1735_BOARDID, 1, SDF_INTERNAL, },
+ .s8254[0] = { 3, PCI1735_C8254, 1, 0, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1736",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1736,
+ .main_pci_region = PCI1736_MAINREG,
+ .cardtype = TYPE_PCI1736,
+ .nsubdevs = 3,
+ .sdi[1] = { 16, PCI1736_IDI, 2, 0, },
+ .sdo[1] = { 16, PCI1736_IDO, 2, 0, },
+ .boardid = { 4, PCI1736_BOARDID, 1, SDF_INTERNAL, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1739",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1739,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1739,
+ .nsubdevs = 2,
+ .sdio[0] = { 48, PCI1739_DIO, 2, 0, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1750",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1750,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1750,
+ .nsubdevs = 2,
+ .sdi[1] = { 16, PCI1750_IDI, 2, 0, },
+ .sdo[1] = { 16, PCI1750_IDO, 2, 0, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1751",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1751,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1751,
+ .nsubdevs = 3,
+ .sdio[0] = { 48, PCI1751_DIO, 2, 0, },
+ .s8254[0] = { 3, PCI1751_CNT, 1, 0, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1752",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1752,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1752,
+ .nsubdevs = 3,
+ .sdo[0] = { 32, PCI1752_IDO, 2, 0, },
+ .sdo[1] = { 32, PCI1752_IDO2, 2, 0, },
+ .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, },
+ .io_access = IO_16b,
+ }, {
+ .name = "pci1753",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1753,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1753,
+ .nsubdevs = 4,
+ .sdio[0] = { 96, PCI1753_DIO, 4, 0, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1753e",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1753,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1753E,
+ .nsubdevs = 8,
+ .sdio[0] = { 96, PCI1753_DIO, 4, 0, },
+ .sdio[1] = { 96, PCI1753E_DIO, 4, 0, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1754",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1754,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1754,
+ .nsubdevs = 3,
+ .sdi[0] = { 32, PCI1754_IDI, 2, 0, },
+ .sdi[1] = { 32, PCI1754_IDI2, 2, 0, },
+ .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, },
+ .io_access = IO_16b,
+ }, {
+ .name = "pci1756",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1756,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1756,
+ .nsubdevs = 3,
+ .sdi[1] = { 32, PCI1756_IDI, 2, 0, },
+ .sdo[1] = { 32, PCI1756_IDO, 2, 0, },
+ .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, },
+ .io_access = IO_16b,
+ }, {
+ /* This card has its own 'attach' */
+ .name = "pci1760",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1760,
+ .main_pci_region = 0,
+ .cardtype = TYPE_PCI1760,
+ .nsubdevs = 4,
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1762",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1762,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1762,
+ .nsubdevs = 3,
+ .sdi[1] = { 16, PCI1762_IDI, 1, 0, },
+ .sdo[1] = { 16, PCI1762_RO, 1, 0, },
+ .boardid = { 4, PCI1762_BOARDID, 1, SDF_INTERNAL, },
+ .io_access = IO_16b,
+ },
};
struct pci_dio_private {
@@ -401,9 +431,6 @@ struct pci_dio_private {
unsigned short IDIFiltrHigh[8]; /* IDI's filter value high signal */
};
-#define devpriv ((struct pci_dio_private *)dev->private)
-#define this_board ((const struct dio_boardtype *)dev->board_ptr)
-
/*
==============================================================================
*/
@@ -694,6 +721,7 @@ static int pci1760_insn_cnt_write(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct pci_dio_private *devpriv = dev->private;
int ret;
unsigned char chan = CR_CHAN(insn->chanspec) & 0x07;
unsigned char bitmask = 1 << chan;
@@ -736,6 +764,7 @@ static int pci1760_insn_cnt_write(struct comedi_device *dev,
*/
static int pci1760_reset(struct comedi_device *dev)
{
+ struct pci_dio_private *devpriv = dev->private;
int i;
unsigned char omb[4] = { 0x00, 0x00, 0x00, 0x00 };
unsigned char imb[4];
@@ -816,7 +845,7 @@ static int pci1760_reset(struct comedi_device *dev)
*/
static int pci_dio_reset(struct comedi_device *dev)
{
- DPRINTK("adv_pci_dio EDBG: BGN: pci171x_reset(...)\n");
+ const struct dio_boardtype *this_board = comedi_board(dev);
switch (this_board->cardtype) {
case TYPE_PCI1730:
@@ -917,21 +946,17 @@ static int pci_dio_reset(struct comedi_device *dev)
break;
}
- DPRINTK("adv_pci_dio EDBG: END: pci171x_reset(...)\n");
-
return 0;
}
/*
==============================================================================
*/
-static int pci1760_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int pci1760_attach(struct comedi_device *dev)
{
struct comedi_subdevice *s;
- int subdev = 0;
- s = dev->subdevices + subdev;
+ s = &dev->subdevices[0];
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
s->n_chan = 8;
@@ -939,9 +964,8 @@ static int pci1760_attach(struct comedi_device *dev,
s->len_chanlist = 8;
s->range_table = &range_digital;
s->insn_bits = pci1760_insn_bits_di;
- subdev++;
- s = dev->subdevices + subdev;
+ s = &dev->subdevices[1];
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
s->n_chan = 8;
@@ -950,18 +974,16 @@ static int pci1760_attach(struct comedi_device *dev,
s->range_table = &range_digital;
s->state = 0;
s->insn_bits = pci1760_insn_bits_do;
- subdev++;
- s = dev->subdevices + subdev;
+ s = &dev->subdevices[2];
s->type = COMEDI_SUBD_TIMER;
s->subdev_flags = SDF_WRITABLE | SDF_LSAMPL;
s->n_chan = 2;
s->maxdata = 0xffffffff;
s->len_chanlist = 2;
/* s->insn_config=pci1760_insn_pwm_cfg; */
- subdev++;
- s = dev->subdevices + subdev;
+ s = &dev->subdevices[3];
s->type = COMEDI_SUBD_COUNTER;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 8;
@@ -970,7 +992,6 @@ static int pci1760_attach(struct comedi_device *dev,
s->insn_read = pci1760_insn_cnt_read;
s->insn_write = pci1760_insn_cnt_write;
/* s->insn_config=pci1760_insn_cnt_cfg; */
- subdev++;
return 0;
}
@@ -978,9 +999,12 @@ static int pci1760_attach(struct comedi_device *dev,
/*
==============================================================================
*/
-static int pci_dio_add_di(struct comedi_device *dev, struct comedi_subdevice *s,
- const struct diosubd_data *d, int subdev)
+static int pci_dio_add_di(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ const struct diosubd_data *d)
{
+ const struct dio_boardtype *this_board = comedi_board(dev);
+
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON | d->specflags;
if (d->chans > 16)
@@ -1005,9 +1029,12 @@ static int pci_dio_add_di(struct comedi_device *dev, struct comedi_subdevice *s,
/*
==============================================================================
*/
-static int pci_dio_add_do(struct comedi_device *dev, struct comedi_subdevice *s,
- const struct diosubd_data *d, int subdev)
+static int pci_dio_add_do(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ const struct diosubd_data *d)
{
+ const struct dio_boardtype *this_board = comedi_board(dev);
+
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
if (d->chans > 16)
@@ -1035,7 +1062,7 @@ static int pci_dio_add_do(struct comedi_device *dev, struct comedi_subdevice *s,
*/
static int pci_dio_add_8254(struct comedi_device *dev,
struct comedi_subdevice *s,
- const struct diosubd_data *d, int subdev)
+ const struct diosubd_data *d)
{
s->type = COMEDI_SUBD_COUNTER;
s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
@@ -1050,101 +1077,69 @@ static int pci_dio_add_8254(struct comedi_device *dev,
return 0;
}
-static struct pci_dev *pci_dio_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static const void *pci_dio_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
+ const struct dio_boardtype *this_board;
int i;
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (bus != pcidev->bus->number ||
- slot != PCI_SLOT(pcidev->devfn))
- continue;
- }
- for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) {
- if (boardtypes[i].vendor_id != pcidev->vendor)
- continue;
- if (boardtypes[i].device_id != pcidev->device)
- continue;
- dev->board_ptr = boardtypes + i;
- return pcidev;
- }
+ for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) {
+ this_board = &boardtypes[i];
+ if (this_board->vendor_id == pcidev->vendor &&
+ this_board->device_id == pcidev->device)
+ return this_board;
}
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
return NULL;
}
-static int pci_dio_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int pci_dio_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev;
+ const struct dio_boardtype *this_board;
+ struct pci_dio_private *devpriv;
struct comedi_subdevice *s;
- int ret, subdev, n_subdevices, i, j;
+ int ret, subdev, i, j;
- ret = alloc_private(dev, sizeof(struct pci_dio_private));
- if (ret < 0)
- return -ENOMEM;
-
- pcidev = pci_dio_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
comedi_set_hw_dev(dev, &pcidev->dev);
- if (comedi_pci_enable(pcidev, dev->driver->driver_name)) {
- dev_err(dev->class_dev,
- "Error: Can't enable PCI device and request regions!\n");
- return -EIO;
- }
-
- dev->iobase = pci_resource_start(pcidev, this_board->main_pci_region);
+ this_board = pci_dio_find_boardinfo(dev, pcidev);
+ if (!this_board)
+ return -ENODEV;
+ dev->board_ptr = this_board;
dev->board_name = this_board->name;
- if (this_board->cardtype == TYPE_PCI1760) {
- n_subdevices = 4; /* 8 IDI, 8 IDO, 2 PWM, 8 CNT */
- } else {
- n_subdevices = 0;
- for (i = 0; i < MAX_DI_SUBDEVS; i++)
- if (this_board->sdi[i].chans)
- n_subdevices++;
- for (i = 0; i < MAX_DO_SUBDEVS; i++)
- if (this_board->sdo[i].chans)
- n_subdevices++;
- for (i = 0; i < MAX_DIO_SUBDEVG; i++)
- n_subdevices += this_board->sdio[i].regs;
- if (this_board->boardid.chans)
- n_subdevices++;
- for (i = 0; i < MAX_8254_SUBDEVS; i++)
- if (this_board->s8254[i].chans)
- n_subdevices++;
- }
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret < 0)
+ return ret;
+ devpriv = dev->private;
- ret = comedi_alloc_subdevices(dev, n_subdevices);
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
+ dev->iobase = pci_resource_start(pcidev, this_board->main_pci_region);
+
+ ret = comedi_alloc_subdevices(dev, this_board->nsubdevs);
if (ret)
return ret;
subdev = 0;
for (i = 0; i < MAX_DI_SUBDEVS; i++)
if (this_board->sdi[i].chans) {
- s = dev->subdevices + subdev;
- pci_dio_add_di(dev, s, &this_board->sdi[i], subdev);
+ s = &dev->subdevices[subdev];
+ pci_dio_add_di(dev, s, &this_board->sdi[i]);
subdev++;
}
for (i = 0; i < MAX_DO_SUBDEVS; i++)
if (this_board->sdo[i].chans) {
- s = dev->subdevices + subdev;
- pci_dio_add_do(dev, s, &this_board->sdo[i], subdev);
+ s = &dev->subdevices[subdev];
+ pci_dio_add_do(dev, s, &this_board->sdo[i]);
subdev++;
}
for (i = 0; i < MAX_DIO_SUBDEVG; i++)
for (j = 0; j < this_board->sdio[i].regs; j++) {
- s = dev->subdevices + subdev;
+ s = &dev->subdevices[subdev];
subdev_8255_init(dev, s, NULL,
dev->iobase +
this_board->sdio[i].addr +
@@ -1153,21 +1148,21 @@ static int pci_dio_attach(struct comedi_device *dev,
}
if (this_board->boardid.chans) {
- s = dev->subdevices + subdev;
+ s = &dev->subdevices[subdev];
s->type = COMEDI_SUBD_DI;
- pci_dio_add_di(dev, s, &this_board->boardid, subdev);
+ pci_dio_add_di(dev, s, &this_board->boardid);
subdev++;
}
for (i = 0; i < MAX_8254_SUBDEVS; i++)
if (this_board->s8254[i].chans) {
- s = dev->subdevices + subdev;
- pci_dio_add_8254(dev, s, &this_board->s8254[i], subdev);
+ s = &dev->subdevices[subdev];
+ pci_dio_add_8254(dev, s, &this_board->s8254[i]);
subdev++;
}
if (this_board->cardtype == TYPE_PCI1760)
- pci1760_attach(dev, it);
+ pci1760_attach(dev);
devpriv->valid = 1;
@@ -1178,52 +1173,34 @@ static int pci_dio_attach(struct comedi_device *dev,
static void pci_dio_detach(struct comedi_device *dev)
{
+ struct pci_dio_private *devpriv = dev->private;
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- int i, j;
struct comedi_subdevice *s;
- int subdev;
+ int i;
- if (dev->private) {
+ if (devpriv) {
if (devpriv->valid)
pci_dio_reset(dev);
- subdev = 0;
- for (i = 0; i < MAX_DI_SUBDEVS; i++) {
- if (this_board->sdi[i].chans)
- subdev++;
- }
- for (i = 0; i < MAX_DO_SUBDEVS; i++) {
- if (this_board->sdo[i].chans)
- subdev++;
- }
- for (i = 0; i < MAX_DIO_SUBDEVG; i++) {
- for (j = 0; j < this_board->sdio[i].regs; j++) {
- s = dev->subdevices + subdev;
- subdev_8255_cleanup(dev, s);
- subdev++;
- }
- }
- if (this_board->boardid.chans)
- subdev++;
- for (i = 0; i < MAX_8254_SUBDEVS; i++)
- if (this_board->s8254[i].chans)
- subdev++;
+ }
+ if (dev->subdevices) {
for (i = 0; i < dev->n_subdevices; i++) {
- s = dev->subdevices + i;
+ s = &dev->subdevices[i];
+ if (s->type == COMEDI_SUBD_DIO)
+ subdev_8255_cleanup(dev, s);
s->private = NULL;
}
}
if (pcidev) {
if (dev->iobase)
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
}
}
static struct comedi_driver adv_pci_dio_driver = {
.driver_name = "adv_pci_dio",
.module = THIS_MODULE,
- .attach = pci_dio_attach,
- .detach = pci_dio_detach
+ .attach_pci = pci_dio_attach_pci,
+ .detach = pci_dio_detach,
};
static int __devinit adv_pci_dio_pci_probe(struct pci_dev *dev,
diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c
index f7d453f8fe33..8acf60d0f20d 100644
--- a/drivers/staging/comedi/drivers/aio_aio12_8.c
+++ b/drivers/staging/comedi/drivers/aio_aio12_8.c
@@ -25,8 +25,9 @@
Driver: aio_aio12_8
Description: Access I/O Products PC-104 AIO12-8 Analog I/O Board
Author: Pablo Mejia <pablo.mejia@cctechnol.com>
-Devices:
- [Access I/O] PC-104 AIO12-8
+Devices: [Access I/O] PC-104 AIO12-8 (aio_aio12_8)
+ [Access I/O] PC-104 AI12-8 (aio_ai12_8)
+ [Access I/O] PC-104 AO12-8 (aio_ao12_8)
Status: experimental
Configuration Options:
@@ -42,91 +43,118 @@ Notes:
#include <linux/ioport.h>
#include "8255.h"
-#define AIO12_8_STATUS 0x00
-#define AIO12_8_INTERRUPT 0x01
-#define AIO12_8_ADC 0x02
-#define AIO12_8_DAC_0 0x04
-#define AIO12_8_DAC_1 0x06
-#define AIO12_8_DAC_2 0x08
-#define AIO12_8_DAC_3 0x0A
-#define AIO12_8_COUNTER_0 0x0C
-#define AIO12_8_COUNTER_1 0x0D
-#define AIO12_8_COUNTER_2 0x0E
-#define AIO12_8_COUNTER_CONTROL 0x0F
-#define AIO12_8_DIO_0 0x10
-#define AIO12_8_DIO_1 0x11
-#define AIO12_8_DIO_2 0x12
-#define AIO12_8_DIO_STATUS 0x13
-#define AIO12_8_DIO_CONTROL 0x14
-#define AIO12_8_ADC_TRIGGER_CONTROL 0x15
-#define AIO12_8_TRIGGER 0x16
-#define AIO12_8_POWER 0x17
-
-#define STATUS_ADC_EOC 0x80
-
-#define ADC_MODE_NORMAL 0x00
-#define ADC_MODE_INTERNAL_CLOCK 0x40
-#define ADC_MODE_STANDBY 0x80
-#define ADC_MODE_POWERDOWN 0xC0
-
-#define DAC_ENABLE 0x18
+/*
+ * Register map
+ */
+#define AIO12_8_STATUS_REG 0x00
+#define AIO12_8_STATUS_ADC_EOC (1 << 7)
+#define AIO12_8_STATUS_PORT_C_COS (1 << 6)
+#define AIO12_8_STATUS_IRQ_ENA (1 << 2)
+#define AIO12_8_INTERRUPT_REG 0x01
+#define AIO12_8_INTERRUPT_ADC (1 << 7)
+#define AIO12_8_INTERRUPT_COS (1 << 6)
+#define AIO12_8_INTERRUPT_COUNTER1 (1 << 5)
+#define AIO12_8_INTERRUPT_PORT_C3 (1 << 4)
+#define AIO12_8_INTERRUPT_PORT_C0 (1 << 3)
+#define AIO12_8_INTERRUPT_ENA (1 << 2)
+#define AIO12_8_ADC_REG 0x02
+#define AIO12_8_ADC_MODE_NORMAL (0 << 6)
+#define AIO12_8_ADC_MODE_INT_CLK (1 << 6)
+#define AIO12_8_ADC_MODE_STANDBY (2 << 6)
+#define AIO12_8_ADC_MODE_POWERDOWN (3 << 6)
+#define AIO12_8_ADC_ACQ_3USEC (0 << 5)
+#define AIO12_8_ADC_ACQ_PROGRAM (1 << 5)
+#define AIO12_8_ADC_RANGE(x) ((x) << 3)
+#define AIO12_8_ADC_CHAN(x) ((x) << 0)
+#define AIO12_8_DAC_REG(x) (0x04 + (x) * 2)
+#define AIO12_8_8254_BASE_REG 0x0c
+#define AIO12_8_8255_BASE_REG 0x10
+#define AIO12_8_DIO_CONTROL_REG 0x14
+#define AIO12_8_DIO_CONTROL_TST (1 << 0)
+#define AIO12_8_ADC_TRIGGER_REG 0x15
+#define AIO12_8_ADC_TRIGGER_RANGE(x) ((x) << 3)
+#define AIO12_8_ADC_TRIGGER_CHAN(x) ((x) << 0)
+#define AIO12_8_TRIGGER_REG 0x16
+#define AIO12_8_TRIGGER_ADTRIG (1 << 1)
+#define AIO12_8_TRIGGER_DACTRIG (1 << 0)
+#define AIO12_8_COS_REG 0x17
+#define AIO12_8_DAC_ENABLE_REG 0x18
+#define AIO12_8_DAC_ENABLE_REF_ENA (1 << 0)
struct aio12_8_boardtype {
const char *name;
+ int ai_nchan;
+ int ao_nchan;
};
static const struct aio12_8_boardtype board_types[] = {
{
- .name = "aio_aio12_8"},
+ .name = "aio_aio12_8",
+ .ai_nchan = 8,
+ .ao_nchan = 4,
+ }, {
+ .name = "aio_ai12_8",
+ .ai_nchan = 8,
+ }, {
+ .name = "aio_ao12_8",
+ .ao_nchan = 4,
+ },
};
struct aio12_8_private {
unsigned int ao_readback[4];
};
-#define devpriv ((struct aio12_8_private *) dev->private)
-
static int aio_aio12_8_ai_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int range = CR_RANGE(insn->chanspec);
+ unsigned int val;
+ unsigned char control;
int n;
- unsigned char control =
- ADC_MODE_NORMAL |
- (CR_RANGE(insn->chanspec) << 3) | CR_CHAN(insn->chanspec);
- /* read status to clear EOC latch */
- inb(dev->iobase + AIO12_8_STATUS);
+ /*
+ * Setup the control byte for internal 2MHz clock, 3uS conversion,
+ * at the desired range of the requested channel.
+ */
+ control = AIO12_8_ADC_MODE_NORMAL | AIO12_8_ADC_ACQ_3USEC |
+ AIO12_8_ADC_RANGE(range) | AIO12_8_ADC_CHAN(chan);
+
+ /* Read status to clear EOC latch */
+ inb(dev->iobase + AIO12_8_STATUS_REG);
for (n = 0; n < insn->n; n++) {
int timeout = 5;
/* Setup and start conversion */
- outb(control, dev->iobase + AIO12_8_ADC);
+ outb(control, dev->iobase + AIO12_8_ADC_REG);
/* Wait for conversion to complete */
- while (timeout &&
- !(inb(dev->iobase + AIO12_8_STATUS) & STATUS_ADC_EOC)) {
+ do {
+ val = inb(dev->iobase + AIO12_8_STATUS_REG);
timeout--;
- printk(KERN_ERR "timeout %d\n", timeout);
- udelay(1);
- }
- if (timeout == 0) {
- comedi_error(dev, "ADC timeout");
- return -EIO;
- }
-
- data[n] = inw(dev->iobase + AIO12_8_ADC) & 0x0FFF;
+ if (timeout == 0) {
+ dev_err(dev->class_dev, "ADC timeout\n");
+ return -ETIMEDOUT;
+ }
+ } while (!(val & AIO12_8_STATUS_ADC_EOC));
+
+ data[n] = inw(dev->iobase + AIO12_8_ADC_REG) & s->maxdata;
}
- return n;
+
+ return insn->n;
}
static int aio_aio12_8_ao_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct aio12_8_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ int val = devpriv->ao_readback[chan];
int i;
- int val = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
for (i = 0; i < insn->n; i++)
data[i] = val;
@@ -137,18 +165,22 @@ static int aio_aio12_8_ao_write(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct aio12_8_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned long port = dev->iobase + AIO12_8_DAC_REG(chan);
+ unsigned int val = 0;
int i;
- int chan = CR_CHAN(insn->chanspec);
- unsigned long port = dev->iobase + AIO12_8_DAC_0 + (2 * chan);
/* enable DACs */
- outb(0x01, dev->iobase + DAC_ENABLE);
+ outb(AIO12_8_DAC_ENABLE_REF_ENA, dev->iobase + AIO12_8_DAC_ENABLE_REG);
for (i = 0; i < insn->n; i++) {
- outb(data[i] & 0xFF, port); /* LSB */
- outb((data[i] >> 8) & 0x0F, port + 1); /* MSB */
- devpriv->ao_readback[chan] = data[i];
+ val = data[i];
+ outw(val, port);
}
+
+ devpriv->ao_readback[chan] = val;
+
return insn->n;
}
@@ -166,53 +198,77 @@ static int aio_aio12_8_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
const struct aio12_8_boardtype *board = comedi_board(dev);
- int iobase;
+ struct aio12_8_private *devpriv;
struct comedi_subdevice *s;
+ int iobase;
int ret;
+ dev->board_name = board->name;
+
iobase = it->options[0];
- if (!request_region(iobase, 24, "aio_aio12_8")) {
+ if (!request_region(iobase, 32, dev->board_name)) {
printk(KERN_ERR "I/O port conflict");
return -EIO;
}
-
- dev->board_name = board->name;
-
dev->iobase = iobase;
- if (alloc_private(dev, sizeof(struct aio12_8_private)) < 0)
- return -ENOMEM;
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret)
+ return ret;
+ devpriv = dev->private;
- ret = comedi_alloc_subdevices(dev, 3);
+ ret = comedi_alloc_subdevices(dev, 4);
if (ret)
return ret;
s = &dev->subdevices[0];
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
- s->n_chan = 8;
- s->maxdata = (1 << 12) - 1;
- s->range_table = &range_aio_aio12_8;
- s->insn_read = aio_aio12_8_ai_read;
+ if (board->ai_nchan) {
+ /* Analog input subdevice */
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
+ s->n_chan = board->ai_nchan;
+ s->maxdata = 0x0fff;
+ s->range_table = &range_aio_aio12_8;
+ s->insn_read = aio_aio12_8_ai_read;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
s = &dev->subdevices[1];
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_DIFF;
- s->n_chan = 4;
- s->maxdata = (1 << 12) - 1;
- s->range_table = &range_aio_aio12_8;
- s->insn_read = aio_aio12_8_ao_read;
- s->insn_write = aio_aio12_8_ao_write;
+ if (board->ao_nchan) {
+ /* Analog output subdevice */
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_DIFF;
+ s->n_chan = 4;
+ s->maxdata = 0x0fff;
+ s->range_table = &range_aio_aio12_8;
+ s->insn_read = aio_aio12_8_ao_read;
+ s->insn_write = aio_aio12_8_ao_write;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
s = &dev->subdevices[2];
- subdev_8255_init(dev, s, NULL, dev->iobase + AIO12_8_DIO_0);
+ /* 8255 Digital i/o subdevice */
+ iobase = dev->iobase + AIO12_8_8255_BASE_REG;
+ ret = subdev_8255_init(dev, s, NULL, iobase);
+ if (ret)
+ return ret;
+
+ s = &dev->subdevices[3];
+ /* 8254 counter/timer subdevice */
+ s->type = COMEDI_SUBD_UNUSED;
+
+ dev_info(dev->class_dev, "%s: %s attached\n",
+ dev->driver->driver_name, dev->board_name);
return 0;
}
static void aio_aio12_8_detach(struct comedi_device *dev)
{
- subdev_8255_cleanup(dev, &dev->subdevices[2]);
+ if (dev->subdevices)
+ subdev_8255_cleanup(dev, &dev->subdevices[2]);
if (dev->iobase)
release_region(dev->iobase, 24);
}
diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
index ba1e3bbf2df8..b2cb8b02b2a1 100644
--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
+++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
@@ -112,7 +112,7 @@ static int aio_iiro_16_attach(struct comedi_device *dev,
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_WRITABLE;
s->n_chan = 16;
@@ -120,7 +120,7 @@ static int aio_iiro_16_attach(struct comedi_device *dev,
s->range_table = &range_digital;
s->insn_bits = aio_iiro_16_dio_insn_bits_write;
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE;
s->n_chan = 16;
diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
index 6c81e377262c..08f305210a69 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200.c
@@ -210,11 +210,15 @@ order they appear in the channel list.
#include "../comedidev.h"
+#include "comedi_fc.h"
#include "8255.h"
#include "8253.h"
#define DIO200_DRIVER_NAME "amplc_dio200"
+#define DO_ISA IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
+#define DO_PCI IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI)
+
/* PCI IDs */
#define PCI_VENDOR_ID_AMPLICON 0x14dc
#define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
@@ -272,12 +276,12 @@ enum dio200_model {
};
enum dio200_layout {
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
+#if DO_ISA
pc212_layout,
pc214_layout,
#endif
pc215_layout,
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
+#if DO_ISA
pc218_layout,
#endif
pc272_layout
@@ -292,7 +296,7 @@ struct dio200_board {
};
static const struct dio200_board dio200_boards[] = {
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
+#if DO_ISA
{
.name = "pc212e",
.bustype = isa_bustype,
@@ -324,7 +328,7 @@ static const struct dio200_board dio200_boards[] = {
.layout = pc272_layout,
},
#endif
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI)
+#if DO_PCI
{
.name = "pci215",
.devid = PCI_DEVICE_ID_AMPLICON_PCI215,
@@ -367,7 +371,7 @@ struct dio200_layout_struct {
};
static const struct dio200_layout_struct dio200_layouts[] = {
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
+#if DO_ISA
[pc212_layout] = {
.n_subdevs = 6,
.sdtype = {sd_8255, sd_8254, sd_8254, sd_8254,
@@ -396,7 +400,7 @@ static const struct dio200_layout_struct dio200_layouts[] = {
.has_int_sce = 1,
.has_clk_gat_sce = 1,
},
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
+#if DO_ISA
[pc218_layout] = {
.n_subdevs = 7,
.sdtype = {sd_8254, sd_8254, sd_8255, sd_8254,
@@ -449,6 +453,16 @@ struct dio200_subdev_intr {
int continuous;
};
+static inline bool is_pci_board(const struct dio200_board *board)
+{
+ return DO_PCI && board->bustype == pci_bustype;
+}
+
+static inline bool is_isa_board(const struct dio200_board *board)
+{
+ return DO_ISA && board->bustype == isa_bustype;
+}
+
/*
* This function looks for a board matching the supplied PCI device.
*/
@@ -458,7 +472,7 @@ dio200_find_pci_board(struct pci_dev *pci_dev)
unsigned int i;
for (i = 0; i < ARRAY_SIZE(dio200_boards); i++)
- if (dio200_boards[i].bustype == pci_bustype &&
+ if (is_pci_board(&dio200_boards[i]) &&
pci_dev->device == dio200_boards[i].devid)
return &dio200_boards[i];
return NULL;
@@ -758,52 +772,24 @@ dio200_subdev_intr_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_cmd *cmd)
{
int err = 0;
- unsigned int tmp;
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= (TRIG_NOW | TRIG_INT);
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_NOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= (TRIG_COUNT | TRIG_NONE);
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
+ 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 2: make sure trigger sources are unique and mutually
- compatible */
+ /* Step 2a : make sure trigger sources are unique */
- /* these tests are true if more than one _src bit is set */
- if ((cmd->start_src & (cmd->start_src - 1)) != 0)
- err++;
- if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
- err++;
- if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
- err++;
- if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
- err++;
- if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -965,15 +951,15 @@ static irqreturn_t dio200_interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
struct dio200_private *devpriv = dev->private;
+ struct comedi_subdevice *s;
int handled;
if (!dev->attached)
return IRQ_NONE;
if (devpriv->intr_sd >= 0) {
- handled = dio200_handle_read_intr(dev,
- dev->subdevices +
- devpriv->intr_sd);
+ s = &dev->subdevices[devpriv->intr_sd];
+ handled = dio200_handle_read_intr(dev, s);
} else {
handled = 0;
}
@@ -1228,12 +1214,10 @@ static void dio200_report_attach(struct comedi_device *dev, unsigned int irq)
char tmpbuf[60];
int tmplen;
- if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) &&
- thisboard->bustype == isa_bustype)
+ if (is_isa_board(thisboard))
tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
"(base %#lx) ", dev->iobase);
- else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) &&
- thisboard->bustype == pci_bustype)
+ else if (is_pci_board(thisboard))
tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
"(pci %s) ", pci_name(pcidev));
else
@@ -1361,8 +1345,7 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
/* Process options and reserve resources according to bus type. */
- if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) &&
- thisboard->bustype == isa_bustype) {
+ if (is_isa_board(thisboard)) {
unsigned long iobase;
unsigned int irq;
@@ -1372,8 +1355,7 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret < 0)
return ret;
return dio200_common_attach(dev, iobase, irq, 0);
- } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) &&
- thisboard->bustype == pci_bustype) {
+ } else if (is_pci_board(thisboard)) {
struct pci_dev *pci_dev;
pci_dev = dio200_find_pci_dev(dev, it);
@@ -1397,7 +1379,7 @@ static int __devinit dio200_attach_pci(struct comedi_device *dev,
{
int ret;
- if (!IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI))
+ if (!DO_PCI)
return -EINVAL;
dev_info(dev->class_dev, DIO200_DRIVER_NAME ": attach pci %s\n",
@@ -1412,13 +1394,19 @@ static int __devinit dio200_attach_pci(struct comedi_device *dev,
dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
return -EINVAL;
}
+ /*
+ * Need to 'get' the PCI device to match the 'put' in dio200_detach().
+ * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
+ * support for manual attachment of PCI devices via dio200_attach()
+ * has been removed.
+ */
+ pci_dev_get(pci_dev);
return dio200_pci_common_attach(dev, pci_dev);
}
static void dio200_detach(struct comedi_device *dev)
{
const struct dio200_board *thisboard = comedi_board(dev);
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
const struct dio200_layout_struct *layout;
unsigned n;
@@ -1443,13 +1431,16 @@ static void dio200_detach(struct comedi_device *dev)
}
}
}
- if (pcidev) {
- if (dev->iobase)
- comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
- } else {
+ if (is_isa_board(thisboard)) {
if (dev->iobase)
release_region(dev->iobase, DIO200_IO_SIZE);
+ } else if (is_pci_board(thisboard)) {
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ if (pcidev) {
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
+ pci_dev_put(pcidev);
+ }
}
}
@@ -1470,7 +1461,7 @@ static struct comedi_driver amplc_dio200_driver = {
.num_names = ARRAY_SIZE(dio200_boards),
};
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI)
+#if DO_PCI
static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272) },
diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
index aabba9886b7d..eacb5e4735d7 100644
--- a/drivers/staging/comedi/drivers/amplc_pc236.c
+++ b/drivers/staging/comedi/drivers/amplc_pc236.c
@@ -56,11 +56,15 @@ unused.
#include "../comedidev.h"
+#include "comedi_fc.h"
#include "8255.h"
#include "plx9052.h"
#define PC236_DRIVER_NAME "amplc_pc236"
+#define DO_ISA IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA)
+#define DO_PCI IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI)
+
/* PCI236 PCI configuration register information */
#define PCI_VENDOR_ID_AMPLICON 0x14dc
#define PCI_DEVICE_ID_AMPLICON_PCI236 0x0009
@@ -103,14 +107,14 @@ struct pc236_board {
enum pc236_model model;
};
static const struct pc236_board pc236_boards[] = {
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA)
+#if DO_ISA
{
.name = "pc36at",
.bustype = isa_bustype,
.model = pc36at_model,
},
#endif
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI)
+#if DO_PCI
{
.name = "pci236",
.devid = PCI_DEVICE_ID_AMPLICON_PCI236,
@@ -135,6 +139,18 @@ struct pc236_private {
int enable_irq;
};
+/* test if ISA supported and this is an ISA board */
+static inline bool is_isa_board(const struct pc236_board *board)
+{
+ return DO_ISA && board->bustype == isa_bustype;
+}
+
+/* test if PCI supported and this is a PCI board */
+static inline bool is_pci_board(const struct pc236_board *board)
+{
+ return DO_PCI && board->bustype == pci_bustype;
+}
+
/*
* This function looks for a board matching the supplied PCI device.
*/
@@ -143,7 +159,7 @@ static const struct pc236_board *pc236_find_pci_board(struct pci_dev *pci_dev)
unsigned int i;
for (i = 0; i < ARRAY_SIZE(pc236_boards); i++)
- if (pc236_boards[i].bustype == pci_bustype &&
+ if (is_pci_board(&pc236_boards[i]) &&
pci_dev->device == pc236_boards[i].devid)
return &pc236_boards[i];
return NULL;
@@ -214,12 +230,13 @@ static int pc236_request_region(struct comedi_device *dev, unsigned long from,
*/
static void pc236_intr_disable(struct comedi_device *dev)
{
+ const struct pc236_board *thisboard = comedi_board(dev);
struct pc236_private *devpriv = dev->private;
unsigned long flags;
spin_lock_irqsave(&dev->spinlock, flags);
devpriv->enable_irq = 0;
- if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) && devpriv->lcr_iobase)
+ if (is_pci_board(thisboard))
outl(PCI236_INTR_DISABLE, devpriv->lcr_iobase + PLX9052_INTCSR);
spin_unlock_irqrestore(&dev->spinlock, flags);
}
@@ -231,12 +248,13 @@ static void pc236_intr_disable(struct comedi_device *dev)
*/
static void pc236_intr_enable(struct comedi_device *dev)
{
+ const struct pc236_board *thisboard = comedi_board(dev);
struct pc236_private *devpriv = dev->private;
unsigned long flags;
spin_lock_irqsave(&dev->spinlock, flags);
devpriv->enable_irq = 1;
- if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) && devpriv->lcr_iobase)
+ if (is_pci_board(thisboard))
outl(PCI236_INTR_ENABLE, devpriv->lcr_iobase + PLX9052_INTCSR);
spin_unlock_irqrestore(&dev->spinlock, flags);
}
@@ -250,6 +268,7 @@ static void pc236_intr_enable(struct comedi_device *dev)
*/
static int pc236_intr_check(struct comedi_device *dev)
{
+ const struct pc236_board *thisboard = comedi_board(dev);
struct pc236_private *devpriv = dev->private;
int retval = 0;
unsigned long flags;
@@ -257,8 +276,7 @@ static int pc236_intr_check(struct comedi_device *dev)
spin_lock_irqsave(&dev->spinlock, flags);
if (devpriv->enable_irq) {
retval = 1;
- if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) &&
- devpriv->lcr_iobase) {
+ if (is_pci_board(thisboard)) {
if ((inl(devpriv->lcr_iobase + PLX9052_INTCSR)
& PLX9052_INTCSR_LI1STAT_MASK)
== PLX9052_INTCSR_LI1STAT_INACTIVE) {
@@ -296,39 +314,20 @@ static int pc236_intr_cmdtest(struct comedi_device *dev,
struct comedi_cmd *cmd)
{
int err = 0;
- int tmp;
- /* step 1 */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_FOLLOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
if (err)
return 1;
- /* step 2: ignored */
+ /* Step 2a : make sure trigger sources are unique */
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -395,7 +394,7 @@ static int pc236_intr_cancel(struct comedi_device *dev,
static irqreturn_t pc236_interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
- struct comedi_subdevice *s = dev->subdevices + 1;
+ struct comedi_subdevice *s = &dev->subdevices[1];
int handled;
handled = pc236_intr_check(dev);
@@ -414,15 +413,13 @@ static void pc236_report_attach(struct comedi_device *dev, unsigned int irq)
char tmpbuf[60];
int tmplen;
- if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) &&
- thisboard->bustype == isa_bustype)
+ if (is_isa_board(thisboard))
tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
"(base %#lx) ", dev->iobase);
- else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) &&
- thisboard->bustype == pci_bustype) {
+ else if (is_pci_board(thisboard))
tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
"(pci %s) ", pci_name(pcidev));
- } else
+ else
tmplen = 0;
if (irq)
tmplen += scnprintf(&tmpbuf[tmplen], sizeof(tmpbuf) - tmplen,
@@ -449,14 +446,14 @@ static int pc236_common_attach(struct comedi_device *dev, unsigned long iobase,
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* digital i/o subdevice (8255) */
ret = subdev_8255_init(dev, s, NULL, iobase);
if (ret < 0) {
dev_err(dev->class_dev, "error! out of memory!\n");
return ret;
}
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
dev->read_subdev = s;
s->type = COMEDI_SUBD_UNUSED;
pc236_intr_disable(dev);
@@ -517,16 +514,14 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return ret;
}
/* Process options according to bus type. */
- if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) &&
- thisboard->bustype == isa_bustype) {
+ if (is_isa_board(thisboard)) {
unsigned long iobase = it->options[0];
unsigned int irq = it->options[1];
ret = pc236_request_region(dev, iobase, PC236_IO_SIZE);
if (ret < 0)
return ret;
return pc236_common_attach(dev, iobase, irq, 0);
- } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) &&
- thisboard->bustype == pci_bustype) {
+ } else if (is_pci_board(thisboard)) {
struct pci_dev *pci_dev;
pci_dev = pc236_find_pci_dev(dev, it);
@@ -550,7 +545,7 @@ static int __devinit pc236_attach_pci(struct comedi_device *dev,
{
int ret;
- if (!IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI))
+ if (!DO_PCI)
return -EINVAL;
dev_info(dev->class_dev, PC236_DRIVER_NAME ": attach pci %s\n",
@@ -565,27 +560,37 @@ static int __devinit pc236_attach_pci(struct comedi_device *dev,
dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
return -EINVAL;
}
+ /*
+ * Need to 'get' the PCI device to match the 'put' in pc236_detach().
+ * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
+ * support for manual attachment of PCI devices via pc236_attach()
+ * has been removed.
+ */
+ pci_dev_get(pci_dev);
return pc236_pci_common_attach(dev, pci_dev);
}
static void pc236_detach(struct comedi_device *dev)
{
+ const struct pc236_board *thisboard = comedi_board(dev);
struct pc236_private *devpriv = dev->private;
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
if (devpriv)
pc236_intr_disable(dev);
if (dev->irq)
free_irq(dev->irq, dev);
if (dev->subdevices)
- subdev_8255_cleanup(dev, dev->subdevices + 0);
- if (pcidev) {
- if (dev->iobase)
- comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
- } else {
+ subdev_8255_cleanup(dev, &dev->subdevices[0]);
+ if (is_isa_board(thisboard)) {
if (dev->iobase)
release_region(dev->iobase, PC236_IO_SIZE);
+ } else if (is_pci_board(thisboard)) {
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ if (pcidev) {
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
+ pci_dev_put(pcidev);
+ }
}
}
@@ -606,7 +611,7 @@ static struct comedi_driver amplc_pc236_driver = {
.num_names = ARRAY_SIZE(pc236_boards),
};
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI)
+#if DO_PCI
static DEFINE_PCI_DEVICE_TABLE(pc236_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI236) },
{0}
diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
index 40ec1ffebba6..60830ccfb903 100644
--- a/drivers/staging/comedi/drivers/amplc_pc263.c
+++ b/drivers/staging/comedi/drivers/amplc_pc263.c
@@ -48,6 +48,9 @@ The state of the outputs can be read.
#define PC263_DRIVER_NAME "amplc_pc263"
+#define DO_ISA IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA)
+#define DO_PCI IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI)
+
/* PCI263 PCI configuration register information */
#define PCI_VENDOR_ID_AMPLICON 0x14dc
#define PCI_DEVICE_ID_AMPLICON_PCI263 0x000c
@@ -70,14 +73,14 @@ struct pc263_board {
enum pc263_model model;
};
static const struct pc263_board pc263_boards[] = {
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA)
+#if DO_ISA
{
.name = "pc263",
.bustype = isa_bustype,
.model = pc263_model,
},
#endif
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI)
+#if DO_PCI
{
.name = "pci263",
.devid = PCI_DEVICE_ID_AMPLICON_PCI263,
@@ -93,6 +96,18 @@ static const struct pc263_board pc263_boards[] = {
#endif
};
+/* test if ISA supported and this is an ISA board */
+static inline bool is_isa_board(const struct pc263_board *board)
+{
+ return DO_ISA && board->bustype == isa_bustype;
+}
+
+/* test if PCI supported and this is a PCI board */
+static inline bool is_pci_board(const struct pc263_board *board)
+{
+ return DO_PCI && board->bustype == pci_bustype;
+}
+
/*
* This function looks for a board matching the supplied PCI device.
*/
@@ -101,7 +116,7 @@ static const struct pc263_board *pc263_find_pci_board(struct pci_dev *pci_dev)
unsigned int i;
for (i = 0; i < ARRAY_SIZE(pc263_boards); i++)
- if (pc263_boards[i].bustype == pci_bustype &&
+ if (is_pci_board(&pc263_boards[i]) &&
pci_dev->device == pc263_boards[i].devid)
return &pc263_boards[i];
return NULL;
@@ -187,11 +202,9 @@ static void pc263_report_attach(struct comedi_device *dev)
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
char tmpbuf[40];
- if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA) &&
- thisboard->bustype == isa_bustype)
+ if (is_isa_board(thisboard))
snprintf(tmpbuf, sizeof(tmpbuf), "(base %#lx) ", dev->iobase);
- else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) &&
- thisboard->bustype == pci_bustype)
+ else if (is_pci_board(thisboard))
snprintf(tmpbuf, sizeof(tmpbuf), "(pci %s) ",
pci_name(pcidev));
else
@@ -212,7 +225,7 @@ static int pc263_common_attach(struct comedi_device *dev, unsigned long iobase)
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* digital output subdevice */
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
@@ -259,15 +272,13 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
dev_info(dev->class_dev, PC263_DRIVER_NAME ": attach\n");
/* Process options and reserve resources according to bus type. */
- if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA) &&
- thisboard->bustype == isa_bustype) {
+ if (is_isa_board(thisboard)) {
unsigned long iobase = it->options[0];
ret = pc263_request_region(dev, iobase, PC263_IO_SIZE);
if (ret < 0)
return ret;
return pc263_common_attach(dev, iobase);
- } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) &&
- thisboard->bustype == pci_bustype) {
+ } else if (is_pci_board(thisboard)) {
struct pci_dev *pci_dev;
pci_dev = pc263_find_pci_dev(dev, it);
@@ -288,7 +299,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
static int __devinit pc263_attach_pci(struct comedi_device *dev,
struct pci_dev *pci_dev)
{
- if (!IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI))
+ if (!DO_PCI)
return -EINVAL;
dev_info(dev->class_dev, PC263_DRIVER_NAME ": attach pci %s\n",
@@ -298,20 +309,30 @@ static int __devinit pc263_attach_pci(struct comedi_device *dev,
dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
return -EINVAL;
}
+ /*
+ * Need to 'get' the PCI device to match the 'put' in pc263_detach().
+ * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
+ * support for manual attachment of PCI devices via pc263_attach()
+ * has been removed.
+ */
+ pci_dev_get(pci_dev);
return pc263_pci_common_attach(dev, pci_dev);
}
static void pc263_detach(struct comedi_device *dev)
{
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ const struct pc263_board *thisboard = comedi_board(dev);
- if (pcidev) {
- if (dev->iobase)
- comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
- } else {
+ if (is_isa_board(thisboard)) {
if (dev->iobase)
release_region(dev->iobase, PC263_IO_SIZE);
+ } else if (is_pci_board(thisboard)) {
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ if (pcidev) {
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
+ pci_dev_put(pcidev);
+ }
}
}
@@ -332,7 +353,7 @@ static struct comedi_driver amplc_pc263_driver = {
.num_names = ARRAY_SIZE(pc263_boards),
};
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI)
+#if DO_PCI
static DEFINE_PCI_DEVICE_TABLE(pc263_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI263) },
{0}
diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
index 4e17f13e57f6..1f65ec4d261e 100644
--- a/drivers/staging/comedi/drivers/amplc_pci224.c
+++ b/drivers/staging/comedi/drivers/amplc_pci224.c
@@ -720,53 +720,31 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
int err = 0;
unsigned int tmp;
- /* Step 1: make sure trigger sources are trivially valid. */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_INT | TRIG_EXT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_EXT | TRIG_TIMER;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_NOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_EXT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_EXT | TRIG_TIMER);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ err |= cfc_check_trigger_src(&cmd->stop_src,
+ TRIG_COUNT | TRIG_EXT | TRIG_NONE);
if (err)
return 1;
- /* Step 2: make sure trigger sources are unique and mutually
- * compatible. */
+ /* Step 2a : make sure trigger sources are unique */
- /* these tests are true if more than one _src bit is set */
- if ((cmd->start_src & (cmd->start_src - 1)) != 0)
- err++;
- if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
- err++;
- if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
- err++;
- if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
- err++;
- if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
- /* There's only one external trigger signal (which makes these
- * tests easier). Only one thing can use it. */
+ /*
+ * There's only one external trigger signal (which makes these
+ * tests easier). Only one thing can use it.
+ */
tmp = 0;
if (cmd->start_src & TRIG_EXT)
tmp++;
@@ -775,7 +753,7 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
if (cmd->stop_src & TRIG_EXT)
tmp++;
if (tmp > 1)
- err++;
+ err |= -EINVAL;
if (err)
return 2;
@@ -1375,7 +1353,7 @@ static int pci224_attach_common(struct comedi_device *dev,
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* Analog output subdevice. */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
@@ -1503,6 +1481,13 @@ pci224_attach_pci(struct comedi_device *dev, struct pci_dev *pci_dev)
DRIVER_NAME ": BUG! cannot determine board type!\n");
return -EINVAL;
}
+ /*
+ * Need to 'get' the PCI device to match the 'put' in pci224_detach().
+ * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
+ * support for manual attachment of PCI devices via pci224_attach()
+ * has been removed.
+ */
+ pci_dev_get(pci_dev);
return pci224_attach_common(dev, pci_dev, NULL);
}
@@ -1516,7 +1501,7 @@ static void pci224_detach(struct comedi_device *dev)
if (dev->subdevices) {
struct comedi_subdevice *s;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* AO subdevice */
kfree(s->range_table_list);
}
diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
index 1b67d0c61fa7..bd8fb876ce2e 100644
--- a/drivers/staging/comedi/drivers/amplc_pci230.c
+++ b/drivers/staging/comedi/drivers/amplc_pci230.c
@@ -193,6 +193,7 @@ for (or detection of) various hardware problems added by Ian Abbott.
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include "comedi_fc.h"
#include "8253.h"
#include "8255.h"
@@ -958,23 +959,11 @@ static int pci230_ao_cmdtest(struct comedi_device *dev,
int err = 0;
unsigned int tmp;
- /* cmdtest tests a particular command to see if it is valid.
- * Using the cmdtest ioctl, a user can create a valid cmd
- * and then have it executes by the cmd ioctl.
- *
- * cmdtest returns 1,2,3,4 or 0, depending on which tests
- * the command passes. */
+ /* Step 1 : check if triggers are trivially valid */
- /* Step 1: make sure trigger sources are trivially valid.
- * "invalid source" returned by comedilib to user mode process
- * if this fails. */
-
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_INT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT);
- tmp = cmd->scan_begin_src;
+ tmp = TRIG_TIMER | TRIG_INT;
if ((thisboard->min_hwver > 0) && (devpriv->hwver >= 2)) {
/*
* For PCI230+ hardware version 2 onwards, allow external
@@ -990,46 +979,23 @@ static int pci230_ao_cmdtest(struct comedi_device *dev,
* scan_begin_src==TRIG_EXT support to be a bonus rather than a
* guarantee!
*/
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_INT | TRIG_EXT;
- } else {
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_INT;
+ tmp |= TRIG_EXT;
}
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, tmp);
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_NOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
+ 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 2: make sure trigger sources are unique and mutually compatible
- * "source conflict" returned by comedilib to user mode process
- * if this fails. */
+ /* Step 2a : make sure trigger sources are unique */
- /* these tests are true if more than one _src bit is set */
- if ((cmd->start_src & (cmd->start_src - 1)) != 0)
- err++;
- if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
- err++;
- if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
- err++;
- if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
- err++;
- if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -1610,75 +1576,45 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
int err = 0;
unsigned int tmp;
- /* cmdtest tests a particular command to see if it is valid.
- * Using the cmdtest ioctl, a user can create a valid cmd
- * and then have it executes by the cmd ioctl.
- *
- * cmdtest returns 1,2,3,4,5 or 0, depending on which tests
- * the command passes. */
+ /* Step 1 : check if triggers are trivially valid */
- /* Step 1: make sure trigger sources are trivially valid.
- * "invalid source" returned by comedilib to user mode process
- * if this fails. */
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_INT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- /* Unfortunately, we cannot trigger a scan off an external source
- * on the PCI260 board, since it uses the PPIC0 (DIO) input, which
- * isn't present on the PCI260. For PCI260+ we can use the
- * EXTTRIG/EXTCONVCLK input on pin 17 instead. */
+ tmp = TRIG_FOLLOW | TRIG_TIMER | TRIG_INT;
if ((thisboard->have_dio) || (thisboard->min_hwver > 0)) {
- cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_INT
- | TRIG_EXT;
- } else {
- cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_INT;
+ /*
+ * Unfortunately, we cannot trigger a scan off an external
+ * source on the PCI260 board, since it uses the PPIC0 (DIO)
+ * input, which isn't present on the PCI260. For PCI260+
+ * we can use the EXTTRIG/EXTCONVCLK input on pin 17 instead.
+ */
+ tmp |= TRIG_EXT;
}
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER | TRIG_INT | TRIG_EXT;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, tmp);
+ err |= cfc_check_trigger_src(&cmd->convert_src,
+ TRIG_TIMER | TRIG_INT | TRIG_EXT);
+ 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 2: make sure trigger sources are unique and mutually compatible
- * "source conflict" returned by comedilib to user mode process
- * if this fails. */
+ /* Step 2a : make sure trigger sources are unique */
- /* these tests are true if more than one _src bit is set */
- if ((cmd->start_src & (cmd->start_src - 1)) != 0)
- err++;
- if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
- err++;
- if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
- err++;
- if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
- err++;
- if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
- /* If scan_begin_src is not TRIG_FOLLOW, then a monostable will be
- * set up to generate a fixed number of timed conversion pulses. */
+ /*
+ * If scan_begin_src is not TRIG_FOLLOW, then a monostable will be
+ * set up to generate a fixed number of timed conversion pulses.
+ */
if ((cmd->scan_begin_src != TRIG_FOLLOW)
&& (cmd->convert_src != TRIG_TIMER))
- err++;
+ err |= -EINVAL;
if (err)
return 2;
@@ -2838,7 +2774,7 @@ static int pci230_attach_common(struct comedi_device *dev,
if (rc)
return rc;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* analog input subdevice */
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;
@@ -2855,7 +2791,7 @@ static int pci230_attach_common(struct comedi_device *dev,
s->do_cmdtest = &pci230_ai_cmdtest;
s->cancel = pci230_ai_cancel;
}
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* analog output subdevice */
if (thisboard->ao_chans > 0) {
s->type = COMEDI_SUBD_AO;
@@ -2878,7 +2814,7 @@ static int pci230_attach_common(struct comedi_device *dev,
} else {
s->type = COMEDI_SUBD_UNUSED;
}
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
/* digital i/o subdevice */
if (thisboard->have_dio) {
rc = subdev_8255_init(dev, s, NULL,
@@ -2925,6 +2861,13 @@ static int __devinit pci230_attach_pci(struct comedi_device *dev,
"amplc_pci230: BUG! cannot determine board type!\n");
return -EINVAL;
}
+ /*
+ * Need to 'get' the PCI device to match the 'put' in pci230_detach().
+ * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
+ * support for manual attachment of PCI devices via pci230_attach()
+ * has been removed.
+ */
+ pci_dev_get(pci_dev);
return pci230_attach_common(dev, pci_dev);
}
@@ -2934,7 +2877,7 @@ static void pci230_detach(struct comedi_device *dev)
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
if (dev->subdevices && thisboard->have_dio)
- subdev_8255_cleanup(dev, dev->subdevices + 2);
+ subdev_8255_cleanup(dev, &dev->subdevices[2]);
if (dev->irq)
free_irq(dev->irq, dev);
if (pcidev) {
diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
index 41ed8576f301..070037c22db7 100644
--- a/drivers/staging/comedi/drivers/c6xdigio.c
+++ b/drivers/staging/comedi/drivers/c6xdigio.c
@@ -447,7 +447,7 @@ static int c6xdigio_attach(struct comedi_device *dev,
else if (irq == 0)
printk(KERN_DEBUG "comedi%d: no irq\n", dev->minor);
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* pwm output subdevice */
s->type = COMEDI_SUBD_AO; /* Not sure what to put here */
s->subdev_flags = SDF_WRITEABLE;
@@ -458,7 +458,7 @@ static int c6xdigio_attach(struct comedi_device *dev,
s->maxdata = 500;
s->range_table = &range_bipolar10; /* A suitable lie */
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* encoder (counter) subdevice */
s->type = COMEDI_SUBD_COUNTER;
s->subdev_flags = SDF_READABLE | SDF_LSAMPL;
@@ -468,7 +468,7 @@ static int c6xdigio_attach(struct comedi_device *dev,
s->maxdata = 0xffffff;
s->range_table = &range_unknown;
- /* s = dev->subdevices + 2; */
+ /* s = &dev->subdevices[2]; */
/* pwm output subdevice */
/* s->type = COMEDI_SUBD_COUNTER; // Not sure what to put here */
/* s->subdev_flags = SDF_WRITEABLE; */
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index 58d45299bf85..6d81d8b40ccc 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -46,6 +46,7 @@ Status: experimental
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
+#include "comedi_fc.h"
#include "8253.h"
#define DAS16CS_SIZE 18
@@ -169,47 +170,26 @@ static int das16cs_ai_cmdtest(struct comedi_device *dev,
int err = 0;
int tmp;
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_TIMER | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src,
+ TRIG_TIMER | TRIG_EXT);
+ 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 2: make sure trigger sources are unique and
- * mutually compatible */
+ /* Step 2a : make sure trigger sources are unique */
- /* note that mutual compatibility is not an issue here */
- if (cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_EXT)
- err++;
- if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
- err++;
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -478,7 +458,7 @@ static int das16cs_attach(struct comedi_device *dev,
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
dev->read_subdev = s;
/* analog input subdevice */
s->type = COMEDI_SUBD_AI;
@@ -491,7 +471,7 @@ static int das16cs_attach(struct comedi_device *dev,
s->do_cmd = das16cs_ai_cmd;
s->do_cmdtest = das16cs_ai_cmdtest;
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* analog output subdevice */
if (thisboard->n_ao_chans) {
s->type = COMEDI_SUBD_AO;
@@ -505,7 +485,7 @@ static int das16cs_attach(struct comedi_device *dev,
s->type = COMEDI_SUBD_UNUSED;
}
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
/* digital i/o subdevice */
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
index 2b6a637c3499..de21a261ff45 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas.c
@@ -45,11 +45,7 @@ Status:
The boards may be autocalibrated using the comedi_calibrate
utility.
-Configuration options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
- If bus/slot is not specified, the first supported
- PCI device found will be used.
+Configuration options: not applicable, uses PCI auto config
For commands, the scanned channels must be consecutive
(i.e. 4-5-6-7, 2-3-4,...), and must all have the same
@@ -807,58 +803,35 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
int tmp;
int i, gain, start_chan;
- /* step 1: trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_EXT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER | TRIG_NOW | TRIG_EXT;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src,
+ TRIG_TIMER | TRIG_NOW | TRIG_EXT);
+ 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 2: trigger sources are unique and mutually compatible */
+ /* Step 2a : make sure trigger sources are unique */
- if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
- err++;
- if (cmd->scan_begin_src != TRIG_FOLLOW &&
- cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_EXT)
- err++;
- if (cmd->convert_src != TRIG_TIMER &&
- cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW)
- err++;
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
- /* make sure trigger sources are compatible with each other */
if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
- err++;
+ err |= -EINVAL;
if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
- err++;
+ err |= -EINVAL;
if (cmd->start_src == TRIG_EXT &&
(cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT))
- err++;
+ err |= -EINVAL;
if (err)
return 2;
@@ -1083,43 +1056,24 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev,
int err = 0;
int tmp;
- /* step 1: trigger sources are trivially valid */
-
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_INT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_NOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_TIMER | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
+ 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 2: trigger sources are unique and mutually compatible */
+ /* Step 2a : make sure trigger sources are unique */
- if (cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_EXT)
- err++;
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -1501,69 +1455,45 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
return IRQ_HANDLED;
}
-static struct pci_dev *cb_pcidas_find_pci_device(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static const void *cb_pcidas_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
const struct cb_pcidas_board *thisboard;
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
int i;
- for_each_pci_dev(pcidev) {
- /* is it not a computer boards card? */
- if (pcidev->vendor != PCI_VENDOR_ID_CB)
- continue;
- /* loop through cards supported by this driver */
- for (i = 0; i < ARRAY_SIZE(cb_pcidas_boards); i++) {
- thisboard = &cb_pcidas_boards[i];
- if (thisboard->device_id != pcidev->device)
- continue;
- /* was a particular bus/slot requested? */
- if (bus || slot) {
- /* are we on the wrong bus/slot? */
- if (pcidev->bus->number != bus ||
- PCI_SLOT(pcidev->devfn) != slot) {
- continue;
- }
- }
- dev_dbg(dev->class_dev,
- "Found %s on bus %i, slot %i\n",
- thisboard->name,
- pcidev->bus->number, PCI_SLOT(pcidev->devfn));
- dev->board_ptr = thisboard;
- return pcidev;
- }
+ for (i = 0; i < ARRAY_SIZE(cb_pcidas_boards); i++) {
+ thisboard = &cb_pcidas_boards[i];
+ if (thisboard->device_id == pcidev->device)
+ return thisboard;
}
- dev_err(dev->class_dev, "No supported card found\n");
return NULL;
}
-static int cb_pcidas_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int cb_pcidas_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
const struct cb_pcidas_board *thisboard;
struct cb_pcidas_private *devpriv;
- struct pci_dev *pcidev;
struct comedi_subdevice *s;
int i;
int ret;
- if (alloc_private(dev, sizeof(struct cb_pcidas_private)) < 0)
- return -ENOMEM;
- devpriv = dev->private;
-
- pcidev = cb_pcidas_find_pci_device(dev, it);
- if (!pcidev)
- return -EIO;
comedi_set_hw_dev(dev, &pcidev->dev);
- thisboard = comedi_board(dev);
- if (comedi_pci_enable(pcidev, dev->driver->driver_name)) {
- dev_err(dev->class_dev,
- "Failed to enable PCI device and request regions\n");
- return -EIO;
- }
+ thisboard = cb_pcidas_find_boardinfo(dev, pcidev);
+ if (!thisboard)
+ return -ENODEV;
+ dev->board_ptr = thisboard;
+ dev->board_name = thisboard->name;
+
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret)
+ return ret;
+ devpriv = dev->private;
+
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
devpriv->s5933_config = pci_resource_start(pcidev, 0);
devpriv->control_status = pci_resource_start(pcidev, 1);
@@ -1584,13 +1514,11 @@ static int cb_pcidas_attach(struct comedi_device *dev,
}
dev->irq = pcidev->irq;
- dev->board_name = thisboard->name;
-
ret = comedi_alloc_subdevices(dev, 7);
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* analog input subdevice */
dev->read_subdev = s;
s->type = COMEDI_SUBD_AI;
@@ -1607,7 +1535,7 @@ static int cb_pcidas_attach(struct comedi_device *dev,
s->cancel = cb_pcidas_cancel;
/* analog output subdevice */
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
if (thisboard->ao_nchan) {
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
@@ -1634,14 +1562,14 @@ static int cb_pcidas_attach(struct comedi_device *dev,
}
/* 8255 */
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
ret = subdev_8255_init(dev, s, NULL,
devpriv->pacer_counter_dio + DIO_8255);
if (ret)
return ret;
/* serial EEPROM, */
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
s->type = COMEDI_SUBD_MEMORY;
s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
s->n_chan = 256;
@@ -1649,7 +1577,7 @@ static int cb_pcidas_attach(struct comedi_device *dev,
s->insn_read = eeprom_read_insn;
/* 8800 caldac */
- s = dev->subdevices + 4;
+ s = &dev->subdevices[4];
s->type = COMEDI_SUBD_CALIB;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
s->n_chan = NUM_CHANNELS_8800;
@@ -1660,7 +1588,7 @@ static int cb_pcidas_attach(struct comedi_device *dev,
caldac_8800_write(dev, i, s->maxdata / 2);
/* trim potentiometer */
- s = dev->subdevices + 5;
+ s = &dev->subdevices[5];
s->type = COMEDI_SUBD_CALIB;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
if (thisboard->trimpot == AD7376) {
@@ -1676,7 +1604,7 @@ static int cb_pcidas_attach(struct comedi_device *dev,
cb_pcidas_trimpot_write(dev, i, s->maxdata / 2);
/* dac08 caldac */
- s = dev->subdevices + 6;
+ s = &dev->subdevices[6];
if (thisboard->has_dac08) {
s->type = COMEDI_SUBD_CALIB;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
@@ -1698,7 +1626,10 @@ static int cb_pcidas_attach(struct comedi_device *dev,
outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
devpriv->s5933_config + AMCC_OP_REG_INTCSR);
- return 1;
+ dev_info(dev->class_dev, "%s: %s attached\n",
+ dev->driver->driver_name, dev->board_name);
+
+ return 0;
}
static void cb_pcidas_detach(struct comedi_device *dev)
@@ -1715,18 +1646,17 @@ static void cb_pcidas_detach(struct comedi_device *dev)
if (dev->irq)
free_irq(dev->irq, dev);
if (dev->subdevices)
- subdev_8255_cleanup(dev, dev->subdevices + 2);
+ subdev_8255_cleanup(dev, &dev->subdevices[2]);
if (pcidev) {
if (devpriv->s5933_config)
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
}
}
static struct comedi_driver cb_pcidas_driver = {
.driver_name = "cb_pcidas",
.module = THIS_MODULE,
- .attach = cb_pcidas_attach,
+ .attach_pci = cb_pcidas_attach_pci,
.detach = cb_pcidas_detach,
};
diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
index 65cbaabf6456..0472a9088abe 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
@@ -1348,7 +1348,7 @@ static int setup_subdevices(struct comedi_device *dev)
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* analog input subdevice */
dev->read_subdev = s;
s->type = COMEDI_SUBD_AI;
@@ -1379,7 +1379,7 @@ static int setup_subdevices(struct comedi_device *dev)
}
/* analog output subdevice */
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
if (board(dev)->ao_nchan) {
s->type = COMEDI_SUBD_AO;
s->subdev_flags =
@@ -1401,7 +1401,7 @@ static int setup_subdevices(struct comedi_device *dev)
}
/* digital input */
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
if (board(dev)->layout == LAYOUT_64XX) {
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
@@ -1414,7 +1414,7 @@ static int setup_subdevices(struct comedi_device *dev)
/* digital output */
if (board(dev)->layout == LAYOUT_64XX) {
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
s->n_chan = 4;
@@ -1425,7 +1425,7 @@ static int setup_subdevices(struct comedi_device *dev)
s->type = COMEDI_SUBD_UNUSED;
/* 8255 */
- s = dev->subdevices + 4;
+ s = &dev->subdevices[4];
if (board(dev)->has_8255) {
if (board(dev)->layout == LAYOUT_4020) {
dio_8255_iobase =
@@ -1442,7 +1442,7 @@ static int setup_subdevices(struct comedi_device *dev)
s->type = COMEDI_SUBD_UNUSED;
/* 8 channel dio for 60xx */
- s = dev->subdevices + 5;
+ s = &dev->subdevices[5];
if (board(dev)->layout == LAYOUT_60XX) {
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
@@ -1455,7 +1455,7 @@ static int setup_subdevices(struct comedi_device *dev)
s->type = COMEDI_SUBD_UNUSED;
/* caldac */
- s = dev->subdevices + 6;
+ s = &dev->subdevices[6];
s->type = COMEDI_SUBD_CALIB;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
s->n_chan = 8;
@@ -1469,7 +1469,7 @@ static int setup_subdevices(struct comedi_device *dev)
caldac_write(dev, i, s->maxdata / 2);
/* 2 channel ad8402 potentiometer */
- s = dev->subdevices + 7;
+ s = &dev->subdevices[7];
if (board(dev)->layout == LAYOUT_64XX) {
s->type = COMEDI_SUBD_CALIB;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
@@ -1483,7 +1483,7 @@ static int setup_subdevices(struct comedi_device *dev)
s->type = COMEDI_SUBD_UNUSED;
/* serial EEPROM, if present */
- s = dev->subdevices + 8;
+ s = &dev->subdevices[8];
if (readl(priv(dev)->plx9080_iobase + PLX_CONTROL_REG) & CTL_EECHK) {
s->type = COMEDI_SUBD_MEMORY;
s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
@@ -1494,7 +1494,7 @@ static int setup_subdevices(struct comedi_device *dev)
s->type = COMEDI_SUBD_UNUSED;
/* user counter subd XXX */
- s = dev->subdevices + 9;
+ s = &dev->subdevices[9];
s->type = COMEDI_SUBD_UNUSED;
return 0;
@@ -1847,7 +1847,7 @@ static void detach(struct comedi_device *dev)
}
}
if (dev->subdevices)
- subdev_8255_cleanup(dev, dev->subdevices + 4);
+ subdev_8255_cleanup(dev, &dev->subdevices[4]);
if (pcidev) {
if (dev->iobase)
comedi_pci_disable(pcidev);
@@ -2108,74 +2108,50 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{
int err = 0;
- int tmp;
unsigned int tmp_arg, tmp_arg2;
int i;
int aref;
unsigned int triggers;
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_EXT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
- tmp = cmd->scan_begin_src;
triggers = TRIG_TIMER;
if (board(dev)->layout == LAYOUT_4020)
triggers |= TRIG_OTHER;
else
triggers |= TRIG_FOLLOW;
- cmd->scan_begin_src &= triggers;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, triggers);
- tmp = cmd->convert_src;
triggers = TRIG_TIMER;
if (board(dev)->layout == LAYOUT_4020)
triggers |= TRIG_NOW;
else
triggers |= TRIG_EXT;
- cmd->convert_src &= triggers;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->convert_src, triggers);
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_EXT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ err |= cfc_check_trigger_src(&cmd->stop_src,
+ TRIG_COUNT | TRIG_EXT | TRIG_NONE);
if (err)
return 1;
- /* step 2: make sure trigger sources are unique and mutually compatible */
+ /* Step 2a : make sure trigger sources are unique */
- /* uniqueness check */
- if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
- err++;
- if (cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_OTHER &&
- cmd->scan_begin_src != TRIG_FOLLOW)
- err++;
- if (cmd->convert_src != TRIG_TIMER &&
- cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW)
- err++;
- if (cmd->stop_src != TRIG_COUNT &&
- cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
- /* compatibility check */
if (cmd->convert_src == TRIG_EXT && cmd->scan_begin_src == TRIG_TIMER)
- err++;
+ err |= -EINVAL;
if (cmd->stop_src != TRIG_COUNT &&
cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT)
- err++;
+ err |= -EINVAL;
if (err)
return 2;
@@ -3466,55 +3442,33 @@ static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{
int err = 0;
- int tmp;
unsigned int tmp_arg;
int i;
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_INT | TRIG_EXT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_NOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_TIMER | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
if (err)
return 1;
- /* step 2: make sure trigger sources are unique and mutually compatible */
+ /* Step 2a : make sure trigger sources are unique */
- /* uniqueness check */
- if (cmd->start_src != TRIG_INT && cmd->start_src != TRIG_EXT)
- err++;
- if (cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_EXT)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+
+ /* Step 2b : and mutually compatible */
- /* compatibility check */
if (cmd->convert_src == TRIG_EXT && cmd->scan_begin_src == TRIG_TIMER)
- err++;
+ err |= -EINVAL;
if (cmd->stop_src != TRIG_COUNT &&
cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT)
- err++;
+ err |= -EINVAL;
if (err)
return 2;
diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
index 12660a384e59..aef946df27e2 100644
--- a/drivers/staging/comedi/drivers/cb_pcidda.c
+++ b/drivers/staging/comedi/drivers/cb_pcidda.c
@@ -48,6 +48,7 @@ Please report success/failure with other different cards to
#include "../comedidev.h"
+#include "comedi_fc.h"
#include "8255.h"
/* PCI vendor number of ComputerBoards */
@@ -56,14 +57,6 @@ Please report success/failure with other different cards to
/* maximum number of ao channels for supported boards */
#define MAX_AO_CHANNELS 8
-/* PCI-DDA base addresses */
-#define DIGITALIO_BADRINDEX 2
- /* DIGITAL I/O is pci_dev->resource[2] */
-#define DIGITALIO_SIZE 8
- /* DIGITAL I/O uses 8 I/O port addresses */
-#define DAC_BADRINDEX 3
- /* DAC is pci_dev->resource[3] */
-
/* Digital I/O registers */
#define PORT1A 0 /* PORT 1A DATA */
@@ -203,11 +196,6 @@ static const struct cb_pcidda_board cb_pcidda_boards[] = {
};
/*
- * Useful for shorthand access to the particular board structure
- */
-#define thisboard ((const struct cb_pcidda_board *)dev->board_ptr)
-
-/*
* this structure is for data unique to this hardware driver. If
* several hardware drivers keep similar information in this structure,
* feel free to suggest moving the variable to the struct comedi_device
@@ -230,164 +218,6 @@ struct cb_pcidda_private {
};
/*
- * most drivers define the following macro to make it easy to
- * access the private structure.
- */
-#define devpriv ((struct cb_pcidda_private *)dev->private)
-
-/* static int cb_pcidda_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data); */
-static int cb_pcidda_ao_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-/* static int cb_pcidda_ai_cmd(struct comedi_device *dev, struct *comedi_subdevice *s);*/
-/* static int cb_pcidda_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd); */
-/* static int cb_pcidda_ns_to_timer(unsigned int *ns,int *round); */
-
-static unsigned int cb_pcidda_serial_in(struct comedi_device *dev);
-static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
- unsigned int num_bits);
-static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
- unsigned int address);
-static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
- unsigned int range);
-
-static struct pci_dev *cb_pcidda_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
- int i;
-
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (bus != pcidev->bus->number ||
- slot != PCI_SLOT(pcidev->devfn))
- continue;
- }
- if (pcidev->vendor != PCI_VENDOR_ID_CB)
- continue;
-
- for (i = 0; i < ARRAY_SIZE(cb_pcidda_boards); i++) {
- if (cb_pcidda_boards[i].device_id != pcidev->device)
- continue;
- dev->board_ptr = cb_pcidda_boards + i;
- return pcidev;
- }
- }
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
- return NULL;
-}
-
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board.
- */
-static int cb_pcidda_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev;
- struct comedi_subdevice *s;
- int index;
- int ret;
-
-/*
- * Allocate the private structure area.
- */
- if (alloc_private(dev, sizeof(struct cb_pcidda_private)) < 0)
- return -ENOMEM;
-
- pcidev = cb_pcidda_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
-
- /*
- * Enable PCI device and request regions.
- */
- if (comedi_pci_enable(pcidev, thisboard->name)) {
- dev_err(dev->class_dev,
- "cb_pcidda: failed to enable PCI device and request regions\n");
- return -EIO;
- }
-
-/*
- * Allocate the I/O ports.
- */
- devpriv->digitalio = pci_resource_start(pcidev, DIGITALIO_BADRINDEX);
- devpriv->dac = pci_resource_start(pcidev, DAC_BADRINDEX);
- dev->iobase = devpriv->dac;
-
-/*
- * Warn about the status of the driver.
- */
- if (thisboard->status == 2)
- printk
- ("WARNING: DRIVER FOR THIS BOARD NOT CHECKED WITH MANUAL. "
- "WORKS ASSUMING FULL COMPATIBILITY WITH PCI-DDA08/12. "
- "PLEASE REPORT USAGE TO <ivanmr@altavista.com>.\n");
-
-/*
- * Initialize dev->board_name.
- */
- dev->board_name = thisboard->name;
-
- ret = comedi_alloc_subdevices(dev, 3);
- if (ret)
- return ret;
-
- s = dev->subdevices + 0;
- /* analog output subdevice */
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE;
- s->n_chan = thisboard->ao_chans;
- s->maxdata = (1 << thisboard->ao_bits) - 1;
- s->range_table = thisboard->ranges;
- s->insn_write = cb_pcidda_ao_winsn;
-
- /* s->subdev_flags |= SDF_CMD_READ; */
- /* s->do_cmd = cb_pcidda_ai_cmd; */
- /* s->do_cmdtest = cb_pcidda_ai_cmdtest; */
-
- /* two 8255 digital io subdevices */
- s = dev->subdevices + 1;
- subdev_8255_init(dev, s, NULL, devpriv->digitalio);
- s = dev->subdevices + 2;
- subdev_8255_init(dev, s, NULL, devpriv->digitalio + PORT2A);
-
- dev_dbg(dev->class_dev, "eeprom:\n");
- for (index = 0; index < EEPROM_SIZE; index++) {
- devpriv->eeprom_data[index] = cb_pcidda_read_eeprom(dev, index);
- dev_dbg(dev->class_dev, "%i:0x%x\n", index,
- devpriv->eeprom_data[index]);
- }
-
- /* set calibrations dacs */
- for (index = 0; index < thisboard->ao_chans; index++)
- cb_pcidda_calibrate(dev, index, devpriv->ao_range[index]);
-
- return 1;
-}
-
-static void cb_pcidda_detach(struct comedi_device *dev)
-{
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
- if (pcidev) {
- if (dev->iobase)
- comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
- }
- if (dev->subdevices) {
- subdev_8255_cleanup(dev, dev->subdevices + 1);
- subdev_8255_cleanup(dev, dev->subdevices + 2);
- }
-}
-
-/*
* I will program this later... ;-)
*/
#if 0
@@ -418,56 +248,26 @@ static int cb_pcidda_ai_cmdtest(struct comedi_device *dev,
int err = 0;
int tmp;
- /* cmdtest tests a particular command to see if it is valid.
- * Using the cmdtest ioctl, a user can create a valid cmd
- * and then have it executes by the cmd ioctl.
- *
- * cmdtest returns 1,2,3,4 or 0, depending on which tests
- * the command passes. */
-
- /* step 1: make sure trigger sources are trivially valid */
-
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_TIMER | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src,
+ TRIG_TIMER | TRIG_EXT);
+ 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 2: make sure trigger sources are unique and mutually
- * compatible
- */
+ /* Step 2a : make sure trigger sources are unique */
- /* note that mutual compatibility is not an issue here */
- if (cmd->scan_begin_src != TRIG_TIMER
- && cmd->scan_begin_src != TRIG_EXT)
- err++;
- if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
- err++;
- if (cmd->stop_src != TRIG_TIMER && cmd->stop_src != TRIG_EXT)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -581,59 +381,10 @@ static int cb_pcidda_ns_to_timer(unsigned int *ns, int round)
}
#endif
-static int cb_pcidda_ao_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- unsigned int command;
- unsigned int channel, range;
-
- channel = CR_CHAN(insn->chanspec);
- range = CR_RANGE(insn->chanspec);
-
- /* adjust calibration dacs if range has changed */
- if (range != devpriv->ao_range[channel])
- cb_pcidda_calibrate(dev, channel, range);
-
- /* output channel configuration */
- command = NOSU | ENABLEDAC;
-
- /* output channel range */
- switch (range) {
- case 0:
- command |= BIP | RANGE10V;
- break;
- case 1:
- command |= BIP | RANGE5V;
- break;
- case 2:
- command |= BIP | RANGE2V5;
- break;
- case 3:
- command |= UNIP | RANGE10V;
- break;
- case 4:
- command |= UNIP | RANGE5V;
- break;
- case 5:
- command |= UNIP | RANGE2V5;
- break;
- }
-
- /* output channel specification */
- command |= channel << 2;
- outw(command, devpriv->dac + DACONTROL);
-
- /* write data */
- outw(data[0], devpriv->dac + DADATA + channel * 2);
-
- /* return the number of samples read/written */
- return 1;
-}
-
/* lowlevel read from eeprom */
static unsigned int cb_pcidda_serial_in(struct comedi_device *dev)
{
+ struct cb_pcidda_private *devpriv = dev->private;
unsigned int value = 0;
int i;
const int value_width = 16; /* number of bits wide values are */
@@ -651,6 +402,7 @@ static unsigned int cb_pcidda_serial_in(struct comedi_device *dev)
static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
unsigned int num_bits)
{
+ struct cb_pcidda_private *devpriv = dev->private;
int i;
for (i = 1; i <= num_bits; i++) {
@@ -667,6 +419,7 @@ static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
unsigned int address)
{
+ struct cb_pcidda_private *devpriv = dev->private;
unsigned int i;
unsigned int cal2_bits;
unsigned int value;
@@ -703,6 +456,7 @@ static void cb_pcidda_write_caldac(struct comedi_device *dev,
unsigned int caldac, unsigned int channel,
unsigned int value)
{
+ struct cb_pcidda_private *devpriv = dev->private;
unsigned int cal2_bits;
unsigned int i;
/* caldacs use 3 bit channel specification */
@@ -797,6 +551,7 @@ static unsigned int eeprom_fine_byte(unsigned int word)
static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
unsigned int range)
{
+ struct cb_pcidda_private *devpriv = dev->private;
unsigned int coarse_offset, fine_offset, coarse_gain, fine_gain;
/* remember range so we can tell when we need to readjust calibration */
@@ -827,10 +582,164 @@ static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
fine_gain_channel(channel), fine_gain);
}
+static int cb_pcidda_ao_winsn(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+ struct cb_pcidda_private *devpriv = dev->private;
+ unsigned int command;
+ unsigned int channel, range;
+
+ channel = CR_CHAN(insn->chanspec);
+ range = CR_RANGE(insn->chanspec);
+
+ /* adjust calibration dacs if range has changed */
+ if (range != devpriv->ao_range[channel])
+ cb_pcidda_calibrate(dev, channel, range);
+
+ /* output channel configuration */
+ command = NOSU | ENABLEDAC;
+
+ /* output channel range */
+ switch (range) {
+ case 0:
+ command |= BIP | RANGE10V;
+ break;
+ case 1:
+ command |= BIP | RANGE5V;
+ break;
+ case 2:
+ command |= BIP | RANGE2V5;
+ break;
+ case 3:
+ command |= UNIP | RANGE10V;
+ break;
+ case 4:
+ command |= UNIP | RANGE5V;
+ break;
+ case 5:
+ command |= UNIP | RANGE2V5;
+ break;
+ }
+
+ /* output channel specification */
+ command |= channel << 2;
+ outw(command, devpriv->dac + DACONTROL);
+
+ /* write data */
+ outw(data[0], devpriv->dac + DADATA + channel * 2);
+
+ /* return the number of samples read/written */
+ return 1;
+}
+
+static const void *cb_pcidda_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
+{
+ const struct cb_pcidda_board *thisboard;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cb_pcidda_boards); i++) {
+ thisboard = &cb_pcidda_boards[i];
+ if (thisboard->device_id != pcidev->device)
+ return thisboard;
+ }
+ return NULL;
+}
+
+static int cb_pcidda_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
+{
+ const struct cb_pcidda_board *thisboard;
+ struct cb_pcidda_private *devpriv;
+ struct comedi_subdevice *s;
+ int index;
+ int ret;
+
+ comedi_set_hw_dev(dev, &pcidev->dev);
+
+ thisboard = cb_pcidda_find_boardinfo(dev, pcidev);
+ if (!pcidev)
+ return -ENODEV;
+ dev->board_ptr = thisboard;
+ dev->board_name = thisboard->name;
+
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret)
+ return ret;
+ devpriv = dev->private;
+
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
+
+ devpriv->digitalio = pci_resource_start(pcidev, 2);
+ devpriv->dac = pci_resource_start(pcidev, 3);
+ dev->iobase = devpriv->dac;
+
+ if (thisboard->status == 2)
+ printk
+ ("WARNING: DRIVER FOR THIS BOARD NOT CHECKED WITH MANUAL. "
+ "WORKS ASSUMING FULL COMPATIBILITY WITH PCI-DDA08/12. "
+ "PLEASE REPORT USAGE TO <ivanmr@altavista.com>.\n");
+
+ ret = comedi_alloc_subdevices(dev, 3);
+ if (ret)
+ return ret;
+
+ s = &dev->subdevices[0];
+ /* analog output subdevice */
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = thisboard->ao_chans;
+ s->maxdata = (1 << thisboard->ao_bits) - 1;
+ s->range_table = thisboard->ranges;
+ s->insn_write = cb_pcidda_ao_winsn;
+
+ /* s->subdev_flags |= SDF_CMD_READ; */
+ /* s->do_cmd = cb_pcidda_ai_cmd; */
+ /* s->do_cmdtest = cb_pcidda_ai_cmdtest; */
+
+ /* two 8255 digital io subdevices */
+ s = &dev->subdevices[1];
+ subdev_8255_init(dev, s, NULL, devpriv->digitalio);
+ s = &dev->subdevices[2];
+ subdev_8255_init(dev, s, NULL, devpriv->digitalio + PORT2A);
+
+ dev_dbg(dev->class_dev, "eeprom:\n");
+ for (index = 0; index < EEPROM_SIZE; index++) {
+ devpriv->eeprom_data[index] = cb_pcidda_read_eeprom(dev, index);
+ dev_dbg(dev->class_dev, "%i:0x%x\n", index,
+ devpriv->eeprom_data[index]);
+ }
+
+ /* set calibrations dacs */
+ for (index = 0; index < thisboard->ao_chans; index++)
+ cb_pcidda_calibrate(dev, index, devpriv->ao_range[index]);
+
+ dev_info(dev->class_dev, "%s attached\n", dev->board_name);
+
+ return 0;
+}
+
+static void cb_pcidda_detach(struct comedi_device *dev)
+{
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+
+ if (dev->subdevices) {
+ subdev_8255_cleanup(dev, &dev->subdevices[1]);
+ subdev_8255_cleanup(dev, &dev->subdevices[2]);
+ }
+ if (pcidev) {
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
+ }
+}
+
static struct comedi_driver cb_pcidda_driver = {
.driver_name = "cb_pcidda",
.module = THIS_MODULE,
- .attach = cb_pcidda_attach,
+ .attach_pci = cb_pcidda_attach_pci,
.detach = cb_pcidda_detach,
};
diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c
deleted file mode 100644
index e370d0d81bbd..000000000000
--- a/drivers/staging/comedi/drivers/cb_pcidio.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- comedi/drivers/cb_pcidio.c
- A Comedi driver for PCI-DIO24H & PCI-DIO48H of ComputerBoards (currently MeasurementComputing)
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 2000 David A. Schleef <ds@schleef.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-/*
-Driver: cb_pcidio
-Description: ComputerBoards' DIO boards with PCI interface
-Devices: [Measurement Computing] PCI-DIO24 (cb_pcidio), PCI-DIO24H, PCI-DIO48H
-Author: Yoshiya Matsuzaka
-Updated: Mon, 29 Oct 2007 15:40:47 +0000
-Status: experimental
-
-This driver has been modified from skel.c of comedi-0.7.70.
-
-Configuration Options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
- If bus/slot is not specified, the first available PCI device will
- be used.
-
-Passing a zero for an option is the same as leaving it unspecified.
-*/
-
-/*------------------------------ HEADER FILES ---------------------------------*/
-#include "../comedidev.h"
-#include "8255.h"
-
-/*-------------------------- MACROS and DATATYPES -----------------------------*/
-#define PCI_VENDOR_ID_CB 0x1307
-
-/*
- * Board descriptions for two imaginary boards. Describing the
- * boards in this way is optional, and completely driver-dependent.
- * Some drivers use arrays such as this, other do not.
- */
-struct pcidio_board {
- const char *name; /* name of the board */
- int dev_id;
- int n_8255; /* number of 8255 chips on board */
-
- /* indices of base address regions */
- int pcicontroler_badrindex;
- int dioregs_badrindex;
-};
-
-static const struct pcidio_board pcidio_boards[] = {
- {
- .name = "pci-dio24",
- .dev_id = 0x0028,
- .n_8255 = 1,
- .pcicontroler_badrindex = 1,
- .dioregs_badrindex = 2,
- },
- {
- .name = "pci-dio24h",
- .dev_id = 0x0014,
- .n_8255 = 1,
- .pcicontroler_badrindex = 1,
- .dioregs_badrindex = 2,
- },
- {
- .name = "pci-dio48h",
- .dev_id = 0x000b,
- .n_8255 = 2,
- .pcicontroler_badrindex = 0,
- .dioregs_badrindex = 1,
- },
-};
-
-/*
- * Useful for shorthand access to the particular board structure
- */
-#define thisboard ((const struct pcidio_board *)dev->board_ptr)
-
-static struct pci_dev *pcidio_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
- int i;
-
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (bus != pcidev->bus->number ||
- slot != PCI_SLOT(pcidev->devfn))
- continue;
- }
- if (pcidev->vendor != PCI_VENDOR_ID_CB)
- continue;
- for (i = 0; i < ARRAY_SIZE(pcidio_boards); i++) {
- if (pcidio_boards[i].dev_id != pcidev->device)
- continue;
-
- dev->board_ptr = pcidio_boards + i;
- return pcidev;
- }
- }
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
- return NULL;
-}
-
-static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev;
- int i;
- int ret;
-
- pcidev = pcidio_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
-
-/*
- * Initialize dev->board_name. Note that we can use the "thisboard"
- * macro now, since we just initialized it in the last line.
- */
- dev->board_name = thisboard->name;
-
- if (comedi_pci_enable(pcidev, thisboard->name))
- return -EIO;
-
- dev->iobase = pci_resource_start(pcidev, thisboard->dioregs_badrindex);
-
- ret = comedi_alloc_subdevices(dev, thisboard->n_8255);
- if (ret)
- return ret;
-
- for (i = 0; i < thisboard->n_8255; i++) {
- subdev_8255_init(dev, dev->subdevices + i,
- NULL, dev->iobase + i * 4);
- dev_dbg(dev->class_dev, "subdev %d: base = 0x%lx\n", i,
- dev->iobase + i * 4);
- }
-
- return 1;
-}
-
-static void pcidio_detach(struct comedi_device *dev)
-{
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
- if (pcidev) {
- if (dev->iobase)
- comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
- }
- if (dev->subdevices) {
- int i;
- for (i = 0; i < thisboard->n_8255; i++)
- subdev_8255_cleanup(dev, dev->subdevices + i);
- }
-}
-
-static struct comedi_driver cb_pcidio_driver = {
- .driver_name = "cb_pcidio",
- .module = THIS_MODULE,
- .attach = pcidio_attach,
- .detach = pcidio_detach,
-};
-
-static int __devinit cb_pcidio_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- return comedi_pci_auto_config(dev, &cb_pcidio_driver);
-}
-
-static void __devexit cb_pcidio_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static DEFINE_PCI_DEVICE_TABLE(cb_pcidio_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0028) },
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0014) },
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x000b) },
- { 0 }
-};
-MODULE_DEVICE_TABLE(pci, cb_pcidio_pci_table);
-
-static struct pci_driver cb_pcidio_pci_driver = {
- .name = "cb_pcidio",
- .id_table = cb_pcidio_pci_table,
- .probe = cb_pcidio_pci_probe,
- .remove = __devexit_p(cb_pcidio_pci_remove),
-};
-module_comedi_pci_driver(cb_pcidio_driver, cb_pcidio_pci_driver);
-
-MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
index c632a89f3ae9..9515b6926662 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
@@ -119,11 +119,6 @@ static const struct cb_pcimdas_board cb_pcimdas_boards[] = {
};
/*
- * Useful for shorthand access to the particular board structure
- */
-#define thisboard ((const struct cb_pcimdas_board *)dev->board_ptr)
-
-/*
* this structure is for data unique to this hardware driver. If
* several hardware drivers keep similar information in this structure,
* feel free to suggest moving the variable to the struct comedi_device
@@ -138,160 +133,6 @@ struct cb_pcimdas_private {
};
/*
- * most drivers define the following macro to make it easy to
- * access the private structure.
- */
-#define devpriv ((struct cb_pcimdas_private *)dev->private)
-
-static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int cb_pcimdas_ao_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int cb_pcimdas_ao_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-static struct pci_dev *cb_pcimdas_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
- int i;
-
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (bus != pcidev->bus->number ||
- slot != PCI_SLOT(pcidev->devfn))
- continue;
- }
- if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
- continue;
-
- for (i = 0; i < ARRAY_SIZE(cb_pcimdas_boards); i++) {
- if (cb_pcimdas_boards[i].device_id != pcidev->device)
- continue;
-
- dev->board_ptr = cb_pcimdas_boards + i;
- return pcidev;
- }
- }
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
- return NULL;
-}
-
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board. If you specified a board_name array
- * in the driver structure, dev->board_ptr contains that
- * address.
- */
-static int cb_pcimdas_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev;
- struct comedi_subdevice *s;
- unsigned long iobase_8255;
- int ret;
-
-/*
- * Allocate the private structure area.
- */
- if (alloc_private(dev, sizeof(struct cb_pcimdas_private)) < 0)
- return -ENOMEM;
-
- pcidev = cb_pcimdas_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
-
- /* Warn about non-tested features */
- switch (thisboard->device_id) {
- case 0x56:
- break;
- default:
- dev_dbg(dev->class_dev, "THIS CARD IS UNSUPPORTED.\n");
- dev_dbg(dev->class_dev,
- "PLEASE REPORT USAGE TO <mocelet@sucs.org>\n");
- }
-
- if (comedi_pci_enable(pcidev, "cb_pcimdas")) {
- dev_err(dev->class_dev,
- "Failed to enable PCI device and request regions\n");
- return -EIO;
- }
-
- dev->iobase = pci_resource_start(pcidev, 2);
- devpriv->BADR3 = pci_resource_start(pcidev, 3);
- iobase_8255 = pci_resource_start(pcidev, 4);
-
-/* Dont support IRQ yet */
-/* get irq */
-/* if(request_irq(pcidev->irq, cb_pcimdas_interrupt, IRQF_SHARED, "cb_pcimdas", dev )) */
-/* { */
-/* printk(" unable to allocate irq %u\n", pcidev->irq); */
-/* return -EINVAL; */
-/* } */
-/* dev->irq = pcidev->irq; */
-
- /* Initialize dev->board_name */
- dev->board_name = thisboard->name;
-
- ret = comedi_alloc_subdevices(dev, 3);
- if (ret)
- return ret;
-
- s = dev->subdevices + 0;
- /* dev->read_subdev=s; */
- /* analog input subdevice */
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND;
- s->n_chan = thisboard->ai_se_chans;
- s->maxdata = (1 << thisboard->ai_bits) - 1;
- s->range_table = &range_unknown;
- s->len_chanlist = 1; /* This is the maximum chanlist length that */
- /* the board can handle */
- s->insn_read = cb_pcimdas_ai_rinsn;
-
- s = dev->subdevices + 1;
- /* analog output subdevice */
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE;
- s->n_chan = thisboard->ao_nchan;
- s->maxdata = 1 << thisboard->ao_bits;
- /* ranges are hardware settable, but not software readable. */
- s->range_table = &range_unknown;
- s->insn_write = &cb_pcimdas_ao_winsn;
- s->insn_read = &cb_pcimdas_ao_rinsn;
-
- s = dev->subdevices + 2;
- /* digital i/o subdevice */
- if (thisboard->has_dio)
- subdev_8255_init(dev, s, NULL, iobase_8255);
- else
- s->type = COMEDI_SUBD_UNUSED;
-
- return 1;
-}
-
-static void cb_pcimdas_detach(struct comedi_device *dev)
-{
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
- if (dev->irq)
- free_irq(dev->irq, dev);
- if (pcidev) {
- if (dev->iobase)
- comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
- }
-}
-
-/*
* "instructions" read/write data in "one-shot" or "software-triggered"
* mode.
*/
@@ -299,6 +140,8 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ const struct cb_pcimdas_board *thisboard = comedi_board(dev);
+ struct cb_pcimdas_private *devpriv = dev->private;
int n, i;
unsigned int d;
unsigned int busy;
@@ -368,6 +211,7 @@ static int cb_pcimdas_ao_winsn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct cb_pcimdas_private *devpriv = dev->private;
int i;
int chan = CR_CHAN(insn->chanspec);
@@ -397,6 +241,7 @@ static int cb_pcimdas_ao_rinsn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct cb_pcimdas_private *devpriv = dev->private;
int i;
int chan = CR_CHAN(insn->chanspec);
@@ -406,10 +251,124 @@ static int cb_pcimdas_ao_rinsn(struct comedi_device *dev,
return i;
}
+static const void *cb_pcimdas_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
+{
+ const struct cb_pcimdas_board *thisboard;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cb_pcimdas_boards); i++) {
+ thisboard = &cb_pcimdas_boards[i];
+ if (thisboard->device_id == pcidev->device)
+ return thisboard;
+ }
+ return NULL;
+}
+
+static int cb_pcimdas_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
+{
+ const struct cb_pcimdas_board *thisboard;
+ struct cb_pcimdas_private *devpriv;
+ struct comedi_subdevice *s;
+ unsigned long iobase_8255;
+ int ret;
+
+ comedi_set_hw_dev(dev, &pcidev->dev);
+
+ thisboard = cb_pcimdas_find_boardinfo(dev, pcidev);
+ if (!thisboard)
+ return -ENODEV;
+ dev->board_ptr = thisboard;
+ dev->board_name = thisboard->name;
+
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret)
+ return ret;
+ devpriv = dev->private;
+
+ /* Warn about non-tested features */
+ switch (thisboard->device_id) {
+ case 0x56:
+ break;
+ default:
+ dev_dbg(dev->class_dev, "THIS CARD IS UNSUPPORTED.\n");
+ dev_dbg(dev->class_dev,
+ "PLEASE REPORT USAGE TO <mocelet@sucs.org>\n");
+ }
+
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
+
+ dev->iobase = pci_resource_start(pcidev, 2);
+ devpriv->BADR3 = pci_resource_start(pcidev, 3);
+ iobase_8255 = pci_resource_start(pcidev, 4);
+
+/* Dont support IRQ yet */
+/* get irq */
+/* if(request_irq(pcidev->irq, cb_pcimdas_interrupt, IRQF_SHARED, "cb_pcimdas", dev )) */
+/* { */
+/* printk(" unable to allocate irq %u\n", pcidev->irq); */
+/* return -EINVAL; */
+/* } */
+/* dev->irq = pcidev->irq; */
+
+ ret = comedi_alloc_subdevices(dev, 3);
+ if (ret)
+ return ret;
+
+ s = &dev->subdevices[0];
+ /* dev->read_subdev=s; */
+ /* analog input subdevice */
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND;
+ s->n_chan = thisboard->ai_se_chans;
+ s->maxdata = (1 << thisboard->ai_bits) - 1;
+ s->range_table = &range_unknown;
+ s->len_chanlist = 1; /* This is the maximum chanlist length that */
+ /* the board can handle */
+ s->insn_read = cb_pcimdas_ai_rinsn;
+
+ s = &dev->subdevices[1];
+ /* analog output subdevice */
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = thisboard->ao_nchan;
+ s->maxdata = 1 << thisboard->ao_bits;
+ /* ranges are hardware settable, but not software readable. */
+ s->range_table = &range_unknown;
+ s->insn_write = &cb_pcimdas_ao_winsn;
+ s->insn_read = &cb_pcimdas_ao_rinsn;
+
+ s = &dev->subdevices[2];
+ /* digital i/o subdevice */
+ if (thisboard->has_dio)
+ subdev_8255_init(dev, s, NULL, iobase_8255);
+ else
+ s->type = COMEDI_SUBD_UNUSED;
+
+ dev_info(dev->class_dev, "%s attached\n", dev->board_name);
+
+ return 0;
+}
+
+static void cb_pcimdas_detach(struct comedi_device *dev)
+{
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+ if (pcidev) {
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
+ }
+}
+
static struct comedi_driver cb_pcimdas_driver = {
.driver_name = "cb_pcimdas",
.module = THIS_MODULE,
- .attach = cb_pcimdas_attach,
+ .attach_pci = cb_pcimdas_attach_pci,
.detach = cb_pcimdas_detach,
};
diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
index a80146133c04..ba9f0599be28 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
@@ -57,12 +57,7 @@ output modes on the board:
then issue one comedi_data_read() on any channel on the AO subdevice
to initiate the simultaneous XFER.
-Configuration Options:
- [0] PCI bus (optional)
- [1] PCI slot (optional)
- [2] analog output range jumper setting
- 0 == +/- 5 V
- 1 == +/- 10 V
+Configuration Options: not applicable, uses PCI auto config
*/
/*
@@ -93,337 +88,133 @@ Configuration Options:
#define PCI_ID_PCIM_DDA06_16 0x0053
/*
- * This is straight from skel.c -- I did this in case this source file
- * will someday support more than 1 board...
+ * Register map, 8-bit access only
*/
-struct board_struct {
- const char *name;
- unsigned short device_id;
- int ao_chans;
- int ao_bits;
- int dio_chans;
- int dio_method;
- /* how many bytes into the BADR are the DIO ports */
- int dio_offset;
- int regs_badrindex; /* IO Region for the control, analog output,
- and DIO registers */
- int reg_sz; /* number of bytes of registers in io region */
-};
+#define PCIMDDA_DA_CHAN(x) (0x00 + (x) * 2)
+#define PCIMDDA_8255_BASE_REG 0x0c
-enum DIO_METHODS {
- DIO_NONE = 0,
- DIO_8255,
- DIO_INTERNAL /* unimplemented */
-};
+#define MAX_AO_READBACK_CHANNELS 6
-static const struct board_struct boards[] = {
- {
- .name = "cb_pcimdda06-16",
- .device_id = PCI_ID_PCIM_DDA06_16,
- .ao_chans = 6,
- .ao_bits = 16,
- .dio_chans = 24,
- .dio_method = DIO_8255,
- .dio_offset = 12,
- .regs_badrindex = 3,
- .reg_sz = 16,
- }
+struct cb_pcimdda_private {
+ unsigned int ao_readback[MAX_AO_READBACK_CHANNELS];
};
-/*
- * Useful for shorthand access to the particular board structure
- */
-#define thisboard ((const struct board_struct *)dev->board_ptr)
-
-#define REG_SZ (thisboard->reg_sz)
-#define REGS_BADRINDEX (thisboard->regs_badrindex)
-
-/*
- * 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 board_private_struct {
- unsigned long registers; /* set by probe */
- unsigned long dio_registers;
- char attached_to_8255; /* boolean */
- /* would be useful for a PCI device */
- struct pci_dev *pci_dev;
-
-#define MAX_AO_READBACK_CHANNELS 6
- /* Used for AO readback */
- unsigned int ao_readback[MAX_AO_READBACK_CHANNELS];
+static int cb_pcimdda_ao_winsn(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ struct cb_pcimdda_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned long offset = dev->iobase + PCIMDDA_DA_CHAN(chan);
+ unsigned int val = 0;
+ int i;
-};
+ for (i = 0; i < insn->n; i++) {
+ val = data[i];
-/*
- * most drivers define the following macro to make it easy to
- * access the private structure.
- */
-#define devpriv ((struct board_private_struct *)dev->private)
+ /*
+ * Write the LSB then MSB.
+ *
+ * If the simultaneous xfer mode is selected by the
+ * jumper on the card, a read instruction is needed
+ * in order to initiate the simultaneous transfer.
+ * Otherwise, the DAC will be updated when the MSB
+ * is written.
+ */
+ outb(val & 0x00ff, offset);
+ outb((val >> 8) & 0x00ff, offset + 1);
+ }
-static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
+ /* Cache the last value for readback */
+ devpriv->ao_readback[chan] = val;
-/*---------------------------------------------------------------------------
- HELPER FUNCTION DECLARATIONS
------------------------------------------------------------------------------*/
+ return insn->n;
+}
-/* returns a maxdata value for a given n_bits */
-static inline unsigned int figure_out_maxdata(int bits)
+static int cb_pcimdda_ao_rinsn(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- return ((unsigned int)1 << bits) - 1;
-}
+ struct cb_pcimdda_private *devpriv = dev->private;
+ int chan = CR_CHAN(insn->chanspec);
+ unsigned long offset = dev->iobase + PCIMDDA_DA_CHAN(chan);
+ int i;
-/*
- * Probes for a supported device.
- *
- * Prerequisite: private be allocated already inside dev
- *
- * If the device is found, it returns 0 and has the following side effects:
- *
- * o assigns a struct pci_dev * to dev->private->pci_dev
- * o assigns a struct board * to dev->board_ptr
- * o sets dev->private->registers
- * o sets dev->private->dio_registers
- *
- * Otherwise, returns a -errno on error
- */
-static int probe(struct comedi_device *dev, const struct comedi_devconfig *it);
+ for (i = 0; i < insn->n; i++) {
+ /* Initiate the simultaneous transfer */
+ inw(offset);
+
+ data[i] = devpriv->ao_readback[chan];
+ }
-/*---------------------------------------------------------------------------
- FUNCTION DEFINITIONS
------------------------------------------------------------------------------*/
+ return insn->n;
+}
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board. If you specified a board_name array
- * in the driver structure, dev->board_ptr contains that
- * address.
- */
-static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int cb_pcimdda_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
+ struct cb_pcimdda_private *devpriv;
struct comedi_subdevice *s;
- int err;
+ int ret;
-/*
- * Allocate the private structure area. alloc_private() is a
- * convenient macro defined in comedidev.h.
- * if this function fails (returns negative) then the private area is
- * kfree'd by comedi
- */
- if (alloc_private(dev, sizeof(struct board_private_struct)) < 0)
- return -ENOMEM;
+ comedi_set_hw_dev(dev, &pcidev->dev);
+ dev->board_name = dev->driver->driver_name;
-/*
- * If you can probe the device to determine what device in a series
- * it is, this is the place to do it. Otherwise, dev->board_ptr
- * should already be initialized.
- */
- err = probe(dev, it);
- if (err)
- return err;
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret)
+ return ret;
+ devpriv = dev->private;
-/* Output some info */
- printk("comedi%d: %s: ", dev->minor, thisboard->name);
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
+ dev->iobase = pci_resource_start(pcidev, 3);
-/*
- * Initialize dev->board_name. Note that we can use the "thisboard"
- * macro now, since we just initialized it in the last line.
- */
- dev->board_name = thisboard->name;
-
- err = comedi_alloc_subdevices(dev, 2);
- if (err)
- return err;
-
- s = dev->subdevices + 0;
+ ret = comedi_alloc_subdevices(dev, 2);
+ if (ret)
+ return ret;
+ s = &dev->subdevices[0];
/* analog output subdevice */
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
- s->n_chan = thisboard->ao_chans;
- s->maxdata = figure_out_maxdata(thisboard->ao_bits);
- /* this is hard-coded here */
- if (it->options[2])
- s->range_table = &range_bipolar10;
- else
- s->range_table = &range_bipolar5;
- s->insn_write = &ao_winsn;
- s->insn_read = &ao_rinsn;
-
- s = dev->subdevices + 1;
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+ s->n_chan = 6;
+ s->maxdata = 0xffff;
+ s->range_table = &range_bipolar5;
+ s->insn_write = cb_pcimdda_ao_winsn;
+ s->insn_read = cb_pcimdda_ao_rinsn;
+
+ s = &dev->subdevices[1];
/* digital i/o subdevice */
- if (thisboard->dio_chans) {
- switch (thisboard->dio_method) {
- case DIO_8255:
- /*
- * this is a straight 8255, so register us with
- * the 8255 driver
- */
- subdev_8255_init(dev, s, NULL, devpriv->dio_registers);
- devpriv->attached_to_8255 = 1;
- break;
- case DIO_INTERNAL:
- default:
- printk("DIO_INTERNAL not implemented yet!\n");
- return -ENXIO;
- break;
- }
- } else {
- s->type = COMEDI_SUBD_UNUSED;
- }
+ ret = subdev_8255_init(dev, s, NULL,
+ dev->iobase + PCIMDDA_8255_BASE_REG);
+ if (ret)
+ return ret;
- printk("attached\n");
+ dev_info(dev->class_dev, "%s attached\n", dev->board_name);
return 1;
}
-static void detach(struct comedi_device *dev)
-{
- if (devpriv) {
- if (dev->subdevices && devpriv->attached_to_8255) {
- subdev_8255_cleanup(dev, dev->subdevices + 2);
- devpriv->attached_to_8255 = 0;
- }
- if (devpriv->pci_dev) {
- if (devpriv->registers)
- comedi_pci_disable(devpriv->pci_dev);
- pci_dev_put(devpriv->pci_dev);
- }
- }
-}
-
-static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static void cb_pcimdda_detach(struct comedi_device *dev)
{
- int i;
- int chan = CR_CHAN(insn->chanspec);
- unsigned long offset = devpriv->registers + chan * 2;
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- /* 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++) {
- /* first, load the low byte */
- outb((char)(data[i] & 0x00ff), offset);
- /* next, write the high byte -- only after this is written is
- the channel voltage updated in the DAC, unless
- we're in simultaneous xfer mode (jumper on card)
- then a rinsn is necessary to actually update the DAC --
- see ao_rinsn() below... */
- outb((char)(data[i] >> 8 & 0x00ff), offset + 1);
-
- /* for testing only.. the actual rinsn SHOULD do an inw!
- (see the stuff about simultaneous XFER mode on this board) */
- devpriv->ao_readback[chan] = data[i];
+ if (dev->subdevices)
+ subdev_8255_cleanup(dev, &dev->subdevices[1]);
+ if (pcidev) {
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
}
-
- /* return the number of samples read/written */
- return i;
-}
-
-/* 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 board has this jumper setting called "Simultaneous
- Xfer mode" (off by default), we will support it. 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)
-{
- int i;
- int chan = CR_CHAN(insn->chanspec);
-
- for (i = 0; i < insn->n; i++) {
- inw(devpriv->registers + chan * 2);
- /*
- * should I set data[i] to the result of the actual read
- * on the register or the cached unsigned int in
- * devpriv->ao_readback[]?
- */
- data[i] = devpriv->ao_readback[chan];
- }
-
- return i;
-}
-
-/*---------------------------------------------------------------------------
- HELPER FUNCTION DEFINITIONS
------------------------------------------------------------------------------*/
-
-/*
- * Probes for a supported device.
- *
- * Prerequisite: private be allocated already inside dev
- *
- * If the device is found, it returns 0 and has the following side effects:
- *
- * o assigns a struct pci_dev * to dev->private->pci_dev
- * o assigns a struct board * to dev->board_ptr
- * o sets dev->private->registers
- * o sets dev->private->dio_registers
- *
- * Otherwise, returns a -errno on error
- */
-static int probe(struct comedi_device *dev, const struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev = NULL;
- int index;
- unsigned long registers;
-
- for_each_pci_dev(pcidev) {
- /* is it not a computer boards card? */
- if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
- continue;
- /* loop through cards supported by this driver */
- for (index = 0; index < ARRAY_SIZE(boards); index++) {
- if (boards[index].device_id != pcidev->device)
- continue;
- /* was a particular bus/slot requested? */
- if (it->options[0] || it->options[1]) {
- /* are we on the wrong bus/slot? */
- if (pcidev->bus->number != it->options[0] ||
- PCI_SLOT(pcidev->devfn) != it->options[1]) {
- continue;
- }
- }
- /* found ! */
-
- devpriv->pci_dev = pcidev;
- dev->board_ptr = boards + index;
- if (comedi_pci_enable(pcidev, thisboard->name)) {
- printk
- ("cb_pcimdda: Failed to enable PCI device and request regions\n");
- return -EIO;
- }
- registers =
- pci_resource_start(devpriv->pci_dev,
- REGS_BADRINDEX);
- devpriv->registers = registers;
- devpriv->dio_registers
- = devpriv->registers + thisboard->dio_offset;
- return 0;
- }
- }
-
- printk("cb_pcimdda: No supported ComputerBoards/MeasurementComputing "
- "card found at the requested position\n");
- return -ENODEV;
}
static struct comedi_driver cb_pcimdda_driver = {
.driver_name = "cb_pcimdda",
.module = THIS_MODULE,
- .attach = attach,
- .detach = detach,
+ .attach_pci = cb_pcimdda_attach_pci,
+ .detach = cb_pcimdda_detach,
};
static int __devinit 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 5ed324c4f620..5c768bc76eb1 100644
--- a/drivers/staging/comedi/drivers/comedi_bond.c
+++ b/drivers/staging/comedi/drivers/comedi_bond.c
@@ -59,40 +59,6 @@ Configuration Options:
/* The maxiumum number of channels per subdevice. */
#define MAX_CHANS 256
-#define MODULE_NAME "comedi_bond"
-#ifndef STR
-# define STR1(x) #x
-# define STR(x) STR1(x)
-#endif
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "If true, print extra cryptic debugging output useful"
- "only to developers.");
-
-#define LOG_MSG(x...) printk(KERN_INFO MODULE_NAME": "x)
-#define DEBUG(x...) \
- do { \
- if (debug) \
- printk(KERN_DEBUG MODULE_NAME": DEBUG: "x); \
- } while (0)
-#define WARNING(x...) printk(KERN_WARNING MODULE_NAME ": WARNING: "x)
-#define ERROR(x...) printk(KERN_ERR MODULE_NAME ": INTERNAL ERROR: "x)
-
-/*
- * 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.
- */
-struct BondingBoard {
- const char *name;
-};
-
-/*
- * Useful for shorthand access to the particular board structure
- */
-#define thisboard ((const struct BondingBoard *)dev->board_ptr)
-
struct BondedDevice {
struct comedi_device *dev;
unsigned minor;
@@ -107,7 +73,7 @@ struct BondedDevice {
/* 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 Private {
+struct comedi_bond_private {
# define MAX_BOARD_NAME 256
char name[MAX_BOARD_NAME];
struct BondedDevice **devs;
@@ -116,12 +82,6 @@ struct Private {
unsigned nchans;
};
-/*
- * most drivers define the following macro to make it easy to
- * access the private structure.
- */
-#define devpriv ((struct Private *)dev->private)
-
/* 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.
@@ -131,6 +91,7 @@ static int bonding_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct comedi_bond_private *devpriv = dev->private;
#define LSAMPL_BITS (sizeof(unsigned int)*8)
unsigned nchans = LSAMPL_BITS, num_done = 0, i;
@@ -177,6 +138,7 @@ static int bonding_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct comedi_bond_private *devpriv = dev->private;
int chan = CR_CHAN(insn->chanspec), ret, io_bits = s->io_bits;
unsigned int io;
struct BondedDevice *bdev;
@@ -230,6 +192,7 @@ static void *Realloc(const void *oldmem, size_t newlen, size_t oldlen)
static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it)
{
+ struct comedi_bond_private *devpriv = dev->private;
int i;
struct comedi_device *devs_opened[COMEDI_NUM_BOARD_MINORS];
@@ -245,15 +208,18 @@ static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it)
struct BondedDevice *bdev = NULL;
if (minor < 0 || minor >= COMEDI_NUM_BOARD_MINORS) {
- ERROR("Minor %d is invalid!\n", minor);
+ dev_err(dev->class_dev,
+ "Minor %d is invalid!\n", minor);
return 0;
}
if (minor == dev->minor) {
- ERROR("Cannot bond this driver to itself!\n");
+ dev_err(dev->class_dev,
+ "Cannot bond this driver to itself!\n");
return 0;
}
if (devs_opened[minor]) {
- ERROR("Minor %d specified more than once!\n", minor);
+ dev_err(dev->class_dev,
+ "Minor %d specified more than once!\n", minor);
return 0;
}
@@ -263,7 +229,8 @@ static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it)
d = devs_opened[minor] = comedi_open(file);
if (!d) {
- ERROR("Minor %u could not be opened\n", minor);
+ dev_err(dev->class_dev,
+ "Minor %u could not be opened\n", minor);
return 0;
}
@@ -272,14 +239,14 @@ static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it)
sdev + 1)) > -1) {
nchans = comedi_get_n_channels(d, sdev);
if (nchans <= 0) {
- ERROR("comedi_get_n_channels() returned %d "
- "on minor %u subdev %d!\n",
- nchans, minor, sdev);
+ dev_err(dev->class_dev,
+ "comedi_get_n_channels() returned %d on minor %u subdev %d!\n",
+ nchans, minor, sdev);
return 0;
}
bdev = kmalloc(sizeof(*bdev), GFP_KERNEL);
if (!bdev) {
- ERROR("Out of memory.\n");
+ dev_err(dev->class_dev, "Out of memory\n");
return 0;
}
bdev->dev = d;
@@ -302,8 +269,8 @@ static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it)
Realloc(devpriv->devs,
++devpriv->ndevs * sizeof(bdev), tmp);
if (!devpriv->devs) {
- ERROR("Could not allocate memory. "
- "Out of memory?");
+ dev_err(dev->class_dev,
+ "Could not allocate memory. Out of memory?\n");
return 0;
}
@@ -323,7 +290,7 @@ static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it)
}
if (!devpriv->nchans) {
- ERROR("No channels found!\n");
+ dev_err(dev->class_dev, "No channels found!\n");
return 0;
}
@@ -333,35 +300,28 @@ static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it)
static int bonding_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
+ struct comedi_bond_private *devpriv;
struct comedi_subdevice *s;
int ret;
- LOG_MSG("comedi%d\n", dev->minor);
-
- /*
- * Allocate the private structure area. alloc_private() is a
- * convenient macro defined in comedidev.h.
- */
- if (alloc_private(dev, sizeof(struct Private)) < 0)
- return -ENOMEM;
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret)
+ return ret;
+ devpriv = dev->private;
/*
- * Setup our bonding from config params.. sets up our Private struct..
+ * Setup our bonding from config params.. sets up our private struct..
*/
if (!doDevConfig(dev, it))
return -EINVAL;
- /*
- * Initialize dev->board_name. Note that we can use the "thisboard"
- * macro now, since we just initialized it in the last line.
- */
dev->board_name = devpriv->name;
ret = comedi_alloc_subdevices(dev, 1);
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = devpriv->nchans;
@@ -370,9 +330,9 @@ static int bonding_attach(struct comedi_device *dev,
s->insn_bits = bonding_dio_insn_bits;
s->insn_config = bonding_dio_insn_config;
- LOG_MSG("attached with %u DIO channels coming from %u different "
- "subdevices all bonded together. "
- "John Lennon would be proud!\n",
+ dev_info(dev->class_dev,
+ "%s: %s attached, %u channels from %u devices\n",
+ dev->driver->driver_name, dev->board_name,
devpriv->nchans, devpriv->ndevs);
return 1;
@@ -380,6 +340,7 @@ static int bonding_attach(struct comedi_device *dev,
static void bonding_detach(struct comedi_device *dev)
{
+ struct comedi_bond_private *devpriv = dev->private;
unsigned long devs_closed = 0;
if (devpriv) {
@@ -402,25 +363,16 @@ static void bonding_detach(struct comedi_device *dev)
}
}
-static const struct BondingBoard bondingBoards[] = {
- {
- .name = "comedi_bond",
- },
-};
-
static struct comedi_driver bonding_driver = {
.driver_name = "comedi_bond",
.module = THIS_MODULE,
.attach = bonding_attach,
.detach = bonding_detach,
- .board_name = &bondingBoards[0].name,
- .offset = sizeof(struct BondingBoard),
- .num_names = ARRAY_SIZE(bondingBoards),
};
module_comedi_driver(bonding_driver);
MODULE_AUTHOR("Calin A. Culianu");
-MODULE_DESCRIPTION(MODULE_NAME "A driver for COMEDI to bond multiple COMEDI "
+MODULE_DESCRIPTION("comedi_bond: A driver for COMEDI to bond multiple COMEDI "
"devices together as one. In the words of John Lennon: "
"'And the world will live as one...'");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/comedi_fc.h b/drivers/staging/comedi/drivers/comedi_fc.h
index 4b2cfd327995..94481c637a0a 100644
--- a/drivers/staging/comedi/drivers/comedi_fc.h
+++ b/drivers/staging/comedi/drivers/comedi_fc.h
@@ -73,4 +73,36 @@ static inline unsigned int cfc_bytes_per_scan(struct comedi_subdevice *subd)
return num_samples * bytes_per_sample(subd);
}
+/**
+ * cfc_check_trigger_src() - trivially validate a comedi_cmd trigger source
+ * @src: pointer to the trigger source to validate
+ * @flags: bitmask of valid TRIG_* for the trigger
+ *
+ * This is used in "step 1" of the do_cmdtest functions of comedi drivers
+ * to vaildate the comedi_cmd triggers. The mask of the @src against the
+ * @flags allows the userspace comedilib to pass all the comedi_cmd
+ * triggers as TRIG_ANY and get back a bitmask of the valid trigger sources.
+ */
+static inline int cfc_check_trigger_src(unsigned int *src, unsigned int flags)
+{
+ unsigned int orig_src = *src;
+
+ *src = orig_src & flags;
+ if (*src == TRIG_INVALID || *src != orig_src)
+ return -EINVAL;
+ return 0;
+}
+
+/**
+ * cfc_check_trigger_is_unique() - make sure a trigger source is unique
+ * @src: the trigger source to check
+ */
+static inline int cfc_check_trigger_is_unique(unsigned int src)
+{
+ /* this test is true if more than one _src bit is set */
+ if ((src & (src - 1)) != 0)
+ return -EINVAL;
+ return 0;
+}
+
#endif /* _COMEDI_FC_H */
diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c
index 9a63cac2434a..22ef94242590 100644
--- a/drivers/staging/comedi/drivers/comedi_parport.c
+++ b/drivers/staging/comedi/drivers/comedi_parport.c
@@ -85,6 +85,8 @@ pin, which can be used to wake up tasks.
#include <linux/interrupt.h>
#include <linux/ioport.h>
+#include "comedi_fc.h"
+
#define PARPORT_SIZE 3
#define PARPORT_A 0
@@ -96,11 +98,12 @@ struct parport_private {
unsigned int c_data;
int enable_irq;
};
-#define devpriv ((struct parport_private *)(dev->private))
static int parport_insn_a(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct parport_private *devpriv = dev->private;
+
if (data[0]) {
devpriv->a_data &= ~data[0];
devpriv->a_data |= (data[0] & data[1]);
@@ -117,6 +120,8 @@ static int parport_insn_config_a(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct parport_private *devpriv = dev->private;
+
if (data[0]) {
s->io_bits = 0xff;
devpriv->c_data &= ~(1 << 5);
@@ -145,6 +150,8 @@ static int parport_insn_b(struct comedi_device *dev, struct comedi_subdevice *s,
static int parport_insn_c(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct parport_private *devpriv = dev->private;
+
data[0] &= 0x0f;
if (data[0]) {
devpriv->c_data &= ~data[0];
@@ -171,39 +178,20 @@ static int parport_intr_cmdtest(struct comedi_device *dev,
struct comedi_cmd *cmd)
{
int err = 0;
- int tmp;
-
- /* step 1 */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_FOLLOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
if (err)
return 1;
- /* step 2: ignored */
+ /* Step 2a : make sure trigger sources are unique */
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -245,6 +233,8 @@ static int parport_intr_cmdtest(struct comedi_device *dev,
static int parport_intr_cmd(struct comedi_device *dev,
struct comedi_subdevice *s)
{
+ struct parport_private *devpriv = dev->private;
+
devpriv->c_data |= 0x10;
outb(devpriv->c_data, dev->iobase + PARPORT_C);
@@ -256,7 +246,7 @@ static int parport_intr_cmd(struct comedi_device *dev,
static int parport_intr_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- printk(KERN_DEBUG "parport_intr_cancel()\n");
+ struct parport_private *devpriv = dev->private;
devpriv->c_data &= ~0x10;
outb(devpriv->c_data, dev->iobase + PARPORT_C);
@@ -269,12 +259,11 @@ static int parport_intr_cancel(struct comedi_device *dev,
static irqreturn_t parport_interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
- struct comedi_subdevice *s = dev->subdevices + 3;
+ struct parport_private *devpriv = dev->private;
+ struct comedi_subdevice *s = &dev->subdevices[3];
- if (!devpriv->enable_irq) {
- printk(KERN_ERR "comedi_parport: bogus irq, ignored\n");
+ if (!devpriv->enable_irq)
return IRQ_NONE;
- }
comedi_buf_put(s->async, 0);
s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
@@ -286,41 +275,42 @@ static irqreturn_t parport_interrupt(int irq, void *d)
static int parport_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
+ struct parport_private *devpriv;
int ret;
unsigned int irq;
unsigned long iobase;
struct comedi_subdevice *s;
+ dev->board_name = dev->driver->driver_name;
+
iobase = it->options[0];
- printk(KERN_INFO "comedi%d: parport: 0x%04lx ", dev->minor, iobase);
- if (!request_region(iobase, PARPORT_SIZE, "parport (comedi)")) {
- printk(KERN_ERR "I/O port conflict\n");
+ if (!request_region(iobase, PARPORT_SIZE, dev->board_name)) {
+ dev_err(dev->class_dev, "I/O port conflict\n");
return -EIO;
}
dev->iobase = iobase;
irq = it->options[1];
if (irq) {
- printk(KERN_INFO " irq=%u", irq);
- ret = request_irq(irq, parport_interrupt, 0, "comedi_parport",
+ ret = request_irq(irq, parport_interrupt, 0, dev->board_name,
dev);
if (ret < 0) {
- printk(KERN_ERR " irq not available\n");
+ dev_err(dev->class_dev, "irq not available\n");
return -EINVAL;
}
dev->irq = irq;
}
- dev->board_name = "parport";
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
return ret;
- ret = alloc_private(dev, sizeof(struct parport_private));
+ ret = alloc_private(dev, sizeof(*devpriv));
if (ret < 0)
return ret;
+ devpriv = dev->private;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 8;
@@ -329,7 +319,7 @@ static int parport_attach(struct comedi_device *dev,
s->insn_bits = parport_insn_a;
s->insn_config = parport_insn_config_a;
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
s->n_chan = 5;
@@ -337,7 +327,7 @@ static int parport_attach(struct comedi_device *dev,
s->range_table = &range_digital;
s->insn_bits = parport_insn_b;
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE;
s->n_chan = 4;
@@ -345,7 +335,7 @@ static int parport_attach(struct comedi_device *dev,
s->range_table = &range_digital;
s->insn_bits = parport_insn_c;
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
if (irq) {
dev->read_subdev = s;
s->type = COMEDI_SUBD_DI;
@@ -366,8 +356,10 @@ static int parport_attach(struct comedi_device *dev,
devpriv->c_data = 0;
outb(devpriv->c_data, dev->iobase + PARPORT_C);
- printk(KERN_INFO "\n");
- return 1;
+ dev_info(dev->class_dev, "%s: iobase=0x%04lx, irq %sabled",
+ dev->board_name, dev->iobase, dev->irq ? "en" : "dis");
+
+ return 0;
}
static void parport_detach(struct comedi_device *dev)
diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
index 523a809708b7..7817def1556c 100644
--- a/drivers/staging/comedi/drivers/comedi_test.c
+++ b/drivers/staging/comedi/drivers/comedi_test.c
@@ -57,14 +57,6 @@ zero volts).
#include "comedi_fc.h"
#include <linux/timer.h>
-/* Board descriptions */
-struct waveform_board {
- const char *name;
- int ai_chans;
- int ai_bits;
- int have_dio;
-};
-
#define N_CHANS 8
/* Data unique to this driver */
@@ -81,7 +73,6 @@ struct waveform_private {
unsigned timer_running:1;
unsigned int ao_loopbacks[N_CHANS];
};
-#define devpriv ((struct waveform_private *)dev->private)
/* 1000 nanosec in a microsec */
static const int nano_per_micro = 1000;
@@ -98,6 +89,7 @@ static const struct comedi_lrange waveform_ai_ranges = {
static short fake_sawtooth(struct comedi_device *dev, unsigned int range_index,
unsigned long current_time)
{
+ struct waveform_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
unsigned int offset = s->maxdata / 2;
u64 value;
@@ -122,6 +114,7 @@ static short fake_squarewave(struct comedi_device *dev,
unsigned int range_index,
unsigned long current_time)
{
+ struct waveform_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
unsigned int offset = s->maxdata / 2;
u64 value;
@@ -175,6 +168,7 @@ static short fake_waveform(struct comedi_device *dev, unsigned int channel,
static void waveform_ai_interrupt(unsigned long arg)
{
struct comedi_device *dev = (struct comedi_device *)arg;
+ struct waveform_private *devpriv = dev->private;
struct comedi_async *async = dev->read_subdev->async;
struct comedi_cmd *cmd = &async->cmd;
unsigned int i, j;
@@ -237,44 +231,23 @@ static int waveform_ai_cmdtest(struct comedi_device *dev,
int err = 0;
int tmp;
- /* step 1: make sure trigger sources are trivially valid */
-
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_NOW | TRIG_TIMER;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW | 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 2: make sure trigger sources are unique and mutually compatible
- */
+ /* Step 2a : make sure trigger sources are unique */
- if (cmd->convert_src != TRIG_NOW && cmd->convert_src != TRIG_TIMER)
- err++;
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -362,6 +335,7 @@ static int waveform_ai_cmdtest(struct comedi_device *dev,
static int waveform_ai_cmd(struct comedi_device *dev,
struct comedi_subdevice *s)
{
+ struct waveform_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
if (cmd->flags & TRIG_RT) {
@@ -395,6 +369,8 @@ static int waveform_ai_cmd(struct comedi_device *dev,
static int waveform_ai_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
+ struct waveform_private *devpriv = dev->private;
+
devpriv->timer_running = 0;
del_timer(&devpriv->timer);
return 0;
@@ -404,6 +380,7 @@ static int waveform_ai_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct waveform_private *devpriv = dev->private;
int i, chan = CR_CHAN(insn->chanspec);
for (i = 0; i < insn->n; i++)
@@ -416,6 +393,7 @@ static int waveform_ao_insn_write(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct waveform_private *devpriv = dev->private;
int i, chan = CR_CHAN(insn->chanspec);
for (i = 0; i < insn->n; i++)
@@ -427,17 +405,19 @@ static int waveform_ao_insn_write(struct comedi_device *dev,
static int waveform_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
- const struct waveform_board *board = comedi_board(dev);
+ struct waveform_private *devpriv;
struct comedi_subdevice *s;
int amplitude = it->options[0];
int period = it->options[1];
int i;
int ret;
- dev->board_name = board->name;
+ dev->board_name = dev->driver->driver_name;
- if (alloc_private(dev, sizeof(struct waveform_private)) < 0)
- return -ENOMEM;
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret < 0)
+ return ret;
+ devpriv = dev->private;
/* set default amplitude and period */
if (amplitude <= 0)
@@ -452,13 +432,13 @@ static int waveform_attach(struct comedi_device *dev,
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
dev->read_subdev = s;
/* analog input subdevice */
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
- s->n_chan = board->ai_chans;
- s->maxdata = (1 << board->ai_bits) - 1;
+ s->n_chan = N_CHANS;
+ s->maxdata = 0xffff;
s->range_table = &waveform_ai_ranges;
s->len_chanlist = s->n_chan * 2;
s->insn_read = waveform_ai_insn_read;
@@ -466,13 +446,13 @@ static int waveform_attach(struct comedi_device *dev,
s->do_cmdtest = waveform_ai_cmdtest;
s->cancel = waveform_ai_cancel;
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
dev->write_subdev = s;
/* analog output subdevice (loopback) */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITEABLE | SDF_GROUND;
- s->n_chan = board->ai_chans;
- s->maxdata = (1 << board->ai_bits) - 1;
+ s->n_chan = N_CHANS;
+ s->maxdata = 0xffff;
s->range_table = &waveform_ai_ranges;
s->len_chanlist = s->n_chan * 2;
s->insn_write = waveform_ao_insn_write;
@@ -488,35 +468,27 @@ static int waveform_attach(struct comedi_device *dev,
devpriv->timer.function = waveform_ai_interrupt;
devpriv->timer.data = (unsigned long)dev;
- printk(KERN_INFO "comedi%d: comedi_test: "
- "%i microvolt, %li microsecond waveform attached\n", dev->minor,
- devpriv->uvolt_amplitude, devpriv->usec_period);
- return 1;
+ dev_info(dev->class_dev,
+ "%s: %i microvolt, %li microsecond waveform attached\n",
+ dev->board_name,
+ devpriv->uvolt_amplitude, devpriv->usec_period);
+
+ return 0;
}
static void waveform_detach(struct comedi_device *dev)
{
- if (dev->private)
+ struct waveform_private *devpriv = dev->private;
+
+ if (devpriv)
waveform_ai_cancel(dev, dev->read_subdev);
}
-static const struct waveform_board waveform_boards[] = {
- {
- .name = "comedi_test",
- .ai_chans = N_CHANS,
- .ai_bits = 16,
- .have_dio = 0,
- },
-};
-
static struct comedi_driver waveform_driver = {
.driver_name = "comedi_test",
.module = THIS_MODULE,
.attach = waveform_attach,
.detach = waveform_detach,
- .board_name = &waveform_boards[0].name,
- .offset = sizeof(struct waveform_board),
- .num_names = ARRAY_SIZE(waveform_boards),
};
module_comedi_driver(waveform_driver);
diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
index 944cfeeb2b2d..178a6a4bb7d5 100644
--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
+++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
@@ -27,51 +27,35 @@ Author: Stefano Rivoir <s.rivoir@gts.it>
Updated: Wed, 27 Jun 2007 13:00:06 +0100
Status: works
-Configuration Options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
- If bus/slot is not specified, the first supported
- PCI device found will be used.
+Configuration Options: not applicable, uses comedi PCI auto config
*/
#include "../comedidev.h"
-enum contec_model {
- PIO1616L = 0,
-};
-
-struct contec_board {
- const char *name;
- int model;
- int in_ports;
- int out_ports;
- int in_offs;
- int out_offs;
- int out_boffs;
-};
-static const struct contec_board contec_boards[] = {
- {"PIO1616L", PIO1616L, 16, 16, 0, 2, 10},
-};
-
#define PCI_DEVICE_ID_PIO1616L 0x8172
-#define thisboard ((const struct contec_board *)dev->board_ptr)
+/*
+ * Register map
+ */
+#define PIO1616L_DI_REG 0x00
+#define PIO1616L_DO_REG 0x02
static int contec_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];
- dev_dbg(dev->class_dev, "contec_do_insn_bits called\n");
- dev_dbg(dev->class_dev, "data: %d %d\n", data[0], data[1]);
+ if (mask) {
+ s->state &= ~mask;
+ s->state |= (bits & mask);
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= data[0] & data[1];
- dev_dbg(dev->class_dev, "out: %d on %lx\n", s->state,
- dev->iobase + thisboard->out_offs);
- outw(s->state, dev->iobase + thisboard->out_offs);
+ outw(s->state, dev->iobase + PIO1616L_DO_REG);
}
+
+ data[1] = s->state;
+
return insn->n;
}
@@ -79,87 +63,49 @@ static int contec_di_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
-
- dev_dbg(dev->class_dev, "contec_di_insn_bits called\n");
- dev_dbg(dev->class_dev, "data: %d %d\n", data[0], data[1]);
-
- data[1] = inw(dev->iobase + thisboard->in_offs);
+ data[1] = inw(dev->iobase + PIO1616L_DI_REG);
return insn->n;
}
-static struct pci_dev *contec_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
-
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (bus != pcidev->bus->number ||
- slot != PCI_SLOT(pcidev->devfn))
- continue;
- }
- if (pcidev->vendor != PCI_VENDOR_ID_CONTEC ||
- pcidev->device != PCI_DEVICE_ID_PIO1616L)
- continue;
-
- dev->board_ptr = contec_boards + 0;
- return pcidev;
- }
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
- return NULL;
-}
-
-static int contec_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int contec_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev;
struct comedi_subdevice *s;
int ret;
- printk("comedi%d: contec: ", dev->minor);
+ comedi_set_hw_dev(dev, &pcidev->dev);
- dev->board_name = thisboard->name;
+ dev->board_name = dev->driver->driver_name;
- ret = comedi_alloc_subdevices(dev, 2);
+ ret = comedi_pci_enable(pcidev, dev->board_name);
if (ret)
return ret;
-
- pcidev = contec_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
-
- if (comedi_pci_enable(pcidev, "contec_pci_dio")) {
- printk("error enabling PCI device and request regions!\n");
- return -EIO;
- }
dev->iobase = pci_resource_start(pcidev, 0);
- printk(" base addr %lx ", dev->iobase);
- s = dev->subdevices + 0;
-
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE;
- s->n_chan = 16;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = contec_di_insn_bits;
-
- s = dev->subdevices + 1;
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE;
- s->n_chan = 16;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = contec_do_insn_bits;
-
- printk("attached\n");
+ ret = comedi_alloc_subdevices(dev, 2);
+ if (ret)
+ return ret;
- return 1;
+ s = &dev->subdevices[0];
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 16;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = contec_di_insn_bits;
+
+ s = &dev->subdevices[1];
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = 16;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = contec_do_insn_bits;
+
+ dev_info(dev->class_dev, "%s attached\n", dev->board_name);
+
+ return 0;
}
static void contec_detach(struct comedi_device *dev)
@@ -169,14 +115,13 @@ static void contec_detach(struct comedi_device *dev)
if (pcidev) {
if (dev->iobase)
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
}
}
static struct comedi_driver contec_pci_dio_driver = {
.driver_name = "contec_pci_dio",
.module = THIS_MODULE,
- .attach = contec_attach,
+ .attach_pci = contec_attach_pci,
.detach = contec_detach,
};
@@ -192,8 +137,7 @@ static void __devexit contec_pci_dio_pci_remove(struct pci_dev *dev)
}
static DEFINE_PCI_DEVICE_TABLE(contec_pci_dio_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_CONTEC, PCI_DEVICE_ID_PIO1616L),
- .driver_data = PIO1616L },
+ { PCI_DEVICE(PCI_VENDOR_ID_CONTEC, PCI_DEVICE_ID_PIO1616L) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, contec_pci_dio_pci_table);
diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
index cad559a1a730..d13c8c5822bf 100644
--- a/drivers/staging/comedi/drivers/daqboard2000.c
+++ b/drivers/staging/comedi/drivers/daqboard2000.c
@@ -31,16 +31,10 @@ Devices: [IOTech] DAQBoard/2000 (daqboard2000)
Much of the functionality of this driver was determined from reading
the source code for the Windows driver.
-The FPGA on the board requires initialization code, which can
-be loaded by comedi_config using the -i
-option. The initialization code is available from http://www.comedi.org
-in the comedi_nonfree_firmware tarball.
-
-Configuration options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
- If bus/slot is not specified, the first supported
- PCI device found will be used.
+The FPGA on the board requires fimware, which is available from
+http://www.comedi.org in the comedi_nonfree_firmware tarball.
+
+Configuration options: not applicable, uses PCI auto config
*/
/*
This card was obviously never intended to leave the Windows world,
@@ -117,17 +111,17 @@ Configuration options:
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/firmware.h>
#include "8255.h"
+#define DAQBOARD2000_FIRMWARE "daqboard2000_firmware.bin"
+
#define PCI_VENDOR_ID_IOTECH 0x1616
#define DAQBOARD2000_SUBSYSTEM_IDS2 0x0002 /* Daqboard/2000 - 2 Dacs */
#define DAQBOARD2000_SUBSYSTEM_IDS4 0x0004 /* Daqboard/2000 - 4 Dacs */
-#define DAQBOARD2000_DAQ_SIZE 0x1002
-#define DAQBOARD2000_PLX_SIZE 0x100
-
/* Initialization bits for the Serial EEPROM Control Register */
#define DAQBOARD2000_SECRProgPinHi 0x8001767e
#define DAQBOARD2000_SECRProgPinLo 0x8000767e
@@ -143,85 +137,56 @@ Configuration options:
#define DAQBOARD2000_CPLD_INIT 0x0002
#define DAQBOARD2000_CPLD_DONE 0x0004
-/* Available ranges */
-static const struct comedi_lrange range_daqboard2000_ai = { 13, {
- RANGE(-10, 10),
- RANGE(-5, 5),
- RANGE(-2.5,
- 2.5),
- RANGE(-1.25,
- 1.25),
- RANGE(-0.625,
- 0.625),
- RANGE(-0.3125,
- 0.3125),
- RANGE(-0.156,
- 0.156),
- RANGE(0, 10),
- RANGE(0, 5),
- RANGE(0, 2.5),
- RANGE(0, 1.25),
- RANGE(0,
- 0.625),
- RANGE(0,
- 0.3125)
- }
-};
-
-static const struct comedi_lrange range_daqboard2000_ao = { 1, {
- RANGE(-10, 10)
- }
+static const struct comedi_lrange range_daqboard2000_ai = {
+ 13, {
+ BIP_RANGE(10),
+ BIP_RANGE(5),
+ BIP_RANGE(2.5),
+ BIP_RANGE(1.25),
+ BIP_RANGE(0.625),
+ BIP_RANGE(0.3125),
+ BIP_RANGE(0.156),
+ UNI_RANGE(10),
+ UNI_RANGE(5),
+ UNI_RANGE(2.5),
+ UNI_RANGE(1.25),
+ UNI_RANGE(0.625),
+ UNI_RANGE(0.3125)
+ }
};
-struct daqboard2000_hw {
- volatile u16 acqControl; /* 0x00 */
- volatile u16 acqScanListFIFO; /* 0x02 */
- volatile u32 acqPacerClockDivLow; /* 0x04 */
-
- volatile u16 acqScanCounter; /* 0x08 */
- volatile u16 acqPacerClockDivHigh; /* 0x0a */
- volatile u16 acqTriggerCount; /* 0x0c */
- volatile u16 fill2; /* 0x0e */
- volatile u16 acqResultsFIFO; /* 0x10 */
- volatile u16 fill3; /* 0x12 */
- volatile u16 acqResultsShadow; /* 0x14 */
- volatile u16 fill4; /* 0x16 */
- volatile u16 acqAdcResult; /* 0x18 */
- volatile u16 fill5; /* 0x1a */
- volatile u16 dacScanCounter; /* 0x1c */
- volatile u16 fill6; /* 0x1e */
-
- volatile u16 dacControl; /* 0x20 */
- volatile u16 fill7; /* 0x22 */
- volatile s16 dacFIFO; /* 0x24 */
- volatile u16 fill8[2]; /* 0x26 */
- volatile u16 dacPacerClockDiv; /* 0x2a */
- volatile u16 refDacs; /* 0x2c */
- volatile u16 fill9; /* 0x2e */
-
- volatile u16 dioControl; /* 0x30 */
- volatile s16 dioP3hsioData; /* 0x32 */
- volatile u16 dioP3Control; /* 0x34 */
- volatile u16 calEepromControl; /* 0x36 */
- volatile s16 dacSetting[4]; /* 0x38 */
- volatile s16 dioP2ExpansionIO8Bit[32]; /* 0x40 */
-
- volatile u16 ctrTmrControl; /* 0x80 */
- volatile u16 fill10[3]; /* 0x82 */
- volatile s16 ctrInput[4]; /* 0x88 */
- volatile u16 fill11[8]; /* 0x90 */
- volatile u16 timerDivisor[2]; /* 0xa0 */
- volatile u16 fill12[6]; /* 0xa4 */
-
- volatile u16 dmaControl; /* 0xb0 */
- volatile u16 trigControl; /* 0xb2 */
- volatile u16 fill13[2]; /* 0xb4 */
- volatile u16 calEeprom; /* 0xb8 */
- volatile u16 acqDigitalMark; /* 0xba */
- volatile u16 trigDacs; /* 0xbc */
- volatile u16 fill14; /* 0xbe */
- volatile s16 dioP2ExpansionIO16Bit[32]; /* 0xc0 */
-};
+/*
+ * Register Memory Map
+ */
+#define acqControl 0x00 /* u16 */
+#define acqScanListFIFO 0x02 /* u16 */
+#define acqPacerClockDivLow 0x04 /* u32 */
+#define acqScanCounter 0x08 /* u16 */
+#define acqPacerClockDivHigh 0x0a /* u16 */
+#define acqTriggerCount 0x0c /* u16 */
+#define acqResultsFIFO 0x10 /* u16 */
+#define acqResultsShadow 0x14 /* u16 */
+#define acqAdcResult 0x18 /* u16 */
+#define dacScanCounter 0x1c /* u16 */
+#define dacControl 0x20 /* u16 */
+#define dacFIFO 0x24 /* s16 */
+#define dacPacerClockDiv 0x2a /* u16 */
+#define refDacs 0x2c /* u16 */
+#define dioControl 0x30 /* u16 */
+#define dioP3hsioData 0x32 /* s16 */
+#define dioP3Control 0x34 /* u16 */
+#define calEepromControl 0x36 /* u16 */
+#define dacSetting(x) (0x38 + (x)*2) /* s16 */
+#define dioP2ExpansionIO8Bit 0x40 /* s16 */
+#define ctrTmrControl 0x80 /* u16 */
+#define ctrInput(x) (0x88 + (x)*2) /* s16 */
+#define timerDivisor(x) (0xa0 + (x)*2) /* u16 */
+#define dmaControl 0xb0 /* u16 */
+#define trigControl 0xb2 /* u16 */
+#define calEeprom 0xb8 /* u16 */
+#define acqDigitalMark 0xba /* u16 */
+#define trigDacs 0xbc /* u16 */
+#define dioP2ExpansionIO16Bit(x) (0xc0 + (x)*2) /* s16 */
/* Scan Sequencer programming */
#define DAQBOARD2000_SeqStartScanList 0x0011
@@ -311,27 +276,23 @@ static const struct daq200_boardtype boardtypes[] = {
{"ids4", DAQBOARD2000_SUBSYSTEM_IDS4},
};
-#define this_board ((const struct daq200_boardtype *)dev->board_ptr)
-
struct daqboard2000_private {
enum {
card_daqboard_2000
} card;
- void *daq;
+ void __iomem *daq;
void __iomem *plx;
unsigned int ao_readback[2];
};
-#define devpriv ((struct daqboard2000_private *)dev->private)
-
static void writeAcqScanListEntry(struct comedi_device *dev, u16 entry)
{
- struct daqboard2000_hw *fpga = devpriv->daq;
+ struct daqboard2000_private *devpriv = dev->private;
-/* udelay(4); */
- fpga->acqScanListFIFO = entry & 0x00ff;
-/* udelay(4); */
- fpga->acqScanListFIFO = (entry >> 8) & 0x00ff;
+ /* udelay(4); */
+ writew(entry & 0x00ff, devpriv->daq + acqScanListFIFO);
+ /* udelay(4); */
+ writew((entry >> 8) & 0x00ff, devpriv->daq + acqScanListFIFO);
}
static void setup_sampling(struct comedi_device *dev, int chan, int gain)
@@ -372,7 +333,6 @@ static void setup_sampling(struct comedi_device *dev, int chan, int gain)
/* These should be read from EEPROM */
word2 |= 0x0800;
word3 |= 0xc000;
-/* printk("%d %4.4x %4.4x %4.4x %4.4x\n", chan, word0, word1, word2, word3);*/
writeAcqScanListEntry(dev, word0);
writeAcqScanListEntry(dev, word1);
writeAcqScanListEntry(dev, word2);
@@ -384,21 +344,22 @@ static int daqboard2000_ai_insn_read(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- int i;
- struct daqboard2000_hw *fpga = devpriv->daq;
+ struct daqboard2000_private *devpriv = dev->private;
+ unsigned int val;
int gain, chan, timeout;
+ int i;
- fpga->acqControl =
- DAQBOARD2000_AcqResetScanListFifo |
- DAQBOARD2000_AcqResetResultsFifo | DAQBOARD2000_AcqResetConfigPipe;
+ writew(DAQBOARD2000_AcqResetScanListFifo |
+ DAQBOARD2000_AcqResetResultsFifo |
+ DAQBOARD2000_AcqResetConfigPipe, devpriv->daq + acqControl);
/*
* If pacer clock is not set to some high value (> 10 us), we
* risk multiple samples to be put into the result FIFO.
*/
/* 1 second, should be long enough */
- fpga->acqPacerClockDivLow = 1000000;
- fpga->acqPacerClockDivHigh = 0;
+ writel(1000000, devpriv->daq + acqPacerClockDivLow);
+ writew(0, devpriv->daq + acqPacerClockDivHigh);
gain = CR_RANGE(insn->chanspec);
chan = CR_CHAN(insn->chanspec);
@@ -410,28 +371,30 @@ static int daqboard2000_ai_insn_read(struct comedi_device *dev,
for (i = 0; i < insn->n; i++) {
setup_sampling(dev, chan, gain);
/* Enable reading from the scanlist FIFO */
- fpga->acqControl = DAQBOARD2000_SeqStartScanList;
+ writew(DAQBOARD2000_SeqStartScanList,
+ devpriv->daq + acqControl);
for (timeout = 0; timeout < 20; timeout++) {
- if (fpga->acqControl & DAQBOARD2000_AcqConfigPipeFull)
+ val = readw(devpriv->daq + acqControl);
+ if (val & DAQBOARD2000_AcqConfigPipeFull)
break;
/* udelay(2); */
}
- fpga->acqControl = DAQBOARD2000_AdcPacerEnable;
+ writew(DAQBOARD2000_AdcPacerEnable, devpriv->daq + acqControl);
for (timeout = 0; timeout < 20; timeout++) {
- if (fpga->acqControl & DAQBOARD2000_AcqLogicScanning)
+ val = readw(devpriv->daq + acqControl);
+ if (val & DAQBOARD2000_AcqLogicScanning)
break;
/* udelay(2); */
}
for (timeout = 0; timeout < 20; timeout++) {
- if (fpga->acqControl &
- DAQBOARD2000_AcqResultsFIFOHasValidData) {
+ val = readw(devpriv->daq + acqControl);
+ if (val & DAQBOARD2000_AcqResultsFIFOHasValidData)
break;
- }
/* udelay(2); */
}
- data[i] = fpga->acqResultsFIFO;
- fpga->acqControl = DAQBOARD2000_AdcPacerDisable;
- fpga->acqControl = DAQBOARD2000_SeqStopScanList;
+ data[i] = readw(devpriv->daq + acqResultsFIFO);
+ writew(DAQBOARD2000_AdcPacerDisable, devpriv->daq + acqControl);
+ writew(DAQBOARD2000_SeqStopScanList, devpriv->daq + acqControl);
}
return i;
@@ -442,8 +405,9 @@ static int daqboard2000_ao_insn_read(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- int i;
+ struct daqboard2000_private *devpriv = dev->private;
int chan = CR_CHAN(insn->chanspec);
+ int i;
for (i = 0; i < insn->n; i++)
data[i] = devpriv->ao_readback[chan];
@@ -456,28 +420,39 @@ static int daqboard2000_ao_insn_write(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- int i;
+ struct daqboard2000_private *devpriv = dev->private;
int chan = CR_CHAN(insn->chanspec);
- struct daqboard2000_hw *fpga = devpriv->daq;
+ unsigned int val;
int timeout;
+ int i;
for (i = 0; i < insn->n; i++) {
+#if 0
/*
- * OK, since it works OK without enabling the DAC's, let's keep
- * it as simple as possible...
+ * OK, since it works OK without enabling the DAC's,
+ * let's keep it as simple as possible...
*/
- /* fpga->dacControl = (chan + 2) * 0x0010 | 0x0001; udelay(1000); */
- fpga->dacSetting[chan] = data[i];
+ writew((chan + 2) * 0x0010 | 0x0001,
+ devpriv->daq + dacControl);
+ udelay(1000);
+#endif
+ writew(data[i], devpriv->daq + dacSetting(chan));
for (timeout = 0; timeout < 20; timeout++) {
- if ((fpga->dacControl & ((chan + 1) * 0x0010)) == 0)
+ val = readw(devpriv->daq + dacControl);
+ if ((val & ((chan + 1) * 0x0010)) == 0)
break;
/* udelay(2); */
}
devpriv->ao_readback[chan] = data[i];
+#if 0
/*
- * Since we never enabled the DAC's, we don't need to disable it...
- * fpga->dacControl = (chan + 2) * 0x0010 | 0x0000; udelay(1000);
+ * Since we never enabled the DAC's, we don't need
+ * to disable it...
*/
+ writew((chan + 2) * 0x0010 | 0x0000,
+ devpriv->daq + dacControl);
+ udelay(1000);
+#endif
}
return i;
@@ -485,7 +460,8 @@ static int daqboard2000_ao_insn_write(struct comedi_device *dev,
static void daqboard2000_resetLocalBus(struct comedi_device *dev)
{
- dev_dbg(dev->class_dev, "daqboard2000_resetLocalBus\n");
+ struct daqboard2000_private *devpriv = dev->private;
+
writel(DAQBOARD2000_SECRLocalBusHi, devpriv->plx + 0x6c);
udelay(10000);
writel(DAQBOARD2000_SECRLocalBusLo, devpriv->plx + 0x6c);
@@ -494,7 +470,8 @@ static void daqboard2000_resetLocalBus(struct comedi_device *dev)
static void daqboard2000_reloadPLX(struct comedi_device *dev)
{
- dev_dbg(dev->class_dev, "daqboard2000_reloadPLX\n");
+ struct daqboard2000_private *devpriv = dev->private;
+
writel(DAQBOARD2000_SECRReloadLo, devpriv->plx + 0x6c);
udelay(10000);
writel(DAQBOARD2000_SECRReloadHi, devpriv->plx + 0x6c);
@@ -505,7 +482,8 @@ static void daqboard2000_reloadPLX(struct comedi_device *dev)
static void daqboard2000_pulseProgPin(struct comedi_device *dev)
{
- dev_dbg(dev->class_dev, "daqboard2000_pulseProgPin 1\n");
+ struct daqboard2000_private *devpriv = dev->private;
+
writel(DAQBOARD2000_SECRProgPinHi, devpriv->plx + 0x6c);
udelay(10000);
writel(DAQBOARD2000_SECRProgPinLo, devpriv->plx + 0x6c);
@@ -514,6 +492,7 @@ static void daqboard2000_pulseProgPin(struct comedi_device *dev)
static int daqboard2000_pollCPLD(struct comedi_device *dev, int mask)
{
+ struct daqboard2000_private *devpriv = dev->private;
int result = 0;
int i;
int cpld;
@@ -533,6 +512,7 @@ static int daqboard2000_pollCPLD(struct comedi_device *dev, int mask)
static int daqboard2000_writeCPLD(struct comedi_device *dev, int data)
{
+ struct daqboard2000_private *devpriv = dev->private;
int result = 0;
udelay(10);
@@ -545,41 +525,29 @@ static int daqboard2000_writeCPLD(struct comedi_device *dev, int data)
}
static int initialize_daqboard2000(struct comedi_device *dev,
- unsigned char *cpld_array, int len)
+ const u8 *cpld_array, size_t len)
{
+ struct daqboard2000_private *devpriv = dev->private;
int result = -EIO;
/* Read the serial EEPROM control register */
int secr;
int retry;
- int i;
+ size_t i;
/* Check to make sure the serial eeprom is present on the board */
secr = readl(devpriv->plx + 0x6c);
- if (!(secr & DAQBOARD2000_EEPROM_PRESENT)) {
-#ifdef DEBUG_EEPROM
- dev_dbg(dev->class_dev, "no serial eeprom\n");
-#endif
+ if (!(secr & DAQBOARD2000_EEPROM_PRESENT))
return -EIO;
- }
for (retry = 0; retry < 3; retry++) {
-#ifdef DEBUG_EEPROM
- dev_dbg(dev->class_dev, "Programming EEPROM try %x\n", retry);
-#endif
-
daqboard2000_resetLocalBus(dev);
daqboard2000_reloadPLX(dev);
daqboard2000_pulseProgPin(dev);
if (daqboard2000_pollCPLD(dev, DAQBOARD2000_CPLD_INIT)) {
for (i = 0; i < len; i++) {
- if (cpld_array[i] == 0xff
- && cpld_array[i + 1] == 0x20) {
-#ifdef DEBUG_EEPROM
- dev_dbg(dev->class_dev,
- "Preamble found at %d\n", i);
-#endif
+ if (cpld_array[i] == 0xff &&
+ cpld_array[i + 1] == 0x20)
break;
- }
}
for (; i < len; i += 2) {
int data =
@@ -588,9 +556,6 @@ static int initialize_daqboard2000(struct comedi_device *dev,
break;
}
if (i >= len) {
-#ifdef DEBUG_EEPROM
- dev_dbg(dev->class_dev, "Programmed\n");
-#endif
daqboard2000_resetLocalBus(dev);
daqboard2000_reloadPLX(dev);
result = 0;
@@ -601,28 +566,45 @@ 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)
{
-/* printk("Implement: daqboard2000_adcStopDmaTransfer\n");*/
}
static void daqboard2000_adcDisarm(struct comedi_device *dev)
{
- struct daqboard2000_hw *fpga = devpriv->daq;
+ struct daqboard2000_private *devpriv = dev->private;
/* Disable hardware triggers */
udelay(2);
- fpga->trigControl = DAQBOARD2000_TrigAnalog | DAQBOARD2000_TrigDisable;
+ writew(DAQBOARD2000_TrigAnalog | DAQBOARD2000_TrigDisable,
+ devpriv->daq + trigControl);
udelay(2);
- fpga->trigControl = DAQBOARD2000_TrigTTL | DAQBOARD2000_TrigDisable;
+ writew(DAQBOARD2000_TrigTTL | DAQBOARD2000_TrigDisable,
+ devpriv->daq + trigControl);
/* Stop the scan list FIFO from loading the configuration pipe */
udelay(2);
- fpga->acqControl = DAQBOARD2000_SeqStopScanList;
+ writew(DAQBOARD2000_SeqStopScanList, devpriv->daq + acqControl);
/* Stop the pacer clock */
udelay(2);
- fpga->acqControl = DAQBOARD2000_AdcPacerDisable;
+ writew(DAQBOARD2000_AdcPacerDisable, devpriv->daq + acqControl);
/* Stop the input dma (abort channel 1) */
daqboard2000_adcStopDmaTransfer(dev);
@@ -630,41 +612,39 @@ static void daqboard2000_adcDisarm(struct comedi_device *dev)
static void daqboard2000_activateReferenceDacs(struct comedi_device *dev)
{
- struct daqboard2000_hw *fpga = devpriv->daq;
+ struct daqboard2000_private *devpriv = dev->private;
+ unsigned int val;
int timeout;
/* Set the + reference dac value in the FPGA */
- fpga->refDacs = 0x80 | DAQBOARD2000_PosRefDacSelect;
+ writew(0x80 | DAQBOARD2000_PosRefDacSelect, devpriv->daq + refDacs);
for (timeout = 0; timeout < 20; timeout++) {
- if ((fpga->dacControl & DAQBOARD2000_RefBusy) == 0)
+ val = readw(devpriv->daq + dacControl);
+ if ((val & DAQBOARD2000_RefBusy) == 0)
break;
udelay(2);
}
-/* printk("DAQBOARD2000_PosRefDacSelect %d\n", timeout);*/
/* Set the - reference dac value in the FPGA */
- fpga->refDacs = 0x80 | DAQBOARD2000_NegRefDacSelect;
+ writew(0x80 | DAQBOARD2000_NegRefDacSelect, devpriv->daq + refDacs);
for (timeout = 0; timeout < 20; timeout++) {
- if ((fpga->dacControl & DAQBOARD2000_RefBusy) == 0)
+ val = readw(devpriv->daq + dacControl);
+ if ((val & DAQBOARD2000_RefBusy) == 0)
break;
udelay(2);
}
-/* printk("DAQBOARD2000_NegRefDacSelect %d\n", timeout);*/
}
static void daqboard2000_initializeCtrs(struct comedi_device *dev)
{
-/* printk("Implement: daqboard2000_initializeCtrs\n");*/
}
static void daqboard2000_initializeTmrs(struct comedi_device *dev)
{
-/* printk("Implement: daqboard2000_initializeTmrs\n");*/
}
static void daqboard2000_dacDisarm(struct comedi_device *dev)
{
-/* printk("Implement: daqboard2000_dacDisarm\n");*/
}
static void daqboard2000_initializeAdc(struct comedi_device *dev)
@@ -680,92 +660,66 @@ static void daqboard2000_initializeDac(struct comedi_device *dev)
daqboard2000_dacDisarm(dev);
}
-/*
-The test command, REMOVE!!:
-
-rmmod daqboard2000 ; rmmod comedi; make install ; modprobe daqboard2000; /usr/sbin/comedi_config /dev/comedi0 daqboard/2000 ; tail -40 /var/log/messages
-*/
-
static int daqboard2000_8255_cb(int dir, int port, int data,
unsigned long ioaddr)
{
- int result = 0;
+ void __iomem *mmio_base = (void __iomem *)ioaddr;
+
if (dir) {
- writew(data, ((void *)ioaddr) + port * 2);
- result = 0;
+ writew(data, mmio_base + port * 2);
+ return 0;
} else {
- result = readw(((void *)ioaddr) + port * 2);
+ return readw(mmio_base + port * 2);
}
-/*
- printk("daqboard2000_8255_cb %x %d %d %2.2x -> %2.2x\n",
- arg, dir, port, data, result);
-*/
- return result;
}
-static struct pci_dev *daqboard2000_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static const void *daqboard2000_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
+ const struct daq200_boardtype *board;
int i;
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (bus != pcidev->bus->number ||
- slot != PCI_SLOT(pcidev->devfn))
- continue;
- }
- if (pcidev->vendor != PCI_VENDOR_ID_IOTECH ||
- pcidev->device != 0x0409 ||
- pcidev->subsystem_device != PCI_VENDOR_ID_IOTECH)
- continue;
-
- for (i = 0; i < ARRAY_SIZE(boardtypes); i++) {
- if (boardtypes[i].id != pcidev->subsystem_device)
- continue;
- dev->board_ptr = boardtypes + i;
- return pcidev;
- }
+ if (pcidev->subsystem_device != PCI_VENDOR_ID_IOTECH)
+ return NULL;
+
+ for (i = 0; i < ARRAY_SIZE(boardtypes); i++) {
+ board = &boardtypes[i];
+ if (pcidev->subsystem_device == board->id)
+ return board;
}
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
return NULL;
}
-static int daqboard2000_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int daqboard2000_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev;
+ const struct daq200_boardtype *board;
+ struct daqboard2000_private *devpriv;
struct comedi_subdevice *s;
- resource_size_t pci_base;
- void *aux_data;
- unsigned int aux_len;
int result;
- result = alloc_private(dev, sizeof(struct daqboard2000_private));
+ comedi_set_hw_dev(dev, &pcidev->dev);
+
+ board = daqboard2000_find_boardinfo(dev, pcidev);
+ if (!board)
+ return -ENODEV;
+ dev->board_ptr = board;
+ dev->board_name = board->name;
+
+ result = alloc_private(dev, sizeof(*devpriv));
if (result < 0)
return -ENOMEM;
+ devpriv = dev->private;
- pcidev = daqboard2000_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
-
- result = comedi_pci_enable(pcidev, "daqboard2000");
- if (result < 0) {
- dev_err(dev->class_dev,
- "failed to enable PCI device and request regions\n");
- return -EIO;
- }
+ result = comedi_pci_enable(pcidev, dev->driver->driver_name);
+ if (result < 0)
+ return result;
dev->iobase = 1; /* the "detach" needs this */
- pci_base = pci_resource_start(pcidev, 0);
- devpriv->plx = ioremap(pci_base, DAQBOARD2000_PLX_SIZE);
- pci_base = pci_resource_start(pcidev, 2);
- devpriv->daq = ioremap(pci_base, DAQBOARD2000_DAQ_SIZE);
+ devpriv->plx = ioremap(pci_resource_start(pcidev, 0),
+ pci_resource_len(pcidev, 0));
+ devpriv->daq = ioremap(pci_resource_start(pcidev, 2),
+ pci_resource_len(pcidev, 2));
if (!devpriv->plx || !devpriv->daq)
return -ENOMEM;
@@ -775,36 +729,14 @@ static int daqboard2000_attach(struct comedi_device *dev,
readl(devpriv->plx + 0x6c);
- /*
- u8 interrupt;
- Windows code does restore interrupts, but since we don't use them...
- pci_read_config_byte(pcidev, PCI_INTERRUPT_LINE, &interrupt);
- printk("Interrupt before is: %x\n", interrupt);
- */
-
- aux_data = comedi_aux_data(it->options, 0);
- aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH];
-
- if (aux_data && aux_len) {
- result = initialize_daqboard2000(dev, aux_data, aux_len);
- } else {
- dev_dbg(dev->class_dev,
- "no FPGA initialization code, aborting\n");
- result = -EIO;
- }
+ result = daqboard2000_upload_firmware(dev);
if (result < 0)
- goto out;
+ return result;
+
daqboard2000_initializeAdc(dev);
daqboard2000_initializeDac(dev);
- /*
- Windows code does restore interrupts, but since we don't use them...
- pci_read_config_byte(pcidev, PCI_INTERRUPT_LINE, &interrupt);
- printk("Interrupt after is: %x\n", interrupt);
- */
-
- dev->board_name = this_board->name;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* ai subdevice */
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_GROUND;
@@ -813,7 +745,7 @@ static int daqboard2000_attach(struct comedi_device *dev,
s->insn_read = daqboard2000_ai_insn_read;
s->range_table = &range_daqboard2000_ai;
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* ao subdevice */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
@@ -821,22 +753,27 @@ static int daqboard2000_attach(struct comedi_device *dev,
s->maxdata = 0xffff;
s->insn_read = daqboard2000_ao_insn_read;
s->insn_write = daqboard2000_ao_insn_write;
- s->range_table = &range_daqboard2000_ao;
+ s->range_table = &range_bipolar10;
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
result = subdev_8255_init(dev, s, daqboard2000_8255_cb,
- (unsigned long)(devpriv->daq + 0x40));
+ (unsigned long)(devpriv->daq + dioP2ExpansionIO8Bit));
+ if (result)
+ return result;
-out:
- return result;
+ dev_info(dev->class_dev, "%s: %s attached\n",
+ dev->driver->driver_name, dev->board_name);
+
+ return 0;
}
static void daqboard2000_detach(struct comedi_device *dev)
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ struct daqboard2000_private *devpriv = dev->private;
if (dev->subdevices)
- subdev_8255_cleanup(dev, dev->subdevices + 2);
+ subdev_8255_cleanup(dev, &dev->subdevices[2]);
if (dev->irq)
free_irq(dev->irq, dev);
if (devpriv) {
@@ -855,7 +792,7 @@ static void daqboard2000_detach(struct comedi_device *dev)
static struct comedi_driver daqboard2000_driver = {
.driver_name = "daqboard2000",
.module = THIS_MODULE,
- .attach = daqboard2000_attach,
+ .attach_pci = daqboard2000_attach_pci,
.detach = daqboard2000_detach,
};
@@ -887,3 +824,4 @@ module_comedi_pci_driver(daqboard2000_driver, daqboard2000_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(DAQBOARD2000_FIRMWARE);
diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
index 874e02e47668..5fd21fa6c1c7 100644
--- a/drivers/staging/comedi/drivers/das08.c
+++ b/drivers/staging/comedi/drivers/das08.c
@@ -32,8 +32,9 @@
* [ComputerBoards] DAS08 (isa-das08), DAS08-PGM (das08-pgm),
* DAS08-PGH (das08-pgh), DAS08-PGL (das08-pgl), DAS08-AOH (das08-aoh),
* DAS08-AOL (das08-aol), DAS08-AOM (das08-aom), DAS08/JR-AO (das08/jr-ao),
- * DAS08/JR-16-AO (das08jr-16-ao), PCI-DAS08 (pci-das08 or das08),
+ * DAS08/JR-16-AO (das08jr-16-ao), PCI-DAS08 (pci-das08),
* PC104-DAS08 (pc104-das08), DAS08/JR/16 (das08jr/16)
+ * Updated: Fri, 31 Aug 2012 19:19:06 +0100
* Status: works
*
* This is a rewrite of the das08 and das08jr drivers.
@@ -41,9 +42,8 @@
* Options (for ISA cards):
* [0] - base io address
*
- * Options (for pci-das08):
- * [0] - bus (optional)
- * [1] = slot (optional)
+ * Manual configuration of PCI cards is not supported; they are
+ * configured automatically.
*
* The das08 driver doesn't support asynchronous commands, since
* the cheap das08 hardware doesn't really support them. The
@@ -61,9 +61,9 @@
#define DRV_NAME "das08"
-#define DO_COMEDI_DRIVER_REGISTER \
- (IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) || \
- IS_ENABLED(CONFIG_COMEDI_DAS08_PCI))
+#define DO_ISA IS_ENABLED(CONFIG_COMEDI_DAS08_ISA)
+#define DO_PCI IS_ENABLED(CONFIG_COMEDI_DAS08_PCI)
+#define DO_COMEDI_DRIVER_REGISTER (DO_ISA || DO_PCI)
#define PCI_VENDOR_ID_COMPUTERBOARDS 0x1307
#define PCI_DEVICE_ID_PCIDAS08 0x29
@@ -236,6 +236,16 @@ static const int *const das08_gainlists[] = {
das08_pgm_gainlist,
};
+static inline bool is_isa_board(const struct das08_board_struct *board)
+{
+ return DO_ISA && board->bustype == isa;
+}
+
+static inline bool is_pci_board(const struct das08_board_struct *board)
+{
+ return DO_PCI && board->bustype == pci;
+}
+
#define TIMEOUT 100000
static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
@@ -342,9 +352,9 @@ static int das08_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
return insn->n;
}
-static int __maybe_unused
-das08jr_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int das08jr_di_rbits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
{
data[0] = 0;
data[1] = inb(dev->iobase + DAS08JR_DIO);
@@ -352,9 +362,9 @@ das08jr_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
return insn->n;
}
-static int __maybe_unused
-das08jr_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int das08jr_do_wbits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
{
struct das08_private_struct *devpriv = dev->private;
@@ -369,88 +379,92 @@ das08jr_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
return insn->n;
}
-static int __maybe_unused
-das08jr_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static void das08_ao_set_data(struct comedi_device *dev,
+ unsigned int chan, unsigned int data)
{
- int n;
- int lsb, msb;
- int chan;
-
- lsb = data[0] & 0xff;
- msb = (data[0] >> 8) & 0xf;
-
- chan = CR_CHAN(insn->chanspec);
+ const struct das08_board_struct *thisboard = comedi_board(dev);
+ struct das08_private_struct *devpriv = dev->private;
+ unsigned char lsb;
+ unsigned char msb;
- for (n = 0; n < insn->n; n++) {
-#if 0
- outb(lsb, dev->iobase + devpriv->ao_offset_lsb[chan]);
- outb(msb, dev->iobase + devpriv->ao_offset_msb[chan]);
-#else
+ lsb = data & 0xff;
+ msb = (data >> 8) & 0xff;
+ if (thisboard->is_jr) {
outb(lsb, dev->iobase + DAS08JR_AO_LSB(chan));
outb(msb, dev->iobase + DAS08JR_AO_MSB(chan));
-#endif
-
/* load DACs */
inb(dev->iobase + DAS08JR_DIO);
+ } else {
+ outb(lsb, dev->iobase + DAS08AO_AO_LSB(chan));
+ outb(msb, dev->iobase + DAS08AO_AO_MSB(chan));
+ /* load DACs */
+ inb(dev->iobase + DAS08AO_AO_UPDATE);
}
-
- return n;
+ devpriv->ao_readback[chan] = data;
}
-/*
- *
- * The -aox boards have the DACs at a different offset and use
- * a different method to force an update.
- *
- */
-static int __maybe_unused
-das08ao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static void das08_ao_initialize(struct comedi_device *dev,
+ struct comedi_subdevice *s)
{
int n;
- int lsb, msb;
- int chan;
+ unsigned int data;
- lsb = data[0] & 0xff;
- msb = (data[0] >> 8) & 0xf;
+ data = s->maxdata / 2; /* should be about 0 volts */
+ for (n = 0; n < s->n_chan; n++)
+ das08_ao_set_data(dev, n, data);
+}
+
+static int das08_ao_winsn(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+ unsigned int n;
+ unsigned int chan;
chan = CR_CHAN(insn->chanspec);
- for (n = 0; n < insn->n; n++) {
-#if 0
- outb(lsb, dev->iobase + devpriv->ao_offset_lsb[chan]);
- outb(msb, dev->iobase + devpriv->ao_offset_msb[chan]);
-#else
- outb(lsb, dev->iobase + DAS08AO_AO_LSB(chan));
- outb(msb, dev->iobase + DAS08AO_AO_MSB(chan));
-#endif
+ for (n = 0; n < insn->n; n++)
+ das08_ao_set_data(dev, chan, *data);
- /* load DACs */
- inb(dev->iobase + DAS08AO_AO_UPDATE);
- }
+ return n;
+}
+
+static int das08_ao_rinsn(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+ struct das08_private_struct *devpriv = dev->private;
+ unsigned int n;
+ unsigned int chan;
+
+ chan = CR_CHAN(insn->chanspec);
+
+ for (n = 0; n < insn->n; n++)
+ data[n] = devpriv->ao_readback[chan];
return n;
}
static void i8254_initialize(struct comedi_device *dev)
{
- struct das08_private_struct *devpriv = dev->private;
+ const struct das08_board_struct *thisboard = comedi_board(dev);
+ unsigned long i8254_iobase = dev->iobase + thisboard->i8254_offset;
unsigned int mode = I8254_MODE0 | I8254_BINARY;
int i;
for (i = 0; i < 3; ++i)
- i8254_set_mode(devpriv->i8254_iobase, 0, i, mode);
+ i8254_set_mode(i8254_iobase, 0, i, mode);
}
static int das08_counter_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
- struct das08_private_struct *devpriv = dev->private;
+ const struct das08_board_struct *thisboard = comedi_board(dev);
+ unsigned long i8254_iobase = dev->iobase + thisboard->i8254_offset;
int chan = insn->chanspec;
- data[0] = i8254_read(devpriv->i8254_iobase, 0, chan);
+ data[0] = i8254_read(i8254_iobase, 0, chan);
return 1;
}
@@ -458,10 +472,11 @@ static int das08_counter_write(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
- struct das08_private_struct *devpriv = dev->private;
+ const struct das08_board_struct *thisboard = comedi_board(dev);
+ unsigned long i8254_iobase = dev->iobase + thisboard->i8254_offset;
int chan = insn->chanspec;
- i8254_write(devpriv->i8254_iobase, 0, chan, data[0]);
+ i8254_write(i8254_iobase, 0, chan, data[0]);
return 1;
}
@@ -469,18 +484,16 @@ static int das08_counter_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
- struct das08_private_struct *devpriv = dev->private;
+ const struct das08_board_struct *thisboard = comedi_board(dev);
+ unsigned long i8254_iobase = dev->iobase + thisboard->i8254_offset;
int chan = insn->chanspec;
- if (insn->n != 2)
- return -EINVAL;
-
switch (data[0]) {
case INSN_CONFIG_SET_COUNTER_MODE:
- i8254_set_mode(devpriv->i8254_iobase, 0, chan, data[1]);
+ i8254_set_mode(i8254_iobase, 0, chan, data[1]);
break;
case INSN_CONFIG_8254_READ_STATUS:
- data[1] = i8254_status(devpriv->i8254_iobase, 0, chan);
+ data[1] = i8254_status(i8254_iobase, 0, chan);
break;
default:
return -EINVAL;
@@ -491,18 +504,14 @@ static int das08_counter_config(struct comedi_device *dev,
#if DO_COMEDI_DRIVER_REGISTER
static const struct das08_board_struct das08_boards[] = {
-#if IS_ENABLED(CONFIG_COMEDI_DAS08_ISA)
+#if DO_ISA
{
.name = "isa-das08", /* cio-das08.pdf */
.bustype = isa,
- .ai = das08_ai_rinsn,
.ai_nbits = 12,
.ai_pg = das08_pg_none,
.ai_encoding = das08_encode12,
- .ao = NULL,
- .ao_nbits = 12,
- .di = das08_di_rbits,
- .do_ = das08_do_wbits,
+ .di_nchan = 3,
.do_nchan = 4,
.i8255_offset = 8,
.i8254_offset = 4,
@@ -511,13 +520,10 @@ static const struct das08_board_struct das08_boards[] = {
{
.name = "das08-pgm", /* cio-das08pgx.pdf */
.bustype = isa,
- .ai = das08_ai_rinsn,
.ai_nbits = 12,
.ai_pg = das08_pgm,
.ai_encoding = das08_encode12,
- .ao = NULL,
- .di = das08_di_rbits,
- .do_ = das08_do_wbits,
+ .di_nchan = 3,
.do_nchan = 4,
.i8255_offset = 0,
.i8254_offset = 0x04,
@@ -526,44 +532,33 @@ static const struct das08_board_struct das08_boards[] = {
{
.name = "das08-pgh", /* cio-das08pgx.pdf */
.bustype = isa,
- .ai = das08_ai_rinsn,
.ai_nbits = 12,
.ai_pg = das08_pgh,
.ai_encoding = das08_encode12,
- .ao = NULL,
- .di = das08_di_rbits,
- .do_ = das08_do_wbits,
+ .di_nchan = 3,
.do_nchan = 4,
- .i8255_offset = 0,
.i8254_offset = 0x04,
.iosize = 16, /* unchecked */
},
{
.name = "das08-pgl", /* cio-das08pgx.pdf */
.bustype = isa,
- .ai = das08_ai_rinsn,
.ai_nbits = 12,
.ai_pg = das08_pgl,
.ai_encoding = das08_encode12,
- .ao = NULL,
- .di = das08_di_rbits,
- .do_ = das08_do_wbits,
+ .di_nchan = 3,
.do_nchan = 4,
- .i8255_offset = 0,
.i8254_offset = 0x04,
.iosize = 16, /* unchecked */
},
{
.name = "das08-aoh", /* cio-das08_aox.pdf */
.bustype = isa,
- .ai = das08_ai_rinsn,
.ai_nbits = 12,
.ai_pg = das08_pgh,
.ai_encoding = das08_encode12,
- .ao = das08ao_ao_winsn, /* 8 */
.ao_nbits = 12,
- .di = das08_di_rbits,
- .do_ = das08_do_wbits,
+ .di_nchan = 3,
.do_nchan = 4,
.i8255_offset = 0x0c,
.i8254_offset = 0x04,
@@ -572,14 +567,11 @@ static const struct das08_board_struct das08_boards[] = {
{
.name = "das08-aol", /* cio-das08_aox.pdf */
.bustype = isa,
- .ai = das08_ai_rinsn,
.ai_nbits = 12,
.ai_pg = das08_pgl,
.ai_encoding = das08_encode12,
- .ao = das08ao_ao_winsn, /* 8 */
.ao_nbits = 12,
- .di = das08_di_rbits,
- .do_ = das08_do_wbits,
+ .di_nchan = 3,
.do_nchan = 4,
.i8255_offset = 0x0c,
.i8254_offset = 0x04,
@@ -588,14 +580,11 @@ static const struct das08_board_struct das08_boards[] = {
{
.name = "das08-aom", /* cio-das08_aox.pdf */
.bustype = isa,
- .ai = das08_ai_rinsn,
.ai_nbits = 12,
.ai_pg = das08_pgm,
.ai_encoding = das08_encode12,
- .ao = das08ao_ao_winsn, /* 8 */
.ao_nbits = 12,
- .di = das08_di_rbits,
- .do_ = das08_do_wbits,
+ .di_nchan = 3,
.do_nchan = 4,
.i8255_offset = 0x0c,
.i8254_offset = 0x04,
@@ -604,152 +593,68 @@ static const struct das08_board_struct das08_boards[] = {
{
.name = "das08/jr-ao", /* cio-das08-jr-ao.pdf */
.bustype = isa,
- .ai = das08_ai_rinsn,
+ .is_jr = true,
.ai_nbits = 12,
.ai_pg = das08_pg_none,
.ai_encoding = das08_encode12,
- .ao = das08jr_ao_winsn,
.ao_nbits = 12,
- .di = das08jr_di_rbits,
- .do_ = das08jr_do_wbits,
+ .di_nchan = 8,
.do_nchan = 8,
- .i8255_offset = 0,
- .i8254_offset = 0,
.iosize = 16, /* unchecked */
},
{
.name = "das08jr-16-ao", /* cio-das08jr-16-ao.pdf */
.bustype = isa,
- .ai = das08_ai_rinsn,
+ .is_jr = true,
.ai_nbits = 16,
.ai_pg = das08_pg_none,
- .ai_encoding = das08_encode12,
- .ao = das08jr_ao_winsn,
+ .ai_encoding = das08_encode16,
.ao_nbits = 16,
- .di = das08jr_di_rbits,
- .do_ = das08jr_do_wbits,
+ .di_nchan = 8,
.do_nchan = 8,
- .i8255_offset = 0,
.i8254_offset = 0x04,
.iosize = 16, /* unchecked */
},
{
.name = "pc104-das08",
- .bustype = pc104,
- .ai = das08_ai_rinsn,
+ .bustype = isa,
.ai_nbits = 12,
.ai_pg = das08_pg_none,
.ai_encoding = das08_encode12,
- .ao = NULL,
- .ao_nbits = 0,
- .di = das08_di_rbits,
- .do_ = das08_do_wbits,
+ .di_nchan = 3,
.do_nchan = 4,
- .i8255_offset = 0,
.i8254_offset = 4,
.iosize = 16, /* unchecked */
},
-#if 0
- {
- .name = "das08/f",
- },
- {
- .name = "das08jr",
- },
-#endif
{
.name = "das08jr/16",
.bustype = isa,
- .ai = das08_ai_rinsn,
+ .is_jr = true,
.ai_nbits = 16,
.ai_pg = das08_pg_none,
.ai_encoding = das08_encode16,
- .ao = NULL,
- .ao_nbits = 0,
- .di = das08jr_di_rbits,
- .do_ = das08jr_do_wbits,
+ .di_nchan = 8,
.do_nchan = 8,
- .i8255_offset = 0,
- .i8254_offset = 0,
.iosize = 16, /* unchecked */
},
-#if 0
- {
- .name = "das48-pga", /* cio-das48-pga.pdf */
- },
- {
- .name = "das08-pga-g2", /* a KM board */
- },
-#endif
-#endif /* IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) */
-#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI)
+#endif /* DO_ISA */
+#if DO_PCI
{
.name = "pci-das08", /* pci-das08 */
.id = PCI_DEVICE_ID_PCIDAS08,
.bustype = pci,
- .ai = das08_ai_rinsn,
.ai_nbits = 12,
.ai_pg = das08_bipolar5,
.ai_encoding = das08_encode12,
- .ao = NULL,
- .ao_nbits = 0,
- .di = das08_di_rbits,
- .do_ = das08_do_wbits,
+ .di_nchan = 3,
.do_nchan = 4,
- .i8255_offset = 0,
.i8254_offset = 4,
.iosize = 8,
},
- { /* wildcard entry matches any supported PCI device */
- .name = DRV_NAME,
- .id = PCI_ANY_ID,
- .bustype = pci,
- },
-#endif /* IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) */
+#endif /* DO_PCI */
};
#endif /* DO_COMEDI_DRIVER_REGISTER */
-#if IS_ENABLED(CONFIG_COMEDI_DAS08_CS)
-struct das08_board_struct das08_cs_boards[NUM_DAS08_CS_BOARDS] = {
- {
- .name = "pcm-das08",
- .id = 0x0, /* XXX */
- .bustype = pcmcia,
- .ai = das08_ai_rinsn,
- .ai_nbits = 12,
- .ai_pg = das08_bipolar5,
- .ai_encoding = das08_pcm_encode12,
- .ao = NULL,
- .ao_nbits = 0,
- .di = das08_di_rbits,
- .do_ = das08_do_wbits,
- .do_nchan = 3,
- .i8255_offset = 0,
- .i8254_offset = 0,
- .iosize = 16,
- },
- /* duplicate so driver name can be used also */
- {
- .name = "das08_cs",
- .id = 0x0, /* XXX */
- .bustype = pcmcia,
- .ai = das08_ai_rinsn,
- .ai_nbits = 12,
- .ai_pg = das08_bipolar5,
- .ai_encoding = das08_pcm_encode12,
- .ao = NULL,
- .ao_nbits = 0,
- .di = das08_di_rbits,
- .do_ = das08_do_wbits,
- .do_nchan = 3,
- .i8255_offset = 0,
- .i8254_offset = 0,
- .iosize = 16,
- },
-};
-EXPORT_SYMBOL_GPL(das08_cs_boards);
-#endif
-
int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
{
const struct das08_board_struct *thisboard = comedi_board(dev);
@@ -765,9 +670,9 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* ai */
- if (thisboard->ai) {
+ if (thisboard->ai_nbits) {
s->type = COMEDI_SUBD_AI;
/* XXX some boards actually have differential
* inputs instead of single ended.
@@ -778,53 +683,56 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
s->n_chan = 8;
s->maxdata = (1 << thisboard->ai_nbits) - 1;
s->range_table = das08_ai_lranges[thisboard->ai_pg];
- s->insn_read = thisboard->ai;
+ s->insn_read = das08_ai_rinsn;
devpriv->pg_gainlist = das08_gainlists[thisboard->ai_pg];
} else {
s->type = COMEDI_SUBD_UNUSED;
}
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* ao */
- if (thisboard->ao) {
+ if (thisboard->ao_nbits) {
s->type = COMEDI_SUBD_AO;
-/* XXX lacks read-back insn */
s->subdev_flags = SDF_WRITABLE;
s->n_chan = 2;
s->maxdata = (1 << thisboard->ao_nbits) - 1;
s->range_table = &range_bipolar5;
- s->insn_write = thisboard->ao;
+ s->insn_write = das08_ao_winsn;
+ s->insn_read = das08_ao_rinsn;
+ das08_ao_initialize(dev, s);
} else {
s->type = COMEDI_SUBD_UNUSED;
}
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
/* di */
- if (thisboard->di) {
+ if (thisboard->di_nchan) {
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
- s->n_chan = (thisboard->di == das08_di_rbits) ? 3 : 8;
+ s->n_chan = thisboard->di_nchan;
s->maxdata = 1;
s->range_table = &range_digital;
- s->insn_bits = thisboard->di;
+ s->insn_bits =
+ thisboard->is_jr ? das08jr_di_rbits : das08_di_rbits;
} else {
s->type = COMEDI_SUBD_UNUSED;
}
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
/* do */
- if (thisboard->do_) {
+ if (thisboard->do_nchan) {
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
s->n_chan = thisboard->do_nchan;
s->maxdata = 1;
s->range_table = &range_digital;
- s->insn_bits = thisboard->do_;
+ s->insn_bits =
+ thisboard->is_jr ? das08jr_do_wbits : das08_do_wbits;
} else {
s->type = COMEDI_SUBD_UNUSED;
}
- s = dev->subdevices + 4;
+ s = &dev->subdevices[4];
/* 8255 */
if (thisboard->i8255_offset != 0) {
subdev_8255_init(dev, s, NULL, (unsigned long)(dev->iobase +
@@ -834,7 +742,7 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
s->type = COMEDI_SUBD_UNUSED;
}
- s = dev->subdevices + 5;
+ s = &dev->subdevices[5];
/* 8254 */
if (thisboard->i8254_offset != 0) {
s->type = COMEDI_SUBD_COUNTER;
@@ -844,8 +752,6 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
s->insn_read = das08_counter_read;
s->insn_write = das08_counter_write;
s->insn_config = das08_counter_config;
-
- devpriv->i8254_iobase = iobase + thisboard->i8254_offset;
i8254_initialize(dev);
} else {
s->type = COMEDI_SUBD_UNUSED;
@@ -855,50 +761,13 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
}
EXPORT_SYMBOL_GPL(das08_common_attach);
-static int das08_pci_attach_common(struct comedi_device *dev,
- struct pci_dev *pdev)
-{
- unsigned long iobase;
- unsigned long pci_iobase;
- struct das08_private_struct *devpriv = dev->private;
-
- if (!IS_ENABLED(CONFIG_COMEDI_DAS08_PCI))
- return -EINVAL;
-
- devpriv->pdev = pdev;
- /* enable PCI device and reserve I/O spaces */
- if (comedi_pci_enable(pdev, dev->driver->driver_name)) {
- dev_err(dev->class_dev,
- "Error enabling PCI device and requesting regions\n");
- return -EIO;
- }
- /* read base addresses */
- pci_iobase = pci_resource_start(pdev, 1);
- iobase = pci_resource_start(pdev, 2);
- dev_info(dev->class_dev, "pcibase 0x%lx iobase 0x%lx\n",
- pci_iobase, iobase);
- devpriv->pci_iobase = pci_iobase;
-#if 0
- /* We could enable pci-das08's interrupt here to make it possible
- * to do timed input in this driver, but there is little point since
- * conversions would have to be started by the interrupt handler
- * so you might as well use comedi_rt_timer to emulate commands
- */
- /* set source of interrupt trigger to counter2 output */
- outb(CNTRL_INTR | CNTRL_DIR, pci_iobase + CNTRL);
- /* Enable local interrupt 1 and pci interrupt */
- outw(INTR1_ENABLE | PCI_INTR_ENABLE, pci_iobase + INTCSR);
-#endif
- return das08_common_attach(dev, iobase);
-}
-
static const struct das08_board_struct *
das08_find_pci_board(struct pci_dev *pdev)
{
#if DO_COMEDI_DRIVER_REGISTER
unsigned int i;
for (i = 0; i < ARRAY_SIZE(das08_boards); i++)
- if (das08_boards[i].bustype == pci &&
+ if (is_pci_board(&das08_boards[i]) &&
pdev->device == das08_boards[i].id)
return &das08_boards[i];
#endif
@@ -909,9 +778,10 @@ das08_find_pci_board(struct pci_dev *pdev)
static int __devinit __maybe_unused
das08_attach_pci(struct comedi_device *dev, struct pci_dev *pdev)
{
+ unsigned long iobase;
int ret;
- if (!IS_ENABLED(CONFIG_COMEDI_DAS08_PCI))
+ if (!DO_PCI)
return -EINVAL;
ret = alloc_private(dev, sizeof(struct das08_private_struct));
if (ret < 0)
@@ -922,58 +792,16 @@ das08_attach_pci(struct comedi_device *dev, struct pci_dev *pdev)
dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
return -EINVAL;
}
- return das08_pci_attach_common(dev, pdev);
-}
-
-static struct pci_dev *das08_find_pci(struct comedi_device *dev,
- int bus, int slot)
-{
- const struct das08_board_struct *thisboard = comedi_board(dev);
- struct pci_dev *pdev;
- unsigned int matchid;
-
- if (bus || slot)
- dev_dbg(dev->class_dev, "Looking for %s at PCI %02X:%02X\n",
- thisboard->name, bus, slot);
- else
- dev_dbg(dev->class_dev, "Looking for %s on PCI buses\n",
- thisboard->name);
-
- matchid = thisboard->id;
- pdev = NULL;
- for_each_pci_dev(pdev) {
- if ((bus || slot) &&
- (bus != pdev->bus->number || slot != PCI_SLOT(pdev->devfn)))
- continue;
- if (pdev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
- continue;
- if (matchid == PCI_ANY_ID) {
- /* wildcard board matches any supported PCI board */
- const struct das08_board_struct *foundboard;
- foundboard = das08_find_pci_board(pdev);
- if (foundboard == NULL)
- continue;
- /* replace wildcard board_ptr */
- dev->board_ptr = thisboard = foundboard;
- } else {
- /* match specific PCI board */
- if (pdev->device != matchid)
- continue;
- }
- /* found a match */
- dev_info(dev->class_dev, "Found %s at PCI %s\n",
- thisboard->name, pci_name(pdev));
- return pdev;
- }
- /* no match found */
- if (bus || slot)
+ comedi_set_hw_dev(dev, &pdev->dev);
+ /* enable PCI device and reserve I/O spaces */
+ if (comedi_pci_enable(pdev, dev->driver->driver_name)) {
dev_err(dev->class_dev,
- "No %s cards found at PCI %02X:%02X\n",
- thisboard->name, bus, slot);
- else
- dev_err(dev->class_dev, "No %s cards found on PCI buses\n",
- thisboard->name);
- return NULL;
+ "Error enabling PCI device and requesting regions\n");
+ return -EIO;
+ }
+ /* read base addresses */
+ iobase = pci_resource_start(pdev, 2);
+ return das08_common_attach(dev, iobase);
}
static int __maybe_unused
@@ -990,14 +818,12 @@ das08_attach(struct comedi_device *dev, struct comedi_devconfig *it)
devpriv = dev->private;
dev_info(dev->class_dev, "attach\n");
- if (IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) && thisboard->bustype == pci) {
- struct pci_dev *pdev;
- pdev = das08_find_pci(dev, it->options[0], it->options[1]);
- if (pdev == NULL)
- return -EIO;
- return das08_pci_attach_common(dev, pdev);
- } else if (IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) &&
- (thisboard->bustype == isa || thisboard->bustype == pc104)) {
+ if (is_pci_board(thisboard)) {
+ dev_err(dev->class_dev,
+ "Manual configuration of PCI board '%s' is not supported\n",
+ thisboard->name);
+ return -EIO;
+ } else if (is_isa_board(thisboard)) {
iobase = it->options[0];
dev_info(dev->class_dev, "iobase 0x%lx\n", iobase);
if (!request_region(iobase, thisboard->iosize, DRV_NAME)) {
@@ -1012,26 +838,23 @@ das08_attach(struct comedi_device *dev, struct comedi_devconfig *it)
void das08_common_detach(struct comedi_device *dev)
{
if (dev->subdevices)
- subdev_8255_cleanup(dev, dev->subdevices + 4);
+ subdev_8255_cleanup(dev, &dev->subdevices[4]);
}
EXPORT_SYMBOL_GPL(das08_common_detach);
static void __maybe_unused das08_detach(struct comedi_device *dev)
{
const struct das08_board_struct *thisboard = comedi_board(dev);
- struct das08_private_struct *devpriv = dev->private;
das08_common_detach(dev);
- if (IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) &&
- (thisboard->bustype == isa || thisboard->bustype == pc104)) {
+ if (is_isa_board(thisboard)) {
if (dev->iobase)
release_region(dev->iobase, thisboard->iosize);
- } else if (IS_ENABLED(CONFIG_COMEDI_DAS08_PCI) &&
- thisboard->bustype == pci) {
- if (devpriv && devpriv->pdev) {
- if (devpriv->pci_iobase)
- comedi_pci_disable(devpriv->pdev);
- pci_dev_put(devpriv->pdev);
+ } else if (is_pci_board(thisboard)) {
+ struct pci_dev *pdev = comedi_to_pci_dev(dev);
+ if (pdev) {
+ if (dev->iobase)
+ comedi_pci_disable(pdev);
}
}
}
@@ -1049,7 +872,7 @@ static struct comedi_driver das08_driver = {
};
#endif
-#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI)
+#if DO_PCI
static DEFINE_PCI_DEVICE_TABLE(das08_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, PCI_DEVICE_ID_PCIDAS08) },
{0}
@@ -1074,10 +897,10 @@ static struct pci_driver das08_pci_driver = {
.probe = &das08_pci_probe,
.remove = __devexit_p(&das08_pci_remove)
};
-#endif /* CONFIG_COMEDI_DAS08_PCI */
+#endif /* DO_PCI */
#if DO_COMEDI_DRIVER_REGISTER
-#if IS_ENABLED(CONFIG_COMEDI_DAS08_PCI)
+#if DO_PCI
module_comedi_pci_driver(das08_driver, das08_pci_driver);
#else
module_comedi_driver(das08_driver);
diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h
index 27b6d4ec9032..0314baebae39 100644
--- a/drivers/staging/comedi/drivers/das08.h
+++ b/drivers/staging/comedi/drivers/das08.h
@@ -24,7 +24,7 @@
#ifndef _DAS08_H
#define _DAS08_H
-enum das08_bustype { isa, pci, pcmcia, pc104 };
+enum das08_bustype { isa, pci, pcmcia };
/* different ways ai data is encoded in first two registers */
enum das08_ai_encoding { das08_encode12, das08_encode16, das08_pcm_encode12 };
enum das08_lrange { das08_pg_none, das08_bipolar5, das08_pgh, das08_pgl,
@@ -35,14 +35,12 @@ struct das08_board_struct {
const char *name;
unsigned int id; /* id for pci/pcmcia boards */
enum das08_bustype bustype;
- void *ai;
+ bool is_jr; /* true for 'JR' boards */
unsigned int ai_nbits;
enum das08_lrange ai_pg;
enum das08_ai_encoding ai_encoding;
- void *ao;
unsigned int ao_nbits;
- void *di;
- void *do_;
+ unsigned int di_nchan;
unsigned int do_nchan;
unsigned int i8255_offset;
unsigned int i8254_offset;
@@ -53,14 +51,9 @@ struct das08_private_struct {
unsigned int do_mux_bits; /* bits for do/mux register on boards without separate do register */
unsigned int do_bits; /* bits for do register on boards with register dedicated to digital out only */
const unsigned int *pg_gainlist;
- struct pci_dev *pdev; /* struct for pci-das08 */
- unsigned int pci_iobase; /* additional base address for pci-das08 */
- unsigned int i8254_iobase;
+ unsigned int ao_readback[2]; /* assume 2 AO channels */
};
-#define NUM_DAS08_CS_BOARDS 2
-extern struct das08_board_struct das08_cs_boards[NUM_DAS08_CS_BOARDS];
-
int das08_common_attach(struct comedi_device *dev, unsigned long iobase);
void das08_common_detach(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
index f5700de7b6c0..e4c91e675379 100644
--- a/drivers/staging/comedi/drivers/das08_cs.c
+++ b/drivers/staging/comedi/drivers/das08_cs.c
@@ -58,6 +58,32 @@ Command support does not exist, but could be added for this board.
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
+static const struct das08_board_struct das08_cs_boards[] = {
+ {
+ .name = "pcm-das08",
+ .id = 0x0, /* XXX */
+ .bustype = pcmcia,
+ .ai_nbits = 12,
+ .ai_pg = das08_bipolar5,
+ .ai_encoding = das08_pcm_encode12,
+ .di_nchan = 3,
+ .do_nchan = 3,
+ .iosize = 16,
+ },
+ /* duplicate so driver name can be used also */
+ {
+ .name = "das08_cs",
+ .id = 0x0, /* XXX */
+ .bustype = pcmcia,
+ .ai_nbits = 12,
+ .ai_pg = das08_bipolar5,
+ .ai_encoding = das08_pcm_encode12,
+ .di_nchan = 3,
+ .do_nchan = 3,
+ .iosize = 16,
+ },
+};
+
static struct pcmcia_device *cur_dev;
static int das08_cs_attach(struct comedi_device *dev,
diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
index 895cc7783c9c..fcb8a32adb2f 100644
--- a/drivers/staging/comedi/drivers/das16.c
+++ b/drivers/staging/comedi/drivers/das16.c
@@ -402,62 +402,42 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
int gain, start_chan, i;
int mask;
- /* make sure triggers are valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
+
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
- tmp = cmd->scan_begin_src;
mask = TRIG_FOLLOW;
/* if board supports burst mode */
if (board->size > 0x400)
mask |= TRIG_TIMER | TRIG_EXT;
- cmd->scan_begin_src &= mask;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, mask);
tmp = cmd->convert_src;
mask = TRIG_TIMER | TRIG_EXT;
/* if board supports burst mode */
if (board->size > 0x400)
mask |= TRIG_NOW;
- cmd->convert_src &= mask;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->convert_src, mask);
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ 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 2: make sure trigger sources are unique and
- * mutually compatible
- */
- if (cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_EXT &&
- cmd->scan_begin_src != TRIG_FOLLOW)
- err++;
- if (cmd->convert_src != TRIG_TIMER &&
- cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW)
- err++;
- if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
- err++;
+ /* Step 2a : make sure trigger sources are unique */
+
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
/* make sure scan_begin_src and convert_src dont conflict */
if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
- err++;
+ err |= -EINVAL;
if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
- err++;
+ err |= -EINVAL;
if (err)
return 2;
@@ -558,7 +538,7 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
/* utility function that suggests a dma transfer size in bytes */
static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
- struct comedi_cmd cmd)
+ const struct comedi_cmd *cmd)
{
unsigned int size;
unsigned int freq;
@@ -571,16 +551,16 @@ static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
/* otherwise, we are relying on dma terminal count interrupt,
* so pick a reasonable size */
- if (cmd.convert_src == TRIG_TIMER)
- freq = 1000000000 / cmd.convert_arg;
- else if (cmd.scan_begin_src == TRIG_TIMER)
- freq = (1000000000 / cmd.scan_begin_arg) * cmd.chanlist_len;
+ if (cmd->convert_src == TRIG_TIMER)
+ freq = 1000000000 / cmd->convert_arg;
+ else if (cmd->scan_begin_src == TRIG_TIMER)
+ freq = (1000000000 / cmd->scan_begin_arg) * cmd->chanlist_len;
/* return some default value */
else
freq = 0xffffffff;
- if (cmd.flags & TRIG_WAKE_EOS) {
- size = sample_size * cmd.chanlist_len;
+ if (cmd->flags & TRIG_WAKE_EOS) {
+ size = sample_size * cmd->chanlist_len;
} else {
/* make buffer fill in no more than 1/3 second */
size = (freq / 3) * sample_size;
@@ -592,7 +572,7 @@ static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
else if (size < sample_size)
size = sample_size;
- if (cmd.stop_src == TRIG_COUNT && size > devpriv->adc_byte_count)
+ if (cmd->stop_src == TRIG_COUNT && size > devpriv->adc_byte_count)
size = devpriv->adc_byte_count;
return size;
@@ -685,7 +665,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
set_dma_addr(devpriv->dma_chan,
devpriv->dma_buffer_addr[devpriv->current_buffer]);
/* set appropriate size of transfer */
- devpriv->dma_transfer_size = das16_suggest_transfer_size(dev, *cmd);
+ devpriv->dma_transfer_size = das16_suggest_transfer_size(dev, cmd);
set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
enable_dma(devpriv->dma_chan);
release_dma_lock(flags);
@@ -1268,7 +1248,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
dev->read_subdev = s;
/* ai */
if (board->ai) {
@@ -1300,7 +1280,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->type = COMEDI_SUBD_UNUSED;
}
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* ao */
if (board->ao) {
s->type = COMEDI_SUBD_AO;
@@ -1318,7 +1298,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->type = COMEDI_SUBD_UNUSED;
}
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
/* di */
if (board->di) {
s->type = COMEDI_SUBD_DI;
@@ -1331,7 +1311,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->type = COMEDI_SUBD_UNUSED;
}
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
/* do */
if (board->do_) {
s->type = COMEDI_SUBD_DO;
@@ -1346,7 +1326,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->type = COMEDI_SUBD_UNUSED;
}
- s = dev->subdevices + 4;
+ s = &dev->subdevices[4];
/* 8255 */
if (board->i8255_offset != 0) {
subdev_8255_init(dev, s, NULL, (dev->iobase +
@@ -1376,7 +1356,7 @@ static void das16_detach(struct comedi_device *dev)
das16_reset(dev);
if (dev->subdevices)
- subdev_8255_cleanup(dev, dev->subdevices + 4);
+ subdev_8255_cleanup(dev, &dev->subdevices[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 200926347861..3f87d7598e5b 100644
--- a/drivers/staging/comedi/drivers/das16m1.c
+++ b/drivers/staging/comedi/drivers/das16m1.c
@@ -170,42 +170,24 @@ static int das16m1_cmd_test(struct comedi_device *dev,
const struct das16m1_board *board = comedi_board(dev);
unsigned int err = 0, tmp, i;
- /* make sure triggers are valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_EXT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_FOLLOW;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
+ 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 2: make sure trigger sources are unique and mutually compatible */
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
- if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
- err++;
- if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
- err++;
+ /* Step 2a : make sure trigger sources are unique */
+
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -650,7 +632,7 @@ static int das16m1_attach(struct comedi_device *dev,
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
dev->read_subdev = s;
/* ai */
s->type = COMEDI_SUBD_AI;
@@ -666,7 +648,7 @@ static int das16m1_attach(struct comedi_device *dev,
s->cancel = das16m1_cancel;
s->poll = das16m1_poll;
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* di */
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
@@ -675,7 +657,7 @@ static int das16m1_attach(struct comedi_device *dev,
s->range_table = &range_digital;
s->insn_bits = das16m1_di_rbits;
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
/* do */
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
@@ -684,7 +666,7 @@ static int das16m1_attach(struct comedi_device *dev,
s->range_table = &range_digital;
s->insn_bits = das16m1_do_wbits;
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
/* 8255 */
subdev_8255_init(dev, s, NULL, dev->iobase + DAS16M1_82C55);
@@ -707,7 +689,7 @@ static int das16m1_attach(struct comedi_device *dev,
static void das16m1_detach(struct comedi_device *dev)
{
if (dev->subdevices)
- subdev_8255_cleanup(dev, dev->subdevices + 3);
+ subdev_8255_cleanup(dev, &dev->subdevices[3]);
if (dev->irq)
free_irq(dev->irq, dev);
if (dev->iobase) {
diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
index 25e7e56a376f..2555f3297d7b 100644
--- a/drivers/staging/comedi/drivers/das1800.c
+++ b/drivers/staging/comedi/drivers/das1800.c
@@ -656,7 +656,7 @@ static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
/* the guts of the interrupt handler, that is shared with das1800_ai_poll */
static void das1800_ai_handler(struct comedi_device *dev)
{
- struct comedi_subdevice *s = dev->subdevices + 0; /* analog input subdevice */
+ struct comedi_subdevice *s = &dev->subdevices[0];
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
unsigned int status = inb(dev->iobase + DAS1800_STATUS);
@@ -784,59 +784,35 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev,
struct comedi_cmd *cmd)
{
int err = 0;
- int tmp;
unsigned int tmp_arg;
int i;
int unipolar;
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_EXT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_EXT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ err |= cfc_check_trigger_src(&cmd->stop_src,
+ TRIG_COUNT | TRIG_EXT | TRIG_NONE);
if (err)
return 1;
- /* step 2: make sure trigger sources are unique and mutually compatible */
+ /* Step 2a : make sure trigger sources are unique */
+
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
- /* uniqueness check */
- if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
- err++;
- if (cmd->scan_begin_src != TRIG_FOLLOW &&
- cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_EXT)
- err++;
- if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
- err++;
- if (cmd->stop_src != TRIG_COUNT &&
- cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT)
- err++;
- /* compatibility check */
if (cmd->scan_begin_src != TRIG_FOLLOW &&
cmd->convert_src != TRIG_TIMER)
- err++;
+ err |= -EINVAL;
if (err)
return 2;
@@ -958,14 +934,14 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev,
}
/* returns appropriate bits for control register a, depending on command */
-static int control_a_bits(struct comedi_cmd cmd)
+static int control_a_bits(const struct comedi_cmd *cmd)
{
int control_a;
control_a = FFEN; /* enable fifo */
- if (cmd.stop_src == TRIG_EXT)
+ if (cmd->stop_src == TRIG_EXT)
control_a |= ATEN;
- switch (cmd.start_src) {
+ switch (cmd->start_src) {
case TRIG_EXT:
control_a |= TGEN | CGSL;
break;
@@ -980,7 +956,7 @@ static int control_a_bits(struct comedi_cmd cmd)
}
/* returns appropriate bits for control register c, depending on command */
-static int control_c_bits(struct comedi_cmd cmd)
+static int control_c_bits(const struct comedi_cmd *cmd)
{
int control_c;
int aref;
@@ -988,18 +964,18 @@ static int control_c_bits(struct comedi_cmd cmd)
/* set clock source to internal or external, select analog reference,
* select unipolar / bipolar
*/
- aref = CR_AREF(cmd.chanlist[0]);
+ aref = CR_AREF(cmd->chanlist[0]);
control_c = UQEN; /* enable upper qram addresses */
if (aref != AREF_DIFF)
control_c |= SD;
if (aref == AREF_COMMON)
control_c |= CMEN;
/* if a unipolar range was selected */
- if (CR_RANGE(cmd.chanlist[0]) & UNIPOLAR)
+ if (CR_RANGE(cmd->chanlist[0]) & UNIPOLAR)
control_c |= UB;
- switch (cmd.scan_begin_src) {
+ switch (cmd->scan_begin_src) {
case TRIG_FOLLOW: /* not in burst mode */
- switch (cmd.convert_src) {
+ switch (cmd->convert_src) {
case TRIG_TIMER:
/* trig on cascaded counters */
control_c |= IPCLK;
@@ -1047,29 +1023,33 @@ static int das1800_set_frequency(struct comedi_device *dev)
}
/* sets up counters */
-static int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd)
+static int setup_counters(struct comedi_device *dev,
+ const struct comedi_cmd *cmd)
{
+ unsigned int period;
+
/* setup cascaded counters for conversion/scan frequency */
- switch (cmd.scan_begin_src) {
+ switch (cmd->scan_begin_src) {
case TRIG_FOLLOW: /* not in burst mode */
- if (cmd.convert_src == TRIG_TIMER) {
+ if (cmd->convert_src == TRIG_TIMER) {
/* set conversion frequency */
+ period = cmd->convert_arg;
i8253_cascade_ns_to_timer_2div(TIMER_BASE,
- &(devpriv->divisor1),
- &(devpriv->divisor2),
- &(cmd.convert_arg),
- cmd.
- flags & TRIG_ROUND_MASK);
+ &devpriv->divisor1,
+ &devpriv->divisor2,
+ &period,
+ cmd->flags &
+ TRIG_ROUND_MASK);
if (das1800_set_frequency(dev) < 0)
return -1;
}
break;
case TRIG_TIMER: /* in burst mode */
/* set scan frequency */
- i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
- &(devpriv->divisor2),
- &(cmd.scan_begin_arg),
- cmd.flags & TRIG_ROUND_MASK);
+ period = cmd->scan_begin_arg;
+ i8253_cascade_ns_to_timer_2div(TIMER_BASE, &devpriv->divisor1,
+ &devpriv->divisor2, &period,
+ cmd->flags & TRIG_ROUND_MASK);
if (das1800_set_frequency(dev) < 0)
return -1;
break;
@@ -1078,7 +1058,7 @@ static int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd)
}
/* setup counter 0 for 'about triggering' */
- if (cmd.stop_src == TRIG_EXT) {
+ if (cmd->stop_src == TRIG_EXT) {
/* load counter 0 in mode 0 */
i8254_load(dev->iobase + DAS1800_COUNTER, 0, 0, 1, 0);
}
@@ -1087,7 +1067,7 @@ static int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd)
}
/* utility function that suggests a dma transfer size based on the conversion period 'ns' */
-static unsigned int suggest_transfer_size(struct comedi_cmd *cmd)
+static unsigned int suggest_transfer_size(const struct comedi_cmd *cmd)
{
unsigned int size = DMA_BUF_SIZE;
static const int sample_size = 2; /* size in bytes of one sample from board */
@@ -1125,7 +1105,7 @@ static unsigned int suggest_transfer_size(struct comedi_cmd *cmd)
}
/* sets up dma */
-static void setup_dma(struct comedi_device *dev, struct comedi_cmd cmd)
+static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
{
unsigned long lock_flags;
const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
@@ -1134,7 +1114,7 @@ static void setup_dma(struct comedi_device *dev, struct comedi_cmd cmd)
return;
/* determine a reasonable dma transfer size */
- devpriv->dma_transfer_size = suggest_transfer_size(&cmd);
+ devpriv->dma_transfer_size = suggest_transfer_size(cmd);
lock_flags = claim_dma_lock();
disable_dma(devpriv->dma0);
/* clear flip-flop to make sure 2-byte registers for
@@ -1163,14 +1143,15 @@ static void setup_dma(struct comedi_device *dev, struct comedi_cmd cmd)
}
/* programs channel/gain list into card */
-static void program_chanlist(struct comedi_device *dev, struct comedi_cmd cmd)
+static void program_chanlist(struct comedi_device *dev,
+ const struct comedi_cmd *cmd)
{
int i, n, chan_range;
unsigned long irq_flags;
const int range_mask = 0x3; /* masks unipolar/bipolar bit off range */
const int range_bitshift = 8;
- n = cmd.chanlist_len;
+ n = cmd->chanlist_len;
/* spinlock protects indirect addressing */
spin_lock_irqsave(&dev->spinlock, irq_flags);
outb(QRAM, dev->iobase + DAS1800_SELECT); /* select QRAM for baseAddress + 0x0 */
@@ -1178,9 +1159,9 @@ static void program_chanlist(struct comedi_device *dev, struct comedi_cmd cmd)
/* make channel / gain list */
for (i = 0; i < n; i++) {
chan_range =
- CR_CHAN(cmd.
- chanlist[i]) | ((CR_RANGE(cmd.chanlist[i]) &
- range_mask) << range_bitshift);
+ CR_CHAN(cmd->chanlist[i]) |
+ ((CR_RANGE(cmd->chanlist[i]) & range_mask) <<
+ range_bitshift);
outw(chan_range, dev->iobase + DAS1800_QRAM);
}
outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */
@@ -1196,7 +1177,7 @@ static int das1800_ai_do_cmd(struct comedi_device *dev,
int ret;
int control_a, control_c;
struct comedi_async *async = s->async;
- struct comedi_cmd cmd = async->cmd;
+ const struct comedi_cmd *cmd = &async->cmd;
if (!dev->irq) {
comedi_error(dev,
@@ -1206,12 +1187,12 @@ static int das1800_ai_do_cmd(struct comedi_device *dev,
/* disable dma on TRIG_WAKE_EOS, or TRIG_RT
* (because dma in handler is unsafe at hard real-time priority) */
- if (cmd.flags & (TRIG_WAKE_EOS | TRIG_RT))
+ if (cmd->flags & (TRIG_WAKE_EOS | TRIG_RT))
devpriv->irq_dma_bits &= ~DMA_ENABLED;
else
devpriv->irq_dma_bits |= devpriv->dma_bits;
/* interrupt on end of conversion for TRIG_WAKE_EOS */
- if (cmd.flags & TRIG_WAKE_EOS) {
+ if (cmd->flags & TRIG_WAKE_EOS) {
/* interrupt fifo not empty */
devpriv->irq_dma_bits &= ~FIMD;
} else {
@@ -1219,8 +1200,8 @@ static int das1800_ai_do_cmd(struct comedi_device *dev,
devpriv->irq_dma_bits |= FIMD;
}
/* determine how many conversions we need */
- if (cmd.stop_src == TRIG_COUNT)
- devpriv->count = cmd.stop_arg * cmd.chanlist_len;
+ if (cmd->stop_src == TRIG_COUNT)
+ devpriv->count = cmd->stop_arg * cmd->chanlist_len;
das1800_cancel(dev, s);
@@ -1240,9 +1221,9 @@ static int das1800_ai_do_cmd(struct comedi_device *dev,
/* set conversion rate and length for burst mode */
if (control_c & BMDE) {
/* program conversion period with number of microseconds minus 1 */
- outb(cmd.convert_arg / 1000 - 1,
+ outb(cmd->convert_arg / 1000 - 1,
dev->iobase + DAS1800_BURST_RATE);
- outb(cmd.chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
+ outb(cmd->chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
}
outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B); /* enable irq/dma */
outb(control_a, dev->iobase + DAS1800_CONTROL_A); /* enable fifo and triggering */
@@ -1653,7 +1634,7 @@ static int das1800_attach(struct comedi_device *dev,
return retval;
/* analog input subdevice */
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
dev->read_subdev = s;
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND | SDF_CMD_READ;
@@ -1670,7 +1651,7 @@ static int das1800_attach(struct comedi_device *dev,
s->cancel = das1800_cancel;
/* analog out */
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
if (thisboard->ao_ability == 1) {
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
@@ -1683,7 +1664,7 @@ static int das1800_attach(struct comedi_device *dev,
}
/* di */
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
s->n_chan = 4;
@@ -1692,7 +1673,7 @@ static int das1800_attach(struct comedi_device *dev,
s->insn_bits = das1800_di_rbits;
/* do */
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
s->n_chan = thisboard->do_n_chan;
diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
index e3afcfa9efc8..e134c46dedff 100644
--- a/drivers/staging/comedi/drivers/das6402.c
+++ b/drivers/staging/comedi/drivers/das6402.c
@@ -152,7 +152,7 @@ static void das6402_setcounter(struct comedi_device *dev)
static irqreturn_t intr_handler(int irq, void *d)
{
struct comedi_device *dev = d;
- struct comedi_subdevice *s = dev->subdevices;
+ struct comedi_subdevice *s = &dev->subdevices[0];
if (!dev->attached || devpriv->das6402_ignoreirq) {
dev_warn(dev->class_dev, "BUG: spurious interrupt\n");
@@ -312,7 +312,7 @@ static int das6402_attach(struct comedi_device *dev,
return ret;
/* ai subdevice */
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_GROUND;
s->n_chan = 8;
diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
index a0959a5e8747..215deac0a396 100644
--- a/drivers/staging/comedi/drivers/das800.c
+++ b/drivers/staging/comedi/drivers/das800.c
@@ -435,7 +435,7 @@ static irqreturn_t das800_interrupt(int irq, void *d)
if (fifo_overflow) {
spin_unlock_irqrestore(&dev->spinlock, irq_flags);
comedi_error(dev, "DAS800 FIFO overflow");
- das800_cancel(dev, dev->subdevices + 0);
+ das800_cancel(dev, s);
async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
comedi_event(dev, s);
async->events = 0;
@@ -517,7 +517,7 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return ret;
/* analog input subdevice */
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
dev->read_subdev = s;
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
@@ -531,7 +531,7 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->cancel = das800_cancel;
/* di */
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
s->n_chan = 3;
@@ -540,7 +540,7 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->insn_bits = das800_di_rbits;
/* do */
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
s->n_chan = 4;
@@ -609,44 +609,24 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev,
int gain, startChan;
int i;
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_EXT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_FOLLOW;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
+ 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 2: make sure trigger sources are unique and mutually compatible */
+ /* Step 2a : make sure trigger sources are unique */
- if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
- err++;
- if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
- err++;
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
index 7107f590b1fe..4d5c33c4750f 100644
--- a/drivers/staging/comedi/drivers/dmm32at.c
+++ b/drivers/staging/comedi/drivers/dmm32at.c
@@ -41,6 +41,8 @@ Configuration Options:
#include "../comedidev.h"
#include <linux/ioport.h>
+#include "comedi_fc.h"
+
/* Board register addresses */
#define DMM32AT_MEMSIZE 0x10
@@ -258,47 +260,26 @@ static int dmm32at_ai_cmdtest(struct comedi_device *dev,
int tmp;
int start_chan, gain, i;
- /* step 1: make sure trigger sources are trivially valid */
-
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER /*| TRIG_EXT */ ;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER /*| TRIG_EXT */ ;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_TIMER /*| TRIG_EXT */);
+ err |= cfc_check_trigger_src(&cmd->convert_src,
+ TRIG_TIMER /*| TRIG_EXT */);
+ 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 2: make sure trigger sources are unique and mutually
- * compatible */
+ /* Step 2a : make sure trigger sources are unique */
- /* note that mutual compatibility is not an issue here */
- if (cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_EXT)
- err++;
- if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
- err++;
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -825,7 +806,7 @@ static int dmm32at_attach(struct comedi_device *dev,
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
dev->read_subdev = s;
/* analog input subdevice */
s->type = COMEDI_SUBD_AI;
@@ -841,7 +822,7 @@ static int dmm32at_attach(struct comedi_device *dev,
s->do_cmdtest = dmm32at_ai_cmdtest;
s->cancel = dmm32at_ai_cancel;
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* analog output subdevice */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
@@ -851,7 +832,7 @@ static int dmm32at_attach(struct comedi_device *dev,
s->insn_write = dmm32at_ao_winsn;
s->insn_read = dmm32at_ao_rinsn;
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
/* digital i/o subdevice */
/* get access to the DIO regs */
diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
index d332269375ab..c59a652a1194 100644
--- a/drivers/staging/comedi/drivers/dt2801.c
+++ b/drivers/staging/comedi/drivers/dt2801.c
@@ -532,7 +532,7 @@ static int dt2801_dio_insn_bits(struct comedi_device *dev,
{
int which = 0;
- if (s == dev->subdevices + 4)
+ if (s == &dev->subdevices[3])
which = 1;
if (data[0]) {
@@ -555,7 +555,7 @@ static int dt2801_dio_insn_config(struct comedi_device *dev,
{
int which = 0;
- if (s == dev->subdevices + 4)
+ if (s == &dev->subdevices[3])
which = 1;
/* configure */
@@ -636,7 +636,7 @@ havetype:
dev->board_name = boardtype.name;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* ai subdevice */
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_GROUND;
@@ -652,7 +652,7 @@ havetype:
s->range_table = ai_range_lkup(boardtype.adrangetype, it->options[3]);
s->insn_read = dt2801_ai_insn_read;
- s++;
+ s = &dev->subdevices[1];
/* ao subdevice */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
@@ -664,7 +664,7 @@ havetype:
s->insn_read = dt2801_ao_insn_read;
s->insn_write = dt2801_ao_insn_write;
- s++;
+ s = &dev->subdevices[2];
/* 1st digital subdevice */
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
@@ -674,7 +674,7 @@ havetype:
s->insn_bits = dt2801_dio_insn_bits;
s->insn_config = dt2801_dio_insn_config;
- s++;
+ s = &dev->subdevices[3];
/* 2nd digital subdevice */
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
index 290b933c5f96..d3a8c1aec9d6 100644
--- a/drivers/staging/comedi/drivers/dt2811.c
+++ b/drivers/staging/comedi/drivers/dt2811.c
@@ -510,7 +510,7 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
break;
}
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* initialize the ADC subdevice */
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_GROUND;
@@ -530,7 +530,7 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
break;
}
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* ao subdevice */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
@@ -542,7 +542,7 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
devpriv->range_type_list[0] = dac_range_types[devpriv->dac_range[0]];
devpriv->range_type_list[1] = dac_range_types[devpriv->dac_range[1]];
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
/* di subdevice */
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
@@ -551,7 +551,7 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->maxdata = 1;
s->range_table = &range_digital;
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
/* do subdevice */
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE;
diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c
index 2e39ebe36fb5..064a8f215e4d 100644
--- a/drivers/staging/comedi/drivers/dt2814.c
+++ b/drivers/staging/comedi/drivers/dt2814.c
@@ -45,6 +45,8 @@ addition, the clock does not seem to be very accurate.
#include <linux/ioport.h>
#include <linux/delay.h>
+#include "comedi_fc.h"
+
#define DT2814_SIZE 2
#define DT2814_CSR 0
@@ -129,42 +131,22 @@ static int dt2814_ai_cmdtest(struct comedi_device *dev,
int err = 0;
int tmp;
- /* step 1: make sure trigger sources are trivially valid */
-
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_NOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
+ 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 2: make sure trigger sources are
- * unique and mutually compatible */
+ /* Step 2a : make sure trigger sources are unique */
- /* note that mutual compatibility is not an issue here */
- if (cmd->stop_src != TRIG_TIMER && cmd->stop_src != TRIG_EXT)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -247,7 +229,7 @@ static irqreturn_t dt2814_interrupt(int irq, void *d)
return IRQ_HANDLED;
}
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
hi = inb(dev->iobase + DT2814_DATA);
lo = inb(dev->iobase + DT2814_DATA);
@@ -346,7 +328,7 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret < 0)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
dev->read_subdev = s;
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c
index 45b20bee4369..b9692ef64c41 100644
--- a/drivers/staging/comedi/drivers/dt2815.c
+++ b/drivers/staging/comedi/drivers/dt2815.c
@@ -185,7 +185,7 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (alloc_private(dev, sizeof(struct dt2815_private)) < 0)
return -ENOMEM;
- s = dev->subdevices;
+ s = &dev->subdevices[0];
/* ao subdevice */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c
index beba0447b3ee..502e42e0753e 100644
--- a/drivers/staging/comedi/drivers/dt2817.c
+++ b/drivers/staging/comedi/drivers/dt2817.c
@@ -141,7 +141,7 @@ static int dt2817_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
s->n_chan = 32;
s->type = COMEDI_SUBD_DIO;
diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
index 1f0b40e4bddd..78d340716d1e 100644
--- a/drivers/staging/comedi/drivers/dt282x.c
+++ b/drivers/staging/comedi/drivers/dt282x.c
@@ -312,7 +312,7 @@ static void dt282x_ao_dma_interrupt(struct comedi_device *dev)
void *ptr;
int size;
int i;
- struct comedi_subdevice *s = dev->subdevices + 1;
+ struct comedi_subdevice *s = &dev->subdevices[1];
outw(devpriv->supcsr | DT2821_CLRDMADNE, dev->iobase + DT2821_SUPCSR);
@@ -345,7 +345,7 @@ static void dt282x_ai_dma_interrupt(struct comedi_device *dev)
int size;
int i;
int ret;
- struct comedi_subdevice *s = dev->subdevices;
+ struct comedi_subdevice *s = &dev->subdevices[0];
outw(devpriv->supcsr | DT2821_CLRDMADNE, dev->iobase + DT2821_SUPCSR);
@@ -457,8 +457,8 @@ static irqreturn_t dt282x_interrupt(int irq, void *d)
return IRQ_HANDLED;
}
- s = dev->subdevices + 0;
- s_ao = dev->subdevices + 1;
+ s = &dev->subdevices[0];
+ s_ao = &dev->subdevices[1];
adcsr = inw(dev->iobase + DT2821_ADCSR);
dacsr = inw(dev->iobase + DT2821_DACSR);
supcsr = inw(dev->iobase + DT2821_SUPCSR);
@@ -582,47 +582,24 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev,
int err = 0;
int tmp;
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_FOLLOW | TRIG_EXT);
+ 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 2: make sure trigger sources are unique
- * and mutually compatible
- */
+ /* Step 2a : make sure trigger sources are unique */
- /* note that mutual compatibility is not an issue here */
- if (cmd->scan_begin_src != TRIG_FOLLOW &&
- cmd->scan_begin_src != TRIG_EXT)
- err++;
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -862,44 +839,22 @@ static int dt282x_ao_cmdtest(struct comedi_device *dev,
int err = 0;
int tmp;
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_INT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_NOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
+ 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 2: make sure trigger sources are unique
- * and mutually compatible
- */
+ /* Step 2a : make sure trigger sources are unique */
- /* note that mutual compatibility is not an issue here */
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -1275,7 +1230,7 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
dev->read_subdev = s;
/* ai subdevice */
@@ -1294,7 +1249,7 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
opt_ai_range_lkup(boardtype.ispgl, it->options[opt_ai_range]);
devpriv->ad_2scomp = it->options[opt_ai_twos];
- s++;
+ s = &dev->subdevices[1];
s->n_chan = boardtype.dachan;
if (s->n_chan) {
@@ -1320,7 +1275,7 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->type = COMEDI_SUBD_UNUSED;
}
- s++;
+ s = &dev->subdevices[2];
/* dio subsystem */
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
index 3476cda0fff0..43d05ef97157 100644
--- a/drivers/staging/comedi/drivers/dt3000.c
+++ b/drivers/staging/comedi/drivers/dt3000.c
@@ -63,6 +63,8 @@ AO commands are not supported.
#include "../comedidev.h"
#include <linux/delay.h>
+#include "comedi_fc.h"
+
#define PCI_VENDOR_ID_DT 0x1116
static const struct comedi_lrange range_dt3000_ai = { 4, {
@@ -330,7 +332,7 @@ static irqreturn_t dt3k_interrupt(int irq, void *d)
if (!dev->attached)
return IRQ_NONE;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
status = readw(devpriv->io_addr + DPR_Intr_Flag);
#ifdef DEBUG
debug_intr_flags(status);
@@ -408,37 +410,19 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev,
int err = 0;
int tmp;
- /* step 1: make sure trigger sources are trivially valid */
-
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
+ 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);
if (err)
return 1;
- /* step 2: make sure trigger sources are unique and mutually compatible */
+ /* Step 2a : make sure trigger sources are unique */
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -842,7 +826,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret)
return ret;
- s = dev->subdevices;
+ s = &dev->subdevices[0];
dev->read_subdev = s;
/* ai subdevice */
@@ -857,7 +841,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->do_cmdtest = dt3k_ai_cmdtest;
s->cancel = dt3k_ai_cancel;
- s++;
+ s = &dev->subdevices[1];
/* ao subsystem */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
@@ -868,7 +852,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->len_chanlist = 1;
s->range_table = &range_bipolar10;
- s++;
+ s = &dev->subdevices[2];
/* dio subsystem */
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
@@ -879,7 +863,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->len_chanlist = 8;
s->range_table = &range_digital;
- s++;
+ s = &dev->subdevices[3];
/* mem subsystem */
s->type = COMEDI_SUBD_MEMORY;
s->subdev_flags = SDF_READABLE;
@@ -890,7 +874,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->range_table = &range_unknown;
#if 0
- s++;
+ s = &dev->subdevices[4];
/* proc subsystem */
s->type = COMEDI_SUBD_PROC;
#endif
diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
index 40821c7303ea..bc6f409b7e19 100644
--- a/drivers/staging/comedi/drivers/dt9812.c
+++ b/drivers/staging/comedi/drivers/dt9812.c
@@ -1041,7 +1041,7 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return ret;
/* digital input subdevice */
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
s->n_chan = 0;
@@ -1050,7 +1050,7 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->insn_read = &dt9812_di_rinsn;
/* digital output subdevice */
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITEABLE;
s->n_chan = 0;
@@ -1059,7 +1059,7 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->insn_write = &dt9812_do_winsn;
/* analog input subdevice */
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_GROUND;
s->n_chan = 0;
@@ -1068,7 +1068,7 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->insn_read = &dt9812_ai_rinsn;
/* analog output subdevice */
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITEABLE;
s->n_chan = 0;
diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c
index 064be9aae3aa..6f612be1b0a5 100644
--- a/drivers/staging/comedi/drivers/dyna_pci10xx.c
+++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c
@@ -41,7 +41,6 @@
#include <linux/mutex.h>
#define PCI_VENDOR_ID_DYNALOG 0x10b5
-#define DRV_NAME "dyna_pci10xx"
#define READ_TIMEOUT 50
@@ -54,59 +53,11 @@ static const struct comedi_lrange range_pci1050_ai = { 3, {
static const char range_codes_pci1050_ai[] = { 0x00, 0x10, 0x30 };
-static const struct comedi_lrange range_pci1050_ao = { 1, {
- UNI_RANGE(10)
- }
-};
-
-static const char range_codes_pci1050_ao[] = { 0x00 };
-
-struct boardtype {
- const char *name;
- int device_id;
- int ai_chans;
- int ai_bits;
- int ao_chans;
- int ao_bits;
- int di_chans;
- int di_bits;
- int do_chans;
- int do_bits;
- const struct comedi_lrange *range_ai;
- const char *range_codes_ai;
- const struct comedi_lrange *range_ao;
- const char *range_codes_ao;
-};
-
-static const struct boardtype boardtypes[] = {
- {
- .name = "dyna_pci1050",
- .device_id = 0x1050,
- .ai_chans = 16,
- .ai_bits = 12,
- .ao_chans = 16,
- .ao_bits = 12,
- .di_chans = 16,
- .di_bits = 16,
- .do_chans = 16,
- .do_bits = 16,
- .range_ai = &range_pci1050_ai,
- .range_codes_ai = range_codes_pci1050_ai,
- .range_ao = &range_pci1050_ao,
- .range_codes_ao = range_codes_pci1050_ao,
- },
- /* dummy entry corresponding to driver name */
- {.name = DRV_NAME},
-};
-
struct dyna_pci10xx_private {
struct mutex mutex;
unsigned long BADR3;
};
-#define thisboard ((const struct boardtype *)dev->board_ptr)
-#define devpriv ((struct dyna_pci10xx_private *)dev->private)
-
/******************************************************************************/
/************************** READ WRITE FUNCTIONS ******************************/
/******************************************************************************/
@@ -116,13 +67,14 @@ static int dyna_pci10xx_insn_read_ai(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct dyna_pci10xx_private *devpriv = dev->private;
int n, counter;
u16 d = 0;
unsigned int chan, range;
/* get the channel number and range */
chan = CR_CHAN(insn->chanspec);
- range = thisboard->range_codes_ai[CR_RANGE((insn->chanspec))];
+ range = range_codes_pci1050_ai[CR_RANGE((insn->chanspec))];
mutex_lock(&devpriv->mutex);
/* convert n samples */
@@ -159,11 +111,12 @@ static int dyna_pci10xx_insn_write_ao(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct dyna_pci10xx_private *devpriv = dev->private;
int n;
unsigned int chan, range;
chan = CR_CHAN(insn->chanspec);
- range = thisboard->range_codes_ai[CR_RANGE((insn->chanspec))];
+ range = range_codes_pci1050_ai[CR_RANGE((insn->chanspec))];
mutex_lock(&devpriv->mutex);
for (n = 0; n < insn->n; n++) {
@@ -181,6 +134,7 @@ static int dyna_pci10xx_di_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct dyna_pci10xx_private *devpriv = dev->private;
u16 d = 0;
mutex_lock(&devpriv->mutex);
@@ -200,6 +154,8 @@ static int dyna_pci10xx_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct dyna_pci10xx_private *devpriv = dev->private;
+
/* The insn data is a mask in data[0] and the new data
* in data[1], each channel cooresponding to a bit.
* s->state contains the previous write data
@@ -223,143 +179,98 @@ static int dyna_pci10xx_do_insn_bits(struct comedi_device *dev,
return insn->n;
}
-static struct pci_dev *dyna_pci10xx_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
- int i;
-
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (bus != pcidev->bus->number ||
- slot != PCI_SLOT(pcidev->devfn))
- continue;
- }
- if (pcidev->vendor != PCI_VENDOR_ID_DYNALOG)
- continue;
-
- for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) {
- if (pcidev->device != boardtypes[i].device_id)
- continue;
-
- dev->board_ptr = &boardtypes[i];
- return pcidev;
- }
- }
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
- return NULL;
-}
-
-static int dyna_pci10xx_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int dyna_pci10xx_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev;
+ struct dyna_pci10xx_private *devpriv;
struct comedi_subdevice *s;
int ret;
- if (alloc_private(dev, sizeof(struct dyna_pci10xx_private)) < 0) {
- printk(KERN_ERR "comedi: dyna_pci10xx: "
- "failed to allocate memory!\n");
- return -ENOMEM;
- }
-
- pcidev = dyna_pci10xx_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
comedi_set_hw_dev(dev, &pcidev->dev);
- dev->board_name = thisboard->name;
- dev->irq = 0;
-
- if (comedi_pci_enable(pcidev, DRV_NAME)) {
- printk(KERN_ERR "comedi: dyna_pci10xx: "
- "failed to enable PCI device and request regions!");
- return -EIO;
- }
-
- mutex_init(&devpriv->mutex);
+ dev->board_name = dev->driver->driver_name;
- printk(KERN_INFO "comedi: dyna_pci10xx: device found!\n");
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret)
+ return ret;
+ devpriv = dev->private;
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
dev->iobase = pci_resource_start(pcidev, 2);
devpriv->BADR3 = pci_resource_start(pcidev, 3);
+ mutex_init(&devpriv->mutex);
+
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
return ret;
/* analog input */
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
- s->n_chan = thisboard->ai_chans;
+ s->n_chan = 16;
s->maxdata = 0x0FFF;
- s->range_table = thisboard->range_ai;
+ s->range_table = &range_pci1050_ai;
s->len_chanlist = 16;
s->insn_read = dyna_pci10xx_insn_read_ai;
/* analog output */
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
- s->n_chan = thisboard->ao_chans;
+ s->n_chan = 16;
s->maxdata = 0x0FFF;
- s->range_table = thisboard->range_ao;
+ s->range_table = &range_unipolar10;
s->len_chanlist = 16;
s->insn_write = dyna_pci10xx_insn_write_ao;
/* digital input */
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE | SDF_GROUND;
- s->n_chan = thisboard->di_chans;
+ s->n_chan = 16;
s->maxdata = 1;
s->range_table = &range_digital;
- s->len_chanlist = thisboard->di_chans;
+ s->len_chanlist = 16;
s->insn_bits = dyna_pci10xx_di_insn_bits;
/* digital output */
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
- s->n_chan = thisboard->do_chans;
+ s->n_chan = 16;
s->maxdata = 1;
s->range_table = &range_digital;
- s->len_chanlist = thisboard->do_chans;
+ s->len_chanlist = 16;
s->state = 0;
s->insn_bits = dyna_pci10xx_do_insn_bits;
- printk(KERN_INFO "comedi: dyna_pci10xx: %s - device setup completed!\n",
- thisboard->name);
+ dev_info(dev->class_dev, "%s attached\n", dev->board_name);
- return 1;
+ return 0;
}
static void dyna_pci10xx_detach(struct comedi_device *dev)
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ struct dyna_pci10xx_private *devpriv = dev->private;
if (devpriv)
mutex_destroy(&devpriv->mutex);
if (pcidev) {
if (dev->iobase)
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
}
}
static struct comedi_driver dyna_pci10xx_driver = {
.driver_name = "dyna_pci10xx",
.module = THIS_MODULE,
- .attach = dyna_pci10xx_attach,
+ .attach_pci = dyna_pci10xx_attach_pci,
.detach = dyna_pci10xx_detach,
- .board_name = &boardtypes[0].name,
- .offset = sizeof(struct boardtype),
- .num_names = ARRAY_SIZE(boardtypes),
};
static int __devinit dyna_pci10xx_pci_probe(struct pci_dev *dev,
diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
index d1da80976f84..ae8e8f460295 100644
--- a/drivers/staging/comedi/drivers/fl512.c
+++ b/drivers/staging/comedi/drivers/fl512.c
@@ -140,7 +140,7 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it)
* this if the definitions of the supdevices, 2 have been defined
*/
/* Analog indput */
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* define subdevice as Analog In */
s->type = COMEDI_SUBD_AI;
/* you can read it from userspace */
@@ -156,7 +156,7 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it)
printk(KERN_INFO "comedi: fl512: subdevice 0 initialized\n");
/* Analog output */
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* define subdevice as Analog OUT */
s->type = COMEDI_SUBD_AO;
/* you can write it from userspace */
diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
index 79f580841dee..abff6603952a 100644
--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
+++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
@@ -436,7 +436,7 @@ static int setup_subdevices(struct comedi_device *dev)
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* analog input subdevice */
dev->read_subdev = s;
/* dev->write_subdev = s; */
@@ -723,45 +723,24 @@ static int di_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{
int err = 0;
- int tmp;
int i;
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_NOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
+ 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 2: make sure trigger sources are unique and mutually
- * compatible */
+ /* Step 2a : make sure trigger sources are unique */
- /* uniqueness check */
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
index b10ebdbc1f7e..d696d4d51e28 100644
--- a/drivers/staging/comedi/drivers/icp_multi.c
+++ b/drivers/staging/comedi/drivers/icp_multi.c
@@ -44,10 +44,7 @@ There are 4 x 12-bit Analogue Outputs. Ranges : 5V, 10V, +/-5V, +/-10V
4 x 16-bit counters
-Options:
- [0] - PCI bus number - if bus number and slot number are 0,
- then driver search for first unused card
- [1] - PCI slot number
+Configuration options: not applicable, uses PCI auto config
*/
#include <linux/interrupt.h>
@@ -56,16 +53,7 @@ Options:
#include <linux/delay.h>
#include <linux/pci.h>
-#include "icp_multi.h"
-
-#define DEVICE_ID 0x8000 /* Device ID */
-
-#define ICP_MULTI_EXTDEBUG
-
-/* Hardware types of the cards */
-#define TYPE_ICP_MULTI 0
-
-#define IORANGE_ICP_MULTI 32
+#define PCI_DEVICE_ID_ICP_MULTI 0x8000
#define ICP_MULTI_ADC_CSR 0 /* R/W: ADC command/status register */
#define ICP_MULTI_AI 2 /* R: Analogue input data */
@@ -124,32 +112,10 @@ static const char range_codes_analog[] = { 0x00, 0x20, 0x10, 0x30 };
Data & Structure declarations
==============================================================================
*/
-static unsigned short pci_list_builded; /*>0 list of card is known */
-
-struct boardtype {
- const char *name; /* driver name */
- int device_id;
- int iorange; /* I/O range len */
- char have_irq; /* 1=card support IRQ */
- char cardtype; /* 0=ICP Multi */
- int n_aichan; /* num of A/D chans */
- int n_aichand; /* num of A/D chans in diff mode */
- int n_aochan; /* num of D/A chans */
- int n_dichan; /* num of DI chans */
- int n_dochan; /* num of DO chans */
- int n_ctrs; /* num of counters */
- int ai_maxdata; /* resolution of A/D */
- int ao_maxdata; /* resolution of D/A */
- const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */
- const char *rangecode; /* range codes for programming */
- const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */
-};
struct icp_multi_private {
- struct pcilst_struct *card; /* pointer to card */
char valid; /* card is usable */
void __iomem *io_addr; /* Pointer to mapped io address */
- resource_size_t phys_iobase; /* Physical io address */
unsigned int AdcCmdStatus; /* ADC Command/Status register */
unsigned int DacCmdStatus; /* DAC Command/Status register */
unsigned int IntEnable; /* Interrupt Enable register */
@@ -164,40 +130,14 @@ struct icp_multi_private {
unsigned int do_data; /* Remember digital output data */
};
-#define devpriv ((struct icp_multi_private *)dev->private)
-#define this_board ((const struct boardtype *)dev->board_ptr)
-
-/*
-==============================================================================
-
-Name: setup_channel_list
-
-Description:
- This function sets the appropriate channel selection,
- differential input mode and range bits in the ADC Command/
- Status register.
-
-Parameters:
- struct comedi_device *dev Pointer to current service structure
- struct comedi_subdevice *s Pointer to current subdevice structure
- unsigned int *chanlist Pointer to packed channel list
- unsigned int n_chan Number of channels to scan
-
-Returns:Void
-
-==============================================================================
-*/
static void setup_channel_list(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned int *chanlist, unsigned int n_chan)
{
+ struct icp_multi_private *devpriv = dev->private;
unsigned int i, range, chanprog;
unsigned int diff;
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG
- "icp multi EDBG: setup_channel_list(...,%d)\n", n_chan);
-#endif
devpriv->act_chanlist_len = n_chan;
devpriv->act_chanlist_pos = 0;
@@ -228,50 +168,23 @@ static void setup_channel_list(struct comedi_device *dev,
devpriv->AdcCmdStatus |= (chanprog << 8);
/* Get range for current channel */
- range = this_board->rangecode[CR_RANGE(chanlist[i])];
+ range = range_codes_analog[CR_RANGE(chanlist[i])];
/* Set range. bits 4-5 */
devpriv->AdcCmdStatus |= range;
/* Output channel, range, mode to ICP Multi */
writew(devpriv->AdcCmdStatus,
devpriv->io_addr + ICP_MULTI_ADC_CSR);
-
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG
- "GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range,
- devpriv->act_chanlist[i]);
-#endif
}
-
}
-/*
-==============================================================================
-
-Name: icp_multi_insn_read_ai
-
-Description:
- This function reads a single analogue input.
-
-Parameters:
- struct comedi_device *dev Pointer to current device structure
- struct comedi_subdevice *s Pointer to current subdevice structure
- struct comedi_insn *insn Pointer to current comedi instruction
- unsigned int *data Pointer to analogue input data
-
-Returns:int Nmuber of instructions executed
-
-==============================================================================
-*/
static int icp_multi_insn_read_ai(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct icp_multi_private *devpriv = dev->private;
int n, timeout;
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG "icp multi EDBG: BGN: icp_multi_insn_read_ai(...)\n");
-#endif
/* Disable A/D conversion ready interrupt */
devpriv->IntEnable &= ~ADC_READY;
writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN);
@@ -283,12 +196,6 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev,
/* Set up appropriate channel, mode and range data, for specified ch */
setup_channel_list(dev, s, &insn->chanspec, 1);
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG "icp_multi A ST=%4x IO=%p\n",
- readw(devpriv->io_addr + ICP_MULTI_ADC_CSR),
- devpriv->io_addr + ICP_MULTI_ADC_CSR);
-#endif
-
for (n = 0; n < insn->n; n++) {
/* Set start ADC bit */
devpriv->AdcCmdStatus |= ADC_ST;
@@ -296,18 +203,8 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev,
devpriv->io_addr + ICP_MULTI_ADC_CSR);
devpriv->AdcCmdStatus &= ~ADC_ST;
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG "icp multi B n=%d ST=%4x\n", n,
- readw(devpriv->io_addr + ICP_MULTI_ADC_CSR));
-#endif
-
udelay(1);
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG "icp multi C n=%d ST=%4x\n", n,
- readw(devpriv->io_addr + ICP_MULTI_ADC_CSR));
-#endif
-
/* Wait for conversion to complete, or get fed up waiting */
timeout = 100;
while (timeout--) {
@@ -315,15 +212,6 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev,
ICP_MULTI_ADC_CSR) & ADC_BSY))
goto conv_finish;
-#ifdef ICP_MULTI_EXTDEBUG
- if (!(timeout % 10))
- printk(KERN_DEBUG
- "icp multi D n=%d tm=%d ST=%4x\n", n,
- timeout,
- readw(devpriv->io_addr +
- ICP_MULTI_ADC_CSR));
-#endif
-
udelay(1);
}
@@ -342,11 +230,6 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev,
/* Clear data received */
data[n] = 0;
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG
- "icp multi EDBG: END: icp_multi_insn_read_ai(...) n=%d\n",
- n);
-#endif
return -ETIME;
conv_finish:
@@ -362,41 +245,16 @@ conv_finish:
devpriv->IntStatus |= ADC_READY;
writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT);
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG
- "icp multi EDBG: END: icp_multi_insn_read_ai(...) n=%d\n", n);
-#endif
return n;
}
-/*
-==============================================================================
-
-Name: icp_multi_insn_write_ao
-
-Description:
- This function writes a single analogue output.
-
-Parameters:
- struct comedi_device *dev Pointer to current device structure
- struct comedi_subdevice *s Pointer to current subdevice structure
- struct comedi_insn *insn Pointer to current comedi instruction
- unsigned int *data Pointer to analogue output data
-
-Returns:int Nmuber of instructions executed
-
-==============================================================================
-*/
static int icp_multi_insn_write_ao(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct icp_multi_private *devpriv = dev->private;
int n, chan, range, timeout;
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG
- "icp multi EDBG: BGN: icp_multi_insn_write_ao(...)\n");
-#endif
/* Disable D/A conversion ready interrupt */
devpriv->IntEnable &= ~DAC_READY;
writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN);
@@ -415,7 +273,7 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev,
/* Bit 5 = 1 : 10V */
/* Bits 8-9 : Channel number */
devpriv->DacCmdStatus &= 0xfccf;
- devpriv->DacCmdStatus |= this_board->rangecode[range];
+ devpriv->DacCmdStatus |= range_codes_analog[range];
devpriv->DacCmdStatus |= (chan << 8);
writew(devpriv->DacCmdStatus, devpriv->io_addr + ICP_MULTI_DAC_CSR);
@@ -429,15 +287,6 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev,
ICP_MULTI_DAC_CSR) & DAC_BSY))
goto dac_ready;
-#ifdef ICP_MULTI_EXTDEBUG
- if (!(timeout % 10))
- printk(KERN_DEBUG
- "icp multi A n=%d tm=%d ST=%4x\n", n,
- timeout,
- readw(devpriv->io_addr +
- ICP_MULTI_DAC_CSR));
-#endif
-
udelay(1);
}
@@ -456,11 +305,6 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev,
/* Clear data received */
devpriv->ao_data[chan] = 0;
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG
- "icp multi EDBG: END: icp_multi_insn_write_ao(...) n=%d\n",
- n);
-#endif
return -ETIME;
dac_ready:
@@ -477,35 +321,14 @@ dac_ready:
devpriv->ao_data[chan] = data[n];
}
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG
- "icp multi EDBG: END: icp_multi_insn_write_ao(...) n=%d\n", n);
-#endif
return n;
}
-/*
-==============================================================================
-
-Name: icp_multi_insn_read_ao
-
-Description:
- This function reads a single analogue output.
-
-Parameters:
- struct comedi_device *dev Pointer to current device structure
- struct comedi_subdevice *s Pointer to current subdevice structure
- struct comedi_insn *insn Pointer to current comedi instruction
- unsigned int *data Pointer to analogue output data
-
-Returns:int Nmuber of instructions executed
-
-==============================================================================
-*/
static int icp_multi_insn_read_ao(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct icp_multi_private *devpriv = dev->private;
int n, chan;
/* Get channel number */
@@ -518,58 +341,22 @@ static int icp_multi_insn_read_ao(struct comedi_device *dev,
return n;
}
-/*
-==============================================================================
-
-Name: icp_multi_insn_bits_di
-
-Description:
- This function reads the digital inputs.
-
-Parameters:
- struct comedi_device *dev Pointer to current device structure
- struct comedi_subdevice *s Pointer to current subdevice structure
- struct comedi_insn *insn Pointer to current comedi instruction
- unsigned int *data Pointer to analogue output data
-
-Returns:int Nmuber of instructions executed
-
-==============================================================================
-*/
static int icp_multi_insn_bits_di(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct icp_multi_private *devpriv = dev->private;
+
data[1] = readw(devpriv->io_addr + ICP_MULTI_DI);
return insn->n;
}
-/*
-==============================================================================
-
-Name: icp_multi_insn_bits_do
-
-Description:
- This function writes the appropriate digital outputs.
-
-Parameters:
- struct comedi_device *dev Pointer to current device structure
- struct comedi_subdevice *s Pointer to current subdevice structure
- struct comedi_insn *insn Pointer to current comedi instruction
- unsigned int *data Pointer to analogue output data
-
-Returns:int Nmuber of instructions executed
-
-==============================================================================
-*/
static int icp_multi_insn_bits_do(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG "icp multi EDBG: BGN: icp_multi_insn_bits_do(...)\n");
-#endif
+ struct icp_multi_private *devpriv = dev->private;
if (data[0]) {
s->state &= ~data[0];
@@ -582,30 +369,9 @@ static int icp_multi_insn_bits_do(struct comedi_device *dev,
data[1] = readw(devpriv->io_addr + ICP_MULTI_DI);
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG "icp multi EDBG: END: icp_multi_insn_bits_do(...)\n");
-#endif
return insn->n;
}
-/*
-==============================================================================
-
-Name: icp_multi_insn_read_ctr
-
-Description:
- This function reads the specified counter.
-
-Parameters:
- struct comedi_device *dev Pointer to current device structure
- struct comedi_subdevice *s Pointer to current subdevice structure
- struct comedi_insn *insn Pointer to current comedi instruction
- unsigned int *data Pointer to counter data
-
-Returns:int Nmuber of instructions executed
-
-==============================================================================
-*/
static int icp_multi_insn_read_ctr(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
@@ -613,24 +379,6 @@ static int icp_multi_insn_read_ctr(struct comedi_device *dev,
return 0;
}
-/*
-==============================================================================
-
-Name: icp_multi_insn_write_ctr
-
-Description:
- This function write to the specified counter.
-
-Parameters:
- struct comedi_device *dev Pointer to current device structure
- struct comedi_subdevice *s Pointer to current subdevice structure
- struct comedi_insn *insn Pointer to current comedi instruction
- unsigned int *data Pointer to counter data
-
-Returns:int Nmuber of instructions executed
-
-==============================================================================
-*/
static int icp_multi_insn_write_ctr(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
@@ -639,44 +387,18 @@ static int icp_multi_insn_write_ctr(struct comedi_device *dev,
return 0;
}
-/*
-==============================================================================
-
-Name: interrupt_service_icp_multi
-
-Description:
- This function is the interrupt service routine for all
- interrupts generated by the icp multi board.
-
-Parameters:
- int irq
- void *d Pointer to current device
-
-==============================================================================
-*/
static irqreturn_t interrupt_service_icp_multi(int irq, void *d)
{
struct comedi_device *dev = d;
+ struct icp_multi_private *devpriv = dev->private;
int int_no;
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG
- "icp multi EDBG: BGN: interrupt_service_icp_multi(%d,...)\n",
- irq);
-#endif
-
/* Is this interrupt from our board? */
int_no = readw(devpriv->io_addr + ICP_MULTI_INT_STAT) & Status_IRQ;
if (!int_no)
/* No, exit */
return IRQ_NONE;
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG
- "icp multi EDBG: interrupt_service_icp_multi() ST: %4x\n",
- readw(devpriv->io_addr + ICP_MULTI_INT_STAT));
-#endif
-
/* Determine which interrupt is active & handle it */
switch (int_no) {
case ADC_READY:
@@ -700,44 +422,16 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d)
}
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG
- "icp multi EDBG: END: interrupt_service_icp_multi(...)\n");
-#endif
return IRQ_HANDLED;
}
#if 0
-/*
-==============================================================================
-
-Name: check_channel_list
-
-Description:
- This function checks if the channel list, provided by user
- is built correctly
-
-Parameters:
- struct comedi_device *dev Pointer to current service structure
- struct comedi_subdevice *s Pointer to current subdevice structure
- unsigned int *chanlist Pointer to packed channel list
- unsigned int n_chan Number of channels to scan
-
-Returns:int 0 = failure
- 1 = success
-
-==============================================================================
-*/
static int check_channel_list(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned int *chanlist, unsigned int n_chan)
{
unsigned int i;
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG
- "icp multi EDBG: check_channel_list(...,%d)\n", n_chan);
-#endif
/* Check that we at least have one channel to check */
if (n_chan < 1) {
comedi_error(dev, "range/channel list is empty!");
@@ -747,13 +441,13 @@ static int check_channel_list(struct comedi_device *dev,
for (i = 0; i < n_chan; i++) {
/* Check that channel number is < maximum */
if (CR_AREF(chanlist[i]) == AREF_DIFF) {
- if (CR_CHAN(chanlist[i]) > this_board->n_aichand) {
+ if (CR_CHAN(chanlist[i]) > (s->nchan / 2)) {
comedi_error(dev,
"Incorrect differential ai ch-nr");
return 0;
}
} else {
- if (CR_CHAN(chanlist[i]) > this_board->n_aichan) {
+ if (CR_CHAN(chanlist[i]) > s->n_chan) {
comedi_error(dev,
"Incorrect ai channel number");
return 0;
@@ -764,295 +458,189 @@ static int check_channel_list(struct comedi_device *dev,
}
#endif
-/*
-==============================================================================
-
-Name: icp_multi_reset
-
-Description:
- This function resets the icp multi device to a 'safe' state
-
-Parameters:
- struct comedi_device *dev Pointer to current service structure
-
-Returns:int 0 = success
-
-==============================================================================
-*/
static int icp_multi_reset(struct comedi_device *dev)
{
+ struct icp_multi_private *devpriv = dev->private;
unsigned int i;
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG
- "icp_multi EDBG: BGN: icp_multi_reset(...)\n");
-#endif
/* Clear INT enables and requests */
writew(0, devpriv->io_addr + ICP_MULTI_INT_EN);
writew(0x00ff, devpriv->io_addr + ICP_MULTI_INT_STAT);
- if (this_board->n_aochan)
- /* Set DACs to 0..5V range and 0V output */
- for (i = 0; i < this_board->n_aochan; i++) {
- devpriv->DacCmdStatus &= 0xfcce;
+ /* Set DACs to 0..5V range and 0V output */
+ for (i = 0; i < 4; i++) {
+ devpriv->DacCmdStatus &= 0xfcce;
+
+ /* Set channel number */
+ devpriv->DacCmdStatus |= (i << 8);
- /* Set channel number */
- devpriv->DacCmdStatus |= (i << 8);
+ /* Output 0V */
+ writew(0, devpriv->io_addr + ICP_MULTI_AO);
- /* Output 0V */
- writew(0, devpriv->io_addr + ICP_MULTI_AO);
+ /* Set start conversion bit */
+ devpriv->DacCmdStatus |= DAC_ST;
- /* Set start conversion bit */
- devpriv->DacCmdStatus |= DAC_ST;
+ /* Output to command / status register */
+ writew(devpriv->DacCmdStatus,
+ devpriv->io_addr + ICP_MULTI_DAC_CSR);
- /* Output to command / status register */
- writew(devpriv->DacCmdStatus,
- devpriv->io_addr + ICP_MULTI_DAC_CSR);
+ /* Delay to allow DAC time to recover */
+ udelay(1);
+ }
- /* Delay to allow DAC time to recover */
- udelay(1);
- }
- /* Digital outputs to 0 */
+ /* Digital outputs to 0 */
writew(0, devpriv->io_addr + ICP_MULTI_DO);
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG
- "icp multi EDBG: END: icp_multi_reset(...)\n");
-#endif
return 0;
}
-static int icp_multi_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int icp_multi_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
+ struct icp_multi_private *devpriv;
struct comedi_subdevice *s;
- int ret, subdev, n_subdevices;
- unsigned int irq;
- struct pcilst_struct *card = NULL;
- resource_size_t io_addr[5], iobase;
- unsigned char pci_bus, pci_slot, pci_func;
+ resource_size_t iobase;
+ int ret;
- printk(KERN_WARNING
- "icp_multi EDBG: BGN: icp_multi_attach(...)\n");
+ comedi_set_hw_dev(dev, &pcidev->dev);
+ dev->board_name = dev->driver->driver_name;
- /* Allocate private data storage space */
- ret = alloc_private(dev, sizeof(struct icp_multi_private));
+ ret = alloc_private(dev, sizeof(*devpriv));
if (ret < 0)
return ret;
+ devpriv = dev->private;
- /* Initialise list of PCI cards in system, if not already done so */
- if (pci_list_builded++ == 0) {
- pci_card_list_init(PCI_VENDOR_ID_ICP,
-#ifdef ICP_MULTI_EXTDEBUG
- 1
-#else
- 0
-#endif
- );
- }
-
- printk(KERN_WARNING
- "Anne's comedi%d: icp_multi: board=%s", dev->minor,
- this_board->name);
-
- card = select_and_alloc_pci_card(PCI_VENDOR_ID_ICP,
- this_board->device_id, it->options[0],
- it->options[1]);
-
- if (card == NULL)
- return -EIO;
-
- devpriv->card = card;
-
- if ((pci_card_data(card, &pci_bus, &pci_slot, &pci_func, &io_addr[0],
- &irq)) < 0) {
- printk(KERN_WARNING " - Can't get configuration data!\n");
- return -EIO;
- }
-
- iobase = io_addr[2];
- devpriv->phys_iobase = iobase;
-
- printk(KERN_WARNING
- ", b:s:f=%d:%d:%d, io=0x%8llx \n", pci_bus, pci_slot, pci_func,
- (unsigned long long)iobase);
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
+ iobase = pci_resource_start(pcidev, 2);
+ dev->iobase = iobase;
devpriv->io_addr = ioremap(iobase, ICP_MULTI_SIZE);
-
- if (devpriv->io_addr == NULL) {
- printk(KERN_WARNING "ioremap failed.\n");
+ if (!devpriv->io_addr)
return -ENOMEM;
- }
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG
- "0x%08llx mapped to %p, ", (unsigned long long)iobase,
- devpriv->io_addr);
-#endif
- dev->board_name = this_board->name;
-
- n_subdevices = 0;
- if (this_board->n_aichan)
- n_subdevices++;
- if (this_board->n_aochan)
- n_subdevices++;
- if (this_board->n_dichan)
- n_subdevices++;
- if (this_board->n_dochan)
- n_subdevices++;
- if (this_board->n_ctrs)
- n_subdevices++;
-
- ret = comedi_alloc_subdevices(dev, n_subdevices);
+ ret = comedi_alloc_subdevices(dev, 5);
if (ret)
return ret;
icp_multi_reset(dev);
- if (this_board->have_irq) {
- if (irq) {
- if (request_irq(irq, interrupt_service_icp_multi,
- IRQF_SHARED, "Inova Icp Multi", dev)) {
- printk(KERN_WARNING
- "unable to allocate IRQ %u, DISABLING IT",
- irq);
- irq = 0; /* Can't use IRQ */
- } else
- printk(KERN_WARNING ", irq=%u", irq);
- } else
- printk(KERN_WARNING ", IRQ disabled");
- } else
- irq = 0;
-
- dev->irq = irq;
-
- printk(KERN_WARNING ".\n");
-
- subdev = 0;
-
- if (this_board->n_aichan) {
- s = dev->subdevices + subdev;
- dev->read_subdev = s;
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND;
- if (this_board->n_aichand)
- s->subdev_flags |= SDF_DIFF;
- s->n_chan = this_board->n_aichan;
- s->maxdata = this_board->ai_maxdata;
- s->len_chanlist = this_board->n_aichan;
- s->range_table = this_board->rangelist_ai;
- s->insn_read = icp_multi_insn_read_ai;
- subdev++;
+ if (pcidev->irq) {
+ ret = request_irq(pcidev->irq, interrupt_service_icp_multi,
+ IRQF_SHARED, dev->board_name, dev);
+ if (ret == 0)
+ dev->irq = pcidev->irq;
}
- if (this_board->n_aochan) {
- s = dev->subdevices + subdev;
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = this_board->n_aochan;
- s->maxdata = this_board->ao_maxdata;
- s->len_chanlist = this_board->n_aochan;
- s->range_table = this_board->rangelist_ao;
- s->insn_write = icp_multi_insn_write_ao;
- s->insn_read = icp_multi_insn_read_ao;
- subdev++;
- }
-
- if (this_board->n_dichan) {
- s = dev->subdevices + subdev;
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE;
- s->n_chan = this_board->n_dichan;
- s->maxdata = 1;
- s->len_chanlist = this_board->n_dichan;
- s->range_table = &range_digital;
- s->io_bits = 0;
- s->insn_bits = icp_multi_insn_bits_di;
- subdev++;
- }
-
- if (this_board->n_dochan) {
- s = dev->subdevices + subdev;
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
- s->n_chan = this_board->n_dochan;
- s->maxdata = 1;
- s->len_chanlist = this_board->n_dochan;
- s->range_table = &range_digital;
- s->io_bits = (1 << this_board->n_dochan) - 1;
- s->state = 0;
- s->insn_bits = icp_multi_insn_bits_do;
- subdev++;
- }
-
- if (this_board->n_ctrs) {
- s = dev->subdevices + subdev;
- s->type = COMEDI_SUBD_COUNTER;
- s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = this_board->n_ctrs;
- s->maxdata = 0xffff;
- s->len_chanlist = this_board->n_ctrs;
- s->state = 0;
- s->insn_read = icp_multi_insn_read_ctr;
- s->insn_write = icp_multi_insn_write_ctr;
- subdev++;
- }
+ s = &dev->subdevices[0];
+ dev->read_subdev = s;
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
+ s->n_chan = 16;
+ s->maxdata = 0x0fff;
+ s->len_chanlist = 16;
+ s->range_table = &range_analog;
+ s->insn_read = icp_multi_insn_read_ai;
+
+ s = &dev->subdevices[1];
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
+ s->n_chan = 4;
+ s->maxdata = 0x0fff;
+ s->len_chanlist = 4;
+ s->range_table = &range_analog;
+ s->insn_write = icp_multi_insn_write_ao;
+ s->insn_read = icp_multi_insn_read_ao;
+
+ s = &dev->subdevices[2];
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 16;
+ s->maxdata = 1;
+ s->len_chanlist = 16;
+ s->range_table = &range_digital;
+ s->io_bits = 0;
+ s->insn_bits = icp_multi_insn_bits_di;
+
+ s = &dev->subdevices[3];
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+ s->n_chan = 8;
+ s->maxdata = 1;
+ s->len_chanlist = 8;
+ s->range_table = &range_digital;
+ s->io_bits = 0xff;
+ s->state = 0;
+ s->insn_bits = icp_multi_insn_bits_do;
+
+ s = &dev->subdevices[4];
+ s->type = COMEDI_SUBD_COUNTER;
+ s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
+ s->n_chan = 4;
+ s->maxdata = 0xffff;
+ s->len_chanlist = 4;
+ s->state = 0;
+ s->insn_read = icp_multi_insn_read_ctr;
+ s->insn_write = icp_multi_insn_write_ctr;
devpriv->valid = 1;
-#ifdef ICP_MULTI_EXTDEBUG
- printk(KERN_DEBUG "icp multi EDBG: END: icp_multi_attach(...)\n");
-#endif
+ dev_info(dev->class_dev, "%s attached, irq %sabled\n",
+ dev->board_name, dev->irq ? "en" : "dis");
return 0;
}
static void icp_multi_detach(struct comedi_device *dev)
{
- if (dev->private)
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ struct icp_multi_private *devpriv = dev->private;
+
+ if (devpriv)
if (devpriv->valid)
icp_multi_reset(dev);
if (dev->irq)
free_irq(dev->irq, dev);
- if (dev->private && devpriv->io_addr)
+ if (devpriv && devpriv->io_addr)
iounmap(devpriv->io_addr);
- if (dev->private && devpriv->card)
- pci_card_free(devpriv->card);
- if (--pci_list_builded == 0)
- pci_card_list_cleanup(PCI_VENDOR_ID_ICP);
+ if (pcidev) {
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
+ }
}
-static const struct boardtype boardtypes[] = {
- {
- .name = "icp_multi",
- .device_id = DEVICE_ID,
- .iorange = IORANGE_ICP_MULTI,
- .have_irq = 1,
- .cardtype = TYPE_ICP_MULTI,
- .n_aichan = 16,
- .n_aichand = 8,
- .n_aochan = 4,
- .n_dichan = 16,
- .n_dochan = 8,
- .n_ctrs = 4,
- .ai_maxdata = 0x0fff,
- .ao_maxdata = 0x0fff,
- .rangelist_ai = &range_analog,
- .rangecode = range_codes_analog,
- .rangelist_ao = &range_analog,
- },
-};
-
static struct comedi_driver icp_multi_driver = {
.driver_name = "icp_multi",
.module = THIS_MODULE,
- .attach = icp_multi_attach,
+ .attach_pci = icp_multi_attach_pci,
.detach = icp_multi_detach,
- .num_names = ARRAY_SIZE(boardtypes),
- .board_name = &boardtypes[0].name,
- .offset = sizeof(struct boardtype),
};
-module_comedi_driver(icp_multi_driver);
+
+static int __devinit icp_multi_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ return comedi_pci_auto_config(dev, &icp_multi_driver);
+}
+
+static void __devexit icp_multi_pci_remove(struct pci_dev *dev)
+{
+ comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(icp_multi_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ICP, PCI_DEVICE_ID_ICP_MULTI) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, icp_multi_pci_table);
+
+static struct pci_driver icp_multi_pci_driver = {
+ .name = "icp_multi",
+ .id_table = icp_multi_pci_table,
+ .probe = icp_multi_pci_probe,
+ .remove = __devexit_p(icp_multi_pci_remove),
+};
+module_comedi_pci_driver(icp_multi_driver, icp_multi_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/icp_multi.h b/drivers/staging/comedi/drivers/icp_multi.h
deleted file mode 100644
index dbf9908cfde6..000000000000
--- a/drivers/staging/comedi/drivers/icp_multi.h
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- comedi/drivers/icp_multi.h
-
- Stuff for ICP Multi
-
- Author: Anne Smorthit <anne.smorthit@sfwte.ch>
-
-*/
-
-#ifndef _ICP_MULTI_H_
-#define _ICP_MULTI_H_
-
-#include "../comedidev.h"
-
-/****************************************************************************/
-
-struct pcilst_struct {
- struct pcilst_struct *next;
- int used;
- struct pci_dev *pcidev;
- unsigned short vendor;
- unsigned short device;
- unsigned char pci_bus;
- unsigned char pci_slot;
- unsigned char pci_func;
- resource_size_t io_addr[5];
- unsigned int irq;
-};
-
-struct pcilst_struct *inova_devices;
-/* ptr to root list of all Inova devices */
-
-/****************************************************************************/
-
-static void pci_card_list_init(unsigned short pci_vendor, char display);
-static void pci_card_list_cleanup(unsigned short pci_vendor);
-static struct pcilst_struct *find_free_pci_card_by_device(unsigned short
- vendor_id,
- unsigned short
- device_id);
-static int find_free_pci_card_by_position(unsigned short vendor_id,
- unsigned short device_id,
- unsigned short pci_bus,
- unsigned short pci_slot,
- struct pcilst_struct **card);
-static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
- unsigned short device_id,
- unsigned short pci_bus,
- unsigned short pci_slot);
-
-static int pci_card_alloc(struct pcilst_struct *amcc);
-static int pci_card_free(struct pcilst_struct *amcc);
-static void pci_card_list_display(void);
-static int pci_card_data(struct pcilst_struct *amcc,
- unsigned char *pci_bus, unsigned char *pci_slot,
- unsigned char *pci_func, resource_size_t * io_addr,
- unsigned int *irq);
-
-/****************************************************************************/
-
-/* build list of Inova cards in this system */
-static void pci_card_list_init(unsigned short pci_vendor, char display)
-{
- struct pci_dev *pcidev = NULL;
- struct pcilst_struct *inova, *last;
- int i;
-
- inova_devices = NULL;
- last = NULL;
-
- for_each_pci_dev(pcidev) {
- if (pcidev->vendor == pci_vendor) {
- inova = kzalloc(sizeof(*inova), GFP_KERNEL);
- if (!inova) {
- printk
- ("icp_multi: pci_card_list_init: allocation failed\n");
- pci_dev_put(pcidev);
- break;
- }
-
- inova->pcidev = pci_dev_get(pcidev);
- if (last) {
- last->next = inova;
- } else {
- inova_devices = inova;
- }
- last = inova;
-
- inova->vendor = pcidev->vendor;
- inova->device = pcidev->device;
- inova->pci_bus = pcidev->bus->number;
- inova->pci_slot = PCI_SLOT(pcidev->devfn);
- inova->pci_func = PCI_FUNC(pcidev->devfn);
- /* Note: resources may be invalid if PCI device
- * not enabled, but they are corrected in
- * pci_card_alloc. */
- for (i = 0; i < 5; i++)
- inova->io_addr[i] =
- pci_resource_start(pcidev, i);
- inova->irq = pcidev->irq;
- }
- }
-
- if (display)
- pci_card_list_display();
-}
-
-/****************************************************************************/
-/* free up list of amcc cards in this system */
-static void pci_card_list_cleanup(unsigned short pci_vendor)
-{
- struct pcilst_struct *inova, *next;
-
- for (inova = inova_devices; inova; inova = next) {
- next = inova->next;
- pci_dev_put(inova->pcidev);
- kfree(inova);
- }
-
- inova_devices = NULL;
-}
-
-/****************************************************************************/
-/* find first unused card with this device_id */
-static struct pcilst_struct *find_free_pci_card_by_device(unsigned short
- vendor_id,
- unsigned short
- device_id)
-{
- struct pcilst_struct *inova, *next;
-
- for (inova = inova_devices; inova; inova = next) {
- next = inova->next;
- if ((!inova->used) && (inova->device == device_id)
- && (inova->vendor == vendor_id))
- return inova;
-
- }
-
- return NULL;
-}
-
-/****************************************************************************/
-/* find card on requested position */
-static int find_free_pci_card_by_position(unsigned short vendor_id,
- unsigned short device_id,
- unsigned short pci_bus,
- unsigned short pci_slot,
- struct pcilst_struct **card)
-{
- struct pcilst_struct *inova, *next;
-
- *card = NULL;
- for (inova = inova_devices; inova; inova = next) {
- next = inova->next;
- if ((inova->vendor == vendor_id) && (inova->device == device_id)
- && (inova->pci_bus == pci_bus)
- && (inova->pci_slot == pci_slot)) {
- if (!(inova->used)) {
- *card = inova;
- return 0; /* ok, card is found */
- } else {
- return 2; /* card exist but is used */
- }
- }
- }
-
- return 1; /* no card found */
-}
-
-/****************************************************************************/
-/* mark card as used */
-static int pci_card_alloc(struct pcilst_struct *inova)
-{
- int i;
-
- if (!inova) {
- printk(" - BUG!! inova is NULL!\n");
- return -1;
- }
-
- if (inova->used)
- return 1;
- if (comedi_pci_enable(inova->pcidev, "icp_multi")) {
- printk(" - Can't enable PCI device and request regions!\n");
- return -1;
- }
- /* Resources will be accurate now. */
- for (i = 0; i < 5; i++)
- inova->io_addr[i] = pci_resource_start(inova->pcidev, i);
- inova->irq = inova->pcidev->irq;
- inova->used = 1;
- return 0;
-}
-
-/****************************************************************************/
-/* mark card as free */
-static int pci_card_free(struct pcilst_struct *inova)
-{
- if (!inova)
- return -1;
-
- if (!inova->used)
- return 1;
- inova->used = 0;
- comedi_pci_disable(inova->pcidev);
- return 0;
-}
-
-/****************************************************************************/
-/* display list of found cards */
-static void pci_card_list_display(void)
-{
- struct pcilst_struct *inova, *next;
-
- printk("Anne's List of pci cards\n");
- printk("bus:slot:func vendor device io_inova io_daq irq used\n");
-
- for (inova = inova_devices; inova; inova = next) {
- next = inova->next;
- printk
- ("%2d %2d %2d 0x%4x 0x%4x 0x%8llx 0x%8llx %2u %2d\n",
- inova->pci_bus, inova->pci_slot, inova->pci_func,
- inova->vendor, inova->device,
- (unsigned long long)inova->io_addr[0],
- (unsigned long long)inova->io_addr[2], inova->irq,
- inova->used);
-
- }
-}
-
-/****************************************************************************/
-/* return all card information for driver */
-static int pci_card_data(struct pcilst_struct *inova,
- unsigned char *pci_bus, unsigned char *pci_slot,
- unsigned char *pci_func, resource_size_t * io_addr,
- unsigned int *irq)
-{
- int i;
-
- if (!inova)
- return -1;
- *pci_bus = inova->pci_bus;
- *pci_slot = inova->pci_slot;
- *pci_func = inova->pci_func;
- for (i = 0; i < 5; i++)
- io_addr[i] = inova->io_addr[i];
- *irq = inova->irq;
- return 0;
-}
-
-/****************************************************************************/
-/* select and alloc card */
-static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
- unsigned short device_id,
- unsigned short pci_bus,
- unsigned short pci_slot)
-{
- struct pcilst_struct *card;
- int err;
-
- if ((pci_bus < 1) & (pci_slot < 1)) { /* use autodetection */
-
- card = find_free_pci_card_by_device(vendor_id, device_id);
- if (card == NULL) {
- printk(" - Unused card not found in system!\n");
- return NULL;
- }
- } else {
- switch (find_free_pci_card_by_position(vendor_id, device_id,
- pci_bus, pci_slot,
- &card)) {
- case 1:
- printk
- (" - Card not found on requested position b:s %d:%d!\n",
- pci_bus, pci_slot);
- return NULL;
- case 2:
- printk
- (" - Card on requested position is used b:s %d:%d!\n",
- pci_bus, pci_slot);
- return NULL;
- }
- }
-
- err = pci_card_alloc(card);
- if (err != 0) {
- if (err > 0)
- printk(" - Can't allocate card!\n");
- /* else: error already printed. */
- return NULL;
- }
-
- return card;
-}
-
-#endif
diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
index 0f9cfe662b9a..65ff1c9b973c 100644
--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
+++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
@@ -224,7 +224,7 @@ static int pci20xxx_attach(struct comedi_device *dev,
dev->minor, devpriv->ioaddr);
for (i = 0; i < PCI20000_MODULES; i++) {
- s = dev->subdevices + i;
+ s = &dev->subdevices[i];
id = readb(devpriv->ioaddr + (i + 1) * PCI20000_OFFSET);
s->private = devpriv->subdev_private + i;
sdp = s->private;
@@ -259,7 +259,7 @@ static int pci20xxx_attach(struct comedi_device *dev,
}
/* initialize struct pci20xxx_private */
- pci20xxx_dio_init(dev, dev->subdevices + PCI20000_MODULES);
+ pci20xxx_dio_init(dev, &dev->subdevices[PCI20000_MODULES]);
return 1;
}
diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
index 93f94cd7bae2..4a108ea8a9aa 100644
--- a/drivers/staging/comedi/drivers/jr3_pci.c
+++ b/drivers/staging/comedi/drivers/jr3_pci.c
@@ -362,10 +362,11 @@ static int jr3_pci_open(struct comedi_device *dev)
return 0;
}
-int read_idm_word(const u8 * data, size_t size, int *pos, unsigned int *val)
+static int read_idm_word(const u8 *data, size_t size, int *pos,
+ unsigned int *val)
{
int result = 0;
- if (pos != 0 && val != 0) {
+ if (pos && val) {
/* Skip over non hex */
for (; *pos < size && !isxdigit(data[*pos]); (*pos)++) {
}
@@ -875,7 +876,7 @@ static int jr3_pci_attach(struct comedi_device *dev,
p->maxdata_list[56] = 0xffff;
p->maxdata_list[57] = 0xffff;
/* Channel specific range and maxdata */
- dev->subdevices[i].range_table = 0;
+ dev->subdevices[i].range_table = NULL;
dev->subdevices[i].range_table_list =
p->range_table_list;
dev->subdevices[i].maxdata = 0;
@@ -884,7 +885,7 @@ static int jr3_pci_attach(struct comedi_device *dev,
}
/* Reset DSP card */
- devpriv->iobase->channel[0].reset = 0;
+ writel(0, &devpriv->iobase->channel[0].reset);
result = comedi_load_firmware(dev, "jr3pci.idm", jr3_download_firmware);
dev_dbg(dev->class_dev, "Firmare load %d\n", result);
diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h
index a1469611d84e..9c42653d8f18 100644
--- a/drivers/staging/comedi/drivers/jr3_pci.h
+++ b/drivers/staging/comedi/drivers/jr3_pci.h
@@ -97,7 +97,7 @@ enum {
mz = 0x0020,
changeV2 = 0x0040,
changeV1 = 0x0080
-} vect_bits_t;
+};
/* WARNING_BITS */
/* The warning_bits structure shows the bit pattern for the warning
@@ -116,7 +116,7 @@ enum {
mx_near_sat = 0x0008,
my_near_sat = 0x0010,
mz_near_sat = 0x0020
-} warning_bits_t;
+};
/* ERROR_BITS */
/* XX_SAT */
diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
index d4e9292483a0..e867b720f666 100644
--- a/drivers/staging/comedi/drivers/ke_counter.c
+++ b/drivers/staging/comedi/drivers/ke_counter.c
@@ -28,11 +28,7 @@ Author: Michael Hillmann
Updated: Mon, 14 Apr 2008 15:42:42 +0100
Status: tested
-Configuration Options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
- If bus/slot is not specified, the first supported
- PCI device found will be used.
+Configuration Options: not applicable, uses PCI auto config
This driver is a simple driver to read the counter values from
Kolter Electronic PCI Counter Card.
@@ -111,82 +107,53 @@ static int cnt_rinsn(struct comedi_device *dev,
return 1;
}
-static struct pci_dev *cnt_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static const void *cnt_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
const struct cnt_board_struct *board;
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
int i;
- /* Probe the device to determine what device in the series it is. */
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (pcidev->bus->number != bus ||
- PCI_SLOT(pcidev->devfn) != slot)
- continue;
- }
- if (pcidev->vendor != PCI_VENDOR_ID_KOLTER)
- continue;
-
- for (i = 0; i < ARRAY_SIZE(cnt_boards); i++) {
- board = &cnt_boards[i];
- if (board->device_id != pcidev->device)
- continue;
-
- dev->board_ptr = board;
- return pcidev;
- }
+ for (i = 0; i < ARRAY_SIZE(cnt_boards); i++) {
+ board = &cnt_boards[i];
+ if (board->device_id == pcidev->device)
+ return board;
}
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
return NULL;
}
-static int cnt_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int cnt_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
const struct cnt_board_struct *board;
- struct pci_dev *pcidev;
- struct comedi_subdevice *subdevice;
- unsigned long io_base;
- int error;
-
- pcidev = cnt_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
+ struct comedi_subdevice *s;
+ int ret;
+
comedi_set_hw_dev(dev, &pcidev->dev);
- board = comedi_board(dev);
+ board = cnt_find_boardinfo(dev, pcidev);
+ if (!board)
+ return -ENODEV;
+ dev->board_ptr = board;
dev->board_name = board->name;
- /* enable PCI device and request regions */
- error = comedi_pci_enable(pcidev, CNT_DRIVER_NAME);
- if (error < 0) {
- printk(KERN_WARNING "comedi%d: "
- "failed to enable PCI device and request regions!\n",
- dev->minor);
- return error;
- }
-
- /* read register base address [PCI_BASE_ADDRESS #0] */
- io_base = pci_resource_start(pcidev, 0);
- dev->iobase = io_base;
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
+ dev->iobase = pci_resource_start(pcidev, 0);
- error = comedi_alloc_subdevices(dev, 1);
- if (error)
- return error;
+ ret = comedi_alloc_subdevices(dev, 1);
+ if (ret)
+ return ret;
- subdevice = dev->subdevices + 0;
- dev->read_subdev = subdevice;
+ s = &dev->subdevices[0];
+ dev->read_subdev = s;
- subdevice->type = COMEDI_SUBD_COUNTER;
- subdevice->subdev_flags = SDF_READABLE /* | SDF_COMMON */ ;
- subdevice->n_chan = board->cnt_channel_nbr;
- subdevice->maxdata = (1 << board->cnt_bits) - 1;
- subdevice->insn_read = cnt_rinsn;
- subdevice->insn_write = cnt_winsn;
+ s->type = COMEDI_SUBD_COUNTER;
+ s->subdev_flags = SDF_READABLE /* | SDF_COMMON */ ;
+ s->n_chan = board->cnt_channel_nbr;
+ s->maxdata = (1 << board->cnt_bits) - 1;
+ s->insn_read = cnt_rinsn;
+ s->insn_write = cnt_winsn;
/* select 20MHz clock */
outb(3, dev->iobase + 248);
@@ -196,8 +163,9 @@ static int cnt_attach(struct comedi_device *dev, struct comedi_devconfig *it)
outb(0, dev->iobase + 0x20);
outb(0, dev->iobase + 0x40);
- printk(KERN_INFO "comedi%d: " CNT_DRIVER_NAME " attached.\n",
- dev->minor);
+ dev_info(dev->class_dev, "%s: %s attached\n",
+ dev->driver->driver_name, dev->board_name);
+
return 0;
}
@@ -208,14 +176,13 @@ static void cnt_detach(struct comedi_device *dev)
if (pcidev) {
if (dev->iobase)
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
}
}
static struct comedi_driver ke_counter_driver = {
.driver_name = "ke_counter",
.module = THIS_MODULE,
- .attach = cnt_attach,
+ .attach_pci = cnt_attach_pci,
.detach = cnt_detach,
};
diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
index 9a8258e6fa45..22db35d091f8 100644
--- a/drivers/staging/comedi/drivers/me4000.c
+++ b/drivers/staging/comedi/drivers/me4000.c
@@ -35,13 +35,7 @@ Supports:
- Digital I/O
- Counter
-Configuration Options:
-
- [0] - PCI bus number (optional)
- [1] - PCI slot number (optional)
-
- If bus/slot is not specified, the first available PCI
- device will be used.
+Configuration Options: not applicable, uses PCI auto config
The firmware required by these boards is available in the
comedi_nonfree_firmware tarball available from
@@ -58,51 +52,306 @@ broken.
#include <linux/list.h>
#include <linux/spinlock.h>
-#include "me4000.h"
+#include "comedi_fc.h"
+#include "8253.h"
+
#if 0
/* file removed due to GPL incompatibility */
#include "me4000_fw.h"
#endif
-static const struct me4000_board me4000_boards[] = {
- {"ME-4650", 0x4650, {0, 0}, {16, 0, 0, 0}, {4}, {0} },
-
- {"ME-4660", 0x4660, {0, 0}, {32, 0, 16, 0}, {4}, {3} },
- {"ME-4660i", 0x4661, {0, 0}, {32, 0, 16, 0}, {4}, {3} },
- {"ME-4660s", 0x4662, {0, 0}, {32, 8, 16, 0}, {4}, {3} },
- {"ME-4660is", 0x4663, {0, 0}, {32, 8, 16, 0}, {4}, {3} },
-
- {"ME-4670", 0x4670, {4, 0}, {32, 0, 16, 1}, {4}, {3} },
- {"ME-4670i", 0x4671, {4, 0}, {32, 0, 16, 1}, {4}, {3} },
- {"ME-4670s", 0x4672, {4, 0}, {32, 8, 16, 1}, {4}, {3} },
- {"ME-4670is", 0x4673, {4, 0}, {32, 8, 16, 1}, {4}, {3} },
+#define PCI_VENDOR_ID_MEILHAUS 0x1402
+
+#define PCI_DEVICE_ID_MEILHAUS_ME4650 0x4650
+#define PCI_DEVICE_ID_MEILHAUS_ME4660 0x4660
+#define PCI_DEVICE_ID_MEILHAUS_ME4660I 0x4661
+#define PCI_DEVICE_ID_MEILHAUS_ME4660S 0x4662
+#define PCI_DEVICE_ID_MEILHAUS_ME4660IS 0x4663
+#define PCI_DEVICE_ID_MEILHAUS_ME4670 0x4670
+#define PCI_DEVICE_ID_MEILHAUS_ME4670I 0x4671
+#define PCI_DEVICE_ID_MEILHAUS_ME4670S 0x4672
+#define PCI_DEVICE_ID_MEILHAUS_ME4670IS 0x4673
+#define PCI_DEVICE_ID_MEILHAUS_ME4680 0x4680
+#define PCI_DEVICE_ID_MEILHAUS_ME4680I 0x4681
+#define PCI_DEVICE_ID_MEILHAUS_ME4680S 0x4682
+#define PCI_DEVICE_ID_MEILHAUS_ME4680IS 0x4683
- {"ME-4680", 0x4680, {4, 4}, {32, 0, 16, 1}, {4}, {3} },
- {"ME-4680i", 0x4681, {4, 4}, {32, 0, 16, 1}, {4}, {3} },
- {"ME-4680s", 0x4682, {4, 4}, {32, 8, 16, 1}, {4}, {3} },
- {"ME-4680is", 0x4683, {4, 4}, {32, 8, 16, 1}, {4}, {3} },
+/*
+ * ME4000 Register map and bit defines
+ */
+#define ME4000_AO_CHAN(x) ((x) * 0x18)
+
+#define ME4000_AO_CTRL_REG(x) (0x00 + ME4000_AO_CHAN(x))
+#define ME4000_AO_CTRL_BIT_MODE_0 (1 << 0)
+#define ME4000_AO_CTRL_BIT_MODE_1 (1 << 1)
+#define ME4000_AO_CTRL_MASK_MODE (3 << 0)
+#define ME4000_AO_CTRL_BIT_STOP (1 << 2)
+#define ME4000_AO_CTRL_BIT_ENABLE_FIFO (1 << 3)
+#define ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG (1 << 4)
+#define ME4000_AO_CTRL_BIT_EX_TRIG_EDGE (1 << 5)
+#define ME4000_AO_CTRL_BIT_IMMEDIATE_STOP (1 << 7)
+#define ME4000_AO_CTRL_BIT_ENABLE_DO (1 << 8)
+#define ME4000_AO_CTRL_BIT_ENABLE_IRQ (1 << 9)
+#define ME4000_AO_CTRL_BIT_RESET_IRQ (1 << 10)
+#define ME4000_AO_STATUS_REG(x) (0x04 + ME4000_AO_CHAN(x))
+#define ME4000_AO_STATUS_BIT_FSM (1 << 0)
+#define ME4000_AO_STATUS_BIT_FF (1 << 1)
+#define ME4000_AO_STATUS_BIT_HF (1 << 2)
+#define ME4000_AO_STATUS_BIT_EF (1 << 3)
+#define ME4000_AO_FIFO_REG(x) (0x08 + ME4000_AO_CHAN(x))
+#define ME4000_AO_SINGLE_REG(x) (0x0c + ME4000_AO_CHAN(x))
+#define ME4000_AO_TIMER_REG(x) (0x10 + ME4000_AO_CHAN(x))
+#define ME4000_AI_CTRL_REG 0x74
+#define ME4000_AI_STATUS_REG 0x74
+#define ME4000_AI_CTRL_BIT_MODE_0 (1 << 0)
+#define ME4000_AI_CTRL_BIT_MODE_1 (1 << 1)
+#define ME4000_AI_CTRL_BIT_MODE_2 (1 << 2)
+#define ME4000_AI_CTRL_BIT_SAMPLE_HOLD (1 << 3)
+#define ME4000_AI_CTRL_BIT_IMMEDIATE_STOP (1 << 4)
+#define ME4000_AI_CTRL_BIT_STOP (1 << 5)
+#define ME4000_AI_CTRL_BIT_CHANNEL_FIFO (1 << 6)
+#define ME4000_AI_CTRL_BIT_DATA_FIFO (1 << 7)
+#define ME4000_AI_CTRL_BIT_FULLSCALE (1 << 8)
+#define ME4000_AI_CTRL_BIT_OFFSET (1 << 9)
+#define ME4000_AI_CTRL_BIT_EX_TRIG_ANALOG (1 << 10)
+#define ME4000_AI_CTRL_BIT_EX_TRIG (1 << 11)
+#define ME4000_AI_CTRL_BIT_EX_TRIG_FALLING (1 << 12)
+#define ME4000_AI_CTRL_BIT_EX_IRQ (1 << 13)
+#define ME4000_AI_CTRL_BIT_EX_IRQ_RESET (1 << 14)
+#define ME4000_AI_CTRL_BIT_LE_IRQ (1 << 15)
+#define ME4000_AI_CTRL_BIT_LE_IRQ_RESET (1 << 16)
+#define ME4000_AI_CTRL_BIT_HF_IRQ (1 << 17)
+#define ME4000_AI_CTRL_BIT_HF_IRQ_RESET (1 << 18)
+#define ME4000_AI_CTRL_BIT_SC_IRQ (1 << 19)
+#define ME4000_AI_CTRL_BIT_SC_IRQ_RESET (1 << 20)
+#define ME4000_AI_CTRL_BIT_SC_RELOAD (1 << 21)
+#define ME4000_AI_STATUS_BIT_EF_CHANNEL (1 << 22)
+#define ME4000_AI_STATUS_BIT_HF_CHANNEL (1 << 23)
+#define ME4000_AI_STATUS_BIT_FF_CHANNEL (1 << 24)
+#define ME4000_AI_STATUS_BIT_EF_DATA (1 << 25)
+#define ME4000_AI_STATUS_BIT_HF_DATA (1 << 26)
+#define ME4000_AI_STATUS_BIT_FF_DATA (1 << 27)
+#define ME4000_AI_STATUS_BIT_LE (1 << 28)
+#define ME4000_AI_STATUS_BIT_FSM (1 << 29)
+#define ME4000_AI_CTRL_BIT_EX_TRIG_BOTH (1 << 31)
+#define ME4000_AI_CHANNEL_LIST_REG 0x78
+#define ME4000_AI_LIST_INPUT_SINGLE_ENDED (0 << 5)
+#define ME4000_AI_LIST_INPUT_DIFFERENTIAL (1 << 5)
+#define ME4000_AI_LIST_RANGE_BIPOLAR_10 (0 << 6)
+#define ME4000_AI_LIST_RANGE_BIPOLAR_2_5 (1 << 6)
+#define ME4000_AI_LIST_RANGE_UNIPOLAR_10 (2 << 6)
+#define ME4000_AI_LIST_RANGE_UNIPOLAR_2_5 (3 << 6)
+#define ME4000_AI_LIST_LAST_ENTRY (1 << 8)
+#define ME4000_AI_DATA_REG 0x7c
+#define ME4000_AI_CHAN_TIMER_REG 0x80
+#define ME4000_AI_CHAN_PRE_TIMER_REG 0x84
+#define ME4000_AI_SCAN_TIMER_LOW_REG 0x88
+#define ME4000_AI_SCAN_TIMER_HIGH_REG 0x8c
+#define ME4000_AI_SCAN_PRE_TIMER_LOW_REG 0x90
+#define ME4000_AI_SCAN_PRE_TIMER_HIGH_REG 0x94
+#define ME4000_AI_START_REG 0x98
+#define ME4000_IRQ_STATUS_REG 0x9c
+#define ME4000_IRQ_STATUS_BIT_EX (1 << 0)
+#define ME4000_IRQ_STATUS_BIT_LE (1 << 1)
+#define ME4000_IRQ_STATUS_BIT_AI_HF (1 << 2)
+#define ME4000_IRQ_STATUS_BIT_AO_0_HF (1 << 3)
+#define ME4000_IRQ_STATUS_BIT_AO_1_HF (1 << 4)
+#define ME4000_IRQ_STATUS_BIT_AO_2_HF (1 << 5)
+#define ME4000_IRQ_STATUS_BIT_AO_3_HF (1 << 6)
+#define ME4000_IRQ_STATUS_BIT_SC (1 << 7)
+#define ME4000_DIO_PORT_0_REG 0xa0
+#define ME4000_DIO_PORT_1_REG 0xa4
+#define ME4000_DIO_PORT_2_REG 0xa8
+#define ME4000_DIO_PORT_3_REG 0xac
+#define ME4000_DIO_DIR_REG 0xb0
+#define ME4000_AO_LOADSETREG_XX 0xb4
+#define ME4000_DIO_CTRL_REG 0xb8
+#define ME4000_DIO_CTRL_BIT_MODE_0 (1 << 0)
+#define ME4000_DIO_CTRL_BIT_MODE_1 (1 << 1)
+#define ME4000_DIO_CTRL_BIT_MODE_2 (1 << 2)
+#define ME4000_DIO_CTRL_BIT_MODE_3 (1 << 3)
+#define ME4000_DIO_CTRL_BIT_MODE_4 (1 << 4)
+#define ME4000_DIO_CTRL_BIT_MODE_5 (1 << 5)
+#define ME4000_DIO_CTRL_BIT_MODE_6 (1 << 6)
+#define ME4000_DIO_CTRL_BIT_MODE_7 (1 << 7)
+#define ME4000_DIO_CTRL_BIT_FUNCTION_0 (1 << 8)
+#define ME4000_DIO_CTRL_BIT_FUNCTION_1 (1 << 9)
+#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_0 (1 << 10)
+#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_1 (1 << 11)
+#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_2 (1 << 12)
+#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_3 (1 << 13)
+#define ME4000_AO_DEMUX_ADJUST_REG 0xbc
+#define ME4000_AO_DEMUX_ADJUST_VALUE 0x4c
+#define ME4000_AI_SAMPLE_COUNTER_REG 0xc0
- {0},
+/*
+ * PLX Register map and bit defines
+ */
+#define PLX_INTCSR 0x4c
+#define PLX_INTCSR_LOCAL_INT1_EN (1 << 0)
+#define PLX_INTCSR_LOCAL_INT1_POL (1 << 1)
+#define PLX_INTCSR_LOCAL_INT1_STATE (1 << 2)
+#define PLX_INTCSR_LOCAL_INT2_EN (1 << 3)
+#define PLX_INTCSR_LOCAL_INT2_POL (1 << 4)
+#define PLX_INTCSR_LOCAL_INT2_STATE (1 << 5)
+#define PLX_INTCSR_PCI_INT_EN (1 << 6)
+#define PLX_INTCSR_SOFT_INT (1 << 7)
+#define PLX_ICR 0x50
+#define PLX_ICR_BIT_EEPROM_CLOCK_SET (1 << 24)
+#define PLX_ICR_BIT_EEPROM_CHIP_SELECT (1 << 25)
+#define PLX_ICR_BIT_EEPROM_WRITE (1 << 26)
+#define PLX_ICR_BIT_EEPROM_READ (1 << 27)
+#define PLX_ICR_BIT_EEPROM_VALID (1 << 28)
+#define PLX_ICR_MASK_EEPROM (0x1f << 24)
+
+#define EEPROM_DELAY 1
+
+#define ME4000_AI_FIFO_COUNT 2048
+
+#define ME4000_AI_MIN_TICKS 66
+#define ME4000_AI_MIN_SAMPLE_TIME 2000
+#define ME4000_AI_BASE_FREQUENCY (unsigned int) 33E6
+
+#define ME4000_AI_CHANNEL_LIST_COUNT 1024
+
+struct me4000_info {
+ unsigned long plx_regbase;
+ unsigned long timer_regbase;
+
+ unsigned int ao_readback[4];
};
-#define ME4000_BOARD_VERSIONS (ARRAY_SIZE(me4000_boards) - 1)
-
-/*-----------------------------------------------------------------------------
- Meilhaus function prototypes
- ---------------------------------------------------------------------------*/
-static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p);
-static int init_board_info(struct comedi_device *dev,
- struct pci_dev *pci_dev_p);
-static int init_ao_context(struct comedi_device *dev);
-static int init_ai_context(struct comedi_device *dev);
-static int init_dio_context(struct comedi_device *dev);
-static int init_cnt_context(struct comedi_device *dev);
-static int xilinx_download(struct comedi_device *dev);
-static int reset_board(struct comedi_device *dev);
+struct me4000_board {
+ const char *name;
+ unsigned short device_id;
+ int ao_nchan;
+ int ao_fifo;
+ int ai_nchan;
+ int ai_diff_nchan;
+ int ai_sh_nchan;
+ int ex_trig_analog;
+ int dio_nchan;
+ int has_counter;
+};
-static int ai_write_chanlist(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_cmd *cmd);
+static const struct me4000_board me4000_boards[] = {
+ {
+ .name = "ME-4650",
+ .device_id = PCI_DEVICE_ID_MEILHAUS_ME4650,
+ .ai_nchan = 16,
+ .dio_nchan = 32,
+ }, {
+ .name = "ME-4660",
+ .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660,
+ .ai_nchan = 32,
+ .ai_diff_nchan = 16,
+ .dio_nchan = 32,
+ .has_counter = 1,
+ }, {
+ .name = "ME-4660i",
+ .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660I,
+ .ai_nchan = 32,
+ .ai_diff_nchan = 16,
+ .dio_nchan = 32,
+ .has_counter = 1,
+ }, {
+ .name = "ME-4660s",
+ .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660S,
+ .ai_nchan = 32,
+ .ai_diff_nchan = 16,
+ .ai_sh_nchan = 8,
+ .dio_nchan = 32,
+ .has_counter = 1,
+ }, {
+ .name = "ME-4660is",
+ .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660IS,
+ .ai_nchan = 32,
+ .ai_diff_nchan = 16,
+ .ai_sh_nchan = 8,
+ .dio_nchan = 32,
+ .has_counter = 1,
+ }, {
+ .name = "ME-4670",
+ .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670,
+ .ao_nchan = 4,
+ .ai_nchan = 32,
+ .ai_diff_nchan = 16,
+ .ex_trig_analog = 1,
+ .dio_nchan = 32,
+ .has_counter = 1,
+ }, {
+ .name = "ME-4670i",
+ .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670I,
+ .ao_nchan = 4,
+ .ai_nchan = 32,
+ .ai_diff_nchan = 16,
+ .ex_trig_analog = 1,
+ .dio_nchan = 32,
+ .has_counter = 1,
+ }, {
+ .name = "ME-4670s",
+ .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670S,
+ .ao_nchan = 4,
+ .ai_nchan = 32,
+ .ai_diff_nchan = 16,
+ .ai_sh_nchan = 8,
+ .ex_trig_analog = 1,
+ .dio_nchan = 32,
+ .has_counter = 1,
+ }, {
+ .name = "ME-4670is",
+ .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670IS,
+ .ao_nchan = 4,
+ .ai_nchan = 32,
+ .ai_diff_nchan = 16,
+ .ai_sh_nchan = 8,
+ .ex_trig_analog = 1,
+ .dio_nchan = 32,
+ .has_counter = 1,
+ }, {
+ .name = "ME-4680",
+ .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680,
+ .ao_nchan = 4,
+ .ao_fifo = 4,
+ .ai_nchan = 32,
+ .ai_diff_nchan = 16,
+ .ex_trig_analog = 1,
+ .dio_nchan = 32,
+ .has_counter = 1,
+ }, {
+ .name = "ME-4680i",
+ .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680I,
+ .ao_nchan = 4,
+ .ao_fifo = 4,
+ .ai_nchan = 32,
+ .ai_diff_nchan = 16,
+ .ex_trig_analog = 1,
+ .dio_nchan = 32,
+ .has_counter = 1,
+ }, {
+ .name = "ME-4680s",
+ .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680S,
+ .ao_nchan = 4,
+ .ao_fifo = 4,
+ .ai_nchan = 32,
+ .ai_diff_nchan = 16,
+ .ai_sh_nchan = 8,
+ .ex_trig_analog = 1,
+ .dio_nchan = 32,
+ .has_counter = 1,
+ }, {
+ .name = "ME-4680is",
+ .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680IS,
+ .ao_nchan = 4,
+ .ao_fifo = 4,
+ .ai_nchan = 32,
+ .ai_diff_nchan = 16,
+ .ai_sh_nchan = 8,
+ .ex_trig_analog = 1,
+ .dio_nchan = 32,
+ .has_counter = 1,
+ },
+};
static const struct comedi_lrange me4000_ai_range = {
4,
@@ -114,380 +363,6 @@ static const struct comedi_lrange me4000_ai_range = {
}
};
-static const struct comedi_lrange me4000_ao_range = {
- 1,
- {
- BIP_RANGE(10),
- }
-};
-
-static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it)
-{
- struct pci_dev *pci_device = NULL;
- int result, i;
- struct me4000_board *board;
-
- /* Allocate private memory */
- if (alloc_private(dev, sizeof(struct me4000_info)) < 0)
- return -ENOMEM;
-
- /*
- * Probe the device to determine what device in the series it is.
- */
- for_each_pci_dev(pci_device) {
- if (pci_device->vendor == PCI_VENDOR_ID_MEILHAUS) {
- for (i = 0; i < ME4000_BOARD_VERSIONS; i++) {
- if (me4000_boards[i].device_id ==
- pci_device->device) {
- /*
- * Was a particular
- * bus/slot requested?
- */
- if ((it->options[0] != 0)
- || (it->options[1] != 0)) {
- /*
- * Are we on the wrong
- * bus/slot?
- */
- if (pci_device->bus->number !=
- it->options[0]
- ||
- PCI_SLOT(pci_device->devfn)
- != it->options[1]) {
- continue;
- }
- }
- dev->board_ptr = me4000_boards + i;
- board =
- (struct me4000_board *)
- dev->board_ptr;
- info->pci_dev_p = pci_device;
- goto found;
- }
- }
- }
- }
-
- printk(KERN_ERR
- "comedi%d: me4000: me4000_probe(): "
- "No supported board found (req. bus/slot : %d/%d)\n",
- dev->minor, it->options[0], it->options[1]);
- return -ENODEV;
-
-found:
-
- printk(KERN_INFO
- "comedi%d: me4000: me4000_probe(): "
- "Found %s at PCI bus %d, slot %d\n",
- dev->minor, me4000_boards[i].name, pci_device->bus->number,
- PCI_SLOT(pci_device->devfn));
-
- /* Set data in device structure */
- dev->board_name = board->name;
-
- /* Enable PCI device and request regions */
- result = comedi_pci_enable(pci_device, dev->board_name);
- if (result) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_probe(): Cannot enable PCI "
- "device and request I/O regions\n", dev->minor);
- return result;
- }
-
- /* Get the PCI base registers */
- result = get_registers(dev, pci_device);
- if (result) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_probe(): "
- "Cannot get registers\n", dev->minor);
- return result;
- }
- /* Initialize board info */
- result = init_board_info(dev, pci_device);
- if (result) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_probe(): "
- "Cannot init baord info\n", dev->minor);
- return result;
- }
-
- /* Init analog output context */
- result = init_ao_context(dev);
- if (result) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_probe(): "
- "Cannot init ao context\n", dev->minor);
- return result;
- }
-
- /* Init analog input context */
- result = init_ai_context(dev);
- if (result) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_probe(): "
- "Cannot init ai context\n", dev->minor);
- return result;
- }
-
- /* Init digital I/O context */
- result = init_dio_context(dev);
- if (result) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_probe(): "
- "Cannot init dio context\n", dev->minor);
- return result;
- }
-
- /* Init counter context */
- result = init_cnt_context(dev);
- if (result) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_probe(): "
- "Cannot init cnt context\n", dev->minor);
- return result;
- }
-
- /* Download the xilinx firmware */
- result = xilinx_download(dev);
- if (result) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_probe(): "
- "Can't download firmware\n", dev->minor);
- return result;
- }
-
- /* Make a hardware reset */
- result = reset_board(dev);
- if (result) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_probe(): Can't reset board\n",
- dev->minor);
- return result;
- }
-
- return 0;
-}
-
-static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p)
-{
- /*--------------------------- plx regbase -------------------------------*/
-
- info->plx_regbase = pci_resource_start(pci_dev_p, 1);
- if (info->plx_regbase == 0) {
- printk(KERN_ERR
- "comedi%d: me4000: get_registers(): "
- "PCI base address 1 is not available\n", dev->minor);
- return -ENODEV;
- }
- info->plx_regbase_size = pci_resource_len(pci_dev_p, 1);
-
- /*--------------------------- me4000 regbase ----------------------------*/
-
- info->me4000_regbase = pci_resource_start(pci_dev_p, 2);
- if (info->me4000_regbase == 0) {
- printk(KERN_ERR
- "comedi%d: me4000: get_registers(): "
- "PCI base address 2 is not available\n", dev->minor);
- return -ENODEV;
- }
- info->me4000_regbase_size = pci_resource_len(pci_dev_p, 2);
-
- /*--------------------------- timer regbase ------------------------------*/
-
- info->timer_regbase = pci_resource_start(pci_dev_p, 3);
- if (info->timer_regbase == 0) {
- printk(KERN_ERR
- "comedi%d: me4000: get_registers(): "
- "PCI base address 3 is not available\n", dev->minor);
- return -ENODEV;
- }
- info->timer_regbase_size = pci_resource_len(pci_dev_p, 3);
-
- /*--------------------------- program regbase ----------------------------*/
-
- info->program_regbase = pci_resource_start(pci_dev_p, 5);
- if (info->program_regbase == 0) {
- printk(KERN_ERR
- "comedi%d: me4000: get_registers(): "
- "PCI base address 5 is not available\n", dev->minor);
- return -ENODEV;
- }
- info->program_regbase_size = pci_resource_len(pci_dev_p, 5);
-
- return 0;
-}
-
-static int init_board_info(struct comedi_device *dev, struct pci_dev *pci_dev_p)
-{
- int result;
-
- /* Init spin locks */
- /* spin_lock_init(&info->preload_lock); */
- /* spin_lock_init(&info->ai_ctrl_lock); */
-
- /* Get the serial number */
- result = pci_read_config_dword(pci_dev_p, 0x2C, &info->serial_no);
- if (result != PCIBIOS_SUCCESSFUL)
- return result;
-
- /* Get the hardware revision */
- result = pci_read_config_byte(pci_dev_p, 0x08, &info->hw_revision);
- if (result != PCIBIOS_SUCCESSFUL)
- return result;
-
- /* Get the vendor id */
- info->vendor_id = pci_dev_p->vendor;
-
- /* Get the device id */
- info->device_id = pci_dev_p->device;
-
- /* Get the irq assigned to the board */
- info->irq = pci_dev_p->irq;
-
- return 0;
-}
-
-static int init_ao_context(struct comedi_device *dev)
-{
- int i;
-
- for (i = 0; i < thisboard->ao.count; i++) {
- /* spin_lock_init(&info->ao_context[i].use_lock); */
- info->ao_context[i].irq = info->irq;
-
- switch (i) {
- case 0:
- info->ao_context[i].ctrl_reg =
- info->me4000_regbase + ME4000_AO_00_CTRL_REG;
- info->ao_context[i].status_reg =
- info->me4000_regbase + ME4000_AO_00_STATUS_REG;
- info->ao_context[i].fifo_reg =
- info->me4000_regbase + ME4000_AO_00_FIFO_REG;
- info->ao_context[i].single_reg =
- info->me4000_regbase + ME4000_AO_00_SINGLE_REG;
- info->ao_context[i].timer_reg =
- info->me4000_regbase + ME4000_AO_00_TIMER_REG;
- info->ao_context[i].irq_status_reg =
- info->me4000_regbase + ME4000_IRQ_STATUS_REG;
- info->ao_context[i].preload_reg =
- info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
- break;
- case 1:
- info->ao_context[i].ctrl_reg =
- info->me4000_regbase + ME4000_AO_01_CTRL_REG;
- info->ao_context[i].status_reg =
- info->me4000_regbase + ME4000_AO_01_STATUS_REG;
- info->ao_context[i].fifo_reg =
- info->me4000_regbase + ME4000_AO_01_FIFO_REG;
- info->ao_context[i].single_reg =
- info->me4000_regbase + ME4000_AO_01_SINGLE_REG;
- info->ao_context[i].timer_reg =
- info->me4000_regbase + ME4000_AO_01_TIMER_REG;
- info->ao_context[i].irq_status_reg =
- info->me4000_regbase + ME4000_IRQ_STATUS_REG;
- info->ao_context[i].preload_reg =
- info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
- break;
- case 2:
- info->ao_context[i].ctrl_reg =
- info->me4000_regbase + ME4000_AO_02_CTRL_REG;
- info->ao_context[i].status_reg =
- info->me4000_regbase + ME4000_AO_02_STATUS_REG;
- info->ao_context[i].fifo_reg =
- info->me4000_regbase + ME4000_AO_02_FIFO_REG;
- info->ao_context[i].single_reg =
- info->me4000_regbase + ME4000_AO_02_SINGLE_REG;
- info->ao_context[i].timer_reg =
- info->me4000_regbase + ME4000_AO_02_TIMER_REG;
- info->ao_context[i].irq_status_reg =
- info->me4000_regbase + ME4000_IRQ_STATUS_REG;
- info->ao_context[i].preload_reg =
- info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
- break;
- case 3:
- info->ao_context[i].ctrl_reg =
- info->me4000_regbase + ME4000_AO_03_CTRL_REG;
- info->ao_context[i].status_reg =
- info->me4000_regbase + ME4000_AO_03_STATUS_REG;
- info->ao_context[i].fifo_reg =
- info->me4000_regbase + ME4000_AO_03_FIFO_REG;
- info->ao_context[i].single_reg =
- info->me4000_regbase + ME4000_AO_03_SINGLE_REG;
- info->ao_context[i].timer_reg =
- info->me4000_regbase + ME4000_AO_03_TIMER_REG;
- info->ao_context[i].irq_status_reg =
- info->me4000_regbase + ME4000_IRQ_STATUS_REG;
- info->ao_context[i].preload_reg =
- info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
- break;
- default:
- break;
- }
- }
-
- return 0;
-}
-
-static int init_ai_context(struct comedi_device *dev)
-{
- info->ai_context.irq = info->irq;
-
- info->ai_context.ctrl_reg = info->me4000_regbase + ME4000_AI_CTRL_REG;
- info->ai_context.status_reg =
- info->me4000_regbase + ME4000_AI_STATUS_REG;
- info->ai_context.channel_list_reg =
- info->me4000_regbase + ME4000_AI_CHANNEL_LIST_REG;
- info->ai_context.data_reg = info->me4000_regbase + ME4000_AI_DATA_REG;
- info->ai_context.chan_timer_reg =
- info->me4000_regbase + ME4000_AI_CHAN_TIMER_REG;
- info->ai_context.chan_pre_timer_reg =
- info->me4000_regbase + ME4000_AI_CHAN_PRE_TIMER_REG;
- info->ai_context.scan_timer_low_reg =
- info->me4000_regbase + ME4000_AI_SCAN_TIMER_LOW_REG;
- info->ai_context.scan_timer_high_reg =
- info->me4000_regbase + ME4000_AI_SCAN_TIMER_HIGH_REG;
- info->ai_context.scan_pre_timer_low_reg =
- info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG;
- info->ai_context.scan_pre_timer_high_reg =
- info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG;
- info->ai_context.start_reg = info->me4000_regbase + ME4000_AI_START_REG;
- info->ai_context.irq_status_reg =
- info->me4000_regbase + ME4000_IRQ_STATUS_REG;
- info->ai_context.sample_counter_reg =
- info->me4000_regbase + ME4000_AI_SAMPLE_COUNTER_REG;
-
- return 0;
-}
-
-static int init_dio_context(struct comedi_device *dev)
-{
- info->dio_context.dir_reg = info->me4000_regbase + ME4000_DIO_DIR_REG;
- info->dio_context.ctrl_reg = info->me4000_regbase + ME4000_DIO_CTRL_REG;
- info->dio_context.port_0_reg =
- info->me4000_regbase + ME4000_DIO_PORT_0_REG;
- info->dio_context.port_1_reg =
- info->me4000_regbase + ME4000_DIO_PORT_1_REG;
- info->dio_context.port_2_reg =
- info->me4000_regbase + ME4000_DIO_PORT_2_REG;
- info->dio_context.port_3_reg =
- info->me4000_regbase + ME4000_DIO_PORT_3_REG;
-
- return 0;
-}
-
-static int init_cnt_context(struct comedi_device *dev)
-{
- info->cnt_context.ctrl_reg = info->timer_regbase + ME4000_CNT_CTRL_REG;
- info->cnt_context.counter_0_reg =
- info->timer_regbase + ME4000_CNT_COUNTER_0_REG;
- info->cnt_context.counter_1_reg =
- info->timer_regbase + ME4000_CNT_COUNTER_1_REG;
- info->cnt_context.counter_2_reg =
- info->timer_regbase + ME4000_CNT_COUNTER_2_REG;
-
- return 0;
-}
-
#define FIRMWARE_NOT_AVAILABLE 1
#if FIRMWARE_NOT_AVAILABLE
extern unsigned char *xilinx_firm;
@@ -495,11 +370,17 @@ extern unsigned char *xilinx_firm;
static int xilinx_download(struct comedi_device *dev)
{
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ struct me4000_info *info = dev->private;
+ unsigned long xilinx_iobase = pci_resource_start(pcidev, 5);
u32 value = 0;
wait_queue_head_t queue;
int idx = 0;
int size = 0;
+ if (!xilinx_iobase)
+ return -ENODEV;
+
init_waitqueue_head(&queue);
/*
@@ -514,14 +395,12 @@ static int xilinx_download(struct comedi_device *dev)
outl(value, info->plx_regbase + PLX_ICR);
/* Init Xilinx with CS1 */
- inb(info->program_regbase + 0xC8);
+ inb(xilinx_iobase + 0xC8);
/* Wait until /INIT pin is set */
udelay(20);
if (!(inl(info->plx_regbase + PLX_INTCSR) & 0x20)) {
- printk(KERN_ERR
- "comedi%d: me4000: xilinx_download(): "
- "Can't init Xilinx\n", dev->minor);
+ dev_err(dev->class_dev, "Can't init Xilinx\n");
return -EIO;
}
@@ -530,8 +409,8 @@ static int xilinx_download(struct comedi_device *dev)
value &= ~0x100;
outl(value, info->plx_regbase + PLX_ICR);
if (FIRMWARE_NOT_AVAILABLE) {
- comedi_error(dev, "xilinx firmware unavailable "
- "due to licensing, aborting");
+ dev_err(dev->class_dev,
+ "xilinx firmware unavailable due to licensing, aborting");
return -EIO;
} else {
/* Download Xilinx firmware */
@@ -540,15 +419,14 @@ static int xilinx_download(struct comedi_device *dev)
udelay(10);
for (idx = 0; idx < size; idx++) {
- outb(xilinx_firm[16 + idx], info->program_regbase);
+ outb(xilinx_firm[16 + idx], xilinx_iobase);
udelay(10);
/* Check if BUSY flag is low */
if (inl(info->plx_regbase + PLX_ICR) & 0x20) {
- printk(KERN_ERR
- "comedi%d: me4000: xilinx_download(): "
- "Xilinx is still busy (idx = %d)\n",
- dev->minor, idx);
+ dev_err(dev->class_dev,
+ "Xilinx is still busy (idx = %d)\n",
+ idx);
return -EIO;
}
}
@@ -557,12 +435,8 @@ static int xilinx_download(struct comedi_device *dev)
/* If done flag is high download was successful */
if (inl(info->plx_regbase + PLX_ICR) & 0x4) {
} else {
- printk(KERN_ERR
- "comedi%d: me4000: xilinx_download(): "
- "DONE flag is not set\n", dev->minor);
- printk(KERN_ERR
- "comedi%d: me4000: xilinx_download(): "
- "Download not successful\n", dev->minor);
+ dev_err(dev->class_dev, "DONE flag is not set\n");
+ dev_err(dev->class_dev, "Download not successful\n");
return -EIO;
}
@@ -574,52 +448,45 @@ static int xilinx_download(struct comedi_device *dev)
return 0;
}
-static int reset_board(struct comedi_device *dev)
+static void me4000_reset(struct comedi_device *dev)
{
- unsigned long icr;
+ struct me4000_info *info = dev->private;
+ unsigned long val;
+ int chan;
/* Make a hardware reset */
- icr = inl(info->plx_regbase + PLX_ICR);
- icr |= 0x40000000;
- outl(icr, info->plx_regbase + PLX_ICR);
- icr &= ~0x40000000;
- outl(icr, info->plx_regbase + PLX_ICR);
+ val = inl(info->plx_regbase + PLX_ICR);
+ val |= 0x40000000;
+ outl(val, info->plx_regbase + PLX_ICR);
+ val &= ~0x40000000;
+ outl(val , info->plx_regbase + PLX_ICR);
/* 0x8000 to the DACs means an output voltage of 0V */
- outl(0x8000, info->me4000_regbase + ME4000_AO_00_SINGLE_REG);
- outl(0x8000, info->me4000_regbase + ME4000_AO_01_SINGLE_REG);
- outl(0x8000, info->me4000_regbase + ME4000_AO_02_SINGLE_REG);
- outl(0x8000, info->me4000_regbase + ME4000_AO_03_SINGLE_REG);
+ for (chan = 0; chan < 4; chan++)
+ outl(0x8000, dev->iobase + ME4000_AO_SINGLE_REG(chan));
/* Set both stop bits in the analog input control register */
outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
- info->me4000_regbase + ME4000_AI_CTRL_REG);
+ dev->iobase + ME4000_AI_CTRL_REG);
/* Set both stop bits in the analog output control register */
- outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
- info->me4000_regbase + ME4000_AO_00_CTRL_REG);
- outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
- info->me4000_regbase + ME4000_AO_01_CTRL_REG);
- outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
- info->me4000_regbase + ME4000_AO_02_CTRL_REG);
- outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
- info->me4000_regbase + ME4000_AO_03_CTRL_REG);
+ val = ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP;
+ for (chan = 0; chan < 4; chan++)
+ outl(val, dev->iobase + ME4000_AO_CTRL_REG(chan));
/* Enable interrupts on the PLX */
outl(0x43, info->plx_regbase + PLX_INTCSR);
/* Set the adustment register for AO demux */
outl(ME4000_AO_DEMUX_ADJUST_VALUE,
- info->me4000_regbase + ME4000_AO_DEMUX_ADJUST_REG);
+ dev->iobase + ME4000_AO_DEMUX_ADJUST_REG);
/*
* Set digital I/O direction for port 0
* to output on isolated versions
*/
- if (!(inl(info->me4000_regbase + ME4000_DIO_DIR_REG) & 0x1))
- outl(0x1, info->me4000_regbase + ME4000_DIO_CTRL_REG);
-
- return 0;
+ if (!(inl(dev->iobase + ME4000_DIO_DIR_REG) & 0x1))
+ outl(0x1, dev->iobase + ME4000_DIO_CTRL_REG);
}
/*=============================================================================
@@ -630,7 +497,7 @@ static int me4000_ai_insn_read(struct comedi_device *dev,
struct comedi_subdevice *subdevice,
struct comedi_insn *insn, unsigned int *data)
{
-
+ const struct me4000_board *thisboard = comedi_board(dev);
int chan = CR_CHAN(insn->chanspec);
int rang = CR_RANGE(insn->chanspec);
int aref = CR_AREF(insn->chanspec);
@@ -642,9 +509,8 @@ static int me4000_ai_insn_read(struct comedi_device *dev,
if (insn->n == 0) {
return 0;
} else if (insn->n > 1) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_insn_read(): "
- "Invalid instruction length %d\n", dev->minor, insn->n);
+ dev_err(dev->class_dev, "Invalid instruction length %d\n",
+ insn->n);
return -EINVAL;
}
@@ -662,19 +528,16 @@ static int me4000_ai_insn_read(struct comedi_device *dev,
entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
break;
default:
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_insn_read(): "
- "Invalid range specified\n", dev->minor);
+ dev_err(dev->class_dev, "Invalid range specified\n");
return -EINVAL;
}
switch (aref) {
case AREF_GROUND:
case AREF_COMMON:
- if (chan >= thisboard->ai.count) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_insn_read(): "
- "Analog input is not available\n", dev->minor);
+ if (chan >= thisboard->ai_nchan) {
+ dev_err(dev->class_dev,
+ "Analog input is not available\n");
return -EINVAL;
}
entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan;
@@ -682,68 +545,61 @@ static int me4000_ai_insn_read(struct comedi_device *dev,
case AREF_DIFF:
if (rang == 0 || rang == 1) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_insn_read(): "
- "Range must be bipolar when aref = diff\n",
- dev->minor);
+ dev_err(dev->class_dev,
+ "Range must be bipolar when aref = diff\n");
return -EINVAL;
}
- if (chan >= thisboard->ai.diff_count) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_insn_read(): "
- "Analog input is not available\n", dev->minor);
+ if (chan >= thisboard->ai_diff_nchan) {
+ dev_err(dev->class_dev,
+ "Analog input is not available\n");
return -EINVAL;
}
entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan;
break;
default:
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_insn_read(): "
- "Invalid aref specified\n", dev->minor);
+ dev_err(dev->class_dev, "Invalid aref specified\n");
return -EINVAL;
}
entry |= ME4000_AI_LIST_LAST_ENTRY;
/* Clear channel list, data fifo and both stop bits */
- tmp = inl(info->ai_context.ctrl_reg);
+ tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
ME4000_AI_CTRL_BIT_DATA_FIFO |
ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
- outl(tmp, info->ai_context.ctrl_reg);
+ outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
/* Set the acquisition mode to single */
tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 |
ME4000_AI_CTRL_BIT_MODE_2);
- outl(tmp, info->ai_context.ctrl_reg);
+ outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
/* Enable channel list and data fifo */
tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
- outl(tmp, info->ai_context.ctrl_reg);
+ outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
/* Generate channel list entry */
- outl(entry, info->ai_context.channel_list_reg);
+ outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
/* Set the timer to maximum sample rate */
- outl(ME4000_AI_MIN_TICKS, info->ai_context.chan_timer_reg);
- outl(ME4000_AI_MIN_TICKS, info->ai_context.chan_pre_timer_reg);
+ outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
+ outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
/* Start conversion by dummy read */
- inl(info->ai_context.start_reg);
+ inl(dev->iobase + ME4000_AI_START_REG);
/* Wait until ready */
udelay(10);
- if (!(inl(info->ai_context.status_reg) &
+ if (!(inl(dev->iobase + ME4000_AI_STATUS_REG) &
ME4000_AI_STATUS_BIT_EF_DATA)) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_insn_read(): "
- "Value not available after wait\n", dev->minor);
+ dev_err(dev->class_dev, "Value not available after wait\n");
return -EIO;
}
/* Read value from data fifo */
- lval = inl(info->ai_context.data_reg) & 0xFFFF;
+ lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
data[0] = lval ^ 0x8000;
return 1;
@@ -755,12 +611,12 @@ static int me4000_ai_cancel(struct comedi_device *dev,
unsigned long tmp;
/* Stop any running conversion */
- tmp = inl(info->ai_context.ctrl_reg);
+ tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
- outl(tmp, info->ai_context.ctrl_reg);
+ outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
/* Clear the control register */
- outl(0x0, info->ai_context.ctrl_reg);
+ outl(0x0, dev->iobase + ME4000_AI_CTRL_REG);
return 0;
}
@@ -768,30 +624,25 @@ static int me4000_ai_cancel(struct comedi_device *dev,
static int ai_check_chanlist(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_cmd *cmd)
{
+ const struct me4000_board *thisboard = comedi_board(dev);
int aref;
int i;
/* Check whether a channel list is available */
if (!cmd->chanlist_len) {
- printk(KERN_ERR
- "comedi%d: me4000: ai_check_chanlist(): "
- "No channel list available\n", dev->minor);
+ dev_err(dev->class_dev, "No channel list available\n");
return -EINVAL;
}
/* Check the channel list size */
if (cmd->chanlist_len > ME4000_AI_CHANNEL_LIST_COUNT) {
- printk(KERN_ERR
- "comedi%d: me4000: ai_check_chanlist(): "
- "Channel list is to large\n", dev->minor);
+ dev_err(dev->class_dev, "Channel list is to large\n");
return -EINVAL;
}
/* Check the pointer */
if (!cmd->chanlist) {
- printk(KERN_ERR
- "comedi%d: me4000: ai_check_chanlist(): "
- "NULL pointer to channel list\n", dev->minor);
+ dev_err(dev->class_dev, "NULL pointer to channel list\n");
return -EFAULT;
}
@@ -799,10 +650,8 @@ static int ai_check_chanlist(struct comedi_device *dev,
aref = CR_AREF(cmd->chanlist[0]);
for (i = 0; i < cmd->chanlist_len; i++) {
if (CR_AREF(cmd->chanlist[i]) != aref) {
- printk(KERN_ERR
- "comedi%d: me4000: ai_check_chanlist(): "
- "Mode is not equal for all entries\n",
- dev->minor);
+ dev_err(dev->class_dev,
+ "Mode is not equal for all entries\n");
return -EINVAL;
}
}
@@ -811,19 +660,17 @@ static int ai_check_chanlist(struct comedi_device *dev,
if (aref == SDF_DIFF) {
for (i = 0; i < cmd->chanlist_len; i++) {
if (CR_CHAN(cmd->chanlist[i]) >=
- thisboard->ai.diff_count) {
- printk(KERN_ERR
- "comedi%d: me4000: ai_check_chanlist():"
- " Channel number to high\n", dev->minor);
+ thisboard->ai_diff_nchan) {
+ dev_err(dev->class_dev,
+ "Channel number to high\n");
return -EINVAL;
}
}
} else {
for (i = 0; i < cmd->chanlist_len; i++) {
- if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai.count) {
- printk(KERN_ERR
- "comedi%d: me4000: ai_check_chanlist(): "
- "Channel number to high\n", dev->minor);
+ if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai_nchan) {
+ dev_err(dev->class_dev,
+ "Channel number to high\n");
return -EINVAL;
}
}
@@ -834,11 +681,8 @@ static int ai_check_chanlist(struct comedi_device *dev,
for (i = 0; i < cmd->chanlist_len; i++) {
if (CR_RANGE(cmd->chanlist[i]) != 1 &&
CR_RANGE(cmd->chanlist[i]) != 2) {
- printk(KERN_ERR
- "comedi%d: me4000: ai_check_chanlist(): "
- "Bipolar is not selected in "
- "differential mode\n",
- dev->minor);
+ dev_err(dev->class_dev,
+ "Bipolar is not selected in differential mode\n");
return -EINVAL;
}
}
@@ -906,16 +750,52 @@ static void ai_write_timer(struct comedi_device *dev,
unsigned int init_ticks,
unsigned int scan_ticks, unsigned int chan_ticks)
{
- outl(init_ticks - 1, info->ai_context.scan_pre_timer_low_reg);
- outl(0x0, info->ai_context.scan_pre_timer_high_reg);
+ outl(init_ticks - 1, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG);
+ outl(0x0, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG);
if (scan_ticks) {
- outl(scan_ticks - 1, info->ai_context.scan_timer_low_reg);
- outl(0x0, info->ai_context.scan_timer_high_reg);
+ outl(scan_ticks - 1, dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG);
+ outl(0x0, dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG);
}
- outl(chan_ticks - 1, info->ai_context.chan_pre_timer_reg);
- outl(chan_ticks - 1, info->ai_context.chan_timer_reg);
+ outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
+ outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
+}
+
+static int ai_write_chanlist(struct comedi_device *dev,
+ struct comedi_subdevice *s, struct comedi_cmd *cmd)
+{
+ unsigned int entry;
+ unsigned int chan;
+ unsigned int rang;
+ unsigned int aref;
+ int i;
+
+ for (i = 0; i < cmd->chanlist_len; i++) {
+ chan = CR_CHAN(cmd->chanlist[i]);
+ rang = CR_RANGE(cmd->chanlist[i]);
+ aref = CR_AREF(cmd->chanlist[i]);
+
+ entry = chan;
+
+ if (rang == 0)
+ entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
+ else if (rang == 1)
+ entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
+ else if (rang == 2)
+ entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
+ else
+ entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
+
+ if (aref == SDF_DIFF)
+ entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
+ else
+ entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED;
+
+ outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
+ }
+
+ return 0;
}
static int ai_prepare(struct comedi_device *dev,
@@ -931,7 +811,7 @@ static int ai_prepare(struct comedi_device *dev,
ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks);
/* Reset control register */
- outl(tmp, info->ai_context.ctrl_reg);
+ outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
/* Start sources */
if ((cmd->start_src == TRIG_EXT &&
@@ -965,19 +845,19 @@ static int ai_prepare(struct comedi_device *dev,
/* Stop triggers */
if (cmd->stop_src == TRIG_COUNT) {
outl(cmd->chanlist_len * cmd->stop_arg,
- info->ai_context.sample_counter_reg);
+ dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
} else if (cmd->stop_src == TRIG_NONE &&
cmd->scan_end_src == TRIG_COUNT) {
outl(cmd->scan_end_arg,
- info->ai_context.sample_counter_reg);
+ dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
} else {
tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
}
/* Write the setup to the control register */
- outl(tmp, info->ai_context.ctrl_reg);
+ outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
/* Write the channel list */
ai_write_chanlist(dev, s, cmd);
@@ -985,42 +865,6 @@ static int ai_prepare(struct comedi_device *dev,
return 0;
}
-static int ai_write_chanlist(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_cmd *cmd)
-{
- unsigned int entry;
- unsigned int chan;
- unsigned int rang;
- unsigned int aref;
- int i;
-
- for (i = 0; i < cmd->chanlist_len; i++) {
- chan = CR_CHAN(cmd->chanlist[i]);
- rang = CR_RANGE(cmd->chanlist[i]);
- aref = CR_AREF(cmd->chanlist[i]);
-
- entry = chan;
-
- if (rang == 0)
- entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
- else if (rang == 1)
- entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
- else if (rang == 2)
- entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
- else
- entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
-
- if (aref == SDF_DIFF)
- entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
- else
- entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED;
-
- outl(entry, info->ai_context.channel_list_reg);
- }
-
- return 0;
-}
-
static int me4000_ai_do_cmd(struct comedi_device *dev,
struct comedi_subdevice *s)
{
@@ -1047,23 +891,11 @@ static int me4000_ai_do_cmd(struct comedi_device *dev,
return err;
/* Start acquistion by dummy read */
- inl(info->ai_context.start_reg);
+ inl(dev->iobase + ME4000_AI_START_REG);
return 0;
}
-/*
- * me4000_ai_do_cmd_test():
- *
- * The demo cmd.c in ./comedilib/demo specifies 6 return values:
- * - success
- * - invalid source
- * - source conflict
- * - invalid argument
- * - argument conflict
- * - invalid chanlist
- * So I tried to adopt this scheme.
- */
static int me4000_ai_do_cmd_test(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
@@ -1080,91 +912,29 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
/* Round the timer arguments */
ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
- /*
- * Stage 1. Check if the trigger sources are generally valid.
- */
- switch (cmd->start_src) {
- case TRIG_NOW:
- case TRIG_EXT:
- break;
- case TRIG_ANY:
- cmd->start_src &= TRIG_NOW | TRIG_EXT;
- err++;
- break;
- default:
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid start source\n", dev->minor);
- cmd->start_src = TRIG_NOW;
- err++;
- }
- switch (cmd->scan_begin_src) {
- case TRIG_FOLLOW:
- case TRIG_TIMER:
- case TRIG_EXT:
- break;
- case TRIG_ANY:
- cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
- err++;
- break;
- default:
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid scan begin source\n", dev->minor);
- cmd->scan_begin_src = TRIG_FOLLOW;
- err++;
- }
- switch (cmd->convert_src) {
- case TRIG_TIMER:
- case TRIG_EXT:
- break;
- case TRIG_ANY:
- cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
- err++;
- break;
- default:
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid convert source\n", dev->minor);
- cmd->convert_src = TRIG_TIMER;
- err++;
- }
- switch (cmd->scan_end_src) {
- case TRIG_NONE:
- case TRIG_COUNT:
- break;
- case TRIG_ANY:
- cmd->scan_end_src &= TRIG_NONE | TRIG_COUNT;
- err++;
- break;
- default:
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid scan end source\n", dev->minor);
- cmd->scan_end_src = TRIG_NONE;
- err++;
- }
- switch (cmd->stop_src) {
- case TRIG_NONE:
- case TRIG_COUNT:
- break;
- case TRIG_ANY:
- cmd->stop_src &= TRIG_NONE | TRIG_COUNT;
- err++;
- break;
- default:
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid stop source\n", dev->minor);
- cmd->stop_src = TRIG_NONE;
- err++;
- }
+ /* Step 1 : check if triggers are trivially valid */
+
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_end_src,
+ TRIG_NONE | TRIG_COUNT);
+ err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE | TRIG_COUNT);
+
if (err)
return 1;
- /*
- * Stage 2. Check for trigger source conflicts.
- */
+ /* Step 2a : make sure trigger sources are unique */
+
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->scan_end_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
+
if (cmd->start_src == TRIG_NOW &&
cmd->scan_begin_src == TRIG_TIMER &&
cmd->convert_src == TRIG_TIMER) {
@@ -1184,13 +954,7 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
cmd->scan_begin_src == TRIG_EXT &&
cmd->convert_src == TRIG_EXT) {
} else {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid start trigger combination\n", dev->minor);
- cmd->start_src = TRIG_NOW;
- cmd->scan_begin_src = TRIG_FOLLOW;
- cmd->convert_src = TRIG_TIMER;
- err++;
+ err |= -EINVAL;
}
if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_NONE) {
@@ -1201,13 +965,9 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
} else if (cmd->stop_src == TRIG_COUNT &&
cmd->scan_end_src == TRIG_COUNT) {
} else {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid stop trigger combination\n", dev->minor);
- cmd->stop_src = TRIG_NONE;
- cmd->scan_end_src = TRIG_NONE;
- err++;
+ err |= -EINVAL;
}
+
if (err)
return 2;
@@ -1215,30 +975,22 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
* Stage 3. Check if arguments are generally valid.
*/
if (cmd->chanlist_len < 1) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "No channel list\n", dev->minor);
+ dev_err(dev->class_dev, "No channel list\n");
cmd->chanlist_len = 1;
err++;
}
if (init_ticks < 66) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Start arg to low\n", dev->minor);
+ dev_err(dev->class_dev, "Start arg to low\n");
cmd->start_arg = 2000;
err++;
}
if (scan_ticks && scan_ticks < 67) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Scan begin arg to low\n", dev->minor);
+ dev_err(dev->class_dev, "Scan begin arg to low\n");
cmd->scan_begin_arg = 2031;
err++;
}
if (chan_ticks < 66) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Convert arg to low\n", dev->minor);
+ dev_err(dev->class_dev, "Convert arg to low\n");
cmd->convert_arg = 2000;
err++;
}
@@ -1255,23 +1007,17 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
/* Check timer arguments */
if (init_ticks < ME4000_AI_MIN_TICKS) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid start arg\n", dev->minor);
+ dev_err(dev->class_dev, "Invalid start arg\n");
cmd->start_arg = 2000; /* 66 ticks at least */
err++;
}
if (chan_ticks < ME4000_AI_MIN_TICKS) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid convert arg\n", dev->minor);
+ dev_err(dev->class_dev, "Invalid convert arg\n");
cmd->convert_arg = 2000; /* 66 ticks at least */
err++;
}
if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid scan end arg\n", dev->minor);
+ dev_err(dev->class_dev, "Invalid scan end arg\n");
/* At least one tick more */
cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
@@ -1283,16 +1029,12 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
/* Check timer arguments */
if (init_ticks < ME4000_AI_MIN_TICKS) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid start arg\n", dev->minor);
+ dev_err(dev->class_dev, "Invalid start arg\n");
cmd->start_arg = 2000; /* 66 ticks at least */
err++;
}
if (chan_ticks < ME4000_AI_MIN_TICKS) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid convert arg\n", dev->minor);
+ dev_err(dev->class_dev, "Invalid convert arg\n");
cmd->convert_arg = 2000; /* 66 ticks at least */
err++;
}
@@ -1302,23 +1044,17 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
/* Check timer arguments */
if (init_ticks < ME4000_AI_MIN_TICKS) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid start arg\n", dev->minor);
+ dev_err(dev->class_dev, "Invalid start arg\n");
cmd->start_arg = 2000; /* 66 ticks at least */
err++;
}
if (chan_ticks < ME4000_AI_MIN_TICKS) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid convert arg\n", dev->minor);
+ dev_err(dev->class_dev, "Invalid convert arg\n");
cmd->convert_arg = 2000; /* 66 ticks at least */
err++;
}
if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid scan end arg\n", dev->minor);
+ dev_err(dev->class_dev, "Invalid scan end arg\n");
/* At least one tick more */
cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
@@ -1330,16 +1066,12 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
/* Check timer arguments */
if (init_ticks < ME4000_AI_MIN_TICKS) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid start arg\n", dev->minor);
+ dev_err(dev->class_dev, "Invalid start arg\n");
cmd->start_arg = 2000; /* 66 ticks at least */
err++;
}
if (chan_ticks < ME4000_AI_MIN_TICKS) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid convert arg\n", dev->minor);
+ dev_err(dev->class_dev, "Invalid convert arg\n");
cmd->convert_arg = 2000; /* 66 ticks at least */
err++;
}
@@ -1349,16 +1081,12 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
/* Check timer arguments */
if (init_ticks < ME4000_AI_MIN_TICKS) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid start arg\n", dev->minor);
+ dev_err(dev->class_dev, "Invalid start arg\n");
cmd->start_arg = 2000; /* 66 ticks at least */
err++;
}
if (chan_ticks < ME4000_AI_MIN_TICKS) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid convert arg\n", dev->minor);
+ dev_err(dev->class_dev, "Invalid convert arg\n");
cmd->convert_arg = 2000; /* 66 ticks at least */
err++;
}
@@ -1368,27 +1096,21 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
/* Check timer arguments */
if (init_ticks < ME4000_AI_MIN_TICKS) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid start arg\n", dev->minor);
+ dev_err(dev->class_dev, "Invalid start arg\n");
cmd->start_arg = 2000; /* 66 ticks at least */
err++;
}
}
if (cmd->stop_src == TRIG_COUNT) {
if (cmd->stop_arg == 0) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid stop arg\n", dev->minor);
+ dev_err(dev->class_dev, "Invalid stop arg\n");
cmd->stop_arg = 1;
err++;
}
}
if (cmd->scan_end_src == TRIG_COUNT) {
if (cmd->scan_end_arg == 0) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_do_cmd_test(): "
- "Invalid scan end arg\n", dev->minor);
+ dev_err(dev->class_dev, "Invalid scan end arg\n");
cmd->scan_end_arg = 1;
err++;
}
@@ -1410,8 +1132,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
{
unsigned int tmp;
struct comedi_device *dev = dev_id;
- struct comedi_subdevice *s = dev->subdevices;
- struct me4000_ai_context *ai_context = &info->ai_context;
+ struct comedi_subdevice *s = &dev->subdevices[0];
int i;
int c = 0;
long lval;
@@ -1423,17 +1144,15 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
s->async->events = 0;
/* Check if irq number is right */
- if (irq != ai_context->irq) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_isr(): "
- "Incorrect interrupt num: %d\n", dev->minor, irq);
+ if (irq != dev->irq) {
+ dev_err(dev->class_dev, "Incorrect interrupt num: %d\n", irq);
return IRQ_HANDLED;
}
- if (inl(ai_context->irq_status_reg) &
+ if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
ME4000_IRQ_STATUS_BIT_AI_HF) {
/* Read status register to find out what happened */
- tmp = inl(ai_context->ctrl_reg);
+ tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
!(tmp & ME4000_AI_STATUS_BIT_HF_DATA) &&
@@ -1447,13 +1166,11 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
ME4000_AI_CTRL_BIT_SC_IRQ);
- outl(tmp, ai_context->ctrl_reg);
+ outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_isr(): "
- "FIFO overflow\n", dev->minor);
+ dev_err(dev->class_dev, "FIFO overflow\n");
} else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
&& !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
&& (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
@@ -1461,9 +1178,8 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
c = ME4000_AI_FIFO_COUNT / 2;
} else {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_isr(): "
- "Can't determine state of fifo\n", dev->minor);
+ dev_err(dev->class_dev,
+ "Can't determine state of fifo\n");
c = 0;
/*
@@ -1473,18 +1189,16 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
ME4000_AI_CTRL_BIT_SC_IRQ);
- outl(tmp, ai_context->ctrl_reg);
+ outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_isr(): "
- "Undefined FIFO state\n", dev->minor);
+ dev_err(dev->class_dev, "Undefined FIFO state\n");
}
for (i = 0; i < c; i++) {
/* Read value from data fifo */
- lval = inl(ai_context->data_reg) & 0xFFFF;
+ lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
lval ^= 0x8000;
if (!comedi_buf_put(s->async, lval)) {
@@ -1495,13 +1209,11 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
ME4000_AI_CTRL_BIT_SC_IRQ);
- outl(tmp, ai_context->ctrl_reg);
+ outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
s->async->events |= COMEDI_CB_OVERFLOW;
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_isr(): "
- "Buffer overflow\n", dev->minor);
+ dev_err(dev->class_dev, "Buffer overflow\n");
break;
}
@@ -1509,33 +1221,33 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
/* Work is done, so reset the interrupt */
tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
- outl(tmp, ai_context->ctrl_reg);
+ outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
- outl(tmp, ai_context->ctrl_reg);
+ outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
}
- if (inl(ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_SC) {
+ if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
+ ME4000_IRQ_STATUS_BIT_SC) {
s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA;
/*
* Acquisition is complete, so stop
* conversion and disable all interrupts
*/
- tmp = inl(ai_context->ctrl_reg);
+ tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ);
- outl(tmp, ai_context->ctrl_reg);
+ outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
/* Poll data until fifo empty */
- while (inl(ai_context->ctrl_reg) & ME4000_AI_STATUS_BIT_EF_DATA) {
+ while (inl(dev->iobase + ME4000_AI_CTRL_REG) &
+ ME4000_AI_STATUS_BIT_EF_DATA) {
/* Read value from data fifo */
- lval = inl(ai_context->data_reg) & 0xFFFF;
+ lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
lval ^= 0x8000;
if (!comedi_buf_put(s->async, lval)) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ai_isr(): "
- "Buffer overflow\n", dev->minor);
+ dev_err(dev->class_dev, "Buffer overflow\n");
s->async->events |= COMEDI_CB_OVERFLOW;
break;
}
@@ -1543,9 +1255,9 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
/* Work is done, so reset the interrupt */
tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
- outl(tmp, ai_context->ctrl_reg);
+ outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
- outl(tmp, ai_context->ctrl_reg);
+ outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
}
if (s->async->events)
@@ -1562,7 +1274,8 @@ static int me4000_ao_insn_write(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
-
+ const struct me4000_board *thisboard = comedi_board(dev);
+ struct me4000_info *info = dev->private;
int chan = CR_CHAN(insn->chanspec);
int rang = CR_RANGE(insn->chanspec);
int aref = CR_AREF(insn->chanspec);
@@ -1571,46 +1284,39 @@ static int me4000_ao_insn_write(struct comedi_device *dev,
if (insn->n == 0) {
return 0;
} else if (insn->n > 1) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ao_insn_write(): "
- "Invalid instruction length %d\n", dev->minor, insn->n);
+ dev_err(dev->class_dev, "Invalid instruction length %d\n",
+ insn->n);
return -EINVAL;
}
- if (chan >= thisboard->ao.count) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ao_insn_write(): "
- "Invalid channel %d\n", dev->minor, insn->n);
+ if (chan >= thisboard->ao_nchan) {
+ dev_err(dev->class_dev, "Invalid channel %d\n", insn->n);
return -EINVAL;
}
if (rang != 0) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ao_insn_write(): "
- "Invalid range %d\n", dev->minor, insn->n);
+ dev_err(dev->class_dev, "Invalid range %d\n", insn->n);
return -EINVAL;
}
if (aref != AREF_GROUND && aref != AREF_COMMON) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_ao_insn_write(): "
- "Invalid aref %d\n", dev->minor, insn->n);
+ dev_err(dev->class_dev, "Invalid aref %d\n", insn->n);
return -EINVAL;
}
/* Stop any running conversion */
- tmp = inl(info->ao_context[chan].ctrl_reg);
+ tmp = inl(dev->iobase + ME4000_AO_CTRL_REG(chan));
tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
- outl(tmp, info->ao_context[chan].ctrl_reg);
+ outl(tmp, dev->iobase + ME4000_AO_CTRL_REG(chan));
/* Clear control register and set to single mode */
- outl(0x0, info->ao_context[chan].ctrl_reg);
+ outl(0x0, dev->iobase + ME4000_AO_CTRL_REG(chan));
/* Write data value */
- outl(data[0], info->ao_context[chan].single_reg);
+ outl(data[0], dev->iobase + ME4000_AO_SINGLE_REG(chan));
/* Store in the mirror */
- info->ao_context[chan].mirror = data[0];
+ info->ao_readback[chan] = data[0];
return 1;
}
@@ -1619,18 +1325,17 @@ static int me4000_ao_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct me4000_info *info = dev->private;
int chan = CR_CHAN(insn->chanspec);
if (insn->n == 0) {
return 0;
} else if (insn->n > 1) {
- printk
- ("comedi%d: me4000: me4000_ao_insn_read(): "
- "Invalid instruction length\n", dev->minor);
+ dev_err(dev->class_dev, "Invalid instruction length\n");
return -EINVAL;
}
- data[0] = info->ao_context[chan].mirror;
+ data[0] = info->ao_readback[chan];
return 1;
}
@@ -1659,21 +1364,21 @@ static int me4000_dio_insn_bits(struct comedi_device *dev,
/* Write out the new digital output lines */
outl((s->state >> 0) & 0xFF,
- info->dio_context.port_0_reg);
+ dev->iobase + ME4000_DIO_PORT_0_REG);
outl((s->state >> 8) & 0xFF,
- info->dio_context.port_1_reg);
+ dev->iobase + ME4000_DIO_PORT_1_REG);
outl((s->state >> 16) & 0xFF,
- info->dio_context.port_2_reg);
+ dev->iobase + ME4000_DIO_PORT_2_REG);
outl((s->state >> 24) & 0xFF,
- info->dio_context.port_3_reg);
+ dev->iobase + ME4000_DIO_PORT_3_REG);
}
/* On return, data[1] contains the value of
the digital input and output lines. */
- data[1] = ((inl(info->dio_context.port_0_reg) & 0xFF) << 0) |
- ((inl(info->dio_context.port_1_reg) & 0xFF) << 8) |
- ((inl(info->dio_context.port_2_reg) & 0xFF) << 16) |
- ((inl(info->dio_context.port_3_reg) & 0xFF) << 24);
+ data[1] = ((inl(dev->iobase + ME4000_DIO_PORT_0_REG) & 0xFF) << 0) |
+ ((inl(dev->iobase + ME4000_DIO_PORT_1_REG) & 0xFF) << 8) |
+ ((inl(dev->iobase + ME4000_DIO_PORT_2_REG) & 0xFF) << 16) |
+ ((inl(dev->iobase + ME4000_DIO_PORT_3_REG) & 0xFF) << 24);
return insn->n;
}
@@ -1705,7 +1410,7 @@ static int me4000_dio_insn_config(struct comedi_device *dev,
* On the ME-4000 it is only possible to switch port wise (8 bit)
*/
- tmp = inl(info->dio_context.ctrl_reg);
+ tmp = inl(dev->iobase + ME4000_DIO_CTRL_REG);
if (data[0] == INSN_CONFIG_DIO_OUTPUT) {
if (chan < 8) {
@@ -1719,7 +1424,7 @@ static int me4000_dio_insn_config(struct comedi_device *dev,
* If one the first port is a fixed output
* port and the second is a fixed input port.
*/
- if (!inl(info->dio_context.dir_reg))
+ if (!inl(dev->iobase + ME4000_DIO_DIR_REG))
return -ENODEV;
s->io_bits |= 0xFF00;
@@ -1746,7 +1451,7 @@ static int me4000_dio_insn_config(struct comedi_device *dev,
* If one the first port is a fixed output
* port and the second is a fixed input port.
*/
- if (!inl(info->dio_context.dir_reg))
+ if (!inl(dev->iobase + ME4000_DIO_DIR_REG))
return -ENODEV;
s->io_bits &= ~0xFF;
@@ -1769,7 +1474,7 @@ static int me4000_dio_insn_config(struct comedi_device *dev,
}
}
- outl(tmp, info->dio_context.ctrl_reg);
+ outl(tmp, dev->iobase + ME4000_DIO_CTRL_REG);
return 1;
}
@@ -1778,177 +1483,56 @@ static int me4000_dio_insn_config(struct comedi_device *dev,
Counter section
===========================================================================*/
-static int cnt_reset(struct comedi_device *dev, unsigned int channel)
-{
- switch (channel) {
- case 0:
- outb(0x30, info->cnt_context.ctrl_reg);
- outb(0x00, info->cnt_context.counter_0_reg);
- outb(0x00, info->cnt_context.counter_0_reg);
- break;
- case 1:
- outb(0x70, info->cnt_context.ctrl_reg);
- outb(0x00, info->cnt_context.counter_1_reg);
- outb(0x00, info->cnt_context.counter_1_reg);
- break;
- case 2:
- outb(0xB0, info->cnt_context.ctrl_reg);
- outb(0x00, info->cnt_context.counter_2_reg);
- outb(0x00, info->cnt_context.counter_2_reg);
- break;
- default:
- printk(KERN_ERR
- "comedi%d: me4000: cnt_reset(): Invalid channel\n",
- dev->minor);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int cnt_config(struct comedi_device *dev, unsigned int channel,
- unsigned int mode)
-{
- int tmp = 0;
-
- switch (channel) {
- case 0:
- tmp |= ME4000_CNT_COUNTER_0;
- break;
- case 1:
- tmp |= ME4000_CNT_COUNTER_1;
- break;
- case 2:
- tmp |= ME4000_CNT_COUNTER_2;
- break;
- default:
- printk(KERN_ERR
- "comedi%d: me4000: cnt_config(): Invalid channel\n",
- dev->minor);
- return -EINVAL;
- }
-
- switch (mode) {
- case 0:
- tmp |= ME4000_CNT_MODE_0;
- break;
- case 1:
- tmp |= ME4000_CNT_MODE_1;
- break;
- case 2:
- tmp |= ME4000_CNT_MODE_2;
- break;
- case 3:
- tmp |= ME4000_CNT_MODE_3;
- break;
- case 4:
- tmp |= ME4000_CNT_MODE_4;
- break;
- case 5:
- tmp |= ME4000_CNT_MODE_5;
- break;
- default:
- printk(KERN_ERR
- "comedi%d: me4000: cnt_config(): Invalid counter mode\n",
- dev->minor);
- return -EINVAL;
- }
-
- /* Write the control word */
- tmp |= 0x30;
- outb(tmp, info->cnt_context.ctrl_reg);
-
- return 0;
-}
-
static int me4000_cnt_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
-
+ struct me4000_info *info = dev->private;
int err;
switch (data[0]) {
case GPCT_RESET:
- if (insn->n != 1) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_cnt_insn_config(): "
- "Invalid instruction length%d\n",
- dev->minor, insn->n);
+ if (insn->n != 1)
return -EINVAL;
- }
- err = cnt_reset(dev, insn->chanspec);
+ err = i8254_load(info->timer_regbase, 0, insn->chanspec, 0,
+ I8254_MODE0 | I8254_BINARY);
if (err)
return err;
break;
case GPCT_SET_OPERATION:
- if (insn->n != 2) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_cnt_insn_config(): "
- "Invalid instruction length%d\n",
- dev->minor, insn->n);
+ if (insn->n != 2)
return -EINVAL;
- }
- err = cnt_config(dev, insn->chanspec, data[1]);
+ err = i8254_set_mode(info->timer_regbase, 0, insn->chanspec,
+ (data[1] << 1) | I8254_BINARY);
if (err)
return err;
break;
default:
- printk(KERN_ERR
- "comedi%d: me4000: me4000_cnt_insn_config(): "
- "Invalid instruction\n", dev->minor);
return -EINVAL;
}
- return 2;
+ return insn->n;
}
static int me4000_cnt_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
-
- unsigned short tmp;
+ struct me4000_info *info = dev->private;
if (insn->n == 0)
return 0;
if (insn->n > 1) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_cnt_insn_read(): "
- "Invalid instruction length %d\n",
- dev->minor, insn->n);
+ dev_err(dev->class_dev, "Invalid instruction length %d\n",
+ insn->n);
return -EINVAL;
}
- switch (insn->chanspec) {
- case 0:
- tmp = inb(info->cnt_context.counter_0_reg);
- data[0] = tmp;
- tmp = inb(info->cnt_context.counter_0_reg);
- data[0] |= tmp << 8;
- break;
- case 1:
- tmp = inb(info->cnt_context.counter_1_reg);
- data[0] = tmp;
- tmp = inb(info->cnt_context.counter_1_reg);
- data[0] |= tmp << 8;
- break;
- case 2:
- tmp = inb(info->cnt_context.counter_2_reg);
- data[0] = tmp;
- tmp = inb(info->cnt_context.counter_2_reg);
- data[0] |= tmp << 8;
- break;
- default:
- printk(KERN_ERR
- "comedi%d: me4000: me4000_cnt_insn_read(): "
- "Invalid channel %d\n",
- dev->minor, insn->chanspec);
- return -EINVAL;
- }
+ data[0] = i8254_read(info->timer_regbase, 0, insn->chanspec);
return 1;
}
@@ -1957,58 +1541,72 @@ static int me4000_cnt_insn_write(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
-
- unsigned short tmp;
+ struct me4000_info *info = dev->private;
if (insn->n == 0) {
return 0;
} else if (insn->n > 1) {
- printk(KERN_ERR
- "comedi%d: me4000: me4000_cnt_insn_write(): "
- "Invalid instruction length %d\n",
- dev->minor, insn->n);
+ dev_err(dev->class_dev, "Invalid instruction length %d\n",
+ insn->n);
return -EINVAL;
}
- switch (insn->chanspec) {
- case 0:
- tmp = data[0] & 0xFF;
- outb(tmp, info->cnt_context.counter_0_reg);
- tmp = (data[0] >> 8) & 0xFF;
- outb(tmp, info->cnt_context.counter_0_reg);
- break;
- case 1:
- tmp = data[0] & 0xFF;
- outb(tmp, info->cnt_context.counter_1_reg);
- tmp = (data[0] >> 8) & 0xFF;
- outb(tmp, info->cnt_context.counter_1_reg);
- break;
- case 2:
- tmp = data[0] & 0xFF;
- outb(tmp, info->cnt_context.counter_2_reg);
- tmp = (data[0] >> 8) & 0xFF;
- outb(tmp, info->cnt_context.counter_2_reg);
- break;
- default:
- printk(KERN_ERR
- "comedi%d: me4000: me4000_cnt_insn_write(): "
- "Invalid channel %d\n",
- dev->minor, insn->chanspec);
- return -EINVAL;
- }
+ i8254_write(info->timer_regbase, 0, insn->chanspec, data[0]);
return 1;
}
-static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static const void *me4000_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
+ const struct me4000_board *thisboard;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(me4000_boards); i++) {
+ thisboard = &me4000_boards[i];
+ if (thisboard->device_id == pcidev->device)
+ return thisboard;
+ }
+ return NULL;
+}
+
+static int me4000_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
+{
+ const struct me4000_board *thisboard;
+ struct me4000_info *info;
struct comedi_subdevice *s;
int result;
- result = me4000_probe(dev, it);
+ comedi_set_hw_dev(dev, &pcidev->dev);
+
+ thisboard = me4000_find_boardinfo(dev, pcidev);
+ if (!thisboard)
+ return -ENODEV;
+ dev->board_ptr = thisboard;
+ dev->board_name = thisboard->name;
+
+ result = alloc_private(dev, sizeof(*info));
+ if (result)
+ return result;
+ info = dev->private;
+
+ result = comedi_pci_enable(pcidev, dev->board_name);
+ if (result)
+ return result;
+
+ info->plx_regbase = pci_resource_start(pcidev, 1);
+ dev->iobase = pci_resource_start(pcidev, 2);
+ info->timer_regbase = pci_resource_start(pcidev, 3);
+ if (!info->plx_regbase || !dev->iobase || !info->timer_regbase)
+ return -ENODEV;
+
+ result = xilinx_download(dev);
if (result)
return result;
+ me4000_reset(dev);
+
result = comedi_alloc_subdevices(dev, 4);
if (result)
return result;
@@ -2017,35 +1615,34 @@ static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
Analog input subdevice
========================================================================*/
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
- if (thisboard->ai.count) {
+ if (thisboard->ai_nchan) {
s->type = COMEDI_SUBD_AI;
s->subdev_flags =
SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
- s->n_chan = thisboard->ai.count;
+ s->n_chan = thisboard->ai_nchan;
s->maxdata = 0xFFFF; /* 16 bit ADC */
s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
s->range_table = &me4000_ai_range;
s->insn_read = me4000_ai_insn_read;
- if (info->irq > 0) {
- if (request_irq(info->irq, me4000_ai_isr,
- IRQF_SHARED, "ME-4000", dev)) {
- printk
- ("comedi%d: me4000: me4000_attach(): "
- "Unable to allocate irq\n", dev->minor);
+ if (pcidev->irq > 0) {
+ if (request_irq(pcidev->irq, me4000_ai_isr,
+ IRQF_SHARED, dev->board_name, dev)) {
+ dev_warn(dev->class_dev,
+ "request_irq failed\n");
} else {
dev->read_subdev = s;
s->subdev_flags |= SDF_CMD_READ;
s->cancel = me4000_ai_cancel;
s->do_cmdtest = me4000_ai_do_cmd_test;
s->do_cmd = me4000_ai_do_cmd;
+
+ dev->irq = pcidev->irq;
}
} else {
- printk(KERN_WARNING
- "comedi%d: me4000: me4000_attach(): "
- "No interrupt available\n", dev->minor);
+ dev_warn(dev->class_dev, "No interrupt available\n");
}
} else {
s->type = COMEDI_SUBD_UNUSED;
@@ -2055,14 +1652,14 @@ static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
Analog output subdevice
========================================================================*/
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
- if (thisboard->ao.count) {
+ if (thisboard->ao_nchan) {
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND;
- s->n_chan = thisboard->ao.count;
+ s->n_chan = thisboard->ao_nchan;
s->maxdata = 0xFFFF; /* 16 bit DAC */
- s->range_table = &me4000_ao_range;
+ s->range_table = &range_bipolar10;
s->insn_write = me4000_ao_insn_write;
s->insn_read = me4000_ao_insn_read;
} else {
@@ -2073,12 +1670,12 @@ static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
Digital I/O subdevice
========================================================================*/
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
- if (thisboard->dio.count) {
+ if (thisboard->dio_nchan) {
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = thisboard->dio.count * 8;
+ s->n_chan = thisboard->dio_nchan;
s->maxdata = 1;
s->range_table = &range_digital;
s->insn_bits = me4000_dio_insn_bits;
@@ -2091,21 +1688,22 @@ static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
* Check for optoisolated ME-4000 version. If one the first
* port is a fixed output port and the second is a fixed input port.
*/
- if (!inl(info->dio_context.dir_reg)) {
+ if (!inl(dev->iobase + ME4000_DIO_DIR_REG)) {
s->io_bits |= 0xFF;
- outl(ME4000_DIO_CTRL_BIT_MODE_0, info->dio_context.dir_reg);
+ outl(ME4000_DIO_CTRL_BIT_MODE_0,
+ dev->iobase + ME4000_DIO_DIR_REG);
}
/*=========================================================================
Counter subdevice
========================================================================*/
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
- if (thisboard->cnt.count) {
+ if (thisboard->has_counter) {
s->type = COMEDI_SUBD_COUNTER;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = thisboard->cnt.count;
+ s->n_chan = 3;
s->maxdata = 0xFFFF; /* 16 bit counters */
s->insn_read = me4000_cnt_insn_read;
s->insn_write = me4000_cnt_insn_write;
@@ -2119,12 +1717,14 @@ static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
static void me4000_detach(struct comedi_device *dev)
{
- if (info) {
- if (info->pci_dev_p) {
- reset_board(dev);
- if (info->plx_regbase)
- comedi_pci_disable(info->pci_dev_p);
- pci_dev_put(info->pci_dev_p);
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+ if (pcidev) {
+ if (dev->iobase) {
+ me4000_reset(dev);
+ comedi_pci_disable(pcidev);
}
}
}
@@ -2132,7 +1732,7 @@ static void me4000_detach(struct comedi_device *dev)
static struct comedi_driver me4000_driver = {
.driver_name = "me4000",
.module = THIS_MODULE,
- .attach = me4000_attach,
+ .attach_pci = me4000_attach_pci,
.detach = me4000_detach,
};
@@ -2148,20 +1748,20 @@ static void __devexit me4000_pci_remove(struct pci_dev *dev)
}
static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4650) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4660) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4661) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4662) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4663) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4670) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4671) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4672) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4673) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4680) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4681) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4682) },
- { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4683) },
- { 0 }
+ {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4650)},
+ {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660)},
+ {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660I)},
+ {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660S)},
+ {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660IS)},
+ {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670)},
+ {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670I)},
+ {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670S)},
+ {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670IS)},
+ {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680)},
+ {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680I)},
+ {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680S)},
+ {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680IS)},
+ {0}
};
MODULE_DEVICE_TABLE(pci, me4000_pci_table);
diff --git a/drivers/staging/comedi/drivers/me4000.h b/drivers/staging/comedi/drivers/me4000.h
deleted file mode 100644
index 5a4df4e4b236..000000000000
--- a/drivers/staging/comedi/drivers/me4000.h
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
- me4000.h
- Register descriptions and defines for the ME-4000 board family
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 1998-9 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.
-
-*/
-
-#ifndef _ME4000_H_
-#define _ME4000_H_
-
-/*=============================================================================
- PCI vendor and device IDs
- ===========================================================================*/
-
-#define PCI_VENDOR_ID_MEILHAUS 0x1402
-
-#define PCI_DEVICE_ID_MEILHAUS_ME4650 0x4650 /* Low Cost version */
-
-#define PCI_DEVICE_ID_MEILHAUS_ME4660 0x4660 /* Standard version */
-#define PCI_DEVICE_ID_MEILHAUS_ME4660I 0x4661 /* Isolated version */
-#define PCI_DEVICE_ID_MEILHAUS_ME4660S 0x4662 /* Standard version with Sample and Hold */
-#define PCI_DEVICE_ID_MEILHAUS_ME4660IS 0x4663 /* Isolated version with Sample and Hold */
-
-#define PCI_DEVICE_ID_MEILHAUS_ME4670 0x4670 /* Standard version */
-#define PCI_DEVICE_ID_MEILHAUS_ME4670I 0x4671 /* Isolated version */
-#define PCI_DEVICE_ID_MEILHAUS_ME4670S 0x4672 /* Standard version with Sample and Hold */
-#define PCI_DEVICE_ID_MEILHAUS_ME4670IS 0x4673 /* Isolated version with Sample and Hold */
-
-#define PCI_DEVICE_ID_MEILHAUS_ME4680 0x4680 /* Standard version */
-#define PCI_DEVICE_ID_MEILHAUS_ME4680I 0x4681 /* Isolated version */
-#define PCI_DEVICE_ID_MEILHAUS_ME4680S 0x4682 /* Standard version with Sample and Hold */
-#define PCI_DEVICE_ID_MEILHAUS_ME4680IS 0x4683 /* Isolated version with Sample and Hold */
-
-/*=============================================================================
- ME-4000 base register offsets
- ===========================================================================*/
-
-#define ME4000_AO_00_CTRL_REG 0x00 /* R/W */
-#define ME4000_AO_00_STATUS_REG 0x04 /* R/_ */
-#define ME4000_AO_00_FIFO_REG 0x08 /* _/W */
-#define ME4000_AO_00_SINGLE_REG 0x0C /* R/W */
-#define ME4000_AO_00_TIMER_REG 0x10 /* _/W */
-
-#define ME4000_AO_01_CTRL_REG 0x18 /* R/W */
-#define ME4000_AO_01_STATUS_REG 0x1C /* R/_ */
-#define ME4000_AO_01_FIFO_REG 0x20 /* _/W */
-#define ME4000_AO_01_SINGLE_REG 0x24 /* R/W */
-#define ME4000_AO_01_TIMER_REG 0x28 /* _/W */
-
-#define ME4000_AO_02_CTRL_REG 0x30 /* R/W */
-#define ME4000_AO_02_STATUS_REG 0x34 /* R/_ */
-#define ME4000_AO_02_FIFO_REG 0x38 /* _/W */
-#define ME4000_AO_02_SINGLE_REG 0x3C /* R/W */
-#define ME4000_AO_02_TIMER_REG 0x40 /* _/W */
-
-#define ME4000_AO_03_CTRL_REG 0x48 /* R/W */
-#define ME4000_AO_03_STATUS_REG 0x4C /* R/_ */
-#define ME4000_AO_03_FIFO_REG 0x50 /* _/W */
-#define ME4000_AO_03_SINGLE_REG 0x54 /* R/W */
-#define ME4000_AO_03_TIMER_REG 0x58 /* _/W */
-
-#define ME4000_AI_CTRL_REG 0x74 /* _/W */
-#define ME4000_AI_STATUS_REG 0x74 /* R/_ */
-#define ME4000_AI_CHANNEL_LIST_REG 0x78 /* _/W */
-#define ME4000_AI_DATA_REG 0x7C /* R/_ */
-#define ME4000_AI_CHAN_TIMER_REG 0x80 /* _/W */
-#define ME4000_AI_CHAN_PRE_TIMER_REG 0x84 /* _/W */
-#define ME4000_AI_SCAN_TIMER_LOW_REG 0x88 /* _/W */
-#define ME4000_AI_SCAN_TIMER_HIGH_REG 0x8C /* _/W */
-#define ME4000_AI_SCAN_PRE_TIMER_LOW_REG 0x90 /* _/W */
-#define ME4000_AI_SCAN_PRE_TIMER_HIGH_REG 0x94 /* _/W */
-#define ME4000_AI_START_REG 0x98 /* R/_ */
-
-#define ME4000_IRQ_STATUS_REG 0x9C /* R/_ */
-
-#define ME4000_DIO_PORT_0_REG 0xA0 /* R/W */
-#define ME4000_DIO_PORT_1_REG 0xA4 /* R/W */
-#define ME4000_DIO_PORT_2_REG 0xA8 /* R/W */
-#define ME4000_DIO_PORT_3_REG 0xAC /* R/W */
-#define ME4000_DIO_DIR_REG 0xB0 /* R/W */
-
-#define ME4000_AO_LOADSETREG_XX 0xB4 /* R/W */
-
-#define ME4000_DIO_CTRL_REG 0xB8 /* R/W */
-
-#define ME4000_AO_DEMUX_ADJUST_REG 0xBC /* -/W */
-
-#define ME4000_AI_SAMPLE_COUNTER_REG 0xC0 /* _/W */
-
-/*=============================================================================
- Value to adjust Demux
- ===========================================================================*/
-
-#define ME4000_AO_DEMUX_ADJUST_VALUE 0x4C
-
-/*=============================================================================
- Counter base register offsets
- ===========================================================================*/
-
-#define ME4000_CNT_COUNTER_0_REG 0x00
-#define ME4000_CNT_COUNTER_1_REG 0x01
-#define ME4000_CNT_COUNTER_2_REG 0x02
-#define ME4000_CNT_CTRL_REG 0x03
-
-/*=============================================================================
- PLX base register offsets
- ===========================================================================*/
-
-#define PLX_INTCSR 0x4C /* Interrupt control and status register */
-#define PLX_ICR 0x50 /* Initialization control register */
-
-/*=============================================================================
- Bits for the PLX_ICSR register
- ===========================================================================*/
-
-#define PLX_INTCSR_LOCAL_INT1_EN 0x01 /* If set, local interrupt 1 is enabled (r/w) */
-#define PLX_INTCSR_LOCAL_INT1_POL 0x02 /* If set, local interrupt 1 polarity is active high (r/w) */
-#define PLX_INTCSR_LOCAL_INT1_STATE 0x04 /* If set, local interrupt 1 is active (r/_) */
-#define PLX_INTCSR_LOCAL_INT2_EN 0x08 /* If set, local interrupt 2 is enabled (r/w) */
-#define PLX_INTCSR_LOCAL_INT2_POL 0x10 /* If set, local interrupt 2 polarity is active high (r/w) */
-#define PLX_INTCSR_LOCAL_INT2_STATE 0x20 /* If set, local interrupt 2 is active (r/_) */
-#define PLX_INTCSR_PCI_INT_EN 0x40 /* If set, PCI interrupt is enabled (r/w) */
-#define PLX_INTCSR_SOFT_INT 0x80 /* If set, a software interrupt is generated (r/w) */
-
-/*=============================================================================
- Bits for the PLX_ICR register
- ===========================================================================*/
-
-#define PLX_ICR_BIT_EEPROM_CLOCK_SET 0x01000000
-#define PLX_ICR_BIT_EEPROM_CHIP_SELECT 0x02000000
-#define PLX_ICR_BIT_EEPROM_WRITE 0x04000000
-#define PLX_ICR_BIT_EEPROM_READ 0x08000000
-#define PLX_ICR_BIT_EEPROM_VALID 0x10000000
-
-#define PLX_ICR_MASK_EEPROM 0x1F000000
-
-#define EEPROM_DELAY 1
-
-/*=============================================================================
- Bits for the ME4000_AO_CTRL_REG register
- ===========================================================================*/
-
-#define ME4000_AO_CTRL_BIT_MODE_0 0x001
-#define ME4000_AO_CTRL_BIT_MODE_1 0x002
-#define ME4000_AO_CTRL_MASK_MODE 0x003
-#define ME4000_AO_CTRL_BIT_STOP 0x004
-#define ME4000_AO_CTRL_BIT_ENABLE_FIFO 0x008
-#define ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG 0x010
-#define ME4000_AO_CTRL_BIT_EX_TRIG_EDGE 0x020
-#define ME4000_AO_CTRL_BIT_IMMEDIATE_STOP 0x080
-#define ME4000_AO_CTRL_BIT_ENABLE_DO 0x100
-#define ME4000_AO_CTRL_BIT_ENABLE_IRQ 0x200
-#define ME4000_AO_CTRL_BIT_RESET_IRQ 0x400
-
-/*=============================================================================
- Bits for the ME4000_AO_STATUS_REG register
- ===========================================================================*/
-
-#define ME4000_AO_STATUS_BIT_FSM 0x01
-#define ME4000_AO_STATUS_BIT_FF 0x02
-#define ME4000_AO_STATUS_BIT_HF 0x04
-#define ME4000_AO_STATUS_BIT_EF 0x08
-
-/*=============================================================================
- Bits for the ME4000_AI_CTRL_REG register
- ===========================================================================*/
-
-#define ME4000_AI_CTRL_BIT_MODE_0 0x00000001
-#define ME4000_AI_CTRL_BIT_MODE_1 0x00000002
-#define ME4000_AI_CTRL_BIT_MODE_2 0x00000004
-#define ME4000_AI_CTRL_BIT_SAMPLE_HOLD 0x00000008
-#define ME4000_AI_CTRL_BIT_IMMEDIATE_STOP 0x00000010
-#define ME4000_AI_CTRL_BIT_STOP 0x00000020
-#define ME4000_AI_CTRL_BIT_CHANNEL_FIFO 0x00000040
-#define ME4000_AI_CTRL_BIT_DATA_FIFO 0x00000080
-#define ME4000_AI_CTRL_BIT_FULLSCALE 0x00000100
-#define ME4000_AI_CTRL_BIT_OFFSET 0x00000200
-#define ME4000_AI_CTRL_BIT_EX_TRIG_ANALOG 0x00000400
-#define ME4000_AI_CTRL_BIT_EX_TRIG 0x00000800
-#define ME4000_AI_CTRL_BIT_EX_TRIG_FALLING 0x00001000
-#define ME4000_AI_CTRL_BIT_EX_IRQ 0x00002000
-#define ME4000_AI_CTRL_BIT_EX_IRQ_RESET 0x00004000
-#define ME4000_AI_CTRL_BIT_LE_IRQ 0x00008000
-#define ME4000_AI_CTRL_BIT_LE_IRQ_RESET 0x00010000
-#define ME4000_AI_CTRL_BIT_HF_IRQ 0x00020000
-#define ME4000_AI_CTRL_BIT_HF_IRQ_RESET 0x00040000
-#define ME4000_AI_CTRL_BIT_SC_IRQ 0x00080000
-#define ME4000_AI_CTRL_BIT_SC_IRQ_RESET 0x00100000
-#define ME4000_AI_CTRL_BIT_SC_RELOAD 0x00200000
-#define ME4000_AI_CTRL_BIT_EX_TRIG_BOTH 0x80000000
-
-/*=============================================================================
- Bits for the ME4000_AI_STATUS_REG register
- ===========================================================================*/
-
-#define ME4000_AI_STATUS_BIT_EF_CHANNEL 0x00400000
-#define ME4000_AI_STATUS_BIT_HF_CHANNEL 0x00800000
-#define ME4000_AI_STATUS_BIT_FF_CHANNEL 0x01000000
-#define ME4000_AI_STATUS_BIT_EF_DATA 0x02000000
-#define ME4000_AI_STATUS_BIT_HF_DATA 0x04000000
-#define ME4000_AI_STATUS_BIT_FF_DATA 0x08000000
-#define ME4000_AI_STATUS_BIT_LE 0x10000000
-#define ME4000_AI_STATUS_BIT_FSM 0x20000000
-
-/*=============================================================================
- Bits for the ME4000_IRQ_STATUS_REG register
- ===========================================================================*/
-
-#define ME4000_IRQ_STATUS_BIT_EX 0x01
-#define ME4000_IRQ_STATUS_BIT_LE 0x02
-#define ME4000_IRQ_STATUS_BIT_AI_HF 0x04
-#define ME4000_IRQ_STATUS_BIT_AO_0_HF 0x08
-#define ME4000_IRQ_STATUS_BIT_AO_1_HF 0x10
-#define ME4000_IRQ_STATUS_BIT_AO_2_HF 0x20
-#define ME4000_IRQ_STATUS_BIT_AO_3_HF 0x40
-#define ME4000_IRQ_STATUS_BIT_SC 0x80
-
-/*=============================================================================
- Bits for the ME4000_DIO_CTRL_REG register
- ===========================================================================*/
-
-#define ME4000_DIO_CTRL_BIT_MODE_0 0x0001
-#define ME4000_DIO_CTRL_BIT_MODE_1 0x0002
-#define ME4000_DIO_CTRL_BIT_MODE_2 0x0004
-#define ME4000_DIO_CTRL_BIT_MODE_3 0x0008
-#define ME4000_DIO_CTRL_BIT_MODE_4 0x0010
-#define ME4000_DIO_CTRL_BIT_MODE_5 0x0020
-#define ME4000_DIO_CTRL_BIT_MODE_6 0x0040
-#define ME4000_DIO_CTRL_BIT_MODE_7 0x0080
-
-#define ME4000_DIO_CTRL_BIT_FUNCTION_0 0x0100
-#define ME4000_DIO_CTRL_BIT_FUNCTION_1 0x0200
-
-#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_0 0x0400
-#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_1 0x0800
-#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_2 0x1000
-#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_3 0x2000
-
-/*=============================================================================
- Information about the hardware capabilities
- ===========================================================================*/
-
-struct me4000_ao_info {
- int count;
- int fifo_count;
-};
-
-struct me4000_ai_info {
- int count;
- int sh_count;
- int diff_count;
- int ex_trig_analog;
-};
-
-struct me4000_dio_info {
- int count;
-};
-
-struct me4000_cnt_info {
- int count;
-};
-
-struct me4000_board {
- const char *name;
- unsigned short device_id;
- struct me4000_ao_info ao;
- struct me4000_ai_info ai;
- struct me4000_dio_info dio;
- struct me4000_cnt_info cnt;
-};
-
-#define thisboard ((const struct me4000_board *)dev->board_ptr)
-
-/*=============================================================================
- Global board and subdevice information structures
- ===========================================================================*/
-
-struct me4000_ao_context {
- int irq;
-
- unsigned long mirror; /* Store the last written value */
-
- unsigned long ctrl_reg;
- unsigned long status_reg;
- unsigned long fifo_reg;
- unsigned long single_reg;
- unsigned long timer_reg;
- unsigned long irq_status_reg;
- unsigned long preload_reg;
-};
-
-struct me4000_ai_context {
- int irq;
-
- unsigned long ctrl_reg;
- unsigned long status_reg;
- unsigned long channel_list_reg;
- unsigned long data_reg;
- unsigned long chan_timer_reg;
- unsigned long chan_pre_timer_reg;
- unsigned long scan_timer_low_reg;
- unsigned long scan_timer_high_reg;
- unsigned long scan_pre_timer_low_reg;
- unsigned long scan_pre_timer_high_reg;
- unsigned long start_reg;
- unsigned long irq_status_reg;
- unsigned long sample_counter_reg;
-};
-
-struct me4000_dio_context {
- unsigned long dir_reg;
- unsigned long ctrl_reg;
- unsigned long port_0_reg;
- unsigned long port_1_reg;
- unsigned long port_2_reg;
- unsigned long port_3_reg;
-};
-
-struct me4000_cnt_context {
- unsigned long ctrl_reg;
- unsigned long counter_0_reg;
- unsigned long counter_1_reg;
- unsigned long counter_2_reg;
-};
-
-struct me4000_info {
- unsigned long plx_regbase; /* PLX configuration space base address */
- unsigned long me4000_regbase; /* Base address of the ME4000 */
- unsigned long timer_regbase; /* Base address of the timer circuit */
- unsigned long program_regbase; /* Base address to set the program pin for the xilinx */
-
- unsigned long plx_regbase_size; /* PLX register set space */
- unsigned long me4000_regbase_size; /* ME4000 register set space */
- unsigned long timer_regbase_size; /* Timer circuit register set space */
- unsigned long program_regbase_size; /* Size of program base address of the ME4000 */
-
- unsigned int serial_no; /* Serial number of the board */
- unsigned char hw_revision; /* Hardware revision of the board */
- unsigned short vendor_id; /* Meilhaus vendor id */
- unsigned short device_id; /* Device id */
-
- struct pci_dev *pci_dev_p; /* General PCI information */
-
- unsigned int irq; /* IRQ assigned from the PCI BIOS */
-
- struct me4000_ai_context ai_context; /* Analog input specific context */
- struct me4000_ao_context ao_context[4]; /* Vector with analog output specific context */
- struct me4000_dio_context dio_context; /* Digital I/O specific context */
- struct me4000_cnt_context cnt_context; /* Counter specific context */
-};
-
-#define info ((struct me4000_info *)dev->private)
-
-/*-----------------------------------------------------------------------------
- Defines for analog input
- ----------------------------------------------------------------------------*/
-
-/* General stuff */
-#define ME4000_AI_FIFO_COUNT 2048
-
-#define ME4000_AI_MIN_TICKS 66
-#define ME4000_AI_MIN_SAMPLE_TIME 2000 /* Minimum sample time [ns] */
-#define ME4000_AI_BASE_FREQUENCY (unsigned int) 33E6
-
-/* Channel list defines and masks */
-#define ME4000_AI_CHANNEL_LIST_COUNT 1024
-
-#define ME4000_AI_LIST_INPUT_SINGLE_ENDED 0x000
-#define ME4000_AI_LIST_INPUT_DIFFERENTIAL 0x020
-
-#define ME4000_AI_LIST_RANGE_BIPOLAR_10 0x000
-#define ME4000_AI_LIST_RANGE_BIPOLAR_2_5 0x040
-#define ME4000_AI_LIST_RANGE_UNIPOLAR_10 0x080
-#define ME4000_AI_LIST_RANGE_UNIPOLAR_2_5 0x0C0
-
-#define ME4000_AI_LIST_LAST_ENTRY 0x100
-
-/*-----------------------------------------------------------------------------
- Defines for counters
- ----------------------------------------------------------------------------*/
-
-#define ME4000_CNT_COUNTER_0 0x00
-#define ME4000_CNT_COUNTER_1 0x40
-#define ME4000_CNT_COUNTER_2 0x80
-
-#define ME4000_CNT_MODE_0 0x00 /* Change state if zero crossing */
-#define ME4000_CNT_MODE_1 0x02 /* Retriggerable One-Shot */
-#define ME4000_CNT_MODE_2 0x04 /* Asymmetrical divider */
-#define ME4000_CNT_MODE_3 0x06 /* Symmetrical divider */
-#define ME4000_CNT_MODE_4 0x08 /* Counter start by software trigger */
-#define ME4000_CNT_MODE_5 0x0A /* Counter start by hardware trigger */
-
-#endif
diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
index 8c6f8b93b277..2ce0b14af589 100644
--- a/drivers/staging/comedi/drivers/me_daq.c
+++ b/drivers/staging/comedi/drivers/me_daq.c
@@ -41,22 +41,14 @@ Configuration options:
If bus/slot is not specified, the first available PCI
device will be used.
-
-The 2600 requires a firmware upload, which can be accomplished
-using the -i or --init-data option of comedi_config.
-The firmware can be
-found in the comedi_nonfree_firmware tarball available
-from http://www.comedi.org
-
*/
#include <linux/interrupt.h>
#include <linux/sched.h>
+#include <linux/firmware.h>
#include "../comedidev.h"
-/*#include "me2600_fw.h" */
-
-#define ME_DRIVER_NAME "me_daq"
+#define ME2600_FIRMWARE "me2600_firmware.bin"
#define PCI_VENDOR_ID_MEILHAUS 0x1402
#define ME2000_DEVICE_ID 0x2000
@@ -198,8 +190,7 @@ struct me_board {
static const struct me_board me_boards[] = {
{
- /* -- ME-2600i -- */
- .name = ME_DRIVER_NAME,
+ .name = "me-2600i",
.device_id = ME2600_DEVICE_ID,
/* Analog Output */
.ao_channel_nbr = 4,
@@ -214,8 +205,7 @@ static const struct me_board me_boards[] = {
.dio_channel_nbr = 32,
},
{
- /* -- ME-2000i -- */
- .name = ME_DRIVER_NAME,
+ .name = "me-2000i",
.device_id = ME2000_DEVICE_ID,
/* Analog Output */
.ao_channel_nbr = 0,
@@ -341,7 +331,7 @@ static int me_dio_insn_bits(struct comedi_device *dev,
/* Analog instant input */
static int me_ai_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *subdevice,
+ struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
unsigned short value;
@@ -435,7 +425,7 @@ static int me_ai_do_cmd_test(struct comedi_device *dev,
/* Analog input command */
static int me_ai_do_cmd(struct comedi_device *dev,
- struct comedi_subdevice *subdevice)
+ struct comedi_subdevice *s)
{
return 0;
}
@@ -524,8 +514,7 @@ static int me_ao_insn_read(struct comedi_device *dev,
/* Xilinx firmware download for card: ME-2600i */
static int me2600_xilinx_download(struct comedi_device *dev,
- unsigned char *me2600_firmware,
- unsigned int length)
+ const u8 *data, size_t size)
{
unsigned int value;
unsigned int file_length;
@@ -552,19 +541,20 @@ static int me2600_xilinx_download(struct comedi_device *dev,
* Byte 8-11: date
* Byte 12-15: reserved
*/
- if (length < 16)
+ if (size < 16)
return -EINVAL;
- file_length = (((unsigned int)me2600_firmware[0] & 0xff) << 24) +
- (((unsigned int)me2600_firmware[1] & 0xff) << 16) +
- (((unsigned int)me2600_firmware[2] & 0xff) << 8) +
- ((unsigned int)me2600_firmware[3] & 0xff);
+
+ file_length = (((unsigned int)data[0] & 0xff) << 24) +
+ (((unsigned int)data[1] & 0xff) << 16) +
+ (((unsigned int)data[2] & 0xff) << 8) +
+ ((unsigned int)data[3] & 0xff);
/*
* Loop for writing firmware byte by byte to xilinx
* Firmware data start at offfset 16
*/
for (i = 0; i < file_length; i++)
- writeb((me2600_firmware[16 + i] & 0xff),
+ writeb((data[16 + i] & 0xff),
dev_private->me_regbase + 0x0);
/* Write 5 dummy values to xilinx */
@@ -590,6 +580,22 @@ 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;
+}
+
/* Reset device */
static int me_reset(struct comedi_device *dev)
{
@@ -607,44 +613,24 @@ static int me_reset(struct comedi_device *dev)
return 0;
}
-static struct pci_dev *me_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static const void *me_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
const struct me_board *board;
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
int i;
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (pcidev->bus->number != bus ||
- PCI_SLOT(pcidev->devfn) != slot)
- continue;
- }
- if (pcidev->vendor != PCI_VENDOR_ID_MEILHAUS)
- continue;
-
- for (i = 0; i < ARRAY_SIZE(me_boards); i++) {
- board = &me_boards[i];
- if (board->device_id != pcidev->device)
- continue;
-
- dev->board_ptr = board;
- return pcidev;
- }
+ for (i = 0; i < ARRAY_SIZE(me_boards); i++) {
+ board = &me_boards[i];
+ if (board->device_id == pcidev->device)
+ return board;
}
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
return NULL;
}
-static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int me_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev)
{
- struct pci_dev *pci_device;
- struct comedi_subdevice *subdevice;
- struct me_board *board;
+ const struct me_board *board;
+ struct comedi_subdevice *s;
resource_size_t plx_regbase_tmp;
unsigned long plx_regbase_size_tmp;
resource_size_t me_regbase_tmp;
@@ -654,29 +640,28 @@ static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it)
resource_size_t regbase_tmp;
int result, error;
+ comedi_set_hw_dev(dev, &pcidev->dev);
+
+ board = me_find_boardinfo(dev, pcidev);
+ if (!board)
+ return -ENODEV;
+ dev->board_ptr = board;
+ dev->board_name = board->name;
+
/* Allocate private memory */
if (alloc_private(dev, sizeof(struct me_private_data)) < 0)
return -ENOMEM;
- pci_device = me_find_pci_dev(dev, it);
- if (!pci_device)
- return -EIO;
- comedi_set_hw_dev(dev, &pci_device->dev);
- board = (struct me_board *)dev->board_ptr;
-
/* Enable PCI device and request PCI regions */
- if (comedi_pci_enable(pci_device, ME_DRIVER_NAME) < 0) {
+ if (comedi_pci_enable(pcidev, dev->board_name) < 0) {
printk(KERN_ERR "comedi%d: Failed to enable PCI device and "
"request regions\n", dev->minor);
return -EIO;
}
- /* Set data in device structure */
- dev->board_name = board->name;
-
/* Read PLX register base address [PCI_BASE_ADDRESS #0]. */
- plx_regbase_tmp = pci_resource_start(pci_device, 0);
- plx_regbase_size_tmp = pci_resource_len(pci_device, 0);
+ plx_regbase_tmp = pci_resource_start(pcidev, 0);
+ plx_regbase_size_tmp = pci_resource_len(pcidev, 0);
dev_private->plx_regbase =
ioremap(plx_regbase_tmp, plx_regbase_size_tmp);
dev_private->plx_regbase_size = plx_regbase_size_tmp;
@@ -687,8 +672,8 @@ static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* Read Swap base address [PCI_BASE_ADDRESS #5]. */
- swap_regbase_tmp = pci_resource_start(pci_device, 5);
- swap_regbase_size_tmp = pci_resource_len(pci_device, 5);
+ swap_regbase_tmp = pci_resource_start(pcidev, 5);
+ swap_regbase_size_tmp = pci_resource_len(pcidev, 5);
if (!swap_regbase_tmp)
printk(KERN_ERR "comedi%d: Swap not present\n", dev->minor);
@@ -702,20 +687,20 @@ static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it)
plx_regbase_tmp = swap_regbase_tmp;
swap_regbase_tmp = regbase_tmp;
- result = pci_write_config_dword(pci_device,
+ result = pci_write_config_dword(pcidev,
PCI_BASE_ADDRESS_0,
plx_regbase_tmp);
if (result != PCIBIOS_SUCCESSFUL)
return -EIO;
- result = pci_write_config_dword(pci_device,
+ result = pci_write_config_dword(pcidev,
PCI_BASE_ADDRESS_5,
swap_regbase_tmp);
if (result != PCIBIOS_SUCCESSFUL)
return -EIO;
} else {
plx_regbase_tmp -= 0x80;
- result = pci_write_config_dword(pci_device,
+ result = pci_write_config_dword(pcidev,
PCI_BASE_ADDRESS_0,
plx_regbase_tmp);
if (result != PCIBIOS_SUCCESSFUL)
@@ -726,8 +711,8 @@ static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* Read Meilhaus register base address [PCI_BASE_ADDRESS #2]. */
- me_regbase_tmp = pci_resource_start(pci_device, 2);
- me_regbase_size_tmp = pci_resource_len(pci_device, 2);
+ me_regbase_tmp = pci_resource_start(pcidev, 2);
+ me_regbase_size_tmp = pci_resource_len(pcidev, 2);
dev_private->me_regbase_size = me_regbase_size_tmp;
dev_private->me_regbase = ioremap(me_regbase_tmp, me_regbase_size_tmp);
if (!dev_private->me_regbase) {
@@ -735,64 +720,55 @@ static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it)
dev->minor);
return -ENOMEM;
}
+
/* Download firmware and reset card */
if (board->device_id == ME2600_DEVICE_ID) {
- unsigned char *aux_data;
- int aux_len;
-
- aux_data = comedi_aux_data(it->options, 0);
- aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH];
-
- if (!aux_data || aux_len < 1) {
- comedi_error(dev, "You must provide me2600 firmware "
- "using the --init-data option of "
- "comedi_config");
- return -EINVAL;
- }
- me2600_xilinx_download(dev, aux_data, aux_len);
+ result = me2600_upload_firmware(dev);
+ if (result < 0)
+ return result;
}
-
me_reset(dev);
error = comedi_alloc_subdevices(dev, 3);
if (error)
return error;
- subdevice = dev->subdevices + 0;
- subdevice->type = COMEDI_SUBD_AI;
- subdevice->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
- subdevice->n_chan = board->ai_channel_nbr;
- subdevice->maxdata = board->ai_resolution_mask;
- subdevice->len_chanlist = board->ai_channel_nbr;
- subdevice->range_table = board->ai_range_list;
- subdevice->cancel = me_ai_cancel;
- subdevice->insn_read = me_ai_insn_read;
- subdevice->do_cmdtest = me_ai_do_cmd_test;
- subdevice->do_cmd = me_ai_do_cmd;
-
- subdevice = dev->subdevices + 1;
- subdevice->type = COMEDI_SUBD_AO;
- subdevice->subdev_flags = SDF_WRITEABLE | SDF_COMMON;
- subdevice->n_chan = board->ao_channel_nbr;
- subdevice->maxdata = board->ao_resolution_mask;
- subdevice->len_chanlist = board->ao_channel_nbr;
- subdevice->range_table = board->ao_range_list;
- subdevice->insn_read = me_ao_insn_read;
- subdevice->insn_write = me_ao_insn_write;
-
- subdevice = dev->subdevices + 2;
- subdevice->type = COMEDI_SUBD_DIO;
- subdevice->subdev_flags = SDF_READABLE | SDF_WRITEABLE;
- subdevice->n_chan = board->dio_channel_nbr;
- subdevice->maxdata = 1;
- subdevice->len_chanlist = board->dio_channel_nbr;
- subdevice->range_table = &range_digital;
- subdevice->insn_bits = me_dio_insn_bits;
- subdevice->insn_config = me_dio_insn_config;
- subdevice->io_bits = 0;
-
- printk(KERN_INFO "comedi%d: " ME_DRIVER_NAME " attached.\n",
- dev->minor);
+ s = &dev->subdevices[0];
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
+ s->n_chan = board->ai_channel_nbr;
+ s->maxdata = board->ai_resolution_mask;
+ s->len_chanlist = board->ai_channel_nbr;
+ s->range_table = board->ai_range_list;
+ s->cancel = me_ai_cancel;
+ s->insn_read = me_ai_insn_read;
+ s->do_cmdtest = me_ai_do_cmd_test;
+ s->do_cmd = me_ai_do_cmd;
+
+ s = &dev->subdevices[1];
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITEABLE | SDF_COMMON;
+ s->n_chan = board->ao_channel_nbr;
+ s->maxdata = board->ao_resolution_mask;
+ s->len_chanlist = board->ao_channel_nbr;
+ s->range_table = board->ao_range_list;
+ s->insn_read = me_ao_insn_read;
+ s->insn_write = me_ao_insn_write;
+
+ s = &dev->subdevices[2];
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITEABLE;
+ s->n_chan = board->dio_channel_nbr;
+ s->maxdata = 1;
+ s->len_chanlist = board->dio_channel_nbr;
+ s->range_table = &range_digital;
+ s->insn_bits = me_dio_insn_bits;
+ s->insn_config = me_dio_insn_config;
+ s->io_bits = 0;
+
+ dev_info(dev->class_dev, "%s: %s attached\n",
+ dev->driver->driver_name, dev->board_name);
+
return 0;
}
@@ -818,7 +794,7 @@ static void me_detach(struct comedi_device *dev)
static struct comedi_driver me_daq_driver = {
.driver_name = "me_daq",
.module = THIS_MODULE,
- .attach = me_attach,
+ .attach_pci = me_attach_pci,
.detach = me_detach,
};
@@ -851,3 +827,4 @@ module_comedi_pci_driver(me_daq_driver, me_daq_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(ME2600_FIRMWARE);
diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c
index a93166d6a8f8..e27850f628ce 100644
--- a/drivers/staging/comedi/drivers/mite.c
+++ b/drivers/staging/comedi/drivers/mite.c
@@ -49,6 +49,8 @@
/* #define USE_KMALLOC */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "mite.h"
#include "comedi_fc.h"
@@ -59,52 +61,38 @@
#define PCI_DAQ_SIZE 4096
#define PCI_DAQ_SIZE_660X 8192
-struct mite_struct *mite_devices;
-EXPORT_SYMBOL(mite_devices);
-
#define TOP_OF_PAGE(x) ((x)|(~(PAGE_MASK)))
-void mite_init(void)
+struct mite_struct *mite_alloc(struct pci_dev *pcidev)
{
- struct pci_dev *pcidev = NULL;
struct mite_struct *mite;
-
- for_each_pci_dev(pcidev) {
- if (pcidev->vendor == PCI_VENDOR_ID_NI) {
- unsigned i;
-
- mite = kzalloc(sizeof(*mite), GFP_KERNEL);
- if (!mite) {
- printk(KERN_ERR "mite: allocation failed\n");
- pci_dev_put(pcidev);
- return;
- }
- spin_lock_init(&mite->lock);
- mite->pcidev = pci_dev_get(pcidev);
- for (i = 0; i < MAX_MITE_DMA_CHANNELS; ++i) {
- mite->channels[i].mite = mite;
- mite->channels[i].channel = i;
- mite->channels[i].done = 1;
- }
- mite->next = mite_devices;
- mite_devices = mite;
+ unsigned int i;
+
+ mite = kzalloc(sizeof(*mite), GFP_KERNEL);
+ if (mite) {
+ spin_lock_init(&mite->lock);
+ mite->pcidev = pcidev;
+ for (i = 0; i < MAX_MITE_DMA_CHANNELS; ++i) {
+ mite->channels[i].mite = mite;
+ mite->channels[i].channel = i;
+ mite->channels[i].done = 1;
}
}
+ return mite;
}
+EXPORT_SYMBOL(mite_alloc);
static void dump_chip_signature(u32 csigr_bits)
{
- printk(KERN_INFO "mite: version = %i, type = %i, mite mode = %i,"
- "interface mode = %i\n",
- mite_csigr_version(csigr_bits), mite_csigr_type(csigr_bits),
- mite_csigr_mmode(csigr_bits), mite_csigr_imode(csigr_bits));
- printk(KERN_INFO "mite: num channels = %i, write post fifo depth = %i,"
- "wins = %i, iowins = %i\n",
- mite_csigr_dmac(csigr_bits), mite_csigr_wpdep(csigr_bits),
- mite_csigr_wins(csigr_bits), mite_csigr_iowins(csigr_bits));
+ pr_info("version = %i, type = %i, mite mode = %i, interface mode = %i\n",
+ mite_csigr_version(csigr_bits), mite_csigr_type(csigr_bits),
+ mite_csigr_mmode(csigr_bits), mite_csigr_imode(csigr_bits));
+ pr_info("num channels = %i, write post fifo depth = %i, wins = %i, iowins = %i\n",
+ mite_csigr_dmac(csigr_bits), mite_csigr_wpdep(csigr_bits),
+ mite_csigr_wins(csigr_bits), mite_csigr_iowins(csigr_bits));
}
-unsigned mite_fifo_size(struct mite_struct *mite, unsigned channel)
+static unsigned mite_fifo_size(struct mite_struct *mite, unsigned channel)
{
unsigned fcr_bits = readl(mite->mite_io_addr + MITE_FCR(channel));
unsigned empty_count = (fcr_bits >> 16) & 0xff;
@@ -121,7 +109,8 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1)
unsigned unknown_dma_burst_bits;
if (comedi_pci_enable(mite->pcidev, "mite")) {
- printk(KERN_ERR "error enabling mite and requesting io regions\n");
+ dev_err(&mite->pcidev->dev,
+ "error enabling mite and requesting io regions\n");
return -EIO;
}
pci_set_master(mite->pcidev);
@@ -130,11 +119,10 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1)
mite->mite_phys_addr = addr;
mite->mite_io_addr = ioremap(addr, PCI_MITE_SIZE);
if (!mite->mite_io_addr) {
- printk(KERN_ERR "Failed to remap mite io memory address\n");
+ dev_err(&mite->pcidev->dev,
+ "Failed to remap mite io memory address\n");
return -ENOMEM;
}
- printk(KERN_INFO "MITE:0x%08llx mapped to %p ",
- (unsigned long long)mite->mite_phys_addr, mite->mite_io_addr);
addr = pci_resource_start(mite->pcidev, 1);
mite->daq_phys_addr = addr;
@@ -145,15 +133,15 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1)
*/
mite->daq_io_addr = ioremap(mite->daq_phys_addr, length);
if (!mite->daq_io_addr) {
- printk(KERN_ERR "Failed to remap daq io memory address\n");
+ dev_err(&mite->pcidev->dev,
+ "Failed to remap daq io memory address\n");
return -ENOMEM;
}
- printk(KERN_INFO "DAQ:0x%08llx mapped to %p\n",
- (unsigned long long)mite->daq_phys_addr, mite->daq_io_addr);
if (use_iodwbsr_1) {
writel(0, mite->mite_io_addr + MITE_IODWBSR);
- printk(KERN_INFO "mite: using I/O Window Base Size register 1\n");
+ dev_info(&mite->pcidev->dev,
+ "using I/O Window Base Size register 1\n");
writel(mite->daq_phys_addr | WENAB |
MITE_IODWBSR_1_WSIZE_bits(length),
mite->mite_io_addr + MITE_IODWBSR_1);
@@ -178,9 +166,9 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1)
csigr_bits = readl(mite->mite_io_addr + MITE_CSIGR);
mite->num_channels = mite_csigr_dmac(csigr_bits);
if (mite->num_channels > MAX_MITE_DMA_CHANNELS) {
- printk(KERN_WARNING "mite: bug? chip claims to have %i dma "
- "channels. Setting to %i.\n",
- mite->num_channels, MAX_MITE_DMA_CHANNELS);
+ dev_warn(&mite->pcidev->dev,
+ "mite: bug? chip claims to have %i dma channels. Setting to %i.\n",
+ mite->num_channels, MAX_MITE_DMA_CHANNELS);
mite->num_channels = MAX_MITE_DMA_CHANNELS;
}
dump_chip_signature(csigr_bits);
@@ -193,9 +181,7 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1)
mite->mite_io_addr + MITE_CHCR(i));
}
mite->fifo_size = mite_fifo_size(mite, 0);
- printk(KERN_INFO "mite: fifo size is %i.\n", mite->fifo_size);
- mite->used = 1;
-
+ dev_info(&mite->pcidev->dev, "fifo size is %i.\n", mite->fifo_size);
return 0;
}
EXPORT_SYMBOL(mite_setup2);
@@ -206,17 +192,6 @@ int mite_setup(struct mite_struct *mite)
}
EXPORT_SYMBOL(mite_setup);
-void mite_cleanup(void)
-{
- struct mite_struct *mite, *next;
-
- for (mite = mite_devices; mite; mite = next) {
- pci_dev_put(mite->pcidev);
- next = mite->next;
- kfree(mite);
- }
-}
-
void mite_unsetup(struct mite_struct *mite)
{
/* unsigned long offset, start, length; */
@@ -236,26 +211,43 @@ void mite_unsetup(struct mite_struct *mite)
comedi_pci_disable(mite->pcidev);
mite->mite_phys_addr = 0;
}
-
- mite->used = 0;
}
EXPORT_SYMBOL(mite_unsetup);
-void mite_list_devices(void)
+struct mite_dma_descriptor_ring *mite_alloc_ring(struct mite_struct *mite)
+{
+ struct mite_dma_descriptor_ring *ring =
+ kmalloc(sizeof(struct mite_dma_descriptor_ring), GFP_KERNEL);
+
+ if (ring == NULL)
+ return ring;
+ ring->hw_dev = get_device(&mite->pcidev->dev);
+ if (ring->hw_dev == NULL) {
+ kfree(ring);
+ return NULL;
+ }
+ ring->n_links = 0;
+ ring->descriptors = NULL;
+ ring->descriptors_dma_addr = 0;
+ return ring;
+};
+EXPORT_SYMBOL(mite_alloc_ring);
+
+void mite_free_ring(struct mite_dma_descriptor_ring *ring)
{
- struct mite_struct *mite, *next;
-
- printk(KERN_INFO "Available NI device IDs:");
- if (mite_devices)
- for (mite = mite_devices; mite; mite = next) {
- next = mite->next;
- printk(KERN_INFO " 0x%04x", mite_device_id(mite));
- if (mite->used)
- printk(KERN_INFO "(used)");
+ if (ring) {
+ if (ring->descriptors) {
+ dma_free_coherent(ring->hw_dev,
+ ring->n_links *
+ sizeof(struct mite_dma_descriptor),
+ ring->descriptors,
+ ring->descriptors_dma_addr);
}
- printk(KERN_INFO "\n");
-}
-EXPORT_SYMBOL(mite_list_devices);
+ put_device(ring->hw_dev);
+ kfree(ring);
+ }
+};
+EXPORT_SYMBOL(mite_free_ring);
struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite,
struct
@@ -317,7 +309,7 @@ void mite_dma_arm(struct mite_channel *mite_chan)
int chor;
unsigned long flags;
- MDPRINTK("mite_dma_arm ch%i\n", channel);
+ MDPRINTK("mite_dma_arm ch%i\n", mite_chan->channel);
/*
* memory barrier is intended to insure any twiddling with the buffer
* is done before writing to the mite to arm dma transfer
@@ -365,7 +357,8 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring,
n_links * sizeof(struct mite_dma_descriptor),
&ring->descriptors_dma_addr, GFP_KERNEL);
if (!ring->descriptors) {
- printk(KERN_ERR "mite: ring buffer allocation failed\n");
+ dev_err(async->subdevice->device->class_dev,
+ "mite: ring buffer allocation failed\n");
return -ENOMEM;
}
ring->n_links = n_links;
@@ -442,8 +435,7 @@ void mite_prep_dma(struct mite_channel *mite_chan,
mcr |= CR_PSIZE32;
break;
default:
- printk(KERN_WARNING "mite: bug! invalid mem bit width for dma "
- "transfer\n");
+ pr_warn("bug! invalid mem bit width for dma transfer\n");
break;
}
writel(mcr, mite->mite_io_addr + MITE_MCR(mite_chan->channel));
@@ -462,8 +454,7 @@ void mite_prep_dma(struct mite_channel *mite_chan,
dcr |= CR_PSIZE32;
break;
default:
- printk(KERN_WARNING "mite: bug! invalid dev bit width for dma "
- "transfer\n");
+ pr_warn("bug! invalid dev bit width for dma transfer\n");
break;
}
writel(dcr, mite->mite_io_addr + MITE_DCR(mite_chan->channel));
@@ -483,7 +474,7 @@ void mite_prep_dma(struct mite_channel *mite_chan,
}
EXPORT_SYMBOL(mite_prep_dma);
-u32 mite_device_bytes_transferred(struct mite_channel *mite_chan)
+static u32 mite_device_bytes_transferred(struct mite_channel *mite_chan)
{
struct mite_struct *mite = mite_chan->mite;
return readl(mite->mite_io_addr + MITE_DAR(mite_chan->channel));
@@ -577,7 +568,8 @@ int mite_sync_input_dma(struct mite_channel *mite_chan,
nbytes = mite_bytes_written_to_memory_lb(mite_chan);
if ((int)(mite_bytes_written_to_memory_ub(mite_chan) -
old_alloc_count) > 0) {
- printk("mite: DMA overwrite of free area\n");
+ dev_warn(async->subdevice->device->class_dev,
+ "mite: DMA overwrite of free area\n");
async->events |= COMEDI_CB_OVERFLOW;
return -1;
}
@@ -621,7 +613,8 @@ int mite_sync_output_dma(struct mite_channel *mite_chan,
(int)(nbytes_ub - stop_count) > 0)
nbytes_ub = stop_count;
if ((int)(nbytes_ub - old_alloc_count) > 0) {
- printk(KERN_ERR "mite: DMA underrun\n");
+ dev_warn(async->subdevice->device->class_dev,
+ "mite: DMA underrun\n");
async->events |= COMEDI_CB_OVERFLOW;
return -1;
}
@@ -672,8 +665,6 @@ EXPORT_SYMBOL(mite_done);
#ifdef DEBUG_MITE
-static void mite_decode(char **bit_str, unsigned int bits);
-
/* names of bits in mite registers */
static const char *const mite_CHOR_strings[] = {
@@ -743,86 +734,80 @@ static const char *const mite_CHSR_strings[] = {
"28", "lpauses", "30", "int",
};
-void mite_dump_regs(struct mite_channel *mite_chan)
-{
- unsigned long mite_io_addr =
- (unsigned long)mite_chan->mite->mite_io_addr;
- unsigned long addr = 0;
- unsigned long temp = 0;
-
- printk(KERN_DEBUG "mite_dump_regs ch%i\n", mite_chan->channel);
- printk(KERN_DEBUG "mite address is =0x%08lx\n", mite_io_addr);
-
- addr = mite_io_addr + MITE_CHOR(channel);
- printk(KERN_DEBUG "mite status[CHOR]at 0x%08lx =0x%08lx\n", addr,
- temp = readl(addr));
- mite_decode(mite_CHOR_strings, temp);
- addr = mite_io_addr + MITE_CHCR(channel);
- printk(KERN_DEBUG "mite status[CHCR]at 0x%08lx =0x%08lx\n", addr,
- temp = readl(addr));
- mite_decode(mite_CHCR_strings, temp);
- addr = mite_io_addr + MITE_TCR(channel);
- printk(KERN_DEBUG "mite status[TCR] at 0x%08lx =0x%08x\n", addr,
- readl(addr));
- addr = mite_io_addr + MITE_MCR(channel);
- printk(KERN_DEBUG "mite status[MCR] at 0x%08lx =0x%08lx\n", addr,
- temp = readl(addr));
- mite_decode(mite_MCR_strings, temp);
-
- addr = mite_io_addr + MITE_MAR(channel);
- printk(KERN_DEBUG "mite status[MAR] at 0x%08lx =0x%08x\n", addr,
- readl(addr));
- addr = mite_io_addr + MITE_DCR(channel);
- printk(KERN_DEBUG "mite status[DCR] at 0x%08lx =0x%08lx\n", addr,
- temp = readl(addr));
- mite_decode(mite_DCR_strings, temp);
- addr = mite_io_addr + MITE_DAR(channel);
- printk(KERN_DEBUG "mite status[DAR] at 0x%08lx =0x%08x\n", addr,
- readl(addr));
- addr = mite_io_addr + MITE_LKCR(channel);
- printk(KERN_DEBUG "mite status[LKCR]at 0x%08lx =0x%08lx\n", addr,
- temp = readl(addr));
- mite_decode(mite_LKCR_strings, temp);
- addr = mite_io_addr + MITE_LKAR(channel);
- printk(KERN_DEBUG "mite status[LKAR]at 0x%08lx =0x%08x\n", addr,
- readl(addr));
- addr = mite_io_addr + MITE_CHSR(channel);
- printk(KERN_DEBUG "mite status[CHSR]at 0x%08lx =0x%08lx\n", addr,
- temp = readl(addr));
- mite_decode(mite_CHSR_strings, temp);
- addr = mite_io_addr + MITE_FCR(channel);
- printk(KERN_DEBUG "mite status[FCR] at 0x%08lx =0x%08x\n\n", addr,
- readl(addr));
-}
-EXPORT_SYMBOL(mite_dump_regs);
-
-static void mite_decode(char **bit_str, unsigned int bits)
+static void mite_decode(const char *const *bit_str, unsigned int bits)
{
int i;
for (i = 31; i >= 0; i--) {
if (bits & (1 << i))
- printk(KERN_DEBUG " %s", bit_str[i]);
+ pr_debug(" %s\n", bit_str[i]);
}
- printk(KERN_DEBUG "\n");
}
-EXPORT_SYMBOL(mite_decode);
-#endif
-#ifdef MODULE
-int __init init_module(void)
+void mite_dump_regs(struct mite_channel *mite_chan)
{
- mite_init();
- mite_list_devices();
+ void __iomem *mite_io_addr = mite_chan->mite->mite_io_addr;
+ unsigned int offset;
+ unsigned int value;
+ int channel = mite_chan->channel;
+
+ pr_debug("mite_dump_regs ch%i\n", channel);
+ pr_debug("mite address is =%p\n", mite_io_addr);
+
+ offset = MITE_CHOR(channel);
+ value = readl(mite_io_addr + offset);
+ pr_debug("mite status[CHOR] at 0x%08x =0x%08x\n", offset, value);
+ mite_decode(mite_CHOR_strings, value);
+ offset = MITE_CHCR(channel);
+ value = readl(mite_io_addr + offset);
+ pr_debug("mite status[CHCR] at 0x%08x =0x%08x\n", offset, value);
+ mite_decode(mite_CHCR_strings, value);
+ offset = MITE_TCR(channel);
+ value = readl(mite_io_addr + offset);
+ pr_debug("mite status[TCR] at 0x%08x =0x%08x\n", offset, value);
+ offset = MITE_MCR(channel);
+ value = readl(mite_io_addr + offset);
+ pr_debug("mite status[MCR] at 0x%08x =0x%08x\n", offset, value);
+ mite_decode(mite_MCR_strings, value);
+ offset = MITE_MAR(channel);
+ value = readl(mite_io_addr + offset);
+ pr_debug("mite status[MAR] at 0x%08x =0x%08x\n", offset, value);
+ offset = MITE_DCR(channel);
+ value = readl(mite_io_addr + offset);
+ pr_debug("mite status[DCR] at 0x%08x =0x%08x\n", offset, value);
+ mite_decode(mite_DCR_strings, value);
+ offset = MITE_DAR(channel);
+ value = readl(mite_io_addr + offset);
+ pr_debug("mite status[DAR] at 0x%08x =0x%08x\n", offset, value);
+ offset = MITE_LKCR(channel);
+ value = readl(mite_io_addr + offset);
+ pr_debug("mite status[LKCR] at 0x%08x =0x%08x\n", offset, value);
+ mite_decode(mite_LKCR_strings, value);
+ offset = MITE_LKAR(channel);
+ value = readl(mite_io_addr + offset);
+ pr_debug("mite status[LKAR] at 0x%08x =0x%08x\n", offset, value);
+ offset = MITE_CHSR(channel);
+ value = readl(mite_io_addr + offset);
+ pr_debug("mite status[CHSR] at 0x%08x =0x%08x\n", offset, value);
+ mite_decode(mite_CHSR_strings, value);
+ offset = MITE_FCR(channel);
+ value = readl(mite_io_addr + offset);
+ pr_debug("mite status[FCR] at 0x%08x =0x%08x\n", offset, value);
+}
+EXPORT_SYMBOL(mite_dump_regs);
+#endif
+static int __init mite_module_init(void)
+{
return 0;
}
-void __exit cleanup_module(void)
+static void __exit mite_module_exit(void)
{
- mite_cleanup();
}
-#endif
+
+module_init(mite_module_init);
+module_exit(mite_module_exit);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h
index 83f1b27a4720..255b8ba9c917 100644
--- a/drivers/staging/comedi/drivers/mite.h
+++ b/drivers/staging/comedi/drivers/mite.h
@@ -25,15 +25,16 @@
#define _MITE_H_
#include <linux/pci.h>
+#include <linux/log2.h>
#include "../comedidev.h"
/* #define DEBUG_MITE */
#define PCIMIO_COMPAT
#ifdef DEBUG_MITE
-#define MDPRINTK(format, args...) printk(format , ## args)
+#define MDPRINTK(format, args...) pr_debug(format , ## args)
#else
-#define MDPRINTK(format, args...)
+#define MDPRINTK(format, args...) do { } while (0)
#endif
#define MAX_MITE_DMA_CHANNELS 8
@@ -61,15 +62,11 @@ struct mite_channel {
};
struct mite_struct {
- struct mite_struct *next;
- int used;
-
struct pci_dev *pcidev;
resource_size_t mite_phys_addr;
void __iomem *mite_io_addr;
resource_size_t daq_phys_addr;
void __iomem *daq_io_addr;
-
struct mite_channel channels[MAX_MITE_DMA_CHANNELS];
short channel_allocated[MAX_MITE_DMA_CHANNELS];
int num_channels;
@@ -77,41 +74,12 @@ struct mite_struct {
spinlock_t lock;
};
-static inline struct mite_dma_descriptor_ring *mite_alloc_ring(struct
- mite_struct
- *mite)
-{
- struct mite_dma_descriptor_ring *ring =
- kmalloc(sizeof(struct mite_dma_descriptor_ring), GFP_KERNEL);
- if (ring == NULL)
- return ring;
- ring->hw_dev = get_device(&mite->pcidev->dev);
- if (ring->hw_dev == NULL) {
- kfree(ring);
- return NULL;
- }
- ring->n_links = 0;
- ring->descriptors = NULL;
- ring->descriptors_dma_addr = 0;
- return ring;
-};
-
-static inline void mite_free_ring(struct mite_dma_descriptor_ring *ring)
-{
- if (ring) {
- if (ring->descriptors) {
- dma_free_coherent(ring->hw_dev,
- ring->n_links *
- sizeof(struct mite_dma_descriptor),
- ring->descriptors,
- ring->descriptors_dma_addr);
- }
- put_device(ring->hw_dev);
- kfree(ring);
- }
-};
+struct mite_struct *mite_alloc(struct pci_dev *pcidev);
-extern struct mite_struct *mite_devices;
+static inline void mite_free(struct mite_struct *mite)
+{
+ kfree(mite);
+}
static inline unsigned int mite_irq(struct mite_struct *mite)
{
@@ -123,12 +91,11 @@ static inline unsigned int mite_device_id(struct mite_struct *mite)
return mite->pcidev->device;
};
-void mite_init(void);
-void mite_cleanup(void);
int mite_setup(struct mite_struct *mite);
int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1);
void mite_unsetup(struct mite_struct *mite);
-void mite_list_devices(void);
+struct mite_dma_descriptor_ring *mite_alloc_ring(struct mite_struct *mite);
+void mite_free_ring(struct mite_dma_descriptor_ring *ring);
struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite,
struct
mite_dma_descriptor_ring
@@ -279,8 +246,9 @@ enum MITE_IODWBSR_bits {
static inline unsigned MITE_IODWBSR_1_WSIZE_bits(unsigned size)
{
unsigned order = 0;
- while (size >>= 1)
- ++order;
+
+ BUG_ON(size == 0);
+ order = ilog2(size);
BUG_ON(order < 1);
return (order - 1) & 0x1f;
}
@@ -427,12 +395,10 @@ static inline int CR_RL(unsigned int retry_limit)
{
int value = 0;
- while (retry_limit) {
- retry_limit >>= 1;
- value++;
- }
+ if (retry_limit)
+ value = 1 + ilog2(retry_limit);
if (value > 0x7)
- printk("comedi: bug! retry_limit too large\n");
+ value = 0x7;
return (value & 0x7) << 21;
}
diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
index b928b6763cd5..f8b7faefc961 100644
--- a/drivers/staging/comedi/drivers/mpc624.c
+++ b/drivers/staging/comedi/drivers/mpc624.c
@@ -353,7 +353,7 @@ static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_DIFF;
s->n_chan = 8;
diff --git a/drivers/staging/comedi/drivers/mpc8260cpm.c b/drivers/staging/comedi/drivers/mpc8260cpm.c
index a7fda8f01e8c..c0c33299b7f1 100644
--- a/drivers/staging/comedi/drivers/mpc8260cpm.c
+++ b/drivers/staging/comedi/drivers/mpc8260cpm.c
@@ -137,7 +137,7 @@ static int mpc8260cpm_attach(struct comedi_device *dev,
return ret;
for (i = 0; i < 4; i++) {
- s = dev->subdevices + i;
+ s = &dev->subdevices[i];
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 32;
diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c
index eccbe1fb4f2c..4625cb4d07c6 100644
--- a/drivers/staging/comedi/drivers/multiq3.c
+++ b/drivers/staging/comedi/drivers/multiq3.c
@@ -204,8 +204,10 @@ static int multiq3_encoder_insn_read(struct comedi_device *dev,
static void encoder_reset(struct comedi_device *dev)
{
+ struct comedi_subdevice *s = &dev->subdevices[4];
int chan;
- for (chan = 0; chan < dev->subdevices[4].n_chan; chan++) {
+
+ for (chan = 0; chan < s->n_chan; chan++) {
int control =
MULTIQ3_CONTROL_MUST | MULTIQ3_AD_MUX_EN | (chan << 3);
outw(control, dev->iobase + MULTIQ3_CONTROL);
@@ -258,7 +260,7 @@ static int multiq3_attach(struct comedi_device *dev,
if (result < 0)
return result;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* ai subdevice */
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_GROUND;
@@ -267,7 +269,7 @@ static int multiq3_attach(struct comedi_device *dev,
s->maxdata = 0x1fff;
s->range_table = &range_bipolar5;
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* ao subdevice */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
@@ -277,7 +279,7 @@ static int multiq3_attach(struct comedi_device *dev,
s->maxdata = 0xfff;
s->range_table = &range_bipolar5;
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
/* di subdevice */
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
@@ -286,7 +288,7 @@ static int multiq3_attach(struct comedi_device *dev,
s->maxdata = 1;
s->range_table = &range_digital;
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
/* do subdevice */
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE;
@@ -296,7 +298,7 @@ static int multiq3_attach(struct comedi_device *dev,
s->range_table = &range_digital;
s->state = 0;
- s = dev->subdevices + 4;
+ s = &dev->subdevices[4];
/* encoder (counter) subdevice */
s->type = COMEDI_SUBD_COUNTER;
s->subdev_flags = SDF_READABLE | SDF_LSAMPL;
diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
index a80c52fb2731..51295f32ee89 100644
--- a/drivers/staging/comedi/drivers/ni_6527.c
+++ b/drivers/staging/comedi/drivers/ni_6527.c
@@ -44,8 +44,11 @@ Updated: Sat, 25 Jan 2003 13:24:40 -0800
#include <linux/interrupt.h>
#include "../comedidev.h"
+#include "comedi_fc.h"
#include "mite.h"
+#define DRIVER_NAME "ni_6527"
+
#define NI6527_DIO_SIZE 4096
#define NI6527_MITE_SIZE 4096
@@ -76,16 +79,6 @@ Updated: Sat, 25 Jan 2003 13:24:40 -0800
#define Rising_Edge_Detection_Enable(x) (0x018+(x))
#define Falling_Edge_Detection_Enable(x) (0x020+(x))
-static int ni6527_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static void ni6527_detach(struct comedi_device *dev);
-static struct comedi_driver driver_ni6527 = {
- .driver_name = "ni6527",
- .module = THIS_MODULE,
- .attach = ni6527_attach,
- .detach = ni6527_detach,
-};
-
struct ni6527_board {
int dev_id;
@@ -103,7 +96,6 @@ static const struct ni6527_board ni6527_boards[] = {
},
};
-#define n_ni6527_boards ARRAY_SIZE(ni6527_boards)
#define this_board ((const struct ni6527_board *)dev->board_ptr)
static DEFINE_PCI_DEVICE_TABLE(ni6527_pci_table) = {
@@ -122,8 +114,6 @@ struct ni6527_private {
#define devpriv ((struct ni6527_private *)dev->private)
-static int ni6527_find_device(struct comedi_device *dev, int bus, int slot);
-
static int ni6527_di_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
@@ -212,7 +202,7 @@ static int ni6527_do_insn_bits(struct comedi_device *dev,
static irqreturn_t ni6527_interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
- struct comedi_subdevice *s = dev->subdevices + 2;
+ struct comedi_subdevice *s = &dev->subdevices[2];
unsigned int status;
status = readb(devpriv->mite->daq_io_addr + Change_Status);
@@ -235,40 +225,20 @@ static int ni6527_intr_cmdtest(struct comedi_device *dev,
struct comedi_cmd *cmd)
{
int err = 0;
- int tmp;
-
- /* step 1: make sure trigger sources are trivially valid */
-
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_OTHER;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_FOLLOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_OTHER);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT);
if (err)
return 1;
- /* step 2: make sure trigger sources are unique and */
- /* are mutually compatible */
+ /* Step 2a : make sure trigger sources are unique */
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -364,36 +334,53 @@ static int ni6527_intr_insn_config(struct comedi_device *dev,
return 2;
}
-static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static const struct ni6527_board *
+ni6527_find_boardinfo(struct pci_dev *pcidev)
+{
+ unsigned int dev_id = pcidev->device;
+ unsigned int n;
+
+ for (n = 0; n < ARRAY_SIZE(ni6527_boards); n++) {
+ const struct ni6527_board *board = &ni6527_boards[n];
+ if (board->dev_id == dev_id)
+ return board;
+ }
+ return NULL;
+}
+
+static int __devinit ni6527_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
struct comedi_subdevice *s;
int ret;
- printk(KERN_INFO "comedi%d: ni6527\n", dev->minor);
-
ret = alloc_private(dev, sizeof(struct ni6527_private));
if (ret < 0)
return ret;
- ret = ni6527_find_device(dev, it->options[0], it->options[1]);
- if (ret < 0)
- return ret;
+ dev->board_ptr = ni6527_find_boardinfo(pcidev);
+ if (!dev->board_ptr)
+ return -ENODEV;
+
+ devpriv->mite = mite_alloc(pcidev);
+ if (!devpriv->mite)
+ return -ENOMEM;
ret = mite_setup(devpriv->mite);
if (ret < 0) {
- printk(KERN_ERR "comedi: error setting up mite\n");
+ dev_err(dev->class_dev, "error setting up mite\n");
return ret;
}
dev->board_name = this_board->name;
- printk(KERN_INFO "comedi board: %s, ID=0x%02x\n", dev->board_name,
- readb(devpriv->mite->daq_io_addr + ID_Register));
+ dev_info(dev->class_dev, "board: %s, ID=0x%02x\n", dev->board_name,
+ readb(devpriv->mite->daq_io_addr + ID_Register));
ret = comedi_alloc_subdevices(dev, 3);
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
s->n_chan = 24;
@@ -402,7 +389,7 @@ static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->insn_config = ni6527_di_insn_config;
s->insn_bits = ni6527_di_insn_bits;
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 24;
@@ -410,7 +397,7 @@ static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->maxdata = 1;
s->insn_bits = ni6527_do_insn_bits;
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
dev->read_subdev = s;
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
@@ -432,9 +419,9 @@ static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it)
writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control);
ret = request_irq(mite_irq(devpriv->mite), ni6527_interrupt,
- IRQF_SHARED, "ni6527", dev);
+ IRQF_SHARED, DRIVER_NAME, dev);
if (ret < 0)
- printk(KERN_WARNING "comedi i6527 irq not available\n");
+ dev_warn(dev->class_dev, "irq not available\n");
else
dev->irq = mite_irq(devpriv->mite);
@@ -448,73 +435,37 @@ static void ni6527_detach(struct comedi_device *dev)
devpriv->mite->daq_io_addr + Master_Interrupt_Control);
if (dev->irq)
free_irq(dev->irq, dev);
- if (devpriv && devpriv->mite)
+ if (devpriv && devpriv->mite) {
mite_unsetup(devpriv->mite);
-}
-
-static int ni6527_find_device(struct comedi_device *dev, int bus, int slot)
-{
- struct mite_struct *mite;
- int i;
-
- for (mite = mite_devices; mite; mite = mite->next) {
- if (mite->used)
- continue;
- if (bus || slot) {
- if (bus != mite->pcidev->bus->number ||
- slot != PCI_SLOT(mite->pcidev->devfn))
- continue;
- }
- for (i = 0; i < n_ni6527_boards; i++) {
- if (mite_device_id(mite) == ni6527_boards[i].dev_id) {
- dev->board_ptr = ni6527_boards + i;
- devpriv->mite = mite;
- return 0;
- }
- }
+ mite_free(devpriv->mite);
}
- printk(KERN_ERR "comedi 6527: no device found\n");
- mite_list_devices();
- return -EIO;
}
-static int __devinit driver_ni6527_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
+static struct comedi_driver ni6527_driver = {
+ .driver_name = DRIVER_NAME,
+ .module = THIS_MODULE,
+ .attach_pci = ni6527_attach_pci,
+ .detach = ni6527_detach,
+};
+
+static int __devinit ni6527_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, &driver_ni6527);
+ return comedi_pci_auto_config(dev, &ni6527_driver);
}
-static void __devexit driver_ni6527_pci_remove(struct pci_dev *dev)
+static void __devexit ni6527_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver driver_ni6527_pci_driver = {
+static struct pci_driver ni6527_pci_driver = {
+ .name = DRIVER_NAME,
.id_table = ni6527_pci_table,
- .probe = &driver_ni6527_pci_probe,
- .remove = __devexit_p(&driver_ni6527_pci_remove)
+ .probe = ni6527_pci_probe,
+ .remove = __devexit_p(ni6527_pci_remove)
};
-
-static int __init driver_ni6527_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_ni6527);
- if (retval < 0)
- return retval;
-
- driver_ni6527_pci_driver.name = (char *)driver_ni6527.driver_name;
- return pci_register_driver(&driver_ni6527_pci_driver);
-}
-
-static void __exit driver_ni6527_cleanup_module(void)
-{
- pci_unregister_driver(&driver_ni6527_pci_driver);
- comedi_driver_unregister(&driver_ni6527);
-}
-
-module_init(driver_ni6527_init_module);
-module_exit(driver_ni6527_cleanup_module);
+module_comedi_pci_driver(ni6527_driver, ni6527_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
index bce39f1ea36d..2a73ff57a2fb 100644
--- a/drivers/staging/comedi/drivers/ni_65xx.c
+++ b/drivers/staging/comedi/drivers/ni_65xx.c
@@ -55,6 +55,7 @@ except maybe the 6514.
#include <linux/slab.h>
#include "../comedidev.h"
+#include "comedi_fc.h"
#include "mite.h"
#define NI6514_DIO_SIZE 4096
@@ -109,18 +110,7 @@ static inline unsigned Filter_Enable(unsigned port)
#define OverflowIntEnable 0x02
#define EdgeIntEnable 0x01
-static int ni_65xx_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static void ni_65xx_detach(struct comedi_device *dev);
-static struct comedi_driver driver_ni_65xx = {
- .driver_name = "ni_65xx",
- .module = THIS_MODULE,
- .attach = ni_65xx_attach,
- .detach = ni_65xx_detach,
-};
-
struct ni_65xx_board {
-
int dev_id;
const char *name;
unsigned num_dio_ports;
@@ -325,8 +315,6 @@ static struct ni_65xx_subdevice_private *ni_65xx_alloc_subdevice_private(void)
return subdev_private;
}
-static int ni_65xx_find_device(struct comedi_device *dev, int bus, int slot);
-
static int ni_65xx_config_filter(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
@@ -453,11 +441,9 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
writeb(bits,
private(dev)->mite->daq_io_addr +
Port_Data(port));
-/* printk("wrote 0x%x to port %i\n", bits, port); */
}
port_read_bits =
readb(private(dev)->mite->daq_io_addr + Port_Data(port));
-/* printk("read 0x%x from port %i\n", port_read_bits, port); */
if (s->type == COMEDI_SUBD_DO && board(dev)->invert_outputs) {
/* Outputs inverted, so invert value read back from
* DO subdevice. (Does not apply to boards with DIO
@@ -478,7 +464,7 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
static irqreturn_t ni_65xx_interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
- struct comedi_subdevice *s = dev->subdevices + 2;
+ struct comedi_subdevice *s = &dev->subdevices[2];
unsigned int status;
status = readb(private(dev)->mite->daq_io_addr + Change_Status);
@@ -501,40 +487,20 @@ static int ni_65xx_intr_cmdtest(struct comedi_device *dev,
struct comedi_cmd *cmd)
{
int err = 0;
- int tmp;
-
- /* step 1: make sure trigger sources are trivially valid */
-
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_OTHER;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_FOLLOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_OTHER);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT);
if (err)
return 1;
- /* step 2: make sure trigger sources are unique and mutually
- compatible */
+ /* Step 2a : make sure trigger sources are unique */
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -644,41 +610,55 @@ static int ni_65xx_intr_insn_config(struct comedi_device *dev,
return 2;
}
-static int ni_65xx_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static const struct ni_65xx_board *
+ni_65xx_find_boardinfo(struct pci_dev *pcidev)
+{
+ unsigned int dev_id = pcidev->device;
+ unsigned int n;
+
+ for (n = 0; n < ARRAY_SIZE(ni_65xx_boards); n++) {
+ const struct ni_65xx_board *board = &ni_65xx_boards[n];
+ if (board->dev_id == dev_id)
+ return board;
+ }
+ return NULL;
+}
+
+static int __devinit ni_65xx_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
struct comedi_subdevice *s;
unsigned i;
int ret;
- printk(KERN_INFO "comedi%d: ni_65xx:", dev->minor);
-
ret = alloc_private(dev, sizeof(struct ni_65xx_private));
if (ret < 0)
return ret;
- ret = ni_65xx_find_device(dev, it->options[0], it->options[1]);
- if (ret < 0)
- return ret;
+ dev->board_ptr = ni_65xx_find_boardinfo(pcidev);
+ if (!dev->board_ptr)
+ return -ENODEV;
+
+ private(dev)->mite = mite_alloc(pcidev);
+ if (!private(dev)->mite)
+ return -ENOMEM;
ret = mite_setup(private(dev)->mite);
if (ret < 0) {
- printk(KERN_WARNING "error setting up mite\n");
+ dev_warn(dev->class_dev, "error setting up mite\n");
return ret;
}
dev->board_name = board(dev)->name;
dev->irq = mite_irq(private(dev)->mite);
- printk(KERN_INFO " %s", dev->board_name);
-
- printk(KERN_INFO " ID=0x%02x",
+ dev_info(dev->class_dev, "board: %s, ID=0x%02x", dev->board_name,
readb(private(dev)->mite->daq_io_addr + ID_Register));
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
if (board(dev)->num_di_ports) {
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
@@ -696,7 +676,7 @@ static int ni_65xx_attach(struct comedi_device *dev,
s->type = COMEDI_SUBD_UNUSED;
}
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
if (board(dev)->num_do_ports) {
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
@@ -713,7 +693,7 @@ static int ni_65xx_attach(struct comedi_device *dev,
s->type = COMEDI_SUBD_UNUSED;
}
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
if (board(dev)->num_dio_ports) {
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
@@ -737,7 +717,7 @@ static int ni_65xx_attach(struct comedi_device *dev,
s->type = COMEDI_SUBD_UNUSED;
}
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
dev->read_subdev = s;
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
@@ -772,11 +752,9 @@ static int ni_65xx_attach(struct comedi_device *dev,
"ni_65xx", dev);
if (ret < 0) {
dev->irq = 0;
- printk(KERN_WARNING " irq not available");
+ dev_warn(dev->class_dev, "irq not available\n");
}
- printk("\n");
-
return 0;
}
@@ -791,79 +769,46 @@ static void ni_65xx_detach(struct comedi_device *dev)
if (dev->irq)
free_irq(dev->irq, dev);
if (private(dev)) {
+ struct comedi_subdevice *s;
unsigned i;
+
for (i = 0; i < dev->n_subdevices; ++i) {
- kfree(dev->subdevices[i].private);
- dev->subdevices[i].private = NULL;
+ s = &dev->subdevices[i];
+ kfree(s->private);
+ s->private = NULL;
}
- if (private(dev)->mite)
+ if (private(dev)->mite) {
mite_unsetup(private(dev)->mite);
- }
-}
-
-static int ni_65xx_find_device(struct comedi_device *dev, int bus, int slot)
-{
- struct mite_struct *mite;
- int i;
-
- for (mite = mite_devices; mite; mite = mite->next) {
- if (mite->used)
- continue;
- if (bus || slot) {
- if (bus != mite->pcidev->bus->number ||
- slot != PCI_SLOT(mite->pcidev->devfn))
- continue;
- }
- for (i = 0; i < n_ni_65xx_boards; i++) {
- if (mite_device_id(mite) == ni_65xx_boards[i].dev_id) {
- dev->board_ptr = ni_65xx_boards + i;
- private(dev)->mite = mite;
- return 0;
- }
+ mite_free(private(dev)->mite);
}
}
- printk(KERN_WARNING "no device found\n");
- mite_list_devices();
- return -EIO;
}
-static int __devinit driver_ni_65xx_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
+static struct comedi_driver ni_65xx_driver = {
+ .driver_name = "ni_65xx",
+ .module = THIS_MODULE,
+ .attach_pci = ni_65xx_attach_pci,
+ .detach = ni_65xx_detach,
+};
+
+static int __devinit ni_65xx_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, &driver_ni_65xx);
+ return comedi_pci_auto_config(dev, &ni_65xx_driver);
}
-static void __devexit driver_ni_65xx_pci_remove(struct pci_dev *dev)
+static void __devexit ni_65xx_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver driver_ni_65xx_pci_driver = {
+static struct pci_driver ni_65xx_pci_driver = {
+ .name = "ni_65xx",
.id_table = ni_65xx_pci_table,
- .probe = &driver_ni_65xx_pci_probe,
- .remove = __devexit_p(&driver_ni_65xx_pci_remove)
+ .probe = ni_65xx_pci_probe,
+ .remove = __devexit_p(ni_65xx_pci_remove)
};
-
-static int __init driver_ni_65xx_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_ni_65xx);
- if (retval < 0)
- return retval;
-
- driver_ni_65xx_pci_driver.name = (char *)driver_ni_65xx.driver_name;
- return pci_register_driver(&driver_ni_65xx_pci_driver);
-}
-
-static void __exit driver_ni_65xx_cleanup_module(void)
-{
- pci_unregister_driver(&driver_ni_65xx_pci_driver);
- comedi_driver_unregister(&driver_ni_65xx);
-}
-
-module_init(driver_ni_65xx_init_module);
-module_exit(driver_ni_65xx_cleanup_module);
+module_comedi_pci_driver(ni_65xx_driver, ni_65xx_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
index 5e863ff343dd..df2f3b0bab48 100644
--- a/drivers/staging/comedi/drivers/ni_660x.c
+++ b/drivers/staging/comedi/drivers/ni_660x.c
@@ -448,68 +448,46 @@ static inline struct ni_660x_private *private(struct comedi_device *dev)
return dev->private;
}
-/* initialized in ni_660x_find_device() */
+/* initialized in ni_660x_attach_pci() */
static inline const struct ni_660x_board *board(struct comedi_device *dev)
{
return dev->board_ptr;
}
-#define n_ni_660x_boards ARRAY_SIZE(ni_660x_boards)
-
-static int ni_660x_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
+static int ni_660x_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev);
static void ni_660x_detach(struct comedi_device *dev);
static void init_tio_chip(struct comedi_device *dev, int chipset);
static void ni_660x_select_pfi_output(struct comedi_device *dev,
unsigned pfi_channel,
unsigned output_select);
-static struct comedi_driver driver_ni_660x = {
+static struct comedi_driver ni_660x_driver = {
.driver_name = "ni_660x",
.module = THIS_MODULE,
- .attach = ni_660x_attach,
+ .attach_pci = ni_660x_attach_pci,
.detach = ni_660x_detach,
};
-static int __devinit driver_ni_660x_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
+static int __devinit ni_660x_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, &driver_ni_660x);
+ return comedi_pci_auto_config(dev, &ni_660x_driver);
}
-static void __devexit driver_ni_660x_pci_remove(struct pci_dev *dev)
+static void __devexit ni_660x_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver driver_ni_660x_pci_driver = {
+static struct pci_driver ni_660x_pci_driver = {
+ .name = "ni_660x",
.id_table = ni_660x_pci_table,
- .probe = &driver_ni_660x_pci_probe,
- .remove = __devexit_p(&driver_ni_660x_pci_remove)
+ .probe = ni_660x_pci_probe,
+ .remove = __devexit_p(ni_660x_pci_remove)
};
+module_comedi_pci_driver(ni_660x_driver, ni_660x_pci_driver);
-static int __init driver_ni_660x_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_ni_660x);
- if (retval < 0)
- return retval;
-
- driver_ni_660x_pci_driver.name = (char *)driver_ni_660x.driver_name;
- return pci_register_driver(&driver_ni_660x_pci_driver);
-}
-
-static void __exit driver_ni_660x_cleanup_module(void)
-{
- pci_unregister_driver(&driver_ni_660x_pci_driver);
- comedi_driver_unregister(&driver_ni_660x);
-}
-
-module_init(driver_ni_660x_init_module);
-module_exit(driver_ni_660x_cleanup_module);
-
-static int ni_660x_find_device(struct comedi_device *dev, int bus, int slot);
static int ni_660x_set_pfi_routing(struct comedi_device *dev, unsigned chan,
unsigned source);
@@ -748,8 +726,6 @@ static enum NI_660x_Register ni_gpct_to_660x_register(enum ni_gpct_register reg)
ni_660x_register = G3InterruptEnable;
break;
default:
- printk(KERN_WARNING "%s: unhandled register 0x%x in switch.\n",
- __func__, reg);
BUG();
return 0;
break;
@@ -773,8 +749,6 @@ static inline void ni_660x_write_register(struct comedi_device *dev,
writel(bits, write_address);
break;
default:
- printk(KERN_WARNING "%s: %s: bug! unhandled case (reg=0x%x) in switch.\n",
- __FILE__, __func__, reg);
BUG();
break;
}
@@ -796,8 +770,6 @@ static inline unsigned ni_660x_read_register(struct comedi_device *dev,
return readl(read_address);
break;
default:
- printk(KERN_WARNING "%s: %s: bug! unhandled case (reg=0x%x) in switch.\n",
- __FILE__, __func__, reg);
BUG();
break;
}
@@ -893,8 +865,8 @@ static int ni_660x_request_mite_channel(struct comedi_device *dev,
return 0;
}
-void ni_660x_release_mite_channel(struct comedi_device *dev,
- struct ni_gpct *counter)
+static void ni_660x_release_mite_channel(struct comedi_device *dev,
+ struct ni_gpct *counter)
{
unsigned long flags;
@@ -985,7 +957,7 @@ static irqreturn_t ni_660x_interrupt(int irq, void *d)
spin_lock_irqsave(&private(dev)->interrupt_lock, flags);
smp_mb();
for (i = 0; i < ni_660x_num_counters(dev); ++i) {
- s = dev->subdevices + NI_660X_GPCT_SUBDEV(i);
+ s = &dev->subdevices[NI_660X_GPCT_SUBDEV(i)];
ni_660x_handle_gpct_interrupt(dev, s);
}
spin_unlock_irqrestore(&private(dev)->interrupt_lock, flags);
@@ -1062,28 +1034,43 @@ static void ni_660x_free_mite_rings(struct comedi_device *dev)
}
}
-static int ni_660x_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static const struct ni_660x_board *
+ni_660x_find_boardinfo(struct pci_dev *pcidev)
+{
+ unsigned int dev_id = pcidev->device;
+ unsigned int n;
+
+ for (n = 0; n < ARRAY_SIZE(ni_660x_boards); n++) {
+ const struct ni_660x_board *board = &ni_660x_boards[n];
+ if (board->dev_id == dev_id)
+ return board;
+ }
+ return NULL;
+}
+
+static int __devinit ni_660x_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
struct comedi_subdevice *s;
int ret;
unsigned i;
unsigned global_interrupt_config_bits;
- printk(KERN_INFO "comedi%d: ni_660x: ", dev->minor);
-
ret = ni_660x_allocate_private(dev);
if (ret < 0)
return ret;
- ret = ni_660x_find_device(dev, it->options[0], it->options[1]);
- if (ret < 0)
- return ret;
+ dev->board_ptr = ni_660x_find_boardinfo(pcidev);
+ if (!dev->board_ptr)
+ return -ENODEV;
+ private(dev)->mite = mite_alloc(pcidev);
+ if (!private(dev)->mite)
+ return -ENOMEM;
dev->board_name = board(dev)->name;
ret = mite_setup2(private(dev)->mite, 1);
if (ret < 0) {
- printk(KERN_WARNING "error setting up mite\n");
+ dev_warn(dev->class_dev, "error setting up mite\n");
return ret;
}
comedi_set_hw_dev(dev, &private(dev)->mite->pcidev->dev);
@@ -1091,17 +1078,15 @@ static int ni_660x_attach(struct comedi_device *dev,
if (ret < 0)
return ret;
- printk(KERN_INFO " %s ", dev->board_name);
-
ret = comedi_alloc_subdevices(dev, 2 + NI_660X_MAX_NUM_COUNTERS);
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* Old GENERAL-PURPOSE COUNTER/TIME (GPCT) subdevice, no longer used */
s->type = COMEDI_SUBD_UNUSED;
- s = dev->subdevices + NI_660X_DIO_SUBDEV;
+ s = &dev->subdevices[NI_660X_DIO_SUBDEV];
/* DIGITAL I/O SUBDEVICE */
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
@@ -1124,7 +1109,7 @@ static int ni_660x_attach(struct comedi_device *dev,
if (private(dev)->counter_dev == NULL)
return -ENOMEM;
for (i = 0; i < NI_660X_MAX_NUM_COUNTERS; ++i) {
- s = dev->subdevices + NI_660X_GPCT_SUBDEV(i);
+ s = &dev->subdevices[NI_660X_GPCT_SUBDEV(i)];
if (i < ni_660x_num_counters(dev)) {
s->type = COMEDI_SUBD_COUNTER;
s->subdev_flags =
@@ -1174,7 +1159,7 @@ static int ni_660x_attach(struct comedi_device *dev,
ret = request_irq(mite_irq(private(dev)->mite), ni_660x_interrupt,
IRQF_SHARED, "ni_660x", dev);
if (ret < 0) {
- printk(KERN_WARNING " irq not available\n");
+ dev_warn(dev->class_dev, " irq not available\n");
return ret;
}
dev->irq = mite_irq(private(dev)->mite);
@@ -1183,7 +1168,7 @@ static int ni_660x_attach(struct comedi_device *dev,
global_interrupt_config_bits |= Cascade_Int_Enable_Bit;
ni_660x_write_register(dev, 0, global_interrupt_config_bits,
GlobalInterruptConfigRegister);
- printk(KERN_INFO "attached\n");
+ dev_info(dev->class_dev, "ni_660x: %s attached\n", dev->board_name);
return 0;
}
@@ -1197,6 +1182,7 @@ static void ni_660x_detach(struct comedi_device *dev)
if (private(dev)->mite) {
ni_660x_free_mite_rings(dev);
mite_unsetup(private(dev)->mite);
+ mite_free(private(dev)->mite);
}
}
}
@@ -1240,33 +1226,6 @@ static int ni_660x_GPCT_winsn(struct comedi_device *dev,
return ni_tio_winsn(subdev_to_counter(s), insn, data);
}
-static int ni_660x_find_device(struct comedi_device *dev, int bus, int slot)
-{
- struct mite_struct *mite;
- int i;
-
- for (mite = mite_devices; mite; mite = mite->next) {
- if (mite->used)
- continue;
- if (bus || slot) {
- if (bus != mite->pcidev->bus->number ||
- slot != PCI_SLOT(mite->pcidev->devfn))
- continue;
- }
-
- for (i = 0; i < n_ni_660x_boards; i++) {
- if (mite_device_id(mite) == ni_660x_boards[i].dev_id) {
- dev->board_ptr = ni_660x_boards + i;
- private(dev)->mite = mite;
- return 0;
- }
- }
- }
- printk(KERN_WARNING "no device found\n");
- mite_list_devices();
- return -EIO;
-}
-
static int ni_660x_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
index 9c57618f2c5b..eac6dc047bb0 100644
--- a/drivers/staging/comedi/drivers/ni_670x.c
+++ b/drivers/staging/comedi/drivers/ni_670x.c
@@ -187,37 +187,22 @@ static int ni_670x_dio_insn_config(struct comedi_device *dev,
return insn->n;
}
-static int ni_670x_find_device(struct comedi_device *dev, int bus, int slot)
+static const struct ni_670x_board *
+ni_670x_find_boardinfo(struct pci_dev *pcidev)
{
- struct ni_670x_private *devpriv = dev->private;
- struct mite_struct *mite;
- int i;
-
- for (mite = mite_devices; mite; mite = mite->next) {
- if (mite->used)
- continue;
- if (bus || slot) {
- if (bus != mite->pcidev->bus->number
- || slot != PCI_SLOT(mite->pcidev->devfn))
- continue;
- }
-
- for (i = 0; i < ARRAY_SIZE(ni_670x_boards); i++) {
- if (mite_device_id(mite) == ni_670x_boards[i].dev_id) {
- dev->board_ptr = ni_670x_boards + i;
- devpriv->mite = mite;
+ unsigned int dev_id = pcidev->device;
+ unsigned int n;
- return 0;
- }
- }
+ for (n = 0; n < ARRAY_SIZE(ni_670x_boards); n++) {
+ const struct ni_670x_board *board = &ni_670x_boards[n];
+ if (board->dev_id == dev_id)
+ return board;
}
- dev_warn(dev->class_dev, "no device found\n");
- mite_list_devices();
- return -EIO;
+ return NULL;
}
-static int ni_670x_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int __devinit ni_670x_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
const struct ni_670x_board *thisboard;
struct ni_670x_private *devpriv;
@@ -229,10 +214,12 @@ static int ni_670x_attach(struct comedi_device *dev,
if (ret < 0)
return ret;
devpriv = dev->private;
-
- ret = ni_670x_find_device(dev, it->options[0], it->options[1]);
- if (ret < 0)
- return ret;
+ dev->board_ptr = ni_670x_find_boardinfo(pcidev);
+ if (!dev->board_ptr)
+ return -ENODEV;
+ devpriv->mite = mite_alloc(pcidev);
+ if (!devpriv->mite)
+ return -ENOMEM;
thisboard = comedi_board(dev);
ret = mite_setup(devpriv->mite);
@@ -241,13 +228,12 @@ static int ni_670x_attach(struct comedi_device *dev,
return ret;
}
dev->board_name = thisboard->name;
- dev->irq = mite_irq(devpriv->mite);
ret = comedi_alloc_subdevices(dev, 2);
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* analog output subdevice */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
@@ -271,7 +257,7 @@ static int ni_670x_attach(struct comedi_device *dev,
s->insn_write = &ni_670x_ao_winsn;
s->insn_read = &ni_670x_ao_rinsn;
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* digital i/o subdevice */
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
@@ -298,20 +284,20 @@ static void ni_670x_detach(struct comedi_device *dev)
struct comedi_subdevice *s;
if (dev->n_subdevices) {
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
if (s)
kfree(s->range_table_list);
}
- if (devpriv && devpriv->mite)
+ if (devpriv && devpriv->mite) {
mite_unsetup(devpriv->mite);
- if (dev->irq)
- free_irq(dev->irq, dev);
+ mite_free(devpriv->mite);
+ }
}
static struct comedi_driver ni_670x_driver = {
.driver_name = "ni_670x",
.module = THIS_MODULE,
- .attach = ni_670x_attach,
+ .attach_pci = ni_670x_attach_pci,
.detach = ni_670x_detach,
};
diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
index b53a4286f8cb..83950807b672 100644
--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
+++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
@@ -321,45 +321,23 @@ static int a2150_ai_cmdtest(struct comedi_device *dev,
int startChan;
int i;
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_EXT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_NOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
+ 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 2: make sure trigger sources are unique and mutually
- * compatible
- */
+ /* Step 2a : make sure trigger sources are unique */
- if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
- err++;
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -832,7 +810,7 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return ret;
/* analog input subdevice */
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
dev->read_subdev = s;
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_OTHER | SDF_CMD_READ;
diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
index 62c8c44a8d28..93938cec93e7 100644
--- a/drivers/staging/comedi/drivers/ni_at_ao.c
+++ b/drivers/staging/comedi/drivers/ni_at_ao.c
@@ -358,7 +358,7 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* analog output subdevice */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
@@ -371,7 +371,7 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->insn_write = &atao_ao_winsn;
s->insn_read = &atao_ao_rinsn;
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* digital i/o subdevice */
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
@@ -381,7 +381,7 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->insn_bits = atao_dio_insn_bits;
s->insn_config = atao_dio_insn_config;
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
/* caldac subdevice */
s->type = COMEDI_SUBD_CALIB;
s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL;
@@ -390,7 +390,7 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->insn_read = atao_calib_insn_read;
s->insn_write = atao_calib_insn_write;
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
/* eeprom subdevice */
/* s->type=COMEDI_SUBD_EEPROM; */
s->type = COMEDI_SUBD_UNUSED;
diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c
index 6448373878ed..cac25572f6bb 100644
--- a/drivers/staging/comedi/drivers/ni_atmio.c
+++ b/drivers/staging/comedi/drivers/ni_atmio.c
@@ -489,7 +489,7 @@ static int ni_atmio_attach(struct comedi_device *dev,
/* generic E series stuff in ni_mio_common.c */
- ret = ni_E_init(dev, it);
+ ret = ni_E_init(dev);
if (ret < 0)
return ret;
diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
index 2c78d3dd242a..e91a620f9db3 100644
--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
+++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
@@ -40,6 +40,7 @@ Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d)
#include <linux/ioport.h>
+#include "comedi_fc.h"
#include "8255.h"
/* Configuration and Status Registers */
@@ -234,7 +235,7 @@ static void reset_atmio16d(struct comedi_device *dev)
static irqreturn_t atmio16d_interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
- struct comedi_subdevice *s = dev->subdevices + 0;
+ struct comedi_subdevice *s = &dev->subdevices[0];
comedi_buf_put(s->async, inw(dev->iobase + AD_FIFO_REG));
@@ -246,45 +247,26 @@ static int atmio16d_ai_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{
- int err = 0, tmp;
+ int err = 0;
- /* make sure triggers are valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_FOLLOW | TRIG_TIMER);
+ 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 2: make sure trigger sources are unique & mutually compatible */
- /* note that mutual compatibility is not an issue here */
- if (cmd->scan_begin_src != TRIG_FOLLOW &&
- cmd->scan_begin_src != TRIG_EXT &&
- cmd->scan_begin_src != TRIG_TIMER)
- err++;
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ /* Step 2a : make sure trigger sources are unique */
+
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -724,7 +706,7 @@ static int atmio16d_attach(struct comedi_device *dev,
devpriv->dac1_coding = it->options[12];
/* setup sub-devices */
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
dev->read_subdev = s;
/* ai subdevice */
s->type = COMEDI_SUBD_AI;
@@ -749,7 +731,7 @@ static int atmio16d_attach(struct comedi_device *dev,
}
/* ao subdevice */
- s++;
+ s = &dev->subdevices[1];
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
s->n_chan = 2;
@@ -775,7 +757,7 @@ static int atmio16d_attach(struct comedi_device *dev,
}
/* Digital I/O */
- s++;
+ s = &dev->subdevices[2];
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
s->n_chan = 8;
@@ -785,7 +767,7 @@ static int atmio16d_attach(struct comedi_device *dev,
s->range_table = &range_digital;
/* 8255 subdevice */
- s++;
+ s = &dev->subdevices[3];
if (board->has_8255)
subdev_8255_init(dev, s, NULL, dev->iobase);
else
@@ -793,7 +775,7 @@ static int atmio16d_attach(struct comedi_device *dev,
/* don't yet know how to deal with counter/timers */
#if 0
- s++;
+ s = &dev->subdevices[4];
/* do */
s->type = COMEDI_SUBD_TIMER;
s->n_chan = 0;
@@ -807,9 +789,12 @@ static int atmio16d_attach(struct comedi_device *dev,
static void atmio16d_detach(struct comedi_device *dev)
{
const struct atmio16_board_t *board = comedi_board(dev);
+ struct comedi_subdevice *s;
- if (dev->subdevices && board->has_8255)
- subdev_8255_cleanup(dev, dev->subdevices + 3);
+ if (dev->subdevices && board->has_8255) {
+ s = &dev->subdevices[3];
+ subdev_8255_cleanup(dev, s);
+ }
if (dev->irq)
free_irq(dev->irq, dev);
reset_atmio16d(dev);
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index 83016b411851..2ba0ade45c64 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -1,6 +1,6 @@
/*
* comedi/drivers/ni_daq_700.c
- * Driver for DAQCard-700 DIO only
+ * Driver for DAQCard-700 DIO/AI
* copied from 8255
*
* COMEDI - Linux Control and Measurement Device Interface
@@ -29,14 +29,25 @@ Author: Fred Brooks <nsaspook@nsaspook.com>,
based on ni_daq_dio24 by Daniel Vecino Castel <dvecino@able.es>
Devices: [National Instruments] PCMCIA DAQ-Card-700 (ni_daq_700)
Status: works
-Updated: Thu, 21 Feb 2008 12:07:20 +0000
+Updated: Wed, 19 Sep 2012 12:07:20 +0000
-The daqcard-700 appears in Comedi as a single digital I/O subdevice with
-16 channels. The channel 0 corresponds to the daqcard-700's output
+The daqcard-700 appears in Comedi as a digital I/O subdevice (0) with
+16 channels and a analog input subdevice (1) with 16 single-ended channels.
+
+Digital: The channel 0 corresponds to the daqcard-700's output
port, bit 0; channel 8 corresponds to the input port, bit 0.
-Direction configuration: channels 0-7 output, 8-15 input (8225 device
+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
+IRQ is assigned but not used.
+
+Version 0.1 Original DIO only driver
+Version 0.2 DIO and basic AI analog input support on 16 se channels
+
+Manuals: Register level: http://www.ni.com/pdf/manuals/340698.pdf
+ User Manual: http://www.ni.com/pdf/manuals/320676d.pdf
*/
#include <linux/interrupt.h>
@@ -51,16 +62,29 @@ emu as port A output, port B input, port C N/A).
static struct pcmcia_device *pcmcia_cur_dev;
-struct dio700_board {
+struct daq700_board {
const char *name;
};
-#define DIO_W 0x04
-#define DIO_R 0x05
-
-static int subdev_700_insn(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data)
+/* daqcard700 registers */
+#define DIO_W 0x04 /* WO 8bit */
+#define DIO_R 0x05 /* RO 8bit */
+#define CMD_R1 0x00 /* WO 8bit */
+#define CMD_R2 0x07 /* RW 8bit */
+#define CMD_R3 0x05 /* W0 8bit */
+#define STA_R1 0x00 /* RO 8bit */
+#define STA_R2 0x01 /* RO 8bit */
+#define ADFIFO_R 0x02 /* RO 16bit */
+#define ADCLEAR_R 0x01 /* WO 8bit */
+#define CDA_R0 0x08 /* RW 8bit */
+#define CDA_R1 0x09 /* RW 8bit */
+#define CDA_R2 0x0A /* RW 8bit */
+#define CMO_R 0x0B /* RO 8bit */
+#define TIC_R 0x06 /* WO 8bit */
+
+static int daq700_dio_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
{
if (data[0]) {
s->state &= ~data[0];
@@ -76,7 +100,7 @@ static int subdev_700_insn(struct comedi_device *dev,
return insn->n;
}
-static int subdev_700_insn_config(struct comedi_device *dev,
+static int daq700_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
@@ -97,9 +121,90 @@ static int subdev_700_insn_config(struct comedi_device *dev,
return insn->n;
}
-static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int daq700_ai_rinsn(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
{
- const struct dio700_board *thisboard = comedi_board(dev);
+ int n, i, chan;
+ int d;
+ unsigned int status;
+ enum { TIMEOUT = 100 };
+
+ chan = CR_CHAN(insn->chanspec);
+ /* write channel to multiplexer */
+ /* set mask scan bit high to disable scanning */
+ outb(chan | 0x80, dev->iobase + CMD_R1);
+
+ /* convert n samples */
+ for (n = 0; n < insn->n; n++) {
+ /* trigger conversion with out0 L to H */
+ outb(0x00, dev->iobase + CMD_R2); /* enable ADC conversions */
+ outb(0x30, dev->iobase + CMO_R); /* mode 0 out0 L, from H */
+ /* mode 1 out0 H, L to H, start conversion */
+ outb(0x32, dev->iobase + CMO_R);
+ /* wait for conversion to end */
+ for (i = 0; i < TIMEOUT; i++) {
+ status = inb(dev->iobase + STA_R2);
+ if ((status & 0x03) != 0) {
+ dev_info(dev->class_dev,
+ "Overflow/run Error\n");
+ return -EOVERFLOW;
+ }
+ status = inb(dev->iobase + STA_R1);
+ if ((status & 0x02) != 0) {
+ dev_info(dev->class_dev, "Data Error\n");
+ return -ENODATA;
+ }
+ if ((status & 0x11) == 0x01) {
+ /* ADC conversion complete */
+ break;
+ }
+ udelay(1);
+ }
+ if (i == TIMEOUT) {
+ dev_info(dev->class_dev,
+ "timeout during ADC conversion\n");
+ return -ETIMEDOUT;
+ }
+ /* read data */
+ d = inw(dev->iobase + ADFIFO_R);
+ /* mangle the data as necessary */
+ /* Bipolar Offset Binary: 0 to 4095 for -10 to +10 */
+ d &= 0x0fff;
+ d ^= 0x0800;
+ data[n] = d;
+ }
+ return n;
+}
+
+/*
+ * Data acquisition is enabled.
+ * The counter 0 output is high.
+ * The I/O connector pin CLK1 drives counter 1 source.
+ * Multiple-channel scanning is disabled.
+ * All interrupts are disabled.
+ * The analog input range is set to +-10 V
+ * The analog input mode is single-ended.
+ * The analog input circuitry is initialized to channel 0.
+ * The A/D FIFO is cleared.
+ */
+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 */
+ outb(0x00, iobase + CMD_R2); /* clear all bits */
+ outb(0x00, iobase + CMD_R3); /* set +-10 range */
+ outb(0x32, iobase + CMO_R); /* config counter mode1, out0 to H */
+ outb(0x00, iobase + TIC_R); /* clear counter interrupt */
+ outb(0x00, iobase + ADCLEAR_R); /* clear the ADC FIFO */
+ inw(iobase + ADFIFO_R); /* read 16bit junk from FIFO to clear */
+}
+
+static int daq700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+{
+ const struct daq700_board *thisboard = comedi_board(dev);
struct comedi_subdevice *s;
struct pcmcia_device *link;
int ret;
@@ -116,23 +221,33 @@ static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
dev->board_name = thisboard->name;
- ret = comedi_alloc_subdevices(dev, 1);
+ ret = comedi_alloc_subdevices(dev, 2);
if (ret)
return ret;
/* DAQCard-700 dio */
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 16;
s->range_table = &range_digital;
s->maxdata = 1;
- s->insn_bits = subdev_700_insn;
- s->insn_config = subdev_700_insn_config;
-
+ s->insn_bits = daq700_dio_insn_bits;
+ s->insn_config = daq700_dio_insn_config;
s->state = 0;
s->io_bits = 0x00ff;
+ /* DAQCard-700 ai */
+ s = &dev->subdevices[1];
+ s->type = COMEDI_SUBD_AI;
+ /* we support single-ended (ground) */
+ s->subdev_flags = SDF_READABLE | SDF_GROUND;
+ s->n_chan = 16;
+ s->maxdata = (1 << 12) - 1;
+ s->range_table = &range_bipolar10;
+ s->insn_read = daq700_ai_rinsn;
+ daq700_ai_config(dev, s);
+
dev_info(dev->class_dev, "%s: %s, io 0x%lx\n",
dev->driver->driver_name,
dev->board_name,
@@ -141,12 +256,12 @@ static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-static void dio700_detach(struct comedi_device *dev)
+static void daq700_detach(struct comedi_device *dev)
{
/* nothing to cleanup */
}
-static const struct dio700_board dio700_boards[] = {
+static const struct daq700_board daq700_boards[] = {
{
.name = "daqcard-700",
}, {
@@ -154,17 +269,17 @@ static const struct dio700_board dio700_boards[] = {
},
};
-static struct comedi_driver driver_dio700 = {
+static struct comedi_driver daq700_driver = {
.driver_name = "ni_daq_700",
.module = THIS_MODULE,
- .attach = dio700_attach,
- .detach = dio700_detach,
- .board_name = &dio700_boards[0].name,
- .num_names = ARRAY_SIZE(dio700_boards),
- .offset = sizeof(struct dio700_board),
+ .attach = daq700_attach,
+ .detach = daq700_detach,
+ .board_name = &daq700_boards[0].name,
+ .num_names = ARRAY_SIZE(daq700_boards),
+ .offset = sizeof(struct daq700_board),
};
-static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev,
+static int daq700_pcmcia_config_loop(struct pcmcia_device *p_dev,
void *priv_data)
{
if (p_dev->config_index == 0)
@@ -173,14 +288,14 @@ static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev,
return pcmcia_request_io(p_dev);
}
-static int dio700_cs_attach(struct pcmcia_device *link)
+static int daq700_cs_attach(struct pcmcia_device *link)
{
int ret;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO |
CONF_AUTO_SET_IO;
- ret = pcmcia_loop_config(link, dio700_pcmcia_config_loop, NULL);
+ ret = pcmcia_loop_config(link, daq700_pcmcia_config_loop, NULL);
if (ret)
goto failed;
@@ -199,52 +314,53 @@ failed:
return ret;
}
-static void dio700_cs_detach(struct pcmcia_device *link)
+static void daq700_cs_detach(struct pcmcia_device *link)
{
pcmcia_disable_device(link);
pcmcia_cur_dev = NULL;
}
-static const struct pcmcia_device_id dio700_cs_ids[] = {
+static const struct pcmcia_device_id daq700_cs_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x010b, 0x4743),
PCMCIA_DEVICE_NULL
};
-MODULE_DEVICE_TABLE(pcmcia, dio700_cs_ids);
+MODULE_DEVICE_TABLE(pcmcia, daq700_cs_ids);
-static struct pcmcia_driver dio700_cs_driver = {
+static struct pcmcia_driver daq700_cs_driver = {
.name = "ni_daq_700",
.owner = THIS_MODULE,
- .probe = dio700_cs_attach,
- .remove = dio700_cs_detach,
- .id_table = dio700_cs_ids,
+ .probe = daq700_cs_attach,
+ .remove = daq700_cs_detach,
+ .id_table = daq700_cs_ids,
};
-static int __init dio700_cs_init(void)
+static int __init daq700_cs_init(void)
{
int ret;
- ret = comedi_driver_register(&driver_dio700);
+ ret = comedi_driver_register(&daq700_driver);
if (ret < 0)
return ret;
- ret = pcmcia_register_driver(&dio700_cs_driver);
+ ret = pcmcia_register_driver(&daq700_cs_driver);
if (ret < 0) {
- comedi_driver_unregister(&driver_dio700);
+ comedi_driver_unregister(&daq700_driver);
return ret;
}
return 0;
}
-module_init(dio700_cs_init);
+module_init(daq700_cs_init);
-static void __exit dio700_cs_exit(void)
+static void __exit daq700_cs_exit(void)
{
- pcmcia_unregister_driver(&dio700_cs_driver);
- comedi_driver_unregister(&driver_dio700);
+ pcmcia_unregister_driver(&daq700_cs_driver);
+ comedi_driver_unregister(&daq700_driver);
}
-module_exit(dio700_cs_exit);
+module_exit(daq700_cs_exit);
MODULE_AUTHOR("Fred Brooks <nsaspook@nsaspook.com>");
MODULE_DESCRIPTION(
- "Comedi driver for National Instruments PCMCIA DAQCard-700 DIO");
+ "Comedi driver for National Instruments PCMCIA DAQCard-700 DIO/AI");
+MODULE_VERSION("0.2.00");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index e27cae0eb8a2..0ca222bbcbe6 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -164,7 +164,7 @@ static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return ret;
/* 8255 dio */
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
subdev_8255_init(dev, s, NULL, dev->iobase);
return 0;
@@ -172,8 +172,12 @@ static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it)
static void dio24_detach(struct comedi_device *dev)
{
- if (dev->subdevices)
- subdev_8255_cleanup(dev, dev->subdevices + 0);
+ struct comedi_subdevice *s;
+
+ if (dev->subdevices) {
+ s = &dev->subdevices[0];
+ subdev_8255_cleanup(dev, s);
+ }
if (thisboard->bustype != pcmcia_bustype && dev->iobase)
release_region(dev->iobase, DIO24_SIZE);
if (dev->irq)
@@ -304,7 +308,7 @@ MODULE_DESCRIPTION("Comedi driver for National Instruments "
"PCMCIA DAQ-Card DIO-24");
MODULE_LICENSE("GPL");
-struct pcmcia_driver dio24_cs_driver = {
+static struct pcmcia_driver dio24_cs_driver = {
.probe = dio24_cs_attach,
.remove = dio24_cs_detach,
.suspend = dio24_cs_suspend,
diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
index ab8b787c78bb..28b91a6c3789 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.c
+++ b/drivers/staging/comedi/drivers/ni_labpc.c
@@ -73,9 +73,6 @@ NI manuals:
*/
-#undef LABPC_DEBUG
-/* #define LABPC_DEBUG enable debugging messages */
-
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/io.h>
@@ -209,7 +206,13 @@ NI manuals:
#define INIT_A1_BITS 0x70
#define COUNTER_B_BASE_REG 0x18
-static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+enum scan_mode {
+ MODE_SINGLE_CHAN,
+ MODE_SINGLE_CHAN_INTERVAL,
+ MODE_MULT_CHAN_UP,
+ MODE_MULT_CHAN_DOWN,
+};
+
static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
static irqreturn_t labpc_interrupt(int irq, void *d);
static int labpc_drain_fifo(struct comedi_device *dev);
@@ -240,12 +243,10 @@ static int labpc_eeprom_write_insn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
-static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd);
+static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd,
+ enum scan_mode scan_mode);
#ifdef CONFIG_ISA_DMA_API
-static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd);
-#endif
-#ifdef CONFIG_COMEDI_PCI_DRIVERS
-static int labpc_find_device(struct comedi_device *dev, int bus, int slot);
+static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd);
#endif
static int labpc_dio_mem_callback(int dir, int port, int data,
unsigned long arg);
@@ -261,13 +262,6 @@ static int labpc_eeprom_write(struct comedi_device *dev,
static void write_caldac(struct comedi_device *dev, unsigned int channel,
unsigned int value);
-enum scan_mode {
- MODE_SINGLE_CHAN,
- MODE_SINGLE_CHAN_INTERVAL,
- MODE_MULT_CHAN_UP,
- MODE_MULT_CHAN_DOWN,
-};
-
/* analog input ranges */
#define NUM_LABPC_PLUS_AI_RANGES 16
/* indicates unipolar ranges */
@@ -416,12 +410,12 @@ static inline void labpc_outb(unsigned int byte, unsigned long address)
static inline unsigned int labpc_readb(unsigned long address)
{
- return readb((void *)address);
+ return readb((void __iomem *)address);
}
static inline void labpc_writeb(unsigned int byte, unsigned long address)
{
- writeb(byte, (void *)address);
+ writeb(byte, (void __iomem *)address);
}
static const struct labpc_board_struct labpc_boards[] = {
@@ -495,33 +489,14 @@ static const int sample_size = 2;
#define devpriv ((struct labpc_private *)dev->private)
-static struct comedi_driver driver_labpc = {
- .driver_name = DRV_NAME,
- .module = THIS_MODULE,
- .attach = labpc_attach,
- .detach = labpc_common_detach,
- .num_names = ARRAY_SIZE(labpc_boards),
- .board_name = &labpc_boards[0].name,
- .offset = sizeof(struct labpc_board_struct),
-};
-
-#ifdef CONFIG_COMEDI_PCI_DRIVERS
-static DEFINE_PCI_DEVICE_TABLE(labpc_pci_table) = {
- {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x161)},
- {0}
-};
-
-MODULE_DEVICE_TABLE(pci, labpc_pci_table);
-#endif /* CONFIG_COMEDI_PCI_DRIVERS */
-
static inline int labpc_counter_load(struct comedi_device *dev,
unsigned long base_address,
unsigned int counter_number,
unsigned int count, unsigned int mode)
{
if (thisboard->memory_mapped_io)
- return i8254_mm_load((void *)base_address, 0, counter_number,
- count, mode);
+ return i8254_mm_load((void __iomem *)base_address, 0,
+ counter_number, count, mode);
else
return i8254_load(base_address, 0, counter_number, count, mode);
}
@@ -538,25 +513,16 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
short lsb, msb;
int ret;
- printk(KERN_ERR "comedi%d: ni_labpc: %s, io 0x%lx", dev->minor,
- thisboard->name,
- iobase);
- if (irq)
- printk(", irq %u", irq);
- if (dma_chan)
- printk(", dma %u", dma_chan);
- printk("\n");
-
+ dev_info(dev->class_dev, "ni_labpc: %s\n", thisboard->name);
if (iobase == 0) {
- printk(KERN_ERR "io base address is zero!\n");
+ dev_err(dev->class_dev, "io base address is zero!\n");
return -EINVAL;
}
/* request io regions for isa boards */
if (thisboard->bustype == isa_bustype) {
/* check if io addresses are available */
- if (!request_region(iobase, LABPC_SIZE,
- driver_labpc.driver_name)) {
- printk(KERN_ERR "I/O port conflict\n");
+ if (!request_region(iobase, LABPC_SIZE, DRV_NAME)) {
+ dev_err(dev->class_dev, "I/O port conflict\n");
return -EIO;
}
}
@@ -588,8 +554,9 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
|| thisboard->bustype == pcmcia_bustype)
isr_flags |= IRQF_SHARED;
if (request_irq(irq, labpc_interrupt, isr_flags,
- driver_labpc.driver_name, dev)) {
- printk(KERN_ERR "unable to allocate irq %u\n", irq);
+ DRV_NAME, dev)) {
+ dev_err(dev->class_dev, "unable to allocate irq %u\n",
+ irq);
return -EINVAL;
}
}
@@ -598,19 +565,21 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
#ifdef CONFIG_ISA_DMA_API
/* grab dma channel */
if (dma_chan > 3) {
- printk(KERN_ERR " invalid dma channel %u\n", dma_chan);
+ dev_err(dev->class_dev, "invalid dma channel %u\n", dma_chan);
return -EINVAL;
} else if (dma_chan) {
/* allocate dma buffer */
devpriv->dma_buffer =
kmalloc(dma_buffer_size, GFP_KERNEL | GFP_DMA);
if (devpriv->dma_buffer == NULL) {
- printk(KERN_ERR " failed to allocate dma buffer\n");
+ dev_err(dev->class_dev,
+ "failed to allocate dma buffer\n");
return -ENOMEM;
}
- if (request_dma(dma_chan, driver_labpc.driver_name)) {
- printk(KERN_ERR " failed to allocate dma channel %u\n",
- dma_chan);
+ if (request_dma(dma_chan, DRV_NAME)) {
+ dev_err(dev->class_dev,
+ "failed to allocate dma channel %u\n",
+ dma_chan);
return -EINVAL;
}
devpriv->dma_chan = dma_chan;
@@ -628,7 +597,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
return ret;
/* analog input subdevice */
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
dev->read_subdev = s;
s->type = COMEDI_SUBD_AI;
s->subdev_flags =
@@ -643,7 +612,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
s->cancel = labpc_cancel;
/* analog output */
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
if (thisboard->has_ao) {
/*
* Could provide command support, except it only has a
@@ -670,7 +639,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
}
/* 8255 dio */
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
/* if board uses io memory we have to give a custom callback
* function to the 8255 driver */
if (thisboard->memory_mapped_io)
@@ -680,7 +649,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
subdev_8255_init(dev, s, NULL, dev->iobase + DIO_BASE_REG);
/* calibration subdevices for boards that have one */
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
if (thisboard->register_layout == labpc_1200_layout) {
s->type = COMEDI_SUBD_CALIB;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
@@ -695,7 +664,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
s->type = COMEDI_SUBD_UNUSED;
/* EEPROM */
- s = dev->subdevices + 4;
+ s = &dev->subdevices[4];
if (thisboard->register_layout == labpc_1200_layout) {
s->type = COMEDI_SUBD_MEMORY;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
@@ -706,12 +675,6 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
for (i = 0; i < EEPROM_SIZE; i++)
devpriv->eeprom_data[i] = labpc_eeprom_read(dev, i);
-#ifdef LABPC_DEBUG
- printk(KERN_ERR " eeprom:");
- for (i = 0; i < EEPROM_SIZE; i++)
- printk(" %i:0x%x ", i, devpriv->eeprom_data[i]);
- printk("\n");
-#endif
} else
s->type = COMEDI_SUBD_UNUSED;
@@ -719,14 +682,52 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
}
EXPORT_SYMBOL_GPL(labpc_common_attach);
+static const struct labpc_board_struct *
+labpc_pci_find_boardinfo(struct pci_dev *pcidev)
+{
+ unsigned int device_id = pcidev->device;
+ unsigned int n;
+
+ for (n = 0; n < ARRAY_SIZE(labpc_boards); n++) {
+ const struct labpc_board_struct *board = &labpc_boards[n];
+ if (board->bustype == pci_bustype &&
+ board->device_id == device_id)
+ return board;
+ }
+ return NULL;
+}
+
+static int __devinit labpc_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
+{
+ unsigned long iobase;
+ unsigned int irq;
+ int ret;
+
+ if (!IS_ENABLED(CONFIG_COMEDI_PCI_DRIVERS))
+ return -ENODEV;
+ ret = alloc_private(dev, sizeof(struct labpc_private));
+ if (ret < 0)
+ return ret;
+ dev->board_ptr = labpc_pci_find_boardinfo(pcidev);
+ if (!dev->board_ptr)
+ return -ENODEV;
+ devpriv->mite = mite_alloc(pcidev);
+ if (!devpriv->mite)
+ return -ENOMEM;
+ ret = mite_setup(devpriv->mite);
+ if (ret < 0)
+ return ret;
+ iobase = (unsigned long)devpriv->mite->daq_io_addr;
+ irq = mite_irq(devpriv->mite);
+ return labpc_common_attach(dev, iobase, irq, 0);
+}
+
static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
unsigned long iobase = 0;
unsigned int irq = 0;
unsigned int dma_chan = 0;
-#ifdef CONFIG_COMEDI_PCI_DRIVERS
- int retval;
-#endif
/* allocate and initialize dev->private */
if (alloc_private(dev, sizeof(struct labpc_private)) < 0)
@@ -740,34 +741,26 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
irq = it->options[1];
dma_chan = it->options[2];
#else
- printk(KERN_ERR " this driver has not been built with ISA DMA "
- "support.\n");
+ dev_err(dev->class_dev,
+ "ni_labpc driver has not been built with ISA DMA support.\n");
return -EINVAL;
#endif
break;
case pci_bustype:
#ifdef CONFIG_COMEDI_PCI_DRIVERS
- retval = labpc_find_device(dev, it->options[0], it->options[1]);
- if (retval < 0)
- return retval;
- retval = mite_setup(devpriv->mite);
- if (retval < 0)
- return retval;
- iobase = (unsigned long)devpriv->mite->daq_io_addr;
- irq = mite_irq(devpriv->mite);
+ dev_err(dev->class_dev,
+ "manual configuration of PCI board '%s' is not supported\n",
+ thisboard->name);
+ return -EINVAL;
#else
- printk(KERN_ERR " this driver has not been built with PCI "
- "support.\n");
+ dev_err(dev->class_dev,
+ "ni_labpc driver has not been built with PCI support.\n");
return -EINVAL;
#endif
break;
- case pcmcia_bustype:
- printk
- (" this driver does not support pcmcia cards, use ni_labpc_cs.o\n");
- return -EINVAL;
- break;
default:
- printk(KERN_ERR "bug! couldn't determine board type\n");
+ dev_err(dev->class_dev,
+ "ni_labpc: bug! couldn't determine board type\n");
return -EINVAL;
break;
}
@@ -775,42 +768,14 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return labpc_common_attach(dev, iobase, irq, dma_chan);
}
-/* adapted from ni_pcimio for finding mite based boards (pc-1200) */
-#ifdef CONFIG_COMEDI_PCI_DRIVERS
-static int labpc_find_device(struct comedi_device *dev, int bus, int slot)
-{
- struct mite_struct *mite;
- int i;
- for (mite = mite_devices; mite; mite = mite->next) {
- if (mite->used)
- continue;
-/* if bus/slot are specified then make sure we have the right bus/slot */
- if (bus || slot) {
- if (bus != mite->pcidev->bus->number
- || slot != PCI_SLOT(mite->pcidev->devfn))
- continue;
- }
- for (i = 0; i < driver_labpc.num_names; i++) {
- if (labpc_boards[i].bustype != pci_bustype)
- continue;
- if (mite_device_id(mite) == labpc_boards[i].device_id) {
- devpriv->mite = mite;
-/* fixup board pointer, in case we were using the dummy "ni_labpc" entry */
- dev->board_ptr = &labpc_boards[i];
- return 0;
- }
- }
- }
- printk(KERN_ERR "no device found\n");
- mite_list_devices();
- return -EIO;
-}
-#endif
-
void labpc_common_detach(struct comedi_device *dev)
{
- if (dev->subdevices)
- subdev_8255_cleanup(dev, dev->subdevices + 2);
+ struct comedi_subdevice *s;
+
+ if (dev->subdevices) {
+ s = &dev->subdevices[2];
+ subdev_8255_cleanup(dev, s);
+ }
#ifdef CONFIG_ISA_DMA_API
/* only free stuff if it has been allocated by _attach */
kfree(devpriv->dma_buffer);
@@ -822,8 +787,10 @@ void labpc_common_detach(struct comedi_device *dev)
if (thisboard->bustype == isa_bustype && dev->iobase)
release_region(dev->iobase, LABPC_SIZE);
#ifdef CONFIG_COMEDI_PCI_DRIVERS
- if (devpriv->mite)
+ if (devpriv->mite) {
mite_unsetup(devpriv->mite);
+ mite_free(devpriv->mite);
+ }
#endif
};
EXPORT_SYMBOL_GPL(labpc_common_detach);
@@ -868,21 +835,19 @@ static enum scan_mode labpc_ai_scan_mode(const struct comedi_cmd *cmd)
if (CR_CHAN(cmd->chanlist[0]) > CR_CHAN(cmd->chanlist[1]))
return MODE_MULT_CHAN_DOWN;
- printk(KERN_ERR "ni_labpc: bug! this should never happen\n");
-
+ pr_err("ni_labpc: bug! cannot determine AI scan mode\n");
return 0;
}
static int labpc_ai_chanlist_invalid(const struct comedi_device *dev,
- const struct comedi_cmd *cmd)
+ const struct comedi_cmd *cmd,
+ enum scan_mode mode)
{
- int mode, channel, range, aref, i;
+ int channel, range, aref, i;
if (cmd->chanlist == NULL)
return 0;
- mode = labpc_ai_scan_mode(cmd);
-
if (mode == MODE_SINGLE_CHAN)
return 0;
@@ -924,7 +889,8 @@ static int labpc_ai_chanlist_invalid(const struct comedi_device *dev,
}
break;
default:
- printk(KERN_ERR "ni_labpc: bug! in chanlist check\n");
+ dev_err(dev->class_dev,
+ "ni_labpc: bug! in chanlist check\n");
return 1;
break;
}
@@ -945,9 +911,10 @@ static int labpc_ai_chanlist_invalid(const struct comedi_device *dev,
return 0;
}
-static int labpc_use_continuous_mode(const struct comedi_cmd *cmd)
+static int labpc_use_continuous_mode(const struct comedi_cmd *cmd,
+ enum scan_mode mode)
{
- if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN)
+ if (mode == MODE_SINGLE_CHAN)
return 1;
if (cmd->scan_begin_src == TRIG_FOLLOW)
@@ -956,24 +923,25 @@ static int labpc_use_continuous_mode(const struct comedi_cmd *cmd)
return 0;
}
-static unsigned int labpc_ai_convert_period(const struct comedi_cmd *cmd)
+static unsigned int labpc_ai_convert_period(const struct comedi_cmd *cmd,
+ enum scan_mode mode)
{
if (cmd->convert_src != TRIG_TIMER)
return 0;
- if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN &&
- cmd->scan_begin_src == TRIG_TIMER)
+ if (mode == MODE_SINGLE_CHAN && cmd->scan_begin_src == TRIG_TIMER)
return cmd->scan_begin_arg;
return cmd->convert_arg;
}
-static void labpc_set_ai_convert_period(struct comedi_cmd *cmd, unsigned int ns)
+static void labpc_set_ai_convert_period(struct comedi_cmd *cmd,
+ enum scan_mode mode, unsigned int ns)
{
if (cmd->convert_src != TRIG_TIMER)
return;
- if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN &&
+ if (mode == MODE_SINGLE_CHAN &&
cmd->scan_begin_src == TRIG_TIMER) {
cmd->scan_begin_arg = ns;
if (cmd->convert_arg > cmd->scan_begin_arg)
@@ -982,25 +950,25 @@ static void labpc_set_ai_convert_period(struct comedi_cmd *cmd, unsigned int ns)
cmd->convert_arg = ns;
}
-static unsigned int labpc_ai_scan_period(const struct comedi_cmd *cmd)
+static unsigned int labpc_ai_scan_period(const struct comedi_cmd *cmd,
+ enum scan_mode mode)
{
if (cmd->scan_begin_src != TRIG_TIMER)
return 0;
- if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN &&
- cmd->convert_src == TRIG_TIMER)
+ if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER)
return 0;
return cmd->scan_begin_arg;
}
-static void labpc_set_ai_scan_period(struct comedi_cmd *cmd, unsigned int ns)
+static void labpc_set_ai_scan_period(struct comedi_cmd *cmd,
+ enum scan_mode mode, unsigned int ns)
{
if (cmd->scan_begin_src != TRIG_TIMER)
return;
- if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN &&
- cmd->convert_src == TRIG_TIMER)
+ if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER)
return;
cmd->scan_begin_arg = ns;
@@ -1011,54 +979,33 @@ static int labpc_ai_cmdtest(struct comedi_device *dev,
{
int err = 0;
int tmp, tmp2;
- int stop_mask;
+ unsigned int stop_mask;
+ enum scan_mode mode;
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_EXT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
stop_mask = TRIG_COUNT | TRIG_NONE;
if (thisboard->register_layout == labpc_1200_layout)
stop_mask |= TRIG_EXT;
- cmd->stop_src &= stop_mask;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->stop_src, stop_mask);
if (err)
return 1;
- /* step 2: make sure trigger sources are unique and mutually compatible */
+ /* Step 2a : make sure trigger sources are unique */
- if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
- err++;
- if (cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_FOLLOW &&
- cmd->scan_begin_src != TRIG_EXT)
- err++;
- if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
- err++;
- if (cmd->stop_src != TRIG_COUNT &&
- cmd->stop_src != TRIG_EXT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
/* can't have external stop and start triggers at once */
if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT)
@@ -1133,14 +1080,15 @@ static int labpc_ai_cmdtest(struct comedi_device *dev,
tmp = cmd->convert_arg;
tmp2 = cmd->scan_begin_arg;
- labpc_adc_timing(dev, cmd);
+ mode = labpc_ai_scan_mode(cmd);
+ labpc_adc_timing(dev, cmd, mode);
if (tmp != cmd->convert_arg || tmp2 != cmd->scan_begin_arg)
err++;
if (err)
return 4;
- if (labpc_ai_chanlist_invalid(dev, cmd))
+ if (labpc_ai_chanlist_invalid(dev, cmd, mode))
return 5;
return 0;
@@ -1156,6 +1104,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
enum transfer_type xfer;
+ enum scan_mode mode;
unsigned long flags;
if (!dev->irq) {
@@ -1221,6 +1170,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
} else
xfer = fifo_not_empty_transfer;
devpriv->current_transfer = xfer;
+ mode = labpc_ai_scan_mode(cmd);
/* setup command6 register for 1200 boards */
if (thisboard->register_layout == labpc_1200_layout) {
@@ -1245,7 +1195,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
else
devpriv->command6_bits &= ~A1_INTR_EN_BIT;
/* are we scanning up or down through channels? */
- if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP)
+ if (mode == MODE_MULT_CHAN_UP)
devpriv->command6_bits |= ADC_SCAN_UP_BIT;
else
devpriv->command6_bits &= ~ADC_SCAN_UP_BIT;
@@ -1256,19 +1206,18 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
/* setup channel list, etc (command1 register) */
devpriv->command1_bits = 0;
- if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP)
+ if (mode == MODE_MULT_CHAN_UP)
channel = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]);
else
channel = CR_CHAN(cmd->chanlist[0]);
/* munge channel bits for differential / scan disabled mode */
- if (labpc_ai_scan_mode(cmd) != MODE_SINGLE_CHAN && aref == AREF_DIFF)
+ if (mode != MODE_SINGLE_CHAN && aref == AREF_DIFF)
channel *= 2;
devpriv->command1_bits |= ADC_CHAN_BITS(channel);
devpriv->command1_bits |= thisboard->ai_range_code[range];
devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG);
/* manual says to set scan enable bit on second pass */
- if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP ||
- labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_DOWN) {
+ if (mode == MODE_MULT_CHAN_UP || mode == MODE_MULT_CHAN_DOWN) {
devpriv->command1_bits |= ADC_SCAN_EN_BIT;
/* need a brief delay before enabling scan, or scan
* list will get screwed when you switch
@@ -1283,7 +1232,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT;
/* XXX should discard first scan when using interval scanning
* since manual says it is not synced with scan clock */
- if (labpc_use_continuous_mode(cmd) == 0) {
+ if (labpc_use_continuous_mode(cmd, mode) == 0) {
devpriv->command4_bits |= INTERVAL_SCAN_EN_BIT;
if (cmd->scan_begin_src == TRIG_EXT)
devpriv->command4_bits |= EXT_SCAN_EN_BIT;
@@ -1301,7 +1250,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
if (cmd->convert_src == TRIG_TIMER || cmd->scan_begin_src == TRIG_TIMER) {
/* set up pacing */
- labpc_adc_timing(dev, cmd);
+ labpc_adc_timing(dev, cmd, mode);
/* load counter b0 in mode 3 */
ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG,
0, devpriv->divisor_b0, 3);
@@ -1311,7 +1260,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
}
}
/* set up conversion pacing */
- if (labpc_ai_convert_period(cmd)) {
+ if (labpc_ai_convert_period(cmd, mode)) {
/* load counter a0 in mode 2 */
ret = labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG,
0, devpriv->divisor_a0, 2);
@@ -1324,7 +1273,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
dev->iobase + COUNTER_A_CONTROL_REG);
/* set up scan pacing */
- if (labpc_ai_scan_period(cmd)) {
+ if (labpc_ai_scan_period(cmd, mode)) {
/* load counter b1 in mode 2 */
ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG,
1, devpriv->divisor_b1, 2);
@@ -1347,7 +1296,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
set_dma_addr(devpriv->dma_chan,
virt_to_bus(devpriv->dma_buffer));
/* set appropriate size of transfer */
- devpriv->dma_transfer_size = labpc_suggest_transfer_size(*cmd);
+ devpriv->dma_transfer_size = labpc_suggest_transfer_size(cmd);
if (cmd->stop_src == TRIG_COUNT &&
devpriv->count * sample_size < devpriv->dma_transfer_size) {
devpriv->dma_transfer_size =
@@ -1786,8 +1735,8 @@ static int labpc_eeprom_write_insn(struct comedi_device *dev,
/* only allow writes to user area of eeprom */
if (channel < 16 || channel > 127) {
- printk
- ("eeprom writes are only allowed to channels 16 through 127 (the pointer and user areas)");
+ dev_dbg(dev->class_dev,
+ "eeprom writes are only allowed to channels 16 through 127 (the pointer and user areas)\n");
return -EINVAL;
}
@@ -1800,13 +1749,13 @@ static int labpc_eeprom_write_insn(struct comedi_device *dev,
#ifdef CONFIG_ISA_DMA_API
/* utility function that suggests a dma transfer size in bytes */
-static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd)
+static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd)
{
unsigned int size;
unsigned int freq;
- if (cmd.convert_src == TRIG_TIMER)
- freq = 1000000000 / cmd.convert_arg;
+ if (cmd->convert_src == TRIG_TIMER)
+ freq = 1000000000 / cmd->convert_arg;
/* return some default value */
else
freq = 0xffffffff;
@@ -1825,24 +1774,29 @@ static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd)
#endif
/* figures out what counter values to use based on command */
-static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd)
+static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd,
+ enum scan_mode mode)
{
/* max value for 16 bit counter in mode 2 */
const int max_counter_value = 0x10000;
/* min value for 16 bit counter in mode 2 */
const int min_counter_value = 2;
unsigned int base_period;
+ unsigned int scan_period;
+ unsigned int convert_period;
/*
* if both convert and scan triggers are TRIG_TIMER, then they
* both rely on counter b0
*/
- if (labpc_ai_convert_period(cmd) && labpc_ai_scan_period(cmd)) {
+ convert_period = labpc_ai_convert_period(cmd, mode);
+ scan_period = labpc_ai_scan_period(cmd, mode);
+ if (convert_period && scan_period) {
/*
* pick the lowest b0 divisor value we can (for maximum input
* clock speed on convert and scan counters)
*/
- devpriv->divisor_b0 = (labpc_ai_scan_period(cmd) - 1) /
+ devpriv->divisor_b0 = (scan_period - 1) /
(LABPC_TIMER_BASE * max_counter_value) + 1;
if (devpriv->divisor_b0 < min_counter_value)
devpriv->divisor_b0 = min_counter_value;
@@ -1856,25 +1810,19 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd)
default:
case TRIG_ROUND_NEAREST:
devpriv->divisor_a0 =
- (labpc_ai_convert_period(cmd) +
- (base_period / 2)) / base_period;
+ (convert_period + (base_period / 2)) / base_period;
devpriv->divisor_b1 =
- (labpc_ai_scan_period(cmd) +
- (base_period / 2)) / base_period;
+ (scan_period + (base_period / 2)) / base_period;
break;
case TRIG_ROUND_UP:
devpriv->divisor_a0 =
- (labpc_ai_convert_period(cmd) + (base_period -
- 1)) / base_period;
+ (convert_period + (base_period - 1)) / base_period;
devpriv->divisor_b1 =
- (labpc_ai_scan_period(cmd) + (base_period -
- 1)) / base_period;
+ (scan_period + (base_period - 1)) / base_period;
break;
case TRIG_ROUND_DOWN:
- devpriv->divisor_a0 =
- labpc_ai_convert_period(cmd) / base_period;
- devpriv->divisor_b1 =
- labpc_ai_scan_period(cmd) / base_period;
+ devpriv->divisor_a0 = convert_period / base_period;
+ devpriv->divisor_b1 = scan_period / base_period;
break;
}
/* make sure a0 and b1 values are acceptable */
@@ -1887,18 +1835,15 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd)
if (devpriv->divisor_b1 > max_counter_value)
devpriv->divisor_b1 = max_counter_value;
/* write corrected timings to command */
- labpc_set_ai_convert_period(cmd,
+ labpc_set_ai_convert_period(cmd, mode,
base_period * devpriv->divisor_a0);
- labpc_set_ai_scan_period(cmd,
+ labpc_set_ai_scan_period(cmd, mode,
base_period * devpriv->divisor_b1);
/*
* if only one TRIG_TIMER is used, we can employ the generic
* cascaded timing functions
*/
- } else if (labpc_ai_scan_period(cmd)) {
- unsigned int scan_period;
-
- scan_period = labpc_ai_scan_period(cmd);
+ } else if (scan_period) {
/*
* calculate cascaded counter values
* that give desired scan timing
@@ -1908,11 +1853,8 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd)
&(devpriv->divisor_b0),
&scan_period,
cmd->flags & TRIG_ROUND_MASK);
- labpc_set_ai_scan_period(cmd, scan_period);
- } else if (labpc_ai_convert_period(cmd)) {
- unsigned int convert_period;
-
- convert_period = labpc_ai_convert_period(cmd);
+ labpc_set_ai_scan_period(cmd, mode, scan_period);
+ } else if (convert_period) {
/*
* calculate cascaded counter values
* that give desired conversion timing
@@ -1922,7 +1864,7 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd)
&(devpriv->divisor_b0),
&convert_period,
cmd->flags & TRIG_ROUND_MASK);
- labpc_set_ai_convert_period(cmd, convert_period);
+ labpc_set_ai_convert_period(cmd, mode, convert_period);
}
}
@@ -1930,10 +1872,10 @@ static int labpc_dio_mem_callback(int dir, int port, int data,
unsigned long iobase)
{
if (dir) {
- writeb(data, (void *)(iobase + port));
+ writeb(data, (void __iomem *)(iobase + port));
return 0;
} else {
- return readb((void *)(iobase + port));
+ return readb((void __iomem *)(iobase + port));
}
}
@@ -2136,57 +2078,44 @@ static void write_caldac(struct comedi_device *dev, unsigned int channel,
devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
}
+static struct comedi_driver labpc_driver = {
+ .driver_name = DRV_NAME,
+ .module = THIS_MODULE,
+ .attach = labpc_attach,
+ .attach_pci = labpc_attach_pci,
+ .detach = labpc_common_detach,
+ .num_names = ARRAY_SIZE(labpc_boards),
+ .board_name = &labpc_boards[0].name,
+ .offset = sizeof(struct labpc_board_struct),
+};
+
#ifdef CONFIG_COMEDI_PCI_DRIVERS
-static int __devinit driver_labpc_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
+static DEFINE_PCI_DEVICE_TABLE(labpc_pci_table) = {
+ {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x161)},
+ {0}
+};
+MODULE_DEVICE_TABLE(pci, labpc_pci_table);
+
+static int __devinit labpc_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
{
- return comedi_pci_auto_config(dev, &driver_labpc);
+ return comedi_pci_auto_config(dev, &labpc_driver);
}
-static void __devexit driver_labpc_pci_remove(struct pci_dev *dev)
+static void __devexit labpc_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
-static struct pci_driver driver_labpc_pci_driver = {
+static struct pci_driver labpc_pci_driver = {
+ .name = DRV_NAME,
.id_table = labpc_pci_table,
- .probe = &driver_labpc_pci_probe,
- .remove = __devexit_p(&driver_labpc_pci_remove)
+ .probe = labpc_pci_probe,
+ .remove = __devexit_p(labpc_pci_remove)
};
-
-static int __init driver_labpc_init_module(void)
-{
- int retval;
-
- retval = comedi_driver_register(&driver_labpc);
- if (retval < 0)
- return retval;
-
- driver_labpc_pci_driver.name = (char *)driver_labpc.driver_name;
- return pci_register_driver(&driver_labpc_pci_driver);
-}
-
-static void __exit driver_labpc_cleanup_module(void)
-{
- pci_unregister_driver(&driver_labpc_pci_driver);
- comedi_driver_unregister(&driver_labpc);
-}
-
-module_init(driver_labpc_init_module);
-module_exit(driver_labpc_cleanup_module);
+module_comedi_pci_driver(labpc_driver, labpc_pci_driver);
#else
-static int __init driver_labpc_init_module(void)
-{
- return comedi_driver_register(&driver_labpc);
-}
-
-static void __exit driver_labpc_cleanup_module(void)
-{
- comedi_driver_unregister(&driver_labpc);
-}
-
-module_init(driver_labpc_init_module);
-module_exit(driver_labpc_cleanup_module);
+module_comedi_driver(labpc_driver);
#endif
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index dbb61b6b3ed1..eb0417eb6d7d 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -270,7 +270,7 @@ MODULE_AUTHOR("Frank Mori Hess <fmhess@users.sourceforge.net>");
MODULE_DESCRIPTION("Comedi driver for National Instruments Lab-PC");
MODULE_LICENSE("GPL");
-struct pcmcia_driver labpc_cs_driver = {
+static struct pcmcia_driver labpc_cs_driver = {
.probe = labpc_cs_attach,
.remove = labpc_cs_detach,
.suspend = labpc_cs_suspend,
@@ -291,7 +291,7 @@ static void __exit exit_labpc_cs(void)
pcmcia_unregister_driver(&labpc_cs_driver);
}
-int __init labpc_init_module(void)
+static int __init labpc_init_module(void)
{
int ret;
@@ -302,7 +302,7 @@ int __init labpc_init_module(void)
return comedi_driver_register(&driver_labpc_cs);
}
-void __exit labpc_exit_module(void)
+static void __exit labpc_exit_module(void)
{
exit_labpc_cs();
comedi_driver_unregister(&driver_labpc_cs);
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index cf0e0d147f8c..3e5fdae93163 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -644,10 +644,10 @@ static void ni_release_ao_mite_channel(struct comedi_device *dev)
#endif /* PCIDMA */
}
-void ni_release_gpct_mite_channel(struct comedi_device *dev,
- unsigned gpct_index)
-{
#ifdef PCIDMA
+static void ni_release_gpct_mite_channel(struct comedi_device *dev,
+ unsigned gpct_index)
+{
unsigned long flags;
BUG_ON(gpct_index >= NUM_GPCT);
@@ -663,8 +663,8 @@ void ni_release_gpct_mite_channel(struct comedi_device *dev,
mite_release_channel(mite_chan);
}
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
-#endif /* PCIDMA */
}
+#endif /* PCIDMA */
static void ni_release_cdo_mite_channel(struct comedi_device *dev)
{
@@ -872,7 +872,7 @@ static irqreturn_t ni_E_interrupt(int irq, void *d)
#ifdef PCIDMA
static void ni_sync_ai_dma(struct comedi_device *dev)
{
- struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
unsigned long flags;
spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -884,7 +884,7 @@ static void ni_sync_ai_dma(struct comedi_device *dev)
static void mite_handle_b_linkc(struct mite_struct *mite,
struct comedi_device *dev)
{
- struct comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV;
+ struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV];
unsigned long flags;
spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -942,7 +942,7 @@ static void ni_handle_eos(struct comedi_device *dev, struct comedi_subdevice *s)
static void shutdown_ai_command(struct comedi_device *dev)
{
- struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
#ifdef PCIDMA
ni_ai_drain_dma(dev);
@@ -984,8 +984,9 @@ static void handle_gpct_interrupt(struct comedi_device *dev,
unsigned short counter_index)
{
#ifdef PCIDMA
- struct comedi_subdevice *s =
- dev->subdevices + NI_GPCT_SUBDEV(counter_index);
+ struct comedi_subdevice *s;
+
+ s = &dev->subdevices[NI_GPCT_SUBDEV(counter_index)];
ni_tio_handle_interrupt(&devpriv->counter_dev->counters[counter_index],
s);
@@ -1018,7 +1019,7 @@ static void ack_a_interrupt(struct comedi_device *dev, unsigned short a_status)
static void handle_a_interrupt(struct comedi_device *dev, unsigned short status,
unsigned ai_mite_status)
{
- struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
/* 67xx boards don't have ai subdevice, but their gpct0 might generate an a interrupt */
if (s->type == COMEDI_SUBD_UNUSED)
@@ -1150,7 +1151,7 @@ static void ack_b_interrupt(struct comedi_device *dev, unsigned short b_status)
static void handle_b_interrupt(struct comedi_device *dev,
unsigned short b_status, unsigned ao_mite_status)
{
- struct comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV;
+ struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV];
/* unsigned short ack=0; */
#ifdef DEBUG_INTERRUPT
printk("ni_mio_common: interrupt: b_status=%04x m1_status=%08x\n",
@@ -1422,7 +1423,7 @@ static void ni_ai_fifo_read(struct comedi_device *dev,
static void ni_handle_fifo_half_full(struct comedi_device *dev)
{
int n;
- struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
n = boardtype.ai_fifo_depth / 2;
@@ -1470,7 +1471,7 @@ static int ni_ai_drain_dma(struct comedi_device *dev)
*/
static void ni_handle_fifo_dregs(struct comedi_device *dev)
{
- struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
short data[2];
u32 dl;
short fifo_empty;
@@ -1534,7 +1535,7 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev)
static void get_last_sample_611x(struct comedi_device *dev)
{
- struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
short data;
u32 dl;
@@ -1551,7 +1552,7 @@ static void get_last_sample_611x(struct comedi_device *dev)
static void get_last_sample_6143(struct comedi_device *dev)
{
- struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
short data;
u32 dl;
@@ -1598,7 +1599,7 @@ static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
static int ni_ai_setup_MITE_dma(struct comedi_device *dev)
{
- struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
int retval;
unsigned long flags;
@@ -1637,7 +1638,7 @@ static int ni_ai_setup_MITE_dma(struct comedi_device *dev)
static int ni_ao_setup_MITE_dma(struct comedi_device *dev)
{
- struct comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV;
+ struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV];
int retval;
unsigned long flags;
@@ -1765,20 +1766,18 @@ static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s)
static int ni_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
{
- unsigned long flags = 0;
+ unsigned long flags;
int count;
/* lock to avoid race with interrupt handler */
- if (in_interrupt() == 0)
- spin_lock_irqsave(&dev->spinlock, flags);
+ spin_lock_irqsave(&dev->spinlock, flags);
#ifndef PCIDMA
ni_handle_fifo_dregs(dev);
#else
ni_sync_ai_dma(dev);
#endif
count = s->async->buf_write_count - s->async->buf_read_count;
- if (in_interrupt() == 0)
- spin_unlock_irqrestore(&dev->spinlock, flags);
+ spin_unlock_irqrestore(&dev->spinlock, flags);
return count;
}
@@ -1880,7 +1879,7 @@ static int ni_ai_insn_read(struct comedi_device *dev,
return insn->n;
}
-void ni_prime_channelgain_list(struct comedi_device *dev)
+static void ni_prime_channelgain_list(struct comedi_device *dev)
{
int i;
devpriv->stc_writew(dev, AI_CONVERT_Pulse, AI_Command_1_Register);
@@ -2165,61 +2164,38 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
{
int err = 0;
int tmp;
- int sources;
+ unsigned int sources;
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- if ((cmd->flags & CMDF_WRITE)) {
+ if ((cmd->flags & CMDF_WRITE))
cmd->flags &= ~CMDF_WRITE;
- }
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_INT | TRIG_EXT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src,
+ TRIG_NOW | TRIG_INT | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_TIMER | TRIG_EXT);
- tmp = cmd->convert_src;
sources = TRIG_TIMER | TRIG_EXT;
- if ((boardtype.reg_type == ni_reg_611x)
- || (boardtype.reg_type == ni_reg_6143))
+ if (boardtype.reg_type == ni_reg_611x ||
+ boardtype.reg_type == ni_reg_6143)
sources |= TRIG_NOW;
- cmd->convert_src &= sources;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->convert_src, sources);
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ 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 2: make sure trigger sources are unique and mutually compatible */
+ /* Step 2a : make sure trigger sources are unique */
- /* note that mutual compatibility is not an issue here */
- if (cmd->start_src != TRIG_NOW &&
- cmd->start_src != TRIG_INT && cmd->start_src != TRIG_EXT)
- err++;
- if (cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_EXT &&
- cmd->scan_begin_src != TRIG_OTHER)
- err++;
- if (cmd->convert_src != TRIG_TIMER &&
- cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW)
- err++;
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -3357,44 +3333,28 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
int err = 0;
int tmp;
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- if ((cmd->flags & CMDF_WRITE) == 0) {
+ if ((cmd->flags & CMDF_WRITE) == 0)
cmd->flags |= CMDF_WRITE;
- }
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_INT | TRIG_EXT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_NOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_TIMER | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
+ 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 2: make sure trigger sources are unique and mutually compatible */
+ /* Step 2a : make sure trigger sources are unique */
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -3644,51 +3604,21 @@ static int ni_cdio_cmdtest(struct comedi_device *dev,
{
int err = 0;
int tmp;
- int sources;
unsigned i;
- /* step 1: make sure trigger sources are trivially valid */
-
- tmp = cmd->start_src;
- sources = TRIG_INT;
- cmd->start_src &= sources;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_NOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
if (err)
return 1;
- /* step 2: make sure trigger sources are unique... */
-
- if (cmd->start_src != TRIG_INT)
- err++;
- if (cmd->scan_begin_src != TRIG_EXT)
- err++;
- if (cmd->convert_src != TRIG_NOW)
- err++;
- if (cmd->stop_src != TRIG_NONE)
- err++;
- /* ... and mutually compatible */
+ /* Step 2a : make sure trigger sources are unique */
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -3852,7 +3782,7 @@ static int ni_cdio_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
static void handle_cdio_interrupt(struct comedi_device *dev)
{
unsigned cdio_status;
- struct comedi_subdevice *s = dev->subdevices + NI_DIO_SUBDEV;
+ struct comedi_subdevice *s = &dev->subdevices[NI_DIO_SUBDEV];
#ifdef PCIDMA
unsigned long flags;
#endif
@@ -4101,13 +4031,17 @@ static int ni_serial_sw_readwrite8(struct comedi_device *dev,
static void mio_common_detach(struct comedi_device *dev)
{
+ struct comedi_subdevice *s;
+
if (dev->private) {
if (devpriv->counter_dev) {
ni_gpct_device_destroy(devpriv->counter_dev);
}
}
- if (dev->subdevices && boardtype.has_8255)
- subdev_8255_cleanup(dev, dev->subdevices + NI_8255_DIO_SUBDEV);
+ if (dev->subdevices && boardtype.has_8255) {
+ s = &dev->subdevices[NI_8255_DIO_SUBDEV];
+ subdev_8255_cleanup(dev, s);
+ }
}
static void init_ao_67xx(struct comedi_device *dev, struct comedi_subdevice *s)
@@ -4399,7 +4333,7 @@ static int ni_alloc_private(struct comedi_device *dev)
return 0;
};
-static int ni_E_init(struct comedi_device *dev, struct comedi_devconfig *it)
+static int ni_E_init(struct comedi_device *dev)
{
struct comedi_subdevice *s;
unsigned j;
@@ -4417,7 +4351,7 @@ static int ni_E_init(struct comedi_device *dev, struct comedi_devconfig *it)
/* analog input subdevice */
- s = dev->subdevices + NI_AI_SUBDEV;
+ s = &dev->subdevices[NI_AI_SUBDEV];
dev->read_subdev = s;
if (boardtype.n_adchan) {
s->type = COMEDI_SUBD_AI;
@@ -4449,7 +4383,7 @@ static int ni_E_init(struct comedi_device *dev, struct comedi_devconfig *it)
/* analog output subdevice */
- s = dev->subdevices + NI_AO_SUBDEV;
+ s = &dev->subdevices[NI_AO_SUBDEV];
if (boardtype.n_aochan) {
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE | SDF_DEGLITCH | SDF_GROUND;
@@ -4488,7 +4422,7 @@ static int ni_E_init(struct comedi_device *dev, struct comedi_devconfig *it)
/* digital i/o subdevice */
- s = dev->subdevices + NI_DIO_SUBDEV;
+ s = &dev->subdevices[NI_DIO_SUBDEV];
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
s->maxdata = 1;
@@ -4516,7 +4450,7 @@ static int ni_E_init(struct comedi_device *dev, struct comedi_devconfig *it)
}
/* 8255 device */
- s = dev->subdevices + NI_8255_DIO_SUBDEV;
+ s = &dev->subdevices[NI_8255_DIO_SUBDEV];
if (boardtype.has_8255) {
subdev_8255_init(dev, s, ni_8255_callback, (unsigned long)dev);
} else {
@@ -4524,11 +4458,11 @@ static int ni_E_init(struct comedi_device *dev, struct comedi_devconfig *it)
}
/* formerly general purpose counter/timer device, but no longer used */
- s = dev->subdevices + NI_UNUSED_SUBDEV;
+ s = &dev->subdevices[NI_UNUSED_SUBDEV];
s->type = COMEDI_SUBD_UNUSED;
/* calibration subdevice -- ai and ao */
- s = dev->subdevices + NI_CALIBRATION_SUBDEV;
+ s = &dev->subdevices[NI_CALIBRATION_SUBDEV];
s->type = COMEDI_SUBD_CALIB;
if (boardtype.reg_type & ni_reg_m_series_mask) {
/* internal PWM analog output used for AI nonlinearity calibration */
@@ -4551,7 +4485,7 @@ static int ni_E_init(struct comedi_device *dev, struct comedi_devconfig *it)
}
/* EEPROM */
- s = dev->subdevices + NI_EEPROM_SUBDEV;
+ s = &dev->subdevices[NI_EEPROM_SUBDEV];
s->type = COMEDI_SUBD_MEMORY;
s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
s->maxdata = 0xff;
@@ -4564,7 +4498,7 @@ static int ni_E_init(struct comedi_device *dev, struct comedi_devconfig *it)
}
/* PFI */
- s = dev->subdevices + NI_PFI_DIO_SUBDEV;
+ s = &dev->subdevices[NI_PFI_DIO_SUBDEV];
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
if (boardtype.reg_type & ni_reg_m_series_mask) {
@@ -4586,7 +4520,7 @@ static int ni_E_init(struct comedi_device *dev, struct comedi_devconfig *it)
ni_set_bits(dev, IO_Bidirection_Pin_Register, ~0, 0);
/* cs5529 calibration adc */
- s = dev->subdevices + NI_CS5529_CALIBRATION_SUBDEV;
+ s = &dev->subdevices[NI_CS5529_CALIBRATION_SUBDEV];
if (boardtype.reg_type & ni_reg_67xx_mask) {
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_INTERNAL;
@@ -4602,7 +4536,7 @@ static int ni_E_init(struct comedi_device *dev, struct comedi_devconfig *it)
}
/* Serial */
- s = dev->subdevices + NI_SERIAL_SUBDEV;
+ s = &dev->subdevices[NI_SERIAL_SUBDEV];
s->type = COMEDI_SUBD_SERIAL;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
s->n_chan = 1;
@@ -4612,7 +4546,7 @@ static int ni_E_init(struct comedi_device *dev, struct comedi_devconfig *it)
devpriv->serial_hw_mode = 0;
/* RTSI */
- s = dev->subdevices + NI_RTSI_SUBDEV;
+ s = &dev->subdevices[NI_RTSI_SUBDEV];
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
s->n_chan = 8;
@@ -4633,7 +4567,7 @@ static int ni_E_init(struct comedi_device *dev, struct comedi_devconfig *it)
NUM_GPCT);
/* General purpose counters */
for (j = 0; j < NUM_GPCT; ++j) {
- s = dev->subdevices + NI_GPCT_SUBDEV(j);
+ s = &dev->subdevices[NI_GPCT_SUBDEV(j)];
s->type = COMEDI_SUBD_COUNTER;
s->subdev_flags =
SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_CMD_READ
@@ -4659,7 +4593,7 @@ static int ni_E_init(struct comedi_device *dev, struct comedi_devconfig *it)
}
/* Frequency output */
- s = dev->subdevices + NI_FREQ_OUT_SUBDEV;
+ s = &dev->subdevices[NI_FREQ_OUT_SUBDEV];
s->type = COMEDI_SUBD_COUNTER;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 1;
@@ -4669,7 +4603,8 @@ static int ni_E_init(struct comedi_device *dev, struct comedi_devconfig *it)
s->insn_config = &ni_freq_out_insn_config;
/* ai configuration */
- ni_ai_reset(dev, dev->subdevices + NI_AI_SUBDEV);
+ s = &dev->subdevices[NI_AI_SUBDEV];
+ ni_ai_reset(dev, s);
if ((boardtype.reg_type & ni_reg_6xxx_mask) == 0) {
/* BEAM is this needed for PCI-6143 ?? */
devpriv->clock_and_fout =
@@ -4688,7 +4623,8 @@ static int ni_E_init(struct comedi_device *dev, struct comedi_devconfig *it)
Clock_and_FOUT_Register);
/* analog output configuration */
- ni_ao_reset(dev, dev->subdevices + NI_AO_SUBDEV);
+ s = &dev->subdevices[NI_AO_SUBDEV];
+ ni_ao_reset(dev, s);
if (dev->irq) {
devpriv->stc_writew(dev,
diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
index b85765d266c2..ca4f8e06e75b 100644
--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
+++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
@@ -382,7 +382,7 @@ static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)
devpriv->stc_writel = &win_out2;
devpriv->stc_readl = &win_in2;
- ret = ni_E_init(dev, it);
+ ret = ni_E_init(dev);
if (ret < 0)
return ret;
@@ -421,7 +421,7 @@ MODULE_AUTHOR("David A. Schleef <ds@schleef.org>");
MODULE_DESCRIPTION("Comedi driver for National Instruments DAQCard E series");
MODULE_LICENSE("GPL");
-struct pcmcia_driver ni_mio_cs_driver = {
+static struct pcmcia_driver ni_mio_cs_driver = {
.probe = &cs_attach,
.remove = &cs_detach,
.suspend = &mio_cs_suspend,
diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
index 0a55de968039..bc9313ec985c 100644
--- a/drivers/staging/comedi/drivers/ni_pcidio.c
+++ b/drivers/staging/comedi/drivers/ni_pcidio.c
@@ -1,8 +1,6 @@
/*
comedi/drivers/ni_pcidio.c
- driver for National Instruments PCI-DIO-96/PCI-6508
- National Instruments PCI-DIO-32HS
- National Instruments PCI-6503
+ driver for National Instruments PCI-DIO-32HS
COMEDI - Linux Control and Measurement Device Interface
Copyright (C) 1999,2002 David A. Schleef <ds@schleef.org>
@@ -24,17 +22,14 @@
*/
/*
Driver: ni_pcidio
-Description: National Instruments PCI-DIO32HS, PCI-DIO96, PCI-6533, PCI-6503
+Description: National Instruments PCI-DIO32HS, PCI-6533
Author: ds
Status: works
-Devices: [National Instruments] PCI-DIO-32HS (ni_pcidio), PXI-6533,
- PCI-DIO-96, PCI-DIO-96B, PXI-6508, PCI-6503, PCI-6503B, PCI-6503X,
- PXI-6503, PCI-6533, PCI-6534
+Devices: [National Instruments] PCI-DIO-32HS (ni_pcidio)
+ [National Instruments] PXI-6533, PCI-6533 (pxi-6533)
+ [National Instruments] PCI-6534 (pci-6534)
Updated: Mon, 09 Jan 2012 14:27:23 +0000
-The DIO-96 appears as four 8255 subdevices. See the 8255
-driver notes for details.
-
The DIO32HS board appears as one subdevice, with 32 channels.
Each channel is individually I/O configurable. The channel order
is 0=A0, 1=A1, 2=A2, ... 8=B0, 16=C0, 24=D0. The driver only
@@ -56,49 +51,28 @@ it are contained in the
comedi_nonfree_firmware tarball available from http://www.comedi.org
*/
-/*
- This driver is for both the NI PCI-DIO-32HS and the PCI-DIO-96,
- which have very different architectures. But, since the '96 is
- so simple, it is included here.
-
- Manuals (available from ftp://ftp.natinst.com/support/manuals)
-
- 320938c.pdf PCI-DIO-96/PXI-6508/PCI-6503 User Manual
- 321464b.pdf AT/PCI-DIO-32HS User Manual
- 341329A.pdf PCI-6533 Register-Level Programmer Manual
- 341330A.pdf DAQ-DIO Technical Reference Manual
-
- */
-
#define USE_DMA
/* #define DEBUG 1 */
/* #define DEBUG_FLAGS */
#include <linux/interrupt.h>
#include <linux/sched.h>
+#include <linux/firmware.h>
#include "../comedidev.h"
+#include "comedi_fc.h"
#include "mite.h"
-#include "8255.h"
#undef DPRINTK
#ifdef DEBUG
-#define DPRINTK(format, args...) printk(format, ## args)
+#define DPRINTK(format, args...) pr_debug(format, ## args)
#else
-#define DPRINTK(format, args...)
+#define DPRINTK(format, args...) do { } while (0)
#endif
#define PCI_DIO_SIZE 4096
#define PCI_MITE_SIZE 4096
-/* defines for the PCI-DIO-96 */
-
-#define NIDIO_8255_BASE(x) ((x)*4)
-#define NIDIO_A 0
-#define NIDIO_B 4
-#define NIDIO_C 8
-#define NIDIO_D 12
-
/* defines for the PCI-DIO-32HS */
#define Window_Address 4 /* W */
@@ -258,6 +232,14 @@ static inline unsigned secondary_DMAChannel_bits(unsigned channel)
#define Protocol_Register_8 88 /* 32 bit */
#define StartDelay Protocol_Register_8
+/* Firmware files for PCI-6524 */
+#define FW_PCI_6534_MAIN "ni6534a.bin"
+#define FW_PCI_6534_SCARAB_DI "niscrb01.bin"
+#define FW_PCI_6534_SCARAB_DO "niscrb02.bin"
+MODULE_FIRMWARE(FW_PCI_6534_MAIN);
+MODULE_FIRMWARE(FW_PCI_6534_SCARAB_DI);
+MODULE_FIRMWARE(FW_PCI_6534_SCARAB_DO);
+
enum pci_6534_firmware_registers { /* 16 bit */
Firmware_Control_Register = 0x100,
Firmware_Status_Register = 0x104,
@@ -297,76 +279,23 @@ static int ni_pcidio_cancel(struct comedi_device *dev,
struct comedi_subdevice *s);
struct nidio_board {
-
int dev_id;
const char *name;
- int n_8255;
- unsigned int is_diodaq:1;
unsigned int uses_firmware:1;
};
static const struct nidio_board nidio_boards[] = {
{
- .dev_id = 0x1150,
- .name = "pci-dio-32hs",
- .n_8255 = 0,
- .is_diodaq = 1,
- },
- {
- .dev_id = 0x1320,
- .name = "pxi-6533",
- .n_8255 = 0,
- .is_diodaq = 1,
- },
- {
- .dev_id = 0x12b0,
- .name = "pci-6534",
- .n_8255 = 0,
- .is_diodaq = 1,
- .uses_firmware = 1,
- },
- {
- .dev_id = 0x0160,
- .name = "pci-dio-96",
- .n_8255 = 4,
- .is_diodaq = 0,
- },
- {
- .dev_id = 0x1630,
- .name = "pci-dio-96b",
- .n_8255 = 4,
- .is_diodaq = 0,
- },
- {
- .dev_id = 0x13c0,
- .name = "pxi-6508",
- .n_8255 = 4,
- .is_diodaq = 0,
- },
- {
- .dev_id = 0x0400,
- .name = "pci-6503",
- .n_8255 = 1,
- .is_diodaq = 0,
- },
- {
- .dev_id = 0x1250,
- .name = "pci-6503b",
- .n_8255 = 1,
- .is_diodaq = 0,
- },
- {
- .dev_id = 0x17d0,
- .name = "pci-6503x",
- .n_8255 = 1,
- .is_diodaq = 0,
- },
- {
- .dev_id = 0x1800,
- .name = "pxi-6503",
- .n_8255 = 1,
- .is_diodaq = 0,
- },
+ .dev_id = 0x1150,
+ .name = "pci-dio-32hs",
+ }, {
+ .dev_id = 0x1320,
+ .name = "pxi-6533",
+ }, {
+ .dev_id = 0x12b0,
+ .name = "pci-6534",
+ .uses_firmware = 1,
+ },
};
#define n_nidio_boards ARRAY_SIZE(nidio_boards)
@@ -442,17 +371,8 @@ static void ni_pcidio_release_di_mite_channel(struct comedi_device *dev)
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
}
-static int nidio96_8255_cb(int dir, int port, int data, unsigned long iobase)
-{
- if (dir) {
- writeb(data, (void *)(iobase + port));
- return 0;
- } else {
- return readb((void *)(iobase + port));
- }
-}
-
-void ni_pcidio_event(struct comedi_device *dev, struct comedi_subdevice *s)
+static void ni_pcidio_event(struct comedi_device *dev,
+ struct comedi_subdevice *s)
{
if (s->
async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
@@ -480,7 +400,7 @@ static int ni_pcidio_poll(struct comedi_device *dev, struct comedi_subdevice *s)
static irqreturn_t nidio_interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
- struct comedi_subdevice *s = dev->subdevices;
+ struct comedi_subdevice *s = &dev->subdevices[0];
struct comedi_async *async = s->async;
struct mite_struct *mite = devpriv->mite;
@@ -511,18 +431,12 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
ni_pcidio_print_flags(flags);
ni_pcidio_print_status(status);
- /* printk("buf[0]=%08x\n",*(unsigned int *)async->prealloc_buf); */
- /* printk("buf[4096]=%08x\n",
- *(unsigned int *)(async->prealloc_buf+4096)); */
-
spin_lock(&devpriv->mite_channel_lock);
if (devpriv->di_mite_chan)
m_status = mite_get_status(devpriv->di_mite_chan);
#ifdef MITE_DEBUG
mite_print_chsr(m_status);
#endif
- /* printk("mite_bytes_transferred: %d\n",
- mite_bytes_transferred(mite,DI_DMA_CHAN)); */
/* mite_dump_regs(mite); */
if (m_status & CHSR_INT) {
@@ -617,7 +531,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
}
#if 0
else {
- printk("ni_pcidio: unknown interrupt\n");
+ DPRINTK("ni_pcidio: unknown interrupt\n");
async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
writeb(0x00,
devpriv->mite->daq_io_addr +
@@ -648,38 +562,47 @@ out:
}
#ifdef DEBUG_FLAGS
+static const char *bit_set_string(unsigned int bits, unsigned int bit,
+ const char *const strings[])
+{
+ return (bits & (1U << bit)) ? strings[bit] : "";
+}
+
static const char *const flags_strings[] = {
- "TransferReady", "CountExpired", "2", "3",
- "4", "Waited", "PrimaryTC", "SecondaryTC",
+ " TransferReady", " CountExpired", " 2", " 3",
+ " 4", " Waited", " PrimaryTC", " SecondaryTC",
};
+
static void ni_pcidio_print_flags(unsigned int flags)
{
- int i;
-
- printk(KERN_INFO "group_1_flags:");
- for (i = 7; i >= 0; i--) {
- if (flags & (1 << i))
- printk(" %s", flags_strings[i]);
- }
- printk("\n");
+ pr_debug("group_1_flags:%s%s%s%s%s%s%s%s\n",
+ bit_set_string(flags, 7, flags_strings),
+ bit_set_string(flags, 6, flags_strings),
+ bit_set_string(flags, 5, flags_strings),
+ bit_set_string(flags, 4, flags_strings),
+ bit_set_string(flags, 3, flags_strings),
+ bit_set_string(flags, 2, flags_strings),
+ bit_set_string(flags, 1, flags_strings),
+ bit_set_string(flags, 0, flags_strings));
}
-static char *status_strings[] = {
- "DataLeft1", "Reserved1", "Req1", "StopTrig1",
- "DataLeft2", "Reserved2", "Req2", "StopTrig2",
+static const char *const status_strings[] = {
+ " DataLeft1", " Reserved1", " Req1", " StopTrig1",
+ " DataLeft2", " Reserved2", " Req2", " StopTrig2",
};
static void ni_pcidio_print_status(unsigned int flags)
{
- int i;
-
- printk(KERN_INFO "group_status:");
- for (i = 7; i >= 0; i--) {
- if (flags & (1 << i))
- printk(" %s", status_strings[i]);
- }
- printk("\n");
+ pr_debug("group_status:%s%s%s%s%s%s%s%s\n",
+ bit_set_string(flags, 7, status_strings),
+ bit_set_string(flags, 6, status_strings),
+ bit_set_string(flags, 5, status_strings),
+ bit_set_string(flags, 4, status_strings),
+ bit_set_string(flags, 3, status_strings),
+ bit_set_string(flags, 2, status_strings),
+ bit_set_string(flags, 1, status_strings),
+ bit_set_string(flags, 0, status_strings));
}
#endif
@@ -761,45 +684,25 @@ static int ni_pcidio_cmdtest(struct comedi_device *dev,
int err = 0;
int tmp;
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_INT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_NOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_TIMER | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
+ 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 2: make sure trigger sources are unique and mutually
- compatible */
+ /* Step 2a : make sure trigger sources are unique */
- /* note that mutual compatibility is not an issue here */
- if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_INT)
- err++;
- if (cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_EXT)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -1065,10 +968,12 @@ static int ni_pcidio_change(struct comedi_device *dev,
}
static int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index,
- u8 *data, int data_len)
+ const u8 *data, size_t data_len)
{
static const int timeout = 1000;
- int i, j;
+ int i;
+ size_t j;
+
writew(0x80 | fpga_index,
devpriv->mite->daq_io_addr + Firmware_Control_Register);
writew(0xc0 | fpga_index,
@@ -1079,8 +984,9 @@ static int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index,
udelay(1);
}
if (i == timeout) {
- printk(KERN_WARNING "ni_pcidio: failed to load fpga %i, "
- "waiting for status 0x2\n", fpga_index);
+ dev_warn(dev->class_dev,
+ "ni_pcidio: failed to load fpga %i, waiting for status 0x2\n",
+ fpga_index);
return -EIO;
}
writew(0x80 | fpga_index,
@@ -1091,8 +997,9 @@ static int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index,
udelay(1);
}
if (i == timeout) {
- printk(KERN_WARNING "ni_pcidio: failed to load fpga %i, "
- "waiting for status 0x3\n", fpga_index);
+ dev_warn(dev->class_dev,
+ "ni_pcidio: failed to load fpga %i, waiting for status 0x3\n",
+ fpga_index);
return -EIO;
}
for (j = 0; j + 1 < data_len;) {
@@ -1107,8 +1014,9 @@ static int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index,
udelay(1);
}
if (i == timeout) {
- printk("ni_pcidio: failed to load word into fpga %i\n",
- fpga_index);
+ dev_warn(dev->class_dev,
+ "ni_pcidio: failed to load word into fpga %i\n",
+ fpga_index);
return -EIO;
}
if (need_resched())
@@ -1147,85 +1055,72 @@ static void pci_6534_init_main_fpga(struct comedi_device *dev)
writel(0, devpriv->mite->daq_io_addr + FPGA_SCBMS_Counter_Register);
}
-static int pci_6534_upload_firmware(struct comedi_device *dev, int options[])
+static int pci_6534_upload_firmware(struct comedi_device *dev)
{
int ret;
- void *main_fpga_data, *scarab_a_data, *scarab_b_data;
- int main_fpga_data_len, scarab_a_data_len, scarab_b_data_len;
+ 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 n;
- if (options[COMEDI_DEVCONF_AUX_DATA_LENGTH] == 0)
- return 0;
ret = pci_6534_reset_fpgas(dev);
if (ret < 0)
return ret;
- main_fpga_data = comedi_aux_data(options, 0);
- main_fpga_data_len = options[COMEDI_DEVCONF_AUX_DATA0_LENGTH];
- ret = pci_6534_load_fpga(dev, 2, main_fpga_data, main_fpga_data_len);
- if (ret < 0)
- return ret;
- pci_6534_init_main_fpga(dev);
- scarab_a_data = comedi_aux_data(options, 1);
- scarab_a_data_len = options[COMEDI_DEVCONF_AUX_DATA1_LENGTH];
- ret = pci_6534_load_fpga(dev, 0, scarab_a_data, scarab_a_data_len);
- if (ret < 0)
- return ret;
- scarab_b_data = comedi_aux_data(options, 2);
- scarab_b_data_len = options[COMEDI_DEVCONF_AUX_DATA2_LENGTH];
- ret = pci_6534_load_fpga(dev, 1, scarab_b_data, scarab_b_data_len);
- if (ret < 0)
- return ret;
- return 0;
+ /* 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);
+ }
+ if (ret < 0)
+ break;
+ }
+ return ret;
}
-static int nidio_find_device(struct comedi_device *dev, int bus, int slot)
+static const struct nidio_board *
+nidio_find_boardinfo(struct pci_dev *pcidev)
{
- struct mite_struct *mite;
- int i;
-
- for (mite = mite_devices; mite; mite = mite->next) {
- if (mite->used)
- continue;
- if (bus || slot) {
- if (bus != mite->pcidev->bus->number ||
- slot != PCI_SLOT(mite->pcidev->devfn))
- continue;
- }
- for (i = 0; i < n_nidio_boards; i++) {
- if (mite_device_id(mite) == nidio_boards[i].dev_id) {
- dev->board_ptr = nidio_boards + i;
- devpriv->mite = mite;
+ unsigned int dev_id = pcidev->device;
+ unsigned int n;
- return 0;
- }
- }
+ for (n = 0; n < ARRAY_SIZE(nidio_boards); n++) {
+ const struct nidio_board *board = &nidio_boards[n];
+ if (board->dev_id == dev_id)
+ return board;
}
- printk(KERN_WARNING "no device found\n");
- mite_list_devices();
- return -EIO;
+ return NULL;
}
-static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int __devinit nidio_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
struct comedi_subdevice *s;
- int i;
int ret;
- int n_subdevices;
unsigned int irq;
- printk(KERN_INFO "comedi%d: nidio:", dev->minor);
-
ret = alloc_private(dev, sizeof(struct nidio96_private));
if (ret < 0)
return ret;
spin_lock_init(&devpriv->mite_channel_lock);
- ret = nidio_find_device(dev, it->options[0], it->options[1]);
- if (ret < 0)
- return ret;
+ dev->board_ptr = nidio_find_boardinfo(pcidev);
+ if (!dev->board_ptr)
+ return -ENODEV;
+ devpriv->mite = mite_alloc(pcidev);
+ if (!devpriv->mite)
+ return -ENOMEM;
ret = mite_setup(devpriv->mite);
if (ret < 0) {
- printk(KERN_WARNING "error setting up mite\n");
+ dev_warn(dev->class_dev, "error setting up mite\n");
return ret;
}
comedi_set_hw_dev(dev, &devpriv->mite->pcidev->dev);
@@ -1235,84 +1130,60 @@ static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
dev->board_name = this_board->name;
irq = mite_irq(devpriv->mite);
- printk(KERN_INFO " %s", dev->board_name);
if (this_board->uses_firmware) {
- ret = pci_6534_upload_firmware(dev, it->options);
+ ret = pci_6534_upload_firmware(dev);
if (ret < 0)
return ret;
}
- if (!this_board->is_diodaq)
- n_subdevices = this_board->n_8255;
- else
- n_subdevices = 1;
- ret = comedi_alloc_subdevices(dev, n_subdevices);
+ ret = comedi_alloc_subdevices(dev, 1);
if (ret)
return ret;
- if (!this_board->is_diodaq) {
- for (i = 0; i < this_board->n_8255; i++) {
- subdev_8255_init(dev, dev->subdevices + i,
- nidio96_8255_cb,
- (unsigned long)(devpriv->mite->
- daq_io_addr +
- NIDIO_8255_BASE(i)));
- }
- } else {
-
- printk(KERN_INFO " rev=%d",
- readb(devpriv->mite->daq_io_addr + Chip_Version));
-
- s = dev->subdevices + 0;
-
- dev->read_subdev = s;
- s->type = COMEDI_SUBD_DIO;
- s->subdev_flags =
- SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_PACKED |
- SDF_CMD_READ;
- s->n_chan = 32;
- s->range_table = &range_digital;
- s->maxdata = 1;
- s->insn_config = &ni_pcidio_insn_config;
- s->insn_bits = &ni_pcidio_insn_bits;
- s->do_cmd = &ni_pcidio_cmd;
- s->do_cmdtest = &ni_pcidio_cmdtest;
- s->cancel = &ni_pcidio_cancel;
- s->len_chanlist = 32; /* XXX */
- s->buf_change = &ni_pcidio_change;
- s->async_dma_dir = DMA_BIDIRECTIONAL;
- s->poll = &ni_pcidio_poll;
-
- writel(0, devpriv->mite->daq_io_addr + Port_IO(0));
- writel(0, devpriv->mite->daq_io_addr + Port_Pin_Directions(0));
- writel(0, devpriv->mite->daq_io_addr + Port_Pin_Mask(0));
-
- /* disable interrupts on board */
- writeb(0x00,
- devpriv->mite->daq_io_addr +
- Master_DMA_And_Interrupt_Control);
-
- ret = request_irq(irq, nidio_interrupt, IRQF_SHARED,
- "ni_pcidio", dev);
- if (ret < 0)
- printk(KERN_WARNING " irq not available");
+ dev_info(dev->class_dev, "%s rev=%d\n", dev->board_name,
+ readb(devpriv->mite->daq_io_addr + Chip_Version));
+
+ s = &dev->subdevices[0];
+
+ dev->read_subdev = s;
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags =
+ SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_PACKED |
+ SDF_CMD_READ;
+ s->n_chan = 32;
+ s->range_table = &range_digital;
+ s->maxdata = 1;
+ s->insn_config = &ni_pcidio_insn_config;
+ s->insn_bits = &ni_pcidio_insn_bits;
+ s->do_cmd = &ni_pcidio_cmd;
+ s->do_cmdtest = &ni_pcidio_cmdtest;
+ s->cancel = &ni_pcidio_cancel;
+ s->len_chanlist = 32; /* XXX */
+ s->buf_change = &ni_pcidio_change;
+ s->async_dma_dir = DMA_BIDIRECTIONAL;
+ s->poll = &ni_pcidio_poll;
+
+ writel(0, devpriv->mite->daq_io_addr + Port_IO(0));
+ writel(0, devpriv->mite->daq_io_addr + Port_Pin_Directions(0));
+ writel(0, devpriv->mite->daq_io_addr + Port_Pin_Mask(0));
+
+ /* disable interrupts on board */
+ writeb(0x00,
+ devpriv->mite->daq_io_addr +
+ Master_DMA_And_Interrupt_Control);
- dev->irq = irq;
- }
+ ret = request_irq(irq, nidio_interrupt, IRQF_SHARED,
+ "ni_pcidio", dev);
+ if (ret < 0)
+ dev_warn(dev->class_dev, "irq not available\n");
- printk("\n");
+ dev->irq = irq;
return 0;
}
static void nidio_detach(struct comedi_device *dev)
{
- int i;
-
- if (this_board && !this_board->is_diodaq) {
- for (i = 0; i < this_board->n_8255; i++)
- subdev_8255_cleanup(dev, dev->subdevices + i);
- }
if (dev->irq)
free_irq(dev->irq, dev);
if (devpriv) {
@@ -1320,15 +1191,17 @@ static void nidio_detach(struct comedi_device *dev)
mite_free_ring(devpriv->di_mite_ring);
devpriv->di_mite_ring = NULL;
}
- if (devpriv->mite)
+ if (devpriv->mite) {
mite_unsetup(devpriv->mite);
+ mite_free(devpriv->mite);
+ }
}
}
static struct comedi_driver ni_pcidio_driver = {
.driver_name = "ni_pcidio",
.module = THIS_MODULE,
- .attach = nidio_attach,
+ .attach_pci = nidio_attach_pci,
.detach = nidio_detach,
};
@@ -1347,13 +1220,6 @@ static DEFINE_PCI_DEVICE_TABLE(ni_pcidio_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1150) },
{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1320) },
{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x12b0) },
- { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x0160) },
- { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1630) },
- { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x13c0) },
- { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x0400) },
- { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1250) },
- { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x17d0) },
- { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1800) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, ni_pcidio_pci_table);
diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
index 89f4d43c6d08..f284a90720ec 100644
--- a/drivers/staging/comedi/drivers/ni_pcimio.c
+++ b/drivers/staging/comedi/drivers/ni_pcimio.c
@@ -1188,8 +1188,6 @@ static const struct ni_board_struct ni_boards[] = {
},
};
-#define n_pcimio_boards ARRAY_SIZE(ni_boards)
-
struct ni_private {
NI_PRIVATE_COMMON};
#define devpriv ((struct ni_private *)dev->private)
@@ -1502,7 +1500,6 @@ static uint32_t m_series_stc_readl(struct comedi_device *dev, int reg)
#include "ni_mio_common.c"
-static int pcimio_find_device(struct comedi_device *dev, int bus, int slot);
static int pcimio_ai_change(struct comedi_device *dev,
struct comedi_subdevice *s, unsigned long new_size);
static int pcimio_ao_change(struct comedi_device *dev,
@@ -1584,24 +1581,45 @@ static void pcimio_detach(struct comedi_device *dev)
mite_free_ring(devpriv->cdo_mite_ring);
mite_free_ring(devpriv->gpct_mite_ring[0]);
mite_free_ring(devpriv->gpct_mite_ring[1]);
- if (devpriv->mite)
+ if (devpriv->mite) {
mite_unsetup(devpriv->mite);
+ mite_free(devpriv->mite);
+ }
}
}
-static int pcimio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static const struct ni_board_struct *
+pcimio_find_boardinfo(struct pci_dev *pcidev)
+{
+ unsigned int device_id = pcidev->device;
+ unsigned int n;
+
+ for (n = 0; n < ARRAY_SIZE(ni_boards); n++) {
+ const struct ni_board_struct *board = &ni_boards[n];
+ if (board->device_id == device_id)
+ return board;
+ }
+ return NULL;
+}
+
+static int __devinit pcimio_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
int ret;
- dev_info(dev->class_dev, "ni_pcimio: attach\n");
+ dev_info(dev->class_dev, "ni_pcimio: attach %s\n", pci_name(pcidev));
ret = ni_alloc_private(dev);
if (ret < 0)
return ret;
- ret = pcimio_find_device(dev, it->options[0], it->options[1]);
- if (ret < 0)
- return ret;
+ dev->board_ptr = pcimio_find_boardinfo(pcidev);
+ if (!dev->board_ptr)
+ return -ENODEV;
+
+ devpriv->mite = mite_alloc(pcidev);
+ if (!devpriv->mite)
+ return -ENOMEM;
dev_dbg(dev->class_dev, "%s\n", boardtype.name);
dev->board_name = boardtype.name;
@@ -1659,7 +1677,7 @@ static int pcimio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
}
- ret = ni_E_init(dev, it);
+ ret = ni_E_init(dev);
if (ret < 0)
return ret;
@@ -1672,34 +1690,6 @@ static int pcimio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return ret;
}
-static int pcimio_find_device(struct comedi_device *dev, int bus, int slot)
-{
- struct mite_struct *mite;
- int i;
-
- for (mite = mite_devices; mite; mite = mite->next) {
- if (mite->used)
- continue;
- if (bus || slot) {
- if (bus != mite->pcidev->bus->number ||
- slot != PCI_SLOT(mite->pcidev->devfn))
- continue;
- }
-
- for (i = 0; i < n_pcimio_boards; i++) {
- if (mite_device_id(mite) == ni_boards[i].device_id) {
- dev->board_ptr = ni_boards + i;
- devpriv->mite = mite;
-
- return 0;
- }
- }
- }
- pr_warn("no device found\n");
- mite_list_devices();
- return -EIO;
-}
-
static int pcimio_ai_change(struct comedi_device *dev,
struct comedi_subdevice *s, unsigned long new_size)
{
@@ -1765,7 +1755,7 @@ static int pcimio_dio_change(struct comedi_device *dev,
static struct comedi_driver ni_pcimio_driver = {
.driver_name = "ni_pcimio",
.module = THIS_MODULE,
- .attach = pcimio_attach,
+ .attach_pci = pcimio_attach_pci,
.detach = pcimio_detach,
};
@@ -1844,7 +1834,7 @@ static struct pci_driver ni_pcimio_pci_driver = {
.probe = ni_pcimio_pci_probe,
.remove = __devexit_p(ni_pcimio_pci_remove)
};
-module_comedi_pci_driver(ni_pcimio_driver, ni_pcimio_pci_driver)
+module_comedi_pci_driver(ni_pcimio_driver, ni_pcimio_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c
index a9611587460a..8ee93d359bed 100644
--- a/drivers/staging/comedi/drivers/ni_tiocmd.c
+++ b/drivers/staging/comedi/drivers/ni_tiocmd.c
@@ -48,6 +48,7 @@ TODO:
Support use of both banks X and Y
*/
+#include "comedi_fc.h"
#include "ni_tio_internal.h"
#include "mite.h"
@@ -237,61 +238,35 @@ EXPORT_SYMBOL_GPL(ni_tio_cmd);
int ni_tio_cmdtest(struct ni_gpct *counter, struct comedi_cmd *cmd)
{
int err = 0;
- int tmp;
- int sources;
+ unsigned int sources;
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
sources = TRIG_NOW | TRIG_INT | TRIG_OTHER;
if (ni_tio_counting_mode_registers_present(counter->counter_dev))
sources |= TRIG_EXT;
- cmd->start_src &= sources;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_EXT | TRIG_OTHER;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- sources = TRIG_NOW | TRIG_EXT | TRIG_OTHER;
- cmd->convert_src &= sources;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, sources);
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_FOLLOW | TRIG_EXT | TRIG_OTHER);
+ err |= cfc_check_trigger_src(&cmd->convert_src,
+ TRIG_NOW | TRIG_EXT | TRIG_OTHER);
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
if (err)
return 1;
- /* step 2: make sure trigger sources are unique... */
+ /* Step 2a : make sure trigger sources are unique */
+
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+
+ /* Step 2b : and mutually compatible */
- if (cmd->start_src != TRIG_NOW &&
- cmd->start_src != TRIG_INT &&
- cmd->start_src != TRIG_EXT && cmd->start_src != TRIG_OTHER)
- err++;
- if (cmd->scan_begin_src != TRIG_FOLLOW &&
- cmd->scan_begin_src != TRIG_EXT &&
- cmd->scan_begin_src != TRIG_OTHER)
- err++;
- if (cmd->convert_src != TRIG_OTHER &&
- cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW)
- err++;
- if (cmd->stop_src != TRIG_NONE)
- err++;
- /* ... and mutually compatible */
if (cmd->convert_src != TRIG_NOW && cmd->scan_begin_src != TRIG_FOLLOW)
- err++;
+ err |= -EINVAL;
if (err)
return 2;
diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
index bb72d0bc2975..89305a14eb5c 100644
--- a/drivers/staging/comedi/drivers/pcl711.c
+++ b/drivers/staging/comedi/drivers/pcl711.c
@@ -64,6 +64,7 @@ supported.
#include <linux/ioport.h>
#include <linux/delay.h>
+#include "comedi_fc.h"
#include "8253.h"
#define PCL711_SIZE 16
@@ -168,7 +169,7 @@ static irqreturn_t pcl711_interrupt(int irq, void *d)
int data;
struct comedi_device *dev = d;
const struct pcl711_board *board = comedi_board(dev);
- struct comedi_subdevice *s = dev->subdevices + 0;
+ struct comedi_subdevice *s = &dev->subdevices[0];
if (!dev->attached) {
comedi_error(dev, "spurious interrupt");
@@ -266,42 +267,24 @@ static int pcl711_ai_cmdtest(struct comedi_device *dev,
int tmp;
int err = 0;
- /* step 1 */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_NOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_TIMER | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
+ 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 2 */
+ /* Step 2a : make sure trigger sources are unique */
- if (cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_EXT)
- err++;
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -520,7 +503,7 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret < 0)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* AI subdevice */
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_GROUND;
@@ -536,7 +519,7 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->do_cmd = pcl711_ai_cmd;
}
- s++;
+ s = &dev->subdevices[1];
/* AO subdevice */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
@@ -547,7 +530,7 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->insn_write = pcl711_ao_insn;
s->insn_read = pcl711_ao_insn_read;
- s++;
+ s = &dev->subdevices[2];
/* 16-bit digital input */
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
@@ -557,7 +540,7 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->range_table = &range_digital;
s->insn_bits = pcl711_di_insn_bits;
- s++;
+ s = &dev->subdevices[3];
/* 16-bit digital out */
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE;
diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c
index c8fe23ca899d..7b3c4293c01b 100644
--- a/drivers/staging/comedi/drivers/pcl724.c
+++ b/drivers/staging/comedi/drivers/pcl724.c
@@ -99,6 +99,7 @@ static int subdev_8255mapped_cb(int dir, int port, int data,
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;
@@ -161,14 +162,13 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return ret;
for (i = 0; i < dev->n_subdevices; i++) {
+ s = &dev->subdevices[i];
if (board->is_pet48) {
- subdev_8255_init(dev, dev->subdevices + i,
- subdev_8255mapped_cb,
+ subdev_8255_init(dev, s, subdev_8255mapped_cb,
(unsigned long)(dev->iobase +
i * 0x1000));
} else
- subdev_8255_init(dev, dev->subdevices + i,
- subdev_8255_cb,
+ subdev_8255_init(dev, s, subdev_8255_cb,
(unsigned long)(dev->iobase +
SIZE_8255 * i));
}
@@ -179,10 +179,13 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it)
static void pcl724_detach(struct comedi_device *dev)
{
const struct pcl724_board *board = comedi_board(dev);
+ struct comedi_subdevice *s;
int i;
- for (i = 0; i < dev->n_subdevices; i++)
- subdev_8255_cleanup(dev, dev->subdevices + i);
+ for (i = 0; i < dev->n_subdevices; i++) {
+ s = &dev->subdevices[i];
+ subdev_8255_cleanup(dev, s);
+ }
#ifdef PCL724_IRQ
if (dev->irq)
free_irq(dev->irq, dev);
diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c
index d5b60cf7c93f..21fbc1ae1e73 100644
--- a/drivers/staging/comedi/drivers/pcl725.c
+++ b/drivers/staging/comedi/drivers/pcl725.c
@@ -62,7 +62,7 @@ static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* do */
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE;
@@ -71,7 +71,7 @@ static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->insn_bits = pcl725_do_insn;
s->range_table = &range_digital;
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* di */
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
index 2b10f1d83085..07e72de982ac 100644
--- a/drivers/staging/comedi/drivers/pcl726.c
+++ b/drivers/staging/comedi/drivers/pcl726.c
@@ -290,7 +290,7 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* ao */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
@@ -316,7 +316,7 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it)
devpriv->bipolar[i] = 1; /* bipolar range */
}
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* di */
if (!board->have_dio) {
s->type = COMEDI_SUBD_UNUSED;
@@ -330,7 +330,7 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->range_table = &range_digital;
}
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
/* do */
if (!board->have_dio) {
s->type = COMEDI_SUBD_UNUSED;
diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c
index 4675ec57082e..e3de49937452 100644
--- a/drivers/staging/comedi/drivers/pcl730.c
+++ b/drivers/staging/comedi/drivers/pcl730.c
@@ -84,7 +84,7 @@ static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* Isolated do */
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE;
@@ -94,7 +94,7 @@ static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->range_table = &range_digital;
s->private = (void *)PCL730_IDIO_LO;
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* Isolated di */
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
@@ -104,7 +104,7 @@ static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->range_table = &range_digital;
s->private = (void *)PCL730_IDIO_LO;
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
/* TTL do */
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE;
@@ -114,7 +114,7 @@ static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->range_table = &range_digital;
s->private = (void *)PCL730_DIO_LO;
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
/* TTL di */
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
index 578fd8920be1..3cf55ff93083 100644
--- a/drivers/staging/comedi/drivers/pcl812.c
+++ b/drivers/staging/comedi/drivers/pcl812.c
@@ -117,6 +117,7 @@
#include <linux/io.h>
#include <asm/dma.h>
+#include "comedi_fc.h"
#include "8253.h"
/* hardware types of the cards */
@@ -533,49 +534,31 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev,
{
const struct pcl812_board *board = comedi_board(dev);
int err = 0;
+ unsigned int flags;
int tmp, divisor1, divisor2;
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_FOLLOW;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
- tmp = cmd->convert_src;
if (devpriv->use_ext_trg)
- cmd->convert_src &= TRIG_EXT;
+ flags = TRIG_EXT;
else
- cmd->convert_src &= TRIG_TIMER;
-
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
+ flags = TRIG_TIMER;
+ err |= cfc_check_trigger_src(&cmd->convert_src, flags);
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ 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 2: make sure trigger sources are
- * unique and mutually compatible
- */
+ /* Step 2a : make sure trigger sources are unique */
- if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -806,7 +789,7 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
char err = 1;
unsigned int mask, timeout;
struct comedi_device *dev = d;
- struct comedi_subdevice *s = dev->subdevices + 0;
+ struct comedi_subdevice *s = &dev->subdevices[0];
unsigned int next_chan;
s->async->events = 0;
@@ -909,7 +892,7 @@ static void transfer_from_dma_buf(struct comedi_device *dev,
static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d)
{
struct comedi_device *dev = d;
- struct comedi_subdevice *s = dev->subdevices + 0;
+ struct comedi_subdevice *s = &dev->subdevices[0];
unsigned long dma_flags;
int len, bufptr;
short *ptr;
@@ -1267,7 +1250,7 @@ no_dma:
/* analog input */
if (board->n_aichan > 0) {
- s = dev->subdevices + subdev;
+ s = &dev->subdevices[subdev];
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE;
switch (board->board_type) {
@@ -1409,7 +1392,7 @@ no_dma:
/* analog output */
if (board->n_aochan > 0) {
- s = dev->subdevices + subdev;
+ s = &dev->subdevices[subdev];
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
s->n_chan = board->n_aochan;
@@ -1438,7 +1421,7 @@ no_dma:
/* digital input */
if (board->n_dichan > 0) {
- s = dev->subdevices + subdev;
+ s = &dev->subdevices[subdev];
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
s->n_chan = board->n_dichan;
@@ -1451,7 +1434,7 @@ no_dma:
/* digital output */
if (board->n_dochan > 0) {
- s = dev->subdevices + subdev;
+ s = &dev->subdevices[subdev];
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE;
s->n_chan = board->n_dochan;
diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
index ba6911f063cb..0822de058e4d 100644
--- a/drivers/staging/comedi/drivers/pcl816.c
+++ b/drivers/staging/comedi/drivers/pcl816.c
@@ -41,6 +41,7 @@ Configuration Options:
#include <linux/io.h>
#include <asm/dma.h>
+#include "comedi_fc.h"
#include "8253.h"
#define DEBUG(x) x
@@ -258,7 +259,7 @@ static int pcl816_ai_insn_read(struct comedi_device *dev,
static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d)
{
struct comedi_device *dev = d;
- struct comedi_subdevice *s = dev->subdevices + 0;
+ struct comedi_subdevice *s = &dev->subdevices[0];
int low, hi;
int timeout = 50; /* wait max 50us */
@@ -349,7 +350,7 @@ static void transfer_from_dma_buf(struct comedi_device *dev,
static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d)
{
struct comedi_device *dev = d;
- struct comedi_subdevice *s = dev->subdevices + 0;
+ struct comedi_subdevice *s = &dev->subdevices[0];
int len, bufptr, this_dma_buf;
unsigned long dma_flags;
short *ptr;
@@ -458,48 +459,23 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev,
pcl816_cmdtest_out(-1, cmd);
);
- /* step 1: make sure trigger sources are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_FOLLOW;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_EXT | TRIG_TIMER;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ 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_EXT | 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 */
- /*
- * step 2: make sure trigger sources
- * are unique and mutually compatible
- */
-
- if (cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_TIMER) {
- cmd->convert_src = TRIG_TIMER;
- err++;
- }
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
- if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
- err++;
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -1183,7 +1159,7 @@ no_dma:
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
if (board->n_aichan > 0) {
s->type = COMEDI_SUBD_AI;
devpriv->sub_ai = s;
diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
index 34169c16fb92..d4b0859d81f2 100644
--- a/drivers/staging/comedi/drivers/pcl818.c
+++ b/drivers/staging/comedi/drivers/pcl818.c
@@ -107,6 +107,7 @@ A word or two about DMA. Driver support DMA operations at two ways:
#include <linux/io.h>
#include <asm/dma.h>
+#include "comedi_fc.h"
#include "8253.h"
/* #define PCL818_MODE13_AO 1 */
@@ -477,7 +478,7 @@ static int pcl818_do_insn_bits(struct comedi_device *dev,
static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d)
{
struct comedi_device *dev = d;
- struct comedi_subdevice *s = dev->subdevices + 0;
+ struct comedi_subdevice *s = &dev->subdevices[0];
int low;
int timeout = 50; /* wait max 50us */
@@ -536,7 +537,7 @@ conv_finish:
static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
{
struct comedi_device *dev = d;
- struct comedi_subdevice *s = dev->subdevices + 0;
+ struct comedi_subdevice *s = &dev->subdevices[0];
int i, len, bufptr;
unsigned long flags;
short *ptr;
@@ -615,7 +616,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
{
struct comedi_device *dev = d;
- struct comedi_subdevice *s = dev->subdevices + 0;
+ struct comedi_subdevice *s = &dev->subdevices[0];
unsigned long tmp;
unsigned int top1, top2, i, bufptr;
long ofs_dats;
@@ -720,7 +721,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
{
struct comedi_device *dev = d;
- struct comedi_subdevice *s = dev->subdevices + 0;
+ struct comedi_subdevice *s = &dev->subdevices[0];
int i, len, lo;
outb(0, dev->iobase + PCL818_FI_INTCLR); /* clear fifo int request */
@@ -811,7 +812,7 @@ static irqreturn_t interrupt_pcl818(int irq, void *d)
being reprogrammed while a DMA transfer is in
progress.
*/
- struct comedi_subdevice *s = dev->subdevices + 0;
+ struct comedi_subdevice *s = &dev->subdevices[0];
devpriv->ai_act_scan = 0;
devpriv->neverending_ai = 0;
pcl818_ai_cancel(dev, s);
@@ -1261,43 +1262,23 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
int err = 0;
int tmp, divisor1 = 0, divisor2 = 0;
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_FOLLOW;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ 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 | TRIG_EXT);
+ 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 2: make sure trigger sources are unique and mutually compatible */
+ /* Step 2a : make sure trigger sources are unique */
- if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
- if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
- err++;
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -1763,7 +1744,7 @@ no_dma:
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
if (!board->n_aichan_se) {
s->type = COMEDI_SUBD_UNUSED;
} else {
@@ -1829,7 +1810,7 @@ no_dma:
}
}
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
if (!board->n_aochan) {
s->type = COMEDI_SUBD_UNUSED;
} else {
@@ -1862,7 +1843,7 @@ no_dma:
}
}
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
if (!board->n_dichan) {
s->type = COMEDI_SUBD_UNUSED;
} else {
@@ -1875,7 +1856,7 @@ no_dma:
s->insn_bits = pcl818_di_insn_bits;
}
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
if (!board->n_dochan) {
s->type = COMEDI_SUBD_UNUSED;
} else {
diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
index 62c22ccfb780..4102547dc6a8 100644
--- a/drivers/staging/comedi/drivers/pcm3724.c
+++ b/drivers/staging/comedi/drivers/pcm3724.c
@@ -119,6 +119,8 @@ static int compute_buffer(int config, int devno, struct comedi_subdevice *s)
static void do_3724_config(struct comedi_device *dev,
struct comedi_subdevice *s, int chanspec)
{
+ struct comedi_subdevice *s_dio1 = &dev->subdevices[0];
+ struct comedi_subdevice *s_dio2 = &dev->subdevices[1];
int config;
int buffer_config;
unsigned long port_8255_cfg;
@@ -136,10 +138,10 @@ static void do_3724_config(struct comedi_device *dev,
if (!(s->io_bits & 0xff0000))
config |= CR_C_IO;
- buffer_config = compute_buffer(0, 0, dev->subdevices);
- buffer_config = compute_buffer(buffer_config, 1, (dev->subdevices) + 1);
+ buffer_config = compute_buffer(0, 0, s_dio1);
+ buffer_config = compute_buffer(buffer_config, 1, s_dio2);
- if (s == dev->subdevices)
+ if (s == s_dio1)
port_8255_cfg = dev->iobase + _8255_CR;
else
port_8255_cfg = dev->iobase + SIZE_8255 + _8255_CR;
@@ -154,6 +156,7 @@ static void do_3724_config(struct comedi_device *dev,
static void enable_chan(struct comedi_device *dev, struct comedi_subdevice *s,
int chanspec)
{
+ struct comedi_subdevice *s_dio1 = &dev->subdevices[0];
unsigned int mask;
int gatecfg;
struct priv_pcm3724 *priv;
@@ -162,9 +165,9 @@ static void enable_chan(struct comedi_device *dev, struct comedi_subdevice *s,
priv = dev->private;
mask = 1 << CR_CHAN(chanspec);
- if (s == dev->subdevices) /* subdev 0 */
+ if (s == s_dio1)
priv->dio_1 |= mask;
- else /* subdev 1 */
+ else
priv->dio_2 |= mask;
if (priv->dio_1 & 0xff0000)
@@ -231,6 +234,7 @@ static int pcm3724_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
const struct pcm3724_board *board = comedi_board(dev);
+ struct comedi_subdevice *s;
unsigned long iobase;
unsigned int iorange;
int ret, i, n_subdevices;
@@ -263,9 +267,10 @@ static int pcm3724_attach(struct comedi_device *dev,
return ret;
for (i = 0; i < dev->n_subdevices; i++) {
- subdev_8255_init(dev, dev->subdevices + i, subdev_8255_cb,
+ s = &dev->subdevices[i];
+ subdev_8255_init(dev, s, subdev_8255_cb,
(unsigned long)(dev->iobase + SIZE_8255 * i));
- ((dev->subdevices) + i)->insn_config = subdev_3724_insn_config;
+ s->insn_config = subdev_3724_insn_config;
}
return 0;
}
@@ -273,11 +278,14 @@ static int pcm3724_attach(struct comedi_device *dev,
static void pcm3724_detach(struct comedi_device *dev)
{
const struct pcm3724_board *board = comedi_board(dev);
+ struct comedi_subdevice *s;
int i;
if (dev->subdevices) {
- for (i = 0; i < dev->n_subdevices; i++)
- subdev_8255_cleanup(dev, dev->subdevices + i);
+ for (i = 0; i < dev->n_subdevices; i++) {
+ s = &dev->subdevices[i];
+ subdev_8255_cleanup(dev, s);
+ }
}
if (dev->iobase)
release_region(dev->iobase, board->io_range);
diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c
index d65e0bda2c44..067f14d22610 100644
--- a/drivers/staging/comedi/drivers/pcm3730.c
+++ b/drivers/staging/comedi/drivers/pcm3730.c
@@ -72,7 +72,7 @@ static int pcm3730_attach(struct comedi_device *dev,
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE;
s->maxdata = 1;
@@ -81,7 +81,7 @@ static int pcm3730_attach(struct comedi_device *dev,
s->range_table = &range_digital;
s->private = (void *)PCM3730_DOA;
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE;
s->maxdata = 1;
@@ -90,7 +90,7 @@ static int pcm3730_attach(struct comedi_device *dev,
s->range_table = &range_digital;
s->private = (void *)PCM3730_DOB;
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE;
s->maxdata = 1;
@@ -99,7 +99,7 @@ static int pcm3730_attach(struct comedi_device *dev,
s->range_table = &range_digital;
s->private = (void *)PCM3730_DOC;
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
s->maxdata = 1;
@@ -108,7 +108,7 @@ static int pcm3730_attach(struct comedi_device *dev,
s->range_table = &range_digital;
s->private = (void *)PCM3730_DIA;
- s = dev->subdevices + 4;
+ s = &dev->subdevices[4];
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
s->maxdata = 1;
@@ -117,7 +117,7 @@ static int pcm3730_attach(struct comedi_device *dev,
s->range_table = &range_digital;
s->private = (void *)PCM3730_DIB;
- s = dev->subdevices + 5;
+ s = &dev->subdevices[5];
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
s->maxdata = 1;
diff --git a/drivers/staging/comedi/drivers/pcm_common.c b/drivers/staging/comedi/drivers/pcm_common.c
index 474af7bc6c8b..85ee05ece9c8 100644
--- a/drivers/staging/comedi/drivers/pcm_common.c
+++ b/drivers/staging/comedi/drivers/pcm_common.c
@@ -1,60 +1,30 @@
#include "../comedidev.h"
+
+#include "comedi_fc.h"
#include "pcm_common.h"
-/*
- * 'do_cmdtest' function for an 'INTERRUPT' subdevice. This is for
- * the PCM drivers.
- */
int comedi_pcm_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_cmd *cmd)
{
int err = 0;
- unsigned int tmp;
-
- /* step 1: make sure trigger sources are trivially valid */
-
- tmp = cmd->start_src;
- cmd->start_src &= (TRIG_NOW | TRIG_INT);
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_NOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->stop_src;
- cmd->stop_src &= (TRIG_COUNT | TRIG_NONE);
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
+ 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 2: make sure trigger sources are unique and
- * mutually compatible */
+ /* Step 2a : make sure trigger sources are unique */
- /* these tests are true if more than one _src bit is set */
- if ((cmd->start_src & (cmd->start_src - 1)) != 0)
- err++;
- if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
- err++;
- if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
- err++;
- if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
- err++;
- if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
index 54d19c943967..5efeb9205c2e 100644
--- a/drivers/staging/comedi/drivers/pcmad.c
+++ b/drivers/staging/comedi/drivers/pcmad.c
@@ -127,7 +127,7 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it)
dev->board_name = board->name;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | AREF_GROUND;
s->n_chan = 16; /* XXX */
diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
index 291ce7c1bdb1..28af8f6873eb 100644
--- a/drivers/staging/comedi/drivers/pcmda12.c
+++ b/drivers/staging/comedi/drivers/pcmda12.c
@@ -195,7 +195,7 @@ static int pcmda12_attach(struct comedi_device *dev,
if (ret)
return ret;
- s = dev->subdevices;
+ s = &dev->subdevices[0];
s->private = NULL;
s->maxdata = (0x1 << BITS) - 1;
s->range_table = &pcmda12_ranges;
diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
index 3d2e6f01c4b7..a10bf0a2987f 100644
--- a/drivers/staging/comedi/drivers/pcmmio.c
+++ b/drivers/staging/comedi/drivers/pcmmio.c
@@ -526,6 +526,7 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d)
{
int asic, got1 = 0;
struct comedi_device *dev = (struct comedi_device *)d;
+ int i;
for (asic = 0; asic < MAX_ASICS; ++asic) {
if (irq == devpriv->asics[asic].irq) {
@@ -583,9 +584,8 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d)
printk
(KERN_DEBUG "got edge detect interrupt %d asic %d which_chans: %06x\n",
irq, asic, triggered);
- for (s = dev->subdevices + 2;
- s < dev->subdevices + dev->n_subdevices;
- ++s) {
+ for (i = 2; i < dev->n_subdevices; i++) {
+ s = &dev->subdevices[i];
/*
* this is an interrupt subdev,
* and it matches this asic!
@@ -1076,9 +1076,8 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return ret;
/* First, AI */
- sdev_no = 0;
- s = dev->subdevices + sdev_no;
- s->private = devpriv->sprivs + sdev_no;
+ s = &dev->subdevices[0];
+ s->private = &devpriv->sprivs[0];
s->maxdata = (1 << board->ai_bits) - 1;
s->range_table = board->ai_range_table;
s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
@@ -1092,9 +1091,8 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
outb(0, subpriv->iobase + 4 + 3);
/* Next, AO */
- ++sdev_no;
- s = dev->subdevices + sdev_no;
- s->private = devpriv->sprivs + sdev_no;
+ s = &dev->subdevices[1];
+ s->private = &devpriv->sprivs[1];
s->maxdata = (1 << board->ao_bits) - 1;
s->range_table = board->ao_range_table;
s->subdev_flags = SDF_READABLE;
@@ -1108,14 +1106,13 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
outb(0, subpriv->iobase + 3);
outb(0, subpriv->iobase + 4 + 3);
- ++sdev_no;
port = 0;
asic = 0;
- for (; sdev_no < (int)dev->n_subdevices; ++sdev_no) {
+ for (sdev_no = 2; sdev_no < dev->n_subdevices; ++sdev_no) {
int byte_no;
- s = dev->subdevices + sdev_no;
- s->private = devpriv->sprivs + sdev_no;
+ s = &dev->subdevices[sdev_no];
+ s->private = &devpriv->sprivs[sdev_no];
s->maxdata = 1;
s->range_table = &range_digital;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
@@ -1200,15 +1197,6 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
* multiple irqs..
*/
- if (irq[0]) {
- printk(KERN_DEBUG "comedi%d: irq: %u\n", dev->minor, irq[0]);
- if (board->dio_num_asics == 2 && irq[1])
- printk(KERN_DEBUG "comedi%d: second ASIC irq: %u\n",
- dev->minor, irq[1]);
- } else {
- printk(KERN_INFO "comedi%d: (IRQ mode disabled)\n", dev->minor);
- }
-
printk(KERN_INFO "comedi%d: attached\n", dev->minor);
return 1;
diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
index feef3d02f35a..0e32119bc3f9 100644
--- a/drivers/staging/comedi/drivers/pcmuio.c
+++ b/drivers/staging/comedi/drivers/pcmuio.c
@@ -442,7 +442,7 @@ static void pcmuio_stop_intr(struct comedi_device *dev,
subpriv->intr.enabled_mask = 0;
subpriv->intr.active = 0;
- s->async->inttrig = 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);
@@ -456,6 +456,7 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d)
{
int asic, got1 = 0;
struct comedi_device *dev = (struct comedi_device *)d;
+ int i;
for (asic = 0; asic < MAX_ASICS; ++asic) {
if (irq == devpriv->asics[asic].irq) {
@@ -507,9 +508,8 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d)
printk
("PCMUIO DEBUG: got edge detect interrupt %d asic %d which_chans: %06x\n",
irq, asic, triggered);
- for (s = dev->subdevices;
- s < dev->subdevices + dev->n_subdevices;
- ++s) {
+ 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;
@@ -683,7 +683,7 @@ pcmuio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
return -EINVAL;
spin_lock_irqsave(&subpriv->intr.spinlock, flags);
- s->async->inttrig = 0;
+ s->async->inttrig = NULL;
if (subpriv->intr.active)
event = pcmuio_start_intr(dev, s);
@@ -811,8 +811,8 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
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;
+ s = &dev->subdevices[sdev_no];
+ s->private = &devpriv->sprivs[sdev_no];
s->maxdata = 1;
s->range_table = &range_digital;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c
index c253bb9ef335..78dfe167b147 100644
--- a/drivers/staging/comedi/drivers/poc.c
+++ b/drivers/staging/comedi/drivers/poc.c
@@ -164,7 +164,7 @@ static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return -ENOMEM;
/* analog output subdevice */
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
s->type = board->type;
s->n_chan = board->n_chan;
s->maxdata = (1 << board->n_bits) - 1;
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
index a029147c9b69..3e276f7a3380 100644
--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
@@ -56,6 +56,8 @@ Devices: [Quatech] DAQP-208 (daqp), DAQP-308
#include <linux/completion.h>
+#include "comedi_fc.h"
+
/* Maximum number of separate DAQP devices we'll allow */
#define MAX_DEV 4
@@ -456,51 +458,26 @@ static int daqp_ai_cmdtest(struct comedi_device *dev,
int err = 0;
int tmp;
- /* step 1: make sure trigger sources are trivially valid */
-
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER | TRIG_NOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_TIMER | TRIG_FOLLOW);
+ err |= cfc_check_trigger_src(&cmd->convert_src,
+ TRIG_TIMER | TRIG_NOW);
+ 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 2: make sure trigger sources
- * are unique and mutually compatible
- */
+ /* Step 2a : make sure trigger sources are unique */
- /* note that mutual compatibility is not an issue here */
- if (cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_FOLLOW)
- err++;
- if (cmd->convert_src != TRIG_NOW && cmd->convert_src != TRIG_TIMER)
- err++;
- if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
- err++;
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -878,7 +855,7 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
printk(KERN_INFO "comedi%d: attaching daqp%d (io 0x%04lx)\n",
dev->minor, it->options[0], dev->iobase);
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
dev->read_subdev = s;
s->private = local;
s->type = COMEDI_SUBD_AI;
@@ -892,7 +869,7 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->do_cmd = daqp_ai_cmd;
s->cancel = daqp_ai_cancel;
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
dev->write_subdev = s;
s->private = local;
s->type = COMEDI_SUBD_AO;
@@ -903,7 +880,7 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->range_table = &range_daqp_ao;
s->insn_write = daqp_ao_insn_write;
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
s->private = local;
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
@@ -911,7 +888,7 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->len_chanlist = 1;
s->insn_read = daqp_di_insn_read;
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
s->private = local;
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITEABLE;
diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
index 5aa8be1e7b92..41d24b08913b 100644
--- a/drivers/staging/comedi/drivers/rtd520.c
+++ b/drivers/staging/comedi/drivers/rtd520.c
@@ -106,6 +106,8 @@ Configuration options:
#include "../comedidev.h"
+#include "comedi_fc.h"
+
#define DRV_NAME "rtd520"
/*======================================================================
@@ -783,7 +785,7 @@ static irqreturn_t rtd_interrupt(int irq, /* interrupt number (ignored) */
void *d)
{ /* our data *//* cpu context (ignored) */
struct comedi_device *dev = d;
- struct comedi_subdevice *s = dev->subdevices + 0; /* analog in subdevice */
+ struct comedi_subdevice *s = &dev->subdevices[0];
struct rtdPrivate *devpriv = dev->private;
u32 overrun;
u16 status;
@@ -964,7 +966,7 @@ static int rtd_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
/*
cmdtest tests a particular command to see if it is valid.
Using the cmdtest ioctl, a user can create a valid cmd
- and then have it executed by the cmd ioctl (asyncronously).
+ and then have it executed by the cmd ioctl (asynchronously).
cmdtest returns 1,2,3,4 or 0, depending on which tests
the command passes.
@@ -976,52 +978,25 @@ static int rtd_ai_cmdtest(struct comedi_device *dev,
int err = 0;
int tmp;
- /* step 1: make sure trigger sources are trivially valid */
-
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ /* 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_TIMER | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
+ 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 2: make sure trigger sources are unique
- and mutually compatible */
- /* note that mutual compatibility is not an issue here */
- if (cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_EXT) {
- err++;
- }
- if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
- err++;
+ /* Step 2a : make sure trigger sources are unique */
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -1706,7 +1681,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
dev->read_subdev = s;
/* analog input subdevice */
s->type = COMEDI_SUBD_AI;
@@ -1726,7 +1701,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->cancel = rtd_ai_cancel;
/* s->poll = rtd_ai_poll; *//* not ready yet */
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* analog output subdevice */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
@@ -1736,7 +1711,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->insn_write = rtd_ao_winsn;
s->insn_read = rtd_ao_rinsn;
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
/* digital i/o subdevice */
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
@@ -1748,7 +1723,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->insn_config = rtd_dio_insn_config;
/* timer/counter subdevices (not currently supported) */
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
s->type = COMEDI_SUBD_COUNTER;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 3;
diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
index f7fa940d9783..137885b1681a 100644
--- a/drivers/staging/comedi/drivers/rti800.c
+++ b/drivers/staging/comedi/drivers/rti800.c
@@ -360,7 +360,7 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
devpriv->dac1_coding = it->options[8];
devpriv->muxgain_bits = -1;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* ai subdevice */
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_GROUND;
@@ -379,7 +379,7 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
break;
}
- s++;
+ s = &dev->subdevices[1];
if (board->has_ao) {
/* ao subdevice (only on rti815) */
s->type = COMEDI_SUBD_AO;
@@ -409,7 +409,7 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->type = COMEDI_SUBD_UNUSED;
}
- s++;
+ s = &dev->subdevices[2];
/* di */
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
@@ -418,7 +418,7 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->maxdata = 1;
s->range_table = &range_digital;
- s++;
+ s = &dev->subdevices[3];
/* do */
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE;
@@ -429,7 +429,7 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* don't yet know how to deal with counter/timers */
#if 0
- s++;
+ s = &dev->subdevices[4];
/* do */
s->type = COMEDI_SUBD_TIMER;
#endif
diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c
index fc16508181d4..3f9d0278be50 100644
--- a/drivers/staging/comedi/drivers/rti802.c
+++ b/drivers/staging/comedi/drivers/rti802.c
@@ -111,7 +111,7 @@ static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret)
return ret;
- s = dev->subdevices;
+ s = &dev->subdevices[0];
/* ao subdevice */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
index 737a194dfce3..a1e256293bd6 100644
--- a/drivers/staging/comedi/drivers/s526.c
+++ b/drivers/staging/comedi/drivers/s526.c
@@ -83,36 +83,6 @@ comedi_config /dev/comedi0 s526 0x2C0,0x3
#define REG_EED 0x32
#define REG_EEC 0x34
-static const int s526_ports[] = {
- REG_TCR,
- REG_WDC,
- REG_DAC,
- REG_ADC,
- REG_ADD,
- REG_DIO,
- REG_IER,
- REG_ISR,
- REG_MSC,
- REG_C0L,
- REG_C0H,
- REG_C0M,
- REG_C0C,
- REG_C1L,
- REG_C1H,
- REG_C1M,
- REG_C1C,
- REG_C2L,
- REG_C2H,
- REG_C2M,
- REG_C2C,
- REG_C3L,
- REG_C3H,
- REG_C3M,
- REG_C3C,
- REG_EED,
- REG_EEC
-};
-
struct counter_mode_register_t {
#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned short coutSource:1;
@@ -148,122 +118,48 @@ union cmReg {
unsigned short value;
};
-#define MAX_GPCT_CONFIG_DATA 6
-
-/* Different Application Classes for GPCT Subdevices */
-/* The list is not exhaustive and needs discussion! */
-enum S526_GPCT_APP_CLASS {
- CountingAndTimeMeasurement,
- SinglePulseGeneration,
- PulseTrainGeneration,
- PositionMeasurement,
- Miscellaneous
-};
-
-/* Config struct for different GPCT subdevice Application Classes and
- their options
-*/
-struct s526GPCTConfig {
- enum S526_GPCT_APP_CLASS app;
- int data[MAX_GPCT_CONFIG_DATA];
-};
-
-/*
- * 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.
- */
-struct s526_board {
- const char *name;
- int gpct_chans;
- int gpct_bits;
- int ad_chans;
- int ad_bits;
- int da_chans;
- int da_bits;
- int have_dio;
-};
-
-static const struct s526_board s526_boards[] = {
- {
- .name = "s526",
- .gpct_chans = 4,
- .gpct_bits = 24,
- .ad_chans = 8,
- .ad_bits = 16,
- .da_chans = 4,
- .da_bits = 16,
- .have_dio = 1,
- }
-};
-
-#define ADDR_REG(reg) (dev->iobase + (reg))
-#define ADDR_CHAN_REG(reg, chan) (dev->iobase + (reg) + (chan) * 8)
-
-/* 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 s526_private {
unsigned int ao_readback[2];
- struct s526GPCTConfig s526_gpct_config[4];
- unsigned short s526_ai_config;
+ unsigned int gpct_config[4];
+ unsigned short ai_config;
};
-/*
- * most drivers define the following macro to make it easy to
- * access the private structure.
- */
-#define devpriv ((struct s526_private *)dev->private)
-
static int s526_gpct_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
unsigned int *data)
{
- int i; /* counts the Data */
- int counter_channel = CR_CHAN(insn->chanspec);
- unsigned short datalow;
- unsigned short datahigh;
-
- /* Check if (n > 0) */
- if (insn->n <= 0) {
- printk(KERN_ERR "s526: INSN_READ: n should be > 0\n");
- return -EINVAL;
- }
- /* Read the low word first */
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned long chan_iobase = dev->iobase + chan * 8;
+ unsigned int lo;
+ unsigned int hi;
+ int i;
+
for (i = 0; i < insn->n; i++) {
- datalow = inw(ADDR_CHAN_REG(REG_C0L, counter_channel));
- datahigh = inw(ADDR_CHAN_REG(REG_C0H, counter_channel));
- data[i] = (int)(datahigh & 0x00FF);
- data[i] = (data[i] << 16) | (datalow & 0xFFFF);
- /* printk("s526 GPCT[%d]: %x(0x%04x, 0x%04x)\n",
- counter_channel, data[i], datahigh, datalow); */
+ /* Read the low word first */
+ lo = inw(chan_iobase + REG_C0L) & 0xffff;
+ hi = inw(chan_iobase + REG_C0H) & 0xff;
+
+ data[i] = (hi << 16) | lo;
}
- return i;
+
+ return insn->n;
}
static int s526_gpct_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- int subdev_channel = CR_CHAN(insn->chanspec); /* Unpack chanspec */
- int i;
- short value;
+ struct s526_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned long chan_iobase = dev->iobase + chan * 8;
+ unsigned int val;
union cmReg cmReg;
- /* printk("s526: GPCT_INSN_CONFIG: Configuring Channel %d\n",
- subdev_channel); */
-
- for (i = 0; i < MAX_GPCT_CONFIG_DATA; i++) {
- devpriv->s526_gpct_config[subdev_channel].data[i] =
- insn->data[i];
-/* printk("data[%d]=%x\n", i, insn->data[i]); */
- }
-
/* Check what type of Counter the user requested, data[0] contains */
/* the Application type */
- switch (insn->data[0]) {
+ switch (data[0]) {
case INSN_CONFIG_GPCT_QUADRATURE_ENCODER:
/*
data[0]: Application Type
@@ -271,9 +167,7 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
data[2]: Pre-load Register Value
data[3]: Conter Control Register
*/
- printk(KERN_INFO "s526: GPCT_INSN_CONFIG: Configuring Encoder\n");
- devpriv->s526_gpct_config[subdev_channel].app =
- PositionMeasurement;
+ devpriv->gpct_config[chan] = data[0];
#if 0
/* Example of Counter Application */
@@ -290,34 +184,32 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
cmReg.reg.preloadRegSel = 0; /* PR0 */
cmReg.reg.reserved = 0;
- outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+ outw(cmReg.value, chan_iobase + REG_C0M);
- outw(0x0001, ADDR_CHAN_REG(REG_C0H, subdev_channel));
- outw(0x3C68, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ outw(0x0001, chan_iobase + REG_C0H);
+ outw(0x3C68, chan_iobase + REG_C0L);
/* Reset the counter */
- outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));
+ outw(0x8000, chan_iobase + REG_C0C);
/* Load the counter from PR0 */
- outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));
+ outw(0x4000, chan_iobase + REG_C0C);
/* Reset RCAP (fires one-shot) */
- outw(0x0008, ADDR_CHAN_REG(REG_C0C, subdev_channel));
+ outw(0x0008, chan_iobase + REG_C0C);
#endif
#if 1
/* Set Counter Mode Register */
- cmReg.value = insn->data[1] & 0xFFFF;
-
-/* printk("s526: Counter Mode register=%x\n", cmReg.value); */
- outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+ cmReg.value = data[1] & 0xffff;
+ outw(cmReg.value, chan_iobase + REG_C0M);
/* Reset the counter if it is software preload */
if (cmReg.reg.autoLoadResetRcap == 0) {
/* Reset the counter */
- outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));
+ outw(0x8000, chan_iobase + REG_C0C);
/* Load the counter from PR0
- * outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));
+ * outw(0x4000, chan_iobase + REG_C0C);
*/
}
#else
@@ -325,47 +217,47 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
cmReg.reg.countDirCtrl = 0;
/* data[1] contains GPCT_X1, GPCT_X2 or GPCT_X4 */
- if (insn->data[1] == GPCT_X2)
+ if (data[1] == GPCT_X2)
cmReg.reg.clockSource = 1;
- else if (insn->data[1] == GPCT_X4)
+ else if (data[1] == GPCT_X4)
cmReg.reg.clockSource = 2;
else
cmReg.reg.clockSource = 0;
/* When to take into account the indexpulse: */
- /*if (insn->data[2] == GPCT_IndexPhaseLowLow) {
- } else if (insn->data[2] == GPCT_IndexPhaseLowHigh) {
- } else if (insn->data[2] == GPCT_IndexPhaseHighLow) {
- } else if (insn->data[2] == GPCT_IndexPhaseHighHigh) {
+ /*if (data[2] == GPCT_IndexPhaseLowLow) {
+ } else if (data[2] == GPCT_IndexPhaseLowHigh) {
+ } else if (data[2] == GPCT_IndexPhaseHighLow) {
+ } else if (data[2] == GPCT_IndexPhaseHighHigh) {
}*/
/* Take into account the index pulse? */
- if (insn->data[3] == GPCT_RESET_COUNTER_ON_INDEX)
+ if (data[3] == GPCT_RESET_COUNTER_ON_INDEX)
/* Auto load with INDEX^ */
cmReg.reg.autoLoadResetRcap = 4;
/* Set Counter Mode Register */
- cmReg.value = (short)(insn->data[1] & 0xFFFF);
- outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+ cmReg.value = data[1] & 0xffff;
+ outw(cmReg.value, chan_iobase + REG_C0M);
/* Load the pre-load register high word */
- value = (short)((insn->data[2] >> 16) & 0xFFFF);
- outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
+ val = (data[2] >> 16) & 0xffff;
+ outw(val, chan_iobase + REG_C0H);
/* Load the pre-load register low word */
- value = (short)(insn->data[2] & 0xFFFF);
- outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ val = data[2] & 0xffff;
+ outw(val, chan_iobase + REG_C0L);
/* Write the Counter Control Register */
- if (insn->data[3] != 0) {
- value = (short)(insn->data[3] & 0xFFFF);
- outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
+ if (data[3]) {
+ val = data[3] & 0xffff;
+ outw(val, chan_iobase + REG_C0C);
}
/* Reset the counter if it is software preload */
if (cmReg.reg.autoLoadResetRcap == 0) {
/* Reset the counter */
- outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));
+ outw(0x8000, chan_iobase + REG_C0C);
/* Load the counter from PR0 */
- outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));
+ outw(0x4000, chan_iobase + REG_C0C);
}
#endif
break;
@@ -378,40 +270,38 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
data[3]: Pre-load Register 1 Value
data[4]: Conter Control Register
*/
- printk(KERN_INFO "s526: GPCT_INSN_CONFIG: Configuring SPG\n");
- devpriv->s526_gpct_config[subdev_channel].app =
- SinglePulseGeneration;
+ devpriv->gpct_config[chan] = data[0];
/* Set Counter Mode Register */
- cmReg.value = (short)(insn->data[1] & 0xFFFF);
+ cmReg.value = data[1] & 0xffff;
cmReg.reg.preloadRegSel = 0; /* PR0 */
- outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+ outw(cmReg.value, chan_iobase + REG_C0M);
/* Load the pre-load register 0 high word */
- value = (short)((insn->data[2] >> 16) & 0xFFFF);
- outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
+ val = (data[2] >> 16) & 0xffff;
+ outw(val, chan_iobase + REG_C0H);
/* Load the pre-load register 0 low word */
- value = (short)(insn->data[2] & 0xFFFF);
- outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ val = data[2] & 0xffff;
+ outw(val, chan_iobase + REG_C0L);
/* Set Counter Mode Register */
- cmReg.value = (short)(insn->data[1] & 0xFFFF);
+ cmReg.value = data[1] & 0xffff;
cmReg.reg.preloadRegSel = 1; /* PR1 */
- outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+ outw(cmReg.value, chan_iobase + REG_C0M);
/* Load the pre-load register 1 high word */
- value = (short)((insn->data[3] >> 16) & 0xFFFF);
- outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
+ val = (data[3] >> 16) & 0xffff;
+ outw(val, chan_iobase + REG_C0H);
/* Load the pre-load register 1 low word */
- value = (short)(insn->data[3] & 0xFFFF);
- outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ val = data[3] & 0xffff;
+ outw(val, chan_iobase + REG_C0L);
/* Write the Counter Control Register */
- if (insn->data[4] != 0) {
- value = (short)(insn->data[4] & 0xFFFF);
- outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
+ if (data[4]) {
+ val = data[4] & 0xffff;
+ outw(val, chan_iobase + REG_C0C);
}
break;
@@ -423,45 +313,42 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
data[3]: Pre-load Register 1 Value
data[4]: Conter Control Register
*/
- printk(KERN_INFO "s526: GPCT_INSN_CONFIG: Configuring PTG\n");
- devpriv->s526_gpct_config[subdev_channel].app =
- PulseTrainGeneration;
+ devpriv->gpct_config[chan] = data[0];
/* Set Counter Mode Register */
- cmReg.value = (short)(insn->data[1] & 0xFFFF);
+ cmReg.value = data[1] & 0xffff;
cmReg.reg.preloadRegSel = 0; /* PR0 */
- outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+ outw(cmReg.value, chan_iobase + REG_C0M);
/* Load the pre-load register 0 high word */
- value = (short)((insn->data[2] >> 16) & 0xFFFF);
- outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
+ val = (data[2] >> 16) & 0xffff;
+ outw(val, chan_iobase + REG_C0H);
/* Load the pre-load register 0 low word */
- value = (short)(insn->data[2] & 0xFFFF);
- outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ val = data[2] & 0xffff;
+ outw(val, chan_iobase + REG_C0L);
/* Set Counter Mode Register */
- cmReg.value = (short)(insn->data[1] & 0xFFFF);
+ cmReg.value = data[1] & 0xffff;
cmReg.reg.preloadRegSel = 1; /* PR1 */
- outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+ outw(cmReg.value, chan_iobase + REG_C0M);
/* Load the pre-load register 1 high word */
- value = (short)((insn->data[3] >> 16) & 0xFFFF);
- outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
+ val = (data[3] >> 16) & 0xffff;
+ outw(val, chan_iobase + REG_C0H);
/* Load the pre-load register 1 low word */
- value = (short)(insn->data[3] & 0xFFFF);
- outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ val = data[3] & 0xffff;
+ outw(val, chan_iobase + REG_C0L);
/* Write the Counter Control Register */
- if (insn->data[4] != 0) {
- value = (short)(insn->data[4] & 0xFFFF);
- outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
+ if (data[4]) {
+ val = data[4] & 0xffff;
+ outw(val, chan_iobase + REG_C0C);
}
break;
default:
- printk(KERN_ERR "s526: unsupported GPCT_insn_config\n");
return -EINVAL;
break;
}
@@ -470,65 +357,40 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
}
static int s526_gpct_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
unsigned int *data)
{
- int subdev_channel = CR_CHAN(insn->chanspec); /* Unpack chanspec */
- short value;
- union cmReg cmReg;
-
- printk(KERN_INFO "s526: GPCT_INSN_WRITE on channel %d\n",
- subdev_channel);
- cmReg.value = inw(ADDR_CHAN_REG(REG_C0M, subdev_channel));
- printk(KERN_INFO "s526: Counter Mode Register: %x\n", cmReg.value);
- /* Check what Application of Counter this channel is configured for */
- switch (devpriv->s526_gpct_config[subdev_channel].app) {
- case PositionMeasurement:
- printk(KERN_INFO "S526: INSN_WRITE: PM\n");
- outw(0xFFFF & ((*data) >> 16), ADDR_CHAN_REG(REG_C0H,
- subdev_channel));
- outw(0xFFFF & (*data), ADDR_CHAN_REG(REG_C0L, subdev_channel));
- break;
+ struct s526_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned long chan_iobase = dev->iobase + chan * 8;
- case SinglePulseGeneration:
- printk(KERN_INFO "S526: INSN_WRITE: SPG\n");
- outw(0xFFFF & ((*data) >> 16), ADDR_CHAN_REG(REG_C0H,
- subdev_channel));
- outw(0xFFFF & (*data), ADDR_CHAN_REG(REG_C0L, subdev_channel));
- break;
+ inw(chan_iobase + REG_C0M); /* Is this read required? */
- case PulseTrainGeneration:
+ /* Check what Application of Counter this channel is configured for */
+ switch (devpriv->gpct_config[chan]) {
+ case INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR:
/* data[0] contains the PULSE_WIDTH
data[1] contains the PULSE_PERIOD
@pre PULSE_PERIOD > PULSE_WIDTH > 0
The above periods must be expressed as a multiple of the
pulse frequency on the selected source
*/
- printk(KERN_INFO "S526: INSN_WRITE: PTG\n");
- if ((insn->data[1] > insn->data[0]) && (insn->data[0] > 0)) {
- (devpriv->s526_gpct_config[subdev_channel]).data[0] =
- insn->data[0];
- (devpriv->s526_gpct_config[subdev_channel]).data[1] =
- insn->data[1];
- } else {
- printk(KERN_ERR "s526: INSN_WRITE: PTG: Problem with Pulse params -> %d %d\n",
- insn->data[0], insn->data[1]);
+ if ((data[1] <= data[0]) || !data[0])
return -EINVAL;
- }
- value = (short)((*data >> 16) & 0xFFFF);
- outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
- value = (short)(*data & 0xFFFF);
- outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ /* Fall thru to write the PULSE_WIDTH */
+
+ case INSN_CONFIG_GPCT_QUADRATURE_ENCODER:
+ case INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR:
+ outw((data[0] >> 16) & 0xffff, chan_iobase + REG_C0H);
+ outw(data[0] & 0xffff, chan_iobase + REG_C0L);
break;
- default: /* Impossible */
- printk
- ("s526: INSN_WRITE: Functionality %d not implemented yet\n",
- devpriv->s526_gpct_config[subdev_channel].app);
+
+ default:
return -EINVAL;
- break;
}
- /* return the number of samples written */
+
return insn->n;
}
@@ -537,6 +399,7 @@ static int s526_ai_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct s526_private *devpriv = dev->private;
int result = -EINVAL;
if (insn->n < 1)
@@ -552,62 +415,50 @@ static int s526_ai_insn_config(struct comedi_device *dev,
* INSN_READ handler. */
/* Enable ADC interrupt */
- outw(ISR_ADC_DONE, ADDR_REG(REG_IER));
-/* printk("s526: ADC current value: 0x%04x\n", inw(ADDR_REG(REG_ADC))); */
- devpriv->s526_ai_config = (data[0] & 0x3FF) << 5;
+ outw(ISR_ADC_DONE, dev->iobase + REG_IER);
+ devpriv->ai_config = (data[0] & 0x3ff) << 5;
if (data[1] > 0)
- devpriv->s526_ai_config |= 0x8000; /* set the delay */
+ devpriv->ai_config |= 0x8000; /* set the delay */
- devpriv->s526_ai_config |= 0x0001; /* ADC start bit. */
+ devpriv->ai_config |= 0x0001; /* ADC start bit */
return result;
}
-/*
- * "instructions" read/write data in "one-shot" or "software-triggered"
- * mode.
- */
static int s526_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct s526_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
int n, i;
- int chan = CR_CHAN(insn->chanspec);
unsigned short value;
unsigned int d;
unsigned int status;
/* Set configured delay, enable channel for this channel only,
* select "ADC read" channel, set "ADC start" bit. */
- value = (devpriv->s526_ai_config & 0x8000) |
- ((1 << 5) << chan) | (chan << 1) | 0x0001;
+ value = (devpriv->ai_config & 0x8000) |
+ ((1 << 5) << chan) | (chan << 1) | 0x0001;
/* convert n samples */
for (n = 0; n < insn->n; n++) {
/* trigger conversion */
- outw(value, ADDR_REG(REG_ADC));
-/* printk("s526: Wrote 0x%04x to ADC\n", value); */
-/* printk("s526: ADC reg=0x%04x\n", inw(ADDR_REG(REG_ADC))); */
+ outw(value, dev->iobase + REG_ADC);
#define TIMEOUT 100
/* wait for conversion to end */
for (i = 0; i < TIMEOUT; i++) {
- status = inw(ADDR_REG(REG_ISR));
+ status = inw(dev->iobase + REG_ISR);
if (status & ISR_ADC_DONE) {
- outw(ISR_ADC_DONE, ADDR_REG(REG_ISR));
+ outw(ISR_ADC_DONE, dev->iobase + REG_ISR);
break;
}
}
- if (i == TIMEOUT) {
- /* printk() should be used instead of printk()
- * whenever the code can be called from real-time. */
- printk(KERN_ERR "s526: ADC(0x%04x) timeout\n",
- inw(ADDR_REG(REG_ISR)));
+ if (i == TIMEOUT)
return -ETIMEDOUT;
- }
/* read data */
- d = inw(ADDR_REG(REG_ADD));
-/* printk("AI[%d]=0x%04x\n", n, (unsigned short)(d & 0xFFFF)); */
+ d = inw(dev->iobase + REG_ADD);
/* munge data */
data[n] = d ^ 0x8000;
@@ -620,40 +471,30 @@ static int s526_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
static int s526_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
- int i;
- int chan = CR_CHAN(insn->chanspec);
+ struct s526_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
unsigned short val;
+ int i;
-/* printk("s526_ao_winsn\n"); */
val = chan << 1;
-/* outw(val, dev->iobase + REG_DAC); */
- outw(val, ADDR_REG(REG_DAC));
+ outw(val, dev->iobase + REG_DAC);
- /* 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++) {
- /* a typical programming sequence */
- /* write the data to preload register
- * outw(data[i], dev->iobase + REG_ADD);
- */
- /* write the data to preload register */
- outw(data[i], ADDR_REG(REG_ADD));
+ outw(data[i], dev->iobase + REG_ADD);
devpriv->ao_readback[chan] = data[i];
-/* outw(val + 1, dev->iobase + REG_DAC); starts the D/A conversion. */
- outw(val + 1, ADDR_REG(REG_DAC)); /*starts the D/A conversion.*/
+ /* starts the D/A conversion */
+ outw(val + 1, dev->iobase + REG_DAC);
}
- /* return the number of samples read/written */
return i;
}
-/* AO subdevices should have a read insn as well as a write insn.
- * Usually this means copying a value stored in devpriv. */
static int s526_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct s526_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++)
data[i] = devpriv->ao_readback[chan];
@@ -661,30 +502,18 @@ static int s526_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
return i;
}
-/* DIO devices are slightly special. Although it is possible to
- * implement the insn_read/insn_write interface, it is much more
- * useful to applications if you implement the insn_bits interface.
- * This allows packed reading/writing of the DIO channels. The
- * comedi core can convert between insn_bits and insn_read/write */
static int s526_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
- /* The insn data is a mask in data[0] and the new data
- * in data[1], each channel cooresponding to a bit. */
if (data[0]) {
s->state &= ~data[0];
s->state |= data[0] & data[1];
- /* Write out the new digital output lines */
- outw(s->state, ADDR_REG(REG_DIO));
+
+ outw(s->state, dev->iobase + REG_DIO);
}
- /* on return, data[1] contains the value of the digital
- * input and output lines. */
- data[1] = inw(ADDR_REG(REG_DIO)) & 0xFF; /* low 8 bits are the data */
- /* or we could just return the software copy of the output values if
- * it was a purely digital output subdevice */
- /* data[1]=s->state & 0xFF; */
+ data[1] = inw(dev->iobase + REG_DIO) & 0xff;
return insn->n;
}
@@ -693,16 +522,9 @@ static int s526_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
- int chan = CR_CHAN(insn->chanspec);
+ unsigned int chan = CR_CHAN(insn->chanspec);
int group, mask;
- printk(KERN_INFO "S526 DIO insn_config\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. */
-
group = chan >> 2;
mask = 0xF << (group << 2);
switch (data[0]) {
@@ -721,88 +543,60 @@ static int s526_dio_insn_config(struct comedi_device *dev,
default:
return -EINVAL;
}
- outw(s->state, ADDR_REG(REG_DIO));
+ outw(s->state, dev->iobase + REG_DIO);
return 1;
}
static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
- const struct s526_board *board = comedi_board(dev);
+ struct s526_private *devpriv;
struct comedi_subdevice *s;
int iobase;
- int i, n;
int ret;
-/* short value; */
-/* int subdev_channel = 0; */
- union cmReg cmReg;
- printk(KERN_INFO "comedi%d: s526: ", dev->minor);
+ dev->board_name = dev->driver->driver_name;
iobase = it->options[0];
- if (!iobase || !request_region(iobase, S526_IOSIZE, board->name)) {
+ if (!iobase || !request_region(iobase, S526_IOSIZE, dev->board_name)) {
comedi_error(dev, "I/O port conflict");
return -EIO;
}
dev->iobase = iobase;
- printk("iobase=0x%lx\n", dev->iobase);
-
- /*** make it a little quieter, exw, 8/29/06
- for (i = 0; i < S526_NUM_PORTS; i++) {
- printk("0x%02x: 0x%04x\n", ADDR_REG(s526_ports[i]),
- inw(ADDR_REG(s526_ports[i])));
- }
- ***/
-
- dev->board_name = board->name;
-
-/*
- * Allocate the private structure area. alloc_private() is a
- * convenient macro defined in comedidev.h.
- */
- if (alloc_private(dev, sizeof(struct s526_private)) < 0)
- return -ENOMEM;
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret)
+ return ret;
+ devpriv = dev->private;
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* GENERAL-PURPOSE COUNTER/TIME (GPCT) */
s->type = COMEDI_SUBD_COUNTER;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL;
- /* KG: What does SDF_LSAMPL (see multiq3.c) mean? */
- s->n_chan = board->gpct_chans;
+ s->n_chan = 4;
s->maxdata = 0x00ffffff; /* 24 bit counter */
s->insn_read = s526_gpct_rinsn;
s->insn_config = s526_gpct_insn_config;
s->insn_write = s526_gpct_winsn;
- /* Command are not implemented yet, however they are necessary to
- allocate the necessary memory for the comedi_async struct (used
- to trigger the GPCT in case of pulsegenerator function */
- /* s->do_cmd = s526_gpct_cmd; */
- /* s->do_cmdtest = s526_gpct_cmdtest; */
- /* s->cancel = s526_gpct_cancel; */
-
- s = dev->subdevices + 1;
- /* dev->read_subdev=s; */
+ s = &dev->subdevices[1];
/* analog input subdevice */
s->type = COMEDI_SUBD_AI;
- /* we support differential */
s->subdev_flags = SDF_READABLE | SDF_DIFF;
/* channels 0 to 7 are the regular differential inputs */
/* channel 8 is "reference 0" (+10V), channel 9 is "reference 1" (0V) */
s->n_chan = 10;
s->maxdata = 0xffff;
s->range_table = &range_bipolar10;
- s->len_chanlist = 16; /* This is the maximum chanlist length that
- the board can handle */
+ s->len_chanlist = 16;
s->insn_read = s526_ai_rinsn;
s->insn_config = s526_ai_insn_config;
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
/* analog output subdevice */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
@@ -812,105 +606,18 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->insn_write = s526_ao_winsn;
s->insn_read = s526_ao_rinsn;
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
/* digital i/o subdevice */
- if (board->have_dio) {
- s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = 8;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = s526_dio_insn_bits;
- s->insn_config = s526_dio_insn_config;
- } else {
- s->type = COMEDI_SUBD_UNUSED;
- }
-
- printk(KERN_INFO "attached\n");
-
- return 1;
-
-#if 0
- /* Example of Counter Application */
- /* One-shot (software trigger) */
- cmReg.reg.coutSource = 0; /* out RCAP */
- cmReg.reg.coutPolarity = 1; /* Polarity inverted */
- cmReg.reg.autoLoadResetRcap = 1;/* Auto load 0:disabled, 1:enabled */
- cmReg.reg.hwCtEnableSource = 3; /* NOT RCAP */
- cmReg.reg.ctEnableCtrl = 2; /* Hardware */
- cmReg.reg.clockSource = 2; /* Internal */
- cmReg.reg.countDir = 1; /* Down */
- cmReg.reg.countDirCtrl = 1; /* Software */
- cmReg.reg.outputRegLatchCtrl = 0; /* latch on read */
- cmReg.reg.preloadRegSel = 0; /* PR0 */
- cmReg.reg.reserved = 0;
-
- outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
-
- outw(0x0001, ADDR_CHAN_REG(REG_C0H, subdev_channel));
- outw(0x3C68, ADDR_CHAN_REG(REG_C0L, subdev_channel));
-
- /* Reset the counter */
- outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));
- /* Load the counter from PR0 */
- outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));
- /* Reset RCAP (fires one-shot) */
- outw(0x0008, ADDR_CHAN_REG(REG_C0C, subdev_channel));
-
-#else
-
- /* Set Counter Mode Register */
- cmReg.reg.coutSource = 0; /* out RCAP */
- cmReg.reg.coutPolarity = 0; /* Polarity inverted */
- cmReg.reg.autoLoadResetRcap = 0; /* Auto load disabled */
- cmReg.reg.hwCtEnableSource = 2; /* NOT RCAP */
- cmReg.reg.ctEnableCtrl = 1; /* 1: Software, >1 : Hardware */
- cmReg.reg.clockSource = 3; /* x4 */
- cmReg.reg.countDir = 0; /* up */
- cmReg.reg.countDirCtrl = 0; /* quadrature */
- cmReg.reg.outputRegLatchCtrl = 0; /* latch on read */
- cmReg.reg.preloadRegSel = 0; /* PR0 */
- cmReg.reg.reserved = 0;
-
- n = 0;
- printk(KERN_INFO "Mode reg=0x%04x, 0x%04lx\n",
- cmReg.value, ADDR_CHAN_REG(REG_C0M, n));
- outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, n));
- udelay(1000);
- printk(KERN_INFO "Read back mode reg=0x%04x\n",
- inw(ADDR_CHAN_REG(REG_C0M, n)));
-
- /* Load the pre-load register high word */
-/* value = (short) (0x55); */
-/* outw(value, ADDR_CHAN_REG(REG_C0H, n)); */
-
- /* Load the pre-load register low word */
-/* value = (short)(0xaa55); */
-/* outw(value, ADDR_CHAN_REG(REG_C0L, n)); */
-
- /* Write the Counter Control Register */
-/* outw(value, ADDR_CHAN_REG(REG_C0C, 0)); */
-
- /* Reset the counter if it is software preload */
- if (cmReg.reg.autoLoadResetRcap == 0) {
- /* Reset the counter */
- outw(0x8000, ADDR_CHAN_REG(REG_C0C, n));
- /* Load the counter from PR0 */
- outw(0x4000, ADDR_CHAN_REG(REG_C0C, n));
- }
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 8;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = s526_dio_insn_bits;
+ s->insn_config = s526_dio_insn_config;
- outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, n));
- udelay(1000);
- printk(KERN_INFO "Read back mode reg=0x%04x\n",
- inw(ADDR_CHAN_REG(REG_C0M, n)));
+ dev_info(dev->class_dev, "%s attached\n", dev->board_name);
-#endif
- printk(KERN_INFO "Current registres:\n");
-
- for (i = 0; i < S526_NUM_PORTS; i++) {
- printk(KERN_INFO "0x%02lx: 0x%04x\n",
- ADDR_REG(s526_ports[i]), inw(ADDR_REG(s526_ports[i])));
- }
return 1;
}
@@ -925,9 +632,6 @@ static struct comedi_driver s526_driver = {
.module = THIS_MODULE,
.attach = s526_attach,
.detach = s526_detach,
- .board_name = &s526_boards[0].name,
- .offset = sizeof(struct s526_board),
- .num_names = ARRAY_SIZE(s526_boards),
};
module_comedi_driver(s526_driver);
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index f90578e5e727..551d68b7837c 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -32,11 +32,7 @@ Authors: Gianluca Palli <gpalli@deis.unibo.it>,
Updated: Fri, 15 Feb 2008 10:28:42 +0000
Status: experimental
-Configuration options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
- If bus/slot is not specified, the first supported
- PCI device found will be used.
+Configuration options: not applicable, uses PCI auto config
INSN_CONFIG instructions:
analog input:
@@ -82,45 +78,8 @@ INSN_CONFIG instructions:
#define PCI_SUBVENDOR_ID_S626 0x6000
#define PCI_SUBDEVICE_ID_S626 0x0272
-struct s626_board {
- const char *name;
- int vendor_id;
- int device_id;
- int subvendor_id;
- int subdevice_id;
- int ai_chans;
- int ai_bits;
- int ao_chans;
- int ao_bits;
- int dio_chans;
- int dio_banks;
- int enc_chans;
-};
-
-static const struct s626_board s626_boards[] = {
- {
- .name = "s626",
- .vendor_id = PCI_VENDOR_ID_S626,
- .device_id = PCI_DEVICE_ID_S626,
- .subvendor_id = PCI_SUBVENDOR_ID_S626,
- .subdevice_id = PCI_SUBDEVICE_ID_S626,
- .ai_chans = S626_ADC_CHANNELS,
- .ai_bits = 14,
- .ao_chans = S626_DAC_CHANNELS,
- .ao_bits = 13,
- .dio_chans = S626_DIO_CHANNELS,
- .dio_banks = S626_DIO_BANKS,
- .enc_chans = S626_ENCODER_CHANNELS,
- }
-};
-
-#define thisboard ((const struct s626_board *)dev->board_ptr)
-
struct s626_private {
- struct pci_dev *pdev;
void __iomem *base_addr;
- int got_regions;
- short allocatedBuf;
uint8_t ai_cmd_running; /* ai_cmd is running */
uint8_t ai_continous; /* continous acquisition */
int ai_sample_count; /* number of samples to acquire */
@@ -139,9 +98,7 @@ struct s626_private {
/* Pointer to logical adrs of DMA buffer used to hold DAC data. */
uint16_t Dacpol; /* Image of DAC polarity register. */
uint8_t TrimSetpoint[12]; /* Images of TrimDAC setpoints */
- uint16_t ChargeEnabled; /* Image of MISC2 Battery */
/* Charge Enabled (0 or WRMISC2_CHARGE_ENABLE). */
- uint16_t WDInterval; /* Image of MISC2 watchdog interval control bits. */
uint32_t I2CAdrs;
/* I2C device address for onboard EEPROM (board rev dependent). */
/* short I2Cards; */
@@ -1548,56 +1505,28 @@ static int s626_ai_cmdtest(struct comedi_device *dev,
int err = 0;
int tmp;
- /* cmdtest tests a particular command to see if it is valid. Using
- * the cmdtest ioctl, a user can create a valid cmd and then have it
- * executes by the cmd ioctl.
- *
- * cmdtest returns 1,2,3,4 or 0, depending on which tests the
- * command passes. */
-
- /* step 1: make sure trigger sources are trivially valid */
-
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_INT | TRIG_EXT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER | TRIG_EXT | TRIG_NOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src,
+ TRIG_NOW | TRIG_INT | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW);
+ err |= cfc_check_trigger_src(&cmd->convert_src,
+ TRIG_TIMER | TRIG_EXT | TRIG_NOW);
+ 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 2: make sure trigger sources are unique and mutually
- compatible */
+ /* Step 2a : make sure trigger sources are unique */
- /* note that mutual compatibility is not an issue here */
- if (cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_EXT
- && cmd->scan_begin_src != TRIG_FOLLOW)
- err++;
- if (cmd->convert_src != TRIG_TIMER &&
- cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW)
- err++;
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -1847,6 +1776,9 @@ static int s626_dio_insn_config(struct comedi_device *dev,
/* Now this function initializes the value of the counter (data[0])
and set the subdevice. To complete with trigger and interrupt
configuration */
+/* FIXME: data[0] is supposed to be an INSN_CONFIG_xxx constant indicating
+ * what is being configured, but this function appears to be using data[0]
+ * as a variable. */
static int s626_enc_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
@@ -1868,7 +1800,7 @@ static int s626_enc_insn_config(struct comedi_device *dev,
/* (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); */
k->SetMode(dev, k, Setup, TRUE);
- Preload(dev, k, *(insn->data));
+ Preload(dev, k, data[0]);
k->PulseIndex(dev, k);
SetLatchSource(dev, k, valueSrclatch);
k->SetEnable(dev, k, (uint16_t) (enab != 0));
@@ -1920,6 +1852,7 @@ static void WriteMISC2(struct comedi_device *dev, uint16_t NewImage)
static void CloseDMAB(struct comedi_device *dev, struct bufferDMA *pdma,
size_t bsize)
{
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
void *vbptr;
dma_addr_t vpptr;
@@ -1930,7 +1863,7 @@ static void CloseDMAB(struct comedi_device *dev, struct bufferDMA *pdma,
vbptr = pdma->LogicalBase;
vpptr = pdma->PhysicalBase;
if (vbptr) {
- pci_free_consistent(devpriv->pdev, bsize, vbptr, vpptr);
+ pci_free_consistent(pcidev, bsize, vbptr, vpptr);
pdma->LogicalBase = NULL;
pdma->PhysicalBase = 0;
}
@@ -2476,146 +2409,317 @@ static void CountersInit(struct comedi_device *dev)
}
}
-static struct pci_dev *s626_find_pci(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int s626_allocate_dma_buffers(struct comedi_device *dev)
{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
- int i;
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ void *addr;
+ dma_addr_t appdma;
- for (i = 0; i < ARRAY_SIZE(s626_boards) && !pcidev; i++) {
- do {
- pcidev = pci_get_subsys(s626_boards[i].vendor_id,
- s626_boards[i].device_id,
- s626_boards[i].subvendor_id,
- s626_boards[i].subdevice_id,
- pcidev);
-
- if ((bus || slot) && pcidev) {
- /* matches requested bus/slot */
- if (pcidev->bus->number == bus &&
- PCI_SLOT(pcidev->devfn) == slot)
- break;
- } else {
- break;
- }
- } while (1);
- }
- return pcidev;
+ addr = pci_alloc_consistent(pcidev, DMABUF_SIZE, &appdma);
+ if (!addr)
+ return -ENOMEM;
+ devpriv->ANABuf.LogicalBase = addr;
+ devpriv->ANABuf.PhysicalBase = appdma;
+
+ addr = pci_alloc_consistent(pcidev, DMABUF_SIZE, &appdma);
+ if (!addr)
+ return -ENOMEM;
+ devpriv->RPSBuf.LogicalBase = addr;
+ devpriv->RPSBuf.PhysicalBase = appdma;
+
+ return 0;
}
-static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static void s626_initialize(struct comedi_device *dev)
{
-/* uint8_t PollList; */
-/* uint16_t AdcData; */
-/* uint16_t StartVal; */
-/* uint16_t index; */
-/* unsigned int data[16]; */
- int result;
+ dma_addr_t pPhysBuf;
+ uint16_t chan;
int i;
- int ret;
- resource_size_t resourceStart;
- dma_addr_t appdma;
- struct comedi_subdevice *s;
- if (alloc_private(dev, sizeof(struct s626_private)) < 0)
- return -ENOMEM;
+ /* Enable DEBI and audio pins, enable I2C interface */
+ MC_ENABLE(P_MC1, MC1_DEBI | MC1_AUDIO | MC1_I2C);
- devpriv->pdev = s626_find_pci(dev, it);
- if (!devpriv->pdev) {
- printk(KERN_ERR "s626_attach: Board not present!!!\n");
- return -ENODEV;
- }
+ /*
+ * Configure DEBI operating mode
+ *
+ * Local bus is 16 bits wide
+ * Declare DEBI transfer timeout interval
+ * Set up byte lane steering
+ * Intel-compatible local bus (DEBI never times out)
+ */
+ WR7146(P_DEBICFG, DEBI_CFG_SLAVE16 |
+ (DEBI_TOUT << DEBI_CFG_TOUT_BIT) |
+ DEBI_SWAP | DEBI_CFG_INTEL);
+
+ /* Disable MMU paging */
+ WR7146(P_DEBIPAGE, DEBI_PAGE_DISABLE);
- result = comedi_pci_enable(devpriv->pdev, "s626");
- if (result < 0) {
- printk(KERN_ERR "s626_attach: comedi_pci_enable fails\n");
- return -ENODEV;
+ /* Init GPIO so that ADC Start* is negated */
+ WR7146(P_GPIO, GPIO_BASE | GPIO1_HI);
+
+ /* I2C device address for onboard eeprom (revb) */
+ devpriv->I2CAdrs = 0xA0;
+
+ /*
+ * Issue an I2C ABORT command to halt any I2C
+ * operation in progress and reset BUSY flag.
+ */
+ WR7146(P_I2CSTAT, I2C_CLKSEL | I2C_ABORT);
+ MC_ENABLE(P_MC2, MC2_UPLD_IIC);
+ while ((RR7146(P_MC2) & MC2_UPLD_IIC) == 0)
+ ;
+
+ /*
+ * Per SAA7146 data sheet, write to STATUS
+ * reg twice to reset all I2C error flags.
+ */
+ for (i = 0; i < 2; i++) {
+ WR7146(P_I2CSTAT, I2C_CLKSEL);
+ MC_ENABLE(P_MC2, MC2_UPLD_IIC);
+ while (!MC_TEST(P_MC2, MC2_UPLD_IIC))
+ ;
}
- devpriv->got_regions = 1;
- resourceStart = pci_resource_start(devpriv->pdev, 0);
+ /*
+ * Init audio interface functional attributes: set DAC/ADC
+ * serial clock rates, invert DAC serial clock so that
+ * DAC data setup times are satisfied, enable DAC serial
+ * clock out.
+ */
+ WR7146(P_ACON2, ACON2_INIT);
+
+ /*
+ * Set up TSL1 slot list, which is used to control the
+ * accumulation of ADC data: RSD1 = shift data in on SD1.
+ * SIB_A1 = store data uint8_t at next available location
+ * in FB BUFFER1 register.
+ */
+ WR7146(P_TSL1, RSD1 | SIB_A1);
+ WR7146(P_TSL1 + 4, RSD1 | SIB_A1 | EOS);
+
+ /* Enable TSL1 slot list so that it executes all the time */
+ WR7146(P_ACON1, ACON1_ADCSTART);
+
+ /*
+ * Initialize RPS registers used for ADC
+ */
+
+ /* Physical start of RPS program */
+ WR7146(P_RPSADDR1, (uint32_t)devpriv->RPSBuf.PhysicalBase);
+ /* RPS program performs no explicit mem writes */
+ WR7146(P_RPSPAGE1, 0);
+ /* Disable RPS timeouts */
+ WR7146(P_RPS1_TOUT, 0);
+
+#if 0
+ /*
+ * SAA7146 BUG WORKAROUND
+ *
+ * Initialize SAA7146 ADC interface to a known state by
+ * invoking ADCs until FB BUFFER 1 register shows that it
+ * is correctly receiving ADC data. This is necessary
+ * because the SAA7146 ADC interface does not start up in
+ * a defined state after a PCI reset.
+ */
+
+ {
+ uint8_t PollList;
+ uint16_t AdcData;
+ uint16_t StartVal;
+ uint16_t index;
+ unsigned int data[16];
+
+ /* Create a simple polling list for analog input channel 0 */
+ PollList = EOPL;
+ ResetADC(dev, &PollList);
- devpriv->base_addr = ioremap(resourceStart, SIZEOF_ADDRESS_SPACE);
- if (devpriv->base_addr == NULL) {
- printk(KERN_ERR "s626_attach: IOREMAP failed\n");
- return -ENODEV;
+ /* Get initial ADC value */
+ s626_ai_rinsn(dev, dev->subdevices, NULL, data);
+ StartVal = data[0];
+
+ /*
+ * VERSION 2.01 CHANGE: TIMEOUT ADDED TO PREVENT HANGED EXECUTION.
+ *
+ * Invoke ADCs until the new ADC value differs from the initial
+ * value or a timeout occurs. The timeout protects against the
+ * possibility that the driver is restarting and the ADC data is a
+ * fixed value resulting from the applied ADC analog input being
+ * unusually quiet or at the rail.
+ */
+ for (index = 0; index < 500; index++) {
+ s626_ai_rinsn(dev, dev->subdevices, NULL, data);
+ AdcData = data[0];
+ if (AdcData != StartVal)
+ break;
}
- if (devpriv->base_addr) {
- /* disable master interrupt */
- writel(0, devpriv->base_addr + P_IER);
+ }
+#endif /* SAA7146 BUG WORKAROUND */
- /* soft reset */
- writel(MC1_SOFT_RESET, devpriv->base_addr + P_MC1);
+ /*
+ * Initialize the DAC interface
+ */
- /* DMA FIXME DMA// */
+ /*
+ * Init Audio2's output DMAC attributes:
+ * burst length = 1 DWORD
+ * threshold = 1 DWORD.
+ */
+ WR7146(P_PCI_BT_A, 0);
- /* adc buffer allocation */
- devpriv->allocatedBuf = 0;
+ /*
+ * Init Audio2's output DMA physical addresses. The protection
+ * address is set to 1 DWORD past the base address so that a
+ * single DWORD will be transferred each time a DMA transfer is
+ * enabled.
+ */
+ pPhysBuf = devpriv->ANABuf.PhysicalBase +
+ (DAC_WDMABUF_OS * sizeof(uint32_t));
+ WR7146(P_BASEA2_OUT, (uint32_t) pPhysBuf);
+ WR7146(P_PROTA2_OUT, (uint32_t) (pPhysBuf + sizeof(uint32_t)));
- devpriv->ANABuf.LogicalBase =
- pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE, &appdma);
+ /*
+ * Cache Audio2's output DMA buffer logical address. This is
+ * where DAC data is buffered for A2 output DMA transfers.
+ */
+ devpriv->pDacWBuf = (uint32_t *)devpriv->ANABuf.LogicalBase +
+ DAC_WDMABUF_OS;
- if (devpriv->ANABuf.LogicalBase == NULL) {
- printk(KERN_ERR "s626_attach: DMA Memory mapping error\n");
- return -ENOMEM;
- }
+ /*
+ * Audio2's output channels does not use paging. The
+ * protection violation handling bit is set so that the
+ * DMAC will automatically halt and its PCI address pointer
+ * will be reset when the protection address is reached.
+ */
+ WR7146(P_PAGEA2_OUT, 8);
- devpriv->ANABuf.PhysicalBase = appdma;
+ /*
+ * Initialize time slot list 2 (TSL2), which is used to control
+ * the clock generation for and serialization of data to be sent
+ * to the DAC devices. Slot 0 is a NOP that is used to trap TSL
+ * execution; this permits other slots to be safely modified
+ * without first turning off the TSL sequencer (which is
+ * apparently impossible to do). Also, SD3 (which is driven by a
+ * pull-up resistor) is shifted in and stored to the MSB of
+ * FB_BUFFER2 to be used as evidence that the slot sequence has
+ * not yet finished executing.
+ */
- devpriv->allocatedBuf++;
+ /* Slot 0: Trap TSL execution, shift 0xFF into FB_BUFFER2 */
+ SETVECT(0, XSD2 | RSD3 | SIB_A2 | EOS);
- devpriv->RPSBuf.LogicalBase =
- pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE, &appdma);
+ /*
+ * Initialize slot 1, which is constant. Slot 1 causes a
+ * DWORD to be transferred from audio channel 2's output FIFO
+ * to the FIFO's output buffer so that it can be serialized
+ * and sent to the DAC during subsequent slots. All remaining
+ * slots are dynamically populated as required by the target
+ * DAC device.
+ */
- if (devpriv->RPSBuf.LogicalBase == NULL) {
- printk(KERN_ERR "s626_attach: DMA Memory mapping error\n");
- return -ENOMEM;
- }
+ /* Slot 1: Fetch DWORD from Audio2's output FIFO */
+ SETVECT(1, LF_A2);
+
+ /* Start DAC's audio interface (TSL2) running */
+ WR7146(P_ACON1, ACON1_DACSTART);
+
+ /*
+ * Init Trim DACs to calibrated values. Do it twice because the
+ * SAA7146 audio channel does not always reset properly and
+ * sometimes causes the first few TrimDAC writes to malfunction.
+ */
+ LoadTrimDACs(dev);
+ LoadTrimDACs(dev);
+
+ /*
+ * Manually init all gate array hardware in case this is a soft
+ * reset (we have no way of determining whether this is a warm
+ * or cold start). This is necessary because the gate array will
+ * reset only in response to a PCI hard reset; there is no soft
+ * reset function.
+ */
- devpriv->RPSBuf.PhysicalBase = appdma;
+ /*
+ * Init all DAC outputs to 0V and init all DAC setpoint and
+ * polarity images.
+ */
+ for (chan = 0; chan < S626_DAC_CHANNELS; chan++)
+ SetDAC(dev, chan, 0);
- devpriv->allocatedBuf++;
+ /* Init counters */
+ CountersInit(dev);
- }
+ /*
+ * Without modifying the state of the Battery Backup enab, disable
+ * the watchdog timer, set DIO channels 0-5 to operate in the
+ * standard DIO (vs. counter overflow) mode, disable the battery
+ * charger, and reset the watchdog interval selector to zero.
+ */
+ WriteMISC2(dev, (uint16_t)(DEBIread(dev, LP_RDMISC2) &
+ MISC2_BATT_ENABLE));
- dev->board_ptr = s626_boards;
- dev->board_name = thisboard->name;
+ /* Initialize the digital I/O subsystem */
+ s626_dio_init(dev);
- ret = comedi_alloc_subdevices(dev, 6);
+ /* enable interrupt test */
+ /* writel(IRQ_GPIO3 | IRQ_RPS1, devpriv->base_addr + P_IER); */
+}
+
+static int s626_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev)
+{
+ struct comedi_subdevice *s;
+ int ret;
+
+ comedi_set_hw_dev(dev, &pcidev->dev);
+ dev->board_name = dev->driver->driver_name;
+
+ if (alloc_private(dev, sizeof(struct s626_private)) < 0)
+ return -ENOMEM;
+
+ ret = comedi_pci_enable(pcidev, dev->board_name);
if (ret)
return ret;
+ dev->iobase = 1; /* detach needs this */
- dev->iobase = (unsigned long)devpriv->base_addr;
- dev->irq = devpriv->pdev->irq;
+ devpriv->base_addr = ioremap(pci_resource_start(pcidev, 0),
+ pci_resource_len(pcidev, 0));
+ if (!devpriv->base_addr)
+ return -ENOMEM;
- /* set up interrupt handler */
- if (dev->irq == 0) {
- printk(KERN_ERR " unknown irq (bad)\n");
- } else {
- ret = request_irq(dev->irq, s626_irq_handler, IRQF_SHARED,
- "s626", dev);
+ /* disable master interrupt */
+ writel(0, devpriv->base_addr + P_IER);
- if (ret < 0) {
- printk(KERN_ERR " irq not available\n");
- dev->irq = 0;
- }
+ /* soft reset */
+ writel(MC1_SOFT_RESET, devpriv->base_addr + P_MC1);
+
+ /* DMA FIXME DMA// */
+
+ ret = s626_allocate_dma_buffers(dev);
+ if (ret)
+ return ret;
+
+ if (pcidev->irq) {
+ ret = request_irq(pcidev->irq, s626_irq_handler, IRQF_SHARED,
+ dev->board_name, dev);
+
+ if (ret == 0)
+ dev->irq = pcidev->irq;
}
+ ret = comedi_alloc_subdevices(dev, 6);
+ if (ret)
+ return ret;
+
s = dev->subdevices + 0;
/* analog input subdevice */
dev->read_subdev = s;
/* we support single-ended (ground) and differential */
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_CMD_READ;
- s->n_chan = thisboard->ai_chans;
+ s->n_chan = S626_ADC_CHANNELS;
s->maxdata = (0xffff >> 2);
s->range_table = &s626_range_table;
- s->len_chanlist = thisboard->ai_chans; /* This is the maximum chanlist
- length that the board can
- handle */
+ s->len_chanlist = S626_ADC_CHANNELS;
s->insn_config = s626_ai_insn_config;
s->insn_read = s626_ai_insn_read;
s->do_cmd = s626_ai_cmd;
@@ -2626,7 +2730,7 @@ static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* analog output subdevice */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
- s->n_chan = thisboard->ao_chans;
+ s->n_chan = S626_DAC_CHANNELS;
s->maxdata = (0x3fff);
s->range_table = &range_bipolar10;
s->insn_write = s626_ao_winsn;
@@ -2672,7 +2776,7 @@ static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* encoder (counter) subdevice */
s->type = COMEDI_SUBD_COUNTER;
s->subdev_flags = SDF_WRITABLE | SDF_READABLE | SDF_LSAMPL;
- s->n_chan = thisboard->enc_chans;
+ s->n_chan = S626_ENCODER_CHANNELS;
s->private = enc_private_data;
s->insn_config = s626_enc_insn_config;
s->insn_read = s626_enc_insn_read;
@@ -2680,269 +2784,17 @@ static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->maxdata = 0xffffff;
s->range_table = &range_unknown;
- /* stop ai_command */
- devpriv->ai_cmd_running = 0;
-
- if (devpriv->base_addr && (devpriv->allocatedBuf == 2)) {
- dma_addr_t pPhysBuf;
- uint16_t chan;
-
- /* enab DEBI and audio pins, enable I2C interface. */
- MC_ENABLE(P_MC1, MC1_DEBI | MC1_AUDIO | MC1_I2C);
- /* Configure DEBI operating mode. */
- WR7146(P_DEBICFG, DEBI_CFG_SLAVE16 /* Local bus is 16 */
- /* bits wide. */
- | (DEBI_TOUT << DEBI_CFG_TOUT_BIT)
-
- /* Declare DEBI */
- /* transfer timeout */
- /* interval. */
- |DEBI_SWAP /* Set up byte lane */
- /* steering. */
- | DEBI_CFG_INTEL); /* Intel-compatible */
- /* local bus (DEBI */
- /* never times out). */
-
- /* DEBI INIT S626 WR7146( P_DEBICFG, DEBI_CFG_INTEL | DEBI_CFG_TOQ */
- /* | DEBI_CFG_INCQ| DEBI_CFG_16Q); //end */
-
- /* Paging is disabled. */
- WR7146(P_DEBIPAGE, DEBI_PAGE_DISABLE); /* Disable MMU paging. */
-
- /* Init GPIO so that ADC Start* is negated. */
- WR7146(P_GPIO, GPIO_BASE | GPIO1_HI);
-
- /* IsBoardRevA is a boolean that indicates whether the board is RevA.
- *
- * VERSION 2.01 CHANGE: REV A & B BOARDS NOW SUPPORTED BY DYNAMIC
- * EEPROM ADDRESS SELECTION. Initialize the I2C interface, which
- * is used to access the onboard serial EEPROM. The EEPROM's I2C
- * DeviceAddress is hardwired to a value that is dependent on the
- * 626 board revision. On all board revisions, the EEPROM stores
- * TrimDAC calibration constants for analog I/O. On RevB and
- * higher boards, the DeviceAddress is hardwired to 0 to enable
- * the EEPROM to also store the PCI SubVendorID and SubDeviceID;
- * this is the address at which the SAA7146 expects a
- * configuration EEPROM to reside. On RevA boards, the EEPROM
- * device address, which is hardwired to 4, prevents the SAA7146
- * from retrieving PCI sub-IDs, so the SAA7146 uses its built-in
- * default values, instead.
- */
-
- /* devpriv->I2Cards= IsBoardRevA ? 0xA8 : 0xA0; // Set I2C EEPROM */
- /* DeviceType (0xA0) */
- /* and DeviceAddress<<1. */
-
- devpriv->I2CAdrs = 0xA0; /* I2C device address for onboard */
- /* eeprom(revb) */
+ s626_initialize(dev);
- /* Issue an I2C ABORT command to halt any I2C operation in */
- /* progress and reset BUSY flag. */
- WR7146(P_I2CSTAT, I2C_CLKSEL | I2C_ABORT);
- /* Write I2C control: abort any I2C activity. */
- MC_ENABLE(P_MC2, MC2_UPLD_IIC);
- /* Invoke command upload */
- while ((RR7146(P_MC2) & MC2_UPLD_IIC) == 0)
- ;
- /* and wait for upload to complete. */
-
- /* Per SAA7146 data sheet, write to STATUS reg twice to
- * reset all I2C error flags. */
- for (i = 0; i < 2; i++) {
- WR7146(P_I2CSTAT, I2C_CLKSEL);
- /* Write I2C control: reset error flags. */
- MC_ENABLE(P_MC2, MC2_UPLD_IIC); /* Invoke command upload */
- while (!MC_TEST(P_MC2, MC2_UPLD_IIC))
- ;
- /* and wait for upload to complete. */
- }
-
- /* Init audio interface functional attributes: set DAC/ADC
- * serial clock rates, invert DAC serial clock so that
- * DAC data setup times are satisfied, enable DAC serial
- * clock out.
- */
+ dev_info(dev->class_dev, "%s attached\n", dev->board_name);
- WR7146(P_ACON2, ACON2_INIT);
-
- /* Set up TSL1 slot list, which is used to control the
- * accumulation of ADC data: RSD1 = shift data in on SD1.
- * SIB_A1 = store data uint8_t at next available location in
- * FB BUFFER1 register. */
- WR7146(P_TSL1, RSD1 | SIB_A1);
- /* Fetch ADC high data uint8_t. */
- WR7146(P_TSL1 + 4, RSD1 | SIB_A1 | EOS);
- /* Fetch ADC low data uint8_t; end of TSL1. */
-
- /* enab TSL1 slot list so that it executes all the time. */
- WR7146(P_ACON1, ACON1_ADCSTART);
-
- /* Initialize RPS registers used for ADC. */
-
- /* Physical start of RPS program. */
- WR7146(P_RPSADDR1, (uint32_t) devpriv->RPSBuf.PhysicalBase);
-
- WR7146(P_RPSPAGE1, 0);
- /* RPS program performs no explicit mem writes. */
- WR7146(P_RPS1_TOUT, 0); /* Disable RPS timeouts. */
-
- /* SAA7146 BUG WORKAROUND. Initialize SAA7146 ADC interface
- * to a known state by invoking ADCs until FB BUFFER 1
- * register shows that it is correctly receiving ADC data.
- * This is necessary because the SAA7146 ADC interface does
- * not start up in a defined state after a PCI reset.
- */
-
-/* PollList = EOPL; // Create a simple polling */
-/* // list for analog input */
-/* // channel 0. */
-/* ResetADC( dev, &PollList ); */
-
-/* s626_ai_rinsn(dev,dev->subdevices,NULL,data); //( &AdcData ); // */
-/* //Get initial ADC */
-/* //value. */
-
-/* StartVal = data[0]; */
-
-/* // VERSION 2.01 CHANGE: TIMEOUT ADDED TO PREVENT HANGED EXECUTION. */
-/* // Invoke ADCs until the new ADC value differs from the initial */
-/* // value or a timeout occurs. The timeout protects against the */
-/* // possibility that the driver is restarting and the ADC data is a */
-/* // fixed value resulting from the applied ADC analog input being */
-/* // unusually quiet or at the rail. */
-
-/* for ( index = 0; index < 500; index++ ) */
-/* { */
-/* s626_ai_rinsn(dev,dev->subdevices,NULL,data); */
-/* AdcData = data[0]; //ReadADC( &AdcData ); */
-/* if ( AdcData != StartVal ) */
-/* break; */
-/* } */
-
- /* end initADC */
-
- /* init the DAC interface */
-
- /* Init Audio2's output DMAC attributes: burst length = 1
- * DWORD, threshold = 1 DWORD.
- */
- WR7146(P_PCI_BT_A, 0);
-
- /* Init Audio2's output DMA physical addresses. The protection
- * address is set to 1 DWORD past the base address so that a
- * single DWORD will be transferred each time a DMA transfer is
- * enabled. */
-
- pPhysBuf =
- devpriv->ANABuf.PhysicalBase +
- (DAC_WDMABUF_OS * sizeof(uint32_t));
-
- WR7146(P_BASEA2_OUT, (uint32_t) pPhysBuf); /* Buffer base adrs. */
- WR7146(P_PROTA2_OUT, (uint32_t) (pPhysBuf + sizeof(uint32_t))); /* Protection address. */
-
- /* Cache Audio2's output DMA buffer logical address. This is
- * where DAC data is buffered for A2 output DMA transfers. */
- devpriv->pDacWBuf =
- (uint32_t *) devpriv->ANABuf.LogicalBase + DAC_WDMABUF_OS;
-
- /* Audio2's output channels does not use paging. The protection
- * violation handling bit is set so that the DMAC will
- * automatically halt and its PCI address pointer will be reset
- * when the protection address is reached. */
-
- WR7146(P_PAGEA2_OUT, 8);
-
- /* Initialize time slot list 2 (TSL2), which is used to control
- * the clock generation for and serialization of data to be sent
- * to the DAC devices. Slot 0 is a NOP that is used to trap TSL
- * execution; this permits other slots to be safely modified
- * without first turning off the TSL sequencer (which is
- * apparently impossible to do). Also, SD3 (which is driven by a
- * pull-up resistor) is shifted in and stored to the MSB of
- * FB_BUFFER2 to be used as evidence that the slot sequence has
- * not yet finished executing.
- */
-
- SETVECT(0, XSD2 | RSD3 | SIB_A2 | EOS);
- /* Slot 0: Trap TSL execution, shift 0xFF into FB_BUFFER2. */
-
- /* Initialize slot 1, which is constant. Slot 1 causes a
- * DWORD to be transferred from audio channel 2's output FIFO
- * to the FIFO's output buffer so that it can be serialized
- * and sent to the DAC during subsequent slots. All remaining
- * slots are dynamically populated as required by the target
- * DAC device.
- */
- SETVECT(1, LF_A2);
- /* Slot 1: Fetch DWORD from Audio2's output FIFO. */
-
- /* Start DAC's audio interface (TSL2) running. */
- WR7146(P_ACON1, ACON1_DACSTART);
-
- /* end init DAC interface */
-
- /* Init Trim DACs to calibrated values. Do it twice because the
- * SAA7146 audio channel does not always reset properly and
- * sometimes causes the first few TrimDAC writes to malfunction.
- */
-
- LoadTrimDACs(dev);
- LoadTrimDACs(dev); /* Insurance. */
-
- /* Manually init all gate array hardware in case this is a soft
- * reset (we have no way of determining whether this is a warm
- * or cold start). This is necessary because the gate array will
- * reset only in response to a PCI hard reset; there is no soft
- * reset function. */
-
- /* Init all DAC outputs to 0V and init all DAC setpoint and
- * polarity images.
- */
- for (chan = 0; chan < S626_DAC_CHANNELS; chan++)
- SetDAC(dev, chan, 0);
-
- /* Init image of WRMISC2 Battery Charger Enabled control bit.
- * This image is used when the state of the charger control bit,
- * which has no direct hardware readback mechanism, is queried.
- */
- devpriv->ChargeEnabled = 0;
-
- /* Init image of watchdog timer interval in WRMISC2. This image
- * maintains the value of the control bits of MISC2 are
- * continuously reset to zero as long as the WD timer is disabled.
- */
- devpriv->WDInterval = 0;
-
- /* Init Counter Interrupt enab mask for RDMISC2. This mask is
- * applied against MISC2 when testing to determine which timer
- * events are requesting interrupt service.
- */
- devpriv->CounterIntEnabs = 0;
-
- /* Init counters. */
- CountersInit(dev);
-
- /* Without modifying the state of the Battery Backup enab, disable
- * the watchdog timer, set DIO channels 0-5 to operate in the
- * standard DIO (vs. counter overflow) mode, disable the battery
- * charger, and reset the watchdog interval selector to zero.
- */
- WriteMISC2(dev, (uint16_t) (DEBIread(dev,
- LP_RDMISC2) &
- MISC2_BATT_ENABLE));
-
- /* Initialize the digital I/O subsystem. */
- s626_dio_init(dev);
-
- /* enable interrupt test */
- /* writel(IRQ_GPIO3 | IRQ_RPS1,devpriv->base_addr+P_IER); */
- }
-
- return 1;
+ return 0;
}
static void s626_detach(struct comedi_device *dev)
{
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+
if (devpriv) {
/* stop ai_command */
devpriv->ai_cmd_running = 0;
@@ -2967,18 +2819,17 @@ static void s626_detach(struct comedi_device *dev)
free_irq(dev->irq, dev);
if (devpriv->base_addr)
iounmap(devpriv->base_addr);
- if (devpriv->pdev) {
- if (devpriv->got_regions)
- comedi_pci_disable(devpriv->pdev);
- pci_dev_put(devpriv->pdev);
- }
+ }
+ if (pcidev) {
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
}
}
static struct comedi_driver s626_driver = {
.driver_name = "s626",
.module = THIS_MODULE,
- .attach = s626_attach,
+ .attach_pci = s626_attach_pci,
.detach = s626_detach,
};
diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h
index 8a8f196cf153..ff4b3a5e4e5f 100644
--- a/drivers/staging/comedi/drivers/s626.h
+++ b/drivers/staging/comedi/drivers/s626.h
@@ -73,7 +73,6 @@
#include <linux/slab.h>
#define S626_SIZE 0x0200
-#define SIZEOF_ADDRESS_SPACE 0x0200
#define DMABUF_SIZE 4096 /* 4k pages */
#define S626_ADC_CHANNELS 16
diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
index c18314be8c82..5bf84cfbdceb 100644
--- a/drivers/staging/comedi/drivers/serial2002.c
+++ b/drivers/staging/comedi/drivers/serial2002.c
@@ -588,7 +588,9 @@ static int serial_2002_open(struct comedi_device *dev)
kfree(s->range_table_list);
s->range_table = NULL;
s->range_table_list = NULL;
- if (range) {
+ if (kind == 1 || kind == 2) {
+ s->range_table = &range_digital;
+ } else if (range) {
s->range_table_list = range_table_list =
kmalloc(sizeof
(struct
@@ -798,7 +800,7 @@ static int serial2002_attach(struct comedi_device *dev,
return ret;
/* digital input subdevice */
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
s->n_chan = 0;
@@ -807,7 +809,7 @@ static int serial2002_attach(struct comedi_device *dev,
s->insn_read = &serial2002_di_rinsn;
/* digital output subdevice */
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITEABLE;
s->n_chan = 0;
@@ -816,7 +818,7 @@ static int serial2002_attach(struct comedi_device *dev,
s->insn_write = &serial2002_do_winsn;
/* analog input subdevice */
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_GROUND;
s->n_chan = 0;
@@ -825,7 +827,7 @@ static int serial2002_attach(struct comedi_device *dev,
s->insn_read = &serial2002_ai_rinsn;
/* analog output subdevice */
- s = dev->subdevices + 3;
+ s = &dev->subdevices[3];
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITEABLE;
s->n_chan = 0;
@@ -835,7 +837,7 @@ static int serial2002_attach(struct comedi_device *dev,
s->insn_read = &serial2002_ao_rinsn;
/* encoder input subdevice */
- s = dev->subdevices + 4;
+ s = &dev->subdevices[4];
s->type = COMEDI_SUBD_COUNTER;
s->subdev_flags = SDF_READABLE | SDF_LSAMPL;
s->n_chan = 0;
diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
index 9a68eebefca0..b70cdf300bbd 100644
--- a/drivers/staging/comedi/drivers/skel.c
+++ b/drivers/staging/comedi/drivers/skel.c
@@ -76,6 +76,8 @@ Configuration Options:
#include <linux/pci.h> /* for PCI devices */
+#include "comedi_fc.h"
+
/* Imaginary registers for the imaginary board */
#define SKEL_SIZE 0
@@ -238,7 +240,7 @@ static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* dev->read_subdev=s; */
/* analog input subdevice */
s->type = COMEDI_SUBD_AI;
@@ -256,7 +258,7 @@ static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it)
*/
s->do_cmdtest = skel_ai_cmdtest;
- s = dev->subdevices + 1;
+ s = &dev->subdevices[1];
/* analog output subdevice */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
@@ -266,7 +268,7 @@ static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->insn_write = skel_ao_winsn;
s->insn_read = skel_ao_rinsn;
- s = dev->subdevices + 2;
+ s = &dev->subdevices[2];
/* digital i/o subdevice */
if (thisboard->have_dio) {
s->type = COMEDI_SUBD_DIO;
@@ -349,60 +351,40 @@ static int skel_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
return n;
}
+/*
+ * cmdtest tests a particular command to see if it is valid.
+ * Using the cmdtest ioctl, a user can create a valid cmd
+ * and then have it executes by the cmd ioctl.
+ *
+ * cmdtest returns 1,2,3,4 or 0, depending on which tests
+ * the command passes.
+ */
static int skel_ai_cmdtest(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_cmd *cmd)
+ struct comedi_subdevice *s,
+ struct comedi_cmd *cmd)
{
int err = 0;
int tmp;
- /* cmdtest tests a particular command to see if it is valid.
- * Using the cmdtest ioctl, a user can create a valid cmd
- * and then have it executes by the cmd ioctl.
- *
- * cmdtest returns 1,2,3,4 or 0, depending on which tests
- * the command passes. */
-
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_TIMER | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
+ 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 2: make sure trigger sources are unique and mutually compatible
- */
+ /* Step 2a : make sure trigger sources are unique */
- /* note that mutual compatibility is not an issue here */
- if (cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_EXT)
- err++;
- if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
- err++;
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
index 84b9f2a4280b..ae3aa1c5caef 100644
--- a/drivers/staging/comedi/drivers/ssv_dnp.c
+++ b/drivers/staging/comedi/drivers/ssv_dnp.c
@@ -177,15 +177,13 @@ static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
struct comedi_subdevice *s;
int ret;
- printk(KERN_INFO "comedi%d: dnp: ", dev->minor);
-
dev->board_name = board->name;
ret = comedi_alloc_subdevices(dev, 1);
if (ret)
return ret;
- s = dev->subdevices + 0;
+ s = &dev->subdevices[0];
/* digital i/o subdevice */
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
@@ -195,8 +193,6 @@ static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->insn_bits = dnp_dio_insn_bits;
s->insn_config = dnp_dio_insn_config;
- printk("attached\n");
-
/* We use the I/O ports 0x22,0x23 and 0xa3-0xa9, which are always
* allocated for the primary 8259, so we don't need to allocate them
* ourselves. */
@@ -209,6 +205,7 @@ static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
outb(PCMR, CSCIR);
outb((inb(CSCDR) & 0xAA), CSCDR);
+ dev_info(dev->class_dev, "%s: attached\n", dev->board_name);
return 1;
}
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index 11ee83681da7..b536bba74351 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -98,6 +98,8 @@ sampling rate. If you sample two channels you get 4kHz and so on.
#include "../comedidev.h"
+#include "comedi_fc.h"
+
/* timeout for the USB-transfer in ms*/
#define BULK_TIMEOUT 1000
@@ -404,7 +406,7 @@ static void usbduxsub_ai_IsocIrq(struct urb *urb)
/* 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;
+ s = &this_comedidev->subdevices[SUBDEV_AD];
/* first we test if something unusual has just happened */
switch (urb->status) {
@@ -604,7 +606,7 @@ static void usbduxsub_ao_IsocIrq(struct urb *urb)
/* the private structure of the subdevice is struct usbduxsub */
this_usbduxsub = this_comedidev->private;
- s = this_comedidev->subdevices + SUBDEV_DA;
+ s = &this_comedidev->subdevices[SUBDEV_DA];
switch (urb->status) {
case 0:
@@ -929,9 +931,9 @@ static int usbduxsub_submit_OutURBs(struct usbduxsub *usbduxsub)
static int usbdux_ai_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_cmd *cmd)
{
- int err = 0, tmp, i;
- unsigned int tmpTimer;
struct usbduxsub *this_usbduxsub = dev->private;
+ int err = 0, i;
+ unsigned int tmpTimer;
if (!(this_usbduxsub->probed))
return -ENODEV;
@@ -939,51 +941,23 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev,
dev_dbg(&this_usbduxsub->interface->dev,
"comedi%d: usbdux_ai_cmdtest\n", dev->minor);
- /* make sure triggers are valid */
- /* Only immediate triggers are allowed */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_INT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- /* trigger should happen timed */
- tmp = cmd->scan_begin_src;
- /* start a new _scan_ with a timer */
- cmd->scan_begin_src &= TRIG_TIMER;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- /* scanning is continuous */
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_NOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- /* issue a trigger when scan is finished and start a new scan */
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- /* trigger at the end of count events or not, stop condition or not */
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
+ 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 2: make sure trigger sources are unique and mutually compatible
- * note that mutual compatibility is not an issue here
- */
- if (cmd->scan_begin_src != TRIG_FOLLOW &&
- cmd->scan_begin_src != TRIG_EXT &&
- cmd->scan_begin_src != TRIG_TIMER)
- err++;
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ /* Step 2a : make sure trigger sources are unique */
+
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -1488,8 +1462,9 @@ static int usbdux_ao_inttrig(struct comedi_device *dev,
static int usbdux_ao_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_cmd *cmd)
{
- int err = 0, tmp;
struct usbduxsub *this_usbduxsub = dev->private;
+ int err = 0;
+ unsigned int flags;
if (!this_usbduxsub)
return -EFAULT;
@@ -1500,69 +1475,46 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev,
dev_dbg(&this_usbduxsub->interface->dev,
"comedi%d: usbdux_ao_cmdtest\n", dev->minor);
- /* make sure triggers are valid */
- /* Only immediate triggers are allowed */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_INT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
+
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
- /* trigger should happen timed */
- tmp = cmd->scan_begin_src;
- /* just now we scan also in the high speed mode every frame */
- /* this is due to ehci driver limitations */
if (0) { /* (this_usbduxsub->high_speed) */
- /* start immediately a new scan */
/* the sampling rate is set by the coversion rate */
- cmd->scan_begin_src &= TRIG_FOLLOW;
+ flags = TRIG_FOLLOW;
} else {
/* start a new scan (output at once) with a timer */
- cmd->scan_begin_src &= TRIG_TIMER;
+ flags = TRIG_TIMER;
}
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags);
- /* scanning is continuous */
- tmp = cmd->convert_src;
- /* we always output at 1kHz just now all channels at once */
if (0) { /* (this_usbduxsub->high_speed) */
/*
- * in usb-2.0 only one conversion it transmitted but with 8kHz/n
+ * in usb-2.0 only one conversion it transmitted
+ * but with 8kHz/n
*/
- cmd->convert_src &= TRIG_TIMER;
+ flags = TRIG_TIMER;
} else {
- /* all conversion events happen simultaneously with a rate of
- * 1kHz/n */
- cmd->convert_src &= TRIG_NOW;
+ /*
+ * all conversion events happen simultaneously with
+ * a rate of 1kHz/n
+ */
+ flags = TRIG_NOW;
}
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- /* issue a trigger when scan is finished and start a new scan */
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->convert_src, flags);
- /* trigger at the end of count events or not, stop condition or not */
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ 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 2: make sure trigger sources are unique and mutually compatible
- * note that mutual compatibility is not an issue here
- */
- if (cmd->scan_begin_src != TRIG_FOLLOW &&
- cmd->scan_begin_src != TRIG_EXT &&
- cmd->scan_begin_src != TRIG_TIMER)
- err++;
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ /* Step 2a : make sure trigger sources are unique */
+
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -1947,7 +1899,7 @@ static void usbduxsub_pwm_irq(struct urb *urb)
/* the private structure of the subdevice is struct usbduxsub */
this_usbduxsub = this_comedidev->private;
- s = this_comedidev->subdevices + SUBDEV_DA;
+ s = &this_comedidev->subdevices[SUBDEV_DA];
switch (urb->status) {
case 0:
@@ -2293,10 +2245,8 @@ static void tidy_up(struct usbduxsub *usbduxsub_tmp)
usbduxsub_tmp->pwm_cmd_running = 0;
}
-/* common part of attach and attach_usb */
static int usbdux_attach_common(struct comedi_device *dev,
- struct usbduxsub *udev,
- void *aux_data, int aux_len)
+ struct usbduxsub *udev)
{
int ret;
struct comedi_subdevice *s = NULL;
@@ -2306,10 +2256,6 @@ static int usbdux_attach_common(struct comedi_device *dev,
/* pointer back to the corresponding comedi device */
udev->comedidev = dev;
- /* trying to upload the firmware into the chip */
- if (aux_data)
- firmwareUpload(udev, aux_data, aux_len);
-
dev->board_name = "usbdux";
/* set number of subdevices */
@@ -2331,7 +2277,7 @@ static int usbdux_attach_common(struct comedi_device *dev,
dev->private = udev;
/* the first subdevice is the A/D converter */
- s = dev->subdevices + SUBDEV_AD;
+ s = &dev->subdevices[SUBDEV_AD];
/* the URBs get the comedi subdevice */
/* which is responsible for reading */
/* this is the subdevice which reads data */
@@ -2358,7 +2304,7 @@ static int usbdux_attach_common(struct comedi_device *dev,
s->range_table = (&range_usbdux_ai_range);
/* analog out */
- s = dev->subdevices + SUBDEV_DA;
+ s = &dev->subdevices[SUBDEV_DA];
/* analog out */
s->type = COMEDI_SUBD_AO;
/* backward pointer */
@@ -2384,7 +2330,7 @@ static int usbdux_attach_common(struct comedi_device *dev,
s->insn_write = usbdux_ao_insn_write;
/* digital I/O */
- s = dev->subdevices + SUBDEV_DIO;
+ s = &dev->subdevices[SUBDEV_DIO];
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 8;
@@ -2396,7 +2342,7 @@ static int usbdux_attach_common(struct comedi_device *dev,
s->private = NULL;
/* counter */
- s = dev->subdevices + SUBDEV_COUNTER;
+ s = &dev->subdevices[SUBDEV_COUNTER];
s->type = COMEDI_SUBD_COUNTER;
s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
s->n_chan = 4;
@@ -2407,7 +2353,7 @@ static int usbdux_attach_common(struct comedi_device *dev,
if (udev->high_speed) {
/* timer / pwm */
- s = dev->subdevices + SUBDEV_PWM;
+ s = &dev->subdevices[SUBDEV_PWM];
s->type = COMEDI_SUBD_PWM;
s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE;
s->n_chan = 8;
@@ -2429,48 +2375,6 @@ static int usbdux_attach_common(struct comedi_device *dev,
return 0;
}
-/* is called when comedi-config is called */
-static int usbdux_attach(struct comedi_device *dev, struct comedi_devconfig *it)
-{
- int ret;
- int index;
- int i;
- void *aux_data;
- int aux_len;
-
- dev->private = NULL;
-
- aux_data = comedi_aux_data(it->options, 0);
- aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH];
- if (aux_data == NULL)
- aux_len = 0;
- else if (aux_len == 0)
- aux_data = NULL;
-
- down(&start_stop_sem);
- /* find a valid device which has been detected by the probe function of
- * the usb */
- index = -1;
- for (i = 0; i < NUMUSBDUX; i++) {
- if ((usbduxsub[i].probed) && (!usbduxsub[i].attached)) {
- index = i;
- break;
- }
- }
-
- if (index < 0) {
- printk(KERN_ERR
- "comedi%d: usbdux: error: attach failed, no usbdux devs connected to the usb bus.\n",
- dev->minor);
- ret = -ENODEV;
- } else
- ret = usbdux_attach_common(dev, &usbduxsub[index],
- aux_data, aux_len);
- up(&start_stop_sem);
- return ret;
-}
-
-/* is called from comedi_usb_auto_config() */
static int usbdux_attach_usb(struct comedi_device *dev,
struct usb_interface *uinterf)
{
@@ -2492,7 +2396,7 @@ static int usbdux_attach_usb(struct comedi_device *dev,
dev->minor);
ret = -ENODEV;
} else
- ret = usbdux_attach_common(dev, this_usbduxsub, NULL, 0);
+ ret = usbdux_attach_common(dev, this_usbduxsub);
up(&start_stop_sem);
return ret;
}
@@ -2513,9 +2417,8 @@ static void usbdux_detach(struct comedi_device *dev)
static struct comedi_driver usbdux_driver = {
.driver_name = "usbdux",
.module = THIS_MODULE,
- .attach = usbdux_attach,
- .detach = usbdux_detach,
.attach_usb = usbdux_attach_usb,
+ .detach = usbdux_detach,
};
static void usbdux_firmware_request_complete_handler(const struct firmware *fw,
diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
index 8eb41257c6ce..1154a7e2895d 100644
--- a/drivers/staging/comedi/drivers/usbduxfast.c
+++ b/drivers/staging/comedi/drivers/usbduxfast.c
@@ -346,7 +346,7 @@ static void usbduxfastsub_ai_Irq(struct urb *urb)
return;
}
/* subdevice which is the AD converter */
- s = this_comedidev->subdevices + SUBDEV_AD;
+ s = &this_comedidev->subdevices[SUBDEV_AD];
/* first we test if something unusual has just happened */
switch (urb->status) {
@@ -549,10 +549,10 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{
- int err = 0, stop_mask = 0;
+ struct usbduxfastsub_s *udfs = dev->private;
+ int err = 0;
long int steps, tmp;
int minSamplPer;
- struct usbduxfastsub_s *udfs = dev->private;
if (!udfs->probed)
return -ENODEV;
@@ -563,57 +563,31 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
"scan_begin_arg=%u\n",
dev->minor, cmd->convert_arg, cmd->scan_begin_arg);
#endif
- /* step 1: make sure trigger sources are trivially valid */
-
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_EXT | TRIG_INT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
- stop_mask = TRIG_COUNT | TRIG_NONE;
- cmd->stop_src &= stop_mask;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src,
+ TRIG_NOW | TRIG_EXT | TRIG_INT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
+ 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 2: make sure trigger sources are unique and mutually compatible
- */
+ /* Step 2a : make sure trigger sources are unique */
- if (cmd->start_src != TRIG_NOW &&
- cmd->start_src != TRIG_EXT && cmd->start_src != TRIG_INT)
- err++;
- if (cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_FOLLOW &&
- cmd->scan_begin_src != TRIG_EXT)
- err++;
- if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
- err++;
- if (cmd->stop_src != TRIG_COUNT &&
- cmd->stop_src != TRIG_EXT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
/* can't have external stop and start triggers at once */
if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT)
- err++;
+ err |= -EINVAL;
if (err)
return 2;
@@ -1430,10 +1404,8 @@ static void tidy_up(struct usbduxfastsub_s *udfs)
udfs->ai_cmd_running = 0;
}
-/* common part of attach and attach_usb */
static int usbduxfast_attach_common(struct comedi_device *dev,
- struct usbduxfastsub_s *udfs,
- void *aux_data, int aux_len)
+ struct usbduxfastsub_s *udfs)
{
int ret;
struct comedi_subdevice *s;
@@ -1441,9 +1413,6 @@ static int usbduxfast_attach_common(struct comedi_device *dev,
down(&udfs->sem);
/* pointer back to the corresponding comedi device */
udfs->comedidev = dev;
- /* trying to upload the firmware into the chip */
- if (aux_data)
- firmwareUpload(udfs, aux_data, aux_len);
dev->board_name = "usbduxfast";
ret = comedi_alloc_subdevices(dev, 1);
if (ret) {
@@ -1453,7 +1422,7 @@ static int usbduxfast_attach_common(struct comedi_device *dev,
/* private structure is also simply the usb-structure */
dev->private = udfs;
/* the first subdevice is the A/D converter */
- s = dev->subdevices + SUBDEV_AD;
+ s = &dev->subdevices[SUBDEV_AD];
/*
* the URBs get the comedi subdevice which is responsible for reading
* this is the subdevice which reads data
@@ -1485,48 +1454,6 @@ static int usbduxfast_attach_common(struct comedi_device *dev,
return 0;
}
-/* is called for COMEDI_DEVCONFIG ioctl (when comedi_config is run) */
-static int usbduxfast_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- int ret;
- int index;
- int i;
- void *aux_data;
- int aux_len;
-
- dev->private = NULL;
-
- aux_data = comedi_aux_data(it->options, 0);
- aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH];
- if (aux_data == NULL)
- aux_len = 0;
- else if (aux_len == 0)
- aux_data = NULL;
- down(&start_stop_sem);
- /*
- * find a valid device which has been detected by the
- * probe function of the usb
- */
- index = -1;
- for (i = 0; i < NUMUSBDUXFAST; i++) {
- if (usbduxfastsub[i].probed && !usbduxfastsub[i].attached) {
- index = i;
- break;
- }
- }
- if (index < 0) {
- dev_err(dev->class_dev,
- "usbduxfast: error: attach failed, no usbduxfast devs connected to the usb bus.\n");
- ret = -ENODEV;
- } else
- ret = usbduxfast_attach_common(dev, &usbduxfastsub[index],
- aux_data, aux_len);
- up(&start_stop_sem);
- return ret;
-}
-
-/* is called from comedi_usb_auto_config() */
static int usbduxfast_attach_usb(struct comedi_device *dev,
struct usb_interface *uinterf)
{
@@ -1545,7 +1472,7 @@ static int usbduxfast_attach_usb(struct comedi_device *dev,
"usbduxfast: error: attach_usb failed, already attached\n");
ret = -ENODEV;
} else
- ret = usbduxfast_attach_common(dev, udfs, NULL, 0);
+ ret = usbduxfast_attach_common(dev, udfs);
up(&start_stop_sem);
return ret;
}
@@ -1568,9 +1495,8 @@ static void usbduxfast_detach(struct comedi_device *dev)
static struct comedi_driver usbduxfast_driver = {
.driver_name = "usbduxfast",
.module = THIS_MODULE,
- .attach = usbduxfast_attach,
- .detach = usbduxfast_detach,
.attach_usb = usbduxfast_attach_usb,
+ .detach = usbduxfast_detach,
};
static void usbduxfast_firmware_request_complete_handler(const struct firmware
diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c
index f54ab8c2fcfd..b1694121f845 100644
--- a/drivers/staging/comedi/drivers/usbduxsigma.c
+++ b/drivers/staging/comedi/drivers/usbduxsigma.c
@@ -356,7 +356,7 @@ static void usbduxsub_ai_IsocIrq(struct urb *urb)
/* 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;
+ s = &this_comedidev->subdevices[SUBDEV_AD];
/* first we test if something unusual has just happened */
switch (urb->status) {
@@ -558,7 +558,7 @@ static void usbduxsub_ao_IsocIrq(struct urb *urb)
/* the private structure of the subdevice is struct usbduxsub */
this_usbduxsub = this_comedidev->private;
- s = this_comedidev->subdevices + SUBDEV_DA;
+ s = &this_comedidev->subdevices[SUBDEV_DA];
switch (urb->status) {
case 0:
@@ -897,9 +897,9 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{
- int err = 0, tmp, i;
- unsigned int tmpTimer;
struct usbduxsub *this_usbduxsub = dev->private;
+ int err = 0, i;
+ unsigned int tmpTimer;
if (!(this_usbduxsub->probed))
return -ENODEV;
@@ -907,51 +907,23 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev,
dev_dbg(&this_usbduxsub->interface->dev,
"comedi%d: usbdux_ai_cmdtest\n", dev->minor);
- /* make sure triggers are valid */
- /* Only immediate triggers are allowed */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_INT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- /* trigger should happen timed */
- tmp = cmd->scan_begin_src;
- /* start a new _scan_ with a timer */
- cmd->scan_begin_src &= TRIG_TIMER;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- /* scanning is continuous */
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_NOW;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
- /* issue a trigger when scan is finished and start a new scan */
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- /* trigger at the end of count events or not, stop condition or not */
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
+ 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 2: make sure trigger sources are unique and mutually compatible
- * note that mutual compatibility is not an issue here
- */
- if (cmd->scan_begin_src != TRIG_FOLLOW &&
- cmd->scan_begin_src != TRIG_EXT &&
- cmd->scan_begin_src != TRIG_TIMER)
- err++;
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ /* Step 2a : make sure trigger sources are unique */
+
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -1558,8 +1530,9 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{
- int err = 0, tmp;
struct usbduxsub *this_usbduxsub = dev->private;
+ int err = 0;
+ unsigned int flags;
if (!this_usbduxsub)
return -EFAULT;
@@ -1570,63 +1543,35 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev,
dev_dbg(&this_usbduxsub->interface->dev,
"comedi%d: usbdux_ao_cmdtest\n", dev->minor);
- /* make sure triggers are valid */
- /* Only immediate triggers are allowed */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_INT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
+ /* Step 1 : check if triggers are trivially valid */
+
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
- /* trigger should happen timed */
- tmp = cmd->scan_begin_src;
- /* just now we scan also in the high speed mode every frame */
- /* this is due to ehci driver limitations */
if (0) { /* (this_usbduxsub->high_speed) */
- /* start immediately a new scan */
- /* the sampling rate is set by the coversion rate */
- cmd->scan_begin_src &= TRIG_FOLLOW;
+ /*
+ * start immediately a new scan
+ * the sampling rate is set by the coversion rate
+ */
+ flags = TRIG_FOLLOW;
} else {
/* start a new scan (output at once) with a timer */
- cmd->scan_begin_src &= TRIG_TIMER;
+ flags = TRIG_TIMER;
}
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
-
- /* scanning is continuous */
- tmp = cmd->convert_src;
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags);
- /* all conversion events happen simultaneously */
- cmd->convert_src &= TRIG_NOW;
-
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- /* issue a trigger when scan is finished and start a new scan */
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- /* trigger at the end of count events or not, stop condition or not */
- tmp = cmd->stop_src;
- cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
+ 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 2: make sure trigger sources
- * are unique and mutually compatible
- * note that mutual compatibility is not an issue here
- */
- if (cmd->scan_begin_src != TRIG_FOLLOW &&
- cmd->scan_begin_src != TRIG_EXT &&
- cmd->scan_begin_src != TRIG_TIMER)
- err++;
- if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
- err++;
+ /* Step 2a : make sure trigger sources are unique */
+
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
if (err)
return 2;
@@ -1950,7 +1895,7 @@ static void usbduxsub_pwm_irq(struct urb *urb)
/* the private structure of the subdevice is struct usbduxsub */
this_usbduxsub = this_comedidev->private;
- s = this_comedidev->subdevices + SUBDEV_DA;
+ s = &this_comedidev->subdevices[SUBDEV_DA];
switch (urb->status) {
case 0:
@@ -2301,10 +2246,8 @@ static void tidy_up(struct usbduxsub *usbduxsub_tmp)
usbduxsub_tmp->pwm_cmd_running = 0;
}
-/* common part of attach and attach_usb */
static int usbduxsigma_attach_common(struct comedi_device *dev,
- struct usbduxsub *uds,
- void *aux_data, int aux_len)
+ struct usbduxsub *uds)
{
int ret;
struct comedi_subdevice *s;
@@ -2314,9 +2257,6 @@ static int usbduxsigma_attach_common(struct comedi_device *dev,
down(&uds->sem);
/* pointer back to the corresponding comedi device */
uds->comedidev = dev;
- /* trying to upload the firmware into the FX2 */
- if (aux_data)
- firmwareUpload(uds, aux_data, aux_len);
dev->board_name = "usbduxsigma";
/* set number of subdevices */
if (uds->high_speed)
@@ -2331,7 +2271,7 @@ static int usbduxsigma_attach_common(struct comedi_device *dev,
/* private structure is also simply the usb-structure */
dev->private = uds;
/* the first subdevice is the A/D converter */
- s = dev->subdevices + SUBDEV_AD;
+ s = &dev->subdevices[SUBDEV_AD];
/* the URBs get the comedi subdevice */
/* which is responsible for reading */
/* this is the subdevice which reads data */
@@ -2358,7 +2298,7 @@ static int usbduxsigma_attach_common(struct comedi_device *dev,
/* range table to convert to physical units */
s->range_table = (&range_usbdux_ai_range);
/* analog output subdevice */
- s = dev->subdevices + SUBDEV_DA;
+ s = &dev->subdevices[SUBDEV_DA];
/* analog out */
s->type = COMEDI_SUBD_AO;
/* backward pointer */
@@ -2383,7 +2323,7 @@ static int usbduxsigma_attach_common(struct comedi_device *dev,
s->insn_read = usbdux_ao_insn_read;
s->insn_write = usbdux_ao_insn_write;
/* digital I/O subdevice */
- s = dev->subdevices + SUBDEV_DIO;
+ s = &dev->subdevices[SUBDEV_DIO];
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
/* 8 external and 16 internal channels */
@@ -2396,7 +2336,7 @@ static int usbduxsigma_attach_common(struct comedi_device *dev,
s->private = NULL;
if (uds->high_speed) {
/* timer / pwm subdevice */
- s = dev->subdevices + SUBDEV_PWM;
+ s = &dev->subdevices[SUBDEV_PWM];
s->type = COMEDI_SUBD_PWM;
s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE;
s->n_chan = 8;
@@ -2419,47 +2359,6 @@ static int usbduxsigma_attach_common(struct comedi_device *dev,
return 0;
}
-/* is called for COMEDI_DEVCONFIG ioctl (when comedi_config is run) */
-static int usbduxsigma_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- int ret;
- int index;
- int i;
- void *aux_data;
- int aux_len;
-
- dev->private = NULL;
-
- aux_data = comedi_aux_data(it->options, 0);
- aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH];
- if (aux_data == NULL)
- aux_len = 0;
- else if (aux_len == 0)
- aux_data = NULL;
-
- down(&start_stop_sem);
- /* find a valid device which has been detected by the probe function of
- * the usb */
- index = -1;
- for (i = 0; i < NUMUSBDUX; i++) {
- if ((usbduxsub[i].probed) && (!usbduxsub[i].attached)) {
- index = i;
- break;
- }
- }
- if (index < 0) {
- dev_err(dev->class_dev,
- "usbduxsigma: error: attach failed, dev not connected to the usb bus.\n");
- ret = -ENODEV;
- } else
- ret = usbduxsigma_attach_common(dev, &usbduxsub[index],
- aux_data, aux_len);
- up(&start_stop_sem);
- return ret;
-}
-
-/* is called from comedi_usb_auto_config() */
static int usbduxsigma_attach_usb(struct comedi_device *dev,
struct usb_interface *uinterf)
{
@@ -2478,7 +2377,7 @@ static int usbduxsigma_attach_usb(struct comedi_device *dev,
"usbduxsigma: error: attach_usb failed, already attached\n");
ret = -ENODEV;
} else
- ret = usbduxsigma_attach_common(dev, uds, NULL, 0);
+ ret = usbduxsigma_attach_common(dev, uds);
up(&start_stop_sem);
return ret;
}
@@ -2499,9 +2398,8 @@ static void usbduxsigma_detach(struct comedi_device *dev)
static struct comedi_driver usbduxsigma_driver = {
.driver_name = "usbduxsigma",
.module = THIS_MODULE,
- .attach = usbduxsigma_attach,
- .detach = usbduxsigma_detach,
.attach_usb = usbduxsigma_attach_usb,
+ .detach = usbduxsigma_detach,
};
static void usbdux_firmware_request_complete_handler(const struct firmware *fw,
diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c
index 94010fc05905..df277aa591bb 100644
--- a/drivers/staging/comedi/drivers/vmk80xx.c
+++ b/drivers/staging/comedi/drivers/vmk80xx.c
@@ -546,6 +546,7 @@ static int vmk80xx_ai_rinsn(struct comedi_device *cdev,
reg[0] = VMK8055_AI2_REG;
break;
case VMK8061_MODEL:
+ default:
reg[0] = VMK8061_AI_REG1;
reg[1] = VMK8061_AI_REG2;
dev->usb_tx_buf[0] = VMK8061_CMD_RD_AI;
@@ -904,6 +905,7 @@ static int vmk80xx_cnt_rinsn(struct comedi_device *cdev,
reg[0] = VMK8055_CNT2_REG;
break;
case VMK8061_MODEL:
+ default:
reg[0] = VMK8061_CNT_REG;
reg[1] = VMK8061_CNT_REG;
dev->usb_tx_buf[0] = VMK8061_CMD_RD_CNT;
@@ -1119,7 +1121,7 @@ static int vmk80xx_attach_common(struct comedi_device *cdev,
return ret;
}
/* Analog input subdevice */
- s = cdev->subdevices + VMK80XX_SUBD_AI;
+ s = &cdev->subdevices[VMK80XX_SUBD_AI];
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_GROUND;
s->n_chan = dev->board.ai_chans;
@@ -1127,7 +1129,7 @@ static int vmk80xx_attach_common(struct comedi_device *cdev,
s->range_table = dev->board.range;
s->insn_read = vmk80xx_ai_rinsn;
/* Analog output subdevice */
- s = cdev->subdevices + VMK80XX_SUBD_AO;
+ s = &cdev->subdevices[VMK80XX_SUBD_AO];
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITEABLE | SDF_GROUND;
s->n_chan = dev->board.ao_chans;
@@ -1139,7 +1141,7 @@ static int vmk80xx_attach_common(struct comedi_device *cdev,
s->insn_read = vmk80xx_ao_rinsn;
}
/* Digital input subdevice */
- s = cdev->subdevices + VMK80XX_SUBD_DI;
+ s = &cdev->subdevices[VMK80XX_SUBD_DI];
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE | SDF_GROUND;
s->n_chan = dev->board.di_chans;
@@ -1147,7 +1149,7 @@ static int vmk80xx_attach_common(struct comedi_device *cdev,
s->insn_read = vmk80xx_di_rinsn;
s->insn_bits = vmk80xx_di_bits;
/* Digital output subdevice */
- s = cdev->subdevices + VMK80XX_SUBD_DO;
+ s = &cdev->subdevices[VMK80XX_SUBD_DO];
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITEABLE | SDF_GROUND;
s->n_chan = dev->board.do_chans;
@@ -1159,7 +1161,7 @@ static int vmk80xx_attach_common(struct comedi_device *cdev,
s->insn_read = vmk80xx_do_rinsn;
}
/* Counter subdevice */
- s = cdev->subdevices + VMK80XX_SUBD_CNT;
+ s = &cdev->subdevices[VMK80XX_SUBD_CNT];
s->type = COMEDI_SUBD_COUNTER;
s->subdev_flags = SDF_READABLE;
s->n_chan = dev->board.cnt_chans;
@@ -1172,7 +1174,7 @@ static int vmk80xx_attach_common(struct comedi_device *cdev,
}
/* PWM subdevice */
if (dev->board.model == VMK8061_MODEL) {
- s = cdev->subdevices + VMK80XX_SUBD_PWM;
+ s = &cdev->subdevices[VMK80XX_SUBD_PWM];
s->type = COMEDI_SUBD_PWM;
s->subdev_flags = SDF_READABLE | SDF_WRITEABLE;
s->n_chan = dev->board.pwm_chans;