aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/comedi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/comedi')
-rw-r--r--drivers/staging/comedi/Kconfig46
-rw-r--r--drivers/staging/comedi/Makefile19
-rw-r--r--drivers/staging/comedi/comedi.h12
-rw-r--r--drivers/staging/comedi/comedi_buf.c415
-rw-r--r--drivers/staging/comedi/comedi_compat32.c4
-rw-r--r--drivers/staging/comedi/comedi_fops.c1007
-rw-r--r--drivers/staging/comedi/comedi_internal.h33
-rw-r--r--drivers/staging/comedi/comedi_pci.c140
-rw-r--r--drivers/staging/comedi/comedi_pcmcia.c160
-rw-r--r--drivers/staging/comedi/comedi_usb.c108
-rw-r--r--drivers/staging/comedi/comedidev.h370
-rw-r--r--drivers/staging/comedi/drivers.c859
-rw-r--r--drivers/staging/comedi/drivers/8255_pci.c9
-rw-r--r--drivers/staging/comedi/drivers/Makefile4
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.c26
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c807
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c263
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c589
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_035.c9
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1032.c10
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1500.c9
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1516.c114
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1564.c9
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_16xx.c257
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1710.c9
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_2032.c282
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_2200.c187
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3120.c9
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3200.c9
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3501.c482
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3xxx.c9
-rw-r--r--drivers/staging/comedi/drivers/addi_watchdog.c172
-rw-r--r--drivers/staging/comedi/drivers/addi_watchdog.h10
-rw-r--r--drivers/staging/comedi/drivers/adl_pci6208.c9
-rw-r--r--drivers/staging/comedi/drivers/adl_pci7x3x.c17
-rw-r--r--drivers/staging/comedi/drivers/adl_pci8164.c39
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9111.c12
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9118.c13
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1710.c8
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1723.c9
-rw-r--r--drivers/staging/comedi/drivers/adv_pci_dio.c12
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200.c20
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc236.c8
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc263.c9
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci224.c8
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci230.c12
-rw-r--r--drivers/staging/comedi/drivers/cb_das16_cs.c132
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas.c11
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas64.c12
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidda.c9
-rw-r--r--drivers/staging/comedi/drivers/cb_pcimdas.c12
-rw-r--r--drivers/staging/comedi/drivers/cb_pcimdda.c9
-rw-r--r--drivers/staging/comedi/drivers/comedi_bond.c5
-rw-r--r--drivers/staging/comedi/drivers/comedi_test.c75
-rw-r--r--drivers/staging/comedi/drivers/contec_pci_dio.c9
-rw-r--r--drivers/staging/comedi/drivers/daqboard2000.c14
-rw-r--r--drivers/staging/comedi/drivers/das08.c358
-rw-r--r--drivers/staging/comedi/drivers/das08.h2
-rw-r--r--drivers/staging/comedi/drivers/das08_cs.c152
-rw-r--r--drivers/staging/comedi/drivers/das08_isa.c217
-rw-r--r--drivers/staging/comedi/drivers/das08_pci.c121
-rw-r--r--drivers/staging/comedi/drivers/das16.c2
-rw-r--r--drivers/staging/comedi/drivers/dt3000.c11
-rw-r--r--drivers/staging/comedi/drivers/dt9812.c30
-rw-r--r--drivers/staging/comedi/drivers/dyna_pci10xx.c11
-rw-r--r--drivers/staging/comedi/drivers/gsc_hpdi.c11
-rw-r--r--drivers/staging/comedi/drivers/icp_multi.c13
-rw-r--r--drivers/staging/comedi/drivers/jr3_pci.c15
-rw-r--r--drivers/staging/comedi/drivers/ke_counter.c9
-rw-r--r--drivers/staging/comedi/drivers/me4000.c14
-rw-r--r--drivers/staging/comedi/drivers/me_daq.c9
-rw-r--r--drivers/staging/comedi/drivers/mite.c5
-rw-r--r--drivers/staging/comedi/drivers/ni_6527.c9
-rw-r--r--drivers/staging/comedi/drivers/ni_65xx.c10
-rw-r--r--drivers/staging/comedi/drivers/ni_660x.c10
-rw-r--r--drivers/staging/comedi/drivers/ni_670x.c9
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_700.c119
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_dio24.c303
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc.c55
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc_cs.c257
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_common.c4
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_cs.c399
-rw-r--r--drivers/staging/comedi/drivers/ni_pcidio.c9
-rw-r--r--drivers/staging/comedi/drivers/ni_pcimio.c11
-rw-r--r--drivers/staging/comedi/drivers/ni_tio.c2
-rw-r--r--drivers/staging/comedi/drivers/ni_tiocmd.c1
-rw-r--r--drivers/staging/comedi/drivers/pcl818.c19
-rw-r--r--drivers/staging/comedi/drivers/pcm_common.c63
-rw-r--r--drivers/staging/comedi/drivers/pcm_common.h8
-rw-r--r--drivers/staging/comedi/drivers/pcmda12.c3
-rw-r--r--drivers/staging/comedi/drivers/pcmmio.c62
-rw-r--r--drivers/staging/comedi/drivers/pcmuio.c72
-rw-r--r--drivers/staging/comedi/drivers/quatech_daqp_cs.c589
-rw-r--r--drivers/staging/comedi/drivers/rtd520.c10
-rw-r--r--drivers/staging/comedi/drivers/s626.c8
-rw-r--r--drivers/staging/comedi/drivers/skel.c12
-rw-r--r--drivers/staging/comedi/drivers/unioxx5.c6
-rw-r--r--drivers/staging/comedi/drivers/usbdux.c29
-rw-r--r--drivers/staging/comedi/drivers/usbduxfast.c8
-rw-r--r--drivers/staging/comedi/drivers/usbduxsigma.c33
-rw-r--r--drivers/staging/comedi/drivers/vmk80xx.c1272
-rw-r--r--drivers/staging/comedi/kcomedilib/kcomedilib_main.c8
-rw-r--r--drivers/staging/comedi/proc.c9
104 files changed, 4572 insertions, 6731 deletions
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
index 36eec320569c..1967852eeb17 100644
--- a/drivers/staging/comedi/Kconfig
+++ b/drivers/staging/comedi/Kconfig
@@ -1,7 +1,6 @@
config COMEDI
tristate "Data acquisition support (comedi)"
depends on m
- depends on BROKEN || FRV || M32R || MN10300 || SUPERH || TILE || X86
---help---
Enable support a wide range of data acquisition devices
for Linux.
@@ -165,7 +164,7 @@ config COMEDI_PCL730
config COMEDI_PCL812
tristate "Advantech PCL-812/813 and ADlink ACL-8112/8113/8113/8216"
- depends on VIRT_TO_BUS
+ depends on VIRT_TO_BUS && ISA_DMA_API
---help---
Enable support for Advantech PCL-812/PG, PCL-813/B, ADLink
ACL-8112DG/HG/PG, ACL-8113, ACL-8216, ICP DAS A-821PGH/PGL/PGL-NDA,
@@ -176,7 +175,7 @@ config COMEDI_PCL812
config COMEDI_PCL816
tristate "Advantech PCL-814 and PCL-816 ISA card support"
- depends on VIRT_TO_BUS
+ depends on VIRT_TO_BUS && ISA_DMA_API
---help---
Enable support for Advantech PCL-814 and PCL-816 ISA cards
@@ -185,7 +184,7 @@ config COMEDI_PCL816
config COMEDI_PCL818
tristate "Advantech PCL-718 and PCL-818 ISA card support"
- depends on VIRT_TO_BUS
+ depends on VIRT_TO_BUS && ISA_DMA_API
---help---
Enable support for Advantech PCL-818 ISA cards
PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818 and PCL-718
@@ -275,10 +274,11 @@ config COMEDI_DAS08_ISA
DAS08/JR-16-AO, PC104-DAS08, DAS08/JR/16.
To compile this driver as a module, choose M here: the module will be
- called das08.
+ called das08_isa.
config COMEDI_DAS16
tristate "DAS-16 compatible ISA and PC/104 card support"
+ depends on ISA_DMA_API
select COMEDI_8255
select COMEDI_FC
---help---
@@ -308,7 +308,7 @@ config COMEDI_DAS800
config COMEDI_DAS1800
tristate "DAS1800 and compatible ISA card support"
- depends on VIRT_TO_BUS
+ depends on VIRT_TO_BUS && ISA_DMA_API
select COMEDI_FC
---help---
Enable support for DAS1800 and compatible ISA cards
@@ -373,7 +373,7 @@ config COMEDI_DT2817
config COMEDI_DT282X
tristate "Data Translation DT2821 series and DT-EZ ISA card support"
select COMEDI_FC
- depends on VIRT_TO_BUS
+ depends on VIRT_TO_BUS && ISA_DMA_API
---help---
Enable support for Data Translation DT2821 series including DT-EZ
DT2821, DT2821-F-16SE, DT2821-F-8DI, DT2821-G-16SE, DT2821-G-8DI,
@@ -445,7 +445,7 @@ config COMEDI_ADQ12B
config COMEDI_NI_AT_A2150
tristate "NI AT-A2150 ISA card support"
select COMEDI_FC
- depends on VIRT_TO_BUS
+ depends on VIRT_TO_BUS && ISA_DMA_API
---help---
Enable support for National Instruments AT-A2150 cards
@@ -542,11 +542,7 @@ menuconfig COMEDI_PCI_DRIVERS
bool "Comedi PCI drivers"
depends on PCI
---help---
- Enable comedi PCI drivers to be built
-
- Note that the answer to this question won't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the questions about PCI comedi drivers.
+ Enable support for comedi PCI drivers.
if COMEDI_PCI_DRIVERS
@@ -567,6 +563,13 @@ config COMEDI_8255_PCI
To compile this driver as a module, choose M here: the module will
be called 8255_pci.
+config COMEDI_ADDI_WATCHDOG
+ tristate
+ ---help---
+ Provides support for the watchdog subdevice found on many ADDI-DATA
+ boards. This module will be automatically selected when needed. The
+ module will be called addi_watchdog.
+
config COMEDI_ADDI_APCI_035
tristate "ADDI-DATA APCI_035 support"
---help---
@@ -593,6 +596,7 @@ config COMEDI_ADDI_APCI_1500
config COMEDI_ADDI_APCI_1516
tristate "ADDI-DATA APCI-1016/1516/2016 support"
+ select COMEDI_ADDI_WATCHDOG
---help---
Enable support for ADDI-DATA APCI-1016, APCI-1516 and APCI-2016 boards.
These are 16 channel, optically isolated, digital I/O boards. The 1516
@@ -619,6 +623,7 @@ config COMEDI_ADDI_APCI_16XX
config COMEDI_ADDI_APCI_2032
tristate "ADDI-DATA APCI_2032 support"
+ select COMEDI_ADDI_WATCHDOG
---help---
Enable support for ADDI-DATA APCI_2032 cards
@@ -627,6 +632,7 @@ config COMEDI_ADDI_APCI_2032
config COMEDI_ADDI_APCI_2200
tristate "ADDI-DATA APCI_2200 support"
+ select COMEDI_ADDI_WATCHDOG
---help---
Enable support for ADDI-DATA APCI_2200 cards
@@ -796,7 +802,7 @@ config COMEDI_DAS08_PCI
Enable support for PCI DAS-08 cards.
To compile this driver as a module, choose M here: the module will be
- called das08.
+ called das08_pci.
config COMEDI_DT3000
tristate "Data Translation DT3000 series support"
@@ -1084,11 +1090,7 @@ menuconfig COMEDI_PCMCIA_DRIVERS
bool "Comedi PCMCIA drivers"
depends on PCMCIA
---help---
- Enable comedi PCMCIA and PCCARD drivers to be built
-
- Note that the answer to this question won't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the questions about PCMCIA comedi drivers.
+ Enable support for comedi PCMCIA drivers.
if COMEDI_PCMCIA_DRIVERS
@@ -1165,11 +1167,7 @@ menuconfig COMEDI_USB_DRIVERS
bool "Comedi USB drivers"
depends on USB
---help---
- Enable comedi USB drivers to be built
-
- Note that the answer to this question won't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the questions about USB comedi drivers.
+ Enable support for comedi USB drivers.
if COMEDI_USB_DRIVERS
diff --git a/drivers/staging/comedi/Makefile b/drivers/staging/comedi/Makefile
index 8dbd306fef88..e6dfc98f8c8e 100644
--- a/drivers/staging/comedi/Makefile
+++ b/drivers/staging/comedi/Makefile
@@ -1,11 +1,12 @@
-obj-$(CONFIG_COMEDI) += comedi.o
+comedi-y := comedi_fops.o range.o drivers.o \
+ comedi_buf.o
+comedi-$(CONFIG_COMEDI_PCI_DRIVERS) += comedi_pci.o
+comedi-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += comedi_pcmcia.o
+comedi-$(CONFIG_COMEDI_USB_DRIVERS) += comedi_usb.o
+comedi-$(CONFIG_PROC_FS) += proc.o
+comedi-$(CONFIG_COMPAT) += comedi_compat32.o
-obj-$(CONFIG_COMEDI) += kcomedilib/
-obj-$(CONFIG_COMEDI) += drivers/
+obj-$(CONFIG_COMEDI) += comedi.o
-comedi-y := \
- comedi_fops.o \
- proc.o \
- range.o \
- drivers.o \
- comedi_compat32.o \
+obj-$(CONFIG_COMEDI) += kcomedilib/
+obj-$(CONFIG_COMEDI) += drivers/
diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
index c8a8ca126127..4233605df30a 100644
--- a/drivers/staging/comedi/comedi.h
+++ b/drivers/staging/comedi/comedi.h
@@ -41,7 +41,17 @@
/* number of config options in the config structure */
#define COMEDI_NDEVCONFOPTS 32
-/*length of nth chunk of firmware data*/
+
+/*
+ * NOTE: 'comedi_config --init-data' is deprecated
+ *
+ * The following indexes in the config options were used by
+ * comedi_config to pass firmware blobs from user space to the
+ * comedi drivers. The request_firmware() hotplug interface is
+ * now used by all comedi drivers instead.
+ */
+
+/* length of nth chunk of firmware data -*/
#define COMEDI_DEVCONF_AUX_DATA3_LENGTH 25
#define COMEDI_DEVCONF_AUX_DATA2_LENGTH 26
#define COMEDI_DEVCONF_AUX_DATA1_LENGTH 27
diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c
new file mode 100644
index 000000000000..9b997ae67796
--- /dev/null
+++ b/drivers/staging/comedi/comedi_buf.c
@@ -0,0 +1,415 @@
+/*
+ * comedi_buf.c
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1997-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.
+ */
+
+#include "comedidev.h"
+#include "comedi_internal.h"
+
+#ifdef PAGE_KERNEL_NOCACHE
+#define COMEDI_PAGE_PROTECTION PAGE_KERNEL_NOCACHE
+#else
+#define COMEDI_PAGE_PROTECTION PAGE_KERNEL
+#endif
+
+static void __comedi_buf_free(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned n_pages)
+{
+ struct comedi_async *async = s->async;
+ struct comedi_buf_page *buf;
+ unsigned i;
+
+ if (async->prealloc_buf) {
+ vunmap(async->prealloc_buf);
+ async->prealloc_buf = NULL;
+ async->prealloc_bufsz = 0;
+ }
+
+ if (!async->buf_page_list)
+ return;
+
+ for (i = 0; i < n_pages; ++i) {
+ buf = &async->buf_page_list[i];
+ if (buf->virt_addr) {
+ clear_bit(PG_reserved,
+ &(virt_to_page(buf->virt_addr)->flags));
+ if (s->async_dma_dir != DMA_NONE) {
+ dma_free_coherent(dev->hw_dev,
+ PAGE_SIZE,
+ buf->virt_addr,
+ buf->dma_addr);
+ } else {
+ free_page((unsigned long)buf->virt_addr);
+ }
+ }
+ }
+ vfree(async->buf_page_list);
+ async->buf_page_list = NULL;
+ async->n_buf_pages = 0;
+}
+
+static void __comedi_buf_alloc(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned n_pages)
+{
+ struct comedi_async *async = s->async;
+ struct page **pages = NULL;
+ struct comedi_buf_page *buf;
+ unsigned i;
+
+ async->buf_page_list = vzalloc(sizeof(*buf) * n_pages);
+ if (async->buf_page_list)
+ pages = vmalloc(sizeof(struct page *) * n_pages);
+
+ if (!pages)
+ return;
+
+ for (i = 0; i < n_pages; i++) {
+ buf = &async->buf_page_list[i];
+ if (s->async_dma_dir != DMA_NONE)
+ buf->virt_addr = dma_alloc_coherent(dev->hw_dev,
+ PAGE_SIZE,
+ &buf->dma_addr,
+ GFP_KERNEL |
+ __GFP_COMP);
+ else
+ buf->virt_addr = (void *)get_zeroed_page(GFP_KERNEL);
+ if (!buf->virt_addr)
+ break;
+
+ set_bit(PG_reserved, &(virt_to_page(buf->virt_addr)->flags));
+
+ pages[i] = virt_to_page(buf->virt_addr);
+ }
+
+ /* vmap the prealloc_buf if all the pages were allocated */
+ if (i == n_pages)
+ async->prealloc_buf = vmap(pages, n_pages, VM_MAP,
+ COMEDI_PAGE_PROTECTION);
+
+ vfree(pages);
+}
+
+int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
+ unsigned long new_size)
+{
+ struct comedi_async *async = s->async;
+
+ /* Round up new_size to multiple of PAGE_SIZE */
+ new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
+
+ /* if no change is required, do nothing */
+ if (async->prealloc_buf && async->prealloc_bufsz == new_size)
+ return 0;
+
+ /* deallocate old buffer */
+ __comedi_buf_free(dev, s, async->n_buf_pages);
+
+ /* allocate new buffer */
+ if (new_size) {
+ unsigned n_pages = new_size >> PAGE_SHIFT;
+
+ __comedi_buf_alloc(dev, s, n_pages);
+
+ if (!async->prealloc_buf) {
+ /* allocation failed */
+ __comedi_buf_free(dev, s, n_pages);
+ return -ENOMEM;
+ }
+ async->n_buf_pages = n_pages;
+ }
+ async->prealloc_bufsz = new_size;
+
+ return 0;
+}
+
+void comedi_buf_reset(struct comedi_async *async)
+{
+ async->buf_write_alloc_count = 0;
+ async->buf_write_count = 0;
+ async->buf_read_alloc_count = 0;
+ async->buf_read_count = 0;
+
+ async->buf_write_ptr = 0;
+ async->buf_read_ptr = 0;
+
+ async->cur_chan = 0;
+ async->scan_progress = 0;
+ async->munge_chan = 0;
+ async->munge_count = 0;
+ async->munge_ptr = 0;
+
+ async->events = 0;
+}
+
+static unsigned int comedi_buf_write_n_available(struct comedi_async *async)
+{
+ unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
+
+ return free_end - async->buf_write_alloc_count;
+}
+
+static unsigned int __comedi_buf_write_alloc(struct comedi_async *async,
+ unsigned int nbytes,
+ int strict)
+{
+ unsigned int available = comedi_buf_write_n_available(async);
+
+ if (nbytes > available)
+ nbytes = strict ? 0 : available;
+
+ async->buf_write_alloc_count += nbytes;
+
+ /*
+ * ensure the async buffer 'counts' are read and updated
+ * before we write data to the write-alloc'ed buffer space
+ */
+ smp_mb();
+
+ return nbytes;
+}
+
+/* allocates chunk for the writer from free buffer space */
+unsigned int comedi_buf_write_alloc(struct comedi_async *async,
+ unsigned int nbytes)
+{
+ return __comedi_buf_write_alloc(async, nbytes, 0);
+}
+EXPORT_SYMBOL(comedi_buf_write_alloc);
+
+/*
+ * munging is applied to data by core as it passes between user
+ * and kernel space
+ */
+static unsigned int comedi_buf_munge(struct comedi_async *async,
+ unsigned int num_bytes)
+{
+ struct comedi_subdevice *s = async->subdevice;
+ unsigned int count = 0;
+ const unsigned num_sample_bytes = bytes_per_sample(s);
+
+ if (!s->munge || (async->cmd.flags & CMDF_RAWDATA)) {
+ async->munge_count += num_bytes;
+ count = num_bytes;
+ } else {
+ /* don't munge partial samples */
+ num_bytes -= num_bytes % num_sample_bytes;
+ while (count < num_bytes) {
+ int block_size = num_bytes - count;
+ unsigned int buf_end;
+
+ buf_end = async->prealloc_bufsz - async->munge_ptr;
+ if (block_size > buf_end)
+ block_size = buf_end;
+
+ s->munge(s->device, s,
+ async->prealloc_buf + async->munge_ptr,
+ block_size, async->munge_chan);
+
+ /*
+ * ensure data is munged in buffer before the
+ * async buffer munge_count is incremented
+ */
+ smp_wmb();
+
+ async->munge_chan += block_size / num_sample_bytes;
+ async->munge_chan %= async->cmd.chanlist_len;
+ async->munge_count += block_size;
+ async->munge_ptr += block_size;
+ async->munge_ptr %= async->prealloc_bufsz;
+ count += block_size;
+ }
+ }
+
+ return count;
+}
+
+unsigned int comedi_buf_write_n_allocated(struct comedi_async *async)
+{
+ return async->buf_write_alloc_count - async->buf_write_count;
+}
+
+/* transfers a chunk from writer to filled buffer space */
+unsigned int comedi_buf_write_free(struct comedi_async *async,
+ unsigned int nbytes)
+{
+ unsigned int allocated = comedi_buf_write_n_allocated(async);
+
+ if (nbytes > allocated)
+ nbytes = allocated;
+
+ async->buf_write_count += nbytes;
+ async->buf_write_ptr += nbytes;
+ comedi_buf_munge(async, async->buf_write_count - async->munge_count);
+ if (async->buf_write_ptr >= async->prealloc_bufsz)
+ async->buf_write_ptr %= async->prealloc_bufsz;
+
+ return nbytes;
+}
+EXPORT_SYMBOL(comedi_buf_write_free);
+
+unsigned int comedi_buf_read_n_available(struct comedi_async *async)
+{
+ unsigned num_bytes;
+
+ if (!async)
+ return 0;
+
+ num_bytes = async->munge_count - async->buf_read_count;
+
+ /*
+ * ensure the async buffer 'counts' are read before we
+ * attempt to read data from the buffer
+ */
+ smp_rmb();
+
+ return num_bytes;
+}
+EXPORT_SYMBOL(comedi_buf_read_n_available);
+
+/* allocates a chunk for the reader from filled (and munged) buffer space */
+unsigned int comedi_buf_read_alloc(struct comedi_async *async,
+ unsigned int nbytes)
+{
+ unsigned int available;
+
+ available = async->munge_count - async->buf_read_alloc_count;
+ if (nbytes > available)
+ nbytes = available;
+
+ async->buf_read_alloc_count += nbytes;
+
+ /*
+ * ensure the async buffer 'counts' are read before we
+ * attempt to read data from the read-alloc'ed buffer space
+ */
+ smp_rmb();
+
+ return nbytes;
+}
+EXPORT_SYMBOL(comedi_buf_read_alloc);
+
+static unsigned int comedi_buf_read_n_allocated(struct comedi_async *async)
+{
+ return async->buf_read_alloc_count - async->buf_read_count;
+}
+
+/* transfers control of a chunk from reader to free buffer space */
+unsigned int comedi_buf_read_free(struct comedi_async *async,
+ unsigned int nbytes)
+{
+ unsigned int allocated;
+
+ /*
+ * ensure data has been read out of buffer before
+ * the async read count is incremented
+ */
+ smp_mb();
+
+ allocated = comedi_buf_read_n_allocated(async);
+ if (nbytes > allocated)
+ nbytes = allocated;
+
+ async->buf_read_count += nbytes;
+ async->buf_read_ptr += nbytes;
+ async->buf_read_ptr %= async->prealloc_bufsz;
+ return nbytes;
+}
+EXPORT_SYMBOL(comedi_buf_read_free);
+
+int comedi_buf_put(struct comedi_async *async, short x)
+{
+ unsigned int n = __comedi_buf_write_alloc(async, sizeof(short), 1);
+
+ if (n < sizeof(short)) {
+ async->events |= COMEDI_CB_ERROR;
+ return 0;
+ }
+ *(short *)(async->prealloc_buf + async->buf_write_ptr) = x;
+ comedi_buf_write_free(async, sizeof(short));
+ return 1;
+}
+EXPORT_SYMBOL(comedi_buf_put);
+
+int comedi_buf_get(struct comedi_async *async, short *x)
+{
+ unsigned int n = comedi_buf_read_n_available(async);
+
+ if (n < sizeof(short))
+ return 0;
+ comedi_buf_read_alloc(async, sizeof(short));
+ *x = *(short *)(async->prealloc_buf + async->buf_read_ptr);
+ comedi_buf_read_free(async, sizeof(short));
+ return 1;
+}
+EXPORT_SYMBOL(comedi_buf_get);
+
+void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset,
+ const void *data, unsigned int num_bytes)
+{
+ unsigned int write_ptr = async->buf_write_ptr + offset;
+
+ if (write_ptr >= async->prealloc_bufsz)
+ write_ptr %= async->prealloc_bufsz;
+
+ while (num_bytes) {
+ unsigned int block_size;
+
+ if (write_ptr + num_bytes > async->prealloc_bufsz)
+ block_size = async->prealloc_bufsz - write_ptr;
+ else
+ block_size = num_bytes;
+
+ memcpy(async->prealloc_buf + write_ptr, data, block_size);
+
+ data += block_size;
+ num_bytes -= block_size;
+
+ write_ptr = 0;
+ }
+}
+EXPORT_SYMBOL(comedi_buf_memcpy_to);
+
+void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset,
+ void *dest, unsigned int nbytes)
+{
+ void *src;
+ unsigned int read_ptr = async->buf_read_ptr + offset;
+
+ if (read_ptr >= async->prealloc_bufsz)
+ read_ptr %= async->prealloc_bufsz;
+
+ while (nbytes) {
+ unsigned int block_size;
+
+ src = async->prealloc_buf + read_ptr;
+
+ if (nbytes >= async->prealloc_bufsz - read_ptr)
+ block_size = async->prealloc_bufsz - read_ptr;
+ else
+ block_size = nbytes;
+
+ memcpy(dest, src, block_size);
+ nbytes -= block_size;
+ dest += block_size;
+ read_ptr = 0;
+ }
+}
+EXPORT_SYMBOL(comedi_buf_memcpy_from);
diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c
index 4b7cbfad1d74..ad208cdd53d4 100644
--- a/drivers/staging/comedi/comedi_compat32.c
+++ b/drivers/staging/comedi/comedi_compat32.c
@@ -30,8 +30,6 @@
#include "comedi.h"
#include "comedi_compat32.h"
-#ifdef CONFIG_COMPAT
-
#define COMEDI32_CHANINFO _IOR(CIO, 3, struct comedi32_chaninfo_struct)
#define COMEDI32_RANGEINFO _IOR(CIO, 8, struct comedi32_rangeinfo_struct)
/* N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR.
@@ -460,5 +458,3 @@ long comedi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
return raw_ioctl(file, cmd, arg);
}
-
-#endif /* CONFIG_COMPAT */
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 9b038e4a7e71..195d56d8a1ee 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -49,10 +49,6 @@
#include "comedi_internal.h"
-MODULE_AUTHOR("http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi core module");
-MODULE_LICENSE("GPL");
-
#ifdef CONFIG_COMEDI_DEBUG
int comedi_debug;
EXPORT_SYMBOL(comedi_debug);
@@ -62,11 +58,6 @@ MODULE_PARM_DESC(comedi_debug,
);
#endif
-bool comedi_autoconfig = 1;
-module_param(comedi_autoconfig, bool, S_IRUGO);
-MODULE_PARM_DESC(comedi_autoconfig,
- "enable drivers to auto-configure comedi devices (default 1)");
-
static int comedi_num_legacy_minors;
module_param(comedi_num_legacy_minors, int, S_IRUGO);
MODULE_PARM_DESC(comedi_num_legacy_minors,
@@ -86,17 +77,58 @@ MODULE_PARM_DESC(comedi_default_buf_maxsize_kb,
"default maximum size of asynchronous buffer in KiB (default "
__MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB) ")");
+struct comedi_file_info {
+ struct comedi_device *device;
+ struct comedi_subdevice *read_subdevice;
+ struct comedi_subdevice *write_subdevice;
+ struct device *hardware_device;
+};
+
static DEFINE_SPINLOCK(comedi_file_info_table_lock);
-static struct comedi_device_file_info
-*comedi_file_info_table[COMEDI_NUM_MINORS];
+static struct comedi_file_info *comedi_file_info_table[COMEDI_NUM_MINORS];
-static void do_become_nonbusy(struct comedi_device *dev,
- struct comedi_subdevice *s);
-static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+static struct comedi_file_info *comedi_file_info_from_minor(unsigned minor)
+{
+ struct comedi_file_info *info;
+
+ BUG_ON(minor >= COMEDI_NUM_MINORS);
+ spin_lock(&comedi_file_info_table_lock);
+ info = comedi_file_info_table[minor];
+ spin_unlock(&comedi_file_info_table_lock);
+ return info;
+}
+
+static struct comedi_device *
+comedi_dev_from_file_info(struct comedi_file_info *info)
+{
+ return info ? info->device : NULL;
+}
+
+struct comedi_device *comedi_dev_from_minor(unsigned minor)
+{
+ return comedi_dev_from_file_info(comedi_file_info_from_minor(minor));
+}
+EXPORT_SYMBOL_GPL(comedi_dev_from_minor);
-static int comedi_fasync(int fd, struct file *file, int on);
+static struct comedi_subdevice *
+comedi_read_subdevice(const struct comedi_file_info *info)
+{
+ if (info->read_subdevice)
+ return info->read_subdevice;
+ if (info->device)
+ return info->device->read_subdev;
+ return NULL;
+}
-static int is_device_busy(struct comedi_device *dev);
+static struct comedi_subdevice *
+comedi_write_subdevice(const struct comedi_file_info *info)
+{
+ if (info->write_subdevice)
+ return info->write_subdevice;
+ if (info->device)
+ return info->device->write_subdev;
+ return NULL;
+}
static int resize_async_buffer(struct comedi_device *dev,
struct comedi_subdevice *s,
@@ -134,7 +166,7 @@ static int resize_async_buffer(struct comedi_device *dev,
}
DPRINTK("comedi%i subd %d buffer resized to %i bytes\n",
- dev->minor, (int)(s - dev->subdevices), async->prealloc_bufsz);
+ dev->minor, s->index, async->prealloc_bufsz);
return 0;
}
@@ -143,8 +175,8 @@ static int resize_async_buffer(struct comedi_device *dev,
static ssize_t show_max_read_buffer_kb(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct comedi_device_file_info *info = dev_get_drvdata(dev);
- struct comedi_subdevice *s = comedi_get_read_subdevice(info);
+ struct comedi_file_info *info = dev_get_drvdata(dev);
+ struct comedi_subdevice *s = comedi_read_subdevice(info);
unsigned int size = 0;
mutex_lock(&info->device->mutex);
@@ -159,8 +191,8 @@ static ssize_t store_max_read_buffer_kb(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct comedi_device_file_info *info = dev_get_drvdata(dev);
- struct comedi_subdevice *s = comedi_get_read_subdevice(info);
+ struct comedi_file_info *info = dev_get_drvdata(dev);
+ struct comedi_subdevice *s = comedi_read_subdevice(info);
unsigned int size;
int err;
@@ -184,8 +216,8 @@ static ssize_t store_max_read_buffer_kb(struct device *dev,
static ssize_t show_read_buffer_kb(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct comedi_device_file_info *info = dev_get_drvdata(dev);
- struct comedi_subdevice *s = comedi_get_read_subdevice(info);
+ struct comedi_file_info *info = dev_get_drvdata(dev);
+ struct comedi_subdevice *s = comedi_read_subdevice(info);
unsigned int size = 0;
mutex_lock(&info->device->mutex);
@@ -200,8 +232,8 @@ static ssize_t store_read_buffer_kb(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct comedi_device_file_info *info = dev_get_drvdata(dev);
- struct comedi_subdevice *s = comedi_get_read_subdevice(info);
+ struct comedi_file_info *info = dev_get_drvdata(dev);
+ struct comedi_subdevice *s = comedi_read_subdevice(info);
unsigned int size;
int err;
@@ -226,8 +258,8 @@ static ssize_t show_max_write_buffer_kb(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct comedi_device_file_info *info = dev_get_drvdata(dev);
- struct comedi_subdevice *s = comedi_get_write_subdevice(info);
+ struct comedi_file_info *info = dev_get_drvdata(dev);
+ struct comedi_subdevice *s = comedi_write_subdevice(info);
unsigned int size = 0;
mutex_lock(&info->device->mutex);
@@ -242,8 +274,8 @@ static ssize_t store_max_write_buffer_kb(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct comedi_device_file_info *info = dev_get_drvdata(dev);
- struct comedi_subdevice *s = comedi_get_write_subdevice(info);
+ struct comedi_file_info *info = dev_get_drvdata(dev);
+ struct comedi_subdevice *s = comedi_write_subdevice(info);
unsigned int size;
int err;
@@ -267,8 +299,8 @@ static ssize_t store_max_write_buffer_kb(struct device *dev,
static ssize_t show_write_buffer_kb(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct comedi_device_file_info *info = dev_get_drvdata(dev);
- struct comedi_subdevice *s = comedi_get_write_subdevice(info);
+ struct comedi_file_info *info = dev_get_drvdata(dev);
+ struct comedi_subdevice *s = comedi_write_subdevice(info);
unsigned int size = 0;
mutex_lock(&info->device->mutex);
@@ -283,8 +315,8 @@ static ssize_t store_write_buffer_kb(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct comedi_device_file_info *info = dev_get_drvdata(dev);
- struct comedi_subdevice *s = comedi_get_write_subdevice(info);
+ struct comedi_file_info *info = dev_get_drvdata(dev);
+ struct comedi_subdevice *s = comedi_write_subdevice(info);
unsigned int size;
int err;
@@ -317,6 +349,103 @@ static struct device_attribute comedi_dev_attrs[] = {
__ATTR_NULL
};
+static void comedi_set_subdevice_runflags(struct comedi_subdevice *s,
+ unsigned mask, unsigned bits)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&s->spin_lock, flags);
+ s->runflags &= ~mask;
+ s->runflags |= (bits & mask);
+ spin_unlock_irqrestore(&s->spin_lock, flags);
+}
+
+static unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s)
+{
+ unsigned long flags;
+ unsigned runflags;
+
+ spin_lock_irqsave(&s->spin_lock, flags);
+ runflags = s->runflags;
+ spin_unlock_irqrestore(&s->spin_lock, flags);
+ return runflags;
+}
+
+bool comedi_is_subdevice_running(struct comedi_subdevice *s)
+{
+ unsigned runflags = comedi_get_subdevice_runflags(s);
+
+ return (runflags & SRF_RUNNING) ? true : false;
+}
+EXPORT_SYMBOL_GPL(comedi_is_subdevice_running);
+
+static bool comedi_is_subdevice_in_error(struct comedi_subdevice *s)
+{
+ unsigned runflags = comedi_get_subdevice_runflags(s);
+
+ return (runflags & SRF_ERROR) ? true : false;
+}
+
+static bool comedi_is_subdevice_idle(struct comedi_subdevice *s)
+{
+ unsigned runflags = comedi_get_subdevice_runflags(s);
+
+ return (runflags & (SRF_ERROR | SRF_RUNNING)) ? false : true;
+}
+
+/*
+ This function restores a subdevice to an idle state.
+ */
+static void do_become_nonbusy(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ struct comedi_async *async = s->async;
+
+ comedi_set_subdevice_runflags(s, SRF_RUNNING, 0);
+ if (async) {
+ comedi_buf_reset(async);
+ async->inttrig = NULL;
+ kfree(async->cmd.chanlist);
+ async->cmd.chanlist = NULL;
+ } else {
+ dev_err(dev->class_dev,
+ "BUG: (?) do_become_nonbusy called with async=NULL\n");
+ }
+
+ s->busy = NULL;
+}
+
+static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+{
+ int ret = 0;
+
+ if (comedi_is_subdevice_running(s) && s->cancel)
+ ret = s->cancel(dev, s);
+
+ do_become_nonbusy(dev, s);
+
+ return ret;
+}
+
+static int is_device_busy(struct comedi_device *dev)
+{
+ struct comedi_subdevice *s;
+ int i;
+
+ if (!dev->attached)
+ return 0;
+
+ for (i = 0; i < dev->n_subdevices; i++) {
+ s = &dev->subdevices[i];
+ if (s->busy)
+ return 1;
+ if (s->async && s->async->mmap_count)
+ return 1;
+ }
+
+ return 0;
+}
+
/*
COMEDI_DEVCONFIG
device config ioctl
@@ -335,8 +464,6 @@ static int do_devconfig_ioctl(struct comedi_device *dev,
{
struct comedi_devconfig it;
int ret;
- unsigned char *aux_data = NULL;
- int aux_len;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -352,36 +479,15 @@ static int do_devconfig_ioctl(struct comedi_device *dev,
return 0;
}
- if (copy_from_user(&it, arg, sizeof(struct comedi_devconfig)))
+ if (copy_from_user(&it, arg, sizeof(it)))
return -EFAULT;
it.board_name[COMEDI_NAMELEN - 1] = 0;
- if (comedi_aux_data(it.options, 0) &&
- it.options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) {
- int bit_shift;
- aux_len = it.options[COMEDI_DEVCONF_AUX_DATA_LENGTH];
- if (aux_len < 0)
- return -EFAULT;
-
- aux_data = vmalloc(aux_len);
- if (!aux_data)
- return -ENOMEM;
-
- if (copy_from_user(aux_data,
- (unsigned char __user *
- )comedi_aux_data(it.options, 0), aux_len)) {
- vfree(aux_data);
- return -EFAULT;
- }
- it.options[COMEDI_DEVCONF_AUX_DATA_LO] =
- (unsigned long)aux_data;
- if (sizeof(void *) > sizeof(int)) {
- bit_shift = sizeof(int) * 8;
- it.options[COMEDI_DEVCONF_AUX_DATA_HI] =
- ((unsigned long)aux_data) >> bit_shift;
- } else
- it.options[COMEDI_DEVCONF_AUX_DATA_HI] = 0;
+ if (it.options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) {
+ dev_warn(dev->class_dev,
+ "comedi_config --init_data is deprecated\n");
+ return -EINVAL;
}
ret = comedi_device_attach(dev, &it);
@@ -392,9 +498,6 @@ static int do_devconfig_ioctl(struct comedi_device *dev,
}
}
- if (aux_data)
- vfree(aux_data);
-
return ret;
}
@@ -420,7 +523,7 @@ static int do_bufconfig_ioctl(struct comedi_device *dev,
struct comedi_subdevice *s;
int retval = 0;
- if (copy_from_user(&bc, arg, sizeof(struct comedi_bufconfig)))
+ if (copy_from_user(&bc, arg, sizeof(bc)))
return -EFAULT;
if (bc.subdevice >= dev->n_subdevices || bc.subdevice < 0)
@@ -453,7 +556,7 @@ static int do_bufconfig_ioctl(struct comedi_device *dev,
bc.maximum_size = async->max_bufsize;
copyback:
- if (copy_to_user(arg, &bc, sizeof(struct comedi_bufconfig)))
+ if (copy_to_user(arg, &bc, sizeof(bc)))
return -EFAULT;
return 0;
@@ -477,14 +580,10 @@ static int do_devinfo_ioctl(struct comedi_device *dev,
struct comedi_devinfo __user *arg,
struct file *file)
{
- struct comedi_devinfo devinfo;
const unsigned minor = iminor(file->f_dentry->d_inode);
- struct comedi_device_file_info *dev_file_info =
- comedi_get_device_file_info(minor);
- struct comedi_subdevice *read_subdev =
- comedi_get_read_subdevice(dev_file_info);
- struct comedi_subdevice *write_subdev =
- comedi_get_write_subdevice(dev_file_info);
+ struct comedi_file_info *info = comedi_file_info_from_minor(minor);
+ struct comedi_subdevice *s;
+ struct comedi_devinfo devinfo;
memset(&devinfo, 0, sizeof(devinfo));
@@ -494,17 +593,19 @@ static int do_devinfo_ioctl(struct comedi_device *dev,
strlcpy(devinfo.driver_name, dev->driver->driver_name, COMEDI_NAMELEN);
strlcpy(devinfo.board_name, dev->board_name, COMEDI_NAMELEN);
- if (read_subdev)
- devinfo.read_subdevice = read_subdev - dev->subdevices;
+ s = comedi_read_subdevice(info);
+ if (s)
+ devinfo.read_subdevice = s->index;
else
devinfo.read_subdevice = -1;
- if (write_subdev)
- devinfo.write_subdevice = write_subdev - dev->subdevices;
+ s = comedi_write_subdevice(info);
+ if (s)
+ devinfo.write_subdevice = s->index;
else
devinfo.write_subdevice = -1;
- if (copy_to_user(arg, &devinfo, sizeof(struct comedi_devinfo)))
+ if (copy_to_user(arg, &devinfo, sizeof(devinfo)))
return -EFAULT;
return 0;
@@ -531,9 +632,7 @@ static int do_subdinfo_ioctl(struct comedi_device *dev,
struct comedi_subdinfo *tmp, *us;
struct comedi_subdevice *s;
- tmp =
- kcalloc(dev->n_subdevices, sizeof(struct comedi_subdinfo),
- GFP_KERNEL);
+ tmp = kcalloc(dev->n_subdevices, sizeof(*tmp), GFP_KERNEL);
if (!tmp)
return -ENOMEM;
@@ -545,7 +644,7 @@ static int do_subdinfo_ioctl(struct comedi_device *dev,
us->type = s->type;
us->n_chan = s->n_chan;
us->subd_flags = s->subdev_flags;
- if (comedi_get_subdevice_runflags(s) & SRF_RUNNING)
+ if (comedi_is_subdevice_running(s))
us->subd_flags |= SDF_RUNNING;
#define TIMER_nanosec 5 /* backwards compatibility */
us->timer_type = TIMER_nanosec;
@@ -584,8 +683,7 @@ static int do_subdinfo_ioctl(struct comedi_device *dev,
us->settling_time_0 = s->settling_time_0;
}
- ret = copy_to_user(arg, tmp,
- dev->n_subdevices * sizeof(struct comedi_subdinfo));
+ ret = copy_to_user(arg, tmp, dev->n_subdevices * sizeof(*tmp));
kfree(tmp);
@@ -612,7 +710,7 @@ static int do_chaninfo_ioctl(struct comedi_device *dev,
struct comedi_subdevice *s;
struct comedi_chaninfo it;
- if (copy_from_user(&it, arg, sizeof(struct comedi_chaninfo)))
+ if (copy_from_user(&it, arg, sizeof(it)))
return -EFAULT;
if (it.subdev >= dev->n_subdevices)
@@ -679,7 +777,7 @@ static int do_bufinfo_ioctl(struct comedi_device *dev,
struct comedi_subdevice *s;
struct comedi_async *async;
- if (copy_from_user(&bi, arg, sizeof(struct comedi_bufinfo)))
+ if (copy_from_user(&bi, arg, sizeof(bi)))
return -EFAULT;
if (bi.subdevice >= dev->n_subdevices || bi.subdevice < 0)
@@ -714,9 +812,8 @@ static int do_bufinfo_ioctl(struct comedi_device *dev,
bi.bytes_read = comedi_buf_read_alloc(async, bi.bytes_read);
comedi_buf_read_free(async, bi.bytes_read);
- if (!(comedi_get_subdevice_runflags(s) & (SRF_ERROR |
- SRF_RUNNING))
- && async->buf_write_count == async->buf_read_count) {
+ if (comedi_is_subdevice_idle(s) &&
+ async->buf_write_count == async->buf_read_count) {
do_become_nonbusy(dev, s);
}
}
@@ -734,103 +831,12 @@ copyback_position:
bi.buf_read_ptr = async->buf_read_ptr;
copyback:
- if (copy_to_user(arg, &bi, sizeof(struct comedi_bufinfo)))
+ if (copy_to_user(arg, &bi, sizeof(bi)))
return -EFAULT;
return 0;
}
-static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn,
- unsigned int *data, void *file);
-/*
- * COMEDI_INSNLIST
- * synchronous instructions
- *
- * arg:
- * pointer to sync cmd structure
- *
- * reads:
- * sync cmd struct at arg
- * instruction list
- * data (for writes)
- *
- * writes:
- * data (for reads)
- */
-/* arbitrary limits */
-#define MAX_SAMPLES 256
-static int do_insnlist_ioctl(struct comedi_device *dev,
- struct comedi_insnlist __user *arg, void *file)
-{
- struct comedi_insnlist insnlist;
- struct comedi_insn *insns = NULL;
- unsigned int *data = NULL;
- int i = 0;
- int ret = 0;
-
- if (copy_from_user(&insnlist, arg, sizeof(struct comedi_insnlist)))
- return -EFAULT;
-
- data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL);
- if (!data) {
- DPRINTK("kmalloc failed\n");
- ret = -ENOMEM;
- goto error;
- }
-
- insns =
- kcalloc(insnlist.n_insns, sizeof(struct comedi_insn), GFP_KERNEL);
- if (!insns) {
- DPRINTK("kmalloc failed\n");
- ret = -ENOMEM;
- goto error;
- }
-
- if (copy_from_user(insns, insnlist.insns,
- sizeof(struct comedi_insn) * insnlist.n_insns)) {
- DPRINTK("copy_from_user failed\n");
- ret = -EFAULT;
- goto error;
- }
-
- for (i = 0; i < insnlist.n_insns; i++) {
- if (insns[i].n > MAX_SAMPLES) {
- DPRINTK("number of samples too large\n");
- ret = -EINVAL;
- goto error;
- }
- if (insns[i].insn & INSN_MASK_WRITE) {
- if (copy_from_user(data, insns[i].data,
- insns[i].n * sizeof(unsigned int))) {
- DPRINTK("copy_from_user failed\n");
- ret = -EFAULT;
- goto error;
- }
- }
- ret = parse_insn(dev, insns + i, data, file);
- if (ret < 0)
- goto error;
- if (insns[i].insn & INSN_MASK_READ) {
- if (copy_to_user(insns[i].data, data,
- insns[i].n * sizeof(unsigned int))) {
- DPRINTK("copy_to_user failed\n");
- ret = -EFAULT;
- goto error;
- }
- }
- if (need_resched())
- schedule();
- }
-
-error:
- kfree(insns);
- kfree(data);
-
- if (ret < 0)
- return ret;
- return i;
-}
-
static int check_insn_config_length(struct comedi_insn *insn,
unsigned int *data)
{
@@ -1062,6 +1068,94 @@ out:
}
/*
+ * COMEDI_INSNLIST
+ * synchronous instructions
+ *
+ * arg:
+ * pointer to sync cmd structure
+ *
+ * reads:
+ * sync cmd struct at arg
+ * instruction list
+ * data (for writes)
+ *
+ * writes:
+ * data (for reads)
+ */
+/* arbitrary limits */
+#define MAX_SAMPLES 256
+static int do_insnlist_ioctl(struct comedi_device *dev,
+ struct comedi_insnlist __user *arg, void *file)
+{
+ struct comedi_insnlist insnlist;
+ struct comedi_insn *insns = NULL;
+ unsigned int *data = NULL;
+ int i = 0;
+ int ret = 0;
+
+ if (copy_from_user(&insnlist, arg, sizeof(insnlist)))
+ return -EFAULT;
+
+ data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL);
+ if (!data) {
+ DPRINTK("kmalloc failed\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ insns = kcalloc(insnlist.n_insns, sizeof(*insns), GFP_KERNEL);
+ if (!insns) {
+ DPRINTK("kmalloc failed\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ if (copy_from_user(insns, insnlist.insns,
+ sizeof(*insns) * insnlist.n_insns)) {
+ DPRINTK("copy_from_user failed\n");
+ ret = -EFAULT;
+ goto error;
+ }
+
+ for (i = 0; i < insnlist.n_insns; i++) {
+ if (insns[i].n > MAX_SAMPLES) {
+ DPRINTK("number of samples too large\n");
+ ret = -EINVAL;
+ goto error;
+ }
+ if (insns[i].insn & INSN_MASK_WRITE) {
+ if (copy_from_user(data, insns[i].data,
+ insns[i].n * sizeof(unsigned int))) {
+ DPRINTK("copy_from_user failed\n");
+ ret = -EFAULT;
+ goto error;
+ }
+ }
+ ret = parse_insn(dev, insns + i, data, file);
+ if (ret < 0)
+ goto error;
+ if (insns[i].insn & INSN_MASK_READ) {
+ if (copy_to_user(insns[i].data, data,
+ insns[i].n * sizeof(unsigned int))) {
+ DPRINTK("copy_to_user failed\n");
+ ret = -EFAULT;
+ goto error;
+ }
+ }
+ if (need_resched())
+ schedule();
+ }
+
+error:
+ kfree(insns);
+ kfree(data);
+
+ if (ret < 0)
+ return ret;
+ return i;
+}
+
+/*
* COMEDI_INSN
* synchronous instructions
*
@@ -1088,7 +1182,7 @@ static int do_insn_ioctl(struct comedi_device *dev,
goto error;
}
- if (copy_from_user(&insn, arg, sizeof(struct comedi_insn))) {
+ if (copy_from_user(&insn, arg, sizeof(insn))) {
ret = -EFAULT;
goto error;
}
@@ -1123,17 +1217,6 @@ error:
return ret;
}
-static void comedi_set_subdevice_runflags(struct comedi_subdevice *s,
- unsigned mask, unsigned bits)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&s->spin_lock, flags);
- s->runflags &= ~mask;
- s->runflags |= (bits & mask);
- spin_unlock_irqrestore(&s->spin_lock, flags);
-}
-
static int do_cmd_ioctl(struct comedi_device *dev,
struct comedi_cmd __user *arg, void *file)
{
@@ -1143,7 +1226,7 @@ static int do_cmd_ioctl(struct comedi_device *dev,
int ret = 0;
unsigned int __user *user_chanlist;
- if (copy_from_user(&cmd, arg, sizeof(struct comedi_cmd))) {
+ if (copy_from_user(&cmd, arg, sizeof(cmd))) {
DPRINTK("bad cmd address\n");
return -EFAULT;
}
@@ -1233,7 +1316,7 @@ static int do_cmd_ioctl(struct comedi_device *dev,
/* restore chanlist pointer before copying back */
cmd.chanlist = (unsigned int __force *)user_chanlist;
cmd.data = NULL;
- if (copy_to_user(arg, &cmd, sizeof(struct comedi_cmd))) {
+ if (copy_to_user(arg, &cmd, sizeof(cmd))) {
DPRINTK("fault writing cmd\n");
ret = -EFAULT;
goto cleanup;
@@ -1248,7 +1331,7 @@ static int do_cmd_ioctl(struct comedi_device *dev,
goto cleanup;
}
- comedi_reset_async_buf(async);
+ comedi_buf_reset(async);
async->cb_mask =
COMEDI_CB_EOA | COMEDI_CB_BLOCK | COMEDI_CB_ERROR |
@@ -1292,7 +1375,7 @@ static int do_cmdtest_ioctl(struct comedi_device *dev,
unsigned int *chanlist = NULL;
unsigned int __user *user_chanlist;
- if (copy_from_user(&cmd, arg, sizeof(struct comedi_cmd))) {
+ if (copy_from_user(&cmd, arg, sizeof(cmd))) {
DPRINTK("bad cmd address\n");
return -EFAULT;
}
@@ -1356,7 +1439,7 @@ static int do_cmdtest_ioctl(struct comedi_device *dev,
/* restore chanlist pointer before copying back */
cmd.chanlist = (unsigned int __force *)user_chanlist;
- if (copy_to_user(arg, &cmd, sizeof(struct comedi_cmd))) {
+ if (copy_to_user(arg, &cmd, sizeof(cmd))) {
DPRINTK("bad cmd address\n");
ret = -EFAULT;
goto cleanup;
@@ -1533,25 +1616,28 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
const unsigned minor = iminor(file->f_dentry->d_inode);
- struct comedi_device_file_info *dev_file_info =
- comedi_get_device_file_info(minor);
- struct comedi_device *dev;
+ struct comedi_file_info *info = comedi_file_info_from_minor(minor);
+ struct comedi_device *dev = comedi_dev_from_file_info(info);
int rc;
- if (dev_file_info == NULL || dev_file_info->device == NULL)
+ if (!dev)
return -ENODEV;
- dev = dev_file_info->device;
mutex_lock(&dev->mutex);
/* Device config is special, because it must work on
* an unconfigured device. */
if (cmd == COMEDI_DEVCONFIG) {
+ if (minor >= COMEDI_NUM_BOARD_MINORS) {
+ /* Device config not appropriate on non-board minors. */
+ rc = -ENOTTY;
+ goto done;
+ }
rc = do_devconfig_ioctl(dev,
(struct comedi_devconfig __user *)arg);
if (rc == 0)
/* Evade comedi_auto_unconfig(). */
- dev_file_info->hardware_device = NULL;
+ info->hardware_device = NULL;
goto done;
}
@@ -1624,19 +1710,6 @@ done:
return rc;
}
-static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
-{
- int ret = 0;
-
- if ((comedi_get_subdevice_runflags(s) & SRF_RUNNING) && s->cancel)
- ret = s->cancel(dev, s);
-
- do_become_nonbusy(dev, s);
-
- return ret;
-}
-
-
static void comedi_vm_open(struct vm_area_struct *area)
{
struct comedi_async *async;
@@ -1671,40 +1744,38 @@ static struct vm_operations_struct comedi_vm_ops = {
static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
{
const unsigned minor = iminor(file->f_dentry->d_inode);
- struct comedi_async *async = NULL;
+ struct comedi_file_info *info = comedi_file_info_from_minor(minor);
+ struct comedi_device *dev = comedi_dev_from_file_info(info);
+ struct comedi_subdevice *s;
+ struct comedi_async *async;
unsigned long start = vma->vm_start;
unsigned long size;
int n_pages;
int i;
int retval;
- struct comedi_subdevice *s;
- struct comedi_device_file_info *dev_file_info;
- struct comedi_device *dev;
- dev_file_info = comedi_get_device_file_info(minor);
- if (dev_file_info == NULL)
- return -ENODEV;
- dev = dev_file_info->device;
- if (dev == NULL)
+ if (!dev)
return -ENODEV;
mutex_lock(&dev->mutex);
+
if (!dev->attached) {
DPRINTK("no driver configured on comedi%i\n", dev->minor);
retval = -ENODEV;
goto done;
}
+
if (vma->vm_flags & VM_WRITE)
- s = comedi_get_write_subdevice(dev_file_info);
+ s = comedi_write_subdevice(info);
else
- s = comedi_get_read_subdevice(dev_file_info);
-
- if (s == NULL) {
+ s = comedi_read_subdevice(info);
+ if (!s) {
retval = -EINVAL;
goto done;
}
+
async = s->async;
- if (async == NULL) {
+ if (!async) {
retval = -EINVAL;
goto done;
}
@@ -1727,11 +1798,11 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
n_pages = size >> PAGE_SHIFT;
for (i = 0; i < n_pages; ++i) {
+ struct comedi_buf_page *buf = &async->buf_page_list[i];
+
if (remap_pfn_range(vma, start,
- page_to_pfn(virt_to_page
- (async->buf_page_list
- [i].virt_addr)), PAGE_SIZE,
- PAGE_SHARED)) {
+ page_to_pfn(virt_to_page(buf->virt_addr)),
+ PAGE_SIZE, PAGE_SHARED)) {
retval = -EAGAIN;
goto done;
}
@@ -1753,50 +1824,40 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait)
{
unsigned int mask = 0;
const unsigned minor = iminor(file->f_dentry->d_inode);
- struct comedi_subdevice *read_subdev;
- struct comedi_subdevice *write_subdev;
- struct comedi_device_file_info *dev_file_info;
- struct comedi_device *dev;
- dev_file_info = comedi_get_device_file_info(minor);
+ struct comedi_file_info *info = comedi_file_info_from_minor(minor);
+ struct comedi_device *dev = comedi_dev_from_file_info(info);
+ struct comedi_subdevice *s;
- if (dev_file_info == NULL)
- return -ENODEV;
- dev = dev_file_info->device;
- if (dev == NULL)
+ if (!dev)
return -ENODEV;
mutex_lock(&dev->mutex);
+
if (!dev->attached) {
DPRINTK("no driver configured on comedi%i\n", dev->minor);
- mutex_unlock(&dev->mutex);
- return 0;
+ goto done;
}
- mask = 0;
- read_subdev = comedi_get_read_subdevice(dev_file_info);
- if (read_subdev) {
- poll_wait(file, &read_subdev->async->wait_head, wait);
- if (!read_subdev->busy
- || comedi_buf_read_n_available(read_subdev->async) > 0
- || !(comedi_get_subdevice_runflags(read_subdev) &
- SRF_RUNNING)) {
+ s = comedi_read_subdevice(info);
+ if (s && s->async) {
+ poll_wait(file, &s->async->wait_head, wait);
+ if (!s->busy || !comedi_is_subdevice_running(s) ||
+ comedi_buf_read_n_available(s->async) > 0)
mask |= POLLIN | POLLRDNORM;
- }
}
- write_subdev = comedi_get_write_subdevice(dev_file_info);
- if (write_subdev) {
- poll_wait(file, &write_subdev->async->wait_head, wait);
- comedi_buf_write_alloc(write_subdev->async,
- write_subdev->async->prealloc_bufsz);
- if (!write_subdev->busy
- || !(comedi_get_subdevice_runflags(write_subdev) &
- SRF_RUNNING)
- || comedi_buf_write_n_allocated(write_subdev->async) >=
- bytes_per_sample(write_subdev->async->subdevice)) {
+
+ s = comedi_write_subdevice(info);
+ if (s && s->async) {
+ unsigned int bps = bytes_per_sample(s->async->subdevice);
+
+ poll_wait(file, &s->async->wait_head, wait);
+ comedi_buf_write_alloc(s->async, s->async->prealloc_bufsz);
+ if (!s->busy || !comedi_is_subdevice_running(s) ||
+ comedi_buf_write_n_allocated(s->async) >= bps)
mask |= POLLOUT | POLLWRNORM;
- }
}
+done:
mutex_unlock(&dev->mutex);
return mask;
}
@@ -1809,53 +1870,38 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
int n, m, count = 0, retval = 0;
DECLARE_WAITQUEUE(wait, current);
const unsigned minor = iminor(file->f_dentry->d_inode);
- struct comedi_device_file_info *dev_file_info;
- struct comedi_device *dev;
- dev_file_info = comedi_get_device_file_info(minor);
+ struct comedi_file_info *info = comedi_file_info_from_minor(minor);
+ struct comedi_device *dev = comedi_dev_from_file_info(info);
- if (dev_file_info == NULL)
- return -ENODEV;
- dev = dev_file_info->device;
- if (dev == NULL)
+ if (!dev)
return -ENODEV;
if (!dev->attached) {
DPRINTK("no driver configured on comedi%i\n", dev->minor);
- retval = -ENODEV;
- goto done;
+ return -ENODEV;
}
- s = comedi_get_write_subdevice(dev_file_info);
- if (s == NULL) {
- retval = -EIO;
- goto done;
- }
+ s = comedi_write_subdevice(info);
+ if (!s || !s->async)
+ return -EIO;
+
async = s->async;
- if (!nbytes) {
- retval = 0;
- goto done;
- }
- if (!s->busy) {
- retval = 0;
- goto done;
- }
- if (s->busy != file) {
- retval = -EACCES;
- goto done;
- }
+ if (!s->busy || !nbytes)
+ return 0;
+ if (s->busy != file)
+ return -EACCES;
+
add_wait_queue(&async->wait_head, &wait);
while (nbytes > 0 && !retval) {
set_current_state(TASK_INTERRUPTIBLE);
- if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
+ if (!comedi_is_subdevice_running(s)) {
if (count == 0) {
- if (comedi_get_subdevice_runflags(s) &
- SRF_ERROR) {
+ if (comedi_is_subdevice_in_error(s))
retval = -EPIPE;
- } else {
+ else
retval = 0;
- }
do_become_nonbusy(dev, s);
}
break;
@@ -1908,7 +1954,6 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
set_current_state(TASK_RUNNING);
remove_wait_queue(&async->wait_head, &wait);
-done:
return count ? count : retval;
}
@@ -1920,40 +1965,26 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
int n, m, count = 0, retval = 0;
DECLARE_WAITQUEUE(wait, current);
const unsigned minor = iminor(file->f_dentry->d_inode);
- struct comedi_device_file_info *dev_file_info;
- struct comedi_device *dev;
- dev_file_info = comedi_get_device_file_info(minor);
+ struct comedi_file_info *info = comedi_file_info_from_minor(minor);
+ struct comedi_device *dev = comedi_dev_from_file_info(info);
- if (dev_file_info == NULL)
- return -ENODEV;
- dev = dev_file_info->device;
- if (dev == NULL)
+ if (!dev)
return -ENODEV;
if (!dev->attached) {
DPRINTK("no driver configured on comedi%i\n", dev->minor);
- retval = -ENODEV;
- goto done;
+ return -ENODEV;
}
- s = comedi_get_read_subdevice(dev_file_info);
- if (s == NULL) {
- retval = -EIO;
- goto done;
- }
+ s = comedi_read_subdevice(info);
+ if (!s || !s->async)
+ return -EIO;
+
async = s->async;
- if (!nbytes) {
- retval = 0;
- goto done;
- }
- if (!s->busy) {
- retval = 0;
- goto done;
- }
- if (s->busy != file) {
- retval = -EACCES;
- goto done;
- }
+ if (!s->busy || !nbytes)
+ return 0;
+ if (s->busy != file)
+ return -EACCES;
add_wait_queue(&async->wait_head, &wait);
while (nbytes > 0 && !retval) {
@@ -1970,14 +2001,12 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
n = m;
if (n == 0) {
- if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
+ if (!comedi_is_subdevice_running(s)) {
do_become_nonbusy(dev, s);
- if (comedi_get_subdevice_runflags(s) &
- SRF_ERROR) {
+ if (comedi_is_subdevice_in_error(s))
retval = -EPIPE;
- } else {
+ else
retval = 0;
- }
break;
}
if (file->f_flags & O_NONBLOCK) {
@@ -2015,48 +2044,22 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
buf += n;
break; /* makes device work like a pipe */
}
- if (!(comedi_get_subdevice_runflags(s) & (SRF_ERROR | SRF_RUNNING)) &&
+ if (comedi_is_subdevice_idle(s) &&
async->buf_read_count - async->buf_write_count == 0) {
do_become_nonbusy(dev, s);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&async->wait_head, &wait);
-done:
return count ? count : retval;
}
-/*
- This function restores a subdevice to an idle state.
- */
-static void do_become_nonbusy(struct comedi_device *dev,
- struct comedi_subdevice *s)
-{
- struct comedi_async *async = s->async;
-
- comedi_set_subdevice_runflags(s, SRF_RUNNING, 0);
- if (async) {
- comedi_reset_async_buf(async);
- async->inttrig = NULL;
- kfree(async->cmd.chanlist);
- async->cmd.chanlist = NULL;
- } else {
- dev_err(dev->class_dev,
- "BUG: (?) do_become_nonbusy called with async=NULL\n");
- }
-
- s->busy = NULL;
-}
-
static int comedi_open(struct inode *inode, struct file *file)
{
const unsigned minor = iminor(inode);
- struct comedi_device_file_info *dev_file_info =
- comedi_get_device_file_info(minor);
- struct comedi_device *dev =
- dev_file_info ? dev_file_info->device : NULL;
+ struct comedi_device *dev = comedi_dev_from_minor(minor);
- if (dev == NULL) {
+ if (!dev) {
DPRINTK("invalid minor number\n");
return -ENODEV;
}
@@ -2128,19 +2131,25 @@ ok:
return 0;
}
+static int comedi_fasync(int fd, struct file *file, int on)
+{
+ const unsigned minor = iminor(file->f_dentry->d_inode);
+ struct comedi_device *dev = comedi_dev_from_minor(minor);
+
+ if (!dev)
+ return -ENODEV;
+
+ return fasync_helper(fd, file, on, &dev->async_queue);
+}
+
static int comedi_close(struct inode *inode, struct file *file)
{
const unsigned minor = iminor(inode);
+ struct comedi_device *dev = comedi_dev_from_minor(minor);
struct comedi_subdevice *s = NULL;
int i;
- struct comedi_device_file_info *dev_file_info;
- struct comedi_device *dev;
- dev_file_info = comedi_get_device_file_info(minor);
- if (dev_file_info == NULL)
- return -ENODEV;
- dev = dev_file_info->device;
- if (dev == NULL)
+ if (!dev)
return -ENODEV;
mutex_lock(&dev->mutex);
@@ -2172,22 +2181,6 @@ static int comedi_close(struct inode *inode, struct file *file)
return 0;
}
-static int comedi_fasync(int fd, struct file *file, int on)
-{
- const unsigned minor = iminor(file->f_dentry->d_inode);
- struct comedi_device_file_info *dev_file_info;
- struct comedi_device *dev;
- dev_file_info = comedi_get_device_file_info(minor);
-
- if (dev_file_info == NULL)
- return -ENODEV;
- dev = dev_file_info->device;
- if (dev == NULL)
- return -ENODEV;
-
- return fasync_helper(fd, file, on, &dev->async_queue);
-}
-
static const struct file_operations comedi_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = comedi_unlocked_ioctl,
@@ -2205,99 +2198,6 @@ static const struct file_operations comedi_fops = {
static struct class *comedi_class;
static struct cdev comedi_cdev;
-static void comedi_cleanup_legacy_minors(void)
-{
- unsigned i;
-
- for (i = 0; i < comedi_num_legacy_minors; i++)
- comedi_free_board_minor(i);
-}
-
-static int __init comedi_init(void)
-{
- int i;
- int retval;
-
- pr_info("comedi: version " COMEDI_RELEASE " - http://www.comedi.org\n");
-
- if (comedi_num_legacy_minors < 0 ||
- comedi_num_legacy_minors > COMEDI_NUM_BOARD_MINORS) {
- pr_err("comedi: error: invalid value for module parameter \"comedi_num_legacy_minors\". Valid values are 0 through %i.\n",
- COMEDI_NUM_BOARD_MINORS);
- return -EINVAL;
- }
-
- /*
- * comedi is unusable if both comedi_autoconfig and
- * comedi_num_legacy_minors are zero, so we might as well adjust the
- * defaults in that case
- */
- if (comedi_autoconfig == 0 && comedi_num_legacy_minors == 0)
- comedi_num_legacy_minors = 16;
-
- memset(comedi_file_info_table, 0,
- sizeof(struct comedi_device_file_info *) * COMEDI_NUM_MINORS);
-
- retval = register_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
- COMEDI_NUM_MINORS, "comedi");
- if (retval)
- return -EIO;
- cdev_init(&comedi_cdev, &comedi_fops);
- comedi_cdev.owner = THIS_MODULE;
- kobject_set_name(&comedi_cdev.kobj, "comedi");
- if (cdev_add(&comedi_cdev, MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS)) {
- unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
- COMEDI_NUM_MINORS);
- return -EIO;
- }
- comedi_class = class_create(THIS_MODULE, "comedi");
- if (IS_ERR(comedi_class)) {
- pr_err("comedi: failed to create class\n");
- cdev_del(&comedi_cdev);
- unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
- COMEDI_NUM_MINORS);
- return PTR_ERR(comedi_class);
- }
-
- comedi_class->dev_attrs = comedi_dev_attrs;
-
- /* XXX requires /proc interface */
- comedi_proc_init();
-
- /* create devices files for legacy/manual use */
- for (i = 0; i < comedi_num_legacy_minors; i++) {
- int minor;
- minor = comedi_alloc_board_minor(NULL);
- if (minor < 0) {
- comedi_cleanup_legacy_minors();
- cdev_del(&comedi_cdev);
- unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
- COMEDI_NUM_MINORS);
- return minor;
- }
- }
-
- return 0;
-}
-
-static void __exit comedi_cleanup(void)
-{
- int i;
-
- comedi_cleanup_legacy_minors();
- for (i = 0; i < COMEDI_NUM_MINORS; ++i)
- BUG_ON(comedi_file_info_table[i]);
-
- class_destroy(comedi_class);
- cdev_del(&comedi_cdev);
- unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
-
- comedi_proc_cleanup();
-}
-
-module_init(comedi_init);
-module_exit(comedi_cleanup);
-
void comedi_error(const struct comedi_device *dev, const char *s)
{
dev_err(dev->class_dev, "%s: %s\n", dev->driver->driver_name, s);
@@ -2312,7 +2212,7 @@ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
/* DPRINTK("comedi_event 0x%x\n",mask); */
- if ((comedi_get_subdevice_runflags(s) & SRF_RUNNING) == 0)
+ if (!comedi_is_subdevice_running(s))
return;
if (s->
@@ -2347,40 +2247,9 @@ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
}
EXPORT_SYMBOL(comedi_event);
-unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s)
-{
- unsigned long flags;
- unsigned runflags;
-
- spin_lock_irqsave(&s->spin_lock, flags);
- runflags = s->runflags;
- spin_unlock_irqrestore(&s->spin_lock, flags);
- return runflags;
-}
-EXPORT_SYMBOL(comedi_get_subdevice_runflags);
-
-static int is_device_busy(struct comedi_device *dev)
-{
- struct comedi_subdevice *s;
- int i;
-
- if (!dev->attached)
- return 0;
-
- for (i = 0; i < dev->n_subdevices; i++) {
- s = &dev->subdevices[i];
- if (s->busy)
- return 1;
- if (s->async && s->async->mmap_count)
- return 1;
- }
-
- return 0;
-}
-
static void comedi_device_init(struct comedi_device *dev)
{
- memset(dev, 0, sizeof(struct comedi_device));
+ memset(dev, 0, sizeof(*dev));
spin_lock_init(&dev->spinlock);
mutex_init(&dev->mutex);
dev->minor = -1;
@@ -2398,11 +2267,11 @@ static void comedi_device_cleanup(struct comedi_device *dev)
int comedi_alloc_board_minor(struct device *hardware_device)
{
- struct comedi_device_file_info *info;
+ struct comedi_file_info *info;
struct device *csdev;
unsigned i;
- info = kzalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
if (info == NULL)
return -ENOMEM;
info->device = kzalloc(sizeof(struct comedi_device), GFP_KERNEL);
@@ -2439,7 +2308,7 @@ int comedi_alloc_board_minor(struct device *hardware_device)
void comedi_free_board_minor(unsigned minor)
{
- struct comedi_device_file_info *info;
+ struct comedi_file_info *info;
BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
spin_lock(&comedi_file_info_table_lock);
@@ -2464,7 +2333,7 @@ void comedi_free_board_minor(unsigned minor)
int comedi_find_board_minor(struct device *hardware_device)
{
int minor;
- struct comedi_device_file_info *info;
+ struct comedi_file_info *info;
for (minor = 0; minor < COMEDI_NUM_BOARD_MINORS; minor++) {
spin_lock(&comedi_file_info_table_lock);
@@ -2478,19 +2347,21 @@ int comedi_find_board_minor(struct device *hardware_device)
return -ENODEV;
}
-int comedi_alloc_subdevice_minor(struct comedi_device *dev,
- struct comedi_subdevice *s)
+int comedi_alloc_subdevice_minor(struct comedi_subdevice *s)
{
- struct comedi_device_file_info *info;
+ struct comedi_device *dev = s->device;
+ struct comedi_file_info *info;
struct device *csdev;
unsigned i;
- info = kmalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
- if (info == NULL)
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
return -ENOMEM;
info->device = dev;
- info->read_subdevice = s;
- info->write_subdevice = s;
+ if (s->subdev_flags & SDF_CMD_READ)
+ info->read_subdevice = s;
+ if (s->subdev_flags & SDF_CMD_WRITE)
+ info->write_subdevice = s;
spin_lock(&comedi_file_info_table_lock);
for (i = COMEDI_FIRST_SUBDEVICE_MINOR; i < COMEDI_NUM_MINORS; ++i) {
if (comedi_file_info_table[i] == NULL) {
@@ -2501,23 +2372,23 @@ int comedi_alloc_subdevice_minor(struct comedi_device *dev,
spin_unlock(&comedi_file_info_table_lock);
if (i == COMEDI_NUM_MINORS) {
kfree(info);
- pr_err("comedi: error: ran out of minor numbers for board device files.\n");
+ pr_err("comedi: error: ran out of minor numbers for subdevice files.\n");
return -EBUSY;
}
s->minor = i;
csdev = device_create(comedi_class, dev->class_dev,
MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i_subd%i",
- dev->minor, (int)(s - dev->subdevices));
+ dev->minor, s->index);
if (!IS_ERR(csdev))
s->class_dev = csdev;
dev_set_drvdata(csdev, info);
- return i;
+ return 0;
}
void comedi_free_subdevice_minor(struct comedi_subdevice *s)
{
- struct comedi_device_file_info *info;
+ struct comedi_file_info *info;
if (s == NULL)
return;
@@ -2539,14 +2410,90 @@ void comedi_free_subdevice_minor(struct comedi_subdevice *s)
kfree(info);
}
-struct comedi_device_file_info *comedi_get_device_file_info(unsigned minor)
+static void comedi_cleanup_board_minors(void)
{
- struct comedi_device_file_info *info;
+ unsigned i;
- BUG_ON(minor >= COMEDI_NUM_MINORS);
- spin_lock(&comedi_file_info_table_lock);
- info = comedi_file_info_table[minor];
- spin_unlock(&comedi_file_info_table_lock);
- return info;
+ for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++)
+ comedi_free_board_minor(i);
+}
+
+static int __init comedi_init(void)
+{
+ int i;
+ int retval;
+
+ pr_info("comedi: version " COMEDI_RELEASE " - http://www.comedi.org\n");
+
+ if (comedi_num_legacy_minors < 0 ||
+ comedi_num_legacy_minors > COMEDI_NUM_BOARD_MINORS) {
+ pr_err("comedi: error: invalid value for module parameter \"comedi_num_legacy_minors\". Valid values are 0 through %i.\n",
+ COMEDI_NUM_BOARD_MINORS);
+ return -EINVAL;
+ }
+
+ memset(comedi_file_info_table, 0,
+ sizeof(struct comedi_file_info *) * COMEDI_NUM_MINORS);
+
+ retval = register_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
+ COMEDI_NUM_MINORS, "comedi");
+ if (retval)
+ return -EIO;
+ cdev_init(&comedi_cdev, &comedi_fops);
+ comedi_cdev.owner = THIS_MODULE;
+ kobject_set_name(&comedi_cdev.kobj, "comedi");
+ if (cdev_add(&comedi_cdev, MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS)) {
+ unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
+ COMEDI_NUM_MINORS);
+ return -EIO;
+ }
+ comedi_class = class_create(THIS_MODULE, "comedi");
+ if (IS_ERR(comedi_class)) {
+ pr_err("comedi: failed to create class\n");
+ cdev_del(&comedi_cdev);
+ unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
+ COMEDI_NUM_MINORS);
+ return PTR_ERR(comedi_class);
+ }
+
+ comedi_class->dev_attrs = comedi_dev_attrs;
+
+ /* XXX requires /proc interface */
+ comedi_proc_init();
+
+ /* create devices files for legacy/manual use */
+ for (i = 0; i < comedi_num_legacy_minors; i++) {
+ int minor;
+ minor = comedi_alloc_board_minor(NULL);
+ if (minor < 0) {
+ comedi_cleanup_board_minors();
+ cdev_del(&comedi_cdev);
+ unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
+ COMEDI_NUM_MINORS);
+ return minor;
+ }
+ }
+
+ return 0;
}
-EXPORT_SYMBOL_GPL(comedi_get_device_file_info);
+module_init(comedi_init);
+
+static void __exit comedi_cleanup(void)
+{
+ int i;
+
+ comedi_cleanup_board_minors();
+ for (i = 0; i < COMEDI_NUM_MINORS; ++i)
+ BUG_ON(comedi_file_info_table[i]);
+
+ class_destroy(comedi_class);
+ cdev_del(&comedi_cdev);
+ unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
+
+ comedi_proc_cleanup();
+}
+module_exit(comedi_cleanup);
+
+MODULE_AUTHOR("http://www.comedi.org");
+MODULE_DESCRIPTION("Comedi core module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/comedi_internal.h b/drivers/staging/comedi/comedi_internal.h
index e70ef0515d9a..b3743135f4aa 100644
--- a/drivers/staging/comedi/comedi_internal.h
+++ b/drivers/staging/comedi/comedi_internal.h
@@ -8,18 +8,43 @@
*/
int do_rangeinfo_ioctl(struct comedi_device *dev,
struct comedi_rangeinfo __user *arg);
-int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
int comedi_alloc_board_minor(struct device *hardware_device);
void comedi_free_board_minor(unsigned minor);
int comedi_find_board_minor(struct device *hardware_device);
-void comedi_reset_async_buf(struct comedi_async *async);
+int comedi_alloc_subdevice_minor(struct comedi_subdevice *s);
+void comedi_free_subdevice_minor(struct comedi_subdevice *s);
+
int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
unsigned long new_size);
+void comedi_buf_reset(struct comedi_async *async);
+unsigned int comedi_buf_write_n_allocated(struct comedi_async *async);
extern unsigned int comedi_default_buf_size_kb;
extern unsigned int comedi_default_buf_maxsize_kb;
-extern bool comedi_autoconfig;
+
+/* drivers.c */
+
extern struct comedi_driver *comedi_drivers;
+int insn_inval(struct comedi_device *, struct comedi_subdevice *,
+ struct comedi_insn *, unsigned int *);
+
+void comedi_device_detach(struct comedi_device *);
+int comedi_device_attach(struct comedi_device *, struct comedi_devconfig *);
+
+#ifdef CONFIG_PROC_FS
+
+/* proc.c */
+
+void comedi_proc_init(void);
+void comedi_proc_cleanup(void);
+#else
+static inline void comedi_proc_init(void)
+{
+}
+static inline void comedi_proc_cleanup(void)
+{
+}
+#endif
+
#endif /* _COMEDI_INTERNAL_H */
diff --git a/drivers/staging/comedi/comedi_pci.c b/drivers/staging/comedi/comedi_pci.c
new file mode 100644
index 000000000000..37d2e4677360
--- /dev/null
+++ b/drivers/staging/comedi/comedi_pci.c
@@ -0,0 +1,140 @@
+/*
+ * comedi_pci.c
+ * Comedi PCI driver specific functions.
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1997-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.
+ */
+
+#include <linux/pci.h>
+
+#include "comedidev.h"
+
+/**
+ * comedi_to_pci_dev() - comedi_device pointer to pci_dev pointer.
+ * @dev: comedi_device struct
+ */
+struct pci_dev *comedi_to_pci_dev(struct comedi_device *dev)
+{
+ return dev->hw_dev ? to_pci_dev(dev->hw_dev) : NULL;
+}
+EXPORT_SYMBOL_GPL(comedi_to_pci_dev);
+
+/**
+ * comedi_pci_enable() - Enable the PCI device and request the regions.
+ * @pcidev: pci_dev struct
+ * @res_name: name for the requested reqource
+ */
+int comedi_pci_enable(struct pci_dev *pcidev, const char *res_name)
+{
+ int rc;
+
+ rc = pci_enable_device(pcidev);
+ if (rc < 0)
+ return rc;
+
+ rc = pci_request_regions(pcidev, res_name);
+ if (rc < 0)
+ pci_disable_device(pcidev);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(comedi_pci_enable);
+
+/**
+ * comedi_pci_disable() - Release the regions and disable the PCI device.
+ * @pcidev: pci_dev struct
+ *
+ * This must be matched with a previous successful call to comedi_pci_enable().
+ */
+void comedi_pci_disable(struct pci_dev *pcidev)
+{
+ pci_release_regions(pcidev);
+ pci_disable_device(pcidev);
+}
+EXPORT_SYMBOL_GPL(comedi_pci_disable);
+
+/**
+ * comedi_pci_auto_config() - Configure/probe a comedi PCI driver.
+ * @pcidev: pci_dev struct
+ * @driver: comedi_driver struct
+ *
+ * Typically called from the pci_driver (*probe) function.
+ */
+int comedi_pci_auto_config(struct pci_dev *pcidev,
+ struct comedi_driver *driver)
+{
+ return comedi_auto_config(&pcidev->dev, driver, 0);
+}
+EXPORT_SYMBOL_GPL(comedi_pci_auto_config);
+
+/**
+ * comedi_pci_auto_unconfig() - Unconfigure/remove a comedi PCI driver.
+ * @pcidev: pci_dev struct
+ *
+ * Typically called from the pci_driver (*remove) function.
+ */
+void comedi_pci_auto_unconfig(struct pci_dev *pcidev)
+{
+ comedi_auto_unconfig(&pcidev->dev);
+}
+EXPORT_SYMBOL_GPL(comedi_pci_auto_unconfig);
+
+/**
+ * comedi_pci_driver_register() - Register a comedi PCI driver.
+ * @comedi_driver: comedi_driver struct
+ * @pci_driver: pci_driver struct
+ *
+ * This function is used for the module_init() of comedi PCI drivers.
+ * Do not call it directly, use the module_comedi_pci_driver() helper
+ * macro instead.
+ */
+int comedi_pci_driver_register(struct comedi_driver *comedi_driver,
+ struct pci_driver *pci_driver)
+{
+ int ret;
+
+ ret = comedi_driver_register(comedi_driver);
+ if (ret < 0)
+ return ret;
+
+ ret = pci_register_driver(pci_driver);
+ if (ret < 0) {
+ comedi_driver_unregister(comedi_driver);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(comedi_pci_driver_register);
+
+/**
+ * comedi_pci_driver_unregister() - Unregister a comedi PCI driver.
+ * @comedi_driver: comedi_driver struct
+ * @pci_driver: pci_driver struct
+ *
+ * This function is used for the module_exit() of comedi PCI drivers.
+ * Do not call it directly, use the module_comedi_pci_driver() helper
+ * macro instead.
+ */
+void comedi_pci_driver_unregister(struct comedi_driver *comedi_driver,
+ struct pci_driver *pci_driver)
+{
+ pci_unregister_driver(pci_driver);
+ comedi_driver_unregister(comedi_driver);
+}
+EXPORT_SYMBOL_GPL(comedi_pci_driver_unregister);
diff --git a/drivers/staging/comedi/comedi_pcmcia.c b/drivers/staging/comedi/comedi_pcmcia.c
new file mode 100644
index 000000000000..453ff3b28617
--- /dev/null
+++ b/drivers/staging/comedi/comedi_pcmcia.c
@@ -0,0 +1,160 @@
+/*
+ * comedi_pcmcia.c
+ * Comedi PCMCIA driver specific functions.
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1997-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.
+ */
+
+#include <linux/kernel.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+
+#include "comedidev.h"
+
+/**
+ * comedi_to_pcmcia_dev() - comedi_device pointer to pcmcia_device pointer.
+ * @dev: comedi_device struct
+ */
+struct pcmcia_device *comedi_to_pcmcia_dev(struct comedi_device *dev)
+{
+ return dev->hw_dev ? to_pcmcia_dev(dev->hw_dev) : NULL;
+}
+EXPORT_SYMBOL_GPL(comedi_to_pcmcia_dev);
+
+static int comedi_pcmcia_conf_check(struct pcmcia_device *link,
+ void *priv_data)
+{
+ if (link->config_index == 0)
+ return -EINVAL;
+
+ return pcmcia_request_io(link);
+}
+
+/**
+ * comedi_pcmcia_enable() - Request the regions and enable the PCMCIA device.
+ * @dev: comedi_device struct
+ * @conf_check: optional callback to check the pcmcia_device configuration
+ *
+ * The comedi PCMCIA driver needs to set the link->config_flags, as
+ * appropriate for that driver, before calling this function in order
+ * to allow pcmcia_loop_config() to do its internal autoconfiguration.
+ */
+int comedi_pcmcia_enable(struct comedi_device *dev,
+ int (*conf_check)(struct pcmcia_device *, void *))
+{
+ struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
+ int ret;
+
+ if (!link)
+ return -ENODEV;
+
+ if (!conf_check)
+ conf_check = comedi_pcmcia_conf_check;
+
+ ret = pcmcia_loop_config(link, conf_check, NULL);
+ if (ret)
+ return ret;
+
+ return pcmcia_enable_device(link);
+}
+EXPORT_SYMBOL_GPL(comedi_pcmcia_enable);
+
+/**
+ * comedi_pcmcia_disable() - Disable the PCMCIA device and release the regions.
+ * @dev: comedi_device struct
+ */
+void comedi_pcmcia_disable(struct comedi_device *dev)
+{
+ struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
+
+ if (link)
+ pcmcia_disable_device(link);
+}
+EXPORT_SYMBOL_GPL(comedi_pcmcia_disable);
+
+/**
+ * comedi_pcmcia_auto_config() - Configure/probe a comedi PCMCIA driver.
+ * @link: pcmcia_device struct
+ * @driver: comedi_driver struct
+ *
+ * Typically called from the pcmcia_driver (*probe) function.
+ */
+int comedi_pcmcia_auto_config(struct pcmcia_device *link,
+ struct comedi_driver *driver)
+{
+ return comedi_auto_config(&link->dev, driver, 0);
+}
+EXPORT_SYMBOL_GPL(comedi_pcmcia_auto_config);
+
+/**
+ * comedi_pcmcia_auto_unconfig() - Unconfigure/remove a comedi PCMCIA driver.
+ * @link: pcmcia_device struct
+ *
+ * Typically called from the pcmcia_driver (*remove) function.
+ */
+void comedi_pcmcia_auto_unconfig(struct pcmcia_device *link)
+{
+ comedi_auto_unconfig(&link->dev);
+}
+EXPORT_SYMBOL_GPL(comedi_pcmcia_auto_unconfig);
+
+/**
+ * comedi_pcmcia_driver_register() - Register a comedi PCMCIA driver.
+ * @comedi_driver: comedi_driver struct
+ * @pcmcia_driver: pcmcia_driver struct
+ *
+ * This function is used for the module_init() of comedi USB drivers.
+ * Do not call it directly, use the module_comedi_pcmcia_driver() helper
+ * macro instead.
+ */
+int comedi_pcmcia_driver_register(struct comedi_driver *comedi_driver,
+ struct pcmcia_driver *pcmcia_driver)
+{
+ int ret;
+
+ ret = comedi_driver_register(comedi_driver);
+ if (ret < 0)
+ return ret;
+
+ ret = pcmcia_register_driver(pcmcia_driver);
+ if (ret < 0) {
+ comedi_driver_unregister(comedi_driver);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(comedi_pcmcia_driver_register);
+
+/**
+ * comedi_pcmcia_driver_unregister() - Unregister a comedi PCMCIA driver.
+ * @comedi_driver: comedi_driver struct
+ * @pcmcia_driver: pcmcia_driver struct
+ *
+ * This function is used for the module_exit() of comedi PCMCIA drivers.
+ * Do not call it directly, use the module_comedi_pcmcia_driver() helper
+ * macro instead.
+ */
+void comedi_pcmcia_driver_unregister(struct comedi_driver *comedi_driver,
+ struct pcmcia_driver *pcmcia_driver)
+{
+ pcmcia_unregister_driver(pcmcia_driver);
+ comedi_driver_unregister(comedi_driver);
+}
+EXPORT_SYMBOL_GPL(comedi_pcmcia_driver_unregister);
diff --git a/drivers/staging/comedi/comedi_usb.c b/drivers/staging/comedi/comedi_usb.c
new file mode 100644
index 000000000000..9d9716a248f1
--- /dev/null
+++ b/drivers/staging/comedi/comedi_usb.c
@@ -0,0 +1,108 @@
+/*
+ * comedi_usb.c
+ * Comedi USB driver specific functions.
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1997-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.
+ */
+
+#include <linux/usb.h>
+
+#include "comedidev.h"
+
+/**
+ * comedi_to_usb_interface() - comedi_device pointer to usb_interface pointer.
+ * @dev: comedi_device struct
+ */
+struct usb_interface *comedi_to_usb_interface(struct comedi_device *dev)
+{
+ return dev->hw_dev ? to_usb_interface(dev->hw_dev) : NULL;
+}
+EXPORT_SYMBOL_GPL(comedi_to_usb_interface);
+
+/**
+ * comedi_usb_auto_config() - Configure/probe a comedi USB driver.
+ * @intf: usb_interface struct
+ * @driver: comedi_driver struct
+ * @context: driver specific data, passed to comedi_auto_config()
+ *
+ * Typically called from the usb_driver (*probe) function.
+ */
+int comedi_usb_auto_config(struct usb_interface *intf,
+ struct comedi_driver *driver,
+ unsigned long context)
+{
+ return comedi_auto_config(&intf->dev, driver, context);
+}
+EXPORT_SYMBOL_GPL(comedi_usb_auto_config);
+
+/**
+ * comedi_pci_auto_unconfig() - Unconfigure/disconnect a comedi USB driver.
+ * @intf: usb_interface struct
+ *
+ * Typically called from the usb_driver (*disconnect) function.
+ */
+void comedi_usb_auto_unconfig(struct usb_interface *intf)
+{
+ comedi_auto_unconfig(&intf->dev);
+}
+EXPORT_SYMBOL_GPL(comedi_usb_auto_unconfig);
+
+/**
+ * comedi_usb_driver_register() - Register a comedi USB driver.
+ * @comedi_driver: comedi_driver struct
+ * @usb_driver: usb_driver struct
+ *
+ * This function is used for the module_init() of comedi USB drivers.
+ * Do not call it directly, use the module_comedi_usb_driver() helper
+ * macro instead.
+ */
+int comedi_usb_driver_register(struct comedi_driver *comedi_driver,
+ struct usb_driver *usb_driver)
+{
+ int ret;
+
+ ret = comedi_driver_register(comedi_driver);
+ if (ret < 0)
+ return ret;
+
+ ret = usb_register(usb_driver);
+ if (ret < 0) {
+ comedi_driver_unregister(comedi_driver);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(comedi_usb_driver_register);
+
+/**
+ * comedi_usb_driver_unregister() - Unregister a comedi USB driver.
+ * @comedi_driver: comedi_driver struct
+ * @usb_driver: usb_driver struct
+ *
+ * This function is used for the module_exit() of comedi USB drivers.
+ * Do not call it directly, use the module_comedi_usb_driver() helper
+ * macro instead.
+ */
+void comedi_usb_driver_unregister(struct comedi_driver *comedi_driver,
+ struct usb_driver *usb_driver)
+{
+ usb_deregister(usb_driver);
+ comedi_driver_unregister(comedi_driver);
+}
+EXPORT_SYMBOL_GPL(comedi_usb_driver_unregister);
diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
index 692e1e615d44..f3a990b45df5 100644
--- a/drivers/staging/comedi/comedidev.h
+++ b/drivers/staging/comedi/comedidev.h
@@ -40,8 +40,6 @@
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/timer.h>
-#include <linux/pci.h>
-#include <linux/usb.h>
#include "comedi.h"
@@ -55,28 +53,13 @@
COMEDI_MINORVERSION, COMEDI_MICROVERSION)
#define COMEDI_RELEASE VERSION
-/*
- * PCI Vendor IDs not in <linux/pci_ids.h>
- */
-#define PCI_VENDOR_ID_KOLTER 0x1001
-#define PCI_VENDOR_ID_ICP 0x104c
-#define PCI_VENDOR_ID_AMCC 0x10e8
-#define PCI_VENDOR_ID_DT 0x1116
-#define PCI_VENDOR_ID_IOTECH 0x1616
-#define PCI_VENDOR_ID_CONTEC 0x1221
-#define PCI_VENDOR_ID_CB 0x1307 /* Measurement Computing */
-#define PCI_VENDOR_ID_ADVANTECH 0x13fe
-#define PCI_VENDOR_ID_MEILHAUS 0x1402
-#define PCI_VENDOR_ID_RTD 0x1435
-#define PCI_VENDOR_ID_ADLINK 0x144a
-#define PCI_VENDOR_ID_AMPLICON 0x14dc
-
#define COMEDI_NUM_MINORS 0x100
#define COMEDI_NUM_BOARD_MINORS 0x30
#define COMEDI_FIRST_SUBDEVICE_MINOR COMEDI_NUM_BOARD_MINORS
struct comedi_subdevice {
struct comedi_device *device;
+ int index;
int type;
int n_chan;
int subdev_flags;
@@ -250,13 +233,6 @@ static inline const void *comedi_board(const struct comedi_device *dev)
return dev->board_ptr;
}
-struct comedi_device_file_info {
- struct comedi_device *device;
- struct comedi_subdevice *read_subdevice;
- struct comedi_subdevice *write_subdevice;
- struct device *hardware_device;
-};
-
#ifdef CONFIG_COMEDI_DEBUG
extern int comedi_debug;
#else
@@ -280,105 +256,13 @@ enum comedi_minor_bits {
static const unsigned COMEDI_SUBDEVICE_MINOR_SHIFT = 4;
static const unsigned COMEDI_SUBDEVICE_MINOR_OFFSET = 1;
-struct comedi_device_file_info *comedi_get_device_file_info(unsigned minor);
-
-static inline struct comedi_subdevice *comedi_get_read_subdevice(
- const struct comedi_device_file_info *info)
-{
- if (info->read_subdevice)
- return info->read_subdevice;
- if (info->device == NULL)
- return NULL;
- return info->device->read_subdev;
-}
-
-static inline struct comedi_subdevice *comedi_get_write_subdevice(
- const struct comedi_device_file_info *info)
-{
- if (info->write_subdevice)
- return info->write_subdevice;
- if (info->device == NULL)
- return NULL;
- return info->device->write_subdev;
-}
-
-int comedi_alloc_subdevices(struct comedi_device *, int);
-
-void comedi_device_detach(struct comedi_device *dev);
-int comedi_device_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-int comedi_driver_register(struct comedi_driver *);
-int comedi_driver_unregister(struct comedi_driver *);
-
-/**
- * module_comedi_driver() - Helper macro for registering a comedi driver
- * @__comedi_driver: comedi_driver struct
- *
- * Helper macro for comedi drivers which do not do anything special in module
- * init/exit. This eliminates a lot of boilerplate. Each module may only use
- * this macro once, and calling it replaces module_init() and module_exit().
- */
-#define module_comedi_driver(__comedi_driver) \
- module_driver(__comedi_driver, comedi_driver_register, \
- comedi_driver_unregister)
-
-int comedi_pci_enable(struct pci_dev *, const char *);
-void comedi_pci_disable(struct pci_dev *);
-
-int comedi_pci_driver_register(struct comedi_driver *, struct pci_driver *);
-void comedi_pci_driver_unregister(struct comedi_driver *, struct pci_driver *);
-
-/**
- * module_comedi_pci_driver() - Helper macro for registering a comedi PCI driver
- * @__comedi_driver: comedi_driver struct
- * @__pci_driver: pci_driver struct
- *
- * Helper macro for comedi PCI drivers which do not do anything special
- * in module init/exit. This eliminates a lot of boilerplate. Each
- * module may only use this macro once, and calling it replaces
- * module_init() and module_exit()
- */
-#define module_comedi_pci_driver(__comedi_driver, __pci_driver) \
- module_driver(__comedi_driver, comedi_pci_driver_register, \
- comedi_pci_driver_unregister, &(__pci_driver))
-
-struct usb_driver;
-
-int comedi_usb_driver_register(struct comedi_driver *, struct usb_driver *);
-void comedi_usb_driver_unregister(struct comedi_driver *, struct usb_driver *);
-
-/**
- * module_comedi_usb_driver() - Helper macro for registering a comedi USB driver
- * @__comedi_driver: comedi_driver struct
- * @__usb_driver: usb_driver struct
- *
- * Helper macro for comedi USB drivers which do not do anything special
- * in module init/exit. This eliminates a lot of boilerplate. Each
- * module may only use this macro once, and calling it replaces
- * module_init() and module_exit()
- */
-#define module_comedi_usb_driver(__comedi_driver, __usb_driver) \
- module_driver(__comedi_driver, comedi_usb_driver_register, \
- comedi_usb_driver_unregister, &(__usb_driver))
+struct comedi_device *comedi_dev_from_minor(unsigned minor);
void init_polling(void);
void cleanup_polling(void);
void start_polling(struct comedi_device *);
void stop_polling(struct comedi_device *);
-#ifdef CONFIG_PROC_FS
-void comedi_proc_init(void);
-void comedi_proc_cleanup(void);
-#else
-static inline void comedi_proc_init(void)
-{
-}
-
-static inline void comedi_proc_cleanup(void)
-{
-}
-#endif
-
/* subdevice runflags */
enum subdevice_runflags {
SRF_USER = 0x00000001,
@@ -389,10 +273,11 @@ enum subdevice_runflags {
SRF_RUNNING = 0x08000000
};
+bool comedi_is_subdevice_running(struct comedi_subdevice *s);
+
int comedi_check_chanlist(struct comedi_subdevice *s,
int n,
unsigned int *chanlist);
-unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s);
/* range stuff */
@@ -433,111 +318,186 @@ static inline unsigned int bytes_per_sample(const struct comedi_subdevice *subd)
return sizeof(short);
}
-/* must be used in attach to set dev->hw_dev if you wish to dma directly
-into comedi's buffer */
-static inline void comedi_set_hw_dev(struct comedi_device *dev,
- struct device *hw_dev)
-{
- if (dev->hw_dev == hw_dev)
- return;
- if (dev->hw_dev)
- put_device(dev->hw_dev);
- dev->hw_dev = hw_dev;
- if (dev->hw_dev) {
- dev->hw_dev = get_device(dev->hw_dev);
- BUG_ON(dev->hw_dev == NULL);
- }
-}
+/*
+ * Must set dev->hw_dev if you wish to dma directly into comedi's buffer.
+ * Also useful for retrieving a previously configured hardware device of
+ * known bus type. Set automatically for auto-configured devices.
+ * Automatically set to NULL when detaching hardware device.
+ */
+int comedi_set_hw_dev(struct comedi_device *dev, struct device *hw_dev);
-static inline struct pci_dev *comedi_to_pci_dev(struct comedi_device *dev)
-{
- return dev->hw_dev ? to_pci_dev(dev->hw_dev) : NULL;
-}
+unsigned int comedi_buf_write_alloc(struct comedi_async *, unsigned int);
+unsigned int comedi_buf_write_free(struct comedi_async *, unsigned int);
-static inline struct usb_interface *
-comedi_to_usb_interface(struct comedi_device *dev)
-{
- return dev->hw_dev ? to_usb_interface(dev->hw_dev) : NULL;
-}
+unsigned int comedi_buf_read_n_available(struct comedi_async *);
+unsigned int comedi_buf_read_alloc(struct comedi_async *, unsigned int);
+unsigned int comedi_buf_read_free(struct comedi_async *, unsigned int);
+
+int comedi_buf_put(struct comedi_async *, short);
+int comedi_buf_get(struct comedi_async *, short *);
-int comedi_buf_put(struct comedi_async *async, short x);
-int comedi_buf_get(struct comedi_async *async, short *x);
-
-unsigned int comedi_buf_write_n_available(struct comedi_async *async);
-unsigned int comedi_buf_write_alloc(struct comedi_async *async,
- unsigned int nbytes);
-unsigned int comedi_buf_write_alloc_strict(struct comedi_async *async,
- unsigned int nbytes);
-unsigned comedi_buf_write_free(struct comedi_async *async, unsigned int nbytes);
-unsigned comedi_buf_read_alloc(struct comedi_async *async, unsigned nbytes);
-unsigned comedi_buf_read_free(struct comedi_async *async, unsigned int nbytes);
-unsigned int comedi_buf_read_n_available(struct comedi_async *async);
void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset,
const void *source, unsigned int num_bytes);
void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset,
void *destination, unsigned int num_bytes);
-static inline unsigned comedi_buf_write_n_allocated(struct comedi_async *async)
-{
- return async->buf_write_alloc_count - async->buf_write_count;
-}
-static inline unsigned comedi_buf_read_n_allocated(struct comedi_async *async)
-{
- return async->buf_read_alloc_count - async->buf_read_count;
-}
+/* drivers.c - general comedi driver functions */
-static inline void *comedi_aux_data(int options[], int n)
-{
- unsigned long address;
- unsigned long addressLow;
- int bit_shift;
- if (sizeof(int) >= sizeof(void *))
- address = options[COMEDI_DEVCONF_AUX_DATA_LO];
- else {
- address = options[COMEDI_DEVCONF_AUX_DATA_HI];
- bit_shift = sizeof(int) * 8;
- address <<= bit_shift;
- addressLow = options[COMEDI_DEVCONF_AUX_DATA_LO];
- addressLow &= (1UL << bit_shift) - 1;
- address |= addressLow;
- }
- if (n >= 1)
- address += options[COMEDI_DEVCONF_AUX_DATA0_LENGTH];
- if (n >= 2)
- address += options[COMEDI_DEVCONF_AUX_DATA1_LENGTH];
- if (n >= 3)
- address += options[COMEDI_DEVCONF_AUX_DATA2_LENGTH];
- BUG_ON(n > 3);
- return (void *)address;
-}
+int comedi_alloc_subdevices(struct comedi_device *, int);
-int comedi_alloc_subdevice_minor(struct comedi_device *dev,
- struct comedi_subdevice *s);
-void comedi_free_subdevice_minor(struct comedi_subdevice *s);
-int comedi_auto_config(struct device *hardware_device,
- struct comedi_driver *driver, unsigned long context);
-void comedi_auto_unconfig(struct device *hardware_device);
+int comedi_auto_config(struct device *, struct comedi_driver *,
+ unsigned long context);
+void comedi_auto_unconfig(struct device *);
-static inline int comedi_pci_auto_config(struct pci_dev *pcidev,
- struct comedi_driver *driver)
-{
- return comedi_auto_config(&pcidev->dev, driver, 0);
-}
+int comedi_driver_register(struct comedi_driver *);
+int comedi_driver_unregister(struct comedi_driver *);
+
+/**
+ * module_comedi_driver() - Helper macro for registering a comedi driver
+ * @__comedi_driver: comedi_driver struct
+ *
+ * Helper macro for comedi drivers which do not do anything special in module
+ * init/exit. This eliminates a lot of boilerplate. Each module may only use
+ * this macro once, and calling it replaces module_init() and module_exit().
+ */
+#define module_comedi_driver(__comedi_driver) \
+ module_driver(__comedi_driver, comedi_driver_register, \
+ comedi_driver_unregister)
+
+#ifdef CONFIG_COMEDI_PCI_DRIVERS
+
+/* comedi_pci.c - comedi PCI driver specific functions */
+
+/*
+ * PCI Vendor IDs not in <linux/pci_ids.h>
+ */
+#define PCI_VENDOR_ID_KOLTER 0x1001
+#define PCI_VENDOR_ID_ICP 0x104c
+#define PCI_VENDOR_ID_AMCC 0x10e8
+#define PCI_VENDOR_ID_DT 0x1116
+#define PCI_VENDOR_ID_IOTECH 0x1616
+#define PCI_VENDOR_ID_CONTEC 0x1221
+#define PCI_VENDOR_ID_RTD 0x1435
+
+struct pci_dev;
+struct pci_driver;
+
+struct pci_dev *comedi_to_pci_dev(struct comedi_device *);
+
+int comedi_pci_enable(struct pci_dev *, const char *);
+void comedi_pci_disable(struct pci_dev *);
+
+int comedi_pci_auto_config(struct pci_dev *, struct comedi_driver *);
+void comedi_pci_auto_unconfig(struct pci_dev *);
+
+int comedi_pci_driver_register(struct comedi_driver *, struct pci_driver *);
+void comedi_pci_driver_unregister(struct comedi_driver *, struct pci_driver *);
+
+/**
+ * module_comedi_pci_driver() - Helper macro for registering a comedi PCI driver
+ * @__comedi_driver: comedi_driver struct
+ * @__pci_driver: pci_driver struct
+ *
+ * Helper macro for comedi PCI drivers which do not do anything special
+ * in module init/exit. This eliminates a lot of boilerplate. Each
+ * module may only use this macro once, and calling it replaces
+ * module_init() and module_exit()
+ */
+#define module_comedi_pci_driver(__comedi_driver, __pci_driver) \
+ module_driver(__comedi_driver, comedi_pci_driver_register, \
+ comedi_pci_driver_unregister, &(__pci_driver))
-static inline void comedi_pci_auto_unconfig(struct pci_dev *pcidev)
+#else
+
+/*
+ * Some of the comedi mixed ISA/PCI drivers call the PCI specific
+ * functions. Provide some dummy functions if CONFIG_COMEDI_PCI_DRIVERS
+ * is not enabled.
+ */
+
+static inline struct pci_dev *comedi_to_pci_dev(struct comedi_device *dev)
{
- comedi_auto_unconfig(&pcidev->dev);
+ return NULL;
}
-static inline int comedi_usb_auto_config(struct usb_interface *intf,
- struct comedi_driver *driver)
+static inline int comedi_pci_enable(struct pci_dev *dev, const char *name)
{
- return comedi_auto_config(&intf->dev, driver, 0);
+ return -ENOSYS;
}
-static inline void comedi_usb_auto_unconfig(struct usb_interface *intf)
+static inline void comedi_pci_disable(struct pci_dev *dev)
{
- comedi_auto_unconfig(&intf->dev);
}
+#endif /* CONFIG_COMEDI_PCI_DRIVERS */
+
+#ifdef CONFIG_COMEDI_PCMCIA_DRIVERS
+
+/* comedi_pcmcia.c - comedi PCMCIA driver specific functions */
+
+struct pcmcia_driver;
+struct pcmcia_device;
+
+struct pcmcia_device *comedi_to_pcmcia_dev(struct comedi_device *);
+
+int comedi_pcmcia_enable(struct comedi_device *,
+ int (*conf_check)(struct pcmcia_device *, void *));
+void comedi_pcmcia_disable(struct comedi_device *);
+
+int comedi_pcmcia_auto_config(struct pcmcia_device *, struct comedi_driver *);
+void comedi_pcmcia_auto_unconfig(struct pcmcia_device *);
+
+int comedi_pcmcia_driver_register(struct comedi_driver *,
+ struct pcmcia_driver *);
+void comedi_pcmcia_driver_unregister(struct comedi_driver *,
+ struct pcmcia_driver *);
+
+/**
+ * module_comedi_pcmcia_driver() - Helper macro for registering a comedi PCMCIA driver
+ * @__comedi_driver: comedi_driver struct
+ * @__pcmcia_driver: pcmcia_driver struct
+ *
+ * Helper macro for comedi PCMCIA drivers which do not do anything special
+ * in module init/exit. This eliminates a lot of boilerplate. Each
+ * module may only use this macro once, and calling it replaces
+ * module_init() and module_exit()
+ */
+#define module_comedi_pcmcia_driver(__comedi_driver, __pcmcia_driver) \
+ module_driver(__comedi_driver, comedi_pcmcia_driver_register, \
+ comedi_pcmcia_driver_unregister, &(__pcmcia_driver))
+
+#endif /* CONFIG_COMEDI_PCMCIA_DRIVERS */
+
+#ifdef CONFIG_COMEDI_USB_DRIVERS
+
+/* comedi_usb.c - comedi USB driver specific functions */
+
+struct usb_driver;
+struct usb_interface;
+
+struct usb_interface *comedi_to_usb_interface(struct comedi_device *);
+
+int comedi_usb_auto_config(struct usb_interface *, struct comedi_driver *,
+ unsigned long context);
+void comedi_usb_auto_unconfig(struct usb_interface *);
+
+int comedi_usb_driver_register(struct comedi_driver *, struct usb_driver *);
+void comedi_usb_driver_unregister(struct comedi_driver *, struct usb_driver *);
+
+/**
+ * module_comedi_usb_driver() - Helper macro for registering a comedi USB driver
+ * @__comedi_driver: comedi_driver struct
+ * @__usb_driver: usb_driver struct
+ *
+ * Helper macro for comedi USB drivers which do not do anything special
+ * in module init/exit. This eliminates a lot of boilerplate. Each
+ * module may only use this macro once, and calling it replaces
+ * module_init() and module_exit()
+ */
+#define module_comedi_usb_driver(__comedi_driver, __usb_driver) \
+ module_driver(__comedi_driver, comedi_usb_driver_register, \
+ comedi_usb_driver_unregister, &(__usb_driver))
+
+#endif /* CONFIG_COMEDI_USB_DRIVERS */
+
#endif /* _COMEDIDEV_H */
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index 50cf498698e2..64be7c5e891e 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -23,8 +23,6 @@
#include <linux/device.h>
#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/usb.h>
#include <linux/errno.h>
#include <linux/kconfig.h>
#include <linux/kernel.h>
@@ -43,16 +41,25 @@
#include "comedidev.h"
#include "comedi_internal.h"
-static int postconfig(struct comedi_device *dev);
-static int insn_rw_emulate_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static void *comedi_recognize(struct comedi_driver *driv, const char *name);
-static void comedi_report_boards(struct comedi_driver *driv);
-static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s);
-
struct comedi_driver *comedi_drivers;
+int comedi_set_hw_dev(struct comedi_device *dev, struct device *hw_dev)
+{
+ if (hw_dev == dev->hw_dev)
+ return 0;
+ if (dev->hw_dev != NULL)
+ return -EEXIST;
+ dev->hw_dev = get_device(hw_dev);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(comedi_set_hw_dev);
+
+static void comedi_clear_hw_dev(struct comedi_device *dev)
+{
+ put_device(dev->hw_dev);
+ dev->hw_dev = NULL;
+}
+
int comedi_alloc_subdevices(struct comedi_device *dev, int num_subdevices)
{
struct comedi_subdevice *s;
@@ -70,6 +77,7 @@ int comedi_alloc_subdevices(struct comedi_device *dev, int num_subdevices)
for (i = 0; i < num_subdevices; ++i) {
s = &dev->subdevices[i];
s->device = dev;
+ s->index = i;
s->async_dma_dir = DMA_NONE;
spin_lock_init(&s->spin_lock);
s->minor = -1;
@@ -107,7 +115,7 @@ static void cleanup_device(struct comedi_device *dev)
dev->write_subdev = NULL;
dev->open = NULL;
dev->close = NULL;
- comedi_set_hw_dev(dev, NULL);
+ comedi_clear_hw_dev(dev);
}
static void __comedi_device_detach(struct comedi_device *dev)
@@ -128,131 +136,105 @@ void comedi_device_detach(struct comedi_device *dev)
__comedi_device_detach(dev);
}
-/* do a little post-config cleanup */
-/* called with module refcount incremented, decrements it */
-static int comedi_device_postconfig(struct comedi_device *dev)
+static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s)
{
- int ret = postconfig(dev);
- module_put(dev->driver->module);
- if (ret < 0) {
- __comedi_device_detach(dev);
- return ret;
- }
- if (!dev->board_name) {
- dev_warn(dev->class_dev, "BUG: dev->board_name=NULL\n");
- dev->board_name = "BUG";
- }
- smp_wmb();
- dev->attached = 1;
- return 0;
+ return -EINVAL;
}
-int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
{
- struct comedi_driver *driv;
+ return -EINVAL;
+}
+
+static int insn_rw_emulate_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+ struct comedi_insn new_insn;
int ret;
+ static const unsigned channels_per_bitfield = 32;
- if (dev->attached)
- return -EBUSY;
+ unsigned chan = CR_CHAN(insn->chanspec);
+ const unsigned base_bitfield_channel =
+ (chan < channels_per_bitfield) ? 0 : chan;
+ unsigned int new_data[2];
+ memset(new_data, 0, sizeof(new_data));
+ memset(&new_insn, 0, sizeof(new_insn));
+ new_insn.insn = INSN_BITS;
+ new_insn.chanspec = base_bitfield_channel;
+ new_insn.n = 2;
+ new_insn.subdev = insn->subdev;
- for (driv = comedi_drivers; driv; driv = driv->next) {
- if (!try_module_get(driv->module))
- continue;
- if (driv->num_names) {
- dev->board_ptr = comedi_recognize(driv, it->board_name);
- if (dev->board_ptr)
- break;
- } else if (strcmp(driv->driver_name, it->board_name) == 0)
- break;
- module_put(driv->module);
- }
- if (driv == NULL) {
- /* recognize has failed if we get here */
- /* report valid board names before returning error */
- for (driv = comedi_drivers; driv; driv = driv->next) {
- if (!try_module_get(driv->module))
- continue;
- comedi_report_boards(driv);
- module_put(driv->module);
- }
- return -EIO;
- }
- if (driv->attach == NULL) {
- /* driver does not support manual configuration */
- dev_warn(dev->class_dev,
- "driver '%s' does not support attach using comedi_config\n",
- driv->driver_name);
- module_put(driv->module);
- return -ENOSYS;
+ if (insn->insn == INSN_WRITE) {
+ if (!(s->subdev_flags & SDF_WRITABLE))
+ return -EINVAL;
+ new_data[0] = 1 << (chan - base_bitfield_channel); /* mask */
+ new_data[1] = data[0] ? (1 << (chan - base_bitfield_channel))
+ : 0; /* bits */
}
- /* initialize dev->driver here so
- * comedi_error() can be called from attach */
- dev->driver = driv;
- ret = driv->attach(dev, it);
- if (ret < 0) {
- module_put(dev->driver->module);
- __comedi_device_detach(dev);
+
+ ret = s->insn_bits(dev, s, &new_insn, new_data);
+ if (ret < 0)
return ret;
- }
- return comedi_device_postconfig(dev);
-}
-int comedi_driver_register(struct comedi_driver *driver)
-{
- driver->next = comedi_drivers;
- comedi_drivers = driver;
+ if (insn->insn == INSN_READ)
+ data[0] = (new_data[1] >> (chan - base_bitfield_channel)) & 1;
- return 0;
+ return 1;
}
-EXPORT_SYMBOL(comedi_driver_register);
-int comedi_driver_unregister(struct comedi_driver *driver)
+static int __comedi_device_postconfig_async(struct comedi_device *dev,
+ struct comedi_subdevice *s)
{
- struct comedi_driver *prev;
- int i;
+ struct comedi_async *async;
+ unsigned int buf_size;
+ int ret;
- /* check for devices using this driver */
- for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
- struct comedi_device_file_info *dev_file_info =
- comedi_get_device_file_info(i);
- struct comedi_device *dev;
+ if ((s->subdev_flags & (SDF_CMD_READ | SDF_CMD_WRITE)) == 0) {
+ dev_warn(dev->class_dev,
+ "async subdevices must support SDF_CMD_READ or SDF_CMD_WRITE\n");
+ return -EINVAL;
+ }
+ if (!s->do_cmdtest) {
+ dev_warn(dev->class_dev,
+ "async subdevices must have a do_cmdtest() function\n");
+ return -EINVAL;
+ }
- if (dev_file_info == NULL)
- continue;
- dev = dev_file_info->device;
+ async = kzalloc(sizeof(*async), GFP_KERNEL);
+ if (!async)
+ return -ENOMEM;
- mutex_lock(&dev->mutex);
- if (dev->attached && dev->driver == driver) {
- if (dev->use_count)
- dev_warn(dev->class_dev,
- "BUG! detaching device with use_count=%d\n",
- dev->use_count);
- comedi_device_detach(dev);
- }
- mutex_unlock(&dev->mutex);
- }
+ init_waitqueue_head(&async->wait_head);
+ async->subdevice = s;
+ s->async = async;
- if (comedi_drivers == driver) {
- comedi_drivers = driver->next;
- return 0;
- }
+ async->max_bufsize = comedi_default_buf_maxsize_kb * 1024;
+ buf_size = comedi_default_buf_size_kb * 1024;
+ if (buf_size > async->max_bufsize)
+ buf_size = async->max_bufsize;
- for (prev = comedi_drivers; prev->next; prev = prev->next) {
- if (prev->next == driver) {
- prev->next = driver->next;
- return 0;
- }
+ if (comedi_buf_alloc(dev, s, buf_size) < 0) {
+ dev_warn(dev->class_dev, "Buffer allocation failed\n");
+ return -ENOMEM;
}
- return -EINVAL;
+ if (s->buf_change) {
+ ret = s->buf_change(dev, s, buf_size);
+ if (ret < 0)
+ return ret;
+ }
+
+ comedi_alloc_subdevice_minor(s);
+
+ return 0;
}
-EXPORT_SYMBOL(comedi_driver_unregister);
-static int postconfig(struct comedi_device *dev)
+static int __comedi_device_postconfig(struct comedi_device *dev)
{
- int i;
struct comedi_subdevice *s;
- struct comedi_async *async = NULL;
int ret;
+ int i;
for (i = 0; i < dev->n_subdevices; i++) {
s = &dev->subdevices[i];
@@ -264,42 +246,9 @@ static int postconfig(struct comedi_device *dev)
s->len_chanlist = 1;
if (s->do_cmd) {
- unsigned int buf_size;
-
- BUG_ON((s->subdev_flags & (SDF_CMD_READ |
- SDF_CMD_WRITE)) == 0);
- BUG_ON(!s->do_cmdtest);
-
- async =
- kzalloc(sizeof(struct comedi_async), GFP_KERNEL);
- if (async == NULL) {
- dev_warn(dev->class_dev,
- "failed to allocate async struct\n");
- return -ENOMEM;
- }
- init_waitqueue_head(&async->wait_head);
- async->subdevice = s;
- s->async = async;
-
- async->max_bufsize =
- comedi_default_buf_maxsize_kb * 1024;
- buf_size = comedi_default_buf_size_kb * 1024;
- if (buf_size > async->max_bufsize)
- buf_size = async->max_bufsize;
-
- async->prealloc_buf = NULL;
- async->prealloc_bufsz = 0;
- if (comedi_buf_alloc(dev, s, buf_size) < 0) {
- dev_warn(dev->class_dev,
- "Buffer allocation failed\n");
- return -ENOMEM;
- }
- if (s->buf_change) {
- ret = s->buf_change(dev, s, buf_size);
- if (ret < 0)
- return ret;
- }
- comedi_alloc_subdevice_minor(dev, s);
+ ret = __comedi_device_postconfig_async(dev, s);
+ if (ret)
+ return ret;
}
if (!s->range_table && !s->range_table_list)
@@ -326,6 +275,25 @@ static int postconfig(struct comedi_device *dev)
return 0;
}
+/* do a little post-config cleanup */
+/* called with module refcount incremented, decrements it */
+static int comedi_device_postconfig(struct comedi_device *dev)
+{
+ int ret = __comedi_device_postconfig(dev);
+ module_put(dev->driver->module);
+ if (ret < 0) {
+ __comedi_device_detach(dev);
+ return ret;
+ }
+ if (!dev->board_name) {
+ dev_warn(dev->class_dev, "BUG: dev->board_name=NULL\n");
+ dev->board_name = "BUG";
+ }
+ smp_wmb();
+ dev->attached = 1;
+ return 0;
+}
+
/*
* Generic recognize function for drivers that register their supported
* board names.
@@ -384,463 +352,63 @@ static void comedi_report_boards(struct comedi_driver *driv)
pr_info(" %s\n", driv->driver_name);
}
-static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s)
-{
- return -EINVAL;
-}
-
-int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- return -EINVAL;
-}
-
-static int insn_rw_emulate_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
- struct comedi_insn new_insn;
+ struct comedi_driver *driv;
int ret;
- static const unsigned channels_per_bitfield = 32;
-
- unsigned chan = CR_CHAN(insn->chanspec);
- const unsigned base_bitfield_channel =
- (chan < channels_per_bitfield) ? 0 : chan;
- unsigned int new_data[2];
- memset(new_data, 0, sizeof(new_data));
- memset(&new_insn, 0, sizeof(new_insn));
- new_insn.insn = INSN_BITS;
- new_insn.chanspec = base_bitfield_channel;
- new_insn.n = 2;
- new_insn.subdev = insn->subdev;
- if (insn->insn == INSN_WRITE) {
- if (!(s->subdev_flags & SDF_WRITABLE))
- return -EINVAL;
- new_data[0] = 1 << (chan - base_bitfield_channel); /* mask */
- new_data[1] = data[0] ? (1 << (chan - base_bitfield_channel))
- : 0; /* bits */
- }
-
- ret = s->insn_bits(dev, s, &new_insn, new_data);
- if (ret < 0)
- return ret;
-
- if (insn->insn == INSN_READ)
- data[0] = (new_data[1] >> (chan - base_bitfield_channel)) & 1;
-
- return 1;
-}
-
-int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
- unsigned long new_size)
-{
- struct comedi_async *async = s->async;
-
- /* Round up new_size to multiple of PAGE_SIZE */
- new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
-
- /* if no change is required, do nothing */
- if (async->prealloc_buf && async->prealloc_bufsz == new_size)
- return 0;
-
- /* deallocate old buffer */
- if (async->prealloc_buf) {
- vunmap(async->prealloc_buf);
- async->prealloc_buf = NULL;
- async->prealloc_bufsz = 0;
- }
- if (async->buf_page_list) {
- unsigned i;
- for (i = 0; i < async->n_buf_pages; ++i) {
- if (async->buf_page_list[i].virt_addr) {
- clear_bit(PG_reserved,
- &(virt_to_page(async->buf_page_list[i].
- virt_addr)->flags));
- if (s->async_dma_dir != DMA_NONE) {
- dma_free_coherent(dev->hw_dev,
- PAGE_SIZE,
- async->
- buf_page_list
- [i].virt_addr,
- async->
- buf_page_list
- [i].dma_addr);
- } else {
- free_page((unsigned long)
- async->buf_page_list[i].
- virt_addr);
- }
- }
- }
- vfree(async->buf_page_list);
- async->buf_page_list = NULL;
- async->n_buf_pages = 0;
- }
- /* allocate new buffer */
- if (new_size) {
- unsigned i = 0;
- unsigned n_pages = new_size >> PAGE_SHIFT;
- struct page **pages = NULL;
-
- async->buf_page_list =
- vzalloc(sizeof(struct comedi_buf_page) * n_pages);
- if (async->buf_page_list)
- pages = vmalloc(sizeof(struct page *) * n_pages);
-
- if (pages) {
- for (i = 0; i < n_pages; i++) {
- if (s->async_dma_dir != DMA_NONE) {
- async->buf_page_list[i].virt_addr =
- dma_alloc_coherent(dev->hw_dev,
- PAGE_SIZE,
- &async->
- buf_page_list
- [i].dma_addr,
- GFP_KERNEL |
- __GFP_COMP);
- } else {
- async->buf_page_list[i].virt_addr =
- (void *)
- get_zeroed_page(GFP_KERNEL);
- }
- if (async->buf_page_list[i].virt_addr == NULL)
- break;
-
- set_bit(PG_reserved,
- &(virt_to_page(async->buf_page_list[i].
- virt_addr)->flags));
- pages[i] = virt_to_page(async->buf_page_list[i].
- virt_addr);
- }
- }
- if (i == n_pages) {
- async->prealloc_buf =
-#ifdef PAGE_KERNEL_NOCACHE
- vmap(pages, n_pages, VM_MAP, PAGE_KERNEL_NOCACHE);
-#else
- vmap(pages, n_pages, VM_MAP, PAGE_KERNEL);
-#endif
- }
- vfree(pages);
-
- if (async->prealloc_buf == NULL) {
- /* Some allocation failed above. */
- if (async->buf_page_list) {
- for (i = 0; i < n_pages; i++) {
- if (async->buf_page_list[i].virt_addr ==
- NULL) {
- break;
- }
- clear_bit(PG_reserved,
- &(virt_to_page(async->
- buf_page_list[i].
- virt_addr)->flags));
- if (s->async_dma_dir != DMA_NONE) {
- dma_free_coherent(dev->hw_dev,
- PAGE_SIZE,
- async->
- buf_page_list
- [i].virt_addr,
- async->
- buf_page_list
- [i].dma_addr);
- } else {
- free_page((unsigned long)
- async->buf_page_list
- [i].virt_addr);
- }
- }
- vfree(async->buf_page_list);
- async->buf_page_list = NULL;
- }
- return -ENOMEM;
- }
- async->n_buf_pages = n_pages;
- }
- async->prealloc_bufsz = new_size;
-
- return 0;
-}
+ if (dev->attached)
+ return -EBUSY;
-/* munging is applied to data by core as it passes between user
- * and kernel space */
-static unsigned int comedi_buf_munge(struct comedi_async *async,
- unsigned int num_bytes)
-{
- struct comedi_subdevice *s = async->subdevice;
- unsigned int count = 0;
- const unsigned num_sample_bytes = bytes_per_sample(s);
-
- if (s->munge == NULL || (async->cmd.flags & CMDF_RAWDATA)) {
- async->munge_count += num_bytes;
- BUG_ON((int)(async->munge_count - async->buf_write_count) > 0);
- return num_bytes;
- }
- /* don't munge partial samples */
- num_bytes -= num_bytes % num_sample_bytes;
- while (count < num_bytes) {
- int block_size;
-
- block_size = num_bytes - count;
- if (block_size < 0) {
- dev_warn(s->device->class_dev,
- "%s: %s: bug! block_size is negative\n",
- __FILE__, __func__);
+ for (driv = comedi_drivers; driv; driv = driv->next) {
+ if (!try_module_get(driv->module))
+ continue;
+ if (driv->num_names) {
+ dev->board_ptr = comedi_recognize(driv, it->board_name);
+ if (dev->board_ptr)
+ break;
+ } else if (strcmp(driv->driver_name, it->board_name) == 0)
break;
- }
- if ((int)(async->munge_ptr + block_size -
- async->prealloc_bufsz) > 0)
- block_size = async->prealloc_bufsz - async->munge_ptr;
-
- s->munge(s->device, s, async->prealloc_buf + async->munge_ptr,
- block_size, async->munge_chan);
-
- smp_wmb(); /* barrier insures data is munged in buffer
- * before munge_count is incremented */
-
- async->munge_chan += block_size / num_sample_bytes;
- async->munge_chan %= async->cmd.chanlist_len;
- async->munge_count += block_size;
- async->munge_ptr += block_size;
- async->munge_ptr %= async->prealloc_bufsz;
- count += block_size;
- }
- BUG_ON((int)(async->munge_count - async->buf_write_count) > 0);
- return count;
-}
-
-unsigned int comedi_buf_write_n_available(struct comedi_async *async)
-{
- unsigned int free_end;
- unsigned int nbytes;
-
- if (async == NULL)
- return 0;
-
- free_end = async->buf_read_count + async->prealloc_bufsz;
- nbytes = free_end - async->buf_write_alloc_count;
- nbytes -= nbytes % bytes_per_sample(async->subdevice);
- /* barrier insures the read of buf_read_count in this
- query occurs before any following writes to the buffer which
- might be based on the return value from this query.
- */
- smp_mb();
- return nbytes;
-}
-
-/* allocates chunk for the writer from free buffer space */
-unsigned int comedi_buf_write_alloc(struct comedi_async *async,
- unsigned int nbytes)
-{
- unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
-
- if ((int)(async->buf_write_alloc_count + nbytes - free_end) > 0)
- nbytes = free_end - async->buf_write_alloc_count;
-
- async->buf_write_alloc_count += nbytes;
- /* barrier insures the read of buf_read_count above occurs before
- we write data to the write-alloc'ed buffer space */
- smp_mb();
- return nbytes;
-}
-EXPORT_SYMBOL(comedi_buf_write_alloc);
-
-/* allocates nothing unless it can completely fulfill the request */
-unsigned int comedi_buf_write_alloc_strict(struct comedi_async *async,
- unsigned int nbytes)
-{
- unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
-
- if ((int)(async->buf_write_alloc_count + nbytes - free_end) > 0)
- nbytes = 0;
-
- async->buf_write_alloc_count += nbytes;
- /* barrier insures the read of buf_read_count above occurs before
- we write data to the write-alloc'ed buffer space */
- smp_mb();
- return nbytes;
-}
-
-/* transfers a chunk from writer to filled buffer space */
-unsigned comedi_buf_write_free(struct comedi_async *async, unsigned int nbytes)
-{
- if ((int)(async->buf_write_count + nbytes -
- async->buf_write_alloc_count) > 0) {
- dev_info(async->subdevice->device->class_dev,
- "attempted to write-free more bytes than have been write-allocated.\n");
- nbytes = async->buf_write_alloc_count - async->buf_write_count;
- }
- async->buf_write_count += nbytes;
- async->buf_write_ptr += nbytes;
- comedi_buf_munge(async, async->buf_write_count - async->munge_count);
- if (async->buf_write_ptr >= async->prealloc_bufsz)
- async->buf_write_ptr %= async->prealloc_bufsz;
-
- return nbytes;
-}
-EXPORT_SYMBOL(comedi_buf_write_free);
-
-/* allocates a chunk for the reader from filled (and munged) buffer space */
-unsigned comedi_buf_read_alloc(struct comedi_async *async, unsigned nbytes)
-{
- if ((int)(async->buf_read_alloc_count + nbytes - async->munge_count) >
- 0) {
- nbytes = async->munge_count - async->buf_read_alloc_count;
- }
- async->buf_read_alloc_count += nbytes;
- /* barrier insures read of munge_count occurs before we actually read
- data out of buffer */
- smp_rmb();
- return nbytes;
-}
-EXPORT_SYMBOL(comedi_buf_read_alloc);
-
-/* transfers control of a chunk from reader to free buffer space */
-unsigned comedi_buf_read_free(struct comedi_async *async, unsigned int nbytes)
-{
- /* barrier insures data has been read out of
- * buffer before read count is incremented */
- smp_mb();
- if ((int)(async->buf_read_count + nbytes -
- async->buf_read_alloc_count) > 0) {
- dev_info(async->subdevice->device->class_dev,
- "attempted to read-free more bytes than have been read-allocated.\n");
- nbytes = async->buf_read_alloc_count - async->buf_read_count;
+ module_put(driv->module);
}
- async->buf_read_count += nbytes;
- async->buf_read_ptr += nbytes;
- async->buf_read_ptr %= async->prealloc_bufsz;
- return nbytes;
-}
-EXPORT_SYMBOL(comedi_buf_read_free);
-
-void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset,
- const void *data, unsigned int num_bytes)
-{
- unsigned int write_ptr = async->buf_write_ptr + offset;
-
- if (write_ptr >= async->prealloc_bufsz)
- write_ptr %= async->prealloc_bufsz;
-
- while (num_bytes) {
- unsigned int block_size;
-
- if (write_ptr + num_bytes > async->prealloc_bufsz)
- block_size = async->prealloc_bufsz - write_ptr;
- else
- block_size = num_bytes;
-
- memcpy(async->prealloc_buf + write_ptr, data, block_size);
-
- data += block_size;
- num_bytes -= block_size;
-
- write_ptr = 0;
+ if (driv == NULL) {
+ /* recognize has failed if we get here */
+ /* report valid board names before returning error */
+ for (driv = comedi_drivers; driv; driv = driv->next) {
+ if (!try_module_get(driv->module))
+ continue;
+ comedi_report_boards(driv);
+ module_put(driv->module);
+ }
+ return -EIO;
}
-}
-EXPORT_SYMBOL(comedi_buf_memcpy_to);
-
-void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset,
- void *dest, unsigned int nbytes)
-{
- void *src;
- unsigned int read_ptr = async->buf_read_ptr + offset;
-
- if (read_ptr >= async->prealloc_bufsz)
- read_ptr %= async->prealloc_bufsz;
-
- while (nbytes) {
- unsigned int block_size;
-
- src = async->prealloc_buf + read_ptr;
-
- if (nbytes >= async->prealloc_bufsz - read_ptr)
- block_size = async->prealloc_bufsz - read_ptr;
- else
- block_size = nbytes;
-
- memcpy(dest, src, block_size);
- nbytes -= block_size;
- dest += block_size;
- read_ptr = 0;
+ if (driv->attach == NULL) {
+ /* driver does not support manual configuration */
+ dev_warn(dev->class_dev,
+ "driver '%s' does not support attach using comedi_config\n",
+ driv->driver_name);
+ module_put(driv->module);
+ return -ENOSYS;
}
-}
-EXPORT_SYMBOL(comedi_buf_memcpy_from);
-
-unsigned int comedi_buf_read_n_available(struct comedi_async *async)
-{
- unsigned num_bytes;
-
- if (async == NULL)
- return 0;
- num_bytes = async->munge_count - async->buf_read_count;
- /* barrier insures the read of munge_count in this
- query occurs before any following reads of the buffer which
- might be based on the return value from this query.
- */
- smp_rmb();
- return num_bytes;
-}
-EXPORT_SYMBOL(comedi_buf_read_n_available);
-
-int comedi_buf_get(struct comedi_async *async, short *x)
-{
- unsigned int n = comedi_buf_read_n_available(async);
-
- if (n < sizeof(short))
- return 0;
- comedi_buf_read_alloc(async, sizeof(short));
- *x = *(short *)(async->prealloc_buf + async->buf_read_ptr);
- comedi_buf_read_free(async, sizeof(short));
- return 1;
-}
-EXPORT_SYMBOL(comedi_buf_get);
-
-int comedi_buf_put(struct comedi_async *async, short x)
-{
- unsigned int n = comedi_buf_write_alloc_strict(async, sizeof(short));
-
- if (n < sizeof(short)) {
- async->events |= COMEDI_CB_ERROR;
- return 0;
+ /* initialize dev->driver here so
+ * comedi_error() can be called from attach */
+ dev->driver = driv;
+ ret = driv->attach(dev, it);
+ if (ret < 0) {
+ module_put(dev->driver->module);
+ __comedi_device_detach(dev);
+ return ret;
}
- *(short *)(async->prealloc_buf + async->buf_write_ptr) = x;
- comedi_buf_write_free(async, sizeof(short));
- return 1;
-}
-EXPORT_SYMBOL(comedi_buf_put);
-
-void comedi_reset_async_buf(struct comedi_async *async)
-{
- async->buf_write_alloc_count = 0;
- async->buf_write_count = 0;
- async->buf_read_alloc_count = 0;
- async->buf_read_count = 0;
-
- async->buf_write_ptr = 0;
- async->buf_read_ptr = 0;
-
- async->cur_chan = 0;
- async->scan_progress = 0;
- async->munge_chan = 0;
- async->munge_count = 0;
- async->munge_ptr = 0;
-
- async->events = 0;
+ return comedi_device_postconfig(dev);
}
int comedi_auto_config(struct device *hardware_device,
struct comedi_driver *driver, unsigned long context)
{
int minor;
- struct comedi_device_file_info *dev_file_info;
struct comedi_device *comedi_dev;
int ret;
- if (!comedi_autoconfig)
- return 0;
-
if (!driver->auto_attach) {
dev_warn(hardware_device,
"BUG! comedi driver '%s' has no auto_attach handler\n",
@@ -852,8 +420,7 @@ int comedi_auto_config(struct device *hardware_device,
if (minor < 0)
return minor;
- dev_file_info = comedi_get_device_file_info(minor);
- comedi_dev = dev_file_info->device;
+ comedi_dev = comedi_dev_from_minor(minor);
mutex_lock(&comedi_dev->mutex);
if (comedi_dev->attached)
@@ -888,103 +455,53 @@ void comedi_auto_unconfig(struct device *hardware_device)
minor = comedi_find_board_minor(hardware_device);
if (minor < 0)
return;
- BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
comedi_free_board_minor(minor);
}
EXPORT_SYMBOL_GPL(comedi_auto_unconfig);
-/**
- * comedi_pci_enable() - Enable the PCI device and request the regions.
- * @pdev: pci_dev struct
- * @res_name: name for the requested reqource
- */
-int comedi_pci_enable(struct pci_dev *pdev, const char *res_name)
-{
- int rc;
-
- rc = pci_enable_device(pdev);
- if (rc < 0)
- return rc;
-
- rc = pci_request_regions(pdev, res_name);
- if (rc < 0)
- pci_disable_device(pdev);
-
- return rc;
-}
-EXPORT_SYMBOL_GPL(comedi_pci_enable);
-
-/**
- * comedi_pci_disable() - Release the regions and disable the PCI device.
- * @pdev: pci_dev struct
- *
- * This must be matched with a previous successful call to comedi_pci_enable().
- */
-void comedi_pci_disable(struct pci_dev *pdev)
-{
- pci_release_regions(pdev);
- pci_disable_device(pdev);
-}
-EXPORT_SYMBOL_GPL(comedi_pci_disable);
-
-int comedi_pci_driver_register(struct comedi_driver *comedi_driver,
- struct pci_driver *pci_driver)
+int comedi_driver_register(struct comedi_driver *driver)
{
- int ret;
-
- ret = comedi_driver_register(comedi_driver);
- if (ret < 0)
- return ret;
-
- /* FIXME: Remove this test after auditing all comedi pci drivers */
- if (!pci_driver->name)
- pci_driver->name = comedi_driver->driver_name;
-
- ret = pci_register_driver(pci_driver);
- if (ret < 0) {
- comedi_driver_unregister(comedi_driver);
- return ret;
- }
+ driver->next = comedi_drivers;
+ comedi_drivers = driver;
return 0;
}
-EXPORT_SYMBOL_GPL(comedi_pci_driver_register);
+EXPORT_SYMBOL(comedi_driver_register);
-void comedi_pci_driver_unregister(struct comedi_driver *comedi_driver,
- struct pci_driver *pci_driver)
+int comedi_driver_unregister(struct comedi_driver *driver)
{
- pci_unregister_driver(pci_driver);
- comedi_driver_unregister(comedi_driver);
-}
-EXPORT_SYMBOL_GPL(comedi_pci_driver_unregister);
-
-#if IS_ENABLED(CONFIG_USB)
+ struct comedi_driver *prev;
+ int i;
-int comedi_usb_driver_register(struct comedi_driver *comedi_driver,
- struct usb_driver *usb_driver)
-{
- int ret;
+ /* check for devices using this driver */
+ for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
+ struct comedi_device *dev = comedi_dev_from_minor(i);
- ret = comedi_driver_register(comedi_driver);
- if (ret < 0)
- return ret;
+ if (!dev)
+ continue;
- ret = usb_register(usb_driver);
- if (ret < 0) {
- comedi_driver_unregister(comedi_driver);
- return ret;
+ mutex_lock(&dev->mutex);
+ if (dev->attached && dev->driver == driver) {
+ if (dev->use_count)
+ dev_warn(dev->class_dev,
+ "BUG! detaching device with use_count=%d\n",
+ dev->use_count);
+ comedi_device_detach(dev);
+ }
+ mutex_unlock(&dev->mutex);
}
- return 0;
-}
-EXPORT_SYMBOL_GPL(comedi_usb_driver_register);
+ if (comedi_drivers == driver) {
+ comedi_drivers = driver->next;
+ return 0;
+ }
-void comedi_usb_driver_unregister(struct comedi_driver *comedi_driver,
- struct usb_driver *usb_driver)
-{
- usb_deregister(usb_driver);
- comedi_driver_unregister(comedi_driver);
+ for (prev = comedi_drivers; prev->next; prev = prev->next) {
+ if (prev->next == driver) {
+ prev->next = driver->next;
+ return 0;
+ }
+ }
+ return -EINVAL;
}
-EXPORT_SYMBOL_GPL(comedi_usb_driver_unregister);
-
-#endif
+EXPORT_SYMBOL(comedi_driver_unregister);
diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c
index e0a79521f35a..0ae356ae56ea 100644
--- a/drivers/staging/comedi/drivers/8255_pci.c
+++ b/drivers/staging/comedi/drivers/8255_pci.c
@@ -54,6 +54,8 @@ Interrupt support for these boards is also not currently supported.
Configuration Options: not applicable, uses PCI auto config
*/
+#include <linux/pci.h>
+
#include "../comedidev.h"
#include "8255.h"
@@ -314,11 +316,6 @@ static int pci_8255_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &pci_8255_driver);
}
-static void 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) },
@@ -342,7 +339,7 @@ static struct pci_driver pci_8255_pci_driver = {
.name = "8255_pci",
.id_table = pci_8255_pci_table,
.probe = pci_8255_pci_probe,
- .remove = pci_8255_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(pci_8255_driver, pci_8255_pci_driver);
diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile
index 0de4d2eb76fc..315e836ff99b 100644
--- a/drivers/staging/comedi/drivers/Makefile
+++ b/drivers/staging/comedi/drivers/Makefile
@@ -2,7 +2,6 @@
#
# Comedi "helper" modules
-obj-$(CONFIG_COMEDI) += pcm_common.o
# Comedi misc drivers
obj-$(CONFIG_COMEDI_BOND) += comedi_bond.o
@@ -26,6 +25,7 @@ obj-$(CONFIG_COMEDI_PCM3730) += pcm3730.o
obj-$(CONFIG_COMEDI_RTI800) += rti800.o
obj-$(CONFIG_COMEDI_RTI802) += rti802.o
obj-$(CONFIG_COMEDI_DAS16M1) += das16m1.o
+obj-$(CONFIG_COMEDI_DAS08_ISA) += das08_isa.o
obj-$(CONFIG_COMEDI_DAS16) += das16.o
obj-$(CONFIG_COMEDI_DAS800) += das800.o
obj-$(CONFIG_COMEDI_DAS1800) += das1800.o
@@ -56,6 +56,7 @@ obj-$(CONFIG_COMEDI_POC) += poc.o
# Comedi PCI drivers
obj-$(CONFIG_COMEDI_8255_PCI) += 8255_pci.o
+obj-$(CONFIG_COMEDI_ADDI_WATCHDOG) += addi_watchdog.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
@@ -81,6 +82,7 @@ obj-$(CONFIG_COMEDI_AMPLC_PC263) += amplc_pc263.o
obj-$(CONFIG_COMEDI_AMPLC_PCI224) += amplc_pci224.o
obj-$(CONFIG_COMEDI_AMPLC_PCI230) += amplc_pci230.o
obj-$(CONFIG_COMEDI_CONTEC_PCI_DIO) += contec_pci_dio.o
+obj-$(CONFIG_COMEDI_DAS08_PCI) += das08_pci.o
obj-$(CONFIG_COMEDI_DT3000) += dt3000.o
obj-$(CONFIG_COMEDI_DYNA_PCI10XX) += dyna_pci10xx.o
obj-$(CONFIG_COMEDI_UNIOXX5) += unioxx5.o
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
index 90cc43263aee..1051fa5ce8f7 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
@@ -11,13 +11,21 @@ Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
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 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.
+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 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.
+You should also find the complete GPL in the COPYING file accompanying this
+source code.
@endverbatim
*/
@@ -29,10 +37,10 @@ You should also find the complete GPL in the COPYING file accompanying this sour
| 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 DATA | Compiler : GCC |
+ | Project : ADDI DATA | Compiler : GCC |
| Modulname : addi_common.c | Version : 2.96 |
+-------------------------------+---------------------------------------+
- | Author : | Date : |
+ | Author : | Date : |
+-----------------------------------------------------------------------+
| Description : ADDI COMMON Main Module |
+-----------------------------------------------------------------------+
@@ -167,11 +175,11 @@ static int addi_auto_attach(struct comedi_device *dev,
if (this_board->i_PCIEeprom) {
if (!(strcmp(this_board->pc_EepromChip, "S5920"))) {
/* Set 3 wait stait */
- if (!(strcmp(dev->board_name, "apci035"))) {
+ if (!(strcmp(dev->board_name, "apci035")))
outl(0x80808082, devpriv->i_IobaseAmcc + 0x60);
- } else {
+ else
outl(0x83838383, devpriv->i_IobaseAmcc + 0x60);
- }
+
/* Enable the interrupt for the controller */
dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38);
outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
deleted file mode 100644
index 5958a9cb2a38..000000000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+++ /dev/null
@@ -1,807 +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 : API APCI1648 | Compiler : gcc |
- | Module name : TTL.C | Version : 2.96 |
- +-------------------------------+---------------------------------------+
- | Project manager: S. Weber | Date : 25/05/2005 |
- +-----------------------------------------------------------------------+
- | Description : APCI-16XX TTL I/O module |
- | |
- | |
- +-----------------------------------------------------------------------+
- | UPDATES |
- +-----------------------------------------------------------------------+
- | Date | Author | Description of updates |
- +----------+-----------+------------------------------------------------+
- |25.05.2005| S.Weber | Creation |
- | | | |
- +-----------------------------------------------------------------------+
-*/
-
-#ifndef COMEDI_SUBD_TTLIO
-#define COMEDI_SUBD_TTLIO 11 /* Digital Input Output But TTL */
-#endif
-
-#define APCI16XX_TTL_INIT 0
-#define APCI16XX_TTL_INITDIRECTION 1
-#define APCI16XX_TTL_OUTPUTMEMORY 2
-
-#define APCI16XX_TTL_READCHANNEL 0
-#define APCI16XX_TTL_READPORT 1
-
-#define APCI16XX_TTL_WRITECHANNEL_ON 0
-#define APCI16XX_TTL_WRITECHANNEL_OFF 1
-#define APCI16XX_TTL_WRITEPORT_ON 2
-#define APCI16XX_TTL_WRITEPORT_OFF 3
-
-#define APCI16XX_TTL_READ_ALL_INPUTS 0
-#define APCI16XX_TTL_READ_ALL_OUTPUTS 1
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI16XX_InsnConfigInitTTLIO |
-| (struct comedi_device *dev, |
-| struct comedi_subdevice *s, |
-| struct comedi_insn *insn, |
-| unsigned int *data) |
-+----------------------------------------------------------------------------+
-| Task APCI16XX_TTL_INIT (using defaults) : |
-| Configure the TTL I/O operating mode from all ports |
-| You must calling this function be |
-| for you call any other function witch access of TTL. |
-| APCI16XX_TTL_INITDIRECTION(user inputs for direction) |
-+----------------------------------------------------------------------------+
-| Input Parameters : b_InitType = (unsigned char) data[0]; |
-| b_Port0Mode = (unsigned char) data[1]; |
-| b_Port1Mode = (unsigned char) data[2]; |
-| b_Port2Mode = (unsigned char) data[3]; |
-| b_Port3Mode = (unsigned char) data[4]; |
-| ........ |
-+----------------------------------------------------------------------------+
-| Output Parameters : - |
-+----------------------------------------------------------------------------+
-| Return Value :>0: No error |
-| -1: Port 0 mode selection is wrong |
-| -2: Port 1 mode selection is wrong |
-| -3: Port 2 mode selection is wrong |
-| -4: Port 3 mode selection is wrong |
-| -X: Port X-1 mode selection is wrong |
-| .... |
-| -100 : Config command error |
-| -101 : Data size error |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- const struct addi_board *this_board = comedi_board(dev);
- struct addi_private *devpriv = dev->private;
- int i_ReturnValue = insn->n;
- unsigned char b_Command = 0;
- unsigned char b_Cpt = 0;
- unsigned char b_NumberOfPort =
- (unsigned char) (this_board->i_NbrTTLChannel / 8);
-
- /************************/
- /* Test the buffer size */
- /************************/
-
- if (insn->n >= 1) {
- /*******************/
- /* Get the command */
- /* **************** */
-
- b_Command = (unsigned char) data[0];
-
- /********************/
- /* Test the command */
- /********************/
-
- if ((b_Command == APCI16XX_TTL_INIT) ||
- (b_Command == APCI16XX_TTL_INITDIRECTION) ||
- (b_Command == APCI16XX_TTL_OUTPUTMEMORY)) {
- /***************************************/
- /* Test the initialisation buffer size */
- /***************************************/
-
- if ((b_Command == APCI16XX_TTL_INITDIRECTION)
- && ((unsigned char) (insn->n - 1) != b_NumberOfPort)) {
- /*******************/
- /* Data size error */
- /*******************/
-
- printk("\nBuffer size error");
- i_ReturnValue = -101;
- }
-
- if ((b_Command == APCI16XX_TTL_OUTPUTMEMORY)
- && ((unsigned char) (insn->n) != 2)) {
- /*******************/
- /* Data size error */
- /*******************/
-
- printk("\nBuffer size error");
- i_ReturnValue = -101;
- }
- } else {
- /************************/
- /* Config command error */
- /************************/
-
- printk("\nCommand selection error");
- i_ReturnValue = -100;
- }
- } else {
- /*******************/
- /* Data size error */
- /*******************/
-
- printk("\nBuffer size error");
- i_ReturnValue = -101;
- }
-
- /**************************************************************************/
- /* Test if no error occur and APCI16XX_TTL_INITDIRECTION command selected */
- /**************************************************************************/
-
- if ((i_ReturnValue >= 0) && (b_Command == APCI16XX_TTL_INITDIRECTION)) {
- memset(devpriv->ul_TTLPortConfiguration, 0,
- sizeof(devpriv->ul_TTLPortConfiguration));
-
- /*************************************/
- /* Test the port direction selection */
- /*************************************/
-
- for (b_Cpt = 1;
- (b_Cpt <= b_NumberOfPort) && (i_ReturnValue >= 0);
- b_Cpt++) {
- /**********************/
- /* Test the direction */
- /**********************/
-
- if ((data[b_Cpt] != 0) && (data[b_Cpt] != 0xFF)) {
- /************************/
- /* Port direction error */
- /************************/
-
- printk("\nPort %d direction selection error",
- (int) b_Cpt);
- i_ReturnValue = -(int) b_Cpt;
- }
-
- /**************************/
- /* Save the configuration */
- /**************************/
-
- devpriv->ul_TTLPortConfiguration[(b_Cpt - 1) / 4] =
- devpriv->ul_TTLPortConfiguration[(b_Cpt -
- 1) / 4] | (data[b_Cpt] << (8 * ((b_Cpt -
- 1) % 4)));
- }
- }
-
- /**************************/
- /* Test if no error occur */
- /**************************/
-
- if (i_ReturnValue >= 0) {
- /***********************************/
- /* Test if TTL port initilaisation */
- /***********************************/
-
- if ((b_Command == APCI16XX_TTL_INIT)
- || (b_Command == APCI16XX_TTL_INITDIRECTION)) {
- /******************************/
- /* Set all port configuration */
- /******************************/
-
- for (b_Cpt = 0; b_Cpt <= b_NumberOfPort; b_Cpt++) {
- if ((b_Cpt % 4) == 0) {
- /*************************/
- /* Set the configuration */
- /*************************/
-
- outl(devpriv->
- ul_TTLPortConfiguration[b_Cpt /
- 4],
- devpriv->iobase + 32 + b_Cpt);
- }
- }
- }
- }
-
- /************************************************/
- /* Test if output memory initialisation command */
- /************************************************/
-
- if (b_Command == APCI16XX_TTL_OUTPUTMEMORY) {
- if (data[1]) {
- devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
- } else {
- devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
- }
- }
-
- return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| INPUT FUNCTIONS |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI16XX_InsnBitsReadTTLIO |
-| (struct comedi_device *dev, |
-| struct comedi_subdevice *s, |
-| struct comedi_insn *insn, |
-| unsigned int *data) |
-+----------------------------------------------------------------------------+
-| Task : Read the status from selected TTL digital input |
-| (b_InputChannel) |
-+----------------------------------------------------------------------------+
-| Task : Read the status from digital input port |
-| (b_SelectedPort) |
-+----------------------------------------------------------------------------+
-| Input Parameters : |
-| APCI16XX_TTL_READCHANNEL |
-| b_SelectedPort= CR_RANGE(insn->chanspec); |
-| b_InputChannel= CR_CHAN(insn->chanspec); |
-| b_ReadType = (unsigned char) data[0]; |
-| |
-| APCI16XX_TTL_READPORT |
-| b_SelectedPort= CR_RANGE(insn->chanspec); |
-| b_ReadType = (unsigned char) data[0]; |
-+----------------------------------------------------------------------------+
-| Output Parameters : data[0] 0 : Channle is not active |
-| 1 : Channle is active |
-+----------------------------------------------------------------------------+
-| Return Value : >0 : No error |
-| -100 : Config command error |
-| -101 : Data size error |
-| -102 : The selected TTL input port is wrong |
-| -103 : The selected TTL digital input is wrong |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- const struct addi_board *this_board = comedi_board(dev);
- struct addi_private *devpriv = dev->private;
- int i_ReturnValue = insn->n;
- unsigned char b_Command = 0;
- unsigned char b_NumberOfPort =
- (unsigned char) (this_board->i_NbrTTLChannel / 8);
- unsigned char b_SelectedPort = CR_RANGE(insn->chanspec);
- unsigned char b_InputChannel = CR_CHAN(insn->chanspec);
- unsigned char *pb_Status;
- unsigned int dw_Status;
-
- /************************/
- /* Test the buffer size */
- /************************/
-
- if (insn->n >= 1) {
- /*******************/
- /* Get the command */
- /* **************** */
-
- b_Command = (unsigned char) data[0];
-
- /********************/
- /* Test the command */
- /********************/
-
- if ((b_Command == APCI16XX_TTL_READCHANNEL)
- || (b_Command == APCI16XX_TTL_READPORT)) {
- /**************************/
- /* Test the selected port */
- /**************************/
-
- if (b_SelectedPort < b_NumberOfPort) {
- /**********************/
- /* Test if input port */
- /**********************/
-
- if (((devpriv->ul_TTLPortConfiguration
- [b_SelectedPort /
- 4] >> (8 *
- (b_SelectedPort
- %
- 4))) &
- 0xFF) == 0) {
- /***************************/
- /* Test the channel number */
- /***************************/
-
- if ((b_Command ==
- APCI16XX_TTL_READCHANNEL)
- && (b_InputChannel > 7)) {
- /*******************************************/
- /* The selected TTL digital input is wrong */
- /*******************************************/
-
- printk("\nChannel selection error");
- i_ReturnValue = -103;
- }
- } else {
- /****************************************/
- /* The selected TTL input port is wrong */
- /****************************************/
-
- printk("\nPort selection error");
- i_ReturnValue = -102;
- }
- } else {
- /****************************************/
- /* The selected TTL input port is wrong */
- /****************************************/
-
- printk("\nPort selection error");
- i_ReturnValue = -102;
- }
- } else {
- /************************/
- /* Config command error */
- /************************/
-
- printk("\nCommand selection error");
- i_ReturnValue = -100;
- }
- } else {
- /*******************/
- /* Data size error */
- /*******************/
-
- printk("\nBuffer size error");
- i_ReturnValue = -101;
- }
-
- /**************************/
- /* Test if no error occur */
- /**************************/
-
- if (i_ReturnValue >= 0) {
- pb_Status = (unsigned char *) &data[0];
-
- /*******************************/
- /* Get the digital inpu status */
- /*******************************/
-
- dw_Status =
- inl(devpriv->iobase + 8 + ((b_SelectedPort / 4) * 4));
- dw_Status = (dw_Status >> (8 * (b_SelectedPort % 4))) & 0xFF;
-
- /***********************/
- /* Save the port value */
- /***********************/
-
- *pb_Status = (unsigned char) dw_Status;
-
- /***************************************/
- /* Test if read channel status command */
- /***************************************/
-
- if (b_Command == APCI16XX_TTL_READCHANNEL) {
- *pb_Status = (*pb_Status >> b_InputChannel) & 1;
- }
- }
-
- return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI16XX_InsnReadTTLIOAllPortValue |
-| (struct comedi_device *dev, |
-| struct comedi_subdevice *s, |
-| struct comedi_insn *insn, |
-| unsigned int *data) |
-+----------------------------------------------------------------------------+
-| Task : Read the status from all digital input ports |
-+----------------------------------------------------------------------------+
-| Input Parameters : - |
-+----------------------------------------------------------------------------+
-| Output Parameters : data[0] : Port 0 to 3 data |
-| data[1] : Port 4 to 7 data |
-| .... |
-+----------------------------------------------------------------------------+
-| Return Value : 0: No error |
-| -100 : Read command error |
-| -101 : Data size error |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- const struct addi_board *this_board = comedi_board(dev);
- struct addi_private *devpriv = dev->private;
- unsigned char b_Command = (unsigned char) CR_AREF(insn->chanspec);
- int i_ReturnValue = insn->n;
- unsigned char b_Cpt = 0;
- unsigned char b_NumberOfPort = 0;
- unsigned int *pls_ReadData = data;
-
- /********************/
- /* Test the command */
- /********************/
-
- if ((b_Command == APCI16XX_TTL_READ_ALL_INPUTS)
- || (b_Command == APCI16XX_TTL_READ_ALL_OUTPUTS)) {
- /**********************************/
- /* Get the number of 32-Bit ports */
- /**********************************/
-
- b_NumberOfPort =
- (unsigned char) (this_board->i_NbrTTLChannel / 32);
- if ((b_NumberOfPort * 32) <
- this_board->i_NbrTTLChannel) {
- b_NumberOfPort = b_NumberOfPort + 1;
- }
-
- /************************/
- /* Test the buffer size */
- /************************/
-
- if (insn->n >= b_NumberOfPort) {
- if (b_Command == APCI16XX_TTL_READ_ALL_INPUTS) {
- /**************************/
- /* Read all digital input */
- /**************************/
-
- for (b_Cpt = 0; b_Cpt < b_NumberOfPort; b_Cpt++) {
- /************************/
- /* Read the 32-Bit port */
- /************************/
-
- pls_ReadData[b_Cpt] =
- inl(devpriv->iobase + 8 +
- (b_Cpt * 4));
-
- /**************************************/
- /* Mask all channels used als outputs */
- /**************************************/
-
- pls_ReadData[b_Cpt] =
- pls_ReadData[b_Cpt] &
- (~devpriv->
- ul_TTLPortConfiguration[b_Cpt]);
- }
- } else {
- /****************************/
- /* Read all digital outputs */
- /****************************/
-
- for (b_Cpt = 0; b_Cpt < b_NumberOfPort; b_Cpt++) {
- /************************/
- /* Read the 32-Bit port */
- /************************/
-
- pls_ReadData[b_Cpt] =
- inl(devpriv->iobase + 20 +
- (b_Cpt * 4));
-
- /**************************************/
- /* Mask all channels used als outputs */
- /**************************************/
-
- pls_ReadData[b_Cpt] =
- pls_ReadData[b_Cpt] & devpriv->
- ul_TTLPortConfiguration[b_Cpt];
- }
- }
- } else {
- /*******************/
- /* Data size error */
- /*******************/
-
- printk("\nBuffer size error");
- i_ReturnValue = -101;
- }
- } else {
- /*****************/
- /* Command error */
- /*****************/
-
- printk("\nCommand selection error");
- i_ReturnValue = -100;
- }
-
- return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| OUTPUT FUNCTIONS |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI16XX_InsnBitsWriteTTLIO |
-| (struct comedi_device *dev, |
-| struct comedi_subdevice *s, |
-| struct comedi_insn *insn, |
-| unsigned int *data) |
-+----------------------------------------------------------------------------+
-| Task : Set the state from selected TTL digital output |
-| (b_OutputChannel) |
-+----------------------------------------------------------------------------+
-| Task : Set the state from digital output port |
-| (b_SelectedPort) |
-+----------------------------------------------------------------------------+
-| Input Parameters : |
-| APCI16XX_TTL_WRITECHANNEL_ON | APCI16XX_TTL_WRITECHANNEL_OFF |
-| b_SelectedPort = CR_RANGE(insn->chanspec); |
-| b_OutputChannel= CR_CHAN(insn->chanspec); |
-| b_Command = (unsigned char) data[0]; |
-| |
-| APCI16XX_TTL_WRITEPORT_ON | APCI16XX_TTL_WRITEPORT_OFF |
-| b_SelectedPort = CR_RANGE(insn->chanspec); |
-| b_Command = (unsigned char) data[0]; |
-+----------------------------------------------------------------------------+
-| Output Parameters : data[0] : TTL output port 0 to 3 data |
-| data[1] : TTL output port 4 to 7 data |
-| .... |
-+----------------------------------------------------------------------------+
-| Return Value : >0 : No error |
-| -100 : Command error |
-| -101 : Data size error |
-| -102 : The selected TTL output port is wrong |
-| -103 : The selected TTL digital output is wrong |
-| -104 : Output memory disabled |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- const struct addi_board *this_board = comedi_board(dev);
- struct addi_private *devpriv = dev->private;
- int i_ReturnValue = insn->n;
- unsigned char b_Command = 0;
- unsigned char b_NumberOfPort =
- (unsigned char) (this_board->i_NbrTTLChannel / 8);
- unsigned char b_SelectedPort = CR_RANGE(insn->chanspec);
- unsigned char b_OutputChannel = CR_CHAN(insn->chanspec);
- unsigned int dw_Status = 0;
-
- /************************/
- /* Test the buffer size */
- /************************/
-
- if (insn->n >= 1) {
- /*******************/
- /* Get the command */
- /* **************** */
-
- b_Command = (unsigned char) data[0];
-
- /********************/
- /* Test the command */
- /********************/
-
- if ((b_Command == APCI16XX_TTL_WRITECHANNEL_ON) ||
- (b_Command == APCI16XX_TTL_WRITEPORT_ON) ||
- (b_Command == APCI16XX_TTL_WRITECHANNEL_OFF) ||
- (b_Command == APCI16XX_TTL_WRITEPORT_OFF)) {
- /**************************/
- /* Test the selected port */
- /**************************/
-
- if (b_SelectedPort < b_NumberOfPort) {
- /***********************/
- /* Test if output port */
- /***********************/
-
- if (((devpriv->ul_TTLPortConfiguration
- [b_SelectedPort /
- 4] >> (8 *
- (b_SelectedPort
- %
- 4))) &
- 0xFF) == 0xFF) {
- /***************************/
- /* Test the channel number */
- /***************************/
-
- if (((b_Command == APCI16XX_TTL_WRITECHANNEL_ON) || (b_Command == APCI16XX_TTL_WRITECHANNEL_OFF)) && (b_OutputChannel > 7)) {
- /********************************************/
- /* The selected TTL digital output is wrong */
- /********************************************/
-
- printk("\nChannel selection error");
- i_ReturnValue = -103;
- }
-
- if (((b_Command == APCI16XX_TTL_WRITECHANNEL_OFF) || (b_Command == APCI16XX_TTL_WRITEPORT_OFF)) && (devpriv->b_OutputMemoryStatus == ADDIDATA_DISABLE)) {
- /********************************************/
- /* The selected TTL digital output is wrong */
- /********************************************/
-
- printk("\nOutput memory disabled");
- i_ReturnValue = -104;
- }
-
- /************************/
- /* Test the buffer size */
- /************************/
-
- if (((b_Command == APCI16XX_TTL_WRITEPORT_ON) || (b_Command == APCI16XX_TTL_WRITEPORT_OFF)) && (insn->n < 2)) {
- /*******************/
- /* Data size error */
- /*******************/
-
- printk("\nBuffer size error");
- i_ReturnValue = -101;
- }
- } else {
- /*****************************************/
- /* The selected TTL output port is wrong */
- /*****************************************/
-
- printk("\nPort selection error %lX",
- (unsigned long)devpriv->
- ul_TTLPortConfiguration[0]);
- i_ReturnValue = -102;
- }
- } else {
- /****************************************/
- /* The selected TTL output port is wrong */
- /****************************************/
-
- printk("\nPort selection error %d %d",
- b_SelectedPort, b_NumberOfPort);
- i_ReturnValue = -102;
- }
- } else {
- /************************/
- /* Config command error */
- /************************/
-
- printk("\nCommand selection error");
- i_ReturnValue = -100;
- }
- } else {
- /*******************/
- /* Data size error */
- /*******************/
-
- printk("\nBuffer size error");
- i_ReturnValue = -101;
- }
-
- /**************************/
- /* Test if no error occur */
- /**************************/
-
- if (i_ReturnValue >= 0) {
- /********************************/
- /* Get the digital output state */
- /********************************/
-
- dw_Status =
- inl(devpriv->iobase + 20 + ((b_SelectedPort / 4) * 4));
-
- /**********************************/
- /* Test if output memory not used */
- /**********************************/
-
- if (devpriv->b_OutputMemoryStatus == ADDIDATA_DISABLE) {
- /*********************************/
- /* Clear the selected port value */
- /*********************************/
-
- dw_Status =
- dw_Status & (0xFFFFFFFFUL -
- (0xFFUL << (8 * (b_SelectedPort % 4))));
- }
-
- /******************************/
- /* Test if setting channel ON */
- /******************************/
-
- if (b_Command == APCI16XX_TTL_WRITECHANNEL_ON) {
- dw_Status =
- dw_Status | (1UL << ((8 * (b_SelectedPort %
- 4)) + b_OutputChannel));
- }
-
- /***************************/
- /* Test if setting port ON */
- /***************************/
-
- if (b_Command == APCI16XX_TTL_WRITEPORT_ON) {
- dw_Status =
- dw_Status | ((data[1] & 0xFF) << (8 *
- (b_SelectedPort % 4)));
- }
-
- /*******************************/
- /* Test if setting channel OFF */
- /*******************************/
-
- if (b_Command == APCI16XX_TTL_WRITECHANNEL_OFF) {
- dw_Status =
- dw_Status & (0xFFFFFFFFUL -
- (1UL << ((8 * (b_SelectedPort % 4)) +
- b_OutputChannel)));
- }
-
- /****************************/
- /* Test if setting port OFF */
- /****************************/
-
- if (b_Command == APCI16XX_TTL_WRITEPORT_OFF) {
- dw_Status =
- dw_Status & (0xFFFFFFFFUL -
- ((data[1] & 0xFF) << (8 * (b_SelectedPort %
- 4))));
- }
-
- outl(dw_Status,
- devpriv->iobase + 20 + ((b_SelectedPort / 4) * 4));
- }
-
- return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI2200_Reset(struct comedi_device *dev) | +----------------------------------------------------------------------------+
-| Task :resets all the registers |
-+----------------------------------------------------------------------------+
-| Input Parameters : struct comedi_device *dev |
-+----------------------------------------------------------------------------+
-| Output Parameters : - |
-+----------------------------------------------------------------------------+
-| Return Value : - |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI16XX_Reset(struct comedi_device *dev)
-{
- return 0;
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
deleted file mode 100644
index 9d4a117aad43..000000000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+++ /dev/null
@@ -1,263 +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 : APCI-2200 | Compiler : GCC |
- | Module name : hwdrv_apci2200.c| Version : 2.96 |
- +-------------------------------+---------------------------------------+
- | Project manager: Eric Stolz | Date : 02/12/2002 |
- +-------------------------------+---------------------------------------+
- | Description : Hardware Layer Access For APCI-2200 |
- +-----------------------------------------------------------------------+
- | UPDATES |
- +----------+-----------+------------------------------------------------+
- | Date | Author | Description of updates |
- +----------+-----------+------------------------------------------------+
- | | | |
- | | | |
- | | | |
- +----------+-----------+------------------------------------------------+
-*/
-
-/********* Definitions for APCI-2200 card *****/
-
-/* Card Specific information */
-#define APCI2200_ADDRESS_RANGE 64
-
-/* DIGITAL INPUT-OUTPUT DEFINE */
-
-#define APCI2200_DIGITAL_OP 4
-#define APCI2200_DIGITAL_IP 0
-
-/* TIMER COUNTER WATCHDOG DEFINES */
-
-#define APCI2200_WATCHDOG 0x08
-#define APCI2200_WATCHDOG_ENABLEDISABLE 12
-#define APCI2200_WATCHDOG_RELOAD_VALUE 4
-#define APCI2200_WATCHDOG_STATUS 16
-
-static int apci2200_di_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
-
- data[1] = inw(devpriv->iobase + APCI2200_DIGITAL_IP);
-
- return insn->n;
-}
-
-static int apci2200_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int mask = data[0];
- unsigned int bits = data[1];
-
- s->state = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
-
- outw(s->state, devpriv->iobase + APCI2200_DIGITAL_OP);
- }
-
- data[1] = s->state;
-
- return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI2200_ConfigWatchdog(struct comedi_device *dev,
-| struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) |
-| |
-+----------------------------------------------------------------------------+
-| Task : Configures The Watchdog |
-+----------------------------------------------------------------------------+
-| Input Parameters : struct comedi_device *dev : Driver handle |
-| struct comedi_subdevice *s, :pointer to subdevice structure
-| struct comedi_insn *insn :pointer to insn structure |
-| unsigned int *data : Data Pointer to read status |
-+----------------------------------------------------------------------------+
-| Output Parameters : -- |
-+----------------------------------------------------------------------------+
-| Return Value : TRUE : No error occur |
-| : FALSE : Error occur. Return the error |
-| |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI2200_ConfigWatchdog(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
-
- if (data[0] == 0) {
- /* Disable the watchdog */
- outw(0x0,
- devpriv->iobase + APCI2200_WATCHDOG +
- APCI2200_WATCHDOG_ENABLEDISABLE);
- /* Loading the Reload value */
- outw(data[1],
- devpriv->iobase + APCI2200_WATCHDOG +
- APCI2200_WATCHDOG_RELOAD_VALUE);
- data[1] = data[1] >> 16;
- outw(data[1],
- devpriv->iobase + APCI2200_WATCHDOG +
- APCI2200_WATCHDOG_RELOAD_VALUE + 2);
- } /* if(data[0]==0) */
- else {
- printk("\nThe input parameters are wrong\n");
- return -EINVAL;
- } /* elseif(data[0]==0) */
-
- return insn->n;
-}
-
- /*
- +----------------------------------------------------------------------------+
- | Function Name : int i_APCI2200_StartStopWriteWatchdog |
- | (struct comedi_device *dev,struct comedi_subdevice *s,
- struct comedi_insn *insn,unsigned int *data); |
- +----------------------------------------------------------------------------+
- | Task : Start / Stop The Watchdog |
- +----------------------------------------------------------------------------+
- | Input Parameters : struct comedi_device *dev : Driver handle |
- | struct comedi_subdevice *s, :pointer to subdevice structure
- struct comedi_insn *insn :pointer to insn structure |
- | unsigned int *data : Data Pointer to read status |
- +----------------------------------------------------------------------------+
- | Output Parameters : -- |
- +----------------------------------------------------------------------------+
- | Return Value : TRUE : No error occur |
- | : FALSE : Error occur. Return the error |
- | |
- +----------------------------------------------------------------------------+
- */
-
-static int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
-
- switch (data[0]) {
- case 0: /* stop the watchdog */
- outw(0x0, devpriv->iobase + APCI2200_WATCHDOG + APCI2200_WATCHDOG_ENABLEDISABLE); /* disable the watchdog */
- break;
- case 1: /* start the watchdog */
- outw(0x0001,
- devpriv->iobase + APCI2200_WATCHDOG +
- APCI2200_WATCHDOG_ENABLEDISABLE);
- break;
- case 2: /* Software trigger */
- outw(0x0201,
- devpriv->iobase + APCI2200_WATCHDOG +
- APCI2200_WATCHDOG_ENABLEDISABLE);
- break;
- default:
- printk("\nSpecified functionality does not exist\n");
- return -EINVAL;
- } /* switch(data[0]) */
- return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI2200_ReadWatchdog |
-| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
-| unsigned int *data); |
-+----------------------------------------------------------------------------+
-| Task : Read The Watchdog |
-+----------------------------------------------------------------------------+
-| Input Parameters : struct comedi_device *dev : Driver handle |
-| struct comedi_subdevice *s, :pointer to subdevice structure
-| struct comedi_insn *insn :pointer to insn structure |
-| unsigned int *data : Data Pointer to read status |
-+----------------------------------------------------------------------------+
-| Output Parameters : -- |
-+----------------------------------------------------------------------------+
-| Return Value : TRUE : No error occur |
-| : FALSE : Error occur. Return the error |
-| |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI2200_ReadWatchdog(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
-
- data[0] =
- inw(devpriv->iobase + APCI2200_WATCHDOG +
- APCI2200_WATCHDOG_STATUS) & 0x1;
- return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI2200_Reset(struct comedi_device *dev) | |
-+----------------------------------------------------------------------------+
-| Task :resets all the registers |
-+----------------------------------------------------------------------------+
-| Input Parameters : struct comedi_device *dev
-+----------------------------------------------------------------------------+
-| Output Parameters : -- |
-+----------------------------------------------------------------------------+
-| Return Value : |
-| |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI2200_Reset(struct comedi_device *dev)
-{
- struct addi_private *devpriv = dev->private;
-
- outw(0x0, devpriv->iobase + APCI2200_DIGITAL_OP); /* RESETS THE DIGITAL OUTPUTS */
- outw(0x0,
- devpriv->iobase + APCI2200_WATCHDOG +
- APCI2200_WATCHDOG_ENABLEDISABLE);
- outw(0x0,
- devpriv->iobase + APCI2200_WATCHDOG +
- APCI2200_WATCHDOG_RELOAD_VALUE);
- outw(0x0,
- devpriv->iobase + APCI2200_WATCHDOG +
- APCI2200_WATCHDOG_RELOAD_VALUE + 2);
- return 0;
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
index 829af187b249..c7908730caa5 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
@@ -633,7 +633,7 @@ static int apci3200_do_insn_bits(struct comedi_device *dev,
s->state = inl(devpriv->i_IobaseAddon) & 0xf;
if (mask) {
s->state &= ~mask;
- s->state |= (bits & mask)
+ s->state |= (bits & mask);
outl(s->state, devpriv->i_IobaseAddon);
}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
index 7a18ce704ba4..ebc1534a8df8 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
@@ -1,274 +1,27 @@
-/**
-@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 : APCI-3501 | Compiler : GCC |
- | Module name : hwdrv_apci3501.c| Version : 2.96 |
- +-------------------------------+---------------------------------------+
- | Project manager: Eric Stolz | Date : 02/12/2002 |
- +-------------------------------+---------------------------------------+
- | Description : Hardware Layer Access For APCI-3501 |
- +-----------------------------------------------------------------------+
- | UPDATES |
- +----------+-----------+------------------------------------------------+
- | Date | Author | Description of updates |
- +----------+-----------+------------------------------------------------+
- | | | |
- | | | |
- | | | |
- +----------+-----------+------------------------------------------------+
-*/
-
-/* Card Specific information */
-#define APCI3501_ADDRESS_RANGE 255
-
-#define APCI3501_DIGITAL_IP 0x50
-#define APCI3501_DIGITAL_OP 0x40
-#define APCI3501_ANALOG_OUTPUT 0x00
-
-/* Analog Output related Defines */
-#define APCI3501_AO_VOLT_MODE 0
-#define APCI3501_AO_PROG 4
-#define APCI3501_AO_TRIG_SCS 8
-#define UNIPOLAR 0
-#define BIPOLAR 1
-#define MODE0 0
-#define MODE1 1
-
/* Watchdog Related Defines */
-#define APCI3501_WATCHDOG 0x20
-#define APCI3501_TCW_SYNC_ENABLEDISABLE 0
-#define APCI3501_TCW_RELOAD_VALUE 4
-#define APCI3501_TCW_TIMEBASE 8
-#define APCI3501_TCW_PROG 12
-#define APCI3501_TCW_TRIG_STATUS 16
-#define APCI3501_TCW_IRQ 20
-#define APCI3501_TCW_WARN_TIMEVAL 24
-#define APCI3501_TCW_WARN_TIMEBASE 28
#define ADDIDATA_TIMER 0
#define ADDIDATA_WATCHDOG 2
-/* ANALOG OUTPUT RANGE */
-static struct comedi_lrange range_apci3501_ao = {
- 2, {
- BIP_RANGE(10),
- UNI_RANGE(10)
- }
-};
-
-static int apci3501_di_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
-
- data[1] = inl(devpriv->iobase + APCI3501_DIGITAL_IP) & 0x3;
-
- return insn->n;
-}
-
-static int apci3501_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int mask = data[0];
- unsigned int bits = data[1];
-
- s->state = inl(devpriv->iobase + APCI3501_DIGITAL_OP);
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
-
- outl(s->state, devpriv->iobase + APCI3501_DIGITAL_OP);
- }
-
- data[1] = s->state;
-
- return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI3501_ConfigAnalogOutput |
-| (struct comedi_device *dev,struct comedi_subdevice *s, |
-| struct comedi_insn *insn,unsigned int *data) |
-+----------------------------------------------------------------------------+
-| Task : Configures The Analog Output Subdevice |
-+----------------------------------------------------------------------------+
-| Input Parameters : struct comedi_device *dev : Driver handle |
-| struct comedi_subdevice *s : Subdevice Pointer |
-| struct comedi_insn *insn : Insn Structure Pointer |
-| unsigned int *data : Data Pointer contains |
-| configuration parameters as below |
-| |
-| data[0] : Voltage Mode |
-| 0:Mode 0 |
-| 1:Mode 1 |
-| |
-+----------------------------------------------------------------------------+
-| Output Parameters : -- |
-+----------------------------------------------------------------------------+
-| Return Value : TRUE : No error occur |
-| : FALSE : Error occur. Return the error |
-| |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
-
- outl(data[0],
- devpriv->iobase + APCI3501_ANALOG_OUTPUT +
- APCI3501_AO_VOLT_MODE);
-
- if (data[0]) {
- devpriv->b_InterruptMode = MODE1;
- } else {
- devpriv->b_InterruptMode = MODE0;
- }
- return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI3501_WriteAnalogOutput |
-| (struct comedi_device *dev,struct comedi_subdevice *s, |
-| struct comedi_insn *insn,unsigned int *data) |
-+----------------------------------------------------------------------------+
-| Task : Writes To the Selected Anlog Output Channel |
-+----------------------------------------------------------------------------+
-| Input Parameters : struct comedi_device *dev : Driver handle |
-| struct comedi_subdevice *s : Subdevice Pointer |
-| struct comedi_insn *insn : Insn Structure Pointer |
-| unsigned int *data : Data Pointer contains |
-| configuration parameters as below |
-| |
-| |
-+----------------------------------------------------------------------------+
-| Output Parameters : -- |
-+----------------------------------------------------------------------------+
-| Return Value : TRUE : No error occur |
-| : FALSE : Error occur. Return the error |
-| |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI3501_WriteAnalogOutput(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int ul_Command1 = 0, ul_Channel_no, ul_Polarity, ul_DAC_Ready = 0;
-
- ul_Channel_no = CR_CHAN(insn->chanspec);
-
- if (devpriv->b_InterruptMode == MODE1) {
- ul_Polarity = 0x80000000;
- if ((*data < 0) || (*data > 16384)) {
- printk("\nIn WriteAnalogOutput :: Not Valid Data\n");
- }
-
- } /* end if(devpriv->b_InterruptMode==MODE1) */
- else {
- ul_Polarity = 0;
- if ((*data < 0) || (*data > 8192)) {
- printk("\nIn WriteAnalogOutput :: Not Valid Data\n");
- }
-
- } /* end else */
-
- if ((ul_Channel_no < 0) || (ul_Channel_no > 7)) {
- printk("\nIn WriteAnalogOutput :: Not Valid Channel\n");
- } /* end if((ul_Channel_no<0)||(ul_Channel_no>7)) */
-
- ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
-
- while (ul_DAC_Ready == 0) {
- ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
- ul_DAC_Ready = (ul_DAC_Ready >> 8) & 1;
- }
-
- if (ul_DAC_Ready) {
-/* Output the Value on the output channels. */
- ul_Command1 =
- (unsigned int) ((unsigned int) (ul_Channel_no & 0xFF) |
- (unsigned int) ((*data << 0x8) & 0x7FFFFF00L) |
- (unsigned int) (ul_Polarity));
- outl(ul_Command1,
- devpriv->iobase + APCI3501_ANALOG_OUTPUT +
- APCI3501_AO_PROG);
- }
-
- return insn->n;
-}
-
/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI3501_ConfigTimerCounterWatchdog |
-| (struct comedi_device *dev,struct comedi_subdevice *s, |
-| struct comedi_insn *insn,unsigned int *data) |
-+----------------------------------------------------------------------------+
-| Task : Configures The Timer , Counter or Watchdog |
-+----------------------------------------------------------------------------+
-| Input Parameters : struct comedi_device *dev : Driver handle |
-| unsigned int *data : Data Pointer contains |
-| configuration parameters as below |
-| |
-| data[0] : 0 Configure As Timer |
-| 1 Configure As Counter |
-| 2 Configure As Watchdog |
-| data[1] : 1 Enable Interrupt |
-| 0 Disable Interrupt |
-| data[2] : Time Unit |
-| data[3] : Reload Value |
-+----------------------------------------------------------------------------+
-| Output Parameters : -- |
-+----------------------------------------------------------------------------+
-| Return Value : TRUE : No error occur |
-| : FALSE : Error occur. Return the error |
-| |
-+----------------------------------------------------------------------------+
-*/
+ * (*insn_config) for the timer subdevice
+ *
+ * Configures The Timer, Counter or Watchdog
+ * Data Pointer contains configuration parameters as below
+ * data[0] : 0 Configure As Timer
+ * 1 Configure As Counter
+ * 2 Configure As Watchdog
+ * data[1] : 1 Enable Interrupt
+ * 0 Disable Interrupt
+ * data[2] : Time Unit
+ * data[3] : Reload Value
+ */
static int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
- struct addi_private *devpriv = dev->private;
+ struct apci3501_private *devpriv = dev->private;
unsigned int ul_Command1 = 0;
devpriv->tsk_Current = current;
@@ -276,224 +29,146 @@ static int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev,
devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
/* Disable the watchdog */
- outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); /* disable Wa */
+ outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
if (data[1] == 1) {
/* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
- outl(0x02,
- devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_PROG);
+ outl(0x02, dev->iobase + APCI3501_TIMER_CTRL_REG);
} else {
- outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); /* disable Timer interrupt */
+ /* disable Timer interrupt */
+ outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
}
- /* Loading the Timebase value */
- outl(data[2],
- devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_TIMEBASE);
+ outl(data[2], dev->iobase + APCI3501_TIMER_TIMEBASE_REG);
+ outl(data[3], dev->iobase + APCI3501_TIMER_RELOAD_REG);
- /* Loading the Reload value */
- outl(data[3],
- devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_RELOAD_VALUE);
- /* Set the mode */
- ul_Command1 = inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG) | 0xFFF819E0UL; /* e2->e0 */
- outl(ul_Command1,
- devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_PROG);
- } /* end if(data[0]==ADDIDATA_WATCHDOG) */
+ /* Set the mode (e2->e0) */
+ ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG) | 0xFFF819E0UL;
+ outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+ }
else if (data[0] == ADDIDATA_TIMER) {
/* First Stop The Timer */
- ul_Command1 =
- inl(devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_PROG);
+ ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
- outl(ul_Command1, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); /* Stop The Timer */
+ outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
if (data[1] == 1) {
/* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
- outl(0x02,
- devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_PROG);
+ outl(0x02, dev->iobase + APCI3501_TIMER_CTRL_REG);
} else {
- outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); /* disable Timer interrupt */
+ /* disable Timer interrupt */
+ outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
}
- /* Loading Timebase */
- outl(data[2],
- devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_TIMEBASE);
-
- /* Loading the Reload value */
- outl(data[3],
- devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_RELOAD_VALUE);
+ outl(data[2], dev->iobase + APCI3501_TIMER_TIMEBASE_REG);
+ outl(data[3], dev->iobase + APCI3501_TIMER_RELOAD_REG);
- /* printk ("\nTimer Address :: %x\n", (devpriv->iobase+APCI3501_WATCHDOG)); */
- ul_Command1 =
- inl(devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_PROG);
+ /* mode 2 */
+ ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
ul_Command1 =
(ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
- outl(ul_Command1, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); /* mode 2 */
-
- } /* end if(data[0]==ADDIDATA_TIMER) */
+ outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+ }
return insn->n;
}
/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI3501_StartStopWriteTimerCounterWatchdog |
-| (struct comedi_device *dev,struct comedi_subdevice *s, |
-| struct comedi_insn *insn,unsigned int *data) |
-+----------------------------------------------------------------------------+
-| Task : Start / Stop The Selected Timer , Counter or Watchdog |
-+----------------------------------------------------------------------------+
-| Input Parameters : struct comedi_device *dev : Driver handle |
-| unsigned int *data : Data Pointer contains |
-| configuration parameters as below |
-| |
-| data[0] : 0 Timer |
-| 1 Counter |
-| 2 Watchdog | | data[1] : 1 Start |
-| 0 Stop | 2 Trigger |
-+----------------------------------------------------------------------------+
-| Output Parameters : -- |
-+----------------------------------------------------------------------------+
-| Return Value : TRUE : No error occur |
-| : FALSE : Error occur. Return the error |
-| |
-+----------------------------------------------------------------------------+
-*/
-
+ * (*insn_write) for the timer subdevice
+ *
+ * Start / Stop The Selected Timer , Counter or Watchdog
+ * Data Pointer contains configuration parameters as below
+ * data[0] : 0 Timer
+ * 1 Counter
+ * 2 Watchdog
+ * data[1] : 1 Start
+ * 0 Stop
+ * 2 Trigger
+ */
static int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
- struct addi_private *devpriv = dev->private;
+ struct apci3501_private *devpriv = dev->private;
unsigned int ul_Command1 = 0;
int i_Temp;
if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
if (data[1] == 1) {
- ul_Command1 =
- inl(devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_PROG);
+ ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
/* Enable the Watchdog */
- outl(ul_Command1,
- devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_PROG);
+ outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
}
else if (data[1] == 0) /* Stop The Watchdog */
{
/* Stop The Watchdog */
- ul_Command1 =
- inl(devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_PROG);
+ ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
- outl(0x0,
- devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_PROG);
+ outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
} else if (data[1] == 2) {
- ul_Command1 =
- inl(devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_PROG);
+ ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL;
- outl(ul_Command1,
- devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_PROG);
- } /* if(data[1]==2) */
- } /* end if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */
+ outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+ }
+ }
if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
if (data[1] == 1) {
- ul_Command1 =
- inl(devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_PROG);
+ ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
/* Enable the Timer */
- outl(ul_Command1,
- devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_PROG);
+ outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
} else if (data[1] == 0) {
/* Stop The Timer */
- ul_Command1 =
- inl(devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_PROG);
+ ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
- outl(ul_Command1,
- devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_PROG);
+ outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
}
else if (data[1] == 2) {
/* Trigger the Timer */
- ul_Command1 =
- inl(devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_PROG);
+ ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL;
- outl(ul_Command1,
- devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_PROG);
+ outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
}
+ }
- } /* end if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
- i_Temp = inl(devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_TRIG_STATUS) & 0x1;
+ i_Temp = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1;
return insn->n;
}
/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI3501_ReadTimerCounterWatchdog |
-| (struct comedi_device *dev,struct comedi_subdevice *s, |
-| struct comedi_insn *insn,unsigned int *data) |
-+----------------------------------------------------------------------------+
-| Task : Read The Selected Timer , Counter or Watchdog |
-+----------------------------------------------------------------------------+
-| Input Parameters : struct comedi_device *dev : Driver handle |
-| unsigned int *data : Data Pointer contains |
-| configuration parameters as below |
-| |
-| data[0] : 0 Timer |
-| 1 Counter |
-| 2 Watchdog | | data[1] : Timer Counter Watchdog Number |
-+----------------------------------------------------------------------------+
-| Output Parameters : -- |
-+----------------------------------------------------------------------------+
-| Return Value : TRUE : No error occur |
-| : FALSE : Error occur. Return the error |
-| |
-+----------------------------------------------------------------------------+
-*/
-
+ * (*insn_read) for the timer subdevice
+ *
+ * Read The Selected Timer, Counter or Watchdog
+ * Data Pointer contains configuration parameters as below
+ * data[0] : 0 Timer
+ * 1 Counter
+ * 2 Watchdog
+ * data[1] : Timer Counter Watchdog Number
+ */
static int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
- struct addi_private *devpriv = dev->private;
+ struct apci3501_private *devpriv = dev->private;
if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
- data[0] =
- inl(devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_TRIG_STATUS) & 0x1;
- data[1] = inl(devpriv->iobase + APCI3501_WATCHDOG);
- } /* end if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */
+ data[0] = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1;
+ data[1] = inl(dev->iobase + APCI3501_TIMER_SYNC_REG);
+ }
else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
- data[0] =
- inl(devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_TRIG_STATUS) & 0x1;
- data[1] = inl(devpriv->iobase + APCI3501_WATCHDOG);
- } /* end if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
+ data[0] = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1;
+ data[1] = inl(dev->iobase + APCI3501_TIMER_SYNC_REG);
+ }
else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
&& (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)) {
@@ -501,111 +176,3 @@ static int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device *dev,
}
return insn->n;
}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : int i_APCI3501_Reset(struct comedi_device *dev) |
-| |
-+----------------------------------------------------------------------------+
-| Task :Resets the registers of the card |
-+----------------------------------------------------------------------------+
-| Input Parameters : |
-+----------------------------------------------------------------------------+
-| Output Parameters : -- |
-+----------------------------------------------------------------------------+
-| Return Value : |
-| |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI3501_Reset(struct comedi_device *dev)
-{
- struct addi_private *devpriv = dev->private;
- int i_Count = 0, i_temp = 0;
- unsigned int ul_Command1 = 0, ul_Polarity, ul_DAC_Ready = 0;
-
- outl(0x0, devpriv->iobase + APCI3501_DIGITAL_OP);
- outl(1, devpriv->iobase + APCI3501_ANALOG_OUTPUT +
- APCI3501_AO_VOLT_MODE);
-
- ul_Polarity = 0x80000000;
-
- for (i_Count = 0; i_Count <= 7; i_Count++) {
- ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
-
- while (ul_DAC_Ready == 0) {
- ul_DAC_Ready =
- inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
- ul_DAC_Ready = (ul_DAC_Ready >> 8) & 1;
- }
-
- if (ul_DAC_Ready) {
- /* Output the Value on the output channels. */
- ul_Command1 =
- (unsigned int) ((unsigned int) (i_Count & 0xFF) |
- (unsigned int) ((i_temp << 0x8) & 0x7FFFFF00L) |
- (unsigned int) (ul_Polarity));
- outl(ul_Command1,
- devpriv->iobase + APCI3501_ANALOG_OUTPUT +
- APCI3501_AO_PROG);
- }
- }
-
- return 0;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name : static void v_APCI3501_Interrupt |
-| (int irq , void *d) |
-+----------------------------------------------------------------------------+
-| Task : Interrupt processing Routine |
-+----------------------------------------------------------------------------+
-| Input Parameters : int irq : irq number |
-| void *d : void pointer |
-+----------------------------------------------------------------------------+
-| Output Parameters : -- |
-+----------------------------------------------------------------------------+
-| Return Value : TRUE : No error occur |
-| : FALSE : Error occur. Return the error |
-| |
-+----------------------------------------------------------------------------+
-*/
-static void v_APCI3501_Interrupt(int irq, void *d)
-{
- int i_temp;
- struct comedi_device *dev = d;
- struct addi_private *devpriv = dev->private;
- unsigned int ui_Timer_AOWatchdog;
- unsigned long ul_Command1;
-
- /* Disable Interrupt */
- ul_Command1 =
- inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
-
- ul_Command1 = (ul_Command1 & 0xFFFFF9FDul);
- outl(ul_Command1,
- devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
-
- ui_Timer_AOWatchdog =
- inl(devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_IRQ) & 0x1;
-
- if ((!ui_Timer_AOWatchdog)) {
- comedi_error(dev, "IRQ from unknown source");
- return;
- }
-
-/*
-* Enable Interrupt Send a signal to from kernel to user space
-*/
- send_sig(SIGIO, devpriv->tsk_Current, 0);
- ul_Command1 =
- inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
- ul_Command1 = ((ul_Command1 & 0xFFFFF9FDul) | 1 << 1);
- outl(ul_Command1,
- devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
- i_temp = inl(devpriv->iobase + APCI3501_WATCHDOG +
- APCI3501_TCW_TRIG_STATUS) & 0x1;
- return;
-}
diff --git a/drivers/staging/comedi/drivers/addi_apci_035.c b/drivers/staging/comedi/drivers/addi_apci_035.c
index c981d4b1cc73..5a53e58258a0 100644
--- a/drivers/staging/comedi/drivers/addi_apci_035.c
+++ b/drivers/staging/comedi/drivers/addi_apci_035.c
@@ -1,3 +1,5 @@
+#include <linux/pci.h>
+
#include "../comedidev.h"
#include "comedi_fc.h"
#include "amcc_s5933.h"
@@ -53,11 +55,6 @@ static int apci035_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &apci035_driver);
}
-static void apci035_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(apci035_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x0300) },
{ 0 }
@@ -68,7 +65,7 @@ static struct pci_driver apci035_pci_driver = {
.name = "addi_apci_035",
.id_table = apci035_pci_table,
.probe = apci035_pci_probe,
- .remove = apci035_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(apci035_driver, apci035_pci_driver);
diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c
index 7f9424205a64..c0d0429c35c8 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1032.c
@@ -29,6 +29,9 @@
* source code.
*/
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+
#include "../comedidev.h"
#include "comedi_fc.h"
#include "amcc_s5933.h"
@@ -375,11 +378,6 @@ static int apci1032_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &apci1032_driver);
}
-static void apci1032_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(apci1032_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1003) },
{ 0 }
@@ -390,7 +388,7 @@ static struct pci_driver apci1032_pci_driver = {
.name = "addi_apci_1032",
.id_table = apci1032_pci_table,
.probe = apci1032_pci_probe,
- .remove = apci1032_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(apci1032_driver, apci1032_pci_driver);
diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c
index 8e686a9b811b..9c2f8eeb7977 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1500.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1500.c
@@ -1,3 +1,5 @@
+#include <linux/pci.h>
+
#include "../comedidev.h"
#include "comedi_fc.h"
#include "amcc_s5933.h"
@@ -53,11 +55,6 @@ static int apci1500_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &apci1500_driver);
}
-static void apci1500_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(apci1500_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA_OLD, 0x80fc) },
{ 0 }
@@ -68,7 +65,7 @@ static struct pci_driver apci1500_pci_driver = {
.name = "addi_apci_1500",
.id_table = apci1500_pci_table,
.probe = apci1500_pci_probe,
- .remove = apci1500_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(apci1500_driver, apci1500_pci_driver);
diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c
index 8fef04b4d197..69e399638419 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1516.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1516.c
@@ -29,7 +29,10 @@
* this source code.
*/
+#include <linux/pci.h>
+
#include "../comedidev.h"
+#include "addi_watchdog.h"
#include "comedi_fc.h"
/*
@@ -49,13 +52,6 @@
* PCI bar 2 I/O Register map - Watchdog (APCI-1516 and APCI-2016)
*/
#define APCI1516_WDOG_REG 0x00
-#define APCI1516_WDOG_RELOAD_REG 0x04
-#define APCI1516_WDOG_CTRL_REG 0x0c
-#define APCI1516_WDOG_CTRL_ENABLE (1 << 0)
-#define APCI1516_WDOG_CTRL_SW_TRIG (1 << 9)
-#define APCI1516_WDOG_STATUS_REG 0x10
-#define APCI1516_WDOG_STATUS_ENABLED (1 << 0)
-#define APCI1516_WDOG_STATUS_SW_TRIG (1 << 1)
struct apci1516_boardinfo {
const char *name;
@@ -86,7 +82,6 @@ static const struct apci1516_boardinfo apci1516_boardtypes[] = {
struct apci1516_private {
unsigned long wdog_iobase;
- unsigned int ctrl;
};
static int apci1516_di_insn_bits(struct comedi_device *dev,
@@ -120,82 +115,6 @@ static int apci1516_do_insn_bits(struct comedi_device *dev,
return insn->n;
}
-/*
- * The watchdog subdevice is configured with two INSN_CONFIG instructions:
- *
- * Enable the watchdog and set the reload timeout:
- * data[0] = INSN_CONFIG_ARM
- * data[1] = timeout reload value
- *
- * Disable the watchdog:
- * data[0] = INSN_CONFIG_DISARM
- */
-static int apci1516_wdog_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct apci1516_private *devpriv = dev->private;
- unsigned int reload;
-
- switch (data[0]) {
- case INSN_CONFIG_ARM:
- devpriv->ctrl = APCI1516_WDOG_CTRL_ENABLE;
- reload = data[1] & s->maxdata;
- outw(reload, devpriv->wdog_iobase + APCI1516_WDOG_RELOAD_REG);
-
- /* Time base is 20ms, let the user know the timeout */
- dev_info(dev->class_dev, "watchdog enabled, timeout:%dms\n",
- 20 * reload + 20);
- break;
- case INSN_CONFIG_DISARM:
- devpriv->ctrl = 0;
- break;
- default:
- return -EINVAL;
- }
-
- outw(devpriv->ctrl, devpriv->wdog_iobase + APCI1516_WDOG_CTRL_REG);
-
- return insn->n;
-}
-
-static int apci1516_wdog_insn_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct apci1516_private *devpriv = dev->private;
- int i;
-
- if (devpriv->ctrl == 0) {
- dev_warn(dev->class_dev, "watchdog is disabled\n");
- return -EINVAL;
- }
-
- /* "ping" the watchdog */
- for (i = 0; i < insn->n; i++) {
- outw(devpriv->ctrl | APCI1516_WDOG_CTRL_SW_TRIG,
- devpriv->wdog_iobase + APCI1516_WDOG_CTRL_REG);
- }
-
- return insn->n;
-}
-
-static int apci1516_wdog_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct apci1516_private *devpriv = dev->private;
- int i;
-
- for (i = 0; i < insn->n; i++)
- data[i] = inw(devpriv->wdog_iobase + APCI1516_WDOG_STATUS_REG);
-
- return insn->n;
-}
-
static int apci1516_reset(struct comedi_device *dev)
{
const struct apci1516_boardinfo *this_board = comedi_board(dev);
@@ -205,8 +124,8 @@ static int apci1516_reset(struct comedi_device *dev)
return 0;
outw(0x0, dev->iobase + APCI1516_DO_REG);
- outw(0x0, devpriv->wdog_iobase + APCI1516_WDOG_CTRL_REG);
- outw(0x0, devpriv->wdog_iobase + APCI1516_WDOG_RELOAD_REG);
+
+ addi_watchdog_reset(devpriv->wdog_iobase);
return 0;
}
@@ -285,13 +204,9 @@ static int apci1516_auto_attach(struct comedi_device *dev,
/* Initialize the watchdog subdevice */
s = &dev->subdevices[2];
if (this_board->has_wdog) {
- s->type = COMEDI_SUBD_TIMER;
- s->subdev_flags = SDF_WRITEABLE;
- s->n_chan = 1;
- s->maxdata = 0xff;
- s->insn_write = apci1516_wdog_insn_write;
- s->insn_read = apci1516_wdog_insn_read;
- s->insn_config = apci1516_wdog_insn_config;
+ ret = addi_watchdog_init(s, devpriv->wdog_iobase);
+ if (ret)
+ return ret;
} else {
s->type = COMEDI_SUBD_UNUSED;
}
@@ -304,10 +219,12 @@ static void apci1516_detach(struct comedi_device *dev)
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- if (dev->iobase) {
+ if (dev->iobase)
apci1516_reset(dev);
+ if (dev->subdevices)
+ addi_watchdog_cleanup(&dev->subdevices[2]);
+ if (dev->iobase)
comedi_pci_disable(pcidev);
- }
}
static struct comedi_driver apci1516_driver = {
@@ -323,11 +240,6 @@ static int apci1516_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &apci1516_driver);
}
-static void apci1516_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(apci1516_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, PCI_DEVICE_ID_APCI1016) },
{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, PCI_DEVICE_ID_APCI1516) },
@@ -340,7 +252,7 @@ static struct pci_driver apci1516_pci_driver = {
.name = "addi_apci_1516",
.id_table = apci1516_pci_table,
.probe = apci1516_pci_probe,
- .remove = apci1516_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(apci1516_driver, apci1516_pci_driver);
diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c
index 513e536f292f..ddea64df9180 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1564.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1564.c
@@ -1,3 +1,5 @@
+#include <linux/pci.h>
+
#include "../comedidev.h"
#include "comedi_fc.h"
#include "amcc_s5933.h"
@@ -50,11 +52,6 @@ static int apci1564_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &apci1564_driver);
}
-static void apci1564_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(apci1564_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1006) },
{ 0 }
@@ -65,7 +62,7 @@ static struct pci_driver apci1564_pci_driver = {
.name = "addi_apci_1564",
.id_table = apci1564_pci_table,
.probe = apci1564_pci_probe,
- .remove = apci1564_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(apci1564_driver, apci1564_pci_driver);
diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c
index ab9a96ac8180..e51f80001363 100644
--- a/drivers/staging/comedi/drivers/addi_apci_16xx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c
@@ -1,49 +1,227 @@
+/*
+ * addi_apci_16xx.c
+ * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+ * Project manager: S. Weber
+ *
+ * ADDI-DATA GmbH
+ * Dieselstrasse 3
+ * D-77833 Ottersweier
+ * Tel: +19(0)7223/9493-0
+ * Fax: +49(0)7223/9493-92
+ * http://www.addi-data.com
+ * info@addi-data.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * You should also find the complete GPL in the COPYING file accompanying
+ * this source code.
+ */
+
+#include <linux/pci.h>
+
#include "../comedidev.h"
-#include "comedi_fc.h"
-#include "amcc_s5933.h"
-#include "addi-data/addi_common.h"
+/*
+ * PCI device ids supported by this driver
+ */
+#define PCI_DEVICE_ID_APCI1648 0x1009
+#define PCI_DEVICE_ID_APCI1696 0x100a
-#include "addi-data/addi_eeprom.c"
-#include "addi-data/hwdrv_apci16xx.c"
-#include "addi-data/addi_common.c"
+/*
+ * Register I/O map
+ */
+#define APCI16XX_IN_REG(x) (((x) * 4) + 0x08)
+#define APCI16XX_OUT_REG(x) (((x) * 4) + 0x14)
+#define APCI16XX_DIR_REG(x) (((x) * 4) + 0x20)
-static const struct addi_board apci16xx_boardtypes[] = {
+struct apci16xx_boardinfo {
+ const char *name;
+ unsigned short vendor;
+ unsigned short device;
+ int n_chan;
+};
+
+static const struct apci16xx_boardinfo apci16xx_boardtypes[] = {
{
- .pc_DriverName = "apci1648",
- .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
- .i_DeviceId = 0x1009,
- .i_IorangeBase0 = 128,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .i_NbrTTLChannel = 48,
- .reset = i_APCI16XX_Reset,
- .ttl_config = i_APCI16XX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI16XX_InsnBitsReadTTLIO,
- .ttl_read = i_APCI16XX_InsnReadTTLIOAllPortValue,
- .ttl_write = i_APCI16XX_InsnBitsWriteTTLIO,
+ .name = "apci1648",
+ .vendor = PCI_VENDOR_ID_ADDIDATA,
+ .device = PCI_DEVICE_ID_APCI1648,
+ .n_chan = 48, /* 2 subdevices */
}, {
- .pc_DriverName = "apci1696",
- .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
- .i_DeviceId = 0x100A,
- .i_IorangeBase0 = 128,
- .i_PCIEeprom = ADDIDATA_NO_EEPROM,
- .i_NbrTTLChannel = 96,
- .reset = i_APCI16XX_Reset,
- .ttl_config = i_APCI16XX_InsnConfigInitTTLIO,
- .ttl_bits = i_APCI16XX_InsnBitsReadTTLIO,
- .ttl_read = i_APCI16XX_InsnReadTTLIOAllPortValue,
- .ttl_write = i_APCI16XX_InsnBitsWriteTTLIO,
+ .name = "apci1696",
+ .vendor = PCI_VENDOR_ID_ADDIDATA,
+ .device = PCI_DEVICE_ID_APCI1696,
+ .n_chan = 96, /* 3 subdevices */
},
};
+static int apci16xx_insn_config(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ unsigned int chan_mask = 1 << CR_CHAN(insn->chanspec);
+ unsigned int bits;
+
+ /*
+ * Each 8-bit "port" is configurable as either input or
+ * output. Changing the configuration of any channel in
+ * a port changes the entire port.
+ */
+ if (chan_mask & 0x000000ff)
+ bits = 0x000000ff;
+ else if (chan_mask & 0x0000ff00)
+ bits = 0x0000ff00;
+ else if (chan_mask & 0x00ff0000)
+ bits = 0x00ff0000;
+ else
+ bits = 0xff000000;
+
+ switch (data[0]) {
+ case INSN_CONFIG_DIO_INPUT:
+ s->io_bits &= ~bits;
+ break;
+ case INSN_CONFIG_DIO_OUTPUT:
+ s->io_bits |= bits;
+ break;
+ case INSN_CONFIG_DIO_QUERY:
+ data[1] = (s->io_bits & bits) ? COMEDI_INPUT : COMEDI_OUTPUT;
+ return insn->n;
+ default:
+ return -EINVAL;
+ }
+
+ outl(s->io_bits, dev->iobase + APCI16XX_DIR_REG(s->index));
+
+ return insn->n;
+}
+
+static int apci16xx_dio_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ unsigned int mask = data[0];
+ unsigned int bits = data[1];
+
+ /* Only update the channels configured as outputs */
+ mask &= s->io_bits;
+ if (mask) {
+ s->state &= ~mask;
+ s->state |= (bits & mask);
+
+ outl(s->state, dev->iobase + APCI16XX_OUT_REG(s->index));
+ }
+
+ data[1] = inl(dev->iobase + APCI16XX_IN_REG(s->index));
+
+ return insn->n;
+}
+
+static const void *apci16xx_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
+{
+ const struct apci16xx_boardinfo *board;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(apci16xx_boardtypes); i++) {
+ board = &apci16xx_boardtypes[i];
+ if (board->vendor == pcidev->vendor &&
+ board->device == pcidev->device)
+ return board;
+ }
+ return NULL;
+}
+
+static int apci16xx_auto_attach(struct comedi_device *dev,
+ unsigned long context_unused)
+{
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ const struct apci16xx_boardinfo *board;
+ struct comedi_subdevice *s;
+ unsigned int n_subdevs;
+ unsigned int last;
+ int i;
+ int ret;
+
+ board = apci16xx_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, 0);
+
+ /*
+ * Work out the nubmer of subdevices needed to support all the
+ * digital i/o channels on the board. Each subdevice supports
+ * up to 32 channels.
+ */
+ n_subdevs = board->n_chan / 32;
+ if ((n_subdevs * 32) < board->n_chan) {
+ last = board->n_chan - (n_subdevs * 32);
+ n_subdevs++;
+ } else {
+ last = 0;
+ }
+
+ ret = comedi_alloc_subdevices(dev, n_subdevs);
+ if (ret)
+ return ret;
+
+ /* Initialize the TTL digital i/o subdevices */
+ for (i = 0; i < n_subdevs; i++) {
+ s = &dev->subdevices[i];
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_WRITEABLE | SDF_READABLE;
+ s->n_chan = ((i * 32) < board->n_chan) ? 32 : last;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_config = apci16xx_insn_config;
+ s->insn_bits = apci16xx_dio_insn_bits;
+
+ /* Default all channels to inputs */
+ s->io_bits = 0;
+ outl(s->io_bits, dev->iobase + APCI16XX_DIR_REG(i));
+ }
+
+ return 0;
+}
+
+static void apci16xx_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 apci16xx_driver = {
.driver_name = "addi_apci_16xx",
.module = THIS_MODULE,
- .auto_attach = addi_auto_attach,
- .detach = i_ADDI_Detach,
+ .auto_attach = apci16xx_auto_attach,
+ .detach = apci16xx_detach,
.num_names = ARRAY_SIZE(apci16xx_boardtypes),
- .board_name = &apci16xx_boardtypes[0].pc_DriverName,
- .offset = sizeof(struct addi_board),
+ .board_name = &apci16xx_boardtypes[0].name,
+ .offset = sizeof(struct apci16xx_boardinfo),
};
static int apci16xx_pci_probe(struct pci_dev *dev,
@@ -52,14 +230,9 @@ static int apci16xx_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &apci16xx_driver);
}
-static void apci16xx_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(apci16xx_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1009) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x100a) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, PCI_DEVICE_ID_APCI1648) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, PCI_DEVICE_ID_APCI1696) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, apci16xx_pci_table);
@@ -68,10 +241,10 @@ static struct pci_driver apci16xx_pci_driver = {
.name = "addi_apci_16xx",
.id_table = apci16xx_pci_table,
.probe = apci16xx_pci_probe,
- .remove = apci16xx_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(apci16xx_driver, apci16xx_pci_driver);
+MODULE_DESCRIPTION("ADDI-DATA APCI-1648/1696, TTL I/O boards");
MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_apci_1710.c b/drivers/staging/comedi/drivers/addi_apci_1710.c
index 152e7ef9b17b..e83e829831b0 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1710.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1710.c
@@ -1,3 +1,5 @@
+#include <linux/pci.h>
+
#include <asm/i387.h>
#include "../comedidev.h"
@@ -128,11 +130,6 @@ static int apci1710_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &apci1710_driver);
}
-static void apci1710_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(apci1710_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA_OLD, APCI1710_BOARD_DEVICE_ID) },
{ 0 }
@@ -143,7 +140,7 @@ static struct pci_driver apci1710_pci_driver = {
.name = "addi_apci_1710",
.id_table = apci1710_pci_table,
.probe = apci1710_pci_probe,
- .remove = apci1710_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(apci1710_driver, apci1710_pci_driver);
diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c
index 8f8d3e95fc78..9ce1d26aff2f 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2032.c
@@ -29,7 +29,11 @@
* this source code.
*/
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+
#include "../comedidev.h"
+#include "addi_watchdog.h"
#include "comedi_fc.h"
/*
@@ -45,17 +49,12 @@
#define APCI2032_STATUS_REG 0x0c
#define APCI2032_STATUS_IRQ (1 << 0)
#define APCI2032_WDOG_REG 0x10
-#define APCI2032_WDOG_RELOAD_REG 0x14
-#define APCI2032_WDOG_TIMEBASE 0x18
-#define APCI2032_WDOG_CTRL_REG 0x1c
-#define APCI2032_WDOG_CTRL_ENABLE (1 << 0)
-#define APCI2032_WDOG_CTRL_SW_TRIG (1 << 9)
-#define APCI2032_WDOG_STATUS_REG 0x20
-#define APCI2032_WDOG_STATUS_ENABLED (1 << 0)
-#define APCI2032_WDOG_STATUS_SW_TRIG (1 << 1)
-
-struct apci2032_private {
- unsigned int wdog_ctrl;
+
+struct apci2032_int_private {
+ spinlock_t spinlock;
+ unsigned int stop_count;
+ bool active;
+ unsigned char enabled_isns;
};
static int apci2032_do_insn_bits(struct comedi_device *dev,
@@ -79,88 +78,47 @@ static int apci2032_do_insn_bits(struct comedi_device *dev,
return insn->n;
}
-/*
- * The watchdog subdevice is configured with two INSN_CONFIG instructions:
- *
- * Enable the watchdog and set the reload timeout:
- * data[0] = INSN_CONFIG_ARM
- * data[1] = timeout reload value
- *
- * Disable the watchdog:
- * data[0] = INSN_CONFIG_DISARM
- */
-static int apci2032_wdog_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
+static int apci2032_int_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct apci2032_private *devpriv = dev->private;
- unsigned int reload;
-
- switch (data[0]) {
- case INSN_CONFIG_ARM:
- devpriv->wdog_ctrl = APCI2032_WDOG_CTRL_ENABLE;
- reload = data[1] & s->maxdata;
- outw(reload, dev->iobase + APCI2032_WDOG_RELOAD_REG);
-
- /* Time base is 20ms, let the user know the timeout */
- dev_info(dev->class_dev, "watchdog enabled, timeout:%dms\n",
- 20 * reload + 20);
- break;
- case INSN_CONFIG_DISARM:
- devpriv->wdog_ctrl = 0;
- break;
- default:
- return -EINVAL;
- }
-
- outw(devpriv->wdog_ctrl, dev->iobase + APCI2032_WDOG_CTRL_REG);
-
+ data[1] = inl(dev->iobase + APCI2032_INT_STATUS_REG) & 3;
return insn->n;
}
-static int apci2032_wdog_insn_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
+static void apci2032_int_stop(struct comedi_device *dev,
+ struct comedi_subdevice *s)
{
- struct apci2032_private *devpriv = dev->private;
- int i;
-
- if (devpriv->wdog_ctrl == 0) {
- dev_warn(dev->class_dev, "watchdog is disabled\n");
- return -EINVAL;
- }
-
- /* "ping" the watchdog */
- for (i = 0; i < insn->n; i++) {
- outw(devpriv->wdog_ctrl | APCI2032_WDOG_CTRL_SW_TRIG,
- dev->iobase + APCI2032_WDOG_CTRL_REG);
- }
+ struct apci2032_int_private *subpriv = s->private;
- return insn->n;
+ subpriv->active = false;
+ subpriv->enabled_isns = 0;
+ outl(0x0, dev->iobase + APCI2032_INT_CTRL_REG);
}
-static int apci2032_wdog_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
+static bool apci2032_int_start(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned char enabled_isns)
{
- int i;
-
- for (i = 0; i < insn->n; i++)
- data[i] = inl(dev->iobase + APCI2032_WDOG_STATUS_REG);
-
- return insn->n;
-}
+ struct apci2032_int_private *subpriv = s->private;
+ struct comedi_cmd *cmd = &s->async->cmd;
+ bool do_event;
+
+ subpriv->enabled_isns = enabled_isns;
+ subpriv->stop_count = cmd->stop_arg;
+ if (cmd->stop_src == TRIG_COUNT && subpriv->stop_count == 0) {
+ /* An empty acquisition! */
+ s->async->events |= COMEDI_CB_EOA;
+ subpriv->active = false;
+ do_event = true;
+ } else {
+ subpriv->active = true;
+ outl(enabled_isns, dev->iobase + APCI2032_INT_CTRL_REG);
+ do_event = false;
+ }
-static int apci2032_int_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- data[1] = s->state;
- return insn->n;
+ return do_event;
}
static int apci2032_int_cmdtest(struct comedi_device *dev,
@@ -172,15 +130,17 @@ static int apci2032_int_cmdtest(struct comedi_device *dev,
/* 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_OTHER);
- err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+ 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);
+ err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
if (err)
return 1;
/* Step 2a : make sure trigger sources are unique */
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
/* Step 2b : and mutually compatible */
if (err)
@@ -189,18 +149,11 @@ static int apci2032_int_cmdtest(struct comedi_device *dev,
/* Step 3: check if arguments are trivially valid */
err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-
- /*
- * 0 == no trigger
- * 1 == trigger on VCC interrupt
- * 2 == trigger on CC interrupt
- * 3 == trigger on either VCC or CC interrupt
- */
- err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 3);
-
+ err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
- err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, 1);
- err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+ err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+ if (cmd->stop_src == TRIG_NONE)
+ err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
if (err)
return 3;
@@ -217,8 +170,22 @@ static int apci2032_int_cmd(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct comedi_cmd *cmd = &s->async->cmd;
+ struct apci2032_int_private *subpriv = s->private;
+ unsigned char enabled_isns;
+ unsigned int n;
+ unsigned long flags;
+ bool do_event;
+
+ enabled_isns = 0;
+ for (n = 0; n < cmd->chanlist_len; n++)
+ enabled_isns |= 1 << CR_CHAN(cmd->chanlist[n]);
+
+ spin_lock_irqsave(&subpriv->spinlock, flags);
+ do_event = apci2032_int_start(dev, s, enabled_isns);
+ spin_unlock_irqrestore(&subpriv->spinlock, flags);
- outl(cmd->scan_begin_arg, dev->iobase + APCI2032_INT_CTRL_REG);
+ if (do_event)
+ comedi_event(dev, s);
return 0;
}
@@ -226,7 +193,13 @@ static int apci2032_int_cmd(struct comedi_device *dev,
static int apci2032_int_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- outl(0x0, dev->iobase + APCI2032_INT_CTRL_REG);
+ struct apci2032_int_private *subpriv = s->private;
+ unsigned long flags;
+
+ spin_lock_irqsave(&subpriv->spinlock, flags);
+ if (subpriv->active)
+ apci2032_int_stop(dev, s);
+ spin_unlock_irqrestore(&subpriv->spinlock, flags);
return 0;
}
@@ -235,19 +208,64 @@ static irqreturn_t apci2032_interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
struct comedi_subdevice *s = dev->read_subdev;
+ struct apci2032_int_private *subpriv;
unsigned int val;
+ bool do_event = false;
+
+ if (!dev->attached)
+ return IRQ_NONE;
/* Check if VCC OR CC interrupt has occurred */
val = inl(dev->iobase + APCI2032_STATUS_REG) & APCI2032_STATUS_IRQ;
if (!val)
return IRQ_NONE;
- s->state = inl(dev->iobase + APCI2032_INT_STATUS_REG);
- outl(0x0, dev->iobase + APCI2032_INT_CTRL_REG);
+ subpriv = s->private;
+ spin_lock(&subpriv->spinlock);
+
+ val = inl(dev->iobase + APCI2032_INT_STATUS_REG) & 3;
+ /* Disable triggered interrupt sources. */
+ outl(~val & 3, dev->iobase + APCI2032_INT_CTRL_REG);
+ /*
+ * Note: We don't reenable the triggered interrupt sources because they
+ * are level-sensitive, hardware error status interrupt sources and
+ * they'd keep triggering interrupts repeatedly.
+ */
- comedi_buf_put(s->async, s->state);
- s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
- comedi_event(dev, s);
+ if (subpriv->active && (val & subpriv->enabled_isns) != 0) {
+ unsigned short bits;
+ unsigned int n, len;
+ unsigned int *chanlist;
+
+ /* Bits in scan data correspond to indices in channel list. */
+ bits = 0;
+ len = s->async->cmd.chanlist_len;
+ chanlist = &s->async->cmd.chanlist[0];
+ for (n = 0; n < len; n++)
+ if ((val & (1U << CR_CHAN(chanlist[n]))) != 0)
+ bits |= 1U << n;
+
+ if (comedi_buf_put(s->async, bits)) {
+ s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
+ if (s->async->cmd.stop_src == TRIG_COUNT &&
+ subpriv->stop_count > 0) {
+ subpriv->stop_count--;
+ if (subpriv->stop_count == 0) {
+ /* end of acquisition */
+ s->async->events |= COMEDI_CB_EOA;
+ apci2032_int_stop(dev, s);
+ }
+ }
+ } else {
+ apci2032_int_stop(dev, s);
+ s->async->events |= COMEDI_CB_OVERFLOW;
+ }
+ do_event = true;
+ }
+
+ spin_unlock(&subpriv->spinlock);
+ if (do_event)
+ comedi_event(dev, s);
return IRQ_HANDLED;
}
@@ -256,8 +274,8 @@ static int apci2032_reset(struct comedi_device *dev)
{
outl(0x0, dev->iobase + APCI2032_DO_REG);
outl(0x0, dev->iobase + APCI2032_INT_CTRL_REG);
- outl(0x0, dev->iobase + APCI2032_WDOG_CTRL_REG);
- outl(0x0, dev->iobase + APCI2032_WDOG_RELOAD_REG);
+
+ addi_watchdog_reset(dev->iobase + APCI2032_WDOG_REG);
return 0;
}
@@ -266,21 +284,16 @@ static int apci2032_auto_attach(struct comedi_device *dev,
unsigned long context_unused)
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- struct apci2032_private *devpriv;
struct comedi_subdevice *s;
int ret;
dev->board_name = dev->driver->driver_name;
- devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
- if (!devpriv)
- return -ENOMEM;
- dev->private = devpriv;
-
ret = comedi_pci_enable(pcidev, dev->board_name);
if (ret)
return ret;
dev->iobase = pci_resource_start(pcidev, 1);
+ apci2032_reset(dev);
if (pcidev->irq > 0) {
ret = request_irq(pcidev->irq, apci2032_interrupt,
@@ -304,32 +317,34 @@ static int apci2032_auto_attach(struct comedi_device *dev,
/* Initialize the watchdog subdevice */
s = &dev->subdevices[1];
- s->type = COMEDI_SUBD_TIMER;
- s->subdev_flags = SDF_WRITEABLE;
- s->n_chan = 1;
- s->maxdata = 0xff;
- s->insn_write = apci2032_wdog_insn_write;
- s->insn_read = apci2032_wdog_insn_read;
- s->insn_config = apci2032_wdog_insn_config;
+ ret = addi_watchdog_init(s, dev->iobase + APCI2032_WDOG_REG);
+ if (ret)
+ return ret;
/* Initialize the interrupt subdevice */
s = &dev->subdevices[2];
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 2;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = apci2032_int_insn_bits;
if (dev->irq) {
+ struct apci2032_int_private *subpriv;
+
dev->read_subdev = s;
- s->type = COMEDI_SUBD_DI | SDF_CMD_READ;
- s->subdev_flags = SDF_READABLE;
- s->n_chan = 1;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = apci2032_int_insn_bits;
+ subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
+ if (!subpriv)
+ return -ENOMEM;
+ spin_lock_init(&subpriv->spinlock);
+ s->private = subpriv;
+ s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
+ s->len_chanlist = 2;
s->do_cmdtest = apci2032_int_cmdtest;
s->do_cmd = apci2032_int_cmd;
s->cancel = apci2032_int_cancel;
- } else {
- s->type = COMEDI_SUBD_UNUSED;
}
- apci2032_reset(dev);
return 0;
}
@@ -341,6 +356,10 @@ static void apci2032_detach(struct comedi_device *dev)
apci2032_reset(dev);
if (dev->irq)
free_irq(dev->irq, dev);
+ if (dev->read_subdev)
+ kfree(dev->read_subdev->private);
+ if (dev->subdevices)
+ addi_watchdog_cleanup(&dev->subdevices[1]);
if (pcidev) {
if (dev->iobase)
comedi_pci_disable(pcidev);
@@ -360,11 +379,6 @@ static int apci2032_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &apci2032_driver);
}
-static void apci2032_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(apci2032_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1004) },
{ 0 }
@@ -375,7 +389,7 @@ static struct pci_driver apci2032_pci_driver = {
.name = "addi_apci_2032",
.id_table = apci2032_pci_table,
.probe = apci2032_pci_probe,
- .remove = apci2032_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(apci2032_driver, apci2032_pci_driver);
diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c
index 7c2c5db01218..b1c4226902e1 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2200.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2200.c
@@ -1,42 +1,152 @@
+/*
+ * addi_apci_2200.c
+ * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+ * Project manager: Eric Stolz
+ *
+ * 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.
+ */
+
+#include <linux/pci.h>
+
#include "../comedidev.h"
-#include "comedi_fc.h"
-#include "amcc_s5933.h"
-
-#include "addi-data/addi_common.h"
-
-#include "addi-data/addi_eeprom.c"
-#include "addi-data/hwdrv_apci2200.c"
-#include "addi-data/addi_common.c"
-
-static const struct addi_board apci2200_boardtypes[] = {
- {
- .pc_DriverName = "apci2200",
- .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
- .i_DeviceId = 0x1005,
- .i_IorangeBase0 = 4,
- .i_IorangeBase1 = APCI2200_ADDRESS_RANGE,
- .i_PCIEeprom = ADDIDATA_EEPROM,
- .pc_EepromChip = ADDIDATA_93C76,
- .i_NbrDiChannel = 8,
- .i_NbrDoChannel = 16,
- .i_Timer = 1,
- .reset = i_APCI2200_Reset,
- .di_bits = apci2200_di_insn_bits,
- .do_bits = apci2200_do_insn_bits,
- .timer_config = i_APCI2200_ConfigWatchdog,
- .timer_write = i_APCI2200_StartStopWriteWatchdog,
- .timer_read = i_APCI2200_ReadWatchdog,
- },
-};
+#include "addi_watchdog.h"
+
+/*
+ * I/O Register Map
+ */
+#define APCI2200_DI_REG 0x00
+#define APCI2200_DO_REG 0x04
+#define APCI2200_WDOG_REG 0x08
+
+static int apci2200_di_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ data[1] = inw(dev->iobase + APCI2200_DI_REG);
+
+ return insn->n;
+}
+
+static int apci2200_do_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ unsigned int mask = data[0];
+ unsigned int bits = data[1];
+
+ s->state = inw(dev->iobase + APCI2200_DO_REG);
+ if (mask) {
+ s->state &= ~mask;
+ s->state |= (bits & mask);
+
+ outw(s->state, dev->iobase + APCI2200_DO_REG);
+ }
+
+ data[1] = s->state;
+
+ return insn->n;
+}
+
+static int apci2200_reset(struct comedi_device *dev)
+{
+ outw(0x0, dev->iobase + APCI2200_DO_REG);
+
+ addi_watchdog_reset(dev->iobase + APCI2200_WDOG_REG);
+
+ return 0;
+}
+
+static int apci2200_auto_attach(struct comedi_device *dev,
+ unsigned long context_unused)
+{
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ struct comedi_subdevice *s;
+ int ret;
+
+ dev->board_name = dev->driver->driver_name;
+
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
+
+ dev->iobase = pci_resource_start(pcidev, 1);
+
+ ret = comedi_alloc_subdevices(dev, 3);
+ if (ret)
+ return ret;
+
+ /* Initialize the digital input subdevice */
+ s = &dev->subdevices[0];
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 8;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = apci2200_di_insn_bits;
+
+ /* Initialize the digital output subdevice */
+ s = &dev->subdevices[1];
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITEABLE;
+ s->n_chan = 16;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = apci2200_do_insn_bits;
+
+ /* Initialize the watchdog subdevice */
+ s = &dev->subdevices[2];
+ ret = addi_watchdog_init(s, dev->iobase + APCI2200_WDOG_REG);
+ if (ret)
+ return ret;
+
+ apci2200_reset(dev);
+ return 0;
+}
+
+static void apci2200_detach(struct comedi_device *dev)
+{
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+
+ if (dev->iobase)
+ apci2200_reset(dev);
+ if (dev->subdevices)
+ addi_watchdog_cleanup(&dev->subdevices[2]);
+ if (pcidev) {
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
+ }
+}
static struct comedi_driver apci2200_driver = {
.driver_name = "addi_apci_2200",
.module = THIS_MODULE,
- .auto_attach = addi_auto_attach,
- .detach = i_ADDI_Detach,
- .num_names = ARRAY_SIZE(apci2200_boardtypes),
- .board_name = &apci2200_boardtypes[0].pc_DriverName,
- .offset = sizeof(struct addi_board),
+ .auto_attach = apci2200_auto_attach,
+ .detach = apci2200_detach,
};
static int apci2200_pci_probe(struct pci_dev *dev,
@@ -45,11 +155,6 @@ static int apci2200_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &apci2200_driver);
}
-static void apci2200_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(apci2200_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1005) },
{ 0 }
@@ -60,10 +165,10 @@ static struct pci_driver apci2200_pci_driver = {
.name = "addi_apci_2200",
.id_table = apci2200_pci_table,
.probe = apci2200_pci_probe,
- .remove = apci2200_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(apci2200_driver, apci2200_pci_driver);
+MODULE_DESCRIPTION("ADDI-DATA APCI-2200 Relay board, optically isolated");
MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c
index fec2962affc7..917234d24e99 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3120.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3120.c
@@ -1,3 +1,5 @@
+#include <linux/pci.h>
+
#include "../comedidev.h"
#include "comedi_fc.h"
#include "amcc_s5933.h"
@@ -251,11 +253,6 @@ static int apci3120_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &apci3120_driver);
}
-static void apci3120_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(apci3120_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA_OLD, 0x818d) },
{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA_OLD, 0x828d) },
@@ -267,7 +264,7 @@ static struct pci_driver apci3120_pci_driver = {
.name = "addi_apci_3120",
.id_table = apci3120_pci_table,
.probe = apci3120_pci_probe,
- .remove = apci3120_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(apci3120_driver, apci3120_pci_driver);
diff --git a/drivers/staging/comedi/drivers/addi_apci_3200.c b/drivers/staging/comedi/drivers/addi_apci_3200.c
index 9085b774b48d..90ee4f844f91 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3200.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3200.c
@@ -1,3 +1,5 @@
+#include <linux/pci.h>
+
#include <asm/i387.h>
#include "../comedidev.h"
@@ -106,15 +108,10 @@ static int apci3200_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &apci3200_driver);
}
-static void apci3200_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static struct pci_driver apci3200_pci_driver = {
.name = "addi_apci_3200",
.id_table = apci3200_pci_table,
.probe = apci3200_pci_probe,
- .remove = apci3200_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(apci3200_driver, apci3200_pci_driver);
diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c
index ed297deb8634..786fcaf82c32 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3501.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3501.c
@@ -1,54 +1,445 @@
+/*
+ * addi_apci_3501.c
+ * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+ * Project manager: Eric Stolz
+ *
+ * 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.
+ */
+
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+
#include "../comedidev.h"
#include "comedi_fc.h"
#include "amcc_s5933.h"
-#include "addi-data/addi_common.h"
+/*
+ * PCI bar 1 register I/O map
+ */
+#define APCI3501_AO_CTRL_STATUS_REG 0x00
+#define APCI3501_AO_CTRL_BIPOLAR (1 << 0)
+#define APCI3501_AO_STATUS_READY (1 << 8)
+#define APCI3501_AO_DATA_REG 0x04
+#define APCI3501_AO_DATA_CHAN(x) ((x) << 0)
+#define APCI3501_AO_DATA_VAL(x) ((x) << 8)
+#define APCI3501_AO_DATA_BIPOLAR (1 << 31)
+#define APCI3501_AO_TRIG_SCS_REG 0x08
+#define APCI3501_TIMER_SYNC_REG 0x20
+#define APCI3501_TIMER_RELOAD_REG 0x24
+#define APCI3501_TIMER_TIMEBASE_REG 0x28
+#define APCI3501_TIMER_CTRL_REG 0x2c
+#define APCI3501_TIMER_STATUS_REG 0x30
+#define APCI3501_TIMER_IRQ_REG 0x34
+#define APCI3501_TIMER_WARN_RELOAD_REG 0x38
+#define APCI3501_TIMER_WARN_TIMEBASE_REG 0x3c
+#define APCI3501_DO_REG 0x40
+#define APCI3501_DI_REG 0x50
-#include "addi-data/addi_eeprom.c"
-#include "addi-data/hwdrv_apci3501.c"
-#include "addi-data/addi_common.c"
-
-static const struct addi_board apci3501_boardtypes[] = {
- {
- .pc_DriverName = "apci3501",
- .i_VendorId = PCI_VENDOR_ID_ADDIDATA,
- .i_DeviceId = 0x3001,
- .i_IorangeBase0 = 64,
- .i_IorangeBase1 = APCI3501_ADDRESS_RANGE,
- .i_PCIEeprom = ADDIDATA_EEPROM,
- .pc_EepromChip = ADDIDATA_S5933,
- .i_AoMaxdata = 16383,
- .pr_AoRangelist = &range_apci3501_ao,
- .i_NbrDiChannel = 2,
- .i_NbrDoChannel = 2,
- .i_DoMaxdata = 0x3,
- .i_Timer = 1,
- .interrupt = v_APCI3501_Interrupt,
- .reset = i_APCI3501_Reset,
- .ao_config = i_APCI3501_ConfigAnalogOutput,
- .ao_write = i_APCI3501_WriteAnalogOutput,
- .di_bits = apci3501_di_insn_bits,
- .do_bits = apci3501_do_insn_bits,
- .timer_config = i_APCI3501_ConfigTimerCounterWatchdog,
- .timer_write = i_APCI3501_StartStopWriteTimerCounterWatchdog,
- .timer_read = i_APCI3501_ReadTimerCounterWatchdog,
- },
+/*
+ * AMCC S5933 NVRAM
+ */
+#define NVRAM_USER_DATA_START 0x100
+
+#define NVCMD_BEGIN_READ (0x7 << 5)
+#define NVCMD_LOAD_LOW (0x4 << 5)
+#define NVCMD_LOAD_HIGH (0x5 << 5)
+
+/*
+ * Function types stored in the eeprom
+ */
+#define EEPROM_DIGITALINPUT 0
+#define EEPROM_DIGITALOUTPUT 1
+#define EEPROM_ANALOGINPUT 2
+#define EEPROM_ANALOGOUTPUT 3
+#define EEPROM_TIMER 4
+#define EEPROM_WATCHDOG 5
+#define EEPROM_TIMER_WATCHDOG_COUNTER 10
+
+struct apci3501_private {
+ int i_IobaseAmcc;
+ struct task_struct *tsk_Current;
+ unsigned char b_TimerSelectMode;
};
-static DEFINE_PCI_DEVICE_TABLE(apci3501_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3001) },
- { 0 }
+static struct comedi_lrange apci3501_ao_range = {
+ 2, {
+ BIP_RANGE(10),
+ UNI_RANGE(10)
+ }
};
-MODULE_DEVICE_TABLE(pci, apci3501_pci_table);
+
+static int apci3501_wait_for_dac(struct comedi_device *dev)
+{
+ unsigned int status;
+
+ do {
+ status = inl(dev->iobase + APCI3501_AO_CTRL_STATUS_REG);
+ } while (!(status & APCI3501_AO_STATUS_READY));
+
+ return 0;
+}
+
+static int apci3501_ao_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int range = CR_RANGE(insn->chanspec);
+ unsigned int val = 0;
+ int i;
+ int ret;
+
+ /*
+ * All analog output channels have the same output range.
+ * 14-bit bipolar: 0-10V
+ * 13-bit unipolar: +/-10V
+ * Changing the range of one channel changes all of them!
+ */
+ if (range) {
+ outl(0, dev->iobase + APCI3501_AO_CTRL_STATUS_REG);
+ } else {
+ val |= APCI3501_AO_DATA_BIPOLAR;
+ outl(APCI3501_AO_CTRL_BIPOLAR,
+ dev->iobase + APCI3501_AO_CTRL_STATUS_REG);
+ }
+
+ val |= APCI3501_AO_DATA_CHAN(chan);
+
+ for (i = 0; i < insn->n; i++) {
+ if (range == 1) {
+ if (data[i] > 0x1fff) {
+ dev_err(dev->class_dev,
+ "Unipolar resolution is only 13-bits\n");
+ return -EINVAL;
+ }
+ }
+
+ ret = apci3501_wait_for_dac(dev);
+ if (ret)
+ return ret;
+
+ outl(val | APCI3501_AO_DATA_VAL(data[i]),
+ dev->iobase + APCI3501_AO_DATA_REG);
+ }
+
+ return insn->n;
+}
+
+#include "addi-data/hwdrv_apci3501.c"
+
+static int apci3501_di_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ data[1] = inl(dev->iobase + APCI3501_DI_REG) & 0x3;
+
+ return insn->n;
+}
+
+static int apci3501_do_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ unsigned int mask = data[0];
+ unsigned int bits = data[1];
+
+ s->state = inl(dev->iobase + APCI3501_DO_REG);
+ if (mask) {
+ s->state &= ~mask;
+ s->state |= (bits & mask);
+
+ outl(s->state, dev->iobase + APCI3501_DO_REG);
+ }
+
+ data[1] = s->state;
+
+ return insn->n;
+}
+
+static void apci3501_eeprom_wait(unsigned long iobase)
+{
+ unsigned char val;
+
+ do {
+ val = inb(iobase + AMCC_OP_REG_MCSR_NVCMD);
+ } while (val & 0x80);
+}
+
+static unsigned short apci3501_eeprom_readw(unsigned long iobase,
+ unsigned short addr)
+{
+ unsigned short val = 0;
+ unsigned char tmp;
+ unsigned char i;
+
+ /* Add the offset to the start of the user data */
+ addr += NVRAM_USER_DATA_START;
+
+ for (i = 0; i < 2; i++) {
+ /* Load the low 8 bit address */
+ outb(NVCMD_LOAD_LOW, iobase + AMCC_OP_REG_MCSR_NVCMD);
+ apci3501_eeprom_wait(iobase);
+ outb((addr + i) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
+ apci3501_eeprom_wait(iobase);
+
+ /* Load the high 8 bit address */
+ outb(NVCMD_LOAD_HIGH, iobase + AMCC_OP_REG_MCSR_NVCMD);
+ apci3501_eeprom_wait(iobase);
+ outb(((addr + i) >> 8) & 0xff,
+ iobase + AMCC_OP_REG_MCSR_NVDATA);
+ apci3501_eeprom_wait(iobase);
+
+ /* Read the eeprom data byte */
+ outb(NVCMD_BEGIN_READ, iobase + AMCC_OP_REG_MCSR_NVCMD);
+ apci3501_eeprom_wait(iobase);
+ tmp = inb(iobase + AMCC_OP_REG_MCSR_NVDATA);
+ apci3501_eeprom_wait(iobase);
+
+ if (i == 0)
+ val |= tmp;
+ else
+ val |= (tmp << 8);
+ }
+
+ return val;
+}
+
+static int apci3501_eeprom_get_ao_n_chan(struct comedi_device *dev)
+{
+ struct apci3501_private *devpriv = dev->private;
+ unsigned long iobase = devpriv->i_IobaseAmcc;
+ unsigned char nfuncs;
+ int i;
+
+ nfuncs = apci3501_eeprom_readw(iobase, 10) & 0xff;
+
+ /* Read functionality details */
+ for (i = 0; i < nfuncs; i++) {
+ unsigned short offset = i * 4;
+ unsigned short addr;
+ unsigned char func;
+ unsigned short val;
+
+ func = apci3501_eeprom_readw(iobase, 12 + offset) & 0x3f;
+ addr = apci3501_eeprom_readw(iobase, 14 + offset);
+
+ if (func == EEPROM_ANALOGOUTPUT) {
+ val = apci3501_eeprom_readw(iobase, addr + 10);
+ return (val >> 4) & 0x3ff;
+ }
+ }
+ return 0;
+}
+
+static int apci3501_eeprom_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ struct apci3501_private *devpriv = dev->private;
+ unsigned short addr = CR_CHAN(insn->chanspec);
+
+ data[0] = apci3501_eeprom_readw(devpriv->i_IobaseAmcc, 2 * addr);
+
+ return insn->n;
+}
+
+static irqreturn_t apci3501_interrupt(int irq, void *d)
+{
+ struct comedi_device *dev = d;
+ struct apci3501_private *devpriv = dev->private;
+ unsigned int ui_Timer_AOWatchdog;
+ unsigned long ul_Command1;
+ int i_temp;
+
+ /* Disable Interrupt */
+ ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
+ ul_Command1 = (ul_Command1 & 0xFFFFF9FDul);
+ outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+
+ ui_Timer_AOWatchdog = inl(dev->iobase + APCI3501_TIMER_IRQ_REG) & 0x1;
+ if ((!ui_Timer_AOWatchdog)) {
+ comedi_error(dev, "IRQ from unknown source");
+ return IRQ_NONE;
+ }
+
+ /* Enable Interrupt Send a signal to from kernel to user space */
+ send_sig(SIGIO, devpriv->tsk_Current, 0);
+ ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
+ ul_Command1 = ((ul_Command1 & 0xFFFFF9FDul) | 1 << 1);
+ outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+ i_temp = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1;
+
+ return IRQ_HANDLED;
+}
+
+static int apci3501_reset(struct comedi_device *dev)
+{
+ unsigned int val;
+ int chan;
+ int ret;
+
+ /* Reset all digital outputs to "0" */
+ outl(0x0, dev->iobase + APCI3501_DO_REG);
+
+ /* Default all analog outputs to 0V (bipolar) */
+ outl(APCI3501_AO_CTRL_BIPOLAR,
+ dev->iobase + APCI3501_AO_CTRL_STATUS_REG);
+ val = APCI3501_AO_DATA_BIPOLAR | APCI3501_AO_DATA_VAL(0);
+
+ /* Set all analog output channels */
+ for (chan = 0; chan < 8; chan++) {
+ ret = apci3501_wait_for_dac(dev);
+ if (ret) {
+ dev_warn(dev->class_dev,
+ "%s: DAC not-ready for channel %i\n",
+ __func__, chan);
+ } else {
+ outl(val | APCI3501_AO_DATA_CHAN(chan),
+ dev->iobase + APCI3501_AO_DATA_REG);
+ }
+ }
+
+ return 0;
+}
+
+static int apci3501_auto_attach(struct comedi_device *dev,
+ unsigned long context_unused)
+{
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ struct apci3501_private *devpriv;
+ struct comedi_subdevice *s;
+ int ao_n_chan;
+ int ret;
+
+ dev->board_name = dev->driver->driver_name;
+
+ devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+ if (!devpriv)
+ return -ENOMEM;
+ dev->private = devpriv;
+
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
+
+ dev->iobase = pci_resource_start(pcidev, 1);
+ devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0);
+
+ ao_n_chan = apci3501_eeprom_get_ao_n_chan(dev);
+
+ if (pcidev->irq > 0) {
+ ret = request_irq(pcidev->irq, apci3501_interrupt, IRQF_SHARED,
+ dev->board_name, dev);
+ if (ret == 0)
+ dev->irq = pcidev->irq;
+ }
+
+ ret = comedi_alloc_subdevices(dev, 5);
+ if (ret)
+ return ret;
+
+ /* Initialize the analog output subdevice */
+ s = &dev->subdevices[0];
+ if (ao_n_chan) {
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
+ s->n_chan = ao_n_chan;
+ s->maxdata = 0x3fff;
+ s->range_table = &apci3501_ao_range;
+ s->insn_write = apci3501_ao_insn_write;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+
+ /* Initialize the digital input subdevice */
+ s = &dev->subdevices[1];
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 2;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = apci3501_di_insn_bits;
+
+ /* Initialize the digital output subdevice */
+ s = &dev->subdevices[2];
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITEABLE;
+ s->n_chan = 2;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = apci3501_do_insn_bits;
+
+ /* Initialize the timer/watchdog subdevice */
+ s = &dev->subdevices[3];
+ s->type = COMEDI_SUBD_TIMER;
+ s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
+ s->n_chan = 1;
+ s->maxdata = 0;
+ s->len_chanlist = 1;
+ s->range_table = &range_digital;
+ s->insn_write = i_APCI3501_StartStopWriteTimerCounterWatchdog;
+ s->insn_read = i_APCI3501_ReadTimerCounterWatchdog;
+ s->insn_config = i_APCI3501_ConfigTimerCounterWatchdog;
+
+ /* Initialize the eeprom subdevice */
+ s = &dev->subdevices[4];
+ s->type = COMEDI_SUBD_MEMORY;
+ s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
+ s->n_chan = 256;
+ s->maxdata = 0xffff;
+ s->insn_read = apci3501_eeprom_insn_read;
+
+ apci3501_reset(dev);
+ return 0;
+}
+
+static void apci3501_detach(struct comedi_device *dev)
+{
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+
+ if (dev->iobase)
+ apci3501_reset(dev);
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+ if (pcidev) {
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
+ }
+}
static struct comedi_driver apci3501_driver = {
.driver_name = "addi_apci_3501",
.module = THIS_MODULE,
- .auto_attach = addi_auto_attach,
- .detach = i_ADDI_Detach,
- .num_names = ARRAY_SIZE(apci3501_boardtypes),
- .board_name = &apci3501_boardtypes[0].pc_DriverName,
- .offset = sizeof(struct addi_board),
+ .auto_attach = apci3501_auto_attach,
+ .detach = apci3501_detach,
};
static int apci3501_pci_probe(struct pci_dev *dev,
@@ -57,19 +448,20 @@ static int apci3501_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &apci3501_driver);
}
-static void apci3501_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
+static DEFINE_PCI_DEVICE_TABLE(apci3501_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3001) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, apci3501_pci_table);
static struct pci_driver apci3501_pci_driver = {
.name = "addi_apci_3501",
.id_table = apci3501_pci_table,
.probe = apci3501_pci_probe,
- .remove = apci3501_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(apci3501_driver, apci3501_pci_driver);
+MODULE_DESCRIPTION("ADDI-DATA APCI-3501 Analog output board");
MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
index 1562347ed64b..09d4b21fce23 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
@@ -1,3 +1,5 @@
+#include <linux/pci.h>
+
#include "../comedidev.h"
#include "comedi_fc.h"
#include "amcc_s5933.h"
@@ -751,11 +753,6 @@ static int apci3xxx_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &apci3xxx_driver);
}
-static void apci3xxx_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(apci3xxx_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3010) },
{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x300f) },
@@ -790,7 +787,7 @@ static struct pci_driver apci3xxx_pci_driver = {
.name = "addi_apci_3xxx",
.id_table = apci3xxx_pci_table,
.probe = apci3xxx_pci_probe,
- .remove = apci3xxx_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(apci3xxx_driver, apci3xxx_pci_driver);
diff --git a/drivers/staging/comedi/drivers/addi_watchdog.c b/drivers/staging/comedi/drivers/addi_watchdog.c
new file mode 100644
index 000000000000..375ab665e091
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi_watchdog.c
@@ -0,0 +1,172 @@
+/*
+ * COMEDI driver for the watchdog subdevice found on some addi-data boards
+ * Copyright (c) 2013 H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * Based on implementations in various addi-data COMEDI drivers.
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1998 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.
+ */
+
+#include "../comedidev.h"
+#include "addi_watchdog.h"
+
+/*
+ * Register offsets/defines for the addi-data watchdog
+ */
+#define ADDI_WDOG_REG 0x00
+#define ADDI_WDOG_RELOAD_REG 0x04
+#define ADDI_WDOG_TIMEBASE 0x08
+#define ADDI_WDOG_CTRL_REG 0x0c
+#define ADDI_WDOG_CTRL_ENABLE (1 << 0)
+#define ADDI_WDOG_CTRL_SW_TRIG (1 << 9)
+#define ADDI_WDOG_STATUS_REG 0x10
+#define ADDI_WDOG_STATUS_ENABLED (1 << 0)
+#define ADDI_WDOG_STATUS_SW_TRIG (1 << 1)
+
+struct addi_watchdog_private {
+ unsigned long iobase;
+ unsigned int wdog_ctrl;
+};
+
+/*
+ * The watchdog subdevice is configured with two INSN_CONFIG instructions:
+ *
+ * Enable the watchdog and set the reload timeout:
+ * data[0] = INSN_CONFIG_ARM
+ * data[1] = timeout reload value
+ *
+ * Disable the watchdog:
+ * data[0] = INSN_CONFIG_DISARM
+ */
+static int addi_watchdog_insn_config(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ struct addi_watchdog_private *spriv = s->private;
+ unsigned int reload;
+
+ switch (data[0]) {
+ case INSN_CONFIG_ARM:
+ spriv->wdog_ctrl = ADDI_WDOG_CTRL_ENABLE;
+ reload = data[1] & s->maxdata;
+ outl(reload, spriv->iobase + ADDI_WDOG_RELOAD_REG);
+
+ /* Time base is 20ms, let the user know the timeout */
+ dev_info(dev->class_dev, "watchdog enabled, timeout:%dms\n",
+ 20 * reload + 20);
+ break;
+ case INSN_CONFIG_DISARM:
+ spriv->wdog_ctrl = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ outl(spriv->wdog_ctrl, spriv->iobase + ADDI_WDOG_CTRL_REG);
+
+ return insn->n;
+}
+
+static int addi_watchdog_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ struct addi_watchdog_private *spriv = s->private;
+ int i;
+
+ for (i = 0; i < insn->n; i++)
+ data[i] = inl(spriv->iobase + ADDI_WDOG_STATUS_REG);
+
+ return insn->n;
+}
+
+static int addi_watchdog_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ struct addi_watchdog_private *spriv = s->private;
+ int i;
+
+ if (spriv->wdog_ctrl == 0) {
+ dev_warn(dev->class_dev, "watchdog is disabled\n");
+ return -EINVAL;
+ }
+
+ /* "ping" the watchdog */
+ for (i = 0; i < insn->n; i++) {
+ outl(spriv->wdog_ctrl | ADDI_WDOG_CTRL_SW_TRIG,
+ spriv->iobase + ADDI_WDOG_CTRL_REG);
+ }
+
+ return insn->n;
+}
+
+void addi_watchdog_reset(unsigned long iobase)
+{
+ outl(0x0, iobase + ADDI_WDOG_CTRL_REG);
+ outl(0x0, iobase + ADDI_WDOG_RELOAD_REG);
+}
+EXPORT_SYMBOL_GPL(addi_watchdog_reset);
+
+int addi_watchdog_init(struct comedi_subdevice *s, unsigned long iobase)
+{
+ struct addi_watchdog_private *spriv;
+
+ spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
+ if (!spriv)
+ return -ENOMEM;
+
+ spriv->iobase = iobase;
+
+ s->private = spriv;
+
+ s->type = COMEDI_SUBD_TIMER;
+ s->subdev_flags = SDF_WRITEABLE;
+ s->n_chan = 1;
+ s->maxdata = 0xff;
+ s->insn_config = addi_watchdog_insn_config;
+ s->insn_read = addi_watchdog_insn_read;
+ s->insn_write = addi_watchdog_insn_write;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(addi_watchdog_init);
+
+void addi_watchdog_cleanup(struct comedi_subdevice *s)
+{
+ kfree(s->private);
+}
+EXPORT_SYMBOL_GPL(addi_watchdog_cleanup);
+
+static int __init addi_watchdog_module_init(void)
+{
+ return 0;
+}
+module_init(addi_watchdog_module_init);
+
+static void __exit addi_watchdog_module_exit(void)
+{
+}
+module_exit(addi_watchdog_module_exit);
+
+MODULE_DESCRIPTION("ADDI-DATA Watchdog subdevice");
+MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_watchdog.h b/drivers/staging/comedi/drivers/addi_watchdog.h
new file mode 100644
index 000000000000..f374a7bff44d
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi_watchdog.h
@@ -0,0 +1,10 @@
+#ifndef _ADDI_WATCHDOG_H
+#define _ADDI_WATCHDOG_H
+
+#include "../comedidev.h"
+
+void addi_watchdog_reset(unsigned long iobase);
+int addi_watchdog_init(struct comedi_subdevice *, unsigned long iobase);
+void addi_watchdog_cleanup(struct comedi_subdevice *s);
+
+#endif
diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
index 9a56eed3910f..7b3e331616ed 100644
--- a/drivers/staging/comedi/drivers/adl_pci6208.c
+++ b/drivers/staging/comedi/drivers/adl_pci6208.c
@@ -42,6 +42,8 @@ References:
- adl_pci9118.c
*/
+#include <linux/pci.h>
+
#include "../comedidev.h"
/*
@@ -270,11 +272,6 @@ static int adl_pci6208_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &adl_pci6208_driver);
}
-static void adl_pci6208_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(adl_pci6208_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI6208) },
{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI6216) },
@@ -286,7 +283,7 @@ static struct pci_driver adl_pci6208_pci_driver = {
.name = "adl_pci6208",
.id_table = adl_pci6208_pci_table,
.probe = adl_pci6208_pci_probe,
- .remove = adl_pci6208_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(adl_pci6208_driver, adl_pci6208_pci_driver);
diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c
index 772edc02f5ce..f27f48e6e702 100644
--- a/drivers/staging/comedi/drivers/adl_pci7x3x.c
+++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c
@@ -38,12 +38,6 @@ 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
@@ -51,9 +45,11 @@ 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
+Configuration Options: not applicable, uses comedi PCI auto config
*/
+#include <linux/pci.h>
+
#include "../comedidev.h"
/*
@@ -302,11 +298,6 @@ static int adl_pci7x3x_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &adl_pci7x3x_driver);
}
-static void 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) },
@@ -322,7 +313,7 @@ static struct pci_driver adl_pci7x3x_pci_driver = {
.name = "adl_pci7x3x",
.id_table = adl_pci7x3x_pci_table,
.probe = adl_pci7x3x_pci_probe,
- .remove = adl_pci7x3x_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(adl_pci7x3x_driver, adl_pci7x3x_pci_driver);
diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
index 4dd9d707a79d..d06b83f38653 100644
--- a/drivers/staging/comedi/drivers/adl_pci8164.c
+++ b/drivers/staging/comedi/drivers/adl_pci8164.c
@@ -30,9 +30,11 @@ Updated: Mon, 14 Apr 2008 15:10:32 +0100
Configuration Options: not applicable, uses PCI auto config
*/
-#include "../comedidev.h"
#include <linux/kernel.h>
+#include <linux/pci.h>
#include <linux/delay.h>
+
+#include "../comedidev.h"
#include "comedi_fc.h"
#include "8253.h"
@@ -62,35 +64,35 @@ static void adl_pci8164_insn_read(struct comedi_device *dev,
char *action, unsigned short offset)
{
int axis, axis_reg;
- char *axisname;
+ char axisname;
axis = CR_CHAN(insn->chanspec);
switch (axis) {
case 0:
axis_reg = PCI8164_AXIS_X;
- axisname = "X";
+ axisname = 'X';
break;
case 1:
axis_reg = PCI8164_AXIS_Y;
- axisname = "Y";
+ axisname = 'Y';
break;
case 2:
axis_reg = PCI8164_AXIS_Z;
- axisname = "Z";
+ axisname = 'Z';
break;
case 3:
axis_reg = PCI8164_AXIS_U;
- axisname = "U";
+ axisname = 'U';
break;
default:
axis_reg = PCI8164_AXIS_X;
- axisname = "X";
+ axisname = 'X';
}
data[0] = inw(dev->iobase + axis_reg + offset);
dev_dbg(dev->class_dev,
- "pci8164 %s read -> %04X:%04X on axis %s\n",
+ "pci8164 %s read -> %04X:%04X on axis %c\n",
action, data[0], data[1], axisname);
}
@@ -142,36 +144,36 @@ static void adl_pci8164_insn_out(struct comedi_device *dev,
{
unsigned int axis, axis_reg;
- char *axisname;
+ char axisname;
axis = CR_CHAN(insn->chanspec);
switch (axis) {
case 0:
axis_reg = PCI8164_AXIS_X;
- axisname = "X";
+ axisname = 'X';
break;
case 1:
axis_reg = PCI8164_AXIS_Y;
- axisname = "Y";
+ axisname = 'Y';
break;
case 2:
axis_reg = PCI8164_AXIS_Z;
- axisname = "Z";
+ axisname = 'Z';
break;
case 3:
axis_reg = PCI8164_AXIS_U;
- axisname = "U";
+ axisname = 'U';
break;
default:
axis_reg = PCI8164_AXIS_X;
- axisname = "X";
+ axisname = 'X';
}
outw(data[0], dev->iobase + axis_reg + offset);
dev_dbg(dev->class_dev,
- "pci8164 %s write -> %04X:%04X on axis %s\n",
+ "pci8164 %s write -> %04X:%04X on axis %c\n",
action, data[0], data[1], axisname);
}
@@ -298,11 +300,6 @@ static int adl_pci8164_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &adl_pci8164_driver);
}
-static void adl_pci8164_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(adl_pci8164_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI8164) },
{0}
@@ -313,7 +310,7 @@ static struct pci_driver adl_pci8164_pci_driver = {
.name = "adl_pci8164",
.id_table = adl_pci8164_pci_table,
.probe = adl_pci8164_pci_probe,
- .remove = adl_pci8164_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(adl_pci8164_driver, adl_pci8164_pci_driver);
diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
index a339b9dd27cf..eeb10ec7f178 100644
--- a/drivers/staging/comedi/drivers/adl_pci9111.c
+++ b/drivers/staging/comedi/drivers/adl_pci9111.c
@@ -68,11 +68,12 @@ TODO:
*/
-#include "../comedidev.h"
-
+#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include "../comedidev.h"
+
#include "8253.h"
#include "comedi_fc.h"
@@ -963,11 +964,6 @@ static int pci9111_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &adl_pci9111_driver);
}
-static void pci9111_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID) },
/* { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID) }, */
@@ -979,7 +975,7 @@ static struct pci_driver adl_pci9111_pci_driver = {
.name = "adl_pci9111",
.id_table = pci9111_pci_table,
.probe = pci9111_pci_probe,
- .remove = pci9111_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(adl_pci9111_driver, adl_pci9111_pci_driver);
diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
index b6dda809bd13..4dbac7459a48 100644
--- a/drivers/staging/comedi/drivers/adl_pci9118.c
+++ b/drivers/staging/comedi/drivers/adl_pci9118.c
@@ -76,13 +76,15 @@ Configuration options:
* attachment if necessary, and possibly to set other options supported by
* manual attachment.
*/
-#include "../comedidev.h"
+#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/gfp.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include "../comedidev.h"
+
#include "amcc_s5933.h"
#include "8253.h"
#include "comedi_fc.h"
@@ -808,7 +810,7 @@ static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
*tim2 = *div1 * devpriv->i8254_osc_base;
/* real convert timer */
- if (usessh & (chnsshfront == 0)) /* use BSSH signal */
+ if (usessh && (chnsshfront == 0)) /* use BSSH signal */
if (*div2 < (chans + 2))
*div2 = chans + 2;
@@ -2225,11 +2227,6 @@ static int adl_pci9118_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &adl_pci9118_driver);
}
-static void adl_pci9118_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(adl_pci9118_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMCC, 0x80d9) },
{ 0 }
@@ -2240,7 +2237,7 @@ static struct pci_driver adl_pci9118_pci_driver = {
.name = "adl_pci9118",
.id_table = adl_pci9118_pci_table,
.probe = adl_pci9118_pci_probe,
- .remove = adl_pci9118_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(adl_pci9118_driver, adl_pci9118_pci_driver);
diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
index a6fd8c2c16ca..3d788c76d648 100644
--- a/drivers/staging/comedi/drivers/adv_pci1710.c
+++ b/drivers/staging/comedi/drivers/adv_pci1710.c
@@ -41,6 +41,7 @@ Configuration options:
device will be used.
*/
+#include <linux/pci.h>
#include <linux/interrupt.h>
#include "../comedidev.h"
@@ -1402,11 +1403,6 @@ static int adv_pci1710_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &adv_pci1710_driver);
}
-static void adv_pci1710_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(adv_pci1710_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1710) },
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1711) },
@@ -1421,7 +1417,7 @@ static struct pci_driver adv_pci1710_pci_driver = {
.name = "adv_pci1710",
.id_table = adv_pci1710_pci_table,
.probe = adv_pci1710_pci_probe,
- .remove = adv_pci1710_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(adv_pci1710_driver, adv_pci1710_pci_driver);
diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
index 5af73146dd85..02ce55a01d2a 100644
--- a/drivers/staging/comedi/drivers/adv_pci1723.c
+++ b/drivers/staging/comedi/drivers/adv_pci1723.c
@@ -48,6 +48,8 @@ TODO:
3. Implement calibration.
*/
+#include <linux/pci.h>
+
#include "../comedidev.h"
/* all the registers for the pci1723 board */
@@ -327,11 +329,6 @@ static int adv_pci1723_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &adv_pci1723_driver);
}
-static void adv_pci1723_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(adv_pci1723_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1723) },
{ 0 }
@@ -342,7 +339,7 @@ static struct pci_driver adv_pci1723_pci_driver = {
.name = "adv_pci1723",
.id_table = adv_pci1723_pci_table,
.probe = adv_pci1723_pci_probe,
- .remove = adv_pci1723_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(adv_pci1723_driver, adv_pci1723_pci_driver);
diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
index 05a663e970c6..338c43e716ba 100644
--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
+++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
@@ -29,10 +29,11 @@ Configuration options:
*/
-#include "../comedidev.h"
-
+#include <linux/pci.h>
#include <linux/delay.h>
+#include "../comedidev.h"
+
#include "8255.h"
#include "8253.h"
@@ -1206,11 +1207,6 @@ static int adv_pci_dio_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &adv_pci_dio_driver);
}
-static void adv_pci_dio_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(adv_pci_dio_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1730) },
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1733) },
@@ -1234,7 +1230,7 @@ static struct pci_driver adv_pci_dio_pci_driver = {
.name = "adv_pci_dio",
.id_table = adv_pci_dio_pci_table,
.probe = adv_pci_dio_pci_probe,
- .remove = adv_pci_dio_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(adv_pci_dio_driver, adv_pci_dio_pci_driver);
diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
index 5f309ba88a1a..7c53dea12c76 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200.c
@@ -258,6 +258,7 @@
* order they appear in the channel list.
*/
+#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
@@ -1104,10 +1105,9 @@ dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
struct dio200_subdev_intr *subpriv;
subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
- if (!subpriv) {
- dev_err(dev->class_dev, "error! out of memory!\n");
+ if (!subpriv)
return -ENOMEM;
- }
+
subpriv->ofs = offset;
subpriv->valid_isns = valid_isns;
spin_lock_init(&subpriv->spinlock);
@@ -1443,10 +1443,8 @@ dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
unsigned int chan;
subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
- if (!subpriv) {
- dev_err(dev->class_dev, "error! out of memory!\n");
+ if (!subpriv)
return -ENOMEM;
- }
s->private = subpriv;
s->type = COMEDI_SUBD_COUNTER;
@@ -1977,8 +1975,7 @@ static int dio200_auto_attach(struct comedi_device *dev,
devpriv->io.u.iobase = (unsigned long)base;
devpriv->io.regtype = io_regtype;
}
- switch (thisboard->model)
- {
+ switch (thisboard->model) {
case pcie215_model:
case pcie236_model:
case pcie296_model:
@@ -2079,16 +2076,11 @@ static int amplc_dio200_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &amplc_dio200_driver);
}
-static void amplc_dio200_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static struct pci_driver amplc_dio200_pci_driver = {
.name = DIO200_DRIVER_NAME,
.id_table = dio200_pci_table,
.probe = &amplc_dio200_pci_probe,
- .remove = &amplc_dio200_pci_remove
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(amplc_dio200_driver, amplc_dio200_pci_driver);
#else
diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
index 289835419577..479e10fddd22 100644
--- a/drivers/staging/comedi/drivers/amplc_pc236.c
+++ b/drivers/staging/comedi/drivers/amplc_pc236.c
@@ -52,6 +52,7 @@ the IRQ jumper. If no interrupt is connected, then subdevice 1 is
unused.
*/
+#include <linux/pci.h>
#include <linux/interrupt.h>
#include "../comedidev.h"
@@ -614,16 +615,11 @@ static int amplc_pc236_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &amplc_pc236_driver);
}
-static void amplc_pc236_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static struct pci_driver amplc_pc236_pci_driver = {
.name = PC236_DRIVER_NAME,
.id_table = pc236_pci_table,
.probe = &amplc_pc236_pci_probe,
- .remove = &amplc_pc236_pci_remove
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(amplc_pc236_driver, amplc_pc236_pci_driver);
diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
index dfbff77cd795..11c1f4764eac 100644
--- a/drivers/staging/comedi/drivers/amplc_pc263.c
+++ b/drivers/staging/comedi/drivers/amplc_pc263.c
@@ -44,6 +44,8 @@ connected to a reed-relay. Relay contacts are closed when output is 1.
The state of the outputs can be read.
*/
+#include <linux/pci.h>
+
#include "../comedidev.h"
#define PC263_DRIVER_NAME "amplc_pc263"
@@ -372,16 +374,11 @@ static int amplc_pc263_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &amplc_pc263_driver);
}
-static void amplc_pc263_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static struct pci_driver amplc_pc263_pci_driver = {
.name = PC263_DRIVER_NAME,
.id_table = pc263_pci_table,
.probe = &amplc_pc263_pci_probe,
- .remove = &amplc_pc263_pci_remove
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(amplc_pc263_driver, amplc_pc263_pci_driver);
#else
diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
index 6e2566a2dd57..c9da4cd74baa 100644
--- a/drivers/staging/comedi/drivers/amplc_pci224.c
+++ b/drivers/staging/comedi/drivers/amplc_pci224.c
@@ -103,6 +103,7 @@ Caveats:
correctly.
*/
+#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
@@ -1512,11 +1513,6 @@ static int amplc_pci224_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &amplc_pci224_driver);
}
-static void amplc_pci224_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(amplc_pci224_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI224) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI234) },
@@ -1528,7 +1524,7 @@ static struct pci_driver amplc_pci224_pci_driver = {
.name = "amplc_pci224",
.id_table = amplc_pci224_pci_table,
.probe = amplc_pci224_pci_probe,
- .remove = amplc_pci224_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(amplc_pci224_driver, amplc_pci224_pci_driver);
diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
index 366c68be56bd..e2244c6e536b 100644
--- a/drivers/staging/comedi/drivers/amplc_pci230.c
+++ b/drivers/staging/comedi/drivers/amplc_pci230.c
@@ -188,11 +188,12 @@ Support for PCI230+/260+, more triggered scan functionality, and workarounds
for (or detection of) various hardware problems added by Ian Abbott.
*/
-#include "../comedidev.h"
-
+#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include "../comedidev.h"
+
#include "comedi_fc.h"
#include "8253.h"
#include "8255.h"
@@ -2863,11 +2864,6 @@ static int amplc_pci230_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &amplc_pci230_driver);
}
-static void amplc_pci230_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(amplc_pci230_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI230) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI260) },
@@ -2879,7 +2875,7 @@ static struct pci_driver amplc_pci230_pci_driver = {
.name = "amplc_pci230",
.id_table = amplc_pci230_pci_table,
.probe = amplc_pci230_pci_probe,
- .remove = amplc_pci230_pci_remove
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(amplc_pci230_driver, amplc_pci230_pci_driver);
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index 93731de1f2b1..f874fff44523 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -40,9 +40,10 @@ Status: experimental
#include <linux/interrupt.h>
#include <linux/slab.h>
-#include "../comedidev.h"
#include <linux/delay.h>
+#include "../comedidev.h"
+
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
@@ -89,8 +90,6 @@ struct das16cs_private {
unsigned short status2;
};
-static struct pcmcia_device *cur_dev;
-
static const struct comedi_lrange das16cs_ai_range = {
4, {
BIP_RANGE(10),
@@ -383,46 +382,45 @@ static int das16cs_dio_insn_config(struct comedi_device *dev,
return insn->n;
}
-static const struct das16cs_board *das16cs_probe(struct comedi_device *dev,
- struct pcmcia_device *link)
+static const void *das16cs_find_boardinfo(struct comedi_device *dev,
+ struct pcmcia_device *link)
{
+ const struct das16cs_board *board;
int i;
for (i = 0; i < ARRAY_SIZE(das16cs_boards); i++) {
- if (das16cs_boards[i].device_id == link->card_id)
- return das16cs_boards + i;
+ board = &das16cs_boards[i];
+ if (board->device_id == link->card_id)
+ return board;
}
- dev_dbg(dev->class_dev, "unknown board!\n");
-
return NULL;
}
-static int das16cs_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int das16cs_auto_attach(struct comedi_device *dev,
+ unsigned long context)
{
- const struct das16cs_board *thisboard;
+ struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
+ const struct das16cs_board *board;
struct das16cs_private *devpriv;
- struct pcmcia_device *link;
struct comedi_subdevice *s;
int ret;
- link = cur_dev; /* XXX hack */
- if (!link)
- return -EIO;
-
- dev->board_ptr = das16cs_probe(dev, link);
- if (!dev->board_ptr)
- return -EIO;
- thisboard = comedi_board(dev);
-
- dev->board_name = thisboard->name;
+ board = das16cs_find_boardinfo(dev, link);
+ if (!board)
+ return -ENODEV;
+ dev->board_ptr = board;
+ dev->board_name = board->name;
+ link->config_flags |= CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
+ ret = comedi_pcmcia_enable(dev, NULL);
+ if (ret)
+ return ret;
dev->iobase = link->resource[0]->start;
- ret = request_irq(link->irq, das16cs_interrupt,
- IRQF_SHARED, "cb_das16_cs", dev);
- if (ret < 0)
+ link->priv = dev;
+ ret = pcmcia_request_irq(link, das16cs_interrupt);
+ if (ret)
return ret;
dev->irq = link->irq;
@@ -450,10 +448,10 @@ static int das16cs_attach(struct comedi_device *dev,
s = &dev->subdevices[1];
/* analog output subdevice */
- if (thisboard->n_ao_chans) {
+ if (board->n_ao_chans) {
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
- s->n_chan = thisboard->n_ao_chans;
+ s->n_chan = board->n_ao_chans;
s->maxdata = 0xffff;
s->range_table = &range_bipolar10;
s->insn_write = &das16cs_ao_winsn;
@@ -479,58 +477,16 @@ static int das16cs_attach(struct comedi_device *dev,
return 0;
}
-static void das16cs_detach(struct comedi_device *dev)
-{
- if (dev->irq)
- free_irq(dev->irq, dev);
-}
-
static struct comedi_driver driver_das16cs = {
.driver_name = "cb_das16_cs",
.module = THIS_MODULE,
- .attach = das16cs_attach,
- .detach = das16cs_detach,
+ .auto_attach = das16cs_auto_attach,
+ .detach = comedi_pcmcia_disable,
};
-static int das16cs_pcmcia_config_loop(struct pcmcia_device *p_dev,
- void *priv_data)
-{
- if (p_dev->config_index == 0)
- return -EINVAL;
-
- return pcmcia_request_io(p_dev);
-}
-
static int das16cs_pcmcia_attach(struct pcmcia_device *link)
{
- int ret;
-
- /* Do we need to allocate an interrupt? */
- link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
-
- ret = pcmcia_loop_config(link, das16cs_pcmcia_config_loop, NULL);
- if (ret)
- goto failed;
-
- if (!link->irq)
- goto failed;
-
- ret = pcmcia_enable_device(link);
- if (ret)
- goto failed;
-
- cur_dev = link;
- return 0;
-
-failed:
- pcmcia_disable_device(link);
- return ret;
-}
-
-static void das16cs_pcmcia_detach(struct pcmcia_device *link)
-{
- pcmcia_disable_device(link);
- cur_dev = NULL;
+ return comedi_pcmcia_auto_config(link, &driver_das16cs);
}
static const struct pcmcia_device_id das16cs_id_table[] = {
@@ -543,35 +499,11 @@ MODULE_DEVICE_TABLE(pcmcia, das16cs_id_table);
static struct pcmcia_driver das16cs_driver = {
.name = "cb_das16_cs",
.owner = THIS_MODULE,
- .probe = das16cs_pcmcia_attach,
- .remove = das16cs_pcmcia_detach,
.id_table = das16cs_id_table,
+ .probe = das16cs_pcmcia_attach,
+ .remove = comedi_pcmcia_auto_unconfig,
};
-
-static int __init das16cs_init(void)
-{
- int ret;
-
- ret = comedi_driver_register(&driver_das16cs);
- if (ret < 0)
- return ret;
-
- ret = pcmcia_register_driver(&das16cs_driver);
- if (ret < 0) {
- comedi_driver_unregister(&driver_das16cs);
- return ret;
- }
-
- return 0;
-}
-module_init(das16cs_init);
-
-static void __exit das16cs_exit(void)
-{
- pcmcia_unregister_driver(&das16cs_driver);
- comedi_driver_unregister(&driver_das16cs);
-}
-module_exit(das16cs_exit);
+module_comedi_pcmcia_driver(driver_das16cs, das16cs_driver);
MODULE_AUTHOR("David A. Schleef <ds@schleef.org>");
MODULE_DESCRIPTION("Comedi driver for Computer Boards PC-CARD DAS16/16");
diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
index aed68639cc9a..79c72118a090 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas.c
@@ -67,10 +67,12 @@ TODO:
analog triggering on 1602 series
*/
-#include "../comedidev.h"
+#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include "../comedidev.h"
+
#include "8253.h"
#include "8255.h"
#include "amcc_s5933.h"
@@ -1632,11 +1634,6 @@ static int cb_pcidas_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &cb_pcidas_driver);
}
-static void cb_pcidas_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(cb_pcidas_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0001) },
{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x000f) },
@@ -1654,7 +1651,7 @@ static struct pci_driver cb_pcidas_pci_driver = {
.name = "cb_pcidas",
.id_table = cb_pcidas_pci_table,
.probe = cb_pcidas_pci_probe,
- .remove = cb_pcidas_pci_remove
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(cb_pcidas_driver, cb_pcidas_pci_driver);
diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
index d72b46cc06bc..9f3112cb7a21 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
@@ -87,10 +87,12 @@ TODO:
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include "../comedidev.h"
+#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include "../comedidev.h"
+
#include "8253.h"
#include "8255.h"
#include "plx9080.h"
@@ -3299,7 +3301,6 @@ static int prep_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
num_bytes = load_ao_dma_buffer(dev, cmd);
if (num_bytes == 0)
return -1;
- if (num_bytes >= DMA_BUFFER_SIZE) ;
load_ao_dma(dev, cmd);
dma_start_sync(dev, 0);
@@ -4220,11 +4221,6 @@ static int cb_pcidas64_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &cb_pcidas64_driver);
}
-static void cb_pcidas64_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(cb_pcidas64_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001d) },
{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001e) },
@@ -4253,7 +4249,7 @@ static struct pci_driver cb_pcidas64_pci_driver = {
.name = "cb_pcidas64",
.id_table = cb_pcidas64_pci_table,
.probe = cb_pcidas64_pci_probe,
- .remove = cb_pcidas64_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(cb_pcidas64_driver, cb_pcidas64_pci_driver);
diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
index 7c6029a8c3e1..e2cadc728455 100644
--- a/drivers/staging/comedi/drivers/cb_pcidda.c
+++ b/drivers/staging/comedi/drivers/cb_pcidda.c
@@ -41,6 +41,8 @@
* Only simple analog output writing is supported.
*/
+#include <linux/pci.h>
+
#include "../comedidev.h"
#include "comedi_fc.h"
@@ -438,11 +440,6 @@ static int cb_pcidda_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &cb_pcidda_driver);
}
-static void cb_pcidda_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(cb_pcidda_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA02_12) },
{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA04_12) },
@@ -458,7 +455,7 @@ static struct pci_driver cb_pcidda_pci_driver = {
.name = "cb_pcidda",
.id_table = cb_pcidda_pci_table,
.probe = cb_pcidda_pci_probe,
- .remove = cb_pcidda_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(cb_pcidda_driver, cb_pcidda_pci_driver);
diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
index b43a5f80ac26..aae063ca85a0 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
@@ -40,11 +40,12 @@ No interrupts, multi channel or FIFO AI, although the card looks like it could s
See http://www.mccdaq.com/PDFs/Manuals/pcim-das1602-16.pdf for more details.
*/
-#include "../comedidev.h"
-
+#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include "../comedidev.h"
+
#include "plx9052.h"
#include "8255.h"
@@ -299,11 +300,6 @@ static int cb_pcimdas_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &cb_pcimdas_driver);
}
-static void cb_pcimdas_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(cb_pcimdas_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0056) },
{ 0 }
@@ -314,7 +310,7 @@ static struct pci_driver cb_pcimdas_pci_driver = {
.name = "cb_pcimdas",
.id_table = cb_pcimdas_pci_table,
.probe = cb_pcimdas_pci_probe,
- .remove = cb_pcimdas_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(cb_pcimdas_driver, cb_pcimdas_pci_driver);
diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
index 699b84f54cc7..63cfbaf3a3fe 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
@@ -79,6 +79,8 @@ Configuration Options: not applicable, uses PCI auto config
-Calin Culianu <calin@ajvar.org>
*/
+#include <linux/pci.h>
+
#include "../comedidev.h"
#include "8255.h"
@@ -222,11 +224,6 @@ static int cb_pcimdda_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &cb_pcimdda_driver);
}
-static void cb_pcimdda_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(cb_pcimdda_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_ID_PCIM_DDA06_16) },
{ 0 }
@@ -237,7 +234,7 @@ static struct pci_driver cb_pcimdda_driver_pci_driver = {
.name = "cb_pcimdda",
.id_table = cb_pcimdda_pci_table,
.probe = cb_pcimdda_pci_probe,
- .remove = cb_pcimdda_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(cb_pcimdda_driver, cb_pcimdda_driver_pci_driver);
diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c
index 31515999bb97..1bb53816eca3 100644
--- a/drivers/staging/comedi/drivers/comedi_bond.c
+++ b/drivers/staging/comedi/drivers/comedi_bond.c
@@ -245,10 +245,9 @@ static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
bdev = kmalloc(sizeof(*bdev), GFP_KERNEL);
- if (!bdev) {
- dev_err(dev->class_dev, "Out of memory\n");
+ if (!bdev)
return 0;
- }
+
bdev->dev = d;
bdev->minor = minor;
bdev->subdev = sdev;
diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
index 01de996239f1..270fea5c6b51 100644
--- a/drivers/staging/comedi/drivers/comedi_test.c
+++ b/drivers/staging/comedi/drivers/comedi_test.c
@@ -62,15 +62,14 @@ zero volts).
/* Data unique to this driver */
struct waveform_private {
struct timer_list timer;
- struct timeval last; /* time at which last timer interrupt occurred */
+ struct timeval last; /* time last timer interrupt occurred */
unsigned int uvolt_amplitude; /* waveform amplitude in microvolts */
unsigned long usec_period; /* waveform period in microseconds */
- unsigned long usec_current; /* current time (modulo waveform period) */
- unsigned long usec_remainder; /* usec since last scan; */
- unsigned long ai_count; /* number of conversions remaining */
+ unsigned long usec_current; /* current time (mod waveform period) */
+ unsigned long usec_remainder; /* usec since last scan */
+ unsigned long ai_count; /* number of conversions remaining */
unsigned int scan_period; /* scan period in usec */
unsigned int convert_period; /* conversion period in usec */
- unsigned timer_running:1;
unsigned int ao_loopbacks[N_CHANS];
};
@@ -86,8 +85,9 @@ static const struct comedi_lrange waveform_ai_ranges = {
}
};
-static short fake_sawtooth(struct comedi_device *dev, unsigned int range_index,
- unsigned long current_time)
+static unsigned 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;
@@ -110,9 +110,9 @@ static short fake_sawtooth(struct comedi_device *dev, unsigned int range_index,
return offset + value;
}
-static short fake_squarewave(struct comedi_device *dev,
- unsigned int range_index,
- unsigned long current_time)
+static unsigned 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;
@@ -132,15 +132,17 @@ static short fake_squarewave(struct comedi_device *dev,
return offset + value;
}
-static short fake_flatline(struct comedi_device *dev, unsigned int range_index,
- unsigned long current_time)
+static unsigned short fake_flatline(struct comedi_device *dev,
+ unsigned int range_index,
+ unsigned long current_time)
{
return dev->read_subdev->maxdata / 2;
}
/* generates a different waveform depending on what channel is read */
-static short fake_waveform(struct comedi_device *dev, unsigned int channel,
- unsigned int range, unsigned long current_time)
+static unsigned short fake_waveform(struct comedi_device *dev,
+ unsigned int channel, unsigned int range,
+ unsigned long current_time)
{
enum {
SAWTOOTH_CHAN,
@@ -176,6 +178,7 @@ static void waveform_ai_interrupt(unsigned long arg)
unsigned long elapsed_time;
unsigned int num_scans;
struct timeval now;
+ bool stopping = false;
do_gettimeofday(&now);
@@ -189,37 +192,35 @@ static void waveform_ai_interrupt(unsigned long arg)
(devpriv->usec_remainder + elapsed_time) % devpriv->scan_period;
async->events = 0;
+ if (cmd->stop_src == TRIG_COUNT) {
+ unsigned int remaining = cmd->stop_arg - devpriv->ai_count;
+ if (num_scans >= remaining) {
+ /* about to finish */
+ num_scans = remaining;
+ stopping = true;
+ }
+ }
+
for (i = 0; i < num_scans; i++) {
for (j = 0; j < cmd->chanlist_len; j++) {
- cfc_write_to_buffer(dev->read_subdev,
- fake_waveform(dev,
- CR_CHAN(cmd->
- chanlist[j]),
- CR_RANGE(cmd->
- chanlist[j]),
- devpriv->
- usec_current +
- i *
- devpriv->scan_period +
- j *
- devpriv->
- convert_period));
- }
- devpriv->ai_count++;
- if (cmd->stop_src == TRIG_COUNT
- && devpriv->ai_count >= cmd->stop_arg) {
- async->events |= COMEDI_CB_EOA;
- break;
+ unsigned short sample;
+ sample = fake_waveform(dev, CR_CHAN(cmd->chanlist[j]),
+ CR_RANGE(cmd->chanlist[j]),
+ devpriv->usec_current +
+ i * devpriv->scan_period +
+ j * devpriv->convert_period);
+ cfc_write_to_buffer(dev->read_subdev, sample);
}
}
+ devpriv->ai_count += i;
devpriv->usec_current += elapsed_time;
devpriv->usec_current %= devpriv->usec_period;
- if ((async->events & COMEDI_CB_EOA) == 0 && devpriv->timer_running)
- mod_timer(&devpriv->timer, jiffies + 1);
+ if (stopping)
+ async->events |= COMEDI_CB_EOA;
else
- del_timer(&devpriv->timer);
+ mod_timer(&devpriv->timer, jiffies + 1);
comedi_event(dev, dev->read_subdev);
}
@@ -317,7 +318,6 @@ static int waveform_ai_cmd(struct comedi_device *dev,
return -1;
}
- devpriv->timer_running = 1;
devpriv->ai_count = 0;
devpriv->scan_period = cmd->scan_begin_arg / nano_per_micro;
@@ -344,7 +344,6 @@ static int waveform_ai_cancel(struct comedi_device *dev,
{
struct waveform_private *devpriv = dev->private;
- devpriv->timer_running = 0;
del_timer_sync(&devpriv->timer);
return 0;
}
diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
index 1a18fa37bfd0..182dea669ef2 100644
--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
+++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
@@ -30,6 +30,8 @@ Status: works
Configuration Options: not applicable, uses comedi PCI auto config
*/
+#include <linux/pci.h>
+
#include "../comedidev.h"
#define PCI_DEVICE_ID_PIO1616L 0x8172
@@ -130,11 +132,6 @@ static int contec_pci_dio_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &contec_pci_dio_driver);
}
-static void contec_pci_dio_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(contec_pci_dio_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_CONTEC, PCI_DEVICE_ID_PIO1616L) },
{ 0 }
@@ -145,7 +142,7 @@ static struct pci_driver contec_pci_dio_pci_driver = {
.name = "contec_pci_dio",
.id_table = contec_pci_dio_pci_table,
.probe = contec_pci_dio_pci_probe,
- .remove = contec_pci_dio_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(contec_pci_dio_driver, contec_pci_dio_pci_driver);
diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
index 992e557e6ae1..50b450f09c65 100644
--- a/drivers/staging/comedi/drivers/daqboard2000.c
+++ b/drivers/staging/comedi/drivers/daqboard2000.c
@@ -107,12 +107,13 @@ Configuration options: not applicable, uses PCI auto config
*/
-#include "../comedidev.h"
-
+#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/firmware.h>
+#include "../comedidev.h"
+
#include "8255.h"
#define DAQBOARD2000_FIRMWARE "daqboard2000_firmware.bin"
@@ -485,7 +486,7 @@ static void daqboard2000_pulseProgPin(struct comedi_device *dev)
writel(DAQBOARD2000_SECRProgPinHi, devpriv->plx + 0x6c);
udelay(10000);
writel(DAQBOARD2000_SECRProgPinLo, devpriv->plx + 0x6c);
- udelay(10000); /* Not in the original code, but I like symmetry... */
+ udelay(10000); /* Not in the original code, but I like symmetry... */
}
static int daqboard2000_pollCPLD(struct comedi_device *dev, int mask)
@@ -799,11 +800,6 @@ static int daqboard2000_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &daqboard2000_driver);
}
-static void daqboard2000_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(daqboard2000_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_IOTECH, 0x0409) },
{ 0 }
@@ -814,7 +810,7 @@ static struct pci_driver daqboard2000_pci_driver = {
.name = "daqboard2000",
.id_table = daqboard2000_pci_table,
.probe = daqboard2000_pci_probe,
- .remove = daqboard2000_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(daqboard2000_driver, daqboard2000_pci_driver);
diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
index b15e05808cb0..9823aa06787a 100644
--- a/drivers/staging/comedi/drivers/das08.c
+++ b/drivers/staging/comedi/drivers/das08.c
@@ -1,6 +1,6 @@
/*
* comedi/drivers/das08.c
- * DAS08 driver
+ * comedi driver for common DAS08 support (used by ISA/PCI/PCMCIA drivers)
*
* COMEDI - Linux Control and Measurement Device Interface
* Copyright (C) 2000 David A. Schleef <ds@schleef.org>
@@ -27,57 +27,26 @@
/*
* Driver: das08
* Description: DAS-08 compatible boards
+ * Devices: various, see das08_isa, das08_cs, and das08_pci drivers
* Author: Warren Jasper, ds, Frank Hess
- * Devices: [Keithley Metrabyte] DAS08 (isa-das08),
- * [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),
- * 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.
+ * This driver is used by the das08_isa, das08_cs, and das08_pci
+ * drivers to provide the common support for the DAS-08 hardware.
*
- * Options (for ISA cards):
- * [0] - base io address
- *
- * 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
- * comedi_rt_timer driver can be used to emulate commands for this
- * driver.
+ * The driver doesn't support asynchronous commands, since the
+ * cheap das08 hardware doesn't really support them.
*/
-#include "../comedidev.h"
-
#include <linux/delay.h>
+#include "../comedidev.h"
+
#include "8255.h"
#include "8253.h"
#include "das08.h"
-#define DRV_NAME "das08"
-
-#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_DEVICE_ID_PCIDAS08 0x29
-#define PCIDAS08_SIZE 0x54
-
-/* pci configuration registers */
-#define INTCSR 0x4c
-#define INTR1_ENABLE 0x1
-#define INTR1_HIGH_POLARITY 0x2
-#define PCI_INTR_ENABLE 0x40
-#define INTR1_EDGE_TRIG 0x100 /* requires high polarity */
-#define CNTRL 0x50
-#define CNTRL_DIR 0x2
-#define CNTRL_INTR 0x4
-
/*
cio-das08.pdf
@@ -235,16 +204,6 @@ 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,
@@ -501,159 +460,6 @@ static int das08_counter_config(struct comedi_device *dev,
return 2;
}
-#if DO_COMEDI_DRIVER_REGISTER
-static const struct das08_board_struct das08_boards[] = {
-#if DO_ISA
- {
- .name = "isa-das08", /* cio-das08.pdf */
- .bustype = isa,
- .ai_nbits = 12,
- .ai_pg = das08_pg_none,
- .ai_encoding = das08_encode12,
- .di_nchan = 3,
- .do_nchan = 4,
- .i8255_offset = 8,
- .i8254_offset = 4,
- .iosize = 16, /* unchecked */
- },
- {
- .name = "das08-pgm", /* cio-das08pgx.pdf */
- .bustype = isa,
- .ai_nbits = 12,
- .ai_pg = das08_pgm,
- .ai_encoding = das08_encode12,
- .di_nchan = 3,
- .do_nchan = 4,
- .i8255_offset = 0,
- .i8254_offset = 0x04,
- .iosize = 16, /* unchecked */
- },
- {
- .name = "das08-pgh", /* cio-das08pgx.pdf */
- .bustype = isa,
- .ai_nbits = 12,
- .ai_pg = das08_pgh,
- .ai_encoding = das08_encode12,
- .di_nchan = 3,
- .do_nchan = 4,
- .i8254_offset = 0x04,
- .iosize = 16, /* unchecked */
- },
- {
- .name = "das08-pgl", /* cio-das08pgx.pdf */
- .bustype = isa,
- .ai_nbits = 12,
- .ai_pg = das08_pgl,
- .ai_encoding = das08_encode12,
- .di_nchan = 3,
- .do_nchan = 4,
- .i8254_offset = 0x04,
- .iosize = 16, /* unchecked */
- },
- {
- .name = "das08-aoh", /* cio-das08_aox.pdf */
- .bustype = isa,
- .ai_nbits = 12,
- .ai_pg = das08_pgh,
- .ai_encoding = das08_encode12,
- .ao_nbits = 12,
- .di_nchan = 3,
- .do_nchan = 4,
- .i8255_offset = 0x0c,
- .i8254_offset = 0x04,
- .iosize = 16, /* unchecked */
- },
- {
- .name = "das08-aol", /* cio-das08_aox.pdf */
- .bustype = isa,
- .ai_nbits = 12,
- .ai_pg = das08_pgl,
- .ai_encoding = das08_encode12,
- .ao_nbits = 12,
- .di_nchan = 3,
- .do_nchan = 4,
- .i8255_offset = 0x0c,
- .i8254_offset = 0x04,
- .iosize = 16, /* unchecked */
- },
- {
- .name = "das08-aom", /* cio-das08_aox.pdf */
- .bustype = isa,
- .ai_nbits = 12,
- .ai_pg = das08_pgm,
- .ai_encoding = das08_encode12,
- .ao_nbits = 12,
- .di_nchan = 3,
- .do_nchan = 4,
- .i8255_offset = 0x0c,
- .i8254_offset = 0x04,
- .iosize = 16, /* unchecked */
- },
- {
- .name = "das08/jr-ao", /* cio-das08-jr-ao.pdf */
- .bustype = isa,
- .is_jr = true,
- .ai_nbits = 12,
- .ai_pg = das08_pg_none,
- .ai_encoding = das08_encode12,
- .ao_nbits = 12,
- .di_nchan = 8,
- .do_nchan = 8,
- .iosize = 16, /* unchecked */
- },
- {
- .name = "das08jr-16-ao", /* cio-das08jr-16-ao.pdf */
- .bustype = isa,
- .is_jr = true,
- .ai_nbits = 16,
- .ai_pg = das08_pg_none,
- .ai_encoding = das08_encode16,
- .ao_nbits = 16,
- .di_nchan = 8,
- .do_nchan = 8,
- .i8254_offset = 0x04,
- .iosize = 16, /* unchecked */
- },
- {
- .name = "pc104-das08",
- .bustype = isa,
- .ai_nbits = 12,
- .ai_pg = das08_pg_none,
- .ai_encoding = das08_encode12,
- .di_nchan = 3,
- .do_nchan = 4,
- .i8254_offset = 4,
- .iosize = 16, /* unchecked */
- },
- {
- .name = "das08jr/16",
- .bustype = isa,
- .is_jr = true,
- .ai_nbits = 16,
- .ai_pg = das08_pg_none,
- .ai_encoding = das08_encode16,
- .di_nchan = 8,
- .do_nchan = 8,
- .iosize = 16, /* unchecked */
- },
-#endif /* DO_ISA */
-#if DO_PCI
- {
- .name = "pci-das08", /* pci-das08 */
- .id = PCI_DEVICE_ID_PCIDAS08,
- .bustype = pci,
- .ai_nbits = 12,
- .ai_pg = das08_bipolar5,
- .ai_encoding = das08_encode12,
- .di_nchan = 3,
- .do_nchan = 4,
- .i8254_offset = 4,
- .iosize = 8,
- },
-#endif /* DO_PCI */
-};
-#endif /* DO_COMEDI_DRIVER_REGISTER */
-
int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
{
const struct das08_board_struct *thisboard = comedi_board(dev);
@@ -760,84 +566,6 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
}
EXPORT_SYMBOL_GPL(das08_common_attach);
-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 (is_pci_board(&das08_boards[i]) &&
- pdev->device == das08_boards[i].id)
- return &das08_boards[i];
-#endif
- return NULL;
-}
-
-/* only called in the PCI probe path, via comedi_pci_auto_config() */
-static int __maybe_unused
-das08_auto_attach(struct comedi_device *dev, unsigned long context_unused)
-{
- struct pci_dev *pdev;
- struct das08_private_struct *devpriv;
- unsigned long iobase;
-
- if (!DO_PCI)
- return -EINVAL;
-
- pdev = comedi_to_pci_dev(dev);
- devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
- if (!devpriv)
- return -ENOMEM;
- dev->private = devpriv;
-
- dev_info(dev->class_dev, "attach pci %s\n", pci_name(pdev));
- dev->board_ptr = das08_find_pci_board(pdev);
- if (dev->board_ptr == NULL) {
- dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
- return -EINVAL;
- }
-
- /* 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 */
- iobase = pci_resource_start(pdev, 2);
- return das08_common_attach(dev, iobase);
-}
-
-static int __maybe_unused
-das08_attach(struct comedi_device *dev, struct comedi_devconfig *it)
-{
- const struct das08_board_struct *thisboard = comedi_board(dev);
- struct das08_private_struct *devpriv;
- unsigned long iobase;
-
- devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
- if (!devpriv)
- return -ENOMEM;
- dev->private = devpriv;
-
- dev_info(dev->class_dev, "attach\n");
- 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)) {
- dev_err(dev->class_dev, "I/O port conflict\n");
- return -EIO;
- }
- return das08_common_attach(dev, iobase);
- } else
- return -EIO;
-}
-
void das08_common_detach(struct comedi_device *dev)
{
if (dev->subdevices)
@@ -845,84 +573,16 @@ void das08_common_detach(struct comedi_device *dev)
}
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);
-
- if (!thisboard)
- return;
- das08_common_detach(dev);
- if (is_isa_board(thisboard)) {
- if (dev->iobase)
- release_region(dev->iobase, thisboard->iosize);
- } else if (is_pci_board(thisboard)) {
- struct pci_dev *pdev = comedi_to_pci_dev(dev);
- if (pdev) {
- if (dev->iobase)
- comedi_pci_disable(pdev);
- }
- }
-}
-
-#if DO_COMEDI_DRIVER_REGISTER
-static struct comedi_driver das08_driver = {
- .driver_name = DRV_NAME,
- .module = THIS_MODULE,
- .attach = das08_attach,
- .auto_attach = das08_auto_attach,
- .detach = das08_detach,
- .board_name = &das08_boards[0].name,
- .num_names = sizeof(das08_boards) / sizeof(struct das08_board_struct),
- .offset = sizeof(struct das08_board_struct),
-};
-#endif
-
-#if DO_PCI
-static DEFINE_PCI_DEVICE_TABLE(das08_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_PCIDAS08) },
- {0}
-};
-
-MODULE_DEVICE_TABLE(pci, das08_pci_table);
-
-static int das08_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- return comedi_pci_auto_config(dev, &das08_driver);
-}
-
-static void das08_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static struct pci_driver das08_pci_driver = {
- .id_table = das08_pci_table,
- .name = DRV_NAME,
- .probe = &das08_pci_probe,
- .remove = &das08_pci_remove
-};
-#endif /* DO_PCI */
-
-#if DO_COMEDI_DRIVER_REGISTER
-#if DO_PCI
-module_comedi_pci_driver(das08_driver, das08_pci_driver);
-#else
-module_comedi_driver(das08_driver);
-#endif
-#else /* DO_COMEDI_DRIVER_REGISTER */
static int __init das08_init(void)
{
return 0;
}
+module_init(das08_init);
static void __exit das08_exit(void)
{
}
-
-module_init(das08_init);
module_exit(das08_exit);
-#endif /* DO_COMEDI_DRIVER_REGISTER */
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h
index 0314baebae39..b102ad4918c4 100644
--- a/drivers/staging/comedi/drivers/das08.h
+++ b/drivers/staging/comedi/drivers/das08.h
@@ -24,7 +24,6 @@
#ifndef _DAS08_H
#define _DAS08_H
-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,
@@ -34,7 +33,6 @@ enum das08_lrange { das08_pg_none, das08_bipolar5, das08_pgh, das08_pgl,
struct das08_board_struct {
const char *name;
unsigned int id; /* id for pci/pcmcia boards */
- enum das08_bustype bustype;
bool is_jr; /* true for 'JR' boards */
unsigned int ai_nbits;
enum das08_lrange ai_pg;
diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
index 024262375e3c..cfeebe4d1ddd 100644
--- a/drivers/staging/comedi/drivers/das08_cs.c
+++ b/drivers/staging/comedi/drivers/das08_cs.c
@@ -46,125 +46,70 @@ Options (for pcm-das08):
Command support does not exist, but could be added for this board.
*/
-#include "../comedidev.h"
-
#include <linux/delay.h>
-#include <linux/pci.h>
#include <linux/slab.h>
-#include "das08.h"
+#include "../comedidev.h"
-/* pcmcia includes */
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
+#include "das08.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,
+ .name = "pcm-das08",
+ .id = 0x0, /* XXX */
+ .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,
- struct comedi_devconfig *it)
+static int das08_cs_auto_attach(struct comedi_device *dev,
+ unsigned long context)
{
- const struct das08_board_struct *thisboard = comedi_board(dev);
+ struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
struct das08_private_struct *devpriv;
unsigned long iobase;
- struct pcmcia_device *link = cur_dev; /* XXX hack */
+ int ret;
+
+ /* The das08 driver needs the board_ptr */
+ dev->board_ptr = &das08_cs_boards[0];
+
+ link->config_flags |= CONF_AUTO_SET_IO;
+ ret = comedi_pcmcia_enable(dev, NULL);
+ if (ret)
+ return ret;
+ iobase = link->resource[0]->start;
devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
if (!devpriv)
return -ENOMEM;
dev->private = devpriv;
- dev_info(dev->class_dev, "das08_cs: attach\n");
- /* deal with a pci board */
-
- if (thisboard->bustype == pcmcia) {
- if (link == NULL) {
- dev_err(dev->class_dev, "no pcmcia cards found\n");
- return -EIO;
- }
- iobase = link->resource[0]->start;
- } else {
- dev_err(dev->class_dev,
- "bug! board does not have PCMCIA bustype\n");
- return -EINVAL;
- }
-
return das08_common_attach(dev, iobase);
}
+static void das08_cs_detach(struct comedi_device *dev)
+{
+ das08_common_detach(dev);
+ comedi_pcmcia_disable(dev);
+}
+
static struct comedi_driver driver_das08_cs = {
.driver_name = "das08_cs",
.module = THIS_MODULE,
- .attach = das08_cs_attach,
- .detach = das08_common_detach,
- .board_name = &das08_cs_boards[0].name,
- .num_names = ARRAY_SIZE(das08_cs_boards),
- .offset = sizeof(struct das08_board_struct),
+ .auto_attach = das08_cs_auto_attach,
+ .detach = das08_cs_detach,
};
-static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev,
- void *priv_data)
-{
- if (p_dev->config_index == 0)
- return -EINVAL;
-
- return pcmcia_request_io(p_dev);
-}
-
static int das08_pcmcia_attach(struct pcmcia_device *link)
{
- int ret;
-
- link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
-
- ret = pcmcia_loop_config(link, das08_pcmcia_config_loop, NULL);
- if (ret)
- goto failed;
-
- if (!link->irq)
- goto failed;
-
- ret = pcmcia_enable_device(link);
- if (ret)
- goto failed;
-
- cur_dev = link;
- return 0;
-
-failed:
- pcmcia_disable_device(link);
- return ret;
-}
-
-static void das08_pcmcia_detach(struct pcmcia_device *link)
-{
- pcmcia_disable_device(link);
- cur_dev = NULL;
+ return comedi_pcmcia_auto_config(link, &driver_das08_cs);
}
static const struct pcmcia_device_id das08_cs_id_table[] = {
@@ -176,36 +121,11 @@ MODULE_DEVICE_TABLE(pcmcia, das08_cs_id_table);
static struct pcmcia_driver das08_cs_driver = {
.name = "pcm-das08",
.owner = THIS_MODULE,
- .probe = das08_pcmcia_attach,
- .remove = das08_pcmcia_detach,
.id_table = das08_cs_id_table,
+ .probe = das08_pcmcia_attach,
+ .remove = comedi_pcmcia_auto_unconfig,
};
-
-static int __init das08_cs_init_module(void)
-{
- int ret;
-
- ret = comedi_driver_register(&driver_das08_cs);
- if (ret < 0)
- return ret;
-
- ret = pcmcia_register_driver(&das08_cs_driver);
- if (ret < 0) {
- comedi_driver_unregister(&driver_das08_cs);
- return ret;
- }
-
- return 0;
-
-}
-module_init(das08_cs_init_module);
-
-static void __exit das08_cs_exit_module(void)
-{
- pcmcia_unregister_driver(&das08_cs_driver);
- comedi_driver_unregister(&driver_das08_cs);
-}
-module_exit(das08_cs_exit_module);
+module_comedi_pcmcia_driver(driver_das08_cs, das08_cs_driver);
MODULE_AUTHOR("David A. Schleef <ds@schleef.org>, "
"Frank Mori Hess <fmhess@users.sourceforge.net>");
diff --git a/drivers/staging/comedi/drivers/das08_isa.c b/drivers/staging/comedi/drivers/das08_isa.c
new file mode 100644
index 000000000000..f12078247163
--- /dev/null
+++ b/drivers/staging/comedi/drivers/das08_isa.c
@@ -0,0 +1,217 @@
+/*
+ * das08_isa.c
+ * comedi driver for DAS08 ISA/PC-104 boards
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ * Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net>
+ * Copyright (C) 2004 Salvador E. Tropea <set@users.sf.net> <set@ieee.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: das08_isa
+ * Description: DAS-08 ISA/PC-104 compatible boards
+ * Devices: (Keithley Metrabyte) DAS08 [isa-das08],
+ * (ComputerBoards) DAS08 [isa-das08]
+ * (ComputerBoards) DAS08-PGM [das08-pgm]
+ * (ComputerBoards) DAS08-PGH [das08-pgh]
+ * (ComputerBoards) DAS08-PGL [das08-pgl]
+ * (ComputerBoards) DAS08-AOH [das08-aoh]
+ * (ComputerBoards) DAS08-AOL [das08-aol]
+ * (ComputerBoards) DAS08-AOM [das08-aom]
+ * (ComputerBoards) DAS08/JR-AO [das08/jr-ao]
+ * (ComputerBoards) DAS08/JR-16-AO [das08jr-16-ao]
+ * (ComputerBoards) PC104-DAS08 [pc104-das08]
+ * (ComputerBoards) DAS08/JR/16 [das08jr/16]
+ * Author: Warren Jasper, ds, Frank Hess
+ * Updated: Fri, 31 Aug 2012 19:19:06 +0100
+ * Status: works
+ *
+ * This is the ISA/PC-104-specific support split off from the das08 driver.
+ *
+ * Configuration Options:
+ * [0] - base io address
+ */
+
+#include "../comedidev.h"
+
+#include "das08.h"
+
+static const struct das08_board_struct das08_isa_boards[] = {
+ {
+ /* cio-das08.pdf */
+ .name = "isa-das08",
+ .ai_nbits = 12,
+ .ai_pg = das08_pg_none,
+ .ai_encoding = das08_encode12,
+ .di_nchan = 3,
+ .do_nchan = 4,
+ .i8255_offset = 8,
+ .i8254_offset = 4,
+ .iosize = 16, /* unchecked */
+ }, {
+ /* cio-das08pgx.pdf */
+ .name = "das08-pgm",
+ .ai_nbits = 12,
+ .ai_pg = das08_pgm,
+ .ai_encoding = das08_encode12,
+ .di_nchan = 3,
+ .do_nchan = 4,
+ .i8255_offset = 0,
+ .i8254_offset = 0x04,
+ .iosize = 16, /* unchecked */
+ }, {
+ /* cio-das08pgx.pdf */
+ .name = "das08-pgh",
+ .ai_nbits = 12,
+ .ai_pg = das08_pgh,
+ .ai_encoding = das08_encode12,
+ .di_nchan = 3,
+ .do_nchan = 4,
+ .i8254_offset = 0x04,
+ .iosize = 16, /* unchecked */
+ }, {
+ /* cio-das08pgx.pdf */
+ .name = "das08-pgl",
+ .ai_nbits = 12,
+ .ai_pg = das08_pgl,
+ .ai_encoding = das08_encode12,
+ .di_nchan = 3,
+ .do_nchan = 4,
+ .i8254_offset = 0x04,
+ .iosize = 16, /* unchecked */
+ }, {
+ /* cio-das08_aox.pdf */
+ .name = "das08-aoh",
+ .ai_nbits = 12,
+ .ai_pg = das08_pgh,
+ .ai_encoding = das08_encode12,
+ .ao_nbits = 12,
+ .di_nchan = 3,
+ .do_nchan = 4,
+ .i8255_offset = 0x0c,
+ .i8254_offset = 0x04,
+ .iosize = 16, /* unchecked */
+ }, {
+ /* cio-das08_aox.pdf */
+ .name = "das08-aol",
+ .ai_nbits = 12,
+ .ai_pg = das08_pgl,
+ .ai_encoding = das08_encode12,
+ .ao_nbits = 12,
+ .di_nchan = 3,
+ .do_nchan = 4,
+ .i8255_offset = 0x0c,
+ .i8254_offset = 0x04,
+ .iosize = 16, /* unchecked */
+ }, {
+ /* cio-das08_aox.pdf */
+ .name = "das08-aom",
+ .ai_nbits = 12,
+ .ai_pg = das08_pgm,
+ .ai_encoding = das08_encode12,
+ .ao_nbits = 12,
+ .di_nchan = 3,
+ .do_nchan = 4,
+ .i8255_offset = 0x0c,
+ .i8254_offset = 0x04,
+ .iosize = 16, /* unchecked */
+ }, {
+ /* cio-das08-jr-ao.pdf */
+ .name = "das08/jr-ao",
+ .is_jr = true,
+ .ai_nbits = 12,
+ .ai_pg = das08_pg_none,
+ .ai_encoding = das08_encode12,
+ .ao_nbits = 12,
+ .di_nchan = 8,
+ .do_nchan = 8,
+ .iosize = 16, /* unchecked */
+ }, {
+ /* cio-das08jr-16-ao.pdf */
+ .name = "das08jr-16-ao",
+ .is_jr = true,
+ .ai_nbits = 16,
+ .ai_pg = das08_pg_none,
+ .ai_encoding = das08_encode16,
+ .ao_nbits = 16,
+ .di_nchan = 8,
+ .do_nchan = 8,
+ .i8254_offset = 0x04,
+ .iosize = 16, /* unchecked */
+ }, {
+ .name = "pc104-das08",
+ .ai_nbits = 12,
+ .ai_pg = das08_pg_none,
+ .ai_encoding = das08_encode12,
+ .di_nchan = 3,
+ .do_nchan = 4,
+ .i8254_offset = 4,
+ .iosize = 16, /* unchecked */
+ }, {
+ .name = "das08jr/16",
+ .is_jr = true,
+ .ai_nbits = 16,
+ .ai_pg = das08_pg_none,
+ .ai_encoding = das08_encode16,
+ .di_nchan = 8,
+ .do_nchan = 8,
+ .iosize = 16, /* unchecked */
+ },
+};
+
+static int das08_isa_attach(struct comedi_device *dev,
+ struct comedi_devconfig *it)
+{
+ const struct das08_board_struct *thisboard = comedi_board(dev);
+ struct das08_private_struct *devpriv;
+
+ devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+ if (!devpriv)
+ return -ENOMEM;
+ dev->private = devpriv;
+
+ if (!request_region(it->options[0], thisboard->iosize,
+ thisboard->name))
+ return -EIO;
+
+ return das08_common_attach(dev, it->options[0]);
+}
+
+static void das08_isa_detach(struct comedi_device *dev)
+{
+ const struct das08_board_struct *thisboard = comedi_board(dev);
+
+ das08_common_detach(dev);
+ if (dev->iobase)
+ release_region(dev->iobase, thisboard->iosize);
+}
+
+static struct comedi_driver das08_isa_driver = {
+ .driver_name = "isa-das08",
+ .module = THIS_MODULE,
+ .attach = das08_isa_attach,
+ .detach = das08_isa_detach,
+ .board_name = &das08_isa_boards[0].name,
+ .num_names = ARRAY_SIZE(das08_isa_boards),
+ .offset = sizeof(das08_isa_boards[0]),
+};
+module_comedi_driver(das08_isa_driver);
+
+MODULE_AUTHOR("Comedi http://www.comedi.org");
+MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/das08_pci.c b/drivers/staging/comedi/drivers/das08_pci.c
new file mode 100644
index 000000000000..c405876ddcf7
--- /dev/null
+++ b/drivers/staging/comedi/drivers/das08_pci.c
@@ -0,0 +1,121 @@
+/*
+ * das08_pci.c
+ * comedi driver for DAS08 PCI boards
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ * Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net>
+ * Copyright (C) 2004 Salvador E. Tropea <set@users.sf.net> <set@ieee.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: das08_pci
+ * Description: DAS-08 PCI compatible boards
+ * Devices: (ComputerBoards) PCI-DAS08 [pci-das08]
+ * Author: Warren Jasper, ds, Frank Hess
+ * Updated: Fri, 31 Aug 2012 19:19:06 +0100
+ * Status: works
+ *
+ * This is the PCI-specific support split off from the das08 driver.
+ *
+ * Configuration Options: not applicable, uses PCI auto config
+ */
+
+#include <linux/pci.h>
+
+#include "../comedidev.h"
+
+#include "das08.h"
+
+#define PCI_DEVICE_ID_PCIDAS08 0x0029
+
+static const struct das08_board_struct das08_pci_boards[] = {
+ {
+ .name = "pci-das08",
+ .id = PCI_DEVICE_ID_PCIDAS08,
+ .ai_nbits = 12,
+ .ai_pg = das08_bipolar5,
+ .ai_encoding = das08_encode12,
+ .di_nchan = 3,
+ .do_nchan = 4,
+ .i8254_offset = 4,
+ .iosize = 8,
+ },
+};
+
+static int das08_pci_auto_attach(struct comedi_device *dev,
+ unsigned long context_unused)
+{
+ struct pci_dev *pdev = comedi_to_pci_dev(dev);
+ struct das08_private_struct *devpriv;
+ int ret;
+
+ devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+ if (!devpriv)
+ return -ENOMEM;
+ dev->private = devpriv;
+
+ /* The das08 driver needs the board_ptr */
+ dev->board_ptr = &das08_pci_boards[0];
+
+ ret = comedi_pci_enable(pdev, dev->driver->driver_name);
+ if (ret)
+ return ret;
+ dev->iobase = pci_resource_start(pdev, 2);
+
+ return das08_common_attach(dev, dev->iobase);
+}
+
+static void das08_pci_detach(struct comedi_device *dev)
+{
+ struct pci_dev *pdev = comedi_to_pci_dev(dev);
+
+ das08_common_detach(dev);
+ if (dev->iobase)
+ comedi_pci_disable(pdev);
+}
+
+static struct comedi_driver das08_pci_comedi_driver = {
+ .driver_name = "pci-das08",
+ .module = THIS_MODULE,
+ .auto_attach = das08_pci_auto_attach,
+ .detach = das08_pci_detach,
+};
+
+static int das08_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ return comedi_pci_auto_config(dev, &das08_pci_comedi_driver);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(das08_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_PCIDAS08) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, das08_pci_table);
+
+static struct pci_driver das08_pci_driver = {
+ .name = "pci-das08",
+ .id_table = das08_pci_table,
+ .probe = das08_pci_probe,
+ .remove = comedi_pci_auto_unconfig,
+};
+module_comedi_pci_driver(das08_pci_comedi_driver, das08_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/das16.c b/drivers/staging/comedi/drivers/das16.c
index b159f44d694f..f238a1fbccbf 100644
--- a/drivers/staging/comedi/drivers/das16.c
+++ b/drivers/staging/comedi/drivers/das16.c
@@ -82,7 +82,9 @@ www.measurementcomputing.com
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
+
#include <asm/dma.h>
+
#include "../comedidev.h"
#include "8253.h"
diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
index 960da8debe17..3ce499fa5dbf 100644
--- a/drivers/staging/comedi/drivers/dt3000.c
+++ b/drivers/staging/comedi/drivers/dt3000.c
@@ -55,9 +55,11 @@ AO commands are not supported.
#define DEBUG 1
+#include <linux/pci.h>
+#include <linux/delay.h>
#include <linux/interrupt.h>
+
#include "../comedidev.h"
-#include <linux/delay.h>
#include "comedi_fc.h"
@@ -856,11 +858,6 @@ static int dt3000_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &dt3000_driver);
}
-static void dt3000_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(dt3000_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3001) },
{ PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3001_PGL) },
@@ -877,7 +874,7 @@ static struct pci_driver dt3000_pci_driver = {
.name = "dt3000",
.id_table = dt3000_pci_table,
.probe = dt3000_pci_probe,
- .remove = dt3000_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(dt3000_driver, dt3000_pci_driver);
diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
index 176799849d20..192cf088f834 100644
--- a/drivers/staging/comedi/drivers/dt9812.c
+++ b/drivers/staging/comedi/drivers/dt9812.c
@@ -702,10 +702,9 @@ static int dt9812_probe(struct usb_interface *interface,
/* allocate memory for our device state and initialize it */
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (dev == NULL) {
- dev_err(&interface->dev, "Out of memory\n");
+ if (dev == NULL)
goto error;
- }
+
kref_init(&dev->kref);
dev->udev = usb_get_dev(interface_to_usbdev(interface));
@@ -1133,7 +1132,7 @@ static struct comedi_driver dt9812_comedi_driver = {
static int __init usb_dt9812_init(void)
{
- int result, i;
+ int i;
/* Initialize all driver slots */
for (i = 0; i < DT9812_NUM_SLOTS; i++) {
@@ -1144,30 +1143,13 @@ static int __init usb_dt9812_init(void)
}
dt9812[12].serial = 0x0;
- /* register with the USB subsystem */
- result = usb_register(&dt9812_usb_driver);
- if (result) {
- pr_err("usb_register failed. Error number %d\n", result);
- return result;
- }
- /* register with comedi */
- result = comedi_driver_register(&dt9812_comedi_driver);
- if (result) {
- usb_deregister(&dt9812_usb_driver);
- pr_err("comedi_driver_register failed. Error number %d\n",
- result);
- }
-
- return result;
+ return comedi_usb_driver_register(&dt9812_comedi_driver,
+ &dt9812_usb_driver);
}
static void __exit usb_dt9812_exit(void)
{
- /* unregister with comedi */
- comedi_driver_unregister(&dt9812_comedi_driver);
-
- /* deregister this driver with the USB subsystem */
- usb_deregister(&dt9812_usb_driver);
+ comedi_usb_driver_unregister(&dt9812_comedi_driver, &dt9812_usb_driver);
}
module_init(usb_dt9812_init);
diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c
index 8497a36db7db..decc17f1867e 100644
--- a/drivers/staging/comedi/drivers/dyna_pci10xx.c
+++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c
@@ -37,9 +37,11 @@
their cards in their manuals.
*/
-#include "../comedidev.h"
+#include <linux/pci.h>
#include <linux/mutex.h>
+#include "../comedidev.h"
+
#define READ_TIMEOUT 50
static const struct comedi_lrange range_pci1050_ai = { 3, {
@@ -276,11 +278,6 @@ static int dyna_pci10xx_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &dyna_pci10xx_driver);
}
-static void dyna_pci10xx_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(dyna_pci10xx_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_PLX, 0x1050) },
{ 0 }
@@ -291,7 +288,7 @@ static struct pci_driver dyna_pci10xx_pci_driver = {
.name = "dyna_pci10xx",
.id_table = dyna_pci10xx_pci_table,
.probe = dyna_pci10xx_pci_probe,
- .remove = dyna_pci10xx_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(dyna_pci10xx_driver, dyna_pci10xx_pci_driver);
diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
index 154598f6d5e3..b60c97562676 100644
--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
+++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
@@ -47,9 +47,11 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/pci.h>
+#include <linux/delay.h>
#include <linux/interrupt.h>
+
#include "../comedidev.h"
-#include <linux/delay.h>
#include "plx9080.h"
#include "comedi_fc.h"
@@ -946,11 +948,6 @@ static int gsc_hpdi_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &gsc_hpdi_driver);
}
-static void gsc_hpdi_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(gsc_hpdi_pci_table) = {
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9080, PCI_VENDOR_ID_PLX,
0x2400, 0, 0, 0},
@@ -962,7 +959,7 @@ static struct pci_driver gsc_hpdi_pci_driver = {
.name = "gsc_hpdi",
.id_table = gsc_hpdi_pci_table,
.probe = gsc_hpdi_pci_probe,
- .remove = gsc_hpdi_pci_remove
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(gsc_hpdi_driver, gsc_hpdi_pci_driver);
diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
index a91a448ba0f0..1e08f9141fad 100644
--- a/drivers/staging/comedi/drivers/icp_multi.c
+++ b/drivers/staging/comedi/drivers/icp_multi.c
@@ -47,11 +47,11 @@ There are 4 x 12-bit Analogue Outputs. Ranges : 5V, 10V, +/-5V, +/-10V
Configuration options: not applicable, uses PCI auto config
*/
+#include <linux/pci.h>
+#include <linux/delay.h>
#include <linux/interrupt.h>
-#include "../comedidev.h"
-#include <linux/delay.h>
-#include <linux/pci.h>
+#include "../comedidev.h"
#define PCI_DEVICE_ID_ICP_MULTI 0x8000
@@ -623,11 +623,6 @@ static int icp_multi_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &icp_multi_driver);
}
-static void 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 }
@@ -638,7 +633,7 @@ static struct pci_driver icp_multi_pci_driver = {
.name = "icp_multi",
.id_table = icp_multi_pci_table,
.probe = icp_multi_pci_probe,
- .remove = icp_multi_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(icp_multi_driver, icp_multi_pci_driver);
diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
index c756a35ce31a..17ba75e0ab89 100644
--- a/drivers/staging/comedi/drivers/jr3_pci.c
+++ b/drivers/staging/comedi/drivers/jr3_pci.c
@@ -42,15 +42,17 @@
* comedi_nonfree_firmware tarball. The file is called "jr3pci.idm".
*/
-#include "../comedidev.h"
-
+#include <linux/kernel.h>
+#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/ctype.h>
#include <linux/firmware.h>
#include <linux/jiffies.h>
#include <linux/slab.h>
#include <linux/timer.h>
-#include <linux/kernel.h>
+
+#include "../comedidev.h"
+
#include "jr3_pci.h"
#define PCI_VENDOR_ID_JR3 0x1762
@@ -844,11 +846,6 @@ static int jr3_pci_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &jr3_pci_driver);
}
-static void jr3_pci_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(jr3_pci_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_1_CHANNEL) },
{ PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_1_CHANNEL_NEW) },
@@ -863,7 +860,7 @@ static struct pci_driver jr3_pci_pci_driver = {
.name = "jr3_pci",
.id_table = jr3_pci_pci_table,
.probe = jr3_pci_pci_probe,
- .remove = jr3_pci_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(jr3_pci_driver, jr3_pci_pci_driver);
diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
index 19c94282ac3f..8c09c026508a 100644
--- a/drivers/staging/comedi/drivers/ke_counter.c
+++ b/drivers/staging/comedi/drivers/ke_counter.c
@@ -34,6 +34,8 @@ This driver is a simple driver to read the counter values from
Kolter Electronic PCI Counter Card.
*/
+#include <linux/pci.h>
+
#include "../comedidev.h"
#define CNT_CARD_DEVICE_ID 0x0014
@@ -152,11 +154,6 @@ static int ke_counter_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &ke_counter_driver);
}
-static void ke_counter_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(ke_counter_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_KOLTER, CNT_CARD_DEVICE_ID) },
{ 0 }
@@ -167,7 +164,7 @@ static struct pci_driver ke_counter_pci_driver = {
.name = "ke_counter",
.id_table = ke_counter_pci_table,
.probe = ke_counter_pci_probe,
- .remove = ke_counter_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(ke_counter_driver, ke_counter_pci_driver);
diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
index 3c4b0228e8dc..b766bb93efd6 100644
--- a/drivers/staging/comedi/drivers/me4000.c
+++ b/drivers/staging/comedi/drivers/me4000.c
@@ -45,13 +45,14 @@ broken.
*/
-#include <linux/interrupt.h>
-#include "../comedidev.h"
-
+#include <linux/pci.h>
#include <linux/delay.h>
+#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/spinlock.h>
+#include "../comedidev.h"
+
#include "comedi_fc.h"
#include "8253.h"
@@ -1734,11 +1735,6 @@ static int me4000_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &me4000_driver);
}
-static void me4000_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
{PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4650)},
{PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660)},
@@ -1761,7 +1757,7 @@ static struct pci_driver me4000_pci_driver = {
.name = "me4000",
.id_table = me4000_pci_table,
.probe = me4000_pci_probe,
- .remove = me4000_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
index ce8e3d3f135c..06490ebc8cc8 100644
--- a/drivers/staging/comedi/drivers/me_daq.c
+++ b/drivers/staging/comedi/drivers/me_daq.c
@@ -34,9 +34,11 @@
* Analog Input, Analog Output, Digital I/O
*/
+#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/firmware.h>
+
#include "../comedidev.h"
#define ME2600_FIRMWARE "me2600_firmware.bin"
@@ -619,11 +621,6 @@ static int me_daq_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &me_daq_driver);
}
-static void me_daq_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(me_daq_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, ME2600_DEVICE_ID) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, ME2000_DEVICE_ID) },
@@ -635,7 +632,7 @@ static struct pci_driver me_daq_pci_driver = {
.name = "me_daq",
.id_table = me_daq_pci_table,
.probe = me_daq_pci_probe,
- .remove = me_daq_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(me_daq_driver, me_daq_pci_driver);
diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c
index e27850f628ce..be2c15f84614 100644
--- a/drivers/staging/comedi/drivers/mite.c
+++ b/drivers/staging/comedi/drivers/mite.c
@@ -51,11 +51,12 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include "mite.h"
+#include <linux/pci.h>
-#include "comedi_fc.h"
#include "../comedidev.h"
+#include "comedi_fc.h"
+#include "mite.h"
#define PCI_MITE_SIZE 4096
#define PCI_DAQ_SIZE 4096
diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
index 5196b460ce11..bcd4df290ec4 100644
--- a/drivers/staging/comedi/drivers/ni_6527.c
+++ b/drivers/staging/comedi/drivers/ni_6527.c
@@ -41,7 +41,9 @@ Updated: Sat, 25 Jan 2003 13:24:40 -0800
#define DEBUG 1
#define DEBUG_FLAGS
+#include <linux/pci.h>
#include <linux/interrupt.h>
+
#include "../comedidev.h"
#include "comedi_fc.h"
@@ -452,16 +454,11 @@ static int ni6527_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &ni6527_driver);
}
-static void ni6527_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static struct pci_driver ni6527_pci_driver = {
.name = DRIVER_NAME,
.id_table = ni6527_pci_table,
.probe = ni6527_pci_probe,
- .remove = ni6527_pci_remove
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(ni6527_driver, ni6527_pci_driver);
diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
index 2fb4b7790aeb..bfa790ecf41d 100644
--- a/drivers/staging/comedi/drivers/ni_65xx.c
+++ b/drivers/staging/comedi/drivers/ni_65xx.c
@@ -50,8 +50,11 @@ except maybe the 6514.
#define DEBUG 1
#define DEBUG_FLAGS
+
+#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
+
#include "../comedidev.h"
#include "comedi_fc.h"
@@ -787,16 +790,11 @@ static int ni_65xx_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &ni_65xx_driver);
}
-static void ni_65xx_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static struct pci_driver ni_65xx_pci_driver = {
.name = "ni_65xx",
.id_table = ni_65xx_pci_table,
.probe = ni_65xx_pci_probe,
- .remove = ni_65xx_pci_remove
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(ni_65xx_driver, ni_65xx_pci_driver);
diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
index 26baf9c96fff..e46dd7a1a724 100644
--- a/drivers/staging/comedi/drivers/ni_660x.c
+++ b/drivers/staging/comedi/drivers/ni_660x.c
@@ -40,8 +40,11 @@ DAQ 6601/6602 User Manual (NI 322137B-01)
*/
+#include <linux/pci.h>
#include <linux/interrupt.h>
+
#include "../comedidev.h"
+
#include "mite.h"
#include "ni_tio.h"
@@ -1327,11 +1330,6 @@ static int ni_660x_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &ni_660x_driver);
}
-static void ni_660x_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(ni_660x_pci_table) = {
{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2c60)},
{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1310)},
@@ -1345,7 +1343,7 @@ static struct pci_driver ni_660x_pci_driver = {
.name = "ni_660x",
.id_table = ni_660x_pci_table,
.probe = ni_660x_pci_probe,
- .remove = ni_660x_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(ni_660x_driver, ni_660x_pci_driver);
diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
index 272caeb6ecee..2faf86c83dc5 100644
--- a/drivers/staging/comedi/drivers/ni_670x.c
+++ b/drivers/staging/comedi/drivers/ni_670x.c
@@ -41,8 +41,10 @@ Commands are not supported.
*/
+#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
+
#include "../comedidev.h"
#include "mite.h"
@@ -309,11 +311,6 @@ static int ni_670x_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &ni_670x_driver);
}
-static void ni_670x_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(ni_670x_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2c90) },
{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1920) },
@@ -325,7 +322,7 @@ static struct pci_driver ni_670x_pci_driver = {
.name = "ni_670x",
.id_table = ni_670x_pci_table,
.probe = ni_670x_pci_probe,
- .remove = ni_670x_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(ni_670x_driver, ni_670x_pci_driver);
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index 68d7c6a5db7d..9cc6092eacdd 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -50,22 +50,15 @@ Manuals: Register level: http://www.ni.com/pdf/manuals/340698.pdf
User Manual: http://www.ni.com/pdf/manuals/320676d.pdf
*/
+#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
-#include "../comedidev.h"
-#include <linux/ioport.h>
+#include "../comedidev.h"
#include <pcmcia/cistpl.h>
-#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
-static struct pcmcia_device *pcmcia_cur_dev;
-
-struct daq700_board {
- const char *name;
-};
-
/* daqcard700 registers */
#define DIO_W 0x04 /* WO 8bit */
#define DIO_R 0x05 /* RO 8bit */
@@ -202,24 +195,20 @@ static void daq700_ai_config(struct comedi_device *dev,
inw(iobase + ADFIFO_R); /* read 16bit junk from FIFO to clear */
}
-static int daq700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int daq700_auto_attach(struct comedi_device *dev,
+ unsigned long context)
{
- const struct daq700_board *thisboard = comedi_board(dev);
+ struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
struct comedi_subdevice *s;
- struct pcmcia_device *link;
int ret;
- link = pcmcia_cur_dev; /* XXX hack */
- if (!link)
- return -EIO;
+ dev->board_name = dev->driver->driver_name;
+ link->config_flags |= CONF_AUTO_SET_IO;
+ ret = comedi_pcmcia_enable(dev, NULL);
+ if (ret)
+ return ret;
dev->iobase = link->resource[0]->start;
- if (!dev->iobase) {
- dev_err(dev->class_dev, "io base address is zero!\n");
- return -EINVAL;
- }
-
- dev->board_name = thisboard->name;
ret = comedi_alloc_subdevices(dev, 2);
if (ret)
@@ -256,68 +245,16 @@ static int daq700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return 0;
}
-static void daq700_detach(struct comedi_device *dev)
-{
- /* nothing to cleanup */
-}
-
-static const struct daq700_board daq700_boards[] = {
- {
- .name = "daqcard-700",
- }, {
- .name = "ni_daq_700",
- },
-};
-
static struct comedi_driver daq700_driver = {
.driver_name = "ni_daq_700",
.module = THIS_MODULE,
- .attach = daq700_attach,
- .detach = daq700_detach,
- .board_name = &daq700_boards[0].name,
- .num_names = ARRAY_SIZE(daq700_boards),
- .offset = sizeof(struct daq700_board),
+ .auto_attach = daq700_auto_attach,
+ .detach = comedi_pcmcia_disable,
};
-static int daq700_pcmcia_config_loop(struct pcmcia_device *p_dev,
- void *priv_data)
-{
- if (p_dev->config_index == 0)
- return -EINVAL;
-
- return pcmcia_request_io(p_dev);
-}
-
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, daq700_pcmcia_config_loop, NULL);
- if (ret)
- goto failed;
-
- if (!link->irq)
- goto failed;
-
- ret = pcmcia_enable_device(link);
- if (ret)
- goto failed;
-
- pcmcia_cur_dev = link;
- return 0;
-
-failed:
- pcmcia_disable_device(link);
- return ret;
-}
-
-static void daq700_cs_detach(struct pcmcia_device *link)
-{
- pcmcia_disable_device(link);
- pcmcia_cur_dev = NULL;
+ return comedi_pcmcia_auto_config(link, &daq700_driver);
}
static const struct pcmcia_device_id daq700_cs_ids[] = {
@@ -329,35 +266,11 @@ MODULE_DEVICE_TABLE(pcmcia, daq700_cs_ids);
static struct pcmcia_driver daq700_cs_driver = {
.name = "ni_daq_700",
.owner = THIS_MODULE,
- .probe = daq700_cs_attach,
- .remove = daq700_cs_detach,
.id_table = daq700_cs_ids,
+ .probe = daq700_cs_attach,
+ .remove = comedi_pcmcia_auto_unconfig,
};
-
-static int __init daq700_cs_init(void)
-{
- int ret;
-
- ret = comedi_driver_register(&daq700_driver);
- if (ret < 0)
- return ret;
-
- ret = pcmcia_register_driver(&daq700_cs_driver);
- if (ret < 0) {
- comedi_driver_unregister(&daq700_driver);
- return ret;
- }
-
- return 0;
-}
-module_init(daq700_cs_init);
-
-static void __exit daq700_cs_exit(void)
-{
- pcmcia_unregister_driver(&daq700_cs_driver);
- comedi_driver_unregister(&daq700_driver);
-}
-module_exit(daq700_cs_exit);
+module_comedi_pcmcia_driver(daq700_driver, daq700_cs_driver);
MODULE_AUTHOR("Fred Brooks <nsaspook@nsaspook.com>");
MODULE_DESCRIPTION(
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index 7b333353c5d9..e1cc9d01f200 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -37,127 +37,28 @@ This is just a wrapper around the 8255.o driver to properly handle
the PCMCIA interface.
*/
- /* #define LABPC_DEBUG *//* enable debugging messages */
-#undef LABPC_DEBUG
-
-#include <linux/interrupt.h>
-#include <linux/slab.h>
#include "../comedidev.h"
-#include <linux/ioport.h>
-
-#include "8255.h"
-
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
-static struct pcmcia_device *pcmcia_cur_dev;
-
-#define DIO24_SIZE 4 /* size of io region used by board */
-
-static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static void dio24_detach(struct comedi_device *dev);
-
-enum dio24_bustype { pcmcia_bustype };
-
-struct dio24_board_struct {
- const char *name;
- int device_id; /* device id for pcmcia board */
- enum dio24_bustype bustype; /* PCMCIA */
- int have_dio; /* have 8255 chip */
- /* function pointers so we can use inb/outb or readb/writeb as appropriate */
- unsigned int (*read_byte) (unsigned int address);
- void (*write_byte) (unsigned int byte, unsigned int address);
-};
-
-static const struct dio24_board_struct dio24_boards[] = {
- {
- .name = "daqcard-dio24",
- .device_id = 0x475c, /* 0x10b is manufacturer id, 0x475c is device id */
- .bustype = pcmcia_bustype,
- .have_dio = 1,
- },
- {
- .name = "ni_daq_dio24",
- .device_id = 0x475c, /* 0x10b is manufacturer id, 0x475c is device id */
- .bustype = pcmcia_bustype,
- .have_dio = 1,
- },
-};
-
-/*
- * Useful for shorthand access to the particular board structure
- */
-#define thisboard ((const struct dio24_board_struct *)dev->board_ptr)
-
-struct dio24_private {
-
- int data; /* number of data points left to be taken */
-};
-
-static struct comedi_driver driver_dio24 = {
- .driver_name = "ni_daq_dio24",
- .module = THIS_MODULE,
- .attach = dio24_attach,
- .detach = dio24_detach,
- .num_names = ARRAY_SIZE(dio24_boards),
- .board_name = &dio24_boards[0].name,
- .offset = sizeof(struct dio24_board_struct),
-};
+#include "8255.h"
-static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int dio24_auto_attach(struct comedi_device *dev,
+ unsigned long context)
{
- struct dio24_private *devpriv;
+ struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
struct comedi_subdevice *s;
- unsigned long iobase = 0;
-#ifdef incomplete
- unsigned int irq = 0;
-#endif
- struct pcmcia_device *link;
int ret;
- devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
- if (!devpriv)
- return -ENOMEM;
- dev->private = devpriv;
-
- /* get base address, irq etc. based on bustype */
- switch (thisboard->bustype) {
- case pcmcia_bustype:
- link = pcmcia_cur_dev; /* XXX hack */
- if (!link)
- return -EIO;
- iobase = link->resource[0]->start;
-#ifdef incomplete
- irq = link->irq;
-#endif
- break;
- default:
- pr_err("bug! couldn't determine board type\n");
- return -EINVAL;
- break;
- }
- pr_debug("comedi%d: ni_daq_dio24: %s, io 0x%lx", dev->minor,
- thisboard->name, iobase);
-#ifdef incomplete
- if (irq)
- pr_debug("irq %u\n", irq);
-#endif
-
- if (iobase == 0) {
- pr_err("io base address is zero!\n");
- return -EINVAL;
- }
+ dev->board_name = dev->driver->driver_name;
- dev->iobase = iobase;
-
-#ifdef incomplete
- /* grab our IRQ */
- dev->irq = irq;
-#endif
-
- dev->board_name = thisboard->name;
+ link->config_flags |= CONF_AUTO_SET_IO;
+ ret = comedi_pcmcia_enable(dev, NULL);
+ if (ret)
+ return ret;
+ dev->iobase = link->resource[0]->start;
ret = comedi_alloc_subdevices(dev, 1);
if (ret)
@@ -165,184 +66,48 @@ static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* 8255 dio */
s = &dev->subdevices[0];
- subdev_8255_init(dev, s, NULL, dev->iobase);
+ ret = subdev_8255_init(dev, s, NULL, dev->iobase);
+ if (ret)
+ return ret;
return 0;
-};
+}
static void dio24_detach(struct comedi_device *dev)
{
- 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)
- free_irq(dev->irq, dev);
-};
-
-static void dio24_config(struct pcmcia_device *link);
-static void dio24_release(struct pcmcia_device *link);
-static int dio24_cs_suspend(struct pcmcia_device *p_dev);
-static int dio24_cs_resume(struct pcmcia_device *p_dev);
-
-static int dio24_cs_attach(struct pcmcia_device *);
-static void dio24_cs_detach(struct pcmcia_device *);
+ if (dev->subdevices)
+ subdev_8255_cleanup(dev, &dev->subdevices[0]);
+ comedi_pcmcia_disable(dev);
+}
-struct local_info_t {
- struct pcmcia_device *link;
- int stop;
- struct bus_operations *bus;
+static struct comedi_driver driver_dio24 = {
+ .driver_name = "ni_daq_dio24",
+ .module = THIS_MODULE,
+ .auto_attach = dio24_auto_attach,
+ .detach = dio24_detach,
};
static int dio24_cs_attach(struct pcmcia_device *link)
{
- struct local_info_t *local;
-
- dev_info(&link->dev, "ni_daq_dio24: HOLA SOY YO - CS-attach!\n");
-
- dev_dbg(&link->dev, "dio24_cs_attach()\n");
-
- /* Allocate space for private device-specific data */
- local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
- if (!local)
- return -ENOMEM;
- local->link = link;
- link->priv = local;
-
- pcmcia_cur_dev = link;
-
- dio24_config(link);
-
- return 0;
-} /* dio24_cs_attach */
-
-static void dio24_cs_detach(struct pcmcia_device *link)
-{
- ((struct local_info_t *)link->priv)->stop = 1;
- dio24_release(link);
-
- /* This points to the parent local_info_t struct */
- kfree(link->priv);
+ return comedi_pcmcia_auto_config(link, &driver_dio24);
}
-static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev,
- void *priv_data)
-{
- if (p_dev->config_index == 0)
- return -EINVAL;
-
- return pcmcia_request_io(p_dev);
-}
-
-static void dio24_config(struct pcmcia_device *link)
-{
- int ret;
-
- dev_info(&link->dev, "ni_daq_dio24: HOLA SOY YO! - config\n");
-
- dev_dbg(&link->dev, "dio24_config\n");
-
- link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO |
- CONF_AUTO_SET_IO;
-
- ret = pcmcia_loop_config(link, dio24_pcmcia_config_loop, NULL);
- if (ret) {
- dev_warn(&link->dev, "no configuration found\n");
- goto failed;
- }
-
- if (!link->irq)
- goto failed;
-
- ret = pcmcia_enable_device(link);
- if (ret)
- goto failed;
-
- return;
-
-failed:
- dev_info(&link->dev, "Fallo");
- dio24_release(link);
-
-} /* dio24_config */
-
-static void dio24_release(struct pcmcia_device *link)
-{
- dev_dbg(&link->dev, "dio24_release\n");
-
- pcmcia_disable_device(link);
-} /* dio24_release */
-
-static int dio24_cs_suspend(struct pcmcia_device *link)
-{
- struct local_info_t *local = link->priv;
-
- /* Mark the device as stopped, to block IO until later */
- local->stop = 1;
- return 0;
-} /* dio24_cs_suspend */
-
-static int dio24_cs_resume(struct pcmcia_device *link)
-{
- struct local_info_t *local = link->priv;
-
- local->stop = 0;
- return 0;
-} /* dio24_cs_resume */
-
-/*====================================================================*/
-
static const struct pcmcia_device_id dio24_cs_ids[] = {
- /* N.B. These IDs should match those in dio24_boards */
PCMCIA_DEVICE_MANF_CARD(0x010b, 0x475c), /* daqcard-dio24 */
PCMCIA_DEVICE_NULL
};
-
MODULE_DEVICE_TABLE(pcmcia, dio24_cs_ids);
-MODULE_AUTHOR("Daniel Vecino Castel <dvecino@able.es>");
-MODULE_DESCRIPTION("Comedi driver for National Instruments "
- "PCMCIA DAQ-Card DIO-24");
-MODULE_LICENSE("GPL");
static struct pcmcia_driver dio24_cs_driver = {
- .probe = dio24_cs_attach,
- .remove = dio24_cs_detach,
- .suspend = dio24_cs_suspend,
- .resume = dio24_cs_resume,
- .id_table = dio24_cs_ids,
- .owner = THIS_MODULE,
- .name = "ni_daq_dio24",
+ .name = "ni_daq_dio24",
+ .owner = THIS_MODULE,
+ .id_table = dio24_cs_ids,
+ .probe = dio24_cs_attach,
+ .remove = comedi_pcmcia_auto_unconfig,
};
+module_comedi_pcmcia_driver(driver_dio24, dio24_cs_driver);
-static int __init init_dio24_cs(void)
-{
- printk("ni_daq_dio24: HOLA SOY YO!\n");
- pcmcia_register_driver(&dio24_cs_driver);
- return 0;
-}
-
-static void __exit exit_dio24_cs(void)
-{
- pcmcia_unregister_driver(&dio24_cs_driver);
-}
-
-int __init init_module(void)
-{
- int ret;
-
- ret = init_dio24_cs();
- if (ret < 0)
- return ret;
-
- return comedi_driver_register(&driver_dio24);
-}
-
-void __exit cleanup_module(void)
-{
- exit_dio24_cs();
- comedi_driver_unregister(&driver_dio24);
-}
+MODULE_AUTHOR("Daniel Vecino Castel <dvecino@able.es>");
+MODULE_DESCRIPTION(
+ "Comedi driver for National Instruments PCMCIA DAQ-Card DIO-24");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
index d29c4d761bac..f957b8859b3d 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.c
+++ b/drivers/staging/comedi/drivers/ni_labpc.c
@@ -73,12 +73,14 @@ NI manuals:
*/
+#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/io.h>
+#include <linux/delay.h>
+
#include "../comedidev.h"
-#include <linux/delay.h>
#include <asm/dma.h>
#include "8253.h"
@@ -568,13 +570,11 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
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) {
- dev_err(dev->class_dev,
- "failed to allocate dma buffer\n");
+ devpriv->dma_buffer = kmalloc(dma_buffer_size,
+ GFP_KERNEL | GFP_DMA);
+ if (devpriv->dma_buffer == NULL)
return -ENOMEM;
- }
+
if (request_dma(dma_chan, DRV_NAME)) {
dev_err(dev->class_dev,
"failed to allocate dma channel %u\n",
@@ -1202,7 +1202,8 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
else
channel = CR_CHAN(cmd->chanlist[0]);
/* munge channel bits for differential / scan disabled mode */
- if (mode != MODE_SINGLE_CHAN && aref == AREF_DIFF)
+ if ((mode == MODE_SINGLE_CHAN || mode == MODE_SINGLE_CHAN_INTERVAL) &&
+ aref == AREF_DIFF)
channel *= 2;
devpriv->command1_bits |= ADC_CHAN_BITS(channel);
devpriv->command1_bits |= thisboard->ai_range_code[range];
@@ -1217,21 +1218,6 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->write_byte(devpriv->command1_bits,
dev->iobase + COMMAND1_REG);
}
- /* setup any external triggering/pacing (command4 register) */
- devpriv->command4_bits = 0;
- if (cmd->convert_src != TRIG_EXT)
- 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, mode) == 0) {
- devpriv->command4_bits |= INTERVAL_SCAN_EN_BIT;
- if (cmd->scan_begin_src == TRIG_EXT)
- devpriv->command4_bits |= EXT_SCAN_EN_BIT;
- }
- /* single-ended/differential */
- if (aref == AREF_DIFF)
- devpriv->command4_bits |= ADC_DIFF_BIT;
- devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG);
devpriv->write_byte(cmd->chanlist_len,
dev->iobase + INTERVAL_COUNT_REG);
@@ -1311,6 +1297,22 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->command3_bits &= ~ADC_FNE_INTR_EN_BIT;
devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);
+ /* setup any external triggering/pacing (command4 register) */
+ devpriv->command4_bits = 0;
+ if (cmd->convert_src != TRIG_EXT)
+ 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, mode) == 0) {
+ devpriv->command4_bits |= INTERVAL_SCAN_EN_BIT;
+ if (cmd->scan_begin_src == TRIG_EXT)
+ devpriv->command4_bits |= EXT_SCAN_EN_BIT;
+ }
+ /* single-ended/differential */
+ if (aref == AREF_DIFF)
+ devpriv->command4_bits |= ADC_DIFF_BIT;
+ devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG);
+
/* startup acquisition */
/* command2 reg */
@@ -2116,16 +2118,11 @@ static int labpc_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &labpc_driver);
}
-static void labpc_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static struct pci_driver labpc_pci_driver = {
.name = DRV_NAME,
.id_table = labpc_pci_table,
.probe = labpc_pci_probe,
- .remove = labpc_pci_remove
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(labpc_driver, labpc_pci_driver);
#else
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index bfe19fa7d66f..be7d1413b2e5 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -59,8 +59,6 @@ NI manuals:
*/
-#undef LABPC_DEBUG /* debugging messages */
-
#include "../comedidev.h"
#include <linux/delay.h>
@@ -75,240 +73,81 @@ NI manuals:
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
-static struct pcmcia_device *pcmcia_cur_dev;
-
-static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-
static const struct labpc_board_struct labpc_cs_boards[] = {
{
- .name = "daqcard-1200",
- .device_id = 0x103, /* 0x10b is manufacturer id,
- 0x103 is device id */
- .ai_speed = 10000,
- .bustype = pcmcia_bustype,
- .register_layout = labpc_1200_layout,
- .has_ao = 1,
- .ai_range_table = &range_labpc_1200_ai,
- .ai_range_code = labpc_1200_ai_gain_bits,
- .ai_range_is_unipolar = labpc_1200_is_unipolar,
- .ai_scan_up = 0,
- .memory_mapped_io = 0,
- },
- /* duplicate entry, to support using alternate name */
- {
- .name = "ni_labpc_cs",
- .device_id = 0x103,
- .ai_speed = 10000,
- .bustype = pcmcia_bustype,
- .register_layout = labpc_1200_layout,
- .has_ao = 1,
- .ai_range_table = &range_labpc_1200_ai,
- .ai_range_code = labpc_1200_ai_gain_bits,
- .ai_range_is_unipolar = labpc_1200_is_unipolar,
- .ai_scan_up = 0,
- .memory_mapped_io = 0,
- },
+ .name = "daqcard-1200",
+ .device_id = 0x103,
+ .ai_speed = 10000,
+ .bustype = pcmcia_bustype,
+ .register_layout = labpc_1200_layout,
+ .has_ao = 1,
+ .ai_range_table = &range_labpc_1200_ai,
+ .ai_range_code = labpc_1200_ai_gain_bits,
+ .ai_range_is_unipolar = labpc_1200_is_unipolar,
+ },
};
-/*
- * Useful for shorthand access to the particular board structure
- */
-#define thisboard ((const struct labpc_board_struct *)dev->board_ptr)
-
-static struct comedi_driver driver_labpc_cs = {
- .driver_name = "ni_labpc_cs",
- .module = THIS_MODULE,
- .attach = &labpc_attach,
- .detach = &labpc_common_detach,
- .num_names = ARRAY_SIZE(labpc_cs_boards),
- .board_name = &labpc_cs_boards[0].name,
- .offset = sizeof(struct labpc_board_struct),
-};
-
-static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int labpc_auto_attach(struct comedi_device *dev,
+ unsigned long context)
{
+ struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
struct labpc_private *devpriv;
- unsigned long iobase = 0;
- unsigned int irq = 0;
- struct pcmcia_device *link;
+ int ret;
+
+ /* The ni_labpc driver needs the board_ptr */
+ dev->board_ptr = &labpc_cs_boards[0];
+
+ link->config_flags |= CONF_AUTO_SET_IO |
+ CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
+ ret = comedi_pcmcia_enable(dev, NULL);
+ if (ret)
+ return ret;
+ dev->iobase = link->resource[0]->start;
+
+ if (!link->irq)
+ return -EINVAL;
devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
if (!devpriv)
return -ENOMEM;
dev->private = devpriv;
- /* get base address, irq etc. based on bustype */
- switch (thisboard->bustype) {
- case pcmcia_bustype:
- link = pcmcia_cur_dev; /* XXX hack */
- if (!link)
- return -EIO;
- iobase = link->resource[0]->start;
- irq = link->irq;
- break;
- default:
- pr_err("bug! couldn't determine board type\n");
- return -EINVAL;
- break;
- }
- return labpc_common_attach(dev, iobase, irq, 0);
+ return labpc_common_attach(dev, dev->iobase, link->irq, 0);
}
-static void labpc_config(struct pcmcia_device *link);
-static void labpc_release(struct pcmcia_device *link);
-static int labpc_cs_suspend(struct pcmcia_device *p_dev);
-static int labpc_cs_resume(struct pcmcia_device *p_dev);
-
-static int labpc_cs_attach(struct pcmcia_device *);
-static void labpc_cs_detach(struct pcmcia_device *);
+static void labpc_detach(struct comedi_device *dev)
+{
+ labpc_common_detach(dev);
+ comedi_pcmcia_disable(dev);
+}
-struct local_info_t {
- struct pcmcia_device *link;
- int stop;
- struct bus_operations *bus;
+static struct comedi_driver driver_labpc_cs = {
+ .driver_name = "ni_labpc_cs",
+ .module = THIS_MODULE,
+ .auto_attach = labpc_auto_attach,
+ .detach = labpc_detach,
};
static int labpc_cs_attach(struct pcmcia_device *link)
{
- struct local_info_t *local;
-
- dev_dbg(&link->dev, "labpc_cs_attach()\n");
-
- /* Allocate space for private device-specific data */
- local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
- if (!local)
- return -ENOMEM;
- local->link = link;
- link->priv = local;
-
- pcmcia_cur_dev = link;
-
- labpc_config(link);
-
- return 0;
-} /* labpc_cs_attach */
-
-static void labpc_cs_detach(struct pcmcia_device *link)
-{
- ((struct local_info_t *)link->priv)->stop = 1;
- labpc_release(link);
-
- /* This points to the parent local_info_t struct (may be null) */
- kfree(link->priv);
-
+ return comedi_pcmcia_auto_config(link, &driver_labpc_cs);
}
-static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev,
- void *priv_data)
-{
- if (p_dev->config_index == 0)
- return -EINVAL;
-
- return pcmcia_request_io(p_dev);
-}
-
-
-static void labpc_config(struct pcmcia_device *link)
-{
- int ret;
-
- dev_dbg(&link->dev, "labpc_config\n");
-
- link->config_flags |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ |
- CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
-
- ret = pcmcia_loop_config(link, labpc_pcmcia_config_loop, NULL);
- if (ret) {
- dev_warn(&link->dev, "no configuration found\n");
- goto failed;
- }
-
- if (!link->irq)
- goto failed;
-
- ret = pcmcia_enable_device(link);
- if (ret)
- goto failed;
-
- return;
-
-failed:
- labpc_release(link);
-
-} /* labpc_config */
-
-static void labpc_release(struct pcmcia_device *link)
-{
- dev_dbg(&link->dev, "labpc_release\n");
-
- pcmcia_disable_device(link);
-} /* labpc_release */
-
-static int labpc_cs_suspend(struct pcmcia_device *link)
-{
- struct local_info_t *local = link->priv;
-
- /* Mark the device as stopped, to block IO until later */
- local->stop = 1;
- return 0;
-} /* labpc_cs_suspend */
-
-static int labpc_cs_resume(struct pcmcia_device *link)
-{
- struct local_info_t *local = link->priv;
-
- local->stop = 0;
- return 0;
-} /* labpc_cs_resume */
-
static const struct pcmcia_device_id labpc_cs_ids[] = {
- /* N.B. These IDs should match those in labpc_cs_boards (ni_labpc.c) */
PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0103), /* daqcard-1200 */
PCMCIA_DEVICE_NULL
};
-
MODULE_DEVICE_TABLE(pcmcia, labpc_cs_ids);
-MODULE_AUTHOR("Frank Mori Hess <fmhess@users.sourceforge.net>");
-MODULE_DESCRIPTION("Comedi driver for National Instruments Lab-PC");
-MODULE_LICENSE("GPL");
static struct pcmcia_driver labpc_cs_driver = {
- .probe = labpc_cs_attach,
- .remove = labpc_cs_detach,
- .suspend = labpc_cs_suspend,
- .resume = labpc_cs_resume,
- .id_table = labpc_cs_ids,
- .owner = THIS_MODULE,
- .name = "daqcard-1200",
+ .name = "daqcard-1200",
+ .owner = THIS_MODULE,
+ .id_table = labpc_cs_ids,
+ .probe = labpc_cs_attach,
+ .remove = comedi_pcmcia_auto_unconfig,
};
+module_comedi_pcmcia_driver(driver_labpc_cs, labpc_cs_driver);
-static int __init init_labpc_cs(void)
-{
- pcmcia_register_driver(&labpc_cs_driver);
- return 0;
-}
-
-static void __exit exit_labpc_cs(void)
-{
- pcmcia_unregister_driver(&labpc_cs_driver);
-}
-
-static int __init labpc_init_module(void)
-{
- int ret;
-
- ret = init_labpc_cs();
- if (ret < 0)
- return ret;
-
- return comedi_driver_register(&driver_labpc_cs);
-}
-
-static void __exit labpc_exit_module(void)
-{
- exit_labpc_cs();
- comedi_driver_unregister(&driver_labpc_cs);
-}
-
-module_init(labpc_init_module);
-module_exit(labpc_exit_module);
+MODULE_DESCRIPTION("Comedi driver for National Instruments Lab-PC");
+MODULE_AUTHOR("Frank Mori Hess <fmhess@users.sourceforge.net>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index 56dc59908d36..b7403597e905 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -986,7 +986,7 @@ static void ni_event(struct comedi_device *dev, struct comedi_subdevice *s)
if (s->
async->events & (COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW |
COMEDI_CB_EOA)) {
- switch (s - dev->subdevices) {
+ switch (s->index) {
case NI_AI_SUBDEV:
ni_ai_reset(dev, s);
break;
@@ -1086,7 +1086,7 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status,
("ni_mio_common: a_status=0xffff. Card removed?\n");
/* we probably aren't even running a command now,
* so it's a good idea to be careful. */
- if (comedi_get_subdevice_runflags(s) & SRF_RUNNING) {
+ if (comedi_is_subdevice_running(s)) {
s->async->events |=
COMEDI_CB_ERROR | COMEDI_CB_EOA;
ni_event(dev, s);
diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
index 76c6a13ea9d6..888be7b89d2d 100644
--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
+++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
@@ -65,112 +65,90 @@ See the notes in the ni_atmio.o driver.
#define MAX_N_CALDACS 32
static const struct ni_board_struct ni_boards[] = {
- {.device_id = 0x010d,
- .name = "DAQCard-ai-16xe-50",
- .n_adchan = 16,
- .adbits = 16,
- .ai_fifo_depth = 1024,
- .alwaysdither = 0,
- .gainlkup = ai_gain_8,
- .ai_speed = 5000,
- .n_aochan = 0,
- .aobits = 0,
- .ao_fifo_depth = 0,
- .ao_unipolar = 0,
- .num_p0_dio_channels = 8,
- .has_8255 = 0,
- .caldac = {dac8800, dac8043},
- },
- {.device_id = 0x010c,
- .name = "DAQCard-ai-16e-4",
- .n_adchan = 16,
- .adbits = 12,
- .ai_fifo_depth = 1024,
- .alwaysdither = 0,
- .gainlkup = ai_gain_16,
- .ai_speed = 4000,
- .n_aochan = 0,
- .aobits = 0,
- .ao_fifo_depth = 0,
- .ao_unipolar = 0,
- .num_p0_dio_channels = 8,
- .has_8255 = 0,
- .caldac = {mb88341}, /* verified */
- },
- {.device_id = 0x02c4,
- .name = "DAQCard-6062E",
- .n_adchan = 16,
- .adbits = 12,
- .ai_fifo_depth = 8192,
- .alwaysdither = 0,
- .gainlkup = ai_gain_16,
- .ai_speed = 2000,
- .n_aochan = 2,
- .aobits = 12,
- .ao_fifo_depth = 2048,
- .ao_range_table = &range_bipolar10,
- .ao_unipolar = 0,
- .ao_speed = 1176,
- .num_p0_dio_channels = 8,
- .has_8255 = 0,
- .caldac = {ad8804_debug}, /* verified */
- },
- {.device_id = 0x075e,
- .name = "DAQCard-6024E", /* specs incorrect! */
- .n_adchan = 16,
- .adbits = 12,
- .ai_fifo_depth = 1024,
- .alwaysdither = 0,
- .gainlkup = ai_gain_4,
- .ai_speed = 5000,
- .n_aochan = 2,
- .aobits = 12,
- .ao_fifo_depth = 0,
- .ao_range_table = &range_bipolar10,
- .ao_unipolar = 0,
- .ao_speed = 1000000,
- .num_p0_dio_channels = 8,
- .has_8255 = 0,
- .caldac = {ad8804_debug},
- },
- {.device_id = 0x0245,
- .name = "DAQCard-6036E", /* specs incorrect! */
- .n_adchan = 16,
- .adbits = 16,
- .ai_fifo_depth = 1024,
- .alwaysdither = 1,
- .gainlkup = ai_gain_4,
- .ai_speed = 5000,
- .n_aochan = 2,
- .aobits = 16,
- .ao_fifo_depth = 0,
- .ao_range_table = &range_bipolar10,
- .ao_unipolar = 0,
- .ao_speed = 1000000,
- .num_p0_dio_channels = 8,
- .has_8255 = 0,
- .caldac = {ad8804_debug},
+ {
+ .device_id = 0x010d,
+ .name = "DAQCard-ai-16xe-50",
+ .n_adchan = 16,
+ .adbits = 16,
+ .ai_fifo_depth = 1024,
+ .gainlkup = ai_gain_8,
+ .ai_speed = 5000,
+ .num_p0_dio_channels = 8,
+ .caldac = { dac8800, dac8043 },
+ }, {
+ .device_id = 0x010c,
+ .name = "DAQCard-ai-16e-4",
+ .n_adchan = 16,
+ .adbits = 12,
+ .ai_fifo_depth = 1024,
+ .gainlkup = ai_gain_16,
+ .ai_speed = 4000,
+ .num_p0_dio_channels = 8,
+ .caldac = { mb88341 }, /* verified */
+ }, {
+ .device_id = 0x02c4,
+ .name = "DAQCard-6062E",
+ .n_adchan = 16,
+ .adbits = 12,
+ .ai_fifo_depth = 8192,
+ .gainlkup = ai_gain_16,
+ .ai_speed = 2000,
+ .n_aochan = 2,
+ .aobits = 12,
+ .ao_fifo_depth = 2048,
+ .ao_range_table = &range_bipolar10,
+ .ao_speed = 1176,
+ .num_p0_dio_channels = 8,
+ .caldac = { ad8804_debug }, /* verified */
+ }, {
+ /* specs incorrect! */
+ .device_id = 0x075e,
+ .name = "DAQCard-6024E",
+ .n_adchan = 16,
+ .adbits = 12,
+ .ai_fifo_depth = 1024,
+ .gainlkup = ai_gain_4,
+ .ai_speed = 5000,
+ .n_aochan = 2,
+ .aobits = 12,
+ .ao_range_table = &range_bipolar10,
+ .ao_speed = 1000000,
+ .num_p0_dio_channels = 8,
+ .caldac = { ad8804_debug },
+ }, {
+ /* specs incorrect! */
+ .device_id = 0x0245,
+ .name = "DAQCard-6036E",
+ .n_adchan = 16,
+ .adbits = 16,
+ .ai_fifo_depth = 1024,
+ .alwaysdither = 1,
+ .gainlkup = ai_gain_4,
+ .ai_speed = 5000,
+ .n_aochan = 2,
+ .aobits = 16,
+ .ao_range_table = &range_bipolar10,
+ .ao_speed = 1000000,
+ .num_p0_dio_channels = 8,
+ .caldac = { ad8804_debug },
},
#if 0
- {.device_id = 0x0000, /* unknown */
- .name = "DAQCard-6715",
- .n_adchan = 0,
- .n_aochan = 8,
- .aobits = 12,
- .ao_671x = 8192,
- .num_p0_dio_channels = 8,
- .caldac = {mb88341, mb88341},
- },
+ {
+ .device_id = 0x0000, /* unknown */
+ .name = "DAQCard-6715",
+ .n_aochan = 8,
+ .aobits = 12,
+ .ao_671x = 8192,
+ .num_p0_dio_channels = 8,
+ .caldac = { mb88341, mb88341 },
+ },
#endif
- /* N.B. Update ni_mio_cs_ids[] when entries added above. */
};
#define interrupt_pin(a) 0
#define IRQ_POLARITY 1
-#define NI_E_IRQ_FLAGS IRQF_SHARED
-
struct ni_private {
struct pcmcia_device *link;
@@ -225,67 +203,22 @@ static uint16_t mio_cs_win_in(struct comedi_device *dev, int addr)
return ret;
}
-static int mio_cs_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
-static void mio_cs_detach(struct comedi_device *dev);
-static struct comedi_driver driver_ni_mio_cs = {
- .driver_name = "ni_mio_cs",
- .module = THIS_MODULE,
- .attach = mio_cs_attach,
- .detach = mio_cs_detach,
-};
-
#include "ni_mio_common.c"
-static int ni_getboardtype(struct comedi_device *dev,
- struct pcmcia_device *link);
-
-static void mio_cs_detach(struct comedi_device *dev)
-{
- mio_common_detach(dev);
- if (dev->irq)
- free_irq(dev->irq, dev);
-}
-
-static void mio_cs_config(struct pcmcia_device *link);
-static void cs_release(struct pcmcia_device *link);
-static void cs_detach(struct pcmcia_device *);
-
-static struct pcmcia_device *cur_dev;
-
-static int cs_attach(struct pcmcia_device *link)
+static const void *ni_getboardtype(struct comedi_device *dev,
+ struct pcmcia_device *link)
{
- cur_dev = link;
-
- mio_cs_config(link);
-
- return 0;
-}
-
-static void cs_release(struct pcmcia_device *link)
-{
- pcmcia_disable_device(link);
-}
-
-static void cs_detach(struct pcmcia_device *link)
-{
- cs_release(link);
-}
-
-static int mio_cs_suspend(struct pcmcia_device *link)
-{
- DPRINTK("pm suspend\n");
-
- return 0;
-}
+ static const struct ni_board_struct *board;
+ int i;
-static int mio_cs_resume(struct pcmcia_device *link)
-{
- DPRINTK("pm resume\n");
- return 0;
+ for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
+ board = &ni_boards[i];
+ if (board->device_id == link->card_id)
+ return board;
+ }
+ return NULL;
}
-
static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data)
{
int base, ret;
@@ -302,114 +235,63 @@ static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data)
return -ENODEV;
}
-
-static void mio_cs_config(struct pcmcia_device *link)
-{
- int ret;
-
- DPRINTK("mio_cs_config(link=%p)\n", link);
- link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
-
- ret = pcmcia_loop_config(link, mio_pcmcia_config_loop, NULL);
- if (ret) {
- dev_warn(&link->dev, "no configuration found\n");
- return;
- }
-
- if (!link->irq)
- dev_info(&link->dev, "no IRQ available\n");
-
- ret = pcmcia_enable_device(link);
-}
-
-static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int mio_cs_auto_attach(struct comedi_device *dev,
+ unsigned long context)
{
+ struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
+ static const struct ni_board_struct *board;
struct ni_private *devpriv;
- struct pcmcia_device *link;
- unsigned int irq;
int ret;
- DPRINTK("mio_cs_attach(dev=%p,it=%p)\n", dev, it);
-
- link = cur_dev; /* XXX hack */
- if (!link)
- return -EIO;
+ board = ni_getboardtype(dev, link);
+ if (!board)
+ return -ENODEV;
+ dev->board_ptr = board;
+ dev->board_name = board->name;
- dev->driver = &driver_ni_mio_cs;
+ link->config_flags |= CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
+ ret = comedi_pcmcia_enable(dev, mio_pcmcia_config_loop);
+ if (ret)
+ return ret;
dev->iobase = link->resource[0]->start;
- irq = link->irq;
-
- dev->board_ptr = ni_boards + ni_getboardtype(dev, link);
-
-#if 0
- {
- int i;
-
- printk("comedi%d: %s: DAQCard: io 0x%04lx, irq %u, ",
- dev->minor, dev->driver->driver_name, dev->iobase, irq);
-
- printk(" board fingerprint:");
- for (i = 0; i < 32; i += 2) {
- printk(" %04x %02x", inw(dev->iobase + i),
- inb(dev->iobase + i + 1));
- }
- printk("\n");
- printk(" board fingerprint (windowed):");
- for (i = 0; i < 10; i++)
- printk(" 0x%04x", win_in(i));
- printk("\n");
-
- printk("boardtype.name: %s\n", boardtype.name);
- }
-#endif
-
- dev->board_name = boardtype.name;
-
- ret = request_irq(irq, ni_E_interrupt, NI_E_IRQ_FLAGS,
- "ni_mio_cs", dev);
- if (ret < 0) {
- dev_err(dev->class_dev, "irq not available\n");
- return -EINVAL;
- }
- dev->irq = irq;
+ link->priv = dev;
+ ret = pcmcia_request_irq(link, ni_E_interrupt);
+ if (ret)
+ return ret;
+ dev->irq = link->irq;
ret = ni_alloc_private(dev);
if (ret)
return ret;
- devpriv = dev->private;
-
- devpriv->stc_writew = &mio_cs_win_out;
- devpriv->stc_readw = &mio_cs_win_in;
- devpriv->stc_writel = &win_out2;
- devpriv->stc_readl = &win_in2;
-
- ret = ni_E_init(dev);
- if (ret < 0)
- return ret;
+ devpriv = dev->private;
+ devpriv->stc_writew = mio_cs_win_out;
+ devpriv->stc_readw = mio_cs_win_in;
+ devpriv->stc_writel = win_out2;
+ devpriv->stc_readl = win_in2;
- return 0;
+ return ni_E_init(dev);
}
-static int ni_getboardtype(struct comedi_device *dev,
- struct pcmcia_device *link)
+static void mio_cs_detach(struct comedi_device *dev)
{
- int i;
-
- for (i = 0; i < n_ni_boards; i++) {
- if (ni_boards[i].device_id == link->card_id)
- return i;
- }
+ mio_common_detach(dev);
+ comedi_pcmcia_disable(dev);
+}
- dev_err(dev->class_dev,
- "unknown board 0x%04x -- pretend it is a ", link->card_id);
+static struct comedi_driver driver_ni_mio_cs = {
+ .driver_name = "ni_mio_cs",
+ .module = THIS_MODULE,
+ .auto_attach = mio_cs_auto_attach,
+ .detach = mio_cs_detach,
+};
- return 0;
+static int cs_attach(struct pcmcia_device *link)
+{
+ return comedi_pcmcia_auto_config(link, &driver_ni_mio_cs);
}
-#ifdef MODULE
-
static const struct pcmcia_device_id ni_mio_cs_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x010b, 0x010d), /* DAQCard-ai-16xe-50 */
PCMCIA_DEVICE_MANF_CARD(0x010b, 0x010c), /* DAQCard-ai-16e-4 */
@@ -418,36 +300,17 @@ static const struct pcmcia_device_id ni_mio_cs_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0245), /* DAQCard-6036E */
PCMCIA_DEVICE_NULL
};
-
MODULE_DEVICE_TABLE(pcmcia, ni_mio_cs_ids);
-MODULE_AUTHOR("David A. Schleef <ds@schleef.org>");
-MODULE_DESCRIPTION("Comedi driver for National Instruments DAQCard E series");
-MODULE_LICENSE("GPL");
static struct pcmcia_driver ni_mio_cs_driver = {
- .probe = &cs_attach,
- .remove = &cs_detach,
- .suspend = &mio_cs_suspend,
- .resume = &mio_cs_resume,
- .id_table = ni_mio_cs_ids,
- .owner = THIS_MODULE,
- .name = "ni_mio_cs",
+ .name = "ni_mio_cs",
+ .owner = THIS_MODULE,
+ .id_table = ni_mio_cs_ids,
+ .probe = cs_attach,
+ .remove = comedi_pcmcia_auto_unconfig,
};
+module_comedi_pcmcia_driver(driver_ni_mio_cs, ni_mio_cs_driver);
-int init_module(void)
-{
- pcmcia_register_driver(&ni_mio_cs_driver);
- comedi_driver_register(&driver_ni_mio_cs);
- return 0;
-}
-
-void cleanup_module(void)
-{
- pcmcia_unregister_driver(&ni_mio_cs_driver);
-#if 0
- while (cur_dev != NULL)
- cs_detach(cur_dev->handle);
-#endif
- comedi_driver_unregister(&driver_ni_mio_cs);
-}
-#endif
+MODULE_DESCRIPTION("Comedi driver for National Instruments DAQCard E series");
+MODULE_AUTHOR("David A. Schleef <ds@schleef.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
index 084ebea33ab9..0a00260d11f3 100644
--- a/drivers/staging/comedi/drivers/ni_pcidio.c
+++ b/drivers/staging/comedi/drivers/ni_pcidio.c
@@ -55,9 +55,11 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org
/* #define DEBUG 1 */
/* #define DEBUG_FLAGS */
+#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/firmware.h>
+
#include "../comedidev.h"
#include "comedi_fc.h"
@@ -1224,11 +1226,6 @@ static int ni_pcidio_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &ni_pcidio_driver);
}
-static void ni_pcidio_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(ni_pcidio_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1150) },
{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1320) },
@@ -1241,7 +1238,7 @@ static struct pci_driver ni_pcidio_pci_driver = {
.name = "ni_pcidio",
.id_table = ni_pcidio_pci_table,
.probe = ni_pcidio_pci_probe,
- .remove = ni_pcidio_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(ni_pcidio_driver, ni_pcidio_pci_driver);
diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
index fd1662b4175d..98b43f2fc65d 100644
--- a/drivers/staging/comedi/drivers/ni_pcimio.c
+++ b/drivers/staging/comedi/drivers/ni_pcimio.c
@@ -110,10 +110,12 @@ Bugs:
*/
+#include <linux/delay.h>
+#include <linux/delay.h>
+
#include "../comedidev.h"
#include <asm/byteorder.h>
-#include <linux/delay.h>
#include "ni_stc.h"
#include "mite.h"
@@ -1791,11 +1793,6 @@ static int ni_pcimio_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &ni_pcimio_driver);
}
-static void ni_pcimio_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(ni_pcimio_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x0162) },
{ PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1170) },
@@ -1858,7 +1855,7 @@ static struct pci_driver ni_pcimio_pci_driver = {
.name = "ni_pcimio",
.id_table = ni_pcimio_pci_table,
.probe = ni_pcimio_pci_probe,
- .remove = ni_pcimio_pci_remove
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(ni_pcimio_driver, ni_pcimio_pci_driver);
diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c
index 98f87897e2a8..225287769dc1 100644
--- a/drivers/staging/comedi/drivers/ni_tio.c
+++ b/drivers/staging/comedi/drivers/ni_tio.c
@@ -276,7 +276,7 @@ static inline unsigned NI_660x_RTSI_Second_Gate_Select(unsigned n)
}
static const unsigned int counter_status_mask =
- COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING;
+ COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING;
static int __init ni_tio_init_module(void)
{
diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c
index 0c991b99da13..13747f324936 100644
--- a/drivers/staging/comedi/drivers/ni_tiocmd.c
+++ b/drivers/staging/comedi/drivers/ni_tiocmd.c
@@ -159,6 +159,7 @@ static int ni_tio_input_cmd(struct ni_gpct *counter, struct comedi_async *async)
async->inttrig = NULL;
mite_dma_arm(counter->mite_chan);
retval = ni_tio_arm(counter, 1, cmd->start_arg);
+ break;
case TRIG_OTHER:
async->inttrig = NULL;
mite_dma_arm(counter->mite_chan);
diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
index 06127a5f62a0..b5af22eb7c37 100644
--- a/drivers/staging/comedi/drivers/pcl818.c
+++ b/drivers/staging/comedi/drivers/pcl818.c
@@ -243,8 +243,8 @@ static const struct comedi_lrange range_pcl818l_h_ai = { 4, {
};
static const struct comedi_lrange range718_bipolar1 = { 1, {BIP_RANGE(1),} };
-static const struct comedi_lrange range718_bipolar0_5 =
- { 1, {BIP_RANGE(0.5),} };
+static const struct comedi_lrange range718_bipolar0_5 = {
+ 1, {BIP_RANGE(0.5),} };
static const struct comedi_lrange range718_unipolar2 = { 1, {UNI_RANGE(2),} };
static const struct comedi_lrange range718_unipolar1 = { 1, {BIP_RANGE(1),} };
@@ -1005,17 +1005,14 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev,
switch (devpriv->dma) {
case 1: /* DMA */
case 3:
- if (devpriv->dma_rtc == 0) {
+ if (devpriv->dma_rtc == 0)
pcl818_ai_mode13dma_int(mode, dev, s);
- }
#ifdef unused
- else {
+ else
pcl818_ai_mode13dma_rtc(mode, dev, s);
- }
#else
- else {
+ else
return -EINVAL;
- }
#endif
break;
case 0:
@@ -1069,7 +1066,7 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev,
*/
#ifdef PCL818_MODE13_AO
static int pcl818_ao_mode13(int mode, struct comedi_device *dev,
- struct comedi_subdevice *s, comedi_trig * it)
+ struct comedi_subdevice *s, comedi_trig *it)
{
struct pcl818_private *devpriv = dev->private;
int divisor1 = 0, divisor2 = 0;
@@ -1124,7 +1121,7 @@ static int pcl818_ao_mode13(int mode, struct comedi_device *dev,
ANALOG OUTPUT MODE 1, 818 cards
*/
static int pcl818_ao_mode1(struct comedi_device *dev,
- struct comedi_subdevice *s, comedi_trig * it)
+ struct comedi_subdevice *s, comedi_trig *it)
{
return pcl818_ao_mode13(1, dev, s, it);
}
@@ -1134,7 +1131,7 @@ static int pcl818_ao_mode1(struct comedi_device *dev,
ANALOG OUTPUT MODE 3, 818 cards
*/
static int pcl818_ao_mode3(struct comedi_device *dev,
- struct comedi_subdevice *s, comedi_trig * it)
+ struct comedi_subdevice *s, comedi_trig *it)
{
return pcl818_ao_mode13(3, dev, s, it);
}
diff --git a/drivers/staging/comedi/drivers/pcm_common.c b/drivers/staging/comedi/drivers/pcm_common.c
deleted file mode 100644
index 8a718aea6f3c..000000000000
--- a/drivers/staging/comedi/drivers/pcm_common.c
+++ /dev/null
@@ -1,63 +0,0 @@
-#include "../comedidev.h"
-
-#include "comedi_fc.h"
-#include "pcm_common.h"
-
-int comedi_pcm_cmdtest(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_cmd *cmd)
-{
- int err = 0;
-
- /* Step 1 : check if triggers are trivially valid */
-
- 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 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;
-
- /* Step 3: check if arguments are trivially valid */
-
- err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
- err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
- err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
- err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
-
- switch (cmd->stop_src) {
- case TRIG_COUNT:
- /* any count allowed */
- break;
- case TRIG_NONE:
- err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
- break;
- default:
- break;
- }
-
- if (err)
- return 3;
-
- /* step 4: fix up any arguments */
-
- /* if (err) return 4; */
-
- return 0;
-}
-EXPORT_SYMBOL(comedi_pcm_cmdtest);
-
-MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcm_common.h b/drivers/staging/comedi/drivers/pcm_common.h
deleted file mode 100644
index cd4840c11444..000000000000
--- a/drivers/staging/comedi/drivers/pcm_common.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _comedi_common_H
-#define _comedi_common_H
-
-extern int comedi_pcm_cmdtest(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_cmd *cmd);
-
-#endif
diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
index 0882dafaf57b..13f79f49748a 100644
--- a/drivers/staging/comedi/drivers/pcmda12.c
+++ b/drivers/staging/comedi/drivers/pcmda12.c
@@ -53,9 +53,6 @@ Configuration Options:
#include "../comedidev.h"
-#include <linux/pci.h> /* for PCI devices */
-
-#define SDEV_NO ((int)(s - dev->subdevices))
#define CHANS 8
#define IOSIZE 16
#define LSB(x) ((unsigned char)((x) & 0xff))
diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
index 7522bfb6db08..5fa1fe08eb97 100644
--- a/drivers/staging/comedi/drivers/pcmmio.c
+++ b/drivers/staging/comedi/drivers/pcmmio.c
@@ -78,9 +78,10 @@ Configuration Options:
#include <linux/interrupt.h>
#include <linux/slab.h>
+
#include "../comedidev.h"
-#include "pcm_common.h"
-#include <linux/pci.h> /* for PCI devices */
+
+#include "comedi_fc.h"
/* This stuff is all from pcmuio.c -- it refers to the DIO subdevices only */
#define CHANS_PER_PORT 8
@@ -93,7 +94,6 @@ Configuration Options:
#define INTR_PORTS_PER_SUBDEV (INTR_CHANS_PER_ASIC/CHANS_PER_PORT)
#define MAX_DIO_CHANS (PORTS_PER_ASIC*1*CHANS_PER_PORT)
#define MAX_ASICS (MAX_DIO_CHANS/CHANS_PER_ASIC)
-#define SDEV_NO ((int)(s - dev->subdevices))
#define CALC_N_DIO_SUBDEVS(nchans) ((nchans)/MAX_CHANS_PER_SUBDEV + (!!((nchans)%MAX_CHANS_PER_SUBDEV)) /*+ (nchans > INTR_CHANS_PER_ASIC ? 2 : 1)*/)
/* IO Memory sizes */
#define ASIC_IOSIZE (0x0B)
@@ -802,11 +802,59 @@ static int pcmmio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
return 0;
}
-static int
-pcmmio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_cmd *cmd)
+static int pcmmio_cmdtest(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_cmd *cmd)
{
- return comedi_pcm_cmdtest(dev, s, cmd);
+ int err = 0;
+
+ /* Step 1 : check if triggers are trivially valid */
+
+ 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 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;
+
+ /* Step 3: check if arguments are trivially valid */
+
+ err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+ err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+ err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+ err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+ switch (cmd->stop_src) {
+ case TRIG_COUNT:
+ /* any count allowed */
+ break;
+ case TRIG_NONE:
+ err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+ break;
+ default:
+ break;
+ }
+
+ if (err)
+ return 3;
+
+ /* step 4: fix up any arguments */
+
+ /* if (err) return 4; */
+
+ return 0;
}
static int adc_wait_ready(unsigned long iobase)
diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
index 31ea20c2d39e..433270ceda4f 100644
--- a/drivers/staging/comedi/drivers/pcmuio.c
+++ b/drivers/staging/comedi/drivers/pcmuio.c
@@ -77,10 +77,10 @@ Configuration Options:
#include <linux/interrupt.h>
#include <linux/slab.h>
+
#include "../comedidev.h"
-#include "pcm_common.h"
-#include <linux/pci.h> /* for PCI devices */
+#include "comedi_fc.h"
#define CHANS_PER_PORT 8
#define PORTS_PER_ASIC 6
@@ -92,7 +92,6 @@ Configuration Options:
#define INTR_PORTS_PER_SUBDEV (INTR_CHANS_PER_ASIC/CHANS_PER_PORT)
#define MAX_DIO_CHANS (PORTS_PER_ASIC*2*CHANS_PER_PORT)
#define MAX_ASICS (MAX_DIO_CHANS/CHANS_PER_ASIC)
-#define SDEV_NO ((int)(s - dev->subdevices))
#define CALC_N_SUBDEVS(nchans) ((nchans)/MAX_CHANS_PER_SUBDEV + (!!((nchans)%MAX_CHANS_PER_SUBDEV)) /*+ (nchans > INTR_CHANS_PER_ASIC ? 2 : 1)*/)
/* IO Memory sizes */
#define ASIC_IOSIZE (0x10)
@@ -740,11 +739,59 @@ static int pcmuio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
return 0;
}
-static int
-pcmuio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_cmd *cmd)
+static int pcmuio_cmdtest(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_cmd *cmd)
{
- return comedi_pcm_cmdtest(dev, s, cmd);
+ int err = 0;
+
+ /* Step 1 : check if triggers are trivially valid */
+
+ 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 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;
+
+ /* Step 3: check if arguments are trivially valid */
+
+ err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+ err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+ err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+ err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+ switch (cmd->stop_src) {
+ case TRIG_COUNT:
+ /* any count allowed */
+ break;
+ case TRIG_NONE:
+ err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+ break;
+ default:
+ break;
+ }
+
+ if (err)
+ return 3;
+
+ /* step 4: fix up any arguments */
+
+ /* if (err) return 4; */
+
+ return 0;
}
static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
@@ -791,14 +838,11 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
chans_left = CHANS_PER_ASIC * board->num_asics;
n_subdevs = CALC_N_SUBDEVS(chans_left);
- devpriv->sprivs =
- kcalloc(n_subdevs, sizeof(struct pcmuio_subdev_private),
- GFP_KERNEL);
- if (!devpriv->sprivs) {
- dev_warn(dev->class_dev,
- "cannot allocate subdevice private data structures\n");
+ devpriv->sprivs = kcalloc(n_subdevs,
+ sizeof(struct pcmuio_subdev_private),
+ GFP_KERNEL);
+ if (!devpriv->sprivs)
return -ENOMEM;
- }
ret = comedi_alloc_subdevices(dev, n_subdevs);
if (ret)
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
index ef0cdaa7f02e..911eb6b32296 100644
--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
@@ -47,8 +47,6 @@ Status: works
Devices: [Quatech] DAQP-208 (daqp), DAQP-308
*/
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
#include "../comedidev.h"
#include <linux/semaphore.h>
@@ -60,28 +58,16 @@ Devices: [Quatech] DAQP-208 (daqp), DAQP-308
#include "comedi_fc.h"
-/* Maximum number of separate DAQP devices we'll allow */
-#define MAX_DEV 4
-
-struct local_info_t {
- struct pcmcia_device *link;
+struct daqp_private {
int stop;
- int table_index;
- char board_name[32];
enum { semaphore, buffer } interrupt_mode;
struct completion eos;
- struct comedi_device *dev;
- struct comedi_subdevice *s;
int count;
};
-/* A list of "instances" of the device. */
-
-static struct local_info_t *dev_table[MAX_DEV] = { NULL, /* ... */ };
-
/* The DAQP communicates with the system through a 16 byte I/O window. */
#define DAQP_FIFO_SIZE 4096
@@ -165,84 +151,38 @@ static struct local_info_t *dev_table[MAX_DEV] = { NULL, /* ... */ };
#define DAQP_AUX_FIFO_NEARFULL 0x02
#define DAQP_AUX_FIFO_EMPTY 0x01
-/* These range structures tell COMEDI how the sample values map to
- * voltages. The A/D converter has four .ranges = +/- 10V through
- * +/- 1.25V, and the D/A converter has only .one = +/- 5V.
- */
-
-static const struct comedi_lrange range_daqp_ai = { 4, {
- BIP_RANGE(10),
- BIP_RANGE(5),
- BIP_RANGE(2.5),
- BIP_RANGE(1.25)
- }
-};
-
-static const struct comedi_lrange range_daqp_ao = { 1, {BIP_RANGE(5)} };
-
-/*====================================================================*/
-
-/* comedi interface code */
-
-static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static void daqp_detach(struct comedi_device *dev);
-static struct comedi_driver driver_daqp = {
- .driver_name = "quatech_daqp_cs",
- .module = THIS_MODULE,
- .attach = daqp_attach,
- .detach = daqp_detach,
-};
-
-#ifdef DAQP_DEBUG
-
-static void daqp_dump(struct comedi_device *dev)
-{
- dev_info(dev->class_dev, "status %02x; aux status %02x\n",
- inb(dev->iobase + DAQP_STATUS), inb(dev->iobase + DAQP_AUX));
-}
-
-static void hex_dump(char *str, void *ptr, int len)
-{
- unsigned char *cptr = ptr;
- int i;
-
- printk(str);
-
- for (i = 0; i < len; i++) {
- if (i % 16 == 0)
- printk("\n%p:", cptr);
-
- printk(" %02x", *(cptr++));
+static const struct comedi_lrange range_daqp_ai = {
+ 4, {
+ BIP_RANGE(10),
+ BIP_RANGE(5),
+ BIP_RANGE(2.5),
+ BIP_RANGE(1.25)
}
- printk("\n");
-}
-
-#endif
+};
/* Cancel a running acquisition */
static int daqp_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
{
- struct local_info_t *local = (struct local_info_t *)s->private;
+ struct daqp_private *devpriv = dev->private;
- if (local->stop)
+ if (devpriv->stop)
return -EIO;
-
outb(DAQP_COMMAND_STOP, dev->iobase + DAQP_COMMAND);
/* flush any linguring data in FIFO - superfluous here */
/* outb(DAQP_COMMAND_RSTF, dev->iobase+DAQP_COMMAND); */
- local->interrupt_mode = semaphore;
+ devpriv->interrupt_mode = semaphore;
return 0;
}
/* Interrupt handler
*
- * Operates in one of two modes. If local->interrupt_mode is
- * 'semaphore', just signal the local->eos completion and return
+ * Operates in one of two modes. If devpriv->interrupt_mode is
+ * 'semaphore', just signal the devpriv->eos completion and return
* (one-shot mode). Otherwise (continuous mode), read data in from
* the card, transfer it to the buffer provided by the higher-level
* comedi kernel module, and signal various comedi callback routines,
@@ -250,48 +190,21 @@ static int daqp_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
*/
static enum irqreturn daqp_interrupt(int irq, void *dev_id)
{
- struct local_info_t *local = (struct local_info_t *)dev_id;
- struct comedi_device *dev;
- struct comedi_subdevice *s;
+ struct comedi_device *dev = dev_id;
+ struct daqp_private *devpriv = dev->private;
+ struct comedi_subdevice *s = dev->read_subdev;
int loop_limit = 10000;
int status;
- if (local == NULL) {
- pr_warn("irq %d for unknown device.\n", irq);
+ if (!dev->attached)
return IRQ_NONE;
- }
-
- dev = local->dev;
- if (dev == NULL) {
- pr_warn("NULL comedi_device.\n");
- return IRQ_NONE;
- }
-
- if (!dev->attached) {
- pr_warn("struct comedi_device not yet attached.\n");
- return IRQ_NONE;
- }
-
- s = local->s;
- if (s == NULL) {
- pr_warn("NULL comedi_subdevice.\n");
- return IRQ_NONE;
- }
-
- if ((struct local_info_t *)s->private != local) {
- pr_warn("invalid comedi_subdevice.\n");
- return IRQ_NONE;
- }
-
- switch (local->interrupt_mode) {
+ switch (devpriv->interrupt_mode) {
case semaphore:
-
- complete(&local->eos);
+ complete(&devpriv->eos);
break;
case buffer:
-
while (!((status = inb(dev->iobase + DAQP_STATUS))
& DAQP_STATUS_FIFO_EMPTY)) {
@@ -315,9 +228,9 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id)
* and stop conversion if zero
*/
- if (local->count > 0) {
- local->count--;
- if (local->count == 0) {
+ if (devpriv->count > 0) {
+ devpriv->count--;
+ if (devpriv->count == 0) {
daqp_ai_cancel(dev, s);
s->async->events |= COMEDI_CB_EOA;
break;
@@ -342,21 +255,41 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static void daqp_ai_set_one_scanlist_entry(struct comedi_device *dev,
+ unsigned int chanspec,
+ int start)
+{
+ unsigned int chan = CR_CHAN(chanspec);
+ unsigned int range = CR_RANGE(chanspec);
+ unsigned int aref = CR_AREF(chanspec);
+ unsigned int val;
+
+ val = DAQP_SCANLIST_CHANNEL(chan) | DAQP_SCANLIST_GAIN(range);
+
+ if (aref == AREF_DIFF)
+ val |= DAQP_SCANLIST_DIFFERENTIAL;
+
+ if (start)
+ val |= DAQP_SCANLIST_START;
+
+ outb(val & 0xff, dev->iobase + DAQP_SCANLIST);
+ outb((val >> 8) & 0xff, dev->iobase + DAQP_SCANLIST);
+}
+
/* One-shot analog data acquisition routine */
static int daqp_ai_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
- struct local_info_t *local = (struct local_info_t *)s->private;
+ struct daqp_private *devpriv = dev->private;
int i;
int v;
int counter = 10000;
- if (local->stop)
+ if (devpriv->stop)
return -EIO;
-
/* Stop any running conversion */
daqp_ai_cancel(dev, s);
@@ -366,18 +299,7 @@ static int daqp_ai_insn_read(struct comedi_device *dev,
outb(DAQP_COMMAND_RSTQ, dev->iobase + DAQP_COMMAND);
/* Program one scan list entry */
-
- v = DAQP_SCANLIST_CHANNEL(CR_CHAN(insn->chanspec))
- | DAQP_SCANLIST_GAIN(CR_RANGE(insn->chanspec));
-
- if (CR_AREF(insn->chanspec) == AREF_DIFF)
- v |= DAQP_SCANLIST_DIFFERENTIAL;
-
-
- v |= DAQP_SCANLIST_START;
-
- outb(v & 0xff, dev->iobase + DAQP_SCANLIST);
- outb(v >> 8, dev->iobase + DAQP_SCANLIST);
+ daqp_ai_set_one_scanlist_entry(dev, insn->chanspec, 1);
/* Reset data FIFO (see page 28 of DAQP User's Manual) */
@@ -403,10 +325,8 @@ static int daqp_ai_insn_read(struct comedi_device *dev,
return -1;
}
- init_completion(&local->eos);
- local->interrupt_mode = semaphore;
- local->dev = dev;
- local->s = s;
+ init_completion(&devpriv->eos);
+ devpriv->interrupt_mode = semaphore;
for (i = 0; i < insn->n; i++) {
@@ -416,7 +336,7 @@ static int daqp_ai_insn_read(struct comedi_device *dev,
/* Wait for interrupt service routine to unblock completion */
/* Maybe could use a timeout here, but it's interruptible */
- if (wait_for_completion_interruptible(&local->eos))
+ if (wait_for_completion_interruptible(&devpriv->eos))
return -EINTR;
data[i] = inb(dev->iobase + DAQP_FIFO);
@@ -541,7 +461,7 @@ static int daqp_ai_cmdtest(struct comedi_device *dev,
static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
- struct local_info_t *local = (struct local_info_t *)s->private;
+ struct daqp_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
int counter;
int scanlist_start_on_every_entry;
@@ -550,10 +470,9 @@ static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
int i;
int v;
- if (local->stop)
+ if (devpriv->stop)
return -EIO;
-
/* Stop any running conversion */
daqp_ai_cancel(dev, s);
@@ -592,24 +511,10 @@ static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
}
/* Program scan list */
-
for (i = 0; i < cmd->chanlist_len; i++) {
+ int start = (i == 0 || scanlist_start_on_every_entry);
- int chanspec = cmd->chanlist[i];
-
- /* Program one scan list entry */
-
- v = DAQP_SCANLIST_CHANNEL(CR_CHAN(chanspec))
- | DAQP_SCANLIST_GAIN(CR_RANGE(chanspec));
-
- if (CR_AREF(chanspec) == AREF_DIFF)
- v |= DAQP_SCANLIST_DIFFERENTIAL;
-
- if (i == 0 || scanlist_start_on_every_entry)
- v |= DAQP_SCANLIST_START;
-
- outb(v & 0xff, dev->iobase + DAQP_SCANLIST);
- outb(v >> 8, dev->iobase + DAQP_SCANLIST);
+ daqp_ai_set_one_scanlist_entry(dev, cmd->chanlist[i], start);
}
/* Now it's time to program the FIFO threshold, basically the
@@ -675,16 +580,16 @@ static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
/* Save away the number of conversions we should perform, and
* compute the FIFO threshold (in bytes, not samples - that's
- * why we multiple local->count by 2 = sizeof(sample))
+ * why we multiple devpriv->count by 2 = sizeof(sample))
*/
if (cmd->stop_src == TRIG_COUNT) {
- local->count = cmd->stop_arg * cmd->scan_end_arg;
- threshold = 2 * local->count;
+ devpriv->count = cmd->stop_arg * cmd->scan_end_arg;
+ threshold = 2 * devpriv->count;
while (threshold > DAQP_FIFO_SIZE * 3 / 4)
threshold /= 2;
} else {
- local->count = -1;
+ devpriv->count = -1;
threshold = DAQP_FIFO_SIZE / 2;
}
@@ -726,9 +631,7 @@ static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
return -1;
}
- local->interrupt_mode = buffer;
- local->dev = dev;
- local->s = s;
+ devpriv->interrupt_mode = buffer;
/* Start conversion */
outb(DAQP_COMMAND_ARM | DAQP_COMMAND_FIFO_DATA,
@@ -737,341 +640,193 @@ static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
return 0;
}
-/* Single-shot analog output routine */
-
static int daqp_ao_insn_write(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct local_info_t *local = (struct local_info_t *)s->private;
- int d;
- unsigned int chan;
+ struct daqp_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int val;
+ int i;
- if (local->stop)
+ if (devpriv->stop)
return -EIO;
- chan = CR_CHAN(insn->chanspec);
- d = data[0];
- d &= 0x0fff;
- d ^= 0x0800; /* Flip the sign */
- d |= chan << 12;
-
/* Make sure D/A update mode is direct update */
outb(0, dev->iobase + DAQP_AUX);
- outw(d, dev->iobase + DAQP_DA);
+ for (i = 0; i > insn->n; i++) {
+ val = data[0];
+ val &= 0x0fff;
+ val ^= 0x0800; /* Flip the sign */
+ val |= (chan << 12);
- return 1;
-}
+ outw(val, dev->iobase + DAQP_DA);
+ }
-/* Digital input routine */
+ return insn->n;
+}
-static int daqp_di_insn_read(struct comedi_device *dev,
+static int daqp_di_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct local_info_t *local = (struct local_info_t *)s->private;
+ struct daqp_private *devpriv = dev->private;
- if (local->stop)
+ if (devpriv->stop)
return -EIO;
data[0] = inb(dev->iobase + DAQP_DIGITAL_IO);
- return 1;
+ return insn->n;
}
-/* Digital output routine */
-
-static int daqp_do_insn_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int daqp_do_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct local_info_t *local = (struct local_info_t *)s->private;
+ struct daqp_private *devpriv = dev->private;
+ unsigned int mask = data[0];
+ unsigned int bits = data[1];
- if (local->stop)
+ if (devpriv->stop)
return -EIO;
- outw(data[0] & 0xf, dev->iobase + DAQP_DIGITAL_IO);
+ if (mask) {
+ s->state &= ~mask;
+ s->state |= (bits & mask);
- return 1;
-}
+ outb(s->state, dev->iobase + DAQP_DIGITAL_IO);
+ }
-/* daqp_attach is called via comedi_config to attach a comedi device
- * to a /dev/comedi*. Note that this is different from daqp_cs_attach()
- * which is called by the pcmcia subsystem to attach the PCMCIA card
- * when it is inserted.
- */
+ data[1] = s->state;
-static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ return insn->n;
+}
+
+static int daqp_auto_attach(struct comedi_device *dev,
+ unsigned long context)
{
- int ret;
- struct local_info_t *local = dev_table[it->options[0]];
+ struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
+ struct daqp_private *devpriv;
struct comedi_subdevice *s;
+ int ret;
- if (it->options[0] < 0 || it->options[0] >= MAX_DEV || !local) {
- dev_err(dev->class_dev, "No such daqp device %d\n",
- it->options[0]);
- return -EIO;
- }
+ dev->board_name = dev->driver->driver_name;
- /* Typically brittle code that I don't completely understand,
- * but "it works on my card". The intent is to pull the model
- * number of the card out the PCMCIA CIS and stash it away as
- * the COMEDI board_name. Looks like the third field in
- * CISTPL_VERS_1 (offset 2) holds what we're looking for. If
- * it doesn't work, who cares, just leave it as "DAQP".
- */
+ devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+ if (!devpriv)
+ return -ENOMEM;
+ dev->private = devpriv;
- strcpy(local->board_name, "DAQP");
- dev->board_name = local->board_name;
- if (local->link->prod_id[2]) {
- if (strncmp(local->link->prod_id[2], "DAQP", 4) == 0) {
- strncpy(local->board_name, local->link->prod_id[2],
- sizeof(local->board_name));
- }
- }
+ link->config_flags |= CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
+ ret = comedi_pcmcia_enable(dev, NULL);
+ if (ret)
+ return ret;
+ dev->iobase = link->resource[0]->start;
- dev->iobase = local->link->resource[0]->start;
+ link->priv = dev;
+ ret = pcmcia_request_irq(link, daqp_interrupt);
+ if (ret)
+ return ret;
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
return ret;
- dev_info(dev->class_dev, "attaching daqp%d (io 0x%04lx)\n",
- it->options[0], dev->iobase);
-
s = &dev->subdevices[0];
dev->read_subdev = s;
- s->private = local;
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
- s->n_chan = 8;
- s->len_chanlist = 2048;
- s->maxdata = 0xffff;
- s->range_table = &range_daqp_ai;
- s->insn_read = daqp_ai_insn_read;
- s->do_cmdtest = daqp_ai_cmdtest;
- s->do_cmd = daqp_ai_cmd;
- s->cancel = daqp_ai_cancel;
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
+ s->n_chan = 8;
+ s->len_chanlist = 2048;
+ s->maxdata = 0xffff;
+ s->range_table = &range_daqp_ai;
+ s->insn_read = daqp_ai_insn_read;
+ s->do_cmdtest = daqp_ai_cmdtest;
+ s->do_cmd = daqp_ai_cmd;
+ s->cancel = daqp_ai_cancel;
s = &dev->subdevices[1];
- dev->write_subdev = s;
- s->private = local;
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE;
- s->n_chan = 2;
- s->len_chanlist = 1;
- s->maxdata = 0x0fff;
- s->range_table = &range_daqp_ao;
- s->insn_write = daqp_ao_insn_write;
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITEABLE;
+ s->n_chan = 2;
+ s->maxdata = 0x0fff;
+ s->range_table = &range_bipolar5;
+ s->insn_write = daqp_ao_insn_write;
s = &dev->subdevices[2];
- s->private = local;
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE;
- s->n_chan = 1;
- s->len_chanlist = 1;
- s->insn_read = daqp_di_insn_read;
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 1;
+ s->maxdata = 1;
+ s->insn_bits = daqp_di_insn_bits;
s = &dev->subdevices[3];
- s->private = local;
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITEABLE;
- s->n_chan = 1;
- s->len_chanlist = 1;
- s->insn_write = daqp_do_insn_write;
-
- return 1;
-}
-
-static void daqp_detach(struct comedi_device *dev)
-{
- /* Nothing to cleanup */
-}
-
-/*====================================================================
-
- PCMCIA interface code
-
- The rest of the code in this file is based on dummy_cs.c v1.24
- from the Linux pcmcia_cs distribution v3.1.8 and is subject
- to the following license agreement.
-
- The remaining contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The initial developer of the original code is David A. Hinds
- <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
- are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
-
- Alternatively, the contents of this file may be used under the
- terms of the GNU Public License version 2 (the "GPL"), in which
- case the provisions of the GPL are applicable instead of the
- above. If you wish to allow the use of your version of this file
- only under the terms of the GPL and not to allow others to use
- your version of this file under the MPL, indicate your decision
- by deleting the provisions above and replace them with the notice
- and other provisions required by the GPL. If you do not delete
- the provisions above, a recipient may use your version of this
- file under either the MPL or the GPL.
-
-======================================================================*/
-
-static void daqp_cs_config(struct pcmcia_device *link);
-static void daqp_cs_release(struct pcmcia_device *link);
-static int daqp_cs_suspend(struct pcmcia_device *p_dev);
-static int daqp_cs_resume(struct pcmcia_device *p_dev);
-
-static int daqp_cs_attach(struct pcmcia_device *);
-static void daqp_cs_detach(struct pcmcia_device *);
-
-static int daqp_cs_attach(struct pcmcia_device *link)
-{
- struct local_info_t *local;
- int i;
-
- dev_dbg(&link->dev, "daqp_cs_attach()\n");
-
- for (i = 0; i < MAX_DEV; i++)
- if (dev_table[i] == NULL)
- break;
- if (i == MAX_DEV) {
- dev_notice(&link->dev, "no devices available\n");
- return -ENODEV;
- }
-
- /* Allocate space for private device-specific data */
- local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
- if (!local)
- return -ENOMEM;
-
- local->table_index = i;
- dev_table[i] = local;
- local->link = link;
- link->priv = local;
-
- daqp_cs_config(link);
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITEABLE;
+ s->n_chan = 1;
+ s->maxdata = 1;
+ s->insn_bits = daqp_do_insn_bits;
return 0;
-} /* daqp_cs_attach */
-
-static void daqp_cs_detach(struct pcmcia_device *link)
-{
- struct local_info_t *dev = link->priv;
-
- dev->stop = 1;
- daqp_cs_release(link);
-
- /* Unlink device structure, and free it */
- dev_table[dev->table_index] = NULL;
- kfree(dev);
-
}
-static int daqp_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data)
-{
- if (p_dev->config_index == 0)
- return -EINVAL;
-
- return pcmcia_request_io(p_dev);
-}
-
-static void daqp_cs_config(struct pcmcia_device *link)
-{
- int ret;
-
- dev_dbg(&link->dev, "daqp_cs_config\n");
-
- link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
-
- ret = pcmcia_loop_config(link, daqp_pcmcia_config_loop, NULL);
- if (ret) {
- dev_warn(&link->dev, "no configuration found\n");
- goto failed;
- }
-
- ret = pcmcia_request_irq(link, daqp_interrupt);
- if (ret)
- goto failed;
-
- ret = pcmcia_enable_device(link);
- if (ret)
- goto failed;
-
- return;
-
-failed:
- daqp_cs_release(link);
-
-} /* daqp_cs_config */
-
-static void daqp_cs_release(struct pcmcia_device *link)
-{
- dev_dbg(&link->dev, "daqp_cs_release\n");
-
- pcmcia_disable_device(link);
-} /* daqp_cs_release */
+static struct comedi_driver driver_daqp = {
+ .driver_name = "quatech_daqp_cs",
+ .module = THIS_MODULE,
+ .auto_attach = daqp_auto_attach,
+ .detach = comedi_pcmcia_disable,
+};
static int daqp_cs_suspend(struct pcmcia_device *link)
{
- struct local_info_t *local = link->priv;
+ struct comedi_device *dev = link->priv;
+ struct daqp_private *devpriv = dev ? dev->private : NULL;
/* Mark the device as stopped, to block IO until later */
- local->stop = 1;
+ if (devpriv)
+ devpriv->stop = 1;
+
return 0;
}
static int daqp_cs_resume(struct pcmcia_device *link)
{
- struct local_info_t *local = link->priv;
+ struct comedi_device *dev = link->priv;
+ struct daqp_private *devpriv = dev ? dev->private : NULL;
- local->stop = 0;
+ if (devpriv)
+ devpriv->stop = 0;
return 0;
}
-/*====================================================================*/
-
-#ifdef MODULE
+static int daqp_cs_attach(struct pcmcia_device *link)
+{
+ return comedi_pcmcia_auto_config(link, &driver_daqp);
+}
static const struct pcmcia_device_id daqp_cs_id_table[] = {
PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0027),
PCMCIA_DEVICE_NULL
};
-
MODULE_DEVICE_TABLE(pcmcia, daqp_cs_id_table);
-MODULE_AUTHOR("Brent Baccala <baccala@freesoft.org>");
-MODULE_DESCRIPTION("Comedi driver for Quatech DAQP PCMCIA data capture cards");
-MODULE_LICENSE("GPL");
static struct pcmcia_driver daqp_cs_driver = {
- .probe = daqp_cs_attach,
- .remove = daqp_cs_detach,
- .suspend = daqp_cs_suspend,
- .resume = daqp_cs_resume,
- .id_table = daqp_cs_id_table,
- .owner = THIS_MODULE,
- .name = "quatech_daqp_cs",
+ .name = "quatech_daqp_cs",
+ .owner = THIS_MODULE,
+ .id_table = daqp_cs_id_table,
+ .probe = daqp_cs_attach,
+ .remove = comedi_pcmcia_auto_unconfig,
+ .suspend = daqp_cs_suspend,
+ .resume = daqp_cs_resume,
};
+module_comedi_pcmcia_driver(driver_daqp, daqp_cs_driver);
-int __init init_module(void)
-{
- pcmcia_register_driver(&daqp_cs_driver);
- comedi_driver_register(&driver_daqp);
- return 0;
-}
-
-void __exit cleanup_module(void)
-{
- comedi_driver_unregister(&driver_daqp);
- pcmcia_unregister_driver(&daqp_cs_driver);
-}
-
-#endif
+MODULE_DESCRIPTION("Comedi driver for Quatech DAQP PCMCIA data capture cards");
+MODULE_AUTHOR("Brent Baccala <baccala@freesoft.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
index 8d7c948a919c..6a5c914fa501 100644
--- a/drivers/staging/comedi/drivers/rtd520.c
+++ b/drivers/staging/comedi/drivers/rtd520.c
@@ -101,8 +101,9 @@ Configuration options:
*/
-#include <linux/interrupt.h>
+#include <linux/pci.h>
#include <linux/delay.h>
+#include <linux/interrupt.h>
#include "../comedidev.h"
@@ -1420,11 +1421,6 @@ static int rtd520_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &rtd520_driver);
}
-static void rtd520_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static DEFINE_PCI_DEVICE_TABLE(rtd520_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_RTD, 0x7520) },
{ PCI_DEVICE(PCI_VENDOR_ID_RTD, 0x4520) },
@@ -1436,7 +1432,7 @@ static struct pci_driver rtd520_pci_driver = {
.name = "rtd520",
.id_table = rtd520_pci_table,
.probe = rtd520_pci_probe,
- .remove = rtd520_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(rtd520_driver, rtd520_pci_driver);
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index 6dc1d2812865..81a1fe661579 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -64,6 +64,7 @@ INSN_CONFIG instructions:
comedi_do_insn(cf,&insn); //executing configuration
*/
+#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/types.h>
@@ -2836,11 +2837,6 @@ static int s626_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &s626_driver);
}
-static void s626_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
/*
* For devices with vendor:device id == 0x1131:0x7146 you must specify
* also subvendor:subdevice ids, because otherwise it will conflict with
@@ -2857,7 +2853,7 @@ static struct pci_driver s626_pci_driver = {
.name = "s626",
.id_table = s626_pci_table,
.probe = s626_pci_probe,
- .remove = s626_pci_remove,
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(s626_driver, s626_pci_driver);
diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
index e2d79700a615..cb83f6ae48b9 100644
--- a/drivers/staging/comedi/drivers/skel.c
+++ b/drivers/staging/comedi/drivers/skel.c
@@ -72,9 +72,9 @@ Configuration Options:
* options that are used with comedi_config.
*/
-#include "../comedidev.h"
+#include <linux/pci.h>
-#include <linux/pci.h> /* for PCI devices */
+#include "../comedidev.h"
#include "comedi_fc.h"
@@ -707,15 +707,11 @@ static int skel_pci_probe(struct pci_dev *dev,
return comedi_pci_auto_config(dev, &skel_driver);
}
-static void skel_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
static struct pci_driver skel_pci_driver = {
+ .name = "dummy",
.id_table = skel_pci_table,
.probe = &skel_pci_probe,
- .remove = &skel_pci_remove
+ .remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver(skel_driver, skel_pci_driver);
#else
diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c
index c9ded938314f..74b974bf1032 100644
--- a/drivers/staging/comedi/drivers/unioxx5.c
+++ b/drivers/staging/comedi/drivers/unioxx5.c
@@ -380,12 +380,8 @@ static int __unioxx5_subdev_init(struct comedi_subdevice *subdev,
}
usp = kzalloc(sizeof(*usp), GFP_KERNEL);
-
- if (usp == NULL) {
- dev_err(subdev->class_dev,
- "comedi%d: error! --> out of memory!\n", minor);
+ if (usp == NULL)
return -1;
- }
usp->usp_iobase = subdev_iobase;
dev_info(subdev->class_dev, "comedi%d: |", minor);
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index 17b45ebb0553..1a0062a04456 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -2388,7 +2388,7 @@ static void usbdux_firmware_request_complete_handler(const struct firmware *fw,
"Could not upload firmware (err=%d)\n", ret);
goto out;
}
- comedi_usb_auto_config(uinterf, &usbdux_driver);
+ comedi_usb_auto_config(uinterf, &usbdux_driver, 0);
out:
release_firmware(fw);
}
@@ -2445,8 +2445,6 @@ static int usbdux_usb_probe(struct usb_interface *uinterf,
/* create space for the commands of the DA converter */
usbduxsub[index].dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL);
if (!usbduxsub[index].dac_commands) {
- dev_err(dev, "comedi_: usbdux: "
- "error alloc space for dac commands\n");
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -2454,8 +2452,6 @@ static int usbdux_usb_probe(struct usb_interface *uinterf,
/* create space for the commands going to the usb device */
usbduxsub[index].dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
if (!usbduxsub[index].dux_commands) {
- dev_err(dev, "comedi_: usbdux: "
- "error alloc space for dux commands\n");
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -2463,8 +2459,6 @@ static int usbdux_usb_probe(struct usb_interface *uinterf,
/* create space for the in buffer and set it to zero */
usbduxsub[index].inBuffer = kzalloc(SIZEINBUF, GFP_KERNEL);
if (!(usbduxsub[index].inBuffer)) {
- dev_err(dev, "comedi_: usbdux: "
- "could not alloc space for inBuffer\n");
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -2472,8 +2466,6 @@ static int usbdux_usb_probe(struct usb_interface *uinterf,
/* create space of the instruction buffer */
usbduxsub[index].insnBuffer = kzalloc(SIZEINSNBUF, GFP_KERNEL);
if (!(usbduxsub[index].insnBuffer)) {
- dev_err(dev, "comedi_: usbdux: "
- "could not alloc space for insnBuffer\n");
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -2481,8 +2473,6 @@ static int usbdux_usb_probe(struct usb_interface *uinterf,
/* create space for the outbuffer */
usbduxsub[index].outBuffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
if (!(usbduxsub[index].outBuffer)) {
- dev_err(dev, "comedi_: usbdux: "
- "could not alloc space for outBuffer\n");
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -2504,10 +2494,9 @@ static int usbdux_usb_probe(struct usb_interface *uinterf,
usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSFULL;
usbduxsub[index].urbIn =
- kzalloc(sizeof(struct urb *) * usbduxsub[index].numOfInBuffers,
- GFP_KERNEL);
+ kcalloc(usbduxsub[index].numOfInBuffers, sizeof(struct urb *),
+ GFP_KERNEL);
if (!(usbduxsub[index].urbIn)) {
- dev_err(dev, "comedi_: usbdux: Could not alloc. urbIn array\n");
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -2532,8 +2521,6 @@ static int usbdux_usb_probe(struct usb_interface *uinterf,
usbduxsub[index].urbIn[i]->transfer_buffer =
kzalloc(SIZEINBUF, GFP_KERNEL);
if (!(usbduxsub[index].urbIn[i]->transfer_buffer)) {
- dev_err(dev, "comedi_: usbdux%d: "
- "could not alloc. transb.\n", index);
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -2552,11 +2539,9 @@ static int usbdux_usb_probe(struct usb_interface *uinterf,
usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSFULL;
usbduxsub[index].urbOut =
- kzalloc(sizeof(struct urb *) * usbduxsub[index].numOfOutBuffers,
- GFP_KERNEL);
+ kcalloc(usbduxsub[index].numOfOutBuffers, sizeof(struct urb *),
+ GFP_KERNEL);
if (!(usbduxsub[index].urbOut)) {
- dev_err(dev, "comedi_: usbdux: "
- "Could not alloc. urbOut array\n");
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -2581,8 +2566,6 @@ static int usbdux_usb_probe(struct usb_interface *uinterf,
usbduxsub[index].urbOut[i]->transfer_buffer =
kzalloc(SIZEOUTBUF, GFP_KERNEL);
if (!(usbduxsub[index].urbOut[i]->transfer_buffer)) {
- dev_err(dev, "comedi_: usbdux%d: "
- "could not alloc. transb.\n", index);
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -2617,8 +2600,6 @@ static int usbdux_usb_probe(struct usb_interface *uinterf,
usbduxsub[index].urbPwm->transfer_buffer =
kzalloc(usbduxsub[index].sizePwmBuf, GFP_KERNEL);
if (!(usbduxsub[index].urbPwm->transfer_buffer)) {
- dev_err(dev, "comedi_: usbdux%d: "
- "could not alloc. transb. for pwm\n", index);
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
index 4e19f6186f28..4bf5dd094dc9 100644
--- a/drivers/staging/comedi/drivers/usbduxfast.c
+++ b/drivers/staging/comedi/drivers/usbduxfast.c
@@ -1490,7 +1490,7 @@ static void usbduxfast_firmware_request_complete_handler(const struct firmware
goto out;
}
- comedi_usb_auto_config(uinterf, &usbduxfast_driver);
+ comedi_usb_auto_config(uinterf, &usbduxfast_driver, 0);
out:
release_firmware(fw);
}
@@ -1556,8 +1556,6 @@ static int usbduxfast_usb_probe(struct usb_interface *uinterf,
usbduxfastsub[index].dux_commands = kmalloc(SIZEOFDUXBUFFER,
GFP_KERNEL);
if (!usbduxfastsub[index].dux_commands) {
- dev_err(&uinterf->dev,
- "error alloc space for dac commands\n");
tidy_up(&(usbduxfastsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -1565,8 +1563,6 @@ static int usbduxfast_usb_probe(struct usb_interface *uinterf,
/* create space of the instruction buffer */
usbduxfastsub[index].insnBuffer = kmalloc(SIZEINSNBUF, GFP_KERNEL);
if (!usbduxfastsub[index].insnBuffer) {
- dev_err(&uinterf->dev,
- "could not alloc space for insnBuffer\n");
tidy_up(&(usbduxfastsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -1592,8 +1588,6 @@ static int usbduxfast_usb_probe(struct usb_interface *uinterf,
}
usbduxfastsub[index].transfer_buffer = kmalloc(SIZEINBUF, GFP_KERNEL);
if (!usbduxfastsub[index].transfer_buffer) {
- dev_err(&uinterf->dev,
- "usbduxfast%d: could not alloc. transb.\n", index);
tidy_up(&(usbduxfastsub[index]));
up(&start_stop_sem);
return -ENOMEM;
diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c
index cdd279b1f61e..d066351a71b2 100644
--- a/drivers/staging/comedi/drivers/usbduxsigma.c
+++ b/drivers/staging/comedi/drivers/usbduxsigma.c
@@ -2374,7 +2374,7 @@ static void usbdux_firmware_request_complete_handler(const struct firmware *fw,
"Could not upload firmware (err=%d)\n", ret);
goto out;
}
- comedi_usb_auto_config(uinterf, &usbduxsigma_driver);
+ comedi_usb_auto_config(uinterf, &usbduxsigma_driver, 0);
out:
release_firmware(fw);
}
@@ -2431,8 +2431,6 @@ static int usbduxsigma_usb_probe(struct usb_interface *uinterf,
/* create space for the commands of the DA converter */
usbduxsub[index].dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL);
if (!usbduxsub[index].dac_commands) {
- dev_err(dev, "comedi_: usbduxsigma: "
- "error alloc space for dac commands\n");
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -2440,8 +2438,6 @@ static int usbduxsigma_usb_probe(struct usb_interface *uinterf,
/* create space for the commands going to the usb device */
usbduxsub[index].dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
if (!usbduxsub[index].dux_commands) {
- dev_err(dev, "comedi_: usbduxsigma: "
- "error alloc space for dux commands\n");
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -2449,8 +2445,6 @@ static int usbduxsigma_usb_probe(struct usb_interface *uinterf,
/* create space for the in buffer and set it to zero */
usbduxsub[index].inBuffer = kzalloc(SIZEINBUF, GFP_KERNEL);
if (!(usbduxsub[index].inBuffer)) {
- dev_err(dev, "comedi_: usbduxsigma: "
- "could not alloc space for inBuffer\n");
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -2458,8 +2452,6 @@ static int usbduxsigma_usb_probe(struct usb_interface *uinterf,
/* create space of the instruction buffer */
usbduxsub[index].insnBuffer = kzalloc(SIZEINSNBUF, GFP_KERNEL);
if (!(usbduxsub[index].insnBuffer)) {
- dev_err(dev, "comedi_: usbduxsigma: "
- "could not alloc space for insnBuffer\n");
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -2467,8 +2459,6 @@ static int usbduxsigma_usb_probe(struct usb_interface *uinterf,
/* create space for the outbuffer */
usbduxsub[index].outBuffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
if (!(usbduxsub[index].outBuffer)) {
- dev_err(dev, "comedi_: usbduxsigma: "
- "could not alloc space for outBuffer\n");
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -2489,12 +2479,10 @@ static int usbduxsigma_usb_probe(struct usb_interface *uinterf,
else
usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSFULL;
- usbduxsub[index].urbIn =
- kzalloc(sizeof(struct urb *) * usbduxsub[index].numOfInBuffers,
- GFP_KERNEL);
+ usbduxsub[index].urbIn = kcalloc(usbduxsub[index].numOfInBuffers,
+ sizeof(struct urb *),
+ GFP_KERNEL);
if (!(usbduxsub[index].urbIn)) {
- dev_err(dev, "comedi_: usbduxsigma: "
- "Could not alloc. urbIn array\n");
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -2519,8 +2507,6 @@ static int usbduxsigma_usb_probe(struct usb_interface *uinterf,
usbduxsub[index].urbIn[i]->transfer_buffer =
kzalloc(SIZEINBUF, GFP_KERNEL);
if (!(usbduxsub[index].urbIn[i]->transfer_buffer)) {
- dev_err(dev, "comedi_: usbduxsigma%d: "
- "could not alloc. transb.\n", index);
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -2539,12 +2525,9 @@ static int usbduxsigma_usb_probe(struct usb_interface *uinterf,
else
usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSFULL;
- usbduxsub[index].urbOut =
- kzalloc(sizeof(struct urb *) * usbduxsub[index].numOfOutBuffers,
- GFP_KERNEL);
+ usbduxsub[index].urbOut = kcalloc(usbduxsub[index].numOfOutBuffers,
+ sizeof(struct urb *), GFP_KERNEL);
if (!(usbduxsub[index].urbOut)) {
- dev_err(dev, "comedi_: usbduxsigma: "
- "Could not alloc. urbOut array\n");
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -2569,8 +2552,6 @@ static int usbduxsigma_usb_probe(struct usb_interface *uinterf,
usbduxsub[index].urbOut[i]->transfer_buffer =
kzalloc(SIZEOUTBUF, GFP_KERNEL);
if (!(usbduxsub[index].urbOut[i]->transfer_buffer)) {
- dev_err(dev, "comedi_: usbduxsigma%d: "
- "could not alloc. transb.\n", index);
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
@@ -2606,8 +2587,6 @@ static int usbduxsigma_usb_probe(struct usb_interface *uinterf,
usbduxsub[index].urbPwm->transfer_buffer =
kzalloc(usbduxsub[index].sizePwmBuf, GFP_KERNEL);
if (!(usbduxsub[index].urbPwm->transfer_buffer)) {
- dev_err(dev, "comedi_: usbduxsigma%d: "
- "could not alloc. transb. for pwm\n", index);
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return -ENOMEM;
diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c
index 609dc6915997..2be5087414f6 100644
--- a/drivers/staging/comedi/drivers/vmk80xx.c
+++ b/drivers/staging/comedi/drivers/vmk80xx.c
@@ -38,19 +38,6 @@ Supports:
- counter
- pwm
*/
-/*
-Changelog:
-
-0.8.81 -3- code completely rewritten (adjust driver logic)
-0.8.81 -2- full support for K8061
-0.8.81 -1- fix some mistaken among others the number of
- supported boards and I/O handling
-
-0.7.76 -4- renamed to vmk80xx
-0.7.76 -3- detect K8061 (only theoretically supported)
-0.7.76 -2- code completely rewritten (adjust driver logic)
-0.7.76 -1- support for digital and counter subdevice
-*/
#include <linux/kernel.h>
#include <linux/module.h>
@@ -113,30 +100,9 @@ enum {
#define VMK8061_CMD_RD_AO 0x0f
#define VMK8061_CMD_RD_PWM 0x10
-#define VMK80XX_MAX_BOARDS COMEDI_NUM_BOARD_MINORS
-
-#define TRANS_OUT_BUSY 1
-#define TRANS_IN_BUSY 2
-#define TRANS_IN_RUNNING 3
-
#define IC3_VERSION (1 << 0)
#define IC6_VERSION (1 << 1)
-#define URB_RCV_FLAG (1 << 0)
-#define URB_SND_FLAG (1 << 1)
-
-#ifdef CONFIG_COMEDI_DEBUG
-static int dbgcm = 1;
-#else
-static int dbgcm;
-#endif
-
-#define dbgcm(fmt, arg...) \
-do { \
- if (dbgcm) \
- printk(KERN_DEBUG fmt, ##arg); \
-} while (0)
-
enum vmk80xx_model {
VMK8055_MODEL,
VMK8061_MODEL
@@ -147,130 +113,73 @@ struct firmware_version {
unsigned char ic6_vers[32]; /* CPU */
};
-static const struct comedi_lrange vmk8055_range = {
- 1, {UNI_RANGE(5)}
-};
-
static const struct comedi_lrange vmk8061_range = {
- 2, {UNI_RANGE(5), UNI_RANGE(10)}
+ 2, {
+ UNI_RANGE(5),
+ UNI_RANGE(10)
+ }
};
struct vmk80xx_board {
const char *name;
enum vmk80xx_model model;
const struct comedi_lrange *range;
- __u8 ai_chans;
- __le16 ai_bits;
- __u8 ao_chans;
- __le16 ao_bits;
- __u8 di_chans;
- __le16 di_bits;
- __u8 do_chans;
- __le16 do_bits;
- __u8 cnt_chans;
- __le16 cnt_bits;
- __u8 pwm_chans;
- __le16 pwm_bits;
+ int ai_nchans;
+ unsigned int ai_maxdata;
+ int ao_nchans;
+ int di_nchans;
+ unsigned int cnt_maxdata;
+ int pwm_nchans;
+ unsigned int pwm_maxdata;
};
-enum {
- VMK80XX_SUBD_AI,
- VMK80XX_SUBD_AO,
- VMK80XX_SUBD_DI,
- VMK80XX_SUBD_DO,
- VMK80XX_SUBD_CNT,
- VMK80XX_SUBD_PWM,
+static const struct vmk80xx_board vmk80xx_boardinfo[] = {
+ [DEVICE_VMK8055] = {
+ .name = "K8055 (VM110)",
+ .model = VMK8055_MODEL,
+ .range = &range_unipolar5,
+ .ai_nchans = 2,
+ .ai_maxdata = 0x00ff,
+ .ao_nchans = 2,
+ .di_nchans = 6,
+ .cnt_maxdata = 0xffff,
+ },
+ [DEVICE_VMK8061] = {
+ .name = "K8061 (VM140)",
+ .model = VMK8061_MODEL,
+ .range = &vmk8061_range,
+ .ai_nchans = 8,
+ .ai_maxdata = 0x03ff,
+ .ao_nchans = 8,
+ .di_nchans = 8,
+ .cnt_maxdata = 0, /* unknown, device is not writeable */
+ .pwm_nchans = 1,
+ .pwm_maxdata = 0x03ff,
+ },
};
-struct vmk80xx_usb {
- struct usb_device *udev;
+struct vmk80xx_private {
+ struct usb_device *usb;
struct usb_interface *intf;
struct usb_endpoint_descriptor *ep_rx;
struct usb_endpoint_descriptor *ep_tx;
- struct usb_anchor rx_anchor;
- struct usb_anchor tx_anchor;
- struct vmk80xx_board board;
struct firmware_version fw;
struct semaphore limit_sem;
- wait_queue_head_t read_wait;
- wait_queue_head_t write_wait;
unsigned char *usb_rx_buf;
unsigned char *usb_tx_buf;
- unsigned long flags;
- int probed;
- int attached;
- int count;
+ enum vmk80xx_model model;
};
-static struct vmk80xx_usb vmb[VMK80XX_MAX_BOARDS];
-
-static DEFINE_MUTEX(glb_mutex);
-
-static void vmk80xx_tx_callback(struct urb *urb)
-{
- struct vmk80xx_usb *dev = urb->context;
- int stat = urb->status;
-
- if (stat && !(stat == -ENOENT
- || stat == -ECONNRESET || stat == -ESHUTDOWN))
- dbgcm("comedi#: vmk80xx: %s - nonzero urb status (%d)\n",
- __func__, stat);
-
- if (!test_bit(TRANS_OUT_BUSY, &dev->flags))
- return;
-
- clear_bit(TRANS_OUT_BUSY, &dev->flags);
-
- wake_up_interruptible(&dev->write_wait);
-}
-
-static void vmk80xx_rx_callback(struct urb *urb)
-{
- struct vmk80xx_usb *dev = urb->context;
- int stat = urb->status;
-
- switch (stat) {
- case 0:
- break;
- case -ENOENT:
- case -ECONNRESET:
- case -ESHUTDOWN:
- break;
- default:
- dbgcm("comedi#: vmk80xx: %s - nonzero urb status (%d)\n",
- __func__, stat);
- goto resubmit;
- }
-
- goto exit;
-resubmit:
- if (test_bit(TRANS_IN_RUNNING, &dev->flags) && dev->intf) {
- usb_anchor_urb(urb, &dev->rx_anchor);
-
- if (!usb_submit_urb(urb, GFP_KERNEL))
- goto exit;
-
- dev_err(&urb->dev->dev,
- "comedi#: vmk80xx: %s - submit urb failed\n",
- __func__);
-
- usb_unanchor_urb(urb);
- }
-exit:
- clear_bit(TRANS_IN_BUSY, &dev->flags);
-
- wake_up_interruptible(&dev->read_wait);
-}
-
-static int vmk80xx_check_data_link(struct vmk80xx_usb *dev)
+static int vmk80xx_check_data_link(struct vmk80xx_private *devpriv)
{
+ struct usb_device *usb = devpriv->usb;
unsigned int tx_pipe;
unsigned int rx_pipe;
unsigned char tx[1];
unsigned char rx[2];
- tx_pipe = usb_sndbulkpipe(dev->udev, 0x01);
- rx_pipe = usb_rcvbulkpipe(dev->udev, 0x81);
+ tx_pipe = usb_sndbulkpipe(usb, 0x01);
+ rx_pipe = usb_rcvbulkpipe(usb, 0x81);
tx[0] = VMK8061_CMD_RD_PWR_STAT;
@@ -279,22 +188,23 @@ static int vmk80xx_check_data_link(struct vmk80xx_usb *dev)
* running and the data link between IC3 and
* IC6 is working properly
*/
- usb_bulk_msg(dev->udev, tx_pipe, tx, 1, NULL, dev->ep_tx->bInterval);
- usb_bulk_msg(dev->udev, rx_pipe, rx, 2, NULL, HZ * 10);
+ usb_bulk_msg(usb, tx_pipe, tx, 1, NULL, devpriv->ep_tx->bInterval);
+ usb_bulk_msg(usb, rx_pipe, rx, 2, NULL, HZ * 10);
return (int)rx[1];
}
-static void vmk80xx_read_eeprom(struct vmk80xx_usb *dev, int flag)
+static void vmk80xx_read_eeprom(struct vmk80xx_private *devpriv, int flag)
{
+ struct usb_device *usb = devpriv->usb;
unsigned int tx_pipe;
unsigned int rx_pipe;
unsigned char tx[1];
unsigned char rx[64];
int cnt;
- tx_pipe = usb_sndbulkpipe(dev->udev, 0x01);
- rx_pipe = usb_rcvbulkpipe(dev->udev, 0x81);
+ tx_pipe = usb_sndbulkpipe(usb, 0x01);
+ rx_pipe = usb_rcvbulkpipe(usb, 0x81);
tx[0] = VMK8061_CMD_RD_VERSION;
@@ -302,243 +212,116 @@ static void vmk80xx_read_eeprom(struct vmk80xx_usb *dev, int flag)
* Read the firmware version info of IC3 and
* IC6 from the internal EEPROM of the IC
*/
- usb_bulk_msg(dev->udev, tx_pipe, tx, 1, NULL, dev->ep_tx->bInterval);
- usb_bulk_msg(dev->udev, rx_pipe, rx, 64, &cnt, HZ * 10);
+ usb_bulk_msg(usb, tx_pipe, tx, 1, NULL, devpriv->ep_tx->bInterval);
+ usb_bulk_msg(usb, rx_pipe, rx, 64, &cnt, HZ * 10);
rx[cnt] = '\0';
if (flag & IC3_VERSION)
- strncpy(dev->fw.ic3_vers, rx + 1, 24);
+ strncpy(devpriv->fw.ic3_vers, rx + 1, 24);
else /* IC6_VERSION */
- strncpy(dev->fw.ic6_vers, rx + 25, 24);
+ strncpy(devpriv->fw.ic6_vers, rx + 25, 24);
}
-static int vmk80xx_reset_device(struct vmk80xx_usb *dev)
-{
- struct urb *urb;
- unsigned int tx_pipe;
- int ival;
- size_t size;
-
- urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!urb)
- return -ENOMEM;
-
- tx_pipe = usb_sndintpipe(dev->udev, 0x01);
-
- ival = dev->ep_tx->bInterval;
- size = le16_to_cpu(dev->ep_tx->wMaxPacketSize);
-
- dev->usb_tx_buf[0] = VMK8055_CMD_RST;
- dev->usb_tx_buf[1] = 0x00;
- dev->usb_tx_buf[2] = 0x00;
- dev->usb_tx_buf[3] = 0x00;
- dev->usb_tx_buf[4] = 0x00;
- dev->usb_tx_buf[5] = 0x00;
- dev->usb_tx_buf[6] = 0x00;
- dev->usb_tx_buf[7] = 0x00;
-
- usb_fill_int_urb(urb, dev->udev, tx_pipe, dev->usb_tx_buf,
- size, vmk80xx_tx_callback, dev, ival);
-
- usb_anchor_urb(urb, &dev->tx_anchor);
-
- return usb_submit_urb(urb, GFP_KERNEL);
-}
-
-static void vmk80xx_build_int_urb(struct urb *urb, int flag)
-{
- struct vmk80xx_usb *dev = urb->context;
- __u8 rx_addr;
- __u8 tx_addr;
- unsigned int pipe;
- unsigned char *buf;
- size_t size;
- void (*callback) (struct urb *);
- int ival;
-
- if (flag & URB_RCV_FLAG) {
- rx_addr = dev->ep_rx->bEndpointAddress;
- pipe = usb_rcvintpipe(dev->udev, rx_addr);
- buf = dev->usb_rx_buf;
- size = le16_to_cpu(dev->ep_rx->wMaxPacketSize);
- callback = vmk80xx_rx_callback;
- ival = dev->ep_rx->bInterval;
- } else { /* URB_SND_FLAG */
- tx_addr = dev->ep_tx->bEndpointAddress;
- pipe = usb_sndintpipe(dev->udev, tx_addr);
- buf = dev->usb_tx_buf;
- size = le16_to_cpu(dev->ep_tx->wMaxPacketSize);
- callback = vmk80xx_tx_callback;
- ival = dev->ep_tx->bInterval;
- }
-
- usb_fill_int_urb(urb, dev->udev, pipe, buf, size, callback, dev, ival);
-}
-
-static void vmk80xx_do_bulk_msg(struct vmk80xx_usb *dev)
+static void vmk80xx_do_bulk_msg(struct vmk80xx_private *devpriv)
{
+ struct usb_device *usb = devpriv->usb;
__u8 tx_addr;
__u8 rx_addr;
unsigned int tx_pipe;
unsigned int rx_pipe;
size_t size;
- set_bit(TRANS_IN_BUSY, &dev->flags);
- set_bit(TRANS_OUT_BUSY, &dev->flags);
-
- tx_addr = dev->ep_tx->bEndpointAddress;
- rx_addr = dev->ep_rx->bEndpointAddress;
- tx_pipe = usb_sndbulkpipe(dev->udev, tx_addr);
- rx_pipe = usb_rcvbulkpipe(dev->udev, rx_addr);
+ tx_addr = devpriv->ep_tx->bEndpointAddress;
+ rx_addr = devpriv->ep_rx->bEndpointAddress;
+ tx_pipe = usb_sndbulkpipe(usb, tx_addr);
+ rx_pipe = usb_rcvbulkpipe(usb, rx_addr);
/*
* The max packet size attributes of the K8061
* input/output endpoints are identical
*/
- size = le16_to_cpu(dev->ep_tx->wMaxPacketSize);
-
- usb_bulk_msg(dev->udev, tx_pipe, dev->usb_tx_buf,
- size, NULL, dev->ep_tx->bInterval);
- usb_bulk_msg(dev->udev, rx_pipe, dev->usb_rx_buf, size, NULL, HZ * 10);
+ size = le16_to_cpu(devpriv->ep_tx->wMaxPacketSize);
- clear_bit(TRANS_OUT_BUSY, &dev->flags);
- clear_bit(TRANS_IN_BUSY, &dev->flags);
+ usb_bulk_msg(usb, tx_pipe, devpriv->usb_tx_buf,
+ size, NULL, devpriv->ep_tx->bInterval);
+ usb_bulk_msg(usb, rx_pipe, devpriv->usb_rx_buf, size, NULL, HZ * 10);
}
-static int vmk80xx_read_packet(struct vmk80xx_usb *dev)
+static int vmk80xx_read_packet(struct vmk80xx_private *devpriv)
{
- struct urb *urb;
- int retval;
+ struct usb_device *usb;
+ struct usb_endpoint_descriptor *ep;
+ unsigned int pipe;
- if (!dev->intf)
+ if (!devpriv->intf)
return -ENODEV;
- /* Only useful for interrupt transfers */
- if (test_bit(TRANS_IN_BUSY, &dev->flags))
- if (wait_event_interruptible(dev->read_wait,
- !test_bit(TRANS_IN_BUSY,
- &dev->flags)))
- return -ERESTART;
-
- if (dev->board.model == VMK8061_MODEL) {
- vmk80xx_do_bulk_msg(dev);
-
+ if (devpriv->model == VMK8061_MODEL) {
+ vmk80xx_do_bulk_msg(devpriv);
return 0;
}
- urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!urb)
- return -ENOMEM;
-
- urb->context = dev;
- vmk80xx_build_int_urb(urb, URB_RCV_FLAG);
-
- set_bit(TRANS_IN_RUNNING, &dev->flags);
- set_bit(TRANS_IN_BUSY, &dev->flags);
-
- usb_anchor_urb(urb, &dev->rx_anchor);
-
- retval = usb_submit_urb(urb, GFP_KERNEL);
- if (!retval)
- goto exit;
-
- clear_bit(TRANS_IN_RUNNING, &dev->flags);
- usb_unanchor_urb(urb);
-
-exit:
- usb_free_urb(urb);
-
- return retval;
+ usb = devpriv->usb;
+ ep = devpriv->ep_rx;
+ pipe = usb_rcvintpipe(usb, ep->bEndpointAddress);
+ return usb_interrupt_msg(usb, pipe, devpriv->usb_rx_buf,
+ le16_to_cpu(ep->wMaxPacketSize), NULL,
+ HZ * 10);
}
-static int vmk80xx_write_packet(struct vmk80xx_usb *dev, int cmd)
+static int vmk80xx_write_packet(struct vmk80xx_private *devpriv, int cmd)
{
- struct urb *urb;
- int retval;
+ struct usb_device *usb;
+ struct usb_endpoint_descriptor *ep;
+ unsigned int pipe;
- if (!dev->intf)
+ if (!devpriv->intf)
return -ENODEV;
- if (test_bit(TRANS_OUT_BUSY, &dev->flags))
- if (wait_event_interruptible(dev->write_wait,
- !test_bit(TRANS_OUT_BUSY,
- &dev->flags)))
- return -ERESTART;
-
- if (dev->board.model == VMK8061_MODEL) {
- dev->usb_tx_buf[0] = cmd;
- vmk80xx_do_bulk_msg(dev);
+ devpriv->usb_tx_buf[0] = cmd;
+ if (devpriv->model == VMK8061_MODEL) {
+ vmk80xx_do_bulk_msg(devpriv);
return 0;
}
- urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!urb)
- return -ENOMEM;
-
- urb->context = dev;
- vmk80xx_build_int_urb(urb, URB_SND_FLAG);
-
- set_bit(TRANS_OUT_BUSY, &dev->flags);
-
- usb_anchor_urb(urb, &dev->tx_anchor);
-
- dev->usb_tx_buf[0] = cmd;
-
- retval = usb_submit_urb(urb, GFP_KERNEL);
- if (!retval)
- goto exit;
-
- clear_bit(TRANS_OUT_BUSY, &dev->flags);
- usb_unanchor_urb(urb);
-
-exit:
- usb_free_urb(urb);
-
- return retval;
+ usb = devpriv->usb;
+ ep = devpriv->ep_tx;
+ pipe = usb_sndintpipe(usb, ep->bEndpointAddress);
+ return usb_interrupt_msg(usb, pipe, devpriv->usb_tx_buf,
+ le16_to_cpu(ep->wMaxPacketSize), NULL,
+ HZ * 10);
}
-#define DIR_IN 1
-#define DIR_OUT 2
-
-static int rudimentary_check(struct vmk80xx_usb *dev, int dir)
+static int vmk80xx_reset_device(struct vmk80xx_private *devpriv)
{
- if (!dev)
- return -EFAULT;
- if (!dev->probed)
- return -ENODEV;
- if (!dev->attached)
- return -ENODEV;
- if (dir & DIR_IN) {
- if (test_bit(TRANS_IN_BUSY, &dev->flags))
- return -EBUSY;
- }
- if (dir & DIR_OUT) {
- if (test_bit(TRANS_OUT_BUSY, &dev->flags))
- return -EBUSY;
- }
+ size_t size;
+ int retval;
- return 0;
+ size = le16_to_cpu(devpriv->ep_tx->wMaxPacketSize);
+ memset(devpriv->usb_tx_buf, 0, size);
+ retval = vmk80xx_write_packet(devpriv, VMK8055_CMD_RST);
+ if (retval)
+ return retval;
+ /* set outputs to known state as we cannot read them */
+ return vmk80xx_write_packet(devpriv, VMK8055_CMD_WRT_AD);
}
-static int vmk80xx_ai_rinsn(struct comedi_device *cdev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int vmk80xx_ai_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct vmk80xx_usb *dev = cdev->private;
+ struct vmk80xx_private *devpriv = dev->private;
int chan;
int reg[2];
int n;
- n = rudimentary_check(dev, DIR_IN);
- if (n)
- return n;
-
- down(&dev->limit_sem);
+ down(&devpriv->limit_sem);
chan = CR_CHAN(insn->chanspec);
- switch (dev->board.model) {
+ switch (devpriv->model) {
case VMK8055_MODEL:
if (!chan)
reg[0] = VMK8055_AI1_REG;
@@ -549,48 +332,45 @@ static int vmk80xx_ai_rinsn(struct comedi_device *cdev,
default:
reg[0] = VMK8061_AI_REG1;
reg[1] = VMK8061_AI_REG2;
- dev->usb_tx_buf[0] = VMK8061_CMD_RD_AI;
- dev->usb_tx_buf[VMK8061_CH_REG] = chan;
+ devpriv->usb_tx_buf[0] = VMK8061_CMD_RD_AI;
+ devpriv->usb_tx_buf[VMK8061_CH_REG] = chan;
break;
}
for (n = 0; n < insn->n; n++) {
- if (vmk80xx_read_packet(dev))
+ if (vmk80xx_read_packet(devpriv))
break;
- if (dev->board.model == VMK8055_MODEL) {
- data[n] = dev->usb_rx_buf[reg[0]];
+ if (devpriv->model == VMK8055_MODEL) {
+ data[n] = devpriv->usb_rx_buf[reg[0]];
continue;
}
/* VMK8061_MODEL */
- data[n] = dev->usb_rx_buf[reg[0]] + 256 *
- dev->usb_rx_buf[reg[1]];
+ data[n] = devpriv->usb_rx_buf[reg[0]] + 256 *
+ devpriv->usb_rx_buf[reg[1]];
}
- up(&dev->limit_sem);
+ up(&devpriv->limit_sem);
return n;
}
-static int vmk80xx_ao_winsn(struct comedi_device *cdev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int vmk80xx_ao_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct vmk80xx_usb *dev = cdev->private;
+ struct vmk80xx_private *devpriv = dev->private;
int chan;
int cmd;
int reg;
int n;
- n = rudimentary_check(dev, DIR_OUT);
- if (n)
- return n;
-
- down(&dev->limit_sem);
+ down(&devpriv->limit_sem);
chan = CR_CHAN(insn->chanspec);
- switch (dev->board.model) {
+ switch (devpriv->model) {
case VMK8055_MODEL:
cmd = VMK8055_CMD_WRT_AD;
if (!chan)
@@ -601,82 +381,76 @@ static int vmk80xx_ao_winsn(struct comedi_device *cdev,
default: /* NOTE: avoid compiler warnings */
cmd = VMK8061_CMD_SET_AO;
reg = VMK8061_AO_REG;
- dev->usb_tx_buf[VMK8061_CH_REG] = chan;
+ devpriv->usb_tx_buf[VMK8061_CH_REG] = chan;
break;
}
for (n = 0; n < insn->n; n++) {
- dev->usb_tx_buf[reg] = data[n];
+ devpriv->usb_tx_buf[reg] = data[n];
- if (vmk80xx_write_packet(dev, cmd))
+ if (vmk80xx_write_packet(devpriv, cmd))
break;
}
- up(&dev->limit_sem);
+ up(&devpriv->limit_sem);
return n;
}
-static int vmk80xx_ao_rinsn(struct comedi_device *cdev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int vmk80xx_ao_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct vmk80xx_usb *dev = cdev->private;
+ struct vmk80xx_private *devpriv = dev->private;
int chan;
int reg;
int n;
- n = rudimentary_check(dev, DIR_IN);
- if (n)
- return n;
-
- down(&dev->limit_sem);
+ down(&devpriv->limit_sem);
chan = CR_CHAN(insn->chanspec);
reg = VMK8061_AO_REG - 1;
- dev->usb_tx_buf[0] = VMK8061_CMD_RD_AO;
+ devpriv->usb_tx_buf[0] = VMK8061_CMD_RD_AO;
for (n = 0; n < insn->n; n++) {
- if (vmk80xx_read_packet(dev))
+ if (vmk80xx_read_packet(devpriv))
break;
- data[n] = dev->usb_rx_buf[reg + chan];
+ data[n] = devpriv->usb_rx_buf[reg + chan];
}
- up(&dev->limit_sem);
+ up(&devpriv->limit_sem);
return n;
}
-static int vmk80xx_di_bits(struct comedi_device *cdev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int vmk80xx_di_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct vmk80xx_usb *dev = cdev->private;
+ struct vmk80xx_private *devpriv = dev->private;
unsigned char *rx_buf;
int reg;
int retval;
- retval = rudimentary_check(dev, DIR_IN);
- if (retval)
- return retval;
-
- down(&dev->limit_sem);
+ down(&devpriv->limit_sem);
- rx_buf = dev->usb_rx_buf;
+ rx_buf = devpriv->usb_rx_buf;
- if (dev->board.model == VMK8061_MODEL) {
+ if (devpriv->model == VMK8061_MODEL) {
reg = VMK8061_DI_REG;
- dev->usb_tx_buf[0] = VMK8061_CMD_RD_DI;
+ devpriv->usb_tx_buf[0] = VMK8061_CMD_RD_DI;
} else {
reg = VMK8055_DI_REG;
}
- retval = vmk80xx_read_packet(dev);
+ retval = vmk80xx_read_packet(devpriv);
if (!retval) {
- if (dev->board.model == VMK8055_MODEL)
+ if (devpriv->model == VMK8055_MODEL)
data[1] = (((rx_buf[reg] >> 4) & 0x03) |
((rx_buf[reg] << 2) & 0x04) |
((rx_buf[reg] >> 3) & 0x18));
@@ -686,185 +460,48 @@ static int vmk80xx_di_bits(struct comedi_device *cdev,
retval = 2;
}
- up(&dev->limit_sem);
+ up(&devpriv->limit_sem);
return retval;
}
-static int vmk80xx_di_rinsn(struct comedi_device *cdev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int vmk80xx_do_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct vmk80xx_usb *dev = cdev->private;
- int chan;
- unsigned char *rx_buf;
- int reg;
- int inp;
- int n;
-
- n = rudimentary_check(dev, DIR_IN);
- if (n)
- return n;
-
- down(&dev->limit_sem);
- chan = CR_CHAN(insn->chanspec);
-
- rx_buf = dev->usb_rx_buf;
-
- if (dev->board.model == VMK8061_MODEL) {
- reg = VMK8061_DI_REG;
- dev->usb_tx_buf[0] = VMK8061_CMD_RD_DI;
- } else {
- reg = VMK8055_DI_REG;
- }
- for (n = 0; n < insn->n; n++) {
- if (vmk80xx_read_packet(dev))
- break;
-
- if (dev->board.model == VMK8055_MODEL)
- inp = (((rx_buf[reg] >> 4) & 0x03) |
- ((rx_buf[reg] << 2) & 0x04) |
- ((rx_buf[reg] >> 3) & 0x18));
- else
- inp = rx_buf[reg];
-
- data[n] = (inp >> chan) & 1;
- }
-
- up(&dev->limit_sem);
-
- return n;
-}
-
-static int vmk80xx_do_winsn(struct comedi_device *cdev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- struct vmk80xx_usb *dev = cdev->private;
- int chan;
- unsigned char *tx_buf;
- int reg;
- int cmd;
- int n;
-
- n = rudimentary_check(dev, DIR_OUT);
- if (n)
- return n;
-
- down(&dev->limit_sem);
- chan = CR_CHAN(insn->chanspec);
-
- tx_buf = dev->usb_tx_buf;
-
- for (n = 0; n < insn->n; n++) {
- if (dev->board.model == VMK8055_MODEL) {
- reg = VMK8055_DO_REG;
- cmd = VMK8055_CMD_WRT_AD;
- if (data[n] == 1)
- tx_buf[reg] |= (1 << chan);
- else
- tx_buf[reg] ^= (1 << chan);
- } else { /* VMK8061_MODEL */
- reg = VMK8061_DO_REG;
- if (data[n] == 1) {
- cmd = VMK8061_CMD_SET_DO;
- tx_buf[reg] = 1 << chan;
- } else {
- cmd = VMK8061_CMD_CLR_DO;
- tx_buf[reg] = 0xff - (1 << chan);
- }
- }
-
- if (vmk80xx_write_packet(dev, cmd))
- break;
- }
-
- up(&dev->limit_sem);
-
- return n;
-}
-
-static int vmk80xx_do_rinsn(struct comedi_device *cdev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- struct vmk80xx_usb *dev = cdev->private;
- int chan;
- int reg;
- int n;
-
- n = rudimentary_check(dev, DIR_IN);
- if (n)
- return n;
-
- down(&dev->limit_sem);
- chan = CR_CHAN(insn->chanspec);
-
- reg = VMK8061_DO_REG;
-
- dev->usb_tx_buf[0] = VMK8061_CMD_RD_DO;
-
- for (n = 0; n < insn->n; n++) {
- if (vmk80xx_read_packet(dev))
- break;
-
- data[n] = (dev->usb_rx_buf[reg] >> chan) & 1;
- }
-
- up(&dev->limit_sem);
-
- return n;
-}
-
-static int vmk80xx_do_bits(struct comedi_device *cdev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- struct vmk80xx_usb *dev = cdev->private;
+ struct vmk80xx_private *devpriv = dev->private;
unsigned char *rx_buf, *tx_buf;
- int dir, reg, cmd;
+ int reg, cmd;
int retval;
- dir = 0;
-
- if (data[0])
- dir |= DIR_OUT;
-
- if (dev->board.model == VMK8061_MODEL)
- dir |= DIR_IN;
-
- retval = rudimentary_check(dev, dir);
- if (retval)
- return retval;
+ if (devpriv->model == VMK8061_MODEL) {
+ reg = VMK8061_DO_REG;
+ cmd = VMK8061_CMD_DO;
+ } else { /* VMK8055_MODEL */
+ reg = VMK8055_DO_REG;
+ cmd = VMK8055_CMD_WRT_AD;
+ }
- down(&dev->limit_sem);
+ down(&devpriv->limit_sem);
- rx_buf = dev->usb_rx_buf;
- tx_buf = dev->usb_tx_buf;
+ rx_buf = devpriv->usb_rx_buf;
+ tx_buf = devpriv->usb_tx_buf;
if (data[0]) {
- if (dev->board.model == VMK8055_MODEL) {
- reg = VMK8055_DO_REG;
- cmd = VMK8055_CMD_WRT_AD;
- } else { /* VMK8061_MODEL */
- reg = VMK8061_DO_REG;
- cmd = VMK8061_CMD_DO;
- }
-
tx_buf[reg] &= ~data[0];
tx_buf[reg] |= (data[0] & data[1]);
- retval = vmk80xx_write_packet(dev, cmd);
+ retval = vmk80xx_write_packet(devpriv, cmd);
if (retval)
goto out;
}
- if (dev->board.model == VMK8061_MODEL) {
- reg = VMK8061_DO_REG;
+ if (devpriv->model == VMK8061_MODEL) {
tx_buf[0] = VMK8061_CMD_RD_DO;
- retval = vmk80xx_read_packet(dev);
+ retval = vmk80xx_read_packet(devpriv);
if (!retval) {
data[1] = rx_buf[reg];
@@ -876,28 +513,25 @@ static int vmk80xx_do_bits(struct comedi_device *cdev,
}
out:
- up(&dev->limit_sem);
+ up(&devpriv->limit_sem);
return retval;
}
-static int vmk80xx_cnt_rinsn(struct comedi_device *cdev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int vmk80xx_cnt_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct vmk80xx_usb *dev = cdev->private;
+ struct vmk80xx_private *devpriv = dev->private;
int chan;
int reg[2];
int n;
- n = rudimentary_check(dev, DIR_IN);
- if (n)
- return n;
-
- down(&dev->limit_sem);
+ down(&devpriv->limit_sem);
chan = CR_CHAN(insn->chanspec);
- switch (dev->board.model) {
+ switch (devpriv->model) {
case VMK8055_MODEL:
if (!chan)
reg[0] = VMK8055_CNT1_REG;
@@ -908,50 +542,47 @@ static int vmk80xx_cnt_rinsn(struct comedi_device *cdev,
default:
reg[0] = VMK8061_CNT_REG;
reg[1] = VMK8061_CNT_REG;
- dev->usb_tx_buf[0] = VMK8061_CMD_RD_CNT;
+ devpriv->usb_tx_buf[0] = VMK8061_CMD_RD_CNT;
break;
}
for (n = 0; n < insn->n; n++) {
- if (vmk80xx_read_packet(dev))
+ if (vmk80xx_read_packet(devpriv))
break;
- if (dev->board.model == VMK8055_MODEL)
- data[n] = dev->usb_rx_buf[reg[0]];
+ if (devpriv->model == VMK8055_MODEL)
+ data[n] = devpriv->usb_rx_buf[reg[0]];
else /* VMK8061_MODEL */
- data[n] = dev->usb_rx_buf[reg[0] * (chan + 1) + 1]
- + 256 * dev->usb_rx_buf[reg[1] * 2 + 2];
+ data[n] = devpriv->usb_rx_buf[reg[0] * (chan + 1) + 1]
+ + 256 * devpriv->usb_rx_buf[reg[1] * 2 + 2];
}
- up(&dev->limit_sem);
+ up(&devpriv->limit_sem);
return n;
}
-static int vmk80xx_cnt_cinsn(struct comedi_device *cdev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int vmk80xx_cnt_insn_config(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct vmk80xx_usb *dev = cdev->private;
+ struct vmk80xx_private *devpriv = dev->private;
unsigned int insn_cmd;
int chan;
int cmd;
int reg;
int n;
- n = rudimentary_check(dev, DIR_OUT);
- if (n)
- return n;
-
insn_cmd = data[0];
if (insn_cmd != INSN_CONFIG_RESET && insn_cmd != GPCT_RESET)
return -EINVAL;
- down(&dev->limit_sem);
+ down(&devpriv->limit_sem);
chan = CR_CHAN(insn->chanspec);
- if (dev->board.model == VMK8055_MODEL) {
+ if (devpriv->model == VMK8055_MODEL) {
if (!chan) {
cmd = VMK8055_CMD_RST_CNT1;
reg = VMK8055_CNT1_REG;
@@ -960,36 +591,33 @@ static int vmk80xx_cnt_cinsn(struct comedi_device *cdev,
reg = VMK8055_CNT2_REG;
}
- dev->usb_tx_buf[reg] = 0x00;
+ devpriv->usb_tx_buf[reg] = 0x00;
} else {
cmd = VMK8061_CMD_RST_CNT;
}
for (n = 0; n < insn->n; n++)
- if (vmk80xx_write_packet(dev, cmd))
+ if (vmk80xx_write_packet(devpriv, cmd))
break;
- up(&dev->limit_sem);
+ up(&devpriv->limit_sem);
return n;
}
-static int vmk80xx_cnt_winsn(struct comedi_device *cdev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int vmk80xx_cnt_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct vmk80xx_usb *dev = cdev->private;
+ struct vmk80xx_private *devpriv = dev->private;
unsigned long debtime;
unsigned long val;
int chan;
int cmd;
int n;
- n = rudimentary_check(dev, DIR_OUT);
- if (n)
- return n;
-
- down(&dev->limit_sem);
+ down(&devpriv->limit_sem);
chan = CR_CHAN(insn->chanspec);
if (!chan)
@@ -1010,65 +638,64 @@ static int vmk80xx_cnt_winsn(struct comedi_device *cdev,
if (((val + 1) * val) < debtime * 1000 / 115)
val += 1;
- dev->usb_tx_buf[6 + chan] = val;
+ devpriv->usb_tx_buf[6 + chan] = val;
- if (vmk80xx_write_packet(dev, cmd))
+ if (vmk80xx_write_packet(devpriv, cmd))
break;
}
- up(&dev->limit_sem);
+ up(&devpriv->limit_sem);
return n;
}
-static int vmk80xx_pwm_rinsn(struct comedi_device *cdev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int vmk80xx_pwm_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct vmk80xx_usb *dev = cdev->private;
+ struct vmk80xx_private *devpriv = dev->private;
+ unsigned char *tx_buf;
+ unsigned char *rx_buf;
int reg[2];
int n;
- n = rudimentary_check(dev, DIR_IN);
- if (n)
- return n;
+ down(&devpriv->limit_sem);
- down(&dev->limit_sem);
+ tx_buf = devpriv->usb_tx_buf;
+ rx_buf = devpriv->usb_rx_buf;
reg[0] = VMK8061_PWM_REG1;
reg[1] = VMK8061_PWM_REG2;
- dev->usb_tx_buf[0] = VMK8061_CMD_RD_PWM;
+ tx_buf[0] = VMK8061_CMD_RD_PWM;
for (n = 0; n < insn->n; n++) {
- if (vmk80xx_read_packet(dev))
+ if (vmk80xx_read_packet(devpriv))
break;
- data[n] = dev->usb_rx_buf[reg[0]] + 4 * dev->usb_rx_buf[reg[1]];
+ data[n] = rx_buf[reg[0]] + 4 * rx_buf[reg[1]];
}
- up(&dev->limit_sem);
+ up(&devpriv->limit_sem);
return n;
}
-static int vmk80xx_pwm_winsn(struct comedi_device *cdev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int vmk80xx_pwm_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct vmk80xx_usb *dev = cdev->private;
+ struct vmk80xx_private *devpriv = dev->private;
unsigned char *tx_buf;
int reg[2];
int cmd;
int n;
- n = rudimentary_check(dev, DIR_OUT);
- if (n)
- return n;
-
- down(&dev->limit_sem);
+ down(&devpriv->limit_sem);
- tx_buf = dev->usb_tx_buf;
+ tx_buf = devpriv->usb_tx_buf;
reg[0] = VMK8061_PWM_REG1;
reg[1] = VMK8061_PWM_REG2;
@@ -1092,341 +719,236 @@ static int vmk80xx_pwm_winsn(struct comedi_device *cdev,
tx_buf[reg[0]] = (unsigned char)(data[n] & 0x03);
tx_buf[reg[1]] = (unsigned char)(data[n] >> 2) & 0xff;
- if (vmk80xx_write_packet(dev, cmd))
+ if (vmk80xx_write_packet(devpriv, cmd))
break;
}
- up(&dev->limit_sem);
+ up(&devpriv->limit_sem);
return n;
}
-static int vmk80xx_attach_common(struct comedi_device *cdev,
- struct vmk80xx_usb *dev)
+static int vmk80xx_find_usb_endpoints(struct comedi_device *dev)
{
- int n_subd;
- struct comedi_subdevice *s;
- int ret;
+ struct vmk80xx_private *devpriv = dev->private;
+ struct usb_interface *intf = devpriv->intf;
+ struct usb_host_interface *iface_desc = intf->cur_altsetting;
+ struct usb_endpoint_descriptor *ep_desc;
+ int i;
- down(&dev->limit_sem);
- cdev->board_name = dev->board.name;
- cdev->private = dev;
- if (dev->board.model == VMK8055_MODEL)
- n_subd = 5;
- else
- n_subd = 6;
- ret = comedi_alloc_subdevices(cdev, n_subd);
- if (ret) {
- up(&dev->limit_sem);
- return ret;
- }
- /* Analog input subdevice */
- 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;
- s->maxdata = (1 << dev->board.ai_bits) - 1;
- s->range_table = dev->board.range;
- s->insn_read = vmk80xx_ai_rinsn;
- /* Analog output subdevice */
- 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;
- s->maxdata = (1 << dev->board.ao_bits) - 1;
- s->range_table = dev->board.range;
- s->insn_write = vmk80xx_ao_winsn;
- if (dev->board.model == VMK8061_MODEL) {
- s->subdev_flags |= SDF_READABLE;
- s->insn_read = vmk80xx_ao_rinsn;
- }
- /* Digital input subdevice */
- 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;
- s->maxdata = 1;
- s->insn_read = vmk80xx_di_rinsn;
- s->insn_bits = vmk80xx_di_bits;
- /* Digital output subdevice */
- 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;
- s->maxdata = 1;
- s->insn_write = vmk80xx_do_winsn;
- s->insn_bits = vmk80xx_do_bits;
- if (dev->board.model == VMK8061_MODEL) {
- s->subdev_flags |= SDF_READABLE;
- s->insn_read = vmk80xx_do_rinsn;
- }
- /* Counter subdevice */
- s = &cdev->subdevices[VMK80XX_SUBD_CNT];
- s->type = COMEDI_SUBD_COUNTER;
- s->subdev_flags = SDF_READABLE;
- s->n_chan = dev->board.cnt_chans;
- s->insn_read = vmk80xx_cnt_rinsn;
- s->insn_config = vmk80xx_cnt_cinsn;
- if (dev->board.model == VMK8055_MODEL) {
- s->subdev_flags |= SDF_WRITEABLE;
- s->maxdata = (1 << dev->board.cnt_bits) - 1;
- s->insn_write = vmk80xx_cnt_winsn;
- }
- /* PWM subdevice */
- if (dev->board.model == VMK8061_MODEL) {
- 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;
- s->maxdata = (1 << dev->board.pwm_bits) - 1;
- s->insn_read = vmk80xx_pwm_rinsn;
- s->insn_write = vmk80xx_pwm_winsn;
- }
- dev->attached = 1;
- dev_info(cdev->class_dev, "vmk80xx: board #%d [%s] attached\n",
- dev->count, dev->board.name);
- up(&dev->limit_sem);
- return 0;
-}
+ if (iface_desc->desc.bNumEndpoints != 2)
+ return -ENODEV;
-/* called for COMEDI_DEVCONFIG ioctl for board_name "vmk80xx" */
-static int vmk80xx_attach(struct comedi_device *cdev,
- struct comedi_devconfig *it)
-{
- int i;
- int ret;
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
+ ep_desc = &iface_desc->endpoint[i].desc;
- mutex_lock(&glb_mutex);
- for (i = 0; i < VMK80XX_MAX_BOARDS; i++)
- if (vmb[i].probed && !vmb[i].attached)
- break;
- if (i == VMK80XX_MAX_BOARDS)
- ret = -ENODEV;
- else
- ret = vmk80xx_attach_common(cdev, &vmb[i]);
- mutex_unlock(&glb_mutex);
- return ret;
-}
+ if (usb_endpoint_is_int_in(ep_desc) ||
+ usb_endpoint_is_bulk_in(ep_desc)) {
+ if (!devpriv->ep_rx)
+ devpriv->ep_rx = ep_desc;
+ continue;
+ }
-/* called via comedi_usb_auto_config() */
-static int vmk80xx_auto_attach(struct comedi_device *cdev,
- unsigned long context_unused)
-{
- struct usb_interface *intf = comedi_to_usb_interface(cdev);
- int i;
- int ret;
+ if (usb_endpoint_is_int_out(ep_desc) ||
+ usb_endpoint_is_bulk_out(ep_desc)) {
+ if (!devpriv->ep_tx)
+ devpriv->ep_tx = ep_desc;
+ continue;
+ }
+ }
- mutex_lock(&glb_mutex);
- for (i = 0; i < VMK80XX_MAX_BOARDS; i++)
- if (vmb[i].probed && vmb[i].intf == intf)
- break;
- if (i == VMK80XX_MAX_BOARDS)
- ret = -ENODEV;
- else if (vmb[i].attached)
- ret = -EBUSY;
- else
- ret = vmk80xx_attach_common(cdev, &vmb[i]);
- mutex_unlock(&glb_mutex);
- return ret;
+ if (!devpriv->ep_rx || !devpriv->ep_tx)
+ return -ENODEV;
+
+ return 0;
}
-static void vmk80xx_detach(struct comedi_device *dev)
+static int vmk80xx_alloc_usb_buffers(struct comedi_device *dev)
{
- struct vmk80xx_usb *usb = dev->private;
+ struct vmk80xx_private *devpriv = dev->private;
+ size_t size;
+
+ size = le16_to_cpu(devpriv->ep_rx->wMaxPacketSize);
+ devpriv->usb_rx_buf = kzalloc(size, GFP_KERNEL);
+ if (!devpriv->usb_rx_buf)
+ return -ENOMEM;
- if (usb) {
- down(&usb->limit_sem);
- dev->private = NULL;
- usb->attached = 0;
- up(&usb->limit_sem);
+ size = le16_to_cpu(devpriv->ep_tx->wMaxPacketSize);
+ devpriv->usb_tx_buf = kzalloc(size, GFP_KERNEL);
+ if (!devpriv->usb_tx_buf) {
+ kfree(devpriv->usb_rx_buf);
+ return -ENOMEM;
}
-}
-static struct comedi_driver vmk80xx_driver = {
- .module = THIS_MODULE,
- .driver_name = "vmk80xx",
- .attach = vmk80xx_attach,
- .detach = vmk80xx_detach,
- .auto_attach = vmk80xx_auto_attach,
-};
+ return 0;
+}
-static int vmk80xx_usb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
+static int vmk80xx_init_subdevices(struct comedi_device *dev)
{
- int i;
- struct vmk80xx_usb *dev;
- struct usb_host_interface *iface_desc;
- struct usb_endpoint_descriptor *ep_desc;
- size_t size;
-
- mutex_lock(&glb_mutex);
+ const struct vmk80xx_board *boardinfo = comedi_board(dev);
+ struct vmk80xx_private *devpriv = dev->private;
+ struct comedi_subdevice *s;
+ int n_subd;
+ int ret;
- for (i = 0; i < VMK80XX_MAX_BOARDS; i++)
- if (!vmb[i].probed)
- break;
+ down(&devpriv->limit_sem);
- if (i == VMK80XX_MAX_BOARDS) {
- mutex_unlock(&glb_mutex);
- return -EMFILE;
+ if (devpriv->model == VMK8055_MODEL)
+ n_subd = 5;
+ else
+ n_subd = 6;
+ ret = comedi_alloc_subdevices(dev, n_subd);
+ if (ret) {
+ up(&devpriv->limit_sem);
+ return ret;
}
- dev = &vmb[i];
+ /* Analog input subdevice */
+ s = &dev->subdevices[0];
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND;
+ s->n_chan = boardinfo->ai_nchans;
+ s->maxdata = boardinfo->ai_maxdata;
+ s->range_table = boardinfo->range;
+ s->insn_read = vmk80xx_ai_insn_read;
- memset(dev, 0x00, sizeof(struct vmk80xx_usb));
- dev->count = i;
+ /* Analog output subdevice */
+ s = &dev->subdevices[1];
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITEABLE | SDF_GROUND;
+ s->n_chan = boardinfo->ao_nchans;
+ s->maxdata = 0x00ff;
+ s->range_table = boardinfo->range;
+ s->insn_write = vmk80xx_ao_insn_write;
+ if (devpriv->model == VMK8061_MODEL) {
+ s->subdev_flags |= SDF_READABLE;
+ s->insn_read = vmk80xx_ao_insn_read;
+ }
- iface_desc = intf->cur_altsetting;
- if (iface_desc->desc.bNumEndpoints != 2)
- goto error;
+ /* Digital input subdevice */
+ s = &dev->subdevices[2];
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = boardinfo->di_nchans;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = vmk80xx_di_insn_bits;
- for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
- ep_desc = &iface_desc->endpoint[i].desc;
+ /* Digital output subdevice */
+ s = &dev->subdevices[3];
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITEABLE;
+ s->n_chan = 8;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = vmk80xx_do_insn_bits;
- if (usb_endpoint_is_int_in(ep_desc)) {
- dev->ep_rx = ep_desc;
- continue;
- }
+ /* Counter subdevice */
+ s = &dev->subdevices[4];
+ s->type = COMEDI_SUBD_COUNTER;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 2;
+ s->maxdata = boardinfo->cnt_maxdata;
+ s->insn_read = vmk80xx_cnt_insn_read;
+ s->insn_config = vmk80xx_cnt_insn_config;
+ if (devpriv->model == VMK8055_MODEL) {
+ s->subdev_flags |= SDF_WRITEABLE;
+ s->insn_write = vmk80xx_cnt_insn_write;
+ }
- if (usb_endpoint_is_int_out(ep_desc)) {
- dev->ep_tx = ep_desc;
- continue;
- }
+ /* PWM subdevice */
+ if (devpriv->model == VMK8061_MODEL) {
+ s = &dev->subdevices[5];
+ s->type = COMEDI_SUBD_PWM;
+ s->subdev_flags = SDF_READABLE | SDF_WRITEABLE;
+ s->n_chan = boardinfo->pwm_nchans;
+ s->maxdata = boardinfo->pwm_maxdata;
+ s->insn_read = vmk80xx_pwm_insn_read;
+ s->insn_write = vmk80xx_pwm_insn_write;
+ }
- if (usb_endpoint_is_bulk_in(ep_desc)) {
- dev->ep_rx = ep_desc;
- continue;
- }
+ up(&devpriv->limit_sem);
- if (usb_endpoint_is_bulk_out(ep_desc)) {
- dev->ep_tx = ep_desc;
- continue;
- }
- }
+ return 0;
+}
- if (!dev->ep_rx || !dev->ep_tx)
- goto error;
+static int vmk80xx_auto_attach(struct comedi_device *dev,
+ unsigned long context)
+{
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
+ const struct vmk80xx_board *boardinfo;
+ struct vmk80xx_private *devpriv;
+ int ret;
- size = le16_to_cpu(dev->ep_rx->wMaxPacketSize);
- dev->usb_rx_buf = kmalloc(size, GFP_KERNEL);
- if (!dev->usb_rx_buf) {
- mutex_unlock(&glb_mutex);
- return -ENOMEM;
- }
+ boardinfo = &vmk80xx_boardinfo[context];
+ dev->board_ptr = boardinfo;
+ dev->board_name = boardinfo->name;
- size = le16_to_cpu(dev->ep_tx->wMaxPacketSize);
- dev->usb_tx_buf = kmalloc(size, GFP_KERNEL);
- if (!dev->usb_tx_buf) {
- kfree(dev->usb_rx_buf);
- mutex_unlock(&glb_mutex);
+ devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+ if (!devpriv)
return -ENOMEM;
- }
-
- dev->udev = interface_to_usbdev(intf);
- dev->intf = intf;
-
- sema_init(&dev->limit_sem, 8);
- init_waitqueue_head(&dev->read_wait);
- init_waitqueue_head(&dev->write_wait);
-
- init_usb_anchor(&dev->rx_anchor);
- init_usb_anchor(&dev->tx_anchor);
-
- usb_set_intfdata(intf, dev);
-
- switch (id->driver_info) {
- case DEVICE_VMK8055:
- dev->board.name = "K8055 (VM110)";
- dev->board.model = VMK8055_MODEL;
- dev->board.range = &vmk8055_range;
- dev->board.ai_chans = 2;
- dev->board.ai_bits = 8;
- dev->board.ao_chans = 2;
- dev->board.ao_bits = 8;
- dev->board.di_chans = 5;
- dev->board.di_bits = 1;
- dev->board.do_chans = 8;
- dev->board.do_bits = 1;
- dev->board.cnt_chans = 2;
- dev->board.cnt_bits = 16;
- dev->board.pwm_chans = 0;
- dev->board.pwm_bits = 0;
- break;
- case DEVICE_VMK8061:
- dev->board.name = "K8061 (VM140)";
- dev->board.model = VMK8061_MODEL;
- dev->board.range = &vmk8061_range;
- dev->board.ai_chans = 8;
- dev->board.ai_bits = 10;
- dev->board.ao_chans = 8;
- dev->board.ao_bits = 8;
- dev->board.di_chans = 8;
- dev->board.di_bits = 1;
- dev->board.do_chans = 8;
- dev->board.do_bits = 1;
- dev->board.cnt_chans = 2;
- dev->board.cnt_bits = 0;
- dev->board.pwm_chans = 1;
- dev->board.pwm_bits = 10;
- break;
- }
+ dev->private = devpriv;
- if (dev->board.model == VMK8061_MODEL) {
- vmk80xx_read_eeprom(dev, IC3_VERSION);
- dev_info(&intf->dev, "%s\n", dev->fw.ic3_vers);
+ devpriv->usb = interface_to_usbdev(intf);
+ devpriv->intf = intf;
+ devpriv->model = boardinfo->model;
- if (vmk80xx_check_data_link(dev)) {
- vmk80xx_read_eeprom(dev, IC6_VERSION);
- dev_info(&intf->dev, "%s\n", dev->fw.ic6_vers);
- } else {
- dbgcm("comedi#: vmk80xx: no conn. to CPU\n");
- }
- }
+ ret = vmk80xx_find_usb_endpoints(dev);
+ if (ret)
+ return ret;
- if (dev->board.model == VMK8055_MODEL)
- vmk80xx_reset_device(dev);
+ ret = vmk80xx_alloc_usb_buffers(dev);
+ if (ret)
+ return ret;
- dev->probed = 1;
+ sema_init(&devpriv->limit_sem, 8);
- dev_info(&intf->dev, "board #%d [%s] now attached\n",
- dev->count, dev->board.name);
+ usb_set_intfdata(intf, devpriv);
- mutex_unlock(&glb_mutex);
+ if (devpriv->model == VMK8061_MODEL) {
+ vmk80xx_read_eeprom(devpriv, IC3_VERSION);
+ dev_info(&intf->dev, "%s\n", devpriv->fw.ic3_vers);
- comedi_usb_auto_config(intf, &vmk80xx_driver);
+ if (vmk80xx_check_data_link(devpriv)) {
+ vmk80xx_read_eeprom(devpriv, IC6_VERSION);
+ dev_info(&intf->dev, "%s\n", devpriv->fw.ic6_vers);
+ }
+ }
- return 0;
-error:
- mutex_unlock(&glb_mutex);
+ if (devpriv->model == VMK8055_MODEL)
+ vmk80xx_reset_device(devpriv);
- return -ENODEV;
+ return vmk80xx_init_subdevices(dev);
}
-static void vmk80xx_usb_disconnect(struct usb_interface *intf)
+static void vmk80xx_detach(struct comedi_device *dev)
{
- struct vmk80xx_usb *dev = usb_get_intfdata(intf);
+ struct vmk80xx_private *devpriv = dev->private;
- if (!dev)
+ if (!devpriv)
return;
- comedi_usb_auto_unconfig(intf);
-
- mutex_lock(&glb_mutex);
- down(&dev->limit_sem);
+ down(&devpriv->limit_sem);
- dev->probed = 0;
- usb_set_intfdata(dev->intf, NULL);
+ usb_set_intfdata(devpriv->intf, NULL);
- usb_kill_anchored_urbs(&dev->rx_anchor);
- usb_kill_anchored_urbs(&dev->tx_anchor);
+ kfree(devpriv->usb_rx_buf);
+ kfree(devpriv->usb_tx_buf);
- kfree(dev->usb_rx_buf);
- kfree(dev->usb_tx_buf);
+ up(&devpriv->limit_sem);
+}
- dev_info(&intf->dev, "board #%d [%s] now detached\n",
- dev->count, dev->board.name);
+static struct comedi_driver vmk80xx_driver = {
+ .module = THIS_MODULE,
+ .driver_name = "vmk80xx",
+ .auto_attach = vmk80xx_auto_attach,
+ .detach = vmk80xx_detach,
+};
- up(&dev->limit_sem);
- mutex_unlock(&glb_mutex);
+static int vmk80xx_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return comedi_usb_auto_config(intf, &vmk80xx_driver, id->driver_info);
}
static const struct usb_device_id vmk80xx_usb_id_table[] = {
@@ -1446,13 +968,11 @@ static const struct usb_device_id vmk80xx_usb_id_table[] = {
};
MODULE_DEVICE_TABLE(usb, vmk80xx_usb_id_table);
-/* TODO: Add support for suspend, resume, pre_reset,
- * post_reset and flush */
static struct usb_driver vmk80xx_usb_driver = {
.name = "vmk80xx",
- .probe = vmk80xx_usb_probe,
- .disconnect = vmk80xx_usb_disconnect,
.id_table = vmk80xx_usb_id_table,
+ .probe = vmk80xx_usb_probe,
+ .disconnect = comedi_usb_auto_unconfig,
};
module_comedi_usb_driver(vmk80xx_driver, vmk80xx_usb_driver);
diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
index 4dc09a210883..8932a510d96c 100644
--- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
@@ -42,7 +42,6 @@ MODULE_LICENSE("GPL");
struct comedi_device *comedi_open(const char *filename)
{
- struct comedi_device_file_info *dev_file_info;
struct comedi_device *dev;
unsigned int minor;
@@ -54,12 +53,9 @@ struct comedi_device *comedi_open(const char *filename)
if (minor >= COMEDI_NUM_BOARD_MINORS)
return NULL;
- dev_file_info = comedi_get_device_file_info(minor);
- if (dev_file_info == NULL)
- return NULL;
- dev = dev_file_info->device;
+ dev = comedi_dev_from_minor(minor);
- if (dev == NULL || !dev->attached)
+ if (!dev || !dev->attached)
return NULL;
if (!try_module_get(dev->driver->module))
diff --git a/drivers/staging/comedi/proc.c b/drivers/staging/comedi/proc.c
index 01acbe97653c..362c214bcc0b 100644
--- a/drivers/staging/comedi/proc.c
+++ b/drivers/staging/comedi/proc.c
@@ -33,7 +33,6 @@
#include <linux/proc_fs.h>
#include <linux/string.h>
-#ifdef CONFIG_PROC_FS
static int comedi_read(char *buf, char **start, off_t offset, int len,
int *eof, void *data)
{
@@ -49,13 +48,10 @@ static int comedi_read(char *buf, char **start, off_t offset, int len,
"driver_name, board_name, n_subdevices");
for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
- struct comedi_device_file_info *dev_file_info =
- comedi_get_device_file_info(i);
- struct comedi_device *dev;
+ struct comedi_device *dev = comedi_dev_from_minor(i);
- if (dev_file_info == NULL)
+ if (!dev)
continue;
- dev = dev_file_info->device;
if (dev->attached) {
devices_q = 1;
@@ -95,4 +91,3 @@ void comedi_proc_cleanup(void)
{
remove_proc_entry("comedi", NULL);
}
-#endif