aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/comedi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/comedi')
-rw-r--r--drivers/staging/comedi/Kconfig28
-rw-r--r--drivers/staging/comedi/Makefile7
-rw-r--r--drivers/staging/comedi/comedi.h13
-rw-r--r--drivers/staging/comedi/comedi_buf.c157
-rw-r--r--drivers/staging/comedi/comedi_compat32.c2
-rw-r--r--drivers/staging/comedi/comedi_fops.c279
-rw-r--r--drivers/staging/comedi/comedi_pci.c16
-rw-r--r--drivers/staging/comedi/comedi_pcmcia.c16
-rw-r--r--drivers/staging/comedi/comedi_usb.c16
-rw-r--r--drivers/staging/comedi/comedidev.h139
-rw-r--r--drivers/staging/comedi/drivers.c102
-rw-r--r--drivers/staging/comedi/drivers/Makefile1
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.c274
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.h144
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_eeprom.c360
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c480
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c28
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c381
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c2050
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c3003
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_035.c77
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1032.c5
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1500.c117
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1516.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1564.c268
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_16xx.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_2032.c32
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_2200.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3120.c1153
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3200.c125
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3501.c7
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3xxx.c11
-rw-r--r--drivers/staging/comedi/drivers/addi_tcw.h56
-rw-r--r--drivers/staging/comedi/drivers/addi_watchdog.c32
-rw-r--r--drivers/staging/comedi/drivers/adl_pci6208.c1
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9111.c40
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9118.c202
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1710.c76
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1723.c338
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1724.c471
-rw-r--r--drivers/staging/comedi/drivers/adv_pci_dio.c8
-rw-r--r--drivers/staging/comedi/drivers/aio_aio12_8.c1
-rw-r--r--drivers/staging/comedi/drivers/amcc_s5933.h2
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200_common.c34
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc236_common.c5
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc263.c2
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci224.c53
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci230.c193
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci263.c2
-rw-r--r--drivers/staging/comedi/drivers/c6xdigio.c2
-rw-r--r--drivers/staging/comedi/drivers/cb_das16_cs.c1
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas.c283
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas64.c295
-rw-r--r--drivers/staging/comedi/drivers/cb_pcimdas.c83
-rw-r--r--drivers/staging/comedi/drivers/comedi_bond.c9
-rw-r--r--drivers/staging/comedi/drivers/comedi_fc.h43
-rw-r--r--drivers/staging/comedi/drivers/comedi_parport.c5
-rw-r--r--drivers/staging/comedi/drivers/comedi_test.c63
-rw-r--r--drivers/staging/comedi/drivers/dac02.c1
-rw-r--r--drivers/staging/comedi/drivers/daqboard2000.c1
-rw-r--r--drivers/staging/comedi/drivers/das08.c3
-rw-r--r--drivers/staging/comedi/drivers/das16.c23
-rw-r--r--drivers/staging/comedi/drivers/das16m1.c7
-rw-r--r--drivers/staging/comedi/drivers/das1800.c62
-rw-r--r--drivers/staging/comedi/drivers/das6402.c202
-rw-r--r--drivers/staging/comedi/drivers/das800.c38
-rw-r--r--drivers/staging/comedi/drivers/dmm32at.c702
-rw-r--r--drivers/staging/comedi/drivers/dt2801.c1
-rw-r--r--drivers/staging/comedi/drivers/dt2811.c1
-rw-r--r--drivers/staging/comedi/drivers/dt2814.c2
-rw-r--r--drivers/staging/comedi/drivers/dt282x.c62
-rw-r--r--drivers/staging/comedi/drivers/dt3000.c9
-rw-r--r--drivers/staging/comedi/drivers/dt9812.c4
-rw-r--r--drivers/staging/comedi/drivers/dyna_pci10xx.c4
-rw-r--r--drivers/staging/comedi/drivers/fl512.c1
-rw-r--r--drivers/staging/comedi/drivers/gsc_hpdi.c8
-rw-r--r--drivers/staging/comedi/drivers/icp_multi.c9
-rw-r--r--drivers/staging/comedi/drivers/ii_pci20kc.c1
-rw-r--r--drivers/staging/comedi/drivers/me4000.c120
-rw-r--r--drivers/staging/comedi/drivers/me_daq.c5
-rw-r--r--drivers/staging/comedi/drivers/mf6x4.c1
-rw-r--r--drivers/staging/comedi/drivers/mite.c9
-rw-r--r--drivers/staging/comedi/drivers/multiq3.c1
-rw-r--r--drivers/staging/comedi/drivers/ni_6527.c8
-rw-r--r--drivers/staging/comedi/drivers/ni_65xx.c9
-rw-r--r--drivers/staging/comedi/drivers/ni_660x.c2
-rw-r--r--drivers/staging/comedi/drivers/ni_670x.c1
-rw-r--r--drivers/staging/comedi/drivers/ni_at_a2150.c21
-rw-r--r--drivers/staging/comedi/drivers/ni_at_ao.c56
-rw-r--r--drivers/staging/comedi/drivers/ni_atmio16d.c8
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc.h6
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc_common.c152
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc_isadma.c7
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_common.c166
-rw-r--r--drivers/staging/comedi/drivers/ni_pcidio.c14
-rw-r--r--drivers/staging/comedi/drivers/ni_stc.h16
-rw-r--r--drivers/staging/comedi/drivers/ni_tiocmd.c6
-rw-r--r--drivers/staging/comedi/drivers/ni_usb6501.c2
-rw-r--r--drivers/staging/comedi/drivers/pcl711.c25
-rw-r--r--drivers/staging/comedi/drivers/pcl726.c6
-rw-r--r--drivers/staging/comedi/drivers/pcl812.c40
-rw-r--r--drivers/staging/comedi/drivers/pcl816.c26
-rw-r--r--drivers/staging/comedi/drivers/pcl818.c34
-rw-r--r--drivers/staging/comedi/drivers/pcmmio.c32
-rw-r--r--drivers/staging/comedi/drivers/pcmuio.c34
-rw-r--r--drivers/staging/comedi/drivers/quatech_daqp_cs.c38
-rw-r--r--drivers/staging/comedi/drivers/rtd520.c77
-rw-r--r--drivers/staging/comedi/drivers/rti800.c1
-rw-r--r--drivers/staging/comedi/drivers/rti802.c1
-rw-r--r--drivers/staging/comedi/drivers/s526.c1
-rw-r--r--drivers/staging/comedi/drivers/s626.c38
-rw-r--r--drivers/staging/comedi/drivers/serial2002.c4
-rw-r--r--drivers/staging/comedi/drivers/usbdux.c400
-rw-r--r--drivers/staging/comedi/drivers/usbduxfast.c145
-rw-r--r--drivers/staging/comedi/drivers/usbduxsigma.c350
-rw-r--r--drivers/staging/comedi/drivers/vmk80xx.c8
-rw-r--r--drivers/staging/comedi/range.c36
117 files changed, 4234 insertions, 10410 deletions
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
index 152f4c12ea43..a8201fe87512 100644
--- a/drivers/staging/comedi/Kconfig
+++ b/drivers/staging/comedi/Kconfig
@@ -384,6 +384,7 @@ config COMEDI_DT282X
config COMEDI_DMM32AT
tristate "Diamond Systems MM-32-AT PC/104 board support"
+ select COMEDI_8255
---help---
Enable support for Diamond Systems MM-32-AT PC/104 boards
@@ -564,11 +565,14 @@ config COMEDI_S526
endif # COMEDI_ISA_DRIVERS
menuconfig COMEDI_PCI_DRIVERS
- bool "Comedi PCI drivers"
+ tristate "Comedi PCI drivers"
depends on PCI
---help---
Enable support for comedi PCI drivers.
+ To compile this support as a module, choose M here: the module will
+ be called comedi_pci.
+
if COMEDI_PCI_DRIVERS
config COMEDI_8255_PCI
@@ -595,14 +599,6 @@ config COMEDI_ADDI_WATCHDOG
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---
- Enable support for ADDI-DATA APCI_035 cards
-
- To compile this driver as a module, choose M here: the module will be
- called addi_apci_035.
-
config COMEDI_ADDI_APCI_1032
tristate "ADDI-DATA APCI_1032 support"
---help---
@@ -939,11 +935,11 @@ config COMEDI_CB_PCIDDA
called cb_pcidda.
config COMEDI_CB_PCIMDAS
- tristate "MeasurementComputing PCIM-DAS1602/16 support"
+ tristate "MeasurementComputing PCIM-DAS1602/16, PCIe-DAS1602/16 support"
select COMEDI_8255
---help---
Enable support for ComputerBoards/MeasurementComputing PCI Migration
- series PCIM-DAS1602/16
+ series PCIM-DAS1602/16 and PCIe-DAS1602/16.
To compile this driver as a module, choose M here: the module will be
called cb_pcimdas.
@@ -1084,11 +1080,14 @@ config COMEDI_NI_TIOCMD
endif # COMEDI_PCI_DRIVERS
menuconfig COMEDI_PCMCIA_DRIVERS
- bool "Comedi PCMCIA drivers"
+ tristate "Comedi PCMCIA drivers"
depends on PCMCIA
---help---
Enable support for comedi PCMCIA drivers.
+ To compile this support as a module, choose M here: the module will
+ be called comedi_pcmcia.
+
if COMEDI_PCMCIA_DRIVERS
config COMEDI_CB_DAS16_CS
@@ -1160,11 +1159,14 @@ config COMEDI_QUATECH_DAQP_CS
endif # COMEDI_PCMCIA_DRIVERS
menuconfig COMEDI_USB_DRIVERS
- bool "Comedi USB drivers"
+ tristate "Comedi USB drivers"
depends on USB
---help---
Enable support for comedi USB drivers.
+ To compile this support as a module, choose M here: the module will
+ be called comedi_usb.
+
if COMEDI_USB_DRIVERS
config COMEDI_DT9812
diff --git a/drivers/staging/comedi/Makefile b/drivers/staging/comedi/Makefile
index fae2d9090006..7f9dfb3923ab 100644
--- a/drivers/staging/comedi/Makefile
+++ b/drivers/staging/comedi/Makefile
@@ -2,12 +2,13 @@ ccflags-$(CONFIG_COMEDI_DEBUG) := -DDEBUG
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_PCI_DRIVERS) += comedi_pci.o
+obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += comedi_pcmcia.o
+obj-$(CONFIG_COMEDI_USB_DRIVERS) += comedi_usb.o
+
obj-$(CONFIG_COMEDI) += comedi.o
obj-$(CONFIG_COMEDI) += kcomedilib/
diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
index c8c99e65423b..745574077352 100644
--- a/drivers/staging/comedi/comedi.h
+++ b/drivers/staging/comedi/comedi.h
@@ -367,6 +367,8 @@ enum comedi_support_level {
#define COMEDI_BUFCONFIG _IOR(CIO, 13, struct comedi_bufconfig)
#define COMEDI_BUFINFO _IOWR(CIO, 14, struct comedi_bufinfo)
#define COMEDI_POLL _IO(CIO, 15)
+#define COMEDI_SETRSUBD _IO(CIO, 16)
+#define COMEDI_SETWSUBD _IO(CIO, 17)
/* structures */
@@ -514,17 +516,6 @@ struct comedi_bufinfo {
#define COMEDI_MIN_SPEED ((unsigned int)0xffffffff)
-/* callback stuff */
-/* only relevant to kernel modules. */
-
-#define COMEDI_CB_EOS 1 /* end of scan */
-#define COMEDI_CB_EOA 2 /* end of acquisition/output */
-#define COMEDI_CB_BLOCK 4 /* data has arrived:
- * wakes up read() / write() */
-#define COMEDI_CB_EOBUF 8 /* DEPRECATED: end of buffer */
-#define COMEDI_CB_ERROR 16 /* card error during acquisition */
-#define COMEDI_CB_OVERFLOW 32 /* buffer overflow/underflow */
-
/**********************************************************/
/* everything after this line is ALPHA */
/**********************************************************/
diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c
index c60a45ad12b9..19e7b229d15e 100644
--- a/drivers/staging/comedi/comedi_buf.c
+++ b/drivers/staging/comedi/comedi_buf.c
@@ -236,6 +236,7 @@ void comedi_buf_reset(struct comedi_subdevice *s)
async->buf_read_ptr = 0;
async->cur_chan = 0;
+ async->scans_done = 0;
async->scan_progress = 0;
async->munge_chan = 0;
async->munge_count = 0;
@@ -252,15 +253,15 @@ static unsigned int comedi_buf_write_n_available(struct comedi_subdevice *s)
return free_end - async->buf_write_alloc_count;
}
-static unsigned int __comedi_buf_write_alloc(struct comedi_subdevice *s,
- unsigned int nbytes,
- int strict)
+/* allocates chunk for the writer from free buffer space */
+unsigned int comedi_buf_write_alloc(struct comedi_subdevice *s,
+ unsigned int nbytes)
{
struct comedi_async *async = s->async;
unsigned int available = comedi_buf_write_n_available(s);
if (nbytes > available)
- nbytes = strict ? 0 : available;
+ nbytes = available;
async->buf_write_alloc_count += nbytes;
@@ -272,13 +273,6 @@ static unsigned int __comedi_buf_write_alloc(struct comedi_subdevice *s,
return nbytes;
}
-
-/* allocates chunk for the writer from free buffer space */
-unsigned int comedi_buf_write_alloc(struct comedi_subdevice *s,
- unsigned int nbytes)
-{
- return __comedi_buf_write_alloc(s, nbytes, 0);
-}
EXPORT_SYMBOL_GPL(comedi_buf_write_alloc);
/*
@@ -290,7 +284,7 @@ static unsigned int comedi_buf_munge(struct comedi_subdevice *s,
{
struct comedi_async *async = s->async;
unsigned int count = 0;
- const unsigned num_sample_bytes = bytes_per_sample(s);
+ const unsigned num_sample_bytes = comedi_bytes_per_sample(s);
if (!s->munge || (async->cmd.flags & CMDF_RAWDATA)) {
async->munge_count += num_bytes;
@@ -427,43 +421,11 @@ unsigned int comedi_buf_read_free(struct comedi_subdevice *s,
}
EXPORT_SYMBOL_GPL(comedi_buf_read_free);
-int comedi_buf_put(struct comedi_subdevice *s, unsigned short x)
-{
- struct comedi_async *async = s->async;
- unsigned int n = __comedi_buf_write_alloc(s, sizeof(short), 1);
-
- if (n < sizeof(short)) {
- async->events |= COMEDI_CB_ERROR;
- return 0;
- }
- *(unsigned short *)(async->prealloc_buf + async->buf_write_ptr) = x;
- comedi_buf_write_free(s, sizeof(short));
- return 1;
-}
-EXPORT_SYMBOL_GPL(comedi_buf_put);
-
-int comedi_buf_get(struct comedi_subdevice *s, unsigned short *x)
+static void comedi_buf_memcpy_to(struct comedi_subdevice *s,
+ const void *data, unsigned int num_bytes)
{
struct comedi_async *async = s->async;
- unsigned int n = comedi_buf_read_n_available(s);
-
- if (n < sizeof(short))
- return 0;
- comedi_buf_read_alloc(s, sizeof(short));
- *x = *(unsigned short *)(async->prealloc_buf + async->buf_read_ptr);
- comedi_buf_read_free(s, sizeof(short));
- return 1;
-}
-EXPORT_SYMBOL_GPL(comedi_buf_get);
-
-void comedi_buf_memcpy_to(struct comedi_subdevice *s, unsigned int offset,
- const void *data, unsigned int num_bytes)
-{
- struct comedi_async *async = s->async;
- unsigned int write_ptr = async->buf_write_ptr + offset;
-
- if (write_ptr >= async->prealloc_bufsz)
- write_ptr %= async->prealloc_bufsz;
+ unsigned int write_ptr = async->buf_write_ptr;
while (num_bytes) {
unsigned int block_size;
@@ -481,17 +443,13 @@ void comedi_buf_memcpy_to(struct comedi_subdevice *s, unsigned int offset,
write_ptr = 0;
}
}
-EXPORT_SYMBOL_GPL(comedi_buf_memcpy_to);
-void comedi_buf_memcpy_from(struct comedi_subdevice *s, unsigned int offset,
- void *dest, unsigned int nbytes)
+static void comedi_buf_memcpy_from(struct comedi_subdevice *s,
+ void *dest, unsigned int nbytes)
{
void *src;
struct comedi_async *async = s->async;
- unsigned int read_ptr = async->buf_read_ptr + offset;
-
- if (read_ptr >= async->prealloc_bufsz)
- read_ptr %= async->prealloc_bufsz;
+ unsigned int read_ptr = async->buf_read_ptr;
while (nbytes) {
unsigned int block_size;
@@ -509,69 +467,84 @@ void comedi_buf_memcpy_from(struct comedi_subdevice *s, unsigned int offset,
read_ptr = 0;
}
}
-EXPORT_SYMBOL_GPL(comedi_buf_memcpy_from);
/**
- * comedi_write_array_to_buffer - write data to comedi buffer
+ * comedi_buf_write_samples - write sample data to comedi buffer
* @s: comedi_subdevice struct
- * @data: destination
- * @num_bytes: number of bytes to write
+ * @data: samples
+ * @nsamples: number of samples
*
- * Writes up to num_bytes bytes of data to the comedi buffer associated with
- * the subdevice, marks it as written and updates the acquisition scan
- * progress.
+ * Writes nsamples to the comedi buffer associated with the subdevice, marks
+ * it as written and updates the acquisition scan progress.
*
* Returns the amount of data written in bytes.
*/
-unsigned int comedi_write_array_to_buffer(struct comedi_subdevice *s,
- const void *data,
- unsigned int num_bytes)
+unsigned int comedi_buf_write_samples(struct comedi_subdevice *s,
+ const void *data, unsigned int nsamples)
{
- struct comedi_async *async = s->async;
- unsigned int retval;
-
- if (num_bytes == 0)
- return 0;
+ unsigned int max_samples;
+ unsigned int nbytes;
- retval = comedi_buf_write_alloc(s, num_bytes);
- if (retval != num_bytes) {
+ /*
+ * Make sure there is enough room in the buffer for all the samples.
+ * If not, clamp the nsamples to the number that will fit, flag the
+ * buffer overrun and add the samples that fit.
+ */
+ max_samples = comedi_bytes_to_samples(s,
+ comedi_buf_write_n_available(s));
+ if (nsamples > max_samples) {
dev_warn(s->device->class_dev, "buffer overrun\n");
- async->events |= COMEDI_CB_OVERFLOW;
- return 0;
+ s->async->events |= COMEDI_CB_OVERFLOW;
+ nsamples = max_samples;
}
- comedi_buf_memcpy_to(s, 0, data, num_bytes);
- comedi_buf_write_free(s, num_bytes);
- comedi_inc_scan_progress(s, num_bytes);
- async->events |= COMEDI_CB_BLOCK;
+ if (nsamples == 0)
+ return 0;
- return num_bytes;
+ nbytes = comedi_buf_write_alloc(s,
+ comedi_samples_to_bytes(s, nsamples));
+ comedi_buf_memcpy_to(s, data, nbytes);
+ comedi_buf_write_free(s, nbytes);
+ comedi_inc_scan_progress(s, nbytes);
+ s->async->events |= COMEDI_CB_BLOCK;
+
+ return nbytes;
}
-EXPORT_SYMBOL_GPL(comedi_write_array_to_buffer);
+EXPORT_SYMBOL_GPL(comedi_buf_write_samples);
/**
- * comedi_read_array_from_buffer - read data from comedi buffer
+ * comedi_buf_read_samples - read sample data from comedi buffer
* @s: comedi_subdevice struct
* @data: destination
- * @num_bytes: number of bytes to read
+ * @nsamples: maximum number of samples to read
*
- * Reads up to num_bytes bytes of data from the comedi buffer associated with
- * the subdevice, marks it as read and updates the acquisition scan progress.
+ * Reads up to nsamples from the comedi buffer associated with the subdevice,
+ * marks it as read and updates the acquisition scan progress.
*
* Returns the amount of data read in bytes.
*/
-unsigned int comedi_read_array_from_buffer(struct comedi_subdevice *s,
- void *data, unsigned int num_bytes)
+unsigned int comedi_buf_read_samples(struct comedi_subdevice *s,
+ void *data, unsigned int nsamples)
{
- if (num_bytes == 0)
+ unsigned int max_samples;
+ unsigned int nbytes;
+
+ /* clamp nsamples to the number of full samples available */
+ max_samples = comedi_bytes_to_samples(s,
+ comedi_buf_read_n_available(s));
+ if (nsamples > max_samples)
+ nsamples = max_samples;
+
+ if (nsamples == 0)
return 0;
- num_bytes = comedi_buf_read_alloc(s, num_bytes);
- comedi_buf_memcpy_from(s, 0, data, num_bytes);
- comedi_buf_read_free(s, num_bytes);
- comedi_inc_scan_progress(s, num_bytes);
+ nbytes = comedi_buf_read_alloc(s,
+ comedi_samples_to_bytes(s, nsamples));
+ comedi_buf_memcpy_from(s, data, nbytes);
+ comedi_buf_read_free(s, nbytes);
+ comedi_inc_scan_progress(s, nbytes);
s->async->events |= COMEDI_CB_BLOCK;
- return num_bytes;
+ return nbytes;
}
-EXPORT_SYMBOL_GPL(comedi_read_array_from_buffer);
+EXPORT_SYMBOL_GPL(comedi_buf_read_samples);
diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c
index 9b6f96f1591c..5a4c74f703b3 100644
--- a/drivers/staging/comedi/comedi_compat32.c
+++ b/drivers/staging/comedi/comedi_compat32.c
@@ -416,6 +416,8 @@ static inline int raw_ioctl(struct file *file, unsigned int cmd,
case COMEDI_UNLOCK:
case COMEDI_CANCEL:
case COMEDI_POLL:
+ case COMEDI_SETRSUBD:
+ case COMEDI_SETWSUBD:
/* No translation needed. */
rc = translated_ioctl(file, cmd, arg);
break;
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 9c32f0276009..f143cb64d69e 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -43,6 +43,22 @@
#include "comedi_internal.h"
+/**
+ * struct comedi_file - per-file private data for comedi device
+ * @dev: comedi_device struct
+ * @read_subdev: current "read" subdevice
+ * @write_subdev: current "write" subdevice
+ * @last_detach_count: last known detach count
+ * @last_attached: last known attached/detached state
+ */
+struct comedi_file {
+ struct comedi_device *dev;
+ struct comedi_subdevice *read_subdev;
+ struct comedi_subdevice *write_subdev;
+ unsigned int last_detach_count;
+ bool last_attached:1;
+};
+
#define COMEDI_NUM_MINORS 0x100
#define COMEDI_NUM_SUBDEVICE_MINORS \
(COMEDI_NUM_MINORS - COMEDI_NUM_BOARD_MINORS)
@@ -239,6 +255,54 @@ comedi_write_subdevice(const struct comedi_device *dev, unsigned int minor)
return dev->write_subdev;
}
+static void comedi_file_reset(struct file *file)
+{
+ struct comedi_file *cfp = file->private_data;
+ struct comedi_device *dev = cfp->dev;
+ struct comedi_subdevice *s, *read_s, *write_s;
+ unsigned int minor = iminor(file_inode(file));
+
+ read_s = dev->read_subdev;
+ write_s = dev->write_subdev;
+ if (minor >= COMEDI_NUM_BOARD_MINORS) {
+ s = comedi_subdevice_from_minor(dev, minor);
+ if (s == NULL || s->subdev_flags & SDF_CMD_READ)
+ read_s = s;
+ if (s == NULL || s->subdev_flags & SDF_CMD_WRITE)
+ write_s = s;
+ }
+ cfp->last_attached = dev->attached;
+ cfp->last_detach_count = dev->detach_count;
+ ACCESS_ONCE(cfp->read_subdev) = read_s;
+ ACCESS_ONCE(cfp->write_subdev) = write_s;
+}
+
+static void comedi_file_check(struct file *file)
+{
+ struct comedi_file *cfp = file->private_data;
+ struct comedi_device *dev = cfp->dev;
+
+ if (cfp->last_attached != dev->attached ||
+ cfp->last_detach_count != dev->detach_count)
+ comedi_file_reset(file);
+}
+
+static struct comedi_subdevice *comedi_file_read_subdevice(struct file *file)
+{
+ struct comedi_file *cfp = file->private_data;
+
+ comedi_file_check(file);
+ return ACCESS_ONCE(cfp->read_subdev);
+}
+
+static struct comedi_subdevice *comedi_file_write_subdevice(struct file *file)
+{
+ struct comedi_file *cfp = file->private_data;
+
+ comedi_file_check(file);
+ return ACCESS_ONCE(cfp->write_subdev);
+}
+
static int resize_async_buffer(struct comedi_device *dev,
struct comedi_subdevice *s, unsigned new_size)
{
@@ -776,7 +840,6 @@ static int do_devinfo_ioctl(struct comedi_device *dev,
struct comedi_devinfo __user *arg,
struct file *file)
{
- const unsigned minor = iminor(file_inode(file));
struct comedi_subdevice *s;
struct comedi_devinfo devinfo;
@@ -788,13 +851,13 @@ 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);
- s = comedi_read_subdevice(dev, minor);
+ s = comedi_file_read_subdevice(file);
if (s)
devinfo.read_subdevice = s->index;
else
devinfo.read_subdevice = -1;
- s = comedi_write_subdevice(dev, minor);
+ s = comedi_file_write_subdevice(file);
if (s)
devinfo.write_subdevice = s->index;
else
@@ -991,7 +1054,7 @@ static int do_bufinfo_ioctl(struct comedi_device *dev,
if (s->busy != file)
return -EACCES;
- if (bi.bytes_read && (s->subdev_flags & SDF_CMD_READ)) {
+ if (bi.bytes_read && !(async->cmd.flags & CMDF_WRITE)) {
bi.bytes_read = comedi_buf_read_alloc(s, bi.bytes_read);
comedi_buf_read_free(s, bi.bytes_read);
@@ -1001,7 +1064,7 @@ static int do_bufinfo_ioctl(struct comedi_device *dev,
}
}
- if (bi.bytes_written && (s->subdev_flags & SDF_CMD_WRITE)) {
+ if (bi.bytes_written && (async->cmd.flags & CMDF_WRITE)) {
bi.bytes_written =
comedi_buf_write_alloc(s, bi.bytes_written);
comedi_buf_write_free(s, bi.bytes_written);
@@ -1451,6 +1514,21 @@ static int __comedi_get_user_cmd(struct comedi_device *dev,
return -EINVAL;
}
+ /*
+ * Set the CMDF_WRITE flag to the correct state if the subdevice
+ * supports only "read" commands or only "write" commands.
+ */
+ switch (s->subdev_flags & (SDF_CMD_READ | SDF_CMD_WRITE)) {
+ case SDF_CMD_READ:
+ cmd->flags &= ~CMDF_WRITE;
+ break;
+ case SDF_CMD_WRITE:
+ cmd->flags |= CMDF_WRITE;
+ break;
+ default:
+ break;
+ }
+
return 0;
}
@@ -1552,9 +1630,7 @@ static int do_cmd_ioctl(struct comedi_device *dev,
comedi_buf_reset(s);
- async->cb_mask =
- COMEDI_CB_EOA | COMEDI_CB_BLOCK | COMEDI_CB_ERROR |
- COMEDI_CB_OVERFLOW;
+ async->cb_mask = COMEDI_CB_BLOCK | COMEDI_CB_CANCEL_MASK;
if (async->cmd.flags & CMDF_WAKE_EOS)
async->cb_mask |= COMEDI_CB_EOS;
@@ -1720,7 +1796,6 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned long arg,
void *file)
{
struct comedi_subdevice *s;
- int ret;
if (arg >= dev->n_subdevices)
return -EINVAL;
@@ -1734,9 +1809,7 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned long arg,
if (s->busy != file)
return -EBUSY;
- ret = do_cancel(dev, s);
-
- return ret;
+ return do_cancel(dev, s);
}
/*
@@ -1774,11 +1847,96 @@ static int do_poll_ioctl(struct comedi_device *dev, unsigned long arg,
return -EINVAL;
}
+/*
+ * COMEDI_SETRSUBD ioctl
+ * sets the current "read" subdevice on a per-file basis
+ *
+ * arg:
+ * subdevice number
+ *
+ * reads:
+ * nothing
+ *
+ * writes:
+ * nothing
+ */
+static int do_setrsubd_ioctl(struct comedi_device *dev, unsigned long arg,
+ struct file *file)
+{
+ struct comedi_file *cfp = file->private_data;
+ struct comedi_subdevice *s_old, *s_new;
+
+ if (arg >= dev->n_subdevices)
+ return -EINVAL;
+
+ s_new = &dev->subdevices[arg];
+ s_old = comedi_file_read_subdevice(file);
+ if (s_old == s_new)
+ return 0; /* no change */
+
+ if (!(s_new->subdev_flags & SDF_CMD_READ))
+ return -EINVAL;
+
+ /*
+ * Check the file isn't still busy handling a "read" command on the
+ * old subdevice (if any).
+ */
+ if (s_old && s_old->busy == file && s_old->async &&
+ !(s_old->async->cmd.flags & CMDF_WRITE))
+ return -EBUSY;
+
+ ACCESS_ONCE(cfp->read_subdev) = s_new;
+ return 0;
+}
+
+/*
+ * COMEDI_SETWSUBD ioctl
+ * sets the current "write" subdevice on a per-file basis
+ *
+ * arg:
+ * subdevice number
+ *
+ * reads:
+ * nothing
+ *
+ * writes:
+ * nothing
+ */
+static int do_setwsubd_ioctl(struct comedi_device *dev, unsigned long arg,
+ struct file *file)
+{
+ struct comedi_file *cfp = file->private_data;
+ struct comedi_subdevice *s_old, *s_new;
+
+ if (arg >= dev->n_subdevices)
+ return -EINVAL;
+
+ s_new = &dev->subdevices[arg];
+ s_old = comedi_file_write_subdevice(file);
+ if (s_old == s_new)
+ return 0; /* no change */
+
+ if (!(s_new->subdev_flags & SDF_CMD_WRITE))
+ return -EINVAL;
+
+ /*
+ * Check the file isn't still busy handling a "write" command on the
+ * old subdevice (if any).
+ */
+ if (s_old && s_old->busy == file && s_old->async &&
+ (s_old->async->cmd.flags & CMDF_WRITE))
+ return -EBUSY;
+
+ ACCESS_ONCE(cfp->write_subdev) = s_new;
+ return 0;
+}
+
static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
- const unsigned minor = iminor(file_inode(file));
- struct comedi_device *dev = file->private_data;
+ unsigned minor = iminor(file_inode(file));
+ struct comedi_file *cfp = file->private_data;
+ struct comedi_device *dev = cfp->dev;
int rc;
mutex_lock(&dev->mutex);
@@ -1867,6 +2025,12 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
case COMEDI_POLL:
rc = do_poll_ioctl(dev, arg, file);
break;
+ case COMEDI_SETRSUBD:
+ rc = do_setrsubd_ioctl(dev, arg, file);
+ break;
+ case COMEDI_SETWSUBD:
+ rc = do_setwsubd_ioctl(dev, arg, file);
+ break;
default:
rc = -ENOTTY;
break;
@@ -1900,8 +2064,8 @@ 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_inode(file));
- struct comedi_device *dev = file->private_data;
+ struct comedi_file *cfp = file->private_data;
+ struct comedi_device *dev = cfp->dev;
struct comedi_subdevice *s;
struct comedi_async *async;
struct comedi_buf_map *bm = NULL;
@@ -1927,9 +2091,9 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
}
if (vma->vm_flags & VM_WRITE)
- s = comedi_write_subdevice(dev, minor);
+ s = comedi_file_write_subdevice(file);
else
- s = comedi_read_subdevice(dev, minor);
+ s = comedi_file_read_subdevice(file);
if (!s) {
retval = -EINVAL;
goto done;
@@ -1992,8 +2156,8 @@ done:
static unsigned int comedi_poll(struct file *file, poll_table *wait)
{
unsigned int mask = 0;
- const unsigned minor = iminor(file_inode(file));
- struct comedi_device *dev = file->private_data;
+ struct comedi_file *cfp = file->private_data;
+ struct comedi_device *dev = cfp->dev;
struct comedi_subdevice *s;
mutex_lock(&dev->mutex);
@@ -2003,21 +2167,23 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait)
goto done;
}
- s = comedi_read_subdevice(dev, minor);
+ s = comedi_file_read_subdevice(file);
if (s && s->async) {
poll_wait(file, &s->async->wait_head, wait);
if (!s->busy || !comedi_is_subdevice_running(s) ||
+ (s->async->cmd.flags & CMDF_WRITE) ||
comedi_buf_read_n_available(s) > 0)
mask |= POLLIN | POLLRDNORM;
}
- s = comedi_write_subdevice(dev, minor);
+ s = comedi_file_write_subdevice(file);
if (s && s->async) {
- unsigned int bps = bytes_per_sample(s);
+ unsigned int bps = comedi_bytes_per_sample(s);
poll_wait(file, &s->async->wait_head, wait);
comedi_buf_write_alloc(s, s->async->prealloc_bufsz);
if (!s->busy || !comedi_is_subdevice_running(s) ||
+ !(s->async->cmd.flags & CMDF_WRITE) ||
comedi_buf_write_n_allocated(s) >= bps)
mask |= POLLOUT | POLLWRNORM;
}
@@ -2034,8 +2200,8 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
struct comedi_async *async;
int n, m, count = 0, retval = 0;
DECLARE_WAITQUEUE(wait, current);
- const unsigned minor = iminor(file_inode(file));
- struct comedi_device *dev = file->private_data;
+ struct comedi_file *cfp = file->private_data;
+ struct comedi_device *dev = cfp->dev;
bool on_wait_queue = false;
bool attach_locked;
unsigned int old_detach_count;
@@ -2051,7 +2217,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
goto out;
}
- s = comedi_write_subdevice(dev, minor);
+ s = comedi_file_write_subdevice(file);
if (!s || !s->async) {
retval = -EIO;
goto out;
@@ -2065,6 +2231,10 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
retval = -EACCES;
goto out;
}
+ if (!(async->cmd.flags & CMDF_WRITE)) {
+ retval = -EINVAL;
+ goto out;
+ }
add_wait_queue(&async->wait_head, &wait);
on_wait_queue = true;
@@ -2099,7 +2269,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
* meantime!), but check the subdevice pointer
* as well just in case.
*/
- new_s = comedi_write_subdevice(dev, minor);
+ new_s = comedi_file_write_subdevice(file);
if (dev->attached &&
old_detach_count == dev->detach_count &&
s == new_s && new_s->async == async)
@@ -2136,6 +2306,10 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
retval = -EACCES;
break;
}
+ if (!(async->cmd.flags & CMDF_WRITE)) {
+ retval = -EINVAL;
+ break;
+ }
continue;
}
@@ -2170,8 +2344,8 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
struct comedi_async *async;
int n, m, count = 0, retval = 0;
DECLARE_WAITQUEUE(wait, current);
- const unsigned minor = iminor(file_inode(file));
- struct comedi_device *dev = file->private_data;
+ struct comedi_file *cfp = file->private_data;
+ struct comedi_device *dev = cfp->dev;
unsigned int old_detach_count;
bool become_nonbusy = false;
bool attach_locked;
@@ -2187,7 +2361,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
goto out;
}
- s = comedi_read_subdevice(dev, minor);
+ s = comedi_file_read_subdevice(file);
if (!s || !s->async) {
retval = -EIO;
goto out;
@@ -2200,6 +2374,10 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
retval = -EACCES;
goto out;
}
+ if (async->cmd.flags & CMDF_WRITE) {
+ retval = -EINVAL;
+ goto out;
+ }
add_wait_queue(&async->wait_head, &wait);
while (nbytes > 0 && !retval) {
@@ -2239,6 +2417,10 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
retval = -EACCES;
break;
}
+ if (async->cmd.flags & CMDF_WRITE) {
+ retval = -EINVAL;
+ break;
+ }
continue;
}
m = copy_to_user(buf, async->prealloc_buf +
@@ -2276,7 +2458,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
* meantime!), but check the subdevice pointer as well just in
* case.
*/
- new_s = comedi_read_subdevice(dev, minor);
+ new_s = comedi_file_read_subdevice(file);
if (dev->attached && old_detach_count == dev->detach_count &&
s == new_s && new_s->async == async) {
if (become_nonbusy || comedi_buf_n_bytes_ready(s) == 0)
@@ -2294,6 +2476,7 @@ out:
static int comedi_open(struct inode *inode, struct file *file)
{
const unsigned minor = iminor(inode);
+ struct comedi_file *cfp;
struct comedi_device *dev = comedi_dev_get_from_minor(minor);
int rc;
@@ -2302,6 +2485,12 @@ static int comedi_open(struct inode *inode, struct file *file)
return -ENODEV;
}
+ cfp = kzalloc(sizeof(*cfp), GFP_KERNEL);
+ if (!cfp)
+ return -ENOMEM;
+
+ cfp->dev = dev;
+
mutex_lock(&dev->mutex);
if (!dev->attached && !capable(CAP_NET_ADMIN)) {
dev_dbg(dev->class_dev, "not attached and not CAP_NET_ADMIN\n");
@@ -2323,26 +2512,31 @@ static int comedi_open(struct inode *inode, struct file *file)
}
dev->use_count++;
- file->private_data = dev;
+ file->private_data = cfp;
+ comedi_file_reset(file);
rc = 0;
out:
mutex_unlock(&dev->mutex);
- if (rc)
+ if (rc) {
comedi_dev_put(dev);
+ kfree(cfp);
+ }
return rc;
}
static int comedi_fasync(int fd, struct file *file, int on)
{
- struct comedi_device *dev = file->private_data;
+ struct comedi_file *cfp = file->private_data;
+ struct comedi_device *dev = cfp->dev;
return fasync_helper(fd, file, on, &dev->async_queue);
}
static int comedi_close(struct inode *inode, struct file *file)
{
- struct comedi_device *dev = file->private_data;
+ struct comedi_file *cfp = file->private_data;
+ struct comedi_device *dev = cfp->dev;
struct comedi_subdevice *s = NULL;
int i;
@@ -2368,6 +2562,7 @@ static int comedi_close(struct inode *inode, struct file *file)
mutex_unlock(&dev->mutex);
comedi_dev_put(dev);
+ kfree(cfp);
return 0;
}
@@ -2395,14 +2590,14 @@ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
if (!comedi_is_subdevice_running(s))
return;
- if (s->
- async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
- COMEDI_CB_OVERFLOW)) {
+ if (s->async->events & COMEDI_CB_CANCEL_MASK)
runflags_mask |= SRF_RUNNING;
- }
- /* remember if an error event has occurred, so an error
- * can be returned the next time the user does a read() */
- if (s->async->events & (COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW)) {
+
+ /*
+ * Remember if an error event has occurred, so an error
+ * can be returned the next time the user does a read().
+ */
+ if (s->async->events & COMEDI_CB_ERROR_MASK) {
runflags_mask |= SRF_ERROR;
runflags |= SRF_ERROR;
}
diff --git a/drivers/staging/comedi/comedi_pci.c b/drivers/staging/comedi/comedi_pci.c
index aa0795a2660e..6ba59c977006 100644
--- a/drivers/staging/comedi/comedi_pci.c
+++ b/drivers/staging/comedi/comedi_pci.c
@@ -16,6 +16,7 @@
* GNU General Public License for more details.
*/
+#include <linux/module.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
@@ -168,3 +169,18 @@ void comedi_pci_driver_unregister(struct comedi_driver *comedi_driver,
comedi_driver_unregister(comedi_driver);
}
EXPORT_SYMBOL_GPL(comedi_pci_driver_unregister);
+
+static int __init comedi_pci_init(void)
+{
+ return 0;
+}
+module_init(comedi_pci_init);
+
+static void __exit comedi_pci_exit(void)
+{
+}
+module_exit(comedi_pci_exit);
+
+MODULE_AUTHOR("http://www.comedi.org");
+MODULE_DESCRIPTION("Comedi PCI interface module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/comedi_pcmcia.c b/drivers/staging/comedi/comedi_pcmcia.c
index 9d49d5d01ad9..0529bae8e5ac 100644
--- a/drivers/staging/comedi/comedi_pcmcia.c
+++ b/drivers/staging/comedi/comedi_pcmcia.c
@@ -16,6 +16,7 @@
* GNU General Public License for more details.
*/
+#include <linux/module.h>
#include <linux/kernel.h>
#include <pcmcia/cistpl.h>
@@ -154,3 +155,18 @@ void comedi_pcmcia_driver_unregister(struct comedi_driver *comedi_driver,
comedi_driver_unregister(comedi_driver);
}
EXPORT_SYMBOL_GPL(comedi_pcmcia_driver_unregister);
+
+static int __init comedi_pcmcia_init(void)
+{
+ return 0;
+}
+module_init(comedi_pcmcia_init);
+
+static void __exit comedi_pcmcia_exit(void)
+{
+}
+module_exit(comedi_pcmcia_exit);
+
+MODULE_AUTHOR("http://www.comedi.org");
+MODULE_DESCRIPTION("Comedi PCMCIA interface module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/comedi_usb.c b/drivers/staging/comedi/comedi_usb.c
index 13f18bef6091..0b862a64c049 100644
--- a/drivers/staging/comedi/comedi_usb.c
+++ b/drivers/staging/comedi/comedi_usb.c
@@ -16,6 +16,7 @@
* GNU General Public License for more details.
*/
+#include <linux/module.h>
#include <linux/usb.h>
#include "comedidev.h"
@@ -114,3 +115,18 @@ void comedi_usb_driver_unregister(struct comedi_driver *comedi_driver,
comedi_driver_unregister(comedi_driver);
}
EXPORT_SYMBOL_GPL(comedi_usb_driver_unregister);
+
+static int __init comedi_usb_init(void)
+{
+ return 0;
+}
+module_init(comedi_usb_init);
+
+static void __exit comedi_usb_exit(void)
+{
+}
+module_exit(comedi_usb_exit);
+
+MODULE_AUTHOR("http://www.comedi.org");
+MODULE_DESCRIPTION("Comedi USB interface module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
index 1b2bbd56f6ef..77be191988ca 100644
--- a/drivers/staging/comedi/comedidev.h
+++ b/drivers/staging/comedi/comedidev.h
@@ -121,6 +121,7 @@ struct comedi_buf_map {
* @buf_read_ptr: buffer position for reader
* @cur_chan: current position in chanlist for scan (for those
* drivers that use it)
+ * @scans_done: the number of scans completed (COMEDI_CB_EOS)
* @scan_progress: amount received or sent for current scan (in bytes)
* @munge_chan: current position in chanlist for "munging"
* @munge_count: "munge" count (in bytes, modulo 2**32)
@@ -201,6 +202,7 @@ struct comedi_async {
unsigned int buf_write_ptr;
unsigned int buf_read_ptr;
unsigned int cur_chan;
+ unsigned int scans_done;
unsigned int scan_progress;
unsigned int munge_chan;
unsigned int munge_count;
@@ -213,6 +215,28 @@ struct comedi_async {
unsigned int x);
};
+/**
+ * comedi_async callback "events"
+ * @COMEDI_CB_EOS: end-of-scan
+ * @COMEDI_CB_EOA: end-of-acquisition/output
+ * @COMEDI_CB_BLOCK: data has arrived, wakes up read() / write()
+ * @COMEDI_CB_EOBUF: DEPRECATED: end of buffer
+ * @COMEDI_CB_ERROR: card error during acquisition
+ * @COMEDI_CB_OVERFLOW: buffer overflow/underflow
+ *
+ * @COMEDI_CB_ERROR_MASK: events that indicate an error has occurred
+ * @COMEDI_CB_CANCEL_MASK: events that will cancel an async command
+ */
+#define COMEDI_CB_EOS (1 << 0)
+#define COMEDI_CB_EOA (1 << 1)
+#define COMEDI_CB_BLOCK (1 << 2)
+#define COMEDI_CB_EOBUF (1 << 3)
+#define COMEDI_CB_ERROR (1 << 4)
+#define COMEDI_CB_OVERFLOW (1 << 5)
+
+#define COMEDI_CB_ERROR_MASK (COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW)
+#define COMEDI_CB_CANCEL_MASK (COMEDI_CB_EOA | COMEDI_CB_ERROR_MASK)
+
struct comedi_driver {
struct comedi_driver *next;
@@ -391,12 +415,61 @@ static inline unsigned int comedi_offset_munge(struct comedi_subdevice *s,
return val ^ s->maxdata ^ (s->maxdata >> 1);
}
-static inline unsigned int bytes_per_sample(const struct comedi_subdevice *subd)
+/**
+ * comedi_bytes_per_sample - determine subdevice sample size
+ * @s: comedi_subdevice struct
+ *
+ * The sample size will be 4 (sizeof int) or 2 (sizeof short) depending on
+ * whether the SDF_LSAMPL subdevice flag is set or not.
+ *
+ * Returns the subdevice sample size.
+ */
+static inline unsigned int comedi_bytes_per_sample(struct comedi_subdevice *s)
+{
+ return s->subdev_flags & SDF_LSAMPL ? sizeof(int) : sizeof(short);
+}
+
+/**
+ * comedi_sample_shift - determine log2 of subdevice sample size
+ * @s: comedi_subdevice struct
+ *
+ * The sample size will be 4 (sizeof int) or 2 (sizeof short) depending on
+ * whether the SDF_LSAMPL subdevice flag is set or not. The log2 of the
+ * sample size will be 2 or 1 and can be used as the right operand of a
+ * bit-shift operator to multiply or divide something by the sample size.
+ *
+ * Returns log2 of the subdevice sample size.
+ */
+static inline unsigned int comedi_sample_shift(struct comedi_subdevice *s)
{
- if (subd->subdev_flags & SDF_LSAMPL)
- return sizeof(unsigned int);
+ return s->subdev_flags & SDF_LSAMPL ? 2 : 1;
+}
- return sizeof(short);
+/**
+ * comedi_bytes_to_samples - converts a number of bytes to a number of samples
+ * @s: comedi_subdevice struct
+ * @nbytes: number of bytes
+ *
+ * Returns the number of bytes divided by the subdevice sample size.
+ */
+static inline unsigned int comedi_bytes_to_samples(struct comedi_subdevice *s,
+ unsigned int nbytes)
+{
+ return nbytes >> comedi_sample_shift(s);
+}
+
+/**
+ * comedi_samples_to_bytes - converts a number of samples to a number of bytes
+ * @s: comedi_subdevice struct
+ * @nsamples: number of samples
+ *
+ * Returns the number of samples multiplied by the subdevice sample size.
+ * Does not check for arithmetic overflow.
+ */
+static inline unsigned int comedi_samples_to_bytes(struct comedi_subdevice *s,
+ unsigned int nsamples)
+{
+ return nsamples << comedi_sample_shift(s);
}
/*
@@ -419,18 +492,10 @@ unsigned int comedi_buf_read_n_available(struct comedi_subdevice *s);
unsigned int comedi_buf_read_alloc(struct comedi_subdevice *s, unsigned int n);
unsigned int comedi_buf_read_free(struct comedi_subdevice *s, unsigned int n);
-int comedi_buf_put(struct comedi_subdevice *s, unsigned short x);
-int comedi_buf_get(struct comedi_subdevice *s, unsigned short *x);
-
-void comedi_buf_memcpy_to(struct comedi_subdevice *s, unsigned int offset,
- const void *source, unsigned int num_bytes);
-void comedi_buf_memcpy_from(struct comedi_subdevice *s, unsigned int offset,
- void *destination, unsigned int num_bytes);
-unsigned int comedi_write_array_to_buffer(struct comedi_subdevice *s,
- const void *data,
- unsigned int num_bytes);
-unsigned int comedi_read_array_from_buffer(struct comedi_subdevice *s,
- void *data, unsigned int num_bytes);
+unsigned int comedi_buf_write_samples(struct comedi_subdevice *s,
+ const void *data, unsigned int nsamples);
+unsigned int comedi_buf_read_samples(struct comedi_subdevice *s,
+ void *data, unsigned int nsamples);
/* drivers.c - general comedi driver functions */
@@ -451,6 +516,10 @@ int comedi_dio_insn_config(struct comedi_device *, struct comedi_subdevice *,
unsigned int comedi_dio_update_state(struct comedi_subdevice *,
unsigned int *data);
unsigned int comedi_bytes_per_scan(struct comedi_subdevice *s);
+unsigned int comedi_nscans_left(struct comedi_subdevice *s,
+ unsigned int nscans);
+unsigned int comedi_nsamples_left(struct comedi_subdevice *s,
+ unsigned int nsamples);
void comedi_inc_scan_progress(struct comedi_subdevice *s,
unsigned int num_bytes);
@@ -493,8 +562,6 @@ void comedi_driver_unregister(struct 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 */
/*
@@ -538,36 +605,6 @@ void comedi_pci_driver_unregister(struct comedi_driver *, struct pci_driver *);
module_driver(__comedi_driver, comedi_pci_driver_register, \
comedi_pci_driver_unregister, &(__pci_driver))
-#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)
-{
- return NULL;
-}
-
-static inline int comedi_pci_enable(struct comedi_device *dev)
-{
- return -ENOSYS;
-}
-
-static inline void comedi_pci_disable(struct comedi_device *dev)
-{
-}
-
-static inline void comedi_pci_detach(struct comedi_device *dev)
-{
-}
-
-#endif /* CONFIG_COMEDI_PCI_DRIVERS */
-
-#ifdef CONFIG_COMEDI_PCMCIA_DRIVERS
-
/* comedi_pcmcia.c - comedi PCMCIA driver specific functions */
struct pcmcia_driver;
@@ -601,10 +638,6 @@ void comedi_pcmcia_driver_unregister(struct comedi_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;
@@ -634,6 +667,4 @@ void comedi_usb_driver_unregister(struct comedi_driver *, struct 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 3e5bccbc9c39..61802d7947ae 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -109,6 +109,10 @@ int comedi_alloc_subdev_readback(struct comedi_subdevice *s)
s->readback = kcalloc(s->n_chan, sizeof(*s->readback), GFP_KERNEL);
if (!s->readback)
return -ENOMEM;
+
+ if (!s->insn_read)
+ s->insn_read = comedi_readback_insn_read;
+
return 0;
}
EXPORT_SYMBOL_GPL(comedi_alloc_subdev_readback);
@@ -316,19 +320,91 @@ unsigned int comedi_bytes_per_scan(struct comedi_subdevice *s)
case COMEDI_SUBD_DI:
case COMEDI_SUBD_DO:
case COMEDI_SUBD_DIO:
- bits_per_sample = 8 * bytes_per_sample(s);
- num_samples = (cmd->chanlist_len + bits_per_sample - 1) /
- bits_per_sample;
+ bits_per_sample = 8 * comedi_bytes_per_sample(s);
+ num_samples = DIV_ROUND_UP(cmd->scan_end_arg, bits_per_sample);
break;
default:
- num_samples = cmd->chanlist_len;
+ num_samples = cmd->scan_end_arg;
break;
}
- return num_samples * bytes_per_sample(s);
+ return comedi_samples_to_bytes(s, num_samples);
}
EXPORT_SYMBOL_GPL(comedi_bytes_per_scan);
/**
+ * comedi_nscans_left - return the number of scans left in the command
+ * @s: comedi_subdevice struct
+ * @nscans: the expected number of scans
+ *
+ * If nscans is 0, the number of scans available in the async buffer will be
+ * used. Otherwise the expected number of scans will be used.
+ *
+ * If the async command has a stop_src of TRIG_COUNT, the nscans will be
+ * checked against the number of scans left in the command.
+ *
+ * The return value will then be either the expected number of scans or the
+ * number of scans remaining in the command.
+ */
+unsigned int comedi_nscans_left(struct comedi_subdevice *s,
+ unsigned int nscans)
+{
+ struct comedi_async *async = s->async;
+ struct comedi_cmd *cmd = &async->cmd;
+
+ if (nscans == 0) {
+ unsigned int nbytes = comedi_buf_read_n_available(s);
+
+ nscans = nbytes / comedi_bytes_per_scan(s);
+ }
+
+ if (cmd->stop_src == TRIG_COUNT) {
+ unsigned int scans_left = 0;
+
+ if (async->scans_done < cmd->stop_arg)
+ scans_left = cmd->stop_arg - async->scans_done;
+
+ if (nscans > scans_left)
+ nscans = scans_left;
+ }
+ return nscans;
+}
+EXPORT_SYMBOL_GPL(comedi_nscans_left);
+
+/**
+ * comedi_nsamples_left - return the number of samples left in the command
+ * @s: comedi_subdevice struct
+ * @nsamples: the expected number of samples
+ *
+ * Returns the expected number of samples of the number of samples remaining
+ * in the command.
+ */
+unsigned int comedi_nsamples_left(struct comedi_subdevice *s,
+ unsigned int nsamples)
+{
+ struct comedi_async *async = s->async;
+ struct comedi_cmd *cmd = &async->cmd;
+
+ if (cmd->stop_src == TRIG_COUNT) {
+ /* +1 to force comedi_nscans_left() to return the scans left */
+ unsigned int nscans = (nsamples / cmd->scan_end_arg) + 1;
+ unsigned int scans_left = comedi_nscans_left(s, nscans);
+ unsigned int scan_pos =
+ comedi_bytes_to_samples(s, async->scan_progress);
+ unsigned long long samples_left = 0;
+
+ if (scans_left) {
+ samples_left = ((unsigned long long)scans_left *
+ cmd->scan_end_arg) - scan_pos;
+ }
+
+ if (samples_left < nsamples)
+ nsamples = samples_left;
+ }
+ return nsamples;
+}
+EXPORT_SYMBOL_GPL(comedi_nsamples_left);
+
+/**
* comedi_inc_scan_progress - update scan progress in asynchronous command
* @s: comedi_subdevice struct
* @num_bytes: amount of data in bytes to increment scan progress
@@ -342,10 +418,24 @@ void comedi_inc_scan_progress(struct comedi_subdevice *s,
unsigned int num_bytes)
{
struct comedi_async *async = s->async;
+ struct comedi_cmd *cmd = &async->cmd;
unsigned int scan_length = comedi_bytes_per_scan(s);
+ /* track the 'cur_chan' for non-SDF_PACKED subdevices */
+ if (!(s->subdev_flags & SDF_PACKED)) {
+ async->cur_chan += comedi_bytes_to_samples(s, num_bytes);
+ async->cur_chan %= cmd->chanlist_len;
+ }
+
async->scan_progress += num_bytes;
if (async->scan_progress >= scan_length) {
+ unsigned int nscans = async->scan_progress / scan_length;
+
+ if (async->scans_done < (UINT_MAX - nscans))
+ async->scans_done += nscans;
+ else
+ async->scans_done = UINT_MAX;
+
async->scan_progress %= scan_length;
async->events |= COMEDI_CB_EOS;
}
@@ -376,7 +466,7 @@ unsigned int comedi_handle_events(struct comedi_device *dev,
if (events == 0)
return events;
- if (events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW))
+ if (events & COMEDI_CB_CANCEL_MASK)
s->cancel(dev, s);
comedi_event(dev, s);
diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile
index 6bc9ef3b25b3..84fdf20ca986 100644
--- a/drivers/staging/comedi/drivers/Makefile
+++ b/drivers/staging/comedi/drivers/Makefile
@@ -60,7 +60,6 @@ obj-$(CONFIG_COMEDI_S526) += s526.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
obj-$(CONFIG_COMEDI_ADDI_APCI_1516) += addi_apci_1516.o
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
deleted file mode 100644
index 2e7fb218340f..000000000000
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
+++ /dev/null
@@ -1,274 +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.
-
-@endverbatim
-*/
-/*
-
- +-----------------------------------------------------------------------+
- | (C) ADDI-DATA GmbH Dieselstrasse 3 D-77833 Ottersweier |
- +-----------------------------------------------------------------------+
- | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
- | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
- +-----------------------------------------------------------------------+
- | Project : ADDI DATA | Compiler : GCC |
- | Modulname : addi_common.c | Version : 2.96 |
- +-------------------------------+---------------------------------------+
- | Author : | Date : |
- +-----------------------------------------------------------------------+
- | Description : ADDI COMMON Main Module |
- +-----------------------------------------------------------------------+
-*/
-
-static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- const struct addi_board *this_board = dev->board_ptr;
- struct addi_private *devpriv = dev->private;
- unsigned short w_Address = CR_CHAN(insn->chanspec);
- unsigned short w_Data;
-
- w_Data = addi_eeprom_readw(devpriv->i_IobaseAmcc,
- this_board->pc_EepromChip, 2 * w_Address);
- data[0] = w_Data;
-
- return insn->n;
-}
-
-static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
-{
- struct comedi_device *dev = d;
- const struct addi_board *this_board = dev->board_ptr;
-
- this_board->interrupt(irq, d);
- return IRQ_RETVAL(1);
-}
-
-static int i_ADDI_Reset(struct comedi_device *dev)
-{
- const struct addi_board *this_board = dev->board_ptr;
-
- this_board->reset(dev);
- return 0;
-}
-
-static int addi_auto_attach(struct comedi_device *dev,
- unsigned long context_unused)
-{
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- const struct addi_board *this_board = dev->board_ptr;
- struct addi_private *devpriv;
- struct comedi_subdevice *s;
- int ret, n_subdevices;
- unsigned int dw_Dummy;
-
- dev->board_name = this_board->pc_DriverName;
-
- devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
- if (!devpriv)
- return -ENOMEM;
-
- ret = comedi_pci_enable(dev);
- if (ret)
- return ret;
-
- if (this_board->i_IorangeBase1)
- dev->iobase = pci_resource_start(pcidev, 1);
- else
- dev->iobase = pci_resource_start(pcidev, 0);
-
- devpriv->iobase = dev->iobase;
- devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0);
- devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2);
- devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3);
-
- /* Initialize parameters that can be overridden in EEPROM */
- devpriv->s_EeParameters.i_NbrAiChannel = this_board->i_NbrAiChannel;
- devpriv->s_EeParameters.i_NbrAoChannel = this_board->i_NbrAoChannel;
- devpriv->s_EeParameters.i_AiMaxdata = this_board->i_AiMaxdata;
- devpriv->s_EeParameters.i_AoMaxdata = this_board->i_AoMaxdata;
- devpriv->s_EeParameters.i_NbrDiChannel = this_board->i_NbrDiChannel;
- devpriv->s_EeParameters.i_NbrDoChannel = this_board->i_NbrDoChannel;
- devpriv->s_EeParameters.i_DoMaxdata = this_board->i_DoMaxdata;
- devpriv->s_EeParameters.i_Timer = this_board->i_Timer;
- devpriv->s_EeParameters.ui_MinAcquisitiontimeNs =
- this_board->ui_MinAcquisitiontimeNs;
- devpriv->s_EeParameters.ui_MinDelaytimeNs =
- this_board->ui_MinDelaytimeNs;
-
- /* ## */
-
- if (pcidev->irq > 0) {
- ret = request_irq(pcidev->irq, v_ADDI_Interrupt, IRQF_SHARED,
- dev->board_name, dev);
- if (ret == 0)
- dev->irq = pcidev->irq;
- }
-
- /* Read eepeom and fill addi_board Structure */
-
- if (this_board->i_PCIEeprom) {
- if (!(strcmp(this_board->pc_EepromChip, "S5920"))) {
- /* Set 3 wait stait */
- if (!(strcmp(dev->board_name, "apci035")))
- outl(0x80808082, devpriv->i_IobaseAmcc + 0x60);
- 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);
- }
- addi_eeprom_read_info(dev, pci_resource_start(pcidev, 0));
- }
-
- n_subdevices = 7;
- ret = comedi_alloc_subdevices(dev, n_subdevices);
- if (ret)
- return ret;
-
- /* Allocate and Initialise AI Subdevice Structures */
- s = &dev->subdevices[0];
- if ((devpriv->s_EeParameters.i_NbrAiChannel)
- || (this_board->i_NbrAiChannelDiff)) {
- dev->read_subdev = s;
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags =
- SDF_READABLE | SDF_COMMON | SDF_GROUND
- | SDF_DIFF;
- if (devpriv->s_EeParameters.i_NbrAiChannel)
- s->n_chan = devpriv->s_EeParameters.i_NbrAiChannel;
- else
- s->n_chan = this_board->i_NbrAiChannelDiff;
- s->maxdata = devpriv->s_EeParameters.i_AiMaxdata;
- s->len_chanlist = this_board->i_AiChannelList;
- s->range_table = this_board->pr_AiRangelist;
-
- s->insn_config = this_board->ai_config;
- s->insn_read = this_board->ai_read;
- s->insn_write = this_board->ai_write;
- s->insn_bits = this_board->ai_bits;
- s->do_cmdtest = this_board->ai_cmdtest;
- s->do_cmd = this_board->ai_cmd;
- s->cancel = this_board->ai_cancel;
-
- } else {
- s->type = COMEDI_SUBD_UNUSED;
- }
-
- /* Allocate and Initialise AO Subdevice Structures */
- s = &dev->subdevices[1];
- if (devpriv->s_EeParameters.i_NbrAoChannel) {
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = devpriv->s_EeParameters.i_NbrAoChannel;
- s->maxdata = devpriv->s_EeParameters.i_AoMaxdata;
- s->len_chanlist =
- devpriv->s_EeParameters.i_NbrAoChannel;
- s->insn_write = this_board->ao_write;
- } else {
- s->type = COMEDI_SUBD_UNUSED;
- }
- /* Allocate and Initialise DI Subdevice Structures */
- s = &dev->subdevices[2];
- if (devpriv->s_EeParameters.i_NbrDiChannel) {
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = devpriv->s_EeParameters.i_NbrDiChannel;
- s->maxdata = 1;
- s->len_chanlist =
- devpriv->s_EeParameters.i_NbrDiChannel;
- s->range_table = &range_digital;
- s->insn_config = this_board->di_config;
- s->insn_read = this_board->di_read;
- s->insn_write = this_board->di_write;
- s->insn_bits = this_board->di_bits;
- } else {
- s->type = COMEDI_SUBD_UNUSED;
- }
- /* Allocate and Initialise DO Subdevice Structures */
- s = &dev->subdevices[3];
- if (devpriv->s_EeParameters.i_NbrDoChannel) {
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags =
- SDF_READABLE | SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = devpriv->s_EeParameters.i_NbrDoChannel;
- s->maxdata = devpriv->s_EeParameters.i_DoMaxdata;
- s->len_chanlist =
- devpriv->s_EeParameters.i_NbrDoChannel;
- s->range_table = &range_digital;
-
- /* insn_config - for digital output memory */
- s->insn_config = this_board->do_config;
- s->insn_write = this_board->do_write;
- s->insn_bits = this_board->do_bits;
- s->insn_read = this_board->do_read;
- } else {
- s->type = COMEDI_SUBD_UNUSED;
- }
-
- /* Allocate and Initialise Timer Subdevice Structures */
- s = &dev->subdevices[4];
- if (devpriv->s_EeParameters.i_Timer) {
- 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 = this_board->timer_write;
- s->insn_read = this_board->timer_read;
- s->insn_config = this_board->timer_config;
- s->insn_bits = this_board->timer_bits;
- } else {
- s->type = COMEDI_SUBD_UNUSED;
- }
-
- /* Allocate and Initialise TTL */
- s = &dev->subdevices[5];
- s->type = COMEDI_SUBD_UNUSED;
-
- /* EEPROM */
- s = &dev->subdevices[6];
- if (this_board->i_PCIEeprom) {
- s->type = COMEDI_SUBD_MEMORY;
- s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
- s->n_chan = 256;
- s->maxdata = 0xffff;
- s->insn_read = i_ADDIDATA_InsnReadEeprom;
- } else {
- s->type = COMEDI_SUBD_UNUSED;
- }
-
- i_ADDI_Reset(dev);
- return 0;
-}
-
-static void i_ADDI_Detach(struct comedi_device *dev)
-{
- if (dev->iobase)
- i_ADDI_Reset(dev);
- comedi_pci_detach(dev);
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
deleted file mode 100644
index e2a3ffeee5cf..000000000000
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
- *
- * ADDI-DATA GmbH
- * Dieselstrasse 3
- * D-77833 Ottersweier
- * Tel: +19(0)7223/9493-0
- * Fax: +49(0)7223/9493-92
- * http://www.addi-data.com
- * info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-
-struct addi_board {
- const char *pc_DriverName; /* driver name */
- int i_IorangeBase1;
- int i_PCIEeprom; /* eeprom present or not */
- char *pc_EepromChip; /* type of chip */
- int i_NbrAiChannel; /* num of A/D chans */
- int i_NbrAiChannelDiff; /* num of A/D chans in diff mode */
- int i_AiChannelList; /* len of chanlist */
- int i_NbrAoChannel; /* num of D/A chans */
- int i_AiMaxdata; /* resolution of A/D */
- int i_AoMaxdata; /* resolution of D/A */
- const struct comedi_lrange *pr_AiRangelist; /* rangelist for A/D */
-
- int i_NbrDiChannel; /* Number of DI channels */
- int i_NbrDoChannel; /* Number of DO channels */
- int i_DoMaxdata; /* data to set all channels high */
-
- int i_Timer; /* timer subdevice present or not */
- unsigned int ui_MinAcquisitiontimeNs; /* Minimum Acquisition in Nano secs */
- unsigned int ui_MinDelaytimeNs; /* Minimum Delay in Nano secs */
-
- /* interrupt and reset */
- void (*interrupt)(int irq, void *d);
- int (*reset)(struct comedi_device *);
-
- /* Subdevice functions */
-
- /* ANALOG INPUT */
- int (*ai_config)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
- int (*ai_read)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
- int (*ai_write)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
- int (*ai_bits)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
- int (*ai_cmdtest)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_cmd *);
- int (*ai_cmd)(struct comedi_device *, struct comedi_subdevice *);
- int (*ai_cancel)(struct comedi_device *, struct comedi_subdevice *);
-
- /* Analog Output */
- int (*ao_write)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
-
- /* Digital Input */
- int (*di_config)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
- int (*di_read)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
- int (*di_write)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
- int (*di_bits)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
-
- /* Digital Output */
- int (*do_config)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
- int (*do_write)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
- int (*do_bits)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
- int (*do_read)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
-
- /* TIMER */
- int (*timer_config)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
- int (*timer_write)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
- int (*timer_read)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
- int (*timer_bits)(struct comedi_device *, struct comedi_subdevice *,
- struct comedi_insn *, unsigned int *);
-};
-
-struct addi_private {
- int iobase;
- int i_IobaseAmcc; /* base+size for AMCC chip */
- int i_IobaseAddon; /* addon base address */
- int i_IobaseReserved;
- unsigned int ui_AiActualScan; /* how many scans we finished */
- unsigned int ui_AiNbrofChannels; /* how many channels is measured */
- unsigned int ui_AiChannelList[32]; /* actual chanlist */
- unsigned int ui_AiReadData[32];
- unsigned short us_UseDma; /* To use Dma or not */
- unsigned char b_DmaDoubleBuffer; /* we can use double buffering */
- unsigned int ui_DmaActualBuffer; /* which buffer is used now */
- unsigned short *ul_DmaBufferVirtual[2]; /* pointers to DMA buffer */
- dma_addr_t ul_DmaBufferHw[2]; /* hw address of DMA buff */
- unsigned int ui_DmaBufferSize[2]; /* size of dma buffer in bytes */
- unsigned int ui_DmaBufferUsesize[2]; /* which size we may now used for transfer */
- unsigned char b_DigitalOutputRegister; /* Digital Output Register */
- unsigned char b_OutputMemoryStatus;
- unsigned char b_TimerSelectMode; /* Contain data written at iobase + 0C */
- unsigned char b_ModeSelectRegister; /* Contain data written at iobase + 0E */
- unsigned short us_OutputRegister; /* Contain data written at iobase + 0 */
- unsigned char b_Timer2Mode; /* Specify the timer 2 mode */
- unsigned char b_Timer2Interrupt; /* Timer2 interrupt enable or disable */
- unsigned int ai_running:1;
- unsigned char b_InterruptMode; /* eoc eos or dma */
- unsigned char b_EocEosInterrupt; /* Enable disable eoc eos interrupt */
- unsigned int ui_EocEosConversionTime;
- unsigned char b_ExttrigEnable; /* To enable or disable external trigger */
-
- /* Pointer to the current process */
- struct task_struct *tsk_Current;
-
- /* Parameters read from EEPROM overriding static board info */
- struct {
- int i_NbrAiChannel; /* num of A/D chans */
- int i_NbrAoChannel; /* num of D/A chans */
- int i_AiMaxdata; /* resolution of A/D */
- int i_AoMaxdata; /* resolution of D/A */
- int i_NbrDiChannel; /* Number of DI channels */
- int i_NbrDoChannel; /* Number of DO channels */
- int i_DoMaxdata; /* data to set all channels high */
- int i_Timer; /* timer subdevice present or not */
- unsigned int ui_MinAcquisitiontimeNs;
- /* Minimum Acquisition in Nano secs */
- unsigned int ui_MinDelaytimeNs;
- /* Minimum Delay in Nano secs */
- } s_EeParameters;
-};
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
deleted file mode 100644
index b731856c27da..000000000000
--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * addi_eeprom.c - ADDI EEPROM Module
- * 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.
- */
-
-#include <linux/delay.h>
-
-#define NVRAM_USER_DATA_START 0x100
-
-#define NVCMD_BEGIN_READ (0x7 << 5) /* nvRam begin read command */
-#define NVCMD_LOAD_LOW (0x4 << 5) /* nvRam load low command */
-#define NVCMD_LOAD_HIGH (0x5 << 5) /* nvRam load high command */
-
-#define EE93C76_CLK_BIT (1 << 0)
-#define EE93C76_CS_BIT (1 << 1)
-#define EE93C76_DOUT_BIT (1 << 2)
-#define EE93C76_DIN_BIT (1 << 3)
-#define EE93C76_READ_CMD (0x0180 << 4)
-#define EE93C76_CMD_LEN 13
-
-#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
-
-static void addi_eeprom_clk_93c76(unsigned long iobase, unsigned int val)
-{
- outl(val & ~EE93C76_CLK_BIT, iobase);
- udelay(100);
-
- outl(val | EE93C76_CLK_BIT, iobase);
- udelay(100);
-}
-
-static unsigned int addi_eeprom_cmd_93c76(unsigned long iobase,
- unsigned int cmd,
- unsigned char len)
-{
- unsigned int val = EE93C76_CS_BIT;
- int i;
-
- /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */
- outl(val, iobase);
- udelay(100);
-
- /* Send EEPROM command - one bit at a time */
- for (i = (len - 1); i >= 0; i--) {
- if (cmd & (1 << i))
- val |= EE93C76_DOUT_BIT;
- else
- val &= ~EE93C76_DOUT_BIT;
-
- /* Write the command */
- outl(val, iobase);
- udelay(100);
-
- addi_eeprom_clk_93c76(iobase, val);
- }
- return val;
-}
-
-static unsigned short addi_eeprom_readw_93c76(unsigned long iobase,
- unsigned short addr)
-{
- unsigned short val = 0;
- unsigned int cmd;
- unsigned int tmp;
- int i;
-
- /* Send EEPROM read command and offset to EEPROM */
- cmd = EE93C76_READ_CMD | (addr / 2);
- cmd = addi_eeprom_cmd_93c76(iobase, cmd, EE93C76_CMD_LEN);
-
- /* Get the 16-bit value */
- for (i = 0; i < 16; i++) {
- addi_eeprom_clk_93c76(iobase, cmd);
-
- tmp = inl(iobase);
- udelay(100);
-
- val <<= 1;
- if (tmp & EE93C76_DIN_BIT)
- val |= 0x1;
- }
-
- /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */
- outl(0, iobase);
- udelay(100);
-
- return val;
-}
-
-static void addi_eeprom_nvram_wait(unsigned long iobase)
-{
- unsigned char val;
-
- do {
- val = inb(iobase + AMCC_OP_REG_MCSR_NVCMD);
- } while (val & 0x80);
-}
-
-static unsigned short addi_eeprom_readw_nvram(unsigned long iobase,
- unsigned short addr)
-{
- unsigned short val = 0;
- unsigned char tmp;
- unsigned char i;
-
- for (i = 0; i < 2; i++) {
- /* Load the low 8 bit address */
- outb(NVCMD_LOAD_LOW, iobase + AMCC_OP_REG_MCSR_NVCMD);
- addi_eeprom_nvram_wait(iobase);
- outb((addr + i) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
- addi_eeprom_nvram_wait(iobase);
-
- /* Load the high 8 bit address */
- outb(NVCMD_LOAD_HIGH, iobase + AMCC_OP_REG_MCSR_NVCMD);
- addi_eeprom_nvram_wait(iobase);
- outb(((addr + i) >> 8) & 0xff,
- iobase + AMCC_OP_REG_MCSR_NVDATA);
- addi_eeprom_nvram_wait(iobase);
-
- /* Read the eeprom data byte */
- outb(NVCMD_BEGIN_READ, iobase + AMCC_OP_REG_MCSR_NVCMD);
- addi_eeprom_nvram_wait(iobase);
- tmp = inb(iobase + AMCC_OP_REG_MCSR_NVDATA);
- addi_eeprom_nvram_wait(iobase);
-
- if (i == 0)
- val |= tmp;
- else
- val |= (tmp << 8);
- }
-
- return val;
-}
-
-static unsigned short addi_eeprom_readw(unsigned long iobase,
- char *type,
- unsigned short addr)
-{
- unsigned short val = 0;
-
- /* Add the offset to the start of the user data */
- addr += NVRAM_USER_DATA_START;
-
- if (!strcmp(type, "S5920") || !strcmp(type, "S5933"))
- val = addi_eeprom_readw_nvram(iobase, addr);
-
- if (!strcmp(type, "93C76"))
- val = addi_eeprom_readw_93c76(iobase, addr);
-
- return val;
-}
-
-static void addi_eeprom_read_di_info(struct comedi_device *dev,
- unsigned long iobase,
- unsigned short addr)
-{
- const struct addi_board *this_board = dev->board_ptr;
- struct addi_private *devpriv = dev->private;
- char *type = this_board->pc_EepromChip;
- unsigned short tmp;
-
- /* Number of channels */
- tmp = addi_eeprom_readw(iobase, type, addr + 6);
- devpriv->s_EeParameters.i_NbrDiChannel = tmp;
-
- /* Interruptible or not */
- tmp = addi_eeprom_readw(iobase, type, addr + 8);
- tmp = (tmp >> 7) & 0x01;
-
- /* How many interruptible logic */
- tmp = addi_eeprom_readw(iobase, type, addr + 10);
-}
-
-static void addi_eeprom_read_do_info(struct comedi_device *dev,
- unsigned long iobase,
- unsigned short addr)
-{
- const struct addi_board *this_board = dev->board_ptr;
- struct addi_private *devpriv = dev->private;
- char *type = this_board->pc_EepromChip;
- unsigned short tmp;
-
- /* Number of channels */
- tmp = addi_eeprom_readw(iobase, type, addr + 6);
- devpriv->s_EeParameters.i_NbrDoChannel = tmp;
-
- devpriv->s_EeParameters.i_DoMaxdata = 0xffffffff >> (32 - tmp);
-}
-
-static void addi_eeprom_read_timer_info(struct comedi_device *dev,
- unsigned long iobase,
- unsigned short addr)
-{
- struct addi_private *devpriv = dev->private;
-#if 0
- const struct addi_board *this_board = dev->board_ptr;
- char *type = this_board->pc_EepromChip;
- unsigned short offset = 0;
- unsigned short ntimers;
- unsigned short tmp;
- int i;
-
- /* Number of Timers */
- ntimers = addi_eeprom_readw(iobase, type, addr + 6);
-
- /* Read header size */
- for (i = 0; i < ntimers; i++) {
- unsigned short size;
- unsigned short res;
- unsigned short mode;
- unsigned short min_timing;
- unsigned short timebase;
-
- size = addi_eeprom_readw(iobase, type, addr + 8 + offset + 0);
-
- /* Resolution / Mode */
- tmp = addi_eeprom_readw(iobase, type, addr + 8 + offset + 2);
- res = (tmp >> 10) & 0x3f;
- mode = (tmp >> 4) & 0x3f;
-
- /* MinTiming / Timebase */
- tmp = addi_eeprom_readw(iobase, type, addr + 8 + offset + 4);
- min_timing = (tmp >> 6) & 0x3ff;
- Timebase = tmp & 0x3f;
-
- offset += size;
- }
-#endif
- /* Timer subdevice present */
- devpriv->s_EeParameters.i_Timer = 1;
-}
-
-static void addi_eeprom_read_ao_info(struct comedi_device *dev,
- unsigned long iobase,
- unsigned short addr)
-{
- const struct addi_board *this_board = dev->board_ptr;
- struct addi_private *devpriv = dev->private;
- char *type = this_board->pc_EepromChip;
- unsigned short tmp;
-
- /* No of channels for 1st hard component */
- tmp = addi_eeprom_readw(iobase, type, addr + 10);
- devpriv->s_EeParameters.i_NbrAoChannel = (tmp >> 4) & 0x3ff;
-
- /* Resolution for 1st hard component */
- tmp = addi_eeprom_readw(iobase, type, addr + 16);
- tmp = (tmp >> 8) & 0xff;
- devpriv->s_EeParameters.i_AoMaxdata = 0xfff >> (16 - tmp);
-}
-
-static void addi_eeprom_read_ai_info(struct comedi_device *dev,
- unsigned long iobase,
- unsigned short addr)
-{
- const struct addi_board *this_board = dev->board_ptr;
- struct addi_private *devpriv = dev->private;
- char *type = this_board->pc_EepromChip;
- unsigned short offset;
- unsigned short tmp;
-
- /* No of channels for 1st hard component */
- tmp = addi_eeprom_readw(iobase, type, addr + 10);
- devpriv->s_EeParameters.i_NbrAiChannel = (tmp >> 4) & 0x3ff;
- if (!strcmp(this_board->pc_DriverName, "apci3200"))
- devpriv->s_EeParameters.i_NbrAiChannel *= 4;
-
- tmp = addi_eeprom_readw(iobase, type, addr + 16);
- devpriv->s_EeParameters.ui_MinAcquisitiontimeNs = tmp * 1000;
-
- tmp = addi_eeprom_readw(iobase, type, addr + 30);
- devpriv->s_EeParameters.ui_MinDelaytimeNs = tmp * 1000;
-
- tmp = addi_eeprom_readw(iobase, type, addr + 20);
- /* dma = (tmp >> 13) & 0x01; */
-
- tmp = addi_eeprom_readw(iobase, type, addr + 72) & 0xff;
- if (tmp) { /* > 0 */
- /* offset of first analog input single header */
- offset = 74 + (2 * tmp) + (10 * (1 + (tmp / 16)));
- } else { /* = 0 */
- offset = 74;
- }
-
- /* Resolution */
- tmp = addi_eeprom_readw(iobase, type, addr + offset + 2) & 0x1f;
- devpriv->s_EeParameters.i_AiMaxdata = 0xffff >> (16 - tmp);
-}
-
-static void addi_eeprom_read_info(struct comedi_device *dev,
- unsigned long iobase)
-{
- const struct addi_board *this_board = dev->board_ptr;
- char *type = this_board->pc_EepromChip;
- unsigned short size;
- unsigned char nfuncs;
- int i;
-
- size = addi_eeprom_readw(iobase, type, 8);
- nfuncs = addi_eeprom_readw(iobase, type, 10) & 0xff;
-
- /* Read functionality details */
- for (i = 0; i < nfuncs; i++) {
- unsigned short offset = i * 4;
- unsigned short addr;
- unsigned char func;
-
- func = addi_eeprom_readw(iobase, type, 12 + offset) & 0x3f;
- addr = addi_eeprom_readw(iobase, type, 14 + offset);
-
- switch (func) {
- case EEPROM_DIGITALINPUT:
- addi_eeprom_read_di_info(dev, iobase, addr);
- break;
-
- case EEPROM_DIGITALOUTPUT:
- addi_eeprom_read_do_info(dev, iobase, addr);
- break;
-
- case EEPROM_ANALOGINPUT:
- addi_eeprom_read_ai_info(dev, iobase, addr);
- break;
-
- case EEPROM_ANALOGOUTPUT:
- addi_eeprom_read_ao_info(dev, iobase, addr);
- break;
-
- case EEPROM_TIMER:
- case EEPROM_WATCHDOG:
- case EEPROM_TIMER_WATCHDOG_COUNTER:
- addi_eeprom_read_timer_info(dev, iobase, addr);
- break;
- }
- }
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
deleted file mode 100644
index 53bb51bd77b5..000000000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
- *
- * ADDI-DATA GmbH
- * Dieselstrasse 3
- * D-77833 Ottersweier
- * Tel: +19(0)7223/9493-0
- * Fax: +49(0)7223/9493-92
- * http://www.addi-data.com
- * info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option) any later
- * version.
- *
- * 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.
- */
-
-/* Card Specific information */
-#define APCI035_ADDRESS_RANGE 255
-
-/* Timer / Watchdog Related Defines */
-#define APCI035_TCW_SYNC_ENABLEDISABLE 0
-#define APCI035_TCW_RELOAD_VALUE 4
-#define APCI035_TCW_TIMEBASE 8
-#define APCI035_TCW_PROG 12
-#define APCI035_TCW_TRIG_STATUS 16
-#define APCI035_TCW_IRQ 20
-#define APCI035_TCW_WARN_TIMEVAL 24
-#define APCI035_TCW_WARN_TIMEBASE 28
-
-#define ADDIDATA_TIMER 0
-/* #define ADDIDATA_WATCHDOG 1 */
-
-#define APCI035_TW1 0
-#define APCI035_TW2 32
-#define APCI035_TW3 64
-#define APCI035_TW4 96
-
-#define APCI035_AI_OFFSET 0
-#define APCI035_TEMP 128
-#define APCI035_ALR_SEQ 4
-#define APCI035_START_STOP_INDEX 8
-#define APCI035_ALR_START_STOP 12
-#define APCI035_ALR_IRQ 16
-#define APCI035_EOS 20
-#define APCI035_CHAN_NO 24
-#define APCI035_CHAN_VAL 28
-#define APCI035_CONV_TIME_TIME_BASE 36
-#define APCI035_RELOAD_CONV_TIME_VAL 32
-#define APCI035_DELAY_TIME_TIME_BASE 44
-#define APCI035_RELOAD_DELAY_TIME_VAL 40
-#define ENABLE_EXT_TRIG 1
-#define ENABLE_EXT_GATE 2
-#define ENABLE_EXT_TRIG_GATE 3
-
-#define ANALOG_INPUT 0
-#define TEMPERATURE 1
-#define RESISTANCE 2
-
-#define ADDIDATA_GREATER_THAN_TEST 0
-#define ADDIDATA_LESS_THAN_TEST 1
-
-#define APCI035_MAXVOLT 2.5
-
-#define ADDIDATA_UNIPOLAR 1
-#define ADDIDATA_BIPOLAR 2
-
-/* ANALOG INPUT RANGE */
-static struct comedi_lrange range_apci035_ai = {
- 8, {
- BIP_RANGE(10),
- BIP_RANGE(5),
- BIP_RANGE(2),
- BIP_RANGE(1),
- UNI_RANGE(10),
- UNI_RANGE(5),
- UNI_RANGE(2),
- UNI_RANGE(1)
- }
-};
-
-static int i_WatchdogNbr;
-static int i_Temp;
-static int i_Flag = 1;
-
-/*
- * Configures The Timer , Counter or Watchdog
- *
- * data[0] 0 = Configure As Timer, 1 = Configure As Watchdog
- * data[1] Watchdog number
- * data[2] Time base Unit
- * data[3] Reload Value
- * data[4] External Trigger, 1 = Enable, 0 = Disable
- * data[5] External Trigger Level
- * 00 = Trigger Disabled
- * 01 = Trigger Enabled (Low level)
- * 10 = Trigger Enabled (High Level)
- * 11 = Trigger Enabled (High/Low level)
- * data[6] External Gate, 1 = Enable, 0 = Disable
- * data[7] External Gate level
- * 00 = Gate Disabled
- * 01 = Gate Enabled (Low level)
- * 10 = Gate Enabled (High Level)
- * data[8] Warning Relay, 1 = Enable, 0 = Disable
- * data[9] Warning Delay available
- * data[10] Warning Relay Time unit
- * data[11] Warning Relay Time Reload value
- * data[12] Reset Relay, 1 = Enable, 0 = Disable
- * data[13] Interrupt, 1 = Enable, 0 = Disable
- */
-static int apci035_timer_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int ui_Status;
- unsigned int ui_Command;
- unsigned int ui_Mode;
-
- i_Temp = 0;
- devpriv->tsk_Current = current;
- devpriv->b_TimerSelectMode = data[0];
- i_WatchdogNbr = data[1];
- if (data[0] == 0)
- ui_Mode = 2;
- else
- ui_Mode = 0;
-
- ui_Command = 0;
- outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-
- ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-
- /* Set the reload value */
- outl(data[3], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 4);
-
- /* Set the time unit */
- outl(data[2], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 8);
- if (data[0] == ADDIDATA_TIMER) {
-
- /* Set the mode : */
- /* - Disable the hardware */
- /* - Disable the counter mode */
- /* - Disable the warning */
- /* - Disable the reset */
- /* - Enable the timer mode */
- /* - Set the timer mode */
-
- ui_Command =
- (ui_Command & 0xFFF719E2UL) | ui_Mode << 13UL | 0x10UL;
-
- } else if (data[0] == ADDIDATA_WATCHDOG) {
-
- /* Set the mode : */
- /* - Disable the hardware */
- /* - Disable the counter mode */
- /* - Disable the warning */
- /* - Disable the reset */
- /* - Disable the timer mode */
-
- ui_Command = ui_Command & 0xFFF819E2UL;
-
- } else {
- dev_err(dev->class_dev, "The parameter for Timer/watchdog selection is in error\n");
- return -EINVAL;
- }
-
- outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-
- ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-
- /* Disable the hardware trigger */
- ui_Command = ui_Command & 0xFFFFF89FUL;
- if (data[4] == 1) {
- /* Set the hardware trigger level */
- ui_Command = ui_Command | (data[5] << 5);
- }
- outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-
- ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-
- /* Disable the hardware gate */
- ui_Command = ui_Command & 0xFFFFF87FUL;
- if (data[6] == 1) {
- /* Set the hardware gate level */
- ui_Command = ui_Command | (data[7] << 7);
- }
- outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-
- ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-
- /* Disable the hardware output */
- ui_Command = ui_Command & 0xFFFFF9FBUL;
-
- /* Set the hardware output level */
- ui_Command = ui_Command | (data[8] << 2);
- outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
- if (data[9] == 1) {
- /* Set the reload value */
- outl(data[11],
- devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 24);
-
- /* Set the time unite */
- outl(data[10],
- devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 28);
- }
-
- ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-
- /* Disable the hardware output */
- ui_Command = ui_Command & 0xFFFFF9F7UL;
-
- /* Set the hardware output level */
- ui_Command = ui_Command | (data[12] << 3);
- outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-
- /* Enable the watchdog interrupt */
- ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-
- /* Set the interrupt selection */
- ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16);
-
- ui_Command = (ui_Command & 0xFFFFF9FDUL) | (data[13] << 1);
- outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-
- return insn->n;
-}
-
-/*
- * Start / Stop The Selected Timer , or Watchdog
- *
- * data[0]
- * 0 - Stop Selected Timer/Watchdog
- * 1 - Start Selected Timer/Watch*dog
- * 2 - Trigger Selected Timer/Watchdog
- * 3 - Stop All Timer/Watchdog
- * 4 - Start All Timer/Watchdog
- * 5 - Trigger All Timer/Watchdog
- */
-static int apci035_timer_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int ui_Command;
- int i_Count;
-
- if (data[0] == 1) {
- ui_Command =
- inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-
- /* Start the hardware */
- ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x1UL;
- outl(ui_Command,
- devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
- }
- if (data[0] == 2) {
- ui_Command =
- inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
-
- /* Set the trigger command */
- ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x200UL;
- outl(ui_Command,
- devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
- }
-
- if (data[0] == 0) {
- /* Stop The Watchdog */
- ui_Command = 0;
- /*
- * ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12);
- * ui_Command = ui_Command & 0xFFFFF9FEUL;
- */
- outl(ui_Command,
- devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
- }
- if (data[0] == 3) {
- /* stop all Watchdogs */
- ui_Command = 0;
- for (i_Count = 1; i_Count <= 4; i_Count++) {
- if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG)
- ui_Command = 0x2UL;
- else
- ui_Command = 0x10UL;
-
- i_WatchdogNbr = i_Count;
- outl(ui_Command,
- devpriv->iobase + ((i_WatchdogNbr - 1) * 32) +
- 0);
- }
-
- }
- if (data[0] == 4) {
- /* start all Watchdogs */
- ui_Command = 0;
- for (i_Count = 1; i_Count <= 4; i_Count++) {
- if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG)
- ui_Command = 0x1UL;
- else
- ui_Command = 0x8UL;
-
- i_WatchdogNbr = i_Count;
- outl(ui_Command,
- devpriv->iobase + ((i_WatchdogNbr - 1) * 32) +
- 0);
- }
- }
- if (data[0] == 5) {
- /* trigger all Watchdogs */
- ui_Command = 0;
- for (i_Count = 1; i_Count <= 4; i_Count++) {
- if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG)
- ui_Command = 0x4UL;
- else
- ui_Command = 0x20UL;
-
- i_WatchdogNbr = i_Count;
- outl(ui_Command,
- devpriv->iobase + ((i_WatchdogNbr - 1) * 32) +
- 0);
- }
- i_Temp = 1;
- }
- return insn->n;
-}
-
-/*
- * Read The Selected Timer , Counter or Watchdog
- *
- * data[0] software trigger status
- * data[1] hardware trigger status
- * data[2] Software clear status
- * data[3] Overflow status
- * data[4] Timer actual value
- */
-static int apci035_timer_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int ui_Status; /* Status register */
-
- i_WatchdogNbr = insn->unused[0];
-
- /* Get the status */
- ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16);
-
- /* Get the software trigger status */
- data[0] = ((ui_Status >> 1) & 1);
-
- /* Get the hardware trigger status */
- data[1] = ((ui_Status >> 2) & 1);
-
- /* Get the software clear status */
- data[2] = ((ui_Status >> 3) & 1);
-
- /* Get the overflow status */
- data[3] = ((ui_Status >> 0) & 1);
- if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER)
- data[4] = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);
-
- return insn->n;
-}
-
-/*
- * Configures The Analog Input Subdevice
- *
- * data[0] Warning delay value
- */
-static int apci035_ai_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
-
- devpriv->tsk_Current = current;
- outl(0x200 | 0, devpriv->iobase + 128 + 0x4);
- outl(0, devpriv->iobase + 128 + 0);
-
- /* Initialise the warning value */
- outl(0x300 | 0, devpriv->iobase + 128 + 0x4);
- outl((data[0] << 8), devpriv->iobase + 128 + 0);
- outl(0x200000UL, devpriv->iobase + 128 + 12);
-
- return insn->n;
-}
-
-/*
- * Read value of the selected channel
- *
- * data[0] Digital Value Of Input
- */
-static int apci035_ai_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int ui_CommandRegister;
-
- /* Set the start */
- ui_CommandRegister = 0x80000;
-
- /* Write the command register */
- outl(ui_CommandRegister, devpriv->iobase + 128 + 8);
-
- /* Read the digital value of the input */
- data[0] = inl(devpriv->iobase + 128 + 28);
- return insn->n;
-}
-
-static int apci035_reset(struct comedi_device *dev)
-{
- struct addi_private *devpriv = dev->private;
- int i_Count;
-
- for (i_Count = 1; i_Count <= 4; i_Count++) {
- i_WatchdogNbr = i_Count;
-
- /* stop all timers */
- outl(0x0, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);
- }
- outl(0x0, devpriv->iobase + 128 + 12); /* Disable the warning delay */
-
- return 0;
-}
-
-static void apci035_interrupt(int irq, void *d)
-{
- struct comedi_device *dev = d;
- struct addi_private *devpriv = dev->private;
- unsigned int ui_StatusRegister1;
- unsigned int ui_StatusRegister2;
- unsigned int ui_ReadCommand;
- unsigned int ui_ChannelNumber;
- unsigned int ui_DigitalTemperature;
-
- if (i_Temp == 1) {
- i_WatchdogNbr = i_Flag;
- i_Flag = i_Flag + 1;
- }
-
- /* Read the interrupt status register of temperature Warning */
- ui_StatusRegister1 = inl(devpriv->iobase + 128 + 16);
-
- /* Read the interrupt status register for Watchdog/timer */
- ui_StatusRegister2 =
- inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 20);
-
- /* Test if warning relay interrupt */
- if ((((ui_StatusRegister1) & 0x8) == 0x8)) {
-
- /* Disable the temperature warning */
- ui_ReadCommand = inl(devpriv->iobase + 128 + 12);
- ui_ReadCommand = ui_ReadCommand & 0xFFDF0000UL;
- outl(ui_ReadCommand, devpriv->iobase + 128 + 12);
-
- /* Read the channel number */
- ui_ChannelNumber = inl(devpriv->iobase + 128 + 60);
-
- /* Read the digital temperature value */
- ui_DigitalTemperature = inl(devpriv->iobase + 128 + 60);
-
- /* send signal to the sample */
- send_sig(SIGIO, devpriv->tsk_Current, 0);
-
- } else if ((ui_StatusRegister2 & 0x1) == 0x1) {
- /* send signal to the sample */
- send_sig(SIGIO, devpriv->tsk_Current, 0);
- }
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
index 0ea081e1e119..bfa9228c833f 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
@@ -158,7 +158,7 @@ static int apci1500_di_config(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- struct addi_private *devpriv = dev->private;
+ struct apci1500_private *devpriv = dev->private;
int i_PatternPolarity = 0, i_PatternTransition = 0, i_PatternMask = 0;
int i_MaxChannel = 0, i_Count = 0, i_EventMask = 0;
int i_PatternTransitionCount = 0, i_RegValue;
@@ -466,7 +466,7 @@ static int apci1500_di_write(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- struct addi_private *devpriv = dev->private;
+ struct apci1500_private *devpriv = dev->private;
int i_Event1InterruptStatus = 0, i_Event2InterruptStatus =
0, i_RegValue;
@@ -653,7 +653,7 @@ static int apci1500_di_read(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- struct addi_private *devpriv = dev->private;
+ struct apci1500_private *devpriv = dev->private;
int i_DummyRead = 0;
/* Software reset */
@@ -789,7 +789,7 @@ static int apci1500_di_insn_bits(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- struct addi_private *devpriv = dev->private;
+ struct apci1500_private *devpriv = dev->private;
data[1] = inw(devpriv->i_IobaseAddon + APCI1500_DIGITAL_IP);
@@ -807,7 +807,7 @@ static int apci1500_do_config(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- struct addi_private *devpriv = dev->private;
+ struct apci1500_private *devpriv = dev->private;
devpriv->b_OutputMemoryStatus = data[0];
return insn->n;
@@ -821,7 +821,7 @@ static int apci1500_do_write(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- struct addi_private *devpriv = dev->private;
+ struct apci1500_private *devpriv = dev->private;
static unsigned int ui_Temp;
unsigned int ui_Temp1;
unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec); /* get the channel */
@@ -981,7 +981,7 @@ static int apci1500_timer_config(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- struct addi_private *devpriv = dev->private;
+ struct apci1500_private *devpriv = dev->private;
int i_TimerCounterMode, i_MasterConfiguration;
devpriv->tsk_Current = current;
@@ -1471,7 +1471,7 @@ static int apci1500_timer_write(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- struct addi_private *devpriv = dev->private;
+ struct apci1500_private *devpriv = dev->private;
int i_CommandAndStatusValue;
switch (data[0]) {
@@ -1731,7 +1731,7 @@ static int apci1500_timer_bits(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- struct addi_private *devpriv = dev->private;
+ struct apci1500_private *devpriv = dev->private;
int i_CommandAndStatusValue;
switch (data[0]) {
@@ -1895,7 +1895,7 @@ static int apci1500_do_bits(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- struct addi_private *devpriv = dev->private;
+ struct apci1500_private *devpriv = dev->private;
unsigned int ui_Status;
int i_RegValue;
int i_Constant;
@@ -2011,11 +2011,11 @@ static int apci1500_do_bits(struct comedi_device *dev,
return insn->n;
}
-static void apci1500_interrupt(int irq, void *d)
+static irqreturn_t apci1500_interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
- struct addi_private *devpriv = dev->private;
+ struct apci1500_private *devpriv = dev->private;
unsigned int ui_InterruptStatus = 0;
int i_RegValue = 0;
@@ -2180,11 +2180,13 @@ static void apci1500_interrupt(int irq, void *d)
"Interrupt from unknown source\n");
}
+
+ return IRQ_HANDLED;
}
static int apci1500_reset(struct comedi_device *dev)
{
- struct addi_private *devpriv = dev->private;
+ struct apci1500_private *devpriv = dev->private;
int i_DummyRead = 0;
i_TimerCounter1Init = 0;
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
index 98de96953a29..fa99c8ca4f95 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
@@ -16,244 +16,189 @@
#define ADDIDATA_TIMER 0
#define ADDIDATA_COUNTER 1
#define ADDIDATA_WATCHDOG 2
-#define APCI1564_COUNTER1 0
-#define APCI1564_COUNTER2 1
-#define APCI1564_COUNTER3 2
-#define APCI1564_COUNTER4 3
-
-/*
- * devpriv->amcc_iobase Register Map
- */
-#define APCI1564_DI_REG 0x04
-#define APCI1564_DI_INT_MODE1_REG 0x08
-#define APCI1564_DI_INT_MODE2_REG 0x0c
-#define APCI1564_DI_INT_STATUS_REG 0x10
-#define APCI1564_DI_IRQ_REG 0x14
-#define APCI1564_DO_REG 0x18
-#define APCI1564_DO_INT_CTRL_REG 0x1c
-#define APCI1564_DO_INT_STATUS_REG 0x20
-#define APCI1564_DO_IRQ_REG 0x24
-#define APCI1564_WDOG_REG 0x28
-#define APCI1564_WDOG_RELOAD_REG 0x2c
-#define APCI1564_WDOG_TIMEBASE_REG 0x30
-#define APCI1564_WDOG_CTRL_REG 0x34
-#define APCI1564_WDOG_STATUS_REG 0x38
-#define APCI1564_WDOG_IRQ_REG 0x3c
-#define APCI1564_WDOG_WARN_TIMEVAL_REG 0x40
-#define APCI1564_WDOG_WARN_TIMEBASE_REG 0x44
-#define APCI1564_TIMER_REG 0x48
-#define APCI1564_TIMER_RELOAD_REG 0x4c
-#define APCI1564_TIMER_TIMEBASE_REG 0x50
-#define APCI1564_TIMER_CTRL_REG 0x54
-#define APCI1564_TIMER_STATUS_REG 0x58
-#define APCI1564_TIMER_IRQ_REG 0x5c
-#define APCI1564_TIMER_WARN_TIMEVAL_REG 0x60
-#define APCI1564_TIMER_WARN_TIMEBASE_REG 0x64
-
-/*
- * dev->iobase Register Map
- */
-#define APCI1564_COUNTER_REG(x) (0x00 + ((x) * 0x20))
-#define APCI1564_COUNTER_RELOAD_REG(x) (0x04 + ((x) * 0x20))
-#define APCI1564_COUNTER_TIMEBASE_REG(x) (0x08 + ((x) * 0x20))
-#define APCI1564_COUNTER_CTRL_REG(x) (0x0c + ((x) * 0x20))
-#define APCI1564_COUNTER_STATUS_REG(x) (0x10 + ((x) * 0x20))
-#define APCI1564_COUNTER_IRQ_REG(x) (0x14 + ((x) * 0x20))
-#define APCI1564_COUNTER_WARN_TIMEVAL_REG(x) (0x18 + ((x) * 0x20))
-#define APCI1564_COUNTER_WARN_TIMEBASE_REG(x) (0x1c + ((x) * 0x20))
-
-/*
- * Configures The Timer or Counter
- *
- * data[0] Configure as: 0 = Timer, 1 = Counter
- * data[1] 1 = Enable Interrupt, 0 = Disable Interrupt
- * data[2] Time Unit
- * data[3] Reload Value
- * data[4] Timer Mode
- * data[5] Timer Counter Watchdog Number
- * data[6] Counter Direction
- */
-static int apci1564_timer_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
+
+static int apci1564_timer_insn_config(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct apci1564_private *devpriv = dev->private;
- unsigned int ul_Command1 = 0;
+ unsigned int ctrl;
devpriv->tsk_current = current;
- if (data[0] == ADDIDATA_TIMER) {
- /* First Stop The Timer */
- ul_Command1 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
- /* Stop The Timer */
- outl(ul_Command1, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
-
- devpriv->timer_select_mode = ADDIDATA_TIMER;
- if (data[1] == 1) {
- /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
- outl(0x02, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
- outl(0x0, devpriv->amcc_iobase + APCI1564_DO_IRQ_REG);
- outl(0x0, devpriv->amcc_iobase + APCI1564_WDOG_IRQ_REG);
- outl(0x0, dev->iobase +
- APCI1564_COUNTER_IRQ_REG(APCI1564_COUNTER1));
- outl(0x0, dev->iobase +
- APCI1564_COUNTER_IRQ_REG(APCI1564_COUNTER2));
- outl(0x0, dev->iobase +
- APCI1564_COUNTER_IRQ_REG(APCI1564_COUNTER3));
- outl(0x0, dev->iobase +
- APCI1564_COUNTER_IRQ_REG(APCI1564_COUNTER4));
- } else {
- /* disable Timer interrupt */
- outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- }
- /* Loading Timebase */
- outl(data[2], devpriv->amcc_iobase + APCI1564_TIMER_TIMEBASE_REG);
-
- /* Loading the Reload value */
- outl(data[3], devpriv->amcc_iobase + APCI1564_TIMER_RELOAD_REG);
-
- ul_Command1 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- ul_Command1 = (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
- /* mode 2 */
- outl(ul_Command1, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- } else if (data[0] == ADDIDATA_COUNTER) {
- devpriv->timer_select_mode = ADDIDATA_COUNTER;
- devpriv->mode_select_register = data[5];
-
- /* First Stop The Counter */
- ul_Command1 = inl(dev->iobase +
- APCI1564_COUNTER_CTRL_REG(data[5] - 1));
- ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
- /* Stop The Timer */
- outl(ul_Command1, dev->iobase +
- APCI1564_COUNTER_CTRL_REG(data[5] - 1));
-
- /* Set the reload value */
- outl(data[3], dev->iobase +
- APCI1564_COUNTER_RELOAD_REG(data[5] - 1));
-
- /* Set the mode : */
- /* - Disable the hardware */
- /* - Disable the counter mode */
- /* - Disable the warning */
- /* - Disable the reset */
- /* - Disable the timer mode */
- /* - Enable the counter mode */
-
- ul_Command1 =
- (ul_Command1 & 0xFFFC19E2UL) | 0x80000UL |
- (unsigned int) ((unsigned int) data[4] << 16UL);
- outl(ul_Command1, dev->iobase +
- APCI1564_COUNTER_CTRL_REG(data[5] - 1));
-
- /* Enable or Disable Interrupt */
- ul_Command1 = (ul_Command1 & 0xFFFFF9FD) | (data[1] << 1);
- outl(ul_Command1, dev->iobase +
- APCI1564_COUNTER_CTRL_REG(data[5] - 1));
-
- /* Set the Up/Down selection */
- ul_Command1 = (ul_Command1 & 0xFFFBF9FFUL) | (data[6] << 18);
- outl(ul_Command1, dev->iobase +
- APCI1564_COUNTER_CTRL_REG(data[5] - 1));
+ /* First Stop The Timer */
+ ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
+ ctrl &= 0xfffff9fe;
+ /* Stop The Timer */
+ outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
+
+ if (data[1] == 1) {
+ /* Enable timer int & disable all the other int sources */
+ outl(0x02, devpriv->timer + ADDI_TCW_CTRL_REG);
+ outl(0x0, dev->iobase + APCI1564_DI_IRQ_REG);
+ outl(0x0, dev->iobase + APCI1564_DO_IRQ_REG);
+ outl(0x0, dev->iobase + APCI1564_WDOG_IRQ_REG);
+ if (devpriv->counters) {
+ unsigned long iobase;
+
+ iobase = devpriv->counters + ADDI_TCW_IRQ_REG;
+ outl(0x0, iobase + APCI1564_COUNTER(0));
+ outl(0x0, iobase + APCI1564_COUNTER(1));
+ outl(0x0, iobase + APCI1564_COUNTER(2));
+ }
} else {
- dev_err(dev->class_dev, "Invalid subdevice.\n");
+ /* disable Timer interrupt */
+ outl(0x0, devpriv->timer + ADDI_TCW_CTRL_REG);
}
+
+ /* Loading Timebase */
+ outl(data[2], devpriv->timer + ADDI_TCW_TIMEBASE_REG);
+
+ /* Loading the Reload value */
+ outl(data[3], devpriv->timer + ADDI_TCW_RELOAD_REG);
+
+ ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
+ ctrl &= 0xfff719e2;
+ ctrl |= (2 << 13) | 0x10;
+ /* mode 2 */
+ outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
+
return insn->n;
}
-/*
- * Start / Stop The Selected Timer or Counter
- *
- * data[0] Configure as: 0 = Timer, 1 = Counter
- * data[1] 0 = Stop, 1 = Start, 2 = Trigger Clear (Only Counter)
- */
-static int apci1564_timer_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
+static int apci1564_timer_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct apci1564_private *devpriv = dev->private;
- unsigned int ul_Command1 = 0;
+ unsigned int ctrl;
+
+ ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
+ switch (data[1]) {
+ case 0: /* Stop The Timer */
+ ctrl &= 0xfffff9fe;
+ break;
+ case 1: /* Enable the Timer */
+ ctrl &= 0xfffff9ff;
+ ctrl |= 0x1;
+ break;
+ }
+ outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
- if (devpriv->timer_select_mode == ADDIDATA_TIMER) {
- if (data[1] == 1) {
- ul_Command1 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
+ return insn->n;
+}
- /* Enable the Timer */
- outl(ul_Command1, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- } else if (data[1] == 0) {
- /* Stop The Timer */
+static int apci1564_timer_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ struct apci1564_private *devpriv = dev->private;
+
+ /* Stores the status of the Timer */
+ data[0] = inl(devpriv->timer + ADDI_TCW_STATUS_REG) & 0x1;
+
+ /* Stores the Actual value of the Timer */
+ data[1] = inl(devpriv->timer + ADDI_TCW_VAL_REG);
- ul_Command1 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
- outl(ul_Command1, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- }
- } else if (devpriv->timer_select_mode == ADDIDATA_COUNTER) {
- ul_Command1 =
- inl(dev->iobase +
- APCI1564_COUNTER_CTRL_REG(devpriv->mode_select_register - 1));
- if (data[1] == 1) {
- /* Start the Counter subdevice */
- ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
- } else if (data[1] == 0) {
- /* Stops the Counter subdevice */
- ul_Command1 = 0;
-
- } else if (data[1] == 2) {
- /* Clears the Counter subdevice */
- ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x400;
- }
- outl(ul_Command1, dev->iobase +
- APCI1564_COUNTER_CTRL_REG(devpriv->mode_select_register - 1));
- } else {
- dev_err(dev->class_dev, "Invalid subdevice.\n");
- }
return insn->n;
}
-/*
- * Read The Selected Timer or Counter
- */
-static int apci1564_timer_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
+static int apci1564_counter_insn_config(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct apci1564_private *devpriv = dev->private;
- unsigned int ul_Command1 = 0;
-
- if (devpriv->timer_select_mode == ADDIDATA_TIMER) {
- /* Stores the status of the Timer */
- data[0] = inl(devpriv->amcc_iobase + APCI1564_TIMER_STATUS_REG) & 0x1;
-
- /* Stores the Actual value of the Timer */
- data[1] = inl(devpriv->amcc_iobase + APCI1564_TIMER_REG);
- } else if (devpriv->timer_select_mode == ADDIDATA_COUNTER) {
- /* Read the Counter Actual Value. */
- data[0] =
- inl(dev->iobase +
- APCI1564_COUNTER_REG(devpriv->mode_select_register - 1));
- ul_Command1 =
- inl(dev->iobase +
- APCI1564_COUNTER_STATUS_REG(devpriv->mode_select_register - 1));
-
- /* Get the software trigger status */
- data[1] = (unsigned char) ((ul_Command1 >> 1) & 1);
-
- /* Get the hardware trigger status */
- data[2] = (unsigned char) ((ul_Command1 >> 2) & 1);
-
- /* Get the software clear status */
- data[3] = (unsigned char) ((ul_Command1 >> 3) & 1);
-
- /* Get the overflow status */
- data[4] = (unsigned char) ((ul_Command1 >> 0) & 1);
- } else {
- dev_err(dev->class_dev, "Invalid subdevice.\n");
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
+ unsigned int ctrl;
+
+ devpriv->tsk_current = current;
+
+ /* First Stop The Counter */
+ ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
+ ctrl &= 0xfffff9fe;
+ /* Stop The Timer */
+ outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
+
+ /* Set the reload value */
+ outl(data[3], iobase + ADDI_TCW_RELOAD_REG);
+
+ /* Set the mode : */
+ /* - Disable the hardware */
+ /* - Disable the counter mode */
+ /* - Disable the warning */
+ /* - Disable the reset */
+ /* - Disable the timer mode */
+ /* - Enable the counter mode */
+
+ ctrl &= 0xfffc19e2;
+ ctrl |= 0x80000 | (data[4] << 16);
+ outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
+
+ /* Enable or Disable Interrupt */
+ ctrl &= 0xfffff9fd;
+ ctrl |= (data[1] << 1);
+ outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
+
+ /* Set the Up/Down selection */
+ ctrl &= 0xfffbf9ff;
+ ctrl |= (data[6] << 18);
+ outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
+
+ return insn->n;
+}
+
+static int apci1564_counter_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ struct apci1564_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
+ unsigned int ctrl;
+
+ ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
+ switch (data[1]) {
+ case 0: /* Stops the Counter subdevice */
+ ctrl = 0;
+ break;
+ case 1: /* Start the Counter subdevice */
+ ctrl &= 0xfffff9ff;
+ ctrl |= 0x1;
+ break;
+ case 2: /* Clears the Counter subdevice */
+ ctrl &= 0xfffff9ff;
+ ctrl |= 0x400;
+ break;
}
+ outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
+
+ return insn->n;
+}
+
+static int apci1564_counter_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ struct apci1564_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
+ unsigned int status;
+
+ /* Read the Counter Actual Value. */
+ data[0] = inl(iobase + ADDI_TCW_VAL_REG);
+
+ status = inl(iobase + ADDI_TCW_STATUS_REG);
+ data[1] = (status >> 1) & 1; /* software trigger status */
+ data[2] = (status >> 2) & 1; /* hardware trigger status */
+ data[3] = (status >> 3) & 1; /* software clear status */
+ data[4] = (status >> 0) & 1; /* overflow status */
+
return insn->n;
}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
deleted file mode 100644
index 2950815b65f4..000000000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+++ /dev/null
@@ -1,2050 +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.
-
-@endverbatim
-*/
-/*
- +-----------------------------------------------------------------------+
- | (C) ADDI-DATA GmbH Dieselstrasse 3 D-77833 Ottersweier |
- +-----------------------------------------------------------------------+
- | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
- | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
- +-----------------------------------------------------------------------+
- | Project : APCI-3120 | Compiler : GCC |
- | Module name : hwdrv_apci3120.c| Version : 2.96 |
- +-------------------------------+---------------------------------------+
- | Project manager: Eric Stolz | Date : 02/12/2002 |
- +-----------------------------------------------------------------------+
- | Description :APCI3120 Module. Hardware abstraction Layer for APCI3120|
- +-----------------------------------------------------------------------+
- | UPDATE'S |
- +-----------------------------------------------------------------------+
- | Date | Author | Description of updates |
- +----------+-----------+------------------------------------------------+
- | | | |
- | | | |
- +----------+-----------+------------------------------------------------+
-*/
-
-#include <linux/delay.h>
-
-/*
- * ADDON RELATED ADDITIONS
- */
-/* Constant */
-#define APCI3120_ENABLE_TRANSFER_ADD_ON_LOW 0x00
-#define APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH 0x1200
-#define APCI3120_A2P_FIFO_MANAGEMENT 0x04000400L
-#define APCI3120_AMWEN_ENABLE 0x02
-#define APCI3120_A2P_FIFO_WRITE_ENABLE 0x01
-#define APCI3120_FIFO_ADVANCE_ON_BYTE_2 0x20000000L
-#define APCI3120_ENABLE_WRITE_TC_INT 0x00004000L
-#define APCI3120_CLEAR_WRITE_TC_INT 0x00040000L
-#define APCI3120_DISABLE_AMWEN_AND_A2P_FIFO_WRITE 0x0
-#define APCI3120_DISABLE_BUS_MASTER_ADD_ON 0x0
-#define APCI3120_DISABLE_BUS_MASTER_PCI 0x0
-
-/* ADD_ON ::: this needed since apci supports 16 bit interface to add on */
-#define APCI3120_ADD_ON_AGCSTS_LOW 0x3C
-#define APCI3120_ADD_ON_AGCSTS_HIGH (APCI3120_ADD_ON_AGCSTS_LOW + 2)
-#define APCI3120_ADD_ON_MWAR_LOW 0x24
-#define APCI3120_ADD_ON_MWAR_HIGH (APCI3120_ADD_ON_MWAR_LOW + 2)
-#define APCI3120_ADD_ON_MWTC_LOW 0x058
-#define APCI3120_ADD_ON_MWTC_HIGH (APCI3120_ADD_ON_MWTC_LOW + 2)
-
-/* AMCC */
-#define APCI3120_AMCC_OP_MCSR 0x3C
-#define APCI3120_AMCC_OP_REG_INTCSR 0x38
-
-/* for transfer count enable bit */
-#define AGCSTS_TC_ENABLE 0x10000000
-
-/* used for test on mixture of BIP/UNI ranges */
-#define APCI3120_BIPOLAR_RANGES 4
-
-#define APCI3120_ADDRESS_RANGE 16
-
-#define APCI3120_DISABLE 0
-#define APCI3120_ENABLE 1
-
-#define APCI3120_START 1
-#define APCI3120_STOP 0
-
-#define APCI3120_EOC_MODE 1
-#define APCI3120_EOS_MODE 2
-#define APCI3120_DMA_MODE 3
-
-/* DIGITAL INPUT-OUTPUT DEFINE */
-
-#define APCI3120_DIGITAL_OUTPUT 0x0d
-#define APCI3120_RD_STATUS 0x02
-#define APCI3120_RD_FIFO 0x00
-
-/* digital output insn_write ON /OFF selection */
-#define APCI3120_SET4DIGITALOUTPUTON 1
-#define APCI3120_SET4DIGITALOUTPUTOFF 0
-
-/* analog output SELECT BIT */
-#define APCI3120_ANALOG_OP_CHANNEL_1 0x0000
-#define APCI3120_ANALOG_OP_CHANNEL_2 0x4000
-#define APCI3120_ANALOG_OP_CHANNEL_3 0x8000
-#define APCI3120_ANALOG_OP_CHANNEL_4 0xc000
-#define APCI3120_ANALOG_OP_CHANNEL_5 0x0000
-#define APCI3120_ANALOG_OP_CHANNEL_6 0x4000
-#define APCI3120_ANALOG_OP_CHANNEL_7 0x8000
-#define APCI3120_ANALOG_OP_CHANNEL_8 0xc000
-
-/* Enable external trigger bit in nWrAddress */
-#define APCI3120_ENABLE_EXT_TRIGGER 0x8000
-
-/* ANALOG OUTPUT AND INPUT DEFINE */
-#define APCI3120_UNIPOLAR 0x80
-#define APCI3120_BIPOLAR 0x00
-#define APCI3120_ANALOG_OUTPUT_1 0x08
-#define APCI3120_ANALOG_OUTPUT_2 0x0a
-#define APCI3120_1_GAIN 0x00
-#define APCI3120_2_GAIN 0x10
-#define APCI3120_5_GAIN 0x20
-#define APCI3120_10_GAIN 0x30
-#define APCI3120_SEQ_RAM_ADDRESS 0x06
-#define APCI3120_RESET_FIFO 0x0c
-#define APCI3120_TIMER_0_MODE_2 0x01
-#define APCI3120_TIMER_0_MODE_4 0x2
-#define APCI3120_SELECT_TIMER_0_WORD 0x00
-#define APCI3120_ENABLE_TIMER0 0x1000
-#define APCI3120_CLEAR_PR 0xf0ff
-#define APCI3120_CLEAR_PA 0xfff0
-#define APCI3120_CLEAR_PA_PR (APCI3120_CLEAR_PR & APCI3120_CLEAR_PA)
-
-/* nWrMode_Select */
-#define APCI3120_ENABLE_SCAN 0x8
-#define APCI3120_DISABLE_SCAN (~APCI3120_ENABLE_SCAN)
-#define APCI3120_ENABLE_EOS_INT 0x2
-
-#define APCI3120_DISABLE_EOS_INT (~APCI3120_ENABLE_EOS_INT)
-#define APCI3120_ENABLE_EOC_INT 0x1
-#define APCI3120_DISABLE_EOC_INT (~APCI3120_ENABLE_EOC_INT)
-#define APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER \
- (APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT)
-#define APCI3120_DISABLE_ALL_INTERRUPT \
- (APCI3120_DISABLE_TIMER_INT & APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT)
-
-/* status register bits */
-#define APCI3120_EOC 0x8000
-#define APCI3120_EOS 0x2000
-
-/* software trigger dummy register */
-#define APCI3120_START_CONVERSION 0x02
-
-/* TIMER DEFINE */
-#define APCI3120_QUARTZ_A 70
-#define APCI3120_QUARTZ_B 50
-#define APCI3120_TIMER 1
-#define APCI3120_WATCHDOG 2
-#define APCI3120_TIMER_DISABLE 0
-#define APCI3120_TIMER_ENABLE 1
-#define APCI3120_ENABLE_TIMER2 0x4000
-#define APCI3120_DISABLE_TIMER2 (~APCI3120_ENABLE_TIMER2)
-#define APCI3120_ENABLE_TIMER_INT 0x04
-#define APCI3120_DISABLE_TIMER_INT (~APCI3120_ENABLE_TIMER_INT)
-#define APCI3120_WRITE_MODE_SELECT 0x0e
-#define APCI3120_SELECT_TIMER_0_WORD 0x00
-#define APCI3120_SELECT_TIMER_1_WORD 0x01
-#define APCI3120_TIMER_1_MODE_2 0x4
-
-/* $$ BIT FOR MODE IN nCsTimerCtr1 */
-#define APCI3120_TIMER_2_MODE_0 0x0
-#define APCI3120_TIMER_2_MODE_2 0x10
-#define APCI3120_TIMER_2_MODE_5 0x30
-
-/* $$ BIT FOR MODE IN nCsTimerCtr0 */
-#define APCI3120_SELECT_TIMER_2_LOW_WORD 0x02
-#define APCI3120_SELECT_TIMER_2_HIGH_WORD 0x03
-
-#define APCI3120_TIMER_CRT0 0x0d
-#define APCI3120_TIMER_CRT1 0x0c
-
-#define APCI3120_TIMER_VALUE 0x04
-#define APCI3120_TIMER_STATUS_REGISTER 0x0d
-#define APCI3120_RD_STATUS 0x02
-#define APCI3120_WR_ADDRESS 0x00
-#define APCI3120_ENABLE_WATCHDOG 0x20
-#define APCI3120_DISABLE_WATCHDOG (~APCI3120_ENABLE_WATCHDOG)
-#define APCI3120_ENABLE_TIMER_COUNTER 0x10
-#define APCI3120_DISABLE_TIMER_COUNTER (~APCI3120_ENABLE_TIMER_COUNTER)
-#define APCI3120_FC_TIMER 0x1000
-#define APCI3120_ENABLE_TIMER0 0x1000
-#define APCI3120_ENABLE_TIMER1 0x2000
-#define APCI3120_ENABLE_TIMER2 0x4000
-#define APCI3120_DISABLE_TIMER0 (~APCI3120_ENABLE_TIMER0)
-#define APCI3120_DISABLE_TIMER1 (~APCI3120_ENABLE_TIMER1)
-#define APCI3120_DISABLE_TIMER2 (~APCI3120_ENABLE_TIMER2)
-
-#define APCI3120_TIMER2_SELECT_EOS 0xc0
-#define APCI3120_COUNTER 3
-#define APCI3120_DISABLE_ALL_TIMER (APCI3120_DISABLE_TIMER0 & \
- APCI3120_DISABLE_TIMER1 & \
- APCI3120_DISABLE_TIMER2)
-
-#define MAX_ANALOGINPUT_CHANNELS 32
-
-struct str_AnalogReadInformation {
- /* EOC or EOS */
- unsigned char b_Type;
- /* Interrupt use or not */
- unsigned char b_InterruptFlag;
- /* Selection of the conversion time */
- unsigned int ui_ConvertTiming;
- /* Number of channel to read */
- unsigned char b_NbrOfChannel;
- /* Number of the channel to be read */
- unsigned int ui_ChannelList[MAX_ANALOGINPUT_CHANNELS];
- /* Gain of each channel */
- unsigned int ui_RangeList[MAX_ANALOGINPUT_CHANNELS];
-};
-
-/* ANALOG INPUT RANGE */
-static const struct comedi_lrange range_apci3120_ai = {
- 8, {
- BIP_RANGE(10),
- BIP_RANGE(5),
- BIP_RANGE(2),
- BIP_RANGE(1),
- UNI_RANGE(10),
- UNI_RANGE(5),
- UNI_RANGE(2),
- UNI_RANGE(1)
- }
-};
-
-/* ANALOG OUTPUT RANGE */
-static const struct comedi_lrange range_apci3120_ao = {
- 2, {
- BIP_RANGE(10),
- UNI_RANGE(10)
- }
-};
-
-
-/* FUNCTION DEFINITIONS */
-static int apci3120_ai_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- const struct addi_board *this_board = dev->board_ptr;
- struct addi_private *devpriv = dev->private;
- unsigned int i;
-
- if ((data[0] != APCI3120_EOC_MODE) && (data[0] != APCI3120_EOS_MODE))
- return -1;
-
- /* Check for Conversion time to be added */
- devpriv->ui_EocEosConversionTime = data[2];
-
- if (data[0] == APCI3120_EOS_MODE) {
-
- /* Test the number of the channel */
- for (i = 0; i < data[3]; i++) {
-
- if (CR_CHAN(data[4 + i]) >=
- this_board->i_NbrAiChannel) {
- dev_err(dev->class_dev, "bad channel list\n");
- return -2;
- }
- }
-
- devpriv->b_InterruptMode = APCI3120_EOS_MODE;
-
- if (data[1])
- devpriv->b_EocEosInterrupt = APCI3120_ENABLE;
- else
- devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
- /* Copy channel list and Range List to devpriv */
- devpriv->ui_AiNbrofChannels = data[3];
- for (i = 0; i < devpriv->ui_AiNbrofChannels; i++)
- devpriv->ui_AiChannelList[i] = data[4 + i];
-
- } else { /* EOC */
- devpriv->b_InterruptMode = APCI3120_EOC_MODE;
- if (data[1])
- devpriv->b_EocEosInterrupt = APCI3120_ENABLE;
- else
- devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
- }
-
- return insn->n;
-}
-
-/*
- * This function will first check channel list is ok or not and then
- * initialize the sequence RAM with the polarity, Gain,Channel number.
- * If the last argument of function "check"is 1 then it only checks
- * the channel list is ok or not.
- */
-static int apci3120_setup_chan_list(struct comedi_device *dev,
- struct comedi_subdevice *s,
- int n_chan,
- unsigned int *chanlist,
- char check)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int i;
- unsigned int gain;
- unsigned short us_TmpValue;
-
- /* correct channel and range number check itself comedi/range.c */
- if (n_chan < 1) {
- if (!check)
- dev_err(dev->class_dev,
- "range/channel list is empty!\n");
- return 0;
- }
- /* All is ok, so we can setup channel/range list */
- if (check)
- return 1;
-
- /* Code to set the PA and PR...Here it set PA to 0 */
- devpriv->us_OutputRegister =
- devpriv->us_OutputRegister & APCI3120_CLEAR_PA_PR;
- devpriv->us_OutputRegister = ((n_chan - 1) & 0xf) << 8;
- outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
-
- for (i = 0; i < n_chan; i++) {
- /* store range list to card */
- us_TmpValue = CR_CHAN(chanlist[i]); /* get channel number */
-
- if (CR_RANGE(chanlist[i]) < APCI3120_BIPOLAR_RANGES)
- us_TmpValue &= ((~APCI3120_UNIPOLAR) & 0xff); /* set bipolar */
- else
- us_TmpValue |= APCI3120_UNIPOLAR; /* enable unipolar */
-
- gain = CR_RANGE(chanlist[i]); /* get gain number */
- us_TmpValue |= ((gain & 0x03) << 4); /* <<4 for G0 and G1 bit in RAM */
- us_TmpValue |= i << 8; /* To select the RAM LOCATION */
- outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS);
- }
- return 1; /* we can serve this with scan logic */
-}
-
-/*
- * Reads analog input in synchronous mode EOC and EOS is selected
- * as per configured if no conversion time is set uses default
- * conversion time 10 microsec.
- */
-static int apci3120_ai_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- const struct addi_board *this_board = dev->board_ptr;
- struct addi_private *devpriv = dev->private;
- unsigned short us_ConvertTiming, us_TmpValue, i;
- unsigned char b_Tmp;
-
- /* fix conversion time to 10 us */
- if (!devpriv->ui_EocEosConversionTime)
- us_ConvertTiming = 10;
- else
- us_ConvertTiming = (unsigned short) (devpriv->ui_EocEosConversionTime / 1000); /* nano to useconds */
-
- /* Clear software registers */
- devpriv->b_TimerSelectMode = 0;
- devpriv->b_ModeSelectRegister = 0;
- devpriv->us_OutputRegister = 0;
-
- if (insn->unused[0] == 222) { /* second insn read */
- for (i = 0; i < insn->n; i++)
- data[i] = devpriv->ui_AiReadData[i];
- } else {
- devpriv->tsk_Current = current; /* Save the current process task structure */
-
- /*
- * Testing if board have the new Quartz and calculate the time value
- * to set in the timer
- */
- us_TmpValue =
- (unsigned short) inw(devpriv->iobase + APCI3120_RD_STATUS);
-
- /* EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001 */
- if ((us_TmpValue & 0x00B0) == 0x00B0
- || !strcmp(this_board->pc_DriverName, "apci3001")) {
- us_ConvertTiming = (us_ConvertTiming * 2) - 2;
- } else {
- us_ConvertTiming =
- ((us_ConvertTiming * 12926) / 10000) - 1;
- }
-
- us_TmpValue = (unsigned short) devpriv->b_InterruptMode;
-
- switch (us_TmpValue) {
-
- case APCI3120_EOC_MODE:
-
- /*
- * Testing the interrupt flag and set the EOC bit Clears the FIFO
- */
- inw(devpriv->iobase + APCI3120_RESET_FIFO);
-
- /* Initialize the sequence array */
- if (!apci3120_setup_chan_list(dev, s, 1,
- &insn->chanspec, 0))
- return -EINVAL;
-
- /* Initialize Timer 0 mode 4 */
- devpriv->b_TimerSelectMode =
- (devpriv->
- b_TimerSelectMode & 0xFC) |
- APCI3120_TIMER_0_MODE_4;
- outb(devpriv->b_TimerSelectMode,
- devpriv->iobase + APCI3120_TIMER_CRT1);
-
- /* Reset the scan bit and Disables the EOS, DMA, EOC interrupt */
- devpriv->b_ModeSelectRegister =
- devpriv->
- b_ModeSelectRegister & APCI3120_DISABLE_SCAN;
-
- if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) {
-
- /* Disables the EOS,DMA and enables the EOC interrupt */
- devpriv->b_ModeSelectRegister =
- (devpriv->
- b_ModeSelectRegister &
- APCI3120_DISABLE_EOS_INT) |
- APCI3120_ENABLE_EOC_INT;
- inw(devpriv->iobase);
-
- } else {
- devpriv->b_ModeSelectRegister =
- devpriv->
- b_ModeSelectRegister &
- APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER;
- }
-
- outb(devpriv->b_ModeSelectRegister,
- devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
-
- /* Sets gate 0 */
- devpriv->us_OutputRegister =
- (devpriv->
- us_OutputRegister & APCI3120_CLEAR_PA_PR) |
- APCI3120_ENABLE_TIMER0;
- outw(devpriv->us_OutputRegister,
- devpriv->iobase + APCI3120_WR_ADDRESS);
-
- /* Select Timer 0 */
- b_Tmp = ((devpriv->
- b_DigitalOutputRegister) & 0xF0) |
- APCI3120_SELECT_TIMER_0_WORD;
- outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
-
- /* Set the conversion time */
- outw(us_ConvertTiming,
- devpriv->iobase + APCI3120_TIMER_VALUE);
-
- us_TmpValue =
- (unsigned short) inw(dev->iobase + APCI3120_RD_STATUS);
-
- if (devpriv->b_EocEosInterrupt == APCI3120_DISABLE) {
-
- do {
- /* Waiting for the end of conversion */
- us_TmpValue =
- inw(devpriv->iobase +
- APCI3120_RD_STATUS);
- } while ((us_TmpValue & APCI3120_EOC) ==
- APCI3120_EOC);
-
- /* Read the result in FIFO and put it in insn data pointer */
- us_TmpValue = inw(devpriv->iobase + 0);
- *data = us_TmpValue;
-
- inw(devpriv->iobase + APCI3120_RESET_FIFO);
- }
-
- break;
-
- case APCI3120_EOS_MODE:
-
- inw(devpriv->iobase);
- /* Clears the FIFO */
- inw(devpriv->iobase + APCI3120_RESET_FIFO);
- /* clear PA PR and disable timer 0 */
-
- devpriv->us_OutputRegister =
- (devpriv->
- us_OutputRegister & APCI3120_CLEAR_PA_PR) |
- APCI3120_DISABLE_TIMER0;
-
- outw(devpriv->us_OutputRegister,
- devpriv->iobase + APCI3120_WR_ADDRESS);
-
- if (!apci3120_setup_chan_list(dev, s,
- devpriv->ui_AiNbrofChannels,
- devpriv->ui_AiChannelList, 0))
- return -EINVAL;
-
- /* Initialize Timer 0 mode 2 */
- devpriv->b_TimerSelectMode =
- (devpriv->
- b_TimerSelectMode & 0xFC) |
- APCI3120_TIMER_0_MODE_2;
- outb(devpriv->b_TimerSelectMode,
- devpriv->iobase + APCI3120_TIMER_CRT1);
-
- /* Select Timer 0 */
- b_Tmp = ((devpriv->
- b_DigitalOutputRegister) & 0xF0) |
- APCI3120_SELECT_TIMER_0_WORD;
- outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
-
- /* Set the conversion time */
- outw(us_ConvertTiming,
- devpriv->iobase + APCI3120_TIMER_VALUE);
-
- /* Set the scan bit */
- devpriv->b_ModeSelectRegister =
- devpriv->
- b_ModeSelectRegister | APCI3120_ENABLE_SCAN;
- outb(devpriv->b_ModeSelectRegister,
- devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
-
- /* If Interrupt function is loaded */
- if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) {
- /* Disables the EOC,DMA and enables the EOS interrupt */
- devpriv->b_ModeSelectRegister =
- (devpriv->
- b_ModeSelectRegister &
- APCI3120_DISABLE_EOC_INT) |
- APCI3120_ENABLE_EOS_INT;
- inw(devpriv->iobase);
-
- } else
- devpriv->b_ModeSelectRegister =
- devpriv->
- b_ModeSelectRegister &
- APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER;
-
- outb(devpriv->b_ModeSelectRegister,
- devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
-
- inw(devpriv->iobase + APCI3120_RD_STATUS);
-
- /* Sets gate 0 */
- devpriv->us_OutputRegister =
- devpriv->
- us_OutputRegister | APCI3120_ENABLE_TIMER0;
- outw(devpriv->us_OutputRegister,
- devpriv->iobase + APCI3120_WR_ADDRESS);
-
- /* Start conversion */
- outw(0, devpriv->iobase + APCI3120_START_CONVERSION);
-
- /* Waiting of end of conversion if interrupt is not installed */
- if (devpriv->b_EocEosInterrupt == APCI3120_DISABLE) {
- /* Waiting the end of conversion */
- do {
- us_TmpValue =
- inw(devpriv->iobase +
- APCI3120_RD_STATUS);
- } while ((us_TmpValue & APCI3120_EOS) !=
- APCI3120_EOS);
-
- for (i = 0; i < devpriv->ui_AiNbrofChannels;
- i++) {
- /* Read the result in FIFO and write them in shared memory */
- us_TmpValue = inw(devpriv->iobase);
- data[i] = (unsigned int) us_TmpValue;
- }
-
- devpriv->b_InterruptMode = APCI3120_EOC_MODE; /* Restore defaults */
- }
- break;
-
- default:
- dev_err(dev->class_dev, "inputs wrong\n");
-
- }
- devpriv->ui_EocEosConversionTime = 0; /* re initializing the variable */
- }
-
- return insn->n;
-
-}
-
-static int apci3120_reset(struct comedi_device *dev)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int i;
- unsigned short us_TmpValue;
-
- devpriv->ai_running = 0;
- devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
- devpriv->b_InterruptMode = APCI3120_EOC_MODE;
- devpriv->ui_EocEosConversionTime = 0; /* set eoc eos conv time to 0 */
-
- /* variables used in timer subdevice */
- devpriv->b_Timer2Mode = 0;
- devpriv->b_Timer2Interrupt = 0;
- devpriv->b_ExttrigEnable = 0; /* Disable ext trigger */
-
- /* Disable all interrupts, watchdog for the anolog output */
- devpriv->b_ModeSelectRegister = 0;
- outb(devpriv->b_ModeSelectRegister,
- dev->iobase + APCI3120_WRITE_MODE_SELECT);
-
- /* Disables all counters, ext trigger and clears PA, PR */
- devpriv->us_OutputRegister = 0;
- outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
-
- /*
- * Code to set the all anolog o/p channel to 0v 8191 is decimal
- * value for zero(0 v)volt in bipolar mode(default)
- */
- outw(8191 | APCI3120_ANALOG_OP_CHANNEL_1, dev->iobase + APCI3120_ANALOG_OUTPUT_1); /* channel 1 */
- outw(8191 | APCI3120_ANALOG_OP_CHANNEL_2, dev->iobase + APCI3120_ANALOG_OUTPUT_1); /* channel 2 */
- outw(8191 | APCI3120_ANALOG_OP_CHANNEL_3, dev->iobase + APCI3120_ANALOG_OUTPUT_1); /* channel 3 */
- outw(8191 | APCI3120_ANALOG_OP_CHANNEL_4, dev->iobase + APCI3120_ANALOG_OUTPUT_1); /* channel 4 */
-
- outw(8191 | APCI3120_ANALOG_OP_CHANNEL_5, dev->iobase + APCI3120_ANALOG_OUTPUT_2); /* channel 5 */
- outw(8191 | APCI3120_ANALOG_OP_CHANNEL_6, dev->iobase + APCI3120_ANALOG_OUTPUT_2); /* channel 6 */
- outw(8191 | APCI3120_ANALOG_OP_CHANNEL_7, dev->iobase + APCI3120_ANALOG_OUTPUT_2); /* channel 7 */
- outw(8191 | APCI3120_ANALOG_OP_CHANNEL_8, dev->iobase + APCI3120_ANALOG_OUTPUT_2); /* channel 8 */
-
- udelay(10);
-
- inw(dev->iobase + 0); /* make a dummy read */
- inb(dev->iobase + APCI3120_RESET_FIFO); /* flush FIFO */
- inw(dev->iobase + APCI3120_RD_STATUS); /* flush A/D status register */
-
- /* code to reset the RAM sequence */
- for (i = 0; i < 16; i++) {
- us_TmpValue = i << 8; /* select the location */
- outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS);
- }
- return 0;
-}
-
-static int apci3120_exttrig_enable(struct comedi_device *dev)
-{
- struct addi_private *devpriv = dev->private;
-
- devpriv->us_OutputRegister |= APCI3120_ENABLE_EXT_TRIGGER;
- outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
- return 0;
-}
-
-static int apci3120_exttrig_disable(struct comedi_device *dev)
-{
- struct addi_private *devpriv = dev->private;
-
- devpriv->us_OutputRegister &= ~APCI3120_ENABLE_EXT_TRIGGER;
- outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
- return 0;
-}
-
-static int apci3120_cancel(struct comedi_device *dev,
- struct comedi_subdevice *s)
-{
- struct addi_private *devpriv = dev->private;
-
- /* Disable A2P Fifo write and AMWEN signal */
- outw(0, devpriv->i_IobaseAddon + 4);
-
- /* Disable Bus Master ADD ON */
- outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
- outw(0, devpriv->i_IobaseAddon + 2);
- outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
- outw(0, devpriv->i_IobaseAddon + 2);
-
- /* Disable BUS Master PCI */
- outl(0, devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR);
-
- /* Disable ext trigger */
- apci3120_exttrig_disable(dev);
-
- devpriv->us_OutputRegister = 0;
- /* stop counters */
- outw(devpriv->
- us_OutputRegister & APCI3120_DISABLE_TIMER0 &
- APCI3120_DISABLE_TIMER1, dev->iobase + APCI3120_WR_ADDRESS);
-
- outw(APCI3120_DISABLE_ALL_TIMER, dev->iobase + APCI3120_WR_ADDRESS);
-
- /* DISABLE_ALL_INTERRUPT */
- outb(APCI3120_DISABLE_ALL_INTERRUPT,
- dev->iobase + APCI3120_WRITE_MODE_SELECT);
- /* Flush FIFO */
- inb(dev->iobase + APCI3120_RESET_FIFO);
- inw(dev->iobase + APCI3120_RD_STATUS);
- devpriv->ui_AiActualScan = 0;
- s->async->cur_chan = 0;
- devpriv->ui_DmaActualBuffer = 0;
-
- devpriv->ai_running = 0;
- devpriv->b_InterruptMode = APCI3120_EOC_MODE;
- devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
- apci3120_reset(dev);
- return 0;
-}
-
-static int apci3120_ai_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_EXT);
- err |= cfc_check_trigger_src(&cmd->scan_begin_src,
- TRIG_TIMER | TRIG_FOLLOW);
- err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
- err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
- err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
-
- if (err)
- return 1;
-
- /* Step 2a : make sure trigger sources are unique */
-
- err |= cfc_check_trigger_is_unique(cmd->start_src);
- err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
- err |= cfc_check_trigger_is_unique(cmd->stop_src);
-
- /* Step 2b : and mutually compatible */
-
- if (err)
- return 2;
-
- /* Step 3: check if arguments are trivially valid */
-
- err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-
- if (cmd->scan_begin_src == TRIG_TIMER) /* Test Delay timing */
- err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, 100000);
-
- if (cmd->scan_begin_src == TRIG_TIMER) {
- if (cmd->convert_arg)
- err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
- 10000);
- } else {
- err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 10000);
- }
-
- err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
- err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
-
- if (cmd->stop_src == TRIG_COUNT)
- err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
- else /* TRIG_NONE */
- err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
-
- if (err)
- return 3;
-
- /* step 4: fix up any arguments */
-
- if (cmd->scan_begin_src == TRIG_TIMER &&
- cmd->scan_begin_arg < cmd->convert_arg * cmd->scan_end_arg) {
- cmd->scan_begin_arg = cmd->convert_arg * cmd->scan_end_arg;
- err |= -EINVAL;
- }
-
- if (err)
- return 4;
-
- return 0;
-}
-
-/*
- * This is used for analog input cyclic acquisition.
- * Performs the command operations.
- * If DMA is configured does DMA initialization otherwise does the
- * acquisition with EOS interrupt.
- */
-static int apci3120_cyclic_ai(int mode,
- struct comedi_device *dev,
- struct comedi_subdevice *s)
-{
- const struct addi_board *this_board = dev->board_ptr;
- struct addi_private *devpriv = dev->private;
- struct comedi_cmd *cmd = &s->async->cmd;
- unsigned char b_Tmp;
- unsigned int ui_Tmp, ui_DelayTiming = 0, ui_TimerValue1 = 0, dmalen0 =
- 0, dmalen1 = 0, ui_TimerValue2 =
- 0, ui_TimerValue0, ui_ConvertTiming;
- unsigned short us_TmpValue;
-
- /* Resets the FIFO */
- inb(dev->iobase + APCI3120_RESET_FIFO);
-
- devpriv->ai_running = 1;
-
- /* clear software registers */
- devpriv->b_TimerSelectMode = 0;
- devpriv->us_OutputRegister = 0;
- devpriv->b_ModeSelectRegister = 0;
-
- /* Clear Timer Write TC int */
- outl(APCI3120_CLEAR_WRITE_TC_INT,
- devpriv->i_IobaseAmcc + APCI3120_AMCC_OP_REG_INTCSR);
-
- /* Disables All Timer */
- /* Sets PR and PA to 0 */
- devpriv->us_OutputRegister = devpriv->us_OutputRegister &
- APCI3120_DISABLE_TIMER0 &
- APCI3120_DISABLE_TIMER1 & APCI3120_CLEAR_PA_PR;
-
- outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
-
- /* Resets the FIFO */
- /* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */
- inb(devpriv->iobase + APCI3120_RESET_FIFO);
- /* END JK 07.05.04: Comparison between WIN32 and Linux driver */
-
- devpriv->ui_AiActualScan = 0;
- s->async->cur_chan = 0;
- devpriv->ui_DmaActualBuffer = 0;
-
- /* value for timer2 minus -2 has to be done */
- ui_TimerValue2 = cmd->stop_arg - 2;
- ui_ConvertTiming = cmd->convert_arg;
-
- if (mode == 2)
- ui_DelayTiming = cmd->scan_begin_arg;
-
- /* Initializes the sequence array */
- if (!apci3120_setup_chan_list(dev, s, devpriv->ui_AiNbrofChannels,
- cmd->chanlist, 0))
- return -EINVAL;
-
- us_TmpValue = (unsigned short) inw(dev->iobase + APCI3120_RD_STATUS);
-
- /* EL241003 Begin: add this section to replace floats calculation by integer calculations */
- /* EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001 */
- if ((us_TmpValue & 0x00B0) == 0x00B0
- || !strcmp(this_board->pc_DriverName, "apci3001")) {
- ui_TimerValue0 = ui_ConvertTiming * 2 - 2000;
- ui_TimerValue0 = ui_TimerValue0 / 1000;
-
- if (mode == 2) {
- ui_DelayTiming = ui_DelayTiming / 1000;
- ui_TimerValue1 = ui_DelayTiming * 2 - 200;
- ui_TimerValue1 = ui_TimerValue1 / 100;
- }
- } else {
- ui_ConvertTiming = ui_ConvertTiming / 1000;
- ui_TimerValue0 = ui_ConvertTiming * 12926 - 10000;
- ui_TimerValue0 = ui_TimerValue0 / 10000;
-
- if (mode == 2) {
- ui_DelayTiming = ui_DelayTiming / 1000;
- ui_TimerValue1 = ui_DelayTiming * 12926 - 1;
- ui_TimerValue1 = ui_TimerValue1 / 1000000;
- }
- }
- /* EL241003 End */
-
- if (devpriv->b_ExttrigEnable == APCI3120_ENABLE)
- apci3120_exttrig_enable(dev); /* activate EXT trigger */
- switch (mode) {
- case 1:
- /* init timer0 in mode 2 */
- devpriv->b_TimerSelectMode =
- (devpriv->
- b_TimerSelectMode & 0xFC) | APCI3120_TIMER_0_MODE_2;
- outb(devpriv->b_TimerSelectMode,
- dev->iobase + APCI3120_TIMER_CRT1);
-
- /* Select Timer 0 */
- b_Tmp = ((devpriv->
- b_DigitalOutputRegister) & 0xF0) |
- APCI3120_SELECT_TIMER_0_WORD;
- outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
- /* Set the conversion time */
- outw(((unsigned short) ui_TimerValue0),
- dev->iobase + APCI3120_TIMER_VALUE);
- break;
-
- case 2:
- /* init timer1 in mode 2 */
- devpriv->b_TimerSelectMode =
- (devpriv->
- b_TimerSelectMode & 0xF3) | APCI3120_TIMER_1_MODE_2;
- outb(devpriv->b_TimerSelectMode,
- dev->iobase + APCI3120_TIMER_CRT1);
-
- /* Select Timer 1 */
- b_Tmp = ((devpriv->
- b_DigitalOutputRegister) & 0xF0) |
- APCI3120_SELECT_TIMER_1_WORD;
- outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
- /* Set the conversion time */
- outw(((unsigned short) ui_TimerValue1),
- dev->iobase + APCI3120_TIMER_VALUE);
-
- /* init timer0 in mode 2 */
- devpriv->b_TimerSelectMode =
- (devpriv->
- b_TimerSelectMode & 0xFC) | APCI3120_TIMER_0_MODE_2;
- outb(devpriv->b_TimerSelectMode,
- dev->iobase + APCI3120_TIMER_CRT1);
-
- /* Select Timer 0 */
- b_Tmp = ((devpriv->
- b_DigitalOutputRegister) & 0xF0) |
- APCI3120_SELECT_TIMER_0_WORD;
- outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
-
- /* Set the conversion time */
- outw(((unsigned short) ui_TimerValue0),
- dev->iobase + APCI3120_TIMER_VALUE);
- break;
-
- }
- /* common for all modes */
- /* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */
- devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister &
- APCI3120_DISABLE_SCAN;
- /* END JK 07.05.04: Comparison between WIN32 and Linux driver */
-
- outb(devpriv->b_ModeSelectRegister,
- dev->iobase + APCI3120_WRITE_MODE_SELECT);
-
- /* If DMA is disabled */
- if (devpriv->us_UseDma == APCI3120_DISABLE) {
- /* disable EOC and enable EOS */
- devpriv->b_InterruptMode = APCI3120_EOS_MODE;
- devpriv->b_EocEosInterrupt = APCI3120_ENABLE;
-
- devpriv->b_ModeSelectRegister =
- (devpriv->
- b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT) |
- APCI3120_ENABLE_EOS_INT;
- outb(devpriv->b_ModeSelectRegister,
- dev->iobase + APCI3120_WRITE_MODE_SELECT);
-
- if (cmd->stop_src == TRIG_COUNT) {
- /*
- * configure Timer2 For counting EOS Reset gate 2 of Timer 2 to
- * disable it (Set Bit D14 to 0)
- */
- devpriv->us_OutputRegister =
- devpriv->
- us_OutputRegister & APCI3120_DISABLE_TIMER2;
- outw(devpriv->us_OutputRegister,
- dev->iobase + APCI3120_WR_ADDRESS);
-
- /* DISABLE TIMER intERRUPT */
- devpriv->b_ModeSelectRegister =
- devpriv->
- b_ModeSelectRegister &
- APCI3120_DISABLE_TIMER_INT & 0xEF;
- outb(devpriv->b_ModeSelectRegister,
- dev->iobase + APCI3120_WRITE_MODE_SELECT);
-
- /* (1) Init timer 2 in mode 0 and write timer value */
- devpriv->b_TimerSelectMode =
- (devpriv->
- b_TimerSelectMode & 0x0F) |
- APCI3120_TIMER_2_MODE_0;
- outb(devpriv->b_TimerSelectMode,
- dev->iobase + APCI3120_TIMER_CRT1);
-
- /* Writing LOW unsigned short */
- b_Tmp = ((devpriv->
- b_DigitalOutputRegister) & 0xF0) |
- APCI3120_SELECT_TIMER_2_LOW_WORD;
- outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
- outw(ui_TimerValue2 & 0xffff,
- dev->iobase + APCI3120_TIMER_VALUE);
-
- /* Writing HIGH unsigned short */
- b_Tmp = ((devpriv->
- b_DigitalOutputRegister) & 0xF0) |
- APCI3120_SELECT_TIMER_2_HIGH_WORD;
- outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
- outw((ui_TimerValue2 >> 16) & 0xffff,
- dev->iobase + APCI3120_TIMER_VALUE);
-
- /* (2) Reset FC_TIMER BIT Clearing timer status register */
- inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
- /* enable timer counter and disable watch dog */
- devpriv->b_ModeSelectRegister =
- (devpriv->
- b_ModeSelectRegister |
- APCI3120_ENABLE_TIMER_COUNTER) &
- APCI3120_DISABLE_WATCHDOG;
- /* select EOS clock input for timer 2 */
- devpriv->b_ModeSelectRegister =
- devpriv->
- b_ModeSelectRegister |
- APCI3120_TIMER2_SELECT_EOS;
- /* Enable timer2 interrupt */
- devpriv->b_ModeSelectRegister =
- devpriv->
- b_ModeSelectRegister |
- APCI3120_ENABLE_TIMER_INT;
- outb(devpriv->b_ModeSelectRegister,
- dev->iobase + APCI3120_WRITE_MODE_SELECT);
- devpriv->b_Timer2Mode = APCI3120_COUNTER;
- devpriv->b_Timer2Interrupt = APCI3120_ENABLE;
- }
- } else {
- /* If DMA Enabled */
- unsigned int scan_bytes = cmd->scan_end_arg * sizeof(short);
-
- devpriv->b_InterruptMode = APCI3120_DMA_MODE;
-
- /* Disables the EOC, EOS interrupt */
- devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister &
- APCI3120_DISABLE_EOC_INT & APCI3120_DISABLE_EOS_INT;
-
- outb(devpriv->b_ModeSelectRegister,
- dev->iobase + APCI3120_WRITE_MODE_SELECT);
-
- dmalen0 = devpriv->ui_DmaBufferSize[0];
- dmalen1 = devpriv->ui_DmaBufferSize[1];
-
- if (cmd->stop_src == TRIG_COUNT) {
- /*
- * Must we fill full first buffer? And must we fill
- * full second buffer when first is once filled?
- */
- if (dmalen0 > (cmd->stop_arg * scan_bytes)) {
- dmalen0 = cmd->stop_arg * scan_bytes;
- } else if (dmalen1 > (cmd->stop_arg * scan_bytes -
- dmalen0))
- dmalen1 = cmd->stop_arg * scan_bytes -
- dmalen0;
- }
-
- if (cmd->flags & CMDF_WAKE_EOS) {
- /* don't we want wake up every scan? */
- if (dmalen0 > scan_bytes) {
- dmalen0 = scan_bytes;
- if (cmd->scan_end_arg & 1)
- dmalen0 += 2;
- }
- if (dmalen1 > scan_bytes) {
- dmalen1 = scan_bytes;
- if (cmd->scan_end_arg & 1)
- dmalen1 -= 2;
- if (dmalen1 < 4)
- dmalen1 = 4;
- }
- } else { /* isn't output buff smaller that our DMA buff? */
- if (dmalen0 > s->async->prealloc_bufsz)
- dmalen0 = s->async->prealloc_bufsz;
- if (dmalen1 > s->async->prealloc_bufsz)
- dmalen1 = s->async->prealloc_bufsz;
- }
- devpriv->ui_DmaBufferUsesize[0] = dmalen0;
- devpriv->ui_DmaBufferUsesize[1] = dmalen1;
-
- /* Initialize DMA */
-
- /*
- * Set Transfer count enable bit and A2P_fifo reset bit in AGCSTS
- * register 1
- */
- ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO;
- outl(ui_Tmp, devpriv->i_IobaseAmcc + AMCC_OP_REG_AGCSTS);
-
- /* changed since 16 bit interface for add on */
- /* ENABLE BUS MASTER */
- outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
- outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,
- devpriv->i_IobaseAddon + 2);
-
- outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
- outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH,
- devpriv->i_IobaseAddon + 2);
-
- /*
- * TO VERIFIED BEGIN JK 07.05.04: Comparison between WIN32 and Linux
- * driver
- */
- outw(0x1000, devpriv->i_IobaseAddon + 2);
- /* END JK 07.05.04: Comparison between WIN32 and Linux driver */
-
- /* 2 No change */
- /* A2P FIFO MANAGEMENT */
- /* A2P fifo reset & transfer control enable */
- outl(APCI3120_A2P_FIFO_MANAGEMENT, devpriv->i_IobaseAmcc +
- APCI3120_AMCC_OP_MCSR);
-
- /*
- * 3
- * beginning address of dma buf The 32 bit address of dma buffer
- * is converted into two 16 bit addresses Can done by using _attach
- * and put into into an array array used may be for differnet pages
- */
-
- /* DMA Start Address Low */
- outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
- outw((devpriv->ul_DmaBufferHw[0] & 0xFFFF),
- devpriv->i_IobaseAddon + 2);
-
- /* DMA Start Address High */
- outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
- outw((devpriv->ul_DmaBufferHw[0] / 65536),
- devpriv->i_IobaseAddon + 2);
-
- /*
- * 4
- * amount of bytes to be transferred set transfer count used ADDON
- * MWTC register commented testing
- */
-
- /* Nbr of acquisition LOW */
- outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0);
- outw((devpriv->ui_DmaBufferUsesize[0] & 0xFFFF),
- devpriv->i_IobaseAddon + 2);
-
- /* Nbr of acquisition HIGH */
- outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0);
- outw((devpriv->ui_DmaBufferUsesize[0] / 65536),
- devpriv->i_IobaseAddon + 2);
-
- /*
- * 5
- * To configure A2P FIFO testing outl(
- * FIFO_ADVANCE_ON_BYTE_2,devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR);
- */
-
- /* A2P FIFO RESET */
- /*
- * TO VERIFY BEGIN JK 07.05.04: Comparison between WIN32 and Linux
- * driver
- */
- outl(0x04000000UL, devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR);
- /* END JK 07.05.04: Comparison between WIN32 and Linux driver */
-
- /*
- * 6
- * ENABLE A2P FIFO WRITE AND ENABLE AMWEN AMWEN_ENABLE |
- * A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
- */
-
- /*
- * 7
- * initialise end of dma interrupt AINT_WRITE_COMPL =
- * ENABLE_WRITE_TC_INT(ADDI)
- */
- /* A2P FIFO CONFIGURATE, END OF DMA intERRUPT INIT */
- outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 |
- APCI3120_ENABLE_WRITE_TC_INT),
- devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
-
- /* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */
- /* ENABLE A2P FIFO WRITE AND ENABLE AMWEN */
- outw(3, devpriv->i_IobaseAddon + 4);
- /* END JK 07.05.04: Comparison between WIN32 and Linux driver */
-
- /* A2P FIFO RESET */
- /* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */
- outl(0x04000000UL,
- devpriv->i_IobaseAmcc + APCI3120_AMCC_OP_MCSR);
- /* END JK 07.05.04: Comparison between WIN32 and Linux driver */
- }
-
- if (devpriv->us_UseDma == APCI3120_DISABLE &&
- cmd->stop_src == TRIG_COUNT) {
- /* set gate 2 to start conversion */
- devpriv->us_OutputRegister =
- devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER2;
- outw(devpriv->us_OutputRegister,
- dev->iobase + APCI3120_WR_ADDRESS);
- }
-
- switch (mode) {
- case 1:
- /* set gate 0 to start conversion */
- devpriv->us_OutputRegister =
- devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER0;
- outw(devpriv->us_OutputRegister,
- dev->iobase + APCI3120_WR_ADDRESS);
- break;
- case 2:
- /* set gate 0 and gate 1 */
- devpriv->us_OutputRegister =
- devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER1;
- devpriv->us_OutputRegister =
- devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER0;
- outw(devpriv->us_OutputRegister,
- dev->iobase + APCI3120_WR_ADDRESS);
- break;
-
- }
-
- return 0;
-
-}
-
-/*
- * Does asynchronous acquisition.
- * Determines the mode 1 or 2.
- */
-static int apci3120_ai_cmd(struct comedi_device *dev,
- struct comedi_subdevice *s)
-{
- struct addi_private *devpriv = dev->private;
- struct comedi_cmd *cmd = &s->async->cmd;
-
- /* loading private structure with cmd structure inputs */
- devpriv->ui_AiNbrofChannels = cmd->chanlist_len;
-
- if (cmd->start_src == TRIG_EXT)
- devpriv->b_ExttrigEnable = APCI3120_ENABLE;
- else
- devpriv->b_ExttrigEnable = APCI3120_DISABLE;
-
- if (cmd->scan_begin_src == TRIG_FOLLOW)
- return apci3120_cyclic_ai(1, dev, s);
- /* TRIG_TIMER */
- return apci3120_cyclic_ai(2, dev, s);
-}
-
-/*
- * This function copies the data from DMA buffer to the Comedi buffer.
- */
-static void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,
- struct comedi_subdevice *s,
- unsigned short *dma_buffer,
- unsigned int num_samples)
-{
- struct addi_private *devpriv = dev->private;
- struct comedi_cmd *cmd = &s->async->cmd;
-
- devpriv->ui_AiActualScan +=
- (s->async->cur_chan + num_samples) / cmd->scan_end_arg;
- s->async->cur_chan += num_samples;
- s->async->cur_chan %= cmd->scan_end_arg;
-
- cfc_write_array_to_buffer(s, dma_buffer, num_samples * sizeof(short));
-}
-
-/*
- * This is a handler for the DMA interrupt.
- * This function copies the data to Comedi Buffer.
- * For continuous DMA it reinitializes the DMA operation.
- * For single mode DMA it stop the acquisition.
- */
-static void apci3120_interrupt_dma(int irq, void *d)
-{
- struct comedi_device *dev = d;
- struct addi_private *devpriv = dev->private;
- struct comedi_subdevice *s = dev->read_subdev;
- struct comedi_cmd *cmd = &s->async->cmd;
- unsigned int next_dma_buf, samplesinbuf;
- unsigned long low_word, high_word, var;
- unsigned int ui_Tmp;
-
- samplesinbuf =
- devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer] -
- inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_MWTC);
-
- if (samplesinbuf <
- devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer]) {
- dev_err(dev->class_dev, "Interrupted DMA transfer!\n");
- }
- if (samplesinbuf & 1) {
- dev_err(dev->class_dev, "Odd count of bytes in DMA ring!\n");
- apci3120_cancel(dev, s);
- return;
- }
- samplesinbuf = samplesinbuf >> 1; /* number of received samples */
- if (devpriv->b_DmaDoubleBuffer) {
- /* switch DMA buffers if is used double buffering */
- next_dma_buf = 1 - devpriv->ui_DmaActualBuffer;
-
- ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO;
- outl(ui_Tmp, devpriv->i_IobaseAddon + AMCC_OP_REG_AGCSTS);
-
- /* changed since 16 bit interface for add on */
- outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
- outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,
- devpriv->i_IobaseAddon + 2);
- outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
- outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2); /* 0x1000 is out putted in windows driver */
-
- var = devpriv->ul_DmaBufferHw[next_dma_buf];
- low_word = var & 0xffff;
- var = devpriv->ul_DmaBufferHw[next_dma_buf];
- high_word = var / 65536;
-
- /* DMA Start Address Low */
- outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
- outw(low_word, devpriv->i_IobaseAddon + 2);
-
- /* DMA Start Address High */
- outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
- outw(high_word, devpriv->i_IobaseAddon + 2);
-
- var = devpriv->ui_DmaBufferUsesize[next_dma_buf];
- low_word = var & 0xffff;
- var = devpriv->ui_DmaBufferUsesize[next_dma_buf];
- high_word = var / 65536;
-
- /* Nbr of acquisition LOW */
- outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0);
- outw(low_word, devpriv->i_IobaseAddon + 2);
-
- /* Nbr of acquisition HIGH */
- outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0);
- outw(high_word, devpriv->i_IobaseAddon + 2);
-
- /*
- * To configure A2P FIFO
- * ENABLE A2P FIFO WRITE AND ENABLE AMWEN
- * AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
- */
- outw(3, devpriv->i_IobaseAddon + 4);
- /* initialise end of dma interrupt AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI) */
- outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 |
- APCI3120_ENABLE_WRITE_TC_INT),
- devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
-
- }
- if (samplesinbuf) {
- v_APCI3120_InterruptDmaMoveBlock16bit(dev, s,
- devpriv->ul_DmaBufferVirtual[devpriv->
- ui_DmaActualBuffer], samplesinbuf);
-
- if (!(cmd->flags & CMDF_WAKE_EOS)) {
- s->async->events |= COMEDI_CB_EOS;
- comedi_event(dev, s);
- }
- }
- if (cmd->stop_src == TRIG_COUNT)
- if (devpriv->ui_AiActualScan >= cmd->stop_arg) {
- /* all data sampled */
- apci3120_cancel(dev, s);
- s->async->events |= COMEDI_CB_EOA;
- comedi_event(dev, s);
- return;
- }
-
- if (devpriv->b_DmaDoubleBuffer) { /* switch dma buffers */
- devpriv->ui_DmaActualBuffer = 1 - devpriv->ui_DmaActualBuffer;
- } else {
- /*
- * restart DMA if is not used double buffering
- * ADDED REINITIALISE THE DMA
- */
- ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO;
- outl(ui_Tmp, devpriv->i_IobaseAddon + AMCC_OP_REG_AGCSTS);
-
- /* changed since 16 bit interface for add on */
- outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
- outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,
- devpriv->i_IobaseAddon + 2);
- outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
- outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2);
- /*
- * A2P FIFO MANAGEMENT
- * A2P fifo reset & transfer control enable
- */
- outl(APCI3120_A2P_FIFO_MANAGEMENT,
- devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR);
-
- var = devpriv->ul_DmaBufferHw[0];
- low_word = var & 0xffff;
- var = devpriv->ul_DmaBufferHw[0];
- high_word = var / 65536;
- outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
- outw(low_word, devpriv->i_IobaseAddon + 2);
- outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
- outw(high_word, devpriv->i_IobaseAddon + 2);
-
- var = devpriv->ui_DmaBufferUsesize[0];
- low_word = var & 0xffff; /* changed */
- var = devpriv->ui_DmaBufferUsesize[0];
- high_word = var / 65536;
- outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0);
- outw(low_word, devpriv->i_IobaseAddon + 2);
- outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0);
- outw(high_word, devpriv->i_IobaseAddon + 2);
-
- /*
- * To configure A2P FIFO
- * ENABLE A2P FIFO WRITE AND ENABLE AMWEN
- * AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
- */
- outw(3, devpriv->i_IobaseAddon + 4);
- /* initialise end of dma interrupt AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI) */
- outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 |
- APCI3120_ENABLE_WRITE_TC_INT),
- devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
- }
-}
-
-/*
- * This function handles EOS interrupt.
- * This function copies the acquired data(from FIFO) to Comedi buffer.
- */
-static int apci3120_interrupt_handle_eos(struct comedi_device *dev)
-{
- struct addi_private *devpriv = dev->private;
- struct comedi_subdevice *s = dev->read_subdev;
- int n_chan, i;
- int err = 1;
-
- n_chan = devpriv->ui_AiNbrofChannels;
-
- for (i = 0; i < n_chan; i++)
- err &= comedi_buf_put(s, inw(dev->iobase + 0));
-
- s->async->events |= COMEDI_CB_EOS;
-
- if (err == 0)
- s->async->events |= COMEDI_CB_OVERFLOW;
-
- comedi_event(dev, s);
-
- return 0;
-}
-
-static void apci3120_interrupt(int irq, void *d)
-{
- struct comedi_device *dev = d;
- struct addi_private *devpriv = dev->private;
- struct comedi_subdevice *s = dev->read_subdev;
- unsigned short int_daq;
- unsigned int int_amcc, ui_Check, i;
- unsigned short us_TmpValue;
- unsigned char b_DummyRead;
-
- ui_Check = 1;
-
- int_daq = inw(dev->iobase + APCI3120_RD_STATUS) & 0xf000; /* get IRQ reasons */
- int_amcc = inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR); /* get AMCC int register */
-
- if ((!int_daq) && (!(int_amcc & ANY_S593X_INT))) {
- dev_err(dev->class_dev, "IRQ from unknown source\n");
- return;
- }
-
- outl(int_amcc | 0x00ff0000, devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR); /* shutdown IRQ reasons in AMCC */
-
- int_daq = (int_daq >> 12) & 0xF;
-
- if (devpriv->b_ExttrigEnable == APCI3120_ENABLE) {
- /* Disable ext trigger */
- apci3120_exttrig_disable(dev);
- devpriv->b_ExttrigEnable = APCI3120_DISABLE;
- }
- /* clear the timer 2 interrupt */
- inb(devpriv->i_IobaseAmcc + APCI3120_TIMER_STATUS_REGISTER);
-
- if (int_amcc & MASTER_ABORT_INT)
- dev_err(dev->class_dev, "AMCC IRQ - MASTER DMA ABORT!\n");
- if (int_amcc & TARGET_ABORT_INT)
- dev_err(dev->class_dev, "AMCC IRQ - TARGET DMA ABORT!\n");
-
- /* Ckeck if EOC interrupt */
- if (((int_daq & 0x8) == 0)
- && (devpriv->b_InterruptMode == APCI3120_EOC_MODE)) {
- if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) {
-
- /* Read the AI Value */
- devpriv->ui_AiReadData[0] =
- (unsigned int) inw(devpriv->iobase + 0);
- devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
- send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */
- } else {
- /* Disable EOC Interrupt */
- devpriv->b_ModeSelectRegister =
- devpriv->
- b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT;
- outb(devpriv->b_ModeSelectRegister,
- devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
-
- }
- }
-
- /* Check If EOS interrupt */
- if ((int_daq & 0x2) && (devpriv->b_InterruptMode == APCI3120_EOS_MODE)) {
-
- if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) { /* enable this in without DMA ??? */
-
- if (devpriv->ai_running) {
- ui_Check = 0;
- apci3120_interrupt_handle_eos(dev);
- devpriv->ui_AiActualScan++;
- devpriv->b_ModeSelectRegister =
- devpriv->
- b_ModeSelectRegister |
- APCI3120_ENABLE_EOS_INT;
- outb(devpriv->b_ModeSelectRegister,
- dev->iobase +
- APCI3120_WRITE_MODE_SELECT);
- } else {
- ui_Check = 0;
- for (i = 0; i < devpriv->ui_AiNbrofChannels;
- i++) {
- us_TmpValue = inw(devpriv->iobase + 0);
- devpriv->ui_AiReadData[i] =
- (unsigned int) us_TmpValue;
- }
- devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
- devpriv->b_InterruptMode = APCI3120_EOC_MODE;
-
- send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */
-
- }
-
- } else {
- devpriv->b_ModeSelectRegister =
- devpriv->
- b_ModeSelectRegister & APCI3120_DISABLE_EOS_INT;
- outb(devpriv->b_ModeSelectRegister,
- dev->iobase + APCI3120_WRITE_MODE_SELECT);
- devpriv->b_EocEosInterrupt = APCI3120_DISABLE; /* Default settings */
- devpriv->b_InterruptMode = APCI3120_EOC_MODE;
- }
-
- }
- /* Timer2 interrupt */
- if (int_daq & 0x1) {
-
- switch (devpriv->b_Timer2Mode) {
- case APCI3120_COUNTER:
- devpriv->b_ModeSelectRegister =
- devpriv->
- b_ModeSelectRegister & APCI3120_DISABLE_EOS_INT;
- outb(devpriv->b_ModeSelectRegister,
- dev->iobase + APCI3120_WRITE_MODE_SELECT);
-
- /* stop timer 2 */
- devpriv->us_OutputRegister =
- devpriv->
- us_OutputRegister & APCI3120_DISABLE_ALL_TIMER;
- outw(devpriv->us_OutputRegister,
- dev->iobase + APCI3120_WR_ADDRESS);
-
- /* stop timer 0 and timer 1 */
- apci3120_cancel(dev, s);
-
- /* UPDATE-0.7.57->0.7.68comedi_done(dev,s); */
- s->async->events |= COMEDI_CB_EOA;
- comedi_event(dev, s);
-
- break;
-
- case APCI3120_TIMER:
-
- /* Send a signal to from kernel to user space */
- send_sig(SIGIO, devpriv->tsk_Current, 0);
- break;
-
- case APCI3120_WATCHDOG:
-
- /* Send a signal to from kernel to user space */
- send_sig(SIGIO, devpriv->tsk_Current, 0);
- break;
-
- default:
-
- /* disable Timer Interrupt */
- devpriv->b_ModeSelectRegister =
- devpriv->
- b_ModeSelectRegister &
- APCI3120_DISABLE_TIMER_INT;
-
- outb(devpriv->b_ModeSelectRegister,
- dev->iobase + APCI3120_WRITE_MODE_SELECT);
-
- }
-
- b_DummyRead = inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
-
- }
-
- if ((int_daq & 0x4) && (devpriv->b_InterruptMode == APCI3120_DMA_MODE)) {
- if (devpriv->ai_running) {
-
- /* Clear Timer Write TC int */
- outl(APCI3120_CLEAR_WRITE_TC_INT,
- devpriv->i_IobaseAmcc +
- APCI3120_AMCC_OP_REG_INTCSR);
-
- /* Clears the timer status register */
- inw(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
- /* do some data transfer */
- apci3120_interrupt_dma(irq, d);
- } else {
- /* Stops the Timer */
- outw(devpriv->
- us_OutputRegister & APCI3120_DISABLE_TIMER0 &
- APCI3120_DISABLE_TIMER1,
- dev->iobase + APCI3120_WR_ADDRESS);
- }
-
- }
-}
-
-/*
- * Configure Timer 2
- *
- * data[0] = TIMER configure as timer
- * = WATCHDOG configure as watchdog
- * data[1] = Timer constant
- * data[2] = Timer2 interrupt (1)enable or(0) disable
- */
-static int apci3120_config_insn_timer(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- const struct addi_board *this_board = dev->board_ptr;
- struct addi_private *devpriv = dev->private;
- unsigned int ui_Timervalue2;
- unsigned short us_TmpValue;
- unsigned char b_Tmp;
-
- if (!data[1])
- dev_err(dev->class_dev, "No timer constant!\n");
-
- devpriv->b_Timer2Interrupt = (unsigned char) data[2]; /* save info whether to enable or disable interrupt */
-
- ui_Timervalue2 = data[1] / 1000; /* convert nano seconds to u seconds */
-
- us_TmpValue = (unsigned short) inw(devpriv->iobase + APCI3120_RD_STATUS);
-
- /*
- * EL250804: Testing if board APCI3120 have the new Quartz or if it
- * is an APCI3001 and calculate the time value to set in the timer
- */
- if ((us_TmpValue & 0x00B0) == 0x00B0
- || !strcmp(this_board->pc_DriverName, "apci3001")) {
- /* Calculate the time value to set in the timer */
- ui_Timervalue2 = ui_Timervalue2 / 50;
- } else {
- /* Calculate the time value to set in the timer */
- ui_Timervalue2 = ui_Timervalue2 / 70;
- }
-
- /* Reset gate 2 of Timer 2 to disable it (Set Bit D14 to 0) */
- devpriv->us_OutputRegister =
- devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER2;
- outw(devpriv->us_OutputRegister, devpriv->iobase + APCI3120_WR_ADDRESS);
-
- /* Disable TIMER Interrupt */
- devpriv->b_ModeSelectRegister =
- devpriv->
- b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT & 0xEF;
-
- /* Disable Eoc and Eos Interrupts */
- devpriv->b_ModeSelectRegister =
- devpriv->
- b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT &
- APCI3120_DISABLE_EOS_INT;
- outb(devpriv->b_ModeSelectRegister,
- devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
- if (data[0] == APCI3120_TIMER) { /* initialize timer */
- /* Set the Timer 2 in mode 2(Timer) */
- devpriv->b_TimerSelectMode =
- (devpriv->
- b_TimerSelectMode & 0x0F) | APCI3120_TIMER_2_MODE_2;
- outb(devpriv->b_TimerSelectMode,
- devpriv->iobase + APCI3120_TIMER_CRT1);
-
- /*
- * Configure the timer 2 for writing the LOW unsigned short of timer
- * is Delay value You must make a b_tmp variable with
- * DigitalOutPutRegister because at Address_1+APCI3120_TIMER_CRT0
- * you can set the digital output and configure the timer 2,and if
- * you don't make this, digital output are erase (Set to 0)
- */
-
- /* Writing LOW unsigned short */
- b_Tmp = ((devpriv->
- b_DigitalOutputRegister) & 0xF0) |
- APCI3120_SELECT_TIMER_2_LOW_WORD;
- outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
- outw(ui_Timervalue2 & 0xffff,
- devpriv->iobase + APCI3120_TIMER_VALUE);
-
- /* Writing HIGH unsigned short */
- b_Tmp = ((devpriv->
- b_DigitalOutputRegister) & 0xF0) |
- APCI3120_SELECT_TIMER_2_HIGH_WORD;
- outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
- outw((ui_Timervalue2 >> 16) & 0xffff,
- devpriv->iobase + APCI3120_TIMER_VALUE);
- /* timer2 in Timer mode enabled */
- devpriv->b_Timer2Mode = APCI3120_TIMER;
-
- } else { /* Initialize Watch dog */
-
- /* Set the Timer 2 in mode 5(Watchdog) */
- devpriv->b_TimerSelectMode =
- (devpriv->
- b_TimerSelectMode & 0x0F) | APCI3120_TIMER_2_MODE_5;
- outb(devpriv->b_TimerSelectMode,
- devpriv->iobase + APCI3120_TIMER_CRT1);
-
- /*
- * Configure the timer 2 for writing the LOW unsigned short of timer
- * is Delay value You must make a b_tmp variable with
- * DigitalOutPutRegister because at Address_1+APCI3120_TIMER_CRT0
- * you can set the digital output and configure the timer 2,and if
- * you don't make this, digital output are erase (Set to 0)
- */
-
- /* Writing LOW unsigned short */
- b_Tmp = ((devpriv->
- b_DigitalOutputRegister) & 0xF0) |
- APCI3120_SELECT_TIMER_2_LOW_WORD;
- outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
- outw(ui_Timervalue2 & 0xffff,
- devpriv->iobase + APCI3120_TIMER_VALUE);
-
- /* Writing HIGH unsigned short */
- b_Tmp = ((devpriv->
- b_DigitalOutputRegister) & 0xF0) |
- APCI3120_SELECT_TIMER_2_HIGH_WORD;
- outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
-
- outw((ui_Timervalue2 >> 16) & 0xffff,
- devpriv->iobase + APCI3120_TIMER_VALUE);
- /* watchdog enabled */
- devpriv->b_Timer2Mode = APCI3120_WATCHDOG;
-
- }
-
- return insn->n;
-
-}
-
-/*
- * To start and stop the timer
- *
- * data[0] = 1 (start)
- * = 0 (stop)
- * = 2 (write new value)
- * data[1] = new value
- *
- * devpriv->b_Timer2Mode = 0 DISABLE
- * = 1 Timer
- * = 2 Watch dog
- */
-static int apci3120_write_insn_timer(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- const struct addi_board *this_board = dev->board_ptr;
- struct addi_private *devpriv = dev->private;
- unsigned int ui_Timervalue2 = 0;
- unsigned short us_TmpValue;
- unsigned char b_Tmp;
-
- if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG)
- && (devpriv->b_Timer2Mode != APCI3120_TIMER)) {
- dev_err(dev->class_dev, "timer2 not configured\n");
- return -EINVAL;
- }
-
- if (data[0] == 2) { /* write new value */
- if (devpriv->b_Timer2Mode != APCI3120_TIMER) {
- dev_err(dev->class_dev,
- "timer2 not configured in TIMER MODE\n");
- return -EINVAL;
- }
-
- if (data[1])
- ui_Timervalue2 = data[1];
- else
- ui_Timervalue2 = 0;
- }
-
- switch (data[0]) {
- case APCI3120_START:
-
- /* Reset FC_TIMER BIT */
- inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER);
- if (devpriv->b_Timer2Mode == APCI3120_TIMER) { /* start timer */
- /* Enable Timer */
- devpriv->b_ModeSelectRegister =
- devpriv->b_ModeSelectRegister & 0x0B;
- } else { /* start watch dog */
- /* Enable WatchDog */
- devpriv->b_ModeSelectRegister =
- (devpriv->
- b_ModeSelectRegister & 0x0B) |
- APCI3120_ENABLE_WATCHDOG;
- }
-
- /* enable disable interrupt */
- if ((devpriv->b_Timer2Interrupt) == APCI3120_ENABLE) {
-
- devpriv->b_ModeSelectRegister =
- devpriv->
- b_ModeSelectRegister |
- APCI3120_ENABLE_TIMER_INT;
- /* save the task structure to pass info to user */
- devpriv->tsk_Current = current;
- } else {
-
- devpriv->b_ModeSelectRegister =
- devpriv->
- b_ModeSelectRegister &
- APCI3120_DISABLE_TIMER_INT;
- }
- outb(devpriv->b_ModeSelectRegister,
- devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
-
- if (devpriv->b_Timer2Mode == APCI3120_TIMER) { /* start timer */
- /* For Timer mode is Gate2 must be activated timer started */
- devpriv->us_OutputRegister =
- devpriv->
- us_OutputRegister | APCI3120_ENABLE_TIMER2;
- outw(devpriv->us_OutputRegister,
- devpriv->iobase + APCI3120_WR_ADDRESS);
- }
-
- break;
-
- case APCI3120_STOP:
- if (devpriv->b_Timer2Mode == APCI3120_TIMER) {
- /* Disable timer */
- devpriv->b_ModeSelectRegister =
- devpriv->
- b_ModeSelectRegister &
- APCI3120_DISABLE_TIMER_COUNTER;
- } else {
- /* Disable WatchDog */
- devpriv->b_ModeSelectRegister =
- devpriv->
- b_ModeSelectRegister &
- APCI3120_DISABLE_WATCHDOG;
- }
- /* Disable timer interrupt */
- devpriv->b_ModeSelectRegister =
- devpriv->
- b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT;
-
- /* Write above states to register */
- outb(devpriv->b_ModeSelectRegister,
- devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
-
- /* Reset Gate 2 */
- devpriv->us_OutputRegister =
- devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER_INT;
- outw(devpriv->us_OutputRegister,
- devpriv->iobase + APCI3120_WR_ADDRESS);
-
- /* Reset FC_TIMER BIT */
- inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER);
-
- break;
-
- case 2: /* write new value to Timer */
- if (devpriv->b_Timer2Mode != APCI3120_TIMER) {
- dev_err(dev->class_dev,
- "timer2 not configured in TIMER MODE\n");
- return -EINVAL;
- }
- us_TmpValue =
- (unsigned short) inw(devpriv->iobase + APCI3120_RD_STATUS);
-
- /*
- * EL250804: Testing if board APCI3120 have the new Quartz or if it
- * is an APCI3001 and calculate the time value to set in the timer
- */
- if ((us_TmpValue & 0x00B0) == 0x00B0
- || !strcmp(this_board->pc_DriverName, "apci3001")) {
- /* Calculate the time value to set in the timer */
- ui_Timervalue2 = ui_Timervalue2 / 50;
- } else {
- /* Calculate the time value to set in the timer */
- ui_Timervalue2 = ui_Timervalue2 / 70;
- }
- /* Writing LOW unsigned short */
- b_Tmp = ((devpriv->
- b_DigitalOutputRegister) & 0xF0) |
- APCI3120_SELECT_TIMER_2_LOW_WORD;
- outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
-
- outw(ui_Timervalue2 & 0xffff,
- devpriv->iobase + APCI3120_TIMER_VALUE);
-
- /* Writing HIGH unsigned short */
- b_Tmp = ((devpriv->
- b_DigitalOutputRegister) & 0xF0) |
- APCI3120_SELECT_TIMER_2_HIGH_WORD;
- outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
-
- outw((ui_Timervalue2 >> 16) & 0xffff,
- devpriv->iobase + APCI3120_TIMER_VALUE);
-
- break;
- default:
- return -EINVAL; /* Not a valid input */
- }
-
- return insn->n;
-}
-
-/*
- * Read the Timer value
- *
- * for Timer: data[0]= Timer constant
- *
- * for watchdog: data[0] = 0 (still running)
- * = 1 (run down)
- */
-static int apci3120_read_insn_timer(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned char b_Tmp;
- unsigned short us_TmpValue, us_TmpValue_2, us_StatusValue;
-
- if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG)
- && (devpriv->b_Timer2Mode != APCI3120_TIMER)) {
- dev_err(dev->class_dev, "timer2 not configured\n");
- }
- if (devpriv->b_Timer2Mode == APCI3120_TIMER) {
-
- /* Read the LOW unsigned short of Timer 2 register */
- b_Tmp = ((devpriv->
- b_DigitalOutputRegister) & 0xF0) |
- APCI3120_SELECT_TIMER_2_LOW_WORD;
- outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
-
- us_TmpValue = inw(devpriv->iobase + APCI3120_TIMER_VALUE);
-
- /* Read the HIGH unsigned short of Timer 2 register */
- b_Tmp = ((devpriv->
- b_DigitalOutputRegister) & 0xF0) |
- APCI3120_SELECT_TIMER_2_HIGH_WORD;
- outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
-
- us_TmpValue_2 = inw(devpriv->iobase + APCI3120_TIMER_VALUE);
-
- /* combining both words */
- data[0] = (unsigned int) ((us_TmpValue) | ((us_TmpValue_2) << 16));
-
- } else { /* Read watch dog status */
-
- us_StatusValue = inw(devpriv->iobase + APCI3120_RD_STATUS);
- us_StatusValue =
- ((us_StatusValue & APCI3120_FC_TIMER) >> 12) & 1;
- if (us_StatusValue == 1) {
- /* RESET FC_TIMER BIT */
- inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER);
- }
- data[0] = us_StatusValue; /* when data[0] = 1 then the watch dog has rundown */
- }
- return insn->n;
-}
-
-static int apci3120_di_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 val;
-
- /* the input channels are bits 11:8 of the status reg */
- val = inw(devpriv->iobase + APCI3120_RD_STATUS);
- data[1] = (val >> 8) & 0xf;
-
- return insn->n;
-}
-
-static int apci3120_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
-
- if (comedi_dio_update_state(s, data)) {
- /* The do channels are bits 7:4 of the do register */
- devpriv->b_DigitalOutputRegister = s->state << 4;
-
- outb(devpriv->b_DigitalOutputRegister,
- devpriv->iobase + APCI3120_DIGITAL_OUTPUT);
- }
-
- data[1] = s->state;
-
- return insn->n;
-}
-
-static int apci3120_ao_insn_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int ui_Range, ui_Channel;
- unsigned short us_TmpValue;
-
- ui_Range = CR_RANGE(insn->chanspec);
- ui_Channel = CR_CHAN(insn->chanspec);
-
- if (ui_Range) { /* if 1 then unipolar */
-
- if (data[0] != 0)
- data[0] =
- ((((ui_Channel & 0x03) << 14) & 0xC000) | (1 <<
- 13) | (data[0] + 8191));
- else
- data[0] =
- ((((ui_Channel & 0x03) << 14) & 0xC000) | (1 <<
- 13) | 8192);
-
- } else { /* if 0 then bipolar */
- data[0] =
- ((((ui_Channel & 0x03) << 14) & 0xC000) | (0 << 13) |
- data[0]);
-
- }
-
- do { /* Waiting of DA_READY BIT */
- us_TmpValue =
- ((unsigned short) inw(devpriv->iobase +
- APCI3120_RD_STATUS)) & 0x0001;
- } while (us_TmpValue != 0x0001);
-
- if (ui_Channel <= 3)
- /*
- * for channel 0-3 out at the register 1 (wrDac1-8) data[i]
- * typecasted to ushort since word write is to be done
- */
- outw((unsigned short) data[0],
- devpriv->iobase + APCI3120_ANALOG_OUTPUT_1);
- else
- /*
- * for channel 4-7 out at the register 2 (wrDac5-8) data[i]
- * typecasted to ushort since word write is to be done
- */
- outw((unsigned short) data[0],
- devpriv->iobase + APCI3120_ANALOG_OUTPUT_2);
-
- return insn->n;
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
deleted file mode 100644
index 5e321f91172f..000000000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+++ /dev/null
@@ -1,3003 +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.
-
-@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-3200 | Compiler : GCC |
- | Module name : hwdrv_apci3200.c| Version : 2.96 |
- +-------------------------------+---------------------------------------+
- | Project manager: Eric Stolz | Date : 02/12/2002 |
- +-------------------------------+---------------------------------------+
- | Description : Hardware Layer Access For APCI-3200 |
- +-----------------------------------------------------------------------+
- | UPDATES |
- +----------+-----------+------------------------------------------------+
- | Date | Author | Description of updates |
- +----------+-----------+------------------------------------------------+
- | 02.07.04 | J. Krauth | Modification from the driver in order to |
- | | | correct some errors when using several boards. |
- | | | |
- | | | |
- +----------+-----------+------------------------------------------------+
- | 26.10.04 | J. Krauth | - Update for COMEDI 0.7.68 |
- | | | - Read eeprom value |
- | | | - Append APCI-3300 |
- +----------+-----------+------------------------------------------------+
-*/
-
-/* Card Specific information */
-/* #define APCI3200_ADDRESS_RANGE 264 */
-
-/* Analog Input related Defines */
-#define APCI3200_AI_OFFSET_GAIN 0
-#define APCI3200_AI_SC_TEST 4
-#define APCI3200_AI_IRQ 8
-#define APCI3200_AI_AUTOCAL 12
-#define APCI3200_RELOAD_CONV_TIME_VAL 32
-#define APCI3200_CONV_TIME_TIME_BASE 36
-#define APCI3200_RELOAD_DELAY_TIME_VAL 40
-#define APCI3200_DELAY_TIME_TIME_BASE 44
-#define APCI3200_AI_MODULE1 0
-#define APCI3200_AI_MODULE2 64
-#define APCI3200_AI_MODULE3 128
-#define APCI3200_AI_MODULE4 192
-#define TRUE 1
-#define FALSE 0
-#define APCI3200_AI_EOSIRQ 16
-#define APCI3200_AI_EOS 20
-#define APCI3200_AI_CHAN_ID 24
-#define APCI3200_AI_CHAN_VAL 28
-#define ANALOG_INPUT 0
-#define TEMPERATURE 1
-#define RESISTANCE 2
-
-#define ENABLE_EXT_TRIG 1
-#define ENABLE_EXT_GATE 2
-#define ENABLE_EXT_TRIG_GATE 3
-
-#define APCI3200_MAXVOLT 2.5
-#define ADDIDATA_GREATER_THAN_TEST 0
-#define ADDIDATA_LESS_THAN_TEST 1
-
-#define ADDIDATA_UNIPOLAR 1
-#define ADDIDATA_BIPOLAR 2
-
-#define MAX_MODULE 4
-
-/* ANALOG INPUT RANGE */
-static const struct comedi_lrange range_apci3200_ai = {
- 8, {
- BIP_RANGE(10),
- BIP_RANGE(5),
- BIP_RANGE(2),
- BIP_RANGE(1),
- UNI_RANGE(10),
- UNI_RANGE(5),
- UNI_RANGE(2),
- UNI_RANGE(1)
- }
-};
-
-static const struct comedi_lrange range_apci3300_ai = {
- 4, {
- UNI_RANGE(10),
- UNI_RANGE(5),
- UNI_RANGE(2),
- UNI_RANGE(1)
- }
-};
-
-int MODULE_NO;
-struct {
- int i_Gain;
- int i_Polarity;
- int i_OffsetRange;
- int i_Coupling;
- int i_SingleDiff;
- int i_AutoCalibration;
- unsigned int ui_ReloadValue;
- unsigned int ui_TimeUnitReloadVal;
- int i_Interrupt;
- int i_ModuleSelection;
-} Config_Parameters_Module1, Config_Parameters_Module2,
- Config_Parameters_Module3, Config_Parameters_Module4;
-
-
-struct str_ADDIDATA_RTDStruct {
- unsigned int ul_NumberOfValue;
- unsigned int *pul_ResistanceValue;
- unsigned int *pul_TemperatureValue;
-};
-
-struct str_Module {
- unsigned long ul_CurrentSourceCJC;
- unsigned long ul_CurrentSource[5];
- unsigned long ul_GainFactor[8]; /* Gain Factor */
- unsigned int w_GainValue[10];
-};
-
-struct str_BoardInfos {
-
- int i_CJCAvailable;
- int i_CJCPolarity;
- int i_CJCGain;
- int i_InterruptFlag;
- int i_ADDIDATAPolarity;
- int i_ADDIDATAGain;
- int i_AutoCalibration;
- int i_ADDIDATAConversionTime;
- int i_ADDIDATAConversionTimeUnit;
- int i_ADDIDATAType;
- int i_ChannelNo;
- int i_ChannelCount;
- int i_ScanType;
- int i_FirstChannel;
- int i_LastChannel;
- int i_Sum;
- int i_Offset;
- unsigned int ui_Channel_num;
- int i_Count;
- int i_Initialised;
- unsigned int ui_InterruptChannelValue[144]; /* Buffer */
- unsigned char b_StructInitialized;
- /* 7 is the maximal number of channels */
- unsigned int ui_ScanValueArray[7 + 12];
-
- int i_ConnectionType;
- int i_NbrOfModule;
- struct str_Module s_Module[MAX_MODULE];
-};
-
-/* BEGIN JK 06.07.04: Management of sevrals boards */
-/*
- int i_CJCAvailable=1;
- int i_CJCPolarity=0;
- int i_CJCGain=2;/* changed from 0 to 2 */
- int i_InterruptFlag=0;
- int i_ADDIDATAPolarity;
- int i_ADDIDATAGain;
- int i_AutoCalibration=0; /* : auto calibration */
- int i_ADDIDATAConversionTime;
- int i_ADDIDATAConversionTimeUnit;
- int i_ADDIDATAType;
- int i_ChannelNo;
- int i_ChannelCount=0;
- int i_ScanType;
- int i_FirstChannel;
- int i_LastChannel;
- int i_Sum=0;
- int i_Offset;
- unsigned int ui_Channel_num=0;
- static int i_Count=0;
- int i_Initialised=0;
- unsigned int ui_InterruptChannelValue[96]; /* Buffer */
-*/
-struct str_BoardInfos s_BoardInfos[100]; /* 100 will be the max number of boards to be used */
-/* END JK 06.07.04: Management of sevrals boards */
-
-#define AMCC_OP_REG_MCSR 0x3c
-#define EEPROM_BUSY 0x80000000
-#define NVCMD_LOAD_LOW (0x4 << 5) /* nvRam load low command */
-#define NVCMD_LOAD_HIGH (0x5 << 5) /* nvRam load high command */
-#define NVCMD_BEGIN_READ (0x7 << 5) /* nvRam begin read command */
-#define NVCMD_BEGIN_WRITE (0x6 << 5) /* EEPROM begin write command */
-
-static int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
- unsigned int dw_PCIBoardEepromAddress,
- unsigned short w_EepromStartAddress,
- unsigned short *pw_DataRead)
-{
- unsigned int dw_eeprom_busy = 0;
- int i_Counter = 0;
- int i_WordCounter;
- int i;
- unsigned char pb_ReadByte[1];
- unsigned char b_ReadLowByte = 0;
- unsigned char b_ReadHighByte = 0;
- unsigned char b_SelectedAddressLow = 0;
- unsigned char b_SelectedAddressHigh = 0;
- unsigned short w_ReadWord = 0;
-
- for (i_WordCounter = 0; i_WordCounter < i_NbOfWordsToRead;
- i_WordCounter++) {
- do {
- dw_eeprom_busy =
- inl(dw_PCIBoardEepromAddress +
- AMCC_OP_REG_MCSR);
- dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
- } while (dw_eeprom_busy == EEPROM_BUSY);
-
- for (i_Counter = 0; i_Counter < 2; i_Counter++) {
- b_SelectedAddressLow = (w_EepromStartAddress + i_Counter) % 256; /* Read the low 8 bit part */
- b_SelectedAddressHigh = (w_EepromStartAddress + i_Counter) / 256; /* Read the high 8 bit part */
-
- /* Select the load low address mode */
- outb(NVCMD_LOAD_LOW,
- dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
- 3);
-
- /* Wait on busy */
- do {
- dw_eeprom_busy =
- inl(dw_PCIBoardEepromAddress +
- AMCC_OP_REG_MCSR);
- dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
- } while (dw_eeprom_busy == EEPROM_BUSY);
-
- /* Load the low address */
- outb(b_SelectedAddressLow,
- dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
- 2);
-
- /* Wait on busy */
- do {
- dw_eeprom_busy =
- inl(dw_PCIBoardEepromAddress +
- AMCC_OP_REG_MCSR);
- dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
- } while (dw_eeprom_busy == EEPROM_BUSY);
-
- /* Select the load high address mode */
- outb(NVCMD_LOAD_HIGH,
- dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
- 3);
-
- /* Wait on busy */
- do {
- dw_eeprom_busy =
- inl(dw_PCIBoardEepromAddress +
- AMCC_OP_REG_MCSR);
- dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
- } while (dw_eeprom_busy == EEPROM_BUSY);
-
- /* Load the high address */
- outb(b_SelectedAddressHigh,
- dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
- 2);
-
- /* Wait on busy */
- do {
- dw_eeprom_busy =
- inl(dw_PCIBoardEepromAddress +
- AMCC_OP_REG_MCSR);
- dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
- } while (dw_eeprom_busy == EEPROM_BUSY);
-
- /* Select the READ mode */
- outb(NVCMD_BEGIN_READ,
- dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
- 3);
-
- /* Wait on busy */
- do {
- dw_eeprom_busy =
- inl(dw_PCIBoardEepromAddress +
- AMCC_OP_REG_MCSR);
- dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
- } while (dw_eeprom_busy == EEPROM_BUSY);
-
- /* Read data into the EEPROM */
- *pb_ReadByte =
- inb(dw_PCIBoardEepromAddress +
- AMCC_OP_REG_MCSR + 2);
-
- /* Wait on busy */
- do {
- dw_eeprom_busy =
- inl(dw_PCIBoardEepromAddress +
- AMCC_OP_REG_MCSR);
- dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
- } while (dw_eeprom_busy == EEPROM_BUSY);
-
- /* Select the upper address part */
- if (i_Counter == 0)
- b_ReadLowByte = pb_ReadByte[0];
- else
- b_ReadHighByte = pb_ReadByte[0];
-
-
- /* Sleep */
- msleep(1);
-
- }
- w_ReadWord =
- (b_ReadLowByte | (((unsigned short)b_ReadHighByte) *
- 256));
-
- pw_DataRead[i_WordCounter] = w_ReadWord;
-
- w_EepromStartAddress += 2; /* to read the next word */
-
- } /* for (...) i_NbOfWordsToRead */
- return 0;
-}
-
-static void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAddress,
- struct str_BoardInfos *BoardInformations)
-{
- unsigned short w_AnalogInputMainHeaderAddress;
- unsigned short w_AnalogInputComponentAddress;
- unsigned short w_NumberOfModuls = 0;
- unsigned short w_CurrentSources[2];
- unsigned short w_ModulCounter = 0;
- unsigned short w_FirstHeaderSize = 0;
- unsigned short w_NumberOfInputs = 0;
- unsigned short w_CJCFlag = 0;
- unsigned short w_NumberOfGainValue = 0;
- unsigned short w_SingleHeaderAddress = 0;
- unsigned short w_SingleHeaderSize = 0;
- unsigned short w_Input = 0;
- unsigned short w_GainFactorAddress = 0;
- unsigned short w_GainFactorValue[2];
- unsigned short w_GainIndex = 0;
- unsigned short w_GainValue = 0;
-
- /*****************************************/
- /** Get the Analog input header address **/
- /*****************************************/
- i_AddiHeaderRW_ReadEeprom(1, /* i_NbOfWordsToRead */
- dw_PCIBoardEepromAddress, 0x116, /* w_EepromStartAddress: Analog input header address */
- &w_AnalogInputMainHeaderAddress);
-
- /*******************************************/
- /** Compute the real analog input address **/
- /*******************************************/
- w_AnalogInputMainHeaderAddress = w_AnalogInputMainHeaderAddress + 0x100;
-
- /******************************/
- /** Get the number of moduls **/
- /******************************/
- i_AddiHeaderRW_ReadEeprom(1, /* i_NbOfWordsToRead */
- dw_PCIBoardEepromAddress, w_AnalogInputMainHeaderAddress + 0x02, /* w_EepromStartAddress: Number of conponment */
- &w_NumberOfModuls);
-
- for (w_ModulCounter = 0; w_ModulCounter < w_NumberOfModuls;
- w_ModulCounter++) {
- /***********************************/
- /** Compute the component address **/
- /***********************************/
- w_AnalogInputComponentAddress =
- w_AnalogInputMainHeaderAddress +
- (w_FirstHeaderSize * w_ModulCounter) + 0x04;
-
- /****************************/
- /** Read first header size **/
- /****************************/
- i_AddiHeaderRW_ReadEeprom(1, /* i_NbOfWordsToRead */
- dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress, /* Address of the first header */
- &w_FirstHeaderSize);
-
- w_FirstHeaderSize = w_FirstHeaderSize >> 4;
-
- /***************************/
- /** Read number of inputs **/
- /***************************/
- i_AddiHeaderRW_ReadEeprom(1, /* i_NbOfWordsToRead */
- dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 0x06, /* Number of inputs for the first modul */
- &w_NumberOfInputs);
-
- w_NumberOfInputs = w_NumberOfInputs >> 4;
-
- /***********************/
- /** Read the CJC flag **/
- /***********************/
- i_AddiHeaderRW_ReadEeprom(1, /* i_NbOfWordsToRead */
- dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 0x08, /* CJC flag */
- &w_CJCFlag);
-
- w_CJCFlag = (w_CJCFlag >> 3) & 0x1; /* Get only the CJC flag */
-
- /*******************************/
- /** Read number of gain value **/
- /*******************************/
- i_AddiHeaderRW_ReadEeprom(1, /* i_NbOfWordsToRead */
- dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 0x44, /* Number of gain value */
- &w_NumberOfGainValue);
-
- w_NumberOfGainValue = w_NumberOfGainValue & 0xFF;
-
- /***********************************/
- /** Compute single header address **/
- /***********************************/
- w_SingleHeaderAddress =
- w_AnalogInputComponentAddress + 0x46 +
- (((w_NumberOfGainValue / 16) + 1) * 2) +
- (6 * w_NumberOfGainValue) +
- (4 * (((w_NumberOfGainValue / 16) + 1) * 2));
-
- /********************************************/
- /** Read current sources value for input 1 **/
- /********************************************/
- i_AddiHeaderRW_ReadEeprom(1, /* i_NbOfWordsToRead */
- dw_PCIBoardEepromAddress, w_SingleHeaderAddress, /* w_EepromStartAddress: Single header address */
- &w_SingleHeaderSize);
-
- w_SingleHeaderSize = w_SingleHeaderSize >> 4;
-
- /*************************************/
- /** Read gain factor for the module **/
- /*************************************/
- w_GainFactorAddress = w_AnalogInputComponentAddress;
-
- for (w_GainIndex = 0; w_GainIndex < w_NumberOfGainValue;
- w_GainIndex++) {
- /************************************/
- /** Read gain value for the module **/
- /************************************/
- i_AddiHeaderRW_ReadEeprom(1, /* i_NbOfWordsToRead */
- dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 70 + (2 * (1 + (w_NumberOfGainValue / 16))) + (0x02 * w_GainIndex), /* Gain value */
- &w_GainValue);
-
- BoardInformations->s_Module[w_ModulCounter].
- w_GainValue[w_GainIndex] = w_GainValue;
-
- /*************************************/
- /** Read gain factor for the module **/
- /*************************************/
- i_AddiHeaderRW_ReadEeprom(2, /* i_NbOfWordsToRead */
- dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 70 + ((2 * w_NumberOfGainValue) + (2 * (1 + (w_NumberOfGainValue / 16)))) + (0x04 * w_GainIndex), /* Gain factor */
- w_GainFactorValue);
-
- BoardInformations->s_Module[w_ModulCounter].
- ul_GainFactor[w_GainIndex] =
- (w_GainFactorValue[1] << 16) +
- w_GainFactorValue[0];
- }
-
- /***************************************************************/
- /** Read current source value for each channels of the module **/
- /***************************************************************/
- for (w_Input = 0; w_Input < w_NumberOfInputs; w_Input++) {
- /********************************************/
- /** Read current sources value for input 1 **/
- /********************************************/
- i_AddiHeaderRW_ReadEeprom(2, /* i_NbOfWordsToRead */
- dw_PCIBoardEepromAddress,
- (w_Input * w_SingleHeaderSize) +
- w_SingleHeaderAddress + 0x0C, w_CurrentSources);
-
- /************************************/
- /** Save the current sources value **/
- /************************************/
- BoardInformations->s_Module[w_ModulCounter].
- ul_CurrentSource[w_Input] =
- (w_CurrentSources[0] +
- ((w_CurrentSources[1] & 0xFFF) << 16));
- }
-
- /***************************************/
- /** Read the CJC current source value **/
- /***************************************/
- i_AddiHeaderRW_ReadEeprom(2, /* i_NbOfWordsToRead */
- dw_PCIBoardEepromAddress,
- (w_Input * w_SingleHeaderSize) + w_SingleHeaderAddress +
- 0x0C, w_CurrentSources);
-
- /************************************/
- /** Save the current sources value **/
- /************************************/
- BoardInformations->s_Module[w_ModulCounter].
- ul_CurrentSourceCJC =
- (w_CurrentSources[0] +
- ((w_CurrentSources[1] & 0xFFF) << 16));
- }
-}
-
-static int i_APCI3200_GetChannelCalibrationValue(struct comedi_device *dev,
- unsigned int ui_Channel_num,
- unsigned int *CJCCurrentSource,
- unsigned int *ChannelCurrentSource,
- unsigned int *ChannelGainFactor)
-{
- int i_DiffChannel = 0;
- int i_Module = 0;
-
- /* Test if single or differential mode */
- if (s_BoardInfos[dev->minor].i_ConnectionType == 1) {
- /* if diff */
-
- if (ui_Channel_num <= 1)
- i_DiffChannel = ui_Channel_num, i_Module = 0;
- else if ((ui_Channel_num >= 2) && (ui_Channel_num <= 3))
- i_DiffChannel = ui_Channel_num - 2, i_Module = 1;
- else if ((ui_Channel_num >= 4) && (ui_Channel_num <= 5))
- i_DiffChannel = ui_Channel_num - 4, i_Module = 2;
- else if ((ui_Channel_num >= 6) && (ui_Channel_num <= 7))
- i_DiffChannel = ui_Channel_num - 6, i_Module = 3;
-
- } else {
- /* if single */
- if ((ui_Channel_num == 0) || (ui_Channel_num == 1))
- i_DiffChannel = 0, i_Module = 0;
- else if ((ui_Channel_num == 2) || (ui_Channel_num == 3))
- i_DiffChannel = 1, i_Module = 0;
- else if ((ui_Channel_num == 4) || (ui_Channel_num == 5))
- i_DiffChannel = 0, i_Module = 1;
- else if ((ui_Channel_num == 6) || (ui_Channel_num == 7))
- i_DiffChannel = 1, i_Module = 1;
- else if ((ui_Channel_num == 8) || (ui_Channel_num == 9))
- i_DiffChannel = 0, i_Module = 2;
- else if ((ui_Channel_num == 10) || (ui_Channel_num == 11))
- i_DiffChannel = 1, i_Module = 2;
- else if ((ui_Channel_num == 12) || (ui_Channel_num == 13))
- i_DiffChannel = 0, i_Module = 3;
- else if ((ui_Channel_num == 14) || (ui_Channel_num == 15))
- i_DiffChannel = 1, i_Module = 3;
- }
-
- /* Test if thermocouple or RTD mode */
- *CJCCurrentSource =
- s_BoardInfos[dev->minor].s_Module[i_Module].ul_CurrentSourceCJC;
-
- *ChannelCurrentSource =
- s_BoardInfos[dev->minor].s_Module[i_Module].
- ul_CurrentSource[i_DiffChannel];
- /* } */
- /* } */
-
- /* Channle gain factor */
- *ChannelGainFactor =
- s_BoardInfos[dev->minor].s_Module[i_Module].
- ul_GainFactor[s_BoardInfos[dev->minor].i_ADDIDATAGain];
- /* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-
- return 0;
-}
-
-static int apci3200_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->i_IobaseReserved) & 0xf;
-
- return insn->n;
-}
-
-static int apci3200_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
-
- s->state = inl(devpriv->i_IobaseAddon) & 0xf;
-
- if (comedi_dio_update_state(s, data))
- outl(s->state, devpriv->i_IobaseAddon);
-
- data[1] = s->state;
-
- return insn->n;
-}
-
-static int i_APCI3200_Read1AnalogInputChannel(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int ui_EOC = 0;
- unsigned int ui_ChannelNo = 0;
- unsigned int ui_CommandRegister = 0;
-
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* ui_ChannelNo=i_ChannelNo; */
- ui_ChannelNo = s_BoardInfos[dev->minor].i_ChannelNo;
-
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /*********************************/
- /* Write the channel to configure */
- /*********************************/
- /* Begin JK 20.10.2004: Bad channel value is used when using differential mode */
- /* outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4); */
- /* outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4); */
- outl(0 | s_BoardInfos[dev->minor].i_ChannelNo,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x4);
- /* End JK 20.10.2004: Bad channel value is used when using differential mode */
-
- /*******************************/
- /* Set the convert timing unit */
- /*******************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
-
- /* outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); */
- outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
-
- /**************************/
- /* Set the convert timing */
- /**************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
-
- /* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
- outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
-
- /**************************************************************************/
- /* Set the start end stop index to the selected channel and set the start */
- /**************************************************************************/
-
- ui_CommandRegister = ui_ChannelNo | (ui_ChannelNo << 8) | 0x80000;
-
- /*Test if the interrupt is enable */
- if (s_BoardInfos[dev->minor].i_InterruptFlag == 1) {
- /* Enable the interrupt */
- ui_CommandRegister = ui_CommandRegister | 0x00100000;
- }
-
- /******************************/
- /* Write the command register */
- /******************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
-
- /* outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8); */
- outl(ui_CommandRegister,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
-
- /*Test if interrupt is enable */
- if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) {
- do {
- /*************************/
- /*Read the EOC Status bit */
- /*************************/
-
- /* ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; */
- ui_EOC = inl(devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 20) & 1;
-
- } while (ui_EOC != 1);
-
- /***************************************/
- /* Read the digital value of the input */
- /***************************************/
-
- /* data[0] = inl (devpriv->iobase+i_Offset + 28); */
- data[0] =
- inl(devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 28);
- /* END JK 06.07.04: Management of sevrals boards */
-
- }
- return 0;
-}
-
-static int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int ui_Temp = 0, ui_EOC = 0;
- unsigned int ui_CommandRegister = 0;
-
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /*********************************/
- /* Write the channel to configure */
- /*********************************/
- /* Begin JK 20.10.2004: This seems not necessary ! */
- /* outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4); */
- /* outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4); */
- /* End JK 20.10.2004: This seems not necessary ! */
-
- /*******************************/
- /* Set the convert timing unit */
- /*******************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); */
- outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
- /**************************/
- /* Set the convert timing */
- /**************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
- outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
- /*****************************/
- /*Read the calibration offset */
- /*****************************/
- /* ui_Temp = inl(devpriv->iobase+i_Offset + 12); */
- ui_Temp = inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
-
- /*********************************/
- /*Configure the Offset Conversion */
- /*********************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl((ui_Temp | 0x00020000), devpriv->iobase+i_Offset + 12); */
- outl((ui_Temp | 0x00020000),
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
- /*******************************/
- /*Initialise ui_CommandRegister */
- /*******************************/
-
- ui_CommandRegister = 0;
-
- /*Test if the interrupt is enable */
- if (s_BoardInfos[dev->minor].i_InterruptFlag == 1) {
- /*Enable the interrupt */
- ui_CommandRegister = ui_CommandRegister | 0x00100000;
- }
-
- /**********************/
- /*Start the conversion */
- /**********************/
- ui_CommandRegister = ui_CommandRegister | 0x00080000;
-
- /***************************/
- /*Write the command regiter */
- /***************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8); */
- outl(ui_CommandRegister,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
-
- /*Test if interrupt is enable */
- if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) {
- do {
- /*******************/
- /*Read the EOC flag */
- /*******************/
-
- /* ui_EOC = inl (devpriv->iobase+i_Offset + 20) & 1; */
- ui_EOC = inl(devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 20) & 1;
-
- } while (ui_EOC != 1);
-
- /**************************************************/
- /*Read the digital value of the calibration Offset */
- /**************************************************/
-
- /* data[0] = inl(devpriv->iobase+i_Offset+ 28); */
- data[0] =
- inl(devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 28);
- }
- return 0;
-}
-
-static int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int ui_EOC = 0;
- int ui_CommandRegister = 0;
-
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /*********************************/
- /* Write the channel to configure */
- /*********************************/
- /* Begin JK 20.10.2004: This seems not necessary ! */
- /* outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4); */
- /* outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4); */
- /* End JK 20.10.2004: This seems not necessary ! */
-
- /***************************/
- /*Read the calibration gain */
- /***************************/
- /*******************************/
- /* Set the convert timing unit */
- /*******************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); */
- outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
- /**************************/
- /* Set the convert timing */
- /**************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
- outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
- /*******************************/
- /*Configure the Gain Conversion */
- /*******************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(0x00040000 , devpriv->iobase+i_Offset + 12); */
- outl(0x00040000,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
-
- /*******************************/
- /*Initialise ui_CommandRegister */
- /*******************************/
-
- ui_CommandRegister = 0;
-
- /*Test if the interrupt is enable */
- if (s_BoardInfos[dev->minor].i_InterruptFlag == 1) {
- /*Enable the interrupt */
- ui_CommandRegister = ui_CommandRegister | 0x00100000;
- }
-
- /**********************/
- /*Start the conversion */
- /**********************/
-
- ui_CommandRegister = ui_CommandRegister | 0x00080000;
- /***************************/
- /*Write the command regiter */
- /***************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8); */
- outl(ui_CommandRegister,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
-
- /*Test if interrupt is enable */
- if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) {
- do {
-
- /*******************/
- /*Read the EOC flag */
- /*******************/
-
- /* ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; */
- ui_EOC = inl(devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 20) & 1;
-
- } while (ui_EOC != 1);
-
- /************************************************/
- /*Read the digital value of the calibration Gain */
- /************************************************/
-
- /* data[0] = inl(devpriv->iobase+i_Offset + 28); */
- data[0] =
- inl(devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 28);
-
- }
- return 0;
-}
-
-static int i_APCI3200_ReadCJCValue(struct comedi_device *dev,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int ui_EOC = 0;
- int ui_CommandRegister = 0;
-
- /******************************/
- /*Set the converting time unit */
- /******************************/
-
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
-
- /* outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); */
- outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
- /**************************/
- /* Set the convert timing */
- /**************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
-
- /* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
- outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
-
- /******************************/
- /*Configure the CJC Conversion */
- /******************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
-
- /* outl( 0x00000400 , devpriv->iobase+i_Offset + 4); */
- outl(0x00000400,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
- /*******************************/
- /*Initialise dw_CommandRegister */
- /*******************************/
- ui_CommandRegister = 0;
- /*Test if the interrupt is enable */
- if (s_BoardInfos[dev->minor].i_InterruptFlag == 1) {
- /*Enable the interrupt */
- ui_CommandRegister = ui_CommandRegister | 0x00100000;
- }
-
- /**********************/
- /*Start the conversion */
- /**********************/
-
- ui_CommandRegister = ui_CommandRegister | 0x00080000;
-
- /***************************/
- /*Write the command regiter */
- /***************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8); */
- outl(ui_CommandRegister,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
-
- /*Test if interrupt is enable */
- if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) {
- do {
-
- /*******************/
- /*Read the EOC flag */
- /*******************/
-
- /* ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; */
- ui_EOC = inl(devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 20) & 1;
-
- } while (ui_EOC != 1);
-
- /***********************************/
- /*Read the digital value of the CJC */
- /***********************************/
-
- /* data[0] = inl(devpriv->iobase+i_Offset + 28); */
- data[0] =
- inl(devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 28);
- }
- return 0;
-}
-
-static int i_APCI3200_ReadCJCCalOffset(struct comedi_device *dev,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int ui_EOC = 0;
- int ui_CommandRegister = 0;
-
- /*******************************************/
- /*Read calibration offset value for the CJC */
- /*******************************************/
- /*******************************/
- /* Set the convert timing unit */
- /*******************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); */
- outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
- /**************************/
- /* Set the convert timing */
- /**************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
- outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
- /******************************/
- /*Configure the CJC Conversion */
- /******************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(0x00000400 , devpriv->iobase+i_Offset + 4); */
- outl(0x00000400,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
- /*********************************/
- /*Configure the Offset Conversion */
- /*********************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(0x00020000, devpriv->iobase+i_Offset + 12); */
- outl(0x00020000,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
- /*******************************/
- /*Initialise ui_CommandRegister */
- /*******************************/
- ui_CommandRegister = 0;
- /*Test if the interrupt is enable */
- if (s_BoardInfos[dev->minor].i_InterruptFlag == 1) {
- /*Enable the interrupt */
- ui_CommandRegister = ui_CommandRegister | 0x00100000;
- }
-
- /**********************/
- /*Start the conversion */
- /**********************/
- ui_CommandRegister = ui_CommandRegister | 0x00080000;
- /***************************/
- /*Write the command regiter */
- /***************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(ui_CommandRegister,devpriv->iobase+i_Offset + 8); */
- outl(ui_CommandRegister,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
- if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) {
- do {
- /*******************/
- /*Read the EOC flag */
- /*******************/
- /* ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; */
- ui_EOC = inl(devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 20) & 1;
- } while (ui_EOC != 1);
-
- /**************************************************/
- /*Read the digital value of the calibration Offset */
- /**************************************************/
- /* data[0] = inl(devpriv->iobase+i_Offset + 28); */
- data[0] =
- inl(devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 28);
- }
- return 0;
-}
-
-static int i_APCI3200_ReadCJCCalGain(struct comedi_device *dev,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int ui_EOC = 0;
- int ui_CommandRegister = 0;
-
- /*******************************/
- /* Set the convert timing unit */
- /*******************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); */
- outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
- /**************************/
- /* Set the convert timing */
- /**************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
- outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
- /******************************/
- /*Configure the CJC Conversion */
- /******************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(0x00000400,devpriv->iobase+i_Offset + 4); */
- outl(0x00000400,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
- /*******************************/
- /*Configure the Gain Conversion */
- /*******************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(0x00040000,devpriv->iobase+i_Offset + 12); */
- outl(0x00040000,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
-
- /*******************************/
- /*Initialise dw_CommandRegister */
- /*******************************/
- ui_CommandRegister = 0;
- /*Test if the interrupt is enable */
- if (s_BoardInfos[dev->minor].i_InterruptFlag == 1) {
- /*Enable the interrupt */
- ui_CommandRegister = ui_CommandRegister | 0x00100000;
- }
- /**********************/
- /*Start the conversion */
- /**********************/
- ui_CommandRegister = ui_CommandRegister | 0x00080000;
- /***************************/
- /*Write the command regiter */
- /***************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(ui_CommandRegister ,devpriv->iobase+i_Offset + 8); */
- outl(ui_CommandRegister,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
- if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) {
- do {
- /*******************/
- /*Read the EOC flag */
- /*******************/
- /* ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; */
- ui_EOC = inl(devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 20) & 1;
- } while (ui_EOC != 1);
- /************************************************/
- /*Read the digital value of the calibration Gain */
- /************************************************/
- /* data[0] = inl (devpriv->iobase+i_Offset + 28); */
- data[0] =
- inl(devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 28);
- }
- return 0;
-}
-
-static int apci3200_reset(struct comedi_device *dev)
-{
- struct addi_private *devpriv = dev->private;
- int i_Temp;
- unsigned int dw_Dummy;
-
- /* i_InterruptFlag=0; */
- /* i_Initialised==0; */
- /* i_Count=0; */
- /* i_Sum=0; */
-
- s_BoardInfos[dev->minor].i_InterruptFlag = 0;
- s_BoardInfos[dev->minor].i_Initialised = 0;
- s_BoardInfos[dev->minor].i_Count = 0;
- s_BoardInfos[dev->minor].i_Sum = 0;
- s_BoardInfos[dev->minor].b_StructInitialized = 0;
-
- 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);
- outl(0, devpriv->i_IobaseAddon); /* Resets the output */
- /***************/
- /*Empty the buffer */
- /**************/
- for (i_Temp = 0; i_Temp <= 95; i_Temp++) {
- /* ui_InterruptChannelValue[i_Temp]=0; */
- s_BoardInfos[dev->minor].ui_InterruptChannelValue[i_Temp] = 0;
- } /* for(i_Temp=0;i_Temp<=95;i_Temp++) */
- /*****************************/
- /*Reset the START and IRQ bit */
- /*****************************/
- for (i_Temp = 0; i_Temp <= 192;) {
- while (((inl(devpriv->iobase + i_Temp + 12) >> 19) & 1) != 1) ;
- outl(0, devpriv->iobase + i_Temp + 8);
- i_Temp = i_Temp + 64;
- } /* for(i_Temp=0;i_Temp<=192;i_Temp+64) */
- return 0;
-}
-
-/*
- * Read value of the selected channel
- *
- * data[0] : Digital Value Of Input
- * data[1] : Calibration Offset Value
- * data[2] : Calibration Gain Value
- * data[3] : CJC value
- * data[4] : CJC offset value
- * data[5] : CJC gain value
- * data[6] : CJC current source from eeprom
- * data[7] : Channel current source from eeprom
- * data[8] : Channle gain factor from eeprom
- */
-static int apci3200_ai_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- unsigned int ui_DummyValue = 0;
- int i_ConvertCJCCalibration;
- int i = 0;
-
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* if(i_Initialised==0) */
- if (s_BoardInfos[dev->minor].i_Initialised == 0)
- /* END JK 06.07.04: Management of sevrals boards */
- {
- apci3200_reset(dev);
- return -EINVAL;
- } /* if(i_Initialised==0); */
-
- switch (insn->unused[0]) {
- case 0:
-
- i_APCI3200_Read1AnalogInputChannel(dev, s, insn,
- &ui_DummyValue);
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* ui_InterruptChannelValue[i_Count+0]=ui_DummyValue; */
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue[s_BoardInfos[dev->minor].
- i_Count + 0] = ui_DummyValue;
- /* END JK 06.07.04: Management of sevrals boards */
-
- /* Begin JK 25.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
- i_APCI3200_GetChannelCalibrationValue(dev,
- s_BoardInfos[dev->minor].ui_Channel_num,
- &s_BoardInfos[dev->minor].
- ui_InterruptChannelValue[s_BoardInfos[dev->minor].
- i_Count + 6],
- &s_BoardInfos[dev->minor].
- ui_InterruptChannelValue[s_BoardInfos[dev->minor].
- i_Count + 7],
- &s_BoardInfos[dev->minor].
- ui_InterruptChannelValue[s_BoardInfos[dev->minor].
- i_Count + 8]);
- /* End JK 25.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1)) */
- if ((s_BoardInfos[dev->minor].i_ADDIDATAType == 2)
- && (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE)
- && (s_BoardInfos[dev->minor].i_CJCAvailable == 1))
- /* END JK 06.07.04: Management of sevrals boards */
- {
- i_APCI3200_ReadCJCValue(dev, &ui_DummyValue);
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* ui_InterruptChannelValue[i_Count + 3]=ui_DummyValue; */
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue[s_BoardInfos[dev->
- minor].i_Count + 3] = ui_DummyValue;
- /* END JK 06.07.04: Management of sevrals boards */
- } /* if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)) */
- else {
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* ui_InterruptChannelValue[i_Count + 3]=0; */
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue[s_BoardInfos[dev->
- minor].i_Count + 3] = 0;
- /* END JK 06.07.04: Management of sevrals boards */
- } /* elseif((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1)) */
-
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE)) */
- if ((s_BoardInfos[dev->minor].i_AutoCalibration == FALSE)
- && (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE))
- /* END JK 06.07.04: Management of sevrals boards */
- {
- i_APCI3200_ReadCalibrationOffsetValue(dev,
- &ui_DummyValue);
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* ui_InterruptChannelValue[i_Count + 1]=ui_DummyValue; */
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue[s_BoardInfos[dev->
- minor].i_Count + 1] = ui_DummyValue;
- /* END JK 06.07.04: Management of sevrals boards */
- i_APCI3200_ReadCalibrationGainValue(dev,
- &ui_DummyValue);
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* ui_InterruptChannelValue[i_Count + 2]=ui_DummyValue; */
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue[s_BoardInfos[dev->
- minor].i_Count + 2] = ui_DummyValue;
- /* END JK 06.07.04: Management of sevrals boards */
- } /* if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE)) */
-
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)&& (i_CJCAvailable==1)) */
- if ((s_BoardInfos[dev->minor].i_ADDIDATAType == 2)
- && (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE)
- && (s_BoardInfos[dev->minor].i_CJCAvailable == 1))
- /* END JK 06.07.04: Management of sevrals boards */
- {
- /**********************************************************/
- /*Test if the Calibration channel must be read for the CJC */
- /**********************************************************/
- /**********************************/
- /*Test if the polarity is the same */
- /**********************************/
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* if(i_CJCPolarity!=i_ADDIDATAPolarity) */
- if (s_BoardInfos[dev->minor].i_CJCPolarity !=
- s_BoardInfos[dev->minor].i_ADDIDATAPolarity)
- /* END JK 06.07.04: Management of sevrals boards */
- {
- i_ConvertCJCCalibration = 1;
- } /* if(i_CJCPolarity!=i_ADDIDATAPolarity) */
- else {
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* if(i_CJCGain==i_ADDIDATAGain) */
- if (s_BoardInfos[dev->minor].i_CJCGain ==
- s_BoardInfos[dev->minor].i_ADDIDATAGain)
- /* END JK 06.07.04: Management of sevrals boards */
- {
- i_ConvertCJCCalibration = 0;
- } /* if(i_CJCGain==i_ADDIDATAGain) */
- else {
- i_ConvertCJCCalibration = 1;
- } /* elseif(i_CJCGain==i_ADDIDATAGain) */
- } /* elseif(i_CJCPolarity!=i_ADDIDATAPolarity) */
- if (i_ConvertCJCCalibration == 1) {
- i_APCI3200_ReadCJCCalOffset(dev,
- &ui_DummyValue);
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* ui_InterruptChannelValue[i_Count+4]=ui_DummyValue; */
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue[s_BoardInfos
- [dev->minor].i_Count + 4] =
- ui_DummyValue;
- /* END JK 06.07.04: Management of sevrals boards */
-
- i_APCI3200_ReadCJCCalGain(dev, &ui_DummyValue);
-
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* ui_InterruptChannelValue[i_Count+5]=ui_DummyValue; */
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue[s_BoardInfos
- [dev->minor].i_Count + 5] =
- ui_DummyValue;
- /* END JK 06.07.04: Management of sevrals boards */
- } /* if(i_ConvertCJCCalibration==1) */
- else {
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* ui_InterruptChannelValue[i_Count+4]=0; */
- /* ui_InterruptChannelValue[i_Count+5]=0; */
-
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue[s_BoardInfos
- [dev->minor].i_Count + 4] = 0;
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue[s_BoardInfos
- [dev->minor].i_Count + 5] = 0;
- /* END JK 06.07.04: Management of sevrals boards */
- } /* elseif(i_ConvertCJCCalibration==1) */
- } /* if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)) */
-
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* if(i_ScanType!=1) */
- if (s_BoardInfos[dev->minor].i_ScanType != 1) {
- /* i_Count=0; */
- s_BoardInfos[dev->minor].i_Count = 0;
- } /* if(i_ScanType!=1) */
- else {
- /* i_Count=i_Count +6; */
- /* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
- /* s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count +6; */
- s_BoardInfos[dev->minor].i_Count =
- s_BoardInfos[dev->minor].i_Count + 9;
- /* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
- } /* else if(i_ScanType!=1) */
-
- /* if((i_ScanType==1) &&(i_InterruptFlag==1)) */
- if ((s_BoardInfos[dev->minor].i_ScanType == 1)
- && (s_BoardInfos[dev->minor].i_InterruptFlag == 1)) {
- /* i_Count=i_Count-6; */
- /* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
- /* s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count-6; */
- s_BoardInfos[dev->minor].i_Count =
- s_BoardInfos[dev->minor].i_Count - 9;
- /* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
- }
- /* if(i_ScanType==0) */
- if (s_BoardInfos[dev->minor].i_ScanType == 0) {
- /*
- data[0]= ui_InterruptChannelValue[0];
- data[1]= ui_InterruptChannelValue[1];
- data[2]= ui_InterruptChannelValue[2];
- data[3]= ui_InterruptChannelValue[3];
- data[4]= ui_InterruptChannelValue[4];
- data[5]= ui_InterruptChannelValue[5];
- */
- data[0] =
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue[0];
- data[1] =
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue[1];
- data[2] =
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue[2];
- data[3] =
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue[3];
- data[4] =
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue[4];
- data[5] =
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue[5];
-
- /* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
- i_APCI3200_GetChannelCalibrationValue(dev,
- s_BoardInfos[dev->minor].ui_Channel_num,
- &data[6], &data[7], &data[8]);
- /* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
- }
- break;
- case 1:
-
- for (i = 0; i < insn->n; i++) {
- /* data[i]=ui_InterruptChannelValue[i]; */
- data[i] =
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue[i];
- }
-
- /* i_Count=0; */
- /* i_Sum=0; */
- /* if(i_ScanType==1) */
- s_BoardInfos[dev->minor].i_Count = 0;
- s_BoardInfos[dev->minor].i_Sum = 0;
- if (s_BoardInfos[dev->minor].i_ScanType == 1) {
- /* i_Initialised=0; */
- /* i_InterruptFlag=0; */
- s_BoardInfos[dev->minor].i_Initialised = 0;
- s_BoardInfos[dev->minor].i_InterruptFlag = 0;
- /* END JK 06.07.04: Management of sevrals boards */
- }
- break;
- default:
- printk("\nThe parameters passed are in error\n");
- apci3200_reset(dev);
- return -EINVAL;
- } /* switch(insn->unused[0]) */
-
- return insn->n;
-}
-
-/*
- * Configures The Analog Input Subdevice
- *
- * data[0] = 0 Normal AI
- * = 1 RTD
- * = 2 THERMOCOUPLE
- * data[1] = Gain To Use
- * data[2] = 0 Bipolar
- * = 1 Unipolar
- * data[3] = Offset Range
- * data[4] = 0 DC Coupling
- * = 1 AC Coupling
- * data[5] = 0 Single
- * = 1 Differential
- * data[6] = TimerReloadValue
- * data[7] = ConvertingTimeUnit
- * data[8] = 0 Analog voltage measurement
- * = 1 Resistance measurement
- * = 2 Temperature measurement
- * data[9] = 0 Interrupt Disable
- * = 1 INterrupt Enable
- * data[10] = Type of Thermocouple
- * data[11] = single channel Module Number
- * data[12] = 0 Single Read
- * = 1 Read more channel
- * = 2 Single scan
- * = 3 Continuous Scan
- * data[13] = Number of channels to read
- * data[14] = 0 RTD not used
- * = 1 RTD 2 wire connection
- * = 2 RTD 3 wire connection
- * = 3 RTD 4 wire connection
- */
-static int apci3200_ai_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int ul_Config = 0, ul_Temp = 0;
- unsigned int ui_ChannelNo = 0;
- unsigned int ui_Dummy = 0;
- int i_err = 0;
-
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* Initialize the structure */
- if (s_BoardInfos[dev->minor].b_StructInitialized != 1) {
- s_BoardInfos[dev->minor].i_CJCAvailable = 1;
- s_BoardInfos[dev->minor].i_CJCPolarity = 0;
- s_BoardInfos[dev->minor].i_CJCGain = 2; /* changed from 0 to 2 */
- s_BoardInfos[dev->minor].i_InterruptFlag = 0;
- s_BoardInfos[dev->minor].i_AutoCalibration = 0; /* : auto calibration */
- s_BoardInfos[dev->minor].i_ChannelCount = 0;
- s_BoardInfos[dev->minor].i_Sum = 0;
- s_BoardInfos[dev->minor].ui_Channel_num = 0;
- s_BoardInfos[dev->minor].i_Count = 0;
- s_BoardInfos[dev->minor].i_Initialised = 0;
- s_BoardInfos[dev->minor].b_StructInitialized = 1;
-
- /* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
- s_BoardInfos[dev->minor].i_ConnectionType = 0;
- /* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-
- /* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
- memset(s_BoardInfos[dev->minor].s_Module, 0,
- sizeof(s_BoardInfos[dev->minor].s_Module[MAX_MODULE]));
-
- v_GetAPCI3200EepromCalibrationValue(devpriv->i_IobaseAmcc,
- &s_BoardInfos[dev->minor]);
- /* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
- }
-
- if (data[0] != 0 && data[0] != 1 && data[0] != 2) {
- printk("\nThe selection of acquisition type is in error\n");
- i_err++;
- } /* if(data[0]!=0 && data[0]!=1 && data[0]!=2) */
- if (data[0] == 1) {
- if (data[14] != 0 && data[14] != 1 && data[14] != 2
- && data[14] != 4) {
- printk("\n Error in selection of RTD connection type\n");
- i_err++;
- } /* if(data[14]!=0 && data[14]!=1 && data[14]!=2 && data[14]!=4) */
- } /* if(data[0]==1 ) */
- if (data[1] < 0 || data[1] > 7) {
- printk("\nThe selection of gain is in error\n");
- i_err++;
- } /* if(data[1]<0 || data[1]>7) */
- if (data[2] != 0 && data[2] != 1) {
- printk("\nThe selection of polarity is in error\n");
- i_err++;
- } /* if(data[2]!=0 && data[2]!=1) */
- if (data[3] != 0) {
- printk("\nThe selection of offset range is in error\n");
- i_err++;
- } /* if(data[3]!=0) */
- if (data[4] != 0 && data[4] != 1) {
- printk("\nThe selection of coupling is in error\n");
- i_err++;
- } /* if(data[4]!=0 && data[4]!=1) */
- if (data[5] != 0 && data[5] != 1) {
- printk("\nThe selection of single/differential mode is in error\n");
- i_err++;
- } /* if(data[5]!=0 && data[5]!=1) */
- if (data[8] != 0 && data[8] != 1 && data[2] != 2) {
- printk("\nError in selection of functionality\n");
- } /* if(data[8]!=0 && data[8]!=1 && data[2]!=2) */
- if (data[12] == 0 || data[12] == 1) {
- if (data[6] != 20 && data[6] != 40 && data[6] != 80
- && data[6] != 160) {
- printk("\nThe selection of conversion time reload value is in error\n");
- i_err++;
- } /* if (data[6]!=20 && data[6]!=40 && data[6]!=80 && data[6]!=160 ) */
- if (data[7] != 2) {
- printk("\nThe selection of conversion time unit is in error\n");
- i_err++;
- } /* if(data[7]!=2) */
- }
- if (data[9] != 0 && data[9] != 1) {
- printk("\nThe selection of interrupt enable is in error\n");
- i_err++;
- } /* if(data[9]!=0 && data[9]!=1) */
- if (data[11] < 0 || data[11] > 4) {
- printk("\nThe selection of module is in error\n");
- i_err++;
- } /* if(data[11] <0 || data[11]>1) */
- if (data[12] < 0 || data[12] > 3) {
- printk("\nThe selection of singlechannel/scan selection is in error\n");
- i_err++;
- } /* if(data[12] < 0 || data[12]> 3) */
- if (data[13] < 0 || data[13] > 16) {
- printk("\nThe selection of number of channels is in error\n");
- i_err++;
- } /* if(data[13] <0 ||data[13] >15) */
-
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /*
- i_ChannelCount=data[13];
- i_ScanType=data[12];
- i_ADDIDATAPolarity = data[2];
- i_ADDIDATAGain=data[1];
- i_ADDIDATAConversionTime=data[6];
- i_ADDIDATAConversionTimeUnit=data[7];
- i_ADDIDATAType=data[0];
- */
-
- /* Save acquisition configuration for the actual board */
- s_BoardInfos[dev->minor].i_ChannelCount = data[13];
- s_BoardInfos[dev->minor].i_ScanType = data[12];
- s_BoardInfos[dev->minor].i_ADDIDATAPolarity = data[2];
- s_BoardInfos[dev->minor].i_ADDIDATAGain = data[1];
- s_BoardInfos[dev->minor].i_ADDIDATAConversionTime = data[6];
- s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit = data[7];
- s_BoardInfos[dev->minor].i_ADDIDATAType = data[0];
- /* Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
- s_BoardInfos[dev->minor].i_ConnectionType = data[5];
- /* End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
- /* END JK 06.07.04: Management of sevrals boards */
-
- /* Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
- memset(s_BoardInfos[dev->minor].ui_ScanValueArray, 0, (7 + 12) * sizeof(unsigned int)); /* 7 is the maximal number of channels */
- /* End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-
- /* BEGIN JK 02.07.04 : This while can't be do, it block the process when using severals boards */
- /* while(i_InterruptFlag==1) */
- while (s_BoardInfos[dev->minor].i_InterruptFlag == 1) {
-#ifndef MSXBOX
- udelay(1);
-#else
- /* In the case where the driver is compiled for the MSX-Box */
- /* we used a printk to have a little delay because udelay */
- /* seems to be broken under the MSX-Box. */
- /* This solution hat to be studied. */
- printk("");
-#endif
- }
- /* END JK 02.07.04 : This while can't be do, it block the process when using severals boards */
-
- ui_ChannelNo = CR_CHAN(insn->chanspec); /* get the channel */
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_ChannelNo=ui_ChannelNo; */
- /* ui_Channel_num =ui_ChannelNo; */
-
- s_BoardInfos[dev->minor].i_ChannelNo = ui_ChannelNo;
- s_BoardInfos[dev->minor].ui_Channel_num = ui_ChannelNo;
-
- /* END JK 06.07.04: Management of sevrals boards */
-
- if (data[5] == 0) {
- if (ui_ChannelNo > 15) {
- printk("\nThe Selection of the channel is in error\n");
- i_err++;
- } /* if(ui_ChannelNo>15) */
- } /* if(data[5]==0) */
- else {
- if (data[14] == 2) {
- if (ui_ChannelNo > 3) {
- printk("\nThe Selection of the channel is in error\n");
- i_err++;
- } /* if(ui_ChannelNo>3) */
- } /* if(data[14]==2) */
- else {
- if (ui_ChannelNo > 7) {
- printk("\nThe Selection of the channel is in error\n");
- i_err++;
- } /* if(ui_ChannelNo>7) */
- } /* elseif(data[14]==2) */
- } /* elseif(data[5]==0) */
- if (data[12] == 0 || data[12] == 1) {
- switch (data[5]) {
- case 0:
- if (ui_ChannelNo <= 3) {
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_Offset=0; */
- s_BoardInfos[dev->minor].i_Offset = 0;
- /* END JK 06.07.04: Management of sevrals boards */
- } /* if(ui_ChannelNo <=3) */
- if (ui_ChannelNo >= 4 && ui_ChannelNo <= 7) {
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_Offset=64; */
- s_BoardInfos[dev->minor].i_Offset = 64;
- /* END JK 06.07.04: Management of sevrals boards */
- } /* if(ui_ChannelNo >=4 && ui_ChannelNo <=7) */
- if (ui_ChannelNo >= 8 && ui_ChannelNo <= 11) {
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_Offset=128; */
- s_BoardInfos[dev->minor].i_Offset = 128;
- /* END JK 06.07.04: Management of sevrals boards */
- } /* if(ui_ChannelNo >=8 && ui_ChannelNo <=11) */
- if (ui_ChannelNo >= 12 && ui_ChannelNo <= 15) {
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_Offset=192; */
- s_BoardInfos[dev->minor].i_Offset = 192;
- /* END JK 06.07.04: Management of sevrals boards */
- } /* if(ui_ChannelNo >=12 && ui_ChannelNo <=15) */
- break;
- case 1:
- if (data[14] == 2) {
- if (ui_ChannelNo == 0) {
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_Offset=0; */
- s_BoardInfos[dev->minor].i_Offset = 0;
- /* END JK 06.07.04: Management of sevrals boards */
- } /* if(ui_ChannelNo ==0 ) */
- if (ui_ChannelNo == 1) {
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_Offset=0; */
- s_BoardInfos[dev->minor].i_Offset = 64;
- /* END JK 06.07.04: Management of sevrals boards */
- } /* if(ui_ChannelNo ==1) */
- if (ui_ChannelNo == 2) {
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_Offset=128; */
- s_BoardInfos[dev->minor].i_Offset = 128;
- /* END JK 06.07.04: Management of sevrals boards */
- } /* if(ui_ChannelNo ==2 ) */
- if (ui_ChannelNo == 3) {
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_Offset=192; */
- s_BoardInfos[dev->minor].i_Offset = 192;
- /* END JK 06.07.04: Management of sevrals boards */
- } /* if(ui_ChannelNo ==3) */
-
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_ChannelNo=0; */
- s_BoardInfos[dev->minor].i_ChannelNo = 0;
- /* END JK 06.07.04: Management of sevrals boards */
- ui_ChannelNo = 0;
- break;
- } /* if(data[14]==2) */
- if (ui_ChannelNo <= 1) {
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_Offset=0; */
- s_BoardInfos[dev->minor].i_Offset = 0;
- /* END JK 06.07.04: Management of sevrals boards */
- } /* if(ui_ChannelNo <=1) */
- if (ui_ChannelNo >= 2 && ui_ChannelNo <= 3) {
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_ChannelNo=i_ChannelNo-2; */
- /* i_Offset=64; */
- s_BoardInfos[dev->minor].i_ChannelNo =
- s_BoardInfos[dev->minor].i_ChannelNo -
- 2;
- s_BoardInfos[dev->minor].i_Offset = 64;
- /* END JK 06.07.04: Management of sevrals boards */
- ui_ChannelNo = ui_ChannelNo - 2;
- } /* if(ui_ChannelNo >=2 && ui_ChannelNo <=3) */
- if (ui_ChannelNo >= 4 && ui_ChannelNo <= 5) {
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_ChannelNo=i_ChannelNo-4; */
- /* i_Offset=128; */
- s_BoardInfos[dev->minor].i_ChannelNo =
- s_BoardInfos[dev->minor].i_ChannelNo -
- 4;
- s_BoardInfos[dev->minor].i_Offset = 128;
- /* END JK 06.07.04: Management of sevrals boards */
- ui_ChannelNo = ui_ChannelNo - 4;
- } /* if(ui_ChannelNo >=4 && ui_ChannelNo <=5) */
- if (ui_ChannelNo >= 6 && ui_ChannelNo <= 7) {
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_ChannelNo=i_ChannelNo-6; */
- /* i_Offset=192; */
- s_BoardInfos[dev->minor].i_ChannelNo =
- s_BoardInfos[dev->minor].i_ChannelNo -
- 6;
- s_BoardInfos[dev->minor].i_Offset = 192;
- /* END JK 06.07.04: Management of sevrals boards */
- ui_ChannelNo = ui_ChannelNo - 6;
- } /* if(ui_ChannelNo >=6 && ui_ChannelNo <=7) */
- break;
-
- default:
- printk("\n This selection of polarity does not exist\n");
- i_err++;
- } /* switch(data[2]) */
- } /* if(data[12]==0 || data[12]==1) */
- else {
- switch (data[11]) {
- case 1:
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_Offset=0; */
- s_BoardInfos[dev->minor].i_Offset = 0;
- /* END JK 06.07.04: Management of sevrals boards */
- break;
- case 2:
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_Offset=64; */
- s_BoardInfos[dev->minor].i_Offset = 64;
- /* END JK 06.07.04: Management of sevrals boards */
- break;
- case 3:
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_Offset=128; */
- s_BoardInfos[dev->minor].i_Offset = 128;
- /* END JK 06.07.04: Management of sevrals boards */
- break;
- case 4:
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_Offset=192; */
- s_BoardInfos[dev->minor].i_Offset = 192;
- /* END JK 06.07.04: Management of sevrals boards */
- break;
- default:
- printk("\nError in module selection\n");
- i_err++;
- } /* switch(data[11]) */
- } /* elseif(data[12]==0 || data[12]==1) */
- if (i_err) {
- apci3200_reset(dev);
- return -EINVAL;
- }
- /* if(i_ScanType!=1) */
- if (s_BoardInfos[dev->minor].i_ScanType != 1) {
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_Count=0; */
- /* i_Sum=0; */
- s_BoardInfos[dev->minor].i_Count = 0;
- s_BoardInfos[dev->minor].i_Sum = 0;
- /* END JK 06.07.04: Management of sevrals boards */
- } /* if(i_ScanType!=1) */
-
- ul_Config =
- data[1] | (data[2] << 6) | (data[5] << 7) | (data[3] << 8) |
- (data[4] << 9);
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* END JK 06.07.04: Management of sevrals boards */
- /*********************************/
- /* Write the channel to configure */
- /*********************************/
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* outl(0 | ui_ChannelNo , devpriv->iobase+i_Offset + 0x4); */
- outl(0 | ui_ChannelNo,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x4);
- /* END JK 06.07.04: Management of sevrals boards */
-
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* END JK 06.07.04: Management of sevrals boards */
- /**************************/
- /* Reset the configuration */
- /**************************/
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* outl(0 , devpriv->iobase+i_Offset + 0x0); */
- outl(0, devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x0);
- /* END JK 06.07.04: Management of sevrals boards */
-
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* END JK 06.07.04: Management of sevrals boards */
-
- /***************************/
- /* Write the configuration */
- /***************************/
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* outl(ul_Config , devpriv->iobase+i_Offset + 0x0); */
- outl(ul_Config,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x0);
- /* END JK 06.07.04: Management of sevrals boards */
-
- /***************************/
- /*Reset the calibration bit */
- /***************************/
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* ul_Temp = inl(devpriv->iobase+i_Offset + 12); */
- ul_Temp = inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
- /* END JK 06.07.04: Management of sevrals boards */
-
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* END JK 06.07.04: Management of sevrals boards */
-
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* outl((ul_Temp & 0xFFF9FFFF) , devpriv->iobase+.i_Offset + 12); */
- outl((ul_Temp & 0xFFF9FFFF),
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
- /* END JK 06.07.04: Management of sevrals boards */
-
- if (data[9] == 1) {
- devpriv->tsk_Current = current;
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_InterruptFlag=1; */
- s_BoardInfos[dev->minor].i_InterruptFlag = 1;
- /* END JK 06.07.04: Management of sevrals boards */
- } /* if(data[9]==1) */
- else {
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_InterruptFlag=0; */
- s_BoardInfos[dev->minor].i_InterruptFlag = 0;
- /* END JK 06.07.04: Management of sevrals boards */
- } /* else if(data[9]==1) */
-
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_Initialised=1; */
- s_BoardInfos[dev->minor].i_Initialised = 1;
- /* END JK 06.07.04: Management of sevrals boards */
-
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* if(i_ScanType==1) */
- if (s_BoardInfos[dev->minor].i_ScanType == 1)
- /* END JK 06.07.04: Management of sevrals boards */
- {
- /* BEGIN JK 06.07.04: Management of sevrals boards */
- /* i_Sum=i_Sum+1; */
- s_BoardInfos[dev->minor].i_Sum =
- s_BoardInfos[dev->minor].i_Sum + 1;
- /* END JK 06.07.04: Management of sevrals boards */
-
- insn->unused[0] = 0;
- apci3200_ai_read(dev, s, insn, &ui_Dummy);
- }
-
- return insn->n;
-}
-
-/*
- * Tests the Selected Anlog Input Channel
- *
- * data[0] = 0 TestAnalogInputShortCircuit
- * = 1 TestAnalogInputConnection
- *
- * data[0] : Digital value obtained
- * data[1] : calibration offset
- * data[2] : calibration gain
- */
-static int apci3200_ai_bits_test(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int ui_Configuration = 0;
- int i_Temp; /* ,i_TimeUnit; */
-
- /* if(i_Initialised==0) */
-
- if (s_BoardInfos[dev->minor].i_Initialised == 0) {
- apci3200_reset(dev);
- return -EINVAL;
- } /* if(i_Initialised==0); */
- if (data[0] != 0 && data[0] != 1) {
- printk("\nError in selection of functionality\n");
- apci3200_reset(dev);
- return -EINVAL;
- } /* if(data[0]!=0 && data[0]!=1) */
-
- if (data[0] == 1) /* Perform Short Circuit TEST */
- {
- /**************************/
- /*Set the short-cicuit bit */
- /**************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].
- i_Offset + 12) >> 19) & 1) !=
- 1) ;
- /* outl((0x00001000 |i_ChannelNo) , devpriv->iobase+i_Offset + 4); */
- outl((0x00001000 | s_BoardInfos[dev->minor].i_ChannelNo),
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 4);
- /*************************/
- /*Set the time unit to ns */
- /*************************/
- /* i_TimeUnit= i_ADDIDATAConversionTimeUnit;
- i_ADDIDATAConversionTimeUnit= 1; */
- /* i_Temp= i_InterruptFlag ; */
- i_Temp = s_BoardInfos[dev->minor].i_InterruptFlag;
- s_BoardInfos[dev->minor].i_InterruptFlag = 0;
- i_APCI3200_Read1AnalogInputChannel(dev, s, insn, data);
- /* if(i_AutoCalibration == FALSE) */
- if (s_BoardInfos[dev->minor].i_AutoCalibration == FALSE) {
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].
- i_Offset +
- 12) >> 19) & 1) != 1) ;
-
- /* outl((0x00001000 |i_ChannelNo) , devpriv->iobase+i_Offset + 4); */
- outl((0x00001000 | s_BoardInfos[dev->minor].
- i_ChannelNo),
- devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 4);
- data++;
- i_APCI3200_ReadCalibrationOffsetValue(dev, data);
- data++;
- i_APCI3200_ReadCalibrationGainValue(dev, data);
- }
- } else {
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].
- i_Offset + 12) >> 19) & 1) !=
- 1) ;
- /* outl((0x00000800|i_ChannelNo) , devpriv->iobase+i_Offset + 4); */
- outl((0x00000800 | s_BoardInfos[dev->minor].i_ChannelNo),
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 4);
- /* ui_Configuration = inl(devpriv->iobase+i_Offset + 0); */
- ui_Configuration =
- inl(devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 0);
- /*************************/
- /*Set the time unit to ns */
- /*************************/
- /* i_TimeUnit= i_ADDIDATAConversionTimeUnit;
- i_ADDIDATAConversionTimeUnit= 1; */
- /* i_Temp= i_InterruptFlag ; */
- i_Temp = s_BoardInfos[dev->minor].i_InterruptFlag;
- s_BoardInfos[dev->minor].i_InterruptFlag = 0;
- i_APCI3200_Read1AnalogInputChannel(dev, s, insn, data);
- /* if(i_AutoCalibration == FALSE) */
- if (s_BoardInfos[dev->minor].i_AutoCalibration == FALSE) {
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].
- i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl((0x00000800|i_ChannelNo) , devpriv->iobase+i_Offset + 4); */
- outl((0x00000800 | s_BoardInfos[dev->minor].
- i_ChannelNo),
- devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 4);
- data++;
- i_APCI3200_ReadCalibrationOffsetValue(dev, data);
- data++;
- i_APCI3200_ReadCalibrationGainValue(dev, data);
- }
- }
- /* i_InterruptFlag=i_Temp ; */
- s_BoardInfos[dev->minor].i_InterruptFlag = i_Temp;
- return insn->n;
-}
-
-static int apci3200_ai_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- apci3200_reset(dev);
- return insn->n;
-}
-
-static int apci3200_ai_cmdtest(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_cmd *cmd)
-{
-
- int err = 0;
- unsigned int ui_ConvertTime = 0;
- unsigned int ui_ConvertTimeBase = 0;
- unsigned int ui_DelayTime = 0;
- unsigned int ui_DelayTimeBase = 0;
- int i_NbrOfChannel = 0;
- int i_Cpt = 0;
- double d_ConversionTimeForAllChannels = 0.0;
- double d_SCANTimeNewUnit = 0.0;
- unsigned int arg;
-
- /* Step 1 : check if triggers are trivially valid */
-
- err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
- err |= cfc_check_trigger_src(&cmd->scan_begin_src,
- TRIG_TIMER | TRIG_FOLLOW);
- err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
- err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
- err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
-
- if (s_BoardInfos[dev->minor].i_InterruptFlag == 0)
- err |= -EINVAL;
-
- if (err) {
- apci3200_reset(dev);
- 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->scan_begin_src);
- err |= cfc_check_trigger_is_unique(&cmd->stop_src);
-
- /* Step 2b : and mutually compatible */
-
- if (err) {
- apci3200_reset(dev);
- return 2;
- }
-
- /* Step 3: check if arguments are trivially valid */
-
- switch (cmd->start_src) {
- case TRIG_NOW:
- err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
- break;
- case TRIG_EXT:
- /* validate the trigger edge selection */
- arg = cmd->start_arg & 0xffff;
- if (arg < 1 || arg > 3) {
- cmd->start_arg &= ~0xffff;
- cmd->start_arg |= 1;
- err |= -EINVAL;
- }
- /* validate the trigger mode selection */
- arg = cmd->start_arg >> 16;
- if (arg != 2) {
- cmd->start_arg &= ~(0xffff << 16);
- cmd->start_arg |= (2 << 16);
- err |= -EINVAL;
- }
- break;
- }
-
- err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
-
- /* i_FirstChannel=cmd->chanlist[0]; */
- s_BoardInfos[dev->minor].i_FirstChannel = cmd->chanlist[0];
- /* i_LastChannel=cmd->chanlist[1]; */
- s_BoardInfos[dev->minor].i_LastChannel = cmd->chanlist[1];
-
- if (cmd->convert_src == TRIG_TIMER) {
- ui_ConvertTime = cmd->convert_arg & 0xFFFF;
- ui_ConvertTimeBase = cmd->convert_arg >> 16;
- if (ui_ConvertTime != 20 && ui_ConvertTime != 40
- && ui_ConvertTime != 80 && ui_ConvertTime != 160)
- {
- printk("\nThe selection of conversion time reload value is in error\n");
- err++;
- } /* if (ui_ConvertTime!=20 && ui_ConvertTime!=40 && ui_ConvertTime!=80 && ui_ConvertTime!=160 ) */
- if (ui_ConvertTimeBase != 2) {
- printk("\nThe selection of conversion time unit is in error\n");
- err++;
- } /* if(ui_ConvertTimeBase!=2) */
- } else {
- ui_ConvertTime = 0;
- ui_ConvertTimeBase = 0;
- }
- if (cmd->scan_begin_src == TRIG_FOLLOW) {
- ui_DelayTime = 0;
- ui_DelayTimeBase = 0;
- } /* if(cmd->scan_begin_src==TRIG_FOLLOW) */
- else {
- ui_DelayTime = cmd->scan_begin_arg & 0xFFFF;
- ui_DelayTimeBase = cmd->scan_begin_arg >> 16;
- if (ui_DelayTimeBase != 2 && ui_DelayTimeBase != 3) {
- err++;
- printk("\nThe Delay time base selection is in error\n");
- }
- if (ui_DelayTime < 1 || ui_DelayTime > 1023) {
- err++;
- printk("\nThe Delay time value is in error\n");
- }
- if (err) {
- apci3200_reset(dev);
- return 3;
- }
- fpu_begin();
- d_SCANTimeNewUnit = (double)ui_DelayTime;
- /* i_NbrOfChannel= i_LastChannel-i_FirstChannel + 4; */
- i_NbrOfChannel =
- s_BoardInfos[dev->minor].i_LastChannel -
- s_BoardInfos[dev->minor].i_FirstChannel + 4;
- /**********************************************************/
- /*calculate the total conversion time for all the channels */
- /**********************************************************/
- d_ConversionTimeForAllChannels =
- (double)((double)ui_ConvertTime /
- (double)i_NbrOfChannel);
-
- /*******************************/
- /*Convert the frequence in time */
- /*******************************/
- d_ConversionTimeForAllChannels =
- (double)1.0 / d_ConversionTimeForAllChannels;
- ui_ConvertTimeBase = 3;
- /***********************************/
- /*Test if the time unit is the same */
- /***********************************/
-
- if (ui_DelayTimeBase <= ui_ConvertTimeBase) {
-
- for (i_Cpt = 0;
- i_Cpt < (ui_ConvertTimeBase - ui_DelayTimeBase);
- i_Cpt++) {
-
- d_ConversionTimeForAllChannels =
- d_ConversionTimeForAllChannels * 1000;
- d_ConversionTimeForAllChannels =
- d_ConversionTimeForAllChannels + 1;
- }
- } else {
- for (i_Cpt = 0;
- i_Cpt < (ui_DelayTimeBase - ui_ConvertTimeBase);
- i_Cpt++) {
- d_SCANTimeNewUnit = d_SCANTimeNewUnit * 1000;
-
- }
- }
-
- if (d_ConversionTimeForAllChannels >= d_SCANTimeNewUnit) {
-
- printk("\nSCAN Delay value cannot be used\n");
- /*********************************/
- /*SCAN Delay value cannot be used */
- /*********************************/
- err++;
- }
- fpu_end();
- } /* else if(cmd->scan_begin_src==TRIG_FOLLOW) */
-
- if (err) {
- apci3200_reset(dev);
- return 4;
- }
-
- return 0;
-}
-
-static int apci3200_cancel(struct comedi_device *dev,
- struct comedi_subdevice *s)
-{
- struct addi_private *devpriv = dev->private;
- unsigned int ui_Configuration = 0;
-
- /* i_InterruptFlag=0; */
- /* i_Initialised=0; */
- /* i_Count=0; */
- /* i_Sum=0; */
- s_BoardInfos[dev->minor].i_InterruptFlag = 0;
- s_BoardInfos[dev->minor].i_Initialised = 0;
- s_BoardInfos[dev->minor].i_Count = 0;
- s_BoardInfos[dev->minor].i_Sum = 0;
-
- /*******************/
- /*Read the register */
- /*******************/
- /* ui_Configuration = inl(devpriv->iobase+i_Offset + 8); */
- ui_Configuration =
- inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
- /*****************************/
- /*Reset the START and IRQ bit */
- /*****************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl((ui_Configuration & 0xFFE7FFFF),devpriv->iobase+i_Offset + 8); */
- outl((ui_Configuration & 0xFFE7FFFF),
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
- return 0;
-}
-
-/*
- * Does asynchronous acquisition
- * Determines the mode 1 or 2.
- */
-static int apci3200_ai_cmd(struct comedi_device *dev,
- struct comedi_subdevice *s)
-{
- struct addi_private *devpriv = dev->private;
- struct comedi_cmd *cmd = &s->async->cmd;
- unsigned int ui_Configuration = 0;
- /* INT i_CurrentSource = 0; */
- unsigned int ui_Trigger = 0;
- unsigned int ui_TriggerEdge = 0;
- unsigned int ui_Triggermode = 0;
- unsigned int ui_ScanMode = 0;
- unsigned int ui_ConvertTime = 0;
- unsigned int ui_ConvertTimeBase = 0;
- unsigned int ui_DelayTime = 0;
- unsigned int ui_DelayTimeBase = 0;
- unsigned int ui_DelayMode = 0;
-
- /* i_FirstChannel=cmd->chanlist[0]; */
- /* i_LastChannel=cmd->chanlist[1]; */
- s_BoardInfos[dev->minor].i_FirstChannel = cmd->chanlist[0];
- s_BoardInfos[dev->minor].i_LastChannel = cmd->chanlist[1];
- if (cmd->start_src == TRIG_EXT) {
- ui_Trigger = 1;
- ui_TriggerEdge = cmd->start_arg & 0xFFFF;
- ui_Triggermode = cmd->start_arg >> 16;
- } /* if(cmd->start_src==TRIG_EXT) */
- else {
- ui_Trigger = 0;
- } /* elseif(cmd->start_src==TRIG_EXT) */
-
- if (cmd->stop_src == TRIG_COUNT) {
- ui_ScanMode = 0;
- } /* if (cmd->stop_src==TRIG_COUNT) */
- else {
- ui_ScanMode = 2;
- } /* else if (cmd->stop_src==TRIG_COUNT) */
-
- if (cmd->scan_begin_src == TRIG_FOLLOW) {
- ui_DelayTime = 0;
- ui_DelayTimeBase = 0;
- ui_DelayMode = 0;
- } /* if(cmd->scan_begin_src==TRIG_FOLLOW) */
- else {
- ui_DelayTime = cmd->scan_begin_arg & 0xFFFF;
- ui_DelayTimeBase = cmd->scan_begin_arg >> 16;
- ui_DelayMode = 1;
- } /* else if(cmd->scan_begin_src==TRIG_FOLLOW) */
- if (cmd->convert_src == TRIG_TIMER) {
- ui_ConvertTime = cmd->convert_arg & 0xFFFF;
- ui_ConvertTimeBase = cmd->convert_arg >> 16;
- } else {
- ui_ConvertTime = 0;
- ui_ConvertTimeBase = 0;
- }
-
- /* if(i_ADDIDATAType ==1 || ((i_ADDIDATAType==2))) */
- /* { */
- /**************************************************/
- /*Read the old configuration of the current source */
- /**************************************************/
- /* ui_Configuration = inl(devpriv->iobase+i_Offset + 12); */
- ui_Configuration =
- inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
- /***********************************************/
- /*Write the configuration of the current source */
- /***********************************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl((ui_Configuration & 0xFFC00000 ), devpriv->iobase+i_Offset +12); */
- outl((ui_Configuration & 0xFFC00000),
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
- /* } */
- ui_Configuration = 0;
-
- /* ui_Configuration = i_FirstChannel |(i_LastChannel << 8)| 0x00100000 | */
- ui_Configuration =
- s_BoardInfos[dev->minor].i_FirstChannel | (s_BoardInfos[dev->
- minor].
- i_LastChannel << 8) | 0x00100000 | (ui_Trigger << 24) |
- (ui_TriggerEdge << 25) | (ui_Triggermode << 27) | (ui_DelayMode
- << 18) | (ui_ScanMode << 16);
-
- /*************************/
- /*Write the Configuration */
- /*************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl( ui_Configuration, devpriv->iobase+i_Offset + 0x8); */
- outl(ui_Configuration,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x8);
- /***********************/
- /*Write the Delay Value */
- /***********************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(ui_DelayTime,devpriv->iobase+i_Offset + 40); */
- outl(ui_DelayTime,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 40);
- /***************************/
- /*Write the Delay time base */
- /***************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(ui_DelayTimeBase,devpriv->iobase+i_Offset + 44); */
- outl(ui_DelayTimeBase,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 44);
- /*********************************/
- /*Write the conversion time value */
- /*********************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(ui_ConvertTime,devpriv->iobase+i_Offset + 32); */
- outl(ui_ConvertTime,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
-
- /********************************/
- /*Write the conversion time base */
- /********************************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl(ui_ConvertTimeBase,devpriv->iobase+i_Offset + 36); */
- outl(ui_ConvertTimeBase,
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
- /*******************/
- /*Read the register */
- /*******************/
- /* ui_Configuration = inl(devpriv->iobase+i_Offset + 4); */
- ui_Configuration =
- inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
- /******************/
- /*Set the SCAN bit */
- /******************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
-
- /* outl(((ui_Configuration & 0x1E0FF) | 0x00002000),devpriv->iobase+i_Offset + 4); */
- outl(((ui_Configuration & 0x1E0FF) | 0x00002000),
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
- /*******************/
- /*Read the register */
- /*******************/
- ui_Configuration = 0;
- /* ui_Configuration = inl(devpriv->iobase+i_Offset + 8); */
- ui_Configuration =
- inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
-
- /*******************/
- /*Set the START bit */
- /*******************/
- /* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
- while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
- 12) >> 19) & 1) != 1) ;
- /* outl((ui_Configuration | 0x00080000),devpriv->iobase+i_Offset + 8); */
- outl((ui_Configuration | 0x00080000),
- devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
- return 0;
-}
-
-/*
- * This function copies the acquired data(from FIFO) to Comedi buffer.
- */
-static int i_APCI3200_InterruptHandleEos(struct comedi_device *dev)
-{
- struct addi_private *devpriv = dev->private;
- struct comedi_subdevice *s = dev->read_subdev;
- unsigned int ui_StatusRegister = 0;
-
- /* BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
- /* comedi_async *async = s->async; */
- /* UINT *data; */
- /* data=async->data+async->buf_int_ptr;//new samples added from here onwards */
- int n = 0, i = 0;
- /* END JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-
- /************************************/
- /*Read the interrupt status register */
- /************************************/
- /* ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16); */
- ui_StatusRegister =
- inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 16);
-
- /*************************/
- /*Test if interrupt occur */
- /*************************/
-
- if ((ui_StatusRegister & 0x2) == 0x2) {
- /*************************/
- /*Read the channel number */
- /*************************/
- /* ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24); */
- /* BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
- /* This value is not used */
- /* ui_ChannelNumber = inl(devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 24); */
- /* END JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-
- /*************************************/
- /*Read the digital Analog Input value */
- /*************************************/
-
- /* data[i_Count] = inl(devpriv->iobase+i_Offset + 28); */
- /* Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
- /* data[s_BoardInfos [dev->minor].i_Count] = inl(devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 28); */
- s_BoardInfos[dev->minor].ui_ScanValueArray[s_BoardInfos[dev->
- minor].i_Count] =
- inl(devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 28);
- /* End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-
- /* if((i_Count == (i_LastChannel-i_FirstChannel+3))) */
- if ((s_BoardInfos[dev->minor].i_Count ==
- (s_BoardInfos[dev->minor].i_LastChannel -
- s_BoardInfos[dev->minor].
- i_FirstChannel + 3))) {
-
- /* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
- s_BoardInfos[dev->minor].i_Count++;
-
- for (i = s_BoardInfos[dev->minor].i_FirstChannel;
- i <= s_BoardInfos[dev->minor].i_LastChannel;
- i++) {
- i_APCI3200_GetChannelCalibrationValue(dev, i,
- &s_BoardInfos[dev->minor].
- ui_ScanValueArray[s_BoardInfos[dev->
- minor].i_Count + ((i -
- s_BoardInfos
- [dev->minor].
- i_FirstChannel)
- * 3)],
- &s_BoardInfos[dev->minor].
- ui_ScanValueArray[s_BoardInfos[dev->
- minor].i_Count + ((i -
- s_BoardInfos
- [dev->minor].
- i_FirstChannel)
- * 3) + 1],
- &s_BoardInfos[dev->minor].
- ui_ScanValueArray[s_BoardInfos[dev->
- minor].i_Count + ((i -
- s_BoardInfos
- [dev->minor].
- i_FirstChannel)
- * 3) + 2]);
- }
-
- /* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-
- /* i_Count=-1; */
-
- s_BoardInfos[dev->minor].i_Count = -1;
-
- /* async->buf_int_count+=(i_LastChannel-i_FirstChannel+4)*sizeof(unsigned int); */
- /* Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
- /* async->buf_int_count+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(unsigned int); */
- /* End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
- /* async->buf_int_ptr+=(i_LastChannel-i_FirstChannel+4)*sizeof(unsigned int); */
- /* Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
- /* async->buf_int_ptr+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(unsigned int); */
- /* comedi_eos(dev,s); */
-
- /* Set the event type (Comedi Buffer End Of Scan) */
- s->async->events |= COMEDI_CB_EOS;
-
- /* Test if enougth memory is available and allocate it for 7 values */
- n = comedi_buf_write_alloc(s,
- (7 + 12) * sizeof(unsigned int));
-
- /* If not enough memory available, event is set to Comedi Buffer Error */
- if (n > ((7 + 12) * sizeof(unsigned int))) {
- printk("\ncomedi_buf_write_alloc n = %i", n);
- s->async->events |= COMEDI_CB_ERROR;
- }
- /* Write all 7 scan values in the comedi buffer */
- comedi_buf_memcpy_to(s, 0,
- (unsigned int *) s_BoardInfos[dev->minor].
- ui_ScanValueArray, (7 + 12) * sizeof(unsigned int));
-
- /* Update comedi buffer pinters indexes */
- comedi_buf_write_free(s,
- (7 + 12) * sizeof(unsigned int));
-
- /* Send events */
- comedi_event(dev, s);
- /* End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-
- /* BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
- /* */
- /* if (s->async->buf_int_ptr>=s->async->data_len) // for buffer rool over */
- /* { */
- /* /* buffer rollover */ */
- /* s->async->buf_int_ptr=0; */
- /* comedi_eobuf(dev,s); */
- /* } */
- /* End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
- }
- /* i_Count++; */
- s_BoardInfos[dev->minor].i_Count++;
- }
- /* i_InterruptFlag=0; */
- s_BoardInfos[dev->minor].i_InterruptFlag = 0;
- return 0;
-}
-
-static void apci3200_interrupt(int irq, void *d)
-{
- struct comedi_device *dev = d;
- struct addi_private *devpriv = dev->private;
- unsigned int ui_StatusRegister = 0;
- unsigned int ui_ChannelNumber = 0;
- int i_CalibrationFlag = 0;
- int i_CJCFlag = 0;
- unsigned int ui_DummyValue = 0;
- unsigned int ui_DigitalTemperature = 0;
- unsigned int ui_DigitalInput = 0;
- int i_ConvertCJCCalibration;
- /* BEGIN JK TEST */
- int i_ReturnValue = 0;
- /* END JK TEST */
-
- /* switch(i_ScanType) */
- switch (s_BoardInfos[dev->minor].i_ScanType) {
- case 0:
- case 1:
- /* switch(i_ADDIDATAType) */
- switch (s_BoardInfos[dev->minor].i_ADDIDATAType) {
- case 0:
- case 1:
-
- /************************************/
- /*Read the interrupt status register */
- /************************************/
- /* ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16); */
- ui_StatusRegister =
- inl(devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 16);
- if ((ui_StatusRegister & 0x2) == 0x2) {
- /* i_CalibrationFlag = ((inl(devpriv->iobase+i_Offset + 12) & 0x00060000) >> 17); */
- i_CalibrationFlag =
- ((inl(devpriv->iobase +
- s_BoardInfos[dev->
- minor].
- i_Offset +
- 12) & 0x00060000) >>
- 17);
- /*************************/
- /*Read the channel number */
- /*************************/
- /* ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24); */
-
- /*************************************/
- /*Read the digital analog input value */
- /*************************************/
- /* ui_DigitalInput = inl(devpriv->iobase+i_Offset + 28); */
- ui_DigitalInput =
- inl(devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 28);
-
- /***********************************************/
- /* Test if the value read is the channel value */
- /***********************************************/
- if (i_CalibrationFlag == 0) {
- /* ui_InterruptChannelValue[i_Count + 0] = ui_DigitalInput; */
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue
- [s_BoardInfos[dev->minor].
- i_Count + 0] = ui_DigitalInput;
-
- /* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
- /*
- i_APCI3200_GetChannelCalibrationValue (dev, s_BoardInfos [dev->minor].ui_Channel_num,
- &s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count + 6],
- &s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count + 7],
- &s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count + 8]);
- */
- /* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-
- /******************************************************/
- /*Start the conversion of the calibration offset value */
- /******************************************************/
- i_APCI3200_ReadCalibrationOffsetValue
- (dev, &ui_DummyValue);
- } /* if (i_CalibrationFlag == 0) */
- /**********************************************************/
- /* Test if the value read is the calibration offset value */
- /**********************************************************/
-
- if (i_CalibrationFlag == 1) {
-
- /******************/
- /* Save the value */
- /******************/
-
- /* ui_InterruptChannelValue[i_Count + 1] = ui_DigitalInput; */
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue
- [s_BoardInfos[dev->minor].
- i_Count + 1] = ui_DigitalInput;
-
- /******************************************************/
- /* Start the conversion of the calibration gain value */
- /******************************************************/
- i_APCI3200_ReadCalibrationGainValue(dev,
- &ui_DummyValue);
- } /* if (i_CalibrationFlag == 1) */
- /******************************************************/
- /*Test if the value read is the calibration gain value */
- /******************************************************/
-
- if (i_CalibrationFlag == 2) {
-
- /****************/
- /*Save the value */
- /****************/
- /* ui_InterruptChannelValue[i_Count + 2] = ui_DigitalInput; */
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue
- [s_BoardInfos[dev->minor].
- i_Count + 2] = ui_DigitalInput;
- /* if(i_ScanType==1) */
- if (s_BoardInfos[dev->minor].
- i_ScanType == 1) {
-
- /* i_InterruptFlag=0; */
- s_BoardInfos[dev->minor].
- i_InterruptFlag = 0;
- /* i_Count=i_Count + 6; */
- /* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
- /* s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count + 6; */
- s_BoardInfos[dev->minor].
- i_Count =
- s_BoardInfos[dev->
- minor].i_Count + 9;
- /* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
- } /* if(i_ScanType==1) */
- else {
- /* i_Count=0; */
- s_BoardInfos[dev->minor].
- i_Count = 0;
- } /* elseif(i_ScanType==1) */
- /* if(i_ScanType!=1) */
- if (s_BoardInfos[dev->minor].
- i_ScanType != 1) {
- i_ReturnValue = send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */
- } /* if(i_ScanType!=1) */
- else {
- /* if(i_ChannelCount==i_Sum) */
- if (s_BoardInfos[dev->minor].
- i_ChannelCount ==
- s_BoardInfos[dev->
- minor].i_Sum) {
- send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */
- }
- } /* if(i_ScanType!=1) */
- } /* if (i_CalibrationFlag == 2) */
- } /* if ((ui_StatusRegister & 0x2) == 0x2) */
-
- break;
-
- case 2:
- /************************************/
- /*Read the interrupt status register */
- /************************************/
-
- /* ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16); */
- ui_StatusRegister =
- inl(devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 16);
- /*************************/
- /*Test if interrupt occur */
- /*************************/
-
- if ((ui_StatusRegister & 0x2) == 0x2) {
-
- /* i_CJCFlag = ((inl(devpriv->iobase+i_Offset + 4) & 0x00000400) >> 10); */
- i_CJCFlag =
- ((inl(devpriv->iobase +
- s_BoardInfos[dev->
- minor].
- i_Offset +
- 4) & 0x00000400) >> 10);
-
- /* i_CalibrationFlag = ((inl(devpriv->iobase+i_Offset + 12) & 0x00060000) >> 17); */
- i_CalibrationFlag =
- ((inl(devpriv->iobase +
- s_BoardInfos[dev->
- minor].
- i_Offset +
- 12) & 0x00060000) >>
- 17);
-
- /*************************/
- /*Read the channel number */
- /*************************/
-
- /* ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24); */
- ui_ChannelNumber =
- inl(devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 24);
- /* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
- s_BoardInfos[dev->minor].ui_Channel_num =
- ui_ChannelNumber;
- /* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-
- /************************************/
- /*Read the digital temperature value */
- /************************************/
- /* ui_DigitalTemperature = inl(devpriv->iobase+i_Offset + 28); */
- ui_DigitalTemperature =
- inl(devpriv->iobase +
- s_BoardInfos[dev->minor].i_Offset + 28);
-
- /*********************************************/
- /*Test if the value read is the channel value */
- /*********************************************/
-
- if ((i_CalibrationFlag == 0)
- && (i_CJCFlag == 0)) {
- /* ui_InterruptChannelValue[i_Count + 0]=ui_DigitalTemperature; */
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue
- [s_BoardInfos[dev->minor].
- i_Count + 0] =
- ui_DigitalTemperature;
-
- /*********************************/
- /*Start the conversion of the CJC */
- /*********************************/
- i_APCI3200_ReadCJCValue(dev,
- &ui_DummyValue);
-
- } /* if ((i_CalibrationFlag == 0) && (i_CJCFlag == 0)) */
-
- /*****************************************/
- /*Test if the value read is the CJC value */
- /*****************************************/
-
- if ((i_CJCFlag == 1)
- && (i_CalibrationFlag == 0)) {
- /* ui_InterruptChannelValue[i_Count + 3]=ui_DigitalTemperature; */
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue
- [s_BoardInfos[dev->minor].
- i_Count + 3] =
- ui_DigitalTemperature;
-
- /******************************************************/
- /*Start the conversion of the calibration offset value */
- /******************************************************/
- i_APCI3200_ReadCalibrationOffsetValue
- (dev, &ui_DummyValue);
- } /* if ((i_CJCFlag == 1) && (i_CalibrationFlag == 0)) */
-
- /********************************************************/
- /*Test if the value read is the calibration offset value */
- /********************************************************/
-
- if ((i_CalibrationFlag == 1)
- && (i_CJCFlag == 0)) {
- /* ui_InterruptChannelValue[i_Count + 1]=ui_DigitalTemperature; */
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue
- [s_BoardInfos[dev->minor].
- i_Count + 1] =
- ui_DigitalTemperature;
-
- /****************************************************/
- /*Start the conversion of the calibration gain value */
- /****************************************************/
- i_APCI3200_ReadCalibrationGainValue(dev,
- &ui_DummyValue);
-
- } /* if ((i_CalibrationFlag == 1) && (i_CJCFlag == 0)) */
-
- /******************************************************/
- /*Test if the value read is the calibration gain value */
- /******************************************************/
-
- if ((i_CalibrationFlag == 2)
- && (i_CJCFlag == 0)) {
- /* ui_InterruptChannelValue[i_Count + 2]=ui_DigitalTemperature; */
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue
- [s_BoardInfos[dev->minor].
- i_Count + 2] =
- ui_DigitalTemperature;
-
- /**********************************************************/
- /*Test if the Calibration channel must be read for the CJC */
- /**********************************************************/
-
- /*Test if the polarity is the same */
- /**********************************/
- /* if(i_CJCPolarity!=i_ADDIDATAPolarity) */
- if (s_BoardInfos[dev->minor].
- i_CJCPolarity !=
- s_BoardInfos[dev->minor].
- i_ADDIDATAPolarity) {
- i_ConvertCJCCalibration = 1;
- } /* if(i_CJCPolarity!=i_ADDIDATAPolarity) */
- else {
- /* if(i_CJCGain==i_ADDIDATAGain) */
- if (s_BoardInfos[dev->minor].
- i_CJCGain ==
- s_BoardInfos[dev->
- minor].
- i_ADDIDATAGain) {
- i_ConvertCJCCalibration
- = 0;
- } /* if(i_CJCGain==i_ADDIDATAGain) */
- else {
- i_ConvertCJCCalibration
- = 1;
- } /* elseif(i_CJCGain==i_ADDIDATAGain) */
- } /* elseif(i_CJCPolarity!=i_ADDIDATAPolarity) */
- if (i_ConvertCJCCalibration == 1) {
- /****************************************************************/
- /*Start the conversion of the calibration gain value for the CJC */
- /****************************************************************/
- i_APCI3200_ReadCJCCalOffset(dev,
- &ui_DummyValue);
-
- } /* if(i_ConvertCJCCalibration==1) */
- else {
- /* ui_InterruptChannelValue[i_Count + 4]=0; */
- /* ui_InterruptChannelValue[i_Count + 5]=0; */
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue
- [s_BoardInfos[dev->
- minor].i_Count +
- 4] = 0;
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue
- [s_BoardInfos[dev->
- minor].i_Count +
- 5] = 0;
- } /* elseif(i_ConvertCJCCalibration==1) */
- } /* else if ((i_CalibrationFlag == 2) && (i_CJCFlag == 0)) */
-
- /********************************************************************/
- /*Test if the value read is the calibration offset value for the CJC */
- /********************************************************************/
-
- if ((i_CalibrationFlag == 1)
- && (i_CJCFlag == 1)) {
- /* ui_InterruptChannelValue[i_Count + 4]=ui_DigitalTemperature; */
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue
- [s_BoardInfos[dev->minor].
- i_Count + 4] =
- ui_DigitalTemperature;
-
- /****************************************************************/
- /*Start the conversion of the calibration gain value for the CJC */
- /****************************************************************/
- i_APCI3200_ReadCJCCalGain(dev,
- &ui_DummyValue);
-
- } /* if ((i_CalibrationFlag == 1) && (i_CJCFlag == 1)) */
-
- /******************************************************************/
- /*Test if the value read is the calibration gain value for the CJC */
- /******************************************************************/
-
- if ((i_CalibrationFlag == 2)
- && (i_CJCFlag == 1)) {
- /* ui_InterruptChannelValue[i_Count + 5]=ui_DigitalTemperature; */
- s_BoardInfos[dev->minor].
- ui_InterruptChannelValue
- [s_BoardInfos[dev->minor].
- i_Count + 5] =
- ui_DigitalTemperature;
-
- /* if(i_ScanType==1) */
- if (s_BoardInfos[dev->minor].
- i_ScanType == 1) {
-
- /* i_InterruptFlag=0; */
- s_BoardInfos[dev->minor].
- i_InterruptFlag = 0;
- /* i_Count=i_Count + 6; */
- /* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
- /* s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count + 6; */
- s_BoardInfos[dev->minor].
- i_Count =
- s_BoardInfos[dev->
- minor].i_Count + 9;
- /* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
- } /* if(i_ScanType==1) */
- else {
- /* i_Count=0; */
- s_BoardInfos[dev->minor].
- i_Count = 0;
- } /* elseif(i_ScanType==1) */
-
- /* if(i_ScanType!=1) */
- if (s_BoardInfos[dev->minor].
- i_ScanType != 1) {
- send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */
- } /* if(i_ScanType!=1) */
- else {
- /* if(i_ChannelCount==i_Sum) */
- if (s_BoardInfos[dev->minor].
- i_ChannelCount ==
- s_BoardInfos[dev->
- minor].i_Sum) {
- send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */
-
- } /* if(i_ChannelCount==i_Sum) */
- } /* else if(i_ScanType!=1) */
- } /* if ((i_CalibrationFlag == 2) && (i_CJCFlag == 1)) */
-
- } /* else if ((ui_StatusRegister & 0x2) == 0x2) */
- break;
- } /* switch(i_ADDIDATAType) */
- break;
- case 2:
- case 3:
- i_APCI3200_InterruptHandleEos(dev);
- break;
- } /* switch(i_ScanType) */
- return;
-}
diff --git a/drivers/staging/comedi/drivers/addi_apci_035.c b/drivers/staging/comedi/drivers/addi_apci_035.c
deleted file mode 100644
index af70c8401880..000000000000
--- a/drivers/staging/comedi/drivers/addi_apci_035.c
+++ /dev/null
@@ -1,77 +0,0 @@
-#include <linux/module.h>
-#include <linux/pci.h>
-
-#include "../comedidev.h"
-#include "comedi_fc.h"
-#include "amcc_s5933.h"
-
-#include "addi-data/addi_common.h"
-
-#define ADDIDATA_WATCHDOG 2 /* Or shold it be something else */
-
-#include "addi-data/addi_eeprom.c"
-#include "addi-data/hwdrv_apci035.c"
-#include "addi-data/addi_common.c"
-
-static const struct addi_board apci035_boardtypes[] = {
- {
- .pc_DriverName = "apci035",
- .i_IorangeBase1 = APCI035_ADDRESS_RANGE,
- .i_PCIEeprom = 1,
- .pc_EepromChip = "S5920",
- .i_NbrAiChannel = 16,
- .i_NbrAiChannelDiff = 8,
- .i_AiChannelList = 16,
- .i_AiMaxdata = 0xff,
- .pr_AiRangelist = &range_apci035_ai,
- .i_Timer = 1,
- .ui_MinAcquisitiontimeNs = 10000,
- .ui_MinDelaytimeNs = 100000,
- .interrupt = apci035_interrupt,
- .reset = apci035_reset,
- .ai_config = apci035_ai_config,
- .ai_read = apci035_ai_read,
- .timer_config = apci035_timer_config,
- .timer_write = apci035_timer_write,
- .timer_read = apci035_timer_read,
- },
-};
-
-static int apci035_auto_attach(struct comedi_device *dev,
- unsigned long context)
-{
- dev->board_ptr = &apci035_boardtypes[0];
-
- return addi_auto_attach(dev, context);
-}
-
-static struct comedi_driver apci035_driver = {
- .driver_name = "addi_apci_035",
- .module = THIS_MODULE,
- .auto_attach = apci035_auto_attach,
- .detach = i_ADDI_Detach,
-};
-
-static int apci035_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *id)
-{
- return comedi_pci_auto_config(dev, &apci035_driver, id->driver_data);
-}
-
-static const struct pci_device_id apci035_pci_table[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x0300) },
- { 0 }
-};
-MODULE_DEVICE_TABLE(pci, apci035_pci_table);
-
-static struct pci_driver apci035_pci_driver = {
- .name = "addi_apci_035",
- .id_table = apci035_pci_table,
- .probe = apci035_pci_probe,
- .remove = comedi_pci_auto_unconfig,
-};
-module_comedi_pci_driver(apci035_driver, apci035_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/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c
index 840cb289507a..bf14165297b7 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1032.c
@@ -258,9 +258,8 @@ static irqreturn_t apci1032_interrupt(int irq, void *d)
outl(ctrl & ~APCI1032_CTRL_INT_ENA, dev->iobase + APCI1032_CTRL_REG);
s->state = inl(dev->iobase + APCI1032_STATUS_REG) & 0xffff;
- comedi_buf_put(s, s->state);
- s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
- comedi_event(dev, s);
+ comedi_buf_write_samples(s, &s->state, 1);
+ comedi_handle_events(dev, s);
/* enable the interrupt */
outl(ctrl, dev->iobase + APCI1032_CTRL_REG);
diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c
index b7a284ac6649..30b132c3d092 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1500.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1500.c
@@ -1,54 +1,109 @@
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
#include "../comedidev.h"
#include "comedi_fc.h"
#include "amcc_s5933.h"
-#include "addi-data/addi_common.h"
+struct apci1500_private {
+ int iobase;
+ int i_IobaseAmcc;
+ int i_IobaseAddon;
+ int i_IobaseReserved;
+ unsigned char b_OutputMemoryStatus;
+ struct task_struct *tsk_Current;
+};
-#include "addi-data/addi_eeprom.c"
#include "addi-data/hwdrv_apci1500.c"
-#include "addi-data/addi_common.c"
-
-static const struct addi_board apci1500_boardtypes[] = {
- {
- .pc_DriverName = "apci1500",
- .i_IorangeBase1 = APCI1500_ADDRESS_RANGE,
- .i_PCIEeprom = 0,
- .i_NbrDiChannel = 16,
- .i_NbrDoChannel = 16,
- .i_DoMaxdata = 0xffff,
- .i_Timer = 1,
- .interrupt = apci1500_interrupt,
- .reset = apci1500_reset,
- .di_config = apci1500_di_config,
- .di_read = apci1500_di_read,
- .di_write = apci1500_di_write,
- .di_bits = apci1500_di_insn_bits,
- .do_config = apci1500_do_config,
- .do_write = apci1500_do_write,
- .do_bits = apci1500_do_bits,
- .timer_config = apci1500_timer_config,
- .timer_write = apci1500_timer_write,
- .timer_read = apci1500_timer_read,
- .timer_bits = apci1500_timer_bits,
- },
-};
static int apci1500_auto_attach(struct comedi_device *dev,
unsigned long context)
{
- dev->board_ptr = &apci1500_boardtypes[0];
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ struct apci1500_private *devpriv;
+ struct comedi_subdevice *s;
+ int ret;
+
+ devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
+ if (!devpriv)
+ return -ENOMEM;
+
+ ret = comedi_pci_enable(dev);
+ if (ret)
+ return ret;
+
+ dev->iobase = pci_resource_start(pcidev, 1);
+ devpriv->iobase = dev->iobase;
+ devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0);
+ devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2);
+ devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3);
+
+ if (pcidev->irq > 0) {
+ ret = request_irq(pcidev->irq, apci1500_interrupt, IRQF_SHARED,
+ dev->board_name, dev);
+ if (ret == 0)
+ dev->irq = pcidev->irq;
+ }
+
+ ret = comedi_alloc_subdevices(dev, 3);
+ if (ret)
+ return ret;
- return addi_auto_attach(dev, context);
+ /* Allocate and Initialise DI Subdevice Structures */
+ s = &dev->subdevices[0];
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 16;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_config = apci1500_di_config;
+ s->insn_read = apci1500_di_read;
+ s->insn_write = apci1500_di_write;
+ s->insn_bits = apci1500_di_insn_bits;
+
+ /* Allocate and Initialise DO Subdevice Structures */
+ s = &dev->subdevices[1];
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 16;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_config = apci1500_do_config;
+ s->insn_write = apci1500_do_write;
+ s->insn_bits = apci1500_do_bits;
+
+ /* Allocate and Initialise Timer Subdevice Structures */
+ s = &dev->subdevices[2];
+ s->type = COMEDI_SUBD_TIMER;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = 1;
+ s->maxdata = 0;
+ s->len_chanlist = 1;
+ s->range_table = &range_digital;
+ s->insn_write = apci1500_timer_write;
+ s->insn_read = apci1500_timer_read;
+ s->insn_config = apci1500_timer_config;
+ s->insn_bits = apci1500_timer_bits;
+
+ apci1500_reset(dev);
+
+ return 0;
+}
+
+static void apci1500_detach(struct comedi_device *dev)
+{
+ if (dev->iobase)
+ apci1500_reset(dev);
+ comedi_pci_detach(dev);
}
static struct comedi_driver apci1500_driver = {
.driver_name = "addi_apci_1500",
.module = THIS_MODULE,
.auto_attach = apci1500_auto_attach,
- .detach = i_ADDI_Detach,
+ .detach = apci1500_detach,
};
static int apci1500_pci_probe(struct pci_dev *dev,
diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c
index 55d00fd94c91..d8410415cc90 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1516.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1516.c
@@ -163,7 +163,7 @@ static int apci1516_auto_attach(struct comedi_device *dev,
s = &dev->subdevices[1];
if (this_board->do_nchan) {
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITEABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = this_board->do_nchan;
s->maxdata = 1;
s->range_table = &range_digital;
diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c
index 688b015a834e..6872b69da5db 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1564.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1564.c
@@ -28,16 +28,91 @@
#include "../comedidev.h"
#include "comedi_fc.h"
-#include "amcc_s5933.h"
+#include "addi_tcw.h"
#include "addi_watchdog.h"
+/*
+ * PCI BAR 0
+ *
+ * PLD Revision 1.0 I/O Mapping
+ * 0x00 93C76 EEPROM
+ * 0x04 - 0x18 Timer 12-Bit
+ *
+ * PLD Revision 2.x I/O Mapping
+ * 0x00 93C76 EEPROM
+ * 0x04 - 0x14 Digital Input
+ * 0x18 - 0x25 Digital Output
+ * 0x28 - 0x44 Watchdog 8-Bit
+ * 0x48 - 0x64 Timer 12-Bit
+ */
+#define APCI1564_EEPROM_REG 0x00
+#define APCI1564_EEPROM_VCC_STATUS (1 << 8)
+#define APCI1564_EEPROM_TO_REV(x) (((x) >> 4) & 0xf)
+#define APCI1564_EEPROM_DI (1 << 3)
+#define APCI1564_EEPROM_DO (1 << 2)
+#define APCI1564_EEPROM_CS (1 << 1)
+#define APCI1564_EEPROM_CLK (1 << 0)
+#define APCI1564_REV1_TIMER_IOBASE 0x04
+#define APCI1564_REV2_MAIN_IOBASE 0x04
+#define APCI1564_REV2_TIMER_IOBASE 0x48
+
+/*
+ * PCI BAR 1
+ *
+ * PLD Revision 1.0 I/O Mapping
+ * 0x00 - 0x10 Digital Input
+ * 0x14 - 0x20 Digital Output
+ * 0x24 - 0x3c Watchdog 8-Bit
+ *
+ * PLD Revision 2.x I/O Mapping
+ * 0x00 Counter_0
+ * 0x20 Counter_1
+ * 0x30 Counter_3
+ */
+#define APCI1564_REV1_MAIN_IOBASE 0x00
+
+/*
+ * dev->iobase Register Map
+ * PLD Revision 1.0 - PCI BAR 1 + 0x00
+ * PLD Revision 2.x - PCI BAR 0 + 0x04
+ */
+#define APCI1564_DI_REG 0x00
+#define APCI1564_DI_INT_MODE1_REG 0x04
+#define APCI1564_DI_INT_MODE2_REG 0x08
+#define APCI1564_DI_INT_STATUS_REG 0x0c
+#define APCI1564_DI_IRQ_REG 0x10
+#define APCI1564_DO_REG 0x14
+#define APCI1564_DO_INT_CTRL_REG 0x18
+#define APCI1564_DO_INT_STATUS_REG 0x1c
+#define APCI1564_DO_IRQ_REG 0x20
+#define APCI1564_WDOG_REG 0x24
+#define APCI1564_WDOG_RELOAD_REG 0x28
+#define APCI1564_WDOG_TIMEBASE_REG 0x2c
+#define APCI1564_WDOG_CTRL_REG 0x30
+#define APCI1564_WDOG_STATUS_REG 0x34
+#define APCI1564_WDOG_IRQ_REG 0x38
+#define APCI1564_WDOG_WARN_TIMEVAL_REG 0x3c
+#define APCI1564_WDOG_WARN_TIMEBASE_REG 0x40
+
+/*
+ * devpriv->timer Register Map (see addi_tcw.h for register/bit defines)
+ * PLD Revision 1.0 - PCI BAR 0 + 0x04
+ * PLD Revision 2.x - PCI BAR 0 + 0x48
+ */
+
+/*
+ * devpriv->counters Register Map (see addi_tcw.h for register/bit defines)
+ * PLD Revision 2.x - PCI BAR 1 + 0x00
+ */
+#define APCI1564_COUNTER(x) ((x) * 0x20)
+
struct apci1564_private {
- unsigned int amcc_iobase; /* base of AMCC I/O registers */
+ unsigned long eeprom; /* base address of EEPROM register */
+ unsigned long timer; /* base address of 12-bit timer */
+ unsigned long counters; /* base address of 32-bit counters */
unsigned int mode1; /* riding-edge/high level channels */
unsigned int mode2; /* falling-edge/low level channels */
unsigned int ctrl; /* interrupt mode OR (edge) . AND (level) */
- unsigned char timer_select_mode;
- unsigned char mode_select_register;
struct task_struct *tsk_current;
};
@@ -48,27 +123,30 @@ static int apci1564_reset(struct comedi_device *dev)
struct apci1564_private *devpriv = dev->private;
/* Disable the input interrupts and reset status register */
- outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
- inl(devpriv->amcc_iobase + APCI1564_DI_INT_STATUS_REG);
- outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE1_REG);
- outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE2_REG);
+ outl(0x0, dev->iobase + APCI1564_DI_IRQ_REG);
+ inl(dev->iobase + APCI1564_DI_INT_STATUS_REG);
+ outl(0x0, dev->iobase + APCI1564_DI_INT_MODE1_REG);
+ outl(0x0, dev->iobase + APCI1564_DI_INT_MODE2_REG);
/* Reset the output channels and disable interrupts */
- outl(0x0, devpriv->amcc_iobase + APCI1564_DO_REG);
- outl(0x0, devpriv->amcc_iobase + APCI1564_DO_INT_CTRL_REG);
+ outl(0x0, dev->iobase + APCI1564_DO_REG);
+ outl(0x0, dev->iobase + APCI1564_DO_INT_CTRL_REG);
/* Reset the watchdog registers */
- addi_watchdog_reset(devpriv->amcc_iobase + APCI1564_WDOG_REG);
+ addi_watchdog_reset(dev->iobase + APCI1564_WDOG_REG);
/* Reset the timer registers */
- outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_RELOAD_REG);
+ outl(0x0, devpriv->timer + ADDI_TCW_CTRL_REG);
+ outl(0x0, devpriv->timer + ADDI_TCW_RELOAD_REG);
+
+ if (devpriv->counters) {
+ unsigned long iobase = devpriv->counters + ADDI_TCW_CTRL_REG;
- /* Reset the counter registers */
- outl(0x0, dev->iobase + APCI1564_COUNTER_CTRL_REG(APCI1564_COUNTER1));
- outl(0x0, dev->iobase + APCI1564_COUNTER_CTRL_REG(APCI1564_COUNTER2));
- outl(0x0, dev->iobase + APCI1564_COUNTER_CTRL_REG(APCI1564_COUNTER3));
- outl(0x0, dev->iobase + APCI1564_COUNTER_CTRL_REG(APCI1564_COUNTER4));
+ /* Reset the counter registers */
+ outl(0x0, iobase + APCI1564_COUNTER(0));
+ outl(0x0, iobase + APCI1564_COUNTER(1));
+ outl(0x0, iobase + APCI1564_COUNTER(2));
+ }
return 0;
}
@@ -82,55 +160,52 @@ static irqreturn_t apci1564_interrupt(int irq, void *d)
unsigned int ctrl;
unsigned int chan;
- /* check interrupt is from this device */
- if ((inl(devpriv->amcc_iobase + AMCC_OP_REG_INTCSR) &
- INTCSR_INTR_ASSERTED) == 0)
- return IRQ_NONE;
-
- status = inl(devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
+ status = inl(dev->iobase + APCI1564_DI_IRQ_REG);
if (status & APCI1564_DI_INT_ENABLE) {
/* disable the interrupt */
outl(status & APCI1564_DI_INT_DISABLE,
- devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
+ dev->iobase + APCI1564_DI_IRQ_REG);
- s->state = inl(dev->iobase + APCI1564_DI_INT_STATUS_REG)
- & 0xffff;
- comedi_buf_put(s, s->state);
- s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
- comedi_event(dev, s);
+ s->state = inl(dev->iobase + APCI1564_DI_INT_STATUS_REG) &
+ 0xffff;
+ comedi_buf_write_samples(s, &s->state, 1);
+ comedi_handle_events(dev, s);
/* enable the interrupt */
- outl(status, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
+ outl(status, dev->iobase + APCI1564_DI_IRQ_REG);
}
- status = inl(devpriv->amcc_iobase + APCI1564_TIMER_IRQ_REG);
+ status = inl(devpriv->timer + ADDI_TCW_IRQ_REG);
if (status & 0x01) {
/* Disable Timer Interrupt */
- ctrl = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
+ ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
+ outl(0x0, devpriv->timer + ADDI_TCW_CTRL_REG);
/* Send a signal to from kernel to user space */
send_sig(SIGIO, devpriv->tsk_current, 0);
/* Enable Timer Interrupt */
- outl(ctrl, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
+ outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
}
- for (chan = 0; chan < 4; chan++) {
- status = inl(dev->iobase + APCI1564_COUNTER_IRQ_REG(chan));
- if (status & 0x01) {
- /* Disable Counter Interrupt */
- ctrl = inl(dev->iobase +
- APCI1564_COUNTER_CTRL_REG(chan));
- outl(0x0, dev->iobase +
- APCI1564_COUNTER_CTRL_REG(chan));
-
- /* Send a signal to from kernel to user space */
- send_sig(SIGIO, devpriv->tsk_current, 0);
-
- /* Enable Counter Interrupt */
- outl(ctrl, dev->iobase +
- APCI1564_COUNTER_CTRL_REG(chan));
+ if (devpriv->counters) {
+ for (chan = 0; chan < 4; chan++) {
+ unsigned long iobase;
+
+ iobase = devpriv->counters + APCI1564_COUNTER(chan);
+
+ status = inl(iobase + ADDI_TCW_IRQ_REG);
+ if (status & 0x01) {
+ /* Disable Counter Interrupt */
+ ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
+ outl(0x0, iobase + ADDI_TCW_CTRL_REG);
+
+ /* Send a signal to from kernel to user space */
+ send_sig(SIGIO, devpriv->tsk_current, 0);
+
+ /* Enable Counter Interrupt */
+ outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
+ }
}
}
@@ -142,9 +217,7 @@ static int apci1564_di_insn_bits(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- struct apci1564_private *devpriv = dev->private;
-
- data[1] = inl(devpriv->amcc_iobase + APCI1564_DI_REG);
+ data[1] = inl(dev->iobase + APCI1564_DI_REG);
return insn->n;
}
@@ -154,12 +227,10 @@ static int apci1564_do_insn_bits(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- struct apci1564_private *devpriv = dev->private;
-
- s->state = inl(devpriv->amcc_iobase + APCI1564_DO_REG);
+ s->state = inl(dev->iobase + APCI1564_DO_REG);
if (comedi_dio_update_state(s, data))
- outl(s->state, devpriv->amcc_iobase + APCI1564_DO_REG);
+ outl(s->state, dev->iobase + APCI1564_DO_REG);
data[1] = s->state;
@@ -171,9 +242,7 @@ static int apci1564_diag_insn_bits(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- struct apci1564_private *devpriv = dev->private;
-
- data[1] = inl(devpriv->amcc_iobase + APCI1564_DO_INT_STATUS_REG) & 3;
+ data[1] = inl(dev->iobase + APCI1564_DO_INT_STATUS_REG) & 3;
return insn->n;
}
@@ -227,10 +296,10 @@ static int apci1564_cos_insn_config(struct comedi_device *dev,
devpriv->ctrl = 0;
devpriv->mode1 = 0;
devpriv->mode2 = 0;
- outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
- inl(devpriv->amcc_iobase + APCI1564_DI_INT_STATUS_REG);
- outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE1_REG);
- outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE2_REG);
+ outl(0x0, dev->iobase + APCI1564_DI_IRQ_REG);
+ inl(dev->iobase + APCI1564_DI_INT_STATUS_REG);
+ outl(0x0, dev->iobase + APCI1564_DI_INT_MODE1_REG);
+ outl(0x0, dev->iobase + APCI1564_DI_INT_MODE2_REG);
break;
case COMEDI_DIGITAL_TRIG_ENABLE_EDGES:
if (devpriv->ctrl != (APCI1564_DI_INT_ENABLE |
@@ -342,9 +411,9 @@ static int apci1564_cos_cmd(struct comedi_device *dev,
return -EINVAL;
}
- outl(devpriv->mode1, devpriv->amcc_iobase + APCI1564_DI_INT_MODE1_REG);
- outl(devpriv->mode2, devpriv->amcc_iobase + APCI1564_DI_INT_MODE2_REG);
- outl(devpriv->ctrl, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
+ outl(devpriv->mode1, dev->iobase + APCI1564_DI_INT_MODE1_REG);
+ outl(devpriv->mode2, dev->iobase + APCI1564_DI_INT_MODE2_REG);
+ outl(devpriv->ctrl, dev->iobase + APCI1564_DI_IRQ_REG);
return 0;
}
@@ -352,12 +421,10 @@ static int apci1564_cos_cmd(struct comedi_device *dev,
static int apci1564_cos_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- struct apci1564_private *devpriv = dev->private;
-
- outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
- inl(devpriv->amcc_iobase + APCI1564_DI_INT_STATUS_REG);
- outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE1_REG);
- outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE2_REG);
+ outl(0x0, dev->iobase + APCI1564_DI_IRQ_REG);
+ inl(dev->iobase + APCI1564_DI_INT_STATUS_REG);
+ outl(0x0, dev->iobase + APCI1564_DI_INT_MODE1_REG);
+ outl(0x0, dev->iobase + APCI1564_DI_INT_MODE2_REG);
return 0;
}
@@ -368,6 +435,7 @@ static int apci1564_auto_attach(struct comedi_device *dev,
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
struct apci1564_private *devpriv;
struct comedi_subdevice *s;
+ unsigned int val;
int ret;
devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
@@ -378,8 +446,20 @@ static int apci1564_auto_attach(struct comedi_device *dev,
if (ret)
return ret;
- dev->iobase = pci_resource_start(pcidev, 1);
- devpriv->amcc_iobase = pci_resource_start(pcidev, 0);
+ /* read the EEPROM register and check the I/O map revision */
+ devpriv->eeprom = pci_resource_start(pcidev, 0);
+ val = inl(devpriv->eeprom + APCI1564_EEPROM_REG);
+ if (APCI1564_EEPROM_TO_REV(val) == 0) {
+ /* PLD Revision 1.0 I/O Mapping */
+ dev->iobase = pci_resource_start(pcidev, 1) +
+ APCI1564_REV1_MAIN_IOBASE;
+ devpriv->timer = devpriv->eeprom + APCI1564_REV1_TIMER_IOBASE;
+ } else {
+ /* PLD Revision 2.x I/O Mapping */
+ dev->iobase = devpriv->eeprom + APCI1564_REV2_MAIN_IOBASE;
+ devpriv->timer = devpriv->eeprom + APCI1564_REV2_TIMER_IOBASE;
+ devpriv->counters = pci_resource_start(pcidev, 1);
+ }
apci1564_reset(dev);
@@ -390,7 +470,7 @@ static int apci1564_auto_attach(struct comedi_device *dev,
dev->irq = pcidev->irq;
}
- ret = comedi_alloc_subdevices(dev, 6);
+ ret = comedi_alloc_subdevices(dev, 7);
if (ret)
return ret;
@@ -406,7 +486,7 @@ static int apci1564_auto_attach(struct comedi_device *dev,
/* Allocate and Initialise DO Subdevice Structures */
s = &dev->subdevices[1];
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITEABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 32;
s->maxdata = 1;
s->range_table = &range_digital;
@@ -431,26 +511,40 @@ static int apci1564_auto_attach(struct comedi_device *dev,
s->type = COMEDI_SUBD_UNUSED;
}
- /* Allocate and Initialise Timer Subdevice Structures */
+ /* Timer subdevice */
s = &dev->subdevices[3];
s->type = COMEDI_SUBD_TIMER;
- s->subdev_flags = SDF_WRITEABLE;
+ s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
s->n_chan = 1;
- s->maxdata = 0;
- s->len_chanlist = 1;
+ s->maxdata = 0x0fff;
s->range_table = &range_digital;
- s->insn_write = apci1564_timer_write;
- s->insn_read = apci1564_timer_read;
- s->insn_config = apci1564_timer_config;
+ s->insn_config = apci1564_timer_insn_config;
+ s->insn_write = apci1564_timer_insn_write;
+ s->insn_read = apci1564_timer_insn_read;
- /* Initialize the watchdog subdevice */
+ /* Counter subdevice */
s = &dev->subdevices[4];
- ret = addi_watchdog_init(s, devpriv->amcc_iobase + APCI1564_WDOG_REG);
+ if (devpriv->counters) {
+ s->type = COMEDI_SUBD_COUNTER;
+ s->subdev_flags = SDF_WRITABLE | SDF_READABLE | SDF_LSAMPL;
+ s->n_chan = 3;
+ s->maxdata = 0xffffffff;
+ s->range_table = &range_digital;
+ s->insn_config = apci1564_counter_insn_config;
+ s->insn_write = apci1564_counter_insn_write;
+ s->insn_read = apci1564_counter_insn_read;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+
+ /* Initialize the watchdog subdevice */
+ s = &dev->subdevices[5];
+ ret = addi_watchdog_init(s, dev->iobase + APCI1564_WDOG_REG);
if (ret)
return ret;
/* Initialize the diagnostic status subdevice */
- s = &dev->subdevices[5];
+ s = &dev->subdevices[6];
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
s->n_chan = 2;
diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c
index 4162e2dc2860..a1248dab369f 100644
--- a/drivers/staging/comedi/drivers/addi_apci_16xx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c
@@ -140,7 +140,7 @@ static int apci16xx_auto_attach(struct comedi_device *dev,
for (i = 0; i < n_subdevs; i++) {
s = &dev->subdevices[i];
s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_WRITEABLE | SDF_READABLE;
+ s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
s->n_chan = ((i * 32) < board->n_chan) ? 32 : last;
s->maxdata = 1;
s->range_table = &range_digital;
diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c
index aea3da325359..eebf4f151b39 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2032.c
@@ -47,7 +47,6 @@
struct apci2032_int_private {
spinlock_t spinlock;
- unsigned int stop_count;
bool active;
unsigned char enabled_isns;
};
@@ -148,7 +147,6 @@ static int apci2032_int_cmd(struct comedi_device *dev,
spin_lock_irqsave(&subpriv->spinlock, flags);
subpriv->enabled_isns = enabled_isns;
- subpriv->stop_count = cmd->stop_arg;
subpriv->active = true;
outl(enabled_isns, dev->iobase + APCI2032_INT_CTRL_REG);
@@ -178,7 +176,6 @@ static irqreturn_t apci2032_interrupt(int irq, void *d)
struct comedi_cmd *cmd = &s->async->cmd;
struct apci2032_int_private *subpriv;
unsigned int val;
- bool do_event = false;
if (!dev->attached)
return IRQ_NONE;
@@ -212,27 +209,16 @@ static irqreturn_t apci2032_interrupt(int irq, void *d)
bits |= (1 << i);
}
- if (comedi_buf_put(s, bits)) {
- s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
- if (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;
+ comedi_buf_write_samples(s, &bits, 1);
+
+ if (cmd->stop_src == TRIG_COUNT &&
+ s->async->scans_done >= cmd->stop_arg)
+ s->async->events |= COMEDI_CB_EOA;
}
spin_unlock(&subpriv->spinlock);
- if (do_event)
- comedi_event(dev, s);
+
+ comedi_handle_events(dev, s);
return IRQ_HANDLED;
}
@@ -274,7 +260,7 @@ static int apci2032_auto_attach(struct comedi_device *dev,
/* Initialize the digital output subdevice */
s = &dev->subdevices[0];
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITEABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 32;
s->maxdata = 1;
s->range_table = &range_digital;
@@ -303,7 +289,7 @@ static int apci2032_auto_attach(struct comedi_device *dev,
return -ENOMEM;
spin_lock_init(&subpriv->spinlock);
s->private = subpriv;
- s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
+ s->subdev_flags = SDF_READABLE | SDF_CMD_READ | SDF_PACKED;
s->len_chanlist = 2;
s->do_cmdtest = apci2032_int_cmdtest;
s->do_cmd = apci2032_int_cmd;
diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c
index 51ab1f937bae..1f9d13661ac9 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2200.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2200.c
@@ -98,7 +98,7 @@ static int apci2200_auto_attach(struct comedi_device *dev,
/* Initialize the digital output subdevice */
s = &dev->subdevices[1];
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITEABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 16;
s->maxdata = 1;
s->range_table = &range_digital;
diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c
index ba71e24a56fd..c65f9407fd06 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3120.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3120.c
@@ -1,70 +1,993 @@
+/*
+ * addi_apci_3120.c
+ * 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.
+ */
+
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/interrupt.h>
#include "../comedidev.h"
#include "comedi_fc.h"
#include "amcc_s5933.h"
-#include "addi-data/addi_common.h"
+/*
+ * PCI BAR 0 register map (devpriv->amcc)
+ * see amcc_s5933.h for register and bit defines
+ */
+#define APCI3120_FIFO_ADVANCE_ON_BYTE_2 (1 << 29)
+
+/*
+ * PCI BAR 1 register map (dev->iobase)
+ */
+#define APCI3120_AI_FIFO_REG 0x00
+#define APCI3120_CTRL_REG 0x00
+#define APCI3120_CTRL_EXT_TRIG (1 << 15)
+#define APCI3120_CTRL_GATE(x) (1 << (12 + (x)))
+#define APCI3120_CTRL_PR(x) (((x) & 0xf) << 8)
+#define APCI3120_CTRL_PA(x) (((x) & 0xf) << 0)
+#define APCI3120_AI_SOFTTRIG_REG 0x02
+#define APCI3120_STATUS_REG 0x02
+#define APCI3120_STATUS_EOC_INT (1 << 15)
+#define APCI3120_STATUS_AMCC_INT (1 << 14)
+#define APCI3120_STATUS_EOS_INT (1 << 13)
+#define APCI3120_STATUS_TIMER2_INT (1 << 12)
+#define APCI3120_STATUS_INT_MASK (0xf << 12)
+#define APCI3120_STATUS_TO_DI_BITS(x) (((x) >> 8) & 0xf)
+#define APCI3120_STATUS_TO_VERSION(x) (((x) >> 4) & 0xf)
+#define APCI3120_STATUS_FIFO_FULL (1 << 2)
+#define APCI3120_STATUS_FIFO_EMPTY (1 << 1)
+#define APCI3120_STATUS_DA_READY (1 << 0)
+#define APCI3120_TIMER_REG 0x04
+#define APCI3120_CHANLIST_REG 0x06
+#define APCI3120_CHANLIST_INDEX(x) (((x) & 0xf) << 8)
+#define APCI3120_CHANLIST_UNIPOLAR (1 << 7)
+#define APCI3120_CHANLIST_GAIN(x) (((x) & 0x3) << 4)
+#define APCI3120_CHANLIST_MUX(x) (((x) & 0xf) << 0)
+#define APCI3120_AO_REG(x) (0x08 + (((x) / 4) * 2))
+#define APCI3120_AO_MUX(x) (((x) & 0x3) << 14)
+#define APCI3120_AO_DATA(x) ((x) << 0)
+#define APCI3120_TIMER_MODE_REG 0x0c
+#define APCI3120_TIMER_MODE(_t, _m) ((_m) << ((_t) * 2))
+#define APCI3120_TIMER_MODE0 0 /* I8254_MODE0 */
+#define APCI3120_TIMER_MODE2 1 /* I8254_MODE2 */
+#define APCI3120_TIMER_MODE4 2 /* I8254_MODE4 */
+#define APCI3120_TIMER_MODE5 3 /* I8254_MODE5 */
+#define APCI3120_TIMER_MODE_MASK(_t) (3 << ((_t) * 2))
+#define APCI3120_CTR0_REG 0x0d
+#define APCI3120_CTR0_DO_BITS(x) ((x) << 4)
+#define APCI3120_CTR0_TIMER_SEL(x) ((x) << 0)
+#define APCI3120_MODE_REG 0x0e
+#define APCI3120_MODE_TIMER2_CLK_OSC (0 << 6)
+#define APCI3120_MODE_TIMER2_CLK_OUT1 (1 << 6)
+#define APCI3120_MODE_TIMER2_CLK_EOC (2 << 6)
+#define APCI3120_MODE_TIMER2_CLK_EOS (3 << 6)
+#define APCI3120_MODE_TIMER2_CLK_MASK (3 << 6)
+#define APCI3120_MODE_TIMER2_AS_TIMER (0 << 4)
+#define APCI3120_MODE_TIMER2_AS_COUNTER (1 << 4)
+#define APCI3120_MODE_TIMER2_AS_WDOG (2 << 4)
+#define APCI3120_MODE_TIMER2_AS_MASK (3 << 4) /* sets AS_TIMER */
+#define APCI3120_MODE_SCAN_ENA (1 << 3)
+#define APCI3120_MODE_TIMER2_IRQ_ENA (1 << 2)
+#define APCI3120_MODE_EOS_IRQ_ENA (1 << 1)
+#define APCI3120_MODE_EOC_IRQ_ENA (1 << 0)
+
+/*
+ * PCI BAR 2 register map (devpriv->addon)
+ */
+#define APCI3120_ADDON_ADDR_REG 0x00
+#define APCI3120_ADDON_DATA_REG 0x02
+#define APCI3120_ADDON_CTRL_REG 0x04
+#define APCI3120_ADDON_CTRL_AMWEN_ENA (1 << 1)
+#define APCI3120_ADDON_CTRL_A2P_FIFO_ENA (1 << 0)
-#include "addi-data/hwdrv_apci3120.c"
+/*
+ * Board revisions
+ */
+#define APCI3120_REVA 0xa
+#define APCI3120_REVB 0xb
+#define APCI3120_REVA_OSC_BASE 70 /* 70ns = 14.29MHz */
+#define APCI3120_REVB_OSC_BASE 50 /* 50ns = 20MHz */
+
+static const struct comedi_lrange apci3120_ai_range = {
+ 8, {
+ BIP_RANGE(10),
+ BIP_RANGE(5),
+ BIP_RANGE(2),
+ BIP_RANGE(1),
+ UNI_RANGE(10),
+ UNI_RANGE(5),
+ UNI_RANGE(2),
+ UNI_RANGE(1)
+ }
+};
enum apci3120_boardid {
BOARD_APCI3120,
BOARD_APCI3001,
};
-static const struct addi_board apci3120_boardtypes[] = {
+struct apci3120_board {
+ const char *name;
+ unsigned int ai_is_16bit:1;
+ unsigned int has_ao:1;
+};
+
+static const struct apci3120_board apci3120_boardtypes[] = {
[BOARD_APCI3120] = {
- .pc_DriverName = "apci3120",
- .i_NbrAiChannel = 16,
- .i_NbrAiChannelDiff = 8,
- .i_AiChannelList = 16,
- .i_NbrAoChannel = 8,
- .i_AiMaxdata = 0xffff,
- .i_AoMaxdata = 0x3fff,
- .i_NbrDiChannel = 4,
- .i_NbrDoChannel = 4,
- .i_DoMaxdata = 0x0f,
- .interrupt = apci3120_interrupt,
+ .name = "apci3120",
+ .ai_is_16bit = 1,
+ .has_ao = 1,
},
[BOARD_APCI3001] = {
- .pc_DriverName = "apci3001",
- .i_NbrAiChannel = 16,
- .i_NbrAiChannelDiff = 8,
- .i_AiChannelList = 16,
- .i_AiMaxdata = 0xfff,
- .i_NbrDiChannel = 4,
- .i_NbrDoChannel = 4,
- .i_DoMaxdata = 0x0f,
- .interrupt = apci3120_interrupt,
+ .name = "apci3001",
},
};
-static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
+struct apci3120_dmabuf {
+ unsigned short *virt;
+ dma_addr_t hw;
+ unsigned int size;
+ unsigned int use_size;
+};
+
+struct apci3120_private {
+ unsigned long amcc;
+ unsigned long addon;
+ unsigned int osc_base;
+ unsigned int use_dma:1;
+ unsigned int use_double_buffer:1;
+ unsigned int cur_dmabuf:1;
+ struct apci3120_dmabuf dmabuf[2];
+ unsigned char do_bits;
+ unsigned char timer_mode;
+ unsigned char mode;
+ unsigned short ctrl;
+};
+
+static void apci3120_addon_write(struct comedi_device *dev,
+ unsigned int val, unsigned int reg)
+{
+ struct apci3120_private *devpriv = dev->private;
+
+ /* 16-bit interface for AMCC add-on registers */
+
+ outw(reg, devpriv->addon + APCI3120_ADDON_ADDR_REG);
+ outw(val & 0xffff, devpriv->addon + APCI3120_ADDON_DATA_REG);
+
+ outw(reg + 2, devpriv->addon + APCI3120_ADDON_ADDR_REG);
+ outw((val >> 16) & 0xffff, devpriv->addon + APCI3120_ADDON_DATA_REG);
+}
+
+static void apci3120_init_dma(struct comedi_device *dev,
+ struct apci3120_dmabuf *dmabuf)
+{
+ struct apci3120_private *devpriv = dev->private;
+
+ /* AMCC - enable transfer count and reset A2P FIFO */
+ outl(AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO,
+ devpriv->amcc + AMCC_OP_REG_AGCSTS);
+
+ /* Add-On - enable transfer count and reset A2P FIFO */
+ apci3120_addon_write(dev, AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO,
+ AMCC_OP_REG_AGCSTS);
+
+ /* AMCC - enable transfers and reset A2P flags */
+ outl(RESET_A2P_FLAGS | EN_A2P_TRANSFERS,
+ devpriv->amcc + AMCC_OP_REG_MCSR);
+
+ /* Add-On - DMA start address */
+ apci3120_addon_write(dev, dmabuf->hw, AMCC_OP_REG_AMWAR);
+
+ /* Add-On - Number of acquisitions */
+ apci3120_addon_write(dev, dmabuf->use_size, AMCC_OP_REG_AMWTC);
+
+ /* AMCC - enable write complete (DMA) and set FIFO advance */
+ outl(APCI3120_FIFO_ADVANCE_ON_BYTE_2 | AINT_WRITE_COMPL,
+ devpriv->amcc + AMCC_OP_REG_INTCSR);
+
+ /* Add-On - enable DMA */
+ outw(APCI3120_ADDON_CTRL_AMWEN_ENA | APCI3120_ADDON_CTRL_A2P_FIFO_ENA,
+ devpriv->addon + APCI3120_ADDON_CTRL_REG);
+}
+
+static void apci3120_setup_dma(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ struct apci3120_private *devpriv = dev->private;
+ struct comedi_cmd *cmd = &s->async->cmd;
+ struct apci3120_dmabuf *dmabuf0 = &devpriv->dmabuf[0];
+ struct apci3120_dmabuf *dmabuf1 = &devpriv->dmabuf[1];
+ unsigned int dmalen0 = dmabuf0->size;
+ unsigned int dmalen1 = dmabuf1->size;
+ unsigned int scan_bytes;
+
+ scan_bytes = comedi_samples_to_bytes(s, cmd->scan_end_arg);
+
+ if (cmd->stop_src == TRIG_COUNT) {
+ /*
+ * Must we fill full first buffer? And must we fill
+ * full second buffer when first is once filled?
+ */
+ if (dmalen0 > (cmd->stop_arg * scan_bytes))
+ dmalen0 = cmd->stop_arg * scan_bytes;
+ else if (dmalen1 > (cmd->stop_arg * scan_bytes - dmalen0))
+ dmalen1 = cmd->stop_arg * scan_bytes - dmalen0;
+ }
+
+ if (cmd->flags & CMDF_WAKE_EOS) {
+ /* don't we want wake up every scan? */
+ if (dmalen0 > scan_bytes) {
+ dmalen0 = scan_bytes;
+ if (cmd->scan_end_arg & 1)
+ dmalen0 += 2;
+ }
+ if (dmalen1 > scan_bytes) {
+ dmalen1 = scan_bytes;
+ if (cmd->scan_end_arg & 1)
+ dmalen1 -= 2;
+ if (dmalen1 < 4)
+ dmalen1 = 4;
+ }
+ } else {
+ /* isn't output buff smaller that our DMA buff? */
+ if (dmalen0 > s->async->prealloc_bufsz)
+ dmalen0 = s->async->prealloc_bufsz;
+ if (dmalen1 > s->async->prealloc_bufsz)
+ dmalen1 = s->async->prealloc_bufsz;
+ }
+ dmabuf0->use_size = dmalen0;
+ dmabuf1->use_size = dmalen1;
+
+ apci3120_init_dma(dev, dmabuf0);
+}
+
+/*
+ * There are three timers on the board. They all use the same base
+ * clock with a fixed prescaler for each timer. The base clock used
+ * depends on the board version and type.
+ *
+ * APCI-3120 Rev A boards OSC = 14.29MHz base clock (~70ns)
+ * APCI-3120 Rev B boards OSC = 20MHz base clock (50ns)
+ * APCI-3001 boards OSC = 20MHz base clock (50ns)
+ *
+ * The prescalers for each timer are:
+ * Timer 0 CLK = OSC/10
+ * Timer 1 CLK = OSC/1000
+ * Timer 2 CLK = OSC/1000
+ */
+static unsigned int apci3120_ns_to_timer(struct comedi_device *dev,
+ unsigned int timer,
+ unsigned int ns,
+ unsigned int flags)
+{
+ struct apci3120_private *devpriv = dev->private;
+ unsigned int prescale = (timer == 0) ? 10 : 1000;
+ unsigned int timer_base = devpriv->osc_base * prescale;
+ unsigned int divisor;
+
+ switch (flags & CMDF_ROUND_MASK) {
+ case CMDF_ROUND_UP:
+ divisor = DIV_ROUND_UP(ns, timer_base);
+ break;
+ case CMDF_ROUND_DOWN:
+ divisor = ns / timer_base;
+ break;
+ case CMDF_ROUND_NEAREST:
+ default:
+ divisor = DIV_ROUND_CLOSEST(ns, timer_base);
+ break;
+ }
+
+ if (timer == 2) {
+ /* timer 2 is 24-bits */
+ if (divisor > 0x00ffffff)
+ divisor = 0x00ffffff;
+ } else {
+ /* timers 0 and 1 are 16-bits */
+ if (divisor > 0xffff)
+ divisor = 0xffff;
+ }
+ /* the timers require a minimum divisor of 2 */
+ if (divisor < 2)
+ divisor = 2;
+
+ return divisor;
+}
+
+static void apci3120_clr_timer2_interrupt(struct comedi_device *dev)
+{
+ /* a dummy read of APCI3120_CTR0_REG clears the timer 2 interrupt */
+ inb(dev->iobase + APCI3120_CTR0_REG);
+}
+
+static void apci3120_timer_write(struct comedi_device *dev,
+ unsigned int timer, unsigned int val)
+{
+ struct apci3120_private *devpriv = dev->private;
+
+ /* write 16-bit value to timer (lower 16-bits of timer 2) */
+ outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) |
+ APCI3120_CTR0_TIMER_SEL(timer),
+ dev->iobase + APCI3120_CTR0_REG);
+ outw(val & 0xffff, dev->iobase + APCI3120_TIMER_REG);
+
+ if (timer == 2) {
+ /* write upper 16-bits to timer 2 */
+ outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) |
+ APCI3120_CTR0_TIMER_SEL(timer + 1),
+ dev->iobase + APCI3120_CTR0_REG);
+ outw((val >> 16) & 0xffff, dev->iobase + APCI3120_TIMER_REG);
+ }
+}
+
+static unsigned int apci3120_timer_read(struct comedi_device *dev,
+ unsigned int timer)
+{
+ struct apci3120_private *devpriv = dev->private;
+ unsigned int val;
+
+ /* read 16-bit value from timer (lower 16-bits of timer 2) */
+ outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) |
+ APCI3120_CTR0_TIMER_SEL(timer),
+ dev->iobase + APCI3120_CTR0_REG);
+ val = inw(dev->iobase + APCI3120_TIMER_REG);
+
+ if (timer == 2) {
+ /* read upper 16-bits from timer 2 */
+ outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) |
+ APCI3120_CTR0_TIMER_SEL(timer + 1),
+ dev->iobase + APCI3120_CTR0_REG);
+ val |= (inw(dev->iobase + APCI3120_TIMER_REG) << 16);
+ }
+
+ return val;
+}
+
+static void apci3120_timer_set_mode(struct comedi_device *dev,
+ unsigned int timer, unsigned int mode)
+{
+ struct apci3120_private *devpriv = dev->private;
+
+ devpriv->timer_mode &= ~APCI3120_TIMER_MODE_MASK(timer);
+ devpriv->timer_mode |= APCI3120_TIMER_MODE(timer, mode);
+ outb(devpriv->timer_mode, dev->iobase + APCI3120_TIMER_MODE_REG);
+}
+
+static void apci3120_timer_enable(struct comedi_device *dev,
+ unsigned int timer, bool enable)
+{
+ struct apci3120_private *devpriv = dev->private;
+
+ if (enable)
+ devpriv->ctrl |= APCI3120_CTRL_GATE(timer);
+ else
+ devpriv->ctrl &= ~APCI3120_CTRL_GATE(timer);
+ outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG);
+}
+
+static void apci3120_exttrig_enable(struct comedi_device *dev, bool enable)
+{
+ struct apci3120_private *devpriv = dev->private;
+
+ if (enable)
+ devpriv->ctrl |= APCI3120_CTRL_EXT_TRIG;
+ else
+ devpriv->ctrl &= ~APCI3120_CTRL_EXT_TRIG;
+ outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG);
+}
+
+static void apci3120_set_chanlist(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ int n_chan, unsigned int *chanlist)
+{
+ struct apci3120_private *devpriv = dev->private;
+ int i;
+
+ /* set chanlist for scan */
+ for (i = 0; i < n_chan; i++) {
+ unsigned int chan = CR_CHAN(chanlist[i]);
+ unsigned int range = CR_RANGE(chanlist[i]);
+ unsigned int val;
+
+ val = APCI3120_CHANLIST_MUX(chan) |
+ APCI3120_CHANLIST_GAIN(range) |
+ APCI3120_CHANLIST_INDEX(i);
+
+ if (comedi_range_is_unipolar(s, range))
+ val |= APCI3120_CHANLIST_UNIPOLAR;
+
+ outw(val, dev->iobase + APCI3120_CHANLIST_REG);
+ }
+
+ /* a dummy read of APCI3120_TIMER_MODE_REG resets the ai FIFO */
+ inw(dev->iobase + APCI3120_TIMER_MODE_REG);
+
+ /* set scan length (PR) and scan start (PA) */
+ devpriv->ctrl = APCI3120_CTRL_PR(n_chan - 1) | APCI3120_CTRL_PA(0);
+ outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG);
+
+ /* enable chanlist scanning if necessary */
+ if (n_chan > 1)
+ devpriv->mode |= APCI3120_MODE_SCAN_ENA;
+}
+
+static void apci3120_interrupt_dma(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ struct apci3120_private *devpriv = dev->private;
+ struct comedi_async *async = s->async;
+ struct comedi_cmd *cmd = &async->cmd;
+ struct apci3120_dmabuf *dmabuf;
+ unsigned int nbytes;
+ unsigned int nsamples;
+
+ dmabuf = &devpriv->dmabuf[devpriv->cur_dmabuf];
+
+ nbytes = dmabuf->use_size - inl(devpriv->amcc + AMCC_OP_REG_MWTC);
+
+ if (nbytes < dmabuf->use_size)
+ dev_err(dev->class_dev, "Interrupted DMA transfer!\n");
+ if (nbytes & 1) {
+ dev_err(dev->class_dev, "Odd count of bytes in DMA ring!\n");
+ async->events |= COMEDI_CB_ERROR;
+ return;
+ }
+
+ nsamples = comedi_bytes_to_samples(s, nbytes);
+ if (nsamples) {
+ comedi_buf_write_samples(s, dmabuf->virt, nsamples);
+
+ if (!(cmd->flags & CMDF_WAKE_EOS))
+ async->events |= COMEDI_CB_EOS;
+ }
+
+ if ((async->events & COMEDI_CB_CANCEL_MASK) ||
+ (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg))
+ return;
+
+ if (devpriv->use_double_buffer) {
+ /* switch DMA buffers for next interrupt */
+ devpriv->cur_dmabuf = !devpriv->cur_dmabuf;
+ dmabuf = &devpriv->dmabuf[devpriv->cur_dmabuf];
+ apci3120_init_dma(dev, dmabuf);
+ } else {
+ /* restart DMA if not using double buffering */
+ apci3120_init_dma(dev, dmabuf);
+ }
+}
+
+static irqreturn_t apci3120_interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
- const struct addi_board *this_board = dev->board_ptr;
+ struct apci3120_private *devpriv = dev->private;
+ struct comedi_subdevice *s = dev->read_subdev;
+ struct comedi_async *async = s->async;
+ struct comedi_cmd *cmd = &async->cmd;
+ unsigned int status;
+ unsigned int int_amcc;
+
+ status = inw(dev->iobase + APCI3120_STATUS_REG);
+ int_amcc = inl(devpriv->amcc + AMCC_OP_REG_INTCSR);
+
+ if (!(status & APCI3120_STATUS_INT_MASK) &&
+ !(int_amcc & ANY_S593X_INT)) {
+ dev_err(dev->class_dev, "IRQ from unknown source\n");
+ return IRQ_NONE;
+ }
+
+ outl(int_amcc | AINT_INT_MASK, devpriv->amcc + AMCC_OP_REG_INTCSR);
- this_board->interrupt(irq, d);
- return IRQ_RETVAL(1);
+ if (devpriv->ctrl & APCI3120_CTRL_EXT_TRIG)
+ apci3120_exttrig_enable(dev, false);
+
+ if (int_amcc & MASTER_ABORT_INT)
+ dev_err(dev->class_dev, "AMCC IRQ - MASTER DMA ABORT!\n");
+ if (int_amcc & TARGET_ABORT_INT)
+ dev_err(dev->class_dev, "AMCC IRQ - TARGET DMA ABORT!\n");
+
+ if ((status & APCI3120_STATUS_EOC_INT) == 0 &&
+ (devpriv->mode & APCI3120_MODE_EOC_IRQ_ENA)) {
+ /* nothing to do... EOC mode is not currently used */
+ }
+
+ if ((status & APCI3120_STATUS_EOS_INT) &&
+ (devpriv->mode & APCI3120_MODE_EOS_IRQ_ENA)) {
+ unsigned short val;
+ int i;
+
+ for (i = 0; i < cmd->chanlist_len; i++) {
+ val = inw(dev->iobase + APCI3120_AI_FIFO_REG);
+ comedi_buf_write_samples(s, &val, 1);
+ }
+
+ devpriv->mode |= APCI3120_MODE_EOS_IRQ_ENA;
+ outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
+ }
+
+ if (status & APCI3120_STATUS_TIMER2_INT) {
+ /*
+ * for safety...
+ * timer2 interrupts are not enabled in the driver
+ */
+ apci3120_clr_timer2_interrupt(dev);
+ }
+
+ if (status & APCI3120_STATUS_AMCC_INT) {
+ /* AMCC- Clear write complete interrupt (DMA) */
+ outl(AINT_WT_COMPLETE, devpriv->amcc + AMCC_OP_REG_INTCSR);
+
+ /* do some data transfer */
+ apci3120_interrupt_dma(dev, s);
+ }
+
+ if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
+ async->events |= COMEDI_CB_EOA;
+
+ comedi_handle_events(dev, s);
+
+ return IRQ_HANDLED;
+}
+
+static int apci3120_ai_cmd(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ struct apci3120_private *devpriv = dev->private;
+ struct comedi_cmd *cmd = &s->async->cmd;
+ unsigned int divisor;
+
+ /* set default mode bits */
+ devpriv->mode = APCI3120_MODE_TIMER2_CLK_OSC |
+ APCI3120_MODE_TIMER2_AS_TIMER;
+
+ /* AMCC- Clear write complete interrupt (DMA) */
+ outl(AINT_WT_COMPLETE, devpriv->amcc + AMCC_OP_REG_INTCSR);
+
+ devpriv->cur_dmabuf = 0;
+
+ /* load chanlist for command scan */
+ apci3120_set_chanlist(dev, s, cmd->chanlist_len, cmd->chanlist);
+
+ if (cmd->start_src == TRIG_EXT)
+ apci3120_exttrig_enable(dev, true);
+
+ if (cmd->scan_begin_src == TRIG_TIMER) {
+ /*
+ * Timer 1 is used in MODE2 (rate generator) to set the
+ * start time for each scan.
+ */
+ divisor = apci3120_ns_to_timer(dev, 1, cmd->scan_begin_arg,
+ cmd->flags);
+ apci3120_timer_set_mode(dev, 1, APCI3120_TIMER_MODE2);
+ apci3120_timer_write(dev, 1, divisor);
+ }
+
+ /*
+ * Timer 0 is used in MODE2 (rate generator) to set the conversion
+ * time for each acquisition.
+ */
+ divisor = apci3120_ns_to_timer(dev, 0, cmd->convert_arg, cmd->flags);
+ apci3120_timer_set_mode(dev, 0, APCI3120_TIMER_MODE2);
+ apci3120_timer_write(dev, 0, divisor);
+
+ if (devpriv->use_dma)
+ apci3120_setup_dma(dev, s);
+ else
+ devpriv->mode |= APCI3120_MODE_EOS_IRQ_ENA;
+
+ /* set mode to enable acquisition */
+ outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
+
+ if (cmd->scan_begin_src == TRIG_TIMER)
+ apci3120_timer_enable(dev, 1, true);
+ apci3120_timer_enable(dev, 0, true);
+
+ return 0;
+}
+
+static int apci3120_ai_cmdtest(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_cmd *cmd)
+{
+ unsigned int arg;
+ int err = 0;
+
+ /* Step 1 : check if triggers are trivially valid */
+
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_TIMER | TRIG_FOLLOW);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+
+ if (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->scan_begin_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);
+
+ if (cmd->scan_begin_src == TRIG_TIMER) /* Test Delay timing */
+ err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, 100000);
+
+ /* minimum conversion time per sample is 10us */
+ err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 10000);
+
+ err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
+ err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+ if (cmd->stop_src == TRIG_COUNT)
+ err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+ else /* TRIG_NONE */
+ err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+
+ if (err)
+ return 3;
+
+ /* Step 4: fix up any arguments */
+
+ if (cmd->scan_begin_src == TRIG_TIMER) {
+ /* scan begin must be larger than the scan time */
+ arg = cmd->convert_arg * cmd->scan_end_arg;
+ err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, arg);
+ }
+
+ if (err)
+ return 4;
+
+ /* Step 5: check channel list if it exists */
+
+ return 0;
+}
+
+static int apci3120_cancel(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ struct apci3120_private *devpriv = dev->private;
+
+ /* Add-On - disable DMA */
+ outw(0, devpriv->addon + 4);
+
+ /* Add-On - disable bus master */
+ apci3120_addon_write(dev, 0, AMCC_OP_REG_AGCSTS);
+
+ /* AMCC - disable bus master */
+ outl(0, devpriv->amcc + AMCC_OP_REG_MCSR);
+
+ /* disable all counters, ext trigger, and reset scan */
+ devpriv->ctrl = 0;
+ outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG);
+
+ /* DISABLE_ALL_INTERRUPT */
+ devpriv->mode = 0;
+ outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
+
+ inw(dev->iobase + APCI3120_STATUS_REG);
+ devpriv->cur_dmabuf = 0;
+
+ return 0;
+}
+
+static int apci3120_ai_eoc(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned long context)
+{
+ unsigned int status;
+
+ status = inw(dev->iobase + APCI3120_STATUS_REG);
+ if ((status & APCI3120_STATUS_EOC_INT) == 0)
+ return 0;
+ return -EBUSY;
+}
+
+static int apci3120_ai_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ struct apci3120_private *devpriv = dev->private;
+ unsigned int divisor;
+ int ret;
+ int i;
+
+ /* set mode for A/D conversions by software trigger with timer 0 */
+ devpriv->mode = APCI3120_MODE_TIMER2_CLK_OSC |
+ APCI3120_MODE_TIMER2_AS_TIMER;
+ outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
+
+ /* load chanlist for single channel scan */
+ apci3120_set_chanlist(dev, s, 1, &insn->chanspec);
+
+ /*
+ * Timer 0 is used in MODE4 (software triggered strobe) to set the
+ * conversion time for each acquisition. Each conversion is triggered
+ * when the divisor is written to the timer, The conversion is done
+ * when the EOC bit in the status register is '0'.
+ */
+ apci3120_timer_set_mode(dev, 0, APCI3120_TIMER_MODE4);
+ apci3120_timer_enable(dev, 0, true);
+
+ /* fixed conversion time of 10 us */
+ divisor = apci3120_ns_to_timer(dev, 0, 10000, CMDF_ROUND_NEAREST);
+
+ for (i = 0; i < insn->n; i++) {
+ /* trigger conversion */
+ apci3120_timer_write(dev, 0, divisor);
+
+ ret = comedi_timeout(dev, s, insn, apci3120_ai_eoc, 0);
+ if (ret)
+ return ret;
+
+ data[i] = inw(dev->iobase + APCI3120_AI_FIFO_REG);
+ }
+
+ return insn->n;
+}
+
+static int apci3120_ao_ready(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned long context)
+{
+ unsigned int status;
+
+ status = inw(dev->iobase + APCI3120_STATUS_REG);
+ if (status & APCI3120_STATUS_DA_READY)
+ return 0;
+ return -EBUSY;
+}
+
+static int apci3120_ao_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ int i;
+
+ for (i = 0; i < insn->n; i++) {
+ unsigned int val = data[i];
+ int ret;
+
+ ret = comedi_timeout(dev, s, insn, apci3120_ao_ready, 0);
+ if (ret)
+ return ret;
+
+ outw(APCI3120_AO_MUX(chan) | APCI3120_AO_DATA(val),
+ dev->iobase + APCI3120_AO_REG(chan));
+
+ s->readback[chan] = val;
+ }
+
+ return insn->n;
+}
+
+static int apci3120_di_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ unsigned int status;
+
+ status = inw(dev->iobase + APCI3120_STATUS_REG);
+ data[1] = APCI3120_STATUS_TO_DI_BITS(status);
+
+ return insn->n;
+}
+
+static int apci3120_do_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ struct apci3120_private *devpriv = dev->private;
+
+ if (comedi_dio_update_state(s, data)) {
+ devpriv->do_bits = s->state;
+ outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits),
+ dev->iobase + APCI3120_CTR0_REG);
+ }
+
+ data[1] = s->state;
+
+ return insn->n;
+}
+
+static int apci3120_timer_insn_config(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ struct apci3120_private *devpriv = dev->private;
+ unsigned int divisor;
+ unsigned int status;
+ unsigned int mode;
+ unsigned int timer_mode;
+
+ switch (data[0]) {
+ case INSN_CONFIG_ARM:
+ apci3120_clr_timer2_interrupt(dev);
+ divisor = apci3120_ns_to_timer(dev, 2, data[1],
+ CMDF_ROUND_DOWN);
+ apci3120_timer_write(dev, 2, divisor);
+ apci3120_timer_enable(dev, 2, true);
+ break;
+
+ case INSN_CONFIG_DISARM:
+ apci3120_timer_enable(dev, 2, false);
+ apci3120_clr_timer2_interrupt(dev);
+ break;
+
+ case INSN_CONFIG_GET_COUNTER_STATUS:
+ data[1] = 0;
+ data[2] = COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING |
+ COMEDI_COUNTER_TERMINAL_COUNT;
+
+ if (devpriv->ctrl & APCI3120_CTRL_GATE(2)) {
+ data[1] |= COMEDI_COUNTER_ARMED;
+ data[1] |= COMEDI_COUNTER_COUNTING;
+ }
+ status = inw(dev->iobase + APCI3120_STATUS_REG);
+ if (status & APCI3120_STATUS_TIMER2_INT) {
+ data[1] &= ~COMEDI_COUNTER_COUNTING;
+ data[1] |= COMEDI_COUNTER_TERMINAL_COUNT;
+ }
+ break;
+
+ case INSN_CONFIG_SET_COUNTER_MODE:
+ switch (data[1]) {
+ case I8254_MODE0:
+ mode = APCI3120_MODE_TIMER2_AS_COUNTER;
+ timer_mode = APCI3120_TIMER_MODE0;
+ break;
+ case I8254_MODE2:
+ mode = APCI3120_MODE_TIMER2_AS_TIMER;
+ timer_mode = APCI3120_TIMER_MODE2;
+ break;
+ case I8254_MODE4:
+ mode = APCI3120_MODE_TIMER2_AS_TIMER;
+ timer_mode = APCI3120_TIMER_MODE4;
+ break;
+ case I8254_MODE5:
+ mode = APCI3120_MODE_TIMER2_AS_WDOG;
+ timer_mode = APCI3120_TIMER_MODE5;
+ break;
+ default:
+ return -EINVAL;
+ }
+ apci3120_timer_enable(dev, 2, false);
+ apci3120_clr_timer2_interrupt(dev);
+ apci3120_timer_set_mode(dev, 2, timer_mode);
+ devpriv->mode &= ~APCI3120_MODE_TIMER2_AS_MASK;
+ devpriv->mode |= mode;
+ outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return insn->n;
+}
+
+static int apci3120_timer_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ int i;
+
+ for (i = 0; i < insn->n; i++)
+ data[i] = apci3120_timer_read(dev, 2);
+
+ return insn->n;
+}
+
+static void apci3120_dma_alloc(struct comedi_device *dev)
+{
+ struct apci3120_private *devpriv = dev->private;
+ struct apci3120_dmabuf *dmabuf;
+ int order;
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ dmabuf = &devpriv->dmabuf[i];
+ for (order = 2; order >= 0; order--) {
+ dmabuf->virt = dma_alloc_coherent(dev->hw_dev,
+ PAGE_SIZE << order,
+ &dmabuf->hw,
+ GFP_KERNEL);
+ if (dmabuf->virt)
+ break;
+ }
+ if (!dmabuf->virt)
+ break;
+ dmabuf->size = PAGE_SIZE << order;
+
+ if (i == 0)
+ devpriv->use_dma = 1;
+ if (i == 1)
+ devpriv->use_double_buffer = 1;
+ }
+}
+
+static void apci3120_dma_free(struct comedi_device *dev)
+{
+ struct apci3120_private *devpriv = dev->private;
+ struct apci3120_dmabuf *dmabuf;
+ int i;
+
+ if (!devpriv)
+ return;
+
+ for (i = 0; i < 2; i++) {
+ dmabuf = &devpriv->dmabuf[i];
+ if (dmabuf->virt) {
+ dma_free_coherent(dev->hw_dev, dmabuf->size,
+ dmabuf->virt, dmabuf->hw);
+ }
+ }
+}
+
+static void apci3120_reset(struct comedi_device *dev)
+{
+ /* disable all interrupt sources */
+ outb(0, dev->iobase + APCI3120_MODE_REG);
+
+ /* disable all counters, ext trigger, and reset scan */
+ outw(0, dev->iobase + APCI3120_CTRL_REG);
+
+ /* clear interrupt status */
+ inw(dev->iobase + APCI3120_STATUS_REG);
}
static int apci3120_auto_attach(struct comedi_device *dev,
unsigned long context)
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- const struct addi_board *this_board = NULL;
- struct addi_private *devpriv;
+ const struct apci3120_board *this_board = NULL;
+ struct apci3120_private *devpriv;
struct comedi_subdevice *s;
- int ret, order, i;
+ unsigned int status;
+ int ret;
if (context < ARRAY_SIZE(apci3120_boardtypes))
this_board = &apci3120_boardtypes[context];
if (!this_board)
return -ENODEV;
dev->board_ptr = this_board;
- dev->board_name = this_board->pc_DriverName;
+ dev->board_name = this_board->name;
devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
if (!devpriv)
@@ -76,136 +999,100 @@ static int apci3120_auto_attach(struct comedi_device *dev,
pci_set_master(pcidev);
dev->iobase = pci_resource_start(pcidev, 1);
- devpriv->iobase = dev->iobase;
- devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0);
- devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2);
- devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3);
+ devpriv->amcc = pci_resource_start(pcidev, 0);
+ devpriv->addon = pci_resource_start(pcidev, 2);
+
+ apci3120_reset(dev);
if (pcidev->irq > 0) {
- ret = request_irq(pcidev->irq, v_ADDI_Interrupt, IRQF_SHARED,
+ ret = request_irq(pcidev->irq, apci3120_interrupt, IRQF_SHARED,
dev->board_name, dev);
- if (ret == 0)
+ if (ret == 0) {
dev->irq = pcidev->irq;
- }
- /* Allocate DMA buffers */
- for (i = 0; i < 2; i++) {
- for (order = 2; order >= 0; order--) {
- devpriv->ul_DmaBufferVirtual[i] =
- dma_alloc_coherent(dev->hw_dev, PAGE_SIZE << order,
- &devpriv->ul_DmaBufferHw[i],
- GFP_KERNEL);
-
- if (devpriv->ul_DmaBufferVirtual[i])
- break;
+ apci3120_dma_alloc(dev);
}
- if (!devpriv->ul_DmaBufferVirtual[i])
- break;
- devpriv->ui_DmaBufferSize[i] = PAGE_SIZE << order;
}
- if (devpriv->ul_DmaBufferVirtual[0])
- devpriv->us_UseDma = 1;
- if (devpriv->ul_DmaBufferVirtual[1])
- devpriv->b_DmaDoubleBuffer = 1;
+ status = inw(dev->iobase + APCI3120_STATUS_REG);
+ if (APCI3120_STATUS_TO_VERSION(status) == APCI3120_REVB ||
+ context == BOARD_APCI3001)
+ devpriv->osc_base = APCI3120_REVB_OSC_BASE;
+ else
+ devpriv->osc_base = APCI3120_REVA_OSC_BASE;
ret = comedi_alloc_subdevices(dev, 5);
if (ret)
return ret;
- /* Allocate and Initialise AI Subdevice Structures */
+ /* Analog Input subdevice */
s = &dev->subdevices[0];
- dev->read_subdev = s;
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags =
- SDF_READABLE | SDF_COMMON | SDF_GROUND
- | SDF_DIFF;
- if (this_board->i_NbrAiChannel)
- s->n_chan = this_board->i_NbrAiChannel;
- else
- s->n_chan = this_board->i_NbrAiChannelDiff;
- s->maxdata = this_board->i_AiMaxdata;
- s->len_chanlist = this_board->i_AiChannelList;
- s->range_table = &range_apci3120_ai;
-
- s->insn_config = apci3120_ai_insn_config;
- s->insn_read = apci3120_ai_insn_read;
- s->do_cmdtest = apci3120_ai_cmdtest;
- s->do_cmd = apci3120_ai_cmd;
- s->cancel = apci3120_cancel;
-
- /* Allocate and Initialise AO Subdevice Structures */
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
+ s->n_chan = 16;
+ s->maxdata = this_board->ai_is_16bit ? 0xffff : 0x0fff;
+ s->range_table = &apci3120_ai_range;
+ s->insn_read = apci3120_ai_insn_read;
+ if (dev->irq) {
+ dev->read_subdev = s;
+ s->subdev_flags |= SDF_CMD_READ;
+ s->len_chanlist = s->n_chan;
+ s->do_cmdtest = apci3120_ai_cmdtest;
+ s->do_cmd = apci3120_ai_cmd;
+ s->cancel = apci3120_cancel;
+ }
+
+ /* Analog Output subdevice */
s = &dev->subdevices[1];
- if (this_board->i_NbrAoChannel) {
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = this_board->i_NbrAoChannel;
- s->maxdata = this_board->i_AoMaxdata;
- s->len_chanlist = this_board->i_NbrAoChannel;
- s->range_table = &range_apci3120_ao;
- s->insn_write = apci3120_ao_insn_write;
+ if (this_board->has_ao) {
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
+ s->n_chan = 8;
+ s->maxdata = 0x3fff;
+ s->range_table = &range_bipolar10;
+ s->insn_write = apci3120_ao_insn_write;
+
+ ret = comedi_alloc_subdev_readback(s);
+ if (ret)
+ return ret;
} else {
- s->type = COMEDI_SUBD_UNUSED;
+ s->type = COMEDI_SUBD_UNUSED;
}
- /* Allocate and Initialise DI Subdevice Structures */
+ /* Digital Input subdevice */
s = &dev->subdevices[2];
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = this_board->i_NbrDiChannel;
- s->maxdata = 1;
- s->len_chanlist = this_board->i_NbrDiChannel;
- s->range_table = &range_digital;
- s->insn_bits = apci3120_di_insn_bits;
-
- /* Allocate and Initialise DO Subdevice Structures */
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 4;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = apci3120_di_insn_bits;
+
+ /* Digital Output subdevice */
s = &dev->subdevices[3];
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags =
- SDF_READABLE | SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = this_board->i_NbrDoChannel;
- s->maxdata = this_board->i_DoMaxdata;
- s->len_chanlist = this_board->i_NbrDoChannel;
- s->range_table = &range_digital;
- s->insn_bits = apci3120_do_insn_bits;
-
- /* Allocate and Initialise Timer Subdevice Structures */
- s = &dev->subdevices[4];
- 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->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = 4;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = apci3120_do_insn_bits;
- s->insn_write = apci3120_write_insn_timer;
- s->insn_read = apci3120_read_insn_timer;
- s->insn_config = apci3120_config_insn_timer;
+ /* Timer subdevice */
+ s = &dev->subdevices[4];
+ s->type = COMEDI_SUBD_TIMER;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 1;
+ s->maxdata = 0x00ffffff;
+ s->insn_config = apci3120_timer_insn_config;
+ s->insn_read = apci3120_timer_insn_read;
- apci3120_reset(dev);
return 0;
}
static void apci3120_detach(struct comedi_device *dev)
{
- struct addi_private *devpriv = dev->private;
-
- if (dev->iobase)
- apci3120_reset(dev);
comedi_pci_detach(dev);
- if (devpriv) {
- unsigned int i;
-
- for (i = 0; i < 2; i++) {
- if (devpriv->ul_DmaBufferVirtual[i]) {
- dma_free_coherent(dev->hw_dev,
- devpriv->ui_DmaBufferSize[i],
- devpriv->
- ul_DmaBufferVirtual[i],
- devpriv->ul_DmaBufferHw[i]);
- }
- }
- }
+ apci3120_dma_free(dev);
}
static struct comedi_driver apci3120_driver = {
diff --git a/drivers/staging/comedi/drivers/addi_apci_3200.c b/drivers/staging/comedi/drivers/addi_apci_3200.c
deleted file mode 100644
index fe6897eff3db..000000000000
--- a/drivers/staging/comedi/drivers/addi_apci_3200.c
+++ /dev/null
@@ -1,125 +0,0 @@
-#include <linux/module.h>
-#include <linux/pci.h>
-
-#include <asm/i387.h>
-
-#include "../comedidev.h"
-#include "comedi_fc.h"
-#include "amcc_s5933.h"
-
-#include "addi-data/addi_common.h"
-
-static void fpu_begin(void)
-{
- kernel_fpu_begin();
-}
-
-static void fpu_end(void)
-{
- kernel_fpu_end();
-}
-
-#include "addi-data/addi_eeprom.c"
-#include "addi-data/hwdrv_apci3200.c"
-#include "addi-data/addi_common.c"
-
-enum apci3200_boardid {
- BOARD_APCI3200,
- BOARD_APCI3300,
-};
-
-static const struct addi_board apci3200_boardtypes[] = {
- [BOARD_APCI3200] = {
- .pc_DriverName = "apci3200",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = 1,
- .pc_EepromChip = "S5920",
- .i_NbrAiChannel = 16,
- .i_NbrAiChannelDiff = 8,
- .i_AiChannelList = 16,
- .i_AiMaxdata = 0x3ffff,
- .pr_AiRangelist = &range_apci3200_ai,
- .i_NbrDiChannel = 4,
- .i_NbrDoChannel = 4,
- .ui_MinAcquisitiontimeNs = 10000,
- .ui_MinDelaytimeNs = 100000,
- .interrupt = apci3200_interrupt,
- .reset = apci3200_reset,
- .ai_config = apci3200_ai_config,
- .ai_read = apci3200_ai_read,
- .ai_write = apci3200_ai_write,
- .ai_bits = apci3200_ai_bits_test,
- .ai_cmdtest = apci3200_ai_cmdtest,
- .ai_cmd = apci3200_ai_cmd,
- .ai_cancel = apci3200_cancel,
- .di_bits = apci3200_di_insn_bits,
- .do_bits = apci3200_do_insn_bits,
- },
- [BOARD_APCI3300] = {
- .pc_DriverName = "apci3300",
- .i_IorangeBase1 = 256,
- .i_PCIEeprom = 1,
- .pc_EepromChip = "S5920",
- .i_NbrAiChannelDiff = 8,
- .i_AiChannelList = 8,
- .i_AiMaxdata = 0x3ffff,
- .pr_AiRangelist = &range_apci3300_ai,
- .i_NbrDiChannel = 4,
- .i_NbrDoChannel = 4,
- .ui_MinAcquisitiontimeNs = 10000,
- .ui_MinDelaytimeNs = 100000,
- .interrupt = apci3200_interrupt,
- .reset = apci3200_reset,
- .ai_config = apci3200_ai_config,
- .ai_read = apci3200_ai_read,
- .ai_write = apci3200_ai_write,
- .ai_bits = apci3200_ai_bits_test,
- .ai_cmdtest = apci3200_ai_cmdtest,
- .ai_cmd = apci3200_ai_cmd,
- .ai_cancel = apci3200_cancel,
- .di_bits = apci3200_di_insn_bits,
- .do_bits = apci3200_do_insn_bits,
- },
-};
-
-static int apci3200_auto_attach(struct comedi_device *dev,
- unsigned long context)
-{
- const struct addi_board *board = NULL;
-
- if (context < ARRAY_SIZE(apci3200_boardtypes))
- board = &apci3200_boardtypes[context];
- if (!board)
- return -ENODEV;
- dev->board_ptr = board;
-
- return addi_auto_attach(dev, context);
-}
-
-static struct comedi_driver apci3200_driver = {
- .driver_name = "addi_apci_3200",
- .module = THIS_MODULE,
- .auto_attach = apci3200_auto_attach,
- .detach = i_ADDI_Detach,
-};
-
-static int apci3200_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *id)
-{
- return comedi_pci_auto_config(dev, &apci3200_driver, id->driver_data);
-}
-
-static const struct pci_device_id apci3200_pci_table[] = {
- { PCI_VDEVICE(ADDIDATA, 0x3000), BOARD_APCI3200 },
- { PCI_VDEVICE(ADDIDATA, 0x3007), BOARD_APCI3300 },
- { 0 }
-};
-MODULE_DEVICE_TABLE(pci, apci3200_pci_table);
-
-static struct pci_driver apci3200_pci_driver = {
- .name = "addi_apci_3200",
- .id_table = apci3200_pci_table,
- .probe = apci3200_pci_probe,
- .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 010efa3fed6c..a726efcea6a5 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3501.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3501.c
@@ -357,12 +357,11 @@ static int apci3501_auto_attach(struct comedi_device *dev,
s = &dev->subdevices[0];
if (ao_n_chan) {
s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
+ s->subdev_flags = SDF_WRITABLE | 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;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
@@ -383,7 +382,7 @@ static int apci3501_auto_attach(struct comedi_device *dev,
/* Initialize the digital output subdevice */
s = &dev->subdevices[2];
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITEABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 2;
s->maxdata = 1;
s->range_table = &range_digital;
@@ -392,7 +391,7 @@ static int apci3501_auto_attach(struct comedi_device *dev,
/* Initialize the timer/watchdog subdevice */
s = &dev->subdevices[3];
s->type = COMEDI_SUBD_TIMER;
- s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 1;
s->maxdata = 0;
s->len_chanlist = 1;
diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
index a296bd5b2c0c..c173810a3b5b 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
@@ -371,10 +371,10 @@ static irqreturn_t apci3xxx_irq_handler(int irq, void *d)
writel(status, dev->mmio + 16);
val = readl(dev->mmio + 28);
- comedi_buf_put(s, val);
+ comedi_buf_write_samples(s, &val, 1);
s->async->events |= COMEDI_CB_EOA;
- comedi_event(dev, s);
+ comedi_handle_events(dev, s);
return IRQ_HANDLED;
}
@@ -849,12 +849,11 @@ static int apci3xxx_auto_attach(struct comedi_device *dev,
if (board->has_ao) {
s = &dev->subdevices[subdev];
s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
+ s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
s->n_chan = 4;
s->maxdata = 0x0fff;
s->range_table = &apci3xxx_ao_range;
s->insn_write = apci3xxx_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
@@ -880,7 +879,7 @@ static int apci3xxx_auto_attach(struct comedi_device *dev,
if (board->has_dig_out) {
s = &dev->subdevices[subdev];
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITEABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 4;
s->maxdata = 1;
s->range_table = &range_digital;
@@ -893,7 +892,7 @@ static int apci3xxx_auto_attach(struct comedi_device *dev,
if (board->has_ttl_io) {
s = &dev->subdevices[subdev];
s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITEABLE;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 24;
s->maxdata = 1;
s->io_bits = 0xff; /* channels 0-7 are always outputs */
diff --git a/drivers/staging/comedi/drivers/addi_tcw.h b/drivers/staging/comedi/drivers/addi_tcw.h
new file mode 100644
index 000000000000..8794d4cbbfb0
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi_tcw.h
@@ -0,0 +1,56 @@
+#ifndef _ADDI_TCW_H
+#define _ADDI_TCW_H
+
+/*
+ * Following are the generic definitions for the ADDI-DATA timer/counter/
+ * watchdog (TCW) registers and bits. Some of the registers are not used
+ * depending on the use of the TCW.
+ */
+
+#define ADDI_TCW_VAL_REG 0x00
+
+#define ADDI_TCW_SYNC_REG 0x00
+#define ADDI_TCW_SYNC_CTR_TRIG (1 << 8)
+#define ADDI_TCW_SYNC_CTR_DIS (1 << 7)
+#define ADDI_TCW_SYNC_CTR_ENA (1 << 6)
+#define ADDI_TCW_SYNC_TIMER_TRIG (1 << 5)
+#define ADDI_TCW_SYNC_TIMER_DIS (1 << 4)
+#define ADDI_TCW_SYNC_TIMER_ENA (1 << 3)
+#define ADDI_TCW_SYNC_WDOG_TRIG (1 << 2)
+#define ADDI_TCW_SYNC_WDOG_DIS (1 << 1)
+#define ADDI_TCW_SYNC_WDOG_ENA (1 << 0)
+
+#define ADDI_TCW_RELOAD_REG 0x04
+
+#define ADDI_TCW_TIMEBASE_REG 0x08
+
+#define ADDI_TCW_CTRL_REG 0x0c
+#define ADDI_TCW_CTRL_EXT_CLK_STATUS (1 << 21)
+#define ADDI_TCW_CTRL_CASCADE (1 << 20)
+#define ADDI_TCW_CTRL_CNTR_ENA (1 << 19)
+#define ADDI_TCW_CTRL_CNT_UP (1 << 18)
+#define ADDI_TCW_CTRL_EXT_CLK(x) ((x) << 16)
+#define ADDI_TCW_CTRL_OUT(x) ((x) << 11)
+#define ADDI_TCW_CTRL_GATE (1 << 10)
+#define ADDI_TCW_CTRL_TRIG (1 << 9)
+#define ADDI_TCW_CTRL_EXT_GATE(x) ((x) << 7)
+#define ADDI_TCW_CTRL_EXT_TRIG(x) ((x) << 5)
+#define ADDI_TCW_CTRL_TIMER_ENA (1 << 4)
+#define ADDI_TCW_CTRL_RESET_ENA (1 << 3)
+#define ADDI_TCW_CTRL_WARN_ENA (1 << 2)
+#define ADDI_TCW_CTRL_IRQ_ENA (1 << 1)
+#define ADDI_TCW_CTRL_ENA (1 << 0)
+
+#define ADDI_TCW_STATUS_REG 0x10
+#define ADDI_TCW_STATUS_SOFT_CLR (1 << 3)
+#define ADDI_TCW_STATUS_SOFT_TRIG (1 << 1)
+#define ADDI_TCW_STATUS_OVERFLOW (1 << 0)
+
+#define ADDI_TCW_IRQ_REG 0x14
+#define ADDI_TCW_IRQ (1 << 0)
+
+#define ADDI_TCW_WARN_TIMEVAL_REG 0x18
+
+#define ADDI_TCW_WARN_TIMEBASE_REG 0x1c
+
+#endif
diff --git a/drivers/staging/comedi/drivers/addi_watchdog.c b/drivers/staging/comedi/drivers/addi_watchdog.c
index 23031feaa095..c5b082d4e51e 100644
--- a/drivers/staging/comedi/drivers/addi_watchdog.c
+++ b/drivers/staging/comedi/drivers/addi_watchdog.c
@@ -20,21 +20,9 @@
#include <linux/module.h>
#include "../comedidev.h"
+#include "addi_tcw.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;
@@ -60,9 +48,9 @@ static int addi_watchdog_insn_config(struct comedi_device *dev,
switch (data[0]) {
case INSN_CONFIG_ARM:
- spriv->wdog_ctrl = ADDI_WDOG_CTRL_ENABLE;
+ spriv->wdog_ctrl = ADDI_TCW_CTRL_ENA;
reload = data[1] & s->maxdata;
- outl(reload, spriv->iobase + ADDI_WDOG_RELOAD_REG);
+ outl(reload, spriv->iobase + ADDI_TCW_RELOAD_REG);
/* Time base is 20ms, let the user know the timeout */
dev_info(dev->class_dev, "watchdog enabled, timeout:%dms\n",
@@ -75,7 +63,7 @@ static int addi_watchdog_insn_config(struct comedi_device *dev,
return -EINVAL;
}
- outl(spriv->wdog_ctrl, spriv->iobase + ADDI_WDOG_CTRL_REG);
+ outl(spriv->wdog_ctrl, spriv->iobase + ADDI_TCW_CTRL_REG);
return insn->n;
}
@@ -89,7 +77,7 @@ static int addi_watchdog_insn_read(struct comedi_device *dev,
int i;
for (i = 0; i < insn->n; i++)
- data[i] = inl(spriv->iobase + ADDI_WDOG_STATUS_REG);
+ data[i] = inl(spriv->iobase + ADDI_TCW_STATUS_REG);
return insn->n;
}
@@ -109,8 +97,8 @@ static int addi_watchdog_insn_write(struct comedi_device *dev,
/* "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);
+ outl(spriv->wdog_ctrl | ADDI_TCW_CTRL_TRIG,
+ spriv->iobase + ADDI_TCW_CTRL_REG);
}
return insn->n;
@@ -118,8 +106,8 @@ static int addi_watchdog_insn_write(struct comedi_device *dev,
void addi_watchdog_reset(unsigned long iobase)
{
- outl(0x0, iobase + ADDI_WDOG_CTRL_REG);
- outl(0x0, iobase + ADDI_WDOG_RELOAD_REG);
+ outl(0x0, iobase + ADDI_TCW_CTRL_REG);
+ outl(0x0, iobase + ADDI_TCW_RELOAD_REG);
}
EXPORT_SYMBOL_GPL(addi_watchdog_reset);
@@ -134,7 +122,7 @@ int addi_watchdog_init(struct comedi_subdevice *s, unsigned long iobase)
spriv->iobase = iobase;
s->type = COMEDI_SUBD_TIMER;
- s->subdev_flags = SDF_WRITEABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 1;
s->maxdata = 0xff;
s->insn_config = addi_watchdog_insn_config;
diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
index 0ad46fe492c9..528f15c25dae 100644
--- a/drivers/staging/comedi/drivers/adl_pci6208.c
+++ b/drivers/staging/comedi/drivers/adl_pci6208.c
@@ -169,7 +169,6 @@ static int pci6208_auto_attach(struct comedi_device *dev,
s->maxdata = 0xffff;
s->range_table = &range_bipolar10;
s->insn_write = pci6208_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
index d18d8f21af23..47f6c0e9f014 100644
--- a/drivers/staging/comedi/drivers/adl_pci9111.c
+++ b/drivers/staging/comedi/drivers/adl_pci9111.c
@@ -133,8 +133,6 @@ static const struct comedi_lrange pci9111_ai_range = {
struct pci9111_private_data {
unsigned long lcr_io_base;
- int stop_counter;
-
unsigned int scan_delay;
unsigned int chunk_counter;
unsigned int chunk_num_samples;
@@ -404,12 +402,6 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
outb(CR_RANGE(cmd->chanlist[0]) & PCI9111_AI_RANGE_MASK,
dev->iobase + PCI9111_AI_RANGE_STAT_REG);
- /* Set counter */
- if (cmd->stop_src == TRIG_COUNT)
- dev_private->stop_counter = cmd->stop_arg * cmd->chanlist_len;
- else /* TRIG_NONE */
- dev_private->stop_counter = 0;
-
/* Set timer pacer */
dev_private->scan_delay = 0;
if (cmd->convert_src == TRIG_TIMER) {
@@ -435,7 +427,6 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
}
outb(trig, dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
- dev_private->stop_counter *= (1 + dev_private->scan_delay);
dev_private->chunk_counter = 0;
dev_private->chunk_num_samples = cmd->chanlist_len *
(1 + dev_private->scan_delay);
@@ -452,7 +443,7 @@ static void pci9111_ai_munge(struct comedi_device *dev,
unsigned int maxdata = s->maxdata;
unsigned int invert = (maxdata + 1) >> 1;
unsigned int shift = (maxdata == 0xffff) ? 0 : 4;
- unsigned int num_samples = num_bytes / sizeof(short);
+ unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes);
unsigned int i;
for (i = 0; i < num_samples; i++)
@@ -464,22 +455,14 @@ static void pci9111_handle_fifo_half_full(struct comedi_device *dev,
{
struct pci9111_private_data *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
- unsigned int total = 0;
unsigned int samples;
- if (cmd->stop_src == TRIG_COUNT &&
- PCI9111_FIFO_HALF_SIZE > devpriv->stop_counter)
- samples = devpriv->stop_counter;
- else
- samples = PCI9111_FIFO_HALF_SIZE;
-
+ samples = comedi_nsamples_left(s, PCI9111_FIFO_HALF_SIZE);
insw(dev->iobase + PCI9111_AI_FIFO_REG,
devpriv->ai_bounce_buffer, samples);
if (devpriv->scan_delay < 1) {
- total = cfc_write_array_to_buffer(s,
- devpriv->ai_bounce_buffer,
- samples * sizeof(short));
+ comedi_buf_write_samples(s, devpriv->ai_bounce_buffer, samples);
} else {
unsigned int pos = 0;
unsigned int to_read;
@@ -492,17 +475,15 @@ static void pci9111_handle_fifo_half_full(struct comedi_device *dev,
if (to_read > samples - pos)
to_read = samples - pos;
- total += cfc_write_array_to_buffer(s,
+ comedi_buf_write_samples(s,
devpriv->ai_bounce_buffer + pos,
- to_read * sizeof(short));
+ to_read);
} else {
to_read = devpriv->chunk_num_samples -
devpriv->chunk_counter;
if (to_read > samples - pos)
to_read = samples - pos;
-
- total += to_read * sizeof(short);
}
pos += to_read;
@@ -513,8 +494,6 @@ static void pci9111_handle_fifo_half_full(struct comedi_device *dev,
devpriv->chunk_counter = 0;
}
}
-
- devpriv->stop_counter -= total / sizeof(short);
}
static irqreturn_t pci9111_interrupt(int irq, void *p_device)
@@ -561,7 +540,7 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device)
dev_dbg(dev->class_dev, "fifo overflow\n");
outb(0, dev->iobase + PCI9111_INT_CLR_REG);
async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return IRQ_HANDLED;
}
@@ -571,14 +550,14 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device)
pci9111_handle_fifo_half_full(dev, s);
}
- if (cmd->stop_src == TRIG_COUNT && dev_private->stop_counter == 0)
+ if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
async->events |= COMEDI_CB_EOA;
outb(0, dev->iobase + PCI9111_INT_CLR_REG);
spin_unlock_irqrestore(&dev->spinlock, irq_flags);
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return IRQ_HANDLED;
}
@@ -752,7 +731,6 @@ static int pci9111_auto_attach(struct comedi_device *dev,
s->len_chanlist = 1;
s->range_table = &range_bipolar10;
s->insn_write = pci9111_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
@@ -768,7 +746,7 @@ static int pci9111_auto_attach(struct comedi_device *dev,
s = &dev->subdevices[3];
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 16;
s->maxdata = 1;
s->range_table = &range_digital;
diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
index e18fd9569a2b..26603582e71a 100644
--- a/drivers/staging/comedi/drivers/adl_pci9118.c
+++ b/drivers/staging/comedi/drivers/adl_pci9118.c
@@ -221,7 +221,6 @@ struct pci9118_private {
unsigned char int_ctrl;
unsigned char ai_cfg;
unsigned int ai_do; /* what do AI? 0=nothing, 1 to 4 mode */
- unsigned int ai_act_scan; /* how many scans we finished */
unsigned int ai_n_realscanlen; /*
* what we must transfer for one
* outgoing scan include front/back adds
@@ -447,51 +446,112 @@ static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev,
outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
}
-static unsigned int defragment_dma_buffer(struct comedi_device *dev,
- struct comedi_subdevice *s,
- unsigned short *dma_buffer,
- unsigned int num_samples)
+static unsigned int valid_samples_in_act_dma_buf(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned int n_raw_samples)
{
struct pci9118_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
- unsigned int i = 0, j = 0;
- unsigned int start_pos = devpriv->ai_add_front,
- stop_pos = devpriv->ai_add_front + cmd->chanlist_len;
- unsigned int raw_scanlen = devpriv->ai_add_front + cmd->chanlist_len +
- devpriv->ai_add_back;
+ unsigned int start_pos = devpriv->ai_add_front;
+ unsigned int stop_pos = start_pos + cmd->chanlist_len;
+ unsigned int span_len = stop_pos + devpriv->ai_add_back;
+ unsigned int dma_pos = devpriv->ai_act_dmapos;
+ unsigned int whole_spans, n_samples, x;
- for (i = 0; i < num_samples; i++) {
- if (devpriv->ai_act_dmapos >= start_pos &&
- devpriv->ai_act_dmapos < stop_pos) {
- dma_buffer[j++] = dma_buffer[i];
+ if (span_len == cmd->chanlist_len)
+ return n_raw_samples; /* use all samples */
+
+ /*
+ * Not all samples are to be used. Buffer contents consist of a
+ * possibly non-whole number of spans and a region of each span
+ * is to be used.
+ *
+ * Account for samples in whole number of spans.
+ */
+ whole_spans = n_raw_samples / span_len;
+ n_samples = whole_spans * cmd->chanlist_len;
+ n_raw_samples -= whole_spans * span_len;
+
+ /*
+ * Deal with remaining samples which could overlap up to two spans.
+ */
+ while (n_raw_samples) {
+ if (dma_pos < start_pos) {
+ /* Skip samples before start position. */
+ x = start_pos - dma_pos;
+ if (x > n_raw_samples)
+ x = n_raw_samples;
+ dma_pos += x;
+ n_raw_samples -= x;
+ if (!n_raw_samples)
+ break;
}
- devpriv->ai_act_dmapos++;
- devpriv->ai_act_dmapos %= raw_scanlen;
+ if (dma_pos < stop_pos) {
+ /* Include samples before stop position. */
+ x = stop_pos - dma_pos;
+ if (x > n_raw_samples)
+ x = n_raw_samples;
+ n_samples += x;
+ dma_pos += x;
+ n_raw_samples -= x;
+ }
+ /* Advance to next span. */
+ start_pos += span_len;
+ stop_pos += span_len;
}
-
- return j;
+ return n_samples;
}
-static int move_block_from_dma(struct comedi_device *dev,
- struct comedi_subdevice *s,
- unsigned short *dma_buffer,
- unsigned int num_samples)
+static void move_block_from_dma(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned short *dma_buffer,
+ unsigned int n_raw_samples)
{
struct pci9118_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
- unsigned int num_bytes;
-
- num_samples = defragment_dma_buffer(dev, s, dma_buffer, num_samples);
- devpriv->ai_act_scan +=
- (s->async->cur_chan + num_samples) / cmd->scan_end_arg;
- s->async->cur_chan += num_samples;
- s->async->cur_chan %= cmd->scan_end_arg;
- num_bytes =
- cfc_write_array_to_buffer(s, dma_buffer,
- num_samples * sizeof(short));
- if (num_bytes < num_samples * sizeof(short))
- return -1;
- return 0;
+ unsigned int start_pos = devpriv->ai_add_front;
+ unsigned int stop_pos = start_pos + cmd->chanlist_len;
+ unsigned int span_len = stop_pos + devpriv->ai_add_back;
+ unsigned int dma_pos = devpriv->ai_act_dmapos;
+ unsigned int x;
+
+ if (span_len == cmd->chanlist_len) {
+ /* All samples are to be copied. */
+ comedi_buf_write_samples(s, dma_buffer, n_raw_samples);
+ dma_pos += n_raw_samples;
+ } else {
+ /*
+ * Not all samples are to be copied. Buffer contents consist
+ * of a possibly non-whole number of spans and a region of
+ * each span is to be copied.
+ */
+ while (n_raw_samples) {
+ if (dma_pos < start_pos) {
+ /* Skip samples before start position. */
+ x = start_pos - dma_pos;
+ if (x > n_raw_samples)
+ x = n_raw_samples;
+ dma_pos += x;
+ n_raw_samples -= x;
+ if (!n_raw_samples)
+ break;
+ }
+ if (dma_pos < stop_pos) {
+ /* Copy samples before stop position. */
+ x = stop_pos - dma_pos;
+ if (x > n_raw_samples)
+ x = n_raw_samples;
+ comedi_buf_write_samples(s, dma_buffer, x);
+ dma_pos += x;
+ n_raw_samples -= x;
+ }
+ /* Advance to next span. */
+ start_pos += span_len;
+ stop_pos += span_len;
+ }
+ }
+ /* Update position in span for next time. */
+ devpriv->ai_act_dmapos = dma_pos % span_len;
}
static void pci9118_exttrg_enable(struct comedi_device *dev, bool enable)
@@ -578,9 +638,7 @@ static int pci9118_ai_cancel(struct comedi_device *dev,
devpriv->ai_do = 0;
devpriv->usedma = 0;
- devpriv->ai_act_scan = 0;
devpriv->ai_act_dmapos = 0;
- s->async->cur_chan = 0;
s->async->inttrig = NULL;
devpriv->ai_neverending = 0;
devpriv->dma_actbuf = 0;
@@ -594,8 +652,9 @@ static void pci9118_ai_munge(struct comedi_device *dev,
unsigned int start_chan_index)
{
struct pci9118_private *devpriv = dev->private;
- unsigned int i, num_samples = num_bytes / sizeof(short);
unsigned short *array = data;
+ unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes);
+ unsigned int i;
for (i = 0; i < num_samples; i++) {
if (devpriv->usedma)
@@ -617,17 +676,11 @@ static void interrupt_pci9118_ai_onesample(struct comedi_device *dev,
sampl = inl(dev->iobase + PCI9118_AI_FIFO_REG);
- cfc_write_to_buffer(s, sampl);
- s->async->cur_chan++;
- if (s->async->cur_chan >= cmd->scan_end_arg) {
- /* one scan done */
- s->async->cur_chan %= cmd->scan_end_arg;
- devpriv->ai_act_scan++;
- if (!devpriv->ai_neverending) {
- /* all data sampled? */
- if (devpriv->ai_act_scan >= cmd->stop_arg)
- s->async->events |= COMEDI_CB_EOA;
- }
+ comedi_buf_write_samples(s, &sampl, 1);
+
+ if (!devpriv->ai_neverending) {
+ if (s->async->scans_done >= cmd->stop_arg)
+ s->async->events |= COMEDI_CB_EOA;
}
}
@@ -637,39 +690,37 @@ static void interrupt_pci9118_ai_dma(struct comedi_device *dev,
struct pci9118_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
struct pci9118_dmabuf *dmabuf = &devpriv->dmabuf[devpriv->dma_actbuf];
- unsigned int next_dma_buf, samplesinbuf, sampls, m;
+ unsigned int n_all = comedi_bytes_to_samples(s, dmabuf->use_size);
+ unsigned int n_valid;
+ bool more_dma;
- samplesinbuf = dmabuf->use_size >> 1; /* number of received samples */
+ /* determine whether more DMA buffers to do after this one */
+ n_valid = valid_samples_in_act_dma_buf(dev, s, n_all);
+ more_dma = n_valid < comedi_nsamples_left(s, n_valid + 1);
- if (devpriv->dma_doublebuf) { /*
- * switch DMA buffers if is used
- * double buffering
- */
- next_dma_buf = 1 - devpriv->dma_actbuf;
- pci9118_amcc_setup_dma(dev, next_dma_buf);
- if (devpriv->ai_do == 4)
- interrupt_pci9118_ai_mode4_switch(dev, next_dma_buf);
+ /* switch DMA buffers and restart DMA if double buffering */
+ if (more_dma && devpriv->dma_doublebuf) {
+ devpriv->dma_actbuf = 1 - devpriv->dma_actbuf;
+ pci9118_amcc_setup_dma(dev, devpriv->dma_actbuf);
+ if (devpriv->ai_do == 4) {
+ interrupt_pci9118_ai_mode4_switch(dev,
+ devpriv->dma_actbuf);
+ }
}
- if (samplesinbuf) {
- /* how many samples is to end of buffer */
- m = s->async->prealloc_bufsz >> 1;
- sampls = m;
- move_block_from_dma(dev, s, dmabuf->virt, samplesinbuf);
- m = m - sampls; /* m=how many samples was transferred */
- }
+ if (n_all)
+ move_block_from_dma(dev, s, dmabuf->virt, n_all);
if (!devpriv->ai_neverending) {
- /* all data sampled? */
- if (devpriv->ai_act_scan >= cmd->stop_arg)
+ if (s->async->scans_done >= cmd->stop_arg)
s->async->events |= COMEDI_CB_EOA;
}
- if (devpriv->dma_doublebuf) {
- /* switch dma buffers */
- devpriv->dma_actbuf = 1 - devpriv->dma_actbuf;
- } else {
- /* restart DMA if is not used double buffering */
+ if (s->async->events & COMEDI_CB_CANCEL_MASK)
+ more_dma = false;
+
+ /* restart DMA if not double buffering */
+ if (more_dma && !devpriv->dma_doublebuf) {
pci9118_amcc_setup_dma(dev, 0);
if (devpriv->ai_do == 4)
interrupt_pci9118_ai_mode4_switch(dev, 0);
@@ -766,7 +817,7 @@ static irqreturn_t pci9118_interrupt(int irq, void *d)
interrupt_pci9118_ai_onesample(dev, s);
interrupt_exit:
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return IRQ_HANDLED;
}
@@ -1123,9 +1174,7 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
inl(dev->iobase + PCI9118_AI_STATUS_REG);
inl(dev->iobase + PCI9118_INT_CTRL_REG);
- devpriv->ai_act_scan = 0;
devpriv->ai_act_dmapos = 0;
- s->async->cur_chan = 0;
if (devpriv->usedma) {
Compute_and_setup_dma(dev, s);
@@ -1624,7 +1673,6 @@ static int pci9118_common_attach(struct comedi_device *dev,
s->maxdata = 0x0fff;
s->range_table = &range_bipolar10;
s->insn_write = pci9118_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
index 5539bd294862..d02df7d0c629 100644
--- a/drivers/staging/comedi/drivers/adv_pci1710.c
+++ b/drivers/staging/comedi/drivers/adv_pci1710.c
@@ -298,7 +298,6 @@ static const struct boardtype boardtypes[] = {
struct pci1710_private {
unsigned int CntrlReg; /* Control register */
- unsigned int ai_act_scan; /* how many scans we finished */
unsigned char ai_et;
unsigned int ai_et_CntrlReg;
unsigned int ai_et_MuxVal;
@@ -730,16 +729,12 @@ static int pci171x_ai_cancel(struct comedi_device *dev,
break;
}
- devpriv->ai_act_scan = 0;
- s->async->cur_chan = 0;
-
return 0;
}
static void pci1710_handle_every_sample(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- struct pci1710_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
unsigned int status;
unsigned int val;
@@ -749,14 +744,14 @@ static void pci1710_handle_every_sample(struct comedi_device *dev,
if (status & Status_FE) {
dev_dbg(dev->class_dev, "A/D FIFO empty (%4x)\n", status);
s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return;
}
if (status & Status_FF) {
dev_dbg(dev->class_dev,
"A/D FIFO Full status (Fatal Error!) (%4x)\n", status);
s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return;
}
@@ -770,27 +765,19 @@ static void pci1710_handle_every_sample(struct comedi_device *dev,
break;
}
- comedi_buf_put(s, val & s->maxdata);
-
- s->async->cur_chan++;
- if (s->async->cur_chan >= cmd->chanlist_len)
- s->async->cur_chan = 0;
+ val &= s->maxdata;
+ comedi_buf_write_samples(s, &val, 1);
-
- if (s->async->cur_chan == 0) { /* one scan done */
- devpriv->ai_act_scan++;
- if (cmd->stop_src == TRIG_COUNT &&
- devpriv->ai_act_scan >= cmd->stop_arg) {
- /* all data sampled */
- s->async->events |= COMEDI_CB_EOA;
- break;
- }
+ if (cmd->stop_src == TRIG_COUNT &&
+ s->async->scans_done >= cmd->stop_arg) {
+ s->async->events |= COMEDI_CB_EOA;
+ break;
}
}
outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
}
/*
@@ -799,8 +786,6 @@ static void pci1710_handle_every_sample(struct comedi_device *dev,
static int move_block_from_fifo(struct comedi_device *dev,
struct comedi_subdevice *s, int n, int turn)
{
- struct pci1710_private *devpriv = dev->private;
- struct comedi_cmd *cmd = &s->async->cmd;
unsigned int val;
int ret;
int i;
@@ -814,13 +799,8 @@ static int move_block_from_fifo(struct comedi_device *dev,
return ret;
}
- comedi_buf_put(s, val & s->maxdata);
-
- s->async->cur_chan++;
- if (s->async->cur_chan >= cmd->chanlist_len) {
- s->async->cur_chan = 0;
- devpriv->ai_act_scan++;
- }
+ val &= s->maxdata;
+ comedi_buf_write_samples(s, &val, 1);
}
return 0;
}
@@ -829,48 +809,47 @@ static void pci1710_handle_fifo(struct comedi_device *dev,
struct comedi_subdevice *s)
{
const struct boardtype *this_board = dev->board_ptr;
- struct pci1710_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
- int m, samplesinbuf;
+ unsigned int nsamples;
+ unsigned int m;
m = inw(dev->iobase + PCI171x_STATUS);
if (!(m & Status_FH)) {
dev_dbg(dev->class_dev, "A/D FIFO not half full! (%4x)\n", m);
s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return;
}
if (m & Status_FF) {
dev_dbg(dev->class_dev,
"A/D FIFO Full status (Fatal Error!) (%4x)\n", m);
s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return;
}
- samplesinbuf = this_board->fifo_half_size;
- if (samplesinbuf * sizeof(short) >= s->async->prealloc_bufsz) {
- m = s->async->prealloc_bufsz / sizeof(short);
+ nsamples = this_board->fifo_half_size;
+ if (comedi_samples_to_bytes(s, nsamples) >= s->async->prealloc_bufsz) {
+ m = comedi_bytes_to_samples(s, s->async->prealloc_bufsz);
if (move_block_from_fifo(dev, s, m, 0))
return;
- samplesinbuf -= m;
+ nsamples -= m;
}
- if (samplesinbuf) {
- if (move_block_from_fifo(dev, s, samplesinbuf, 1))
+ if (nsamples) {
+ if (move_block_from_fifo(dev, s, nsamples, 1))
return;
}
if (cmd->stop_src == TRIG_COUNT &&
- devpriv->ai_act_scan >= cmd->stop_arg) {
- /* all data sampled */
+ s->async->scans_done >= cmd->stop_arg) {
s->async->events |= COMEDI_CB_EOA;
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return;
}
outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
}
/*
@@ -928,9 +907,6 @@ static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
outb(0, dev->iobase + PCI171x_CLRFIFO);
outb(0, dev->iobase + PCI171x_CLRINT);
- devpriv->ai_act_scan = 0;
- s->async->cur_chan = 0;
-
devpriv->CntrlReg &= Control_CNT0;
if ((cmd->flags & CMDF_WAKE_EOS) == 0)
devpriv->CntrlReg |= Control_ONEFH;
@@ -1208,7 +1184,7 @@ static int pci1710_auto_attach(struct comedi_device *dev,
if (this_board->n_dichan) {
s = &dev->subdevices[subdev];
s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
+ s->subdev_flags = SDF_READABLE;
s->n_chan = this_board->n_dichan;
s->maxdata = 1;
s->len_chanlist = this_board->n_dichan;
@@ -1220,7 +1196,7 @@ static int pci1710_auto_attach(struct comedi_device *dev,
if (this_board->n_dochan) {
s = &dev->subdevices[subdev];
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = this_board->n_dochan;
s->maxdata = 1;
s->len_chanlist = this_board->n_dochan;
diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
index 1610e2b406f3..65f854e1eb66 100644
--- a/drivers/staging/comedi/drivers/adv_pci1723.c
+++ b/drivers/staging/comedi/drivers/adv_pci1723.c
@@ -1,205 +1,124 @@
/*
- comedi/drivers/pci1723.c
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 2000 David A. Schleef <ds@schleef.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ * adv_pci1723.c
+ * Comedi driver for the Advantech PCI-1723 card.
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-*/
/*
-Driver: adv_pci1723
-Description: Advantech PCI-1723
-Author: yonggang <rsmgnu@gmail.com>, Ian Abbott <abbotti@mev.co.uk>
-Devices: [Advantech] PCI-1723 (adv_pci1723)
-Updated: Mon, 14 Apr 2008 15:12:56 +0100
-Status: works
-
-Configuration Options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
-
- If bus/slot is not specified, the first supported
- PCI device found will be used.
-
-Subdevice 0 is 8-channel AO, 16-bit, range +/- 10 V.
-
-Subdevice 1 is 16-channel DIO. The channels are configurable as input or
-output in 2 groups (0 to 7, 8 to 15). Configuring any channel implicitly
-configures all channels in the same group.
-
-TODO:
-
-1. Add the two milliamp ranges to the AO subdevice (0 to 20 mA, 4 to 20 mA).
-2. Read the initial ranges and values of the AO subdevice at start-up instead
- of reinitializing them.
-3. Implement calibration.
-*/
+ * Driver: adv_pci1723
+ * Description: Advantech PCI-1723
+ * Author: yonggang <rsmgnu@gmail.com>, Ian Abbott <abbotti@mev.co.uk>
+ * Devices: (Advantech) PCI-1723 [adv_pci1723]
+ * Updated: Mon, 14 Apr 2008 15:12:56 +0100
+ * Status: works
+ *
+ * Configuration Options: not applicable, uses comedi PCI auto config
+ *
+ * Subdevice 0 is 8-channel AO, 16-bit, range +/- 10 V.
+ *
+ * Subdevice 1 is 16-channel DIO. The channels are configurable as
+ * input or output in 2 groups (0 to 7, 8 to 15). Configuring any
+ * channel implicitly configures all channels in the same group.
+ *
+ * TODO:
+ * 1. Add the two milliamp ranges to the AO subdevice (0 to 20 mA,
+ * 4 to 20 mA).
+ * 2. Read the initial ranges and values of the AO subdevice at
+ * start-up instead of reinitializing them.
+ * 3. Implement calibration.
+ */
#include <linux/module.h>
#include <linux/pci.h>
#include "../comedidev.h"
-/* all the registers for the pci1723 board */
-#define PCI1723_DA(N) ((N)<<1) /* W: D/A register N (0 to 7) */
-
-#define PCI1723_SYN_SET 0x12 /* synchronized set register */
-#define PCI1723_ALL_CHNNELE_SYN_STROBE 0x12
- /* synchronized status register */
-
-#define PCI1723_RANGE_CALIBRATION_MODE 0x14
- /* range and calibration mode */
-#define PCI1723_RANGE_CALIBRATION_STATUS 0x14
- /* range and calibration status */
-
-#define PCI1723_CONTROL_CMD_CALIBRATION_FUN 0x16
- /*
- * SADC control command for
- * calibration function
- */
-#define PCI1723_STATUS_CMD_CALIBRATION_FUN 0x16
- /*
- * SADC control status for
- * calibration function
- */
-
-#define PCI1723_CALIBRATION_PARA_STROBE 0x18
- /* Calibration parameter strobe */
-
-#define PCI1723_DIGITAL_IO_PORT_SET 0x1A /* Digital I/O port setting */
-#define PCI1723_DIGITAL_IO_PORT_MODE 0x1A /* Digital I/O port mode */
-
-#define PCI1723_WRITE_DIGITAL_OUTPUT_CMD 0x1C
- /* Write digital output command */
-#define PCI1723_READ_DIGITAL_INPUT_DATA 0x1C /* Read digital input data */
-
-#define PCI1723_WRITE_CAL_CMD 0x1E /* Write calibration command */
-#define PCI1723_READ_CAL_STATUS 0x1E /* Read calibration status */
-
-#define PCI1723_SYN_STROBE 0x20 /* Synchronized strobe */
-
-#define PCI1723_RESET_ALL_CHN_STROBE 0x22
- /* Reset all D/A channels strobe */
-
-#define PCI1723_RESET_CAL_CONTROL_STROBE 0x24
- /*
- * Reset the calibration
- * controller strobe
- */
-
-#define PCI1723_CHANGE_CHA_OUTPUT_TYPE_STROBE 0x26
- /*
- * Change D/A channels output
- * type strobe
- */
-
-#define PCI1723_SELECT_CALIBRATION 0x28 /* Select the calibration Ref_V */
-
-struct pci1723_private {
- unsigned char da_range[8]; /* D/A output range for each channel */
- unsigned short ao_data[8]; /* data output buffer */
-};
-
/*
- * The pci1723 card reset;
+ * PCI Bar 2 I/O Register map (dev->iobase)
*/
-static int pci1723_reset(struct comedi_device *dev)
+#define PCI1723_AO_REG(x) (0x00 + ((x) * 2))
+#define PCI1723_BOARD_ID_REG 0x10
+#define PCI1723_BOARD_ID_MASK (0xf << 0)
+#define PCI1723_SYNC_CTRL_REG 0x12
+#define PCI1723_SYNC_CTRL_ASYNC (0 << 0)
+#define PCI1723_SYNC_CTRL_SYNC (1 << 0)
+#define PCI1723_CTRL_REG 0x14
+#define PCI1723_CTRL_BUSY (1 << 15)
+#define PCI1723_CTRL_INIT (1 << 14)
+#define PCI1723_CTRL_SELF (1 << 8)
+#define PCI1723_CTRL_IDX(x) (((x) & 0x3) << 6)
+#define PCI1723_CTRL_RANGE(x) (((x) & 0x3) << 4)
+#define PCI1723_CTRL_GAIN (0 << 3)
+#define PCI1723_CTRL_OFFSET (1 << 3)
+#define PCI1723_CTRL_CHAN(x) (((x) & 0x7) << 0)
+#define PCI1723_CALIB_CTRL_REG 0x16
+#define PCI1723_CALIB_CTRL_CS (1 << 2)
+#define PCI1723_CALIB_CTRL_DAT (1 << 1)
+#define PCI1723_CALIB_CTRL_CLK (1 << 0)
+#define PCI1723_CALIB_STROBE_REG 0x18
+#define PCI1723_DIO_CTRL_REG 0x1a
+#define PCI1723_DIO_CTRL_HDIO (1 << 1)
+#define PCI1723_DIO_CTRL_LDIO (1 << 0)
+#define PCI1723_DIO_DATA_REG 0x1c
+#define PCI1723_CALIB_DATA_REG 0x1e
+#define PCI1723_SYNC_STROBE_REG 0x20
+#define PCI1723_RESET_AO_STROBE_REG 0x22
+#define PCI1723_RESET_CALIB_STROBE_REG 0x24
+#define PCI1723_RANGE_STROBE_REG 0x26
+#define PCI1723_VREF_REG 0x28
+#define PCI1723_VREF_NEG10V (0 << 0)
+#define PCI1723_VREF_0V (1 << 0)
+#define PCI1723_VREF_POS10V (3 << 0)
+
+static int pci1723_ao_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct pci1723_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
int i;
- outw(0x01, dev->iobase + PCI1723_SYN_SET);
- /* set synchronous output mode */
-
- for (i = 0; i < 8; i++) {
- /* set all outputs to 0V */
- devpriv->ao_data[i] = 0x8000;
- outw(devpriv->ao_data[i], dev->iobase + PCI1723_DA(i));
- /* set all ranges to +/- 10V */
- devpriv->da_range[i] = 0;
- outw(((devpriv->da_range[i] << 4) | i),
- PCI1723_RANGE_CALIBRATION_MODE);
- }
-
- outw(0, dev->iobase + PCI1723_CHANGE_CHA_OUTPUT_TYPE_STROBE);
- /* update ranges */
- outw(0, dev->iobase + PCI1723_SYN_STROBE); /* update outputs */
-
- /* set asynchronous output mode */
- outw(0, dev->iobase + PCI1723_SYN_SET);
-
- return 0;
-}
-
-static int pci1723_insn_read_ao(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- struct pci1723_private *devpriv = dev->private;
- int n, chan;
-
- chan = CR_CHAN(insn->chanspec);
- for (n = 0; n < insn->n; n++)
- data[n] = devpriv->ao_data[chan];
+ for (i = 0; i < insn->n; i++) {
+ unsigned int val = data[i];
- return n;
-}
-
-/*
- analog data output;
-*/
-static int pci1723_ao_write_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- struct pci1723_private *devpriv = dev->private;
- unsigned int chan = CR_CHAN(insn->chanspec);
- int n;
-
- for (n = 0; n < insn->n; n++) {
- devpriv->ao_data[chan] = data[n];
- outw(data[n], dev->iobase + PCI1723_DA(chan));
+ outw(val, dev->iobase + PCI1723_AO_REG(chan));
+ s->readback[chan] = val;
}
- return n;
+ return insn->n;
}
-/*
- digital i/o config/query
-*/
static int pci1723_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
unsigned int chan = CR_CHAN(insn->chanspec);
- unsigned int mask;
- unsigned short mode;
+ unsigned int mask = (chan < 8) ? 0x00ff : 0xff00;
+ unsigned short mode = 0x0000; /* assume output */
int ret;
- if (chan < 8)
- mask = 0x00ff;
- else
- mask = 0xff00;
-
ret = comedi_dio_insn_config(dev, s, insn, data, mask);
if (ret)
return ret;
- /* update hardware DIO mode */
- mode = 0x0000; /* assume output */
if (!(s->io_bits & 0x00ff))
- mode |= 0x0001; /* low byte input */
+ mode |= PCI1723_DIO_CTRL_LDIO; /* low byte input */
if (!(s->io_bits & 0xff00))
- mode |= 0x0002; /* high byte input */
- outw(mode, dev->iobase + PCI1723_DIGITAL_IO_PORT_SET);
+ mode |= PCI1723_DIO_CTRL_HDIO; /* high byte input */
+ outw(mode, dev->iobase + PCI1723_DIO_CTRL_REG);
return insn->n;
}
@@ -210,24 +129,21 @@ static int pci1723_dio_insn_bits(struct comedi_device *dev,
unsigned int *data)
{
if (comedi_dio_update_state(s, data))
- outw(s->state, dev->iobase + PCI1723_WRITE_DIGITAL_OUTPUT_CMD);
+ outw(s->state, dev->iobase + PCI1723_DIO_DATA_REG);
- data[1] = inw(dev->iobase + PCI1723_READ_DIGITAL_INPUT_DATA);
+ data[1] = inw(dev->iobase + PCI1723_DIO_DATA_REG);
return insn->n;
}
static int pci1723_auto_attach(struct comedi_device *dev,
- unsigned long context_unused)
+ unsigned long context_unused)
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- struct pci1723_private *devpriv;
struct comedi_subdevice *s;
+ unsigned int val;
int ret;
-
- devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
- if (!devpriv)
- return -ENOMEM;
+ int i;
ret = comedi_pci_enable(dev);
if (ret)
@@ -239,61 +155,57 @@ static int pci1723_auto_attach(struct comedi_device *dev,
return ret;
s = &dev->subdevices[0];
- dev->write_subdev = s;
s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
+ s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
s->n_chan = 8;
s->maxdata = 0xffff;
- s->len_chanlist = 8;
s->range_table = &range_bipolar10;
- s->insn_write = pci1723_ao_write_winsn;
- s->insn_read = pci1723_insn_read_ao;
+ s->insn_write = pci1723_ao_insn_write;
+
+ ret = comedi_alloc_subdev_readback(s);
+ if (ret)
+ return ret;
+
+ /* synchronously reset all analog outputs to 0V, +/-10V range */
+ outw(PCI1723_SYNC_CTRL_SYNC, dev->iobase + PCI1723_SYNC_CTRL_REG);
+ for (i = 0; i < s->n_chan; i++) {
+ outw(PCI1723_CTRL_RANGE(0) | PCI1723_CTRL_CHAN(i),
+ PCI1723_CTRL_REG);
+ outw(0, dev->iobase + PCI1723_RANGE_STROBE_REG);
+
+ outw(0x8000, dev->iobase + PCI1723_AO_REG(i));
+ s->readback[i] = 0x8000;
+ }
+ outw(0, dev->iobase + PCI1723_SYNC_STROBE_REG);
+
+ /* disable syncronous control */
+ outw(PCI1723_SYNC_CTRL_ASYNC, dev->iobase + PCI1723_SYNC_CTRL_REG);
s = &dev->subdevices[1];
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 16;
s->maxdata = 1;
- s->len_chanlist = 16;
s->range_table = &range_digital;
s->insn_config = pci1723_dio_insn_config;
s->insn_bits = pci1723_dio_insn_bits;
- /* read DIO config */
- switch (inw(dev->iobase + PCI1723_DIGITAL_IO_PORT_MODE) & 0x03) {
- case 0x00: /* low byte output, high byte output */
- s->io_bits = 0xFFFF;
- break;
- case 0x01: /* low byte input, high byte output */
- s->io_bits = 0xFF00;
- break;
- case 0x02: /* low byte output, high byte input */
- s->io_bits = 0x00FF;
- break;
- case 0x03: /* low byte input, high byte input */
- s->io_bits = 0x0000;
- break;
- }
- /* read DIO port state */
- s->state = inw(dev->iobase + PCI1723_READ_DIGITAL_INPUT_DATA);
-
- pci1723_reset(dev);
+ /* get initial DIO direction and state */
+ val = inw(dev->iobase + PCI1723_DIO_CTRL_REG);
+ if (!(val & PCI1723_DIO_CTRL_LDIO))
+ s->io_bits |= 0x00ff; /* low byte output */
+ if (!(val & PCI1723_DIO_CTRL_HDIO))
+ s->io_bits |= 0xff00; /* high byte output */
+ s->state = inw(dev->iobase + PCI1723_DIO_DATA_REG);
return 0;
}
-static void pci1723_detach(struct comedi_device *dev)
-{
- if (dev->iobase)
- pci1723_reset(dev);
- comedi_pci_detach(dev);
-}
-
static struct comedi_driver adv_pci1723_driver = {
.driver_name = "adv_pci1723",
.module = THIS_MODULE,
.auto_attach = pci1723_auto_attach,
- .detach = pci1723_detach,
+ .detach = comedi_pci_detach,
};
static int adv_pci1723_pci_probe(struct pci_dev *dev,
@@ -318,5 +230,5 @@ static struct pci_driver adv_pci1723_pci_driver = {
module_comedi_pci_driver(adv_pci1723_driver, adv_pci1723_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Advantech PCI-1723 Comedi driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/adv_pci1724.c b/drivers/staging/comedi/drivers/adv_pci1724.c
index 2697758b1ed9..a8d28403262e 100644
--- a/drivers/staging/comedi/drivers/adv_pci1724.c
+++ b/drivers/staging/comedi/drivers/adv_pci1724.c
@@ -1,122 +1,76 @@
/*
- comedi/drivers/adv_pci1724.c
- This is a driver for the Advantech PCI-1724U card.
-
- Author: Frank Mori Hess <fmh6jj@gmail.com>
- Copyright (C) 2013 GnuBIO Inc
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 1997-8 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.
-*/
+ * adv_pci1724.c
+ * Comedi driver for the Advantech PCI-1724U card.
+ *
+ * Author: Frank Mori Hess <fmh6jj@gmail.com>
+ * Copyright (C) 2013 GnuBIO Inc
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
/*
-
-Driver: adv_1724
-Description: Advantech PCI-1724U
-Author: Frank Mori Hess <fmh6jj@gmail.com>
-Status: works
-Updated: 2013-02-09
-Devices: [Advantech] PCI-1724U (adv_pci1724)
-
-Subdevice 0 is the analog output.
-Subdevice 1 is the offset calibration for the analog output.
-Subdevice 2 is the gain calibration for the analog output.
-
-The calibration offset and gains have quite a large effect
-on the analog output, so it is possible to adjust the analog output to
-have an output range significantly different from the board's
-nominal output ranges. For a calibrated +/- 10V range, the analog
-output's offset will be set somewhere near mid-range (0x2000) and its
-gain will be near maximum (0x3fff).
-
-There is really no difference between the board's documented 0-20mA
-versus 4-20mA output ranges. To pick one or the other is simply a matter
-of adjusting the offset and gain calibration until the board outputs in
-the desired range.
-
-Configuration options:
- None
-
-Manual configuration of comedi devices is not supported by this driver;
-supported PCI devices are configured as comedi devices automatically.
-
-*/
+ * Driver: adv_pci1724
+ * Description: Advantech PCI-1724U
+ * Devices: (Advantech) PCI-1724U [adv_pci1724]
+ * Author: Frank Mori Hess <fmh6jj@gmail.com>
+ * Updated: 2013-02-09
+ * Status: works
+ *
+ * Configuration Options: not applicable, uses comedi PCI auto config
+ *
+ * Subdevice 0 is the analog output.
+ * Subdevice 1 is the offset calibration for the analog output.
+ * Subdevice 2 is the gain calibration for the analog output.
+ *
+ * The calibration offset and gains have quite a large effect on the
+ * analog output, so it is possible to adjust the analog output to
+ * have an output range significantly different from the board's
+ * nominal output ranges. For a calibrated +/-10V range, the analog
+ * output's offset will be set somewhere near mid-range (0x2000) and
+ * its gain will be near maximum (0x3fff).
+ *
+ * There is really no difference between the board's documented 0-20mA
+ * versus 4-20mA output ranges. To pick one or the other is simply a
+ * matter of adjusting the offset and gain calibration until the board
+ * outputs in the desired range.
+ */
#include <linux/module.h>
-#include <linux/delay.h>
#include <linux/pci.h>
#include "../comedidev.h"
-#define PCI_VENDOR_ID_ADVANTECH 0x13fe
-
-#define NUM_AO_CHANNELS 32
-
-/* register offsets */
-enum board_registers {
- DAC_CONTROL_REG = 0x0,
- SYNC_OUTPUT_REG = 0x4,
- EEPROM_CONTROL_REG = 0x8,
- SYNC_OUTPUT_TRIGGER_REG = 0xc,
- BOARD_ID_REG = 0x10
-};
-
-/* bit definitions for registers */
-enum dac_control_contents {
- DAC_DATA_MASK = 0x3fff,
- DAC_DESTINATION_MASK = 0xc000,
- DAC_NORMAL_MODE = 0xc000,
- DAC_OFFSET_MODE = 0x8000,
- DAC_GAIN_MODE = 0x4000,
- DAC_CHANNEL_SELECT_MASK = 0xf0000,
- DAC_GROUP_SELECT_MASK = 0xf00000
-};
-
-static uint32_t dac_data_bits(uint16_t dac_data)
-{
- return dac_data & DAC_DATA_MASK;
-}
-
-static uint32_t dac_channel_select_bits(unsigned channel)
-{
- return (channel << 16) & DAC_CHANNEL_SELECT_MASK;
-}
-
-static uint32_t dac_group_select_bits(unsigned group)
-{
- return (1 << (20 + group)) & DAC_GROUP_SELECT_MASK;
-}
-
-static uint32_t dac_channel_and_group_select_bits(unsigned comedi_channel)
-{
- return dac_channel_select_bits(comedi_channel % 8) |
- dac_group_select_bits(comedi_channel / 8);
-}
-
-enum sync_output_contents {
- SYNC_MODE = 0x1,
- DAC_BUSY = 0x2, /* dac state machine is not ready */
-};
-
-enum sync_output_trigger_contents {
- SYNC_TRIGGER_BITS = 0x0 /* any value works */
-};
-
-enum board_id_contents {
- BOARD_ID_MASK = 0xf
-};
-
-static const struct comedi_lrange ao_ranges_1724 = {
+/*
+ * PCI bar 2 Register I/O map (dev->iobase)
+ */
+#define PCI1724_DAC_CTRL_REG 0x00
+#define PCI1724_DAC_CTRL_GX(x) (1 << (20 + ((x) / 8)))
+#define PCI1724_DAC_CTRL_CX(x) (((x) % 8) << 16)
+#define PCI1724_DAC_CTRL_MODE_GAIN (1 << 14)
+#define PCI1724_DAC_CTRL_MODE_OFFSET (2 << 14)
+#define PCI1724_DAC_CTRL_MODE_NORMAL (3 << 14)
+#define PCI1724_DAC_CTRL_MODE_MASK (3 << 14)
+#define PCI1724_DAC_CTRL_DATA(x) (((x) & 0x3fff) << 0)
+#define PCI1724_SYNC_CTRL_REG 0x04
+#define PCI1724_SYNC_CTRL_DACSTAT (1 << 1)
+#define PCI1724_SYNC_CTRL_SYN (1 << 0)
+#define PCI1724_EEPROM_CTRL_REG 0x08
+#define PCI1724_SYNC_TRIG_REG 0x0c /* any value works */
+#define PCI1724_BOARD_ID_REG 0x10
+#define PCI1724_BOARD_ID_MASK (0xf << 0)
+
+static const struct comedi_lrange adv_pci1724_ao_ranges = {
4, {
BIP_RANGE(10),
RANGE_mA(0, 20),
@@ -125,254 +79,120 @@ static const struct comedi_lrange ao_ranges_1724 = {
}
};
-/* this structure is for data unique to this hardware driver. */
-struct adv_pci1724_private {
- int ao_value[NUM_AO_CHANNELS];
- int offset_value[NUM_AO_CHANNELS];
- int gain_value[NUM_AO_CHANNELS];
-};
-
-static int wait_for_dac_idle(struct comedi_device *dev)
-{
- static const int timeout = 10000;
- int i;
-
- for (i = 0; i < timeout; ++i) {
- if ((inl(dev->iobase + SYNC_OUTPUT_REG) & DAC_BUSY) == 0)
- break;
- udelay(1);
- }
- if (i == timeout) {
- dev_err(dev->class_dev,
- "Timed out waiting for dac to become idle\n");
- return -EIO;
- }
- return 0;
-}
-
-static int set_dac(struct comedi_device *dev, unsigned mode, unsigned channel,
- unsigned data)
-{
- int retval;
- unsigned control_bits;
-
- retval = wait_for_dac_idle(dev);
- if (retval < 0)
- return retval;
-
- control_bits = mode;
- control_bits |= dac_channel_and_group_select_bits(channel);
- control_bits |= dac_data_bits(data);
- outl(control_bits, dev->iobase + DAC_CONTROL_REG);
- return 0;
-}
-
-static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int adv_pci1724_dac_idle(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned long context)
{
- struct adv_pci1724_private *devpriv = dev->private;
- int channel = CR_CHAN(insn->chanspec);
- int retval;
- int i;
+ unsigned int status;
- /* turn off synchronous mode */
- outl(0, dev->iobase + SYNC_OUTPUT_REG);
-
- for (i = 0; i < insn->n; ++i) {
- retval = set_dac(dev, DAC_NORMAL_MODE, channel, data[i]);
- if (retval < 0)
- return retval;
- devpriv->ao_value[channel] = data[i];
- }
- return insn->n;
+ status = inl(dev->iobase + PCI1724_SYNC_CTRL_REG);
+ if ((status & PCI1724_SYNC_CTRL_DACSTAT) == 0)
+ return 0;
+ return -EBUSY;
}
-static int ao_readback_insn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int adv_pci1724_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct adv_pci1724_private *devpriv = dev->private;
- int channel = CR_CHAN(insn->chanspec);
- int i;
-
- if (devpriv->ao_value[channel] < 0) {
- dev_err(dev->class_dev,
- "Cannot read back channels which have not yet been written to\n");
- return -EIO;
- }
- for (i = 0; i < insn->n; i++)
- data[i] = devpriv->ao_value[channel];
-
- return insn->n;
-}
-
-static int offset_write_insn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- struct adv_pci1724_private *devpriv = dev->private;
- int channel = CR_CHAN(insn->chanspec);
- int retval;
- int i;
-
- /* turn off synchronous mode */
- outl(0, dev->iobase + SYNC_OUTPUT_REG);
-
- for (i = 0; i < insn->n; ++i) {
- retval = set_dac(dev, DAC_OFFSET_MODE, channel, data[i]);
- if (retval < 0)
- return retval;
- devpriv->offset_value[channel] = data[i];
- }
-
- return insn->n;
-}
-
-static int offset_read_insn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- struct adv_pci1724_private *devpriv = dev->private;
- unsigned int channel = CR_CHAN(insn->chanspec);
+ unsigned long mode = (unsigned long)s->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int ctrl;
+ int ret;
int i;
- if (devpriv->offset_value[channel] < 0) {
- dev_err(dev->class_dev,
- "Cannot read back channels which have not yet been written to\n");
- return -EIO;
- }
- for (i = 0; i < insn->n; i++)
- data[i] = devpriv->offset_value[channel];
-
- return insn->n;
-}
-
-static int gain_write_insn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- struct adv_pci1724_private *devpriv = dev->private;
- int channel = CR_CHAN(insn->chanspec);
- int retval;
- int i;
+ ctrl = PCI1724_DAC_CTRL_GX(chan) | PCI1724_DAC_CTRL_CX(chan) | mode;
/* turn off synchronous mode */
- outl(0, dev->iobase + SYNC_OUTPUT_REG);
+ outl(0, dev->iobase + PCI1724_SYNC_CTRL_REG);
for (i = 0; i < insn->n; ++i) {
- retval = set_dac(dev, DAC_GAIN_MODE, channel, data[i]);
- if (retval < 0)
- return retval;
- devpriv->gain_value[channel] = data[i];
- }
+ unsigned int val = data[i];
- return insn->n;
-}
+ ret = comedi_timeout(dev, s, insn, adv_pci1724_dac_idle, 0);
+ if (ret)
+ return ret;
-static int gain_read_insn(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data)
-{
- struct adv_pci1724_private *devpriv = dev->private;
- unsigned int channel = CR_CHAN(insn->chanspec);
- int i;
+ outl(ctrl | PCI1724_DAC_CTRL_DATA(val),
+ dev->iobase + PCI1724_DAC_CTRL_REG);
- if (devpriv->gain_value[channel] < 0) {
- dev_err(dev->class_dev,
- "Cannot read back channels which have not yet been written to\n");
- return -EIO;
+ s->readback[chan] = val;
}
- for (i = 0; i < insn->n; i++)
- data[i] = devpriv->gain_value[channel];
return insn->n;
}
-/* Allocate and initialize the subdevice structures.
- */
-static int setup_subdevices(struct comedi_device *dev)
+static int adv_pci1724_auto_attach(struct comedi_device *dev,
+ unsigned long context_unused)
{
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
struct comedi_subdevice *s;
+ unsigned int board_id;
int ret;
+ ret = comedi_pci_enable(dev);
+ if (ret)
+ return ret;
+
+ dev->iobase = pci_resource_start(pcidev, 2);
+ board_id = inl(dev->iobase + PCI1724_BOARD_ID_REG);
+ dev_info(dev->class_dev, "board id: %d\n",
+ board_id & PCI1724_BOARD_ID_MASK);
+
ret = comedi_alloc_subdevices(dev, 3);
if (ret)
return ret;
- /* analog output subdevice */
+ /* Analog Output subdevice */
s = &dev->subdevices[0];
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
- s->n_chan = NUM_AO_CHANNELS;
- s->maxdata = 0x3fff;
- s->range_table = &ao_ranges_1724;
- s->insn_read = ao_readback_insn;
- s->insn_write = ao_winsn;
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
+ s->n_chan = 32;
+ s->maxdata = 0x3fff;
+ s->range_table = &adv_pci1724_ao_ranges;
+ s->insn_write = adv_pci1724_insn_write;
+ s->private = (void *)PCI1724_DAC_CTRL_MODE_NORMAL;
+
+ ret = comedi_alloc_subdev_readback(s);
+ if (ret)
+ return ret;
- /* offset calibration */
+ /* Offset Calibration subdevice */
s = &dev->subdevices[1];
- s->type = COMEDI_SUBD_CALIB;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
- s->n_chan = NUM_AO_CHANNELS;
- s->insn_read = offset_read_insn;
- s->insn_write = offset_write_insn;
- s->maxdata = 0x3fff;
+ s->type = COMEDI_SUBD_CALIB;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
+ s->n_chan = 32;
+ s->maxdata = 0x3fff;
+ s->insn_write = adv_pci1724_insn_write;
+ s->private = (void *)PCI1724_DAC_CTRL_MODE_OFFSET;
+
+ ret = comedi_alloc_subdev_readback(s);
+ if (ret)
+ return ret;
- /* gain calibration */
+ /* Gain Calibration subdevice */
s = &dev->subdevices[2];
- s->type = COMEDI_SUBD_CALIB;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
- s->n_chan = NUM_AO_CHANNELS;
- s->insn_read = gain_read_insn;
- s->insn_write = gain_write_insn;
- s->maxdata = 0x3fff;
-
- return 0;
-}
-
-static int adv_pci1724_auto_attach(struct comedi_device *dev,
- unsigned long context_unused)
-{
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- struct adv_pci1724_private *devpriv;
- int i;
- int retval;
- unsigned int board_id;
-
- devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
- if (!devpriv)
- return -ENOMEM;
-
- /* init software copies of output values to indicate we don't know
- * what the output value is since it has never been written. */
- for (i = 0; i < NUM_AO_CHANNELS; ++i) {
- devpriv->ao_value[i] = -1;
- devpriv->offset_value[i] = -1;
- devpriv->gain_value[i] = -1;
- }
-
- retval = comedi_pci_enable(dev);
- if (retval)
- return retval;
-
- dev->iobase = pci_resource_start(pcidev, 2);
- board_id = inl(dev->iobase + BOARD_ID_REG) & BOARD_ID_MASK;
- dev_info(dev->class_dev, "board id: %d\n", board_id);
-
- retval = setup_subdevices(dev);
- if (retval < 0)
- return retval;
+ s->type = COMEDI_SUBD_CALIB;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
+ s->n_chan = 32;
+ s->maxdata = 0x3fff;
+ s->insn_write = adv_pci1724_insn_write;
+ s->private = (void *)PCI1724_DAC_CTRL_MODE_GAIN;
+
+ ret = comedi_alloc_subdev_readback(s);
+ if (ret)
+ return ret;
- dev_info(dev->class_dev, "%s (pci %s) attached, board id: %u\n",
- dev->board_name, pci_name(pcidev), board_id);
return 0;
}
static struct comedi_driver adv_pci1724_driver = {
- .driver_name = "adv_pci1724",
- .module = THIS_MODULE,
- .auto_attach = adv_pci1724_auto_attach,
- .detach = comedi_pci_detach,
+ .driver_name = "adv_pci1724",
+ .module = THIS_MODULE,
+ .auto_attach = adv_pci1724_auto_attach,
+ .detach = comedi_pci_detach,
};
static int adv_pci1724_pci_probe(struct pci_dev *dev,
@@ -389,12 +209,11 @@ static const struct pci_device_id adv_pci1724_pci_table[] = {
MODULE_DEVICE_TABLE(pci, adv_pci1724_pci_table);
static struct pci_driver adv_pci1724_pci_driver = {
- .name = "adv_pci1724",
- .id_table = adv_pci1724_pci_table,
- .probe = adv_pci1724_pci_probe,
- .remove = comedi_pci_auto_unconfig,
+ .name = "adv_pci1724",
+ .id_table = adv_pci1724_pci_table,
+ .probe = adv_pci1724_pci_probe,
+ .remove = comedi_pci_auto_unconfig,
};
-
module_comedi_pci_driver(adv_pci1724_driver, adv_pci1724_pci_driver);
MODULE_AUTHOR("Frank Mori Hess <fmh6jj@gmail.com>");
diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
index f2e2d7e163bf..09609d6d02da 100644
--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
+++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
@@ -930,7 +930,7 @@ static int pci1760_attach(struct comedi_device *dev)
s = &dev->subdevices[0];
s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
+ s->subdev_flags = SDF_READABLE;
s->n_chan = 8;
s->maxdata = 1;
s->len_chanlist = 8;
@@ -939,7 +939,7 @@ static int pci1760_attach(struct comedi_device *dev)
s = &dev->subdevices[1];
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 8;
s->maxdata = 1;
s->len_chanlist = 8;
@@ -978,7 +978,7 @@ static int pci_dio_add_di(struct comedi_device *dev,
const struct dio_boardtype *this_board = dev->board_ptr;
s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON | d->specflags;
+ s->subdev_flags = SDF_READABLE | d->specflags;
if (d->chans > 16)
s->subdev_flags |= SDF_LSAMPL;
s->n_chan = d->chans;
@@ -1008,7 +1008,7 @@ static int pci_dio_add_do(struct comedi_device *dev,
const struct dio_boardtype *this_board = dev->board_ptr;
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
+ s->subdev_flags = SDF_WRITABLE;
if (d->chans > 16)
s->subdev_flags |= SDF_LSAMPL;
s->n_chan = d->chans;
diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c
index 538277a691b2..fbc3e5aa94cb 100644
--- a/drivers/staging/comedi/drivers/aio_aio12_8.c
+++ b/drivers/staging/comedi/drivers/aio_aio12_8.c
@@ -212,7 +212,6 @@ static int aio_aio12_8_attach(struct comedi_device *dev,
s->maxdata = 0x0fff;
s->range_table = &range_aio_aio12_8;
s->insn_write = aio_aio12_8_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/amcc_s5933.h b/drivers/staging/comedi/drivers/amcc_s5933.h
index cf6a497b092c..d4b8c0195bd3 100644
--- a/drivers/staging/comedi/drivers/amcc_s5933.h
+++ b/drivers/staging/comedi/drivers/amcc_s5933.h
@@ -110,6 +110,8 @@
#define AGCSTS_TCZERO_MASK 0x000000c0
#define AGCSTS_FIFO_ST_MASK 0x0000003f
+#define AGCSTS_TC_ENABLE 0x10000000
+
#define AGCSTS_RESET_MBFLAGS 0x08000000
#define AGCSTS_RESET_P2A_FIFO 0x04000000
#define AGCSTS_RESET_A2P_FIFO 0x02000000
diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c
index 2c1bfb09601d..26aad705aad3 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200_common.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c
@@ -120,7 +120,6 @@ struct dio200_subdev_intr {
unsigned int ofs;
unsigned int valid_isns;
unsigned int enabled_isns;
- unsigned int stopcount;
bool active:1;
};
@@ -256,7 +255,6 @@ static void dio200_read_scan_intr(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned int triggered)
{
- struct dio200_subdev_intr *subpriv = s->private;
struct comedi_cmd *cmd = &s->async->cmd;
unsigned short val;
unsigned int n, ch;
@@ -267,26 +265,12 @@ static void dio200_read_scan_intr(struct comedi_device *dev,
if (triggered & (1U << ch))
val |= (1U << n);
}
- /* Write the scan to the buffer. */
- if (comedi_buf_put(s, val)) {
- s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
- } else {
- /* Error! Stop acquisition. */
- dio200_stop_intr(dev, s);
- s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
- dev_err(dev->class_dev, "buffer overflow\n");
- }
- /* Check for end of acquisition. */
- if (cmd->stop_src == TRIG_COUNT) {
- if (subpriv->stopcount > 0) {
- subpriv->stopcount--;
- if (subpriv->stopcount == 0) {
- s->async->events |= COMEDI_CB_EOA;
- dio200_stop_intr(dev, s);
- }
- }
- }
+ comedi_buf_write_samples(s, &val, 1);
+
+ if (cmd->stop_src == TRIG_COUNT &&
+ s->async->scans_done >= cmd->stop_arg)
+ s->async->events |= COMEDI_CB_EOA;
}
static int dio200_handle_read_intr(struct comedi_device *dev,
@@ -297,13 +281,11 @@ static int dio200_handle_read_intr(struct comedi_device *dev,
unsigned triggered;
unsigned intstat;
unsigned cur_enabled;
- unsigned int oldevents;
unsigned long flags;
triggered = 0;
spin_lock_irqsave(&subpriv->spinlock, flags);
- oldevents = s->async->events;
if (board->has_int_sce) {
/*
* Collect interrupt sources that have triggered and disable
@@ -356,8 +338,7 @@ static int dio200_handle_read_intr(struct comedi_device *dev,
}
spin_unlock_irqrestore(&subpriv->spinlock, flags);
- if (oldevents != s->async->events)
- comedi_event(dev, s);
+ comedi_handle_events(dev, s);
return (triggered != 0);
}
@@ -436,7 +417,6 @@ static int dio200_subdev_intr_cmd(struct comedi_device *dev,
spin_lock_irqsave(&subpriv->spinlock, flags);
subpriv->active = true;
- subpriv->stopcount = cmd->stop_arg;
if (cmd->start_src == TRIG_INT)
s->async->inttrig = dio200_inttrig_start_intr;
@@ -469,7 +449,7 @@ static int dio200_subdev_intr_init(struct comedi_device *dev,
dio200_write8(dev, subpriv->ofs, 0);
s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
+ s->subdev_flags = SDF_READABLE | SDF_CMD_READ | SDF_PACKED;
if (board->has_int_sce) {
s->n_chan = DIO200_MAX_ISNS;
s->len_chanlist = DIO200_MAX_ISNS;
diff --git a/drivers/staging/comedi/drivers/amplc_pc236_common.c b/drivers/staging/comedi/drivers/amplc_pc236_common.c
index 963c5d868b81..be87172d1f3f 100644
--- a/drivers/staging/comedi/drivers/amplc_pc236_common.c
+++ b/drivers/staging/comedi/drivers/amplc_pc236_common.c
@@ -135,9 +135,8 @@ static irqreturn_t pc236_interrupt(int irq, void *d)
handled = pc236_intr_check(dev);
if (dev->attached && handled) {
- comedi_buf_put(s, 0);
- s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
- comedi_event(dev, s);
+ comedi_buf_write_samples(s, &s->state, 1);
+ comedi_handle_events(dev, s);
}
return IRQ_RETVAL(handled);
}
diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
index f8e551d8fd9e..b1946ce6ecc1 100644
--- a/drivers/staging/comedi/drivers/amplc_pc263.c
+++ b/drivers/staging/comedi/drivers/amplc_pc263.c
@@ -83,7 +83,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s = &dev->subdevices[0];
/* digital output subdevice */
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 16;
s->maxdata = 1;
s->range_table = &range_digital;
diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
index 3bbbb57f19d6..924c8298c7a0 100644
--- a/drivers/staging/comedi/drivers/amplc_pci224.c
+++ b/drivers/staging/comedi/drivers/amplc_pci224.c
@@ -381,7 +381,6 @@ struct pci224_private {
unsigned short daccon;
unsigned int cached_div1;
unsigned int cached_div2;
- unsigned int ao_stop_count;
unsigned short ao_enab; /* max 16 channels so 'short' will do */
unsigned char intsce;
};
@@ -514,30 +513,21 @@ static void pci224_ao_handle_fifo(struct comedi_device *dev,
{
struct pci224_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
- unsigned int bytes_per_scan = cfc_bytes_per_scan(s);
- unsigned int num_scans;
+ unsigned int num_scans = comedi_nscans_left(s, 0);
unsigned int room;
unsigned short dacstat;
unsigned int i, n;
- /* Determine number of scans available in buffer. */
- num_scans = comedi_buf_read_n_available(s) / bytes_per_scan;
- if (cmd->stop_src == TRIG_COUNT) {
- /* Fixed number of scans. */
- if (num_scans > devpriv->ao_stop_count)
- num_scans = devpriv->ao_stop_count;
- }
-
/* Determine how much room is in the FIFO (in samples). */
dacstat = inw(dev->iobase + PCI224_DACCON);
switch (dacstat & PCI224_DACCON_FIFOFL_MASK) {
case PCI224_DACCON_FIFOFL_EMPTY:
room = PCI224_FIFO_ROOM_EMPTY;
if (cmd->stop_src == TRIG_COUNT &&
- devpriv->ao_stop_count == 0) {
+ s->async->scans_done >= cmd->stop_arg) {
/* FIFO empty at end of counted acquisition. */
s->async->events |= COMEDI_CB_EOA;
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return;
}
break;
@@ -568,25 +558,23 @@ static void pci224_ao_handle_fifo(struct comedi_device *dev,
/* Process scans. */
for (n = 0; n < num_scans; n++) {
- cfc_read_array_from_buffer(s, &devpriv->ao_scan_vals[0],
- bytes_per_scan);
+ comedi_buf_read_samples(s, &devpriv->ao_scan_vals[0],
+ cmd->chanlist_len);
for (i = 0; i < cmd->chanlist_len; i++) {
outw(devpriv->ao_scan_vals[devpriv->ao_scan_order[i]],
dev->iobase + PCI224_DACDATA);
}
}
- if (cmd->stop_src == TRIG_COUNT) {
- devpriv->ao_stop_count -= num_scans;
- if (devpriv->ao_stop_count == 0) {
- /*
- * Change FIFO interrupt trigger level to wait
- * until FIFO is empty.
- */
- devpriv->daccon = COMBINE(devpriv->daccon,
- PCI224_DACCON_FIFOINTR_EMPTY,
- PCI224_DACCON_FIFOINTR_MASK);
- outw(devpriv->daccon, dev->iobase + PCI224_DACCON);
- }
+ if (cmd->stop_src == TRIG_COUNT &&
+ s->async->scans_done >= cmd->stop_arg) {
+ /*
+ * Change FIFO interrupt trigger level to wait
+ * until FIFO is empty.
+ */
+ devpriv->daccon = COMBINE(devpriv->daccon,
+ PCI224_DACCON_FIFOINTR_EMPTY,
+ PCI224_DACCON_FIFOINTR_MASK);
+ outw(devpriv->daccon, dev->iobase + PCI224_DACCON);
}
if ((devpriv->daccon & PCI224_DACCON_TRIG_MASK) ==
PCI224_DACCON_TRIG_NONE) {
@@ -618,7 +606,7 @@ static void pci224_ao_handle_fifo(struct comedi_device *dev,
outw(devpriv->daccon, dev->iobase + PCI224_DACCON);
}
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
}
static int pci224_ao_inttrig_start(struct comedi_device *dev,
@@ -908,14 +896,6 @@ static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
if (cmd->scan_begin_src == TRIG_TIMER)
pci224_ao_start_pacer(dev, s);
- /*
- * Sort out end of acquisition.
- */
- if (cmd->stop_src == TRIG_COUNT)
- devpriv->ao_stop_count = cmd->stop_arg;
- else /* TRIG_EXT | TRIG_NONE */
- devpriv->ao_stop_count = 0;
-
spin_lock_irqsave(&devpriv->ao_spinlock, flags);
if (cmd->start_src == TRIG_INT) {
s->async->inttrig = pci224_ao_inttrig_start;
@@ -1095,7 +1075,6 @@ pci224_auto_attach(struct comedi_device *dev, unsigned long context_model)
s->maxdata = (1 << thisboard->ao_bits) - 1;
s->range_table = thisboard->ao_range;
s->insn_write = pci224_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
s->len_chanlist = s->n_chan;
dev->write_subdev = s;
s->do_cmd = pci224_ao_cmd;
diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
index 01796cd28e5b..49806a5e514c 100644
--- a/drivers/staging/comedi/drivers/amplc_pci230.c
+++ b/drivers/staging/comedi/drivers/amplc_pci230.c
@@ -35,7 +35,7 @@
* automatically.
*
* The PCI230+ and PCI260+ have the same PCI device IDs as the PCI230 and
- * PCI260, but can be distinguished by the the size of the PCI regions. A
+ * PCI260, but can be distinguished by the size of the PCI regions. A
* card will be configured as a "+" model if detected as such.
*
* Subdevices:
@@ -490,9 +490,6 @@ struct pci230_private {
spinlock_t ai_stop_spinlock; /* Spin lock for stopping AI command */
spinlock_t ao_stop_spinlock; /* Spin lock for stopping AO command */
unsigned long daqio; /* PCI230's DAQ I/O space */
- unsigned int ai_scan_count; /* Number of AI scans remaining */
- unsigned int ai_scan_pos; /* Current position within AI scan */
- unsigned int ao_scan_count; /* Number of AO scans remaining. */
int intr_cpuid; /* ID of CPU running ISR */
unsigned short hwver; /* Hardware version (for '+' models) */
unsigned short adccon; /* ADCCON register value */
@@ -1074,37 +1071,27 @@ static void pci230_ao_stop(struct comedi_device *dev,
static void pci230_handle_ao_nofifo(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- struct pci230_private *devpriv = dev->private;
- unsigned short data;
- int i, ret;
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
+ unsigned short data;
+ int i;
- if (cmd->stop_src == TRIG_COUNT && devpriv->ao_scan_count == 0)
+ if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
return;
+
for (i = 0; i < cmd->chanlist_len; i++) {
unsigned int chan = CR_CHAN(cmd->chanlist[i]);
- /* Read sample from Comedi's circular buffer. */
- ret = comedi_buf_get(s, &data);
- if (ret == 0) {
- s->async->events |= COMEDI_CB_OVERFLOW;
- pci230_ao_stop(dev, s);
- dev_err(dev->class_dev, "AO buffer underrun\n");
+ if (!comedi_buf_read_samples(s, &data, 1)) {
+ async->events |= COMEDI_CB_OVERFLOW;
return;
}
pci230_ao_write_nofifo(dev, data, chan);
s->readback[chan] = data;
}
- async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
- if (cmd->stop_src == TRIG_COUNT) {
- devpriv->ao_scan_count--;
- if (devpriv->ao_scan_count == 0) {
- /* End of acquisition. */
- async->events |= COMEDI_CB_EOA;
- pci230_ao_stop(dev, s);
- }
- }
+
+ if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
+ async->events |= COMEDI_CB_EOA;
}
/*
@@ -1117,26 +1104,18 @@ static bool pci230_handle_ao_fifo(struct comedi_device *dev,
struct pci230_private *devpriv = dev->private;
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
- unsigned int num_scans;
+ unsigned int num_scans = comedi_nscans_left(s, 0);
unsigned int room;
unsigned short dacstat;
unsigned int i, n;
unsigned int events = 0;
- bool running;
/* Get DAC FIFO status. */
dacstat = inw(devpriv->daqio + PCI230_DACCON);
- /* Determine number of scans available in buffer. */
- num_scans = comedi_buf_read_n_available(s) / cfc_bytes_per_scan(s);
- if (cmd->stop_src == TRIG_COUNT) {
- /* Fixed number of scans. */
- if (num_scans > devpriv->ao_scan_count)
- num_scans = devpriv->ao_scan_count;
- if (devpriv->ao_scan_count == 0) {
- /* End of acquisition. */
- events |= COMEDI_CB_EOA;
- }
- }
+
+ if (cmd->stop_src == TRIG_COUNT && num_scans == 0)
+ events |= COMEDI_CB_EOA;
+
if (events == 0) {
/* Check for FIFO underrun. */
if (dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) {
@@ -1175,27 +1154,22 @@ static bool pci230_handle_ao_fifo(struct comedi_device *dev,
unsigned int chan = CR_CHAN(cmd->chanlist[i]);
unsigned short datum;
- comedi_buf_get(s, &datum);
+ comedi_buf_read_samples(s, &datum, 1);
pci230_ao_write_fifo(dev, datum, chan);
s->readback[chan] = datum;
}
}
- events |= COMEDI_CB_EOS | COMEDI_CB_BLOCK;
- if (cmd->stop_src == TRIG_COUNT) {
- devpriv->ao_scan_count -= num_scans;
- if (devpriv->ao_scan_count == 0) {
- /*
- * All data for the command has been written
- * to FIFO. Set FIFO interrupt trigger level
- * to 'empty'.
- */
- devpriv->daccon =
- (devpriv->daccon &
- ~PCI230P2_DAC_INT_FIFO_MASK) |
- PCI230P2_DAC_INT_FIFO_EMPTY;
- outw(devpriv->daccon,
- devpriv->daqio + PCI230_DACCON);
- }
+
+ if (cmd->stop_src == TRIG_COUNT &&
+ async->scans_done >= cmd->stop_arg) {
+ /*
+ * All data for the command has been written
+ * to FIFO. Set FIFO interrupt trigger level
+ * to 'empty'.
+ */
+ devpriv->daccon &= ~PCI230P2_DAC_INT_FIFO_MASK;
+ devpriv->daccon |= PCI230P2_DAC_INT_FIFO_EMPTY;
+ outw(devpriv->daccon, devpriv->daqio + PCI230_DACCON);
}
/* Check if FIFO underrun occurred while writing to FIFO. */
dacstat = inw(devpriv->daqio + PCI230_DACCON);
@@ -1204,15 +1178,8 @@ static bool pci230_handle_ao_fifo(struct comedi_device *dev,
events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
}
}
- if (events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW)) {
- /* Stopping AO due to completion or error. */
- pci230_ao_stop(dev, s);
- running = false;
- } else {
- running = true;
- }
async->events |= events;
- return running;
+ return !(async->events & COMEDI_CB_CANCEL_MASK);
}
static int pci230_ao_inttrig_scan_begin(struct comedi_device *dev,
@@ -1235,7 +1202,7 @@ static int pci230_ao_inttrig_scan_begin(struct comedi_device *dev,
/* Not using DAC FIFO. */
spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
pci230_handle_ao_nofifo(dev, s);
- comedi_event(dev, s);
+ comedi_handle_events(dev, s);
} else {
/* Using DAC FIFO. */
/* Read DACSWTRIG register to trigger conversion. */
@@ -1265,7 +1232,7 @@ static void pci230_ao_start(struct comedi_device *dev,
/* Preload FIFO data. */
run = pci230_handle_ao_fifo(dev, s);
- comedi_event(dev, s);
+ comedi_handle_events(dev, s);
if (!run) {
/* Stopped. */
return;
@@ -1354,8 +1321,6 @@ static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
return -EBUSY;
}
- devpriv->ao_scan_count = cmd->stop_arg;
-
/*
* Set range - see analogue output range table; 0 => unipolar 10V,
* 1 => bipolar +/-10V range scale
@@ -1754,19 +1719,15 @@ static void pci230_ai_update_fifo_trigger_level(struct comedi_device *dev,
{
struct pci230_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
- unsigned int scanlen = cmd->scan_end_arg;
unsigned int wake;
unsigned short triglev;
unsigned short adccon;
if (cmd->flags & CMDF_WAKE_EOS)
- wake = scanlen - devpriv->ai_scan_pos;
- else if (cmd->stop_src != TRIG_COUNT ||
- devpriv->ai_scan_count >= PCI230_ADC_FIFOLEVEL_HALFFULL ||
- scanlen >= PCI230_ADC_FIFOLEVEL_HALFFULL)
- wake = PCI230_ADC_FIFOLEVEL_HALFFULL;
+ wake = cmd->scan_end_arg - s->async->cur_chan;
else
- wake = devpriv->ai_scan_count * scanlen - devpriv->ai_scan_pos;
+ wake = comedi_nsamples_left(s, PCI230_ADC_FIFOLEVEL_HALFFULL);
+
if (wake >= PCI230_ADC_FIFOLEVEL_HALFFULL) {
triglev = PCI230_ADC_INT_FIFO_HALF;
} else if (wake > 1 && devpriv->hwver > 0) {
@@ -2059,28 +2020,17 @@ static void pci230_handle_ai(struct comedi_device *dev,
struct pci230_private *devpriv = dev->private;
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
- unsigned int scanlen = cmd->scan_end_arg;
- unsigned int events = 0;
unsigned int status_fifo;
unsigned int i;
unsigned int todo;
unsigned int fifoamount;
+ unsigned short val;
/* Determine number of samples to read. */
- if (cmd->stop_src != TRIG_COUNT) {
- todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
- } else if (devpriv->ai_scan_count == 0) {
- todo = 0;
- } else if (devpriv->ai_scan_count > PCI230_ADC_FIFOLEVEL_HALFFULL ||
- scanlen > PCI230_ADC_FIFOLEVEL_HALFFULL) {
- todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
- } else {
- todo = devpriv->ai_scan_count * scanlen - devpriv->ai_scan_pos;
- if (todo > PCI230_ADC_FIFOLEVEL_HALFFULL)
- todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
- }
+ todo = comedi_nsamples_left(s, PCI230_ADC_FIFOLEVEL_HALFFULL);
if (todo == 0)
return;
+
fifoamount = 0;
for (i = 0; i < todo; i++) {
if (fifoamount == 0) {
@@ -2092,7 +2042,7 @@ static void pci230_handle_ai(struct comedi_device *dev,
* unnoticed by the caller.
*/
dev_err(dev->class_dev, "AI FIFO overrun\n");
- events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
+ async->events |= COMEDI_CB_ERROR;
break;
} else if (status_fifo & PCI230_ADC_FIFO_EMPTY) {
/* FIFO empty. */
@@ -2111,37 +2061,23 @@ static void pci230_handle_ai(struct comedi_device *dev,
fifoamount = 1;
}
}
- /* Read sample and store in Comedi's circular buffer. */
- if (comedi_buf_put(s, pci230_ai_read(dev)) == 0) {
- events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
- dev_err(dev->class_dev, "AI buffer overflow\n");
+
+ val = pci230_ai_read(dev);
+ if (!comedi_buf_write_samples(s, &val, 1))
break;
- }
+
fifoamount--;
- devpriv->ai_scan_pos++;
- if (devpriv->ai_scan_pos == scanlen) {
- /* End of scan. */
- devpriv->ai_scan_pos = 0;
- devpriv->ai_scan_count--;
- async->events |= COMEDI_CB_EOS;
+
+ if (cmd->stop_src == TRIG_COUNT &&
+ async->scans_done >= cmd->stop_arg) {
+ async->events |= COMEDI_CB_EOA;
+ break;
}
}
- if (cmd->stop_src == TRIG_COUNT && devpriv->ai_scan_count == 0) {
- /* End of acquisition. */
- events |= COMEDI_CB_EOA;
- } else {
- /* More samples required, tell Comedi to block. */
- events |= COMEDI_CB_BLOCK;
- }
- async->events |= events;
- if (async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
- COMEDI_CB_OVERFLOW)) {
- /* disable hardware conversions */
- pci230_ai_stop(dev, s);
- } else {
- /* update FIFO interrupt trigger level */
+
+ /* update FIFO interrupt trigger level if still running */
+ if (!(async->events & COMEDI_CB_CANCEL_MASK))
pci230_ai_update_fifo_trigger_level(dev, s);
- }
}
static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
@@ -2177,9 +2113,6 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
if (!pci230_claim_shared(dev, res_mask, OWNER_AICMD))
return -EBUSY;
- devpriv->ai_scan_count = cmd->stop_arg;
- devpriv->ai_scan_pos = 0; /* Position within scan. */
-
/*
* Steps:
* - Set channel scan list.
@@ -2355,7 +2288,8 @@ static irqreturn_t pci230_interrupt(int irq, void *d)
unsigned char status_int, valid_status_int, temp_ier;
struct comedi_device *dev = (struct comedi_device *)d;
struct pci230_private *devpriv = dev->private;
- struct comedi_subdevice *s;
+ struct comedi_subdevice *s_ao = dev->write_subdev;
+ struct comedi_subdevice *s_ai = dev->read_subdev;
unsigned long irqflags;
/* Read interrupt status/enable register. */
@@ -2385,23 +2319,14 @@ static irqreturn_t pci230_interrupt(int irq, void *d)
* two.
*/
- if (valid_status_int & PCI230_INT_ZCLK_CT1) {
- s = dev->write_subdev;
- pci230_handle_ao_nofifo(dev, s);
- comedi_event(dev, s);
- }
+ if (valid_status_int & PCI230_INT_ZCLK_CT1)
+ pci230_handle_ao_nofifo(dev, s_ao);
- if (valid_status_int & PCI230P2_INT_DAC) {
- s = dev->write_subdev;
- pci230_handle_ao_fifo(dev, s);
- comedi_event(dev, s);
- }
+ if (valid_status_int & PCI230P2_INT_DAC)
+ pci230_handle_ao_fifo(dev, s_ao);
- if (valid_status_int & PCI230_INT_ADC) {
- s = dev->read_subdev;
- pci230_handle_ai(dev, s);
- comedi_event(dev, s);
- }
+ if (valid_status_int & PCI230_INT_ADC)
+ pci230_handle_ai(dev, s_ai);
/* Reenable interrupts. */
spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
@@ -2410,6 +2335,9 @@ static irqreturn_t pci230_interrupt(int irq, void *d)
devpriv->intr_running = false;
spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
+ comedi_handle_events(dev, s_ao);
+ comedi_handle_events(dev, s_ai);
+
return IRQ_HANDLED;
}
@@ -2583,7 +2511,6 @@ static int pci230_auto_attach(struct comedi_device *dev,
s->maxdata = (1 << thisboard->ao_bits) - 1;
s->range_table = &pci230_ao_range;
s->insn_write = pci230_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
s->len_chanlist = 2;
if (dev->irq) {
dev->write_subdev = s;
diff --git a/drivers/staging/comedi/drivers/amplc_pci263.c b/drivers/staging/comedi/drivers/amplc_pci263.c
index 2259bee98d48..0d2224b832ac 100644
--- a/drivers/staging/comedi/drivers/amplc_pci263.c
+++ b/drivers/staging/comedi/drivers/amplc_pci263.c
@@ -71,7 +71,7 @@ static int pci263_auto_attach(struct comedi_device *dev,
s = &dev->subdevices[0];
/* digital output subdevice */
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 16;
s->maxdata = 1;
s->range_table = &range_digital;
diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
index e03dd6e71415..e7cb7032a910 100644
--- a/drivers/staging/comedi/drivers/c6xdigio.c
+++ b/drivers/staging/comedi/drivers/c6xdigio.c
@@ -265,7 +265,7 @@ static int c6xdigio_attach(struct comedi_device *dev,
s = &dev->subdevices[0];
/* pwm output subdevice */
s->type = COMEDI_SUBD_PWM;
- s->subdev_flags = SDF_WRITEABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 2;
s->maxdata = 500;
s->range_table = &range_unknown;
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index f88880aea6da..0a48d2a961d5 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -305,7 +305,6 @@ static int das16cs_auto_attach(struct comedi_device *dev,
s->maxdata = 0xffff;
s->range_table = &range_bipolar10;
s->insn_write = &das16cs_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
index 1ec363b7505c..669b1703eb99 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas.c
@@ -346,8 +346,6 @@ struct cb_pcidas_private {
/* divisors of master clock for analog input pacing */
unsigned int divisor1;
unsigned int divisor2;
- /* number of analog input samples remaining */
- unsigned int count;
/* bits to write to registers */
unsigned int adc_fifo_bits;
unsigned int s5933_intcsr_bits;
@@ -358,11 +356,6 @@ struct cb_pcidas_private {
/* divisors of master clock for analog output pacing */
unsigned int ao_divisor1;
unsigned int ao_divisor2;
- /* number of analog output samples remaining */
- unsigned int ao_count;
- unsigned int caldac_value[NUM_CHANNELS_8800];
- unsigned int trimpot_value[NUM_CHANNELS_8402];
- unsigned int dac08_value;
unsigned int calibration_source;
};
@@ -596,25 +589,14 @@ static void write_calibration_bitstream(struct comedi_device *dev,
}
}
-static int caldac_8800_write(struct comedi_device *dev, unsigned int address,
- uint8_t value)
+static void caldac_8800_write(struct comedi_device *dev,
+ unsigned int chan, uint8_t val)
{
struct cb_pcidas_private *devpriv = dev->private;
- static const int num_caldac_channels = 8;
static const int bitstream_length = 11;
- unsigned int bitstream = ((address & 0x7) << 8) | value;
+ unsigned int bitstream = ((chan & 0x7) << 8) | val;
static const int caldac_8800_udelay = 1;
- if (address >= num_caldac_channels) {
- dev_err(dev->class_dev, "illegal caldac channel\n");
- return -1;
- }
-
- if (value == devpriv->caldac_value[address])
- return 1;
-
- devpriv->caldac_value[address] = value;
-
write_calibration_bitstream(dev, cal_enable_bits(dev), bitstream,
bitstream_length);
@@ -623,75 +605,62 @@ static int caldac_8800_write(struct comedi_device *dev, unsigned int address,
devpriv->control_status + CALIBRATION_REG);
udelay(caldac_8800_udelay);
outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
-
- return 1;
}
-static int caldac_write_insn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int cb_pcidas_caldac_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- const unsigned int channel = CR_CHAN(insn->chanspec);
+ unsigned int chan = CR_CHAN(insn->chanspec);
- return caldac_8800_write(dev, channel, data[0]);
-}
+ if (insn->n) {
+ unsigned int val = data[insn->n - 1];
-static int caldac_read_insn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- struct cb_pcidas_private *devpriv = dev->private;
-
- data[0] = devpriv->caldac_value[CR_CHAN(insn->chanspec)];
+ if (s->readback[chan] != val) {
+ caldac_8800_write(dev, chan, val);
+ s->readback[chan] = val;
+ }
+ }
- return 1;
+ return insn->n;
}
/* 1602/16 pregain offset */
static void dac08_write(struct comedi_device *dev, unsigned int value)
{
struct cb_pcidas_private *devpriv = dev->private;
- unsigned long cal_reg;
-
- if (devpriv->dac08_value != value) {
- devpriv->dac08_value = value;
-
- cal_reg = devpriv->control_status + CALIBRATION_REG;
- value &= 0xff;
- value |= cal_enable_bits(dev);
+ value &= 0xff;
+ value |= cal_enable_bits(dev);
- /* latch the new value into the caldac */
- outw(value, cal_reg);
- udelay(1);
- outw(value | SELECT_DAC08_BIT, cal_reg);
- udelay(1);
- outw(value, cal_reg);
- udelay(1);
- }
+ /* latch the new value into the caldac */
+ outw(value, devpriv->control_status + CALIBRATION_REG);
+ udelay(1);
+ outw(value | SELECT_DAC08_BIT,
+ devpriv->control_status + CALIBRATION_REG);
+ udelay(1);
+ outw(value, devpriv->control_status + CALIBRATION_REG);
+ udelay(1);
}
-static int dac08_write_insn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int cb_pcidas_dac08_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- int i;
-
- for (i = 0; i < insn->n; i++)
- dac08_write(dev, data[i]);
-
- return insn->n;
-}
+ unsigned int chan = CR_CHAN(insn->chanspec);
-static int dac08_read_insn(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data)
-{
- struct cb_pcidas_private *devpriv = dev->private;
+ if (insn->n) {
+ unsigned int val = data[insn->n - 1];
- data[0] = devpriv->dac08_value;
+ if (s->readback[chan] != val) {
+ dac08_write(dev, val);
+ s->readback[chan] = val;
+ }
+ }
- return 1;
+ return insn->n;
}
static int trimpot_7376_write(struct comedi_device *dev, uint8_t value)
@@ -740,50 +709,41 @@ static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel,
return 0;
}
-static int cb_pcidas_trimpot_write(struct comedi_device *dev,
- unsigned int channel, unsigned int value)
+static void cb_pcidas_trimpot_write(struct comedi_device *dev,
+ unsigned int chan, unsigned int val)
{
const struct cb_pcidas_board *thisboard = dev->board_ptr;
- struct cb_pcidas_private *devpriv = dev->private;
-
- if (devpriv->trimpot_value[channel] == value)
- return 1;
- devpriv->trimpot_value[channel] = value;
switch (thisboard->trimpot) {
case AD7376:
- trimpot_7376_write(dev, value);
+ trimpot_7376_write(dev, val);
break;
case AD8402:
- trimpot_8402_write(dev, channel, value);
+ trimpot_8402_write(dev, chan, val);
break;
default:
dev_err(dev->class_dev, "driver bug?\n");
- return -1;
+ break;
}
-
- return 1;
}
-static int trimpot_write_insn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int cb_pcidas_trimpot_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- unsigned int channel = CR_CHAN(insn->chanspec);
+ unsigned int chan = CR_CHAN(insn->chanspec);
- return cb_pcidas_trimpot_write(dev, channel, data[0]);
-}
+ if (insn->n) {
+ unsigned int val = data[insn->n - 1];
-static int trimpot_read_insn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- struct cb_pcidas_private *devpriv = dev->private;
- unsigned int channel = CR_CHAN(insn->chanspec);
-
- data[0] = devpriv->trimpot_value[channel];
+ if (s->readback[chan] != val) {
+ cb_pcidas_trimpot_write(dev, chan, val);
+ s->readback[chan] = val;
+ }
+ }
- return 1;
+ return insn->n;
}
static int cb_pcidas_ai_check_chanlist(struct comedi_device *dev,
@@ -976,9 +936,6 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev,
if (cmd->scan_begin_src == TRIG_TIMER || cmd->convert_src == TRIG_TIMER)
cb_pcidas_ai_load_counters(dev);
- /* set number of conversions */
- if (cmd->stop_src == TRIG_COUNT)
- devpriv->count = cmd->chanlist_len * cmd->stop_arg;
/* enable interrupts */
spin_lock_irqsave(&dev->spinlock, flags);
devpriv->adc_fifo_bits |= INTE;
@@ -1134,32 +1091,34 @@ static int cb_pcidas_cancel(struct comedi_device *dev,
return 0;
}
+static void cb_pcidas_ao_load_fifo(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned int nsamples)
+{
+ struct cb_pcidas_private *devpriv = dev->private;
+ unsigned int nbytes;
+
+ nsamples = comedi_nsamples_left(s, nsamples);
+ nbytes = comedi_buf_read_samples(s, devpriv->ao_buffer, nsamples);
+
+ nsamples = comedi_bytes_to_samples(s, nbytes);
+ outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, nsamples);
+}
+
static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned int trig_num)
{
const struct cb_pcidas_board *thisboard = dev->board_ptr;
struct cb_pcidas_private *devpriv = dev->private;
- unsigned int num_bytes, num_points = thisboard->fifo_size;
struct comedi_async *async = s->async;
- struct comedi_cmd *cmd = &s->async->cmd;
+ struct comedi_cmd *cmd = &async->cmd;
unsigned long flags;
if (trig_num != cmd->start_arg)
return -EINVAL;
- /* load up fifo */
- if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count < num_points)
- num_points = devpriv->ao_count;
-
- num_bytes = cfc_read_array_from_buffer(s, devpriv->ao_buffer,
- num_points * sizeof(short));
- num_points = num_bytes / sizeof(short);
-
- if (cmd->stop_src == TRIG_COUNT)
- devpriv->ao_count -= num_points;
- /* write data to board's fifo */
- outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, num_bytes);
+ cb_pcidas_ao_load_fifo(dev, s, thisboard->fifo_size);
/* enable dac half-full and empty interrupts */
spin_lock_irqsave(&dev->spinlock, flags);
@@ -1224,9 +1183,6 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev,
if (cmd->scan_begin_src == TRIG_TIMER)
cb_pcidas_ao_load_counters(dev);
- /* set number of conversions */
- if (cmd->stop_src == TRIG_COUNT)
- devpriv->ao_count = cmd->chanlist_len * cmd->stop_arg;
/* set pacer source */
spin_lock_irqsave(&dev->spinlock, flags);
switch (cmd->scan_begin_src) {
@@ -1275,8 +1231,6 @@ static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status)
struct comedi_subdevice *s = dev->write_subdev;
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
- unsigned int half_fifo = thisboard->fifo_size / 2;
- unsigned int num_points;
unsigned long flags;
if (status & DAEMI) {
@@ -1286,32 +1240,17 @@ static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status)
devpriv->control_status + INT_ADCFIFO);
spin_unlock_irqrestore(&dev->spinlock, flags);
if (inw(devpriv->ao_registers + DAC_CSR) & DAC_EMPTY) {
- if (cmd->stop_src == TRIG_NONE ||
- (cmd->stop_src == TRIG_COUNT
- && devpriv->ao_count)) {
+ if (cmd->stop_src == TRIG_COUNT &&
+ async->scans_done >= cmd->stop_arg) {
+ async->events |= COMEDI_CB_EOA;
+ } else {
dev_err(dev->class_dev, "dac fifo underflow\n");
async->events |= COMEDI_CB_ERROR;
}
- async->events |= COMEDI_CB_EOA;
}
} else if (status & DAHFI) {
- unsigned int num_bytes;
+ cb_pcidas_ao_load_fifo(dev, s, thisboard->fifo_size / 2);
- /* figure out how many points we are writing to fifo */
- num_points = half_fifo;
- if (cmd->stop_src == TRIG_COUNT &&
- devpriv->ao_count < num_points)
- num_points = devpriv->ao_count;
- num_bytes =
- cfc_read_array_from_buffer(s, devpriv->ao_buffer,
- num_points * sizeof(short));
- num_points = num_bytes / sizeof(short);
-
- if (cmd->stop_src == TRIG_COUNT)
- devpriv->ao_count -= num_points;
- /* write data to board's fifo */
- outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer,
- num_points);
/* clear half-full interrupt latch */
spin_lock_irqsave(&dev->spinlock, flags);
outw(devpriv->adc_fifo_bits | DAHFI,
@@ -1319,7 +1258,7 @@ static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status)
spin_unlock_irqrestore(&dev->spinlock, flags);
}
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
}
static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
@@ -1362,18 +1301,15 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
/* if fifo half-full */
if (status & ADHFI) {
/* read data */
- num_samples = half_fifo;
- if (cmd->stop_src == TRIG_COUNT &&
- num_samples > devpriv->count) {
- num_samples = devpriv->count;
- }
+ num_samples = comedi_nsamples_left(s, half_fifo);
insw(devpriv->adc_fifo + ADCDATA, devpriv->ai_buffer,
num_samples);
- cfc_write_array_to_buffer(s, devpriv->ai_buffer,
- num_samples * sizeof(short));
- devpriv->count -= num_samples;
- if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0)
+ comedi_buf_write_samples(s, devpriv->ai_buffer, num_samples);
+
+ if (cmd->stop_src == TRIG_COUNT &&
+ async->scans_done >= cmd->stop_arg)
async->events |= COMEDI_CB_EOA;
+
/* clear half-full interrupt latch */
spin_lock_irqsave(&dev->spinlock, flags);
outw(devpriv->adc_fifo_bits | INT,
@@ -1382,14 +1318,17 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
/* else if fifo not empty */
} else if (status & (ADNEI | EOBI)) {
for (i = 0; i < timeout; i++) {
+ unsigned short val;
+
/* break if fifo is empty */
if ((ADNE & inw(devpriv->control_status +
INT_ADCFIFO)) == 0)
break;
- cfc_write_to_buffer(s, inw(devpriv->adc_fifo));
+ val = inw(devpriv->adc_fifo);
+ comedi_buf_write_samples(s, &val, 1);
+
if (cmd->stop_src == TRIG_COUNT &&
- --devpriv->count == 0) {
- /* end of acquisition */
+ async->scans_done >= cmd->stop_arg) {
async->events |= COMEDI_CB_EOA;
break;
}
@@ -1419,7 +1358,7 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
}
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return IRQ_HANDLED;
}
@@ -1503,7 +1442,6 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
s->range_table = &cb_pcidas_ao_ranges;
/* default to no fifo (*insn_write) */
s->insn_write = cb_pcidas_ao_nofifo_winsn;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
@@ -1542,10 +1480,16 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
s->n_chan = NUM_CHANNELS_8800;
s->maxdata = 0xff;
- s->insn_read = caldac_read_insn;
- s->insn_write = caldac_write_insn;
- for (i = 0; i < s->n_chan; i++)
+ s->insn_write = cb_pcidas_caldac_insn_write;
+
+ ret = comedi_alloc_subdev_readback(s);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < s->n_chan; i++) {
caldac_8800_write(dev, i, s->maxdata / 2);
+ s->readback[i] = s->maxdata / 2;
+ }
/* trim potentiometer */
s = &dev->subdevices[5];
@@ -1558,10 +1502,16 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
s->n_chan = NUM_CHANNELS_8402;
s->maxdata = 0xff;
}
- s->insn_read = trimpot_read_insn;
- s->insn_write = trimpot_write_insn;
- for (i = 0; i < s->n_chan; i++)
+ s->insn_write = cb_pcidas_trimpot_insn_write;
+
+ ret = comedi_alloc_subdev_readback(s);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < s->n_chan; i++) {
cb_pcidas_trimpot_write(dev, i, s->maxdata / 2);
+ s->readback[i] = s->maxdata / 2;
+ }
/* dac08 caldac */
s = &dev->subdevices[6];
@@ -1569,10 +1519,17 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
s->type = COMEDI_SUBD_CALIB;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
s->n_chan = NUM_CHANNELS_DAC08;
- s->insn_read = dac08_read_insn;
- s->insn_write = dac08_write_insn;
s->maxdata = 0xff;
- dac08_write(dev, s->maxdata / 2);
+ s->insn_write = cb_pcidas_dac08_insn_write;
+
+ ret = comedi_alloc_subdev_readback(s);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < s->n_chan; i++) {
+ dac08_write(dev, s->maxdata / 2);
+ s->readback[i] = s->maxdata / 2;
+ }
} else
s->type = COMEDI_SUBD_UNUSED;
diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
index 3b6bffc66918..eddb7ace43df 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
@@ -1065,8 +1065,6 @@ struct pcidas64_private {
/* local address (used by dma controller) */
uint32_t local0_iobase;
uint32_t local1_iobase;
- /* number of analog input samples remaining */
- unsigned int ai_count;
/* dma buffers for analog input */
uint16_t *ai_buffer[MAX_AI_DMA_RING_COUNT];
/* physical addresses of ai dma buffers */
@@ -1087,8 +1085,6 @@ struct pcidas64_private {
dma_addr_t ao_dma_desc_bus_addr;
/* keeps track of buffer where the next ao sample should go */
unsigned int ao_dma_index;
- /* number of analog output samples remaining */
- unsigned long ao_count;
unsigned int hw_revision; /* stc chip hardware revision number */
/* last bits sent to INTR_ENABLE_REG register */
unsigned int intr_enable_bits;
@@ -1109,9 +1105,6 @@ struct pcidas64_private {
uint8_t i2c_cal_range_bits;
/* configure digital triggers to trigger on falling edge */
unsigned int ext_trig_falling;
- /* states of various devices stored to enable read-back */
- unsigned int ad8402_state[2];
- unsigned int caldac_state[8];
short ai_cmd_running;
unsigned int ai_fifo_segment_length;
struct ext_clock_info ext_clock;
@@ -2199,10 +2192,6 @@ static void setup_sample_counters(struct comedi_device *dev,
{
struct pcidas64_private *devpriv = dev->private;
- if (cmd->stop_src == TRIG_COUNT) {
- /* set software count */
- devpriv->ai_count = cmd->stop_arg * cmd->chanlist_len;
- }
/* load hardware conversion counter */
if (use_hw_sample_counter(cmd)) {
writew(cmd->stop_arg & 0xffff,
@@ -2642,8 +2631,6 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev)
{
struct pcidas64_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
- struct comedi_async *async = s->async;
- struct comedi_cmd *cmd = &async->cmd;
unsigned int i;
uint16_t prepost_bits;
int read_segment, read_index, write_segment, write_index;
@@ -2672,26 +2659,21 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev)
devpriv->ai_fifo_segment_length - read_index;
else
num_samples = write_index - read_index;
-
- if (cmd->stop_src == TRIG_COUNT) {
- if (devpriv->ai_count == 0)
- break;
- if (num_samples > devpriv->ai_count)
- num_samples = devpriv->ai_count;
-
- devpriv->ai_count -= num_samples;
- }
-
if (num_samples < 0) {
dev_err(dev->class_dev,
"cb_pcidas64: bug! num_samples < 0\n");
break;
}
+ num_samples = comedi_nsamples_left(s, num_samples);
+ if (num_samples == 0)
+ break;
+
for (i = 0; i < num_samples; i++) {
- cfc_write_to_buffer(s,
- readw(devpriv->main_iobase +
- ADC_FIFO_REG));
+ unsigned short val;
+
+ val = readw(devpriv->main_iobase + ADC_FIFO_REG);
+ comedi_buf_write_samples(s, &val, 1);
}
} while (read_segment != write_segment);
@@ -2706,33 +2688,30 @@ static void pio_drain_ai_fifo_32(struct comedi_device *dev)
{
struct pcidas64_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
- struct comedi_async *async = s->async;
- struct comedi_cmd *cmd = &async->cmd;
+ unsigned int nsamples;
unsigned int i;
- unsigned int max_transfer = 100000;
uint32_t fifo_data;
int write_code =
readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG) & 0x7fff;
int read_code =
readw(devpriv->main_iobase + ADC_READ_PNTR_REG) & 0x7fff;
- if (cmd->stop_src == TRIG_COUNT) {
- if (max_transfer > devpriv->ai_count)
- max_transfer = devpriv->ai_count;
+ nsamples = comedi_nsamples_left(s, 100000);
+ for (i = 0; read_code != write_code && i < nsamples;) {
+ unsigned short val;
- }
- for (i = 0; read_code != write_code && i < max_transfer;) {
fifo_data = readl(dev->mmio + ADC_FIFO_REG);
- cfc_write_to_buffer(s, fifo_data & 0xffff);
+ val = fifo_data & 0xffff;
+ comedi_buf_write_samples(s, &val, 1);
i++;
- if (i < max_transfer) {
- cfc_write_to_buffer(s, (fifo_data >> 16) & 0xffff);
+ if (i < nsamples) {
+ val = (fifo_data >> 16) & 0xffff;
+ comedi_buf_write_samples(s, &val, 1);
i++;
}
read_code = readw(devpriv->main_iobase + ADC_READ_PNTR_REG) &
0x7fff;
}
- devpriv->ai_count -= i;
}
/* empty fifo */
@@ -2750,8 +2729,7 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel)
{
const struct pcidas64_board *thisboard = dev->board_ptr;
struct pcidas64_private *devpriv = dev->private;
- struct comedi_async *async = dev->read_subdev->async;
- struct comedi_cmd *cmd = &async->cmd;
+ struct comedi_subdevice *s = dev->read_subdev;
uint32_t next_transfer_addr;
int j;
int num_samples = 0;
@@ -2772,16 +2750,10 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel)
devpriv->ai_buffer_bus_addr[devpriv->ai_dma_index] +
DMA_BUFFER_SIZE) && j < ai_dma_ring_count(thisboard); j++) {
/* transfer data from dma buffer to comedi buffer */
- num_samples = dma_transfer_size(dev);
- if (cmd->stop_src == TRIG_COUNT) {
- if (num_samples > devpriv->ai_count)
- num_samples = devpriv->ai_count;
- devpriv->ai_count -= num_samples;
- }
- cfc_write_array_to_buffer(dev->read_subdev,
- devpriv->ai_buffer[devpriv->
- ai_dma_index],
- num_samples * sizeof(uint16_t));
+ num_samples = comedi_nsamples_left(s, dma_transfer_size(dev));
+ comedi_buf_write_samples(s,
+ devpriv->ai_buffer[devpriv->ai_dma_index],
+ num_samples);
devpriv->ai_dma_index = (devpriv->ai_dma_index + 1) %
ai_dma_ring_count(thisboard);
}
@@ -2831,12 +2803,12 @@ static void handle_ai_interrupt(struct comedi_device *dev,
spin_unlock_irqrestore(&dev->spinlock, flags);
}
/* if we are have all the data, then quit */
- if ((cmd->stop_src == TRIG_COUNT && (int)devpriv->ai_count <= 0) ||
- (cmd->stop_src == TRIG_EXT && (status & ADC_STOP_BIT))) {
+ if ((cmd->stop_src == TRIG_COUNT &&
+ async->scans_done >= cmd->stop_arg) ||
+ (cmd->stop_src == TRIG_EXT && (status & ADC_STOP_BIT)))
async->events |= COMEDI_CB_EOA;
- }
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
}
static inline unsigned int prev_ao_dma_index(struct comedi_device *dev)
@@ -2871,22 +2843,6 @@ static int last_ao_dma_load_completed(struct comedi_device *dev)
return 1;
}
-static int ao_stopped_by_error(struct comedi_device *dev,
- const struct comedi_cmd *cmd)
-{
- struct pcidas64_private *devpriv = dev->private;
-
- if (cmd->stop_src == TRIG_NONE)
- return 1;
- if (cmd->stop_src == TRIG_COUNT) {
- if (devpriv->ao_count)
- return 1;
- if (last_ao_dma_load_completed(dev) == 0)
- return 1;
- }
- return 0;
-}
-
static inline int ao_dma_needs_restart(struct comedi_device *dev,
unsigned short dma_status)
{
@@ -2912,32 +2868,39 @@ static void restart_ao_dma(struct comedi_device *dev)
dma_start_sync(dev, 0);
}
+static unsigned int cb_pcidas64_ao_fill_buffer(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned short *dest,
+ unsigned int max_bytes)
+{
+ unsigned int nsamples = comedi_bytes_to_samples(s, max_bytes);
+ unsigned int actual_bytes;
+
+ nsamples = comedi_nsamples_left(s, nsamples);
+ actual_bytes = comedi_buf_read_samples(s, dest, nsamples);
+
+ return comedi_bytes_to_samples(s, actual_bytes);
+}
+
static unsigned int load_ao_dma_buffer(struct comedi_device *dev,
const struct comedi_cmd *cmd)
{
struct pcidas64_private *devpriv = dev->private;
- unsigned int num_bytes, buffer_index, prev_buffer_index;
+ struct comedi_subdevice *s = dev->write_subdev;
+ unsigned int buffer_index = devpriv->ao_dma_index;
+ unsigned int prev_buffer_index = prev_ao_dma_index(dev);
+ unsigned int nsamples;
+ unsigned int nbytes;
unsigned int next_bits;
- buffer_index = devpriv->ao_dma_index;
- prev_buffer_index = prev_ao_dma_index(dev);
-
- num_bytes = comedi_buf_read_n_available(dev->write_subdev);
- if (num_bytes > DMA_BUFFER_SIZE)
- num_bytes = DMA_BUFFER_SIZE;
- if (cmd->stop_src == TRIG_COUNT && num_bytes > devpriv->ao_count)
- num_bytes = devpriv->ao_count;
- num_bytes -= num_bytes % bytes_in_sample;
-
- if (num_bytes == 0)
+ nsamples = cb_pcidas64_ao_fill_buffer(dev, s,
+ devpriv->ao_buffer[buffer_index],
+ DMA_BUFFER_SIZE);
+ if (nsamples == 0)
return 0;
- num_bytes = cfc_read_array_from_buffer(dev->write_subdev,
- devpriv->
- ao_buffer[buffer_index],
- num_bytes);
- devpriv->ao_dma_desc[buffer_index].transfer_size =
- cpu_to_le32(num_bytes);
+ nbytes = comedi_samples_to_bytes(s, nsamples);
+ devpriv->ao_dma_desc[buffer_index].transfer_size = cpu_to_le32(nbytes);
/* set end of chain bit so we catch underruns */
next_bits = le32_to_cpu(devpriv->ao_dma_desc[buffer_index].next);
next_bits |= PLX_END_OF_CHAIN_BIT;
@@ -2949,9 +2912,8 @@ static unsigned int load_ao_dma_buffer(struct comedi_device *dev,
devpriv->ao_dma_desc[prev_buffer_index].next = cpu_to_le32(next_bits);
devpriv->ao_dma_index = (buffer_index + 1) % AO_DMA_RING_COUNT;
- devpriv->ao_count -= num_bytes;
- return num_bytes;
+ return nbytes;
}
static void load_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
@@ -3016,11 +2978,14 @@ static void handle_ao_interrupt(struct comedi_device *dev,
}
if ((status & DAC_DONE_BIT)) {
- async->events |= COMEDI_CB_EOA;
- if (ao_stopped_by_error(dev, cmd))
+ if ((cmd->stop_src == TRIG_COUNT &&
+ async->scans_done >= cmd->stop_arg) ||
+ last_ao_dma_load_completed(dev))
+ async->events |= COMEDI_CB_EOA;
+ else
async->events |= COMEDI_CB_ERROR;
}
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
}
static irqreturn_t handle_interrupt(int irq, void *d)
@@ -3191,7 +3156,9 @@ static void set_dac_interval_regs(struct comedi_device *dev,
static int prep_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
{
struct pcidas64_private *devpriv = dev->private;
- unsigned int num_bytes;
+ struct comedi_subdevice *s = dev->write_subdev;
+ unsigned int nsamples;
+ unsigned int nbytes;
int i;
/* clear queue pointer too, since external queue has
@@ -3199,22 +3166,23 @@ static int prep_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG);
writew(0, devpriv->main_iobase + DAC_BUFFER_CLEAR_REG);
- num_bytes = (DAC_FIFO_SIZE / 2) * bytes_in_sample;
- if (cmd->stop_src == TRIG_COUNT &&
- num_bytes / bytes_in_sample > devpriv->ao_count)
- num_bytes = devpriv->ao_count * bytes_in_sample;
- num_bytes = cfc_read_array_from_buffer(dev->write_subdev,
- devpriv->ao_bounce_buffer,
- num_bytes);
- for (i = 0; i < num_bytes / bytes_in_sample; i++) {
+ nsamples = cb_pcidas64_ao_fill_buffer(dev, s,
+ devpriv->ao_bounce_buffer,
+ DAC_FIFO_SIZE);
+ if (nsamples == 0)
+ return -1;
+
+ for (i = 0; i < nsamples; i++) {
writew(devpriv->ao_bounce_buffer[i],
devpriv->main_iobase + DAC_FIFO_REG);
}
- devpriv->ao_count -= num_bytes / bytes_in_sample;
- if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count == 0)
+
+ if (cmd->stop_src == TRIG_COUNT &&
+ s->async->scans_done >= cmd->stop_arg)
return 0;
- num_bytes = load_ao_dma_buffer(dev, cmd);
- if (num_bytes == 0)
+
+ nbytes = load_ao_dma_buffer(dev, cmd);
+ if (nbytes == 0)
return -1;
load_ao_dma(dev, cmd);
@@ -3275,7 +3243,6 @@ static int ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
writew(0x0, devpriv->main_iobase + DAC_CONTROL0_REG);
devpriv->ao_dma_index = 0;
- devpriv->ao_count = cmd->stop_arg * cmd->chanlist_len;
set_dac_select_reg(dev, cmd);
set_dac_interval_regs(dev, cmd);
@@ -3580,9 +3547,6 @@ static void caldac_write(struct comedi_device *dev, unsigned int channel,
unsigned int value)
{
const struct pcidas64_board *thisboard = dev->board_ptr;
- struct pcidas64_private *devpriv = dev->private;
-
- devpriv->caldac_state[channel] = value;
switch (thisboard->layout) {
case LAYOUT_60XX:
@@ -3597,33 +3561,27 @@ static void caldac_write(struct comedi_device *dev, unsigned int channel,
}
}
-static int calib_write_insn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int cb_pcidas64_calib_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct pcidas64_private *devpriv = dev->private;
- int channel = CR_CHAN(insn->chanspec);
-
- /* return immediately if setting hasn't changed, since
- * programming these things is slow */
- if (devpriv->caldac_state[channel] == data[0])
- return 1;
-
- caldac_write(dev, channel, data[0]);
-
- return 1;
-}
+ unsigned int chan = CR_CHAN(insn->chanspec);
-static int calib_read_insn(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data)
-{
- struct pcidas64_private *devpriv = dev->private;
- unsigned int channel = CR_CHAN(insn->chanspec);
+ /*
+ * Programming the calib device is slow. Only write the
+ * last data value if the value has changed.
+ */
+ if (insn->n) {
+ unsigned int val = data[insn->n - 1];
- data[0] = devpriv->caldac_state[channel];
+ if (s->readback[chan] != val) {
+ caldac_write(dev, chan, val);
+ s->readback[chan] = val;
+ }
+ }
- return 1;
+ return insn->n;
}
static void ad8402_write(struct comedi_device *dev, unsigned int channel,
@@ -3635,8 +3593,6 @@ static void ad8402_write(struct comedi_device *dev, unsigned int channel,
unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff);
static const int ad8402_udelay = 1;
- devpriv->ad8402_state[channel] = value;
-
register_bits = SELECT_8402_64XX_BIT;
udelay(ad8402_udelay);
writew(register_bits, devpriv->main_iobase + CALIBRATION_REG);
@@ -3658,35 +3614,27 @@ static void ad8402_write(struct comedi_device *dev, unsigned int channel,
}
/* for pci-das6402/16, channel 0 is analog input gain and channel 1 is offset */
-static int ad8402_write_insn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int cb_pcidas64_ad8402_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct pcidas64_private *devpriv = dev->private;
- int channel = CR_CHAN(insn->chanspec);
-
- /* return immediately if setting hasn't changed, since
- * programming these things is slow */
- if (devpriv->ad8402_state[channel] == data[0])
- return 1;
-
- devpriv->ad8402_state[channel] = data[0];
-
- ad8402_write(dev, channel, data[0]);
-
- return 1;
-}
+ unsigned int chan = CR_CHAN(insn->chanspec);
-static int ad8402_read_insn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- struct pcidas64_private *devpriv = dev->private;
- unsigned int channel = CR_CHAN(insn->chanspec);
+ /*
+ * Programming the calib device is slow. Only write the
+ * last data value if the value has changed.
+ */
+ if (insn->n) {
+ unsigned int val = data[insn->n - 1];
- data[0] = devpriv->ad8402_state[channel];
+ if (s->readback[chan] != val) {
+ ad8402_write(dev, chan, val);
+ s->readback[chan] = val;
+ }
+ }
- return 1;
+ return insn->n;
}
static uint16_t read_eeprom(struct comedi_device *dev, uint8_t address)
@@ -3816,7 +3764,6 @@ static int setup_subdevices(struct comedi_device *dev)
s->maxdata = (1 << thisboard->ao_bits) - 1;
s->range_table = thisboard->ao_range_table;
s->insn_write = ao_winsn;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
@@ -3849,7 +3796,7 @@ static int setup_subdevices(struct comedi_device *dev)
if (thisboard->layout == LAYOUT_64XX) {
s = &dev->subdevices[3];
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 4;
s->maxdata = 1;
s->range_table = &range_digital;
@@ -3895,10 +3842,16 @@ static int setup_subdevices(struct comedi_device *dev)
s->maxdata = 0xfff;
else
s->maxdata = 0xff;
- s->insn_read = calib_read_insn;
- s->insn_write = calib_write_insn;
- for (i = 0; i < s->n_chan; i++)
+ s->insn_write = cb_pcidas64_calib_insn_write;
+
+ ret = comedi_alloc_subdev_readback(s);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < s->n_chan; i++) {
caldac_write(dev, i, s->maxdata / 2);
+ s->readback[i] = s->maxdata / 2;
+ }
/* 2 channel ad8402 potentiometer */
s = &dev->subdevices[7];
@@ -3906,11 +3859,17 @@ static int setup_subdevices(struct comedi_device *dev)
s->type = COMEDI_SUBD_CALIB;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
s->n_chan = 2;
- s->insn_read = ad8402_read_insn;
- s->insn_write = ad8402_write_insn;
s->maxdata = 0xff;
- for (i = 0; i < s->n_chan; i++)
+ s->insn_write = cb_pcidas64_ad8402_insn_write;
+
+ ret = comedi_alloc_subdev_readback(s);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < s->n_chan; i++) {
ad8402_write(dev, i, s->maxdata / 2);
+ s->readback[i] = s->maxdata / 2;
+ }
} else
s->type = COMEDI_SUBD_UNUSED;
diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
index fe4d2544f3dc..70dd2c9eecdb 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
@@ -1,40 +1,45 @@
/*
- comedi/drivers/cb_pcimdas.c
- Comedi driver for Computer Boards PCIM-DAS1602/16
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 2000 David A. Schleef <ds@schleef.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-*/
+ * comedi/drivers/cb_pcimdas.c
+ * Comedi driver for Computer Boards PCIM-DAS1602/16 and PCIe-DAS1602/16
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
/*
-Driver: cb_pcimdas
-Description: Measurement Computing PCI Migration series boards
-Devices: [ComputerBoards] PCIM-DAS1602/16 (cb_pcimdas)
-Author: Richard Bytheway
-Updated: Wed, 13 Nov 2002 12:34:56 +0000
-Status: experimental
-
-Written to support the PCIM-DAS1602/16 on a 2.4 series kernel.
-
-Configuration Options:
- [0] - PCI bus number
- [1] - PCI slot number
-
-Developed from cb_pcidas and skel by Richard Bytheway (mocelet@sucs.org).
-Only supports DIO, AO and simple AI in it's present form.
-No interrupts, multi channel or FIFO AI,
-although the card looks like it could support this.
-See http://www.mccdaq.com/PDFs/Manuals/pcim-das1602-16.pdf for more details.
-*/
+ * Driver: cb_pcimdas
+ * Description: Measurement Computing PCI Migration series boards
+ * Devices: [ComputerBoards] PCIM-DAS1602/16 (cb_pcimdas), PCIe-DAS1602/16
+ * Author: Richard Bytheway
+ * Updated: Mon, 13 Oct 2014 11:57:39 +0000
+ * Status: experimental
+ *
+ * Written to support the PCIM-DAS1602/16 and PCIe-DAS1602/16.
+ *
+ * Configuration Options:
+ * none
+ *
+ * Manual configuration of PCI(e) cards is not supported; they are configured
+ * automatically.
+ *
+ * Developed from cb_pcidas and skel by Richard Bytheway (mocelet@sucs.org).
+ * Only supports DIO, AO and simple AI in it's present form.
+ * No interrupts, multi channel or FIFO AI,
+ * although the card looks like it could support this.
+ *
+ * http://www.mccdaq.com/PDFs/Manuals/pcim-das1602-16.pdf
+ * http://www.mccdaq.com/PDFs/Manuals/pcie-das1602-16.pdf
+ */
#include <linux/module.h>
#include <linux/pci.h>
@@ -45,7 +50,7 @@ See http://www.mccdaq.com/PDFs/Manuals/pcim-das1602-16.pdf for more details.
#include "plx9052.h"
#include "8255.h"
-/* Registers for the PCIM-DAS1602/16 */
+/* Registers for the PCIM-DAS1602/16 and PCIe-DAS1602/16 */
/* DAC Offsets */
#define ADC_TRIG 0
@@ -221,7 +226,6 @@ static int cb_pcimdas_auto_attach(struct comedi_device *dev,
/* ranges are hardware settable, but not software readable. */
s->range_table = &range_unknown;
s->insn_write = cb_pcimdas_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
@@ -251,7 +255,8 @@ static int cb_pcimdas_pci_probe(struct pci_dev *dev,
}
static const struct pci_device_id cb_pcimdas_pci_table[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0056) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0056) }, /* PCIM-DAS1602/16 */
+ { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0115) }, /* PCIe-DAS1602/16 */
{ 0 }
};
MODULE_DEVICE_TABLE(pci, cb_pcimdas_pci_table);
@@ -265,5 +270,5 @@ static struct pci_driver cb_pcimdas_pci_driver = {
module_comedi_pci_driver(cb_pcimdas_driver, cb_pcimdas_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for PCIM-DAS1602/16 and PCIe-DAS1602/16");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c
index 8450c99af8b0..85b2f4ab1ba4 100644
--- a/drivers/staging/comedi/drivers/comedi_bond.c
+++ b/drivers/staging/comedi/drivers/comedi_bond.c
@@ -61,8 +61,7 @@ struct bonded_device {
};
struct comedi_bond_private {
-# define MAX_BOARD_NAME 256
- char name[MAX_BOARD_NAME];
+ char name[256];
struct bonded_device **devs;
unsigned ndevs;
unsigned nchans;
@@ -262,12 +261,10 @@ static int do_dev_config(struct comedi_device *dev, struct comedi_devconfig *it)
{
/* Append dev:subdev to devpriv->name */
char buf[20];
- int left =
- MAX_BOARD_NAME - strlen(devpriv->name) - 1;
snprintf(buf, sizeof(buf), "%u:%u ",
bdev->minor, bdev->subdev);
- buf[sizeof(buf) - 1] = 0;
- strncat(devpriv->name, buf, left);
+ strlcat(devpriv->name, buf,
+ sizeof(devpriv->name));
}
}
diff --git a/drivers/staging/comedi/drivers/comedi_fc.h b/drivers/staging/comedi/drivers/comedi_fc.h
index ce2835972507..756be931c1a4 100644
--- a/drivers/staging/comedi/drivers/comedi_fc.h
+++ b/drivers/staging/comedi/drivers/comedi_fc.h
@@ -23,49 +23,6 @@
#include "../comedidev.h"
-static inline unsigned int cfc_bytes_per_scan(struct comedi_subdevice *s)
-{
- return comedi_bytes_per_scan(s);
-}
-
-static inline void cfc_inc_scan_progress(struct comedi_subdevice *s,
- unsigned int num_bytes)
-{
- comedi_inc_scan_progress(s, num_bytes);
-}
-
-static inline unsigned int cfc_write_array_to_buffer(struct comedi_subdevice *s,
- const void *data,
- unsigned int num_bytes)
-{
- return comedi_write_array_to_buffer(s, data, num_bytes);
-}
-
-static inline unsigned int cfc_write_to_buffer(struct comedi_subdevice *s,
- unsigned short data)
-{
- return comedi_write_array_to_buffer(s, &data, sizeof(data));
-};
-
-static inline unsigned int cfc_write_long_to_buffer(struct comedi_subdevice *s,
- unsigned int data)
-{
- return comedi_write_array_to_buffer(s, &data, sizeof(data));
-};
-
-static inline unsigned int
-cfc_read_array_from_buffer(struct comedi_subdevice *s, void *data,
- unsigned int num_bytes)
-{
- return comedi_read_array_from_buffer(s, data, num_bytes);
-}
-
-static inline unsigned int cfc_handle_events(struct comedi_device *dev,
- struct comedi_subdevice *s)
-{
- return comedi_handle_events(dev, s);
-}
-
/**
* cfc_check_trigger_src() - trivially validate a comedi_cmd trigger source
* @src: pointer to the trigger source to validate
diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c
index bf002988192d..3bac903c8627 100644
--- a/drivers/staging/comedi/drivers/comedi_parport.c
+++ b/drivers/staging/comedi/drivers/comedi_parport.c
@@ -225,10 +225,9 @@ static irqreturn_t parport_interrupt(int irq, void *d)
if (!(ctrl & PARPORT_CTRL_IRQ_ENA))
return IRQ_NONE;
- comedi_buf_put(s, 0);
- s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
+ comedi_buf_write_samples(s, &s->state, 1);
+ comedi_handle_events(dev, s);
- comedi_event(dev, s);
return IRQ_HANDLED;
}
diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
index 00c03df72523..e56525a1c8f3 100644
--- a/drivers/staging/comedi/drivers/comedi_test.c
+++ b/drivers/staging/comedi/drivers/comedi_test.c
@@ -52,18 +52,23 @@ zero volts).
#include "comedi_fc.h"
#include <linux/timer.h>
+#include <linux/ktime.h>
#define N_CHANS 8
+enum waveform_state_bits {
+ WAVEFORM_AI_RUNNING = 0
+};
+
/* Data unique to this driver */
struct waveform_private {
struct timer_list timer;
- struct timeval last; /* time last timer interrupt occurred */
+ ktime_t 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 (mod waveform period) */
unsigned long usec_remainder; /* usec since last scan */
- unsigned long ai_count; /* number of conversions remaining */
+ unsigned long state_bits;
unsigned int scan_period; /* scan period in usec */
unsigned int convert_period; /* conversion period in usec */
unsigned int ao_loopbacks[N_CHANS];
@@ -164,36 +169,29 @@ static void waveform_ai_interrupt(unsigned long arg)
{
struct comedi_device *dev = (struct comedi_device *)arg;
struct waveform_private *devpriv = dev->private;
- struct comedi_async *async = dev->read_subdev->async;
+ struct comedi_subdevice *s = dev->read_subdev;
+ struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
unsigned int i, j;
/* all times in microsec */
unsigned long elapsed_time;
unsigned int num_scans;
- struct timeval now;
- bool stopping = false;
+ ktime_t now;
+
+ /* check command is still active */
+ if (!test_bit(WAVEFORM_AI_RUNNING, &devpriv->state_bits))
+ return;
- do_gettimeofday(&now);
+ now = ktime_get();
- elapsed_time =
- 1000000 * (now.tv_sec - devpriv->last.tv_sec) + now.tv_usec -
- devpriv->last.tv_usec;
+ elapsed_time = ktime_to_us(ktime_sub(now, devpriv->last));
devpriv->last = now;
num_scans =
(devpriv->usec_remainder + elapsed_time) / devpriv->scan_period;
devpriv->usec_remainder =
(devpriv->usec_remainder + elapsed_time) % devpriv->scan_period;
- 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;
- }
- }
-
+ num_scans = comedi_nscans_left(s, num_scans);
for (i = 0; i < num_scans; i++) {
for (j = 0; j < cmd->chanlist_len; j++) {
unsigned short sample;
@@ -203,20 +201,19 @@ static void waveform_ai_interrupt(unsigned long arg)
devpriv->usec_current +
i * devpriv->scan_period +
j * devpriv->convert_period);
- cfc_write_to_buffer(dev->read_subdev, sample);
+ comedi_buf_write_samples(s, &sample, 1);
}
}
- devpriv->ai_count += i;
devpriv->usec_current += elapsed_time;
devpriv->usec_current %= devpriv->usec_period;
- if (stopping)
+ if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
async->events |= COMEDI_CB_EOA;
else
mod_timer(&devpriv->timer, jiffies + 1);
- comedi_event(dev, dev->read_subdev);
+ comedi_handle_events(dev, s);
}
static int waveform_ai_cmdtest(struct comedi_device *dev,
@@ -308,7 +305,6 @@ static int waveform_ai_cmd(struct comedi_device *dev,
return -1;
}
- devpriv->ai_count = 0;
devpriv->scan_period = cmd->scan_begin_arg / nano_per_micro;
if (cmd->convert_src == TRIG_NOW)
@@ -316,11 +312,16 @@ static int waveform_ai_cmd(struct comedi_device *dev,
else /* TRIG_TIMER */
devpriv->convert_period = cmd->convert_arg / nano_per_micro;
- do_gettimeofday(&devpriv->last);
- devpriv->usec_current = devpriv->last.tv_usec % devpriv->usec_period;
+ devpriv->last = ktime_get();
+ devpriv->usec_current =
+ ((u32)ktime_to_us(devpriv->last)) % devpriv->usec_period;
devpriv->usec_remainder = 0;
devpriv->timer.expires = jiffies + 1;
+ /* mark command as active */
+ smp_mb__before_atomic();
+ set_bit(WAVEFORM_AI_RUNNING, &devpriv->state_bits);
+ smp_mb__after_atomic();
add_timer(&devpriv->timer);
return 0;
}
@@ -330,7 +331,11 @@ static int waveform_ai_cancel(struct comedi_device *dev,
{
struct waveform_private *devpriv = dev->private;
- del_timer_sync(&devpriv->timer);
+ /* mark command as no longer active */
+ clear_bit(WAVEFORM_AI_RUNNING, &devpriv->state_bits);
+ smp_mb__after_atomic();
+ /* cannot call del_timer_sync() as may be called from timer routine */
+ del_timer(&devpriv->timer);
return 0;
}
@@ -405,7 +410,7 @@ static int waveform_attach(struct comedi_device *dev,
dev->write_subdev = s;
/* analog output subdevice (loopback) */
s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE | SDF_GROUND;
+ s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
s->n_chan = N_CHANS;
s->maxdata = 0xffff;
s->range_table = &waveform_ai_ranges;
@@ -432,7 +437,7 @@ static void waveform_detach(struct comedi_device *dev)
struct waveform_private *devpriv = dev->private;
if (devpriv)
- waveform_ai_cancel(dev, dev->read_subdev);
+ del_timer_sync(&devpriv->timer);
}
static struct comedi_driver waveform_driver = {
diff --git a/drivers/staging/comedi/drivers/dac02.c b/drivers/staging/comedi/drivers/dac02.c
index 34cbe83f0ce7..beb36c8dd00a 100644
--- a/drivers/staging/comedi/drivers/dac02.c
+++ b/drivers/staging/comedi/drivers/dac02.c
@@ -129,7 +129,6 @@ static int dac02_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->maxdata = 0x0fff;
s->range_table = &das02_ao_ranges;
s->insn_write = dac02_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
index e5b5a8133b34..96697fbb5239 100644
--- a/drivers/staging/comedi/drivers/daqboard2000.c
+++ b/drivers/staging/comedi/drivers/daqboard2000.c
@@ -707,7 +707,6 @@ static int daqboard2000_auto_attach(struct comedi_device *dev,
s->n_chan = 2;
s->maxdata = 0xffff;
s->insn_write = daqboard2000_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
s->range_table = &range_bipolar10;
result = comedi_alloc_subdev_readback(s);
diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
index bdb671a66e22..20a9f0eb72b5 100644
--- a/drivers/staging/comedi/drivers/das08.c
+++ b/drivers/staging/comedi/drivers/das08.c
@@ -474,7 +474,6 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
s->maxdata = (1 << thisboard->ao_nbits) - 1;
s->range_table = &range_bipolar5;
s->insn_write = das08_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
@@ -507,7 +506,7 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
/* do */
if (thisboard->do_nchan) {
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = thisboard->do_nchan;
s->maxdata = 1;
s->range_table = &range_digital;
diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
index 2d8e86cec47a..2436057304a3 100644
--- a/drivers/staging/comedi/drivers/das16.c
+++ b/drivers/staging/comedi/drivers/das16.c
@@ -541,6 +541,7 @@ static void das16_interrupt(struct comedi_device *dev)
struct comedi_cmd *cmd = &async->cmd;
unsigned long spin_flags;
unsigned long dma_flags;
+ unsigned int nsamples;
int num_bytes, residue;
int buffer_index;
@@ -583,21 +584,25 @@ static void das16_interrupt(struct comedi_device *dev)
spin_unlock_irqrestore(&dev->spinlock, spin_flags);
- cfc_write_array_to_buffer(s,
- devpriv->dma_buffer[buffer_index], num_bytes);
+ nsamples = comedi_bytes_to_samples(s, num_bytes);
+ comedi_buf_write_samples(s, devpriv->dma_buffer[buffer_index],
+ nsamples);
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
}
static void das16_timer_interrupt(unsigned long arg)
{
struct comedi_device *dev = (struct comedi_device *)arg;
struct das16_private_struct *devpriv = dev->private;
+ unsigned long flags;
das16_interrupt(dev);
+ spin_lock_irqsave(&dev->spinlock, flags);
if (devpriv->timer_running)
mod_timer(&devpriv->timer, jiffies + timer_period());
+ spin_unlock_irqrestore(&dev->spinlock, flags);
}
static int das16_ai_check_chanlist(struct comedi_device *dev,
@@ -764,7 +769,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
return -1;
}
- devpriv->adc_byte_count = cmd->stop_arg * cfc_bytes_per_scan(s);
+ devpriv->adc_byte_count = cmd->stop_arg * comedi_bytes_per_scan(s);
if (devpriv->can_burst)
outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV_REG);
@@ -814,7 +819,8 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
enable_dma(devpriv->dma_chan);
release_dma_lock(flags);
- /* set up interrupt */
+ /* set up timer */
+ spin_lock_irqsave(&dev->spinlock, flags);
devpriv->timer_running = 1;
devpriv->timer.expires = jiffies + timer_period();
add_timer(&devpriv->timer);
@@ -823,6 +829,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
if (devpriv->can_burst)
outb(0, dev->iobase + DAS1600_CONV_REG);
+ spin_unlock_irqrestore(&dev->spinlock, flags);
return 0;
}
@@ -856,8 +863,9 @@ static void das16_ai_munge(struct comedi_device *dev,
unsigned int num_bytes,
unsigned int start_chan_index)
{
- unsigned int i, num_samples = num_bytes / sizeof(short);
unsigned short *data = array;
+ unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes);
+ unsigned int i;
for (i = 0; i < num_samples; i++) {
data[i] = le16_to_cpu(data[i]);
@@ -1167,7 +1175,6 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->maxdata = 0x0fff;
s->range_table = devpriv->user_ao_range_table;
s->insn_write = das16_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
@@ -1226,6 +1233,8 @@ static void das16_detach(struct comedi_device *dev)
int i;
if (devpriv) {
+ if (devpriv->timer.data)
+ del_timer_sync(&devpriv->timer);
if (dev->iobase)
das16_reset(dev);
diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
index 24b63c452f51..80f41b7e8273 100644
--- a/drivers/staging/comedi/drivers/das16m1.c
+++ b/drivers/staging/comedi/drivers/das16m1.c
@@ -442,8 +442,7 @@ static void das16m1_handler(struct comedi_device *dev, unsigned int status)
num_samples = FIFO_SIZE;
insw(dev->iobase, devpriv->ai_buffer, num_samples);
munge_sample_array(devpriv->ai_buffer, num_samples);
- cfc_write_array_to_buffer(s, devpriv->ai_buffer,
- num_samples * sizeof(short));
+ comedi_buf_write_samples(s, devpriv->ai_buffer, num_samples);
devpriv->adc_count += num_samples;
if (cmd->stop_src == TRIG_COUNT) {
@@ -460,7 +459,7 @@ static void das16m1_handler(struct comedi_device *dev, unsigned int status)
dev_err(dev->class_dev, "fifo overflow\n");
}
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
}
static int das16m1_poll(struct comedi_device *dev, struct comedi_subdevice *s)
@@ -598,7 +597,7 @@ static int das16m1_attach(struct comedi_device *dev,
s = &dev->subdevices[2];
/* do */
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 4;
s->maxdata = 1;
s->range_table = &range_digital;
diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
index a53d87ce9b14..be825d21a185 100644
--- a/drivers/staging/comedi/drivers/das1800.c
+++ b/drivers/staging/comedi/drivers/das1800.c
@@ -421,7 +421,6 @@ static const struct das1800_board das1800_boards[] = {
};
struct das1800_private {
- unsigned int count; /* number of data points left to be taken */
unsigned int divisor1; /* value to load into board's counter 1 for timed conversions */
unsigned int divisor2; /* value to load into board's counter 2 for timed conversions */
int irq_dma_bits; /* bits for control register b */
@@ -479,42 +478,33 @@ static void das1800_handle_fifo_half_full(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct das1800_private *devpriv = dev->private;
- int numPoints = 0; /* number of points to read */
- struct comedi_cmd *cmd = &s->async->cmd;
+ unsigned int nsamples = comedi_nsamples_left(s, FIFO_SIZE / 2);
- numPoints = FIFO_SIZE / 2;
- /* if we only need some of the points */
- if (cmd->stop_src == TRIG_COUNT && devpriv->count < numPoints)
- numPoints = devpriv->count;
- insw(dev->iobase + DAS1800_FIFO, devpriv->ai_buf0, numPoints);
- munge_data(dev, devpriv->ai_buf0, numPoints);
- cfc_write_array_to_buffer(s, devpriv->ai_buf0,
- numPoints * sizeof(devpriv->ai_buf0[0]));
- if (cmd->stop_src == TRIG_COUNT)
- devpriv->count -= numPoints;
+ insw(dev->iobase + DAS1800_FIFO, devpriv->ai_buf0, nsamples);
+ munge_data(dev, devpriv->ai_buf0, nsamples);
+ comedi_buf_write_samples(s, devpriv->ai_buf0, nsamples);
}
static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- struct das1800_private *devpriv = dev->private;
+ struct comedi_cmd *cmd = &s->async->cmd;
unsigned short dpnt;
int unipolar;
- struct comedi_cmd *cmd = &s->async->cmd;
unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
while (inb(dev->iobase + DAS1800_STATUS) & FNE) {
- if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0)
- break;
dpnt = inw(dev->iobase + DAS1800_FIFO);
/* convert to unsigned type if we are in a bipolar mode */
if (!unipolar)
;
dpnt = munge_bipolar_sample(dev, dpnt);
- cfc_write_to_buffer(s, dpnt);
- if (cmd->stop_src == TRIG_COUNT)
- devpriv->count--;
+ comedi_buf_write_samples(s, &dpnt, 1);
+
+ if (cmd->stop_src == TRIG_COUNT &&
+ s->async->scans_done >= cmd->stop_arg)
+ break;
}
}
@@ -525,8 +515,8 @@ static void das1800_flush_dma_channel(struct comedi_device *dev,
unsigned int channel, uint16_t *buffer)
{
struct das1800_private *devpriv = dev->private;
- unsigned int num_bytes, num_samples;
- struct comedi_cmd *cmd = &s->async->cmd;
+ unsigned int nbytes;
+ unsigned int nsamples;
disable_dma(channel);
@@ -535,17 +525,12 @@ static void das1800_flush_dma_channel(struct comedi_device *dev,
clear_dma_ff(channel);
/* figure out how many points to read */
- num_bytes = devpriv->dma_transfer_size - get_dma_residue(channel);
- num_samples = num_bytes / sizeof(short);
-
- /* if we only need some of the points */
- if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_samples)
- num_samples = devpriv->count;
+ nbytes = devpriv->dma_transfer_size - get_dma_residue(channel);
+ nsamples = comedi_bytes_to_samples(s, nbytes);
+ nsamples = comedi_nsamples_left(s, nsamples);
- munge_data(dev, buffer, num_samples);
- cfc_write_array_to_buffer(s, buffer, num_bytes);
- if (cmd->stop_src == TRIG_COUNT)
- devpriv->count -= num_samples;
+ munge_data(dev, buffer, nsamples);
+ comedi_buf_write_samples(s, buffer, nsamples);
}
/* flushes remaining data from board when external trigger has stopped acquisition
@@ -649,14 +634,13 @@ static void das1800_ai_handler(struct comedi_device *dev)
das1800_handle_fifo_not_empty(dev, s);
}
- async->events |= COMEDI_CB_BLOCK;
/* if the card's fifo has overflowed */
if (status & OVF) {
/* clear OVF interrupt bit */
outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
dev_err(dev->class_dev, "FIFO overflow\n");
async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return;
}
/* stop taking data if appropriate */
@@ -670,11 +654,12 @@ static void das1800_ai_handler(struct comedi_device *dev)
else
das1800_handle_fifo_not_empty(dev, s);
async->events |= COMEDI_CB_EOA;
- } else if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) { /* stop_src TRIG_COUNT */
+ } else if (cmd->stop_src == TRIG_COUNT &&
+ async->scans_done >= cmd->stop_arg) {
async->events |= COMEDI_CB_EOA;
}
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
}
static int das1800_ai_poll(struct comedi_device *dev,
@@ -1102,9 +1087,6 @@ static int das1800_ai_do_cmd(struct comedi_device *dev,
/* interrupt fifo half full */
devpriv->irq_dma_bits |= FIMD;
}
- /* determine how many conversions we need */
- if (cmd->stop_src == TRIG_COUNT)
- devpriv->count = cmd->stop_arg * cmd->chanlist_len;
das1800_cancel(dev, s);
@@ -1515,7 +1497,7 @@ static int das1800_attach(struct comedi_device *dev,
/* do */
s = &dev->subdevices[3];
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = thisboard->do_n_chan;
s->maxdata = 1;
s->range_table = &range_digital;
diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
index ab6e40608885..780f4f646ea0 100644
--- a/drivers/staging/comedi/drivers/das6402.c
+++ b/drivers/staging/comedi/drivers/das6402.c
@@ -35,6 +35,7 @@
#include <linux/interrupt.h>
#include "../comedidev.h"
+#include "comedi_fc.h"
#include "8253.h"
/*
@@ -192,26 +193,197 @@ static void das6402_enable_counter(struct comedi_device *dev, bool load)
}
}
+static unsigned int das6402_ai_read_sample(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ unsigned int val;
+
+ val = inw(dev->iobase + DAS6402_AI_DATA_REG);
+ if (s->maxdata == 0x0fff)
+ val >>= 4;
+ return val;
+}
+
static irqreturn_t das6402_interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
+ struct comedi_subdevice *s = dev->read_subdev;
+ struct comedi_async *async = s->async;
+ struct comedi_cmd *cmd = &async->cmd;
+ unsigned int status;
+
+ status = inb(dev->iobase + DAS6402_STATUS_REG);
+ if ((status & DAS6402_STATUS_INT) == 0)
+ return IRQ_NONE;
+
+ if (status & DAS6402_STATUS_FFULL) {
+ async->events |= COMEDI_CB_OVERFLOW;
+ } else if (status & DAS6402_STATUS_FFNE) {
+ unsigned int val;
+
+ val = das6402_ai_read_sample(dev, s);
+ comedi_buf_write_samples(s, &val, 1);
+
+ if (cmd->stop_src == TRIG_COUNT &&
+ async->scans_done >= cmd->stop_arg)
+ async->events |= COMEDI_CB_EOA;
+ }
das6402_clear_all_interrupts(dev);
+ comedi_handle_events(dev, s);
+
return IRQ_HANDLED;
}
+static void das6402_ai_set_mode(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned int chanspec,
+ unsigned int mode)
+{
+ unsigned int range = CR_RANGE(chanspec);
+ unsigned int aref = CR_AREF(chanspec);
+
+ mode |= DAS6402_MODE_RANGE(range);
+ if (aref == AREF_GROUND)
+ mode |= DAS6402_MODE_SE;
+ if (comedi_range_is_unipolar(s, range))
+ mode |= DAS6402_MODE_UNI;
+
+ das6402_set_mode(dev, mode);
+}
+
static int das6402_ai_cmd(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- return -EINVAL;
+ struct das6402_private *devpriv = dev->private;
+ struct comedi_cmd *cmd = &s->async->cmd;
+ unsigned int chan_lo = CR_CHAN(cmd->chanlist[0]);
+ unsigned int chan_hi = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]);
+
+ das6402_ai_set_mode(dev, s, cmd->chanlist[0], DAS6402_MODE_FIFONEPTY);
+
+ /* load the mux for chanlist conversion */
+ outw(DAS6402_AI_MUX_HI(chan_hi) | DAS6402_AI_MUX_LO(chan_lo),
+ dev->iobase + DAS6402_AI_MUX_REG);
+
+ das6402_enable_counter(dev, true);
+
+ /* enable interrupt and pacer trigger */
+ outb(DAS6402_CTRL_INTE |
+ DAS6402_CTRL_IRQ(devpriv->irq) |
+ DAS6402_CTRL_PACER_TRIG, dev->iobase + DAS6402_CTRL_REG);
+
+ return 0;
+}
+
+static int das6402_ai_check_chanlist(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_cmd *cmd)
+{
+ unsigned int chan0 = CR_CHAN(cmd->chanlist[0]);
+ unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
+ unsigned int aref0 = CR_AREF(cmd->chanlist[0]);
+ int i;
+
+ for (i = 1; i < cmd->chanlist_len; i++) {
+ unsigned int chan = CR_CHAN(cmd->chanlist[i]);
+ unsigned int range = CR_RANGE(cmd->chanlist[i]);
+ unsigned int aref = CR_AREF(cmd->chanlist[i]);
+
+ if (chan != chan0 + i) {
+ dev_dbg(dev->class_dev,
+ "chanlist must be consecutive\n");
+ return -EINVAL;
+ }
+
+ if (range != range0) {
+ dev_dbg(dev->class_dev,
+ "chanlist must have the same range\n");
+ return -EINVAL;
+ }
+
+ if (aref != aref0) {
+ dev_dbg(dev->class_dev,
+ "chanlist must have the same reference\n");
+ return -EINVAL;
+ }
+
+ if (aref0 == AREF_DIFF && chan > (s->n_chan / 2)) {
+ dev_dbg(dev->class_dev,
+ "chanlist differential channel to large\n");
+ return -EINVAL;
+ }
+ }
+ return 0;
}
static int das6402_ai_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{
- return -EINVAL;
+ struct das6402_private *devpriv = dev->private;
+ int err = 0;
+ unsigned int arg;
+
+ /* Step 1 : check if triggers are trivially valid */
+
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+
+ if (err)
+ return 1;
+
+ /* Step 2a : make sure trigger sources are unique */
+
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
+
+ if (err)
+ return 2;
+
+ /* Step 3: check if arguments are trivially valid */
+
+ err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+ err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+ err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 10000);
+ err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
+ err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+ if (cmd->stop_src == TRIG_COUNT)
+ err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+ else /* TRIG_NONE */
+ err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+
+ if (err)
+ return 3;
+
+ /* step 4: fix up any arguments */
+
+ if (cmd->convert_src == TRIG_TIMER) {
+ arg = cmd->convert_arg;
+ i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+ &devpriv->divider1,
+ &devpriv->divider2,
+ &arg, cmd->flags);
+ err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
+ }
+
+ if (err)
+ return 4;
+
+ /* Step 5: check channel list if it exists */
+ if (cmd->chanlist && cmd->chanlist_len > 0)
+ err |= das6402_ai_check_chanlist(dev, s, cmd);
+
+ if (err)
+ return 5;
+
+ return 0;
}
static int das6402_ai_cancel(struct comedi_device *dev,
@@ -246,26 +418,17 @@ static int das6402_ai_insn_read(struct comedi_device *dev,
unsigned int *data)
{
unsigned int chan = CR_CHAN(insn->chanspec);
- unsigned int range = CR_RANGE(insn->chanspec);
unsigned int aref = CR_AREF(insn->chanspec);
- unsigned int val;
int ret;
int i;
- val = DAS6402_MODE_RANGE(range) | DAS6402_MODE_POLLED;
- if (aref == AREF_DIFF) {
- if (chan > s->n_chan / 2)
- return -EINVAL;
- } else {
- val |= DAS6402_MODE_SE;
- }
- if (comedi_range_is_unipolar(s, range))
- val |= DAS6402_MODE_UNI;
+ if (aref == AREF_DIFF && chan > (s->n_chan / 2))
+ return -EINVAL;
/* enable software conversion trigger */
outb(DAS6402_CTRL_SOFT_TRIG, dev->iobase + DAS6402_CTRL_REG);
- das6402_set_mode(dev, val);
+ das6402_ai_set_mode(dev, s, insn->chanspec, DAS6402_MODE_POLLED);
/* load the mux for single channel conversion */
outw(DAS6402_AI_MUX_HI(chan) | DAS6402_AI_MUX_LO(chan),
@@ -279,12 +442,7 @@ static int das6402_ai_insn_read(struct comedi_device *dev,
if (ret)
break;
- val = inw(dev->iobase + DAS6402_AI_DATA_REG);
-
- if (s->maxdata == 0x0fff)
- val >>= 4;
-
- data[i] = val;
+ data[i] = das6402_ai_read_sample(dev, s);
}
das6402_ai_clear_eoc(dev);
@@ -497,7 +655,7 @@ static int das6402_attach(struct comedi_device *dev,
/* Analog Output subdevice */
s = &dev->subdevices[1];
s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 2;
s->maxdata = board->maxdata;
s->range_table = &das6402_ao_ranges;
@@ -520,7 +678,7 @@ static int das6402_attach(struct comedi_device *dev,
/* Digital Input subdevice */
s = &dev->subdevices[3];
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITEABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 8;
s->maxdata = 1;
s->range_table = &range_digital;
diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
index d75e5528258c..e5bdc2423445 100644
--- a/drivers/staging/comedi/drivers/das800.c
+++ b/drivers/staging/comedi/drivers/das800.c
@@ -219,7 +219,6 @@ static const struct das800_board das800_boards[] = {
};
struct das800_private {
- unsigned int count; /* number of data points left to be taken */
unsigned int divisor1; /* counter 1 value for timed conversions */
unsigned int divisor2; /* counter 2 value for timed conversions */
unsigned int do_bits; /* digital output bits */
@@ -286,9 +285,6 @@ static void das800_set_frequency(struct comedi_device *dev)
static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
{
- struct das800_private *devpriv = dev->private;
-
- devpriv->count = 0;
das800_disable(dev);
return 0;
}
@@ -399,7 +395,6 @@ static int das800_ai_do_cmd(struct comedi_device *dev,
struct comedi_subdevice *s)
{
const struct das800_board *thisboard = dev->board_ptr;
- struct das800_private *devpriv = dev->private;
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
unsigned int gain = CR_RANGE(cmd->chanlist[0]);
@@ -422,11 +417,6 @@ static int das800_ai_do_cmd(struct comedi_device *dev,
gain &= 0xf;
outb(gain, dev->iobase + DAS800_GAIN);
- if (cmd->stop_src == TRIG_COUNT)
- devpriv->count = cmd->stop_arg * cmd->chanlist_len;
- else /* TRIG_NONE */
- devpriv->count = 0;
-
/* enable auto channel scan, send interrupts on end of conversion
* and set clock source to internal or external
*/
@@ -509,25 +499,28 @@ static irqreturn_t das800_interrupt(int irq, void *d)
if (s->maxdata == 0x0fff)
val >>= 4; /* 12-bit sample */
- /* if there are more data points to collect */
- if (cmd->stop_src == TRIG_NONE || devpriv->count > 0) {
- /* write data point to buffer */
- cfc_write_to_buffer(s, val & s->maxdata);
- devpriv->count--;
+ val &= s->maxdata;
+ comedi_buf_write_samples(s, &val, 1);
+
+ if (cmd->stop_src == TRIG_COUNT &&
+ async->scans_done >= cmd->stop_arg) {
+ async->events |= COMEDI_CB_EOA;
+ break;
}
}
- async->events |= COMEDI_CB_BLOCK;
if (fifo_overflow) {
spin_unlock_irqrestore(&dev->spinlock, irq_flags);
async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return IRQ_HANDLED;
}
- if (cmd->stop_src == TRIG_NONE || devpriv->count > 0) {
- /* Re-enable card's interrupt.
- * We already have spinlock, so indirect addressing is safe */
+ if (!(async->events & COMEDI_CB_CANCEL_MASK)) {
+ /*
+ * Re-enable card's interrupt.
+ * We already have spinlock, so indirect addressing is safe
+ */
das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits,
CONTROL1);
spin_unlock_irqrestore(&dev->spinlock, irq_flags);
@@ -535,9 +528,8 @@ static irqreturn_t das800_interrupt(int irq, void *d)
/* otherwise, stop taking data */
spin_unlock_irqrestore(&dev->spinlock, irq_flags);
das800_disable(dev);
- async->events |= COMEDI_CB_EOA;
}
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return IRQ_HANDLED;
}
@@ -738,7 +730,7 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* Digital Output subdevice */
s = &dev->subdevices[2];
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 4;
s->maxdata = 1;
s->range_table = &range_digital;
diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
index 7215e09305cf..6df298a99cc6 100644
--- a/drivers/staging/comedi/drivers/dmm32at.c
+++ b/drivers/staging/comedi/drivers/dmm32at.c
@@ -1,125 +1,139 @@
/*
- comedi/drivers/dmm32at.c
- Diamond Systems mm32at code for a Comedi driver
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 2000 David A. Schleef <ds@schleef.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-*/
+ * dmm32at.c
+ * Diamond Systems Diamond-MM-32-AT Comedi driver
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
/*
-Driver: dmm32at
-Description: Diamond Systems mm32at driver.
-Devices:
-Author: Perry J. Piplani <perry.j.piplani@nasa.gov>
-Updated: Fri Jun 4 09:13:24 CDT 2004
-Status: experimental
-
-This driver is for the Diamond Systems MM-32-AT board
-http://www.diamondsystems.com/products/diamondmm32at It is being used
-on serveral projects inside NASA, without problems so far. For analog
-input commands, TRIG_EXT is not yet supported at all..
-
-Configuration Options:
- comedi_config /dev/comedi0 dmm32at baseaddr,irq
-*/
+ * Driver: dmm32at
+ * Description: Diamond Systems Diamond-MM-32-AT
+ * Devices: (Diamond Systems) Diamond-MM-32-AT [dmm32at]
+ * Author: Perry J. Piplani <perry.j.piplani@nasa.gov>
+ * Updated: Fri Jun 4 09:13:24 CDT 2004
+ * Status: experimental
+ *
+ * Configuration Options:
+ * comedi_config /dev/comedi0 dmm32at baseaddr,irq
+ *
+ * This driver is for the Diamond Systems MM-32-AT board
+ * http://www.diamondsystems.com/products/diamondmm32at
+ *
+ * It is being used on serveral projects inside NASA, without
+ * problems so far. For analog input commands, TRIG_EXT is not
+ * yet supported.
+ */
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include "../comedidev.h"
+#include "8255.h"
#include "comedi_fc.h"
/* Board register addresses */
-#define DMM32AT_CONV 0x00
-#define DMM32AT_AILSB 0x00
-#define DMM32AT_AUXDOUT 0x01
-#define DMM32AT_AIMSB 0x01
-#define DMM32AT_AILOW 0x02
-#define DMM32AT_AIHIGH 0x03
-
-#define DMM32AT_DACSTAT 0x04
-#define DMM32AT_DACLSB_REG 0x04
-#define DMM32AT_DACMSB_REG 0x05
-#define DMM32AT_DACMSB_CHAN(x) ((x) << 6)
-
-#define DMM32AT_FIFOCNTRL 0x07
-#define DMM32AT_FIFOSTAT 0x07
-
-#define DMM32AT_CNTRL 0x08
-#define DMM32AT_AISTAT 0x08
-
-#define DMM32AT_INTCLOCK 0x09
-
-#define DMM32AT_CNTRDIO 0x0a
-
-#define DMM32AT_AICONF 0x0b
-#define DMM32AT_AIRBACK 0x0b
+#define DMM32AT_AI_START_CONV_REG 0x00
+#define DMM32AT_AI_LSB_REG 0x00
+#define DMM32AT_AUX_DOUT_REG 0x01
+#define DMM32AT_AUX_DOUT2 (1 << 2) /* J3.42 - OUT2 (OUT2EN) */
+#define DMM32AT_AUX_DOUT1 (1 << 1) /* J3.43 */
+#define DMM32AT_AUX_DOUT0 (1 << 0) /* J3.44 - OUT0 (OUT0EN) */
+#define DMM32AT_AI_MSB_REG 0x01
+#define DMM32AT_AI_LO_CHAN_REG 0x02
+#define DMM32AT_AI_HI_CHAN_REG 0x03
+#define DMM32AT_AUX_DI_REG 0x04
+#define DMM32AT_AUX_DI_DACBUSY (1 << 7)
+#define DMM32AT_AUX_DI_CALBUSY (1 << 6)
+#define DMM32AT_AUX_DI3 (1 << 3) /* J3.45 - ADCLK (CLKSEL) */
+#define DMM32AT_AUX_DI2 (1 << 2) /* J3.46 - GATE12 (GT12EN) */
+#define DMM32AT_AUX_DI1 (1 << 1) /* J3.47 - GATE0 (GT0EN) */
+#define DMM32AT_AUX_DI0 (1 << 0) /* J3.48 - CLK0 (SRC0) */
+#define DMM32AT_AO_LSB_REG 0x04
+#define DMM32AT_AO_MSB_REG 0x05
+#define DMM32AT_AO_MSB_DACH(x) ((x) << 6)
+#define DMM32AT_FIFO_DEPTH_REG 0x06
+#define DMM32AT_FIFO_CTRL_REG 0x07
+#define DMM32AT_FIFO_CTRL_FIFOEN (1 << 3)
+#define DMM32AT_FIFO_CTRL_SCANEN (1 << 2)
+#define DMM32AT_FIFO_CTRL_FIFORST (1 << 1)
+#define DMM32AT_FIFO_STATUS_REG 0x07
+#define DMM32AT_FIFO_STATUS_EF (1 << 7)
+#define DMM32AT_FIFO_STATUS_HF (1 << 6)
+#define DMM32AT_FIFO_STATUS_FF (1 << 5)
+#define DMM32AT_FIFO_STATUS_OVF (1 << 4)
+#define DMM32AT_FIFO_STATUS_FIFOEN (1 << 3)
+#define DMM32AT_FIFO_STATUS_SCANEN (1 << 2)
+#define DMM32AT_FIFO_STATUS_PAGE_MASK (3 << 0)
+#define DMM32AT_CTRL_REG 0x08
+#define DMM32AT_CTRL_RESETA (1 << 5)
+#define DMM32AT_CTRL_RESETD (1 << 4)
+#define DMM32AT_CTRL_INTRST (1 << 3)
+#define DMM32AT_CTRL_PAGE_8254 (0 << 0)
+#define DMM32AT_CTRL_PAGE_8255 (1 << 0)
+#define DMM32AT_CTRL_PAGE_CALIB (3 << 0)
+#define DMM32AT_AI_STATUS_REG 0x08
+#define DMM32AT_AI_STATUS_STS (1 << 7)
+#define DMM32AT_AI_STATUS_SD1 (1 << 6)
+#define DMM32AT_AI_STATUS_SD0 (1 << 5)
+#define DMM32AT_AI_STATUS_ADCH_MASK (0x1f << 0)
+#define DMM32AT_INTCLK_REG 0x09
+#define DMM32AT_INTCLK_ADINT (1 << 7)
+#define DMM32AT_INTCLK_DINT (1 << 6)
+#define DMM32AT_INTCLK_TINT (1 << 5)
+#define DMM32AT_INTCLK_CLKEN (1 << 1) /* 1=see below 0=software */
+#define DMM32AT_INTCLK_CLKSEL (1 << 0) /* 1=OUT2 0=EXTCLK */
+#define DMM32AT_CTRDIO_CFG_REG 0x0a
+#define DMM32AT_CTRDIO_CFG_FREQ12 (1 << 7) /* CLK12 1=100KHz 0=10MHz */
+#define DMM32AT_CTRDIO_CFG_FREQ0 (1 << 6) /* CLK0 1=10KHz 0=10MHz */
+#define DMM32AT_CTRDIO_CFG_OUT2EN (1 << 5) /* J3.42 1=OUT2 is DOUT2 */
+#define DMM32AT_CTRDIO_CFG_OUT0EN (1 << 4) /* J3,44 1=OUT0 is DOUT0 */
+#define DMM32AT_CTRDIO_CFG_GT0EN (1 << 2) /* J3.47 1=DIN1 is GATE0 */
+#define DMM32AT_CTRDIO_CFG_SRC0 (1 << 1) /* CLK0 is 0=FREQ0 1=J3.48 */
+#define DMM32AT_CTRDIO_CFG_GT12EN (1 << 0) /* J3.46 1=DIN2 is GATE12 */
+#define DMM32AT_AI_CFG_REG 0x0b
+#define DMM32AT_AI_CFG_SCINT_20US (0 << 4)
+#define DMM32AT_AI_CFG_SCINT_15US (1 << 4)
+#define DMM32AT_AI_CFG_SCINT_10US (2 << 4)
+#define DMM32AT_AI_CFG_SCINT_5US (3 << 4)
+#define DMM32AT_AI_CFG_RANGE (1 << 3) /* 0=5V 1=10V */
+#define DMM32AT_AI_CFG_ADBU (1 << 2) /* 0=bipolar 1=unipolar */
+#define DMM32AT_AI_CFG_GAIN(x) ((x) << 0)
+#define DMM32AT_AI_READBACK_REG 0x0b
+#define DMM32AT_AI_READBACK_WAIT (1 << 7) /* DMM32AT_AI_STATUS_STS */
+#define DMM32AT_AI_READBACK_RANGE (1 << 3)
+#define DMM32AT_AI_READBACK_ADBU (1 << 2)
+#define DMM32AT_AI_READBACK_GAIN_MASK (3 << 0)
#define DMM32AT_CLK1 0x0d
#define DMM32AT_CLK2 0x0e
#define DMM32AT_CLKCT 0x0f
-#define DMM32AT_DIOA 0x0c
-#define DMM32AT_DIOB 0x0d
-#define DMM32AT_DIOC 0x0e
-#define DMM32AT_DIOCONF 0x0f
+#define DMM32AT_8255_IOBASE 0x0c /* Page 1 registers */
/* Board register values. */
-/* DMM32AT_DACSTAT 0x04 */
-#define DMM32AT_DACBUSY 0x80
-
-/* DMM32AT_FIFOCNTRL 0x07 */
-#define DMM32AT_FIFORESET 0x02
-#define DMM32AT_SCANENABLE 0x04
-
-/* DMM32AT_CNTRL 0x08 */
-#define DMM32AT_RESET 0x20
-#define DMM32AT_INTRESET 0x08
-#define DMM32AT_CLKACC 0x00
-#define DMM32AT_DIOACC 0x01
-
-/* DMM32AT_AISTAT 0x08 */
-#define DMM32AT_STATUS 0x80
-
-/* DMM32AT_INTCLOCK 0x09 */
-#define DMM32AT_ADINT 0x80
-#define DMM32AT_CLKSEL 0x03
-
-/* DMM32AT_CNTRDIO 0x0a */
-#define DMM32AT_FREQ12 0x80
-
-/* DMM32AT_AICONF 0x0b */
+/* DMM32AT_AI_CFG_REG 0x0b */
#define DMM32AT_RANGE_U10 0x0c
#define DMM32AT_RANGE_U5 0x0d
#define DMM32AT_RANGE_B10 0x08
#define DMM32AT_RANGE_B5 0x00
-#define DMM32AT_SCINT_20 0x00
-#define DMM32AT_SCINT_15 0x10
-#define DMM32AT_SCINT_10 0x20
-#define DMM32AT_SCINT_5 0x30
/* DMM32AT_CLKCT 0x0f */
#define DMM32AT_CLKCT1 0x56 /* mode3 counter 1 - write low byte only */
#define DMM32AT_CLKCT2 0xb6 /* mode3 counter 2 - write high and low byte */
-/* DMM32AT_DIOCONF 0x0f */
-#define DMM32AT_DIENABLE 0x80
-#define DMM32AT_DIRA 0x10
-#define DMM32AT_DIRB 0x02
-#define DMM32AT_DIRCL 0x01
-#define DMM32AT_DIRCH 0x08
-
/* board AI ranges in comedi structure */
static const struct comedi_lrange dmm32at_airanges = {
4, {
@@ -150,12 +164,36 @@ static const struct comedi_lrange dmm32at_aoranges = {
}
};
-struct dmm32at_private {
- int data;
- int ai_inuse;
- unsigned int ai_scans_left;
- unsigned char dio_config;
-};
+static void dmm32at_ai_set_chanspec(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned int chanspec, int nchan)
+{
+ unsigned int chan = CR_CHAN(chanspec);
+ unsigned int range = CR_RANGE(chanspec);
+ unsigned int last_chan = (chan + nchan - 1) % s->n_chan;
+
+ outb(DMM32AT_FIFO_CTRL_FIFORST, dev->iobase + DMM32AT_FIFO_CTRL_REG);
+
+ if (nchan > 1)
+ outb(DMM32AT_FIFO_CTRL_SCANEN,
+ dev->iobase + DMM32AT_FIFO_CTRL_REG);
+
+ outb(chan, dev->iobase + DMM32AT_AI_LO_CHAN_REG);
+ outb(last_chan, dev->iobase + DMM32AT_AI_HI_CHAN_REG);
+ outb(dmm32at_rangebits[range], dev->iobase + DMM32AT_AI_CFG_REG);
+}
+
+static unsigned int dmm32at_ai_get_sample(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ unsigned int val;
+
+ val = inb(dev->iobase + DMM32AT_AI_LSB_REG);
+ val |= (inb(dev->iobase + DMM32AT_AI_MSB_REG) << 8);
+
+ /* munge two's complement value to offset binary */
+ return comedi_offset_munge(s, val);
+}
static int dmm32at_ai_status(struct comedi_device *dev,
struct comedi_subdevice *s,
@@ -165,75 +203,39 @@ static int dmm32at_ai_status(struct comedi_device *dev,
unsigned char status;
status = inb(dev->iobase + context);
- if ((status & DMM32AT_STATUS) == 0)
+ if ((status & DMM32AT_AI_STATUS_STS) == 0)
return 0;
return -EBUSY;
}
-static int dmm32at_ai_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int dmm32at_ai_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- int n;
- unsigned int d;
- unsigned short msb, lsb;
- unsigned char chan;
- int range;
int ret;
+ int i;
- /* get the channel and range number */
-
- chan = CR_CHAN(insn->chanspec) & (s->n_chan - 1);
- range = CR_RANGE(insn->chanspec);
-
- /* zero scan and fifo control and reset fifo */
- outb(DMM32AT_FIFORESET, dev->iobase + DMM32AT_FIFOCNTRL);
-
- /* write the ai channel range regs */
- outb(chan, dev->iobase + DMM32AT_AILOW);
- outb(chan, dev->iobase + DMM32AT_AIHIGH);
- /* set the range bits */
- outb(dmm32at_rangebits[range], dev->iobase + DMM32AT_AICONF);
+ dmm32at_ai_set_chanspec(dev, s, insn->chanspec, 1);
/* wait for circuit to settle */
- ret = comedi_timeout(dev, s, insn, dmm32at_ai_status, DMM32AT_AIRBACK);
+ ret = comedi_timeout(dev, s, insn, dmm32at_ai_status,
+ DMM32AT_AI_READBACK_REG);
if (ret)
return ret;
- /* convert n samples */
- for (n = 0; n < insn->n; n++) {
- /* trigger conversion */
- outb(0xff, dev->iobase + DMM32AT_CONV);
+ for (i = 0; i < insn->n; i++) {
+ outb(0xff, dev->iobase + DMM32AT_AI_START_CONV_REG);
- /* wait for conversion to end */
ret = comedi_timeout(dev, s, insn, dmm32at_ai_status,
- DMM32AT_AISTAT);
+ DMM32AT_AI_STATUS_REG);
if (ret)
return ret;
- /* read data */
- lsb = inb(dev->iobase + DMM32AT_AILSB);
- msb = inb(dev->iobase + DMM32AT_AIMSB);
-
- /* invert sign bit to make range unsigned, this is an
- idiosyncrasy of the diamond board, it return
- conversions as a signed value, i.e. -32768 to
- 32767, flipping the bit and interpreting it as
- signed gives you a range of 0 to 65535 which is
- used by comedi */
- d = ((msb ^ 0x0080) << 8) + lsb;
-
- data[n] = d;
+ data[i] = dmm32at_ai_get_sample(dev, s);
}
- /* return the number of samples read/written */
- return n;
-}
-
-static int dmm32at_ns_to_timer(unsigned int *ns, unsigned int flags)
-{
- /* trivial timer */
- return *ns;
+ return insn->n;
}
static int dmm32at_ai_check_chanlist(struct comedi_device *dev,
@@ -273,10 +275,8 @@ static int dmm32at_ai_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_TIMER /*| TRIG_EXT */);
- err |= cfc_check_trigger_src(&cmd->convert_src,
- TRIG_TIMER /*| TRIG_EXT */);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
@@ -285,8 +285,6 @@ static int dmm32at_ai_cmdtest(struct comedi_device *dev,
/* Step 2a : make sure trigger sources are unique */
- err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
- err |= cfc_check_trigger_is_unique(cmd->convert_src);
err |= cfc_check_trigger_is_unique(cmd->stop_src);
/* Step 2b : and mutually compatible */
@@ -298,67 +296,32 @@ static int dmm32at_ai_cmdtest(struct comedi_device *dev,
err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-#define MAX_SCAN_SPEED 1000000 /* in nanoseconds */
-#define MIN_SCAN_SPEED 1000000000 /* in nanoseconds */
-
- if (cmd->scan_begin_src == TRIG_TIMER) {
- err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
- MAX_SCAN_SPEED);
- err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
- MIN_SCAN_SPEED);
- } else {
- /* external trigger */
- /* should be level/edge, hi/lo specification here */
- /* should specify multiple external triggers */
- err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9);
- }
+ err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, 1000000);
+ err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 1000000000);
- if (cmd->convert_src == TRIG_TIMER) {
- if (cmd->convert_arg >= 17500)
- cmd->convert_arg = 20000;
- else if (cmd->convert_arg >= 12500)
- cmd->convert_arg = 15000;
- else if (cmd->convert_arg >= 7500)
- cmd->convert_arg = 10000;
- else
- cmd->convert_arg = 5000;
- } else {
- /* external trigger */
- /* see above */
- err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 9);
- }
+ if (cmd->convert_arg >= 17500)
+ cmd->convert_arg = 20000;
+ else if (cmd->convert_arg >= 12500)
+ cmd->convert_arg = 15000;
+ else if (cmd->convert_arg >= 7500)
+ cmd->convert_arg = 10000;
+ else
+ cmd->convert_arg = 5000;
err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
- if (cmd->stop_src == TRIG_COUNT) {
- err |= cfc_check_trigger_arg_max(&cmd->stop_arg, 0xfffffff0);
+ if (cmd->stop_src == TRIG_COUNT)
err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
- } else {
- /* TRIG_NONE */
+ else /* TRIG_NONE */
err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
- }
if (err)
return 3;
- /* step 4: fix up any arguments */
+ /* Step 4: fix up any arguments */
- if (cmd->scan_begin_src == TRIG_TIMER) {
- arg = cmd->scan_begin_arg;
- dmm32at_ns_to_timer(&arg, cmd->flags);
- err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
- }
- if (cmd->convert_src == TRIG_TIMER) {
- arg = cmd->convert_arg;
- dmm32at_ns_to_timer(&arg, cmd->flags);
- err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
-
- if (cmd->scan_begin_src == TRIG_TIMER) {
- arg = cmd->convert_arg * cmd->scan_end_arg;
- err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
- arg);
- }
- }
+ arg = cmd->convert_arg * cmd->scan_end_arg;
+ err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, arg);
if (err)
return 4;
@@ -384,11 +347,11 @@ static void dmm32at_setaitimer(struct comedi_device *dev, unsigned int nansec)
hi2 = (both2 & 0xff00) >> 8;
lo2 = both2 & 0x00ff;
- /* set the counter frequency to 10mhz */
- outb(0, dev->iobase + DMM32AT_CNTRDIO);
+ /* set counter clocks to 10MHz, disable all aux dio */
+ outb(0, dev->iobase + DMM32AT_CTRDIO_CFG_REG);
/* get access to the clock regs */
- outb(DMM32AT_CLKACC, dev->iobase + DMM32AT_CNTRL);
+ outb(DMM32AT_CTRL_PAGE_8254, dev->iobase + DMM32AT_CTRL_REG);
/* write the counter 1 control word and low byte to counter */
outb(DMM32AT_CLKCT1, dev->iobase + DMM32AT_CLKCT);
@@ -400,65 +363,37 @@ static void dmm32at_setaitimer(struct comedi_device *dev, unsigned int nansec)
outb(hi2, dev->iobase + DMM32AT_CLK2);
/* enable the ai conversion interrupt and the clock to start scans */
- outb(DMM32AT_ADINT | DMM32AT_CLKSEL, dev->iobase + DMM32AT_INTCLOCK);
+ outb(DMM32AT_INTCLK_ADINT |
+ DMM32AT_INTCLK_CLKEN | DMM32AT_INTCLK_CLKSEL,
+ dev->iobase + DMM32AT_INTCLK_REG);
}
static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
- struct dmm32at_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
- int range;
- unsigned char chanlo, chanhi;
int ret;
- if (!cmd->chanlist)
- return -EINVAL;
-
- /* get the channel list and range */
- chanlo = CR_CHAN(cmd->chanlist[0]) & (s->n_chan - 1);
- chanhi = chanlo + cmd->chanlist_len - 1;
- if (chanhi >= s->n_chan)
- return -EINVAL;
- range = CR_RANGE(cmd->chanlist[0]);
-
- /* reset fifo */
- outb(DMM32AT_FIFORESET, dev->iobase + DMM32AT_FIFOCNTRL);
-
- /* set scan enable */
- outb(DMM32AT_SCANENABLE, dev->iobase + DMM32AT_FIFOCNTRL);
-
- /* write the ai channel range regs */
- outb(chanlo, dev->iobase + DMM32AT_AILOW);
- outb(chanhi, dev->iobase + DMM32AT_AIHIGH);
-
- /* set the range bits */
- outb(dmm32at_rangebits[range], dev->iobase + DMM32AT_AICONF);
+ dmm32at_ai_set_chanspec(dev, s, cmd->chanlist[0], cmd->chanlist_len);
/* reset the interrupt just in case */
- outb(DMM32AT_INTRESET, dev->iobase + DMM32AT_CNTRL);
-
- if (cmd->stop_src == TRIG_COUNT)
- devpriv->ai_scans_left = cmd->stop_arg;
- else { /* TRIG_NONE */
- devpriv->ai_scans_left = 0xffffffff; /* indicates TRIG_NONE to
- * isr */
- }
+ outb(DMM32AT_CTRL_INTRST, dev->iobase + DMM32AT_CTRL_REG);
/*
* wait for circuit to settle
* we don't have the 'insn' here but it's not needed
*/
- ret = comedi_timeout(dev, s, NULL, dmm32at_ai_status, DMM32AT_AIRBACK);
+ ret = comedi_timeout(dev, s, NULL, dmm32at_ai_status,
+ DMM32AT_AI_READBACK_REG);
if (ret)
return ret;
- if (devpriv->ai_scans_left > 1) {
+ if (cmd->stop_src == TRIG_NONE || cmd->stop_arg > 1) {
/* start the clock and enable the interrupts */
dmm32at_setaitimer(dev, cmd->scan_begin_arg);
} else {
/* start the interrups and initiate a single scan */
- outb(DMM32AT_ADINT, dev->iobase + DMM32AT_INTCLOCK);
- outb(0xff, dev->iobase + DMM32AT_CONV);
+ outb(DMM32AT_INTCLK_ADINT, dev->iobase + DMM32AT_INTCLK_REG);
+ outb(0xff, dev->iobase + DMM32AT_AI_START_CONV_REG);
}
return 0;
@@ -468,19 +403,16 @@ static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
static int dmm32at_ai_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- struct dmm32at_private *devpriv = dev->private;
-
- devpriv->ai_scans_left = 1;
+ /* disable further interrupts and clocks */
+ outb(0x0, dev->iobase + DMM32AT_INTCLK_REG);
return 0;
}
static irqreturn_t dmm32at_isr(int irq, void *d)
{
struct comedi_device *dev = d;
- struct dmm32at_private *devpriv = dev->private;
unsigned char intstat;
- unsigned int samp;
- unsigned short msb, lsb;
+ unsigned int val;
int i;
if (!dev->attached) {
@@ -488,38 +420,26 @@ static irqreturn_t dmm32at_isr(int irq, void *d)
return IRQ_HANDLED;
}
- intstat = inb(dev->iobase + DMM32AT_INTCLOCK);
+ intstat = inb(dev->iobase + DMM32AT_INTCLK_REG);
- if (intstat & DMM32AT_ADINT) {
+ if (intstat & DMM32AT_INTCLK_ADINT) {
struct comedi_subdevice *s = dev->read_subdev;
struct comedi_cmd *cmd = &s->async->cmd;
for (i = 0; i < cmd->chanlist_len; i++) {
- /* read data */
- lsb = inb(dev->iobase + DMM32AT_AILSB);
- msb = inb(dev->iobase + DMM32AT_AIMSB);
-
- /* invert sign bit to make range unsigned */
- samp = ((msb ^ 0x0080) << 8) + lsb;
- comedi_buf_put(s, samp);
+ val = dmm32at_ai_get_sample(dev, s);
+ comedi_buf_write_samples(s, &val, 1);
}
- if (devpriv->ai_scans_left != 0xffffffff) { /* TRIG_COUNT */
- devpriv->ai_scans_left--;
- if (devpriv->ai_scans_left == 0) {
- /* disable further interrupts and clocks */
- outb(0x0, dev->iobase + DMM32AT_INTCLOCK);
- /* set the buffer to be flushed with an EOF */
- s->async->events |= COMEDI_CB_EOA;
- }
+ if (cmd->stop_src == TRIG_COUNT &&
+ s->async->scans_done >= cmd->stop_arg)
+ s->async->events |= COMEDI_CB_EOA;
- }
- /* flush the buffer */
- comedi_event(dev, s);
+ comedi_handle_events(dev, s);
}
/* reset the interrupt */
- outb(DMM32AT_INTRESET, dev->iobase + DMM32AT_CNTRL);
+ outb(DMM32AT_CTRL_INTRST, dev->iobase + DMM32AT_CTRL_REG);
return IRQ_HANDLED;
}
@@ -530,8 +450,8 @@ static int dmm32at_ao_eoc(struct comedi_device *dev,
{
unsigned char status;
- status = inb(dev->iobase + DMM32AT_DACSTAT);
- if ((status & DMM32AT_DACBUSY) == 0)
+ status = inb(dev->iobase + DMM32AT_AUX_DI_REG);
+ if ((status & DMM32AT_AUX_DI_DACBUSY) == 0)
return 0;
return -EBUSY;
}
@@ -549,9 +469,9 @@ static int dmm32at_ao_insn_write(struct comedi_device *dev,
int ret;
/* write LSB then MSB + chan to load DAC */
- outb(val & 0xff, dev->iobase + DMM32AT_DACLSB_REG);
- outb((val >> 8) | DMM32AT_DACMSB_CHAN(chan),
- dev->iobase + DMM32AT_DACMSB_REG);
+ outb(val & 0xff, dev->iobase + DMM32AT_AO_LSB_REG);
+ outb((val >> 8) | DMM32AT_AO_MSB_DACH(chan),
+ dev->iobase + DMM32AT_AO_MSB_REG);
/* wait for circuit to settle */
ret = comedi_timeout(dev, s, insn, dmm32at_ao_eoc, 0);
@@ -559,7 +479,7 @@ static int dmm32at_ao_insn_write(struct comedi_device *dev,
return ret;
/* dummy read to update DAC */
- inb(dev->iobase + DMM32AT_DACMSB_REG);
+ inb(dev->iobase + DMM32AT_AO_MSB_REG);
s->readback[chan] = val;
}
@@ -567,136 +487,82 @@ static int dmm32at_ao_insn_write(struct comedi_device *dev,
return insn->n;
}
-static int dmm32at_dio_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct dmm32at_private *devpriv = dev->private;
- unsigned int mask;
- unsigned int val;
-
- mask = comedi_dio_update_state(s, data);
- if (mask) {
- /* get access to the DIO regs */
- outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL);
-
- /* if either part of dio is set for output */
- if (((devpriv->dio_config & DMM32AT_DIRCL) == 0) ||
- ((devpriv->dio_config & DMM32AT_DIRCH) == 0)) {
- val = (s->state & 0x00ff0000) >> 16;
- outb(val, dev->iobase + DMM32AT_DIOC);
- }
- if ((devpriv->dio_config & DMM32AT_DIRB) == 0) {
- val = (s->state & 0x0000ff00) >> 8;
- outb(val, dev->iobase + DMM32AT_DIOB);
- }
- if ((devpriv->dio_config & DMM32AT_DIRA) == 0) {
- val = (s->state & 0x000000ff);
- outb(val, dev->iobase + DMM32AT_DIOA);
- }
- }
-
- val = inb(dev->iobase + DMM32AT_DIOA);
- val |= inb(dev->iobase + DMM32AT_DIOB) << 8;
- val |= inb(dev->iobase + DMM32AT_DIOC) << 16;
- s->state = val;
-
- data[1] = val;
-
- return insn->n;
-}
-
-static int dmm32at_dio_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
+static int dmm32at_8255_io(struct comedi_device *dev,
+ int dir, int port, int data, unsigned long regbase)
{
- struct dmm32at_private *devpriv = dev->private;
- unsigned int chan = CR_CHAN(insn->chanspec);
- unsigned int mask;
- unsigned char chanbit;
- int ret;
-
- if (chan < 8) {
- mask = 0x0000ff;
- chanbit = DMM32AT_DIRA;
- } else if (chan < 16) {
- mask = 0x00ff00;
- chanbit = DMM32AT_DIRB;
- } else if (chan < 20) {
- mask = 0x0f0000;
- chanbit = DMM32AT_DIRCL;
- } else {
- mask = 0xf00000;
- chanbit = DMM32AT_DIRCH;
- }
-
- ret = comedi_dio_insn_config(dev, s, insn, data, mask);
- if (ret)
- return ret;
-
- if (data[0] == INSN_CONFIG_DIO_OUTPUT)
- devpriv->dio_config &= ~chanbit;
- else
- devpriv->dio_config |= chanbit;
/* get access to the DIO regs */
- outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL);
- /* set the DIO's to the new configuration setting */
- outb(devpriv->dio_config, dev->iobase + DMM32AT_DIOCONF);
+ outb(DMM32AT_CTRL_PAGE_8255, dev->iobase + DMM32AT_CTRL_REG);
- return insn->n;
+ if (dir) {
+ outb(data, dev->iobase + regbase + port);
+ return 0;
+ }
+ return inb(dev->iobase + regbase + port);
}
-static int dmm32at_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+/* Make sure the board is there and put it to a known state */
+static int dmm32at_reset(struct comedi_device *dev)
{
- struct dmm32at_private *devpriv;
- int ret;
- struct comedi_subdevice *s;
unsigned char aihi, ailo, fifostat, aistat, intstat, airback;
- ret = comedi_request_region(dev, it->options[0], 0x10);
- if (ret)
- return ret;
-
- /* the following just makes sure the board is there and gets
- it to a known state */
-
/* reset the board */
- outb(DMM32AT_RESET, dev->iobase + DMM32AT_CNTRL);
+ outb(DMM32AT_CTRL_RESETA, dev->iobase + DMM32AT_CTRL_REG);
/* allow a millisecond to reset */
udelay(1000);
/* zero scan and fifo control */
- outb(0x0, dev->iobase + DMM32AT_FIFOCNTRL);
+ outb(0x0, dev->iobase + DMM32AT_FIFO_CTRL_REG);
/* zero interrupt and clock control */
- outb(0x0, dev->iobase + DMM32AT_INTCLOCK);
+ outb(0x0, dev->iobase + DMM32AT_INTCLK_REG);
/* write a test channel range, the high 3 bits should drop */
- outb(0x80, dev->iobase + DMM32AT_AILOW);
- outb(0xff, dev->iobase + DMM32AT_AIHIGH);
+ outb(0x80, dev->iobase + DMM32AT_AI_LO_CHAN_REG);
+ outb(0xff, dev->iobase + DMM32AT_AI_HI_CHAN_REG);
/* set the range at 10v unipolar */
- outb(DMM32AT_RANGE_U10, dev->iobase + DMM32AT_AICONF);
+ outb(DMM32AT_RANGE_U10, dev->iobase + DMM32AT_AI_CFG_REG);
/* should take 10 us to settle, here's a hundred */
udelay(100);
/* read back the values */
- ailo = inb(dev->iobase + DMM32AT_AILOW);
- aihi = inb(dev->iobase + DMM32AT_AIHIGH);
- fifostat = inb(dev->iobase + DMM32AT_FIFOSTAT);
- aistat = inb(dev->iobase + DMM32AT_AISTAT);
- intstat = inb(dev->iobase + DMM32AT_INTCLOCK);
- airback = inb(dev->iobase + DMM32AT_AIRBACK);
-
- if ((ailo != 0x00) || (aihi != 0x1f) || (fifostat != 0x80) ||
- (aistat != 0x60 || (intstat != 0x00) || airback != 0x0c)) {
- dev_err(dev->class_dev, "board detection failed\n");
+ ailo = inb(dev->iobase + DMM32AT_AI_LO_CHAN_REG);
+ aihi = inb(dev->iobase + DMM32AT_AI_HI_CHAN_REG);
+ fifostat = inb(dev->iobase + DMM32AT_FIFO_STATUS_REG);
+ aistat = inb(dev->iobase + DMM32AT_AI_STATUS_REG);
+ intstat = inb(dev->iobase + DMM32AT_INTCLK_REG);
+ airback = inb(dev->iobase + DMM32AT_AI_READBACK_REG);
+
+ /*
+ * NOTE: The (DMM32AT_AI_STATUS_SD1 | DMM32AT_AI_STATUS_SD0)
+ * test makes this driver only work if the board is configured
+ * with all A/D channels set for single-ended operation.
+ */
+ if (ailo != 0x00 || aihi != 0x1f ||
+ fifostat != DMM32AT_FIFO_STATUS_EF ||
+ aistat != (DMM32AT_AI_STATUS_SD1 | DMM32AT_AI_STATUS_SD0) ||
+ intstat != 0x00 || airback != 0x0c)
return -EIO;
+
+ return 0;
+}
+
+static int dmm32at_attach(struct comedi_device *dev,
+ struct comedi_devconfig *it)
+{
+ struct comedi_subdevice *s;
+ int ret;
+
+ ret = comedi_request_region(dev, it->options[0], 0x10);
+ if (ret)
+ return ret;
+
+ ret = dmm32at_reset(dev);
+ if (ret) {
+ dev_err(dev->class_dev, "board detection failed\n");
+ return ret;
}
if (it->options[1]) {
@@ -706,65 +572,45 @@ static int dmm32at_attach(struct comedi_device *dev,
dev->irq = it->options[1];
}
- devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
- if (!devpriv)
- return -ENOMEM;
-
ret = comedi_alloc_subdevices(dev, 3);
if (ret)
return ret;
+ /* Analog Input subdevice */
s = &dev->subdevices[0];
- /* analog input subdevice */
- s->type = COMEDI_SUBD_AI;
- /* we support single-ended (ground) and differential */
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
- s->n_chan = 32;
- s->maxdata = 0xffff;
- s->range_table = &dmm32at_airanges;
- s->insn_read = dmm32at_ai_rinsn;
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
+ s->n_chan = 32;
+ s->maxdata = 0xffff;
+ s->range_table = &dmm32at_airanges;
+ s->insn_read = dmm32at_ai_insn_read;
if (dev->irq) {
dev->read_subdev = s;
- s->subdev_flags |= SDF_CMD_READ;
- s->len_chanlist = 32;
- s->do_cmd = dmm32at_ai_cmd;
- s->do_cmdtest = dmm32at_ai_cmdtest;
- s->cancel = dmm32at_ai_cancel;
+ s->subdev_flags |= SDF_CMD_READ;
+ s->len_chanlist = s->n_chan;
+ s->do_cmd = dmm32at_ai_cmd;
+ s->do_cmdtest = dmm32at_ai_cmdtest;
+ s->cancel = dmm32at_ai_cancel;
}
+ /* Analog Output subdevice */
s = &dev->subdevices[1];
- /* analog output subdevice */
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE;
- s->n_chan = 4;
- s->maxdata = 0x0fff;
- s->range_table = &dmm32at_aoranges;
- s->insn_write = dmm32at_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = 4;
+ s->maxdata = 0x0fff;
+ s->range_table = &dmm32at_aoranges;
+ s->insn_write = dmm32at_ao_insn_write;
ret = comedi_alloc_subdev_readback(s);
if (ret)
return ret;
+ /* Digital I/O subdevice */
s = &dev->subdevices[2];
- /* digital i/o subdevice */
-
- /* get access to the DIO regs */
- outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL);
- /* set the DIO's to the defualt input setting */
- devpriv->dio_config = DMM32AT_DIRA | DMM32AT_DIRB |
- DMM32AT_DIRCL | DMM32AT_DIRCH | DMM32AT_DIENABLE;
- outb(devpriv->dio_config, dev->iobase + DMM32AT_DIOCONF);
-
- /* set up the subdevice */
- s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = 24;
- s->maxdata = 1;
- s->state = 0;
- s->range_table = &range_digital;
- s->insn_bits = dmm32at_dio_insn_bits;
- s->insn_config = dmm32at_dio_insn_config;
+ ret = subdev_8255_init(dev, s, dmm32at_8255_io, DMM32AT_8255_IOBASE);
+ if (ret)
+ return ret;
return 0;
}
@@ -778,5 +624,5 @@ static struct comedi_driver dmm32at_driver = {
module_comedi_driver(dmm32at_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi: Diamond Systems Diamond-MM-32-AT");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
index e97386343a0e..b96e60ffad73 100644
--- a/drivers/staging/comedi/drivers/dt2801.c
+++ b/drivers/staging/comedi/drivers/dt2801.c
@@ -597,7 +597,6 @@ havetype:
devpriv->dac_range_types[0] = dac_range_lkup(it->options[4]);
devpriv->dac_range_types[1] = dac_range_lkup(it->options[5]);
s->insn_write = dt2801_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
index 1736e397ad2c..d660f277487e 100644
--- a/drivers/staging/comedi/drivers/dt2811.c
+++ b/drivers/staging/comedi/drivers/dt2811.c
@@ -418,7 +418,6 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
devpriv->range_type_list[0] = dac_range_types[devpriv->dac_range[0]];
devpriv->range_type_list[1] = dac_range_types[devpriv->dac_range[1]];
s->insn_write = dt2811_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c
index 9216c35c414e..9805be13005a 100644
--- a/drivers/staging/comedi/drivers/dt2814.c
+++ b/drivers/staging/comedi/drivers/dt2814.c
@@ -230,7 +230,7 @@ static irqreturn_t dt2814_interrupt(int irq, void *d)
s->async->events |= COMEDI_CB_EOA;
}
- comedi_event(dev, s);
+ comedi_handle_events(dev, s);
return IRQ_HANDLED;
}
diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
index cc974a5e5cf6..2be98bb9a809 100644
--- a/drivers/staging/comedi/drivers/dt282x.c
+++ b/drivers/staging/comedi/drivers/dt282x.c
@@ -449,13 +449,29 @@ static void dt282x_munge(struct comedi_device *dev,
}
}
+static unsigned int dt282x_ao_setup_dma(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ int cur_dma)
+{
+ struct dt282x_private *devpriv = dev->private;
+ void *ptr = devpriv->dma[cur_dma].buf;
+ unsigned int nsamples = comedi_bytes_to_samples(s, devpriv->dma_maxsize);
+ unsigned int nbytes;
+
+ nbytes = comedi_buf_read_samples(s, ptr, nsamples);
+ if (nbytes)
+ dt282x_prep_ao_dma(dev, cur_dma, nbytes);
+ else
+ dev_err(dev->class_dev, "AO underrun\n");
+
+ return nbytes;
+}
+
static void dt282x_ao_dma_interrupt(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct dt282x_private *devpriv = dev->private;
int cur_dma = devpriv->current_dma_index;
- void *ptr = devpriv->dma[cur_dma].buf;
- int size;
outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE,
dev->iobase + DT2821_SUPCSR_REG);
@@ -464,13 +480,8 @@ static void dt282x_ao_dma_interrupt(struct comedi_device *dev,
devpriv->current_dma_index = 1 - cur_dma;
- size = cfc_read_array_from_buffer(s, ptr, devpriv->dma_maxsize);
- if (size == 0) {
- dev_err(dev->class_dev, "AO underrun\n");
+ if (!dt282x_ao_setup_dma(dev, s, cur_dma))
s->async->events |= COMEDI_CB_OVERFLOW;
- } else {
- dt282x_prep_ao_dma(dev, cur_dma, size);
- }
}
static void dt282x_ai_dma_interrupt(struct comedi_device *dev,
@@ -480,6 +491,7 @@ static void dt282x_ai_dma_interrupt(struct comedi_device *dev,
int cur_dma = devpriv->current_dma_index;
void *ptr = devpriv->dma[cur_dma].buf;
int size = devpriv->dma[cur_dma].size;
+ unsigned int nsamples = comedi_bytes_to_samples(s, size);
int ret;
outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE,
@@ -490,13 +502,11 @@ static void dt282x_ai_dma_interrupt(struct comedi_device *dev,
devpriv->current_dma_index = 1 - cur_dma;
dt282x_munge(dev, s, ptr, size);
- ret = cfc_write_array_to_buffer(s, ptr, size);
- if (ret != size) {
- s->async->events |= COMEDI_CB_OVERFLOW;
+ ret = comedi_buf_write_samples(s, ptr, nsamples);
+ if (ret != size)
return;
- }
- devpriv->nread -= size / 2;
+ devpriv->nread -= nsamples;
if (devpriv->nread < 0) {
dev_info(dev->class_dev, "nread off by one\n");
devpriv->nread = 0;
@@ -555,7 +565,6 @@ static irqreturn_t dt282x_interrupt(int irq, void *d)
}
#if 0
if (adcsr & DT2821_ADCSR_ADDONE) {
- int ret;
unsigned short data;
data = inw(dev->iobase + DT2821_ADDAT_REG);
@@ -563,10 +572,7 @@ static irqreturn_t dt282x_interrupt(int irq, void *d)
if (devpriv->ad_2scomp)
data = comedi_offset_munge(s, data);
- ret = comedi_buf_put(s, data);
-
- if (ret == 0)
- s->async->events |= COMEDI_CB_OVERFLOW;
+ comedi_buf_write_samples(s, &data, 1);
devpriv->nread--;
if (!devpriv->nread) {
@@ -579,8 +585,8 @@ static irqreturn_t dt282x_interrupt(int irq, void *d)
handled = 1;
}
#endif
- cfc_handle_events(dev, s);
- cfc_handle_events(dev, s_ao);
+ comedi_handle_events(dev, s);
+ comedi_handle_events(dev, s_ao);
return IRQ_RETVAL(handled);
}
@@ -916,26 +922,15 @@ static int dt282x_ao_inttrig(struct comedi_device *dev,
{
struct dt282x_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
- int size;
if (trig_num != cmd->start_src)
return -EINVAL;
- size = cfc_read_array_from_buffer(s, devpriv->dma[0].buf,
- devpriv->dma_maxsize);
- if (size == 0) {
- dev_err(dev->class_dev, "AO underrun\n");
+ if (!dt282x_ao_setup_dma(dev, s, 0))
return -EPIPE;
- }
- dt282x_prep_ao_dma(dev, 0, size);
- size = cfc_read_array_from_buffer(s, devpriv->dma[1].buf,
- devpriv->dma_maxsize);
- if (size == 0) {
- dev_err(dev->class_dev, "AO underrun\n");
+ if (!dt282x_ao_setup_dma(dev, s, 1))
return -EPIPE;
- }
- dt282x_prep_ao_dma(dev, 1, size);
outw(devpriv->supcsr | DT2821_SUPCSR_STRIG,
dev->iobase + DT2821_SUPCSR_REG);
@@ -1236,7 +1231,6 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* ranges are per-channel, set by jumpers on the board */
s->range_table = &dt282x_ao_range;
s->insn_write = dt282x_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
if (dev->irq) {
dev->write_subdev = s;
s->subdev_flags |= SDF_CMD_WRITE;
diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
index 825561046b6f..1d9a7a63e06f 100644
--- a/drivers/staging/comedi/drivers/dt3000.c
+++ b/drivers/staging/comedi/drivers/dt3000.c
@@ -315,7 +315,7 @@ static void dt3k_ai_empty_fifo(struct comedi_device *dev,
for (i = 0; i < count; i++) {
data = readw(dev->mmio + DPR_ADC_buffer + rear);
- comedi_buf_put(s, data);
+ comedi_buf_write_samples(s, &data, 1);
rear++;
if (rear >= AI_FIFO_DEPTH)
rear = 0;
@@ -351,10 +351,8 @@ static irqreturn_t dt3k_interrupt(int irq, void *d)
status = readw(dev->mmio + DPR_Intr_Flag);
- if (status & DT3000_ADFULL) {
+ if (status & DT3000_ADFULL)
dt3k_ai_empty_fifo(dev, s);
- s->async->events |= COMEDI_CB_BLOCK;
- }
if (status & (DT3000_ADSWERR | DT3000_ADHWERR))
s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
@@ -363,7 +361,7 @@ static irqreturn_t dt3k_interrupt(int irq, void *d)
if (debug_n_ints >= 10)
s->async->events |= COMEDI_CB_EOA;
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return IRQ_HANDLED;
}
@@ -699,7 +697,6 @@ static int dt3000_auto_attach(struct comedi_device *dev,
s->len_chanlist = 1;
s->range_table = &range_bipolar10;
s->insn_write = dt3k_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
index 77bb89fee327..06c601d8fdff 100644
--- a/drivers/staging/comedi/drivers/dt9812.c
+++ b/drivers/staging/comedi/drivers/dt9812.c
@@ -804,7 +804,7 @@ static int dt9812_auto_attach(struct comedi_device *dev,
/* Digital Output subdevice */
s = &dev->subdevices[1];
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITEABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 8;
s->maxdata = 1;
s->range_table = &range_digital;
@@ -822,7 +822,7 @@ static int dt9812_auto_attach(struct comedi_device *dev,
/* Analog Output subdevice */
s = &dev->subdevices[3];
s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 2;
s->maxdata = 0x0fff;
s->range_table = is_unipolar ? &range_unipolar2_5 : &range_bipolar10;
diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c
index 608aee0c3a15..1b6324c6eb29 100644
--- a/drivers/staging/comedi/drivers/dyna_pci10xx.c
+++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c
@@ -218,7 +218,7 @@ static int dyna_pci10xx_auto_attach(struct comedi_device *dev,
/* digital input */
s = &dev->subdevices[2];
s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND;
+ s->subdev_flags = SDF_READABLE;
s->n_chan = 16;
s->maxdata = 1;
s->range_table = &range_digital;
@@ -228,7 +228,7 @@ static int dyna_pci10xx_auto_attach(struct comedi_device *dev,
/* digital output */
s = &dev->subdevices[3];
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 16;
s->maxdata = 1;
s->range_table = &range_digital;
diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
index 5a1e3c8fc01c..e1f493241cd6 100644
--- a/drivers/staging/comedi/drivers/fl512.c
+++ b/drivers/staging/comedi/drivers/fl512.c
@@ -135,7 +135,6 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->maxdata = 0x0fff;
s->range_table = &range_fl512;
s->insn_write = fl512_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
index b8975a4606ea..0979f536ed39 100644
--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
+++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
@@ -196,8 +196,8 @@ static void gsc_hpdi_drain_dma(struct comedi_device *dev, unsigned int channel)
size = devpriv->dio_count;
devpriv->dio_count -= size;
}
- cfc_write_array_to_buffer(s, devpriv->desc_dio_buffer[idx],
- size * sizeof(uint32_t));
+ comedi_buf_write_samples(s, devpriv->desc_dio_buffer[idx],
+ size);
idx++;
idx %= devpriv->num_dma_descriptors;
start = le32_to_cpu(devpriv->dma_desc[idx].pci_start_addr);
@@ -272,7 +272,7 @@ static irqreturn_t gsc_hpdi_interrupt(int irq, void *d)
if (devpriv->dio_count == 0)
async->events |= COMEDI_CB_EOA;
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return IRQ_HANDLED;
}
@@ -689,7 +689,7 @@ static int gsc_hpdi_auto_attach(struct comedi_device *dev,
s = &dev->subdevices[0];
dev->read_subdev = s;
s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITEABLE | SDF_LSAMPL |
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL |
SDF_CMD_READ;
s->n_chan = 32;
s->len_chanlist = 32;
diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
index f4e1c1cf4178..1ea168620103 100644
--- a/drivers/staging/comedi/drivers/icp_multi.c
+++ b/drivers/staging/comedi/drivers/icp_multi.c
@@ -53,7 +53,7 @@ Configuration options: not applicable, uses PCI auto config
#define ICP_MULTI_AI 2 /* R: Analogue input data */
#define ICP_MULTI_DAC_CSR 4 /* R/W: DAC command/status register */
#define ICP_MULTI_AO 6 /* R/W: Analogue output data */
-#define ICP_MULTI_DI 8 /* R/W: Digital inouts */
+#define ICP_MULTI_DI 8 /* R/W: Digital inputs */
#define ICP_MULTI_DO 0x0A /* R/W: Digital outputs */
#define ICP_MULTI_INT_EN 0x0C /* R/W: Interrupt enable register */
#define ICP_MULTI_INT_STAT 0x0E /* R/W: Interrupt status register */
@@ -319,7 +319,7 @@ static int icp_multi_insn_bits_do(struct comedi_device *dev,
if (comedi_dio_update_state(s, data))
writew(s->state, dev->mmio + ICP_MULTI_DO);
- data[1] = readw(dev->mmio + ICP_MULTI_DI);
+ data[1] = s->state;
return insn->n;
}
@@ -495,7 +495,6 @@ static int icp_multi_auto_attach(struct comedi_device *dev,
s->len_chanlist = 4;
s->range_table = &range_analog;
s->insn_write = icp_multi_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
@@ -512,7 +511,7 @@ static int icp_multi_auto_attach(struct comedi_device *dev,
s = &dev->subdevices[3];
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 8;
s->maxdata = 1;
s->len_chanlist = 8;
@@ -521,7 +520,7 @@ static int icp_multi_auto_attach(struct comedi_device *dev,
s = &dev->subdevices[4];
s->type = COMEDI_SUBD_COUNTER;
- s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 4;
s->maxdata = 0xffff;
s->len_chanlist = 4;
diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
index cc5fd75b8bc0..1085d66935fe 100644
--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
+++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
@@ -392,7 +392,6 @@ static int ii20k_init_module(struct comedi_device *dev,
s->maxdata = 0xffff;
s->range_table = &ii20k_ao_ranges;
s->insn_write = ii20k_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
index 6561b00bea59..915685c1c85c 100644
--- a/drivers/staging/comedi/drivers/me4000.c
+++ b/drivers/staging/comedi/drivers/me4000.c
@@ -44,8 +44,6 @@ broken.
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
#include "../comedidev.h"
@@ -53,10 +51,7 @@ broken.
#include "8253.h"
#include "plx9052.h"
-#if 0
-/* file removed due to GPL incompatibility */
-#include "me4000_fw.h"
-#endif
+#define ME4000_FIRMWARE "me4000_firmware.bin"
/*
* ME4000 Register map and bit defines
@@ -333,27 +328,20 @@ static const struct comedi_lrange me4000_ai_range = {
}
};
-#define FIRMWARE_NOT_AVAILABLE 1
-#if FIRMWARE_NOT_AVAILABLE
-extern unsigned char *xilinx_firm;
-#endif
-
-static int xilinx_download(struct comedi_device *dev)
+static int me4000_xilinx_download(struct comedi_device *dev,
+ const u8 *data, size_t size,
+ unsigned long context)
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
struct me4000_info *info = dev->private;
unsigned long xilinx_iobase = pci_resource_start(pcidev, 5);
- u32 value = 0;
- wait_queue_head_t queue;
- int idx = 0;
- int size = 0;
- unsigned int intcsr;
+ unsigned int file_length;
+ unsigned int val;
+ unsigned int i;
if (!xilinx_iobase)
return -ENODEV;
- init_waitqueue_head(&queue);
-
/*
* Set PLX local interrupt 2 polarity to high.
* Interrupt is thrown by init pin of xilinx.
@@ -361,61 +349,58 @@ static int xilinx_download(struct comedi_device *dev)
outl(PLX9052_INTCSR_LI2POL, info->plx_regbase + PLX9052_INTCSR);
/* Set /CS and /WRITE of the Xilinx */
- value = inl(info->plx_regbase + PLX9052_CNTRL);
- value |= PLX9052_CNTRL_UIO2_DATA;
- outl(value, info->plx_regbase + PLX9052_CNTRL);
+ val = inl(info->plx_regbase + PLX9052_CNTRL);
+ val |= PLX9052_CNTRL_UIO2_DATA;
+ outl(val, info->plx_regbase + PLX9052_CNTRL);
/* Init Xilinx with CS1 */
inb(xilinx_iobase + 0xC8);
/* Wait until /INIT pin is set */
udelay(20);
- intcsr = inl(info->plx_regbase + PLX9052_INTCSR);
- if (!(intcsr & PLX9052_INTCSR_LI2STAT)) {
+ val = inl(info->plx_regbase + PLX9052_INTCSR);
+ if (!(val & PLX9052_INTCSR_LI2STAT)) {
dev_err(dev->class_dev, "Can't init Xilinx\n");
return -EIO;
}
/* Reset /CS and /WRITE of the Xilinx */
- value = inl(info->plx_regbase + PLX9052_CNTRL);
- value &= ~PLX9052_CNTRL_UIO2_DATA;
- outl(value, info->plx_regbase + PLX9052_CNTRL);
- if (FIRMWARE_NOT_AVAILABLE) {
- dev_err(dev->class_dev,
- "xilinx firmware unavailable due to licensing, aborting");
- return -EIO;
- } else {
- /* Download Xilinx firmware */
- size = (xilinx_firm[0] << 24) + (xilinx_firm[1] << 16) +
- (xilinx_firm[2] << 8) + xilinx_firm[3];
- udelay(10);
+ val = inl(info->plx_regbase + PLX9052_CNTRL);
+ val &= ~PLX9052_CNTRL_UIO2_DATA;
+ outl(val, info->plx_regbase + PLX9052_CNTRL);
- for (idx = 0; idx < size; idx++) {
- outb(xilinx_firm[16 + idx], xilinx_iobase);
- udelay(10);
+ /* Download Xilinx firmware */
+ file_length = (((unsigned int)data[0] & 0xff) << 24) +
+ (((unsigned int)data[1] & 0xff) << 16) +
+ (((unsigned int)data[2] & 0xff) << 8) +
+ ((unsigned int)data[3] & 0xff);
+ udelay(10);
- /* Check if BUSY flag is low */
- if (inl(info->plx_regbase + PLX9052_CNTRL) & PLX9052_CNTRL_UIO1_DATA) {
- dev_err(dev->class_dev,
- "Xilinx is still busy (idx = %d)\n",
- idx);
- return -EIO;
- }
+ for (i = 0; i < file_length; i++) {
+ outb(data[16 + i], xilinx_iobase);
+ udelay(10);
+
+ /* Check if BUSY flag is low */
+ val = inl(info->plx_regbase + PLX9052_CNTRL);
+ if (val & PLX9052_CNTRL_UIO1_DATA) {
+ dev_err(dev->class_dev,
+ "Xilinx is still busy (i = %d)\n", i);
+ return -EIO;
}
}
/* If done flag is high download was successful */
- if (inl(info->plx_regbase + PLX9052_CNTRL) & PLX9052_CNTRL_UIO0_DATA) {
- } else {
+ val = inl(info->plx_regbase + PLX9052_CNTRL);
+ if (!(val & PLX9052_CNTRL_UIO0_DATA)) {
dev_err(dev->class_dev, "DONE flag is not set\n");
dev_err(dev->class_dev, "Download not successful\n");
return -EIO;
}
/* Set /CS and /WRITE */
- value = inl(info->plx_regbase + PLX9052_CNTRL);
- value |= PLX9052_CNTRL_UIO2_DATA;
- outl(value, info->plx_regbase + PLX9052_CNTRL);
+ val = inl(info->plx_regbase + PLX9052_CNTRL);
+ val |= PLX9052_CNTRL_UIO2_DATA;
+ outl(val, info->plx_regbase + PLX9052_CNTRL);
return 0;
}
@@ -431,7 +416,7 @@ static void me4000_reset(struct comedi_device *dev)
val |= PLX9052_CNTRL_PCI_RESET;
outl(val, info->plx_regbase + PLX9052_CNTRL);
val &= ~PLX9052_CNTRL_PCI_RESET;
- outl(val , info->plx_regbase + PLX9052_CNTRL);
+ outl(val, info->plx_regbase + PLX9052_CNTRL);
/* 0x8000 to the DACs means an output voltage of 0V */
for (chan = 0; chan < 4; chan++)
@@ -848,9 +833,6 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
unsigned int scan_ticks;
int err = 0;
- /* Only rounding flags are implemented */
- cmd->flags &= CMDF_ROUND_NEAREST | CMDF_ROUND_UP | CMDF_ROUND_DOWN;
-
/* Round the timer arguments */
ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
@@ -1092,8 +1074,6 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
} else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
&& !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
&& (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
- s->async->events |= COMEDI_CB_BLOCK;
-
c = ME4000_AI_FIFO_COUNT / 2;
} else {
dev_err(dev->class_dev,
@@ -1119,7 +1099,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
lval ^= 0x8000;
- if (!comedi_buf_put(s, lval)) {
+ if (!comedi_buf_write_samples(s, &lval, 1)) {
/*
* Buffer overflow, so stop conversion
* and disable all interrupts
@@ -1128,11 +1108,6 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
ME4000_AI_CTRL_BIT_SC_IRQ);
outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
-
- s->async->events |= COMEDI_CB_OVERFLOW;
-
- dev_err(dev->class_dev, "Buffer overflow\n");
-
break;
}
}
@@ -1146,7 +1121,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
ME4000_IRQ_STATUS_BIT_SC) {
- s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA;
+ s->async->events |= COMEDI_CB_EOA;
/*
* Acquisition is complete, so stop
@@ -1164,11 +1139,8 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
lval ^= 0x8000;
- if (!comedi_buf_put(s, lval)) {
- dev_err(dev->class_dev, "Buffer overflow\n");
- s->async->events |= COMEDI_CB_OVERFLOW;
+ if (!comedi_buf_write_samples(s, &lval, 1))
break;
- }
}
/* Work is done, so reset the interrupt */
@@ -1178,8 +1150,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
}
- if (s->async->events)
- comedi_event(dev, s);
+ comedi_handle_events(dev, s);
return IRQ_HANDLED;
}
@@ -1397,8 +1368,9 @@ static int me4000_auto_attach(struct comedi_device *dev,
if (!info->plx_regbase || !dev->iobase || !info->timer_regbase)
return -ENODEV;
- result = xilinx_download(dev);
- if (result)
+ result = comedi_load_firmware(dev, &pcidev->dev, ME4000_FIRMWARE,
+ me4000_xilinx_download, 0);
+ if (result < 0)
return result;
me4000_reset(dev);
@@ -1449,12 +1421,11 @@ static int me4000_auto_attach(struct comedi_device *dev,
if (thisboard->ao_nchan) {
s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND;
+ s->subdev_flags = SDF_WRITABLE | SDF_COMMON | SDF_GROUND;
s->n_chan = thisboard->ao_nchan;
s->maxdata = 0xFFFF; /* 16 bit DAC */
s->range_table = &range_bipolar10;
s->insn_write = me4000_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
result = comedi_alloc_subdev_readback(s);
if (result)
@@ -1561,3 +1532,4 @@ module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(ME4000_FIRMWARE);
diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
index 00eaaf8ac148..b5278c11e622 100644
--- a/drivers/staging/comedi/drivers/me_daq.c
+++ b/drivers/staging/comedi/drivers/me_daq.c
@@ -511,13 +511,12 @@ static int me_auto_attach(struct comedi_device *dev,
s = &dev->subdevices[1];
if (board->has_ao) {
s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE | SDF_COMMON;
+ s->subdev_flags = SDF_WRITABLE | SDF_COMMON;
s->n_chan = 4;
s->maxdata = 0x0fff;
s->len_chanlist = 4;
s->range_table = &me_ao_range;
s->insn_write = me_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
@@ -528,7 +527,7 @@ static int me_auto_attach(struct comedi_device *dev,
s = &dev->subdevices[2];
s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITEABLE;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 32;
s->maxdata = 1;
s->len_chanlist = 32;
diff --git a/drivers/staging/comedi/drivers/mf6x4.c b/drivers/staging/comedi/drivers/mf6x4.c
index c8d3a22c5896..af21bc180c46 100644
--- a/drivers/staging/comedi/drivers/mf6x4.c
+++ b/drivers/staging/comedi/drivers/mf6x4.c
@@ -259,7 +259,6 @@ static int mf6x4_auto_attach(struct comedi_device *dev, unsigned long context)
s->maxdata = 0x3fff; /* 14 bits DAC */
s->range_table = &range_bipolar10;
s->insn_write = mf6x4_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c
index 4f7829010a99..ffc9e61d6cdd 100644
--- a/drivers/staging/comedi/drivers/mite.c
+++ b/drivers/staging/comedi/drivers/mite.c
@@ -494,13 +494,10 @@ EXPORT_SYMBOL_GPL(mite_bytes_read_from_memory_ub);
unsigned mite_dma_tcr(struct mite_channel *mite_chan)
{
struct mite_struct *mite = mite_chan->mite;
- int tcr;
int lkar;
lkar = readl(mite->mite_io_addr + MITE_LKAR(mite_chan->channel));
- tcr = readl(mite->mite_io_addr + MITE_TCR(mite_chan->channel));
-
- return tcr;
+ return readl(mite->mite_io_addr + MITE_TCR(mite_chan->channel));
}
EXPORT_SYMBOL_GPL(mite_dma_tcr);
@@ -542,7 +539,7 @@ int mite_sync_input_dma(struct mite_channel *mite_chan,
return 0;
comedi_buf_write_free(s, count);
- cfc_inc_scan_progress(s, count);
+ comedi_inc_scan_progress(s, count);
async->events |= COMEDI_CB_BLOCK;
return 0;
}
@@ -553,7 +550,7 @@ int mite_sync_output_dma(struct mite_channel *mite_chan,
{
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
- u32 stop_count = cmd->stop_arg * cfc_bytes_per_scan(s);
+ u32 stop_count = cmd->stop_arg * comedi_bytes_per_scan(s);
unsigned int old_alloc_count = async->buf_read_alloc_count;
u32 nbytes_ub, nbytes_lb;
int count;
diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c
index f710c8e81320..8471219210b6 100644
--- a/drivers/staging/comedi/drivers/multiq3.c
+++ b/drivers/staging/comedi/drivers/multiq3.c
@@ -238,7 +238,6 @@ static int multiq3_attach(struct comedi_device *dev,
s->maxdata = 0xfff;
s->range_table = &range_bipolar5;
s->insn_write = multiq3_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
index 45fb601e4080..f99847f3999f 100644
--- a/drivers/staging/comedi/drivers/ni_6527.c
+++ b/drivers/staging/comedi/drivers/ni_6527.c
@@ -208,9 +208,8 @@ static irqreturn_t ni6527_interrupt(int irq, void *d)
return IRQ_NONE;
if (status & NI6527_STATUS_EDGE) {
- comedi_buf_put(s, 0);
- s->async->events |= COMEDI_CB_EOS;
- comedi_event(dev, s);
+ comedi_buf_write_samples(s, &s->state, 1);
+ comedi_handle_events(dev, s);
}
writeb(NI6527_CLR_IRQS, dev->mmio + NI6527_CLR_REG);
@@ -238,9 +237,6 @@ static int ni6527_intr_cmdtest(struct comedi_device *dev,
/* Step 2a : make sure trigger sources are unique */
/* 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);
diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
index 3b642861eb36..bcb326e31562 100644
--- a/drivers/staging/comedi/drivers/ni_65xx.c
+++ b/drivers/staging/comedi/drivers/ni_65xx.c
@@ -508,9 +508,9 @@ static irqreturn_t ni_65xx_interrupt(int irq, void *d)
writeb(NI_65XX_CLR_EDGE_INT | NI_65XX_CLR_OVERFLOW_INT,
dev->mmio + NI_65XX_CLR_REG);
- comedi_buf_put(s, 0);
- s->async->events |= COMEDI_CB_EOS;
- comedi_event(dev, s);
+ comedi_buf_write_samples(s, &s->state, 1);
+ comedi_handle_events(dev, s);
+
return IRQ_HANDLED;
}
@@ -534,9 +534,6 @@ static int ni_65xx_intr_cmdtest(struct comedi_device *dev,
/* Step 2a : make sure trigger sources are unique */
/* 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);
diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
index 5b6794c8232e..1e4dd82b12ea 100644
--- a/drivers/staging/comedi/drivers/ni_660x.c
+++ b/drivers/staging/comedi/drivers/ni_660x.c
@@ -780,7 +780,7 @@ static void ni_660x_handle_gpct_interrupt(struct comedi_device *dev,
struct ni_gpct *counter = s->private;
ni_tio_handle_interrupt(counter, s);
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
}
static irqreturn_t ni_660x_interrupt(int irq, void *d)
diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
index 54721deb80cc..c42a81c0bfa1 100644
--- a/drivers/staging/comedi/drivers/ni_670x.c
+++ b/drivers/staging/comedi/drivers/ni_670x.c
@@ -228,7 +228,6 @@ static int ni_670x_auto_attach(struct comedi_device *dev,
s->range_table = &range_bipolar10;
}
s->insn_write = ni_670x_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
index 72ec857d073e..69e543a0bf22 100644
--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
+++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
@@ -168,7 +168,6 @@ static irqreturn_t a2150_interrupt(int irq, void *d)
struct comedi_cmd *cmd;
unsigned int max_points, num_points, residue, leftover;
unsigned short dpnt;
- static const int sample_size = sizeof(devpriv->dma_buffer[0]);
if (!dev->attached) {
dev_err(dev->class_dev, "premature interrupt\n");
@@ -188,14 +187,14 @@ static irqreturn_t a2150_interrupt(int irq, void *d)
if (status & OVFL_BIT) {
dev_err(dev->class_dev, "fifo overflow\n");
async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
}
if ((status & DMA_TC_BIT) == 0) {
dev_err(dev->class_dev,
"caught non-dma interrupt? Aborting.\n");
async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return IRQ_HANDLED;
}
@@ -206,12 +205,12 @@ static irqreturn_t a2150_interrupt(int irq, void *d)
clear_dma_ff(devpriv->dma);
/* figure out how many points to read */
- max_points = devpriv->dma_transfer_size / sample_size;
+ max_points = comedi_bytes_to_samples(s, devpriv->dma_transfer_size);
/* residue is the number of points left to be done on the dma
* transfer. It should always be zero at this point unless
* the stop_src is set to external triggering.
*/
- residue = get_dma_residue(devpriv->dma) / sample_size;
+ residue = comedi_bytes_to_samples(s, get_dma_residue(devpriv->dma));
num_points = max_points - residue;
if (devpriv->count < num_points && cmd->stop_src == TRIG_COUNT)
num_points = devpriv->count;
@@ -219,7 +218,8 @@ static irqreturn_t a2150_interrupt(int irq, void *d)
/* figure out how many points will be stored next time */
leftover = 0;
if (cmd->stop_src == TRIG_NONE) {
- leftover = devpriv->dma_transfer_size / sample_size;
+ leftover = comedi_bytes_to_samples(s,
+ devpriv->dma_transfer_size);
} else if (devpriv->count > max_points) {
leftover = devpriv->count - max_points;
if (leftover > max_points)
@@ -237,7 +237,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d)
dpnt = devpriv->dma_buffer[i];
/* convert from 2's complement to unsigned coding */
dpnt ^= 0x8000;
- cfc_write_to_buffer(s, dpnt);
+ comedi_buf_write_samples(s, &dpnt, 1);
if (cmd->stop_src == TRIG_COUNT) {
if (--devpriv->count == 0) { /* end of acquisition */
async->events |= COMEDI_CB_EOA;
@@ -248,14 +248,13 @@ static irqreturn_t a2150_interrupt(int irq, void *d)
/* re-enable dma */
if (leftover) {
set_dma_addr(devpriv->dma, virt_to_bus(devpriv->dma_buffer));
- set_dma_count(devpriv->dma, leftover * sample_size);
+ set_dma_count(devpriv->dma,
+ comedi_samples_to_bytes(s, leftover));
enable_dma(devpriv->dma);
}
release_dma_lock(flags);
- async->events |= COMEDI_CB_BLOCK;
-
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
/* clear interrupt */
outw(0x00, dev->iobase + DMA_TC_CLEAR_REG);
diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
index 3e1ce5866147..05370a4a74a5 100644
--- a/drivers/staging/comedi/drivers/ni_at_ao.c
+++ b/drivers/staging/comedi/drivers/ni_at_ao.c
@@ -244,47 +244,31 @@ static int atao_calib_insn_write(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- struct atao_private *devpriv = dev->private;
unsigned int chan = CR_CHAN(insn->chanspec);
- unsigned int bitstring;
- unsigned int val;
- int bit;
- if (insn->n == 0)
- return 0;
+ if (insn->n) {
+ unsigned int val = data[insn->n - 1];
+ unsigned int bitstring = ((chan & 0x7) << 8) | val;
+ unsigned int bits;
+ int bit;
- devpriv->caldac[chan] = data[insn->n - 1] & s->maxdata;
+ /* write the channel and last data value to the caldac */
+ /* clock the bitstring to the caldac; MSB -> LSB */
+ for (bit = 1 << 10; bit; bit >>= 1) {
+ bits = (bit & bitstring) ? ATAO_CFG2_SDATA : 0;
- /* write the channel and last data value to the caldac */
- bitstring = ((chan & 0x7) << 8) | devpriv->caldac[chan];
+ outw(bits, dev->iobase + ATAO_CFG2_REG);
+ outw(bits | ATAO_CFG2_SCLK,
+ dev->iobase + ATAO_CFG2_REG);
+ }
- /* clock the bitstring to the caldac; MSB -> LSB */
- for (bit = 1 << 10; bit; bit >>= 1) {
- val = (bit & bitstring) ? ATAO_CFG2_SDATA : 0;
+ /* strobe the caldac to load the value */
+ outw(ATAO_CFG2_CALLD(chan), dev->iobase + ATAO_CFG2_REG);
+ outw(ATAO_CFG2_CALLD_NOP, dev->iobase + ATAO_CFG2_REG);
- outw(val, dev->iobase + ATAO_CFG2_REG);
- outw(val | ATAO_CFG2_SCLK, dev->iobase + ATAO_CFG2_REG);
+ s->readback[chan] = val;
}
- /* strobe the caldac to load the value */
- outw(ATAO_CFG2_CALLD(chan), dev->iobase + ATAO_CFG2_REG);
- outw(ATAO_CFG2_CALLD_NOP, dev->iobase + ATAO_CFG2_REG);
-
- return insn->n;
-}
-
-static int atao_calib_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct atao_private *devpriv = dev->private;
- unsigned int chan = CR_CHAN(insn->chanspec);
- int i;
-
- for (i = 0; i < insn->n; i++)
- data[i] = devpriv->caldac[chan];
-
return insn->n;
}
@@ -344,7 +328,6 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->maxdata = 0x0fff;
s->range_table = it->options[3] ? &range_unipolar10 : &range_bipolar10;
s->insn_write = atao_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
@@ -366,9 +349,12 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL;
s->n_chan = (board->n_ao_chans * 2) + 1;
s->maxdata = 0xff;
- s->insn_read = atao_calib_insn_read;
s->insn_write = atao_calib_insn_write;
+ ret = comedi_alloc_subdev_readback(s);
+ if (ret)
+ return ret;
+
/* EEPROM subdevice */
s = &dev->subdevices[3];
s->type = COMEDI_SUBD_UNUSED;
diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
index fc3c19de7005..c484c89c94b5 100644
--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
+++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
@@ -217,10 +217,12 @@ static irqreturn_t atmio16d_interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
struct comedi_subdevice *s = dev->read_subdev;
+ unsigned short val;
- comedi_buf_put(s, inw(dev->iobase + AD_FIFO_REG));
+ val = inw(dev->iobase + AD_FIFO_REG);
+ comedi_buf_write_samples(s, &val, 1);
+ comedi_handle_events(dev, s);
- comedi_event(dev, s);
return IRQ_HANDLED;
}
@@ -298,7 +300,6 @@ static int atmio16d_ai_cmd(struct comedi_device *dev,
* It is still uber-experimental */
reset_counters(dev);
- s->async->cur_chan = 0;
/* check if scanning multiple channels */
if (cmd->chanlist_len < 2) {
@@ -691,7 +692,6 @@ static int atmio16d_attach(struct comedi_device *dev,
break;
}
s->insn_write = atmio16d_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h
index f6e5cd15a409..ac2c01f9dfdc 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.h
+++ b/drivers/staging/comedi/drivers/ni_labpc.h
@@ -37,8 +37,6 @@ struct labpc_boardinfo {
struct labpc_private {
/* number of data points left to be taken */
unsigned long long count;
- /* software copy of analog output values */
- unsigned int ao_value[NUM_AO_CHAN];
/* software copys of bits written to command registers */
unsigned int cmd1;
unsigned int cmd2;
@@ -70,10 +68,6 @@ struct labpc_private {
unsigned int dma_transfer_size;
/* we are using dma/fifo-half-full/etc. */
enum transfer_type current_transfer;
- /* stores contents of board's eeprom */
- unsigned int eeprom_data[EEPROM_SIZE];
- /* stores settings of calibration dacs */
- unsigned int caldac[16];
/*
* function pointers so we can use inb/outb or readb/writeb as
* appropriate
diff --git a/drivers/staging/comedi/drivers/ni_labpc_common.c b/drivers/staging/comedi/drivers/ni_labpc_common.c
index 35bc2c25ddfb..d89d5852aeea 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_common.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_common.c
@@ -818,7 +818,7 @@ static int labpc_drain_fifo(struct comedi_device *dev)
devpriv->count--;
}
data = labpc_read_adc_fifo(dev);
- cfc_write_to_buffer(dev->read_subdev, data);
+ comedi_buf_write_samples(dev->read_subdev, &data, 1);
devpriv->stat1 = devpriv->read_byte(dev, STAT1_REG);
}
if (i == timeout) {
@@ -876,7 +876,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d)
/* clear error interrupt */
devpriv->write_byte(dev, 0x1, ADC_FIFO_CLEAR_REG);
async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
dev_err(dev->class_dev, "overrun\n");
return IRQ_HANDLED;
}
@@ -896,7 +896,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d)
/* clear error interrupt */
devpriv->write_byte(dev, 0x1, ADC_FIFO_CLEAR_REG);
async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
dev_err(dev->class_dev, "overflow\n");
return IRQ_HANDLED;
}
@@ -914,10 +914,22 @@ static irqreturn_t labpc_interrupt(int irq, void *d)
async->events |= COMEDI_CB_EOA;
}
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return IRQ_HANDLED;
}
+static void labpc_ao_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned int chan, unsigned int val)
+{
+ struct labpc_private *devpriv = dev->private;
+
+ devpriv->write_byte(dev, val & 0xff, DAC_LSB_REG(chan));
+ devpriv->write_byte(dev, (val >> 8) & 0xff, DAC_MSB_REG(chan));
+
+ s->readback[chan] = val;
+}
+
static int labpc_ao_insn_write(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
@@ -927,7 +939,6 @@ static int labpc_ao_insn_write(struct comedi_device *dev,
struct labpc_private *devpriv = dev->private;
int channel, range;
unsigned long flags;
- int lsb, msb;
channel = CR_CHAN(insn->chanspec);
@@ -950,25 +961,7 @@ static int labpc_ao_insn_write(struct comedi_device *dev,
devpriv->write_byte(dev, devpriv->cmd6, CMD6_REG);
}
/* send data */
- lsb = data[0] & 0xff;
- msb = (data[0] >> 8) & 0xff;
- devpriv->write_byte(dev, lsb, DAC_LSB_REG(channel));
- devpriv->write_byte(dev, msb, DAC_MSB_REG(channel));
-
- /* remember value for readback */
- devpriv->ao_value[channel] = data[0];
-
- return 1;
-}
-
-static int labpc_ao_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct labpc_private *devpriv = dev->private;
-
- data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
+ labpc_ao_write(dev, s, channel, data[0]);
return 1;
}
@@ -1085,29 +1078,13 @@ static unsigned int labpc_eeprom_read_status(struct comedi_device *dev)
return value;
}
-static int labpc_eeprom_write(struct comedi_device *dev,
- unsigned int address, unsigned int value)
+static void labpc_eeprom_write(struct comedi_device *dev,
+ unsigned int address, unsigned int value)
{
struct labpc_private *devpriv = dev->private;
const int write_enable_instruction = 0x6;
const int write_instruction = 0x2;
const int write_length = 8; /* 8 bit write lengths to eeprom */
- const int write_in_progress_bit = 0x1;
- const int timeout = 10000;
- int i;
-
- /* make sure there isn't already a write in progress */
- for (i = 0; i < timeout; i++) {
- if ((labpc_eeprom_read_status(dev) & write_in_progress_bit) ==
- 0)
- break;
- }
- if (i == timeout) {
- dev_err(dev->class_dev, "eeprom write timed out\n");
- return -ETIME;
- }
- /* update software copy of eeprom */
- devpriv->eeprom_data[address] = value;
/* enable read/write to eeprom */
devpriv->cmd5 &= ~CMD5_EEPROMCS;
@@ -1140,8 +1117,6 @@ static int labpc_eeprom_write(struct comedi_device *dev,
devpriv->cmd5 &= ~(CMD5_EEPROMCS | CMD5_WRTPRT);
udelay(1);
devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
-
- return 0;
}
/* writes to 8 bit calibration dacs */
@@ -1150,10 +1125,6 @@ static void write_caldac(struct comedi_device *dev, unsigned int channel,
{
struct labpc_private *devpriv = dev->private;
- if (value == devpriv->caldac[channel])
- return;
- devpriv->caldac[channel] = value;
-
/* clear caldac load bit and make sure we don't write to eeprom */
devpriv->cmd5 &= ~(CMD5_CALDACLD | CMD5_EEPROMCS | CMD5_WRTPRT);
udelay(1);
@@ -1184,25 +1155,30 @@ static int labpc_calib_insn_write(struct comedi_device *dev,
* Only write the last data value to the caldac. Preceding
* data would be overwritten anyway.
*/
- if (insn->n > 0)
- write_caldac(dev, chan, data[insn->n - 1]);
+ if (insn->n > 0) {
+ unsigned int val = data[insn->n - 1];
+
+ if (s->readback[chan] != val) {
+ write_caldac(dev, chan, val);
+ s->readback[chan] = val;
+ }
+ }
return insn->n;
}
-static int labpc_calib_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
+static int labpc_eeprom_ready(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned long context)
{
- struct labpc_private *devpriv = dev->private;
- unsigned int chan = CR_CHAN(insn->chanspec);
- int i;
-
- for (i = 0; i < insn->n; i++)
- data[i] = devpriv->caldac[chan];
+ unsigned int status;
- return insn->n;
+ /* make sure there isn't already a write in progress */
+ status = labpc_eeprom_read_status(dev);
+ if ((status & 0x1) == 0)
+ return 0;
+ return -EBUSY;
}
static int labpc_eeprom_insn_write(struct comedi_device *dev,
@@ -1222,25 +1198,15 @@ static int labpc_eeprom_insn_write(struct comedi_device *dev,
* data would be overwritten anyway.
*/
if (insn->n > 0) {
- ret = labpc_eeprom_write(dev, chan, data[insn->n - 1]);
+ unsigned int val = data[insn->n - 1];
+
+ ret = comedi_timeout(dev, s, insn, labpc_eeprom_ready, 0);
if (ret)
return ret;
- }
-
- return insn->n;
-}
-
-static int labpc_eeprom_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct labpc_private *devpriv = dev->private;
- unsigned int chan = CR_CHAN(insn->chanspec);
- int i;
- for (i = 0; i < insn->n; i++)
- data[i] = devpriv->eeprom_data[chan];
+ labpc_eeprom_write(dev, chan, val);
+ s->readback[chan] = val;
+ }
return insn->n;
}
@@ -1309,19 +1275,15 @@ int labpc_common_attach(struct comedi_device *dev,
s->n_chan = NUM_AO_CHAN;
s->maxdata = 0x0fff;
s->range_table = &range_labpc_ao;
- s->insn_read = labpc_ao_insn_read;
s->insn_write = labpc_ao_insn_write;
- /* initialize analog outputs to a known value */
- for (i = 0; i < s->n_chan; i++) {
- short lsb, msb;
+ ret = comedi_alloc_subdev_readback(s);
+ if (ret)
+ return ret;
- devpriv->ao_value[i] = s->maxdata / 2;
- lsb = devpriv->ao_value[i] & 0xff;
- msb = (devpriv->ao_value[i] >> 8) & 0xff;
- devpriv->write_byte(dev, lsb, DAC_LSB_REG(i));
- devpriv->write_byte(dev, msb, DAC_MSB_REG(i));
- }
+ /* initialize analog outputs to a known value */
+ for (i = 0; i < s->n_chan; i++)
+ labpc_ao_write(dev, s, i, s->maxdata / 2);
} else {
s->type = COMEDI_SUBD_UNUSED;
}
@@ -1342,11 +1304,16 @@ int labpc_common_attach(struct comedi_device *dev,
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
s->n_chan = 16;
s->maxdata = 0xff;
- s->insn_read = labpc_calib_insn_read;
s->insn_write = labpc_calib_insn_write;
- for (i = 0; i < s->n_chan; i++)
+ ret = comedi_alloc_subdev_readback(s);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < s->n_chan; i++) {
write_caldac(dev, i, s->maxdata / 2);
+ s->readback[i] = s->maxdata / 2;
+ }
} else {
s->type = COMEDI_SUBD_UNUSED;
}
@@ -1358,11 +1325,14 @@ int labpc_common_attach(struct comedi_device *dev,
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
s->n_chan = EEPROM_SIZE;
s->maxdata = 0xff;
- s->insn_read = labpc_eeprom_insn_read;
s->insn_write = labpc_eeprom_insn_write;
+ ret = comedi_alloc_subdev_readback(s);
+ if (ret)
+ return ret;
+
for (i = 0; i < s->n_chan; i++)
- devpriv->eeprom_data[i] = labpc_eeprom_read(dev, i);
+ s->readback[i] = labpc_eeprom_read(dev, i);
} else {
s->type = COMEDI_SUBD_UNUSED;
}
diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c
index 967202e0635e..6d386050e59d 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c
@@ -91,7 +91,6 @@ void labpc_drain_dma(struct comedi_device *dev)
int status;
unsigned long flags;
unsigned int max_points, num_points, residue, leftover;
- int i;
status = devpriv->stat1;
@@ -122,9 +121,7 @@ void labpc_drain_dma(struct comedi_device *dev)
leftover = max_points;
}
- /* write data to comedi buffer */
- for (i = 0; i < num_points; i++)
- cfc_write_to_buffer(s, devpriv->dma_buffer[i]);
+ comedi_buf_write_samples(s, devpriv->dma_buffer, num_points);
if (cmd->stop_src == TRIG_COUNT)
devpriv->count -= num_points;
@@ -133,8 +130,6 @@ void labpc_drain_dma(struct comedi_device *dev)
set_dma_addr(devpriv->dma_chan, devpriv->dma_addr);
set_dma_count(devpriv->dma_chan, leftover * sample_size);
release_dma_lock(flags);
-
- async->events |= COMEDI_CB_BLOCK;
}
EXPORT_SYMBOL_GPL(labpc_drain_dma);
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index 320b080149b6..11e70173712d 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -686,13 +686,12 @@ static inline void ni_set_ai_dma_channel(struct comedi_device *dev, int channel)
{
unsigned bitfield;
- if (channel >= 0) {
+ if (channel >= 0)
bitfield =
(ni_stc_dma_channel_select_bitfield(channel) <<
AI_DMA_Select_Shift) & AI_DMA_Select_Mask;
- } else {
+ else
bitfield = 0;
- }
ni_set_bitfield(dev, AI_AO_Select, AI_DMA_Select_Mask, bitfield);
}
@@ -701,13 +700,12 @@ static inline void ni_set_ao_dma_channel(struct comedi_device *dev, int channel)
{
unsigned bitfield;
- if (channel >= 0) {
+ if (channel >= 0)
bitfield =
(ni_stc_dma_channel_select_bitfield(channel) <<
AO_DMA_Select_Shift) & AO_DMA_Select_Mask;
- } else {
+ else
bitfield = 0;
- }
ni_set_bitfield(dev, AI_AO_Select, AO_DMA_Select_Mask, bitfield);
}
@@ -1127,31 +1125,18 @@ static void ni_ao_fifo_load(struct comedi_device *dev,
struct comedi_subdevice *s, int n)
{
struct ni_private *devpriv = dev->private;
- struct comedi_async *async = s->async;
- struct comedi_cmd *cmd = &async->cmd;
- int chan;
int i;
unsigned short d;
u32 packed_data;
- int range;
- int err = 1;
- chan = async->cur_chan;
for (i = 0; i < n; i++) {
- err &= comedi_buf_get(s, &d);
- if (err == 0)
- break;
-
- range = CR_RANGE(cmd->chanlist[chan]);
+ comedi_buf_read_samples(s, &d, 1);
if (devpriv->is_6xxx) {
packed_data = d & 0xffff;
/* 6711 only has 16 bit wide ao fifo */
if (!devpriv->is_6711) {
- err &= comedi_buf_get(s, &d);
- if (err == 0)
- break;
- chan++;
+ comedi_buf_read_samples(s, &d, 1);
i++;
packed_data |= (d << 16) & 0xffff0000;
}
@@ -1159,12 +1144,7 @@ static void ni_ao_fifo_load(struct comedi_device *dev,
} else {
ni_writew(dev, d, DAC_FIFO_Data);
}
- chan++;
- chan %= cmd->chanlist_len;
}
- async->cur_chan = chan;
- if (err == 0)
- async->events |= COMEDI_CB_OVERFLOW;
}
/*
@@ -1187,21 +1167,20 @@ static int ni_ao_fifo_half_empty(struct comedi_device *dev,
struct comedi_subdevice *s)
{
const struct ni_board_struct *board = dev->board_ptr;
- int n;
+ unsigned int nbytes;
+ unsigned int nsamples;
- n = comedi_buf_read_n_available(s);
- if (n == 0) {
+ nbytes = comedi_buf_read_n_available(s);
+ if (nbytes == 0) {
s->async->events |= COMEDI_CB_OVERFLOW;
return 0;
}
- n /= sizeof(short);
- if (n > board->ao_fifo_depth / 2)
- n = board->ao_fifo_depth / 2;
-
- ni_ao_fifo_load(dev, s, n);
+ nsamples = comedi_bytes_to_samples(s, nbytes);
+ if (nsamples > board->ao_fifo_depth / 2)
+ nsamples = board->ao_fifo_depth / 2;
- s->async->events |= COMEDI_CB_BLOCK;
+ ni_ao_fifo_load(dev, s, nsamples);
return 1;
}
@@ -1211,7 +1190,8 @@ static int ni_ao_prep_fifo(struct comedi_device *dev,
{
const struct ni_board_struct *board = dev->board_ptr;
struct ni_private *devpriv = dev->private;
- int n;
+ unsigned int nbytes;
+ unsigned int nsamples;
/* reset fifo */
ni_stc_writew(dev, 1, DAC_FIFO_Clear);
@@ -1219,17 +1199,17 @@ static int ni_ao_prep_fifo(struct comedi_device *dev,
ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x);
/* load some data */
- n = comedi_buf_read_n_available(s);
- if (n == 0)
+ nbytes = comedi_buf_read_n_available(s);
+ if (nbytes == 0)
return 0;
- n /= sizeof(short);
- if (n > board->ao_fifo_depth)
- n = board->ao_fifo_depth;
+ nsamples = comedi_bytes_to_samples(s, nbytes);
+ if (nsamples > board->ao_fifo_depth)
+ nsamples = board->ao_fifo_depth;
- ni_ao_fifo_load(dev, s, n);
+ ni_ao_fifo_load(dev, s, nsamples);
- return n;
+ return nsamples;
}
static void ni_ai_fifo_read(struct comedi_device *dev,
@@ -1237,44 +1217,42 @@ static void ni_ai_fifo_read(struct comedi_device *dev,
{
struct ni_private *devpriv = dev->private;
struct comedi_async *async = s->async;
+ u32 dl;
+ unsigned short data;
int i;
if (devpriv->is_611x) {
- unsigned short data[2];
- u32 dl;
-
for (i = 0; i < n / 2; i++) {
dl = ni_readl(dev, ADC_FIFO_Data_611x);
/* This may get the hi/lo data in the wrong order */
- data[0] = (dl >> 16) & 0xffff;
- data[1] = dl & 0xffff;
- cfc_write_array_to_buffer(s, data, sizeof(data));
+ data = (dl >> 16) & 0xffff;
+ comedi_buf_write_samples(s, &data, 1);
+ data = dl & 0xffff;
+ comedi_buf_write_samples(s, &data, 1);
}
/* Check if there's a single sample stuck in the FIFO */
if (n % 2) {
dl = ni_readl(dev, ADC_FIFO_Data_611x);
- data[0] = dl & 0xffff;
- cfc_write_to_buffer(s, data[0]);
+ data = dl & 0xffff;
+ comedi_buf_write_samples(s, &data, 1);
}
} else if (devpriv->is_6143) {
- unsigned short data[2];
- u32 dl;
-
/* This just reads the FIFO assuming the data is present, no checks on the FIFO status are performed */
for (i = 0; i < n / 2; i++) {
dl = ni_readl(dev, AIFIFO_Data_6143);
- data[0] = (dl >> 16) & 0xffff;
- data[1] = dl & 0xffff;
- cfc_write_array_to_buffer(s, data, sizeof(data));
+ data = (dl >> 16) & 0xffff;
+ comedi_buf_write_samples(s, &data, 1);
+ data = dl & 0xffff;
+ comedi_buf_write_samples(s, &data, 1);
}
if (n % 2) {
/* Assume there is a single sample stuck in the FIFO */
/* Get stranded sample into FIFO */
ni_writel(dev, 0x01, AIFIFO_Control_6143);
dl = ni_readl(dev, AIFIFO_Data_6143);
- data[0] = (dl >> 16) & 0xffff;
- cfc_write_to_buffer(s, data[0]);
+ data = (dl >> 16) & 0xffff;
+ comedi_buf_write_samples(s, &data, 1);
}
} else {
if (n > sizeof(devpriv->ai_fifo_buffer) /
@@ -1288,9 +1266,7 @@ static void ni_ai_fifo_read(struct comedi_device *dev,
devpriv->ai_fifo_buffer[i] =
ni_readw(dev, ADC_FIFO_Data_Register);
}
- cfc_write_array_to_buffer(s, devpriv->ai_fifo_buffer,
- n *
- sizeof(devpriv->ai_fifo_buffer[0]));
+ comedi_buf_write_samples(s, devpriv->ai_fifo_buffer, n);
}
}
@@ -1313,8 +1289,8 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev)
{
struct ni_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
- unsigned short data[2];
u32 dl;
+ unsigned short data;
unsigned short fifo_empty;
int i;
@@ -1324,9 +1300,10 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev)
dl = ni_readl(dev, ADC_FIFO_Data_611x);
/* This may get the hi/lo data in the wrong order */
- data[0] = (dl >> 16);
- data[1] = (dl & 0xffff);
- cfc_write_array_to_buffer(s, data, sizeof(data));
+ data = dl >> 16;
+ comedi_buf_write_samples(s, &data, 1);
+ data = dl & 0xffff;
+ comedi_buf_write_samples(s, &data, 1);
}
} else if (devpriv->is_6143) {
i = 0;
@@ -1334,9 +1311,10 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev)
dl = ni_readl(dev, AIFIFO_Data_6143);
/* This may get the hi/lo data in the wrong order */
- data[0] = (dl >> 16);
- data[1] = (dl & 0xffff);
- cfc_write_array_to_buffer(s, data, sizeof(data));
+ data = dl >> 16;
+ comedi_buf_write_samples(s, &data, 1);
+ data = dl & 0xffff;
+ comedi_buf_write_samples(s, &data, 1);
i += 2;
}
/* Check if stranded sample is present */
@@ -1344,8 +1322,8 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev)
/* Get stranded sample into FIFO */
ni_writel(dev, 0x01, AIFIFO_Control_6143);
dl = ni_readl(dev, AIFIFO_Data_6143);
- data[0] = (dl >> 16) & 0xffff;
- cfc_write_to_buffer(s, data[0]);
+ data = (dl >> 16) & 0xffff;
+ comedi_buf_write_samples(s, &data, 1);
}
} else {
@@ -1364,10 +1342,7 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev)
devpriv->ai_fifo_buffer[i] =
ni_readw(dev, ADC_FIFO_Data_Register);
}
- cfc_write_array_to_buffer(s, devpriv->ai_fifo_buffer,
- i *
- sizeof(devpriv->
- ai_fifo_buffer[0]));
+ comedi_buf_write_samples(s, devpriv->ai_fifo_buffer, i);
}
}
}
@@ -1386,7 +1361,7 @@ static void get_last_sample_611x(struct comedi_device *dev)
if (ni_readb(dev, XXX_Status) & 0x80) {
dl = ni_readl(dev, ADC_FIFO_Data_611x);
data = (dl & 0xffff);
- cfc_write_to_buffer(s, data);
+ comedi_buf_write_samples(s, &data, 1);
}
}
@@ -1408,7 +1383,7 @@ static void get_last_sample_6143(struct comedi_device *dev)
/* This may get the hi/lo data in the wrong order */
data = (dl >> 16) & 0xffff;
- cfc_write_to_buffer(s, data);
+ comedi_buf_write_samples(s, &data, 1);
}
}
@@ -1462,7 +1437,7 @@ static void handle_gpct_interrupt(struct comedi_device *dev,
ni_tio_handle_interrupt(&devpriv->counter_dev->counters[counter_index],
s);
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
#endif
}
@@ -1518,7 +1493,7 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status,
if (comedi_is_subdevice_running(s)) {
s->async->events |=
COMEDI_CB_ERROR | COMEDI_CB_EOA;
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
}
return;
}
@@ -1533,7 +1508,7 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status,
if (status & (AI_Overrun_St | AI_Overflow_St))
s->async->events |= COMEDI_CB_OVERFLOW;
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return;
}
if (status & AI_SC_TC_St) {
@@ -1559,7 +1534,7 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status,
if ((status & AI_STOP_St))
ni_handle_eos(dev, s);
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
}
static void ack_b_interrupt(struct comedi_device *dev, unsigned short b_status)
@@ -1635,7 +1610,7 @@ static void handle_b_interrupt(struct comedi_device *dev,
}
#endif
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
}
static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
@@ -1645,12 +1620,12 @@ static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
struct ni_private *devpriv = dev->private;
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
- unsigned int length = num_bytes / bytes_per_sample(s);
+ unsigned int nsamples = comedi_bytes_to_samples(s, num_bytes);
unsigned short *array = data;
unsigned int *larray = data;
unsigned int i;
- for (i = 0; i < length; i++) {
+ for (i = 0; i < nsamples; i++) {
#ifdef PCIDMA
if (s->subdev_flags & SDF_LSAMPL)
larray[i] = le32_to_cpu(larray[i]);
@@ -2253,9 +2228,6 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
/* Step 1 : check if triggers are trivially valid */
- if ((cmd->flags & CMDF_WRITE))
- cmd->flags &= ~CMDF_WRITE;
-
err |= cfc_check_trigger_src(&cmd->start_src,
TRIG_NOW | TRIG_INT | TRIG_EXT);
err |= cfc_check_trigger_src(&cmd->scan_begin_src,
@@ -2762,11 +2734,11 @@ static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s,
unsigned int chan_index)
{
struct comedi_cmd *cmd = &s->async->cmd;
- unsigned int length = num_bytes / bytes_per_sample(s);
+ unsigned int nsamples = comedi_bytes_to_samples(s, num_bytes);
unsigned short *array = data;
unsigned int i;
- for (i = 0; i < length; i++) {
+ for (i = 0; i < nsamples; i++) {
unsigned int range = CR_RANGE(cmd->chanlist[chan_index]);
unsigned short val = array[i];
@@ -2981,12 +2953,15 @@ static int ni_ao_insn_config(struct comedi_device *dev,
{
const struct ni_board_struct *board = dev->board_ptr;
struct ni_private *devpriv = dev->private;
+ unsigned int nbytes;
switch (data[0]) {
case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE:
switch (data[1]) {
case COMEDI_OUTPUT:
- data[2] = 1 + board->ao_fifo_depth * sizeof(short);
+ nbytes = comedi_samples_to_bytes(s,
+ board->ao_fifo_depth);
+ data[2] = 1 + nbytes;
if (devpriv->mite)
data[2] += devpriv->mite->fifo_size;
break;
@@ -3288,9 +3263,6 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
/* Step 1 : check if triggers are trivially valid */
- if ((cmd->flags & CMDF_WRITE) == 0)
- cmd->flags |= CMDF_WRITE;
-
err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT);
err |= cfc_check_trigger_src(&cmd->scan_begin_src,
TRIG_TIMER | TRIG_EXT);
@@ -3515,9 +3487,6 @@ static int ni_cdio_cmdtest(struct comedi_device *dev,
/* Step 2a : make sure trigger sources are unique */
/* 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);
@@ -3693,7 +3662,7 @@ static void handle_cdio_interrupt(struct comedi_device *dev)
M_Offset_CDIO_Command);
/* s->async->events |= COMEDI_CB_EOA; */
}
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
}
static int ni_serial_hw_readwrite8(struct comedi_device *dev,
@@ -3976,7 +3945,7 @@ static unsigned ni_gpct_to_stc_register(enum ni_gpct_register reg)
stc_register = Interrupt_B_Enable_Register;
break;
default:
- printk("%s: unhandled register 0x%x in switch.\n",
+ pr_err("%s: unhandled register 0x%x in switch.\n",
__func__, reg);
BUG();
return 0;
@@ -5472,7 +5441,6 @@ static int ni_E_init(struct comedi_device *dev,
s->range_table = board->ao_range_table;
s->insn_config = ni_ao_insn_config;
s->insn_write = ni_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
index 5252cba82e5e..db7e8aac67b5 100644
--- a/drivers/staging/comedi/drivers/ni_pcidio.c
+++ b/drivers/staging/comedi/drivers/ni_pcidio.c
@@ -384,11 +384,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
struct comedi_subdevice *s = dev->read_subdev;
struct comedi_async *async = s->async;
struct mite_struct *mite = devpriv->mite;
-
- /* int i, j; */
- unsigned int auxdata = 0;
- unsigned short data1 = 0;
- unsigned short data2 = 0;
+ unsigned int auxdata;
int flags;
int status;
int work = 0;
@@ -451,13 +447,9 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
goto out;
}
auxdata = readl(dev->mmio + Group_1_FIFO);
- data1 = auxdata & 0xffff;
- data2 = (auxdata & 0xffff0000) >> 16;
- comedi_buf_put(s, data1);
- comedi_buf_put(s, data2);
+ comedi_buf_write_samples(s, &auxdata, 1);
flags = readb(dev->mmio + Group_1_Flags);
}
- async->events |= COMEDI_CB_BLOCK;
}
if (flags & CountExpired) {
@@ -485,7 +477,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
}
out:
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
#if 0
if (!tag)
writeb(0x03, dev->mmio + Master_DMA_And_Interrupt_Control);
diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h
index 29efce30eb7f..bd69c3f0acdc 100644
--- a/drivers/staging/comedi/drivers/ni_stc.h
+++ b/drivers/staging/comedi/drivers/ni_stc.h
@@ -334,7 +334,7 @@ static inline unsigned RTSI_Output_Bit(unsigned channel, int is_mseries)
max_channel = 6;
}
if (channel > max_channel) {
- printk("%s: bug, invalid RTSI_channel=%i\n", __func__, channel);
+ pr_err("%s: bug, invalid RTSI_channel=%i\n", __func__, channel);
return 0;
}
return 1 << (base_bit_shift + channel);
@@ -1090,7 +1090,7 @@ static inline int M_Offset_Static_AI_Control(int i)
0x263,
};
if (((unsigned)i) >= ARRAY_SIZE(offset)) {
- printk("%s: invalid channel=%i\n", __func__, i);
+ pr_err("%s: invalid channel=%i\n", __func__, i);
return offset[0];
}
return offset[i];
@@ -1105,7 +1105,7 @@ static inline int M_Offset_AO_Reference_Attenuation(int channel)
0x267
};
if (((unsigned)channel) >= ARRAY_SIZE(offset)) {
- printk("%s: invalid channel=%i\n", __func__, channel);
+ pr_err("%s: invalid channel=%i\n", __func__, channel);
return offset[0];
}
return offset[channel];
@@ -1114,7 +1114,7 @@ static inline int M_Offset_AO_Reference_Attenuation(int channel)
static inline unsigned M_Offset_PFI_Output_Select(unsigned n)
{
if (n < 1 || n > NUM_PFI_OUTPUT_SELECT_REGS) {
- printk("%s: invalid pfi output select register=%i\n",
+ pr_err("%s: invalid pfi output select register=%i\n",
__func__, n);
return M_Offset_PFI_Output_Select_1;
}
@@ -1171,7 +1171,7 @@ static inline unsigned MSeries_PLL_In_Source_Select_RTSI_Bits(unsigned
RTSI_channel)
{
if (RTSI_channel > 7) {
- printk("%s: bug, invalid RTSI_channel=%i\n", __func__,
+ pr_err("%s: bug, invalid RTSI_channel=%i\n", __func__,
RTSI_channel);
return 0;
}
@@ -1192,7 +1192,7 @@ static inline unsigned MSeries_PLL_Divisor_Bits(unsigned divisor)
{
static const unsigned max_divisor = 0x10;
if (divisor < 1 || divisor > max_divisor) {
- printk("%s: bug, invalid divisor=%i\n", __func__, divisor);
+ pr_err("%s: bug, invalid divisor=%i\n", __func__, divisor);
return 0;
}
return (divisor & 0xf) << 8;
@@ -1202,7 +1202,7 @@ static inline unsigned MSeries_PLL_Multiplier_Bits(unsigned multiplier)
{
static const unsigned max_multiplier = 0x100;
if (multiplier < 1 || multiplier > max_multiplier) {
- printk("%s: bug, invalid multiplier=%i\n", __func__,
+ pr_err("%s: bug, invalid multiplier=%i\n", __func__,
multiplier);
return 0;
}
@@ -1464,7 +1464,7 @@ struct ni_private {
unsigned short ai_fifo_buffer[0x2000];
uint8_t eeprom_buffer[M_SERIES_EEPROM_SIZE];
- uint32_t serial_number;
+ __be32 serial_number;
struct mite_struct *mite;
struct mite_channel *ai_mite_chan;
diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c
index 26e7291c4a51..6037bec77ef1 100644
--- a/drivers/staging/comedi/drivers/ni_tiocmd.c
+++ b/drivers/staging/comedi/drivers/ni_tiocmd.c
@@ -371,9 +371,8 @@ static void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter,
of gate interrupt via dma read/write
and report bogus gate errors */
if (counter->counter_dev->variant !=
- ni_gpct_variant_660x) {
+ ni_gpct_variant_660x)
*gate_error = 1;
- }
}
}
if (gxx_status & GI_TC_ERROR(cidx)) {
@@ -450,11 +449,10 @@ void ni_tio_handle_interrupt(struct ni_gpct *counter,
return;
}
gpct_mite_status = mite_get_status(counter->mite_chan);
- if (gpct_mite_status & CHSR_LINKC) {
+ if (gpct_mite_status & CHSR_LINKC)
writel(CHOR_CLRLC,
counter->mite_chan->mite->mite_io_addr +
MITE_CHOR(counter->mite_chan->channel));
- }
mite_sync_input_dma(counter->mite_chan, s);
spin_unlock_irqrestore(&counter->lock, flags);
}
diff --git a/drivers/staging/comedi/drivers/ni_usb6501.c b/drivers/staging/comedi/drivers/ni_usb6501.c
index df7ada8611f4..3b5a1b90366d 100644
--- a/drivers/staging/comedi/drivers/ni_usb6501.c
+++ b/drivers/staging/comedi/drivers/ni_usb6501.c
@@ -561,7 +561,7 @@ static int ni6501_auto_attach(struct comedi_device *dev,
/* Counter subdevice */
s = &dev->subdevices[1];
s->type = COMEDI_SUBD_COUNTER;
- s->subdev_flags = SDF_READABLE | SDF_WRITEABLE | SDF_LSAMPL;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL;
s->n_chan = 1;
s->maxdata = 0xffffffff;
s->insn_read = ni6501_cnt_insn_read;
diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
index 47f4887108a7..938aebc8e0ea 100644
--- a/drivers/staging/comedi/drivers/pcl711.c
+++ b/drivers/staging/comedi/drivers/pcl711.c
@@ -156,7 +156,6 @@ static const struct pcl711_board boardtypes[] = {
};
struct pcl711_private {
- unsigned int ntrig;
unsigned int divisor1;
unsigned int divisor2;
};
@@ -199,7 +198,6 @@ static int pcl711_ai_cancel(struct comedi_device *dev,
static irqreturn_t pcl711_interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
- struct pcl711_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
struct comedi_cmd *cmd = &s->async->cmd;
unsigned int data;
@@ -213,16 +211,14 @@ static irqreturn_t pcl711_interrupt(int irq, void *d)
outb(PCL711_INT_STAT_CLR, dev->iobase + PCL711_INT_STAT_REG);
- if (comedi_buf_put(s, data) == 0) {
- s->async->events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
- } else {
- s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
- if (cmd->stop_src == TRIG_COUNT && !(--devpriv->ntrig)) {
- pcl711_ai_set_mode(dev, PCL711_MODE_SOFTTRIG);
- s->async->events |= COMEDI_CB_EOA;
- }
- }
- comedi_event(dev, s);
+ comedi_buf_write_samples(s, &data, 1);
+
+ if (cmd->stop_src == TRIG_COUNT &&
+ s->async->scans_done >= cmd->stop_arg)
+ s->async->events |= COMEDI_CB_EOA;
+
+ comedi_handle_events(dev, s);
+
return IRQ_HANDLED;
}
@@ -373,14 +369,10 @@ static void pcl711_ai_load_counters(struct comedi_device *dev)
static int pcl711_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
- struct pcl711_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
pcl711_set_changain(dev, s, cmd->chanlist[0]);
- if (cmd->stop_src == TRIG_COUNT)
- devpriv->ntrig = cmd->stop_arg;
-
if (cmd->scan_begin_src == TRIG_TIMER) {
pcl711_ai_load_counters(dev);
outb(PCL711_INT_STAT_CLR, dev->iobase + PCL711_INT_STAT_REG);
@@ -505,7 +497,6 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->maxdata = 0xfff;
s->range_table = &range_bipolar5;
s->insn_write = pcl711_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
index dc179bd02dfd..86f713fdf1d0 100644
--- a/drivers/staging/comedi/drivers/pcl726.c
+++ b/drivers/staging/comedi/drivers/pcl726.c
@@ -235,9 +235,8 @@ static irqreturn_t pcl726_interrupt(int irq, void *d)
if (devpriv->cmd_running) {
pcl726_intr_cancel(dev, s);
- comedi_buf_put(s, 0);
- s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
- comedi_event(dev, s);
+ comedi_buf_write_samples(s, &s->state, 1);
+ comedi_handle_events(dev, s);
}
return IRQ_HANDLED;
@@ -377,7 +376,6 @@ static int pcl726_attach(struct comedi_device *dev,
s->maxdata = 0x0fff;
s->range_table_list = devpriv->rangelist;
s->insn_write = pcl726_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
index fd5ea6e01619..ac243ca5e0f8 100644
--- a/drivers/staging/comedi/drivers/pcl812.c
+++ b/drivers/staging/comedi/drivers/pcl812.c
@@ -512,7 +512,6 @@ struct pcl812_private {
unsigned int last_ai_chanspec;
unsigned char mode_reg_int; /* there is stored INT number for some card */
unsigned int ai_poll_ptr; /* how many sampes transfer poll */
- unsigned int ai_act_scan; /* how many scans we finished */
unsigned int dmapages;
unsigned int hwdmasize;
unsigned long dmabuf[2]; /* PTR to DMA buf */
@@ -556,8 +555,8 @@ static void pcl812_ai_setup_dma(struct comedi_device *dev,
/* we use EOS, so adapt DMA buffer to one scan */
if (devpriv->ai_eos) {
- devpriv->dmabytestomove[0] = cfc_bytes_per_scan(s);
- devpriv->dmabytestomove[1] = cfc_bytes_per_scan(s);
+ devpriv->dmabytestomove[0] = comedi_bytes_per_scan(s);
+ devpriv->dmabytestomove[1] = comedi_bytes_per_scan(s);
devpriv->dma_runs_to_end = 1;
} else {
devpriv->dmabytestomove[0] = devpriv->hwdmasize;
@@ -572,7 +571,7 @@ static void pcl812_ai_setup_dma(struct comedi_device *dev,
devpriv->dma_runs_to_end = 1;
} else {
/* how many samples we must transfer? */
- bytes = cmd->stop_arg * cfc_bytes_per_scan(s);
+ bytes = cmd->stop_arg * comedi_bytes_per_scan(s);
/* how many DMA pages we must fill */
devpriv->dma_runs_to_end =
@@ -807,9 +806,7 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->ai_dma = 0;
}
- devpriv->ai_act_scan = 0;
devpriv->ai_poll_ptr = 0;
- s->async->cur_chan = 0;
/* don't we want wake up every scan? */
if (cmd->flags & CMDF_WAKE_EOS) {
@@ -841,21 +838,10 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
static bool pcl812_ai_next_chan(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- struct pcl812_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
- s->async->events |= COMEDI_CB_BLOCK;
-
- s->async->cur_chan++;
- if (s->async->cur_chan >= cmd->chanlist_len) {
- s->async->cur_chan = 0;
- devpriv->ai_act_scan++;
- s->async->events |= COMEDI_CB_EOS;
- }
-
if (cmd->stop_src == TRIG_COUNT &&
- devpriv->ai_act_scan >= cmd->stop_arg) {
- /* all data sampled */
+ s->async->scans_done >= cmd->stop_arg) {
s->async->events |= COMEDI_CB_EOA;
return false;
}
@@ -867,7 +853,9 @@ static void pcl812_handle_eoc(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct comedi_cmd *cmd = &s->async->cmd;
+ unsigned int chan = s->async->cur_chan;
unsigned int next_chan;
+ unsigned short val;
if (pcl812_ai_eoc(dev, s, NULL, 0)) {
dev_dbg(dev->class_dev, "A/D cmd IRQ without DRDY!\n");
@@ -875,13 +863,12 @@ static void pcl812_handle_eoc(struct comedi_device *dev,
return;
}
- comedi_buf_put(s, pcl812_ai_get_sample(dev, s));
+ val = pcl812_ai_get_sample(dev, s);
+ comedi_buf_write_samples(s, &val, 1);
/* Set up next channel. Added by abbotti 2010-01-20, but untested. */
- next_chan = s->async->cur_chan + 1;
- if (next_chan >= cmd->chanlist_len)
- next_chan = 0;
- if (cmd->chanlist[s->async->cur_chan] != cmd->chanlist[next_chan])
+ next_chan = s->async->cur_chan;
+ if (cmd->chanlist[chan] != cmd->chanlist[next_chan])
pcl812_ai_set_chan_range(dev, cmd->chanlist[next_chan], 0);
pcl812_ai_next_chan(dev, s);
@@ -893,9 +880,11 @@ static void transfer_from_dma_buf(struct comedi_device *dev,
unsigned int bufptr, unsigned int len)
{
unsigned int i;
+ unsigned short val;
for (i = len; i; i--) {
- comedi_buf_put(s, ptr[bufptr++]);
+ val = ptr[bufptr++];
+ comedi_buf_write_samples(s, &val, 1);
if (!pcl812_ai_next_chan(dev, s))
break;
@@ -939,7 +928,7 @@ static irqreturn_t pcl812_interrupt(int irq, void *d)
pcl812_ai_clear_eoc(dev);
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return IRQ_HANDLED;
}
@@ -1335,7 +1324,6 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
break;
}
s->insn_write = pcl812_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
index aa6487132017..73deb4bd5c93 100644
--- a/drivers/staging/comedi/drivers/pcl816.c
+++ b/drivers/staging/comedi/drivers/pcl816.c
@@ -122,7 +122,6 @@ struct pcl816_private {
int next_dma_buf; /* which DMA buffer will be used next round */
long dma_runs_to_end; /* how many we must permorm DMA transfer to end of record */
unsigned long last_dma_run; /* how many bytes we must transfer on last DMA page */
- int ai_act_scan; /* how many scans we finished */
unsigned int ai_poll_ptr; /* how many sampes transfer poll */
unsigned int divisor1;
unsigned int divisor2;
@@ -160,7 +159,7 @@ static void pcl816_ai_setup_dma(struct comedi_device *dev,
bytes = devpriv->hwdmasize;
if (cmd->stop_src == TRIG_COUNT) {
/* how many */
- bytes = cmd->stop_arg * cfc_bytes_per_scan(s);
+ bytes = cmd->stop_arg * comedi_bytes_per_scan(s);
/* how many DMA pages we must fill */
devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize;
@@ -286,21 +285,10 @@ static int pcl816_ai_eoc(struct comedi_device *dev,
static bool pcl816_ai_next_chan(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- struct pcl816_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
- s->async->events |= COMEDI_CB_BLOCK;
-
- s->async->cur_chan++;
- if (s->async->cur_chan >= cmd->chanlist_len) {
- s->async->cur_chan = 0;
- devpriv->ai_act_scan++;
- s->async->events |= COMEDI_CB_EOS;
- }
-
if (cmd->stop_src == TRIG_COUNT &&
- devpriv->ai_act_scan >= cmd->stop_arg) {
- /* all data sampled */
+ s->async->scans_done >= cmd->stop_arg) {
s->async->events |= COMEDI_CB_EOA;
return false;
}
@@ -313,10 +301,12 @@ static void transfer_from_dma_buf(struct comedi_device *dev,
unsigned short *ptr,
unsigned int bufptr, unsigned int len)
{
+ unsigned short val;
int i;
for (i = 0; i < len; i++) {
- comedi_buf_put(s, ptr[bufptr++]);
+ val = ptr[bufptr++];
+ comedi_buf_write_samples(s, &val, 1);
if (!pcl816_ai_next_chan(dev, s))
return;
@@ -355,7 +345,7 @@ static irqreturn_t pcl816_interrupt(int irq, void *d)
pcl816_ai_clear_eoc(dev);
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return IRQ_HANDLED;
}
@@ -508,8 +498,6 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
pcl816_ai_setup_chanlist(dev, cmd->chanlist, seglen);
udelay(1);
- devpriv->ai_act_scan = 0;
- s->async->cur_chan = 0;
devpriv->ai_cmd_running = 1;
devpriv->ai_poll_ptr = 0;
devpriv->ai_cmd_canceled = 0;
@@ -566,7 +554,7 @@ static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->ai_poll_ptr = top1; /* new buffer position */
spin_unlock_irqrestore(&dev->spinlock, flags);
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return comedi_buf_n_bytes_ready(s);
}
diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
index ac19e83ce62a..8edea35532a9 100644
--- a/drivers/staging/comedi/drivers/pcl818.c
+++ b/drivers/staging/comedi/drivers/pcl818.c
@@ -313,8 +313,6 @@ struct pcl818_private {
unsigned long last_dma_run; /* how many bytes we must transfer on last DMA page */
unsigned int ns_min; /* manimal allowed delay between samples (in us) for actual card */
int i8253_osc_base; /* 1/frequency of on board oscilator in ns */
- int ai_act_scan; /* how many scans we finished */
- int ai_act_chan; /* actual position in actual scan */
unsigned int act_chanlist[16]; /* MUX setting for actual AI operations */
unsigned int act_chanlist_len; /* how long is actual MUX list */
unsigned int act_chanlist_pos; /* actual position in MUX list */
@@ -352,7 +350,7 @@ static void pcl818_ai_setup_dma(struct comedi_device *dev,
disable_dma(devpriv->dma); /* disable dma */
bytes = devpriv->hwdmasize;
if (cmd->stop_src == TRIG_COUNT) {
- bytes = cmd->stop_arg * cfc_bytes_per_scan(s);
+ bytes = cmd->stop_arg * comedi_bytes_per_scan(s);
devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize;
devpriv->last_dma_run = bytes % devpriv->hwdmasize;
devpriv->dma_runs_to_end--;
@@ -521,21 +519,12 @@ static bool pcl818_ai_next_chan(struct comedi_device *dev,
struct pcl818_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
- s->async->events |= COMEDI_CB_BLOCK;
-
devpriv->act_chanlist_pos++;
if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len)
devpriv->act_chanlist_pos = 0;
- s->async->cur_chan++;
- if (s->async->cur_chan >= cmd->chanlist_len) {
- s->async->cur_chan = 0;
- devpriv->ai_act_scan--;
- s->async->events |= COMEDI_CB_EOS;
- }
-
- if (cmd->stop_src == TRIG_COUNT && devpriv->ai_act_scan == 0) {
- /* all data sampled */
+ if (cmd->stop_src == TRIG_COUNT &&
+ s->async->scans_done >= cmd->stop_arg) {
s->async->events |= COMEDI_CB_EOA;
return false;
}
@@ -560,7 +549,7 @@ static void pcl818_handle_eoc(struct comedi_device *dev,
if (pcl818_ai_dropout(dev, s, chan))
return;
- comedi_buf_put(s, val);
+ comedi_buf_write_samples(s, &val, 1);
pcl818_ai_next_chan(dev, s);
}
@@ -589,7 +578,7 @@ static void pcl818_handle_dma(struct comedi_device *dev,
if (pcl818_ai_dropout(dev, s, chan))
break;
- comedi_buf_put(s, val);
+ comedi_buf_write_samples(s, &val, 1);
if (!pcl818_ai_next_chan(dev, s))
break;
@@ -630,7 +619,7 @@ static void pcl818_handle_fifo(struct comedi_device *dev,
if (pcl818_ai_dropout(dev, s, chan))
break;
- comedi_buf_put(s, val);
+ comedi_buf_write_samples(s, &val, 1);
if (!pcl818_ai_next_chan(dev, s))
break;
@@ -642,6 +631,7 @@ static irqreturn_t pcl818_interrupt(int irq, void *d)
struct comedi_device *dev = d;
struct pcl818_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
+ struct comedi_cmd *cmd = &s->async->cmd;
if (!dev->attached || !devpriv->ai_cmd_running) {
pcl818_ai_clear_eoc(dev);
@@ -655,7 +645,7 @@ static irqreturn_t pcl818_interrupt(int irq, void *d)
* being reprogrammed while a DMA transfer is in
* progress.
*/
- devpriv->ai_act_scan = 0;
+ s->async->scans_done = cmd->stop_arg;
s->cancel(dev, s);
return IRQ_HANDLED;
}
@@ -669,7 +659,7 @@ static irqreturn_t pcl818_interrupt(int irq, void *d)
pcl818_ai_clear_eoc(dev);
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
return IRQ_HANDLED;
}
@@ -829,8 +819,6 @@ static int pcl818_ai_cmd(struct comedi_device *dev,
pcl818_ai_setup_chanlist(dev, cmd->chanlist, seglen);
devpriv->ai_data_len = s->async->prealloc_bufsz;
- devpriv->ai_act_scan = cmd->stop_arg;
- devpriv->ai_act_chan = 0;
devpriv->ai_cmd_running = 1;
devpriv->ai_cmd_canceled = 0;
devpriv->act_chanlist_pos = 0;
@@ -873,7 +861,8 @@ static int pcl818_ai_cancel(struct comedi_device *dev,
if (devpriv->dma) {
if (cmd->stop_src == TRIG_NONE ||
- (cmd->stop_src == TRIG_COUNT && devpriv->ai_act_scan > 0)) {
+ (cmd->stop_src == TRIG_COUNT &&
+ s->async->scans_done < cmd->stop_arg)) {
if (!devpriv->ai_cmd_canceled) {
/*
* Wait for running dma transfer to end,
@@ -1169,7 +1158,6 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->range_table = &range_unknown;
}
s->insn_write = pcl818_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
index fc40ee2b34e9..f0059e935da0 100644
--- a/drivers/staging/comedi/drivers/pcmmio.c
+++ b/drivers/staging/comedi/drivers/pcmmio.c
@@ -190,7 +190,6 @@ struct pcmmio_private {
spinlock_t pagelock; /* protects the page registers */
spinlock_t spinlock; /* protects the member variables */
unsigned int enabled_mask;
- unsigned int stop_count;
unsigned int active:1;
};
@@ -337,7 +336,6 @@ static void pcmmio_handle_dio_intr(struct comedi_device *dev,
{
struct pcmmio_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
- unsigned int oldevents = s->async->events;
unsigned int val = 0;
unsigned long flags;
int i;
@@ -357,31 +355,16 @@ static void pcmmio_handle_dio_intr(struct comedi_device *dev,
val |= (1 << i);
}
- /* Write the scan to the buffer. */
- if (comedi_buf_put(s, val) &&
- comedi_buf_put(s, val >> 16)) {
- s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
- } else {
- /* Overflow! Stop acquisition!! */
- /* TODO: STOP_ACQUISITION_CALL_HERE!! */
- pcmmio_stop_intr(dev, s);
- }
+ comedi_buf_write_samples(s, &val, 1);
- /* Check for end of acquisition. */
- if (cmd->stop_src == TRIG_COUNT && devpriv->stop_count > 0) {
- devpriv->stop_count--;
- if (devpriv->stop_count == 0) {
- s->async->events |= COMEDI_CB_EOA;
- /* TODO: STOP_ACQUISITION_CALL_HERE!! */
- pcmmio_stop_intr(dev, s);
- }
- }
+ if (cmd->stop_src == TRIG_COUNT &&
+ s->async->scans_done >= cmd->stop_arg)
+ s->async->events |= COMEDI_CB_EOA;
done:
spin_unlock_irqrestore(&devpriv->spinlock, flags);
- if (oldevents != s->async->events)
- comedi_event(dev, s);
+ comedi_handle_events(dev, s);
}
static irqreturn_t interrupt_pcmmio(int irq, void *d)
@@ -481,8 +464,6 @@ static int pcmmio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
spin_lock_irqsave(&devpriv->spinlock, flags);
devpriv->active = 1;
- devpriv->stop_count = cmd->stop_arg;
-
/* Set up start of acquisition. */
if (cmd->start_src == TRIG_INT)
s->async->inttrig = pcmmio_inttrig_start_intr;
@@ -751,7 +732,6 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->maxdata = 0xffff;
s->range_table = &pcmmio_ao_ranges;
s->insn_write = pcmmio_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
@@ -774,7 +754,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->insn_config = pcmmio_dio_insn_config;
if (dev->irq) {
dev->read_subdev = s;
- s->subdev_flags |= SDF_CMD_READ;
+ s->subdev_flags |= SDF_CMD_READ | SDF_LSAMPL | SDF_PACKED;
s->len_chanlist = s->n_chan;
s->cancel = pcmmio_cancel;
s->do_cmd = pcmmio_cmd;
diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
index d4fe2ec25ecf..0f5483b6147f 100644
--- a/drivers/staging/comedi/drivers/pcmuio.c
+++ b/drivers/staging/comedi/drivers/pcmuio.c
@@ -130,7 +130,6 @@ struct pcmuio_asic {
spinlock_t pagelock; /* protects the page registers */
spinlock_t spinlock; /* protects member variables */
unsigned int enabled_mask;
- unsigned int stop_count;
unsigned int active:1;
};
@@ -317,7 +316,6 @@ static void pcmuio_handle_intr_subdev(struct comedi_device *dev,
int asic = pcmuio_subdevice_to_asic(s);
struct pcmuio_asic *chip = &devpriv->asics[asic];
struct comedi_cmd *cmd = &s->async->cmd;
- unsigned oldevents = s->async->events;
unsigned int val = 0;
unsigned long flags;
unsigned int i;
@@ -337,33 +335,16 @@ static void pcmuio_handle_intr_subdev(struct comedi_device *dev,
val |= (1 << i);
}
- /* Write the scan to the buffer. */
- if (comedi_buf_put(s, val) &&
- comedi_buf_put(s, val >> 16)) {
- s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
- } else {
- /* Overflow! Stop acquisition!! */
- /* TODO: STOP_ACQUISITION_CALL_HERE!! */
- pcmuio_stop_intr(dev, s);
- }
+ comedi_buf_write_samples(s, &val, 1);
- /* Check for end of acquisition. */
- if (cmd->stop_src == TRIG_COUNT) {
- if (chip->stop_count > 0) {
- chip->stop_count--;
- if (chip->stop_count == 0) {
- s->async->events |= COMEDI_CB_EOA;
- /* TODO: STOP_ACQUISITION_CALL_HERE!! */
- pcmuio_stop_intr(dev, s);
- }
- }
- }
+ if (cmd->stop_src == TRIG_COUNT &&
+ s->async->scans_done >= cmd->stop_arg)
+ s->async->events |= COMEDI_CB_EOA;
done:
spin_unlock_irqrestore(&chip->spinlock, flags);
- if (oldevents != s->async->events)
- comedi_event(dev, s);
+ comedi_handle_events(dev, s);
}
static int pcmuio_handle_asic_interrupt(struct comedi_device *dev, int asic)
@@ -487,8 +468,6 @@ static int pcmuio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
spin_lock_irqsave(&chip->spinlock, flags);
chip->active = 1;
- chip->stop_count = cmd->stop_arg;
-
/* Set up start of acquisition. */
if (cmd->start_src == TRIG_INT)
s->async->inttrig = pcmuio_inttrig_start_intr;
@@ -614,7 +593,8 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if ((i == 0 && dev->irq) || (i == 2 && devpriv->irq2)) {
/* setup the interrupt subdevice */
dev->read_subdev = s;
- s->subdev_flags |= SDF_CMD_READ;
+ s->subdev_flags |= SDF_CMD_READ | SDF_LSAMPL |
+ SDF_PACKED;
s->len_chanlist = s->n_chan;
s->cancel = pcmuio_cancel;
s->do_cmd = pcmuio_cmd;
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
index 6407df0404f0..96098110b0b3 100644
--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
@@ -65,8 +65,6 @@ struct daqp_private {
enum { semaphore, buffer } interrupt_mode;
struct completion eos;
-
- int count;
};
/* The DAQP communicates with the system through a 16 byte I/O window. */
@@ -194,6 +192,7 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id)
struct comedi_device *dev = dev_id;
struct daqp_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
+ struct comedi_cmd *cmd = &s->async->cmd;
int loop_limit = 10000;
int status;
@@ -221,18 +220,16 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id)
data |= inb(dev->iobase + DAQP_FIFO) << 8;
data ^= 0x8000;
- comedi_buf_put(s, data);
+ comedi_buf_write_samples(s, &data, 1);
/* If there's a limit, decrement it
* and stop conversion if zero
*/
- if (devpriv->count > 0) {
- devpriv->count--;
- if (devpriv->count == 0) {
- s->async->events |= COMEDI_CB_EOA;
- break;
- }
+ if (cmd->stop_src == TRIG_COUNT &&
+ s->async->scans_done >= cmd->stop_arg) {
+ s->async->events |= COMEDI_CB_EOA;
+ break;
}
if ((loop_limit--) <= 0)
@@ -245,9 +242,7 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id)
s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
}
- s->async->events |= COMEDI_CB_BLOCK;
-
- cfc_handle_events(dev, s);
+ comedi_handle_events(dev, s);
}
return IRQ_HANDLED;
}
@@ -575,12 +570,16 @@ static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
*/
if (cmd->stop_src == TRIG_COUNT) {
- devpriv->count = cmd->stop_arg * cmd->scan_end_arg;
- threshold = 2 * devpriv->count;
- while (threshold > DAQP_FIFO_SIZE * 3 / 4)
- threshold /= 2;
+ unsigned long long nsamples;
+ unsigned long long nbytes;
+
+ nsamples = (unsigned long long)cmd->stop_arg *
+ cmd->scan_end_arg;
+ nbytes = nsamples * comedi_bytes_per_sample(s);
+ while (nbytes > DAQP_FIFO_SIZE * 3 / 4)
+ nbytes /= 2;
+ threshold = nbytes;
} else {
- devpriv->count = -1;
threshold = DAQP_FIFO_SIZE / 2;
}
@@ -736,12 +735,11 @@ static int daqp_auto_attach(struct comedi_device *dev,
s = &dev->subdevices[1];
s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 2;
s->maxdata = 0x0fff;
s->range_table = &range_bipolar5;
s->insn_write = daqp_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
@@ -756,7 +754,7 @@ static int daqp_auto_attach(struct comedi_device *dev,
s = &dev->subdevices[3];
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITEABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 1;
s->maxdata = 1;
s->insn_bits = daqp_do_insn_bits;
diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
index 7d4cb140959c..581aa58d9c0a 100644
--- a/drivers/staging/comedi/drivers/rtd520.c
+++ b/drivers/staging/comedi/drivers/rtd520.c
@@ -379,7 +379,6 @@ struct rtd_private {
long ai_count; /* total transfer size (samples) */
int xfer_count; /* # to transfer data. 0->1/2FIFO */
int flags; /* flag event modes */
- DECLARE_BITMAP(chan_is_bipolar, RTD_MAX_CHANLIST);
unsigned fifosz;
};
@@ -438,7 +437,6 @@ static unsigned short rtd_convert_chan_gain(struct comedi_device *dev,
unsigned int chanspec, int index)
{
const struct rtd_boardinfo *board = dev->board_ptr;
- struct rtd_private *devpriv = dev->private;
unsigned int chan = CR_CHAN(chanspec);
unsigned int range = CR_RANGE(chanspec);
unsigned int aref = CR_AREF(chanspec);
@@ -451,17 +449,14 @@ static unsigned short rtd_convert_chan_gain(struct comedi_device *dev,
/* +-5 range */
r |= 0x000;
r |= (range & 0x7) << 4;
- __set_bit(index, devpriv->chan_is_bipolar);
} else if (range < board->range_uni10) {
/* +-10 range */
r |= 0x100;
r |= ((range - board->range_bip10) & 0x7) << 4;
- __set_bit(index, devpriv->chan_is_bipolar);
} else {
/* +10 range */
r |= 0x200;
r |= ((range - board->range_uni10) & 0x7) << 4;
- __clear_bit(index, devpriv->chan_is_bipolar);
}
switch (aref) {
@@ -561,6 +556,7 @@ static int rtd_ai_rinsn(struct comedi_device *dev,
unsigned int *data)
{
struct rtd_private *devpriv = dev->private;
+ unsigned int range = CR_RANGE(insn->chanspec);
int ret;
int n;
@@ -586,9 +582,11 @@ static int rtd_ai_rinsn(struct comedi_device *dev,
/* read data */
d = readw(devpriv->las1 + LAS1_ADC_FIFO);
d = d >> 3; /* low 3 bits are marker lines */
- if (test_bit(0, devpriv->chan_is_bipolar))
- /* convert to comedi unsigned data */
+
+ /* convert bipolar data to comedi unsigned data */
+ if (comedi_range_is_bipolar(s, range))
d = comedi_offset_munge(s, d);
+
data[n] = d & s->maxdata;
}
@@ -606,9 +604,12 @@ static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s,
int count)
{
struct rtd_private *devpriv = dev->private;
+ struct comedi_async *async = s->async;
+ struct comedi_cmd *cmd = &async->cmd;
int ii;
for (ii = 0; ii < count; ii++) {
+ unsigned int range = CR_RANGE(cmd->chanlist[async->cur_chan]);
unsigned short d;
if (0 == devpriv->ai_count) { /* done */
@@ -618,41 +619,13 @@ static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s,
d = readw(devpriv->las1 + LAS1_ADC_FIFO);
d = d >> 3; /* low 3 bits are marker lines */
- if (test_bit(s->async->cur_chan, devpriv->chan_is_bipolar))
- /* convert to comedi unsigned data */
- d = comedi_offset_munge(s, d);
- d &= s->maxdata;
-
- if (!comedi_buf_put(s, d))
- return -1;
-
- if (devpriv->ai_count > 0) /* < 0, means read forever */
- devpriv->ai_count--;
- }
- return 0;
-}
-
-/*
- unknown amout of data is waiting in fifo.
-*/
-static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s)
-{
- struct rtd_private *devpriv = dev->private;
-
- while (readl(dev->mmio + LAS0_ADC) & FS_ADC_NOT_EMPTY) {
- unsigned short d = readw(devpriv->las1 + LAS1_ADC_FIFO);
-
- if (0 == devpriv->ai_count) { /* done */
- continue; /* read rest */
- }
- d = d >> 3; /* low 3 bits are marker lines */
- if (test_bit(s->async->cur_chan, devpriv->chan_is_bipolar))
- /* convert to comedi unsigned data */
+ /* convert bipolar data to comedi unsigned data */
+ if (comedi_range_is_bipolar(s, range))
d = comedi_offset_munge(s, d);
d &= s->maxdata;
- if (!comedi_buf_put(s, d))
+ if (!comedi_buf_write_samples(s, &d, 1))
return -1;
if (devpriv->ai_count > 0) /* < 0, means read forever */
@@ -703,8 +676,6 @@ static irqreturn_t rtd_interrupt(int irq, void *d)
if (0 == devpriv->ai_count)
goto xfer_done;
-
- comedi_event(dev, s);
} else if (devpriv->xfer_count > 0) {
if (fifo_status & FS_ADC_NOT_EMPTY) {
/* FIFO not empty */
@@ -713,8 +684,6 @@ static irqreturn_t rtd_interrupt(int irq, void *d)
if (0 == devpriv->ai_count)
goto xfer_done;
-
- comedi_event(dev, s);
}
}
}
@@ -726,28 +695,16 @@ static irqreturn_t rtd_interrupt(int irq, void *d)
/* clear the interrupt */
writew(status, dev->mmio + LAS0_CLEAR);
readw(dev->mmio + LAS0_CLEAR);
+
+ comedi_handle_events(dev, s);
+
return IRQ_HANDLED;
xfer_abort:
- writel(0, dev->mmio + LAS0_ADC_FIFO_CLEAR);
s->async->events |= COMEDI_CB_ERROR;
- devpriv->ai_count = 0; /* stop and don't transfer any more */
- /* fall into xfer_done */
xfer_done:
- /* pacer stop source: SOFTWARE */
- writel(0, dev->mmio + LAS0_PACER_STOP);
- writel(0, dev->mmio + LAS0_PACER); /* stop pacer */
- writel(0, dev->mmio + LAS0_ADC_CONVERSION);
- writew(0, dev->mmio + LAS0_IT);
-
- if (devpriv->ai_count > 0) { /* there shouldn't be anything left */
- fifo_status = readl(dev->mmio + LAS0_ADC);
- ai_read_dregs(dev, s); /* read anything left in FIFO */
- }
-
- s->async->events |= COMEDI_CB_EOA; /* signal end to comedi */
- comedi_event(dev, s);
+ s->async->events |= COMEDI_CB_EOA;
/* clear the interrupt */
status = readw(dev->mmio + LAS0_IT);
@@ -757,6 +714,8 @@ xfer_done:
fifo_status = readl(dev->mmio + LAS0_ADC);
overrun = readl(dev->mmio + LAS0_OVERRUN) & 0xffff;
+ comedi_handle_events(dev, s);
+
return IRQ_HANDLED;
}
@@ -1083,6 +1042,7 @@ static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->ai_count = 0; /* stop and don't transfer any more */
status = readw(dev->mmio + LAS0_IT);
overrun = readl(dev->mmio + LAS0_OVERRUN) & 0xffff;
+ writel(0, dev->mmio + LAS0_ADC_FIFO_CLEAR);
return 0;
}
@@ -1303,7 +1263,6 @@ static int rtd_auto_attach(struct comedi_device *dev,
s->maxdata = 0x0fff;
s->range_table = &rtd_ao_range;
s->insn_write = rtd_ao_winsn;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
index e3d9f44cefb9..67b4b378bd01 100644
--- a/drivers/staging/comedi/drivers/rti800.c
+++ b/drivers/staging/comedi/drivers/rti800.c
@@ -313,7 +313,6 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
? rti800_ao_ranges[it->options[7]]
: &range_unknown;
s->insn_write = rti800_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c
index c81b01c40f12..96c3974207ae 100644
--- a/drivers/staging/comedi/drivers/rti802.c
+++ b/drivers/staging/comedi/drivers/rti802.c
@@ -100,7 +100,6 @@ static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->maxdata = 0xfff;
s->n_chan = 8;
s->insn_write = rti802_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
index 75872c6aec2a..6f3e8a08e75c 100644
--- a/drivers/staging/comedi/drivers/s526.c
+++ b/drivers/staging/comedi/drivers/s526.c
@@ -583,7 +583,6 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->maxdata = 0xffff;
s->range_table = &range_bipolar10;
s->insn_write = s526_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index 0e7621e890c3..14932c5f3798 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -78,7 +78,6 @@ struct s626_buffer_dma {
struct s626_private {
uint8_t ai_cmd_running; /* ai_cmd is running */
- int ai_sample_count; /* number of samples to acquire */
unsigned int ai_sample_timer; /* time between samples in
* units of the timer */
int ai_convert_count; /* conversion counter */
@@ -1480,7 +1479,6 @@ static bool s626_handle_eos_interrupt(struct comedi_device *dev)
* from the final ADC of the previous poll list scan.
*/
uint32_t *readaddr = (uint32_t *)devpriv->ana_buf.logical_base + 1;
- bool finished = false;
int i;
/* get the data and hand it over to comedi */
@@ -1494,36 +1492,21 @@ static bool s626_handle_eos_interrupt(struct comedi_device *dev)
tempdata = s626_ai_reg_to_uint(*readaddr);
readaddr++;
- /* put data into read buffer */
- cfc_write_to_buffer(s, tempdata);
+ comedi_buf_write_samples(s, &tempdata, 1);
}
- /* end of scan occurs */
- async->events |= COMEDI_CB_EOS;
+ if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
+ async->events |= COMEDI_CB_EOA;
- if (cmd->stop_src == TRIG_COUNT) {
- devpriv->ai_sample_count--;
- if (devpriv->ai_sample_count <= 0) {
- devpriv->ai_cmd_running = 0;
-
- /* Stop RPS program */
- s626_mc_disable(dev, S626_MC1_ERPS1, S626_P_MC1);
-
- /* send end of acquisition */
- async->events |= COMEDI_CB_EOA;
-
- /* disable master interrupt */
- finished = true;
- }
- }
+ if (async->events & COMEDI_CB_CANCEL_MASK)
+ devpriv->ai_cmd_running = 0;
if (devpriv->ai_cmd_running && cmd->scan_begin_src == TRIG_EXT)
s626_dio_set_irq(dev, cmd->scan_begin_arg);
- /* tell comedi that data is there */
- comedi_event(dev, s);
+ comedi_handle_events(dev, s);
- return finished;
+ return !devpriv->ai_cmd_running;
}
static irqreturn_t s626_irq_handler(int irq, void *d)
@@ -1970,13 +1953,13 @@ static int s626_ns_to_timer(unsigned int *nanosec, unsigned int flags)
switch (flags & CMDF_ROUND_MASK) {
case CMDF_ROUND_NEAREST:
default:
- divider = (*nanosec + base / 2) / base;
+ divider = DIV_ROUND_CLOSEST(*nanosec, base);
break;
case CMDF_ROUND_DOWN:
divider = (*nanosec) / base;
break;
case CMDF_ROUND_UP:
- divider = (*nanosec + base - 1) / base;
+ divider = DIV_ROUND_UP(*nanosec, base);
break;
}
@@ -2102,8 +2085,6 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
break;
}
- devpriv->ai_sample_count = cmd->stop_arg;
-
s626_reset_adc(dev, ppl);
switch (cmd->start_src) {
@@ -2820,7 +2801,6 @@ static int s626_auto_attach(struct comedi_device *dev,
s->maxdata = 0x3fff;
s->range_table = &range_bipolar10;
s->insn_write = s626_ao_insn_write;
- s->insn_read = comedi_readback_insn_read;
ret = comedi_alloc_subdev_readback(s);
if (ret)
diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
index 167f82418cb4..71226ee9064e 100644
--- a/drivers/staging/comedi/drivers/serial2002.c
+++ b/drivers/staging/comedi/drivers/serial2002.c
@@ -742,7 +742,7 @@ static int serial2002_attach(struct comedi_device *dev,
/* digital output subdevice */
s = &dev->subdevices[1];
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITEABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 0;
s->maxdata = 1;
s->range_table = &range_digital;
@@ -760,7 +760,7 @@ static int serial2002_attach(struct comedi_device *dev,
/* analog output subdevice */
s = &dev->subdevices[3];
s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 0;
s->maxdata = 1;
s->range_table = NULL;
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index 5adbfedf780f..4737dbf8e01d 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -1,37 +1,34 @@
/*
- comedi/drivers/usbdux.c
- Copyright (C) 2003-2007 Bernd Porr, Bernd.Porr@f2s.com
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ * usbdux.c
+ * Copyright (C) 2003-2014 Bernd Porr, mail@berndporr.me.uk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*/
+
/*
-Driver: usbdux
-Description: University of Stirling USB DAQ & INCITE Technology Limited
-Devices: [ITL] USB-DUX (usbdux.o)
-Author: Bernd Porr <BerndPorr@f2s.com>
-Updated: 8 Dec 2008
-Status: Stable
-Configuration options:
- You have to upload firmware with the -i option. The
- firmware is usually installed under /usr/share/usb or
- /usr/local/share/usb or /lib/firmware.
-
-Connection scheme for the counter at the digital port:
- 0=/CLK0, 1=UP/DOWN0, 2=RESET0, 4=/CLK1, 5=UP/DOWN1, 6=RESET1.
- The sampling rate of the counter is approximately 500Hz.
-
-Please note that under USB2.0 the length of the channel list determines
-the max sampling rate. If you sample only one channel you get 8kHz
-sampling rate. If you sample two channels you get 4kHz and so on.
-*/
+ * Driver: usbdux
+ * Description: University of Stirling USB DAQ & INCITE Technology Limited
+ * Devices: (ITL) USB-DUX [usbdux]
+ * Author: Bernd Porr <mail@berndporr.me.uk>
+ * Updated: 10 Oct 2014
+ * Status: Stable
+ * Connection scheme for the counter at the digital port:
+ * 0=/CLK0, 1=UP/DOWN0, 2=RESET0, 4=/CLK1, 5=UP/DOWN1, 6=RESET1.
+ * The sampling rate of the counter is approximately 500Hz.
+ *
+ * Note that under USB2.0 the length of the channel list determines
+ * the max sampling rate. If you sample only one channel you get 8kHz
+ * sampling rate. If you sample two channels you get 4kHz and so on.
+ */
+
/*
* I must give credit here to Chris Baugher who
* wrote the driver for AT-MIO-16d. I used some parts of this
@@ -205,9 +202,6 @@ struct usbdux_private {
unsigned int ao_cmd_running:1;
unsigned int pwm_cmd_running:1;
- /* number of samples to acquire */
- int ai_sample_count;
- int ao_sample_count;
/* time between samples in units of the timer */
unsigned int ai_timer;
unsigned int ao_timer;
@@ -253,128 +247,107 @@ static int usbdux_ai_cancel(struct comedi_device *dev,
return 0;
}
-/* analogue IN - interrupt service routine */
+static void usbduxsub_ai_handle_urb(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct urb *urb)
+{
+ struct usbdux_private *devpriv = dev->private;
+ struct comedi_async *async = s->async;
+ struct comedi_cmd *cmd = &async->cmd;
+ int ret;
+ int i;
+
+ devpriv->ai_counter--;
+ if (devpriv->ai_counter == 0) {
+ devpriv->ai_counter = devpriv->ai_timer;
+
+ /* get the data from the USB bus and hand it over to comedi */
+ for (i = 0; i < cmd->chanlist_len; i++) {
+ unsigned int range = CR_RANGE(cmd->chanlist[i]);
+ uint16_t val = le16_to_cpu(devpriv->in_buf[i]);
+
+ /* bipolar data is two's-complement */
+ if (comedi_range_is_bipolar(s, range))
+ val ^= ((s->maxdata + 1) >> 1);
+
+ /* transfer data */
+ if (!comedi_buf_write_samples(s, &val, 1))
+ return;
+ }
+
+ if (cmd->stop_src == TRIG_COUNT &&
+ async->scans_done >= cmd->stop_arg)
+ async->events |= COMEDI_CB_EOA;
+ }
+
+ /* if command is still running, resubmit urb */
+ if (!(async->events & COMEDI_CB_CANCEL_MASK)) {
+ urb->dev = comedi_to_usb_dev(dev);
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret < 0) {
+ dev_err(dev->class_dev,
+ "urb resubmit failed in int-context! err=%d\n",
+ ret);
+ if (ret == -EL2NSYNC)
+ dev_err(dev->class_dev,
+ "buggy USB host controller or bug in IRQ handler!\n");
+ async->events |= COMEDI_CB_ERROR;
+ }
+ }
+}
+
static void usbduxsub_ai_isoc_irq(struct urb *urb)
{
struct comedi_device *dev = urb->context;
struct comedi_subdevice *s = dev->read_subdev;
+ struct comedi_async *async = s->async;
struct usbdux_private *devpriv = dev->private;
- struct comedi_cmd *cmd = &s->async->cmd;
- int i, err;
- /* first we test if something unusual has just happened */
+ /* exit if not running a command, do not resubmit urb */
+ if (!devpriv->ai_cmd_running)
+ return;
+
switch (urb->status) {
case 0:
/* copy the result in the transfer buffer */
memcpy(devpriv->in_buf, urb->transfer_buffer, SIZEINBUF);
+ usbduxsub_ai_handle_urb(dev, s, urb);
break;
+
case -EILSEQ:
- /* error in the ISOchronous data */
- /* we don't copy the data into the transfer buffer */
- /* and recycle the last data byte */
+ /*
+ * error in the ISOchronous data
+ * we don't copy the data into the transfer buffer
+ * and recycle the last data byte
+ */
dev_dbg(dev->class_dev, "CRC error in ISO IN stream\n");
+ usbduxsub_ai_handle_urb(dev, s, urb);
break;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
case -ECONNABORTED:
- /* happens after an unlink command */
- if (devpriv->ai_cmd_running) {
- s->async->events |= COMEDI_CB_EOA;
- s->async->events |= COMEDI_CB_ERROR;
- comedi_event(dev, s);
- /* stop the transfer w/o unlink */
- usbdux_ai_stop(dev, 0);
- }
- return;
+ /* after an unlink command, unplug, ... etc */
+ async->events |= COMEDI_CB_ERROR;
+ break;
default:
- /* a real error on the bus */
- /* pass error to comedi if we are really running a command */
- if (devpriv->ai_cmd_running) {
- dev_err(dev->class_dev,
- "Non-zero urb status received in ai intr context: %d\n",
- urb->status);
- s->async->events |= COMEDI_CB_EOA;
- s->async->events |= COMEDI_CB_ERROR;
- comedi_event(dev, s);
- /* don't do an unlink here */
- usbdux_ai_stop(dev, 0);
- }
- return;
+ /* a real error */
+ dev_err(dev->class_dev,
+ "Non-zero urb status received in ai intr context: %d\n",
+ urb->status);
+ async->events |= COMEDI_CB_ERROR;
+ break;
}
/*
- * at this point we are reasonably sure that nothing dodgy has happened
- * are we running a command?
+ * comedi_handle_events() cannot be used in this driver. The (*cancel)
+ * operation would unlink the urb.
*/
- if (unlikely(!devpriv->ai_cmd_running)) {
- /*
- * not running a command, do not continue execution if no
- * asynchronous command is running in particular not resubmit
- */
- return;
- }
-
- urb->dev = comedi_to_usb_dev(dev);
-
- /* resubmit the urb */
- err = usb_submit_urb(urb, GFP_ATOMIC);
- if (unlikely(err < 0)) {
- dev_err(dev->class_dev,
- "urb resubmit failed in int-context! err=%d\n", err);
- if (err == -EL2NSYNC)
- dev_err(dev->class_dev,
- "buggy USB host controller or bug in IRQ handler!\n");
- s->async->events |= COMEDI_CB_EOA;
- s->async->events |= COMEDI_CB_ERROR;
- comedi_event(dev, s);
- /* don't do an unlink here */
+ if (async->events & COMEDI_CB_CANCEL_MASK)
usbdux_ai_stop(dev, 0);
- return;
- }
-
- devpriv->ai_counter--;
- if (likely(devpriv->ai_counter > 0))
- return;
-
- /* timer zero, transfer measurements to comedi */
- devpriv->ai_counter = devpriv->ai_timer;
-
- /* test, if we transmit only a fixed number of samples */
- if (cmd->stop_src == TRIG_COUNT) {
- /* not continuous, fixed number of samples */
- devpriv->ai_sample_count--;
- /* all samples received? */
- if (devpriv->ai_sample_count < 0) {
- /* prevent a resubmit next time */
- usbdux_ai_stop(dev, 0);
- /* say comedi that the acquistion is over */
- s->async->events |= COMEDI_CB_EOA;
- comedi_event(dev, s);
- return;
- }
- }
- /* get the data from the USB bus and hand it over to comedi */
- for (i = 0; i < cmd->chanlist_len; i++) {
- unsigned int range = CR_RANGE(cmd->chanlist[i]);
- uint16_t val = le16_to_cpu(devpriv->in_buf[i]);
-
- /* bipolar data is two's-complement */
- if (comedi_range_is_bipolar(s, range))
- val ^= ((s->maxdata + 1) >> 1);
- /* transfer data */
- err = comedi_buf_put(s, val);
- if (unlikely(err == 0)) {
- /* buffer overflow */
- usbdux_ai_stop(dev, 0);
- return;
- }
- }
- /* tell comedi that data is there */
- s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
comedi_event(dev, s);
}
@@ -402,71 +375,25 @@ static int usbdux_ao_cancel(struct comedi_device *dev,
return 0;
}
-static void usbduxsub_ao_isoc_irq(struct urb *urb)
+static void usbduxsub_ao_handle_urb(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct urb *urb)
{
- struct comedi_device *dev = urb->context;
- struct comedi_subdevice *s = dev->write_subdev;
struct usbdux_private *devpriv = dev->private;
- struct comedi_cmd *cmd = &s->async->cmd;
+ struct comedi_async *async = s->async;
+ struct comedi_cmd *cmd = &async->cmd;
uint8_t *datap;
int ret;
int i;
- switch (urb->status) {
- case 0:
- /* success */
- break;
-
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- case -ECONNABORTED:
- /* after an unlink command, unplug, ... etc */
- /* no unlink needed here. Already shutting down. */
- if (devpriv->ao_cmd_running) {
- s->async->events |= COMEDI_CB_EOA;
- comedi_event(dev, s);
- usbdux_ao_stop(dev, 0);
- }
- return;
-
- default:
- /* a real error */
- if (devpriv->ao_cmd_running) {
- dev_err(dev->class_dev,
- "Non-zero urb status received in ao intr context: %d\n",
- urb->status);
- s->async->events |= COMEDI_CB_ERROR;
- s->async->events |= COMEDI_CB_EOA;
- comedi_event(dev, s);
- /* we do an unlink if we are in the high speed mode */
- usbdux_ao_stop(dev, 0);
- }
- return;
- }
-
- /* are we actually running? */
- if (!devpriv->ao_cmd_running)
- return;
-
- /* normal operation: executing a command in this subdevice */
devpriv->ao_counter--;
- if ((int)devpriv->ao_counter <= 0) {
- /* timer zero */
+ if (devpriv->ao_counter == 0) {
devpriv->ao_counter = devpriv->ao_timer;
- /* handle non continous acquisition */
- if (cmd->stop_src == TRIG_COUNT) {
- /* fixed number of samples */
- devpriv->ao_sample_count--;
- if (devpriv->ao_sample_count < 0) {
- /* all samples transmitted */
- usbdux_ao_stop(dev, 0);
- s->async->events |= COMEDI_CB_EOA;
- comedi_event(dev, s);
- /* no resubmit of the urb */
- return;
- }
+ if (cmd->stop_src == TRIG_COUNT &&
+ async->scans_done >= cmd->stop_arg) {
+ async->events |= COMEDI_CB_EOA;
+ return;
}
/* transmit data to the USB bus */
@@ -476,26 +403,25 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb)
unsigned int chan = CR_CHAN(cmd->chanlist[i]);
unsigned short val;
- ret = comedi_buf_get(s, &val);
- if (ret < 0) {
+ if (!comedi_buf_read_samples(s, &val, 1)) {
dev_err(dev->class_dev, "buffer underflow\n");
- s->async->events |= (COMEDI_CB_EOA |
- COMEDI_CB_OVERFLOW);
+ async->events |= COMEDI_CB_OVERFLOW;
+ return;
}
+
/* pointer to the DA */
*datap++ = val & 0xff;
*datap++ = (val >> 8) & 0xff;
*datap++ = chan << 6;
s->readback[chan] = val;
-
- s->async->events |= COMEDI_CB_BLOCK;
- comedi_event(dev, s);
}
}
- urb->transfer_buffer_length = SIZEOUTBUF;
- urb->dev = comedi_to_usb_dev(dev);
- urb->status = 0;
- if (devpriv->ao_cmd_running) {
+
+ /* if command is still running, resubmit urb for BULK transfer */
+ if (!(async->events & COMEDI_CB_CANCEL_MASK)) {
+ urb->transfer_buffer_length = SIZEOUTBUF;
+ urb->dev = comedi_to_usb_dev(dev);
+ urb->status = 0;
if (devpriv->high_speed)
urb->interval = 8; /* uframes */
else
@@ -512,16 +438,54 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb)
if (ret == -EL2NSYNC)
dev_err(dev->class_dev,
"buggy USB host controller or bug in IRQ handling!\n");
-
- s->async->events |= COMEDI_CB_EOA;
- s->async->events |= COMEDI_CB_ERROR;
- comedi_event(dev, s);
- /* don't do an unlink here */
- usbdux_ao_stop(dev, 0);
+ async->events |= COMEDI_CB_ERROR;
}
}
}
+static void usbduxsub_ao_isoc_irq(struct urb *urb)
+{
+ struct comedi_device *dev = urb->context;
+ struct comedi_subdevice *s = dev->write_subdev;
+ struct comedi_async *async = s->async;
+ struct usbdux_private *devpriv = dev->private;
+
+ /* exit if not running a command, do not resubmit urb */
+ if (!devpriv->ao_cmd_running)
+ return;
+
+ switch (urb->status) {
+ case 0:
+ usbduxsub_ao_handle_urb(dev, s, urb);
+ break;
+
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -ECONNABORTED:
+ /* after an unlink command, unplug, ... etc */
+ async->events |= COMEDI_CB_ERROR;
+ break;
+
+ default:
+ /* a real error */
+ dev_err(dev->class_dev,
+ "Non-zero urb status received in ao intr context: %d\n",
+ urb->status);
+ async->events |= COMEDI_CB_ERROR;
+ break;
+ }
+
+ /*
+ * comedi_handle_events() cannot be used in this driver. The (*cancel)
+ * operation would unlink the urb.
+ */
+ if (async->events & COMEDI_CB_CANCEL_MASK)
+ usbdux_ao_stop(dev, 0);
+
+ comedi_event(dev, s);
+}
+
static int usbdux_submit_urbs(struct comedi_device *dev,
struct urb **urbs, int num_urbs,
int input_urb)
@@ -725,9 +689,6 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
if (devpriv->ai_cmd_running)
goto ai_cmd_exit;
- /* set current channel of the running acquisition to zero */
- s->async->cur_chan = 0;
-
devpriv->dux_commands[1] = len;
for (i = 0; i < len; ++i) {
unsigned int chan = CR_CHAN(cmd->chanlist[i]);
@@ -765,14 +726,6 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->ai_counter = devpriv->ai_timer;
- if (cmd->stop_src == TRIG_COUNT) {
- /* data arrives as one packet */
- devpriv->ai_sample_count = cmd->stop_arg;
- } else {
- /* continous acquisition */
- devpriv->ai_sample_count = 0;
- }
-
if (cmd->start_src == TRIG_NOW) {
/* enable this acquisition operation */
devpriv->ai_cmd_running = 1;
@@ -1023,9 +976,6 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
if (devpriv->ao_cmd_running)
goto ao_cmd_exit;
- /* set current channel of the running acquisition to zero */
- s->async->cur_chan = 0;
-
/* we count in steps of 1ms (125us) */
/* 125us mode not used yet */
if (0) { /* (devpriv->high_speed) */
@@ -1044,24 +994,6 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->ao_counter = devpriv->ao_timer;
- if (cmd->stop_src == TRIG_COUNT) {
- /* not continuous */
- /* counter */
- /* high speed also scans everything at once */
- if (0) { /* (devpriv->high_speed) */
- devpriv->ao_sample_count = cmd->stop_arg *
- cmd->scan_end_arg;
- } else {
- /* there's no scan as the scan has been */
- /* perf inside the FX2 */
- /* data arrives as one packet */
- devpriv->ao_sample_count = cmd->stop_arg;
- }
- } else {
- /* continous acquisition */
- devpriv->ao_sample_count = 0;
- }
-
if (cmd->start_src == TRIG_NOW) {
/* enable this acquisition operation */
devpriv->ao_cmd_running = 1;
diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
index f85818dd5e11..ddc4cb9d5ed4 100644
--- a/drivers/staging/comedi/drivers/usbduxfast.c
+++ b/drivers/staging/comedi/drivers/usbduxfast.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004 Bernd Porr, Bernd.Porr@f2s.com
+ * Copyright (C) 2004-2014 Bernd Porr, mail@berndporr.me.uk
*
* 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
@@ -13,6 +13,15 @@
*/
/*
+ * Driver: usbduxfast
+ * Description: University of Stirling USB DAQ & INCITE Technology Limited
+ * Devices: (ITL) USB-DUX [usbduxfast]
+ * Author: Bernd Porr <mail@berndporr.me.uk>
+ * Updated: 10 Oct 2014
+ * Status: stable
+ */
+
+/*
* I must give credit here to Chris Baugher who
* wrote the driver for AT-MIO-16d. I used some parts of this
* driver. I also must give credits to David Brownell
@@ -152,7 +161,6 @@ struct usbduxfast_private {
uint8_t *duxbuf;
int8_t *inbuf;
short int ai_cmd_running; /* asynchronous command is running */
- long int ai_sample_count; /* number of samples to acquire */
int ignore; /* counter which ignores the first
buffers */
struct semaphore sem;
@@ -227,114 +235,82 @@ static int usbduxfast_ai_cancel(struct comedi_device *dev,
return ret;
}
-/*
- * analogue IN
- * interrupt service routine
- */
+static void usbduxfast_ai_handle_urb(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct urb *urb)
+{
+ struct usbduxfast_private *devpriv = dev->private;
+ struct comedi_async *async = s->async;
+ struct comedi_cmd *cmd = &async->cmd;
+ int ret;
+
+ if (devpriv->ignore) {
+ devpriv->ignore--;
+ } else {
+ unsigned int nsamples;
+
+ nsamples = comedi_bytes_to_samples(s, urb->actual_length);
+ nsamples = comedi_nsamples_left(s, nsamples);
+ comedi_buf_write_samples(s, urb->transfer_buffer, nsamples);
+
+ if (cmd->stop_src == TRIG_COUNT &&
+ async->scans_done >= cmd->stop_arg)
+ async->events |= COMEDI_CB_EOA;
+ }
+
+ /* if command is still running, resubmit urb for BULK transfer */
+ if (!(async->events & COMEDI_CB_CANCEL_MASK)) {
+ urb->dev = comedi_to_usb_dev(dev);
+ urb->status = 0;
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret < 0) {
+ dev_err(dev->class_dev, "urb resubm failed: %d", ret);
+ async->events |= COMEDI_CB_ERROR;
+ }
+ }
+}
+
static void usbduxfast_ai_interrupt(struct urb *urb)
{
struct comedi_device *dev = urb->context;
struct comedi_subdevice *s = dev->read_subdev;
struct comedi_async *async = s->async;
- struct comedi_cmd *cmd = &async->cmd;
- struct usb_device *usb = comedi_to_usb_dev(dev);
struct usbduxfast_private *devpriv = dev->private;
- int n, err;
- /* are we running a command? */
- if (unlikely(!devpriv->ai_cmd_running)) {
- /*
- * not running a command
- * do not continue execution if no asynchronous command
- * is running in particular not resubmit
- */
+ /* exit if not running a command, do not resubmit urb */
+ if (!devpriv->ai_cmd_running)
return;
- }
- /* first we test if something unusual has just happened */
switch (urb->status) {
case 0:
+ usbduxfast_ai_handle_urb(dev, s, urb);
break;
- /*
- * happens after an unlink command or when the device
- * is plugged out
- */
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
case -ECONNABORTED:
- /* tell this comedi */
- async->events |= COMEDI_CB_EOA;
+ /* after an unlink command, unplug, ... etc */
async->events |= COMEDI_CB_ERROR;
- comedi_event(dev, s);
- /* stop the transfer w/o unlink */
- usbduxfast_ai_stop(dev, 0);
- return;
+ break;
default:
+ /* a real error */
dev_err(dev->class_dev,
"non-zero urb status received in ai intr context: %d\n",
urb->status);
- async->events |= COMEDI_CB_EOA;
async->events |= COMEDI_CB_ERROR;
- comedi_event(dev, s);
- usbduxfast_ai_stop(dev, 0);
- return;
- }
-
- if (!devpriv->ignore) {
- if (cmd->stop_src == TRIG_COUNT) {
- /* not continuous, fixed number of samples */
- n = urb->actual_length / sizeof(uint16_t);
- if (unlikely(devpriv->ai_sample_count < n)) {
- unsigned int num_bytes;
-
- /* partial sample received */
- num_bytes = devpriv->ai_sample_count *
- sizeof(uint16_t);
- cfc_write_array_to_buffer(s,
- urb->transfer_buffer,
- num_bytes);
- usbduxfast_ai_stop(dev, 0);
- /* tell comedi that the acquistion is over */
- async->events |= COMEDI_CB_EOA;
- comedi_event(dev, s);
- return;
- }
- devpriv->ai_sample_count -= n;
- }
- /* write the full buffer to comedi */
- err = cfc_write_array_to_buffer(s, urb->transfer_buffer,
- urb->actual_length);
- if (unlikely(err == 0)) {
- /* buffer overflow */
- usbduxfast_ai_stop(dev, 0);
- return;
- }
-
- /* tell comedi that data is there */
- comedi_event(dev, s);
- } else {
- /* ignore this packet */
- devpriv->ignore--;
+ break;
}
/*
- * command is still running
- * resubmit urb for BULK transfer
+ * comedi_handle_events() cannot be used in this driver. The (*cancel)
+ * operation would unlink the urb.
*/
- urb->dev = usb;
- urb->status = 0;
- err = usb_submit_urb(urb, GFP_ATOMIC);
- if (err < 0) {
- dev_err(dev->class_dev,
- "urb resubm failed: %d", err);
- async->events |= COMEDI_CB_EOA;
- async->events |= COMEDI_CB_ERROR;
- comedi_event(dev, s);
+ if (async->events & COMEDI_CB_CANCEL_MASK)
usbduxfast_ai_stop(dev, 0);
- }
+
+ comedi_event(dev, s);
}
static int usbduxfast_submit_urb(struct comedi_device *dev)
@@ -499,8 +475,6 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
up(&devpriv->sem);
return -EBUSY;
}
- /* set current channel of the running acquisition to zero */
- s->async->cur_chan = 0;
/*
* ignore the first buffers from the device if there
@@ -810,11 +784,6 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
return result;
}
- if (cmd->stop_src == TRIG_COUNT)
- devpriv->ai_sample_count = cmd->stop_arg * cmd->scan_end_arg;
- else /* TRIG_NONE */
- devpriv->ai_sample_count = 0;
-
if ((cmd->start_src == TRIG_NOW) || (cmd->start_src == TRIG_EXT)) {
/* enable this acquisition operation */
devpriv->ai_cmd_running = 1;
diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c
index ebd68e365bac..dc19435b6520 100644
--- a/drivers/staging/comedi/drivers/usbduxsigma.c
+++ b/drivers/staging/comedi/drivers/usbduxsigma.c
@@ -1,6 +1,6 @@
/*
* usbduxsigma.c
- * Copyright (C) 2011 Bernd Porr, Bernd.Porr@f2s.com
+ * Copyright (C) 2011-2014 Bernd Porr, mail@berndporr.me.uk
*
* 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
@@ -17,9 +17,9 @@
* Driver: usbduxsigma
* Description: University of Stirling USB DAQ & INCITE Technology Limited
* Devices: (ITL) USB-DUX [usbduxsigma]
- * Author: Bernd Porr <BerndPorr@f2s.com>
- * Updated: 8 Nov 2011
- * Status: testing
+ * Author: Bernd Porr <mail@berndporr.me.uk>
+ * Updated: 10 Oct 2014
+ * Status: stable
*/
/*
@@ -164,9 +164,6 @@ struct usbduxsigma_private {
unsigned ao_cmd_running:1;
unsigned pwm_cmd_running:1;
- /* number of samples to acquire */
- int ai_sample_count;
- int ao_sample_count;
/* time between samples in units of the timer */
unsigned int ai_timer;
unsigned int ao_timer;
@@ -211,23 +208,75 @@ static int usbduxsigma_ai_cancel(struct comedi_device *dev,
return 0;
}
-static void usbduxsigma_ai_urb_complete(struct urb *urb)
+static void usbduxsigma_ai_handle_urb(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct urb *urb)
{
- struct comedi_device *dev = urb->context;
struct usbduxsigma_private *devpriv = dev->private;
- struct comedi_subdevice *s = dev->read_subdev;
- struct comedi_cmd *cmd = &s->async->cmd;
+ struct comedi_async *async = s->async;
+ struct comedi_cmd *cmd = &async->cmd;
unsigned int dio_state;
uint32_t val;
int ret;
int i;
- /* first we test if something unusual has just happened */
+ devpriv->ai_counter--;
+ if (devpriv->ai_counter == 0) {
+ devpriv->ai_counter = devpriv->ai_timer;
+
+ /* get the state of the dio pins to allow external trigger */
+ dio_state = be32_to_cpu(devpriv->in_buf[0]);
+
+ /* get the data from the USB bus and hand it over to comedi */
+ for (i = 0; i < cmd->chanlist_len; i++) {
+ /* transfer data, note first byte is the DIO state */
+ val = be32_to_cpu(devpriv->in_buf[i+1]);
+ val &= 0x00ffffff; /* strip status byte */
+ val ^= 0x00800000; /* convert to unsigned */
+
+ if (!comedi_buf_write_samples(s, &val, 1))
+ return;
+ }
+
+ if (cmd->stop_src == TRIG_COUNT &&
+ async->scans_done >= cmd->stop_arg)
+ async->events |= COMEDI_CB_EOA;
+ }
+
+ /* if command is still running, resubmit urb */
+ if (!(async->events & COMEDI_CB_CANCEL_MASK)) {
+ urb->dev = comedi_to_usb_dev(dev);
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret < 0) {
+ dev_err(dev->class_dev,
+ "%s: urb resubmit failed (%d)\n",
+ __func__, ret);
+ if (ret == -EL2NSYNC)
+ dev_err(dev->class_dev,
+ "buggy USB host controller or bug in IRQ handler\n");
+ async->events |= COMEDI_CB_ERROR;
+ }
+ }
+}
+
+static void usbduxsigma_ai_urb_complete(struct urb *urb)
+{
+ struct comedi_device *dev = urb->context;
+ struct usbduxsigma_private *devpriv = dev->private;
+ struct comedi_subdevice *s = dev->read_subdev;
+ struct comedi_async *async = s->async;
+
+ /* exit if not running a command, do not resubmit urb */
+ if (!devpriv->ai_cmd_running)
+ return;
+
switch (urb->status) {
case 0:
/* copy the result in the transfer buffer */
memcpy(devpriv->in_buf, urb->transfer_buffer, SIZEINBUF);
+ usbduxsigma_ai_handle_urb(dev, s, urb);
break;
+
case -EILSEQ:
/*
* error in the ISOchronous data
@@ -235,7 +284,7 @@ static void usbduxsigma_ai_urb_complete(struct urb *urb)
* and recycle the last data byte
*/
dev_dbg(dev->class_dev, "CRC error in ISO IN stream\n");
-
+ usbduxsigma_ai_handle_urb(dev, s, urb);
break;
case -ECONNRESET:
@@ -243,86 +292,24 @@ static void usbduxsigma_ai_urb_complete(struct urb *urb)
case -ESHUTDOWN:
case -ECONNABORTED:
/* happens after an unlink command */
- if (devpriv->ai_cmd_running) {
- usbduxsigma_ai_stop(dev, 0); /* w/o unlink */
- /* we are still running a command, tell comedi */
- s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
- comedi_event(dev, s);
- }
- return;
+ async->events |= COMEDI_CB_ERROR;
+ break;
default:
- /*
- * a real error on the bus
- * pass error to comedi if we are really running a command
- */
- if (devpriv->ai_cmd_running) {
- dev_err(dev->class_dev,
- "%s: non-zero urb status (%d)\n",
- __func__, urb->status);
- usbduxsigma_ai_stop(dev, 0); /* w/o unlink */
- s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
- comedi_event(dev, s);
- }
- return;
- }
-
- if (unlikely(!devpriv->ai_cmd_running))
- return;
-
- urb->dev = comedi_to_usb_dev(dev);
-
- ret = usb_submit_urb(urb, GFP_ATOMIC);
- if (unlikely(ret < 0)) {
- dev_err(dev->class_dev, "%s: urb resubmit failed (%d)\n",
- __func__, ret);
- if (ret == -EL2NSYNC)
- dev_err(dev->class_dev,
- "buggy USB host controller or bug in IRQ handler\n");
- usbduxsigma_ai_stop(dev, 0); /* w/o unlink */
- s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
- comedi_event(dev, s);
- return;
- }
-
- /* get the state of the dio pins to allow external trigger */
- dio_state = be32_to_cpu(devpriv->in_buf[0]);
-
- devpriv->ai_counter--;
- if (likely(devpriv->ai_counter > 0))
- return;
-
- /* timer zero, transfer measurements to comedi */
- devpriv->ai_counter = devpriv->ai_timer;
-
- if (cmd->stop_src == TRIG_COUNT) {
- /* not continuous, fixed number of samples */
- devpriv->ai_sample_count--;
- if (devpriv->ai_sample_count < 0) {
- usbduxsigma_ai_stop(dev, 0); /* w/o unlink */
- /* acquistion is over, tell comedi */
- s->async->events |= COMEDI_CB_EOA;
- comedi_event(dev, s);
- return;
- }
+ /* a real error */
+ dev_err(dev->class_dev, "%s: non-zero urb status (%d)\n",
+ __func__, urb->status);
+ async->events |= COMEDI_CB_ERROR;
+ break;
}
- /* get the data from the USB bus and hand it over to comedi */
- for (i = 0; i < cmd->chanlist_len; i++) {
- /* transfer data, note first byte is the DIO state */
- val = be32_to_cpu(devpriv->in_buf[i+1]);
- val &= 0x00ffffff; /* strip status byte */
- val ^= 0x00800000; /* convert to unsigned */
+ /*
+ * comedi_handle_events() cannot be used in this driver. The (*cancel)
+ * operation would unlink the urb.
+ */
+ if (async->events & COMEDI_CB_CANCEL_MASK)
+ usbduxsigma_ai_stop(dev, 0);
- ret = cfc_write_array_to_buffer(s, &val, sizeof(uint32_t));
- if (unlikely(ret == 0)) {
- /* buffer overflow */
- usbduxsigma_ai_stop(dev, 0); /* w/o unlink */
- return;
- }
- }
- /* tell comedi that data is there */
- s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
comedi_event(dev, s);
}
@@ -349,64 +336,25 @@ static int usbduxsigma_ao_cancel(struct comedi_device *dev,
return 0;
}
-static void usbduxsigma_ao_urb_complete(struct urb *urb)
+static void usbduxsigma_ao_handle_urb(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct urb *urb)
{
- struct comedi_device *dev = urb->context;
struct usbduxsigma_private *devpriv = dev->private;
- struct comedi_subdevice *s = dev->write_subdev;
- struct comedi_cmd *cmd = &s->async->cmd;
+ struct comedi_async *async = s->async;
+ struct comedi_cmd *cmd = &async->cmd;
uint8_t *datap;
int ret;
int i;
- switch (urb->status) {
- case 0:
- /* success */
- break;
-
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- case -ECONNABORTED:
- /* happens after an unlink command */
- if (devpriv->ao_cmd_running) {
- usbduxsigma_ao_stop(dev, 0); /* w/o unlink */
- s->async->events |= COMEDI_CB_EOA;
- comedi_event(dev, s);
- }
- return;
-
- default:
- /* a real error */
- if (devpriv->ao_cmd_running) {
- dev_err(dev->class_dev,
- "%s: non-zero urb status (%d)\n",
- __func__, urb->status);
- usbduxsigma_ao_stop(dev, 0); /* w/o unlink */
- s->async->events |= (COMEDI_CB_ERROR | COMEDI_CB_EOA);
- comedi_event(dev, s);
- }
- return;
- }
-
- if (!devpriv->ao_cmd_running)
- return;
-
devpriv->ao_counter--;
- if ((int)devpriv->ao_counter <= 0) {
- /* timer zero, transfer from comedi */
+ if (devpriv->ao_counter == 0) {
devpriv->ao_counter = devpriv->ao_timer;
- if (cmd->stop_src == TRIG_COUNT) {
- /* not continuous, fixed number of samples */
- devpriv->ao_sample_count--;
- if (devpriv->ao_sample_count < 0) {
- usbduxsigma_ao_stop(dev, 0); /* w/o unlink */
- /* acquistion is over, tell comedi */
- s->async->events |= COMEDI_CB_EOA;
- comedi_event(dev, s);
- return;
- }
+ if (cmd->stop_src == TRIG_COUNT &&
+ async->scans_done >= cmd->stop_arg) {
+ async->events |= COMEDI_CB_EOA;
+ return;
}
/* transmit data to the USB bus */
@@ -416,46 +364,86 @@ static void usbduxsigma_ao_urb_complete(struct urb *urb)
unsigned int chan = CR_CHAN(cmd->chanlist[i]);
unsigned short val;
- ret = comedi_buf_get(s, &val);
- if (ret < 0) {
+ if (!comedi_buf_read_samples(s, &val, 1)) {
dev_err(dev->class_dev, "buffer underflow\n");
- s->async->events |= (COMEDI_CB_EOA |
- COMEDI_CB_OVERFLOW);
+ async->events |= COMEDI_CB_OVERFLOW;
+ return;
}
+
*datap++ = val;
*datap++ = chan;
s->readback[chan] = val;
-
- s->async->events |= COMEDI_CB_BLOCK;
- comedi_event(dev, s);
}
}
- urb->transfer_buffer_length = SIZEOUTBUF;
- urb->dev = comedi_to_usb_dev(dev);
- urb->status = 0;
- if (devpriv->high_speed)
- urb->interval = 8; /* uframes */
- else
- urb->interval = 1; /* frames */
- urb->number_of_packets = 1;
- urb->iso_frame_desc[0].offset = 0;
- urb->iso_frame_desc[0].length = SIZEOUTBUF;
- urb->iso_frame_desc[0].status = 0;
- ret = usb_submit_urb(urb, GFP_ATOMIC);
- if (ret < 0) {
- dev_err(dev->class_dev,
- "%s: urb resubmit failed (%d)\n",
- __func__, ret);
- if (ret == -EL2NSYNC)
+ /* if command is still running, resubmit urb */
+ if (!(async->events & COMEDI_CB_CANCEL_MASK)) {
+ urb->transfer_buffer_length = SIZEOUTBUF;
+ urb->dev = comedi_to_usb_dev(dev);
+ urb->status = 0;
+ if (devpriv->high_speed)
+ urb->interval = 8; /* uframes */
+ else
+ urb->interval = 1; /* frames */
+ urb->number_of_packets = 1;
+ urb->iso_frame_desc[0].offset = 0;
+ urb->iso_frame_desc[0].length = SIZEOUTBUF;
+ urb->iso_frame_desc[0].status = 0;
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret < 0) {
dev_err(dev->class_dev,
- "buggy USB host controller or bug in IRQ handler\n");
- usbduxsigma_ao_stop(dev, 0); /* w/o unlink */
- s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
- comedi_event(dev, s);
+ "%s: urb resubmit failed (%d)\n",
+ __func__, ret);
+ if (ret == -EL2NSYNC)
+ dev_err(dev->class_dev,
+ "buggy USB host controller or bug in IRQ handler\n");
+ async->events |= COMEDI_CB_ERROR;
+ }
}
}
+static void usbduxsigma_ao_urb_complete(struct urb *urb)
+{
+ struct comedi_device *dev = urb->context;
+ struct usbduxsigma_private *devpriv = dev->private;
+ struct comedi_subdevice *s = dev->write_subdev;
+ struct comedi_async *async = s->async;
+
+ /* exit if not running a command, do not resubmit urb */
+ if (!devpriv->ao_cmd_running)
+ return;
+
+ switch (urb->status) {
+ case 0:
+ usbduxsigma_ao_handle_urb(dev, s, urb);
+ break;
+
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -ECONNABORTED:
+ /* happens after an unlink command */
+ async->events |= COMEDI_CB_ERROR;
+ break;
+
+ default:
+ /* a real error */
+ dev_err(dev->class_dev, "%s: non-zero urb status (%d)\n",
+ __func__, urb->status);
+ async->events |= COMEDI_CB_ERROR;
+ break;
+ }
+
+ /*
+ * comedi_handle_events() cannot be used in this driver. The (*cancel)
+ * operation would unlink the urb.
+ */
+ if (async->events & COMEDI_CB_CANCEL_MASK)
+ usbduxsigma_ao_stop(dev, 0);
+
+ comedi_event(dev, s);
+}
+
static int usbduxsigma_submit_urbs(struct comedi_device *dev,
struct urb **urbs, int num_urbs,
int input_urb)
@@ -584,14 +572,6 @@ static int usbduxsigma_ai_cmdtest(struct comedi_device *dev,
if (devpriv->ai_timer < 1)
err |= -EINVAL;
- if (cmd->stop_src == TRIG_COUNT) {
- /* data arrives as one packet */
- devpriv->ai_sample_count = cmd->stop_arg;
- } else {
- /* continuous acquisition */
- devpriv->ai_sample_count = 0;
- }
-
if (err)
return 4;
@@ -692,8 +672,6 @@ static int usbduxsigma_ai_cmd(struct comedi_device *dev,
down(&devpriv->sem);
- /* set current channel of the running acquisition to zero */
- s->async->cur_chan = 0;
for (i = 0; i < len; i++) {
unsigned int chan = CR_CHAN(cmd->chanlist[i]);
@@ -957,25 +935,6 @@ static int usbduxsigma_ao_cmdtest(struct comedi_device *dev,
if (devpriv->ao_timer < 1)
err |= -EINVAL;
- if (cmd->stop_src == TRIG_COUNT) {
- /* not continuous, use counter */
- if (high_speed) {
- /* high speed also scans everything at once */
- devpriv->ao_sample_count = cmd->stop_arg *
- cmd->scan_end_arg;
- } else {
- /*
- * There's no scan as the scan has been
- * handled inside the FX2. Data arrives as
- * one packet.
- */
- devpriv->ao_sample_count = cmd->stop_arg;
- }
- } else {
- /* continuous acquisition */
- devpriv->ao_sample_count = 0;
- }
-
if (err)
return 4;
@@ -991,9 +950,6 @@ static int usbduxsigma_ao_cmd(struct comedi_device *dev,
down(&devpriv->sem);
- /* set current channel of the running acquisition to zero */
- s->async->cur_chan = 0;
-
devpriv->ao_counter = devpriv->ao_timer;
if (cmd->start_src == TRIG_NOW) {
diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c
index 71003416edcf..a19a56ee0eef 100644
--- a/drivers/staging/comedi/drivers/vmk80xx.c
+++ b/drivers/staging/comedi/drivers/vmk80xx.c
@@ -797,7 +797,7 @@ static int vmk80xx_init_subdevices(struct comedi_device *dev)
/* Analog output subdevice */
s = &dev->subdevices[1];
s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE | SDF_GROUND;
+ s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
s->n_chan = boardinfo->ao_nchans;
s->maxdata = 0x00ff;
s->range_table = boardinfo->range;
@@ -819,7 +819,7 @@ static int vmk80xx_init_subdevices(struct comedi_device *dev)
/* Digital output subdevice */
s = &dev->subdevices[3];
s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITEABLE;
+ s->subdev_flags = SDF_WRITABLE;
s->n_chan = 8;
s->maxdata = 1;
s->range_table = &range_digital;
@@ -834,7 +834,7 @@ static int vmk80xx_init_subdevices(struct comedi_device *dev)
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->subdev_flags |= SDF_WRITABLE;
s->insn_write = vmk80xx_cnt_insn_write;
}
@@ -842,7 +842,7 @@ static int vmk80xx_init_subdevices(struct comedi_device *dev)
if (devpriv->model == VMK8061_MODEL) {
s = &dev->subdevices[5];
s->type = COMEDI_SUBD_PWM;
- s->subdev_flags = SDF_READABLE | SDF_WRITEABLE;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = boardinfo->pwm_nchans;
s->maxdata = boardinfo->pwm_maxdata;
s->insn_read = vmk80xx_pwm_insn_read;
diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c
index b6849545b810..9a1dc56f21d1 100644
--- a/drivers/staging/comedi/range.c
+++ b/drivers/staging/comedi/range.c
@@ -97,39 +97,6 @@ int do_rangeinfo_ioctl(struct comedi_device *dev,
return 0;
}
-static int aref_invalid(struct comedi_subdevice *s, unsigned int chanspec)
-{
- unsigned int aref;
-
- /* disable reporting invalid arefs... maybe someday */
- return 0;
-
- aref = CR_AREF(chanspec);
- switch (aref) {
- case AREF_DIFF:
- if (s->subdev_flags & SDF_DIFF)
- return 0;
- break;
- case AREF_COMMON:
- if (s->subdev_flags & SDF_COMMON)
- return 0;
- break;
- case AREF_GROUND:
- if (s->subdev_flags & SDF_GROUND)
- return 0;
- break;
- case AREF_OTHER:
- if (s->subdev_flags & SDF_OTHER)
- return 0;
- break;
- default:
- break;
- }
- dev_dbg(s->device->class_dev, "subdevice does not support aref %i",
- aref);
- return 1;
-}
-
/**
* comedi_check_chanlist() - Validate each element in a chanlist.
* @s: comedi_subdevice struct
@@ -153,8 +120,7 @@ int comedi_check_chanlist(struct comedi_subdevice *s, int n,
else
range_len = 0;
if (chan >= s->n_chan ||
- CR_RANGE(chanspec) >= range_len ||
- aref_invalid(s, chanspec)) {
+ CR_RANGE(chanspec) >= range_len) {
dev_warn(dev->class_dev,
"bad chanlist[%d]=0x%08x chan=%d range length=%d\n",
i, chanspec, chan, range_len);