diff options
author | 2016-04-11 10:41:07 +0300 | |
---|---|---|
committer | 2016-04-13 08:17:18 +0300 | |
commit | e09b41010ba33a20a87472ee821fa407a5b8da36 (patch) | |
tree | d10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/drivers/staging/comedi | |
parent | f93b97fd65072de626c074dbe099a1fff05ce060 (diff) |
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page.
During the rebasing, the following patch collided:
Force tick interrupt and get rid of softirq magic(I70131fb85).
Collisions have been removed because its logic was found on the
source already.
Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769
Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/drivers/staging/comedi')
107 files changed, 9728 insertions, 10314 deletions
diff --git a/kernel/drivers/staging/comedi/Kconfig b/kernel/drivers/staging/comedi/Kconfig index 61c6351f5..ac0f01007 100644 --- a/kernel/drivers/staging/comedi/Kconfig +++ b/kernel/drivers/staging/comedi/Kconfig @@ -2,7 +2,7 @@ config COMEDI tristate "Data acquisition support (comedi)" depends on m ---help--- - Enable support a wide range of data acquisition devices + Enable support for a wide range of data acquisition devices for Linux. if COMEDI @@ -400,14 +400,6 @@ config COMEDI_DMM32AT To compile this driver as a module, choose M here: the module will be called dmm32at. -config COMEDI_UNIOXX5 - tristate "Fastwel UNIOxx-5 analog and digital io board support" - ---help--- - Enable support for Fastwel UNIOxx-5 (analog and digital i/o) boards - - To compile this driver as a module, choose M here: the module will be - called unioxx5. - config COMEDI_FL512 tristate "FL512 ISA card support" ---help--- @@ -418,6 +410,7 @@ config COMEDI_FL512 config COMEDI_AIO_AIO12_8 tristate "I/O Products PC/104 AIO12-8 Analog I/O Board support" + select COMEDI_8254 select COMEDI_8255 ---help--- Enable support for I/O Products PC/104 AIO12-8 Analog I/O Board @@ -1072,6 +1065,7 @@ config COMEDI_NI_PCIMIO config COMEDI_RTD520 tristate "Real Time Devices PCI4520/DM7520 support" + select COMEDI_8254 ---help--- Enable support for Real Time Devices PCI4520/DM7520 @@ -1247,16 +1241,22 @@ config COMEDI_8254 tristate config COMEDI_8255 - tristate "Generic 8255 support" + tristate + +config COMEDI_8255_SA + tristate "Standalone 8255 support" + select COMEDI_8255 ---help--- - Enable generic 8255 support. + Enable support for 8255 digital I/O as a standalone driver. You should enable compilation this driver if you plan to use a board - that has an 8255 chip. For multifunction boards, the main driver will - configure the 8255 subdevice automatically. + that has an 8255 chip at a known I/O base address and there are no + other Comedi drivers for the board. - Note that most PCI based 8255 boards use the 8255_pci driver as a - wrapper around this driver. + Note that Comedi drivers for most multi-function boards incorporating + an 8255 chip use the 'comedi_8255' module. Most PCI-based 8255 + boards use the 8255_pci driver as a wrapper around the 'comedi_8255' + module. To compile this driver as a module, choose M here: the module will be called 8255. diff --git a/kernel/drivers/staging/comedi/comedi.h b/kernel/drivers/staging/comedi/comedi.h index 745574077..66edda190 100644 --- a/kernel/drivers/staging/comedi/comedi.h +++ b/kernel/drivers/staging/comedi/comedi.h @@ -217,7 +217,7 @@ #define SDF_RUNNING 0x08000000 /* subdevice is acquiring data */ #define SDF_LSAMPL 0x10000000 /* subdevice uses 32-bit samples */ #define SDF_PACKED 0x20000000 /* subdevice can do packed DIO */ -/* re recyle these flags for PWM */ +/* re recycle these flags for PWM */ #define SDF_PWM_COUNTER SDF_MODE0 /* PWM can automatically switch off */ #define SDF_PWM_HBRIDGE SDF_MODE1 /* PWM is signed (H-bridge) */ diff --git a/kernel/drivers/staging/comedi/comedi_buf.c b/kernel/drivers/staging/comedi/comedi_buf.c index 19e7b229d..90c28016c 100644 --- a/kernel/drivers/staging/comedi/comedi_buf.c +++ b/kernel/drivers/staging/comedi/comedi_buf.c @@ -245,7 +245,7 @@ void comedi_buf_reset(struct comedi_subdevice *s) async->events = 0; } -static unsigned int comedi_buf_write_n_available(struct comedi_subdevice *s) +static unsigned int comedi_buf_write_n_unalloc(struct comedi_subdevice *s) { struct comedi_async *async = s->async; unsigned int free_end = async->buf_read_count + async->prealloc_bufsz; @@ -253,15 +253,33 @@ static unsigned int comedi_buf_write_n_available(struct comedi_subdevice *s) return free_end - async->buf_write_alloc_count; } -/* allocates chunk for the writer from free buffer space */ +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_count; +} + +/** + * comedi_buf_write_alloc() - Reserve buffer space for writing + * @s: COMEDI subdevice. + * @nbytes: Maximum space to reserve in bytes. + * + * Reserve up to @nbytes bytes of space to be written in the COMEDI acquisition + * data buffer associated with the subdevice. The amount reserved is limited + * by the space available. + * + * Return: The amount of space reserved in bytes. + */ unsigned int comedi_buf_write_alloc(struct comedi_subdevice *s, unsigned int nbytes) { struct comedi_async *async = s->async; - unsigned int available = comedi_buf_write_n_available(s); + unsigned int unalloc = comedi_buf_write_n_unalloc(s); - if (nbytes > available) - nbytes = available; + if (nbytes > unalloc) + nbytes = unalloc; async->buf_write_alloc_count += nbytes; @@ -329,7 +347,21 @@ unsigned int comedi_buf_write_n_allocated(struct comedi_subdevice *s) return async->buf_write_alloc_count - async->buf_write_count; } -/* transfers a chunk from writer to filled buffer space */ +/** + * comedi_buf_write_free() - Free buffer space after it is written + * @s: COMEDI subdevice. + * @nbytes: Maximum space to free in bytes. + * + * Free up to @nbytes bytes of space previously reserved for writing in the + * COMEDI acquisition data buffer associated with the subdevice. The amount of + * space freed is limited to the amount that was reserved. The freed space is + * assumed to have been filled with sample data by the writer. + * + * If the samples in the freed space need to be "munged", do so here. The + * freed space becomes available for allocation by the reader. + * + * Return: The amount of space freed in bytes. + */ unsigned int comedi_buf_write_free(struct comedi_subdevice *s, unsigned int nbytes) { @@ -349,6 +381,17 @@ unsigned int comedi_buf_write_free(struct comedi_subdevice *s, } EXPORT_SYMBOL_GPL(comedi_buf_write_free); +/** + * comedi_buf_read_n_available() - Determine amount of readable buffer space + * @s: COMEDI subdevice. + * + * Determine the amount of readable buffer space in the COMEDI acquisition data + * buffer associated with the subdevice. The readable buffer space is that + * which has been freed by the writer and "munged" to the sample data format + * expected by COMEDI if necessary. + * + * Return: The amount of readable buffer space. + */ unsigned int comedi_buf_read_n_available(struct comedi_subdevice *s) { struct comedi_async *async = s->async; @@ -369,7 +412,21 @@ unsigned int comedi_buf_read_n_available(struct comedi_subdevice *s) } EXPORT_SYMBOL_GPL(comedi_buf_read_n_available); -/* allocates a chunk for the reader from filled (and munged) buffer space */ +/** + * comedi_buf_read_alloc() - Reserve buffer space for reading + * @s: COMEDI subdevice. + * @nbytes: Maximum space to reserve in bytes. + * + * Reserve up to @nbytes bytes of previously written and "munged" buffer space + * for reading in the COMEDI acquisition data buffer associated with the + * subdevice. The amount reserved is limited to the space available. The + * reader can read from the reserved space and then free it. A reader is also + * allowed to read from the space before reserving it as long as it determines + * the amount of readable data available, but the space needs to be marked as + * reserved before it can be freed. + * + * Return: The amount of space reserved in bytes. + */ unsigned int comedi_buf_read_alloc(struct comedi_subdevice *s, unsigned int nbytes) { @@ -397,7 +454,19 @@ static unsigned int comedi_buf_read_n_allocated(struct comedi_async *async) return async->buf_read_alloc_count - async->buf_read_count; } -/* transfers control of a chunk from reader to free buffer space */ +/** + * comedi_buf_read_free() - Free buffer space after it has been read + * @s: COMEDI subdevice. + * @nbytes: Maximum space to free in bytes. + * + * Free up to @nbytes bytes of buffer space previously reserved for reading in + * the COMEDI acquisition data buffer associated with the subdevice. The + * amount of space freed is limited to the amount that was reserved. + * + * The freed space becomes available for allocation by the writer. + * + * Return: The amount of space freed in bytes. + */ unsigned int comedi_buf_read_free(struct comedi_subdevice *s, unsigned int nbytes) { @@ -469,15 +538,21 @@ static void comedi_buf_memcpy_from(struct comedi_subdevice *s, } /** - * comedi_buf_write_samples - write sample data to comedi buffer - * @s: comedi_subdevice struct - * @data: samples - * @nsamples: number of samples + * comedi_buf_write_samples() - Write sample data to COMEDI buffer + * @s: COMEDI subdevice. + * @data: Pointer to source samples. + * @nsamples: Number of samples to write. * - * Writes nsamples to the comedi buffer associated with the subdevice, marks - * it as written and updates the acquisition scan progress. + * Write up to @nsamples samples to the COMEDI acquisition data buffer + * associated with the subdevice, mark it as written and update the + * acquisition scan progress. If there is not enough room for the specified + * number of samples, the number of samples written is limited to the number + * that will fit and the %COMEDI_CB_OVERFLOW event flag is set to cause the + * acquisition to terminate with an overrun error. Set the %COMEDI_CB_BLOCK + * event flag if any samples are written to cause waiting tasks to be woken + * when the event flags are processed. * - * Returns the amount of data written in bytes. + * Return: The amount of data written in bytes. */ unsigned int comedi_buf_write_samples(struct comedi_subdevice *s, const void *data, unsigned int nsamples) @@ -490,8 +565,7 @@ unsigned int comedi_buf_write_samples(struct comedi_subdevice *s, * If not, clamp the nsamples to the number that will fit, flag the * buffer overrun and add the samples that fit. */ - max_samples = comedi_bytes_to_samples(s, - comedi_buf_write_n_available(s)); + max_samples = comedi_bytes_to_samples(s, comedi_buf_write_n_unalloc(s)); if (nsamples > max_samples) { dev_warn(s->device->class_dev, "buffer overrun\n"); s->async->events |= COMEDI_CB_OVERFLOW; @@ -513,15 +587,18 @@ unsigned int comedi_buf_write_samples(struct comedi_subdevice *s, EXPORT_SYMBOL_GPL(comedi_buf_write_samples); /** - * comedi_buf_read_samples - read sample data from comedi buffer - * @s: comedi_subdevice struct - * @data: destination - * @nsamples: maximum number of samples to read + * comedi_buf_read_samples() - Read sample data from COMEDI buffer + * @s: COMEDI subdevice. + * @data: Pointer to destination. + * @nsamples: Maximum number of samples to read. * - * Reads up to nsamples from the comedi buffer associated with the subdevice, - * marks it as read and updates the acquisition scan progress. + * Read up to @nsamples samples from the COMEDI acquisition data buffer + * associated with the subdevice, mark it as read and update the acquisition + * scan progress. Limit the number of samples read to the number available. + * Set the %COMEDI_CB_BLOCK event flag if any samples are read to cause waiting + * tasks to be woken when the event flags are processed. * - * Returns the amount of data read in bytes. + * Return: The amount of data read in bytes. */ unsigned int comedi_buf_read_samples(struct comedi_subdevice *s, void *data, unsigned int nsamples) diff --git a/kernel/drivers/staging/comedi/comedi_compat32.c b/kernel/drivers/staging/comedi/comedi_compat32.c index 25848244c..f356386d8 100644 --- a/kernel/drivers/staging/comedi/comedi_compat32.c +++ b/kernel/drivers/staging/comedi/comedi_compat32.c @@ -202,7 +202,8 @@ static int get_compat_cmd(struct comedi_cmd __user *cmd, err |= __get_user(temp.uint, &cmd32->stop_arg); err |= __put_user(temp.uint, &cmd->stop_arg); err |= __get_user(temp.uptr, &cmd32->chanlist); - err |= __put_user(compat_ptr(temp.uptr), &cmd->chanlist); + err |= __put_user((unsigned int __force *)compat_ptr(temp.uptr), + &cmd->chanlist); err |= __get_user(temp.uint, &cmd32->chanlist_len); err |= __put_user(temp.uint, &cmd->chanlist_len); err |= __get_user(temp.uptr, &cmd32->data); diff --git a/kernel/drivers/staging/comedi/comedi_fops.c b/kernel/drivers/staging/comedi/comedi_fops.c index e78ddbe5a..7b4af519e 100644 --- a/kernel/drivers/staging/comedi/comedi_fops.c +++ b/kernel/drivers/staging/comedi/comedi_fops.c @@ -43,13 +43,30 @@ #include "comedi_internal.h" +/* + * comedi_subdevice "runflags" + * COMEDI_SRF_RT: DEPRECATED: command is running real-time + * COMEDI_SRF_ERROR: indicates an COMEDI_CB_ERROR event has occurred + * since the last command was started + * COMEDI_SRF_RUNNING: command is running + * COMEDI_SRF_FREE_SPRIV: free s->private on detach + * + * COMEDI_SRF_BUSY_MASK: runflags that indicate the subdevice is "busy" + */ +#define COMEDI_SRF_RT BIT(1) +#define COMEDI_SRF_ERROR BIT(2) +#define COMEDI_SRF_RUNNING BIT(27) +#define COMEDI_SRF_FREE_SPRIV BIT(31) + +#define COMEDI_SRF_BUSY_MASK (COMEDI_SRF_ERROR | COMEDI_SRF_RUNNING) + /** - * struct comedi_file - per-file private data for comedi device - * @dev: comedi_device struct - * @read_subdev: current "read" subdevice - * @write_subdev: current "write" subdevice - * @last_detach_count: last known detach count - * @last_attached: last known attached/detached state + * struct comedi_file - Per-file private data for COMEDI device + * @dev: COMEDI device. + * @read_subdev: Current "read" subdevice. + * @write_subdev: Current "write" subdevice. + * @last_detach_count: Last known detach count. + * @last_attached: Last known attached/detached state. */ struct comedi_file { struct comedi_device *dev; @@ -114,15 +131,15 @@ static void comedi_dev_kref_release(struct kref *kref) } /** - * comedi_dev_put - release a use of a comedi device structure - * @dev: comedi_device struct + * comedi_dev_put() - Release a use of a COMEDI device + * @dev: COMEDI device. * - * Must be called when a user of a comedi device is finished with it. - * When the last user of the comedi device calls this function, the - * comedi device is destroyed. + * Must be called when a user of a COMEDI device is finished with it. + * When the last user of the COMEDI device calls this function, the + * COMEDI device is destroyed. * - * Return 1 if the comedi device is destroyed by this call or dev is - * NULL, otherwise return 0. Callers must not assume the comedi + * Return: 1 if the COMEDI device is destroyed by this call or @dev is + * NULL, otherwise return 0. Callers must not assume the COMEDI * device is still valid if this function returns 0. */ int comedi_dev_put(struct comedi_device *dev) @@ -198,7 +215,6 @@ static struct comedi_subdevice struct comedi_subdevice *s; unsigned int i = minor - COMEDI_NUM_BOARD_MINORS; - BUG_ON(i >= COMEDI_NUM_SUBDEVICE_MINORS); mutex_lock(&comedi_subdevice_minor_table_lock); s = comedi_subdevice_minor_table[i]; if (s && s->device != dev) @@ -211,7 +227,6 @@ static struct comedi_device *comedi_dev_get_from_board_minor(unsigned minor) { struct comedi_device *dev; - BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS); mutex_lock(&comedi_board_minor_table_lock); dev = comedi_dev_get(comedi_board_minor_table[minor]); mutex_unlock(&comedi_board_minor_table_lock); @@ -224,7 +239,6 @@ static struct comedi_device *comedi_dev_get_from_subdevice_minor(unsigned minor) struct comedi_subdevice *s; unsigned int i = minor - COMEDI_NUM_BOARD_MINORS; - BUG_ON(i >= COMEDI_NUM_SUBDEVICE_MINORS); mutex_lock(&comedi_subdevice_minor_table_lock); s = comedi_subdevice_minor_table[i]; dev = comedi_dev_get(s ? s->device : NULL); @@ -233,15 +247,15 @@ static struct comedi_device *comedi_dev_get_from_subdevice_minor(unsigned minor) } /** - * comedi_dev_get_from_minor - get comedi device by minor device number - * @minor: minor device number + * comedi_dev_get_from_minor() - Get COMEDI device by minor device number + * @minor: Minor device number. * - * Finds the comedi device associated by the minor device number, if any, - * and increments its reference count. The comedi device is prevented from + * Finds the COMEDI device associated with the minor device number, if any, + * and increments its reference count. The COMEDI device is prevented from * being freed until a matching call is made to comedi_dev_put(). * - * Return a pointer to the comedi device if it exists, with its usage - * reference incremented. Return NULL if no comedi device exists with the + * Return: A pointer to the COMEDI device if it exists, with its usage + * reference incremented. Return NULL if no COMEDI device exists with the * specified minor device number. */ struct comedi_device *comedi_dev_get_from_minor(unsigned minor) @@ -651,11 +665,11 @@ static bool comedi_is_runflags_in_error(unsigned runflags) } /** - * comedi_is_subdevice_running - check if async command running on subdevice - * @s: comedi_subdevice struct + * comedi_is_subdevice_running() - Check if async command running on subdevice + * @s: COMEDI subdevice. * - * Return true if an asynchronous comedi command is active on the comedi - * subdevice, else return false. + * Return: %true if an asynchronous COMEDI command is active on the + * subdevice, else %false. */ bool comedi_is_subdevice_running(struct comedi_subdevice *s) { @@ -679,19 +693,44 @@ static bool comedi_is_subdevice_idle(struct comedi_subdevice *s) return !(runflags & COMEDI_SRF_BUSY_MASK); } +bool comedi_can_auto_free_spriv(struct comedi_subdevice *s) +{ + unsigned runflags = __comedi_get_subdevice_runflags(s); + + return runflags & COMEDI_SRF_FREE_SPRIV; +} + +/** + * comedi_set_spriv_auto_free() - Mark subdevice private data as freeable + * @s: COMEDI subdevice. + * + * Mark the subdevice as having a pointer to private data that can be + * automatically freed when the COMEDI device is detached from the low-level + * driver. + */ +void comedi_set_spriv_auto_free(struct comedi_subdevice *s) +{ + __comedi_set_subdevice_runflags(s, COMEDI_SRF_FREE_SPRIV); +} +EXPORT_SYMBOL_GPL(comedi_set_spriv_auto_free); + /** - * comedi_alloc_spriv() - Allocate memory for the subdevice private data. - * @s: comedi_subdevice struct - * @size: size of the memory to allocate + * comedi_alloc_spriv - Allocate memory for the subdevice private data + * @s: COMEDI subdevice. + * @size: Size of the memory to allocate. + * + * Allocate memory for the subdevice private data and point @s->private + * to it. The memory will be freed automatically when the COMEDI device + * is detached from the low-level driver. * - * This also sets the subdevice runflags to allow the core to automatically - * free the private data during the detach. + * Return: A pointer to the allocated memory @s->private on success. + * Return NULL on failure. */ void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size) { s->private = kzalloc(size, GFP_KERNEL); if (s->private) - s->runflags |= COMEDI_SRF_FREE_SPRIV; + comedi_set_spriv_auto_free(s); return s->private; } EXPORT_SYMBOL_GPL(comedi_alloc_spriv); @@ -1048,11 +1087,6 @@ static int do_chaninfo_ioctl(struct comedi_device *dev, if (put_user(x, it.rangelist + i)) return -EFAULT; } -#if 0 - if (copy_to_user(it.rangelist, s->range_type_list, - s->n_chan * sizeof(unsigned int))) - return -EFAULT; -#endif } return 0; @@ -1112,7 +1146,7 @@ static int do_bufinfo_ioctl(struct comedi_device *dev, comedi_buf_read_free(s, bi.bytes_read); if (comedi_is_subdevice_idle(s) && - comedi_buf_n_bytes_ready(s) == 0) { + comedi_buf_read_n_available(s) == 0) { do_become_nonbusy(dev, s); } } @@ -1307,7 +1341,7 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, goto out; } /* This looks arbitrary. It is. */ - s->busy = &parse_insn; + s->busy = parse_insn; switch (insn->insn) { case INSN_READ: ret = s->insn_read(dev, s, insn, data); @@ -1725,7 +1759,7 @@ cleanup: /* * COMEDI_CMDTEST ioctl - * asynchronous aquisition command testing + * asynchronous acquisition command testing * * arg: * pointer to comedi_cmd structure @@ -2127,7 +2161,7 @@ static void comedi_vm_close(struct vm_area_struct *area) comedi_buf_map_put(bm); } -static struct vm_operations_struct comedi_vm_ops = { +static const struct vm_operations_struct comedi_vm_ops = { .open = comedi_vm_open, .close = comedi_vm_close, }; @@ -2228,9 +2262,9 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait) unsigned int mask = 0; struct comedi_file *cfp = file->private_data; struct comedi_device *dev = cfp->dev; - struct comedi_subdevice *s; + struct comedi_subdevice *s, *s_read; - mutex_lock(&dev->mutex); + down_read(&dev->attach_lock); if (!dev->attached) { dev_dbg(dev->class_dev, "no driver attached\n"); @@ -2238,9 +2272,10 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait) } s = comedi_file_read_subdevice(file); + s_read = s; if (s && s->async) { poll_wait(file, &s->async->wait_head, wait); - if (!s->busy || !comedi_is_subdevice_running(s) || + if (s->busy != file || !comedi_is_subdevice_running(s) || (s->async->cmd.flags & CMDF_WRITE) || comedi_buf_read_n_available(s) > 0) mask |= POLLIN | POLLRDNORM; @@ -2250,16 +2285,16 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait) if (s && s->async) { unsigned int bps = comedi_bytes_per_sample(s); - poll_wait(file, &s->async->wait_head, wait); - comedi_buf_write_alloc(s, s->async->prealloc_bufsz); - if (!s->busy || !comedi_is_subdevice_running(s) || + if (s != s_read) + poll_wait(file, &s->async->wait_head, wait); + if (s->busy != file || !comedi_is_subdevice_running(s) || !(s->async->cmd.flags & CMDF_WRITE) || - comedi_buf_write_n_allocated(s) >= bps) + comedi_buf_write_n_available(s) >= bps) mask |= POLLOUT | POLLWRNORM; } done: - mutex_unlock(&dev->mutex); + up_read(&dev->attach_lock); return mask; } @@ -2415,7 +2450,9 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, { struct comedi_subdevice *s; struct comedi_async *async; - int n, m, count = 0, retval = 0; + unsigned int n, m; + ssize_t count = 0; + int retval = 0; DECLARE_WAITQUEUE(wait, current); struct comedi_file *cfp = file->private_data; struct comedi_device *dev = cfp->dev; @@ -2441,28 +2478,19 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, } async = s->async; - if (!s->busy || !nbytes) - goto out; - if (s->busy != file) { - retval = -EACCES; - goto out; - } - if (async->cmd.flags & CMDF_WRITE) { + if (s->busy != file || (async->cmd.flags & CMDF_WRITE)) { retval = -EINVAL; goto out; } add_wait_queue(&async->wait_head, &wait); - while (nbytes > 0 && !retval) { - set_current_state(TASK_INTERRUPTIBLE); + while (count == 0 && !retval) { + unsigned int rp, n1, n2; - n = nbytes; + set_current_state(TASK_INTERRUPTIBLE); m = comedi_buf_read_n_available(s); - if (async->buf_read_ptr + m > async->prealloc_bufsz) - m = async->prealloc_bufsz - async->buf_read_ptr; - if (m < n) - n = m; + n = min_t(size_t, m, nbytes); if (n == 0) { unsigned runflags = comedi_get_subdevice_runflags(s); @@ -2470,11 +2498,12 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, if (!comedi_is_runflags_running(runflags)) { if (comedi_is_runflags_in_error(runflags)) retval = -EPIPE; - else - retval = 0; - become_nonbusy = true; + if (retval || nbytes) + become_nonbusy = true; break; } + if (nbytes == 0) + break; if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; break; @@ -2484,22 +2513,21 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, retval = -ERESTARTSYS; break; } - if (!s->busy) { - retval = 0; - break; - } - if (s->busy != file) { - retval = -EACCES; - break; - } - if (async->cmd.flags & CMDF_WRITE) { + if (s->busy != file || + (async->cmd.flags & CMDF_WRITE)) { retval = -EINVAL; break; } continue; } - m = copy_to_user(buf, async->prealloc_buf + - async->buf_read_ptr, n); + rp = async->buf_read_ptr; + n1 = min(n, async->prealloc_bufsz - rp); + n2 = n - n1; + m = copy_to_user(buf, async->prealloc_buf + rp, n1); + if (m) + m += n2; + else if (n2) + m = copy_to_user(buf + n1, async->prealloc_buf, n2); if (m) { n -= m; retval = -EFAULT; @@ -2512,11 +2540,10 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, nbytes -= n; buf += n; - break; /* makes device work like a pipe */ } remove_wait_queue(&async->wait_head, &wait); set_current_state(TASK_RUNNING); - if (become_nonbusy || comedi_is_subdevice_idle(s)) { + if (become_nonbusy && count == 0) { struct comedi_subdevice *new_s; /* @@ -2532,13 +2559,17 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, * sufficient (unless there have been 2**32 detaches in the * meantime!), but check the subdevice pointer as well just in * case. + * + * Also check the subdevice is still in a suitable state to + * become non-busy in case it changed behind our back. */ new_s = comedi_file_read_subdevice(file); if (dev->attached && old_detach_count == dev->detach_count && - s == new_s && new_s->async == async) { - if (become_nonbusy || comedi_buf_n_bytes_ready(s) == 0) - do_become_nonbusy(dev, s); - } + s == new_s && new_s->async == async && s->busy == file && + !(async->cmd.flags & CMDF_WRITE) && + !comedi_is_subdevice_running(s) && + comedi_buf_read_n_available(s) == 0) + do_become_nonbusy(dev, s); mutex_unlock(&dev->mutex); } out: @@ -2567,14 +2598,14 @@ static int comedi_open(struct inode *inode, struct file *file) cfp->dev = dev; mutex_lock(&dev->mutex); - if (!dev->attached && !capable(CAP_NET_ADMIN)) { - dev_dbg(dev->class_dev, "not attached and not CAP_NET_ADMIN\n"); + if (!dev->attached && !capable(CAP_SYS_ADMIN)) { + dev_dbg(dev->class_dev, "not attached and not CAP_SYS_ADMIN\n"); rc = -ENODEV; goto out; } if (dev->attached && dev->use_count == 0) { if (!try_module_get(dev->driver->module)) { - rc = -ENOSYS; + rc = -ENXIO; goto out; } if (dev->open) { @@ -2657,15 +2688,15 @@ static const struct file_operations comedi_fops = { }; /** - * comedi_event - handle events for asynchronous comedi command - * @dev: comedi_device struct - * @s: comedi_subdevice struct associated with dev - * Context: interrupt (usually), s->spin_lock spin-lock not held + * comedi_event() - Handle events for asynchronous COMEDI command + * @dev: COMEDI device. + * @s: COMEDI subdevice. + * Context: in_interrupt() (usually), @s->spin_lock spin-lock not held. * - * If an asynchronous comedi command is active on the subdevice, process - * any COMEDI_CB_... event flags that have been set, usually by an + * If an asynchronous COMEDI command is active on the subdevice, process + * any %COMEDI_CB_... event flags that have been set, usually by an * interrupt handler. These may change the run state of the asynchronous - * command, wake a task, and/or send a SIGIO signal. + * command, wake a task, and/or send a %SIGIO signal. */ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s) { @@ -2745,12 +2776,6 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device) return dev; } -static void comedi_free_board_minor(unsigned minor) -{ - BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS); - comedi_free_board_dev(comedi_clear_board_minor(minor)); -} - void comedi_release_hardware_device(struct device *hardware_device) { int minor; @@ -2806,12 +2831,10 @@ void comedi_free_subdevice_minor(struct comedi_subdevice *s) if (!s) return; - if (s->minor < 0) + if (s->minor < COMEDI_NUM_BOARD_MINORS || + s->minor >= COMEDI_NUM_MINORS) return; - BUG_ON(s->minor >= COMEDI_NUM_MINORS); - BUG_ON(s->minor < COMEDI_NUM_BOARD_MINORS); - i = s->minor - COMEDI_NUM_BOARD_MINORS; mutex_lock(&comedi_subdevice_minor_table_lock); if (s == comedi_subdevice_minor_table[i]) @@ -2825,10 +2848,13 @@ void comedi_free_subdevice_minor(struct comedi_subdevice *s) static void comedi_cleanup_board_minors(void) { + struct comedi_device *dev; unsigned i; - for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) - comedi_free_board_minor(i); + for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) { + dev = comedi_clear_board_minor(i); + comedi_free_board_dev(dev); + } } static int __init comedi_init(void) @@ -2900,14 +2926,7 @@ module_init(comedi_init); static void __exit comedi_cleanup(void) { - int i; - comedi_cleanup_board_minors(); - for (i = 0; i < COMEDI_NUM_BOARD_MINORS; ++i) - BUG_ON(comedi_board_minor_table[i]); - for (i = 0; i < COMEDI_NUM_SUBDEVICE_MINORS; ++i) - BUG_ON(comedi_subdevice_minor_table[i]); - class_destroy(comedi_class); cdev_del(&comedi_cdev); unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS); diff --git a/kernel/drivers/staging/comedi/comedi_internal.h b/kernel/drivers/staging/comedi/comedi_internal.h index 3b9185388..3f2c88ae6 100644 --- a/kernel/drivers/staging/comedi/comedi_internal.h +++ b/kernel/drivers/staging/comedi/comedi_internal.h @@ -31,8 +31,10 @@ 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_available(struct comedi_subdevice *s); unsigned int comedi_buf_write_n_allocated(struct comedi_subdevice *s); void comedi_device_cancel_all(struct comedi_device *dev); +bool comedi_can_auto_free_spriv(struct comedi_subdevice *s); extern unsigned int comedi_default_buf_size_kb; extern unsigned int comedi_default_buf_maxsize_kb; diff --git a/kernel/drivers/staging/comedi/comedi_pci.c b/kernel/drivers/staging/comedi/comedi_pci.c index 027f0f4e5..51e023a1c 100644 --- a/kernel/drivers/staging/comedi/comedi_pci.c +++ b/kernel/drivers/staging/comedi/comedi_pci.c @@ -22,8 +22,14 @@ #include "comedi_pci.h" /** - * comedi_to_pci_dev() - comedi_device pointer to pci_dev pointer. - * @dev: comedi_device struct + * comedi_to_pci_dev() - Return PCI device attached to COMEDI device + * @dev: COMEDI device. + * + * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a + * a &struct device embedded in a &struct pci_dev. + * + * Return: Attached PCI device if @dev->hw_dev is non-%NULL. + * Return %NULL if @dev->hw_dev is %NULL. */ struct pci_dev *comedi_to_pci_dev(struct comedi_device *dev) { @@ -32,8 +38,22 @@ struct pci_dev *comedi_to_pci_dev(struct comedi_device *dev) EXPORT_SYMBOL_GPL(comedi_to_pci_dev); /** - * comedi_pci_enable() - Enable the PCI device and request the regions. - * @dev: comedi_device struct + * comedi_pci_enable() - Enable the PCI device and request the regions + * @dev: COMEDI device. + * + * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a + * a &struct device embedded in a &struct pci_dev. Enable the PCI device + * and request its regions. Set @dev->ioenabled to %true if successful, + * otherwise undo what was done. + * + * Calls to comedi_pci_enable() and comedi_pci_disable() cannot be nested. + * + * Return: + * 0 on success, + * -%ENODEV if @dev->hw_dev is %NULL, + * -%EBUSY if regions busy, + * or some negative error number if failed to enable PCI device. + * */ int comedi_pci_enable(struct comedi_device *dev) { @@ -58,8 +78,13 @@ int comedi_pci_enable(struct comedi_device *dev) EXPORT_SYMBOL_GPL(comedi_pci_enable); /** - * comedi_pci_disable() - Release the regions and disable the PCI device. - * @dev: comedi_device struct + * comedi_pci_disable() - Release the regions and disable the PCI device + * @dev: COMEDI device. + * + * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a + * a &struct device embedded in a &struct pci_dev. If the earlier call + * to comedi_pci_enable() was successful, release the PCI device's regions + * and disable it. Reset @dev->ioenabled back to %false. */ void comedi_pci_disable(struct comedi_device *dev) { @@ -74,8 +99,18 @@ void comedi_pci_disable(struct comedi_device *dev) EXPORT_SYMBOL_GPL(comedi_pci_disable); /** - * comedi_pci_detach() - A generic (*detach) function for PCI drivers. - * @dev: comedi_device struct + * comedi_pci_detach() - A generic "detach" handler for PCI COMEDI drivers + * @dev: COMEDI device. + * + * COMEDI drivers for PCI devices that need no special clean-up of private data + * and have no ioremapped regions other than that pointed to by @dev->mmio may + * use this function as its "detach" handler called by the COMEDI core when a + * COMEDI device is being detached from the low-level driver. It may be also + * called from a more specific "detach" handler that does additional clean-up. + * + * Free the IRQ if @dev->irq is non-zero, iounmap @dev->mmio if it is + * non-%NULL, and call comedi_pci_disable() to release the PCI device's regions + * and disable it. */ void comedi_pci_detach(struct comedi_device *dev) { @@ -97,12 +132,19 @@ void comedi_pci_detach(struct comedi_device *dev) EXPORT_SYMBOL_GPL(comedi_pci_detach); /** - * comedi_pci_auto_config() - Configure/probe a comedi PCI driver. - * @pcidev: pci_dev struct - * @driver: comedi_driver struct - * @context: driver specific data, passed to comedi_auto_config() + * comedi_pci_auto_config() - Configure/probe a PCI COMEDI device + * @pcidev: PCI device. + * @driver: Registered COMEDI driver. + * @context: Driver specific data, passed to comedi_auto_config(). * - * Typically called from the pci_driver (*probe) function. + * Typically called from the pci_driver (*probe) function. Auto-configure + * a COMEDI device, using the &struct device embedded in *@pcidev as the + * hardware device. The @context value gets passed through to @driver's + * "auto_attach" handler. The "auto_attach" handler may call + * comedi_to_pci_dev() on the passed in COMEDI device to recover @pcidev. + * + * Return: The result of calling comedi_auto_config() (0 on success, or + * a negative error number on failure). */ int comedi_pci_auto_config(struct pci_dev *pcidev, struct comedi_driver *driver, @@ -113,10 +155,18 @@ int comedi_pci_auto_config(struct pci_dev *pcidev, EXPORT_SYMBOL_GPL(comedi_pci_auto_config); /** - * comedi_pci_auto_unconfig() - Unconfigure/remove a comedi PCI driver. - * @pcidev: pci_dev struct + * comedi_pci_auto_unconfig() - Unconfigure/remove a PCI COMEDI device + * @pcidev: PCI device. + * + * Typically called from the pci_driver (*remove) function. Auto-unconfigure + * a COMEDI device attached to this PCI device, using a pointer to the + * &struct device embedded in *@pcidev as the hardware device. The COMEDI + * driver's "detach" handler will be called during unconfiguration of the + * COMEDI device. * - * Typically called from the pci_driver (*remove) function. + * Note that the COMEDI device may have already been unconfigured using the + * %COMEDI_DEVCONFIG ioctl, in which case this attempt to unconfigure it + * again should be ignored. */ void comedi_pci_auto_unconfig(struct pci_dev *pcidev) { @@ -125,13 +175,15 @@ void comedi_pci_auto_unconfig(struct pci_dev *pcidev) EXPORT_SYMBOL_GPL(comedi_pci_auto_unconfig); /** - * comedi_pci_driver_register() - Register a comedi PCI driver. - * @comedi_driver: comedi_driver struct - * @pci_driver: pci_driver struct + * comedi_pci_driver_register() - Register a PCI COMEDI driver + * @comedi_driver: COMEDI driver to be registered. + * @pci_driver: PCI driver to be registered. + * + * This function is called from the module_init() of PCI COMEDI driver modules + * to register the COMEDI driver and the PCI driver. Do not call it directly, + * use the module_comedi_pci_driver() helper macro instead. * - * This function is used for the module_init() of comedi PCI drivers. - * Do not call it directly, use the module_comedi_pci_driver() helper - * macro instead. + * Return: 0 on success, or a negative error number on failure. */ int comedi_pci_driver_register(struct comedi_driver *comedi_driver, struct pci_driver *pci_driver) @@ -153,13 +205,13 @@ int comedi_pci_driver_register(struct comedi_driver *comedi_driver, EXPORT_SYMBOL_GPL(comedi_pci_driver_register); /** - * comedi_pci_driver_unregister() - Unregister a comedi PCI driver. - * @comedi_driver: comedi_driver struct - * @pci_driver: pci_driver struct + * comedi_pci_driver_unregister() - Unregister a PCI COMEDI driver + * @comedi_driver: COMEDI driver to be unregistered. + * @pci_driver: PCI driver to be unregistered. * - * This function is used for the module_exit() of comedi PCI drivers. - * Do not call it directly, use the module_comedi_pci_driver() helper - * macro instead. + * This function is called from the module_exit() of PCI COMEDI driver modules + * to unregister the PCI driver and the COMEDI driver. Do not call it + * directly, use the module_comedi_pci_driver() helper macro instead. */ void comedi_pci_driver_unregister(struct comedi_driver *comedi_driver, struct pci_driver *pci_driver) diff --git a/kernel/drivers/staging/comedi/comedi_pcmcia.c b/kernel/drivers/staging/comedi/comedi_pcmcia.c index 7e784399a..d7072a5c1 100644 --- a/kernel/drivers/staging/comedi/comedi_pcmcia.c +++ b/kernel/drivers/staging/comedi/comedi_pcmcia.c @@ -22,8 +22,14 @@ #include "comedi_pcmcia.h" /** - * comedi_to_pcmcia_dev() - comedi_device pointer to pcmcia_device pointer. - * @dev: comedi_device struct + * comedi_to_pcmcia_dev() - Return PCMCIA device attached to COMEDI device + * @dev: COMEDI device. + * + * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a + * a &struct device embedded in a &struct pcmcia_device. + * + * Return: Attached PCMCIA device if @dev->hw_dev is non-%NULL. + * Return %NULL if @dev->hw_dev is %NULL. */ struct pcmcia_device *comedi_to_pcmcia_dev(struct comedi_device *dev) { @@ -41,13 +47,35 @@ static int comedi_pcmcia_conf_check(struct pcmcia_device *link, } /** - * comedi_pcmcia_enable() - Request the regions and enable the PCMCIA device. - * @dev: comedi_device struct - * @conf_check: optional callback to check the pcmcia_device configuration + * comedi_pcmcia_enable() - Request the regions and enable the PCMCIA device + * @dev: COMEDI device. + * @conf_check: Optional callback to check each configuration option of the + * PCMCIA device and request I/O regions. + * + * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a a + * &struct device embedded in a &struct pcmcia_device. The comedi PCMCIA + * driver needs to set the 'config_flags' member in the &struct pcmcia_device, + * as appropriate for that driver, before calling this function in order to + * allow pcmcia_loop_config() to do its internal autoconfiguration. + * + * If @conf_check is %NULL it is set to a default function. If is + * passed to pcmcia_loop_config() and should return %0 if the configuration + * is valid and I/O regions requested successfully, otherwise it should return + * a negative error value. The default function returns -%EINVAL if the + * 'config_index' member is %0, otherwise it calls pcmcia_request_io() and + * returns the result. + * + * If the above configuration check passes, pcmcia_enable_device() is called + * to set up and activate the PCMCIA device. * - * The comedi PCMCIA driver needs to set the link->config_flags, as - * appropriate for that driver, before calling this function in order - * to allow pcmcia_loop_config() to do its internal autoconfiguration. + * If this function returns an error, comedi_pcmcia_disable() should be called + * to release requested resources. + * + * Return: + * 0 on success, + * -%ENODEV id @dev->hw_dev is %NULL, + * a negative error number from pcmcia_loop_config() if it fails, + * or a negative error number from pcmcia_enable_device() if it fails. */ int comedi_pcmcia_enable(struct comedi_device *dev, int (*conf_check)(struct pcmcia_device *, void *)) @@ -70,8 +98,12 @@ int comedi_pcmcia_enable(struct comedi_device *dev, EXPORT_SYMBOL_GPL(comedi_pcmcia_enable); /** - * comedi_pcmcia_disable() - Disable the PCMCIA device and release the regions. - * @dev: comedi_device struct + * comedi_pcmcia_disable() - Disable the PCMCIA device and release the regions + * @dev: COMEDI device. + * + * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a + * a &struct device embedded in a &struct pcmcia_device. Call + * pcmcia_disable_device() to disable and clean up the PCMCIA device. */ void comedi_pcmcia_disable(struct comedi_device *dev) { @@ -83,11 +115,17 @@ void comedi_pcmcia_disable(struct comedi_device *dev) EXPORT_SYMBOL_GPL(comedi_pcmcia_disable); /** - * comedi_pcmcia_auto_config() - Configure/probe a comedi PCMCIA driver. - * @link: pcmcia_device struct - * @driver: comedi_driver struct + * comedi_pcmcia_auto_config() - Configure/probe a PCMCIA COMEDI device + * @link: PCMCIA device. + * @driver: Registered COMEDI driver. + * + * Typically called from the pcmcia_driver (*probe) function. Auto-configure + * a COMEDI device, using a pointer to the &struct device embedded in *@link + * as the hardware device. The @driver's "auto_attach" handler may call + * comedi_to_pcmcia_dev() on the passed in COMEDI device to recover @link. * - * Typically called from the pcmcia_driver (*probe) function. + * Return: The result of calling comedi_auto_config() (0 on success, or a + * negative error number on failure). */ int comedi_pcmcia_auto_config(struct pcmcia_device *link, struct comedi_driver *driver) @@ -97,10 +135,18 @@ int comedi_pcmcia_auto_config(struct pcmcia_device *link, EXPORT_SYMBOL_GPL(comedi_pcmcia_auto_config); /** - * comedi_pcmcia_auto_unconfig() - Unconfigure/remove a comedi PCMCIA driver. - * @link: pcmcia_device struct + * comedi_pcmcia_auto_unconfig() - Unconfigure/remove a PCMCIA COMEDI device + * @link: PCMCIA device. * * Typically called from the pcmcia_driver (*remove) function. + * Auto-unconfigure a COMEDI device attached to this PCMCIA device, using a + * pointer to the &struct device embedded in *@link as the hardware device. + * The COMEDI driver's "detach" handler will be called during unconfiguration + * of the COMEDI device. + * + * Note that the COMEDI device may have already been unconfigured using the + * %COMEDI_DEVCONFIG ioctl, in which case this attempt to unconfigure it + * again should be ignored. */ void comedi_pcmcia_auto_unconfig(struct pcmcia_device *link) { @@ -109,13 +155,15 @@ void comedi_pcmcia_auto_unconfig(struct pcmcia_device *link) EXPORT_SYMBOL_GPL(comedi_pcmcia_auto_unconfig); /** - * comedi_pcmcia_driver_register() - Register a comedi PCMCIA driver. - * @comedi_driver: comedi_driver struct - * @pcmcia_driver: pcmcia_driver struct + * comedi_pcmcia_driver_register() - Register a PCMCIA COMEDI driver + * @comedi_driver: COMEDI driver to be registered. + * @pcmcia_driver: PCMCIA driver to be registered. + * + * This function is used for the module_init() of PCMCIA COMEDI driver modules + * to register the COMEDI driver and the PCMCIA driver. Do not call it + * directly, use the module_comedi_pcmcia_driver() helper macro instead. * - * This function is used for the module_init() of comedi USB drivers. - * Do not call it directly, use the module_comedi_pcmcia_driver() helper - * macro instead. + * Return: 0 on success, or a negative error number on failure. */ int comedi_pcmcia_driver_register(struct comedi_driver *comedi_driver, struct pcmcia_driver *pcmcia_driver) @@ -137,13 +185,13 @@ int comedi_pcmcia_driver_register(struct comedi_driver *comedi_driver, EXPORT_SYMBOL_GPL(comedi_pcmcia_driver_register); /** - * comedi_pcmcia_driver_unregister() - Unregister a comedi PCMCIA driver. - * @comedi_driver: comedi_driver struct - * @pcmcia_driver: pcmcia_driver struct + * comedi_pcmcia_driver_unregister() - Unregister a PCMCIA COMEDI driver + * @comedi_driver: COMEDI driver to be registered. + * @pcmcia_driver: PCMCIA driver to be registered. * - * This function is used for the module_exit() of comedi PCMCIA drivers. - * Do not call it directly, use the module_comedi_pcmcia_driver() helper - * macro instead. + * This function is called from the module_exit() of PCMCIA COMEDI driver + * modules to unregister the PCMCIA driver and the COMEDI driver. Do not call + * it directly, use the module_comedi_pcmcia_driver() helper macro instead. */ void comedi_pcmcia_driver_unregister(struct comedi_driver *comedi_driver, struct pcmcia_driver *pcmcia_driver) diff --git a/kernel/drivers/staging/comedi/comedi_usb.c b/kernel/drivers/staging/comedi/comedi_usb.c index 68b75e8fe..9c946d40b 100644 --- a/kernel/drivers/staging/comedi/comedi_usb.c +++ b/kernel/drivers/staging/comedi/comedi_usb.c @@ -21,8 +21,14 @@ #include "comedi_usb.h" /** - * comedi_to_usb_interface() - comedi_device pointer to usb_interface pointer. - * @dev: comedi_device struct + * comedi_to_usb_interface() - Return USB interface attached to COMEDI device + * @dev: COMEDI device. + * + * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a + * a &struct device embedded in a &struct usb_interface. + * + * Return: Attached USB interface if @dev->hw_dev is non-%NULL. + * Return %NULL if @dev->hw_dev is %NULL. */ struct usb_interface *comedi_to_usb_interface(struct comedi_device *dev) { @@ -31,8 +37,14 @@ struct usb_interface *comedi_to_usb_interface(struct comedi_device *dev) EXPORT_SYMBOL_GPL(comedi_to_usb_interface); /** - * comedi_to_usb_dev() - comedi_device pointer to usb_device pointer. - * @dev: comedi_device struct + * comedi_to_usb_dev() - Return USB device attached to COMEDI device + * @dev: COMEDI device. + * + * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a + * a &struct device embedded in a &struct usb_interface. + * + * Return: USB device to which the USB interface belongs if @dev->hw_dev is + * non-%NULL. Return %NULL if @dev->hw_dev is %NULL. */ struct usb_device *comedi_to_usb_dev(struct comedi_device *dev) { @@ -43,12 +55,19 @@ struct usb_device *comedi_to_usb_dev(struct comedi_device *dev) EXPORT_SYMBOL_GPL(comedi_to_usb_dev); /** - * comedi_usb_auto_config() - Configure/probe a comedi USB driver. - * @intf: usb_interface struct - * @driver: comedi_driver struct - * @context: driver specific data, passed to comedi_auto_config() + * comedi_usb_auto_config() - Configure/probe a USB COMEDI driver + * @intf: USB interface. + * @driver: Registered COMEDI driver. + * @context: Driver specific data, passed to comedi_auto_config(). * - * Typically called from the usb_driver (*probe) function. + * Typically called from the usb_driver (*probe) function. Auto-configure a + * COMEDI device, using a pointer to the &struct device embedded in *@intf as + * the hardware device. The @context value gets passed through to @driver's + * "auto_attach" handler. The "auto_attach" handler may call + * comedi_to_usb_interface() on the passed in COMEDI device to recover @intf. + * + * Return: The result of calling comedi_auto_config() (%0 on success, or + * a negative error number on failure). */ int comedi_usb_auto_config(struct usb_interface *intf, struct comedi_driver *driver, @@ -59,10 +78,18 @@ int comedi_usb_auto_config(struct usb_interface *intf, EXPORT_SYMBOL_GPL(comedi_usb_auto_config); /** - * comedi_pci_auto_unconfig() - Unconfigure/disconnect a comedi USB driver. - * @intf: usb_interface struct + * comedi_usb_auto_unconfig() - Unconfigure/disconnect a USB COMEDI device + * @intf: USB interface. * * Typically called from the usb_driver (*disconnect) function. + * Auto-unconfigure a COMEDI device attached to this USB interface, using a + * pointer to the &struct device embedded in *@intf as the hardware device. + * The COMEDI driver's "detach" handler will be called during unconfiguration + * of the COMEDI device. + * + * Note that the COMEDI device may have already been unconfigured using the + * %COMEDI_DEVCONFIG ioctl, in which case this attempt to unconfigure it + * again should be ignored. */ void comedi_usb_auto_unconfig(struct usb_interface *intf) { @@ -71,13 +98,15 @@ void comedi_usb_auto_unconfig(struct usb_interface *intf) EXPORT_SYMBOL_GPL(comedi_usb_auto_unconfig); /** - * comedi_usb_driver_register() - Register a comedi USB driver. - * @comedi_driver: comedi_driver struct - * @usb_driver: usb_driver struct + * comedi_usb_driver_register() - Register a USB COMEDI driver + * @comedi_driver: COMEDI driver to be registered. + * @usb_driver: USB driver to be registered. + * + * This function is called from the module_init() of USB COMEDI driver modules + * to register the COMEDI driver and the USB driver. Do not call it directly, + * use the module_comedi_usb_driver() helper macro instead. * - * This function is used for the module_init() of comedi USB drivers. - * Do not call it directly, use the module_comedi_usb_driver() helper - * macro instead. + * Return: %0 on success, or a negative error number on failure. */ int comedi_usb_driver_register(struct comedi_driver *comedi_driver, struct usb_driver *usb_driver) @@ -99,13 +128,13 @@ int comedi_usb_driver_register(struct comedi_driver *comedi_driver, EXPORT_SYMBOL_GPL(comedi_usb_driver_register); /** - * comedi_usb_driver_unregister() - Unregister a comedi USB driver. - * @comedi_driver: comedi_driver struct - * @usb_driver: usb_driver struct + * comedi_usb_driver_unregister() - Unregister a USB COMEDI driver + * @comedi_driver: COMEDI driver to be registered. + * @usb_driver: USB driver to be registered. * - * This function is used for the module_exit() of comedi USB drivers. - * Do not call it directly, use the module_comedi_usb_driver() helper - * macro instead. + * This function is called from the module_exit() of USB COMEDI driver modules + * to unregister the USB driver and the COMEDI driver. Do not call it + * directly, use the module_comedi_usb_driver() helper macro instead. */ void comedi_usb_driver_unregister(struct comedi_driver *comedi_driver, struct usb_driver *usb_driver) diff --git a/kernel/drivers/staging/comedi/comedidev.h b/kernel/drivers/staging/comedi/comedidev.h index dfab5a84b..115807215 100644 --- a/kernel/drivers/staging/comedi/comedidev.h +++ b/kernel/drivers/staging/comedi/comedidev.h @@ -1,20 +1,20 @@ /* - include/linux/comedidev.h - header file for kernel-only structures, variables, and constants - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedidev.h + * header file for kernel-only structures, variables, and constants + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #ifndef _COMEDIDEV_H #define _COMEDIDEV_H @@ -34,6 +34,131 @@ #define COMEDI_NUM_BOARD_MINORS 0x30 +/** + * struct comedi_subdevice - Working data for a COMEDI subdevice + * @device: COMEDI device to which this subdevice belongs. (Initialized by + * comedi_alloc_subdevices().) + * @index: Index of this subdevice within device's array of subdevices. + * (Initialized by comedi_alloc_subdevices().) + * @type: Type of subdevice from &enum comedi_subdevice_type. (Initialized by + * the low-level driver.) + * @n_chan: Number of channels the subdevice supports. (Initialized by the + * low-level driver.) + * @subdev_flags: Various "SDF" flags indicating aspects of the subdevice to + * the COMEDI core and user application. (Initialized by the low-level + * driver.) + * @len_chanlist: Maximum length of a channel list if the subdevice supports + * asynchronous acquisition commands. (Optionally initialized by the + * low-level driver, or changed from 0 to 1 during post-configuration.) + * @private: Private data pointer which is either set by the low-level driver + * itself, or by a call to comedi_alloc_spriv() which allocates storage. + * In the latter case, the storage is automatically freed after the + * low-level driver's "detach" handler is called for the device. + * (Initialized by the low-level driver.) + * @async: Pointer to &struct comedi_async id the subdevice supports + * asynchronous acquisition commands. (Allocated and initialized during + * post-configuration if needed.) + * @lock: Pointer to a file object that performed a %COMEDI_LOCK ioctl on the + * subdevice. (Initially NULL.) + * @busy: Pointer to a file object that is performing an asynchronous + * acquisition command on the subdevice. (Initially NULL.) + * @runflags: Internal flags for use by COMEDI core, mostly indicating whether + * an asynchronous acquisition command is running. + * @spin_lock: Generic spin-lock for use by the COMEDI core and the low-level + * driver. (Initialized by comedi_alloc_subdevices().) + * @io_bits: Bit-mask indicating the channel directions for a DIO subdevice + * with no more than 32 channels. A '1' at a bit position indicates the + * corresponding channel is configured as an output. (Initialized by the + * low-level driver for a DIO subdevice. Forced to all-outputs during + * post-configuration for a digital output subdevice.) + * @maxdata: If non-zero, this is the maximum raw data value of each channel. + * If zero, the maximum data value is channel-specific. (Initialized by + * the low-level driver.) + * @maxdata_list: If the maximum data value is channel-specific, this points + * to an array of maximum data values indexed by channel index. + * (Initialized by the low-level driver.) + * @range_table: If non-NULL, this points to a COMEDI range table for the + * subdevice. If NULL, the range table is channel-specific. (Initialized + * by the low-level driver, will be set to an "invalid" range table during + * post-configuration if @range_table and @range_table_list are both + * NULL.) + * @range_table_list: If the COMEDI range table is channel-specific, this + * points to an array of pointers to COMEDI range tables indexed by + * channel number. (Initialized by the low-level driver.) + * @chanlist: Not used. + * @insn_read: Optional pointer to a handler for the %INSN_READ instruction. + * (Initialized by the low-level driver, or set to a default handler + * during post-configuration.) + * @insn_write: Optional pointer to a handler for the %INSN_WRITE instruction. + * (Initialized by the low-level driver, or set to a default handler + * during post-configuration.) + * @insn_bits: Optional pointer to a handler for the %INSN_BITS instruction + * for a digital input, digital output or digital input/output subdevice. + * (Initialized by the low-level driver, or set to a default handler + * during post-configuration.) + * @insn_config: Optional pointer to a handler for the %INSN_CONFIG + * instruction. (Initialized by the low-level driver, or set to a default + * handler during post-configuration.) + * @do_cmd: If the subdevice supports asynchronous acquisition commands, this + * points to a handler to set it up in hardware. (Initialized by the + * low-level driver.) + * @do_cmdtest: If the subdevice supports asynchronous acquisition commands, + * this points to a handler used to check and possibly tweak a prospective + * acquisition command without setting it up in hardware. (Initialized by + * the low-level driver.) + * @poll: If the subdevice supports asynchronous acquisition commands, this + * is an optional pointer to a handler for the %COMEDI_POLL ioctl which + * instructs the low-level driver to synchronize buffers. (Initialized by + * the low-level driver if needed.) + * @cancel: If the subdevice supports asynchronous acquisition commands, this + * points to a handler used to terminate a running command. (Initialized + * by the low-level driver.) + * @buf_change: If the subdevice supports asynchronous acquisition commands, + * this is an optional pointer to a handler that is called when the data + * buffer for handling asynchronous commands is allocated or reallocated. + * (Initialized by the low-level driver if needed.) + * @munge: If the subdevice supports asynchronous acquisition commands and + * uses DMA to transfer data from the hardware to the acquisition buffer, + * this points to a function used to "munge" the data values from the + * hardware into the format expected by COMEDI. (Initialized by the + * low-level driver if needed.) + * @async_dma_dir: If the subdevice supports asynchronous acquisition commands + * and uses DMA to transfer data from the hardware to the acquisition + * buffer, this sets the DMA direction for the buffer. (initialized to + * %DMA_NONE by comedi_alloc_subdevices() and changed by the low-level + * driver if necessary.) + * @state: Handy bit-mask indicating the output states for a DIO or digital + * output subdevice with no more than 32 channels. (Initialized by the + * low-level driver.) + * @class_dev: If the subdevice supports asynchronous acquisition commands, + * this points to a sysfs comediX_subdY device where X is the minor device + * number of the COMEDI device and Y is the subdevice number. The minor + * device number for the sysfs device is allocated dynamically in the + * range 48 to 255. This is used to allow the COMEDI device to be opened + * with a different default read or write subdevice. (Allocated during + * post-configuration if needed.) + * @minor: If @class_dev is set, this is its dynamically allocated minor + * device number. (Set during post-configuration if necessary.) + * @readback: Optional pointer to memory allocated by + * comedi_alloc_subdev_readback() used to hold the values written to + * analog output channels so they can be read back. The storage is + * automatically freed after the low-level driver's "detach" handler is + * called for the device. (Initialized by the low-level driver.) + * + * This is the main control structure for a COMEDI subdevice. If the subdevice + * supports asynchronous acquisition commands, additional information is stored + * in the &struct comedi_async pointed to by @async. + * + * Most of the subdevice is initialized by the low-level driver's "attach" or + * "auto_attach" handlers but parts of it are initialized by + * comedi_alloc_subdevices(), and other parts are initialized during + * post-configuration on return from that handler. + * + * A low-level driver that sets @insn_bits for a digital input, digital output, + * or DIO subdevice may leave @insn_read and @insn_write uninitialized, in + * which case they will be set to a default handler during post-configuration + * that uses @insn_bits to emulate the %INSN_READ and %INSN_WRITE instructions. + */ struct comedi_subdevice { struct comedi_device *device; int index; @@ -49,7 +174,7 @@ struct comedi_subdevice { void *lock; void *busy; unsigned runflags; - spinlock_t spin_lock; + spinlock_t spin_lock; /* generic spin-lock for COMEDI and drivers */ unsigned int io_bits; @@ -92,11 +217,40 @@ struct comedi_subdevice { unsigned int *readback; }; +/** + * struct comedi_buf_page - Describe a page of a COMEDI buffer + * @virt_addr: Kernel address of page. + * @dma_addr: DMA address of page if in DMA coherent memory. + */ struct comedi_buf_page { void *virt_addr; dma_addr_t dma_addr; }; +/** + * struct comedi_buf_map - Describe pages in a COMEDI buffer + * @dma_hw_dev: Low-level hardware &struct device pointer copied from the + * COMEDI device's hw_dev member. + * @page_list: Pointer to array of &struct comedi_buf_page, one for each + * page in the buffer. + * @n_pages: Number of pages in the buffer. + * @dma_dir: DMA direction used to allocate pages of DMA coherent memory, + * or %DMA_NONE if pages allocated from regular memory. + * @refcount: &struct kref reference counter used to free the buffer. + * + * A COMEDI data buffer is allocated as individual pages, either in + * conventional memory or DMA coherent memory, depending on the attached, + * low-level hardware device. (The buffer pages also get mapped into the + * kernel's contiguous virtual address space pointed to by the 'prealloc_buf' + * member of &struct comedi_async.) + * + * The buffer is normally freed when the COMEDI device is detached from the + * low-level driver (which may happen due to device removal), but if it happens + * to be mmapped at the time, the pages cannot be freed until the buffer has + * been munmapped. That is what the reference counter is for. (The virtual + * address space pointed by 'prealloc_buf' is freed when the COMEDI device is + * detached.) + */ struct comedi_buf_map { struct device *dma_hw_dev; struct comedi_buf_page *page_list; @@ -106,61 +260,66 @@ struct comedi_buf_map { }; /** - * struct comedi_async - control data for asynchronous comedi commands - * @prealloc_buf: preallocated buffer - * @prealloc_bufsz: buffer size (in bytes) - * @buf_map: map of buffer pages - * @max_bufsize: maximum buffer size (in bytes) - * @buf_write_count: "write completed" count (in bytes, modulo 2**32) - * @buf_write_alloc_count: "allocated for writing" count (in bytes, - * modulo 2**32) - * @buf_read_count: "read completed" count (in bytes, modulo 2**32) - * @buf_read_alloc_count: "allocated for reading" count (in bytes, - * modulo 2**32) - * @buf_write_ptr: buffer position for writer - * @buf_read_ptr: buffer position for reader - * @cur_chan: current position in chanlist for scan (for those - * drivers that use it) - * @scans_done: the number of scans completed (COMEDI_CB_EOS) - * @scan_progress: amount received or sent for current scan (in bytes) - * @munge_chan: current position in chanlist for "munging" - * @munge_count: "munge" count (in bytes, modulo 2**32) - * @munge_ptr: buffer position for "munging" - * @events: bit-vector of events that have occurred - * @cmd: details of comedi command in progress - * @wait_head: task wait queue for file reader or writer - * @cb_mask: bit-vector of events that should wake waiting tasks - * @inttrig: software trigger function for command, or NULL + * struct comedi_async - Control data for asynchronous COMEDI commands + * @prealloc_buf: Kernel virtual address of allocated acquisition buffer. + * @prealloc_bufsz: Buffer size (in bytes). + * @buf_map: Map of buffer pages. + * @max_bufsize: Maximum allowed buffer size (in bytes). + * @buf_write_count: "Write completed" count (in bytes, modulo 2**32). + * @buf_write_alloc_count: "Allocated for writing" count (in bytes, + * modulo 2**32). + * @buf_read_count: "Read completed" count (in bytes, modulo 2**32). + * @buf_read_alloc_count: "Allocated for reading" count (in bytes, + * modulo 2**32). + * @buf_write_ptr: Buffer position for writer. + * @buf_read_ptr: Buffer position for reader. + * @cur_chan: Current position in chanlist for scan (for those drivers that + * use it). + * @scans_done: The number of scans completed. + * @scan_progress: Amount received or sent for current scan (in bytes). + * @munge_chan: Current position in chanlist for "munging". + * @munge_count: "Munge" count (in bytes, modulo 2**32). + * @munge_ptr: Buffer position for "munging". + * @events: Bit-vector of events that have occurred. + * @cmd: Details of comedi command in progress. + * @wait_head: Task wait queue for file reader or writer. + * @cb_mask: Bit-vector of events that should wake waiting tasks. + * @inttrig: Software trigger function for command, or NULL. * * Note about the ..._count and ..._ptr members: * * Think of the _Count values being integers of unlimited size, indexing * into a buffer of infinite length (though only an advancing portion - * of the buffer of fixed length prealloc_bufsz is accessible at any time). - * Then: + * of the buffer of fixed length prealloc_bufsz is accessible at any + * time). Then: * * Buf_Read_Count <= Buf_Read_Alloc_Count <= Munge_Count <= * Buf_Write_Count <= Buf_Write_Alloc_Count <= * (Buf_Read_Count + prealloc_bufsz) * - * (Those aren't the actual members, apart from prealloc_bufsz.) When - * the buffer is reset, those _Count values start at 0 and only increase - * in value, maintaining the above inequalities until the next time the - * buffer is reset. The buffer is divided into the following regions by - * the inequalities: + * (Those aren't the actual members, apart from prealloc_bufsz.) When the + * buffer is reset, those _Count values start at 0 and only increase in value, + * maintaining the above inequalities until the next time the buffer is + * reset. The buffer is divided into the following regions by the inequalities: * * [0, Buf_Read_Count): * old region no longer accessible + * * [Buf_Read_Count, Buf_Read_Alloc_Count): * filled and munged region allocated for reading but not yet read + * * [Buf_Read_Alloc_Count, Munge_Count): * filled and munged region not yet allocated for reading + * * [Munge_Count, Buf_Write_Count): * filled region not yet munged + * * [Buf_Write_Count, Buf_Write_Alloc_Count): * unfilled region allocated for writing but not yet written + * * [Buf_Write_Alloc_Count, Buf_Read_Count + prealloc_bufsz): * unfilled region not yet allocated for writing + * * [Buf_Read_Count + prealloc_bufsz, infinity): * unfilled region not yet accessible * @@ -216,43 +375,153 @@ struct comedi_async { }; /** - * comedi_async callback "events" + * enum comedi_cb - &struct comedi_async callback "events" * @COMEDI_CB_EOS: end-of-scan * @COMEDI_CB_EOA: end-of-acquisition/output * @COMEDI_CB_BLOCK: data has arrived, wakes up read() / write() * @COMEDI_CB_EOBUF: DEPRECATED: end of buffer * @COMEDI_CB_ERROR: card error during acquisition * @COMEDI_CB_OVERFLOW: buffer overflow/underflow - * * @COMEDI_CB_ERROR_MASK: events that indicate an error has occurred * @COMEDI_CB_CANCEL_MASK: events that will cancel an async command */ -#define COMEDI_CB_EOS (1 << 0) -#define COMEDI_CB_EOA (1 << 1) -#define COMEDI_CB_BLOCK (1 << 2) -#define COMEDI_CB_EOBUF (1 << 3) -#define COMEDI_CB_ERROR (1 << 4) -#define COMEDI_CB_OVERFLOW (1 << 5) - -#define COMEDI_CB_ERROR_MASK (COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW) -#define COMEDI_CB_CANCEL_MASK (COMEDI_CB_EOA | COMEDI_CB_ERROR_MASK) +enum comedi_cb { + COMEDI_CB_EOS = BIT(0), + COMEDI_CB_EOA = BIT(1), + COMEDI_CB_BLOCK = BIT(2), + COMEDI_CB_EOBUF = BIT(3), + COMEDI_CB_ERROR = BIT(4), + COMEDI_CB_OVERFLOW = BIT(5), + /* masks */ + COMEDI_CB_ERROR_MASK = (COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW), + COMEDI_CB_CANCEL_MASK = (COMEDI_CB_EOA | COMEDI_CB_ERROR_MASK) +}; +/** + * struct comedi_driver - COMEDI driver registration + * @driver_name: Name of driver. + * @module: Owning module. + * @attach: The optional "attach" handler for manually configured COMEDI + * devices. + * @detach: The "detach" handler for deconfiguring COMEDI devices. + * @auto_attach: The optional "auto_attach" handler for automatically + * configured COMEDI devices. + * @num_names: Optional number of "board names" supported. + * @board_name: Optional pointer to a pointer to a board name. The pointer + * to a board name is embedded in an element of a driver-defined array + * of static, read-only board type information. + * @offset: Optional size of each element of the driver-defined array of + * static, read-only board type information, i.e. the offset between each + * pointer to a board name. + * + * This is used with comedi_driver_register() and comedi_driver_unregister() to + * register and unregister a low-level COMEDI driver with the COMEDI core. + * + * If @num_names is non-zero, @board_name should be non-NULL, and @offset + * should be at least sizeof(*board_name). These are used by the handler for + * the %COMEDI_DEVCONFIG ioctl to match a hardware device and its driver by + * board name. If @num_names is zero, the %COMEDI_DEVCONFIG ioctl matches a + * hardware device and its driver by driver name. This is only useful if the + * @attach handler is set. If @num_names is non-zero, the driver's @attach + * handler will be called with the COMEDI device structure's board_ptr member + * pointing to the matched pointer to a board name within the driver's private + * array of static, read-only board type information. + */ struct comedi_driver { - struct comedi_driver *next; - + /* private: */ + struct comedi_driver *next; /* Next in list of COMEDI drivers. */ + /* public: */ const char *driver_name; struct module *module; int (*attach)(struct comedi_device *, struct comedi_devconfig *); void (*detach)(struct comedi_device *); int (*auto_attach)(struct comedi_device *, unsigned long); - - /* number of elements in board_name and board_id arrays */ unsigned int num_names; const char *const *board_name; - /* offset in bytes from one board name pointer to the next */ int offset; }; +/** + * struct comedi_device - Working data for a COMEDI device + * @use_count: Number of open file objects. + * @driver: Low-level COMEDI driver attached to this COMEDI device. + * @pacer: Optional pointer to a dynamically allocated acquisition pacer + * control. It is freed automatically after the COMEDI device is + * detached from the low-level driver. + * @private: Optional pointer to private data allocated by the low-level + * driver. It is freed automatically after the COMEDI device is + * detached from the low-level driver. + * @class_dev: Sysfs comediX device. + * @minor: Minor device number of COMEDI char device (0-47). + * @detach_count: Counter incremented every time the COMEDI device is detached. + * Used for checking a previous attachment is still valid. + * @hw_dev: Optional pointer to the low-level hardware &struct device. It is + * required for automatically configured COMEDI devices and optional for + * COMEDI devices configured by the %COMEDI_DEVCONFIG ioctl, although + * the bus-specific COMEDI functions only work if it is set correctly. + * It is also passed to dma_alloc_coherent() for COMEDI subdevices that + * have their 'async_dma_dir' member set to something other than + * %DMA_NONE. + * @board_name: Pointer to a COMEDI board name or a COMEDI driver name. When + * the low-level driver's "attach" handler is called by the handler for + * the %COMEDI_DEVCONFIG ioctl, it either points to a matched board name + * string if the 'num_names' member of the &struct comedi_driver is + * non-zero, otherwise it points to the low-level driver name string. + * When the low-lever driver's "auto_attach" handler is called for an + * automatically configured COMEDI device, it points to the low-level + * driver name string. The low-level driver is free to change it in its + * "attach" or "auto_attach" handler if it wishes. + * @board_ptr: Optional pointer to private, read-only board type information in + * the low-level driver. If the 'num_names' member of the &struct + * comedi_driver is non-zero, the handler for the %COMEDI_DEVCONFIG ioctl + * will point it to a pointer to a matched board name string within the + * driver's private array of static, read-only board type information when + * calling the driver's "attach" handler. The low-level driver is free to + * change it. + * @attached: Flag indicating that the COMEDI device is attached to a low-level + * driver. + * @ioenabled: Flag used to indicate that a PCI device has been enabled and + * its regions requested. + * @spinlock: Generic spin-lock for use by the low-level driver. + * @mutex: Generic mutex for use by the COMEDI core module. + * @attach_lock: &struct rw_semaphore used to guard against the COMEDI device + * being detached while an operation is in progress. The down_write() + * operation is only allowed while @mutex is held and is used when + * changing @attached and @detach_count and calling the low-level driver's + * "detach" handler. The down_read() operation is generally used without + * holding @mutex. + * @refcount: &struct kref reference counter for freeing COMEDI device. + * @n_subdevices: Number of COMEDI subdevices allocated by the low-level + * driver for this device. + * @subdevices: Dynamically allocated array of COMEDI subdevices. + * @mmio: Optional pointer to a remapped MMIO region set by the low-level + * driver. + * @iobase: Optional base of an I/O port region requested by the low-level + * driver. + * @iolen: Length of I/O port region requested at @iobase. + * @irq: Optional IRQ number requested by the low-level driver. + * @read_subdev: Optional pointer to a default COMEDI subdevice operated on by + * the read() file operation. Set by the low-level driver. + * @write_subdev: Optional pointer to a default COMEDI subdevice operated on by + * the write() file operation. Set by the low-level driver. + * @async_queue: Storage for fasync_helper(). + * @open: Optional pointer to a function set by the low-level driver to be + * called when @use_count changes from 0 to 1. + * @close: Optional pointer to a function set by the low-level driver to be + * called when @use_count changed from 1 to 0. + * + * This is the main control data structure for a COMEDI device (as far as the + * COMEDI core is concerned). There are two groups of COMEDI devices - + * "legacy" devices that are configured by the handler for the + * %COMEDI_DEVCONFIG ioctl, and automatically configured devices resulting + * from a call to comedi_auto_config() as a result of a bus driver probe in + * a low-level COMEDI driver. The "legacy" COMEDI devices are allocated + * during module initialization if the "comedi_num_legacy_minors" module + * parameter is non-zero and use minor device numbers from 0 to + * comedi_num_legacy_minors minus one. The automatically configured COMEDI + * devices are allocated on demand and use minor device numbers from + * comedi_num_legacy_minors to 47. + */ struct comedi_device { int use_count; struct comedi_driver *driver; @@ -262,17 +531,14 @@ struct comedi_device { struct device *class_dev; int minor; unsigned int detach_count; - /* hw_dev is passed to dma_alloc_coherent when allocating async buffers - * for subdevices that have async_dma_dir set to something other than - * DMA_NONE */ struct device *hw_dev; const char *board_name; const void *board_ptr; bool attached:1; bool ioenabled:1; - spinlock_t spinlock; - struct mutex mutex; + spinlock_t spinlock; /* generic spin-lock for low-level driver */ + struct mutex mutex; /* generic mutex for COMEDI core */ struct rw_semaphore attach_lock; struct kref refcount; @@ -303,26 +569,10 @@ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s); struct comedi_device *comedi_dev_get_from_minor(unsigned minor); int comedi_dev_put(struct comedi_device *dev); -/** - * comedi_subdevice "runflags" - * @COMEDI_SRF_RT: DEPRECATED: command is running real-time - * @COMEDI_SRF_ERROR: indicates an COMEDI_CB_ERROR event has occurred - * since the last command was started - * @COMEDI_SRF_RUNNING: command is running - * @COMEDI_SRF_FREE_SPRIV: free s->private on detach - * - * @COMEDI_SRF_BUSY_MASK: runflags that indicate the subdevice is "busy" - */ -#define COMEDI_SRF_RT BIT(1) -#define COMEDI_SRF_ERROR BIT(2) -#define COMEDI_SRF_RUNNING BIT(27) -#define COMEDI_SRF_FREE_SPRIV BIT(31) - -#define COMEDI_SRF_BUSY_MASK (COMEDI_SRF_ERROR | COMEDI_SRF_RUNNING) - bool comedi_is_subdevice_running(struct comedi_subdevice *s); void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size); +void comedi_set_spriv_auto_free(struct comedi_subdevice *s); int comedi_check_chanlist(struct comedi_subdevice *s, int n, @@ -330,12 +580,12 @@ int comedi_check_chanlist(struct comedi_subdevice *s, /* range stuff */ -#define RANGE(a, b) {(a)*1e6, (b)*1e6, 0} -#define RANGE_ext(a, b) {(a)*1e6, (b)*1e6, RF_EXTERNAL} -#define RANGE_mA(a, b) {(a)*1e6, (b)*1e6, UNIT_mA} -#define RANGE_unitless(a, b) {(a)*1e6, (b)*1e6, 0} -#define BIP_RANGE(a) {-(a)*1e6, (a)*1e6, 0} -#define UNI_RANGE(a) {0, (a)*1e6, 0} +#define RANGE(a, b) {(a) * 1e6, (b) * 1e6, 0} +#define RANGE_ext(a, b) {(a) * 1e6, (b) * 1e6, RF_EXTERNAL} +#define RANGE_mA(a, b) {(a) * 1e6, (b) * 1e6, UNIT_mA} +#define RANGE_unitless(a, b) {(a) * 1e6, (b) * 1e6, 0} +#define BIP_RANGE(a) {-(a) * 1e6, (a) * 1e6, 0} +#define UNI_RANGE(a) {0, (a) * 1e6, 0} extern const struct comedi_lrange range_bipolar10; extern const struct comedi_lrange range_bipolar5; @@ -356,29 +606,101 @@ extern const struct comedi_lrange range_unknown; #define GCC_ZERO_LENGTH_ARRAY 0 #endif +/** + * struct comedi_lrange - Describes a COMEDI range table + * @length: Number of entries in the range table. + * @range: Array of &struct comedi_krange, one for each range. + * + * Each element of @range[] describes the minimum and maximum physical range + * range and the type of units. Typically, the type of unit is %UNIT_volt + * (i.e. volts) and the minimum and maximum are in millionths of a volt. + * There may also be a flag that indicates the minimum and maximum are merely + * scale factors for an unknown, external reference. + */ struct comedi_lrange { int length; struct comedi_krange range[GCC_ZERO_LENGTH_ARRAY]; }; +/** + * comedi_range_is_bipolar() - Test if subdevice range is bipolar + * @s: COMEDI subdevice. + * @range: Index of range within a range table. + * + * Tests whether a range is bipolar by checking whether its minimum value + * is negative. + * + * Assumes @range is valid. Does not work for subdevices using a + * channel-specific range table list. + * + * Return: + * %true if the range is bipolar. + * %false if the range is unipolar. + */ static inline bool comedi_range_is_bipolar(struct comedi_subdevice *s, unsigned int range) { return s->range_table->range[range].min < 0; } +/** + * comedi_range_is_unipolar() - Test if subdevice range is unipolar + * @s: COMEDI subdevice. + * @range: Index of range within a range table. + * + * Tests whether a range is unipolar by checking whether its minimum value + * is at least 0. + * + * Assumes @range is valid. Does not work for subdevices using a + * channel-specific range table list. + * + * Return: + * %true if the range is unipolar. + * %false if the range is bipolar. + */ static inline bool comedi_range_is_unipolar(struct comedi_subdevice *s, unsigned int range) { return s->range_table->range[range].min >= 0; } +/** + * comedi_range_is_external() - Test if subdevice range is external + * @s: COMEDI subdevice. + * @range: Index of range within a range table. + * + * Tests whether a range is externally reference by checking whether its + * %RF_EXTERNAL flag is set. + * + * Assumes @range is valid. Does not work for subdevices using a + * channel-specific range table list. + * + * Return: + * %true if the range is external. + * %false if the range is internal. + */ static inline bool comedi_range_is_external(struct comedi_subdevice *s, unsigned int range) { return !!(s->range_table->range[range].flags & RF_EXTERNAL); } +/** + * comedi_chan_range_is_bipolar() - Test if channel-specific range is bipolar + * @s: COMEDI subdevice. + * @chan: The channel number. + * @range: Index of range within a range table. + * + * Tests whether a range is bipolar by checking whether its minimum value + * is negative. + * + * Assumes @chan and @range are valid. Only works for subdevices with a + * channel-specific range table list. + * + * Return: + * %true if the range is bipolar. + * %false if the range is unipolar. + */ static inline bool comedi_chan_range_is_bipolar(struct comedi_subdevice *s, unsigned int chan, unsigned int range) @@ -386,6 +708,22 @@ static inline bool comedi_chan_range_is_bipolar(struct comedi_subdevice *s, return s->range_table_list[chan]->range[range].min < 0; } +/** + * comedi_chan_range_is_unipolar() - Test if channel-specific range is unipolar + * @s: COMEDI subdevice. + * @chan: The channel number. + * @range: Index of range within a range table. + * + * Tests whether a range is unipolar by checking whether its minimum value + * is at least 0. + * + * Assumes @chan and @range are valid. Only works for subdevices with a + * channel-specific range table list. + * + * Return: + * %true if the range is unipolar. + * %false if the range is bipolar. + */ static inline bool comedi_chan_range_is_unipolar(struct comedi_subdevice *s, unsigned int chan, unsigned int range) @@ -393,6 +731,22 @@ static inline bool comedi_chan_range_is_unipolar(struct comedi_subdevice *s, return s->range_table_list[chan]->range[range].min >= 0; } +/** + * comedi_chan_range_is_external() - Test if channel-specific range is external + * @s: COMEDI subdevice. + * @chan: The channel number. + * @range: Index of range within a range table. + * + * Tests whether a range is externally reference by checking whether its + * %RF_EXTERNAL flag is set. + * + * Assumes @chan and @range are valid. Only works for subdevices with a + * channel-specific range table list. + * + * Return: + * %true if the range is bipolar. + * %false if the range is unipolar. + */ static inline bool comedi_chan_range_is_external(struct comedi_subdevice *s, unsigned int chan, unsigned int range) @@ -400,7 +754,16 @@ static inline bool comedi_chan_range_is_external(struct comedi_subdevice *s, return !!(s->range_table_list[chan]->range[range].flags & RF_EXTERNAL); } -/* munge between offset binary and two's complement values */ +/** + * comedi_offset_munge() - Convert between offset binary and 2's complement + * @s: COMEDI subdevice. + * @val: Value to be converted. + * + * Toggles the highest bit of a sample value to toggle between offset binary + * and 2's complement. Assumes that @s->maxdata is a power of 2 minus 1. + * + * Return: The converted value. + */ static inline unsigned int comedi_offset_munge(struct comedi_subdevice *s, unsigned int val) { @@ -408,13 +771,13 @@ static inline unsigned int comedi_offset_munge(struct comedi_subdevice *s, } /** - * comedi_bytes_per_sample - determine subdevice sample size - * @s: comedi_subdevice struct + * comedi_bytes_per_sample() - Determine subdevice sample size + * @s: COMEDI subdevice. * * The sample size will be 4 (sizeof int) or 2 (sizeof short) depending on - * whether the SDF_LSAMPL subdevice flag is set or not. + * whether the %SDF_LSAMPL subdevice flag is set or not. * - * Returns the subdevice sample size. + * Return: The subdevice sample size. */ static inline unsigned int comedi_bytes_per_sample(struct comedi_subdevice *s) { @@ -422,15 +785,15 @@ static inline unsigned int comedi_bytes_per_sample(struct comedi_subdevice *s) } /** - * comedi_sample_shift - determine log2 of subdevice sample size - * @s: comedi_subdevice struct + * comedi_sample_shift() - Determine log2 of subdevice sample size + * @s: COMEDI subdevice. * * The sample size will be 4 (sizeof int) or 2 (sizeof short) depending on - * whether the SDF_LSAMPL subdevice flag is set or not. The log2 of the + * whether the %SDF_LSAMPL subdevice flag is set or not. The log2 of the * sample size will be 2 or 1 and can be used as the right operand of a * bit-shift operator to multiply or divide something by the sample size. * - * Returns log2 of the subdevice sample size. + * Return: log2 of the subdevice sample size. */ static inline unsigned int comedi_sample_shift(struct comedi_subdevice *s) { @@ -438,11 +801,11 @@ static inline unsigned int comedi_sample_shift(struct comedi_subdevice *s) } /** - * comedi_bytes_to_samples - converts a number of bytes to a number of samples - * @s: comedi_subdevice struct - * @nbytes: number of bytes + * comedi_bytes_to_samples() - Convert a number of bytes to a number of samples + * @s: COMEDI subdevice. + * @nbytes: Number of bytes * - * Returns the number of bytes divided by the subdevice sample size. + * Return: The number of bytes divided by the subdevice sample size. */ static inline unsigned int comedi_bytes_to_samples(struct comedi_subdevice *s, unsigned int nbytes) @@ -451,12 +814,12 @@ static inline unsigned int comedi_bytes_to_samples(struct comedi_subdevice *s, } /** - * comedi_samples_to_bytes - converts a number of samples to a number of bytes - * @s: comedi_subdevice struct - * @nsamples: number of samples + * comedi_samples_to_bytes() - Convert a number of samples to a number of bytes + * @s: COMEDI subdevice. + * @nsamples: Number of samples. * - * Returns the number of samples multiplied by the subdevice sample size. - * Does not check for arithmetic overflow. + * Return: The number of samples multiplied by the subdevice sample size. + * (Does not check for arithmetic overflow.) */ static inline unsigned int comedi_samples_to_bytes(struct comedi_subdevice *s, unsigned int nsamples) @@ -465,14 +828,18 @@ static inline unsigned int comedi_samples_to_bytes(struct comedi_subdevice *s, } /** - * comedi_check_trigger_src() - trivially validate a comedi_cmd trigger source - * @src: pointer to the trigger source to validate - * @flags: bitmask of valid TRIG_* for the trigger + * comedi_check_trigger_src() - Trivially validate a comedi_cmd trigger source + * @src: Pointer to the trigger source to validate. + * @flags: Bitmask of valid %TRIG_* for the trigger. * * This is used in "step 1" of the do_cmdtest functions of comedi drivers - * to vaildate the comedi_cmd triggers. The mask of the @src against the + * to validate the comedi_cmd triggers. The mask of the @src against the * @flags allows the userspace comedilib to pass all the comedi_cmd - * triggers as TRIG_ANY and get back a bitmask of the valid trigger sources. + * triggers as %TRIG_ANY and get back a bitmask of the valid trigger sources. + * + * Return: + * 0 if trigger sources in *@src are all supported. + * -EINVAL if any trigger source in *@src is unsupported. */ static inline int comedi_check_trigger_src(unsigned int *src, unsigned int flags) @@ -486,8 +853,12 @@ static inline int comedi_check_trigger_src(unsigned int *src, } /** - * comedi_check_trigger_is_unique() - make sure a trigger source is unique - * @src: the trigger source to check + * comedi_check_trigger_is_unique() - Make sure a trigger source is unique + * @src: The trigger source to check. + * + * Return: + * 0 if no more than one trigger source is set. + * -EINVAL if more than one trigger source is set. */ static inline int comedi_check_trigger_is_unique(unsigned int src) { @@ -498,9 +869,15 @@ static inline int comedi_check_trigger_is_unique(unsigned int src) } /** - * comedi_check_trigger_arg_is() - trivially validate a trigger argument - * @arg: pointer to the trigger arg to validate - * @val: the value the argument should be + * comedi_check_trigger_arg_is() - Trivially validate a trigger argument + * @arg: Pointer to the trigger arg to validate. + * @val: The value the argument should be. + * + * Forces *@arg to be @val. + * + * Return: + * 0 if *@arg was already @val. + * -EINVAL if *@arg differed from @val. */ static inline int comedi_check_trigger_arg_is(unsigned int *arg, unsigned int val) @@ -513,9 +890,15 @@ static inline int comedi_check_trigger_arg_is(unsigned int *arg, } /** - * comedi_check_trigger_arg_min() - trivially validate a trigger argument - * @arg: pointer to the trigger arg to validate - * @val: the minimum value the argument should be + * comedi_check_trigger_arg_min() - Trivially validate a trigger argument min + * @arg: Pointer to the trigger arg to validate. + * @val: The minimum value the argument should be. + * + * Forces *@arg to be at least @val, setting it to @val if necessary. + * + * Return: + * 0 if *@arg was already at least @val. + * -EINVAL if *@arg was less than @val. */ static inline int comedi_check_trigger_arg_min(unsigned int *arg, unsigned int val) @@ -528,9 +911,15 @@ static inline int comedi_check_trigger_arg_min(unsigned int *arg, } /** - * comedi_check_trigger_arg_max() - trivially validate a trigger argument - * @arg: pointer to the trigger arg to validate - * @val: the maximum value the argument should be + * comedi_check_trigger_arg_max() - Trivially validate a trigger argument max + * @arg: Pointer to the trigger arg to validate. + * @val: The maximum value the argument should be. + * + * Forces *@arg to be no more than @val, setting it to @val if necessary. + * + * Return: + * 0 if*@arg was already no more than @val. + * -EINVAL if *@arg was greater than @val. */ static inline int comedi_check_trigger_arg_max(unsigned int *arg, unsigned int val) @@ -550,6 +939,16 @@ static inline int comedi_check_trigger_arg_max(unsigned int *arg, */ int comedi_set_hw_dev(struct comedi_device *dev, struct device *hw_dev); +/** + * comedi_buf_n_bytes_ready - Determine amount of unread data in buffer + * @s: COMEDI subdevice. + * + * Determines the number of bytes of unread data in the asynchronous + * acquisition data buffer for a subdevice. The data in question might not + * have been fully "munged" yet. + * + * Returns: The amount of unread data in bytes. + */ static inline unsigned int comedi_buf_n_bytes_ready(struct comedi_subdevice *s) { return s->async->buf_write_count - s->async->buf_read_count; diff --git a/kernel/drivers/staging/comedi/drivers.c b/kernel/drivers/staging/comedi/drivers.c index 57dcffe00..b63dd2ef7 100644 --- a/kernel/drivers/staging/comedi/drivers.c +++ b/kernel/drivers/staging/comedi/drivers.c @@ -1,37 +1,29 @@ /* - module/drivers.c - functions for manipulating drivers - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org> - Copyright (C) 2002 Frank Mori Hess <fmhess@users.sourceforge.net> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + * module/drivers.c + * functions for manipulating drivers + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org> + * Copyright (C) 2002 Frank Mori Hess <fmhess@users.sourceforge.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. */ #include <linux/device.h> #include <linux/module.h> #include <linux/errno.h> -#include <linux/kconfig.h> #include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/fcntl.h> #include <linux/ioport.h> -#include <linux/mm.h> #include <linux/slab.h> -#include <linux/highmem.h> /* for SuSE brokenness */ -#include <linux/vmalloc.h> -#include <linux/cdev.h> -#include <linux/dma-mapping.h> -#include <linux/io.h> +#include <linux/dma-direction.h> #include <linux/interrupt.h> #include <linux/firmware.h> @@ -42,6 +34,28 @@ struct comedi_driver *comedi_drivers; /* protects access to comedi_drivers */ DEFINE_MUTEX(comedi_drivers_list_lock); +/** + * comedi_set_hw_dev() - Set hardware device associated with COMEDI device + * @dev: COMEDI device. + * @hw_dev: Hardware device. + * + * For automatically configured COMEDI devices (resulting from a call to + * comedi_auto_config() or one of its wrappers from the low-level COMEDI + * driver), comedi_set_hw_dev() is called automatically by the COMEDI core + * to associate the COMEDI device with the hardware device. It can also be + * called directly by "legacy" low-level COMEDI drivers that rely on the + * %COMEDI_DEVCONFIG ioctl to configure the hardware as long as the hardware + * has a &struct device. + * + * If @dev->hw_dev is NULL, it gets a reference to @hw_dev and sets + * @dev->hw_dev, otherwise, it does nothing. Calling it multiple times + * with the same hardware device is not considered an error. If it gets + * a reference to the hardware device, it will be automatically 'put' when + * the device is detached from COMEDI. + * + * Returns 0 if @dev->hw_dev was NULL or the same as @hw_dev, otherwise + * returns -EEXIST. + */ int comedi_set_hw_dev(struct comedi_device *dev, struct device *hw_dev) { if (hw_dev == dev->hw_dev) @@ -60,9 +74,15 @@ static void comedi_clear_hw_dev(struct comedi_device *dev) } /** - * comedi_alloc_devpriv() - Allocate memory for the device private data. - * @dev: comedi_device struct - * @size: size of the memory to allocate + * comedi_alloc_devpriv() - Allocate memory for the device private data + * @dev: COMEDI device. + * @size: Size of the memory to allocate. + * + * The allocated memory is zero-filled. @dev->private points to it on + * return. The memory will be automatically freed when the COMEDI device is + * "detached". + * + * Returns a pointer to the allocated memory, or NULL on failure. */ void *comedi_alloc_devpriv(struct comedi_device *dev, size_t size) { @@ -71,6 +91,18 @@ void *comedi_alloc_devpriv(struct comedi_device *dev, size_t size) } EXPORT_SYMBOL_GPL(comedi_alloc_devpriv); +/** + * comedi_alloc_subdevices() - Allocate subdevices for COMEDI device + * @dev: COMEDI device. + * @num_subdevices: Number of subdevices to allocate. + * + * Allocates and initializes an array of &struct comedi_subdevice for the + * COMEDI device. If successful, sets @dev->subdevices to point to the + * first one and @dev->n_subdevices to the number. + * + * Returns 0 on success, -EINVAL if @num_subdevices is < 1, or -ENOMEM if + * failed to allocate the memory. + */ int comedi_alloc_subdevices(struct comedi_device *dev, int num_subdevices) { struct comedi_subdevice *s; @@ -98,8 +130,22 @@ int comedi_alloc_subdevices(struct comedi_device *dev, int num_subdevices) EXPORT_SYMBOL_GPL(comedi_alloc_subdevices); /** - * comedi_alloc_subdev_readback() - Allocate memory for the subdevice readback. - * @s: comedi_subdevice struct + * comedi_alloc_subdev_readback() - Allocate memory for the subdevice readback + * @s: COMEDI subdevice. + * + * This is called by low-level COMEDI drivers to allocate an array to record + * the last values written to a subdevice's analog output channels (at least + * by the %INSN_WRITE instruction), to allow them to be read back by an + * %INSN_READ instruction. It also provides a default handler for the + * %INSN_READ instruction unless one has already been set. + * + * On success, @s->readback points to the first element of the array, which + * is zero-filled. The low-level driver is responsible for updating its + * contents. @s->insn_read will be set to comedi_readback_insn_read() + * unless it is already non-NULL. + * + * Returns 0 on success, -EINVAL if the subdevice has no channels, or + * -ENOMEM on allocation failure. */ int comedi_alloc_subdev_readback(struct comedi_subdevice *s) { @@ -125,7 +171,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev) if (dev->subdevices) { for (i = 0; i < dev->n_subdevices; i++) { s = &dev->subdevices[i]; - if (s->runflags & COMEDI_SRF_FREE_SPRIV) + if (comedi_can_auto_free_spriv(s)) kfree(s->private); comedi_free_subdevice_minor(s); if (s->async) { @@ -182,10 +228,20 @@ int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s, /** * comedi_readback_insn_read() - A generic (*insn_read) for subdevice readback. - * @dev: comedi_device struct - * @s: comedi_subdevice struct - * @insn: comedi_insn struct - * @data: pointer to return the readback data + * @dev: COMEDI device. + * @s: COMEDI subdevice. + * @insn: COMEDI instruction. + * @data: Pointer to return the readback data. + * + * Handles the %INSN_READ instruction for subdevices that use the readback + * array allocated by comedi_alloc_subdev_readback(). It may be used + * directly as the subdevice's handler (@s->insn_read) or called via a + * wrapper. + * + * @insn->n is normally 1, which will read a single value. If higher, the + * same element of the readback array will be read multiple times. + * + * Returns @insn->n on success, or -EINVAL if @s->readback is NULL. */ int comedi_readback_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, @@ -206,12 +262,21 @@ int comedi_readback_insn_read(struct comedi_device *dev, EXPORT_SYMBOL_GPL(comedi_readback_insn_read); /** - * comedi_timeout() - busy-wait for a driver condition to occur. - * @dev: comedi_device struct - * @s: comedi_subdevice struct - * @insn: comedi_insn struct - * @cb: callback to check for the condition - * @context: private context from the driver + * comedi_timeout() - Busy-wait for a driver condition to occur + * @dev: COMEDI device. + * @s: COMEDI subdevice. + * @insn: COMEDI instruction. + * @cb: Callback to check for the condition. + * @context: Private context from the driver. + * + * Busy-waits for up to a second (%COMEDI_TIMEOUT_MS) for the condition or + * some error (other than -EBUSY) to occur. The parameters @dev, @s, @insn, + * and @context are passed to the callback function, which returns -EBUSY to + * continue waiting or some other value to stop waiting (generally 0 if the + * condition occurred, or some error value). + * + * Returns -ETIMEDOUT if timed out, otherwise the return value from the + * callback function. */ int comedi_timeout(struct comedi_device *dev, struct comedi_subdevice *s, @@ -236,12 +301,30 @@ int comedi_timeout(struct comedi_device *dev, EXPORT_SYMBOL_GPL(comedi_timeout); /** - * comedi_dio_insn_config() - boilerplate (*insn_config) for DIO subdevices. - * @dev: comedi_device struct - * @s: comedi_subdevice struct - * @insn: comedi_insn struct - * @data: parameters for the @insn - * @mask: io_bits mask for grouped channels + * comedi_dio_insn_config() - Boilerplate (*insn_config) for DIO subdevices + * @dev: COMEDI device. + * @s: COMEDI subdevice. + * @insn: COMEDI instruction. + * @data: Instruction parameters and return data. + * @mask: io_bits mask for grouped channels, or 0 for single channel. + * + * If @mask is 0, it is replaced with a single-bit mask corresponding to the + * channel number specified by @insn->chanspec. Otherwise, @mask + * corresponds to a group of channels (which should include the specified + * channel) that are always configured together as inputs or outputs. + * + * Partially handles the %INSN_CONFIG_DIO_INPUT, %INSN_CONFIG_DIO_OUTPUTS, + * and %INSN_CONFIG_DIO_QUERY instructions. The first two update + * @s->io_bits to record the directions of the masked channels. The last + * one sets @data[1] to the current direction of the group of channels + * (%COMEDI_INPUT) or %COMEDI_OUTPUT) as recorded in @s->io_bits. + * + * The caller is responsible for updating the DIO direction in the hardware + * registers if this function returns 0. + * + * Returns 0 for a %INSN_CONFIG_DIO_INPUT or %INSN_CONFIG_DIO_OUTPUT + * instruction, @insn->n (> 0) for a %INSN_CONFIG_DIO_QUERY instruction, or + * -EINVAL for some other instruction. */ int comedi_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, @@ -276,9 +359,18 @@ int comedi_dio_insn_config(struct comedi_device *dev, EXPORT_SYMBOL_GPL(comedi_dio_insn_config); /** - * comedi_dio_update_state() - update the internal state of DIO subdevices. - * @s: comedi_subdevice struct - * @data: the channel mask and bits to update + * comedi_dio_update_state() - Update the internal state of DIO subdevices + * @s: COMEDI subdevice. + * @data: The channel mask and bits to update. + * + * Updates @s->state which holds the internal state of the outputs for DIO + * or DO subdevices (up to 32 channels). @data[0] contains a bit-mask of + * the channels to be updated. @data[1] contains a bit-mask of those + * channels to be set to '1'. The caller is responsible for updating the + * outputs in hardware according to @s->state. As a minimum, the channels + * in the returned bit-mask need to be updated. + * + * Returns @mask with non-existent channels removed. */ unsigned int comedi_dio_update_state(struct comedi_subdevice *s, unsigned int *data) @@ -298,17 +390,17 @@ unsigned int comedi_dio_update_state(struct comedi_subdevice *s, EXPORT_SYMBOL_GPL(comedi_dio_update_state); /** - * comedi_bytes_per_scan - get length of asynchronous command "scan" in bytes - * @s: comedi_subdevice struct + * comedi_bytes_per_scan() - Get length of asynchronous command "scan" in bytes + * @s: COMEDI subdevice. * * Determines the overall scan length according to the subdevice type and the * number of channels in the scan. * - * For digital input, output or input/output subdevices, samples for multiple - * channels are assumed to be packed into one or more unsigned short or - * unsigned int values according to the subdevice's SDF_LSAMPL flag. For other - * types of subdevice, samples are assumed to occupy a whole unsigned short or - * unsigned int according to the SDF_LSAMPL flag. + * For digital input, output or input/output subdevices, samples for + * multiple channels are assumed to be packed into one or more unsigned + * short or unsigned int values according to the subdevice's %SDF_LSAMPL + * flag. For other types of subdevice, samples are assumed to occupy a + * whole unsigned short or unsigned int according to the %SDF_LSAMPL flag. * * Returns the overall scan length in bytes. */ @@ -333,32 +425,12 @@ unsigned int comedi_bytes_per_scan(struct comedi_subdevice *s) } EXPORT_SYMBOL_GPL(comedi_bytes_per_scan); -/** - * comedi_nscans_left - return the number of scans left in the command - * @s: comedi_subdevice struct - * @nscans: the expected number of scans - * - * If nscans is 0, the number of scans available in the async buffer will be - * used. Otherwise the expected number of scans will be used. - * - * If the async command has a stop_src of TRIG_COUNT, the nscans will be - * checked against the number of scans left in the command. - * - * The return value will then be either the expected number of scans or the - * number of scans remaining in the command. - */ -unsigned int comedi_nscans_left(struct comedi_subdevice *s, - unsigned int nscans) +static unsigned int __comedi_nscans_left(struct comedi_subdevice *s, + unsigned int nscans) { struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; - if (nscans == 0) { - unsigned int nbytes = comedi_buf_read_n_available(s); - - nscans = nbytes / comedi_bytes_per_scan(s); - } - if (cmd->stop_src == TRIG_COUNT) { unsigned int scans_left = 0; @@ -370,15 +442,40 @@ unsigned int comedi_nscans_left(struct comedi_subdevice *s, } return nscans; } + +/** + * comedi_nscans_left() - Return the number of scans left in the command + * @s: COMEDI subdevice. + * @nscans: The expected number of scans or 0 for all available scans. + * + * If @nscans is 0, it is set to the number of scans available in the + * async buffer. + * + * If the async command has a stop_src of %TRIG_COUNT, the @nscans will be + * checked against the number of scans remaining to complete the command. + * + * The return value will then be either the expected number of scans or the + * number of scans remaining to complete the command, whichever is fewer. + */ +unsigned int comedi_nscans_left(struct comedi_subdevice *s, + unsigned int nscans) +{ + if (nscans == 0) { + unsigned int nbytes = comedi_buf_read_n_available(s); + + nscans = nbytes / comedi_bytes_per_scan(s); + } + return __comedi_nscans_left(s, nscans); +} EXPORT_SYMBOL_GPL(comedi_nscans_left); /** - * comedi_nsamples_left - return the number of samples left in the command - * @s: comedi_subdevice struct - * @nsamples: the expected number of samples + * comedi_nsamples_left() - Return the number of samples left in the command + * @s: COMEDI subdevice. + * @nsamples: The expected number of samples. * - * Returns the expected number of samples of the number of samples remaining - * in the command. + * Returns the number of samples remaining to complete the command, or the + * specified expected number of samples (@nsamples), whichever is fewer. */ unsigned int comedi_nsamples_left(struct comedi_subdevice *s, unsigned int nsamples) @@ -387,9 +484,8 @@ unsigned int comedi_nsamples_left(struct comedi_subdevice *s, struct comedi_cmd *cmd = &async->cmd; if (cmd->stop_src == TRIG_COUNT) { - /* +1 to force comedi_nscans_left() to return the scans left */ - unsigned int nscans = (nsamples / cmd->scan_end_arg) + 1; - unsigned int scans_left = comedi_nscans_left(s, nscans); + unsigned int nscans = nsamples / cmd->scan_end_arg; + unsigned int scans_left = __comedi_nscans_left(s, nscans); unsigned int scan_pos = comedi_bytes_to_samples(s, async->scan_progress); unsigned long long samples_left = 0; @@ -407,14 +503,14 @@ unsigned int comedi_nsamples_left(struct comedi_subdevice *s, EXPORT_SYMBOL_GPL(comedi_nsamples_left); /** - * comedi_inc_scan_progress - update scan progress in asynchronous command - * @s: comedi_subdevice struct - * @num_bytes: amount of data in bytes to increment scan progress + * comedi_inc_scan_progress() - Update scan progress in asynchronous command + * @s: COMEDI subdevice. + * @num_bytes: Amount of data in bytes to increment scan progress. * - * Increments the scan progress by the number of bytes specified by num_bytes. + * Increments the scan progress by the number of bytes specified by @num_bytes. * If the scan progress reaches or exceeds the scan length in bytes, reduce * it modulo the scan length in bytes and set the "end of scan" asynchronous - * event flag to be processed later. + * event flag (%COMEDI_CB_EOS) to be processed later. */ void comedi_inc_scan_progress(struct comedi_subdevice *s, unsigned int num_bytes) @@ -445,12 +541,12 @@ void comedi_inc_scan_progress(struct comedi_subdevice *s, EXPORT_SYMBOL_GPL(comedi_inc_scan_progress); /** - * comedi_handle_events - handle events and possibly stop acquisition - * @dev: comedi_device struct - * @s: comedi_subdevice struct + * comedi_handle_events() - Handle events and possibly stop acquisition + * @dev: COMEDI device. + * @s: COMEDI subdevice. * * Handles outstanding asynchronous acquisition event flags associated - * with the subdevice. Call the subdevice's "->cancel()" handler if the + * with the subdevice. Call the subdevice's @s->cancel() handler if the * "end of acquisition", "error" or "overflow" event flags are set in order * to stop the acquisition at the driver level. * @@ -685,12 +781,19 @@ static void comedi_report_boards(struct comedi_driver *driv) } /** - * comedi_load_firmware() - Request and load firmware for a device. - * @dev: comedi_device struct - * @hw_device: device struct for the comedi_device - * @name: the name of the firmware image - * @cb: callback to the upload the firmware image - * @context: private context from the driver + * comedi_load_firmware() - Request and load firmware for a device + * @dev: COMEDI device. + * @device: Hardware device. + * @name: The name of the firmware image. + * @cb: Callback to the upload the firmware image. + * @context: Private context from the driver. + * + * Sends a firmware request for the hardware device and waits for it. Calls + * the callback function to upload the firmware to the device, them releases + * the firmware. + * + * Returns 0 on success, -EINVAL if @cb is NULL, or a negative error number + * from the firmware request or the callback function. */ int comedi_load_firmware(struct comedi_device *dev, struct device *device, @@ -717,10 +820,16 @@ int comedi_load_firmware(struct comedi_device *dev, EXPORT_SYMBOL_GPL(comedi_load_firmware); /** - * __comedi_request_region() - Request an I/O reqion for a legacy driver. - * @dev: comedi_device struct - * @start: base address of the I/O reqion - * @len: length of the I/O region + * __comedi_request_region() - Request an I/O region for a legacy driver + * @dev: COMEDI device. + * @start: Base address of the I/O region. + * @len: Length of the I/O region. + * + * Requests the specified I/O port region which must start at a non-zero + * address. + * + * Returns 0 on success, -EINVAL if @start is 0, or -EIO if the request + * fails. */ int __comedi_request_region(struct comedi_device *dev, unsigned long start, unsigned long len) @@ -743,10 +852,19 @@ int __comedi_request_region(struct comedi_device *dev, EXPORT_SYMBOL_GPL(__comedi_request_region); /** - * comedi_request_region() - Request an I/O reqion for a legacy driver. - * @dev: comedi_device struct - * @start: base address of the I/O reqion - * @len: length of the I/O region + * comedi_request_region() - Request an I/O region for a legacy driver + * @dev: COMEDI device. + * @start: Base address of the I/O region. + * @len: Length of the I/O region. + * + * Requests the specified I/O port region which must start at a non-zero + * address. + * + * On success, @dev->iobase is set to the base address of the region and + * @dev->iolen is set to its length. + * + * Returns 0 on success, -EINVAL if @start is 0, or -EIO if the request + * fails. */ int comedi_request_region(struct comedi_device *dev, unsigned long start, unsigned long len) @@ -764,8 +882,16 @@ int comedi_request_region(struct comedi_device *dev, EXPORT_SYMBOL_GPL(comedi_request_region); /** - * comedi_legacy_detach() - A generic (*detach) function for legacy drivers. - * @dev: comedi_device struct + * comedi_legacy_detach() - A generic (*detach) function for legacy drivers + * @dev: COMEDI device. + * + * This is a simple, generic 'detach' handler for legacy COMEDI devices that + * just use a single I/O port region and possibly an IRQ and that don't need + * any special clean-up for their private device or subdevice storage. It + * can also be called by a driver-specific 'detach' handler. + * + * If @dev->irq is non-zero, the IRQ will be freed. If @dev->iobase and + * @dev->iolen are both non-zero, the I/O port region will be released. */ void comedi_legacy_detach(struct comedi_device *dev) { @@ -820,7 +946,7 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) "driver '%s' does not support attach using comedi_config\n", driv->driver_name); module_put(driv->module); - ret = -ENOSYS; + ret = -EIO; goto out; } dev->driver = driv; @@ -839,6 +965,29 @@ out: return ret; } +/** + * comedi_auto_config() - Create a COMEDI device for a hardware device + * @hardware_device: Hardware device. + * @driver: COMEDI low-level driver for the hardware device. + * @context: Driver context for the auto_attach handler. + * + * Allocates a new COMEDI device for the hardware device and calls the + * low-level driver's 'auto_attach' handler to set-up the hardware and + * allocate the COMEDI subdevices. Additional "post-configuration" setting + * up is performed on successful return from the 'auto_attach' handler. + * If the 'auto_attach' handler fails, the low-level driver's 'detach' + * handler will be called as part of the clean-up. + * + * This is usually called from a wrapper function in a bus-specific COMEDI + * module, which in turn is usually called from a bus device 'probe' + * function in the low-level driver. + * + * Returns 0 on success, -EINVAL if the parameters are invalid or the + * post-configuration determines the driver has set the COMEDI device up + * incorrectly, -ENOMEM if failed to allocate memory, -EBUSY if run out of + * COMEDI minor device numbers, or some negative error number returned by + * the driver's 'auto_attach' handler. + */ int comedi_auto_config(struct device *hardware_device, struct comedi_driver *driver, unsigned long context) { @@ -896,6 +1045,22 @@ int comedi_auto_config(struct device *hardware_device, } EXPORT_SYMBOL_GPL(comedi_auto_config); +/** + * comedi_auto_unconfig() - Unconfigure auto-allocated COMEDI device + * @hardware_device: Hardware device previously passed to + * comedi_auto_config(). + * + * Cleans up and eventually destroys the COMEDI device allocated by + * comedi_auto_config() for the same hardware device. As part of this + * clean-up, the low-level COMEDI driver's 'detach' handler will be called. + * (The COMEDI device itself will persist in an unattached state if it is + * still open, until it is released, and any mmapped buffers will persist + * until they are munmapped.) + * + * This is usually called from a wrapper module in a bus-specific COMEDI + * module, which in turn is usually set as the bus device 'remove' function + * in the low-level COMEDI driver. + */ void comedi_auto_unconfig(struct device *hardware_device) { if (!hardware_device) @@ -904,6 +1069,17 @@ void comedi_auto_unconfig(struct device *hardware_device) } EXPORT_SYMBOL_GPL(comedi_auto_unconfig); +/** + * comedi_driver_register() - Register a low-level COMEDI driver + * @driver: Low-level COMEDI driver. + * + * The low-level COMEDI driver is added to the list of registered COMEDI + * drivers. This is used by the handler for the "/proc/comedi" file and is + * also used by the handler for the %COMEDI_DEVCONFIG ioctl to configure + * "legacy" COMEDI devices (for those low-level drivers that support it). + * + * Returns 0. + */ int comedi_driver_register(struct comedi_driver *driver) { mutex_lock(&comedi_drivers_list_lock); @@ -915,6 +1091,15 @@ int comedi_driver_register(struct comedi_driver *driver) } EXPORT_SYMBOL_GPL(comedi_driver_register); +/** + * comedi_driver_unregister() - Unregister a low-level COMEDI driver + * @driver: Low-level COMEDI driver. + * + * The low-level COMEDI driver is removed from the list of registered COMEDI + * drivers. Detaches any COMEDI devices attached to the driver, which will + * result in the low-level driver's 'detach' handler being called for those + * devices before this function returns. + */ void comedi_driver_unregister(struct comedi_driver *driver) { struct comedi_driver *prev; diff --git a/kernel/drivers/staging/comedi/drivers/8255.c b/kernel/drivers/staging/comedi/drivers/8255.c index ba89321df..b79d3764a 100644 --- a/kernel/drivers/staging/comedi/drivers/8255.c +++ b/kernel/drivers/staging/comedi/drivers/8255.c @@ -53,221 +53,6 @@ #include "8255.h" -struct subdev_8255_private { - unsigned long regbase; - int (*io)(struct comedi_device *, int, int, int, unsigned long); -}; - -static int subdev_8255_io(struct comedi_device *dev, - int dir, int port, int data, unsigned long regbase) -{ - if (dir) { - outb(data, dev->iobase + regbase + port); - return 0; - } - return inb(dev->iobase + regbase + port); -} - -static int subdev_8255_mmio(struct comedi_device *dev, - int dir, int port, int data, unsigned long regbase) -{ - if (dir) { - writeb(data, dev->mmio + regbase + port); - return 0; - } - return readb(dev->mmio + regbase + port); -} - -static int subdev_8255_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct subdev_8255_private *spriv = s->private; - unsigned long regbase = spriv->regbase; - unsigned int mask; - unsigned int v; - - mask = comedi_dio_update_state(s, data); - if (mask) { - if (mask & 0xff) - spriv->io(dev, 1, I8255_DATA_A_REG, - s->state & 0xff, regbase); - if (mask & 0xff00) - spriv->io(dev, 1, I8255_DATA_B_REG, - (s->state >> 8) & 0xff, regbase); - if (mask & 0xff0000) - spriv->io(dev, 1, I8255_DATA_C_REG, - (s->state >> 16) & 0xff, regbase); - } - - v = spriv->io(dev, 0, I8255_DATA_A_REG, 0, regbase); - v |= (spriv->io(dev, 0, I8255_DATA_B_REG, 0, regbase) << 8); - v |= (spriv->io(dev, 0, I8255_DATA_C_REG, 0, regbase) << 16); - - data[1] = v; - - return insn->n; -} - -static void subdev_8255_do_config(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct subdev_8255_private *spriv = s->private; - unsigned long regbase = spriv->regbase; - int config; - - config = I8255_CTRL_CW; - /* 1 in io_bits indicates output, 1 in config indicates input */ - if (!(s->io_bits & 0x0000ff)) - config |= I8255_CTRL_A_IO; - if (!(s->io_bits & 0x00ff00)) - config |= I8255_CTRL_B_IO; - if (!(s->io_bits & 0x0f0000)) - config |= I8255_CTRL_C_LO_IO; - if (!(s->io_bits & 0xf00000)) - config |= I8255_CTRL_C_HI_IO; - - spriv->io(dev, 1, I8255_CTRL_REG, config, regbase); -} - -static int subdev_8255_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - unsigned int chan = CR_CHAN(insn->chanspec); - unsigned int mask; - int ret; - - if (chan < 8) - mask = 0x0000ff; - else if (chan < 16) - mask = 0x00ff00; - else if (chan < 20) - mask = 0x0f0000; - else - mask = 0xf00000; - - ret = comedi_dio_insn_config(dev, s, insn, data, mask); - if (ret) - return ret; - - subdev_8255_do_config(dev, s); - - return insn->n; -} - -static int __subdev_8255_init(struct comedi_device *dev, - struct comedi_subdevice *s, - int (*io)(struct comedi_device *, - int, int, int, unsigned long), - unsigned long regbase, - bool is_mmio) -{ - struct subdev_8255_private *spriv; - - spriv = comedi_alloc_spriv(s, sizeof(*spriv)); - if (!spriv) - return -ENOMEM; - - if (io) - spriv->io = io; - else if (is_mmio) - spriv->io = subdev_8255_mmio; - else - spriv->io = subdev_8255_io; - spriv->regbase = regbase; - - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 24; - s->range_table = &range_digital; - s->maxdata = 1; - s->insn_bits = subdev_8255_insn; - s->insn_config = subdev_8255_insn_config; - - subdev_8255_do_config(dev, s); - - return 0; -} - -/** - * subdev_8255_init - initialize DIO subdevice for driving I/O mapped 8255 - * @dev: comedi device owning subdevice - * @s: comedi subdevice to initialize - * @io: (optional) register I/O call-back function - * @regbase: offset of 8255 registers from dev->iobase, or call-back context - * - * Initializes a comedi subdevice as a DIO subdevice driving an 8255 chip. - * - * If the optional I/O call-back function is provided, its prototype is of - * the following form: - * - * int my_8255_callback(struct comedi_device *dev, - * struct comedi_subdevice *s, int dir, int port, - * int data, unsigned long regbase); - * - * where 'dev', 's', and 'regbase' match the values passed to this function, - * 'port' is the 8255 port number 0 to 3 (including the control port), 'dir' - * is the direction (0 for read, 1 for write) and 'data' is the value to be - * written. It should return 0 if writing or the value read if reading. - * - * If the optional I/O call-back function is not provided, an internal - * call-back function is used which uses consecutive I/O port addresses - * starting at dev->iobase + regbase. - * - * Return: -ENOMEM if failed to allocate memory, zero on success. - */ -int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, - int (*io)(struct comedi_device *, - int, int, int, unsigned long), - unsigned long regbase) -{ - return __subdev_8255_init(dev, s, io, regbase, false); -} -EXPORT_SYMBOL_GPL(subdev_8255_init); - -/** - * subdev_8255_mm_init - initialize DIO subdevice for driving mmio-mapped 8255 - * @dev: comedi device owning subdevice - * @s: comedi subdevice to initialize - * @io: (optional) register I/O call-back function - * @regbase: offset of 8255 registers from dev->mmio, or call-back context - * - * Initializes a comedi subdevice as a DIO subdevice driving an 8255 chip. - * - * If the optional I/O call-back function is provided, its prototype is of - * the following form: - * - * int my_8255_callback(struct comedi_device *dev, - * struct comedi_subdevice *s, int dir, int port, - * int data, unsigned long regbase); - * - * where 'dev', 's', and 'regbase' match the values passed to this function, - * 'port' is the 8255 port number 0 to 3 (including the control port), 'dir' - * is the direction (0 for read, 1 for write) and 'data' is the value to be - * written. It should return 0 if writing or the value read if reading. - * - * If the optional I/O call-back function is not provided, an internal - * call-back function is used which uses consecutive MMIO virtual addresses - * starting at dev->mmio + regbase. - * - * Return: -ENOMEM if failed to allocate memory, zero on success. - */ -int subdev_8255_mm_init(struct comedi_device *dev, struct comedi_subdevice *s, - int (*io)(struct comedi_device *, - int, int, int, unsigned long), - unsigned long regbase) -{ - return __subdev_8255_init(dev, s, io, regbase, true); -} -EXPORT_SYMBOL_GPL(subdev_8255_mm_init); - -/* - * Start of the 8255 standalone device - */ - static int dev_8255_attach(struct comedi_device *dev, struct comedi_devconfig *it) { @@ -306,8 +91,15 @@ static int dev_8255_attach(struct comedi_device *dev, s->type = COMEDI_SUBD_UNUSED; } else { ret = subdev_8255_init(dev, s, NULL, iobase); - if (ret) + if (ret) { + /* + * Release the I/O port region here, as the + * "detach" handler cannot find it. + */ + release_region(iobase, I8255_SIZE); + s->type = COMEDI_SUBD_UNUSED; return ret; + } } } @@ -317,14 +109,14 @@ static int dev_8255_attach(struct comedi_device *dev, static void dev_8255_detach(struct comedi_device *dev) { struct comedi_subdevice *s; - struct subdev_8255_private *spriv; int i; for (i = 0; i < dev->n_subdevices; i++) { s = &dev->subdevices[i]; if (s->type != COMEDI_SUBD_UNUSED) { - spriv = s->private; - release_region(spriv->regbase, I8255_SIZE); + unsigned long regbase = subdev_8255_regbase(s); + + release_region(regbase, I8255_SIZE); } } } @@ -338,5 +130,5 @@ static struct comedi_driver dev_8255_driver = { module_comedi_driver(dev_8255_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for standalone 8255 devices"); MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/staging/comedi/drivers/8255.h b/kernel/drivers/staging/comedi/drivers/8255.h index 934b940eb..55a67af51 100644 --- a/kernel/drivers/staging/comedi/drivers/8255.h +++ b/kernel/drivers/staging/comedi/drivers/8255.h @@ -19,30 +19,33 @@ #ifndef _8255_H #define _8255_H -#include "../comedidev.h" - #define I8255_SIZE 0x04 #define I8255_DATA_A_REG 0x00 #define I8255_DATA_B_REG 0x01 #define I8255_DATA_C_REG 0x02 #define I8255_CTRL_REG 0x03 -#define I8255_CTRL_C_LO_IO (1 << 0) -#define I8255_CTRL_B_IO (1 << 1) -#define I8255_CTRL_B_MODE (1 << 2) -#define I8255_CTRL_C_HI_IO (1 << 3) -#define I8255_CTRL_A_IO (1 << 4) +#define I8255_CTRL_C_LO_IO BIT(0) +#define I8255_CTRL_B_IO BIT(1) +#define I8255_CTRL_B_MODE BIT(2) +#define I8255_CTRL_C_HI_IO BIT(3) +#define I8255_CTRL_A_IO BIT(4) #define I8255_CTRL_A_MODE(x) ((x) << 5) -#define I8255_CTRL_CW (1 << 7) +#define I8255_CTRL_CW BIT(7) + +struct comedi_device; +struct comedi_subdevice; -int subdev_8255_init(struct comedi_device *, struct comedi_subdevice *, - int (*io)(struct comedi_device *, - int, int, int, unsigned long), +int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, + int (*io)(struct comedi_device *dev, int dir, int port, + int data, unsigned long regbase), unsigned long regbase); -int subdev_8255_mm_init(struct comedi_device *, struct comedi_subdevice *, - int (*io)(struct comedi_device *, - int, int, int, unsigned long), +int subdev_8255_mm_init(struct comedi_device *dev, struct comedi_subdevice *s, + int (*io)(struct comedi_device *dev, int dir, int port, + int data, unsigned long regbase), unsigned long regbase); +unsigned long subdev_8255_regbase(struct comedi_subdevice *s); + #endif diff --git a/kernel/drivers/staging/comedi/drivers/8255_pci.c b/kernel/drivers/staging/comedi/drivers/8255_pci.c index bb9854b56..38c05d1ec 100644 --- a/kernel/drivers/staging/comedi/drivers/8255_pci.c +++ b/kernel/drivers/staging/comedi/drivers/8255_pci.c @@ -178,8 +178,8 @@ static const struct pci_8255_boardinfo pci_8255_boards[] = { }; /* ripped from mite.h and mite_setup2() to avoid mite dependency */ -#define MITE_IODWBSR 0xc0 /* IO Device Window Base Size Register */ -#define WENAB (1 << 7) /* window enable */ +#define MITE_IODWBSR 0xc0 /* IO Device Window Base Size Register */ +#define WENAB BIT(7) /* window enable */ static int pci_8255_mite_init(struct pci_dev *pcidev) { diff --git a/kernel/drivers/staging/comedi/drivers/Makefile b/kernel/drivers/staging/comedi/drivers/Makefile index d6d834006..c3b8f2d76 100644 --- a/kernel/drivers/staging/comedi/drivers/Makefile +++ b/kernel/drivers/staging/comedi/drivers/Makefile @@ -90,7 +90,6 @@ obj-$(CONFIG_COMEDI_CONTEC_PCI_DIO) += contec_pci_dio.o obj-$(CONFIG_COMEDI_DAS08_PCI) += das08_pci.o obj-$(CONFIG_COMEDI_DT3000) += dt3000.o obj-$(CONFIG_COMEDI_DYNA_PCI10XX) += dyna_pci10xx.o -obj-$(CONFIG_COMEDI_UNIOXX5) += unioxx5.o obj-$(CONFIG_COMEDI_GSC_HPDI) += gsc_hpdi.o obj-$(CONFIG_COMEDI_ICP_MULTI) += icp_multi.o obj-$(CONFIG_COMEDI_DAQBOARD2000) += daqboard2000.o @@ -139,7 +138,8 @@ obj-$(CONFIG_COMEDI_NI_TIOCMD) += ni_tiocmd.o obj-$(CONFIG_COMEDI_NI_LABPC) += ni_labpc_common.o obj-$(CONFIG_COMEDI_NI_LABPC_ISADMA) += ni_labpc_isadma.o -obj-$(CONFIG_COMEDI_8255) += 8255.o +obj-$(CONFIG_COMEDI_8255) += comedi_8255.o +obj-$(CONFIG_COMEDI_8255_SA) += 8255.o obj-$(CONFIG_COMEDI_AMPLC_DIO200) += amplc_dio200_common.o obj-$(CONFIG_COMEDI_AMPLC_PC236) += amplc_pc236_common.o obj-$(CONFIG_COMEDI_DAS08) += das08.o diff --git a/kernel/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/kernel/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c index fa99c8ca4..f0c0d5838 100644 --- a/kernel/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c +++ b/kernel/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c @@ -1,22 +1,3 @@ -/* Digital Input IRQ Function Selection */ -#define APCI1564_DI_INT_OR (0 << 1) -#define APCI1564_DI_INT_AND (1 << 1) - -/* Digital Input Interrupt Enable Disable. */ -#define APCI1564_DI_INT_ENABLE 0x4 -#define APCI1564_DI_INT_DISABLE 0xfffffffb - -/* Digital Output Interrupt Enable Disable. */ -#define APCI1564_DO_VCC_INT_ENABLE 0x1 -#define APCI1564_DO_VCC_INT_DISABLE 0xfffffffe -#define APCI1564_DO_CC_INT_ENABLE 0x2 -#define APCI1564_DO_CC_INT_DISABLE 0xfffffffd - -/* TIMER COUNTER WATCHDOG DEFINES */ -#define ADDIDATA_TIMER 0 -#define ADDIDATA_COUNTER 1 -#define ADDIDATA_WATCHDOG 2 - static int apci1564_timer_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -27,15 +8,16 @@ static int apci1564_timer_insn_config(struct comedi_device *dev, devpriv->tsk_current = current; - /* First Stop The Timer */ + /* Stop the timer */ ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG); - ctrl &= 0xfffff9fe; - /* Stop The Timer */ + ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG | + ADDI_TCW_CTRL_ENA); outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG); if (data[1] == 1) { /* Enable timer int & disable all the other int sources */ - outl(0x02, devpriv->timer + ADDI_TCW_CTRL_REG); + outl(ADDI_TCW_CTRL_IRQ_ENA, + devpriv->timer + ADDI_TCW_CTRL_REG); outl(0x0, dev->iobase + APCI1564_DI_IRQ_REG); outl(0x0, dev->iobase + APCI1564_DO_IRQ_REG); outl(0x0, dev->iobase + APCI1564_WDOG_IRQ_REG); @@ -59,9 +41,11 @@ static int apci1564_timer_insn_config(struct comedi_device *dev, outl(data[3], devpriv->timer + ADDI_TCW_RELOAD_REG); ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG); - ctrl &= 0xfff719e2; - ctrl |= (2 << 13) | 0x10; - /* mode 2 */ + ctrl &= ~(ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE_MASK | + ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG | + ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA | + ADDI_TCW_CTRL_WARN_ENA | ADDI_TCW_CTRL_ENA); + ctrl |= ADDI_TCW_CTRL_MODE(2) | ADDI_TCW_CTRL_TIMER_ENA; outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG); return insn->n; @@ -76,13 +60,13 @@ static int apci1564_timer_insn_write(struct comedi_device *dev, unsigned int ctrl; ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG); + ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG); switch (data[1]) { case 0: /* Stop The Timer */ - ctrl &= 0xfffff9fe; + ctrl &= ~ADDI_TCW_CTRL_ENA; break; case 1: /* Enable the Timer */ - ctrl &= 0xfffff9ff; - ctrl |= 0x1; + ctrl |= ADDI_TCW_CTRL_ENA; break; } outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG); @@ -98,7 +82,8 @@ static int apci1564_timer_insn_read(struct comedi_device *dev, struct apci1564_private *devpriv = dev->private; /* Stores the status of the Timer */ - data[0] = inl(devpriv->timer + ADDI_TCW_STATUS_REG) & 0x1; + data[0] = inl(devpriv->timer + ADDI_TCW_STATUS_REG) & + ADDI_TCW_STATUS_OVERFLOW; /* Stores the Actual value of the Timer */ data[1] = inl(devpriv->timer + ADDI_TCW_VAL_REG); @@ -118,35 +103,34 @@ static int apci1564_counter_insn_config(struct comedi_device *dev, devpriv->tsk_current = current; - /* First Stop The Counter */ - ctrl = inl(iobase + ADDI_TCW_CTRL_REG); - ctrl &= 0xfffff9fe; /* Stop The Timer */ + ctrl = inl(iobase + ADDI_TCW_CTRL_REG); + ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG | + ADDI_TCW_CTRL_ENA); outl(ctrl, iobase + ADDI_TCW_CTRL_REG); /* Set the reload value */ outl(data[3], iobase + ADDI_TCW_RELOAD_REG); - /* Set the mode : */ - /* - Disable the hardware */ - /* - Disable the counter mode */ - /* - Disable the warning */ - /* - Disable the reset */ - /* - Disable the timer mode */ - /* - Enable the counter mode */ - - ctrl &= 0xfffc19e2; - ctrl |= 0x80000 | (data[4] << 16); + /* Set the mode */ + ctrl &= ~(ADDI_TCW_CTRL_EXT_CLK_MASK | ADDI_TCW_CTRL_MODE_MASK | + ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA | + ADDI_TCW_CTRL_WARN_ENA); + ctrl |= ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE(data[4]); outl(ctrl, iobase + ADDI_TCW_CTRL_REG); /* Enable or Disable Interrupt */ - ctrl &= 0xfffff9fd; - ctrl |= (data[1] << 1); + if (data[1]) + ctrl |= ADDI_TCW_CTRL_IRQ_ENA; + else + ctrl &= ~ADDI_TCW_CTRL_IRQ_ENA; outl(ctrl, iobase + ADDI_TCW_CTRL_REG); /* Set the Up/Down selection */ - ctrl &= 0xfffbf9ff; - ctrl |= (data[6] << 18); + if (data[6]) + ctrl |= ADDI_TCW_CTRL_CNT_UP; + else + ctrl &= ~ADDI_TCW_CTRL_CNT_UP; outl(ctrl, iobase + ADDI_TCW_CTRL_REG); return insn->n; @@ -163,17 +147,16 @@ static int apci1564_counter_insn_write(struct comedi_device *dev, unsigned int ctrl; ctrl = inl(iobase + ADDI_TCW_CTRL_REG); + ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG); switch (data[1]) { case 0: /* Stops the Counter subdevice */ ctrl = 0; break; case 1: /* Start the Counter subdevice */ - ctrl &= 0xfffff9ff; - ctrl |= 0x1; + ctrl |= ADDI_TCW_CTRL_ENA; break; case 2: /* Clears the Counter subdevice */ - ctrl &= 0xfffff9ff; - ctrl |= 0x400; + ctrl |= ADDI_TCW_CTRL_GATE; break; } outl(ctrl, iobase + ADDI_TCW_CTRL_REG); @@ -195,10 +178,10 @@ static int apci1564_counter_insn_read(struct comedi_device *dev, data[0] = inl(iobase + ADDI_TCW_VAL_REG); status = inl(iobase + ADDI_TCW_STATUS_REG); - data[1] = (status >> 1) & 1; /* software trigger status */ - data[2] = (status >> 2) & 1; /* hardware trigger status */ - data[3] = (status >> 3) & 1; /* software clear status */ - data[4] = (status >> 0) & 1; /* overflow status */ + data[1] = (status & ADDI_TCW_STATUS_SOFT_TRIG) ? 1 : 0; + data[2] = (status & ADDI_TCW_STATUS_HARDWARE_TRIG) ? 1 : 0; + data[3] = (status & ADDI_TCW_STATUS_SOFT_CLR) ? 1 : 0; + data[4] = (status & ADDI_TCW_STATUS_OVERFLOW) ? 1 : 0; return insn->n; } diff --git a/kernel/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/kernel/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c index 1f2f78186..375707497 100644 --- a/kernel/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c +++ b/kernel/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c @@ -22,54 +22,50 @@ static int apci3501_config_insn_timer(struct comedi_device *dev, unsigned int *data) { struct apci3501_private *devpriv = dev->private; - unsigned int ul_Command1 = 0; + unsigned int ctrl; + + if (data[0] != ADDIDATA_WATCHDOG && + data[0] != ADDIDATA_TIMER) + return -EINVAL; devpriv->tsk_Current = current; - if (data[0] == ADDIDATA_WATCHDOG) { - - devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG; - /* Disable the watchdog */ - outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG); - - if (data[1] == 1) { - /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */ - outl(0x02, dev->iobase + APCI3501_TIMER_CTRL_REG); - } else { - /* disable Timer interrupt */ - outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG); - } - outl(data[2], dev->iobase + APCI3501_TIMER_TIMEBASE_REG); - outl(data[3], dev->iobase + APCI3501_TIMER_RELOAD_REG); + devpriv->timer_mode = data[0]; - /* Set the mode (e2->e0) */ - ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG) | 0xFFF819E0UL; - outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG); + /* first, disable the watchdog or stop the timer */ + if (devpriv->timer_mode == ADDIDATA_WATCHDOG) { + ctrl = 0; + } else { + ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG); + ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG | + ADDI_TCW_CTRL_ENA); } - - else if (data[0] == ADDIDATA_TIMER) { - /* First Stop The Timer */ - ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG); - ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; - outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG); - devpriv->b_TimerSelectMode = ADDIDATA_TIMER; - if (data[1] == 1) { - /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */ - outl(0x02, dev->iobase + APCI3501_TIMER_CTRL_REG); - } else { - /* disable Timer interrupt */ - outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG); - } - - outl(data[2], dev->iobase + APCI3501_TIMER_TIMEBASE_REG); - outl(data[3], dev->iobase + APCI3501_TIMER_RELOAD_REG); - + outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); + + /* enable/disable the timer interrupt */ + ctrl = (data[1] == 1) ? ADDI_TCW_CTRL_IRQ_ENA : 0; + outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); + + outl(data[2], devpriv->tcw + ADDI_TCW_TIMEBASE_REG); + outl(data[3], devpriv->tcw + ADDI_TCW_RELOAD_REG); + + ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG); + if (devpriv->timer_mode == ADDIDATA_WATCHDOG) { + /* Set the mode (e2->e0) NOTE: this doesn't look correct */ + ctrl |= ~(ADDI_TCW_CTRL_CNT_UP | ADDI_TCW_CTRL_EXT_CLK_MASK | + ADDI_TCW_CTRL_MODE_MASK | ADDI_TCW_CTRL_GATE | + ADDI_TCW_CTRL_TRIG | ADDI_TCW_CTRL_TIMER_ENA | + ADDI_TCW_CTRL_RESET_ENA | ADDI_TCW_CTRL_WARN_ENA | + ADDI_TCW_CTRL_IRQ_ENA | ADDI_TCW_CTRL_ENA); + } else { /* mode 2 */ - ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG); - ul_Command1 = - (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL; - outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG); + ctrl &= ~(ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE_MASK | + ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG | + ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA | + ADDI_TCW_CTRL_WARN_ENA | ADDI_TCW_CTRL_ENA); + ctrl |= ADDI_TCW_CTRL_MODE(2) | ADDI_TCW_CTRL_TIMER_ENA; } + outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); return insn->n; } @@ -92,49 +88,27 @@ static int apci3501_write_insn_timer(struct comedi_device *dev, unsigned int *data) { struct apci3501_private *devpriv = dev->private; - unsigned int ul_Command1 = 0; - - if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { - - if (data[1] == 1) { - ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG); - 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 */ - ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG); - ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; - outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG); - } else if (data[1] == 2) { - ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG); - ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL; - outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG); - } - } - - if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) { - if (data[1] == 1) { - - ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG); - ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL; - /* Enable the Timer */ - outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG); - } else if (data[1] == 0) { - /* Stop The Timer */ - ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG); - ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; - outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG); - } - - else if (data[1] == 2) { - /* Trigger the Timer */ - ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG); - ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL; - outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG); + unsigned int ctrl; + + if (devpriv->timer_mode == ADDIDATA_WATCHDOG || + devpriv->timer_mode == ADDIDATA_TIMER) { + ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG); + ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG); + + if (data[1] == 1) { /* enable */ + ctrl |= ADDI_TCW_CTRL_ENA; + } else if (data[1] == 0) { /* stop */ + if (devpriv->timer_mode == ADDIDATA_WATCHDOG) + ctrl = 0; + else + ctrl &= ~ADDI_TCW_CTRL_ENA; + } else if (data[1] == 2) { /* trigger */ + ctrl |= ADDI_TCW_CTRL_TRIG; } + outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); } - inl(dev->iobase + APCI3501_TIMER_STATUS_REG); + inl(devpriv->tcw + ADDI_TCW_STATUS_REG); return insn->n; } @@ -155,19 +129,13 @@ static int apci3501_read_insn_timer(struct comedi_device *dev, { struct apci3501_private *devpriv = dev->private; - if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { - data[0] = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1; - data[1] = inl(dev->iobase + APCI3501_TIMER_SYNC_REG); - } + if (devpriv->timer_mode != ADDIDATA_TIMER && + devpriv->timer_mode != ADDIDATA_WATCHDOG) + return -EINVAL; - else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) { - data[0] = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1; - data[1] = inl(dev->iobase + APCI3501_TIMER_SYNC_REG); - } + data[0] = inl(devpriv->tcw + ADDI_TCW_STATUS_REG) & + ADDI_TCW_STATUS_OVERFLOW; + data[1] = inl(devpriv->tcw + ADDI_TCW_VAL_REG); - else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER) - && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)) { - dev_err(dev->class_dev, "Invalid subdevice.\n"); - } return insn->n; } diff --git a/kernel/drivers/staging/comedi/drivers/addi_apci_1032.c b/kernel/drivers/staging/comedi/drivers/addi_apci_1032.c index b37166d57..ccd1a9129 100644 --- a/kernel/drivers/staging/comedi/drivers/addi_apci_1032.c +++ b/kernel/drivers/staging/comedi/drivers/addi_apci_1032.c @@ -84,9 +84,10 @@ #define APCI1032_MODE2_REG 0x08 #define APCI1032_STATUS_REG 0x0c #define APCI1032_CTRL_REG 0x10 -#define APCI1032_CTRL_INT_OR (0 << 1) -#define APCI1032_CTRL_INT_AND (1 << 1) -#define APCI1032_CTRL_INT_ENA (1 << 2) +#define APCI1032_CTRL_INT_MODE(x) (((x) & 0x1) << 1) +#define APCI1032_CTRL_INT_OR APCI1032_CTRL_INT_MODE(0) +#define APCI1032_CTRL_INT_AND APCI1032_CTRL_INT_MODE(1) +#define APCI1032_CTRL_INT_ENA BIT(2) struct apci1032_private { unsigned long amcc_iobase; /* base of AMCC I/O registers */ diff --git a/kernel/drivers/staging/comedi/drivers/addi_apci_1516.c b/kernel/drivers/staging/comedi/drivers/addi_apci_1516.c index 9c516d1fe..f1f8b1c42 100644 --- a/kernel/drivers/staging/comedi/drivers/addi_apci_1516.c +++ b/kernel/drivers/staging/comedi/drivers/addi_apci_1516.c @@ -100,10 +100,10 @@ static int apci1516_do_insn_bits(struct comedi_device *dev, static int apci1516_reset(struct comedi_device *dev) { - const struct apci1516_boardinfo *this_board = dev->board_ptr; + const struct apci1516_boardinfo *board = dev->board_ptr; struct apci1516_private *devpriv = dev->private; - if (!this_board->has_wdog) + if (!board->has_wdog) return 0; outw(0x0, dev->iobase + APCI1516_DO_REG); @@ -117,17 +117,17 @@ static int apci1516_auto_attach(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct apci1516_boardinfo *this_board = NULL; + const struct apci1516_boardinfo *board = NULL; struct apci1516_private *devpriv; struct comedi_subdevice *s; int ret; if (context < ARRAY_SIZE(apci1516_boardtypes)) - this_board = &apci1516_boardtypes[context]; - if (!this_board) + board = &apci1516_boardtypes[context]; + if (!board) return -ENODEV; - dev->board_ptr = this_board; - dev->board_name = this_board->name; + dev->board_ptr = board; + dev->board_name = board->name; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -146,10 +146,10 @@ static int apci1516_auto_attach(struct comedi_device *dev, /* Initialize the digital input subdevice */ s = &dev->subdevices[0]; - if (this_board->di_nchan) { + if (board->di_nchan) { s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; - s->n_chan = this_board->di_nchan; + s->n_chan = board->di_nchan; s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = apci1516_di_insn_bits; @@ -159,10 +159,10 @@ static int apci1516_auto_attach(struct comedi_device *dev, /* Initialize the digital output subdevice */ s = &dev->subdevices[1]; - if (this_board->do_nchan) { + if (board->do_nchan) { s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = this_board->do_nchan; + s->n_chan = board->do_nchan; s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = apci1516_do_insn_bits; @@ -172,7 +172,7 @@ static int apci1516_auto_attach(struct comedi_device *dev, /* Initialize the watchdog subdevice */ s = &dev->subdevices[2]; - if (this_board->has_wdog) { + if (board->has_wdog) { ret = addi_watchdog_init(s, devpriv->wdog_iobase); if (ret) return ret; diff --git a/kernel/drivers/staging/comedi/drivers/addi_apci_1564.c b/kernel/drivers/staging/comedi/drivers/addi_apci_1564.c index 33e58b9a2..f1ccfbd4c 100644 --- a/kernel/drivers/staging/comedi/drivers/addi_apci_1564.c +++ b/kernel/drivers/staging/comedi/drivers/addi_apci_1564.c @@ -44,12 +44,12 @@ * 0x48 - 0x64 Timer 12-Bit */ #define APCI1564_EEPROM_REG 0x00 -#define APCI1564_EEPROM_VCC_STATUS (1 << 8) +#define APCI1564_EEPROM_VCC_STATUS BIT(8) #define APCI1564_EEPROM_TO_REV(x) (((x) >> 4) & 0xf) -#define APCI1564_EEPROM_DI (1 << 3) -#define APCI1564_EEPROM_DO (1 << 2) -#define APCI1564_EEPROM_CS (1 << 1) -#define APCI1564_EEPROM_CLK (1 << 0) +#define APCI1564_EEPROM_DI BIT(3) +#define APCI1564_EEPROM_DO BIT(2) +#define APCI1564_EEPROM_CS BIT(1) +#define APCI1564_EEPROM_CLK BIT(0) #define APCI1564_REV1_TIMER_IOBASE 0x04 #define APCI1564_REV2_MAIN_IOBASE 0x04 #define APCI1564_REV2_TIMER_IOBASE 0x48 @@ -79,10 +79,17 @@ #define APCI1564_DI_INT_MODE2_REG 0x08 #define APCI1564_DI_INT_STATUS_REG 0x0c #define APCI1564_DI_IRQ_REG 0x10 +#define APCI1564_DI_IRQ_ENA BIT(2) +#define APCI1564_DI_IRQ_MODE BIT(1) /* 1=AND, 0=OR */ #define APCI1564_DO_REG 0x14 #define APCI1564_DO_INT_CTRL_REG 0x18 +#define APCI1564_DO_INT_CTRL_CC_INT_ENA BIT(1) +#define APCI1564_DO_INT_CTRL_VCC_INT_ENA BIT(0) #define APCI1564_DO_INT_STATUS_REG 0x1c +#define APCI1564_DO_INT_STATUS_CC BIT(1) +#define APCI1564_DO_INT_STATUS_VCC BIT(0) #define APCI1564_DO_IRQ_REG 0x20 +#define APCI1564_DO_IRQ_INTR BIT(0) #define APCI1564_WDOG_REG 0x24 #define APCI1564_WDOG_RELOAD_REG 0x28 #define APCI1564_WDOG_TIMEBASE_REG 0x2c @@ -159,9 +166,9 @@ static irqreturn_t apci1564_interrupt(int irq, void *d) unsigned int chan; status = inl(dev->iobase + APCI1564_DI_IRQ_REG); - if (status & APCI1564_DI_INT_ENABLE) { + if (status & APCI1564_DI_IRQ_ENA) { /* disable the interrupt */ - outl(status & APCI1564_DI_INT_DISABLE, + outl(status & ~APCI1564_DI_IRQ_ENA, dev->iobase + APCI1564_DI_IRQ_REG); s->state = inl(dev->iobase + APCI1564_DI_INT_STATUS_REG) & @@ -300,11 +307,9 @@ static int apci1564_cos_insn_config(struct comedi_device *dev, outl(0x0, dev->iobase + APCI1564_DI_INT_MODE2_REG); break; case COMEDI_DIGITAL_TRIG_ENABLE_EDGES: - if (devpriv->ctrl != (APCI1564_DI_INT_ENABLE | - APCI1564_DI_INT_OR)) { + if (devpriv->ctrl != APCI1564_DI_IRQ_ENA) { /* switching to 'OR' mode */ - devpriv->ctrl = APCI1564_DI_INT_ENABLE | - APCI1564_DI_INT_OR; + devpriv->ctrl = APCI1564_DI_IRQ_ENA; /* wipe old channels */ devpriv->mode1 = 0; devpriv->mode2 = 0; @@ -318,11 +323,11 @@ static int apci1564_cos_insn_config(struct comedi_device *dev, devpriv->mode2 |= data[5] << shift; break; case COMEDI_DIGITAL_TRIG_ENABLE_LEVELS: - if (devpriv->ctrl != (APCI1564_DI_INT_ENABLE | - APCI1564_DI_INT_AND)) { + if (devpriv->ctrl != (APCI1564_DI_IRQ_ENA | + APCI1564_DI_IRQ_MODE)) { /* switching to 'AND' mode */ - devpriv->ctrl = APCI1564_DI_INT_ENABLE | - APCI1564_DI_INT_AND; + devpriv->ctrl = APCI1564_DI_IRQ_ENA | + APCI1564_DI_IRQ_MODE; /* wipe old channels */ devpriv->mode1 = 0; devpriv->mode2 = 0; diff --git a/kernel/drivers/staging/comedi/drivers/addi_apci_2032.c b/kernel/drivers/staging/comedi/drivers/addi_apci_2032.c index ad715253b..50f9eb25d 100644 --- a/kernel/drivers/staging/comedi/drivers/addi_apci_2032.c +++ b/kernel/drivers/staging/comedi/drivers/addi_apci_2032.c @@ -34,19 +34,19 @@ */ #define APCI2032_DO_REG 0x00 #define APCI2032_INT_CTRL_REG 0x04 -#define APCI2032_INT_CTRL_VCC_ENA (1 << 0) -#define APCI2032_INT_CTRL_CC_ENA (1 << 1) +#define APCI2032_INT_CTRL_VCC_ENA BIT(0) +#define APCI2032_INT_CTRL_CC_ENA BIT(1) #define APCI2032_INT_STATUS_REG 0x08 -#define APCI2032_INT_STATUS_VCC (1 << 0) -#define APCI2032_INT_STATUS_CC (1 << 1) +#define APCI2032_INT_STATUS_VCC BIT(0) +#define APCI2032_INT_STATUS_CC BIT(1) #define APCI2032_STATUS_REG 0x0c -#define APCI2032_STATUS_IRQ (1 << 0) +#define APCI2032_STATUS_IRQ BIT(0) #define APCI2032_WDOG_REG 0x10 struct apci2032_int_private { - spinlock_t spinlock; - bool active; - unsigned char enabled_isns; + spinlock_t spinlock; /* protects the following members */ + bool active; /* an async command is running */ + unsigned char enabled_isns; /* mask of enabled interrupt channels */ }; static int apci2032_do_insn_bits(struct comedi_device *dev, diff --git a/kernel/drivers/staging/comedi/drivers/addi_apci_3120.c b/kernel/drivers/staging/comedi/drivers/addi_apci_3120.c index 95dc64bfe..3630d75e3 100644 --- a/kernel/drivers/staging/comedi/drivers/addi_apci_3120.c +++ b/kernel/drivers/staging/comedi/drivers/addi_apci_3120.c @@ -31,33 +31,33 @@ * PCI BAR 0 register map (devpriv->amcc) * see amcc_s5933.h for register and bit defines */ -#define APCI3120_FIFO_ADVANCE_ON_BYTE_2 (1 << 29) +#define APCI3120_FIFO_ADVANCE_ON_BYTE_2 BIT(29) /* * PCI BAR 1 register map (dev->iobase) */ #define APCI3120_AI_FIFO_REG 0x00 #define APCI3120_CTRL_REG 0x00 -#define APCI3120_CTRL_EXT_TRIG (1 << 15) -#define APCI3120_CTRL_GATE(x) (1 << (12 + (x))) +#define APCI3120_CTRL_EXT_TRIG BIT(15) +#define APCI3120_CTRL_GATE(x) BIT(12 + (x)) #define APCI3120_CTRL_PR(x) (((x) & 0xf) << 8) #define APCI3120_CTRL_PA(x) (((x) & 0xf) << 0) #define APCI3120_AI_SOFTTRIG_REG 0x02 #define APCI3120_STATUS_REG 0x02 -#define APCI3120_STATUS_EOC_INT (1 << 15) -#define APCI3120_STATUS_AMCC_INT (1 << 14) -#define APCI3120_STATUS_EOS_INT (1 << 13) -#define APCI3120_STATUS_TIMER2_INT (1 << 12) +#define APCI3120_STATUS_EOC_INT BIT(15) +#define APCI3120_STATUS_AMCC_INT BIT(14) +#define APCI3120_STATUS_EOS_INT BIT(13) +#define APCI3120_STATUS_TIMER2_INT BIT(12) #define APCI3120_STATUS_INT_MASK (0xf << 12) #define APCI3120_STATUS_TO_DI_BITS(x) (((x) >> 8) & 0xf) #define APCI3120_STATUS_TO_VERSION(x) (((x) >> 4) & 0xf) -#define APCI3120_STATUS_FIFO_FULL (1 << 2) -#define APCI3120_STATUS_FIFO_EMPTY (1 << 1) -#define APCI3120_STATUS_DA_READY (1 << 0) +#define APCI3120_STATUS_FIFO_FULL BIT(2) +#define APCI3120_STATUS_FIFO_EMPTY BIT(1) +#define APCI3120_STATUS_DA_READY BIT(0) #define APCI3120_TIMER_REG 0x04 #define APCI3120_CHANLIST_REG 0x06 #define APCI3120_CHANLIST_INDEX(x) (((x) & 0xf) << 8) -#define APCI3120_CHANLIST_UNIPOLAR (1 << 7) +#define APCI3120_CHANLIST_UNIPOLAR BIT(7) #define APCI3120_CHANLIST_GAIN(x) (((x) & 0x3) << 4) #define APCI3120_CHANLIST_MUX(x) (((x) & 0xf) << 0) #define APCI3120_AO_REG(x) (0x08 + (((x) / 4) * 2)) @@ -74,19 +74,21 @@ #define APCI3120_CTR0_DO_BITS(x) ((x) << 4) #define APCI3120_CTR0_TIMER_SEL(x) ((x) << 0) #define APCI3120_MODE_REG 0x0e -#define APCI3120_MODE_TIMER2_CLK_OSC (0 << 6) -#define APCI3120_MODE_TIMER2_CLK_OUT1 (1 << 6) -#define APCI3120_MODE_TIMER2_CLK_EOC (2 << 6) -#define APCI3120_MODE_TIMER2_CLK_EOS (3 << 6) -#define APCI3120_MODE_TIMER2_CLK_MASK (3 << 6) -#define APCI3120_MODE_TIMER2_AS_TIMER (0 << 4) -#define APCI3120_MODE_TIMER2_AS_COUNTER (1 << 4) -#define APCI3120_MODE_TIMER2_AS_WDOG (2 << 4) -#define APCI3120_MODE_TIMER2_AS_MASK (3 << 4) /* sets AS_TIMER */ -#define APCI3120_MODE_SCAN_ENA (1 << 3) -#define APCI3120_MODE_TIMER2_IRQ_ENA (1 << 2) -#define APCI3120_MODE_EOS_IRQ_ENA (1 << 1) -#define APCI3120_MODE_EOC_IRQ_ENA (1 << 0) +#define APCI3120_MODE_TIMER2_CLK(x) (((x) & 0x3) << 6) +#define APCI3120_MODE_TIMER2_CLK_OSC APCI3120_MODE_TIMER2_CLK(0) +#define APCI3120_MODE_TIMER2_CLK_OUT1 APCI3120_MODE_TIMER2_CLK(1) +#define APCI3120_MODE_TIMER2_CLK_EOC APCI3120_MODE_TIMER2_CLK(2) +#define APCI3120_MODE_TIMER2_CLK_EOS APCI3120_MODE_TIMER2_CLK(3) +#define APCI3120_MODE_TIMER2_CLK_MASK APCI3120_MODE_TIMER2_CLK(3) +#define APCI3120_MODE_TIMER2_AS(x) (((x) & 0x3) << 4) +#define APCI3120_MODE_TIMER2_AS_TIMER APCI3120_MODE_TIMER2_AS(0) +#define APCI3120_MODE_TIMER2_AS_COUNTER APCI3120_MODE_TIMER2_AS(1) +#define APCI3120_MODE_TIMER2_AS_WDOG APCI3120_MODE_TIMER2_AS(2) +#define APCI3120_MODE_TIMER2_AS_MASK APCI3120_MODE_TIMER2_AS(3) +#define APCI3120_MODE_SCAN_ENA BIT(3) +#define APCI3120_MODE_TIMER2_IRQ_ENA BIT(2) +#define APCI3120_MODE_EOS_IRQ_ENA BIT(1) +#define APCI3120_MODE_EOC_IRQ_ENA BIT(0) /* * PCI BAR 2 register map (devpriv->addon) @@ -94,8 +96,8 @@ #define APCI3120_ADDON_ADDR_REG 0x00 #define APCI3120_ADDON_DATA_REG 0x02 #define APCI3120_ADDON_CTRL_REG 0x04 -#define APCI3120_ADDON_CTRL_AMWEN_ENA (1 << 1) -#define APCI3120_ADDON_CTRL_A2P_FIFO_ENA (1 << 0) +#define APCI3120_ADDON_CTRL_AMWEN_ENA BIT(1) +#define APCI3120_ADDON_CTRL_A2P_FIFO_ENA BIT(0) /* * Board revisions @@ -502,11 +504,6 @@ static irqreturn_t apci3120_interrupt(int irq, void *d) if (int_amcc & TARGET_ABORT_INT) dev_err(dev->class_dev, "AMCC IRQ - TARGET DMA ABORT!\n"); - if ((status & APCI3120_STATUS_EOC_INT) == 0 && - (devpriv->mode & APCI3120_MODE_EOC_IRQ_ENA)) { - /* nothing to do... EOC mode is not currently used */ - } - if ((status & APCI3120_STATUS_EOS_INT) && (devpriv->mode & APCI3120_MODE_EOS_IRQ_ENA)) { unsigned short val; @@ -977,18 +974,18 @@ static int apci3120_auto_attach(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct apci3120_board *this_board = NULL; + const struct apci3120_board *board = NULL; struct apci3120_private *devpriv; struct comedi_subdevice *s; unsigned int status; int ret; if (context < ARRAY_SIZE(apci3120_boardtypes)) - this_board = &apci3120_boardtypes[context]; - if (!this_board) + board = &apci3120_boardtypes[context]; + if (!board) return -ENODEV; - dev->board_ptr = this_board; - dev->board_name = this_board->name; + dev->board_ptr = board; + dev->board_name = board->name; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -1031,7 +1028,7 @@ static int apci3120_auto_attach(struct comedi_device *dev, s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; s->n_chan = 16; - s->maxdata = this_board->ai_is_16bit ? 0xffff : 0x0fff; + s->maxdata = board->ai_is_16bit ? 0xffff : 0x0fff; s->range_table = &apci3120_ai_range; s->insn_read = apci3120_ai_insn_read; if (dev->irq) { @@ -1045,7 +1042,7 @@ static int apci3120_auto_attach(struct comedi_device *dev, /* Analog Output subdevice */ s = &dev->subdevices[1]; - if (this_board->has_ao) { + if (board->has_ao) { s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; s->n_chan = 8; diff --git a/kernel/drivers/staging/comedi/drivers/addi_apci_3501.c b/kernel/drivers/staging/comedi/drivers/addi_apci_3501.c index 73786a3f3..40ff91411 100644 --- a/kernel/drivers/staging/comedi/drivers/addi_apci_3501.c +++ b/kernel/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -27,27 +27,21 @@ #include <linux/sched.h> #include "../comedi_pci.h" +#include "addi_tcw.h" #include "amcc_s5933.h" /* * PCI bar 1 register I/O map */ #define APCI3501_AO_CTRL_STATUS_REG 0x00 -#define APCI3501_AO_CTRL_BIPOLAR (1 << 0) -#define APCI3501_AO_STATUS_READY (1 << 8) +#define APCI3501_AO_CTRL_BIPOLAR BIT(0) +#define APCI3501_AO_STATUS_READY BIT(8) #define APCI3501_AO_DATA_REG 0x04 #define APCI3501_AO_DATA_CHAN(x) ((x) << 0) #define APCI3501_AO_DATA_VAL(x) ((x) << 8) -#define APCI3501_AO_DATA_BIPOLAR (1 << 31) +#define APCI3501_AO_DATA_BIPOLAR BIT(31) #define APCI3501_AO_TRIG_SCS_REG 0x08 -#define APCI3501_TIMER_SYNC_REG 0x20 -#define APCI3501_TIMER_RELOAD_REG 0x24 -#define APCI3501_TIMER_TIMEBASE_REG 0x28 -#define APCI3501_TIMER_CTRL_REG 0x2c -#define APCI3501_TIMER_STATUS_REG 0x30 -#define APCI3501_TIMER_IRQ_REG 0x34 -#define APCI3501_TIMER_WARN_RELOAD_REG 0x38 -#define APCI3501_TIMER_WARN_TIMEBASE_REG 0x3c +#define APCI3501_TIMER_BASE 0x20 #define APCI3501_DO_REG 0x40 #define APCI3501_DI_REG 0x50 @@ -72,9 +66,10 @@ #define EEPROM_TIMER_WATCHDOG_COUNTER 10 struct apci3501_private { - int i_IobaseAmcc; + unsigned long amcc; + unsigned long tcw; struct task_struct *tsk_Current; - unsigned char b_TimerSelectMode; + unsigned char timer_mode; }; static struct comedi_lrange apci3501_ao_range = { @@ -222,11 +217,10 @@ static unsigned short apci3501_eeprom_readw(unsigned long iobase, static int apci3501_eeprom_get_ao_n_chan(struct comedi_device *dev) { struct apci3501_private *devpriv = dev->private; - unsigned long iobase = devpriv->i_IobaseAmcc; unsigned char nfuncs; int i; - nfuncs = apci3501_eeprom_readw(iobase, 10) & 0xff; + nfuncs = apci3501_eeprom_readw(devpriv->amcc, 10) & 0xff; /* Read functionality details */ for (i = 0; i < nfuncs; i++) { @@ -235,11 +229,11 @@ static int apci3501_eeprom_get_ao_n_chan(struct comedi_device *dev) unsigned char func; unsigned short val; - func = apci3501_eeprom_readw(iobase, 12 + offset) & 0x3f; - addr = apci3501_eeprom_readw(iobase, 14 + offset); + func = apci3501_eeprom_readw(devpriv->amcc, 12 + offset) & 0x3f; + addr = apci3501_eeprom_readw(devpriv->amcc, 14 + offset); if (func == EEPROM_ANALOGOUTPUT) { - val = apci3501_eeprom_readw(iobase, addr + 10); + val = apci3501_eeprom_readw(devpriv->amcc, addr + 10); return (val >> 4) & 0x3ff; } } @@ -254,7 +248,7 @@ static int apci3501_eeprom_insn_read(struct comedi_device *dev, struct apci3501_private *devpriv = dev->private; unsigned short addr = CR_CHAN(insn->chanspec); - data[0] = apci3501_eeprom_readw(devpriv->i_IobaseAmcc, 2 * addr); + data[0] = apci3501_eeprom_readw(devpriv->amcc, 2 * addr); return insn->n; } @@ -263,26 +257,29 @@ static irqreturn_t apci3501_interrupt(int irq, void *d) { struct comedi_device *dev = d; struct apci3501_private *devpriv = dev->private; - unsigned int ui_Timer_AOWatchdog; - unsigned long ul_Command1; + unsigned int status; + unsigned int ctrl; /* Disable Interrupt */ - ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG); - ul_Command1 = ul_Command1 & 0xFFFFF9FDul; - outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG); + ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG); + ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG | + ADDI_TCW_CTRL_IRQ_ENA); + outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); - ui_Timer_AOWatchdog = inl(dev->iobase + APCI3501_TIMER_IRQ_REG) & 0x1; - if ((!ui_Timer_AOWatchdog)) { + status = inl(devpriv->tcw + ADDI_TCW_IRQ_REG); + if (!(status & ADDI_TCW_IRQ)) { dev_err(dev->class_dev, "IRQ from unknown source\n"); return IRQ_NONE; } /* Enable Interrupt Send a signal to from kernel to user space */ send_sig(SIGIO, devpriv->tsk_Current, 0); - ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG); - ul_Command1 = (ul_Command1 & 0xFFFFF9FDul) | 1 << 1; - outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG); - inl(dev->iobase + APCI3501_TIMER_STATUS_REG); + ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG); + ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG | + ADDI_TCW_CTRL_IRQ_ENA); + ctrl |= ADDI_TCW_CTRL_IRQ_ENA; + outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); + inl(devpriv->tcw + ADDI_TCW_STATUS_REG); return IRQ_HANDLED; } @@ -334,8 +331,9 @@ static int apci3501_auto_attach(struct comedi_device *dev, if (ret) return ret; + devpriv->amcc = pci_resource_start(pcidev, 0); dev->iobase = pci_resource_start(pcidev, 1); - devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0); + devpriv->tcw = dev->iobase + APCI3501_TIMER_BASE; ao_n_chan = apci3501_eeprom_get_ao_n_chan(dev); diff --git a/kernel/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/kernel/drivers/staging/comedi/drivers/addi_apci_3xxx.c index bef6efc84..995096c78 100644 --- a/kernel/drivers/staging/comedi/drivers/addi_apci_3xxx.c +++ b/kernel/drivers/staging/comedi/drivers/addi_apci_3xxx.c @@ -27,9 +27,9 @@ #include "../comedi_pci.h" -#define CONV_UNIT_NS (1 << 0) -#define CONV_UNIT_US (1 << 1) -#define CONV_UNIT_MS (1 << 2) +#define CONV_UNIT_NS BIT(0) +#define CONV_UNIT_US BIT(1) +#define CONV_UNIT_MS BIT(2) static const struct comedi_lrange apci3xxx_ai_range = { 8, { diff --git a/kernel/drivers/staging/comedi/drivers/addi_tcw.h b/kernel/drivers/staging/comedi/drivers/addi_tcw.h index 8794d4cbb..db6d5a4e8 100644 --- a/kernel/drivers/staging/comedi/drivers/addi_tcw.h +++ b/kernel/drivers/staging/comedi/drivers/addi_tcw.h @@ -10,44 +10,51 @@ #define ADDI_TCW_VAL_REG 0x00 #define ADDI_TCW_SYNC_REG 0x00 -#define ADDI_TCW_SYNC_CTR_TRIG (1 << 8) -#define ADDI_TCW_SYNC_CTR_DIS (1 << 7) -#define ADDI_TCW_SYNC_CTR_ENA (1 << 6) -#define ADDI_TCW_SYNC_TIMER_TRIG (1 << 5) -#define ADDI_TCW_SYNC_TIMER_DIS (1 << 4) -#define ADDI_TCW_SYNC_TIMER_ENA (1 << 3) -#define ADDI_TCW_SYNC_WDOG_TRIG (1 << 2) -#define ADDI_TCW_SYNC_WDOG_DIS (1 << 1) -#define ADDI_TCW_SYNC_WDOG_ENA (1 << 0) +#define ADDI_TCW_SYNC_CTR_TRIG BIT(8) +#define ADDI_TCW_SYNC_CTR_DIS BIT(7) +#define ADDI_TCW_SYNC_CTR_ENA BIT(6) +#define ADDI_TCW_SYNC_TIMER_TRIG BIT(5) +#define ADDI_TCW_SYNC_TIMER_DIS BIT(4) +#define ADDI_TCW_SYNC_TIMER_ENA BIT(3) +#define ADDI_TCW_SYNC_WDOG_TRIG BIT(2) +#define ADDI_TCW_SYNC_WDOG_DIS BIT(1) +#define ADDI_TCW_SYNC_WDOG_ENA BIT(0) #define ADDI_TCW_RELOAD_REG 0x04 #define ADDI_TCW_TIMEBASE_REG 0x08 #define ADDI_TCW_CTRL_REG 0x0c -#define ADDI_TCW_CTRL_EXT_CLK_STATUS (1 << 21) -#define ADDI_TCW_CTRL_CASCADE (1 << 20) -#define ADDI_TCW_CTRL_CNTR_ENA (1 << 19) -#define ADDI_TCW_CTRL_CNT_UP (1 << 18) -#define ADDI_TCW_CTRL_EXT_CLK(x) ((x) << 16) -#define ADDI_TCW_CTRL_OUT(x) ((x) << 11) -#define ADDI_TCW_CTRL_GATE (1 << 10) -#define ADDI_TCW_CTRL_TRIG (1 << 9) -#define ADDI_TCW_CTRL_EXT_GATE(x) ((x) << 7) -#define ADDI_TCW_CTRL_EXT_TRIG(x) ((x) << 5) -#define ADDI_TCW_CTRL_TIMER_ENA (1 << 4) -#define ADDI_TCW_CTRL_RESET_ENA (1 << 3) -#define ADDI_TCW_CTRL_WARN_ENA (1 << 2) -#define ADDI_TCW_CTRL_IRQ_ENA (1 << 1) -#define ADDI_TCW_CTRL_ENA (1 << 0) +#define ADDI_TCW_CTRL_EXT_CLK_STATUS BIT(21) +#define ADDI_TCW_CTRL_CASCADE BIT(20) +#define ADDI_TCW_CTRL_CNTR_ENA BIT(19) +#define ADDI_TCW_CTRL_CNT_UP BIT(18) +#define ADDI_TCW_CTRL_EXT_CLK(x) (((x) & 3) << 16) +#define ADDI_TCW_CTRL_EXT_CLK_MASK ADDI_TCW_CTRL_EXT_CLK(3) +#define ADDI_TCW_CTRL_MODE(x) (((x) & 7) << 13) +#define ADDI_TCW_CTRL_MODE_MASK ADDI_TCW_CTRL_MODE(7) +#define ADDI_TCW_CTRL_OUT(x) (((x) & 3) << 11) +#define ADDI_TCW_CTRL_OUT_MASK ADDI_TCW_CTRL_OUT(3) +#define ADDI_TCW_CTRL_GATE BIT(10) +#define ADDI_TCW_CTRL_TRIG BIT(9) +#define ADDI_TCW_CTRL_EXT_GATE(x) (((x) & 3) << 7) +#define ADDI_TCW_CTRL_EXT_GATE_MASK ADDI_TCW_CTRL_EXT_GATE(3) +#define ADDI_TCW_CTRL_EXT_TRIG(x) (((x) & 3) << 5) +#define ADDI_TCW_CTRL_EXT_TRIG_MASK ADDI_TCW_CTRL_EXT_TRIG(3) +#define ADDI_TCW_CTRL_TIMER_ENA BIT(4) +#define ADDI_TCW_CTRL_RESET_ENA BIT(3) +#define ADDI_TCW_CTRL_WARN_ENA BIT(2) +#define ADDI_TCW_CTRL_IRQ_ENA BIT(1) +#define ADDI_TCW_CTRL_ENA BIT(0) #define ADDI_TCW_STATUS_REG 0x10 -#define ADDI_TCW_STATUS_SOFT_CLR (1 << 3) -#define ADDI_TCW_STATUS_SOFT_TRIG (1 << 1) -#define ADDI_TCW_STATUS_OVERFLOW (1 << 0) +#define ADDI_TCW_STATUS_SOFT_CLR BIT(3) +#define ADDI_TCW_STATUS_HARDWARE_TRIG BIT(2) +#define ADDI_TCW_STATUS_SOFT_TRIG BIT(1) +#define ADDI_TCW_STATUS_OVERFLOW BIT(0) #define ADDI_TCW_IRQ_REG 0x14 -#define ADDI_TCW_IRQ (1 << 0) +#define ADDI_TCW_IRQ BIT(0) #define ADDI_TCW_WARN_TIMEVAL_REG 0x18 diff --git a/kernel/drivers/staging/comedi/drivers/addi_watchdog.h b/kernel/drivers/staging/comedi/drivers/addi_watchdog.h index 83b47befa..3f8e7388b 100644 --- a/kernel/drivers/staging/comedi/drivers/addi_watchdog.h +++ b/kernel/drivers/staging/comedi/drivers/addi_watchdog.h @@ -1,7 +1,7 @@ #ifndef _ADDI_WATCHDOG_H #define _ADDI_WATCHDOG_H -#include "../comedidev.h" +struct comedi_subdevice; void addi_watchdog_reset(unsigned long iobase); int addi_watchdog_init(struct comedi_subdevice *, unsigned long iobase); diff --git a/kernel/drivers/staging/comedi/drivers/adl_pci6208.c b/kernel/drivers/staging/comedi/drivers/adl_pci6208.c index 7ed3fd6fb..ad7e7c4a5 100644 --- a/kernel/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/kernel/drivers/staging/comedi/drivers/adl_pci6208.c @@ -41,7 +41,7 @@ */ #define PCI6208_AO_CONTROL(x) (0x00 + (2 * (x))) #define PCI6208_AO_STATUS 0x00 -#define PCI6208_AO_STATUS_DATA_SEND (1 << 0) +#define PCI6208_AO_STATUS_DATA_SEND BIT(0) #define PCI6208_DIO 0x40 #define PCI6208_DIO_DO_MASK (0x0f) #define PCI6208_DIO_DO_SHIFT (0) diff --git a/kernel/drivers/staging/comedi/drivers/adl_pci9111.c b/kernel/drivers/staging/comedi/drivers/adl_pci9111.c index c9df3afe9..01d2ee931 100644 --- a/kernel/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/kernel/drivers/staging/comedi/drivers/adl_pci9111.c @@ -1,68 +1,52 @@ /* - -comedi/drivers/adl_pci9111.c - -Hardware driver for PCI9111 ADLink cards: - -PCI-9111HR - -Copyright (C) 2002-2005 Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr> - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. -*/ + * adl_pci9111.c + * Hardware driver for PCI9111 ADLink cards: PCI-9111HR + * Copyright (C) 2002-2005 Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ /* -Driver: adl_pci9111 -Description: Adlink PCI-9111HR -Author: Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr> -Devices: [ADLink] PCI-9111HR (adl_pci9111) -Status: experimental - -Supports: - - - ai_insn read - - ao_insn read/write - - di_insn read - - do_insn read/write - - ai_do_cmd mode with the following sources: - - - start_src TRIG_NOW - - scan_begin_src TRIG_FOLLOW TRIG_TIMER TRIG_EXT - - convert_src TRIG_TIMER TRIG_EXT - - scan_end_src TRIG_COUNT - - stop_src TRIG_COUNT TRIG_NONE - -The scanned channels must be consecutive and start from 0. They must -all have the same range and aref. - -Configuration options: not applicable, uses PCI auto config -*/ + * Driver: adl_pci9111 + * Description: Adlink PCI-9111HR + * Devices: [ADLink] PCI-9111HR (adl_pci9111) + * Author: Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr> + * Status: experimental + * + * Configuration options: not applicable, uses PCI auto config + * + * Supports: + * - ai_insn read + * - ao_insn read/write + * - di_insn read + * - do_insn read/write + * - ai_do_cmd mode with the following sources: + * - start_src TRIG_NOW + * - scan_begin_src TRIG_FOLLOW TRIG_TIMER TRIG_EXT + * - convert_src TRIG_TIMER TRIG_EXT + * - scan_end_src TRIG_COUNT + * - stop_src TRIG_COUNT TRIG_NONE + * + * The scanned channels must be consecutive and start from 0. They must + * all have the same range and aref. + */ /* -CHANGELOG: - -2005/02/17 Extend AI streaming capabilities. Now, scan_begin_arg can be -a multiple of chanlist_len*convert_arg. -2002/02/19 Fixed the two's complement conversion in pci9111_(hr_)ai_get_data. -2002/02/18 Added external trigger support for analog input. - -TODO: - - - Really test implemented functionality. - - Add support for the PCI-9111DG with a probe routine to identify - the card type (perhaps with the help of the channel number readback - of the A/D Data register). - - Add external multiplexer support. - -*/ + * TODO: + * - Really test implemented functionality. + * - Add support for the PCI-9111DG with a probe routine to identify + * the card type (perhaps with the help of the channel number readback + * of the A/D Data register). + * - Add external multiplexer support. + */ #include <linux/module.h> #include <linux/delay.h> @@ -89,23 +73,24 @@ TODO: #define PCI9111_EDIO_REG 0x04 #define PCI9111_AI_CHANNEL_REG 0x06 #define PCI9111_AI_RANGE_STAT_REG 0x08 -#define PCI9111_AI_STAT_AD_BUSY (1 << 7) -#define PCI9111_AI_STAT_FF_FF (1 << 6) -#define PCI9111_AI_STAT_FF_HF (1 << 5) -#define PCI9111_AI_STAT_FF_EF (1 << 4) -#define PCI9111_AI_RANGE_MASK (7 << 0) +#define PCI9111_AI_STAT_AD_BUSY BIT(7) +#define PCI9111_AI_STAT_FF_FF BIT(6) +#define PCI9111_AI_STAT_FF_HF BIT(5) +#define PCI9111_AI_STAT_FF_EF BIT(4) +#define PCI9111_AI_RANGE(x) (((x) & 0x7) << 0) +#define PCI9111_AI_RANGE_MASK PCI9111_AI_RANGE(7) #define PCI9111_AI_TRIG_CTRL_REG 0x0a -#define PCI9111_AI_TRIG_CTRL_TRGEVENT (1 << 5) -#define PCI9111_AI_TRIG_CTRL_POTRG (1 << 4) -#define PCI9111_AI_TRIG_CTRL_PTRG (1 << 3) -#define PCI9111_AI_TRIG_CTRL_ETIS (1 << 2) -#define PCI9111_AI_TRIG_CTRL_TPST (1 << 1) -#define PCI9111_AI_TRIG_CTRL_ASCAN (1 << 0) +#define PCI9111_AI_TRIG_CTRL_TRGEVENT BIT(5) +#define PCI9111_AI_TRIG_CTRL_POTRG BIT(4) +#define PCI9111_AI_TRIG_CTRL_PTRG BIT(3) +#define PCI9111_AI_TRIG_CTRL_ETIS BIT(2) +#define PCI9111_AI_TRIG_CTRL_TPST BIT(1) +#define PCI9111_AI_TRIG_CTRL_ASCAN BIT(0) #define PCI9111_INT_CTRL_REG 0x0c -#define PCI9111_INT_CTRL_ISC2 (1 << 3) -#define PCI9111_INT_CTRL_FFEN (1 << 2) -#define PCI9111_INT_CTRL_ISC1 (1 << 1) -#define PCI9111_INT_CTRL_ISC0 (1 << 0) +#define PCI9111_INT_CTRL_ISC2 BIT(3) +#define PCI9111_INT_CTRL_FFEN BIT(2) +#define PCI9111_INT_CTRL_ISC1 BIT(1) +#define PCI9111_INT_CTRL_ISC0 BIT(0) #define PCI9111_SOFT_TRIG_REG 0x0e #define PCI9111_8254_BASE_REG 0x40 #define PCI9111_INT_CLR_REG 0x48 @@ -139,21 +124,21 @@ struct pci9111_private_data { }; static void plx9050_interrupt_control(unsigned long io_base, - bool LINTi1_enable, - bool LINTi1_active_high, - bool LINTi2_enable, - bool LINTi2_active_high, + bool int1_enable, + bool int1_active_high, + bool int2_enable, + bool int2_active_high, bool interrupt_enable) { int flags = 0; - if (LINTi1_enable) + if (int1_enable) flags |= PLX9052_INTCSR_LI1ENAB; - if (LINTi1_active_high) + if (int1_active_high) flags |= PLX9052_INTCSR_LI1POL; - if (LINTi2_enable) + if (int2_enable) flags |= PLX9052_INTCSR_LI2ENAB; - if (LINTi2_active_high) + if (int2_active_high) flags |= PLX9052_INTCSR_LI2POL; if (interrupt_enable) @@ -363,6 +348,7 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev, struct pci9111_private_data *dev_private = dev->private; struct comedi_cmd *cmd = &s->async->cmd; unsigned int last_chan = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]); + unsigned int range0 = CR_RANGE(cmd->chanlist[0]); unsigned int trig = 0; /* Set channel scan limit */ @@ -374,11 +360,8 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev, outb(last_chan, dev->iobase + PCI9111_AI_CHANNEL_REG); - /* Set gain */ - /* This is the same gain on every channel */ - - outb(CR_RANGE(cmd->chanlist[0]) & PCI9111_AI_RANGE_MASK, - dev->iobase + PCI9111_AI_RANGE_STAT_REG); + /* Set gain - all channels use the same range */ + outb(PCI9111_AI_RANGE(range0), dev->iobase + PCI9111_AI_RANGE_STAT_REG); /* Set timer pacer */ dev_private->scan_delay = 0; @@ -434,14 +417,14 @@ static void pci9111_handle_fifo_half_full(struct comedi_device *dev, { struct pci9111_private_data *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; + unsigned short *buf = devpriv->ai_bounce_buffer; unsigned int samples; samples = comedi_nsamples_left(s, PCI9111_FIFO_HALF_SIZE); - insw(dev->iobase + PCI9111_AI_FIFO_REG, - devpriv->ai_bounce_buffer, samples); + insw(dev->iobase + PCI9111_AI_FIFO_REG, buf, samples); if (devpriv->scan_delay < 1) { - comedi_buf_write_samples(s, devpriv->ai_bounce_buffer, samples); + comedi_buf_write_samples(s, buf, samples); } else { unsigned int pos = 0; unsigned int to_read; @@ -454,9 +437,7 @@ static void pci9111_handle_fifo_half_full(struct comedi_device *dev, if (to_read > samples - pos) to_read = samples - pos; - comedi_buf_write_samples(s, - devpriv->ai_bounce_buffer + pos, - to_read); + comedi_buf_write_samples(s, buf + pos, to_read); } else { to_read = devpriv->chunk_num_samples - devpriv->chunk_counter; @@ -571,7 +552,7 @@ static int pci9111_ai_insn_read(struct comedi_device *dev, status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG); if ((status & PCI9111_AI_RANGE_MASK) != range) { - outb(range & PCI9111_AI_RANGE_MASK, + outb(PCI9111_AI_RANGE(range), dev->iobase + PCI9111_AI_RANGE_STAT_REG); } diff --git a/kernel/drivers/staging/comedi/drivers/adl_pci9118.c b/kernel/drivers/staging/comedi/drivers/adl_pci9118.c index fb3043dcf..0dff1dbb5 100644 --- a/kernel/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/kernel/drivers/staging/comedi/drivers/adl_pci9118.c @@ -83,12 +83,6 @@ #include "amcc_s5933.h" #include "comedi_8254.h" -#define IORANGE_9118 64 /* I hope */ -#define PCI9118_CHANLEN 255 /* - * len of chanlist, some source say 256, - * but reality looks like 255 :-( - */ - /* * PCI BAR2 Register map (dev->iobase) */ @@ -96,24 +90,24 @@ #define PCI9118_AI_FIFO_REG 0x10 #define PCI9118_AO_REG(x) (0x10 + ((x) * 4)) #define PCI9118_AI_STATUS_REG 0x18 -#define PCI9118_AI_STATUS_NFULL (1 << 8) /* 0=FIFO full (fatal) */ -#define PCI9118_AI_STATUS_NHFULL (1 << 7) /* 0=FIFO half full */ -#define PCI9118_AI_STATUS_NEPTY (1 << 6) /* 0=FIFO empty */ -#define PCI9118_AI_STATUS_ACMP (1 << 5) /* 1=about trigger complete */ -#define PCI9118_AI_STATUS_DTH (1 << 4) /* 1=ext. digital trigger */ -#define PCI9118_AI_STATUS_BOVER (1 << 3) /* 1=burst overrun (fatal) */ -#define PCI9118_AI_STATUS_ADOS (1 << 2) /* 1=A/D over speed (warn) */ -#define PCI9118_AI_STATUS_ADOR (1 << 1) /* 1=A/D overrun (fatal) */ -#define PCI9118_AI_STATUS_ADRDY (1 << 0) /* 1=A/D ready */ +#define PCI9118_AI_STATUS_NFULL BIT(8) /* 0=FIFO full (fatal) */ +#define PCI9118_AI_STATUS_NHFULL BIT(7) /* 0=FIFO half full */ +#define PCI9118_AI_STATUS_NEPTY BIT(6) /* 0=FIFO empty */ +#define PCI9118_AI_STATUS_ACMP BIT(5) /* 1=about trigger complete */ +#define PCI9118_AI_STATUS_DTH BIT(4) /* 1=ext. digital trigger */ +#define PCI9118_AI_STATUS_BOVER BIT(3) /* 1=burst overrun (fatal) */ +#define PCI9118_AI_STATUS_ADOS BIT(2) /* 1=A/D over speed (warn) */ +#define PCI9118_AI_STATUS_ADOR BIT(1) /* 1=A/D overrun (fatal) */ +#define PCI9118_AI_STATUS_ADRDY BIT(0) /* 1=A/D ready */ #define PCI9118_AI_CTRL_REG 0x18 -#define PCI9118_AI_CTRL_UNIP (1 << 7) /* 1=unipolar */ -#define PCI9118_AI_CTRL_DIFF (1 << 6) /* 1=differential inputs */ -#define PCI9118_AI_CTRL_SOFTG (1 << 5) /* 1=8254 software gate */ -#define PCI9118_AI_CTRL_EXTG (1 << 4) /* 1=8254 TGIN(pin 46) gate */ -#define PCI9118_AI_CTRL_EXTM (1 << 3) /* 1=ext. trigger (pin 44) */ -#define PCI9118_AI_CTRL_TMRTR (1 << 2) /* 1=8254 is trigger source */ -#define PCI9118_AI_CTRL_INT (1 << 1) /* 1=enable interrupt */ -#define PCI9118_AI_CTRL_DMA (1 << 0) /* 1=enable DMA */ +#define PCI9118_AI_CTRL_UNIP BIT(7) /* 1=unipolar */ +#define PCI9118_AI_CTRL_DIFF BIT(6) /* 1=differential inputs */ +#define PCI9118_AI_CTRL_SOFTG BIT(5) /* 1=8254 software gate */ +#define PCI9118_AI_CTRL_EXTG BIT(4) /* 1=8254 TGIN(pin 46) gate */ +#define PCI9118_AI_CTRL_EXTM BIT(3) /* 1=ext. trigger (pin 44) */ +#define PCI9118_AI_CTRL_TMRTR BIT(2) /* 1=8254 is trigger source */ +#define PCI9118_AI_CTRL_INT BIT(1) /* 1=enable interrupt */ +#define PCI9118_AI_CTRL_DMA BIT(0) /* 1=enable DMA */ #define PCI9118_DIO_REG 0x1c #define PCI9118_SOFTTRG_REG 0x20 #define PCI9118_AI_CHANLIST_REG 0x24 @@ -122,27 +116,25 @@ #define PCI9118_AI_BURST_NUM_REG 0x28 #define PCI9118_AI_AUTOSCAN_MODE_REG 0x2c #define PCI9118_AI_CFG_REG 0x30 -#define PCI9118_AI_CFG_PDTRG (1 << 7) /* 1=positive trigger */ -#define PCI9118_AI_CFG_PETRG (1 << 6) /* 1=positive ext. trigger */ -#define PCI9118_AI_CFG_BSSH (1 << 5) /* 1=with sample & hold */ -#define PCI9118_AI_CFG_BM (1 << 4) /* 1=burst mode */ -#define PCI9118_AI_CFG_BS (1 << 3) /* 1=burst mode start */ -#define PCI9118_AI_CFG_PM (1 << 2) /* 1=post trigger */ -#define PCI9118_AI_CFG_AM (1 << 1) /* 1=about trigger */ -#define PCI9118_AI_CFG_START (1 << 0) /* 1=trigger start */ +#define PCI9118_AI_CFG_PDTRG BIT(7) /* 1=positive trigger */ +#define PCI9118_AI_CFG_PETRG BIT(6) /* 1=positive ext. trigger */ +#define PCI9118_AI_CFG_BSSH BIT(5) /* 1=with sample & hold */ +#define PCI9118_AI_CFG_BM BIT(4) /* 1=burst mode */ +#define PCI9118_AI_CFG_BS BIT(3) /* 1=burst mode start */ +#define PCI9118_AI_CFG_PM BIT(2) /* 1=post trigger */ +#define PCI9118_AI_CFG_AM BIT(1) /* 1=about trigger */ +#define PCI9118_AI_CFG_START BIT(0) /* 1=trigger start */ #define PCI9118_FIFO_RESET_REG 0x34 #define PCI9118_INT_CTRL_REG 0x38 -#define PCI9118_INT_CTRL_TIMER (1 << 3) /* timer interrupt */ -#define PCI9118_INT_CTRL_ABOUT (1 << 2) /* about trigger complete */ -#define PCI9118_INT_CTRL_HFULL (1 << 1) /* A/D FIFO half full */ -#define PCI9118_INT_CTRL_DTRG (1 << 0) /* ext. digital trigger */ +#define PCI9118_INT_CTRL_TIMER BIT(3) /* timer interrupt */ +#define PCI9118_INT_CTRL_ABOUT BIT(2) /* about trigger complete */ +#define PCI9118_INT_CTRL_HFULL BIT(1) /* A/D FIFO half full */ +#define PCI9118_INT_CTRL_DTRG BIT(0) /* ext. digital trigger */ #define START_AI_EXT 0x01 /* start measure on external trigger */ #define STOP_AI_EXT 0x02 /* stop measure on external trigger */ #define STOP_AI_INT 0x08 /* stop measure on internal trigger */ -#define PCI9118_HALF_FIFO_SZ (1024 / 2) - static const struct comedi_lrange pci9118_ai_range = { 8, { BIP_RANGE(5), @@ -169,11 +161,6 @@ static const struct comedi_lrange pci9118hg_ai_range = { } }; -#define PCI9118_BIPOLAR_RANGES 4 /* - * used for test on mixture - * of BIP/UNI ranges - */ - enum pci9118_boardid { BOARD_PCI9118DG, BOARD_PCI9118HG, @@ -296,51 +283,44 @@ static void pci9118_ai_reset_fifo(struct comedi_device *dev) outl(0, dev->iobase + PCI9118_FIFO_RESET_REG); } -static int check_channel_list(struct comedi_device *dev, - struct comedi_subdevice *s, int n_chan, - unsigned int *chanlist, int frontadd, int backadd) +static int pci9118_ai_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) { struct pci9118_private *devpriv = dev->private; - unsigned int i, differencial = 0, bipolar = 0; + unsigned int range0 = CR_RANGE(cmd->chanlist[0]); + unsigned int aref0 = CR_AREF(cmd->chanlist[0]); + int i; - /* correct channel and range number check itself comedi/range.c */ - if (n_chan < 1) { - dev_err(dev->class_dev, "range/channel list is empty!\n"); + /* single channel scans are always ok */ + if (cmd->chanlist_len == 1) return 0; - } - if ((frontadd + n_chan + backadd) > s->len_chanlist) { - dev_err(dev->class_dev, - "range/channel list is too long for actual configuration!\n"); - return 0; - } - if (CR_AREF(chanlist[0]) == AREF_DIFF) - differencial = 1; /* all input must be diff */ - if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES) - bipolar = 1; /* all input must be bipolar */ - if (n_chan > 1) - for (i = 1; i < n_chan; i++) { /* check S.E/diff */ - if ((CR_AREF(chanlist[i]) == AREF_DIFF) != - (differencial)) { - dev_err(dev->class_dev, - "Differential and single ended inputs can't be mixed!\n"); - return 0; - } - if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) != - (bipolar)) { - dev_err(dev->class_dev, - "Bipolar and unipolar ranges can't be mixed!\n"); - return 0; - } - if (!devpriv->usemux && differencial && - (CR_CHAN(chanlist[i]) >= (s->n_chan / 2))) { - dev_err(dev->class_dev, - "AREF_DIFF is only available for the first 8 channels!\n"); - return 0; - } + 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 (aref != aref0) { + dev_err(dev->class_dev, + "Differential and single ended inputs can't be mixed!\n"); + return -EINVAL; + } + if (comedi_range_is_bipolar(s, range) != + comedi_range_is_bipolar(s, range0)) { + dev_err(dev->class_dev, + "Bipolar and unipolar ranges can't be mixed!\n"); + return -EINVAL; } + if (!devpriv->usemux && aref == AREF_DIFF && + (chan >= (s->n_chan / 2))) { + dev_err(dev->class_dev, + "AREF_DIFF is only available for the first 8 channels!\n"); + return -EINVAL; + } + } - return 1; + return 0; } static void pci9118_set_chanlist(struct comedi_device *dev, @@ -406,8 +386,8 @@ static void pci9118_set_chanlist(struct comedi_device *dev, /* udelay(100); important delay, or first sample will be crippled */ } -static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev, - unsigned int next_buf) +static void pci9118_ai_mode4_switch(struct comedi_device *dev, + unsigned int next_buf) { struct pci9118_private *devpriv = dev->private; struct pci9118_dmabuf *dmabuf = &devpriv->dmabuf[next_buf]; @@ -421,9 +401,9 @@ static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev, outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG); } -static unsigned int valid_samples_in_act_dma_buf(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int n_raw_samples) +static unsigned int pci9118_ai_samples_ready(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int n_raw_samples) { struct pci9118_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; @@ -477,7 +457,7 @@ static unsigned int valid_samples_in_act_dma_buf(struct comedi_device *dev, return n_samples; } -static void move_block_from_dma(struct comedi_device *dev, +static void pci9118_ai_dma_xfer(struct comedi_device *dev, struct comedi_subdevice *s, unsigned short *dma_buffer, unsigned int n_raw_samples) @@ -634,8 +614,8 @@ static void pci9118_ai_munge(struct comedi_device *dev, } } -static void interrupt_pci9118_ai_onesample(struct comedi_device *dev, - struct comedi_subdevice *s) +static void pci9118_ai_get_onesample(struct comedi_device *dev, + struct comedi_subdevice *s) { struct pci9118_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; @@ -651,8 +631,8 @@ static void interrupt_pci9118_ai_onesample(struct comedi_device *dev, } } -static void interrupt_pci9118_ai_dma(struct comedi_device *dev, - struct comedi_subdevice *s) +static void pci9118_ai_get_dma(struct comedi_device *dev, + struct comedi_subdevice *s) { struct pci9118_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; @@ -662,21 +642,19 @@ static void interrupt_pci9118_ai_dma(struct comedi_device *dev, bool more_dma; /* determine whether more DMA buffers to do after this one */ - n_valid = valid_samples_in_act_dma_buf(dev, s, n_all); + n_valid = pci9118_ai_samples_ready(dev, s, n_all); more_dma = n_valid < comedi_nsamples_left(s, n_valid + 1); /* switch DMA buffers and restart DMA if double buffering */ if (more_dma && devpriv->dma_doublebuf) { devpriv->dma_actbuf = 1 - devpriv->dma_actbuf; pci9118_amcc_setup_dma(dev, devpriv->dma_actbuf); - if (devpriv->ai_do == 4) { - interrupt_pci9118_ai_mode4_switch(dev, - devpriv->dma_actbuf); - } + if (devpriv->ai_do == 4) + pci9118_ai_mode4_switch(dev, devpriv->dma_actbuf); } if (n_all) - move_block_from_dma(dev, s, dmabuf->virt, n_all); + pci9118_ai_dma_xfer(dev, s, dmabuf->virt, n_all); if (!devpriv->ai_neverending) { if (s->async->scans_done >= cmd->stop_arg) @@ -690,7 +668,7 @@ static void interrupt_pci9118_ai_dma(struct comedi_device *dev, if (more_dma && !devpriv->dma_doublebuf) { pci9118_amcc_setup_dma(dev, 0); if (devpriv->ai_do == 4) - interrupt_pci9118_ai_mode4_switch(dev, 0); + pci9118_ai_mode4_switch(dev, 0); } } @@ -779,9 +757,9 @@ static irqreturn_t pci9118_interrupt(int irq, void *d) } if (devpriv->usedma) - interrupt_pci9118_ai_dma(dev, s); + pci9118_ai_get_dma(dev, s); else - interrupt_pci9118_ai_onesample(dev, s); + pci9118_ai_get_onesample(dev, s); interrupt_exit: comedi_handle_events(dev, s); @@ -816,17 +794,18 @@ static int pci9118_ai_inttrig(struct comedi_device *dev, return 1; } -static int Compute_and_setup_dma(struct comedi_device *dev, - struct comedi_subdevice *s) +static int pci9118_ai_setup_dma(struct comedi_device *dev, + struct comedi_subdevice *s) { struct pci9118_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; struct pci9118_dmabuf *dmabuf0 = &devpriv->dmabuf[0]; struct pci9118_dmabuf *dmabuf1 = &devpriv->dmabuf[1]; - unsigned int dmalen0, dmalen1, i; + unsigned int dmalen0 = dmabuf0->size; + unsigned int dmalen1 = dmabuf1->size; + unsigned int scan_bytes = devpriv->ai_n_realscanlen * + comedi_bytes_per_sample(s); - dmalen0 = dmabuf0->size; - dmalen1 = dmabuf1->size; /* isn't output buff smaller that our DMA buff? */ if (dmalen0 > s->async->prealloc_bufsz) { /* align to 32bit down */ @@ -839,15 +818,15 @@ static int Compute_and_setup_dma(struct comedi_device *dev, /* we want wake up every scan? */ if (devpriv->ai_flags & CMDF_WAKE_EOS) { - if (dmalen0 < (devpriv->ai_n_realscanlen << 1)) { + if (dmalen0 < scan_bytes) { /* uff, too short DMA buffer, disable EOS support! */ devpriv->ai_flags &= (~CMDF_WAKE_EOS); dev_info(dev->class_dev, "WAR: DMA0 buf too short, can't support CMDF_WAKE_EOS (%d<%d)\n", - dmalen0, devpriv->ai_n_realscanlen << 1); + dmalen0, scan_bytes); } else { /* short first DMA buffer to one scan */ - dmalen0 = devpriv->ai_n_realscanlen << 1; + dmalen0 = scan_bytes; if (dmalen0 < 4) { dev_info(dev->class_dev, "ERR: DMA0 buf len bug? (%d<4)\n", @@ -857,15 +836,15 @@ static int Compute_and_setup_dma(struct comedi_device *dev, } } if (devpriv->ai_flags & CMDF_WAKE_EOS) { - if (dmalen1 < (devpriv->ai_n_realscanlen << 1)) { + if (dmalen1 < scan_bytes) { /* uff, too short DMA buffer, disable EOS support! */ devpriv->ai_flags &= (~CMDF_WAKE_EOS); dev_info(dev->class_dev, "WAR: DMA1 buf too short, can't support CMDF_WAKE_EOS (%d<%d)\n", - dmalen1, devpriv->ai_n_realscanlen << 1); + dmalen1, scan_bytes); } else { /* short second DMA buffer to one scan */ - dmalen1 = devpriv->ai_n_realscanlen << 1; + dmalen1 = scan_bytes; if (dmalen1 < 4) { dev_info(dev->class_dev, "ERR: DMA1 buf len bug? (%d<4)\n", @@ -877,45 +856,39 @@ static int Compute_and_setup_dma(struct comedi_device *dev, /* transfer without CMDF_WAKE_EOS */ if (!(devpriv->ai_flags & CMDF_WAKE_EOS)) { + unsigned int tmp; + /* if it's possible then align DMA buffers to length of scan */ - i = dmalen0; - dmalen0 = - (dmalen0 / (devpriv->ai_n_realscanlen << 1)) * - (devpriv->ai_n_realscanlen << 1); + tmp = dmalen0; + dmalen0 = (dmalen0 / scan_bytes) * scan_bytes; dmalen0 &= ~3L; if (!dmalen0) - dmalen0 = i; /* uff. very long scan? */ - i = dmalen1; - dmalen1 = - (dmalen1 / (devpriv->ai_n_realscanlen << 1)) * - (devpriv->ai_n_realscanlen << 1); + dmalen0 = tmp; /* uff. very long scan? */ + tmp = dmalen1; + dmalen1 = (dmalen1 / scan_bytes) * scan_bytes; dmalen1 &= ~3L; if (!dmalen1) - dmalen1 = i; /* uff. very long scan? */ + dmalen1 = tmp; /* uff. very long scan? */ /* * if measure isn't neverending then test, if it fits whole * into one or two DMA buffers */ if (!devpriv->ai_neverending) { + unsigned long long scanlen; + + scanlen = (unsigned long long)scan_bytes * + cmd->stop_arg; + /* fits whole measure into one DMA buffer? */ - if (dmalen0 > - ((devpriv->ai_n_realscanlen << 1) * - cmd->stop_arg)) { - dmalen0 = - (devpriv->ai_n_realscanlen << 1) * - cmd->stop_arg; + if (dmalen0 > scanlen) { + dmalen0 = scanlen; dmalen0 &= ~3L; - } else { /* - * fits whole measure into - * two DMA buffer? - */ - if (dmalen1 > - ((devpriv->ai_n_realscanlen << 1) * - cmd->stop_arg - dmalen0)) - dmalen1 = - (devpriv->ai_n_realscanlen << 1) * - cmd->stop_arg - dmalen0; - dmalen1 &= ~3L; + } else { + /* fits whole measure into two DMA buffer? */ + if (dmalen1 > (scanlen - dmalen0)) { + dmalen1 = scanlen - dmalen0; + dmalen1 &= ~3L; + } } } } @@ -945,6 +918,7 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) struct comedi_8254 *pacer = dev->pacer; struct comedi_cmd *cmd = &s->async->cmd; unsigned int addchans = 0; + unsigned int scanlen; devpriv->ai12_startstop = 0; devpriv->ai_flags = cmd->flags; @@ -1030,19 +1004,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 cmd->scan_end_arg on output? - */ - (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, cmd->chanlist_len, - cmd->chanlist, devpriv->ai_add_front, - devpriv->ai_add_back)) + scanlen = devpriv->ai_add_front + cmd->chanlist_len + + devpriv->ai_add_back; + /* + * what we must take from card in real to have cmd->scan_end_arg + * on output? + */ + devpriv->ai_n_realscanlen = scanlen * + (cmd->scan_end_arg / cmd->chanlist_len); + + if (scanlen > s->len_chanlist) { + dev_err(dev->class_dev, + "range/channel list is too long for actual configuration!\n"); return -EINVAL; + } /* * Configure analog input and load the chanlist. @@ -1141,7 +1116,7 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_act_dmapos = 0; if (devpriv->usedma) { - Compute_and_setup_dma(dev, s); + pci9118_ai_setup_dma(dev, s); outl(0x02000000 | AINT_WRITE_COMPL, devpriv->iobase_a + AMCC_OP_REG_INTCSR); @@ -1205,9 +1180,6 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev, if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) err |= -EINVAL; - if (cmd->start_src == TRIG_INT && cmd->scan_begin_src == TRIG_INT) - err |= -EINVAL; - if ((cmd->scan_begin_src & (TRIG_TIMER | TRIG_EXT)) && (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW)))) err |= -EINVAL; @@ -1315,10 +1287,13 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev, if (err) return 4; + /* Step 5: check channel list if it exists */ + if (cmd->chanlist) - if (!check_channel_list(dev, s, cmd->chanlist_len, - cmd->chanlist, 0, 0)) - return 5; /* incorrect channels list */ + err |= pci9118_ai_check_chanlist(dev, s, cmd); + + if (err) + return 5; return 0; } @@ -1608,7 +1583,7 @@ static int pci9118_common_attach(struct comedi_device *dev, if (dev->irq) { dev->read_subdev = s; s->subdev_flags |= SDF_CMD_READ; - s->len_chanlist = PCI9118_CHANLEN; + s->len_chanlist = 255; s->do_cmdtest = pci9118_ai_cmdtest; s->do_cmd = pci9118_ai_cmd; s->cancel = pci9118_ai_cancel; diff --git a/kernel/drivers/staging/comedi/drivers/adq12b.c b/kernel/drivers/staging/comedi/drivers/adq12b.c index bc5f97f50..315050454 100644 --- a/kernel/drivers/staging/comedi/drivers/adq12b.c +++ b/kernel/drivers/staging/comedi/drivers/adq12b.c @@ -1,75 +1,59 @@ /* - comedi/drivers/adq12b.c - driver for MicroAxial ADQ12-B data acquisition and control card - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ -/* -Driver: adq12b -Description: driver for MicroAxial ADQ12-B data acquisition and control card -Devices: [MicroAxial] ADQ12-B (adq12b) -Author: jeremy theler <thelerg@ib.cnea.gov.ar> -Updated: Thu, 21 Feb 2008 02:56:27 -0300 -Status: works - -Driver for the acquisition card ADQ12-B (without any add-on). - - - Analog input is subdevice 0 (16 channels single-ended or 8 differential) - - Digital input is subdevice 1 (5 channels) - - Digital output is subdevice 1 (8 channels) - - The PACER is not supported in this version - -If you do not specify any options, they will default to - - # comedi_config /dev/comedi0 adq12b 0x300,0,0 - - option 1: I/O base address. The following table is provided as a help - of the hardware jumpers. - - address jumper JADR - 0x300 1 (factory default) - 0x320 2 - 0x340 3 - 0x360 4 - 0x380 5 - 0x3A0 6 - - option 2: unipolar/bipolar ADC selection: 0 -> bipolar, 1 -> unipolar + * adq12b.c + * Driver for MicroAxial ADQ12-B data acquisition and control card + * written by jeremy theler <thelerg@ib.cnea.gov.ar> + * instituto balseiro + * commission nacional de energia atomica + * universidad nacional de cuyo + * argentina + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - selection comedi_config option JUB - bipolar 0 2-3 (factory default) - unipolar 1 1-2 - - option 3: single-ended/differential AI selection: 0 -> SE, 1 -> differential - - selection comedi_config option JCHA JCHB - single-ended 0 1-2 1-2 (factory default) - differential 1 2-3 2-3 - - written by jeremy theler <thelerg@ib.cnea.gov.ar> - - instituto balseiro - commission nacional de energia atomica - universidad nacional de cuyo - argentina - - 21-feb-2008 - + changed supported devices string (missused the [] and ()) - - 13-oct-2007 - + first try -*/ +/* + * Driver: adq12b + * Description: Driver for MicroAxial ADQ12-B data acquisition and control card + * Devices: [MicroAxial] ADQ12-B (adq12b) + * Author: jeremy theler <thelerg@ib.cnea.gov.ar> + * Updated: Thu, 21 Feb 2008 02:56:27 -0300 + * Status: works + * + * Configuration options: + * [0] - I/O base address (set with hardware jumpers) + * address jumper JADR + * 0x300 1 (factory default) + * 0x320 2 + * 0x340 3 + * 0x360 4 + * 0x380 5 + * 0x3A0 6 + * [1] - Analog Input unipolar/bipolar selection + * selection option JUB + * bipolar 0 2-3 (factory default) + * unipolar 1 1-2 + * [2] - Analog Input single-ended/differential selection + * selection option JCHA JCHB + * single-ended 0 1-2 1-2 (factory default) + * differential 1 2-3 2-3 + * + * Driver for the acquisition card ADQ12-B (without any add-on). + * + * - Analog input is subdevice 0 (16 channels single-ended or 8 differential) + * - Digital input is subdevice 1 (5 channels) + * - Digital output is subdevice 1 (8 channels) + * - The PACER is not supported in this version + */ #include <linux/module.h> #include <linux/delay.h> @@ -78,14 +62,14 @@ If you do not specify any options, they will default to /* address scheme (page 2.17 of the manual) */ #define ADQ12B_CTREG 0x00 -#define ADQ12B_CTREG_MSKP (1 << 7) /* enable pacer interrupt */ -#define ADQ12B_CTREG_GTP (1 << 6) /* enable pacer */ +#define ADQ12B_CTREG_MSKP BIT(7) /* enable pacer interrupt */ +#define ADQ12B_CTREG_GTP BIT(6) /* enable pacer */ #define ADQ12B_CTREG_RANGE(x) ((x) << 4) #define ADQ12B_CTREG_CHAN(x) ((x) << 0) #define ADQ12B_STINR 0x00 -#define ADQ12B_STINR_OUT2 (1 << 7) /* timer 2 output state */ -#define ADQ12B_STINR_OUTP (1 << 6) /* pacer output state */ -#define ADQ12B_STINR_EOC (1 << 5) /* A/D end-of-conversion */ +#define ADQ12B_STINR_OUT2 BIT(7) /* timer 2 output state */ +#define ADQ12B_STINR_OUTP BIT(6) /* pacer output state */ +#define ADQ12B_STINR_EOC BIT(5) /* A/D end-of-conversion */ #define ADQ12B_STINR_IN_MASK (0x1f << 0) #define ADQ12B_OUTBR 0x04 #define ADQ12B_ADLOW 0x08 @@ -145,7 +129,7 @@ static int adq12b_ai_insn_read(struct comedi_device *dev, if (val != devpriv->last_ctreg) { outb(val, dev->iobase + ADQ12B_CTREG); devpriv->last_ctreg = val; - udelay(50); /* wait for the mux to settle */ + usleep_range(50, 100); /* wait for the mux to settle */ } val = inb(dev->iobase + ADQ12B_ADLOW); /* trigger A/D */ diff --git a/kernel/drivers/staging/comedi/drivers/adv_pci1710.c b/kernel/drivers/staging/comedi/drivers/adv_pci1710.c index 0c6aa964c..399c511cf 100644 --- a/kernel/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/kernel/drivers/staging/comedi/drivers/adv_pci1710.c @@ -1,45 +1,30 @@ /* - * comedi/drivers/adv_pci1710.c - * + * adv_pci1710.c + * Comedi driver for Advantech PCI-1710 series boards * Author: Michal Dobes <dobes@tesnet.cz> * * Thanks to ZhenGang Shang <ZhenGang.Shang@Advantech.com.cn> * for testing and information. + */ + +/* + * Driver: adv_pci1710 + * Description: Comedi driver for Advantech PCI-1710 series boards + * Devices: [Advantech] PCI-1710 (adv_pci1710), PCI-1710HG, PCI-1711, + * PCI-1713, PCI-1720, PCI-1731 + * Author: Michal Dobes <dobes@tesnet.cz> + * Status: works * - * hardware driver for Advantech cards: - * card: PCI-1710, PCI-1710HG, PCI-1711, PCI-1713, PCI-1720, PCI-1731 - * driver: pci1710, pci1710hg, pci1711, pci1713, pci1720, pci1731 + * Configuration options: not applicable, uses PCI auto config * - * Options: - * [0] - PCI bus number - if bus number and slot number are 0, - * then driver search for first unused card - * [1] - PCI slot number + * This driver supports AI, AO, DI and DO subdevices. + * AI subdevice supports cmd and insn interface, + * other subdevices support only insn interface. * -*/ -/* -Driver: adv_pci1710 -Description: Advantech PCI-1710, PCI-1710HG, PCI-1711, PCI-1713, - Advantech PCI-1720, PCI-1731 -Author: Michal Dobes <dobes@tesnet.cz> -Devices: [Advantech] PCI-1710 (adv_pci1710), PCI-1710HG (pci1710hg), - PCI-1711 (adv_pci1710), PCI-1713, PCI-1720, - PCI-1731 -Status: works - -This driver supports AI, AO, DI and DO subdevices. -AI subdevice supports cmd and insn interface, -other subdevices support only insn interface. - -The PCI-1710 and PCI-1710HG have the same PCI device ID, so the -driver cannot distinguish between them, as would be normal for a -PCI driver. - -Configuration options: - [0] - PCI bus of device (optional) - [1] - PCI slot of device (optional) - If bus/slot is not specified, the first available PCI - device will be used. -*/ + * The PCI-1710 and PCI-1710HG have the same PCI device ID, so the + * driver cannot distinguish between them, as would be normal for a + * PCI driver. + */ #include <linux/module.h> #include <linux/interrupt.h> @@ -49,48 +34,43 @@ Configuration options: #include "comedi_8254.h" #include "amcc_s5933.h" -#define PCI171x_AD_DATA 0 /* R: A/D data */ -#define PCI171x_SOFTTRG 0 /* W: soft trigger for A/D */ -#define PCI171x_RANGE 2 /* W: A/D gain/range register */ -#define PCI171x_MUX 4 /* W: A/D multiplexor control */ -#define PCI171x_STATUS 6 /* R: status register */ -#define PCI171x_CONTROL 6 /* W: control register */ -#define PCI171x_CLRINT 8 /* W: clear interrupts request */ -#define PCI171x_CLRFIFO 9 /* W: clear FIFO */ -#define PCI171x_DA1 10 /* W: D/A register */ -#define PCI171x_DA2 12 /* W: D/A register */ -#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 - -/* upper bits from status register (PCI171x_STATUS) (lower is same with control - * reg) */ -#define Status_FE 0x0100 /* 1=FIFO is empty */ -#define Status_FH 0x0200 /* 1=FIFO is half full */ -#define Status_FF 0x0400 /* 1=FIFO is full, fatal error */ -#define Status_IRQ 0x0800 /* 1=IRQ occurred */ -/* bits from control register (PCI171x_CONTROL) */ -#define Control_CNT0 0x0040 /* 1=CNT0 have external source, - * 0=have internal 100kHz source */ -#define Control_ONEFH 0x0020 /* 1=IRQ on FIFO is half full, 0=every sample */ -#define Control_IRQEN 0x0010 /* 1=enable IRQ */ -#define Control_GATE 0x0008 /* 1=enable external trigger GATE (8254?) */ -#define Control_EXT 0x0004 /* 1=external trigger source */ -#define Control_PACER 0x0002 /* 1=enable internal 8254 trigger source */ -#define Control_SW 0x0001 /* 1=enable software trigger source */ - -#define PCI1720_DA0 0 /* W: D/A register 0 */ -#define PCI1720_DA1 2 /* W: D/A register 1 */ -#define PCI1720_DA2 4 /* W: D/A register 2 */ -#define PCI1720_DA3 6 /* W: D/A register 3 */ -#define PCI1720_RANGE 8 /* R/W: D/A range register */ -#define PCI1720_SYNCOUT 9 /* W: D/A synchronized output register */ -#define PCI1720_SYNCONT 15 /* R/W: D/A synchronized control */ - -/* D/A synchronized control (PCI1720_SYNCONT) */ -#define Syncont_SC0 1 /* set synchronous output mode */ +/* + * PCI BAR2 Register map (dev->iobase) + */ +#define PCI171X_AD_DATA_REG 0x00 /* R: A/D data */ +#define PCI171X_SOFTTRG_REG 0x00 /* W: soft trigger for A/D */ +#define PCI171X_RANGE_REG 0x02 /* W: A/D gain/range register */ +#define PCI171X_MUX_REG 0x04 /* W: A/D multiplexor control */ +#define PCI171X_STATUS_REG 0x06 /* R: status register */ +#define PCI171X_STATUS_IRQ BIT(11) /* 1=IRQ occurred */ +#define PCI171X_STATUS_FF BIT(10) /* 1=FIFO is full, fatal error */ +#define PCI171X_STATUS_FH BIT(9) /* 1=FIFO is half full */ +#define PCI171X_STATUS_FE BIT(8) /* 1=FIFO is empty */ +#define PCI171X_CTRL_REG 0x06 /* W: control register */ +#define PCI171X_CTRL_CNT0 BIT(6) /* 1=ext. clk, 0=int. 100kHz clk */ +#define PCI171X_CTRL_ONEFH BIT(5) /* 1=on FIFO half full, 0=on sample */ +#define PCI171X_CTRL_IRQEN BIT(4) /* 1=enable IRQ */ +#define PCI171X_CTRL_GATE BIT(3) /* 1=enable ext. trigger GATE (8254?) */ +#define PCI171X_CTRL_EXT BIT(2) /* 1=enable ext. trigger source */ +#define PCI171X_CTRL_PACER BIT(1) /* 1=enable int. 8254 trigger source */ +#define PCI171X_CTRL_SW BIT(0) /* 1=enable software trigger source */ +#define PCI171X_CLRINT_REG 0x08 /* W: clear interrupts request */ +#define PCI171X_CLRFIFO_REG 0x09 /* W: clear FIFO */ +#define PCI171X_DA_REG(x) (0x0a + ((x) * 2)) /* W: D/A register */ +#define PCI171X_DAREF_REG 0x0e /* W: D/A reference control */ +#define PCI171X_DI_REG 0x10 /* R: digital inputs */ +#define PCI171X_DO_REG 0x10 /* W: digital outputs */ +#define PCI171X_TIMER_BASE 0x18 /* R/W: 8254 timer */ + +/* + * PCI-1720 only has analog outputs and has a different + * register map (dev->iobase) + */ +#define PCI1720_DA_REG(x) (0x00 + ((x) * 2)) /* W: D/A registers */ +#define PCI1720_RANGE_REG 0x08 /* R/W: D/A range register */ +#define PCI1720_SYNC_REG 0x09 /* W: D/A synchronized output */ +#define PCI1720_SYNC_CTRL_REG 0x0f /* R/W: D/A synchronized control */ +#define PCI1720_SYNC_CTRL_SC0 BIT(0) /* set synchronous output mode */ static const struct comedi_lrange range_pci1710_3 = { 9, { @@ -244,10 +224,10 @@ static const struct boardtype boardtypes[] = { struct pci1710_private { unsigned int max_samples; - unsigned int CntrlReg; /* Control register */ + unsigned int ctrl; /* control register value */ + unsigned int ctrl_ext; /* used to switch from TRIG_EXT to TRIG_xxx */ + unsigned int mux_ext; /* used to set the channel interval to scan */ unsigned char ai_et; - unsigned int ai_et_CntrlReg; - unsigned int ai_et_MuxVal; unsigned int act_chanlist[32]; /* list of scanned channel */ unsigned char saved_seglen; /* len of the non-repeating chanlist */ unsigned char da_ranges; /* copy of D/A outpit range register */ @@ -342,8 +322,8 @@ static void pci171x_ai_setup_chanlist(struct comedi_device *dev, rangeval |= 0x0020; /* select channel and set range */ - outw(chan | (chan << 8), dev->iobase + PCI171x_MUX); - outw(rangeval, dev->iobase + PCI171x_RANGE); + outw(chan | (chan << 8), dev->iobase + PCI171X_MUX_REG); + outw(rangeval, dev->iobase + PCI171X_RANGE_REG); devpriv->act_chanlist[i] = chan; } @@ -351,8 +331,8 @@ static void pci171x_ai_setup_chanlist(struct comedi_device *dev, devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]); /* select channel interval to scan */ - devpriv->ai_et_MuxVal = first_chan | (last_chan << 8); - outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX); + devpriv->mux_ext = first_chan | (last_chan << 8); + outw(devpriv->mux_ext, dev->iobase + PCI171X_MUX_REG); } static int pci171x_ai_eoc(struct comedi_device *dev, @@ -362,8 +342,8 @@ static int pci171x_ai_eoc(struct comedi_device *dev, { unsigned int status; - status = inw(dev->iobase + PCI171x_STATUS); - if ((status & Status_FE) == 0) + status = inw(dev->iobase + PCI171X_STATUS_REG); + if ((status & PCI171X_STATUS_FE) == 0) return 0; return -EBUSY; } @@ -378,7 +358,7 @@ static int pci171x_ai_read_sample(struct comedi_device *dev, unsigned int sample; unsigned int chan; - sample = inw(dev->iobase + PCI171x_AD_DATA); + sample = inw(dev->iobase + PCI171X_AD_DATA_REG); if (!board->is_pci1713) { /* * The upper 4 bits of the 16-bit sample are the channel number @@ -406,18 +386,19 @@ static int pci171x_ai_insn_read(struct comedi_device *dev, int ret = 0; int i; - devpriv->CntrlReg &= Control_CNT0; - devpriv->CntrlReg |= Control_SW; /* set software trigger */ - outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); - outb(0, dev->iobase + PCI171x_CLRFIFO); - outb(0, dev->iobase + PCI171x_CLRINT); + devpriv->ctrl &= PCI171X_CTRL_CNT0; + devpriv->ctrl |= PCI171X_CTRL_SW; /* set software trigger */ + outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); + outb(0, dev->iobase + PCI171X_CLRFIFO_REG); + outb(0, dev->iobase + PCI171X_CLRINT_REG); pci171x_ai_setup_chanlist(dev, s, &insn->chanspec, 1, 1); for (i = 0; i < insn->n; i++) { unsigned int val; - outw(0, dev->iobase + PCI171x_SOFTTRG); /* start conversion */ + /* start conversion */ + outw(0, dev->iobase + PCI171X_SOFTTRG_REG); ret = comedi_timeout(dev, s, insn, pci171x_ai_eoc, 0); if (ret) @@ -430,8 +411,8 @@ static int pci171x_ai_insn_read(struct comedi_device *dev, data[i] = val; } - outb(0, dev->iobase + PCI171x_CLRFIFO); - outb(0, dev->iobase + PCI171x_CLRINT); + outb(0, dev->iobase + PCI171X_CLRFIFO_REG); + outb(0, dev->iobase + PCI171X_CLRINT_REG); return ret ? ret : insn->n; } @@ -444,17 +425,16 @@ static int pci171x_ao_insn_write(struct comedi_device *dev, struct pci1710_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); unsigned int range = CR_RANGE(insn->chanspec); - unsigned int reg = chan ? PCI171x_DA2 : PCI171x_DA1; unsigned int val = s->readback[chan]; int i; devpriv->da_ranges &= ~(1 << (chan << 1)); devpriv->da_ranges |= (range << (chan << 1)); - outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); + outw(devpriv->da_ranges, dev->iobase + PCI171X_DAREF_REG); for (i = 0; i < insn->n; i++) { val = data[i]; - outw(val, dev->iobase + reg); + outw(val, dev->iobase + PCI171X_DA_REG(chan)); } s->readback[chan] = val; @@ -467,7 +447,7 @@ static int pci171x_di_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - data[1] = inw(dev->iobase + PCI171x_DI); + data[1] = inw(dev->iobase + PCI171X_DI_REG); return insn->n; } @@ -478,7 +458,7 @@ static int pci171x_do_insn_bits(struct comedi_device *dev, unsigned int *data) { if (comedi_dio_update_state(s, data)) - outw(s->state, dev->iobase + PCI171x_DO); + outw(s->state, dev->iobase + PCI171X_DO_REG); data[1] = s->state; @@ -499,15 +479,15 @@ static int pci1720_ao_insn_write(struct comedi_device *dev, val = devpriv->da_ranges & (~(0x03 << (chan << 1))); val |= (range << (chan << 1)); if (val != devpriv->da_ranges) { - outb(val, dev->iobase + PCI1720_RANGE); + outb(val, dev->iobase + PCI1720_RANGE_REG); devpriv->da_ranges = val; } val = s->readback[chan]; for (i = 0; i < insn->n; i++) { val = data[i]; - outw(val, dev->iobase + PCI1720_DA0 + (chan << 1)); - outb(0, dev->iobase + PCI1720_SYNCOUT); /* update outputs */ + outw(val, dev->iobase + PCI1720_DA_REG(chan)); + outb(0, dev->iobase + PCI1720_SYNC_REG); /* update outputs */ } s->readback[chan] = val; @@ -520,13 +500,13 @@ static int pci171x_ai_cancel(struct comedi_device *dev, { struct pci1710_private *devpriv = dev->private; - devpriv->CntrlReg &= Control_CNT0; - devpriv->CntrlReg |= Control_SW; + devpriv->ctrl &= PCI171X_CTRL_CNT0; + devpriv->ctrl |= PCI171X_CTRL_SW; /* reset any operations */ - outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); + outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); comedi_8254_pacer_enable(dev->pacer, 1, 2, false); - outb(0, dev->iobase + PCI171x_CLRFIFO); - outb(0, dev->iobase + PCI171x_CLRINT); + outb(0, dev->iobase + PCI171X_CLRFIFO_REG); + outb(0, dev->iobase + PCI171X_CLRINT_REG); return 0; } @@ -539,22 +519,22 @@ static void pci1710_handle_every_sample(struct comedi_device *dev, unsigned int val; int ret; - status = inw(dev->iobase + PCI171x_STATUS); - if (status & Status_FE) { + status = inw(dev->iobase + PCI171X_STATUS_REG); + if (status & PCI171X_STATUS_FE) { dev_dbg(dev->class_dev, "A/D FIFO empty (%4x)\n", status); s->async->events |= COMEDI_CB_ERROR; return; } - if (status & Status_FF) { + if (status & PCI171X_STATUS_FF) { dev_dbg(dev->class_dev, "A/D FIFO Full status (Fatal Error!) (%4x)\n", status); s->async->events |= COMEDI_CB_ERROR; return; } - outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ + outb(0, dev->iobase + PCI171X_CLRINT_REG); - for (; !(inw(dev->iobase + PCI171x_STATUS) & Status_FE);) { + for (; !(inw(dev->iobase + PCI171X_STATUS_REG) & PCI171X_STATUS_FE);) { ret = pci171x_ai_read_sample(dev, s, s->async->cur_chan, &val); if (ret) { s->async->events |= COMEDI_CB_ERROR; @@ -570,7 +550,7 @@ static void pci1710_handle_every_sample(struct comedi_device *dev, } } - outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ + outb(0, dev->iobase + PCI171X_CLRINT_REG); } static void pci1710_handle_fifo(struct comedi_device *dev, @@ -582,13 +562,13 @@ static void pci1710_handle_fifo(struct comedi_device *dev, unsigned int status; int i; - status = inw(dev->iobase + PCI171x_STATUS); - if (!(status & Status_FH)) { + status = inw(dev->iobase + PCI171X_STATUS_REG); + if (!(status & PCI171X_STATUS_FH)) { dev_dbg(dev->class_dev, "A/D FIFO not half full!\n"); async->events |= COMEDI_CB_ERROR; return; } - if (status & Status_FF) { + if (status & PCI171X_STATUS_FF) { dev_dbg(dev->class_dev, "A/D FIFO Full status (Fatal Error!)\n"); async->events |= COMEDI_CB_ERROR; @@ -615,7 +595,7 @@ static void pci1710_handle_fifo(struct comedi_device *dev, } } - outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ + outb(0, dev->iobase + PCI171X_CLRINT_REG); } static irqreturn_t interrupt_service_pci1710(int irq, void *d) @@ -632,19 +612,20 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d) cmd = &s->async->cmd; /* is this interrupt from our board? */ - if (!(inw(dev->iobase + PCI171x_STATUS) & Status_IRQ)) + if (!(inw(dev->iobase + PCI171X_STATUS_REG) & PCI171X_STATUS_IRQ)) return IRQ_NONE; /* no, exit */ if (devpriv->ai_et) { /* Switch from initial TRIG_EXT to TRIG_xxx. */ devpriv->ai_et = 0; - devpriv->CntrlReg &= Control_CNT0; - devpriv->CntrlReg |= Control_SW; /* set software trigger */ - outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); - devpriv->CntrlReg = devpriv->ai_et_CntrlReg; - outb(0, dev->iobase + PCI171x_CLRFIFO); - outb(0, dev->iobase + PCI171x_CLRINT); - outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX); - outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); + devpriv->ctrl &= PCI171X_CTRL_CNT0; + devpriv->ctrl |= PCI171X_CTRL_SW; /* set software trigger */ + outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); + devpriv->ctrl = devpriv->ctrl_ext; + outb(0, dev->iobase + PCI171X_CLRFIFO_REG); + outb(0, dev->iobase + PCI171X_CLRINT_REG); + /* no sample on this interrupt; reset the channel interval */ + outw(devpriv->mux_ext, dev->iobase + PCI171X_MUX_REG); + outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); comedi_8254_pacer_enable(dev->pacer, 1, 2, true); return IRQ_HANDLED; } @@ -667,33 +648,34 @@ static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) pci171x_ai_setup_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, devpriv->saved_seglen); - outb(0, dev->iobase + PCI171x_CLRFIFO); - outb(0, dev->iobase + PCI171x_CLRINT); + outb(0, dev->iobase + PCI171X_CLRFIFO_REG); + outb(0, dev->iobase + PCI171X_CLRINT_REG); - devpriv->CntrlReg &= Control_CNT0; + devpriv->ctrl &= PCI171X_CTRL_CNT0; if ((cmd->flags & CMDF_WAKE_EOS) == 0) - devpriv->CntrlReg |= Control_ONEFH; + devpriv->ctrl |= PCI171X_CTRL_ONEFH; if (cmd->convert_src == TRIG_TIMER) { comedi_8254_update_divisors(dev->pacer); - devpriv->CntrlReg |= Control_PACER | Control_IRQEN; + devpriv->ctrl |= PCI171X_CTRL_PACER | PCI171X_CTRL_IRQEN; 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->ctrl_ext = devpriv->ctrl; + devpriv->ctrl &= ~(PCI171X_CTRL_PACER | + PCI171X_CTRL_ONEFH | + PCI171X_CTRL_GATE); + devpriv->ctrl |= PCI171X_CTRL_EXT; devpriv->ai_et = 1; } else { /* TRIG_NOW */ devpriv->ai_et = 0; } - outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); + outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); if (cmd->start_src == TRIG_NOW) comedi_8254_pacer_enable(dev->pacer, 1, 2, true); } else { /* TRIG_EXT */ - devpriv->CntrlReg |= Control_EXT | Control_IRQEN; - outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); + devpriv->ctrl |= PCI171X_CTRL_EXT | PCI171X_CTRL_IRQEN; + outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); } return 0; @@ -782,18 +764,18 @@ static int pci171x_insn_counter_config(struct comedi_device *dev, case INSN_CONFIG_SET_CLOCK_SRC: switch (data[1]) { case 0: /* internal */ - devpriv->ai_et_CntrlReg &= ~Control_CNT0; + devpriv->ctrl_ext &= ~PCI171X_CTRL_CNT0; break; case 1: /* external */ - devpriv->ai_et_CntrlReg |= Control_CNT0; + devpriv->ctrl_ext |= PCI171X_CTRL_CNT0; break; default: return -EINVAL; } - outw(devpriv->ai_et_CntrlReg, dev->iobase + PCI171x_CONTROL); + outw(devpriv->ctrl_ext, dev->iobase + PCI171X_CTRL_REG); break; case INSN_CONFIG_GET_CLOCK_SRC: - if (devpriv->ai_et_CntrlReg & Control_CNT0) { + if (devpriv->ctrl_ext & PCI171X_CTRL_CNT0) { data[1] = 1; data[2] = 0; } else { @@ -814,21 +796,21 @@ static int pci171x_reset(struct comedi_device *dev) struct pci1710_private *devpriv = dev->private; /* Software trigger, CNT0=external */ - devpriv->CntrlReg = Control_SW | Control_CNT0; + devpriv->ctrl = PCI171X_CTRL_SW | PCI171X_CTRL_CNT0; /* reset any operations */ - outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); - outb(0, dev->iobase + PCI171x_CLRFIFO); /* clear FIFO */ - outb(0, dev->iobase + PCI171x_CLRINT); /* clear INT request */ + outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); + outb(0, dev->iobase + PCI171X_CLRFIFO_REG); + outb(0, dev->iobase + PCI171X_CLRINT_REG); devpriv->da_ranges = 0; if (board->has_ao) { - /* set DACs to 0..5V */ - outb(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); - outw(0, dev->iobase + PCI171x_DA1); /* set DA outputs to 0V */ - outw(0, dev->iobase + PCI171x_DA2); + /* set DACs to 0..5V and outputs to 0V */ + outb(devpriv->da_ranges, dev->iobase + PCI171X_DAREF_REG); + outw(0, dev->iobase + PCI171X_DA_REG(0)); + outw(0, dev->iobase + PCI171X_DA_REG(1)); } - outw(0, dev->iobase + PCI171x_DO); /* digital outputs to 0 */ - outb(0, dev->iobase + PCI171x_CLRFIFO); /* clear FIFO */ - outb(0, dev->iobase + PCI171x_CLRINT); /* clear INT request */ + outw(0, dev->iobase + PCI171X_DO_REG); /* digital outputs to 0 */ + outb(0, dev->iobase + PCI171X_CLRFIFO_REG); + outb(0, dev->iobase + PCI171X_CLRINT_REG); return 0; } @@ -837,15 +819,15 @@ static int pci1720_reset(struct comedi_device *dev) { struct pci1710_private *devpriv = dev->private; /* set synchronous output mode */ - outb(Syncont_SC0, dev->iobase + PCI1720_SYNCONT); + outb(PCI1720_SYNC_CTRL_SC0, dev->iobase + PCI1720_SYNC_CTRL_REG); devpriv->da_ranges = 0xAA; - /* set all ranges to +/-5V */ - outb(devpriv->da_ranges, dev->iobase + PCI1720_RANGE); - outw(0x0800, dev->iobase + PCI1720_DA0); /* set outputs to 0V */ - outw(0x0800, dev->iobase + PCI1720_DA1); - outw(0x0800, dev->iobase + PCI1720_DA2); - outw(0x0800, dev->iobase + PCI1720_DA3); - outb(0, dev->iobase + PCI1720_SYNCOUT); /* update outputs */ + /* set all ranges to +/-5V and outputs to 0V */ + outb(devpriv->da_ranges, dev->iobase + PCI1720_RANGE_REG); + outw(0x0800, dev->iobase + PCI1720_DA_REG(0)); + outw(0x0800, dev->iobase + PCI1720_DA_REG(1)); + outw(0x0800, dev->iobase + PCI1720_DA_REG(2)); + outw(0x0800, dev->iobase + PCI1720_DA_REG(3)); + outb(0, dev->iobase + PCI1720_SYNC_REG); /* update outputs */ return 0; } diff --git a/kernel/drivers/staging/comedi/drivers/adv_pci1723.c b/kernel/drivers/staging/comedi/drivers/adv_pci1723.c index 1921a97cc..f82afd947 100644 --- a/kernel/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/kernel/drivers/staging/comedi/drivers/adv_pci1723.c @@ -51,25 +51,27 @@ #define PCI1723_BOARD_ID_REG 0x10 #define PCI1723_BOARD_ID_MASK (0xf << 0) #define PCI1723_SYNC_CTRL_REG 0x12 -#define PCI1723_SYNC_CTRL_ASYNC (0 << 0) -#define PCI1723_SYNC_CTRL_SYNC (1 << 0) +#define PCI1723_SYNC_CTRL(x) (((x) & 0x1) << 0) +#define PCI1723_SYNC_CTRL_ASYNC PCI1723_SYNC_CTRL(0) +#define PCI1723_SYNC_CTRL_SYNC PCI1723_SYNC_CTRL(1) #define PCI1723_CTRL_REG 0x14 -#define PCI1723_CTRL_BUSY (1 << 15) -#define PCI1723_CTRL_INIT (1 << 14) -#define PCI1723_CTRL_SELF (1 << 8) +#define PCI1723_CTRL_BUSY BIT(15) +#define PCI1723_CTRL_INIT BIT(14) +#define PCI1723_CTRL_SELF BIT(8) #define PCI1723_CTRL_IDX(x) (((x) & 0x3) << 6) #define PCI1723_CTRL_RANGE(x) (((x) & 0x3) << 4) -#define PCI1723_CTRL_GAIN (0 << 3) -#define PCI1723_CTRL_OFFSET (1 << 3) +#define PCI1723_CTRL_SEL(x) (((x) & 0x1) << 3) +#define PCI1723_CTRL_GAIN PCI1723_CTRL_SEL(0) +#define PCI1723_CTRL_OFFSET PCI1723_CTRL_SEL(1) #define PCI1723_CTRL_CHAN(x) (((x) & 0x7) << 0) #define PCI1723_CALIB_CTRL_REG 0x16 -#define PCI1723_CALIB_CTRL_CS (1 << 2) -#define PCI1723_CALIB_CTRL_DAT (1 << 1) -#define PCI1723_CALIB_CTRL_CLK (1 << 0) +#define PCI1723_CALIB_CTRL_CS BIT(2) +#define PCI1723_CALIB_CTRL_DAT BIT(1) +#define PCI1723_CALIB_CTRL_CLK BIT(0) #define PCI1723_CALIB_STROBE_REG 0x18 #define PCI1723_DIO_CTRL_REG 0x1a -#define PCI1723_DIO_CTRL_HDIO (1 << 1) -#define PCI1723_DIO_CTRL_LDIO (1 << 0) +#define PCI1723_DIO_CTRL_HDIO BIT(1) +#define PCI1723_DIO_CTRL_LDIO BIT(0) #define PCI1723_DIO_DATA_REG 0x1c #define PCI1723_CALIB_DATA_REG 0x1e #define PCI1723_SYNC_STROBE_REG 0x20 @@ -77,9 +79,10 @@ #define PCI1723_RESET_CALIB_STROBE_REG 0x24 #define PCI1723_RANGE_STROBE_REG 0x26 #define PCI1723_VREF_REG 0x28 -#define PCI1723_VREF_NEG10V (0 << 0) -#define PCI1723_VREF_0V (1 << 0) -#define PCI1723_VREF_POS10V (3 << 0) +#define PCI1723_VREF(x) (((x) & 0x3) << 0) +#define PCI1723_VREF_NEG10V PCI1723_VREF(0) +#define PCI1723_VREF_0V PCI1723_VREF(1) +#define PCI1723_VREF_POS10V PCI1723_VREF(3) static int pci1723_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, diff --git a/kernel/drivers/staging/comedi/drivers/adv_pci1724.c b/kernel/drivers/staging/comedi/drivers/adv_pci1724.c index f7a7dab01..bf6a8f101 100644 --- a/kernel/drivers/staging/comedi/drivers/adv_pci1724.c +++ b/kernel/drivers/staging/comedi/drivers/adv_pci1724.c @@ -54,16 +54,17 @@ * PCI bar 2 Register I/O map (dev->iobase) */ #define PCI1724_DAC_CTRL_REG 0x00 -#define PCI1724_DAC_CTRL_GX(x) (1 << (20 + ((x) / 8))) +#define PCI1724_DAC_CTRL_GX(x) BIT(20 + ((x) / 8)) #define PCI1724_DAC_CTRL_CX(x) (((x) % 8) << 16) -#define PCI1724_DAC_CTRL_MODE_GAIN (1 << 14) -#define PCI1724_DAC_CTRL_MODE_OFFSET (2 << 14) -#define PCI1724_DAC_CTRL_MODE_NORMAL (3 << 14) -#define PCI1724_DAC_CTRL_MODE_MASK (3 << 14) +#define PCI1724_DAC_CTRL_MODE(x) (((x) & 0x3) << 14) +#define PCI1724_DAC_CTRL_MODE_GAIN PCI1724_DAC_CTRL_MODE(1) +#define PCI1724_DAC_CTRL_MODE_OFFSET PCI1724_DAC_CTRL_MODE(2) +#define PCI1724_DAC_CTRL_MODE_NORMAL PCI1724_DAC_CTRL_MODE(3) +#define PCI1724_DAC_CTRL_MODE_MASK PCI1724_DAC_CTRL_MODE(3) #define PCI1724_DAC_CTRL_DATA(x) (((x) & 0x3fff) << 0) #define PCI1724_SYNC_CTRL_REG 0x04 -#define PCI1724_SYNC_CTRL_DACSTAT (1 << 1) -#define PCI1724_SYNC_CTRL_SYN (1 << 0) +#define PCI1724_SYNC_CTRL_DACSTAT BIT(1) +#define PCI1724_SYNC_CTRL_SYN BIT(0) #define PCI1724_EEPROM_CTRL_REG 0x08 #define PCI1724_SYNC_TRIG_REG 0x0c /* any value works */ #define PCI1724_BOARD_ID_REG 0x10 @@ -180,11 +181,7 @@ static int adv_pci1724_auto_attach(struct comedi_device *dev, s->insn_write = adv_pci1724_insn_write; s->private = (void *)PCI1724_DAC_CTRL_MODE_GAIN; - ret = comedi_alloc_subdev_readback(s); - if (ret) - return ret; - - return 0; + return comedi_alloc_subdev_readback(s); } static struct comedi_driver adv_pci1724_driver = { diff --git a/kernel/drivers/staging/comedi/drivers/adv_pci_dio.c b/kernel/drivers/staging/comedi/drivers/adv_pci_dio.c index 456e87013..f1b3c5aa8 100644 --- a/kernel/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/kernel/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -732,9 +732,9 @@ static int pci1760_reset(struct comedi_device *dev) */ static int pci_dio_reset(struct comedi_device *dev) { - const struct dio_boardtype *this_board = dev->board_ptr; + const struct dio_boardtype *board = dev->board_ptr; - switch (this_board->cardtype) { + switch (board->cardtype) { case TYPE_PCI1730: outb(0, dev->iobase + PCI1730_DO); /* clear outputs */ outb(0, dev->iobase + PCI1730_DO + 1); @@ -887,7 +887,7 @@ static int pci_dio_add_di(struct comedi_device *dev, struct comedi_subdevice *s, const struct diosubd_data *d) { - const struct dio_boardtype *this_board = dev->board_ptr; + const struct dio_boardtype *board = dev->board_ptr; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE | d->specflags; @@ -897,7 +897,7 @@ static int pci_dio_add_di(struct comedi_device *dev, s->maxdata = 1; s->len_chanlist = d->chans; s->range_table = &range_digital; - switch (this_board->io_access) { + switch (board->io_access) { case IO_8b: s->insn_bits = pci_dio_insn_bits_di_b; break; @@ -917,7 +917,7 @@ static int pci_dio_add_do(struct comedi_device *dev, struct comedi_subdevice *s, const struct diosubd_data *d) { - const struct dio_boardtype *this_board = dev->board_ptr; + const struct dio_boardtype *board = dev->board_ptr; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; @@ -928,7 +928,7 @@ static int pci_dio_add_do(struct comedi_device *dev, s->len_chanlist = d->chans; s->range_table = &range_digital; s->state = 0; - switch (this_board->io_access) { + switch (board->io_access) { case IO_8b: s->insn_bits = pci_dio_insn_bits_do_b; break; @@ -978,17 +978,17 @@ static int pci_dio_auto_attach(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct dio_boardtype *this_board = NULL; + const struct dio_boardtype *board = NULL; struct pci_dio_private *devpriv; struct comedi_subdevice *s; int ret, subdev, i, j; if (context < ARRAY_SIZE(boardtypes)) - this_board = &boardtypes[context]; - if (!this_board) + board = &boardtypes[context]; + if (!board) return -ENODEV; - dev->board_ptr = this_board; - dev->board_name = this_board->name; + dev->board_ptr = board; + dev->board_name = board->name; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -997,50 +997,50 @@ static int pci_dio_auto_attach(struct comedi_device *dev, ret = comedi_pci_enable(dev); if (ret) return ret; - dev->iobase = pci_resource_start(pcidev, this_board->main_pci_region); + dev->iobase = pci_resource_start(pcidev, board->main_pci_region); - ret = comedi_alloc_subdevices(dev, this_board->nsubdevs); + ret = comedi_alloc_subdevices(dev, board->nsubdevs); if (ret) return ret; subdev = 0; for (i = 0; i < MAX_DI_SUBDEVS; i++) - if (this_board->sdi[i].chans) { + if (board->sdi[i].chans) { s = &dev->subdevices[subdev]; - pci_dio_add_di(dev, s, &this_board->sdi[i]); + pci_dio_add_di(dev, s, &board->sdi[i]); subdev++; } for (i = 0; i < MAX_DO_SUBDEVS; i++) - if (this_board->sdo[i].chans) { + if (board->sdo[i].chans) { s = &dev->subdevices[subdev]; - pci_dio_add_do(dev, s, &this_board->sdo[i]); + pci_dio_add_do(dev, s, &board->sdo[i]); subdev++; } for (i = 0; i < MAX_DIO_SUBDEVG; i++) - for (j = 0; j < this_board->sdio[i].regs; j++) { + for (j = 0; j < board->sdio[i].regs; j++) { s = &dev->subdevices[subdev]; ret = subdev_8255_init(dev, s, NULL, - this_board->sdio[i].addr + + board->sdio[i].addr + j * I8255_SIZE); if (ret) return ret; subdev++; } - if (this_board->boardid.chans) { + if (board->boardid.chans) { s = &dev->subdevices[subdev]; s->type = COMEDI_SUBD_DI; - pci_dio_add_di(dev, s, &this_board->boardid); + pci_dio_add_di(dev, s, &board->boardid); subdev++; } - if (this_board->timer_regbase) { + if (board->timer_regbase) { s = &dev->subdevices[subdev]; dev->pacer = comedi_8254_init(dev->iobase + - this_board->timer_regbase, + board->timer_regbase, 0, I8254_IO8, 0); if (!dev->pacer) return -ENOMEM; @@ -1050,7 +1050,7 @@ static int pci_dio_auto_attach(struct comedi_device *dev, subdev++; } - if (this_board->cardtype == TYPE_PCI1760) + if (board->cardtype == TYPE_PCI1760) pci1760_attach(dev); pci_dio_reset(dev); diff --git a/kernel/drivers/staging/comedi/drivers/aio_aio12_8.c b/kernel/drivers/staging/comedi/drivers/aio_aio12_8.c index fbc3e5aa9..43a0ce572 100644 --- a/kernel/drivers/staging/comedi/drivers/aio_aio12_8.c +++ b/kernel/drivers/staging/comedi/drivers/aio_aio12_8.c @@ -1,99 +1,107 @@ /* - - comedi/drivers/aio_aio12_8.c - - Driver for Access I/O Products PC-104 AIO12-8 Analog I/O Board - Copyright (C) 2006 C&C Technologies, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * aio_aio12_8.c + * Driver for Access I/O Products PC-104 AIO12-8 Analog I/O Board + * Copyright (C) 2006 C&C Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ /* - -Driver: aio_aio12_8 -Description: Access I/O Products PC-104 AIO12-8 Analog I/O Board -Author: Pablo Mejia <pablo.mejia@cctechnol.com> -Devices: [Access I/O] PC-104 AIO12-8 (aio_aio12_8) - [Access I/O] PC-104 AI12-8 (aio_ai12_8) - [Access I/O] PC-104 AO12-8 (aio_ao12_8) -Status: experimental - -Configuration Options: - [0] - I/O port base address - -Notes: - - Only synchronous operations are supported. - -*/ + * Driver: aio_aio12_8 + * Description: Access I/O Products PC-104 AIO12-8 Analog I/O Board + * Author: Pablo Mejia <pablo.mejia@cctechnol.com> + * Devices: [Access I/O] PC-104 AIO12-8 (aio_aio12_8), + * [Access I/O] PC-104 AI12-8 (aio_ai12_8), + * [Access I/O] PC-104 AO12-4 (aio_ao12_4) + * Status: experimental + * + * Configuration Options: + * [0] - I/O port base address + * + * Notes: + * Only synchronous operations are supported. + */ #include <linux/module.h> #include "../comedidev.h" + +#include "comedi_8254.h" #include "8255.h" /* * Register map */ #define AIO12_8_STATUS_REG 0x00 -#define AIO12_8_STATUS_ADC_EOC (1 << 7) -#define AIO12_8_STATUS_PORT_C_COS (1 << 6) -#define AIO12_8_STATUS_IRQ_ENA (1 << 2) +#define AIO12_8_STATUS_ADC_EOC BIT(7) +#define AIO12_8_STATUS_PORT_C_COS BIT(6) +#define AIO12_8_STATUS_IRQ_ENA BIT(2) #define AIO12_8_INTERRUPT_REG 0x01 -#define AIO12_8_INTERRUPT_ADC (1 << 7) -#define AIO12_8_INTERRUPT_COS (1 << 6) -#define AIO12_8_INTERRUPT_COUNTER1 (1 << 5) -#define AIO12_8_INTERRUPT_PORT_C3 (1 << 4) -#define AIO12_8_INTERRUPT_PORT_C0 (1 << 3) -#define AIO12_8_INTERRUPT_ENA (1 << 2) +#define AIO12_8_INTERRUPT_ADC BIT(7) +#define AIO12_8_INTERRUPT_COS BIT(6) +#define AIO12_8_INTERRUPT_COUNTER1 BIT(5) +#define AIO12_8_INTERRUPT_PORT_C3 BIT(4) +#define AIO12_8_INTERRUPT_PORT_C0 BIT(3) +#define AIO12_8_INTERRUPT_ENA BIT(2) #define AIO12_8_ADC_REG 0x02 -#define AIO12_8_ADC_MODE_NORMAL (0 << 6) -#define AIO12_8_ADC_MODE_INT_CLK (1 << 6) -#define AIO12_8_ADC_MODE_STANDBY (2 << 6) -#define AIO12_8_ADC_MODE_POWERDOWN (3 << 6) -#define AIO12_8_ADC_ACQ_3USEC (0 << 5) -#define AIO12_8_ADC_ACQ_PROGRAM (1 << 5) +#define AIO12_8_ADC_MODE(x) (((x) & 0x3) << 6) +#define AIO12_8_ADC_MODE_NORMAL AIO12_8_ADC_MODE(0) +#define AIO12_8_ADC_MODE_INT_CLK AIO12_8_ADC_MODE(1) +#define AIO12_8_ADC_MODE_STANDBY AIO12_8_ADC_MODE(2) +#define AIO12_8_ADC_MODE_POWERDOWN AIO12_8_ADC_MODE(3) +#define AIO12_8_ADC_ACQ(x) (((x) & 0x1) << 5) +#define AIO12_8_ADC_ACQ_3USEC AIO12_8_ADC_ACQ(0) +#define AIO12_8_ADC_ACQ_PROGRAM AIO12_8_ADC_ACQ(1) #define AIO12_8_ADC_RANGE(x) ((x) << 3) #define AIO12_8_ADC_CHAN(x) ((x) << 0) #define AIO12_8_DAC_REG(x) (0x04 + (x) * 2) #define AIO12_8_8254_BASE_REG 0x0c #define AIO12_8_8255_BASE_REG 0x10 #define AIO12_8_DIO_CONTROL_REG 0x14 -#define AIO12_8_DIO_CONTROL_TST (1 << 0) +#define AIO12_8_DIO_CONTROL_TST BIT(0) #define AIO12_8_ADC_TRIGGER_REG 0x15 #define AIO12_8_ADC_TRIGGER_RANGE(x) ((x) << 3) #define AIO12_8_ADC_TRIGGER_CHAN(x) ((x) << 0) #define AIO12_8_TRIGGER_REG 0x16 -#define AIO12_8_TRIGGER_ADTRIG (1 << 1) -#define AIO12_8_TRIGGER_DACTRIG (1 << 0) +#define AIO12_8_TRIGGER_ADTRIG BIT(1) +#define AIO12_8_TRIGGER_DACTRIG BIT(0) #define AIO12_8_COS_REG 0x17 #define AIO12_8_DAC_ENABLE_REG 0x18 -#define AIO12_8_DAC_ENABLE_REF_ENA (1 << 0) +#define AIO12_8_DAC_ENABLE_REF_ENA BIT(0) + +static const struct comedi_lrange aio_aio12_8_range = { + 4, { + UNI_RANGE(5), + BIP_RANGE(5), + UNI_RANGE(10), + BIP_RANGE(10) + } +}; struct aio12_8_boardtype { const char *name; - int ai_nchan; - int ao_nchan; + unsigned int has_ai:1; + unsigned int has_ao:1; }; static const struct aio12_8_boardtype board_types[] = { { .name = "aio_aio12_8", - .ai_nchan = 8, - .ao_nchan = 4, + .has_ai = 1, + .has_ao = 1, }, { .name = "aio_ai12_8", - .ai_nchan = 8, + .has_ai = 1, }, { - .name = "aio_ao12_8", - .ao_nchan = 4, + .name = "aio_ao12_4", + .has_ao = 1, }, }; @@ -112,13 +120,15 @@ static int aio_aio12_8_ai_eoc(struct comedi_device *dev, static int aio_aio12_8_ai_read(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { unsigned int chan = CR_CHAN(insn->chanspec); unsigned int range = CR_RANGE(insn->chanspec); + unsigned int val; unsigned char control; int ret; - int n; + int i; /* * Setup the control byte for internal 2MHz clock, 3uS conversion, @@ -130,7 +140,7 @@ static int aio_aio12_8_ai_read(struct comedi_device *dev, /* Read status to clear EOC latch */ inb(dev->iobase + AIO12_8_STATUS_REG); - for (n = 0; n < insn->n; n++) { + for (i = 0; i < insn->n; i++) { /* Setup and start conversion */ outb(control, dev->iobase + AIO12_8_ADC_REG); @@ -139,7 +149,13 @@ static int aio_aio12_8_ai_read(struct comedi_device *dev, if (ret) return ret; - data[n] = inw(dev->iobase + AIO12_8_ADC_REG) & s->maxdata; + val = inw(dev->iobase + AIO12_8_ADC_REG) & s->maxdata; + + /* munge bipolar 2's complement data to offset binary */ + if (comedi_range_is_bipolar(s, range)) + val = comedi_offset_munge(s, val); + + data[i] = val; } return insn->n; @@ -166,14 +182,28 @@ static int aio_aio12_8_ao_insn_write(struct comedi_device *dev, return insn->n; } -static const struct comedi_lrange range_aio_aio12_8 = { - 4, { - UNI_RANGE(5), - BIP_RANGE(5), - UNI_RANGE(10), - BIP_RANGE(10) +static int aio_aio12_8_counter_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned int chan = CR_CHAN(insn->chanspec); + + switch (data[0]) { + case INSN_CONFIG_GET_CLOCK_SRC: + /* + * Channels 0 and 2 have external clock sources. + * Channel 1 has a fixed 1 MHz clock source. + */ + data[0] = 0; + data[1] = (chan == 1) ? I8254_OSC_BASE_1MHZ : 0; + break; + default: + return -EINVAL; } -}; + + return insn->n; +} static int aio_aio12_8_attach(struct comedi_device *dev, struct comedi_devconfig *it) @@ -186,31 +216,36 @@ static int aio_aio12_8_attach(struct comedi_device *dev, if (ret) return ret; + dev->pacer = comedi_8254_init(dev->iobase + AIO12_8_8254_BASE_REG, + 0, I8254_IO8, 0); + if (!dev->pacer) + return -ENOMEM; + ret = comedi_alloc_subdevices(dev, 4); if (ret) return ret; + /* Analog Input subdevice */ s = &dev->subdevices[0]; - if (board->ai_nchan) { - /* Analog input subdevice */ + if (board->has_ai) { s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; - s->n_chan = board->ai_nchan; + s->n_chan = 8; s->maxdata = 0x0fff; - s->range_table = &range_aio_aio12_8; + s->range_table = &aio_aio12_8_range; s->insn_read = aio_aio12_8_ai_read; } else { s->type = COMEDI_SUBD_UNUSED; } + /* Analog Output subdevice */ s = &dev->subdevices[1]; - if (board->ao_nchan) { - /* Analog output subdevice */ + if (board->has_ao) { s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_DIFF; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND; s->n_chan = 4; s->maxdata = 0x0fff; - s->range_table = &range_aio_aio12_8; + s->range_table = &aio_aio12_8_range; s->insn_write = aio_aio12_8_ao_insn_write; ret = comedi_alloc_subdev_readback(s); @@ -220,15 +255,17 @@ static int aio_aio12_8_attach(struct comedi_device *dev, s->type = COMEDI_SUBD_UNUSED; } + /* Digital I/O subdevice (8255) */ s = &dev->subdevices[2]; - /* 8255 Digital i/o subdevice */ ret = subdev_8255_init(dev, s, NULL, AIO12_8_8255_BASE_REG); if (ret) return ret; + /* Counter subdevice (8254) */ s = &dev->subdevices[3]; - /* 8254 counter/timer subdevice */ - s->type = COMEDI_SUBD_UNUSED; + comedi_8254_subdevice_init(s, dev->pacer); + + dev->pacer->insn_config = aio_aio12_8_counter_insn_config; return 0; } @@ -245,5 +282,5 @@ static struct comedi_driver aio_aio12_8_driver = { module_comedi_driver(aio_aio12_8_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for Access I/O AIO12-8 Analog I/O Board"); MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/staging/comedi/drivers/amplc_dio200.c b/kernel/drivers/staging/comedi/drivers/amplc_dio200.c index 4fe118380..f5cfa71a9 100644 --- a/kernel/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/kernel/drivers/staging/comedi/drivers/amplc_dio200.c @@ -1,23 +1,24 @@ /* - comedi/drivers/amplc_dio200.c - - Driver for Amplicon PC212E, PC214E, PC215E, PC218E, PC272E. - - Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + * comedi/drivers/amplc_dio200.c + * + * Driver for Amplicon PC212E, PC214E, PC215E, PC218E, PC272E. + * + * Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ /* * Driver: amplc_dio200 * Description: Amplicon 200 Series ISA Digital I/O diff --git a/kernel/drivers/staging/comedi/drivers/amplc_dio200.h b/kernel/drivers/staging/comedi/drivers/amplc_dio200.h index d6d6a265c..53fb86d59 100644 --- a/kernel/drivers/staging/comedi/drivers/amplc_dio200.h +++ b/kernel/drivers/staging/comedi/drivers/amplc_dio200.h @@ -1,28 +1,32 @@ /* - comedi/drivers/amplc_dio.h - - Header for amplc_dio200.c, amplc_dio200_common.c and - amplc_dio200_pci.c. - - Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedi/drivers/amplc_dio.h + * + * Header for amplc_dio200.c, amplc_dio200_common.c and + * amplc_dio200_pci.c. + * + * Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #ifndef AMPLC_DIO200_H_INCLUDED #define AMPLC_DIO200_H_INCLUDED +#include <linux/types.h> + +struct comedi_device; + /* * Subdevice types. */ diff --git a/kernel/drivers/staging/comedi/drivers/amplc_dio200_common.c b/kernel/drivers/staging/comedi/drivers/amplc_dio200_common.c index d15a3dc12..d1539e798 100644 --- a/kernel/drivers/staging/comedi/drivers/amplc_dio200_common.c +++ b/kernel/drivers/staging/comedi/drivers/amplc_dio200_common.c @@ -1,23 +1,23 @@ /* - comedi/drivers/amplc_dio200_common.c - - Common support code for "amplc_dio200" and "amplc_dio200_pci". - - Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedi/drivers/amplc_dio200_common.c + * + * Common support code for "amplc_dio200" and "amplc_dio200_pci". + * + * Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #include <linux/module.h> #include <linux/interrupt.h> @@ -337,9 +337,10 @@ static int dio200_handle_read_intr(struct comedi_device *dev, * interested in (just in case there's a race * condition). */ - if (triggered & subpriv->enabled_isns) + if (triggered & subpriv->enabled_isns) { /* Collect scan data. */ dio200_read_scan_intr(dev, s, triggered); + } } } spin_unlock_irqrestore(&subpriv->spinlock, flags); @@ -576,12 +577,13 @@ static int dio200_subdev_8254_init(struct comedi_device *dev, regshift = 0; } - if (dev->mmio) + if (dev->mmio) { i8254 = comedi_8254_mm_init(dev->mmio + offset, 0, I8254_IO8, regshift); - else + } else { i8254 = comedi_8254_init(dev->iobase + offset, 0, I8254_IO8, regshift); + } if (!i8254) return -ENOMEM; @@ -593,10 +595,10 @@ static int dio200_subdev_8254_init(struct comedi_device *dev, * There could be multiple timers so this driver does not * use dev->pacer to save the i8254 pointer. Instead, * comedi_8254_subdevice_init() saved the i8254 pointer in - * s->private. Set the runflag bit so that the core will - * automatically free it when the driver is detached. + * s->private. Mark the subdevice as having private data + * to be automatically freed when the device is detached. */ - s->runflags |= COMEDI_SRF_FREE_SPRIV; + comedi_set_spriv_auto_free(s); /* Initialize channels. */ if (board->has_clk_gat_sce) { @@ -641,15 +643,18 @@ static int dio200_subdev_8255_bits(struct comedi_device *dev, mask = comedi_dio_update_state(s, data); if (mask) { - if (mask & 0xff) + if (mask & 0xff) { dio200_write8(dev, subpriv->ofs + I8255_DATA_A_REG, s->state & 0xff); - if (mask & 0xff00) + } + if (mask & 0xff00) { dio200_write8(dev, subpriv->ofs + I8255_DATA_B_REG, (s->state >> 8) & 0xff); - if (mask & 0xff0000) + } + if (mask & 0xff0000) { dio200_write8(dev, subpriv->ofs + I8255_DATA_C_REG, (s->state >> 16) & 0xff); + } } val = dio200_read8(dev, subpriv->ofs + I8255_DATA_A_REG); diff --git a/kernel/drivers/staging/comedi/drivers/amplc_dio200_pci.c b/kernel/drivers/staging/comedi/drivers/amplc_dio200_pci.c index d9850c917..2598e6e7d 100644 --- a/kernel/drivers/staging/comedi/drivers/amplc_dio200_pci.c +++ b/kernel/drivers/staging/comedi/drivers/amplc_dio200_pci.c @@ -1,22 +1,23 @@ /* comedi/drivers/amplc_dio200_pci.c + * + * Driver for Amplicon PCI215, PCI272, PCIe215, PCIe236, PCIe296. + * + * Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - Driver for Amplicon PCI215, PCI272, PCIe215, PCIe236, PCIe296. - - Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ /* * Driver: amplc_dio200_pci * Description: Amplicon 200 Series PCI Digital I/O diff --git a/kernel/drivers/staging/comedi/drivers/amplc_pc236_common.c b/kernel/drivers/staging/comedi/drivers/amplc_pc236_common.c index 245f932a7..0c02d3245 100644 --- a/kernel/drivers/staging/comedi/drivers/amplc_pc236_common.c +++ b/kernel/drivers/staging/comedi/drivers/amplc_pc236_common.c @@ -28,14 +28,14 @@ static void pc236_intr_update(struct comedi_device *dev, bool enable) { - const struct pc236_board *thisboard = dev->board_ptr; + const struct pc236_board *board = dev->board_ptr; struct pc236_private *devpriv = dev->private; unsigned long flags; spin_lock_irqsave(&dev->spinlock, flags); devpriv->enable_irq = enable; - if (thisboard->intr_update_cb) - thisboard->intr_update_cb(dev, enable); + if (board->intr_update_cb) + board->intr_update_cb(dev, enable); spin_unlock_irqrestore(&dev->spinlock, flags); } @@ -48,15 +48,15 @@ static void pc236_intr_update(struct comedi_device *dev, bool enable) */ static bool pc236_intr_check(struct comedi_device *dev) { - const struct pc236_board *thisboard = dev->board_ptr; + const struct pc236_board *board = dev->board_ptr; struct pc236_private *devpriv = dev->private; bool retval = false; unsigned long flags; spin_lock_irqsave(&dev->spinlock, flags); if (devpriv->enable_irq) { - if (thisboard->intr_chk_clr_cb) - retval = thisboard->intr_chk_clr_cb(dev); + if (board->intr_chk_clr_cb) + retval = board->intr_chk_clr_cb(dev); else retval = true; } diff --git a/kernel/drivers/staging/comedi/drivers/amplc_pci224.c b/kernel/drivers/staging/comedi/drivers/amplc_pci224.c index 08a918548..b2f7679a0 100644 --- a/kernel/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/kernel/drivers/staging/comedi/drivers/amplc_pci224.c @@ -385,14 +385,14 @@ static void pci224_ao_set_data(struct comedi_device *dev, int chan, int range, unsigned int data) { - const struct pci224_board *thisboard = dev->board_ptr; + const struct pci224_board *board = dev->board_ptr; struct pci224_private *devpriv = dev->private; unsigned short mangled; /* Enable the channel. */ outw(1 << chan, dev->iobase + PCI224_DACCEN); /* Set range and reset FIFO. */ - devpriv->daccon = COMBINE(devpriv->daccon, thisboard->ao_hwrange[range], + devpriv->daccon = COMBINE(devpriv->daccon, board->ao_hwrange[range], PCI224_DACCON_POLAR_MASK | PCI224_DACCON_VREF_MASK); outw(devpriv->daccon | PCI224_DACCON_FIFORESET, @@ -402,7 +402,7 @@ pci224_ao_set_data(struct comedi_device *dev, int chan, int range, * - bipolar: 16-bit 2's complement * - unipolar: 16-bit unsigned */ - mangled = (unsigned short)data << (16 - thisboard->ao_bits); + mangled = (unsigned short)data << (16 - board->ao_bits); if ((devpriv->daccon & PCI224_DACCON_POLAR_MASK) == PCI224_DACCON_POLAR_BI) { mangled ^= 0x8000; @@ -620,12 +620,12 @@ static int pci224_ao_check_chanlist(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct pci224_board *thisboard = dev->board_ptr; + const struct pci224_board *board = dev->board_ptr; unsigned int range_check_0; unsigned int chan_mask = 0; int i; - range_check_0 = thisboard->ao_range_check[CR_RANGE(cmd->chanlist[0])]; + range_check_0 = board->ao_range_check[CR_RANGE(cmd->chanlist[0])]; for (i = 0; i < cmd->chanlist_len; i++) { unsigned int chan = CR_CHAN(cmd->chanlist[i]); @@ -637,7 +637,7 @@ static int pci224_ao_check_chanlist(struct comedi_device *dev, } chan_mask |= 1 << chan; - if (thisboard->ao_range_check[CR_RANGE(cmd->chanlist[i])] != + if (board->ao_range_check[CR_RANGE(cmd->chanlist[i])] != range_check_0) { dev_dbg(dev->class_dev, "%s: entries in chanlist have incompatible ranges\n", @@ -826,7 +826,7 @@ static void pci224_ao_start_pacer(struct comedi_device *dev, static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - const struct pci224_board *thisboard = dev->board_ptr; + const struct pci224_board *board = dev->board_ptr; struct pci224_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; int range; @@ -869,7 +869,7 @@ static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) */ devpriv->daccon = COMBINE(devpriv->daccon, - thisboard->ao_hwrange[range] | PCI224_DACCON_TRIG_NONE | + board->ao_hwrange[range] | PCI224_DACCON_TRIG_NONE | PCI224_DACCON_FIFOINTR_NHALF, PCI224_DACCON_POLAR_MASK | PCI224_DACCON_VREF_MASK | PCI224_DACCON_TRIG_MASK | PCI224_DACCON_FIFOINTR_MASK); @@ -911,7 +911,7 @@ static void pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, void *data, unsigned int num_bytes, unsigned int chan_index) { - const struct pci224_board *thisboard = dev->board_ptr; + const struct pci224_board *board = dev->board_ptr; struct comedi_cmd *cmd = &s->async->cmd; unsigned short *array = data; unsigned int length = num_bytes / sizeof(*array); @@ -920,9 +920,9 @@ pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int i; /* The hardware expects 16-bit numbers. */ - shift = 16 - thisboard->ao_bits; + shift = 16 - board->ao_bits; /* Channels will be all bipolar or all unipolar. */ - if ((thisboard->ao_hwrange[CR_RANGE(cmd->chanlist[0])] & + if ((board->ao_hwrange[CR_RANGE(cmd->chanlist[0])] & PCI224_DACCON_POLAR_MASK) == PCI224_DACCON_POLAR_UNI) { /* Unipolar */ offset = 0; @@ -988,21 +988,21 @@ static int pci224_auto_attach(struct comedi_device *dev, unsigned long context_model) { struct pci_dev *pci_dev = comedi_to_pci_dev(dev); - const struct pci224_board *thisboard = NULL; + const struct pci224_board *board = NULL; struct pci224_private *devpriv; struct comedi_subdevice *s; unsigned int irq; int ret; if (context_model < ARRAY_SIZE(pci224_boards)) - thisboard = &pci224_boards[context_model]; - if (!thisboard || !thisboard->name) { + board = &pci224_boards[context_model]; + if (!board || !board->name) { dev_err(dev->class_dev, "amplc_pci224: BUG! cannot determine board type!\n"); return -EINVAL; } - dev->board_ptr = thisboard; - dev->board_name = thisboard->name; + dev->board_ptr = board; + dev->board_name = board->name; dev_info(dev->class_dev, "amplc_pci224: attach pci %s - %s\n", pci_name(pci_dev), dev->board_name); @@ -1023,13 +1023,13 @@ pci224_auto_attach(struct comedi_device *dev, unsigned long context_model) /* Allocate buffer to hold values for AO channel scan. */ devpriv->ao_scan_vals = kmalloc(sizeof(devpriv->ao_scan_vals[0]) * - thisboard->ao_chans, GFP_KERNEL); + board->ao_chans, GFP_KERNEL); if (!devpriv->ao_scan_vals) return -ENOMEM; /* Allocate buffer to hold AO channel scan order. */ devpriv->ao_scan_order = kmalloc(sizeof(devpriv->ao_scan_order[0]) * - thisboard->ao_chans, GFP_KERNEL); + board->ao_chans, GFP_KERNEL); if (!devpriv->ao_scan_order) return -ENOMEM; @@ -1059,9 +1059,9 @@ pci224_auto_attach(struct comedi_device *dev, unsigned long context_model) /* Analog output subdevice. */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; - s->n_chan = thisboard->ao_chans; - s->maxdata = (1 << thisboard->ao_bits) - 1; - s->range_table = thisboard->ao_range; + s->n_chan = board->ao_chans; + s->maxdata = (1 << board->ao_bits) - 1; + s->range_table = board->ao_range; s->insn_write = pci224_ao_insn_write; s->len_chanlist = s->n_chan; dev->write_subdev = s; diff --git a/kernel/drivers/staging/comedi/drivers/amplc_pci230.c b/kernel/drivers/staging/comedi/drivers/amplc_pci230.c index 20d592002..4b39f6960 100644 --- a/kernel/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/kernel/drivers/staging/comedi/drivers/amplc_pci230.c @@ -528,7 +528,7 @@ static const struct comedi_lrange pci230_ao_range = { static unsigned short pci230_ai_read(struct comedi_device *dev) { - const struct pci230_board *thisboard = dev->board_ptr; + const struct pci230_board *board = dev->board_ptr; struct pci230_private *devpriv = dev->private; unsigned short data; @@ -543,21 +543,21 @@ static unsigned short pci230_ai_read(struct comedi_device *dev) */ if (devpriv->ai_bipolar) data ^= 0x8000; - data >>= (16 - thisboard->ai_bits); + data >>= (16 - board->ai_bits); return data; } static unsigned short pci230_ao_mangle_datum(struct comedi_device *dev, unsigned short datum) { - const struct pci230_board *thisboard = dev->board_ptr; + const struct pci230_board *board = dev->board_ptr; struct pci230_private *devpriv = dev->private; /* * PCI230 is 12 bit - stored in upper bits of 16 bit register (lower * four bits reserved for expansion). PCI230+ is also 12 bit AO. */ - datum <<= (16 - thisboard->ao_bits); + datum <<= (16 - board->ao_bits); /* * If a bipolar range was specified, mangle it * (straight binary->twos complement). @@ -877,7 +877,7 @@ static int pci230_ao_check_chanlist(struct comedi_device *dev, static int pci230_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct pci230_board *thisboard = dev->board_ptr; + const struct pci230_board *board = dev->board_ptr; struct pci230_private *devpriv = dev->private; int err = 0; unsigned int tmp; @@ -887,14 +887,14 @@ static int pci230_ao_cmdtest(struct comedi_device *dev, err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT); tmp = TRIG_TIMER | TRIG_INT; - if (thisboard->min_hwver > 0 && devpriv->hwver >= 2) { + if (board->min_hwver > 0 && devpriv->hwver >= 2) { /* * For PCI230+ hardware version 2 onwards, allow external * trigger from EXTTRIG/EXTCONVCLK input (PCI230+ pin 25). * * FIXME: The permitted scan_begin_src values shouldn't depend * on devpriv->hwver (the detected card's actual hardware - * version). They should only depend on thisboard->min_hwver + * version). They should only depend on board->min_hwver * (the static capabilities of the configured card). To fix * it, a new card model, e.g. "pci230+2" would have to be * defined with min_hwver set to 2. It doesn't seem worth it @@ -1500,7 +1500,7 @@ static int pci230_ai_check_chanlist(struct comedi_device *dev, static int pci230_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct pci230_board *thisboard = dev->board_ptr; + const struct pci230_board *board = dev->board_ptr; struct pci230_private *devpriv = dev->private; int err = 0; unsigned int tmp; @@ -1510,7 +1510,7 @@ static int pci230_ai_cmdtest(struct comedi_device *dev, err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); tmp = TRIG_FOLLOW | TRIG_TIMER | TRIG_INT; - if (thisboard->have_dio || thisboard->min_hwver > 0) { + if (board->have_dio || board->min_hwver > 0) { /* * Unfortunately, we cannot trigger a scan off an external * source on the PCI260 board, since it uses the PPIC0 (DIO) @@ -2011,17 +2011,17 @@ static void pci230_handle_ai(struct comedi_device *dev, struct comedi_cmd *cmd = &async->cmd; unsigned int status_fifo; unsigned int i; - unsigned int todo; + unsigned int nsamples; unsigned int fifoamount; unsigned short val; /* Determine number of samples to read. */ - todo = comedi_nsamples_left(s, PCI230_ADC_FIFOLEVEL_HALFFULL); - if (todo == 0) + nsamples = comedi_nsamples_left(s, PCI230_ADC_FIFOLEVEL_HALFFULL); + if (nsamples == 0) return; fifoamount = 0; - for (i = 0; i < todo; i++) { + for (i = 0; i < nsamples; i++) { if (fifoamount == 0) { /* Read FIFO state. */ status_fifo = inw(devpriv->daqio + PCI230_ADCCON); @@ -2275,7 +2275,7 @@ static int pci230_ai_cancel(struct comedi_device *dev, static irqreturn_t pci230_interrupt(int irq, void *d) { unsigned char status_int, valid_status_int, temp_ier; - struct comedi_device *dev = (struct comedi_device *)d; + struct comedi_device *dev = d; struct pci230_private *devpriv = dev->private; struct comedi_subdevice *s_ao = dev->write_subdev; struct comedi_subdevice *s_ai = dev->read_subdev; @@ -2364,7 +2364,7 @@ static int pci230_auto_attach(struct comedi_device *dev, unsigned long context_unused) { struct pci_dev *pci_dev = comedi_to_pci_dev(dev); - const struct pci230_board *thisboard; + const struct pci230_board *board; struct pci230_private *devpriv; struct comedi_subdevice *s; int rc; @@ -2381,14 +2381,14 @@ static int pci230_auto_attach(struct comedi_device *dev, spin_lock_init(&devpriv->ai_stop_spinlock); spin_lock_init(&devpriv->ao_stop_spinlock); - dev->board_ptr = pci230_find_pci_board(pci_dev); - if (!dev->board_ptr) { + board = pci230_find_pci_board(pci_dev); + if (!board) { dev_err(dev->class_dev, "amplc_pci230: BUG! cannot determine board type!\n"); return -EINVAL; } - thisboard = dev->board_ptr; - dev->board_name = thisboard->name; + dev->board_ptr = board; + dev->board_name = board->name; rc = comedi_pci_enable(dev); if (rc) @@ -2414,15 +2414,15 @@ static int pci230_auto_attach(struct comedi_device *dev, unsigned short extfunc = 0; devpriv->hwver = inw(devpriv->daqio + PCI230P_HWVER); - if (devpriv->hwver < thisboard->min_hwver) { + if (devpriv->hwver < board->min_hwver) { dev_err(dev->class_dev, "%s - bad hardware version - got %u, need %u\n", dev->board_name, devpriv->hwver, - thisboard->min_hwver); + board->min_hwver); return -EIO; } if (devpriv->hwver > 0) { - if (!thisboard->have_dio) { + if (!board->have_dio) { /* * No DIO ports. Route counters' external gates * to the EXTTRIG signal (PCI260+ pin 17). @@ -2432,7 +2432,7 @@ static int pci230_auto_attach(struct comedi_device *dev, */ extfunc |= PCI230P_EXTFUNC_GAT_EXTTRIG; } - if (thisboard->ao_bits && devpriv->hwver >= 2) { + if (board->ao_bits && devpriv->hwver >= 2) { /* Enable DAC FIFO functionality. */ extfunc |= PCI230P2_EXTFUNC_DACFIFO; } @@ -2484,7 +2484,7 @@ static int pci230_auto_attach(struct comedi_device *dev, s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND; s->n_chan = 16; - s->maxdata = (1 << thisboard->ai_bits) - 1; + s->maxdata = (1 << board->ai_bits) - 1; s->range_table = &pci230_ai_range; s->insn_read = pci230_ai_insn_read; s->len_chanlist = 256; /* but there are restrictions. */ @@ -2498,11 +2498,11 @@ static int pci230_auto_attach(struct comedi_device *dev, s = &dev->subdevices[1]; /* analog output subdevice */ - if (thisboard->ao_bits) { + if (board->ao_bits) { s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND; s->n_chan = 2; - s->maxdata = (1 << thisboard->ao_bits) - 1; + s->maxdata = (1 << board->ao_bits) - 1; s->range_table = &pci230_ao_range; s->insn_write = pci230_ao_insn_write; s->len_chanlist = 2; @@ -2523,7 +2523,7 @@ static int pci230_auto_attach(struct comedi_device *dev, s = &dev->subdevices[2]; /* digital i/o subdevice */ - if (thisboard->have_dio) { + if (board->have_dio) { rc = subdev_8255_init(dev, s, NULL, PCI230_PPI_X_BASE); if (rc) return rc; diff --git a/kernel/drivers/staging/comedi/drivers/cb_das16_cs.c b/kernel/drivers/staging/comedi/drivers/cb_das16_cs.c index ae84f2c0c..78d098f9e 100644 --- a/kernel/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/kernel/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -1,36 +1,37 @@ /* - comedi/drivers/das16cs.c - Driver for Computer Boards PC-CARD DAS16/16. + * cb_das16_cs.c + * Driver for Computer Boards PC-CARD DAS16/16. + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000, 2001, 2002 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * PCMCIA support code for this driver is adapted from the dummy_cs.c + * driver of the Linux PCMCIA Card Services package. + * + * The initial developer of the original code is David A. Hinds + * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + */ - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000, 2001, 2002 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - PCMCIA support code for this driver is adapted from the dummy_cs.c - driver of the Linux PCMCIA Card Services package. - - The initial developer of the original code is David A. Hinds - <dahinds@users.sourceforge.net>. Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - -*/ /* -Driver: cb_das16_cs -Description: Computer Boards PC-CARD DAS16/16 -Devices: [ComputerBoards] PC-CARD DAS16/16 (cb_das16_cs), PC-CARD DAS16/16-AO -Author: ds -Updated: Mon, 04 Nov 2002 20:04:21 -0800 -Status: experimental -*/ + * Driver: cb_das16_cs + * Description: Computer Boards PC-CARD DAS16/16 + * Devices: [ComputerBoards] PC-CARD DAS16/16 (cb_das16_cs), + * PC-CARD DAS16/16-AO + * Author: ds + * Updated: Mon, 04 Nov 2002 20:04:21 -0800 + * Status: experimental + */ #include <linux/module.h> #include <linux/interrupt.h> @@ -40,38 +41,86 @@ Status: experimental #include "comedi_8254.h" -#define DAS16CS_ADC_DATA 0 -#define DAS16CS_DIO_MUX 2 -#define DAS16CS_MISC1 4 -#define DAS16CS_MISC2 6 -#define DAS16CS_TIMER_BASE 8 -#define DAS16CS_DIO 16 +/* + * Register I/O map + */ +#define DAS16CS_AI_DATA_REG 0x00 +#define DAS16CS_AI_MUX_REG 0x02 +#define DAS16CS_AI_MUX_HI_CHAN(x) (((x) & 0xf) << 4) +#define DAS16CS_AI_MUX_LO_CHAN(x) (((x) & 0xf) << 0) +#define DAS16CS_AI_MUX_SINGLE_CHAN(x) (DAS16CS_AI_MUX_HI_CHAN(x) | \ + DAS16CS_AI_MUX_LO_CHAN(x)) +#define DAS16CS_MISC1_REG 0x04 +#define DAS16CS_MISC1_INTE BIT(15) /* 1=enable; 0=disable */ +#define DAS16CS_MISC1_INT_SRC(x) (((x) & 0x7) << 12) /* interrupt src */ +#define DAS16CS_MISC1_INT_SRC_NONE DAS16CS_MISC1_INT_SRC(0) +#define DAS16CS_MISC1_INT_SRC_PACER DAS16CS_MISC1_INT_SRC(1) +#define DAS16CS_MISC1_INT_SRC_EXT DAS16CS_MISC1_INT_SRC(2) +#define DAS16CS_MISC1_INT_SRC_FNE DAS16CS_MISC1_INT_SRC(3) +#define DAS16CS_MISC1_INT_SRC_FHF DAS16CS_MISC1_INT_SRC(4) +#define DAS16CS_MISC1_INT_SRC_EOS DAS16CS_MISC1_INT_SRC(5) +#define DAS16CS_MISC1_INT_SRC_MASK DAS16CS_MISC1_INT_SRC(7) +#define DAS16CS_MISC1_OVR BIT(10) /* ro - 1=FIFO overflow */ +#define DAS16CS_MISC1_AI_CONV(x) (((x) & 0x3) << 8) /* AI convert src */ +#define DAS16CS_MISC1_AI_CONV_SW DAS16CS_MISC1_AI_CONV(0) +#define DAS16CS_MISC1_AI_CONV_EXT_NEG DAS16CS_MISC1_AI_CONV(1) +#define DAS16CS_MISC1_AI_CONV_EXT_POS DAS16CS_MISC1_AI_CONV(2) +#define DAS16CS_MISC1_AI_CONV_PACER DAS16CS_MISC1_AI_CONV(3) +#define DAS16CS_MISC1_AI_CONV_MASK DAS16CS_MISC1_AI_CONV(3) +#define DAS16CS_MISC1_EOC BIT(7) /* ro - 0=busy; 1=ready */ +#define DAS16CS_MISC1_SEDIFF BIT(5) /* 0=diff; 1=se */ +#define DAS16CS_MISC1_INTB BIT(4) /* ro - 0=latched; 1=cleared */ +#define DAS16CS_MISC1_MA_MASK (0xf << 0) /* ro - current ai mux */ +#define DAS16CS_MISC1_DAC1CS BIT(3) /* wo - DAC1 chip select */ +#define DAS16CS_MISC1_DACCLK BIT(2) /* wo - Serial DAC clock */ +#define DAS16CS_MISC1_DACSD BIT(1) /* wo - Serial DAC data */ +#define DAS16CS_MISC1_DAC0CS BIT(0) /* wo - DAC0 chip select */ +#define DAS16CS_MISC1_DAC_MASK (0x0f << 0) +#define DAS16CS_MISC2_REG 0x06 +#define DAS16CS_MISC2_BME BIT(14) /* 1=burst enable; 0=disable */ +#define DAS16CS_MISC2_AI_GAIN(x) (((x) & 0xf) << 8) /* AI gain */ +#define DAS16CS_MISC2_AI_GAIN_1 DAS16CS_MISC2_AI_GAIN(4) /* +/-10V */ +#define DAS16CS_MISC2_AI_GAIN_2 DAS16CS_MISC2_AI_GAIN(0) /* +/-5V */ +#define DAS16CS_MISC2_AI_GAIN_4 DAS16CS_MISC2_AI_GAIN(1) /* +/-2.5V */ +#define DAS16CS_MISC2_AI_GAIN_8 DAS16CS_MISC2_AI_GAIN(2) /* +-1.25V */ +#define DAS16CS_MISC2_AI_GAIN_MASK DAS16CS_MISC2_AI_GAIN(0xf) +#define DAS16CS_MISC2_UDIR BIT(7) /* 1=dio7:4 output; 0=input */ +#define DAS16CS_MISC2_LDIR BIT(6) /* 1=dio3:0 output; 0=input */ +#define DAS16CS_MISC2_TRGPOL BIT(5) /* 1=active lo; 0=hi */ +#define DAS16CS_MISC2_TRGSEL BIT(4) /* 1=edge; 0=level */ +#define DAS16CS_MISC2_FFNE BIT(3) /* ro - 1=FIFO not empty */ +#define DAS16CS_MISC2_TRGCLR BIT(3) /* wo - 1=clr (monstable) */ +#define DAS16CS_MISC2_CLK2 BIT(2) /* 1=10 MHz; 0=1 MHz */ +#define DAS16CS_MISC2_CTR1 BIT(1) /* 1=int. 100 kHz; 0=ext. clk */ +#define DAS16CS_MISC2_TRG0 BIT(0) /* 1=enable; 0=disable */ +#define DAS16CS_TIMER_BASE 0x08 +#define DAS16CS_DIO_REG 0x10 struct das16cs_board { const char *name; int device_id; - int n_ao_chans; + unsigned int has_ao:1; + unsigned int has_4dio:1; }; static const struct das16cs_board das16cs_boards[] = { { .name = "PC-CARD DAS16/16-AO", .device_id = 0x0039, - .n_ao_chans = 2, + .has_ao = 1, + .has_4dio = 1, }, { .name = "PCM-DAS16s/16", .device_id = 0x4009, - .n_ao_chans = 0, }, { .name = "PC-CARD DAS16/16", .device_id = 0x0000, /* unknown */ - .n_ao_chans = 0, }, }; struct das16cs_private { - unsigned short status1; - unsigned short status2; + unsigned short misc1; + unsigned short misc2; }; static const struct comedi_lrange das16cs_ai_range = { @@ -90,15 +139,16 @@ static int das16cs_ai_eoc(struct comedi_device *dev, { unsigned int status; - status = inw(dev->iobase + DAS16CS_MISC1); - if (status & 0x0080) + status = inw(dev->iobase + DAS16CS_MISC1_REG); + if (status & DAS16CS_MISC1_EOC) return 0; return -EBUSY; } -static int das16cs_ai_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int das16cs_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct das16cs_private *devpriv = dev->private; int chan = CR_CHAN(insn->chanspec); @@ -107,37 +157,43 @@ static int das16cs_ai_rinsn(struct comedi_device *dev, int ret; int i; - outw(chan, dev->iobase + DAS16CS_DIO_MUX); + outw(DAS16CS_AI_MUX_SINGLE_CHAN(chan), + dev->iobase + DAS16CS_AI_MUX_REG); - devpriv->status1 &= ~0xf320; - devpriv->status1 |= (aref == AREF_DIFF) ? 0 : 0x0020; - outw(devpriv->status1, dev->iobase + DAS16CS_MISC1); + /* disable interrupts, software convert */ + devpriv->misc1 &= ~(DAS16CS_MISC1_INTE | DAS16CS_MISC1_INT_SRC_MASK | + DAS16CS_MISC1_AI_CONV_MASK); + if (aref == AREF_DIFF) + devpriv->misc1 &= ~DAS16CS_MISC1_SEDIFF; + else + devpriv->misc1 |= DAS16CS_MISC1_SEDIFF; + outw(devpriv->misc1, dev->iobase + DAS16CS_MISC1_REG); - devpriv->status2 &= ~0xff00; + devpriv->misc2 &= ~(DAS16CS_MISC2_BME | DAS16CS_MISC2_AI_GAIN_MASK); switch (range) { case 0: - devpriv->status2 |= 0x800; + devpriv->misc2 |= DAS16CS_MISC2_AI_GAIN_1; break; case 1: - devpriv->status2 |= 0x000; + devpriv->misc2 |= DAS16CS_MISC2_AI_GAIN_2; break; case 2: - devpriv->status2 |= 0x100; + devpriv->misc2 |= DAS16CS_MISC2_AI_GAIN_4; break; case 3: - devpriv->status2 |= 0x200; + devpriv->misc2 |= DAS16CS_MISC2_AI_GAIN_8; break; } - outw(devpriv->status2, dev->iobase + DAS16CS_MISC2); + outw(devpriv->misc2, dev->iobase + DAS16CS_MISC2_REG); for (i = 0; i < insn->n; i++) { - outw(0, dev->iobase + DAS16CS_ADC_DATA); + outw(0, dev->iobase + DAS16CS_AI_DATA_REG); ret = comedi_timeout(dev, s, insn, das16cs_ai_eoc, 0); if (ret) return ret; - data[i] = inw(dev->iobase + DAS16CS_ADC_DATA); + data[i] = inw(dev->iobase + DAS16CS_AI_DATA_REG); } return i; @@ -151,39 +207,43 @@ static int das16cs_ao_insn_write(struct comedi_device *dev, struct das16cs_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); unsigned int val = s->readback[chan]; - unsigned short status1; + unsigned short misc1; int bit; int i; for (i = 0; i < insn->n; i++) { val = data[i]; - outw(devpriv->status1, dev->iobase + DAS16CS_MISC1); + outw(devpriv->misc1, dev->iobase + DAS16CS_MISC1_REG); udelay(1); - status1 = devpriv->status1 & ~0xf; + /* raise the DACxCS line for the non-selected channel */ + misc1 = devpriv->misc1 & ~DAS16CS_MISC1_DAC_MASK; if (chan) - status1 |= 0x0001; + misc1 |= DAS16CS_MISC1_DAC0CS; else - status1 |= 0x0008; + misc1 |= DAS16CS_MISC1_DAC1CS; - outw(status1, dev->iobase + DAS16CS_MISC1); + outw(misc1, dev->iobase + DAS16CS_MISC1_REG); udelay(1); for (bit = 15; bit >= 0; bit--) { - int b = (val >> bit) & 0x1; - - b <<= 1; - outw(status1 | b | 0x0000, dev->iobase + DAS16CS_MISC1); + if ((val >> bit) & 0x1) + misc1 |= DAS16CS_MISC1_DACSD; + else + misc1 &= ~DAS16CS_MISC1_DACSD; + outw(misc1, dev->iobase + DAS16CS_MISC1_REG); udelay(1); - outw(status1 | b | 0x0004, dev->iobase + DAS16CS_MISC1); + outw(misc1 | DAS16CS_MISC1_DACCLK, + dev->iobase + DAS16CS_MISC1_REG); udelay(1); } /* * Make both DAC0CS and DAC1CS high to load * the new data and update analog the output */ - outw(status1 | 0x9, dev->iobase + DAS16CS_MISC1); + outw(misc1 | DAS16CS_MISC1_DAC0CS | DAS16CS_MISC1_DAC1CS, + dev->iobase + DAS16CS_MISC1_REG); } s->readback[chan] = val; @@ -196,9 +256,9 @@ static int das16cs_dio_insn_bits(struct comedi_device *dev, unsigned int *data) { if (comedi_dio_update_state(s, data)) - outw(s->state, dev->iobase + DAS16CS_DIO); + outw(s->state, dev->iobase + DAS16CS_DIO_REG); - data[1] = inw(dev->iobase + DAS16CS_DIO); + data[1] = inw(dev->iobase + DAS16CS_DIO_REG); return insn->n; } @@ -222,11 +282,52 @@ static int das16cs_dio_insn_config(struct comedi_device *dev, if (ret) return ret; - devpriv->status2 &= ~0x00c0; - devpriv->status2 |= (s->io_bits & 0xf0) ? 0x0080 : 0; - devpriv->status2 |= (s->io_bits & 0x0f) ? 0x0040 : 0; + if (s->io_bits & 0xf0) + devpriv->misc2 |= DAS16CS_MISC2_UDIR; + else + devpriv->misc2 &= ~DAS16CS_MISC2_UDIR; + if (s->io_bits & 0x0f) + devpriv->misc2 |= DAS16CS_MISC2_LDIR; + else + devpriv->misc2 &= ~DAS16CS_MISC2_LDIR; + outw(devpriv->misc2, dev->iobase + DAS16CS_MISC2_REG); + + return insn->n; +} + +static int das16cs_counter_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct das16cs_private *devpriv = dev->private; - outw(devpriv->status2, dev->iobase + DAS16CS_MISC2); + switch (data[0]) { + case INSN_CONFIG_SET_CLOCK_SRC: + switch (data[1]) { + case 0: /* internal 100 kHz */ + devpriv->misc2 |= DAS16CS_MISC2_CTR1; + break; + case 1: /* external */ + devpriv->misc2 &= ~DAS16CS_MISC2_CTR1; + break; + default: + return -EINVAL; + } + outw(devpriv->misc2, dev->iobase + DAS16CS_MISC2_REG); + break; + case INSN_CONFIG_GET_CLOCK_SRC: + if (devpriv->misc2 & DAS16CS_MISC2_CTR1) { + data[1] = 0; + data[2] = I8254_OSC_BASE_100KHZ; + } else { + data[1] = 1; + data[2] = 0; /* unknown */ + } + break; + default: + return -EINVAL; + } return insn->n; } @@ -278,26 +379,25 @@ static int das16cs_auto_attach(struct comedi_device *dev, if (!dev->pacer) return -ENOMEM; - ret = comedi_alloc_subdevices(dev, 3); + ret = comedi_alloc_subdevices(dev, 4); if (ret) return ret; + /* Analog Input subdevice */ s = &dev->subdevices[0]; - /* analog input subdevice */ s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; s->n_chan = 16; s->maxdata = 0xffff; s->range_table = &das16cs_ai_range; - s->len_chanlist = 16; - s->insn_read = das16cs_ai_rinsn; + s->insn_read = das16cs_ai_insn_read; + /* Analog Output subdevice */ s = &dev->subdevices[1]; - /* analog output subdevice */ - if (board->n_ao_chans) { + if (board->has_ao) { s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = board->n_ao_chans; + s->n_chan = 2; s->maxdata = 0xffff; s->range_table = &range_bipolar10; s->insn_write = &das16cs_ao_insn_write; @@ -309,16 +409,26 @@ static int das16cs_auto_attach(struct comedi_device *dev, s->type = COMEDI_SUBD_UNUSED; } + /* Digital I/O subdevice */ s = &dev->subdevices[2]; - /* digital i/o subdevice */ s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 8; + s->n_chan = board->has_4dio ? 4 : 8; s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = das16cs_dio_insn_bits; s->insn_config = das16cs_dio_insn_config; + /* Counter subdevice (8254) */ + s = &dev->subdevices[3]; + comedi_8254_subdevice_init(s, dev->pacer); + + dev->pacer->insn_config = das16cs_counter_insn_config; + + /* counters 1 and 2 are used internally for the pacer */ + comedi_8254_set_busy(dev->pacer, 1, true); + comedi_8254_set_busy(dev->pacer, 2, true); + return 0; } diff --git a/kernel/drivers/staging/comedi/drivers/cb_pcidas.c b/kernel/drivers/staging/comedi/drivers/cb_pcidas.c index e3591a582..3cd008acb 100644 --- a/kernel/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/kernel/drivers/staging/comedi/drivers/cb_pcidas.c @@ -1,65 +1,64 @@ /* - comedi/drivers/cb_pcidas.c + * cb_pcidas.c + * Developed by Ivan Martinez and Frank Mori Hess, with valuable help from + * David Schleef and the rest of the Comedi developers comunity. + * + * Copyright (C) 2001-2003 Ivan Martinez <imr@oersted.dtu.dk> + * Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net> + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - Developed by Ivan Martinez and Frank Mori Hess, with valuable help from - David Schleef and the rest of the Comedi developers comunity. - - Copyright (C) 2001-2003 Ivan Martinez <imr@oersted.dtu.dk> - Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net> - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-8 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ -/* -Driver: cb_pcidas -Description: MeasurementComputing PCI-DAS series - with the AMCC S5933 PCI controller -Author: Ivan Martinez <imr@oersted.dtu.dk>, - Frank Mori Hess <fmhess@users.sourceforge.net> -Updated: 2003-3-11 -Devices: [Measurement Computing] PCI-DAS1602/16 (cb_pcidas), - PCI-DAS1602/16jr, PCI-DAS1602/12, PCI-DAS1200, PCI-DAS1200jr, - PCI-DAS1000, PCI-DAS1001, PCI_DAS1002 - -Status: - There are many reports of the driver being used with most of the - supported cards. Despite no detailed log is maintained, it can - be said that the driver is quite tested and stable. - - The boards may be autocalibrated using the comedi_calibrate - utility. - -Configuration options: not applicable, uses PCI auto config - -For commands, the scanned channels must be consecutive -(i.e. 4-5-6-7, 2-3-4,...), and must all have the same -range and aref. - -AI Triggering: - For start_src == TRIG_EXT, the A/D EXTERNAL TRIGGER IN (pin 45) is used. - For 1602 series, the start_arg is interpreted as follows: - start_arg == 0 => gated trigger (level high) - start_arg == CR_INVERT => gated trigger (level low) - start_arg == CR_EDGE => Rising edge - start_arg == CR_EDGE | CR_INVERT => Falling edge - For the other boards the trigger will be done on rising edge -*/ /* + * Driver: cb_pcidas + * Description: MeasurementComputing PCI-DAS series + * with the AMCC S5933 PCI controller + * Devices: [Measurement Computing] PCI-DAS1602/16 (cb_pcidas), + * PCI-DAS1602/16jr, PCI-DAS1602/12, PCI-DAS1200, PCI-DAS1200jr, + * PCI-DAS1000, PCI-DAS1001, PCI_DAS1002 + * Author: Ivan Martinez <imr@oersted.dtu.dk>, + * Frank Mori Hess <fmhess@users.sourceforge.net> + * Updated: 2003-3-11 + * + * Status: + * There are many reports of the driver being used with most of the + * supported cards. Despite no detailed log is maintained, it can + * be said that the driver is quite tested and stable. + * + * The boards may be autocalibrated using the comedi_calibrate + * utility. + * + * Configuration options: not applicable, uses PCI auto config + * + * For commands, the scanned channels must be consecutive + * (i.e. 4-5-6-7, 2-3-4,...), and must all have the same + * range and aref. + * + * AI Triggering: + * For start_src == TRIG_EXT, the A/D EXTERNAL TRIGGER IN (pin 45) is used. + * For 1602 series, the start_arg is interpreted as follows: + * start_arg == 0 => gated trigger (level high) + * start_arg == CR_INVERT => gated trigger (level low) + * start_arg == CR_EDGE => Rising edge + * start_arg == CR_EDGE | CR_INVERT => Falling edge + * For the other boards the trigger will be done on rising edge + */ -TODO: - -analog triggering on 1602 series -*/ +/* + * TODO: + * analog triggering on 1602 series + */ #include <linux/module.h> #include <linux/delay.h> @@ -73,109 +72,107 @@ analog triggering on 1602 series #define AI_BUFFER_SIZE 1024 /* max ai fifo size */ #define AO_BUFFER_SIZE 1024 /* max ao fifo size */ -#define NUM_CHANNELS_8800 8 -#define NUM_CHANNELS_7376 1 -#define NUM_CHANNELS_8402 2 -#define NUM_CHANNELS_DAC08 1 - -/* Control/Status registers */ -#define INT_ADCFIFO 0 /* INTERRUPT / ADC FIFO register */ -#define INT_EOS 0x1 /* int end of scan */ -#define INT_FHF 0x2 /* int fifo half full */ -#define INT_FNE 0x3 /* int fifo not empty */ -#define INT_MASK 0x3 /* mask of int select bits */ -#define INTE 0x4 /* int enable */ -#define DAHFIE 0x8 /* dac half full int enable */ -#define EOAIE 0x10 /* end of acq. int enable */ -#define DAHFI 0x20 /* dac half full status / clear */ -#define EOAI 0x40 /* end of acq. int status / clear */ -#define INT 0x80 /* int status / clear */ -#define EOBI 0x200 /* end of burst int status */ -#define ADHFI 0x400 /* half-full int status */ -#define ADNEI 0x800 /* fifo not empty int status (latch) */ -#define ADNE 0x1000 /* fifo not empty status (realtime) */ -#define DAEMIE 0x1000 /* dac empty int enable */ -#define LADFUL 0x2000 /* fifo overflow / clear */ -#define DAEMI 0x4000 /* dac fifo empty int status / clear */ - -#define ADCMUX_CONT 2 /* ADC CHANNEL MUX AND CONTROL reg */ -#define BEGIN_SCAN(x) ((x) & 0xf) -#define END_SCAN(x) (((x) & 0xf) << 4) -#define GAIN_BITS(x) (((x) & 0x3) << 8) -#define UNIP 0x800 /* Analog front-end unipolar mode */ -#define SE 0x400 /* Inputs in single-ended mode */ -#define PACER_MASK 0x3000 /* pacer source bits */ -#define PACER_INT 0x1000 /* int. pacer */ -#define PACER_EXT_FALL 0x2000 /* ext. falling edge */ -#define PACER_EXT_RISE 0x3000 /* ext. rising edge */ -#define EOC 0x4000 /* adc not busy */ - -#define TRIG_CONTSTAT 4 /* TRIGGER CONTROL/STATUS register */ -#define SW_TRIGGER 0x1 /* software start trigger */ -#define EXT_TRIGGER 0x2 /* ext. start trigger */ -#define ANALOG_TRIGGER 0x3 /* ext. analog trigger */ -#define TRIGGER_MASK 0x3 /* start trigger mask */ -#define TGPOL 0x04 /* invert trigger (1602 only) */ -#define TGSEL 0x08 /* edge/level trigerred (1602 only) */ -#define TGEN 0x10 /* enable external start trigger */ -#define BURSTE 0x20 /* burst mode enable */ -#define XTRCL 0x80 /* clear external trigger */ - -#define CALIBRATION_REG 6 /* CALIBRATION register */ -#define SELECT_8800_BIT 0x100 /* select 8800 caldac */ -#define SELECT_TRIMPOT_BIT 0x200 /* select ad7376 trim pot */ -#define SELECT_DAC08_BIT 0x400 /* select dac08 caldac */ -#define CAL_SRC_BITS(x) (((x) & 0x7) << 11) -#define CAL_EN_BIT 0x4000 /* calibration source enable */ -#define SERIAL_DATA_IN_BIT 0x8000 /* serial data bit going to caldac */ - -#define DAC_CSR 0x8 /* dac control and status register */ -#define DACEN 0x02 /* dac enable */ -#define DAC_MODE_UPDATE_BOTH 0x80 /* update both dacs */ - -static inline unsigned int DAC_RANGE(unsigned int channel, unsigned int range) -{ - return (range & 0x3) << (8 + 2 * (channel & 0x1)); -} - -static inline unsigned int DAC_RANGE_MASK(unsigned int channel) -{ - return 0x3 << (8 + 2 * (channel & 0x1)); -}; - -/* bits for 1602 series only */ -#define DAC_EMPTY 0x1 /* fifo empty, read, write clear */ -#define DAC_START 0x4 /* start/arm fifo operations */ -#define DAC_PACER_MASK 0x18 /* bits that set pacer source */ -#define DAC_PACER_INT 0x8 /* int. pacing */ -#define DAC_PACER_EXT_FALL 0x10 /* ext. pacing, falling edge */ -#define DAC_PACER_EXT_RISE 0x18 /* ext. pacing, rising edge */ - -static inline unsigned int DAC_CHAN_EN(unsigned int channel) -{ - return 1 << (5 + (channel & 0x1)); /* enable channel 0 or 1 */ -}; - -/* analog input fifo */ -#define ADCDATA 0 /* ADC DATA register */ -#define ADCFIFOCLR 2 /* ADC FIFO CLEAR */ -/* pacer, counter, dio registers */ -#define ADC8254 0 -#define DIO_8255 4 -#define DAC8254 8 +/* + * PCI BAR1 Register map (devpriv->pcibar1) + */ +#define PCIDAS_CTRL_REG 0x00 /* INTERRUPT / ADC FIFO register */ +#define PCIDAS_CTRL_INT(x) (((x) & 0x3) << 0) +#define PCIDAS_CTRL_INT_NONE PCIDAS_CTRL_INT(0) /* no int selected */ +#define PCIDAS_CTRL_INT_EOS PCIDAS_CTRL_INT(1) /* int on end of scan */ +#define PCIDAS_CTRL_INT_FHF PCIDAS_CTRL_INT(2) /* int on fifo half full */ +#define PCIDAS_CTRL_INT_FNE PCIDAS_CTRL_INT(3) /* int on fifo not empty */ +#define PCIDAS_CTRL_INT_MASK PCIDAS_CTRL_INT(3) /* mask of int select bits */ +#define PCIDAS_CTRL_INTE BIT(2) /* int enable */ +#define PCIDAS_CTRL_DAHFIE BIT(3) /* dac half full int enable */ +#define PCIDAS_CTRL_EOAIE BIT(4) /* end of acq. int enable */ +#define PCIDAS_CTRL_DAHFI BIT(5) /* dac half full status / clear */ +#define PCIDAS_CTRL_EOAI BIT(6) /* end of acq. int status / clear */ +#define PCIDAS_CTRL_INT_CLR BIT(7) /* int status / clear */ +#define PCIDAS_CTRL_EOBI BIT(9) /* end of burst int status */ +#define PCIDAS_CTRL_ADHFI BIT(10) /* half-full int status */ +#define PCIDAS_CTRL_ADNEI BIT(11) /* fifo not empty int status (latch) */ +#define PCIDAS_CTRL_ADNE BIT(12) /* fifo not empty status (realtime) */ +#define PCIDAS_CTRL_DAEMIE BIT(12) /* dac empty int enable */ +#define PCIDAS_CTRL_LADFUL BIT(13) /* fifo overflow / clear */ +#define PCIDAS_CTRL_DAEMI BIT(14) /* dac fifo empty int status / clear */ + +#define PCIDAS_CTRL_AI_INT (PCIDAS_CTRL_EOAI | PCIDAS_CTRL_EOBI | \ + PCIDAS_CTRL_ADHFI | PCIDAS_CTRL_ADNEI | \ + PCIDAS_CTRL_LADFUL) +#define PCIDAS_CTRL_AO_INT (PCIDAS_CTRL_DAHFI | PCIDAS_CTRL_DAEMI) + +#define PCIDAS_AI_REG 0x02 /* ADC CHANNEL MUX AND CONTROL reg */ +#define PCIDAS_AI_FIRST(x) ((x) & 0xf) +#define PCIDAS_AI_LAST(x) (((x) & 0xf) << 4) +#define PCIDAS_AI_CHAN(x) (PCIDAS_AI_FIRST(x) | PCIDAS_AI_LAST(x)) +#define PCIDAS_AI_GAIN(x) (((x) & 0x3) << 8) +#define PCIDAS_AI_SE BIT(10) /* Inputs in single-ended mode */ +#define PCIDAS_AI_UNIP BIT(11) /* Analog front-end unipolar mode */ +#define PCIDAS_AI_PACER(x) (((x) & 0x3) << 12) +#define PCIDAS_AI_PACER_SW PCIDAS_AI_PACER(0) /* software pacer */ +#define PCIDAS_AI_PACER_INT PCIDAS_AI_PACER(1) /* int. pacer */ +#define PCIDAS_AI_PACER_EXTN PCIDAS_AI_PACER(2) /* ext. falling edge */ +#define PCIDAS_AI_PACER_EXTP PCIDAS_AI_PACER(3) /* ext. rising edge */ +#define PCIDAS_AI_PACER_MASK PCIDAS_AI_PACER(3) /* pacer source bits */ +#define PCIDAS_AI_EOC BIT(14) /* adc not busy */ + +#define PCIDAS_TRIG_REG 0x04 /* TRIGGER CONTROL/STATUS register */ +#define PCIDAS_TRIG_SEL(x) (((x) & 0x3) << 0) +#define PCIDAS_TRIG_SEL_NONE PCIDAS_TRIG_SEL(0) /* no start trigger */ +#define PCIDAS_TRIG_SEL_SW PCIDAS_TRIG_SEL(1) /* software start trigger */ +#define PCIDAS_TRIG_SEL_EXT PCIDAS_TRIG_SEL(2) /* ext. start trigger */ +#define PCIDAS_TRIG_SEL_ANALOG PCIDAS_TRIG_SEL(3) /* ext. analog trigger */ +#define PCIDAS_TRIG_SEL_MASK PCIDAS_TRIG_SEL(3) /* start trigger mask */ +#define PCIDAS_TRIG_POL BIT(2) /* invert trigger (1602 only) */ +#define PCIDAS_TRIG_MODE BIT(3) /* edge/level trigerred (1602 only) */ +#define PCIDAS_TRIG_EN BIT(4) /* enable external start trigger */ +#define PCIDAS_TRIG_BURSTE BIT(5) /* burst mode enable */ +#define PCIDAS_TRIG_CLR BIT(7) /* clear external trigger */ + +#define PCIDAS_CALIB_REG 0x06 /* CALIBRATION register */ +#define PCIDAS_CALIB_8800_SEL BIT(8) /* select 8800 caldac */ +#define PCIDAS_CALIB_TRIM_SEL BIT(9) /* select ad7376 trim pot */ +#define PCIDAS_CALIB_DAC08_SEL BIT(10) /* select dac08 caldac */ +#define PCIDAS_CALIB_SRC(x) (((x) & 0x7) << 11) +#define PCIDAS_CALIB_EN BIT(14) /* calibration source enable */ +#define PCIDAS_CALIB_DATA BIT(15) /* serial data bit going to caldac */ + +#define PCIDAS_AO_REG 0x08 /* dac control and status register */ +#define PCIDAS_AO_EMPTY BIT(0) /* fifo empty, write clear (1602) */ +#define PCIDAS_AO_DACEN BIT(1) /* dac enable */ +#define PCIDAS_AO_START BIT(2) /* start/arm fifo (1602) */ +#define PCIDAS_AO_PACER(x) (((x) & 0x3) << 3) /* (1602) */ +#define PCIDAS_AO_PACER_SW PCIDAS_AO_PACER(0) /* software pacer */ +#define PCIDAS_AO_PACER_INT PCIDAS_AO_PACER(1) /* int. pacer */ +#define PCIDAS_AO_PACER_EXTN PCIDAS_AO_PACER(2) /* ext. falling edge */ +#define PCIDAS_AO_PACER_EXTP PCIDAS_AO_PACER(3) /* ext. rising edge */ +#define PCIDAS_AO_PACER_MASK PCIDAS_AO_PACER(3) /* pacer source bits */ +#define PCIDAS_AO_CHAN_EN(c) BIT(5 + ((c) & 0x1)) +#define PCIDAS_AO_CHAN_MASK (PCIDAS_AO_CHAN_EN(0) | PCIDAS_AO_CHAN_EN(1)) +#define PCIDAS_AO_UPDATE_BOTH BIT(7) /* update both dacs */ +#define PCIDAS_AO_RANGE(c, r) (((r) & 0x3) << (8 + 2 * ((c) & 0x1))) +#define PCIDAS_AO_RANGE_MASK(c) PCIDAS_AO_RANGE((c), 0x3) -/* analog output registers for 100x, 1200 series */ -static inline unsigned int DAC_DATA_REG(unsigned int channel) -{ - return 2 * (channel & 0x1); -} +/* + * PCI BAR2 Register map (devpriv->pcibar2) + */ +#define PCIDAS_AI_DATA_REG 0x00 +#define PCIDAS_AI_FIFO_CLR_REG 0x02 -/* analog output registers for 1602 series*/ -#define DACDATA 0 /* DAC DATA register */ -#define DACFIFOCLR 2 /* DAC FIFO CLEAR */ +/* + * PCI BAR3 Register map (dev->iobase) + */ +#define PCIDAS_AI_8254_BASE 0x00 +#define PCIDAS_8255_BASE 0x04 +#define PCIDAS_AO_8254_BASE 0x08 -#define IS_UNIPOLAR 0x4 /* unipolar range mask */ +/* + * PCI BAR4 Register map (devpriv->pcibar4) + */ +#define PCIDAS_AO_DATA_REG(x) (0x00 + ((x) * 2)) +#define PCIDAS_AO_FIFO_REG 0x00 +#define PCIDAS_AO_FIFO_CLR_REG 0x02 /* analog input ranges for most boards */ static const struct comedi_lrange cb_pcidas_ranges = { @@ -215,11 +212,6 @@ static const struct comedi_lrange cb_pcidas_ao_ranges = { } }; -enum trimpot_model { - AD7376, - AD8402, -}; - enum cb_pcidas_boardid { BOARD_PCIDAS1602_16, BOARD_PCIDAS1200, @@ -233,132 +225,97 @@ enum cb_pcidas_boardid { struct cb_pcidas_board { const char *name; - int ai_nchan; /* Inputs in single-ended mode */ - int ai_bits; /* analog input resolution */ int ai_speed; /* fastest conversion period in ns */ - int ao_nchan; /* number of analog out channels */ - int has_ao_fifo; /* analog output has fifo */ int ao_scan_speed; /* analog output scan speed for 1602 series */ int fifo_size; /* number of samples fifo can hold */ - const struct comedi_lrange *ranges; - enum trimpot_model trimpot; - unsigned has_dac08:1; - unsigned is_1602:1; + unsigned int is_16bit; /* ai/ao is 1=16-bit; 0=12-bit */ + unsigned int use_alt_range:1; /* use alternate ai range table */ + unsigned int has_ao:1; /* has 2 analog output channels */ + unsigned int has_ao_fifo:1; /* analog output has fifo */ + unsigned int has_ad8402:1; /* trimpot type 1=AD8402; 0=AD7376 */ + unsigned int has_dac08:1; + unsigned int is_1602:1; }; static const struct cb_pcidas_board cb_pcidas_boards[] = { [BOARD_PCIDAS1602_16] = { .name = "pci-das1602/16", - .ai_nchan = 16, - .ai_bits = 16, .ai_speed = 5000, - .ao_nchan = 2, - .has_ao_fifo = 1, .ao_scan_speed = 10000, .fifo_size = 512, - .ranges = &cb_pcidas_ranges, - .trimpot = AD8402, + .is_16bit = 1, + .has_ao = 1, + .has_ao_fifo = 1, + .has_ad8402 = 1, .has_dac08 = 1, .is_1602 = 1, }, [BOARD_PCIDAS1200] = { .name = "pci-das1200", - .ai_nchan = 16, - .ai_bits = 12, .ai_speed = 3200, - .ao_nchan = 2, .fifo_size = 1024, - .ranges = &cb_pcidas_ranges, - .trimpot = AD7376, + .has_ao = 1, }, [BOARD_PCIDAS1602_12] = { .name = "pci-das1602/12", - .ai_nchan = 16, - .ai_bits = 12, .ai_speed = 3200, - .ao_nchan = 2, - .has_ao_fifo = 1, .ao_scan_speed = 4000, .fifo_size = 1024, - .ranges = &cb_pcidas_ranges, - .trimpot = AD7376, + .has_ao = 1, + .has_ao_fifo = 1, .is_1602 = 1, }, [BOARD_PCIDAS1200_JR] = { .name = "pci-das1200/jr", - .ai_nchan = 16, - .ai_bits = 12, .ai_speed = 3200, .fifo_size = 1024, - .ranges = &cb_pcidas_ranges, - .trimpot = AD7376, }, [BOARD_PCIDAS1602_16_JR] = { .name = "pci-das1602/16/jr", - .ai_nchan = 16, - .ai_bits = 16, .ai_speed = 5000, .fifo_size = 512, - .ranges = &cb_pcidas_ranges, - .trimpot = AD8402, + .is_16bit = 1, + .has_ad8402 = 1, .has_dac08 = 1, .is_1602 = 1, }, [BOARD_PCIDAS1000] = { .name = "pci-das1000", - .ai_nchan = 16, - .ai_bits = 12, .ai_speed = 4000, .fifo_size = 1024, - .ranges = &cb_pcidas_ranges, - .trimpot = AD7376, }, [BOARD_PCIDAS1001] = { .name = "pci-das1001", - .ai_nchan = 16, - .ai_bits = 12, .ai_speed = 6800, - .ao_nchan = 2, .fifo_size = 1024, - .ranges = &cb_pcidas_alt_ranges, - .trimpot = AD7376, + .use_alt_range = 1, + .has_ao = 1, }, [BOARD_PCIDAS1002] = { .name = "pci-das1002", - .ai_nchan = 16, - .ai_bits = 12, .ai_speed = 6800, - .ao_nchan = 2, .fifo_size = 1024, - .ranges = &cb_pcidas_ranges, - .trimpot = AD7376, + .has_ao = 1, }, }; struct cb_pcidas_private { struct comedi_8254 *ao_pacer; /* base addresses */ - unsigned long s5933_config; - unsigned long control_status; - unsigned long adc_fifo; - unsigned long ao_registers; + unsigned long amcc; /* pcibar0 */ + unsigned long pcibar1; + unsigned long pcibar2; + unsigned long pcibar4; /* bits to write to registers */ - unsigned int adc_fifo_bits; - unsigned int s5933_intcsr_bits; - unsigned int ao_control_bits; + unsigned int ctrl; + unsigned int amcc_intcsr; + unsigned int ao_ctrl; /* fifo buffers */ unsigned short ai_buffer[AI_BUFFER_SIZE]; unsigned short ao_buffer[AO_BUFFER_SIZE]; - unsigned int calibration_source; + unsigned int calib_src; }; -static inline unsigned int cal_enable_bits(struct comedi_device *dev) -{ - struct cb_pcidas_private *devpriv = dev->private; - - return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source); -} - static int cb_pcidas_ai_eoc(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -367,15 +324,16 @@ static int cb_pcidas_ai_eoc(struct comedi_device *dev, struct cb_pcidas_private *devpriv = dev->private; unsigned int status; - status = inw(devpriv->control_status + ADCMUX_CONT); - if (status & EOC) + status = inw(devpriv->pcibar1 + PCIDAS_AI_REG); + if (status & PCIDAS_AI_EOC) return 0; return -EBUSY; } -static int cb_pcidas_ai_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int cb_pcidas_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct cb_pcidas_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); @@ -387,30 +345,30 @@ static int cb_pcidas_ai_rinsn(struct comedi_device *dev, /* enable calibration input if appropriate */ if (insn->chanspec & CR_ALT_SOURCE) { - outw(cal_enable_bits(dev), - devpriv->control_status + CALIBRATION_REG); + outw(PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src), + devpriv->pcibar1 + PCIDAS_CALIB_REG); chan = 0; } else { - outw(0, devpriv->control_status + CALIBRATION_REG); + outw(0, devpriv->pcibar1 + PCIDAS_CALIB_REG); } /* set mux limits and gain */ - bits = BEGIN_SCAN(chan) | END_SCAN(chan) | GAIN_BITS(range); + bits = PCIDAS_AI_CHAN(chan) | PCIDAS_AI_GAIN(range); /* set unipolar/bipolar */ - if (range & IS_UNIPOLAR) - bits |= UNIP; + if (comedi_range_is_unipolar(s, range)) + bits |= PCIDAS_AI_UNIP; /* set single-ended/differential */ if (aref != AREF_DIFF) - bits |= SE; - outw(bits, devpriv->control_status + ADCMUX_CONT); + bits |= PCIDAS_AI_SE; + outw(bits, devpriv->pcibar1 + PCIDAS_AI_REG); /* clear fifo */ - outw(0, devpriv->adc_fifo + ADCFIFOCLR); + outw(0, devpriv->pcibar2 + PCIDAS_AI_FIFO_CLR_REG); /* convert n samples */ for (n = 0; n < insn->n; n++) { /* trigger conversion */ - outw(0, devpriv->adc_fifo + ADCDATA); + outw(0, devpriv->pcibar2 + PCIDAS_AI_DATA_REG); /* wait for conversion to end */ ret = comedi_timeout(dev, s, insn, cb_pcidas_ai_eoc, 0); @@ -418,15 +376,17 @@ static int cb_pcidas_ai_rinsn(struct comedi_device *dev, return ret; /* read data */ - data[n] = inw(devpriv->adc_fifo + ADCDATA); + data[n] = inw(devpriv->pcibar2 + PCIDAS_AI_DATA_REG); } /* return the number of samples read/written */ return n; } -static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int cb_pcidas_ai_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct cb_pcidas_private *devpriv = dev->private; int id = data[0]; @@ -440,7 +400,7 @@ static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s, source); return -EINVAL; } - devpriv->calibration_source = source; + devpriv->calib_src = source; break; default: return -EINVAL; @@ -449,155 +409,160 @@ static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s, } /* analog output insn for pcidas-1000 and 1200 series */ -static int cb_pcidas_ao_nofifo_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) +static int cb_pcidas_ao_nofifo_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct cb_pcidas_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); unsigned int range = CR_RANGE(insn->chanspec); + unsigned int val = s->readback[chan]; unsigned long flags; + int i; /* set channel and range */ spin_lock_irqsave(&dev->spinlock, flags); - devpriv->ao_control_bits &= (~DAC_MODE_UPDATE_BOTH & - ~DAC_RANGE_MASK(chan)); - devpriv->ao_control_bits |= (DACEN | DAC_RANGE(chan, range)); - outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); + devpriv->ao_ctrl &= ~(PCIDAS_AO_UPDATE_BOTH | + PCIDAS_AO_RANGE_MASK(chan)); + devpriv->ao_ctrl |= PCIDAS_AO_DACEN | PCIDAS_AO_RANGE(chan, range); + outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG); spin_unlock_irqrestore(&dev->spinlock, flags); - /* remember value for readback */ - s->readback[chan] = data[0]; + for (i = 0; i < insn->n; i++) { + val = data[i]; + outw(val, devpriv->pcibar4 + PCIDAS_AO_DATA_REG(chan)); + } - /* send data */ - outw(data[0], devpriv->ao_registers + DAC_DATA_REG(chan)); + s->readback[chan] = val; return insn->n; } /* analog output insn for pcidas-1602 series */ -static int cb_pcidas_ao_fifo_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int cb_pcidas_ao_fifo_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct cb_pcidas_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); unsigned int range = CR_RANGE(insn->chanspec); + unsigned int val = s->readback[chan]; unsigned long flags; + int i; /* clear dac fifo */ - outw(0, devpriv->ao_registers + DACFIFOCLR); + outw(0, devpriv->pcibar4 + PCIDAS_AO_FIFO_CLR_REG); /* set channel and range */ spin_lock_irqsave(&dev->spinlock, flags); - devpriv->ao_control_bits &= (~DAC_CHAN_EN(0) & ~DAC_CHAN_EN(1) & - ~DAC_RANGE_MASK(chan) & ~DAC_PACER_MASK); - devpriv->ao_control_bits |= (DACEN | DAC_RANGE(chan, range) | - DAC_CHAN_EN(chan) | DAC_START); - outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); + devpriv->ao_ctrl &= ~(PCIDAS_AO_CHAN_MASK | PCIDAS_AO_RANGE_MASK(chan) | + PCIDAS_AO_PACER_MASK); + devpriv->ao_ctrl |= PCIDAS_AO_DACEN | PCIDAS_AO_RANGE(chan, range) | + PCIDAS_AO_CHAN_EN(chan) | PCIDAS_AO_START; + outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG); spin_unlock_irqrestore(&dev->spinlock, flags); - /* remember value for readback */ - s->readback[chan] = data[0]; + for (i = 0; i < insn->n; i++) { + val = data[i]; + outw(val, devpriv->pcibar4 + PCIDAS_AO_FIFO_REG); + } - /* send data */ - outw(data[0], devpriv->ao_registers + DACDATA); + s->readback[chan] = val; return insn->n; } -static int wait_for_nvram_ready(unsigned long s5933_base_addr) +static int cb_pcidas_eeprom_ready(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned long context) { - static const int timeout = 1000; - unsigned int i; + struct cb_pcidas_private *devpriv = dev->private; + unsigned int status; - for (i = 0; i < timeout; i++) { - if ((inb(s5933_base_addr + - AMCC_OP_REG_MCSR_NVCMD) & MCSR_NV_BUSY) - == 0) - return 0; - udelay(1); - } - return -1; + status = inb(devpriv->amcc + AMCC_OP_REG_MCSR_NVCMD); + if ((status & MCSR_NV_BUSY) == 0) + return 0; + return -EBUSY; } -static int nvram_read(struct comedi_device *dev, unsigned int address, - uint8_t *data) +static int cb_pcidas_eeprom_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct cb_pcidas_private *devpriv = dev->private; - unsigned long iobase = devpriv->s5933_config; - - if (wait_for_nvram_ready(iobase) < 0) - return -ETIMEDOUT; - - outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR, - iobase + AMCC_OP_REG_MCSR_NVCMD); - outb(address & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA); - outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR, - iobase + AMCC_OP_REG_MCSR_NVCMD); - outb((address >> 8) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA); - outb(MCSR_NV_ENABLE | MCSR_NV_READ, iobase + AMCC_OP_REG_MCSR_NVCMD); - - if (wait_for_nvram_ready(iobase) < 0) - return -ETIMEDOUT; - - *data = inb(iobase + AMCC_OP_REG_MCSR_NVDATA); - - return 0; -} + unsigned int chan = CR_CHAN(insn->chanspec); + int ret; + int i; -static int eeprom_read_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - uint8_t nvram_data; - int retval; + for (i = 0; i < insn->n; i++) { + /* make sure eeprom is ready */ + ret = comedi_timeout(dev, s, insn, cb_pcidas_eeprom_ready, 0); + if (ret) + return ret; - retval = nvram_read(dev, CR_CHAN(insn->chanspec), &nvram_data); - if (retval < 0) - return retval; + /* set address (chan) and read operation */ + outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR, + devpriv->amcc + AMCC_OP_REG_MCSR_NVCMD); + outb(chan & 0xff, devpriv->amcc + AMCC_OP_REG_MCSR_NVDATA); + outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR, + devpriv->amcc + AMCC_OP_REG_MCSR_NVCMD); + outb((chan >> 8) & 0xff, + devpriv->amcc + AMCC_OP_REG_MCSR_NVDATA); + outb(MCSR_NV_ENABLE | MCSR_NV_READ, + devpriv->amcc + AMCC_OP_REG_MCSR_NVCMD); + + /* wait for data to be returned */ + ret = comedi_timeout(dev, s, insn, cb_pcidas_eeprom_ready, 0); + if (ret) + return ret; - data[0] = nvram_data; + data[i] = inb(devpriv->amcc + AMCC_OP_REG_MCSR_NVDATA); + } - return 1; + return insn->n; } -static void write_calibration_bitstream(struct comedi_device *dev, - unsigned int register_bits, - unsigned int bitstream, - unsigned int bitstream_length) +static void cb_pcidas_calib_write(struct comedi_device *dev, + unsigned int val, unsigned int len, + bool trimpot) { struct cb_pcidas_private *devpriv = dev->private; - static const int write_delay = 1; + unsigned int calib_bits; unsigned int bit; - for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) { - if (bitstream & bit) - register_bits |= SERIAL_DATA_IN_BIT; + calib_bits = PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src); + if (trimpot) { + /* select trimpot */ + calib_bits |= PCIDAS_CALIB_TRIM_SEL; + outw(calib_bits, devpriv->pcibar1 + PCIDAS_CALIB_REG); + } + + /* write bitstream to calibration device */ + for (bit = 1 << (len - 1); bit; bit >>= 1) { + if (val & bit) + calib_bits |= PCIDAS_CALIB_DATA; else - register_bits &= ~SERIAL_DATA_IN_BIT; - udelay(write_delay); - outw(register_bits, devpriv->control_status + CALIBRATION_REG); + calib_bits &= ~PCIDAS_CALIB_DATA; + udelay(1); + outw(calib_bits, devpriv->pcibar1 + PCIDAS_CALIB_REG); } -} + udelay(1); -static void caldac_8800_write(struct comedi_device *dev, - unsigned int chan, uint8_t val) -{ - struct cb_pcidas_private *devpriv = dev->private; - static const int bitstream_length = 11; - unsigned int bitstream = ((chan & 0x7) << 8) | val; - static const int caldac_8800_udelay = 1; - - write_calibration_bitstream(dev, cal_enable_bits(dev), bitstream, - bitstream_length); - - udelay(caldac_8800_udelay); - outw(cal_enable_bits(dev) | SELECT_8800_BIT, - devpriv->control_status + CALIBRATION_REG); - udelay(caldac_8800_udelay); - outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG); + calib_bits = PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src); + + if (!trimpot) { + /* select caldac */ + outw(calib_bits | PCIDAS_CALIB_8800_SEL, + devpriv->pcibar1 + PCIDAS_CALIB_REG); + udelay(1); + } + + /* latch value to trimpot/caldac */ + outw(calib_bits, devpriv->pcibar1 + PCIDAS_CALIB_REG); } static int cb_pcidas_caldac_insn_write(struct comedi_device *dev, @@ -611,7 +576,9 @@ static int cb_pcidas_caldac_insn_write(struct comedi_device *dev, unsigned int val = data[insn->n - 1]; if (s->readback[chan] != val) { - caldac_8800_write(dev, chan, val); + /* write 11-bit channel/value to caldac */ + cb_pcidas_calib_write(dev, (chan << 8) | val, 11, + false); s->readback[chan] = val; } } @@ -619,21 +586,19 @@ static int cb_pcidas_caldac_insn_write(struct comedi_device *dev, return insn->n; } -/* 1602/16 pregain offset */ -static void dac08_write(struct comedi_device *dev, unsigned int value) +static void cb_pcidas_dac08_write(struct comedi_device *dev, unsigned int val) { struct cb_pcidas_private *devpriv = dev->private; - value &= 0xff; - value |= cal_enable_bits(dev); + val |= PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src); /* latch the new value into the caldac */ - outw(value, devpriv->control_status + CALIBRATION_REG); + outw(val, devpriv->pcibar1 + PCIDAS_CALIB_REG); udelay(1); - outw(value | SELECT_DAC08_BIT, - devpriv->control_status + CALIBRATION_REG); + outw(val | PCIDAS_CALIB_DAC08_SEL, + devpriv->pcibar1 + PCIDAS_CALIB_REG); udelay(1); - outw(value, devpriv->control_status + CALIBRATION_REG); + outw(val, devpriv->pcibar1 + PCIDAS_CALIB_REG); udelay(1); } @@ -648,7 +613,7 @@ static int cb_pcidas_dac08_insn_write(struct comedi_device *dev, unsigned int val = data[insn->n - 1]; if (s->readback[chan] != val) { - dac08_write(dev, val); + cb_pcidas_dac08_write(dev, val); s->readback[chan] = val; } } @@ -656,67 +621,17 @@ static int cb_pcidas_dac08_insn_write(struct comedi_device *dev, return insn->n; } -static int trimpot_7376_write(struct comedi_device *dev, uint8_t value) -{ - struct cb_pcidas_private *devpriv = dev->private; - static const int bitstream_length = 7; - unsigned int bitstream = value & 0x7f; - unsigned int register_bits; - static const int ad7376_udelay = 1; - - register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT; - udelay(ad7376_udelay); - outw(register_bits, devpriv->control_status + CALIBRATION_REG); - - write_calibration_bitstream(dev, register_bits, bitstream, - bitstream_length); - - udelay(ad7376_udelay); - outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG); - - return 0; -} - -/* For 1602/16 only - * ch 0 : adc gain - * ch 1 : adc postgain offset */ -static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel, - uint8_t value) -{ - struct cb_pcidas_private *devpriv = dev->private; - static const int bitstream_length = 10; - unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff); - unsigned int register_bits; - static const int ad8402_udelay = 1; - - register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT; - udelay(ad8402_udelay); - outw(register_bits, devpriv->control_status + CALIBRATION_REG); - - write_calibration_bitstream(dev, register_bits, bitstream, - bitstream_length); - - udelay(ad8402_udelay); - outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG); - - return 0; -} - static void cb_pcidas_trimpot_write(struct comedi_device *dev, unsigned int chan, unsigned int val) { - const struct cb_pcidas_board *thisboard = dev->board_ptr; + const struct cb_pcidas_board *board = dev->board_ptr; - switch (thisboard->trimpot) { - case AD7376: - trimpot_7376_write(dev, val); - break; - case AD8402: - trimpot_8402_write(dev, chan, val); - break; - default: - dev_err(dev->class_dev, "driver bug?\n"); - break; + if (board->has_ad8402) { + /* write 10-bit channel/value to AD8402 trimpot */ + cb_pcidas_calib_write(dev, (chan << 8) | val, 10, true); + } else { + /* write 7-bit value to AD7376 trimpot */ + cb_pcidas_calib_write(dev, val, 7, true); } } @@ -770,7 +685,7 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct cb_pcidas_board *thisboard = dev->board_ptr; + const struct cb_pcidas_board *board = dev->board_ptr; int err = 0; unsigned int arg; @@ -821,7 +736,7 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, ~(CR_EDGE | CR_INVERT)); err |= -EINVAL; } - if (!thisboard->is_1602 && (cmd->start_arg & CR_INVERT)) { + if (!board->is_1602 && (cmd->start_arg & CR_INVERT)) { cmd->start_arg &= (CR_FLAGS_MASK & ~CR_INVERT); err |= -EINVAL; } @@ -830,13 +745,13 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER) { err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, - thisboard->ai_speed * + board->ai_speed * cmd->chanlist_len); } if (cmd->convert_src == TRIG_TIMER) { err |= comedi_check_trigger_arg_min(&cmd->convert_arg, - thisboard->ai_speed); + board->ai_speed); } err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, @@ -879,36 +794,37 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, static int cb_pcidas_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - const struct cb_pcidas_board *thisboard = dev->board_ptr; + const struct cb_pcidas_board *board = dev->board_ptr; struct cb_pcidas_private *devpriv = dev->private; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; + unsigned int range0 = CR_RANGE(cmd->chanlist[0]); unsigned int bits; unsigned long flags; - /* make sure CAL_EN_BIT is disabled */ - outw(0, devpriv->control_status + CALIBRATION_REG); + /* make sure PCIDAS_CALIB_EN is disabled */ + outw(0, devpriv->pcibar1 + PCIDAS_CALIB_REG); /* initialize before settings pacer source and count values */ - outw(0, devpriv->control_status + TRIG_CONTSTAT); + outw(PCIDAS_TRIG_SEL_NONE, devpriv->pcibar1 + PCIDAS_TRIG_REG); /* clear fifo */ - outw(0, devpriv->adc_fifo + ADCFIFOCLR); + outw(0, devpriv->pcibar2 + PCIDAS_AI_FIFO_CLR_REG); /* set mux limits, gain and pacer source */ - bits = BEGIN_SCAN(CR_CHAN(cmd->chanlist[0])) | - END_SCAN(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) | - GAIN_BITS(CR_RANGE(cmd->chanlist[0])); + bits = PCIDAS_AI_FIRST(CR_CHAN(cmd->chanlist[0])) | + PCIDAS_AI_LAST(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) | + PCIDAS_AI_GAIN(range0); /* set unipolar/bipolar */ - if (CR_RANGE(cmd->chanlist[0]) & IS_UNIPOLAR) - bits |= UNIP; + if (comedi_range_is_unipolar(s, range0)) + bits |= PCIDAS_AI_UNIP; /* set singleended/differential */ if (CR_AREF(cmd->chanlist[0]) != AREF_DIFF) - bits |= SE; + bits |= PCIDAS_AI_SE; /* set pacer source */ if (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT) - bits |= PACER_EXT_RISE; + bits |= PCIDAS_AI_PACER_EXTP; else - bits |= PACER_INT; - outw(bits, devpriv->control_status + ADCMUX_CONT); + bits |= PCIDAS_AI_PACER_INT; + outw(bits, devpriv->pcibar1 + PCIDAS_AI_REG); /* load counters */ if (cmd->scan_begin_src == TRIG_TIMER || @@ -919,42 +835,43 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev, /* enable interrupts */ spin_lock_irqsave(&dev->spinlock, flags); - devpriv->adc_fifo_bits |= INTE; - devpriv->adc_fifo_bits &= ~INT_MASK; + devpriv->ctrl |= PCIDAS_CTRL_INTE; + devpriv->ctrl &= ~PCIDAS_CTRL_INT_MASK; if (cmd->flags & CMDF_WAKE_EOS) { if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1) { /* interrupt end of burst */ - devpriv->adc_fifo_bits |= INT_EOS; + devpriv->ctrl |= PCIDAS_CTRL_INT_EOS; } else { /* interrupt fifo not empty */ - devpriv->adc_fifo_bits |= INT_FNE; + devpriv->ctrl |= PCIDAS_CTRL_INT_FNE; } } else { /* interrupt fifo half full */ - devpriv->adc_fifo_bits |= INT_FHF; + devpriv->ctrl |= PCIDAS_CTRL_INT_FHF; } /* enable (and clear) interrupts */ - outw(devpriv->adc_fifo_bits | EOAI | INT | LADFUL, - devpriv->control_status + INT_ADCFIFO); + outw(devpriv->ctrl | + PCIDAS_CTRL_EOAI | PCIDAS_CTRL_INT_CLR | PCIDAS_CTRL_LADFUL, + devpriv->pcibar1 + PCIDAS_CTRL_REG); spin_unlock_irqrestore(&dev->spinlock, flags); /* set start trigger and burst mode */ bits = 0; if (cmd->start_src == TRIG_NOW) { - bits |= SW_TRIGGER; + bits |= PCIDAS_TRIG_SEL_SW; } else { /* TRIG_EXT */ - bits |= EXT_TRIGGER | TGEN | XTRCL; - if (thisboard->is_1602) { + bits |= PCIDAS_TRIG_SEL_EXT | PCIDAS_TRIG_EN | PCIDAS_TRIG_CLR; + if (board->is_1602) { if (cmd->start_arg & CR_INVERT) - bits |= TGPOL; + bits |= PCIDAS_TRIG_POL; if (cmd->start_arg & CR_EDGE) - bits |= TGSEL; + bits |= PCIDAS_TRIG_MODE; } } if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1) - bits |= BURSTE; - outw(bits, devpriv->control_status + TRIG_CONTSTAT); + bits |= PCIDAS_TRIG_BURSTE; + outw(bits, devpriv->pcibar1 + PCIDAS_TRIG_REG); return 0; } @@ -982,7 +899,7 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct cb_pcidas_board *thisboard = dev->board_ptr; + const struct cb_pcidas_board *board = dev->board_ptr; struct cb_pcidas_private *devpriv = dev->private; int err = 0; @@ -1014,7 +931,7 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER) { err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, - thisboard->ao_scan_speed); + board->ao_scan_speed); } err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, @@ -1051,23 +968,21 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, return 0; } -/* cancel analog input command */ -static int cb_pcidas_cancel(struct comedi_device *dev, - struct comedi_subdevice *s) +static int cb_pcidas_ai_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) { struct cb_pcidas_private *devpriv = dev->private; unsigned long flags; spin_lock_irqsave(&dev->spinlock, flags); /* disable interrupts */ - devpriv->adc_fifo_bits &= ~INTE & ~EOAIE; - outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO); + devpriv->ctrl &= ~(PCIDAS_CTRL_INTE | PCIDAS_CTRL_EOAIE); + outw(devpriv->ctrl, devpriv->pcibar1 + PCIDAS_CTRL_REG); spin_unlock_irqrestore(&dev->spinlock, flags); /* disable start trigger source and burst mode */ - outw(0, devpriv->control_status + TRIG_CONTSTAT); - /* software pacer source */ - outw(0, devpriv->control_status + ADCMUX_CONT); + outw(PCIDAS_TRIG_SEL_NONE, devpriv->pcibar1 + PCIDAS_TRIG_REG); + outw(PCIDAS_AI_PACER_SW, devpriv->pcibar1 + PCIDAS_AI_REG); return 0; } @@ -1083,14 +998,15 @@ static void cb_pcidas_ao_load_fifo(struct comedi_device *dev, nbytes = comedi_buf_read_samples(s, devpriv->ao_buffer, nsamples); nsamples = comedi_bytes_to_samples(s, nbytes); - outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, nsamples); + outsw(devpriv->pcibar4 + PCIDAS_AO_FIFO_REG, + devpriv->ao_buffer, nsamples); } static int cb_pcidas_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trig_num) { - const struct cb_pcidas_board *thisboard = dev->board_ptr; + const struct cb_pcidas_board *board = dev->board_ptr; struct cb_pcidas_private *devpriv = dev->private; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; @@ -1099,19 +1015,19 @@ static int cb_pcidas_ao_inttrig(struct comedi_device *dev, if (trig_num != cmd->start_arg) return -EINVAL; - cb_pcidas_ao_load_fifo(dev, s, thisboard->fifo_size); + cb_pcidas_ao_load_fifo(dev, s, board->fifo_size); /* enable dac half-full and empty interrupts */ spin_lock_irqsave(&dev->spinlock, flags); - devpriv->adc_fifo_bits |= DAEMIE | DAHFIE; + devpriv->ctrl |= PCIDAS_CTRL_DAEMIE | PCIDAS_CTRL_DAHFIE; /* enable and clear interrupts */ - outw(devpriv->adc_fifo_bits | DAEMI | DAHFI, - devpriv->control_status + INT_ADCFIFO); + outw(devpriv->ctrl | PCIDAS_CTRL_DAEMI | PCIDAS_CTRL_DAHFI, + devpriv->pcibar1 + PCIDAS_CTRL_REG); /* start dac */ - devpriv->ao_control_bits |= DAC_START | DACEN | DAC_EMPTY; - outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); + devpriv->ao_ctrl |= PCIDAS_AO_START | PCIDAS_AO_DACEN | PCIDAS_AO_EMPTY; + outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG); spin_unlock_irqrestore(&dev->spinlock, flags); @@ -1132,21 +1048,21 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev, /* set channel limits, gain */ spin_lock_irqsave(&dev->spinlock, flags); for (i = 0; i < cmd->chanlist_len; i++) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); + unsigned int range = CR_RANGE(cmd->chanlist[i]); + /* enable channel */ - devpriv->ao_control_bits |= - DAC_CHAN_EN(CR_CHAN(cmd->chanlist[i])); + devpriv->ao_ctrl |= PCIDAS_AO_CHAN_EN(chan); /* set range */ - devpriv->ao_control_bits |= DAC_RANGE(CR_CHAN(cmd->chanlist[i]), - CR_RANGE(cmd-> - chanlist[i])); + devpriv->ao_ctrl |= PCIDAS_AO_RANGE(chan, range); } /* disable analog out before settings pacer source and count values */ - outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); + outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG); spin_unlock_irqrestore(&dev->spinlock, flags); /* clear fifo */ - outw(0, devpriv->ao_registers + DACFIFOCLR); + outw(0, devpriv->pcibar4 + PCIDAS_AO_FIFO_CLR_REG); /* load counters */ if (cmd->scan_begin_src == TRIG_TIMER) { @@ -1158,10 +1074,10 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev, spin_lock_irqsave(&dev->spinlock, flags); switch (cmd->scan_begin_src) { case TRIG_TIMER: - devpriv->ao_control_bits |= DAC_PACER_INT; + devpriv->ao_ctrl |= PCIDAS_AO_PACER_INT; break; case TRIG_EXT: - devpriv->ao_control_bits |= DAC_PACER_EXT_RISE; + devpriv->ao_ctrl |= PCIDAS_AO_PACER_EXTP; break; default: spin_unlock_irqrestore(&dev->spinlock, flags); @@ -1175,7 +1091,6 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev, return 0; } -/* cancel analog output command */ static int cb_pcidas_ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { @@ -1184,33 +1099,31 @@ static int cb_pcidas_ao_cancel(struct comedi_device *dev, spin_lock_irqsave(&dev->spinlock, flags); /* disable interrupts */ - devpriv->adc_fifo_bits &= ~DAHFIE & ~DAEMIE; - outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO); + devpriv->ctrl &= ~(PCIDAS_CTRL_DAHFIE | PCIDAS_CTRL_DAEMIE); + outw(devpriv->ctrl, devpriv->pcibar1 + PCIDAS_CTRL_REG); /* disable output */ - devpriv->ao_control_bits &= ~DACEN & ~DAC_PACER_MASK; - outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); + devpriv->ao_ctrl &= ~(PCIDAS_AO_DACEN | PCIDAS_AO_PACER_MASK); + outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG); spin_unlock_irqrestore(&dev->spinlock, flags); return 0; } -static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status) +static unsigned int cb_pcidas_ao_interrupt(struct comedi_device *dev, + unsigned int status) { - const struct cb_pcidas_board *thisboard = dev->board_ptr; + const struct cb_pcidas_board *board = dev->board_ptr; struct cb_pcidas_private *devpriv = dev->private; struct comedi_subdevice *s = dev->write_subdev; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; - unsigned long flags; + unsigned int irq_clr = 0; - if (status & DAEMI) { - /* clear dac empty interrupt latch */ - spin_lock_irqsave(&dev->spinlock, flags); - outw(devpriv->adc_fifo_bits | DAEMI, - devpriv->control_status + INT_ADCFIFO); - spin_unlock_irqrestore(&dev->spinlock, flags); - if (inw(devpriv->ao_registers + DAC_CSR) & DAC_EMPTY) { + if (status & PCIDAS_CTRL_DAEMI) { + irq_clr |= PCIDAS_CTRL_DAEMI; + + if (inw(devpriv->pcibar4 + PCIDAS_AO_REG) & PCIDAS_AO_EMPTY) { if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg) { async->events |= COMEDI_CB_EOA; @@ -1219,83 +1132,55 @@ static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status) async->events |= COMEDI_CB_ERROR; } } - } else if (status & DAHFI) { - cb_pcidas_ao_load_fifo(dev, s, thisboard->fifo_size / 2); + } else if (status & PCIDAS_CTRL_DAHFI) { + irq_clr |= PCIDAS_CTRL_DAHFI; - /* clear half-full interrupt latch */ - spin_lock_irqsave(&dev->spinlock, flags); - outw(devpriv->adc_fifo_bits | DAHFI, - devpriv->control_status + INT_ADCFIFO); - spin_unlock_irqrestore(&dev->spinlock, flags); + cb_pcidas_ao_load_fifo(dev, s, board->fifo_size / 2); } comedi_handle_events(dev, s); + + return irq_clr; } -static irqreturn_t cb_pcidas_interrupt(int irq, void *d) +static unsigned int cb_pcidas_ai_interrupt(struct comedi_device *dev, + unsigned int status) { - struct comedi_device *dev = (struct comedi_device *)d; - const struct cb_pcidas_board *thisboard = dev->board_ptr; + const struct cb_pcidas_board *board = dev->board_ptr; 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; - static const int timeout = 10000; - unsigned long flags; - - if (!dev->attached) - return IRQ_NONE; - - async = s->async; - cmd = &async->cmd; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned int irq_clr = 0; - s5933_status = inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR); + if (status & PCIDAS_CTRL_ADHFI) { + unsigned int num_samples; - if ((INTCSR_INTR_ASSERTED & s5933_status) == 0) - return IRQ_NONE; + irq_clr |= PCIDAS_CTRL_INT_CLR; - /* make sure mailbox 4 is empty */ - inl_p(devpriv->s5933_config + AMCC_OP_REG_IMB4); - /* clear interrupt on amcc s5933 */ - outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS, - devpriv->s5933_config + AMCC_OP_REG_INTCSR); - - status = inw(devpriv->control_status + INT_ADCFIFO); - - /* check for analog output interrupt */ - if (status & (DAHFI | DAEMI)) - handle_ao_interrupt(dev, status); - /* check for analog input interrupts */ - /* if fifo half-full */ - if (status & ADHFI) { - /* read data */ - num_samples = comedi_nsamples_left(s, half_fifo); - insw(devpriv->adc_fifo + ADCDATA, devpriv->ai_buffer, - num_samples); + /* FIFO is half-full - read data */ + num_samples = comedi_nsamples_left(s, board->fifo_size / 2); + insw(devpriv->pcibar2 + PCIDAS_AI_DATA_REG, + devpriv->ai_buffer, num_samples); comedi_buf_write_samples(s, devpriv->ai_buffer, num_samples); if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg) async->events |= COMEDI_CB_EOA; + } else if (status & (PCIDAS_CTRL_ADNEI | PCIDAS_CTRL_EOBI)) { + unsigned int i; - /* clear half-full interrupt latch */ - spin_lock_irqsave(&dev->spinlock, flags); - outw(devpriv->adc_fifo_bits | INT, - devpriv->control_status + INT_ADCFIFO); - spin_unlock_irqrestore(&dev->spinlock, flags); - /* else if fifo not empty */ - } else if (status & (ADNEI | EOBI)) { - for (i = 0; i < timeout; i++) { + irq_clr |= PCIDAS_CTRL_INT_CLR; + + /* FIFO is not empty - read data until empty or timeoout */ + for (i = 0; i < 10000; i++) { unsigned short val; /* break if fifo is empty */ - if ((ADNE & inw(devpriv->control_status + - INT_ADCFIFO)) == 0) + if ((inw(devpriv->pcibar1 + PCIDAS_CTRL_REG) & + PCIDAS_CTRL_ADNE) == 0) break; - val = inw(devpriv->adc_fifo); + val = inw(devpriv->pcibar2 + PCIDAS_AI_DATA_REG); comedi_buf_write_samples(s, &val, 1); if (cmd->stop_src == TRIG_COUNT && @@ -1304,33 +1189,67 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) break; } } - /* clear not-empty interrupt latch */ - spin_lock_irqsave(&dev->spinlock, flags); - outw(devpriv->adc_fifo_bits | INT, - devpriv->control_status + INT_ADCFIFO); - spin_unlock_irqrestore(&dev->spinlock, flags); - } else if (status & EOAI) { + } else if (status & PCIDAS_CTRL_EOAI) { + irq_clr |= PCIDAS_CTRL_EOAI; + dev_err(dev->class_dev, "bug! encountered end of acquisition interrupt?\n"); - /* clear EOA interrupt latch */ - spin_lock_irqsave(&dev->spinlock, flags); - outw(devpriv->adc_fifo_bits | EOAI, - devpriv->control_status + INT_ADCFIFO); - spin_unlock_irqrestore(&dev->spinlock, flags); } + /* check for fifo overflow */ - if (status & LADFUL) { + if (status & PCIDAS_CTRL_LADFUL) { + irq_clr |= PCIDAS_CTRL_LADFUL; + dev_err(dev->class_dev, "fifo overflow\n"); - /* clear overflow interrupt latch */ - spin_lock_irqsave(&dev->spinlock, flags); - outw(devpriv->adc_fifo_bits | LADFUL, - devpriv->control_status + INT_ADCFIFO); - spin_unlock_irqrestore(&dev->spinlock, flags); async->events |= COMEDI_CB_ERROR; } comedi_handle_events(dev, s); + return irq_clr; +} + +static irqreturn_t cb_pcidas_interrupt(int irq, void *d) +{ + struct comedi_device *dev = d; + struct cb_pcidas_private *devpriv = dev->private; + unsigned int irq_clr = 0; + unsigned int amcc_status; + unsigned int status; + + if (!dev->attached) + return IRQ_NONE; + + amcc_status = inl(devpriv->amcc + AMCC_OP_REG_INTCSR); + + if ((INTCSR_INTR_ASSERTED & amcc_status) == 0) + return IRQ_NONE; + + /* make sure mailbox 4 is empty */ + inl_p(devpriv->amcc + AMCC_OP_REG_IMB4); + /* clear interrupt on amcc s5933 */ + outl(devpriv->amcc_intcsr | INTCSR_INBOX_INTR_STATUS, + devpriv->amcc + AMCC_OP_REG_INTCSR); + + status = inw(devpriv->pcibar1 + PCIDAS_CTRL_REG); + + /* handle analog output interrupts */ + if (status & PCIDAS_CTRL_AO_INT) + irq_clr |= cb_pcidas_ao_interrupt(dev, status); + + /* handle analog input interrupts */ + if (status & PCIDAS_CTRL_AI_INT) + irq_clr |= cb_pcidas_ai_interrupt(dev, status); + + if (irq_clr) { + unsigned long flags; + + spin_lock_irqsave(&dev->spinlock, flags); + outw(devpriv->ctrl | irq_clr, + devpriv->pcibar1 + PCIDAS_CTRL_REG); + spin_unlock_irqrestore(&dev->spinlock, flags); + } + return IRQ_HANDLED; } @@ -1338,18 +1257,18 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct cb_pcidas_board *thisboard = NULL; + const struct cb_pcidas_board *board = NULL; struct cb_pcidas_private *devpriv; struct comedi_subdevice *s; int i; int ret; if (context < ARRAY_SIZE(cb_pcidas_boards)) - thisboard = &cb_pcidas_boards[context]; - if (!thisboard) + board = &cb_pcidas_boards[context]; + if (!board) return -ENODEV; - dev->board_ptr = thisboard; - dev->board_name = thisboard->name; + dev->board_ptr = board; + dev->board_name = board->name; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -1359,16 +1278,16 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, if (ret) return ret; - devpriv->s5933_config = pci_resource_start(pcidev, 0); - devpriv->control_status = pci_resource_start(pcidev, 1); - devpriv->adc_fifo = pci_resource_start(pcidev, 2); + devpriv->amcc = pci_resource_start(pcidev, 0); + devpriv->pcibar1 = pci_resource_start(pcidev, 1); + devpriv->pcibar2 = pci_resource_start(pcidev, 2); dev->iobase = pci_resource_start(pcidev, 3); - if (thisboard->ao_nchan) - devpriv->ao_registers = pci_resource_start(pcidev, 4); + if (board->has_ao) + devpriv->pcibar4 = pci_resource_start(pcidev, 4); /* disable and clear interrupts on amcc s5933 */ outl(INTCSR_INBOX_INTR_STATUS, - devpriv->s5933_config + AMCC_OP_REG_INTCSR); + devpriv->amcc + AMCC_OP_REG_INTCSR); ret = request_irq(pcidev->irq, cb_pcidas_interrupt, IRQF_SHARED, dev->board_name, dev); @@ -1379,12 +1298,12 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, } dev->irq = pcidev->irq; - dev->pacer = comedi_8254_init(dev->iobase + ADC8254, + dev->pacer = comedi_8254_init(dev->iobase + PCIDAS_AI_8254_BASE, I8254_OSC_BASE_10MHZ, I8254_IO8, 0); if (!dev->pacer) return -ENOMEM; - devpriv->ao_pacer = comedi_8254_init(dev->iobase + DAC8254, + devpriv->ao_pacer = comedi_8254_init(dev->iobase + PCIDAS_AO_8254_BASE, I8254_OSC_BASE_10MHZ, I8254_IO8, 0); if (!devpriv->ao_pacer) @@ -1394,97 +1313,104 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, if (ret) return ret; + /* Analog Input subdevice */ s = &dev->subdevices[0]; - /* analog input subdevice */ - dev->read_subdev = s; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; - /* WARNING: Number of inputs in differential mode is ignored */ - s->n_chan = thisboard->ai_nchan; - s->len_chanlist = thisboard->ai_nchan; - s->maxdata = (1 << thisboard->ai_bits) - 1; - s->range_table = thisboard->ranges; - s->insn_read = cb_pcidas_ai_rinsn; - s->insn_config = ai_config_insn; - s->do_cmd = cb_pcidas_ai_cmd; - s->do_cmdtest = cb_pcidas_ai_cmdtest; - s->cancel = cb_pcidas_cancel; - - /* analog output subdevice */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; + s->n_chan = 16; + s->maxdata = board->is_16bit ? 0xffff : 0x0fff; + s->range_table = board->use_alt_range ? &cb_pcidas_alt_ranges + : &cb_pcidas_ranges; + s->insn_read = cb_pcidas_ai_insn_read; + s->insn_config = cb_pcidas_ai_insn_config; + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = s->n_chan; + s->do_cmd = cb_pcidas_ai_cmd; + s->do_cmdtest = cb_pcidas_ai_cmdtest; + s->cancel = cb_pcidas_ai_cancel; + } + + /* Analog Output subdevice */ s = &dev->subdevices[1]; - if (thisboard->ao_nchan) { - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND; - s->n_chan = thisboard->ao_nchan; - /* - * analog out resolution is the same as - * analog input resolution, so use ai_bits - */ - s->maxdata = (1 << thisboard->ai_bits) - 1; - s->range_table = &cb_pcidas_ao_ranges; - /* default to no fifo (*insn_write) */ - s->insn_write = cb_pcidas_ao_nofifo_winsn; + if (board->has_ao) { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND; + s->n_chan = 2; + s->maxdata = board->is_16bit ? 0xffff : 0x0fff; + s->range_table = &cb_pcidas_ao_ranges; + s->insn_write = (board->has_ao_fifo) + ? cb_pcidas_ao_fifo_insn_write + : cb_pcidas_ao_nofifo_insn_write; ret = comedi_alloc_subdev_readback(s); if (ret) return ret; - if (thisboard->has_ao_fifo) { + if (dev->irq && board->has_ao_fifo) { dev->write_subdev = s; - s->subdev_flags |= SDF_CMD_WRITE; - /* use fifo (*insn_write) instead */ - s->insn_write = cb_pcidas_ao_fifo_winsn; - s->do_cmdtest = cb_pcidas_ao_cmdtest; - s->do_cmd = cb_pcidas_ao_cmd; - s->cancel = cb_pcidas_ao_cancel; + s->subdev_flags |= SDF_CMD_WRITE; + s->do_cmdtest = cb_pcidas_ao_cmdtest; + s->do_cmd = cb_pcidas_ao_cmd; + s->cancel = cb_pcidas_ao_cancel; } } else { - s->type = COMEDI_SUBD_UNUSED; + s->type = COMEDI_SUBD_UNUSED; } /* 8255 */ s = &dev->subdevices[2]; - ret = subdev_8255_init(dev, s, NULL, DIO_8255); + ret = subdev_8255_init(dev, s, NULL, PCIDAS_8255_BASE); if (ret) return ret; - /* serial EEPROM, */ + /* Memory subdevice - serial EEPROM */ s = &dev->subdevices[3]; - s->type = COMEDI_SUBD_MEMORY; - s->subdev_flags = SDF_READABLE | SDF_INTERNAL; - s->n_chan = 256; - s->maxdata = 0xff; - s->insn_read = eeprom_read_insn; + s->type = COMEDI_SUBD_MEMORY; + s->subdev_flags = SDF_READABLE | SDF_INTERNAL; + s->n_chan = 256; + s->maxdata = 0xff; + s->insn_read = cb_pcidas_eeprom_insn_read; - /* 8800 caldac */ + /* Calibration subdevice - 8800 caldac */ s = &dev->subdevices[4]; - s->type = COMEDI_SUBD_CALIB; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; - s->n_chan = NUM_CHANNELS_8800; - s->maxdata = 0xff; - s->insn_write = cb_pcidas_caldac_insn_write; + s->type = COMEDI_SUBD_CALIB; + s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = 8; + s->maxdata = 0xff; + s->insn_write = cb_pcidas_caldac_insn_write; ret = comedi_alloc_subdev_readback(s); if (ret) return ret; for (i = 0; i < s->n_chan; i++) { - caldac_8800_write(dev, i, s->maxdata / 2); - s->readback[i] = s->maxdata / 2; + unsigned int val = s->maxdata / 2; + + /* write 11-bit channel/value to caldac */ + cb_pcidas_calib_write(dev, (i << 8) | val, 11, false); + s->readback[i] = val; } - /* trim potentiometer */ + /* Calibration subdevice - trim potentiometer */ s = &dev->subdevices[5]; - s->type = COMEDI_SUBD_CALIB; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; - if (thisboard->trimpot == AD7376) { - s->n_chan = NUM_CHANNELS_7376; - s->maxdata = 0x7f; + s->type = COMEDI_SUBD_CALIB; + s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL; + if (board->has_ad8402) { + /* + * pci-das1602/16 have an AD8402 trimpot: + * chan 0 : adc gain + * chan 1 : adc postgain offset + */ + s->n_chan = 2; + s->maxdata = 0xff; } else { - s->n_chan = NUM_CHANNELS_8402; - s->maxdata = 0xff; + /* all other boards have an AD7376 trimpot */ + s->n_chan = 1; + s->maxdata = 0x7f; } - s->insn_write = cb_pcidas_trimpot_insn_write; + s->insn_write = cb_pcidas_trimpot_insn_write; ret = comedi_alloc_subdev_readback(s); if (ret) @@ -1495,36 +1421,35 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, s->readback[i] = s->maxdata / 2; } - /* dac08 caldac */ + /* Calibration subdevice - pci-das1602/16 pregain offset (dac08) */ s = &dev->subdevices[6]; - if (thisboard->has_dac08) { - s->type = COMEDI_SUBD_CALIB; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; - s->n_chan = NUM_CHANNELS_DAC08; - s->maxdata = 0xff; - s->insn_write = cb_pcidas_dac08_insn_write; + if (board->has_dac08) { + s->type = COMEDI_SUBD_CALIB; + s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = 1; + s->maxdata = 0xff; + s->insn_write = cb_pcidas_dac08_insn_write; ret = comedi_alloc_subdev_readback(s); if (ret) return ret; for (i = 0; i < s->n_chan; i++) { - dac08_write(dev, s->maxdata / 2); + cb_pcidas_dac08_write(dev, s->maxdata / 2); s->readback[i] = s->maxdata / 2; } } else { - s->type = COMEDI_SUBD_UNUSED; + s->type = COMEDI_SUBD_UNUSED; } /* make sure mailbox 4 is empty */ - inl(devpriv->s5933_config + AMCC_OP_REG_IMB4); + inl(devpriv->amcc + AMCC_OP_REG_IMB4); /* Set bits to enable incoming mailbox interrupts on amcc s5933. */ - devpriv->s5933_intcsr_bits = - INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) | - INTCSR_INBOX_FULL_INT; + devpriv->amcc_intcsr = INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) | + INTCSR_INBOX_FULL_INT; /* clear and enable interrupt on amcc s5933 */ - outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS, - devpriv->s5933_config + AMCC_OP_REG_INTCSR); + outl(devpriv->amcc_intcsr | INTCSR_INBOX_INTR_STATUS, + devpriv->amcc + AMCC_OP_REG_INTCSR); return 0; } @@ -1534,9 +1459,9 @@ static void cb_pcidas_detach(struct comedi_device *dev) struct cb_pcidas_private *devpriv = dev->private; if (devpriv) { - if (devpriv->s5933_config) + if (devpriv->amcc) outl(INTCSR_INBOX_INTR_STATUS, - devpriv->s5933_config + AMCC_OP_REG_INTCSR); + devpriv->amcc + AMCC_OP_REG_INTCSR); kfree(devpriv->ao_pacer); } comedi_pci_detach(dev); @@ -1578,5 +1503,5 @@ static struct pci_driver cb_pcidas_pci_driver = { module_comedi_pci_driver(cb_pcidas_driver, cb_pcidas_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for MeasurementComputing PCI-DAS series"); MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/staging/comedi/drivers/cb_pcidas64.c b/kernel/drivers/staging/comedi/drivers/cb_pcidas64.c index a94c33c3d..d33b8fe87 100644 --- a/kernel/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/kernel/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -155,8 +155,10 @@ static inline unsigned int dac_msb_4020_reg(unsigned int channel) } enum read_only_registers { - /* hardware status register, - * reading this apparently clears pending interrupts as well */ + /* + * hardware status register, + * reading this apparently clears pending interrupts as well + */ HW_STATUS_REG = 0x0, PIPE1_READ_REG = 0x4, ADC_READ_PNTR_REG = 0x8, @@ -243,7 +245,8 @@ enum adc_control0_contents { ADC_SOFT_GATE_BITS = 0x1, /* software gate */ ADC_EXT_GATE_BITS = 0x2, /* external digital gate */ ADC_ANALOG_GATE_BITS = 0x3, /* analog level gate */ - ADC_GATE_LEVEL_BIT = 0x4, /* level-sensitive gate (for digital) */ + /* level-sensitive gate (for digital) */ + ADC_GATE_LEVEL_BIT = 0x4, ADC_GATE_POLARITY_BIT = 0x8, /* gate active low */ ADC_START_TRIG_SOFT_BITS = 0x10, ADC_START_TRIG_EXT_BITS = 0x20, @@ -300,7 +303,8 @@ enum calibration_contents { CAL_GAIN_BIT = 0x800, }; -/* calibration sources for 6025 are: +/* + * calibration sources for 6025 are: * 0 : ground * 1 : 10V * 2 : 5V @@ -660,8 +664,10 @@ static const struct hw_fifo_info ai_fifo_60xx = { .fifo_size_reg_mask = 0x7f, }; -/* maximum number of dma transfers we will chain together into a ring - * (and the maximum number of dma buffers we maintain) */ +/* + * maximum number of dma transfers we will chain together into a ring + * (and the maximum number of dma buffers we maintain) + */ #define MAX_AI_DMA_RING_COUNT (0x80000 / DMA_BUFFER_SIZE) #define MIN_AI_DMA_RING_COUNT (0x10000 / DMA_BUFFER_SIZE) #define AO_DMA_RING_COUNT (0x10000 / DMA_BUFFER_SIZE) @@ -1100,10 +1106,10 @@ static const struct pcidas64_board pcidas64_boards[] = { static inline unsigned short se_diff_bit_6xxx(struct comedi_device *dev, int use_differential) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; - if ((thisboard->layout == LAYOUT_64XX && !use_differential) || - (thisboard->layout == LAYOUT_60XX && use_differential)) + if ((board->layout == LAYOUT_64XX && !use_differential) || + (board->layout == LAYOUT_60XX && use_differential)) return ADC_SE_DIFF_BIT; return 0; @@ -1176,17 +1182,17 @@ struct pcidas64_private { static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev, unsigned int range_index) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; - return thisboard->ai_range_code[range_index] << 8; + return board->ai_range_code[range_index] << 8; } static unsigned int hw_revision(const struct comedi_device *dev, uint16_t hw_status_bits) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; - if (thisboard->layout == LAYOUT_4020) + if (board->layout == LAYOUT_4020) return (hw_status_bits >> 13) & 0x7; return (hw_status_bits >> 12) & 0xf; @@ -1196,8 +1202,8 @@ static void set_dac_range_bits(struct comedi_device *dev, uint16_t *bits, unsigned int channel, unsigned int range) { - const struct pcidas64_board *thisboard = dev->board_ptr; - unsigned int code = thisboard->ao_range_code[range]; + const struct pcidas64_board *board = dev->board_ptr; + unsigned int code = board->ao_range_code[range]; if (channel > 1) dev_err(dev->class_dev, "bug! bad channel?\n"); @@ -1253,18 +1259,20 @@ static void disable_ai_interrupts(struct comedi_device *dev) static void enable_ai_interrupts(struct comedi_device *dev, const struct comedi_cmd *cmd) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; uint32_t bits; unsigned long flags; bits = EN_ADC_OVERRUN_BIT | EN_ADC_DONE_INTR_BIT | EN_ADC_ACTIVE_INTR_BIT | EN_ADC_STOP_INTR_BIT; - /* Use pio transfer and interrupt on end of conversion - * if CMDF_WAKE_EOS flag is set. */ + /* + * Use pio transfer and interrupt on end of conversion + * if CMDF_WAKE_EOS flag is set. + */ if (cmd->flags & CMDF_WAKE_EOS) { /* 4020 doesn't support pio transfers except for fifo dregs */ - if (thisboard->layout != LAYOUT_4020) + if (board->layout != LAYOUT_4020) bits |= ADC_INTR_EOSCAN_BITS | EN_ADC_INTR_SRC_BIT; } spin_lock_irqsave(&dev->spinlock, flags); @@ -1277,7 +1285,7 @@ static void enable_ai_interrupts(struct comedi_device *dev, /* initialize plx9080 chip */ static void init_plx9080(struct comedi_device *dev) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; uint32_t bits; void __iomem *plx_iobase = devpriv->plx9080_iobase; @@ -1318,12 +1326,12 @@ static void init_plx9080(struct comedi_device *dev) /* enable local burst mode */ bits |= PLX_DMA_LOCAL_BURST_EN_BIT; /* 4020 uses 32 bit dma */ - if (thisboard->layout == LAYOUT_4020) + if (board->layout == LAYOUT_4020) bits |= PLX_LOCAL_BUS_32_WIDE_BITS; else /* localspace0 bus is 16 bits wide */ bits |= PLX_LOCAL_BUS_16_WIDE_BITS; writel(bits, plx_iobase + PLX_DMA1_MODE_REG); - if (ao_cmd_is_supported(thisboard)) + if (ao_cmd_is_supported(board)) writel(bits, plx_iobase + PLX_DMA0_MODE_REG); /* enable interrupts on plx 9080 */ @@ -1355,10 +1363,10 @@ static void disable_ai_pacing(struct comedi_device *dev) static int set_ai_fifo_segment_length(struct comedi_device *dev, unsigned int num_entries) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; static const int increment_size = 0x100; - const struct hw_fifo_info *const fifo = thisboard->ai_fifo; + const struct hw_fifo_info *const fifo = board->ai_fifo; unsigned int num_increments; uint16_t bits; @@ -1381,13 +1389,15 @@ static int set_ai_fifo_segment_length(struct comedi_device *dev, return devpriv->ai_fifo_segment_length; } -/* adjusts the size of hardware fifo (which determines block size for dma xfers) */ +/* + * adjusts the size of hardware fifo (which determines block size for dma xfers) + */ static int set_ai_fifo_size(struct comedi_device *dev, unsigned int num_samples) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; unsigned int num_fifo_entries; int retval; - const struct hw_fifo_info *const fifo = thisboard->ai_fifo; + const struct hw_fifo_info *const fifo = board->ai_fifo; num_fifo_entries = num_samples / fifo->sample_packing_ratio; @@ -1405,25 +1415,27 @@ static int set_ai_fifo_size(struct comedi_device *dev, unsigned int num_samples) /* query length of fifo */ static unsigned int ai_fifo_size(struct comedi_device *dev) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; return devpriv->ai_fifo_segment_length * - thisboard->ai_fifo->num_segments * - thisboard->ai_fifo->sample_packing_ratio; + board->ai_fifo->num_segments * + board->ai_fifo->sample_packing_ratio; } static void init_stc_registers(struct comedi_device *dev) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; uint16_t bits; unsigned long flags; spin_lock_irqsave(&dev->spinlock, flags); - /* bit should be set for 6025, - * although docs say boards with <= 16 chans should be cleared XXX */ + /* + * bit should be set for 6025, + * although docs say boards with <= 16 chans should be cleared XXX + */ if (1) devpriv->adc_control1_bits |= ADC_QUEUE_CONFIG_BIT; writew(devpriv->adc_control1_bits, @@ -1433,7 +1445,7 @@ static void init_stc_registers(struct comedi_device *dev) writew(0xff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG); bits = SLOW_DAC_BIT | DMA_CH_SELECT_BIT; - if (thisboard->layout == LAYOUT_4020) + if (board->layout == LAYOUT_4020) bits |= INTERNAL_CLOCK_4020_BITS; devpriv->hw_config_bits |= bits; writew(devpriv->hw_config_bits, @@ -1446,8 +1458,7 @@ static void init_stc_registers(struct comedi_device *dev) /* set fifos to maximum size */ devpriv->fifo_size_bits |= DAC_FIFO_BITS; - set_ai_fifo_segment_length(dev, - thisboard->ai_fifo->max_segment_length); + set_ai_fifo_segment_length(dev, board->ai_fifo->max_segment_length); devpriv->dac_control1_bits = DAC_OUTPUT_ENABLE_BIT; devpriv->intr_enable_bits = @@ -1461,13 +1472,13 @@ static void init_stc_registers(struct comedi_device *dev) static int alloc_and_init_dma_members(struct comedi_device *dev) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct pcidas64_private *devpriv = dev->private; int i; /* allocate pci dma buffers */ - for (i = 0; i < ai_dma_ring_count(thisboard); i++) { + for (i = 0; i < ai_dma_ring_count(board); i++) { devpriv->ai_buffer[i] = pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE, &devpriv->ai_buffer_bus_addr[i]); @@ -1475,7 +1486,7 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) return -ENOMEM; } for (i = 0; i < AO_DMA_RING_COUNT; i++) { - if (ao_cmd_is_supported(thisboard)) { + if (ao_cmd_is_supported(board)) { devpriv->ao_buffer[i] = pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE, &devpriv-> @@ -1487,12 +1498,12 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) /* allocate dma descriptors */ devpriv->ai_dma_desc = pci_alloc_consistent(pcidev, sizeof(struct plx_dma_desc) * - ai_dma_ring_count(thisboard), + ai_dma_ring_count(board), &devpriv->ai_dma_desc_bus_addr); if (!devpriv->ai_dma_desc) return -ENOMEM; - if (ao_cmd_is_supported(thisboard)) { + if (ao_cmd_is_supported(board)) { devpriv->ao_dma_desc = pci_alloc_consistent(pcidev, sizeof(struct plx_dma_desc) * @@ -1502,10 +1513,10 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) return -ENOMEM; } /* initialize dma descriptors */ - for (i = 0; i < ai_dma_ring_count(thisboard); i++) { + for (i = 0; i < ai_dma_ring_count(board); i++) { devpriv->ai_dma_desc[i].pci_start_addr = cpu_to_le32(devpriv->ai_buffer_bus_addr[i]); - if (thisboard->layout == LAYOUT_4020) + if (board->layout == LAYOUT_4020) devpriv->ai_dma_desc[i].local_start_addr = cpu_to_le32(devpriv->local1_iobase + ADC_FIFO_REG); @@ -1516,12 +1527,12 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) devpriv->ai_dma_desc[i].transfer_size = cpu_to_le32(0); devpriv->ai_dma_desc[i].next = cpu_to_le32((devpriv->ai_dma_desc_bus_addr + - ((i + 1) % ai_dma_ring_count(thisboard)) * + ((i + 1) % ai_dma_ring_count(board)) * sizeof(devpriv->ai_dma_desc[0])) | PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT | PLX_XFER_LOCAL_TO_PCI); } - if (ao_cmd_is_supported(thisboard)) { + if (ao_cmd_is_supported(board)) { for (i = 0; i < AO_DMA_RING_COUNT; i++) { devpriv->ao_dma_desc[i].pci_start_addr = cpu_to_le32(devpriv->ao_buffer_bus_addr[i]); @@ -1542,7 +1553,7 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) static void cb_pcidas64_free_dma(struct comedi_device *dev) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct pcidas64_private *devpriv = dev->private; int i; @@ -1551,7 +1562,7 @@ static void cb_pcidas64_free_dma(struct comedi_device *dev) return; /* free pci dma buffers */ - for (i = 0; i < ai_dma_ring_count(thisboard); i++) { + for (i = 0; i < ai_dma_ring_count(board); i++) { if (devpriv->ai_buffer[i]) pci_free_consistent(pcidev, DMA_BUFFER_SIZE, @@ -1569,7 +1580,7 @@ static void cb_pcidas64_free_dma(struct comedi_device *dev) if (devpriv->ai_dma_desc) pci_free_consistent(pcidev, sizeof(struct plx_dma_desc) * - ai_dma_ring_count(thisboard), + ai_dma_ring_count(board), devpriv->ai_dma_desc, devpriv->ai_dma_desc_bus_addr); if (devpriv->ao_dma_desc) @@ -1588,7 +1599,9 @@ static inline void warn_external_queue(struct comedi_device *dev) "Use internal AI channel queue (channels must be consecutive and use same range/aref)\n"); } -/* Their i2c requires a huge delay on setting clock or data high for some reason */ +/* + * their i2c requires a huge delay on setting clock or data high for some reason + */ static const int i2c_high_udelay = 1000; static const int i2c_low_udelay = 10; @@ -1684,8 +1697,10 @@ static void i2c_write(struct comedi_device *dev, unsigned int address, uint8_t bitstream; static const int read_bit = 0x1; - /* XXX need mutex to prevent simultaneous attempts to access - * eeprom and i2c bus */ + /* + * XXX need mutex to prevent simultaneous attempts to access + * eeprom and i2c bus + */ /* make sure we dont send anything to eeprom */ devpriv->plx_control_bits &= ~CTL_EE_CS; @@ -1720,12 +1735,12 @@ static int cb_pcidas64_ai_eoc(struct comedi_device *dev, struct comedi_insn *insn, unsigned long context) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; unsigned int status; status = readw(devpriv->main_iobase + HW_STATUS_REG); - if (thisboard->layout == LAYOUT_4020) { + if (board->layout == LAYOUT_4020) { status = readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG); if (status) return 0; @@ -1739,7 +1754,7 @@ static int cb_pcidas64_ai_eoc(struct comedi_device *dev, static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; unsigned int bits = 0, n; unsigned int channel, range, aref; @@ -1763,7 +1778,7 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, devpriv->main_iobase + ADC_CONTROL1_REG); spin_unlock_irqrestore(&dev->spinlock, flags); - if (thisboard->layout != LAYOUT_4020) { + if (board->layout != LAYOUT_4020) { /* use internal queue */ devpriv->hw_config_bits &= ~EXT_QUEUE_BIT; writew(devpriv->hw_config_bits, @@ -1773,18 +1788,22 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, if (insn->chanspec & CR_ALT_SOURCE) { unsigned int cal_en_bit; - if (thisboard->layout == LAYOUT_60XX) + if (board->layout == LAYOUT_60XX) cal_en_bit = CAL_EN_60XX_BIT; else cal_en_bit = CAL_EN_64XX_BIT; - /* select internal reference source to connect - * to channel 0 */ + /* + * select internal reference source to connect + * to channel 0 + */ writew(cal_en_bit | adc_src_bits(devpriv->calibration_source), devpriv->main_iobase + CALIBRATION_REG); } else { - /* make sure internal calibration source - * is turned off */ + /* + * make sure internal calibration source + * is turned off + */ writew(0, devpriv->main_iobase + CALIBRATION_REG); } /* load internal queue */ @@ -1816,8 +1835,10 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, devpriv->i2c_cal_range_bits |= attenuate_bit(channel); else devpriv->i2c_cal_range_bits &= ~attenuate_bit(channel); - /* update calibration/range i2c register only if necessary, - * as it is very slow */ + /* + * update calibration/range i2c register only if necessary, + * as it is very slow + */ if (old_cal_range_bits != devpriv->i2c_cal_range_bits) { uint8_t i2c_data = devpriv->i2c_cal_range_bits; @@ -1825,10 +1846,12 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, sizeof(i2c_data)); } - /* 4020 manual asks that sample interval register to be set + /* + * 4020 manual asks that sample interval register to be set * before writing to convert register. * Using somewhat arbitrary setting of 4 master clock ticks - * = 0.1 usec */ + * = 0.1 usec + */ writew(0, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG); writew(2, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG); } @@ -1846,7 +1869,7 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, if (ret) return ret; - if (thisboard->layout == LAYOUT_4020) + if (board->layout == LAYOUT_4020) data[n] = readl(dev->mmio + ADC_FIFO_REG) & 0xffff; else data[n] = readw(devpriv->main_iobase + PIPE1_READ_REG); @@ -1858,12 +1881,12 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, static int ai_config_calibration_source(struct comedi_device *dev, unsigned int *data) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; unsigned int source = data[1]; int num_calibration_sources; - if (thisboard->layout == LAYOUT_60XX) + if (board->layout == LAYOUT_60XX) num_calibration_sources = 16; else num_calibration_sources = 8; @@ -1880,9 +1903,9 @@ static int ai_config_calibration_source(struct comedi_device *dev, static int ai_config_block_size(struct comedi_device *dev, unsigned int *data) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; int fifo_size; - const struct hw_fifo_info *const fifo = thisboard->ai_fifo; + const struct hw_fifo_info *const fifo = board->ai_fifo; unsigned int block_size, requested_block_size; int retval; @@ -1933,9 +1956,9 @@ static int ai_config_master_clock_4020(struct comedi_device *dev, /* XXX could add support for 60xx series */ static int ai_config_master_clock(struct comedi_device *dev, unsigned int *data) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; - switch (thisboard->layout) { + switch (board->layout) { case LAYOUT_4020: return ai_config_master_clock_4020(dev, data); default: @@ -1963,9 +1986,11 @@ static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s, return -EINVAL; } -/* Gets nearest achievable timing given master clock speed, does not +/* + * Gets nearest achievable timing given master clock speed, does not * take into account possible minimum/maximum divisor values. Used - * by other timing checking functions. */ + * by other timing checking functions. + */ static unsigned int get_divisor(unsigned int ns, unsigned int flags) { unsigned int divisor; @@ -1985,13 +2010,15 @@ static unsigned int get_divisor(unsigned int ns, unsigned int flags) return divisor; } -/* utility function that rounds desired timing to an achievable time, and +/* + * utility function that rounds desired timing to an achievable time, and * sets cmd members appropriately. - * adc paces conversions from master clock by dividing by (x + 3) where x is 24 bit number + * adc paces conversions from master clock by dividing by (x + 3) where x is + * 24 bit number */ static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; unsigned long long convert_divisor = 0; unsigned int scan_divisor; static const int min_convert_divisor = 3; @@ -2001,7 +2028,7 @@ static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd) unsigned long long max_scan_divisor, min_scan_divisor; if (cmd->convert_src == TRIG_TIMER) { - if (thisboard->layout == LAYOUT_4020) { + if (board->layout == LAYOUT_4020) { cmd->convert_arg = 0; } else { convert_divisor = get_divisor(cmd->convert_arg, @@ -2078,7 +2105,7 @@ static int cb_pcidas64_ai_check_chanlist(struct comedi_device *dev, static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; int err = 0; unsigned int tmp_arg, tmp_arg2; unsigned int triggers; @@ -2088,14 +2115,14 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); triggers = TRIG_TIMER; - if (thisboard->layout == LAYOUT_4020) + if (board->layout == LAYOUT_4020) triggers |= TRIG_OTHER; else triggers |= TRIG_FOLLOW; err |= comedi_check_trigger_src(&cmd->scan_begin_src, triggers); triggers = TRIG_TIMER; - if (thisboard->layout == LAYOUT_4020) + if (board->layout == LAYOUT_4020) triggers |= TRIG_NOW; else triggers |= TRIG_EXT; @@ -2137,13 +2164,12 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, } if (cmd->convert_src == TRIG_TIMER) { - if (thisboard->layout == LAYOUT_4020) { + if (board->layout == LAYOUT_4020) { err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0); } else { err |= comedi_check_trigger_arg_min(&cmd->convert_arg, - thisboard-> - ai_speed); + board->ai_speed); /* * if scans are timed faster than conversion rate * allows @@ -2231,12 +2257,12 @@ static void setup_sample_counters(struct comedi_device *dev, static inline unsigned int dma_transfer_size(struct comedi_device *dev) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; unsigned int num_samples; num_samples = devpriv->ai_fifo_segment_length * - thisboard->ai_fifo->sample_packing_ratio; + board->ai_fifo->sample_packing_ratio; if (num_samples > DMA_BUFFER_SIZE / sizeof(uint16_t)) num_samples = DMA_BUFFER_SIZE / sizeof(uint16_t); @@ -2318,9 +2344,9 @@ static void select_master_clock_4020(struct comedi_device *dev, static void select_master_clock(struct comedi_device *dev, const struct comedi_cmd *cmd) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; - switch (thisboard->layout) { + switch (board->layout) { case LAYOUT_4020: select_master_clock_4020(dev, cmd); break; @@ -2350,7 +2376,7 @@ static inline void dma_start_sync(struct comedi_device *dev, static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; uint32_t convert_counter = 0, scan_counter = 0; @@ -2358,7 +2384,7 @@ static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd) select_master_clock(dev, cmd); - if (thisboard->layout == LAYOUT_4020) { + if (board->layout == LAYOUT_4020) { convert_counter = ai_convert_counter_4020(dev, cmd); } else { convert_counter = ai_convert_counter_6xxx(dev, cmd); @@ -2399,12 +2425,12 @@ static int use_internal_queue_6xxx(const struct comedi_cmd *cmd) static int setup_channel_queue(struct comedi_device *dev, const struct comedi_cmd *cmd) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; unsigned short bits; int i; - if (thisboard->layout != LAYOUT_4020) { + if (board->layout != LAYOUT_4020) { if (use_internal_queue_6xxx(cmd)) { devpriv->hw_config_bits &= ~EXT_QUEUE_BIT; writew(devpriv->hw_config_bits, @@ -2468,8 +2494,10 @@ static int setup_channel_queue(struct comedi_device *dev, devpriv->main_iobase + ADC_QUEUE_FIFO_REG); } - /* doing a queue clear is not specified in board docs, - * but required for reliable operation */ + /* + * doing a queue clear is not specified in board docs, + * but required for reliable operation + */ writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG); /* prime queue holding register */ writew(0, devpriv->main_iobase + ADC_QUEUE_LOAD_REG); @@ -2492,8 +2520,10 @@ static int setup_channel_queue(struct comedi_device *dev, devpriv->i2c_cal_range_bits &= ~attenuate_bit(channel); } - /* update calibration/range i2c register only if necessary, - * as it is very slow */ + /* + * update calibration/range i2c register only if necessary, + * as it is very slow + */ if (old_cal_range_bits != devpriv->i2c_cal_range_bits) { uint8_t i2c_data = devpriv->i2c_cal_range_bits; @@ -2510,11 +2540,13 @@ static inline void load_first_dma_descriptor(struct comedi_device *dev, { struct pcidas64_private *devpriv = dev->private; - /* The transfer size, pci address, and local address registers + /* + * The transfer size, pci address, and local address registers * are supposedly unused during chained dma, * but I have found that left over values from last operation * occasionally cause problems with transfer of first dma - * block. Initializing them to zero seems to fix the problem. */ + * block. Initializing them to zero seems to fix the problem. + */ if (dma_channel) { writel(0, devpriv->plx9080_iobase + PLX_DMA1_TRANSFER_SIZE_REG); @@ -2536,7 +2568,7 @@ static inline void load_first_dma_descriptor(struct comedi_device *dev, static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; @@ -2565,7 +2597,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* set mode, allow conversions through software gate */ devpriv->adc_control1_bits |= ADC_SW_GATE_BIT; devpriv->adc_control1_bits &= ~ADC_DITHER_BIT; - if (thisboard->layout != LAYOUT_4020) { + if (board->layout != LAYOUT_4020) { devpriv->adc_control1_bits &= ~ADC_MODE_MASK; if (cmd->convert_src == TRIG_EXT) /* good old mode 13 */ @@ -2595,11 +2627,11 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) writew(0, devpriv->main_iobase + ADC_BUFFER_CLEAR_REG); if ((cmd->flags & CMDF_WAKE_EOS) == 0 || - thisboard->layout == LAYOUT_4020) { + board->layout == LAYOUT_4020) { devpriv->ai_dma_index = 0; /* set dma transfer size */ - for (i = 0; i < ai_dma_ring_count(thisboard); i++) + for (i = 0; i < ai_dma_ring_count(board); i++) devpriv->ai_dma_desc[i].transfer_size = cpu_to_le32(dma_transfer_size(dev) * sizeof(uint16_t)); @@ -2614,7 +2646,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) dma_start_sync(dev, 1); } - if (thisboard->layout == LAYOUT_4020) { + if (board->layout == LAYOUT_4020) { /* set source for external triggers */ bits = 0; if (cmd->start_src == TRIG_EXT && CR_CHAN(cmd->start_arg)) @@ -2669,15 +2701,19 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev) 0x7fff; write_index = readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG) & 0x7fff; - /* Get most significant bits (grey code). + /* + * Get most significant bits (grey code). * Different boards use different code so use a scheme * that doesn't depend on encoding. This read must * occur after reading least significant 15 bits to avoid race - * with fifo switching to next segment. */ + * with fifo switching to next segment. + */ prepost_bits = readw(devpriv->main_iobase + PREPOST_REG); - /* if read and write pointers are not on the same fifo segment, - * read to the end of the read segment */ + /* + * if read and write pointers are not on the same fifo segment, + * read to the end of the read segment + */ read_segment = adc_upper_read_ptr_code(prepost_bits); write_segment = adc_upper_write_ptr_code(prepost_bits); @@ -2706,7 +2742,8 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev) } while (read_segment != write_segment); } -/* Read from 32 bit wide ai fifo of 4020 - deal with insane grey coding of +/* + * Read from 32 bit wide ai fifo of 4020 - deal with insane grey coding of * pointers. The pci-4020 hardware only supports dma transfers (it only * supports the use of pio for draining the last remaining points from the * fifo when a data acquisition operation has completed). @@ -2744,9 +2781,9 @@ static void pio_drain_ai_fifo_32(struct comedi_device *dev) /* empty fifo */ static void pio_drain_ai_fifo(struct comedi_device *dev) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; - if (thisboard->layout == LAYOUT_4020) + if (board->layout == LAYOUT_4020) pio_drain_ai_fifo_32(dev); else pio_drain_ai_fifo_16(dev); @@ -2754,7 +2791,7 @@ static void pio_drain_ai_fifo(struct comedi_device *dev) static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; uint32_t next_transfer_addr; @@ -2775,24 +2812,26 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel) devpriv->ai_buffer_bus_addr[devpriv->ai_dma_index] || next_transfer_addr >= devpriv->ai_buffer_bus_addr[devpriv->ai_dma_index] + - DMA_BUFFER_SIZE) && j < ai_dma_ring_count(thisboard); j++) { + DMA_BUFFER_SIZE) && j < ai_dma_ring_count(board); j++) { /* transfer data from dma buffer to comedi buffer */ num_samples = comedi_nsamples_left(s, dma_transfer_size(dev)); comedi_buf_write_samples(s, devpriv->ai_buffer[devpriv->ai_dma_index], num_samples); devpriv->ai_dma_index = (devpriv->ai_dma_index + 1) % - ai_dma_ring_count(thisboard); + ai_dma_ring_count(board); } - /* XXX check for dma ring buffer overrun - * (use end-of-chain bit to mark last unused buffer) */ + /* + * XXX check for dma ring buffer overrun + * (use end-of-chain bit to mark last unused buffer) + */ } static void handle_ai_interrupt(struct comedi_device *dev, unsigned short status, unsigned int plx_status) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; @@ -2821,7 +2860,7 @@ static void handle_ai_interrupt(struct comedi_device *dev, if ((status & ADC_DONE_BIT) || ((cmd->flags & CMDF_WAKE_EOS) && (status & ADC_INTR_PENDING_BIT) && - (thisboard->layout != LAYOUT_4020))) { + (board->layout != LAYOUT_4020))) { spin_lock_irqsave(&dev->spinlock, flags); if (devpriv->ai_cmd_running) { spin_unlock_irqrestore(&dev->spinlock, flags); @@ -2933,8 +2972,10 @@ static unsigned int load_ao_dma_buffer(struct comedi_device *dev, next_bits = le32_to_cpu(devpriv->ao_dma_desc[buffer_index].next); next_bits |= PLX_END_OF_CHAIN_BIT; devpriv->ao_dma_desc[buffer_index].next = cpu_to_le32(next_bits); - /* clear end of chain bit on previous buffer now that we have set it - * for the last buffer */ + /* + * clear end of chain bit on previous buffer now that we have set it + * for the last buffer + */ next_bits = le32_to_cpu(devpriv->ao_dma_desc[prev_buffer_index].next); next_bits &= ~PLX_END_OF_CHAIN_BIT; devpriv->ao_dma_desc[prev_buffer_index].next = cpu_to_le32(next_bits); @@ -3027,9 +3068,11 @@ static irqreturn_t handle_interrupt(int irq, void *d) plx_status = readl(devpriv->plx9080_iobase + PLX_INTRCS_REG); status = readw(devpriv->main_iobase + HW_STATUS_REG); - /* an interrupt before all the postconfig stuff gets done could + /* + * an interrupt before all the postconfig stuff gets done could * cause a NULL dereference if we continue through the - * interrupt handler */ + * interrupt handler + */ if (!dev->attached) return IRQ_HANDLED; @@ -3068,7 +3111,7 @@ static int ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; int chan = CR_CHAN(insn->chanspec); int range = CR_RANGE(insn->chanspec); @@ -3082,7 +3125,7 @@ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, devpriv->main_iobase + DAC_CONTROL1_REG); /* write to channel */ - if (thisboard->layout == LAYOUT_4020) { + if (board->layout == LAYOUT_4020) { writew(data[0] & 0xff, devpriv->main_iobase + dac_lsb_4020_reg(chan)); writew((data[0] >> 8) & 0xf, @@ -3189,8 +3232,10 @@ static int prep_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) unsigned int nbytes; int i; - /* clear queue pointer too, since external queue has - * weird interactions with ao fifo */ + /* + * clear queue pointer too, since external queue has + * weird interactions with ao fifo + */ writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG); writew(0, devpriv->main_iobase + DAC_BUFFER_CLEAR_REG); @@ -3223,11 +3268,11 @@ 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 = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; if (s->busy) return 0; - if (thisboard->layout == LAYOUT_4020) + if (board->layout == LAYOUT_4020) return 0; else if (use_internal_queue_6xxx(cmd)) return 0; @@ -3306,7 +3351,7 @@ static int cb_pcidas64_ao_check_chanlist(struct comedi_device *dev, static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; int err = 0; unsigned int tmp_arg; @@ -3344,7 +3389,7 @@ static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, if (cmd->scan_begin_src == TRIG_TIMER) { err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, - thisboard->ao_scan_speed); + board->ao_scan_speed); if (get_ao_divisor(cmd->scan_begin_arg, cmd->flags) > max_counter_value) { cmd->scan_begin_arg = (max_counter_value + 2) * @@ -3459,7 +3504,8 @@ static int dio_60xx_wbits(struct comedi_device *dev, return insn->n; } -/* pci-6025 8800 caldac: +/* + * pci-6025 8800 caldac: * address 0 == dac channel 0 offset * address 1 == dac channel 0 gain * address 2 == dac channel 1 offset @@ -3469,7 +3515,8 @@ static int dio_60xx_wbits(struct comedi_device *dev, * address 6 == coarse adc gain * address 7 == fine adc gain */ -/* pci-6402/16 uses all 8 channels for dac: +/* + * pci-6402/16 uses all 8 channels for dac: * address 0 == dac channel 0 fine gain * address 1 == dac channel 0 coarse gain * address 2 == dac channel 0 coarse offset @@ -3478,7 +3525,7 @@ static int dio_60xx_wbits(struct comedi_device *dev, * address 5 == dac channel 1 coarse gain * address 6 == dac channel 0 fine offset * address 7 == dac channel 1 fine offset -*/ + */ static int caldac_8800_write(struct comedi_device *dev, unsigned int address, uint8_t value) @@ -3575,9 +3622,9 @@ static int caldac_i2c_write(struct comedi_device *dev, static void caldac_write(struct comedi_device *dev, unsigned int channel, unsigned int value) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; - switch (thisboard->layout) { + switch (board->layout) { case LAYOUT_60XX: case LAYOUT_64XX: caldac_8800_write(dev, channel, value); @@ -3738,11 +3785,12 @@ static int eeprom_read_insn(struct comedi_device *dev, return 1; } -/* Allocate and initialize the subdevice structures. +/* + * Allocate and initialize the subdevice structures. */ static int setup_subdevices(struct comedi_device *dev) { - const struct pcidas64_board *thisboard = dev->board_ptr; + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; struct comedi_subdevice *s; int i; @@ -3757,24 +3805,26 @@ static int setup_subdevices(struct comedi_device *dev) dev->read_subdev = s; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DITHER | SDF_CMD_READ; - if (thisboard->layout == LAYOUT_60XX) + if (board->layout == LAYOUT_60XX) s->subdev_flags |= SDF_COMMON | SDF_DIFF; - else if (thisboard->layout == LAYOUT_64XX) + else if (board->layout == LAYOUT_64XX) s->subdev_flags |= SDF_DIFF; /* XXX Number of inputs in differential mode is ignored */ - s->n_chan = thisboard->ai_se_chans; + s->n_chan = board->ai_se_chans; s->len_chanlist = 0x2000; - s->maxdata = (1 << thisboard->ai_bits) - 1; - s->range_table = thisboard->ai_range_table; + s->maxdata = (1 << board->ai_bits) - 1; + s->range_table = board->ai_range_table; s->insn_read = ai_rinsn; s->insn_config = ai_config_insn; s->do_cmd = ai_cmd; s->do_cmdtest = ai_cmdtest; s->cancel = ai_cancel; - if (thisboard->layout == LAYOUT_4020) { + if (board->layout == LAYOUT_4020) { uint8_t data; - /* set adc to read from inputs - * (not internal calibration sources) */ + /* + * set adc to read from inputs + * (not internal calibration sources) + */ devpriv->i2c_cal_range_bits = adc_src_4020_bits(4); /* set channels to +-5 volt input ranges */ for (i = 0; i < s->n_chan; i++) @@ -3785,24 +3835,24 @@ static int setup_subdevices(struct comedi_device *dev) /* analog output subdevice */ s = &dev->subdevices[1]; - if (thisboard->ao_nchan) { + if (board->ao_nchan) { s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; - s->n_chan = thisboard->ao_nchan; - s->maxdata = (1 << thisboard->ao_bits) - 1; - s->range_table = thisboard->ao_range_table; + s->n_chan = board->ao_nchan; + s->maxdata = (1 << board->ao_bits) - 1; + s->range_table = board->ao_range_table; s->insn_write = ao_winsn; ret = comedi_alloc_subdev_readback(s); if (ret) return ret; - if (ao_cmd_is_supported(thisboard)) { + if (ao_cmd_is_supported(board)) { dev->write_subdev = s; s->do_cmdtest = ao_cmdtest; s->do_cmd = ao_cmd; - s->len_chanlist = thisboard->ao_nchan; + s->len_chanlist = board->ao_nchan; s->cancel = ao_cancel; } } else { @@ -3811,7 +3861,7 @@ static int setup_subdevices(struct comedi_device *dev) /* digital input */ s = &dev->subdevices[2]; - if (thisboard->layout == LAYOUT_64XX) { + if (board->layout == LAYOUT_64XX) { s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = 4; @@ -3823,7 +3873,7 @@ static int setup_subdevices(struct comedi_device *dev) } /* digital output */ - if (thisboard->layout == LAYOUT_64XX) { + if (board->layout == LAYOUT_64XX) { s = &dev->subdevices[3]; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; @@ -3837,8 +3887,8 @@ static int setup_subdevices(struct comedi_device *dev) /* 8255 */ s = &dev->subdevices[4]; - if (thisboard->has_8255) { - if (thisboard->layout == LAYOUT_4020) { + if (board->has_8255) { + if (board->layout == LAYOUT_4020) { ret = subdev_8255_init(dev, s, dio_callback_4020, I8255_4020_REG); } else { @@ -3853,7 +3903,7 @@ static int setup_subdevices(struct comedi_device *dev) /* 8 channel dio for 60xx */ s = &dev->subdevices[5]; - if (thisboard->layout == LAYOUT_60XX) { + if (board->layout == LAYOUT_60XX) { s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_WRITABLE | SDF_READABLE; s->n_chan = 8; @@ -3870,7 +3920,7 @@ static int setup_subdevices(struct comedi_device *dev) s->type = COMEDI_SUBD_CALIB; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; s->n_chan = 8; - if (thisboard->layout == LAYOUT_4020) + if (board->layout == LAYOUT_4020) s->maxdata = 0xfff; else s->maxdata = 0xff; @@ -3887,7 +3937,7 @@ static int setup_subdevices(struct comedi_device *dev) /* 2 channel ad8402 potentiometer */ s = &dev->subdevices[7]; - if (thisboard->layout == LAYOUT_64XX) { + if (board->layout == LAYOUT_64XX) { s->type = COMEDI_SUBD_CALIB; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; s->n_chan = 2; @@ -3929,16 +3979,16 @@ static int auto_attach(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct pcidas64_board *thisboard = NULL; + const struct pcidas64_board *board = NULL; struct pcidas64_private *devpriv; uint32_t local_range, local_decode; int retval; if (context < ARRAY_SIZE(pcidas64_boards)) - thisboard = &pcidas64_boards[context]; - if (!thisboard) + board = &pcidas64_boards[context]; + if (!board) return -ENODEV; - dev->board_ptr = thisboard; + dev->board_ptr = board; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -3950,7 +4000,7 @@ static int auto_attach(struct comedi_device *dev, pci_set_master(pcidev); /* Initialize dev->board_name */ - dev->board_name = thisboard->name; + dev->board_name = board->name; devpriv->main_phys_iobase = pci_resource_start(pcidev, 2); devpriv->dio_counter_phys_iobase = pci_resource_start(pcidev, 3); diff --git a/kernel/drivers/staging/comedi/drivers/cb_pcidda.c b/kernel/drivers/staging/comedi/drivers/cb_pcidda.c index 30c9e27d1..b00a36a5c 100644 --- a/kernel/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/kernel/drivers/staging/comedi/drivers/cb_pcidda.c @@ -335,18 +335,18 @@ static int cb_pcidda_auto_attach(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct cb_pcidda_board *thisboard = NULL; + const struct cb_pcidda_board *board = NULL; struct cb_pcidda_private *devpriv; struct comedi_subdevice *s; int i; int ret; if (context < ARRAY_SIZE(cb_pcidda_boards)) - thisboard = &cb_pcidda_boards[context]; - if (!thisboard) + board = &cb_pcidda_boards[context]; + if (!board) return -ENODEV; - dev->board_ptr = thisboard; - dev->board_name = thisboard->name; + dev->board_ptr = board; + dev->board_name = board->name; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -366,8 +366,8 @@ static int cb_pcidda_auto_attach(struct comedi_device *dev, /* analog output subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = thisboard->ao_chans; - s->maxdata = (1 << thisboard->ao_bits) - 1; + s->n_chan = board->ao_chans; + s->maxdata = (1 << board->ao_bits) - 1; s->range_table = &cb_pcidda_ranges; s->insn_write = cb_pcidda_ao_insn_write; @@ -384,7 +384,7 @@ static int cb_pcidda_auto_attach(struct comedi_device *dev, devpriv->eeprom_data[i] = cb_pcidda_read_eeprom(dev, i); /* set calibrations dacs */ - for (i = 0; i < thisboard->ao_chans; i++) + for (i = 0; i < board->ao_chans; i++) cb_pcidda_calibrate(dev, i, devpriv->ao_range[i]); return 0; diff --git a/kernel/drivers/staging/comedi/drivers/cb_pcimdas.c b/kernel/drivers/staging/comedi/drivers/cb_pcimdas.c index 4ebf5aae5..47e383989 100644 --- a/kernel/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/kernel/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -141,11 +141,13 @@ static const struct comedi_lrange cb_pcimdas_ai_uni_range = { * jumper-settable on the board. The settings are not software-readable. */ static const struct comedi_lrange cb_pcimdas_ao_range = { - 4, { + 6, { BIP_RANGE(10), BIP_RANGE(5), UNI_RANGE(10), - UNI_RANGE(5) + UNI_RANGE(5), + RANGE_ext(-1, 1), + RANGE_ext(0, 1) } }; diff --git a/kernel/drivers/staging/comedi/drivers/cb_pcimdda.c b/kernel/drivers/staging/comedi/drivers/cb_pcimdda.c index a4781dbbd..19210d89f 100644 --- a/kernel/drivers/staging/comedi/drivers/cb_pcimdda.c +++ b/kernel/drivers/staging/comedi/drivers/cb_pcimdda.c @@ -164,11 +164,7 @@ static int cb_pcimdda_auto_attach(struct comedi_device *dev, s = &dev->subdevices[1]; /* digital i/o subdevice */ - ret = subdev_8255_init(dev, s, NULL, PCIMDDA_8255_BASE_REG); - if (ret) - return ret; - - return 0; + return subdev_8255_init(dev, s, NULL, PCIMDDA_8255_BASE_REG); } static struct comedi_driver cb_pcimdda_driver = { diff --git a/kernel/drivers/staging/comedi/drivers/comedi_8254.h b/kernel/drivers/staging/comedi/drivers/comedi_8254.h index d89f6d94f..f4610ead6 100644 --- a/kernel/drivers/staging/comedi/drivers/comedi_8254.h +++ b/kernel/drivers/staging/comedi/drivers/comedi_8254.h @@ -20,6 +20,12 @@ #ifndef _COMEDI_8254_H #define _COMEDI_8254_H +#include <linux/types.h> + +struct comedi_device; +struct comedi_insn; +struct comedi_subdevice; + /* * Common oscillator base values in nanoseconds */ diff --git a/kernel/drivers/staging/comedi/drivers/comedi_8255.c b/kernel/drivers/staging/comedi/drivers/comedi_8255.c new file mode 100644 index 000000000..b2441efc6 --- /dev/null +++ b/kernel/drivers/staging/comedi/drivers/comedi_8255.c @@ -0,0 +1,285 @@ +/* + * comedi_8255.c + * Generic 8255 digital I/O support + * + * Split from the Comedi "8255" driver module. + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1998 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * Module: comedi_8255 + * Description: Generic 8255 support + * Author: ds + * Updated: Fri, 22 May 2015 12:14:17 +0000 + * Status: works + * + * This module is not used directly by end-users. Rather, it is used by + * other drivers to provide support for an 8255 "Programmable Peripheral + * Interface" (PPI) chip. + * + * The classic in digital I/O. The 8255 appears in Comedi as a single + * digital I/O subdevice with 24 channels. The channel 0 corresponds to + * the 8255's port A, bit 0; channel 23 corresponds to port C, bit 7. + * Direction configuration is done in blocks, with channels 0-7, 8-15, + * 16-19, and 20-23 making up the 4 blocks. The only 8255 mode + * supported is mode 0. + */ + +#include <linux/module.h> +#include "../comedidev.h" + +#include "8255.h" + +struct subdev_8255_private { + unsigned long regbase; + int (*io)(struct comedi_device *dev, int dir, int port, int data, + unsigned long regbase); +}; + +static int subdev_8255_io(struct comedi_device *dev, + int dir, int port, int data, unsigned long regbase) +{ + if (dir) { + outb(data, dev->iobase + regbase + port); + return 0; + } + return inb(dev->iobase + regbase + port); +} + +static int subdev_8255_mmio(struct comedi_device *dev, + int dir, int port, int data, unsigned long regbase) +{ + if (dir) { + writeb(data, dev->mmio + regbase + port); + return 0; + } + return readb(dev->mmio + regbase + port); +} + +static int subdev_8255_insn(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct subdev_8255_private *spriv = s->private; + unsigned long regbase = spriv->regbase; + unsigned int mask; + unsigned int v; + + mask = comedi_dio_update_state(s, data); + if (mask) { + if (mask & 0xff) + spriv->io(dev, 1, I8255_DATA_A_REG, + s->state & 0xff, regbase); + if (mask & 0xff00) + spriv->io(dev, 1, I8255_DATA_B_REG, + (s->state >> 8) & 0xff, regbase); + if (mask & 0xff0000) + spriv->io(dev, 1, I8255_DATA_C_REG, + (s->state >> 16) & 0xff, regbase); + } + + v = spriv->io(dev, 0, I8255_DATA_A_REG, 0, regbase); + v |= (spriv->io(dev, 0, I8255_DATA_B_REG, 0, regbase) << 8); + v |= (spriv->io(dev, 0, I8255_DATA_C_REG, 0, regbase) << 16); + + data[1] = v; + + return insn->n; +} + +static void subdev_8255_do_config(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct subdev_8255_private *spriv = s->private; + unsigned long regbase = spriv->regbase; + int config; + + config = I8255_CTRL_CW; + /* 1 in io_bits indicates output, 1 in config indicates input */ + if (!(s->io_bits & 0x0000ff)) + config |= I8255_CTRL_A_IO; + if (!(s->io_bits & 0x00ff00)) + config |= I8255_CTRL_B_IO; + if (!(s->io_bits & 0x0f0000)) + config |= I8255_CTRL_C_LO_IO; + if (!(s->io_bits & 0xf00000)) + config |= I8255_CTRL_C_HI_IO; + + spriv->io(dev, 1, I8255_CTRL_REG, config, regbase); +} + +static int subdev_8255_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int mask; + int ret; + + if (chan < 8) + mask = 0x0000ff; + else if (chan < 16) + mask = 0x00ff00; + else if (chan < 20) + mask = 0x0f0000; + else + mask = 0xf00000; + + ret = comedi_dio_insn_config(dev, s, insn, data, mask); + if (ret) + return ret; + + subdev_8255_do_config(dev, s); + + return insn->n; +} + +static int __subdev_8255_init(struct comedi_device *dev, + struct comedi_subdevice *s, + int (*io)(struct comedi_device *dev, + int dir, int port, int data, + unsigned long regbase), + unsigned long regbase, + bool is_mmio) +{ + struct subdev_8255_private *spriv; + + spriv = comedi_alloc_spriv(s, sizeof(*spriv)); + if (!spriv) + return -ENOMEM; + + if (io) + spriv->io = io; + else if (is_mmio) + spriv->io = subdev_8255_mmio; + else + spriv->io = subdev_8255_io; + spriv->regbase = regbase; + + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 24; + s->range_table = &range_digital; + s->maxdata = 1; + s->insn_bits = subdev_8255_insn; + s->insn_config = subdev_8255_insn_config; + + subdev_8255_do_config(dev, s); + + return 0; +} + +/** + * subdev_8255_init - initialize DIO subdevice for driving I/O mapped 8255 + * @dev: comedi device owning subdevice + * @s: comedi subdevice to initialize + * @io: (optional) register I/O call-back function + * @regbase: offset of 8255 registers from dev->iobase, or call-back context + * + * Initializes a comedi subdevice as a DIO subdevice driving an 8255 chip. + * + * If the optional I/O call-back function is provided, its prototype is of + * the following form: + * + * int my_8255_callback(struct comedi_device *dev, int dir, int port, + * int data, unsigned long regbase); + * + * where 'dev', and 'regbase' match the values passed to this function, + * 'port' is the 8255 port number 0 to 3 (including the control port), 'dir' + * is the direction (0 for read, 1 for write) and 'data' is the value to be + * written. It should return 0 if writing or the value read if reading. + * + * If the optional I/O call-back function is not provided, an internal + * call-back function is used which uses consecutive I/O port addresses + * starting at dev->iobase + regbase. + * + * Return: -ENOMEM if failed to allocate memory, zero on success. + */ +int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, + int (*io)(struct comedi_device *dev, int dir, int port, + int data, unsigned long regbase), + unsigned long regbase) +{ + return __subdev_8255_init(dev, s, io, regbase, false); +} +EXPORT_SYMBOL_GPL(subdev_8255_init); + +/** + * subdev_8255_mm_init - initialize DIO subdevice for driving mmio-mapped 8255 + * @dev: comedi device owning subdevice + * @s: comedi subdevice to initialize + * @io: (optional) register I/O call-back function + * @regbase: offset of 8255 registers from dev->mmio, or call-back context + * + * Initializes a comedi subdevice as a DIO subdevice driving an 8255 chip. + * + * If the optional I/O call-back function is provided, its prototype is of + * the following form: + * + * int my_8255_callback(struct comedi_device *dev, int dir, int port, + * int data, unsigned long regbase); + * + * where 'dev', and 'regbase' match the values passed to this function, + * 'port' is the 8255 port number 0 to 3 (including the control port), 'dir' + * is the direction (0 for read, 1 for write) and 'data' is the value to be + * written. It should return 0 if writing or the value read if reading. + * + * If the optional I/O call-back function is not provided, an internal + * call-back function is used which uses consecutive MMIO virtual addresses + * starting at dev->mmio + regbase. + * + * Return: -ENOMEM if failed to allocate memory, zero on success. + */ +int subdev_8255_mm_init(struct comedi_device *dev, struct comedi_subdevice *s, + int (*io)(struct comedi_device *dev, int dir, int port, + int data, unsigned long regbase), + unsigned long regbase) +{ + return __subdev_8255_init(dev, s, io, regbase, true); +} +EXPORT_SYMBOL_GPL(subdev_8255_mm_init); + +/** + * subdev_8255_regbase - get offset of 8255 registers or call-back context + * @s: comedi subdevice + * + * Returns the 'regbase' parameter that was previously passed to to + * subdev_8255_init() or subdev_8255_mm_init() to set up the subdevice. + * Only valid if the subdevice was set up successfully. + */ +unsigned long subdev_8255_regbase(struct comedi_subdevice *s) +{ + struct subdev_8255_private *spriv = s->private; + + return spriv->regbase; +} +EXPORT_SYMBOL_GPL(subdev_8255_regbase); + +static int __init comedi_8255_module_init(void) +{ + return 0; +} +module_init(comedi_8255_module_init); + +static void __exit comedi_8255_module_exit(void) +{ +} +module_exit(comedi_8255_module_exit); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi: Generic 8255 digital I/O support"); +MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/staging/comedi/drivers/comedi_bond.c b/kernel/drivers/staging/comedi/drivers/comedi_bond.c index 96db0c268..50b76eccb 100644 --- a/kernel/drivers/staging/comedi/drivers/comedi_bond.c +++ b/kernel/drivers/staging/comedi/drivers/comedi_bond.c @@ -101,7 +101,8 @@ static int bonding_dio_insn_bits(struct comedi_device *dev, b_chans = bdev->nchans - base_chan; if (b_chans > n_left) b_chans = n_left; - b_mask = (1U << b_chans) - 1; + b_mask = (b_chans < 32) ? ((1 << b_chans) - 1) + : 0xffffffff; b_write_mask = (write_mask >> n_done) & b_mask; b_data_bits = (data_bits >> n_done) & b_mask; /* Read/Write the new digital lines. */ diff --git a/kernel/drivers/staging/comedi/drivers/comedi_isadma.h b/kernel/drivers/staging/comedi/drivers/comedi_isadma.h index c7c524faf..2fb6573ba 100644 --- a/kernel/drivers/staging/comedi/drivers/comedi_isadma.h +++ b/kernel/drivers/staging/comedi/drivers/comedi_isadma.h @@ -16,6 +16,10 @@ #ifndef _COMEDI_ISADMA_H #define _COMEDI_ISADMA_H +#include <linux/types.h> + +struct comedi_device; + /* * These are used to avoid issues when <asm/dma.h> and the DMA_MODE_ * defines are not available. diff --git a/kernel/drivers/staging/comedi/drivers/comedi_test.c b/kernel/drivers/staging/comedi/drivers/comedi_test.c index 80d613c0f..4ab186669 100644 --- a/kernel/drivers/staging/comedi/drivers/comedi_test.c +++ b/kernel/drivers/staging/comedi/drivers/comedi_test.c @@ -1,49 +1,49 @@ /* - comedi/drivers/comedi_test.c + * comedi/drivers/comedi_test.c + * + * Generates fake waveform signals that can be read through + * the command interface. It does _not_ read from any board; + * it just generates deterministic waveforms. + * Useful for various testing purposes. + * + * Copyright (C) 2002 Joachim Wuttke <Joachim.Wuttke@icn.siemens.de> + * Copyright (C) 2002 Frank Mori Hess <fmhess@users.sourceforge.net> + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - Generates fake waveform signals that can be read through - the command interface. It does _not_ read from any board; - it just generates deterministic waveforms. - Useful for various testing purposes. - - Copyright (C) 2002 Joachim Wuttke <Joachim.Wuttke@icn.siemens.de> - Copyright (C) 2002 Frank Mori Hess <fmhess@users.sourceforge.net> - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ /* -Driver: comedi_test -Description: generates fake waveforms -Author: Joachim Wuttke <Joachim.Wuttke@icn.siemens.de>, Frank Mori Hess - <fmhess@users.sourceforge.net>, ds -Devices: -Status: works -Updated: Sat, 16 Mar 2002 17:34:48 -0800 - -This driver is mainly for testing purposes, but can also be used to -generate sample waveforms on systems that don't have data acquisition -hardware. - -Configuration options: - [0] - Amplitude in microvolts for fake waveforms (default 1 volt) - [1] - Period in microseconds for fake waveforms (default 0.1 sec) - -Generates a sawtooth wave on channel 0, square wave on channel 1, additional -waveforms could be added to other channels (currently they return flatline -zero volts). - -*/ + * Driver: comedi_test + * Description: generates fake waveforms + * Author: Joachim Wuttke <Joachim.Wuttke@icn.siemens.de>, Frank Mori Hess + * <fmhess@users.sourceforge.net>, ds + * Devices: + * Status: works + * Updated: Sat, 16 Mar 2002 17:34:48 -0800 + * + * This driver is mainly for testing purposes, but can also be used to + * generate sample waveforms on systems that don't have data acquisition + * hardware. + * + * Configuration options: + * [0] - Amplitude in microvolts for fake waveforms (default 1 volt) + * [1] - Period in microseconds for fake waveforms (default 0.1 sec) + * + * Generates a sawtooth wave on channel 0, square wave on channel 1, additional + * waveforms could be added to other channels (currently they return flatline + * zero volts). + */ #include <linux/module.h> #include "../comedidev.h" @@ -52,30 +52,31 @@ zero volts). #include <linux/timer.h> #include <linux/ktime.h> +#include <linux/jiffies.h> #define N_CHANS 8 enum waveform_state_bits { - WAVEFORM_AI_RUNNING = 0 + WAVEFORM_AI_RUNNING, + WAVEFORM_AO_RUNNING }; /* Data unique to this driver */ struct waveform_private { - struct timer_list timer; - ktime_t last; /* time last timer interrupt occurred */ - unsigned int uvolt_amplitude; /* waveform amplitude in microvolts */ - unsigned long usec_period; /* waveform period in microseconds */ - unsigned long usec_current; /* current time (mod waveform period) */ - unsigned long usec_remainder; /* usec since last scan */ + struct timer_list ai_timer; /* timer for AI commands */ + u64 ai_convert_time; /* time of next AI conversion in usec */ + unsigned int wf_amplitude; /* waveform amplitude in microvolts */ + unsigned int wf_period; /* waveform period in microseconds */ + unsigned int wf_current; /* current time in waveform period */ unsigned long state_bits; - unsigned int scan_period; /* scan period in usec */ - unsigned int convert_period; /* conversion period in usec */ - unsigned int ao_loopbacks[N_CHANS]; + unsigned int ai_scan_period; /* AI scan period in usec */ + unsigned int ai_convert_period; /* AI conversion period in usec */ + struct timer_list ao_timer; /* timer for AO commands */ + u64 ao_last_scan_time; /* time of previous AO scan in usec */ + unsigned int ao_scan_period; /* AO scan period in usec */ + unsigned short ao_loopbacks[N_CHANS]; }; -/* 1000 nanosec in a microsec */ -static const int nano_per_micro = 1000; - /* fake analog input ranges */ static const struct comedi_lrange waveform_ai_ranges = { 2, { @@ -86,7 +87,7 @@ static const struct comedi_lrange waveform_ai_ranges = { static unsigned short fake_sawtooth(struct comedi_device *dev, unsigned int range_index, - unsigned long current_time) + unsigned int current_time) { struct waveform_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; @@ -97,21 +98,28 @@ static unsigned short fake_sawtooth(struct comedi_device *dev, u64 binary_amplitude; binary_amplitude = s->maxdata; - binary_amplitude *= devpriv->uvolt_amplitude; + binary_amplitude *= devpriv->wf_amplitude; do_div(binary_amplitude, krange->max - krange->min); - current_time %= devpriv->usec_period; value = current_time; value *= binary_amplitude * 2; - do_div(value, devpriv->usec_period); - value -= binary_amplitude; /* get rid of sawtooth's dc offset */ + do_div(value, devpriv->wf_period); + value += offset; + /* get rid of sawtooth's dc offset and clamp value */ + if (value < binary_amplitude) { + value = 0; /* negative saturation */ + } else { + value -= binary_amplitude; + if (value > s->maxdata) + value = s->maxdata; /* positive saturation */ + } - return offset + value; + return value; } static unsigned short fake_squarewave(struct comedi_device *dev, unsigned int range_index, - unsigned long current_time) + unsigned int current_time) { struct waveform_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; @@ -119,21 +127,29 @@ static unsigned short fake_squarewave(struct comedi_device *dev, u64 value; const struct comedi_krange *krange = &s->range_table->range[range_index]; - current_time %= devpriv->usec_period; value = s->maxdata; - value *= devpriv->uvolt_amplitude; + value *= devpriv->wf_amplitude; do_div(value, krange->max - krange->min); - if (current_time < devpriv->usec_period / 2) - value *= -1; + /* get one of two values for square-wave and clamp */ + if (current_time < devpriv->wf_period / 2) { + if (offset < value) + value = 0; /* negative saturation */ + else + value = offset - value; + } else { + value += offset; + if (value > s->maxdata) + value = s->maxdata; /* positive saturation */ + } - return offset + value; + return value; } static unsigned short fake_flatline(struct comedi_device *dev, unsigned int range_index, - unsigned long current_time) + unsigned int current_time) { return dev->read_subdev->maxdata / 2; } @@ -141,7 +157,7 @@ static unsigned short fake_flatline(struct comedi_device *dev, /* generates a different waveform depending on what channel is read */ static unsigned short fake_waveform(struct comedi_device *dev, unsigned int channel, unsigned int range, - unsigned long current_time) + unsigned int current_time) { enum { SAWTOOTH_CHAN, @@ -160,58 +176,62 @@ static unsigned short fake_waveform(struct comedi_device *dev, } /* - This is the background routine used to generate arbitrary data. - It should run in the background; therefore it is scheduled by - a timer mechanism. -*/ -static void waveform_ai_interrupt(unsigned long arg) + * This is the background routine used to generate arbitrary data. + * It should run in the background; therefore it is scheduled by + * a timer mechanism. + */ +static void waveform_ai_timer(unsigned long arg) { struct comedi_device *dev = (struct comedi_device *)arg; struct waveform_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; - unsigned int i, j; - /* all times in microsec */ - unsigned long elapsed_time; - unsigned int num_scans; - ktime_t now; + u64 now; + unsigned int nsamples; + unsigned int time_increment; /* check command is still active */ if (!test_bit(WAVEFORM_AI_RUNNING, &devpriv->state_bits)) return; - now = ktime_get(); - - elapsed_time = ktime_to_us(ktime_sub(now, devpriv->last)); - devpriv->last = now; - num_scans = - (devpriv->usec_remainder + elapsed_time) / devpriv->scan_period; - devpriv->usec_remainder = - (devpriv->usec_remainder + elapsed_time) % devpriv->scan_period; - - num_scans = comedi_nscans_left(s, num_scans); - for (i = 0; i < num_scans; i++) { - for (j = 0; j < cmd->chanlist_len; j++) { - unsigned short sample; - - sample = fake_waveform(dev, CR_CHAN(cmd->chanlist[j]), - CR_RANGE(cmd->chanlist[j]), - devpriv->usec_current + - i * devpriv->scan_period + - j * devpriv->convert_period); - comedi_buf_write_samples(s, &sample, 1); + now = ktime_to_us(ktime_get()); + nsamples = comedi_nsamples_left(s, UINT_MAX); + + while (nsamples && devpriv->ai_convert_time < now) { + unsigned int chanspec = cmd->chanlist[async->cur_chan]; + unsigned short sample; + + sample = fake_waveform(dev, CR_CHAN(chanspec), + CR_RANGE(chanspec), devpriv->wf_current); + if (comedi_buf_write_samples(s, &sample, 1) == 0) + goto overrun; + time_increment = devpriv->ai_convert_period; + if (async->scan_progress == 0) { + /* done last conversion in scan, so add dead time */ + time_increment += devpriv->ai_scan_period - + devpriv->ai_convert_period * + cmd->scan_end_arg; } + devpriv->wf_current += time_increment; + if (devpriv->wf_current >= devpriv->wf_period) + devpriv->wf_current %= devpriv->wf_period; + devpriv->ai_convert_time += time_increment; + nsamples--; } - devpriv->usec_current += elapsed_time; - devpriv->usec_current %= devpriv->usec_period; - - if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg) + if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg) { async->events |= COMEDI_CB_EOA; - else - mod_timer(&devpriv->timer, jiffies + 1); + } else { + if (devpriv->ai_convert_time > now) + time_increment = devpriv->ai_convert_time - now; + else + time_increment = 1; + mod_timer(&devpriv->ai_timer, + jiffies + usecs_to_jiffies(time_increment)); + } +overrun: comedi_handle_events(dev, s); } @@ -220,12 +240,13 @@ static int waveform_ai_cmdtest(struct comedi_device *dev, struct comedi_cmd *cmd) { int err = 0; - unsigned int arg; + unsigned int arg, limit; /* Step 1 : check if triggers are trivially valid */ err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER); + err |= comedi_check_trigger_src(&cmd->scan_begin_src, + TRIG_FOLLOW | TRIG_TIMER); err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW | TRIG_TIMER); err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); @@ -241,6 +262,9 @@ static int waveform_ai_cmdtest(struct comedi_device *dev, /* Step 2b : and mutually compatible */ + if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW) + err |= -EINVAL; /* scan period would be 0 */ + if (err) return 2; @@ -248,18 +272,20 @@ static int waveform_ai_cmdtest(struct comedi_device *dev, err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); - if (cmd->convert_src == TRIG_NOW) + if (cmd->convert_src == TRIG_NOW) { err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0); + } else { /* cmd->convert_src == TRIG_TIMER */ + if (cmd->scan_begin_src == TRIG_FOLLOW) { + err |= comedi_check_trigger_arg_min(&cmd->convert_arg, + NSEC_PER_USEC); + } + } - if (cmd->scan_begin_src == TRIG_TIMER) { + if (cmd->scan_begin_src == TRIG_FOLLOW) { + err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0); + } else { /* cmd->scan_begin_src == TRIG_TIMER */ err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, - nano_per_micro); - if (cmd->convert_src == TRIG_TIMER) { - err |= comedi_check_trigger_arg_min(&cmd-> - scan_begin_arg, - cmd->convert_arg * - cmd->chanlist_len); - } + NSEC_PER_USEC); } err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1); @@ -268,7 +294,7 @@ static int waveform_ai_cmdtest(struct comedi_device *dev, if (cmd->stop_src == TRIG_COUNT) err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1); - else /* TRIG_NONE */ + else /* cmd->stop_src == TRIG_NONE */ err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); if (err) @@ -276,21 +302,34 @@ static int waveform_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ - if (cmd->scan_begin_src == TRIG_TIMER) { - arg = cmd->scan_begin_arg; - /* round to nearest microsec */ - arg = nano_per_micro * - ((arg + (nano_per_micro / 2)) / nano_per_micro); - err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg); - } if (cmd->convert_src == TRIG_TIMER) { + /* round convert_arg to nearest microsecond */ arg = cmd->convert_arg; - /* round to nearest microsec */ - arg = nano_per_micro * - ((arg + (nano_per_micro / 2)) / nano_per_micro); + arg = min(arg, + rounddown(UINT_MAX, (unsigned int)NSEC_PER_USEC)); + arg = NSEC_PER_USEC * DIV_ROUND_CLOSEST(arg, NSEC_PER_USEC); + if (cmd->scan_begin_arg == TRIG_TIMER) { + /* limit convert_arg to keep scan_begin_arg in range */ + limit = UINT_MAX / cmd->scan_end_arg; + limit = rounddown(limit, (unsigned int)NSEC_PER_SEC); + arg = min(arg, limit); + } err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg); } + if (cmd->scan_begin_src == TRIG_TIMER) { + /* round scan_begin_arg to nearest microsecond */ + arg = cmd->scan_begin_arg; + arg = min(arg, + rounddown(UINT_MAX, (unsigned int)NSEC_PER_USEC)); + arg = NSEC_PER_USEC * DIV_ROUND_CLOSEST(arg, NSEC_PER_USEC); + if (cmd->convert_src == TRIG_TIMER) { + /* but ensure scan_begin_arg is large enough */ + arg = max(arg, cmd->convert_arg * cmd->scan_end_arg); + } + err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg); + } + if (err) return 4; @@ -302,6 +341,8 @@ static int waveform_ai_cmd(struct comedi_device *dev, { struct waveform_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; + unsigned int first_convert_time; + u64 wf_current; if (cmd->flags & CMDF_PRIORITY) { dev_err(dev->class_dev, @@ -309,24 +350,48 @@ static int waveform_ai_cmd(struct comedi_device *dev, return -1; } - devpriv->scan_period = cmd->scan_begin_arg / nano_per_micro; - if (cmd->convert_src == TRIG_NOW) - devpriv->convert_period = 0; - else /* TRIG_TIMER */ - devpriv->convert_period = cmd->convert_arg / nano_per_micro; + devpriv->ai_convert_period = 0; + else /* cmd->convert_src == TRIG_TIMER */ + devpriv->ai_convert_period = cmd->convert_arg / NSEC_PER_USEC; + + if (cmd->scan_begin_src == TRIG_FOLLOW) { + devpriv->ai_scan_period = devpriv->ai_convert_period * + cmd->scan_end_arg; + } else { /* cmd->scan_begin_src == TRIG_TIMER */ + devpriv->ai_scan_period = cmd->scan_begin_arg / NSEC_PER_USEC; + } - devpriv->last = ktime_get(); - devpriv->usec_current = - ((u32)ktime_to_us(devpriv->last)) % devpriv->usec_period; - devpriv->usec_remainder = 0; + /* + * Simulate first conversion to occur at convert period after + * conversion timer starts. If scan_begin_src is TRIG_FOLLOW, assume + * the conversion timer starts immediately. If scan_begin_src is + * TRIG_TIMER, assume the conversion timer starts after the scan + * period. + */ + first_convert_time = devpriv->ai_convert_period; + if (cmd->scan_begin_src == TRIG_TIMER) + first_convert_time += devpriv->ai_scan_period; + devpriv->ai_convert_time = ktime_to_us(ktime_get()) + + first_convert_time; + + /* Determine time within waveform period at time of conversion. */ + wf_current = devpriv->ai_convert_time; + devpriv->wf_current = do_div(wf_current, devpriv->wf_period); + + /* + * Schedule timer to expire just after first conversion time. + * Seem to need an extra jiffy here, otherwise timer expires slightly + * early! + */ + devpriv->ai_timer.expires = + jiffies + usecs_to_jiffies(devpriv->ai_convert_period) + 1; - devpriv->timer.expires = jiffies + 1; /* mark command as active */ smp_mb__before_atomic(); set_bit(WAVEFORM_AI_RUNNING, &devpriv->state_bits); smp_mb__after_atomic(); - add_timer(&devpriv->timer); + add_timer(&devpriv->ai_timer); return 0; } @@ -339,7 +404,7 @@ static int waveform_ai_cancel(struct comedi_device *dev, clear_bit(WAVEFORM_AI_RUNNING, &devpriv->state_bits); smp_mb__after_atomic(); /* cannot call del_timer_sync() as may be called from timer routine */ - del_timer(&devpriv->timer); + del_timer(&devpriv->ai_timer); return 0; } @@ -356,6 +421,201 @@ static int waveform_ai_insn_read(struct comedi_device *dev, return insn->n; } +/* + * This is the background routine to handle AO commands, scheduled by + * a timer mechanism. + */ +static void waveform_ao_timer(unsigned long arg) +{ + struct comedi_device *dev = (struct comedi_device *)arg; + struct waveform_private *devpriv = dev->private; + struct comedi_subdevice *s = dev->write_subdev; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + u64 now; + u64 scans_since; + unsigned int scans_avail = 0; + + /* check command is still active */ + if (!test_bit(WAVEFORM_AO_RUNNING, &devpriv->state_bits)) + return; + + /* determine number of scan periods since last time */ + now = ktime_to_us(ktime_get()); + scans_since = now - devpriv->ao_last_scan_time; + do_div(scans_since, devpriv->ao_scan_period); + if (scans_since) { + unsigned int i; + + /* determine scans in buffer, limit to scans to do this time */ + scans_avail = comedi_nscans_left(s, 0); + if (scans_avail > scans_since) + scans_avail = scans_since; + if (scans_avail) { + /* skip all but the last scan to save processing time */ + if (scans_avail > 1) { + unsigned int skip_bytes, nbytes; + + skip_bytes = + comedi_samples_to_bytes(s, cmd->scan_end_arg * + (scans_avail - 1)); + nbytes = comedi_buf_read_alloc(s, skip_bytes); + comedi_buf_read_free(s, nbytes); + comedi_inc_scan_progress(s, nbytes); + if (nbytes < skip_bytes) { + /* unexpected underrun! (cancelled?) */ + async->events |= COMEDI_CB_OVERFLOW; + goto underrun; + } + } + /* output the last scan */ + for (i = 0; i < cmd->scan_end_arg; i++) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); + + if (comedi_buf_read_samples(s, + &devpriv-> + ao_loopbacks[chan], + 1) == 0) { + /* unexpected underrun! (cancelled?) */ + async->events |= COMEDI_CB_OVERFLOW; + goto underrun; + } + } + /* advance time of last scan */ + devpriv->ao_last_scan_time += + (u64)scans_avail * devpriv->ao_scan_period; + } + } + if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg) { + async->events |= COMEDI_CB_EOA; + } else if (scans_avail < scans_since) { + async->events |= COMEDI_CB_OVERFLOW; + } else { + unsigned int time_inc = devpriv->ao_last_scan_time + + devpriv->ao_scan_period - now; + + mod_timer(&devpriv->ao_timer, + jiffies + usecs_to_jiffies(time_inc)); + } + +underrun: + comedi_handle_events(dev, s); +} + +static int waveform_ao_inttrig_start(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int trig_num) +{ + struct waveform_private *devpriv = dev->private; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + + if (trig_num != cmd->start_arg) + return -EINVAL; + + async->inttrig = NULL; + + devpriv->ao_last_scan_time = ktime_to_us(ktime_get()); + devpriv->ao_timer.expires = + jiffies + usecs_to_jiffies(devpriv->ao_scan_period); + + /* mark command as active */ + smp_mb__before_atomic(); + set_bit(WAVEFORM_AO_RUNNING, &devpriv->state_bits); + smp_mb__after_atomic(); + add_timer(&devpriv->ao_timer); + + return 1; +} + +static int waveform_ao_cmdtest(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + int err = 0; + unsigned int arg; + + /* Step 1 : check if triggers are trivially valid */ + + err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT); + err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER); + err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW); + err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); + err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + + if (err) + return 1; + + /* Step 2a : make sure trigger sources are unique */ + + err |= comedi_check_trigger_is_unique(cmd->stop_src); + + /* Step 2b : and mutually compatible */ + + if (err) + return 2; + + /* Step 3: check if arguments are trivially valid */ + + err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, + NSEC_PER_USEC); + err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0); + err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1); + err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, + cmd->chanlist_len); + if (cmd->stop_src == TRIG_COUNT) + err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1); + else /* cmd->stop_src == TRIG_NONE */ + err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + /* round scan_begin_arg to nearest microsecond */ + arg = cmd->scan_begin_arg; + arg = min(arg, rounddown(UINT_MAX, (unsigned int)NSEC_PER_USEC)); + arg = NSEC_PER_USEC * DIV_ROUND_CLOSEST(arg, NSEC_PER_USEC); + err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg); + + if (err) + return 4; + + return 0; +} + +static int waveform_ao_cmd(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct waveform_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; + + if (cmd->flags & CMDF_PRIORITY) { + dev_err(dev->class_dev, + "commands at RT priority not supported in this driver\n"); + return -1; + } + + devpriv->ao_scan_period = cmd->scan_begin_arg / NSEC_PER_USEC; + s->async->inttrig = waveform_ao_inttrig_start; + return 0; +} + +static int waveform_ao_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct waveform_private *devpriv = dev->private; + + s->async->inttrig = NULL; + /* mark command as no longer active */ + clear_bit(WAVEFORM_AO_RUNNING, &devpriv->state_bits); + smp_mb__after_atomic(); + /* cannot call del_timer_sync() as may be called from timer routine */ + del_timer(&devpriv->ao_timer); + return 0; +} + static int waveform_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -389,8 +649,8 @@ static int waveform_attach(struct comedi_device *dev, if (period <= 0) period = 100000; /* 0.1 sec */ - devpriv->uvolt_amplitude = amplitude; - devpriv->usec_period = period; + devpriv->wf_amplitude = amplitude; + devpriv->wf_period = period; ret = comedi_alloc_subdevices(dev, 2); if (ret) @@ -414,23 +674,28 @@ static int waveform_attach(struct comedi_device *dev, dev->write_subdev = s; /* analog output subdevice (loopback) */ s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE | SDF_GROUND; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; s->n_chan = N_CHANS; s->maxdata = 0xffff; s->range_table = &waveform_ai_ranges; + s->len_chanlist = s->n_chan; s->insn_write = waveform_ao_insn_write; + s->insn_read = waveform_ai_insn_read; /* do same as AI insn_read */ + s->do_cmd = waveform_ao_cmd; + s->do_cmdtest = waveform_ao_cmdtest; + s->cancel = waveform_ao_cancel; /* Our default loopback value is just a 0V flatline */ for (i = 0; i < s->n_chan; i++) devpriv->ao_loopbacks[i] = s->maxdata / 2; - setup_timer(&devpriv->timer, waveform_ai_interrupt, - (unsigned long)dev); + setup_timer(&devpriv->ai_timer, waveform_ai_timer, (unsigned long)dev); + setup_timer(&devpriv->ao_timer, waveform_ao_timer, (unsigned long)dev); dev_info(dev->class_dev, - "%s: %i microvolt, %li microsecond waveform attached\n", + "%s: %u microvolt, %u microsecond waveform attached\n", dev->board_name, - devpriv->uvolt_amplitude, devpriv->usec_period); + devpriv->wf_amplitude, devpriv->wf_period); return 0; } @@ -439,8 +704,10 @@ static void waveform_detach(struct comedi_device *dev) { struct waveform_private *devpriv = dev->private; - if (devpriv) - del_timer_sync(&devpriv->timer); + if (devpriv) { + del_timer_sync(&devpriv->ai_timer); + del_timer_sync(&devpriv->ao_timer); + } } static struct comedi_driver waveform_driver = { diff --git a/kernel/drivers/staging/comedi/drivers/dac02.c b/kernel/drivers/staging/comedi/drivers/dac02.c index a6798ad8f..a562df498 100644 --- a/kernel/drivers/staging/comedi/drivers/dac02.c +++ b/kernel/drivers/staging/comedi/drivers/dac02.c @@ -130,11 +130,7 @@ static int dac02_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->range_table = &das02_ao_ranges; s->insn_write = dac02_ao_insn_write; - ret = comedi_alloc_subdev_readback(s); - if (ret) - return ret; - - return 0; + return comedi_alloc_subdev_readback(s); } static struct comedi_driver dac02_driver = { diff --git a/kernel/drivers/staging/comedi/drivers/daqboard2000.c b/kernel/drivers/staging/comedi/drivers/daqboard2000.c index f97d18d92..57ab6680e 100644 --- a/kernel/drivers/staging/comedi/drivers/daqboard2000.c +++ b/kernel/drivers/staging/comedi/drivers/daqboard2000.c @@ -1,105 +1,105 @@ /* - comedi/drivers/daqboard2000.c - hardware driver for IOtech DAQboard/2000 - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + * comedi/drivers/daqboard2000.c + * hardware driver for IOtech DAQboard/2000 + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. */ /* -Driver: daqboard2000 -Description: IOTech DAQBoard/2000 -Author: Anders Blomdell <anders.blomdell@control.lth.se> -Status: works -Updated: Mon, 14 Apr 2008 15:28:52 +0100 -Devices: [IOTech] DAQBoard/2000 (daqboard2000) - -Much of the functionality of this driver was determined from reading -the source code for the Windows driver. - -The FPGA on the board requires fimware, which is available from -http://www.comedi.org in the comedi_nonfree_firmware tarball. - -Configuration options: not applicable, uses PCI auto config -*/ + * Driver: daqboard2000 + * Description: IOTech DAQBoard/2000 + * Author: Anders Blomdell <anders.blomdell@control.lth.se> + * Status: works + * Updated: Mon, 14 Apr 2008 15:28:52 +0100 + * Devices: [IOTech] DAQBoard/2000 (daqboard2000) + * + * Much of the functionality of this driver was determined from reading + * the source code for the Windows driver. + * + * The FPGA on the board requires fimware, which is available from + * http://www.comedi.org in the comedi_nonfree_firmware tarball. + * + * Configuration options: not applicable, uses PCI auto config + */ /* - This card was obviously never intended to leave the Windows world, - since it lacked all kind of hardware documentation (except for cable - pinouts, plug and pray has something to catch up with yet). - - With some help from our swedish distributor, we got the Windows sourcecode - for the card, and here are the findings so far. - - 1. A good document that describes the PCI interface chip is 9080db-106.pdf - available from http://www.plxtech.com/products/io/pci9080 - - 2. The initialization done so far is: - a. program the FPGA (windows code sans a lot of error messages) - b. - - 3. Analog out seems to work OK with DAC's disabled, if DAC's are enabled, - you have to output values to all enabled DAC's until result appears, I - guess that it has something to do with pacer clocks, but the source - gives me no clues. I'll keep it simple so far. - - 4. Analog in. - Each channel in the scanlist seems to be controlled by four - control words: - - Word0: - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! | | | ! | | | ! | | | ! | | | ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Word1: - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! | | | ! | | | ! | | | ! | | | ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | | | | | | - +------+------+ | | | | +-- Digital input (??) - | | | | +---- 10 us settling time - | | | +------ Suspend acquisition (last to scan) - | | +-------- Simultaneous sample and hold - | +---------- Signed data format - +------------------------- Correction offset low - - Word2: - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! | | | ! | | | ! | | | ! | | | ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | | | | | | | | | - +-----+ +--+--+ +++ +++ +--+--+ - | | | | +----- Expansion channel - | | | +----------- Expansion gain - | | +--------------- Channel (low) - | +--------------------- Correction offset high - +----------------------------- Correction gain low - Word3: - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! | | | ! | | | ! | | | ! | | | ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | | | | | | | | - +------+------+ | | +-+-+ | | +-- Low bank enable - | | | | | +---- High bank enable - | | | | +------ Hi/low select - | | | +---------- Gain (1,?,2,4,8,16,32,64) - | | +-------------- differential/single ended - | +---------------- Unipolar - +------------------------- Correction gain high - - 999. The card seems to have an incredible amount of capabilities, but - trying to reverse engineer them from the Windows source is beyond my - patience. - + * This card was obviously never intended to leave the Windows world, + * since it lacked all kind of hardware documentation (except for cable + * pinouts, plug and pray has something to catch up with yet). + * + * With some help from our swedish distributor, we got the Windows sourcecode + * for the card, and here are the findings so far. + * + * 1. A good document that describes the PCI interface chip is 9080db-106.pdf + * available from http://www.plxtech.com/products/io/pci9080 + * + * 2. The initialization done so far is: + * a. program the FPGA (windows code sans a lot of error messages) + * b. + * + * 3. Analog out seems to work OK with DAC's disabled, if DAC's are enabled, + * you have to output values to all enabled DAC's until result appears, I + * guess that it has something to do with pacer clocks, but the source + * gives me no clues. I'll keep it simple so far. + * + * 4. Analog in. + * Each channel in the scanlist seems to be controlled by four + * control words: + * + * Word0: + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * ! | | | ! | | | ! | | | ! | | | ! + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Word1: + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * ! | | | ! | | | ! | | | ! | | | ! + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | | | | | + * +------+------+ | | | | +-- Digital input (??) + * | | | | +---- 10 us settling time + * | | | +------ Suspend acquisition (last to scan) + * | | +-------- Simultaneous sample and hold + * | +---------- Signed data format + * +------------------------- Correction offset low + * + * Word2: + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * ! | | | ! | | | ! | | | ! | | | ! + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | | | | | | | | + * +-----+ +--+--+ +++ +++ +--+--+ + * | | | | +----- Expansion channel + * | | | +----------- Expansion gain + * | | +--------------- Channel (low) + * | +--------------------- Correction offset high + * +----------------------------- Correction gain low + * Word3: + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * ! | | | ! | | | ! | | | ! | | | ! + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | | | | | | | + * +------+------+ | | +-+-+ | | +-- Low bank enable + * | | | | | +---- High bank enable + * | | | | +------ Hi/low select + * | | | +---------- Gain (1,?,2,4,8,16,32,64) + * | | +-------------- differential/single ended + * | +---------------- Unipolar + * +------------------------- Correction gain high + * + * 999. The card seems to have an incredible amount of capabilities, but + * trying to reverse engineer them from the Windows source is beyond my + * patience. + * */ #include <linux/module.h> @@ -713,12 +713,8 @@ static int daqboard2000_auto_attach(struct comedi_device *dev, return result; s = &dev->subdevices[2]; - result = subdev_8255_init(dev, s, daqboard2000_8255_cb, - dioP2ExpansionIO8Bit); - if (result) - return result; - - return 0; + return subdev_8255_init(dev, s, daqboard2000_8255_cb, + dioP2ExpansionIO8Bit); } static void daqboard2000_detach(struct comedi_device *dev) diff --git a/kernel/drivers/staging/comedi/drivers/das08.c b/kernel/drivers/staging/comedi/drivers/das08.c index 73f4c8dbb..3d8fc6ad4 100644 --- a/kernel/drivers/staging/comedi/drivers/das08.c +++ b/kernel/drivers/staging/comedi/drivers/das08.c @@ -1,21 +1,21 @@ /* - * comedi/drivers/das08.c - * comedi module for common DAS08 support (used by ISA/PCI/PCMCIA drivers) + * comedi/drivers/das08.c + * comedi module for common DAS08 support (used by ISA/PCI/PCMCIA drivers) * - * COMEDI - Linux Control and Measurement Device Interface - * Copyright (C) 2000 David A. Schleef <ds@schleef.org> - * Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net> - * Copyright (C) 2004 Salvador E. Tropea <set@users.sf.net> <set@ieee.org> + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef <ds@schleef.org> + * Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net> + * Copyright (C) 2004 Salvador E. Tropea <set@users.sf.net> <set@ieee.org> * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. */ #include <linux/module.h> @@ -27,85 +27,74 @@ #include "das08.h" /* - cio-das08.pdf - - "isa-das08" - - 0 a/d bits 0-3 start 8 bit - 1 a/d bits 4-11 start 12 bit - 2 eoc, ip1-3, irq, mux op1-4, inte, mux - 3 unused unused - 4567 8254 - 89ab 8255 - - requires hard-wiring for async ai - -*/ - -#define DAS08_LSB 0 -#define DAS08_MSB 1 -#define DAS08_TRIG_12BIT 1 -#define DAS08_STATUS 2 -#define DAS08_EOC (1<<7) -#define DAS08_IRQ (1<<3) -#define DAS08_IP(x) (((x)>>4)&0x7) -#define DAS08_CONTROL 2 -#define DAS08_MUX_MASK 0x7 -#define DAS08_MUX(x) ((x) & DAS08_MUX_MASK) -#define DAS08_INTE (1<<3) -#define DAS08_DO_MASK 0xf0 -#define DAS08_OP(x) (((x) << 4) & DAS08_DO_MASK) - + * Data format of DAS08_AI_LSB_REG and DAS08_AI_MSB_REG depends on + * 'ai_encoding' member of board structure: + * + * das08_encode12 : DATA[11..4] = MSB[7..0], DATA[3..0] = LSB[7..4]. + * das08_pcm_encode12 : DATA[11..8] = MSB[3..0], DATA[7..9] = LSB[7..0]. + * das08_encode16 : SIGN = MSB[7], MAGNITUDE[14..8] = MSB[6..0], + * MAGNITUDE[7..0] = LSB[7..0]. + * SIGN==0 for negative input, SIGN==1 for positive input. + * Note: when read a second time after conversion + * complete, MSB[7] is an "over-range" bit. + */ +#define DAS08_AI_LSB_REG 0x00 /* (R) AI least significant bits */ +#define DAS08_AI_MSB_REG 0x01 /* (R) AI most significant bits */ +#define DAS08_AI_TRIG_REG 0x01 /* (W) AI software trigger */ +#define DAS08_STATUS_REG 0x02 /* (R) status */ +#define DAS08_STATUS_AI_BUSY BIT(7) /* AI conversion in progress */ /* - cio-das08jr.pdf - - "das08/jr-ao" - - 0 a/d bits 0-3 unused - 1 a/d bits 4-11 start 12 bit - 2 eoc, mux mux - 3 di do - 4 unused ao0_lsb - 5 unused ao0_msb - 6 unused ao1_lsb - 7 unused ao1_msb - -*/ - -#define DAS08JR_DIO 3 -#define DAS08JR_AO_LSB(x) ((x) ? 6 : 4) -#define DAS08JR_AO_MSB(x) ((x) ? 7 : 5) + * The IRQ status bit is set to 1 by a rising edge on the external interrupt + * input (which may be jumpered to the pacer output). It is cleared by + * setting the INTE control bit to 0. Not present on "JR" boards. + */ +#define DAS08_STATUS_IRQ BIT(3) /* latched interrupt input */ +/* digital inputs (not "JR" boards) */ +#define DAS08_STATUS_DI(x) (((x) & 0x70) >> 4) +#define DAS08_CONTROL_REG 0x02 /* (W) control */ +/* + * Note: The AI multiplexor channel can also be read from status register using + * the same mask. + */ +#define DAS08_CONTROL_MUX_MASK 0x7 /* multiplexor channel mask */ +#define DAS08_CONTROL_MUX(x) ((x) & DAS08_CONTROL_MUX_MASK) /* mux channel */ +#define DAS08_CONTROL_INTE BIT(3) /* interrupt enable (not "JR" boards) */ +#define DAS08_CONTROL_DO_MASK 0xf0 /* digital outputs mask (not "JR") */ +/* digital outputs (not "JR" boards) */ +#define DAS08_CONTROL_DO(x) (((x) << 4) & DAS08_CONTROL_DO_MASK) +/* + * (R/W) programmable AI gain ("PGx" and "AOx" boards): + * + bits 3..0 (R/W) show/set the gain for the current AI mux channel + * + bits 6..4 (R) show the current AI mux channel + * + bit 7 (R) not unused + */ +#define DAS08_GAIN_REG 0x03 + +#define DAS08JR_DI_REG 0x03 /* (R) digital inputs ("JR" boards) */ +#define DAS08JR_DO_REG 0x03 /* (W) digital outputs ("JR" boards) */ +/* (W) analog output l.s.b. registers for 2 channels ("JR" boards) */ +#define DAS08JR_AO_LSB_REG(x) ((x) ? 0x06 : 0x04) +/* (W) analog output m.s.b. registers for 2 channels ("JR" boards) */ +#define DAS08JR_AO_MSB_REG(x) ((x) ? 0x07 : 0x05) +/* + * (R) update analog outputs ("JR" boards set for simultaneous output) + * (same register as digital inputs) + */ +#define DAS08JR_AO_UPDATE_REG 0x03 +/* (W) analog output l.s.b. registers for 2 channels ("AOx" boards) */ +#define DAS08AOX_AO_LSB_REG(x) ((x) ? 0x0a : 0x08) +/* (W) analog output m.s.b. registers for 2 channels ("AOx" boards) */ +#define DAS08AOX_AO_MSB_REG(x) ((x) ? 0x0b : 0x09) /* - cio-das08_aox.pdf - - "das08-aoh" - "das08-aol" - "das08-aom" - - 0 a/d bits 0-3 start 8 bit - 1 a/d bits 4-11 start 12 bit - 2 eoc, ip1-3, irq, mux op1-4, inte, mux - 3 mux, gain status gain control - 4567 8254 - 8 unused ao0_lsb - 9 unused ao0_msb - a unused ao1_lsb - b unused ao1_msb - 89ab - cdef 8255 -*/ - -#define DAS08AO_GAIN_CONTROL 3 -#define DAS08AO_GAIN_STATUS 3 - -#define DAS08AO_AO_LSB(x) ((x) ? 0xa : 8) -#define DAS08AO_AO_MSB(x) ((x) ? 0xb : 9) -#define DAS08AO_AO_UPDATE 8 + * (R) update analog outputs ("AOx" boards set for simultaneous output) + * (any of the analog output registers could be used for this) + */ +#define DAS08AOX_AO_UPDATE_REG 0x08 /* gainlist same as _pgx_ below */ -static const struct comedi_lrange range_das08_pgl = { +static const struct comedi_lrange das08_pgl_ai_range = { 9, { BIP_RANGE(10), BIP_RANGE(5), @@ -119,7 +108,7 @@ static const struct comedi_lrange range_das08_pgl = { } }; -static const struct comedi_lrange range_das08_pgh = { +static const struct comedi_lrange das08_pgh_ai_range = { 12, { BIP_RANGE(10), BIP_RANGE(5), @@ -136,7 +125,7 @@ static const struct comedi_lrange range_das08_pgh = { } }; -static const struct comedi_lrange range_das08_pgm = { +static const struct comedi_lrange das08_pgm_ai_range = { 9, { BIP_RANGE(10), BIP_RANGE(5), @@ -148,42 +137,28 @@ static const struct comedi_lrange range_das08_pgm = { UNI_RANGE(0.1), UNI_RANGE(0.01) } -}; /* - cio-das08jr.pdf - - "das08/jr-ao" - - 0 a/d bits 0-3 unused - 1 a/d bits 4-11 start 12 bit - 2 eoc, mux mux - 3 di do - 4 unused ao0_lsb - 5 unused ao0_msb - 6 unused ao1_lsb - 7 unused ao1_msb - - */ +}; static const struct comedi_lrange *const das08_ai_lranges[] = { - &range_unknown, - &range_bipolar5, - &range_das08_pgh, - &range_das08_pgl, - &range_das08_pgm, + [das08_pg_none] = &range_unknown, + [das08_bipolar5] = &range_bipolar5, + [das08_pgh] = &das08_pgh_ai_range, + [das08_pgl] = &das08_pgl_ai_range, + [das08_pgm] = &das08_pgm_ai_range, }; -static const int das08_pgh_gainlist[] = { +static const int das08_pgh_ai_gainlist[] = { 8, 0, 10, 2, 12, 4, 14, 6, 1, 3, 5, 7 }; -static const int das08_pgl_gainlist[] = { 8, 0, 2, 4, 6, 1, 3, 5, 7 }; -static const int das08_pgm_gainlist[] = { 8, 0, 10, 12, 14, 9, 11, 13, 15 }; - -static const int *const das08_gainlists[] = { - NULL, - NULL, - das08_pgh_gainlist, - das08_pgl_gainlist, - das08_pgm_gainlist, +static const int das08_pgl_ai_gainlist[] = { 8, 0, 2, 4, 6, 1, 3, 5, 7 }; +static const int das08_pgm_ai_gainlist[] = { 8, 0, 10, 12, 14, 9, 11, 13, 15 }; + +static const int *const das08_ai_gainlists[] = { + [das08_pg_none] = NULL, + [das08_bipolar5] = NULL, + [das08_pgh] = das08_pgh_ai_gainlist, + [das08_pgl] = das08_pgl_ai_gainlist, + [das08_pgm] = das08_pgm_ai_gainlist, }; static int das08_ai_eoc(struct comedi_device *dev, @@ -193,16 +168,17 @@ static int das08_ai_eoc(struct comedi_device *dev, { unsigned int status; - status = inb(dev->iobase + DAS08_STATUS); - if ((status & DAS08_EOC) == 0) + status = inb(dev->iobase + DAS08_STATUS_REG); + if ((status & DAS08_STATUS_AI_BUSY) == 0) return 0; return -EBUSY; } -static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int das08_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { - const struct das08_board_struct *thisboard = dev->board_ptr; + const struct das08_board_struct *board = dev->board_ptr; struct das08_private_struct *devpriv = dev->private; int n; int chan; @@ -214,49 +190,64 @@ static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, range = CR_RANGE(insn->chanspec); /* clear crap */ - inb(dev->iobase + DAS08_LSB); - inb(dev->iobase + DAS08_MSB); + inb(dev->iobase + DAS08_AI_LSB_REG); + inb(dev->iobase + DAS08_AI_MSB_REG); /* set multiplexer */ - /* lock to prevent race with digital output */ + /* lock to prevent race with digital output */ spin_lock(&dev->spinlock); - devpriv->do_mux_bits &= ~DAS08_MUX_MASK; - devpriv->do_mux_bits |= DAS08_MUX(chan); - outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL); + devpriv->do_mux_bits &= ~DAS08_CONTROL_MUX_MASK; + devpriv->do_mux_bits |= DAS08_CONTROL_MUX(chan); + outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL_REG); spin_unlock(&dev->spinlock); - if (s->range_table->length > 1) { + if (devpriv->pg_gainlist) { /* set gain/range */ range = CR_RANGE(insn->chanspec); outb(devpriv->pg_gainlist[range], - dev->iobase + DAS08AO_GAIN_CONTROL); + dev->iobase + DAS08_GAIN_REG); } for (n = 0; n < insn->n; n++) { /* clear over-range bits for 16-bit boards */ - if (thisboard->ai_nbits == 16) - if (inb(dev->iobase + DAS08_MSB) & 0x80) + if (board->ai_nbits == 16) + if (inb(dev->iobase + DAS08_AI_MSB_REG) & 0x80) dev_info(dev->class_dev, "over-range\n"); /* trigger conversion */ - outb_p(0, dev->iobase + DAS08_TRIG_12BIT); + outb_p(0, dev->iobase + DAS08_AI_TRIG_REG); ret = comedi_timeout(dev, s, insn, das08_ai_eoc, 0); if (ret) return ret; - msb = inb(dev->iobase + DAS08_MSB); - lsb = inb(dev->iobase + DAS08_LSB); - if (thisboard->ai_encoding == das08_encode12) { + msb = inb(dev->iobase + DAS08_AI_MSB_REG); + lsb = inb(dev->iobase + DAS08_AI_LSB_REG); + if (board->ai_encoding == das08_encode12) { data[n] = (lsb >> 4) | (msb << 4); - } else if (thisboard->ai_encoding == das08_pcm_encode12) { + } else if (board->ai_encoding == das08_pcm_encode12) { data[n] = (msb << 8) + lsb; - } else if (thisboard->ai_encoding == das08_encode16) { - /* FPOS 16-bit boards are sign-magnitude */ + } else if (board->ai_encoding == das08_encode16) { + /* + * "JR" 16-bit boards are sign-magnitude. + * + * XXX The manual seems to imply that 0 is full-scale + * negative and 65535 is full-scale positive, but the + * original COMEDI patch to add support for the + * DAS08/JR/16 and DAS08/JR/16-AO boards have it + * encoded as sign-magnitude. Assume the original + * COMEDI code is correct for now. + */ + unsigned int magnitude = lsb | ((msb & 0x7f) << 8); + + /* + * MSB bit 7 is 0 for negative, 1 for positive voltage. + * COMEDI 16-bit bipolar data value for 0V is 0x8000. + */ if (msb & 0x80) - data[n] = (1 << 15) | lsb | ((msb & 0x7f) << 8); + data[n] = (1 << 15) + magnitude; else - data[n] = (1 << 15) - (lsb | (msb & 0x7f) << 8); + data[n] = (1 << 15) - magnitude; } else { dev_err(dev->class_dev, "bug! unknown ai encoding\n"); return -1; @@ -266,28 +257,28 @@ static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, return n; } -static int das08_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int das08_di_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { data[0] = 0; - data[1] = DAS08_IP(inb(dev->iobase + DAS08_STATUS)); + data[1] = DAS08_STATUS_DI(inb(dev->iobase + DAS08_STATUS_REG)); return insn->n; } -static int das08_do_wbits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) +static int das08_do_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { struct das08_private_struct *devpriv = dev->private; if (comedi_dio_update_state(s, data)) { /* prevent race with setting of analog input mux */ spin_lock(&dev->spinlock); - devpriv->do_mux_bits &= ~DAS08_DO_MASK; - devpriv->do_mux_bits |= DAS08_OP(s->state); - outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL); + devpriv->do_mux_bits &= ~DAS08_CONTROL_DO_MASK; + devpriv->do_mux_bits |= DAS08_CONTROL_DO(s->state); + outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL_REG); spin_unlock(&dev->spinlock); } @@ -296,23 +287,22 @@ static int das08_do_wbits(struct comedi_device *dev, return insn->n; } -static int das08jr_di_rbits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int das08jr_di_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { data[0] = 0; - data[1] = inb(dev->iobase + DAS08JR_DIO); + data[1] = inb(dev->iobase + DAS08JR_DI_REG); return insn->n; } -static int das08jr_do_wbits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) +static int das08jr_do_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { if (comedi_dio_update_state(s, data)) - outb(s->state, dev->iobase + DAS08JR_DIO); + outb(s->state, dev->iobase + DAS08JR_DO_REG); data[1] = s->state; @@ -322,22 +312,22 @@ static int das08jr_do_wbits(struct comedi_device *dev, static void das08_ao_set_data(struct comedi_device *dev, unsigned int chan, unsigned int data) { - const struct das08_board_struct *thisboard = dev->board_ptr; + const struct das08_board_struct *board = dev->board_ptr; unsigned char lsb; unsigned char msb; lsb = data & 0xff; msb = (data >> 8) & 0xff; - if (thisboard->is_jr) { - outb(lsb, dev->iobase + DAS08JR_AO_LSB(chan)); - outb(msb, dev->iobase + DAS08JR_AO_MSB(chan)); + if (board->is_jr) { + outb(lsb, dev->iobase + DAS08JR_AO_LSB_REG(chan)); + outb(msb, dev->iobase + DAS08JR_AO_MSB_REG(chan)); /* load DACs */ - inb(dev->iobase + DAS08JR_DIO); + inb(dev->iobase + DAS08JR_AO_UPDATE_REG); } else { - outb(lsb, dev->iobase + DAS08AO_AO_LSB(chan)); - outb(msb, dev->iobase + DAS08AO_AO_MSB(chan)); + outb(lsb, dev->iobase + DAS08AOX_AO_LSB_REG(chan)); + outb(msb, dev->iobase + DAS08AOX_AO_MSB_REG(chan)); /* load DACs */ - inb(dev->iobase + DAS08AO_AO_UPDATE); + inb(dev->iobase + DAS08AOX_AO_UPDATE_REG); } } @@ -361,7 +351,7 @@ static int das08_ao_insn_write(struct comedi_device *dev, int das08_common_attach(struct comedi_device *dev, unsigned long iobase) { - const struct das08_board_struct *thisboard = dev->board_ptr; + const struct das08_board_struct *board = dev->board_ptr; struct das08_private_struct *devpriv = dev->private; struct comedi_subdevice *s; int ret; @@ -369,7 +359,7 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) dev->iobase = iobase; - dev->board_name = thisboard->name; + dev->board_name = board->name; ret = comedi_alloc_subdevices(dev, 6); if (ret) @@ -377,30 +367,31 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) s = &dev->subdevices[0]; /* ai */ - if (thisboard->ai_nbits) { + if (board->ai_nbits) { s->type = COMEDI_SUBD_AI; - /* XXX some boards actually have differential + /* + * XXX some boards actually have differential * inputs instead of single ended. * The driver does nothing with arefs though, * so it's no big deal. */ s->subdev_flags = SDF_READABLE | SDF_GROUND; s->n_chan = 8; - s->maxdata = (1 << thisboard->ai_nbits) - 1; - s->range_table = das08_ai_lranges[thisboard->ai_pg]; - s->insn_read = das08_ai_rinsn; - devpriv->pg_gainlist = das08_gainlists[thisboard->ai_pg]; + s->maxdata = (1 << board->ai_nbits) - 1; + s->range_table = das08_ai_lranges[board->ai_pg]; + s->insn_read = das08_ai_insn_read; + devpriv->pg_gainlist = das08_ai_gainlists[board->ai_pg]; } else { s->type = COMEDI_SUBD_UNUSED; } s = &dev->subdevices[1]; /* ao */ - if (thisboard->ao_nbits) { + if (board->ao_nbits) { s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; s->n_chan = 2; - s->maxdata = (1 << thisboard->ao_nbits) - 1; + s->maxdata = (1 << board->ao_nbits) - 1; s->range_table = &range_bipolar5; s->insn_write = das08_ao_insn_write; @@ -419,36 +410,36 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) s = &dev->subdevices[2]; /* di */ - if (thisboard->di_nchan) { + if (board->di_nchan) { s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; - s->n_chan = thisboard->di_nchan; + s->n_chan = board->di_nchan; s->maxdata = 1; s->range_table = &range_digital; - s->insn_bits = - thisboard->is_jr ? das08jr_di_rbits : das08_di_rbits; + s->insn_bits = board->is_jr ? das08jr_di_insn_bits : + das08_di_insn_bits; } else { s->type = COMEDI_SUBD_UNUSED; } s = &dev->subdevices[3]; /* do */ - if (thisboard->do_nchan) { + if (board->do_nchan) { s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = thisboard->do_nchan; + s->n_chan = board->do_nchan; s->maxdata = 1; s->range_table = &range_digital; - s->insn_bits = - thisboard->is_jr ? das08jr_do_wbits : das08_do_wbits; + s->insn_bits = board->is_jr ? das08jr_do_insn_bits : + das08_do_insn_bits; } else { s->type = COMEDI_SUBD_UNUSED; } s = &dev->subdevices[4]; /* 8255 */ - if (thisboard->i8255_offset != 0) { - ret = subdev_8255_init(dev, s, NULL, thisboard->i8255_offset); + if (board->i8255_offset != 0) { + ret = subdev_8255_init(dev, s, NULL, board->i8255_offset); if (ret) return ret; } else { @@ -457,9 +448,8 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) /* Counter subdevice (8254) */ s = &dev->subdevices[5]; - if (thisboard->i8254_offset) { - dev->pacer = comedi_8254_init(dev->iobase + - thisboard->i8254_offset, + if (board->i8254_offset) { + dev->pacer = comedi_8254_init(dev->iobase + board->i8254_offset, 0, I8254_IO8, 0); if (!dev->pacer) return -ENOMEM; @@ -485,5 +475,5 @@ static void __exit das08_exit(void) module_exit(das08_exit); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi common DAS08 support module"); MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/staging/comedi/drivers/das08.h b/kernel/drivers/staging/comedi/drivers/das08.h index f86167da5..d27044cb7 100644 --- a/kernel/drivers/staging/comedi/drivers/das08.h +++ b/kernel/drivers/staging/comedi/drivers/das08.h @@ -1,28 +1,33 @@ /* - das08.h - - Header for das08.c and das08_cs.c - - Copyright (C) 2003 Frank Mori Hess <fmhess@users.sourceforge.net> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * das08.h + * + * Header for common DAS08 support (used by ISA/PCI/PCMCIA drivers) + * + * Copyright (C) 2003 Frank Mori Hess <fmhess@users.sourceforge.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #ifndef _DAS08_H #define _DAS08_H +#include <linux/types.h> + +struct comedi_device; + /* different ways ai data is encoded in first two registers */ enum das08_ai_encoding { das08_encode12, das08_encode16, das08_pcm_encode12 }; -enum das08_lrange { das08_pg_none, das08_bipolar5, das08_pgh, das08_pgl, - das08_pgm +/* types of ai range table used by different boards */ +enum das08_lrange { + das08_pg_none, das08_bipolar5, das08_pgh, das08_pgl, das08_pgm }; struct das08_board_struct { @@ -36,13 +41,12 @@ struct das08_board_struct { unsigned int do_nchan; unsigned int i8255_offset; unsigned int i8254_offset; - unsigned int iosize; /* number of ioports used */ + unsigned int iosize; /* number of ioports used */ }; struct das08_private_struct { - unsigned int do_mux_bits; /* bits for do/mux register on boards - * without separate do register - */ + /* bits for do/mux register on boards without separate do register */ + unsigned int do_mux_bits; const unsigned int *pg_gainlist; }; diff --git a/kernel/drivers/staging/comedi/drivers/das08_cs.c b/kernel/drivers/staging/comedi/drivers/das08_cs.c index 93fab6890..9c02b17a2 100644 --- a/kernel/drivers/staging/comedi/drivers/das08_cs.c +++ b/kernel/drivers/staging/comedi/drivers/das08_cs.c @@ -108,7 +108,7 @@ static struct pcmcia_driver das08_cs_driver = { }; module_comedi_pcmcia_driver(driver_das08_cs, das08_cs_driver); -MODULE_AUTHOR("David A. Schleef <ds@schleef.org>, " - "Frank Mori Hess <fmhess@users.sourceforge.net>"); +MODULE_AUTHOR("David A. Schleef <ds@schleef.org>"); +MODULE_AUTHOR("Frank Mori Hess <fmhess@users.sourceforge.net>"); MODULE_DESCRIPTION("Comedi driver for ComputerBoards DAS-08 PCMCIA boards"); MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/staging/comedi/drivers/das08_isa.c b/kernel/drivers/staging/comedi/drivers/das08_isa.c index 2d9a31dab..cdefc99b6 100644 --- a/kernel/drivers/staging/comedi/drivers/das08_isa.c +++ b/kernel/drivers/staging/comedi/drivers/das08_isa.c @@ -168,7 +168,7 @@ static const struct das08_board_struct das08_isa_boards[] = { static int das08_isa_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - const struct das08_board_struct *thisboard = dev->board_ptr; + const struct das08_board_struct *board = dev->board_ptr; struct das08_private_struct *devpriv; int ret; @@ -176,7 +176,7 @@ static int das08_isa_attach(struct comedi_device *dev, if (!devpriv) return -ENOMEM; - ret = comedi_request_region(dev, it->options[0], thisboard->iosize); + ret = comedi_request_region(dev, it->options[0], board->iosize); if (ret) return ret; diff --git a/kernel/drivers/staging/comedi/drivers/das16.c b/kernel/drivers/staging/comedi/drivers/das16.c index d7cf4b153..056bca9c6 100644 --- a/kernel/drivers/staging/comedi/drivers/das16.c +++ b/kernel/drivers/staging/comedi/drivers/das16.c @@ -1032,8 +1032,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* check that clock setting is valid */ if (it->options[3]) { - if (it->options[3] != 0 && - it->options[3] != 1 && it->options[3] != 10) { + if (it->options[3] != 1 && it->options[3] != 10) { dev_err(dev->class_dev, "Invalid option. Master clock must be set to 1 or 10 (MHz)\n"); return -EINVAL; diff --git a/kernel/drivers/staging/comedi/drivers/das16m1.c b/kernel/drivers/staging/comedi/drivers/das16m1.c index 1adf6a71a..3a37373fb 100644 --- a/kernel/drivers/staging/comedi/drivers/das16m1.c +++ b/kernel/drivers/staging/comedi/drivers/das16m1.c @@ -46,8 +46,8 @@ list has 2 or more channels in it, then two conditions must be satisfied: (2) - the list must have an even number of entries. Options: - [0] - base io address - [1] - irq (optional, but you probably want it) + [0] - base io address + [1] - irq (optional, but you probably want it) irq can be omitted, although the cmd interface will not work without it. */ @@ -69,18 +69,18 @@ irq can be omitted, although the cmd interface will not work without it. "cio-das16/m1" - 0 a/d bits 0-3, mux start 12 bit - 1 a/d bits 4-11 unused - 2 status control - 3 di 4 bit do 4 bit - 4 unused clear interrupt - 5 interrupt, pacer - 6 channel/gain queue address - 7 channel/gain queue data - 89ab 8254 - cdef 8254 - 400 8255 - 404-407 8254 + 0 a/d bits 0-3, mux start 12 bit + 1 a/d bits 4-11 unused + 2 status control + 3 di 4 bit do 4 bit + 4 unused clear interrupt + 5 interrupt, pacer + 6 channel/gain queue address + 7 channel/gain queue data + 89ab 8254 + cdef 8254 + 400 8255 + 404-407 8254 */ @@ -411,15 +411,18 @@ static void das16m1_handler(struct comedi_device *dev, unsigned int status) hw_counter = comedi_8254_read(devpriv->counter, 1); /* make sure hardware counter reading is not bogus due to initial value * not having been loaded yet */ - if (devpriv->adc_count == 0 && hw_counter == devpriv->initial_hw_count) { + if (devpriv->adc_count == 0 && + hw_counter == devpriv->initial_hw_count) { num_samples = 0; } else { - /* The calculation of num_samples looks odd, but it uses the following facts. - * 16 bit hardware counter is initialized with value of zero (which really - * means 0x1000). The counter decrements by one on each conversion - * (when the counter decrements from zero it goes to 0xffff). num_samples - * is a 16 bit variable, so it will roll over in a similar fashion to the - * hardware counter. Work it out, and this is what you get. */ + /* The calculation of num_samples looks odd, but it uses the + * following facts. 16 bit hardware counter is initialized with + * value of zero (which really means 0x1000). The counter + * decrements by one on each conversion (when the counter + * decrements from zero it goes to 0xffff). num_samples is a + * 16 bit variable, so it will roll over in a similar fashion + * to the hardware counter. Work it out, and this is what you + * get. */ num_samples = -hw_counter - devpriv->adc_count; } /* check if we only need some of the points */ diff --git a/kernel/drivers/staging/comedi/drivers/das1800.c b/kernel/drivers/staging/comedi/drivers/das1800.c index 53baf37cd..940781183 100644 --- a/kernel/drivers/staging/comedi/drivers/das1800.c +++ b/kernel/drivers/staging/comedi/drivers/das1800.c @@ -444,9 +444,9 @@ static const struct comedi_lrange range_ao_2 = { static inline uint16_t munge_bipolar_sample(const struct comedi_device *dev, uint16_t sample) { - const struct das1800_board *thisboard = dev->board_ptr; + const struct das1800_board *board = dev->board_ptr; - sample += 1 << (thisboard->resolution - 1); + sample += 1 << (board->resolution - 1); return sample; } @@ -725,7 +725,7 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct das1800_board *thisboard = dev->board_ptr; + const struct das1800_board *board = dev->board_ptr; int err = 0; unsigned int arg; @@ -765,7 +765,7 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev, if (cmd->convert_src == TRIG_TIMER) { err |= comedi_check_trigger_arg_min(&cmd->convert_arg, - thisboard->ai_speed); + board->ai_speed); } err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1); @@ -1048,7 +1048,7 @@ static int das1800_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - const struct das1800_board *thisboard = dev->board_ptr; + const struct das1800_board *board = dev->board_ptr; int i, n; int chan, range, aref, chan_range; int timeout = 1000; @@ -1098,7 +1098,7 @@ static int das1800_ai_rinsn(struct comedi_device *dev, dpnt = inw(dev->iobase + DAS1800_FIFO); /* shift data to offset binary for bipolar ranges */ if ((conv_flags & UB) == 0) - dpnt += 1 << (thisboard->resolution - 1); + dpnt += 1 << (board->resolution - 1); data[n] = dpnt; } exit: @@ -1112,16 +1112,16 @@ static int das1800_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - const struct das1800_board *thisboard = dev->board_ptr; + const struct das1800_board *board = dev->board_ptr; struct das1800_private *devpriv = dev->private; int chan = CR_CHAN(insn->chanspec); /* int range = CR_RANGE(insn->chanspec); */ - int update_chan = thisboard->ao_n_chan - 1; + int update_chan = board->ao_n_chan - 1; unsigned short output; unsigned long irq_flags; /* card expects two's complement data */ - output = data[0] - (1 << (thisboard->resolution - 1)); + output = data[0] - (1 << (board->resolution - 1)); /* if the write is to the 'update' channel, we need to remember its value */ if (chan == update_chan) devpriv->ao_update_bits = output; @@ -1216,72 +1216,77 @@ static void das1800_free_dma(struct comedi_device *dev) comedi_isadma_free(devpriv->dma); } -static int das1800_probe(struct comedi_device *dev) +static const struct das1800_board *das1800_probe(struct comedi_device *dev) { const struct das1800_board *board = dev->board_ptr; - int index; + int index = board ? board - das1800_boards : -EINVAL; int id; - /* calc the offset to the boardinfo that was found by the core */ - index = board - das1800_boards; - - /* verify that the board id matches the boardinfo */ + /* + * The dev->board_ptr will be set by comedi_device_attach() if the + * board name provided by the user matches a board->name in this + * driver. If so, this function sanity checks the id to verify that + * the board is correct. + * + * If the dev->board_ptr is not set, the user is trying to attach + * an unspecified board to this driver. In this case the id is used + * to 'probe' for the correct dev->board_ptr. + */ id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf; switch (id) { case 0x3: if (index == das1801st_da || index == das1802st_da || index == das1701st_da || index == das1702st_da) - return index; + return board; index = das1801st; break; case 0x4: if (index == das1802hr_da || index == das1702hr_da) - return index; + return board; index = das1802hr; break; case 0x5: if (index == das1801ao || index == das1802ao || index == das1701ao || index == das1702ao) - return index; + return board; index = das1801ao; break; case 0x6: if (index == das1802hr || index == das1702hr) - return index; + return board; index = das1802hr; break; case 0x7: if (index == das1801st || index == das1802st || index == das1701st || index == das1702st) - return index; + return board; index = das1801st; break; case 0x8: if (index == das1801hc || index == das1802hc) - return index; + return board; index = das1801hc; break; default: dev_err(dev->class_dev, "Board model: probe returned 0x%x (unknown, please report)\n", id); - break; + return NULL; } dev_err(dev->class_dev, "Board model (probed, not recommended): %s series\n", das1800_boards[index].name); - return index; + return &das1800_boards[index]; } static int das1800_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - const struct das1800_board *thisboard; + const struct das1800_board *board; struct das1800_private *devpriv; struct comedi_subdevice *s; unsigned int irq = it->options[1]; - int board; int ret; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); @@ -1293,17 +1298,15 @@ static int das1800_attach(struct comedi_device *dev, return ret; board = das1800_probe(dev); - if (board < 0) { + if (!board) { dev_err(dev->class_dev, "unable to determine board type\n"); return -ENODEV; } - - dev->board_ptr = das1800_boards + board; - thisboard = dev->board_ptr; - dev->board_name = thisboard->name; + dev->board_ptr = board; + dev->board_name = board->name; /* if it is an 'ao' board with fancy analog out then we need extra io ports */ - if (thisboard->ao_ability == 2) { + if (board->ao_ability == 2) { unsigned long iobase2 = dev->iobase + IOBASE2; ret = __comedi_request_region(dev, iobase2, DAS1800_SIZE); @@ -1363,11 +1366,11 @@ static int das1800_attach(struct comedi_device *dev, s = &dev->subdevices[0]; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND; - if (thisboard->common) + if (board->common) s->subdev_flags |= SDF_COMMON; - s->n_chan = thisboard->qram_len; - s->maxdata = (1 << thisboard->resolution) - 1; - s->range_table = thisboard->range_ai; + s->n_chan = board->qram_len; + s->maxdata = (1 << board->resolution) - 1; + s->range_table = board->range_ai; s->insn_read = das1800_ai_rinsn; if (dev->irq) { dev->read_subdev = s; @@ -1381,11 +1384,11 @@ static int das1800_attach(struct comedi_device *dev, /* analog out */ s = &dev->subdevices[1]; - if (thisboard->ao_ability == 1) { + if (board->ao_ability == 1) { s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = thisboard->ao_n_chan; - s->maxdata = (1 << thisboard->resolution) - 1; + s->n_chan = board->ao_n_chan; + s->maxdata = (1 << board->resolution) - 1; s->range_table = &range_bipolar10; s->insn_write = das1800_ao_winsn; } else { @@ -1405,7 +1408,7 @@ static int das1800_attach(struct comedi_device *dev, s = &dev->subdevices[3]; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = thisboard->do_n_chan; + s->n_chan = board->do_n_chan; s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = das1800_do_wbits; @@ -1416,9 +1419,9 @@ static int das1800_attach(struct comedi_device *dev, outb(0, dev->iobase + DAS1800_DIGITAL); /* initialize analog out channels */ - if (thisboard->ao_ability == 1) { + if (board->ao_ability == 1) { /* select 'update' dac channel for baseAddress + 0x0 */ - outb(DAC(thisboard->ao_n_chan - 1), + outb(DAC(board->ao_n_chan - 1), dev->iobase + DAS1800_SELECT); outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC); } diff --git a/kernel/drivers/staging/comedi/drivers/das800.c b/kernel/drivers/staging/comedi/drivers/das800.c index 39d304a12..b02f12201 100644 --- a/kernel/drivers/staging/comedi/drivers/das800.c +++ b/kernel/drivers/staging/comedi/drivers/das800.c @@ -240,13 +240,13 @@ static unsigned das800_ind_read(struct comedi_device *dev, unsigned reg) static void das800_enable(struct comedi_device *dev) { - const struct das800_board *thisboard = dev->board_ptr; + const struct das800_board *board = dev->board_ptr; struct das800_private *devpriv = dev->private; unsigned long irq_flags; spin_lock_irqsave(&dev->spinlock, irq_flags); /* enable fifo-half full interrupts for cio-das802/16 */ - if (thisboard->resolution == 16) + if (board->resolution == 16) outb(CIO_ENHF, dev->iobase + DAS800_GAIN); /* enable hardware triggering */ das800_ind_write(dev, CONV_HCEN, CONV_CONTROL); @@ -303,7 +303,7 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct das800_board *thisboard = dev->board_ptr; + const struct das800_board *board = dev->board_ptr; int err = 0; /* Step 1 : check if triggers are trivially valid */ @@ -335,7 +335,7 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev, if (cmd->convert_src == TRIG_TIMER) { err |= comedi_check_trigger_arg_min(&cmd->convert_arg, - thisboard->ai_speed); + board->ai_speed); } err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1); @@ -375,7 +375,7 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev, static int das800_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - const struct das800_board *thisboard = dev->board_ptr; + const struct das800_board *board = dev->board_ptr; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; unsigned int gain = CR_RANGE(cmd->chanlist[0]); @@ -393,7 +393,7 @@ static int das800_ai_do_cmd(struct comedi_device *dev, spin_unlock_irqrestore(&dev->spinlock, irq_flags); /* set gain */ - if (thisboard->resolution == 12 && gain > 0) + if (board->resolution == 12 && gain > 0) gain += 0x7; gain &= 0xf; outb(gain, dev->iobase + DAS800_GAIN); @@ -604,54 +604,62 @@ static int das800_do_insn_bits(struct comedi_device *dev, return insn->n; } -static int das800_probe(struct comedi_device *dev) +static const struct das800_board *das800_probe(struct comedi_device *dev) { - const struct das800_board *thisboard = dev->board_ptr; - int board = thisboard ? thisboard - das800_boards : -EINVAL; + const struct das800_board *board = dev->board_ptr; + int index = board ? board - das800_boards : -EINVAL; int id_bits; unsigned long irq_flags; + /* + * The dev->board_ptr will be set by comedi_device_attach() if the + * board name provided by the user matches a board->name in this + * driver. If so, this function sanity checks the id_bits to verify + * that the board is correct. + * + * If the dev->board_ptr is not set, the user is trying to attach + * an unspecified board to this driver. In this case the id_bits + * are used to 'probe' for the correct dev->board_ptr. + */ spin_lock_irqsave(&dev->spinlock, irq_flags); id_bits = das800_ind_read(dev, ID) & 0x3; spin_unlock_irqrestore(&dev->spinlock, irq_flags); switch (id_bits) { case 0x0: - if (board == BOARD_DAS800 || board == BOARD_CIODAS800) - break; - dev_dbg(dev->class_dev, "Board model (probed): DAS-800\n"); - board = BOARD_DAS800; + if (index == BOARD_DAS800 || index == BOARD_CIODAS800) + return board; + index = BOARD_DAS800; break; case 0x2: - if (board == BOARD_DAS801 || board == BOARD_CIODAS801) - break; - dev_dbg(dev->class_dev, "Board model (probed): DAS-801\n"); - board = BOARD_DAS801; + if (index == BOARD_DAS801 || index == BOARD_CIODAS801) + return board; + index = BOARD_DAS801; break; case 0x3: - if (board == BOARD_DAS802 || board == BOARD_CIODAS802 || - board == BOARD_CIODAS80216) - break; - dev_dbg(dev->class_dev, "Board model (probed): DAS-802\n"); - board = BOARD_DAS802; + if (index == BOARD_DAS802 || index == BOARD_CIODAS802 || + index == BOARD_CIODAS80216) + return board; + index = BOARD_DAS802; break; default: dev_dbg(dev->class_dev, "Board model: 0x%x (unknown)\n", id_bits); - board = -EINVAL; - break; + return NULL; } - return board; + dev_dbg(dev->class_dev, "Board model (probed): %s series\n", + das800_boards[index].name); + + return &das800_boards[index]; } static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - const struct das800_board *thisboard; + const struct das800_board *board; struct das800_private *devpriv; struct comedi_subdevice *s; unsigned int irq = it->options[1]; unsigned long irq_flags; - int board; int ret; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); @@ -663,13 +671,10 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) return ret; board = das800_probe(dev); - if (board < 0) { - dev_dbg(dev->class_dev, "unable to determine board type\n"); + if (!board) return -ENODEV; - } - dev->board_ptr = das800_boards + board; - thisboard = dev->board_ptr; - dev->board_name = thisboard->name; + dev->board_ptr = board; + dev->board_name = board->name; if (irq > 1 && irq <= 7) { ret = request_irq(irq, das800_interrupt, 0, dev->board_name, @@ -693,8 +698,8 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND; s->n_chan = 8; - s->maxdata = (1 << thisboard->resolution) - 1; - s->range_table = thisboard->ai_range; + s->maxdata = (1 << board->resolution) - 1; + s->range_table = board->ai_range; s->insn_read = das800_ai_insn_read; if (dev->irq) { s->subdev_flags |= SDF_CMD_READ; diff --git a/kernel/drivers/staging/comedi/drivers/dmm32at.c b/kernel/drivers/staging/comedi/drivers/dmm32at.c index bb2883c83..958c0d4aa 100644 --- a/kernel/drivers/staging/comedi/drivers/dmm32at.c +++ b/kernel/drivers/staging/comedi/drivers/dmm32at.c @@ -607,11 +607,7 @@ static int dmm32at_attach(struct comedi_device *dev, /* Digital I/O subdevice */ s = &dev->subdevices[2]; - ret = subdev_8255_init(dev, s, dmm32at_8255_io, DMM32AT_8255_IOBASE); - if (ret) - return ret; - - return 0; + return subdev_8255_init(dev, s, dmm32at_8255_io, DMM32AT_8255_IOBASE); } static struct comedi_driver dmm32at_driver = { diff --git a/kernel/drivers/staging/comedi/drivers/dt3000.c b/kernel/drivers/staging/comedi/drivers/dt3000.c index 031282c82..ab7a332fb 100644 --- a/kernel/drivers/staging/comedi/drivers/dt3000.c +++ b/kernel/drivers/staging/comedi/drivers/dt3000.c @@ -1,52 +1,53 @@ /* - comedi/drivers/dt3000.c - Data Translation DT3000 series driver - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1999 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ -/* -Driver: dt3000 -Description: Data Translation DT3000 series -Author: ds -Devices: [Data Translation] DT3001 (dt3000), DT3001-PGL, DT3002, DT3003, - DT3003-PGL, DT3004, DT3005, DT3004-200 -Updated: Mon, 14 Apr 2008 15:41:24 +0100 -Status: works - -Configuration Options: not applicable, uses PCI auto config - -There is code to support AI commands, but it may not work. + * dt3000.c + * Data Translation DT3000 series driver + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1999 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ -AO commands are not supported. -*/ +/* + * Driver: dt3000 + * Description: Data Translation DT3000 series + * Devices: [Data Translation] DT3001 (dt3000), DT3001-PGL, DT3002, DT3003, + * DT3003-PGL, DT3004, DT3005, DT3004-200 + * Author: ds + * Updated: Mon, 14 Apr 2008 15:41:24 +0100 + * Status: works + * + * Configuration Options: not applicable, uses PCI auto config + * + * There is code to support AI commands, but it may not work. + * + * AO commands are not supported. + */ /* - The DT3000 series is Data Translation's attempt to make a PCI - data acquisition board. The design of this series is very nice, - since each board has an on-board DSP (Texas Instruments TMS320C52). - However, a few details are a little annoying. The boards lack - bus-mastering DMA, which eliminates them from serious work. - They also are not capable of autocalibration, which is a common - feature in modern hardware. The default firmware is pretty bad, - making it nearly impossible to write an RT compatible driver. - It would make an interesting project to write a decent firmware - for these boards. - - Data Translation originally wanted an NDA for the documentation - for the 3k series. However, if you ask nicely, they might send - you the docs without one, also. -*/ + * The DT3000 series is Data Translation's attempt to make a PCI + * data acquisition board. The design of this series is very nice, + * since each board has an on-board DSP (Texas Instruments TMS320C52). + * However, a few details are a little annoying. The boards lack + * bus-mastering DMA, which eliminates them from serious work. + * They also are not capable of autocalibration, which is a common + * feature in modern hardware. The default firmware is pretty bad, + * making it nearly impossible to write an RT compatible driver. + * It would make an interesting project to write a decent firmware + * for these boards. + * + * Data Translation originally wanted an NDA for the documentation + * for the 3k series. However, if you ask nicely, they might send + * you the docs without one, also. + */ #include <linux/module.h> #include <linux/delay.h> @@ -54,6 +55,88 @@ AO commands are not supported. #include "../comedi_pci.h" +/* + * PCI BAR0 - dual-ported RAM location definitions (dev->mmio) + */ +#define DPR_DAC_BUFFER (4 * 0x000) +#define DPR_ADC_BUFFER (4 * 0x800) +#define DPR_COMMAND (4 * 0xfd3) +#define DPR_SUBSYS (4 * 0xfd3) +#define DPR_SUBSYS_AI 0 +#define DPR_SUBSYS_AO 1 +#define DPR_SUBSYS_DIN 2 +#define DPR_SUBSYS_DOUT 3 +#define DPR_SUBSYS_MEM 4 +#define DPR_SUBSYS_CT 5 +#define DPR_ENCODE (4 * 0xfd4) +#define DPR_PARAMS(x) (4 * (0xfd5 + (x))) +#define DPR_TICK_REG_LO (4 * 0xff5) +#define DPR_TICK_REG_HI (4 * 0xff6) +#define DPR_DA_BUF_FRONT (4 * 0xff7) +#define DPR_DA_BUF_REAR (4 * 0xff8) +#define DPR_AD_BUF_FRONT (4 * 0xff9) +#define DPR_AD_BUF_REAR (4 * 0xffa) +#define DPR_INT_MASK (4 * 0xffb) +#define DPR_INTR_FLAG (4 * 0xffc) +#define DPR_INTR_CMDONE BIT(7) +#define DPR_INTR_CTDONE BIT(6) +#define DPR_INTR_DAHWERR BIT(5) +#define DPR_INTR_DASWERR BIT(4) +#define DPR_INTR_DAEMPTY BIT(3) +#define DPR_INTR_ADHWERR BIT(2) +#define DPR_INTR_ADSWERR BIT(1) +#define DPR_INTR_ADFULL BIT(0) +#define DPR_RESPONSE_MBX (4 * 0xffe) +#define DPR_CMD_MBX (4 * 0xfff) +#define DPR_CMD_COMPLETION(x) ((x) << 8) +#define DPR_CMD_NOTPROCESSED DPR_CMD_COMPLETION(0x00) +#define DPR_CMD_NOERROR DPR_CMD_COMPLETION(0x55) +#define DPR_CMD_ERROR DPR_CMD_COMPLETION(0xaa) +#define DPR_CMD_NOTSUPPORTED DPR_CMD_COMPLETION(0xff) +#define DPR_CMD_COMPLETION_MASK DPR_CMD_COMPLETION(0xff) +#define DPR_CMD(x) ((x) << 0) +#define DPR_CMD_GETBRDINFO DPR_CMD(0) +#define DPR_CMD_CONFIG DPR_CMD(1) +#define DPR_CMD_GETCONFIG DPR_CMD(2) +#define DPR_CMD_START DPR_CMD(3) +#define DPR_CMD_STOP DPR_CMD(4) +#define DPR_CMD_READSINGLE DPR_CMD(5) +#define DPR_CMD_WRITESINGLE DPR_CMD(6) +#define DPR_CMD_CALCCLOCK DPR_CMD(7) +#define DPR_CMD_READEVENTS DPR_CMD(8) +#define DPR_CMD_WRITECTCTRL DPR_CMD(16) +#define DPR_CMD_READCTCTRL DPR_CMD(17) +#define DPR_CMD_WRITECT DPR_CMD(18) +#define DPR_CMD_READCT DPR_CMD(19) +#define DPR_CMD_WRITEDATA DPR_CMD(32) +#define DPR_CMD_READDATA DPR_CMD(33) +#define DPR_CMD_WRITEIO DPR_CMD(34) +#define DPR_CMD_READIO DPR_CMD(35) +#define DPR_CMD_WRITECODE DPR_CMD(36) +#define DPR_CMD_READCODE DPR_CMD(37) +#define DPR_CMD_EXECUTE DPR_CMD(38) +#define DPR_CMD_HALT DPR_CMD(48) +#define DPR_CMD_MASK DPR_CMD(0xff) + +#define DPR_PARAM5_AD_TRIG(x) (((x) & 0x7) << 2) +#define DPR_PARAM5_AD_TRIG_INT DPR_PARAM5_AD_TRIG(0) +#define DPR_PARAM5_AD_TRIG_EXT DPR_PARAM5_AD_TRIG(1) +#define DPR_PARAM5_AD_TRIG_INT_RETRIG DPR_PARAM5_AD_TRIG(2) +#define DPR_PARAM5_AD_TRIG_EXT_RETRIG DPR_PARAM5_AD_TRIG(3) +#define DPR_PARAM5_AD_TRIG_INT_RETRIG2 DPR_PARAM5_AD_TRIG(4) + +#define DPR_PARAM6_AD_DIFF BIT(0) + +#define DPR_AI_FIFO_DEPTH 2003 +#define DPR_AO_FIFO_DEPTH 2048 + +#define DPR_EXTERNAL_CLOCK 1 +#define DPR_RISING_EDGE 2 + +#define DPR_TMODE_MASK 0x1c + +#define DPR_CMD_TIMEOUT 100 + static const struct comedi_lrange range_dt3000_ai = { 4, { BIP_RANGE(10), @@ -85,184 +168,87 @@ enum dt3k_boardid { struct dt3k_boardtype { const char *name; int adchan; - int adbits; int ai_speed; const struct comedi_lrange *adrange; - int dachan; - int dabits; + unsigned int ai_is_16bit:1; + unsigned int has_ao:1; }; static const struct dt3k_boardtype dt3k_boardtypes[] = { [BOARD_DT3001] = { .name = "dt3001", .adchan = 16, - .adbits = 12, .adrange = &range_dt3000_ai, .ai_speed = 3000, - .dachan = 2, - .dabits = 12, + .has_ao = 1, }, [BOARD_DT3001_PGL] = { .name = "dt3001-pgl", .adchan = 16, - .adbits = 12, .adrange = &range_dt3000_ai_pgl, .ai_speed = 3000, - .dachan = 2, - .dabits = 12, + .has_ao = 1, }, [BOARD_DT3002] = { .name = "dt3002", .adchan = 32, - .adbits = 12, .adrange = &range_dt3000_ai, .ai_speed = 3000, }, [BOARD_DT3003] = { .name = "dt3003", .adchan = 64, - .adbits = 12, .adrange = &range_dt3000_ai, .ai_speed = 3000, - .dachan = 2, - .dabits = 12, + .has_ao = 1, }, [BOARD_DT3003_PGL] = { .name = "dt3003-pgl", .adchan = 64, - .adbits = 12, .adrange = &range_dt3000_ai_pgl, .ai_speed = 3000, - .dachan = 2, - .dabits = 12, + .has_ao = 1, }, [BOARD_DT3004] = { .name = "dt3004", .adchan = 16, - .adbits = 16, .adrange = &range_dt3000_ai, .ai_speed = 10000, - .dachan = 2, - .dabits = 12, + .ai_is_16bit = 1, + .has_ao = 1, }, [BOARD_DT3005] = { .name = "dt3005", /* a.k.a. 3004-200 */ .adchan = 16, - .adbits = 16, .adrange = &range_dt3000_ai, .ai_speed = 5000, - .dachan = 2, - .dabits = 12, + .ai_is_16bit = 1, + .has_ao = 1, }, }; -/* dual-ported RAM location definitions */ - -#define DPR_DAC_buffer (4*0x000) -#define DPR_ADC_buffer (4*0x800) -#define DPR_Command (4*0xfd3) -#define DPR_SubSys (4*0xfd3) -#define DPR_Encode (4*0xfd4) -#define DPR_Params(a) (4*(0xfd5+(a))) -#define DPR_Tick_Reg_Lo (4*0xff5) -#define DPR_Tick_Reg_Hi (4*0xff6) -#define DPR_DA_Buf_Front (4*0xff7) -#define DPR_DA_Buf_Rear (4*0xff8) -#define DPR_AD_Buf_Front (4*0xff9) -#define DPR_AD_Buf_Rear (4*0xffa) -#define DPR_Int_Mask (4*0xffb) -#define DPR_Intr_Flag (4*0xffc) -#define DPR_Response_Mbx (4*0xffe) -#define DPR_Command_Mbx (4*0xfff) - -#define AI_FIFO_DEPTH 2003 -#define AO_FIFO_DEPTH 2048 - -/* command list */ - -#define CMD_GETBRDINFO 0 -#define CMD_CONFIG 1 -#define CMD_GETCONFIG 2 -#define CMD_START 3 -#define CMD_STOP 4 -#define CMD_READSINGLE 5 -#define CMD_WRITESINGLE 6 -#define CMD_CALCCLOCK 7 -#define CMD_READEVENTS 8 -#define CMD_WRITECTCTRL 16 -#define CMD_READCTCTRL 17 -#define CMD_WRITECT 18 -#define CMD_READCT 19 -#define CMD_WRITEDATA 32 -#define CMD_READDATA 33 -#define CMD_WRITEIO 34 -#define CMD_READIO 35 -#define CMD_WRITECODE 36 -#define CMD_READCODE 37 -#define CMD_EXECUTE 38 -#define CMD_HALT 48 - -#define SUBS_AI 0 -#define SUBS_AO 1 -#define SUBS_DIN 2 -#define SUBS_DOUT 3 -#define SUBS_MEM 4 -#define SUBS_CT 5 - -/* interrupt flags */ -#define DT3000_CMDONE 0x80 -#define DT3000_CTDONE 0x40 -#define DT3000_DAHWERR 0x20 -#define DT3000_DASWERR 0x10 -#define DT3000_DAEMPTY 0x08 -#define DT3000_ADHWERR 0x04 -#define DT3000_ADSWERR 0x02 -#define DT3000_ADFULL 0x01 - -#define DT3000_COMPLETION_MASK 0xff00 -#define DT3000_COMMAND_MASK 0x00ff -#define DT3000_NOTPROCESSED 0x0000 -#define DT3000_NOERROR 0x5500 -#define DT3000_ERROR 0xaa00 -#define DT3000_NOTSUPPORTED 0xff00 - -#define DT3000_EXTERNAL_CLOCK 1 -#define DT3000_RISING_EDGE 2 - -#define TMODE_MASK 0x1c - -#define DT3000_AD_TRIG_INTERNAL (0<<2) -#define DT3000_AD_TRIG_EXTERNAL (1<<2) -#define DT3000_AD_RETRIG_INTERNAL (2<<2) -#define DT3000_AD_RETRIG_EXTERNAL (3<<2) -#define DT3000_AD_EXTRETRIG (4<<2) - -#define DT3000_CHANNEL_MODE_SE 0 -#define DT3000_CHANNEL_MODE_DI 1 - struct dt3k_private { unsigned int lock; unsigned int ai_front; unsigned int ai_rear; }; -#define TIMEOUT 100 - static void dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd) { int i; unsigned int status = 0; - writew(cmd, dev->mmio + DPR_Command_Mbx); + writew(cmd, dev->mmio + DPR_CMD_MBX); - for (i = 0; i < TIMEOUT; i++) { - status = readw(dev->mmio + DPR_Command_Mbx); - if ((status & DT3000_COMPLETION_MASK) != DT3000_NOTPROCESSED) + for (i = 0; i < DPR_CMD_TIMEOUT; i++) { + status = readw(dev->mmio + DPR_CMD_MBX); + status &= DPR_CMD_COMPLETION_MASK; + if (status != DPR_CMD_NOTPROCESSED) break; udelay(1); } - if ((status & DT3000_COMPLETION_MASK) != DT3000_NOERROR) + if (status != DPR_CMD_NOERROR) dev_dbg(dev->class_dev, "%s: timeout/error status=0x%04x\n", __func__, status); } @@ -271,26 +257,26 @@ static unsigned int dt3k_readsingle(struct comedi_device *dev, unsigned int subsys, unsigned int chan, unsigned int gain) { - writew(subsys, dev->mmio + DPR_SubSys); + writew(subsys, dev->mmio + DPR_SUBSYS); - writew(chan, dev->mmio + DPR_Params(0)); - writew(gain, dev->mmio + DPR_Params(1)); + writew(chan, dev->mmio + DPR_PARAMS(0)); + writew(gain, dev->mmio + DPR_PARAMS(1)); - dt3k_send_cmd(dev, CMD_READSINGLE); + dt3k_send_cmd(dev, DPR_CMD_READSINGLE); - return readw(dev->mmio + DPR_Params(2)); + return readw(dev->mmio + DPR_PARAMS(2)); } static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys, unsigned int chan, unsigned int data) { - writew(subsys, dev->mmio + DPR_SubSys); + writew(subsys, dev->mmio + DPR_SUBSYS); - writew(chan, dev->mmio + DPR_Params(0)); - writew(0, dev->mmio + DPR_Params(1)); - writew(data, dev->mmio + DPR_Params(2)); + writew(chan, dev->mmio + DPR_PARAMS(0)); + writew(0, dev->mmio + DPR_PARAMS(1)); + writew(data, dev->mmio + DPR_PARAMS(2)); - dt3k_send_cmd(dev, CMD_WRITESINGLE); + dt3k_send_cmd(dev, DPR_CMD_WRITESINGLE); } static void dt3k_ai_empty_fifo(struct comedi_device *dev, @@ -303,32 +289,32 @@ static void dt3k_ai_empty_fifo(struct comedi_device *dev, int i; unsigned short data; - front = readw(dev->mmio + DPR_AD_Buf_Front); + front = readw(dev->mmio + DPR_AD_BUF_FRONT); count = front - devpriv->ai_front; if (count < 0) - count += AI_FIFO_DEPTH; + count += DPR_AI_FIFO_DEPTH; rear = devpriv->ai_rear; for (i = 0; i < count; i++) { - data = readw(dev->mmio + DPR_ADC_buffer + rear); + data = readw(dev->mmio + DPR_ADC_BUFFER + rear); comedi_buf_write_samples(s, &data, 1); rear++; - if (rear >= AI_FIFO_DEPTH) + if (rear >= DPR_AI_FIFO_DEPTH) rear = 0; } devpriv->ai_rear = rear; - writew(rear, dev->mmio + DPR_AD_Buf_Rear); + writew(rear, dev->mmio + DPR_AD_BUF_REAR); } static int dt3k_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - writew(SUBS_AI, dev->mmio + DPR_SubSys); - dt3k_send_cmd(dev, CMD_STOP); + writew(DPR_SUBSYS_AI, dev->mmio + DPR_SUBSYS); + dt3k_send_cmd(dev, DPR_CMD_STOP); - writew(0, dev->mmio + DPR_Int_Mask); + writew(0, dev->mmio + DPR_INT_MASK); return 0; } @@ -346,12 +332,12 @@ static irqreturn_t dt3k_interrupt(int irq, void *d) if (!dev->attached) return IRQ_NONE; - status = readw(dev->mmio + DPR_Intr_Flag); + status = readw(dev->mmio + DPR_INTR_FLAG); - if (status & DT3000_ADFULL) + if (status & DPR_INTR_ADFULL) dt3k_ai_empty_fifo(dev, s); - if (status & (DT3000_ADSWERR | DT3000_ADHWERR)) + if (status & (DPR_INTR_ADSWERR | DPR_INTR_ADHWERR)) s->async->events |= COMEDI_CB_ERROR; debug_n_ints++; @@ -400,7 +386,7 @@ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec, static int dt3k_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct dt3k_boardtype *this_board = dev->board_ptr; + const struct dt3k_boardtype *board = dev->board_ptr; int err = 0; unsigned int arg; @@ -424,14 +410,14 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER) { err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, - this_board->ai_speed); + board->ai_speed); err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg, 100 * 16 * 65535); } if (cmd->convert_src == TRIG_TIMER) { err |= comedi_check_trigger_arg_min(&cmd->convert_arg, - this_board->ai_speed); + board->ai_speed); err |= comedi_check_trigger_arg_max(&cmd->convert_arg, 50 * 16 * 65535); } @@ -486,46 +472,49 @@ static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) chan = CR_CHAN(cmd->chanlist[i]); range = CR_RANGE(cmd->chanlist[i]); - writew((range << 6) | chan, dev->mmio + DPR_ADC_buffer + i); + writew((range << 6) | chan, dev->mmio + DPR_ADC_BUFFER + i); } aref = CR_AREF(cmd->chanlist[0]); - writew(cmd->scan_end_arg, dev->mmio + DPR_Params(0)); + writew(cmd->scan_end_arg, dev->mmio + DPR_PARAMS(0)); if (cmd->convert_src == TRIG_TIMER) { divider = dt3k_ns_to_timer(50, &cmd->convert_arg, cmd->flags); - writew((divider >> 16), dev->mmio + DPR_Params(1)); - writew((divider & 0xffff), dev->mmio + DPR_Params(2)); + writew((divider >> 16), dev->mmio + DPR_PARAMS(1)); + writew((divider & 0xffff), dev->mmio + DPR_PARAMS(2)); } if (cmd->scan_begin_src == TRIG_TIMER) { tscandiv = dt3k_ns_to_timer(100, &cmd->scan_begin_arg, cmd->flags); - writew((tscandiv >> 16), dev->mmio + DPR_Params(3)); - writew((tscandiv & 0xffff), dev->mmio + DPR_Params(4)); + writew((tscandiv >> 16), dev->mmio + DPR_PARAMS(3)); + writew((tscandiv & 0xffff), dev->mmio + DPR_PARAMS(4)); } - writew(DT3000_AD_RETRIG_INTERNAL, dev->mmio + DPR_Params(5)); - writew(aref == AREF_DIFF, dev->mmio + DPR_Params(6)); + writew(DPR_PARAM5_AD_TRIG_INT_RETRIG, dev->mmio + DPR_PARAMS(5)); + writew((aref == AREF_DIFF) ? DPR_PARAM6_AD_DIFF : 0, + dev->mmio + DPR_PARAMS(6)); - writew(AI_FIFO_DEPTH / 2, dev->mmio + DPR_Params(7)); + writew(DPR_AI_FIFO_DEPTH / 2, dev->mmio + DPR_PARAMS(7)); - writew(SUBS_AI, dev->mmio + DPR_SubSys); - dt3k_send_cmd(dev, CMD_CONFIG); + writew(DPR_SUBSYS_AI, dev->mmio + DPR_SUBSYS); + dt3k_send_cmd(dev, DPR_CMD_CONFIG); - writew(DT3000_ADFULL | DT3000_ADSWERR | DT3000_ADHWERR, - dev->mmio + DPR_Int_Mask); + writew(DPR_INTR_ADFULL | DPR_INTR_ADSWERR | DPR_INTR_ADHWERR, + dev->mmio + DPR_INT_MASK); debug_n_ints = 0; - writew(SUBS_AI, dev->mmio + DPR_SubSys); - dt3k_send_cmd(dev, CMD_START); + writew(DPR_SUBSYS_AI, dev->mmio + DPR_SUBSYS); + dt3k_send_cmd(dev, DPR_CMD_START); return 0; } -static int dt3k_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int dt3k_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { int i; unsigned int chan, gain, aref; @@ -536,7 +525,7 @@ static int dt3k_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s, aref = CR_AREF(insn->chanspec); for (i = 0; i < insn->n; i++) - data[i] = dt3k_readsingle(dev, SUBS_AI, chan, gain); + data[i] = dt3k_readsingle(dev, DPR_SUBSYS_AI, chan, gain); return i; } @@ -552,7 +541,7 @@ static int dt3k_ao_insn_write(struct comedi_device *dev, for (i = 0; i < insn->n; i++) { val = data[i]; - dt3k_writesingle(dev, SUBS_AO, chan, val); + dt3k_writesingle(dev, DPR_SUBSYS_AO, chan, val); } s->readback[chan] = val; @@ -562,16 +551,13 @@ static int dt3k_ao_insn_write(struct comedi_device *dev, static void dt3k_dio_config(struct comedi_device *dev, int bits) { /* XXX */ - writew(SUBS_DOUT, dev->mmio + DPR_SubSys); + writew(DPR_SUBSYS_DOUT, dev->mmio + DPR_SUBSYS); - writew(bits, dev->mmio + DPR_Params(0)); -#if 0 - /* don't know */ - writew(0, dev->mmio + DPR_Params(1)); - writew(0, dev->mmio + DPR_Params(2)); -#endif + writew(bits, dev->mmio + DPR_PARAMS(0)); - dt3k_send_cmd(dev, CMD_CONFIG); + /* XXX write 0 to DPR_PARAMS(1) and DPR_PARAMS(2) ? */ + + dt3k_send_cmd(dev, DPR_CMD_CONFIG); } static int dt3k_dio_insn_config(struct comedi_device *dev, @@ -603,9 +589,9 @@ static int dt3k_dio_insn_bits(struct comedi_device *dev, unsigned int *data) { if (comedi_dio_update_state(s, data)) - dt3k_writesingle(dev, SUBS_DOUT, 0, s->state); + dt3k_writesingle(dev, DPR_SUBSYS_DOUT, 0, s->state); - data[1] = dt3k_readsingle(dev, SUBS_DIN, 0, 0); + data[1] = dt3k_readsingle(dev, DPR_SUBSYS_DIN, 0, 0); return insn->n; } @@ -619,13 +605,13 @@ static int dt3k_mem_insn_read(struct comedi_device *dev, int i; for (i = 0; i < insn->n; i++) { - writew(SUBS_MEM, dev->mmio + DPR_SubSys); - writew(addr, dev->mmio + DPR_Params(0)); - writew(1, dev->mmio + DPR_Params(1)); + writew(DPR_SUBSYS_MEM, dev->mmio + DPR_SUBSYS); + writew(addr, dev->mmio + DPR_PARAMS(0)); + writew(1, dev->mmio + DPR_PARAMS(1)); - dt3k_send_cmd(dev, CMD_READCODE); + dt3k_send_cmd(dev, DPR_CMD_READCODE); - data[i] = readw(dev->mmio + DPR_Params(2)); + data[i] = readw(dev->mmio + DPR_PARAMS(2)); } return i; @@ -635,17 +621,17 @@ static int dt3000_auto_attach(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct dt3k_boardtype *this_board = NULL; + const struct dt3k_boardtype *board = NULL; struct dt3k_private *devpriv; struct comedi_subdevice *s; int ret = 0; if (context < ARRAY_SIZE(dt3k_boardtypes)) - this_board = &dt3k_boardtypes[context]; - if (!this_board) + board = &dt3k_boardtypes[context]; + if (!board) return -ENODEV; - dev->board_ptr = this_board; - dev->board_name = this_board->name; + dev->board_ptr = board; + dev->board_name = board->name; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -670,14 +656,14 @@ static int dt3000_auto_attach(struct comedi_device *dev, if (ret) return ret; + /* Analog Input subdevice */ s = &dev->subdevices[0]; - /* ai subdevice */ s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; - s->n_chan = this_board->adchan; - s->insn_read = dt3k_ai_insn; - s->maxdata = (1 << this_board->adbits) - 1; + s->n_chan = board->adchan; + s->maxdata = board->ai_is_16bit ? 0xffff : 0x0fff; s->range_table = &range_dt3000_ai; /* XXX */ + s->insn_read = dt3k_ai_insn_read; if (dev->irq) { dev->read_subdev = s; s->subdev_flags |= SDF_CMD_READ; @@ -687,46 +673,42 @@ static int dt3000_auto_attach(struct comedi_device *dev, s->cancel = dt3k_ai_cancel; } + /* Analog Output subdevice */ s = &dev->subdevices[1]; - /* ao subsystem */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 2; - s->maxdata = (1 << this_board->dabits) - 1; - s->len_chanlist = 1; - s->range_table = &range_bipolar10; - s->insn_write = dt3k_ao_insn_write; - - ret = comedi_alloc_subdev_readback(s); - if (ret) - return ret; + if (board->has_ao) { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 2; + s->maxdata = 0x0fff; + s->range_table = &range_bipolar10; + s->insn_write = dt3k_ao_insn_write; + + ret = comedi_alloc_subdev_readback(s); + if (ret) + return ret; + + } else { + s->type = COMEDI_SUBD_UNUSED; + } + /* Digital I/O subdevice */ s = &dev->subdevices[2]; - /* dio subsystem */ s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 8; - s->insn_config = dt3k_dio_insn_config; - s->insn_bits = dt3k_dio_insn_bits; s->maxdata = 1; - s->len_chanlist = 8; s->range_table = &range_digital; + s->insn_config = dt3k_dio_insn_config; + s->insn_bits = dt3k_dio_insn_bits; + /* Memory subdevice */ s = &dev->subdevices[3]; - /* mem subsystem */ s->type = COMEDI_SUBD_MEMORY; s->subdev_flags = SDF_READABLE; s->n_chan = 0x1000; - s->insn_read = dt3k_mem_insn_read; s->maxdata = 0xff; - s->len_chanlist = 1; s->range_table = &range_unknown; - -#if 0 - s = &dev->subdevices[4]; - /* proc subsystem */ - s->type = COMEDI_SUBD_PROC; -#endif + s->insn_read = dt3k_mem_insn_read; return 0; } @@ -765,5 +747,5 @@ static struct pci_driver dt3000_pci_driver = { module_comedi_pci_driver(dt3000_driver, dt3000_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for Data Translation DT3000 series boards"); MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/staging/comedi/drivers/dt9812.c b/kernel/drivers/staging/comedi/drivers/dt9812.c index e11c216a4..3295bb4ac 100644 --- a/kernel/drivers/staging/comedi/drivers/dt9812.c +++ b/kernel/drivers/staging/comedi/drivers/dt9812.c @@ -18,17 +18,17 @@ */ /* -Driver: dt9812 -Description: Data Translation DT9812 USB module -Author: anders.blomdell@control.lth.se (Anders Blomdell) -Status: in development -Devices: [Data Translation] DT9812 (dt9812) -Updated: Sun Nov 20 20:18:34 EST 2005 - -This driver works, but bulk transfers not implemented. Might be a starting point -for someone else. I found out too late that USB has too high latencies (>1 ms) -for my needs. -*/ + * Driver: dt9812 + * Description: Data Translation DT9812 USB module + * Devices: [Data Translation] DT9812 (dt9812) + * Author: anders.blomdell@control.lth.se (Anders Blomdell) + * Status: in development + * Updated: Sun Nov 20 20:18:34 EST 2005 + * + * This driver works, but bulk transfers not implemented. Might be a + * starting point for someone else. I found out too late that USB has + * too high latencies (>1 ms) for my needs. + */ /* * Nota Bene: @@ -80,7 +80,7 @@ for my needs. #define F020_MASK_ADC0CN_AD0INT 0x20 #define F020_MASK_ADC0CN_AD0BUSY 0x10 -#define F020_MASK_DACxCN_DACxEN 0x80 +#define F020_MASK_DACXCN_DACXEN 0x80 enum { /* A/D D/A DI DO CT */ @@ -233,7 +233,7 @@ struct dt9812_usb_cmd { }; struct dt9812_private { - struct semaphore sem; + struct mutex mut; struct { __u8 addr; size_t size; @@ -335,7 +335,7 @@ static int dt9812_digital_in(struct comedi_device *dev, u8 *bits) u8 value[2]; int ret; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); ret = dt9812_read_multiple_registers(dev, 2, reg, value); if (ret == 0) { /* @@ -345,7 +345,7 @@ static int dt9812_digital_in(struct comedi_device *dev, u8 *bits) */ *bits = (value[0] & 0x7f) | ((value[1] & 0x08) << 4); } - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } @@ -357,9 +357,9 @@ static int dt9812_digital_out(struct comedi_device *dev, u8 bits) u8 value[1] = { bits }; int ret; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); ret = dt9812_write_multiple_registers(dev, 1, reg, value); - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } @@ -444,7 +444,7 @@ static int dt9812_analog_in(struct comedi_device *dev, u8 val[3]; int ret; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); /* 1 select the gain */ dt9812_configure_gain(dev, &rmw[0], gain); @@ -493,7 +493,7 @@ static int dt9812_analog_in(struct comedi_device *dev, } exit: - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } @@ -504,22 +504,21 @@ static int dt9812_analog_out(struct comedi_device *dev, int channel, u16 value) struct dt9812_rmw_byte rmw[3]; int ret; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); switch (channel) { case 0: /* 1. Set DAC mode */ rmw[0].address = F020_SFR_DAC0CN; rmw[0].and_mask = 0xff; - rmw[0].or_value = F020_MASK_DACxCN_DACxEN; + rmw[0].or_value = F020_MASK_DACXCN_DACXEN; - /* 2 load low byte of DAC value first */ + /* 2. load lsb of DAC value first */ rmw[1].address = F020_SFR_DAC0L; rmw[1].and_mask = 0xff; rmw[1].or_value = value & 0xff; - /* 3 load high byte of DAC value next to latch the - 12-bit value */ + /* 3. load msb of DAC value next to latch the 12-bit value */ rmw[2].address = F020_SFR_DAC0H; rmw[2].and_mask = 0xff; rmw[2].or_value = (value >> 8) & 0xf; @@ -529,15 +528,14 @@ static int dt9812_analog_out(struct comedi_device *dev, int channel, u16 value) /* 1. Set DAC mode */ rmw[0].address = F020_SFR_DAC1CN; rmw[0].and_mask = 0xff; - rmw[0].or_value = F020_MASK_DACxCN_DACxEN; + rmw[0].or_value = F020_MASK_DACXCN_DACXEN; - /* 2 load low byte of DAC value first */ + /* 2. load lsb of DAC value first */ rmw[1].address = F020_SFR_DAC1L; rmw[1].and_mask = 0xff; rmw[1].or_value = value & 0xff; - /* 3 load high byte of DAC value next to latch the - 12-bit value */ + /* 3. load msb of DAC value next to latch the 12-bit value */ rmw[2].address = F020_SFR_DAC1H; rmw[2].and_mask = 0xff; rmw[2].or_value = (value >> 8) & 0xf; @@ -545,7 +543,7 @@ static int dt9812_analog_out(struct comedi_device *dev, int channel, u16 value) } ret = dt9812_rmw_multiple_registers(dev, 3, rmw); - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } @@ -608,9 +606,9 @@ static int dt9812_ao_insn_read(struct comedi_device *dev, struct dt9812_private *devpriv = dev->private; int ret; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); ret = comedi_readback_insn_read(dev, s, insn, data); - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } @@ -774,7 +772,7 @@ static int dt9812_auto_attach(struct comedi_device *dev, if (!devpriv) return -ENOMEM; - sema_init(&devpriv->sem, 1); + mutex_init(&devpriv->mut); usb_set_intfdata(intf, devpriv); ret = dt9812_find_endpoints(dev); @@ -846,11 +844,11 @@ static void dt9812_detach(struct comedi_device *dev) if (!devpriv) return; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); usb_set_intfdata(intf, NULL); - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); } static struct comedi_driver dt9812_driver = { diff --git a/kernel/drivers/staging/comedi/drivers/fl512.c b/kernel/drivers/staging/comedi/drivers/fl512.c index e1f493241..0f278ffda 100644 --- a/kernel/drivers/staging/comedi/drivers/fl512.c +++ b/kernel/drivers/staging/comedi/drivers/fl512.c @@ -71,7 +71,7 @@ static int fl512_ai_insn_read(struct comedi_device *dev, outb(0, dev->iobase + FL512_AI_START_CONV_REG); /* XXX should test "done" flag instead of delay */ - udelay(30); + usleep_range(30, 100); val = inb(dev->iobase + FL512_AI_LSB_REG); val |= (inb(dev->iobase + FL512_AI_MSB_REG) << 8); @@ -136,11 +136,7 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->range_table = &range_fl512; s->insn_write = fl512_ao_insn_write; - ret = comedi_alloc_subdev_readback(s); - if (ret) - return ret; - - return 0; + return comedi_alloc_subdev_readback(s); } static struct comedi_driver fl512_driver = { diff --git a/kernel/drivers/staging/comedi/drivers/gsc_hpdi.c b/kernel/drivers/staging/comedi/drivers/gsc_hpdi.c index 3cb6409c4..46ca5d938 100644 --- a/kernel/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/kernel/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -52,45 +52,45 @@ * PCI BAR2 Register map (dev->mmio) */ #define FIRMWARE_REV_REG 0x00 -#define FEATURES_REG_PRESENT_BIT (1 << 15) +#define FEATURES_REG_PRESENT_BIT BIT(15) #define BOARD_CONTROL_REG 0x04 -#define BOARD_RESET_BIT (1 << 0) -#define TX_FIFO_RESET_BIT (1 << 1) -#define RX_FIFO_RESET_BIT (1 << 2) -#define TX_ENABLE_BIT (1 << 4) -#define RX_ENABLE_BIT (1 << 5) -#define DEMAND_DMA_DIRECTION_TX_BIT (1 << 6) /* ch 0 only */ -#define LINE_VALID_ON_STATUS_VALID_BIT (1 << 7) -#define START_TX_BIT (1 << 8) -#define CABLE_THROTTLE_ENABLE_BIT (1 << 9) -#define TEST_MODE_ENABLE_BIT (1 << 31) +#define BOARD_RESET_BIT BIT(0) +#define TX_FIFO_RESET_BIT BIT(1) +#define RX_FIFO_RESET_BIT BIT(2) +#define TX_ENABLE_BIT BIT(4) +#define RX_ENABLE_BIT BIT(5) +#define DEMAND_DMA_DIRECTION_TX_BIT BIT(6) /* ch 0 only */ +#define LINE_VALID_ON_STATUS_VALID_BIT BIT(7) +#define START_TX_BIT BIT(8) +#define CABLE_THROTTLE_ENABLE_BIT BIT(9) +#define TEST_MODE_ENABLE_BIT BIT(31) #define BOARD_STATUS_REG 0x08 #define COMMAND_LINE_STATUS_MASK (0x7f << 0) -#define TX_IN_PROGRESS_BIT (1 << 7) -#define TX_NOT_EMPTY_BIT (1 << 8) -#define TX_NOT_ALMOST_EMPTY_BIT (1 << 9) -#define TX_NOT_ALMOST_FULL_BIT (1 << 10) -#define TX_NOT_FULL_BIT (1 << 11) -#define RX_NOT_EMPTY_BIT (1 << 12) -#define RX_NOT_ALMOST_EMPTY_BIT (1 << 13) -#define RX_NOT_ALMOST_FULL_BIT (1 << 14) -#define RX_NOT_FULL_BIT (1 << 15) -#define BOARD_JUMPER0_INSTALLED_BIT (1 << 16) -#define BOARD_JUMPER1_INSTALLED_BIT (1 << 17) -#define TX_OVERRUN_BIT (1 << 21) -#define RX_UNDERRUN_BIT (1 << 22) -#define RX_OVERRUN_BIT (1 << 23) +#define TX_IN_PROGRESS_BIT BIT(7) +#define TX_NOT_EMPTY_BIT BIT(8) +#define TX_NOT_ALMOST_EMPTY_BIT BIT(9) +#define TX_NOT_ALMOST_FULL_BIT BIT(10) +#define TX_NOT_FULL_BIT BIT(11) +#define RX_NOT_EMPTY_BIT BIT(12) +#define RX_NOT_ALMOST_EMPTY_BIT BIT(13) +#define RX_NOT_ALMOST_FULL_BIT BIT(14) +#define RX_NOT_FULL_BIT BIT(15) +#define BOARD_JUMPER0_INSTALLED_BIT BIT(16) +#define BOARD_JUMPER1_INSTALLED_BIT BIT(17) +#define TX_OVERRUN_BIT BIT(21) +#define RX_UNDERRUN_BIT BIT(22) +#define RX_OVERRUN_BIT BIT(23) #define TX_PROG_ALMOST_REG 0x0c #define RX_PROG_ALMOST_REG 0x10 #define ALMOST_EMPTY_BITS(x) (((x) & 0xffff) << 0) #define ALMOST_FULL_BITS(x) (((x) & 0xff) << 16) #define FEATURES_REG 0x14 -#define FIFO_SIZE_PRESENT_BIT (1 << 0) -#define FIFO_WORDS_PRESENT_BIT (1 << 1) -#define LEVEL_EDGE_INTERRUPTS_PRESENT_BIT (1 << 2) -#define GPIO_SUPPORTED_BIT (1 << 3) -#define PLX_DMA_CH1_SUPPORTED_BIT (1 << 4) -#define OVERRUN_UNDERRUN_SUPPORTED_BIT (1 << 5) +#define FIFO_SIZE_PRESENT_BIT BIT(0) +#define FIFO_WORDS_PRESENT_BIT BIT(1) +#define LEVEL_EDGE_INTERRUPTS_PRESENT_BIT BIT(2) +#define GPIO_SUPPORTED_BIT BIT(3) +#define PLX_DMA_CH1_SUPPORTED_BIT BIT(4) +#define OVERRUN_UNDERRUN_SUPPORTED_BIT BIT(5) #define FIFO_REG 0x18 #define TX_STATUS_COUNT_REG 0x1c #define TX_LINE_VALID_COUNT_REG 0x20, @@ -98,16 +98,16 @@ #define RX_STATUS_COUNT_REG 0x28 #define RX_LINE_COUNT_REG 0x2c #define INTERRUPT_CONTROL_REG 0x30 -#define FRAME_VALID_START_INTR (1 << 0) -#define FRAME_VALID_END_INTR (1 << 1) -#define TX_FIFO_EMPTY_INTR (1 << 8) -#define TX_FIFO_ALMOST_EMPTY_INTR (1 << 9) -#define TX_FIFO_ALMOST_FULL_INTR (1 << 10) -#define TX_FIFO_FULL_INTR (1 << 11) -#define RX_EMPTY_INTR (1 << 12) -#define RX_ALMOST_EMPTY_INTR (1 << 13) -#define RX_ALMOST_FULL_INTR (1 << 14) -#define RX_FULL_INTR (1 << 15) +#define FRAME_VALID_START_INTR BIT(0) +#define FRAME_VALID_END_INTR BIT(1) +#define TX_FIFO_EMPTY_INTR BIT(8) +#define TX_FIFO_ALMOST_EMPTY_INTR BIT(9) +#define TX_FIFO_ALMOST_FULL_INTR BIT(10) +#define TX_FIFO_FULL_INTR BIT(11) +#define RX_EMPTY_INTR BIT(12) +#define RX_ALMOST_EMPTY_INTR BIT(13) +#define RX_ALMOST_FULL_INTR BIT(14) +#define RX_FULL_INTR BIT(15) #define INTERRUPT_STATUS_REG 0x34 #define TX_CLOCK_DIVIDER_REG 0x38 #define TX_FIFO_SIZE_REG 0x40 @@ -123,40 +123,21 @@ #define NUM_DMA_BUFFERS 4 #define NUM_DMA_DESCRIPTORS 256 -struct hpdi_board { - const char *name; - int device_id; - int subdevice_id; -}; - -static const struct hpdi_board hpdi_boards[] = { - { - .name = "pci-hpdi32", - .device_id = PCI_DEVICE_ID_PLX_9080, - .subdevice_id = 0x2400, - }, -#if 0 - { - .name = "pxi-hpdi32", - .device_id = 0x9656, - .subdevice_id = 0x2705, - }, -#endif -}; - struct hpdi_private { void __iomem *plx9080_mmio; - uint32_t *dio_buffer[NUM_DMA_BUFFERS]; /* dma buffers */ + u32 *dio_buffer[NUM_DMA_BUFFERS]; /* dma buffers */ /* physical addresses of dma buffers */ dma_addr_t dio_buffer_phys_addr[NUM_DMA_BUFFERS]; - /* array of dma descriptors read by plx9080, allocated to get proper - * alignment */ + /* + * array of dma descriptors read by plx9080, allocated to get proper + * alignment + */ struct plx_dma_desc *dma_desc; /* physical address of dma descriptor array */ dma_addr_t dma_desc_phys_addr; unsigned int num_dma_descriptors; /* pointer to start of buffers indexed by descriptor */ - uint32_t *desc_dio_buffer[NUM_DMA_DESCRIPTORS]; + u32 *desc_dio_buffer[NUM_DMA_DESCRIPTORS]; /* index of the dma descriptor that is currently being used */ unsigned int dma_desc_index; unsigned int tx_fifo_size; @@ -188,7 +169,7 @@ static void gsc_hpdi_drain_dma(struct comedi_device *dev, unsigned int channel) for (desc = 0; (next < start || next >= start + devpriv->block_size) && desc < devpriv->num_dma_descriptors; desc++) { /* transfer data from dma buffer to comedi buffer */ - size = devpriv->block_size / sizeof(uint32_t); + size = devpriv->block_size / sizeof(u32); if (cmd->stop_src == TRIG_COUNT) { if (size > devpriv->dio_count) size = devpriv->dio_count; @@ -202,7 +183,7 @@ static void gsc_hpdi_drain_dma(struct comedi_device *dev, unsigned int channel) devpriv->dma_desc_index = idx; } - /* XXX check for buffer overrun somehow */ + /* XXX check for buffer overrun somehow */ } static irqreturn_t gsc_hpdi_interrupt(int irq, void *d) @@ -211,10 +192,10 @@ static irqreturn_t gsc_hpdi_interrupt(int irq, void *d) struct hpdi_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; - uint32_t hpdi_intr_status, hpdi_board_status; - uint32_t plx_status; - uint32_t plx_bits; - uint8_t dma0_status, dma1_status; + u32 hpdi_intr_status, hpdi_board_status; + u32 plx_status; + u32 plx_bits; + u8 dma0_status, dma1_status; unsigned long flags; if (!dev->attached) @@ -230,10 +211,11 @@ static irqreturn_t gsc_hpdi_interrupt(int irq, void *d) if (hpdi_intr_status) writel(hpdi_intr_status, dev->mmio + INTERRUPT_STATUS_REG); - /* spin lock makes sure no one else changes plx dma control reg */ + /* spin lock makes sure no one else changes plx dma control reg */ spin_lock_irqsave(&dev->spinlock, flags); dma0_status = readb(devpriv->plx9080_mmio + PLX_DMA0_CS_REG); - if (plx_status & ICS_DMA0_A) { /* dma chan 0 interrupt */ + if (plx_status & ICS_DMA0_A) { + /* dma chan 0 interrupt */ writeb((dma0_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT, devpriv->plx9080_mmio + PLX_DMA0_CS_REG); @@ -242,17 +224,19 @@ static irqreturn_t gsc_hpdi_interrupt(int irq, void *d) } spin_unlock_irqrestore(&dev->spinlock, flags); - /* spin lock makes sure no one else changes plx dma control reg */ + /* spin lock makes sure no one else changes plx dma control reg */ spin_lock_irqsave(&dev->spinlock, flags); dma1_status = readb(devpriv->plx9080_mmio + PLX_DMA1_CS_REG); - if (plx_status & ICS_DMA1_A) { /* XXX *//* dma chan 1 interrupt */ + if (plx_status & ICS_DMA1_A) { + /* XXX */ /* dma chan 1 interrupt */ writeb((dma1_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT, devpriv->plx9080_mmio + PLX_DMA1_CS_REG); } spin_unlock_irqrestore(&dev->spinlock, flags); - /* clear possible plx9080 interrupt sources */ - if (plx_status & ICS_LDIA) { /* clear local doorbell interrupt */ + /* clear possible plx9080 interrupt sources */ + if (plx_status & ICS_LDIA) { + /* clear local doorbell interrupt */ plx_bits = readl(devpriv->plx9080_mmio + PLX_DBR_OUT_REG); writel(plx_bits, devpriv->plx9080_mmio + PLX_DBR_OUT_REG); } @@ -280,7 +264,7 @@ static void gsc_hpdi_abort_dma(struct comedi_device *dev, unsigned int channel) struct hpdi_private *devpriv = dev->private; unsigned long flags; - /* spinlock for plx dma control/status reg */ + /* spinlock for plx dma control/status reg */ spin_lock_irqsave(&dev->spinlock, flags); plx9080_abort_dma(devpriv->plx9080_mmio, channel); @@ -306,7 +290,7 @@ static int gsc_hpdi_cmd(struct comedi_device *dev, struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; unsigned long flags; - uint32_t bits; + u32 bits; if (s->io_bits) return -EINVAL; @@ -440,15 +424,15 @@ static int gsc_hpdi_setup_dma_descriptors(struct comedi_device *dev, { struct hpdi_private *devpriv = dev->private; dma_addr_t phys_addr = devpriv->dma_desc_phys_addr; - uint32_t next_bits = PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT | - PLX_XFER_LOCAL_TO_PCI; + u32 next_bits = PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT | + PLX_XFER_LOCAL_TO_PCI; unsigned int offset = 0; unsigned int idx = 0; unsigned int i; if (len > DMA_BUFFER_SIZE) len = DMA_BUFFER_SIZE; - len -= len % sizeof(uint32_t); + len -= len % sizeof(u32); if (len == 0) return -EINVAL; @@ -461,7 +445,7 @@ static int gsc_hpdi_setup_dma_descriptors(struct comedi_device *dev, (i + 1) * sizeof(devpriv->dma_desc[0])) | next_bits); devpriv->desc_dio_buffer[i] = devpriv->dio_buffer[idx] + - (offset / sizeof(uint32_t)); + (offset / sizeof(u32)); offset += len; if (len + offset > DMA_BUFFER_SIZE) { @@ -532,11 +516,11 @@ static void gsc_hpdi_free_dma(struct comedi_device *dev) static int gsc_hpdi_init(struct comedi_device *dev) { struct hpdi_private *devpriv = dev->private; - uint32_t plx_intcsr_bits; + u32 plx_intcsr_bits; /* wait 10usec after reset before accessing fifos */ writel(BOARD_RESET_BIT, dev->mmio + BOARD_CONTROL_REG); - udelay(10); + usleep_range(10, 1000); writel(ALMOST_EMPTY_BITS(32) | ALMOST_FULL_BITS(32), dev->mmio + RX_PROG_ALMOST_REG); @@ -550,7 +534,7 @@ static int gsc_hpdi_init(struct comedi_device *dev) writel(0, dev->mmio + INTERRUPT_CONTROL_REG); - /* enable interrupts */ + /* enable interrupts */ plx_intcsr_bits = ICS_AERR | ICS_PERR | ICS_PIE | ICS_PLIE | ICS_PAIE | ICS_LIE | ICS_DMA0_E; @@ -562,7 +546,7 @@ static int gsc_hpdi_init(struct comedi_device *dev) static void gsc_hpdi_init_plx9080(struct comedi_device *dev) { struct hpdi_private *devpriv = dev->private; - uint32_t bits; + u32 bits; void __iomem *plx_iobase = devpriv->plx9080_mmio; #ifdef __BIG_ENDIAN @@ -577,57 +561,42 @@ static void gsc_hpdi_init_plx9080(struct comedi_device *dev) gsc_hpdi_abort_dma(dev, 0); gsc_hpdi_abort_dma(dev, 1); - /* configure dma0 mode */ + /* configure dma0 mode */ bits = 0; - /* enable ready input */ + /* enable ready input */ bits |= PLX_DMA_EN_READYIN_BIT; - /* enable dma chaining */ + /* enable dma chaining */ bits |= PLX_EN_CHAIN_BIT; - /* enable interrupt on dma done - * (probably don't need this, since chain never finishes) */ + /* + * enable interrupt on dma done + * (probably don't need this, since chain never finishes) + */ bits |= PLX_EN_DMA_DONE_INTR_BIT; - /* don't increment local address during transfers - * (we are transferring from a fixed fifo register) */ + /* + * don't increment local address during transfers + * (we are transferring from a fixed fifo register) + */ bits |= PLX_LOCAL_ADDR_CONST_BIT; - /* route dma interrupt to pci bus */ + /* route dma interrupt to pci bus */ bits |= PLX_DMA_INTR_PCI_BIT; - /* enable demand mode */ + /* enable demand mode */ bits |= PLX_DEMAND_MODE_BIT; - /* enable local burst mode */ + /* enable local burst mode */ bits |= PLX_DMA_LOCAL_BURST_EN_BIT; bits |= PLX_LOCAL_BUS_32_WIDE_BITS; writel(bits, plx_iobase + PLX_DMA0_MODE_REG); } -static const struct hpdi_board *gsc_hpdi_find_board(struct pci_dev *pcidev) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(hpdi_boards); i++) - if (pcidev->device == hpdi_boards[i].device_id && - pcidev->subsystem_device == hpdi_boards[i].subdevice_id) - return &hpdi_boards[i]; - return NULL; -} - static int gsc_hpdi_auto_attach(struct comedi_device *dev, unsigned long context_unused) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct hpdi_board *thisboard; struct hpdi_private *devpriv; struct comedi_subdevice *s; int i; int retval; - thisboard = gsc_hpdi_find_board(pcidev); - if (!thisboard) { - dev_err(dev->class_dev, "gsc_hpdi: pci %s not supported\n", - pci_name(pcidev)); - return -EINVAL; - } - dev->board_ptr = thisboard; - dev->board_name = thisboard->name; + dev->board_name = "pci-hpdi32"; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -647,7 +616,7 @@ static int gsc_hpdi_auto_attach(struct comedi_device *dev, gsc_hpdi_init_plx9080(dev); - /* get irq */ + /* get irq */ if (request_irq(pcidev->irq, gsc_hpdi_interrupt, IRQF_SHARED, dev->board_name, dev)) { dev_warn(dev->class_dev, @@ -658,13 +627,13 @@ static int gsc_hpdi_auto_attach(struct comedi_device *dev, dev_dbg(dev->class_dev, " irq %u\n", dev->irq); - /* allocate pci dma buffers */ + /* allocate pci dma buffers */ for (i = 0; i < NUM_DMA_BUFFERS; i++) { devpriv->dio_buffer[i] = pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE, &devpriv->dio_buffer_phys_addr[i]); } - /* allocate dma descriptors */ + /* allocate dma descriptors */ devpriv->dma_desc = pci_alloc_consistent(pcidev, sizeof(struct plx_dma_desc) * NUM_DMA_DESCRIPTORS, @@ -733,8 +702,8 @@ static int gsc_hpdi_pci_probe(struct pci_dev *dev, } static const struct pci_device_id gsc_hpdi_pci_table[] = { - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9080, PCI_VENDOR_ID_PLX, - 0x2400, 0, 0, 0}, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9080, + PCI_VENDOR_ID_PLX, 0x2400) }, { 0 } }; MODULE_DEVICE_TABLE(pci, gsc_hpdi_pci_table); @@ -748,5 +717,5 @@ static struct pci_driver gsc_hpdi_pci_driver = { module_comedi_pci_driver(gsc_hpdi_driver, gsc_hpdi_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for General Standards PCI-HPDI32/PMC-HPDI32"); MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/staging/comedi/drivers/icp_multi.c b/kernel/drivers/staging/comedi/drivers/icp_multi.c index 1e104ebf8..28cf53e48 100644 --- a/kernel/drivers/staging/comedi/drivers/icp_multi.c +++ b/kernel/drivers/staging/comedi/drivers/icp_multi.c @@ -1,94 +1,89 @@ /* - comedi/drivers/icp_multi.c - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-2002 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * icp_multi.c + * Comedi driver for Inova ICP_MULTI board + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2002 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ /* -Driver: icp_multi -Description: Inova ICP_MULTI -Author: Anne Smorthit <anne.smorthit@sfwte.ch> -Devices: [Inova] ICP_MULTI (icp_multi) -Status: works - -The driver works for analog input and output and digital input and output. -It does not work with interrupts or with the counters. Currently no support -for DMA. - -It has 16 single-ended or 8 differential Analogue Input channels with 12-bit -resolution. Ranges : 5V, 10V, +/-5V, +/-10V, 0..20mA and 4..20mA. Input -ranges can be individually programmed for each channel. Voltage or current -measurement is selected by jumper. - -There are 4 x 12-bit Analogue Outputs. Ranges : 5V, 10V, +/-5V, +/-10V - -16 x Digital Inputs, 24V - -8 x Digital Outputs, 24V, 1A - -4 x 16-bit counters - -Configuration options: not applicable, uses PCI auto config -*/ + * Driver: icp_multi + * Description: Inova ICP_MULTI + * Devices: [Inova] ICP_MULTI (icp_multi) + * Author: Anne Smorthit <anne.smorthit@sfwte.ch> + * Status: works + * + * Configuration options: not applicable, uses PCI auto config + * + * The driver works for analog input and output and digital input and + * output. It does not work with interrupts or with the counters. Currently + * no support for DMA. + * + * It has 16 single-ended or 8 differential Analogue Input channels with + * 12-bit resolution. Ranges : 5V, 10V, +/-5V, +/-10V, 0..20mA and 4..20mA. + * Input ranges can be individually programmed for each channel. Voltage or + * current measurement is selected by jumper. + * + * There are 4 x 12-bit Analogue Outputs. Ranges : 5V, 10V, +/-5V, +/-10V + * + * 16 x Digital Inputs, 24V + * + * 8 x Digital Outputs, 24V, 1A + * + * 4 x 16-bit counters - not implemented + */ #include <linux/module.h> #include <linux/delay.h> -#include <linux/interrupt.h> #include "../comedi_pci.h" -#define ICP_MULTI_ADC_CSR 0 /* R/W: ADC command/status register */ +#define ICP_MULTI_ADC_CSR 0x00 /* R/W: ADC command/status register */ +#define ICP_MULTI_ADC_CSR_ST BIT(0) /* Start ADC */ +#define ICP_MULTI_ADC_CSR_BSY BIT(0) /* ADC busy */ +#define ICP_MULTI_ADC_CSR_BI BIT(4) /* Bipolar input range */ +#define ICP_MULTI_ADC_CSR_RA BIT(5) /* Input range 0 = 5V, 1 = 10V */ +#define ICP_MULTI_ADC_CSR_DI BIT(6) /* Input mode 1 = differential */ +#define ICP_MULTI_ADC_CSR_DI_CHAN(x) (((x) & 0x7) << 9) +#define ICP_MULTI_ADC_CSR_SE_CHAN(x) (((x) & 0xf) << 8) #define ICP_MULTI_AI 2 /* R: Analogue input data */ -#define ICP_MULTI_DAC_CSR 4 /* R/W: DAC command/status register */ +#define ICP_MULTI_DAC_CSR 0x04 /* R/W: DAC command/status register */ +#define ICP_MULTI_DAC_CSR_ST BIT(0) /* Start DAC */ +#define ICP_MULTI_DAC_CSR_BSY BIT(0) /* DAC busy */ +#define ICP_MULTI_DAC_CSR_BI BIT(4) /* Bipolar output range */ +#define ICP_MULTI_DAC_CSR_RA BIT(5) /* Output range 0 = 5V, 1 = 10V */ +#define ICP_MULTI_DAC_CSR_CHAN(x) (((x) & 0x3) << 8) #define ICP_MULTI_AO 6 /* R/W: Analogue output data */ #define ICP_MULTI_DI 8 /* R/W: Digital inputs */ #define ICP_MULTI_DO 0x0A /* R/W: Digital outputs */ -#define ICP_MULTI_INT_EN 0x0C /* R/W: Interrupt enable register */ -#define ICP_MULTI_INT_STAT 0x0E /* R/W: Interrupt status register */ +#define ICP_MULTI_INT_EN 0x0c /* R/W: Interrupt enable register */ +#define ICP_MULTI_INT_STAT 0x0e /* R/W: Interrupt status register */ +#define ICP_MULTI_INT_ADC_RDY BIT(0) /* A/D conversion ready interrupt */ +#define ICP_MULTI_INT_DAC_RDY BIT(1) /* D/A conversion ready interrupt */ +#define ICP_MULTI_INT_DOUT_ERR BIT(2) /* Digital output error interrupt */ +#define ICP_MULTI_INT_DIN_STAT BIT(3) /* Digital input status change int. */ +#define ICP_MULTI_INT_CIE0 BIT(4) /* Counter 0 overrun interrupt */ +#define ICP_MULTI_INT_CIE1 BIT(5) /* Counter 1 overrun interrupt */ +#define ICP_MULTI_INT_CIE2 BIT(6) /* Counter 2 overrun interrupt */ +#define ICP_MULTI_INT_CIE3 BIT(7) /* Counter 3 overrun interrupt */ +#define ICP_MULTI_INT_MASK 0xff /* All interrupts */ #define ICP_MULTI_CNTR0 0x10 /* R/W: Counter 0 */ #define ICP_MULTI_CNTR1 0x12 /* R/W: counter 1 */ #define ICP_MULTI_CNTR2 0x14 /* R/W: Counter 2 */ #define ICP_MULTI_CNTR3 0x16 /* R/W: Counter 3 */ -/* Define bits from ADC command/status register */ -#define ADC_ST 0x0001 /* Start ADC */ -#define ADC_BSY 0x0001 /* ADC busy */ -#define ADC_BI 0x0010 /* Bipolar input range 1 = bipolar */ -#define ADC_RA 0x0020 /* Input range 0 = 5V, 1 = 10V */ -#define ADC_DI 0x0040 /* Differential input mode 1 = differential */ - -/* Define bits from DAC command/status register */ -#define DAC_ST 0x0001 /* Start DAC */ -#define DAC_BSY 0x0001 /* DAC busy */ -#define DAC_BI 0x0010 /* Bipolar input range 1 = bipolar */ -#define DAC_RA 0x0020 /* Input range 0 = 5V, 1 = 10V */ - -/* Define bits from interrupt enable/status registers */ -#define ADC_READY 0x0001 /* A/d conversion ready interrupt */ -#define DAC_READY 0x0002 /* D/a conversion ready interrupt */ -#define DOUT_ERROR 0x0004 /* Digital output error interrupt */ -#define DIN_STATUS 0x0008 /* Digital input status change interrupt */ -#define CIE0 0x0010 /* Counter 0 overrun interrupt */ -#define CIE1 0x0020 /* Counter 1 overrun interrupt */ -#define CIE2 0x0040 /* Counter 2 overrun interrupt */ -#define CIE3 0x0080 /* Counter 3 overrun interrupt */ - -/* Useful definitions */ -#define Status_IRQ 0x00ff /* All interrupts */ - -/* Define analogue range */ -static const struct comedi_lrange range_analog = { +/* analog input and output have the same range options */ +static const struct comedi_lrange icp_multi_ranges = { 4, { UNI_RANGE(5), UNI_RANGE(10), @@ -99,71 +94,6 @@ static const struct comedi_lrange range_analog = { static const char range_codes_analog[] = { 0x00, 0x20, 0x10, 0x30 }; -/* -============================================================================== - Data & Structure declarations -============================================================================== -*/ - -struct icp_multi_private { - unsigned int AdcCmdStatus; /* ADC Command/Status register */ - unsigned int DacCmdStatus; /* DAC Command/Status register */ - unsigned int IntEnable; /* Interrupt Enable register */ - unsigned int IntStatus; /* Interrupt Status register */ - 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 int *ai_chanlist; /* actaul chanlist */ - unsigned int do_data; /* Remember digital output data */ -}; - -static void setup_channel_list(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int *chanlist, unsigned int n_chan) -{ - struct icp_multi_private *devpriv = dev->private; - unsigned int i, range, chanprog; - unsigned int diff; - - devpriv->act_chanlist_len = n_chan; - devpriv->act_chanlist_pos = 0; - - for (i = 0; i < n_chan; i++) { - /* Get channel */ - chanprog = CR_CHAN(chanlist[i]); - - /* Determine if it is a differential channel (Bit 15 = 1) */ - if (CR_AREF(chanlist[i]) == AREF_DIFF) { - diff = 1; - chanprog &= 0x0007; - } else { - diff = 0; - chanprog &= 0x000f; - } - - /* Clear channel, range and input mode bits - * in A/D command/status register */ - devpriv->AdcCmdStatus &= 0xf00f; - - /* Set channel number and differential mode status bit */ - if (diff) { - /* Set channel number, bits 9-11 & mode, bit 6 */ - devpriv->AdcCmdStatus |= (chanprog << 9); - devpriv->AdcCmdStatus |= ADC_DI; - } else - /* Set channel number, bits 8-11 */ - devpriv->AdcCmdStatus |= (chanprog << 8); - - /* Get range for current channel */ - range = range_codes_analog[CR_RANGE(chanlist[i])]; - /* Set range. bits 4-5 */ - devpriv->AdcCmdStatus |= range; - - /* Output channel, range, mode to ICP Multi */ - writew(devpriv->AdcCmdStatus, dev->mmio + ICP_MULTI_ADC_CSR); - } -} - static int icp_multi_ai_eoc(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -172,36 +102,37 @@ static int icp_multi_ai_eoc(struct comedi_device *dev, unsigned int status; status = readw(dev->mmio + ICP_MULTI_ADC_CSR); - if ((status & ADC_BSY) == 0) + if ((status & ICP_MULTI_ADC_CSR_BSY) == 0) return 0; return -EBUSY; } -static int icp_multi_insn_read_ai(struct comedi_device *dev, +static int icp_multi_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct icp_multi_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); + unsigned int aref = CR_AREF(insn->chanspec); + unsigned int adc_csr; int ret = 0; int n; - /* Disable A/D conversion ready interrupt */ - devpriv->IntEnable &= ~ADC_READY; - writew(devpriv->IntEnable, dev->mmio + ICP_MULTI_INT_EN); - - /* Clear interrupt status */ - devpriv->IntStatus |= ADC_READY; - writew(devpriv->IntStatus, dev->mmio + ICP_MULTI_INT_STAT); - - /* Set up appropriate channel, mode and range data, for specified ch */ - setup_channel_list(dev, s, &insn->chanspec, 1); + /* Set mode and range data for specified channel */ + if (aref == AREF_DIFF) { + adc_csr = ICP_MULTI_ADC_CSR_DI_CHAN(chan) | + ICP_MULTI_ADC_CSR_DI; + } else { + adc_csr = ICP_MULTI_ADC_CSR_SE_CHAN(chan); + } + adc_csr |= range_codes_analog[range]; + writew(adc_csr, dev->mmio + ICP_MULTI_ADC_CSR); for (n = 0; n < insn->n; n++) { /* Set start ADC bit */ - devpriv->AdcCmdStatus |= ADC_ST; - writew(devpriv->AdcCmdStatus, dev->mmio + ICP_MULTI_ADC_CSR); - devpriv->AdcCmdStatus &= ~ADC_ST; + writew(adc_csr | ICP_MULTI_ADC_CSR_ST, + dev->mmio + ICP_MULTI_ADC_CSR); udelay(1); @@ -213,26 +144,18 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev, data[n] = (readw(dev->mmio + ICP_MULTI_AI) >> 4) & 0x0fff; } - /* Disable interrupt */ - devpriv->IntEnable &= ~ADC_READY; - writew(devpriv->IntEnable, dev->mmio + ICP_MULTI_INT_EN); - - /* Clear interrupt status */ - devpriv->IntStatus |= ADC_READY; - writew(devpriv->IntStatus, dev->mmio + ICP_MULTI_INT_STAT); - return ret ? ret : n; } -static int icp_multi_ao_eoc(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned long context) +static int icp_multi_ao_ready(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned long context) { unsigned int status; status = readw(dev->mmio + ICP_MULTI_DAC_CSR); - if ((status & DAC_BSY) == 0) + if ((status & ICP_MULTI_DAC_CSR_BSY) == 0) return 0; return -EBUSY; } @@ -242,57 +165,30 @@ static int icp_multi_ao_insn_write(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct icp_multi_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); unsigned int range = CR_RANGE(insn->chanspec); + unsigned int dac_csr; int i; - /* Disable D/A conversion ready interrupt */ - devpriv->IntEnable &= ~DAC_READY; - writew(devpriv->IntEnable, dev->mmio + ICP_MULTI_INT_EN); - - /* Clear interrupt status */ - devpriv->IntStatus |= DAC_READY; - writew(devpriv->IntStatus, dev->mmio + ICP_MULTI_INT_STAT); - - /* Set up range and channel data */ - /* Bit 4 = 1 : Bipolar */ - /* Bit 5 = 0 : 5V */ - /* Bit 5 = 1 : 10V */ - /* Bits 8-9 : Channel number */ - devpriv->DacCmdStatus &= 0xfccf; - devpriv->DacCmdStatus |= range_codes_analog[range]; - devpriv->DacCmdStatus |= (chan << 8); - - writew(devpriv->DacCmdStatus, dev->mmio + ICP_MULTI_DAC_CSR); + /* Select channel and range */ + dac_csr = ICP_MULTI_DAC_CSR_CHAN(chan); + dac_csr |= range_codes_analog[range]; + writew(dac_csr, dev->mmio + ICP_MULTI_DAC_CSR); for (i = 0; i < insn->n; i++) { unsigned int val = data[i]; int ret; - /* Wait for analogue output data register to be - * ready for new data, or get fed up waiting */ - ret = comedi_timeout(dev, s, insn, icp_multi_ao_eoc, 0); - if (ret) { - /* Disable interrupt */ - devpriv->IntEnable &= ~DAC_READY; - writew(devpriv->IntEnable, - dev->mmio + ICP_MULTI_INT_EN); - - /* Clear interrupt status */ - devpriv->IntStatus |= DAC_READY; - writew(devpriv->IntStatus, - dev->mmio + ICP_MULTI_INT_STAT); - + /* Wait for analog output to be ready for new data */ + ret = comedi_timeout(dev, s, insn, icp_multi_ao_ready, 0); + if (ret) return ret; - } writew(val, dev->mmio + ICP_MULTI_AO); - /* Set DAC_ST bit to write the data to selected channel */ - devpriv->DacCmdStatus |= DAC_ST; - writew(devpriv->DacCmdStatus, dev->mmio + ICP_MULTI_DAC_CSR); - devpriv->DacCmdStatus &= ~DAC_ST; + /* Set start conversion bit to write data to channel */ + writew(dac_csr | ICP_MULTI_DAC_CSR_ST, + dev->mmio + ICP_MULTI_DAC_CSR); s->readback[chan] = val; } @@ -300,7 +196,7 @@ static int icp_multi_ao_insn_write(struct comedi_device *dev, return insn->n; } -static int icp_multi_insn_bits_di(struct comedi_device *dev, +static int icp_multi_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -310,7 +206,7 @@ static int icp_multi_insn_bits_di(struct comedi_device *dev, return insn->n; } -static int icp_multi_insn_bits_do(struct comedi_device *dev, +static int icp_multi_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -323,116 +219,27 @@ static int icp_multi_insn_bits_do(struct comedi_device *dev, return insn->n; } -static int icp_multi_insn_read_ctr(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - return 0; -} - -static int icp_multi_insn_write_ctr(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - return 0; -} - -static irqreturn_t interrupt_service_icp_multi(int irq, void *d) -{ - struct comedi_device *dev = d; - int int_no; - - /* Is this interrupt from our board? */ - int_no = readw(dev->mmio + ICP_MULTI_INT_STAT) & Status_IRQ; - if (!int_no) - /* No, exit */ - return IRQ_NONE; - - /* Determine which interrupt is active & handle it */ - switch (int_no) { - case ADC_READY: - break; - case DAC_READY: - break; - case DOUT_ERROR: - break; - case DIN_STATUS: - break; - case CIE0: - break; - case CIE1: - break; - case CIE2: - break; - case CIE3: - break; - default: - break; - } - - return IRQ_HANDLED; -} - -#if 0 -static int check_channel_list(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int *chanlist, unsigned int n_chan) -{ - unsigned int i; - - /* Check that we at least have one channel to check */ - if (n_chan < 1) { - dev_err(dev->class_dev, "range/channel list is empty!\n"); - return 0; - } - /* Check all channels */ - for (i = 0; i < n_chan; i++) { - /* Check that channel number is < maximum */ - if (CR_AREF(chanlist[i]) == AREF_DIFF) { - if (CR_CHAN(chanlist[i]) > (s->nchan / 2)) { - dev_err(dev->class_dev, - "Incorrect differential ai ch-nr\n"); - return 0; - } - } else { - if (CR_CHAN(chanlist[i]) > s->n_chan) { - dev_err(dev->class_dev, - "Incorrect ai channel number\n"); - return 0; - } - } - } - return 1; -} -#endif - static int icp_multi_reset(struct comedi_device *dev) { - struct icp_multi_private *devpriv = dev->private; - unsigned int i; + int i; - /* Clear INT enables and requests */ + /* Disable all interrupts and clear any requests */ writew(0, dev->mmio + ICP_MULTI_INT_EN); - writew(0x00ff, dev->mmio + ICP_MULTI_INT_STAT); + writew(ICP_MULTI_INT_MASK, dev->mmio + ICP_MULTI_INT_STAT); - /* Set DACs to 0..5V range and 0V output */ + /* Reset the analog output channels to 0V */ for (i = 0; i < 4; i++) { - devpriv->DacCmdStatus &= 0xfcce; + unsigned int dac_csr = ICP_MULTI_DAC_CSR_CHAN(i); - /* Set channel number */ - devpriv->DacCmdStatus |= (i << 8); + /* Select channel and 0..5V range */ + writew(dac_csr, dev->mmio + ICP_MULTI_DAC_CSR); - /* Output 0V */ + /* Output 0V */ writew(0, dev->mmio + ICP_MULTI_AO); - /* Set start conversion bit */ - devpriv->DacCmdStatus |= DAC_ST; - - /* Output to command / status register */ - writew(devpriv->DacCmdStatus, dev->mmio + ICP_MULTI_DAC_CSR); - - /* Delay to allow DAC time to recover */ + /* Set start conversion bit to write data to channel */ + writew(dac_csr | ICP_MULTI_DAC_CSR_ST, + dev->mmio + ICP_MULTI_DAC_CSR); udelay(1); } @@ -446,14 +253,9 @@ static int icp_multi_auto_attach(struct comedi_device *dev, unsigned long context_unused) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - struct icp_multi_private *devpriv; struct comedi_subdevice *s; int ret; - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) - return -ENOMEM; - ret = comedi_pci_enable(dev); if (ret) return ret; @@ -462,85 +264,60 @@ static int icp_multi_auto_attach(struct comedi_device *dev, if (!dev->mmio) return -ENOMEM; - ret = comedi_alloc_subdevices(dev, 5); + ret = comedi_alloc_subdevices(dev, 4); if (ret) return ret; icp_multi_reset(dev); - if (pcidev->irq) { - ret = request_irq(pcidev->irq, interrupt_service_icp_multi, - IRQF_SHARED, dev->board_name, dev); - if (ret == 0) - dev->irq = pcidev->irq; - } - + /* Analog Input subdevice */ s = &dev->subdevices[0]; - dev->read_subdev = s; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; - s->n_chan = 16; - s->maxdata = 0x0fff; - s->len_chanlist = 16; - s->range_table = &range_analog; - s->insn_read = icp_multi_insn_read_ai; - + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; + s->n_chan = 16; + s->maxdata = 0x0fff; + s->range_table = &icp_multi_ranges; + s->insn_read = icp_multi_ai_insn_read; + + /* Analog Output subdevice */ s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; - s->n_chan = 4; - s->maxdata = 0x0fff; - s->len_chanlist = 4; - s->range_table = &range_analog; - s->insn_write = icp_multi_ao_insn_write; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = 4; + s->maxdata = 0x0fff; + s->range_table = &icp_multi_ranges; + s->insn_write = icp_multi_ao_insn_write; ret = comedi_alloc_subdev_readback(s); if (ret) return ret; + /* Digital Input subdevice */ s = &dev->subdevices[2]; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 16; - s->maxdata = 1; - s->len_chanlist = 16; - s->range_table = &range_digital; - s->insn_bits = icp_multi_insn_bits_di; - + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = icp_multi_di_insn_bits; + + /* Digital Output subdevice */ s = &dev->subdevices[3]; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 8; - s->maxdata = 1; - s->len_chanlist = 8; - s->range_table = &range_digital; - s->insn_bits = icp_multi_insn_bits_do; - - s = &dev->subdevices[4]; - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 4; - s->maxdata = 0xffff; - s->len_chanlist = 4; - s->state = 0; - s->insn_read = icp_multi_insn_read_ctr; - s->insn_write = icp_multi_insn_write_ctr; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = icp_multi_do_insn_bits; return 0; } -static void icp_multi_detach(struct comedi_device *dev) -{ - if (dev->mmio) - icp_multi_reset(dev); - comedi_pci_detach(dev); -} - static struct comedi_driver icp_multi_driver = { .driver_name = "icp_multi", .module = THIS_MODULE, .auto_attach = icp_multi_auto_attach, - .detach = icp_multi_detach, + .detach = comedi_pci_detach, }; static int icp_multi_pci_probe(struct pci_dev *dev, @@ -564,5 +341,5 @@ static struct pci_driver icp_multi_pci_driver = { module_comedi_pci_driver(icp_multi_driver, icp_multi_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for Inova ICP_MULTI board"); MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/staging/comedi/drivers/ii_pci20kc.c b/kernel/drivers/staging/comedi/drivers/ii_pci20kc.c index 0768bc42a..77e1d891f 100644 --- a/kernel/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/kernel/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -28,6 +28,7 @@ */ #include <linux/module.h> +#include <linux/io.h> #include "../comedidev.h" /* @@ -36,37 +37,37 @@ #define II20K_SIZE 0x400 #define II20K_MOD_OFFSET 0x100 #define II20K_ID_REG 0x00 -#define II20K_ID_MOD1_EMPTY (1 << 7) -#define II20K_ID_MOD2_EMPTY (1 << 6) -#define II20K_ID_MOD3_EMPTY (1 << 5) +#define II20K_ID_MOD1_EMPTY BIT(7) +#define II20K_ID_MOD2_EMPTY BIT(6) +#define II20K_ID_MOD3_EMPTY BIT(5) #define II20K_ID_MASK 0x1f #define II20K_ID_PCI20001C_1A 0x1b /* no on-board DIO */ #define II20K_ID_PCI20001C_2A 0x1d /* on-board DIO */ #define II20K_MOD_STATUS_REG 0x40 -#define II20K_MOD_STATUS_IRQ_MOD1 (1 << 7) -#define II20K_MOD_STATUS_IRQ_MOD2 (1 << 6) -#define II20K_MOD_STATUS_IRQ_MOD3 (1 << 5) +#define II20K_MOD_STATUS_IRQ_MOD1 BIT(7) +#define II20K_MOD_STATUS_IRQ_MOD2 BIT(6) +#define II20K_MOD_STATUS_IRQ_MOD3 BIT(5) #define II20K_DIO0_REG 0x80 #define II20K_DIO1_REG 0x81 #define II20K_DIR_ENA_REG 0x82 -#define II20K_DIR_DIO3_OUT (1 << 7) -#define II20K_DIR_DIO2_OUT (1 << 6) -#define II20K_BUF_DISAB_DIO3 (1 << 5) -#define II20K_BUF_DISAB_DIO2 (1 << 4) -#define II20K_DIR_DIO1_OUT (1 << 3) -#define II20K_DIR_DIO0_OUT (1 << 2) -#define II20K_BUF_DISAB_DIO1 (1 << 1) -#define II20K_BUF_DISAB_DIO0 (1 << 0) +#define II20K_DIR_DIO3_OUT BIT(7) +#define II20K_DIR_DIO2_OUT BIT(6) +#define II20K_BUF_DISAB_DIO3 BIT(5) +#define II20K_BUF_DISAB_DIO2 BIT(4) +#define II20K_DIR_DIO1_OUT BIT(3) +#define II20K_DIR_DIO0_OUT BIT(2) +#define II20K_BUF_DISAB_DIO1 BIT(1) +#define II20K_BUF_DISAB_DIO0 BIT(0) #define II20K_CTRL01_REG 0x83 -#define II20K_CTRL01_SET (1 << 7) -#define II20K_CTRL01_DIO0_IN (1 << 4) -#define II20K_CTRL01_DIO1_IN (1 << 1) +#define II20K_CTRL01_SET BIT(7) +#define II20K_CTRL01_DIO0_IN BIT(4) +#define II20K_CTRL01_DIO1_IN BIT(1) #define II20K_DIO2_REG 0xc0 #define II20K_DIO3_REG 0xc1 #define II20K_CTRL23_REG 0xc3 -#define II20K_CTRL23_SET (1 << 7) -#define II20K_CTRL23_DIO2_IN (1 << 4) -#define II20K_CTRL23_DIO3_IN (1 << 1) +#define II20K_CTRL23_SET BIT(7) +#define II20K_CTRL23_DIO2_IN BIT(4) +#define II20K_CTRL23_DIO3_IN BIT(1) #define II20K_ID_PCI20006M_1 0xe2 /* 1 AO channels */ #define II20K_ID_PCI20006M_2 0xe3 /* 2 AO channels */ @@ -77,27 +78,27 @@ #define II20K_ID_PCI20341M_1 0x77 /* 4 AI channels */ #define II20K_AI_STATUS_CMD_REG 0x01 -#define II20K_AI_STATUS_CMD_BUSY (1 << 7) -#define II20K_AI_STATUS_CMD_HW_ENA (1 << 1) -#define II20K_AI_STATUS_CMD_EXT_START (1 << 0) +#define II20K_AI_STATUS_CMD_BUSY BIT(7) +#define II20K_AI_STATUS_CMD_HW_ENA BIT(1) +#define II20K_AI_STATUS_CMD_EXT_START BIT(0) #define II20K_AI_LSB_REG 0x02 #define II20K_AI_MSB_REG 0x03 #define II20K_AI_PACER_RESET_REG 0x04 #define II20K_AI_16BIT_DATA_REG 0x06 #define II20K_AI_CONF_REG 0x10 -#define II20K_AI_CONF_ENA (1 << 2) +#define II20K_AI_CONF_ENA BIT(2) #define II20K_AI_OPT_REG 0x11 -#define II20K_AI_OPT_TRIG_ENA (1 << 5) -#define II20K_AI_OPT_TRIG_INV (1 << 4) +#define II20K_AI_OPT_TRIG_ENA BIT(5) +#define II20K_AI_OPT_TRIG_INV BIT(4) #define II20K_AI_OPT_TIMEBASE(x) (((x) & 0x3) << 1) -#define II20K_AI_OPT_BURST_MODE (1 << 0) +#define II20K_AI_OPT_BURST_MODE BIT(0) #define II20K_AI_STATUS_REG 0x12 -#define II20K_AI_STATUS_INT (1 << 7) -#define II20K_AI_STATUS_TRIG (1 << 6) -#define II20K_AI_STATUS_TRIG_ENA (1 << 5) -#define II20K_AI_STATUS_PACER_ERR (1 << 2) -#define II20K_AI_STATUS_DATA_ERR (1 << 1) -#define II20K_AI_STATUS_SET_TIME_ERR (1 << 0) +#define II20K_AI_STATUS_INT BIT(7) +#define II20K_AI_STATUS_TRIG BIT(6) +#define II20K_AI_STATUS_TRIG_ENA BIT(5) +#define II20K_AI_STATUS_PACER_ERR BIT(2) +#define II20K_AI_STATUS_DATA_ERR BIT(1) +#define II20K_AI_STATUS_SET_TIME_ERR BIT(0) #define II20K_AI_LAST_CHAN_ADDR_REG 0x13 #define II20K_AI_CUR_ADDR_REG 0x14 #define II20K_AI_SET_TIME_REG 0x15 @@ -108,9 +109,9 @@ #define II20K_AI_START_TRIG_REG 0x1a #define II20K_AI_COUNT_RESET_REG 0x1b #define II20K_AI_CHANLIST_REG 0x80 -#define II20K_AI_CHANLIST_ONBOARD_ONLY (1 << 5) +#define II20K_AI_CHANLIST_ONBOARD_ONLY BIT(5) #define II20K_AI_CHANLIST_GAIN(x) (((x) & 0x3) << 3) -#define II20K_AI_CHANLIST_MUX_ENA (1 << 2) +#define II20K_AI_CHANLIST_MUX_ENA BIT(2) #define II20K_AI_CHANLIST_CHAN(x) (((x) & 0x3) << 0) #define II20K_AI_CHANLIST_LEN 0x80 @@ -152,9 +153,8 @@ static int ii20k_ao_insn_write(struct comedi_device *dev, s->readback[chan] = val; - /* munge data */ - val += ((s->maxdata + 1) >> 1); - val &= s->maxdata; + /* munge the offset binary data to 2's complement */ + val = comedi_offset_munge(s, val); writeb(val & 0xff, iobase + II20K_AO_LSB_REG(chan)); writeb((val >> 8) & 0xff, iobase + II20K_AO_MSB_REG(chan)); @@ -242,11 +242,8 @@ static int ii20k_ai_insn_read(struct comedi_device *dev, val = readb(iobase + II20K_AI_LSB_REG); val |= (readb(iobase + II20K_AI_MSB_REG) << 8); - /* munge two's complement data */ - val += ((s->maxdata + 1) >> 1); - val &= s->maxdata; - - data[i] = val; + /* munge the 2's complement data to offset binary */ + data[i] = comedi_offset_munge(s, val); } return insn->n; @@ -522,5 +519,5 @@ static struct comedi_driver ii20k_driver = { module_comedi_driver(ii20k_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for Intelligent Instruments PCI-20001C"); MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/staging/comedi/drivers/ke_counter.c b/kernel/drivers/staging/comedi/drivers/ke_counter.c index dc642edf4..93198abf0 100644 --- a/kernel/drivers/staging/comedi/drivers/ke_counter.c +++ b/kernel/drivers/staging/comedi/drivers/ke_counter.c @@ -41,9 +41,10 @@ #define KE_MSB_REG(x) (0x0c + ((x) * 0x20)) #define KE_SIGN_REG(x) (0x10 + ((x) * 0x20)) #define KE_OSC_SEL_REG 0xf8 -#define KE_OSC_SEL_EXT (1 << 0) -#define KE_OSC_SEL_4MHZ (2 << 0) -#define KE_OSC_SEL_20MHZ (3 << 0) +#define KE_OSC_SEL_CLK(x) (((x) & 0x3) << 0) +#define KE_OSC_SEL_EXT KE_OSC_SEL_CLK(1) +#define KE_OSC_SEL_4MHZ KE_OSC_SEL_CLK(2) +#define KE_OSC_SEL_20MHZ KE_OSC_SEL_CLK(3) #define KE_DO_REG 0xfc static int ke_counter_insn_write(struct comedi_device *dev, diff --git a/kernel/drivers/staging/comedi/drivers/me4000.c b/kernel/drivers/staging/comedi/drivers/me4000.c index 7a8c27dd7..15a53204a 100644 --- a/kernel/drivers/staging/comedi/drivers/me4000.c +++ b/kernel/drivers/staging/comedi/drivers/me4000.c @@ -1,43 +1,41 @@ /* - comedi/drivers/me4000.c - Source code for the Meilhaus ME-4000 board family. - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + * me4000.c + * Source code for the Meilhaus ME-4000 board family. + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. */ -/* -Driver: me4000 -Description: Meilhaus ME-4000 series boards -Devices: [Meilhaus] ME-4650 (me4000), ME-4670i, ME-4680, ME-4680i, ME-4680is -Author: gg (Guenter Gebhardt <g.gebhardt@meilhaus.com>) -Updated: Mon, 18 Mar 2002 15:34:01 -0800 -Status: broken (no support for loading firmware) - -Supports: - - - Analog Input - - Analog Output - - Digital I/O - - Counter - -Configuration Options: not applicable, uses PCI auto config - -The firmware required by these boards is available in the -comedi_nonfree_firmware tarball available from -http://www.comedi.org. However, the driver's support for -loading the firmware through comedi_config is currently -broken. +/* + * Driver: me4000 + * Description: Meilhaus ME-4000 series boards + * Devices: [Meilhaus] ME-4650 (me4000), ME-4670i, ME-4680, ME-4680i, + * ME-4680is + * Author: gg (Guenter Gebhardt <g.gebhardt@meilhaus.com>) + * Updated: Mon, 18 Mar 2002 15:34:01 -0800 + * Status: untested + * + * Supports: + * - Analog Input + * - Analog Output + * - Digital I/O + * - Counter + * + * Configuration Options: not applicable, uses PCI auto config + * + * The firmware required by these boards is available in the + * comedi_nonfree_firmware tarball available from + * http://www.comedi.org. */ #include <linux/module.h> @@ -57,66 +55,61 @@ broken. #define ME4000_AO_CHAN(x) ((x) * 0x18) #define ME4000_AO_CTRL_REG(x) (0x00 + ME4000_AO_CHAN(x)) -#define ME4000_AO_CTRL_BIT_MODE_0 (1 << 0) -#define ME4000_AO_CTRL_BIT_MODE_1 (1 << 1) -#define ME4000_AO_CTRL_MASK_MODE (3 << 0) -#define ME4000_AO_CTRL_BIT_STOP (1 << 2) -#define ME4000_AO_CTRL_BIT_ENABLE_FIFO (1 << 3) -#define ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG (1 << 4) -#define ME4000_AO_CTRL_BIT_EX_TRIG_EDGE (1 << 5) -#define ME4000_AO_CTRL_BIT_IMMEDIATE_STOP (1 << 7) -#define ME4000_AO_CTRL_BIT_ENABLE_DO (1 << 8) -#define ME4000_AO_CTRL_BIT_ENABLE_IRQ (1 << 9) -#define ME4000_AO_CTRL_BIT_RESET_IRQ (1 << 10) +#define ME4000_AO_CTRL_MODE_0 BIT(0) +#define ME4000_AO_CTRL_MODE_1 BIT(1) +#define ME4000_AO_CTRL_STOP BIT(2) +#define ME4000_AO_CTRL_ENABLE_FIFO BIT(3) +#define ME4000_AO_CTRL_ENABLE_EX_TRIG BIT(4) +#define ME4000_AO_CTRL_EX_TRIG_EDGE BIT(5) +#define ME4000_AO_CTRL_IMMEDIATE_STOP BIT(7) +#define ME4000_AO_CTRL_ENABLE_DO BIT(8) +#define ME4000_AO_CTRL_ENABLE_IRQ BIT(9) +#define ME4000_AO_CTRL_RESET_IRQ BIT(10) #define ME4000_AO_STATUS_REG(x) (0x04 + ME4000_AO_CHAN(x)) -#define ME4000_AO_STATUS_BIT_FSM (1 << 0) -#define ME4000_AO_STATUS_BIT_FF (1 << 1) -#define ME4000_AO_STATUS_BIT_HF (1 << 2) -#define ME4000_AO_STATUS_BIT_EF (1 << 3) +#define ME4000_AO_STATUS_FSM BIT(0) +#define ME4000_AO_STATUS_FF BIT(1) +#define ME4000_AO_STATUS_HF BIT(2) +#define ME4000_AO_STATUS_EF BIT(3) #define ME4000_AO_FIFO_REG(x) (0x08 + ME4000_AO_CHAN(x)) #define ME4000_AO_SINGLE_REG(x) (0x0c + ME4000_AO_CHAN(x)) #define ME4000_AO_TIMER_REG(x) (0x10 + ME4000_AO_CHAN(x)) #define ME4000_AI_CTRL_REG 0x74 #define ME4000_AI_STATUS_REG 0x74 -#define ME4000_AI_CTRL_BIT_MODE_0 (1 << 0) -#define ME4000_AI_CTRL_BIT_MODE_1 (1 << 1) -#define ME4000_AI_CTRL_BIT_MODE_2 (1 << 2) -#define ME4000_AI_CTRL_BIT_SAMPLE_HOLD (1 << 3) -#define ME4000_AI_CTRL_BIT_IMMEDIATE_STOP (1 << 4) -#define ME4000_AI_CTRL_BIT_STOP (1 << 5) -#define ME4000_AI_CTRL_BIT_CHANNEL_FIFO (1 << 6) -#define ME4000_AI_CTRL_BIT_DATA_FIFO (1 << 7) -#define ME4000_AI_CTRL_BIT_FULLSCALE (1 << 8) -#define ME4000_AI_CTRL_BIT_OFFSET (1 << 9) -#define ME4000_AI_CTRL_BIT_EX_TRIG_ANALOG (1 << 10) -#define ME4000_AI_CTRL_BIT_EX_TRIG (1 << 11) -#define ME4000_AI_CTRL_BIT_EX_TRIG_FALLING (1 << 12) -#define ME4000_AI_CTRL_BIT_EX_IRQ (1 << 13) -#define ME4000_AI_CTRL_BIT_EX_IRQ_RESET (1 << 14) -#define ME4000_AI_CTRL_BIT_LE_IRQ (1 << 15) -#define ME4000_AI_CTRL_BIT_LE_IRQ_RESET (1 << 16) -#define ME4000_AI_CTRL_BIT_HF_IRQ (1 << 17) -#define ME4000_AI_CTRL_BIT_HF_IRQ_RESET (1 << 18) -#define ME4000_AI_CTRL_BIT_SC_IRQ (1 << 19) -#define ME4000_AI_CTRL_BIT_SC_IRQ_RESET (1 << 20) -#define ME4000_AI_CTRL_BIT_SC_RELOAD (1 << 21) -#define ME4000_AI_STATUS_BIT_EF_CHANNEL (1 << 22) -#define ME4000_AI_STATUS_BIT_HF_CHANNEL (1 << 23) -#define ME4000_AI_STATUS_BIT_FF_CHANNEL (1 << 24) -#define ME4000_AI_STATUS_BIT_EF_DATA (1 << 25) -#define ME4000_AI_STATUS_BIT_HF_DATA (1 << 26) -#define ME4000_AI_STATUS_BIT_FF_DATA (1 << 27) -#define ME4000_AI_STATUS_BIT_LE (1 << 28) -#define ME4000_AI_STATUS_BIT_FSM (1 << 29) -#define ME4000_AI_CTRL_BIT_EX_TRIG_BOTH (1 << 31) +#define ME4000_AI_CTRL_MODE_0 BIT(0) +#define ME4000_AI_CTRL_MODE_1 BIT(1) +#define ME4000_AI_CTRL_MODE_2 BIT(2) +#define ME4000_AI_CTRL_SAMPLE_HOLD BIT(3) +#define ME4000_AI_CTRL_IMMEDIATE_STOP BIT(4) +#define ME4000_AI_CTRL_STOP BIT(5) +#define ME4000_AI_CTRL_CHANNEL_FIFO BIT(6) +#define ME4000_AI_CTRL_DATA_FIFO BIT(7) +#define ME4000_AI_CTRL_FULLSCALE BIT(8) +#define ME4000_AI_CTRL_OFFSET BIT(9) +#define ME4000_AI_CTRL_EX_TRIG_ANALOG BIT(10) +#define ME4000_AI_CTRL_EX_TRIG BIT(11) +#define ME4000_AI_CTRL_EX_TRIG_FALLING BIT(12) +#define ME4000_AI_CTRL_EX_IRQ BIT(13) +#define ME4000_AI_CTRL_EX_IRQ_RESET BIT(14) +#define ME4000_AI_CTRL_LE_IRQ BIT(15) +#define ME4000_AI_CTRL_LE_IRQ_RESET BIT(16) +#define ME4000_AI_CTRL_HF_IRQ BIT(17) +#define ME4000_AI_CTRL_HF_IRQ_RESET BIT(18) +#define ME4000_AI_CTRL_SC_IRQ BIT(19) +#define ME4000_AI_CTRL_SC_IRQ_RESET BIT(20) +#define ME4000_AI_CTRL_SC_RELOAD BIT(21) +#define ME4000_AI_STATUS_EF_CHANNEL BIT(22) +#define ME4000_AI_STATUS_HF_CHANNEL BIT(23) +#define ME4000_AI_STATUS_FF_CHANNEL BIT(24) +#define ME4000_AI_STATUS_EF_DATA BIT(25) +#define ME4000_AI_STATUS_HF_DATA BIT(26) +#define ME4000_AI_STATUS_FF_DATA BIT(27) +#define ME4000_AI_STATUS_LE BIT(28) +#define ME4000_AI_STATUS_FSM BIT(29) +#define ME4000_AI_CTRL_EX_TRIG_BOTH BIT(31) #define ME4000_AI_CHANNEL_LIST_REG 0x78 -#define ME4000_AI_LIST_INPUT_SINGLE_ENDED (0 << 5) -#define ME4000_AI_LIST_INPUT_DIFFERENTIAL (1 << 5) -#define ME4000_AI_LIST_RANGE_BIPOLAR_10 (0 << 6) -#define ME4000_AI_LIST_RANGE_BIPOLAR_2_5 (1 << 6) -#define ME4000_AI_LIST_RANGE_UNIPOLAR_10 (2 << 6) -#define ME4000_AI_LIST_RANGE_UNIPOLAR_2_5 (3 << 6) -#define ME4000_AI_LIST_LAST_ENTRY (1 << 8) +#define ME4000_AI_LIST_INPUT_DIFFERENTIAL BIT(5) +#define ME4000_AI_LIST_RANGE(x) ((3 - ((x) & 3)) << 6) +#define ME4000_AI_LIST_LAST_ENTRY BIT(8) #define ME4000_AI_DATA_REG 0x7c #define ME4000_AI_CHAN_TIMER_REG 0x80 #define ME4000_AI_CHAN_PRE_TIMER_REG 0x84 @@ -126,14 +119,14 @@ broken. #define ME4000_AI_SCAN_PRE_TIMER_HIGH_REG 0x94 #define ME4000_AI_START_REG 0x98 #define ME4000_IRQ_STATUS_REG 0x9c -#define ME4000_IRQ_STATUS_BIT_EX (1 << 0) -#define ME4000_IRQ_STATUS_BIT_LE (1 << 1) -#define ME4000_IRQ_STATUS_BIT_AI_HF (1 << 2) -#define ME4000_IRQ_STATUS_BIT_AO_0_HF (1 << 3) -#define ME4000_IRQ_STATUS_BIT_AO_1_HF (1 << 4) -#define ME4000_IRQ_STATUS_BIT_AO_2_HF (1 << 5) -#define ME4000_IRQ_STATUS_BIT_AO_3_HF (1 << 6) -#define ME4000_IRQ_STATUS_BIT_SC (1 << 7) +#define ME4000_IRQ_STATUS_EX BIT(0) +#define ME4000_IRQ_STATUS_LE BIT(1) +#define ME4000_IRQ_STATUS_AI_HF BIT(2) +#define ME4000_IRQ_STATUS_AO_0_HF BIT(3) +#define ME4000_IRQ_STATUS_AO_1_HF BIT(4) +#define ME4000_IRQ_STATUS_AO_2_HF BIT(5) +#define ME4000_IRQ_STATUS_AO_3_HF BIT(6) +#define ME4000_IRQ_STATUS_SC BIT(7) #define ME4000_DIO_PORT_0_REG 0xa0 #define ME4000_DIO_PORT_1_REG 0xa4 #define ME4000_DIO_PORT_2_REG 0xa8 @@ -141,20 +134,20 @@ broken. #define ME4000_DIO_DIR_REG 0xb0 #define ME4000_AO_LOADSETREG_XX 0xb4 #define ME4000_DIO_CTRL_REG 0xb8 -#define ME4000_DIO_CTRL_BIT_MODE_0 (1 << 0) -#define ME4000_DIO_CTRL_BIT_MODE_1 (1 << 1) -#define ME4000_DIO_CTRL_BIT_MODE_2 (1 << 2) -#define ME4000_DIO_CTRL_BIT_MODE_3 (1 << 3) -#define ME4000_DIO_CTRL_BIT_MODE_4 (1 << 4) -#define ME4000_DIO_CTRL_BIT_MODE_5 (1 << 5) -#define ME4000_DIO_CTRL_BIT_MODE_6 (1 << 6) -#define ME4000_DIO_CTRL_BIT_MODE_7 (1 << 7) -#define ME4000_DIO_CTRL_BIT_FUNCTION_0 (1 << 8) -#define ME4000_DIO_CTRL_BIT_FUNCTION_1 (1 << 9) -#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_0 (1 << 10) -#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_1 (1 << 11) -#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_2 (1 << 12) -#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_3 (1 << 13) +#define ME4000_DIO_CTRL_MODE_0 BIT(0) +#define ME4000_DIO_CTRL_MODE_1 BIT(1) +#define ME4000_DIO_CTRL_MODE_2 BIT(2) +#define ME4000_DIO_CTRL_MODE_3 BIT(3) +#define ME4000_DIO_CTRL_MODE_4 BIT(4) +#define ME4000_DIO_CTRL_MODE_5 BIT(5) +#define ME4000_DIO_CTRL_MODE_6 BIT(6) +#define ME4000_DIO_CTRL_MODE_7 BIT(7) +#define ME4000_DIO_CTRL_FUNCTION_0 BIT(8) +#define ME4000_DIO_CTRL_FUNCTION_1 BIT(9) +#define ME4000_DIO_CTRL_FIFO_HIGH_0 BIT(10) +#define ME4000_DIO_CTRL_FIFO_HIGH_1 BIT(11) +#define ME4000_DIO_CTRL_FIFO_HIGH_2 BIT(12) +#define ME4000_DIO_CTRL_FIFO_HIGH_3 BIT(13) #define ME4000_AO_DEMUX_ADJUST_REG 0xbc #define ME4000_AO_DEMUX_ADJUST_VALUE 0x4c #define ME4000_AI_SAMPLE_COUNTER_REG 0xc0 @@ -166,8 +159,12 @@ broken. #define ME4000_AI_CHANNEL_LIST_COUNT 1024 -struct me4000_info { +struct me4000_private { unsigned long plx_regbase; + unsigned int ai_ctrl_mode; + unsigned int ai_init_ticks; + unsigned int ai_scan_ticks; + unsigned int ai_chan_ticks; }; enum me4000_boardid { @@ -188,134 +185,126 @@ enum me4000_boardid { struct me4000_board { const char *name; - int ao_nchan; - int ao_fifo; int ai_nchan; - int ai_diff_nchan; - int ai_sh_nchan; - int ex_trig_analog; - int dio_nchan; - int has_counter; + unsigned int can_do_diff_ai:1; + unsigned int can_do_sh_ai:1; /* sample & hold (8 channels) */ + unsigned int ex_trig_analog:1; + unsigned int has_ao:1; + unsigned int has_ao_fifo:1; + unsigned int has_counter:1; }; static const struct me4000_board me4000_boards[] = { [BOARD_ME4650] = { .name = "ME-4650", .ai_nchan = 16, - .dio_nchan = 32, }, [BOARD_ME4660] = { .name = "ME-4660", .ai_nchan = 32, - .ai_diff_nchan = 16, - .dio_nchan = 32, + .can_do_diff_ai = 1, .has_counter = 1, }, [BOARD_ME4660I] = { .name = "ME-4660i", .ai_nchan = 32, - .ai_diff_nchan = 16, - .dio_nchan = 32, + .can_do_diff_ai = 1, .has_counter = 1, }, [BOARD_ME4660S] = { .name = "ME-4660s", .ai_nchan = 32, - .ai_diff_nchan = 16, - .ai_sh_nchan = 8, - .dio_nchan = 32, + .can_do_diff_ai = 1, + .can_do_sh_ai = 1, .has_counter = 1, }, [BOARD_ME4660IS] = { .name = "ME-4660is", .ai_nchan = 32, - .ai_diff_nchan = 16, - .ai_sh_nchan = 8, - .dio_nchan = 32, + .can_do_diff_ai = 1, + .can_do_sh_ai = 1, .has_counter = 1, }, [BOARD_ME4670] = { .name = "ME-4670", - .ao_nchan = 4, .ai_nchan = 32, - .ai_diff_nchan = 16, + .can_do_diff_ai = 1, .ex_trig_analog = 1, - .dio_nchan = 32, + .has_ao = 1, .has_counter = 1, }, [BOARD_ME4670I] = { .name = "ME-4670i", - .ao_nchan = 4, .ai_nchan = 32, - .ai_diff_nchan = 16, + .can_do_diff_ai = 1, .ex_trig_analog = 1, - .dio_nchan = 32, + .has_ao = 1, .has_counter = 1, }, [BOARD_ME4670S] = { .name = "ME-4670s", - .ao_nchan = 4, .ai_nchan = 32, - .ai_diff_nchan = 16, - .ai_sh_nchan = 8, + .can_do_diff_ai = 1, + .can_do_sh_ai = 1, .ex_trig_analog = 1, - .dio_nchan = 32, + .has_ao = 1, .has_counter = 1, }, [BOARD_ME4670IS] = { .name = "ME-4670is", - .ao_nchan = 4, .ai_nchan = 32, - .ai_diff_nchan = 16, - .ai_sh_nchan = 8, + .can_do_diff_ai = 1, + .can_do_sh_ai = 1, .ex_trig_analog = 1, - .dio_nchan = 32, + .has_ao = 1, .has_counter = 1, }, [BOARD_ME4680] = { .name = "ME-4680", - .ao_nchan = 4, - .ao_fifo = 4, .ai_nchan = 32, - .ai_diff_nchan = 16, + .can_do_diff_ai = 1, .ex_trig_analog = 1, - .dio_nchan = 32, + .has_ao = 1, + .has_ao_fifo = 1, .has_counter = 1, }, [BOARD_ME4680I] = { .name = "ME-4680i", - .ao_nchan = 4, - .ao_fifo = 4, .ai_nchan = 32, - .ai_diff_nchan = 16, + .can_do_diff_ai = 1, .ex_trig_analog = 1, - .dio_nchan = 32, + .has_ao = 1, + .has_ao_fifo = 1, .has_counter = 1, }, [BOARD_ME4680S] = { .name = "ME-4680s", - .ao_nchan = 4, - .ao_fifo = 4, .ai_nchan = 32, - .ai_diff_nchan = 16, - .ai_sh_nchan = 8, + .can_do_diff_ai = 1, + .can_do_sh_ai = 1, .ex_trig_analog = 1, - .dio_nchan = 32, + .has_ao = 1, + .has_ao_fifo = 1, .has_counter = 1, }, [BOARD_ME4680IS] = { .name = "ME-4680is", - .ao_nchan = 4, - .ao_fifo = 4, .ai_nchan = 32, - .ai_diff_nchan = 16, - .ai_sh_nchan = 8, + .can_do_diff_ai = 1, + .can_do_sh_ai = 1, .ex_trig_analog = 1, - .dio_nchan = 32, + .has_ao = 1, + .has_ao_fifo = 1, .has_counter = 1, }, }; +/* + * NOTE: the ranges here are inverted compared to the values + * written to the ME4000_AI_CHANNEL_LIST_REG, + * + * The ME4000_AI_LIST_RANGE() macro handles the inversion. + */ static const struct comedi_lrange me4000_ai_range = { 4, { UNI_RANGE(2.5), @@ -330,7 +319,7 @@ static int me4000_xilinx_download(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - struct me4000_info *info = dev->private; + struct me4000_private *devpriv = dev->private; unsigned long xilinx_iobase = pci_resource_start(pcidev, 5); unsigned int file_length; unsigned int val; @@ -343,42 +332,42 @@ static int me4000_xilinx_download(struct comedi_device *dev, * Set PLX local interrupt 2 polarity to high. * Interrupt is thrown by init pin of xilinx. */ - outl(PLX9052_INTCSR_LI2POL, info->plx_regbase + PLX9052_INTCSR); + outl(PLX9052_INTCSR_LI2POL, devpriv->plx_regbase + PLX9052_INTCSR); /* Set /CS and /WRITE of the Xilinx */ - val = inl(info->plx_regbase + PLX9052_CNTRL); + val = inl(devpriv->plx_regbase + PLX9052_CNTRL); val |= PLX9052_CNTRL_UIO2_DATA; - outl(val, info->plx_regbase + PLX9052_CNTRL); + outl(val, devpriv->plx_regbase + PLX9052_CNTRL); /* Init Xilinx with CS1 */ inb(xilinx_iobase + 0xC8); /* Wait until /INIT pin is set */ - udelay(20); - val = inl(info->plx_regbase + PLX9052_INTCSR); + usleep_range(20, 1000); + val = inl(devpriv->plx_regbase + PLX9052_INTCSR); if (!(val & PLX9052_INTCSR_LI2STAT)) { dev_err(dev->class_dev, "Can't init Xilinx\n"); return -EIO; } /* Reset /CS and /WRITE of the Xilinx */ - val = inl(info->plx_regbase + PLX9052_CNTRL); + val = inl(devpriv->plx_regbase + PLX9052_CNTRL); val &= ~PLX9052_CNTRL_UIO2_DATA; - outl(val, info->plx_regbase + PLX9052_CNTRL); + outl(val, devpriv->plx_regbase + PLX9052_CNTRL); /* Download Xilinx firmware */ file_length = (((unsigned int)data[0] & 0xff) << 24) + (((unsigned int)data[1] & 0xff) << 16) + (((unsigned int)data[2] & 0xff) << 8) + ((unsigned int)data[3] & 0xff); - udelay(10); + usleep_range(10, 1000); for (i = 0; i < file_length; i++) { outb(data[16 + i], xilinx_iobase); - udelay(10); + usleep_range(10, 1000); /* Check if BUSY flag is low */ - val = inl(info->plx_regbase + PLX9052_CNTRL); + val = inl(devpriv->plx_regbase + PLX9052_CNTRL); if (val & PLX9052_CNTRL_UIO1_DATA) { dev_err(dev->class_dev, "Xilinx is still busy (i = %d)\n", i); @@ -387,7 +376,7 @@ static int me4000_xilinx_download(struct comedi_device *dev, } /* If done flag is high download was successful */ - val = inl(info->plx_regbase + PLX9052_CNTRL); + val = inl(devpriv->plx_regbase + PLX9052_CNTRL); if (!(val & PLX9052_CNTRL_UIO0_DATA)) { dev_err(dev->class_dev, "DONE flag is not set\n"); dev_err(dev->class_dev, "Download not successful\n"); @@ -395,44 +384,53 @@ static int me4000_xilinx_download(struct comedi_device *dev, } /* Set /CS and /WRITE */ - val = inl(info->plx_regbase + PLX9052_CNTRL); + val = inl(devpriv->plx_regbase + PLX9052_CNTRL); val |= PLX9052_CNTRL_UIO2_DATA; - outl(val, info->plx_regbase + PLX9052_CNTRL); + outl(val, devpriv->plx_regbase + PLX9052_CNTRL); return 0; } +static void me4000_ai_reset(struct comedi_device *dev) +{ + unsigned int ctrl; + + /* Stop any running conversion */ + ctrl = inl(dev->iobase + ME4000_AI_CTRL_REG); + ctrl |= ME4000_AI_CTRL_STOP | ME4000_AI_CTRL_IMMEDIATE_STOP; + outl(ctrl, dev->iobase + ME4000_AI_CTRL_REG); + + /* Clear the control register */ + outl(0x0, dev->iobase + ME4000_AI_CTRL_REG); +} + static void me4000_reset(struct comedi_device *dev) { - struct me4000_info *info = dev->private; + struct me4000_private *devpriv = dev->private; unsigned int val; int chan; - /* Make a hardware reset */ - val = inl(info->plx_regbase + PLX9052_CNTRL); + /* Disable interrupts on the PLX */ + outl(0, devpriv->plx_regbase + PLX9052_INTCSR); + + /* Software reset the PLX */ + val = inl(devpriv->plx_regbase + PLX9052_CNTRL); val |= PLX9052_CNTRL_PCI_RESET; - outl(val, info->plx_regbase + PLX9052_CNTRL); + outl(val, devpriv->plx_regbase + PLX9052_CNTRL); val &= ~PLX9052_CNTRL_PCI_RESET; - outl(val, info->plx_regbase + PLX9052_CNTRL); + outl(val, devpriv->plx_regbase + PLX9052_CNTRL); /* 0x8000 to the DACs means an output voltage of 0V */ for (chan = 0; chan < 4; chan++) outl(0x8000, dev->iobase + ME4000_AO_SINGLE_REG(chan)); - /* Set both stop bits in the analog input control register */ - outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP, - dev->iobase + ME4000_AI_CTRL_REG); + me4000_ai_reset(dev); /* Set both stop bits in the analog output control register */ - val = ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP; + val = ME4000_AO_CTRL_IMMEDIATE_STOP | ME4000_AO_CTRL_STOP; for (chan = 0; chan < 4; chan++) outl(val, dev->iobase + ME4000_AO_CTRL_REG(chan)); - /* Enable interrupts on the PLX */ - outl(PLX9052_INTCSR_LI1ENAB | - PLX9052_INTCSR_LI1POL | - PLX9052_INTCSR_PCIENAB, info->plx_regbase + PLX9052_INTCSR); - /* Set the adustment register for AO demux */ outl(ME4000_AO_DEMUX_ADJUST_VALUE, dev->iobase + ME4000_AO_DEMUX_ADJUST_REG); @@ -445,96 +443,68 @@ static void me4000_reset(struct comedi_device *dev) outl(0x1, dev->iobase + ME4000_DIO_CTRL_REG); } -/*============================================================================= - Analog input section - ===========================================================================*/ - -static int me4000_ai_insn_read(struct comedi_device *dev, - struct comedi_subdevice *subdevice, - struct comedi_insn *insn, unsigned int *data) +static unsigned int me4000_ai_get_sample(struct comedi_device *dev, + struct comedi_subdevice *s) { - const struct me4000_board *thisboard = dev->board_ptr; - int chan = CR_CHAN(insn->chanspec); - int rang = CR_RANGE(insn->chanspec); - int aref = CR_AREF(insn->chanspec); + unsigned int val; - unsigned int entry = 0; - unsigned int tmp; - unsigned int lval; + /* read two's complement value and munge to offset binary */ + val = inl(dev->iobase + ME4000_AI_DATA_REG); + return comedi_offset_munge(s, val); +} - if (insn->n == 0) { +static int me4000_ai_eoc(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned long context) +{ + unsigned int status; + + status = inl(dev->iobase + ME4000_AI_STATUS_REG); + if (status & ME4000_AI_STATUS_EF_DATA) return 0; - } else if (insn->n > 1) { - dev_err(dev->class_dev, "Invalid instruction length %d\n", - insn->n); - return -EINVAL; - } + return -EBUSY; +} - switch (rang) { - case 0: - entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5; - break; - case 1: - entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10; - break; - case 2: - entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5; - break; - case 3: - entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10; - break; - default: - dev_err(dev->class_dev, "Invalid range specified\n"); - return -EINVAL; - } +static int me4000_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); + unsigned int aref = CR_AREF(insn->chanspec); + unsigned int entry; + int ret = 0; + int i; - switch (aref) { - case AREF_GROUND: - case AREF_COMMON: - if (chan >= thisboard->ai_nchan) { + entry = chan | ME4000_AI_LIST_RANGE(range); + if (aref == AREF_DIFF) { + if (!(s->subdev_flags & SDF_DIFF)) { dev_err(dev->class_dev, - "Analog input is not available\n"); + "Differential inputs are not available\n"); return -EINVAL; } - entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan; - break; - case AREF_DIFF: - if (rang == 0 || rang == 1) { + if (!comedi_range_is_bipolar(s, range)) { dev_err(dev->class_dev, "Range must be bipolar when aref = diff\n"); return -EINVAL; } - if (chan >= thisboard->ai_diff_nchan) { + if (chan >= (s->n_chan / 2)) { dev_err(dev->class_dev, "Analog input is not available\n"); return -EINVAL; } - entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan; - break; - default: - dev_err(dev->class_dev, "Invalid aref specified\n"); - return -EINVAL; + entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL; } entry |= ME4000_AI_LIST_LAST_ENTRY; - /* Clear channel list, data fifo and both stop bits */ - tmp = inl(dev->iobase + ME4000_AI_CTRL_REG); - tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO | - ME4000_AI_CTRL_BIT_DATA_FIFO | - ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - - /* Set the acquisition mode to single */ - tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 | - ME4000_AI_CTRL_BIT_MODE_2); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - - /* Enable channel list and data fifo */ - tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO; - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + /* Enable channel list and data fifo for single acquisition mode */ + outl(ME4000_AI_CTRL_CHANNEL_FIFO | ME4000_AI_CTRL_DATA_FIFO, + dev->iobase + ME4000_AI_CTRL_REG); /* Generate channel list entry */ outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG); @@ -543,36 +513,29 @@ static int me4000_ai_insn_read(struct comedi_device *dev, outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_TIMER_REG); outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG); - /* Start conversion by dummy read */ - inl(dev->iobase + ME4000_AI_START_REG); + for (i = 0; i < insn->n; i++) { + unsigned int val; - /* Wait until ready */ - udelay(10); - if (!(inl(dev->iobase + ME4000_AI_STATUS_REG) & - ME4000_AI_STATUS_BIT_EF_DATA)) { - dev_err(dev->class_dev, "Value not available after wait\n"); - return -EIO; + /* start conversion by dummy read */ + inl(dev->iobase + ME4000_AI_START_REG); + + ret = comedi_timeout(dev, s, insn, me4000_ai_eoc, 0); + if (ret) + break; + + val = me4000_ai_get_sample(dev, s); + data[i] = comedi_offset_munge(s, val); } - /* Read value from data fifo */ - lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF; - data[0] = lval ^ 0x8000; + me4000_ai_reset(dev); - return 1; + return ret ? ret : insn->n; } static int me4000_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - unsigned int tmp; - - /* Stop any running conversion */ - tmp = inl(dev->iobase + ME4000_AI_CTRL_REG); - tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - - /* Clear the control register */ - outl(0x0, dev->iobase + ME4000_AI_CTRL_REG); + me4000_ai_reset(dev); return 0; } @@ -581,8 +544,6 @@ static int me4000_ai_check_chanlist(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct me4000_board *board = dev->board_ptr; - unsigned int max_diff_chan = board->ai_diff_nchan; unsigned int aref0 = CR_AREF(cmd->chanlist[0]); int i; @@ -598,7 +559,13 @@ static int me4000_ai_check_chanlist(struct comedi_device *dev, } if (aref == AREF_DIFF) { - if (chan >= max_diff_chan) { + if (!(s->subdev_flags & SDF_DIFF)) { + dev_err(dev->class_dev, + "Differential inputs are not available\n"); + return -EINVAL; + } + + if (chan >= (s->n_chan / 2)) { dev_dbg(dev->class_dev, "Channel number to high\n"); return -EINVAL; @@ -615,202 +582,127 @@ static int me4000_ai_check_chanlist(struct comedi_device *dev, return 0; } -static int ai_round_cmd_args(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd, - unsigned int *init_ticks, - unsigned int *scan_ticks, unsigned int *chan_ticks) +static void me4000_ai_round_cmd_args(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) { + struct me4000_private *devpriv = dev->private; int rest; - *init_ticks = 0; - *scan_ticks = 0; - *chan_ticks = 0; + devpriv->ai_init_ticks = 0; + devpriv->ai_scan_ticks = 0; + devpriv->ai_chan_ticks = 0; if (cmd->start_arg) { - *init_ticks = (cmd->start_arg * 33) / 1000; + devpriv->ai_init_ticks = (cmd->start_arg * 33) / 1000; rest = (cmd->start_arg * 33) % 1000; if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) { if (rest > 33) - (*init_ticks)++; + devpriv->ai_init_ticks++; } else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) { if (rest) - (*init_ticks)++; + devpriv->ai_init_ticks++; } } if (cmd->scan_begin_arg) { - *scan_ticks = (cmd->scan_begin_arg * 33) / 1000; + devpriv->ai_scan_ticks = (cmd->scan_begin_arg * 33) / 1000; rest = (cmd->scan_begin_arg * 33) % 1000; if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) { if (rest > 33) - (*scan_ticks)++; + devpriv->ai_scan_ticks++; } else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) { if (rest) - (*scan_ticks)++; + devpriv->ai_scan_ticks++; } } if (cmd->convert_arg) { - *chan_ticks = (cmd->convert_arg * 33) / 1000; + devpriv->ai_chan_ticks = (cmd->convert_arg * 33) / 1000; rest = (cmd->convert_arg * 33) % 1000; if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) { if (rest > 33) - (*chan_ticks)++; + devpriv->ai_chan_ticks++; } else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) { if (rest) - (*chan_ticks)++; + devpriv->ai_chan_ticks++; } } - - return 0; -} - -static void ai_write_timer(struct comedi_device *dev, - unsigned int init_ticks, - unsigned int scan_ticks, unsigned int chan_ticks) -{ - outl(init_ticks - 1, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG); - outl(0x0, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG); - - if (scan_ticks) { - outl(scan_ticks - 1, dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG); - outl(0x0, dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG); - } - - outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG); - outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_TIMER_REG); } -static int ai_write_chanlist(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_cmd *cmd) +static void me4000_ai_write_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) { - unsigned int entry; - unsigned int chan; - unsigned int rang; - unsigned int aref; int i; for (i = 0; i < cmd->chanlist_len; i++) { - chan = CR_CHAN(cmd->chanlist[i]); - rang = CR_RANGE(cmd->chanlist[i]); - aref = CR_AREF(cmd->chanlist[i]); - - entry = chan; + unsigned int chan = CR_CHAN(cmd->chanlist[i]); + unsigned int range = CR_RANGE(cmd->chanlist[i]); + unsigned int aref = CR_AREF(cmd->chanlist[i]); + unsigned int entry; - if (rang == 0) - entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5; - else if (rang == 1) - entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10; - else if (rang == 2) - entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5; - else - entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10; + entry = chan | ME4000_AI_LIST_RANGE(range); if (aref == AREF_DIFF) entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL; - else - entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED; + + if (i == (cmd->chanlist_len - 1)) + entry |= ME4000_AI_LIST_LAST_ENTRY; outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG); } - - return 0; } -static int ai_prepare(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd, - unsigned int init_ticks, - unsigned int scan_ticks, unsigned int chan_ticks) +static int me4000_ai_do_cmd(struct comedi_device *dev, + struct comedi_subdevice *s) { - unsigned int tmp = 0; + struct me4000_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; + unsigned int ctrl; /* Write timer arguments */ - ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks); + outl(devpriv->ai_init_ticks - 1, + dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG); + outl(0x0, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG); + + if (devpriv->ai_scan_ticks) { + outl(devpriv->ai_scan_ticks - 1, + dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG); + outl(0x0, dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG); + } - /* Reset control register */ - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + outl(devpriv->ai_chan_ticks - 1, + dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG); + outl(devpriv->ai_chan_ticks - 1, + dev->iobase + ME4000_AI_CHAN_TIMER_REG); /* Start sources */ - if ((cmd->start_src == TRIG_EXT && - cmd->scan_begin_src == TRIG_TIMER && - cmd->convert_src == TRIG_TIMER) || - (cmd->start_src == TRIG_EXT && - cmd->scan_begin_src == TRIG_FOLLOW && - cmd->convert_src == TRIG_TIMER)) { - tmp = ME4000_AI_CTRL_BIT_MODE_1 | - ME4000_AI_CTRL_BIT_CHANNEL_FIFO | - ME4000_AI_CTRL_BIT_DATA_FIFO; - } else if (cmd->start_src == TRIG_EXT && - cmd->scan_begin_src == TRIG_EXT && - cmd->convert_src == TRIG_TIMER) { - tmp = ME4000_AI_CTRL_BIT_MODE_2 | - ME4000_AI_CTRL_BIT_CHANNEL_FIFO | - ME4000_AI_CTRL_BIT_DATA_FIFO; - } else if (cmd->start_src == TRIG_EXT && - cmd->scan_begin_src == TRIG_EXT && - cmd->convert_src == TRIG_EXT) { - tmp = ME4000_AI_CTRL_BIT_MODE_0 | - ME4000_AI_CTRL_BIT_MODE_1 | - ME4000_AI_CTRL_BIT_CHANNEL_FIFO | - ME4000_AI_CTRL_BIT_DATA_FIFO; - } else { - tmp = ME4000_AI_CTRL_BIT_MODE_0 | - ME4000_AI_CTRL_BIT_CHANNEL_FIFO | - ME4000_AI_CTRL_BIT_DATA_FIFO; - } + ctrl = devpriv->ai_ctrl_mode | + ME4000_AI_CTRL_CHANNEL_FIFO | + ME4000_AI_CTRL_DATA_FIFO; /* Stop triggers */ if (cmd->stop_src == TRIG_COUNT) { outl(cmd->chanlist_len * cmd->stop_arg, dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG); - tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ; + ctrl |= ME4000_AI_CTRL_SC_IRQ; } else if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_COUNT) { outl(cmd->scan_end_arg, dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG); - tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ; - } else { - tmp |= ME4000_AI_CTRL_BIT_HF_IRQ; + ctrl |= ME4000_AI_CTRL_SC_IRQ; } + ctrl |= ME4000_AI_CTRL_HF_IRQ; /* Write the setup to the control register */ - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + outl(ctrl, dev->iobase + ME4000_AI_CTRL_REG); /* Write the channel list */ - ai_write_chanlist(dev, s, cmd); - - return 0; -} - -static int me4000_ai_do_cmd(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - int err; - unsigned int init_ticks = 0; - unsigned int scan_ticks = 0; - unsigned int chan_ticks = 0; - struct comedi_cmd *cmd = &s->async->cmd; - - /* Reset the analog input */ - err = me4000_ai_cancel(dev, s); - if (err) - return err; - - /* Round the timer arguments */ - err = ai_round_cmd_args(dev, - s, cmd, &init_ticks, &scan_ticks, &chan_ticks); - if (err) - return err; - - /* Prepare the AI for acquisition */ - err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks); - if (err) - return err; + me4000_ai_write_chanlist(dev, s, cmd); /* Start acquistion by dummy read */ inl(dev->iobase + ME4000_AI_START_REG); @@ -822,14 +714,9 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - unsigned int init_ticks; - unsigned int chan_ticks; - unsigned int scan_ticks; + struct me4000_private *devpriv = dev->private; int err = 0; - /* Round the timer arguments */ - ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks); - /* Step 1 : check if triggers are trivially valid */ err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); @@ -857,21 +744,28 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, if (cmd->start_src == TRIG_NOW && cmd->scan_begin_src == TRIG_TIMER && cmd->convert_src == TRIG_TIMER) { + devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_0; } else if (cmd->start_src == TRIG_NOW && cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_TIMER) { + devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_0; } else if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_TIMER && cmd->convert_src == TRIG_TIMER) { + devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_1; } else if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_TIMER) { + devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_1; } else if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT && cmd->convert_src == TRIG_TIMER) { + devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_2; } else if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT && cmd->convert_src == TRIG_EXT) { + devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_0 | + ME4000_AI_CTRL_MODE_1; } else { err |= -EINVAL; } @@ -887,15 +781,19 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, cmd->chanlist_len = 1; err |= -EINVAL; } - if (init_ticks < 66) { + + /* Round the timer arguments */ + me4000_ai_round_cmd_args(dev, s, cmd); + + if (devpriv->ai_init_ticks < 66) { cmd->start_arg = 2000; err |= -EINVAL; } - if (scan_ticks && scan_ticks < 67) { + if (devpriv->ai_scan_ticks && devpriv->ai_scan_ticks < 67) { cmd->scan_begin_arg = 2031; err |= -EINVAL; } - if (chan_ticks < 66) { + if (devpriv->ai_chan_ticks < 66) { cmd->convert_arg = 2000; err |= -EINVAL; } @@ -915,17 +813,18 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, cmd->scan_begin_src == TRIG_TIMER && cmd->convert_src == TRIG_TIMER) { /* Check timer arguments */ - if (init_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid start arg\n"); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } - if (chan_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid convert arg\n"); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; } - if (scan_ticks <= cmd->chanlist_len * chan_ticks) { + if (devpriv->ai_scan_ticks <= + cmd->chanlist_len * devpriv->ai_chan_ticks) { dev_err(dev->class_dev, "Invalid scan end arg\n"); /* At least one tick more */ @@ -936,12 +835,12 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_TIMER) { /* Check timer arguments */ - if (init_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid start arg\n"); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } - if (chan_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid convert arg\n"); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; @@ -950,17 +849,18 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, cmd->scan_begin_src == TRIG_TIMER && cmd->convert_src == TRIG_TIMER) { /* Check timer arguments */ - if (init_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid start arg\n"); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } - if (chan_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid convert arg\n"); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; } - if (scan_ticks <= cmd->chanlist_len * chan_ticks) { + if (devpriv->ai_scan_ticks <= + cmd->chanlist_len * devpriv->ai_chan_ticks) { dev_err(dev->class_dev, "Invalid scan end arg\n"); /* At least one tick more */ @@ -971,12 +871,12 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_TIMER) { /* Check timer arguments */ - if (init_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid start arg\n"); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } - if (chan_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid convert arg\n"); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; @@ -985,12 +885,12 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, cmd->scan_begin_src == TRIG_EXT && cmd->convert_src == TRIG_TIMER) { /* Check timer arguments */ - if (init_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid start arg\n"); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } - if (chan_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid convert arg\n"); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; @@ -999,7 +899,7 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, cmd->scan_begin_src == TRIG_EXT && cmd->convert_src == TRIG_EXT) { /* Check timer arguments */ - if (init_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid start arg\n"); cmd->start_arg = 2000; /* 66 ticks at least */ err++; @@ -1039,103 +939,57 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) return IRQ_NONE; if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) & - ME4000_IRQ_STATUS_BIT_AI_HF) { + ME4000_IRQ_STATUS_AI_HF) { /* Read status register to find out what happened */ - tmp = inl(dev->iobase + ME4000_AI_CTRL_REG); - - if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) && - !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) && - (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) { - c = ME4000_AI_FIFO_COUNT; - - /* - * FIFO overflow, so stop conversion - * and disable all interrupts - */ - tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; - tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | - ME4000_AI_CTRL_BIT_SC_IRQ); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - - s->async->events |= COMEDI_CB_ERROR; + tmp = inl(dev->iobase + ME4000_AI_STATUS_REG); + if (!(tmp & ME4000_AI_STATUS_FF_DATA) && + !(tmp & ME4000_AI_STATUS_HF_DATA) && + (tmp & ME4000_AI_STATUS_EF_DATA)) { dev_err(dev->class_dev, "FIFO overflow\n"); - } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA) - && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) - && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) { + s->async->events |= COMEDI_CB_ERROR; + c = ME4000_AI_FIFO_COUNT; + } else if ((tmp & ME4000_AI_STATUS_FF_DATA) && + !(tmp & ME4000_AI_STATUS_HF_DATA) && + (tmp & ME4000_AI_STATUS_EF_DATA)) { c = ME4000_AI_FIFO_COUNT / 2; } else { - dev_err(dev->class_dev, - "Can't determine state of fifo\n"); - c = 0; - - /* - * Undefined state, so stop conversion - * and disable all interrupts - */ - tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; - tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | - ME4000_AI_CTRL_BIT_SC_IRQ); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - - s->async->events |= COMEDI_CB_ERROR; - dev_err(dev->class_dev, "Undefined FIFO state\n"); + s->async->events |= COMEDI_CB_ERROR; + c = 0; } for (i = 0; i < c; i++) { - /* Read value from data fifo */ - lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF; - lval ^= 0x8000; - - if (!comedi_buf_write_samples(s, &lval, 1)) { - /* - * Buffer overflow, so stop conversion - * and disable all interrupts - */ - tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; - tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | - ME4000_AI_CTRL_BIT_SC_IRQ); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + lval = me4000_ai_get_sample(dev, s); + if (!comedi_buf_write_samples(s, &lval, 1)) break; - } } /* Work is done, so reset the interrupt */ - tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET; + tmp |= ME4000_AI_CTRL_HF_IRQ_RESET; outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET; + tmp &= ~ME4000_AI_CTRL_HF_IRQ_RESET; outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); } if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) & - ME4000_IRQ_STATUS_BIT_SC) { + ME4000_IRQ_STATUS_SC) { + /* Acquisition is complete */ s->async->events |= COMEDI_CB_EOA; - /* - * Acquisition is complete, so stop - * conversion and disable all interrupts - */ - tmp = inl(dev->iobase + ME4000_AI_CTRL_REG); - tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; - tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - /* Poll data until fifo empty */ - while (inl(dev->iobase + ME4000_AI_CTRL_REG) & - ME4000_AI_STATUS_BIT_EF_DATA) { - /* Read value from data fifo */ - lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF; - lval ^= 0x8000; - + while (inl(dev->iobase + ME4000_AI_STATUS_REG) & + ME4000_AI_STATUS_EF_DATA) { + lval = me4000_ai_get_sample(dev, s); if (!comedi_buf_write_samples(s, &lval, 1)) break; } /* Work is done, so reset the interrupt */ - tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET; + tmp = inl(dev->iobase + ME4000_AI_CTRL_REG); + tmp |= ME4000_AI_CTRL_SC_IRQ_RESET; outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET; + tmp &= ~ME4000_AI_CTRL_SC_IRQ_RESET; outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); } @@ -1149,12 +1003,12 @@ static int me4000_ao_insn_write(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - int chan = CR_CHAN(insn->chanspec); + unsigned int chan = CR_CHAN(insn->chanspec); unsigned int tmp; /* Stop any running conversion */ tmp = inl(dev->iobase + ME4000_AO_CTRL_REG(chan)); - tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP; + tmp |= ME4000_AO_CTRL_IMMEDIATE_STOP; outl(tmp, dev->iobase + ME4000_AO_CTRL_REG(chan)); /* Clear control register and set to single mode */ @@ -1217,18 +1071,18 @@ static int me4000_dio_insn_config(struct comedi_device *dev, return ret; tmp = inl(dev->iobase + ME4000_DIO_CTRL_REG); - tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 | ME4000_DIO_CTRL_BIT_MODE_1 | - ME4000_DIO_CTRL_BIT_MODE_2 | ME4000_DIO_CTRL_BIT_MODE_3 | - ME4000_DIO_CTRL_BIT_MODE_4 | ME4000_DIO_CTRL_BIT_MODE_5 | - ME4000_DIO_CTRL_BIT_MODE_6 | ME4000_DIO_CTRL_BIT_MODE_7); + tmp &= ~(ME4000_DIO_CTRL_MODE_0 | ME4000_DIO_CTRL_MODE_1 | + ME4000_DIO_CTRL_MODE_2 | ME4000_DIO_CTRL_MODE_3 | + ME4000_DIO_CTRL_MODE_4 | ME4000_DIO_CTRL_MODE_5 | + ME4000_DIO_CTRL_MODE_6 | ME4000_DIO_CTRL_MODE_7); if (s->io_bits & 0x000000ff) - tmp |= ME4000_DIO_CTRL_BIT_MODE_0; + tmp |= ME4000_DIO_CTRL_MODE_0; if (s->io_bits & 0x0000ff00) - tmp |= ME4000_DIO_CTRL_BIT_MODE_2; + tmp |= ME4000_DIO_CTRL_MODE_2; if (s->io_bits & 0x00ff0000) - tmp |= ME4000_DIO_CTRL_BIT_MODE_4; + tmp |= ME4000_DIO_CTRL_MODE_4; if (s->io_bits & 0xff000000) - tmp |= ME4000_DIO_CTRL_BIT_MODE_6; + tmp |= ME4000_DIO_CTRL_MODE_6; /* * Check for optoisolated ME-4000 version. @@ -1238,9 +1092,8 @@ static int me4000_dio_insn_config(struct comedi_device *dev, if (inl(dev->iobase + ME4000_DIO_DIR_REG)) { s->io_bits |= 0x000000ff; s->io_bits &= ~0x0000ff00; - tmp |= ME4000_DIO_CTRL_BIT_MODE_0; - tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 | - ME4000_DIO_CTRL_BIT_MODE_3); + tmp |= ME4000_DIO_CTRL_MODE_0; + tmp &= ~(ME4000_DIO_CTRL_MODE_2 | ME4000_DIO_CTRL_MODE_3); } outl(tmp, dev->iobase + ME4000_DIO_CTRL_REG); @@ -1252,29 +1105,29 @@ static int me4000_auto_attach(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct me4000_board *thisboard = NULL; - struct me4000_info *info; + const struct me4000_board *board = NULL; + struct me4000_private *devpriv; struct comedi_subdevice *s; int result; if (context < ARRAY_SIZE(me4000_boards)) - thisboard = &me4000_boards[context]; - if (!thisboard) + board = &me4000_boards[context]; + if (!board) return -ENODEV; - dev->board_ptr = thisboard; - dev->board_name = thisboard->name; + dev->board_ptr = board; + dev->board_name = board->name; - info = comedi_alloc_devpriv(dev, sizeof(*info)); - if (!info) + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); + if (!devpriv) return -ENOMEM; result = comedi_pci_enable(dev); if (result) return result; - info->plx_regbase = pci_resource_start(pcidev, 1); + devpriv->plx_regbase = pci_resource_start(pcidev, 1); dev->iobase = pci_resource_start(pcidev, 2); - if (!info->plx_regbase || !dev->iobase) + if (!devpriv->plx_regbase || !dev->iobase) return -ENODEV; result = comedi_load_firmware(dev, &pcidev->dev, ME4000_FIRMWARE, @@ -1287,79 +1140,66 @@ static int me4000_auto_attach(struct comedi_device *dev, if (pcidev->irq > 0) { result = request_irq(pcidev->irq, me4000_ai_isr, IRQF_SHARED, dev->board_name, dev); - if (result == 0) + if (result == 0) { dev->irq = pcidev->irq; + + /* Enable interrupts on the PLX */ + outl(PLX9052_INTCSR_LI1ENAB | PLX9052_INTCSR_LI1POL | + PLX9052_INTCSR_PCIENAB, + devpriv->plx_regbase + PLX9052_INTCSR); + } } result = comedi_alloc_subdevices(dev, 4); if (result) return result; - /*========================================================================= - Analog input subdevice - ========================================================================*/ - + /* Analog Input subdevice */ s = &dev->subdevices[0]; - - if (thisboard->ai_nchan) { - s->type = COMEDI_SUBD_AI; - s->subdev_flags = - SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; - s->n_chan = thisboard->ai_nchan; - s->maxdata = 0xFFFF; /* 16 bit ADC */ - s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT; - s->range_table = &me4000_ai_range; - s->insn_read = me4000_ai_insn_read; - - if (dev->irq) { - dev->read_subdev = s; - s->subdev_flags |= SDF_CMD_READ; - s->cancel = me4000_ai_cancel; - s->do_cmdtest = me4000_ai_do_cmd_test; - s->do_cmd = me4000_ai_do_cmd; - } - } else { - s->type = COMEDI_SUBD_UNUSED; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND; + if (board->can_do_diff_ai) + s->subdev_flags |= SDF_DIFF; + s->n_chan = board->ai_nchan; + s->maxdata = 0xffff; + s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT; + s->range_table = &me4000_ai_range; + s->insn_read = me4000_ai_insn_read; + + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->cancel = me4000_ai_cancel; + s->do_cmdtest = me4000_ai_do_cmd_test; + s->do_cmd = me4000_ai_do_cmd; } - /*========================================================================= - Analog output subdevice - ========================================================================*/ - + /* Analog Output subdevice */ s = &dev->subdevices[1]; - - if (thisboard->ao_nchan) { - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE | SDF_COMMON | SDF_GROUND; - s->n_chan = thisboard->ao_nchan; - s->maxdata = 0xFFFF; /* 16 bit DAC */ - s->range_table = &range_bipolar10; - s->insn_write = me4000_ao_insn_write; + if (board->has_ao) { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_COMMON | SDF_GROUND; + s->n_chan = 4; + s->maxdata = 0xffff; + s->range_table = &range_bipolar10; + s->insn_write = me4000_ao_insn_write; result = comedi_alloc_subdev_readback(s); if (result) return result; } else { - s->type = COMEDI_SUBD_UNUSED; + s->type = COMEDI_SUBD_UNUSED; } - /*========================================================================= - Digital I/O subdevice - ========================================================================*/ - + /* Digital I/O subdevice */ s = &dev->subdevices[2]; - - if (thisboard->dio_nchan) { - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = thisboard->dio_nchan; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = me4000_dio_insn_bits; - s->insn_config = me4000_dio_insn_config; - } else { - s->type = COMEDI_SUBD_UNUSED; - } + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 32; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = me4000_dio_insn_bits; + s->insn_config = me4000_dio_insn_config; /* * Check for optoisolated ME-4000 version. If one the first @@ -1367,13 +1207,13 @@ static int me4000_auto_attach(struct comedi_device *dev, */ if (!inl(dev->iobase + ME4000_DIO_DIR_REG)) { s->io_bits |= 0xFF; - outl(ME4000_DIO_CTRL_BIT_MODE_0, + outl(ME4000_DIO_CTRL_MODE_0, dev->iobase + ME4000_DIO_DIR_REG); } /* Counter subdevice (8254) */ s = &dev->subdevices[3]; - if (thisboard->has_counter) { + if (board->has_counter) { unsigned long timer_base = pci_resource_start(pcidev, 3); if (!timer_base) @@ -1393,8 +1233,12 @@ static int me4000_auto_attach(struct comedi_device *dev, static void me4000_detach(struct comedi_device *dev) { - if (dev->iobase) - me4000_reset(dev); + if (dev->irq) { + struct me4000_private *devpriv = dev->private; + + /* Disable interrupts on the PLX */ + outl(0, devpriv->plx_regbase + PLX9052_INTCSR); + } comedi_pci_detach(dev); } @@ -1438,6 +1282,6 @@ static struct pci_driver me4000_pci_driver = { module_comedi_pci_driver(me4000_driver, me4000_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for Meilhaus ME-4000 series boards"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(ME4000_FIRMWARE); diff --git a/kernel/drivers/staging/comedi/drivers/me_daq.c b/kernel/drivers/staging/comedi/drivers/me_daq.c index d78e9195f..3bf0caa18 100644 --- a/kernel/drivers/staging/comedi/drivers/me_daq.c +++ b/kernel/drivers/staging/comedi/drivers/me_daq.c @@ -41,84 +41,63 @@ #define XILINX_DOWNLOAD_RESET 0x42 /* Xilinx registers */ -#define ME_CONTROL_1 0x0000 /* - | W */ -#define INTERRUPT_ENABLE (1<<15) -#define COUNTER_B_IRQ (1<<12) -#define COUNTER_A_IRQ (1<<11) -#define CHANLIST_READY_IRQ (1<<10) -#define EXT_IRQ (1<<9) -#define ADFIFO_HALFFULL_IRQ (1<<8) -#define SCAN_COUNT_ENABLE (1<<5) -#define SIMULTANEOUS_ENABLE (1<<4) -#define TRIGGER_FALLING_EDGE (1<<3) -#define CONTINUOUS_MODE (1<<2) -#define DISABLE_ADC (0<<0) -#define SOFTWARE_TRIGGERED_ADC (1<<0) -#define SCAN_TRIGGERED_ADC (2<<0) -#define EXT_TRIGGERED_ADC (3<<0) -#define ME_ADC_START 0x0000 /* R | - */ -#define ME_CONTROL_2 0x0002 /* - | W */ -#define ENABLE_ADFIFO (1<<10) -#define ENABLE_CHANLIST (1<<9) -#define ENABLE_PORT_B (1<<7) -#define ENABLE_PORT_A (1<<6) -#define ENABLE_COUNTER_B (1<<4) -#define ENABLE_COUNTER_A (1<<3) -#define ENABLE_DAC (1<<1) -#define BUFFERED_DAC (1<<0) -#define ME_DAC_UPDATE 0x0002 /* R | - */ -#define ME_STATUS 0x0004 /* R | - */ -#define COUNTER_B_IRQ_PENDING (1<<12) -#define COUNTER_A_IRQ_PENDING (1<<11) -#define CHANLIST_READY_IRQ_PENDING (1<<10) -#define EXT_IRQ_PENDING (1<<9) -#define ADFIFO_HALFFULL_IRQ_PENDING (1<<8) -#define ADFIFO_FULL (1<<4) -#define ADFIFO_HALFFULL (1<<3) -#define ADFIFO_EMPTY (1<<2) -#define CHANLIST_FULL (1<<1) -#define FST_ACTIVE (1<<0) -#define ME_RESET_INTERRUPT 0x0004 /* - | W */ -#define ME_DIO_PORT_A 0x0006 /* R | W */ -#define ME_DIO_PORT_B 0x0008 /* R | W */ -#define ME_TIMER_DATA_0 0x000A /* - | W */ -#define ME_TIMER_DATA_1 0x000C /* - | W */ -#define ME_TIMER_DATA_2 0x000E /* - | W */ -#define ME_CHANNEL_LIST 0x0010 /* - | W */ -#define ADC_UNIPOLAR (1<<6) -#define ADC_GAIN_0 (0<<4) -#define ADC_GAIN_1 (1<<4) -#define ADC_GAIN_2 (2<<4) -#define ADC_GAIN_3 (3<<4) -#define ME_READ_AD_FIFO 0x0010 /* R | - */ -#define ME_DAC_CONTROL 0x0012 /* - | W */ -#define DAC_UNIPOLAR_D (0<<4) -#define DAC_BIPOLAR_D (1<<4) -#define DAC_UNIPOLAR_C (0<<5) -#define DAC_BIPOLAR_C (1<<5) -#define DAC_UNIPOLAR_B (0<<6) -#define DAC_BIPOLAR_B (1<<6) -#define DAC_UNIPOLAR_A (0<<7) -#define DAC_BIPOLAR_A (1<<7) -#define DAC_GAIN_0_D (0<<8) -#define DAC_GAIN_1_D (1<<8) -#define DAC_GAIN_0_C (0<<9) -#define DAC_GAIN_1_C (1<<9) -#define DAC_GAIN_0_B (0<<10) -#define DAC_GAIN_1_B (1<<10) -#define DAC_GAIN_0_A (0<<11) -#define DAC_GAIN_1_A (1<<11) -#define ME_DAC_CONTROL_UPDATE 0x0012 /* R | - */ -#define ME_DAC_DATA_A 0x0014 /* - | W */ -#define ME_DAC_DATA_B 0x0016 /* - | W */ -#define ME_DAC_DATA_C 0x0018 /* - | W */ -#define ME_DAC_DATA_D 0x001A /* - | W */ -#define ME_COUNTER_ENDDATA_A 0x001C /* - | W */ -#define ME_COUNTER_ENDDATA_B 0x001E /* - | W */ -#define ME_COUNTER_STARTDATA_A 0x0020 /* - | W */ -#define ME_COUNTER_VALUE_A 0x0020 /* R | - */ -#define ME_COUNTER_STARTDATA_B 0x0022 /* - | W */ -#define ME_COUNTER_VALUE_B 0x0022 /* R | - */ +/* + * PCI BAR2 Memory map (dev->mmio) + */ +#define ME_CTRL1_REG 0x00 /* R (ai start) | W */ +#define ME_CTRL1_INT_ENA BIT(15) +#define ME_CTRL1_COUNTER_B_IRQ BIT(12) +#define ME_CTRL1_COUNTER_A_IRQ BIT(11) +#define ME_CTRL1_CHANLIST_READY_IRQ BIT(10) +#define ME_CTRL1_EXT_IRQ BIT(9) +#define ME_CTRL1_ADFIFO_HALFFULL_IRQ BIT(8) +#define ME_CTRL1_SCAN_COUNT_ENA BIT(5) +#define ME_CTRL1_SIMULTANEOUS_ENA BIT(4) +#define ME_CTRL1_TRIGGER_FALLING_EDGE BIT(3) +#define ME_CTRL1_CONTINUOUS_MODE BIT(2) +#define ME_CTRL1_ADC_MODE(x) (((x) & 0x3) << 0) +#define ME_CTRL1_ADC_MODE_DISABLE ME_CTRL1_ADC_MODE(0) +#define ME_CTRL1_ADC_MODE_SOFT_TRIG ME_CTRL1_ADC_MODE(1) +#define ME_CTRL1_ADC_MODE_SCAN_TRIG ME_CTRL1_ADC_MODE(2) +#define ME_CTRL1_ADC_MODE_EXT_TRIG ME_CTRL1_ADC_MODE(3) +#define ME_CTRL1_ADC_MODE_MASK ME_CTRL1_ADC_MODE(3) +#define ME_CTRL2_REG 0x02 /* R (dac update) | W */ +#define ME_CTRL2_ADFIFO_ENA BIT(10) +#define ME_CTRL2_CHANLIST_ENA BIT(9) +#define ME_CTRL2_PORT_B_ENA BIT(7) +#define ME_CTRL2_PORT_A_ENA BIT(6) +#define ME_CTRL2_COUNTER_B_ENA BIT(4) +#define ME_CTRL2_COUNTER_A_ENA BIT(3) +#define ME_CTRL2_DAC_ENA BIT(1) +#define ME_CTRL2_BUFFERED_DAC BIT(0) +#define ME_STATUS_REG 0x04 /* R | W (clears interrupts) */ +#define ME_STATUS_COUNTER_B_IRQ BIT(12) +#define ME_STATUS_COUNTER_A_IRQ BIT(11) +#define ME_STATUS_CHANLIST_READY_IRQ BIT(10) +#define ME_STATUS_EXT_IRQ BIT(9) +#define ME_STATUS_ADFIFO_HALFFULL_IRQ BIT(8) +#define ME_STATUS_ADFIFO_FULL BIT(4) +#define ME_STATUS_ADFIFO_HALFFULL BIT(3) +#define ME_STATUS_ADFIFO_EMPTY BIT(2) +#define ME_STATUS_CHANLIST_FULL BIT(1) +#define ME_STATUS_FST_ACTIVE BIT(0) +#define ME_DIO_PORT_A_REG 0x06 /* R | W */ +#define ME_DIO_PORT_B_REG 0x08 /* R | W */ +#define ME_TIMER_DATA_REG(x) (0x0a + ((x) * 2)) /* - | W */ +#define ME_AI_FIFO_REG 0x10 /* R (fifo) | W (chanlist) */ +#define ME_AI_FIFO_CHANLIST_DIFF BIT(7) +#define ME_AI_FIFO_CHANLIST_UNIPOLAR BIT(6) +#define ME_AI_FIFO_CHANLIST_GAIN(x) (((x) & 0x3) << 4) +#define ME_AI_FIFO_CHANLIST_CHAN(x) (((x) & 0xf) << 0) +#define ME_DAC_CTRL_REG 0x12 /* R (updates) | W */ +#define ME_DAC_CTRL_BIPOLAR(x) BIT(7 - ((x) & 0x3)) +#define ME_DAC_CTRL_GAIN(x) BIT(11 - ((x) & 0x3)) +#define ME_DAC_CTRL_MASK(x) (ME_DAC_CTRL_BIPOLAR(x) | \ + ME_DAC_CTRL_GAIN(x)) +#define ME_AO_DATA_REG(x) (0x14 + ((x) * 2)) /* - | W */ +#define ME_COUNTER_ENDDATA_REG(x) (0x1c + ((x) * 2)) /* - | W */ +#define ME_COUNTER_STARTDATA_REG(x) (0x20 + ((x) * 2)) /* - | W */ +#define ME_COUNTER_VALUE_REG(x) (0x20 + ((x) * 2)) /* R | - */ static const struct comedi_lrange me_ai_range = { 8, { @@ -166,15 +145,14 @@ static const struct me_board me_boards[] = { struct me_private_data { void __iomem *plx_regbase; /* PLX configuration base address */ - unsigned short control_1; /* Mirror of CONTROL_1 register */ - unsigned short control_2; /* Mirror of CONTROL_2 register */ - unsigned short dac_control; /* Mirror of the DAC_CONTROL register */ + unsigned short ctrl1; /* Mirror of CONTROL_1 register */ + unsigned short ctrl2; /* Mirror of CONTROL_2 register */ + unsigned short dac_ctrl; /* Mirror of the DAC_CONTROL register */ }; static inline void sleep(unsigned sec) { - __set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(sec * HZ); + schedule_timeout_interruptible(sec * HZ); } static int me_dio_insn_config(struct comedi_device *dev, @@ -197,15 +175,15 @@ static int me_dio_insn_config(struct comedi_device *dev, return ret; if (s->io_bits & 0x0000ffff) - devpriv->control_2 |= ENABLE_PORT_A; + devpriv->ctrl2 |= ME_CTRL2_PORT_A_ENA; else - devpriv->control_2 &= ~ENABLE_PORT_A; + devpriv->ctrl2 &= ~ME_CTRL2_PORT_A_ENA; if (s->io_bits & 0xffff0000) - devpriv->control_2 |= ENABLE_PORT_B; + devpriv->ctrl2 |= ME_CTRL2_PORT_B_ENA; else - devpriv->control_2 &= ~ENABLE_PORT_B; + devpriv->ctrl2 &= ~ME_CTRL2_PORT_B_ENA; - writew(devpriv->control_2, dev->mmio + ME_CONTROL_2); + writew(devpriv->ctrl2, dev->mmio + ME_CTRL2_REG); return insn->n; } @@ -215,8 +193,8 @@ static int me_dio_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - void __iomem *mmio_porta = dev->mmio + ME_DIO_PORT_A; - void __iomem *mmio_portb = dev->mmio + ME_DIO_PORT_B; + void __iomem *mmio_porta = dev->mmio + ME_DIO_PORT_A_REG; + void __iomem *mmio_portb = dev->mmio + ME_DIO_PORT_B_REG; unsigned int mask; unsigned int val; @@ -250,8 +228,8 @@ static int me_ai_eoc(struct comedi_device *dev, { unsigned int status; - status = readw(dev->mmio + ME_STATUS); - if ((status & 0x0004) == 0) + status = readw(dev->mmio + ME_STATUS_REG); + if ((status & ME_STATUS_ADFIFO_EMPTY) == 0) return 0; return -EBUSY; } @@ -261,57 +239,66 @@ static int me_ai_insn_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct me_private_data *dev_private = dev->private; + struct me_private_data *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); - unsigned int rang = CR_RANGE(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); unsigned int aref = CR_AREF(insn->chanspec); - unsigned short val; - int ret; + unsigned int val; + int ret = 0; + int i; - /* stop any running conversion */ - dev_private->control_1 &= 0xFFFC; - writew(dev_private->control_1, dev->mmio + ME_CONTROL_1); + /* + * For differential operation, there are only 8 input channels + * and only bipolar ranges are available. + */ + if (aref & AREF_DIFF) { + if (chan > 7 || comedi_range_is_unipolar(s, range)) + return -EINVAL; + } /* clear chanlist and ad fifo */ - dev_private->control_2 &= ~(ENABLE_ADFIFO | ENABLE_CHANLIST); - writew(dev_private->control_2, dev->mmio + ME_CONTROL_2); + devpriv->ctrl2 &= ~(ME_CTRL2_ADFIFO_ENA | ME_CTRL2_CHANLIST_ENA); + writew(devpriv->ctrl2, dev->mmio + ME_CTRL2_REG); - /* reset any pending interrupt */ - writew(0x00, dev->mmio + ME_RESET_INTERRUPT); + writew(0x00, dev->mmio + ME_STATUS_REG); /* clear interrupts */ /* enable the chanlist and ADC fifo */ - dev_private->control_2 |= (ENABLE_ADFIFO | ENABLE_CHANLIST); - writew(dev_private->control_2, dev->mmio + ME_CONTROL_2); + devpriv->ctrl2 |= (ME_CTRL2_ADFIFO_ENA | ME_CTRL2_CHANLIST_ENA); + writew(devpriv->ctrl2, dev->mmio + ME_CTRL2_REG); /* write to channel list fifo */ - val = chan & 0x0f; /* b3:b0 channel */ - val |= (rang & 0x03) << 4; /* b5:b4 gain */ - val |= (rang & 0x04) << 4; /* b6 polarity */ - val |= ((aref & AREF_DIFF) ? 0x80 : 0); /* b7 differential */ - writew(val & 0xff, dev->mmio + ME_CHANNEL_LIST); + val = ME_AI_FIFO_CHANLIST_CHAN(chan) | ME_AI_FIFO_CHANLIST_GAIN(range); + if (comedi_range_is_unipolar(s, range)) + val |= ME_AI_FIFO_CHANLIST_UNIPOLAR; + if (aref & AREF_DIFF) + val |= ME_AI_FIFO_CHANLIST_DIFF; + writew(val, dev->mmio + ME_AI_FIFO_REG); /* set ADC mode to software trigger */ - dev_private->control_1 |= SOFTWARE_TRIGGERED_ADC; - writew(dev_private->control_1, dev->mmio + ME_CONTROL_1); + devpriv->ctrl1 |= ME_CTRL1_ADC_MODE_SOFT_TRIG; + writew(devpriv->ctrl1, dev->mmio + ME_CTRL1_REG); + + for (i = 0; i < insn->n; i++) { + /* start ai conversion */ + readw(dev->mmio + ME_CTRL1_REG); - /* start conversion by reading from ADC_START */ - readw(dev->mmio + ME_ADC_START); + /* wait for ADC fifo not empty flag */ + ret = comedi_timeout(dev, s, insn, me_ai_eoc, 0); + if (ret) + break; - /* wait for ADC fifo not empty flag */ - ret = comedi_timeout(dev, s, insn, me_ai_eoc, 0); - if (ret) - return ret; + /* get value from ADC fifo */ + val = readw(dev->mmio + ME_AI_FIFO_REG) & s->maxdata; - /* get value from ADC fifo */ - val = readw(dev->mmio + ME_READ_AD_FIFO); - val = (val ^ 0x800) & 0x0fff; - data[0] = val; + /* munge 2's complement value to offset binary */ + data[i] = comedi_offset_munge(s, val); + } /* stop any running conversion */ - dev_private->control_1 &= 0xFFFC; - writew(dev_private->control_1, dev->mmio + ME_CONTROL_1); + devpriv->ctrl1 &= ~ME_CTRL1_ADC_MODE_MASK; + writew(devpriv->ctrl1, dev->mmio + ME_CTRL1_REG); - return 1; + return ret ? ret : insn->n; } static int me_ao_insn_write(struct comedi_device *dev, @@ -319,46 +306,41 @@ static int me_ao_insn_write(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct me_private_data *dev_private = dev->private; + struct me_private_data *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); - unsigned int rang = CR_RANGE(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); unsigned int val = s->readback[chan]; int i; /* Enable all DAC */ - dev_private->control_2 |= ENABLE_DAC; - writew(dev_private->control_2, dev->mmio + ME_CONTROL_2); + devpriv->ctrl2 |= ME_CTRL2_DAC_ENA; + writew(devpriv->ctrl2, dev->mmio + ME_CTRL2_REG); /* and set DAC to "buffered" mode */ - dev_private->control_2 |= BUFFERED_DAC; - writew(dev_private->control_2, dev->mmio + ME_CONTROL_2); + devpriv->ctrl2 |= ME_CTRL2_BUFFERED_DAC; + writew(devpriv->ctrl2, dev->mmio + ME_CTRL2_REG); /* Set dac-control register */ - for (i = 0; i < insn->n; i++) { - /* clear bits for this channel */ - dev_private->dac_control &= ~(0x0880 >> chan); - if (rang == 0) - dev_private->dac_control |= - ((DAC_BIPOLAR_A | DAC_GAIN_1_A) >> chan); - else if (rang == 1) - dev_private->dac_control |= - ((DAC_BIPOLAR_A | DAC_GAIN_0_A) >> chan); - } - writew(dev_private->dac_control, dev->mmio + ME_DAC_CONTROL); + devpriv->dac_ctrl &= ~ME_DAC_CTRL_MASK(chan); + if (range == 0) + devpriv->dac_ctrl |= ME_DAC_CTRL_GAIN(chan); + if (comedi_range_is_bipolar(s, range)) + devpriv->dac_ctrl |= ME_DAC_CTRL_BIPOLAR(chan); + writew(devpriv->dac_ctrl, dev->mmio + ME_DAC_CTRL_REG); /* Update dac-control register */ - readw(dev->mmio + ME_DAC_CONTROL_UPDATE); + readw(dev->mmio + ME_DAC_CTRL_REG); /* Set data register */ for (i = 0; i < insn->n; i++) { val = data[i]; - writew(val, dev->mmio + ME_DAC_DATA_A + (chan << 1)); + writew(val, dev->mmio + ME_AO_DATA_REG(chan)); } s->readback[chan] = val; /* Update dac with data registers */ - readw(dev->mmio + ME_DAC_UPDATE); + readw(dev->mmio + ME_CTRL2_REG); return insn->n; } @@ -367,13 +349,13 @@ static int me2600_xilinx_download(struct comedi_device *dev, const u8 *data, size_t size, unsigned long context) { - struct me_private_data *dev_private = dev->private; + struct me_private_data *devpriv = dev->private; unsigned int value; unsigned int file_length; unsigned int i; /* disable irq's on PLX */ - writel(0x00, dev_private->plx_regbase + PLX9052_INTCSR); + writel(0x00, devpriv->plx_regbase + PLX9052_INTCSR); /* First, make a dummy read to reset xilinx */ value = readw(dev->mmio + XILINX_DOWNLOAD_RESET); @@ -413,10 +395,10 @@ static int me2600_xilinx_download(struct comedi_device *dev, writeb(0x00, dev->mmio + 0x0); /* Test if there was an error during download -> INTB was thrown */ - value = readl(dev_private->plx_regbase + PLX9052_INTCSR); + value = readl(devpriv->plx_regbase + PLX9052_INTCSR); if (value & PLX9052_INTCSR_LI2STAT) { /* Disable interrupt */ - writel(0x00, dev_private->plx_regbase + PLX9052_INTCSR); + writel(0x00, devpriv->plx_regbase + PLX9052_INTCSR); dev_err(dev->class_dev, "Xilinx download failed\n"); return -EIO; } @@ -428,25 +410,25 @@ static int me2600_xilinx_download(struct comedi_device *dev, writel(PLX9052_INTCSR_LI1ENAB | PLX9052_INTCSR_LI1POL | PLX9052_INTCSR_PCIENAB, - dev_private->plx_regbase + PLX9052_INTCSR); + devpriv->plx_regbase + PLX9052_INTCSR); return 0; } static int me_reset(struct comedi_device *dev) { - struct me_private_data *dev_private = dev->private; + struct me_private_data *devpriv = dev->private; /* Reset board */ - writew(0x00, dev->mmio + ME_CONTROL_1); - writew(0x00, dev->mmio + ME_CONTROL_2); - writew(0x00, dev->mmio + ME_RESET_INTERRUPT); - writew(0x00, dev->mmio + ME_DAC_CONTROL); + writew(0x00, dev->mmio + ME_CTRL1_REG); + writew(0x00, dev->mmio + ME_CTRL2_REG); + writew(0x00, dev->mmio + ME_STATUS_REG); /* clear interrupts */ + writew(0x00, dev->mmio + ME_DAC_CTRL_REG); /* Save values in the board context */ - dev_private->dac_control = 0; - dev_private->control_1 = 0; - dev_private->control_2 = 0; + devpriv->dac_ctrl = 0; + devpriv->ctrl1 = 0; + devpriv->ctrl2 = 0; return 0; } @@ -456,7 +438,7 @@ static int me_auto_attach(struct comedi_device *dev, { struct pci_dev *pcidev = comedi_to_pci_dev(dev); const struct me_board *board = NULL; - struct me_private_data *dev_private; + struct me_private_data *devpriv; struct comedi_subdevice *s; int ret; @@ -467,16 +449,16 @@ static int me_auto_attach(struct comedi_device *dev, dev->board_ptr = board; dev->board_name = board->name; - dev_private = comedi_alloc_devpriv(dev, sizeof(*dev_private)); - if (!dev_private) + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); + if (!devpriv) return -ENOMEM; ret = comedi_pci_enable(dev); if (ret) return ret; - dev_private->plx_regbase = pci_ioremap_bar(pcidev, 0); - if (!dev_private->plx_regbase) + devpriv->plx_regbase = pci_ioremap_bar(pcidev, 0); + if (!devpriv->plx_regbase) return -ENOMEM; dev->mmio = pci_ioremap_bar(pcidev, 2); @@ -499,7 +481,7 @@ static int me_auto_attach(struct comedi_device *dev, s = &dev->subdevices[0]; s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_COMMON; + s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_DIFF; s->n_chan = 16; s->maxdata = 0x0fff; s->len_chanlist = 16; @@ -538,13 +520,13 @@ static int me_auto_attach(struct comedi_device *dev, static void me_detach(struct comedi_device *dev) { - struct me_private_data *dev_private = dev->private; + struct me_private_data *devpriv = dev->private; - if (dev_private) { + if (devpriv) { if (dev->mmio) me_reset(dev); - if (dev_private->plx_regbase) - iounmap(dev_private->plx_regbase); + if (devpriv->plx_regbase) + iounmap(devpriv->plx_regbase); } comedi_pci_detach(dev); } diff --git a/kernel/drivers/staging/comedi/drivers/mf6x4.c b/kernel/drivers/staging/comedi/drivers/mf6x4.c index a675e2ef9..fbdf181d8 100644 --- a/kernel/drivers/staging/comedi/drivers/mf6x4.c +++ b/kernel/drivers/staging/comedi/drivers/mf6x4.c @@ -31,36 +31,24 @@ #include "../comedi_pci.h" /* Registers present in BAR0 memory region */ -#define MF624_GPIOC_R 0x54 +#define MF624_GPIOC_REG 0x54 -#define MF6X4_GPIOC_EOLC /* End Of Last Conversion */ (1 << 17) -#define MF6X4_GPIOC_LDAC /* Load DACs */ (1 << 23) -#define MF6X4_GPIOC_DACEN (1 << 26) +#define MF6X4_GPIOC_EOLC BIT(17) /* End Of Last Conversion */ +#define MF6X4_GPIOC_LDAC BIT(23) /* Load DACs */ +#define MF6X4_GPIOC_DACEN BIT(26) /* BAR1 registers */ -#define MF6X4_DIN_R 0x10 -#define MF6X4_DIN_M 0xff -#define MF6X4_DOUT_R 0x10 -#define MF6X4_DOUT_M 0xff - -#define MF6X4_ADSTART_R 0x20 -#define MF6X4_ADDATA_R 0x00 -#define MF6X4_ADCTRL_R 0x00 -#define MF6X4_ADCTRL_M 0xff - -#define MF6X4_DA0_R 0x20 -#define MF6X4_DA1_R 0x22 -#define MF6X4_DA2_R 0x24 -#define MF6X4_DA3_R 0x26 -#define MF6X4_DA4_R 0x28 -#define MF6X4_DA5_R 0x2a -#define MF6X4_DA6_R 0x2c -#define MF6X4_DA7_R 0x2e -/* Map DAC cahnnel id to real HW-dependent offset value */ -#define MF6X4_DAC_R(x) (0x20 + ((x) * 2)) +#define MF6X4_ADDATA_REG 0x00 +#define MF6X4_ADCTRL_REG 0x00 +#define MF6X4_ADCTRL_CHAN(x) BIT(chan) +#define MF6X4_DIN_REG 0x10 +#define MF6X4_DIN_MASK 0xff +#define MF6X4_DOUT_REG 0x10 +#define MF6X4_ADSTART_REG 0x20 +#define MF6X4_DAC_REG(x) (0x20 + ((x) * 2)) /* BAR2 registers */ -#define MF634_GPIOC_R 0x68 +#define MF634_GPIOC_REG 0x68 enum mf6x4_boardid { BOARD_MF634, @@ -69,8 +57,8 @@ enum mf6x4_boardid { struct mf6x4_board { const char *name; - unsigned int bar_nums[3]; /* We need to keep track of the - order of BARs used by the cards */ + /* We need to keep track of the order of BARs used by the cards */ + unsigned int bar_nums[3]; }; static const struct mf6x4_board mf6x4_boards[] = { @@ -99,7 +87,7 @@ struct mf6x4_private { * for both cards however it lies in different BARs on different * offsets -- this variable makes the access easier */ - void __iomem *gpioc_R; + void __iomem *gpioc_reg; }; static int mf6x4_di_insn_bits(struct comedi_device *dev, @@ -107,7 +95,7 @@ static int mf6x4_di_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - data[1] = ioread16(dev->mmio + MF6X4_DIN_R) & MF6X4_DIN_M; + data[1] = ioread16(dev->mmio + MF6X4_DIN_REG) & MF6X4_DIN_MASK; return insn->n; } @@ -118,7 +106,7 @@ static int mf6x4_do_insn_bits(struct comedi_device *dev, unsigned int *data) { if (comedi_dio_update_state(s, data)) - iowrite16(s->state & MF6X4_DOUT_M, dev->mmio + MF6X4_DOUT_R); + iowrite16(s->state, dev->mmio + MF6X4_DOUT_REG); data[1] = s->state; @@ -133,7 +121,7 @@ static int mf6x4_ai_eoc(struct comedi_device *dev, struct mf6x4_private *devpriv = dev->private; unsigned int status; - status = ioread32(devpriv->gpioc_R); + status = ioread32(devpriv->gpioc_reg); if (status & MF6X4_GPIOC_EOLC) return 0; return -EBUSY; @@ -144,29 +132,30 @@ static int mf6x4_ai_insn_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - int chan = CR_CHAN(insn->chanspec); + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int d; int ret; int i; - int d; /* Set the ADC channel number in the scan list */ - iowrite16((1 << chan) & MF6X4_ADCTRL_M, dev->mmio + MF6X4_ADCTRL_R); + iowrite16(MF6X4_ADCTRL_CHAN(chan), dev->mmio + MF6X4_ADCTRL_REG); for (i = 0; i < insn->n; i++) { /* Trigger ADC conversion by reading ADSTART */ - ioread16(dev->mmio + MF6X4_ADSTART_R); + ioread16(dev->mmio + MF6X4_ADSTART_REG); ret = comedi_timeout(dev, s, insn, mf6x4_ai_eoc, 0); if (ret) return ret; /* Read the actual value */ - d = ioread16(dev->mmio + MF6X4_ADDATA_R); + d = ioread16(dev->mmio + MF6X4_ADDATA_REG); d &= s->maxdata; - data[i] = d; + /* munge the 2's complement data to offset binary */ + data[i] = comedi_offset_munge(s, d); } - iowrite16(0x0, dev->mmio + MF6X4_ADCTRL_R); + iowrite16(0x0, dev->mmio + MF6X4_ADCTRL_REG); return insn->n; } @@ -179,17 +168,17 @@ static int mf6x4_ao_insn_write(struct comedi_device *dev, struct mf6x4_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); unsigned int val = s->readback[chan]; - uint32_t gpioc; + unsigned int gpioc; int i; /* Enable instantaneous update of converters outputs + Enable DACs */ - gpioc = ioread32(devpriv->gpioc_R); + gpioc = ioread32(devpriv->gpioc_reg); iowrite32((gpioc & ~MF6X4_GPIOC_LDAC) | MF6X4_GPIOC_DACEN, - devpriv->gpioc_R); + devpriv->gpioc_reg); for (i = 0; i < insn->n; i++) { val = data[i]; - iowrite16(val, dev->mmio + MF6X4_DAC_R(chan)); + iowrite16(val, dev->mmio + MF6X4_DAC_REG(chan)); } s->readback[chan] = val; @@ -233,53 +222,53 @@ static int mf6x4_auto_attach(struct comedi_device *dev, unsigned long context) return -ENODEV; if (board == &mf6x4_boards[BOARD_MF634]) - devpriv->gpioc_R = devpriv->bar2_mem + MF634_GPIOC_R; + devpriv->gpioc_reg = devpriv->bar2_mem + MF634_GPIOC_REG; else - devpriv->gpioc_R = devpriv->bar0_mem + MF624_GPIOC_R; + devpriv->gpioc_reg = devpriv->bar0_mem + MF624_GPIOC_REG; ret = comedi_alloc_subdevices(dev, 4); if (ret) return ret; - /* ADC */ + /* Analog Input subdevice */ s = &dev->subdevices[0]; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND; - s->n_chan = 8; - s->maxdata = 0x3fff; /* 14 bits ADC */ - s->range_table = &range_bipolar10; - s->insn_read = mf6x4_ai_insn_read; - - /* DAC */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND; + s->n_chan = 8; + s->maxdata = 0x3fff; + s->range_table = &range_bipolar10; + s->insn_read = mf6x4_ai_insn_read; + + /* Analog Output subdevice */ s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 8; - s->maxdata = 0x3fff; /* 14 bits DAC */ - s->range_table = &range_bipolar10; - s->insn_write = mf6x4_ao_insn_write; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 0x3fff; + s->range_table = &range_bipolar10; + s->insn_write = mf6x4_ao_insn_write; ret = comedi_alloc_subdev_readback(s); if (ret) return ret; - /* DIN */ + /* Digital Input subdevice */ s = &dev->subdevices[2]; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 8; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = mf6x4_di_insn_bits; - - /* DOUT */ + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = mf6x4_di_insn_bits; + + /* Digital Output subdevice */ s = &dev->subdevices[3]; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 8; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = mf6x4_do_insn_bits; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = mf6x4_do_insn_bits; return 0; } diff --git a/kernel/drivers/staging/comedi/drivers/mite.c b/kernel/drivers/staging/comedi/drivers/mite.c index e43a0c832..fa7ae2c04 100644 --- a/kernel/drivers/staging/comedi/drivers/mite.c +++ b/kernel/drivers/staging/comedi/drivers/mite.c @@ -1,52 +1,51 @@ /* - comedi/drivers/mite.c - Hardware driver for NI Mite PCI interface chip - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-2002 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedi/drivers/mite.c + * Hardware driver for NI Mite PCI interface chip + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2002 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ /* - The PCI-MIO E series driver was originally written by - Tomasz Motylewski <...>, and ported to comedi by ds. - - References for specifications: - - 321747b.pdf Register Level Programmer Manual (obsolete) - 321747c.pdf Register Level Programmer Manual (new) - DAQ-STC reference manual - - Other possibly relevant info: - - 320517c.pdf User manual (obsolete) - 320517f.pdf User manual (new) - 320889a.pdf delete - 320906c.pdf maximum signal ratings - 321066a.pdf about 16x - 321791a.pdf discontinuation of at-mio-16e-10 rev. c - 321808a.pdf about at-mio-16e-10 rev P - 321837a.pdf discontinuation of at-mio-16de-10 rev d - 321838a.pdf about at-mio-16de-10 rev N - - ISSUES: - -*/ - -/* #define USE_KMALLOC */ + * The PCI-MIO E series driver was originally written by + * Tomasz Motylewski <...>, and ported to comedi by ds. + * + * References for specifications: + * + * 321747b.pdf Register Level Programmer Manual (obsolete) + * 321747c.pdf Register Level Programmer Manual (new) + * DAQ-STC reference manual + * + * Other possibly relevant info: + * + * 320517c.pdf User manual (obsolete) + * 320517f.pdf User manual (new) + * 320889a.pdf delete + * 320906c.pdf maximum signal ratings + * 321066a.pdf about 16x + * 321791a.pdf discontinuation of at-mio-16e-10 rev. c + * 321808a.pdf about at-mio-16e-10 rev P + * 321837a.pdf discontinuation of at-mio-16de-10 rev d + * 321838a.pdf about at-mio-16de-10 rev N + * + * ISSUES: + * + */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/module.h> +#include <linux/slab.h> #include "../comedi_pci.h" @@ -132,7 +131,7 @@ int mite_setup2(struct comedi_device *dev, mite->mite_io_addr + MITE_IODWBSR); } /* - * make sure dma bursts work. I got this from running a bus analyzer + * Make sure dma bursts work. I got this from running a bus analyzer * on a pxi-6281 and a pxi-6713. 6713 powered up with register value * of 0x61f and bursts worked. 6281 powered up with register value of * 0x1f and bursts didn't work. The NI windows driver reads the @@ -224,7 +223,8 @@ struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite, unsigned long flags; struct mite_channel *channel = NULL; - /* spin lock so mite_release_channel can be called safely + /* + * spin lock so mite_release_channel can be called safely * from interrupts */ spin_lock_irqsave(&mite->lock, flags); @@ -246,15 +246,15 @@ void mite_release_channel(struct mite_channel *mite_chan) struct mite_struct *mite = mite_chan->mite; unsigned long flags; - /* spin lock to prevent races with mite_request_channel */ + /* spin lock to prevent races with mite_request_channel */ spin_lock_irqsave(&mite->lock, flags); if (mite->channel_allocated[mite_chan->channel]) { mite_dma_disarm(mite_chan); mite_dma_reset(mite_chan); - /* - * disable all channel's interrupts (do it after disarm/reset so - * MITE_CHCR reg isn't changed while dma is still active!) - */ + /* + * disable all channel's interrupts (do it after disarm/reset so + * MITE_CHCR reg isn't changed while dma is still active!) + */ writel(CHCR_CLR_DMA_IE | CHCR_CLR_LINKP_IE | CHCR_CLR_SAR_IE | CHCR_CLR_DONE_IE | CHCR_CLR_MRDY_IE | CHCR_CLR_DRDY_IE | @@ -286,7 +286,7 @@ void mite_dma_arm(struct mite_channel *mite_chan) writel(chor, mite->mite_io_addr + MITE_CHOR(mite_chan->channel)); mmiowb(); spin_unlock_irqrestore(&mite->lock, flags); -/* mite_dma_tcr(mite, channel); */ + /* mite_dma_tcr(mite, channel); */ } EXPORT_SYMBOL_GPL(mite_dma_arm); @@ -529,8 +529,10 @@ int mite_sync_input_dma(struct mite_channel *mite_chan, } count = nbytes - async->buf_write_count; - /* it's possible count will be negative due to - * conservative value returned by mite_bytes_written_to_memory_lb */ + /* + * it's possible count will be negative due to conservative value + * returned by mite_bytes_written_to_memory_lb + */ if (count <= 0) return 0; @@ -551,7 +553,7 @@ int mite_sync_output_dma(struct mite_channel *mite_chan, u32 nbytes_ub, nbytes_lb; int count; - /* read alloc as much as we can */ + /* read alloc as much as we can */ comedi_buf_read_alloc(s, async->prealloc_bufsz); nbytes_lb = mite_bytes_read_from_memory_lb(mite_chan); if (cmd->stop_src == TRIG_COUNT && (int)(nbytes_lb - stop_count) > 0) @@ -622,5 +624,5 @@ module_init(mite_module_init); module_exit(mite_module_exit); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi helper for NI Mite PCI interface chip"); MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/staging/comedi/drivers/mite.h b/kernel/drivers/staging/comedi/drivers/mite.h index b3ca7fc3a..c32d4e4dd 100644 --- a/kernel/drivers/staging/comedi/drivers/mite.h +++ b/kernel/drivers/staging/comedi/drivers/mite.h @@ -1,32 +1,35 @@ /* - module/mite.h - Hardware driver for NI Mite PCI interface chip - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1999 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * module/mite.h + * Hardware driver for NI Mite PCI interface chip + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1999 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #ifndef _MITE_H_ #define _MITE_H_ +#include <linux/io.h> #include <linux/log2.h> -#include <linux/slab.h> -#include "../comedi_pci.h" - -#define PCIMIO_COMPAT +#include <linux/spinlock.h> #define MAX_MITE_DMA_CHANNELS 8 +struct comedi_device; +struct comedi_subdevice; +struct device; +struct pci_dev; + struct mite_dma_descriptor { __le32 count; __le32 addr; @@ -74,16 +77,13 @@ static inline int mite_setup(struct comedi_device *dev, void mite_detach(struct mite_struct *mite); struct mite_dma_descriptor_ring *mite_alloc_ring(struct mite_struct *mite); void mite_free_ring(struct mite_dma_descriptor_ring *ring); -struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite, - struct - mite_dma_descriptor_ring - *ring, unsigned min_channel, - unsigned max_channel); -static inline struct mite_channel *mite_request_channel(struct mite_struct - *mite, - struct - mite_dma_descriptor_ring - *ring) +struct mite_channel * +mite_request_channel_in_range(struct mite_struct *mite, + struct mite_dma_descriptor_ring *ring, + unsigned min_channel, unsigned max_channel); +static inline struct mite_channel * +mite_request_channel(struct mite_struct *mite, + struct mite_dma_descriptor_ring *ring) { return mite_request_channel_in_range(mite, ring, 0, mite->num_channels - 1); @@ -112,12 +112,14 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring, struct comedi_subdevice *s); enum mite_registers { - /* The bits 0x90180700 in MITE_UNKNOWN_DMA_BURST_REG can be - written and read back. The bits 0x1f always read as 1. - The rest always read as zero. */ + /* + * The bits 0x90180700 in MITE_UNKNOWN_DMA_BURST_REG can be + * written and read back. The bits 0x1f always read as 1. + * The rest always read as zero. + */ MITE_UNKNOWN_DMA_BURST_REG = 0x28, MITE_IODWBSR = 0xc0, /* IO Device Window Base Size Register */ - MITE_IODWBSR_1 = 0xc4, /* IO Device Window Base Size Register 1 */ + MITE_IODWBSR_1 = 0xc4, /* IO Device Window Base Size Register 1 */ MITE_IODWCR_1 = 0xf4, MITE_PCI_CONFIG_OFFSET = 0x300, MITE_CSIGR = 0x460 /* chip signature */ @@ -143,7 +145,7 @@ enum mite_registers { #define MITE_FCR(x) (0x40 + MITE_CHAN(x)) /* fifo count */ enum MITE_IODWBSR_bits { - WENAB = 0x80, /* window enable */ + WENAB = 0x80, /* window enable */ }; static inline unsigned MITE_IODWBSR_1_WSIZE_bits(unsigned size) @@ -166,27 +168,27 @@ static inline int mite_csigr_version(u32 csigr_bits) }; static inline int mite_csigr_type(u32 csigr_bits) -{ /* original mite = 0, minimite = 1 */ +{ /* original mite = 0, minimite = 1 */ return (csigr_bits >> 4) & 0xf; }; static inline int mite_csigr_mmode(u32 csigr_bits) -{ /* mite mode, minimite = 1 */ +{ /* mite mode, minimite = 1 */ return (csigr_bits >> 8) & 0x3; }; static inline int mite_csigr_imode(u32 csigr_bits) -{ /* cpu port interface mode, pci = 0x3 */ +{ /* cpu port interface mode, pci = 0x3 */ return (csigr_bits >> 12) & 0x3; }; static inline int mite_csigr_dmac(u32 csigr_bits) -{ /* number of dma channels */ +{ /* number of dma channels */ return (csigr_bits >> 16) & 0xf; }; static inline int mite_csigr_wpdep(u32 csigr_bits) -{ /* write post fifo depth */ +{ /* write post fifo depth */ unsigned int wpdep_bits = (csigr_bits >> 20) & 0x7; return (wpdep_bits) ? (1 << (wpdep_bits - 1)) : 0; @@ -198,7 +200,7 @@ static inline int mite_csigr_wins(u32 csigr_bits) }; static inline int mite_csigr_iowins(u32 csigr_bits) -{ /* number of io windows */ +{ /* number of io windows */ return (csigr_bits >> 29) & 0x7; }; @@ -280,6 +282,7 @@ enum ConfigRegister_bits { CR_PORTMXI = (3 << 6), CR_AMDEVICE = (1 << 0), }; + static inline int CR_REQS(int source) { return (source & 0x7) << 16; @@ -287,8 +290,7 @@ static inline int CR_REQS(int source) static inline int CR_REQSDRQ(unsigned drq_line) { - /* This also works on m-series when - using channels (drq_line) 4 or 5. */ + /* This also works on m-series when using channels (drq_line) 4 or 5. */ return CR_REQS((drq_line & 0x3) | 0x4); } diff --git a/kernel/drivers/staging/comedi/drivers/mpc624.c b/kernel/drivers/staging/comedi/drivers/mpc624.c index 0207b8edf..826e4399c 100644 --- a/kernel/drivers/staging/comedi/drivers/mpc624.c +++ b/kernel/drivers/staging/comedi/drivers/mpc624.c @@ -1,55 +1,56 @@ /* - comedi/drivers/mpc624.c - Hardware driver for a Micro/sys inc. MPC-624 PC/104 board - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * mpc624.c + * Hardware driver for a Micro/sys inc. MPC-624 PC/104 board + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + /* -Driver: mpc624 -Description: Micro/sys MPC-624 PC/104 board -Devices: [Micro/sys] MPC-624 (mpc624) -Author: Stanislaw Raczynski <sraczynski@op.pl> -Updated: Thu, 15 Sep 2005 12:01:18 +0200 -Status: working - - The Micro/sys MPC-624 board is based on the LTC2440 24-bit sigma-delta - ADC chip. - - Subdevices supported by the driver: - - Analog In: supported - - Digital I/O: not supported - - LEDs: not supported - - EEPROM: not supported - -Configuration Options: - [0] - I/O base address - [1] - conversion rate - Conversion rate RMS noise Effective Number Of Bits - 0 3.52kHz 23uV 17 - 1 1.76kHz 3.5uV 20 - 2 880Hz 2uV 21.3 - 3 440Hz 1.4uV 21.8 - 4 220Hz 1uV 22.4 - 5 110Hz 750uV 22.9 - 6 55Hz 510nV 23.4 - 7 27.5Hz 375nV 24 - 8 13.75Hz 250nV 24.4 - 9 6.875Hz 200nV 24.6 - [2] - voltage range - 0 -1.01V .. +1.01V - 1 -10.1V .. +10.1V -*/ + * Driver: mpc624 + * Description: Micro/sys MPC-624 PC/104 board + * Devices: [Micro/sys] MPC-624 (mpc624) + * Author: Stanislaw Raczynski <sraczynski@op.pl> + * Updated: Thu, 15 Sep 2005 12:01:18 +0200 + * Status: working + * + * The Micro/sys MPC-624 board is based on the LTC2440 24-bit sigma-delta + * ADC chip. + * + * Subdevices supported by the driver: + * - Analog In: supported + * - Digital I/O: not supported + * - LEDs: not supported + * - EEPROM: not supported + * + * Configuration Options: + * [0] - I/O base address + * [1] - conversion rate + * Conversion rate RMS noise Effective Number Of Bits + * 0 3.52kHz 23uV 17 + * 1 1.76kHz 3.5uV 20 + * 2 880Hz 2uV 21.3 + * 3 440Hz 1.4uV 21.8 + * 4 220Hz 1uV 22.4 + * 5 110Hz 750uV 22.9 + * 6 55Hz 510nV 23.4 + * 7 27.5Hz 375nV 24 + * 8 13.75Hz 250nV 24.4 + * 9 6.875Hz 200nV 24.6 + * [2] - voltage range + * 0 -1.01V .. +1.01V + * 1 -10.1V .. +10.1V + */ #include <linux/module.h> #include "../comedidev.h" @@ -58,65 +59,41 @@ Configuration Options: /* Offsets of different ports */ #define MPC624_MASTER_CONTROL 0 /* not used */ -#define MPC624_GNMUXCH 1 /* Gain, Mux, Channel of ADC */ -#define MPC624_ADC 2 /* read/write to/from ADC */ -#define MPC624_EE 3 /* read/write to/from serial EEPROM via I2C */ -#define MPC624_LEDS 4 /* write to LEDs */ -#define MPC624_DIO 5 /* read/write to/from digital I/O ports */ -#define MPC624_IRQ_MASK 6 /* IRQ masking enable/disable */ +#define MPC624_GNMUXCH 1 /* Gain, Mux, Channel of ADC */ +#define MPC624_ADC 2 /* read/write to/from ADC */ +#define MPC624_EE 3 /* read/write to/from serial EEPROM via I2C */ +#define MPC624_LEDS 4 /* write to LEDs */ +#define MPC624_DIO 5 /* read/write to/from digital I/O ports */ +#define MPC624_IRQ_MASK 6 /* IRQ masking enable/disable */ /* Register bits' names */ -#define MPC624_ADBUSY (1<<5) -#define MPC624_ADSDO (1<<4) -#define MPC624_ADFO (1<<3) -#define MPC624_ADCS (1<<2) -#define MPC624_ADSCK (1<<1) -#define MPC624_ADSDI (1<<0) - -/* SDI Speed/Resolution Programming bits */ -#define MPC624_OSR4 (1<<31) -#define MPC624_OSR3 (1<<30) -#define MPC624_OSR2 (1<<29) -#define MPC624_OSR1 (1<<28) -#define MPC624_OSR0 (1<<27) +#define MPC624_ADBUSY BIT(5) +#define MPC624_ADSDO BIT(4) +#define MPC624_ADFO BIT(3) +#define MPC624_ADCS BIT(2) +#define MPC624_ADSCK BIT(1) +#define MPC624_ADSDI BIT(0) /* 32-bit output value bits' names */ -#define MPC624_EOC_BIT (1<<31) -#define MPC624_DMY_BIT (1<<30) -#define MPC624_SGN_BIT (1<<29) - -/* Conversion speeds */ -/* OSR4 OSR3 OSR2 OSR1 OSR0 Conversion rate RMS noise ENOB^ - * X 0 0 0 1 3.52kHz 23uV 17 - * X 0 0 1 0 1.76kHz 3.5uV 20 - * X 0 0 1 1 880Hz 2uV 21.3 - * X 0 1 0 0 440Hz 1.4uV 21.8 - * X 0 1 0 1 220Hz 1uV 22.4 - * X 0 1 1 0 110Hz 750uV 22.9 - * X 0 1 1 1 55Hz 510nV 23.4 - * X 1 0 0 0 27.5Hz 375nV 24 - * X 1 0 0 1 13.75Hz 250nV 24.4 - * X 1 1 1 1 6.875Hz 200nV 24.6 - * - * ^ - Effective Number Of Bits - */ +#define MPC624_EOC_BIT BIT(31) +#define MPC624_DMY_BIT BIT(30) +#define MPC624_SGN_BIT BIT(29) + +/* SDI Speed/Resolution Programming bits */ +#define MPC624_OSR(x) (((x) & 0x1f) << 27) +#define MPC624_SPEED_3_52_KHZ MPC624_OSR(0x11) +#define MPC624_SPEED_1_76_KHZ MPC624_OSR(0x12) +#define MPC624_SPEED_880_HZ MPC624_OSR(0x13) +#define MPC624_SPEED_440_HZ MPC624_OSR(0x14) +#define MPC624_SPEED_220_HZ MPC624_OSR(0x15) +#define MPC624_SPEED_110_HZ MPC624_OSR(0x16) +#define MPC624_SPEED_55_HZ MPC624_OSR(0x17) +#define MPC624_SPEED_27_5_HZ MPC624_OSR(0x18) +#define MPC624_SPEED_13_75_HZ MPC624_OSR(0x19) +#define MPC624_SPEED_6_875_HZ MPC624_OSR(0x1f) -#define MPC624_SPEED_3_52_kHz (MPC624_OSR4 | MPC624_OSR0) -#define MPC624_SPEED_1_76_kHz (MPC624_OSR4 | MPC624_OSR1) -#define MPC624_SPEED_880_Hz (MPC624_OSR4 | MPC624_OSR1 | MPC624_OSR0) -#define MPC624_SPEED_440_Hz (MPC624_OSR4 | MPC624_OSR2) -#define MPC624_SPEED_220_Hz (MPC624_OSR4 | MPC624_OSR2 | MPC624_OSR0) -#define MPC624_SPEED_110_Hz (MPC624_OSR4 | MPC624_OSR2 | MPC624_OSR1) -#define MPC624_SPEED_55_Hz \ - (MPC624_OSR4 | MPC624_OSR2 | MPC624_OSR1 | MPC624_OSR0) -#define MPC624_SPEED_27_5_Hz (MPC624_OSR4 | MPC624_OSR3) -#define MPC624_SPEED_13_75_Hz (MPC624_OSR4 | MPC624_OSR3 | MPC624_OSR0) -#define MPC624_SPEED_6_875_Hz \ - (MPC624_OSR4 | MPC624_OSR3 | MPC624_OSR2 | MPC624_OSR1 | MPC624_OSR0) -/* -------------------------------------------------------------------------- */ struct mpc624_private { - /* set by mpc624_attach() from driver's parameters */ - unsigned long int ulConvertionRate; + unsigned int ai_speed; }; /* -------------------------------------------------------------------------- */ @@ -138,6 +115,85 @@ static const struct comedi_lrange range_mpc624_bipolar10 = { } }; +static unsigned int mpc624_ai_get_sample(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct mpc624_private *devpriv = dev->private; + unsigned int data_out = devpriv->ai_speed; + unsigned int data_in = 0; + unsigned int bit; + int i; + + /* Start reading data */ + udelay(1); + for (i = 0; i < 32; i++) { + /* Set the clock low */ + outb(0, dev->iobase + MPC624_ADC); + udelay(1); + + /* Set the ADSDI line for the next bit (send to MPC624) */ + bit = (data_out & BIT(31)) ? MPC624_ADSDI : 0; + outb(bit, dev->iobase + MPC624_ADC); + udelay(1); + + /* Set the clock high */ + outb(MPC624_ADSCK | bit, dev->iobase + MPC624_ADC); + udelay(1); + + /* Read ADSDO on high clock (receive from MPC624) */ + data_in <<= 1; + data_in |= (inb(dev->iobase + MPC624_ADC) & MPC624_ADSDO) >> 4; + udelay(1); + + data_out <<= 1; + } + + /* + * Received 32-bit long value consist of: + * 31: EOC - (End Of Transmission) bit - should be 0 + * 30: DMY - (Dummy) bit - should be 0 + * 29: SIG - (Sign) bit - 1 if positive, 0 if negative + * 28: MSB - (Most Significant Bit) - the first bit of the + * conversion result + * .... + * 05: LSB - (Least Significant Bit)- the last bit of the + * conversion result + * 04-00: sub-LSB - sub-LSBs are basically noise, but when + * averaged properly, they can increase + * conversion precision up to 29 bits; + * they can be discarded without loss of + * resolution. + */ + if (data_in & MPC624_EOC_BIT) + dev_dbg(dev->class_dev, "EOC bit is set!"); + if (data_in & MPC624_DMY_BIT) + dev_dbg(dev->class_dev, "DMY bit is set!"); + + if (data_in & MPC624_SGN_BIT) { + /* + * Voltage is positive + * + * comedi operates on unsigned numbers, so mask off EOC + * and DMY and don't clear the SGN bit + */ + data_in &= 0x3fffffff; + } else { + /* + * The voltage is negative + * + * data_in contains a number in 30-bit two's complement + * code and we must deal with it + */ + data_in |= MPC624_SGN_BIT; + data_in = ~data_in; + data_in += 1; + /* clear EOC and DMY bits */ + data_in &= ~(MPC624_EOC_BIT | MPC624_DMY_BIT); + data_in = 0x20000000 - data_in; + } + return data_in; +} + static int mpc624_ai_eoc(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -151,14 +207,13 @@ static int mpc624_ai_eoc(struct comedi_device *dev, return -EBUSY; } -static int mpc624_ai_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data) +static int mpc624_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - struct mpc624_private *devpriv = dev->private; - int n, i; - unsigned long int data_in, data_out; int ret; + int i; /* * WARNING: @@ -166,7 +221,7 @@ static int mpc624_ai_rinsn(struct comedi_device *dev, */ outb(insn->chanspec, dev->iobase + MPC624_GNMUXCH); - for (n = 0; n < insn->n; n++) { + for (i = 0; i < insn->n; i++) { /* Trigger the conversion */ outb(MPC624_ADSCK, dev->iobase + MPC624_ADC); udelay(1); @@ -180,93 +235,10 @@ static int mpc624_ai_rinsn(struct comedi_device *dev, if (ret) return ret; - /* Start reading data */ - data_in = 0; - data_out = devpriv->ulConvertionRate; - udelay(1); - for (i = 0; i < 32; i++) { - /* Set the clock low */ - outb(0, dev->iobase + MPC624_ADC); - udelay(1); - - if (data_out & (1 << 31)) { /* the next bit is a 1 */ - /* Set the ADSDI line (send to MPC624) */ - outb(MPC624_ADSDI, dev->iobase + MPC624_ADC); - udelay(1); - /* Set the clock high */ - outb(MPC624_ADSCK | MPC624_ADSDI, - dev->iobase + MPC624_ADC); - } else { /* the next bit is a 0 */ - - /* Set the ADSDI line (send to MPC624) */ - outb(0, dev->iobase + MPC624_ADC); - udelay(1); - /* Set the clock high */ - outb(MPC624_ADSCK, dev->iobase + MPC624_ADC); - } - /* Read ADSDO on high clock (receive from MPC624) */ - udelay(1); - data_in <<= 1; - data_in |= - (inb(dev->iobase + MPC624_ADC) & MPC624_ADSDO) >> 4; - udelay(1); - - data_out <<= 1; - } - - /* - * Received 32-bit long value consist of: - * 31: EOC - - * (End Of Transmission) bit - should be 0 - * 30: DMY - * (Dummy) bit - should be 0 - * 29: SIG - * (Sign) bit- 1 if the voltage is positive, - * 0 if negative - * 28: MSB - * (Most Significant Bit) - the first bit of - * the conversion result - * .... - * 05: LSB - * (Least Significant Bit)- the last bit of the - * conversion result - * 04-00: sub-LSB - * - sub-LSBs are basically noise, but when - * averaged properly, they can increase conversion - * precision up to 29 bits; they can be discarded - * without loss of resolution. - */ - - if (data_in & MPC624_EOC_BIT) - dev_dbg(dev->class_dev, - "EOC bit is set (data_in=%lu)!", data_in); - if (data_in & MPC624_DMY_BIT) - dev_dbg(dev->class_dev, - "DMY bit is set (data_in=%lu)!", data_in); - if (data_in & MPC624_SGN_BIT) { /* Volatge is positive */ - /* - * comedi operates on unsigned numbers, so mask off EOC - * and DMY and don't clear the SGN bit - */ - data_in &= 0x3FFFFFFF; - data[n] = data_in; - } else { /* The voltage is negative */ - /* - * data_in contains a number in 30-bit two's complement - * code and we must deal with it - */ - data_in |= MPC624_SGN_BIT; - data_in = ~data_in; - data_in += 1; - data_in &= ~(MPC624_EOC_BIT | MPC624_DMY_BIT); - /* clear EOC and DMY bits */ - data_in = 0x20000000 - data_in; - data[n] = data_in; - } + data[i] = mpc624_ai_get_sample(dev, s); } - /* Return the number of samples read/written */ - return n; + return insn->n; } static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it) @@ -285,61 +257,52 @@ static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it) switch (it->options[1]) { case 0: - devpriv->ulConvertionRate = MPC624_SPEED_3_52_kHz; + devpriv->ai_speed = MPC624_SPEED_3_52_KHZ; break; case 1: - devpriv->ulConvertionRate = MPC624_SPEED_1_76_kHz; + devpriv->ai_speed = MPC624_SPEED_1_76_KHZ; break; case 2: - devpriv->ulConvertionRate = MPC624_SPEED_880_Hz; + devpriv->ai_speed = MPC624_SPEED_880_HZ; break; case 3: - devpriv->ulConvertionRate = MPC624_SPEED_440_Hz; + devpriv->ai_speed = MPC624_SPEED_440_HZ; break; case 4: - devpriv->ulConvertionRate = MPC624_SPEED_220_Hz; + devpriv->ai_speed = MPC624_SPEED_220_HZ; break; case 5: - devpriv->ulConvertionRate = MPC624_SPEED_110_Hz; + devpriv->ai_speed = MPC624_SPEED_110_HZ; break; case 6: - devpriv->ulConvertionRate = MPC624_SPEED_55_Hz; + devpriv->ai_speed = MPC624_SPEED_55_HZ; break; case 7: - devpriv->ulConvertionRate = MPC624_SPEED_27_5_Hz; + devpriv->ai_speed = MPC624_SPEED_27_5_HZ; break; case 8: - devpriv->ulConvertionRate = MPC624_SPEED_13_75_Hz; + devpriv->ai_speed = MPC624_SPEED_13_75_HZ; break; case 9: - devpriv->ulConvertionRate = MPC624_SPEED_6_875_Hz; + devpriv->ai_speed = MPC624_SPEED_6_875_HZ; break; default: - devpriv->ulConvertionRate = MPC624_SPEED_3_52_kHz; + devpriv->ai_speed = MPC624_SPEED_3_52_KHZ; } ret = comedi_alloc_subdevices(dev, 1); if (ret) return ret; + /* Analog Input subdevice */ s = &dev->subdevices[0]; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_DIFF; - s->n_chan = 8; - switch (it->options[1]) { - default: - s->maxdata = 0x3FFFFFFF; - } - - switch (it->options[1]) { - case 0: - s->range_table = &range_mpc624_bipolar1; - break; - default: - s->range_table = &range_mpc624_bipolar10; - } - s->len_chanlist = 1; - s->insn_read = mpc624_ai_rinsn; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_DIFF; + s->n_chan = 4; + s->maxdata = 0x3fffffff; + s->range_table = (it->options[1] == 0) ? &range_mpc624_bipolar1 + : &range_mpc624_bipolar10; + s->insn_read = mpc624_ai_insn_read; return 0; } @@ -353,5 +316,5 @@ static struct comedi_driver mpc624_driver = { module_comedi_driver(mpc624_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for Micro/sys MPC-624 PC/104 board"); MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/staging/comedi/drivers/multiq3.c b/kernel/drivers/staging/comedi/drivers/multiq3.c index 847121921..b5a26f7b4 100644 --- a/kernel/drivers/staging/comedi/drivers/multiq3.c +++ b/kernel/drivers/staging/comedi/drivers/multiq3.c @@ -1,79 +1,91 @@ /* - comedi/drivers/multiq3.c - Hardware driver for Quanser Consulting MultiQ-3 board - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + * multiq3.c + * Hardware driver for Quanser Consulting MultiQ-3 board + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. */ -/* -Driver: multiq3 -Description: Quanser Consulting MultiQ-3 -Author: Anders Blomdell <anders.blomdell@control.lth.se> -Status: works -Devices: [Quanser Consulting] MultiQ-3 (multiq3) - -*/ - -#include <linux/module.h> -#include <linux/interrupt.h> -#include "../comedidev.h" /* - * MULTIQ-3 port offsets + * Driver: multiq3 + * Description: Quanser Consulting MultiQ-3 + * Devices: [Quanser Consulting] MultiQ-3 (multiq3) + * Author: Anders Blomdell <anders.blomdell@control.lth.se> + * Status: works + * + * Configuration Options: + * [0] - I/O port base address + * [1] - IRQ (not used) + * [2] - Number of optional encoder chips installed on board + * 0 = none + * 1 = 2 inputs (Model -2E) + * 2 = 4 inputs (Model -4E) + * 3 = 6 inputs (Model -6E) + * 4 = 8 inputs (Model -8E) */ -#define MULTIQ3_DIGIN_PORT 0 -#define MULTIQ3_DIGOUT_PORT 0 -#define MULTIQ3_DAC_DATA 2 -#define MULTIQ3_AD_DATA 4 -#define MULTIQ3_AD_CS 4 -#define MULTIQ3_STATUS 6 -#define MULTIQ3_CONTROL 6 -#define MULTIQ3_CLK_DATA 8 -#define MULTIQ3_ENC_DATA 12 -#define MULTIQ3_ENC_CONTROL 14 -/* - * flags for CONTROL register - */ -#define MULTIQ3_AD_MUX_EN 0x0040 -#define MULTIQ3_AD_AUTOZ 0x0080 -#define MULTIQ3_AD_AUTOCAL 0x0100 -#define MULTIQ3_AD_SH 0x0200 -#define MULTIQ3_AD_CLOCK_4M 0x0400 -#define MULTIQ3_DA_LOAD 0x1800 +#include <linux/module.h> -#define MULTIQ3_CONTROL_MUST 0x0600 +#include "../comedidev.h" /* - * flags for STATUS register + * Register map */ -#define MULTIQ3_STATUS_EOC 0x008 -#define MULTIQ3_STATUS_EOC_I 0x010 +#define MULTIQ3_DI_REG 0x00 +#define MULTIQ3_DO_REG 0x00 +#define MULTIQ3_AO_REG 0x02 +#define MULTIQ3_AI_REG 0x04 +#define MULTIQ3_AI_CONV_REG 0x04 +#define MULTIQ3_STATUS_REG 0x06 +#define MULTIQ3_STATUS_EOC BIT(3) +#define MULTIQ3_STATUS_EOC_I BIT(4) +#define MULTIQ3_CTRL_REG 0x06 +#define MULTIQ3_CTRL_AO_CHAN(x) (((x) & 0x7) << 0) +#define MULTIQ3_CTRL_RC(x) (((x) & 0x3) << 0) +#define MULTIQ3_CTRL_AI_CHAN(x) (((x) & 0x7) << 3) +#define MULTIQ3_CTRL_E_CHAN(x) (((x) & 0x7) << 3) +#define MULTIQ3_CTRL_EN BIT(6) +#define MULTIQ3_CTRL_AZ BIT(7) +#define MULTIQ3_CTRL_CAL BIT(8) +#define MULTIQ3_CTRL_SH BIT(9) +#define MULTIQ3_CTRL_CLK BIT(10) +#define MULTIQ3_CTRL_LD (3 << 11) +#define MULTIQ3_CLK_REG 0x08 +#define MULTIQ3_ENC_DATA_REG 0x0c +#define MULTIQ3_ENC_CTRL_REG 0x0e /* - * flags for encoder control + * Encoder chip commands (from the programming manual) */ -#define MULTIQ3_CLOCK_DATA 0x00 -#define MULTIQ3_CLOCK_SETUP 0x18 -#define MULTIQ3_INPUT_SETUP 0x41 -#define MULTIQ3_QUAD_X4 0x38 -#define MULTIQ3_BP_RESET 0x01 -#define MULTIQ3_CNTR_RESET 0x02 -#define MULTIQ3_TRSFRPR_CTR 0x08 -#define MULTIQ3_TRSFRCNTR_OL 0x10 -#define MULTIQ3_EFLAG_RESET 0x06 - -#define MULTIQ3_TIMEOUT 30 +#define MULTIQ3_CLOCK_DATA 0x00 /* FCK frequency divider */ +#define MULTIQ3_CLOCK_SETUP 0x18 /* xfer PR0 to PSC */ +#define MULTIQ3_INPUT_SETUP 0x41 /* enable inputs A and B */ +#define MULTIQ3_QUAD_X4 0x38 /* quadrature */ +#define MULTIQ3_BP_RESET 0x01 /* reset byte pointer */ +#define MULTIQ3_CNTR_RESET 0x02 /* reset counter */ +#define MULTIQ3_TRSFRPR_CTR 0x08 /* xfre preset reg to counter */ +#define MULTIQ3_TRSFRCNTR_OL 0x10 /* xfer CNTR to OL (x and y) */ +#define MULTIQ3_EFLAG_RESET 0x06 /* reset E bit of flag reg */ + +static void multiq3_set_ctrl(struct comedi_device *dev, unsigned int bits) +{ + /* + * According to the programming manual, the SH and CLK bits should + * be kept high at all times. + */ + outw(MULTIQ3_CTRL_SH | MULTIQ3_CTRL_CLK | bits, + dev->iobase + MULTIQ3_CTRL_REG); +} static int multiq3_ai_status(struct comedi_device *dev, struct comedi_subdevice *s, @@ -82,7 +94,7 @@ static int multiq3_ai_status(struct comedi_device *dev, { unsigned int status; - status = inw(dev->iobase + MULTIQ3_STATUS); + status = inw(dev->iobase + MULTIQ3_STATUS_REG); if (status & context) return 0; return -EBUSY; @@ -90,36 +102,39 @@ static int multiq3_ai_status(struct comedi_device *dev, static int multiq3_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - int n; - int chan; - unsigned int hi, lo; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int val; int ret; + int i; - chan = CR_CHAN(insn->chanspec); - outw(MULTIQ3_CONTROL_MUST | MULTIQ3_AD_MUX_EN | (chan << 3), - dev->iobase + MULTIQ3_CONTROL); + multiq3_set_ctrl(dev, MULTIQ3_CTRL_EN | MULTIQ3_CTRL_AI_CHAN(chan)); ret = comedi_timeout(dev, s, insn, multiq3_ai_status, MULTIQ3_STATUS_EOC); if (ret) return ret; - for (n = 0; n < insn->n; n++) { - outw(0, dev->iobase + MULTIQ3_AD_CS); + for (i = 0; i < insn->n; i++) { + outw(0, dev->iobase + MULTIQ3_AI_CONV_REG); ret = comedi_timeout(dev, s, insn, multiq3_ai_status, MULTIQ3_STATUS_EOC_I); if (ret) return ret; - hi = inb(dev->iobase + MULTIQ3_AD_CS); - lo = inb(dev->iobase + MULTIQ3_AD_CS); - data[n] = (((hi << 8) | lo) + 0x1000) & 0x1fff; + /* get a 16-bit sample; mask it to the subdevice resolution */ + val = inb(dev->iobase + MULTIQ3_AI_REG) << 8; + val |= inb(dev->iobase + MULTIQ3_AI_REG); + val &= s->maxdata; + + /* munge the 2's complement value to offset binary */ + data[i] = comedi_offset_munge(s, val); } - return n; + return insn->n; } static int multiq3_ao_insn_write(struct comedi_device *dev, @@ -133,10 +148,10 @@ static int multiq3_ao_insn_write(struct comedi_device *dev, for (i = 0; i < insn->n; i++) { val = data[i]; - outw(MULTIQ3_CONTROL_MUST | MULTIQ3_DA_LOAD | chan, - dev->iobase + MULTIQ3_CONTROL); - outw(val, dev->iobase + MULTIQ3_DAC_DATA); - outw(MULTIQ3_CONTROL_MUST, dev->iobase + MULTIQ3_CONTROL); + multiq3_set_ctrl(dev, MULTIQ3_CTRL_LD | + MULTIQ3_CTRL_AO_CHAN(chan)); + outw(val, dev->iobase + MULTIQ3_AO_REG); + multiq3_set_ctrl(dev, 0); } s->readback[chan] = val; @@ -147,7 +162,7 @@ static int multiq3_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - data[1] = inw(dev->iobase + MULTIQ3_DIGIN_PORT); + data[1] = inw(dev->iobase + MULTIQ3_DI_REG); return insn->n; } @@ -158,7 +173,7 @@ static int multiq3_do_insn_bits(struct comedi_device *dev, unsigned int *data) { if (comedi_dio_update_state(s, data)) - outw(s->state, dev->iobase + MULTIQ3_DIGOUT_PORT); + outw(s->state, dev->iobase + MULTIQ3_DO_REG); data[1] = s->state; @@ -170,41 +185,76 @@ static int multiq3_encoder_insn_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - int chan = CR_CHAN(insn->chanspec); - int control = MULTIQ3_CONTROL_MUST | MULTIQ3_AD_MUX_EN | (chan << 3); - int value; - int n; - - for (n = 0; n < insn->n; n++) { - outw(control, dev->iobase + MULTIQ3_CONTROL); - outb(MULTIQ3_BP_RESET, dev->iobase + MULTIQ3_ENC_CONTROL); - outb(MULTIQ3_TRSFRCNTR_OL, dev->iobase + MULTIQ3_ENC_CONTROL); - value = inb(dev->iobase + MULTIQ3_ENC_DATA); - value |= (inb(dev->iobase + MULTIQ3_ENC_DATA) << 8); - value |= (inb(dev->iobase + MULTIQ3_ENC_DATA) << 16); - data[n] = (value + 0x800000) & 0xffffff; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int val; + int i; + + for (i = 0; i < insn->n; i++) { + /* select encoder channel */ + multiq3_set_ctrl(dev, MULTIQ3_CTRL_EN | + MULTIQ3_CTRL_E_CHAN(chan)); + + /* reset the byte pointer */ + outb(MULTIQ3_BP_RESET, dev->iobase + MULTIQ3_ENC_CTRL_REG); + + /* latch the data */ + outb(MULTIQ3_TRSFRCNTR_OL, dev->iobase + MULTIQ3_ENC_CTRL_REG); + + /* read the 24-bit encoder data (lsb/mid/msb) */ + val = inb(dev->iobase + MULTIQ3_ENC_DATA_REG); + val |= (inb(dev->iobase + MULTIQ3_ENC_DATA_REG) << 8); + val |= (inb(dev->iobase + MULTIQ3_ENC_DATA_REG) << 16); + + /* + * Munge the data so that the reset value is in the middle + * of the maxdata range, i.e.: + * + * real value comedi value + * 0xffffff 0x7fffff 1 negative count + * 0x000000 0x800000 reset value + * 0x000001 0x800001 1 positive count + * + * It's possible for the 24-bit counter to overflow but it + * would normally take _quite_ a few turns. A 2000 line + * encoder in quadrature results in 8000 counts/rev. So about + * 1048 turns in either direction can be measured without + * an overflow. + */ + data[i] = (val + ((s->maxdata + 1) >> 1)) & s->maxdata; } - return n; + return insn->n; } -static void encoder_reset(struct comedi_device *dev) +static void multiq3_encoder_reset(struct comedi_device *dev, + unsigned int chan) { - struct comedi_subdevice *s = &dev->subdevices[4]; - int chan; - - for (chan = 0; chan < s->n_chan; chan++) { - int control = - MULTIQ3_CONTROL_MUST | MULTIQ3_AD_MUX_EN | (chan << 3); - outw(control, dev->iobase + MULTIQ3_CONTROL); - outb(MULTIQ3_EFLAG_RESET, dev->iobase + MULTIQ3_ENC_CONTROL); - outb(MULTIQ3_BP_RESET, dev->iobase + MULTIQ3_ENC_CONTROL); - outb(MULTIQ3_CLOCK_DATA, dev->iobase + MULTIQ3_ENC_DATA); - outb(MULTIQ3_CLOCK_SETUP, dev->iobase + MULTIQ3_ENC_CONTROL); - outb(MULTIQ3_INPUT_SETUP, dev->iobase + MULTIQ3_ENC_CONTROL); - outb(MULTIQ3_QUAD_X4, dev->iobase + MULTIQ3_ENC_CONTROL); - outb(MULTIQ3_CNTR_RESET, dev->iobase + MULTIQ3_ENC_CONTROL); + multiq3_set_ctrl(dev, MULTIQ3_CTRL_EN | MULTIQ3_CTRL_E_CHAN(chan)); + outb(MULTIQ3_EFLAG_RESET, dev->iobase + MULTIQ3_ENC_CTRL_REG); + outb(MULTIQ3_BP_RESET, dev->iobase + MULTIQ3_ENC_CTRL_REG); + outb(MULTIQ3_CLOCK_DATA, dev->iobase + MULTIQ3_ENC_DATA_REG); + outb(MULTIQ3_CLOCK_SETUP, dev->iobase + MULTIQ3_ENC_CTRL_REG); + outb(MULTIQ3_INPUT_SETUP, dev->iobase + MULTIQ3_ENC_CTRL_REG); + outb(MULTIQ3_QUAD_X4, dev->iobase + MULTIQ3_ENC_CTRL_REG); + outb(MULTIQ3_CNTR_RESET, dev->iobase + MULTIQ3_ENC_CTRL_REG); +} + +static int multiq3_encoder_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned int chan = CR_CHAN(insn->chanspec); + + switch (data[0]) { + case INSN_CONFIG_RESET: + multiq3_encoder_reset(dev, chan); + break; + default: + return -EINVAL; } + + return insn->n; } static int multiq3_attach(struct comedi_device *dev, @@ -212,6 +262,7 @@ static int multiq3_attach(struct comedi_device *dev, { struct comedi_subdevice *s; int ret; + int i; ret = comedi_request_region(dev, it->options[0], 0x10); if (ret) @@ -221,57 +272,58 @@ static int multiq3_attach(struct comedi_device *dev, if (ret) return ret; + /* Analog Input subdevice */ s = &dev->subdevices[0]; - /* ai subdevice */ - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND; - s->n_chan = 8; - s->insn_read = multiq3_ai_insn_read; - s->maxdata = 0x1fff; - s->range_table = &range_bipolar5; - + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND; + s->n_chan = 8; + s->maxdata = 0x1fff; + s->range_table = &range_bipolar5; + s->insn_read = multiq3_ai_insn_read; + + /* Analog Output subdevice */ s = &dev->subdevices[1]; - /* ao subdevice */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 8; - s->maxdata = 0xfff; - s->range_table = &range_bipolar5; - s->insn_write = multiq3_ao_insn_write; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 0x0fff; + s->range_table = &range_bipolar5; + s->insn_write = multiq3_ao_insn_write; ret = comedi_alloc_subdev_readback(s); if (ret) return ret; + /* Digital Input subdevice */ s = &dev->subdevices[2]; - /* di subdevice */ - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 16; - s->insn_bits = multiq3_di_insn_bits; - s->maxdata = 1; - s->range_table = &range_digital; - + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = multiq3_di_insn_bits; + + /* Digital Output subdevice */ s = &dev->subdevices[3]; - /* do subdevice */ - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 16; - s->insn_bits = multiq3_do_insn_bits; - s->maxdata = 1; - s->range_table = &range_digital; - s->state = 0; - + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = multiq3_do_insn_bits; + + /* Encoder (Counter) subdevice */ s = &dev->subdevices[4]; - /* encoder (counter) subdevice */ - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_READABLE | SDF_LSAMPL; - s->n_chan = it->options[2] * 2; - s->insn_read = multiq3_encoder_insn_read; - s->maxdata = 0xffffff; - s->range_table = &range_unknown; + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_READABLE | SDF_LSAMPL; + s->n_chan = it->options[2] * 2; + s->maxdata = 0x00ffffff; + s->range_table = &range_unknown; + s->insn_read = multiq3_encoder_insn_read; + s->insn_config = multiq3_encoder_insn_config; - encoder_reset(dev); + for (i = 0; i < s->n_chan; i++) + multiq3_encoder_reset(dev, i); return 0; } @@ -285,5 +337,5 @@ static struct comedi_driver multiq3_driver = { module_comedi_driver(multiq3_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for Quanser Consulting MultiQ-3 board"); MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/staging/comedi/drivers/ni_670x.c b/kernel/drivers/staging/comedi/drivers/ni_670x.c index 13c6ccb1f..f4c580f65 100644 --- a/kernel/drivers/staging/comedi/drivers/ni_670x.c +++ b/kernel/drivers/staging/comedi/drivers/ni_670x.c @@ -172,18 +172,18 @@ static int ni_670x_auto_attach(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct ni_670x_board *thisboard = NULL; + const struct ni_670x_board *board = NULL; struct ni_670x_private *devpriv; struct comedi_subdevice *s; int ret; int i; if (context < ARRAY_SIZE(ni_670x_boards)) - thisboard = &ni_670x_boards[context]; - if (!thisboard) + board = &ni_670x_boards[context]; + if (!board) return -ENODEV; - dev->board_ptr = thisboard; - dev->board_name = thisboard->name; + dev->board_ptr = board; + dev->board_name = board->name; ret = comedi_pci_enable(dev); if (ret) @@ -209,7 +209,7 @@ static int ni_670x_auto_attach(struct comedi_device *dev, /* analog output subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = thisboard->ao_chans; + s->n_chan = board->ao_chans; s->maxdata = 0xffff; if (s->n_chan == 32) { const struct comedi_lrange **range_table_list; diff --git a/kernel/drivers/staging/comedi/drivers/ni_at_a2150.c b/kernel/drivers/staging/comedi/drivers/ni_at_a2150.c index 3a972d153..9b444f8c4 100644 --- a/kernel/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/kernel/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -106,7 +106,7 @@ TRIG_WAKE_EOS #define IRQ_LVL_BITS(x) (((x) & 0xf) << 4) /* sets irq level */ #define FIFO_INTR_EN_BIT 0x100 /* enable fifo interrupts */ #define FIFO_INTR_FHF_BIT 0x200 /* interrupt fifo half full */ -#define DMA_INTR_EN_BIT 0x800 /* enable interrupt on dma terminal count */ +#define DMA_INTR_EN_BIT 0x800 /* enable interrupt on dma terminal count */ #define DMA_DEM_EN_BIT 0x1000 /* enables demand mode dma */ #define I8253_BASE_REG 0x14 @@ -264,7 +264,7 @@ static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s) static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, unsigned int flags) { - const struct a2150_board *thisboard = dev->board_ptr; + const struct a2150_board *board = dev->board_ptr; struct a2150_private *devpriv = dev->private; int lub, glb, temp; int lub_divisor_shift, lub_index, glb_divisor_shift, glb_index; @@ -273,10 +273,10 @@ static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, /* initialize greatest lower and least upper bounds */ lub_divisor_shift = 3; lub_index = 0; - lub = thisboard->clock[lub_index] * (1 << lub_divisor_shift); + lub = board->clock[lub_index] * (1 << lub_divisor_shift); glb_divisor_shift = 0; - glb_index = thisboard->num_clocks - 1; - glb = thisboard->clock[glb_index] * (1 << glb_divisor_shift); + glb_index = board->num_clocks - 1; + glb = board->clock[glb_index] * (1 << glb_divisor_shift); /* make sure period is in available range */ if (*period < glb) @@ -287,9 +287,9 @@ static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, /* we can multiply period by 1, 2, 4, or 8, using (1 << i) */ for (i = 0; i < 4; i++) { /* there are a maximum of 4 master clocks */ - for (j = 0; j < thisboard->num_clocks; j++) { + for (j = 0; j < board->num_clocks; j++) { /* temp is the period in nanosec we are evaluating */ - temp = thisboard->clock[j] * (1 << i); + temp = board->clock[j] * (1 << i); /* if it is the best match yet */ if (temp < lub && temp >= *period) { lub_divisor_shift = i; @@ -413,7 +413,7 @@ static int a2150_ai_check_chanlist(struct comedi_device *dev, static int a2150_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct a2150_board *thisboard = dev->board_ptr; + const struct a2150_board *board = dev->board_ptr; int err = 0; unsigned int arg; @@ -444,7 +444,7 @@ static int a2150_ai_cmdtest(struct comedi_device *dev, if (cmd->convert_src == TRIG_TIMER) { err |= comedi_check_trigger_arg_min(&cmd->convert_arg, - thisboard->ai_speed); + board->ai_speed); } err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1); @@ -687,17 +687,19 @@ static void a2150_free_dma(struct comedi_device *dev) comedi_isadma_free(devpriv->dma); } -/* probes board type, returns offset */ -static int a2150_probe(struct comedi_device *dev) +static const struct a2150_board *a2150_probe(struct comedi_device *dev) { - int status = inw(dev->iobase + STATUS_REG); + int id = ID_BITS(inw(dev->iobase + STATUS_REG)); - return ID_BITS(status); + if (id >= ARRAY_SIZE(a2150_boards)) + return NULL; + + return &a2150_boards[id]; } static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - const struct a2150_board *thisboard; + const struct a2150_board *board; struct a2150_private *devpriv; struct comedi_subdevice *s; static const int timeout = 2000; @@ -712,13 +714,11 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - i = a2150_probe(dev); - if (i >= ARRAY_SIZE(a2150_boards)) + board = a2150_probe(dev); + if (!board) return -ENODEV; - - dev->board_ptr = a2150_boards + i; - thisboard = dev->board_ptr; - dev->board_name = thisboard->name; + dev->board_ptr = board; + dev->board_name = board->name; /* an IRQ and DMA are required to support async commands */ a2150_alloc_irq_and_dma(dev, it); diff --git a/kernel/drivers/staging/comedi/drivers/ni_atmio.c b/kernel/drivers/staging/comedi/drivers/ni_atmio.c index 1304b0698..95435b81a 100644 --- a/kernel/drivers/staging/comedi/drivers/ni_atmio.c +++ b/kernel/drivers/staging/comedi/drivers/ni_atmio.c @@ -274,14 +274,16 @@ static int ni_isapnp_find_board(struct pnp_dev **dev) return 0; } -static int ni_getboardtype(struct comedi_device *dev) +static const struct ni_board_struct *ni_atmio_probe(struct comedi_device *dev) { int device_id = ni_read_eeprom(dev, 511); int i; for (i = 0; i < ARRAY_SIZE(ni_boards); i++) { - if (ni_boards[i].device_id == device_id) - return i; + const struct ni_board_struct *board = &ni_boards[i]; + + if (board->device_id == device_id) + return board; } if (device_id == 255) dev_err(dev->class_dev, "can't find board\n"); @@ -292,17 +294,16 @@ static int ni_getboardtype(struct comedi_device *dev) dev_err(dev->class_dev, "unknown device ID %d -- contact author\n", device_id); - return -1; + return NULL; } static int ni_atmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - const struct ni_board_struct *boardtype; + const struct ni_board_struct *board; struct pnp_dev *isapnp_dev; int ret; unsigned long iobase; - int board; unsigned int irq; ret = ni_alloc_private(dev); @@ -326,15 +327,11 @@ static int ni_atmio_attach(struct comedi_device *dev, if (ret) return ret; - /* get board type */ - - board = ni_getboardtype(dev); - if (board < 0) - return -EIO; - - dev->board_ptr = ni_boards + board; - boardtype = dev->board_ptr; - dev->board_name = boardtype->name; + board = ni_atmio_probe(dev); + if (!board) + return -ENODEV; + dev->board_ptr = board; + dev->board_name = board->name; /* irq stuff */ diff --git a/kernel/drivers/staging/comedi/drivers/ni_daq_dio24.c b/kernel/drivers/staging/comedi/drivers/ni_daq_dio24.c index a208cb348..d9de83ab0 100644 --- a/kernel/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/kernel/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -55,11 +55,7 @@ static int dio24_auto_attach(struct comedi_device *dev, /* 8255 dio */ s = &dev->subdevices[0]; - ret = subdev_8255_init(dev, s, NULL, 0x00); - if (ret) - return ret; - - return 0; + return subdev_8255_init(dev, s, NULL, 0x00); } static struct comedi_driver driver_dio24 = { diff --git a/kernel/drivers/staging/comedi/drivers/ni_mio_common.c b/kernel/drivers/staging/comedi/drivers/ni_mio_common.c index c66affd99..6cc304a4c 100644 --- a/kernel/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/kernel/drivers/staging/comedi/drivers/ni_mio_common.c @@ -60,7 +60,6 @@ /* A timeout count */ #define NI_TIMEOUT 1000 -static const unsigned old_RTSI_clock_channel = 7; /* Note: this table must match the ai_gain_* definitions */ static const short ni_gainlkup[][16] = { @@ -308,262 +307,154 @@ static uint8_t ni_readb(struct comedi_device *dev, int reg) * windowed STC registers to the m series register offsets. */ -static void m_series_stc_writel(struct comedi_device *dev, - uint32_t data, int reg) +struct mio_regmap { + unsigned int mio_reg; + int size; +}; + +static const struct mio_regmap m_series_stc_write_regmap[] = { + [NISTC_INTA_ACK_REG] = { 0x104, 2 }, + [NISTC_INTB_ACK_REG] = { 0x106, 2 }, + [NISTC_AI_CMD2_REG] = { 0x108, 2 }, + [NISTC_AO_CMD2_REG] = { 0x10a, 2 }, + [NISTC_G0_CMD_REG] = { 0x10c, 2 }, + [NISTC_G1_CMD_REG] = { 0x10e, 2 }, + [NISTC_AI_CMD1_REG] = { 0x110, 2 }, + [NISTC_AO_CMD1_REG] = { 0x112, 2 }, + /* + * NISTC_DIO_OUT_REG maps to: + * { NI_M_DIO_REG, 4 } and { NI_M_SCXI_SER_DO_REG, 1 } + */ + [NISTC_DIO_OUT_REG] = { 0, 0 }, /* DOES NOT MAP CLEANLY */ + [NISTC_DIO_CTRL_REG] = { 0, 0 }, /* DOES NOT MAP CLEANLY */ + [NISTC_AI_MODE1_REG] = { 0x118, 2 }, + [NISTC_AI_MODE2_REG] = { 0x11a, 2 }, + [NISTC_AI_SI_LOADA_REG] = { 0x11c, 4 }, + [NISTC_AI_SI_LOADB_REG] = { 0x120, 4 }, + [NISTC_AI_SC_LOADA_REG] = { 0x124, 4 }, + [NISTC_AI_SC_LOADB_REG] = { 0x128, 4 }, + [NISTC_AI_SI2_LOADA_REG] = { 0x12c, 4 }, + [NISTC_AI_SI2_LOADB_REG] = { 0x130, 4 }, + [NISTC_G0_MODE_REG] = { 0x134, 2 }, + [NISTC_G1_MODE_REG] = { 0x136, 2 }, + [NISTC_G0_LOADA_REG] = { 0x138, 4 }, + [NISTC_G0_LOADB_REG] = { 0x13c, 4 }, + [NISTC_G1_LOADA_REG] = { 0x140, 4 }, + [NISTC_G1_LOADB_REG] = { 0x144, 4 }, + [NISTC_G0_INPUT_SEL_REG] = { 0x148, 2 }, + [NISTC_G1_INPUT_SEL_REG] = { 0x14a, 2 }, + [NISTC_AO_MODE1_REG] = { 0x14c, 2 }, + [NISTC_AO_MODE2_REG] = { 0x14e, 2 }, + [NISTC_AO_UI_LOADA_REG] = { 0x150, 4 }, + [NISTC_AO_UI_LOADB_REG] = { 0x154, 4 }, + [NISTC_AO_BC_LOADA_REG] = { 0x158, 4 }, + [NISTC_AO_BC_LOADB_REG] = { 0x15c, 4 }, + [NISTC_AO_UC_LOADA_REG] = { 0x160, 4 }, + [NISTC_AO_UC_LOADB_REG] = { 0x164, 4 }, + [NISTC_CLK_FOUT_REG] = { 0x170, 2 }, + [NISTC_IO_BIDIR_PIN_REG] = { 0x172, 2 }, + [NISTC_RTSI_TRIG_DIR_REG] = { 0x174, 2 }, + [NISTC_INT_CTRL_REG] = { 0x176, 2 }, + [NISTC_AI_OUT_CTRL_REG] = { 0x178, 2 }, + [NISTC_ATRIG_ETC_REG] = { 0x17a, 2 }, + [NISTC_AI_START_STOP_REG] = { 0x17c, 2 }, + [NISTC_AI_TRIG_SEL_REG] = { 0x17e, 2 }, + [NISTC_AI_DIV_LOADA_REG] = { 0x180, 4 }, + [NISTC_AO_START_SEL_REG] = { 0x184, 2 }, + [NISTC_AO_TRIG_SEL_REG] = { 0x186, 2 }, + [NISTC_G0_AUTOINC_REG] = { 0x188, 2 }, + [NISTC_G1_AUTOINC_REG] = { 0x18a, 2 }, + [NISTC_AO_MODE3_REG] = { 0x18c, 2 }, + [NISTC_RESET_REG] = { 0x190, 2 }, + [NISTC_INTA_ENA_REG] = { 0x192, 2 }, + [NISTC_INTA2_ENA_REG] = { 0, 0 }, /* E-Series only */ + [NISTC_INTB_ENA_REG] = { 0x196, 2 }, + [NISTC_INTB2_ENA_REG] = { 0, 0 }, /* E-Series only */ + [NISTC_AI_PERSONAL_REG] = { 0x19a, 2 }, + [NISTC_AO_PERSONAL_REG] = { 0x19c, 2 }, + [NISTC_RTSI_TRIGA_OUT_REG] = { 0x19e, 2 }, + [NISTC_RTSI_TRIGB_OUT_REG] = { 0x1a0, 2 }, + [NISTC_RTSI_BOARD_REG] = { 0, 0 }, /* Unknown */ + [NISTC_CFG_MEM_CLR_REG] = { 0x1a4, 2 }, + [NISTC_ADC_FIFO_CLR_REG] = { 0x1a6, 2 }, + [NISTC_DAC_FIFO_CLR_REG] = { 0x1a8, 2 }, + [NISTC_AO_OUT_CTRL_REG] = { 0x1ac, 2 }, + [NISTC_AI_MODE3_REG] = { 0x1ae, 2 }, +}; + +static void m_series_stc_write(struct comedi_device *dev, + unsigned int data, unsigned int reg) { - unsigned offset; + const struct mio_regmap *regmap; - switch (reg) { - case AI_SC_Load_A_Registers: - offset = M_Offset_AI_SC_Load_A; - break; - case AI_SI_Load_A_Registers: - offset = M_Offset_AI_SI_Load_A; - break; - case AO_BC_Load_A_Register: - offset = M_Offset_AO_BC_Load_A; - break; - case AO_UC_Load_A_Register: - offset = M_Offset_AO_UC_Load_A; - break; - case AO_UI_Load_A_Register: - offset = M_Offset_AO_UI_Load_A; - break; - case G_Load_A_Register(0): - offset = M_Offset_G0_Load_A; - break; - case G_Load_A_Register(1): - offset = M_Offset_G1_Load_A; - break; - case G_Load_B_Register(0): - offset = M_Offset_G0_Load_B; - break; - case G_Load_B_Register(1): - offset = M_Offset_G1_Load_B; - break; - default: - dev_warn(dev->class_dev, - "%s: bug! unhandled register=0x%x in switch\n", + if (reg < ARRAY_SIZE(m_series_stc_write_regmap)) { + regmap = &m_series_stc_write_regmap[reg]; + } else { + dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n", __func__, reg); return; } - ni_writel(dev, data, offset); -} -static void m_series_stc_writew(struct comedi_device *dev, - uint16_t data, int reg) -{ - unsigned offset; - - switch (reg) { - case ADC_FIFO_Clear: - offset = M_Offset_AI_FIFO_Clear; - break; - case AI_Command_1_Register: - offset = M_Offset_AI_Command_1; - break; - case AI_Command_2_Register: - offset = M_Offset_AI_Command_2; - break; - case AI_Mode_1_Register: - offset = M_Offset_AI_Mode_1; - break; - case AI_Mode_2_Register: - offset = M_Offset_AI_Mode_2; - break; - case AI_Mode_3_Register: - offset = M_Offset_AI_Mode_3; - break; - case AI_Output_Control_Register: - offset = M_Offset_AI_Output_Control; - break; - case AI_Personal_Register: - offset = M_Offset_AI_Personal; - break; - case AI_SI2_Load_A_Register: - /* this is a 32 bit register on m series boards */ - ni_writel(dev, data, M_Offset_AI_SI2_Load_A); - return; - case AI_SI2_Load_B_Register: - /* this is a 32 bit register on m series boards */ - ni_writel(dev, data, M_Offset_AI_SI2_Load_B); - return; - case AI_START_STOP_Select_Register: - offset = M_Offset_AI_START_STOP_Select; - break; - case AI_Trigger_Select_Register: - offset = M_Offset_AI_Trigger_Select; - break; - case Analog_Trigger_Etc_Register: - offset = M_Offset_Analog_Trigger_Etc; - break; - case AO_Command_1_Register: - offset = M_Offset_AO_Command_1; - break; - case AO_Command_2_Register: - offset = M_Offset_AO_Command_2; - break; - case AO_Mode_1_Register: - offset = M_Offset_AO_Mode_1; - break; - case AO_Mode_2_Register: - offset = M_Offset_AO_Mode_2; - break; - case AO_Mode_3_Register: - offset = M_Offset_AO_Mode_3; - break; - case AO_Output_Control_Register: - offset = M_Offset_AO_Output_Control; - break; - case AO_Personal_Register: - offset = M_Offset_AO_Personal; - break; - case AO_Start_Select_Register: - offset = M_Offset_AO_Start_Select; - break; - case AO_Trigger_Select_Register: - offset = M_Offset_AO_Trigger_Select; - break; - case Clock_and_FOUT_Register: - offset = M_Offset_Clock_and_FOUT; - break; - case Configuration_Memory_Clear: - offset = M_Offset_Configuration_Memory_Clear; - break; - case DAC_FIFO_Clear: - offset = M_Offset_AO_FIFO_Clear; - break; - case DIO_Control_Register: - dev_dbg(dev->class_dev, - "%s: FIXME: register 0x%x does not map cleanly on to m-series boards\n", - __func__, reg); - return; - case G_Autoincrement_Register(0): - offset = M_Offset_G0_Autoincrement; - break; - case G_Autoincrement_Register(1): - offset = M_Offset_G1_Autoincrement; - break; - case G_Command_Register(0): - offset = M_Offset_G0_Command; - break; - case G_Command_Register(1): - offset = M_Offset_G1_Command; - break; - case G_Input_Select_Register(0): - offset = M_Offset_G0_Input_Select; - break; - case G_Input_Select_Register(1): - offset = M_Offset_G1_Input_Select; - break; - case G_Mode_Register(0): - offset = M_Offset_G0_Mode; - break; - case G_Mode_Register(1): - offset = M_Offset_G1_Mode; - break; - case Interrupt_A_Ack_Register: - offset = M_Offset_Interrupt_A_Ack; - break; - case Interrupt_A_Enable_Register: - offset = M_Offset_Interrupt_A_Enable; - break; - case Interrupt_B_Ack_Register: - offset = M_Offset_Interrupt_B_Ack; - break; - case Interrupt_B_Enable_Register: - offset = M_Offset_Interrupt_B_Enable; - break; - case Interrupt_Control_Register: - offset = M_Offset_Interrupt_Control; - break; - case IO_Bidirection_Pin_Register: - offset = M_Offset_IO_Bidirection_Pin; - break; - case Joint_Reset_Register: - offset = M_Offset_Joint_Reset; - break; - case RTSI_Trig_A_Output_Register: - offset = M_Offset_RTSI_Trig_A_Output; - break; - case RTSI_Trig_B_Output_Register: - offset = M_Offset_RTSI_Trig_B_Output; + switch (regmap->size) { + case 4: + ni_writel(dev, data, regmap->mio_reg); break; - case RTSI_Trig_Direction_Register: - offset = M_Offset_RTSI_Trig_Direction; + case 2: + ni_writew(dev, data, regmap->mio_reg); break; - /* - * FIXME: DIO_Output_Register (16 bit reg) is replaced by - * M_Offset_Static_Digital_Output (32 bit) and - * M_Offset_SCXI_Serial_Data_Out (8 bit) - */ default: - dev_warn(dev->class_dev, - "%s: bug! unhandled register=0x%x in switch\n", + dev_warn(dev->class_dev, "%s: unmapped register=0x%x\n", __func__, reg); - return; + break; } - ni_writew(dev, data, offset); } -static uint32_t m_series_stc_readl(struct comedi_device *dev, int reg) +static const struct mio_regmap m_series_stc_read_regmap[] = { + [NISTC_AI_STATUS1_REG] = { 0x104, 2 }, + [NISTC_AO_STATUS1_REG] = { 0x106, 2 }, + [NISTC_G01_STATUS_REG] = { 0x108, 2 }, + [NISTC_AI_STATUS2_REG] = { 0, 0 }, /* Unknown */ + [NISTC_AO_STATUS2_REG] = { 0x10c, 2 }, + [NISTC_DIO_IN_REG] = { 0, 0 }, /* Unknown */ + [NISTC_G0_HW_SAVE_REG] = { 0x110, 4 }, + [NISTC_G1_HW_SAVE_REG] = { 0x114, 4 }, + [NISTC_G0_SAVE_REG] = { 0x118, 4 }, + [NISTC_G1_SAVE_REG] = { 0x11c, 4 }, + [NISTC_AO_UI_SAVE_REG] = { 0x120, 4 }, + [NISTC_AO_BC_SAVE_REG] = { 0x124, 4 }, + [NISTC_AO_UC_SAVE_REG] = { 0x128, 4 }, + [NISTC_STATUS1_REG] = { 0x136, 2 }, + [NISTC_DIO_SERIAL_IN_REG] = { 0x009, 1 }, + [NISTC_STATUS2_REG] = { 0x13a, 2 }, + [NISTC_AI_SI_SAVE_REG] = { 0x180, 4 }, + [NISTC_AI_SC_SAVE_REG] = { 0x184, 4 }, +}; + +static unsigned int m_series_stc_read(struct comedi_device *dev, + unsigned int reg) { - unsigned offset; + const struct mio_regmap *regmap; - switch (reg) { - case G_HW_Save_Register(0): - offset = M_Offset_G0_HW_Save; - break; - case G_HW_Save_Register(1): - offset = M_Offset_G1_HW_Save; - break; - case G_Save_Register(0): - offset = M_Offset_G0_Save; - break; - case G_Save_Register(1): - offset = M_Offset_G1_Save; - break; - default: - dev_warn(dev->class_dev, - "%s: bug! unhandled register=0x%x in switch\n", + if (reg < ARRAY_SIZE(m_series_stc_read_regmap)) { + regmap = &m_series_stc_read_regmap[reg]; + } else { + dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n", __func__, reg); return 0; } - return ni_readl(dev, offset); -} -static uint16_t m_series_stc_readw(struct comedi_device *dev, int reg) -{ - unsigned offset; - - switch (reg) { - case AI_Status_1_Register: - offset = M_Offset_AI_Status_1; - break; - case AO_Status_1_Register: - offset = M_Offset_AO_Status_1; - break; - case AO_Status_2_Register: - offset = M_Offset_AO_Status_2; - break; - case DIO_Serial_Input_Register: - return ni_readb(dev, M_Offset_SCXI_Serial_Data_In); - case Joint_Status_1_Register: - offset = M_Offset_Joint_Status_1; - break; - case Joint_Status_2_Register: - offset = M_Offset_Joint_Status_2; - break; - case G_Status_Register: - offset = M_Offset_G01_Status; - break; + switch (regmap->size) { + case 4: + return ni_readl(dev, regmap->mio_reg); + case 2: + return ni_readw(dev, regmap->mio_reg); + case 1: + return ni_readb(dev, regmap->mio_reg); default: - dev_warn(dev->class_dev, - "%s: bug! unhandled register=0x%x in switch\n", + dev_warn(dev->class_dev, "%s: unmapped register=0x%x\n", __func__, reg); return 0; } - return ni_readw(dev, offset); } static void ni_stc_writew(struct comedi_device *dev, uint16_t data, int reg) @@ -572,14 +463,14 @@ static void ni_stc_writew(struct comedi_device *dev, uint16_t data, int reg) unsigned long flags; if (devpriv->is_m_series) { - m_series_stc_writew(dev, data, reg); + m_series_stc_write(dev, data, reg); } else { spin_lock_irqsave(&devpriv->window_lock, flags); if (!devpriv->mite && reg < 8) { ni_writew(dev, data, reg * 2); } else { - ni_writew(dev, reg, Window_Address); - ni_writew(dev, data, Window_Data); + ni_writew(dev, reg, NI_E_STC_WINDOW_ADDR_REG); + ni_writew(dev, data, NI_E_STC_WINDOW_DATA_REG); } spin_unlock_irqrestore(&devpriv->window_lock, flags); } @@ -590,7 +481,7 @@ static void ni_stc_writel(struct comedi_device *dev, uint32_t data, int reg) struct ni_private *devpriv = dev->private; if (devpriv->is_m_series) { - m_series_stc_writel(dev, data, reg); + m_series_stc_write(dev, data, reg); } else { ni_stc_writew(dev, data >> 16, reg); ni_stc_writew(dev, data & 0xffff, reg + 1); @@ -604,14 +495,14 @@ static uint16_t ni_stc_readw(struct comedi_device *dev, int reg) uint16_t val; if (devpriv->is_m_series) { - val = m_series_stc_readw(dev, reg); + val = m_series_stc_read(dev, reg); } else { spin_lock_irqsave(&devpriv->window_lock, flags); if (!devpriv->mite && reg < 8) { val = ni_readw(dev, reg * 2); } else { - ni_writew(dev, reg, Window_Address); - val = ni_readw(dev, Window_Data); + ni_writew(dev, reg, NI_E_STC_WINDOW_ADDR_REG); + val = ni_readw(dev, NI_E_STC_WINDOW_DATA_REG); } spin_unlock_irqrestore(&devpriv->window_lock, flags); } @@ -624,7 +515,7 @@ static uint32_t ni_stc_readl(struct comedi_device *dev, int reg) uint32_t val; if (devpriv->is_m_series) { - val = m_series_stc_readl(dev, reg); + val = m_series_stc_read(dev, reg); } else { val = ni_stc_readw(dev, reg) << 16; val |= ni_stc_readw(dev, reg + 1); @@ -640,33 +531,30 @@ static inline void ni_set_bitfield(struct comedi_device *dev, int reg, spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); switch (reg) { - case Interrupt_A_Enable_Register: + case NISTC_INTA_ENA_REG: devpriv->int_a_enable_reg &= ~bit_mask; devpriv->int_a_enable_reg |= bit_values & bit_mask; - ni_stc_writew(dev, devpriv->int_a_enable_reg, - Interrupt_A_Enable_Register); + ni_stc_writew(dev, devpriv->int_a_enable_reg, reg); break; - case Interrupt_B_Enable_Register: + case NISTC_INTB_ENA_REG: devpriv->int_b_enable_reg &= ~bit_mask; devpriv->int_b_enable_reg |= bit_values & bit_mask; - ni_stc_writew(dev, devpriv->int_b_enable_reg, - Interrupt_B_Enable_Register); + ni_stc_writew(dev, devpriv->int_b_enable_reg, reg); break; - case IO_Bidirection_Pin_Register: + case NISTC_IO_BIDIR_PIN_REG: devpriv->io_bidirection_pin_reg &= ~bit_mask; devpriv->io_bidirection_pin_reg |= bit_values & bit_mask; - ni_stc_writew(dev, devpriv->io_bidirection_pin_reg, - IO_Bidirection_Pin_Register); + ni_stc_writew(dev, devpriv->io_bidirection_pin_reg, reg); break; - case AI_AO_Select: + case NI_E_DMA_AI_AO_SEL_REG: devpriv->ai_ao_select_reg &= ~bit_mask; devpriv->ai_ao_select_reg |= bit_values & bit_mask; - ni_writeb(dev, devpriv->ai_ao_select_reg, AI_AO_Select); + ni_writeb(dev, devpriv->ai_ao_select_reg, reg); break; - case G0_G1_Select: + case NI_E_DMA_G0_G1_SEL_REG: devpriv->g0_g1_select_reg &= ~bit_mask; devpriv->g0_g1_select_reg |= bit_values & bit_mask; - ni_writeb(dev, devpriv->g0_g1_select_reg, G0_G1_Select); + ni_writeb(dev, devpriv->g0_g1_select_reg, reg); break; default: dev_err(dev->class_dev, "called with invalid register %d\n", @@ -679,48 +567,55 @@ static inline void ni_set_bitfield(struct comedi_device *dev, int reg, #ifdef PCIDMA /* DMA channel setup */ +static inline unsigned ni_stc_dma_channel_select_bitfield(unsigned channel) +{ + if (channel < 4) + return 1 << channel; + if (channel == 4) + return 0x3; + if (channel == 5) + return 0x5; + BUG(); + return 0; +} /* negative channel means no channel */ static inline void ni_set_ai_dma_channel(struct comedi_device *dev, int channel) { - unsigned bitfield; + unsigned bits = 0; if (channel >= 0) - bitfield = - (ni_stc_dma_channel_select_bitfield(channel) << - AI_DMA_Select_Shift) & AI_DMA_Select_Mask; - else - bitfield = 0; - ni_set_bitfield(dev, AI_AO_Select, AI_DMA_Select_Mask, bitfield); + bits = ni_stc_dma_channel_select_bitfield(channel); + + ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, + NI_E_DMA_AI_SEL_MASK, NI_E_DMA_AI_SEL(bits)); } /* negative channel means no channel */ static inline void ni_set_ao_dma_channel(struct comedi_device *dev, int channel) { - unsigned bitfield; + unsigned bits = 0; if (channel >= 0) - bitfield = - (ni_stc_dma_channel_select_bitfield(channel) << - AO_DMA_Select_Shift) & AO_DMA_Select_Mask; - else - bitfield = 0; - ni_set_bitfield(dev, AI_AO_Select, AO_DMA_Select_Mask, bitfield); + bits = ni_stc_dma_channel_select_bitfield(channel); + + ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, + NI_E_DMA_AO_SEL_MASK, NI_E_DMA_AO_SEL(bits)); } -/* negative mite_channel means no channel */ +/* negative channel means no channel */ static inline void ni_set_gpct_dma_channel(struct comedi_device *dev, unsigned gpct_index, - int mite_channel) + int channel) { - unsigned bitfield; + unsigned bits = 0; - if (mite_channel >= 0) - bitfield = GPCT_DMA_Select_Bits(gpct_index, mite_channel); - else - bitfield = 0; - ni_set_bitfield(dev, G0_G1_Select, GPCT_DMA_Select_Mask(gpct_index), - bitfield); + if (channel >= 0) + bits = ni_stc_dma_channel_select_bitfield(channel); + + ni_set_bitfield(dev, NI_E_DMA_G0_G1_SEL_REG, + NI_E_DMA_G0_G1_SEL_MASK(gpct_index), + NI_E_DMA_G0_G1_SEL(gpct_index, bits)); } /* negative mite_channel means no channel */ @@ -729,18 +624,21 @@ static inline void ni_set_cdo_dma_channel(struct comedi_device *dev, { struct ni_private *devpriv = dev->private; unsigned long flags; + unsigned bits; spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); - devpriv->cdio_dma_select_reg &= ~CDO_DMA_Select_Mask; + devpriv->cdio_dma_select_reg &= ~NI_M_CDIO_DMA_SEL_CDO_MASK; if (mite_channel >= 0) { - /*XXX just guessing ni_stc_dma_channel_select_bitfield() returns the right bits, - under the assumption the cdio dma selection works just like ai/ao/gpct. - Definitely works for dma channels 0 and 1. */ - devpriv->cdio_dma_select_reg |= - (ni_stc_dma_channel_select_bitfield(mite_channel) << - CDO_DMA_Select_Shift) & CDO_DMA_Select_Mask; - } - ni_writeb(dev, devpriv->cdio_dma_select_reg, M_Offset_CDIO_DMA_Select); + /* + * XXX just guessing ni_stc_dma_channel_select_bitfield() + * returns the right bits, under the assumption the cdio dma + * selection works just like ai/ao/gpct. + * Definitely works for dma channels 0 and 1. + */ + bits = ni_stc_dma_channel_select_bitfield(mite_channel); + devpriv->cdio_dma_select_reg |= NI_M_CDIO_DMA_SEL_CDO(bits); + } + ni_writeb(dev, devpriv->cdio_dma_select_reg, NI_M_CDIO_DMA_SEL_REG); mmiowb(); spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags); } @@ -795,7 +693,6 @@ static int ni_request_gpct_mite_channel(struct comedi_device *dev, unsigned long flags; struct mite_channel *mite_chan; - BUG_ON(gpct_index >= NUM_GPCT); spin_lock_irqsave(&devpriv->mite_channel_lock, flags); BUG_ON(devpriv->counter_dev->counters[gpct_index].mite_chan); mite_chan = @@ -879,7 +776,6 @@ static void ni_release_gpct_mite_channel(struct comedi_device *dev, struct ni_private *devpriv = dev->private; unsigned long flags; - BUG_ON(gpct_index >= NUM_GPCT); spin_lock_irqsave(&devpriv->mite_channel_lock, flags); if (devpriv->counter_dev->counters[gpct_index].mite_chan) { struct mite_channel *mite_chan = @@ -927,13 +823,13 @@ static void ni_e_series_enable_second_irq(struct comedi_device *dev, * dma requests for their counters */ if (gpct_index == 0) { - reg = Second_IRQ_A_Enable_Register; + reg = NISTC_INTA2_ENA_REG; if (enable) - val = G0_Gate_Second_Irq_Enable; + val = NISTC_INTA_ENA_G0_GATE; } else { - reg = Second_IRQ_B_Enable_Register; + reg = NISTC_INTB2_ENA_REG; if (enable) - val = G1_Gate_Second_Irq_Enable; + val = NISTC_INTB_ENA_G1_GATE; } ni_stc_writew(dev, val, reg); } @@ -947,30 +843,30 @@ static void ni_clear_ai_fifo(struct comedi_device *dev) if (devpriv->is_6143) { /* Flush the 6143 data FIFO */ - ni_writel(dev, 0x10, AIFIFO_Control_6143); - ni_writel(dev, 0x00, AIFIFO_Control_6143); + ni_writel(dev, 0x10, NI6143_AI_FIFO_CTRL_REG); + ni_writel(dev, 0x00, NI6143_AI_FIFO_CTRL_REG); /* Wait for complete */ for (i = 0; i < timeout; i++) { - if (!(ni_readl(dev, AIFIFO_Status_6143) & 0x10)) + if (!(ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x10)) break; udelay(1); } if (i == timeout) dev_err(dev->class_dev, "FIFO flush timeout\n"); } else { - ni_stc_writew(dev, 1, ADC_FIFO_Clear); + ni_stc_writew(dev, 1, NISTC_ADC_FIFO_CLR_REG); if (devpriv->is_625x) { - ni_writeb(dev, 0, M_Offset_Static_AI_Control(0)); - ni_writeb(dev, 1, M_Offset_Static_AI_Control(0)); + ni_writeb(dev, 0, NI_M_STATIC_AI_CTRL_REG(0)); + ni_writeb(dev, 1, NI_M_STATIC_AI_CTRL_REG(0)); #if 0 /* the NI example code does 3 convert pulses for 625x boards, but that appears to be wrong in practice. */ - ni_stc_writew(dev, AI_CONVERT_Pulse, - AI_Command_1_Register); - ni_stc_writew(dev, AI_CONVERT_Pulse, - AI_Command_1_Register); - ni_stc_writew(dev, AI_CONVERT_Pulse, - AI_Command_1_Register); + ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, + NISTC_AI_CMD1_REG); + ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, + NISTC_AI_CMD1_REG); + ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, + NISTC_AI_CMD1_REG); #endif } } @@ -983,8 +879,8 @@ static inline void ni_ao_win_outw(struct comedi_device *dev, uint16_t data, unsigned long flags; spin_lock_irqsave(&devpriv->window_lock, flags); - ni_writew(dev, addr, AO_Window_Address_611x); - ni_writew(dev, data, AO_Window_Data_611x); + ni_writew(dev, addr, NI611X_AO_WINDOW_ADDR_REG); + ni_writew(dev, data, NI611X_AO_WINDOW_DATA_REG); spin_unlock_irqrestore(&devpriv->window_lock, flags); } @@ -995,8 +891,8 @@ static inline void ni_ao_win_outl(struct comedi_device *dev, uint32_t data, unsigned long flags; spin_lock_irqsave(&devpriv->window_lock, flags); - ni_writew(dev, addr, AO_Window_Address_611x); - ni_writel(dev, data, AO_Window_Data_611x); + ni_writew(dev, addr, NI611X_AO_WINDOW_ADDR_REG); + ni_writel(dev, data, NI611X_AO_WINDOW_DATA_REG); spin_unlock_irqrestore(&devpriv->window_lock, flags); } @@ -1007,8 +903,8 @@ static inline unsigned short ni_ao_win_inw(struct comedi_device *dev, int addr) unsigned short data; spin_lock_irqsave(&devpriv->window_lock, flags); - ni_writew(dev, addr, AO_Window_Address_611x); - data = ni_readw(dev, AO_Window_Data_611x); + ni_writew(dev, addr, NI611X_AO_WINDOW_ADDR_REG); + data = ni_readw(dev, NI611X_AO_WINDOW_DATA_REG); spin_unlock_irqrestore(&devpriv->window_lock, flags); return data; } @@ -1059,8 +955,8 @@ static int ni_ai_drain_dma(struct comedi_device *dev) spin_lock_irqsave(&devpriv->mite_channel_lock, flags); if (devpriv->ai_mite_chan) { for (i = 0; i < timeout; i++) { - if ((ni_stc_readw(dev, AI_Status_1_Register) & - AI_FIFO_Empty_St) + if ((ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & + NISTC_AI_STATUS1_FIFO_E) && mite_bytes_in_transit(devpriv->ai_mite_chan) == 0) break; @@ -1071,7 +967,7 @@ static int ni_ai_drain_dma(struct comedi_device *dev) dev_err(dev->class_dev, "mite_bytes_in_transit=%i, AI_Status1_Register=0x%x\n", mite_bytes_in_transit(devpriv->ai_mite_chan), - ni_stc_readw(dev, AI_Status_1_Register)); + ni_stc_readw(dev, NISTC_AI_STATUS1_REG)); retval = -1; } } @@ -1103,8 +999,8 @@ static int ni_ao_wait_for_dma_load(struct comedi_device *dev) for (i = 0; i < timeout; i++) { unsigned short b_status; - b_status = ni_stc_readw(dev, AO_Status_1_Register); - if (b_status & AO_FIFO_Half_Full_St) + b_status = ni_stc_readw(dev, NISTC_AO_STATUS1_REG); + if (b_status & NISTC_AO_STATUS1_FIFO_HF) break; /* if we poll too often, the pci bus activity seems to slow the dma transfer down */ @@ -1139,9 +1035,9 @@ static void ni_ao_fifo_load(struct comedi_device *dev, i++; packed_data |= (d << 16) & 0xffff0000; } - ni_writel(dev, packed_data, DAC_FIFO_Data_611x); + ni_writel(dev, packed_data, NI611X_AO_FIFO_DATA_REG); } else { - ni_writew(dev, d, DAC_FIFO_Data); + ni_writew(dev, d, NI_E_AO_FIFO_DATA_REG); } } } @@ -1193,9 +1089,9 @@ static int ni_ao_prep_fifo(struct comedi_device *dev, unsigned int nsamples; /* reset fifo */ - ni_stc_writew(dev, 1, DAC_FIFO_Clear); + ni_stc_writew(dev, 1, NISTC_DAC_FIFO_CLR_REG); if (devpriv->is_6xxx) - ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x); + ni_ao_win_outl(dev, 0x6, NI611X_AO_FIFO_OFFSET_LOAD_REG); /* load some data */ nbytes = comedi_buf_read_n_available(s); @@ -1222,7 +1118,7 @@ static void ni_ai_fifo_read(struct comedi_device *dev, if (devpriv->is_611x) { for (i = 0; i < n / 2; i++) { - dl = ni_readl(dev, ADC_FIFO_Data_611x); + dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG); /* This may get the hi/lo data in the wrong order */ data = (dl >> 16) & 0xffff; comedi_buf_write_samples(s, &data, 1); @@ -1231,14 +1127,14 @@ static void ni_ai_fifo_read(struct comedi_device *dev, } /* Check if there's a single sample stuck in the FIFO */ if (n % 2) { - dl = ni_readl(dev, ADC_FIFO_Data_611x); + dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG); data = dl & 0xffff; comedi_buf_write_samples(s, &data, 1); } } else if (devpriv->is_6143) { /* This just reads the FIFO assuming the data is present, no checks on the FIFO status are performed */ for (i = 0; i < n / 2; i++) { - dl = ni_readl(dev, AIFIFO_Data_6143); + dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG); data = (dl >> 16) & 0xffff; comedi_buf_write_samples(s, &data, 1); @@ -1248,8 +1144,8 @@ static void ni_ai_fifo_read(struct comedi_device *dev, if (n % 2) { /* Assume there is a single sample stuck in the FIFO */ /* Get stranded sample into FIFO */ - ni_writel(dev, 0x01, AIFIFO_Control_6143); - dl = ni_readl(dev, AIFIFO_Data_6143); + ni_writel(dev, 0x01, NI6143_AI_FIFO_CTRL_REG); + dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG); data = (dl >> 16) & 0xffff; comedi_buf_write_samples(s, &data, 1); } @@ -1263,7 +1159,7 @@ static void ni_ai_fifo_read(struct comedi_device *dev, } for (i = 0; i < n; i++) { devpriv->ai_fifo_buffer[i] = - ni_readw(dev, ADC_FIFO_Data_Register); + ni_readw(dev, NI_E_AI_FIFO_DATA_REG); } comedi_buf_write_samples(s, devpriv->ai_fifo_buffer, n); } @@ -1294,9 +1190,9 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev) int i; if (devpriv->is_611x) { - while ((ni_stc_readw(dev, AI_Status_1_Register) & - AI_FIFO_Empty_St) == 0) { - dl = ni_readl(dev, ADC_FIFO_Data_611x); + while ((ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & + NISTC_AI_STATUS1_FIFO_E) == 0) { + dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG); /* This may get the hi/lo data in the wrong order */ data = dl >> 16; @@ -1306,8 +1202,8 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev) } } else if (devpriv->is_6143) { i = 0; - while (ni_readl(dev, AIFIFO_Status_6143) & 0x04) { - dl = ni_readl(dev, AIFIFO_Data_6143); + while (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x04) { + dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG); /* This may get the hi/lo data in the wrong order */ data = dl >> 16; @@ -1317,29 +1213,29 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev) i += 2; } /* Check if stranded sample is present */ - if (ni_readl(dev, AIFIFO_Status_6143) & 0x01) { + if (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x01) { /* Get stranded sample into FIFO */ - ni_writel(dev, 0x01, AIFIFO_Control_6143); - dl = ni_readl(dev, AIFIFO_Data_6143); + ni_writel(dev, 0x01, NI6143_AI_FIFO_CTRL_REG); + dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG); data = (dl >> 16) & 0xffff; comedi_buf_write_samples(s, &data, 1); } } else { - fifo_empty = ni_stc_readw(dev, AI_Status_1_Register) & - AI_FIFO_Empty_St; + fifo_empty = ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & + NISTC_AI_STATUS1_FIFO_E; while (fifo_empty == 0) { for (i = 0; i < sizeof(devpriv->ai_fifo_buffer) / sizeof(devpriv->ai_fifo_buffer[0]); i++) { fifo_empty = ni_stc_readw(dev, - AI_Status_1_Register) & - AI_FIFO_Empty_St; + NISTC_AI_STATUS1_REG) & + NISTC_AI_STATUS1_FIFO_E; if (fifo_empty) break; devpriv->ai_fifo_buffer[i] = - ni_readw(dev, ADC_FIFO_Data_Register); + ni_readw(dev, NI_E_AI_FIFO_DATA_REG); } comedi_buf_write_samples(s, devpriv->ai_fifo_buffer, i); } @@ -1357,8 +1253,8 @@ static void get_last_sample_611x(struct comedi_device *dev) return; /* Check if there's a single sample stuck in the FIFO */ - if (ni_readb(dev, XXX_Status) & 0x80) { - dl = ni_readl(dev, ADC_FIFO_Data_611x); + if (ni_readb(dev, NI_E_STATUS_REG) & 0x80) { + dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG); data = dl & 0xffff; comedi_buf_write_samples(s, &data, 1); } @@ -1375,10 +1271,10 @@ static void get_last_sample_6143(struct comedi_device *dev) return; /* Check if there's a single sample stuck in the FIFO */ - if (ni_readl(dev, AIFIFO_Status_6143) & 0x01) { + if (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x01) { /* Get stranded sample into FIFO */ - ni_writel(dev, 0x01, AIFIFO_Control_6143); - dl = ni_readl(dev, AIFIFO_Data_6143); + ni_writel(dev, 0x01, NI6143_AI_FIFO_CTRL_REG); + dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG); /* This may get the hi/lo data in the wrong order */ data = (dl >> 16) & 0xffff; @@ -1420,8 +1316,8 @@ static void ni_handle_eos(struct comedi_device *dev, struct comedi_subdevice *s) s->async->events |= COMEDI_CB_EOS; #endif } - /* handle special case of single scan using AI_End_On_End_Of_Scan */ - if ((devpriv->ai_cmd2 & AI_End_On_End_Of_Scan)) + /* handle special case of single scan */ + if (devpriv->ai_cmd2 & NISTC_AI_CMD2_END_ON_EOS) shutdown_ai_command(dev); } @@ -1444,17 +1340,16 @@ static void ack_a_interrupt(struct comedi_device *dev, unsigned short a_status) { unsigned short ack = 0; - if (a_status & AI_SC_TC_St) - ack |= AI_SC_TC_Interrupt_Ack; - if (a_status & AI_START1_St) - ack |= AI_START1_Interrupt_Ack; - if (a_status & AI_START_St) - ack |= AI_START_Interrupt_Ack; - if (a_status & AI_STOP_St) - /* not sure why we used to ack the START here also, instead of doing it independently. Frank Hess 2007-07-06 */ - ack |= AI_STOP_Interrupt_Ack /*| AI_START_Interrupt_Ack */; + if (a_status & NISTC_AI_STATUS1_SC_TC) + ack |= NISTC_INTA_ACK_AI_SC_TC; + if (a_status & NISTC_AI_STATUS1_START1) + ack |= NISTC_INTA_ACK_AI_START1; + if (a_status & NISTC_AI_STATUS1_START) + ack |= NISTC_INTA_ACK_AI_START; + if (a_status & NISTC_AI_STATUS1_STOP) + ack |= NISTC_INTA_ACK_AI_STOP; if (ack) - ni_stc_writew(dev, ack, Interrupt_A_Ack_Register); + ni_stc_writew(dev, ack, NISTC_INTA_ACK_REG); } static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, @@ -1483,8 +1378,8 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, #endif /* test for all uncommon interrupt events at the same time */ - if (status & (AI_Overrun_St | AI_Overflow_St | AI_SC_TC_Error_St | - AI_SC_TC_St | AI_START1_St)) { + if (status & (NISTC_AI_STATUS1_ERR | + NISTC_AI_STATUS1_SC_TC | NISTC_AI_STATUS1_START1)) { if (status == 0xffff) { dev_err(dev->class_dev, "Card removed?\n"); /* we probably aren't even running a command now, @@ -1495,41 +1390,40 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, } return; } - if (status & (AI_Overrun_St | AI_Overflow_St | - AI_SC_TC_Error_St)) { + if (status & NISTC_AI_STATUS1_ERR) { dev_err(dev->class_dev, "ai error a_status=%04x\n", status); shutdown_ai_command(dev); s->async->events |= COMEDI_CB_ERROR; - if (status & (AI_Overrun_St | AI_Overflow_St)) + if (status & NISTC_AI_STATUS1_OVER) s->async->events |= COMEDI_CB_OVERFLOW; comedi_handle_events(dev, s); return; } - if (status & AI_SC_TC_St) { + if (status & NISTC_AI_STATUS1_SC_TC) { if (cmd->stop_src == TRIG_COUNT) shutdown_ai_command(dev); } } #ifndef PCIDMA - if (status & AI_FIFO_Half_Full_St) { + if (status & NISTC_AI_STATUS1_FIFO_HF) { int i; static const int timeout = 10; /* pcmcia cards (at least 6036) seem to stop producing interrupts if we *fail to get the fifo less than half full, so loop to be sure.*/ for (i = 0; i < timeout; ++i) { ni_handle_fifo_half_full(dev); - if ((ni_stc_readw(dev, AI_Status_1_Register) & - AI_FIFO_Half_Full_St) == 0) + if ((ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & + NISTC_AI_STATUS1_FIFO_HF) == 0) break; } } #endif /* !PCIDMA */ - if ((status & AI_STOP_St)) + if (status & NISTC_AI_STATUS1_STOP) ni_handle_eos(dev, s); comedi_handle_events(dev, s); @@ -1539,22 +1433,22 @@ static void ack_b_interrupt(struct comedi_device *dev, unsigned short b_status) { unsigned short ack = 0; - if (b_status & AO_BC_TC_St) - ack |= AO_BC_TC_Interrupt_Ack; - if (b_status & AO_Overrun_St) - ack |= AO_Error_Interrupt_Ack; - if (b_status & AO_START_St) - ack |= AO_START_Interrupt_Ack; - if (b_status & AO_START1_St) - ack |= AO_START1_Interrupt_Ack; - if (b_status & AO_UC_TC_St) - ack |= AO_UC_TC_Interrupt_Ack; - if (b_status & AO_UI2_TC_St) - ack |= AO_UI2_TC_Interrupt_Ack; - if (b_status & AO_UPDATE_St) - ack |= AO_UPDATE_Interrupt_Ack; + if (b_status & NISTC_AO_STATUS1_BC_TC) + ack |= NISTC_INTB_ACK_AO_BC_TC; + if (b_status & NISTC_AO_STATUS1_OVERRUN) + ack |= NISTC_INTB_ACK_AO_ERR; + if (b_status & NISTC_AO_STATUS1_START) + ack |= NISTC_INTB_ACK_AO_START; + if (b_status & NISTC_AO_STATUS1_START1) + ack |= NISTC_INTB_ACK_AO_START1; + if (b_status & NISTC_AO_STATUS1_UC_TC) + ack |= NISTC_INTB_ACK_AO_UC_TC; + if (b_status & NISTC_AO_STATUS1_UI2_TC) + ack |= NISTC_INTB_ACK_AO_UI2_TC; + if (b_status & NISTC_AO_STATUS1_UPDATE) + ack |= NISTC_INTB_ACK_AO_UPDATE; if (ack) - ni_stc_writew(dev, ack, Interrupt_B_Ack_Register); + ni_stc_writew(dev, ack, NISTC_INTB_ACK_REG); } static void handle_b_interrupt(struct comedi_device *dev, @@ -1583,26 +1477,26 @@ static void handle_b_interrupt(struct comedi_device *dev, if (b_status == 0xffff) return; - if (b_status & AO_Overrun_St) { + if (b_status & NISTC_AO_STATUS1_OVERRUN) { dev_err(dev->class_dev, "AO FIFO underrun status=0x%04x status2=0x%04x\n", - b_status, ni_stc_readw(dev, AO_Status_2_Register)); + b_status, ni_stc_readw(dev, NISTC_AO_STATUS2_REG)); s->async->events |= COMEDI_CB_OVERFLOW; } - if (b_status & AO_BC_TC_St) + if (b_status & NISTC_AO_STATUS1_BC_TC) s->async->events |= COMEDI_CB_EOA; #ifndef PCIDMA - if (b_status & AO_FIFO_Request_St) { + if (b_status & NISTC_AO_STATUS1_FIFO_REQ) { int ret; ret = ni_ao_fifo_half_empty(dev, s); if (!ret) { dev_err(dev->class_dev, "AO buffer underrun\n"); - ni_set_bits(dev, Interrupt_B_Enable_Register, - AO_FIFO_Interrupt_Enable | - AO_Error_Interrupt_Enable, 0); + ni_set_bits(dev, NISTC_INTB_ENA_REG, + NISTC_INTB_ENA_AO_FIFO | + NISTC_INTB_ENA_AO_ERR, 0); s->async->events |= COMEDI_CB_OVERFLOW; } } @@ -1718,101 +1612,65 @@ static int ni_ao_setup_MITE_dma(struct comedi_device *dev) static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s) { struct ni_private *devpriv = dev->private; + unsigned ai_personal; + unsigned ai_out_ctrl; ni_release_ai_mite_channel(dev); /* ai configuration */ - ni_stc_writew(dev, AI_Configuration_Start | AI_Reset, - Joint_Reset_Register); + ni_stc_writew(dev, NISTC_RESET_AI_CFG_START | NISTC_RESET_AI, + NISTC_RESET_REG); - ni_set_bits(dev, Interrupt_A_Enable_Register, - AI_SC_TC_Interrupt_Enable | AI_START1_Interrupt_Enable | - AI_START2_Interrupt_Enable | AI_START_Interrupt_Enable | - AI_STOP_Interrupt_Enable | AI_Error_Interrupt_Enable | - AI_FIFO_Interrupt_Enable, 0); + ni_set_bits(dev, NISTC_INTA_ENA_REG, NISTC_INTA_ENA_AI_MASK, 0); ni_clear_ai_fifo(dev); if (!devpriv->is_6143) - ni_writeb(dev, 0, Misc_Command); - - ni_stc_writew(dev, AI_Disarm, AI_Command_1_Register); /* reset pulses */ - ni_stc_writew(dev, AI_Start_Stop | AI_Mode_1_Reserved - /*| AI_Trigger_Once */, - AI_Mode_1_Register); - ni_stc_writew(dev, 0x0000, AI_Mode_2_Register); + ni_writeb(dev, NI_E_MISC_CMD_EXT_ATRIG, NI_E_MISC_CMD_REG); + + ni_stc_writew(dev, NISTC_AI_CMD1_DISARM, NISTC_AI_CMD1_REG); + ni_stc_writew(dev, NISTC_AI_MODE1_START_STOP | + NISTC_AI_MODE1_RSVD + /*| NISTC_AI_MODE1_TRIGGER_ONCE */, + NISTC_AI_MODE1_REG); + ni_stc_writew(dev, 0, NISTC_AI_MODE2_REG); /* generate FIFO interrupts on non-empty */ - ni_stc_writew(dev, (0 << 6) | 0x0000, AI_Mode_3_Register); + ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_NE, + NISTC_AI_MODE3_REG); + + ai_personal = NISTC_AI_PERSONAL_SHIFTIN_PW | + NISTC_AI_PERSONAL_SOC_POLARITY | + NISTC_AI_PERSONAL_LOCALMUX_CLK_PW; + ai_out_ctrl = NISTC_AI_OUT_CTRL_SCAN_IN_PROG_SEL(3) | + NISTC_AI_OUT_CTRL_EXTMUX_CLK_SEL(0) | + NISTC_AI_OUT_CTRL_LOCALMUX_CLK_SEL(2) | + NISTC_AI_OUT_CTRL_SC_TC_SEL(3); if (devpriv->is_611x) { - ni_stc_writew(dev, - AI_SHIFTIN_Pulse_Width | - AI_SOC_Polarity | - AI_LOCALMUX_CLK_Pulse_Width, - AI_Personal_Register); - ni_stc_writew(dev, - AI_SCAN_IN_PROG_Output_Select(3) | - AI_EXTMUX_CLK_Output_Select(0) | - AI_LOCALMUX_CLK_Output_Select(2) | - AI_SC_TC_Output_Select(3) | - AI_CONVERT_Output_Select - (AI_CONVERT_Output_Enable_High), - AI_Output_Control_Register); + ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_HIGH; } else if (devpriv->is_6143) { - ni_stc_writew(dev, AI_SHIFTIN_Pulse_Width | - AI_SOC_Polarity | - AI_LOCALMUX_CLK_Pulse_Width, - AI_Personal_Register); - ni_stc_writew(dev, - AI_SCAN_IN_PROG_Output_Select(3) | - AI_EXTMUX_CLK_Output_Select(0) | - AI_LOCALMUX_CLK_Output_Select(2) | - AI_SC_TC_Output_Select(3) | - AI_CONVERT_Output_Select - (AI_CONVERT_Output_Enable_Low), - AI_Output_Control_Register); + ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_LOW; } else { - unsigned ai_output_control_bits; - - ni_stc_writew(dev, - AI_SHIFTIN_Pulse_Width | - AI_SOC_Polarity | - AI_CONVERT_Pulse_Width | - AI_LOCALMUX_CLK_Pulse_Width, - AI_Personal_Register); - ai_output_control_bits = - AI_SCAN_IN_PROG_Output_Select(3) | - AI_EXTMUX_CLK_Output_Select(0) | - AI_LOCALMUX_CLK_Output_Select(2) | - AI_SC_TC_Output_Select(3); + ai_personal |= NISTC_AI_PERSONAL_CONVERT_PW; if (devpriv->is_622x) - ai_output_control_bits |= - AI_CONVERT_Output_Select - (AI_CONVERT_Output_Enable_High); + ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_HIGH; else - ai_output_control_bits |= - AI_CONVERT_Output_Select - (AI_CONVERT_Output_Enable_Low); - ni_stc_writew(dev, ai_output_control_bits, - AI_Output_Control_Register); + ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_LOW; } + ni_stc_writew(dev, ai_personal, NISTC_AI_PERSONAL_REG); + ni_stc_writew(dev, ai_out_ctrl, NISTC_AI_OUT_CTRL_REG); + /* the following registers should not be changed, because there * are no backup registers in devpriv. If you want to change * any of these, add a backup register and other appropriate code: - * AI_Mode_1_Register - * AI_Mode_3_Register - * AI_Personal_Register - * AI_Output_Control_Register + * NISTC_AI_MODE1_REG + * NISTC_AI_MODE3_REG + * NISTC_AI_PERSONAL_REG + * NISTC_AI_OUT_CTRL_REG */ - ni_stc_writew(dev, - AI_SC_TC_Error_Confirm | - AI_START_Interrupt_Ack | - AI_START2_Interrupt_Ack | - AI_START1_Interrupt_Ack | - AI_SC_TC_Interrupt_Ack | - AI_Error_Interrupt_Ack | - AI_STOP_Interrupt_Ack, - Interrupt_A_Ack_Register); /* clear interrupts */ - - ni_stc_writew(dev, AI_Configuration_End, Joint_Reset_Register); + + /* clear interrupts */ + ni_stc_writew(dev, NISTC_INTA_ACK_AI_ALL, NISTC_INTA_ACK_REG); + + ni_stc_writew(dev, NISTC_RESET_AI_CFG_END, NISTC_RESET_REG); return 0; } @@ -1839,11 +1697,11 @@ static void ni_prime_channelgain_list(struct comedi_device *dev) { int i; - ni_stc_writew(dev, AI_CONVERT_Pulse, AI_Command_1_Register); + ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, NISTC_AI_CMD1_REG); for (i = 0; i < NI_TIMEOUT; ++i) { - if (!(ni_stc_readw(dev, AI_Status_1_Register) & - AI_FIFO_Empty_St)) { - ni_stc_writew(dev, 1, ADC_FIFO_Clear); + if (!(ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & + NISTC_AI_STATUS1_FIFO_E)) { + ni_stc_writew(dev, 1, NISTC_ADC_FIFO_CLR_REG); return; } udelay(1); @@ -1862,7 +1720,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev, unsigned int dither; unsigned range_code; - ni_stc_writew(dev, 1, Configuration_Memory_Clear); + ni_stc_writew(dev, 1, NISTC_CFG_MEM_CLR_REG); if ((list[0] & CR_ALT_SOURCE)) { unsigned bypass_bits; @@ -1871,22 +1729,17 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev, range = CR_RANGE(list[0]); range_code = ni_gainlkup[board->gainlkup][range]; dither = (list[0] & CR_ALT_FILTER) != 0; - bypass_bits = MSeries_AI_Bypass_Config_FIFO_Bit; - bypass_bits |= chan; - bypass_bits |= - (devpriv->ai_calib_source) & - (MSeries_AI_Bypass_Cal_Sel_Pos_Mask | - MSeries_AI_Bypass_Cal_Sel_Neg_Mask | - MSeries_AI_Bypass_Mode_Mux_Mask | - MSeries_AO_Bypass_AO_Cal_Sel_Mask); - bypass_bits |= MSeries_AI_Bypass_Gain_Bits(range_code); + bypass_bits = NI_M_CFG_BYPASS_FIFO | + NI_M_CFG_BYPASS_AI_CHAN(chan) | + NI_M_CFG_BYPASS_AI_GAIN(range_code) | + devpriv->ai_calib_source; if (dither) - bypass_bits |= MSeries_AI_Bypass_Dither_Bit; + bypass_bits |= NI_M_CFG_BYPASS_AI_DITHER; /* don't use 2's complement encoding */ - bypass_bits |= MSeries_AI_Bypass_Polarity_Bit; - ni_writel(dev, bypass_bits, M_Offset_AI_Config_FIFO_Bypass); + bypass_bits |= NI_M_CFG_BYPASS_AI_POLARITY; + ni_writel(dev, bypass_bits, NI_M_CFG_BYPASS_FIFO_REG); } else { - ni_writel(dev, 0, M_Offset_AI_Config_FIFO_Bypass); + ni_writel(dev, 0, NI_M_CFG_BYPASS_FIFO_REG); } for (i = 0; i < n_chan; i++) { unsigned config_bits = 0; @@ -1900,31 +1753,27 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev, devpriv->ai_offset[i] = 0; switch (aref) { case AREF_DIFF: - config_bits |= - MSeries_AI_Config_Channel_Type_Differential_Bits; + config_bits |= NI_M_AI_CFG_CHAN_TYPE_DIFF; break; case AREF_COMMON: - config_bits |= - MSeries_AI_Config_Channel_Type_Common_Ref_Bits; + config_bits |= NI_M_AI_CFG_CHAN_TYPE_COMMON; break; case AREF_GROUND: - config_bits |= - MSeries_AI_Config_Channel_Type_Ground_Ref_Bits; + config_bits |= NI_M_AI_CFG_CHAN_TYPE_GROUND; break; case AREF_OTHER: break; } - config_bits |= MSeries_AI_Config_Channel_Bits(chan); - config_bits |= - MSeries_AI_Config_Bank_Bits(board->reg_type, chan); - config_bits |= MSeries_AI_Config_Gain_Bits(range_code); + config_bits |= NI_M_AI_CFG_CHAN_SEL(chan); + config_bits |= NI_M_AI_CFG_BANK_SEL(chan); + config_bits |= NI_M_AI_CFG_GAIN(range_code); if (i == n_chan - 1) - config_bits |= MSeries_AI_Config_Last_Channel_Bit; + config_bits |= NI_M_AI_CFG_LAST_CHAN; if (dither) - config_bits |= MSeries_AI_Config_Dither_Bit; + config_bits |= NI_M_AI_CFG_DITHER; /* don't use 2's complement encoding */ - config_bits |= MSeries_AI_Config_Polarity_Bit; - ni_writew(dev, config_bits, M_Offset_AI_Config_FIFO_Data); + config_bits |= NI_M_AI_CFG_POLARITY; + ni_writew(dev, config_bits, NI_M_AI_CFG_FIFO_DATA_REG); } ni_prime_channelgain_list(dev); } @@ -1986,7 +1835,7 @@ static void ni_load_channelgain_list(struct comedi_device *dev, devpriv->changain_state = 0; } - ni_stc_writew(dev, 1, Configuration_Memory_Clear); + ni_stc_writew(dev, 1, NISTC_CFG_MEM_CLR_REG); /* Set up Calibration mode if required */ if (devpriv->is_6143) { @@ -1994,20 +1843,20 @@ static void ni_load_channelgain_list(struct comedi_device *dev, && !devpriv->ai_calib_source_enabled) { /* Strobe Relay enable bit */ ni_writew(dev, devpriv->ai_calib_source | - Calibration_Channel_6143_RelayOn, - Calibration_Channel_6143); + NI6143_CALIB_CHAN_RELAY_ON, + NI6143_CALIB_CHAN_REG); ni_writew(dev, devpriv->ai_calib_source, - Calibration_Channel_6143); + NI6143_CALIB_CHAN_REG); devpriv->ai_calib_source_enabled = 1; msleep_interruptible(100); /* Allow relays to change */ } else if (!(list[0] & CR_ALT_SOURCE) && devpriv->ai_calib_source_enabled) { /* Strobe Relay disable bit */ ni_writew(dev, devpriv->ai_calib_source | - Calibration_Channel_6143_RelayOff, - Calibration_Channel_6143); + NI6143_CALIB_CHAN_RELAY_OFF, + NI6143_CALIB_CHAN_REG); ni_writew(dev, devpriv->ai_calib_source, - Calibration_Channel_6143); + NI6143_CALIB_CHAN_REG); devpriv->ai_calib_source_enabled = 0; msleep_interruptible(100); /* Allow relays to change */ } @@ -2033,7 +1882,7 @@ static void ni_load_channelgain_list(struct comedi_device *dev, if ((list[i] & CR_ALT_SOURCE)) { if (devpriv->is_611x) ni_writew(dev, CR_CHAN(list[i]) & 0x0003, - Calibration_Channel_Select_611x); + NI611X_CALIB_CHAN_SEL_REG); } else { if (devpriv->is_611x) aref = AREF_DIFF; @@ -2041,30 +1890,31 @@ static void ni_load_channelgain_list(struct comedi_device *dev, aref = AREF_OTHER; switch (aref) { case AREF_DIFF: - hi |= AI_DIFFERENTIAL; + hi |= NI_E_AI_CFG_HI_TYPE_DIFF; break; case AREF_COMMON: - hi |= AI_COMMON; + hi |= NI_E_AI_CFG_HI_TYPE_COMMON; break; case AREF_GROUND: - hi |= AI_GROUND; + hi |= NI_E_AI_CFG_HI_TYPE_GROUND; break; case AREF_OTHER: break; } } - hi |= AI_CONFIG_CHANNEL(chan); + hi |= NI_E_AI_CFG_HI_CHAN(chan); - ni_writew(dev, hi, Configuration_Memory_High); + ni_writew(dev, hi, NI_E_AI_CFG_HI_REG); if (!devpriv->is_6143) { - lo = range; + lo = NI_E_AI_CFG_LO_GAIN(range); + if (i == n_chan - 1) - lo |= AI_LAST_CHANNEL; + lo |= NI_E_AI_CFG_LO_LAST_CHAN; if (dither) - lo |= AI_DITHER; + lo |= NI_E_AI_CFG_LO_DITHER; - ni_writew(dev, lo, Configuration_Memory_Low); + ni_writew(dev, lo, NI_E_AI_CFG_LO_REG); } } @@ -2092,25 +1942,27 @@ static int ni_ai_insn_read(struct comedi_device *dev, signbits = devpriv->ai_offset[0]; if (devpriv->is_611x) { for (n = 0; n < num_adc_stages_611x; n++) { - ni_stc_writew(dev, AI_CONVERT_Pulse, - AI_Command_1_Register); + ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, + NISTC_AI_CMD1_REG); udelay(1); } for (n = 0; n < insn->n; n++) { - ni_stc_writew(dev, AI_CONVERT_Pulse, - AI_Command_1_Register); + ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, + NISTC_AI_CMD1_REG); /* The 611x has screwy 32-bit FIFOs. */ d = 0; for (i = 0; i < NI_TIMEOUT; i++) { - if (ni_readb(dev, XXX_Status) & 0x80) { - d = ni_readl(dev, ADC_FIFO_Data_611x); + if (ni_readb(dev, NI_E_STATUS_REG) & 0x80) { + d = ni_readl(dev, + NI611X_AI_FIFO_DATA_REG); d >>= 16; d &= 0xffff; break; } - if (!(ni_stc_readw(dev, AI_Status_1_Register) & - AI_FIFO_Empty_St)) { - d = ni_readl(dev, ADC_FIFO_Data_611x); + if (!(ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & + NISTC_AI_STATUS1_FIFO_E)) { + d = ni_readl(dev, + NI611X_AI_FIFO_DATA_REG); d &= 0xffff; break; } @@ -2124,17 +1976,19 @@ static int ni_ai_insn_read(struct comedi_device *dev, } } else if (devpriv->is_6143) { for (n = 0; n < insn->n; n++) { - ni_stc_writew(dev, AI_CONVERT_Pulse, - AI_Command_1_Register); + ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, + NISTC_AI_CMD1_REG); /* The 6143 has 32-bit FIFOs. You need to strobe a bit to move a single 16bit stranded sample into the FIFO */ dl = 0; for (i = 0; i < NI_TIMEOUT; i++) { - if (ni_readl(dev, AIFIFO_Status_6143) & 0x01) { + if (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & + 0x01) { /* Get stranded sample into FIFO */ ni_writel(dev, 0x01, - AIFIFO_Control_6143); - dl = ni_readl(dev, AIFIFO_Data_6143); + NI6143_AI_FIFO_CTRL_REG); + dl = ni_readl(dev, + NI6143_AI_FIFO_DATA_REG); break; } } @@ -2146,11 +2000,11 @@ static int ni_ai_insn_read(struct comedi_device *dev, } } else { for (n = 0; n < insn->n; n++) { - ni_stc_writew(dev, AI_CONVERT_Pulse, - AI_Command_1_Register); + ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, + NISTC_AI_CMD1_REG); for (i = 0; i < NI_TIMEOUT; i++) { - if (!(ni_stc_readw(dev, AI_Status_1_Register) & - AI_FIFO_Empty_St)) + if (!(ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & + NISTC_AI_STATUS1_FIFO_E)) break; } if (i == NI_TIMEOUT) { @@ -2158,11 +2012,11 @@ static int ni_ai_insn_read(struct comedi_device *dev, return -ETIME; } if (devpriv->is_m_series) { - dl = ni_readl(dev, M_Offset_AI_FIFO_Data); + dl = ni_readl(dev, NI_M_AI_FIFO_DATA_REG); dl &= mask; data[n] = dl; } else { - d = ni_readw(dev, ADC_FIFO_Data_Register); + d = ni_readw(dev, NI_E_AI_FIFO_DATA_REG); d += signbits; /* subtle: needs to be short addition */ data[n] = d; } @@ -2374,8 +2228,8 @@ static int ni_ai_inttrig(struct comedi_device *dev, if (trig_num != cmd->start_arg) return -EINVAL; - ni_stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2, - AI_Command_2_Register); + ni_stc_writew(dev, NISTC_AI_CMD2_START1_PULSE | devpriv->ai_cmd2, + NISTC_AI_CMD2_REG); s->async->inttrig = NULL; return 1; @@ -2391,6 +2245,7 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) int start_stop_select = 0; unsigned int stop_count; int interrupt_a_enable = 0; + unsigned ai_trig; if (dev->irq == 0) { dev_err(dev->class_dev, "cannot run command without an irq\n"); @@ -2401,51 +2256,47 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) ni_load_channelgain_list(dev, s, cmd->chanlist_len, cmd->chanlist); /* start configuration */ - ni_stc_writew(dev, AI_Configuration_Start, Joint_Reset_Register); + ni_stc_writew(dev, NISTC_RESET_AI_CFG_START, NISTC_RESET_REG); /* disable analog triggering for now, since it * interferes with the use of pfi0 */ - devpriv->an_trig_etc_reg &= ~Analog_Trigger_Enable; - ni_stc_writew(dev, devpriv->an_trig_etc_reg, - Analog_Trigger_Etc_Register); + devpriv->an_trig_etc_reg &= ~NISTC_ATRIG_ETC_ENA; + ni_stc_writew(dev, devpriv->an_trig_etc_reg, NISTC_ATRIG_ETC_REG); + ai_trig = NISTC_AI_TRIG_START2_SEL(0) | NISTC_AI_TRIG_START1_SYNC; switch (cmd->start_src) { case TRIG_INT: case TRIG_NOW: - ni_stc_writew(dev, - AI_START2_Select(0) | - AI_START1_Sync | AI_START1_Edge | - AI_START1_Select(0), - AI_Trigger_Select_Register); + ai_trig |= NISTC_AI_TRIG_START1_EDGE | + NISTC_AI_TRIG_START1_SEL(0); break; case TRIG_EXT: - { - int chan = CR_CHAN(cmd->start_arg); - unsigned int bits = AI_START2_Select(0) | - AI_START1_Sync | AI_START1_Select(chan + 1); - - if (cmd->start_arg & CR_INVERT) - bits |= AI_START1_Polarity; - if (cmd->start_arg & CR_EDGE) - bits |= AI_START1_Edge; - ni_stc_writew(dev, bits, AI_Trigger_Select_Register); - break; - } + ai_trig |= NISTC_AI_TRIG_START1_SEL(CR_CHAN(cmd->start_arg) + + 1); + + if (cmd->start_arg & CR_INVERT) + ai_trig |= NISTC_AI_TRIG_START1_POLARITY; + if (cmd->start_arg & CR_EDGE) + ai_trig |= NISTC_AI_TRIG_START1_EDGE; + break; } + ni_stc_writew(dev, ai_trig, NISTC_AI_TRIG_SEL_REG); - mode2 &= ~AI_Pre_Trigger; - mode2 &= ~AI_SC_Initial_Load_Source; - mode2 &= ~AI_SC_Reload_Mode; - ni_stc_writew(dev, mode2, AI_Mode_2_Register); + mode2 &= ~NISTC_AI_MODE2_PRE_TRIGGER; + mode2 &= ~NISTC_AI_MODE2_SC_INIT_LOAD_SRC; + mode2 &= ~NISTC_AI_MODE2_SC_RELOAD_MODE; + ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG); if (cmd->chanlist_len == 1 || devpriv->is_611x || devpriv->is_6143) { - start_stop_select |= AI_STOP_Polarity; - start_stop_select |= AI_STOP_Select(31); /* logic low */ - start_stop_select |= AI_STOP_Sync; + /* logic low */ + start_stop_select |= NISTC_AI_STOP_POLARITY | + NISTC_AI_STOP_SEL(31) | + NISTC_AI_STOP_SYNC; } else { - start_stop_select |= AI_STOP_Select(19); /* ai configuration memory */ + /* ai configuration memory */ + start_stop_select |= NISTC_AI_STOP_SEL(19); } - ni_stc_writew(dev, start_stop_select, AI_START_STOP_Select_Register); + ni_stc_writew(dev, start_stop_select, NISTC_AI_START_STOP_REG); devpriv->ai_cmd2 = 0; switch (cmd->stop_src) { @@ -2457,80 +2308,80 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) stop_count += num_adc_stages_611x; } /* stage number of scans */ - ni_stc_writel(dev, stop_count, AI_SC_Load_A_Registers); + ni_stc_writel(dev, stop_count, NISTC_AI_SC_LOADA_REG); - mode1 |= AI_Start_Stop | AI_Mode_1_Reserved | AI_Trigger_Once; - ni_stc_writew(dev, mode1, AI_Mode_1_Register); + mode1 |= NISTC_AI_MODE1_START_STOP | + NISTC_AI_MODE1_RSVD | + NISTC_AI_MODE1_TRIGGER_ONCE; + ni_stc_writew(dev, mode1, NISTC_AI_MODE1_REG); /* load SC (Scan Count) */ - ni_stc_writew(dev, AI_SC_Load, AI_Command_1_Register); + ni_stc_writew(dev, NISTC_AI_CMD1_SC_LOAD, NISTC_AI_CMD1_REG); if (stop_count == 0) { - devpriv->ai_cmd2 |= AI_End_On_End_Of_Scan; - interrupt_a_enable |= AI_STOP_Interrupt_Enable; + devpriv->ai_cmd2 |= NISTC_AI_CMD2_END_ON_EOS; + interrupt_a_enable |= NISTC_INTA_ENA_AI_STOP; /* this is required to get the last sample for chanlist_len > 1, not sure why */ if (cmd->chanlist_len > 1) - start_stop_select |= - AI_STOP_Polarity | AI_STOP_Edge; + start_stop_select |= NISTC_AI_STOP_POLARITY | + NISTC_AI_STOP_EDGE; } break; case TRIG_NONE: /* stage number of scans */ - ni_stc_writel(dev, 0, AI_SC_Load_A_Registers); + ni_stc_writel(dev, 0, NISTC_AI_SC_LOADA_REG); - mode1 |= AI_Start_Stop | AI_Mode_1_Reserved | AI_Continuous; - ni_stc_writew(dev, mode1, AI_Mode_1_Register); + mode1 |= NISTC_AI_MODE1_START_STOP | + NISTC_AI_MODE1_RSVD | + NISTC_AI_MODE1_CONTINUOUS; + ni_stc_writew(dev, mode1, NISTC_AI_MODE1_REG); /* load SC (Scan Count) */ - ni_stc_writew(dev, AI_SC_Load, AI_Command_1_Register); + ni_stc_writew(dev, NISTC_AI_CMD1_SC_LOAD, NISTC_AI_CMD1_REG); break; } switch (cmd->scan_begin_src) { case TRIG_TIMER: /* - stop bits for non 611x boards - AI_SI_Special_Trigger_Delay=0 - AI_Pre_Trigger=0 - AI_START_STOP_Select_Register: - AI_START_Polarity=0 (?) rising edge - AI_START_Edge=1 edge triggered - AI_START_Sync=1 (?) - AI_START_Select=0 SI_TC - AI_STOP_Polarity=0 rising edge - AI_STOP_Edge=0 level - AI_STOP_Sync=1 - AI_STOP_Select=19 external pin (configuration mem) + * stop bits for non 611x boards + * NISTC_AI_MODE3_SI_TRIG_DELAY=0 + * NISTC_AI_MODE2_PRE_TRIGGER=0 + * NISTC_AI_START_STOP_REG: + * NISTC_AI_START_POLARITY=0 (?) rising edge + * NISTC_AI_START_EDGE=1 edge triggered + * NISTC_AI_START_SYNC=1 (?) + * NISTC_AI_START_SEL=0 SI_TC + * NISTC_AI_STOP_POLARITY=0 rising edge + * NISTC_AI_STOP_EDGE=0 level + * NISTC_AI_STOP_SYNC=1 + * NISTC_AI_STOP_SEL=19 external pin (configuration mem) */ - start_stop_select |= AI_START_Edge | AI_START_Sync; - ni_stc_writew(dev, start_stop_select, - AI_START_STOP_Select_Register); + start_stop_select |= NISTC_AI_START_EDGE | NISTC_AI_START_SYNC; + ni_stc_writew(dev, start_stop_select, NISTC_AI_START_STOP_REG); - mode2 |= AI_SI_Reload_Mode(0); - /* AI_SI_Initial_Load_Source=A */ - mode2 &= ~AI_SI_Initial_Load_Source; - /* mode2 |= AI_SC_Reload_Mode; */ - ni_stc_writew(dev, mode2, AI_Mode_2_Register); + mode2 &= ~NISTC_AI_MODE2_SI_INIT_LOAD_SRC; /* A */ + mode2 |= NISTC_AI_MODE2_SI_RELOAD_MODE(0); + /* mode2 |= NISTC_AI_MODE2_SC_RELOAD_MODE; */ + ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG); /* load SI */ timer = ni_ns_to_timer(dev, cmd->scan_begin_arg, CMDF_ROUND_NEAREST); - ni_stc_writel(dev, timer, AI_SI_Load_A_Registers); - ni_stc_writew(dev, AI_SI_Load, AI_Command_1_Register); + ni_stc_writel(dev, timer, NISTC_AI_SI_LOADA_REG); + ni_stc_writew(dev, NISTC_AI_CMD1_SI_LOAD, NISTC_AI_CMD1_REG); break; case TRIG_EXT: if (cmd->scan_begin_arg & CR_EDGE) - start_stop_select |= AI_START_Edge; - /* AI_START_Polarity==1 is falling edge */ - if (cmd->scan_begin_arg & CR_INVERT) - start_stop_select |= AI_START_Polarity; + start_stop_select |= NISTC_AI_START_EDGE; + if (cmd->scan_begin_arg & CR_INVERT) /* falling edge */ + start_stop_select |= NISTC_AI_START_POLARITY; if (cmd->scan_begin_src != cmd->convert_src || (cmd->scan_begin_arg & ~CR_EDGE) != (cmd->convert_arg & ~CR_EDGE)) - start_stop_select |= AI_START_Sync; + start_stop_select |= NISTC_AI_START_SYNC; start_stop_select |= - AI_START_Select(1 + CR_CHAN(cmd->scan_begin_arg)); - ni_stc_writew(dev, start_stop_select, - AI_START_STOP_Select_Register); + NISTC_AI_START_SEL(1 + CR_CHAN(cmd->scan_begin_arg)); + ni_stc_writew(dev, start_stop_select, NISTC_AI_START_STOP_REG); break; } @@ -2543,46 +2394,43 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) timer = ni_ns_to_timer(dev, cmd->convert_arg, CMDF_ROUND_NEAREST); /* 0,0 does not work */ - ni_stc_writew(dev, 1, AI_SI2_Load_A_Register); - ni_stc_writew(dev, timer, AI_SI2_Load_B_Register); + ni_stc_writew(dev, 1, NISTC_AI_SI2_LOADA_REG); + ni_stc_writew(dev, timer, NISTC_AI_SI2_LOADB_REG); - /* AI_SI2_Reload_Mode = alternate */ - /* AI_SI2_Initial_Load_Source = A */ - mode2 &= ~AI_SI2_Initial_Load_Source; - mode2 |= AI_SI2_Reload_Mode; - ni_stc_writew(dev, mode2, AI_Mode_2_Register); + mode2 &= ~NISTC_AI_MODE2_SI2_INIT_LOAD_SRC; /* A */ + mode2 |= NISTC_AI_MODE2_SI2_RELOAD_MODE; /* alternate */ + ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG); - /* AI_SI2_Load */ - ni_stc_writew(dev, AI_SI2_Load, AI_Command_1_Register); + ni_stc_writew(dev, NISTC_AI_CMD1_SI2_LOAD, NISTC_AI_CMD1_REG); - mode2 |= AI_SI2_Reload_Mode; /* alternate */ - mode2 |= AI_SI2_Initial_Load_Source; /* B */ - - ni_stc_writew(dev, mode2, AI_Mode_2_Register); + mode2 |= NISTC_AI_MODE2_SI2_INIT_LOAD_SRC; /* B */ + mode2 |= NISTC_AI_MODE2_SI2_RELOAD_MODE; /* alternate */ + ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG); break; case TRIG_EXT: - mode1 |= AI_CONVERT_Source_Select(1 + cmd->convert_arg); + mode1 |= NISTC_AI_MODE1_CONVERT_SRC(1 + cmd->convert_arg); if ((cmd->convert_arg & CR_INVERT) == 0) - mode1 |= AI_CONVERT_Source_Polarity; - ni_stc_writew(dev, mode1, AI_Mode_1_Register); + mode1 |= NISTC_AI_MODE1_CONVERT_POLARITY; + ni_stc_writew(dev, mode1, NISTC_AI_MODE1_REG); - mode2 |= AI_Start_Stop_Gate_Enable | AI_SC_Gate_Enable; - ni_stc_writew(dev, mode2, AI_Mode_2_Register); + mode2 |= NISTC_AI_MODE2_SC_GATE_ENA | + NISTC_AI_MODE2_START_STOP_GATE_ENA; + ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG); break; } if (dev->irq) { /* interrupt on FIFO, errors, SC_TC */ - interrupt_a_enable |= AI_Error_Interrupt_Enable | - AI_SC_TC_Interrupt_Enable; + interrupt_a_enable |= NISTC_INTA_ENA_AI_ERR | + NISTC_INTA_ENA_AI_SC_TC; #ifndef PCIDMA - interrupt_a_enable |= AI_FIFO_Interrupt_Enable; + interrupt_a_enable |= NISTC_INTA_ENA_AI_FIFO; #endif - if (cmd->flags & CMDF_WAKE_EOS - || (devpriv->ai_cmd2 & AI_End_On_End_Of_Scan)) { + if ((cmd->flags & CMDF_WAKE_EOS) || + (devpriv->ai_cmd2 & NISTC_AI_CMD2_END_ON_EOS)) { /* wake on end-of-scan */ devpriv->aimode = AIMODE_SCAN; } else { @@ -2593,66 +2441,60 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) case AIMODE_HALF_FULL: /*generate FIFO interrupts and DMA requests on half-full */ #ifdef PCIDMA - ni_stc_writew(dev, AI_FIFO_Mode_HF_to_E, - AI_Mode_3_Register); + ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_HF_E, + NISTC_AI_MODE3_REG); #else - ni_stc_writew(dev, AI_FIFO_Mode_HF, - AI_Mode_3_Register); + ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_HF, + NISTC_AI_MODE3_REG); #endif break; case AIMODE_SAMPLE: /*generate FIFO interrupts on non-empty */ - ni_stc_writew(dev, AI_FIFO_Mode_NE, - AI_Mode_3_Register); + ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_NE, + NISTC_AI_MODE3_REG); break; case AIMODE_SCAN: #ifdef PCIDMA - ni_stc_writew(dev, AI_FIFO_Mode_NE, - AI_Mode_3_Register); + ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_NE, + NISTC_AI_MODE3_REG); #else - ni_stc_writew(dev, AI_FIFO_Mode_HF, - AI_Mode_3_Register); + ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_HF, + NISTC_AI_MODE3_REG); #endif - interrupt_a_enable |= AI_STOP_Interrupt_Enable; + interrupt_a_enable |= NISTC_INTA_ENA_AI_STOP; break; default: break; } /* clear interrupts */ - ni_stc_writew(dev, - AI_Error_Interrupt_Ack | - AI_STOP_Interrupt_Ack | - AI_START_Interrupt_Ack | - AI_START2_Interrupt_Ack | - AI_START1_Interrupt_Ack | - AI_SC_TC_Interrupt_Ack | - AI_SC_TC_Error_Confirm, - Interrupt_A_Ack_Register); - - ni_set_bits(dev, Interrupt_A_Enable_Register, - interrupt_a_enable, 1); + ni_stc_writew(dev, NISTC_INTA_ACK_AI_ALL, NISTC_INTA_ACK_REG); + + ni_set_bits(dev, NISTC_INTA_ENA_REG, interrupt_a_enable, 1); } else { /* interrupt on nothing */ - ni_set_bits(dev, Interrupt_A_Enable_Register, ~0, 0); + ni_set_bits(dev, NISTC_INTA_ENA_REG, ~0, 0); /* XXX start polling if necessary */ } /* end configuration */ - ni_stc_writew(dev, AI_Configuration_End, Joint_Reset_Register); + ni_stc_writew(dev, NISTC_RESET_AI_CFG_END, NISTC_RESET_REG); switch (cmd->scan_begin_src) { case TRIG_TIMER: - ni_stc_writew(dev, - AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm | AI_SC_Arm, - AI_Command_1_Register); + ni_stc_writew(dev, NISTC_AI_CMD1_SI2_ARM | + NISTC_AI_CMD1_SI_ARM | + NISTC_AI_CMD1_DIV_ARM | + NISTC_AI_CMD1_SC_ARM, + NISTC_AI_CMD1_REG); break; case TRIG_EXT: - /* XXX AI_SI_Arm? */ - ni_stc_writew(dev, - AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm | AI_SC_Arm, - AI_Command_1_Register); + ni_stc_writew(dev, NISTC_AI_CMD1_SI2_ARM | + NISTC_AI_CMD1_SI_ARM | /* XXX ? */ + NISTC_AI_CMD1_DIV_ARM | + NISTC_AI_CMD1_SC_ARM, + NISTC_AI_CMD1_REG); break; } @@ -2666,9 +2508,9 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) #endif if (cmd->start_src == TRIG_NOW) { - /* AI_START1_Pulse */ - ni_stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2, - AI_Command_2_Register); + ni_stc_writew(dev, NISTC_AI_CMD2_START1_PULSE | + devpriv->ai_cmd2, + NISTC_AI_CMD2_REG); s->async->inttrig = NULL; } else if (cmd->start_src == TRIG_EXT) { s->async->inttrig = NULL; @@ -2691,12 +2533,8 @@ static int ni_ai_insn_config(struct comedi_device *dev, switch (data[0]) { case INSN_CONFIG_ALT_SOURCE: if (devpriv->is_m_series) { - if (data[1] & ~(MSeries_AI_Bypass_Cal_Sel_Pos_Mask | - MSeries_AI_Bypass_Cal_Sel_Neg_Mask | - MSeries_AI_Bypass_Mode_Mux_Mask | - MSeries_AO_Bypass_AO_Cal_Sel_Mask)) { + if (data[1] & ~NI_M_CFG_BYPASS_AI_CAL_MASK) return -EINVAL; - } devpriv->ai_calib_source = data[1]; } else if (devpriv->is_6143) { unsigned int calib_source; @@ -2704,7 +2542,7 @@ static int ni_ai_insn_config(struct comedi_device *dev, calib_source = data[1] & 0xf; devpriv->ai_calib_source = calib_source; - ni_writew(dev, calib_source, Calibration_Channel_6143); + ni_writew(dev, calib_source, NI6143_CALIB_CHAN_REG); } else { unsigned int calib_source; unsigned int calib_source_adjust; @@ -2717,7 +2555,7 @@ static int ni_ai_insn_config(struct comedi_device *dev, devpriv->ai_calib_source = calib_source; if (devpriv->is_611x) { ni_writeb(dev, calib_source_adjust, - Cal_Gain_Select_611x); + NI611X_CAL_GAIN_SEL_REG); } } return 2; @@ -2771,10 +2609,10 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev, if (timed) { for (i = 0; i < s->n_chan; ++i) { - devpriv->ao_conf[i] &= ~MSeries_AO_Update_Timed_Bit; + devpriv->ao_conf[i] &= ~NI_M_AO_CFG_BANK_UPDATE_TIMED; ni_writeb(dev, devpriv->ao_conf[i], - M_Offset_AO_Config_Bank(i)); - ni_writeb(dev, 0xf, M_Offset_AO_Waveform_Order(i)); + NI_M_AO_CFG_BANK_REG(i)); + ni_writeb(dev, 0xf, NI_M_AO_WAVEFORM_ORDER_REG(i)); } } for (i = 0; i < n_chans; i++) { @@ -2787,24 +2625,22 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev, conf = 0; switch (krange->max - krange->min) { case 20000000: - conf |= MSeries_AO_DAC_Reference_10V_Internal_Bits; - ni_writeb(dev, 0, - M_Offset_AO_Reference_Attenuation(chan)); + conf |= NI_M_AO_CFG_BANK_REF_INT_10V; + ni_writeb(dev, 0, NI_M_AO_REF_ATTENUATION_REG(chan)); break; case 10000000: - conf |= MSeries_AO_DAC_Reference_5V_Internal_Bits; - ni_writeb(dev, 0, - M_Offset_AO_Reference_Attenuation(chan)); + conf |= NI_M_AO_CFG_BANK_REF_INT_5V; + ni_writeb(dev, 0, NI_M_AO_REF_ATTENUATION_REG(chan)); break; case 4000000: - conf |= MSeries_AO_DAC_Reference_10V_Internal_Bits; - ni_writeb(dev, MSeries_Attenuate_x5_Bit, - M_Offset_AO_Reference_Attenuation(chan)); + conf |= NI_M_AO_CFG_BANK_REF_INT_10V; + ni_writeb(dev, NI_M_AO_REF_ATTENUATION_X5, + NI_M_AO_REF_ATTENUATION_REG(chan)); break; case 2000000: - conf |= MSeries_AO_DAC_Reference_5V_Internal_Bits; - ni_writeb(dev, MSeries_Attenuate_x5_Bit, - M_Offset_AO_Reference_Attenuation(chan)); + conf |= NI_M_AO_CFG_BANK_REF_INT_5V; + ni_writeb(dev, NI_M_AO_REF_ATTENUATION_X5, + NI_M_AO_REF_ATTENUATION_REG(chan)); break; default: dev_err(dev->class_dev, @@ -2813,10 +2649,10 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev, } switch (krange->max + krange->min) { case 0: - conf |= MSeries_AO_DAC_Offset_0V_Bits; + conf |= NI_M_AO_CFG_BANK_OFFSET_0V; break; case 10000000: - conf |= MSeries_AO_DAC_Offset_5V_Bits; + conf |= NI_M_AO_CFG_BANK_OFFSET_5V; break; default: dev_err(dev->class_dev, @@ -2824,10 +2660,10 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev, break; } if (timed) - conf |= MSeries_AO_Update_Timed_Bit; - ni_writeb(dev, conf, M_Offset_AO_Config_Bank(chan)); + conf |= NI_M_AO_CFG_BANK_UPDATE_TIMED; + ni_writeb(dev, conf, NI_M_AO_CFG_BANK_REG(chan)); devpriv->ao_conf[chan] = conf; - ni_writeb(dev, i, M_Offset_AO_Waveform_Order(chan)); + ni_writeb(dev, i, NI_M_AO_WAVEFORM_ORDER_REG(chan)); } return invert; } @@ -2847,27 +2683,27 @@ static int ni_old_ao_config_chanlist(struct comedi_device *dev, for (i = 0; i < n_chans; i++) { chan = CR_CHAN(chanspec[i]); range = CR_RANGE(chanspec[i]); - conf = AO_Channel(chan); + conf = NI_E_AO_DACSEL(chan); if (comedi_range_is_bipolar(s, range)) { - conf |= AO_Bipolar; + conf |= NI_E_AO_CFG_BIP; invert = (s->maxdata + 1) >> 1; } else { invert = 0; } if (comedi_range_is_external(s, range)) - conf |= AO_Ext_Ref; + conf |= NI_E_AO_EXT_REF; /* not all boards can deglitch, but this shouldn't hurt */ if (chanspec[i] & CR_DEGLITCH) - conf |= AO_Deglitch; + conf |= NI_E_AO_DEGLITCH; /* analog reference */ /* AREF_OTHER connects AO ground to AI ground, i think */ - conf |= (CR_AREF(chanspec[i]) == - AREF_OTHER) ? AO_Ground_Ref : 0; + if (CR_AREF(chanspec[i]) == AREF_OTHER) + conf |= NI_E_AO_GROUND_REF; - ni_writew(dev, conf, AO_Configuration); + ni_writew(dev, conf, NI_E_AO_CFG_REG); devpriv->ao_conf[chan] = conf; } return invert; @@ -2899,13 +2735,13 @@ static int ni_ao_insn_write(struct comedi_device *dev, int i; if (devpriv->is_6xxx) { - ni_ao_win_outw(dev, 1 << chan, AO_Immediate_671x); + ni_ao_win_outw(dev, 1 << chan, NI671X_AO_IMMEDIATE_REG); - reg = DACx_Direct_Data_671x(chan); + reg = NI671X_DAC_DIRECT_DATA_REG(chan); } else if (devpriv->is_m_series) { - reg = M_Offset_DAC_Direct_Data(chan); + reg = NI_M_DAC_DIRECT_DATA_REG(chan); } else { - reg = (chan) ? DAC1_Direct_Data : DAC0_Direct_Data; + reg = NI_E_DAC_DIRECT_DATA_REG(chan); } ni_ao_config_chanlist(dev, s, &insn->chanspec, 1, 0); @@ -2995,13 +2831,13 @@ static int ni_ao_inttrig(struct comedi_device *dev, multiple times) */ s->async->inttrig = NULL; - ni_set_bits(dev, Interrupt_B_Enable_Register, - AO_FIFO_Interrupt_Enable | AO_Error_Interrupt_Enable, 0); - interrupt_b_bits = AO_Error_Interrupt_Enable; + ni_set_bits(dev, NISTC_INTB_ENA_REG, + NISTC_INTB_ENA_AO_FIFO | NISTC_INTB_ENA_AO_ERR, 0); + interrupt_b_bits = NISTC_INTB_ENA_AO_ERR; #ifdef PCIDMA - ni_stc_writew(dev, 1, DAC_FIFO_Clear); + ni_stc_writew(dev, 1, NISTC_DAC_FIFO_CLR_REG); if (devpriv->is_6xxx) - ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x); + ni_ao_win_outl(dev, 0x6, NI611X_AO_FIFO_OFFSET_LOAD_REG); ret = ni_ao_setup_MITE_dma(dev); if (ret) return ret; @@ -3013,17 +2849,17 @@ static int ni_ao_inttrig(struct comedi_device *dev, if (ret == 0) return -EPIPE; - interrupt_b_bits |= AO_FIFO_Interrupt_Enable; + interrupt_b_bits |= NISTC_INTB_ENA_AO_FIFO; #endif - ni_stc_writew(dev, devpriv->ao_mode3 | AO_Not_An_UPDATE, - AO_Mode_3_Register); - ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); + ni_stc_writew(dev, devpriv->ao_mode3 | NISTC_AO_MODE3_NOT_AN_UPDATE, + NISTC_AO_MODE3_REG); + ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG); /* wait for DACs to be loaded */ for (i = 0; i < timeout; i++) { udelay(1); - if ((ni_stc_readw(dev, Joint_Status_2_Register) & - AO_TMRDACWRs_In_Progress_St) == 0) + if ((ni_stc_readw(dev, NISTC_STATUS2_REG) & + NISTC_STATUS2_AO_TMRDACWRS_IN_PROGRESS) == 0) break; } if (i == timeout) { @@ -3035,17 +2871,20 @@ static int ni_ao_inttrig(struct comedi_device *dev, * stc manual says we are need to clear error interrupt after * AO_TMRDACWRs_In_Progress_St clears */ - ni_stc_writew(dev, AO_Error_Interrupt_Ack, Interrupt_B_Ack_Register); + ni_stc_writew(dev, NISTC_INTB_ACK_AO_ERR, NISTC_INTB_ACK_REG); - ni_set_bits(dev, Interrupt_B_Enable_Register, interrupt_b_bits, 1); + ni_set_bits(dev, NISTC_INTB_ENA_REG, interrupt_b_bits, 1); - ni_stc_writew(dev, devpriv->ao_cmd1 | - AO_UI_Arm | AO_UC_Arm | AO_BC_Arm | - AO_DAC1_Update_Mode | AO_DAC0_Update_Mode, - AO_Command_1_Register); + ni_stc_writew(dev, NISTC_AO_CMD1_UI_ARM | + NISTC_AO_CMD1_UC_ARM | + NISTC_AO_CMD1_BC_ARM | + NISTC_AO_CMD1_DAC1_UPDATE_MODE | + NISTC_AO_CMD1_DAC0_UPDATE_MODE | + devpriv->ao_cmd1, + NISTC_AO_CMD1_REG); - ni_stc_writew(dev, devpriv->ao_cmd2 | AO_START1_Pulse, - AO_Command_2_Register); + ni_stc_writew(dev, NISTC_AO_CMD2_START1_PULSE | devpriv->ao_cmd2, + NISTC_AO_CMD2_REG); return 0; } @@ -3058,18 +2897,20 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) int bits; int i; unsigned trigvar; + unsigned val; if (dev->irq == 0) { dev_err(dev->class_dev, "cannot run command without an irq\n"); return -EIO; } - ni_stc_writew(dev, AO_Configuration_Start, Joint_Reset_Register); + ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); - ni_stc_writew(dev, AO_Disarm, AO_Command_1_Register); + ni_stc_writew(dev, NISTC_AO_CMD1_DISARM, NISTC_AO_CMD1_REG); if (devpriv->is_6xxx) { - ni_ao_win_outw(dev, CLEAR_WG, AO_Misc_611x); + ni_ao_win_outw(dev, NI611X_AO_MISC_CLEAR_WG, + NI611X_AO_MISC_REG); bits = 0; for (i = 0; i < cmd->chanlist_len; i++) { @@ -3077,172 +2918,186 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) chan = CR_CHAN(cmd->chanlist[i]); bits |= 1 << chan; - ni_ao_win_outw(dev, chan, AO_Waveform_Generation_611x); + ni_ao_win_outw(dev, chan, NI611X_AO_WAVEFORM_GEN_REG); } - ni_ao_win_outw(dev, bits, AO_Timed_611x); + ni_ao_win_outw(dev, bits, NI611X_AO_TIMED_REG); } ni_ao_config_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, 1); if (cmd->stop_src == TRIG_NONE) { - devpriv->ao_mode1 |= AO_Continuous; - devpriv->ao_mode1 &= ~AO_Trigger_Once; + devpriv->ao_mode1 |= NISTC_AO_MODE1_CONTINUOUS; + devpriv->ao_mode1 &= ~NISTC_AO_MODE1_TRIGGER_ONCE; } else { - devpriv->ao_mode1 &= ~AO_Continuous; - devpriv->ao_mode1 |= AO_Trigger_Once; + devpriv->ao_mode1 &= ~NISTC_AO_MODE1_CONTINUOUS; + devpriv->ao_mode1 |= NISTC_AO_MODE1_TRIGGER_ONCE; } - ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); + ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); + + val = devpriv->ao_trigger_select; switch (cmd->start_src) { case TRIG_INT: case TRIG_NOW: - devpriv->ao_trigger_select &= - ~(AO_START1_Polarity | AO_START1_Select(-1)); - devpriv->ao_trigger_select |= AO_START1_Edge | AO_START1_Sync; - ni_stc_writew(dev, devpriv->ao_trigger_select, - AO_Trigger_Select_Register); + val &= ~(NISTC_AO_TRIG_START1_POLARITY | + NISTC_AO_TRIG_START1_SEL_MASK); + val |= NISTC_AO_TRIG_START1_EDGE | + NISTC_AO_TRIG_START1_SYNC; break; case TRIG_EXT: - devpriv->ao_trigger_select = - AO_START1_Select(CR_CHAN(cmd->start_arg) + 1); - if (cmd->start_arg & CR_INVERT) - devpriv->ao_trigger_select |= AO_START1_Polarity; /* 0=active high, 1=active low. see daq-stc 3-24 (p186) */ - if (cmd->start_arg & CR_EDGE) - devpriv->ao_trigger_select |= AO_START1_Edge; /* 0=edge detection disabled, 1=enabled */ + val = NISTC_AO_TRIG_START1_SEL(CR_CHAN(cmd->start_arg) + 1); + if (cmd->start_arg & CR_INVERT) { + /* 0=active high, 1=active low. see daq-stc 3-24 (p186) */ + val |= NISTC_AO_TRIG_START1_POLARITY; + } + if (cmd->start_arg & CR_EDGE) { + /* 0=edge detection disabled, 1=enabled */ + val |= NISTC_AO_TRIG_START1_EDGE; + } ni_stc_writew(dev, devpriv->ao_trigger_select, - AO_Trigger_Select_Register); + NISTC_AO_TRIG_SEL_REG); break; default: BUG(); break; } - devpriv->ao_mode3 &= ~AO_Trigger_Length; - ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); + devpriv->ao_trigger_select = val; + ni_stc_writew(dev, devpriv->ao_trigger_select, NISTC_AO_TRIG_SEL_REG); + + devpriv->ao_mode3 &= ~NISTC_AO_MODE3_TRIG_LEN; + ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG); - ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); - devpriv->ao_mode2 &= ~AO_BC_Initial_Load_Source; - ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); + ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); + devpriv->ao_mode2 &= ~NISTC_AO_MODE2_BC_INIT_LOAD_SRC; + ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); if (cmd->stop_src == TRIG_NONE) - ni_stc_writel(dev, 0xffffff, AO_BC_Load_A_Register); + ni_stc_writel(dev, 0xffffff, NISTC_AO_BC_LOADA_REG); else - ni_stc_writel(dev, 0, AO_BC_Load_A_Register); - ni_stc_writew(dev, AO_BC_Load, AO_Command_1_Register); - devpriv->ao_mode2 &= ~AO_UC_Initial_Load_Source; - ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); + ni_stc_writel(dev, 0, NISTC_AO_BC_LOADA_REG); + ni_stc_writew(dev, NISTC_AO_CMD1_BC_LOAD, NISTC_AO_CMD1_REG); + devpriv->ao_mode2 &= ~NISTC_AO_MODE2_UC_INIT_LOAD_SRC; + ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); switch (cmd->stop_src) { case TRIG_COUNT: if (devpriv->is_m_series) { /* this is how the NI example code does it for m-series boards, verified correct with 6259 */ ni_stc_writel(dev, cmd->stop_arg - 1, - AO_UC_Load_A_Register); - ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register); + NISTC_AO_UC_LOADA_REG); + ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, + NISTC_AO_CMD1_REG); } else { ni_stc_writel(dev, cmd->stop_arg, - AO_UC_Load_A_Register); - ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register); + NISTC_AO_UC_LOADA_REG); + ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, + NISTC_AO_CMD1_REG); ni_stc_writel(dev, cmd->stop_arg - 1, - AO_UC_Load_A_Register); + NISTC_AO_UC_LOADA_REG); } break; case TRIG_NONE: - ni_stc_writel(dev, 0xffffff, AO_UC_Load_A_Register); - ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register); - ni_stc_writel(dev, 0xffffff, AO_UC_Load_A_Register); + ni_stc_writel(dev, 0xffffff, NISTC_AO_UC_LOADA_REG); + ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG); + ni_stc_writel(dev, 0xffffff, NISTC_AO_UC_LOADA_REG); break; default: - ni_stc_writel(dev, 0, AO_UC_Load_A_Register); - ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register); - ni_stc_writel(dev, cmd->stop_arg, AO_UC_Load_A_Register); + ni_stc_writel(dev, 0, NISTC_AO_UC_LOADA_REG); + ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG); + ni_stc_writel(dev, cmd->stop_arg, NISTC_AO_UC_LOADA_REG); } - devpriv->ao_mode1 &= - ~(AO_UI_Source_Select(0x1f) | AO_UI_Source_Polarity | - AO_UPDATE_Source_Select(0x1f) | AO_UPDATE_Source_Polarity); + devpriv->ao_mode1 &= ~(NISTC_AO_MODE1_UPDATE_SRC_MASK | + NISTC_AO_MODE1_UI_SRC_MASK | + NISTC_AO_MODE1_UPDATE_SRC_POLARITY | + NISTC_AO_MODE1_UI_SRC_POLARITY); switch (cmd->scan_begin_src) { case TRIG_TIMER: - devpriv->ao_cmd2 &= ~AO_BC_Gate_Enable; + devpriv->ao_cmd2 &= ~NISTC_AO_CMD2_BC_GATE_ENA; trigvar = ni_ns_to_timer(dev, cmd->scan_begin_arg, CMDF_ROUND_NEAREST); - ni_stc_writel(dev, 1, AO_UI_Load_A_Register); - ni_stc_writew(dev, AO_UI_Load, AO_Command_1_Register); - ni_stc_writel(dev, trigvar, AO_UI_Load_A_Register); + ni_stc_writel(dev, 1, NISTC_AO_UI_LOADA_REG); + ni_stc_writew(dev, NISTC_AO_CMD1_UI_LOAD, NISTC_AO_CMD1_REG); + ni_stc_writel(dev, trigvar, NISTC_AO_UI_LOADA_REG); break; case TRIG_EXT: devpriv->ao_mode1 |= - AO_UPDATE_Source_Select(cmd->scan_begin_arg); + NISTC_AO_MODE1_UPDATE_SRC(cmd->scan_begin_arg); if (cmd->scan_begin_arg & CR_INVERT) - devpriv->ao_mode1 |= AO_UPDATE_Source_Polarity; - devpriv->ao_cmd2 |= AO_BC_Gate_Enable; + devpriv->ao_mode1 |= NISTC_AO_MODE1_UPDATE_SRC_POLARITY; + devpriv->ao_cmd2 |= NISTC_AO_CMD2_BC_GATE_ENA; break; default: BUG(); break; } - ni_stc_writew(dev, devpriv->ao_cmd2, AO_Command_2_Register); - ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); - devpriv->ao_mode2 &= - ~(AO_UI_Reload_Mode(3) | AO_UI_Initial_Load_Source); - ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); + ni_stc_writew(dev, devpriv->ao_cmd2, NISTC_AO_CMD2_REG); + ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); + devpriv->ao_mode2 &= ~(NISTC_AO_MODE2_UI_RELOAD_MODE(3) | + NISTC_AO_MODE2_UI_INIT_LOAD_SRC); + ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); if (cmd->scan_end_arg > 1) { - devpriv->ao_mode1 |= AO_Multiple_Channels; + devpriv->ao_mode1 |= NISTC_AO_MODE1_MULTI_CHAN; ni_stc_writew(dev, - AO_Number_Of_Channels(cmd->scan_end_arg - 1) | - AO_UPDATE_Output_Select(AO_Update_Output_High_Z), - AO_Output_Control_Register); + NISTC_AO_OUT_CTRL_CHANS(cmd->scan_end_arg - 1) | + NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ, + NISTC_AO_OUT_CTRL_REG); } else { unsigned bits; - devpriv->ao_mode1 &= ~AO_Multiple_Channels; - bits = AO_UPDATE_Output_Select(AO_Update_Output_High_Z); + devpriv->ao_mode1 &= ~NISTC_AO_MODE1_MULTI_CHAN; + bits = NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ; if (devpriv->is_m_series || devpriv->is_6xxx) { - bits |= AO_Number_Of_Channels(0); + bits |= NISTC_AO_OUT_CTRL_CHANS(0); } else { bits |= - AO_Number_Of_Channels(CR_CHAN(cmd->chanlist[0])); + NISTC_AO_OUT_CTRL_CHANS(CR_CHAN(cmd->chanlist[0])); } - ni_stc_writew(dev, bits, AO_Output_Control_Register); + ni_stc_writew(dev, bits, NISTC_AO_OUT_CTRL_REG); } - ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); + ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); - ni_stc_writew(dev, AO_DAC0_Update_Mode | AO_DAC1_Update_Mode, - AO_Command_1_Register); + ni_stc_writew(dev, NISTC_AO_CMD1_DAC1_UPDATE_MODE | + NISTC_AO_CMD1_DAC0_UPDATE_MODE, + NISTC_AO_CMD1_REG); - devpriv->ao_mode3 |= AO_Stop_On_Overrun_Error; - ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); + devpriv->ao_mode3 |= NISTC_AO_MODE3_STOP_ON_OVERRUN_ERR; + ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG); - devpriv->ao_mode2 &= ~AO_FIFO_Mode_Mask; + devpriv->ao_mode2 &= ~NISTC_AO_MODE2_FIFO_MODE_MASK; #ifdef PCIDMA - devpriv->ao_mode2 |= AO_FIFO_Mode_HF_to_F; + devpriv->ao_mode2 |= NISTC_AO_MODE2_FIFO_MODE_HF_F; #else - devpriv->ao_mode2 |= AO_FIFO_Mode_HF; + devpriv->ao_mode2 |= NISTC_AO_MODE2_FIFO_MODE_HF; #endif - devpriv->ao_mode2 &= ~AO_FIFO_Retransmit_Enable; - ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); + devpriv->ao_mode2 &= ~NISTC_AO_MODE2_FIFO_REXMIT_ENA; + ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); - bits = AO_BC_Source_Select | AO_UPDATE_Pulse_Width | - AO_TMRDACWR_Pulse_Width; + bits = NISTC_AO_PERSONAL_BC_SRC_SEL | + NISTC_AO_PERSONAL_UPDATE_PW | + NISTC_AO_PERSONAL_TMRDACWR_PW; if (board->ao_fifo_depth) - bits |= AO_FIFO_Enable; + bits |= NISTC_AO_PERSONAL_FIFO_ENA; else - bits |= AO_DMA_PIO_Control; + bits |= NISTC_AO_PERSONAL_DMA_PIO_CTRL; #if 0 - /* F Hess: windows driver does not set AO_Number_Of_DAC_Packages bit for 6281, - verified with bus analyzer. */ + /* + * F Hess: windows driver does not set NISTC_AO_PERSONAL_NUM_DAC bit + * for 6281, verified with bus analyzer. + */ if (devpriv->is_m_series) - bits |= AO_Number_Of_DAC_Packages; + bits |= NISTC_AO_PERSONAL_NUM_DAC; #endif - ni_stc_writew(dev, bits, AO_Personal_Register); + ni_stc_writew(dev, bits, NISTC_AO_PERSONAL_REG); /* enable sending of ao dma requests */ - ni_stc_writew(dev, AO_AOFREQ_Enable, AO_Start_Select_Register); + ni_stc_writew(dev, NISTC_AO_START_AOFREQ_ENA, NISTC_AO_START_SEL_REG); - ni_stc_writew(dev, AO_Configuration_End, Joint_Reset_Register); + ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); if (cmd->stop_src == TRIG_COUNT) { - ni_stc_writew(dev, AO_BC_TC_Interrupt_Ack, - Interrupt_B_Ack_Register); - ni_set_bits(dev, Interrupt_B_Enable_Register, - AO_BC_TC_Interrupt_Enable, 1); + ni_stc_writew(dev, NISTC_INTB_ACK_AO_BC_TC, + NISTC_INTB_ACK_REG); + ni_set_bits(dev, NISTC_INTB_ENA_REG, + NISTC_INTB_ENA_AO_BC_TC, 1); } s->async->inttrig = ni_ao_inttrig; @@ -3339,41 +3194,44 @@ static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s) ni_release_ao_mite_channel(dev); - ni_stc_writew(dev, AO_Configuration_Start, Joint_Reset_Register); - ni_stc_writew(dev, AO_Disarm, AO_Command_1_Register); - ni_set_bits(dev, Interrupt_B_Enable_Register, ~0, 0); - ni_stc_writew(dev, AO_BC_Source_Select, AO_Personal_Register); - ni_stc_writew(dev, 0x3f98, Interrupt_B_Ack_Register); - ni_stc_writew(dev, AO_BC_Source_Select | AO_UPDATE_Pulse_Width | - AO_TMRDACWR_Pulse_Width, AO_Personal_Register); - ni_stc_writew(dev, 0, AO_Output_Control_Register); - ni_stc_writew(dev, 0, AO_Start_Select_Register); + ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); + ni_stc_writew(dev, NISTC_AO_CMD1_DISARM, NISTC_AO_CMD1_REG); + ni_set_bits(dev, NISTC_INTB_ENA_REG, ~0, 0); + ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL, NISTC_AO_PERSONAL_REG); + ni_stc_writew(dev, NISTC_INTB_ACK_AO_ALL, NISTC_INTB_ACK_REG); + ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL | + NISTC_AO_PERSONAL_UPDATE_PW | + NISTC_AO_PERSONAL_TMRDACWR_PW, + NISTC_AO_PERSONAL_REG); + ni_stc_writew(dev, 0, NISTC_AO_OUT_CTRL_REG); + ni_stc_writew(dev, 0, NISTC_AO_START_SEL_REG); devpriv->ao_cmd1 = 0; - ni_stc_writew(dev, devpriv->ao_cmd1, AO_Command_1_Register); + ni_stc_writew(dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG); devpriv->ao_cmd2 = 0; - ni_stc_writew(dev, devpriv->ao_cmd2, AO_Command_2_Register); + ni_stc_writew(dev, devpriv->ao_cmd2, NISTC_AO_CMD2_REG); devpriv->ao_mode1 = 0; - ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); + ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); devpriv->ao_mode2 = 0; - ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); + ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); if (devpriv->is_m_series) - devpriv->ao_mode3 = AO_Last_Gate_Disable; + devpriv->ao_mode3 = NISTC_AO_MODE3_LAST_GATE_DISABLE; else devpriv->ao_mode3 = 0; - ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); + ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG); devpriv->ao_trigger_select = 0; ni_stc_writew(dev, devpriv->ao_trigger_select, - AO_Trigger_Select_Register); + NISTC_AO_TRIG_SEL_REG); if (devpriv->is_6xxx) { unsigned immediate_bits = 0; unsigned i; for (i = 0; i < s->n_chan; ++i) immediate_bits |= 1 << i; - ni_ao_win_outw(dev, immediate_bits, AO_Immediate_671x); - ni_ao_win_outw(dev, CLEAR_WG, AO_Misc_611x); + ni_ao_win_outw(dev, immediate_bits, NI671X_AO_IMMEDIATE_REG); + ni_ao_win_outw(dev, NI611X_AO_MISC_CLEAR_WG, + NI611X_AO_MISC_REG); } - ni_stc_writew(dev, AO_Configuration_End, Joint_Reset_Register); + ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); return 0; } @@ -3392,9 +3250,9 @@ static int ni_dio_insn_config(struct comedi_device *dev, if (ret) return ret; - devpriv->dio_control &= ~DIO_Pins_Dir_Mask; - devpriv->dio_control |= DIO_Pins_Dir(s->io_bits); - ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); + devpriv->dio_control &= ~NISTC_DIO_CTRL_DIR_MASK; + devpriv->dio_control |= NISTC_DIO_CTRL_DIR(s->io_bits); + ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG); return insn->n; } @@ -3407,16 +3265,17 @@ static int ni_dio_insn_bits(struct comedi_device *dev, struct ni_private *devpriv = dev->private; /* Make sure we're not using the serial part of the dio */ - if ((data[0] & (DIO_SDIN | DIO_SDOUT)) && devpriv->serial_interval_ns) + if ((data[0] & (NISTC_DIO_SDIN | NISTC_DIO_SDOUT)) && + devpriv->serial_interval_ns) return -EBUSY; if (comedi_dio_update_state(s, data)) { - devpriv->dio_output &= ~DIO_Parallel_Data_Mask; - devpriv->dio_output |= DIO_Parallel_Data_Out(s->state); - ni_stc_writew(dev, devpriv->dio_output, DIO_Output_Register); + devpriv->dio_output &= ~NISTC_DIO_OUT_PARALLEL_MASK; + devpriv->dio_output |= NISTC_DIO_OUT_PARALLEL(s->state); + ni_stc_writew(dev, devpriv->dio_output, NISTC_DIO_OUT_REG); } - data[1] = ni_stc_readw(dev, DIO_Parallel_Input_Register); + data[1] = ni_stc_readw(dev, NISTC_DIO_IN_REG); return insn->n; } @@ -3432,7 +3291,7 @@ static int ni_m_series_dio_insn_config(struct comedi_device *dev, if (ret) return ret; - ni_writel(dev, s->io_bits, M_Offset_DIO_Direction); + ni_writel(dev, s->io_bits, NI_M_DIO_DIR_REG); return insn->n; } @@ -3443,9 +3302,9 @@ static int ni_m_series_dio_insn_bits(struct comedi_device *dev, unsigned int *data) { if (comedi_dio_update_state(s, data)) - ni_writel(dev, s->state, M_Offset_Static_Digital_Output); + ni_writel(dev, s->state, NI_M_DIO_REG); - data[1] = ni_readl(dev, M_Offset_Static_Digital_Input); + data[1] = ni_readl(dev, NI_M_DIO_REG); return insn->n; } @@ -3491,7 +3350,7 @@ static int ni_cdio_cmdtest(struct comedi_device *dev, err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); tmp = cmd->scan_begin_arg; - tmp &= CR_PACK_FLAGS(CDO_Sample_Source_Select_Mask, 0, 0, CR_INVERT); + tmp &= CR_PACK_FLAGS(NI_M_CDO_MODE_SAMPLE_SRC_MASK, 0, 0, CR_INVERT); if (tmp != cmd->scan_begin_arg) err |= -EINVAL; @@ -3550,13 +3409,14 @@ static int ni_cdo_inttrig(struct comedi_device *dev, if (retval < 0) return retval; #endif -/* -* XXX not sure what interrupt C group does -* ni_writeb(dev, Interrupt_Group_C_Enable_Bit, -* M_Offset_Interrupt_C_Enable); wait for dma to fill output fifo -*/ + /* + * XXX not sure what interrupt C group does + * wait for dma to fill output fifo + * ni_writeb(dev, NI_M_INTC_ENA, NI_M_INTC_ENA_REG); + */ for (i = 0; i < timeout; ++i) { - if (ni_readl(dev, M_Offset_CDIO_Status) & CDO_FIFO_Full_Bit) + if (ni_readl(dev, NI_M_CDIO_STATUS_REG) & + NI_M_CDIO_STATUS_CDO_FIFO_FULL) break; udelay(10); } @@ -3565,36 +3425,30 @@ static int ni_cdo_inttrig(struct comedi_device *dev, s->cancel(dev, s); return -EIO; } - ni_writel(dev, CDO_Arm_Bit | CDO_Error_Interrupt_Enable_Set_Bit | - CDO_Empty_FIFO_Interrupt_Enable_Set_Bit, - M_Offset_CDIO_Command); + ni_writel(dev, NI_M_CDO_CMD_ARM | + NI_M_CDO_CMD_ERR_INT_ENA_SET | + NI_M_CDO_CMD_F_E_INT_ENA_SET, + NI_M_CDIO_CMD_REG); return retval; } static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { const struct comedi_cmd *cmd = &s->async->cmd; - unsigned cdo_mode_bits = CDO_FIFO_Mode_Bit | CDO_Halt_On_Error_Bit; + unsigned cdo_mode_bits; int retval; - ni_writel(dev, CDO_Reset_Bit, M_Offset_CDIO_Command); - switch (cmd->scan_begin_src) { - case TRIG_EXT: - cdo_mode_bits |= - CR_CHAN(cmd->scan_begin_arg) & - CDO_Sample_Source_Select_Mask; - break; - default: - BUG(); - break; - } + ni_writel(dev, NI_M_CDO_CMD_RESET, NI_M_CDIO_CMD_REG); + cdo_mode_bits = NI_M_CDO_MODE_FIFO_MODE | + NI_M_CDO_MODE_HALT_ON_ERROR | + NI_M_CDO_MODE_SAMPLE_SRC(CR_CHAN(cmd->scan_begin_arg)); if (cmd->scan_begin_arg & CR_INVERT) - cdo_mode_bits |= CDO_Polarity_Bit; - ni_writel(dev, cdo_mode_bits, M_Offset_CDO_Mode); + cdo_mode_bits |= NI_M_CDO_MODE_POLARITY; + ni_writel(dev, cdo_mode_bits, NI_M_CDO_MODE_REG); if (s->io_bits) { - ni_writel(dev, s->state, M_Offset_CDO_FIFO_Data); - ni_writel(dev, CDO_SW_Update_Bit, M_Offset_CDIO_Command); - ni_writel(dev, s->io_bits, M_Offset_CDO_Mask_Enable); + ni_writel(dev, s->state, NI_M_CDO_FIFO_DATA_REG); + ni_writel(dev, NI_M_CDO_CMD_SW_UPDATE, NI_M_CDIO_CMD_REG); + ni_writel(dev, s->io_bits, NI_M_CDO_MASK_ENA_REG); } else { dev_err(dev->class_dev, "attempted to run digital output command with no lines configured as outputs\n"); @@ -3611,15 +3465,16 @@ static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int ni_cdio_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - ni_writel(dev, CDO_Disarm_Bit | CDO_Error_Interrupt_Enable_Clear_Bit | - CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit | - CDO_FIFO_Request_Interrupt_Enable_Clear_Bit, - M_Offset_CDIO_Command); -/* -* XXX not sure what interrupt C group does ni_writeb(dev, 0, -* M_Offset_Interrupt_C_Enable); -*/ - ni_writel(dev, 0, M_Offset_CDO_Mask_Enable); + ni_writel(dev, NI_M_CDO_CMD_DISARM | + NI_M_CDO_CMD_ERR_INT_ENA_CLR | + NI_M_CDO_CMD_F_E_INT_ENA_CLR | + NI_M_CDO_CMD_F_REQ_INT_ENA_CLR, + NI_M_CDIO_CMD_REG); + /* + * XXX not sure what interrupt C group does + * ni_writeb(dev, 0, NI_M_INTC_ENA_REG); + */ + ni_writel(dev, 0, NI_M_CDO_MASK_ENA_REG); ni_release_cdo_mite_channel(dev); return 0; } @@ -3650,16 +3505,16 @@ static void handle_cdio_interrupt(struct comedi_device *dev) spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); #endif - cdio_status = ni_readl(dev, M_Offset_CDIO_Status); - if (cdio_status & (CDO_Overrun_Bit | CDO_Underflow_Bit)) { + cdio_status = ni_readl(dev, NI_M_CDIO_STATUS_REG); + if (cdio_status & NI_M_CDIO_STATUS_CDO_ERROR) { /* XXX just guessing this is needed and does something useful */ - ni_writel(dev, CDO_Error_Interrupt_Confirm_Bit, - M_Offset_CDIO_Command); + ni_writel(dev, NI_M_CDO_CMD_ERR_INT_CONFIRM, + NI_M_CDIO_CMD_REG); s->async->events |= COMEDI_CB_OVERFLOW; } - if (cdio_status & CDO_FIFO_Empty_Bit) { - ni_writel(dev, CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit, - M_Offset_CDIO_Command); + if (cdio_status & NI_M_CDIO_STATUS_CDO_FIFO_EMPTY) { + ni_writel(dev, NI_M_CDO_CMD_F_E_INT_ENA_CLR, + NI_M_CDIO_CMD_REG); /* s->async->events |= COMEDI_CB_EOA; */ } comedi_handle_events(dev, s); @@ -3674,23 +3529,23 @@ static int ni_serial_hw_readwrite8(struct comedi_device *dev, unsigned int status1; int err = 0, count = 20; - devpriv->dio_output &= ~DIO_Serial_Data_Mask; - devpriv->dio_output |= DIO_Serial_Data_Out(data_out); - ni_stc_writew(dev, devpriv->dio_output, DIO_Output_Register); + devpriv->dio_output &= ~NISTC_DIO_OUT_SERIAL_MASK; + devpriv->dio_output |= NISTC_DIO_OUT_SERIAL(data_out); + ni_stc_writew(dev, devpriv->dio_output, NISTC_DIO_OUT_REG); - status1 = ni_stc_readw(dev, Joint_Status_1_Register); - if (status1 & DIO_Serial_IO_In_Progress_St) { + status1 = ni_stc_readw(dev, NISTC_STATUS1_REG); + if (status1 & NISTC_STATUS1_SERIO_IN_PROG) { err = -EBUSY; goto Error; } - devpriv->dio_control |= DIO_HW_Serial_Start; - ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); - devpriv->dio_control &= ~DIO_HW_Serial_Start; + devpriv->dio_control |= NISTC_DIO_CTRL_HW_SER_START; + ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG); + devpriv->dio_control &= ~NISTC_DIO_CTRL_HW_SER_START; /* Wait until STC says we're done, but don't loop infinitely. */ - while ((status1 = ni_stc_readw(dev, Joint_Status_1_Register)) & - DIO_Serial_IO_In_Progress_St) { + while ((status1 = ni_stc_readw(dev, NISTC_STATUS1_REG)) & + NISTC_STATUS1_SERIO_IN_PROG) { /* Delay one bit per loop */ udelay((devpriv->serial_interval_ns + 999) / 1000); if (--count < 0) { @@ -3701,15 +3556,17 @@ static int ni_serial_hw_readwrite8(struct comedi_device *dev, } } - /* Delay for last bit. This delay is absolutely necessary, because - DIO_Serial_IO_In_Progress_St goes high one bit too early. */ + /* + * Delay for last bit. This delay is absolutely necessary, because + * NISTC_STATUS1_SERIO_IN_PROG goes high one bit too early. + */ udelay((devpriv->serial_interval_ns + 999) / 1000); if (data_in) - *data_in = ni_stc_readw(dev, DIO_Serial_Input_Register); + *data_in = ni_stc_readw(dev, NISTC_DIO_SERIAL_IN_REG); Error: - ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); + ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG); return err; } @@ -3729,25 +3586,25 @@ static int ni_serial_sw_readwrite8(struct comedi_device *dev, /* Output current bit; note that we cannot touch s->state because it is a per-subdevice field, and serial is a separate subdevice from DIO. */ - devpriv->dio_output &= ~DIO_SDOUT; + devpriv->dio_output &= ~NISTC_DIO_SDOUT; if (data_out & mask) - devpriv->dio_output |= DIO_SDOUT; - ni_stc_writew(dev, devpriv->dio_output, DIO_Output_Register); + devpriv->dio_output |= NISTC_DIO_SDOUT; + ni_stc_writew(dev, devpriv->dio_output, NISTC_DIO_OUT_REG); /* Assert SDCLK (active low, inverted), wait for half of the delay, deassert SDCLK, and wait for the other half. */ - devpriv->dio_control |= DIO_Software_Serial_Control; - ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); + devpriv->dio_control |= NISTC_DIO_SDCLK; + ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG); udelay((devpriv->serial_interval_ns + 999) / 2000); - devpriv->dio_control &= ~DIO_Software_Serial_Control; - ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); + devpriv->dio_control &= ~NISTC_DIO_SDCLK; + ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG); udelay((devpriv->serial_interval_ns + 999) / 2000); /* Input current bit */ - if (ni_stc_readw(dev, DIO_Parallel_Input_Register) & DIO_SDIN) + if (ni_stc_readw(dev, NISTC_DIO_IN_REG) & NISTC_DIO_SDIN) input |= mask; } @@ -3763,6 +3620,7 @@ static int ni_serial_insn_config(struct comedi_device *dev, unsigned int *data) { struct ni_private *devpriv = dev->private; + unsigned clk_fout = devpriv->clock_and_fout; int err = insn->n; unsigned char byte_out, byte_in = 0; @@ -3772,49 +3630,49 @@ static int ni_serial_insn_config(struct comedi_device *dev, switch (data[0]) { case INSN_CONFIG_SERIAL_CLOCK: devpriv->serial_hw_mode = 1; - devpriv->dio_control |= DIO_HW_Serial_Enable; + devpriv->dio_control |= NISTC_DIO_CTRL_HW_SER_ENA; if (data[1] == SERIAL_DISABLED) { devpriv->serial_hw_mode = 0; - devpriv->dio_control &= ~(DIO_HW_Serial_Enable | - DIO_Software_Serial_Control); + devpriv->dio_control &= ~(NISTC_DIO_CTRL_HW_SER_ENA | + NISTC_DIO_SDCLK); data[1] = SERIAL_DISABLED; devpriv->serial_interval_ns = data[1]; } else if (data[1] <= SERIAL_600NS) { /* Warning: this clock speed is too fast to reliably control SCXI. */ - devpriv->dio_control &= ~DIO_HW_Serial_Timebase; - devpriv->clock_and_fout |= Slow_Internal_Timebase; - devpriv->clock_and_fout &= ~DIO_Serial_Out_Divide_By_2; + devpriv->dio_control &= ~NISTC_DIO_CTRL_HW_SER_TIMEBASE; + clk_fout |= NISTC_CLK_FOUT_SLOW_TIMEBASE; + clk_fout &= ~NISTC_CLK_FOUT_DIO_SER_OUT_DIV2; data[1] = SERIAL_600NS; devpriv->serial_interval_ns = data[1]; } else if (data[1] <= SERIAL_1_2US) { - devpriv->dio_control &= ~DIO_HW_Serial_Timebase; - devpriv->clock_and_fout |= Slow_Internal_Timebase | - DIO_Serial_Out_Divide_By_2; + devpriv->dio_control &= ~NISTC_DIO_CTRL_HW_SER_TIMEBASE; + clk_fout |= NISTC_CLK_FOUT_SLOW_TIMEBASE | + NISTC_CLK_FOUT_DIO_SER_OUT_DIV2; data[1] = SERIAL_1_2US; devpriv->serial_interval_ns = data[1]; } else if (data[1] <= SERIAL_10US) { - devpriv->dio_control |= DIO_HW_Serial_Timebase; - devpriv->clock_and_fout |= Slow_Internal_Timebase | - DIO_Serial_Out_Divide_By_2; - /* Note: DIO_Serial_Out_Divide_By_2 only affects + devpriv->dio_control |= NISTC_DIO_CTRL_HW_SER_TIMEBASE; + clk_fout |= NISTC_CLK_FOUT_SLOW_TIMEBASE | + NISTC_CLK_FOUT_DIO_SER_OUT_DIV2; + /* Note: NISTC_CLK_FOUT_DIO_SER_OUT_DIV2 only affects 600ns/1.2us. If you turn divide_by_2 off with the slow clock, you will still get 10us, except then all your delays are wrong. */ data[1] = SERIAL_10US; devpriv->serial_interval_ns = data[1]; } else { - devpriv->dio_control &= ~(DIO_HW_Serial_Enable | - DIO_Software_Serial_Control); + devpriv->dio_control &= ~(NISTC_DIO_CTRL_HW_SER_ENA | + NISTC_DIO_SDCLK); devpriv->serial_hw_mode = 0; data[1] = (data[1] / 1000) * 1000; devpriv->serial_interval_ns = data[1]; } + devpriv->clock_and_fout = clk_fout; - ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); - ni_stc_writew(dev, devpriv->clock_and_fout, - Clock_and_FOUT_Register); + ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG); + ni_stc_writew(dev, devpriv->clock_and_fout, NISTC_CLK_FOUT_REG); return 1; case INSN_CONFIG_BIDIRECTIONAL_DATA: @@ -3850,141 +3708,91 @@ static void init_ao_67xx(struct comedi_device *dev, struct comedi_subdevice *s) int i; for (i = 0; i < s->n_chan; i++) { - ni_ao_win_outw(dev, AO_Channel(i) | 0x0, - AO_Configuration_2_67xx); - } - ni_ao_win_outw(dev, 0x0, AO_Later_Single_Point_Updates); -} + ni_ao_win_outw(dev, NI_E_AO_DACSEL(i) | 0x0, + NI67XX_AO_CFG2_REG); + } + ni_ao_win_outw(dev, 0x0, NI67XX_AO_SP_UPDATES_REG); +} + +static const struct mio_regmap ni_gpct_to_stc_regmap[] = { + [NITIO_G0_AUTO_INC] = { NISTC_G0_AUTOINC_REG, 2 }, + [NITIO_G1_AUTO_INC] = { NISTC_G1_AUTOINC_REG, 2 }, + [NITIO_G0_CMD] = { NISTC_G0_CMD_REG, 2 }, + [NITIO_G1_CMD] = { NISTC_G1_CMD_REG, 2 }, + [NITIO_G0_HW_SAVE] = { NISTC_G0_HW_SAVE_REG, 4 }, + [NITIO_G1_HW_SAVE] = { NISTC_G1_HW_SAVE_REG, 4 }, + [NITIO_G0_SW_SAVE] = { NISTC_G0_SAVE_REG, 4 }, + [NITIO_G1_SW_SAVE] = { NISTC_G1_SAVE_REG, 4 }, + [NITIO_G0_MODE] = { NISTC_G0_MODE_REG, 2 }, + [NITIO_G1_MODE] = { NISTC_G1_MODE_REG, 2 }, + [NITIO_G0_LOADA] = { NISTC_G0_LOADA_REG, 4 }, + [NITIO_G1_LOADA] = { NISTC_G1_LOADA_REG, 4 }, + [NITIO_G0_LOADB] = { NISTC_G0_LOADB_REG, 4 }, + [NITIO_G1_LOADB] = { NISTC_G1_LOADB_REG, 4 }, + [NITIO_G0_INPUT_SEL] = { NISTC_G0_INPUT_SEL_REG, 2 }, + [NITIO_G1_INPUT_SEL] = { NISTC_G1_INPUT_SEL_REG, 2 }, + [NITIO_G0_CNT_MODE] = { 0x1b0, 2 }, /* M-Series only */ + [NITIO_G1_CNT_MODE] = { 0x1b2, 2 }, /* M-Series only */ + [NITIO_G0_GATE2] = { 0x1b4, 2 }, /* M-Series only */ + [NITIO_G1_GATE2] = { 0x1b6, 2 }, /* M-Series only */ + [NITIO_G01_STATUS] = { NISTC_G01_STATUS_REG, 2 }, + [NITIO_G01_RESET] = { NISTC_RESET_REG, 2 }, + [NITIO_G01_STATUS1] = { NISTC_STATUS1_REG, 2 }, + [NITIO_G01_STATUS2] = { NISTC_STATUS2_REG, 2 }, + [NITIO_G0_DMA_CFG] = { 0x1b8, 2 }, /* M-Series only */ + [NITIO_G1_DMA_CFG] = { 0x1ba, 2 }, /* M-Series only */ + [NITIO_G0_DMA_STATUS] = { 0x1b8, 2 }, /* M-Series only */ + [NITIO_G1_DMA_STATUS] = { 0x1ba, 2 }, /* M-Series only */ + [NITIO_G0_ABZ] = { 0x1c0, 2 }, /* M-Series only */ + [NITIO_G1_ABZ] = { 0x1c2, 2 }, /* M-Series only */ + [NITIO_G0_INT_ACK] = { NISTC_INTA_ACK_REG, 2 }, + [NITIO_G1_INT_ACK] = { NISTC_INTB_ACK_REG, 2 }, + [NITIO_G0_STATUS] = { NISTC_AI_STATUS1_REG, 2 }, + [NITIO_G1_STATUS] = { NISTC_AO_STATUS1_REG, 2 }, + [NITIO_G0_INT_ENA] = { NISTC_INTA_ENA_REG, 2 }, + [NITIO_G1_INT_ENA] = { NISTC_INTB_ENA_REG, 2 }, +}; -static unsigned ni_gpct_to_stc_register(enum ni_gpct_register reg) +static unsigned int ni_gpct_to_stc_register(struct comedi_device *dev, + enum ni_gpct_register reg) { - unsigned stc_register; + const struct mio_regmap *regmap; - switch (reg) { - case NITIO_G0_AUTO_INC: - stc_register = G_Autoincrement_Register(0); - break; - case NITIO_G1_AUTO_INC: - stc_register = G_Autoincrement_Register(1); - break; - case NITIO_G0_CMD: - stc_register = G_Command_Register(0); - break; - case NITIO_G1_CMD: - stc_register = G_Command_Register(1); - break; - case NITIO_G0_HW_SAVE: - stc_register = G_HW_Save_Register(0); - break; - case NITIO_G1_HW_SAVE: - stc_register = G_HW_Save_Register(1); - break; - case NITIO_G0_SW_SAVE: - stc_register = G_Save_Register(0); - break; - case NITIO_G1_SW_SAVE: - stc_register = G_Save_Register(1); - break; - case NITIO_G0_MODE: - stc_register = G_Mode_Register(0); - break; - case NITIO_G1_MODE: - stc_register = G_Mode_Register(1); - break; - case NITIO_G0_LOADA: - stc_register = G_Load_A_Register(0); - break; - case NITIO_G1_LOADA: - stc_register = G_Load_A_Register(1); - break; - case NITIO_G0_LOADB: - stc_register = G_Load_B_Register(0); - break; - case NITIO_G1_LOADB: - stc_register = G_Load_B_Register(1); - break; - case NITIO_G0_INPUT_SEL: - stc_register = G_Input_Select_Register(0); - break; - case NITIO_G1_INPUT_SEL: - stc_register = G_Input_Select_Register(1); - break; - case NITIO_G01_STATUS: - stc_register = G_Status_Register; - break; - case NITIO_G01_RESET: - stc_register = Joint_Reset_Register; - break; - case NITIO_G01_STATUS1: - stc_register = Joint_Status_1_Register; - break; - case NITIO_G01_STATUS2: - stc_register = Joint_Status_2_Register; - break; - case NITIO_G0_INT_ACK: - stc_register = Interrupt_A_Ack_Register; - break; - case NITIO_G1_INT_ACK: - stc_register = Interrupt_B_Ack_Register; - break; - case NITIO_G0_STATUS: - stc_register = AI_Status_1_Register; - break; - case NITIO_G1_STATUS: - stc_register = AO_Status_1_Register; - break; - case NITIO_G0_INT_ENA: - stc_register = Interrupt_A_Enable_Register; - break; - case NITIO_G1_INT_ENA: - stc_register = Interrupt_B_Enable_Register; - break; - default: - pr_err("%s: unhandled register 0x%x in switch.\n", - __func__, reg); - BUG(); + if (reg < ARRAY_SIZE(ni_gpct_to_stc_regmap)) { + regmap = &ni_gpct_to_stc_regmap[reg]; + } else { + dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n", + __func__, reg); return 0; } - return stc_register; + + return regmap->mio_reg; } static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits, enum ni_gpct_register reg) { struct comedi_device *dev = counter->counter_dev->dev; - unsigned stc_register; - /* bits in the join reset register which are relevant to counters */ - static const unsigned gpct_joint_reset_mask = G0_Reset | G1_Reset; + unsigned int stc_register = ni_gpct_to_stc_register(dev, reg); static const unsigned gpct_interrupt_a_enable_mask = - G0_Gate_Interrupt_Enable | G0_TC_Interrupt_Enable; + NISTC_INTA_ENA_G0_GATE | NISTC_INTA_ENA_G0_TC; static const unsigned gpct_interrupt_b_enable_mask = - G1_Gate_Interrupt_Enable | G1_TC_Interrupt_Enable; + NISTC_INTB_ENA_G1_GATE | NISTC_INTB_ENA_G1_TC; + + if (stc_register == 0) + return; switch (reg) { - /* m-series-only registers */ + /* m-series only registers */ case NITIO_G0_CNT_MODE: - ni_writew(dev, bits, M_Offset_G0_Counting_Mode); - break; case NITIO_G1_CNT_MODE: - ni_writew(dev, bits, M_Offset_G1_Counting_Mode); - break; case NITIO_G0_GATE2: - ni_writew(dev, bits, M_Offset_G0_Second_Gate); - break; case NITIO_G1_GATE2: - ni_writew(dev, bits, M_Offset_G1_Second_Gate); - break; case NITIO_G0_DMA_CFG: - ni_writew(dev, bits, M_Offset_G0_DMA_Config); - break; case NITIO_G1_DMA_CFG: - ni_writew(dev, bits, M_Offset_G1_DMA_Config); - break; case NITIO_G0_ABZ: - ni_writew(dev, bits, M_Offset_G0_MSeries_ABZ); - break; case NITIO_G1_ABZ: - ni_writew(dev, bits, M_Offset_G1_MSeries_ABZ); + ni_writew(dev, bits, stc_register); break; /* 32 bit registers */ @@ -3992,26 +3800,24 @@ static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits, case NITIO_G1_LOADA: case NITIO_G0_LOADB: case NITIO_G1_LOADB: - stc_register = ni_gpct_to_stc_register(reg); ni_stc_writel(dev, bits, stc_register); break; /* 16 bit registers */ case NITIO_G0_INT_ENA: BUG_ON(bits & ~gpct_interrupt_a_enable_mask); - ni_set_bitfield(dev, Interrupt_A_Enable_Register, + ni_set_bitfield(dev, stc_register, gpct_interrupt_a_enable_mask, bits); break; case NITIO_G1_INT_ENA: BUG_ON(bits & ~gpct_interrupt_b_enable_mask); - ni_set_bitfield(dev, Interrupt_B_Enable_Register, + ni_set_bitfield(dev, stc_register, gpct_interrupt_b_enable_mask, bits); break; case NITIO_G01_RESET: - BUG_ON(bits & ~gpct_joint_reset_mask); + BUG_ON(bits & ~(NISTC_RESET_G0 | NISTC_RESET_G1)); /* fall-through */ default: - stc_register = ni_gpct_to_stc_register(reg); ni_stc_writew(dev, bits, stc_register); } } @@ -4020,29 +3826,28 @@ static unsigned ni_gpct_read_register(struct ni_gpct *counter, enum ni_gpct_register reg) { struct comedi_device *dev = counter->counter_dev->dev; - unsigned stc_register; + unsigned int stc_register = ni_gpct_to_stc_register(dev, reg); + + if (stc_register == 0) + return 0; switch (reg) { /* m-series only registers */ case NITIO_G0_DMA_STATUS: - return ni_readw(dev, M_Offset_G0_DMA_Status); case NITIO_G1_DMA_STATUS: - return ni_readw(dev, M_Offset_G1_DMA_Status); + return ni_readw(dev, stc_register); /* 32 bit registers */ case NITIO_G0_HW_SAVE: case NITIO_G1_HW_SAVE: case NITIO_G0_SW_SAVE: case NITIO_G1_SW_SAVE: - stc_register = ni_gpct_to_stc_register(reg); return ni_stc_readl(dev, stc_register); /* 16 bit registers */ default: - stc_register = ni_gpct_to_stc_register(reg); return ni_stc_readw(dev, stc_register); } - return 0; } static int ni_freq_out_insn_read(struct comedi_device *dev, @@ -4051,7 +3856,7 @@ static int ni_freq_out_insn_read(struct comedi_device *dev, unsigned int *data) { struct ni_private *devpriv = dev->private; - unsigned int val = devpriv->clock_and_fout & FOUT_Divider_mask; + unsigned int val = NISTC_CLK_FOUT_TO_DIVIDER(devpriv->clock_and_fout); int i; for (i = 0; i < insn->n; i++) @@ -4068,17 +3873,17 @@ static int ni_freq_out_insn_write(struct comedi_device *dev, struct ni_private *devpriv = dev->private; if (insn->n) { - devpriv->clock_and_fout &= ~FOUT_Enable; - ni_stc_writew(dev, devpriv->clock_and_fout, - Clock_and_FOUT_Register); - devpriv->clock_and_fout &= ~FOUT_Divider_mask; + unsigned int val = data[insn->n - 1]; + + devpriv->clock_and_fout &= ~NISTC_CLK_FOUT_ENA; + ni_stc_writew(dev, devpriv->clock_and_fout, NISTC_CLK_FOUT_REG); + devpriv->clock_and_fout &= ~NISTC_CLK_FOUT_DIVIDER_MASK; /* use the last data value to set the fout divider */ - devpriv->clock_and_fout |= FOUT_Divider(data[insn->n - 1]); + devpriv->clock_and_fout |= NISTC_CLK_FOUT_DIVIDER(val); - devpriv->clock_and_fout |= FOUT_Enable; - ni_stc_writew(dev, devpriv->clock_and_fout, - Clock_and_FOUT_Register); + devpriv->clock_and_fout |= NISTC_CLK_FOUT_ENA; + ni_stc_writew(dev, devpriv->clock_and_fout, NISTC_CLK_FOUT_REG); } return insn->n; } @@ -4094,19 +3899,18 @@ static int ni_freq_out_insn_config(struct comedi_device *dev, case INSN_CONFIG_SET_CLOCK_SRC: switch (data[1]) { case NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC: - devpriv->clock_and_fout &= ~FOUT_Timebase_Select; + devpriv->clock_and_fout &= ~NISTC_CLK_FOUT_TIMEBASE_SEL; break; case NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC: - devpriv->clock_and_fout |= FOUT_Timebase_Select; + devpriv->clock_and_fout |= NISTC_CLK_FOUT_TIMEBASE_SEL; break; default: return -EINVAL; } - ni_stc_writew(dev, devpriv->clock_and_fout, - Clock_and_FOUT_Register); + ni_stc_writew(dev, devpriv->clock_and_fout, NISTC_CLK_FOUT_REG); break; case INSN_CONFIG_GET_CLOCK_SRC: - if (devpriv->clock_and_fout & FOUT_Timebase_Select) { + if (devpriv->clock_and_fout & NISTC_CLK_FOUT_TIMEBASE_SEL) { data[1] = NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC; data[2] = TIMEBASE_2_NS; } else { @@ -4190,9 +3994,9 @@ static int ni_m_series_pwm_config(struct comedi_device *dev, data[4] = down_count * devpriv->clock_ns; return -EAGAIN; } - ni_writel(dev, MSeries_Cal_PWM_High_Time_Bits(up_count) | - MSeries_Cal_PWM_Low_Time_Bits(down_count), - M_Offset_Cal_PWM); + ni_writel(dev, NI_M_CAL_PWM_HIGH_TIME(up_count) | + NI_M_CAL_PWM_LOW_TIME(down_count), + NI_M_CAL_PWM_REG); devpriv->pwm_up_count = up_count; devpriv->pwm_down_count = down_count; return 5; @@ -4254,9 +4058,9 @@ static int ni_6143_pwm_config(struct comedi_device *dev, data[4] = down_count * devpriv->clock_ns; return -EAGAIN; } - ni_writel(dev, up_count, Calibration_HighTime_6143); + ni_writel(dev, up_count, NI6143_CALIB_HI_TIME_REG); devpriv->pwm_up_count = up_count; - ni_writel(dev, down_count, Calibration_LowTime_6143); + ni_writel(dev, down_count, NI6143_CALIB_LO_TIME_REG); devpriv->pwm_down_count = down_count; return 5; case INSN_CONFIG_GET_PWM_OUTPUT: @@ -4336,6 +4140,7 @@ static void ni_write_caldac(struct comedi_device *dev, int addr, int val) const struct ni_board_struct *board = dev->board_ptr; struct ni_private *devpriv = dev->private; unsigned int loadbit = 0, bits = 0, bit, bitstring = 0; + unsigned int cmd; int i; int type; @@ -4349,22 +4154,26 @@ static void ni_write_caldac(struct comedi_device *dev, int addr, int val) break; if (addr < caldacs[type].n_chans) { bits = caldacs[type].packbits(addr, val, &bitstring); - loadbit = SerDacLd(i); + loadbit = NI_E_SERIAL_CMD_DAC_LD(i); break; } addr -= caldacs[type].n_chans; } + /* bits will be 0 if there is no caldac for the given addr */ + if (bits == 0) + return; + for (bit = 1 << (bits - 1); bit; bit >>= 1) { - ni_writeb(dev, ((bit & bitstring) ? 0x02 : 0), Serial_Command); + cmd = (bit & bitstring) ? NI_E_SERIAL_CMD_SDATA : 0; + ni_writeb(dev, cmd, NI_E_SERIAL_CMD_REG); udelay(1); - ni_writeb(dev, 1 | ((bit & bitstring) ? 0x02 : 0), - Serial_Command); + ni_writeb(dev, NI_E_SERIAL_CMD_SCLK | cmd, NI_E_SERIAL_CMD_REG); udelay(1); } - ni_writeb(dev, loadbit, Serial_Command); + ni_writeb(dev, loadbit, NI_E_SERIAL_CMD_REG); udelay(1); - ni_writeb(dev, 0, Serial_Command); + ni_writeb(dev, 0, NI_E_SERIAL_CMD_REG); } static int ni_calib_insn_write(struct comedi_device *dev, @@ -4446,24 +4255,30 @@ static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s) static int ni_read_eeprom(struct comedi_device *dev, int addr) { + unsigned int cmd = NI_E_SERIAL_CMD_EEPROM_CS; int bit; int bitstring; bitstring = 0x0300 | ((addr & 0x100) << 3) | (addr & 0xff); - ni_writeb(dev, 0x04, Serial_Command); + ni_writeb(dev, cmd, NI_E_SERIAL_CMD_REG); for (bit = 0x8000; bit; bit >>= 1) { - ni_writeb(dev, 0x04 | ((bit & bitstring) ? 0x02 : 0), - Serial_Command); - ni_writeb(dev, 0x05 | ((bit & bitstring) ? 0x02 : 0), - Serial_Command); + if (bit & bitstring) + cmd |= NI_E_SERIAL_CMD_SDATA; + else + cmd &= ~NI_E_SERIAL_CMD_SDATA; + + ni_writeb(dev, cmd, NI_E_SERIAL_CMD_REG); + ni_writeb(dev, NI_E_SERIAL_CMD_SCLK | cmd, NI_E_SERIAL_CMD_REG); } + cmd = NI_E_SERIAL_CMD_EEPROM_CS; bitstring = 0; for (bit = 0x80; bit; bit >>= 1) { - ni_writeb(dev, 0x04, Serial_Command); - ni_writeb(dev, 0x05, Serial_Command); - bitstring |= ((ni_readb(dev, XXX_Status) & PROMOUT) ? bit : 0); + ni_writeb(dev, cmd, NI_E_SERIAL_CMD_REG); + ni_writeb(dev, NI_E_SERIAL_CMD_SCLK | cmd, NI_E_SERIAL_CMD_REG); + if (ni_readb(dev, NI_E_STATUS_REG) & NI_E_STATUS_PROMOUT) + bitstring |= bit; } - ni_writeb(dev, 0x00, Serial_Command); + ni_writeb(dev, 0, NI_E_SERIAL_CMD_REG); return bitstring; } @@ -4537,7 +4352,7 @@ static unsigned ni_m_series_get_pfi_routing(struct comedi_device *dev, struct ni_private *devpriv = dev->private; const unsigned array_offset = chan / 3; - return MSeries_PFI_Output_Select_Source(chan, + return NI_M_PFI_OUT_SEL_TO_SRC(chan, devpriv->pfi_output_select_reg[array_offset]); } @@ -4545,19 +4360,17 @@ static int ni_m_series_set_pfi_routing(struct comedi_device *dev, unsigned chan, unsigned source) { struct ni_private *devpriv = dev->private; - unsigned pfi_reg_index; - unsigned array_offset; + unsigned index = chan / 3; + unsigned short val = devpriv->pfi_output_select_reg[index]; if ((source & 0x1f) != source) return -EINVAL; - pfi_reg_index = 1 + chan / 3; - array_offset = pfi_reg_index - 1; - devpriv->pfi_output_select_reg[array_offset] &= - ~MSeries_PFI_Output_Select_Mask(chan); - devpriv->pfi_output_select_reg[array_offset] |= - MSeries_PFI_Output_Select_Bits(chan, source); - ni_writew(dev, devpriv->pfi_output_select_reg[array_offset], - M_Offset_PFI_Output_Select(pfi_reg_index)); + + val &= ~NI_M_PFI_OUT_SEL_MASK(chan); + val |= NI_M_PFI_OUT_SEL(chan, source); + ni_writew(dev, val, NI_M_PFI_OUT_SEL_REG(index)); + devpriv->pfi_output_select_reg[index] = val; + return 2; } @@ -4590,10 +4403,10 @@ static int ni_config_filter(struct comedi_device *dev, if (!devpriv->is_m_series) return -ENOTSUPP; - bits = ni_readl(dev, M_Offset_PFI_Filter); - bits &= ~MSeries_PFI_Filter_Select_Mask(pfi_channel); - bits |= MSeries_PFI_Filter_Select_Bits(pfi_channel, filter); - ni_writel(dev, bits, M_Offset_PFI_Filter); + bits = ni_readl(dev, NI_M_PFI_FILTER_REG); + bits &= ~NI_M_PFI_FILTER_SEL_MASK(pfi_channel); + bits |= NI_M_PFI_FILTER_SEL(pfi_channel, filter); + ni_writel(dev, bits, NI_M_PFI_FILTER_REG); return 0; } @@ -4612,10 +4425,10 @@ static int ni_pfi_insn_config(struct comedi_device *dev, switch (data[0]) { case COMEDI_OUTPUT: - ni_set_bits(dev, IO_Bidirection_Pin_Register, 1 << chan, 1); + ni_set_bits(dev, NISTC_IO_BIDIR_PIN_REG, 1 << chan, 1); break; case COMEDI_INPUT: - ni_set_bits(dev, IO_Bidirection_Pin_Register, 1 << chan, 0); + ni_set_bits(dev, NISTC_IO_BIDIR_PIN_REG, 1 << chan, 0); break; case INSN_CONFIG_DIO_QUERY: data[1] = @@ -4646,9 +4459,9 @@ static int ni_pfi_insn_bits(struct comedi_device *dev, return -ENOTSUPP; if (comedi_dio_update_state(s, data)) - ni_writew(dev, s->state, M_Offset_PFI_DO); + ni_writew(dev, s->state, NI_M_PFI_DO_REG); - data[1] = ni_readw(dev, M_Offset_PFI_DI); + data[1] = ni_readw(dev, NI_M_PFI_DI_REG); return insn->n; } @@ -4660,8 +4473,8 @@ static int cs5529_wait_for_idle(struct comedi_device *dev) int i; for (i = 0; i < timeout; i++) { - status = ni_ao_win_inw(dev, CAL_ADC_Status_67xx); - if ((status & CSS_ADC_BUSY) == 0) + status = ni_ao_win_inw(dev, NI67XX_CAL_STATUS_REG); + if ((status & NI67XX_CAL_STATUS_BUSY) == 0) break; set_current_state(TASK_INTERRUPTIBLE); if (schedule_timeout(1)) @@ -4679,13 +4492,14 @@ static void cs5529_command(struct comedi_device *dev, unsigned short value) static const int timeout = 100; int i; - ni_ao_win_outw(dev, value, CAL_ADC_Command_67xx); + ni_ao_win_outw(dev, value, NI67XX_CAL_CMD_REG); /* give time for command to start being serially clocked into cs5529. - * this insures that the CSS_ADC_BUSY bit will get properly + * this insures that the NI67XX_CAL_STATUS_BUSY bit will get properly * set before we exit this function. */ for (i = 0; i < timeout; i++) { - if ((ni_ao_win_inw(dev, CAL_ADC_Status_67xx) & CSS_ADC_BUSY)) + if (ni_ao_win_inw(dev, NI67XX_CAL_STATUS_REG) & + NI67XX_CAL_STATUS_BUSY) break; udelay(1); } @@ -4700,25 +4514,25 @@ static int cs5529_do_conversion(struct comedi_device *dev, int retval; unsigned short status; - cs5529_command(dev, CSCMD_COMMAND | CSCMD_SINGLE_CONVERSION); + cs5529_command(dev, CS5529_CMD_CB | CS5529_CMD_SINGLE_CONV); retval = cs5529_wait_for_idle(dev); if (retval) { dev_err(dev->class_dev, "timeout or signal in cs5529_do_conversion()\n"); return -ETIME; } - status = ni_ao_win_inw(dev, CAL_ADC_Status_67xx); - if (status & CSS_OSC_DETECT) { + status = ni_ao_win_inw(dev, NI67XX_CAL_STATUS_REG); + if (status & NI67XX_CAL_STATUS_OSC_DETECT) { dev_err(dev->class_dev, "cs5529 conversion error, status CSS_OSC_DETECT\n"); return -EIO; } - if (status & CSS_OVERRANGE) { + if (status & NI67XX_CAL_STATUS_OVERRANGE) { dev_err(dev->class_dev, "cs5529 conversion error, overrange (ignoring)\n"); } if (data) { - *data = ni_ao_win_inw(dev, CAL_ADC_Data_67xx); + *data = ni_ao_win_inw(dev, NI67XX_CAL_DATA_REG); /* cs5529 returns 16 bit signed data in bipolar mode */ *data ^= (1 << 15); } @@ -4742,7 +4556,7 @@ static int cs5529_ai_insn_read(struct comedi_device *dev, channel_select = INTERNAL_REF; else channel_select = CR_CHAN(insn->chanspec); - ni_ao_win_outw(dev, channel_select, AO_Calibration_Channel_Select_67xx); + ni_ao_win_outw(dev, channel_select, NI67XX_AO_CAL_CHAN_SEL_REG); for (n = 0; n < insn->n; n++) { retval = cs5529_do_conversion(dev, &sample); @@ -4756,12 +4570,10 @@ static int cs5529_ai_insn_read(struct comedi_device *dev, static void cs5529_config_write(struct comedi_device *dev, unsigned int value, unsigned int reg_select_bits) { - ni_ao_win_outw(dev, ((value >> 16) & 0xff), - CAL_ADC_Config_Data_High_Word_67xx); - ni_ao_win_outw(dev, (value & 0xffff), - CAL_ADC_Config_Data_Low_Word_67xx); - reg_select_bits &= CSCMD_REGISTER_SELECT_MASK; - cs5529_command(dev, CSCMD_COMMAND | reg_select_bits); + ni_ao_win_outw(dev, (value >> 16) & 0xff, NI67XX_CAL_CFG_HI_REG); + ni_ao_win_outw(dev, value & 0xffff, NI67XX_CAL_CFG_LO_REG); + reg_select_bits &= CS5529_CMD_REG_MASK; + cs5529_command(dev, CS5529_CMD_CB | reg_select_bits); if (cs5529_wait_for_idle(dev)) dev_err(dev->class_dev, "timeout or signal in %s\n", __func__); @@ -4769,20 +4581,20 @@ static void cs5529_config_write(struct comedi_device *dev, unsigned int value, static int init_cs5529(struct comedi_device *dev) { - unsigned int config_bits = - CSCFG_PORT_MODE | CSCFG_WORD_RATE_2180_CYCLES; + unsigned int config_bits = CS5529_CFG_PORT_FLAG | + CS5529_CFG_WORD_RATE_2180; #if 1 /* do self-calibration */ - cs5529_config_write(dev, config_bits | CSCFG_SELF_CAL_OFFSET_GAIN, - CSCMD_CONFIG_REGISTER); + cs5529_config_write(dev, config_bits | CS5529_CFG_CALIB_BOTH_SELF, + CS5529_CFG_REG); /* need to force a conversion for calibration to run */ cs5529_do_conversion(dev, NULL); #else /* force gain calibration to 1 */ - cs5529_config_write(dev, 0x400000, CSCMD_GAIN_REGISTER); - cs5529_config_write(dev, config_bits | CSCFG_SELF_CAL_OFFSET, - CSCMD_CONFIG_REGISTER); + cs5529_config_write(dev, 0x400000, CS5529_GAIN_REG); + cs5529_config_write(dev, config_bits | CS5529_CFG_CALIB_OFFSET_SELF, + CS5529_CFG_REG); if (cs5529_wait_for_idle(dev)) dev_err(dev->class_dev, "timeout or signal in %s\n", __func__); @@ -4801,10 +4613,8 @@ static int ni_mseries_get_pll_parameters(unsigned reference_period_ns, { unsigned div; unsigned best_div = 1; - static const unsigned max_div = 0x10; unsigned mult; unsigned best_mult = 1; - static const unsigned max_mult = 0x100; static const unsigned pico_per_nano = 1000; const unsigned reference_picosec = reference_period_ns * pico_per_nano; @@ -4814,8 +4624,8 @@ static int ni_mseries_get_pll_parameters(unsigned reference_period_ns, static const unsigned fudge_factor_80_to_20Mhz = 4; int best_period_picosec = 0; - for (div = 1; div <= max_div; ++div) { - for (mult = 1; mult <= max_mult; ++mult) { + for (div = 1; div <= NI_M_PLL_MAX_DIVISOR; ++div) { + for (mult = 1; mult <= NI_M_PLL_MAX_MULTIPLIER; ++mult) { unsigned new_period_ps = (reference_picosec * div) / mult; if (abs(new_period_ps - target_picosec) < @@ -4847,6 +4657,7 @@ static int ni_mseries_set_pll_master_clock(struct comedi_device *dev, unsigned pll_control_bits; unsigned freq_divider; unsigned freq_multiplier; + unsigned rtsi; unsigned i; int retval; @@ -4859,42 +4670,31 @@ static int ni_mseries_set_pll_master_clock(struct comedi_device *dev, __func__, min_period_ns, max_period_ns); return -EINVAL; } - devpriv->rtsi_trig_direction_reg &= ~Use_RTSI_Clock_Bit; + devpriv->rtsi_trig_direction_reg &= ~NISTC_RTSI_TRIG_USE_CLK; ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg, - RTSI_Trig_Direction_Register); - pll_control_bits = - MSeries_PLL_Enable_Bit | MSeries_PLL_VCO_Mode_75_150MHz_Bits; - devpriv->clock_and_fout2 |= - MSeries_Timebase1_Select_Bit | MSeries_Timebase3_Select_Bit; - devpriv->clock_and_fout2 &= ~MSeries_PLL_In_Source_Select_Mask; + NISTC_RTSI_TRIG_DIR_REG); + pll_control_bits = NI_M_PLL_CTRL_ENA | NI_M_PLL_CTRL_VCO_MODE_75_150MHZ; + devpriv->clock_and_fout2 |= NI_M_CLK_FOUT2_TIMEBASE1_PLL | + NI_M_CLK_FOUT2_TIMEBASE3_PLL; + devpriv->clock_and_fout2 &= ~NI_M_CLK_FOUT2_PLL_SRC_MASK; switch (source) { case NI_MIO_PLL_PXI_STAR_TRIGGER_CLOCK: - devpriv->clock_and_fout2 |= - MSeries_PLL_In_Source_Select_Star_Trigger_Bits; + devpriv->clock_and_fout2 |= NI_M_CLK_FOUT2_PLL_SRC_STAR; break; case NI_MIO_PLL_PXI10_CLOCK: /* pxi clock is 10MHz */ - devpriv->clock_and_fout2 |= - MSeries_PLL_In_Source_Select_PXI_Clock10; + devpriv->clock_and_fout2 |= NI_M_CLK_FOUT2_PLL_SRC_PXI10; break; default: - { - unsigned rtsi_channel; - static const unsigned max_rtsi_channel = 7; - - for (rtsi_channel = 0; rtsi_channel <= max_rtsi_channel; - ++rtsi_channel) { - if (source == - NI_MIO_PLL_RTSI_CLOCK(rtsi_channel)) { - devpriv->clock_and_fout2 |= - MSeries_PLL_In_Source_Select_RTSI_Bits - (rtsi_channel); - break; - } + for (rtsi = 0; rtsi <= NI_M_MAX_RTSI_CHAN; ++rtsi) { + if (source == NI_MIO_PLL_RTSI_CLOCK(rtsi)) { + devpriv->clock_and_fout2 |= + NI_M_CLK_FOUT2_PLL_SRC_RTSI(rtsi); + break; } - if (rtsi_channel > max_rtsi_channel) - return -EINVAL; } + if (rtsi > NI_M_MAX_RTSI_CHAN) + return -EINVAL; break; } retval = ni_mseries_get_pll_parameters(period_ns, @@ -4907,16 +4707,15 @@ static int ni_mseries_set_pll_master_clock(struct comedi_device *dev, return retval; } - ni_writew(dev, devpriv->clock_and_fout2, M_Offset_Clock_and_Fout2); - pll_control_bits |= - MSeries_PLL_Divisor_Bits(freq_divider) | - MSeries_PLL_Multiplier_Bits(freq_multiplier); + ni_writew(dev, devpriv->clock_and_fout2, NI_M_CLK_FOUT2_REG); + pll_control_bits |= NI_M_PLL_CTRL_DIVISOR(freq_divider) | + NI_M_PLL_CTRL_MULTIPLIER(freq_multiplier); - ni_writew(dev, pll_control_bits, M_Offset_PLL_Control); + ni_writew(dev, pll_control_bits, NI_M_PLL_CTRL_REG); devpriv->clock_source = source; /* it seems to typically take a few hundred microseconds for PLL to lock */ for (i = 0; i < timeout; ++i) { - if (ni_readw(dev, M_Offset_PLL_Status) & MSeries_PLL_Locked_Bit) + if (ni_readw(dev, NI_M_PLL_STATUS_REG) & NI_M_PLL_STATUS_LOCKED) break; udelay(1); } @@ -4935,17 +4734,17 @@ static int ni_set_master_clock(struct comedi_device *dev, struct ni_private *devpriv = dev->private; if (source == NI_MIO_INTERNAL_CLOCK) { - devpriv->rtsi_trig_direction_reg &= ~Use_RTSI_Clock_Bit; + devpriv->rtsi_trig_direction_reg &= ~NISTC_RTSI_TRIG_USE_CLK; ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg, - RTSI_Trig_Direction_Register); + NISTC_RTSI_TRIG_DIR_REG); devpriv->clock_ns = TIMEBASE_1_NS; if (devpriv->is_m_series) { devpriv->clock_and_fout2 &= - ~(MSeries_Timebase1_Select_Bit | - MSeries_Timebase3_Select_Bit); + ~(NI_M_CLK_FOUT2_TIMEBASE1_PLL | + NI_M_CLK_FOUT2_TIMEBASE3_PLL); ni_writew(dev, devpriv->clock_and_fout2, - M_Offset_Clock_and_Fout2); - ni_writew(dev, 0, M_Offset_PLL_Control); + NI_M_CLK_FOUT2_REG); + ni_writew(dev, 0, NI_M_PLL_CTRL_REG); } devpriv->clock_source = source; } else { @@ -4955,10 +4754,10 @@ static int ni_set_master_clock(struct comedi_device *dev, } else { if (source == NI_MIO_RTSI_CLOCK) { devpriv->rtsi_trig_direction_reg |= - Use_RTSI_Clock_Bit; + NISTC_RTSI_TRIG_USE_CLK; ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg, - RTSI_Trig_Direction_Register); + NISTC_RTSI_TRIG_DIR_REG); if (period_ns == 0) { dev_err(dev->class_dev, "we don't handle an unspecified clock period correctly yet, returning error\n"); @@ -4974,26 +4773,19 @@ static int ni_set_master_clock(struct comedi_device *dev, return 3; } -static unsigned num_configurable_rtsi_channels(struct comedi_device *dev) -{ - struct ni_private *devpriv = dev->private; - - return (devpriv->is_m_series) ? 8 : 7; -} - static int ni_valid_rtsi_output_source(struct comedi_device *dev, unsigned chan, unsigned source) { struct ni_private *devpriv = dev->private; - if (chan >= num_configurable_rtsi_channels(dev)) { - if (chan == old_RTSI_clock_channel) { + if (chan >= NISTC_RTSI_TRIG_NUM_CHAN(devpriv->is_m_series)) { + if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN) { if (source == NI_RTSI_OUTPUT_RTSI_OSC) return 1; dev_err(dev->class_dev, "%s: invalid source for channel=%i, channel %i is always the RTSI clock for pre-m-series boards\n", - __func__, chan, old_RTSI_clock_channel); + __func__, chan, NISTC_RTSI_TRIG_OLD_CLK_CHAN); return 0; } return 0; @@ -5017,24 +4809,22 @@ static int ni_valid_rtsi_output_source(struct comedi_device *dev, } static int ni_set_rtsi_routing(struct comedi_device *dev, - unsigned chan, unsigned source) + unsigned chan, unsigned src) { struct ni_private *devpriv = dev->private; - if (ni_valid_rtsi_output_source(dev, chan, source) == 0) + if (ni_valid_rtsi_output_source(dev, chan, src) == 0) return -EINVAL; if (chan < 4) { - devpriv->rtsi_trig_a_output_reg &= ~RTSI_Trig_Output_Mask(chan); - devpriv->rtsi_trig_a_output_reg |= - RTSI_Trig_Output_Bits(chan, source); + devpriv->rtsi_trig_a_output_reg &= ~NISTC_RTSI_TRIG_MASK(chan); + devpriv->rtsi_trig_a_output_reg |= NISTC_RTSI_TRIG(chan, src); ni_stc_writew(dev, devpriv->rtsi_trig_a_output_reg, - RTSI_Trig_A_Output_Register); + NISTC_RTSI_TRIGA_OUT_REG); } else if (chan < 8) { - devpriv->rtsi_trig_b_output_reg &= ~RTSI_Trig_Output_Mask(chan); - devpriv->rtsi_trig_b_output_reg |= - RTSI_Trig_Output_Bits(chan, source); + devpriv->rtsi_trig_b_output_reg &= ~NISTC_RTSI_TRIG_MASK(chan); + devpriv->rtsi_trig_b_output_reg |= NISTC_RTSI_TRIG(chan, src); ni_stc_writew(dev, devpriv->rtsi_trig_b_output_reg, - RTSI_Trig_B_Output_Register); + NISTC_RTSI_TRIGB_OUT_REG); } return 2; } @@ -5044,13 +4834,13 @@ static unsigned ni_get_rtsi_routing(struct comedi_device *dev, unsigned chan) struct ni_private *devpriv = dev->private; if (chan < 4) { - return RTSI_Trig_Output_Source(chan, - devpriv->rtsi_trig_a_output_reg); - } else if (chan < num_configurable_rtsi_channels(dev)) { - return RTSI_Trig_Output_Source(chan, - devpriv->rtsi_trig_b_output_reg); + return NISTC_RTSI_TRIG_TO_SRC(chan, + devpriv->rtsi_trig_a_output_reg); + } else if (chan < NISTC_RTSI_TRIG_NUM_CHAN(devpriv->is_m_series)) { + return NISTC_RTSI_TRIG_TO_SRC(chan, + devpriv->rtsi_trig_b_output_reg); } else { - if (chan == old_RTSI_clock_channel) + if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN) return NI_RTSI_OUTPUT_RTSI_OSC; dev_err(dev->class_dev, "bug! should never get here?\n"); return 0; @@ -5064,42 +4854,43 @@ static int ni_rtsi_insn_config(struct comedi_device *dev, { struct ni_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int max_chan = NISTC_RTSI_TRIG_NUM_CHAN(devpriv->is_m_series); switch (data[0]) { case INSN_CONFIG_DIO_OUTPUT: - if (chan < num_configurable_rtsi_channels(dev)) { + if (chan < max_chan) { devpriv->rtsi_trig_direction_reg |= - RTSI_Output_Bit(chan, devpriv->is_m_series); - } else if (chan == old_RTSI_clock_channel) { + NISTC_RTSI_TRIG_DIR(chan, devpriv->is_m_series); + } else if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN) { devpriv->rtsi_trig_direction_reg |= - Drive_RTSI_Clock_Bit; + NISTC_RTSI_TRIG_DRV_CLK; } ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg, - RTSI_Trig_Direction_Register); + NISTC_RTSI_TRIG_DIR_REG); break; case INSN_CONFIG_DIO_INPUT: - if (chan < num_configurable_rtsi_channels(dev)) { + if (chan < max_chan) { devpriv->rtsi_trig_direction_reg &= - ~RTSI_Output_Bit(chan, devpriv->is_m_series); - } else if (chan == old_RTSI_clock_channel) { + ~NISTC_RTSI_TRIG_DIR(chan, devpriv->is_m_series); + } else if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN) { devpriv->rtsi_trig_direction_reg &= - ~Drive_RTSI_Clock_Bit; + ~NISTC_RTSI_TRIG_DRV_CLK; } ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg, - RTSI_Trig_Direction_Register); + NISTC_RTSI_TRIG_DIR_REG); break; case INSN_CONFIG_DIO_QUERY: - if (chan < num_configurable_rtsi_channels(dev)) { + if (chan < max_chan) { data[1] = (devpriv->rtsi_trig_direction_reg & - RTSI_Output_Bit(chan, devpriv->is_m_series)) + NISTC_RTSI_TRIG_DIR(chan, devpriv->is_m_series)) ? INSN_CONFIG_DIO_OUTPUT : INSN_CONFIG_DIO_INPUT; - } else if (chan == old_RTSI_clock_channel) { - data[1] = - (devpriv->rtsi_trig_direction_reg & - Drive_RTSI_Clock_Bit) - ? INSN_CONFIG_DIO_OUTPUT : INSN_CONFIG_DIO_INPUT; + } else if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN) { + data[1] = (devpriv->rtsi_trig_direction_reg & + NISTC_RTSI_TRIG_DRV_CLK) + ? INSN_CONFIG_DIO_OUTPUT + : INSN_CONFIG_DIO_INPUT; } return 2; case INSN_CONFIG_SET_CLOCK_SRC: @@ -5135,37 +4926,37 @@ static void ni_rtsi_init(struct comedi_device *dev) /* Initialises the RTSI bus signal switch to a default state */ + /* + * Use 10MHz instead of 20MHz for RTSI clock frequency. Appears + * to have no effect, at least on pxi-6281, which always uses + * 20MHz rtsi clock frequency + */ + devpriv->clock_and_fout2 = NI_M_CLK_FOUT2_RTSI_10MHZ; /* Set clock mode to internal */ - devpriv->clock_and_fout2 = MSeries_RTSI_10MHz_Bit; if (ni_set_master_clock(dev, NI_MIO_INTERNAL_CLOCK, 0) < 0) dev_err(dev->class_dev, "ni_set_master_clock failed, bug?\n"); /* default internal lines routing to RTSI bus lines */ devpriv->rtsi_trig_a_output_reg = - RTSI_Trig_Output_Bits(0, - NI_RTSI_OUTPUT_ADR_START1) | - RTSI_Trig_Output_Bits(1, - NI_RTSI_OUTPUT_ADR_START2) | - RTSI_Trig_Output_Bits(2, - NI_RTSI_OUTPUT_SCLKG) | - RTSI_Trig_Output_Bits(3, NI_RTSI_OUTPUT_DACUPDN); + NISTC_RTSI_TRIG(0, NI_RTSI_OUTPUT_ADR_START1) | + NISTC_RTSI_TRIG(1, NI_RTSI_OUTPUT_ADR_START2) | + NISTC_RTSI_TRIG(2, NI_RTSI_OUTPUT_SCLKG) | + NISTC_RTSI_TRIG(3, NI_RTSI_OUTPUT_DACUPDN); ni_stc_writew(dev, devpriv->rtsi_trig_a_output_reg, - RTSI_Trig_A_Output_Register); + NISTC_RTSI_TRIGA_OUT_REG); devpriv->rtsi_trig_b_output_reg = - RTSI_Trig_Output_Bits(4, - NI_RTSI_OUTPUT_DA_START1) | - RTSI_Trig_Output_Bits(5, - NI_RTSI_OUTPUT_G_SRC0) | - RTSI_Trig_Output_Bits(6, NI_RTSI_OUTPUT_G_GATE0); + NISTC_RTSI_TRIG(4, NI_RTSI_OUTPUT_DA_START1) | + NISTC_RTSI_TRIG(5, NI_RTSI_OUTPUT_G_SRC0) | + NISTC_RTSI_TRIG(6, NI_RTSI_OUTPUT_G_GATE0); if (devpriv->is_m_series) devpriv->rtsi_trig_b_output_reg |= - RTSI_Trig_Output_Bits(7, NI_RTSI_OUTPUT_RTSI_OSC); + NISTC_RTSI_TRIG(7, NI_RTSI_OUTPUT_RTSI_OSC); ni_stc_writew(dev, devpriv->rtsi_trig_b_output_reg, - RTSI_Trig_B_Output_Register); + NISTC_RTSI_TRIGB_OUT_REG); -/* -* Sets the source and direction of the 4 on board lines -* ni_stc_writew(dev, 0x0000, RTSI_Board_Register); -*/ + /* + * Sets the source and direction of the 4 on board lines + * ni_stc_writew(dev, 0, NISTC_RTSI_BOARD_REG); + */ } #ifdef PCIDMA @@ -5199,88 +4990,6 @@ static int ni_gpct_cancel(struct comedi_device *dev, struct comedi_subdevice *s) } #endif -#if 0 -/* - * Read the GPCTs current value. - */ -static int GPCT_G_Watch(struct comedi_device *dev, int chan) -{ - unsigned int hi1, hi2, lo; - - devpriv->gpct_command[chan] &= ~G_Save_Trace; - ni_stc_writew(dev, devpriv->gpct_command[chan], - G_Command_Register(chan)); - - devpriv->gpct_command[chan] |= G_Save_Trace; - ni_stc_writew(dev, devpriv->gpct_command[chan], - G_Command_Register(chan)); - - /* This procedure is used because the two registers cannot - * be read atomically. */ - do { - hi1 = ni_stc_readw(dev, G_Save_Register_High(chan)); - lo = ni_stc_readw(dev, G_Save_Register_Low(chan)); - hi2 = ni_stc_readw(dev, G_Save_Register_High(chan)); - } while (hi1 != hi2); - - return (hi1 << 16) | lo; -} - -static void GPCT_Reset(struct comedi_device *dev, int chan) -{ - int temp_ack_reg = 0; - - devpriv->gpct_cur_operation[chan] = GPCT_RESET; - - switch (chan) { - case 0: - ni_stc_writew(dev, G0_Reset, Joint_Reset_Register); - ni_set_bits(dev, Interrupt_A_Enable_Register, - G0_TC_Interrupt_Enable, 0); - ni_set_bits(dev, Interrupt_A_Enable_Register, - G0_Gate_Interrupt_Enable, 0); - temp_ack_reg |= G0_Gate_Error_Confirm; - temp_ack_reg |= G0_TC_Error_Confirm; - temp_ack_reg |= G0_TC_Interrupt_Ack; - temp_ack_reg |= G0_Gate_Interrupt_Ack; - ni_stc_writew(dev, temp_ack_reg, Interrupt_A_Ack_Register); - - /* problem...this interferes with the other ctr... */ - devpriv->an_trig_etc_reg |= GPFO_0_Output_Enable; - ni_stc_writew(dev, devpriv->an_trig_etc_reg, - Analog_Trigger_Etc_Register); - break; - case 1: - ni_stc_writew(dev, G1_Reset, Joint_Reset_Register); - ni_set_bits(dev, Interrupt_B_Enable_Register, - G1_TC_Interrupt_Enable, 0); - ni_set_bits(dev, Interrupt_B_Enable_Register, - G0_Gate_Interrupt_Enable, 0); - temp_ack_reg |= G1_Gate_Error_Confirm; - temp_ack_reg |= G1_TC_Error_Confirm; - temp_ack_reg |= G1_TC_Interrupt_Ack; - temp_ack_reg |= G1_Gate_Interrupt_Ack; - ni_stc_writew(dev, temp_ack_reg, Interrupt_B_Ack_Register); - - devpriv->an_trig_etc_reg |= GPFO_1_Output_Enable; - ni_stc_writew(dev, devpriv->an_trig_etc_reg, - Analog_Trigger_Etc_Register); - break; - } - - devpriv->gpct_mode[chan] = 0; - devpriv->gpct_input_select[chan] = 0; - devpriv->gpct_command[chan] = 0; - - devpriv->gpct_command[chan] |= G_Synchronized_Gate; - - ni_stc_writew(dev, devpriv->gpct_mode[chan], G_Mode_Register(chan)); - ni_stc_writew(dev, devpriv->gpct_input_select[chan], - G_Input_Select_Register(chan)); - ni_stc_writew(dev, 0, G_Autoincrement_Register(chan)); -} -#endif - static irqreturn_t ni_E_interrupt(int irq, void *d) { struct comedi_device *dev = d; @@ -5300,8 +5009,8 @@ static irqreturn_t ni_E_interrupt(int irq, void *d) /* lock to avoid race with comedi_poll */ spin_lock_irqsave(&dev->spinlock, flags); - a_status = ni_stc_readw(dev, AI_Status_1_Register); - b_status = ni_stc_readw(dev, AO_Status_1_Register); + a_status = ni_stc_readw(dev, NISTC_AI_STATUS1_REG); + b_status = ni_stc_readw(dev, NISTC_AO_STATUS1_REG); #ifdef PCIDMA if (mite) { struct ni_private *devpriv = dev->private; @@ -5329,9 +5038,9 @@ static irqreturn_t ni_E_interrupt(int irq, void *d) #endif ack_a_interrupt(dev, a_status); ack_b_interrupt(dev, b_status); - if ((a_status & Interrupt_A_St) || (ai_mite_status & CHSR_INT)) + if ((a_status & NISTC_AI_STATUS1_INTA) || (ai_mite_status & CHSR_INT)) handle_a_interrupt(dev, a_status, ai_mite_status); - if ((b_status & Interrupt_B_St) || (ao_mite_status & CHSR_INT)) + if ((b_status & NISTC_AO_STATUS1_INTB) || (ao_mite_status & CHSR_INT)) handle_b_interrupt(dev, b_status, ao_mite_status); handle_gpct_interrupt(dev, 0); handle_gpct_interrupt(dev, 1); @@ -5371,16 +5080,16 @@ static int ni_E_init(struct comedi_device *dev, } /* initialize clock dividers */ - devpriv->clock_and_fout = Slow_Internal_Time_Divide_By_2 | - Slow_Internal_Timebase | - Clock_To_Board_Divide_By_2 | - Clock_To_Board; + devpriv->clock_and_fout = NISTC_CLK_FOUT_SLOW_DIV2 | + NISTC_CLK_FOUT_SLOW_TIMEBASE | + NISTC_CLK_FOUT_TO_BOARD_DIV2 | + NISTC_CLK_FOUT_TO_BOARD; if (!devpriv->is_6xxx) { /* BEAM is this needed for PCI-6143 ?? */ - devpriv->clock_and_fout |= (AI_Output_Divide_By_2 | - AO_Output_Divide_By_2); + devpriv->clock_and_fout |= (NISTC_CLK_FOUT_AI_OUT_DIV2 | + NISTC_CLK_FOUT_AO_OUT_DIV2); } - ni_stc_writew(dev, devpriv->clock_and_fout, Clock_and_FOUT_Register); + ni_stc_writew(dev, devpriv->clock_and_fout, NISTC_CLK_FOUT_REG); ret = comedi_alloc_subdevices(dev, NI_NUM_SUBDEVICES); if (ret) @@ -5489,22 +5198,24 @@ static int ni_E_init(struct comedi_device *dev, } /* reset DIO and set all channels to inputs */ - ni_writel(dev, CDO_Reset_Bit | CDI_Reset_Bit, - M_Offset_CDIO_Command); - ni_writel(dev, s->io_bits, M_Offset_DIO_Direction); + ni_writel(dev, NI_M_CDO_CMD_RESET | + NI_M_CDI_CMD_RESET, + NI_M_CDIO_CMD_REG); + ni_writel(dev, s->io_bits, NI_M_DIO_DIR_REG); } else { s->insn_bits = ni_dio_insn_bits; s->insn_config = ni_dio_insn_config; /* set all channels to inputs */ - devpriv->dio_control = DIO_Pins_Dir(s->io_bits); - ni_writew(dev, devpriv->dio_control, DIO_Control_Register); + devpriv->dio_control = NISTC_DIO_CTRL_DIR(s->io_bits); + ni_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG); } /* 8255 device */ s = &dev->subdevices[NI_8255_DIO_SUBDEV]; if (board->has_8255) { - ret = subdev_8255_init(dev, s, ni_8255_callback, Port_A); + ret = subdev_8255_init(dev, s, ni_8255_callback, + NI_E_8255_BASE); if (ret) return ret; } else { @@ -5525,7 +5236,7 @@ static int ni_E_init(struct comedi_device *dev, /* internal PWM output used for AI nonlinearity calibration */ s->insn_config = ni_m_series_pwm_config; - ni_writel(dev, 0x0, M_Offset_Cal_PWM); + ni_writel(dev, 0x0, NI_M_CAL_PWM_REG); } else if (devpriv->is_6143) { /* internal PWM output used for AI nonlinearity calibration */ s->insn_config = ni_6143_pwm_config; @@ -5560,17 +5271,17 @@ static int ni_E_init(struct comedi_device *dev, s->n_chan = 16; s->insn_bits = ni_pfi_insn_bits; - ni_writew(dev, s->state, M_Offset_PFI_DO); + ni_writew(dev, s->state, NI_M_PFI_DO_REG); for (i = 0; i < NUM_PFI_OUTPUT_SELECT_REGS; ++i) { ni_writew(dev, devpriv->pfi_output_select_reg[i], - M_Offset_PFI_Output_Select(i + 1)); + NI_M_PFI_OUT_SEL_REG(i)); } } else { s->n_chan = 10; } s->insn_config = ni_pfi_insn_config; - ni_set_bits(dev, IO_Bidirection_Pin_Register, ~0, 0); + ni_set_bits(dev, NISTC_IO_BIDIR_PIN_REG, ~0, 0); /* cs5529 calibration adc */ s = &dev->subdevices[NI_CS5529_CALIBRATION_SUBDEV]; @@ -5663,30 +5374,31 @@ static int ni_E_init(struct comedi_device *dev, if (dev->irq) { ni_stc_writew(dev, - (irq_polarity ? Interrupt_Output_Polarity : 0) | - (Interrupt_Output_On_3_Pins & 0) | - Interrupt_A_Enable | Interrupt_B_Enable | - Interrupt_A_Output_Select(interrupt_pin) | - Interrupt_B_Output_Select(interrupt_pin), - Interrupt_Control_Register); + (irq_polarity ? NISTC_INT_CTRL_INT_POL : 0) | + (NISTC_INT_CTRL_3PIN_INT & 0) | + NISTC_INT_CTRL_INTA_ENA | + NISTC_INT_CTRL_INTB_ENA | + NISTC_INT_CTRL_INTA_SEL(interrupt_pin) | + NISTC_INT_CTRL_INTB_SEL(interrupt_pin), + NISTC_INT_CTRL_REG); } /* DMA setup */ - ni_writeb(dev, devpriv->ai_ao_select_reg, AI_AO_Select); - ni_writeb(dev, devpriv->g0_g1_select_reg, G0_G1_Select); + ni_writeb(dev, devpriv->ai_ao_select_reg, NI_E_DMA_AI_AO_SEL_REG); + ni_writeb(dev, devpriv->g0_g1_select_reg, NI_E_DMA_G0_G1_SEL_REG); if (devpriv->is_6xxx) { - ni_writeb(dev, 0, Magic_611x); + ni_writeb(dev, 0, NI611X_MAGIC_REG); } else if (devpriv->is_m_series) { int channel; for (channel = 0; channel < board->n_aochan; ++channel) { ni_writeb(dev, 0xf, - M_Offset_AO_Waveform_Order(channel)); + NI_M_AO_WAVEFORM_ORDER_REG(channel)); ni_writeb(dev, 0x0, - M_Offset_AO_Reference_Attenuation(channel)); + NI_M_AO_REF_ATTENUATION_REG(channel)); } - ni_writeb(dev, 0x0, M_Offset_AO_Calibration); + ni_writeb(dev, 0x0, NI_M_AO_CALIB_REG); } return 0; diff --git a/kernel/drivers/staging/comedi/drivers/ni_pcimio.c b/kernel/drivers/staging/comedi/drivers/ni_pcimio.c index 1481f71a3..30a5a75d1 100644 --- a/kernel/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/kernel/drivers/staging/comedi/drivers/ni_pcimio.c @@ -1085,26 +1085,25 @@ static void init_6143(struct comedi_device *dev) struct ni_private *devpriv = dev->private; /* Disable interrupts */ - ni_stc_writew(dev, 0, Interrupt_Control_Register); + ni_stc_writew(dev, 0, NISTC_INT_CTRL_REG); /* Initialise 6143 AI specific bits */ /* Set G0,G1 DMA mode to E series version */ - ni_writeb(dev, 0x00, Magic_6143); + ni_writeb(dev, 0x00, NI6143_MAGIC_REG); /* Set EOCMode, ADCMode and pipelinedelay */ - ni_writeb(dev, 0x80, PipelineDelay_6143); + ni_writeb(dev, 0x80, NI6143_PIPELINE_DELAY_REG); /* Set EOC Delay */ - ni_writeb(dev, 0x00, EOC_Set_6143); + ni_writeb(dev, 0x00, NI6143_EOC_SET_REG); /* Set the FIFO half full level */ - ni_writel(dev, board->ai_fifo_depth / 2, AIFIFO_Flag_6143); + ni_writel(dev, board->ai_fifo_depth / 2, NI6143_AI_FIFO_FLAG_REG); /* Strobe Relay disable bit */ devpriv->ai_calib_source_enabled = 0; - ni_writew(dev, devpriv->ai_calib_source | - Calibration_Channel_6143_RelayOff, - Calibration_Channel_6143); - ni_writew(dev, devpriv->ai_calib_source, Calibration_Channel_6143); + ni_writew(dev, devpriv->ai_calib_source | NI6143_CALIB_CHAN_RELAY_OFF, + NI6143_CALIB_CHAN_REG); + ni_writew(dev, devpriv->ai_calib_source, NI6143_CALIB_CHAN_REG); } static void pcimio_detach(struct comedi_device *dev) diff --git a/kernel/drivers/staging/comedi/drivers/ni_stc.h b/kernel/drivers/staging/comedi/drivers/ni_stc.h index bd69c3f0a..1d5af25b9 100644 --- a/kernel/drivers/staging/comedi/drivers/ni_stc.h +++ b/kernel/drivers/staging/comedi/drivers/ni_stc.h @@ -26,884 +26,907 @@ #include "ni_tio.h" -#define _bit15 0x8000 -#define _bit14 0x4000 -#define _bit13 0x2000 -#define _bit12 0x1000 -#define _bit11 0x0800 -#define _bit10 0x0400 -#define _bit9 0x0200 -#define _bit8 0x0100 -#define _bit7 0x0080 -#define _bit6 0x0040 -#define _bit5 0x0020 -#define _bit4 0x0010 -#define _bit3 0x0008 -#define _bit2 0x0004 -#define _bit1 0x0002 -#define _bit0 0x0001 - -#define NUM_PFI_OUTPUT_SELECT_REGS 6 - -/* Registers in the National Instruments DAQ-STC chip */ - -#define Interrupt_A_Ack_Register 2 -#define G0_Gate_Interrupt_Ack _bit15 -#define G0_TC_Interrupt_Ack _bit14 -#define AI_Error_Interrupt_Ack _bit13 -#define AI_STOP_Interrupt_Ack _bit12 -#define AI_START_Interrupt_Ack _bit11 -#define AI_START2_Interrupt_Ack _bit10 -#define AI_START1_Interrupt_Ack _bit9 -#define AI_SC_TC_Interrupt_Ack _bit8 -#define AI_SC_TC_Error_Confirm _bit7 -#define G0_TC_Error_Confirm _bit6 -#define G0_Gate_Error_Confirm _bit5 - -#define AI_Status_1_Register 2 -#define Interrupt_A_St 0x8000 -#define AI_FIFO_Full_St 0x4000 -#define AI_FIFO_Half_Full_St 0x2000 -#define AI_FIFO_Empty_St 0x1000 -#define AI_Overrun_St 0x0800 -#define AI_Overflow_St 0x0400 -#define AI_SC_TC_Error_St 0x0200 -#define AI_START2_St 0x0100 -#define AI_START1_St 0x0080 -#define AI_SC_TC_St 0x0040 -#define AI_START_St 0x0020 -#define AI_STOP_St 0x0010 -#define G0_TC_St 0x0008 -#define G0_Gate_Interrupt_St 0x0004 -#define AI_FIFO_Request_St 0x0002 -#define Pass_Thru_0_Interrupt_St 0x0001 - -#define AI_Status_2_Register 5 - -#define Interrupt_B_Ack_Register 3 -enum Interrupt_B_Ack_Bits { - G1_Gate_Error_Confirm = _bit1, - G1_TC_Error_Confirm = _bit2, - AO_BC_TC_Trigger_Error_Confirm = _bit3, - AO_BC_TC_Error_Confirm = _bit4, - AO_UI2_TC_Error_Confrim = _bit5, - AO_UI2_TC_Interrupt_Ack = _bit6, - AO_UC_TC_Interrupt_Ack = _bit7, - AO_BC_TC_Interrupt_Ack = _bit8, - AO_START1_Interrupt_Ack = _bit9, - AO_UPDATE_Interrupt_Ack = _bit10, - AO_START_Interrupt_Ack = _bit11, - AO_STOP_Interrupt_Ack = _bit12, - AO_Error_Interrupt_Ack = _bit13, - G1_TC_Interrupt_Ack = _bit14, - G1_Gate_Interrupt_Ack = _bit15 -}; - -#define AO_Status_1_Register 3 -#define Interrupt_B_St _bit15 -#define AO_FIFO_Full_St _bit14 -#define AO_FIFO_Half_Full_St _bit13 -#define AO_FIFO_Empty_St _bit12 -#define AO_BC_TC_Error_St _bit11 -#define AO_START_St _bit10 -#define AO_Overrun_St _bit9 -#define AO_START1_St _bit8 -#define AO_BC_TC_St _bit7 -#define AO_UC_TC_St _bit6 -#define AO_UPDATE_St _bit5 -#define AO_UI2_TC_St _bit4 -#define G1_TC_St _bit3 -#define G1_Gate_Interrupt_St _bit2 -#define AO_FIFO_Request_St _bit1 -#define Pass_Thru_1_Interrupt_St _bit0 - -#define AI_Command_2_Register 4 -#define AI_End_On_SC_TC _bit15 -#define AI_End_On_End_Of_Scan _bit14 -#define AI_START1_Disable _bit11 -#define AI_SC_Save_Trace _bit10 -#define AI_SI_Switch_Load_On_SC_TC _bit9 -#define AI_SI_Switch_Load_On_STOP _bit8 -#define AI_SI_Switch_Load_On_TC _bit7 -#define AI_SC_Switch_Load_On_TC _bit4 -#define AI_STOP_Pulse _bit3 -#define AI_START_Pulse _bit2 -#define AI_START2_Pulse _bit1 -#define AI_START1_Pulse _bit0 - -#define AO_Command_2_Register 5 -#define AO_End_On_BC_TC(x) (((x) & 0x3) << 14) -#define AO_Start_Stop_Gate_Enable _bit13 -#define AO_UC_Save_Trace _bit12 -#define AO_BC_Gate_Enable _bit11 -#define AO_BC_Save_Trace _bit10 -#define AO_UI_Switch_Load_On_BC_TC _bit9 -#define AO_UI_Switch_Load_On_Stop _bit8 -#define AO_UI_Switch_Load_On_TC _bit7 -#define AO_UC_Switch_Load_On_BC_TC _bit6 -#define AO_UC_Switch_Load_On_TC _bit5 -#define AO_BC_Switch_Load_On_TC _bit4 -#define AO_Mute_B _bit3 -#define AO_Mute_A _bit2 -#define AO_UPDATE2_Pulse _bit1 -#define AO_START1_Pulse _bit0 - -#define AO_Status_2_Register 6 - -#define DIO_Parallel_Input_Register 7 - -#define AI_Command_1_Register 8 -#define AI_Analog_Trigger_Reset _bit14 -#define AI_Disarm _bit13 -#define AI_SI2_Arm _bit12 -#define AI_SI2_Load _bit11 -#define AI_SI_Arm _bit10 -#define AI_SI_Load _bit9 -#define AI_DIV_Arm _bit8 -#define AI_DIV_Load _bit7 -#define AI_SC_Arm _bit6 -#define AI_SC_Load _bit5 -#define AI_SCAN_IN_PROG_Pulse _bit4 -#define AI_EXTMUX_CLK_Pulse _bit3 -#define AI_LOCALMUX_CLK_Pulse _bit2 -#define AI_SC_TC_Pulse _bit1 -#define AI_CONVERT_Pulse _bit0 - -#define AO_Command_1_Register 9 -#define AO_Analog_Trigger_Reset _bit15 -#define AO_START_Pulse _bit14 -#define AO_Disarm _bit13 -#define AO_UI2_Arm_Disarm _bit12 -#define AO_UI2_Load _bit11 -#define AO_UI_Arm _bit10 -#define AO_UI_Load _bit9 -#define AO_UC_Arm _bit8 -#define AO_UC_Load _bit7 -#define AO_BC_Arm _bit6 -#define AO_BC_Load _bit5 -#define AO_DAC1_Update_Mode _bit4 -#define AO_LDAC1_Source_Select _bit3 -#define AO_DAC0_Update_Mode _bit2 -#define AO_LDAC0_Source_Select _bit1 -#define AO_UPDATE_Pulse _bit0 - -#define DIO_Output_Register 10 -#define DIO_Parallel_Data_Out(a) ((a)&0xff) -#define DIO_Parallel_Data_Mask 0xff -#define DIO_SDOUT _bit0 -#define DIO_SDIN _bit4 -#define DIO_Serial_Data_Out(a) (((a)&0xff)<<8) -#define DIO_Serial_Data_Mask 0xff00 - -#define DIO_Control_Register 11 -#define DIO_Software_Serial_Control _bit11 -#define DIO_HW_Serial_Timebase _bit10 -#define DIO_HW_Serial_Enable _bit9 -#define DIO_HW_Serial_Start _bit8 -#define DIO_Pins_Dir(a) ((a)&0xff) -#define DIO_Pins_Dir_Mask 0xff - -#define AI_Mode_1_Register 12 -#define AI_CONVERT_Source_Select(a) (((a) & 0x1f) << 11) -#define AI_SI_Source_select(a) (((a) & 0x1f) << 6) -#define AI_CONVERT_Source_Polarity _bit5 -#define AI_SI_Source_Polarity _bit4 -#define AI_Start_Stop _bit3 -#define AI_Mode_1_Reserved _bit2 -#define AI_Continuous _bit1 -#define AI_Trigger_Once _bit0 - -#define AI_Mode_2_Register 13 -#define AI_SC_Gate_Enable _bit15 -#define AI_Start_Stop_Gate_Enable _bit14 -#define AI_Pre_Trigger _bit13 -#define AI_External_MUX_Present _bit12 -#define AI_SI2_Initial_Load_Source _bit9 -#define AI_SI2_Reload_Mode _bit8 -#define AI_SI_Initial_Load_Source _bit7 -#define AI_SI_Reload_Mode(a) (((a) & 0x7)<<4) -#define AI_SI_Write_Switch _bit3 -#define AI_SC_Initial_Load_Source _bit2 -#define AI_SC_Reload_Mode _bit1 -#define AI_SC_Write_Switch _bit0 - -#define AI_SI_Load_A_Registers 14 -#define AI_SI_Load_B_Registers 16 -#define AI_SC_Load_A_Registers 18 -#define AI_SC_Load_B_Registers 20 -#define AI_SI_Save_Registers 64 -#define AI_SC_Save_Registers 66 - -#define AI_SI2_Load_A_Register 23 -#define AI_SI2_Load_B_Register 25 - -#define Joint_Status_1_Register 27 -#define DIO_Serial_IO_In_Progress_St _bit12 - -#define DIO_Serial_Input_Register 28 -#define Joint_Status_2_Register 29 -enum Joint_Status_2_Bits { - AO_TMRDACWRs_In_Progress_St = 0x20, -}; - -#define AO_Mode_1_Register 38 -#define AO_UPDATE_Source_Select(x) (((x)&0x1f)<<11) -#define AO_UI_Source_Select(x) (((x)&0x1f)<<6) -#define AO_Multiple_Channels _bit5 -#define AO_UPDATE_Source_Polarity _bit4 -#define AO_UI_Source_Polarity _bit3 -#define AO_UC_Switch_Load_Every_TC _bit2 -#define AO_Continuous _bit1 -#define AO_Trigger_Once _bit0 - -#define AO_Mode_2_Register 39 -#define AO_FIFO_Mode_Mask (0x3 << 14) -enum AO_FIFO_Mode_Bits { - AO_FIFO_Mode_HF_to_F = (3 << 14), - AO_FIFO_Mode_F = (2 << 14), - AO_FIFO_Mode_HF = (1 << 14), - AO_FIFO_Mode_E = (0 << 14), -}; -#define AO_FIFO_Retransmit_Enable _bit13 -#define AO_START1_Disable _bit12 -#define AO_UC_Initial_Load_Source _bit11 -#define AO_UC_Write_Switch _bit10 -#define AO_UI2_Initial_Load_Source _bit9 -#define AO_UI2_Reload_Mode _bit8 -#define AO_UI_Initial_Load_Source _bit7 -#define AO_UI_Reload_Mode(x) (((x) & 0x7) << 4) -#define AO_UI_Write_Switch _bit3 -#define AO_BC_Initial_Load_Source _bit2 -#define AO_BC_Reload_Mode _bit1 -#define AO_BC_Write_Switch _bit0 - -#define AO_UI_Load_A_Register 40 -#define AO_UI_Load_A_Register_High 40 -#define AO_UI_Load_A_Register_Low 41 -#define AO_UI_Load_B_Register 42 -#define AO_UI_Save_Registers 16 -#define AO_BC_Load_A_Register 44 -#define AO_BC_Load_A_Register_High 44 -#define AO_BC_Load_A_Register_Low 45 -#define AO_BC_Load_B_Register 46 -#define AO_BC_Load_B_Register_High 46 -#define AO_BC_Load_B_Register_Low 47 -#define AO_BC_Save_Registers 18 -#define AO_UC_Load_A_Register 48 -#define AO_UC_Load_A_Register_High 48 -#define AO_UC_Load_A_Register_Low 49 -#define AO_UC_Load_B_Register 50 -#define AO_UC_Save_Registers 20 - -#define Clock_and_FOUT_Register 56 -enum Clock_and_FOUT_bits { - FOUT_Enable = _bit15, - FOUT_Timebase_Select = _bit14, - DIO_Serial_Out_Divide_By_2 = _bit13, - Slow_Internal_Time_Divide_By_2 = _bit12, - Slow_Internal_Timebase = _bit11, - G_Source_Divide_By_2 = _bit10, - Clock_To_Board_Divide_By_2 = _bit9, - Clock_To_Board = _bit8, - AI_Output_Divide_By_2 = _bit7, - AI_Source_Divide_By_2 = _bit6, - AO_Output_Divide_By_2 = _bit5, - AO_Source_Divide_By_2 = _bit4, - FOUT_Divider_mask = 0xf -}; -static inline unsigned FOUT_Divider(unsigned divider) -{ - return divider & FOUT_Divider_mask; -} - -#define IO_Bidirection_Pin_Register 57 -#define RTSI_Trig_Direction_Register 58 -enum RTSI_Trig_Direction_Bits { - Drive_RTSI_Clock_Bit = 0x1, - Use_RTSI_Clock_Bit = 0x2, -}; -static inline unsigned RTSI_Output_Bit(unsigned channel, int is_mseries) -{ - unsigned max_channel; - unsigned base_bit_shift; - if (is_mseries) { - base_bit_shift = 8; - max_channel = 7; - } else { - base_bit_shift = 9; - max_channel = 6; - } - if (channel > max_channel) { - pr_err("%s: bug, invalid RTSI_channel=%i\n", __func__, channel); - return 0; - } - return 1 << (base_bit_shift + channel); -} - -#define Interrupt_Control_Register 59 -#define Interrupt_B_Enable _bit15 -#define Interrupt_B_Output_Select(x) ((x)<<12) -#define Interrupt_A_Enable _bit11 -#define Interrupt_A_Output_Select(x) ((x)<<8) -#define Pass_Thru_0_Interrupt_Polarity _bit3 -#define Pass_Thru_1_Interrupt_Polarity _bit2 -#define Interrupt_Output_On_3_Pins _bit1 -#define Interrupt_Output_Polarity _bit0 - -#define AI_Output_Control_Register 60 -#define AI_START_Output_Select _bit10 -#define AI_SCAN_IN_PROG_Output_Select(x) (((x) & 0x3) << 8) -#define AI_EXTMUX_CLK_Output_Select(x) (((x) & 0x3) << 6) -#define AI_LOCALMUX_CLK_Output_Select(x) ((x)<<4) -#define AI_SC_TC_Output_Select(x) ((x)<<2) -enum ai_convert_output_selection { - AI_CONVERT_Output_High_Z = 0, - AI_CONVERT_Output_Ground = 1, - AI_CONVERT_Output_Enable_Low = 2, - AI_CONVERT_Output_Enable_High = 3 -}; -static unsigned AI_CONVERT_Output_Select(enum ai_convert_output_selection - selection) -{ - return selection & 0x3; -} - -#define AI_START_STOP_Select_Register 62 -#define AI_START_Polarity _bit15 -#define AI_STOP_Polarity _bit14 -#define AI_STOP_Sync _bit13 -#define AI_STOP_Edge _bit12 -#define AI_STOP_Select(a) (((a) & 0x1f)<<7) -#define AI_START_Sync _bit6 -#define AI_START_Edge _bit5 -#define AI_START_Select(a) ((a) & 0x1f) - -#define AI_Trigger_Select_Register 63 -#define AI_START1_Polarity _bit15 -#define AI_START2_Polarity _bit14 -#define AI_START2_Sync _bit13 -#define AI_START2_Edge _bit12 -#define AI_START2_Select(a) (((a) & 0x1f) << 7) -#define AI_START1_Sync _bit6 -#define AI_START1_Edge _bit5 -#define AI_START1_Select(a) ((a) & 0x1f) - -#define AI_DIV_Load_A_Register 64 - -#define AO_Start_Select_Register 66 -#define AO_UI2_Software_Gate _bit15 -#define AO_UI2_External_Gate_Polarity _bit14 -#define AO_START_Polarity _bit13 -#define AO_AOFREQ_Enable _bit12 -#define AO_UI2_External_Gate_Select(a) (((a) & 0x1f) << 7) -#define AO_START_Sync _bit6 -#define AO_START_Edge _bit5 -#define AO_START_Select(a) ((a) & 0x1f) - -#define AO_Trigger_Select_Register 67 -#define AO_UI2_External_Gate_Enable _bit15 -#define AO_Delayed_START1 _bit14 -#define AO_START1_Polarity _bit13 -#define AO_UI2_Source_Polarity _bit12 -#define AO_UI2_Source_Select(x) (((x)&0x1f)<<7) -#define AO_START1_Sync _bit6 -#define AO_START1_Edge _bit5 -#define AO_START1_Select(x) (((x)&0x1f)<<0) - -#define AO_Mode_3_Register 70 -#define AO_UI2_Switch_Load_Next_TC _bit13 -#define AO_UC_Switch_Load_Every_BC_TC _bit12 -#define AO_Trigger_Length _bit11 -#define AO_Stop_On_Overrun_Error _bit5 -#define AO_Stop_On_BC_TC_Trigger_Error _bit4 -#define AO_Stop_On_BC_TC_Error _bit3 -#define AO_Not_An_UPDATE _bit2 -#define AO_Software_Gate _bit1 -#define AO_Last_Gate_Disable _bit0 /* M Series only */ - -#define Joint_Reset_Register 72 -#define Software_Reset _bit11 -#define AO_Configuration_End _bit9 -#define AI_Configuration_End _bit8 -#define AO_Configuration_Start _bit5 -#define AI_Configuration_Start _bit4 -#define G1_Reset _bit3 -#define G0_Reset _bit2 -#define AO_Reset _bit1 -#define AI_Reset _bit0 - -#define Interrupt_A_Enable_Register 73 -#define Pass_Thru_0_Interrupt_Enable _bit9 -#define G0_Gate_Interrupt_Enable _bit8 -#define AI_FIFO_Interrupt_Enable _bit7 -#define G0_TC_Interrupt_Enable _bit6 -#define AI_Error_Interrupt_Enable _bit5 -#define AI_STOP_Interrupt_Enable _bit4 -#define AI_START_Interrupt_Enable _bit3 -#define AI_START2_Interrupt_Enable _bit2 -#define AI_START1_Interrupt_Enable _bit1 -#define AI_SC_TC_Interrupt_Enable _bit0 - -#define Interrupt_B_Enable_Register 75 -#define Pass_Thru_1_Interrupt_Enable _bit11 -#define G1_Gate_Interrupt_Enable _bit10 -#define G1_TC_Interrupt_Enable _bit9 -#define AO_FIFO_Interrupt_Enable _bit8 -#define AO_UI2_TC_Interrupt_Enable _bit7 -#define AO_UC_TC_Interrupt_Enable _bit6 -#define AO_Error_Interrupt_Enable _bit5 -#define AO_STOP_Interrupt_Enable _bit4 -#define AO_START_Interrupt_Enable _bit3 -#define AO_UPDATE_Interrupt_Enable _bit2 -#define AO_START1_Interrupt_Enable _bit1 -#define AO_BC_TC_Interrupt_Enable _bit0 - -#define Second_IRQ_A_Enable_Register 74 -enum Second_IRQ_A_Enable_Bits { - AI_SC_TC_Second_Irq_Enable = _bit0, - AI_START1_Second_Irq_Enable = _bit1, - AI_START2_Second_Irq_Enable = _bit2, - AI_START_Second_Irq_Enable = _bit3, - AI_STOP_Second_Irq_Enable = _bit4, - AI_Error_Second_Irq_Enable = _bit5, - G0_TC_Second_Irq_Enable = _bit6, - AI_FIFO_Second_Irq_Enable = _bit7, - G0_Gate_Second_Irq_Enable = _bit8, - Pass_Thru_0_Second_Irq_Enable = _bit9 -}; +/* + * Registers in the National Instruments DAQ-STC chip + */ + +#define NISTC_INTA_ACK_REG 2 +#define NISTC_INTA_ACK_G0_GATE BIT(15) +#define NISTC_INTA_ACK_G0_TC BIT(14) +#define NISTC_INTA_ACK_AI_ERR BIT(13) +#define NISTC_INTA_ACK_AI_STOP BIT(12) +#define NISTC_INTA_ACK_AI_START BIT(11) +#define NISTC_INTA_ACK_AI_START2 BIT(10) +#define NISTC_INTA_ACK_AI_START1 BIT(9) +#define NISTC_INTA_ACK_AI_SC_TC BIT(8) +#define NISTC_INTA_ACK_AI_SC_TC_ERR BIT(7) +#define NISTC_INTA_ACK_G0_TC_ERR BIT(6) +#define NISTC_INTA_ACK_G0_GATE_ERR BIT(5) +#define NISTC_INTA_ACK_AI_ALL (NISTC_INTA_ACK_AI_ERR | \ + NISTC_INTA_ACK_AI_STOP | \ + NISTC_INTA_ACK_AI_START | \ + NISTC_INTA_ACK_AI_START2 | \ + NISTC_INTA_ACK_AI_START1 | \ + NISTC_INTA_ACK_AI_SC_TC | \ + NISTC_INTA_ACK_AI_SC_TC_ERR) + +#define NISTC_INTB_ACK_REG 3 +#define NISTC_INTB_ACK_G1_GATE BIT(15) +#define NISTC_INTB_ACK_G1_TC BIT(14) +#define NISTC_INTB_ACK_AO_ERR BIT(13) +#define NISTC_INTB_ACK_AO_STOP BIT(12) +#define NISTC_INTB_ACK_AO_START BIT(11) +#define NISTC_INTB_ACK_AO_UPDATE BIT(10) +#define NISTC_INTB_ACK_AO_START1 BIT(9) +#define NISTC_INTB_ACK_AO_BC_TC BIT(8) +#define NISTC_INTB_ACK_AO_UC_TC BIT(7) +#define NISTC_INTB_ACK_AO_UI2_TC BIT(6) +#define NISTC_INTB_ACK_AO_UI2_TC_ERR BIT(5) +#define NISTC_INTB_ACK_AO_BC_TC_ERR BIT(4) +#define NISTC_INTB_ACK_AO_BC_TC_TRIG_ERR BIT(3) +#define NISTC_INTB_ACK_G1_TC_ERR BIT(2) +#define NISTC_INTB_ACK_G1_GATE_ERR BIT(1) +#define NISTC_INTB_ACK_AO_ALL (NISTC_INTB_ACK_AO_ERR | \ + NISTC_INTB_ACK_AO_STOP | \ + NISTC_INTB_ACK_AO_START | \ + NISTC_INTB_ACK_AO_UPDATE | \ + NISTC_INTB_ACK_AO_START1 | \ + NISTC_INTB_ACK_AO_BC_TC | \ + NISTC_INTB_ACK_AO_UC_TC | \ + NISTC_INTB_ACK_AO_BC_TC_ERR | \ + NISTC_INTB_ACK_AO_BC_TC_TRIG_ERR) + +#define NISTC_AI_CMD2_REG 4 +#define NISTC_AI_CMD2_END_ON_SC_TC BIT(15) +#define NISTC_AI_CMD2_END_ON_EOS BIT(14) +#define NISTC_AI_CMD2_START1_DISABLE BIT(11) +#define NISTC_AI_CMD2_SC_SAVE_TRACE BIT(10) +#define NISTC_AI_CMD2_SI_SW_ON_SC_TC BIT(9) +#define NISTC_AI_CMD2_SI_SW_ON_STOP BIT(8) +#define NISTC_AI_CMD2_SI_SW_ON_TC BIT(7) +#define NISTC_AI_CMD2_SC_SW_ON_TC BIT(4) +#define NISTC_AI_CMD2_STOP_PULSE BIT(3) +#define NISTC_AI_CMD2_START_PULSE BIT(2) +#define NISTC_AI_CMD2_START2_PULSE BIT(1) +#define NISTC_AI_CMD2_START1_PULSE BIT(0) + +#define NISTC_AO_CMD2_REG 5 +#define NISTC_AO_CMD2_END_ON_BC_TC(x) (((x) & 0x3) << 14) +#define NISTC_AO_CMD2_START_STOP_GATE_ENA BIT(13) +#define NISTC_AO_CMD2_UC_SAVE_TRACE BIT(12) +#define NISTC_AO_CMD2_BC_GATE_ENA BIT(11) +#define NISTC_AO_CMD2_BC_SAVE_TRACE BIT(10) +#define NISTC_AO_CMD2_UI_SW_ON_BC_TC BIT(9) +#define NISTC_AO_CMD2_UI_SW_ON_STOP BIT(8) +#define NISTC_AO_CMD2_UI_SW_ON_TC BIT(7) +#define NISTC_AO_CMD2_UC_SW_ON_BC_TC BIT(6) +#define NISTC_AO_CMD2_UC_SW_ON_TC BIT(5) +#define NISTC_AO_CMD2_BC_SW_ON_TC BIT(4) +#define NISTC_AO_CMD2_MUTE_B BIT(3) +#define NISTC_AO_CMD2_MUTE_A BIT(2) +#define NISTC_AO_CMD2_UPDATE2_PULSE BIT(1) +#define NISTC_AO_CMD2_START1_PULSE BIT(0) + +#define NISTC_G0_CMD_REG 6 +#define NISTC_G1_CMD_REG 7 + +#define NISTC_AI_CMD1_REG 8 +#define NISTC_AI_CMD1_ATRIG_RESET BIT(14) +#define NISTC_AI_CMD1_DISARM BIT(13) +#define NISTC_AI_CMD1_SI2_ARM BIT(12) +#define NISTC_AI_CMD1_SI2_LOAD BIT(11) +#define NISTC_AI_CMD1_SI_ARM BIT(10) +#define NISTC_AI_CMD1_SI_LOAD BIT(9) +#define NISTC_AI_CMD1_DIV_ARM BIT(8) +#define NISTC_AI_CMD1_DIV_LOAD BIT(7) +#define NISTC_AI_CMD1_SC_ARM BIT(6) +#define NISTC_AI_CMD1_SC_LOAD BIT(5) +#define NISTC_AI_CMD1_SCAN_IN_PROG_PULSE BIT(4) +#define NISTC_AI_CMD1_EXTMUX_CLK_PULSE BIT(3) +#define NISTC_AI_CMD1_LOCALMUX_CLK_PULSE BIT(2) +#define NISTC_AI_CMD1_SC_TC_PULSE BIT(1) +#define NISTC_AI_CMD1_CONVERT_PULSE BIT(0) + +#define NISTC_AO_CMD1_REG 9 +#define NISTC_AO_CMD1_ATRIG_RESET BIT(15) +#define NISTC_AO_CMD1_START_PULSE BIT(14) +#define NISTC_AO_CMD1_DISARM BIT(13) +#define NISTC_AO_CMD1_UI2_ARM_DISARM BIT(12) +#define NISTC_AO_CMD1_UI2_LOAD BIT(11) +#define NISTC_AO_CMD1_UI_ARM BIT(10) +#define NISTC_AO_CMD1_UI_LOAD BIT(9) +#define NISTC_AO_CMD1_UC_ARM BIT(8) +#define NISTC_AO_CMD1_UC_LOAD BIT(7) +#define NISTC_AO_CMD1_BC_ARM BIT(6) +#define NISTC_AO_CMD1_BC_LOAD BIT(5) +#define NISTC_AO_CMD1_DAC1_UPDATE_MODE BIT(4) +#define NISTC_AO_CMD1_LDAC1_SRC_SEL BIT(3) +#define NISTC_AO_CMD1_DAC0_UPDATE_MODE BIT(2) +#define NISTC_AO_CMD1_LDAC0_SRC_SEL BIT(1) +#define NISTC_AO_CMD1_UPDATE_PULSE BIT(0) + +#define NISTC_DIO_OUT_REG 10 +#define NISTC_DIO_OUT_SERIAL(x) (((x) & 0xff) << 8) +#define NISTC_DIO_OUT_SERIAL_MASK NISTC_DIO_OUT_SERIAL(0xff) +#define NISTC_DIO_OUT_PARALLEL(x) ((x) & 0xff) +#define NISTC_DIO_OUT_PARALLEL_MASK NISTC_DIO_OUT_PARALLEL(0xff) +#define NISTC_DIO_SDIN BIT(4) +#define NISTC_DIO_SDOUT BIT(0) + +#define NISTC_DIO_CTRL_REG 11 +#define NISTC_DIO_SDCLK BIT(11) +#define NISTC_DIO_CTRL_HW_SER_TIMEBASE BIT(10) +#define NISTC_DIO_CTRL_HW_SER_ENA BIT(9) +#define NISTC_DIO_CTRL_HW_SER_START BIT(8) +#define NISTC_DIO_CTRL_DIR(x) ((x) & 0xff) +#define NISTC_DIO_CTRL_DIR_MASK NISTC_DIO_CTRL_DIR(0xff) + +#define NISTC_AI_MODE1_REG 12 +#define NISTC_AI_MODE1_CONVERT_SRC(x) (((x) & 0x1f) << 11) +#define NISTC_AI_MODE1_SI_SRC(x) (((x) & 0x1f) << 6) +#define NISTC_AI_MODE1_CONVERT_POLARITY BIT(5) +#define NISTC_AI_MODE1_SI_POLARITY BIT(4) +#define NISTC_AI_MODE1_START_STOP BIT(3) +#define NISTC_AI_MODE1_RSVD BIT(2) +#define NISTC_AI_MODE1_CONTINUOUS BIT(1) +#define NISTC_AI_MODE1_TRIGGER_ONCE BIT(0) + +#define NISTC_AI_MODE2_REG 13 +#define NISTC_AI_MODE2_SC_GATE_ENA BIT(15) +#define NISTC_AI_MODE2_START_STOP_GATE_ENA BIT(14) +#define NISTC_AI_MODE2_PRE_TRIGGER BIT(13) +#define NISTC_AI_MODE2_EXTMUX_PRESENT BIT(12) +#define NISTC_AI_MODE2_SI2_INIT_LOAD_SRC BIT(9) +#define NISTC_AI_MODE2_SI2_RELOAD_MODE BIT(8) +#define NISTC_AI_MODE2_SI_INIT_LOAD_SRC BIT(7) +#define NISTC_AI_MODE2_SI_RELOAD_MODE(x) (((x) & 0x7) << 4) +#define NISTC_AI_MODE2_SI_WR_SWITCH BIT(3) +#define NISTC_AI_MODE2_SC_INIT_LOAD_SRC BIT(2) +#define NISTC_AI_MODE2_SC_RELOAD_MODE BIT(1) +#define NISTC_AI_MODE2_SC_WR_SWITCH BIT(0) + +#define NISTC_AI_SI_LOADA_REG 14 +#define NISTC_AI_SI_LOADB_REG 16 +#define NISTC_AI_SC_LOADA_REG 18 +#define NISTC_AI_SC_LOADB_REG 20 +#define NISTC_AI_SI2_LOADA_REG 23 +#define NISTC_AI_SI2_LOADB_REG 25 + +#define NISTC_G0_MODE_REG 26 +#define NISTC_G1_MODE_REG 27 +#define NISTC_G0_LOADA_REG 28 +#define NISTC_G0_LOADB_REG 30 +#define NISTC_G1_LOADA_REG 32 +#define NISTC_G1_LOADB_REG 34 +#define NISTC_G0_INPUT_SEL_REG 36 +#define NISTC_G1_INPUT_SEL_REG 37 + +#define NISTC_AO_MODE1_REG 38 +#define NISTC_AO_MODE1_UPDATE_SRC(x) (((x) & 0x1f) << 11) +#define NISTC_AO_MODE1_UPDATE_SRC_MASK NISTC_AO_MODE1_UPDATE_SRC(0x1f) +#define NISTC_AO_MODE1_UI_SRC(x) (((x) & 0x1f) << 6) +#define NISTC_AO_MODE1_UI_SRC_MASK NISTC_AO_MODE1_UI_SRC(0x1f) +#define NISTC_AO_MODE1_MULTI_CHAN BIT(5) +#define NISTC_AO_MODE1_UPDATE_SRC_POLARITY BIT(4) +#define NISTC_AO_MODE1_UI_SRC_POLARITY BIT(3) +#define NISTC_AO_MODE1_UC_SW_EVERY_TC BIT(2) +#define NISTC_AO_MODE1_CONTINUOUS BIT(1) +#define NISTC_AO_MODE1_TRIGGER_ONCE BIT(0) + +#define NISTC_AO_MODE2_REG 39 +#define NISTC_AO_MODE2_FIFO_MODE(x) (((x) & 0x3) << 14) +#define NISTC_AO_MODE2_FIFO_MODE_MASK NISTC_AO_MODE2_FIFO_MODE(3) +#define NISTC_AO_MODE2_FIFO_MODE_E NISTC_AO_MODE2_FIFO_MODE(0) +#define NISTC_AO_MODE2_FIFO_MODE_HF NISTC_AO_MODE2_FIFO_MODE(1) +#define NISTC_AO_MODE2_FIFO_MODE_F NISTC_AO_MODE2_FIFO_MODE(2) +#define NISTC_AO_MODE2_FIFO_MODE_HF_F NISTC_AO_MODE2_FIFO_MODE(3) +#define NISTC_AO_MODE2_FIFO_REXMIT_ENA BIT(13) +#define NISTC_AO_MODE2_START1_DISABLE BIT(12) +#define NISTC_AO_MODE2_UC_INIT_LOAD_SRC BIT(11) +#define NISTC_AO_MODE2_UC_WR_SWITCH BIT(10) +#define NISTC_AO_MODE2_UI2_INIT_LOAD_SRC BIT(9) +#define NISTC_AO_MODE2_UI2_RELOAD_MODE BIT(8) +#define NISTC_AO_MODE2_UI_INIT_LOAD_SRC BIT(7) +#define NISTC_AO_MODE2_UI_RELOAD_MODE(x) (((x) & 0x7) << 4) +#define NISTC_AO_MODE2_UI_WR_SWITCH BIT(3) +#define NISTC_AO_MODE2_BC_INIT_LOAD_SRC BIT(2) +#define NISTC_AO_MODE2_BC_RELOAD_MODE BIT(1) +#define NISTC_AO_MODE2_BC_WR_SWITCH BIT(0) + +#define NISTC_AO_UI_LOADA_REG 40 +#define NISTC_AO_UI_LOADB_REG 42 +#define NISTC_AO_BC_LOADA_REG 44 +#define NISTC_AO_BC_LOADB_REG 46 +#define NISTC_AO_UC_LOADA_REG 48 +#define NISTC_AO_UC_LOADB_REG 50 + +#define NISTC_CLK_FOUT_REG 56 +#define NISTC_CLK_FOUT_ENA BIT(15) +#define NISTC_CLK_FOUT_TIMEBASE_SEL BIT(14) +#define NISTC_CLK_FOUT_DIO_SER_OUT_DIV2 BIT(13) +#define NISTC_CLK_FOUT_SLOW_DIV2 BIT(12) +#define NISTC_CLK_FOUT_SLOW_TIMEBASE BIT(11) +#define NISTC_CLK_FOUT_G_SRC_DIV2 BIT(10) +#define NISTC_CLK_FOUT_TO_BOARD_DIV2 BIT(9) +#define NISTC_CLK_FOUT_TO_BOARD BIT(8) +#define NISTC_CLK_FOUT_AI_OUT_DIV2 BIT(7) +#define NISTC_CLK_FOUT_AI_SRC_DIV2 BIT(6) +#define NISTC_CLK_FOUT_AO_OUT_DIV2 BIT(5) +#define NISTC_CLK_FOUT_AO_SRC_DIV2 BIT(4) +#define NISTC_CLK_FOUT_DIVIDER(x) (((x) & 0xf) << 0) +#define NISTC_CLK_FOUT_TO_DIVIDER(x) (((x) >> 0) & 0xf) +#define NISTC_CLK_FOUT_DIVIDER_MASK NISTC_CLK_FOUT_DIVIDER(0xf) + +#define NISTC_IO_BIDIR_PIN_REG 57 + +#define NISTC_RTSI_TRIG_DIR_REG 58 +#define NISTC_RTSI_TRIG_OLD_CLK_CHAN 7 +#define NISTC_RTSI_TRIG_NUM_CHAN(_m) ((_m) ? 8 : 7) +#define NISTC_RTSI_TRIG_DIR(_c, _m) ((_m) ? BIT(8 + (_c)) : BIT(7 + (_c))) +#define NISTC_RTSI_TRIG_USE_CLK BIT(1) +#define NISTC_RTSI_TRIG_DRV_CLK BIT(0) + +#define NISTC_INT_CTRL_REG 59 +#define NISTC_INT_CTRL_INTB_ENA BIT(15) +#define NISTC_INT_CTRL_INTB_SEL(x) (((x) & 0x7) << 12) +#define NISTC_INT_CTRL_INTA_ENA BIT(11) +#define NISTC_INT_CTRL_INTA_SEL(x) (((x) & 0x7) << 8) +#define NISTC_INT_CTRL_PASSTHRU0_POL BIT(3) +#define NISTC_INT_CTRL_PASSTHRU1_POL BIT(2) +#define NISTC_INT_CTRL_3PIN_INT BIT(1) +#define NISTC_INT_CTRL_INT_POL BIT(0) + +#define NISTC_AI_OUT_CTRL_REG 60 +#define NISTC_AI_OUT_CTRL_START_SEL BIT(10) +#define NISTC_AI_OUT_CTRL_SCAN_IN_PROG_SEL(x) (((x) & 0x3) << 8) +#define NISTC_AI_OUT_CTRL_EXTMUX_CLK_SEL(x) (((x) & 0x3) << 6) +#define NISTC_AI_OUT_CTRL_LOCALMUX_CLK_SEL(x) (((x) & 0x3) << 4) +#define NISTC_AI_OUT_CTRL_SC_TC_SEL(x) (((x) & 0x3) << 2) +#define NISTC_AI_OUT_CTRL_CONVERT_SEL(x) (((x) & 0x3) << 0) +#define NISTC_AI_OUT_CTRL_CONVERT_HIGH_Z NISTC_AI_OUT_CTRL_CONVERT_SEL(0) +#define NISTC_AI_OUT_CTRL_CONVERT_GND NISTC_AI_OUT_CTRL_CONVERT_SEL(1) +#define NISTC_AI_OUT_CTRL_CONVERT_LOW NISTC_AI_OUT_CTRL_CONVERT_SEL(2) +#define NISTC_AI_OUT_CTRL_CONVERT_HIGH NISTC_AI_OUT_CTRL_CONVERT_SEL(3) + +#define NISTC_ATRIG_ETC_REG 61 +#define NISTC_ATRIG_ETC_GPFO_1_ENA BIT(15) +#define NISTC_ATRIG_ETC_GPFO_0_ENA BIT(14) +#define NISTC_ATRIG_ETC_GPFO_0_SEL(x) (((x) & 0x3) << 11) +#define NISTC_ATRIG_ETC_GPFO_1_SEL BIT(7) +#define NISTC_ATRIG_ETC_DRV BIT(4) +#define NISTC_ATRIG_ETC_ENA BIT(3) +#define NISTC_ATRIG_ETC_MODE(x) (((x) & 0x7) << 0) + +#define NISTC_AI_START_STOP_REG 62 +#define NISTC_AI_START_POLARITY BIT(15) +#define NISTC_AI_STOP_POLARITY BIT(14) +#define NISTC_AI_STOP_SYNC BIT(13) +#define NISTC_AI_STOP_EDGE BIT(12) +#define NISTC_AI_STOP_SEL(x) (((x) & 0x1f) << 7) +#define NISTC_AI_START_SYNC BIT(6) +#define NISTC_AI_START_EDGE BIT(5) +#define NISTC_AI_START_SEL(x) (((x) & 0x1f) << 0) + +#define NISTC_AI_TRIG_SEL_REG 63 +#define NISTC_AI_TRIG_START1_POLARITY BIT(15) +#define NISTC_AI_TRIG_START2_POLARITY BIT(14) +#define NISTC_AI_TRIG_START2_SYNC BIT(13) +#define NISTC_AI_TRIG_START2_EDGE BIT(12) +#define NISTC_AI_TRIG_START2_SEL(x) (((x) & 0x1f) << 7) +#define NISTC_AI_TRIG_START1_SYNC BIT(6) +#define NISTC_AI_TRIG_START1_EDGE BIT(5) +#define NISTC_AI_TRIG_START1_SEL(x) (((x) & 0x1f) << 0) + +#define NISTC_AI_DIV_LOADA_REG 64 + +#define NISTC_AO_START_SEL_REG 66 +#define NISTC_AO_START_UI2_SW_GATE BIT(15) +#define NISTC_AO_START_UI2_EXT_GATE_POL BIT(14) +#define NISTC_AO_START_POLARITY BIT(13) +#define NISTC_AO_START_AOFREQ_ENA BIT(12) +#define NISTC_AO_START_UI2_EXT_GATE_SEL(x) (((x) & 0x1f) << 7) +#define NISTC_AO_START_SYNC BIT(6) +#define NISTC_AO_START_EDGE BIT(5) +#define NISTC_AO_START_SEL(x) (((x) & 0x1f) << 0) + +#define NISTC_AO_TRIG_SEL_REG 67 +#define NISTC_AO_TRIG_UI2_EXT_GATE_ENA BIT(15) +#define NISTC_AO_TRIG_DELAYED_START1 BIT(14) +#define NISTC_AO_TRIG_START1_POLARITY BIT(13) +#define NISTC_AO_TRIG_UI2_SRC_POLARITY BIT(12) +#define NISTC_AO_TRIG_UI2_SRC_SEL(x) (((x) & 0x1f) << 7) +#define NISTC_AO_TRIG_START1_SYNC BIT(6) +#define NISTC_AO_TRIG_START1_EDGE BIT(5) +#define NISTC_AO_TRIG_START1_SEL(x) (((x) & 0x1f) << 0) +#define NISTC_AO_TRIG_START1_SEL_MASK NISTC_AO_TRIG_START1_SEL(0x1f) + +#define NISTC_G0_AUTOINC_REG 68 +#define NISTC_G1_AUTOINC_REG 69 + +#define NISTC_AO_MODE3_REG 70 +#define NISTC_AO_MODE3_UI2_SW_NEXT_TC BIT(13) +#define NISTC_AO_MODE3_UC_SW_EVERY_BC_TC BIT(12) +#define NISTC_AO_MODE3_TRIG_LEN BIT(11) +#define NISTC_AO_MODE3_STOP_ON_OVERRUN_ERR BIT(5) +#define NISTC_AO_MODE3_STOP_ON_BC_TC_TRIG_ERR BIT(4) +#define NISTC_AO_MODE3_STOP_ON_BC_TC_ERR BIT(3) +#define NISTC_AO_MODE3_NOT_AN_UPDATE BIT(2) +#define NISTC_AO_MODE3_SW_GATE BIT(1) +#define NISTC_AO_MODE3_LAST_GATE_DISABLE BIT(0) /* M-Series only */ + +#define NISTC_RESET_REG 72 +#define NISTC_RESET_SOFTWARE BIT(11) +#define NISTC_RESET_AO_CFG_END BIT(9) +#define NISTC_RESET_AI_CFG_END BIT(8) +#define NISTC_RESET_AO_CFG_START BIT(5) +#define NISTC_RESET_AI_CFG_START BIT(4) +#define NISTC_RESET_G1 BIT(3) +#define NISTC_RESET_G0 BIT(2) +#define NISTC_RESET_AO BIT(1) +#define NISTC_RESET_AI BIT(0) + +#define NISTC_INTA_ENA_REG 73 +#define NISTC_INTA2_ENA_REG 74 +#define NISTC_INTA_ENA_PASSTHRU0 BIT(9) +#define NISTC_INTA_ENA_G0_GATE BIT(8) +#define NISTC_INTA_ENA_AI_FIFO BIT(7) +#define NISTC_INTA_ENA_G0_TC BIT(6) +#define NISTC_INTA_ENA_AI_ERR BIT(5) +#define NISTC_INTA_ENA_AI_STOP BIT(4) +#define NISTC_INTA_ENA_AI_START BIT(3) +#define NISTC_INTA_ENA_AI_START2 BIT(2) +#define NISTC_INTA_ENA_AI_START1 BIT(1) +#define NISTC_INTA_ENA_AI_SC_TC BIT(0) +#define NISTC_INTA_ENA_AI_MASK (NISTC_INTA_ENA_AI_FIFO | \ + NISTC_INTA_ENA_AI_ERR | \ + NISTC_INTA_ENA_AI_STOP | \ + NISTC_INTA_ENA_AI_START | \ + NISTC_INTA_ENA_AI_START2 | \ + NISTC_INTA_ENA_AI_START1 | \ + NISTC_INTA_ENA_AI_SC_TC) + +#define NISTC_INTB_ENA_REG 75 +#define NISTC_INTB2_ENA_REG 76 +#define NISTC_INTB_ENA_PASSTHRU1 BIT(11) +#define NISTC_INTB_ENA_G1_GATE BIT(10) +#define NISTC_INTB_ENA_G1_TC BIT(9) +#define NISTC_INTB_ENA_AO_FIFO BIT(8) +#define NISTC_INTB_ENA_AO_UI2_TC BIT(7) +#define NISTC_INTB_ENA_AO_UC_TC BIT(6) +#define NISTC_INTB_ENA_AO_ERR BIT(5) +#define NISTC_INTB_ENA_AO_STOP BIT(4) +#define NISTC_INTB_ENA_AO_START BIT(3) +#define NISTC_INTB_ENA_AO_UPDATE BIT(2) +#define NISTC_INTB_ENA_AO_START1 BIT(1) +#define NISTC_INTB_ENA_AO_BC_TC BIT(0) + +#define NISTC_AI_PERSONAL_REG 77 +#define NISTC_AI_PERSONAL_SHIFTIN_PW BIT(15) +#define NISTC_AI_PERSONAL_EOC_POLARITY BIT(14) +#define NISTC_AI_PERSONAL_SOC_POLARITY BIT(13) +#define NISTC_AI_PERSONAL_SHIFTIN_POL BIT(12) +#define NISTC_AI_PERSONAL_CONVERT_TIMEBASE BIT(11) +#define NISTC_AI_PERSONAL_CONVERT_PW BIT(10) +#define NISTC_AI_PERSONAL_CONVERT_ORIG_PULSE BIT(9) +#define NISTC_AI_PERSONAL_FIFO_FLAGS_POL BIT(8) +#define NISTC_AI_PERSONAL_OVERRUN_MODE BIT(7) +#define NISTC_AI_PERSONAL_EXTMUX_CLK_PW BIT(6) +#define NISTC_AI_PERSONAL_LOCALMUX_CLK_PW BIT(5) +#define NISTC_AI_PERSONAL_AIFREQ_POL BIT(4) + +#define NISTC_AO_PERSONAL_REG 78 +#define NISTC_AO_PERSONAL_MULTI_DACS BIT(15) /* M-Series only */ +#define NISTC_AO_PERSONAL_NUM_DAC BIT(14) /* 1:single; 0:dual */ +#define NISTC_AO_PERSONAL_FAST_CPU BIT(13) /* M-Series reserved */ +#define NISTC_AO_PERSONAL_TMRDACWR_PW BIT(12) +#define NISTC_AO_PERSONAL_FIFO_FLAGS_POL BIT(11) /* M-Series reserved */ +#define NISTC_AO_PERSONAL_FIFO_ENA BIT(10) +#define NISTC_AO_PERSONAL_AOFREQ_POL BIT(9) /* M-Series reserved */ +#define NISTC_AO_PERSONAL_DMA_PIO_CTRL BIT(8) /* M-Series reserved */ +#define NISTC_AO_PERSONAL_UPDATE_ORIG_PULSE BIT(7) +#define NISTC_AO_PERSONAL_UPDATE_TIMEBASE BIT(6) +#define NISTC_AO_PERSONAL_UPDATE_PW BIT(5) +#define NISTC_AO_PERSONAL_BC_SRC_SEL BIT(4) +#define NISTC_AO_PERSONAL_INTERVAL_BUFFER_MODE BIT(3) + +#define NISTC_RTSI_TRIGA_OUT_REG 79 +#define NISTC_RTSI_TRIGB_OUT_REG 80 +#define NISTC_RTSI_TRIGB_SUB_SEL1 BIT(15) /* not for M-Series */ +#define NISTC_RTSI_TRIG(_c, _s) (((_s) & 0xf) << (((_c) % 4) * 4)) +#define NISTC_RTSI_TRIG_MASK(_c) NISTC_RTSI_TRIG((_c), 0xf) +#define NISTC_RTSI_TRIG_TO_SRC(_c, _b) (((_b) >> (((_c) % 4) * 4)) & 0xf) + +#define NISTC_RTSI_BOARD_REG 81 + +#define NISTC_CFG_MEM_CLR_REG 82 +#define NISTC_ADC_FIFO_CLR_REG 83 +#define NISTC_DAC_FIFO_CLR_REG 84 +#define NISTC_WR_STROBE3_REG 85 + +#define NISTC_AO_OUT_CTRL_REG 86 +#define NISTC_AO_OUT_CTRL_EXT_GATE_ENA BIT(15) +#define NISTC_AO_OUT_CTRL_EXT_GATE_SEL(x) (((x) & 0x1f) << 10) +#define NISTC_AO_OUT_CTRL_CHANS(x) (((x) & 0xf) << 6) +#define NISTC_AO_OUT_CTRL_UPDATE2_SEL(x) (((x) & 0x3) << 4) +#define NISTC_AO_OUT_CTRL_EXT_GATE_POL BIT(3) +#define NISTC_AO_OUT_CTRL_UPDATE2_TOGGLE BIT(2) +#define NISTC_AO_OUT_CTRL_UPDATE_SEL(x) (((x) & 0x3) << 0) +#define NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ NISTC_AO_OUT_CTRL_UPDATE_SEL(0) +#define NISTC_AO_OUT_CTRL_UPDATE_SEL_GND NISTC_AO_OUT_CTRL_UPDATE_SEL(1) +#define NISTC_AO_OUT_CTRL_UPDATE_SEL_LOW NISTC_AO_OUT_CTRL_UPDATE_SEL(2) +#define NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGH NISTC_AO_OUT_CTRL_UPDATE_SEL(3) + +#define NISTC_AI_MODE3_REG 87 +#define NISTC_AI_MODE3_TRIG_LEN BIT(15) +#define NISTC_AI_MODE3_DELAY_START BIT(14) +#define NISTC_AI_MODE3_SOFTWARE_GATE BIT(13) +#define NISTC_AI_MODE3_SI_TRIG_DELAY BIT(12) +#define NISTC_AI_MODE3_SI2_SRC_SEL BIT(11) +#define NISTC_AI_MODE3_DELAYED_START2 BIT(10) +#define NISTC_AI_MODE3_DELAYED_START1 BIT(9) +#define NISTC_AI_MODE3_EXT_GATE_MODE BIT(8) +#define NISTC_AI_MODE3_FIFO_MODE(x) (((x) & 0x3) << 6) +#define NISTC_AI_MODE3_FIFO_MODE_NE NISTC_AI_MODE3_FIFO_MODE(0) +#define NISTC_AI_MODE3_FIFO_MODE_HF NISTC_AI_MODE3_FIFO_MODE(1) +#define NISTC_AI_MODE3_FIFO_MODE_F NISTC_AI_MODE3_FIFO_MODE(2) +#define NISTC_AI_MODE3_FIFO_MODE_HF_E NISTC_AI_MODE3_FIFO_MODE(3) +#define NISTC_AI_MODE3_EXT_GATE_POL BIT(5) +#define NISTC_AI_MODE3_EXT_GATE_SEL(x) (((x) & 0x1f) << 0) + +#define NISTC_AI_STATUS1_REG 2 +#define NISTC_AI_STATUS1_INTA BIT(15) +#define NISTC_AI_STATUS1_FIFO_F BIT(14) +#define NISTC_AI_STATUS1_FIFO_HF BIT(13) +#define NISTC_AI_STATUS1_FIFO_E BIT(12) +#define NISTC_AI_STATUS1_OVERRUN BIT(11) +#define NISTC_AI_STATUS1_OVERFLOW BIT(10) +#define NISTC_AI_STATUS1_SC_TC_ERR BIT(9) +#define NISTC_AI_STATUS1_OVER (NISTC_AI_STATUS1_OVERRUN | \ + NISTC_AI_STATUS1_OVERFLOW) +#define NISTC_AI_STATUS1_ERR (NISTC_AI_STATUS1_OVER | \ + NISTC_AI_STATUS1_SC_TC_ERR) +#define NISTC_AI_STATUS1_START2 BIT(8) +#define NISTC_AI_STATUS1_START1 BIT(7) +#define NISTC_AI_STATUS1_SC_TC BIT(6) +#define NISTC_AI_STATUS1_START BIT(5) +#define NISTC_AI_STATUS1_STOP BIT(4) +#define NISTC_AI_STATUS1_G0_TC BIT(3) +#define NISTC_AI_STATUS1_G0_GATE BIT(2) +#define NISTC_AI_STATUS1_FIFO_REQ BIT(1) +#define NISTC_AI_STATUS1_PASSTHRU0 BIT(0) + +#define NISTC_AO_STATUS1_REG 3 +#define NISTC_AO_STATUS1_INTB BIT(15) +#define NISTC_AO_STATUS1_FIFO_F BIT(14) +#define NISTC_AO_STATUS1_FIFO_HF BIT(13) +#define NISTC_AO_STATUS1_FIFO_E BIT(12) +#define NISTC_AO_STATUS1_BC_TC_ERR BIT(11) +#define NISTC_AO_STATUS1_START BIT(10) +#define NISTC_AO_STATUS1_OVERRUN BIT(9) +#define NISTC_AO_STATUS1_START1 BIT(8) +#define NISTC_AO_STATUS1_BC_TC BIT(7) +#define NISTC_AO_STATUS1_UC_TC BIT(6) +#define NISTC_AO_STATUS1_UPDATE BIT(5) +#define NISTC_AO_STATUS1_UI2_TC BIT(4) +#define NISTC_AO_STATUS1_G1_TC BIT(3) +#define NISTC_AO_STATUS1_G1_GATE BIT(2) +#define NISTC_AO_STATUS1_FIFO_REQ BIT(1) +#define NISTC_AO_STATUS1_PASSTHRU1 BIT(0) + +#define NISTC_G01_STATUS_REG 4 + +#define NISTC_AI_STATUS2_REG 5 + +#define NISTC_AO_STATUS2_REG 6 + +#define NISTC_DIO_IN_REG 7 + +#define NISTC_G0_HW_SAVE_REG 8 +#define NISTC_G1_HW_SAVE_REG 10 + +#define NISTC_G0_SAVE_REG 12 +#define NISTC_G1_SAVE_REG 14 + +#define NISTC_AO_UI_SAVE_REG 16 +#define NISTC_AO_BC_SAVE_REG 18 +#define NISTC_AO_UC_SAVE_REG 20 + +#define NISTC_STATUS1_REG 27 +#define NISTC_STATUS1_SERIO_IN_PROG BIT(12) + +#define NISTC_DIO_SERIAL_IN_REG 28 + +#define NISTC_STATUS2_REG 29 +#define NISTC_STATUS2_AO_TMRDACWRS_IN_PROGRESS BIT(5) + +#define NISTC_AI_SI_SAVE_REG 64 +#define NISTC_AI_SC_SAVE_REG 66 -#define Second_IRQ_B_Enable_Register 76 -enum Second_IRQ_B_Enable_Bits { - AO_BC_TC_Second_Irq_Enable = _bit0, - AO_START1_Second_Irq_Enable = _bit1, - AO_UPDATE_Second_Irq_Enable = _bit2, - AO_START_Second_Irq_Enable = _bit3, - AO_STOP_Second_Irq_Enable = _bit4, - AO_Error_Second_Irq_Enable = _bit5, - AO_UC_TC_Second_Irq_Enable = _bit6, - AO_UI2_TC_Second_Irq_Enable = _bit7, - AO_FIFO_Second_Irq_Enable = _bit8, - G1_TC_Second_Irq_Enable = _bit9, - G1_Gate_Second_Irq_Enable = _bit10, - Pass_Thru_1_Second_Irq_Enable = _bit11 -}; +/* + * PCI E Series Registers + */ +#define NI_E_STC_WINDOW_ADDR_REG 0x00 /* rw16 */ +#define NI_E_STC_WINDOW_DATA_REG 0x02 /* rw16 */ + +#define NI_E_STATUS_REG 0x01 /* r8 */ +#define NI_E_STATUS_AI_FIFO_LOWER_NE BIT(3) +#define NI_E_STATUS_PROMOUT BIT(0) + +#define NI_E_DMA_AI_AO_SEL_REG 0x09 /* w8 */ +#define NI_E_DMA_AI_SEL(x) (((x) & 0xf) << 0) +#define NI_E_DMA_AI_SEL_MASK NI_E_DMA_AI_SEL(0xf) +#define NI_E_DMA_AO_SEL(x) (((x) & 0xf) << 4) +#define NI_E_DMA_AO_SEL_MASK NI_E_DMA_AO_SEL(0xf) + +#define NI_E_DMA_G0_G1_SEL_REG 0x0b /* w8 */ +#define NI_E_DMA_G0_G1_SEL(_g, _c) (((_c) & 0xf) << ((_g) * 4)) +#define NI_E_DMA_G0_G1_SEL_MASK(_g) NI_E_DMA_G0_G1_SEL((_g), 0xf) + +#define NI_E_SERIAL_CMD_REG 0x0d /* w8 */ +#define NI_E_SERIAL_CMD_DAC_LD(x) BIT(3 + (x)) +#define NI_E_SERIAL_CMD_EEPROM_CS BIT(2) +#define NI_E_SERIAL_CMD_SDATA BIT(1) +#define NI_E_SERIAL_CMD_SCLK BIT(0) + +#define NI_E_MISC_CMD_REG 0x0f /* w8 */ +#define NI_E_MISC_CMD_INTEXT_ATRIG(x) (((x) & 0x1) << 7) +#define NI_E_MISC_CMD_EXT_ATRIG NI_E_MISC_CMD_INTEXT_ATRIG(0) +#define NI_E_MISC_CMD_INT_ATRIG NI_E_MISC_CMD_INTEXT_ATRIG(1) + +#define NI_E_AI_CFG_LO_REG 0x10 /* w16 */ +#define NI_E_AI_CFG_LO_LAST_CHAN BIT(15) +#define NI_E_AI_CFG_LO_GEN_TRIG BIT(12) +#define NI_E_AI_CFG_LO_DITHER BIT(9) +#define NI_E_AI_CFG_LO_UNI BIT(8) +#define NI_E_AI_CFG_LO_GAIN(x) ((x) << 0) + +#define NI_E_AI_CFG_HI_REG 0x12 /* w16 */ +#define NI_E_AI_CFG_HI_TYPE(x) (((x) & 0x7) << 12) +#define NI_E_AI_CFG_HI_TYPE_DIFF NI_E_AI_CFG_HI_TYPE(1) +#define NI_E_AI_CFG_HI_TYPE_COMMON NI_E_AI_CFG_HI_TYPE(2) +#define NI_E_AI_CFG_HI_TYPE_GROUND NI_E_AI_CFG_HI_TYPE(3) +#define NI_E_AI_CFG_HI_AC_COUPLE BIT(11) +#define NI_E_AI_CFG_HI_CHAN(x) (((x) & 0x3f) << 0) + +#define NI_E_AO_CFG_REG 0x16 /* w16 */ +#define NI_E_AO_DACSEL(x) ((x) << 8) +#define NI_E_AO_GROUND_REF BIT(3) +#define NI_E_AO_EXT_REF BIT(2) +#define NI_E_AO_DEGLITCH BIT(1) +#define NI_E_AO_CFG_BIP BIT(0) + +#define NI_E_DAC_DIRECT_DATA_REG(x) (0x18 + ((x) * 2)) /* w16 */ + +#define NI_E_8255_BASE 0x19 /* rw8 */ + +#define NI_E_AI_FIFO_DATA_REG 0x1c /* r16 */ + +#define NI_E_AO_FIFO_DATA_REG 0x1e /* w16 */ -#define AI_Personal_Register 77 -#define AI_SHIFTIN_Pulse_Width _bit15 -#define AI_EOC_Polarity _bit14 -#define AI_SOC_Polarity _bit13 -#define AI_SHIFTIN_Polarity _bit12 -#define AI_CONVERT_Pulse_Timebase _bit11 -#define AI_CONVERT_Pulse_Width _bit10 -#define AI_CONVERT_Original_Pulse _bit9 -#define AI_FIFO_Flags_Polarity _bit8 -#define AI_Overrun_Mode _bit7 -#define AI_EXTMUX_CLK_Pulse_Width _bit6 -#define AI_LOCALMUX_CLK_Pulse_Width _bit5 -#define AI_AIFREQ_Polarity _bit4 - -#define AO_Personal_Register 78 -enum AO_Personal_Bits { - AO_Interval_Buffer_Mode = 1 << 3, - AO_BC_Source_Select = 1 << 4, - AO_UPDATE_Pulse_Width = 1 << 5, - AO_UPDATE_Pulse_Timebase = 1 << 6, - AO_UPDATE_Original_Pulse = 1 << 7, - AO_DMA_PIO_Control = 1 << 8, /* M Series: reserved */ - AO_AOFREQ_Polarity = 1 << 9, /* M Series: reserved */ - AO_FIFO_Enable = 1 << 10, - AO_FIFO_Flags_Polarity = 1 << 11, /* M Series: reserved */ - AO_TMRDACWR_Pulse_Width = 1 << 12, - AO_Fast_CPU = 1 << 13, /* M Series: reserved */ - AO_Number_Of_DAC_Packages = 1 << 14, /* 1 for "single" mode, 0 for "dual" */ - AO_Multiple_DACS_Per_Package = 1 << 15 /* m-series only */ -}; -#define RTSI_Trig_A_Output_Register 79 -#define RTSI_Trig_B_Output_Register 80 -enum RTSI_Trig_B_Output_Bits { - RTSI_Sub_Selection_1_Bit = 0x8000 /* not for m-series */ -}; -static inline unsigned RTSI_Trig_Output_Bits(unsigned rtsi_channel, - unsigned source) -{ - return (source & 0xf) << ((rtsi_channel % 4) * 4); -}; +/* + * 611x registers (these boards differ from the e-series) + */ +#define NI611X_MAGIC_REG 0x19 /* w8 (new) */ +#define NI611X_CALIB_CHAN_SEL_REG 0x1a /* w16 (new) */ +#define NI611X_AI_FIFO_DATA_REG 0x1c /* r32 (incompatible) */ +#define NI611X_AI_FIFO_OFFSET_LOAD_REG 0x05 /* r8 (new) */ +#define NI611X_AO_FIFO_DATA_REG 0x14 /* w32 (incompatible) */ +#define NI611X_CAL_GAIN_SEL_REG 0x05 /* w8 (new) */ + +#define NI611X_AO_WINDOW_ADDR_REG 0x18 +#define NI611X_AO_WINDOW_DATA_REG 0x1e -static inline unsigned RTSI_Trig_Output_Mask(unsigned rtsi_channel) -{ - return 0xf << ((rtsi_channel % 4) * 4); -}; +/* + * 6143 registers + */ +#define NI6143_MAGIC_REG 0x19 /* w8 */ +#define NI6143_DMA_G0_G1_SEL_REG 0x0b /* w8 */ +#define NI6143_PIPELINE_DELAY_REG 0x1f /* w8 */ +#define NI6143_EOC_SET_REG 0x1d /* w8 */ +#define NI6143_DMA_AI_SEL_REG 0x09 /* w8 */ +#define NI6143_AI_FIFO_DATA_REG 0x8c /* r32 */ +#define NI6143_AI_FIFO_FLAG_REG 0x84 /* w32 */ +#define NI6143_AI_FIFO_CTRL_REG 0x88 /* w32 */ +#define NI6143_AI_FIFO_STATUS_REG 0x88 /* r32 */ +#define NI6143_AI_FIFO_DMA_THRESH_REG 0x90 /* w32 */ +#define NI6143_AI_FIFO_WORDS_AVAIL_REG 0x94 /* w32 */ + +#define NI6143_CALIB_CHAN_REG 0x42 /* w16 */ +#define NI6143_CALIB_CHAN_RELAY_ON BIT(15) +#define NI6143_CALIB_CHAN_RELAY_OFF BIT(14) +#define NI6143_CALIB_CHAN(x) (((x) & 0xf) << 0) +#define NI6143_CALIB_CHAN_GND_GND NI6143_CALIB_CHAN(0) /* Offset Cal */ +#define NI6143_CALIB_CHAN_2V5_GND NI6143_CALIB_CHAN(2) /* 2.5V ref */ +#define NI6143_CALIB_CHAN_PWM_GND NI6143_CALIB_CHAN(5) /* +-5V Self Cal */ +#define NI6143_CALIB_CHAN_2V5_PWM NI6143_CALIB_CHAN(10) /* PWM Cal */ +#define NI6143_CALIB_CHAN_PWM_PWM NI6143_CALIB_CHAN(13) /* CMRR */ +#define NI6143_CALIB_CHAN_GND_PWM NI6143_CALIB_CHAN(14) /* PWM Cal */ +#define NI6143_CALIB_LO_TIME_REG 0x20 /* w16 */ +#define NI6143_CALIB_HI_TIME_REG 0x22 /* w16 */ +#define NI6143_RELAY_COUNTER_LOAD_REG 0x4c /* w32 */ +#define NI6143_SIGNATURE_REG 0x50 /* w32 */ +#define NI6143_RELEASE_DATE_REG 0x54 /* w32 */ +#define NI6143_RELEASE_OLDEST_DATE_REG 0x58 /* w32 */ -/* inverse to RTSI_Trig_Output_Bits() */ -static inline unsigned RTSI_Trig_Output_Source(unsigned rtsi_channel, - unsigned bits) -{ - return (bits >> ((rtsi_channel % 4) * 4)) & 0xf; -}; +/* + * 671x, 611x windowed ao registers + */ +#define NI671X_DAC_DIRECT_DATA_REG(x) (0x00 + (x)) /* w16 */ +#define NI611X_AO_TIMED_REG 0x10 /* w16 */ +#define NI671X_AO_IMMEDIATE_REG 0x11 /* w16 */ +#define NI611X_AO_FIFO_OFFSET_LOAD_REG 0x13 /* w32 */ +#define NI67XX_AO_SP_UPDATES_REG 0x14 /* w16 */ +#define NI611X_AO_WAVEFORM_GEN_REG 0x15 /* w16 */ +#define NI611X_AO_MISC_REG 0x16 /* w16 */ +#define NI611X_AO_MISC_CLEAR_WG BIT(0) +#define NI67XX_AO_CAL_CHAN_SEL_REG 0x17 /* w16 */ +#define NI67XX_AO_CFG2_REG 0x18 /* w16 */ +#define NI67XX_CAL_CMD_REG 0x19 /* w16 */ +#define NI67XX_CAL_STATUS_REG 0x1a /* r8 */ +#define NI67XX_CAL_STATUS_BUSY BIT(0) +#define NI67XX_CAL_STATUS_OSC_DETECT BIT(1) +#define NI67XX_CAL_STATUS_OVERRANGE BIT(2) +#define NI67XX_CAL_DATA_REG 0x1b /* r16 */ +#define NI67XX_CAL_CFG_HI_REG 0x1c /* rw16 */ +#define NI67XX_CAL_CFG_LO_REG 0x1d /* rw16 */ + +#define CS5529_CMD_CB BIT(7) +#define CS5529_CMD_SINGLE_CONV BIT(6) +#define CS5529_CMD_CONT_CONV BIT(5) +#define CS5529_CMD_READ BIT(4) +#define CS5529_CMD_REG(x) (((x) & 0x7) << 1) +#define CS5529_CMD_REG_MASK CS5529_CMD_REG(7) +#define CS5529_CMD_PWR_SAVE BIT(0) + +#define CS5529_OFFSET_REG CS5529_CMD_REG(0) +#define CS5529_GAIN_REG CS5529_CMD_REG(1) +#define CS5529_CONV_DATA_REG CS5529_CMD_REG(3) +#define CS5529_SETUP_REG CS5529_CMD_REG(4) + +#define CS5529_CFG_REG CS5529_CMD_REG(2) +#define CS5529_CFG_AOUT(x) BIT(22 + (x)) +#define CS5529_CFG_DOUT(x) BIT(18 + (x)) +#define CS5529_CFG_LOW_PWR_MODE BIT(16) +#define CS5529_CFG_WORD_RATE(x) (((x) & 0x7) << 13) +#define CS5529_CFG_WORD_RATE_MASK CS5529_CFG_WORD_RATE(0x7) +#define CS5529_CFG_WORD_RATE_2180 CS5529_CFG_WORD_RATE(0) +#define CS5529_CFG_WORD_RATE_1092 CS5529_CFG_WORD_RATE(1) +#define CS5529_CFG_WORD_RATE_532 CS5529_CFG_WORD_RATE(2) +#define CS5529_CFG_WORD_RATE_388 CS5529_CFG_WORD_RATE(3) +#define CS5529_CFG_WORD_RATE_324 CS5529_CFG_WORD_RATE(4) +#define CS5529_CFG_WORD_RATE_17444 CS5529_CFG_WORD_RATE(5) +#define CS5529_CFG_WORD_RATE_8724 CS5529_CFG_WORD_RATE(6) +#define CS5529_CFG_WORD_RATE_4364 CS5529_CFG_WORD_RATE(7) +#define CS5529_CFG_UNIPOLAR BIT(12) +#define CS5529_CFG_RESET BIT(7) +#define CS5529_CFG_RESET_VALID BIT(6) +#define CS5529_CFG_PORT_FLAG BIT(5) +#define CS5529_CFG_PWR_SAVE_SEL BIT(4) +#define CS5529_CFG_DONE_FLAG BIT(3) +#define CS5529_CFG_CALIB(x) (((x) & 0x7) << 0) +#define CS5529_CFG_CALIB_NONE CS5529_CFG_CALIB(0) +#define CS5529_CFG_CALIB_OFFSET_SELF CS5529_CFG_CALIB(1) +#define CS5529_CFG_CALIB_GAIN_SELF CS5529_CFG_CALIB(2) +#define CS5529_CFG_CALIB_BOTH_SELF CS5529_CFG_CALIB(3) +#define CS5529_CFG_CALIB_OFFSET_SYS CS5529_CFG_CALIB(5) +#define CS5529_CFG_CALIB_GAIN_SYS CS5529_CFG_CALIB(6) -#define RTSI_Board_Register 81 -#define Write_Strobe_0_Register 82 -#define Write_Strobe_1_Register 83 -#define Write_Strobe_2_Register 84 -#define Write_Strobe_3_Register 85 - -#define AO_Output_Control_Register 86 -#define AO_External_Gate_Enable _bit15 -#define AO_External_Gate_Select(x) (((x)&0x1f)<<10) -#define AO_Number_Of_Channels(x) (((x)&0xf)<<6) -#define AO_UPDATE2_Output_Select(x) (((x)&0x3)<<4) -#define AO_External_Gate_Polarity _bit3 -#define AO_UPDATE2_Output_Toggle _bit2 -enum ao_update_output_selection { - AO_Update_Output_High_Z = 0, - AO_Update_Output_Ground = 1, - AO_Update_Output_Enable_Low = 2, - AO_Update_Output_Enable_High = 3 -}; -static unsigned AO_UPDATE_Output_Select(enum ao_update_output_selection - selection) -{ - return selection & 0x3; -} - -#define AI_Mode_3_Register 87 -#define AI_Trigger_Length _bit15 -#define AI_Delay_START _bit14 -#define AI_Software_Gate _bit13 -#define AI_SI_Special_Trigger_Delay _bit12 -#define AI_SI2_Source_Select _bit11 -#define AI_Delayed_START2 _bit10 -#define AI_Delayed_START1 _bit9 -#define AI_External_Gate_Mode _bit8 -#define AI_FIFO_Mode_HF_to_E (3<<6) -#define AI_FIFO_Mode_F (2<<6) -#define AI_FIFO_Mode_HF (1<<6) -#define AI_FIFO_Mode_NE (0<<6) -#define AI_External_Gate_Polarity _bit5 -#define AI_External_Gate_Select(a) ((a) & 0x1f) - -#define G_Autoincrement_Register(a) (68+(a)) -#define G_Command_Register(a) (6+(a)) -#define G_HW_Save_Register(a) (8+(a)*2) -#define G_HW_Save_Register_High(a) (8+(a)*2) -#define G_HW_Save_Register_Low(a) (9+(a)*2) -#define G_Input_Select_Register(a) (36+(a)) -#define G_Load_A_Register(a) (28+(a)*4) -#define G_Load_A_Register_High(a) (28+(a)*4) -#define G_Load_A_Register_Low(a) (29+(a)*4) -#define G_Load_B_Register(a) (30+(a)*4) -#define G_Load_B_Register_High(a) (30+(a)*4) -#define G_Load_B_Register_Low(a) (31+(a)*4) -#define G_Mode_Register(a) (26+(a)) -#define G_Save_Register(a) (12+(a)*2) -#define G_Save_Register_High(a) (12+(a)*2) -#define G_Save_Register_Low(a) (13+(a)*2) -#define G_Status_Register 4 -#define Analog_Trigger_Etc_Register 61 - -/* command register */ -#define G_Disarm_Copy _bit15 /* strobe */ -#define G_Save_Trace_Copy _bit14 -#define G_Arm_Copy _bit13 /* strobe */ -#define G_Bank_Switch_Start _bit10 /* strobe */ -#define G_Little_Big_Endian _bit9 -#define G_Synchronized_Gate _bit8 -#define G_Write_Switch _bit7 -#define G_Up_Down(a) (((a)&0x03)<<5) -#define G_Disarm _bit4 /* strobe */ -#define G_Analog_Trigger_Reset _bit3 /* strobe */ -#define G_Save_Trace _bit1 -#define G_Arm _bit0 /* strobe */ - -/*channel agnostic names for the command register #defines */ -#define G_Bank_Switch_Enable _bit12 -#define G_Bank_Switch_Mode _bit11 -#define G_Load _bit2 /* strobe */ - -/* input select register */ -#define G_Gate_Select(a) (((a)&0x1f)<<7) -#define G_Source_Select(a) (((a)&0x1f)<<2) -#define G_Write_Acknowledges_Irq _bit1 -#define G_Read_Acknowledges_Irq _bit0 - -/* same input select register, but with channel agnostic names */ -#define G_Source_Polarity _bit15 -#define G_Output_Polarity _bit14 -#define G_OR_Gate _bit13 -#define G_Gate_Select_Load_Source _bit12 - -/* mode register */ -#define G_Loading_On_TC _bit12 -#define G_Output_Mode(a) (((a)&0x03)<<8) -#define G_Trigger_Mode_For_Edge_Gate(a) (((a)&0x03)<<3) -#define G_Gating_Mode(a) (((a)&0x03)<<0) - -/* same input mode register, but with channel agnostic names */ -#define G_Load_Source_Select _bit7 -#define G_Reload_Source_Switching _bit15 -#define G_Loading_On_Gate _bit14 -#define G_Gate_Polarity _bit13 - -#define G_Counting_Once(a) (((a)&0x03)<<10) -#define G_Stop_Mode(a) (((a)&0x03)<<5) -#define G_Gate_On_Both_Edges _bit2 - -/* G_Status_Register */ -#define G1_Gate_Error_St _bit15 -#define G0_Gate_Error_St _bit14 -#define G1_TC_Error_St _bit13 -#define G0_TC_Error_St _bit12 -#define G1_No_Load_Between_Gates_St _bit11 -#define G0_No_Load_Between_Gates_St _bit10 -#define G1_Armed_St _bit9 -#define G0_Armed_St _bit8 -#define G1_Stale_Data_St _bit7 -#define G0_Stale_Data_St _bit6 -#define G1_Next_Load_Source_St _bit5 -#define G0_Next_Load_Source_St _bit4 -#define G1_Counting_St _bit3 -#define G0_Counting_St _bit2 -#define G1_Save_St _bit1 -#define G0_Save_St _bit0 - -/* general purpose counter timer */ -#define G_Autoincrement(a) ((a)<<0) - -/*Analog_Trigger_Etc_Register*/ -#define Analog_Trigger_Mode(x) ((x) & 0x7) -#define Analog_Trigger_Enable _bit3 -#define Analog_Trigger_Drive _bit4 -#define GPFO_1_Output_Select _bit7 -#define GPFO_0_Output_Select(a) ((a)<<11) -#define GPFO_0_Output_Enable _bit14 -#define GPFO_1_Output_Enable _bit15 - -/* Additional windowed registers unique to E series */ - -/* 16 bit registers shadowed from DAQ-STC */ -#define Window_Address 0x00 -#define Window_Data 0x02 - -#define Configuration_Memory_Clear 82 -#define ADC_FIFO_Clear 83 -#define DAC_FIFO_Clear 84 - -/* i/o port offsets */ - -/* 8 bit registers */ -#define XXX_Status 0x01 -enum XXX_Status_Bits { - PROMOUT = 0x1, - AI_FIFO_LOWER_NOT_EMPTY = 0x8, -}; -#define Serial_Command 0x0d -#define Misc_Command 0x0f -#define Port_A 0x19 -#define Port_B 0x1b -#define Port_C 0x1d -#define Configuration 0x1f -#define Strobes 0x01 -#define Channel_A_Mode 0x03 -#define Channel_B_Mode 0x05 -#define Channel_C_Mode 0x07 -#define AI_AO_Select 0x09 -enum AI_AO_Select_Bits { - AI_DMA_Select_Shift = 0, - AI_DMA_Select_Mask = 0xf, - AO_DMA_Select_Shift = 4, - AO_DMA_Select_Mask = 0xf << AO_DMA_Select_Shift -}; -#define G0_G1_Select 0x0b -static inline unsigned ni_stc_dma_channel_select_bitfield(unsigned channel) -{ - if (channel < 4) - return 1 << channel; - if (channel == 4) - return 0x3; - if (channel == 5) - return 0x5; - BUG(); - return 0; -} - -static inline unsigned GPCT_DMA_Select_Bits(unsigned gpct_index, - unsigned mite_channel) -{ - BUG_ON(gpct_index > 1); - return ni_stc_dma_channel_select_bitfield(mite_channel) << (4 * - gpct_index); -} - -static inline unsigned GPCT_DMA_Select_Mask(unsigned gpct_index) -{ - BUG_ON(gpct_index > 1); - return 0xf << (4 * gpct_index); -} - -/* 16 bit registers */ - -#define Configuration_Memory_Low 0x10 -enum Configuration_Memory_Low_Bits { - AI_DITHER = 0x200, - AI_LAST_CHANNEL = 0x8000, -}; -#define Configuration_Memory_High 0x12 -enum Configuration_Memory_High_Bits { - AI_AC_COUPLE = 0x800, - AI_DIFFERENTIAL = 0x1000, - AI_COMMON = 0x2000, - AI_GROUND = 0x3000, -}; -static inline unsigned int AI_CONFIG_CHANNEL(unsigned int channel) -{ - return channel & 0x3f; -} - -#define ADC_FIFO_Data_Register 0x1c - -#define AO_Configuration 0x16 -#define AO_Bipolar _bit0 -#define AO_Deglitch _bit1 -#define AO_Ext_Ref _bit2 -#define AO_Ground_Ref _bit3 -#define AO_Channel(x) ((x) << 8) - -#define DAC_FIFO_Data 0x1e -#define DAC0_Direct_Data 0x18 -#define DAC1_Direct_Data 0x1a - -/* 611x registers (these boards differ from the e-series) */ - -#define Magic_611x 0x19 /* w8 (new) */ -#define Calibration_Channel_Select_611x 0x1a /* w16 (new) */ -#define ADC_FIFO_Data_611x 0x1c /* r32 (incompatible) */ -#define AI_FIFO_Offset_Load_611x 0x05 /* r8 (new) */ -#define DAC_FIFO_Data_611x 0x14 /* w32 (incompatible) */ -#define Cal_Gain_Select_611x 0x05 /* w8 (new) */ - -#define AO_Window_Address_611x 0x18 -#define AO_Window_Data_611x 0x1e - -/* 6143 registers */ -#define Magic_6143 0x19 /* w8 */ -#define G0G1_DMA_Select_6143 0x0B /* w8 */ -#define PipelineDelay_6143 0x1f /* w8 */ -#define EOC_Set_6143 0x1D /* w8 */ -#define AIDMA_Select_6143 0x09 /* w8 */ -#define AIFIFO_Data_6143 0x8C /* w32 */ -#define AIFIFO_Flag_6143 0x84 /* w32 */ -#define AIFIFO_Control_6143 0x88 /* w32 */ -#define AIFIFO_Status_6143 0x88 /* w32 */ -#define AIFIFO_DMAThreshold_6143 0x90 /* w32 */ -#define AIFIFO_Words_Available_6143 0x94 /* w32 */ - -#define Calibration_Channel_6143 0x42 /* w16 */ -#define Calibration_LowTime_6143 0x20 /* w16 */ -#define Calibration_HighTime_6143 0x22 /* w16 */ -#define Relay_Counter_Load_Val__6143 0x4C /* w32 */ -#define Signature_6143 0x50 /* w32 */ -#define Release_Date_6143 0x54 /* w32 */ -#define Release_Oldest_Date_6143 0x58 /* w32 */ - -#define Calibration_Channel_6143_RelayOn 0x8000 /* Calibration relay switch On */ -#define Calibration_Channel_6143_RelayOff 0x4000 /* Calibration relay switch Off */ -#define Calibration_Channel_Gnd_Gnd 0x00 /* Offset Calibration */ -#define Calibration_Channel_2v5_Gnd 0x02 /* 2.5V Reference */ -#define Calibration_Channel_Pwm_Gnd 0x05 /* +/- 5V Self Cal */ -#define Calibration_Channel_2v5_Pwm 0x0a /* PWM Calibration */ -#define Calibration_Channel_Pwm_Pwm 0x0d /* CMRR */ -#define Calibration_Channel_Gnd_Pwm 0x0e /* PWM Calibration */ - -/* 671x, 611x registers */ - -/* 671xi, 611x windowed ao registers */ -enum windowed_regs_67xx_61xx { - AO_Immediate_671x = 0x11, /* W 16 */ - AO_Timed_611x = 0x10, /* W 16 */ - AO_FIFO_Offset_Load_611x = 0x13, /* W32 */ - AO_Later_Single_Point_Updates = 0x14, /* W 16 */ - AO_Waveform_Generation_611x = 0x15, /* W 16 */ - AO_Misc_611x = 0x16, /* W 16 */ - AO_Calibration_Channel_Select_67xx = 0x17, /* W 16 */ - AO_Configuration_2_67xx = 0x18, /* W 16 */ - CAL_ADC_Command_67xx = 0x19, /* W 8 */ - CAL_ADC_Status_67xx = 0x1a, /* R 8 */ - CAL_ADC_Data_67xx = 0x1b, /* R 16 */ - CAL_ADC_Config_Data_High_Word_67xx = 0x1c, /* RW 16 */ - CAL_ADC_Config_Data_Low_Word_67xx = 0x1d, /* RW 16 */ +/* + * M-Series specific registers not handled by the DAQ-STC and GPCT register + * remapping. + */ +#define NI_M_CDIO_DMA_SEL_REG 0x007 +#define NI_M_CDIO_DMA_SEL_CDO(x) (((x) & 0xf) << 4) +#define NI_M_CDIO_DMA_SEL_CDO_MASK NI_M_CDIO_DMA_SEL_CDO(0xf) +#define NI_M_CDIO_DMA_SEL_CDI(x) (((x) & 0xf) << 0) +#define NI_M_CDIO_DMA_SEL_CDI_MASK NI_M_CDIO_DMA_SEL_CDI(0xf) +#define NI_M_SCXI_STATUS_REG 0x007 +#define NI_M_AI_AO_SEL_REG 0x009 +#define NI_M_G0_G1_SEL_REG 0x00b +#define NI_M_MISC_CMD_REG 0x00f +#define NI_M_SCXI_SER_DO_REG 0x011 +#define NI_M_SCXI_CTRL_REG 0x013 +#define NI_M_SCXI_OUT_ENA_REG 0x015 +#define NI_M_AI_FIFO_DATA_REG 0x01c +#define NI_M_DIO_REG 0x024 +#define NI_M_DIO_DIR_REG 0x028 +#define NI_M_CAL_PWM_REG 0x040 +#define NI_M_CAL_PWM_HIGH_TIME(x) (((x) & 0xffff) << 16) +#define NI_M_CAL_PWM_LOW_TIME(x) (((x) & 0xffff) << 0) +#define NI_M_GEN_PWM_REG(x) (0x044 + ((x) * 2)) +#define NI_M_AI_CFG_FIFO_DATA_REG 0x05e +#define NI_M_AI_CFG_LAST_CHAN BIT(14) +#define NI_M_AI_CFG_DITHER BIT(13) +#define NI_M_AI_CFG_POLARITY BIT(12) +#define NI_M_AI_CFG_GAIN(x) (((x) & 0x7) << 9) +#define NI_M_AI_CFG_CHAN_TYPE(x) (((x) & 0x7) << 6) +#define NI_M_AI_CFG_CHAN_TYPE_MASK NI_M_AI_CFG_CHAN_TYPE(7) +#define NI_M_AI_CFG_CHAN_TYPE_CALIB NI_M_AI_CFG_CHAN_TYPE(0) +#define NI_M_AI_CFG_CHAN_TYPE_DIFF NI_M_AI_CFG_CHAN_TYPE(1) +#define NI_M_AI_CFG_CHAN_TYPE_COMMON NI_M_AI_CFG_CHAN_TYPE(2) +#define NI_M_AI_CFG_CHAN_TYPE_GROUND NI_M_AI_CFG_CHAN_TYPE(3) +#define NI_M_AI_CFG_CHAN_TYPE_AUX NI_M_AI_CFG_CHAN_TYPE(5) +#define NI_M_AI_CFG_CHAN_TYPE_GHOST NI_M_AI_CFG_CHAN_TYPE(7) +#define NI_M_AI_CFG_BANK_SEL(x) ((((x) & 0x40) << 4) | ((x) & 0x30)) +#define NI_M_AI_CFG_CHAN_SEL(x) (((x) & 0xf) << 0) +#define NI_M_INTC_ENA_REG 0x088 +#define NI_M_INTC_ENA BIT(0) +#define NI_M_INTC_STATUS_REG 0x088 +#define NI_M_INTC_STATUS BIT(0) +#define NI_M_ATRIG_CTRL_REG 0x08c +#define NI_M_AO_SER_INT_ENA_REG 0x0a0 +#define NI_M_AO_SER_INT_ACK_REG 0x0a1 +#define NI_M_AO_SER_INT_STATUS_REG 0x0a1 +#define NI_M_AO_CALIB_REG 0x0a3 +#define NI_M_AO_FIFO_DATA_REG 0x0a4 +#define NI_M_PFI_FILTER_REG 0x0b0 +#define NI_M_PFI_FILTER_SEL(_c, _f) (((_f) & 0x3) << ((_c) * 2)) +#define NI_M_PFI_FILTER_SEL_MASK(_c) NI_M_PFI_FILTER_SEL((_c), 0x3) +#define NI_M_RTSI_FILTER_REG 0x0b4 +#define NI_M_SCXI_LEGACY_COMPAT_REG 0x0bc +#define NI_M_DAC_DIRECT_DATA_REG(x) (0x0c0 + ((x) * 4)) +#define NI_M_AO_WAVEFORM_ORDER_REG(x) (0x0c2 + ((x) * 4)) +#define NI_M_AO_CFG_BANK_REG(x) (0x0c3 + ((x) * 4)) +#define NI_M_AO_CFG_BANK_BIPOLAR BIT(7) +#define NI_M_AO_CFG_BANK_UPDATE_TIMED BIT(6) +#define NI_M_AO_CFG_BANK_REF(x) (((x) & 0x7) << 3) +#define NI_M_AO_CFG_BANK_REF_MASK NI_M_AO_CFG_BANK_REF(7) +#define NI_M_AO_CFG_BANK_REF_INT_10V NI_M_AO_CFG_BANK_REF(0) +#define NI_M_AO_CFG_BANK_REF_INT_5V NI_M_AO_CFG_BANK_REF(1) +#define NI_M_AO_CFG_BANK_OFFSET(x) (((x) & 0x7) << 0) +#define NI_M_AO_CFG_BANK_OFFSET_MASK NI_M_AO_CFG_BANK_OFFSET(7) +#define NI_M_AO_CFG_BANK_OFFSET_0V NI_M_AO_CFG_BANK_OFFSET(0) +#define NI_M_AO_CFG_BANK_OFFSET_5V NI_M_AO_CFG_BANK_OFFSET(1) +#define NI_M_RTSI_SHARED_MUX_REG 0x1a2 +#define NI_M_CLK_FOUT2_REG 0x1c4 +#define NI_M_CLK_FOUT2_RTSI_10MHZ BIT(7) +#define NI_M_CLK_FOUT2_TIMEBASE3_PLL BIT(6) +#define NI_M_CLK_FOUT2_TIMEBASE1_PLL BIT(5) +#define NI_M_CLK_FOUT2_PLL_SRC(x) (((x) & 0x1f) << 0) +#define NI_M_CLK_FOUT2_PLL_SRC_MASK NI_M_CLK_FOUT2_PLL_SRC(0x1f) +#define NI_M_MAX_RTSI_CHAN 7 +#define NI_M_CLK_FOUT2_PLL_SRC_RTSI(x) (((x) == NI_M_MAX_RTSI_CHAN) \ + ? NI_M_CLK_FOUT2_PLL_SRC(0x1b) \ + : NI_M_CLK_FOUT2_PLL_SRC(0xb + (x))) +#define NI_M_CLK_FOUT2_PLL_SRC_STAR NI_M_CLK_FOUT2_PLL_SRC(0x14) +#define NI_M_CLK_FOUT2_PLL_SRC_PXI10 NI_M_CLK_FOUT2_PLL_SRC(0x1d) +#define NI_M_PLL_CTRL_REG 0x1c6 +#define NI_M_PLL_CTRL_VCO_MODE(x) (((x) & 0x3) << 13) +#define NI_M_PLL_CTRL_VCO_MODE_200_325MHZ NI_M_PLL_CTRL_VCO_MODE(0) +#define NI_M_PLL_CTRL_VCO_MODE_175_225MHZ NI_M_PLL_CTRL_VCO_MODE(1) +#define NI_M_PLL_CTRL_VCO_MODE_100_225MHZ NI_M_PLL_CTRL_VCO_MODE(2) +#define NI_M_PLL_CTRL_VCO_MODE_75_150MHZ NI_M_PLL_CTRL_VCO_MODE(3) +#define NI_M_PLL_CTRL_ENA BIT(12) +#define NI_M_PLL_MAX_DIVISOR 0x10 +#define NI_M_PLL_CTRL_DIVISOR(x) (((x) & 0xf) << 8) +#define NI_M_PLL_MAX_MULTIPLIER 0x100 +#define NI_M_PLL_CTRL_MULTIPLIER(x) (((x) & 0xff) << 0) +#define NI_M_PLL_STATUS_REG 0x1c8 +#define NI_M_PLL_STATUS_LOCKED BIT(0) +#define NI_M_PFI_OUT_SEL_REG(x) (0x1d0 + ((x) * 2)) +#define NI_M_PFI_CHAN(_c) (((_c) % 3) * 5) +#define NI_M_PFI_OUT_SEL(_c, _s) (((_s) & 0x1f) << NI_M_PFI_CHAN(_c)) +#define NI_M_PFI_OUT_SEL_MASK(_c) (0x1f << NI_M_PFI_CHAN(_c)) +#define NI_M_PFI_OUT_SEL_TO_SRC(_c, _b) (((_b) >> NI_M_PFI_CHAN(_c)) & 0x1f) +#define NI_M_PFI_DI_REG 0x1dc +#define NI_M_PFI_DO_REG 0x1de +#define NI_M_CFG_BYPASS_FIFO_REG 0x218 +#define NI_M_CFG_BYPASS_FIFO BIT(31) +#define NI_M_CFG_BYPASS_AI_POLARITY BIT(22) +#define NI_M_CFG_BYPASS_AI_DITHER BIT(21) +#define NI_M_CFG_BYPASS_AI_GAIN(x) (((x) & 0x7) << 18) +#define NI_M_CFG_BYPASS_AO_CAL(x) (((x) & 0xf) << 15) +#define NI_M_CFG_BYPASS_AO_CAL_MASK NI_M_CFG_BYPASS_AO_CAL(0xf) +#define NI_M_CFG_BYPASS_AI_MODE_MUX(x) (((x) & 0x3) << 13) +#define NI_M_CFG_BYPASS_AI_MODE_MUX_MASK NI_M_CFG_BYPASS_AI_MODE_MUX(3) +#define NI_M_CFG_BYPASS_AI_CAL_NEG(x) (((x) & 0x7) << 10) +#define NI_M_CFG_BYPASS_AI_CAL_NEG_MASK NI_M_CFG_BYPASS_AI_CAL_NEG(7) +#define NI_M_CFG_BYPASS_AI_CAL_POS(x) (((x) & 0x7) << 7) +#define NI_M_CFG_BYPASS_AI_CAL_POS_MASK NI_M_CFG_BYPASS_AI_CAL_POS(7) +#define NI_M_CFG_BYPASS_AI_CAL_MASK (NI_M_CFG_BYPASS_AI_CAL_POS_MASK | \ + NI_M_CFG_BYPASS_AI_CAL_NEG_MASK | \ + NI_M_CFG_BYPASS_AI_MODE_MUX_MASK | \ + NI_M_CFG_BYPASS_AO_CAL_MASK) +#define NI_M_CFG_BYPASS_AI_BANK(x) (((x) & 0xf) << 3) +#define NI_M_CFG_BYPASS_AI_BANK_MASK NI_M_CFG_BYPASS_AI_BANK(0xf) +#define NI_M_CFG_BYPASS_AI_CHAN(x) (((x) & 0x7) << 0) +#define NI_M_CFG_BYPASS_AI_CHAN_MASK NI_M_CFG_BYPASS_AI_CHAN(7) +#define NI_M_SCXI_DIO_ENA_REG 0x21c +#define NI_M_CDI_FIFO_DATA_REG 0x220 +#define NI_M_CDO_FIFO_DATA_REG 0x220 +#define NI_M_CDIO_STATUS_REG 0x224 +#define NI_M_CDIO_STATUS_CDI_OVERFLOW BIT(20) +#define NI_M_CDIO_STATUS_CDI_OVERRUN BIT(19) +#define NI_M_CDIO_STATUS_CDI_ERROR (NI_M_CDIO_STATUS_CDI_OVERFLOW | \ + NI_M_CDIO_STATUS_CDI_OVERRUN) +#define NI_M_CDIO_STATUS_CDI_FIFO_REQ BIT(18) +#define NI_M_CDIO_STATUS_CDI_FIFO_FULL BIT(17) +#define NI_M_CDIO_STATUS_CDI_FIFO_EMPTY BIT(16) +#define NI_M_CDIO_STATUS_CDO_UNDERFLOW BIT(4) +#define NI_M_CDIO_STATUS_CDO_OVERRUN BIT(3) +#define NI_M_CDIO_STATUS_CDO_ERROR (NI_M_CDIO_STATUS_CDO_UNDERFLOW | \ + NI_M_CDIO_STATUS_CDO_OVERRUN) +#define NI_M_CDIO_STATUS_CDO_FIFO_REQ BIT(2) +#define NI_M_CDIO_STATUS_CDO_FIFO_FULL BIT(1) +#define NI_M_CDIO_STATUS_CDO_FIFO_EMPTY BIT(0) +#define NI_M_CDIO_CMD_REG 0x224 +#define NI_M_CDI_CMD_SW_UPDATE BIT(20) +#define NI_M_CDO_CMD_SW_UPDATE BIT(19) +#define NI_M_CDO_CMD_F_E_INT_ENA_CLR BIT(17) +#define NI_M_CDO_CMD_F_E_INT_ENA_SET BIT(16) +#define NI_M_CDI_CMD_ERR_INT_CONFIRM BIT(15) +#define NI_M_CDO_CMD_ERR_INT_CONFIRM BIT(14) +#define NI_M_CDI_CMD_F_REQ_INT_ENA_CLR BIT(13) +#define NI_M_CDI_CMD_F_REQ_INT_ENA_SET BIT(12) +#define NI_M_CDO_CMD_F_REQ_INT_ENA_CLR BIT(11) +#define NI_M_CDO_CMD_F_REQ_INT_ENA_SET BIT(10) +#define NI_M_CDI_CMD_ERR_INT_ENA_CLR BIT(9) +#define NI_M_CDI_CMD_ERR_INT_ENA_SET BIT(8) +#define NI_M_CDO_CMD_ERR_INT_ENA_CLR BIT(7) +#define NI_M_CDO_CMD_ERR_INT_ENA_SET BIT(6) +#define NI_M_CDI_CMD_RESET BIT(5) +#define NI_M_CDO_CMD_RESET BIT(4) +#define NI_M_CDI_CMD_ARM BIT(3) +#define NI_M_CDI_CMD_DISARM BIT(2) +#define NI_M_CDO_CMD_ARM BIT(1) +#define NI_M_CDO_CMD_DISARM BIT(0) +#define NI_M_CDI_MODE_REG 0x228 +#define NI_M_CDI_MODE_DATA_LANE(x) (((x) & 0x3) << 12) +#define NI_M_CDI_MODE_DATA_LANE_MASK NI_M_CDI_MODE_DATA_LANE(3) +#define NI_M_CDI_MODE_DATA_LANE_0_15 NI_M_CDI_MODE_DATA_LANE(0) +#define NI_M_CDI_MODE_DATA_LANE_16_31 NI_M_CDI_MODE_DATA_LANE(1) +#define NI_M_CDI_MODE_DATA_LANE_0_7 NI_M_CDI_MODE_DATA_LANE(0) +#define NI_M_CDI_MODE_DATA_LANE_8_15 NI_M_CDI_MODE_DATA_LANE(1) +#define NI_M_CDI_MODE_DATA_LANE_16_23 NI_M_CDI_MODE_DATA_LANE(2) +#define NI_M_CDI_MODE_DATA_LANE_24_31 NI_M_CDI_MODE_DATA_LANE(3) +#define NI_M_CDI_MODE_FIFO_MODE BIT(11) +#define NI_M_CDI_MODE_POLARITY BIT(10) +#define NI_M_CDI_MODE_HALT_ON_ERROR BIT(9) +#define NI_M_CDI_MODE_SAMPLE_SRC(x) (((x) & 0x3f) << 0) +#define NI_M_CDI_MODE_SAMPLE_SRC_MASK NI_M_CDI_MODE_SAMPLE_SRC(0x3f) +#define NI_M_CDO_MODE_REG 0x22c +#define NI_M_CDO_MODE_DATA_LANE(x) (((x) & 0x3) << 12) +#define NI_M_CDO_MODE_DATA_LANE_MASK NI_M_CDO_MODE_DATA_LANE(3) +#define NI_M_CDO_MODE_DATA_LANE_0_15 NI_M_CDO_MODE_DATA_LANE(0) +#define NI_M_CDO_MODE_DATA_LANE_16_31 NI_M_CDO_MODE_DATA_LANE(1) +#define NI_M_CDO_MODE_DATA_LANE_0_7 NI_M_CDO_MODE_DATA_LANE(0) +#define NI_M_CDO_MODE_DATA_LANE_8_15 NI_M_CDO_MODE_DATA_LANE(1) +#define NI_M_CDO_MODE_DATA_LANE_16_23 NI_M_CDO_MODE_DATA_LANE(2) +#define NI_M_CDO_MODE_DATA_LANE_24_31 NI_M_CDO_MODE_DATA_LANE(3) +#define NI_M_CDO_MODE_FIFO_MODE BIT(11) +#define NI_M_CDO_MODE_POLARITY BIT(10) +#define NI_M_CDO_MODE_HALT_ON_ERROR BIT(9) +#define NI_M_CDO_MODE_RETRANSMIT BIT(8) +#define NI_M_CDO_MODE_SAMPLE_SRC(x) (((x) & 0x3f) << 0) +#define NI_M_CDO_MODE_SAMPLE_SRC_MASK NI_M_CDO_MODE_SAMPLE_SRC(0x3f) +#define NI_M_CDI_MASK_ENA_REG 0x230 +#define NI_M_CDO_MASK_ENA_REG 0x234 +#define NI_M_STATIC_AI_CTRL_REG(x) ((x) ? (0x260 + (x)) : 0x064) +#define NI_M_AO_REF_ATTENUATION_REG(x) (0x264 + (x)) +#define NI_M_AO_REF_ATTENUATION_X5 BIT(0) + +enum { + ai_gain_16 = 0, + ai_gain_8, + ai_gain_14, + ai_gain_4, + ai_gain_611x, + ai_gain_622x, + ai_gain_628x, + ai_gain_6143 }; -static inline unsigned int DACx_Direct_Data_671x(int channel) -{ - return channel; -} -enum AO_Misc_611x_Bits { - CLEAR_WG = 1, +enum caldac_enum { + caldac_none = 0, + mb88341, + dac8800, + dac8043, + ad8522, + ad8804, + ad8842, + ad8804_debug }; -enum cs5529_configuration_bits { - CSCFG_CAL_CONTROL_MASK = 0x7, - CSCFG_SELF_CAL_OFFSET = 0x1, - CSCFG_SELF_CAL_GAIN = 0x2, - CSCFG_SELF_CAL_OFFSET_GAIN = 0x3, - CSCFG_SYSTEM_CAL_OFFSET = 0x5, - CSCFG_SYSTEM_CAL_GAIN = 0x6, - CSCFG_DONE = 1 << 3, - CSCFG_POWER_SAVE_SELECT = 1 << 4, - CSCFG_PORT_MODE = 1 << 5, - CSCFG_RESET_VALID = 1 << 6, - CSCFG_RESET = 1 << 7, - CSCFG_UNIPOLAR = 1 << 12, - CSCFG_WORD_RATE_2180_CYCLES = 0x0 << 13, - CSCFG_WORD_RATE_1092_CYCLES = 0x1 << 13, - CSCFG_WORD_RATE_532_CYCLES = 0x2 << 13, - CSCFG_WORD_RATE_388_CYCLES = 0x3 << 13, - CSCFG_WORD_RATE_324_CYCLES = 0x4 << 13, - CSCFG_WORD_RATE_17444_CYCLES = 0x5 << 13, - CSCFG_WORD_RATE_8724_CYCLES = 0x6 << 13, - CSCFG_WORD_RATE_4364_CYCLES = 0x7 << 13, - CSCFG_WORD_RATE_MASK = 0x7 << 13, - CSCFG_LOW_POWER = 1 << 16, -}; -static inline unsigned int CS5529_CONFIG_DOUT(int output) -{ - return 1 << (18 + output); -} - -static inline unsigned int CS5529_CONFIG_AOUT(int output) -{ - return 1 << (22 + output); -} - -enum cs5529_command_bits { - CSCMD_POWER_SAVE = 0x1, - CSCMD_REGISTER_SELECT_MASK = 0xe, - CSCMD_OFFSET_REGISTER = 0x0, - CSCMD_GAIN_REGISTER = 0x2, - CSCMD_CONFIG_REGISTER = 0x4, - CSCMD_READ = 0x10, - CSCMD_CONTINUOUS_CONVERSIONS = 0x20, - CSCMD_SINGLE_CONVERSION = 0x40, - CSCMD_COMMAND = 0x80, -}; -enum cs5529_status_bits { - CSS_ADC_BUSY = 0x1, - CSS_OSC_DETECT = 0x2, /* indicates adc error */ - CSS_OVERRANGE = 0x4, -}; -#define SerDacLd(x) (0x08<<(x)) - -/* - This is stuff unique to the NI E series drivers, - but I thought I'd put it here anyway. -*/ -enum { ai_gain_16 = - 0, ai_gain_8, ai_gain_14, ai_gain_4, ai_gain_611x, ai_gain_622x, - ai_gain_628x, ai_gain_6143 -}; -enum caldac_enum { caldac_none = 0, mb88341, dac8800, dac8043, ad8522, - ad8804, ad8842, ad8804_debug -}; enum ni_reg_type { ni_reg_normal = 0x0, ni_reg_611x = 0x1, @@ -918,467 +941,6 @@ enum ni_reg_type { ni_reg_6143 = 0x20 }; -static const struct comedi_lrange range_ni_E_ao_ext; - -enum m_series_register_offsets { - M_Offset_CDIO_DMA_Select = 0x7, /* write */ - M_Offset_SCXI_Status = 0x7, /* read */ - M_Offset_AI_AO_Select = 0x9, /* write, same offset as e-series */ - M_Offset_SCXI_Serial_Data_In = 0x9, /* read */ - M_Offset_G0_G1_Select = 0xb, /* write, same offset as e-series */ - M_Offset_Misc_Command = 0xf, - M_Offset_SCXI_Serial_Data_Out = 0x11, - M_Offset_SCXI_Control = 0x13, - M_Offset_SCXI_Output_Enable = 0x15, - M_Offset_AI_FIFO_Data = 0x1c, - M_Offset_Static_Digital_Output = 0x24, /* write */ - M_Offset_Static_Digital_Input = 0x24, /* read */ - M_Offset_DIO_Direction = 0x28, - M_Offset_Cal_PWM = 0x40, - M_Offset_AI_Config_FIFO_Data = 0x5e, - M_Offset_Interrupt_C_Enable = 0x88, /* write */ - M_Offset_Interrupt_C_Status = 0x88, /* read */ - M_Offset_Analog_Trigger_Control = 0x8c, - M_Offset_AO_Serial_Interrupt_Enable = 0xa0, - M_Offset_AO_Serial_Interrupt_Ack = 0xa1, /* write */ - M_Offset_AO_Serial_Interrupt_Status = 0xa1, /* read */ - M_Offset_AO_Calibration = 0xa3, - M_Offset_AO_FIFO_Data = 0xa4, - M_Offset_PFI_Filter = 0xb0, - M_Offset_RTSI_Filter = 0xb4, - M_Offset_SCXI_Legacy_Compatibility = 0xbc, - M_Offset_Interrupt_A_Ack = 0x104, /* write */ - M_Offset_AI_Status_1 = 0x104, /* read */ - M_Offset_Interrupt_B_Ack = 0x106, /* write */ - M_Offset_AO_Status_1 = 0x106, /* read */ - M_Offset_AI_Command_2 = 0x108, /* write */ - M_Offset_G01_Status = 0x108, /* read */ - M_Offset_AO_Command_2 = 0x10a, - M_Offset_AO_Status_2 = 0x10c, /* read */ - M_Offset_G0_Command = 0x10c, /* write */ - M_Offset_G1_Command = 0x10e, /* write */ - M_Offset_G0_HW_Save = 0x110, - M_Offset_G0_HW_Save_High = 0x110, - M_Offset_AI_Command_1 = 0x110, - M_Offset_G0_HW_Save_Low = 0x112, - M_Offset_AO_Command_1 = 0x112, - M_Offset_G1_HW_Save = 0x114, - M_Offset_G1_HW_Save_High = 0x114, - M_Offset_G1_HW_Save_Low = 0x116, - M_Offset_AI_Mode_1 = 0x118, - M_Offset_G0_Save = 0x118, - M_Offset_G0_Save_High = 0x118, - M_Offset_AI_Mode_2 = 0x11a, - M_Offset_G0_Save_Low = 0x11a, - M_Offset_AI_SI_Load_A = 0x11c, - M_Offset_G1_Save = 0x11c, - M_Offset_G1_Save_High = 0x11c, - M_Offset_G1_Save_Low = 0x11e, - M_Offset_AI_SI_Load_B = 0x120, /* write */ - M_Offset_AO_UI_Save = 0x120, /* read */ - M_Offset_AI_SC_Load_A = 0x124, /* write */ - M_Offset_AO_BC_Save = 0x124, /* read */ - M_Offset_AI_SC_Load_B = 0x128, /* write */ - M_Offset_AO_UC_Save = 0x128, /* read */ - M_Offset_AI_SI2_Load_A = 0x12c, - M_Offset_AI_SI2_Load_B = 0x130, - M_Offset_G0_Mode = 0x134, - M_Offset_G1_Mode = 0x136, /* write */ - M_Offset_Joint_Status_1 = 0x136, /* read */ - M_Offset_G0_Load_A = 0x138, - M_Offset_Joint_Status_2 = 0x13a, - M_Offset_G0_Load_B = 0x13c, - M_Offset_G1_Load_A = 0x140, - M_Offset_G1_Load_B = 0x144, - M_Offset_G0_Input_Select = 0x148, - M_Offset_G1_Input_Select = 0x14a, - M_Offset_AO_Mode_1 = 0x14c, - M_Offset_AO_Mode_2 = 0x14e, - M_Offset_AO_UI_Load_A = 0x150, - M_Offset_AO_UI_Load_B = 0x154, - M_Offset_AO_BC_Load_A = 0x158, - M_Offset_AO_BC_Load_B = 0x15c, - M_Offset_AO_UC_Load_A = 0x160, - M_Offset_AO_UC_Load_B = 0x164, - M_Offset_Clock_and_FOUT = 0x170, - M_Offset_IO_Bidirection_Pin = 0x172, - M_Offset_RTSI_Trig_Direction = 0x174, - M_Offset_Interrupt_Control = 0x176, - M_Offset_AI_Output_Control = 0x178, - M_Offset_Analog_Trigger_Etc = 0x17a, - M_Offset_AI_START_STOP_Select = 0x17c, - M_Offset_AI_Trigger_Select = 0x17e, - M_Offset_AI_SI_Save = 0x180, /* read */ - M_Offset_AI_DIV_Load_A = 0x180, /* write */ - M_Offset_AI_SC_Save = 0x184, /* read */ - M_Offset_AO_Start_Select = 0x184, /* write */ - M_Offset_AO_Trigger_Select = 0x186, - M_Offset_AO_Mode_3 = 0x18c, - M_Offset_G0_Autoincrement = 0x188, - M_Offset_G1_Autoincrement = 0x18a, - M_Offset_Joint_Reset = 0x190, - M_Offset_Interrupt_A_Enable = 0x192, - M_Offset_Interrupt_B_Enable = 0x196, - M_Offset_AI_Personal = 0x19a, - M_Offset_AO_Personal = 0x19c, - M_Offset_RTSI_Trig_A_Output = 0x19e, - M_Offset_RTSI_Trig_B_Output = 0x1a0, - M_Offset_RTSI_Shared_MUX = 0x1a2, - M_Offset_AO_Output_Control = 0x1ac, - M_Offset_AI_Mode_3 = 0x1ae, - M_Offset_Configuration_Memory_Clear = 0x1a4, - M_Offset_AI_FIFO_Clear = 0x1a6, - M_Offset_AO_FIFO_Clear = 0x1a8, - M_Offset_G0_Counting_Mode = 0x1b0, - M_Offset_G1_Counting_Mode = 0x1b2, - M_Offset_G0_Second_Gate = 0x1b4, - M_Offset_G1_Second_Gate = 0x1b6, - M_Offset_G0_DMA_Config = 0x1b8, /* write */ - M_Offset_G0_DMA_Status = 0x1b8, /* read */ - M_Offset_G1_DMA_Config = 0x1ba, /* write */ - M_Offset_G1_DMA_Status = 0x1ba, /* read */ - M_Offset_G0_MSeries_ABZ = 0x1c0, - M_Offset_G1_MSeries_ABZ = 0x1c2, - M_Offset_Clock_and_Fout2 = 0x1c4, - M_Offset_PLL_Control = 0x1c6, - M_Offset_PLL_Status = 0x1c8, - M_Offset_PFI_Output_Select_1 = 0x1d0, - M_Offset_PFI_Output_Select_2 = 0x1d2, - M_Offset_PFI_Output_Select_3 = 0x1d4, - M_Offset_PFI_Output_Select_4 = 0x1d6, - M_Offset_PFI_Output_Select_5 = 0x1d8, - M_Offset_PFI_Output_Select_6 = 0x1da, - M_Offset_PFI_DI = 0x1dc, - M_Offset_PFI_DO = 0x1de, - M_Offset_AI_Config_FIFO_Bypass = 0x218, - M_Offset_SCXI_DIO_Enable = 0x21c, - M_Offset_CDI_FIFO_Data = 0x220, /* read */ - M_Offset_CDO_FIFO_Data = 0x220, /* write */ - M_Offset_CDIO_Status = 0x224, /* read */ - M_Offset_CDIO_Command = 0x224, /* write */ - M_Offset_CDI_Mode = 0x228, - M_Offset_CDO_Mode = 0x22c, - M_Offset_CDI_Mask_Enable = 0x230, - M_Offset_CDO_Mask_Enable = 0x234, -}; -static inline int M_Offset_AO_Waveform_Order(int channel) -{ - return 0xc2 + 0x4 * channel; -}; - -static inline int M_Offset_AO_Config_Bank(int channel) -{ - return 0xc3 + 0x4 * channel; -}; - -static inline int M_Offset_DAC_Direct_Data(int channel) -{ - return 0xc0 + 0x4 * channel; -} - -static inline int M_Offset_Gen_PWM(int channel) -{ - return 0x44 + 0x2 * channel; -} - -static inline int M_Offset_Static_AI_Control(int i) -{ - int offset[] = { - 0x64, - 0x261, - 0x262, - 0x263, - }; - if (((unsigned)i) >= ARRAY_SIZE(offset)) { - pr_err("%s: invalid channel=%i\n", __func__, i); - return offset[0]; - } - return offset[i]; -}; - -static inline int M_Offset_AO_Reference_Attenuation(int channel) -{ - int offset[] = { - 0x264, - 0x265, - 0x266, - 0x267 - }; - if (((unsigned)channel) >= ARRAY_SIZE(offset)) { - pr_err("%s: invalid channel=%i\n", __func__, channel); - return offset[0]; - } - return offset[channel]; -}; - -static inline unsigned M_Offset_PFI_Output_Select(unsigned n) -{ - if (n < 1 || n > NUM_PFI_OUTPUT_SELECT_REGS) { - pr_err("%s: invalid pfi output select register=%i\n", - __func__, n); - return M_Offset_PFI_Output_Select_1; - } - return M_Offset_PFI_Output_Select_1 + (n - 1) * 2; -} - -enum MSeries_AI_Config_FIFO_Data_Bits { - MSeries_AI_Config_Channel_Type_Mask = 0x7 << 6, - MSeries_AI_Config_Channel_Type_Calibration_Bits = 0x0, - MSeries_AI_Config_Channel_Type_Differential_Bits = 0x1 << 6, - MSeries_AI_Config_Channel_Type_Common_Ref_Bits = 0x2 << 6, - MSeries_AI_Config_Channel_Type_Ground_Ref_Bits = 0x3 << 6, - MSeries_AI_Config_Channel_Type_Aux_Bits = 0x5 << 6, - MSeries_AI_Config_Channel_Type_Ghost_Bits = 0x7 << 6, - MSeries_AI_Config_Polarity_Bit = 0x1000, /* 0 for 2's complement encoding */ - MSeries_AI_Config_Dither_Bit = 0x2000, - MSeries_AI_Config_Last_Channel_Bit = 0x4000, -}; -static inline unsigned MSeries_AI_Config_Channel_Bits(unsigned channel) -{ - return channel & 0xf; -} - -static inline unsigned MSeries_AI_Config_Bank_Bits(enum ni_reg_type reg_type, - unsigned channel) -{ - unsigned bits = channel & 0x30; - if (reg_type == ni_reg_622x) { - if (channel & 0x40) - bits |= 0x400; - } - return bits; -} - -static inline unsigned MSeries_AI_Config_Gain_Bits(unsigned range) -{ - return (range & 0x7) << 9; -} - -enum MSeries_Clock_and_Fout2_Bits { - MSeries_PLL_In_Source_Select_RTSI0_Bits = 0xb, - MSeries_PLL_In_Source_Select_Star_Trigger_Bits = 0x14, - MSeries_PLL_In_Source_Select_RTSI7_Bits = 0x1b, - MSeries_PLL_In_Source_Select_PXI_Clock10 = 0x1d, - MSeries_PLL_In_Source_Select_Mask = 0x1f, - MSeries_Timebase1_Select_Bit = 0x20, /* use PLL for timebase 1 */ - MSeries_Timebase3_Select_Bit = 0x40, /* use PLL for timebase 3 */ - /* use 10MHz instead of 20MHz for RTSI clock frequency. Appears - to have no effect, at least on pxi-6281, which always uses - 20MHz rtsi clock frequency */ - MSeries_RTSI_10MHz_Bit = 0x80 -}; -static inline unsigned MSeries_PLL_In_Source_Select_RTSI_Bits(unsigned - RTSI_channel) -{ - if (RTSI_channel > 7) { - pr_err("%s: bug, invalid RTSI_channel=%i\n", __func__, - RTSI_channel); - return 0; - } - if (RTSI_channel == 7) - return MSeries_PLL_In_Source_Select_RTSI7_Bits; - else - return MSeries_PLL_In_Source_Select_RTSI0_Bits + RTSI_channel; -} - -enum MSeries_PLL_Control_Bits { - MSeries_PLL_Enable_Bit = 0x1000, - MSeries_PLL_VCO_Mode_200_325MHz_Bits = 0x0, - MSeries_PLL_VCO_Mode_175_225MHz_Bits = 0x2000, - MSeries_PLL_VCO_Mode_100_225MHz_Bits = 0x4000, - MSeries_PLL_VCO_Mode_75_150MHz_Bits = 0x6000, -}; -static inline unsigned MSeries_PLL_Divisor_Bits(unsigned divisor) -{ - static const unsigned max_divisor = 0x10; - if (divisor < 1 || divisor > max_divisor) { - pr_err("%s: bug, invalid divisor=%i\n", __func__, divisor); - return 0; - } - return (divisor & 0xf) << 8; -} - -static inline unsigned MSeries_PLL_Multiplier_Bits(unsigned multiplier) -{ - static const unsigned max_multiplier = 0x100; - if (multiplier < 1 || multiplier > max_multiplier) { - pr_err("%s: bug, invalid multiplier=%i\n", __func__, - multiplier); - return 0; - } - return multiplier & 0xff; -} - -enum MSeries_PLL_Status { - MSeries_PLL_Locked_Bit = 0x1 -}; - -enum MSeries_AI_Config_FIFO_Bypass_Bits { - MSeries_AI_Bypass_Channel_Mask = 0x7, - MSeries_AI_Bypass_Bank_Mask = 0x78, - MSeries_AI_Bypass_Cal_Sel_Pos_Mask = 0x380, - MSeries_AI_Bypass_Cal_Sel_Neg_Mask = 0x1c00, - MSeries_AI_Bypass_Mode_Mux_Mask = 0x6000, - MSeries_AO_Bypass_AO_Cal_Sel_Mask = 0x38000, - MSeries_AI_Bypass_Gain_Mask = 0x1c0000, - MSeries_AI_Bypass_Dither_Bit = 0x200000, - MSeries_AI_Bypass_Polarity_Bit = 0x400000, /* 0 for 2's complement encoding */ - MSeries_AI_Bypass_Config_FIFO_Bit = 0x80000000 -}; -static inline unsigned MSeries_AI_Bypass_Cal_Sel_Pos_Bits(int - calibration_source) -{ - return (calibration_source << 7) & MSeries_AI_Bypass_Cal_Sel_Pos_Mask; -} - -static inline unsigned MSeries_AI_Bypass_Cal_Sel_Neg_Bits(int - calibration_source) -{ - return (calibration_source << 10) & MSeries_AI_Bypass_Cal_Sel_Pos_Mask; -} - -static inline unsigned MSeries_AI_Bypass_Gain_Bits(int gain) -{ - return (gain << 18) & MSeries_AI_Bypass_Gain_Mask; -} - -enum MSeries_AO_Config_Bank_Bits { - MSeries_AO_DAC_Offset_Select_Mask = 0x7, - MSeries_AO_DAC_Offset_0V_Bits = 0x0, - MSeries_AO_DAC_Offset_5V_Bits = 0x1, - MSeries_AO_DAC_Reference_Mask = 0x38, - MSeries_AO_DAC_Reference_10V_Internal_Bits = 0x0, - MSeries_AO_DAC_Reference_5V_Internal_Bits = 0x8, - MSeries_AO_Update_Timed_Bit = 0x40, - MSeries_AO_Bipolar_Bit = 0x80 /* turns on 2's complement encoding */ -}; - -enum MSeries_AO_Reference_Attenuation_Bits { - MSeries_Attenuate_x5_Bit = 0x1 -}; - -static inline unsigned MSeries_Cal_PWM_High_Time_Bits(unsigned count) -{ - return (count << 16) & 0xffff0000; -} - -static inline unsigned MSeries_Cal_PWM_Low_Time_Bits(unsigned count) -{ - return count & 0xffff; -} - -static inline unsigned MSeries_PFI_Output_Select_Mask(unsigned channel) -{ - return 0x1f << (channel % 3) * 5; -}; - -static inline unsigned MSeries_PFI_Output_Select_Bits(unsigned channel, - unsigned source) -{ - return (source & 0x1f) << ((channel % 3) * 5); -}; - -/* inverse to MSeries_PFI_Output_Select_Bits */ -static inline unsigned MSeries_PFI_Output_Select_Source(unsigned channel, - unsigned bits) -{ - return (bits >> ((channel % 3) * 5)) & 0x1f; -}; - -static inline unsigned MSeries_PFI_Filter_Select_Mask(unsigned channel) -{ - return 0x3 << (channel * 2); -} - -static inline unsigned MSeries_PFI_Filter_Select_Bits(unsigned channel, - unsigned filter) -{ - return (filter << (channel * - 2)) & MSeries_PFI_Filter_Select_Mask(channel); -} - -enum CDIO_DMA_Select_Bits { - CDI_DMA_Select_Shift = 0, - CDI_DMA_Select_Mask = 0xf, - CDO_DMA_Select_Shift = 4, - CDO_DMA_Select_Mask = 0xf << CDO_DMA_Select_Shift -}; - -enum CDIO_Status_Bits { - CDO_FIFO_Empty_Bit = 0x1, - CDO_FIFO_Full_Bit = 0x2, - CDO_FIFO_Request_Bit = 0x4, - CDO_Overrun_Bit = 0x8, - CDO_Underflow_Bit = 0x10, - CDI_FIFO_Empty_Bit = 0x10000, - CDI_FIFO_Full_Bit = 0x20000, - CDI_FIFO_Request_Bit = 0x40000, - CDI_Overrun_Bit = 0x80000, - CDI_Overflow_Bit = 0x100000 -}; - -enum CDIO_Command_Bits { - CDO_Disarm_Bit = 0x1, - CDO_Arm_Bit = 0x2, - CDI_Disarm_Bit = 0x4, - CDI_Arm_Bit = 0x8, - CDO_Reset_Bit = 0x10, - CDI_Reset_Bit = 0x20, - CDO_Error_Interrupt_Enable_Set_Bit = 0x40, - CDO_Error_Interrupt_Enable_Clear_Bit = 0x80, - CDI_Error_Interrupt_Enable_Set_Bit = 0x100, - CDI_Error_Interrupt_Enable_Clear_Bit = 0x200, - CDO_FIFO_Request_Interrupt_Enable_Set_Bit = 0x400, - CDO_FIFO_Request_Interrupt_Enable_Clear_Bit = 0x800, - CDI_FIFO_Request_Interrupt_Enable_Set_Bit = 0x1000, - CDI_FIFO_Request_Interrupt_Enable_Clear_Bit = 0x2000, - CDO_Error_Interrupt_Confirm_Bit = 0x4000, - CDI_Error_Interrupt_Confirm_Bit = 0x8000, - CDO_Empty_FIFO_Interrupt_Enable_Set_Bit = 0x10000, - CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit = 0x20000, - CDO_SW_Update_Bit = 0x80000, - CDI_SW_Update_Bit = 0x100000 -}; - -enum CDI_Mode_Bits { - CDI_Sample_Source_Select_Mask = 0x3f, - CDI_Halt_On_Error_Bit = 0x200, - CDI_Polarity_Bit = 0x400, /* sample clock on falling edge */ - CDI_FIFO_Mode_Bit = 0x800, /* set for half full mode, clear for not empty mode */ - CDI_Data_Lane_Mask = 0x3000, /* data lanes specify which dio channels map to byte or word accesses to the dio fifos */ - CDI_Data_Lane_0_15_Bits = 0x0, - CDI_Data_Lane_16_31_Bits = 0x1000, - CDI_Data_Lane_0_7_Bits = 0x0, - CDI_Data_Lane_8_15_Bits = 0x1000, - CDI_Data_Lane_16_23_Bits = 0x2000, - CDI_Data_Lane_24_31_Bits = 0x3000 -}; - -enum CDO_Mode_Bits { - CDO_Sample_Source_Select_Mask = 0x3f, - CDO_Retransmit_Bit = 0x100, - CDO_Halt_On_Error_Bit = 0x200, - CDO_Polarity_Bit = 0x400, /* sample clock on falling edge */ - CDO_FIFO_Mode_Bit = 0x800, /* set for half full mode, clear for not full mode */ - CDO_Data_Lane_Mask = 0x3000, /* data lanes specify which dio channels map to byte or word accesses to the dio fifos */ - CDO_Data_Lane_0_15_Bits = 0x0, - CDO_Data_Lane_16_31_Bits = 0x1000, - CDO_Data_Lane_0_7_Bits = 0x0, - CDO_Data_Lane_8_15_Bits = 0x1000, - CDO_Data_Lane_16_23_Bits = 0x2000, - CDO_Data_Lane_24_31_Bits = 0x3000 -}; - -enum Interrupt_C_Enable_Bits { - Interrupt_Group_C_Enable_Bit = 0x1 -}; - -enum Interrupt_C_Status_Bits { - Interrupt_Group_C_Status_Bit = 0x1 -}; - -#define M_SERIES_EEPROM_SIZE 1024 - struct ni_board_struct { const char *name; int device_id; @@ -1405,9 +967,13 @@ struct ni_board_struct { enum caldac_enum caldac[3]; }; -#define MAX_N_CALDACS 34 -#define MAX_N_AO_CHAN 8 -#define NUM_GPCT 2 +#define MAX_N_CALDACS 34 +#define MAX_N_AO_CHAN 8 +#define NUM_GPCT 2 + +#define NUM_PFI_OUTPUT_SELECT_REGS 6 + +#define M_SERIES_EEPROM_SIZE 1024 struct ni_private { unsigned short dio_output; @@ -1415,8 +981,11 @@ struct ni_private { int aimode; unsigned int ai_calib_source; unsigned int ai_calib_source_enabled; + /* protects access to windowed registers */ spinlock_t window_lock; + /* protects interrupt/dma register access */ spinlock_t soft_reg_copy_lock; + /* protects mite DMA channel request/release */ spinlock_t mite_channel_lock; int changain_state; @@ -1488,4 +1057,6 @@ struct ni_private { unsigned int is_6713:1; }; +static const struct comedi_lrange range_ni_E_ao_ext; + #endif /* _COMEDI_NI_STC_H */ diff --git a/kernel/drivers/staging/comedi/drivers/ni_tio.c b/kernel/drivers/staging/comedi/drivers/ni_tio.c index c20c51bef..b74e44ec5 100644 --- a/kernel/drivers/staging/comedi/drivers/ni_tio.c +++ b/kernel/drivers/staging/comedi/drivers/ni_tio.c @@ -167,15 +167,15 @@ static inline unsigned GI_HW_ARM_SEL_MASK(enum ni_gpct_variant variant) } } -static int ni_tio_has_gate2_registers(const struct ni_gpct_device *counter_dev) +static bool ni_tio_has_gate2_registers(const struct ni_gpct_device *counter_dev) { switch (counter_dev->variant) { case ni_gpct_variant_e_series: default: - return 0; + return false; case ni_gpct_variant_m_series: case ni_gpct_variant_660x: - return 1; + return true; } } diff --git a/kernel/drivers/staging/comedi/drivers/ni_tiocmd.c b/kernel/drivers/staging/comedi/drivers/ni_tiocmd.c index 9b124b09e..437f723bb 100644 --- a/kernel/drivers/staging/comedi/drivers/ni_tiocmd.c +++ b/kernel/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -157,12 +157,6 @@ static int ni_tio_output_cmd(struct comedi_subdevice *s) dev_err(counter->counter_dev->dev->class_dev, "output commands not yet implemented.\n"); return -ENOTSUPP; - - counter->mite_chan->dir = COMEDI_OUTPUT; - mite_prep_dma(counter->mite_chan, 32, 32); - ni_tio_configure_dma(counter, true, false); - mite_dma_arm(counter->mite_chan); - return ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE); } static int ni_tio_cmd_setup(struct comedi_subdevice *s) diff --git a/kernel/drivers/staging/comedi/drivers/ni_usb6501.c b/kernel/drivers/staging/comedi/drivers/ni_usb6501.c index 5f649f88d..95b537a8e 100644 --- a/kernel/drivers/staging/comedi/drivers/ni_usb6501.c +++ b/kernel/drivers/staging/comedi/drivers/ni_usb6501.c @@ -166,13 +166,13 @@ enum commands { struct ni6501_private { struct usb_endpoint_descriptor *ep_rx; struct usb_endpoint_descriptor *ep_tx; - struct semaphore sem; + struct mutex mut; u8 *usb_rx_buf; u8 *usb_tx_buf; }; static int ni6501_port_command(struct comedi_device *dev, int command, - const u8 *port, u8 *bitmap) + unsigned int val, u8 *bitmap) { struct usb_device *usb = comedi_to_usb_dev(dev); struct ni6501_private *devpriv = dev->private; @@ -183,29 +183,29 @@ static int ni6501_port_command(struct comedi_device *dev, int command, if (command != SET_PORT_DIR && !bitmap) return -EINVAL; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); switch (command) { case READ_PORT: request_size = sizeof(READ_PORT_REQUEST); response_size = sizeof(READ_PORT_RESPONSE); memcpy(tx, READ_PORT_REQUEST, request_size); - tx[14] = port[0]; + tx[14] = val & 0xff; break; case WRITE_PORT: request_size = sizeof(WRITE_PORT_REQUEST); response_size = sizeof(GENERIC_RESPONSE); memcpy(tx, WRITE_PORT_REQUEST, request_size); - tx[14] = port[0]; - tx[17] = bitmap[0]; + tx[14] = val & 0xff; + tx[17] = *bitmap; break; case SET_PORT_DIR: request_size = sizeof(SET_PORT_DIR_REQUEST); response_size = sizeof(GENERIC_RESPONSE); memcpy(tx, SET_PORT_DIR_REQUEST, request_size); - tx[14] = port[0]; - tx[15] = port[1]; - tx[16] = port[2]; + tx[14] = val & 0xff; + tx[15] = (val >> 8) & 0xff; + tx[16] = (val >> 16) & 0xff; break; default: ret = -EINVAL; @@ -235,7 +235,7 @@ static int ni6501_port_command(struct comedi_device *dev, int command, /* Check if results are valid */ if (command == READ_PORT) { - bitmap[0] = devpriv->usb_rx_buf[14]; + *bitmap = devpriv->usb_rx_buf[14]; /* mask bitmap for comparing */ devpriv->usb_rx_buf[14] = 0x00; @@ -248,7 +248,7 @@ static int ni6501_port_command(struct comedi_device *dev, int command, ret = -EINVAL; } end: - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } @@ -265,7 +265,7 @@ static int ni6501_counter_command(struct comedi_device *dev, int command, if ((command == READ_COUNTER || command == WRITE_COUNTER) && !val) return -EINVAL; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); switch (command) { case START_COUNTER: @@ -338,7 +338,7 @@ static int ni6501_counter_command(struct comedi_device *dev, int command, ret = -EINVAL; } end: - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } @@ -349,17 +349,12 @@ static int ni6501_dio_insn_config(struct comedi_device *dev, unsigned int *data) { int ret; - u8 port[3]; ret = comedi_dio_insn_config(dev, s, insn, data, 0); if (ret) return ret; - port[0] = (s->io_bits) & 0xff; - port[1] = (s->io_bits >> 8) & 0xff; - port[2] = (s->io_bits >> 16) & 0xff; - - ret = ni6501_port_command(dev, SET_PORT_DIR, port, NULL); + ret = ni6501_port_command(dev, SET_PORT_DIR, s->io_bits, NULL); if (ret) return ret; @@ -382,7 +377,7 @@ static int ni6501_dio_insn_bits(struct comedi_device *dev, if (mask & (0xFF << port * 8)) { bitmap = (s->state >> port * 8) & 0xFF; ret = ni6501_port_command(dev, WRITE_PORT, - &port, &bitmap); + port, &bitmap); if (ret) return ret; } @@ -391,7 +386,7 @@ static int ni6501_dio_insn_bits(struct comedi_device *dev, data[1] = 0; for (port = 0; port < 3; port++) { - ret = ni6501_port_command(dev, READ_PORT, &port, &bitmap); + ret = ni6501_port_command(dev, READ_PORT, port, &bitmap); if (ret) return ret; data[1] |= bitmap << port * 8; @@ -540,7 +535,7 @@ static int ni6501_auto_attach(struct comedi_device *dev, if (ret) return ret; - sema_init(&devpriv->sem, 1); + mutex_init(&devpriv->mut); usb_set_intfdata(intf, devpriv); ret = comedi_alloc_subdevices(dev, 2); @@ -578,14 +573,14 @@ static void ni6501_detach(struct comedi_device *dev) if (!devpriv) return; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); usb_set_intfdata(intf, NULL); kfree(devpriv->usb_rx_buf); kfree(devpriv->usb_tx_buf); - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); } static struct comedi_driver ni6501_driver = { diff --git a/kernel/drivers/staging/comedi/drivers/pcl711.c b/kernel/drivers/staging/comedi/drivers/pcl711.c index cfc3a627d..3774daa9d 100644 --- a/kernel/drivers/staging/comedi/drivers/pcl711.c +++ b/kernel/drivers/staging/comedi/drivers/pcl711.c @@ -49,7 +49,7 @@ #define PCL711_TIMER_BASE 0x00 #define PCL711_AI_LSB_REG 0x04 #define PCL711_AI_MSB_REG 0x05 -#define PCL711_AI_MSB_DRDY (1 << 4) +#define PCL711_AI_MSB_DRDY BIT(4) #define PCL711_AO_LSB_REG(x) (0x04 + ((x) * 2)) #define PCL711_AO_MSB_REG(x) (0x05 + ((x) * 2)) #define PCL711_DI_LSB_REG 0x06 @@ -60,16 +60,17 @@ #define PCL711_AI_GAIN(x) (((x) & 0xf) << 0) #define PCL711_MUX_REG 0x0a #define PCL711_MUX_CHAN(x) (((x) & 0xf) << 0) -#define PCL711_MUX_CS0 (1 << 4) -#define PCL711_MUX_CS1 (1 << 5) +#define PCL711_MUX_CS0 BIT(4) +#define PCL711_MUX_CS1 BIT(5) #define PCL711_MUX_DIFF (PCL711_MUX_CS0 | PCL711_MUX_CS1) #define PCL711_MODE_REG 0x0b -#define PCL711_MODE_DEFAULT (0 << 0) -#define PCL711_MODE_SOFTTRIG (1 << 0) -#define PCL711_MODE_EXT (2 << 0) -#define PCL711_MODE_EXT_IRQ (3 << 0) -#define PCL711_MODE_PACER (4 << 0) -#define PCL711_MODE_PACER_IRQ (6 << 0) +#define PCL711_MODE(x) (((x) & 0x7) << 0) +#define PCL711_MODE_DEFAULT PCL711_MODE(0) +#define PCL711_MODE_SOFTTRIG PCL711_MODE(1) +#define PCL711_MODE_EXT PCL711_MODE(2) +#define PCL711_MODE_EXT_IRQ PCL711_MODE(3) +#define PCL711_MODE_PACER PCL711_MODE(4) +#define PCL711_MODE_PACER_IRQ PCL711_MODE(6) #define PCL711_MODE_IRQ(x) (((x) & 0x7) << 4) #define PCL711_SOFTTRIG_REG 0x0c #define PCL711_SOFTTRIG (0 << 0) /* any value will work */ diff --git a/kernel/drivers/staging/comedi/drivers/pcl812.c b/kernel/drivers/staging/comedi/drivers/pcl812.c index 03a3fd6cd..9c75065dd 100644 --- a/kernel/drivers/staging/comedi/drivers/pcl812.c +++ b/kernel/drivers/staging/comedi/drivers/pcl812.c @@ -119,40 +119,30 @@ #include "comedi_isadma.h" #include "comedi_8254.h" -/* hardware types of the cards */ -#define boardPCL812PG 0 /* and ACL-8112PG */ -#define boardPCL813B 1 -#define boardPCL812 2 -#define boardPCL813 3 -#define boardISO813 5 -#define boardACL8113 6 -#define boardACL8112 7 /* ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH */ -#define boardACL8216 8 /* and ICP DAS A-826PG */ -#define boardA821 9 /* PGH, PGL, PGL/NDA versions */ - /* * Register I/O map */ #define PCL812_TIMER_BASE 0x00 #define PCL812_AI_LSB_REG 0x04 #define PCL812_AI_MSB_REG 0x05 -#define PCL812_AI_MSB_DRDY (1 << 4) +#define PCL812_AI_MSB_DRDY BIT(4) #define PCL812_AO_LSB_REG(x) (0x04 + ((x) * 2)) #define PCL812_AO_MSB_REG(x) (0x05 + ((x) * 2)) #define PCL812_DI_LSB_REG 0x06 #define PCL812_DI_MSB_REG 0x07 #define PCL812_STATUS_REG 0x08 -#define PCL812_STATUS_DRDY (1 << 5) +#define PCL812_STATUS_DRDY BIT(5) #define PCL812_RANGE_REG 0x09 #define PCL812_MUX_REG 0x0a #define PCL812_MUX_CHAN(x) ((x) << 0) -#define PCL812_MUX_CS0 (1 << 4) -#define PCL812_MUX_CS1 (1 << 5) +#define PCL812_MUX_CS0 BIT(4) +#define PCL812_MUX_CS1 BIT(5) #define PCL812_CTRL_REG 0x0b -#define PCL812_CTRL_DISABLE_TRIG (0 << 0) -#define PCL812_CTRL_SOFT_TRIG (1 << 0) -#define PCL812_CTRL_PACER_DMA_TRIG (2 << 0) -#define PCL812_CTRL_PACER_EOC_TRIG (6 << 0) +#define PCL812_CTRL_TRIG(x) (((x) & 0x7) << 0) +#define PCL812_CTRL_DISABLE_TRIG PCL812_CTRL_TRIG(0) +#define PCL812_CTRL_SOFT_TRIG PCL812_CTRL_TRIG(1) +#define PCL812_CTRL_PACER_DMA_TRIG PCL812_CTRL_TRIG(2) +#define PCL812_CTRL_PACER_EOC_TRIG PCL812_CTRL_TRIG(6) #define PCL812_SOFTTRIG_REG 0x0c #define PCL812_DO_LSB_REG 0x0d #define PCL812_DO_MSB_REG 0x0e @@ -327,14 +317,26 @@ static const struct comedi_lrange range_a821pgh_ai = { } }; +enum pcl812_boardtype { + BOARD_PCL812PG = 0, /* and ACL-8112PG */ + BOARD_PCL813B = 1, + BOARD_PCL812 = 2, + BOARD_PCL813 = 3, + BOARD_ISO813 = 5, + BOARD_ACL8113 = 6, + BOARD_ACL8112 = 7, /* ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH */ + BOARD_ACL8216 = 8, /* and ICP DAS A-826PG */ + BOARD_A821 = 9, /* PGH, PGL, PGL/NDA versions */ +}; + struct pcl812_board { const char *name; - int board_type; + enum pcl812_boardtype board_type; int n_aichan; int n_aochan; unsigned int ai_ns_min; const struct comedi_lrange *rangelist_ai; - unsigned int IRQbits; + unsigned int irq_bits; unsigned int has_dma:1; unsigned int has_16bit_ai:1; unsigned int has_mpc508_mux:1; @@ -344,161 +346,161 @@ struct pcl812_board { static const struct pcl812_board boardtypes[] = { { .name = "pcl812", - .board_type = boardPCL812, + .board_type = BOARD_PCL812, .n_aichan = 16, .n_aochan = 2, .ai_ns_min = 33000, .rangelist_ai = &range_bipolar10, - .IRQbits = 0xdcfc, + .irq_bits = 0xdcfc, .has_dma = 1, .has_dio = 1, }, { .name = "pcl812pg", - .board_type = boardPCL812PG, + .board_type = BOARD_PCL812PG, .n_aichan = 16, .n_aochan = 2, .ai_ns_min = 33000, .rangelist_ai = &range_pcl812pg_ai, - .IRQbits = 0xdcfc, + .irq_bits = 0xdcfc, .has_dma = 1, .has_dio = 1, }, { .name = "acl8112pg", - .board_type = boardPCL812PG, + .board_type = BOARD_PCL812PG, .n_aichan = 16, .n_aochan = 2, .ai_ns_min = 10000, .rangelist_ai = &range_pcl812pg_ai, - .IRQbits = 0xdcfc, + .irq_bits = 0xdcfc, .has_dma = 1, .has_dio = 1, }, { .name = "acl8112dg", - .board_type = boardACL8112, + .board_type = BOARD_ACL8112, .n_aichan = 16, /* 8 differential */ .n_aochan = 2, .ai_ns_min = 10000, .rangelist_ai = &range_acl8112dg_ai, - .IRQbits = 0xdcfc, + .irq_bits = 0xdcfc, .has_dma = 1, .has_mpc508_mux = 1, .has_dio = 1, }, { .name = "acl8112hg", - .board_type = boardACL8112, + .board_type = BOARD_ACL8112, .n_aichan = 16, /* 8 differential */ .n_aochan = 2, .ai_ns_min = 10000, .rangelist_ai = &range_acl8112hg_ai, - .IRQbits = 0xdcfc, + .irq_bits = 0xdcfc, .has_dma = 1, .has_mpc508_mux = 1, .has_dio = 1, }, { .name = "a821pgl", - .board_type = boardA821, + .board_type = BOARD_A821, .n_aichan = 16, /* 8 differential */ .n_aochan = 1, .ai_ns_min = 10000, .rangelist_ai = &range_pcl813b_ai, - .IRQbits = 0x000c, + .irq_bits = 0x000c, .has_dio = 1, }, { .name = "a821pglnda", - .board_type = boardA821, + .board_type = BOARD_A821, .n_aichan = 16, /* 8 differential */ .ai_ns_min = 10000, .rangelist_ai = &range_pcl813b_ai, - .IRQbits = 0x000c, + .irq_bits = 0x000c, }, { .name = "a821pgh", - .board_type = boardA821, + .board_type = BOARD_A821, .n_aichan = 16, /* 8 differential */ .n_aochan = 1, .ai_ns_min = 10000, .rangelist_ai = &range_a821pgh_ai, - .IRQbits = 0x000c, + .irq_bits = 0x000c, .has_dio = 1, }, { .name = "a822pgl", - .board_type = boardACL8112, + .board_type = BOARD_ACL8112, .n_aichan = 16, /* 8 differential */ .n_aochan = 2, .ai_ns_min = 10000, .rangelist_ai = &range_acl8112dg_ai, - .IRQbits = 0xdcfc, + .irq_bits = 0xdcfc, .has_dma = 1, .has_dio = 1, }, { .name = "a822pgh", - .board_type = boardACL8112, + .board_type = BOARD_ACL8112, .n_aichan = 16, /* 8 differential */ .n_aochan = 2, .ai_ns_min = 10000, .rangelist_ai = &range_acl8112hg_ai, - .IRQbits = 0xdcfc, + .irq_bits = 0xdcfc, .has_dma = 1, .has_dio = 1, }, { .name = "a823pgl", - .board_type = boardACL8112, + .board_type = BOARD_ACL8112, .n_aichan = 16, /* 8 differential */ .n_aochan = 2, .ai_ns_min = 8000, .rangelist_ai = &range_acl8112dg_ai, - .IRQbits = 0xdcfc, + .irq_bits = 0xdcfc, .has_dma = 1, .has_dio = 1, }, { .name = "a823pgh", - .board_type = boardACL8112, + .board_type = BOARD_ACL8112, .n_aichan = 16, /* 8 differential */ .n_aochan = 2, .ai_ns_min = 8000, .rangelist_ai = &range_acl8112hg_ai, - .IRQbits = 0xdcfc, + .irq_bits = 0xdcfc, .has_dma = 1, .has_dio = 1, }, { .name = "pcl813", - .board_type = boardPCL813, + .board_type = BOARD_PCL813, .n_aichan = 32, .rangelist_ai = &range_pcl813b_ai, }, { .name = "pcl813b", - .board_type = boardPCL813B, + .board_type = BOARD_PCL813B, .n_aichan = 32, .rangelist_ai = &range_pcl813b_ai, }, { .name = "acl8113", - .board_type = boardACL8113, + .board_type = BOARD_ACL8113, .n_aichan = 32, .rangelist_ai = &range_acl8113_1_ai, }, { .name = "iso813", - .board_type = boardISO813, + .board_type = BOARD_ISO813, .n_aichan = 32, .rangelist_ai = &range_iso813_1_ai, }, { .name = "acl8216", - .board_type = boardACL8216, + .board_type = BOARD_ACL8216, .n_aichan = 16, /* 8 differential */ .n_aochan = 2, .ai_ns_min = 10000, .rangelist_ai = &range_pcl813b2_ai, - .IRQbits = 0xdcfc, + .irq_bits = 0xdcfc, .has_dma = 1, .has_16bit_ai = 1, .has_mpc508_mux = 1, .has_dio = 1, }, { .name = "a826pg", - .board_type = boardACL8216, + .board_type = BOARD_ACL8216, .n_aichan = 16, /* 8 differential */ .n_aochan = 2, .ai_ns_min = 10000, .rangelist_ai = &range_pcl813b2_ai, - .IRQbits = 0xdcfc, + .irq_bits = 0xdcfc, .has_dma = 1, .has_16bit_ai = 1, .has_dio = 1, @@ -507,11 +509,11 @@ static const struct pcl812_board boardtypes[] = { struct pcl812_private { struct comedi_isadma *dma; - unsigned char range_correction; /* =1 we must add 1 to range number */ + unsigned char range_correction; /* =1 we must add 1 to range number */ unsigned int last_ai_chanspec; - unsigned char mode_reg_int; /* there is stored INT number for some card */ - unsigned int ai_poll_ptr; /* how many sampes transfer poll */ - unsigned int max_812_ai_mode0_rangewait; /* setling time for gain */ + unsigned char mode_reg_int; /* stored INT number for some cards */ + unsigned int ai_poll_ptr; /* how many samples transfer poll */ + unsigned int max_812_ai_mode0_rangewait; /* settling time for gain */ unsigned int use_diff:1; unsigned int use_mpc508:1; unsigned int use_ext_trg:1; @@ -1017,16 +1019,14 @@ static void pcl812_set_ai_range_table(struct comedi_device *dev, const struct pcl812_board *board = dev->board_ptr; struct pcl812_private *devpriv = dev->private; - /* default to the range table from the boardinfo */ - s->range_table = board->rangelist_ai; - - /* now check the user config option based on the boardtype */ switch (board->board_type) { - case boardPCL812PG: + case BOARD_PCL812PG: if (it->options[4] == 1) s->range_table = &range_pcl812pg2_ai; + else + s->range_table = board->rangelist_ai; break; - case boardPCL812: + case BOARD_PCL812: switch (it->options[4]) { case 0: s->range_table = &range_bipolar10; @@ -1051,11 +1051,13 @@ static void pcl812_set_ai_range_table(struct comedi_device *dev, break; } break; - case boardPCL813B: + case BOARD_PCL813B: if (it->options[1] == 1) s->range_table = &range_pcl813b2_ai; + else + s->range_table = board->rangelist_ai; break; - case boardISO813: + case BOARD_ISO813: switch (it->options[1]) { case 0: s->range_table = &range_iso813_1_ai; @@ -1076,7 +1078,7 @@ static void pcl812_set_ai_range_table(struct comedi_device *dev, break; } break; - case boardACL8113: + case BOARD_ACL8113: switch (it->options[1]) { case 0: s->range_table = &range_acl8113_1_ai; @@ -1097,6 +1099,9 @@ static void pcl812_set_ai_range_table(struct comedi_device *dev, break; } break; + default: + s->range_table = board->rangelist_ai; + break; } } @@ -1138,14 +1143,14 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - if (board->IRQbits) { + if (board->irq_bits) { dev->pacer = comedi_8254_init(dev->iobase + PCL812_TIMER_BASE, I8254_OSC_BASE_2MHZ, I8254_IO8, 0); if (!dev->pacer) return -ENOMEM; - if ((1 << it->options[1]) & board->IRQbits) { + if ((1 << it->options[1]) & board->irq_bits) { ret = request_irq(it->options[1], pcl812_interrupt, 0, dev->board_name, dev); if (ret == 0) @@ -1155,19 +1160,21 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* we need an IRQ to do DMA on channel 3 or 1 */ if (dev->irq && board->has_dma) - pcl812_alloc_dma(dev, it->options[2]); + pcl812_alloc_dma(dev, it->options[2]); /* differential analog inputs? */ switch (board->board_type) { - case boardA821: + case BOARD_A821: if (it->options[2] == 1) devpriv->use_diff = 1; break; - case boardACL8112: - case boardACL8216: + case BOARD_ACL8112: + case BOARD_ACL8216: if (it->options[4] == 1) devpriv->use_diff = 1; break; + default: + break; } n_subdevices = 1; /* all boardtypes have analog inputs */ @@ -1220,20 +1227,31 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->subdev_flags = SDF_WRITABLE | SDF_GROUND; s->n_chan = board->n_aochan; s->maxdata = 0xfff; - s->range_table = &range_unipolar5; switch (board->board_type) { - case boardA821: + case BOARD_A821: if (it->options[3] == 1) s->range_table = &range_unipolar10; + else + s->range_table = &range_unipolar5; break; - case boardPCL812: - case boardACL8112: - case boardPCL812PG: - case boardACL8216: - if (it->options[5] == 1) + case BOARD_PCL812: + case BOARD_ACL8112: + case BOARD_PCL812PG: + case BOARD_ACL8216: + switch (it->options[5]) { + case 1: s->range_table = &range_unipolar10; - if (it->options[5] == 2) + break; + case 2: s->range_table = &range_unknown; + break; + default: + s->range_table = &range_unipolar5; + break; + } + break; + default: + s->range_table = &range_unipolar5; break; } s->insn_write = pcl812_ao_insn_write; @@ -1268,23 +1286,23 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) } switch (board->board_type) { - case boardACL8216: - case boardPCL812PG: - case boardPCL812: - case boardACL8112: + case BOARD_ACL8216: + case BOARD_PCL812PG: + case BOARD_PCL812: + case BOARD_ACL8112: devpriv->max_812_ai_mode0_rangewait = 1; if (it->options[3] > 0) /* we use external trigger */ devpriv->use_ext_trg = 1; break; - case boardA821: + case BOARD_A821: devpriv->max_812_ai_mode0_rangewait = 1; devpriv->mode_reg_int = (dev->irq << 4) & 0xf0; break; - case boardPCL813B: - case boardPCL813: - case boardISO813: - case boardACL8113: + case BOARD_PCL813B: + case BOARD_PCL813: + case BOARD_ISO813: + case BOARD_ACL8113: /* maybe there must by greatest timeout */ devpriv->max_812_ai_mode0_rangewait = 5; break; diff --git a/kernel/drivers/staging/comedi/drivers/pcl816.c b/kernel/drivers/staging/comedi/drivers/pcl816.c index 1ccb2f19f..c00a71f53 100644 --- a/kernel/drivers/staging/comedi/drivers/pcl816.c +++ b/kernel/drivers/staging/comedi/drivers/pcl816.c @@ -1,36 +1,33 @@ /* - comedi/drivers/pcl816.c - - Author: Juan Grigera <juan@grigera.com.ar> - based on pcl818 by Michal Dobes <dobes@tesnet.cz> and bits of pcl812 + * pcl816.c + * Comedi driver for Advantech PCL-816 cards + * + * Author: Juan Grigera <juan@grigera.com.ar> + * based on pcl818 by Michal Dobes <dobes@tesnet.cz> and bits of pcl812 + */ - hardware driver for Advantech cards: - card: PCL-816, PCL814B - driver: pcl816 -*/ /* -Driver: pcl816 -Description: Advantech PCL-816 cards, PCL-814 -Author: Juan Grigera <juan@grigera.com.ar> -Devices: [Advantech] PCL-816 (pcl816), PCL-814B (pcl814b) -Status: works -Updated: Tue, 2 Apr 2002 23:15:21 -0800 - -PCL 816 and 814B have 16 SE/DIFF ADCs, 16 DACs, 16 DI and 16 DO. -Differences are at resolution (16 vs 12 bits). - -The driver support AI command mode, other subdevices not written. - -Analog output and digital input and output are not supported. - -Configuration Options: - [0] - IO Base - [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) - [2] - DMA (0=disable, 1, 3) - [3] - 0, 10=10MHz clock for 8254 - 1= 1MHz clock for 8254 - -*/ + * Driver: pcl816 + * Description: Advantech PCL-816 cards, PCL-814 + * Devices: [Advantech] PCL-816 (pcl816), PCL-814B (pcl814b) + * Author: Juan Grigera <juan@grigera.com.ar> + * Status: works + * Updated: Tue, 2 Apr 2002 23:15:21 -0800 + * + * PCL 816 and 814B have 16 SE/DIFF ADCs, 16 DACs, 16 DI and 16 DO. + * Differences are at resolution (16 vs 12 bits). + * + * The driver support AI command mode, other subdevices not written. + * + * Analog output and digital input and output are not supported. + * + * Configuration Options: + * [0] - IO Base + * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + * [2] - DMA (0=disable, 1, 3) + * [3] - 0, 10=10MHz clock for 8254 + * 1= 1MHz clock for 8254 + */ #include <linux/module.h> #include <linux/gfp.h> @@ -56,25 +53,20 @@ Configuration Options: #define PCL816_MUX_REG 0x0b #define PCL816_MUX_SCAN(_first, _last) (((_last) << 4) | (_first)) #define PCL816_CTRL_REG 0x0c -#define PCL816_CTRL_DISABLE_TRIG (0 << 0) -#define PCL816_CTRL_SOFT_TRIG (1 << 0) -#define PCL816_CTRL_PACER_TRIG (1 << 1) -#define PCL816_CTRL_EXT_TRIG (1 << 2) -#define PCL816_CTRL_POE (1 << 3) -#define PCL816_CTRL_DMAEN (1 << 4) -#define PCL816_CTRL_INTEN (1 << 5) -#define PCL816_CTRL_DMASRC_SLOT0 (0 << 6) -#define PCL816_CTRL_DMASRC_SLOT1 (1 << 6) -#define PCL816_CTRL_DMASRC_SLOT2 (2 << 6) +#define PCL816_CTRL_SOFT_TRIG BIT(0) +#define PCL816_CTRL_PACER_TRIG BIT(1) +#define PCL816_CTRL_EXT_TRIG BIT(2) +#define PCL816_CTRL_POE BIT(3) +#define PCL816_CTRL_DMAEN BIT(4) +#define PCL816_CTRL_INTEN BIT(5) +#define PCL816_CTRL_DMASRC_SLOT(x) (((x) & 0x3) << 6) #define PCL816_STATUS_REG 0x0d #define PCL816_STATUS_NEXT_CHAN_MASK (0xf << 0) -#define PCL816_STATUS_INTSRC_MASK (3 << 4) -#define PCL816_STATUS_INTSRC_SLOT0 (0 << 4) -#define PCL816_STATUS_INTSRC_SLOT1 (1 << 4) -#define PCL816_STATUS_INTSRC_SLOT2 (2 << 4) -#define PCL816_STATUS_INTSRC_DMA (3 << 4) -#define PCL816_STATUS_INTACT (1 << 6) -#define PCL816_STATUS_DRDY (1 << 7) +#define PCL816_STATUS_INTSRC_SLOT(x) (((x) & 0x3) << 4) +#define PCL816_STATUS_INTSRC_DMA PCL816_STATUS_INTSRC_SLOT(3) +#define PCL816_STATUS_INTSRC_MASK PCL816_STATUS_INTSRC_SLOT(3) +#define PCL816_STATUS_INTACT BIT(6) +#define PCL816_STATUS_DRDY BIT(7) #define MAGIC_DMA_WORD 0x5a5a @@ -94,7 +86,6 @@ static const struct comedi_lrange range_pcl816 = { struct pcl816_board { const char *name; int ai_maxdata; - int ao_maxdata; int ai_chanlist; }; @@ -102,12 +93,10 @@ static const struct pcl816_board boardtypes[] = { { .name = "pcl816", .ai_maxdata = 0xffff, - .ao_maxdata = 0xffff, .ai_chanlist = 1024, }, { .name = "pcl814b", .ai_maxdata = 0x3fff, - .ao_maxdata = 0x3fff, .ai_chanlist = 1024, }, }; @@ -305,7 +294,7 @@ static int check_channel_list(struct comedi_device *dev, chansegment[0] = chanlist[0]; for (i = 1, seglen = 1; i < chanlen; i++, seglen++) { /* we detect loop, this must by finish */ - if (chanlist[0] == chanlist[i]) + if (chanlist[0] == chanlist[i]) break; nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % chanlen; @@ -323,7 +312,7 @@ static int check_channel_list(struct comedi_device *dev, /* check whole chanlist */ for (i = 0, segpos = 0; i < chanlen; i++) { - if (chanlist[i] != chansegment[i % seglen]) { + if (chanlist[i] != chansegment[i % seglen]) { dev_dbg(dev->class_dev, "bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", i, CR_CHAN(chansegment[i]), @@ -443,7 +432,8 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) comedi_8254_update_divisors(dev->pacer); comedi_8254_pacer_enable(dev->pacer, 1, 2, true); - ctrl = PCL816_CTRL_INTEN | PCL816_CTRL_DMAEN | PCL816_CTRL_DMASRC_SLOT0; + ctrl = PCL816_CTRL_INTEN | PCL816_CTRL_DMAEN | + PCL816_CTRL_DMASRC_SLOT(0); if (cmd->convert_src == TRIG_TIMER) ctrl |= PCL816_CTRL_PACER_TRIG; else /* TRIG_EXT */ @@ -497,7 +487,7 @@ static int pcl816_ai_cancel(struct comedi_device *dev, if (!devpriv->ai_cmd_running) return 0; - outb(PCL816_CTRL_DISABLE_TRIG, dev->iobase + PCL816_CTRL_REG); + outb(0, dev->iobase + PCL816_CTRL_REG); pcl816_ai_clear_eoc(dev); comedi_8254_pacer_enable(dev->pacer, 1, 2, false); @@ -533,7 +523,7 @@ static int pcl816_ai_insn_read(struct comedi_device *dev, data[i] = pcl816_ai_get_sample(dev, s); } - outb(PCL816_CTRL_DISABLE_TRIG, dev->iobase + PCL816_CTRL_REG); + outb(0, dev->iobase + PCL816_CTRL_REG); pcl816_ai_clear_eoc(dev); return ret ? ret : insn->n; @@ -567,7 +557,7 @@ static int pcl816_do_insn_bits(struct comedi_device *dev, static void pcl816_reset(struct comedi_device *dev) { - outb(PCL816_CTRL_DISABLE_TRIG, dev->iobase + PCL816_CTRL_REG); + outb(0, dev->iobase + PCL816_CTRL_REG); pcl816_ai_set_chan_range(dev, 0, 0); pcl816_ai_clear_eoc(dev); @@ -652,16 +642,9 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->cancel = pcl816_ai_cancel; } - /* Analog OUtput subdevice */ - s = &dev->subdevices[2]; + /* Piggyback Slot1 subdevice */ + s = &dev->subdevices[1]; s->type = COMEDI_SUBD_UNUSED; -#if 0 - subdevs[1] = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE | SDF_GROUND; - s->n_chan = 1; - s->maxdata = board->ao_maxdata; - s->range_table = &range_pcl816; -#endif /* Digital Input subdevice */ s = &dev->subdevices[2]; diff --git a/kernel/drivers/staging/comedi/drivers/pcl818.c b/kernel/drivers/staging/comedi/drivers/pcl818.c index e1bdde977..5aeed44df 100644 --- a/kernel/drivers/staging/comedi/drivers/pcl818.c +++ b/kernel/drivers/staging/comedi/drivers/pcl818.c @@ -102,15 +102,6 @@ #include "comedi_isadma.h" #include "comedi_8254.h" -/* boards constants */ - -#define boardPCL818L 0 -#define boardPCL818H 1 -#define boardPCL818HD 2 -#define boardPCL818HG 3 -#define boardPCL818 4 -#define boardPCL718 5 - /* * Register I/O map */ @@ -124,23 +115,22 @@ #define PCL818_AO_MSB_REG(x) (0x05 + ((x) * 2)) #define PCL818_STATUS_REG 0x08 #define PCL818_STATUS_NEXT_CHAN_MASK (0xf << 0) -#define PCL818_STATUS_INT (1 << 4) -#define PCL818_STATUS_MUX (1 << 5) -#define PCL818_STATUS_UNI (1 << 6) -#define PCL818_STATUS_EOC (1 << 7) +#define PCL818_STATUS_INT BIT(4) +#define PCL818_STATUS_MUX BIT(5) +#define PCL818_STATUS_UNI BIT(6) +#define PCL818_STATUS_EOC BIT(7) #define PCL818_CTRL_REG 0x09 -#define PCL818_CTRL_DISABLE_TRIG (0 << 0) -#define PCL818_CTRL_SOFT_TRIG (1 << 0) -#define PCL818_CTRL_EXT_TRIG (2 << 0) -#define PCL818_CTRL_PACER_TRIG (3 << 0) -#define PCL818_CTRL_DMAE (1 << 2) +#define PCL818_CTRL_TRIG(x) (((x) & 0x3) << 0) +#define PCL818_CTRL_DISABLE_TRIG PCL818_CTRL_TRIG(0) +#define PCL818_CTRL_SOFT_TRIG PCL818_CTRL_TRIG(1) +#define PCL818_CTRL_EXT_TRIG PCL818_CTRL_TRIG(2) +#define PCL818_CTRL_PACER_TRIG PCL818_CTRL_TRIG(3) +#define PCL818_CTRL_DMAE BIT(2) #define PCL818_CTRL_IRQ(x) ((x) << 4) -#define PCL818_CTRL_INTE (1 << 7) +#define PCL818_CTRL_INTE BIT(7) #define PCL818_CNTENABLE_REG 0x0a -#define PCL818_CNTENABLE_PACER_ENA (0 << 0) -#define PCL818_CNTENABLE_PACER_TRIG0 (1 << 0) -#define PCL818_CNTENABLE_CNT0_EXT_CLK (0 << 1) -#define PCL818_CNTENABLE_CNT0_INT_CLK (1 << 1) +#define PCL818_CNTENABLE_PACER_TRIG0 BIT(0) +#define PCL818_CNTENABLE_CNT0_INT_CLK BIT(1) /* 0=ext clk */ #define PCL818_DO_DI_MSB_REG 0x0b #define PCL818_TIMER_BASE 0x0c @@ -740,7 +730,7 @@ static int pcl818_ai_cmd(struct comedi_device *dev, else ctrl |= PCL818_CTRL_EXT_TRIG; - outb(PCL818_CNTENABLE_PACER_ENA, dev->iobase + PCL818_CNTENABLE_REG); + outb(0, dev->iobase + PCL818_CNTENABLE_REG); if (dma) { /* setup and enable dma for the first buffer */ @@ -902,7 +892,7 @@ static void pcl818_reset(struct comedi_device *dev) pcl818_ai_set_chan_range(dev, 0, 0); /* stop pacer */ - outb(PCL818_CNTENABLE_PACER_ENA, dev->iobase + PCL818_CNTENABLE_REG); + outb(0, dev->iobase + PCL818_CNTENABLE_REG); /* set analog output channels to 0V */ for (chan = 0; chan < board->n_aochan; chan++) { diff --git a/kernel/drivers/staging/comedi/drivers/pcm3724.c b/kernel/drivers/staging/comedi/drivers/pcm3724.c index 6176dfa24..588ae5ece 100644 --- a/kernel/drivers/staging/comedi/drivers/pcm3724.c +++ b/kernel/drivers/staging/comedi/drivers/pcm3724.c @@ -1,31 +1,25 @@ /* - comedi/drivers/pcm724.c - - Drew Csillag <drew_csillag@yahoo.com> - - hardware driver for Advantech card: - card: PCM-3724 - driver: pcm3724 + * pcm3724.c + * Comedi driver for Advantech PCM-3724 Digital I/O board + * + * Drew Csillag <drew_csillag@yahoo.com> + */ - Options for PCM-3724 - [0] - IO Base -*/ -/* -Driver: pcm3724 -Description: Advantech PCM-3724 -Author: Drew Csillag <drew_csillag@yahoo.com> -Devices: [Advantech] PCM-3724 (pcm724) -Status: tested - -This is driver for digital I/O boards PCM-3724 with 48 DIO. -It needs 8255.o for operations and only immediate mode is supported. -See the source for configuration details. - -Copy/pasted/hacked from pcm724.c -*/ /* - * check_driver overrides: - * struct comedi_insn + * Driver: pcm3724 + * Description: Advantech PCM-3724 + * Devices: [Advantech] PCM-3724 (pcm3724) + * Author: Drew Csillag <drew_csillag@yahoo.com> + * Status: tested + * + * This is driver for digital I/O boards PCM-3724 with 48 DIO. + * It needs 8255.o for operations and only immediate mode is supported. + * See the source for configuration details. + * + * Copy/pasted/hacked from pcm724.c + * + * Configuration Options: + * [0] - I/O port base address */ #include <linux/module.h> @@ -33,19 +27,31 @@ Copy/pasted/hacked from pcm724.c #include "8255.h" -#define BUF_C0 0x1 -#define BUF_B0 0x2 -#define BUF_A0 0x4 -#define BUF_C1 0x8 -#define BUF_B1 0x10 -#define BUF_A1 0x20 - -#define GATE_A0 0x4 -#define GATE_B0 0x2 -#define GATE_C0 0x1 -#define GATE_A1 0x20 -#define GATE_B1 0x10 -#define GATE_C1 0x8 +/* + * Register I/O Map + * + * This board has two standard 8255 devices that provide six 8-bit DIO ports + * (48 channels total). Six 74HCT245 chips (one for each port) buffer the + * I/O lines to increase driving capability. Because the 74HCT245 is a + * bidirectional, tri-state line buffer, two additional I/O ports are used + * to control the direction of data and the enable of each port. + */ +#define PCM3724_8255_0_BASE 0x00 +#define PCM3724_8255_1_BASE 0x04 +#define PCM3724_DIO_DIR_REG 0x08 +#define PCM3724_DIO_DIR_C0_OUT BIT(0) +#define PCM3724_DIO_DIR_B0_OUT BIT(1) +#define PCM3724_DIO_DIR_A0_OUT BIT(2) +#define PCM3724_DIO_DIR_C1_OUT BIT(3) +#define PCM3724_DIO_DIR_B1_OUT BIT(4) +#define PCM3724_DIO_DIR_A1_OUT BIT(5) +#define PCM3724_GATE_CTRL_REG 0x09 +#define PCM3724_GATE_CTRL_C0_ENA BIT(0) +#define PCM3724_GATE_CTRL_B0_ENA BIT(1) +#define PCM3724_GATE_CTRL_A0_ENA BIT(2) +#define PCM3724_GATE_CTRL_C1_ENA BIT(3) +#define PCM3724_GATE_CTRL_B1_ENA BIT(4) +#define PCM3724_GATE_CTRL_A1_ENA BIT(5) /* used to track configured dios */ struct priv_pcm3724 { @@ -58,21 +64,21 @@ static int compute_buffer(int config, int devno, struct comedi_subdevice *s) /* 1 in io_bits indicates output */ if (s->io_bits & 0x0000ff) { if (devno == 0) - config |= BUF_A0; + config |= PCM3724_DIO_DIR_A0_OUT; else - config |= BUF_A1; + config |= PCM3724_DIO_DIR_A1_OUT; } if (s->io_bits & 0x00ff00) { if (devno == 0) - config |= BUF_B0; + config |= PCM3724_DIO_DIR_B0_OUT; else - config |= BUF_B1; + config |= PCM3724_DIO_DIR_B1_OUT; } if (s->io_bits & 0xff0000) { if (devno == 0) - config |= BUF_C0; + config |= PCM3724_DIO_DIR_C0_OUT; else - config |= BUF_C1; + config |= PCM3724_DIO_DIR_C1_OUT; } return config; } @@ -107,7 +113,7 @@ static void do_3724_config(struct comedi_device *dev, else port_8255_cfg = dev->iobase + I8255_SIZE + I8255_CTRL_REG; - outb(buffer_config, dev->iobase + 8); /* update buffer register */ + outb(buffer_config, dev->iobase + PCM3724_DIO_DIR_REG); outb(config, port_8255_cfg); } @@ -129,24 +135,24 @@ static void enable_chan(struct comedi_device *dev, struct comedi_subdevice *s, priv->dio_2 |= mask; if (priv->dio_1 & 0xff0000) - gatecfg |= GATE_C0; + gatecfg |= PCM3724_GATE_CTRL_C0_ENA; if (priv->dio_1 & 0xff00) - gatecfg |= GATE_B0; + gatecfg |= PCM3724_GATE_CTRL_B0_ENA; if (priv->dio_1 & 0xff) - gatecfg |= GATE_A0; + gatecfg |= PCM3724_GATE_CTRL_A0_ENA; if (priv->dio_2 & 0xff0000) - gatecfg |= GATE_C1; + gatecfg |= PCM3724_GATE_CTRL_C1_ENA; if (priv->dio_2 & 0xff00) - gatecfg |= GATE_B1; + gatecfg |= PCM3724_GATE_CTRL_B1_ENA; if (priv->dio_2 & 0xff) - gatecfg |= GATE_A1; + gatecfg |= PCM3724_GATE_CTRL_A1_ENA; - outb(gatecfg, dev->iobase + 9); + outb(gatecfg, dev->iobase + PCM3724_GATE_CTRL_REG); } /* overriding the 8255 insn config */ @@ -216,5 +222,5 @@ static struct comedi_driver pcm3724_driver = { module_comedi_driver(pcm3724_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for Advantech PCM-3724 Digital I/O board"); MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/kernel/drivers/staging/comedi/drivers/quatech_daqp_cs.c index 152cb146f..e9e431391 100644 --- a/kernel/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/kernel/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -1,149 +1,153 @@ -/*====================================================================== - - comedi/drivers/quatech_daqp_cs.c - - Quatech DAQP PCMCIA data capture cards COMEDI client driver - Copyright (C) 2000, 2003 Brent Baccala <baccala@freesoft.org> - The DAQP interface code in this file is released into the public domain. - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1998 David A. Schleef <ds@schleef.org> - http://www.comedi.org/ - - quatech_daqp_cs.c 1.10 - - Documentation for the DAQP PCMCIA cards can be found on Quatech's site: - - ftp://ftp.quatech.com/Manuals/daqp-208.pdf - - This manual is for both the DAQP-208 and the DAQP-308. - - What works: - - - A/D conversion - - 8 channels - - 4 gain ranges - - ground ref or differential - - single-shot and timed both supported - - D/A conversion, single-shot - - digital I/O - - What doesn't: - - - any kind of triggering - external or D/A channel 1 - - the card's optional expansion board - - the card's timer (for anything other than A/D conversion) - - D/A update modes other than immediate (i.e, timed) - - fancier timing modes - - setting card's FIFO buffer thresholds to anything but default - -======================================================================*/ +/* + * quatech_daqp_cs.c + * Quatech DAQP PCMCIA data capture cards COMEDI client driver + * Copyright (C) 2000, 2003 Brent Baccala <baccala@freesoft.org> + * The DAQP interface code in this file is released into the public domain. + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1998 David A. Schleef <ds@schleef.org> + * http://www.comedi.org/ + * + * Documentation for the DAQP PCMCIA cards can be found on Quatech's site: + * ftp://ftp.quatech.com/Manuals/daqp-208.pdf + * + * This manual is for both the DAQP-208 and the DAQP-308. + * + * What works: + * - A/D conversion + * - 8 channels + * - 4 gain ranges + * - ground ref or differential + * - single-shot and timed both supported + * - D/A conversion, single-shot + * - digital I/O + * + * What doesn't: + * - any kind of triggering - external or D/A channel 1 + * - the card's optional expansion board + * - the card's timer (for anything other than A/D conversion) + * - D/A update modes other than immediate (i.e, timed) + * - fancier timing modes + * - setting card's FIFO buffer thresholds to anything but default + */ /* -Driver: quatech_daqp_cs -Description: Quatech DAQP PCMCIA data capture cards -Author: Brent Baccala <baccala@freesoft.org> -Status: works -Devices: [Quatech] DAQP-208 (daqp), DAQP-308 -*/ + * Driver: quatech_daqp_cs + * Description: Quatech DAQP PCMCIA data capture cards + * Devices: [Quatech] DAQP-208 (daqp), DAQP-308 + * Author: Brent Baccala <baccala@freesoft.org> + * Status: works + */ #include <linux/module.h> -#include <linux/semaphore.h> -#include <linux/completion.h> #include "../comedi_pcmcia.h" +/* + * Register I/O map + * + * The D/A and timer registers can be accessed with 16-bit or 8-bit I/O + * instructions. All other registers can only use 8-bit instructions. + * + * The FIFO and scanlist registers require two 8-bit instructions to + * access the 16-bit data. Data is transferred LSB then MSB. + */ +#define DAQP_AI_FIFO_REG 0x00 + +#define DAQP_SCANLIST_REG 0x01 +#define DAQP_SCANLIST_DIFFERENTIAL BIT(14) +#define DAQP_SCANLIST_GAIN(x) (((x) & 0x3) << 12) +#define DAQP_SCANLIST_CHANNEL(x) (((x) & 0xf) << 8) +#define DAQP_SCANLIST_START BIT(7) +#define DAQP_SCANLIST_EXT_GAIN(x) (((x) & 0x3) << 4) +#define DAQP_SCANLIST_EXT_CHANNEL(x) (((x) & 0xf) << 0) + +#define DAQP_CTRL_REG 0x02 +#define DAQP_CTRL_PACER_CLK(x) (((x) & 0x3) << 6) +#define DAQP_CTRL_PACER_CLK_EXT DAQP_CTRL_PACER_CLK(0) +#define DAQP_CTRL_PACER_CLK_5MHZ DAQP_CTRL_PACER_CLK(1) +#define DAQP_CTRL_PACER_CLK_1MHZ DAQP_CTRL_PACER_CLK(2) +#define DAQP_CTRL_PACER_CLK_100KHZ DAQP_CTRL_PACER_CLK(3) +#define DAQP_CTRL_EXPANSION BIT(5) +#define DAQP_CTRL_EOS_INT_ENA BIT(4) +#define DAQP_CTRL_FIFO_INT_ENA BIT(3) +#define DAQP_CTRL_TRIG_MODE BIT(2) /* 0=one-shot; 1=continuous */ +#define DAQP_CTRL_TRIG_SRC BIT(1) /* 0=internal; 1=external */ +#define DAQP_CTRL_TRIG_EDGE BIT(0) /* 0=rising; 1=falling */ + +#define DAQP_STATUS_REG 0x02 +#define DAQP_STATUS_IDLE BIT(7) +#define DAQP_STATUS_RUNNING BIT(6) +#define DAQP_STATUS_DATA_LOST BIT(5) +#define DAQP_STATUS_END_OF_SCAN BIT(4) +#define DAQP_STATUS_FIFO_THRESHOLD BIT(3) +#define DAQP_STATUS_FIFO_FULL BIT(2) +#define DAQP_STATUS_FIFO_NEARFULL BIT(1) +#define DAQP_STATUS_FIFO_EMPTY BIT(0) +/* these bits clear when the status register is read */ +#define DAQP_STATUS_EVENTS (DAQP_STATUS_DATA_LOST | \ + DAQP_STATUS_END_OF_SCAN | \ + DAQP_STATUS_FIFO_THRESHOLD) + +#define DAQP_DI_REG 0x03 +#define DAQP_DO_REG 0x03 + +#define DAQP_PACER_LOW_REG 0x04 +#define DAQP_PACER_MID_REG 0x05 +#define DAQP_PACER_HIGH_REG 0x06 + +#define DAQP_CMD_REG 0x07 +/* the monostable bits are self-clearing after the function is complete */ +#define DAQP_CMD_ARM BIT(7) /* monostable */ +#define DAQP_CMD_RSTF BIT(6) /* monostable */ +#define DAQP_CMD_RSTQ BIT(5) /* monostable */ +#define DAQP_CMD_STOP BIT(4) /* monostable */ +#define DAQP_CMD_LATCH BIT(3) /* monostable */ +#define DAQP_CMD_SCANRATE(x) (((x) & 0x3) << 1) +#define DAQP_CMD_SCANRATE_100KHZ DAQP_CMD_SCANRATE(0) +#define DAQP_CMD_SCANRATE_50KHZ DAQP_CMD_SCANRATE(1) +#define DAQP_CMD_SCANRATE_25KHZ DAQP_CMD_SCANRATE(2) +#define DAQP_CMD_FIFO_DATA BIT(0) + +#define DAQP_AO_REG 0x08 /* and 0x09 (16-bit) */ + +#define DAQP_TIMER_REG 0x0a /* and 0x0b (16-bit) */ + +#define DAQP_AUX_REG 0x0f +/* Auxiliary Control register bits (write) */ +#define DAQP_AUX_EXT_ANALOG_TRIG BIT(7) +#define DAQP_AUX_PRETRIG BIT(6) +#define DAQP_AUX_TIMER_INT_ENA BIT(5) +#define DAQP_AUX_TIMER_MODE(x) (((x) & 0x3) << 3) +#define DAQP_AUX_TIMER_MODE_RELOAD DAQP_AUX_TIMER_MODE(0) +#define DAQP_AUX_TIMER_MODE_PAUSE DAQP_AUX_TIMER_MODE(1) +#define DAQP_AUX_TIMER_MODE_GO DAQP_AUX_TIMER_MODE(2) +#define DAQP_AUX_TIMER_MODE_EXT DAQP_AUX_TIMER_MODE(3) +#define DAQP_AUX_TIMER_CLK_SRC_EXT BIT(2) +#define DAQP_AUX_DA_UPDATE(x) (((x) & 0x3) << 0) +#define DAQP_AUX_DA_UPDATE_DIRECT DAQP_AUX_DA_UPDATE(0) +#define DAQP_AUX_DA_UPDATE_OVERFLOW DAQP_AUX_DA_UPDATE(1) +#define DAQP_AUX_DA_UPDATE_EXTERNAL DAQP_AUX_DA_UPDATE(2) +#define DAQP_AUX_DA_UPDATE_PACER DAQP_AUX_DA_UPDATE(3) +/* Auxiliary Status register bits (read) */ +#define DAQP_AUX_RUNNING BIT(7) +#define DAQP_AUX_TRIGGERED BIT(6) +#define DAQP_AUX_DA_BUFFER BIT(5) +#define DAQP_AUX_TIMER_OVERFLOW BIT(4) +#define DAQP_AUX_CONVERSION BIT(3) +#define DAQP_AUX_DATA_LOST BIT(2) +#define DAQP_AUX_FIFO_NEARFULL BIT(1) +#define DAQP_AUX_FIFO_EMPTY BIT(0) + +#define DAQP_FIFO_SIZE 4096 + +#define DAQP_MAX_TIMER_SPEED 10000 /* 100 kHz in nanoseconds */ + struct daqp_private { + unsigned int pacer_div; int stop; - - enum { semaphore, buffer } interrupt_mode; - - struct completion eos; }; -/* The DAQP communicates with the system through a 16 byte I/O window. */ - -#define DAQP_FIFO_SIZE 4096 - -#define DAQP_FIFO 0 -#define DAQP_SCANLIST 1 -#define DAQP_CONTROL 2 -#define DAQP_STATUS 2 -#define DAQP_DIGITAL_IO 3 -#define DAQP_PACER_LOW 4 -#define DAQP_PACER_MID 5 -#define DAQP_PACER_HIGH 6 -#define DAQP_COMMAND 7 -#define DAQP_DA 8 -#define DAQP_TIMER 10 -#define DAQP_AUX 15 - -#define DAQP_SCANLIST_DIFFERENTIAL 0x4000 -#define DAQP_SCANLIST_GAIN(x) ((x)<<12) -#define DAQP_SCANLIST_CHANNEL(x) ((x)<<8) -#define DAQP_SCANLIST_START 0x0080 -#define DAQP_SCANLIST_EXT_GAIN(x) ((x)<<4) -#define DAQP_SCANLIST_EXT_CHANNEL(x) (x) - -#define DAQP_CONTROL_PACER_100kHz 0xc0 -#define DAQP_CONTROL_PACER_1MHz 0x80 -#define DAQP_CONTROL_PACER_5MHz 0x40 -#define DAQP_CONTROL_PACER_EXTERNAL 0x00 -#define DAQP_CONTORL_EXPANSION 0x20 -#define DAQP_CONTROL_EOS_INT_ENABLE 0x10 -#define DAQP_CONTROL_FIFO_INT_ENABLE 0x08 -#define DAQP_CONTROL_TRIGGER_ONESHOT 0x00 -#define DAQP_CONTROL_TRIGGER_CONTINUOUS 0x04 -#define DAQP_CONTROL_TRIGGER_INTERNAL 0x00 -#define DAQP_CONTROL_TRIGGER_EXTERNAL 0x02 -#define DAQP_CONTROL_TRIGGER_RISING 0x00 -#define DAQP_CONTROL_TRIGGER_FALLING 0x01 - -#define DAQP_STATUS_IDLE 0x80 -#define DAQP_STATUS_RUNNING 0x40 -#define DAQP_STATUS_EVENTS 0x38 -#define DAQP_STATUS_DATA_LOST 0x20 -#define DAQP_STATUS_END_OF_SCAN 0x10 -#define DAQP_STATUS_FIFO_THRESHOLD 0x08 -#define DAQP_STATUS_FIFO_FULL 0x04 -#define DAQP_STATUS_FIFO_NEARFULL 0x02 -#define DAQP_STATUS_FIFO_EMPTY 0x01 - -#define DAQP_COMMAND_ARM 0x80 -#define DAQP_COMMAND_RSTF 0x40 -#define DAQP_COMMAND_RSTQ 0x20 -#define DAQP_COMMAND_STOP 0x10 -#define DAQP_COMMAND_LATCH 0x08 -#define DAQP_COMMAND_100kHz 0x00 -#define DAQP_COMMAND_50kHz 0x02 -#define DAQP_COMMAND_25kHz 0x04 -#define DAQP_COMMAND_FIFO_DATA 0x01 -#define DAQP_COMMAND_FIFO_PROGRAM 0x00 - -#define DAQP_AUX_TRIGGER_TTL 0x00 -#define DAQP_AUX_TRIGGER_ANALOG 0x80 -#define DAQP_AUX_TRIGGER_PRETRIGGER 0x40 -#define DAQP_AUX_TIMER_INT_ENABLE 0x20 -#define DAQP_AUX_TIMER_RELOAD 0x00 -#define DAQP_AUX_TIMER_PAUSE 0x08 -#define DAQP_AUX_TIMER_GO 0x10 -#define DAQP_AUX_TIMER_GO_EXTERNAL 0x18 -#define DAQP_AUX_TIMER_EXTERNAL_SRC 0x04 -#define DAQP_AUX_TIMER_INTERNAL_SRC 0x00 -#define DAQP_AUX_DA_DIRECT 0x00 -#define DAQP_AUX_DA_OVERFLOW 0x01 -#define DAQP_AUX_DA_EXTERNAL 0x02 -#define DAQP_AUX_DA_PACER 0x03 - -#define DAQP_AUX_RUNNING 0x80 -#define DAQP_AUX_TRIGGERED 0x40 -#define DAQP_AUX_DA_BUFFER 0x20 -#define DAQP_AUX_TIMER_OVERFLOW 0x10 -#define DAQP_AUX_CONVERSION 0x08 -#define DAQP_AUX_DATA_LOST 0x04 -#define DAQP_AUX_FIFO_NEARFULL 0x02 -#define DAQP_AUX_FIFO_EMPTY 0x01 - static const struct comedi_lrange range_daqp_ai = { 4, { BIP_RANGE(10), @@ -153,38 +157,59 @@ static const struct comedi_lrange range_daqp_ai = { } }; -/* Cancel a running acquisition */ +static int daqp_clear_events(struct comedi_device *dev, int loops) +{ + unsigned int status; -static int daqp_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) + /* + * Reset any pending interrupts (my card has a tendency to require + * require multiple reads on the status register to achieve this). + */ + while (--loops) { + status = inb(dev->iobase + DAQP_STATUS_REG); + if ((status & DAQP_STATUS_EVENTS) == 0) + return 0; + } + dev_err(dev->class_dev, "couldn't clear events in status register\n"); + return -EBUSY; +} + +static int daqp_ai_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) { struct daqp_private *devpriv = dev->private; if (devpriv->stop) return -EIO; - outb(DAQP_COMMAND_STOP, dev->iobase + DAQP_COMMAND); + /* + * Stop any conversions, disable interrupts, and clear + * the status event flags. + */ + outb(DAQP_CMD_STOP, dev->iobase + DAQP_CMD_REG); + outb(0, dev->iobase + DAQP_CTRL_REG); + inb(dev->iobase + DAQP_STATUS_REG); - /* flush any linguring data in FIFO - superfluous here */ - /* outb(DAQP_COMMAND_RSTF, dev->iobase+DAQP_COMMAND); */ + return 0; +} - devpriv->interrupt_mode = semaphore; +static unsigned int daqp_ai_get_sample(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + unsigned int val; - return 0; + /* + * Get a two's complement sample from the FIFO and + * return the munged offset binary value. + */ + val = inb(dev->iobase + DAQP_AI_FIFO_REG); + val |= inb(dev->iobase + DAQP_AI_FIFO_REG) << 8; + return comedi_offset_munge(s, val); } -/* Interrupt handler - * - * Operates in one of two modes. If devpriv->interrupt_mode is - * 'semaphore', just signal the devpriv->eos completion and return - * (one-shot mode). Otherwise (continuous mode), read data in from - * the card, transfer it to the buffer provided by the higher-level - * comedi kernel module, and signal various comedi callback routines, - * which run pretty quick. - */ -static enum irqreturn daqp_interrupt(int irq, void *dev_id) +static irqreturn_t daqp_interrupt(int irq, void *dev_id) { struct comedi_device *dev = dev_id; - struct daqp_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; struct comedi_cmd *cmd = &s->async->cmd; int loop_limit = 10000; @@ -193,50 +218,42 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id) if (!dev->attached) return IRQ_NONE; - switch (devpriv->interrupt_mode) { - case semaphore: - complete(&devpriv->eos); - break; + status = inb(dev->iobase + DAQP_STATUS_REG); + if (!(status & DAQP_STATUS_EVENTS)) + return IRQ_NONE; - case buffer: - while (!((status = inb(dev->iobase + DAQP_STATUS)) - & DAQP_STATUS_FIFO_EMPTY)) { - unsigned short data; + while (!(status & DAQP_STATUS_FIFO_EMPTY)) { + unsigned short data; - if (status & DAQP_STATUS_DATA_LOST) { - s->async->events |= COMEDI_CB_OVERFLOW; - dev_warn(dev->class_dev, "data lost\n"); - break; - } + if (status & DAQP_STATUS_DATA_LOST) { + s->async->events |= COMEDI_CB_OVERFLOW; + dev_warn(dev->class_dev, "data lost\n"); + break; + } - data = inb(dev->iobase + DAQP_FIFO); - data |= inb(dev->iobase + DAQP_FIFO) << 8; - data ^= 0x8000; + data = daqp_ai_get_sample(dev, s); + comedi_buf_write_samples(s, &data, 1); - comedi_buf_write_samples(s, &data, 1); + if (cmd->stop_src == TRIG_COUNT && + s->async->scans_done >= cmd->stop_arg) { + s->async->events |= COMEDI_CB_EOA; + break; + } - /* If there's a limit, decrement it - * and stop conversion if zero - */ + if ((loop_limit--) <= 0) + break; - if (cmd->stop_src == TRIG_COUNT && - s->async->scans_done >= cmd->stop_arg) { - s->async->events |= COMEDI_CB_EOA; - break; - } + status = inb(dev->iobase + DAQP_STATUS_REG); + } - if ((loop_limit--) <= 0) - break; - } + if (loop_limit <= 0) { + dev_warn(dev->class_dev, + "loop_limit reached in daqp_interrupt()\n"); + s->async->events |= COMEDI_CB_ERROR; + } - if (loop_limit <= 0) { - dev_warn(dev->class_dev, - "loop_limit reached in daqp_interrupt()\n"); - s->async->events |= COMEDI_CB_ERROR; - } + comedi_handle_events(dev, s); - comedi_handle_events(dev, s); - } return IRQ_HANDLED; } @@ -257,78 +274,73 @@ static void daqp_ai_set_one_scanlist_entry(struct comedi_device *dev, if (start) val |= DAQP_SCANLIST_START; - outb(val & 0xff, dev->iobase + DAQP_SCANLIST); - outb((val >> 8) & 0xff, dev->iobase + DAQP_SCANLIST); + outb(val & 0xff, dev->iobase + DAQP_SCANLIST_REG); + outb((val >> 8) & 0xff, dev->iobase + DAQP_SCANLIST_REG); } -/* One-shot analog data acquisition routine */ +static int daqp_ai_eos(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned long context) +{ + unsigned int status; + + status = inb(dev->iobase + DAQP_AUX_REG); + if (status & DAQP_AUX_CONVERSION) + return 0; + return -EBUSY; +} static int daqp_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct daqp_private *devpriv = dev->private; + int ret = 0; int i; - int v; - int counter = 10000; if (devpriv->stop) return -EIO; - /* Stop any running conversion */ - daqp_ai_cancel(dev, s); - - outb(0, dev->iobase + DAQP_AUX); + outb(0, dev->iobase + DAQP_AUX_REG); /* Reset scan list queue */ - outb(DAQP_COMMAND_RSTQ, dev->iobase + DAQP_COMMAND); + outb(DAQP_CMD_RSTQ, dev->iobase + DAQP_CMD_REG); /* Program one scan list entry */ daqp_ai_set_one_scanlist_entry(dev, insn->chanspec, 1); /* Reset data FIFO (see page 28 of DAQP User's Manual) */ + outb(DAQP_CMD_RSTF, dev->iobase + DAQP_CMD_REG); - outb(DAQP_COMMAND_RSTF, dev->iobase + DAQP_COMMAND); - - /* Set trigger */ - - v = DAQP_CONTROL_TRIGGER_ONESHOT | DAQP_CONTROL_TRIGGER_INTERNAL - | DAQP_CONTROL_PACER_100kHz | DAQP_CONTROL_EOS_INT_ENABLE; - - outb(v, dev->iobase + DAQP_CONTROL); + /* Set trigger - one-shot, internal, no interrupts */ + outb(DAQP_CTRL_PACER_CLK_100KHZ, dev->iobase + DAQP_CTRL_REG); - /* Reset any pending interrupts (my card has a tendency to require - * require multiple reads on the status register to achieve this) - */ - - while (--counter - && (inb(dev->iobase + DAQP_STATUS) & DAQP_STATUS_EVENTS)) - ; - if (!counter) { - dev_err(dev->class_dev, - "couldn't clear interrupts in status register\n"); - return -1; - } - - init_completion(&devpriv->eos); - devpriv->interrupt_mode = semaphore; + ret = daqp_clear_events(dev, 10000); + if (ret) + return ret; for (i = 0; i < insn->n; i++) { /* Start conversion */ - outb(DAQP_COMMAND_ARM | DAQP_COMMAND_FIFO_DATA, - dev->iobase + DAQP_COMMAND); + outb(DAQP_CMD_ARM | DAQP_CMD_FIFO_DATA, + dev->iobase + DAQP_CMD_REG); - /* Wait for interrupt service routine to unblock completion */ - /* Maybe could use a timeout here, but it's interruptible */ - if (wait_for_completion_interruptible(&devpriv->eos)) - return -EINTR; + ret = comedi_timeout(dev, s, insn, daqp_ai_eos, 0); + if (ret) + break; - data[i] = inb(dev->iobase + DAQP_FIFO); - data[i] |= inb(dev->iobase + DAQP_FIFO) << 8; - data[i] ^= 0x8000; + /* clear the status event flags */ + inb(dev->iobase + DAQP_STATUS_REG); + + data[i] = daqp_ai_get_sample(dev, s); } - return insn->n; + /* stop any conversions and clear the status event flags */ + outb(DAQP_CMD_STOP, dev->iobase + DAQP_CMD_REG); + inb(dev->iobase + DAQP_STATUS_REG); + + return ret ? ret : insn->n; } /* This function converts ns nanoseconds to a counter value suitable @@ -348,17 +360,18 @@ static int daqp_ns_to_timer(unsigned int *ns, unsigned int flags) return timer; } -/* cmdtest tests a particular command to see if it is valid. - * Using the cmdtest ioctl, a user can create a valid cmd - * and then have it executed by the cmd ioctl. - * - * cmdtest returns 1,2,3,4 or 0, depending on which tests - * the command passes. - */ +static void daqp_set_pacer(struct comedi_device *dev, unsigned int val) +{ + outb(val & 0xff, dev->iobase + DAQP_PACER_LOW_REG); + outb((val >> 8) & 0xff, dev->iobase + DAQP_PACER_MID_REG); + outb((val >> 16) & 0xff, dev->iobase + DAQP_PACER_HIGH_REG); +} static int daqp_ai_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_cmd *cmd) + struct comedi_subdevice *s, + struct comedi_cmd *cmd) { + struct daqp_private *devpriv = dev->private; int err = 0; unsigned int arg; @@ -383,6 +396,10 @@ static int daqp_ai_cmdtest(struct comedi_device *dev, /* Step 2b : and mutually compatible */ + /* the async command requires a pacer */ + if (cmd->scan_begin_src != TRIG_TIMER && cmd->convert_src != TRIG_TIMER) + err |= -EINVAL; + if (err) return 2; @@ -390,31 +407,31 @@ static int daqp_ai_cmdtest(struct comedi_device *dev, err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); -#define MAX_SPEED 10000 /* 100 kHz - in nanoseconds */ + err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1); + err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, + cmd->chanlist_len); - if (cmd->scan_begin_src == TRIG_TIMER) { + if (cmd->scan_begin_src == TRIG_TIMER) err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, - MAX_SPEED); - } - - /* If both scan_begin and convert are both timer values, the only - * way that can make sense is if the scan time is the number of - * conversions times the convert time - */ - - if (cmd->scan_begin_src == TRIG_TIMER && cmd->convert_src == TRIG_TIMER - && cmd->scan_begin_arg != cmd->convert_arg * cmd->scan_end_arg) { - err |= -EINVAL; - } + DAQP_MAX_TIMER_SPEED); if (cmd->convert_src == TRIG_TIMER) { err |= comedi_check_trigger_arg_min(&cmd->convert_arg, - MAX_SPEED); + DAQP_MAX_TIMER_SPEED); + + if (cmd->scan_begin_src == TRIG_TIMER) { + /* + * If both scan_begin and convert are both timer + * values, the only way that can make sense is if + * the scan time is the number of conversions times + * the convert time. + */ + arg = cmd->convert_arg * cmd->scan_end_arg; + err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, + arg); + } } - err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, - cmd->chanlist_len); - if (cmd->stop_src == TRIG_COUNT) err |= comedi_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff); else /* TRIG_NONE */ @@ -425,16 +442,14 @@ static int daqp_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ - if (cmd->scan_begin_src == TRIG_TIMER) { - arg = cmd->scan_begin_arg; - daqp_ns_to_timer(&arg, cmd->flags); - err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg); - } - if (cmd->convert_src == TRIG_TIMER) { arg = cmd->convert_arg; - daqp_ns_to_timer(&arg, cmd->flags); + devpriv->pacer_div = daqp_ns_to_timer(&arg, cmd->flags); err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg); + } else if (cmd->scan_begin_src == TRIG_TIMER) { + arg = cmd->scan_begin_arg; + devpriv->pacer_div = daqp_ns_to_timer(&arg, cmd->flags); + err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (err) @@ -447,23 +462,18 @@ static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct daqp_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; - int counter; int scanlist_start_on_every_entry; int threshold; - + int ret; int i; - int v; if (devpriv->stop) return -EIO; - /* Stop any running conversion */ - daqp_ai_cancel(dev, s); - - outb(0, dev->iobase + DAQP_AUX); + outb(0, dev->iobase + DAQP_AUX_REG); /* Reset scan list queue */ - outb(DAQP_COMMAND_RSTQ, dev->iobase + DAQP_COMMAND); + outb(DAQP_CMD_RSTQ, dev->iobase + DAQP_CMD_REG); /* Program pacer clock * @@ -477,20 +487,12 @@ static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * each scan, so we program the pacer clock to this frequency * and only set the SCANLIST_START bit on the first entry. */ + daqp_set_pacer(dev, devpriv->pacer_div); - if (cmd->convert_src == TRIG_TIMER) { - counter = daqp_ns_to_timer(&cmd->convert_arg, cmd->flags); - outb(counter & 0xff, dev->iobase + DAQP_PACER_LOW); - outb((counter >> 8) & 0xff, dev->iobase + DAQP_PACER_MID); - outb((counter >> 16) & 0xff, dev->iobase + DAQP_PACER_HIGH); + if (cmd->convert_src == TRIG_TIMER) scanlist_start_on_every_entry = 1; - } else { - counter = daqp_ns_to_timer(&cmd->scan_begin_arg, cmd->flags); - outb(counter & 0xff, dev->iobase + DAQP_PACER_LOW); - outb((counter >> 8) & 0xff, dev->iobase + DAQP_PACER_MID); - outb((counter >> 16) & 0xff, dev->iobase + DAQP_PACER_HIGH); + else scanlist_start_on_every_entry = 0; - } /* Program scan list */ for (i = 0; i < cmd->chanlist_len; i++) { @@ -581,7 +583,7 @@ static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* Reset data FIFO (see page 28 of DAQP User's Manual) */ - outb(DAQP_COMMAND_RSTF, dev->iobase + DAQP_COMMAND); + outb(DAQP_CMD_RSTF, dev->iobase + DAQP_CMD_REG); /* Set FIFO threshold. First two bytes are near-empty * threshold, which is unused; next two bytes are near-full @@ -591,41 +593,40 @@ static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * when the interrupt is to happen. */ - outb(0x00, dev->iobase + DAQP_FIFO); - outb(0x00, dev->iobase + DAQP_FIFO); - - outb((DAQP_FIFO_SIZE - threshold) & 0xff, dev->iobase + DAQP_FIFO); - outb((DAQP_FIFO_SIZE - threshold) >> 8, dev->iobase + DAQP_FIFO); + outb(0x00, dev->iobase + DAQP_AI_FIFO_REG); + outb(0x00, dev->iobase + DAQP_AI_FIFO_REG); - /* Set trigger */ + outb((DAQP_FIFO_SIZE - threshold) & 0xff, + dev->iobase + DAQP_AI_FIFO_REG); + outb((DAQP_FIFO_SIZE - threshold) >> 8, dev->iobase + DAQP_AI_FIFO_REG); - v = DAQP_CONTROL_TRIGGER_CONTINUOUS | DAQP_CONTROL_TRIGGER_INTERNAL - | DAQP_CONTROL_PACER_5MHz | DAQP_CONTROL_FIFO_INT_ENABLE; - - outb(v, dev->iobase + DAQP_CONTROL); - - /* Reset any pending interrupts (my card has a tendency to require - * require multiple reads on the status register to achieve this) - */ - counter = 100; - while (--counter - && (inb(dev->iobase + DAQP_STATUS) & DAQP_STATUS_EVENTS)) - ; - if (!counter) { - dev_err(dev->class_dev, - "couldn't clear interrupts in status register\n"); - return -1; - } + /* Set trigger - continuous, internal */ + outb(DAQP_CTRL_TRIG_MODE | DAQP_CTRL_PACER_CLK_5MHZ | + DAQP_CTRL_FIFO_INT_ENA, dev->iobase + DAQP_CTRL_REG); - devpriv->interrupt_mode = buffer; + ret = daqp_clear_events(dev, 100); + if (ret) + return ret; /* Start conversion */ - outb(DAQP_COMMAND_ARM | DAQP_COMMAND_FIFO_DATA, - dev->iobase + DAQP_COMMAND); + outb(DAQP_CMD_ARM | DAQP_CMD_FIFO_DATA, dev->iobase + DAQP_CMD_REG); return 0; } +static int daqp_ao_empty(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned long context) +{ + unsigned int status; + + status = inb(dev->iobase + DAQP_AUX_REG); + if ((status & DAQP_AUX_DA_BUFFER) == 0) + return 0; + return -EBUSY; +} + static int daqp_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -639,18 +640,22 @@ static int daqp_ao_insn_write(struct comedi_device *dev, return -EIO; /* Make sure D/A update mode is direct update */ - outb(0, dev->iobase + DAQP_AUX); + outb(0, dev->iobase + DAQP_AUX_REG); for (i = 0; i > insn->n; i++) { unsigned val = data[i]; + int ret; - s->readback[chan] = val; + /* D/A transfer rate is about 8ms */ + ret = comedi_timeout(dev, s, insn, daqp_ao_empty, 0); + if (ret) + return ret; - val &= 0x0fff; - val ^= 0x0800; /* Flip the sign */ - val |= (chan << 12); + /* write the two's complement value to the channel */ + outw((chan << 12) | comedi_offset_munge(s, val), + dev->iobase + DAQP_AO_REG); - outw(val, dev->iobase + DAQP_DA); + s->readback[chan] = val; } return insn->n; @@ -666,7 +671,7 @@ static int daqp_di_insn_bits(struct comedi_device *dev, if (devpriv->stop) return -EIO; - data[0] = inb(dev->iobase + DAQP_DIGITAL_IO); + data[0] = inb(dev->iobase + DAQP_DI_REG); return insn->n; } @@ -682,7 +687,7 @@ static int daqp_do_insn_bits(struct comedi_device *dev, return -EIO; if (comedi_dio_update_state(s, data)) - outb(s->state, dev->iobase + DAQP_DIGITAL_IO); + outb(s->state, dev->iobase + DAQP_DO_REG); data[1] = s->state; @@ -709,25 +714,28 @@ static int daqp_auto_attach(struct comedi_device *dev, link->priv = dev; ret = pcmcia_request_irq(link, daqp_interrupt); - if (ret) - return ret; + if (ret == 0) + dev->irq = link->irq; ret = comedi_alloc_subdevices(dev, 4); if (ret) return ret; s = &dev->subdevices[0]; - dev->read_subdev = s; s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; s->n_chan = 8; - s->len_chanlist = 2048; s->maxdata = 0xffff; s->range_table = &range_daqp_ai; s->insn_read = daqp_ai_insn_read; - s->do_cmdtest = daqp_ai_cmdtest; - s->do_cmd = daqp_ai_cmd; - s->cancel = daqp_ai_cancel; + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = 2048; + s->do_cmdtest = daqp_ai_cmdtest; + s->do_cmd = daqp_ai_cmd; + s->cancel = daqp_ai_cancel; + } s = &dev->subdevices[1]; s->type = COMEDI_SUBD_AO; @@ -741,17 +749,35 @@ static int daqp_auto_attach(struct comedi_device *dev, if (ret) return ret; + /* + * Digital Input subdevice + * NOTE: The digital input lines are shared: + * + * Chan Normal Mode Expansion Mode + * ---- ----------------- ---------------------------- + * 0 DI0, ext. trigger Same as normal mode + * 1 DI1 External gain select, lo bit + * 2 DI2, ext. clock Same as normal mode + * 3 DI3 External gain select, hi bit + */ s = &dev->subdevices[2]; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; - s->n_chan = 1; + s->n_chan = 4; s->maxdata = 1; s->insn_bits = daqp_di_insn_bits; + /* + * Digital Output subdevice + * NOTE: The digital output lines share the same pins on the + * interface connector as the four external channel selection + * bits. If expansion mode is used the digital outputs do not + * work. + */ s = &dev->subdevices[3]; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = 1; + s->n_chan = 4; s->maxdata = 1; s->insn_bits = daqp_do_insn_bits; diff --git a/kernel/drivers/staging/comedi/drivers/rtd520.c b/kernel/drivers/staging/comedi/drivers/rtd520.c index 4c13f5eb0..68ac02b68 100644 --- a/kernel/drivers/staging/comedi/drivers/rtd520.c +++ b/kernel/drivers/staging/comedi/drivers/rtd520.c @@ -72,8 +72,6 @@ * As far as I can tell, the About interrupt doesn't work if Sample is * also enabled. It turns out that About really isn't needed, since * we always count down samples read. - * - * There was some timer/counter code, but it didn't follow the right API. */ /* @@ -99,6 +97,7 @@ #include "../comedi_pci.h" +#include "comedi_8254.h" #include "plx9080.h" /* @@ -106,39 +105,38 @@ */ #define LAS0_USER_IO 0x0008 /* User I/O */ #define LAS0_ADC 0x0010 /* FIFO Status/Software A/D Start */ -#define FS_DAC1_NOT_EMPTY (1 << 0) /* DAC1 FIFO not empty */ -#define FS_DAC1_HEMPTY (1 << 1) /* DAC1 FIFO half empty */ -#define FS_DAC1_NOT_FULL (1 << 2) /* DAC1 FIFO not full */ -#define FS_DAC2_NOT_EMPTY (1 << 4) /* DAC2 FIFO not empty */ -#define FS_DAC2_HEMPTY (1 << 5) /* DAC2 FIFO half empty */ -#define FS_DAC2_NOT_FULL (1 << 6) /* DAC2 FIFO not full */ -#define FS_ADC_NOT_EMPTY (1 << 8) /* ADC FIFO not empty */ -#define FS_ADC_HEMPTY (1 << 9) /* ADC FIFO half empty */ -#define FS_ADC_NOT_FULL (1 << 10) /* ADC FIFO not full */ -#define FS_DIN_NOT_EMPTY (1 << 12) /* DIN FIFO not empty */ -#define FS_DIN_HEMPTY (1 << 13) /* DIN FIFO half empty */ -#define FS_DIN_NOT_FULL (1 << 14) /* DIN FIFO not full */ -#define LAS0_DAC1 0x0014 /* Software D/A1 Update (w) */ -#define LAS0_DAC2 0x0018 /* Software D/A2 Update (w) */ +#define FS_DAC1_NOT_EMPTY BIT(0) /* DAC1 FIFO not empty */ +#define FS_DAC1_HEMPTY BIT(1) /* DAC1 FIFO half empty */ +#define FS_DAC1_NOT_FULL BIT(2) /* DAC1 FIFO not full */ +#define FS_DAC2_NOT_EMPTY BIT(4) /* DAC2 FIFO not empty */ +#define FS_DAC2_HEMPTY BIT(5) /* DAC2 FIFO half empty */ +#define FS_DAC2_NOT_FULL BIT(6) /* DAC2 FIFO not full */ +#define FS_ADC_NOT_EMPTY BIT(8) /* ADC FIFO not empty */ +#define FS_ADC_HEMPTY BIT(9) /* ADC FIFO half empty */ +#define FS_ADC_NOT_FULL BIT(10) /* ADC FIFO not full */ +#define FS_DIN_NOT_EMPTY BIT(12) /* DIN FIFO not empty */ +#define FS_DIN_HEMPTY BIT(13) /* DIN FIFO half empty */ +#define FS_DIN_NOT_FULL BIT(14) /* DIN FIFO not full */ +#define LAS0_UPDATE_DAC(x) (0x0014 + ((x) * 0x4)) /* D/Ax Update (w) */ #define LAS0_DAC 0x0024 /* Software Simultaneous Update (w) */ #define LAS0_PACER 0x0028 /* Software Pacer Start/Stop */ #define LAS0_TIMER 0x002c /* Timer Status/HDIN Software Trig. */ #define LAS0_IT 0x0030 /* Interrupt Status/Enable */ -#define IRQM_ADC_FIFO_WRITE (1 << 0) /* ADC FIFO Write */ -#define IRQM_CGT_RESET (1 << 1) /* Reset CGT */ -#define IRQM_CGT_PAUSE (1 << 3) /* Pause CGT */ -#define IRQM_ADC_ABOUT_CNT (1 << 4) /* About Counter out */ -#define IRQM_ADC_DELAY_CNT (1 << 5) /* Delay Counter out */ -#define IRQM_ADC_SAMPLE_CNT (1 << 6) /* ADC Sample Counter */ -#define IRQM_DAC1_UCNT (1 << 7) /* DAC1 Update Counter */ -#define IRQM_DAC2_UCNT (1 << 8) /* DAC2 Update Counter */ -#define IRQM_UTC1 (1 << 9) /* User TC1 out */ -#define IRQM_UTC1_INV (1 << 10) /* User TC1 out, inverted */ -#define IRQM_UTC2 (1 << 11) /* User TC2 out */ -#define IRQM_DIGITAL_IT (1 << 12) /* Digital Interrupt */ -#define IRQM_EXTERNAL_IT (1 << 13) /* External Interrupt */ -#define IRQM_ETRIG_RISING (1 << 14) /* Ext Trigger rising-edge */ -#define IRQM_ETRIG_FALLING (1 << 15) /* Ext Trigger falling-edge */ +#define IRQM_ADC_FIFO_WRITE BIT(0) /* ADC FIFO Write */ +#define IRQM_CGT_RESET BIT(1) /* Reset CGT */ +#define IRQM_CGT_PAUSE BIT(3) /* Pause CGT */ +#define IRQM_ADC_ABOUT_CNT BIT(4) /* About Counter out */ +#define IRQM_ADC_DELAY_CNT BIT(5) /* Delay Counter out */ +#define IRQM_ADC_SAMPLE_CNT BIT(6) /* ADC Sample Counter */ +#define IRQM_DAC1_UCNT BIT(7) /* DAC1 Update Counter */ +#define IRQM_DAC2_UCNT BIT(8) /* DAC2 Update Counter */ +#define IRQM_UTC1 BIT(9) /* User TC1 out */ +#define IRQM_UTC1_INV BIT(10) /* User TC1 out, inverted */ +#define IRQM_UTC2 BIT(11) /* User TC2 out */ +#define IRQM_DIGITAL_IT BIT(12) /* Digital Interrupt */ +#define IRQM_EXTERNAL_IT BIT(13) /* External Interrupt */ +#define IRQM_ETRIG_RISING BIT(14) /* Ext Trigger rising-edge */ +#define IRQM_ETRIG_FALLING BIT(15) /* Ext Trigger falling-edge */ #define LAS0_CLEAR 0x0034 /* Clear/Set Interrupt Clear Mask */ #define LAS0_OVERRUN 0x0038 /* Pending interrupts/Clear Overrun */ #define LAS0_PCLK 0x0040 /* Pacer Clock (24bit) */ @@ -149,10 +147,7 @@ #define LAS0_DCNT 0x0054 /* Delay counter (16 bit) */ #define LAS0_ACNT 0x0058 /* About counter (16 bit) */ #define LAS0_DAC_CLK 0x005c /* DAC clock (16bit) */ -#define LAS0_UTC0 0x0060 /* 8254 TC Counter 0 */ -#define LAS0_UTC1 0x0064 /* 8254 TC Counter 1 */ -#define LAS0_UTC2 0x0068 /* 8254 TC Counter 2 */ -#define LAS0_UTC_CTRL 0x006c /* 8254 TC Control */ +#define LAS0_8254_TIMER_BASE 0x0060 /* 8254 timer/counter base */ #define LAS0_DIO0 0x0070 /* Digital I/O Port 0 */ #define LAS0_DIO1 0x0074 /* Digital I/O Port 1 */ #define LAS0_DIO0_CTRL 0x0078 /* Digital I/O Control */ @@ -177,16 +172,11 @@ #define LAS0_CGT_PAUSE 0x0144 /* Table Pause Enable */ #define LAS0_CGT_RESET 0x0148 /* Reset Channel Gain Table */ #define LAS0_CGT_CLEAR 0x014c /* Clear Channel Gain Table */ -#define LAS0_DAC1_CTRL 0x0150 /* D/A1 output type/range */ -#define LAS0_DAC1_SRC 0x0154 /* D/A1 update source */ -#define LAS0_DAC1_CYCLE 0x0158 /* D/A1 cycle mode */ -#define LAS0_DAC1_RESET 0x015c /* D/A1 FIFO reset */ -#define LAS0_DAC1_FIFO_CLEAR 0x0160 /* D/A1 FIFO clear */ -#define LAS0_DAC2_CTRL 0x0164 /* D/A2 output type/range */ -#define LAS0_DAC2_SRC 0x0168 /* D/A2 update source */ -#define LAS0_DAC2_CYCLE 0x016c /* D/A2 cycle mode */ -#define LAS0_DAC2_RESET 0x0170 /* D/A2 FIFO reset */ -#define LAS0_DAC2_FIFO_CLEAR 0x0174 /* D/A2 FIFO clear */ +#define LAS0_DAC_CTRL(x) (0x0150 + ((x) * 0x14)) /* D/Ax type/range */ +#define LAS0_DAC_SRC(x) (0x0154 + ((x) * 0x14)) /* D/Ax update source */ +#define LAS0_DAC_CYCLE(x) (0x0158 + ((x) * 0x14)) /* D/Ax cycle mode */ +#define LAS0_DAC_RESET(x) (0x015c + ((x) * 0x14)) /* D/Ax FIFO reset */ +#define LAS0_DAC_FIFO_CLEAR(x) (0x0160 + ((x) * 0x14)) /* D/Ax FIFO clear */ #define LAS0_ADC_SCNT_SRC 0x0178 /* A/D Sample Counter Source select */ #define LAS0_PACER_SELECT 0x0180 /* Pacer Clock select */ #define LAS0_SBUS0_SRC 0x0184 /* SyncBus 0 Source select */ @@ -197,12 +187,8 @@ #define LAS0_SBUS2_ENABLE 0x019c /* SyncBus 2 enable */ #define LAS0_ETRG_POLARITY 0x01a4 /* Ext. Trigger polarity select */ #define LAS0_EINT_POLARITY 0x01a8 /* Ext. Interrupt polarity select */ -#define LAS0_UTC0_CLOCK 0x01ac /* UTC0 Clock select */ -#define LAS0_UTC0_GATE 0x01b0 /* UTC0 Gate select */ -#define LAS0_UTC1_CLOCK 0x01b4 /* UTC1 Clock select */ -#define LAS0_UTC1_GATE 0x01b8 /* UTC1 Gate select */ -#define LAS0_UTC2_CLOCK 0x01bc /* UTC2 Clock select */ -#define LAS0_UTC2_GATE 0x01c0 /* UTC2 Gate select */ +#define LAS0_8254_CLK_SEL(x) (0x01ac + ((x) * 0x8)) /* 8254 clock select */ +#define LAS0_8254_GATE_SEL(x) (0x01b0 + ((x) * 0x8)) /* 8254 gate select */ #define LAS0_UOUT0_SELECT 0x01c4 /* User Output 0 source select */ #define LAS0_UOUT1_SELECT 0x01c8 /* User Output 1 source select */ #define LAS0_DMA0_RESET 0x01cc /* DMA0 Request state machine reset */ @@ -213,15 +199,16 @@ */ #define LAS1_ADC_FIFO 0x0000 /* A/D FIFO (16bit) */ #define LAS1_HDIO_FIFO 0x0004 /* HiSpd DI FIFO (16bit) */ -#define LAS1_DAC1_FIFO 0x0008 /* D/A1 FIFO (16bit) */ -#define LAS1_DAC2_FIFO 0x000c /* D/A2 FIFO (16bit) */ +#define LAS1_DAC_FIFO(x) (0x0008 + ((x) * 0x4)) /* D/Ax FIFO (16bit) */ -/*====================================================================== - Driver specific stuff (tunable) -======================================================================*/ +/* + * Driver specific stuff (tunable) + */ -/* We really only need 2 buffers. More than that means being much - smarter about knowing which ones are full. */ +/* + * We really only need 2 buffers. More than that means being much + * smarter about knowing which ones are full. + */ #define DMA_CHAIN_COUNT 2 /* max DMA segments/buffers in a ring (min 2) */ /* Target period for periodic transfers. This sets the user read latency. */ @@ -233,9 +220,9 @@ /* The board support a channel list up to the FIFO length (1K or 8K) */ #define RTD_MAX_CHANLIST 128 /* max channel list that we allow */ -/*====================================================================== - Board specific stuff -======================================================================*/ +/* + * Board specific stuff + */ #define RTD_CLOCK_RATE 8000000 /* 8Mhz onboard clock */ #define RTD_CLOCK_BASE 125 /* clock period in ns */ @@ -264,9 +251,9 @@ /* interrupt at end of block */ | PLX_INTR_TERM_COUNT \ /* from board to PCI */ | PLX_XFER_LOCAL_TO_PCI) -/*====================================================================== - Comedi specific stuff -======================================================================*/ +/* + * Comedi specific stuff + */ /* * The board has 3 input modes and the gains of 1,2,4,...32 (, 64, 128) @@ -352,7 +339,7 @@ struct rtd_boardinfo { const struct comedi_lrange *ai_range; }; -static const struct rtd_boardinfo rtd520Boards[] = { +static const struct rtd_boardinfo rtd520_boards[] = { [BOARD_DM7520] = { .name = "DM7520", .range_bip10 = 6, @@ -376,6 +363,10 @@ struct rtd_private { int xfer_count; /* # to transfer data. 0->1/2FIFO */ int flags; /* flag event modes */ unsigned fifosz; + + /* 8254 Timer/Counter gate and clock sources */ + unsigned char timer_gate_src[3]; + unsigned char timer_clk_src[3]; }; /* bit defines for "flags" */ @@ -384,11 +375,11 @@ struct rtd_private { #define DMA1_ACTIVE 0x04 /* DMA1 is active */ /* - Given a desired period and the clock period (both in ns), - return the proper counter value (divider-1). - Sets the original period to be the true value. - Note: you have to check if the value is larger than the counter range! -*/ + * Given a desired period and the clock period (both in ns), return the + * proper counter value (divider-1). Sets the original period to be the + * true value. + * Note: you have to check if the value is larger than the counter range! + */ static int rtd_ns_to_timer_base(unsigned int *nanosec, unsigned int flags, int base) { @@ -397,38 +388,38 @@ static int rtd_ns_to_timer_base(unsigned int *nanosec, switch (flags & CMDF_ROUND_MASK) { case CMDF_ROUND_NEAREST: default: - divider = (*nanosec + base / 2) / base; + divider = DIV_ROUND_CLOSEST(*nanosec, base); break; case CMDF_ROUND_DOWN: divider = (*nanosec) / base; break; case CMDF_ROUND_UP: - divider = (*nanosec + base - 1) / base; + divider = DIV_ROUND_UP(*nanosec, base); break; } if (divider < 2) divider = 2; /* min is divide by 2 */ - /* Note: we don't check for max, because different timers - have different ranges */ + /* + * Note: we don't check for max, because different timers + * have different ranges + */ *nanosec = base * divider; return divider - 1; /* countdown is divisor+1 */ } /* - Given a desired period (in ns), - return the proper counter value (divider-1) for the internal clock. - Sets the original period to be the true value. -*/ + * Given a desired period (in ns), return the proper counter value + * (divider-1) for the internal clock. Sets the original period to + * be the true value. + */ static int rtd_ns_to_timer(unsigned int *ns, unsigned int flags) { return rtd_ns_to_timer_base(ns, flags, RTD_CLOCK_BASE); } -/* - Convert a single comedi channel-gain entry to a RTD520 table entry -*/ +/* Convert a single comedi channel-gain entry to a RTD520 table entry */ static unsigned short rtd_convert_chan_gain(struct comedi_device *dev, unsigned int chanspec, int index) { @@ -473,9 +464,7 @@ static unsigned short rtd_convert_chan_gain(struct comedi_device *dev, return r; } -/* - Setup the channel-gain table from a comedi list -*/ +/* Setup the channel-gain table from a comedi list */ static void rtd_load_channelgain_list(struct comedi_device *dev, unsigned int n_chan, unsigned int *list) { @@ -495,8 +484,10 @@ static void rtd_load_channelgain_list(struct comedi_device *dev, } } -/* determine fifo size by doing adc conversions until the fifo half -empty status flag clears */ +/* + * Determine fifo size by doing adc conversions until the fifo half + * empty status flag clears. + */ static int rtd520_probe_fifo_depth(struct comedi_device *dev) { unsigned int chanspec = CR_PACK(0, 0, AREF_GROUND); @@ -513,7 +504,7 @@ static int rtd520_probe_fifo_depth(struct comedi_device *dev) unsigned fifo_status; /* trigger conversion */ writew(0, dev->mmio + LAS0_ADC); - udelay(1); + usleep_range(1, 1000); fifo_status = readl(dev->mmio + LAS0_ADC); if ((fifo_status & FS_ADC_HEMPTY) == 0) { fifo_size = 2 * i; @@ -590,12 +581,6 @@ static int rtd_ai_rinsn(struct comedi_device *dev, return n; } -/* - Get what we know is there.... Fast! - This uses 1/2 the bus cycles of read_dregs (below). - - The manual claims that we can do a lword read, but it doesn't work here. -*/ static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s, int count) { @@ -608,7 +593,7 @@ static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int range = CR_RANGE(cmd->chanlist[async->cur_chan]); unsigned short d; - if (0 == devpriv->ai_count) { /* done */ + if (devpriv->ai_count == 0) { /* done */ d = readw(devpriv->las1 + LAS1_ADC_FIFO); continue; } @@ -630,12 +615,6 @@ static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s, return 0; } -/* - Handle all rtd520 interrupts. - Runs atomically and is never re-entered. - This is a "slow handler"; other interrupts may be active. - The data conversion may someday happen in a "bottom half". -*/ static irqreturn_t rtd_interrupt(int irq, void *d) { struct comedi_device *dev = d; @@ -655,7 +634,7 @@ static irqreturn_t rtd_interrupt(int irq, void *d) status = readw(dev->mmio + LAS0_IT); /* if interrupt was not caused by our board, or handled above */ - if (0 == status) + if (status == 0) return IRQ_HANDLED; if (status & IRQM_ADC_ABOUT_CNT) { /* sample count -> read FIFO */ @@ -670,7 +649,7 @@ static irqreturn_t rtd_interrupt(int irq, void *d) if (ai_read_n(dev, s, devpriv->fifosz / 2) < 0) goto xfer_abort; - if (0 == devpriv->ai_count) + if (devpriv->ai_count == 0) goto xfer_done; } else if (devpriv->xfer_count > 0) { if (fifo_status & FS_ADC_NOT_EMPTY) { @@ -678,7 +657,7 @@ static irqreturn_t rtd_interrupt(int irq, void *d) if (ai_read_n(dev, s, devpriv->xfer_count) < 0) goto xfer_abort; - if (0 == devpriv->ai_count) + if (devpriv->ai_count == 0) goto xfer_done; } } @@ -715,15 +694,6 @@ xfer_done: return IRQ_HANDLED; } -/* - cmdtest tests a particular command to see if it is valid. - Using the cmdtest ioctl, a user can create a valid cmd - and then have it executed by the cmd ioctl (asynchronously). - - cmdtest returns 1,2,3,4 or 0, depending on which tests - the command passes. -*/ - static int rtd_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { @@ -760,7 +730,7 @@ static int rtd_ai_cmdtest(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER) { /* Note: these are time periods, not actual rates */ - if (1 == cmd->chanlist_len) { /* no scanning */ + if (cmd->chanlist_len == 1) { /* no scanning */ if (comedi_check_trigger_arg_min(&cmd->scan_begin_arg, RTD_MAX_SPEED_1)) { rtd_ns_to_timer(&cmd->scan_begin_arg, @@ -795,7 +765,7 @@ static int rtd_ai_cmdtest(struct comedi_device *dev, } if (cmd->convert_src == TRIG_TIMER) { - if (1 == cmd->chanlist_len) { /* no scanning */ + if (cmd->chanlist_len == 1) { /* no scanning */ if (comedi_check_trigger_arg_min(&cmd->convert_arg, RTD_MAX_SPEED_1)) { rtd_ns_to_timer(&cmd->convert_arg, @@ -866,12 +836,6 @@ static int rtd_ai_cmdtest(struct comedi_device *dev, return 0; } -/* - Execute a analog in command with many possible triggering options. - The data get stored in the async structure of the subdevice. - This is usually done by an interrupt handler. - Userland gets to the data using read calls. -*/ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct rtd_private *devpriv = dev->private; @@ -907,7 +871,7 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } writel((devpriv->fifosz / 2 - 1) & 0xffff, dev->mmio + LAS0_ACNT); - if (TRIG_TIMER == cmd->scan_begin_src) { + if (cmd->scan_begin_src == TRIG_TIMER) { /* scan_begin_arg is in nanoseconds */ /* find out how many samples to wait before transferring */ if (cmd->flags & CMDF_WAKE_EOS) { @@ -959,8 +923,8 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) switch (cmd->stop_src) { case TRIG_COUNT: /* stop after N scans */ devpriv->ai_count = cmd->stop_arg * cmd->chanlist_len; - if ((devpriv->xfer_count > 0) - && (devpriv->xfer_count > devpriv->ai_count)) { + if ((devpriv->xfer_count > 0) && + (devpriv->xfer_count > devpriv->ai_count)) { devpriv->xfer_count = devpriv->ai_count; } break; @@ -1006,8 +970,10 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } /* end configuration */ - /* This doesn't seem to work. There is no way to clear an interrupt - that the priority controller has queued! */ + /* + * This doesn't seem to work. There is no way to clear an interrupt + * that the priority controller has queued! + */ writew(~0, dev->mmio + LAS0_CLEAR); readw(dev->mmio + LAS0_CLEAR); @@ -1021,9 +987,6 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } -/* - Stop a running data acquisition. -*/ static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct rtd_private *devpriv = dev->private; @@ -1053,49 +1016,43 @@ static int rtd_ao_eoc(struct comedi_device *dev, return -EBUSY; } -static int rtd_ao_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data) +static int rtd_ao_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct rtd_private *devpriv = dev->private; - int i; - int chan = CR_CHAN(insn->chanspec); - int range = CR_RANGE(insn->chanspec); + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); int ret; + int i; /* Configure the output range (table index matches the range values) */ - writew(range & 7, - dev->mmio + ((chan == 0) ? LAS0_DAC1_CTRL : LAS0_DAC2_CTRL)); + writew(range & 7, dev->mmio + LAS0_DAC_CTRL(chan)); - /* Writing a list of values to an AO channel is probably not - * very useful, but that's how the interface is defined. */ for (i = 0; i < insn->n; ++i) { - int val = data[i] << 3; + unsigned int val = data[i]; - /* VERIFY: comedi range and offset conversions */ - - if ((range > 1) /* bipolar */ - && (data[i] < 2048)) { - /* offset and sign extend */ - val = (((int)data[i]) - 2048) << 3; - } else { /* unipolor */ - val = data[i] << 3; + /* bipolar uses 2's complement values with an extended sign */ + if (comedi_range_is_bipolar(s, range)) { + val = comedi_offset_munge(s, val); + val |= (val & ((s->maxdata + 1) >> 1)) << 1; } - /* a typical programming sequence */ - writew(val, devpriv->las1 + - ((chan == 0) ? LAS1_DAC1_FIFO : LAS1_DAC2_FIFO)); - writew(0, dev->mmio + ((chan == 0) ? LAS0_DAC1 : LAS0_DAC2)); + /* shift the 12-bit data (+ sign) to match the register */ + val <<= 3; - s->readback[chan] = data[i]; + writew(val, devpriv->las1 + LAS1_DAC_FIFO(chan)); + writew(0, dev->mmio + LAS0_UPDATE_DAC(chan)); ret = comedi_timeout(dev, s, insn, rtd_ao_eoc, 0); if (ret) return ret; + + s->readback[chan] = data[i]; } - /* return the number of samples read/written */ - return i; + return insn->n; } static int rtd_dio_insn_bits(struct comedi_device *dev, @@ -1138,12 +1095,87 @@ static int rtd_dio_insn_config(struct comedi_device *dev, return insn->n; } +static int rtd_counter_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct rtd_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int max_src; + unsigned int src; + + switch (data[0]) { + case INSN_CONFIG_SET_GATE_SRC: + /* + * 8254 Timer/Counter gate sources: + * + * 0 = Not gated, free running (reset state) + * 1 = Gated, off + * 2 = Ext. TC Gate 1 + * 3 = Ext. TC Gate 2 + * 4 = Previous TC out (chan 1 and 2 only) + */ + src = data[2]; + max_src = (chan == 0) ? 3 : 4; + if (src > max_src) + return -EINVAL; + + devpriv->timer_gate_src[chan] = src; + writeb(src, dev->mmio + LAS0_8254_GATE_SEL(chan)); + break; + case INSN_CONFIG_GET_GATE_SRC: + data[2] = devpriv->timer_gate_src[chan]; + break; + case INSN_CONFIG_SET_CLOCK_SRC: + /* + * 8254 Timer/Counter clock sources: + * + * 0 = 8 MHz (reset state) + * 1 = Ext. TC Clock 1 + * 2 = Ext. TX Clock 2 + * 3 = Ext. Pacer Clock + * 4 = Previous TC out (chan 1 and 2 only) + * 5 = High-Speed Digital Input Sampling signal (chan 1 only) + */ + src = data[1]; + switch (chan) { + case 0: + max_src = 3; + break; + case 1: + max_src = 5; + break; + case 2: + max_src = 4; + break; + default: + return -EINVAL; + } + if (src > max_src) + return -EINVAL; + + devpriv->timer_clk_src[chan] = src; + writeb(src, dev->mmio + LAS0_8254_CLK_SEL(chan)); + break; + case INSN_CONFIG_GET_CLOCK_SRC: + src = devpriv->timer_clk_src[chan]; + data[1] = devpriv->timer_clk_src[chan]; + data[2] = (src == 0) ? RTD_CLOCK_BASE : 0; + break; + default: + return -EINVAL; + } + + return insn->n; +} + static void rtd_reset(struct comedi_device *dev) { struct rtd_private *devpriv = dev->private; writel(0, dev->mmio + LAS0_BOARD_RESET); - udelay(100); /* needed? */ + usleep_range(100, 1000); /* needed? */ writel(0, devpriv->lcfg + PLX_INTRCS_REG); writew(0, dev->mmio + LAS0_IT); writew(~0, dev->mmio + LAS0_CLEAR); @@ -1161,14 +1193,10 @@ static void rtd_init_board(struct comedi_device *dev) writel(0, dev->mmio + LAS0_OVERRUN); writel(0, dev->mmio + LAS0_CGT_CLEAR); writel(0, dev->mmio + LAS0_ADC_FIFO_CLEAR); - writel(0, dev->mmio + LAS0_DAC1_RESET); - writel(0, dev->mmio + LAS0_DAC2_RESET); + writel(0, dev->mmio + LAS0_DAC_RESET(0)); + writel(0, dev->mmio + LAS0_DAC_RESET(1)); /* clear digital IO fifo */ writew(0, dev->mmio + LAS0_DIO_STATUS); - writeb((0 << 6) | 0x30, dev->mmio + LAS0_UTC_CTRL); - writeb((1 << 6) | 0x30, dev->mmio + LAS0_UTC_CTRL); - writeb((2 << 6) | 0x30, dev->mmio + LAS0_UTC_CTRL); - writeb((3 << 6) | 0x00, dev->mmio + LAS0_UTC_CTRL); /* TODO: set user out source ??? */ } @@ -1196,8 +1224,8 @@ static int rtd_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - if (context < ARRAY_SIZE(rtd520Boards)) - board = &rtd520Boards[context]; + if (context < ARRAY_SIZE(rtd520_boards)) + board = &rtd520_boards[context]; if (!board) return -ENODEV; dev->board_ptr = board; @@ -1254,7 +1282,7 @@ static int rtd_auto_attach(struct comedi_device *dev, s->n_chan = 2; s->maxdata = 0x0fff; s->range_table = &rtd_ao_range; - s->insn_write = rtd_ao_winsn; + s->insn_write = rtd_ao_insn_write; ret = comedi_alloc_subdev_readback(s); if (ret) @@ -1271,12 +1299,15 @@ static int rtd_auto_attach(struct comedi_device *dev, s->insn_bits = rtd_dio_insn_bits; s->insn_config = rtd_dio_insn_config; - /* timer/counter subdevices (not currently supported) */ + /* 8254 Timer/Counter subdevice */ s = &dev->subdevices[3]; - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 3; - s->maxdata = 0xffff; + dev->pacer = comedi_8254_mm_init(dev->mmio + LAS0_8254_TIMER_BASE, + RTD_CLOCK_BASE, I8254_IO8, 2); + if (!dev->pacer) + return -ENOMEM; + + comedi_8254_subdevice_init(s, dev->pacer); + dev->pacer->insn_config = rtd_counter_insn_config; rtd_init_board(dev); diff --git a/kernel/drivers/staging/comedi/drivers/rti800.c b/kernel/drivers/staging/comedi/drivers/rti800.c index 340ac776e..cd61d2645 100644 --- a/kernel/drivers/staging/comedi/drivers/rti800.c +++ b/kernel/drivers/staging/comedi/drivers/rti800.c @@ -57,14 +57,14 @@ * Register map */ #define RTI800_CSR 0x00 -#define RTI800_CSR_BUSY (1 << 7) -#define RTI800_CSR_DONE (1 << 6) -#define RTI800_CSR_OVERRUN (1 << 5) -#define RTI800_CSR_TCR (1 << 4) -#define RTI800_CSR_DMA_ENAB (1 << 3) -#define RTI800_CSR_INTR_TC (1 << 2) -#define RTI800_CSR_INTR_EC (1 << 1) -#define RTI800_CSR_INTR_OVRN (1 << 0) +#define RTI800_CSR_BUSY BIT(7) +#define RTI800_CSR_DONE BIT(6) +#define RTI800_CSR_OVERRUN BIT(5) +#define RTI800_CSR_TCR BIT(4) +#define RTI800_CSR_DMA_ENAB BIT(3) +#define RTI800_CSR_INTR_TC BIT(2) +#define RTI800_CSR_INTR_EC BIT(1) +#define RTI800_CSR_INTR_OVRN BIT(0) #define RTI800_MUXGAIN 0x01 #define RTI800_CONVERT 0x02 #define RTI800_ADCLO 0x03 @@ -189,17 +189,21 @@ static int rti800_ai_insn_read(struct comedi_device *dev, } for (i = 0; i < insn->n; i++) { + unsigned int val; + outb(0, dev->iobase + RTI800_CONVERT); ret = comedi_timeout(dev, s, insn, rti800_ai_eoc, 0); if (ret) return ret; - data[i] = inb(dev->iobase + RTI800_ADCLO); - data[i] |= (inb(dev->iobase + RTI800_ADCHI) & 0xf) << 8; + val = inb(dev->iobase + RTI800_ADCLO); + val |= (inb(dev->iobase + RTI800_ADCHI) & 0xf) << 8; if (devpriv->adc_2comp) - data[i] ^= 0x800; + val = comedi_offset_munge(s, val); + + data[i] = val; } return insn->n; @@ -222,7 +226,7 @@ static int rti800_ao_insn_write(struct comedi_device *dev, s->readback[chan] = val; if (devpriv->dac_2comp[chan]) - val ^= 0x800; + val = comedi_offset_munge(s, val); outb(val & 0xff, dev->iobase + reg_lo); outb((val >> 8) & 0xff, dev->iobase + reg_hi); diff --git a/kernel/drivers/staging/comedi/drivers/s526.c b/kernel/drivers/staging/comedi/drivers/s526.c index 6f3e8a08e..d70c97947 100644 --- a/kernel/drivers/staging/comedi/drivers/s526.c +++ b/kernel/drivers/staging/comedi/drivers/s526.c @@ -1,79 +1,96 @@ /* - comedi/drivers/s526.c - Sensoray s526 Comedi driver - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ -/* -Driver: s526 -Description: Sensoray 526 driver -Devices: [Sensoray] 526 (s526) -Author: Richie - Everett Wang <everett.wang@everteq.com> -Updated: Thu, 14 Sep. 2006 -Status: experimental - -Encoder works -Analog input works -Analog output works -PWM output works -Commands are not supported yet. - -Configuration Options: + * s526.c + * Sensoray s526 Comedi driver + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ -comedi_config /dev/comedi0 s526 0x2C0,0x3 - -*/ +/* + * Driver: s526 + * Description: Sensoray 526 driver + * Devices: [Sensoray] 526 (s526) + * Author: Richie + * Everett Wang <everett.wang@everteq.com> + * Updated: Thu, 14 Sep. 2006 + * Status: experimental + * + * Encoder works + * Analog input works + * Analog output works + * PWM output works + * Commands are not supported yet. + * + * Configuration Options: + * [0] - I/O port base address + */ #include <linux/module.h> #include "../comedidev.h" #include <asm/byteorder.h> -#define S526_START_AI_CONV 0 -#define S526_AI_READ 0 - -/* Ports */ -#define S526_NUM_PORTS 27 - -/* registers */ -#define REG_TCR 0x00 -#define REG_WDC 0x02 -#define REG_DAC 0x04 -#define REG_ADC 0x06 -#define REG_ADD 0x08 -#define REG_DIO 0x0A -#define REG_IER 0x0C -#define REG_ISR 0x0E -#define REG_MSC 0x10 -#define REG_C0L 0x12 -#define REG_C0H 0x14 -#define REG_C0M 0x16 -#define REG_C0C 0x18 -#define REG_C1L 0x1A -#define REG_C1H 0x1C -#define REG_C1M 0x1E -#define REG_C1C 0x20 -#define REG_C2L 0x22 -#define REG_C2H 0x24 -#define REG_C2M 0x26 -#define REG_C2C 0x28 -#define REG_C3L 0x2A -#define REG_C3H 0x2C -#define REG_C3M 0x2E -#define REG_C3C 0x30 -#define REG_EED 0x32 -#define REG_EEC 0x34 +/* + * Register I/O map + */ +#define S526_TIMER_REG 0x00 +#define S526_TIMER_LOAD(x) (((x) & 0xff) << 8) +#define S526_TIMER_MODE ((x) << 1) +#define S526_TIMER_MANUAL S526_TIMER_MODE(0) +#define S526_TIMER_AUTO S526_TIMER_MODE(1) +#define S526_TIMER_RESTART BIT(0) +#define S526_WDOG_REG 0x02 +#define S526_WDOG_INVERTED BIT(4) +#define S526_WDOG_ENA BIT(3) +#define S526_WDOG_INTERVAL(x) (((x) & 0x7) << 0) +#define S526_AO_CTRL_REG 0x04 +#define S526_AO_CTRL_RESET BIT(3) +#define S526_AO_CTRL_CHAN(x) (((x) & 0x3) << 1) +#define S526_AO_CTRL_START BIT(0) +#define S526_AI_CTRL_REG 0x06 +#define S526_AI_CTRL_DELAY BIT(15) +#define S526_AI_CTRL_CONV(x) (1 << (5 + ((x) & 0x9))) +#define S526_AI_CTRL_READ(x) (((x) & 0xf) << 1) +#define S526_AI_CTRL_START BIT(0) +#define S526_AO_REG 0x08 +#define S526_AI_REG 0x08 +#define S526_DIO_CTRL_REG 0x0a +#define S526_DIO_CTRL_DIO3_NEG BIT(15) /* irq on DIO3 neg/pos edge */ +#define S526_DIO_CTRL_DIO2_NEG BIT(14) /* irq on DIO2 neg/pos edge */ +#define S526_DIO_CTRL_DIO1_NEG BIT(13) /* irq on DIO1 neg/pos edge */ +#define S526_DIO_CTRL_DIO0_NEG BIT(12) /* irq on DIO0 neg/pos edge */ +#define S526_DIO_CTRL_GRP2_OUT BIT(11) +#define S526_DIO_CTRL_GRP1_OUT BIT(10) +#define S526_DIO_CTRL_GRP2_NEG BIT(8) /* irq on DIO[4-7] neg/pos edge */ +#define S526_INT_ENA_REG 0x0c +#define S526_INT_STATUS_REG 0x0e +#define S526_INT_DIO(x) BIT(8 + ((x) & 0x7)) +#define S526_INT_EEPROM BIT(7) /* status only */ +#define S526_INT_CNTR(x) BIT(3 + (3 - ((x) & 0x3))) +#define S526_INT_AI BIT(2) +#define S526_INT_AO BIT(1) +#define S526_INT_TIMER BIT(0) +#define S526_MISC_REG 0x10 +#define S526_MISC_LED_OFF BIT(0) +#define S526_GPCT_LSB_REG(x) (0x12 + ((x) * 8)) +#define S526_GPCT_MSB_REG(x) (0x14 + ((x) * 8)) +#define S526_GPCT_MODE_REG(x) (0x16 + ((x) * 8)) +#define S526_GPCT_CTRL_REG(x) (0x18 + ((x) * 8)) +#define S526_EEPROM_DATA_REG 0x32 +#define S526_EEPROM_CTRL_REG 0x34 +#define S526_EEPROM_CTRL_ADDR(x) (((x) & 0x3f) << 3) +#define S526_EEPROM_CTRL(x) (((x) & 0x3) << 1) +#define S526_EEPROM_CTRL_READ S526_EEPROM_CTRL(2) +#define S526_EEPROM_CTRL_START BIT(0) struct counter_mode_register_t { #if defined(__LITTLE_ENDIAN_BITFIELD) @@ -112,27 +129,39 @@ union cmReg { struct s526_private { unsigned int gpct_config[4]; - unsigned short ai_config; + unsigned short ai_ctrl; }; +static void s526_gpct_write(struct comedi_device *dev, + unsigned int chan, unsigned int val) +{ + /* write high word then low word */ + outw((val >> 16) & 0xffff, dev->iobase + S526_GPCT_MSB_REG(chan)); + outw(val & 0xffff, dev->iobase + S526_GPCT_LSB_REG(chan)); +} + +static unsigned int s526_gpct_read(struct comedi_device *dev, + unsigned int chan) +{ + unsigned int val; + + /* read the low word then high word */ + val = inw(dev->iobase + S526_GPCT_LSB_REG(chan)) & 0xffff; + val |= (inw(dev->iobase + S526_GPCT_MSB_REG(chan)) & 0xff) << 16; + + return val; +} + static int s526_gpct_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { unsigned int chan = CR_CHAN(insn->chanspec); - unsigned long chan_iobase = dev->iobase + chan * 8; - unsigned int lo; - unsigned int hi; int i; - for (i = 0; i < insn->n; i++) { - /* Read the low word first */ - lo = inw(chan_iobase + REG_C0L) & 0xffff; - hi = inw(chan_iobase + REG_C0H) & 0xff; - - data[i] = (hi << 16) | lo; - } + for (i = 0; i < insn->n; i++) + data[i] = s526_gpct_read(dev, chan); return insn->n; } @@ -144,63 +173,34 @@ static int s526_gpct_insn_config(struct comedi_device *dev, { struct s526_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); - unsigned long chan_iobase = dev->iobase + chan * 8; unsigned int val; union cmReg cmReg; - /* Check what type of Counter the user requested, data[0] contains */ - /* the Application type */ + /* + * Check what type of Counter the user requested + * data[0] contains the Application type + */ switch (data[0]) { case INSN_CONFIG_GPCT_QUADRATURE_ENCODER: /* - data[0]: Application Type - data[1]: Counter Mode Register Value - data[2]: Pre-load Register Value - data[3]: Conter Control Register + * data[0]: Application Type + * data[1]: Counter Mode Register Value + * data[2]: Pre-load Register Value + * data[3]: Conter Control Register */ devpriv->gpct_config[chan] = data[0]; -#if 0 - /* Example of Counter Application */ - /* One-shot (software trigger) */ - cmReg.reg.coutSource = 0; /* out RCAP */ - cmReg.reg.coutPolarity = 1; /* Polarity inverted */ - cmReg.reg.autoLoadResetRcap = 0;/* Auto load disabled */ - cmReg.reg.hwCtEnableSource = 3; /* NOT RCAP */ - cmReg.reg.ctEnableCtrl = 2; /* Hardware */ - cmReg.reg.clockSource = 2; /* Internal */ - cmReg.reg.countDir = 1; /* Down */ - cmReg.reg.countDirCtrl = 1; /* Software */ - cmReg.reg.outputRegLatchCtrl = 0; /* latch on read */ - cmReg.reg.preloadRegSel = 0; /* PR0 */ - cmReg.reg.reserved = 0; - - outw(cmReg.value, chan_iobase + REG_C0M); - - outw(0x0001, chan_iobase + REG_C0H); - outw(0x3C68, chan_iobase + REG_C0L); - - /* Reset the counter */ - outw(0x8000, chan_iobase + REG_C0C); - /* Load the counter from PR0 */ - outw(0x4000, chan_iobase + REG_C0C); - - /* Reset RCAP (fires one-shot) */ - outw(0x0008, chan_iobase + REG_C0C); - -#endif - #if 1 /* Set Counter Mode Register */ cmReg.value = data[1] & 0xffff; - outw(cmReg.value, chan_iobase + REG_C0M); + outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); /* Reset the counter if it is software preload */ if (cmReg.reg.autoLoadResetRcap == 0) { /* Reset the counter */ - outw(0x8000, chan_iobase + REG_C0C); + outw(0x8000, dev->iobase + S526_GPCT_CTRL_REG(chan)); /* Load the counter from PR0 - * outw(0x4000, chan_iobase + REG_C0C); + * outw(0x4000, dev->iobase + S526_GPCT_CTRL_REG(chan)); */ } #else @@ -216,11 +216,13 @@ static int s526_gpct_insn_config(struct comedi_device *dev, cmReg.reg.clockSource = 0; /* When to take into account the indexpulse: */ - /*if (data[2] == GPCT_IndexPhaseLowLow) { - } else if (data[2] == GPCT_IndexPhaseLowHigh) { - } else if (data[2] == GPCT_IndexPhaseHighLow) { - } else if (data[2] == GPCT_IndexPhaseHighHigh) { - }*/ + /* + * if (data[2] == GPCT_IndexPhaseLowLow) { + * } else if (data[2] == GPCT_IndexPhaseLowHigh) { + * } else if (data[2] == GPCT_IndexPhaseHighLow) { + * } else if (data[2] == GPCT_IndexPhaseHighHigh) { + * } + */ /* Take into account the index pulse? */ if (data[3] == GPCT_RESET_COUNTER_ON_INDEX) /* Auto load with INDEX^ */ @@ -228,114 +230,89 @@ static int s526_gpct_insn_config(struct comedi_device *dev, /* Set Counter Mode Register */ cmReg.value = data[1] & 0xffff; - outw(cmReg.value, chan_iobase + REG_C0M); - - /* Load the pre-load register high word */ - val = (data[2] >> 16) & 0xffff; - outw(val, chan_iobase + REG_C0H); + outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); - /* Load the pre-load register low word */ - val = data[2] & 0xffff; - outw(val, chan_iobase + REG_C0L); + /* Load the pre-load register */ + s526_gpct_write(dev, chan, data[2]); /* Write the Counter Control Register */ - if (data[3]) { - val = data[3] & 0xffff; - outw(val, chan_iobase + REG_C0C); - } + if (data[3]) + outw(data[3] & 0xffff, + dev->iobase + S526_GPCT_CTRL_REG(chan)); + /* Reset the counter if it is software preload */ if (cmReg.reg.autoLoadResetRcap == 0) { /* Reset the counter */ - outw(0x8000, chan_iobase + REG_C0C); + outw(0x8000, dev->iobase + S526_GPCT_CTRL_REG(chan)); /* Load the counter from PR0 */ - outw(0x4000, chan_iobase + REG_C0C); + outw(0x4000, dev->iobase + S526_GPCT_CTRL_REG(chan)); } #endif break; case INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR: /* - data[0]: Application Type - data[1]: Counter Mode Register Value - data[2]: Pre-load Register 0 Value - data[3]: Pre-load Register 1 Value - data[4]: Conter Control Register + * data[0]: Application Type + * data[1]: Counter Mode Register Value + * data[2]: Pre-load Register 0 Value + * data[3]: Pre-load Register 1 Value + * data[4]: Conter Control Register */ devpriv->gpct_config[chan] = data[0]; /* Set Counter Mode Register */ cmReg.value = data[1] & 0xffff; cmReg.reg.preloadRegSel = 0; /* PR0 */ - outw(cmReg.value, chan_iobase + REG_C0M); + outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); - /* Load the pre-load register 0 high word */ - val = (data[2] >> 16) & 0xffff; - outw(val, chan_iobase + REG_C0H); - - /* Load the pre-load register 0 low word */ - val = data[2] & 0xffff; - outw(val, chan_iobase + REG_C0L); + /* Load the pre-load register 0 */ + s526_gpct_write(dev, chan, data[2]); /* Set Counter Mode Register */ cmReg.value = data[1] & 0xffff; cmReg.reg.preloadRegSel = 1; /* PR1 */ - outw(cmReg.value, chan_iobase + REG_C0M); - - /* Load the pre-load register 1 high word */ - val = (data[3] >> 16) & 0xffff; - outw(val, chan_iobase + REG_C0H); + outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); - /* Load the pre-load register 1 low word */ - val = data[3] & 0xffff; - outw(val, chan_iobase + REG_C0L); + /* Load the pre-load register 1 */ + s526_gpct_write(dev, chan, data[3]); /* Write the Counter Control Register */ if (data[4]) { val = data[4] & 0xffff; - outw(val, chan_iobase + REG_C0C); + outw(val, dev->iobase + S526_GPCT_CTRL_REG(chan)); } break; case INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR: /* - data[0]: Application Type - data[1]: Counter Mode Register Value - data[2]: Pre-load Register 0 Value - data[3]: Pre-load Register 1 Value - data[4]: Conter Control Register + * data[0]: Application Type + * data[1]: Counter Mode Register Value + * data[2]: Pre-load Register 0 Value + * data[3]: Pre-load Register 1 Value + * data[4]: Conter Control Register */ devpriv->gpct_config[chan] = data[0]; /* Set Counter Mode Register */ cmReg.value = data[1] & 0xffff; cmReg.reg.preloadRegSel = 0; /* PR0 */ - outw(cmReg.value, chan_iobase + REG_C0M); + outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); - /* Load the pre-load register 0 high word */ - val = (data[2] >> 16) & 0xffff; - outw(val, chan_iobase + REG_C0H); - - /* Load the pre-load register 0 low word */ - val = data[2] & 0xffff; - outw(val, chan_iobase + REG_C0L); + /* Load the pre-load register 0 */ + s526_gpct_write(dev, chan, data[2]); /* Set Counter Mode Register */ cmReg.value = data[1] & 0xffff; cmReg.reg.preloadRegSel = 1; /* PR1 */ - outw(cmReg.value, chan_iobase + REG_C0M); - - /* Load the pre-load register 1 high word */ - val = (data[3] >> 16) & 0xffff; - outw(val, chan_iobase + REG_C0H); + outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); - /* Load the pre-load register 1 low word */ - val = data[3] & 0xffff; - outw(val, chan_iobase + REG_C0L); + /* Load the pre-load register 1 */ + s526_gpct_write(dev, chan, data[3]); /* Write the Counter Control Register */ if (data[4]) { val = data[4] & 0xffff; - outw(val, chan_iobase + REG_C0C); + outw(val, dev->iobase + S526_GPCT_CTRL_REG(chan)); } break; @@ -353,18 +330,18 @@ static int s526_gpct_winsn(struct comedi_device *dev, { struct s526_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); - unsigned long chan_iobase = dev->iobase + chan * 8; - inw(chan_iobase + REG_C0M); /* Is this read required? */ + inw(dev->iobase + S526_GPCT_MODE_REG(chan)); /* Is this required? */ /* Check what Application of Counter this channel is configured for */ switch (devpriv->gpct_config[chan]) { case INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR: - /* data[0] contains the PULSE_WIDTH - data[1] contains the PULSE_PERIOD - @pre PULSE_PERIOD > PULSE_WIDTH > 0 - The above periods must be expressed as a multiple of the - pulse frequency on the selected source + /* + * data[0] contains the PULSE_WIDTH + * data[1] contains the PULSE_PERIOD + * @pre PULSE_PERIOD > PULSE_WIDTH > 0 + * The above periods must be expressed as a multiple of the + * pulse frequency on the selected source */ if ((data[1] <= data[0]) || !data[0]) return -EINVAL; @@ -373,8 +350,7 @@ static int s526_gpct_winsn(struct comedi_device *dev, case INSN_CONFIG_GPCT_QUADRATURE_ENCODER: case INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR: - outw((data[0] >> 16) & 0xffff, chan_iobase + REG_C0H); - outw(data[0] & 0xffff, chan_iobase + REG_C0L); + s526_gpct_write(dev, chan, data[0]); break; default: @@ -384,86 +360,60 @@ static int s526_gpct_winsn(struct comedi_device *dev, return insn->n; } -#define ISR_ADC_DONE 0x4 -static int s526_ai_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct s526_private *devpriv = dev->private; - int result = -EINVAL; - - if (insn->n < 1) - return result; - - result = insn->n; - - /* data[0] : channels was set in relevant bits. - data[1] : delay - */ - /* COMMENT: abbotti 2008-07-24: I don't know why you'd want to - * enable channels here. The channel should be enabled in the - * INSN_READ handler. */ - - /* Enable ADC interrupt */ - outw(ISR_ADC_DONE, dev->iobase + REG_IER); - devpriv->ai_config = (data[0] & 0x3ff) << 5; - if (data[1] > 0) - devpriv->ai_config |= 0x8000; /* set the delay */ - - devpriv->ai_config |= 0x0001; /* ADC start bit */ - - return result; -} - -static int s526_ai_eoc(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned long context) +static int s526_eoc(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned long context) { unsigned int status; - status = inw(dev->iobase + REG_ISR); - if (status & ISR_ADC_DONE) + status = inw(dev->iobase + S526_INT_STATUS_REG); + if (status & context) { + /* we got our eoc event, clear it */ + outw(context, dev->iobase + S526_INT_STATUS_REG); return 0; + } return -EBUSY; } -static int s526_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int s526_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct s526_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); - int n; - unsigned short value; - unsigned int d; + unsigned int ctrl; + unsigned int val; int ret; + int i; - /* Set configured delay, enable channel for this channel only, - * select "ADC read" channel, set "ADC start" bit. */ - value = (devpriv->ai_config & 0x8000) | - ((1 << 5) << chan) | (chan << 1) | 0x0001; + ctrl = S526_AI_CTRL_CONV(chan) | S526_AI_CTRL_READ(chan) | + S526_AI_CTRL_START; + if (ctrl != devpriv->ai_ctrl) { + /* + * The multiplexor needs to change, enable the 15us + * delay for the first sample. + */ + devpriv->ai_ctrl = ctrl; + ctrl |= S526_AI_CTRL_DELAY; + } - /* convert n samples */ - for (n = 0; n < insn->n; n++) { + for (i = 0; i < insn->n; i++) { /* trigger conversion */ - outw(value, dev->iobase + REG_ADC); + outw(ctrl, dev->iobase + S526_AI_CTRL_REG); + ctrl &= ~S526_AI_CTRL_DELAY; /* wait for conversion to end */ - ret = comedi_timeout(dev, s, insn, s526_ai_eoc, 0); + ret = comedi_timeout(dev, s, insn, s526_eoc, S526_INT_AI); if (ret) return ret; - outw(ISR_ADC_DONE, dev->iobase + REG_ISR); - - /* read data */ - d = inw(dev->iobase + REG_ADD); - - /* munge data */ - data[n] = d ^ 0x8000; + val = inw(dev->iobase + S526_AI_REG); + data[i] = comedi_offset_munge(s, val); } - /* return the number of samples read/written */ - return n; + return insn->n; } static int s526_ao_insn_write(struct comedi_device *dev, @@ -472,16 +422,23 @@ static int s526_ao_insn_write(struct comedi_device *dev, unsigned int *data) { unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int ctrl = S526_AO_CTRL_CHAN(chan); unsigned int val = s->readback[chan]; + int ret; int i; - outw(chan << 1, dev->iobase + REG_DAC); + outw(ctrl, dev->iobase + S526_AO_CTRL_REG); + ctrl |= S526_AO_CTRL_START; for (i = 0; i < insn->n; i++) { val = data[i]; - outw(val, dev->iobase + REG_ADD); - /* starts the D/A conversion */ - outw((chan << 1) | 1, dev->iobase + REG_DAC); + outw(val, dev->iobase + S526_AO_REG); + outw(ctrl, dev->iobase + S526_AO_CTRL_REG); + + /* wait for conversion to end */ + ret = comedi_timeout(dev, s, insn, s526_eoc, S526_INT_AO); + if (ret) + return ret; } s->readback[chan] = val; @@ -494,9 +451,9 @@ static int s526_dio_insn_bits(struct comedi_device *dev, unsigned int *data) { if (comedi_dio_update_state(s, data)) - outw(s->state, dev->iobase + REG_DIO); + outw(s->state, dev->iobase + S526_DIO_CTRL_REG); - data[1] = inw(dev->iobase + REG_DIO) & 0xff; + data[1] = inw(dev->iobase + S526_DIO_CTRL_REG) & 0xff; return insn->n; } @@ -510,6 +467,10 @@ static int s526_dio_insn_config(struct comedi_device *dev, unsigned int mask; int ret; + /* + * Digital I/O can be configured as inputs or outputs in + * groups of 4; DIO group 1 (DIO0-3) and DIO group 2 (DIO4-7). + */ if (chan < 4) mask = 0x0f; else @@ -519,17 +480,16 @@ static int s526_dio_insn_config(struct comedi_device *dev, if (ret) return ret; - /* bit 10/11 set the group 1/2's mode */ if (s->io_bits & 0x0f) - s->state |= (1 << 10); + s->state |= S526_DIO_CTRL_GRP1_OUT; else - s->state &= ~(1 << 10); + s->state &= ~S526_DIO_CTRL_GRP1_OUT; if (s->io_bits & 0xf0) - s->state |= (1 << 11); + s->state |= S526_DIO_CTRL_GRP2_OUT; else - s->state &= ~(1 << 11); + s->state &= ~S526_DIO_CTRL_GRP2_OUT; - outw(s->state, dev->iobase + REG_DIO); + outw(s->state, dev->iobase + S526_DIO_CTRL_REG); return insn->n; } @@ -552,51 +512,53 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; + /* General-Purpose Counter/Timer (GPCT) */ s = &dev->subdevices[0]; - /* GENERAL-PURPOSE COUNTER/TIME (GPCT) */ - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL; - s->n_chan = 4; - s->maxdata = 0x00ffffff; /* 24 bit counter */ - s->insn_read = s526_gpct_rinsn; - s->insn_config = s526_gpct_insn_config; - s->insn_write = s526_gpct_winsn; - + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL; + s->n_chan = 4; + s->maxdata = 0x00ffffff; + s->insn_read = s526_gpct_rinsn; + s->insn_config = s526_gpct_insn_config; + s->insn_write = s526_gpct_winsn; + + /* + * Analog Input subdevice + * channels 0 to 7 are the regular differential inputs + * channel 8 is "reference 0" (+10V) + * channel 9 is "reference 1" (0V) + */ s = &dev->subdevices[1]; - /* analog input subdevice */ - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_DIFF; - /* channels 0 to 7 are the regular differential inputs */ - /* channel 8 is "reference 0" (+10V), channel 9 is "reference 1" (0V) */ - s->n_chan = 10; - s->maxdata = 0xffff; - s->range_table = &range_bipolar10; - s->len_chanlist = 16; - s->insn_read = s526_ai_rinsn; - s->insn_config = s526_ai_insn_config; - + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_DIFF; + s->n_chan = 10; + s->maxdata = 0xffff; + s->range_table = &range_bipolar10; + s->len_chanlist = 16; + s->insn_read = s526_ai_insn_read; + + /* Analog Output subdevice */ s = &dev->subdevices[2]; - /* analog output subdevice */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 4; - s->maxdata = 0xffff; - s->range_table = &range_bipolar10; - s->insn_write = s526_ao_insn_write; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 4; + s->maxdata = 0xffff; + s->range_table = &range_bipolar10; + s->insn_write = s526_ao_insn_write; ret = comedi_alloc_subdev_readback(s); if (ret) return ret; + /* Digital I/O subdevice */ s = &dev->subdevices[3]; - /* digital i/o subdevice */ - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 8; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = s526_dio_insn_bits; - s->insn_config = s526_dio_insn_config; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = s526_dio_insn_bits; + s->insn_config = s526_dio_insn_config; return 0; } diff --git a/kernel/drivers/staging/comedi/drivers/s626.c b/kernel/drivers/staging/comedi/drivers/s626.c index 781918d8d..35f0f676e 100644 --- a/kernel/drivers/staging/comedi/drivers/s626.c +++ b/kernel/drivers/staging/comedi/drivers/s626.c @@ -2852,11 +2852,7 @@ static int s626_auto_attach(struct comedi_device *dev, s->insn_read = s626_enc_insn_read; s->insn_write = s626_enc_insn_write; - ret = s626_initialize(dev); - if (ret) - return ret; - - return 0; + return s626_initialize(dev); } static void s626_detach(struct comedi_device *dev) diff --git a/kernel/drivers/staging/comedi/drivers/serial2002.c b/kernel/drivers/staging/comedi/drivers/serial2002.c index 304ebff11..7a1defcf2 100644 --- a/kernel/drivers/staging/comedi/drivers/serial2002.c +++ b/kernel/drivers/staging/comedi/drivers/serial2002.c @@ -1,30 +1,29 @@ /* - comedi/drivers/serial2002.c - Skeleton code for a Comedi driver - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2002 Anders Blomdell <anders.blomdell@control.lth.se> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * serial2002.c + * Comedi driver for serial connected hardware + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2002 Anders Blomdell <anders.blomdell@control.lth.se> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ /* -Driver: serial2002 -Description: Driver for serial connected hardware -Devices: -Author: Anders Blomdell -Updated: Fri, 7 Jun 2002 12:56:45 -0700 -Status: in development - -*/ + * Driver: serial2002 + * Description: Driver for serial connected hardware + * Devices: + * Author: Anders Blomdell + * Updated: Fri, 7 Jun 2002 12:56:45 -0700 + * Status: in development + */ #include <linux/module.h> #include "../comedidev.h" @@ -32,6 +31,7 @@ Status: in development #include <linux/delay.h> #include <linux/sched.h> #include <linux/slab.h> +#include <linux/ktime.h> #include <linux/termios.h> #include <asm/ioctls.h> @@ -101,7 +101,7 @@ static long serial2002_tty_ioctl(struct file *f, unsigned op, if (f->f_op->unlocked_ioctl) return f->f_op->unlocked_ioctl(f, op, param); - return -ENOSYS; + return -ENOTTY; } static int serial2002_tty_write(struct file *f, unsigned char *buf, int count) @@ -121,9 +121,9 @@ static int serial2002_tty_write(struct file *f, unsigned char *buf, int count) static void serial2002_tty_read_poll_wait(struct file *f, int timeout) { struct poll_wqueues table; - struct timeval start, now; + ktime_t start, now; - do_gettimeofday(&start); + start = ktime_get(); poll_initwait(&table); while (1) { long elapsed; @@ -134,9 +134,8 @@ static void serial2002_tty_read_poll_wait(struct file *f, int timeout) POLLHUP | POLLERR)) { break; } - do_gettimeofday(&now); - elapsed = 1000000 * (now.tv_sec - start.tv_sec) + - now.tv_usec - start.tv_usec; + now = ktime_get(); + elapsed = ktime_us_delta(now, start); if (elapsed > timeout) break; set_current_state(TASK_INTERRUPTIBLE); @@ -176,7 +175,7 @@ static int serial2002_tty_read(struct file *f, int timeout) result = ch; break; } - udelay(100); + usleep_range(100, 1000); } } set_fs(oldfs); @@ -373,7 +372,7 @@ static int serial2002_setup_subdevice(struct comedi_subdevice *s, if (cfg[j].kind == kind) { if (mapping) mapping[chan] = j; - if (range) { + if (range && range_table_list) { range[j].length = 1; range[j].range.min = cfg[j].min; range[j].range.max = cfg[j].max; diff --git a/kernel/drivers/staging/comedi/drivers/ssv_dnp.c b/kernel/drivers/staging/comedi/drivers/ssv_dnp.c index acc7f3445..f9f634fd5 100644 --- a/kernel/drivers/staging/comedi/drivers/ssv_dnp.c +++ b/kernel/drivers/staging/comedi/drivers/ssv_dnp.c @@ -1,28 +1,29 @@ /* - comedi/drivers/ssv_dnp.c - generic comedi driver for SSV Embedded Systems' DIL/Net-PCs - Copyright (C) 2001 Robert Schwebel <robert@schwebel.de> - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * ssv_dnp.c + * generic comedi driver for SSV Embedded Systems' DIL/Net-PCs + * Copyright (C) 2001 Robert Schwebel <robert@schwebel.de> + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + /* -Driver: ssv_dnp -Description: SSV Embedded Systems DIL/Net-PC -Author: Robert Schwebel <robert@schwebel.de> -Devices: [SSV Embedded Systems] DIL/Net-PC 1486 (dnp-1486) -Status: unknown -*/ + * Driver: ssv_dnp + * Description: SSV Embedded Systems DIL/Net-PC + * Author: Robert Schwebel <robert@schwebel.de> + * Devices: [SSV Embedded Systems] DIL/Net-PC 1486 (dnp-1486) + * Status: unknown + */ /* include files ----------------------------------------------------------- */ @@ -134,6 +135,12 @@ static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; int ret; + /* + * We use I/O ports 0x22, 0x23 and 0xa3-0xa9, which are always + * allocated for the primary 8259, so we don't need to allocate + * them ourselves. + */ + ret = comedi_alloc_subdevices(dev, 1); if (ret) return ret; @@ -148,10 +155,6 @@ static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_bits = dnp_dio_insn_bits; s->insn_config = dnp_dio_insn_config; - /* We use the I/O ports 0x22,0x23 and 0xa3-0xa9, which are always - * allocated for the primary 8259, so we don't need to allocate them - * ourselves. */ - /* configure all ports as input (default) */ outb(PAMR, CSCIR); outb(0x00, CSCDR); diff --git a/kernel/drivers/staging/comedi/drivers/unioxx5.c b/kernel/drivers/staging/comedi/drivers/unioxx5.c deleted file mode 100644 index 51498b889..000000000 --- a/kernel/drivers/staging/comedi/drivers/unioxx5.c +++ /dev/null @@ -1,506 +0,0 @@ -/*************************************************************************** - * * - * comedi/drivers/unioxx5.c * - * Driver for Fastwel UNIOxx-5 (analog and digital i/o) boards. * - * * - * Copyright (C) 2006 Kruchinin Daniil (asgard) [asgard@etersoft.ru] * - * * - * COMEDI - Linux Control and Measurement Device Interface * - * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - ***************************************************************************/ -/* - -Driver: unioxx5 -Description: Driver for Fastwel UNIOxx-5 (analog and digital i/o) boards. -Author: Kruchinin Daniil (asgard) <asgard@etersoft.ru> -Status: unknown -Updated: 2006-10-09 -Devices: [Fastwel] UNIOxx-5 (unioxx5), - - This card supports digital and analog I/O. It written for g01 - subdevices only. - channels range: 0 .. 23 dio channels - and 0 .. 11 analog modules range - During attaching unioxx5 module displays modules identifiers - (see dmesg after comedi_config) in format: - | [module_number] module_id | - -*/ - -#include <linux/module.h> -#include <linux/delay.h> -#include "../comedidev.h" - -#define UNIOXX5_SIZE 0x10 -#define UNIOXX5_SUBDEV_BASE 0xA000 /* base addr of first subdev */ -#define UNIOXX5_SUBDEV_ODDS 0x400 - -/* modules types */ -#define MODULE_DIGITAL 0 -#define MODULE_OUTPUT_MASK 0x80 /* analog input/output */ - -/* constants for digital i/o */ -#define UNIOXX5_NUM_OF_CHANS 24 - -/* constants for analog i/o */ -#define TxBE 0x10 /* transmit buffer enable */ -#define RxCA 0x20 /* 1 receive character available */ -#define Rx2CA 0x40 /* 2 receive character available */ -#define Rx4CA 0x80 /* 4 receive character available */ - -/* bytes mask errors */ -#define Rx2CA_ERR_MASK 0x04 /* 2 bytes receiving error */ -#define Rx4CA_ERR_MASK 0x08 /* 4 bytes receiving error */ - -/* channel modes */ -#define ALL_2_INPUT 0 /* config all digital channels to input */ -#define ALL_2_OUTPUT 1 /* config all digital channels to output */ - -/* 'private' structure for each subdevice */ -struct unioxx5_subd_priv { - int usp_iobase; - /* 12 modules. each can be 70L or 73L */ - unsigned char usp_module_type[12]; - /* for saving previous written value for analog modules */ - unsigned char usp_extra_data[12][4]; - unsigned char usp_prev_wr_val[3]; /* previous written value */ - unsigned char usp_prev_cn_val[3]; /* previous channel value */ -}; - -static int __unioxx5_define_chan_offset(int chan_num) -{ - if (chan_num < 0 || chan_num > 23) - return -1; - - return (chan_num >> 3) + 1; -} - -#if 0 /* not used? */ -static void __unioxx5_digital_config(struct comedi_subdevice *s, int mode) -{ - struct unioxx5_subd_priv *usp = s->private; - struct device *csdev = s->device->class_dev; - int i, mask; - - mask = (mode == ALL_2_OUTPUT) ? 0xFF : 0x00; - dev_dbg(csdev, "mode = %d\n", mask); - - outb(1, usp->usp_iobase + 0); - - for (i = 0; i < 3; i++) - outb(mask, usp->usp_iobase + i); - - outb(0, usp->usp_iobase + 0); -} -#endif - -/* configure channels for analog i/o (even to output, odd to input) */ -static void __unioxx5_analog_config(struct unioxx5_subd_priv *usp, int channel) -{ - int chan_a, chan_b, conf, channel_offset; - - channel_offset = __unioxx5_define_chan_offset(channel); - conf = usp->usp_prev_cn_val[channel_offset - 1]; - chan_a = chan_b = 1; - - /* setting channel A and channel B mask */ - if (channel % 2 == 0) { - chan_a <<= channel & 0x07; - chan_b <<= (channel + 1) & 0x07; - } else { - chan_a <<= (channel - 1) & 0x07; - chan_b <<= channel & 0x07; - } - - conf |= chan_a; /* even channel ot output */ - conf &= ~chan_b; /* odd channel to input */ - - outb(1, usp->usp_iobase + 0); - outb(conf, usp->usp_iobase + channel_offset); - outb(0, usp->usp_iobase + 0); - - usp->usp_prev_cn_val[channel_offset - 1] = conf; -} - -static int __unioxx5_digital_read(struct comedi_subdevice *s, - unsigned int *data, int channel, int minor) -{ - struct unioxx5_subd_priv *usp = s->private; - struct device *csdev = s->device->class_dev; - int channel_offset, mask = 1 << (channel & 0x07); - - channel_offset = __unioxx5_define_chan_offset(channel); - if (channel_offset < 0) { - dev_err(csdev, - "undefined channel %d. channel range is 0 .. 23\n", - channel); - return 0; - } - - *data = inb(usp->usp_iobase + channel_offset); - *data &= mask; - - /* correct the read value to 0 or 1 */ - if (channel_offset > 1) - channel -= 2 << channel_offset; - *data >>= channel; - return 1; -} - -static int __unioxx5_analog_read(struct comedi_subdevice *s, - unsigned int *data, int channel, int minor) -{ - struct unioxx5_subd_priv *usp = s->private; - struct device *csdev = s->device->class_dev; - int module_no, read_ch; - char control; - - module_no = channel / 2; - read_ch = channel % 2; /* depend on type of channel (A or B) */ - - /* defining if given module can work on input */ - if (usp->usp_module_type[module_no] & MODULE_OUTPUT_MASK) { - dev_err(csdev, - "module in position %d with id 0x%02x is for output only", - module_no, usp->usp_module_type[module_no]); - return 0; - } - - __unioxx5_analog_config(usp, channel); - /* sends module number to card(1 .. 12) */ - outb(module_no + 1, usp->usp_iobase + 5); - outb('V', usp->usp_iobase + 6); /* sends to module (V)erify command */ - control = inb(usp->usp_iobase); /* get control register byte */ - - /* waits while reading four bytes will be allowed */ - while (!((control = inb(usp->usp_iobase + 0)) & Rx4CA)) - ; - - /* if four bytes readding error occurs - return 0(false) */ - if ((control & Rx4CA_ERR_MASK)) { - dev_err(csdev, "4 bytes error\n"); - return 0; - } - - if (read_ch) - *data = inw(usp->usp_iobase + 6); /* channel B */ - else - *data = inw(usp->usp_iobase + 4); /* channel A */ - - return 1; -} - -static int __unioxx5_digital_write(struct comedi_subdevice *s, - unsigned int *data, int channel, int minor) -{ - struct unioxx5_subd_priv *usp = s->private; - struct device *csdev = s->device->class_dev; - int channel_offset, val; - int mask = 1 << (channel & 0x07); - - channel_offset = __unioxx5_define_chan_offset(channel); - if (channel_offset < 0) { - dev_err(csdev, - "undefined channel %d. channel range is 0 .. 23\n", - channel); - return 0; - } - - /* getting previous written value */ - val = usp->usp_prev_wr_val[channel_offset - 1]; - - if (*data) - val |= mask; - else - val &= ~mask; - - outb(val, usp->usp_iobase + channel_offset); - /* saving new written value */ - usp->usp_prev_wr_val[channel_offset - 1] = val; - - return 1; -} - -static int __unioxx5_analog_write(struct comedi_subdevice *s, - unsigned int *data, int channel, int minor) -{ - struct unioxx5_subd_priv *usp = s->private; - struct device *csdev = s->device->class_dev; - int module, i; - - module = channel / 2; /* definig module number(0 .. 11) */ - i = (channel % 2) << 1; /* depends on type of channel (A or B) */ - - /* defining if given module can work on output */ - if (!(usp->usp_module_type[module] & MODULE_OUTPUT_MASK)) { - dev_err(csdev, - "module in position %d with id 0x%0x is for input only!\n", - module, usp->usp_module_type[module]); - return 0; - } - - __unioxx5_analog_config(usp, channel); - /* saving minor byte */ - usp->usp_extra_data[module][i++] = (unsigned char)(*data & 0x00FF); - /* saving major byte */ - usp->usp_extra_data[module][i] = (unsigned char)((*data & 0xFF00) >> 8); - - /* while(!((inb(usp->usp_iobase + 0)) & TxBE)); */ - /* sending module number to card(1 .. 12) */ - outb(module + 1, usp->usp_iobase + 5); - outb('W', usp->usp_iobase + 6); /* sends (W)rite command to module */ - - /* sending for bytes to module(one byte per cycle iteration) */ - for (i = 0; i < 4; i++) { - while (!((inb(usp->usp_iobase + 0)) & TxBE)) - ; /* waits while writing will be allowed */ - outb(usp->usp_extra_data[module][i], usp->usp_iobase + 6); - } - - return 1; -} - -static int unioxx5_subdev_read(struct comedi_device *dev, - struct comedi_subdevice *subdev, - struct comedi_insn *insn, unsigned int *data) -{ - struct unioxx5_subd_priv *usp = subdev->private; - int channel, type; - - channel = CR_CHAN(insn->chanspec); - /* defining module type(analog or digital) */ - type = usp->usp_module_type[channel / 2]; - - if (type == MODULE_DIGITAL) { - if (!__unioxx5_digital_read(subdev, data, channel, dev->minor)) - return -1; - } else { - if (!__unioxx5_analog_read(subdev, data, channel, dev->minor)) - return -1; - } - - return 1; -} - -static int unioxx5_subdev_write(struct comedi_device *dev, - struct comedi_subdevice *subdev, - struct comedi_insn *insn, unsigned int *data) -{ - struct unioxx5_subd_priv *usp = subdev->private; - int channel, type; - - channel = CR_CHAN(insn->chanspec); - /* defining module type(analog or digital) */ - type = usp->usp_module_type[channel / 2]; - - if (type == MODULE_DIGITAL) { - if (!__unioxx5_digital_write(subdev, data, channel, dev->minor)) - return -1; - } else { - if (!__unioxx5_analog_write(subdev, data, channel, dev->minor)) - return -1; - } - - return 1; -} - -/* for digital modules only */ -static int unioxx5_insn_config(struct comedi_device *dev, - struct comedi_subdevice *subdev, - struct comedi_insn *insn, unsigned int *data) -{ - int channel_offset, flags, channel = CR_CHAN(insn->chanspec), type; - struct unioxx5_subd_priv *usp = subdev->private; - int mask = 1 << (channel & 0x07); - - type = usp->usp_module_type[channel / 2]; - - if (type != MODULE_DIGITAL) { - dev_err(dev->class_dev, - "channel configuration accessible only for digital modules\n"); - return -1; - } - - channel_offset = __unioxx5_define_chan_offset(channel); - if (channel_offset < 0) { - dev_err(dev->class_dev, - "undefined channel %d. channel range is 0 .. 23\n", - channel); - return -1; - } - - /* gets previously written value */ - flags = usp->usp_prev_cn_val[channel_offset - 1]; - - switch (*data) { - case COMEDI_INPUT: - flags &= ~mask; - break; - case COMEDI_OUTPUT: - flags |= mask; - break; - default: - dev_err(dev->class_dev, "unknown flag\n"); - return -1; - } - - /* *\ - * sets channels buffer to 1(after this we are allowed to * - * change channel type on input or output) * - \* */ - outb(1, usp->usp_iobase + 0); - /* changes type of _one_ channel */ - outb(flags, usp->usp_iobase + channel_offset); - /* sets channels bank to 0(allows directly input/output) */ - outb(0, usp->usp_iobase + 0); - /* saves written value */ - usp->usp_prev_cn_val[channel_offset - 1] = flags; - - return 0; -} - -/* initializing subdevice with given address */ -static int __unioxx5_subdev_init(struct comedi_device *dev, - struct comedi_subdevice *s, - int iobase) -{ - struct unioxx5_subd_priv *usp; - int i, to, ndef_flag = 0; - int ret; - - usp = comedi_alloc_spriv(s, sizeof(*usp)); - if (!usp) - return -ENOMEM; - - ret = __comedi_request_region(dev, iobase, UNIOXX5_SIZE); - if (ret) - return ret; - usp->usp_iobase = iobase; - - /* defining modules types */ - for (i = 0; i < 12; i++) { - to = 10000; - - __unioxx5_analog_config(usp, i * 2); - /* sends channel number to card */ - outb(i + 1, iobase + 5); - outb('H', iobase + 6); /* requests EEPROM world */ - while (!(inb(iobase + 0) & TxBE)) - ; /* waits while writing will be allowed */ - outb(0, iobase + 6); - - /* waits while reading of two bytes will be allowed */ - while (!(inb(iobase + 0) & Rx2CA)) { - if (--to <= 0) { - ndef_flag = 1; - break; - } - } - - if (ndef_flag) { - usp->usp_module_type[i] = 0; - ndef_flag = 0; - } else { - usp->usp_module_type[i] = inb(iobase + 6); - } - - udelay(1); - } - - /* initial subdevice for digital or analog i/o */ - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = UNIOXX5_NUM_OF_CHANS; - s->maxdata = 0xFFF; - s->range_table = &range_digital; - s->insn_read = unioxx5_subdev_read; - s->insn_write = unioxx5_subdev_write; - /* for digital modules only!!! */ - s->insn_config = unioxx5_insn_config; - - return 0; -} - -static int unioxx5_attach(struct comedi_device *dev, - struct comedi_devconfig *it) -{ - struct comedi_subdevice *s; - int iobase, i, n_subd; - int id, num, ba; - int ret; - - iobase = it->options[0]; - - dev->iobase = iobase; - iobase += UNIOXX5_SUBDEV_BASE; - n_subd = 0; - - /* getting number of subdevices with types 'g01' */ - for (i = 0, ba = iobase; i < 4; i++, ba += UNIOXX5_SUBDEV_ODDS) { - id = inb(ba + 0xE); - num = inb(ba + 0xF); - - if (id != 'g' || num != 1) - continue; - - n_subd++; - } - - /* unioxx5 can has from two to four subdevices */ - if (n_subd < 2) { - dev_err(dev->class_dev, - "your card must has at least 2 'g01' subdevices\n"); - return -1; - } - - ret = comedi_alloc_subdevices(dev, n_subd); - if (ret) - return ret; - - /* initializing each of for same subdevices */ - for (i = 0; i < n_subd; i++, iobase += UNIOXX5_SUBDEV_ODDS) { - s = &dev->subdevices[i]; - ret = __unioxx5_subdev_init(dev, s, iobase); - if (ret) - return ret; - } - - return 0; -} - -static void unioxx5_detach(struct comedi_device *dev) -{ - struct comedi_subdevice *s; - struct unioxx5_subd_priv *spriv; - int i; - - for (i = 0; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; - spriv = s->private; - if (spriv && spriv->usp_iobase) - release_region(spriv->usp_iobase, UNIOXX5_SIZE); - } -} - -static struct comedi_driver unioxx5_driver = { - .driver_name = "unioxx5", - .module = THIS_MODULE, - .attach = unioxx5_attach, - .detach = unioxx5_detach, -}; -module_comedi_driver(unioxx5_driver); - -MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); -MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/staging/comedi/drivers/usbdux.c b/kernel/drivers/staging/comedi/drivers/usbdux.c index ced05e581..f4f05d29d 100644 --- a/kernel/drivers/staging/comedi/drivers/usbdux.c +++ b/kernel/drivers/staging/comedi/drivers/usbdux.c @@ -108,55 +108,55 @@ #define BULK_TIMEOUT 1000 /* 300Hz max frequ under PWM */ -#define MIN_PWM_PERIOD ((long)(1E9/300)) +#define MIN_PWM_PERIOD ((long)(1E9 / 300)) /* Default PWM frequency */ -#define PWM_DEFAULT_PERIOD ((long)(1E9/100)) +#define PWM_DEFAULT_PERIOD ((long)(1E9 / 100)) /* Size of one A/D value */ -#define SIZEADIN ((sizeof(uint16_t))) +#define SIZEADIN ((sizeof(u16))) /* * Size of the input-buffer IN BYTES * Always multiple of 8 for 8 microframes which is needed in the highspeed mode */ -#define SIZEINBUF ((8*SIZEADIN)) +#define SIZEINBUF (8 * SIZEADIN) /* 16 bytes. */ -#define SIZEINSNBUF 16 +#define SIZEINSNBUF 16 /* size of one value for the D/A converter: channel and value */ -#define SIZEDAOUT ((sizeof(uint8_t)+sizeof(uint16_t))) +#define SIZEDAOUT ((sizeof(u8) + sizeof(u16))) /* * Size of the output-buffer in bytes * Actually only the first 4 triplets are used but for the * high speed mode we need to pad it to 8 (microframes). */ -#define SIZEOUTBUF ((8*SIZEDAOUT)) +#define SIZEOUTBUF (8 * SIZEDAOUT) /* * Size of the buffer for the dux commands: just now max size is determined * by the analogue out + command byte + panic bytes... */ -#define SIZEOFDUXBUFFER ((8*SIZEDAOUT+2)) +#define SIZEOFDUXBUFFER (8 * SIZEDAOUT + 2) /* Number of in-URBs which receive the data: min=2 */ -#define NUMOFINBUFFERSFULL 5 +#define NUMOFINBUFFERSFULL 5 /* Number of out-URBs which send the data: min=2 */ -#define NUMOFOUTBUFFERSFULL 5 +#define NUMOFOUTBUFFERSFULL 5 /* Number of in-URBs which receive the data: min=5 */ /* must have more buffers due to buggy USB ctr */ -#define NUMOFINBUFFERSHIGH 10 +#define NUMOFINBUFFERSHIGH 10 /* Number of out-URBs which send the data: min=5 */ /* must have more buffers due to buggy USB ctr */ -#define NUMOFOUTBUFFERSHIGH 10 +#define NUMOFOUTBUFFERSHIGH 10 /* number of retries to get the right dux command */ -#define RETRIES 10 +#define RETRIES 10 static const struct comedi_lrange range_usbdux_ai_range = { 4, { @@ -187,7 +187,7 @@ struct usbdux_private { /* PWM period */ unsigned int pwm_period; /* PWM internal delay for the GPIF in the FX2 */ - uint8_t pwm_delay; + u8 pwm_delay; /* size of the PWM buffer which holds the bit pattern */ int pwm_buf_sz; /* input buffer for the ISO-transfer */ @@ -209,8 +209,8 @@ struct usbdux_private { /* interval in frames/uframes */ unsigned int ai_interval; /* commands */ - uint8_t *dux_commands; - struct semaphore sem; + u8 *dux_commands; + struct mutex mut; }; static void usbdux_unlink_urbs(struct urb **urbs, int num_urbs) @@ -237,10 +237,10 @@ static int usbdux_ai_cancel(struct comedi_device *dev, struct usbdux_private *devpriv = dev->private; /* prevent other CPUs from submitting new commands just now */ - down(&devpriv->sem); + mutex_lock(&devpriv->mut); /* unlink only if the urb really has been submitted */ usbdux_ai_stop(dev, devpriv->ai_cmd_running); - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return 0; } @@ -262,11 +262,11 @@ static void usbduxsub_ai_handle_urb(struct comedi_device *dev, /* get the data from the USB bus and hand it over to comedi */ for (i = 0; i < cmd->chanlist_len; i++) { unsigned int range = CR_RANGE(cmd->chanlist[i]); - uint16_t val = le16_to_cpu(devpriv->in_buf[i]); + u16 val = le16_to_cpu(devpriv->in_buf[i]); /* bipolar data is two's-complement */ if (comedi_range_is_bipolar(s, range)) - val ^= ((s->maxdata + 1) >> 1); + val = comedi_offset_munge(s, val); /* transfer data */ if (!comedi_buf_write_samples(s, &val, 1)) @@ -365,10 +365,10 @@ static int usbdux_ao_cancel(struct comedi_device *dev, struct usbdux_private *devpriv = dev->private; /* prevent other CPUs from submitting a command just now */ - down(&devpriv->sem); + mutex_lock(&devpriv->mut); /* unlink only if it is really running */ usbdux_ao_stop(dev, devpriv->ao_cmd_running); - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return 0; } @@ -380,7 +380,7 @@ static void usbduxsub_ao_handle_urb(struct comedi_device *dev, struct usbdux_private *devpriv = dev->private; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; - uint8_t *datap; + u8 *datap; int ret; int i; @@ -516,9 +516,8 @@ static int usbdux_submit_urbs(struct comedi_device *dev, static int usbdux_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - struct usbdux_private *this_usbduxsub = dev->private; - int err = 0, i; - unsigned int tmp_timer; + struct usbdux_private *devpriv = dev->private; + int err = 0; /* Step 1 : check if triggers are trivially valid */ @@ -549,40 +548,31 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev, err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0); if (cmd->scan_begin_src == TRIG_TIMER) { - if (this_usbduxsub->high_speed) { + /* full speed does 1kHz scans every USB frame */ + unsigned int arg = 1000000; + unsigned int min_arg = arg; + + if (devpriv->high_speed) { /* * In high speed mode microframes are possible. * However, during one microframe we can roughly * sample one channel. Thus, the more channels * are in the channel list the more time we need. */ - i = 1; + int i = 1; + /* find a power of 2 for the number of channels */ - while (i < (cmd->chanlist_len)) + while (i < cmd->chanlist_len) i = i * 2; - err |= comedi_check_trigger_arg_min(&cmd-> - scan_begin_arg, - 1000000 / 8 * i); - /* now calc the real sampling rate with all the - * rounding errors */ - tmp_timer = - ((unsigned int)(cmd->scan_begin_arg / 125000)) * - 125000; - } else { - /* full speed */ - /* 1kHz scans every USB frame */ - err |= comedi_check_trigger_arg_min(&cmd-> - scan_begin_arg, - 1000000); - /* - * calc the real sampling rate with the rounding errors - */ - tmp_timer = ((unsigned int)(cmd->scan_begin_arg / - 1000000)) * 1000000; + arg /= 8; + min_arg = arg * i; } - err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, - tmp_timer); + err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, + min_arg); + /* calc the real sampling rate with the rounding errors */ + arg = (cmd->scan_begin_arg / arg) * arg; + err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, @@ -603,10 +593,10 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev, * creates the ADC command for the MAX1271 * range is the range value from comedi */ -static uint8_t create_adc_command(unsigned int chan, unsigned int range) +static u8 create_adc_command(unsigned int chan, unsigned int range) { - uint8_t p = (range <= 1); - uint8_t r = ((range % 2) == 0); + u8 p = (range <= 1); + u8 r = ((range % 2) == 0); return (chan << 4) | ((p == 1) << 2) | ((r == 1) << 3); } @@ -656,7 +646,7 @@ static int usbdux_ai_inttrig(struct comedi_device *dev, if (trig_num != cmd->start_arg) return -EINVAL; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); if (!devpriv->ai_cmd_running) { devpriv->ai_cmd_running = 1; @@ -672,7 +662,7 @@ static int usbdux_ai_inttrig(struct comedi_device *dev, } ai_trig_exit: - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } @@ -685,7 +675,7 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) int i; /* block other CPUs from starting an ai_cmd */ - down(&devpriv->sem); + mutex_lock(&devpriv->mut); if (devpriv->ai_cmd_running) goto ai_cmd_exit; @@ -746,7 +736,7 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } ai_cmd_exit: - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } @@ -764,7 +754,7 @@ static int usbdux_ai_insn_read(struct comedi_device *dev, int ret = -EBUSY; int i; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); if (devpriv->ai_cmd_running) goto ai_read_exit; @@ -786,13 +776,13 @@ static int usbdux_ai_insn_read(struct comedi_device *dev, /* bipolar data is two's-complement */ if (comedi_range_is_bipolar(s, range)) - val ^= ((s->maxdata + 1) >> 1); + val = comedi_offset_munge(s, val); data[i] = val; } ai_read_exit: - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret ? ret : insn->n; } @@ -805,9 +795,9 @@ static int usbdux_ao_insn_read(struct comedi_device *dev, struct usbdux_private *devpriv = dev->private; int ret; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); ret = comedi_readback_insn_read(dev, s, insn, data); - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } @@ -824,7 +814,7 @@ static int usbdux_ao_insn_write(struct comedi_device *dev, int ret = -EBUSY; int i; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); if (devpriv->ao_cmd_running) goto ao_write_exit; @@ -848,7 +838,7 @@ static int usbdux_ao_insn_write(struct comedi_device *dev, } ao_write_exit: - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret ? ret : insn->n; } @@ -864,7 +854,7 @@ static int usbdux_ao_inttrig(struct comedi_device *dev, if (trig_num != cmd->start_arg) return -EINVAL; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); if (!devpriv->ao_cmd_running) { devpriv->ao_cmd_running = 1; @@ -880,25 +870,21 @@ static int usbdux_ao_inttrig(struct comedi_device *dev, } ao_trig_exit: - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } static int usbdux_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - struct usbdux_private *this_usbduxsub = dev->private; int err = 0; unsigned int flags; - if (!this_usbduxsub) - return -EFAULT; - /* Step 1 : check if triggers are trivially valid */ err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); - if (0) { /* (this_usbduxsub->high_speed) */ + if (0) { /* (devpriv->high_speed) */ /* the sampling rate is set by the coversion rate */ flags = TRIG_FOLLOW; } else { @@ -907,7 +893,7 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev, } err |= comedi_check_trigger_src(&cmd->scan_begin_src, flags); - if (0) { /* (this_usbduxsub->high_speed) */ + if (0) { /* (devpriv->high_speed) */ /* * in usb-2.0 only one conversion it transmitted * but with 8kHz/n @@ -974,7 +960,7 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) struct comedi_cmd *cmd = &s->async->cmd; int ret = -EBUSY; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); if (devpriv->ao_cmd_running) goto ao_cmd_exit; @@ -1016,7 +1002,7 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } ao_cmd_exit: - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } @@ -1047,7 +1033,7 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev, struct usbdux_private *devpriv = dev->private; int ret; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); comedi_dio_update_state(s, data); @@ -1069,7 +1055,7 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev, data[1] = le16_to_cpu(devpriv->insn_buf[1]); dio_exit: - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret ? ret : insn->n; } @@ -1084,7 +1070,7 @@ static int usbdux_counter_read(struct comedi_device *dev, int ret = 0; int i; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); for (i = 0; i < insn->n; i++) { ret = send_dux_commands(dev, USBDUX_CMD_TIMER_RD); @@ -1098,7 +1084,7 @@ static int usbdux_counter_read(struct comedi_device *dev, } counter_read_exit: - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret ? ret : insn->n; } @@ -1114,7 +1100,7 @@ static int usbdux_counter_write(struct comedi_device *dev, int ret = 0; int i; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); devpriv->dux_commands[1] = chan; @@ -1126,7 +1112,7 @@ static int usbdux_counter_write(struct comedi_device *dev, break; } - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret ? ret : insn->n; } @@ -1162,11 +1148,11 @@ static int usbdux_pwm_cancel(struct comedi_device *dev, struct usbdux_private *devpriv = dev->private; int ret; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); /* unlink only if it is really running */ usbdux_pwm_stop(dev, devpriv->pwm_cmd_running); ret = send_dux_commands(dev, USBDUX_CMD_PWM_OFF); - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } @@ -1271,7 +1257,7 @@ static int usbdux_pwm_start(struct comedi_device *dev, struct usbdux_private *devpriv = dev->private; int ret = 0; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); if (devpriv->pwm_cmd_running) goto pwm_start_exit; @@ -1290,7 +1276,7 @@ static int usbdux_pwm_start(struct comedi_device *dev, devpriv->pwm_cmd_running = 0; pwm_start_exit: - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } @@ -1391,8 +1377,8 @@ static int usbdux_firmware_upload(struct comedi_device *dev, unsigned long context) { struct usb_device *usb = comedi_to_usb_dev(dev); - uint8_t *buf; - uint8_t *tmp; + u8 *buf; + u8 *tmp; int ret; if (!data) @@ -1590,7 +1576,7 @@ static int usbdux_auto_attach(struct comedi_device *dev, if (!devpriv) return -ENOMEM; - sema_init(&devpriv->sem, 1); + mutex_init(&devpriv->mut); usb_set_intfdata(intf, devpriv); @@ -1705,7 +1691,7 @@ static void usbdux_detach(struct comedi_device *dev) if (!devpriv) return; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); /* force unlink all urbs */ usbdux_pwm_stop(dev, 1); @@ -1714,7 +1700,7 @@ static void usbdux_detach(struct comedi_device *dev) usbdux_free_usb_buffers(dev); - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); } static struct comedi_driver usbdux_driver = { diff --git a/kernel/drivers/staging/comedi/drivers/usbduxfast.c b/kernel/drivers/staging/comedi/drivers/usbduxfast.c index d90dc5998..10f94ec34 100644 --- a/kernel/drivers/staging/comedi/drivers/usbduxfast.c +++ b/kernel/drivers/staging/comedi/drivers/usbduxfast.c @@ -97,7 +97,7 @@ /* * size of one A/D value */ -#define SIZEADIN (sizeof(int16_t)) +#define SIZEADIN (sizeof(s16)) /* * size of the input-buffer IN BYTES @@ -156,12 +156,11 @@ static const struct comedi_lrange range_usbduxfast_ai_range = { */ struct usbduxfast_private { struct urb *urb; /* BULK-transfer handling: urb */ - uint8_t *duxbuf; - int8_t *inbuf; + u8 *duxbuf; + s8 *inbuf; short int ai_cmd_running; /* asynchronous command is running */ - int ignore; /* counter which ignores the first - buffers */ - struct semaphore sem; + int ignore; /* counter which ignores the first buffers */ + struct mutex mut; }; /* @@ -190,8 +189,7 @@ static int usbduxfast_send_cmd(struct comedi_device *dev, int cmd_type) } static void usbduxfast_cmd_data(struct comedi_device *dev, int index, - uint8_t len, uint8_t op, uint8_t out, - uint8_t log) + u8 len, u8 op, u8 out, u8 log) { struct usbduxfast_private *devpriv = dev->private; @@ -223,12 +221,9 @@ static int usbduxfast_ai_cancel(struct comedi_device *dev, struct usbduxfast_private *devpriv = dev->private; int ret; - if (!devpriv) - return -EFAULT; - - down(&devpriv->sem); + mutex_lock(&devpriv->mut); ret = usbduxfast_ai_stop(dev, 1); - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } @@ -317,9 +312,6 @@ static int usbduxfast_submit_urb(struct comedi_device *dev) struct usbduxfast_private *devpriv = dev->private; int ret; - if (!devpriv) - return -EFAULT; - usb_fill_bulk_urb(devpriv->urb, usb, usb_rcvbulkpipe(usb, BULKINEP), devpriv->inbuf, SIZEINBUF, usbduxfast_ai_interrupt, dev); @@ -332,22 +324,50 @@ static int usbduxfast_submit_urb(struct comedi_device *dev) return 0; } +static int usbduxfast_ai_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + unsigned int gain0 = CR_RANGE(cmd->chanlist[0]); + int i; + + if (cmd->chanlist_len > 3 && cmd->chanlist_len != 16) { + dev_err(dev->class_dev, "unsupported combination of channels\n"); + return -EINVAL; + } + + for (i = 0; i < cmd->chanlist_len; ++i) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); + unsigned int gain = CR_RANGE(cmd->chanlist[i]); + + if (chan != i) { + dev_err(dev->class_dev, + "channels are not consecutive\n"); + return -EINVAL; + } + if (gain != gain0 && cmd->chanlist_len > 3) { + dev_err(dev->class_dev, + "gain must be the same for all channels\n"); + return -EINVAL; + } + } + return 0; +} + static int usbduxfast_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0; - long int steps, tmp; - int min_sample_period; + unsigned int steps; + unsigned int arg; /* Step 1 : check if triggers are trivially valid */ err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT | TRIG_INT); - err |= comedi_check_trigger_src(&cmd->scan_begin_src, - TRIG_FOLLOW | TRIG_EXT); - err |= comedi_check_trigger_src(&cmd->convert_src, - TRIG_TIMER | TRIG_EXT); + err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW); + err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_TIMER); err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); @@ -357,16 +377,10 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev, /* Step 2a : make sure trigger sources are unique */ err |= comedi_check_trigger_is_unique(cmd->start_src); - err |= comedi_check_trigger_is_unique(cmd->scan_begin_src); - err |= comedi_check_trigger_is_unique(cmd->convert_src); err |= comedi_check_trigger_is_unique(cmd->stop_src); /* Step 2b : and mutually compatible */ - /* can't have external stop and start triggers at once */ - if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT) - err |= -EINVAL; - if (err) return 2; @@ -377,47 +391,44 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev, if (!cmd->chanlist_len) err |= -EINVAL; + /* external start trigger is only valid for 1 or 16 channels */ + if (cmd->start_src == TRIG_EXT && + cmd->chanlist_len != 1 && cmd->chanlist_len != 16) + err |= -EINVAL; + err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); - if (cmd->chanlist_len == 1) - min_sample_period = 1; - else - min_sample_period = MIN_SAMPLING_PERIOD; - - if (cmd->convert_src == TRIG_TIMER) { - steps = cmd->convert_arg * 30; - if (steps < (min_sample_period * 1000)) - steps = min_sample_period * 1000; - - if (steps > (MAX_SAMPLING_PERIOD * 1000)) - steps = MAX_SAMPLING_PERIOD * 1000; - - /* calc arg again */ - tmp = steps / 30; - err |= comedi_check_trigger_arg_is(&cmd->convert_arg, tmp); - } - - /* stop source */ - switch (cmd->stop_src) { - case TRIG_COUNT: + /* + * Validate the conversion timing: + * for 1 channel the timing in 30MHz "steps" is: + * steps <= MAX_SAMPLING_PERIOD + * for all other chanlist_len it is: + * MIN_SAMPLING_PERIOD <= steps <= MAX_SAMPLING_PERIOD + */ + steps = (cmd->convert_arg * 30) / 1000; + if (cmd->chanlist_len != 1) + err |= comedi_check_trigger_arg_min(&steps, + MIN_SAMPLING_PERIOD); + err |= comedi_check_trigger_arg_max(&steps, MAX_SAMPLING_PERIOD); + arg = (steps * 1000) / 30; + err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg); + + if (cmd->stop_src == TRIG_COUNT) err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1); - break; - case TRIG_NONE: + else /* TRIG_NONE */ err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); - break; - /* - * TRIG_EXT doesn't care since it doesn't trigger - * off a numbered channel - */ - default: - break; - } if (err) return 3; - /* step 4: fix up any arguments */ + /* Step 4: fix up any arguments */ + + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= usbduxfast_ai_check_chanlist(dev, s, cmd); + if (err) + return 5; return 0; } @@ -430,13 +441,10 @@ static int usbduxfast_ai_inttrig(struct comedi_device *dev, struct comedi_cmd *cmd = &s->async->cmd; int ret; - if (!devpriv) - return -EFAULT; - if (trig_num != cmd->start_arg) return -EINVAL; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); if (!devpriv->ai_cmd_running) { devpriv->ai_cmd_running = 1; @@ -444,14 +452,14 @@ static int usbduxfast_ai_inttrig(struct comedi_device *dev, if (ret < 0) { dev_err(dev->class_dev, "urbSubmit: err=%d\n", ret); devpriv->ai_cmd_running = 0; - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } s->async->inttrig = NULL; } else { dev_err(dev->class_dev, "ai is already running\n"); } - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return 1; } @@ -460,19 +468,14 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev, { struct usbduxfast_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; - unsigned int chan, gain, rngmask = 0xff; - int i, j, ret; - int result; + unsigned int rngmask = 0xff; + int j, ret; long steps, steps_tmp; - if (!devpriv) - return -EFAULT; - - down(&devpriv->sem); + mutex_lock(&devpriv->mut); if (devpriv->ai_cmd_running) { - dev_err(dev->class_dev, "ai_cmd not possible\n"); - up(&devpriv->sem); - return -EBUSY; + ret = -EBUSY; + goto cmd_exit; } /* @@ -481,50 +484,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev, */ devpriv->ignore = PACKETS_TO_IGNORE; - gain = CR_RANGE(cmd->chanlist[0]); - for (i = 0; i < cmd->chanlist_len; ++i) { - chan = CR_CHAN(cmd->chanlist[i]); - if (chan != i) { - dev_err(dev->class_dev, - "channels are not consecutive\n"); - up(&devpriv->sem); - return -EINVAL; - } - if ((gain != CR_RANGE(cmd->chanlist[i])) - && (cmd->chanlist_len > 3)) { - dev_err(dev->class_dev, - "gain must be the same for all channels\n"); - up(&devpriv->sem); - return -EINVAL; - } - if (i >= NUMCHANNELS) { - dev_err(dev->class_dev, "chanlist too long\n"); - break; - } - } - steps = 0; - if (cmd->convert_src == TRIG_TIMER) - steps = (cmd->convert_arg * 30) / 1000; - - if ((steps < MIN_SAMPLING_PERIOD) && (cmd->chanlist_len != 1)) { - dev_err(dev->class_dev, - "steps=%ld, scan_begin_arg=%d. Not properly tested by cmdtest?\n", - steps, cmd->scan_begin_arg); - up(&devpriv->sem); - return -EINVAL; - } - if (steps > MAX_SAMPLING_PERIOD) { - dev_err(dev->class_dev, "sampling rate too low\n"); - up(&devpriv->sem); - return -EINVAL; - } - if ((cmd->start_src == TRIG_EXT) && (cmd->chanlist_len != 1) - && (cmd->chanlist_len != 16)) { - dev_err(dev->class_dev, - "TRIG_EXT only with 1 or 16 channels possible\n"); - up(&devpriv->sem); - return -EINVAL; - } + steps = (cmd->convert_arg * 30) / 1000; switch (cmd->chanlist_len) { case 1: @@ -769,19 +729,12 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev, usbduxfast_cmd_data(dev, 4, 0x09, 0x01, rngmask, 0xff); break; - - default: - dev_err(dev->class_dev, "unsupported combination of channels\n"); - up(&devpriv->sem); - return -EFAULT; } /* 0 means that the AD commands are sent */ - result = usbduxfast_send_cmd(dev, SENDADCOMMANDS); - if (result < 0) { - up(&devpriv->sem); - return result; - } + ret = usbduxfast_send_cmd(dev, SENDADCOMMANDS); + if (ret < 0) + goto cmd_exit; if ((cmd->start_src == TRIG_NOW) || (cmd->start_src == TRIG_EXT)) { /* enable this acquisition operation */ @@ -790,16 +743,17 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev, if (ret < 0) { devpriv->ai_cmd_running = 0; /* fixme: unlink here?? */ - up(&devpriv->sem); - return ret; + goto cmd_exit; } s->async->inttrig = NULL; } else { /* TRIG_INT */ s->async->inttrig = usbduxfast_ai_inttrig; } - up(&devpriv->sem); - return 0; +cmd_exit: + mutex_unlock(&devpriv->mut); + + return ret; } /* @@ -814,16 +768,16 @@ static int usbduxfast_ai_insn_read(struct comedi_device *dev, struct usbduxfast_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); unsigned int range = CR_RANGE(insn->chanspec); - uint8_t rngmask = range ? (0xff - 0x04) : 0xff; + u8 rngmask = range ? (0xff - 0x04) : 0xff; int i, j, n, actual_length; int ret; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); if (devpriv->ai_cmd_running) { dev_err(dev->class_dev, "ai_insn_read not possible, async cmd is running\n"); - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return -EBUSY; } @@ -845,7 +799,7 @@ static int usbduxfast_ai_insn_read(struct comedi_device *dev, ret = usbduxfast_send_cmd(dev, SENDADCOMMANDS); if (ret < 0) { - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } @@ -855,7 +809,7 @@ static int usbduxfast_ai_insn_read(struct comedi_device *dev, &actual_length, 10000); if (ret < 0) { dev_err(dev->class_dev, "insn timeout, no data\n"); - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } } @@ -866,65 +820,32 @@ static int usbduxfast_ai_insn_read(struct comedi_device *dev, &actual_length, 10000); if (ret < 0) { dev_err(dev->class_dev, "insn data error: %d\n", ret); - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } - n = actual_length / sizeof(uint16_t); + n = actual_length / sizeof(u16); if ((n % 16) != 0) { dev_err(dev->class_dev, "insn data packet corrupted\n"); - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return -EINVAL; } for (j = chan; (j < n) && (i < insn->n); j = j + 16) { - data[i] = ((uint16_t *) (devpriv->inbuf))[j]; + data[i] = ((u16 *)(devpriv->inbuf))[j]; i++; } } - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return insn->n; } -static int usbduxfast_attach_common(struct comedi_device *dev) -{ - struct usbduxfast_private *devpriv = dev->private; - struct comedi_subdevice *s; - int ret; - - down(&devpriv->sem); - - ret = comedi_alloc_subdevices(dev, 1); - if (ret) { - up(&devpriv->sem); - return ret; - } - - /* Analog Input subdevice */ - s = &dev->subdevices[0]; - dev->read_subdev = s; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; - s->n_chan = 16; - s->len_chanlist = 16; - s->insn_read = usbduxfast_ai_insn_read; - s->do_cmdtest = usbduxfast_ai_cmdtest; - s->do_cmd = usbduxfast_ai_cmd; - s->cancel = usbduxfast_ai_cancel; - s->maxdata = 0x1000; - s->range_table = &range_usbduxfast_ai_range; - - up(&devpriv->sem); - - return 0; -} - static int usbduxfast_upload_firmware(struct comedi_device *dev, const u8 *data, size_t size, unsigned long context) { struct usb_device *usb = comedi_to_usb_dev(dev); - uint8_t *buf; + u8 *buf; unsigned char *tmp; int ret; @@ -996,6 +917,7 @@ static int usbduxfast_auto_attach(struct comedi_device *dev, struct usb_interface *intf = comedi_to_usb_interface(dev); struct usb_device *usb = comedi_to_usb_dev(dev); struct usbduxfast_private *devpriv; + struct comedi_subdevice *s; int ret; if (usb->speed != USB_SPEED_HIGH) { @@ -1008,7 +930,7 @@ static int usbduxfast_auto_attach(struct comedi_device *dev, if (!devpriv) return -ENOMEM; - sema_init(&devpriv->sem, 1); + mutex_init(&devpriv->mut); usb_set_intfdata(intf, devpriv); devpriv->duxbuf = kmalloc(SIZEOFDUXBUF, GFP_KERNEL); @@ -1038,7 +960,25 @@ static int usbduxfast_auto_attach(struct comedi_device *dev, if (ret) return ret; - return usbduxfast_attach_common(dev); + ret = comedi_alloc_subdevices(dev, 1); + if (ret) + return ret; + + /* Analog Input subdevice */ + s = &dev->subdevices[0]; + dev->read_subdev = s; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; + s->n_chan = 16; + s->maxdata = 0x1000; /* 12-bit + 1 overflow bit */ + s->range_table = &range_usbduxfast_ai_range; + s->insn_read = usbduxfast_ai_insn_read; + s->len_chanlist = s->n_chan; + s->do_cmdtest = usbduxfast_ai_cmdtest; + s->do_cmd = usbduxfast_ai_cmd; + s->cancel = usbduxfast_ai_cancel; + + return 0; } static void usbduxfast_detach(struct comedi_device *dev) @@ -1049,7 +989,7 @@ static void usbduxfast_detach(struct comedi_device *dev) if (!devpriv) return; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); usb_set_intfdata(intf, NULL); @@ -1058,18 +998,12 @@ static void usbduxfast_detach(struct comedi_device *dev) usb_kill_urb(devpriv->urb); kfree(devpriv->inbuf); - devpriv->inbuf = NULL; - usb_free_urb(devpriv->urb); - devpriv->urb = NULL; } kfree(devpriv->duxbuf); - devpriv->duxbuf = NULL; - - devpriv->ai_cmd_running = 0; - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); } static struct comedi_driver usbduxfast_driver = { diff --git a/kernel/drivers/staging/comedi/drivers/usbduxsigma.c b/kernel/drivers/staging/comedi/drivers/usbduxsigma.c index dc0b25a54..456e9f13b 100644 --- a/kernel/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/kernel/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1,6 +1,6 @@ /* * usbduxsigma.c - * Copyright (C) 2011-2014 Bernd Porr, mail@berndporr.me.uk + * Copyright (C) 2011-2015 Bernd Porr, mail@berndporr.me.uk * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,7 +18,7 @@ * Description: University of Stirling USB DAQ & INCITE Technology Limited * Devices: [ITL] USB-DUX-SIGMA (usbduxsigma) * Author: Bernd Porr <mail@berndporr.me.uk> - * Updated: 10 Oct 2014 + * Updated: 20 July 2015 * Status: stable */ @@ -39,6 +39,7 @@ * 0.4: fixed D/A voltage range * 0.5: various bug fixes, health check at startup * 0.6: corrected wrong input range + * 0.7: rewrite code that urb->interval is always 1 */ #include <linux/kernel.h> @@ -65,22 +66,22 @@ #define USBDUXSUB_CPUCS 0xE600 /* 300Hz max frequ under PWM */ -#define MIN_PWM_PERIOD ((long)(1E9/300)) +#define MIN_PWM_PERIOD ((long)(1E9 / 300)) /* Default PWM frequency */ -#define PWM_DEFAULT_PERIOD ((long)(1E9/100)) +#define PWM_DEFAULT_PERIOD ((long)(1E9 / 100)) /* Number of channels (16 AD and offset)*/ #define NUMCHANNELS 16 /* Size of one A/D value */ -#define SIZEADIN ((sizeof(uint32_t))) +#define SIZEADIN ((sizeof(u32))) /* * Size of the async input-buffer IN BYTES, the DIO state is transmitted * as the first byte. */ -#define SIZEINBUF (((NUMCHANNELS+1)*SIZEADIN)) +#define SIZEINBUF (((NUMCHANNELS + 1) * SIZEADIN)) /* 16 bytes. */ #define SIZEINSNBUF 16 @@ -89,20 +90,20 @@ #define NUMOUTCHANNELS 8 /* size of one value for the D/A converter: channel and value */ -#define SIZEDAOUT ((sizeof(uint8_t)+sizeof(uint16_t))) +#define SIZEDAOUT ((sizeof(u8) + sizeof(uint16_t))) /* * Size of the output-buffer in bytes * Actually only the first 4 triplets are used but for the * high speed mode we need to pad it to 8 (microframes). */ -#define SIZEOUTBUF ((8*SIZEDAOUT)) +#define SIZEOUTBUF ((8 * SIZEDAOUT)) /* * Size of the buffer for the dux commands: just now max size is determined * by the analogue out + command byte + panic bytes... */ -#define SIZEOFDUXBUFFER ((8*SIZEDAOUT+2)) +#define SIZEOFDUXBUFFER ((8 * SIZEDAOUT + 2)) /* Number of in-URBs which receive the data: min=2 */ #define NUMOFINBUFFERSFULL 5 @@ -122,7 +123,7 @@ #define RETRIES 10 /* bulk transfer commands to usbduxsigma */ -#define USBBUXSIGMA_AD_CMD 0 +#define USBBUXSIGMA_AD_CMD 9 #define USBDUXSIGMA_DA_CMD 1 #define USBDUXSIGMA_DIO_CFG_CMD 2 #define USBDUXSIGMA_DIO_BITS_CMD 3 @@ -149,13 +150,13 @@ struct usbduxsigma_private { /* PWM period */ unsigned int pwm_period; /* PWM internal delay for the GPIF in the FX2 */ - uint8_t pwm_delay; + u8 pwm_delay; /* size of the PWM buffer which holds the bit pattern */ int pwm_buf_sz; /* input buffer for the ISO-transfer */ __be32 *in_buf; /* input buffer for single insn */ - uint8_t *insn_buf; + u8 *insn_buf; unsigned high_speed:1; unsigned ai_cmd_running:1; @@ -171,8 +172,8 @@ struct usbduxsigma_private { /* interval in frames/uframes */ unsigned int ai_interval; /* commands */ - uint8_t *dux_commands; - struct semaphore sem; + u8 *dux_commands; + struct mutex mut; }; static void usbduxsigma_unlink_urbs(struct urb **urbs, int num_urbs) @@ -198,10 +199,10 @@ static int usbduxsigma_ai_cancel(struct comedi_device *dev, { struct usbduxsigma_private *devpriv = dev->private; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); /* unlink only if it is really running */ usbduxsigma_ai_stop(dev, devpriv->ai_cmd_running); - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return 0; } @@ -213,28 +214,31 @@ static void usbduxsigma_ai_handle_urb(struct comedi_device *dev, struct usbduxsigma_private *devpriv = dev->private; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; - uint32_t val; + u32 val; int ret; int i; - devpriv->ai_counter--; - if (devpriv->ai_counter == 0) { - devpriv->ai_counter = devpriv->ai_timer; + if ((urb->actual_length > 0) && (urb->status != -EXDEV)) { + devpriv->ai_counter--; + if (devpriv->ai_counter == 0) { + devpriv->ai_counter = devpriv->ai_timer; - /* get the data from the USB bus and hand it over to comedi */ - for (i = 0; i < cmd->chanlist_len; i++) { - /* transfer data, note first byte is the DIO state */ - val = be32_to_cpu(devpriv->in_buf[i+1]); - val &= 0x00ffffff; /* strip status byte */ - val ^= 0x00800000; /* convert to unsigned */ + /* + * Get the data from the USB bus and hand it over + * to comedi. Note, first byte is the DIO state. + */ + for (i = 0; i < cmd->chanlist_len; i++) { + val = be32_to_cpu(devpriv->in_buf[i + 1]); + val &= 0x00ffffff; /* strip status byte */ + val = comedi_offset_munge(s, val); + if (!comedi_buf_write_samples(s, &val, 1)) + return; + } - if (!comedi_buf_write_samples(s, &val, 1)) - return; + if (cmd->stop_src == TRIG_COUNT && + async->scans_done >= cmd->stop_arg) + async->events |= COMEDI_CB_EOA; } - - if (cmd->stop_src == TRIG_COUNT && - async->scans_done >= cmd->stop_arg) - async->events |= COMEDI_CB_EOA; } /* if command is still running, resubmit urb */ @@ -321,10 +325,10 @@ static int usbduxsigma_ao_cancel(struct comedi_device *dev, { struct usbduxsigma_private *devpriv = dev->private; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); /* unlink only if it is really running */ usbduxsigma_ao_stop(dev, devpriv->ao_cmd_running); - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return 0; } @@ -336,7 +340,7 @@ static void usbduxsigma_ao_handle_urb(struct comedi_device *dev, struct usbduxsigma_private *devpriv = dev->private; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; - uint8_t *datap; + u8 *datap; int ret; int i; @@ -374,10 +378,7 @@ static void usbduxsigma_ao_handle_urb(struct comedi_device *dev, urb->transfer_buffer_length = SIZEOUTBUF; urb->dev = comedi_to_usb_dev(dev); urb->status = 0; - if (devpriv->high_speed) - urb->interval = 8; /* uframes */ - else - urb->interval = 1; /* frames */ + urb->interval = 1; /* (u)frames */ urb->number_of_packets = 1; urb->iso_frame_desc[0].offset = 0; urb->iso_frame_desc[0].length = SIZEOUTBUF; @@ -441,7 +442,6 @@ static int usbduxsigma_submit_urbs(struct comedi_device *dev, int input_urb) { struct usb_device *usb = comedi_to_usb_dev(dev); - struct usbduxsigma_private *devpriv = dev->private; struct urb *urb; int ret; int i; @@ -452,7 +452,7 @@ static int usbduxsigma_submit_urbs(struct comedi_device *dev, /* in case of a resubmission after an unlink... */ if (input_urb) - urb->interval = devpriv->ai_interval; + urb->interval = 1; urb->context = dev; urb->dev = usb; urb->status = 0; @@ -481,6 +481,7 @@ static int usbduxsigma_ai_cmdtest(struct comedi_device *dev, struct usbduxsigma_private *devpriv = dev->private; int high_speed = devpriv->high_speed; int interval = usbduxsigma_chans_to_interval(cmd->chanlist_len); + unsigned int tmp; int err = 0; /* Step 1 : check if triggers are trivially valid */ @@ -508,35 +509,20 @@ static int usbduxsigma_ai_cmdtest(struct comedi_device *dev, err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); - if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */ - err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0); - - if (cmd->scan_begin_src == TRIG_TIMER) { - unsigned int tmp; - - if (high_speed) { - /* - * In high speed mode microframes are possible. - * However, during one microframe we can roughly - * sample two channels. Thus, the more channels - * are in the channel list the more time we need. - */ - err |= comedi_check_trigger_arg_min(&cmd-> - scan_begin_arg, - (1000000 / 8 * - interval)); - - tmp = (cmd->scan_begin_arg / 125000) * 125000; - } else { - /* full speed */ - /* 1kHz scans every USB frame */ - err |= comedi_check_trigger_arg_min(&cmd-> - scan_begin_arg, - 1000000); - - tmp = (cmd->scan_begin_arg / 1000000) * 1000000; - } - err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, tmp); + if (high_speed) { + /* + * In high speed mode microframes are possible. + * However, during one microframe we can roughly + * sample two channels. Thus, the more channels + * are in the channel list the more time we need. + */ + err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, + (125000 * interval)); + } else { + /* full speed */ + /* 1kHz scans every USB frame */ + err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, + 1000000); } err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, @@ -550,6 +536,14 @@ static int usbduxsigma_ai_cmdtest(struct comedi_device *dev, if (err) return 3; + /* Step 4: fix up any arguments */ + + tmp = rounddown(cmd->scan_begin_arg, high_speed ? 125000 : 1000000); + err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, tmp); + + if (err) + return 4; + return 0; } @@ -558,13 +552,12 @@ static int usbduxsigma_ai_cmdtest(struct comedi_device *dev, * range is the range value from comedi */ static void create_adc_command(unsigned int chan, - uint8_t *muxsg0, - uint8_t *muxsg1) + u8 *muxsg0, u8 *muxsg1) { if (chan < 8) (*muxsg0) = (*muxsg0) | (1 << chan); else if (chan < 16) - (*muxsg1) = (*muxsg1) | (1 << (chan-8)); + (*muxsg1) = (*muxsg1) | (1 << (chan - 8)); } static int usbbuxsigma_send_cmd(struct comedi_device *dev, int cmd_type) @@ -616,19 +609,19 @@ static int usbduxsigma_ai_inttrig(struct comedi_device *dev, if (trig_num != cmd->start_arg) return -EINVAL; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); if (!devpriv->ai_cmd_running) { devpriv->ai_cmd_running = 1; ret = usbduxsigma_submit_urbs(dev, devpriv->ai_urbs, devpriv->n_ai_urbs, 1); if (ret < 0) { devpriv->ai_cmd_running = 0; - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } s->async->inttrig = NULL; } - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return 1; } @@ -639,13 +632,13 @@ static int usbduxsigma_ai_cmd(struct comedi_device *dev, struct usbduxsigma_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; unsigned int len = cmd->chanlist_len; - uint8_t muxsg0 = 0; - uint8_t muxsg1 = 0; - uint8_t sysred = 0; + u8 muxsg0 = 0; + u8 muxsg1 = 0; + u8 sysred = 0; int ret; int i; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); if (devpriv->high_speed) { /* @@ -669,17 +662,18 @@ static int usbduxsigma_ai_cmd(struct comedi_device *dev, create_adc_command(chan, &muxsg0, &muxsg1); } - devpriv->dux_commands[1] = len; /* num channels per time step */ - devpriv->dux_commands[2] = 0x12; /* CONFIG0 */ - devpriv->dux_commands[3] = 0x03; /* CONFIG1: 23kHz sample, delay 0us */ - devpriv->dux_commands[4] = 0x00; /* CONFIG3: diff. channels off */ - devpriv->dux_commands[5] = muxsg0; - devpriv->dux_commands[6] = muxsg1; - devpriv->dux_commands[7] = sysred; + devpriv->dux_commands[1] = devpriv->ai_interval; + devpriv->dux_commands[2] = len; /* num channels per time step */ + devpriv->dux_commands[3] = 0x12; /* CONFIG0 */ + devpriv->dux_commands[4] = 0x03; /* CONFIG1: 23kHz sample, delay 0us */ + devpriv->dux_commands[5] = 0x00; /* CONFIG3: diff. channels off */ + devpriv->dux_commands[6] = muxsg0; + devpriv->dux_commands[7] = muxsg1; + devpriv->dux_commands[8] = sysred; ret = usbbuxsigma_send_cmd(dev, USBBUXSIGMA_AD_CMD); if (ret < 0) { - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } @@ -692,7 +686,7 @@ static int usbduxsigma_ai_cmd(struct comedi_device *dev, devpriv->n_ai_urbs, 1); if (ret < 0) { devpriv->ai_cmd_running = 0; - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } s->async->inttrig = NULL; @@ -700,7 +694,7 @@ static int usbduxsigma_ai_cmd(struct comedi_device *dev, s->async->inttrig = usbduxsigma_ai_inttrig; } - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return 0; } @@ -712,15 +706,15 @@ static int usbduxsigma_ai_insn_read(struct comedi_device *dev, { struct usbduxsigma_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); - uint8_t muxsg0 = 0; - uint8_t muxsg1 = 0; - uint8_t sysred = 0; + u8 muxsg0 = 0; + u8 muxsg1 = 0; + u8 sysred = 0; int ret; int i; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); if (devpriv->ai_cmd_running) { - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return -EBUSY; } @@ -737,16 +731,16 @@ static int usbduxsigma_ai_insn_read(struct comedi_device *dev, /* adc commands */ ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD); if (ret < 0) { - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } for (i = 0; i < insn->n; i++) { - uint32_t val; + u32 val; ret = usbduxsigma_receive_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD); if (ret < 0) { - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } @@ -754,11 +748,9 @@ static int usbduxsigma_ai_insn_read(struct comedi_device *dev, val = be32_to_cpu(get_unaligned((__be32 *)(devpriv->insn_buf + 1))); val &= 0x00ffffff; /* strip status byte */ - val ^= 0x00800000; /* convert to unsigned */ - - data[i] = val; + data[i] = comedi_offset_munge(s, val); } - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return insn->n; } @@ -771,9 +763,9 @@ static int usbduxsigma_ao_insn_read(struct comedi_device *dev, struct usbduxsigma_private *devpriv = dev->private; int ret; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); ret = comedi_readback_insn_read(dev, s, insn, data); - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } @@ -788,9 +780,9 @@ static int usbduxsigma_ao_insn_write(struct comedi_device *dev, int ret; int i; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); if (devpriv->ao_cmd_running) { - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return -EBUSY; } @@ -800,12 +792,12 @@ static int usbduxsigma_ao_insn_write(struct comedi_device *dev, devpriv->dux_commands[3] = chan; /* channel number */ ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_DA_CMD); if (ret < 0) { - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } s->readback[chan] = data[i]; } - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return insn->n; } @@ -821,19 +813,19 @@ static int usbduxsigma_ao_inttrig(struct comedi_device *dev, if (trig_num != cmd->start_arg) return -EINVAL; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); if (!devpriv->ao_cmd_running) { devpriv->ao_cmd_running = 1; ret = usbduxsigma_submit_urbs(dev, devpriv->ao_urbs, devpriv->n_ao_urbs, 0); if (ret < 0) { devpriv->ao_cmd_running = 0; - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } s->async->inttrig = NULL; } - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return 1; } @@ -843,35 +835,28 @@ static int usbduxsigma_ao_cmdtest(struct comedi_device *dev, struct comedi_cmd *cmd) { struct usbduxsigma_private *devpriv = dev->private; + unsigned int tmp; int err = 0; - int high_speed; - unsigned int flags; - - /* high speed conversions are not used yet */ - high_speed = 0; /* (devpriv->high_speed) */ /* Step 1 : check if triggers are trivially valid */ err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); - if (high_speed) { - /* - * start immediately a new scan - * the sampling rate is set by the coversion rate - */ - flags = TRIG_FOLLOW; - } else { - /* start a new scan (output at once) with a timer */ - flags = TRIG_TIMER; - } - err |= comedi_check_trigger_src(&cmd->scan_begin_src, flags); - + /* + * For now, always use "scan" timing with all channels updated at once + * (cmd->scan_begin_src == TRIG_TIMER, cmd->convert_src == TRIG_NOW). + * + * In a future version, "convert" timing with channels updated + * indivually may be supported in high speed mode + * (cmd->scan_begin_src == TRIG_FOLLOW, cmd->convert_src == TRIG_TIMER). + */ + err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER); err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW); err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); if (err) { - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return 1; } @@ -889,17 +874,7 @@ static int usbduxsigma_ao_cmdtest(struct comedi_device *dev, err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); - if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */ - err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0); - - if (cmd->scan_begin_src == TRIG_TIMER) { - err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, - 1000000); - } - - /* not used now, is for later use */ - if (cmd->convert_src == TRIG_TIMER) - err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 125000); + err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, 1000000); err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); @@ -912,6 +887,14 @@ static int usbduxsigma_ao_cmdtest(struct comedi_device *dev, if (err) return 3; + /* Step 4: fix up any arguments */ + + tmp = rounddown(cmd->scan_begin_arg, 1000000); + err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, tmp); + + if (err) + return 4; + return 0; } @@ -922,21 +905,15 @@ static int usbduxsigma_ao_cmd(struct comedi_device *dev, struct comedi_cmd *cmd = &s->async->cmd; int ret; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); - if (cmd->convert_src == TRIG_TIMER) { - /* - * timing of the conversion itself: every 125 us - * at high speed (not used yet) - */ - devpriv->ao_timer = cmd->convert_arg / 125000; - } else { - /* - * timing of the scan: every 1ms - * we get all channels at once - */ - devpriv->ao_timer = cmd->scan_begin_arg / 1000000; - } + /* + * For now, only "scan" timing is supported. A future version may + * support "convert" timing in high speed mode. + * + * Timing of the scan: every 1ms all channels updated at once. + */ + devpriv->ao_timer = cmd->scan_begin_arg / 1000000; devpriv->ao_counter = devpriv->ao_timer; @@ -947,7 +924,7 @@ static int usbduxsigma_ao_cmd(struct comedi_device *dev, devpriv->n_ao_urbs, 0); if (ret < 0) { devpriv->ao_cmd_running = 0; - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } s->async->inttrig = NULL; @@ -955,7 +932,7 @@ static int usbduxsigma_ao_cmd(struct comedi_device *dev, s->async->inttrig = usbduxsigma_ao_inttrig; } - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return 0; } @@ -986,7 +963,7 @@ static int usbduxsigma_dio_insn_bits(struct comedi_device *dev, struct usbduxsigma_private *devpriv = dev->private; int ret; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); comedi_dio_update_state(s, data); @@ -1013,7 +990,7 @@ static int usbduxsigma_dio_insn_bits(struct comedi_device *dev, ret = insn->n; done: - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); return ret; } @@ -1239,9 +1216,10 @@ static int usbduxsigma_pwm_config(struct comedi_device *dev, static int usbduxsigma_getstatusinfo(struct comedi_device *dev, int chan) { + struct comedi_subdevice *s = dev->read_subdev; struct usbduxsigma_private *devpriv = dev->private; - uint8_t sysred; - uint32_t val; + u8 sysred; + u32 val; int ret; switch (chan) { @@ -1283,9 +1261,8 @@ static int usbduxsigma_getstatusinfo(struct comedi_device *dev, int chan) /* 32 bits big endian from the A/D converter */ val = be32_to_cpu(get_unaligned((__be32 *)(devpriv->insn_buf + 1))); val &= 0x00ffffff; /* strip status byte */ - val ^= 0x00800000; /* convert to unsigned */ - return (int)val; + return (int)comedi_offset_munge(s, val); } static int usbduxsigma_firmware_upload(struct comedi_device *dev, @@ -1293,8 +1270,8 @@ static int usbduxsigma_firmware_upload(struct comedi_device *dev, unsigned long context) { struct usb_device *usb = comedi_to_usb_dev(dev); - uint8_t *buf; - uint8_t *tmp; + u8 *buf; + u8 *tmp; int ret; if (!data) @@ -1417,10 +1394,7 @@ static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev) urb->transfer_buffer_length = SIZEOUTBUF; urb->iso_frame_desc[0].offset = 0; urb->iso_frame_desc[0].length = SIZEOUTBUF; - if (devpriv->high_speed) - urb->interval = 8; /* uframes */ - else - urb->interval = 1; /* frames */ + urb->interval = 1; /* (u)frames */ } if (devpriv->pwm_buf_sz) { @@ -1488,7 +1462,7 @@ static int usbduxsigma_auto_attach(struct comedi_device *dev, if (!devpriv) return -ENOMEM; - sema_init(&devpriv->sem, 1); + mutex_init(&devpriv->mut); usb_set_intfdata(intf, devpriv); @@ -1602,7 +1576,7 @@ static void usbduxsigma_detach(struct comedi_device *dev) if (!devpriv) return; - down(&devpriv->sem); + mutex_lock(&devpriv->mut); /* force unlink all urbs */ usbduxsigma_ai_stop(dev, 1); @@ -1611,7 +1585,7 @@ static void usbduxsigma_detach(struct comedi_device *dev) usbduxsigma_free_usb_buffers(dev); - up(&devpriv->sem); + mutex_unlock(&devpriv->mut); } static struct comedi_driver usbduxsigma_driver = { @@ -1643,7 +1617,7 @@ static struct usb_driver usbduxsigma_usb_driver = { }; module_comedi_usb_driver(usbduxsigma_driver, usbduxsigma_usb_driver); -MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com"); -MODULE_DESCRIPTION("Stirling/ITL USB-DUX SIGMA -- Bernd.Porr@f2s.com"); +MODULE_AUTHOR("Bernd Porr, mail@berndporr.me.uk"); +MODULE_DESCRIPTION("Stirling/ITL USB-DUX SIGMA -- mail@berndporr.me.uk"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(FIRMWARE); diff --git a/kernel/drivers/staging/comedi/drivers/vmk80xx.c b/kernel/drivers/staging/comedi/drivers/vmk80xx.c index a0906685e..8c7393ef7 100644 --- a/kernel/drivers/staging/comedi/drivers/vmk80xx.c +++ b/kernel/drivers/staging/comedi/drivers/vmk80xx.c @@ -1,22 +1,23 @@ /* - comedi/drivers/vmk80xx.c - Velleman USB Board Low-Level Driver - - Copyright (C) 2009 Manuel Gebele <forensixs@gmx.de>, Germany - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + * vmk80xx.c + * Velleman USB Board Low-Level Driver + * + * Copyright (C) 2009 Manuel Gebele <forensixs@gmx.de>, Germany + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ /* * Driver: vmk80xx * Description: Velleman USB Board Low-Level Driver @@ -51,52 +52,52 @@ enum { DEVICE_VMK8061 }; -#define VMK8055_DI_REG 0x00 -#define VMK8055_DO_REG 0x01 -#define VMK8055_AO1_REG 0x02 -#define VMK8055_AO2_REG 0x03 -#define VMK8055_AI1_REG 0x02 -#define VMK8055_AI2_REG 0x03 -#define VMK8055_CNT1_REG 0x04 -#define VMK8055_CNT2_REG 0x06 - -#define VMK8061_CH_REG 0x01 -#define VMK8061_DI_REG 0x01 -#define VMK8061_DO_REG 0x01 -#define VMK8061_PWM_REG1 0x01 -#define VMK8061_PWM_REG2 0x02 -#define VMK8061_CNT_REG 0x02 -#define VMK8061_AO_REG 0x02 -#define VMK8061_AI_REG1 0x02 -#define VMK8061_AI_REG2 0x03 - -#define VMK8055_CMD_RST 0x00 -#define VMK8055_CMD_DEB1_TIME 0x01 -#define VMK8055_CMD_DEB2_TIME 0x02 -#define VMK8055_CMD_RST_CNT1 0x03 -#define VMK8055_CMD_RST_CNT2 0x04 -#define VMK8055_CMD_WRT_AD 0x05 - -#define VMK8061_CMD_RD_AI 0x00 -#define VMK8061_CMR_RD_ALL_AI 0x01 /* !non-active! */ -#define VMK8061_CMD_SET_AO 0x02 -#define VMK8061_CMD_SET_ALL_AO 0x03 /* !non-active! */ -#define VMK8061_CMD_OUT_PWM 0x04 -#define VMK8061_CMD_RD_DI 0x05 -#define VMK8061_CMD_DO 0x06 /* !non-active! */ -#define VMK8061_CMD_CLR_DO 0x07 -#define VMK8061_CMD_SET_DO 0x08 -#define VMK8061_CMD_RD_CNT 0x09 /* TODO: completely pointless? */ -#define VMK8061_CMD_RST_CNT 0x0a /* TODO: completely pointless? */ -#define VMK8061_CMD_RD_VERSION 0x0b /* internal usage */ -#define VMK8061_CMD_RD_JMP_STAT 0x0c /* TODO: not implemented yet */ -#define VMK8061_CMD_RD_PWR_STAT 0x0d /* internal usage */ -#define VMK8061_CMD_RD_DO 0x0e -#define VMK8061_CMD_RD_AO 0x0f -#define VMK8061_CMD_RD_PWM 0x10 - -#define IC3_VERSION (1 << 0) -#define IC6_VERSION (1 << 1) +#define VMK8055_DI_REG 0x00 +#define VMK8055_DO_REG 0x01 +#define VMK8055_AO1_REG 0x02 +#define VMK8055_AO2_REG 0x03 +#define VMK8055_AI1_REG 0x02 +#define VMK8055_AI2_REG 0x03 +#define VMK8055_CNT1_REG 0x04 +#define VMK8055_CNT2_REG 0x06 + +#define VMK8061_CH_REG 0x01 +#define VMK8061_DI_REG 0x01 +#define VMK8061_DO_REG 0x01 +#define VMK8061_PWM_REG1 0x01 +#define VMK8061_PWM_REG2 0x02 +#define VMK8061_CNT_REG 0x02 +#define VMK8061_AO_REG 0x02 +#define VMK8061_AI_REG1 0x02 +#define VMK8061_AI_REG2 0x03 + +#define VMK8055_CMD_RST 0x00 +#define VMK8055_CMD_DEB1_TIME 0x01 +#define VMK8055_CMD_DEB2_TIME 0x02 +#define VMK8055_CMD_RST_CNT1 0x03 +#define VMK8055_CMD_RST_CNT2 0x04 +#define VMK8055_CMD_WRT_AD 0x05 + +#define VMK8061_CMD_RD_AI 0x00 +#define VMK8061_CMR_RD_ALL_AI 0x01 /* !non-active! */ +#define VMK8061_CMD_SET_AO 0x02 +#define VMK8061_CMD_SET_ALL_AO 0x03 /* !non-active! */ +#define VMK8061_CMD_OUT_PWM 0x04 +#define VMK8061_CMD_RD_DI 0x05 +#define VMK8061_CMD_DO 0x06 /* !non-active! */ +#define VMK8061_CMD_CLR_DO 0x07 +#define VMK8061_CMD_SET_DO 0x08 +#define VMK8061_CMD_RD_CNT 0x09 /* TODO: completely pointless? */ +#define VMK8061_CMD_RST_CNT 0x0a /* TODO: completely pointless? */ +#define VMK8061_CMD_RD_VERSION 0x0b /* internal usage */ +#define VMK8061_CMD_RD_JMP_STAT 0x0c /* TODO: not implemented yet */ +#define VMK8061_CMD_RD_PWR_STAT 0x0d /* internal usage */ +#define VMK8061_CMD_RD_DO 0x0e +#define VMK8061_CMD_RD_AO 0x0f +#define VMK8061_CMD_RD_PWM 0x10 + +#define IC3_VERSION BIT(0) +#define IC6_VERSION BIT(1) enum vmk80xx_model { VMK8055_MODEL, @@ -700,7 +701,7 @@ static int vmk80xx_alloc_usb_buffers(struct comedi_device *dev) static int vmk80xx_init_subdevices(struct comedi_device *dev) { - const struct vmk80xx_board *boardinfo = dev->board_ptr; + const struct vmk80xx_board *board = dev->board_ptr; struct vmk80xx_private *devpriv = dev->private; struct comedi_subdevice *s; int n_subd; @@ -722,18 +723,18 @@ static int vmk80xx_init_subdevices(struct comedi_device *dev) s = &dev->subdevices[0]; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND; - s->n_chan = boardinfo->ai_nchans; - s->maxdata = boardinfo->ai_maxdata; - s->range_table = boardinfo->range; + s->n_chan = board->ai_nchans; + s->maxdata = board->ai_maxdata; + s->range_table = board->range; s->insn_read = vmk80xx_ai_insn_read; /* Analog output subdevice */ s = &dev->subdevices[1]; s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND; - s->n_chan = boardinfo->ao_nchans; + s->n_chan = board->ao_nchans; s->maxdata = 0x00ff; - s->range_table = boardinfo->range; + s->range_table = board->range; s->insn_write = vmk80xx_ao_insn_write; if (devpriv->model == VMK8061_MODEL) { s->subdev_flags |= SDF_READABLE; @@ -744,7 +745,7 @@ static int vmk80xx_init_subdevices(struct comedi_device *dev) s = &dev->subdevices[2]; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; - s->n_chan = boardinfo->di_nchans; + s->n_chan = board->di_nchans; s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = vmk80xx_di_insn_bits; @@ -763,7 +764,7 @@ static int vmk80xx_init_subdevices(struct comedi_device *dev) s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE; s->n_chan = 2; - s->maxdata = boardinfo->cnt_maxdata; + s->maxdata = board->cnt_maxdata; s->insn_read = vmk80xx_cnt_insn_read; s->insn_config = vmk80xx_cnt_insn_config; if (devpriv->model == VMK8055_MODEL) { @@ -776,8 +777,8 @@ static int vmk80xx_init_subdevices(struct comedi_device *dev) s = &dev->subdevices[5]; s->type = COMEDI_SUBD_PWM; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = boardinfo->pwm_nchans; - s->maxdata = boardinfo->pwm_maxdata; + s->n_chan = board->pwm_nchans; + s->maxdata = board->pwm_maxdata; s->insn_read = vmk80xx_pwm_insn_read; s->insn_write = vmk80xx_pwm_insn_write; } @@ -791,19 +792,22 @@ static int vmk80xx_auto_attach(struct comedi_device *dev, unsigned long context) { struct usb_interface *intf = comedi_to_usb_interface(dev); - const struct vmk80xx_board *boardinfo; + const struct vmk80xx_board *board = NULL; struct vmk80xx_private *devpriv; int ret; - boardinfo = &vmk80xx_boardinfo[context]; - dev->board_ptr = boardinfo; - dev->board_name = boardinfo->name; + if (context < ARRAY_SIZE(vmk80xx_boardinfo)) + board = &vmk80xx_boardinfo[context]; + if (!board) + return -ENODEV; + dev->board_ptr = board; + dev->board_name = board->name; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - devpriv->model = boardinfo->model; + devpriv->model = board->model; ret = vmk80xx_find_usb_endpoints(dev); if (ret) diff --git a/kernel/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/kernel/drivers/staging/comedi/kcomedilib/kcomedilib_main.c index 76bf5619f..d0a8a28ed 100644 --- a/kernel/drivers/staging/comedi/kcomedilib/kcomedilib_main.c +++ b/kernel/drivers/staging/comedi/kcomedilib/kcomedilib_main.c @@ -1,20 +1,20 @@ /* - kcomedilib/kcomedilib.c - a comedlib interface for kernel modules - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * kcomedilib/kcomedilib.c + * a comedlib interface for kernel modules + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #include <linux/module.h> diff --git a/kernel/drivers/staging/comedi/range.c b/kernel/drivers/staging/comedi/range.c index 6a393b24b..ce3a58a7a 100644 --- a/kernel/drivers/staging/comedi/range.c +++ b/kernel/drivers/staging/comedi/range.c @@ -102,7 +102,18 @@ int do_rangeinfo_ioctl(struct comedi_device *dev, * @s: comedi_subdevice struct * @n: number of elements in the chanlist * @chanlist: the chanlist to validate -*/ + * + * Each element consists of a channel number, a range index, an analog + * reference type and some flags, all packed into an unsigned int. + * + * This checks that the channel number and range index are supported by + * the comedi subdevice. It does not check whether the analog reference + * type and the flags are supported. Drivers that care should check those + * themselves. + * + * Return: %0 if all @chanlist elements are valid (success), + * %-EINVAL if one or more elements are invalid. + */ int comedi_check_chanlist(struct comedi_subdevice *s, int n, unsigned int *chanlist) { |