diff options
author | James Morris <james.l.morris@oracle.com> | 2014-07-17 02:10:27 +1000 |
---|---|---|
committer | James Morris <james.l.morris@oracle.com> | 2014-07-17 02:10:27 +1000 |
commit | bd89bb78f35fd175db7a9cfc504d789b6ca0f7b0 (patch) | |
tree | dee9f8b31f3d6d2fb141541da88e1cc1329b017e /drivers/staging/comedi | |
parent | Merge commit 'v3.15' into next (diff) | |
parent | Linux 3.16-rc5 (diff) | |
download | linux-dev-bd89bb78f35fd175db7a9cfc504d789b6ca0f7b0.tar.xz linux-dev-bd89bb78f35fd175db7a9cfc504d789b6ca0f7b0.zip |
Sync with the changes pushed by Serge in the last merge window.
Diffstat (limited to 'drivers/staging/comedi')
78 files changed, 2397 insertions, 2946 deletions
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 703c5d40ae5c..a2f6957e7ee9 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -160,16 +160,18 @@ config COMEDI_PCL730 Enable support for various simple ISA or PC/104 Digital I/O boards. These boards all use 8-bit I/O ports. - Advantech PCL-730 isolated - 16 in/16 out ttl - 16 in/16 out - ICP ISO-730 isolated - 16 in/16 out ttl - 16 in/16 out - ADlink ACL-7130 isolated - 16 in/16 out ttl - 16 in/16 out - Advantech PCM-3730 isolated - 8 in/8 out ttl - 16 in/16 out - Advantech PCL-725 isolated - 8 in/8 out - ICP P8R8-DIO isolated - 8 in/8 out - ADlink ACL-7225b isolated - 16 in/16 out - ICP P16R16-DIO isolated - 16 in/16 out - Advantech PCL-733 isolated - 32 in - Advantech PCL-734 isolated - 32 out + Advantech PCL-730 iso - 16 in/16 out ttl - 16 in/16 out + ICP ISO-730 iso - 16 in/16 out ttl - 16 in/16 out + ADlink ACL-7130 iso - 16 in/16 out ttl - 16 in/16 out + Advantech PCM-3730 iso - 8 in/8 out ttl - 16 in/16 out + Advantech PCL-725 iso - 8 in/8 out + ICP P8R8-DIO iso - 8 in/8 out + ADlink ACL-7225b iso - 16 in/16 out + ICP P16R16-DIO iso - 16 in/16 out + Advantech PCL-733 iso - 32 in + Advantech PCL-734 iso - 32 out + Diamond Systems OPMM-1616-XT iso - 16 in/16 out + Diamond Systems PEARL-MM-P iso - 16 out To compile this driver as a module, choose M here: the module will be called pcl730. @@ -649,6 +651,7 @@ config COMEDI_ADDI_APCI_1516 config COMEDI_ADDI_APCI_1564 tristate "ADDI-DATA APCI_1564 support" + select COMEDI_ADDI_WATCHDOG ---help--- Enable support for ADDI-DATA APCI_1564 cards diff --git a/drivers/staging/comedi/TODO b/drivers/staging/comedi/TODO index fa8da9aada30..b68fbdb5eebf 100644 --- a/drivers/staging/comedi/TODO +++ b/drivers/staging/comedi/TODO @@ -3,7 +3,6 @@ TODO: - Lindent - remove all wrappers - audit userspace interface - - reserve major number - cleanup the individual comedi drivers as well Please send patches to Greg Kroah-Hartman <greg@kroah.com> and diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c index 257595016161..df4a9c4bca35 100644 --- a/drivers/staging/comedi/comedi_buf.c +++ b/drivers/staging/comedi/comedi_buf.c @@ -183,9 +183,9 @@ comedi_buf_map_from_subdev_get(struct comedi_subdevice *s) return bm; } -bool comedi_buf_is_mmapped(struct comedi_async *async) +bool comedi_buf_is_mmapped(struct comedi_subdevice *s) { - struct comedi_buf_map *bm = async->buf_map; + struct comedi_buf_map *bm = s->async->buf_map; return bm && (atomic_read(&bm->refcount.refcount) > 1); } @@ -222,8 +222,10 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, return 0; } -void comedi_buf_reset(struct comedi_async *async) +void comedi_buf_reset(struct comedi_subdevice *s) { + struct comedi_async *async = s->async; + async->buf_write_alloc_count = 0; async->buf_write_count = 0; async->buf_read_alloc_count = 0; @@ -241,18 +243,20 @@ void comedi_buf_reset(struct comedi_async *async) async->events = 0; } -static unsigned int comedi_buf_write_n_available(struct comedi_async *async) +static unsigned int comedi_buf_write_n_available(struct comedi_subdevice *s) { + struct comedi_async *async = s->async; unsigned int free_end = async->buf_read_count + async->prealloc_bufsz; return free_end - async->buf_write_alloc_count; } -static unsigned int __comedi_buf_write_alloc(struct comedi_async *async, +static unsigned int __comedi_buf_write_alloc(struct comedi_subdevice *s, unsigned int nbytes, int strict) { - unsigned int available = comedi_buf_write_n_available(async); + struct comedi_async *async = s->async; + unsigned int available = comedi_buf_write_n_available(s); if (nbytes > available) nbytes = strict ? 0 : available; @@ -269,10 +273,10 @@ static unsigned int __comedi_buf_write_alloc(struct comedi_async *async, } /* allocates chunk for the writer from free buffer space */ -unsigned int comedi_buf_write_alloc(struct comedi_async *async, +unsigned int comedi_buf_write_alloc(struct comedi_subdevice *s, unsigned int nbytes) { - return __comedi_buf_write_alloc(async, nbytes, 0); + return __comedi_buf_write_alloc(s, nbytes, 0); } EXPORT_SYMBOL_GPL(comedi_buf_write_alloc); @@ -280,10 +284,10 @@ EXPORT_SYMBOL_GPL(comedi_buf_write_alloc); * munging is applied to data by core as it passes between user * and kernel space */ -static unsigned int comedi_buf_munge(struct comedi_async *async, +static unsigned int comedi_buf_munge(struct comedi_subdevice *s, unsigned int num_bytes) { - struct comedi_subdevice *s = async->subdevice; + struct comedi_async *async = s->async; unsigned int count = 0; const unsigned num_sample_bytes = bytes_per_sample(s); @@ -323,23 +327,26 @@ static unsigned int comedi_buf_munge(struct comedi_async *async, return count; } -unsigned int comedi_buf_write_n_allocated(struct comedi_async *async) +unsigned int comedi_buf_write_n_allocated(struct comedi_subdevice *s) { + struct comedi_async *async = s->async; + return async->buf_write_alloc_count - async->buf_write_count; } /* transfers a chunk from writer to filled buffer space */ -unsigned int comedi_buf_write_free(struct comedi_async *async, +unsigned int comedi_buf_write_free(struct comedi_subdevice *s, unsigned int nbytes) { - unsigned int allocated = comedi_buf_write_n_allocated(async); + struct comedi_async *async = s->async; + unsigned int allocated = comedi_buf_write_n_allocated(s); if (nbytes > allocated) nbytes = allocated; async->buf_write_count += nbytes; async->buf_write_ptr += nbytes; - comedi_buf_munge(async, async->buf_write_count - async->munge_count); + comedi_buf_munge(s, async->buf_write_count - async->munge_count); if (async->buf_write_ptr >= async->prealloc_bufsz) async->buf_write_ptr %= async->prealloc_bufsz; @@ -347,8 +354,9 @@ unsigned int comedi_buf_write_free(struct comedi_async *async, } EXPORT_SYMBOL_GPL(comedi_buf_write_free); -unsigned int comedi_buf_read_n_available(struct comedi_async *async) +unsigned int comedi_buf_read_n_available(struct comedi_subdevice *s) { + struct comedi_async *async = s->async; unsigned num_bytes; if (!async) @@ -367,9 +375,10 @@ unsigned int comedi_buf_read_n_available(struct comedi_async *async) EXPORT_SYMBOL_GPL(comedi_buf_read_n_available); /* allocates a chunk for the reader from filled (and munged) buffer space */ -unsigned int comedi_buf_read_alloc(struct comedi_async *async, +unsigned int comedi_buf_read_alloc(struct comedi_subdevice *s, unsigned int nbytes) { + struct comedi_async *async = s->async; unsigned int available; available = async->munge_count - async->buf_read_alloc_count; @@ -394,9 +403,10 @@ static unsigned int comedi_buf_read_n_allocated(struct comedi_async *async) } /* transfers control of a chunk from reader to free buffer space */ -unsigned int comedi_buf_read_free(struct comedi_async *async, +unsigned int comedi_buf_read_free(struct comedi_subdevice *s, unsigned int nbytes) { + struct comedi_async *async = s->async; unsigned int allocated; /* @@ -416,36 +426,39 @@ unsigned int comedi_buf_read_free(struct comedi_async *async, } EXPORT_SYMBOL_GPL(comedi_buf_read_free); -int comedi_buf_put(struct comedi_async *async, unsigned short x) +int comedi_buf_put(struct comedi_subdevice *s, unsigned short x) { - unsigned int n = __comedi_buf_write_alloc(async, sizeof(short), 1); + 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(async, sizeof(short)); + comedi_buf_write_free(s, sizeof(short)); return 1; } EXPORT_SYMBOL_GPL(comedi_buf_put); -int comedi_buf_get(struct comedi_async *async, unsigned short *x) +int comedi_buf_get(struct comedi_subdevice *s, unsigned short *x) { - unsigned int n = comedi_buf_read_n_available(async); + 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(async, sizeof(short)); + comedi_buf_read_alloc(s, sizeof(short)); *x = *(unsigned short *)(async->prealloc_buf + async->buf_read_ptr); - comedi_buf_read_free(async, sizeof(short)); + comedi_buf_read_free(s, sizeof(short)); return 1; } EXPORT_SYMBOL_GPL(comedi_buf_get); -void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset, +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) @@ -469,10 +482,11 @@ void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset, } EXPORT_SYMBOL_GPL(comedi_buf_memcpy_to); -void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset, +void comedi_buf_memcpy_from(struct comedi_subdevice *s, unsigned int offset, 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) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index acc80197e35e..9d99fb3c18a6 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -238,9 +238,9 @@ comedi_write_subdevice(const struct comedi_device *dev, unsigned int minor) } static int resize_async_buffer(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_async *async, unsigned new_size) + struct comedi_subdevice *s, unsigned new_size) { + struct comedi_async *async = s->async; int retval; if (new_size > async->max_bufsize) @@ -251,7 +251,7 @@ static int resize_async_buffer(struct comedi_device *dev, "subdevice is busy, cannot resize buffer\n"); return -EBUSY; } - if (comedi_buf_is_mmapped(async)) { + if (comedi_buf_is_mmapped(s)) { dev_dbg(dev->class_dev, "subdevice is mmapped, cannot resize buffer\n"); return -EBUSY; @@ -380,7 +380,7 @@ static ssize_t read_buffer_kb_store(struct device *csdev, mutex_lock(&dev->mutex); s = comedi_read_subdevice(dev, minor); if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) - err = resize_async_buffer(dev, s, s->async, size); + err = resize_async_buffer(dev, s, size); else err = -EINVAL; mutex_unlock(&dev->mutex); @@ -493,7 +493,7 @@ static ssize_t write_buffer_kb_store(struct device *csdev, mutex_lock(&dev->mutex); s = comedi_write_subdevice(dev, minor); if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) - err = resize_async_buffer(dev, s, s->async, size); + err = resize_async_buffer(dev, s, size); else err = -EINVAL; mutex_unlock(&dev->mutex); @@ -583,7 +583,7 @@ static void do_become_nonbusy(struct comedi_device *dev, comedi_set_subdevice_runflags(s, SRF_RUNNING, 0); if (async) { - comedi_buf_reset(async); + comedi_buf_reset(s); async->inttrig = NULL; kfree(async->cmd.chanlist); async->cmd.chanlist = NULL; @@ -635,7 +635,7 @@ static int is_device_busy(struct comedi_device *dev) s = &dev->subdevices[i]; if (s->busy) return 1; - if (s->async && comedi_buf_is_mmapped(s->async)) + if (s->async && comedi_buf_is_mmapped(s)) return 1; } @@ -668,6 +668,7 @@ static int do_devconfig_ioctl(struct comedi_device *dev, return -EBUSY; if (dev->attached) { struct module *driver_module = dev->driver->module; + comedi_device_detach(dev); module_put(driver_module); } @@ -740,7 +741,7 @@ static int do_bufconfig_ioctl(struct comedi_device *dev, } if (bc.size) { - retval = resize_async_buffer(dev, s, async, bc.size); + retval = resize_async_buffer(dev, s, bc.size); if (retval < 0) return retval; } @@ -992,8 +993,8 @@ static int do_bufinfo_ioctl(struct comedi_device *dev, return -EACCES; if (bi.bytes_read && (s->subdev_flags & SDF_CMD_READ)) { - bi.bytes_read = comedi_buf_read_alloc(async, bi.bytes_read); - comedi_buf_read_free(async, bi.bytes_read); + bi.bytes_read = comedi_buf_read_alloc(s, bi.bytes_read); + comedi_buf_read_free(s, bi.bytes_read); if (comedi_is_subdevice_idle(s) && async->buf_write_count == async->buf_read_count) { @@ -1003,8 +1004,8 @@ static int do_bufinfo_ioctl(struct comedi_device *dev, if (bi.bytes_written && (s->subdev_flags & SDF_CMD_WRITE)) { bi.bytes_written = - comedi_buf_write_alloc(async, bi.bytes_written); - comedi_buf_write_free(async, bi.bytes_written); + comedi_buf_write_alloc(s, bi.bytes_written); + comedi_buf_write_free(s, bi.bytes_written); } copyback_position: @@ -1435,13 +1436,15 @@ static int __comedi_get_user_cmd(struct comedi_device *dev, s = &dev->subdevices[cmd->subdev]; if (s->type == COMEDI_SUBD_UNUSED) { - dev_dbg(dev->class_dev, "%d not valid subdevice\n", cmd->subdev); + dev_dbg(dev->class_dev, "%d not valid subdevice\n", + cmd->subdev); return -EIO; } if (!s->do_cmd || !s->do_cmdtest || !s->async) { dev_dbg(dev->class_dev, - "subdevice %d does not support commands\n", cmd->subdev); + "subdevice %d does not support commands\n", + cmd->subdev); return -EIO; } @@ -1554,7 +1557,7 @@ static int do_cmd_ioctl(struct comedi_device *dev, goto cleanup; } - comedi_buf_reset(async); + comedi_buf_reset(s); async->cb_mask = COMEDI_CB_EOA | COMEDI_CB_BLOCK | COMEDI_CB_ERROR | @@ -1597,7 +1600,6 @@ static int do_cmdtest_ioctl(struct comedi_device *dev, { struct comedi_cmd cmd; struct comedi_subdevice *s; - unsigned int *chanlist = NULL; unsigned int __user *user_chanlist; int ret; @@ -1626,8 +1628,6 @@ static int do_cmdtest_ioctl(struct comedi_device *dev, ret = -EFAULT; } - kfree(chanlist); - return ret; } @@ -2029,18 +2029,18 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait) if (s && s->async) { poll_wait(file, &s->async->wait_head, wait); if (!s->busy || !comedi_is_subdevice_running(s) || - comedi_buf_read_n_available(s->async) > 0) + comedi_buf_read_n_available(s) > 0) mask |= POLLIN | POLLRDNORM; } s = comedi_write_subdevice(dev, minor); if (s && s->async) { - unsigned int bps = bytes_per_sample(s->async->subdevice); + unsigned int bps = bytes_per_sample(s); poll_wait(file, &s->async->wait_head, wait); - comedi_buf_write_alloc(s->async, s->async->prealloc_bufsz); + comedi_buf_write_alloc(s, s->async->prealloc_bufsz); if (!s->busy || !comedi_is_subdevice_running(s) || - comedi_buf_write_n_allocated(s->async) >= bps) + comedi_buf_write_n_allocated(s) >= bps) mask |= POLLOUT | POLLWRNORM; } @@ -2136,9 +2136,9 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, m = n; if (async->buf_write_ptr + m > async->prealloc_bufsz) m = async->prealloc_bufsz - async->buf_write_ptr; - comedi_buf_write_alloc(async, async->prealloc_bufsz); - if (m > comedi_buf_write_n_allocated(async)) - m = comedi_buf_write_n_allocated(async); + comedi_buf_write_alloc(s, async->prealloc_bufsz); + if (m > comedi_buf_write_n_allocated(s)) + m = comedi_buf_write_n_allocated(s); if (m < n) n = m; @@ -2167,7 +2167,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, n -= m; retval = -EFAULT; } - comedi_buf_write_free(async, n); + comedi_buf_write_free(s, n); count += n; nbytes -= n; @@ -2229,7 +2229,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, n = nbytes; - m = comedi_buf_read_n_available(async); + m = comedi_buf_read_n_available(s); /* printk("%d available\n",m); */ if (async->buf_read_ptr + m > async->prealloc_bufsz) m = async->prealloc_bufsz - async->buf_read_ptr; @@ -2272,8 +2272,8 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, retval = -EFAULT; } - comedi_buf_read_alloc(async, n); - comedi_buf_read_free(async, n); + comedi_buf_read_alloc(s, n); + comedi_buf_read_free(s, n); count += n; nbytes -= n; @@ -2327,46 +2327,12 @@ static int comedi_open(struct inode *inode, struct file *file) return -ENODEV; } - /* This is slightly hacky, but we want module autoloading - * to work for root. - * case: user opens device, attached -> ok - * case: user opens device, unattached, !in_request_module -> autoload - * case: user opens device, unattached, in_request_module -> fail - * case: root opens device, attached -> ok - * case: root opens device, unattached, in_request_module -> ok - * (typically called from modprobe) - * case: root opens device, unattached, !in_request_module -> autoload - * - * The last could be changed to "-> ok", which would deny root - * autoloading. - */ - mutex_lock(&dev->mutex); - if (dev->attached) - goto ok; - if (!capable(CAP_NET_ADMIN) && dev->in_request_module) { - dev_dbg(dev->class_dev, "in request module\n"); - rc = -ENODEV; - goto out; - } - if (capable(CAP_NET_ADMIN) && dev->in_request_module) - goto ok; - - dev->in_request_module = true; - -#ifdef CONFIG_KMOD - mutex_unlock(&dev->mutex); - request_module("char-major-%i-%i", COMEDI_MAJOR, dev->minor); mutex_lock(&dev->mutex); -#endif - - dev->in_request_module = false; - if (!dev->attached && !capable(CAP_NET_ADMIN)) { dev_dbg(dev->class_dev, "not attached and not CAP_NET_ADMIN\n"); rc = -ENODEV; goto out; } -ok: if (dev->attached && dev->use_count == 0) { if (!try_module_get(dev->driver->module)) { rc = -ENOSYS; @@ -2654,6 +2620,7 @@ static int __init comedi_init(void) /* create devices files for legacy/manual use */ for (i = 0; i < comedi_num_legacy_minors; i++) { struct comedi_device *dev; + dev = comedi_alloc_board_minor(NULL); if (IS_ERR(dev)) { comedi_cleanup_board_minors(); diff --git a/drivers/staging/comedi/comedi_internal.h b/drivers/staging/comedi/comedi_internal.h index a492f2d2436e..e978c223f5b5 100644 --- a/drivers/staging/comedi/comedi_internal.h +++ b/drivers/staging/comedi/comedi_internal.h @@ -15,13 +15,13 @@ void comedi_free_subdevice_minor(struct comedi_subdevice *s); int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long new_size); -void comedi_buf_reset(struct comedi_async *async); -bool comedi_buf_is_mmapped(struct comedi_async *async); +void comedi_buf_reset(struct comedi_subdevice *s); +bool comedi_buf_is_mmapped(struct comedi_subdevice *s); void comedi_buf_map_get(struct comedi_buf_map *bm); int comedi_buf_map_put(struct comedi_buf_map *bm); struct comedi_buf_map *comedi_buf_map_from_subdev_get( struct comedi_subdevice *s); -unsigned int comedi_buf_write_n_allocated(struct comedi_async *async); +unsigned int comedi_buf_write_n_allocated(struct comedi_subdevice *s); void comedi_device_cancel_all(struct comedi_device *dev); extern unsigned int comedi_default_buf_size_kb; diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index d46123a97582..8f4e44bfbe00 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -108,8 +108,6 @@ struct comedi_buf_map { }; struct comedi_async { - struct comedi_subdevice *subdevice; - void *prealloc_buf; /* pre-allocated buffer */ unsigned int prealloc_bufsz; /* buffer size, in bytes */ struct comedi_buf_map *buf_map; /* map of buffer pages */ @@ -182,7 +180,6 @@ struct comedi_device { const char *board_name; const void *board_ptr; bool attached:1; - bool in_request_module:1; bool ioenabled:1; spinlock_t spinlock; struct mutex mutex; @@ -336,19 +333,19 @@ static inline unsigned int bytes_per_sample(const struct comedi_subdevice *subd) */ int comedi_set_hw_dev(struct comedi_device *dev, struct device *hw_dev); -unsigned int comedi_buf_write_alloc(struct comedi_async *, unsigned int); -unsigned int comedi_buf_write_free(struct comedi_async *, unsigned int); +unsigned int comedi_buf_write_alloc(struct comedi_subdevice *s, unsigned int n); +unsigned int comedi_buf_write_free(struct comedi_subdevice *s, unsigned int n); -unsigned int comedi_buf_read_n_available(struct comedi_async *); -unsigned int comedi_buf_read_alloc(struct comedi_async *, unsigned int); -unsigned int comedi_buf_read_free(struct comedi_async *, unsigned int); +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_async *, unsigned short); -int comedi_buf_get(struct comedi_async *, unsigned short *); +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_async *async, unsigned int offset, +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_async *async, unsigned int offset, +void comedi_buf_memcpy_from(struct comedi_subdevice *s, unsigned int offset, void *destination, unsigned int num_bytes); /* drivers.c - general comedi driver functions */ diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index ab0e8ed47291..299726f39e26 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -258,6 +258,7 @@ static int insn_rw_emulate_bits(struct comedi_device *dev, const unsigned base_bitfield_channel = (chan < channels_per_bitfield) ? 0 : chan; unsigned int new_data[2]; + memset(new_data, 0, sizeof(new_data)); memset(&new_insn, 0, sizeof(new_insn)); new_insn.insn = INSN_BITS; @@ -306,7 +307,6 @@ static int __comedi_device_postconfig_async(struct comedi_device *dev, return -ENOMEM; init_waitqueue_head(&async->wait_head); - async->subdevice = s; s->async = async; async->max_bufsize = comedi_default_buf_maxsize_kb * 1024; diff --git a/drivers/staging/comedi/drivers/8253.h b/drivers/staging/comedi/drivers/8253.h index e3d737cf7302..5829b46b757b 100644 --- a/drivers/staging/comedi/drivers/8253.h +++ b/drivers/staging/comedi/drivers/8253.h @@ -30,106 +30,11 @@ #define I8254_OSC_BASE_2MHZ 500 #define I8254_OSC_BASE_1MHZ 1000 -#define i8253_cascade_ns_to_timer i8253_cascade_ns_to_timer_2div - -static inline void i8253_cascade_ns_to_timer_2div_old(int i8253_osc_base, - unsigned int *d1, - unsigned int *d2, - unsigned int *nanosec, - int round_mode) -{ - int divider; - int div1, div2; - int div1_glb, div2_glb, ns_glb; - int div1_lub, div2_lub, ns_lub; - int ns; - - divider = (*nanosec + i8253_osc_base / 2) / i8253_osc_base; - - /* find 2 integers 1<={x,y}<=65536 such that x*y is - close to divider */ - - div1_lub = div2_lub = 0; - div1_glb = div2_glb = 0; - - ns_glb = 0; - ns_lub = 0xffffffff; - - div2 = 0x10000; - for (div1 = divider / 65536 + 1; div1 < div2; div1++) { - div2 = divider / div1; - - ns = i8253_osc_base * div1 * div2; - if (ns <= *nanosec && ns > ns_glb) { - ns_glb = ns; - div1_glb = div1; - div2_glb = div2; - } - - div2++; - if (div2 <= 65536) { - ns = i8253_osc_base * div1 * div2; - if (ns > *nanosec && ns < ns_lub) { - ns_lub = ns; - div1_lub = div1; - div2_lub = div2; - } - } - } - - *nanosec = div1_lub * div2_lub * i8253_osc_base; - *d1 = div1_lub & 0xffff; - *d2 = div2_lub & 0xffff; - return; -} - -static inline void i8253_cascade_ns_to_timer_power(int i8253_osc_base, - unsigned int *d1, - unsigned int *d2, - unsigned int *nanosec, - int round_mode) -{ - int div1, div2; - int base; - - for (div1 = 2; div1 <= (1 << 16); div1 <<= 1) { - base = i8253_osc_base * div1; - round_mode &= TRIG_ROUND_MASK; - switch (round_mode) { - case TRIG_ROUND_NEAREST: - default: - div2 = (*nanosec + base / 2) / base; - break; - case TRIG_ROUND_DOWN: - div2 = (*nanosec) / base; - break; - case TRIG_ROUND_UP: - div2 = (*nanosec + base - 1) / base; - break; - } - if (div2 < 2) - div2 = 2; - if (div2 <= 65536) { - *nanosec = div2 * base; - *d1 = div1 & 0xffff; - *d2 = div2 & 0xffff; - return; - } - } - - /* shouldn't get here */ - div1 = 0x10000; - div2 = 0x10000; - *nanosec = div1 * div2 * i8253_osc_base; - *d1 = div1 & 0xffff; - *d2 = div2 & 0xffff; -} - -static inline void i8253_cascade_ns_to_timer_2div(int i8253_osc_base, - unsigned int *d1, - unsigned int *d2, - unsigned int *nanosec, - int round_mode) +static inline void i8253_cascade_ns_to_timer(int i8253_osc_base, + unsigned int *d1, + unsigned int *d2, + unsigned int *nanosec, + int round_mode) { unsigned int divider; unsigned int div1, div2; @@ -386,7 +291,7 @@ static inline int i8254_set_mode(unsigned long base_address, if (counter_number > 2) return -1; - if (mode > (I8254_MODE5 | I8254_BINARY)) + if (mode > (I8254_MODE5 | I8254_BCD)) return -1; byte = counter_number << 6; @@ -406,7 +311,7 @@ static inline int i8254_mm_set_mode(void __iomem *base_address, if (counter_number > 2) return -1; - if (mode > (I8254_MODE5 | I8254_BINARY)) + if (mode > (I8254_MODE5 | I8254_BCD)) return -1; byte = counter_number << 6; diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 48817f087d97..46113a374133 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -117,7 +117,7 @@ void subdev_8255_interrupt(struct comedi_device *dev, d = spriv->io(0, _8255_DATA, 0, iobase); d |= (spriv->io(0, _8255_DATA + 1, 0, iobase) << 8); - comedi_buf_put(s->async, d); + comedi_buf_put(s, d); s->async->events |= COMEDI_CB_EOS; comedi_event(dev, s); @@ -231,7 +231,7 @@ static int subdev_8255_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); - err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, 1); + err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); if (err) @@ -298,6 +298,7 @@ int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice *s, if (ret) return ret; + s->len_chanlist = 1; s->do_cmdtest = subdev_8255_cmdtest; s->do_cmd = subdev_8255_cmd; s->cancel = subdev_8255_cancel; diff --git a/drivers/staging/comedi/drivers/8255.h b/drivers/staging/comedi/drivers/8255.h index 4f16ea78f86a..795d232a6c02 100644 --- a/drivers/staging/comedi/drivers/8255.h +++ b/drivers/staging/comedi/drivers/8255.h @@ -22,10 +22,10 @@ #include "../comedidev.h" int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, - int (*io) (int, int, int, unsigned long), + int (*io)(int, int, int, unsigned long), unsigned long iobase); int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice *s, - int (*io) (int, int, int, unsigned long), + int (*io)(int, int, int, unsigned long), unsigned long iobase); void subdev_8255_interrupt(struct comedi_device *dev, struct comedi_subdevice *s); diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h index 2ed2da3499f4..5c6a11c35ded 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_common.h +++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h @@ -118,18 +118,10 @@ struct addi_private { int i_IobaseAmcc; /* base+size for AMCC chip */ int i_IobaseAddon; /* addon base address */ int i_IobaseReserved; - unsigned char b_AiContinuous; /* we do unlimited AI */ unsigned int ui_AiActualScan; /* how many scans we finished */ unsigned int ui_AiNbrofChannels; /* how many channels is measured */ - unsigned int ui_AiScanLength; /* Length of actual scanlist */ - unsigned int *pui_AiChannelList; /* actual chanlist */ unsigned int ui_AiChannelList[32]; /* actual chanlist */ unsigned int ui_AiReadData[32]; - unsigned int ui_AiTimer0; /* Timer Constant for Timer0 */ - unsigned int ui_AiTimer1; /* Timer constant for Timer1 */ - unsigned int ui_AiFlags; - unsigned int ui_AiDataLength; - unsigned int ui_AiNbrofScans; /* number of scans to do */ unsigned short us_UseDma; /* To use Dma or not */ unsigned char b_DmaDoubleBuffer; /* we can use double buffering */ unsigned int ui_DmaActualBuffer; /* which buffer is used now */ @@ -145,7 +137,7 @@ struct addi_private { 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 char b_AiCyclicAcquisition; /* indicate cyclic acquisition */ + 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; diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c index 9c86b02eb6da..0ba5385226ae 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c @@ -21,6 +21,8 @@ * */ +#include "../addi_watchdog.h" + #define APCI1564_ADDRESS_RANGE 128 /* Digital Input IRQ Function Selection */ @@ -76,7 +78,7 @@ #define APCI1564_TIMER_WARN_TIMEBASE_REG 0x64 /* - * devpriv->iobase Register Map + * dev>iobase Register Map */ #define APCI1564_TCW_REG(x) (0x00 + ((x) * 0x20)) #define APCI1564_TCW_RELOAD_REG(x) (0x04 + ((x) * 0x20)) @@ -127,18 +129,6 @@ static int apci1564_di_config(struct comedi_device *dev, return insn->n; } -static int apci1564_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_IobaseAmcc + APCI1564_DI_REG); - - return insn->n; -} - /* * Configures The Digital Output Subdevice. * @@ -180,23 +170,6 @@ static int apci1564_do_config(struct comedi_device *dev, return insn->n; } -static int apci1564_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_IobaseAmcc + APCI1564_DO_REG); - - if (comedi_dio_update_state(s, data)) - outl(s->state, devpriv->i_IobaseAmcc + APCI1564_DO_REG); - - data[1] = s->state; - - return insn->n; -} - /* * Configures The Timer, Counter or Watchdog * @@ -239,13 +212,13 @@ static int apci1564_timer_config(struct comedi_device *dev, outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DO_IRQ_REG); outl(0x0, devpriv->i_IobaseAmcc + APCI1564_WDOG_IRQ_REG); outl(0x0, - devpriv->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER1)); + dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER1)); outl(0x0, - devpriv->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER2)); + dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER2)); outl(0x0, - devpriv->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER3)); + dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER3)); outl(0x0, - devpriv->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER4)); + dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER4)); } else { /* disable Timer interrupt */ outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG); @@ -266,13 +239,13 @@ static int apci1564_timer_config(struct comedi_device *dev, devpriv->b_ModeSelectRegister = data[5]; /* First Stop The Counter */ - ul_Command1 = inl(devpriv->iobase + APCI1564_TCW_CTRL_REG(data[5] - 1)); + ul_Command1 = inl(dev->iobase + APCI1564_TCW_CTRL_REG(data[5] - 1)); ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; /* Stop The Timer */ - outl(ul_Command1, devpriv->iobase + APCI1564_TCW_CTRL_REG(data[5] - 1)); + outl(ul_Command1, dev->iobase + APCI1564_TCW_CTRL_REG(data[5] - 1)); /* Set the reload value */ - outl(data[3], devpriv->iobase + APCI1564_TCW_RELOAD_REG(data[5] - 1)); + outl(data[3], dev->iobase + APCI1564_TCW_RELOAD_REG(data[5] - 1)); /* Set the mode : */ /* - Disable the hardware */ @@ -285,15 +258,15 @@ static int apci1564_timer_config(struct comedi_device *dev, ul_Command1 = (ul_Command1 & 0xFFFC19E2UL) | 0x80000UL | (unsigned int) ((unsigned int) data[4] << 16UL); - outl(ul_Command1, devpriv->iobase + APCI1564_TCW_CTRL_REG(data[5] - 1)); + outl(ul_Command1, dev->iobase + APCI1564_TCW_CTRL_REG(data[5] - 1)); /* Enable or Disable Interrupt */ ul_Command1 = (ul_Command1 & 0xFFFFF9FD) | (data[1] << 1); - outl(ul_Command1, devpriv->iobase + APCI1564_TCW_CTRL_REG(data[5] - 1)); + outl(ul_Command1, dev->iobase + APCI1564_TCW_CTRL_REG(data[5] - 1)); /* Set the Up/Down selection */ ul_Command1 = (ul_Command1 & 0xFFFBF9FFUL) | (data[6] << 18); - outl(ul_Command1, devpriv->iobase + APCI1564_TCW_CTRL_REG(data[5] - 1)); + outl(ul_Command1, dev->iobase + APCI1564_TCW_CTRL_REG(data[5] - 1)); } else { dev_err(dev->class_dev, "Invalid subdevice.\n"); } @@ -349,8 +322,8 @@ static int apci1564_timer_write(struct comedi_device *dev, } if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) { ul_Command1 = - inl(devpriv->iobase + - APCI1564_TCW_CTRL_REG(devpriv->b_ModeSelectRegister - 1)); + inl(dev->iobase + + APCI1564_TCW_CTRL_REG(devpriv->b_ModeSelectRegister - 1)); if (data[1] == 1) { /* Start the Counter subdevice */ ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL; @@ -362,9 +335,8 @@ static int apci1564_timer_write(struct comedi_device *dev, /* Clears the Counter subdevice */ ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x400; } - outl(ul_Command1, - devpriv->iobase + - APCI1564_TCW_CTRL_REG(devpriv->b_ModeSelectRegister - 1)); + outl(ul_Command1, dev->iobase + + APCI1564_TCW_CTRL_REG(devpriv->b_ModeSelectRegister - 1)); } return insn->n; } @@ -393,11 +365,11 @@ static int apci1564_timer_read(struct comedi_device *dev, } else if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) { /* Read the Counter Actual Value. */ data[0] = - inl(devpriv->iobase + - APCI1564_TCW_REG(devpriv->b_ModeSelectRegister - 1)); + inl(dev->iobase + + APCI1564_TCW_REG(devpriv->b_ModeSelectRegister - 1)); ul_Command1 = - inl(devpriv->iobase + - APCI1564_TCW_STATUS_REG(devpriv->b_ModeSelectRegister - 1)); + inl(dev->iobase + + APCI1564_TCW_STATUS_REG(devpriv->b_ModeSelectRegister - 1)); /* Get the software trigger status */ data[1] = (unsigned char) ((ul_Command1 >> 1) & 1); @@ -446,13 +418,13 @@ static void apci1564_interrupt(int irq, void *d) ui_DO = inl(devpriv->i_IobaseAmcc + APCI1564_DO_IRQ_REG) & 0x01; ui_Timer = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER_IRQ_REG) & 0x01; ui_C1 = - inl(devpriv->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER1)) & 0x1; + inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER1)) & 0x1; ui_C2 = - inl(devpriv->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER2)) & 0x1; + inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER2)) & 0x1; ui_C3 = - inl(devpriv->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER3)) & 0x1; + inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER3)) & 0x1; ui_C4 = - inl(devpriv->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER4)) & 0x1; + inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER4)) & 0x1; if (ui_DI == 0 && ui_DO == 0 && ui_Timer == 0 && ui_C1 == 0 && ui_C2 == 0 && ui_C3 == 0 && ui_C4 == 0) { dev_err(dev->class_dev, "Interrupt from unknown source.\n"); @@ -506,16 +478,16 @@ static void apci1564_interrupt(int irq, void *d) /* Disable Counter Interrupt */ ul_Command2 = - inl(devpriv->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1)); + inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1)); outl(0x0, - devpriv->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1)); + dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1)); /* Send a signal to from kernel to user space */ send_sig(SIGIO, devpriv->tsk_Current, 0); /* Enable Counter Interrupt */ outl(ul_Command2, - devpriv->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1)); + dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1)); } } @@ -525,16 +497,16 @@ static void apci1564_interrupt(int irq, void *d) /* Disable Counter Interrupt */ ul_Command2 = - inl(devpriv->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2)); + inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2)); outl(0x0, - devpriv->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2)); + dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2)); /* Send a signal to from kernel to user space */ send_sig(SIGIO, devpriv->tsk_Current, 0); /* Enable Counter Interrupt */ outl(ul_Command2, - devpriv->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2)); + dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2)); } } @@ -544,16 +516,16 @@ static void apci1564_interrupt(int irq, void *d) /* Disable Counter Interrupt */ ul_Command2 = - inl(devpriv->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3)); + inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3)); outl(0x0, - devpriv->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3)); + dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3)); /* Send a signal to from kernel to user space */ send_sig(SIGIO, devpriv->tsk_Current, 0); /* Enable Counter Interrupt */ outl(ul_Command2, - devpriv->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3)); + dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3)); } } @@ -563,45 +535,17 @@ static void apci1564_interrupt(int irq, void *d) /* Disable Counter Interrupt */ ul_Command2 = - inl(devpriv->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4)); + inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4)); outl(0x0, - devpriv->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4)); + dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4)); /* Send a signal to from kernel to user space */ send_sig(SIGIO, devpriv->tsk_Current, 0); /* Enable Counter Interrupt */ outl(ul_Command2, - devpriv->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4)); + dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4)); } } return; } - -static int apci1564_reset(struct comedi_device *dev) -{ - struct addi_private *devpriv = dev->private; - - /* disable the interrupts */ - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG); - /* Reset the interrupt status register */ - inl(devpriv->i_IobaseAmcc + APCI1564_DI_INT_STATUS_REG); - /* Disable the and/or interrupt */ - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_INT_MODE1_REG); - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_INT_MODE2_REG); - devpriv->b_DigitalOutputRegister = 0; - ui_Type = 0; - /* Resets the output channels */ - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DO_REG); - /* Disables the interrupt. */ - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DO_INT_CTRL_REG); - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_WDOG_RELOAD_REG); - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER_REG); - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG); - - outl(0x0, devpriv->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1)); - outl(0x0, devpriv->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2)); - outl(0x0, devpriv->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3)); - outl(0x0, devpriv->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4)); - return 0; -} diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c index 70e8f426285c..764c8f17f8fa 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c @@ -609,11 +609,10 @@ static int apci3120_reset(struct comedi_device *dev) unsigned int i; unsigned short us_TmpValue; - devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE; + 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 */ - devpriv->b_OutputMemoryStatus = 0; /* variables used in timer subdevice */ devpriv->b_Timer2Mode = 0; @@ -720,10 +719,9 @@ static int apci3120_cancel(struct comedi_device *dev, inw(dev->iobase + APCI3120_RD_STATUS); devpriv->ui_AiActualScan = 0; s->async->cur_chan = 0; - devpriv->b_AiContinuous = 0; devpriv->ui_DmaActualBuffer = 0; - devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE; + devpriv->ai_running = 0; devpriv->b_InterruptMode = APCI3120_EOC_MODE; devpriv->b_EocEosInterrupt = APCI3120_DISABLE; apci3120_reset(dev); @@ -734,7 +732,6 @@ static int apci3120_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct addi_board *this_board = comedi_board(dev); int err = 0; /* Step 1 : check if triggers are trivially valid */ @@ -767,20 +764,16 @@ static int apci3120_ai_cmdtest(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER) /* Test Delay timing */ err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, 100000); - if (cmd->convert_src == TRIG_TIMER) { /* Test Acquisition timing */ - if (cmd->scan_begin_src == TRIG_TIMER) { - if (cmd->convert_arg) - err |= cfc_check_trigger_arg_min( - &cmd->convert_arg, 10000); - } else { + if (cmd->scan_begin_src == TRIG_TIMER) { + if (cmd->convert_arg) err |= cfc_check_trigger_arg_min(&cmd->convert_arg, - 10000); - } + 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_max(&cmd->chanlist_len, - this_board->i_AiChannelList); + 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); @@ -792,15 +785,10 @@ static int apci3120_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ - if (cmd->convert_src == TRIG_TIMER) { - - 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++; - } + 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) @@ -821,16 +809,13 @@ static int apci3120_cyclic_ai(int mode, { const struct addi_board *this_board = comedi_board(dev); 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; - /* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */ - /* devpriv->b_AiCyclicAcquisition=APCI3120_ENABLE; */ - /* END JK 07.05.04: Comparison between WIN32 and Linux driver */ - /*******************/ /* Resets the FIFO */ /*******************/ @@ -840,12 +825,7 @@ static int apci3120_cyclic_ai(int mode, /* inw(dev->iobase+APCI3120_RD_STATUS); */ /* END JK 07.05.04: Comparison between WIN32 and Linux driver */ - /***************************/ - /* Acquisition initialized */ - /***************************/ - /* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */ - devpriv->b_AiCyclicAcquisition = APCI3120_ENABLE; - /* END JK 07.05.04: Comparison between WIN32 and Linux driver */ + devpriv->ai_running = 1; /* clear software registers */ devpriv->b_TimerSelectMode = 0; @@ -892,17 +872,17 @@ static int apci3120_cyclic_ai(int mode, devpriv->ui_DmaActualBuffer = 0; /* value for timer2 minus -2 has to be done .....dunno y?? */ - ui_TimerValue2 = devpriv->ui_AiNbrofScans - 2; - ui_ConvertTiming = devpriv->ui_AiTimer0; + ui_TimerValue2 = cmd->stop_arg - 2; + ui_ConvertTiming = cmd->convert_arg; if (mode == 2) - ui_DelayTiming = devpriv->ui_AiTimer1; + ui_DelayTiming = cmd->scan_begin_arg; /**********************************/ /* Initializes the sequence array */ /**********************************/ if (!apci3120_setup_chan_list(dev, s, devpriv->ui_AiNbrofChannels, - devpriv->pui_AiChannelList, 0)) + cmd->chanlist, 0)) return -EINVAL; us_TmpValue = (unsigned short) inw(dev->iobase + APCI3120_RD_STATUS); @@ -1039,7 +1019,7 @@ static int apci3120_cyclic_ai(int mode, outb(devpriv->b_ModeSelectRegister, dev->iobase + APCI3120_WRITE_MODE_SELECT); - if (!devpriv->b_AiContinuous) { + 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) @@ -1107,6 +1087,7 @@ static int apci3120_cyclic_ai(int mode, } } else { /* If DMA Enabled */ + unsigned int scan_bytes = cmd->scan_end_arg * sizeof(short); /* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */ /* inw(dev->iobase+0); reset EOC bit */ @@ -1125,37 +1106,38 @@ static int apci3120_cyclic_ai(int mode, dmalen0 = devpriv->ui_DmaBufferSize[0]; dmalen1 = devpriv->ui_DmaBufferSize[1]; - if (!devpriv->b_AiContinuous) { - - if (dmalen0 > (devpriv->ui_AiNbrofScans * devpriv->ui_AiScanLength * 2)) { /* must we fill full first buffer? */ - dmalen0 = - devpriv->ui_AiNbrofScans * - devpriv->ui_AiScanLength * 2; - } else if (dmalen1 > (devpriv->ui_AiNbrofScans * devpriv->ui_AiScanLength * 2 - dmalen0)) /* and must we fill full second buffer when first is once filled? */ - dmalen1 = - devpriv->ui_AiNbrofScans * - devpriv->ui_AiScanLength * 2 - dmalen0; + 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 (devpriv->ui_AiFlags & TRIG_WAKE_EOS) { + if (cmd->flags & TRIG_WAKE_EOS) { /* don't we want wake up every scan? */ - if (dmalen0 > (devpriv->ui_AiScanLength * 2)) { - dmalen0 = devpriv->ui_AiScanLength * 2; - if (devpriv->ui_AiScanLength & 1) + if (dmalen0 > scan_bytes) { + dmalen0 = scan_bytes; + if (cmd->scan_end_arg & 1) dmalen0 += 2; } - if (dmalen1 > (devpriv->ui_AiScanLength * 2)) { - dmalen1 = devpriv->ui_AiScanLength * 2; - if (devpriv->ui_AiScanLength & 1) + 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 > (devpriv->ui_AiDataLength)) - dmalen0 = devpriv->ui_AiDataLength; - if (dmalen1 > (devpriv->ui_AiDataLength)) - dmalen1 = devpriv->ui_AiDataLength; + 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; @@ -1293,8 +1275,8 @@ static int apci3120_cyclic_ai(int mode, /* END JK 07.05.04: Comparison between WIN32 and Linux driver */ } - if ((devpriv->us_UseDma == APCI3120_DISABLE) - && !devpriv->b_AiContinuous) { + 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; @@ -1337,50 +1319,17 @@ static int apci3120_ai_cmd(struct comedi_device *dev, struct comedi_cmd *cmd = &s->async->cmd; /* loading private structure with cmd structure inputs */ - devpriv->ui_AiFlags = cmd->flags; devpriv->ui_AiNbrofChannels = cmd->chanlist_len; - devpriv->ui_AiScanLength = cmd->scan_end_arg; - devpriv->pui_AiChannelList = cmd->chanlist; - - /* UPDATE-0.7.57->0.7.68devpriv->ui_AiDataLength=s->async->data_len; */ - devpriv->ui_AiDataLength = s->async->prealloc_bufsz; - - if (cmd->stop_src == TRIG_COUNT) - devpriv->ui_AiNbrofScans = cmd->stop_arg; - else - devpriv->ui_AiNbrofScans = 0; - - devpriv->ui_AiTimer0 = 0; /* variables changed to timer0,timer1 */ - devpriv->ui_AiTimer1 = 0; - if ((devpriv->ui_AiNbrofScans == 0) || (devpriv->ui_AiNbrofScans == -1)) - devpriv->b_AiContinuous = 1; /* user want neverending analog acquisition */ - /* stopped using cancel */ if (cmd->start_src == TRIG_EXT) devpriv->b_ExttrigEnable = APCI3120_ENABLE; else devpriv->b_ExttrigEnable = APCI3120_DISABLE; - if (cmd->scan_begin_src == TRIG_FOLLOW) { - /* mode 1 or 3 */ - if (cmd->convert_src == TRIG_TIMER) { - /* mode 1 */ - - devpriv->ui_AiTimer0 = cmd->convert_arg; /* timer constant in nano seconds */ - /* return this_board->ai_cmd(1,dev,s); */ - return apci3120_cyclic_ai(1, dev, s); - } - - } - if ((cmd->scan_begin_src == TRIG_TIMER) - && (cmd->convert_src == TRIG_TIMER)) { - /* mode 2 */ - devpriv->ui_AiTimer1 = cmd->scan_begin_arg; - devpriv->ui_AiTimer0 = cmd->convert_arg; /* variable changed timer2 to timer0 */ - /* return this_board->ai_cmd(2,dev,s); */ + if (cmd->scan_begin_src == TRIG_FOLLOW) + return apci3120_cyclic_ai(1, dev, s); + else /* TRIG_TIMER */ return apci3120_cyclic_ai(2, dev, s); - } - return -1; } /* @@ -1392,11 +1341,12 @@ static void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev, 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) / devpriv->ui_AiScanLength; + (s->async->cur_chan + num_samples) / cmd->scan_end_arg; s->async->cur_chan += num_samples; - s->async->cur_chan %= devpriv->ui_AiScanLength; + s->async->cur_chan %= cmd->scan_end_arg; cfc_write_array_to_buffer(s, dma_buffer, num_samples * sizeof(short)); } @@ -1412,6 +1362,7 @@ 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; @@ -1427,8 +1378,6 @@ static void apci3120_interrupt_dma(int irq, void *d) if (samplesinbuf & 1) { comedi_error(dev, "Odd count of bytes in DMA ring!"); apci3120_cancel(dev, s); - devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE; - return; } samplesinbuf = samplesinbuf >> 1; /* number of received samples */ @@ -1489,16 +1438,15 @@ static void apci3120_interrupt_dma(int irq, void *d) devpriv->ul_DmaBufferVirtual[devpriv-> ui_DmaActualBuffer], samplesinbuf); - if (!(devpriv->ui_AiFlags & TRIG_WAKE_EOS)) { + if (!(cmd->flags & TRIG_WAKE_EOS)) { s->async->events |= COMEDI_CB_EOS; comedi_event(dev, s); } } - if (!devpriv->b_AiContinuous) - if (devpriv->ui_AiActualScan >= devpriv->ui_AiNbrofScans) { + if (cmd->stop_src == TRIG_COUNT) + if (devpriv->ui_AiActualScan >= cmd->stop_arg) { /* all data sampled */ apci3120_cancel(dev, s); - devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE; s->async->events |= COMEDI_CB_EOA; comedi_event(dev, s); return; @@ -1572,7 +1520,7 @@ static int apci3120_interrupt_handle_eos(struct comedi_device *dev) n_chan = devpriv->ui_AiNbrofChannels; for (i = 0; i < n_chan; i++) - err &= comedi_buf_put(s->async, inw(dev->iobase + 0)); + err &= comedi_buf_put(s, inw(dev->iobase + 0)); s->async->events |= COMEDI_CB_EOS; @@ -1648,7 +1596,7 @@ static void apci3120_interrupt(int irq, void *d) if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) { /* enable this in without DMA ??? */ - if (devpriv->b_AiCyclicAcquisition == APCI3120_ENABLE) { + if (devpriv->ai_running) { ui_Check = 0; apci3120_interrupt_handle_eos(dev); devpriv->ui_AiActualScan++; @@ -1690,8 +1638,6 @@ static void apci3120_interrupt(int irq, void *d) switch (devpriv->b_Timer2Mode) { case APCI3120_COUNTER: - - devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE; devpriv->b_ModeSelectRegister = devpriv-> b_ModeSelectRegister & APCI3120_DISABLE_EOS_INT; @@ -1707,7 +1653,6 @@ static void apci3120_interrupt(int irq, void *d) /* stop timer 0 and timer 1 */ apci3120_cancel(dev, s); - devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE; /* UPDATE-0.7.57->0.7.68comedi_done(dev,s); */ s->async->events |= COMEDI_CB_EOA; @@ -1746,7 +1691,7 @@ static void apci3120_interrupt(int irq, void *d) } if ((int_daq & 0x4) && (devpriv->b_InterruptMode == APCI3120_DMA_MODE)) { - if (devpriv->b_AiCyclicAcquisition == APCI3120_ENABLE) { + if (devpriv->ai_running) { /****************************/ /* Clear Timer Write TC int */ diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c index 0536d8373861..f540394d17b0 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c @@ -2221,12 +2221,11 @@ static int apci3200_ai_cmdtest(struct comedi_device *dev, unsigned int ui_ConvertTimeBase = 0; unsigned int ui_DelayTime = 0; unsigned int ui_DelayTimeBase = 0; - int i_Triggermode = 0; - int i_TriggerEdge = 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 */ @@ -2253,23 +2252,37 @@ static int apci3200_ai_cmdtest(struct comedi_device *dev, /* Step 2b : and mutually compatible */ - if (cmd->start_src == TRIG_EXT) { - i_TriggerEdge = cmd->start_arg & 0xFFFF; - i_Triggermode = cmd->start_arg >> 16; - if (i_TriggerEdge < 1 || i_TriggerEdge > 3) { - err++; - printk("\nThe trigger edge selection is in error\n"); - } - if (i_Triggermode != 2) { - err++; - printk("\nThe trigger mode selection is in error\n"); - } - } - 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]; */ @@ -2689,8 +2702,7 @@ static int i_APCI3200_InterruptHandleEos(struct comedi_device *dev) s->async->events |= COMEDI_CB_EOS; /* Test if enougth memory is available and allocate it for 7 values */ - /* n = comedi_buf_write_alloc(s->async, 7*sizeof(unsigned int)); */ - n = comedi_buf_write_alloc(s->async, + n = comedi_buf_write_alloc(s, (7 + 12) * sizeof(unsigned int)); /* If not enough memory available, event is set to Comedi Buffer Error */ @@ -2699,12 +2711,12 @@ static int i_APCI3200_InterruptHandleEos(struct comedi_device *dev) s->async->events |= COMEDI_CB_ERROR; } /* Write all 7 scan values in the comedi buffer */ - comedi_buf_memcpy_to(s->async, 0, + 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->async, + comedi_buf_write_free(s, (7 + 12) * sizeof(unsigned int)); /* Send events */ diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c index 20e89b0bdc4d..e82c3fcd048b 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c @@ -102,11 +102,7 @@ static int apci3501_write_insn_timer(struct comedi_device *dev, ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL; /* Enable the Watchdog */ outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG); - } - - else if (data[1] == 0) /* Stop The Watchdog */ - { - /* Stop The Watchdog */ + } else if (data[1] == 0) { /* Stop The Watchdog */ ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG); ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG); diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c index 0daa0ea63b5e..1b2e7c040c9f 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1032.c +++ b/drivers/staging/comedi/drivers/addi_apci_1032.c @@ -198,7 +198,7 @@ static int apci1032_cos_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); - err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, 1); + err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); if (err) @@ -262,7 +262,7 @@ 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->async, s->state); + comedi_buf_put(s, s->state); s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; comedi_event(dev, s); @@ -332,6 +332,7 @@ static int apci1032_auto_attach(struct comedi_device *dev, s->range_table = &range_digital; s->insn_config = apci1032_cos_insn_config; s->insn_bits = apci1032_cos_insn_bits; + s->len_chanlist = 1; s->do_cmdtest = apci1032_cos_cmdtest; s->do_cmd = apci1032_cos_cmd; s->cancel = apci1032_cos_cancel; @@ -379,5 +380,5 @@ static struct pci_driver apci1032_pci_driver = { module_comedi_pci_driver(apci1032_driver, apci1032_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("ADDI-DATA APCI-1032, 32 channel DI boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index bd8e08ca14c0..eab75eb26478 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -72,5 +72,5 @@ static struct pci_driver apci1500_pci_driver = { module_comedi_pci_driver(apci1500_driver, apci1500_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("ADDI-DATA APCI-1500, 16 channel DI / 16 channel DO boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c index 27aa9ae1bdd9..13d9962b47ec 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1564.c +++ b/drivers/staging/comedi/drivers/addi_apci_1564.c @@ -3,50 +3,168 @@ #include "../comedidev.h" #include "comedi_fc.h" -#include "amcc_s5933.h" #include "addi-data/addi_common.h" -#include "addi-data/addi_eeprom.c" #include "addi-data/hwdrv_apci1564.c" -#include "addi-data/addi_common.c" - -static const struct addi_board apci1564_boardtypes[] = { - { - .pc_DriverName = "apci1564", - .i_IorangeBase1 = APCI1564_ADDRESS_RANGE, - .i_PCIEeprom = ADDIDATA_EEPROM, - .pc_EepromChip = ADDIDATA_93C76, - .i_NbrDiChannel = 32, - .i_NbrDoChannel = 32, - .i_DoMaxdata = 0xffffffff, - .i_Timer = 1, - .interrupt = apci1564_interrupt, - .reset = apci1564_reset, - .di_config = apci1564_di_config, - .di_bits = apci1564_di_insn_bits, - .do_config = apci1564_do_config, - .do_bits = apci1564_do_insn_bits, - .do_read = apci1564_do_read, - .timer_config = apci1564_timer_config, - .timer_write = apci1564_timer_write, - .timer_read = apci1564_timer_read, - }, -}; + +static irqreturn_t v_ADDI_Interrupt(int irq, void *d) +{ + apci1564_interrupt(irq, d); + return IRQ_RETVAL(1); +} + +static int apci1564_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_IobaseAmcc + APCI1564_DI_REG); + + return insn->n; +} + +static int apci1564_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_IobaseAmcc + APCI1564_DO_REG); + + if (comedi_dio_update_state(s, data)) + outl(s->state, devpriv->i_IobaseAmcc + APCI1564_DO_REG); + + data[1] = s->state; + + return insn->n; +} + +static int apci1564_reset(struct comedi_device *dev) +{ + struct addi_private *devpriv = dev->private; + + ui_Type = 0; + + /* Disable the input interrupts and reset status register */ + outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG); + inl(devpriv->i_IobaseAmcc + APCI1564_DI_INT_STATUS_REG); + outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_INT_MODE1_REG); + outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_INT_MODE2_REG); + + /* Reset the output channels and disable interrupts */ + outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DO_REG); + outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DO_INT_CTRL_REG); + + /* Reset the watchdog registers */ + addi_watchdog_reset(devpriv->i_IobaseAmcc + APCI1564_WDOG_REG); + + /* Reset the timer registers */ + outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG); + outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER_RELOAD_REG); + + /* Reset the counter registers */ + outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1)); + outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2)); + outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3)); + outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4)); + + return 0; +} static int apci1564_auto_attach(struct comedi_device *dev, - unsigned long context) + unsigned long context_unused) +{ + struct pci_dev *pcidev = comedi_to_pci_dev(dev); + struct addi_private *devpriv; + struct comedi_subdevice *s; + int ret; + + dev->board_name = dev->driver->driver_name; + + 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->i_IobaseAmcc = pci_resource_start(pcidev, 0); + + apci1564_reset(dev); + + 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; + } + + ret = comedi_alloc_subdevices(dev, 3); + if (ret) + return ret; + + /* Allocate and Initialise DI Subdevice Structures */ + s = &dev->subdevices[0]; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 32; + s->maxdata = 1; + s->len_chanlist = 32; + s->range_table = &range_digital; + s->insn_config = apci1564_di_config; + s->insn_bits = apci1564_di_insn_bits; + + /* Allocate and Initialise DO Subdevice Structures */ + s = &dev->subdevices[1]; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITEABLE; + s->n_chan = 32; + s->maxdata = 0xffffffff; + s->len_chanlist = 32; + s->range_table = &range_digital; + s->insn_config = apci1564_do_config; + s->insn_bits = apci1564_do_insn_bits; + s->insn_read = apci1564_do_read; + + /* Allocate and Initialise Timer Subdevice Structures */ + s = &dev->subdevices[2]; + s->type = COMEDI_SUBD_TIMER; + s->subdev_flags = SDF_WRITEABLE; + s->n_chan = 1; + s->maxdata = 0; + s->len_chanlist = 1; + s->range_table = &range_digital; + s->insn_write = apci1564_timer_write; + s->insn_read = apci1564_timer_read; + s->insn_config = apci1564_timer_config; + + return 0; +} + +static void apci1564_detach(struct comedi_device *dev) { - dev->board_ptr = &apci1564_boardtypes[0]; + struct addi_private *devpriv = dev->private; - return addi_auto_attach(dev, context); + if (devpriv) { + if (dev->iobase) + apci1564_reset(dev); + if (dev->irq) + free_irq(dev->irq, dev); + } + comedi_pci_disable(dev); } static struct comedi_driver apci1564_driver = { .driver_name = "addi_apci_1564", .module = THIS_MODULE, .auto_attach = apci1564_auto_attach, - .detach = i_ADDI_Detach, + .detach = apci1564_detach, }; static int apci1564_pci_probe(struct pci_dev *dev, @@ -70,5 +188,5 @@ static struct pci_driver apci1564_pci_driver = { module_comedi_pci_driver(apci1564_driver, apci1564_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("ADDI-DATA APCI-1564, 32 channel DI / 32 channel DO boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c index c9b933cb5987..be0a8a7bd3b2 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2032.c +++ b/drivers/staging/comedi/drivers/addi_apci_2032.c @@ -197,6 +197,7 @@ static irqreturn_t apci2032_interrupt(int irq, void *d) { struct comedi_device *dev = d; struct comedi_subdevice *s = dev->read_subdev; + struct comedi_cmd *cmd = &s->async->cmd; struct apci2032_int_private *subpriv; unsigned int val; bool do_event = false; @@ -222,21 +223,20 @@ static irqreturn_t apci2032_interrupt(int irq, void *d) */ if (subpriv->active && (val & subpriv->enabled_isns) != 0) { - unsigned short bits; - unsigned int n, len; - unsigned int *chanlist; + unsigned short bits = 0; + int i; /* Bits in scan data correspond to indices in channel list. */ - bits = 0; - len = s->async->cmd.chanlist_len; - chanlist = &s->async->cmd.chanlist[0]; - for (n = 0; n < len; n++) - if ((val & (1U << CR_CHAN(chanlist[n]))) != 0) - bits |= 1U << n; - - if (comedi_buf_put(s->async, bits)) { + for (i = 0; i < cmd->chanlist_len; i++) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); + + if (val & (1 << chan)) + bits |= (1 << i); + } + + if (comedi_buf_put(s, bits)) { s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; - if (s->async->cmd.stop_src == TRIG_COUNT && + if (cmd->stop_src == TRIG_COUNT && subpriv->stop_count > 0) { subpriv->stop_count--; if (subpriv->stop_count == 0) { @@ -374,5 +374,5 @@ static struct pci_driver apci2032_pci_driver = { module_comedi_pci_driver(apci2032_driver, apci2032_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("ADDI-DATA APCI-2032, 32 channel DO boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c index 57ee6e5c7635..0cfb12fa1cbc 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3120.c +++ b/drivers/staging/comedi/drivers/addi_apci_3120.c @@ -246,5 +246,5 @@ static struct pci_driver apci3120_pci_driver = { module_comedi_pci_driver(apci3120_driver, apci3120_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("ADDI-DATA APCI-3120, Analog input board"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c index 6dc11c407f57..0532b6cc40e3 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c +++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c @@ -373,7 +373,7 @@ static irqreturn_t apci3xxx_irq_handler(int irq, void *d) writel(status, devpriv->mmio + 16); val = readl(devpriv->mmio + 28); - comedi_buf_put(s->async, val); + comedi_buf_put(s, val); s->async->events |= COMEDI_CB_EOA; comedi_event(dev, s); @@ -533,7 +533,7 @@ static int apci3xxx_ai_cmdtest(struct comedi_device *dev, { const struct apci3xxx_boardinfo *board = comedi_board(dev); int err = 0; - unsigned int tmp; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -573,31 +573,9 @@ static int apci3xxx_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ - /* - * FIXME: The hardware supports multiple scan modes but the original - * addi-data driver only supported reading a single channel with - * interrupts. Need a proper datasheet to fix this. - * - * The following scan modes are supported by the hardware: - * 1) Single software scan - * 2) Single hardware triggered scan - * 3) Continuous software scan - * 4) Continuous software scan with timer delay - * 5) Continuous hardware triggered scan - * 6) Continuous hardware triggered scan with timer delay - * - * For now, limit the chanlist to a single channel. - */ - if (cmd->chanlist_len > 1) { - cmd->chanlist_len = 1; - err |= -EINVAL; - } - - tmp = cmd->convert_arg; - err |= apci3xxx_ai_ns_to_timer(dev, &cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); - if (tmp != cmd->convert_arg) - err |= -EINVAL; + arg = cmd->convert_arg; + err |= apci3xxx_ai_ns_to_timer(dev, &arg, cmd->flags & TRIG_ROUND_MASK); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); if (err) return 4; @@ -719,7 +697,8 @@ static int apci3xxx_dio_insn_config(struct comedi_device *dev, if (chan < 16) return -EINVAL; else - /* changing any channel in port 2 changes the entire port */ + /* changing any channel in port 2 */ + /* changes the entire port */ mask = 0xff0000; } @@ -842,12 +821,30 @@ static int apci3xxx_auto_attach(struct comedi_device *dev, s->subdev_flags = SDF_READABLE | board->ai_subdev_flags; s->n_chan = board->ai_n_chan; s->maxdata = board->ai_maxdata; - s->len_chanlist = s->n_chan; s->range_table = &apci3xxx_ai_range; s->insn_read = apci3xxx_ai_insn_read; if (dev->irq) { + /* + * FIXME: The hardware supports multiple scan modes + * but the original addi-data driver only supported + * reading a single channel with interrupts. Need a + * proper datasheet to fix this. + * + * The following scan modes are supported by the + * hardware: + * 1) Single software scan + * 2) Single hardware triggered scan + * 3) Continuous software scan + * 4) Continuous software scan with timer delay + * 5) Continuous hardware triggered scan + * 6) Continuous hardware triggered scan with timer + * delay + * + * For now, limit the chanlist to a single channel. + */ dev->read_subdev = s; s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = 1; s->do_cmdtest = apci3xxx_ai_cmdtest; s->do_cmd = apci3xxx_ai_cmd; s->cancel = apci3xxx_ai_cancel; diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index a29ceacb966d..584fd57ecb70 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -137,10 +137,8 @@ struct pci9111_private_data { unsigned long lcr_io_base; int stop_counter; - int stop_is_none; unsigned int scan_delay; - unsigned int chanlist_len; unsigned int chunk_counter; unsigned int chunk_num_samples; @@ -314,148 +312,137 @@ static int pci9111_ai_cancel(struct comedi_device *dev, return 0; } +static int pci9111_ai_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + 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 != i) { + dev_dbg(dev->class_dev, + "entries in chanlist must be consecutive channels,counting upwards from 0\n"); + return -EINVAL; + } + + if (range != range0) { + dev_dbg(dev->class_dev, + "entries in chanlist must all have the same gain\n"); + return -EINVAL; + } + + if (aref != aref0) { + dev_dbg(dev->class_dev, + "entries in chanlist must all have the same reference\n"); + return -EINVAL; + } + } + + return 0; +} + static int pci9111_ai_do_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { struct pci9111_private_data *dev_private = dev->private; - int tmp; - int error = 0; - int range, reference; - int i; + int err = 0; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ - error |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - error |= cfc_check_trigger_src(&cmd->scan_begin_src, + err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); + err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT); - error |= cfc_check_trigger_src(&cmd->convert_src, + err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT); - error |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - error |= cfc_check_trigger_src(&cmd->stop_src, + err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); + err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); - if (error) + if (err) return 1; /* Step 2a : make sure trigger sources are unique */ - error |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - error |= cfc_check_trigger_is_unique(cmd->convert_src); - error |= cfc_check_trigger_is_unique(cmd->stop_src); + err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); + err |= cfc_check_trigger_is_unique(cmd->convert_src); + err |= cfc_check_trigger_is_unique(cmd->stop_src); /* Step 2b : and mutually compatible */ - if ((cmd->convert_src == TRIG_TIMER) && - !((cmd->scan_begin_src == TRIG_TIMER) || - (cmd->scan_begin_src == TRIG_FOLLOW))) - error |= -EINVAL; - if ((cmd->convert_src == TRIG_EXT) && - !((cmd->scan_begin_src == TRIG_EXT) || - (cmd->scan_begin_src == TRIG_FOLLOW))) - error |= -EINVAL; + if (cmd->scan_begin_src != TRIG_FOLLOW) { + if (cmd->scan_begin_src != cmd->convert_src) + err |= -EINVAL; + } - if (error) + if (err) return 2; /* Step 3: check if arguments are trivially valid */ - error |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); if (cmd->convert_src == TRIG_TIMER) - error |= cfc_check_trigger_arg_min(&cmd->convert_arg, + err |= cfc_check_trigger_arg_min(&cmd->convert_arg, PCI9111_AI_ACQUISITION_PERIOD_MIN_NS); else /* TRIG_EXT */ - error |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); if (cmd->scan_begin_src == TRIG_TIMER) - error |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, + err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, PCI9111_AI_ACQUISITION_PERIOD_MIN_NS); else /* TRIG_FOLLOW || TRIG_EXT */ - error |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); - error |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, - cmd->chanlist_len); + err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); if (cmd->stop_src == TRIG_COUNT) - error |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1); + err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1); else /* TRIG_NONE */ - error |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); - if (error) + if (err) return 3; - /* Step 4 : fix up any arguments */ + /* Step 4: fix up any arguments */ if (cmd->convert_src == TRIG_TIMER) { - tmp = cmd->convert_arg; + arg = cmd->convert_arg; i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ, &dev_private->div1, &dev_private->div2, - &cmd->convert_arg, cmd->flags); - if (tmp != cmd->convert_arg) - error++; + &arg, cmd->flags); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); } - /* There's only one timer on this card, so the scan_begin timer must */ - /* be a multiple of chanlist_len*convert_arg */ + /* + * There's only one timer on this card, so the scan_begin timer + * must be a multiple of chanlist_len*convert_arg + */ if (cmd->scan_begin_src == TRIG_TIMER) { + arg = cmd->chanlist_len * cmd->convert_arg; - unsigned int scan_begin_min; - unsigned int scan_begin_arg; - unsigned int scan_factor; - - scan_begin_min = cmd->chanlist_len * cmd->convert_arg; - - if (cmd->scan_begin_arg != scan_begin_min) { - if (scan_begin_min < cmd->scan_begin_arg) { - scan_factor = - cmd->scan_begin_arg / scan_begin_min; - scan_begin_arg = scan_factor * scan_begin_min; - if (cmd->scan_begin_arg != scan_begin_arg) { - cmd->scan_begin_arg = scan_begin_arg; - error++; - } - } else { - cmd->scan_begin_arg = scan_begin_min; - error++; - } - } + if (arg < cmd->scan_begin_arg) + arg *= (cmd->scan_begin_arg / arg); + + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } - if (error) + if (err) return 4; - /* Step 5 : check channel list */ - - if (cmd->chanlist) { - - range = CR_RANGE(cmd->chanlist[0]); - reference = CR_AREF(cmd->chanlist[0]); - - if (cmd->chanlist_len > 1) { - for (i = 0; i < cmd->chanlist_len; i++) { - if (CR_CHAN(cmd->chanlist[i]) != i) { - comedi_error(dev, - "entries in chanlist must be consecutive " - "channels,counting upwards from 0\n"); - error++; - } - if (CR_RANGE(cmd->chanlist[i]) != range) { - comedi_error(dev, - "entries in chanlist must all have the same gain\n"); - error++; - } - if (CR_AREF(cmd->chanlist[i]) != reference) { - comedi_error(dev, - "entries in chanlist must all have the same reference\n"); - error++; - } - } - } - } + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= pci9111_ai_check_chanlist(dev, s, cmd); - if (error) + if (err) return 5; return 0; @@ -466,18 +453,18 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct pci9111_private_data *dev_private = dev->private; - struct comedi_cmd *async_cmd = &s->async->cmd; + struct comedi_cmd *cmd = &s->async->cmd; /* Set channel scan limit */ /* PCI9111 allows only scanning from channel 0 to channel n */ /* TODO: handle the case of an external multiplexer */ - if (async_cmd->chanlist_len > 1) { - outb(async_cmd->chanlist_len - 1, + if (cmd->chanlist_len > 1) { + outb(cmd->chanlist_len - 1, dev->iobase + PCI9111_AI_CHANNEL_REG); pci9111_autoscan_set(dev, true); } else { - outb(CR_CHAN(async_cmd->chanlist[0]), + outb(CR_CHAN(cmd->chanlist[0]), dev->iobase + PCI9111_AI_CHANNEL_REG); pci9111_autoscan_set(dev, false); } @@ -485,22 +472,18 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev, /* Set gain */ /* This is the same gain on every channel */ - outb(CR_RANGE(async_cmd->chanlist[0]) & PCI9111_AI_RANGE_MASK, + outb(CR_RANGE(cmd->chanlist[0]) & PCI9111_AI_RANGE_MASK, dev->iobase + PCI9111_AI_RANGE_STAT_REG); /* Set counter */ - if (async_cmd->stop_src == TRIG_COUNT) { - dev_private->stop_counter = - async_cmd->stop_arg * async_cmd->chanlist_len; - dev_private->stop_is_none = 0; - } else { /* TRIG_NONE */ + if (cmd->stop_src == TRIG_COUNT) + dev_private->stop_counter = cmd->stop_arg * cmd->chanlist_len; + else /* TRIG_NONE */ dev_private->stop_counter = 0; - dev_private->stop_is_none = 1; - } /* Set timer pacer */ dev_private->scan_delay = 0; - if (async_cmd->convert_src == TRIG_TIMER) { + if (cmd->convert_src == TRIG_TIMER) { pci9111_trigger_source_set(dev, software); pci9111_timer_set(dev); pci9111_fifo_reset(dev); @@ -510,11 +493,9 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev, plx9050_interrupt_control(dev_private->lcr_io_base, true, true, false, true, true); - if (async_cmd->scan_begin_src == TRIG_TIMER) { - dev_private->scan_delay = - (async_cmd->scan_begin_arg / - (async_cmd->convert_arg * - async_cmd->chanlist_len)) - 1; + if (cmd->scan_begin_src == TRIG_TIMER) { + dev_private->scan_delay = (cmd->scan_begin_arg / + (cmd->convert_arg * cmd->chanlist_len)) - 1; } } else { /* TRIG_EXT */ pci9111_trigger_source_set(dev, external); @@ -527,10 +508,9 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev, } dev_private->stop_counter *= (1 + dev_private->scan_delay); - dev_private->chanlist_len = async_cmd->chanlist_len; dev_private->chunk_counter = 0; - dev_private->chunk_num_samples = - dev_private->chanlist_len * (1 + dev_private->scan_delay); + dev_private->chunk_num_samples = cmd->chanlist_len * + (1 + dev_private->scan_delay); return 0; } @@ -551,12 +531,71 @@ static void pci9111_ai_munge(struct comedi_device *dev, array[i] = ((array[i] >> shift) & maxdata) ^ invert; } +static void pci9111_handle_fifo_half_full(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + 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; + + 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)); + } else { + unsigned int pos = 0; + unsigned int to_read; + + while (pos < samples) { + if (devpriv->chunk_counter < cmd->chanlist_len) { + to_read = cmd->chanlist_len - + devpriv->chunk_counter; + + if (to_read > samples - pos) + to_read = samples - pos; + + total += cfc_write_array_to_buffer(s, + devpriv->ai_bounce_buffer + pos, + to_read * sizeof(short)); + } 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; + devpriv->chunk_counter += to_read; + + if (devpriv->chunk_counter >= + devpriv->chunk_num_samples) + devpriv->chunk_counter = 0; + } + } + + devpriv->stop_counter -= total / sizeof(short); +} + static irqreturn_t pci9111_interrupt(int irq, void *p_device) { struct comedi_device *dev = p_device; struct pci9111_private_data *dev_private = dev->private; struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async; + struct comedi_cmd *cmd; unsigned int status; unsigned long irq_flags; unsigned char intcsr; @@ -568,6 +607,7 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device) } async = s->async; + cmd = &async->cmd; spin_lock_irqsave(&dev->spinlock, irq_flags); @@ -599,79 +639,11 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device) } /* '0' means FIFO is half-full */ - if (!(status & PCI9111_AI_STAT_FF_HF)) { - unsigned int num_samples; - unsigned int bytes_written = 0; - - num_samples = - PCI9111_FIFO_HALF_SIZE > - dev_private->stop_counter - && !dev_private-> - stop_is_none ? dev_private->stop_counter : - PCI9111_FIFO_HALF_SIZE; - insw(dev->iobase + PCI9111_AI_FIFO_REG, - dev_private->ai_bounce_buffer, num_samples); - - if (dev_private->scan_delay < 1) { - bytes_written = - cfc_write_array_to_buffer(s, - dev_private-> - ai_bounce_buffer, - num_samples * - sizeof(short)); - } else { - int position = 0; - int to_read; - - while (position < num_samples) { - if (dev_private->chunk_counter < - dev_private->chanlist_len) { - to_read = - dev_private->chanlist_len - - dev_private->chunk_counter; - - if (to_read > - num_samples - position) - to_read = - num_samples - - position; - - bytes_written += - cfc_write_array_to_buffer - (s, - dev_private->ai_bounce_buffer - + position, - to_read * sizeof(short)); - } else { - to_read = - dev_private->chunk_num_samples - - - dev_private->chunk_counter; - if (to_read > - num_samples - position) - to_read = - num_samples - - position; - - bytes_written += - sizeof(short) * to_read; - } - - position += to_read; - dev_private->chunk_counter += to_read; - - if (dev_private->chunk_counter >= - dev_private->chunk_num_samples) - dev_private->chunk_counter = 0; - } - } - - dev_private->stop_counter -= - bytes_written / sizeof(short); - } + if (!(status & PCI9111_AI_STAT_FF_HF)) + pci9111_handle_fifo_half_full(dev, s); } - if (dev_private->stop_counter == 0 && !dev_private->stop_is_none) + if (cmd->stop_src == TRIG_COUNT && dev_private->stop_counter == 0) async->events |= COMEDI_CB_EOA; outb(0, dev->iobase + PCI9111_INT_CLR_REG); diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 3cfa1756fa6a..59a65cbc6db9 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -96,7 +96,7 @@ Configuration options: * correct channel number on every 12 bit sample */ -#define IORANGE_9118 64 /* I hope */ +#define IORANGE_9118 64 /* I hope */ #define PCI9118_CHANLEN 255 /* * len of chanlist, some source say 256, * but reality looks like 255 :-( @@ -320,14 +320,9 @@ struct pci9118_private { unsigned char AdControlReg; /* A/D control register */ unsigned char IntControlReg; /* Interrupt control register */ unsigned char AdFunctionReg; /* A/D function register */ - char valid; /* driver is ok */ char ai_neverending; /* we do unlimited AI */ - unsigned int i8254_osc_base; /* frequence of onboard oscilator */ 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_buf_ptr; /* data buffer ptr in samples */ - unsigned int ai_n_chan; /* how many channels is measured */ - unsigned int ai_n_scanlen; /* len of actual scanlist */ unsigned int ai_n_realscanlen; /* * what we must transfer for one * outgoing scan include front/back adds @@ -341,9 +336,6 @@ struct pci9118_private { * how many channels we must add * before scan to satisfy DMA? */ - unsigned int *ai_chanlist; /* actual chanlist */ - unsigned int ai_timer1; - unsigned int ai_timer2; unsigned int ai_flags; char ai12_startstop; /* * measure can start/stop @@ -353,9 +345,7 @@ struct pci9118_private { * divisors for start of measure * on external start */ - unsigned int ai_data_len; unsigned short ao_data[2]; /* data output buffer */ - unsigned int ai_scans; /* number of scans to do */ char dma_doublebuf; /* we can use double buffering */ unsigned int dma_actbuf; /* which buffer is used now */ unsigned short *dmabuf_virt[2]; /* @@ -372,31 +362,12 @@ struct pci9118_private { */ unsigned int dmabuf_used_size[2]; /* which size was truly used */ unsigned int dmabuf_panic_size[2]; - unsigned int dmabuf_samples[2]; /* size in samples */ int dmabuf_pages[2]; /* number of pages in buffer */ - unsigned char cnt0_users; /* - * bit field of 8254 CNT0 users - * (0-unused, 1-AO, 2-DI, 3-DO) - */ unsigned char exttrg_users; /* * bit field of external trigger * users(0-AI, 1-AO, 2-DI, 3-DO) */ - unsigned int cnt0_divisor; /* actual CNT0 divisor */ - void (*int_ai_func) (struct comedi_device *, struct comedi_subdevice *, - unsigned short, - unsigned int, - unsigned short); /* - * ptr to actual interrupt - * AI function - */ - unsigned char ai16bits; /* =1 16 bit card */ unsigned char usedma; /* =1 use DMA transfer and not INT */ - unsigned char useeoshandle; /* - * =1 change WAKE_EOS DMA transfer - * to fit on every second - */ - unsigned char usessh; /* =1 turn on S&H support */ int softsshdelay; /* * >0 use software S&H, * numer is requested delay in ns @@ -411,7 +382,6 @@ struct pci9118_private { */ unsigned int ai_maskerr; /* which warning was printed */ unsigned int ai_maskharderr; /* on which error bits stops */ - unsigned int ai_inttrig_start; /* TRIG_INT for start */ }; static int check_channel_list(struct comedi_device *dev, @@ -468,7 +438,7 @@ static int check_channel_list(struct comedi_device *dev, static int setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s, int n_chan, unsigned int *chanlist, int rot, int frontadd, - int backadd, int usedma, char useeos) + int backadd, int usedma) { struct pci9118_private *devpriv = dev->private; unsigned int i, differencial = 0, bipolar = 0; @@ -552,18 +522,6 @@ static int setup_channel_list(struct comedi_device *dev, #ifdef PCI9118_PARANOIDCHECK devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma]; /* for 32bit operations */ - if (useeos) { - for (i = 1; i < n_chan; i++) { /* store range list to card */ - devpriv->chanlist[(n_chan + i) ^ usedma] = - (CR_CHAN(chanlist[i]) & 0xf) << rot; - } - devpriv->chanlist[(2 * n_chan) ^ usedma] = - devpriv->chanlist[0 ^ usedma]; - /* for 32bit operations */ - useeos = 2; - } else { - useeos = 1; - } #endif outl(0, dev->iobase + PCI9118_SCANMOD); /* close scan queue */ /* udelay(100); important delay, or first sample will be crippled */ @@ -603,7 +561,7 @@ static int pci9118_insn_read_ai(struct comedi_device *dev, * trigger stop */ - if (!setup_channel_list(dev, s, 1, &insn->chanspec, 0, 0, 0, 0, 0)) + if (!setup_channel_list(dev, s, 1, &insn->chanspec, 0, 0, 0, 0)) return -EINVAL; outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */ @@ -618,7 +576,7 @@ static int pci9118_insn_read_ai(struct comedi_device *dev, return ret; } - if (devpriv->ai16bits) { + if (s->maxdata == 0xffff) { data[n] = (inl(dev->iobase + PCI9118_AD_DATA) & 0xffff) ^ 0x8000; @@ -713,10 +671,11 @@ static unsigned int defragment_dma_buffer(struct comedi_device *dev, unsigned int num_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 + devpriv->ai_n_chan; - unsigned int raw_scanlen = devpriv->ai_add_front + devpriv->ai_n_chan + + stop_pos = devpriv->ai_add_front + cmd->chanlist_len; + unsigned int raw_scanlen = devpriv->ai_add_front + cmd->chanlist_len + devpriv->ai_add_back; for (i = 0; i < num_samples; i++) { @@ -737,13 +696,14 @@ static int move_block_from_dma(struct comedi_device *dev, unsigned int num_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) / devpriv->ai_n_scanlen; + (s->async->cur_chan + num_samples) / cmd->scan_end_arg; s->async->cur_chan += num_samples; - s->async->cur_chan %= devpriv->ai_n_scanlen; + s->async->cur_chan %= cmd->scan_end_arg; num_bytes = cfc_write_array_to_buffer(s, dma_buffer, num_samples * sizeof(short)); @@ -791,47 +751,51 @@ static void pci9118_calc_divisors(char mode, struct comedi_device *dev, unsigned int *tim1, unsigned int *tim2, unsigned int flags, int chans, unsigned int *div1, unsigned int *div2, - char usessh, unsigned int chnsshfront) + unsigned int chnsshfront) { const struct boardtype *this_board = comedi_board(dev); - struct pci9118_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; switch (mode) { case 1: case 4: if (*tim2 < this_board->ai_ns_min) *tim2 = this_board->ai_ns_min; - i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, + i8253_cascade_ns_to_timer(I8254_OSC_BASE_4MHZ, div1, div2, tim2, flags & TRIG_ROUND_NEAREST); break; case 2: if (*tim2 < this_board->ai_ns_min) *tim2 = this_board->ai_ns_min; - *div1 = *tim2 / devpriv->i8254_osc_base; + *div1 = *tim2 / I8254_OSC_BASE_4MHZ; /* convert timer (burst) */ if (*div1 < this_board->ai_pacer_min) *div1 = this_board->ai_pacer_min; - *div2 = *tim1 / devpriv->i8254_osc_base; /* scan timer */ + *div2 = *tim1 / I8254_OSC_BASE_4MHZ; /* scan timer */ *div2 = *div2 / *div1; /* major timer is c1*c2 */ if (*div2 < chans) *div2 = chans; - *tim2 = *div1 * devpriv->i8254_osc_base; - /* real convert timer */ + *tim2 = *div1 * I8254_OSC_BASE_4MHZ; /* real convert timer */ - if (usessh && (chnsshfront == 0)) /* use BSSH signal */ + if (cmd->convert_src == TRIG_NOW && !chnsshfront) { + /* use BSSH signal */ if (*div2 < (chans + 2)) *div2 = chans + 2; + } - *tim1 = *div1 * *div2 * devpriv->i8254_osc_base; + *tim1 = *div1 * *div2 * I8254_OSC_BASE_4MHZ; break; } } -static void start_pacer(struct comedi_device *dev, int mode, - unsigned int divisor1, unsigned int divisor2) +static void pci9118_start_pacer(struct comedi_device *dev, int mode) { + struct pci9118_private *devpriv = dev->private; + unsigned int divisor1 = devpriv->ai_divisor1; + unsigned int divisor2 = devpriv->ai_divisor2; + outl(0x74, dev->iobase + PCI9118_CNTCTRL); outl(0xb4, dev->iobase + PCI9118_CNTCTRL); /* outl(0x30, dev->iobase + PCI9118_CNTCTRL); */ @@ -855,7 +819,7 @@ static int pci9118_ai_cancel(struct comedi_device *dev, (~EN_A2P_TRANSFERS), devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */ pci9118_exttrg_del(dev, EXTTRG_AI); - start_pacer(dev, 0, 0, 0); /* stop 8254 counters */ + pci9118_start_pacer(dev, 0); /* stop 8254 counters */ devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg; outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); /* @@ -882,7 +846,6 @@ static int pci9118_ai_cancel(struct comedi_device *dev, devpriv->ai_act_dmapos = 0; s->async->cur_chan = 0; s->async->inttrig = NULL; - devpriv->ai_buf_ptr = 0; devpriv->ai_neverending = 0; devpriv->dma_actbuf = 0; @@ -938,7 +901,7 @@ static void pci9118_ai_munge(struct comedi_device *dev, for (i = 0; i < num_samples; i++) { if (devpriv->usedma) array[i] = be16_to_cpu(array[i]); - if (devpriv->ai16bits) + if (s->maxdata == 0xffff) array[i] ^= 0x8000; else array[i] = (array[i] >> 4) & 0x0fff; @@ -953,6 +916,7 @@ static void interrupt_pci9118_ai_onesample(struct comedi_device *dev, unsigned short int_daq) { struct pci9118_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; unsigned short sampl; if (int_adstat & devpriv->ai_maskerr) @@ -962,7 +926,7 @@ static void interrupt_pci9118_ai_onesample(struct comedi_device *dev, sampl = inw(dev->iobase + PCI9118_AD_DATA); #ifdef PCI9118_PARANOIDCHECK - if (devpriv->ai16bits == 0) { + if (s->maxdata != 0xffff) { if ((sampl & 0x000f) != devpriv->chanlist[s->async->cur_chan]) { /* data dropout! */ dev_info(dev->class_dev, @@ -977,13 +941,13 @@ static void interrupt_pci9118_ai_onesample(struct comedi_device *dev, #endif cfc_write_to_buffer(s, sampl); s->async->cur_chan++; - if (s->async->cur_chan >= devpriv->ai_n_scanlen) { + if (s->async->cur_chan >= cmd->scan_end_arg) { /* one scan done */ - s->async->cur_chan %= devpriv->ai_n_scanlen; + s->async->cur_chan %= cmd->scan_end_arg; devpriv->ai_act_scan++; if (!devpriv->ai_neverending) { /* all data sampled? */ - if (devpriv->ai_act_scan >= devpriv->ai_scans) + if (devpriv->ai_act_scan >= cmd->stop_arg) s->async->events |= COMEDI_CB_EOA; } } @@ -998,6 +962,7 @@ static void interrupt_pci9118_ai_dma(struct comedi_device *dev, unsigned short int_daq) { struct pci9118_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; unsigned int next_dma_buf, samplesinbuf, sampls, m; if (int_amcc & MASTER_ABORT_INT) { @@ -1037,20 +1002,18 @@ static void interrupt_pci9118_ai_dma(struct comedi_device *dev, } if (samplesinbuf) { - m = devpriv->ai_data_len >> 1; /* - * how many samples is to - * end of buffer - */ + /* how many samples is to end of buffer */ + m = s->async->prealloc_bufsz >> 1; sampls = m; move_block_from_dma(dev, s, devpriv->dmabuf_virt[devpriv->dma_actbuf], samplesinbuf); - m = m - sampls; /* m= how many samples was transferred */ + m = m - sampls; /* m=how many samples was transferred */ } if (!devpriv->ai_neverending) { /* all data sampled? */ - if (devpriv->ai_act_scan >= devpriv->ai_scans) + if (devpriv->ai_act_scan >= cmd->stop_arg) s->async->events |= COMEDI_CB_EOA; } @@ -1068,78 +1031,71 @@ static void interrupt_pci9118_ai_dma(struct comedi_device *dev, cfc_handle_events(dev, s); } -static irqreturn_t interrupt_pci9118(int irq, void *d) +static irqreturn_t pci9118_interrupt(int irq, void *d) { struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->read_subdev; struct pci9118_private *devpriv = dev->private; - unsigned int int_daq = 0, int_amcc, int_adstat; + unsigned int intsrc; /* IRQ reasons from card */ + unsigned int intcsr; /* INT register from AMCC chip */ + unsigned int adstat; /* STATUS register */ if (!dev->attached) - return IRQ_NONE; /* not fully initialized */ - - int_daq = inl(dev->iobase + PCI9118_INTSRC) & 0xf; - /* get IRQ reasons from card */ - int_amcc = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR); - /* get INT register from AMCC chip */ - - if ((!int_daq) && (!(int_amcc & ANY_S593X_INT))) - return IRQ_NONE; /* interrupt from other source */ - - outl(int_amcc | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR); - /* shutdown IRQ reasons in AMCC */ - - int_adstat = inw(dev->iobase + PCI9118_ADSTAT) & 0x1ff; - /* get STATUS register */ - - if (devpriv->ai_do) { - if (devpriv->ai12_startstop) - if ((int_adstat & AdStatus_DTH) && - (int_daq & Int_DTrg)) { - /* start stop of measure */ - if (devpriv->ai12_startstop & START_AI_EXT) { - devpriv->ai12_startstop &= - ~START_AI_EXT; - if (!(devpriv->ai12_startstop & - STOP_AI_EXT)) - pci9118_exttrg_del - (dev, EXTTRG_AI); - /* deactivate EXT trigger */ - start_pacer(dev, devpriv->ai_do, - devpriv->ai_divisor1, - devpriv->ai_divisor2); - /* start pacer */ - outl(devpriv->AdControlReg, - dev->iobase + PCI9118_ADCNTRL); - } else { - if (devpriv->ai12_startstop & - STOP_AI_EXT) { - devpriv->ai12_startstop &= - ~STOP_AI_EXT; - pci9118_exttrg_del - (dev, EXTTRG_AI); - /* deactivate EXT trigger */ - devpriv->ai_neverending = 0; - /* - * well, on next interrupt from - * DMA/EOC measure will stop - */ - } - } - } + return IRQ_NONE; + + intsrc = inl(dev->iobase + PCI9118_INTSRC) & 0xf; + intcsr = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR); + + if (!intsrc && !(intcsr & ANY_S593X_INT)) + return IRQ_NONE; + + outl(intcsr | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR); + + adstat = inw(dev->iobase + PCI9118_ADSTAT) & 0x1ff; - (devpriv->int_ai_func) (dev, dev->read_subdev, int_adstat, - int_amcc, int_daq); + if (!devpriv->ai_do) + return IRQ_HANDLED; + if (devpriv->ai12_startstop) { + if ((adstat & AdStatus_DTH) && (intsrc & Int_DTrg)) { + /* start/stop of measure */ + if (devpriv->ai12_startstop & START_AI_EXT) { + /* deactivate EXT trigger */ + devpriv->ai12_startstop &= ~START_AI_EXT; + if (!(devpriv->ai12_startstop & STOP_AI_EXT)) + pci9118_exttrg_del(dev, EXTTRG_AI); + + /* start pacer */ + pci9118_start_pacer(dev, devpriv->ai_do); + outl(devpriv->AdControlReg, + dev->iobase + PCI9118_ADCNTRL); + } else if (devpriv->ai12_startstop & STOP_AI_EXT) { + /* deactivate EXT trigger */ + devpriv->ai12_startstop &= ~STOP_AI_EXT; + pci9118_exttrg_del(dev, EXTTRG_AI); + + /* on next interrupt measure will stop */ + devpriv->ai_neverending = 0; + } + } } + + if (devpriv->usedma) + interrupt_pci9118_ai_dma(dev, s, adstat, intcsr, intsrc); + else + interrupt_pci9118_ai_onesample(dev, s, adstat, intcsr, intsrc); + return IRQ_HANDLED; } static int pci9118_ai_inttrig(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned int trignum) + struct comedi_subdevice *s, + unsigned int trig_num) { struct pci9118_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; - if (trignum != devpriv->ai_inttrig_start) + if (trig_num != cmd->start_arg) return -EINVAL; devpriv->ai12_startstop &= ~START_AI_INT; @@ -1148,8 +1104,7 @@ static int pci9118_ai_inttrig(struct comedi_device *dev, outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); if (devpriv->ai_do != 3) { - start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1, - devpriv->ai_divisor2); + pci9118_start_pacer(dev, devpriv->ai_do); devpriv->AdControlReg |= AdControl_SoftG; } outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); @@ -1165,7 +1120,7 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev, struct pci9118_private *devpriv = dev->private; int err = 0; unsigned int flags; - int tmp; + unsigned int arg; unsigned int divisor1 = 0, divisor2 = 0; /* Step 1 : check if triggers are trivially valid */ @@ -1221,8 +1176,15 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev, /* Step 3: check if arguments are trivially valid */ - if (cmd->start_src & (TRIG_NOW | TRIG_EXT)) + switch (cmd->start_src) { + case TRIG_NOW: + case TRIG_EXT: err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); + break; + case TRIG_INT: + /* start_arg is the internal trigger (any value) */ + break; + } if (cmd->scan_begin_src & (TRIG_FOLLOW | TRIG_EXT)) err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); @@ -1259,8 +1221,6 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1); - err |= cfc_check_trigger_arg_max(&cmd->chanlist_len, - this_board->n_aichanlist); err |= cfc_check_trigger_arg_min(&cmd->scan_end_arg, cmd->chanlist_len); @@ -1277,45 +1237,30 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ if (cmd->scan_begin_src == TRIG_TIMER) { - tmp = cmd->scan_begin_arg; - i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, + arg = cmd->scan_begin_arg; + i8253_cascade_ns_to_timer(I8254_OSC_BASE_4MHZ, &divisor1, &divisor2, - &cmd->scan_begin_arg, cmd->flags); - if (cmd->scan_begin_arg < this_board->ai_ns_min) - cmd->scan_begin_arg = this_board->ai_ns_min; - if (tmp != cmd->scan_begin_arg) - err++; + &arg, cmd->flags); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) { - tmp = cmd->convert_arg; - i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, + arg = cmd->convert_arg; + i8253_cascade_ns_to_timer(I8254_OSC_BASE_4MHZ, &divisor1, &divisor2, - &cmd->convert_arg, cmd->flags); - if (cmd->convert_arg < this_board->ai_ns_min) - cmd->convert_arg = this_board->ai_ns_min; - if (tmp != cmd->convert_arg) - err++; - if (cmd->scan_begin_src == TRIG_TIMER - && cmd->convert_src == TRIG_NOW) { + &arg, cmd->flags); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); + + if (cmd->scan_begin_src == TRIG_TIMER && + cmd->convert_src == TRIG_NOW) { if (cmd->convert_arg == 0) { - if (cmd->scan_begin_arg < - this_board->ai_ns_min * - (cmd->scan_end_arg + 2)) { - cmd->scan_begin_arg = - this_board->ai_ns_min * - (cmd->scan_end_arg + 2); - err++; - } + arg = this_board->ai_ns_min * + (cmd->scan_end_arg + 2); } else { - if (cmd->scan_begin_arg < - cmd->convert_arg * cmd->chanlist_len) { - cmd->scan_begin_arg = - cmd->convert_arg * - cmd->chanlist_len; - err++; - } + arg = cmd->convert_arg * cmd->chanlist_len; } + err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, + arg); } } @@ -1330,23 +1275,23 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev, return 0; } -static int Compute_and_setup_dma(struct comedi_device *dev) +static int Compute_and_setup_dma(struct comedi_device *dev, + struct comedi_subdevice *s) { struct pci9118_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; unsigned int dmalen0, dmalen1, i; dmalen0 = devpriv->dmabuf_size[0]; dmalen1 = devpriv->dmabuf_size[1]; /* isn't output buff smaller that our DMA buff? */ - if (dmalen0 > (devpriv->ai_data_len)) { - dmalen0 = devpriv->ai_data_len & ~3L; /* - * align to 32bit down - */ + if (dmalen0 > s->async->prealloc_bufsz) { + /* align to 32bit down */ + dmalen0 = s->async->prealloc_bufsz & ~3L; } - if (dmalen1 > (devpriv->ai_data_len)) { - dmalen1 = devpriv->ai_data_len & ~3L; /* - * align to 32bit down - */ + if (dmalen1 > s->async->prealloc_bufsz) { + /* align to 32bit down */ + dmalen1 = s->async->prealloc_bufsz & ~3L; } /* we want wake up every scan? */ @@ -1360,8 +1305,6 @@ static int Compute_and_setup_dma(struct comedi_device *dev) } else { /* short first DMA buffer to one scan */ dmalen0 = devpriv->ai_n_realscanlen << 1; - if (devpriv->useeoshandle) - dmalen0 += 2; if (dmalen0 < 4) { dev_info(dev->class_dev, "ERR: DMA0 buf len bug? (%d<4)\n", @@ -1380,8 +1323,6 @@ static int Compute_and_setup_dma(struct comedi_device *dev) } else { /* short second DMA buffer to one scan */ dmalen1 = devpriv->ai_n_realscanlen << 1; - if (devpriv->useeoshandle) - dmalen1 -= 2; if (dmalen1 < 4) { dev_info(dev->class_dev, "ERR: DMA1 buf len bug? (%d<4)\n", @@ -1416,10 +1357,10 @@ static int Compute_and_setup_dma(struct comedi_device *dev) /* fits whole measure into one DMA buffer? */ if (dmalen0 > ((devpriv->ai_n_realscanlen << 1) * - devpriv->ai_scans)) { + cmd->stop_arg)) { dmalen0 = (devpriv->ai_n_realscanlen << 1) * - devpriv->ai_scans; + cmd->stop_arg; dmalen0 &= ~3L; } else { /* * fits whole measure into @@ -1427,10 +1368,10 @@ static int Compute_and_setup_dma(struct comedi_device *dev) */ if (dmalen1 > ((devpriv->ai_n_realscanlen << 1) * - devpriv->ai_scans - dmalen0)) + cmd->stop_arg - dmalen0)) dmalen1 = (devpriv->ai_n_realscanlen << 1) * - devpriv->ai_scans - dmalen0; + cmd->stop_arg - dmalen0; dmalen1 &= ~3L; } } @@ -1442,18 +1383,18 @@ static int Compute_and_setup_dma(struct comedi_device *dev) devpriv->dmabuf_use_size[1] = dmalen1; #if 0 - if (devpriv->ai_n_scanlen < this_board->half_fifo_size) { + if (cmd->scan_end_arg < this_board->half_fifo_size) { devpriv->dmabuf_panic_size[0] = - (this_board->half_fifo_size / devpriv->ai_n_scanlen + - 1) * devpriv->ai_n_scanlen * sizeof(short); + (this_board->half_fifo_size / cmd->scan_end_arg + + 1) * cmd->scan_end_arg * sizeof(short); devpriv->dmabuf_panic_size[1] = - (this_board->half_fifo_size / devpriv->ai_n_scanlen + - 1) * devpriv->ai_n_scanlen * sizeof(short); + (this_board->half_fifo_size / cmd->scan_end_arg + + 1) * cmd->scan_end_arg * sizeof(short); } else { devpriv->dmabuf_panic_size[0] = - (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[0]; + (cmd->scan_end_arg << 1) % devpriv->dmabuf_size[0]; devpriv->dmabuf_panic_size[1] = - (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[1]; + (cmd->scan_end_arg << 1) % devpriv->dmabuf_size[1]; } #endif @@ -1500,9 +1441,6 @@ static int pci9118_ai_docmd_sampl(struct comedi_device *dev, return -EIO; } - devpriv->int_ai_func = interrupt_pci9118_ai_onesample; - /* transfer function */ - if (devpriv->ai12_startstop) pci9118_exttrg_add(dev, EXTTRG_AI); /* activate EXT trigger */ @@ -1520,8 +1458,7 @@ static int pci9118_ai_docmd_sampl(struct comedi_device *dev, outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); if (devpriv->ai_do != 3) { - start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1, - devpriv->ai_divisor2); + pci9118_start_pacer(dev, devpriv->ai_do); devpriv->AdControlReg |= AdControl_SoftG; } outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); @@ -1534,8 +1471,9 @@ static int pci9118_ai_docmd_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct pci9118_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; - Compute_and_setup_dma(dev); + Compute_and_setup_dma(dev, s); switch (devpriv->ai_do) { case 1: @@ -1548,7 +1486,7 @@ static int pci9118_ai_docmd_dma(struct comedi_device *dev, devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg | AdFunction_BM | AdFunction_BS; - if (devpriv->usessh && (!devpriv->softsshdelay)) + if (cmd->convert_src == TRIG_NOW && !devpriv->softsshdelay) devpriv->AdFunctionReg |= AdFunction_BSSH; outl(devpriv->ai_n_realscanlen, dev->iobase + PCI9118_BURST); break; @@ -1580,9 +1518,6 @@ static int pci9118_ai_docmd_dma(struct comedi_device *dev, /* activate EXT trigger */ } - devpriv->int_ai_func = interrupt_pci9118_ai_dma; - /* transfer function */ - outl(0x02000000 | AINT_WRITE_COMPL, devpriv->iobase_a + AMCC_OP_REG_INTCSR); @@ -1590,8 +1525,7 @@ static int pci9118_ai_docmd_dma(struct comedi_device *dev, outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); if (devpriv->ai_do != 3) { - start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1, - devpriv->ai_divisor2); + pci9118_start_pacer(dev, devpriv->ai_do); devpriv->AdControlReg |= AdControl_SoftG; } outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); @@ -1610,12 +1544,6 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai12_startstop = 0; devpriv->ai_flags = cmd->flags; - devpriv->ai_n_chan = cmd->chanlist_len; - devpriv->ai_n_scanlen = cmd->scan_end_arg; - devpriv->ai_chanlist = cmd->chanlist; - devpriv->ai_data_len = s->async->prealloc_bufsz; - devpriv->ai_timer1 = 0; - devpriv->ai_timer2 = 0; devpriv->ai_add_front = 0; devpriv->ai_add_back = 0; devpriv->ai_maskerr = 0x10e; @@ -1629,31 +1557,12 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } if (cmd->start_src == TRIG_INT) { devpriv->ai12_startstop |= START_AI_INT; - devpriv->ai_inttrig_start = cmd->start_arg; s->async->inttrig = pci9118_ai_inttrig; } -#if 0 - if (cmd->stop_src == TRIG_INT) { - devpriv->ai_neverending = 1; - devpriv->ai12_startstop |= STOP_AI_INT; - } -#endif if (cmd->stop_src == TRIG_NONE) devpriv->ai_neverending = 1; - if (cmd->stop_src == TRIG_COUNT) { - devpriv->ai_scans = cmd->stop_arg; + if (cmd->stop_src == TRIG_COUNT) devpriv->ai_neverending = 0; - } else { - devpriv->ai_scans = 0; - } - - /* use sample&hold signal? */ - if (cmd->convert_src == TRIG_NOW) - devpriv->usessh = 1; - /* yes */ - else - devpriv->usessh = 0; - /* no */ /* * use additional sample at end of every scan @@ -1661,11 +1570,10 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) */ devpriv->ai_add_front = 0; devpriv->ai_add_back = 0; - devpriv->useeoshandle = 0; if (devpriv->master) { devpriv->usedma = 1; if ((cmd->flags & TRIG_WAKE_EOS) && - (devpriv->ai_n_scanlen == 1)) { + (cmd->scan_end_arg == 1)) { if (cmd->convert_src == TRIG_NOW) devpriv->ai_add_back = 1; if (cmd->convert_src == TRIG_TIMER) { @@ -1677,13 +1585,9 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } } if ((cmd->flags & TRIG_WAKE_EOS) && - (devpriv->ai_n_scanlen & 1) && - (devpriv->ai_n_scanlen > 1)) { + (cmd->scan_end_arg & 1) && + (cmd->scan_end_arg > 1)) { if (cmd->scan_begin_src == TRIG_FOLLOW) { - /* - * vpriv->useeoshandle=1; // change DMA transfer - * block to fit EOS on every second call - */ devpriv->usedma = 0; /* * XXX maybe can be corrected to use 16 bit DMA @@ -1703,7 +1607,7 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * we need software S&H signal? * It adds two samples before every scan as minimum */ - if (devpriv->usessh && devpriv->softsshdelay) { + if (cmd->convert_src == TRIG_NOW && devpriv->softsshdelay) { devpriv->ai_add_front = 2; if ((devpriv->usedma == 1) && (devpriv->ai_add_back == 1)) { /* move it to front */ @@ -1720,7 +1624,7 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_add_front = addchans + 1; if (devpriv->usedma == 1) if ((devpriv->ai_add_front + - devpriv->ai_n_chan + + cmd->chanlist_len + devpriv->ai_add_back) & 1) devpriv->ai_add_front++; /* round up to 32 bit */ @@ -1729,21 +1633,20 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* well, we now know what must be all added */ devpriv->ai_n_realscanlen = /* * what we must take from card in real - * to have ai_n_scanlen on output? + * to have cmd->scan_end_arg on output? */ - (devpriv->ai_add_front + devpriv->ai_n_chan + - devpriv->ai_add_back) * (devpriv->ai_n_scanlen / - devpriv->ai_n_chan); + (devpriv->ai_add_front + cmd->chanlist_len + + devpriv->ai_add_back) * (cmd->scan_end_arg / + cmd->chanlist_len); /* check and setup channel list */ - if (!check_channel_list(dev, s, devpriv->ai_n_chan, - devpriv->ai_chanlist, devpriv->ai_add_front, + if (!check_channel_list(dev, s, cmd->chanlist_len, + cmd->chanlist, devpriv->ai_add_front, devpriv->ai_add_back)) return -EINVAL; - if (!setup_channel_list(dev, s, devpriv->ai_n_chan, - devpriv->ai_chanlist, 0, devpriv->ai_add_front, - devpriv->ai_add_back, devpriv->usedma, - devpriv->useeoshandle)) + if (!setup_channel_list(dev, s, cmd->chanlist_len, + cmd->chanlist, 0, devpriv->ai_add_front, + devpriv->ai_add_back, devpriv->usedma)) return -EINVAL; /* compute timers settings */ @@ -1765,9 +1668,8 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_flags, devpriv->ai_n_realscanlen, &devpriv->ai_divisor1, - &devpriv->ai_divisor2, devpriv->usessh, + &devpriv->ai_divisor2, devpriv->ai_add_front); - devpriv->ai_timer2 = cmd->convert_arg; } if ((cmd->scan_begin_src == TRIG_TIMER) && @@ -1787,10 +1689,8 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_flags, devpriv->ai_n_realscanlen, &devpriv->ai_divisor1, - &devpriv->ai_divisor2, devpriv->usessh, + &devpriv->ai_divisor2, devpriv->ai_add_front); - devpriv->ai_timer1 = cmd->scan_begin_arg; - devpriv->ai_timer2 = cmd->convert_arg; } if ((cmd->scan_begin_src == TRIG_FOLLOW) @@ -1798,7 +1698,7 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_do = 3; } - start_pacer(dev, -1, 0, 0); /* stop pacer */ + pci9118_start_pacer(dev, -1); /* stop pacer */ devpriv->AdControlReg = 0; /* * bipolar, S.E., use 8254, stop 8354, @@ -1824,7 +1724,6 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_act_scan = 0; devpriv->ai_act_dmapos = 0; s->async->cur_chan = 0; - devpriv->ai_buf_ptr = 0; if (devpriv->usedma) ret = pci9118_ai_docmd_dma(dev, s); @@ -1845,7 +1744,7 @@ static int pci9118_reset(struct comedi_device *dev) /* disable interrupts source */ outl(0x30, dev->iobase + PCI9118_CNTCTRL); /* outl(0xb4, dev->iobase + PCI9118_CNTCTRL); */ - start_pacer(dev, 0, 0, 0); /* stop 8254 counters */ + pci9118_start_pacer(dev, 0); /* stop 8254 counters */ devpriv->AdControlReg = 0; outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); /* @@ -1888,7 +1787,6 @@ static int pci9118_reset(struct comedi_device *dev) * disable INT and DMA */ - devpriv->cnt0_users = 0; devpriv->exttrg_users = 0; return 0; @@ -1971,8 +1869,6 @@ static int pci9118_common_attach(struct comedi_device *dev, int disable_irq, if (devpriv->dmabuf_virt[i]) { devpriv->dmabuf_pages[i] = pages; devpriv->dmabuf_size[i] = PAGE_SIZE * pages; - devpriv->dmabuf_samples[i] = - devpriv->dmabuf_size[i] >> 1; devpriv->dmabuf_hw[i] = virt_to_bus((void *) devpriv->dmabuf_virt[i]); @@ -2015,7 +1911,7 @@ static int pci9118_common_attach(struct comedi_device *dev, int disable_irq, /* Enable parity check for parity error */ if (!disable_irq && pcidev->irq) { - ret = request_irq(pcidev->irq, interrupt_pci9118, IRQF_SHARED, + ret = request_irq(pcidev->irq, pci9118_interrupt, IRQF_SHARED, dev->board_name, dev); if (ret == 0) dev->irq = pcidev->irq; @@ -2074,22 +1970,11 @@ static int pci9118_common_attach(struct comedi_device *dev, int disable_irq, s->range_table = &range_digital; s->insn_bits = pci9118_insn_bits_do; - devpriv->valid = 1; - devpriv->i8254_osc_base = I8254_OSC_BASE_4MHZ; devpriv->ai_maskharderr = 0x10a; /* default measure crash condition */ if (hw_err_mask) /* disable some requested */ devpriv->ai_maskharderr &= ~hw_err_mask; - switch (this_board->ai_maxdata) { - case 0xffff: - devpriv->ai16bits = 1; - break; - default: - devpriv->ai16bits = 0; - break; - } - return 0; } @@ -2152,7 +2037,7 @@ static void pci9118_detach(struct comedi_device *dev) struct pci9118_private *devpriv = dev->private; if (devpriv) { - if (devpriv->valid) + if (dev->iobase) pci9118_reset(dev); if (dev->irq) free_irq(dev->irq, dev); diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 28ec48548317..602b7a1e40e6 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -51,10 +51,6 @@ Configuration options: #include "8253.h" #include "amcc_s5933.h" -#define PCI171x_PARANOIDCHECK /* if defined, then is used code which control - * correct channel number on every 12 bit - * sample */ - /* hardware types of the cards */ #define TYPE_PCI171X 0 #define TYPE_PCI1713 2 @@ -73,6 +69,9 @@ Configuration options: #define PCI171x_DAREF 14 /* W: D/A reference control */ #define PCI171x_DI 16 /* R: digi inputs */ #define PCI171x_DO 16 /* R: digi inputs */ + +#define PCI171X_TIMER_BASE 0x18 + #define PCI171x_CNT0 24 /* R/W: 8254 counter 0 */ #define PCI171x_CNT1 26 /* R/W: 8254 counter 1 */ #define PCI171x_CNT2 28 /* R/W: 8254 counter 2 */ @@ -298,29 +297,18 @@ static const struct boardtype boardtypes[] = { }; struct pci1710_private { - char neverending_ai; /* we do unlimited AI */ unsigned int CntrlReg; /* Control register */ - unsigned int i8254_osc_base; /* frequence of onboard oscilator */ - 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_act_chan; /* actual position in actual scan */ - unsigned int ai_buf_ptr; /* data buffer ptr in samples */ - unsigned char ai_eos; /* 1=EOS wake up */ unsigned char ai_et; unsigned int ai_et_CntrlReg; unsigned int ai_et_MuxVal; - unsigned int ai_et_div1, ai_et_div2; + unsigned int next_divisor1; + unsigned int next_divisor2; + unsigned int divisor1; + unsigned int divisor2; unsigned int act_chanlist[32]; /* list of scanned channel */ - unsigned char act_chanlist_len; /* len of scanlist */ - unsigned char act_chanlist_pos; /* actual position in MUX list */ + unsigned char saved_seglen; /* len of the non-repeating chanlist */ unsigned char da_ranges; /* copy of D/A outpit range register */ - unsigned int ai_scans; /* len of scanlist */ - unsigned int ai_n_chan; /* how many channels is measured */ - unsigned int *ai_chanlist; /* actaul chanlist */ - unsigned int ai_flags; /* flaglist */ - unsigned int ai_data_len; /* len of data buffer */ - unsigned int ai_timer1; /* timers */ - unsigned int ai_timer2; unsigned short ao_data[4]; /* data output buffer */ unsigned int cnt0_write_wait; /* after a write, wait for update of the * internal state */ @@ -334,62 +322,90 @@ static const unsigned int muxonechan[] = { 0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f }; -/* -============================================================================== - Check if channel list from user is built correctly - If it's ok, then program scan/gain logic. - This works for all cards. -*/ -static int check_channel_list(struct comedi_device *dev, +static int pci171x_ai_dropout(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int *chanlist, unsigned int n_chan) + unsigned int chan, + unsigned int val) +{ + const struct boardtype *board = comedi_board(dev); + struct pci1710_private *devpriv = dev->private; + + if (board->cardtype != TYPE_PCI1713) { + if ((val & 0xf000) != devpriv->act_chanlist[chan]) { + dev_err(dev->class_dev, + "A/D data droput: received from channel %d, expected %d\n", + (val >> 12) & 0xf, + (devpriv->act_chanlist[chan] >> 12) & 0xf); + return -ENODATA; + } + } + return 0; +} + +static int pci171x_ai_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) { + struct pci1710_private *devpriv = dev->private; + unsigned int chan0 = CR_CHAN(cmd->chanlist[0]); + unsigned int last_aref = CR_AREF(cmd->chanlist[0]); + unsigned int next_chan = (chan0 + 1) % s->n_chan; unsigned int chansegment[32]; - unsigned int i, nowmustbechan, seglen, segpos; + unsigned int seglen; + int i; - /* correct channel and range number check itself comedi/range.c */ - if (n_chan < 1) { - comedi_error(dev, "range/channel list is empty!"); + if (cmd->chanlist_len == 1) { + devpriv->saved_seglen = cmd->chanlist_len; return 0; } - if (n_chan == 1) - return 1; /* seglen=1 */ + /* first channel is always ok */ + chansegment[0] = cmd->chanlist[0]; - chansegment[0] = chanlist[0]; /* first channel is every time ok */ - for (i = 1, seglen = 1; i < n_chan; i++, seglen++) { - if (chanlist[0] == chanlist[i]) + for (i = 1; i < cmd->chanlist_len; i++) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); + unsigned int aref = CR_AREF(cmd->chanlist[i]); + + if (cmd->chanlist[0] == cmd->chanlist[i]) break; /* we detected a loop, stop */ - if ((CR_CHAN(chanlist[i]) & 1) && - (CR_AREF(chanlist[i]) == AREF_DIFF)) { - comedi_error(dev, "Odd channel cannot be differential input!\n"); - return 0; + + if (aref == AREF_DIFF && (chan & 1)) { + dev_err(dev->class_dev, + "Odd channel cannot be differential input!\n"); + return -EINVAL; } - nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan; - if (CR_AREF(chansegment[i - 1]) == AREF_DIFF) - nowmustbechan = (nowmustbechan + 1) % s->n_chan; - if (nowmustbechan != CR_CHAN(chanlist[i])) { - printk("channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n", - i, CR_CHAN(chanlist[i]), nowmustbechan, - CR_CHAN(chanlist[0])); - return 0; + + if (last_aref == AREF_DIFF) + next_chan = (next_chan + 1) % s->n_chan; + if (chan != next_chan) { + dev_err(dev->class_dev, + "channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n", + i, chan, next_chan, chan0); + return -EINVAL; } - chansegment[i] = chanlist[i]; /* next correct channel in list */ - } - for (i = 0, segpos = 0; i < n_chan; i++) { - if (chanlist[i] != chansegment[i % seglen]) { - printk("bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", - i, CR_CHAN(chansegment[i]), - CR_RANGE(chansegment[i]), - CR_AREF(chansegment[i]), - CR_CHAN(chanlist[i % seglen]), - CR_RANGE(chanlist[i % seglen]), - CR_AREF(chansegment[i % seglen])); - return 0; + /* next correct channel in list */ + chansegment[i] = cmd->chanlist[i]; + last_aref = aref; + } + seglen = i; + + for (i = 0; i < cmd->chanlist_len; i++) { + if (cmd->chanlist[i] != chansegment[i % seglen]) { + dev_err(dev->class_dev, + "bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", + i, CR_CHAN(chansegment[i]), + CR_RANGE(chansegment[i]), + CR_AREF(chansegment[i]), + CR_CHAN(cmd->chanlist[i % seglen]), + CR_RANGE(cmd->chanlist[i % seglen]), + CR_AREF(chansegment[i % seglen])); + return -EINVAL; } } - return seglen; + devpriv->saved_seglen = seglen; + + return 0; } static void setup_channel_list(struct comedi_device *dev, @@ -401,9 +417,6 @@ static void setup_channel_list(struct comedi_device *dev, struct pci1710_private *devpriv = dev->private; unsigned int i, range, chanprog; - devpriv->act_chanlist_len = seglen; - devpriv->act_chanlist_pos = 0; - for (i = 0; i < seglen; i++) { /* store range list to card */ chanprog = muxonechan[CR_CHAN(chanlist[i])]; outw(chanprog, dev->iobase + PCI171x_MUX); /* select channel */ @@ -411,17 +424,13 @@ static void setup_channel_list(struct comedi_device *dev, if (CR_AREF(chanlist[i]) == AREF_DIFF) range |= 0x0020; outw(range, dev->iobase + PCI171x_RANGE); /* select gain */ -#ifdef PCI171x_PARANOIDCHECK devpriv->act_chanlist[i] = (CR_CHAN(chanlist[i]) << 12) & 0xf000; -#endif } -#ifdef PCI171x_PARANOIDCHECK for ( ; i < n_chan; i++) { /* store remainder of channel list */ devpriv->act_chanlist[i] = (CR_CHAN(chanlist[i]) << 12) & 0xf000; } -#endif devpriv->ai_et_MuxVal = CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8); @@ -447,12 +456,9 @@ static int pci171x_insn_read_ai(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { struct pci1710_private *devpriv = dev->private; - int ret; - int n; -#ifdef PCI171x_PARANOIDCHECK - const struct boardtype *this_board = comedi_board(dev); - unsigned int idata; -#endif + unsigned int chan = CR_CHAN(insn->chanspec); + int ret = 0; + int i; devpriv->CntrlReg &= Control_CNT0; devpriv->CntrlReg |= Control_SW; /* set software trigger */ @@ -462,34 +468,27 @@ static int pci171x_insn_read_ai(struct comedi_device *dev, setup_channel_list(dev, s, &insn->chanspec, 1, 1); - for (n = 0; n < insn->n; n++) { + for (i = 0; i < insn->n; i++) { + unsigned int val; + outw(0, dev->iobase + PCI171x_SOFTTRG); /* start conversion */ ret = comedi_timeout(dev, s, insn, pci171x_ai_eoc, 0); - if (ret) { - outb(0, dev->iobase + PCI171x_CLRFIFO); - outb(0, dev->iobase + PCI171x_CLRINT); - return ret; - } + if (ret) + break; -#ifdef PCI171x_PARANOIDCHECK - idata = inw(dev->iobase + PCI171x_AD_DATA); - if (this_board->cardtype != TYPE_PCI1713) - if ((idata & 0xf000) != devpriv->act_chanlist[0]) { - comedi_error(dev, "A/D insn data droput!"); - return -ETIME; - } - data[n] = idata & 0x0fff; -#else - data[n] = inw(dev->iobase + PCI171x_AD_DATA) & 0x0fff; -#endif + val = inw(dev->iobase + PCI171x_AD_DATA); + ret = pci171x_ai_dropout(dev, s, chan, val); + if (ret) + break; + data[i] = val & s->maxdata; } outb(0, dev->iobase + PCI171x_CLRFIFO); outb(0, dev->iobase + PCI171x_CLRINT); - return n; + return ret ? ret : insn->n; } /* @@ -571,20 +570,18 @@ static int pci171x_insn_bits_do(struct comedi_device *dev, return insn->n; } -/* -============================================================================== -*/ -static void start_pacer(struct comedi_device *dev, int mode, - unsigned int divisor1, unsigned int divisor2) +static void pci171x_start_pacer(struct comedi_device *dev, + bool load_counters) { - outw(0xb4, dev->iobase + PCI171x_CNTCTRL); - outw(0x74, dev->iobase + PCI171x_CNTCTRL); - - if (mode == 1) { - outw(divisor2 & 0xff, dev->iobase + PCI171x_CNT2); - outw((divisor2 >> 8) & 0xff, dev->iobase + PCI171x_CNT2); - outw(divisor1 & 0xff, dev->iobase + PCI171x_CNT1); - outw((divisor1 >> 8) & 0xff, dev->iobase + PCI171x_CNT1); + struct pci1710_private *devpriv = dev->private; + unsigned long timer_base = dev->iobase + PCI171X_TIMER_BASE; + + i8254_set_mode(timer_base, 1, 2, I8254_MODE2 | I8254_BINARY); + i8254_set_mode(timer_base, 1, 1, I8254_MODE2 | I8254_BINARY); + + if (load_counters) { + i8254_write(timer_base, 1, 2, devpriv->divisor2); + i8254_write(timer_base, 1, 1, devpriv->divisor1); } } @@ -727,45 +724,37 @@ static int pci171x_ai_cancel(struct comedi_device *dev, devpriv->CntrlReg |= Control_SW; outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */ - start_pacer(dev, -1, 0, 0); + pci171x_start_pacer(dev, false); outb(0, dev->iobase + PCI171x_CLRFIFO); outb(0, dev->iobase + PCI171x_CLRINT); break; } - devpriv->ai_do = 0; devpriv->ai_act_scan = 0; s->async->cur_chan = 0; - devpriv->ai_buf_ptr = 0; - devpriv->neverending_ai = 0; return 0; } -/* -============================================================================== -*/ -static void interrupt_pci1710_every_sample(void *d) +static void pci1710_handle_every_sample(struct comedi_device *dev, + struct comedi_subdevice *s) { - struct comedi_device *dev = d; struct pci1710_private *devpriv = dev->private; - struct comedi_subdevice *s = dev->read_subdev; - int m; -#ifdef PCI171x_PARANOIDCHECK - const struct boardtype *this_board = comedi_board(dev); - unsigned short sampl; -#endif + struct comedi_cmd *cmd = &s->async->cmd; + unsigned int status; + unsigned int val; + int ret; - m = inw(dev->iobase + PCI171x_STATUS); - if (m & Status_FE) { - dev_dbg(dev->class_dev, "A/D FIFO empty (%4x)\n", m); + status = inw(dev->iobase + PCI171x_STATUS); + 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); return; } - if (m & Status_FF) { + if (status & Status_FF) { dev_dbg(dev->class_dev, - "A/D FIFO Full status (Fatal Error!) (%4x)\n", m); + "A/D FIFO Full status (Fatal Error!) (%4x)\n", status); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; cfc_handle_events(dev, s); return; @@ -774,42 +763,27 @@ static void interrupt_pci1710_every_sample(void *d) outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ for (; !(inw(dev->iobase + PCI171x_STATUS) & Status_FE);) { -#ifdef PCI171x_PARANOIDCHECK - sampl = inw(dev->iobase + PCI171x_AD_DATA); - if (this_board->cardtype != TYPE_PCI1713) - if ((sampl & 0xf000) != - devpriv->act_chanlist[s->async->cur_chan]) { - printk - ("comedi: A/D data dropout: received data from channel %d, expected %d!\n", - (sampl & 0xf000) >> 12, - (devpriv-> - act_chanlist[s-> - async->cur_chan] & 0xf000) >> - 12); - s->async->events |= - COMEDI_CB_EOA | COMEDI_CB_ERROR; - cfc_handle_events(dev, s); - return; - } - comedi_buf_put(s->async, sampl & 0x0fff); -#else - comedi_buf_put(s->async, - inw(dev->iobase + PCI171x_AD_DATA) & 0x0fff); -#endif - ++s->async->cur_chan; + val = inw(dev->iobase + PCI171x_AD_DATA); + ret = pci171x_ai_dropout(dev, s, s->async->cur_chan, val); + if (ret) { + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + break; + } - if (s->async->cur_chan >= devpriv->ai_n_chan) + comedi_buf_put(s, val & s->maxdata); + + s->async->cur_chan++; + if (s->async->cur_chan >= cmd->chanlist_len) s->async->cur_chan = 0; if (s->async->cur_chan == 0) { /* one scan done */ devpriv->ai_act_scan++; - if ((!devpriv->neverending_ai) && - (devpriv->ai_act_scan >= devpriv->ai_scans)) { + if (cmd->stop_src == TRIG_COUNT && + devpriv->ai_act_scan >= cmd->stop_arg) { /* all data sampled */ s->async->events |= COMEDI_CB_EOA; - cfc_handle_events(dev, s); - return; + break; } } } @@ -826,53 +800,37 @@ static int move_block_from_fifo(struct comedi_device *dev, struct comedi_subdevice *s, int n, int turn) { struct pci1710_private *devpriv = dev->private; - int i, j; -#ifdef PCI171x_PARANOIDCHECK - const struct boardtype *this_board = comedi_board(dev); - unsigned short sampl; -#endif + struct comedi_cmd *cmd = &s->async->cmd; + unsigned int val; + int ret; + int i; - j = s->async->cur_chan; for (i = 0; i < n; i++) { -#ifdef PCI171x_PARANOIDCHECK - sampl = inw(dev->iobase + PCI171x_AD_DATA); - if (this_board->cardtype != TYPE_PCI1713) - if ((sampl & 0xf000) != devpriv->act_chanlist[j]) { - dev_dbg(dev->class_dev, - "A/D FIFO data dropout: received data from channel %d, expected %d! (%d/%d/%d/%d/%d/%4x)\n", - (sampl & 0xf000) >> 12, - (devpriv->act_chanlist[j] & 0xf000) >> 12, - i, j, devpriv->ai_act_scan, n, turn, - sampl); - s->async->events |= - COMEDI_CB_EOA | COMEDI_CB_ERROR; - cfc_handle_events(dev, s); - return 1; - } - comedi_buf_put(s->async, sampl & 0x0fff); -#else - comedi_buf_put(s->async, - inw(dev->iobase + PCI171x_AD_DATA) & 0x0fff); -#endif - j++; - if (j >= devpriv->ai_n_chan) { - j = 0; + val = inw(dev->iobase + PCI171x_AD_DATA); + + ret = pci171x_ai_dropout(dev, s, s->async->cur_chan, val); + if (ret) { + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + 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++; } } - s->async->cur_chan = j; return 0; } -/* -============================================================================== -*/ -static void interrupt_pci1710_half_fifo(void *d) +static void pci1710_handle_fifo(struct comedi_device *dev, + struct comedi_subdevice *s) { - struct comedi_device *dev = d; const struct boardtype *this_board = comedi_board(dev); struct pci1710_private *devpriv = dev->private; - struct comedi_subdevice *s = dev->read_subdev; + struct comedi_cmd *cmd = &s->async->cmd; int m, samplesinbuf; m = inw(dev->iobase + PCI171x_STATUS); @@ -891,8 +849,8 @@ static void interrupt_pci1710_half_fifo(void *d) } samplesinbuf = this_board->fifo_half_size; - if (samplesinbuf * sizeof(short) >= devpriv->ai_data_len) { - m = devpriv->ai_data_len / sizeof(short); + if (samplesinbuf * sizeof(short) >= s->async->prealloc_bufsz) { + m = s->async->prealloc_bufsz / sizeof(short); if (move_block_from_fifo(dev, s, m, 0)) return; samplesinbuf -= m; @@ -903,13 +861,13 @@ static void interrupt_pci1710_half_fifo(void *d) return; } - if (!devpriv->neverending_ai) - if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data - sampled */ - s->async->events |= COMEDI_CB_EOA; - cfc_handle_events(dev, s); - return; - } + if (cmd->stop_src == TRIG_COUNT && + devpriv->ai_act_scan >= cmd->stop_arg) { + /* all data sampled */ + s->async->events |= COMEDI_CB_EOA; + cfc_handle_events(dev, s); + return; + } outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ cfc_handle_events(dev, s); @@ -922,9 +880,15 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d) { struct comedi_device *dev = d; struct pci1710_private *devpriv = dev->private; + struct comedi_subdevice *s; + struct comedi_cmd *cmd; if (!dev->attached) /* is device attached? */ return IRQ_NONE; /* no, exit */ + + s = dev->read_subdev; + cmd = &s->async->cmd; + /* is this interrupt from our board? */ if (!(inw(dev->iobase + PCI171x_STATUS) & Status_IRQ)) return IRQ_NONE; /* no, exit */ @@ -939,95 +903,59 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d) outb(0, dev->iobase + PCI171x_CLRINT); outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX); outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); - /* start pacer */ - start_pacer(dev, 1, devpriv->ai_et_div1, devpriv->ai_et_div2); + pci171x_start_pacer(dev, true); return IRQ_HANDLED; } - if (devpriv->ai_eos) { /* We use FIFO half full INT or not? */ - interrupt_pci1710_every_sample(d); - } else { - interrupt_pci1710_half_fifo(d); - } + + if (cmd->flags & TRIG_WAKE_EOS) + pci1710_handle_every_sample(dev, s); + else + pci1710_handle_fifo(dev, s); + return IRQ_HANDLED; } -/* -============================================================================== -*/ -static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev, - struct comedi_subdevice *s) +static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - const struct boardtype *this_board = comedi_board(dev); struct pci1710_private *devpriv = dev->private; - unsigned int divisor1 = 0, divisor2 = 0; - unsigned int seglen; + struct comedi_cmd *cmd = &s->async->cmd; - start_pacer(dev, -1, 0, 0); /* stop pacer */ + pci171x_start_pacer(dev, false); - seglen = check_channel_list(dev, s, devpriv->ai_chanlist, - devpriv->ai_n_chan); - if (seglen < 1) - return -EINVAL; - setup_channel_list(dev, s, devpriv->ai_chanlist, - devpriv->ai_n_chan, seglen); + setup_channel_list(dev, s, cmd->chanlist, cmd->chanlist_len, + devpriv->saved_seglen); outb(0, dev->iobase + PCI171x_CLRFIFO); outb(0, dev->iobase + PCI171x_CLRINT); - devpriv->ai_do = mode; - devpriv->ai_act_scan = 0; s->async->cur_chan = 0; - devpriv->ai_buf_ptr = 0; - devpriv->neverending_ai = 0; devpriv->CntrlReg &= Control_CNT0; - /* don't we want wake up every scan? devpriv->ai_eos=1; */ - if ((devpriv->ai_flags & TRIG_WAKE_EOS)) { - devpriv->ai_eos = 1; - } else { + if ((cmd->flags & TRIG_WAKE_EOS) == 0) devpriv->CntrlReg |= Control_ONEFH; - devpriv->ai_eos = 0; - } - if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1)) - devpriv->neverending_ai = 1; - /* well, user want neverending */ - else - devpriv->neverending_ai = 0; + devpriv->divisor1 = devpriv->next_divisor1; + devpriv->divisor2 = devpriv->next_divisor2; - switch (mode) { - case 1: - case 2: - if (devpriv->ai_timer1 < this_board->ai_ns_min) - devpriv->ai_timer1 = this_board->ai_ns_min; + if (cmd->convert_src == TRIG_TIMER) { devpriv->CntrlReg |= Control_PACER | Control_IRQEN; - if (mode == 2) { + if (cmd->start_src == TRIG_EXT) { devpriv->ai_et_CntrlReg = devpriv->CntrlReg; devpriv->CntrlReg &= ~(Control_PACER | Control_ONEFH | Control_GATE); devpriv->CntrlReg |= Control_EXT; devpriv->ai_et = 1; - } else { + } else { /* TRIG_NOW */ devpriv->ai_et = 0; } - i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, - &divisor1, &divisor2, - &devpriv->ai_timer1, - devpriv->ai_flags); outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); - if (mode != 2) { - /* start pacer */ - start_pacer(dev, mode, divisor1, divisor2); - } else { - devpriv->ai_et_div1 = divisor1; - devpriv->ai_et_div2 = divisor2; - } - break; - case 3: + + if (cmd->start_src == TRIG_NOW) + pci171x_start_pacer(dev, true); + } else { /* TRIG_EXT */ devpriv->CntrlReg |= Control_EXT | Control_IRQEN; outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); - break; } return 0; @@ -1043,8 +971,7 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, const struct boardtype *this_board = comedi_board(dev); struct pci1710_private *devpriv = dev->private; int err = 0; - int tmp; - unsigned int divisor1 = 0, divisor2 = 0; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -1092,64 +1019,25 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ if (cmd->convert_src == TRIG_TIMER) { - tmp = cmd->convert_arg; - i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, - &divisor1, &divisor2, - &cmd->convert_arg, cmd->flags); - if (cmd->convert_arg < this_board->ai_ns_min) - cmd->convert_arg = this_board->ai_ns_min; - if (tmp != cmd->convert_arg) - err++; + arg = cmd->convert_arg; + i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, + &devpriv->next_divisor1, + &devpriv->next_divisor2, + &arg, cmd->flags); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); } if (err) return 4; - /* step 5: complain about special chanlist considerations */ + /* Step 5: check channel list */ - if (cmd->chanlist) { - if (!check_channel_list(dev, s, cmd->chanlist, - cmd->chanlist_len)) - return 5; /* incorrect channels list */ - } + err |= pci171x_ai_check_chanlist(dev, s, cmd); - return 0; -} - -/* -============================================================================== -*/ -static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) -{ - struct pci1710_private *devpriv = dev->private; - struct comedi_cmd *cmd = &s->async->cmd; - - devpriv->ai_n_chan = cmd->chanlist_len; - devpriv->ai_chanlist = cmd->chanlist; - devpriv->ai_flags = cmd->flags; - devpriv->ai_data_len = s->async->prealloc_bufsz; - devpriv->ai_timer1 = 0; - devpriv->ai_timer2 = 0; - - if (cmd->stop_src == TRIG_COUNT) - devpriv->ai_scans = cmd->stop_arg; - else - devpriv->ai_scans = 0; - - - if (cmd->scan_begin_src == TRIG_FOLLOW) { /* mode 1, 2, 3 */ - if (cmd->convert_src == TRIG_TIMER) { /* mode 1 and 2 */ - devpriv->ai_timer1 = cmd->convert_arg; - return pci171x_ai_docmd_and_mode(cmd->start_src == - TRIG_EXT ? 2 : 1, dev, - s); - } - if (cmd->convert_src == TRIG_EXT) { /* mode 3 */ - return pci171x_ai_docmd_and_mode(3, dev, s); - } - } + if (err) + return 5; - return -1; + return 0; } /* @@ -1165,7 +1053,7 @@ static int pci171x_reset(struct comedi_device *dev) outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */ outb(0, dev->iobase + PCI171x_CLRFIFO); /* clear FIFO */ outb(0, dev->iobase + PCI171x_CLRINT); /* clear INT request */ - start_pacer(dev, -1, 0, 0); /* stop 8254 */ + pci171x_start_pacer(dev, false); devpriv->da_ranges = 0; if (this_board->n_aochan) { outb(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); /* set DACs to 0..5V */ @@ -1290,7 +1178,6 @@ static int pci1710_auto_attach(struct comedi_device *dev, s->do_cmd = pci171x_ai_cmd; s->cancel = pci171x_ai_cancel; } - devpriv->i8254_osc_base = I8254_OSC_BASE_10MHZ; subdev++; } diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c index 818a0d7e3d58..3edaa4028da2 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_common.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c @@ -130,7 +130,6 @@ struct dio200_subdev_intr { unsigned int enabled_isns; unsigned int stopcount; bool active:1; - bool continuous:1; }; static inline const struct dio200_layout * @@ -259,7 +258,7 @@ static int dio200_start_intr(struct comedi_device *dev, struct comedi_cmd *cmd = &s->async->cmd; int retval = 0; - if (!subpriv->continuous && subpriv->stopcount == 0) { + if (cmd->stop_src == TRIG_COUNT && subpriv->stopcount == 0) { /* An empty acquisition! */ s->async->events |= COMEDI_CB_EOA; subpriv->active = false; @@ -281,22 +280,18 @@ static int dio200_start_intr(struct comedi_device *dev, return retval; } -/* - * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice. - */ -static int -dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int trignum) +static int dio200_inttrig_start_intr(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int trig_num) { - struct dio200_subdev_intr *subpriv; + struct dio200_subdev_intr *subpriv = s->private; + struct comedi_cmd *cmd = &s->async->cmd; unsigned long flags; int event = 0; - if (trignum != 0) + if (trig_num != cmd->start_arg) return -EINVAL; - subpriv = s->private; - spin_lock_irqsave(&subpriv->spinlock, flags); s->async->inttrig = NULL; if (subpriv->active) @@ -315,18 +310,18 @@ static void dio200_read_scan_intr(struct comedi_device *dev, unsigned int triggered) { struct dio200_subdev_intr *subpriv = s->private; + struct comedi_cmd *cmd = &s->async->cmd; unsigned short val; - unsigned int n, ch, len; + unsigned int n, ch; val = 0; - len = s->async->cmd.chanlist_len; - for (n = 0; n < len; n++) { - ch = CR_CHAN(s->async->cmd.chanlist[n]); + for (n = 0; n < cmd->chanlist_len; n++) { + ch = CR_CHAN(cmd->chanlist[n]); if (triggered & (1U << ch)) val |= (1U << n); } /* Write the scan to the buffer. */ - if (comedi_buf_put(s->async, val)) { + if (comedi_buf_put(s, val)) { s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS); } else { /* Error! Stop acquisition. */ @@ -336,8 +331,7 @@ static void dio200_read_scan_intr(struct comedi_device *dev, } /* Check for end of acquisition. */ - if (!subpriv->continuous) { - /* stop_src == TRIG_COUNT */ + if (cmd->stop_src == TRIG_COUNT) { if (subpriv->stopcount > 0) { subpriv->stopcount--; if (subpriv->stopcount == 0) { @@ -516,28 +510,16 @@ static int dio200_subdev_intr_cmd(struct comedi_device *dev, subpriv->active = true; /* Set up end of acquisition. */ - switch (cmd->stop_src) { - case TRIG_COUNT: - subpriv->continuous = false; + if (cmd->stop_src == TRIG_COUNT) subpriv->stopcount = cmd->stop_arg; - break; - default: - /* TRIG_NONE */ - subpriv->continuous = true; + else /* TRIG_NONE */ subpriv->stopcount = 0; - break; - } - /* Set up start of acquisition. */ - switch (cmd->start_src) { - case TRIG_INT: + if (cmd->start_src == TRIG_INT) s->async->inttrig = dio200_inttrig_start_intr; - break; - default: - /* TRIG_NOW */ + else /* TRIG_NOW */ event = dio200_start_intr(dev, s); - break; - } + spin_unlock_irqrestore(&subpriv->spinlock, flags); if (event) @@ -829,7 +811,7 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s, spin_lock_irqsave(&subpriv->spinlock, flags); switch (data[0]) { case INSN_CONFIG_SET_COUNTER_MODE: - if (data[1] > (I8254_MODE5 | I8254_BINARY)) + if (data[1] > (I8254_MODE5 | I8254_BCD)) ret = -EINVAL; else dio200_subdev_8254_set_mode(dev, s, chan, data[1]); diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index b21d7b48f1da..c9a96ad00559 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -314,7 +314,7 @@ static int pc236_intr_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); - err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, 1); + err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); if (err) @@ -361,7 +361,7 @@ static irqreturn_t pc236_interrupt(int irq, void *d) handled = pc236_intr_check(dev); if (dev->attached && handled) { - comedi_buf_put(s->async, 0); + comedi_buf_put(s, 0); s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; comedi_event(dev, s); } @@ -402,6 +402,7 @@ static int pc236_common_attach(struct comedi_device *dev, unsigned long iobase, s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = pc236_intr_insn; + s->len_chanlist = 1; s->do_cmdtest = pc236_intr_cmdtest; s->do_cmd = pc236_intr_cmd; s->cancel = pc236_intr_cancel; diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 29e01e280039..339c47c1eb97 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -377,7 +377,6 @@ struct pci224_private { unsigned int cached_div1; unsigned int cached_div2; unsigned int ao_stop_count; - short ao_stop_continuous; unsigned short ao_enab; /* max 16 channels so 'short' will do */ unsigned char intsce; }; @@ -467,16 +466,6 @@ pci224_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, } /* - * Just a wrapper for the inline function 'i8253_cascade_ns_to_timer'. - */ -static void -pci224_cascade_ns_to_timer(int osc_base, unsigned int *d1, unsigned int *d2, - unsigned int *nanosec, int round_mode) -{ - i8253_cascade_ns_to_timer(osc_base, d1, d2, nanosec, round_mode); -} - -/* * Kills a command running on the AO subdevice. */ static void pci224_ao_stop(struct comedi_device *dev, @@ -531,7 +520,7 @@ static void pci224_ao_start(struct comedi_device *dev, unsigned long flags; set_bit(AO_CMD_STARTED, &devpriv->state); - if (!devpriv->ao_stop_continuous && devpriv->ao_stop_count == 0) { + if (cmd->stop_src == TRIG_COUNT && devpriv->ao_stop_count == 0) { /* An empty acquisition! */ s->async->events |= COMEDI_CB_EOA; cfc_handle_events(dev, s); @@ -556,21 +545,15 @@ 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 room; unsigned short dacstat; unsigned int i, n; - unsigned int bytes_per_scan; - if (cmd->chanlist_len) { - bytes_per_scan = cmd->chanlist_len * sizeof(short); - } else { - /* Shouldn't get here! */ - bytes_per_scan = sizeof(short); - } /* Determine number of scans available in buffer. */ - num_scans = comedi_buf_read_n_available(s->async) / bytes_per_scan; - if (!devpriv->ao_stop_continuous) { + 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; @@ -582,7 +565,7 @@ static void pci224_ao_handle_fifo(struct comedi_device *dev, switch (dacstat & PCI224_DACCON_FIFOFL_MASK) { case PCI224_DACCON_FIFOFL_EMPTY: room = PCI224_FIFO_ROOM_EMPTY; - if (!devpriv->ao_stop_continuous && devpriv->ao_stop_count == 0) { + if (cmd->stop_src == TRIG_COUNT && devpriv->ao_stop_count == 0) { /* FIFO empty at end of counted acquisition. */ s->async->events |= COMEDI_CB_EOA; cfc_handle_events(dev, s); @@ -608,8 +591,7 @@ static void pci224_ao_handle_fifo(struct comedi_device *dev, } } /* Determine how many new scans can be put in the FIFO. */ - if (cmd->chanlist_len) - room /= cmd->chanlist_len; + room /= cmd->chanlist_len; /* Determine how many scans to process. */ if (num_scans > room) @@ -624,7 +606,7 @@ static void pci224_ao_handle_fifo(struct comedi_device *dev, dev->iobase + PCI224_DACDATA); } } - if (!devpriv->ao_stop_continuous) { + if (cmd->stop_src == TRIG_COUNT) { devpriv->ao_stop_count -= num_scans; if (devpriv->ao_stop_count == 0) { /* @@ -671,14 +653,13 @@ static void pci224_ao_handle_fifo(struct comedi_device *dev, cfc_handle_events(dev, s); } -/* - * Internal trigger function to start acquisition on AO subdevice. - */ -static int -pci224_ao_inttrig_start(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int trignum) +static int pci224_ao_inttrig_start(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int trig_num) { - if (trignum != 0) + struct comedi_cmd *cmd = &s->async->cmd; + + if (trig_num != cmd->start_arg) return -EINVAL; s->async->inttrig = NULL; @@ -687,6 +668,37 @@ pci224_ao_inttrig_start(struct comedi_device *dev, struct comedi_subdevice *s, return 1; } +static int pci224_ao_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + unsigned int range0 = CR_RANGE(cmd->chanlist[0]); + unsigned int chan_mask = 0; + int i; + + for (i = 0; i < cmd->chanlist_len; i++) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); + unsigned int range = CR_RANGE(cmd->chanlist[i]); + + if (chan_mask & (1 << chan)) { + dev_dbg(dev->class_dev, + "%s: entries in chanlist must contain no duplicate channels\n", + __func__); + return -EINVAL; + } + chan_mask |= (1 << chan); + + if (range != range0) { + dev_dbg(dev->class_dev, + "%s: entries in chanlist must all have the same range index\n", + __func__); + return -EINVAL; + } + } + + return 0; +} + #define MAX_SCAN_PERIOD 0xFFFFFFFFU #define MIN_SCAN_PERIOD 2500 #define CONVERT_PERIOD 625 @@ -700,7 +712,7 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, { struct pci224_private *devpriv = dev->private; int err = 0; - unsigned int tmp; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -727,14 +739,14 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, * There's only one external trigger signal (which makes these * tests easier). Only one thing can use it. */ - tmp = 0; + arg = 0; if (cmd->start_src & TRIG_EXT) - tmp++; + arg++; if (cmd->scan_begin_src & TRIG_EXT) - tmp++; + arg++; if (cmd->stop_src & TRIG_EXT) - tmp++; - if (tmp > 1) + arg++; + if (arg > 1) err |= -EINVAL; if (err) @@ -767,10 +779,10 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, MAX_SCAN_PERIOD); - tmp = cmd->chanlist_len * CONVERT_PERIOD; - if (tmp < MIN_SCAN_PERIOD) - tmp = MIN_SCAN_PERIOD; - err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, tmp); + arg = cmd->chanlist_len * CONVERT_PERIOD; + if (arg < MIN_SCAN_PERIOD) + arg = MIN_SCAN_PERIOD; + err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, arg); break; case TRIG_EXT: /* Force to external trigger 0. */ @@ -821,98 +833,21 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, /* Step 4: fix up any arguments. */ if (cmd->scan_begin_src == TRIG_TIMER) { - unsigned int div1, div2, round; - int round_mode = cmd->flags & TRIG_ROUND_MASK; - - tmp = cmd->scan_begin_arg; - /* Check whether to use a single timer. */ - switch (round_mode) { - case TRIG_ROUND_NEAREST: - default: - round = I8254_OSC_BASE_10MHZ / 2; - break; - case TRIG_ROUND_DOWN: - round = 0; - break; - case TRIG_ROUND_UP: - round = I8254_OSC_BASE_10MHZ - 1; - break; - } - /* Be careful to avoid overflow! */ - div2 = cmd->scan_begin_arg / I8254_OSC_BASE_10MHZ; - div2 += (round + cmd->scan_begin_arg % I8254_OSC_BASE_10MHZ) / - I8254_OSC_BASE_10MHZ; - if (div2 <= 0x10000) { - /* A single timer will suffice. */ - if (div2 < 2) - div2 = 2; - cmd->scan_begin_arg = div2 * I8254_OSC_BASE_10MHZ; - if (cmd->scan_begin_arg < div2 || - cmd->scan_begin_arg < I8254_OSC_BASE_10MHZ) { - /* Overflow! */ - cmd->scan_begin_arg = MAX_SCAN_PERIOD; - } - } else { - /* Use two timers. */ - div1 = devpriv->cached_div1; - div2 = devpriv->cached_div2; - pci224_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, - &div1, &div2, - &cmd->scan_begin_arg, - round_mode); - devpriv->cached_div1 = div1; - devpriv->cached_div2 = div2; - } - if (tmp != cmd->scan_begin_arg) - err++; - + arg = cmd->scan_begin_arg; + /* Use two timers. */ + i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, + &devpriv->cached_div1, + &devpriv->cached_div2, + &arg, cmd->flags); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (err) return 4; - /* Step 5: check channel list. */ - - if (cmd->chanlist && (cmd->chanlist_len > 0)) { - unsigned int range; - enum { range_err = 1, dupchan_err = 2, }; - unsigned errors; - unsigned int n; - unsigned int ch; - - /* - * Check all channels have the same range index. Don't care - * about analogue reference, as we can't configure it. - * - * Check the list has no duplicate channels. - */ - range = CR_RANGE(cmd->chanlist[0]); - errors = 0; - tmp = 0; - for (n = 0; n < cmd->chanlist_len; n++) { - ch = CR_CHAN(cmd->chanlist[n]); - if (tmp & (1U << ch)) - errors |= dupchan_err; - - tmp |= (1U << ch); - if (CR_RANGE(cmd->chanlist[n]) != range) - errors |= range_err; - - } - if (errors) { - if (errors & dupchan_err) { - dev_dbg(dev->class_dev, - "%s: entries in chanlist must contain no duplicate channels\n", - __func__); - } - if (errors & range_err) { - dev_dbg(dev->class_dev, - "%s: entries in chanlist must all have the same range index\n", - __func__); - } - err++; - } - } + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= pci224_ao_check_chanlist(dev, s, cmd); if (err) return 5; @@ -920,9 +855,33 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, return 0; } -/* - * 'do_cmd' function for AO subdevice. - */ +static void pci224_ao_start_pacer(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct pci224_private *devpriv = dev->private; + unsigned long timer_base = devpriv->iobase1 + PCI224_Z2_CT0; + + /* + * The output of timer Z2-0 will be used as the scan trigger + * source. + */ + /* Make sure Z2-0 is gated on. */ + outb(GAT_CONFIG(0, GAT_VCC), devpriv->iobase1 + PCI224_ZGAT_SCE); + /* Cascading with Z2-2. */ + /* Make sure Z2-2 is gated on. */ + outb(GAT_CONFIG(2, GAT_VCC), devpriv->iobase1 + PCI224_ZGAT_SCE); + /* Z2-2 needs 10 MHz clock. */ + outb(CLK_CONFIG(2, CLK_10MHZ), devpriv->iobase1 + PCI224_ZCLK_SCE); + /* Load Z2-2 mode (2) and counter (div1). */ + i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY); + i8254_write(timer_base, 0, 2, devpriv->cached_div1); + /* Z2-0 is clocked from Z2-2's output. */ + outb(CLK_CONFIG(0, CLK_OUTNM1), devpriv->iobase1 + PCI224_ZCLK_SCE); + /* Load Z2-0 mode (2) and counter (div2). */ + i8254_set_mode(timer_base, 0, 0, I8254_MODE2 | I8254_BINARY); + i8254_write(timer_base, 0, 0, devpriv->cached_div2); +} + static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct pci224_private *devpriv = dev->private; @@ -978,106 +937,26 @@ static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) outw(devpriv->daccon | PCI224_DACCON_FIFORESET, dev->iobase + PCI224_DACCON); - if (cmd->scan_begin_src == TRIG_TIMER) { - unsigned int div1, div2, round; - unsigned int ns = cmd->scan_begin_arg; - int round_mode = cmd->flags & TRIG_ROUND_MASK; - - /* Check whether to use a single timer. */ - switch (round_mode) { - case TRIG_ROUND_NEAREST: - default: - round = I8254_OSC_BASE_10MHZ / 2; - break; - case TRIG_ROUND_DOWN: - round = 0; - break; - case TRIG_ROUND_UP: - round = I8254_OSC_BASE_10MHZ - 1; - break; - } - /* Be careful to avoid overflow! */ - div2 = cmd->scan_begin_arg / I8254_OSC_BASE_10MHZ; - div2 += (round + cmd->scan_begin_arg % I8254_OSC_BASE_10MHZ) / - I8254_OSC_BASE_10MHZ; - if (div2 <= 0x10000) { - /* A single timer will suffice. */ - if (div2 < 2) - div2 = 2; - div2 &= 0xffff; - div1 = 1; /* Flag that single timer to be used. */ - } else { - /* Use two timers. */ - div1 = devpriv->cached_div1; - div2 = devpriv->cached_div2; - pci224_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, - &div1, &div2, - &ns, round_mode); - } - - /* - * The output of timer Z2-0 will be used as the scan trigger - * source. - */ - /* Make sure Z2-0 is gated on. */ - outb(GAT_CONFIG(0, GAT_VCC), - devpriv->iobase1 + PCI224_ZGAT_SCE); - if (div1 == 1) { - /* Not cascading. Z2-0 needs 10 MHz clock. */ - outb(CLK_CONFIG(0, CLK_10MHZ), - devpriv->iobase1 + PCI224_ZCLK_SCE); - } else { - /* Cascading with Z2-2. */ - /* Make sure Z2-2 is gated on. */ - outb(GAT_CONFIG(2, GAT_VCC), - devpriv->iobase1 + PCI224_ZGAT_SCE); - /* Z2-2 needs 10 MHz clock. */ - outb(CLK_CONFIG(2, CLK_10MHZ), - devpriv->iobase1 + PCI224_ZCLK_SCE); - /* Load Z2-2 mode (2) and counter (div1). */ - i8254_load(devpriv->iobase1 + PCI224_Z2_CT0, 0, - 2, div1, 2); - /* Z2-0 is clocked from Z2-2's output. */ - outb(CLK_CONFIG(0, CLK_OUTNM1), - devpriv->iobase1 + PCI224_ZCLK_SCE); - } - /* Load Z2-0 mode (2) and counter (div2). */ - i8254_load(devpriv->iobase1 + PCI224_Z2_CT0, 0, 0, div2, 2); - } + if (cmd->scan_begin_src == TRIG_TIMER) + pci224_ao_start_pacer(dev, s); /* * Sort out end of acquisition. */ - switch (cmd->stop_src) { - case TRIG_COUNT: - /* Fixed number of scans. */ - devpriv->ao_stop_continuous = 0; + if (cmd->stop_src == TRIG_COUNT) devpriv->ao_stop_count = cmd->stop_arg; - break; - default: - /* Continuous scans. */ - devpriv->ao_stop_continuous = 1; + else /* TRIG_EXT | TRIG_NONE */ devpriv->ao_stop_count = 0; - break; - } - /* - * Sort out start of acquisition. - */ - switch (cmd->start_src) { - case TRIG_INT: - spin_lock_irqsave(&devpriv->ao_spinlock, flags); - s->async->inttrig = &pci224_ao_inttrig_start; - spin_unlock_irqrestore(&devpriv->ao_spinlock, flags); - break; - case TRIG_EXT: + spin_lock_irqsave(&devpriv->ao_spinlock, flags); + if (cmd->start_src == TRIG_INT) { + s->async->inttrig = pci224_ao_inttrig_start; + } else { /* TRIG_EXT */ /* Enable external interrupt trigger to start acquisition. */ - spin_lock_irqsave(&devpriv->ao_spinlock, flags); devpriv->intsce |= PCI224_INTR_EXT; outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE); - spin_unlock_irqrestore(&devpriv->ao_spinlock, flags); - break; } + spin_unlock_irqrestore(&devpriv->ao_spinlock, flags); return 0; } @@ -1101,7 +980,7 @@ pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, { const struct pci224_board *thisboard = comedi_board(dev); struct pci224_private *devpriv = dev->private; - struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &s->async->cmd; unsigned short *array = data; unsigned int length = num_bytes / sizeof(*array); unsigned int offset; @@ -1111,7 +990,7 @@ pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, /* The hardware expects 16-bit numbers. */ shift = 16 - thisboard->ao_bits; /* Channels will be all bipolar or all unipolar. */ - if ((devpriv->hwrange[CR_RANGE(async->cmd.chanlist[0])] & + if ((devpriv->hwrange[CR_RANGE(cmd->chanlist[0])] & PCI224_DACCON_POLAR_MASK) == PCI224_DACCON_POLAR_UNI) { /* Unipolar */ offset = 0; diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 99e60835dc4a..3895bc7cb3e3 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -519,14 +519,6 @@ struct pci230_private { * level threshold (PCI230+/260+). */ unsigned short adcg; /* ADCG register value. */ unsigned char int_en; /* Interrupt enables bits. */ - unsigned char ai_continuous; /* Flag set when cmd->stop_src == - * TRIG_NONE - user chooses to stop - * continuous conversion by - * cancelation. */ - unsigned char ao_continuous; /* Flag set when cmd->stop_src == - * TRIG_NONE - user chooses to stop - * continuous conversion by - * cancelation. */ unsigned char ai_bipolar; /* Set if bipolar input range so we * know to mangle it. */ unsigned char ao_bipolar; /* Set if bipolar output range so we @@ -953,6 +945,38 @@ static int pci230_ao_rinsn(struct comedi_device *dev, return i; } +static int pci230_ao_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + unsigned int prev_chan = CR_CHAN(cmd->chanlist[0]); + unsigned int range0 = CR_RANGE(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]); + + if (chan < prev_chan) { + dev_dbg(dev->class_dev, + "%s: channel numbers must increase\n", + __func__); + return -EINVAL; + } + + if (range != range0) { + dev_dbg(dev->class_dev, + "%s: channels must have the same range\n", + __func__); + return -EINVAL; + } + + prev_chan = chan; + } + + return 0; +} + static int pci230_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { @@ -1065,48 +1089,9 @@ static int pci230_ao_cmdtest(struct comedi_device *dev, if (err) return 4; - /* Step 5: check channel list if it exists. */ - - if (cmd->chanlist && cmd->chanlist_len > 0) { - enum { - seq_err = (1 << 0), - range_err = (1 << 1) - }; - unsigned int errors; - unsigned int n; - unsigned int chan, prev_chan; - unsigned int range, first_range; - - prev_chan = CR_CHAN(cmd->chanlist[0]); - first_range = CR_RANGE(cmd->chanlist[0]); - errors = 0; - for (n = 1; n < cmd->chanlist_len; n++) { - chan = CR_CHAN(cmd->chanlist[n]); - range = CR_RANGE(cmd->chanlist[n]); - /* Channel numbers must strictly increase. */ - if (chan < prev_chan) - errors |= seq_err; - - /* Ranges must be the same. */ - if (range != first_range) - errors |= range_err; - - prev_chan = chan; - } - if (errors != 0) { - err++; - if ((errors & seq_err) != 0) { - dev_dbg(dev->class_dev, - "%s: channel numbers must increase\n", - __func__); - } - if ((errors & range_err) != 0) { - dev_dbg(dev->class_dev, - "%s: channels must have the same range\n", - __func__); - } - } - } + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= pci230_ao_check_chanlist(dev, s, cmd); if (err) return 5; @@ -1175,11 +1160,11 @@ static void pci230_handle_ao_nofifo(struct comedi_device *dev, struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; - if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0)) + if (cmd->stop_src == TRIG_COUNT && devpriv->ao_scan_count == 0) return; for (i = 0; i < cmd->chanlist_len; i++) { /* Read sample from Comedi's circular buffer. */ - ret = comedi_buf_get(s->async, &data); + ret = comedi_buf_get(s, &data); if (ret == 0) { s->async->events |= COMEDI_CB_OVERFLOW; pci230_ao_stop(dev, s); @@ -1190,7 +1175,7 @@ static void pci230_handle_ao_nofifo(struct comedi_device *dev, pci230_ao_write_nofifo(dev, data, CR_CHAN(cmd->chanlist[i])); } async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; - if (!devpriv->ao_continuous) { + if (cmd->stop_src == TRIG_COUNT) { devpriv->ao_scan_count--; if (devpriv->ao_scan_count == 0) { /* End of acquisition. */ @@ -1212,16 +1197,14 @@ static int pci230_handle_ao_fifo(struct comedi_device *dev, unsigned int room; unsigned short dacstat; unsigned int i, n; - unsigned int bytes_per_scan; unsigned int events = 0; int running; /* Get DAC FIFO status. */ dacstat = inw(dev->iobase + PCI230_DACCON); /* Determine number of scans available in buffer. */ - bytes_per_scan = cmd->chanlist_len * sizeof(short); - num_scans = comedi_buf_read_n_available(async) / bytes_per_scan; - if (!devpriv->ao_continuous) { + 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; @@ -1265,13 +1248,13 @@ static int pci230_handle_ao_fifo(struct comedi_device *dev, for (i = 0; i < cmd->chanlist_len; i++) { unsigned short datum; - comedi_buf_get(async, &datum); + comedi_buf_get(s, &datum); pci230_ao_write_fifo(dev, datum, CR_CHAN(cmd->chanlist[i])); } } events |= COMEDI_CB_EOS | COMEDI_CB_BLOCK; - if (!devpriv->ao_continuous) { + 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 @@ -1349,7 +1332,7 @@ static void pci230_ao_start(struct comedi_device *dev, unsigned long irqflags; set_bit(AO_CMD_STARTED, &devpriv->state); - if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0)) { + if (cmd->stop_src == TRIG_COUNT && devpriv->ao_scan_count == 0) { /* An empty acquisition! */ async->events |= COMEDI_CB_EOA; pci230_ao_stop(dev, s); @@ -1434,7 +1417,9 @@ static int pci230_ao_inttrig_start(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trig_num) { - if (trig_num != 0) + struct comedi_cmd *cmd = &s->async->cmd; + + if (trig_num != cmd->start_src) return -EINVAL; s->async->inttrig = NULL; @@ -1460,14 +1445,10 @@ static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } /* Get number of scans required. */ - if (cmd->stop_src == TRIG_COUNT) { + if (cmd->stop_src == TRIG_COUNT) devpriv->ao_scan_count = cmd->stop_arg; - devpriv->ao_continuous = 0; - } else { - /* TRIG_NONE, user calls cancel. */ + else /* TRIG_NONE, user calls cancel */ devpriv->ao_scan_count = 0; - devpriv->ao_continuous = 1; - } /* Set range - see analogue output range table; 0 => unipolar 10V, * 1 => bipolar +/-10V range scale */ @@ -1552,6 +1533,109 @@ static int pci230_ai_check_scan_period(struct comedi_cmd *cmd) return !err; } +static int pci230_ai_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + struct pci230_private *devpriv = dev->private; + unsigned int max_diff_chan = (s->n_chan / 2) - 1; + unsigned int prev_chan = 0; + unsigned int prev_range = 0; + unsigned int prev_aref = 0; + unsigned int prev_polarity = 0; + unsigned int subseq_len = 0; + int i; + + for (i = 0; i < cmd->chanlist_len; i++) { + unsigned int chanspec = cmd->chanlist[i]; + unsigned int chan = CR_CHAN(chanspec); + unsigned int range = CR_RANGE(chanspec); + unsigned int aref = CR_AREF(chanspec); + unsigned int polarity = pci230_ai_bipolar[range]; + + if (aref == AREF_DIFF && chan >= max_diff_chan) { + dev_dbg(dev->class_dev, + "%s: differential channel number out of range 0 to %u\n", + __func__, max_diff_chan); + return -EINVAL; + } + + if (i > 0) { + /* + * Channel numbers must strictly increase or + * subsequence must repeat exactly. + */ + if (chan <= prev_chan && subseq_len == 0) + subseq_len = i; + + if (subseq_len > 0 && + cmd->chanlist[i % subseq_len] != chanspec) { + dev_dbg(dev->class_dev, + "%s: channel numbers must increase or sequence must repeat exactly\n", + __func__); + return -EINVAL; + } + + if (aref != prev_aref) { + dev_dbg(dev->class_dev, + "%s: channel sequence analogue references must be all the same (single-ended or differential)\n", + __func__); + return -EINVAL; + } + + if (polarity != prev_polarity) { + dev_dbg(dev->class_dev, + "%s: channel sequence ranges must be all bipolar or all unipolar\n", + __func__); + return -EINVAL; + } + + if (aref != AREF_DIFF && range != prev_range && + ((chan ^ prev_chan) & ~1) == 0) { + dev_dbg(dev->class_dev, + "%s: single-ended channel pairs must have the same range\n", + __func__); + return -EINVAL; + } + } + prev_chan = chan; + prev_range = range; + prev_aref = aref; + prev_polarity = polarity; + } + + if (subseq_len == 0) + subseq_len = cmd->chanlist_len; + + if ((cmd->chanlist_len % subseq_len) != 0) { + dev_dbg(dev->class_dev, + "%s: sequence must repeat exactly\n", __func__); + return -EINVAL; + } + + /* + * Buggy PCI230+ or PCI260+ requires channel 0 to be (first) in the + * sequence if the sequence contains more than one channel. Hardware + * versions 1 and 2 have the bug. There is no hardware version 3. + * + * Actually, there are two firmwares that report themselves as + * hardware version 1 (the boards have different ADC chips with + * slightly different timing requirements, which was supposed to + * be invisible to software). The first one doesn't seem to have + * the bug, but the second one does, and we can't tell them apart! + */ + if (devpriv->hwver > 0 && devpriv->hwver < 4) { + if (subseq_len > 1 && CR_CHAN(cmd->chanlist[0]) != 0) { + dev_info(dev->class_dev, + "amplc_pci230: ai_cmdtest: Buggy PCI230+/260+ h/w version %u requires first channel of multi-channel sequence to be 0 (corrected in h/w version 4)\n", + devpriv->hwver); + return -EINVAL; + } + } + + return 0; +} + static int pci230_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { @@ -1740,136 +1824,9 @@ static int pci230_ai_cmdtest(struct comedi_device *dev, if (err) return 4; - /* Step 5: check channel list if it exists. */ - - if (cmd->chanlist && cmd->chanlist_len > 0) { - enum { - seq_err = 1 << 0, - rangepair_err = 1 << 1, - polarity_err = 1 << 2, - aref_err = 1 << 3, - diffchan_err = 1 << 4, - buggy_chan0_err = 1 << 5 - }; - unsigned int errors; - unsigned int chan, prev_chan; - unsigned int range, prev_range; - unsigned int polarity, prev_polarity; - unsigned int aref, prev_aref; - unsigned int subseq_len; - unsigned int n; - - subseq_len = 0; - errors = 0; - prev_chan = prev_aref = prev_range = prev_polarity = 0; - for (n = 0; n < cmd->chanlist_len; n++) { - chan = CR_CHAN(cmd->chanlist[n]); - range = CR_RANGE(cmd->chanlist[n]); - aref = CR_AREF(cmd->chanlist[n]); - polarity = pci230_ai_bipolar[range]; - /* Only the first half of the channels are available if - * differential. (These are remapped in software. In - * hardware, only the even channels are available.) */ - if ((aref == AREF_DIFF) - && (chan >= (s->n_chan / 2))) { - errors |= diffchan_err; - } - if (n > 0) { - /* Channel numbers must strictly increase or - * subsequence must repeat exactly. */ - if ((chan <= prev_chan) - && (subseq_len == 0)) { - subseq_len = n; - } - if ((subseq_len > 0) - && (cmd->chanlist[n] != - cmd->chanlist[n % subseq_len])) { - errors |= seq_err; - } - /* Channels must have same AREF. */ - if (aref != prev_aref) - errors |= aref_err; - - /* Channel ranges must have same polarity. */ - if (polarity != prev_polarity) - errors |= polarity_err; - - /* Single-ended channel pairs must have same - * range. */ - if ((aref != AREF_DIFF) - && (((chan ^ prev_chan) & ~1) == 0) - && (range != prev_range)) { - errors |= rangepair_err; - } - } - prev_chan = chan; - prev_range = range; - prev_aref = aref; - prev_polarity = polarity; - } - if (subseq_len == 0) { - /* Subsequence is whole sequence. */ - subseq_len = n; - } - /* If channel list is a repeating subsequence, need a whole - * number of repeats. */ - if ((n % subseq_len) != 0) - errors |= seq_err; - - if ((devpriv->hwver > 0) && (devpriv->hwver < 4)) { - /* - * Buggy PCI230+ or PCI260+ requires channel 0 to be - * (first) in the sequence if the sequence contains - * more than one channel. Hardware versions 1 and 2 - * have the bug. There is no hardware version 3. - * - * Actually, there are two firmwares that report - * themselves as hardware version 1 (the boards - * have different ADC chips with slightly different - * timing requirements, which was supposed to be - * invisible to software). The first one doesn't - * seem to have the bug, but the second one - * does, and we can't tell them apart! - */ - if ((subseq_len > 1) - && (CR_CHAN(cmd->chanlist[0]) != 0)) { - errors |= buggy_chan0_err; - } - } - if (errors != 0) { - err++; - if ((errors & seq_err) != 0) { - dev_dbg(dev->class_dev, - "%s: channel numbers must increase or sequence must repeat exactly\n", - __func__); - } - if ((errors & rangepair_err) != 0) { - dev_dbg(dev->class_dev, - "%s: single-ended channel pairs must have the same range\n", - __func__); - } - if ((errors & polarity_err) != 0) { - dev_dbg(dev->class_dev, - "%s: channel sequence ranges must be all bipolar or all unipolar\n", - __func__); - } - if ((errors & aref_err) != 0) { - dev_dbg(dev->class_dev, - "%s: channel sequence analogue references must be all the same (single-ended or differential)\n", - __func__); - } - if ((errors & diffchan_err) != 0) { - dev_dbg(dev->class_dev, - "%s: differential channel number out of range 0 to %u\n", - __func__, (s->n_chan / 2) - 1); - } - if ((errors & buggy_chan0_err) != 0) { - dev_info(dev->class_dev, - "amplc_pci230: ai_cmdtest: Buggy PCI230+/260+ h/w version %u requires first channel of multi-channel sequence to be 0 (corrected in h/w version 4)\n", - devpriv->hwver); - } - } - } + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= pci230_ai_check_chanlist(dev, s, cmd); if (err) return 5; @@ -1891,9 +1848,9 @@ static void pci230_ai_update_fifo_trigger_level(struct comedi_device *dev, /* Wake at end of scan. */ wake = scanlen - devpriv->ai_scan_pos; } else { - if (devpriv->ai_continuous - || (devpriv->ai_scan_count >= PCI230_ADC_FIFOLEVEL_HALFFULL) - || (scanlen >= PCI230_ADC_FIFOLEVEL_HALFFULL)) { + if (cmd->stop_src != TRIG_COUNT || + devpriv->ai_scan_count >= PCI230_ADC_FIFOLEVEL_HALFFULL || + scanlen >= PCI230_ADC_FIFOLEVEL_HALFFULL) { wake = PCI230_ADC_FIFOLEVEL_HALFFULL; } else { wake = (devpriv->ai_scan_count * scanlen) @@ -2044,7 +2001,7 @@ static void pci230_ai_start(struct comedi_device *dev, struct comedi_cmd *cmd = &async->cmd; set_bit(AI_CMD_STARTED, &devpriv->state); - if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) { + if (cmd->stop_src == TRIG_COUNT && devpriv->ai_scan_count == 0) { /* An empty acquisition! */ async->events |= COMEDI_CB_EOA; pci230_ai_stop(dev, s); @@ -2177,7 +2134,9 @@ static int pci230_ai_inttrig_start(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trig_num) { - if (trig_num != 0) + struct comedi_cmd *cmd = &s->async->cmd; + + if (trig_num != cmd->start_arg) return -EINVAL; s->async->inttrig = NULL; @@ -2190,16 +2149,17 @@ static void pci230_handle_ai(struct comedi_device *dev, struct comedi_subdevice *s) { 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; - struct comedi_async *async = s->async; - unsigned int scanlen = async->cmd.scan_end_arg; /* Determine number of samples to read. */ - if (devpriv->ai_continuous) { + if (cmd->stop_src != TRIG_COUNT) { todo = PCI230_ADC_FIFOLEVEL_HALFFULL; } else if (devpriv->ai_scan_count == 0) { todo = 0; @@ -2247,7 +2207,7 @@ static void pci230_handle_ai(struct comedi_device *dev, } } /* Read sample and store in Comedi's circular buffer. */ - if (comedi_buf_put(async, pci230_ai_read(dev)) == 0) { + if (comedi_buf_put(s, pci230_ai_read(dev)) == 0) { events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW; comedi_error(dev, "AI buffer overflow"); break; @@ -2261,7 +2221,7 @@ static void pci230_handle_ai(struct comedi_device *dev, async->events |= COMEDI_CB_EOS; } } - if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) { + if (cmd->stop_src == TRIG_COUNT && devpriv->ai_scan_count == 0) { /* End of acquisition. */ events |= COMEDI_CB_EOA; } else { @@ -2312,14 +2272,10 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* Get number of scans required. */ - if (cmd->stop_src == TRIG_COUNT) { + if (cmd->stop_src == TRIG_COUNT) devpriv->ai_scan_count = cmd->stop_arg; - devpriv->ai_continuous = 0; - } else { - /* TRIG_NONE, user calls cancel. */ + else /* TRIG_NONE, user calls cancel */ devpriv->ai_scan_count = 0; - devpriv->ai_continuous = 1; - } devpriv->ai_scan_pos = 0; /* Position within scan. */ /* Steps; @@ -2463,12 +2419,10 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } } - if (cmd->start_src == TRIG_INT) { + if (cmd->start_src == TRIG_INT) s->async->inttrig = pci230_ai_inttrig_start; - } else { - /* TRIG_NOW */ + else /* TRIG_NOW */ pci230_ai_start(dev, s); - } return 0; } diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index 645fcb0cf17d..eb1b92d72e87 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -184,6 +184,7 @@ static int das16cs_ao_winsn(struct comedi_device *dev, for (bit = 15; bit >= 0; bit--) { int b = (d >> bit) & 0x1; + b <<= 1; outw(status1 | b | 0x0000, dev->iobase + DAS16CS_MISC1); udelay(1); diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 83a265f3408c..7377da1aff7c 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -803,6 +803,33 @@ static int trimpot_read_insn(struct comedi_device *dev, return 1; } +static int cb_pcidas_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]); + 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]); + + if (chan != (chan0 + i) % s->n_chan) { + dev_dbg(dev->class_dev, + "entries in chanlist must be consecutive channels, counting upwards\n"); + return -EINVAL; + } + + if (range != range0) { + dev_dbg(dev->class_dev, + "entries in chanlist must all have the same gain\n"); + return -EINVAL; + } + } + return 0; +} + static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) @@ -810,8 +837,7 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, const struct cb_pcidas_board *thisboard = comedi_board(dev); struct cb_pcidas_private *devpriv = dev->private; int err = 0; - int tmp; - int i, gain, start_chan; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -846,9 +872,12 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, if (err) return 2; - /* step 3: arguments are trivially compatible */ + /* 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: /* External trigger, only CR_EDGE and CR_INVERT flags allowed */ if ((cmd->start_arg @@ -862,9 +891,6 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, err |= -EINVAL; } break; - default: - err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); - break; } if (cmd->scan_begin_src == TRIG_TIMER) @@ -886,45 +912,28 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ if (cmd->scan_begin_src == TRIG_TIMER) { - tmp = cmd->scan_begin_arg; + arg = cmd->scan_begin_arg; i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, &devpriv->divisor1, &devpriv->divisor2, - &cmd->scan_begin_arg, cmd->flags); - if (tmp != cmd->scan_begin_arg) - err++; + &arg, cmd->flags); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (cmd->convert_src == TRIG_TIMER) { - tmp = cmd->convert_arg; + arg = cmd->convert_arg; i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, &devpriv->divisor1, &devpriv->divisor2, - &cmd->convert_arg, cmd->flags); - if (tmp != cmd->convert_arg) - err++; + &arg, cmd->flags); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); } if (err) return 4; - /* check channel/gain list against card's limitations */ - if (cmd->chanlist) { - gain = CR_RANGE(cmd->chanlist[0]); - start_chan = CR_CHAN(cmd->chanlist[0]); - for (i = 1; i < cmd->chanlist_len; i++) { - if (CR_CHAN(cmd->chanlist[i]) != - (start_chan + i) % s->n_chan) { - comedi_error(dev, - "entries in chanlist must be consecutive channels, counting upwards\n"); - err++; - } - if (CR_RANGE(cmd->chanlist[i]) != gain) { - comedi_error(dev, - "entries in chanlist must all have the same gain\n"); - err++; - } - } - } + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= cb_pcidas_ai_check_chanlist(dev, s, cmd); if (err) return 5; @@ -932,20 +941,16 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, return 0; } -static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns, - int rounding_flags) +static void cb_pcidas_ai_load_counters(struct comedi_device *dev) { struct cb_pcidas_private *devpriv = dev->private; + unsigned long timer_base = devpriv->pacer_counter_dio + ADC8254; - i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, - &devpriv->divisor1, &devpriv->divisor2, - ns, rounding_flags); + i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY); + i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY); - /* Write the values of ctr1 and ctr2 into counters 1 and 2 */ - i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 1, - devpriv->divisor1, 2); - i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 2, - devpriv->divisor2, 2); + i8254_write(timer_base, 0, 1, devpriv->divisor1); + i8254_write(timer_base, 0, 2, devpriv->divisor2); } static int cb_pcidas_ai_cmd(struct comedi_device *dev, @@ -983,12 +988,8 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev, outw(bits, devpriv->control_status + ADCMUX_CONT); /* load counters */ - if (cmd->convert_src == TRIG_TIMER) - cb_pcidas_load_counters(dev, &cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); - else if (cmd->scan_begin_src == TRIG_TIMER) - cb_pcidas_load_counters(dev, &cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); + 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) @@ -1035,6 +1036,25 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev, return 0; } +static int cb_pcidas_ao_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + unsigned int chan0 = CR_CHAN(cmd->chanlist[0]); + + if (cmd->chanlist_len > 1) { + unsigned int chan1 = CR_CHAN(cmd->chanlist[1]); + + if (chan0 != 0 || chan1 != 1) { + dev_dbg(dev->class_dev, + "channels must be ordered channel 0, channel 1 in chanlist\n"); + return -EINVAL; + } + } + + return 0; +} + static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) @@ -1042,7 +1062,7 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, const struct cb_pcidas_board *thisboard = comedi_board(dev); struct cb_pcidas_private *devpriv = dev->private; int err = 0; - int tmp; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -1085,27 +1105,20 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ if (cmd->scan_begin_src == TRIG_TIMER) { - tmp = cmd->scan_begin_arg; + arg = cmd->scan_begin_arg; i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, &devpriv->ao_divisor1, &devpriv->ao_divisor2, - &cmd->scan_begin_arg, cmd->flags); - if (tmp != cmd->scan_begin_arg) - err++; + &arg, cmd->flags); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (err) return 4; - /* check channel/gain list against card's limitations */ - if (cmd->chanlist && cmd->chanlist_len > 1) { - if (CR_CHAN(cmd->chanlist[0]) != 0 || - CR_CHAN(cmd->chanlist[1]) != 1) { - comedi_error(dev, - "channels must be ordered channel 0, channel 1 in chanlist\n"); - err++; - } - } + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= cb_pcidas_ao_check_chanlist(dev, s, cmd); if (err) return 5; @@ -1145,7 +1158,7 @@ static int cb_pcidas_ao_inttrig(struct comedi_device *dev, struct comedi_cmd *cmd = &s->async->cmd; unsigned long flags; - if (trig_num != 0) + if (trig_num != cmd->start_arg) return -EINVAL; /* load up fifo */ @@ -1180,6 +1193,18 @@ static int cb_pcidas_ao_inttrig(struct comedi_device *dev, return 0; } +static void cb_pcidas_ao_load_counters(struct comedi_device *dev) +{ + struct cb_pcidas_private *devpriv = dev->private; + unsigned long timer_base = devpriv->pacer_counter_dio + DAC8254; + + i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY); + i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY); + + i8254_write(timer_base, 0, 1, devpriv->ao_divisor1); + i8254_write(timer_base, 0, 2, devpriv->ao_divisor2); +} + static int cb_pcidas_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { @@ -1209,18 +1234,9 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev, outw(0, devpriv->ao_registers + DACFIFOCLR); /* load counters */ - if (cmd->scan_begin_src == TRIG_TIMER) { - i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, - &devpriv->ao_divisor1, - &devpriv->ao_divisor2, - &cmd->scan_begin_arg, cmd->flags); + if (cmd->scan_begin_src == TRIG_TIMER) + cb_pcidas_ao_load_counters(dev); - /* Write the values of ctr1 and ctr2 into counters 1 and 2 */ - i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 1, - devpriv->ao_divisor1, 2); - i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 2, - devpriv->ao_divisor2, 2); - } /* set number of conversions */ if (cmd->stop_src == TRIG_COUNT) devpriv->ao_count = cmd->chanlist_len * cmd->stop_arg; @@ -1305,7 +1321,7 @@ static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status) num_points * sizeof(short)); num_points = num_bytes / sizeof(short); - if (async->cmd.stop_src == TRIG_COUNT) + 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, @@ -1327,6 +1343,7 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) struct cb_pcidas_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async; + struct comedi_cmd *cmd; int status, s5933_status; int half_fifo = thisboard->fifo_size / 2; unsigned int num_samples, i; @@ -1337,6 +1354,7 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) return IRQ_NONE; async = s->async; + cmd = &async->cmd; s5933_status = inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR); @@ -1359,7 +1377,7 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) if (status & ADHFI) { /* read data */ num_samples = half_fifo; - if (async->cmd.stop_src == TRIG_COUNT && + if (cmd->stop_src == TRIG_COUNT && num_samples > devpriv->count) { num_samples = devpriv->count; } @@ -1368,7 +1386,7 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) cfc_write_array_to_buffer(s, devpriv->ai_buffer, num_samples * sizeof(short)); devpriv->count -= num_samples; - if (async->cmd.stop_src == TRIG_COUNT && devpriv->count == 0) + if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) async->events |= COMEDI_CB_EOA; /* clear half-full interrupt latch */ spin_lock_irqsave(&dev->spinlock, flags); @@ -1383,7 +1401,7 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) INT_ADCFIFO)) == 0) break; cfc_write_to_buffer(s, inw(devpriv->adc_fifo)); - if (async->cmd.stop_src == TRIG_COUNT && + if (cmd->stop_src == TRIG_COUNT && --devpriv->count == 0) { /* end of acquisition */ async->events |= COMEDI_CB_EOA; diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index f9afcbe1da54..035c3a176005 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -1995,14 +1995,52 @@ static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd) return; } +static int cb_pcidas64_ai_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + const struct pcidas64_board *board = comedi_board(dev); + unsigned int aref0 = CR_AREF(cmd->chanlist[0]); + int i; + + for (i = 1; i < cmd->chanlist_len; i++) { + unsigned int aref = CR_AREF(cmd->chanlist[i]); + + if (aref != aref0) { + dev_dbg(dev->class_dev, + "all elements in chanlist must use the same analog reference\n"); + return -EINVAL; + } + } + + if (board->layout == LAYOUT_4020) { + unsigned int chan0 = CR_CHAN(cmd->chanlist[0]); + + for (i = 1; i < cmd->chanlist_len; i++) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); + + if (chan != (chan0 + i)) { + dev_dbg(dev->class_dev, + "chanlist must use consecutive channels\n"); + return -EINVAL; + } + } + if (cmd->chanlist_len == 3) { + dev_dbg(dev->class_dev, + "chanlist cannot be 3 channels long, use 1, 2, or 4 channels\n"); + return -EINVAL; + } + } + + return 0; +} + static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { const struct pcidas64_board *thisboard = comedi_board(dev); int err = 0; unsigned int tmp_arg, tmp_arg2; - int i; - int aref; unsigned int triggers; /* Step 1 : check if triggers are trivially valid */ @@ -2040,15 +2078,24 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, if (cmd->convert_src == TRIG_EXT && cmd->scan_begin_src == TRIG_TIMER) err |= -EINVAL; - if (cmd->stop_src != TRIG_COUNT && - cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT) - err |= -EINVAL; if (err) 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: + /* + * start_arg is the CR_CHAN | CR_INVERT of the + * external trigger. + */ + break; + } + if (cmd->convert_src == TRIG_TIMER) { if (thisboard->layout == LAYOUT_4020) { err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); @@ -2098,36 +2145,9 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, if (err) return 4; - /* make sure user is doesn't change analog reference mid chanlist */ - if (cmd->chanlist) { - aref = CR_AREF(cmd->chanlist[0]); - for (i = 1; i < cmd->chanlist_len; i++) { - if (aref != CR_AREF(cmd->chanlist[i])) { - comedi_error(dev, - "all elements in chanlist must use the same analog reference"); - err++; - break; - } - } - /* check 4020 chanlist */ - if (thisboard->layout == LAYOUT_4020) { - unsigned int first_channel = CR_CHAN(cmd->chanlist[0]); - for (i = 1; i < cmd->chanlist_len; i++) { - if (CR_CHAN(cmd->chanlist[i]) != - first_channel + i) { - comedi_error(dev, - "chanlist must use consecutive channels"); - err++; - break; - } - } - if (cmd->chanlist_len == 3) { - comedi_error(dev, - "chanlist cannot be 3 channels long, use 1, 2, or 4 channels"); - err++; - } - } - } + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= cb_pcidas64_ai_check_chanlist(dev, s, cmd); if (err) return 5; @@ -2703,6 +2723,7 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel) const struct pcidas64_board *thisboard = comedi_board(dev); struct pcidas64_private *devpriv = dev->private; struct comedi_async *async = dev->read_subdev->async; + struct comedi_cmd *cmd = &async->cmd; uint32_t next_transfer_addr; int j; int num_samples = 0; @@ -2724,7 +2745,7 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel) 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 (async->cmd.stop_src == TRIG_COUNT) { + if (cmd->stop_src == TRIG_COUNT) { if (num_samples > devpriv->ai_count) num_samples = devpriv->ai_count; devpriv->ai_count -= num_samples; @@ -2873,7 +2894,7 @@ static unsigned int load_ao_dma_buffer(struct comedi_device *dev, buffer_index = devpriv->ao_dma_index; prev_buffer_index = prev_ao_dma_index(dev); - num_bytes = comedi_buf_read_n_available(dev->write_subdev->async); + 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) @@ -3184,15 +3205,17 @@ static int prep_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) return 0; } -static inline int external_ai_queue_in_use(struct comedi_device *dev) +static inline int external_ai_queue_in_use(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) { const struct pcidas64_board *thisboard = comedi_board(dev); - if (dev->read_subdev->busy) + if (s->busy) return 0; if (thisboard->layout == LAYOUT_4020) return 0; - else if (use_internal_queue_6xxx(&dev->read_subdev->async->cmd)) + else if (use_internal_queue_6xxx(cmd)) return 0; return 1; } @@ -3204,7 +3227,7 @@ static int ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd = &s->async->cmd; int retval; - if (trig_num != 0) + if (trig_num != cmd->start_arg) return -EINVAL; retval = prep_ao_dma(dev, cmd); @@ -3226,7 +3249,7 @@ static int ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) struct pcidas64_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; - if (external_ai_queue_in_use(dev)) { + if (external_ai_queue_in_use(dev, s, cmd)) { warn_external_queue(dev); return -EBUSY; } @@ -3247,13 +3270,32 @@ static int ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } +static int cb_pcidas64_ao_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + unsigned int chan0 = CR_CHAN(cmd->chanlist[0]); + int i; + + for (i = 1; i < cmd->chanlist_len; i++) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); + + if (chan != (chan0 + i)) { + dev_dbg(dev->class_dev, + "chanlist must use consecutive channels\n"); + return -EINVAL; + } + } + + return 0; +} + static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { const struct pcidas64_board *thisboard = comedi_board(dev); int err = 0; unsigned int tmp_arg; - int i; /* Step 1 : check if triggers are trivially valid */ @@ -3285,6 +3327,8 @@ static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, /* 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) { err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, thisboard->ao_scan_speed); @@ -3315,17 +3359,9 @@ static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, if (err) return 4; - if (cmd->chanlist) { - unsigned int first_channel = CR_CHAN(cmd->chanlist[0]); - for (i = 1; i < cmd->chanlist_len; i++) { - if (CR_CHAN(cmd->chanlist[i]) != first_channel + i) { - comedi_error(dev, - "chanlist must use consecutive channels"); - err++; - break; - } - } - } + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= cb_pcidas64_ao_check_chanlist(dev, s, cmd); if (err) return 5; diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index d3141c865fe7..50e522e6e690 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -31,7 +31,8 @@ Configuration Options: 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. +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. */ @@ -128,8 +129,12 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device *dev, d = d & 0xfd; outb(d, devpriv->BADR3 + 5); } - outb(0x01, devpriv->BADR3 + 6); /* set bursting off, conversions on */ - outb(0x00, devpriv->BADR3 + 7); /* set range to 10V. UP/BP is controlled by a switch on the board */ + + /* set bursting off, conversions on */ + outb(0x01, devpriv->BADR3 + 6); + + /* set range to 10V. UP/BP is controlled by a switch on the board */ + outb(0x00, devpriv->BADR3 + 7); /* * write channel limits to multiplexer, set Low (bits 0-3) and diff --git a/drivers/staging/comedi/drivers/comedi_fc.c b/drivers/staging/comedi/drivers/comedi_fc.c index 9d9b1469e89a..c33c3e5680a6 100644 --- a/drivers/staging/comedi/drivers/comedi_fc.c +++ b/drivers/staging/comedi/drivers/comedi_fc.c @@ -24,7 +24,7 @@ unsigned int cfc_bytes_per_scan(struct comedi_subdevice *s) { - unsigned int chanlist_len = s->async->cmd.chanlist_len; + struct comedi_cmd *cmd = &s->async->cmd; unsigned int num_samples; unsigned int bits_per_sample; @@ -33,11 +33,11 @@ unsigned int cfc_bytes_per_scan(struct comedi_subdevice *s) case COMEDI_SUBD_DO: case COMEDI_SUBD_DIO: bits_per_sample = 8 * bytes_per_sample(s); - num_samples = (chanlist_len + bits_per_sample - 1) / + num_samples = (cmd->chanlist_len + bits_per_sample - 1) / bits_per_sample; break; default: - num_samples = chanlist_len; + num_samples = cmd->chanlist_len; break; } return num_samples * bytes_per_sample(s); @@ -67,15 +67,15 @@ unsigned int cfc_write_array_to_buffer(struct comedi_subdevice *s, if (num_bytes == 0) return 0; - retval = comedi_buf_write_alloc(async, num_bytes); + retval = comedi_buf_write_alloc(s, num_bytes); if (retval != num_bytes) { dev_warn(s->device->class_dev, "buffer overrun\n"); async->events |= COMEDI_CB_OVERFLOW; return 0; } - comedi_buf_memcpy_to(async, 0, data, num_bytes); - comedi_buf_write_free(async, num_bytes); + comedi_buf_memcpy_to(s, 0, data, num_bytes); + comedi_buf_write_free(s, num_bytes); cfc_inc_scan_progress(s, num_bytes); async->events |= COMEDI_CB_BLOCK; @@ -86,16 +86,14 @@ EXPORT_SYMBOL_GPL(cfc_write_array_to_buffer); unsigned int cfc_read_array_from_buffer(struct comedi_subdevice *s, void *data, unsigned int num_bytes) { - struct comedi_async *async = s->async; - if (num_bytes == 0) return 0; - num_bytes = comedi_buf_read_alloc(async, num_bytes); - comedi_buf_memcpy_from(async, 0, data, num_bytes); - comedi_buf_read_free(async, num_bytes); + 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); cfc_inc_scan_progress(s, num_bytes); - async->events |= COMEDI_CB_BLOCK; + s->async->events |= COMEDI_CB_BLOCK; return num_bytes; } diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index 9de81c7712fb..a42748692357 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -181,7 +181,7 @@ static int parport_intr_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); - err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, 1); + err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); if (err) @@ -229,7 +229,7 @@ static irqreturn_t parport_interrupt(int irq, void *d) if (!(ctrl & PARPORT_CTRL_IRQ_ENA)) return IRQ_NONE; - comedi_buf_put(s->async, 0); + comedi_buf_put(s, 0); s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; comedi_event(dev, s); @@ -295,6 +295,7 @@ static int parport_attach(struct comedi_device *dev, s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = parport_intr_insn_bits; + s->len_chanlist = 1; s->do_cmdtest = parport_intr_cmdtest; s->do_cmd = parport_intr_cmd; s->cancel = parport_intr_cancel; diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index cd9562556d2c..67a09aa6b721 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -188,6 +188,7 @@ static void waveform_ai_interrupt(unsigned long arg) 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; @@ -198,6 +199,7 @@ static void waveform_ai_interrupt(unsigned long arg) for (i = 0; i < num_scans; i++) { for (j = 0; j < cmd->chanlist_len; j++) { unsigned short sample; + sample = fake_waveform(dev, CR_CHAN(cmd->chanlist[j]), CR_RANGE(cmd->chanlist[j]), devpriv->usec_current + @@ -224,7 +226,7 @@ static int waveform_ai_cmdtest(struct comedi_device *dev, struct comedi_cmd *cmd) { int err = 0; - int tmp; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -276,22 +278,18 @@ static int waveform_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ if (cmd->scan_begin_src == TRIG_TIMER) { - tmp = cmd->scan_begin_arg; + arg = cmd->scan_begin_arg; /* round to nearest microsec */ - cmd->scan_begin_arg = - nano_per_micro * ((tmp + - (nano_per_micro / 2)) / nano_per_micro); - if (tmp != cmd->scan_begin_arg) - err++; + arg = nano_per_micro * + ((arg + (nano_per_micro / 2)) / nano_per_micro); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (cmd->convert_src == TRIG_TIMER) { - tmp = cmd->convert_arg; + arg = cmd->convert_arg; /* round to nearest microsec */ - cmd->convert_arg = - nano_per_micro * ((tmp + - (nano_per_micro / 2)) / nano_per_micro); - if (tmp != cmd->convert_arg) - err++; + arg = nano_per_micro * + ((arg + (nano_per_micro / 2)) / nano_per_micro); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); } if (err) @@ -413,11 +411,7 @@ static int waveform_attach(struct comedi_device *dev, s->n_chan = N_CHANS; s->maxdata = 0xffff; s->range_table = &waveform_ai_ranges; - s->len_chanlist = s->n_chan * 2; s->insn_write = waveform_ao_insn_write; - s->do_cmd = NULL; - s->do_cmdtest = NULL; - s->cancel = NULL; /* Our default loopback value is just a 0V flatline */ for (i = 0; i < s->n_chan; i++) diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h index 46a314c5113e..18cc170facd0 100644 --- a/drivers/staging/comedi/drivers/das08.h +++ b/drivers/staging/comedi/drivers/das08.h @@ -40,7 +40,9 @@ struct das08_board_struct { }; struct das08_private_struct { - unsigned int do_mux_bits; /* bits for do/mux register on boards without separate do register */ + unsigned int do_mux_bits; /* bits for do/mux register on boards + * without separate do register + */ const unsigned int *pg_gainlist; unsigned int ao_readback[2]; /* assume 2 AO channels */ }; diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 6a7d652ff564..2feecf199f27 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -600,29 +600,56 @@ static void das16_timer_interrupt(unsigned long arg) mod_timer(&devpriv->timer, jiffies + timer_period()); } +static int das16_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]); + 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]); + + if (chan != ((chan0 + i) % s->n_chan)) { + dev_dbg(dev->class_dev, + "entries in chanlist must be consecutive channels, counting upwards\n"); + return -EINVAL; + } + + if (range != range0) { + dev_dbg(dev->class_dev, + "entries in chanlist must all have the same gain\n"); + return -EINVAL; + } + } + + return 0; +} + static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { const struct das16_board *board = comedi_board(dev); struct das16_private_struct *devpriv = dev->private; - int err = 0, tmp; - int gain, start_chan, i; - int mask; + int err = 0; + unsigned int trig_mask; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - mask = TRIG_FOLLOW; + trig_mask = TRIG_FOLLOW; if (devpriv->can_burst) - mask |= TRIG_TIMER | TRIG_EXT; - err |= cfc_check_trigger_src(&cmd->scan_begin_src, mask); + trig_mask |= TRIG_TIMER | TRIG_EXT; + err |= cfc_check_trigger_src(&cmd->scan_begin_src, trig_mask); - tmp = cmd->convert_src; - mask = TRIG_TIMER | TRIG_EXT; + trig_mask = TRIG_TIMER | TRIG_EXT; if (devpriv->can_burst) - mask |= TRIG_NOW; - err |= cfc_check_trigger_src(&cmd->convert_src, mask); + trig_mask |= TRIG_NOW; + err |= cfc_check_trigger_src(&cmd->convert_src, trig_mask); err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); @@ -673,44 +700,28 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, /* step 4: fix up arguments */ if (cmd->scan_begin_src == TRIG_TIMER) { - unsigned int tmp = cmd->scan_begin_arg; - /* set divisors, correct timing arguments */ + arg = cmd->scan_begin_arg; i8253_cascade_ns_to_timer(devpriv->clockbase, &devpriv->divisor1, &devpriv->divisor2, - &cmd->scan_begin_arg, cmd->flags); - err += (tmp != cmd->scan_begin_arg); + &arg, cmd->flags); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (cmd->convert_src == TRIG_TIMER) { - unsigned int tmp = cmd->convert_arg; - /* set divisors, correct timing arguments */ + arg = cmd->convert_arg; i8253_cascade_ns_to_timer(devpriv->clockbase, &devpriv->divisor1, &devpriv->divisor2, - &cmd->convert_arg, cmd->flags); - err += (tmp != cmd->convert_arg); + &arg, cmd->flags); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); } if (err) return 4; - /* check channel/gain list against card's limitations */ - if (cmd->chanlist) { - gain = CR_RANGE(cmd->chanlist[0]); - start_chan = CR_CHAN(cmd->chanlist[0]); - for (i = 1; i < cmd->chanlist_len; i++) { - if (CR_CHAN(cmd->chanlist[i]) != - (start_chan + i) % s->n_chan) { - dev_err(dev->class_dev, - "entries in chanlist must be consecutive channels, counting upwards\n"); - err++; - } - if (CR_RANGE(cmd->chanlist[i]) != gain) { - dev_err(dev->class_dev, - "entries in chanlist must all have the same gain\n"); - err++; - } - } - } + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= das16_ai_check_chanlist(dev, s, cmd); + if (err) return 5; @@ -727,9 +738,10 @@ static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns, &devpriv->divisor1, &devpriv->divisor2, &ns, rounding_flags); - /* Write the values of ctr1 and ctr2 into counters 1 and 2 */ - i8254_load(timer_base, 0, 1, devpriv->divisor1, 2); - i8254_load(timer_base, 0, 2, devpriv->divisor2, 2); + i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY); + i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY); + i8254_write(timer_base, 0, 1, devpriv->divisor1); + i8254_write(timer_base, 0, 2, devpriv->divisor2); return ns; } @@ -750,8 +762,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) return -1; } - devpriv->adc_byte_count = - cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t); + devpriv->adc_byte_count = cmd->stop_arg * cfc_bytes_per_scan(s); if (devpriv->can_burst) outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV_REG); diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index 779225831dc0..ec039fbff0f9 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -150,11 +150,40 @@ static void munge_sample_array(unsigned short *array, unsigned int num_elements) array[i] = munge_sample(array[i]); } +static int das16m1_ai_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + int i; + + if (cmd->chanlist_len == 1) + return 0; + + if ((cmd->chanlist_len % 2) != 0) { + dev_dbg(dev->class_dev, + "chanlist must be of even length or length 1\n"); + return -EINVAL; + } + + for (i = 0; i < cmd->chanlist_len; i++) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); + + if ((i % 2) != (chan % 2)) { + dev_dbg(dev->class_dev, + "even/odd channels must go have even/odd chanlist indices\n"); + return -EINVAL; + } + } + + return 0; +} + static int das16m1_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { struct das16m1_private_struct *devpriv = dev->private; - unsigned int err = 0, tmp, i; + int err = 0; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -203,35 +232,20 @@ static int das16m1_cmd_test(struct comedi_device *dev, /* step 4: fix up arguments */ if (cmd->convert_src == TRIG_TIMER) { - tmp = cmd->convert_arg; - /* calculate counter values that give desired timing */ + arg = cmd->convert_arg; i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, &devpriv->divisor1, &devpriv->divisor2, - &cmd->convert_arg, cmd->flags); - if (tmp != cmd->convert_arg) - err++; + &arg, cmd->flags); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); } if (err) return 4; - /* check chanlist against board's peculiarities */ - if (cmd->chanlist && cmd->chanlist_len > 1) { - for (i = 0; i < cmd->chanlist_len; i++) { - /* even/odd channels must go into even/odd queue addresses */ - if ((i % 2) != (CR_CHAN(cmd->chanlist[i]) % 2)) { - comedi_error(dev, "bad chanlist:\n" - " even/odd channels must go have even/odd chanlist indices"); - err++; - } - } - if ((cmd->chanlist_len % 2) != 0) { - comedi_error(dev, - "chanlist must be of even length or length 1"); - err++; - } - } + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= das16m1_ai_check_chanlist(dev, s, cmd); if (err) return 5; @@ -239,26 +253,16 @@ static int das16m1_cmd_test(struct comedi_device *dev, return 0; } -/* This function takes a time in nanoseconds and sets the * - * 2 pacer clocks to the closest frequency possible. It also * - * returns the actual sampling period. */ -static unsigned int das16m1_set_pacer(struct comedi_device *dev, - unsigned int ns, int rounding_flags) +static void das16m1_set_pacer(struct comedi_device *dev) { struct das16m1_private_struct *devpriv = dev->private; + unsigned long timer_base = dev->iobase + DAS16M1_8254_SECOND; - i8253_cascade_ns_to_timer_2div(I8254_OSC_BASE_10MHZ, - &devpriv->divisor1, - &devpriv->divisor2, - &ns, rounding_flags); - - /* Write the values of ctr1 and ctr2 into counters 1 and 2 */ - i8254_load(dev->iobase + DAS16M1_8254_SECOND, 0, 1, devpriv->divisor1, - 2); - i8254_load(dev->iobase + DAS16M1_8254_SECOND, 0, 2, devpriv->divisor2, - 2); + i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY); + i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY); - return ns; + i8254_write(timer_base, 0, 1, devpriv->divisor1); + i8254_write(timer_base, 0, 2, devpriv->divisor2); } static int das16m1_cmd_exec(struct comedi_device *dev, @@ -267,6 +271,7 @@ static int das16m1_cmd_exec(struct comedi_device *dev, struct das16m1_private_struct *devpriv = dev->private; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; + unsigned long timer_base = dev->iobase + DAS16M1_8254_FIRST; unsigned int byte, i; /* disable interrupts and internal pacer */ @@ -278,11 +283,11 @@ static int das16m1_cmd_exec(struct comedi_device *dev, /* Initialize lower half of hardware counter, used to determine how * many samples are in fifo. Value doesn't actually load into counter * until counter's next clock (the next a/d conversion) */ - i8254_load(dev->iobase + DAS16M1_8254_FIRST, 0, 1, 0, 2); + i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY); + i8254_write(timer_base, 0, 1, 0); /* remember current reading of counter so we know when counter has * actually been loaded */ - devpriv->initial_hw_count = - i8254_read(dev->iobase + DAS16M1_8254_FIRST, 0, 1); + devpriv->initial_hw_count = i8254_read(timer_base, 0, 1); /* setup channel/gain queue */ for (i = 0; i < cmd->chanlist_len; i++) { outb(i, dev->iobase + DAS16M1_QUEUE_ADDR); @@ -292,10 +297,14 @@ static int das16m1_cmd_exec(struct comedi_device *dev, outb(byte, dev->iobase + DAS16M1_QUEUE_DATA); } - /* set counter mode and counts */ - cmd->convert_arg = - das16m1_set_pacer(dev, cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); + /* enable interrupts and set internal pacer counter mode and counts */ + devpriv->control_state &= ~PACER_MASK; + if (cmd->convert_src == TRIG_TIMER) { + das16m1_set_pacer(dev); + devpriv->control_state |= INT_PACER; + } else { /* TRIG_EXT */ + devpriv->control_state |= EXT_PACER; + } /* set control & status register */ byte = 0; @@ -308,13 +317,6 @@ static int das16m1_cmd_exec(struct comedi_device *dev, /* clear interrupt bit */ outb(0, dev->iobase + DAS16M1_CLEAR_INTR); - /* enable interrupts and internal pacer */ - devpriv->control_state &= ~PACER_MASK; - if (cmd->convert_src == TRIG_TIMER) - devpriv->control_state |= INT_PACER; - else - devpriv->control_state |= EXT_PACER; - devpriv->control_state |= INTE; outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL); diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 8e975d6b06db..859519026c4c 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -547,7 +547,7 @@ static void das1800_flush_dma_channel(struct comedi_device *dev, munge_data(dev, buffer, num_samples); cfc_write_array_to_buffer(s, buffer, num_bytes); - if (s->async->cmd.stop_src == TRIG_COUNT) + if (cmd->stop_src == TRIG_COUNT) devpriv->count -= num_samples; return; @@ -731,7 +731,7 @@ static irqreturn_t das1800_interrupt(int irq, void *d) /* converts requested conversion timing to timing compatible with * hardware, used only when card is in 'burst mode' */ -static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode) +static unsigned int burst_convert_arg(unsigned int convert_arg, int flags) { unsigned int micro_sec; @@ -740,7 +740,7 @@ static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode) convert_arg = 64000; /* the conversion time must be an integral number of microseconds */ - switch (round_mode) { + switch (flags & TRIG_ROUND_MASK) { case TRIG_ROUND_NEAREST: default: micro_sec = (convert_arg + 500) / 1000; @@ -757,6 +757,26 @@ static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode) return micro_sec * 1000; } +static int das1800_ai_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + unsigned int unipolar0 = CR_RANGE(cmd->chanlist[0]) & UNIPOLAR; + int i; + + for (i = 1; i < cmd->chanlist_len; i++) { + unsigned int unipolar = CR_RANGE(cmd->chanlist[i]) & UNIPOLAR; + + if (unipolar != unipolar0) { + dev_dbg(dev->class_dev, + "unipolar and bipolar ranges cannot be mixed in the chanlist\n"); + return -EINVAL; + } + } + + return 0; +} + /* test analog input cmd */ static int das1800_ai_do_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, @@ -765,9 +785,7 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev, const struct das1800_board *thisboard = comedi_board(dev); struct das1800_private *devpriv = dev->private; int err = 0; - unsigned int tmp_arg; - int i; - int unipolar; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -825,66 +843,48 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ - if (cmd->convert_src == TRIG_TIMER) { - /* if we are not in burst mode */ - if (cmd->scan_begin_src == TRIG_FOLLOW) { - tmp_arg = cmd->convert_arg; - /* calculate counter values that give desired timing */ + if (cmd->scan_begin_src == TRIG_FOLLOW && + cmd->convert_src == TRIG_TIMER) { + /* we are not in burst mode */ + arg = cmd->convert_arg; + i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ, + &devpriv->divisor1, + &devpriv->divisor2, + &cmd->convert_arg, cmd->flags); + if (arg != cmd->convert_arg) + err++; + } else if (cmd->convert_src == TRIG_TIMER) { + /* we are in burst mode */ + arg = cmd->convert_arg; + cmd->convert_arg = burst_convert_arg(cmd->convert_arg, + cmd->flags); + if (arg != cmd->convert_arg) + err++; + + if (cmd->scan_begin_src == TRIG_TIMER) { + arg = cmd->convert_arg * cmd->chanlist_len; + if (arg > cmd->scan_begin_arg) { + cmd->scan_begin_arg = arg; + err++; + } + + arg = cmd->scan_begin_arg; i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ, &devpriv->divisor1, &devpriv->divisor2, - &cmd->convert_arg, + &cmd->scan_begin_arg, cmd->flags); - if (tmp_arg != cmd->convert_arg) - err++; - } - /* if we are in burst mode */ - else { - /* check that convert_arg is compatible */ - tmp_arg = cmd->convert_arg; - cmd->convert_arg = - burst_convert_arg(cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); - if (tmp_arg != cmd->convert_arg) + if (arg != cmd->scan_begin_arg) err++; - - if (cmd->scan_begin_src == TRIG_TIMER) { - /* if scans are timed faster than conversion rate allows */ - if (cmd->convert_arg * cmd->chanlist_len > - cmd->scan_begin_arg) { - cmd->scan_begin_arg = - cmd->convert_arg * - cmd->chanlist_len; - err++; - } - tmp_arg = cmd->scan_begin_arg; - /* calculate counter values that give desired timing */ - i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ, - &devpriv->divisor1, - &devpriv->divisor2, - &cmd->scan_begin_arg, - cmd->flags); - if (tmp_arg != cmd->scan_begin_arg) - err++; - } } } if (err) return 4; - /* make sure user is not trying to mix unipolar and bipolar ranges */ - if (cmd->chanlist) { - unipolar = CR_RANGE(cmd->chanlist[0]) & UNIPOLAR; - for (i = 1; i < cmd->chanlist_len; i++) { - if (unipolar != (CR_RANGE(cmd->chanlist[i]) & UNIPOLAR)) { - comedi_error(dev, - "unipolar and bipolar ranges cannot be mixed in the chanlist"); - err++; - break; - } - } - } + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= das1800_ai_check_chanlist(dev, s, cmd); if (err) return 5; @@ -962,68 +962,29 @@ static int control_c_bits(const struct comedi_cmd *cmd) return control_c; } -/* loads counters with divisor1, divisor2 from private structure */ -static int das1800_set_frequency(struct comedi_device *dev) +static void das1800_setup_counters(struct comedi_device *dev, + const struct comedi_cmd *cmd) { struct das1800_private *devpriv = dev->private; - int err = 0; - - /* counter 1, mode 2 */ - if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 1, devpriv->divisor1, - 2)) - err++; - /* counter 2, mode 2 */ - if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 2, devpriv->divisor2, - 2)) - err++; - if (err) - return -1; + unsigned long timer_base = dev->iobase + DAS1800_COUNTER; - return 0; -} - -/* sets up counters */ -static int setup_counters(struct comedi_device *dev, - const struct comedi_cmd *cmd) -{ - struct das1800_private *devpriv = dev->private; - unsigned int period; + /* setup cascaded counters for conversion/scan frequency */ + if ((cmd->scan_begin_src == TRIG_FOLLOW || + cmd->scan_begin_src == TRIG_TIMER) && + cmd->convert_src == TRIG_TIMER) { + i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY); + i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY); - /* setup cascaded counters for conversion/scan frequency */ - switch (cmd->scan_begin_src) { - case TRIG_FOLLOW: /* not in burst mode */ - if (cmd->convert_src == TRIG_TIMER) { - /* set conversion frequency */ - period = cmd->convert_arg; - i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ, - &devpriv->divisor1, - &devpriv->divisor2, - &period, cmd->flags); - if (das1800_set_frequency(dev) < 0) - return -1; - } - break; - case TRIG_TIMER: /* in burst mode */ - /* set scan frequency */ - period = cmd->scan_begin_arg; - i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ, - &devpriv->divisor1, - &devpriv->divisor2, - &period, cmd->flags); - if (das1800_set_frequency(dev) < 0) - return -1; - break; - default: - break; + i8254_write(timer_base, 0, 1, devpriv->divisor1); + i8254_write(timer_base, 0, 2, devpriv->divisor2); } - /* setup counter 0 for 'about triggering' */ + /* setup counter 0 for 'about triggering' */ if (cmd->stop_src == TRIG_EXT) { - /* load counter 0 in mode 0 */ - i8254_load(dev->iobase + DAS1800_COUNTER, 0, 0, 1, 0); - } + i8254_set_mode(timer_base, 0, 0, I8254_MODE0 | I8254_BINARY); - return 0; + i8254_write(timer_base, 0, 0, 1); + } } /* utility function that suggests a dma transfer size based on the conversion period 'ns' */ @@ -1136,7 +1097,6 @@ static int das1800_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct das1800_private *devpriv = dev->private; - int ret; int control_a, control_c; struct comedi_async *async = s->async; const struct comedi_cmd *cmd = &async->cmd; @@ -1167,11 +1127,7 @@ static int das1800_ai_do_cmd(struct comedi_device *dev, /* setup card and start */ program_chanlist(dev, cmd); - ret = setup_counters(dev, cmd); - if (ret < 0) { - comedi_error(dev, "Error setting up counters"); - return ret; - } + das1800_setup_counters(dev, cmd); setup_dma(dev, cmd); outb(control_c, dev->iobase + DAS1800_CONTROL_C); /* set conversion rate and length for burst mode */ @@ -1470,7 +1426,7 @@ static int das1800_probe(struct comedi_device *dev) static int das1800_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - const struct das1800_board *thisboard = comedi_board(dev); + const struct das1800_board *thisboard; struct das1800_private *devpriv; struct comedi_subdevice *s; unsigned int irq = it->options[1]; diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c index e0cfb6cb547b..d18eea6c01aa 100644 --- a/drivers/staging/comedi/drivers/das6402.c +++ b/drivers/staging/comedi/drivers/das6402.c @@ -125,7 +125,7 @@ struct das6402_boardinfo { unsigned int maxdata; }; -struct das6402_boardinfo das6402_boards[] = { +static struct das6402_boardinfo das6402_boards[] = { { .name = "das6402-12", .maxdata = 0x0fff, diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index 3e408370dcf3..6f7f8d531dd5 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -224,7 +224,6 @@ struct das800_private { 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 */ - bool forever; /* flag that we should take data forever */ }; static void das800_ind_write(struct comedi_device *dev, @@ -275,31 +274,54 @@ static void das800_disable(struct comedi_device *dev) spin_unlock_irqrestore(&dev->spinlock, irq_flags); } -static int das800_set_frequency(struct comedi_device *dev) +static void das800_set_frequency(struct comedi_device *dev) { struct das800_private *devpriv = dev->private; - int err = 0; - - if (i8254_load(dev->iobase + DAS800_8254, 0, 1, devpriv->divisor1, 2)) - err++; - if (i8254_load(dev->iobase + DAS800_8254, 0, 2, devpriv->divisor2, 2)) - err++; - if (err) - return -1; + unsigned long timer_base = dev->iobase + DAS800_8254; - return 0; + i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY); + i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY); + i8254_write(timer_base, 0, 1, devpriv->divisor1); + i8254_write(timer_base, 0, 2, devpriv->divisor2); } static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct das800_private *devpriv = dev->private; - devpriv->forever = false; devpriv->count = 0; das800_disable(dev); return 0; } +static int das800_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]); + 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]); + + if (chan != (chan0 + i) % s->n_chan) { + dev_dbg(dev->class_dev, + "chanlist must be consecutive, counting upwards\n"); + return -EINVAL; + } + + if (range != range0) { + dev_dbg(dev->class_dev, + "chanlist must all have the same gain\n"); + return -EINVAL; + } + } + + return 0; +} + static int das800_ai_do_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) @@ -307,6 +329,7 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev, const struct das800_board *thisboard = comedi_board(dev); struct das800_private *devpriv = dev->private; int err = 0; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -352,41 +375,20 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ if (cmd->convert_src == TRIG_TIMER) { - int tmp = cmd->convert_arg; - - /* calculate counter values that give desired timing */ + arg = cmd->convert_arg; i8253_cascade_ns_to_timer(I8254_OSC_BASE_1MHZ, &devpriv->divisor1, &devpriv->divisor2, - &cmd->convert_arg, cmd->flags); - if (tmp != cmd->convert_arg) - err++; + &arg, cmd->flags); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); } if (err) return 4; - /* check channel/gain list against card's limitations */ - if (cmd->chanlist) { - unsigned int chan = CR_CHAN(cmd->chanlist[0]); - unsigned int range = CR_RANGE(cmd->chanlist[0]); - unsigned int next; - int i; - - for (i = 1; i < cmd->chanlist_len; i++) { - next = cmd->chanlist[i]; - if (CR_CHAN(next) != (chan + i) % N_CHAN_AI) { - dev_err(dev->class_dev, - "chanlist must be consecutive, counting upwards\n"); - err++; - } - if (CR_RANGE(next) != range) { - dev_err(dev->class_dev, - "chanlist must all have the same gain\n"); - err++; - } - } - } + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= das800_ai_check_chanlist(dev, s, cmd); if (err) return 5; @@ -400,9 +402,10 @@ static int das800_ai_do_cmd(struct comedi_device *dev, const struct das800_board *thisboard = comedi_board(dev); struct das800_private *devpriv = dev->private; struct comedi_async *async = s->async; - unsigned int gain = CR_RANGE(async->cmd.chanlist[0]); - unsigned int start_chan = CR_CHAN(async->cmd.chanlist[0]); - unsigned int end_chan = (start_chan + async->cmd.chanlist_len - 1) % 8; + struct comedi_cmd *cmd = &async->cmd; + unsigned int gain = CR_RANGE(cmd->chanlist[0]); + unsigned int start_chan = CR_CHAN(cmd->chanlist[0]); + unsigned int end_chan = (start_chan + cmd->chanlist_len - 1) % 8; unsigned int scan_chans = (end_chan << 3) | start_chan; int conv_bits; unsigned long irq_flags; @@ -420,28 +423,22 @@ static int das800_ai_do_cmd(struct comedi_device *dev, gain &= 0xf; outb(gain, dev->iobase + DAS800_GAIN); - if (async->cmd.stop_src == TRIG_COUNT) { - devpriv->count = async->cmd.stop_arg * async->cmd.chanlist_len; - devpriv->forever = false; - } else { /* TRIG_NONE */ - devpriv->forever = true; + 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 */ conv_bits = 0; conv_bits |= EACS | IEOC; - if (async->cmd.start_src == TRIG_EXT) + if (cmd->start_src == TRIG_EXT) conv_bits |= DTEN; - if (async->cmd.convert_src == TRIG_TIMER) { + if (cmd->convert_src == TRIG_TIMER) { conv_bits |= CASC | ITE; /* set conversion frequency */ - if (das800_set_frequency(dev) < 0) { - comedi_error(dev, "Error setting up counters"); - return -1; - } + das800_set_frequency(dev); } spin_lock_irqsave(&dev->spinlock, irq_flags); @@ -465,7 +462,8 @@ static irqreturn_t das800_interrupt(int irq, void *d) struct comedi_device *dev = d; struct das800_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; - struct comedi_async *async = s ? s->async : NULL; + struct comedi_async *async; + struct comedi_cmd *cmd; unsigned long irq_flags; unsigned int status; unsigned int val; @@ -479,6 +477,9 @@ static irqreturn_t das800_interrupt(int irq, void *d) if (!dev->attached) return IRQ_HANDLED; + async = s->async; + cmd = &async->cmd; + spin_lock_irqsave(&dev->spinlock, irq_flags); status = das800_ind_read(dev, CONTROL1) & STATUS2_HCEN; /* @@ -510,7 +511,7 @@ static irqreturn_t das800_interrupt(int irq, void *d) val >>= 4; /* 12-bit sample */ /* if there are more data points to collect */ - if (devpriv->count > 0 || devpriv->forever) { + if (cmd->stop_src == TRIG_NONE || devpriv->count > 0) { /* write data point to buffer */ cfc_write_to_buffer(s, val & s->maxdata); devpriv->count--; @@ -525,7 +526,7 @@ static irqreturn_t das800_interrupt(int irq, void *d) return IRQ_HANDLED; } - if (devpriv->count > 0 || devpriv->forever) { + if (cmd->stop_src == TRIG_NONE || devpriv->count > 0) { /* Re-enable card's interrupt. * We already have spinlock, so indirect addressing is safe */ das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits, @@ -673,7 +674,7 @@ static int das800_probe(struct comedi_device *dev) static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - const struct das800_board *thisboard = comedi_board(dev); + const struct das800_board *thisboard; struct das800_private *devpriv; struct comedi_subdevice *s; unsigned int irq = it->options[1]; diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index c8a36eb5f015..ad7a5d53b97b 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -243,13 +243,39 @@ static int dmm32at_ns_to_timer(unsigned int *ns, int round) return *ns; } +static int dmm32at_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]); + 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]); + + if (chan != (chan0 + i) % s->n_chan) { + dev_dbg(dev->class_dev, + "entries in chanlist must be consecutive channels, counting upwards\n"); + return -EINVAL; + } + if (range != range0) { + dev_dbg(dev->class_dev, + "entries in chanlist must all have the same gain\n"); + return -EINVAL; + } + } + + return 0; +} + static int dmm32at_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0; - int tmp; - int start_chan, gain, i; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -325,50 +351,28 @@ static int dmm32at_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ if (cmd->scan_begin_src == TRIG_TIMER) { - tmp = cmd->scan_begin_arg; - dmm32at_ns_to_timer(&cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); - if (tmp != cmd->scan_begin_arg) - err++; + arg = cmd->scan_begin_arg; + dmm32at_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (cmd->convert_src == TRIG_TIMER) { - tmp = cmd->convert_arg; - dmm32at_ns_to_timer(&cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); - if (tmp != cmd->convert_arg) - err++; - 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++; + arg = cmd->convert_arg; + dmm32at_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + 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); } } if (err) return 4; - /* step 5 check the channel list, the channel list for this - board must be consecutive and gains must be the same */ - - if (cmd->chanlist) { - gain = CR_RANGE(cmd->chanlist[0]); - start_chan = CR_CHAN(cmd->chanlist[0]); - for (i = 1; i < cmd->chanlist_len; i++) { - if (CR_CHAN(cmd->chanlist[i]) != - (start_chan + i) % s->n_chan) { - comedi_error(dev, - "entries in chanlist must be consecutive channels, counting upwards\n"); - err++; - } - if (CR_RANGE(cmd->chanlist[i]) != gain) { - comedi_error(dev, - "entries in chanlist must all have the same gain\n"); - err++; - } - } - } + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= dmm32at_ai_check_chanlist(dev, s, cmd); if (err) return 5; @@ -464,12 +468,6 @@ static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) outb(0xff, dev->iobase + DMM32AT_CONV); } -/* for(i=0;i<cmd->chanlist_len;i++) */ -/* comedi_buf_put(s->async,i*100); */ - -/* s->async->events |= COMEDI_CB_EOA; */ -/* comedi_event(dev, s); */ - return 0; } @@ -510,7 +508,7 @@ static irqreturn_t dmm32at_isr(int irq, void *d) /* invert sign bit to make range unsigned */ samp = ((msb ^ 0x0080) << 8) + lsb; - comedi_buf_put(s->async, samp); + comedi_buf_put(s, samp); } if (devpriv->ai_scans_left != 0xffffffff) { /* TRIG_COUNT */ diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index d4d4e4b497dc..4263014426f8 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -545,7 +545,7 @@ static int dt2801_dio_insn_config(struct comedi_device *dev, */ static int dt2801_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - const struct dt2801_board *board = comedi_board(dev); + const struct dt2801_board *board; struct dt2801_private *devpriv; struct comedi_subdevice *s; int board_code, type; diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index 3794b7e52091..904c9f0e4afb 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -128,7 +128,7 @@ static int dt2814_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0; - int tmp; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -170,10 +170,9 @@ static int dt2814_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ - tmp = cmd->scan_begin_arg; - dt2814_ns_to_timer(&cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); - if (tmp != cmd->scan_begin_arg) - err++; + arg = cmd->scan_begin_arg; + dt2814_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); if (err) return 4; diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 16cc100531e5..c2a66dcf99fe 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -466,7 +466,7 @@ static irqreturn_t dt282x_interrupt(int irq, void *d) if (devpriv->ad_2scomp) data ^= 1 << (board->adbits - 1); - ret = comedi_buf_put(s->async, data); + ret = comedi_buf_put(s, data); if (ret == 0) s->async->events |= COMEDI_CB_OVERFLOW; @@ -578,7 +578,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev, { const struct dt282x_board *board = comedi_board(dev); int err = 0; - int tmp; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -633,10 +633,9 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ - tmp = cmd->convert_arg; - dt282x_ns_to_timer(&cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); - if (tmp != cmd->convert_arg) - err++; + arg = cmd->convert_arg; + dt282x_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); if (err) return 4; @@ -825,7 +824,7 @@ static int dt282x_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0; - int tmp; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -852,7 +851,7 @@ static int dt282x_ao_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, 5000); err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); - err |= cfc_check_trigger_arg_max(&cmd->scan_end_arg, 2); + err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); if (cmd->stop_src == TRIG_COUNT) { /* any count is allowed */ @@ -865,10 +864,9 @@ static int dt282x_ao_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ - tmp = cmd->scan_begin_arg; - dt282x_ns_to_timer(&cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); - if (tmp != cmd->scan_begin_arg) - err++; + arg = cmd->scan_begin_arg; + dt282x_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); if (err) return 4; @@ -878,12 +876,14 @@ static int dt282x_ao_cmdtest(struct comedi_device *dev, } static int dt282x_ao_inttrig(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned int x) + struct comedi_subdevice *s, + unsigned int trig_num) { struct dt282x_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; int size; - if (x != 0) + if (trig_num != cmd->start_src) return -EINVAL; size = cfc_read_array_from_buffer(s, devpriv->dma[0].buf, diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 436e451cadf5..4ab4de005924 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -322,7 +322,7 @@ static void dt3k_ai_empty_fifo(struct comedi_device *dev, for (i = 0; i < count; i++) { data = readw(devpriv->io_addr + DPR_ADC_buffer + rear); - comedi_buf_put(s->async, data); + comedi_buf_put(s, data); rear++; if (rear >= AI_FIFO_DEPTH) rear = 0; @@ -416,7 +416,7 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev, { const struct dt3k_boardtype *this_board = comedi_board(dev); int err = 0; - int tmp; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -466,25 +466,20 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ if (cmd->scan_begin_src == TRIG_TIMER) { - tmp = cmd->scan_begin_arg; - dt3k_ns_to_timer(100, &cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); - if (tmp != cmd->scan_begin_arg) - err++; + arg = cmd->scan_begin_arg; + dt3k_ns_to_timer(100, &arg, cmd->flags & TRIG_ROUND_MASK); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (cmd->convert_src == TRIG_TIMER) { - tmp = cmd->convert_arg; - dt3k_ns_to_timer(50, &cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); - if (tmp != cmd->convert_arg) - err++; - 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++; + arg = cmd->convert_arg; + dt3k_ns_to_timer(50, &arg, cmd->flags & TRIG_ROUND_MASK); + 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); } } diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index 08d7655e24e7..22333c1ad88c 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -360,12 +360,30 @@ static int gsc_hpdi_cmd(struct comedi_device *dev, return 0; } +static int gsc_hpdi_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + int i; + + for (i = 0; i < cmd->chanlist_len; i++) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); + + if (chan != i) { + dev_dbg(dev->class_dev, + "chanlist must be ch 0 to 31 in order\n"); + return -EINVAL; + } + } + + return 0; +} + static int gsc_hpdi_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0; - int i; if (s->io_bits) return -EINVAL; @@ -392,6 +410,8 @@ static int gsc_hpdi_cmd_test(struct comedi_device *dev, /* Step 3: check if arguments are trivially valid */ + err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); + if (!cmd->chanlist_len || !cmd->chanlist) { cmd->chanlist_len = 32; err |= -EINVAL; @@ -411,17 +431,9 @@ static int gsc_hpdi_cmd_test(struct comedi_device *dev, if (err) return 4; - /* step 5: complain about special chanlist considerations */ - - for (i = 0; i < cmd->chanlist_len; i++) { - if (CR_CHAN(cmd->chanlist[i]) != i) { - /* XXX could support 8 or 16 channels */ - dev_err(dev->class_dev, - "chanlist must be ch 0 to 31 in order"); - err |= -EINVAL; - break; - } - } + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= gsc_hpdi_check_chanlist(dev, s, cmd); if (err) return 5; diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 3558ab3b6e1f..2516ce834839 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -461,6 +461,7 @@ static int ii20k_attach(struct comedi_device *dev, id = readb(devpriv->ioaddr + II20K_ID_REG); switch (id & II20K_ID_MASK) { case II20K_ID_PCI20001C_1A: + has_dio = false; break; case II20K_ID_PCI20001C_2A: has_dio = true; diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index f02b31b317ec..25ce2f78db81 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -598,67 +598,35 @@ static int me4000_ai_cancel(struct comedi_device *dev, return 0; } -static int ai_check_chanlist(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_cmd *cmd) +static int me4000_ai_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) { - const struct me4000_board *thisboard = comedi_board(dev); - int aref; + const struct me4000_board *board = comedi_board(dev); + unsigned int max_diff_chan = board->ai_diff_nchan; + unsigned int aref0 = CR_AREF(cmd->chanlist[0]); int i; - /* Check whether a channel list is available */ - if (!cmd->chanlist_len) { - dev_err(dev->class_dev, "No channel list available\n"); - return -EINVAL; - } - - /* Check the channel list size */ - if (cmd->chanlist_len > ME4000_AI_CHANNEL_LIST_COUNT) { - dev_err(dev->class_dev, "Channel list is to large\n"); - return -EINVAL; - } - - /* Check the pointer */ - if (!cmd->chanlist) { - dev_err(dev->class_dev, "NULL pointer to channel list\n"); - return -EFAULT; - } - - /* Check whether aref is equal for all entries */ - aref = CR_AREF(cmd->chanlist[0]); for (i = 0; i < cmd->chanlist_len; i++) { - if (CR_AREF(cmd->chanlist[i]) != aref) { - dev_err(dev->class_dev, + 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 (aref != aref0) { + dev_dbg(dev->class_dev, "Mode is not equal for all entries\n"); return -EINVAL; } - } - /* Check whether channels are available for this ending */ - if (aref == SDF_DIFF) { - for (i = 0; i < cmd->chanlist_len; i++) { - if (CR_CHAN(cmd->chanlist[i]) >= - thisboard->ai_diff_nchan) { - dev_err(dev->class_dev, - "Channel number to high\n"); - return -EINVAL; - } - } - } else { - for (i = 0; i < cmd->chanlist_len; i++) { - if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai_nchan) { - dev_err(dev->class_dev, + if (aref == SDF_DIFF) { + if (chan >= max_diff_chan) { + dev_dbg(dev->class_dev, "Channel number to high\n"); return -EINVAL; } - } - } - /* Check if bipolar is set for all entries when in differential mode */ - if (aref == SDF_DIFF) { - for (i = 0; i < cmd->chanlist_len; i++) { - if (CR_RANGE(cmd->chanlist[i]) != 1 && - CR_RANGE(cmd->chanlist[i]) != 2) { - dev_err(dev->class_dev, + if (!comedi_range_is_bipolar(s, range)) { + dev_dbg(dev->class_dev, "Bipolar is not selected in differential mode\n"); return -EINVAL; } @@ -934,22 +902,13 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, err |= -EINVAL; } - if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_NONE) { - } else if (cmd->stop_src == TRIG_COUNT && - cmd->scan_end_src == TRIG_NONE) { - } else if (cmd->stop_src == TRIG_NONE && - cmd->scan_end_src == TRIG_COUNT) { - } else if (cmd->stop_src == TRIG_COUNT && - cmd->scan_end_src == TRIG_COUNT) { - } else { - err |= -EINVAL; - } - if (err) return 2; /* Step 3: check if arguments are trivially valid */ + err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); + if (cmd->chanlist_len < 1) { cmd->chanlist_len = 1; err |= -EINVAL; @@ -1091,10 +1050,11 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, if (err) return 4; - /* - * Stage 5. Check the channel list. - */ - if (ai_check_chanlist(dev, s, cmd)) + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= me4000_ai_check_chanlist(dev, s, cmd); + + if (err) return 5; return 0; @@ -1164,7 +1124,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->async, lval)) { + if (!comedi_buf_put(s, lval)) { /* * Buffer overflow, so stop conversion * and disable all interrupts @@ -1209,7 +1169,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->async, lval)) { + if (!comedi_buf_put(s, lval)) { dev_err(dev->class_dev, "Buffer overflow\n"); s->async->events |= COMEDI_CB_OVERFLOW; break; @@ -1392,6 +1352,7 @@ static int me4000_cnt_insn_config(struct comedi_device *dev, unsigned int *data) { struct me4000_info *info = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); int err; switch (data[0]) { @@ -1399,16 +1360,17 @@ static int me4000_cnt_insn_config(struct comedi_device *dev, if (insn->n != 1) return -EINVAL; - err = i8254_load(info->timer_regbase, 0, insn->chanspec, 0, - I8254_MODE0 | I8254_BINARY); + err = i8254_set_mode(info->timer_regbase, 0, chan, + I8254_MODE0 | I8254_BINARY); if (err) return err; + i8254_write(info->timer_regbase, 0, chan, 0); break; case GPCT_SET_OPERATION: if (insn->n != 2) return -EINVAL; - err = i8254_set_mode(info->timer_regbase, 0, insn->chanspec, + err = i8254_set_mode(info->timer_regbase, 0, chan, (data[1] << 1) | I8254_BINARY); if (err) return err; diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index 1a572c83f996..19c029acbc99 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -307,8 +307,9 @@ EXPORT_SYMBOL_GPL(mite_dma_arm); /**************************************/ int mite_buf_change(struct mite_dma_descriptor_ring *ring, - struct comedi_async *async) + struct comedi_subdevice *s) { + struct comedi_async *async = s->async; unsigned int n_links; int i; @@ -333,7 +334,7 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring, n_links * sizeof(struct mite_dma_descriptor), &ring->descriptors_dma_addr, GFP_KERNEL); if (!ring->descriptors) { - dev_err(async->subdevice->device->class_dev, + dev_err(s->device->class_dev, "mite: ring buffer allocation failed\n"); return -ENOMEM; } @@ -525,15 +526,15 @@ void mite_dma_disarm(struct mite_channel *mite_chan) EXPORT_SYMBOL_GPL(mite_dma_disarm); int mite_sync_input_dma(struct mite_channel *mite_chan, - struct comedi_async *async) + struct comedi_subdevice *s) { - struct comedi_subdevice *s = async->subdevice; + struct comedi_async *async = s->async; int count; unsigned int nbytes, old_alloc_count; old_alloc_count = async->buf_write_alloc_count; /* write alloc as much as we can */ - comedi_buf_write_alloc(async, async->prealloc_bufsz); + comedi_buf_write_alloc(s, async->prealloc_bufsz); nbytes = mite_bytes_written_to_memory_lb(mite_chan); if ((int)(mite_bytes_written_to_memory_ub(mite_chan) - @@ -550,7 +551,7 @@ int mite_sync_input_dma(struct mite_channel *mite_chan, if (count <= 0) return 0; - comedi_buf_write_free(async, count); + comedi_buf_write_free(s, count); cfc_inc_scan_progress(s, count); async->events |= COMEDI_CB_BLOCK; return 0; @@ -558,28 +559,25 @@ int mite_sync_input_dma(struct mite_channel *mite_chan, EXPORT_SYMBOL_GPL(mite_sync_input_dma); int mite_sync_output_dma(struct mite_channel *mite_chan, - struct comedi_async *async) + struct comedi_subdevice *s) { - int count; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + u32 stop_count = cmd->stop_arg * cfc_bytes_per_scan(s); + unsigned int old_alloc_count = async->buf_read_alloc_count; u32 nbytes_ub, nbytes_lb; - unsigned int old_alloc_count; - u32 stop_count = - async->cmd.stop_arg * cfc_bytes_per_scan(async->subdevice); + int count; - old_alloc_count = async->buf_read_alloc_count; /* read alloc as much as we can */ - comedi_buf_read_alloc(async, async->prealloc_bufsz); + comedi_buf_read_alloc(s, async->prealloc_bufsz); nbytes_lb = mite_bytes_read_from_memory_lb(mite_chan); - if (async->cmd.stop_src == TRIG_COUNT && - (int)(nbytes_lb - stop_count) > 0) + if (cmd->stop_src == TRIG_COUNT && (int)(nbytes_lb - stop_count) > 0) nbytes_lb = stop_count; nbytes_ub = mite_bytes_read_from_memory_ub(mite_chan); - if (async->cmd.stop_src == TRIG_COUNT && - (int)(nbytes_ub - stop_count) > 0) + if (cmd->stop_src == TRIG_COUNT && (int)(nbytes_ub - stop_count) > 0) nbytes_ub = stop_count; if ((int)(nbytes_ub - old_alloc_count) > 0) { - dev_warn(async->subdevice->device->class_dev, - "mite: DMA underrun\n"); + dev_warn(s->device->class_dev, "mite: DMA underrun\n"); async->events |= COMEDI_CB_OVERFLOW; return -1; } @@ -588,7 +586,7 @@ int mite_sync_output_dma(struct mite_channel *mite_chan, return 0; if (count) { - comedi_buf_read_free(async, count); + comedi_buf_read_free(s, count); async->events |= COMEDI_CB_BLOCK; } return 0; diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h index 78f235747991..e6e58e989b73 100644 --- a/drivers/staging/comedi/drivers/mite.h +++ b/drivers/staging/comedi/drivers/mite.h @@ -106,9 +106,9 @@ unsigned mite_dma_tcr(struct mite_channel *mite_chan); void mite_dma_arm(struct mite_channel *mite_chan); void mite_dma_disarm(struct mite_channel *mite_chan); int mite_sync_input_dma(struct mite_channel *mite_chan, - struct comedi_async *async); + struct comedi_subdevice *s); int mite_sync_output_dma(struct mite_channel *mite_chan, - struct comedi_async *async); + struct comedi_subdevice *s); u32 mite_bytes_written_to_memory_lb(struct mite_channel *mite_chan); u32 mite_bytes_written_to_memory_ub(struct mite_channel *mite_chan); u32 mite_bytes_read_from_memory_lb(struct mite_channel *mite_chan); @@ -120,7 +120,7 @@ int mite_done(struct mite_channel *mite_chan); void mite_prep_dma(struct mite_channel *mite_chan, unsigned int num_device_bits, unsigned int num_memory_bits); int mite_buf_change(struct mite_dma_descriptor_ring *ring, - struct comedi_async *async); + struct comedi_subdevice *s); static inline int CHAN_OFFSET(int channel) { diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index 860fc81fb11c..c8b1fa793a37 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -215,7 +215,7 @@ static irqreturn_t ni6527_interrupt(int irq, void *d) return IRQ_NONE; if (status & NI6527_STATUS_EDGE) { - comedi_buf_put(s->async, 0); + comedi_buf_put(s, 0); s->async->events |= COMEDI_CB_EOS; comedi_event(dev, s); } @@ -253,7 +253,7 @@ static int ni6527_intr_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); - err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, 1); + err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); if (err) @@ -421,6 +421,7 @@ static int ni6527_auto_attach(struct comedi_device *dev, s->range_table = &range_digital; s->insn_config = ni6527_intr_insn_config; s->insn_bits = ni6527_intr_insn_bits; + s->len_chanlist = 1; s->do_cmdtest = ni6527_intr_cmdtest; s->do_cmd = ni6527_intr_cmd; s->cancel = ni6527_intr_cancel; diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index 6e42001f686e..9a139d6b8ef4 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -439,7 +439,7 @@ static irqreturn_t ni_65xx_interrupt(int irq, void *d) writeb(ClrEdge | ClrOverflow, devpriv->mite->daq_io_addr + Clear_Register); - comedi_buf_put(s->async, 0); + comedi_buf_put(s, 0); s->async->events |= COMEDI_CB_EOS; comedi_event(dev, s); return IRQ_HANDLED; @@ -473,7 +473,7 @@ static int ni_65xx_intr_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); - err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, 1); + err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); if (err) @@ -491,7 +491,6 @@ static int ni_65xx_intr_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct ni_65xx_private *devpriv = dev->private; - /* struct comedi_cmd *cmd = &s->async->cmd; */ writeb(ClrEdge | ClrOverflow, devpriv->mite->daq_io_addr + Clear_Register); @@ -671,6 +670,7 @@ static int ni_65xx_auto_attach(struct comedi_device *dev, s->n_chan = 1; s->range_table = &range_unknown; s->maxdata = 1; + s->len_chanlist = 1; s->do_cmdtest = ni_65xx_intr_cmdtest; s->do_cmd = ni_65xx_intr_cmd; s->cancel = ni_65xx_intr_cancel; diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 0d4b9019f76a..634cde83a02b 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -823,9 +823,9 @@ static int ni_660x_input_poll(struct comedi_device *dev, /* lock to avoid race with comedi_poll */ spin_lock_irqsave(&devpriv->interrupt_lock, flags); - mite_sync_input_dma(counter->mite_chan, s->async); + mite_sync_input_dma(counter->mite_chan, s); spin_unlock_irqrestore(&devpriv->interrupt_lock, flags); - return comedi_buf_read_n_available(s->async); + return comedi_buf_read_n_available(s); } static int ni_660x_buf_change(struct comedi_device *dev, @@ -836,7 +836,7 @@ static int ni_660x_buf_change(struct comedi_device *dev, struct ni_gpct *counter = s->private; int ret; - ret = mite_buf_change(mite_ring(devpriv, counter), s->async); + ret = mite_buf_change(mite_ring(devpriv, counter), s); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 4e39b1f63d81..5bd19494dbf6 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -287,14 +287,54 @@ static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } +static int a2150_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 aref0 = CR_AREF(cmd->chanlist[0]); + int i; + + if (cmd->chanlist_len == 2 && (chan0 == 1 || chan0 == 3)) { + dev_dbg(dev->class_dev, + "length 2 chanlist must be channels 0,1 or channels 2,3\n"); + return -EINVAL; + } + + if (cmd->chanlist_len == 3) { + dev_dbg(dev->class_dev, + "chanlist must have 1,2 or 4 channels\n"); + return -EINVAL; + } + + for (i = 1; i < cmd->chanlist_len; i++) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); + unsigned int aref = CR_AREF(cmd->chanlist[i]); + + if (chan != (chan0 + i)) { + dev_dbg(dev->class_dev, + "entries in chanlist must be consecutive channels, counting upwards\n"); + return -EINVAL; + } + + if (chan == 2) + aref0 = aref; + if (aref != aref0) { + dev_dbg(dev->class_dev, + "channels 0/1 and 2/3 must have the same analog reference\n"); + return -EINVAL; + } + } + + return 0; +} + static int a2150_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { const struct a2150_board *thisboard = comedi_board(dev); int err = 0; - int tmp; - int startChan; - int i; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -339,42 +379,17 @@ static int a2150_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ if (cmd->scan_begin_src == TRIG_TIMER) { - tmp = cmd->scan_begin_arg; - a2150_get_timing(dev, &cmd->scan_begin_arg, cmd->flags); - if (tmp != cmd->scan_begin_arg) - err++; + arg = cmd->scan_begin_arg; + a2150_get_timing(dev, &arg, cmd->flags); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (err) return 4; - /* check channel/gain list against card's limitations */ - if (cmd->chanlist) { - startChan = CR_CHAN(cmd->chanlist[0]); - for (i = 1; i < cmd->chanlist_len; i++) { - if (CR_CHAN(cmd->chanlist[i]) != (startChan + i)) { - comedi_error(dev, - "entries in chanlist must be consecutive channels, counting upwards\n"); - err++; - } - } - if (cmd->chanlist_len == 2 && CR_CHAN(cmd->chanlist[0]) == 1) { - comedi_error(dev, - "length 2 chanlist must be channels 0,1 or channels 2,3"); - err++; - } - if (cmd->chanlist_len == 3) { - comedi_error(dev, - "chanlist must have 1,2 or 4 channels"); - err++; - } - if (CR_AREF(cmd->chanlist[0]) != CR_AREF(cmd->chanlist[1]) || - CR_AREF(cmd->chanlist[2]) != CR_AREF(cmd->chanlist[3])) { - comedi_error(dev, - "channels 0/1 and 2/3 must have the same analog reference"); - err++; - } - } + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= a2150_ai_check_chanlist(dev, s, cmd); if (err) return 5; @@ -387,6 +402,7 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) struct a2150_private *devpriv = dev->private; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; + unsigned long timer_base = dev->iobase + I8253_BASE_REG; unsigned long lock_flags; unsigned int old_config_bits = devpriv->config_bits; unsigned int trigger_bits; @@ -454,7 +470,8 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG); /* may need to wait 72 sampling periods if timing was changed */ - i8254_load(dev->iobase + I8253_BASE_REG, 0, 2, 72, 0); + i8254_set_mode(timer_base, 0, 2, I8254_MODE0 | I8254_BINARY); + i8254_write(timer_base, 0, 2, 72); /* setup start triggering */ trigger_bits = 0; @@ -679,7 +696,7 @@ static int a2150_probe(struct comedi_device *dev) static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - const struct a2150_board *thisboard = comedi_board(dev); + const struct a2150_board *thisboard; struct a2150_private *devpriv; struct comedi_subdevice *s; unsigned int irq = it->options[1]; diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index 10e3e9475ee2..c93b47bcca51 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -310,6 +310,7 @@ static int atao_calib_insn_read(struct comedi_device *dev, static void atao_reset(struct comedi_device *dev) { struct atao_private *devpriv = dev->private; + unsigned long timer_base = dev->iobase + ATAO_82C53_BASE; /* This is the reset sequence described in the manual */ @@ -317,10 +318,9 @@ static void atao_reset(struct comedi_device *dev) outw(devpriv->cfg1, dev->iobase + ATAO_CFG1_REG); /* Put outputs of counter 1 and counter 2 in a high state */ - i8254_load(dev->iobase + ATAO_82C53_BASE, 0, - 0, 0x0003, I8254_MODE4 | I8254_BINARY); - i8254_set_mode(dev->iobase + ATAO_82C53_BASE, 0, - 1, I8254_MODE4 | I8254_BINARY); + i8254_set_mode(timer_base, 0, 0, I8254_MODE4 | I8254_BINARY); + i8254_set_mode(timer_base, 0, 1, I8254_MODE4 | I8254_BINARY); + i8254_write(timer_base, 0, 0, 0x0003); outw(ATAO_CFG2_CALLD_NOP, dev->iobase + ATAO_CFG2_REG); diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index 4262385e4f46..6ad27f50c6ec 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -221,7 +221,7 @@ static irqreturn_t atmio16d_interrupt(int irq, void *d) struct comedi_device *dev = d; struct comedi_subdevice *s = dev->read_subdev; - comedi_buf_put(s->async, inw(dev->iobase + AD_FIFO_REG)); + comedi_buf_put(s, inw(dev->iobase + AD_FIFO_REG)); comedi_event(dev, s); return IRQ_HANDLED; diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index f4216e825f03..3e3f940fa57c 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -171,32 +171,39 @@ static const struct labpc_boardinfo labpc_boards[] = { }; #endif -static int labpc_counter_load(struct comedi_device *dev, - unsigned long base_address, - unsigned int counter_number, - unsigned int count, unsigned int mode) +static void labpc_counter_load(struct comedi_device *dev, + unsigned long base_address, + unsigned int counter_number, + unsigned int count, + unsigned int mode) { const struct labpc_boardinfo *board = comedi_board(dev); - if (board->has_mmio) - return i8254_mm_load((void __iomem *)base_address, 0, - counter_number, count, mode); - else - return i8254_load(base_address, 0, counter_number, count, mode); + if (board->has_mmio) { + void __iomem *mmio_base = (void __iomem *)base_address; + + i8254_mm_set_mode(mmio_base, 0, counter_number, mode); + i8254_mm_write(mmio_base, 0, counter_number, count); + } else { + i8254_set_mode(base_address, 0, counter_number, mode); + i8254_write(base_address, 0, counter_number, count); + } } -static int labpc_counter_set_mode(struct comedi_device *dev, - unsigned long base_address, - unsigned int counter_number, - unsigned int mode) +static void labpc_counter_set_mode(struct comedi_device *dev, + unsigned long base_address, + unsigned int counter_number, + unsigned int mode) { const struct labpc_boardinfo *board = comedi_board(dev); - if (board->has_mmio) - return i8254_mm_set_mode((void __iomem *)base_address, 0, - counter_number, mode); - else - return i8254_set_mode(base_address, 0, counter_number, mode); + if (board->has_mmio) { + void __iomem *mmio_base = (void __iomem *)base_address; + + i8254_mm_set_mode(mmio_base, 0, counter_number, mode); + } else { + i8254_set_mode(base_address, 0, counter_number, mode); + } } static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s) @@ -349,10 +356,8 @@ static int labpc_ai_insn_read(struct comedi_device *dev, devpriv->write_byte(devpriv->cmd4, dev->iobase + CMD4_REG); /* initialize pacer counter to prevent any problems */ - ret = labpc_counter_set_mode(dev, dev->iobase + COUNTER_A_BASE_REG, - 0, I8254_MODE2); - if (ret) - return ret; + labpc_counter_set_mode(dev, dev->iobase + COUNTER_A_BASE_REG, + 0, I8254_MODE2); labpc_clear_adc_fifo(dev); @@ -546,72 +551,60 @@ static enum scan_mode labpc_ai_scan_mode(const struct comedi_cmd *cmd) return 0; } -static int labpc_ai_chanlist_invalid(const struct comedi_device *dev, - const struct comedi_cmd *cmd, - enum scan_mode mode) +static int labpc_ai_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) { - int channel, range, aref, i; - - if (cmd->chanlist == NULL) - return 0; + enum scan_mode mode = labpc_ai_scan_mode(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; if (mode == MODE_SINGLE_CHAN) return 0; - if (mode == MODE_SINGLE_CHAN_INTERVAL) { - if (cmd->chanlist_len > 0xff) { - comedi_error(dev, - "ni_labpc: chanlist too long for single channel interval mode\n"); - return 1; - } - } - - channel = CR_CHAN(cmd->chanlist[0]); - range = CR_RANGE(cmd->chanlist[0]); - aref = CR_AREF(cmd->chanlist[0]); - for (i = 0; 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]); switch (mode) { + case MODE_SINGLE_CHAN: + break; case MODE_SINGLE_CHAN_INTERVAL: - if (CR_CHAN(cmd->chanlist[i]) != channel) { - comedi_error(dev, - "channel scanning order specified in chanlist is not supported by hardware.\n"); - return 1; + if (chan != chan0) { + dev_dbg(dev->class_dev, + "channel scanning order specified in chanlist is not supported by hardware\n"); + return -EINVAL; } break; case MODE_MULT_CHAN_UP: - if (CR_CHAN(cmd->chanlist[i]) != i) { - comedi_error(dev, - "channel scanning order specified in chanlist is not supported by hardware.\n"); - return 1; + if (chan != i) { + dev_dbg(dev->class_dev, + "channel scanning order specified in chanlist is not supported by hardware\n"); + return -EINVAL; } break; case MODE_MULT_CHAN_DOWN: - if (CR_CHAN(cmd->chanlist[i]) != - cmd->chanlist_len - i - 1) { - comedi_error(dev, - "channel scanning order specified in chanlist is not supported by hardware.\n"); - return 1; + if (chan != (cmd->chanlist_len - i - 1)) { + dev_dbg(dev->class_dev, + "channel scanning order specified in chanlist is not supported by hardware\n"); + return -EINVAL; } break; - default: - dev_err(dev->class_dev, - "ni_labpc: bug! in chanlist check\n"); - return 1; - break; } - if (CR_RANGE(cmd->chanlist[i]) != range) { - comedi_error(dev, - "entries in chanlist must all have the same range\n"); - return 1; + if (range != range0) { + dev_dbg(dev->class_dev, + "entries in chanlist must all have the same range\n"); + return -EINVAL; } - if (CR_AREF(cmd->chanlist[i]) != aref) { - comedi_error(dev, - "entries in chanlist must all have the same reference\n"); - return 1; + if (aref != aref0) { + dev_dbg(dev->class_dev, + "entries in chanlist must all have the same reference\n"); + return -EINVAL; } } @@ -661,8 +654,14 @@ static int labpc_ai_cmdtest(struct comedi_device *dev, /* Step 3: check if arguments are trivially valid */ - if (cmd->start_arg == TRIG_NOW) + switch (cmd->start_src) { + case TRIG_NOW: err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); + break; + case TRIG_EXT: + /* start_arg value is ignored */ + break; + } if (!cmd->chanlist_len) err |= -EINVAL; @@ -711,7 +710,11 @@ static int labpc_ai_cmdtest(struct comedi_device *dev, if (err) return 4; - if (labpc_ai_chanlist_invalid(dev, cmd, mode)) + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= labpc_ai_check_chanlist(dev, s, cmd); + + if (err) return 5; return 0; @@ -732,7 +735,6 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) unsigned int aref = CR_AREF(chanspec); enum transfer_type xfer; unsigned long flags; - int ret; /* make sure board is disabled before setting up acquisition */ labpc_cancel(dev, s); @@ -747,17 +749,12 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * load counter a1 with count of 3 * (pc+ manual says this is minimum allowed) using mode 0 */ - ret = labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG, - 1, 3, I8254_MODE0); + labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG, + 1, 3, I8254_MODE0); } else { /* just put counter a1 in mode 0 to set its output low */ - ret = labpc_counter_set_mode(dev, - dev->iobase + COUNTER_A_BASE_REG, - 1, I8254_MODE0); - } - if (ret) { - comedi_error(dev, "error loading counter a1"); - return ret; + labpc_counter_set_mode(dev, dev->iobase + COUNTER_A_BASE_REG, + 1, I8254_MODE0); } /* figure out what method we will use to transfer data */ @@ -802,38 +799,25 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* set up pacing */ labpc_adc_timing(dev, cmd, mode); /* load counter b0 in mode 3 */ - ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG, - 0, devpriv->divisor_b0, I8254_MODE3); - if (ret < 0) { - comedi_error(dev, "error loading counter b0"); - return -1; - } + labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG, + 0, devpriv->divisor_b0, I8254_MODE3); } /* set up conversion pacing */ if (labpc_ai_convert_period(cmd, mode)) { /* load counter a0 in mode 2 */ - ret = labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG, - 0, devpriv->divisor_a0, I8254_MODE2); + labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG, + 0, devpriv->divisor_a0, I8254_MODE2); } else { /* initialize pacer counter to prevent any problems */ - ret = labpc_counter_set_mode(dev, - dev->iobase + COUNTER_A_BASE_REG, - 0, I8254_MODE2); - } - if (ret) { - comedi_error(dev, "error loading counter a0"); - return ret; + labpc_counter_set_mode(dev, dev->iobase + COUNTER_A_BASE_REG, + 0, I8254_MODE2); } /* set up scan pacing */ if (labpc_ai_scan_period(cmd, mode)) { /* load counter b1 in mode 2 */ - ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG, - 1, devpriv->divisor_b1, I8254_MODE2); - if (ret < 0) { - comedi_error(dev, "error loading counter b1"); - return -1; - } + labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG, + 1, devpriv->divisor_b1, I8254_MODE2); } labpc_clear_adc_fifo(dev); @@ -890,8 +874,9 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int labpc_drain_fifo(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; - unsigned short data; struct comedi_async *async = dev->read_subdev->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned short data; const int timeout = 10000; unsigned int i; @@ -900,7 +885,7 @@ static int labpc_drain_fifo(struct comedi_device *dev) for (i = 0; (devpriv->stat1 & STAT1_DAVAIL) && i < timeout; i++) { /* quit if we have all the data we want */ - if (async->cmd.stop_src == TRIG_COUNT) { + if (cmd->stop_src == TRIG_COUNT) { if (devpriv->count == 0) break; devpriv->count--; diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index 2149596830af..d9f25fdbb728 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -87,6 +87,7 @@ void labpc_drain_dma(struct comedi_device *dev) struct labpc_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; int status; unsigned long flags; unsigned int max_points, num_points, residue, leftover; @@ -108,12 +109,12 @@ void labpc_drain_dma(struct comedi_device *dev) */ residue = get_dma_residue(devpriv->dma_chan) / sample_size; num_points = max_points - residue; - if (devpriv->count < num_points && async->cmd.stop_src == TRIG_COUNT) + if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_points) num_points = devpriv->count; /* figure out how many points will be stored next time */ leftover = 0; - if (async->cmd.stop_src != TRIG_COUNT) { + if (cmd->stop_src != TRIG_COUNT) { leftover = devpriv->dma_transfer_size / sample_size; } else if (devpriv->count > num_points) { leftover = devpriv->count - num_points; @@ -125,7 +126,7 @@ void labpc_drain_dma(struct comedi_device *dev) for (i = 0; i < num_points; i++) cfc_write_to_buffer(s, devpriv->dma_buffer[i]); - if (async->cmd.stop_src == TRIG_COUNT) + if (cmd->stop_src == TRIG_COUNT) devpriv->count -= num_points; /* set address and count for next transfer */ diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 8a0e3b7236ad..7ffdcc07ef92 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -864,7 +864,7 @@ static void ni_sync_ai_dma(struct comedi_device *dev) spin_lock_irqsave(&devpriv->mite_channel_lock, flags); if (devpriv->ai_mite_chan) - mite_sync_input_dma(devpriv->ai_mite_chan, s->async); + mite_sync_input_dma(devpriv->ai_mite_chan, s); spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); } @@ -877,7 +877,7 @@ static void mite_handle_b_linkc(struct mite_struct *mite, spin_lock_irqsave(&devpriv->mite_channel_lock, flags); if (devpriv->ao_mite_chan) - mite_sync_output_dma(devpriv->ao_mite_chan, s->async); + mite_sync_output_dma(devpriv->ao_mite_chan, s); spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); } @@ -1149,7 +1149,7 @@ static void ni_ao_fifo_load(struct comedi_device *dev, chan = async->cur_chan; for (i = 0; i < n; i++) { - err &= comedi_buf_get(async, &d); + err &= comedi_buf_get(s, &d); if (err == 0) break; @@ -1159,7 +1159,7 @@ static void ni_ao_fifo_load(struct comedi_device *dev, packed_data = d & 0xffff; /* 6711 only has 16 bit wide ao fifo */ if (board->reg_type != ni_reg_6711) { - err &= comedi_buf_get(async, &d); + err &= comedi_buf_get(s, &d); if (err == 0) break; chan++; @@ -1200,7 +1200,7 @@ static int ni_ao_fifo_half_empty(struct comedi_device *dev, const struct ni_board_struct *board = comedi_board(dev); int n; - n = comedi_buf_read_n_available(s->async); + n = comedi_buf_read_n_available(s); if (n == 0) { s->async->events |= COMEDI_CB_OVERFLOW; return 0; @@ -1230,7 +1230,7 @@ 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->async); + n = comedi_buf_read_n_available(s); if (n == 0) return 0; @@ -1468,10 +1468,11 @@ 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; - unsigned int i; + struct comedi_cmd *cmd = &async->cmd; unsigned int length = num_bytes / bytes_per_sample(s); unsigned short *array = data; unsigned int *larray = data; + unsigned int i; for (i = 0; i < length; i++) { #ifdef PCIDMA @@ -1485,7 +1486,7 @@ static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s, else array[i] += devpriv->ai_offset[chan_index]; chan_index++; - chan_index %= async->cmd.chanlist_len; + chan_index %= cmd->chanlist_len; } } @@ -1505,7 +1506,7 @@ static int ni_ai_setup_MITE_dma(struct comedi_device *dev) /* printk("comedi_debug: using mite channel %i for ai.\n", devpriv->ai_mite_chan->channel); */ /* write alloc the entire buffer */ - comedi_buf_write_alloc(s->async, s->async->prealloc_bufsz); + comedi_buf_write_alloc(s, s->async->prealloc_bufsz); spin_lock_irqsave(&devpriv->mite_channel_lock, flags); if (devpriv->ai_mite_chan == NULL) { @@ -1545,7 +1546,7 @@ static int ni_ao_setup_MITE_dma(struct comedi_device *dev) return retval; /* read alloc the entire buffer */ - comedi_buf_read_alloc(s->async, s->async->prealloc_bufsz); + comedi_buf_read_alloc(s, s->async->prealloc_bufsz); spin_lock_irqsave(&devpriv->mite_channel_lock, flags); if (devpriv->ao_mite_chan) { @@ -2080,7 +2081,7 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; int err = 0; - int tmp; + unsigned int tmp; unsigned int sources; /* Step 1 : check if triggers are trivially valid */ @@ -2119,17 +2120,19 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, /* Step 3: check if arguments are trivially valid */ - if (cmd->start_src == TRIG_EXT) { - /* external trigger */ - unsigned int tmp = CR_CHAN(cmd->start_arg); + switch (cmd->start_src) { + case TRIG_NOW: + case TRIG_INT: + err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); + break; + case TRIG_EXT: + tmp = CR_CHAN(cmd->start_arg); if (tmp > 16) tmp = 16; tmp |= (cmd->start_arg & (CR_INVERT | CR_EDGE)); err |= cfc_check_trigger_arg_is(&cmd->start_arg, tmp); - } else { - /* true for both TRIG_NOW and TRIG_INT */ - err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); + break; } if (cmd->scan_begin_src == TRIG_TIMER) { @@ -2510,30 +2513,28 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } #endif - switch (cmd->start_src) { - case TRIG_NOW: + if (cmd->start_src == TRIG_NOW) { /* AI_START1_Pulse */ devpriv->stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2, AI_Command_2_Register); s->async->inttrig = NULL; - break; - case TRIG_EXT: + } else if (cmd->start_src == TRIG_EXT) { s->async->inttrig = NULL; - break; - case TRIG_INT: - s->async->inttrig = &ni_ai_inttrig; - break; + } else { /* TRIG_INT */ + s->async->inttrig = ni_ai_inttrig; } return 0; } -static int ni_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int trignum) +static int ni_ai_inttrig(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int trig_num) { struct ni_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; - if (trignum != 0) + if (trig_num != cmd->start_arg) return -EINVAL; devpriv->stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2, @@ -2710,22 +2711,22 @@ static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, { const struct ni_board_struct *board = comedi_board(dev); struct comedi_async *async = s->async; - unsigned int range; - unsigned int i; - unsigned int offset; + struct comedi_cmd *cmd = &async->cmd; unsigned int length = num_bytes / sizeof(short); + unsigned int offset = 1 << (board->aobits - 1); unsigned short *array = data; + unsigned int range; + unsigned int i; - offset = 1 << (board->aobits - 1); for (i = 0; i < length; i++) { - range = CR_RANGE(async->cmd.chanlist[chan_index]); + range = CR_RANGE(cmd->chanlist[chan_index]); if (board->ao_unipolar == 0 || (range & 1) == 0) array[i] -= offset; #ifdef PCIDMA array[i] = cpu_to_le16(array[i]); #endif chan_index++; - chan_index %= async->cmd.chanlist_len; + chan_index %= cmd->chanlist_len; } } @@ -2946,17 +2947,19 @@ static int ni_ao_insn_config(struct comedi_device *dev, return -EINVAL; } -static int ni_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int trignum) +static int ni_ao_inttrig(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int trig_num) { const struct ni_board_struct *board __maybe_unused = comedi_board(dev); struct ni_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; int ret; int interrupt_b_bits; int i; static const int timeout = 1000; - if (trignum != 0) + if (trig_num != cmd->start_arg) return -EINVAL; /* Null trig at beginning prevent ao start trigger from executing more than @@ -3217,7 +3220,7 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) AO_BC_TC_Interrupt_Enable, 1); } - s->async->inttrig = &ni_ao_inttrig; + s->async->inttrig = ni_ao_inttrig; return 0; } @@ -3228,7 +3231,7 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; int err = 0; - int tmp; + unsigned int tmp; /* Step 1 : check if triggers are trivially valid */ @@ -3258,17 +3261,18 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, /* Step 3: check if arguments are trivially valid */ - if (cmd->start_src == TRIG_EXT) { - /* external trigger */ - unsigned int tmp = CR_CHAN(cmd->start_arg); + switch (cmd->start_src) { + case TRIG_INT: + err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); + break; + case TRIG_EXT: + tmp = CR_CHAN(cmd->start_arg); if (tmp > 18) tmp = 18; tmp |= (cmd->start_arg & (CR_INVERT | CR_EDGE)); err |= cfc_check_trigger_arg_is(&cmd->start_arg, tmp); - } else { - /* true for both TRIG_NOW and TRIG_INT */ - err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); + break; } if (cmd->scan_begin_src == TRIG_TIMER) { @@ -3304,11 +3308,6 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, if (err) return 4; - /* step 5: fix up chanlist */ - - if (err) - return 5; - return 0; } @@ -3439,12 +3438,27 @@ static int ni_m_series_dio_insn_bits(struct comedi_device *dev, return insn->n; } +static int ni_cdio_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + int i; + + for (i = 0; i < cmd->chanlist_len; ++i) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); + + if (chan != i) + return -EINVAL; + } + + return 0; +} + static int ni_cdio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0; int tmp; - unsigned i; /* Step 1 : check if triggers are trivially valid */ @@ -3484,12 +3498,9 @@ static int ni_cdio_cmdtest(struct comedi_device *dev, if (err) return 4; - /* step 5: check chanlist */ - - for (i = 0; i < cmd->chanlist_len; ++i) { - if (cmd->chanlist[i] != i) - err = 1; - } + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= ni_cdio_check_chanlist(dev, s, cmd); if (err) return 5; @@ -3530,25 +3541,32 @@ static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) retval = ni_request_cdo_mite_channel(dev); if (retval < 0) return retval; - s->async->inttrig = &ni_cdo_inttrig; + + s->async->inttrig = ni_cdo_inttrig; + return 0; } -static int ni_cdo_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int trignum) +static int ni_cdo_inttrig(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int trig_num) { #ifdef PCIDMA struct ni_private *devpriv = dev->private; unsigned long flags; #endif + struct comedi_cmd *cmd = &s->async->cmd; int retval = 0; unsigned i; const unsigned timeout = 1000; + if (trig_num != cmd->start_arg) + return -EINVAL; + s->async->inttrig = NULL; /* read alloc the entire buffer */ - comedi_buf_read_alloc(s->async, s->async->prealloc_bufsz); + comedi_buf_read_alloc(s, s->async->prealloc_bufsz); #ifdef PCIDMA spin_lock_irqsave(&devpriv->mite_channel_lock, flags); @@ -3623,7 +3641,7 @@ static void handle_cdio_interrupt(struct comedi_device *dev) devpriv->mite->mite_io_addr + MITE_CHOR(devpriv->cdo_mite_chan->channel)); } - mite_sync_output_dma(devpriv->cdo_mite_chan, s->async); + mite_sync_output_dma(devpriv->cdo_mite_chan, s); } spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); #endif diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 85ac2d964f5c..5fc74d6ff6af 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -359,7 +359,7 @@ static int ni_pcidio_poll(struct comedi_device *dev, struct comedi_subdevice *s) spin_lock_irqsave(&dev->spinlock, irq_flags); spin_lock(&devpriv->mite_channel_lock); if (devpriv->di_mite_chan) - mite_sync_input_dma(devpriv->di_mite_chan, s->async); + mite_sync_input_dma(devpriv->di_mite_chan, s); spin_unlock(&devpriv->mite_channel_lock); count = s->async->buf_write_count - s->async->buf_read_count; spin_unlock_irqrestore(&dev->spinlock, irq_flags); @@ -405,7 +405,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d) writel(CHOR_CLRLC, mite->mite_io_addr + MITE_CHOR(devpriv->di_mite_chan->channel)); - mite_sync_input_dma(devpriv->di_mite_chan, s->async); + mite_sync_input_dma(devpriv->di_mite_chan, s); /* XXX need to byteswap */ } if (m_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_DRDY | @@ -447,8 +447,8 @@ static irqreturn_t nidio_interrupt(int irq, void *d) Group_1_FIFO); data1 = auxdata & 0xffff; data2 = (auxdata & 0xffff0000) >> 16; - comedi_buf_put(async, data1); - comedi_buf_put(async, data2); + comedi_buf_put(s, data1); + comedi_buf_put(s, data2); flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags); } @@ -536,7 +536,7 @@ static int ni_pcidio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0; - int tmp; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -595,11 +595,9 @@ static int ni_pcidio_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ if (cmd->scan_begin_src == TRIG_TIMER) { - tmp = cmd->scan_begin_arg; - ni_pcidio_ns_to_timer(&cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); - if (tmp != cmd->scan_begin_arg) - err++; + arg = cmd->scan_begin_arg; + ni_pcidio_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (err) @@ -759,7 +757,7 @@ static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s) return retval; /* write alloc the entire buffer */ - comedi_buf_write_alloc(s->async, s->async->prealloc_bufsz); + comedi_buf_write_alloc(s, s->async->prealloc_bufsz); spin_lock_irqsave(&devpriv->mite_channel_lock, flags); if (devpriv->di_mite_chan) { @@ -773,11 +771,13 @@ static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s) } static int ni_pcidio_inttrig(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned int trignum) + struct comedi_subdevice *s, + unsigned int trig_num) { struct nidio96_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; - if (trignum != 0) + if (trig_num != cmd->start_arg) return -EINVAL; writeb(devpriv->OpModeBits, devpriv->mite->daq_io_addr + OpMode); @@ -804,7 +804,7 @@ static int ni_pcidio_change(struct comedi_device *dev, struct nidio96_private *devpriv = dev->private; int ret; - ret = mite_buf_change(devpriv->di_mite_ring, s->async); + ret = mite_buf_change(devpriv->di_mite_ring, s); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index d40df072583c..89300dc78e35 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -1560,7 +1560,7 @@ static int pcimio_ai_change(struct comedi_device *dev, struct ni_private *devpriv = dev->private; int ret; - ret = mite_buf_change(devpriv->ai_mite_ring, s->async); + ret = mite_buf_change(devpriv->ai_mite_ring, s); if (ret < 0) return ret; @@ -1573,7 +1573,7 @@ static int pcimio_ao_change(struct comedi_device *dev, struct ni_private *devpriv = dev->private; int ret; - ret = mite_buf_change(devpriv->ao_mite_ring, s->async); + ret = mite_buf_change(devpriv->ao_mite_ring, s); if (ret < 0) return ret; @@ -1587,7 +1587,7 @@ static int pcimio_gpct0_change(struct comedi_device *dev, struct ni_private *devpriv = dev->private; int ret; - ret = mite_buf_change(devpriv->gpct_mite_ring[0], s->async); + ret = mite_buf_change(devpriv->gpct_mite_ring[0], s); if (ret < 0) return ret; @@ -1601,7 +1601,7 @@ static int pcimio_gpct1_change(struct comedi_device *dev, struct ni_private *devpriv = dev->private; int ret; - ret = mite_buf_change(devpriv->gpct_mite_ring[1], s->async); + ret = mite_buf_change(devpriv->gpct_mite_ring[1], s); if (ret < 0) return ret; @@ -1614,7 +1614,7 @@ static int pcimio_dio_change(struct comedi_device *dev, struct ni_private *devpriv = dev->private; int ret; - ret = mite_buf_change(devpriv->cdo_mite_ring, s->async); + ret = mite_buf_change(devpriv->cdo_mite_ring, s); if (ret < 0) return ret; diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c index 7d64f8892f08..2557ab48cb6c 100644 --- a/drivers/staging/comedi/drivers/ni_tiocmd.c +++ b/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -89,14 +89,16 @@ static void ni_tio_configure_dma(struct ni_gpct *counter, short enable, static int ni_tio_input_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int trignum) + unsigned int trig_num) { + struct ni_gpct *counter = s->private; + struct comedi_cmd *cmd = &s->async->cmd; unsigned long flags; int retval = 0; - struct ni_gpct *counter = s->private; BUG_ON(counter == NULL); - if (trignum != 0) + + if (trig_num != cmd->start_src) return -EINVAL; spin_lock_irqsave(&counter->lock, flags); @@ -113,15 +115,17 @@ static int ni_tio_input_inttrig(struct comedi_device *dev, return retval; } -static int ni_tio_input_cmd(struct ni_gpct *counter, struct comedi_async *async) +static int ni_tio_input_cmd(struct comedi_subdevice *s) { + struct ni_gpct *counter = s->private; struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned cidx = counter->counter_index; + struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; int retval = 0; /* write alloc the entire buffer */ - comedi_buf_write_alloc(async, async->prealloc_bufsz); + comedi_buf_write_alloc(s, async->prealloc_bufsz); counter->mite_chan->dir = COMEDI_INPUT; switch (counter_dev->variant) { case ni_gpct_variant_m_series: @@ -162,9 +166,10 @@ static int ni_tio_input_cmd(struct ni_gpct *counter, struct comedi_async *async) return retval; } -static int ni_tio_output_cmd(struct ni_gpct *counter, - struct comedi_async *async) +static int ni_tio_output_cmd(struct comedi_subdevice *s) { + struct ni_gpct *counter = s->private; + dev_err(counter->counter_dev->dev->class_dev, "output commands not yet implemented.\n"); return -ENOTSUPP; @@ -176,9 +181,10 @@ static int ni_tio_output_cmd(struct ni_gpct *counter, return ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE); } -static int ni_tio_cmd_setup(struct ni_gpct *counter, struct comedi_async *async) +static int ni_tio_cmd_setup(struct comedi_subdevice *s) { - struct comedi_cmd *cmd = &async->cmd; + struct comedi_cmd *cmd = &s->async->cmd; + struct ni_gpct *counter = s->private; unsigned cidx = counter->counter_index; int set_gate_source = 0; unsigned gate_source; @@ -217,12 +223,12 @@ int ni_tio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) "Interrupt-driven commands not yet implemented.\n"); retval = -EIO; } else { - retval = ni_tio_cmd_setup(counter, async); + retval = ni_tio_cmd_setup(s); if (retval == 0) { if (cmd->flags & CMDF_WRITE) - retval = ni_tio_output_cmd(counter, async); + retval = ni_tio_output_cmd(s); else - retval = ni_tio_input_cmd(counter, async); + retval = ni_tio_input_cmd(s); } } spin_unlock_irqrestore(&counter->lock, flags); @@ -271,8 +277,16 @@ int ni_tio_cmdtest(struct comedi_device *dev, /* Step 3: check if arguments are trivially valid */ - if (cmd->start_src != TRIG_EXT) + switch (cmd->start_src) { + case TRIG_NOW: + case TRIG_INT: + case TRIG_OTHER: err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); + break; + case TRIG_EXT: + /* start_arg is the start_trigger passed to ni_tio_arm() */ + break; + } if (cmd->scan_begin_src != TRIG_EXT) err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); @@ -450,7 +464,7 @@ void ni_tio_handle_interrupt(struct ni_gpct *counter, counter->mite_chan->mite->mite_io_addr + MITE_CHOR(counter->mite_chan->channel)); } - mite_sync_input_dma(counter->mite_chan, s->async); + mite_sync_input_dma(counter->mite_chan, s); spin_unlock_irqrestore(&counter->lock, flags); } EXPORT_SYMBOL_GPL(ni_tio_handle_interrupt); diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index 7c03a5d17b1b..c38d97a9a899 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -202,6 +202,7 @@ 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; if (!dev->attached) { @@ -213,12 +214,11 @@ 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->async, data) == 0) { + 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 (s->async->cmd.stop_src == TRIG_COUNT && - !(--devpriv->ntrig)) { + if (cmd->stop_src == TRIG_COUNT && !(--devpriv->ntrig)) { pcl711_ai_set_mode(dev, PCL711_MODE_SOFTTRIG); s->async->events |= COMEDI_CB_EOA; } @@ -295,8 +295,8 @@ static int pcl711_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { struct pcl711_private *devpriv = dev->private; - int tmp; int err = 0; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -344,14 +344,12 @@ static int pcl711_ai_cmdtest(struct comedi_device *dev, /* step 4 */ if (cmd->scan_begin_src == TRIG_TIMER) { - tmp = cmd->scan_begin_arg; + arg = cmd->scan_begin_arg; i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ, &devpriv->divisor1, &devpriv->divisor2, - &cmd->scan_begin_arg, - cmd->flags); - if (tmp != cmd->scan_begin_arg) - err++; + &arg, cmd->flags); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (err) @@ -360,6 +358,18 @@ static int pcl711_ai_cmdtest(struct comedi_device *dev, return 0; } +static void pcl711_ai_load_counters(struct comedi_device *dev) +{ + struct pcl711_private *devpriv = dev->private; + unsigned long timer_base = dev->iobase + PCL711_TIMER_BASE; + + i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY); + i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY); + + i8254_write(timer_base, 0, 1, devpriv->divisor1); + i8254_write(timer_base, 0, 2, devpriv->divisor2); +} + static int pcl711_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl711_private *devpriv = dev->private; @@ -378,13 +388,8 @@ static int pcl711_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } if (cmd->scan_begin_src == TRIG_TIMER) { - i8254_load(dev->iobase + PCL711_TIMER_BASE, 0, - 1, devpriv->divisor1, I8254_MODE2 | I8254_BINARY); - i8254_load(dev->iobase + PCL711_TIMER_BASE, 0, - 2, devpriv->divisor2, I8254_MODE2 | I8254_BINARY); - + pcl711_ai_load_counters(dev); outb(PCL711_INT_STAT_CLR, dev->iobase + PCL711_INT_STAT_REG); - pcl711_ai_set_mode(dev, PCL711_MODE_PACER_IRQ); } else { pcl711_ai_set_mode(dev, PCL711_MODE_EXT_IRQ); diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index cf9568ee46e4..74f6489bd124 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -197,7 +197,7 @@ static int pcl726_intr_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); - err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, 1); + err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); if (err) @@ -240,7 +240,7 @@ static irqreturn_t pcl726_interrupt(int irq, void *d) if (devpriv->cmd_running) { pcl726_intr_cancel(dev, s); - comedi_buf_put(s->async, 0); + comedi_buf_put(s, 0); s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS); comedi_event(dev, s); } @@ -430,6 +430,7 @@ static int pcl726_attach(struct comedi_device *dev, s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = pcl726_intr_insn_bits; + s->len_chanlist = 1; s->do_cmdtest = pcl726_intr_cmdtest; s->do_cmd = pcl726_intr_cmd; s->cancel = pcl726_intr_cancel; diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c index 2baaf1db6fbf..7fb044ce399b 100644 --- a/drivers/staging/comedi/drivers/pcl730.c +++ b/drivers/staging/comedi/drivers/pcl730.c @@ -17,6 +17,8 @@ * (ICP) P16R16-DIO [p16r16dio] * (Advantech) PCL-733 [pcl733] * (Advantech) PCL-734 [pcl734] + * (Diamond Systems) OPMM-1616-XT [opmm-1616-xt] + * (Diamond Systems) PEARL-MM-P [prearl-mm-p] * Author: José Luis Sánchez (jsanchezv@teleline.es) * Status: untested * @@ -70,6 +72,27 @@ * BASE+1 Isolated outputs 8-15 (write) or inputs 8-15 (read) * BASE+2 Isolated outputs 16-23 (write) or inputs 16-23 (read) * BASE+3 Isolated outputs 24-31 (write) or inputs 24-31 (read) + * + * The opmm-1616-xt board has this register mapping: + * + * BASE+0 Isolated outputs 0-7 (write) (read back) + * BASE+1 Isolated outputs 8-15 (write) (read back) + * BASE+2 Isolated inputs 0-7 (read) + * BASE+3 Isolated inputs 8-15 (read) + * + * These registers are not currently supported: + * + * BASE+2 Relay select register (write) + * BASE+3 Board reset control register (write) + * BASE+4 Interrupt control register (write) + * BASE+4 Change detect 7-0 status register (read) + * BASE+5 LED control register (write) + * BASE+5 Change detect 15-8 status register (read) + * + * The pearl-mm-p board has this register mapping: + * + * BASE+0 Isolated outputs 0-7 (write) + * BASE+1 Isolated outputs 8-15 (write) */ struct pcl730_board { @@ -158,6 +181,19 @@ static const struct pcl730_board pcl730_boards[] = { .io_range = 0x04, .n_subdevs = 1, .n_iso_out_chan = 32, + }, { + .name = "opmm-1616-xt", + .io_range = 0x10, + .is_acl7225b = 1, + .has_readback = 1, + .n_subdevs = 2, + .n_iso_out_chan = 16, + .n_iso_in_chan = 16, + }, { + .name = "pearl-mm-p", + .io_range = 0x02, + .n_subdevs = 1, + .n_iso_out_chan = 16, }, }; diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 160eac8083db..4c1b94706478 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -557,10 +557,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] = - cmd->chanlist_len * sizeof(short); - devpriv->dmabytestomove[1] = - cmd->chanlist_len * sizeof(short); + devpriv->dmabytestomove[0] = cfc_bytes_per_scan(s); + devpriv->dmabytestomove[1] = cfc_bytes_per_scan(s); devpriv->dma_runs_to_end = 1; } else { devpriv->dmabytestomove[0] = devpriv->hwdmasize; @@ -575,8 +573,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->chanlist_len * - cmd->stop_arg * sizeof(short); + bytes = cmd->stop_arg * cfc_bytes_per_scan(s); /* how many DMA pages we must fill */ devpriv->dma_runs_to_end = @@ -721,7 +718,7 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev, struct pcl812_private *devpriv = dev->private; int err = 0; unsigned int flags; - int tmp; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -761,7 +758,6 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1); - err |= cfc_check_trigger_arg_max(&cmd->chanlist_len, MAX_CHANLIST_LEN); err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); if (cmd->stop_src == TRIG_COUNT) @@ -775,15 +771,12 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ if (cmd->convert_src == TRIG_TIMER) { - tmp = cmd->convert_arg; + arg = cmd->convert_arg; i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ, &devpriv->divisor1, &devpriv->divisor2, - &cmd->convert_arg, cmd->flags); - if (cmd->convert_arg < board->ai_ns_min) - cmd->convert_arg = board->ai_ns_min; - if (tmp != cmd->convert_arg) - err++; + &arg, cmd->flags); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); } if (err) @@ -811,8 +804,9 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_dma = 0; break; } - } else + } else { devpriv->ai_dma = 0; + } devpriv->ai_act_scan = 0; devpriv->ai_poll_ptr = 0; @@ -882,7 +876,7 @@ static void pcl812_handle_eoc(struct comedi_device *dev, return; } - comedi_buf_put(s->async, pcl812_ai_get_sample(dev, s)); + comedi_buf_put(s, pcl812_ai_get_sample(dev, s)); /* Set up next channel. Added by abbotti 2010-01-20, but untested. */ next_chan = s->async->cur_chan + 1; @@ -902,7 +896,7 @@ static void transfer_from_dma_buf(struct comedi_device *dev, unsigned int i; for (i = len; i; i--) { - comedi_buf_put(s->async, ptr[bufptr++]); + comedi_buf_put(s, ptr[bufptr++]); if (!pcl812_ai_next_chan(dev, s)) break; diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 6f276f23fabe..d9ca7fe16c96 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -164,9 +164,7 @@ static void pcl816_ai_setup_dma(struct comedi_device *dev, bytes = devpriv->hwdmasize; if (cmd->stop_src == TRIG_COUNT) { /* how many */ - bytes = s->async->cmd.chanlist_len * - s->async->cmd.chanlist_len * - sizeof(short); + bytes = cmd->stop_arg * cfc_bytes_per_scan(s); /* how many DMA pages we must fill */ devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize; @@ -322,7 +320,7 @@ static void transfer_from_dma_buf(struct comedi_device *dev, int i; for (i = 0; i < len; i++) { - comedi_buf_put(s->async, ptr[bufptr++]); + comedi_buf_put(s, ptr[bufptr++]); if (!pcl816_ai_next_chan(dev, s)) return; @@ -370,7 +368,7 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev, { struct pcl816_private *devpriv = dev->private; int err = 0; - int tmp; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -417,15 +415,12 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ if (cmd->convert_src == TRIG_TIMER) { - tmp = cmd->convert_arg; + arg = cmd->convert_arg; i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, &devpriv->divisor1, &devpriv->divisor2, - &cmd->convert_arg, cmd->flags); - if (cmd->convert_arg < 10000) - cmd->convert_arg = 10000; - if (tmp != cmd->convert_arg) - err++; + &arg, cmd->flags); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); } if (err) diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 6463476ce45a..7d00ae639d38 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -353,7 +353,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->chanlist_len * cmd->stop_arg * sizeof(short); + bytes = cmd->stop_arg * cfc_bytes_per_scan(s); devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize; devpriv->last_dma_run = bytes % devpriv->hwdmasize; devpriv->dma_runs_to_end--; @@ -561,7 +561,7 @@ static void pcl818_handle_eoc(struct comedi_device *dev, if (pcl818_ai_dropout(dev, s, chan)) return; - comedi_buf_put(s->async, val); + comedi_buf_put(s, val); pcl818_ai_next_chan(dev, s); } @@ -590,7 +590,7 @@ static void pcl818_handle_dma(struct comedi_device *dev, if (pcl818_ai_dropout(dev, s, chan)) break; - comedi_buf_put(s->async, val); + comedi_buf_put(s, val); if (!pcl818_ai_next_chan(dev, s)) break; @@ -630,7 +630,7 @@ static void pcl818_handle_fifo(struct comedi_device *dev, if (pcl818_ai_dropout(dev, s, chan)) break; - comedi_buf_put(s->async, val); + comedi_buf_put(s, val); if (!pcl818_ai_next_chan(dev, s)) break; @@ -741,7 +741,7 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, const struct pcl818_board *board = comedi_board(dev); struct pcl818_private *devpriv = dev->private; int err = 0; - int tmp; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -788,15 +788,12 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, /* step 4: fix up any arguments */ if (cmd->convert_src == TRIG_TIMER) { - tmp = cmd->convert_arg; + arg = cmd->convert_arg; i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &devpriv->divisor1, &devpriv->divisor2, - &cmd->convert_arg, cmd->flags); - if (cmd->convert_arg < board->ns_min) - cmd->convert_arg = board->ns_min; - if (tmp != cmd->convert_arg) - err++; + &arg, cmd->flags); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); } if (err) diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index e89bca845349..fed7e77e0305 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -192,7 +192,6 @@ struct pcmmio_private { unsigned int enabled_mask; unsigned int stop_count; unsigned int active:1; - unsigned int continuous:1; unsigned int ao_readback[8]; }; @@ -339,8 +338,8 @@ static void pcmmio_handle_dio_intr(struct comedi_device *dev, unsigned int triggered) { struct pcmmio_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; unsigned int oldevents = s->async->events; - unsigned int len = s->async->cmd.chanlist_len; unsigned int val = 0; unsigned long flags; int i; @@ -353,16 +352,16 @@ static void pcmmio_handle_dio_intr(struct comedi_device *dev, if (!(triggered & devpriv->enabled_mask)) goto done; - for (i = 0; i < len; i++) { - unsigned int chan = CR_CHAN(s->async->cmd.chanlist[i]); + for (i = 0; i < cmd->chanlist_len; i++) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); if (triggered & (1 << chan)) val |= (1 << i); } /* Write the scan to the buffer. */ - if (comedi_buf_put(s->async, val) && - comedi_buf_put(s->async, val >> 16)) { + 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!! */ @@ -371,15 +370,12 @@ static void pcmmio_handle_dio_intr(struct comedi_device *dev, } /* Check for end of acquisition. */ - if (!devpriv->continuous) { - /* stop_src == TRIG_COUNT */ - if (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 && 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); } } @@ -421,7 +417,7 @@ static int pcmmio_start_intr(struct comedi_device *dev, unsigned int pol_bits = 0; int i; - if (!devpriv->continuous && devpriv->stop_count == 0) { + if (cmd->stop_src == TRIG_COUNT && devpriv->stop_count == 0) { /* An empty acquisition! */ s->async->events |= COMEDI_CB_EOA; devpriv->active = 0; @@ -464,18 +460,16 @@ static int pcmmio_cancel(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } -/* - * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice. - */ -static int -pcmmio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int trignum) +static int pcmmio_inttrig_start_intr(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int trig_num) { struct pcmmio_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; unsigned long flags; int event = 0; - if (trignum != 0) + if (trig_num != cmd->start_arg) return -EINVAL; spin_lock_irqsave(&devpriv->spinlock, flags); @@ -504,28 +498,17 @@ static int pcmmio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->active = 1; /* Set up end of acquisition. */ - switch (cmd->stop_src) { - case TRIG_COUNT: - devpriv->continuous = 0; + if (cmd->stop_src == TRIG_COUNT) devpriv->stop_count = cmd->stop_arg; - break; - default: - /* TRIG_NONE */ - devpriv->continuous = 1; + else /* TRIG_NONE */ devpriv->stop_count = 0; - break; - } /* Set up start of acquisition. */ - switch (cmd->start_src) { - case TRIG_INT: + if (cmd->start_src == TRIG_INT) s->async->inttrig = pcmmio_inttrig_start_intr; - break; - default: - /* TRIG_NOW */ + else /* TRIG_NOW */ event = pcmmio_start_intr(dev, s); - break; - } + spin_unlock_irqrestore(&devpriv->spinlock, flags); if (event) diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index a8f390f7a874..62914bb342d2 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -317,7 +317,7 @@ static void pcmuio_handle_intr_subdev(struct comedi_device *dev, struct pcmuio_private *devpriv = dev->private; int asic = pcmuio_subdevice_to_asic(s); struct pcmuio_asic *chip = &devpriv->asics[asic]; - unsigned int len = s->async->cmd.chanlist_len; + struct comedi_cmd *cmd = &s->async->cmd; unsigned oldevents = s->async->events; unsigned int val = 0; unsigned long flags; @@ -331,15 +331,15 @@ static void pcmuio_handle_intr_subdev(struct comedi_device *dev, if (!(triggered & chip->enabled_mask)) goto done; - for (i = 0; i < len; i++) { - unsigned int chan = CR_CHAN(s->async->cmd.chanlist[i]); + for (i = 0; i < cmd->chanlist_len; i++) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); if (triggered & (1 << chan)) val |= (1 << i); } /* Write the scan to the buffer. */ - if (comedi_buf_put(s->async, val) && - comedi_buf_put(s->async, val >> 16)) { + 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!! */ @@ -460,20 +460,18 @@ static int pcmuio_cancel(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } -/* - * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice. - */ -static int -pcmuio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int trignum) +static int pcmuio_inttrig_start_intr(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int trig_num) { struct pcmuio_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; int asic = pcmuio_subdevice_to_asic(s); struct pcmuio_asic *chip = &devpriv->asics[asic]; unsigned long flags; int event = 0; - if (trignum != 0) + if (trig_num != cmd->start_arg) return -EINVAL; spin_lock_irqsave(&chip->spinlock, flags); @@ -518,15 +516,11 @@ static int pcmuio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } /* Set up start of acquisition. */ - switch (cmd->start_src) { - case TRIG_INT: + if (cmd->start_src == TRIG_INT) s->async->inttrig = pcmuio_inttrig_start_intr; - break; - default: - /* TRIG_NOW */ + else /* TRIG_NOW */ event = pcmuio_start_intr(dev, s); - break; - } + spin_unlock_irqrestore(&chip->spinlock, flags); if (event) diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index 298dba03f902..b3bbec0a0d23 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -221,7 +221,7 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id) data |= inb(dev->iobase + DAQP_FIFO) << 8; data ^= 0x8000; - comedi_buf_put(s->async, data); + comedi_buf_put(s, data); /* If there's a limit, decrement it * and stop conversion if zero @@ -373,7 +373,7 @@ static int daqp_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0; - int tmp; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -435,19 +435,15 @@ static int daqp_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ if (cmd->scan_begin_src == TRIG_TIMER) { - tmp = cmd->scan_begin_arg; - daqp_ns_to_timer(&cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); - if (tmp != cmd->scan_begin_arg) - err++; + arg = cmd->scan_begin_arg; + daqp_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (cmd->convert_src == TRIG_TIMER) { - tmp = cmd->convert_arg; - daqp_ns_to_timer(&cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); - if (tmp != cmd->convert_arg) - err++; + arg = cmd->convert_arg; + daqp_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); } if (err) diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index cd3fdf973bdd..d55c5893203b 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -629,7 +629,7 @@ static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s, d = comedi_offset_munge(s, d); d &= s->maxdata; - if (!comedi_buf_put(s->async, d)) + if (!comedi_buf_put(s, d)) return -1; if (devpriv->ai_count > 0) /* < 0, means read forever */ @@ -658,7 +658,7 @@ static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s) d = comedi_offset_munge(s, d); d &= s->maxdata; - if (!comedi_buf_put(s->async, d)) + if (!comedi_buf_put(s, d)) return -1; if (devpriv->ai_count > 0) /* < 0, means read forever */ @@ -779,7 +779,7 @@ static int rtd_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0; - int tmp; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -878,6 +878,8 @@ static int rtd_ai_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 9); } + err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); + if (cmd->stop_src == TRIG_COUNT) { /* TODO check for rounding error due to counter wrap */ } else { @@ -891,31 +893,21 @@ static int rtd_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ - if (cmd->chanlist_len > RTD_MAX_CHANLIST) { - cmd->chanlist_len = RTD_MAX_CHANLIST; - err++; - } if (cmd->scan_begin_src == TRIG_TIMER) { - tmp = cmd->scan_begin_arg; - rtd_ns_to_timer(&cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); - if (tmp != cmd->scan_begin_arg) - err++; - + arg = cmd->scan_begin_arg; + rtd_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } + if (cmd->convert_src == TRIG_TIMER) { - tmp = cmd->convert_arg; - rtd_ns_to_timer(&cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); - if (tmp != cmd->convert_arg) - err++; - - 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++; + arg = cmd->convert_arg; + rtd_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + 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); } } diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 95fadf343f27..0838f8aa6951 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -295,10 +295,24 @@ static void s626_debi_replace(struct comedi_device *dev, unsigned int addr, /* ************** EEPROM ACCESS FUNCTIONS ************** */ -static uint32_t s626_i2c_handshake(struct comedi_device *dev, uint32_t val) +static int s626_i2c_handshake_eoc(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned long context) +{ + bool status; + + status = s626_mc_test(dev, S626_MC2_UPLD_IIC, S626_P_MC2); + if (status) + return 0; + return -EBUSY; +} + +static int s626_i2c_handshake(struct comedi_device *dev, uint32_t val) { struct s626_private *devpriv = dev->private; unsigned int ctrl; + int ret; /* Write I2C command to I2C Transfer Control shadow register */ writel(val, devpriv->mmio + S626_P_I2CCTRL); @@ -308,8 +322,9 @@ static uint32_t s626_i2c_handshake(struct comedi_device *dev, uint32_t val) * wait for upload confirmation. */ s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2); - while (!s626_mc_test(dev, S626_MC2_UPLD_IIC, S626_P_MC2)) - ; + ret = comedi_timeout(dev, NULL, NULL, s626_i2c_handshake_eoc, 0); + if (ret) + return ret; /* Wait until I2C bus transfer is finished or an error occurs */ do { @@ -1613,7 +1628,6 @@ static bool s626_handle_eos_interrupt(struct comedi_device *dev) readaddr++; /* put data into read buffer */ - /* comedi_buf_put(async, tempdata); */ cfc_write_to_buffer(s, tempdata); } @@ -2029,8 +2043,9 @@ static int s626_ai_insn_read(struct comedi_device *dev, /* Wait for the data to arrive in FB BUFFER 1 register. */ /* Wait for ADC done */ - while (!(readl(devpriv->mmio + S626_P_PSR) & S626_PSR_GPIO2)) - ; + ret = comedi_timeout(dev, s, insn, s626_ai_eoc, 0); + if (ret) + return ret; /* Fetch ADC data from audio interface's input shift register. */ @@ -2060,9 +2075,12 @@ static int s626_ai_load_polllist(uint8_t *ppl, struct comedi_cmd *cmd) } static int s626_ai_inttrig(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned int trignum) + struct comedi_subdevice *s, + unsigned int trig_num) { - if (trignum != 0) + struct comedi_cmd *cmd = &s->async->cmd; + + if (trig_num != cmd->start_arg) return -EINVAL; /* Start executing the RPS program */ @@ -2080,7 +2098,7 @@ static int s626_ai_inttrig(struct comedi_device *dev, * Also, it should adjust ns so that it cooresponds to the actual time * that the device will use. */ -static int s626_ns_to_timer(int *nanosec, int round_mode) +static int s626_ns_to_timer(unsigned int *nanosec, int round_mode) { int divider, base; @@ -2188,7 +2206,7 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * interval */ k = &s626_enc_chan_info[5]; - tick = s626_ns_to_timer((int *)&cmd->scan_begin_arg, + tick = s626_ns_to_timer(&cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); /* load timer value and enable interrupt */ @@ -2211,7 +2229,7 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * interval */ k = &s626_enc_chan_info[4]; - tick = s626_ns_to_timer((int *)&cmd->convert_arg, + tick = s626_ns_to_timer(&cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); /* load timer value and enable interrupt */ @@ -2270,7 +2288,7 @@ static int s626_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0; - int tmp; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -2298,12 +2316,18 @@ static int s626_ai_cmdtest(struct comedi_device *dev, if (err) return 2; - /* step 3: make sure arguments are trivially compatible */ + /* Step 3: check if arguments are trivially valid */ - if (cmd->start_src != TRIG_EXT) + switch (cmd->start_src) { + case TRIG_NOW: + case TRIG_INT: err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); - if (cmd->start_src == TRIG_EXT) + break; + case TRIG_EXT: err |= cfc_check_trigger_arg_max(&cmd->start_arg, 39); + break; + } + if (cmd->scan_begin_src == TRIG_EXT) err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 39); if (cmd->convert_src == TRIG_EXT) @@ -2347,24 +2371,20 @@ static int s626_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ if (cmd->scan_begin_src == TRIG_TIMER) { - tmp = cmd->scan_begin_arg; - s626_ns_to_timer((int *)&cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); - if (tmp != cmd->scan_begin_arg) - err++; + arg = cmd->scan_begin_arg; + s626_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } + if (cmd->convert_src == TRIG_TIMER) { - tmp = cmd->convert_arg; - s626_ns_to_timer((int *)&cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); - if (tmp != cmd->convert_arg) - err++; - 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++; + arg = cmd->convert_arg; + s626_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + 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); } } @@ -2681,8 +2701,9 @@ static int s626_initialize(struct comedi_device *dev) writel(S626_I2C_CLKSEL | S626_I2C_ABORT, devpriv->mmio + S626_P_I2CSTAT); s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2); - while (!(readl(devpriv->mmio + S626_P_MC2) & S626_MC2_UPLD_IIC)) - ; + ret = comedi_timeout(dev, NULL, NULL, s626_i2c_handshake_eoc, 0); + if (ret) + return ret; /* * Per SAA7146 data sheet, write to STATUS @@ -2691,8 +2712,9 @@ static int s626_initialize(struct comedi_device *dev) for (i = 0; i < 2; i++) { writel(S626_I2C_CLKSEL, devpriv->mmio + S626_P_I2CSTAT); s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2); - while (!s626_mc_test(dev, S626_MC2_UPLD_IIC, S626_P_MC2)) - ; + ret = comedi_timeout(dev, NULL, NULL, s626_i2c_handshake_eoc, 0); + if (ret) + return ret; } /* diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c index 39008cf30ecb..3bfa221faf4d 100644 --- a/drivers/staging/comedi/drivers/skel.c +++ b/drivers/staging/comedi/drivers/skel.c @@ -220,7 +220,7 @@ static int skel_ai_cmdtest(struct comedi_device *dev, struct comedi_cmd *cmd) { int err = 0; - int tmp; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ @@ -286,24 +286,19 @@ static int skel_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ if (cmd->scan_begin_src == TRIG_TIMER) { - tmp = cmd->scan_begin_arg; - skel_ns_to_timer(&cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); - if (tmp != cmd->scan_begin_arg) - err++; + arg = cmd->scan_begin_arg; + skel_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (cmd->convert_src == TRIG_TIMER) { - tmp = cmd->convert_arg; - skel_ns_to_timer(&cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); - if (tmp != cmd->convert_arg) - err++; - 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++; + arg = cmd->convert_arg; + skel_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + 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); } } diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index b59af0303581..5f65e4213c6e 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -202,14 +202,11 @@ struct usbdux_private { /* input buffer for single insn */ uint16_t *insn_buf; - uint8_t ao_chanlist[USBDUX_NUM_AO_CHAN]; unsigned int ao_readback[USBDUX_NUM_AO_CHAN]; unsigned int high_speed:1; unsigned int ai_cmd_running:1; - unsigned int ai_continous:1; unsigned int ao_cmd_running:1; - unsigned int ao_continous:1; unsigned int pwm_cmd_running:1; /* number of samples to acquire */ @@ -266,7 +263,8 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) struct comedi_device *dev = urb->context; struct comedi_subdevice *s = dev->read_subdev; struct usbdux_private *devpriv = dev->private; - int i, err, n; + struct comedi_cmd *cmd = &s->async->cmd; + int i, err; /* first we test if something unusual has just happened */ switch (urb->status) { @@ -349,7 +347,7 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) devpriv->ai_counter = devpriv->ai_timer; /* test, if we transmit only a fixed number of samples */ - if (!devpriv->ai_continous) { + if (cmd->stop_src == TRIG_COUNT) { /* not continuous, fixed number of samples */ devpriv->ai_sample_count--; /* all samples received? */ @@ -363,9 +361,8 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) } } /* get the data from the USB bus and hand it over to comedi */ - n = s->async->cmd.chanlist_len; - for (i = 0; i < n; i++) { - unsigned int range = CR_RANGE(s->async->cmd.chanlist[i]); + 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 */ @@ -373,7 +370,7 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) val ^= ((s->maxdata + 1) >> 1); /* transfer data */ - err = comedi_buf_put(s->async, val); + err = comedi_buf_put(s, val); if (unlikely(err == 0)) { /* buffer overflow */ usbdux_ai_stop(dev, 0); @@ -414,8 +411,8 @@ static void usbduxsub_ao_isoc_irq(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; uint8_t *datap; - int len; int ret; int i; @@ -463,7 +460,7 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) devpriv->ao_counter = devpriv->ao_timer; /* handle non continous acquisition */ - if (!devpriv->ao_continous) { + if (cmd->stop_src == TRIG_COUNT) { /* fixed number of samples */ devpriv->ao_sample_count--; if (devpriv->ao_sample_count < 0) { @@ -478,13 +475,12 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) /* transmit data to the USB bus */ datap = urb->transfer_buffer; - len = s->async->cmd.chanlist_len; - *datap++ = len; - for (i = 0; i < s->async->cmd.chanlist_len; i++) { - unsigned int chan = devpriv->ao_chanlist[i]; + *datap++ = cmd->chanlist_len; + for (i = 0; i < cmd->chanlist_len; i++) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); unsigned short val; - ret = comedi_buf_get(s->async, &val); + ret = comedi_buf_get(s, &val); if (ret < 0) { dev_err(dev->class_dev, "buffer underflow\n"); s->async->events |= (COMEDI_CB_EOA | @@ -692,15 +688,16 @@ static int receive_dux_commands(struct comedi_device *dev, unsigned int command) static int usbdux_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int trignum) + unsigned int trig_num) { struct usbdux_private *devpriv = dev->private; - int ret = -EINVAL; + struct comedi_cmd *cmd = &s->async->cmd; + int ret; - down(&devpriv->sem); + if (trig_num != cmd->start_arg) + return -EINVAL; - if (trignum != 0) - goto ai_trig_exit; + down(&devpriv->sem); if (!devpriv->ai_cmd_running) { devpriv->ai_cmd_running = 1; @@ -777,10 +774,8 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (cmd->stop_src == TRIG_COUNT) { /* data arrives as one packet */ devpriv->ai_sample_count = cmd->stop_arg; - devpriv->ai_continous = 0; } else { /* continous acquisition */ - devpriv->ai_continous = 1; devpriv->ai_sample_count = 0; } @@ -913,15 +908,16 @@ ao_write_exit: static int usbdux_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int trignum) + unsigned int trig_num) { struct usbdux_private *devpriv = dev->private; - int ret = -EINVAL; + struct comedi_cmd *cmd = &s->async->cmd; + int ret; - down(&devpriv->sem); + if (trig_num != cmd->start_arg) + return -EINVAL; - if (trignum != 0) - goto ao_trig_exit; + down(&devpriv->sem); if (!devpriv->ao_cmd_running) { devpriv->ao_cmd_running = 1; @@ -1030,7 +1026,6 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) struct usbdux_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; int ret = -EBUSY; - int i; down(&devpriv->sem); @@ -1040,9 +1035,6 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* set current channel of the running acquisition to zero */ s->async->cur_chan = 0; - for (i = 0; i < cmd->chanlist_len; ++i) - devpriv->ao_chanlist[i] = CR_CHAN(cmd->chanlist[i]); - /* we count in steps of 1ms (125us) */ /* 125us mode not used yet */ if (0) { /* (devpriv->high_speed) */ @@ -1074,10 +1066,8 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* data arrives as one packet */ devpriv->ao_sample_count = cmd->stop_arg; } - devpriv->ao_continous = 0; } else { /* continous acquisition */ - devpriv->ao_continous = 1; devpriv->ao_sample_count = 0; } diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index d6fae11ee4e0..85f9dcf59403 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -154,7 +154,6 @@ struct usbduxfast_private { uint8_t *duxbuf; int8_t *inbuf; short int ai_cmd_running; /* asynchronous command is running */ - short int ai_continous; /* continous acquisition */ long int ai_sample_count; /* number of samples to acquire */ int ignore; /* counter which ignores the first buffers */ @@ -239,6 +238,7 @@ 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; @@ -285,7 +285,7 @@ static void usbduxfast_ai_interrupt(struct urb *urb) } if (!devpriv->ignore) { - if (!devpriv->ai_continous) { + 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)) { @@ -398,8 +398,7 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev, /* Step 3: check if arguments are trivially valid */ - if (cmd->start_src == TRIG_NOW) - err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); if (!cmd->chanlist_len) err |= -EINVAL; @@ -451,21 +450,20 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev, static int usbduxfast_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int trignum) + unsigned int trig_num) { struct usbduxfast_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; int ret; if (!devpriv) return -EFAULT; + if (trig_num != cmd->start_arg) + return -EINVAL; + down(&devpriv->sem); - if (trignum != 0) { - dev_err(dev->class_dev, "invalid trignum\n"); - up(&devpriv->sem); - return -EINVAL; - } if (!devpriv->ai_cmd_running) { devpriv->ai_cmd_running = 1; ret = usbduxfast_submit_urb(dev); @@ -811,20 +809,11 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev, up(&devpriv->sem); return result; } - if (cmd->stop_src == TRIG_COUNT) { + + if (cmd->stop_src == TRIG_COUNT) devpriv->ai_sample_count = cmd->stop_arg * cmd->scan_end_arg; - if (devpriv->ai_sample_count < 1) { - dev_err(dev->class_dev, - "(cmd->stop_arg)*(cmd->scan_end_arg)<1, aborting\n"); - up(&devpriv->sem); - return -EFAULT; - } - devpriv->ai_continous = 0; - } else { - /* continous acquisition */ - devpriv->ai_continous = 1; + else /* TRIG_NONE */ devpriv->ai_sample_count = 0; - } if ((cmd->start_src == TRIG_NOW) || (cmd->start_src == TRIG_EXT)) { /* enable this acquisition operation */ @@ -837,12 +826,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev, return ret; } s->async->inttrig = NULL; - } else { - /* - * TRIG_INT - * don't enable the acquision operation - * wait for an internal signal - */ + } else { /* TRIG_INT */ s->async->inttrig = usbduxfast_ai_inttrig; } up(&devpriv->sem); diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 88c60b6020c4..ccc3ef7ba55c 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -161,14 +161,11 @@ struct usbduxsigma_private { /* input buffer for single insn */ uint8_t *insn_buf; - uint8_t ao_chanlist[USBDUXSIGMA_NUM_AO_CHAN]; unsigned int ao_readback[USBDUXSIGMA_NUM_AO_CHAN]; unsigned high_speed:1; unsigned ai_cmd_running:1; - unsigned ai_continuous:1; unsigned ao_cmd_running:1; - unsigned ao_continuous:1; unsigned pwm_cmd_running:1; /* number of samples to acquire */ @@ -223,6 +220,7 @@ 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_cmd *cmd = &s->async->cmd; unsigned int dio_state; uint32_t val; int ret; @@ -301,7 +299,7 @@ static void usbduxsigma_ai_urb_complete(struct urb *urb) /* timer zero, transfer measurements to comedi */ devpriv->ai_counter = devpriv->ai_timer; - if (!devpriv->ai_continuous) { + if (cmd->stop_src == TRIG_COUNT) { /* not continuous, fixed number of samples */ devpriv->ai_sample_count--; if (devpriv->ai_sample_count < 0) { @@ -314,7 +312,7 @@ static void usbduxsigma_ai_urb_complete(struct urb *urb) } /* get the data from the USB bus and hand it over to comedi */ - for (i = 0; i < s->async->cmd.chanlist_len; i++) { + 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 */ @@ -360,8 +358,8 @@ 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_cmd *cmd = &s->async->cmd; uint8_t *datap; - int len; int ret; int i; @@ -403,7 +401,7 @@ static void usbduxsigma_ao_urb_complete(struct urb *urb) /* timer zero, transfer from comedi */ devpriv->ao_counter = devpriv->ao_timer; - if (!devpriv->ao_continuous) { + if (cmd->stop_src == TRIG_COUNT) { /* not continuous, fixed number of samples */ devpriv->ao_sample_count--; if (devpriv->ao_sample_count < 0) { @@ -417,13 +415,12 @@ static void usbduxsigma_ao_urb_complete(struct urb *urb) /* transmit data to the USB bus */ datap = urb->transfer_buffer; - len = s->async->cmd.chanlist_len; - *datap++ = len; - for (i = 0; i < len; i++) { - unsigned int chan = devpriv->ao_chanlist[i]; + *datap++ = cmd->chanlist_len; + for (i = 0; i < cmd->chanlist_len; i++) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); unsigned short val; - ret = comedi_buf_get(s->async, &val); + ret = comedi_buf_get(s, &val); if (ret < 0) { dev_err(dev->class_dev, "buffer underflow\n"); s->async->events |= (COMEDI_CB_EOA | @@ -596,10 +593,8 @@ static int usbduxsigma_ai_cmdtest(struct comedi_device *dev, if (cmd->stop_src == TRIG_COUNT) { /* data arrives as one packet */ devpriv->ai_sample_count = cmd->stop_arg; - devpriv->ai_continuous = 0; } else { /* continuous acquisition */ - devpriv->ai_continuous = 1; devpriv->ai_sample_count = 0; } @@ -663,12 +658,13 @@ static int usbduxsigma_receive_cmd(struct comedi_device *dev, int command) static int usbduxsigma_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int trignum) + unsigned int trig_num) { struct usbduxsigma_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; int ret; - if (trignum != 0) + if (trig_num != cmd->start_arg) return -EINVAL; down(&devpriv->sem); @@ -738,7 +734,6 @@ static int usbduxsigma_ai_cmd(struct comedi_device *dev, } s->async->inttrig = NULL; } else { /* TRIG_INT */ - /* wait for an internal signal and submit the urbs later */ s->async->inttrig = usbduxsigma_ai_inttrig; } @@ -856,12 +851,13 @@ static int usbduxsigma_ao_insn_write(struct comedi_device *dev, static int usbduxsigma_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int trignum) + unsigned int trig_num) { struct usbduxsigma_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; int ret; - if (trignum != 0) + if (trig_num != cmd->start_arg) return -EINVAL; down(&devpriv->sem); @@ -985,10 +981,8 @@ static int usbduxsigma_ao_cmdtest(struct comedi_device *dev, */ devpriv->ao_sample_count = cmd->stop_arg; } - devpriv->ao_continuous = 0; } else { /* continuous acquisition */ - devpriv->ao_continuous = 1; devpriv->ao_sample_count = 0; } @@ -1004,14 +998,11 @@ static int usbduxsigma_ao_cmd(struct comedi_device *dev, struct usbduxsigma_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; int ret; - int i; down(&devpriv->sem); /* set current channel of the running acquisition to zero */ s->async->cur_chan = 0; - for (i = 0; i < cmd->chanlist_len; ++i) - devpriv->ao_chanlist[i] = CR_CHAN(cmd->chanlist[i]); devpriv->ao_counter = devpriv->ao_timer; @@ -1027,7 +1018,6 @@ static int usbduxsigma_ao_cmd(struct comedi_device *dev, } s->async->inttrig = NULL; } else { /* TRIG_INT */ - /* wait for an internal signal and submit the urbs later */ s->async->inttrig = usbduxsigma_ao_inttrig; } |