diff options
Diffstat (limited to 'drivers/staging/comedi')
123 files changed, 8810 insertions, 10436 deletions
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index a2f6957e7ee9..36f2c7159250 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -135,13 +135,14 @@ config COMEDI_PCL724 support driver. Supported boards include: - Advantech PCL-724 24 channels - Advantech PCL-722 144 (or 96) channels - Advantech PCL-731 48 channels - ADlink ACL-7122 144 (or 96) channels - ADlink ACL-7124 24 channels - ADlink PET-48DIO 48 channels - WinSystems PCM-IO48 48 channels (PC/104) + Advantech PCL-724 24 channels + Advantech PCL-722 144 (or 96) channels + Advantech PCL-731 48 channels + ADlink ACL-7122 144 (or 96) channels + ADlink ACL-7124 24 channels + ADlink PET-48DIO 48 channels + WinSystems PCM-IO48 48 channels (PC/104) + Diamond Systems ONYX-MM-DIO 48 channels (PC/104) To compile this driver as a module, choose M here: the module will be called pcl724. @@ -172,6 +173,7 @@ config COMEDI_PCL730 Advantech PCL-734 iso - 32 out Diamond Systems OPMM-1616-XT iso - 16 in/16 out Diamond Systems PEARL-MM-P iso - 16 out + Diamond Systems IR104-PBF iso - 20 in/20 out To compile this driver as a module, choose M here: the module will be called pcl730. @@ -813,7 +815,7 @@ config COMEDI_AMPLC_PC236_PCI Enable support for Amplicon PCI236 DIO board. To compile this driver as a module, choose M here: the module will be - called amplc_pc236. + called amplc_pci236. config COMEDI_AMPLC_PC263_PCI tristate "Amplicon PCI263 relay board support" @@ -1012,8 +1014,6 @@ config COMEDI_NI_6527 config COMEDI_NI_65XX tristate "NI 65xx static dio PCI card support" - depends on HAS_DMA - select COMEDI_MITE ---help--- Enable support for National Instruments 65xx static dio boards. Supported devices: National Instruments PCI-6509 (ni_65xx), @@ -1037,8 +1037,6 @@ config COMEDI_NI_660X config COMEDI_NI_670X tristate "NI 670x PCI card support" - depends on HAS_DMA - select COMEDI_MITE ---help--- Enable support for National Instruments PCI-6703 and PCI-6704 @@ -1047,9 +1045,7 @@ config COMEDI_NI_670X config COMEDI_NI_LABPC_PCI tristate "NI Lab-PC PCI-1200 support" - depends on HAS_DMA select COMEDI_NI_LABPC - select COMEDI_MITE ---help--- Enable support for National Instruments Lab-PC PCI-1200. diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index 6bbbe5b08954..217baf812f87 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -551,21 +551,8 @@ enum i8254_mode { I8254_BINARY = 0 }; -static inline unsigned NI_USUAL_PFI_SELECT(unsigned pfi_channel) -{ - if (pfi_channel < 10) - return 0x1 + pfi_channel; - else - return 0xb + pfi_channel; -} - -static inline unsigned NI_USUAL_RTSI_SELECT(unsigned rtsi_channel) -{ - if (rtsi_channel < 7) - return 0xb + rtsi_channel; - else - return 0x1b; -} +#define NI_USUAL_PFI_SELECT(x) (((x) < 10) ? (0x1 + (x)) : (0xb + (x))) +#define NI_USUAL_RTSI_SELECT(x) (((x) < 7) ? (0xb + (x)) : 0x1b) /* mode bits for NI general-purpose counters, set with * INSN_CONFIG_SET_COUNTER_MODE */ @@ -659,20 +646,14 @@ enum ni_gpct_clock_source_bits { NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS = 0x20000000, NI_GPCT_INVERT_CLOCK_SRC_BIT = 0x80000000 }; -static inline unsigned NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(unsigned n) -{ - /* NI 660x-specific */ - return 0x10 + n; -} -static inline unsigned NI_GPCT_RTSI_CLOCK_SRC_BITS(unsigned n) -{ - return 0x18 + n; -} -static inline unsigned NI_GPCT_PFI_CLOCK_SRC_BITS(unsigned n) -{ - /* no pfi on NI 660x */ - return 0x20 + n; -} + +/* NI 660x-specific */ +#define NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(x) (0x10 + (x)) + +#define NI_GPCT_RTSI_CLOCK_SRC_BITS(x) (0x18 + (x)) + +/* no pfi on NI 660x */ +#define NI_GPCT_PFI_CLOCK_SRC_BITS(x) (0x20 + (x)) /* Possibilities for setting a gate source with INSN_CONFIG_SET_GATE_SRC when using NI general-purpose counters. @@ -698,22 +679,11 @@ enum ni_gpct_gate_select { * known. */ NI_GPCT_DISABLED_GATE_SELECT = 0x8000, }; -static inline unsigned NI_GPCT_GATE_PIN_GATE_SELECT(unsigned n) -{ - return 0x102 + n; -} -static inline unsigned NI_GPCT_RTSI_GATE_SELECT(unsigned n) -{ - return NI_USUAL_RTSI_SELECT(n); -} -static inline unsigned NI_GPCT_PFI_GATE_SELECT(unsigned n) -{ - return NI_USUAL_PFI_SELECT(n); -} -static inline unsigned NI_GPCT_UP_DOWN_PIN_GATE_SELECT(unsigned n) -{ - return 0x202 + n; -} + +#define NI_GPCT_GATE_PIN_GATE_SELECT(x) (0x102 + (x)) +#define NI_GPCT_RTSI_GATE_SELECT(x) NI_USUAL_RTSI_SELECT(x) +#define NI_GPCT_PFI_GATE_SELECT(x) NI_USUAL_PFI_SELECT(x) +#define NI_GPCT_UP_DOWN_PIN_GATE_SELECT(x) (0x202 + (x)) /* Possibilities for setting a source with INSN_CONFIG_SET_OTHER_SRC when using NI general-purpose counters. */ @@ -722,15 +692,14 @@ enum ni_gpct_other_index { NI_GPCT_SOURCE_ENCODER_B, NI_GPCT_SOURCE_ENCODER_Z }; + enum ni_gpct_other_select { /* m-series gates */ /* Still unknown, probably only need NI_GPCT_PFI_OTHER_SELECT */ NI_GPCT_DISABLED_OTHER_SELECT = 0x8000, }; -static inline unsigned NI_GPCT_PFI_OTHER_SELECT(unsigned n) -{ - return NI_USUAL_PFI_SELECT(n); -} + +#define NI_GPCT_PFI_OTHER_SELECT(x) NI_USUAL_PFI_SELECT(x) /* start sources for ni general-purpose counters for use with INSN_CONFIG_ARM */ @@ -777,10 +746,8 @@ enum ni_mio_clock_source { NI_MIO_PLL_PXI10_CLOCK = 3, NI_MIO_PLL_RTSI0_CLOCK = 4 }; -static inline unsigned NI_MIO_PLL_RTSI_CLOCK(unsigned rtsi_channel) -{ - return NI_MIO_PLL_RTSI0_CLOCK + rtsi_channel; -} + +#define NI_MIO_PLL_RTSI_CLOCK(x) (NI_MIO_PLL_RTSI0_CLOCK + (x)) /* Signals which can be routed to an NI RTSI pin with INSN_CONFIG_SET_ROUTING. The numbers assigned are not arbitrary, they correspond to the bits required @@ -798,10 +765,8 @@ enum ni_rtsi_routing { NI_RTSI_OUTPUT_RTSI_OSC = 12 /* pre-m-series always have RTSI * clock on line 7 */ }; -static inline unsigned NI_RTSI_OUTPUT_RTSI_BRD(unsigned n) -{ - return NI_RTSI_OUTPUT_RTSI_BRD_0 + n; -} + +#define NI_RTSI_OUTPUT_RTSI_BRD(x) (NI_RTSI_OUTPUT_RTSI_BRD_0 + (x)) /* Signals which can be routed to an NI PFI pin on an m-series board with * INSN_CONFIG_SET_ROUTING. These numbers are also returned by @@ -834,10 +799,8 @@ enum ni_pfi_routing { NI_PFI_OUTPUT_CDI_SAMPLE = 29, NI_PFI_OUTPUT_CDO_UPDATE = 30 }; -static inline unsigned NI_PFI_OUTPUT_RTSI(unsigned rtsi_channel) -{ - return NI_PFI_OUTPUT_RTSI0 + rtsi_channel; -} + +#define NI_PFI_OUTPUT_RTSI(x) (NI_PFI_OUTPUT_RTSI0 + (x)) /* Signals which can be routed to output on a NI PFI pin on a 660x board with INSN_CONFIG_SET_ROUTING. The numbers assigned are @@ -853,14 +816,8 @@ enum ni_660x_pfi_routing { /* NI External Trigger lines. These values are not arbitrary, but are related * to the bits required to program the board (offset by 1 for historical * reasons). */ -static inline unsigned NI_EXT_PFI(unsigned pfi_channel) -{ - return NI_USUAL_PFI_SELECT(pfi_channel) - 1; -} -static inline unsigned NI_EXT_RTSI(unsigned rtsi_channel) -{ - return NI_USUAL_RTSI_SELECT(rtsi_channel) - 1; -} +#define NI_EXT_PFI(x) (NI_USUAL_PFI_SELECT(x) - 1) +#define NI_EXT_RTSI(x) (NI_USUAL_RTSI_SELECT(x) - 1) /* status bits for INSN_CONFIG_GET_COUNTER_STATUS */ enum comedi_counter_status_flags { @@ -884,26 +841,15 @@ enum ni_m_series_cdio_scan_begin_src { NI_CDIO_SCAN_BEGIN_SRC_FREQ_OUT = 32, NI_CDIO_SCAN_BEGIN_SRC_DIO_CHANGE_DETECT_IRQ = 33 }; -static inline unsigned NI_CDIO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel) -{ - return NI_USUAL_PFI_SELECT(pfi_channel); -} -static inline unsigned NI_CDIO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel) -{ - return NI_USUAL_RTSI_SELECT(rtsi_channel); -} + +#define NI_CDIO_SCAN_BEGIN_SRC_PFI(x) NI_USUAL_PFI_SELECT(x) +#define NI_CDIO_SCAN_BEGIN_SRC_RTSI(x) NI_USUAL_RTSI_SELECT(x) /* scan_begin_src for scan_begin_arg==TRIG_EXT with analog output command on NI * boards. These scan begin sources can also be bitwise-or'd with CR_INVERT to * change polarity. */ -static inline unsigned NI_AO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel) -{ - return NI_USUAL_PFI_SELECT(pfi_channel); -} -static inline unsigned NI_AO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel) -{ - return NI_USUAL_RTSI_SELECT(rtsi_channel); -} +#define NI_AO_SCAN_BEGIN_SRC_PFI(x) NI_USUAL_PFI_SELECT(x) +#define NI_AO_SCAN_BEGIN_SRC_RTSI(x) NI_USUAL_RTSI_SELECT(x) /* Bits for setting a clock source with * INSN_CONFIG_SET_CLOCK_SRC when using NI frequency output subdevice. */ @@ -976,4 +922,15 @@ enum amplc_dio_gate_source { AMPLC_DIO_GAT_NPAT_GONE /* negated "pattern gone away" */ }; +/* + * Values for setting a clock source with INSN_CONFIG_SET_CLOCK_SRC for + * the counter subdevice on the Kolter Electronic PCI-Counter board + * (ke_counter driver). + */ +enum ke_counter_clock_source { + KE_CLK_20MHZ, /* internal 20MHz (default) */ + KE_CLK_4MHZ, /* internal 4MHz (option) */ + KE_CLK_EXT /* external clock on pin 21 of D-Sub */ +}; + #endif /* _COMEDI_H */ diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c index 1e9da405d833..9b6f96f1591c 100644 --- a/drivers/staging/comedi/comedi_compat32.c +++ b/drivers/staging/comedi/comedi_compat32.c @@ -107,10 +107,10 @@ static int compat_chaninfo(struct file *file, unsigned long arg) chaninfo = compat_alloc_user_space(sizeof(*chaninfo)); /* Copy chaninfo structure. Ignore unused members. */ - if (!access_ok(VERIFY_READ, chaninfo32, sizeof(*chaninfo32)) - || !access_ok(VERIFY_WRITE, chaninfo, sizeof(*chaninfo))) { + if (!access_ok(VERIFY_READ, chaninfo32, sizeof(*chaninfo32)) || + !access_ok(VERIFY_WRITE, chaninfo, sizeof(*chaninfo))) return -EFAULT; - } + err = 0; err |= __get_user(temp.uint, &chaninfo32->subdev); err |= __put_user(temp.uint, &chaninfo->subdev); @@ -141,10 +141,10 @@ static int compat_rangeinfo(struct file *file, unsigned long arg) rangeinfo = compat_alloc_user_space(sizeof(*rangeinfo)); /* Copy rangeinfo structure. */ - if (!access_ok(VERIFY_READ, rangeinfo32, sizeof(*rangeinfo32)) - || !access_ok(VERIFY_WRITE, rangeinfo, sizeof(*rangeinfo))) { + if (!access_ok(VERIFY_READ, rangeinfo32, sizeof(*rangeinfo32)) || + !access_ok(VERIFY_WRITE, rangeinfo, sizeof(*rangeinfo))) return -EFAULT; - } + err = 0; err |= __get_user(temp.uint, &rangeinfo32->range_type); err |= __put_user(temp.uint, &rangeinfo->range_type); @@ -168,10 +168,10 @@ static int get_compat_cmd(struct comedi_cmd __user *cmd, } temp; /* Copy cmd structure. */ - if (!access_ok(VERIFY_READ, cmd32, sizeof(*cmd32)) - || !access_ok(VERIFY_WRITE, cmd, sizeof(*cmd))) { + if (!access_ok(VERIFY_READ, cmd32, sizeof(*cmd32)) || + !access_ok(VERIFY_WRITE, cmd, sizeof(*cmd))) return -EFAULT; - } + err = 0; err |= __get_user(temp.uint, &cmd32->subdev); err |= __put_user(temp.uint, &cmd->subdev); @@ -219,10 +219,10 @@ static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32, /* Assume the pointer values are already valid. */ /* (Could use ptr_to_compat() to set them, but that wasn't implemented * until kernel version 2.6.11.) */ - if (!access_ok(VERIFY_READ, cmd, sizeof(*cmd)) - || !access_ok(VERIFY_WRITE, cmd32, sizeof(*cmd32))) { + if (!access_ok(VERIFY_READ, cmd, sizeof(*cmd)) || + !access_ok(VERIFY_WRITE, cmd32, sizeof(*cmd32))) return -EFAULT; - } + err = 0; err |= __get_user(temp, &cmd->subdev); err |= __put_user(temp, &cmd32->subdev); @@ -311,8 +311,8 @@ static int get_compat_insn(struct comedi_insn __user *insn, /* Copy insn structure. Ignore the unused members. */ err = 0; - if (!access_ok(VERIFY_READ, insn32, sizeof(*insn32)) - || !access_ok(VERIFY_WRITE, insn, sizeof(*insn))) + if (!access_ok(VERIFY_READ, insn32, sizeof(*insn32)) || + !access_ok(VERIFY_WRITE, insn, sizeof(*insn))) return -EFAULT; err |= __get_user(temp.uint, &insn32->insn); diff --git a/drivers/staging/comedi/comedi_compat32.h b/drivers/staging/comedi/comedi_compat32.h index 28e3c3059037..2d0a6fcf60f3 100644 --- a/drivers/staging/comedi/comedi_compat32.h +++ b/drivers/staging/comedi/comedi_compat32.h @@ -25,8 +25,7 @@ #ifdef CONFIG_COMPAT struct file; -extern long comedi_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg); +long comedi_compat_ioctl(struct file *, unsigned int cmd, unsigned long arg); #else /* CONFIG_COMPAT */ diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 9d99fb3c18a6..2182c7463cdb 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -16,6 +16,8 @@ GNU General Public License for more details. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "comedi_compat32.h" #include <linux/module.h> @@ -206,8 +208,8 @@ struct comedi_device *comedi_dev_get_from_minor(unsigned minor) { if (minor < COMEDI_NUM_BOARD_MINORS) return comedi_dev_get_from_board_minor(minor); - else - return comedi_dev_get_from_subdevice_minor(minor); + + return comedi_dev_get_from_subdevice_minor(minor); } EXPORT_SYMBOL_GPL(comedi_dev_get_from_minor); @@ -266,7 +268,7 @@ static int resize_async_buffer(struct comedi_device *dev, return retval; if (s->buf_change) { - retval = s->buf_change(dev, s, new_size); + retval = s->buf_change(dev, s); if (retval < 0) return retval; } @@ -968,9 +970,6 @@ static int do_bufinfo_ioctl(struct comedi_device *dev, s = &dev->subdevices[bi.subdevice]; - if (s->lock && s->lock != file) - return -EACCES; - async = s->async; if (!async) { @@ -997,7 +996,7 @@ static int do_bufinfo_ioctl(struct comedi_device *dev, comedi_buf_read_free(s, bi.bytes_read); if (comedi_is_subdevice_idle(s) && - async->buf_write_count == async->buf_read_count) { + comedi_buf_n_bytes_ready(s) == 0) { do_become_nonbusy(dev, s); } } @@ -1076,11 +1075,10 @@ static int check_insn_config_length(struct comedi_insn *insn, /* by default we allow the insn since we don't have checks for * all possible cases yet */ default: - pr_warn("comedi: No check for data length of config insn id %i is implemented.\n", + pr_warn("No check for data length of config insn id %i is implemented\n", data[0]); - pr_warn("comedi: Add a check to %s in %s.\n", - __func__, __FILE__); - pr_warn("comedi: Assuming n=%i is correct.\n", insn->n); + pr_warn("Add a check to %s in %s\n", __func__, __FILE__); + pr_warn("Assuming n=%i is correct\n", insn->n); return 0; } return -EINVAL; @@ -1229,10 +1227,9 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, /* Most drivers ignore the base channel in * insn->chanspec. Fix this here if * the subdevice has <= 32 channels. */ - unsigned int shift; - unsigned int orig_mask; + unsigned int orig_mask = data[0]; + unsigned int shift = 0; - orig_mask = data[0]; if (s->n_chan <= 32) { shift = CR_CHAN(insn->chanspec); if (shift > 0) { @@ -1240,8 +1237,7 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, data[0] <<= shift; data[1] <<= shift; } - } else - shift = 0; + } ret = s->insn_bits(dev, s, insn, data); data[0] = orig_mask; if (shift > 0) @@ -1295,7 +1291,7 @@ static int do_insnlist_ioctl(struct comedi_device *dev, if (copy_from_user(&insnlist, arg, sizeof(insnlist))) return -EFAULT; - data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL); + data = kmalloc_array(MAX_SAMPLES, sizeof(unsigned int), GFP_KERNEL); if (!data) { ret = -ENOMEM; goto error; @@ -1376,7 +1372,7 @@ static int do_insn_ioctl(struct comedi_device *dev, unsigned int *data = NULL; int ret = 0; - data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL); + data = kmalloc_array(MAX_SAMPLES, sizeof(unsigned int), GFP_KERNEL); if (!data) { ret = -ENOMEM; goto error; @@ -1664,14 +1660,6 @@ static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg, s->lock = file; spin_unlock_irqrestore(&s->spin_lock, flags); -#if 0 - if (ret < 0) - return ret; - - if (s->lock_f) - ret = s->lock_f(dev, s); -#endif - return ret; } @@ -1706,14 +1694,8 @@ static int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg, if (s->lock && s->lock != file) return -EACCES; - if (s->lock == file) { -#if 0 - if (s->unlock) - s->unlock(dev, s); -#endif - + if (s->lock == file) s->lock = NULL; - } return 0; } @@ -1744,9 +1726,6 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg, if (s->async == NULL) return -EINVAL; - if (s->lock && s->lock != file) - return -EACCES; - if (!s->busy) return 0; @@ -1781,9 +1760,6 @@ static int do_poll_ioctl(struct comedi_device *dev, unsigned int arg, return -EINVAL; s = &dev->subdevices[arg]; - if (s->lock && s->lock != file) - return -EACCES; - if (!s->busy) return 0; @@ -2186,7 +2162,7 @@ out: } static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, - loff_t *offset) + loff_t *offset) { struct comedi_subdevice *s; struct comedi_async *async; @@ -2230,10 +2206,8 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, n = nbytes; m = comedi_buf_read_n_available(s); - /* printk("%d available\n",m); */ if (async->buf_read_ptr + m > async->prealloc_bufsz) m = async->prealloc_bufsz - async->buf_read_ptr; - /* printk("%d contiguous\n",m); */ if (m < n) n = m; @@ -2303,8 +2277,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, new_s = comedi_read_subdevice(dev, minor); if (dev->attached && old_detach_count == dev->detach_count && s == new_s && new_s->async == async) { - if (become_nonbusy || - async->buf_read_count - async->buf_write_count == 0) + if (become_nonbusy || comedi_buf_n_bytes_ready(s) == 0) do_become_nonbusy(dev, s); } mutex_unlock(&dev->mutex); @@ -2411,12 +2384,6 @@ static const struct file_operations comedi_fops = { .llseek = noop_llseek, }; -void comedi_error(const struct comedi_device *dev, const char *s) -{ - dev_err(dev->class_dev, "%s: %s\n", dev->driver->driver_name, s); -} -EXPORT_SYMBOL_GPL(comedi_error); - void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s) { struct comedi_async *async = s->async; @@ -2460,7 +2427,7 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device) struct device *csdev; unsigned i; - dev = kzalloc(sizeof(struct comedi_device), GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) return ERR_PTR(-ENOMEM); comedi_device_init(dev); @@ -2479,7 +2446,7 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device) mutex_unlock(&dev->mutex); comedi_device_cleanup(dev); comedi_dev_put(dev); - pr_err("comedi: error: ran out of minor numbers for board device files.\n"); + pr_err("ran out of minor numbers for board device files\n"); return ERR_PTR(-EBUSY); } dev->minor = i; @@ -2532,7 +2499,7 @@ int comedi_alloc_subdevice_minor(struct comedi_subdevice *s) } mutex_unlock(&comedi_subdevice_minor_table_lock); if (i == COMEDI_NUM_SUBDEVICE_MINORS) { - pr_err("comedi: error: ran out of minor numbers for subdevice files.\n"); + pr_err("ran out of minor numbers for subdevice files\n"); return -EBUSY; } i += COMEDI_NUM_BOARD_MINORS; @@ -2582,11 +2549,11 @@ static int __init comedi_init(void) int i; int retval; - pr_info("comedi: version " COMEDI_RELEASE " - http://www.comedi.org\n"); + pr_info("version " COMEDI_RELEASE " - http://www.comedi.org\n"); if (comedi_num_legacy_minors < 0 || comedi_num_legacy_minors > COMEDI_NUM_BOARD_MINORS) { - pr_err("comedi: error: invalid value for module parameter \"comedi_num_legacy_minors\". Valid values are 0 through %i.\n", + pr_err("invalid value for module parameter \"comedi_num_legacy_minors\". Valid values are 0 through %i.\n", COMEDI_NUM_BOARD_MINORS); return -EINVAL; } @@ -2597,7 +2564,14 @@ static int __init comedi_init(void) return -EIO; cdev_init(&comedi_cdev, &comedi_fops); comedi_cdev.owner = THIS_MODULE; - kobject_set_name(&comedi_cdev.kobj, "comedi"); + + retval = kobject_set_name(&comedi_cdev.kobj, "comedi"); + if (retval) { + unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), + COMEDI_NUM_MINORS); + return retval; + } + if (cdev_add(&comedi_cdev, MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS)) { unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS); @@ -2605,7 +2579,7 @@ static int __init comedi_init(void) } comedi_class = class_create(THIS_MODULE, "comedi"); if (IS_ERR(comedi_class)) { - pr_err("comedi: failed to create class\n"); + pr_err("failed to create class\n"); cdev_del(&comedi_cdev); unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS); @@ -2628,10 +2602,9 @@ static int __init comedi_init(void) unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS); return PTR_ERR(dev); - } else { - /* comedi_alloc_board_minor() locked the mutex */ - mutex_unlock(&dev->mutex); } + /* comedi_alloc_board_minor() locked the mutex */ + mutex_unlock(&dev->mutex); } return 0; diff --git a/drivers/staging/comedi/comedi_internal.h b/drivers/staging/comedi/comedi_internal.h index e978c223f5b5..d57817c19aea 100644 --- a/drivers/staging/comedi/comedi_internal.h +++ b/drivers/staging/comedi/comedi_internal.h @@ -48,6 +48,7 @@ void comedi_proc_cleanup(void); static inline void comedi_proc_init(void) { } + static inline void comedi_proc_cleanup(void) { } diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 8f4e44bfbe00..58e58a32e93d 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -75,13 +75,9 @@ struct comedi_subdevice { struct comedi_cmd *); int (*poll)(struct comedi_device *, struct comedi_subdevice *); int (*cancel)(struct comedi_device *, struct comedi_subdevice *); - /* int (*do_lock)(struct comedi_device *, struct comedi_subdevice *); */ - /* int (*do_unlock)(struct comedi_device *, \ - struct comedi_subdevice *); */ /* called when the buffer changes */ - int (*buf_change)(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned long new_size); + int (*buf_change)(struct comedi_device *, struct comedi_subdevice *); void (*munge)(struct comedi_device *dev, struct comedi_subdevice *s, void *data, unsigned int num_bytes, @@ -107,43 +103,110 @@ struct comedi_buf_map { struct kref refcount; }; +/** + * 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) + * @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: + * + * 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: + * + * [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 + * + * Data needs to be written into the buffer before it can be read out, + * and may need to be converted (or "munged") between the two + * operations. Extra unfilled buffer space may need to allocated for + * writing (advancing Buf_Write_Alloc_Count) before new data is written. + * After writing new data, the newly filled space needs to be released + * (advancing Buf_Write_Count). This also results in the new data being + * "munged" (advancing Munge_Count). Before data is read out of the + * buffer, extra space may need to be allocated for reading (advancing + * Buf_Read_Alloc_Count). After the data has been read out, the space + * needs to be released (advancing Buf_Read_Count). + * + * The actual members, buf_read_count, buf_read_alloc_count, + * munge_count, buf_write_count, and buf_write_alloc_count take the + * value of the corresponding capitalized _Count values modulo 2^32 + * (UINT_MAX+1). Subtracting a "higher" _count value from a "lower" + * _count value gives the same answer as subtracting a "higher" _Count + * value from a lower _Count value because prealloc_bufsz < UINT_MAX+1. + * The modulo operation is done implicitly. + * + * The buf_read_ptr, munge_ptr, and buf_write_ptr members take the value + * of the corresponding capitalized _Count values modulo prealloc_bufsz. + * These correspond to byte indices in the physical buffer. The modulo + * operation is done by subtracting prealloc_bufsz when the value + * exceeds prealloc_bufsz (assuming prealloc_bufsz plus the increment is + * less than or equal to UINT_MAX). + */ struct comedi_async { - void *prealloc_buf; /* pre-allocated buffer */ - unsigned int prealloc_bufsz; /* buffer size, in bytes */ - struct comedi_buf_map *buf_map; /* map of buffer pages */ - - unsigned int max_bufsize; /* maximum buffer size, bytes */ - - /* byte count for writer (write completed) */ + void *prealloc_buf; + unsigned int prealloc_bufsz; + struct comedi_buf_map *buf_map; + unsigned int max_bufsize; unsigned int buf_write_count; - /* byte count for writer (allocated for writing) */ unsigned int buf_write_alloc_count; - /* byte count for reader (read completed) */ unsigned int buf_read_count; - /* byte count for reader (allocated for reading) */ unsigned int buf_read_alloc_count; - - unsigned int buf_write_ptr; /* buffer marker for writer */ - unsigned int buf_read_ptr; /* buffer marker for reader */ - - unsigned int cur_chan; /* useless channel marker for interrupt */ - /* number of bytes that have been received for current scan */ + unsigned int buf_write_ptr; + unsigned int buf_read_ptr; + unsigned int cur_chan; unsigned int scan_progress; - /* keeps track of where we are in chanlist as for munging */ unsigned int munge_chan; - /* number of bytes that have been munged */ unsigned int munge_count; - /* buffer marker for munging */ unsigned int munge_ptr; - - unsigned int events; /* events that have occurred */ - + unsigned int events; struct comedi_cmd cmd; - wait_queue_head_t wait_head; - unsigned int cb_mask; - int (*inttrig)(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int x); }; @@ -190,6 +253,7 @@ struct comedi_device { struct comedi_subdevice *subdevices; /* dumb */ + void __iomem *mmio; unsigned long iobase; unsigned long iolen; unsigned int irq; @@ -213,7 +277,6 @@ static inline const void *comedi_board(const struct comedi_device *dev) */ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s); -void comedi_error(const struct comedi_device *dev, const char *s); /* we can expand the number of bits used to encode devices/subdevices into the minor number soon, after more distros support > 8 bit minor numbers @@ -222,6 +285,7 @@ enum comedi_minor_bits { COMEDI_DEVICE_MINOR_MASK = 0xf, COMEDI_SUBDEVICE_MINOR_MASK = 0xf0 }; + static const unsigned COMEDI_SUBDEVICE_MINOR_SHIFT = 4; static const unsigned COMEDI_SUBDEVICE_MINOR_OFFSET = 1; @@ -296,6 +360,12 @@ static inline bool comedi_range_is_unipolar(struct comedi_subdevice *s, return s->range_table->range[range].min >= 0; } +static inline bool comedi_range_is_external(struct comedi_subdevice *s, + unsigned int range) +{ + return !!(s->range_table->range[range].flags & RF_EXTERNAL); +} + static inline bool comedi_chan_range_is_bipolar(struct comedi_subdevice *s, unsigned int chan, unsigned int range) @@ -310,6 +380,13 @@ static inline bool comedi_chan_range_is_unipolar(struct comedi_subdevice *s, return s->range_table_list[chan]->range[range].min >= 0; } +static inline bool comedi_chan_range_is_external(struct comedi_subdevice *s, + unsigned int chan, + unsigned int range) +{ + return !!(s->range_table_list[chan]->range[range].flags & RF_EXTERNAL); +} + /* munge between offset binary and two's complement values */ static inline unsigned int comedi_offset_munge(struct comedi_subdevice *s, unsigned int val) @@ -321,8 +398,8 @@ static inline unsigned int bytes_per_sample(const struct comedi_subdevice *subd) { if (subd->subdev_flags & SDF_LSAMPL) return sizeof(unsigned int); - else - return sizeof(short); + + return sizeof(short); } /* @@ -333,6 +410,11 @@ static inline unsigned int bytes_per_sample(const struct comedi_subdevice *subd) */ int comedi_set_hw_dev(struct comedi_device *dev, struct device *hw_dev); +static inline unsigned int comedi_buf_n_bytes_ready(struct comedi_subdevice *s) +{ + return s->async->buf_write_count - s->async->buf_read_count; +} + unsigned int comedi_buf_write_alloc(struct comedi_subdevice *s, unsigned int n); unsigned int comedi_buf_write_free(struct comedi_subdevice *s, unsigned int n); @@ -484,9 +566,9 @@ int comedi_pcmcia_auto_config(struct pcmcia_device *, struct comedi_driver *); void comedi_pcmcia_auto_unconfig(struct pcmcia_device *); int comedi_pcmcia_driver_register(struct comedi_driver *, - struct pcmcia_driver *); + struct pcmcia_driver *); void comedi_pcmcia_driver_unregister(struct comedi_driver *, - struct pcmcia_driver *); + struct pcmcia_driver *); /** * module_comedi_pcmcia_driver() - Helper macro for registering a comedi PCMCIA driver diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 299726f39e26..9ada130f2a76 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -38,6 +38,7 @@ #include "comedi_internal.h" struct comedi_driver *comedi_drivers; +/* protects access to comedi_drivers */ DEFINE_MUTEX(comedi_drivers_list_lock); int comedi_set_hw_dev(struct comedi_device *dev, struct device *hw_dev) @@ -120,6 +121,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev) dev->driver = NULL; dev->board_name = NULL; dev->board_ptr = NULL; + dev->mmio = NULL; dev->iobase = 0; dev->iolen = 0; dev->ioenabled = false; @@ -319,7 +321,7 @@ static int __comedi_device_postconfig_async(struct comedi_device *dev, return -ENOMEM; } if (s->buf_change) { - ret = s->buf_change(dev, s, buf_size); + ret = s->buf_change(dev, s); if (ret < 0) return ret; } @@ -566,8 +568,9 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_ptr = comedi_recognize(driv, it->board_name); if (dev->board_ptr) break; - } else if (strcmp(driv->driver_name, it->board_name) == 0) + } else if (strcmp(driv->driver_name, it->board_name) == 0) { break; + } module_put(driv->module); } if (driv == NULL) { @@ -591,8 +594,6 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) ret = -ENOSYS; goto out; } - /* initialize dev->driver here so - * comedi_error() can be called from attach */ dev->driver = driv; dev->board_name = dev->board_ptr ? *(const char **)dev->board_ptr : dev->driver->driver_name; diff --git a/drivers/staging/comedi/drivers/8253.h b/drivers/staging/comedi/drivers/8253.h index 5829b46b757b..f8e1ebad304d 100644 --- a/drivers/staging/comedi/drivers/8253.h +++ b/drivers/staging/comedi/drivers/8253.h @@ -34,7 +34,7 @@ static inline void i8253_cascade_ns_to_timer(int i8253_osc_base, unsigned int *d1, unsigned int *d2, unsigned int *nanosec, - int round_mode) + unsigned int flags) { unsigned int divider; unsigned int div1, div2; @@ -90,8 +90,7 @@ static inline void i8253_cascade_ns_to_timer(int i8253_osc_base, } } - round_mode &= TRIG_ROUND_MASK; - switch (round_mode) { + switch (flags & TRIG_ROUND_MASK) { case TRIG_ROUND_NEAREST: default: ns_high = div1_lub * div2_lub * i8253_osc_base; @@ -118,7 +117,6 @@ static inline void i8253_cascade_ns_to_timer(int i8253_osc_base, /* masking is done since counter maps zero to 0x10000 */ *d1 = div1 & 0xffff; *d2 = div2 & 0xffff; - return; } #ifndef CMDTEST diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 46113a374133..a33a19622745 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -102,9 +102,8 @@ static int subdev_8255_io(int dir, int port, int data, unsigned long iobase) if (dir) { outb(data, iobase + port); return 0; - } else { - return inb(iobase + port); } + return inb(iobase + port); } void subdev_8255_interrupt(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c index 46a385c29ba8..f21e6567ac2f 100644 --- a/drivers/staging/comedi/drivers/8255_pci.c +++ b/drivers/staging/comedi/drivers/8255_pci.c @@ -56,7 +56,6 @@ Configuration Options: not applicable, uses PCI auto config #include "../comedidev.h" #include "8255.h" -#include "mite.h" enum pci_8255_boardid { BOARD_ADLINK_PCI7224, @@ -168,9 +167,9 @@ static const struct pci_8255_boardinfo pci_8255_boards[] = { }, }; -struct pci_8255_private { - void __iomem *mmio_base; -}; +/* ripped from mite.h and mite_setup2() to avoid mite dependancy */ +#define MITE_IODWBSR 0xc0 /* IO Device Window Base Size Register */ +#define WENAB (1 << 7) /* window enable */ static int pci_8255_mite_init(struct pci_dev *pcidev) { @@ -198,9 +197,8 @@ static int pci_8255_mmio(int dir, int port, int data, unsigned long iobase) if (dir) { writeb(data, mmio_base + port); return 0; - } else { - return readb(mmio_base + port); } + return readb(mmio_base + port); } static int pci_8255_auto_attach(struct comedi_device *dev, @@ -208,7 +206,6 @@ static int pci_8255_auto_attach(struct comedi_device *dev, { struct pci_dev *pcidev = comedi_to_pci_dev(dev); const struct pci_8255_boardinfo *board = NULL; - struct pci_8255_private *devpriv; struct comedi_subdevice *s; bool is_mmio; int ret; @@ -221,10 +218,6 @@ static int pci_8255_auto_attach(struct comedi_device *dev, dev->board_ptr = board; dev->board_name = board->name; - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) - return -ENOMEM; - ret = comedi_pci_enable(dev); if (ret) return ret; @@ -238,8 +231,8 @@ static int pci_8255_auto_attach(struct comedi_device *dev, is_mmio = (pci_resource_flags(pcidev, board->dio_badr) & IORESOURCE_MEM) != 0; if (is_mmio) { - devpriv->mmio_base = pci_ioremap_bar(pcidev, board->dio_badr); - if (!devpriv->mmio_base) + dev->mmio = pci_ioremap_bar(pcidev, board->dio_badr); + if (!dev->mmio) return -ENOMEM; } else { dev->iobase = pci_resource_start(pcidev, board->dio_badr); @@ -259,7 +252,7 @@ static int pci_8255_auto_attach(struct comedi_device *dev, s = &dev->subdevices[i]; if (is_mmio) { - iobase = (unsigned long)(devpriv->mmio_base + (i * 4)); + iobase = (unsigned long)(dev->mmio + (i * 4)); ret = subdev_8255_init(dev, s, pci_8255_mmio, iobase); } else { iobase = dev->iobase + (i * 4); @@ -274,10 +267,8 @@ static int pci_8255_auto_attach(struct comedi_device *dev, static void pci_8255_detach(struct comedi_device *dev) { - struct pci_8255_private *devpriv = dev->private; - - if (devpriv && devpriv->mmio_base) - iounmap(devpriv->mmio_base); + if (dev->mmio) + iounmap(dev->mmio); comedi_pci_disable(dev); } diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile index 0757a82ddcfa..8873d4807a01 100644 --- a/drivers/staging/comedi/drivers/Makefile +++ b/drivers/staging/comedi/drivers/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_COMEDI_SKEL) += skel.o # Comedi ISA drivers obj-$(CONFIG_COMEDI_AMPLC_DIO200_ISA) += amplc_dio200.o +obj-$(CONFIG_COMEDI_AMPLC_PC236_ISA) += amplc_pc236.o obj-$(CONFIG_COMEDI_AMPLC_PC263_ISA) += amplc_pc263.o obj-$(CONFIG_COMEDI_PCL711) += pcl711.o obj-$(CONFIG_COMEDI_PCL724) += pcl724.o @@ -80,7 +81,7 @@ obj-$(CONFIG_COMEDI_ADV_PCI1723) += adv_pci1723.o obj-$(CONFIG_COMEDI_ADV_PCI1724) += adv_pci1724.o obj-$(CONFIG_COMEDI_ADV_PCI_DIO) += adv_pci_dio.o obj-$(CONFIG_COMEDI_AMPLC_DIO200_PCI) += amplc_dio200_pci.o -obj-$(CONFIG_COMEDI_AMPLC_PC236) += amplc_pc236.o +obj-$(CONFIG_COMEDI_AMPLC_PC236_PCI) += amplc_pci236.o obj-$(CONFIG_COMEDI_AMPLC_PC263_PCI) += amplc_pci263.o obj-$(CONFIG_COMEDI_AMPLC_PCI224) += amplc_pci224.o obj-$(CONFIG_COMEDI_AMPLC_PCI230) += amplc_pci230.o @@ -138,5 +139,6 @@ obj-$(CONFIG_COMEDI_NI_LABPC_ISADMA) += ni_labpc_isadma.o obj-$(CONFIG_COMEDI_8255) += 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 obj-$(CONFIG_COMEDI_FC) += comedi_fc.o diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c index dc87df032203..de5843ab01ae 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_common.c +++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c @@ -157,14 +157,10 @@ static int addi_auto_attach(struct comedi_device *dev, s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; - if (devpriv->s_EeParameters.i_NbrAiChannel) { - s->n_chan = - devpriv->s_EeParameters.i_NbrAiChannel; - devpriv->b_SingelDiff = 0; - } else { + if (devpriv->s_EeParameters.i_NbrAiChannel) + s->n_chan = devpriv->s_EeParameters.i_NbrAiChannel; + else s->n_chan = this_board->i_NbrAiChannelDiff; - devpriv->b_SingelDiff = 1; - } s->maxdata = devpriv->s_EeParameters.i_AiMaxdata; s->len_chanlist = this_board->i_AiChannelList; s->range_table = this_board->pr_AiRangelist; diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h index 5c6a11c35ded..a7400a25f620 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_common.h +++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h @@ -18,25 +18,6 @@ #include <linux/sched.h> #include <linux/interrupt.h> -#define LOWORD(W) (unsigned short)((W) & 0xFFFF) -#define HIWORD(W) (unsigned short)(((W) >> 16) & 0xFFFF) - -#define ADDI_ENABLE 1 -#define ADDI_DISABLE 0 -#define APCI1710_SAVE_INTERRUPT 1 - -#define ADDIDATA_EEPROM 1 -#define ADDIDATA_NO_EEPROM 0 -#define ADDIDATA_93C76 "93C76" -#define ADDIDATA_S5920 "S5920" - -/* ADDIDATA Enable Disable */ -#define ADDIDATA_ENABLE 1 -#define ADDIDATA_DISABLE 0 - -/* Structures */ - -/* structure for the boardtype */ struct addi_board { const char *pc_DriverName; /* driver name */ int i_IorangeBase1; @@ -141,7 +122,6 @@ struct addi_private { unsigned char b_InterruptMode; /* eoc eos or dma */ unsigned char b_EocEosInterrupt; /* Enable disable eoc eos interrupt */ unsigned int ui_EocEosConversionTime; - unsigned char b_SingelDiff; unsigned char b_ExttrigEnable; /* To enable or disable external trigger */ /* Pointer to the current process */ diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c index 28450f65a134..cad33f1a04fe 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c @@ -177,8 +177,7 @@ static int apci035_timer_config(struct comedi_device *dev, /* Disable the hardware trigger */ ui_Command = ui_Command & 0xFFFFF89FUL; - if (data[4] == ADDIDATA_ENABLE) { - + if (data[4] == 1) { /* Set the hardware trigger level */ ui_Command = ui_Command | (data[5] << 5); } @@ -188,8 +187,7 @@ static int apci035_timer_config(struct comedi_device *dev, /* Disable the hardware gate */ ui_Command = ui_Command & 0xFFFFF87FUL; - if (data[6] == ADDIDATA_ENABLE) { - + if (data[6] == 1) { /* Set the hardware gate level */ ui_Command = ui_Command | (data[7] << 7); } @@ -203,8 +201,7 @@ static int apci035_timer_config(struct comedi_device *dev, /* Set the hardware output level */ ui_Command = ui_Command | (data[8] << 2); outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); - if (data[9] == ADDIDATA_ENABLE) { - + if (data[9] == 1) { /* Set the reload value */ outl(data[11], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 24); diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index a633957890d7..1e2fe66818e4 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -872,7 +872,8 @@ static int apci1500_do_write(struct comedi_device *dev, break; default: - comedi_error(dev, " chan spec wrong"); + dev_err(dev->class_dev, + "chan spec wrong\n"); return -EINVAL; /* "sorry channel spec wrong " */ } /* switch(ui_NoOfChannels) */ @@ -950,8 +951,8 @@ static int apci1500_do_write(struct comedi_device *dev, break; default: - comedi_error(dev, - " chan spec wrong"); + dev_err(dev->class_dev, + "chan spec wrong\n"); return -EINVAL; /* "sorry channel spec wrong " */ } /* switch(ui_NoOfChannels) */ diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c index 0ba5385226ae..8a613ae0acba 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c @@ -21,17 +21,15 @@ * */ -#include "../addi_watchdog.h" - #define APCI1564_ADDRESS_RANGE 128 /* Digital Input IRQ Function Selection */ -#define ADDIDATA_OR 0 -#define ADDIDATA_AND 1 +#define APCI1564_DI_INT_OR (0 << 1) +#define APCI1564_DI_INT_AND (1 << 1) /* Digital Input Interrupt Enable Disable. */ -#define APCI1564_DIGITAL_IP_INTERRUPT_ENABLE 0x4 -#define APCI1564_DIGITAL_IP_INTERRUPT_DISABLE 0xfffffffb +#define APCI1564_DI_INT_ENABLE 0x4 +#define APCI1564_DI_INT_DISABLE 0xfffffffb /* Digital Output Interrupt Enable Disable. */ #define APCI1564_DIGITAL_OP_VCC_INTERRUPT_ENABLE 0x1 @@ -49,7 +47,7 @@ #define APCI1564_COUNTER4 3 /* - * devpriv->i_IobaseAmcc Register Map + * devpriv->amcc_iobase Register Map */ #define APCI1564_DI_REG 0x04 #define APCI1564_DI_INT_MODE1_REG 0x08 @@ -89,46 +87,6 @@ #define APCI1564_TCW_WARN_TIMEVAL_REG(x) (0x18 + ((x) * 0x20)) #define APCI1564_TCW_WARN_TIMEBASE_REG(x) (0x1c + ((x) * 0x20)) -/* Global variables */ -static unsigned int ui_InterruptStatus_1564; -static unsigned int ui_InterruptData, ui_Type; - -/* - * Configures the digital input Subdevice - * - * data[0] 1 = Enable interrupt, 0 = Disable interrupt - * data[1] 0 = ADDIDATA Interrupt OR LOGIC, 1 = ADDIDATA Interrupt AND LOGIC - * data[2] Interrupt mask for the mode 1 - * data[3] Interrupt mask for the mode 2 - */ -static int apci1564_di_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - - devpriv->tsk_Current = current; - - /* Set the digital input logic */ - if (data[0] == ADDIDATA_ENABLE) { - data[2] = data[2] << 4; - data[3] = data[3] << 4; - outl(data[2], devpriv->i_IobaseAmcc + APCI1564_DI_INT_MODE1_REG); - outl(data[3], devpriv->i_IobaseAmcc + APCI1564_DI_INT_MODE2_REG); - if (data[1] == ADDIDATA_OR) - outl(0x4, devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG); - else - outl(0x6, devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG); - } else { - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_INT_MODE1_REG); - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_INT_MODE2_REG); - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG); - } - - return insn->n; -} - /* * Configures The Digital Output Subdevice. * @@ -140,33 +98,26 @@ static int apci1564_do_config(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct addi_private *devpriv = dev->private; + struct apci1564_private *devpriv = dev->private; unsigned int ul_Command = 0; if ((data[0] != 0) && (data[0] != 1)) { - comedi_error(dev, - "Not a valid Data !!! ,Data should be 1 or 0\n"); + dev_err(dev->class_dev, "Data should be 1 or 0\n"); return -EINVAL; } - if (data[0]) - devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE; - else - devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE; - - if (data[1] == ADDIDATA_ENABLE) + if (data[1] == 1) ul_Command = ul_Command | 0x1; else ul_Command = ul_Command & 0xFFFFFFFE; - if (data[2] == ADDIDATA_ENABLE) + if (data[2] == 1) ul_Command = ul_Command | 0x2; else ul_Command = ul_Command & 0xFFFFFFFD; - outl(ul_Command, devpriv->i_IobaseAmcc + APCI1564_DO_INT_CTRL_REG); - ui_InterruptData = inl(devpriv->i_IobaseAmcc + APCI1564_DO_INT_CTRL_REG); - devpriv->tsk_Current = current; + outl(ul_Command, devpriv->amcc_iobase + APCI1564_DO_INT_CTRL_REG); + devpriv->tsk_current = current; return insn->n; } @@ -186,31 +137,31 @@ static int apci1564_timer_config(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct addi_private *devpriv = dev->private; + struct apci1564_private *devpriv = dev->private; unsigned int ul_Command1 = 0; - devpriv->tsk_Current = current; + devpriv->tsk_current = current; if (data[0] == ADDIDATA_WATCHDOG) { - devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG; + devpriv->timer_select_mode = ADDIDATA_WATCHDOG; /* Disable the watchdog */ - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_WDOG_CTRL_REG); + outl(0x0, devpriv->amcc_iobase + APCI1564_WDOG_CTRL_REG); /* Loading the Reload value */ - outl(data[3], devpriv->i_IobaseAmcc + APCI1564_WDOG_RELOAD_REG); + outl(data[3], devpriv->amcc_iobase + APCI1564_WDOG_RELOAD_REG); } else if (data[0] == ADDIDATA_TIMER) { /* First Stop The Timer */ - ul_Command1 = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG); + ul_Command1 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; /* Stop The Timer */ - outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG); + outl(ul_Command1, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); - devpriv->b_TimerSelectMode = ADDIDATA_TIMER; + devpriv->timer_select_mode = ADDIDATA_TIMER; if (data[1] == 1) { /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */ - outl(0x02, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG); - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG); - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DO_IRQ_REG); - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_WDOG_IRQ_REG); + outl(0x02, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); + outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG); + outl(0x0, devpriv->amcc_iobase + APCI1564_DO_IRQ_REG); + outl(0x0, devpriv->amcc_iobase + APCI1564_WDOG_IRQ_REG); outl(0x0, dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER1)); outl(0x0, @@ -221,22 +172,22 @@ static int apci1564_timer_config(struct comedi_device *dev, dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER4)); } else { /* disable Timer interrupt */ - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG); + outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); } /* Loading Timebase */ - outl(data[2], devpriv->i_IobaseAmcc + APCI1564_TIMER_TIMEBASE_REG); + outl(data[2], devpriv->amcc_iobase + APCI1564_TIMER_TIMEBASE_REG); /* Loading the Reload value */ - outl(data[3], devpriv->i_IobaseAmcc + APCI1564_TIMER_RELOAD_REG); + outl(data[3], devpriv->amcc_iobase + APCI1564_TIMER_RELOAD_REG); - ul_Command1 = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG); + ul_Command1 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); ul_Command1 = (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL; /* mode 2 */ - outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG); + outl(ul_Command1, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); } else if (data[0] == ADDIDATA_COUNTER) { - devpriv->b_TimerSelectMode = ADDIDATA_COUNTER; - devpriv->b_ModeSelectRegister = data[5]; + devpriv->timer_select_mode = ADDIDATA_COUNTER; + devpriv->mode_select_register = data[5]; /* First Stop The Counter */ ul_Command1 = inl(dev->iobase + APCI1564_TCW_CTRL_REG(data[5] - 1)); @@ -285,45 +236,45 @@ static int apci1564_timer_write(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct addi_private *devpriv = dev->private; + struct apci1564_private *devpriv = dev->private; unsigned int ul_Command1 = 0; - if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { + if (devpriv->timer_select_mode == ADDIDATA_WATCHDOG) { switch (data[1]) { case 0: /* stop the watchdog */ /* disable the watchdog */ - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_WDOG_CTRL_REG); + outl(0x0, devpriv->amcc_iobase + APCI1564_WDOG_CTRL_REG); break; case 1: /* start the watchdog */ - outl(0x0001, devpriv->i_IobaseAmcc + APCI1564_WDOG_CTRL_REG); + outl(0x0001, devpriv->amcc_iobase + APCI1564_WDOG_CTRL_REG); break; case 2: /* Software trigger */ - outl(0x0201, devpriv->i_IobaseAmcc + APCI1564_WDOG_CTRL_REG); + outl(0x0201, devpriv->amcc_iobase + APCI1564_WDOG_CTRL_REG); break; default: dev_err(dev->class_dev, "Specified functionality does not exist.\n"); return -EINVAL; } } - if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) { + if (devpriv->timer_select_mode == ADDIDATA_TIMER) { if (data[1] == 1) { - ul_Command1 = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG); + ul_Command1 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL; /* Enable the Timer */ - outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG); + outl(ul_Command1, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); } else if (data[1] == 0) { /* Stop The Timer */ - ul_Command1 = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG); + ul_Command1 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; - outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG); + outl(ul_Command1, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); } } - if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) { + if (devpriv->timer_select_mode == ADDIDATA_COUNTER) { ul_Command1 = inl(dev->iobase + - APCI1564_TCW_CTRL_REG(devpriv->b_ModeSelectRegister - 1)); + APCI1564_TCW_CTRL_REG(devpriv->mode_select_register - 1)); if (data[1] == 1) { /* Start the Counter subdevice */ ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL; @@ -336,7 +287,7 @@ static int apci1564_timer_write(struct comedi_device *dev, ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x400; } outl(ul_Command1, dev->iobase + - APCI1564_TCW_CTRL_REG(devpriv->b_ModeSelectRegister - 1)); + APCI1564_TCW_CTRL_REG(devpriv->mode_select_register - 1)); } return insn->n; } @@ -349,27 +300,27 @@ static int apci1564_timer_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct addi_private *devpriv = dev->private; + struct apci1564_private *devpriv = dev->private; unsigned int ul_Command1 = 0; - if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { + if (devpriv->timer_select_mode == ADDIDATA_WATCHDOG) { /* Stores the status of the Watchdog */ - data[0] = inl(devpriv->i_IobaseAmcc + APCI1564_WDOG_STATUS_REG) & 0x1; - data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_WDOG_REG); - } else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) { + data[0] = inl(devpriv->amcc_iobase + APCI1564_WDOG_STATUS_REG) & 0x1; + data[1] = inl(devpriv->amcc_iobase + APCI1564_WDOG_REG); + } else if (devpriv->timer_select_mode == ADDIDATA_TIMER) { /* Stores the status of the Timer */ - data[0] = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER_STATUS_REG) & 0x1; + data[0] = inl(devpriv->amcc_iobase + APCI1564_TIMER_STATUS_REG) & 0x1; /* Stores the Actual value of the Timer */ - data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER_REG); - } else if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) { + data[1] = inl(devpriv->amcc_iobase + APCI1564_TIMER_REG); + } else if (devpriv->timer_select_mode == ADDIDATA_COUNTER) { /* Read the Counter Actual Value. */ data[0] = inl(dev->iobase + - APCI1564_TCW_REG(devpriv->b_ModeSelectRegister - 1)); + APCI1564_TCW_REG(devpriv->mode_select_register - 1)); ul_Command1 = inl(dev->iobase + - APCI1564_TCW_STATUS_REG(devpriv->b_ModeSelectRegister - 1)); + APCI1564_TCW_STATUS_REG(devpriv->mode_select_register - 1)); /* Get the software trigger status */ data[1] = (unsigned char) ((ul_Command1 >> 1) & 1); @@ -382,170 +333,10 @@ static int apci1564_timer_read(struct comedi_device *dev, /* Get the overflow status */ data[4] = (unsigned char) ((ul_Command1 >> 0) & 1); - } else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER) - && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG) - && (devpriv->b_TimerSelectMode != ADDIDATA_COUNTER)) { + } else if ((devpriv->timer_select_mode != ADDIDATA_TIMER) + && (devpriv->timer_select_mode != ADDIDATA_WATCHDOG) + && (devpriv->timer_select_mode != ADDIDATA_COUNTER)) { dev_err(dev->class_dev, "Invalid Subdevice!\n"); } return insn->n; } - -/* - * Reads the interrupt status register - */ -static int apci1564_do_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - *data = ui_Type; - return insn->n; -} - -/* - * Interrupt handler for the interruptible digital inputs - */ -static void apci1564_interrupt(int irq, void *d) -{ - struct comedi_device *dev = d; - struct addi_private *devpriv = dev->private; - unsigned int ui_DO, ui_DI; - unsigned int ui_Timer; - unsigned int ui_C1, ui_C2, ui_C3, ui_C4; - unsigned int ul_Command2 = 0; - - ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG) & 0x01; - ui_DO = inl(devpriv->i_IobaseAmcc + APCI1564_DO_IRQ_REG) & 0x01; - ui_Timer = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER_IRQ_REG) & 0x01; - ui_C1 = - inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER1)) & 0x1; - ui_C2 = - inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER2)) & 0x1; - ui_C3 = - inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER3)) & 0x1; - ui_C4 = - inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER4)) & 0x1; - if (ui_DI == 0 && ui_DO == 0 && ui_Timer == 0 && ui_C1 == 0 - && ui_C2 == 0 && ui_C3 == 0 && ui_C4 == 0) { - dev_err(dev->class_dev, "Interrupt from unknown source.\n"); - } - - if (ui_DI == 1) { - ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG); - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG); - ui_InterruptStatus_1564 = - inl(devpriv->i_IobaseAmcc + APCI1564_DI_INT_STATUS_REG); - ui_InterruptStatus_1564 = ui_InterruptStatus_1564 & 0X000FFFF0; - /* send signal to the sample */ - send_sig(SIGIO, devpriv->tsk_Current, 0); - /* enable the interrupt */ - outl(ui_DI, devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG); - return; - } - - if (ui_DO == 1) { - /* Check for Digital Output interrupt Type */ - /* 1: VCC interrupt */ - /* 2: CC interrupt */ - ui_Type = inl(devpriv->i_IobaseAmcc + APCI1564_DO_INT_STATUS_REG) & 0x3; - /* Disable the Interrupt */ - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DO_INT_CTRL_REG); - - /* Sends signal to user space */ - send_sig(SIGIO, devpriv->tsk_Current, 0); - } - - if (ui_Timer == 1) { - devpriv->b_TimerSelectMode = ADDIDATA_TIMER; - if (devpriv->b_TimerSelectMode) { - - /* Disable Timer Interrupt */ - ul_Command2 = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG); - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG); - - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_Current, 0); - - /* Enable Timer Interrupt */ - - outl(ul_Command2, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG); - } - } - - if (ui_C1 == 1) { - devpriv->b_TimerSelectMode = ADDIDATA_COUNTER; - if (devpriv->b_TimerSelectMode) { - - /* Disable Counter Interrupt */ - ul_Command2 = - inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1)); - outl(0x0, - dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1)); - - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_Current, 0); - - /* Enable Counter Interrupt */ - outl(ul_Command2, - dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1)); - } - } - - if (ui_C2 == 1) { - devpriv->b_TimerSelectMode = ADDIDATA_COUNTER; - if (devpriv->b_TimerSelectMode) { - - /* Disable Counter Interrupt */ - ul_Command2 = - inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2)); - outl(0x0, - dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2)); - - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_Current, 0); - - /* Enable Counter Interrupt */ - outl(ul_Command2, - dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2)); - } - } - - if (ui_C3 == 1) { - devpriv->b_TimerSelectMode = ADDIDATA_COUNTER; - if (devpriv->b_TimerSelectMode) { - - /* Disable Counter Interrupt */ - ul_Command2 = - inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3)); - outl(0x0, - dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3)); - - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_Current, 0); - - /* Enable Counter Interrupt */ - outl(ul_Command2, - dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3)); - } - } - - if (ui_C4 == 1) { - devpriv->b_TimerSelectMode = ADDIDATA_COUNTER; - if (devpriv->b_TimerSelectMode) { - - /* Disable Counter Interrupt */ - ul_Command2 = - inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4)); - outl(0x0, - dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4)); - - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_Current, 0); - - /* Enable Counter Interrupt */ - outl(ul_Command2, - dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4)); - } - } - return; -} diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c index 764c8f17f8fa..77cee876a374 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c @@ -270,7 +270,7 @@ static int apci3120_ai_insn_config(struct comedi_device *dev, if (CR_CHAN(data[4 + i]) >= this_board->i_NbrAiChannel) { - printk("bad channel list\n"); + dev_err(dev->class_dev, "bad channel list\n"); return -2; } } @@ -318,7 +318,8 @@ static int apci3120_setup_chan_list(struct comedi_device *dev, /* correct channel and range number check itself comedi/range.c */ if (n_chan < 1) { if (!check) - comedi_error(dev, "range/channel list is empty!"); + dev_err(dev->class_dev, + "range/channel list is empty!\n"); return 0; } /* All is ok, so we can setup channel/range list */ @@ -344,11 +345,6 @@ static int apci3120_setup_chan_list(struct comedi_device *dev, us_TmpValue |= ((gain & 0x03) << 4); /* <<4 for G0 and G1 bit in RAM */ us_TmpValue |= i << 8; /* To select the RAM LOCATION.... */ outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS); - - printk("\n Gain = %i", - (((unsigned char)CR_RANGE(chanlist[i]) & 0x03) << 2)); - printk("\n Channel = %i", CR_CHAN(chanlist[i])); - printk("\n Polarity = %i", us_TmpValue & APCI3120_UNIPOLAR); } return 1; /* we can serve this with scan logic */ } @@ -369,10 +365,9 @@ static int apci3120_ai_insn_read(struct comedi_device *dev, unsigned char b_Tmp; /* fix conversion time to 10 us */ - if (!devpriv->ui_EocEosConversionTime) { - printk("No timer0 Value using 10 us\n"); + if (!devpriv->ui_EocEosConversionTime) us_ConvertTiming = 10; - } else + else us_ConvertTiming = (unsigned short) (devpriv->ui_EocEosConversionTime / 1000); /* nano to useconds */ /* this_board->ai_read(dev,us_ConvertTiming,insn->n,&insn->chanspec,data,insn->unused[0]); */ @@ -593,7 +588,7 @@ static int apci3120_ai_insn_read(struct comedi_device *dev, break; default: - printk("inputs wrong\n"); + dev_err(dev->class_dev, "inputs wrong\n"); } devpriv->ui_EocEosConversionTime = 0; /* re initializing the variable; */ @@ -1051,7 +1046,7 @@ static int apci3120_cyclic_ai(int mode, b_DigitalOutputRegister) & 0xF0) | APCI3120_SELECT_TIMER_2_LOW_WORD; outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0); - outw(LOWORD(ui_TimerValue2), + outw(ui_TimerValue2 & 0xffff, dev->iobase + APCI3120_TIMER_VALUE); /* Writing HIGH unsigned short */ @@ -1059,7 +1054,7 @@ static int apci3120_cyclic_ai(int mode, b_DigitalOutputRegister) & 0xF0) | APCI3120_SELECT_TIMER_2_HIGH_WORD; outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0); - outw(HIWORD(ui_TimerValue2), + outw((ui_TimerValue2 >> 16) & 0xffff, dev->iobase + APCI3120_TIMER_VALUE); /* (2) Reset FC_TIMER BIT Clearing timer status register */ @@ -1373,10 +1368,10 @@ static void apci3120_interrupt_dma(int irq, void *d) if (samplesinbuf < devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer]) { - comedi_error(dev, "Interrupted DMA transfer!"); + dev_err(dev->class_dev, "Interrupted DMA transfer!\n"); } if (samplesinbuf & 1) { - comedi_error(dev, "Odd count of bytes in DMA ring!"); + dev_err(dev->class_dev, "Odd count of bytes in DMA ring!\n"); apci3120_cancel(dev, s); return; } @@ -1548,7 +1543,7 @@ static void apci3120_interrupt(int irq, void *d) int_amcc = inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR); /* get AMCC int register */ if ((!int_daq) && (!(int_amcc & ANY_S593X_INT))) { - comedi_error(dev, "IRQ from unknown source"); + dev_err(dev->class_dev, "IRQ from unknown source\n"); return; } @@ -1565,9 +1560,9 @@ static void apci3120_interrupt(int irq, void *d) inb(devpriv->i_IobaseAmcc + APCI3120_TIMER_STATUS_REGISTER); if (int_amcc & MASTER_ABORT_INT) - comedi_error(dev, "AMCC IRQ - MASTER DMA ABORT!"); + dev_err(dev->class_dev, "AMCC IRQ - MASTER DMA ABORT!\n"); if (int_amcc & TARGET_ABORT_INT) - comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!"); + dev_err(dev->class_dev, "AMCC IRQ - TARGET DMA ABORT!\n"); /* Ckeck if EOC interrupt */ if (((int_daq & 0x8) == 0) @@ -1740,7 +1735,7 @@ static int apci3120_config_insn_timer(struct comedi_device *dev, unsigned char b_Tmp; if (!data[1]) - comedi_error(dev, "config:No timer constant !"); + dev_err(dev->class_dev, "No timer constant!\n"); devpriv->b_Timer2Interrupt = (unsigned char) data[2]; /* save info whether to enable or disable interrupt */ @@ -1805,7 +1800,7 @@ static int apci3120_config_insn_timer(struct comedi_device *dev, b_DigitalOutputRegister) & 0xF0) | APCI3120_SELECT_TIMER_2_LOW_WORD; outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); - outw(LOWORD(ui_Timervalue2), + outw(ui_Timervalue2 & 0xffff, devpriv->iobase + APCI3120_TIMER_VALUE); /* Writing HIGH unsigned short */ @@ -1813,7 +1808,7 @@ static int apci3120_config_insn_timer(struct comedi_device *dev, b_DigitalOutputRegister) & 0xF0) | APCI3120_SELECT_TIMER_2_HIGH_WORD; outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); - outw(HIWORD(ui_Timervalue2), + outw((ui_Timervalue2 >> 16) & 0xffff, devpriv->iobase + APCI3120_TIMER_VALUE); /* timer2 in Timer mode enabled */ devpriv->b_Timer2Mode = APCI3120_TIMER; @@ -1841,7 +1836,7 @@ static int apci3120_config_insn_timer(struct comedi_device *dev, b_DigitalOutputRegister) & 0xF0) | APCI3120_SELECT_TIMER_2_LOW_WORD; outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); - outw(LOWORD(ui_Timervalue2), + outw(ui_Timervalue2 & 0xffff, devpriv->iobase + APCI3120_TIMER_VALUE); /* Writing HIGH unsigned short */ @@ -1850,7 +1845,7 @@ static int apci3120_config_insn_timer(struct comedi_device *dev, APCI3120_SELECT_TIMER_2_HIGH_WORD; outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); - outw(HIWORD(ui_Timervalue2), + outw((ui_Timervalue2 >> 16) & 0xffff, devpriv->iobase + APCI3120_TIMER_VALUE); /* watchdog enabled */ devpriv->b_Timer2Mode = APCI3120_WATCHDOG; @@ -1886,14 +1881,14 @@ static int apci3120_write_insn_timer(struct comedi_device *dev, if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG) && (devpriv->b_Timer2Mode != APCI3120_TIMER)) { - comedi_error(dev, "\nwrite:timer2 not configured "); + dev_err(dev->class_dev, "timer2 not configured\n"); return -EINVAL; } if (data[0] == 2) { /* write new value */ if (devpriv->b_Timer2Mode != APCI3120_TIMER) { - comedi_error(dev, - "write :timer2 not configured in TIMER MODE"); + dev_err(dev->class_dev, + "timer2 not configured in TIMER MODE\n"); return -EINVAL; } @@ -1991,8 +1986,8 @@ static int apci3120_write_insn_timer(struct comedi_device *dev, case 2: /* write new value to Timer */ if (devpriv->b_Timer2Mode != APCI3120_TIMER) { - comedi_error(dev, - "write :timer2 not configured in TIMER MODE"); + dev_err(dev->class_dev, + "timer2 not configured in TIMER MODE\n"); return -EINVAL; } /* ui_Timervalue2=data[1]; // passed as argument */ @@ -2017,7 +2012,7 @@ static int apci3120_write_insn_timer(struct comedi_device *dev, APCI3120_SELECT_TIMER_2_LOW_WORD; outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); - outw(LOWORD(ui_Timervalue2), + outw(ui_Timervalue2 & 0xffff, devpriv->iobase + APCI3120_TIMER_VALUE); /* Writing HIGH unsigned short */ @@ -2026,7 +2021,7 @@ static int apci3120_write_insn_timer(struct comedi_device *dev, APCI3120_SELECT_TIMER_2_HIGH_WORD; outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); - outw(HIWORD(ui_Timervalue2), + outw((ui_Timervalue2 >> 16) & 0xffff, devpriv->iobase + APCI3120_TIMER_VALUE); break; @@ -2056,7 +2051,7 @@ static int apci3120_read_insn_timer(struct comedi_device *dev, if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG) && (devpriv->b_Timer2Mode != APCI3120_TIMER)) { - comedi_error(dev, "\nread:timer2 not configured "); + dev_err(dev->class_dev, "timer2 not configured\n"); } /* this_board->timer_read(dev,data); */ @@ -2161,10 +2156,6 @@ static int apci3120_ao_insn_write(struct comedi_device *dev, } -/* - * out put n values at the given channel. printk("\nwaiting for - * DA_READY BIT"); - */ do { /* Waiting of DA_READY BIT */ us_TmpValue = ((unsigned short) inw(devpriv->iobase + diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c index f540394d17b0..5e321f91172f 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c @@ -47,8 +47,6 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY +----------+-----------+------------------------------------------------+ */ -/* #define PRINT_INFO */ - /* Card Specific information */ /* #define APCI3200_ADDRESS_RANGE 264 */ @@ -455,12 +453,6 @@ static void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAd BoardInformations->s_Module[w_ModulCounter]. w_GainValue[w_GainIndex] = w_GainValue; -# ifdef PRINT_INFO - printk("\n Gain value = %d", - BoardInformations->s_Module[w_ModulCounter]. - w_GainValue[w_GainIndex]); -# endif - /*************************************/ /** Read gain factor for the module **/ /*************************************/ @@ -472,12 +464,6 @@ static void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAd ul_GainFactor[w_GainIndex] = (w_GainFactorValue[1] << 16) + w_GainFactorValue[0]; - -# ifdef PRINT_INFO - printk("\n w_GainFactorValue [%d] = %lu", w_GainIndex, - BoardInformations->s_Module[w_ModulCounter]. - ul_GainFactor[w_GainIndex]); -# endif } /***************************************************************/ @@ -499,12 +485,6 @@ static void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAd ul_CurrentSource[w_Input] = (w_CurrentSources[0] + ((w_CurrentSources[1] & 0xFFF) << 16)); - -# ifdef PRINT_INFO - printk("\n Current sources [%d] = %lu", w_Input, - BoardInformations->s_Module[w_ModulCounter]. - ul_CurrentSource[w_Input]); -# endif } /***************************************/ @@ -522,12 +502,6 @@ static void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAd ul_CurrentSourceCJC = (w_CurrentSources[0] + ((w_CurrentSources[1] & 0xFFF) << 16)); - -# ifdef PRINT_INFO - printk("\n Current sources CJC = %lu", - BoardInformations->s_Module[w_ModulCounter]. - ul_CurrentSourceCJC); -# endif } } @@ -540,10 +514,6 @@ static int i_APCI3200_GetChannelCalibrationValue(struct comedi_device *dev, int i_DiffChannel = 0; int i_Module = 0; -#ifdef PRINT_INFO - printk("\n Channel = %u", ui_Channel_num); -#endif - /* Test if single or differential mode */ if (s_BoardInfos[dev->minor].i_ConnectionType == 1) { /* if diff */ @@ -580,16 +550,10 @@ static int i_APCI3200_GetChannelCalibrationValue(struct comedi_device *dev, /* Test if thermocouple or RTD mode */ *CJCCurrentSource = s_BoardInfos[dev->minor].s_Module[i_Module].ul_CurrentSourceCJC; -#ifdef PRINT_INFO - printk("\n CJCCurrentSource = %lu", *CJCCurrentSource); -#endif *ChannelCurrentSource = s_BoardInfos[dev->minor].s_Module[i_Module]. ul_CurrentSource[i_DiffChannel]; -#ifdef PRINT_INFO - printk("\n ChannelCurrentSource = %lu", *ChannelCurrentSource); -#endif /* } */ /* } */ @@ -597,9 +561,6 @@ static int i_APCI3200_GetChannelCalibrationValue(struct comedi_device *dev, *ChannelGainFactor = s_BoardInfos[dev->minor].s_Module[i_Module]. ul_GainFactor[s_BoardInfos[dev->minor].i_ADDIDATAGain]; -#ifdef PRINT_INFO - printk("\n ChannelGainFactor = %lu", *ChannelGainFactor); -#endif /* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */ return 0; @@ -689,17 +650,11 @@ static int i_APCI3200_Read1AnalogInputChannel(struct comedi_device *dev, ui_CommandRegister = ui_ChannelNo | (ui_ChannelNo << 8) | 0x80000; - /*********************************/ /*Test if the interrupt is enable */ - /*********************************/ - - /* if (i_InterruptFlag == ADDIDATA_ENABLE) */ - if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) { - /************************/ + if (s_BoardInfos[dev->minor].i_InterruptFlag == 1) { /* Enable the interrupt */ - /************************/ ui_CommandRegister = ui_CommandRegister | 0x00100000; - } /* if (i_InterruptFlag == ADDIDATA_ENABLE) */ + } /******************************/ /* Write the command register */ @@ -712,11 +667,8 @@ static int i_APCI3200_Read1AnalogInputChannel(struct comedi_device *dev, outl(ui_CommandRegister, devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8); - /*****************************/ /*Test if interrupt is enable */ - /*****************************/ - /* if (i_InterruptFlag == ADDIDATA_DISABLE) */ - if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) { + if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) { do { /*************************/ /*Read the EOC Status bit */ @@ -738,7 +690,7 @@ static int i_APCI3200_Read1AnalogInputChannel(struct comedi_device *dev, s_BoardInfos[dev->minor].i_Offset + 28); /* END JK 06.07.04: Management of sevrals boards */ - } /* if (i_InterruptFlag == ADDIDATA_DISABLE) */ + } return 0; } @@ -800,20 +752,11 @@ static int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev, ui_CommandRegister = 0; - /*********************************/ /*Test if the interrupt is enable */ - /*********************************/ - - /* if (i_InterruptFlag == ADDIDATA_ENABLE) */ - if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) { - - /**********************/ + if (s_BoardInfos[dev->minor].i_InterruptFlag == 1) { /*Enable the interrupt */ - /**********************/ - ui_CommandRegister = ui_CommandRegister | 0x00100000; - - } /* if (i_InterruptFlag == ADDIDATA_ENABLE) */ + } /**********************/ /*Start the conversion */ @@ -830,13 +773,8 @@ static int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev, outl(ui_CommandRegister, devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8); - /*****************************/ /*Test if interrupt is enable */ - /*****************************/ - - /* if (i_InterruptFlag == ADDIDATA_DISABLE) */ - if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) { - + if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) { do { /*******************/ /*Read the EOC flag */ @@ -856,7 +794,7 @@ static int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev, data[0] = inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 28); - } /* if (i_InterruptFlag == ADDIDATA_DISABLE) */ + } return 0; } @@ -915,20 +853,11 @@ static int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev, ui_CommandRegister = 0; - /*********************************/ /*Test if the interrupt is enable */ - /*********************************/ - - /* if (i_InterruptFlag == ADDIDATA_ENABLE) */ - if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) { - - /**********************/ + if (s_BoardInfos[dev->minor].i_InterruptFlag == 1) { /*Enable the interrupt */ - /**********************/ - ui_CommandRegister = ui_CommandRegister | 0x00100000; - - } /* if (i_InterruptFlag == ADDIDATA_ENABLE) */ + } /**********************/ /*Start the conversion */ @@ -945,13 +874,8 @@ static int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev, outl(ui_CommandRegister, devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8); - /*****************************/ /*Test if interrupt is enable */ - /*****************************/ - - /* if (i_InterruptFlag == ADDIDATA_DISABLE) */ - if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) { - + if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) { do { /*******************/ @@ -973,7 +897,7 @@ static int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev, inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 28); - } /* if (i_InterruptFlag == ADDIDATA_DISABLE) */ + } return 0; } @@ -1020,14 +944,9 @@ static int i_APCI3200_ReadCJCValue(struct comedi_device *dev, /*Initialise dw_CommandRegister */ /*******************************/ ui_CommandRegister = 0; - /*********************************/ /*Test if the interrupt is enable */ - /*********************************/ - /* if (i_InterruptFlag == ADDIDATA_ENABLE) */ - if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) { - /**********************/ + if (s_BoardInfos[dev->minor].i_InterruptFlag == 1) { /*Enable the interrupt */ - /**********************/ ui_CommandRegister = ui_CommandRegister | 0x00100000; } @@ -1047,12 +966,8 @@ static int i_APCI3200_ReadCJCValue(struct comedi_device *dev, outl(ui_CommandRegister, devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8); - /*****************************/ /*Test if interrupt is enable */ - /*****************************/ - - /* if (i_InterruptFlag == ADDIDATA_DISABLE) */ - if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) { + if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) { do { /*******************/ @@ -1073,8 +988,7 @@ static int i_APCI3200_ReadCJCValue(struct comedi_device *dev, data[0] = inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 28); - - } /* if (i_InterruptFlag == ADDIDATA_DISABLE) */ + } return 0; } @@ -1128,17 +1042,10 @@ static int i_APCI3200_ReadCJCCalOffset(struct comedi_device *dev, /*Initialise ui_CommandRegister */ /*******************************/ ui_CommandRegister = 0; - /*********************************/ /*Test if the interrupt is enable */ - /*********************************/ - - /* if (i_InterruptFlag == ADDIDATA_ENABLE) */ - if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) { - /**********************/ + if (s_BoardInfos[dev->minor].i_InterruptFlag == 1) { /*Enable the interrupt */ - /**********************/ ui_CommandRegister = ui_CommandRegister | 0x00100000; - } /**********************/ @@ -1154,8 +1061,7 @@ static int i_APCI3200_ReadCJCCalOffset(struct comedi_device *dev, /* outl(ui_CommandRegister,devpriv->iobase+i_Offset + 8); */ outl(ui_CommandRegister, devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8); - /* if (i_InterruptFlag == ADDIDATA_DISABLE) */ - if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) { + if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) { do { /*******************/ /*Read the EOC flag */ @@ -1172,7 +1078,7 @@ static int i_APCI3200_ReadCJCCalOffset(struct comedi_device *dev, data[0] = inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 28); - } /* if (i_InterruptFlag == ADDIDATA_DISABLE) */ + } return 0; } @@ -1224,14 +1130,9 @@ static int i_APCI3200_ReadCJCCalGain(struct comedi_device *dev, /*Initialise dw_CommandRegister */ /*******************************/ ui_CommandRegister = 0; - /*********************************/ /*Test if the interrupt is enable */ - /*********************************/ - /* if (i_InterruptFlag == ADDIDATA_ENABLE) */ - if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) { - /**********************/ + if (s_BoardInfos[dev->minor].i_InterruptFlag == 1) { /*Enable the interrupt */ - /**********************/ ui_CommandRegister = ui_CommandRegister | 0x00100000; } /**********************/ @@ -1247,8 +1148,7 @@ static int i_APCI3200_ReadCJCCalGain(struct comedi_device *dev, /* outl(ui_CommandRegister ,devpriv->iobase+i_Offset + 8); */ outl(ui_CommandRegister, devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8); - /* if (i_InterruptFlag == ADDIDATA_DISABLE) */ - if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) { + if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) { do { /*******************/ /*Read the EOC flag */ @@ -1264,7 +1164,7 @@ static int i_APCI3200_ReadCJCCalGain(struct comedi_device *dev, data[0] = inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 28); - } /* if (i_InterruptFlag == ADDIDATA_DISABLE) */ + } return 0; } @@ -1340,10 +1240,6 @@ static int apci3200_ai_read(struct comedi_device *dev, return -EINVAL; } /* if(i_Initialised==0); */ -#ifdef PRINT_INFO - printk("\n insn->unused[0] = %i", insn->unused[0]); -#endif - switch (insn->unused[0]) { case 0: @@ -1368,15 +1264,6 @@ static int apci3200_ai_read(struct comedi_device *dev, &s_BoardInfos[dev->minor]. ui_InterruptChannelValue[s_BoardInfos[dev->minor]. i_Count + 8]); - -#ifdef PRINT_INFO - printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+6] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 6]); - - printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+7] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 7]); - - printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+8] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 8]); -#endif - /* End JK 25.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */ /* BEGIN JK 06.07.04: Management of sevrals boards */ @@ -1532,9 +1419,6 @@ static int apci3200_ai_read(struct comedi_device *dev, data[4]= ui_InterruptChannelValue[4]; data[5]= ui_InterruptChannelValue[5]; */ -#ifdef PRINT_INFO - printk("\n data[0]= s_BoardInfos [dev->minor].ui_InterruptChannelValue[0];"); -#endif data[0] = s_BoardInfos[dev->minor]. ui_InterruptChannelValue[0]; @@ -1555,7 +1439,6 @@ static int apci3200_ai_read(struct comedi_device *dev, ui_InterruptChannelValue[5]; /* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */ - /* printk("\n 0 - i_APCI3200_GetChannelCalibrationValue data [6] = %lu, data [7] = %lu, data [8] = %lu", data [6], data [7], data [8]); */ i_APCI3200_GetChannelCalibrationValue(dev, s_BoardInfos[dev->minor].ui_Channel_num, &data[6], &data[7], &data[8]); @@ -1637,13 +1520,6 @@ static int apci3200_ai_config(struct comedi_device *dev, unsigned int ui_Dummy = 0; int i_err = 0; - /* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */ - -#ifdef PRINT_INFO - int i = 0, i2 = 0; -#endif - /* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */ - /* BEGIN JK 06.07.04: Management of sevrals boards */ /* Initialize the structure */ if (s_BoardInfos[dev->minor].b_StructInitialized != 1) { @@ -1669,29 +1545,6 @@ static int apci3200_ai_config(struct comedi_device *dev, v_GetAPCI3200EepromCalibrationValue(devpriv->i_IobaseAmcc, &s_BoardInfos[dev->minor]); - -#ifdef PRINT_INFO - for (i = 0; i < MAX_MODULE; i++) { - printk("\n s_Module[%i].ul_CurrentSourceCJC = %lu", i, - s_BoardInfos[dev->minor].s_Module[i]. - ul_CurrentSourceCJC); - - for (i2 = 0; i2 < 5; i2++) { - printk("\n s_Module[%i].ul_CurrentSource [%i] = %lu", i, i2, s_BoardInfos[dev->minor].s_Module[i].ul_CurrentSource[i2]); - } - - for (i2 = 0; i2 < 8; i2++) { - printk("\n s_Module[%i].ul_GainFactor [%i] = %lu", i, i2, s_BoardInfos[dev->minor].s_Module[i].ul_GainFactor[i2]); - } - - for (i2 = 0; i2 < 8; i2++) { - printk("\n s_Module[%i].w_GainValue [%i] = %u", - i, i2, - s_BoardInfos[dev->minor].s_Module[i]. - w_GainValue[i2]); - } - } -#endif /* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */ } @@ -1811,34 +1664,34 @@ static int apci3200_ai_config(struct comedi_device *dev, /* END JK 06.07.04: Management of sevrals boards */ if (data[5] == 0) { - if (ui_ChannelNo < 0 || ui_ChannelNo > 15) { + if (ui_ChannelNo > 15) { printk("\nThe Selection of the channel is in error\n"); i_err++; - } /* if(ui_ChannelNo<0 || ui_ChannelNo>15) */ + } /* if(ui_ChannelNo>15) */ } /* if(data[5]==0) */ else { if (data[14] == 2) { - if (ui_ChannelNo < 0 || ui_ChannelNo > 3) { + if (ui_ChannelNo > 3) { printk("\nThe Selection of the channel is in error\n"); i_err++; - } /* if(ui_ChannelNo<0 || ui_ChannelNo>3) */ + } /* if(ui_ChannelNo>3) */ } /* if(data[14]==2) */ else { - if (ui_ChannelNo < 0 || ui_ChannelNo > 7) { + if (ui_ChannelNo > 7) { printk("\nThe Selection of the channel is in error\n"); i_err++; - } /* if(ui_ChannelNo<0 || ui_ChannelNo>7) */ + } /* if(ui_ChannelNo>7) */ } /* elseif(data[14]==2) */ } /* elseif(data[5]==0) */ if (data[12] == 0 || data[12] == 1) { switch (data[5]) { case 0: - if (ui_ChannelNo >= 0 && ui_ChannelNo <= 3) { + if (ui_ChannelNo <= 3) { /* BEGIN JK 06.07.04: Management of sevrals boards */ /* i_Offset=0; */ s_BoardInfos[dev->minor].i_Offset = 0; /* END JK 06.07.04: Management of sevrals boards */ - } /* if(ui_ChannelNo >=0 && ui_ChannelNo <=3) */ + } /* if(ui_ChannelNo <=3) */ if (ui_ChannelNo >= 4 && ui_ChannelNo <= 7) { /* BEGIN JK 06.07.04: Management of sevrals boards */ /* i_Offset=64; */ @@ -1892,12 +1745,12 @@ static int apci3200_ai_config(struct comedi_device *dev, ui_ChannelNo = 0; break; } /* if(data[14]==2) */ - if (ui_ChannelNo >= 0 && ui_ChannelNo <= 1) { + if (ui_ChannelNo <= 1) { /* BEGIN JK 06.07.04: Management of sevrals boards */ /* i_Offset=0; */ s_BoardInfos[dev->minor].i_Offset = 0; /* END JK 06.07.04: Management of sevrals boards */ - } /* if(ui_ChannelNo >=0 && ui_ChannelNo <=1) */ + } /* if(ui_ChannelNo <=1) */ if (ui_ChannelNo >= 2 && ui_ChannelNo <= 3) { /* BEGIN JK 06.07.04: Management of sevrals boards */ /* i_ChannelNo=i_ChannelNo-2; */ @@ -2136,8 +1989,7 @@ static int apci3200_ai_bits_test(struct comedi_device *dev, i_ADDIDATAConversionTimeUnit= 1; */ /* i_Temp= i_InterruptFlag ; */ i_Temp = s_BoardInfos[dev->minor].i_InterruptFlag; - /* i_InterruptFlag = ADDIDATA_DISABLE; */ - s_BoardInfos[dev->minor].i_InterruptFlag = ADDIDATA_DISABLE; + s_BoardInfos[dev->minor].i_InterruptFlag = 0; i_APCI3200_Read1AnalogInputChannel(dev, s, insn, data); /* if(i_AutoCalibration == FALSE) */ if (s_BoardInfos[dev->minor].i_AutoCalibration == FALSE) { @@ -2176,8 +2028,7 @@ static int apci3200_ai_bits_test(struct comedi_device *dev, i_ADDIDATAConversionTimeUnit= 1; */ /* i_Temp= i_InterruptFlag ; */ i_Temp = s_BoardInfos[dev->minor].i_InterruptFlag; - /* i_InterruptFlag = ADDIDATA_DISABLE; */ - s_BoardInfos[dev->minor].i_InterruptFlag = ADDIDATA_DISABLE; + s_BoardInfos[dev->minor].i_InterruptFlag = 0; i_APCI3200_Read1AnalogInputChannel(dev, s, insn, data); /* if(i_AutoCalibration == FALSE) */ if (s_BoardInfos[dev->minor].i_AutoCalibration == FALSE) { @@ -2198,7 +2049,6 @@ static int apci3200_ai_bits_test(struct comedi_device *dev, } /* i_InterruptFlag=i_Temp ; */ s_BoardInfos[dev->minor].i_InterruptFlag = i_Temp; - /* printk("\ni_InterruptFlag=%d\n",i_InterruptFlag); */ return insn->n; } @@ -2470,8 +2320,6 @@ static int apci3200_ai_cmd(struct comedi_device *dev, ui_DelayTimeBase = cmd->scan_begin_arg >> 16; ui_DelayMode = 1; } /* else if(cmd->scan_begin_src==TRIG_FOLLOW) */ - /* printk("\nui_DelayTime=%u\n",ui_DelayTime); */ - /* printk("\nui_DelayTimeBase=%u\n",ui_DelayTimeBase); */ if (cmd->convert_src == TRIG_TIMER) { ui_ConvertTime = cmd->convert_arg & 0xFFFF; ui_ConvertTimeBase = cmd->convert_arg >> 16; @@ -2499,13 +2347,6 @@ static int apci3200_ai_cmd(struct comedi_device *dev, devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12); /* } */ ui_Configuration = 0; - /* printk("\nfirstchannel=%u\n",i_FirstChannel); */ - /* printk("\nlastchannel=%u\n",i_LastChannel); */ - /* printk("\nui_Trigger=%u\n",ui_Trigger); */ - /* printk("\nui_TriggerEdge=%u\n",ui_TriggerEdge); */ - /* printk("\nui_Triggermode=%u\n",ui_Triggermode); */ - /* printk("\nui_DelayMode=%u\n",ui_DelayMode); */ - /* printk("\nui_ScanMode=%u\n",ui_ScanMode); */ /* ui_Configuration = i_FirstChannel |(i_LastChannel << 8)| 0x00100000 | */ ui_Configuration = @@ -2757,8 +2598,6 @@ static void apci3200_interrupt(int irq, void *d) int i_ReturnValue = 0; /* END JK TEST */ - /* printk ("\n i_ScanType = %i i_ADDIDATAType = %i", s_BoardInfos [dev->minor].i_ScanType, s_BoardInfos [dev->minor].i_ADDIDATAType); */ - /* switch(i_ScanType) */ switch (s_BoardInfos[dev->minor].i_ScanType) { case 0: @@ -2809,7 +2648,6 @@ static void apci3200_interrupt(int irq, void *d) /* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */ /* - printk("\n 1 - i_APCI3200_GetChannelCalibrationValue (dev, s_BoardInfos %i", ui_ChannelNumber); i_APCI3200_GetChannelCalibrationValue (dev, s_BoardInfos [dev->minor].ui_Channel_num, &s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count + 6], &s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count + 7], diff --git a/drivers/staging/comedi/drivers/addi_apci_035.c b/drivers/staging/comedi/drivers/addi_apci_035.c index 4da9db35b8e2..af70c8401880 100644 --- a/drivers/staging/comedi/drivers/addi_apci_035.c +++ b/drivers/staging/comedi/drivers/addi_apci_035.c @@ -18,7 +18,7 @@ static const struct addi_board apci035_boardtypes[] = { .pc_DriverName = "apci035", .i_IorangeBase1 = APCI035_ADDRESS_RANGE, .i_PCIEeprom = 1, - .pc_EepromChip = ADDIDATA_S5920, + .pc_EepromChip = "S5920", .i_NbrAiChannel = 16, .i_NbrAiChannelDiff = 8, .i_AiChannelList = 16, diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index eab75eb26478..b7a284ac6649 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -15,7 +15,7 @@ static const struct addi_board apci1500_boardtypes[] = { { .pc_DriverName = "apci1500", .i_IorangeBase1 = APCI1500_ADDRESS_RANGE, - .i_PCIEeprom = ADDIDATA_NO_EEPROM, + .i_PCIEeprom = 0, .i_NbrDiChannel = 16, .i_NbrDoChannel = 16, .i_DoMaxdata = 0xffff, diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c index 13d9962b47ec..543cb074213a 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1564.c +++ b/drivers/staging/comedi/drivers/addi_apci_1564.c @@ -1,17 +1,114 @@ #include <linux/module.h> #include <linux/pci.h> +#include <linux/interrupt.h> +#include <linux/sched.h> #include "../comedidev.h" #include "comedi_fc.h" - -#include "addi-data/addi_common.h" +#include "amcc_s5933.h" +#include "addi_watchdog.h" + +struct apci1564_private { + unsigned int amcc_iobase; /* base of AMCC I/O registers */ + unsigned int mode1; /* riding-edge/high level channels */ + unsigned int mode2; /* falling-edge/low level channels */ + unsigned int ctrl; /* interrupt mode OR (edge) . AND (level) */ + unsigned char timer_select_mode; + unsigned char mode_select_register; + struct task_struct *tsk_current; +}; #include "addi-data/hwdrv_apci1564.c" -static irqreturn_t v_ADDI_Interrupt(int irq, void *d) +static int apci1564_reset(struct comedi_device *dev) { - apci1564_interrupt(irq, d); - return IRQ_RETVAL(1); + struct apci1564_private *devpriv = dev->private; + + /* Disable the input interrupts and reset status register */ + outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG); + inl(devpriv->amcc_iobase + APCI1564_DI_INT_STATUS_REG); + outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE1_REG); + outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE2_REG); + + /* Reset the output channels and disable interrupts */ + outl(0x0, devpriv->amcc_iobase + APCI1564_DO_REG); + outl(0x0, devpriv->amcc_iobase + APCI1564_DO_INT_CTRL_REG); + + /* Reset the watchdog registers */ + addi_watchdog_reset(devpriv->amcc_iobase + APCI1564_WDOG_REG); + + /* Reset the timer registers */ + outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); + outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_RELOAD_REG); + + /* Reset the counter registers */ + outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1)); + outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2)); + outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3)); + outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4)); + + return 0; +} + +static irqreturn_t apci1564_interrupt(int irq, void *d) +{ + struct comedi_device *dev = d; + struct apci1564_private *devpriv = dev->private; + struct comedi_subdevice *s = dev->read_subdev; + unsigned int status; + unsigned int ctrl; + unsigned int chan; + + /* check interrupt is from this device */ + if ((inl(devpriv->amcc_iobase + AMCC_OP_REG_INTCSR) & + INTCSR_INTR_ASSERTED) == 0) + return IRQ_NONE; + + status = inl(devpriv->amcc_iobase + APCI1564_DI_IRQ_REG); + if (status & APCI1564_DI_INT_ENABLE) { + /* disable the interrupt */ + outl(status & APCI1564_DI_INT_DISABLE, + devpriv->amcc_iobase + APCI1564_DI_IRQ_REG); + + s->state = inl(dev->iobase + APCI1564_DI_INT_STATUS_REG) + & 0xffff; + comedi_buf_put(s, s->state); + s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; + comedi_event(dev, s); + + /* enable the interrupt */ + outl(status, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG); + } + + status = inl(devpriv->amcc_iobase + APCI1564_TIMER_IRQ_REG); + if (status & 0x01) { + /* Disable Timer Interrupt */ + ctrl = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); + outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); + + /* Send a signal to from kernel to user space */ + send_sig(SIGIO, devpriv->tsk_current, 0); + + /* Enable Timer Interrupt */ + outl(ctrl, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); + } + + for (chan = 0; chan < 4; chan++) { + status = inl(dev->iobase + APCI1564_TCW_IRQ_REG(chan)); + if (status & 0x01) { + /* Disable Counter Interrupt */ + ctrl = inl(dev->iobase + APCI1564_TCW_CTRL_REG(chan)); + outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(chan)); + + /* Send a signal to from kernel to user space */ + send_sig(SIGIO, devpriv->tsk_current, 0); + + /* Enable Counter Interrupt */ + outl(ctrl, dev->iobase + APCI1564_TCW_CTRL_REG(chan)); + } + } + + return IRQ_HANDLED; } static int apci1564_di_insn_bits(struct comedi_device *dev, @@ -19,9 +116,9 @@ static int apci1564_di_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct addi_private *devpriv = dev->private; + struct apci1564_private *devpriv = dev->private; - data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_DI_REG); + data[1] = inl(devpriv->amcc_iobase + APCI1564_DI_REG); return insn->n; } @@ -31,46 +128,214 @@ static int apci1564_do_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct addi_private *devpriv = dev->private; + struct apci1564_private *devpriv = dev->private; - s->state = inl(devpriv->i_IobaseAmcc + APCI1564_DO_REG); + s->state = inl(devpriv->amcc_iobase + APCI1564_DO_REG); if (comedi_dio_update_state(s, data)) - outl(s->state, devpriv->i_IobaseAmcc + APCI1564_DO_REG); + outl(s->state, devpriv->amcc_iobase + APCI1564_DO_REG); data[1] = s->state; return insn->n; } -static int apci1564_reset(struct comedi_device *dev) +static int apci1564_diag_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - struct addi_private *devpriv = dev->private; + struct apci1564_private *devpriv = dev->private; - ui_Type = 0; + data[1] = inl(devpriv->amcc_iobase + APCI1564_DO_INT_STATUS_REG) & 3; - /* Disable the input interrupts and reset status register */ - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_IRQ_REG); - inl(devpriv->i_IobaseAmcc + APCI1564_DI_INT_STATUS_REG); - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_INT_MODE1_REG); - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DI_INT_MODE2_REG); + return insn->n; +} - /* Reset the output channels and disable interrupts */ - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DO_REG); - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DO_INT_CTRL_REG); +/* + * Change-Of-State (COS) interrupt configuration + * + * Channels 0 to 15 are interruptible. These channels can be configured + * to generate interrupts based on AND/OR logic for the desired channels. + * + * OR logic + * - reacts to rising or falling edges + * - interrupt is generated when any enabled channel + * meet the desired interrupt condition + * + * AND logic + * - reacts to changes in level of the selected inputs + * - interrupt is generated when all enabled channels + * meet the desired interrupt condition + * - after an interrupt, a change in level must occur on + * the selected inputs to release the IRQ logic + * + * The COS interrupt must be configured before it can be enabled. + * + * data[0] : INSN_CONFIG_DIGITAL_TRIG + * data[1] : trigger number (= 0) + * data[2] : configuration operation: + * COMEDI_DIGITAL_TRIG_DISABLE = no interrupts + * COMEDI_DIGITAL_TRIG_ENABLE_EDGES = OR (edge) interrupts + * COMEDI_DIGITAL_TRIG_ENABLE_LEVELS = AND (level) interrupts + * data[3] : left-shift for data[4] and data[5] + * data[4] : rising-edge/high level channels + * data[5] : falling-edge/low level channels + */ +static int apci1564_cos_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct apci1564_private *devpriv = dev->private; + unsigned int shift, oldmask; + + switch (data[0]) { + case INSN_CONFIG_DIGITAL_TRIG: + if (data[1] != 0) + return -EINVAL; + shift = data[3]; + oldmask = (1U << shift) - 1; + switch (data[2]) { + case COMEDI_DIGITAL_TRIG_DISABLE: + devpriv->ctrl = 0; + devpriv->mode1 = 0; + devpriv->mode2 = 0; + outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG); + inl(devpriv->amcc_iobase + APCI1564_DI_INT_STATUS_REG); + outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE1_REG); + outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE2_REG); + break; + case COMEDI_DIGITAL_TRIG_ENABLE_EDGES: + if (devpriv->ctrl != (APCI1564_DI_INT_ENABLE | + APCI1564_DI_INT_OR)) { + /* switching to 'OR' mode */ + devpriv->ctrl = APCI1564_DI_INT_ENABLE | + APCI1564_DI_INT_OR; + /* wipe old channels */ + devpriv->mode1 = 0; + devpriv->mode2 = 0; + } else { + /* preserve unspecified channels */ + devpriv->mode1 &= oldmask; + devpriv->mode2 &= oldmask; + } + /* configure specified channels */ + devpriv->mode1 |= data[4] << shift; + devpriv->mode2 |= data[5] << shift; + break; + case COMEDI_DIGITAL_TRIG_ENABLE_LEVELS: + if (devpriv->ctrl != (APCI1564_DI_INT_ENABLE | + APCI1564_DI_INT_AND)) { + /* switching to 'AND' mode */ + devpriv->ctrl = APCI1564_DI_INT_ENABLE | + APCI1564_DI_INT_AND; + /* wipe old channels */ + devpriv->mode1 = 0; + devpriv->mode2 = 0; + } else { + /* preserve unspecified channels */ + devpriv->mode1 &= oldmask; + devpriv->mode2 &= oldmask; + } + /* configure specified channels */ + devpriv->mode1 |= data[4] << shift; + devpriv->mode2 |= data[5] << shift; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + return insn->n; +} - /* Reset the watchdog registers */ - addi_watchdog_reset(devpriv->i_IobaseAmcc + APCI1564_WDOG_REG); +static int apci1564_cos_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + data[1] = s->state; - /* Reset the timer registers */ - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER_CTRL_REG); - outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER_RELOAD_REG); + return 0; +} - /* Reset the counter registers */ - outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1)); - outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2)); - outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3)); - outl(0x0, dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4)); +static int apci1564_cos_cmdtest(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + int err = 0; + + /* Step 1 : check if triggers are trivially valid */ + + err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); + err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); + err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW); + err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); + err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE); + + if (err) + return 1; + + /* Step 2a : make sure trigger sources are unique */ + /* Step 2b : and mutually compatible */ + + if (err) + return 2; + + /* Step 3: check if arguments are trivially valid */ + + err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); + err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); + + if (err) + return 3; + + /* step 4: ignored */ + + if (err) + return 4; + + return 0; +} + +/* + * Change-Of-State (COS) 'do_cmd' operation + * + * Enable the COS interrupt as configured by apci1564_cos_insn_config(). + */ +static int apci1564_cos_cmd(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct apci1564_private *devpriv = dev->private; + + if (!devpriv->ctrl) { + dev_warn(dev->class_dev, + "Interrupts disabled due to mode configuration!\n"); + return -EINVAL; + } + + outl(devpriv->mode1, devpriv->amcc_iobase + APCI1564_DI_INT_MODE1_REG); + outl(devpriv->mode2, devpriv->amcc_iobase + APCI1564_DI_INT_MODE2_REG); + outl(devpriv->ctrl, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG); + + return 0; +} + +static int apci1564_cos_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct apci1564_private *devpriv = dev->private; + + outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG); + inl(devpriv->amcc_iobase + APCI1564_DI_INT_STATUS_REG); + outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE1_REG); + outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE2_REG); return 0; } @@ -79,12 +344,10 @@ static int apci1564_auto_attach(struct comedi_device *dev, unsigned long context_unused) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - struct addi_private *devpriv; + struct apci1564_private *devpriv; struct comedi_subdevice *s; int ret; - dev->board_name = dev->driver->driver_name; - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; @@ -94,18 +357,18 @@ static int apci1564_auto_attach(struct comedi_device *dev, return ret; dev->iobase = pci_resource_start(pcidev, 1); - devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0); + devpriv->amcc_iobase = pci_resource_start(pcidev, 0); apci1564_reset(dev); if (pcidev->irq > 0) { - ret = request_irq(pcidev->irq, v_ADDI_Interrupt, IRQF_SHARED, + ret = request_irq(pcidev->irq, apci1564_interrupt, IRQF_SHARED, dev->board_name, dev); if (ret == 0) dev->irq = pcidev->irq; } - ret = comedi_alloc_subdevices(dev, 3); + ret = comedi_alloc_subdevices(dev, 6); if (ret) return ret; @@ -115,9 +378,7 @@ static int apci1564_auto_attach(struct comedi_device *dev, s->subdev_flags = SDF_READABLE; s->n_chan = 32; s->maxdata = 1; - s->len_chanlist = 32; s->range_table = &range_digital; - s->insn_config = apci1564_di_config; s->insn_bits = apci1564_di_insn_bits; /* Allocate and Initialise DO Subdevice Structures */ @@ -125,15 +386,32 @@ static int apci1564_auto_attach(struct comedi_device *dev, s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITEABLE; s->n_chan = 32; - s->maxdata = 0xffffffff; - s->len_chanlist = 32; + s->maxdata = 1; s->range_table = &range_digital; s->insn_config = apci1564_do_config; s->insn_bits = apci1564_do_insn_bits; - s->insn_read = apci1564_do_read; - /* Allocate and Initialise Timer Subdevice Structures */ + /* Change-Of-State (COS) interrupt subdevice */ s = &dev->subdevices[2]; + if (dev->irq) { + dev->read_subdev = s; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_CMD_READ; + s->n_chan = 1; + s->maxdata = 1; + s->range_table = &range_digital; + s->len_chanlist = 1; + s->insn_config = apci1564_cos_insn_config; + s->insn_bits = apci1564_cos_insn_bits; + s->do_cmdtest = apci1564_cos_cmdtest; + s->do_cmd = apci1564_cos_cmd; + s->cancel = apci1564_cos_cancel; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + /* Allocate and Initialise Timer Subdevice Structures */ + s = &dev->subdevices[3]; s->type = COMEDI_SUBD_TIMER; s->subdev_flags = SDF_WRITEABLE; s->n_chan = 1; @@ -144,19 +422,30 @@ static int apci1564_auto_attach(struct comedi_device *dev, s->insn_read = apci1564_timer_read; s->insn_config = apci1564_timer_config; + /* Initialize the watchdog subdevice */ + s = &dev->subdevices[4]; + ret = addi_watchdog_init(s, devpriv->amcc_iobase + APCI1564_WDOG_REG); + if (ret) + return ret; + + /* Initialize the diagnostic status subdevice */ + s = &dev->subdevices[5]; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 2; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = apci1564_diag_insn_bits; + return 0; } static void apci1564_detach(struct comedi_device *dev) { - struct addi_private *devpriv = dev->private; - - if (devpriv) { - if (dev->iobase) - apci1564_reset(dev); - if (dev->irq) - free_irq(dev->irq, dev); - } + if (dev->iobase) + apci1564_reset(dev); + if (dev->irq) + free_irq(dev->irq, dev); comedi_pci_disable(dev); } diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c index 0cfb12fa1cbc..0b77f1012d47 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3120.c +++ b/drivers/staging/comedi/drivers/addi_apci_3120.c @@ -88,7 +88,7 @@ static int apci3120_auto_attach(struct comedi_device *dev, dev->irq = pcidev->irq; } - devpriv->us_UseDma = ADDI_ENABLE; + devpriv->us_UseDma = 1; /* Allocate DMA buffers */ devpriv->b_DmaDoubleBuffer = 0; @@ -109,7 +109,7 @@ static int apci3120_auto_attach(struct comedi_device *dev, } } if (!devpriv->ul_DmaBufferVirtual[0]) - devpriv->us_UseDma = ADDI_DISABLE; + devpriv->us_UseDma = 0; if (devpriv->ul_DmaBufferVirtual[1]) devpriv->b_DmaDoubleBuffer = 1; @@ -125,13 +125,10 @@ static int apci3120_auto_attach(struct comedi_device *dev, s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; - if (this_board->i_NbrAiChannel) { + if (this_board->i_NbrAiChannel) s->n_chan = this_board->i_NbrAiChannel; - devpriv->b_SingelDiff = 0; - } else { + else s->n_chan = this_board->i_NbrAiChannelDiff; - devpriv->b_SingelDiff = 1; - } s->maxdata = this_board->i_AiMaxdata; s->len_chanlist = this_board->i_AiChannelList; s->range_table = &range_apci3120_ai; diff --git a/drivers/staging/comedi/drivers/addi_apci_3200.c b/drivers/staging/comedi/drivers/addi_apci_3200.c index f0f891a482a3..fe6897eff3db 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3200.c +++ b/drivers/staging/comedi/drivers/addi_apci_3200.c @@ -32,8 +32,8 @@ static const struct addi_board apci3200_boardtypes[] = { [BOARD_APCI3200] = { .pc_DriverName = "apci3200", .i_IorangeBase1 = 256, - .i_PCIEeprom = ADDIDATA_EEPROM, - .pc_EepromChip = ADDIDATA_S5920, + .i_PCIEeprom = 1, + .pc_EepromChip = "S5920", .i_NbrAiChannel = 16, .i_NbrAiChannelDiff = 8, .i_AiChannelList = 16, @@ -58,8 +58,8 @@ static const struct addi_board apci3200_boardtypes[] = { [BOARD_APCI3300] = { .pc_DriverName = "apci3300", .i_IorangeBase1 = 256, - .i_PCIEeprom = ADDIDATA_EEPROM, - .pc_EepromChip = ADDIDATA_S5920, + .i_PCIEeprom = 1, + .pc_EepromChip = "S5920", .i_NbrAiChannelDiff = 8, .i_AiChannelList = 8, .i_AiMaxdata = 0x3ffff, diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c index 49bf1fb840f6..d9594f48d00f 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3501.c +++ b/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -274,7 +274,7 @@ static irqreturn_t apci3501_interrupt(int irq, void *d) ui_Timer_AOWatchdog = inl(dev->iobase + APCI3501_TIMER_IRQ_REG) & 0x1; if ((!ui_Timer_AOWatchdog)) { - comedi_error(dev, "IRQ from unknown source"); + dev_err(dev->class_dev, "IRQ from unknown source\n"); return IRQ_NONE; } diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c index 0532b6cc40e3..0f0c7fa5daa3 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c +++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c @@ -353,7 +353,6 @@ static const struct apci3xxx_boardinfo apci3xxx_boardtypes[] = { }; struct apci3xxx_private { - void __iomem *mmio; unsigned int ai_timer; unsigned char ai_time_base; }; @@ -361,18 +360,17 @@ struct apci3xxx_private { static irqreturn_t apci3xxx_irq_handler(int irq, void *d) { struct comedi_device *dev = d; - struct apci3xxx_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; unsigned int status; unsigned int val; /* Test if interrupt occur */ - status = readl(devpriv->mmio + 16); + status = readl(dev->mmio + 16); if ((status & 0x2) == 0x2) { /* Reset the interrupt */ - writel(status, devpriv->mmio + 16); + writel(status, dev->mmio + 16); - val = readl(devpriv->mmio + 28); + val = readl(dev->mmio + 28); comedi_buf_put(s, val); s->async->events |= COMEDI_CB_EOA; @@ -385,18 +383,14 @@ static irqreturn_t apci3xxx_irq_handler(int irq, void *d) static int apci3xxx_ai_started(struct comedi_device *dev) { - struct apci3xxx_private *devpriv = dev->private; - - if ((readl(devpriv->mmio + 8) & 0x80000) == 0x80000) + if ((readl(dev->mmio + 8) & 0x80000) == 0x80000) return 1; - else - return 0; + return 0; } static int apci3xxx_ai_setup(struct comedi_device *dev, unsigned int chanspec) { - struct apci3xxx_private *devpriv = dev->private; unsigned int chan = CR_CHAN(chanspec); unsigned int range = CR_RANGE(chanspec); unsigned int aref = CR_AREF(chanspec); @@ -407,29 +401,29 @@ static int apci3xxx_ai_setup(struct comedi_device *dev, unsigned int chanspec) return -EBUSY; /* Clear the FIFO */ - writel(0x10000, devpriv->mmio + 12); + writel(0x10000, dev->mmio + 12); /* Get and save the delay mode */ - delay_mode = readl(devpriv->mmio + 4); + delay_mode = readl(dev->mmio + 4); delay_mode &= 0xfffffef0; /* Channel configuration selection */ - writel(delay_mode, devpriv->mmio + 4); + writel(delay_mode, dev->mmio + 4); /* Make the configuration */ val = (range & 3) | ((range >> 2) << 6) | ((aref == AREF_DIFF) << 7); - writel(val, devpriv->mmio + 0); + writel(val, dev->mmio + 0); /* Channel selection */ - writel(delay_mode | 0x100, devpriv->mmio + 4); - writel(chan, devpriv->mmio + 0); + writel(delay_mode | 0x100, dev->mmio + 4); + writel(chan, dev->mmio + 0); /* Restore delay mode */ - writel(delay_mode, devpriv->mmio + 4); + writel(delay_mode, dev->mmio + 4); /* Set the number of sequence to 1 */ - writel(1, devpriv->mmio + 48); + writel(1, dev->mmio + 48); return 0; } @@ -439,10 +433,9 @@ static int apci3xxx_ai_eoc(struct comedi_device *dev, struct comedi_insn *insn, unsigned long context) { - struct apci3xxx_private *devpriv = dev->private; unsigned int status; - status = readl(devpriv->mmio + 20); + status = readl(dev->mmio + 20); if (status & 0x1) return 0; return -EBUSY; @@ -453,7 +446,6 @@ static int apci3xxx_ai_insn_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct apci3xxx_private *devpriv = dev->private; int ret; int i; @@ -463,7 +455,7 @@ static int apci3xxx_ai_insn_read(struct comedi_device *dev, for (i = 0; i < insn->n; i++) { /* Start the conversion */ - writel(0x80000, devpriv->mmio + 8); + writel(0x80000, dev->mmio + 8); /* Wait the EOS */ ret = comedi_timeout(dev, s, insn, apci3xxx_ai_eoc, 0); @@ -471,14 +463,14 @@ static int apci3xxx_ai_insn_read(struct comedi_device *dev, return ret; /* Read the analog value */ - data[i] = readl(devpriv->mmio + 28); + data[i] = readl(dev->mmio + 28); } return insn->n; } static int apci3xxx_ai_ns_to_timer(struct comedi_device *dev, - unsigned int *ns, int round_mode) + unsigned int *ns, unsigned int flags) { const struct apci3xxx_boardinfo *board = comedi_board(dev); struct apci3xxx_private *devpriv = dev->private; @@ -504,7 +496,7 @@ static int apci3xxx_ai_ns_to_timer(struct comedi_device *dev, break; } - switch (round_mode) { + switch (flags & TRIG_ROUND_MASK) { case TRIG_ROUND_NEAREST: default: timer = (*ns + base / 2) / base; @@ -574,7 +566,7 @@ static int apci3xxx_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ arg = cmd->convert_arg; - err |= apci3xxx_ai_ns_to_timer(dev, &arg, cmd->flags & TRIG_ROUND_MASK); + err |= apci3xxx_ai_ns_to_timer(dev, &arg, cmd->flags); err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); if (err) @@ -595,13 +587,13 @@ static int apci3xxx_ai_cmd(struct comedi_device *dev, return ret; /* Set the convert timing unit */ - writel(devpriv->ai_time_base, devpriv->mmio + 36); + writel(devpriv->ai_time_base, dev->mmio + 36); /* Set the convert timing */ - writel(devpriv->ai_timer, devpriv->mmio + 32); + writel(devpriv->ai_timer, dev->mmio + 32); /* Start the conversion */ - writel(0x180000, devpriv->mmio + 8); + writel(0x180000, dev->mmio + 8); return 0; } @@ -617,10 +609,9 @@ static int apci3xxx_ao_eoc(struct comedi_device *dev, struct comedi_insn *insn, unsigned long context) { - struct apci3xxx_private *devpriv = dev->private; unsigned int status; - status = readl(devpriv->mmio + 96); + status = readl(dev->mmio + 96); if (status & 0x100) return 0; return -EBUSY; @@ -631,7 +622,6 @@ static int apci3xxx_ao_insn_write(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct apci3xxx_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); unsigned int range = CR_RANGE(insn->chanspec); int ret; @@ -639,10 +629,10 @@ static int apci3xxx_ao_insn_write(struct comedi_device *dev, for (i = 0; i < insn->n; i++) { /* Set the range selection */ - writel(range, devpriv->mmio + 96); + writel(range, dev->mmio + 96); /* Write the analog value to the selected channel */ - writel((data[i] << 8) | chan, devpriv->mmio + 100); + writel((data[i] << 8) | chan, dev->mmio + 100); /* Wait the end of transfer */ ret = comedi_timeout(dev, s, insn, apci3xxx_ao_eoc, 0); @@ -696,10 +686,9 @@ static int apci3xxx_dio_insn_config(struct comedi_device *dev, /* ignore all other instructions for ports 0 and 1 */ if (chan < 16) return -EINVAL; - else - /* changing any channel in port 2 */ - /* changes the entire port */ - mask = 0xff0000; + + /* changing any channel in port 2 changes the entire port */ + mask = 0xff0000; } ret = comedi_dio_insn_config(dev, s, insn, data, mask); @@ -742,7 +731,6 @@ static int apci3xxx_dio_insn_bits(struct comedi_device *dev, static int apci3xxx_reset(struct comedi_device *dev) { - struct apci3xxx_private *devpriv = dev->private; unsigned int val; int i; @@ -750,18 +738,18 @@ static int apci3xxx_reset(struct comedi_device *dev) disable_irq(dev->irq); /* Clear the start command */ - writel(0, devpriv->mmio + 8); + writel(0, dev->mmio + 8); /* Reset the interrupt flags */ - val = readl(devpriv->mmio + 16); - writel(val, devpriv->mmio + 16); + val = readl(dev->mmio + 16); + writel(val, dev->mmio + 16); /* clear the EOS */ - readl(devpriv->mmio + 20); + readl(dev->mmio + 20); /* Clear the FIFO */ for (i = 0; i < 16; i++) - val = readl(devpriv->mmio + 28); + val = readl(dev->mmio + 28); /* Enable the interrupt */ enable_irq(dev->irq); @@ -796,7 +784,7 @@ static int apci3xxx_auto_attach(struct comedi_device *dev, return ret; dev->iobase = pci_resource_start(pcidev, 2); - devpriv->mmio = pci_ioremap_bar(pcidev, 3); + dev->mmio = pci_ioremap_bar(pcidev, 3); if (pcidev->irq > 0) { ret = request_irq(pcidev->irq, apci3xxx_irq_handler, @@ -920,8 +908,8 @@ static void apci3xxx_detach(struct comedi_device *dev) apci3xxx_reset(dev); if (dev->irq) free_irq(dev->irq, dev); - if (devpriv->mmio) - iounmap(devpriv->mmio); + if (dev->mmio) + iounmap(dev->mmio); } comedi_pci_disable(dev); } diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index 584fd57ecb70..51edfebb952a 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -75,9 +75,6 @@ TODO: #include "plx9052.h" #include "comedi_fc.h" -#define PCI9111_DRIVER_NAME "adl_pci9111" -#define PCI9111_HR_DEVICE_ID 0x9111 - #define PCI9111_FIFO_HALF_SIZE 512 #define PCI9111_AI_ACQUISITION_PERIOD_MIN_NS 10000 @@ -189,68 +186,6 @@ static void pci9111_timer_set(struct comedi_device *dev) i8254_write(timer_base, 1, 1, dev_private->div1); } -enum pci9111_trigger_sources { - software, - timer_pacer, - external -}; - -static void pci9111_trigger_source_set(struct comedi_device *dev, - enum pci9111_trigger_sources source) -{ - int flags; - - /* Read the current trigger mode control bits */ - flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG); - /* Mask off the EITS and TPST bits */ - flags &= 0x9; - - switch (source) { - case software: - break; - - case timer_pacer: - flags |= PCI9111_AI_TRIG_CTRL_TPST; - break; - - case external: - flags |= PCI9111_AI_TRIG_CTRL_ETIS; - break; - } - - outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG); -} - -static void pci9111_pretrigger_set(struct comedi_device *dev, bool pretrigger) -{ - int flags; - - /* Read the current trigger mode control bits */ - flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG); - /* Mask off the PTRG bit */ - flags &= 0x7; - - if (pretrigger) - flags |= PCI9111_AI_TRIG_CTRL_PTRG; - - outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG); -} - -static void pci9111_autoscan_set(struct comedi_device *dev, bool autoscan) -{ - int flags; - - /* Read the current trigger mode control bits */ - flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG); - /* Mask off the ASCAN bit */ - flags &= 0xe; - - if (autoscan) - flags |= PCI9111_AI_TRIG_CTRL_ASCAN; - - outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG); -} - enum pci9111_ISC0_sources { irq_on_eoc, irq_on_fifo_half_full @@ -303,9 +238,8 @@ static int pci9111_ai_cancel(struct comedi_device *dev, plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true, true, false); - pci9111_trigger_source_set(dev, software); - - pci9111_autoscan_set(dev, false); + /* disable A/D triggers (software trigger mode) and auto scan off */ + outb(0, dev->iobase + PCI9111_AI_TRIG_CTRL_REG); pci9111_fifo_reset(dev); @@ -454,20 +388,17 @@ 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 trig = 0; /* Set channel scan limit */ /* PCI9111 allows only scanning from channel 0 to channel n */ /* TODO: handle the case of an external multiplexer */ - if (cmd->chanlist_len > 1) { - outb(cmd->chanlist_len - 1, - dev->iobase + PCI9111_AI_CHANNEL_REG); - pci9111_autoscan_set(dev, true); - } else { - outb(CR_CHAN(cmd->chanlist[0]), - dev->iobase + PCI9111_AI_CHANNEL_REG); - pci9111_autoscan_set(dev, false); - } + if (cmd->chanlist_len > 1) + trig |= PCI9111_AI_TRIG_CTRL_ASCAN; + + outb(last_chan, dev->iobase + PCI9111_AI_CHANNEL_REG); /* Set gain */ /* This is the same gain on every channel */ @@ -484,12 +415,11 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev, /* Set timer pacer */ dev_private->scan_delay = 0; if (cmd->convert_src == TRIG_TIMER) { - pci9111_trigger_source_set(dev, software); + trig |= PCI9111_AI_TRIG_CTRL_TPST; pci9111_timer_set(dev); pci9111_fifo_reset(dev); pci9111_interrupt_source_set(dev, irq_on_fifo_half_full, irq_on_timer_tick); - pci9111_trigger_source_set(dev, timer_pacer); plx9050_interrupt_control(dev_private->lcr_io_base, true, true, false, true, true); @@ -498,14 +428,14 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev, (cmd->convert_arg * cmd->chanlist_len)) - 1; } } else { /* TRIG_EXT */ - pci9111_trigger_source_set(dev, external); + trig |= PCI9111_AI_TRIG_CTRL_ETIS; pci9111_fifo_reset(dev); pci9111_interrupt_source_set(dev, irq_on_fifo_half_full, irq_on_timer_tick); plx9050_interrupt_control(dev_private->lcr_io_base, true, true, false, true, true); - } + outb(trig, dev->iobase + PCI9111_AI_TRIG_CTRL_REG); dev_private->stop_counter *= (1 + dev_private->scan_delay); dev_private->chunk_counter = 0; @@ -630,7 +560,7 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device) /* '0' means FIFO is full, data may have been lost */ if (!(status & PCI9111_AI_STAT_FF_FF)) { spin_unlock_irqrestore(&dev->spinlock, irq_flags); - comedi_error(dev, PCI9111_DRIVER_NAME " fifo overflow"); + dev_dbg(dev->class_dev, "fifo overflow\n"); outb(0, dev->iobase + PCI9111_INT_CLR_REG); async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; cfc_handle_events(dev, s); @@ -771,9 +701,8 @@ static int pci9111_reset(struct comedi_device *dev) plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true, true, false); - pci9111_trigger_source_set(dev, software); - pci9111_pretrigger_set(dev, false); - pci9111_autoscan_set(dev, false); + /* disable A/D triggers (software trigger mode) and auto scan off */ + outb(0, dev->iobase + PCI9111_AI_TRIG_CTRL_REG); /* Reset 8254 chip */ dev_private->div1 = 0; @@ -884,7 +813,7 @@ static int pci9111_pci_probe(struct pci_dev *dev, } static const struct pci_device_id pci9111_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID) }, + { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x9111) }, /* { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID) }, */ { 0 } }; diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 59a65cbc6db9..f30b84e1987b 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -7,61 +7,62 @@ * * Author: Michal Dobes <dobes@tesnet.cz> * -*/ + */ + /* -Driver: adl_pci9118 -Description: Adlink PCI-9118DG, PCI-9118HG, PCI-9118HR -Author: Michal Dobes <dobes@tesnet.cz> -Devices: [ADLink] PCI-9118DG (pci9118dg), PCI-9118HG (pci9118hg), - PCI-9118HR (pci9118hr) -Status: works - -This driver supports AI, AO, DI and DO subdevices. -AI subdevice supports cmd and insn interface, -other subdevices support only insn interface. -For AI: -- If cmd->scan_begin_src=TRIG_EXT then trigger input is TGIN (pin 46). -- If cmd->convert_src=TRIG_EXT then trigger input is EXTTRG (pin 44). -- If cmd->start_src/stop_src=TRIG_EXT then trigger input is TGIN (pin 46). -- It is not necessary to have cmd.scan_end_arg=cmd.chanlist_len but - cmd.scan_end_arg modulo cmd.chanlist_len must by 0. -- If return value of cmdtest is 5 then you've bad channel list - (it isn't possible mixture S.E. and DIFF inputs or bipolar and unipolar - ranges). - -There are some hardware limitations: -a) You cann't use mixture of unipolar/bipoar ranges or differencial/single - ended inputs. -b) DMA transfers must have the length aligned to two samples (32 bit), - so there is some problems if cmd->chanlist_len is odd. This driver tries - bypass this with adding one sample to the end of the every scan and discard - it on output but this cann't be used if cmd->scan_begin_src=TRIG_FOLLOW - and is used flag TRIG_WAKE_EOS, then driver switch to interrupt driven mode - with interrupt after every sample. -c) If isn't used DMA then you can use only mode where - cmd->scan_begin_src=TRIG_FOLLOW. - -Configuration options: - [0] - PCI bus of device (optional) - [1] - PCI slot of device (optional) - If bus/slot is not specified, then first available PCI - card will be used. - [2] - 0= standard 8 DIFF/16 SE channels configuration - n = external multiplexer connected, 1 <= n <= 256 - [3] - 0=autoselect DMA or EOC interrupts operation - 1 = disable DMA mode - 3 = disable DMA and INT, only insn interface will work - [4] - sample&hold signal - card can generate signal for external S&H board - 0 = use SSHO(pin 45) signal is generated in onboard hardware S&H logic - 0 != use ADCHN7(pin 23) signal is generated from driver, number say how - long delay is requested in ns and sign polarity of the hold - (in this case external multiplexor can serve only 128 channels) - [5] - 0=stop measure on all hardware errors - 2 | = ignore ADOR - A/D Overrun status - 8|=ignore Bover - A/D Burst Mode Overrun status - 256|=ignore nFull - A/D FIFO Full status - -*/ + * Driver: adl_pci9118 + * Description: Adlink PCI-9118DG, PCI-9118HG, PCI-9118HR + * Author: Michal Dobes <dobes@tesnet.cz> + * Devices: [ADLink] PCI-9118DG (pci9118dg), PCI-9118HG (pci9118hg), + * PCI-9118HR (pci9118hr) + * Status: works + * + * This driver supports AI, AO, DI and DO subdevices. + * AI subdevice supports cmd and insn interface, + * other subdevices support only insn interface. + * For AI: + * - If cmd->scan_begin_src=TRIG_EXT then trigger input is TGIN (pin 46). + * - If cmd->convert_src=TRIG_EXT then trigger input is EXTTRG (pin 44). + * - If cmd->start_src/stop_src=TRIG_EXT then trigger input is TGIN (pin 46). + * - It is not necessary to have cmd.scan_end_arg=cmd.chanlist_len but + * cmd.scan_end_arg modulo cmd.chanlist_len must by 0. + * - If return value of cmdtest is 5 then you've bad channel list + * (it isn't possible mixture S.E. and DIFF inputs or bipolar and unipolar + * ranges). + * + * There are some hardware limitations: + * a) You cann't use mixture of unipolar/bipoar ranges or differencial/single + * ended inputs. + * b) DMA transfers must have the length aligned to two samples (32 bit), + * so there is some problems if cmd->chanlist_len is odd. This driver tries + * bypass this with adding one sample to the end of the every scan and discard + * it on output but this cann't be used if cmd->scan_begin_src=TRIG_FOLLOW + * and is used flag TRIG_WAKE_EOS, then driver switch to interrupt driven mode + * with interrupt after every sample. + * c) If isn't used DMA then you can use only mode where + * cmd->scan_begin_src=TRIG_FOLLOW. + * + * Configuration options: + * [0] - PCI bus of device (optional) + * [1] - PCI slot of device (optional) + * If bus/slot is not specified, then first available PCI + * card will be used. + * [2] - 0= standard 8 DIFF/16 SE channels configuration + * n = external multiplexer connected, 1 <= n <= 256 + * [3] - 0=autoselect DMA or EOC interrupts operation + * 1 = disable DMA mode + * 3 = disable DMA and INT, only insn interface will work + * [4] - sample&hold signal - card can generate signal for external S&H board + * 0 = use SSHO(pin 45) signal is generated in onboard hardware S&H logic + * 0 != use ADCHN7(pin 23) signal is generated from driver, number say how + * long delay is requested in ns and sign polarity of the hold + * (in this case external multiplexor can serve only 128 channels) + * [5] - 0=stop measure on all hardware errors + * 2 | = ignore ADOR - A/D Overrun status + * 8|=ignore Bover - A/D Burst Mode Overrun status + * 256|=ignore nFull - A/D FIFO Full status + * + */ /* * FIXME @@ -346,7 +347,7 @@ struct pci9118_private { * on external start */ unsigned short ao_data[2]; /* data output buffer */ - char dma_doublebuf; /* we can use double buffering */ + char dma_doublebuf; /* use double buffering */ unsigned int dma_actbuf; /* which buffer is used now */ unsigned short *dmabuf_virt[2]; /* * pointers to begin of @@ -394,12 +395,12 @@ static int check_channel_list(struct comedi_device *dev, /* correct channel and range number check itself comedi/range.c */ if (n_chan < 1) { - comedi_error(dev, "range/channel list is empty!"); + dev_err(dev->class_dev, "range/channel list is empty!\n"); return 0; } if ((frontadd + n_chan + backadd) > s->len_chanlist) { - comedi_error(dev, - "range/channel list is too long for actual configuration!\n"); + dev_err(dev->class_dev, + "range/channel list is too long for actual configuration!\n"); return 0; } @@ -411,23 +412,20 @@ static int check_channel_list(struct comedi_device *dev, for (i = 1; i < n_chan; i++) { /* check S.E/diff */ if ((CR_AREF(chanlist[i]) == AREF_DIFF) != (differencial)) { - comedi_error(dev, - "Differencial and single ended " - "inputs can't be mixtured!"); + 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)) { - comedi_error(dev, - "Bipolar and unipolar ranges " - "can't be mixtured!"); + dev_err(dev->class_dev, + "Bipolar and unipolar ranges can't be mixed!\n"); return 0; } if (!devpriv->usemux && differencial && (CR_CHAN(chanlist[i]) >= this_board->n_aichand)) { - comedi_error(dev, - "If AREF_DIFF is used then is " - "available only first 8 channels!"); + dev_err(dev->class_dev, + "AREF_DIFF is only available for the first 8 channels!\n"); return 0; } } @@ -864,20 +862,21 @@ static char pci9118_decode_error_status(struct comedi_device *dev, struct pci9118_private *devpriv = dev->private; if (m & 0x100) { - comedi_error(dev, "A/D FIFO Full status (Fatal Error!)"); + dev_err(dev->class_dev, + "A/D FIFO Full status (Fatal Error!)\n"); devpriv->ai_maskerr &= ~0x100L; } if (m & 0x008) { - comedi_error(dev, - "A/D Burst Mode Overrun Status (Fatal Error!)"); + dev_err(dev->class_dev, + "A/D Burst Mode Overrun Status (Fatal Error!)\n"); devpriv->ai_maskerr &= ~0x008L; } if (m & 0x004) { - comedi_error(dev, "A/D Over Speed Status (Warning!)"); + dev_err(dev->class_dev, "A/D Over Speed Status (Warning!)\n"); devpriv->ai_maskerr &= ~0x004L; } if (m & 0x002) { - comedi_error(dev, "A/D Overrun Status (Fatal Error!)"); + dev_err(dev->class_dev, "A/D Overrun Status (Fatal Error!)\n"); devpriv->ai_maskerr &= ~0x002L; } if (m & devpriv->ai_maskharderr) { @@ -966,14 +965,14 @@ static void interrupt_pci9118_ai_dma(struct comedi_device *dev, unsigned int next_dma_buf, samplesinbuf, sampls, m; if (int_amcc & MASTER_ABORT_INT) { - comedi_error(dev, "AMCC IRQ - MASTER DMA ABORT!"); + dev_err(dev->class_dev, "AMCC IRQ - MASTER DMA ABORT!\n"); s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; cfc_handle_events(dev, s); return; } if (int_amcc & TARGET_ABORT_INT) { - comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!"); + dev_err(dev->class_dev, "AMCC IRQ - TARGET DMA ABORT!\n"); s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; cfc_handle_events(dev, s); return; @@ -1427,17 +1426,16 @@ static int pci9118_ai_docmd_sampl(struct comedi_device *dev, devpriv->AdControlReg |= AdControl_TmrTr; break; case 2: - comedi_error(dev, "pci9118_ai_docmd_sampl() mode 2 bug!\n"); + dev_err(dev->class_dev, "%s mode 2 bug!\n", __func__); return -EIO; case 3: devpriv->AdControlReg |= AdControl_ExtM; break; case 4: - comedi_error(dev, "pci9118_ai_docmd_sampl() mode 4 bug!\n"); + dev_err(dev->class_dev, "%s mode 4 bug!\n", __func__); return -EIO; default: - comedi_error(dev, - "pci9118_ai_docmd_sampl() mode number bug!\n"); + dev_err(dev->class_dev, "%s mode number bug!\n", __func__); return -EIO; } @@ -1509,7 +1507,7 @@ static int pci9118_ai_docmd_dma(struct comedi_device *dev, devpriv->AdFunctionReg |= AdFunction_Start; break; default: - comedi_error(dev, "pci9118_ai_docmd_dma() mode number bug!\n"); + dev_err(dev->class_dev, "%s mode number bug!\n", __func__); return -EIO; } @@ -1677,9 +1675,8 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) (cmd->convert_src == TRIG_NOW))) { /* double timed action */ if (!devpriv->usedma) { - comedi_error(dev, - "cmd->scan_begin_src=TRIG_TIMER works " - "only with bus mastering!"); + dev_err(dev->class_dev, + "cmd->scan_begin_src=TRIG_TIMER works only with bus mastering!\n"); return -EIO; } diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c index b4ea37704eaf..8b15cbec9891 100644 --- a/drivers/staging/comedi/drivers/adq12b.c +++ b/drivers/staging/comedi/drivers/adq12b.c @@ -79,20 +79,20 @@ If you do not specify any options, they will default to #include "../comedidev.h" /* address scheme (page 2.17 of the manual) */ -#define ADQ12B_SIZE 16 - -#define ADQ12B_CTREG 0x00 -#define ADQ12B_STINR 0x00 -#define ADQ12B_OUTBR 0x04 -#define ADQ12B_ADLOW 0x08 -#define ADQ12B_ADHIG 0x09 -#define ADQ12B_CONT0 0x0c -#define ADQ12B_CONT1 0x0d -#define ADQ12B_CONT2 0x0e -#define ADQ12B_COWORD 0x0f - -/* mask of the bit at STINR to check end of conversion */ -#define ADQ12B_EOC 0x20 +#define ADQ12B_CTREG 0x00 +#define ADQ12B_CTREG_MSKP (1 << 7) /* enable pacer interrupt */ +#define ADQ12B_CTREG_GTP (1 << 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_IN_MASK (0x1f << 0) +#define ADQ12B_OUTBR 0x04 +#define ADQ12B_ADLOW 0x08 +#define ADQ12B_ADHIG 0x09 +#define ADQ12B_TIMER_BASE 0x0c /* available ranges through the PGA gains */ static const struct comedi_lrange range_adq12b_ai_bipolar = { @@ -114,10 +114,7 @@ static const struct comedi_lrange range_adq12b_ai_unipolar = { }; struct adq12b_private { - int unipolar; /* option 2 of comedi_config (1 is iobase) */ - int differential; /* option 3 of comedi_config */ - int last_channel; - int last_range; + unsigned int last_ctreg; }; static int adq12b_ai_eoc(struct comedi_device *dev, @@ -128,50 +125,45 @@ static int adq12b_ai_eoc(struct comedi_device *dev, unsigned char status; status = inb(dev->iobase + ADQ12B_STINR); - if (status & ADQ12B_EOC) + if (status & ADQ12B_STINR_EOC) return 0; return -EBUSY; } -static int adq12b_ai_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data) +static int adq12b_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct adq12b_private *devpriv = dev->private; - int n; - int range, channel; - unsigned char hi, lo, status; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); + unsigned int val; int ret; + int i; /* change channel and range only if it is different from the previous */ - range = CR_RANGE(insn->chanspec); - channel = CR_CHAN(insn->chanspec); - if (channel != devpriv->last_channel || range != devpriv->last_range) { - outb((range << 4) | channel, dev->iobase + ADQ12B_CTREG); + val = ADQ12B_CTREG_RANGE(range) | ADQ12B_CTREG_CHAN(chan); + if (val != devpriv->last_ctreg) { + outb(val, dev->iobase + ADQ12B_CTREG); + devpriv->last_ctreg = val; udelay(50); /* wait for the mux to settle */ } - /* trigger conversion */ - status = inb(dev->iobase + ADQ12B_ADLOW); - - /* convert n samples */ - for (n = 0; n < insn->n; n++) { + val = inb(dev->iobase + ADQ12B_ADLOW); /* trigger A/D */ - /* wait for end of conversion */ + for (i = 0; i < insn->n; i++) { ret = comedi_timeout(dev, s, insn, adq12b_ai_eoc, 0); if (ret) return ret; - /* read data */ - hi = inb(dev->iobase + ADQ12B_ADHIG); - lo = inb(dev->iobase + ADQ12B_ADLOW); - - data[n] = (hi << 8) | lo; + val = inb(dev->iobase + ADQ12B_ADHIG) << 8; + val |= inb(dev->iobase + ADQ12B_ADLOW); /* retriggers A/D */ + data[i] = val; } - /* return the number of samples read/written */ - return n; + return insn->n; } static int adq12b_di_insn_bits(struct comedi_device *dev, @@ -180,7 +172,7 @@ static int adq12b_di_insn_bits(struct comedi_device *dev, { /* only bits 0-4 have information about digital inputs */ - data[1] = (inb(dev->iobase + ADQ12B_STINR) & (0x1f)); + data[1] = (inb(dev->iobase + ADQ12B_STINR) & ADQ12B_STINR_IN_MASK); return insn->n; } @@ -216,7 +208,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; int ret; - ret = comedi_request_region(dev, it->options[0], ADQ12B_SIZE); + ret = comedi_request_region(dev, it->options[0], 0x10); if (ret) return ret; @@ -224,58 +216,44 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (!devpriv) return -ENOMEM; - devpriv->unipolar = it->options[1]; - devpriv->differential = it->options[2]; - /* - * initialize channel and range to -1 so we make sure we - * always write at least once to the CTREG in the instruction - */ - devpriv->last_channel = -1; - devpriv->last_range = -1; + devpriv->last_ctreg = -1; /* force ctreg update */ ret = comedi_alloc_subdevices(dev, 3); if (ret) return ret; + /* Analog Input subdevice */ s = &dev->subdevices[0]; - /* analog input subdevice */ - s->type = COMEDI_SUBD_AI; - if (devpriv->differential) { - s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; - s->n_chan = 8; + s->type = COMEDI_SUBD_AI; + if (it->options[2]) { + s->subdev_flags = SDF_READABLE | SDF_DIFF; + s->n_chan = 8; } else { - s->subdev_flags = SDF_READABLE | SDF_GROUND; - s->n_chan = 16; + s->subdev_flags = SDF_READABLE | SDF_GROUND; + s->n_chan = 16; } + s->maxdata = 0xfff; + s->range_table = it->options[1] ? &range_adq12b_ai_unipolar + : &range_adq12b_ai_bipolar; + s->insn_read = adq12b_ai_insn_read; - if (devpriv->unipolar) - s->range_table = &range_adq12b_ai_unipolar; - else - s->range_table = &range_adq12b_ai_bipolar; - - s->maxdata = 0xfff; - - s->len_chanlist = 4; /* This is the maximum chanlist length that - the board can handle */ - s->insn_read = adq12b_ai_rinsn; - + /* Digital Input subdevice */ s = &dev->subdevices[1]; - /* digital input subdevice */ - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 5; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = adq12b_di_insn_bits; - + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 5; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = adq12b_di_insn_bits; + + /* Digital Output subdevice */ s = &dev->subdevices[2]; - /* digital output subdevice */ - 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 = adq12b_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 = adq12b_do_insn_bits; return 0; } diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 602b7a1e40e6..e19ab958791b 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -722,8 +722,8 @@ static int pci171x_ai_cancel(struct comedi_device *dev, default: devpriv->CntrlReg &= Control_CNT0; devpriv->CntrlReg |= Control_SW; - - outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */ + /* reset any operations */ + outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); pci171x_start_pacer(dev, false); outb(0, dev->iobase + PCI171x_CLRFIFO); outb(0, dev->iobase + PCI171x_CLRINT); @@ -1049,15 +1049,18 @@ static int pci171x_reset(struct comedi_device *dev) struct pci1710_private *devpriv = dev->private; outw(0x30, dev->iobase + PCI171x_CNTCTRL); - devpriv->CntrlReg = Control_SW | Control_CNT0; /* Software trigger, CNT0=external */ - outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */ + /* Software trigger, CNT0=external */ + devpriv->CntrlReg = Control_SW | Control_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 */ pci171x_start_pacer(dev, false); devpriv->da_ranges = 0; if (this_board->n_aochan) { - outb(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); /* set DACs to 0..5V */ - outw(0, dev->iobase + PCI171x_DA1); /* set DA outputs to 0V */ + /* set DACs to 0..5V */ + outb(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); + outw(0, dev->iobase + PCI171x_DA1); /* set DA outputs to 0V */ devpriv->ao_data[0] = 0x0000; if (this_board->n_aochan > 1) { outw(0, dev->iobase + PCI171x_DA2); @@ -1077,10 +1080,11 @@ static int pci171x_reset(struct comedi_device *dev) static int pci1720_reset(struct comedi_device *dev) { struct pci1710_private *devpriv = dev->private; - - outb(Syncont_SC0, dev->iobase + PCI1720_SYNCONT); /* set synchronous output mode */ + /* set synchronous output mode */ + outb(Syncont_SC0, dev->iobase + PCI1720_SYNCONT); devpriv->da_ranges = 0xAA; - outb(devpriv->da_ranges, dev->iobase + PCI1720_RANGE); /* set all ranges to +/-5V */ + /* 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); diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index 07b107d1ab33..1881df459dae 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -161,11 +161,10 @@ static int pci1723_ao_write_winsn(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { struct pci1723_private *devpriv = dev->private; - int n, chan; - chan = CR_CHAN(insn->chanspec); + unsigned int chan = CR_CHAN(insn->chanspec); + int n; for (n = 0; n < insn->n; n++) { - devpriv->ao_data[chan] = data[n]; outw(data[n], dev->iobase + PCI1723_DA(chan)); } diff --git a/drivers/staging/comedi/drivers/adv_pci1724.c b/drivers/staging/comedi/drivers/adv_pci1724.c index af670acb03d8..bc3c34916768 100644 --- a/drivers/staging/comedi/drivers/adv_pci1724.c +++ b/drivers/staging/comedi/drivers/adv_pci1724.c @@ -143,7 +143,8 @@ static int wait_for_dac_idle(struct comedi_device *dev) udelay(1); } if (i == timeout) { - comedi_error(dev, "Timed out waiting for dac to become idle."); + dev_err(dev->class_dev, + "Timed out waiting for dac to become idle\n"); return -EIO; } return 0; @@ -195,8 +196,8 @@ static int ao_readback_insn(struct comedi_device *dev, int i; if (devpriv->ao_value[channel] < 0) { - comedi_error(dev, - "Cannot read back channels which have not yet been written to."); + dev_err(dev->class_dev, + "Cannot read back channels which have not yet been written to\n"); return -EIO; } for (i = 0; i < insn->n; i++) @@ -236,8 +237,8 @@ static int offset_read_insn(struct comedi_device *dev, int i; if (devpriv->offset_value[channel] < 0) { - comedi_error(dev, - "Cannot read back channels which have not yet been written to."); + dev_err(dev->class_dev, + "Cannot read back channels which have not yet been written to\n"); return -EIO; } for (i = 0; i < insn->n; i++) @@ -277,8 +278,8 @@ static int gain_read_insn(struct comedi_device *dev, int i; if (devpriv->gain_value[channel] < 0) { - comedi_error(dev, - "Cannot read back channels which have not yet been written to."); + dev_err(dev->class_dev, + "Cannot read back channels which have not yet been written to\n"); return -EIO; } for (i = 0; i < insn->n; i++) diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index 2d966a87f2e8..b8c7d9145a54 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -592,7 +592,7 @@ static int pci1760_unchecked_mbxrequest(struct comedi_device *dev, return 0; } - comedi_error(dev, "PCI-1760 mailbox request timeout!"); + dev_err(dev->class_dev, "PCI-1760 mailbox request timeout!\n"); return -ETIME; } @@ -610,12 +610,13 @@ static int pci1760_mbxrequest(struct comedi_device *dev, unsigned char *omb, unsigned char *imb) { if (omb[2] == CMD_ClearIMB2) { - comedi_error(dev, - "bug! this function should not be used for CMD_ClearIMB2 command"); + dev_err(dev->class_dev, + "bug! this function should not be used for CMD_ClearIMB2 command\n"); return -EINVAL; } if (inb(dev->iobase + IMB2) == omb[2]) { int retval; + retval = pci1760_clear_imb2(dev); if (retval < 0) return retval; @@ -826,7 +827,7 @@ static int pci_dio_reset(struct comedi_device *dev) outb(0, dev->iobase + PCI1730_DO + 1); outb(0, dev->iobase + PCI1730_IDO); outb(0, dev->iobase + PCI1730_IDO + 1); - /* NO break there! */ + /* fallthrough */ case TYPE_PCI1733: /* disable interrupts */ outb(0, dev->iobase + PCI1730_3_INT_EN); @@ -886,7 +887,7 @@ static int pci_dio_reset(struct comedi_device *dev) outb(0x80, dev->iobase + PCI1753E_ICR1); outb(0x80, dev->iobase + PCI1753E_ICR2); outb(0x80, dev->iobase + PCI1753E_ICR3); - /* NO break there! */ + /* fallthrough */ case TYPE_PCI1753: outb(0x88, dev->iobase + PCI1753_ICR0); /* disable & clear * interrupts */ diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 781104aa533e..7b5ed439c164 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -33,7 +33,6 @@ Configuration Options: #include <linux/module.h> #include "../comedidev.h" -#define AIO_IIRO_16_SIZE 0x08 #define AIO_IIRO_16_RELAY_0_7 0x00 #define AIO_IIRO_16_INPUT_0_7 0x01 #define AIO_IIRO_16_IRQ 0x02 @@ -74,7 +73,7 @@ static int aio_iiro_16_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - ret = comedi_request_region(dev, it->options[0], AIO_IIRO_16_SIZE); + ret = comedi_request_region(dev, it->options[0], 0x8); if (ret) return ret; diff --git a/drivers/staging/comedi/drivers/amcc_s5933.h b/drivers/staging/comedi/drivers/amcc_s5933.h index 2ba736444610..cf6a497b092c 100644 --- a/drivers/staging/comedi/drivers/amcc_s5933.h +++ b/drivers/staging/comedi/drivers/amcc_s5933.h @@ -41,7 +41,7 @@ #define AMCC_OP_REG_MCSR_NVCMD (AMCC_OP_REG_MCSR + 3) /* Command in byte 3 */ #define AMCC_FIFO_DEPTH_DWORD 8 -#define AMCC_FIFO_DEPTH_BYTES (8 * sizeof (u32)) +#define AMCC_FIFO_DEPTH_BYTES (8 * sizeof(u32)) /****************************************************************************/ /* AMCC - PCI Interrupt Control/Status Register */ @@ -52,8 +52,10 @@ #define INTCSR_INBOX_BYTE(x) (((x) & 0x3) << 8) #define INTCSR_INBOX_SELECT(x) (((x) & 0x3) << 10) #define INTCSR_INBOX_FULL_INT 0x1000 /* enable inbox full interrupt */ -#define INTCSR_INBOX_INTR_STATUS 0x20000 /* read, or write clear inbox full interrupt */ -#define INTCSR_INTR_ASSERTED 0x800000 /* read only, interrupt asserted */ +/* read, or write clear inbox full interrupt */ +#define INTCSR_INBOX_INTR_STATUS 0x20000 +/* read only, interrupt asserted */ +#define INTCSR_INTR_ASSERTED 0x800000 /****************************************************************************/ /* AMCC - PCI non-volatile ram command register (byte 3 of master control/status register) */ diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index dc1dee79fc16..17d2e20663cb 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -278,8 +278,7 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) ret = comedi_request_region(dev, it->options[0], thisboard->mainsize); if (ret) return ret; - devpriv->io.u.iobase = dev->iobase; - devpriv->io.regtype = io_regtype; + return amplc_dio200_common_attach(dev, irq, 0); } diff --git a/drivers/staging/comedi/drivers/amplc_dio200.h b/drivers/staging/comedi/drivers/amplc_dio200.h index 43160b9944bb..e0afe2cee2d6 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.h +++ b/drivers/staging/comedi/drivers/amplc_dio200.h @@ -28,18 +28,6 @@ #define DIO200_PCIE_IO_SIZE 0x4000 /* - * Register region. - */ -enum dio200_regtype { no_regtype = 0, io_regtype, mmio_regtype }; -struct dio200_region { - union { - unsigned long iobase; /* I/O base address */ - unsigned char __iomem *membase; /* mapped MMIO base address */ - } u; - enum dio200_regtype regtype; -}; - -/* * Subdevice types. */ enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254, sd_timer }; @@ -75,7 +63,6 @@ struct dio200_board { * Comedi device private data. */ struct dio200_private { - struct dio200_region io; /* Register region */ int intr_sd; }; diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c index 3edaa4028da2..f0d709e0dafc 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_common.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c @@ -151,13 +151,12 @@ static unsigned char dio200_read8(struct comedi_device *dev, unsigned int offset) { const struct dio200_board *thisboard = comedi_board(dev); - struct dio200_private *devpriv = dev->private; offset <<= thisboard->mainshift; - if (devpriv->io.regtype == io_regtype) - return inb(devpriv->io.u.iobase + offset); - else - return readb(devpriv->io.u.membase + offset); + + if (dev->mmio) + return readb(dev->mmio + offset); + return inb(dev->iobase + offset); } /* @@ -167,13 +166,13 @@ static void dio200_write8(struct comedi_device *dev, unsigned int offset, unsigned char val) { const struct dio200_board *thisboard = comedi_board(dev); - struct dio200_private *devpriv = dev->private; offset <<= thisboard->mainshift; - if (devpriv->io.regtype == io_regtype) - outb(val, devpriv->io.u.iobase + offset); + + if (dev->mmio) + writeb(val, dev->mmio + offset); else - writeb(val, devpriv->io.u.membase + offset); + outb(val, dev->iobase + offset); } /* @@ -183,13 +182,12 @@ static unsigned int dio200_read32(struct comedi_device *dev, unsigned int offset) { const struct dio200_board *thisboard = comedi_board(dev); - struct dio200_private *devpriv = dev->private; offset <<= thisboard->mainshift; - if (devpriv->io.regtype == io_regtype) - return inl(devpriv->io.u.iobase + offset); - else - return readl(devpriv->io.u.membase + offset); + + if (dev->mmio) + return readl(dev->mmio + offset); + return inl(dev->iobase + offset); } /* @@ -199,13 +197,13 @@ static void dio200_write32(struct comedi_device *dev, unsigned int offset, unsigned int val) { const struct dio200_board *thisboard = comedi_board(dev); - struct dio200_private *devpriv = dev->private; offset <<= thisboard->mainshift; - if (devpriv->io.regtype == io_regtype) - outl(val, devpriv->io.u.iobase + offset); + + if (dev->mmio) + writel(val, dev->mmio + offset); else - writel(val, devpriv->io.u.membase + offset); + outl(val, dev->iobase + offset); } /* @@ -327,7 +325,7 @@ static void dio200_read_scan_intr(struct comedi_device *dev, /* Error! Stop acquisition. */ dio200_stop_intr(dev, s); s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW; - comedi_error(dev, "buffer overflow"); + dev_err(dev->class_dev, "buffer overflow\n"); } /* Check for end of acquisition. */ @@ -1197,13 +1195,10 @@ EXPORT_SYMBOL_GPL(amplc_dio200_common_attach); void amplc_dio200_common_detach(struct comedi_device *dev) { - const struct dio200_board *thisboard = comedi_board(dev); - struct dio200_private *devpriv = dev->private; - - if (!thisboard || !devpriv) - return; - if (dev->irq) + if (dev->irq) { free_irq(dev->irq, dev); + dev->irq = 0; + } } EXPORT_SYMBOL_GPL(amplc_dio200_common_detach); diff --git a/drivers/staging/comedi/drivers/amplc_dio200_pci.c b/drivers/staging/comedi/drivers/amplc_dio200_pci.c index e0367380b37a..fbf05687347f 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_pci.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_pci.c @@ -228,13 +228,6 @@ #include "amplc_dio200.h" -/* PCI IDs */ -#define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a -#define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b -#define PCI_DEVICE_ID_AMPLICON_PCIE236 0x0011 -#define PCI_DEVICE_ID_AMPLICON_PCIE215 0x0012 -#define PCI_DEVICE_ID_AMPLICON_PCIE296 0x0014 - /* * Board descriptions. */ @@ -394,16 +387,14 @@ static int dio200_pci_auto_attach(struct comedi_device *dev, return -EINVAL; } if (pci_resource_flags(pci_dev, bar) & IORESOURCE_MEM) { - devpriv->io.u.membase = pci_ioremap_bar(pci_dev, bar); - if (!devpriv->io.u.membase) { + dev->mmio = pci_ioremap_bar(pci_dev, bar); + if (!dev->mmio) { dev_err(dev->class_dev, "error! cannot remap registers\n"); return -ENOMEM; } - devpriv->io.regtype = mmio_regtype; } else { - devpriv->io.u.iobase = pci_resource_start(pci_dev, bar); - devpriv->io.regtype = io_regtype; + dev->iobase = pci_resource_start(pci_dev, bar); } switch (context_model) { case pcie215_model: @@ -421,14 +412,9 @@ static int dio200_pci_auto_attach(struct comedi_device *dev, static void dio200_pci_detach(struct comedi_device *dev) { - const struct dio200_board *thisboard = comedi_board(dev); - struct dio200_private *devpriv = dev->private; - - if (!thisboard || !devpriv) - return; amplc_dio200_common_detach(dev); - if (devpriv->io.regtype == mmio_regtype) - iounmap(devpriv->io.u.membase); + if (dev->mmio) + iounmap(dev->mmio); comedi_pci_disable(dev); } @@ -440,22 +426,11 @@ static struct comedi_driver dio200_pci_comedi_driver = { }; static const struct pci_device_id dio200_pci_table[] = { - { - PCI_VDEVICE(AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215), - pci215_model - }, { - PCI_VDEVICE(AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272), - pci272_model - }, { - PCI_VDEVICE(AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE236), - pcie236_model - }, { - PCI_VDEVICE(AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE215), - pcie215_model - }, { - PCI_VDEVICE(AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE296), - pcie296_model - }, + { PCI_VDEVICE(AMPLICON, 0x000b), pci215_model }, + { PCI_VDEVICE(AMPLICON, 0x000a), pci272_model }, + { PCI_VDEVICE(AMPLICON, 0x0011), pcie236_model }, + { PCI_VDEVICE(AMPLICON, 0x0012), pcie215_model }, + { PCI_VDEVICE(AMPLICON, 0x0014), pcie296_model }, {0} }; diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index c9a96ad00559..875cc19cb969 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -1,444 +1,53 @@ /* - comedi/drivers/amplc_pc236.c - Driver for Amplicon PC36AT and PCI236 DIO boards. - - Copyright (C) 2002 MEV Ltd. <http://www.mev.co.uk/> - - 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: amplc_pc236 -Description: Amplicon PC36AT, PCI236 -Author: Ian Abbott <abbotti@mev.co.uk> -Devices: [Amplicon] PC36AT (pc36at), PCI236 (pci236 or amplc_pc236) -Updated: Wed, 01 Apr 2009 15:41:25 +0100 -Status: works - -Configuration options - PC36AT: - [0] - I/O port base address - [1] - IRQ (optional) - -Configuration options - PCI236: - [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 PC36AT ISA board and PCI236 PCI board have a single 8255 appearing -as subdevice 0. - -Subdevice 1 pretends to be a digital input device, but it always returns -0 when read. However, if you run a command with scan_begin_src=TRIG_EXT, -a rising edge on port C bit 3 acts as an external trigger, which can be -used to wake up tasks. This is like the comedi_parport device, but the -only way to physically disable the interrupt on the PC36AT is to remove -the IRQ jumper. If no interrupt is connected, then subdevice 1 is -unused. -*/ - -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/interrupt.h> - -#include "../comedidev.h" - -#include "comedi_fc.h" -#include "8255.h" -#include "plx9052.h" - -#define PC236_DRIVER_NAME "amplc_pc236" - -#define DO_ISA IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) -#define DO_PCI IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) - -/* PCI236 PCI configuration register information */ -#define PCI_DEVICE_ID_AMPLICON_PCI236 0x0009 -#define PCI_DEVICE_ID_INVALID 0xffff - -/* PC36AT / PCI236 registers */ - -#define PC236_IO_SIZE 4 -#define PC236_LCR_IO_SIZE 128 - -/* Disable, and clear, interrupts */ -#define PCI236_INTR_DISABLE (PLX9052_INTCSR_LI1POL | \ - PLX9052_INTCSR_LI2POL | \ - PLX9052_INTCSR_LI1SEL | \ - PLX9052_INTCSR_LI1CLRINT) - -/* Enable, and clear, interrupts */ -#define PCI236_INTR_ENABLE (PLX9052_INTCSR_LI1ENAB | \ - PLX9052_INTCSR_LI1POL | \ - PLX9052_INTCSR_LI2POL | \ - PLX9052_INTCSR_PCIENAB | \ - PLX9052_INTCSR_LI1SEL | \ - PLX9052_INTCSR_LI1CLRINT) - -/* - * Board descriptions for Amplicon PC36AT and PCI236. - */ - -enum pc236_bustype { isa_bustype, pci_bustype }; -enum pc236_model { pc36at_model, pci236_model, anypci_model }; - -struct pc236_board { - const char *name; - unsigned short devid; - enum pc236_bustype bustype; - enum pc236_model model; -}; -static const struct pc236_board pc236_boards[] = { -#if DO_ISA - { - .name = "pc36at", - .bustype = isa_bustype, - .model = pc36at_model, - }, -#endif -#if DO_PCI - { - .name = "pci236", - .devid = PCI_DEVICE_ID_AMPLICON_PCI236, - .bustype = pci_bustype, - .model = pci236_model, - }, - { - .name = PC236_DRIVER_NAME, - .devid = PCI_DEVICE_ID_INVALID, - .bustype = pci_bustype, - .model = anypci_model, /* wildcard */ - }, -#endif -}; - -/* this structure is for data unique to this hardware driver. If - several hardware drivers keep similar information in this structure, - feel free to suggest moving the variable to the struct comedi_device struct. - */ -struct pc236_private { - unsigned long lcr_iobase; /* PLX PCI9052 config registers in PCIBAR1 */ - int enable_irq; -}; - -/* test if ISA supported and this is an ISA board */ -static inline bool is_isa_board(const struct pc236_board *board) -{ - return DO_ISA && board->bustype == isa_bustype; -} - -/* test if PCI supported and this is a PCI board */ -static inline bool is_pci_board(const struct pc236_board *board) -{ - return DO_PCI && board->bustype == pci_bustype; -} - -/* - * This function looks for a board matching the supplied PCI device. - */ -static const struct pc236_board *pc236_find_pci_board(struct pci_dev *pci_dev) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(pc236_boards); i++) - if (is_pci_board(&pc236_boards[i]) && - pci_dev->device == pc236_boards[i].devid) - return &pc236_boards[i]; - return NULL; -} - -/* - * This function looks for a PCI device matching the requested board name, - * bus and slot. - */ -static struct pci_dev *pc236_find_pci_dev(struct comedi_device *dev, - struct comedi_devconfig *it) -{ - const struct pc236_board *thisboard = comedi_board(dev); - struct pci_dev *pci_dev = NULL; - int bus = it->options[0]; - int slot = it->options[1]; - - for_each_pci_dev(pci_dev) { - if (bus || slot) { - if (bus != pci_dev->bus->number || - slot != PCI_SLOT(pci_dev->devfn)) - continue; - } - if (pci_dev->vendor != PCI_VENDOR_ID_AMPLICON) - continue; - - if (thisboard->model == anypci_model) { - /* Wildcard board matches any supported PCI board. */ - const struct pc236_board *foundboard; - - foundboard = pc236_find_pci_board(pci_dev); - if (foundboard == NULL) - continue; - /* Replace wildcard board_ptr. */ - dev->board_ptr = foundboard; - } else { - /* Match specific model name. */ - if (pci_dev->device != thisboard->devid) - continue; - } - return pci_dev; - } - dev_err(dev->class_dev, - "No supported board found! (req. bus %d, slot %d)\n", - bus, slot); - return NULL; -} - -/* - * This function is called to mark the interrupt as disabled (no command - * configured on subdevice 1) and to physically disable the interrupt - * (not possible on the PC36AT, except by removing the IRQ jumper!). + * comedi/drivers/amplc_pc236.c + * Driver for Amplicon PC36AT DIO boards. + * + * Copyright (C) 2002 MEV Ltd. <http://www.mev.co.uk/> + * + * 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. */ -static void pc236_intr_disable(struct comedi_device *dev) -{ - const struct pc236_board *thisboard = comedi_board(dev); - struct pc236_private *devpriv = dev->private; - unsigned long flags; - - spin_lock_irqsave(&dev->spinlock, flags); - devpriv->enable_irq = 0; - if (is_pci_board(thisboard)) - outl(PCI236_INTR_DISABLE, devpriv->lcr_iobase + PLX9052_INTCSR); - spin_unlock_irqrestore(&dev->spinlock, flags); -} - /* - * This function is called to mark the interrupt as enabled (a command - * configured on subdevice 1) and to physically enable the interrupt - * (not possible on the PC36AT, except by (re)connecting the IRQ jumper!). + * Driver: amplc_pc236 + * Description: Amplicon PC36AT + * Author: Ian Abbott <abbotti@mev.co.uk> + * Devices: [Amplicon] PC36AT (pc36at) + * Updated: Fri, 25 Jul 2014 15:32:40 +0000 + * Status: works + * + * Configuration options - PC36AT: + * [0] - I/O port base address + * [1] - IRQ (optional) + * + * The PC36AT board has a single 8255 appearing as subdevice 0. + * + * Subdevice 1 pretends to be a digital input device, but it always returns + * 0 when read. However, if you run a command with scan_begin_src=TRIG_EXT, + * a rising edge on port C bit 3 acts as an external trigger, which can be + * used to wake up tasks. This is like the comedi_parport device, but the + * only way to physically disable the interrupt on the PC36AT is to remove + * the IRQ jumper. If no interrupt is connected, then subdevice 1 is + * unused. */ -static void pc236_intr_enable(struct comedi_device *dev) -{ - const struct pc236_board *thisboard = comedi_board(dev); - struct pc236_private *devpriv = dev->private; - unsigned long flags; - - spin_lock_irqsave(&dev->spinlock, flags); - devpriv->enable_irq = 1; - if (is_pci_board(thisboard)) - outl(PCI236_INTR_ENABLE, devpriv->lcr_iobase + PLX9052_INTCSR); - spin_unlock_irqrestore(&dev->spinlock, flags); -} - -/* - * This function is called when an interrupt occurs to check whether - * the interrupt has been marked as enabled and was generated by the - * board. If so, the function prepares the hardware for the next - * interrupt. - * Returns 0 if the interrupt should be ignored. - */ -static int pc236_intr_check(struct comedi_device *dev) -{ - const struct pc236_board *thisboard = comedi_board(dev); - struct pc236_private *devpriv = dev->private; - int retval = 0; - unsigned long flags; - unsigned int intcsr; - - spin_lock_irqsave(&dev->spinlock, flags); - if (devpriv->enable_irq) { - retval = 1; - if (is_pci_board(thisboard)) { - intcsr = inl(devpriv->lcr_iobase + PLX9052_INTCSR); - if (!(intcsr & PLX9052_INTCSR_LI1STAT)) { - retval = 0; - } else { - /* Clear interrupt and keep it enabled. */ - outl(PCI236_INTR_ENABLE, - devpriv->lcr_iobase + PLX9052_INTCSR); - } - } - } - spin_unlock_irqrestore(&dev->spinlock, flags); - - return retval; -} - -/* - * Input from subdevice 1. - * Copied from the comedi_parport driver. - */ -static int pc236_intr_insn(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data) -{ - data[1] = 0; - return insn->n; -} - -/* - * Subdevice 1 command test. - * Copied from the comedi_parport driver. - */ -static int pc236_intr_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd) -{ - int err = 0; - - /* Step 1 : check if triggers are trivially valid */ - - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE); - if (err) - return 1; - - /* Step 2a : make sure trigger sources are unique */ - /* Step 2b : and mutually compatible */ - - if (err) - return 2; - - /* Step 3: check it arguments are trivially valid */ - - err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); - err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); - err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); - err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); - err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); - - if (err) - return 3; - - /* step 4: ignored */ - - if (err) - return 4; - - return 0; -} - -/* - * Subdevice 1 command. - */ -static int pc236_intr_cmd(struct comedi_device *dev, struct comedi_subdevice *s) -{ - pc236_intr_enable(dev); - - return 0; -} - -/* - * Subdevice 1 cancel command. - */ -static int pc236_intr_cancel(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - pc236_intr_disable(dev); - - return 0; -} - -/* - * Interrupt service routine. - * Based on the comedi_parport driver. - */ -static irqreturn_t pc236_interrupt(int irq, void *d) -{ - struct comedi_device *dev = d; - struct comedi_subdevice *s = dev->read_subdev; - int handled; - - handled = pc236_intr_check(dev); - if (dev->attached && handled) { - comedi_buf_put(s, 0); - s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; - comedi_event(dev, s); - } - return IRQ_RETVAL(handled); -} - -static int pc236_common_attach(struct comedi_device *dev, unsigned long iobase, - unsigned int irq, unsigned long req_irq_flags) -{ - const struct pc236_board *thisboard = comedi_board(dev); - struct comedi_subdevice *s; - int ret; - - dev->board_name = thisboard->name; - dev->iobase = iobase; - - ret = comedi_alloc_subdevices(dev, 2); - if (ret) - return ret; - - s = &dev->subdevices[0]; - /* digital i/o subdevice (8255) */ - ret = subdev_8255_init(dev, s, NULL, iobase); - if (ret) - return ret; - - s = &dev->subdevices[1]; - dev->read_subdev = s; - s->type = COMEDI_SUBD_UNUSED; - pc236_intr_disable(dev); - if (irq) { - if (request_irq(irq, pc236_interrupt, req_irq_flags, - PC236_DRIVER_NAME, dev) >= 0) { - dev->irq = irq; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE | SDF_CMD_READ; - s->n_chan = 1; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = pc236_intr_insn; - s->len_chanlist = 1; - s->do_cmdtest = pc236_intr_cmdtest; - s->do_cmd = pc236_intr_cmd; - s->cancel = pc236_intr_cancel; - } - } - - return 0; -} - -static int pc236_pci_common_attach(struct comedi_device *dev, - struct pci_dev *pci_dev) -{ - struct pc236_private *devpriv = dev->private; - unsigned long iobase; - int ret; - - comedi_set_hw_dev(dev, &pci_dev->dev); +#include <linux/module.h> - ret = comedi_pci_enable(dev); - if (ret) - return ret; +#include "../comedidev.h" - devpriv->lcr_iobase = pci_resource_start(pci_dev, 1); - iobase = pci_resource_start(pci_dev, 2); - return pc236_common_attach(dev, iobase, pci_dev->irq, IRQF_SHARED); -} +#include "amplc_pc236.h" -/* - * Attach is called by the Comedi core to configure the driver - * for a particular board. If you specified a board_name array - * in the driver structure, dev->board_ptr contains that - * address. - */ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - const struct pc236_board *thisboard = comedi_board(dev); struct pc236_private *devpriv; int ret; @@ -446,127 +55,31 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (!devpriv) return -ENOMEM; - /* Process options according to bus type. */ - if (is_isa_board(thisboard)) { - ret = comedi_request_region(dev, it->options[0], PC236_IO_SIZE); - if (ret) - return ret; - - return pc236_common_attach(dev, dev->iobase, it->options[1], 0); - } else if (is_pci_board(thisboard)) { - struct pci_dev *pci_dev; - - pci_dev = pc236_find_pci_dev(dev, it); - if (!pci_dev) - return -EIO; - return pc236_pci_common_attach(dev, pci_dev); - } else { - dev_err(dev->class_dev, PC236_DRIVER_NAME - ": BUG! cannot determine board type!\n"); - return -EINVAL; - } -} - -/* - * The auto_attach hook is called at PCI probe time via - * comedi_pci_auto_config(). dev->board_ptr is NULL on entry. - * There should be a board entry matching the supplied PCI device. - */ -static int pc236_auto_attach(struct comedi_device *dev, - unsigned long context_unused) -{ - struct pci_dev *pci_dev = comedi_to_pci_dev(dev); - struct pc236_private *devpriv; - - if (!DO_PCI) - return -EINVAL; - - dev_info(dev->class_dev, PC236_DRIVER_NAME ": attach pci %s\n", - pci_name(pci_dev)); - - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) - return -ENOMEM; + ret = comedi_request_region(dev, it->options[0], 0x4); + if (ret) + return ret; - dev->board_ptr = pc236_find_pci_board(pci_dev); - if (dev->board_ptr == NULL) { - dev_err(dev->class_dev, "BUG! cannot determine board type!\n"); - return -EINVAL; - } - /* - * Need to 'get' the PCI device to match the 'put' in pc236_detach(). - * TODO: Remove the pci_dev_get() and matching pci_dev_put() once - * support for manual attachment of PCI devices via pc236_attach() - * has been removed. - */ - pci_dev_get(pci_dev); - return pc236_pci_common_attach(dev, pci_dev); + return amplc_pc236_common_attach(dev, dev->iobase, it->options[1], 0); } -static void pc236_detach(struct comedi_device *dev) -{ - const struct pc236_board *thisboard = comedi_board(dev); - - if (!thisboard) - return; - if (dev->iobase) - pc236_intr_disable(dev); - if (is_isa_board(thisboard)) { - comedi_legacy_detach(dev); - } else if (is_pci_board(thisboard)) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (dev->irq) - free_irq(dev->irq, dev); - comedi_pci_disable(dev); - if (pcidev) - pci_dev_put(pcidev); - } -} +static const struct pc236_board pc236_boards[] = { + { + .name = "pc36at", + }, +}; -/* - * The struct comedi_driver structure tells the Comedi core module - * which functions to call to configure/deconfigure (attach/detach) - * the board, and also about the kernel module that contains - * the device code. - */ static struct comedi_driver amplc_pc236_driver = { - .driver_name = PC236_DRIVER_NAME, + .driver_name = "amplc_pc236", .module = THIS_MODULE, .attach = pc236_attach, - .auto_attach = pc236_auto_attach, - .detach = pc236_detach, + .detach = comedi_legacy_detach, .board_name = &pc236_boards[0].name, .offset = sizeof(struct pc236_board), .num_names = ARRAY_SIZE(pc236_boards), }; -#if DO_PCI -static const struct pci_device_id pc236_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI236) }, - {0} -}; - -MODULE_DEVICE_TABLE(pci, pc236_pci_table); - -static int amplc_pc236_pci_probe(struct pci_dev *dev, - const struct pci_device_id *id) -{ - return comedi_pci_auto_config(dev, &lc_pc236_driver, - id->driver_data); -} - -static struct pci_driver amplc_pc236_pci_driver = { - .name = PC236_DRIVER_NAME, - .id_table = pc236_pci_table, - .probe = &lc_pc236_pci_probe, - .remove = comedi_pci_auto_unconfig, -}; - -module_comedi_pci_driver(amplc_pc236_driver, amplc_pc236_pci_driver); -#else module_comedi_driver(amplc_pc236_driver); -#endif MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for Amplicon PC36AT DIO boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_pc236.h b/drivers/staging/comedi/drivers/amplc_pc236.h new file mode 100644 index 000000000000..91d6d9c065b5 --- /dev/null +++ b/drivers/staging/comedi/drivers/amplc_pc236.h @@ -0,0 +1,42 @@ +/* + * comedi/drivers/amplc_pc236.h + * Header for "amplc_pc236", "amplc_pci236" and "amplc_pc236_common". + * + * Copyright (C) 2002-2014 MEV Ltd. <http://www.mev.co.uk/> + * + * 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. + */ + +#ifndef AMPLC_PC236_H_INCLUDED +#define AMPLC_PC236_H_INCLUDED + +#include <linux/types.h> + +struct comedi_device; + +struct pc236_board { + const char *name; + void (*intr_update_cb)(struct comedi_device *dev, bool enable); + bool (*intr_chk_clr_cb)(struct comedi_device *dev); +}; + +struct pc236_private { + unsigned long lcr_iobase; /* PLX PCI9052 config registers in PCIBAR1 */ + bool enable_irq; +}; + +int amplc_pc236_common_attach(struct comedi_device *dev, unsigned long iobase, + unsigned int irq, unsigned long req_irq_flags); + +#endif diff --git a/drivers/staging/comedi/drivers/amplc_pc236_common.c b/drivers/staging/comedi/drivers/amplc_pc236_common.c new file mode 100644 index 000000000000..18e237cca419 --- /dev/null +++ b/drivers/staging/comedi/drivers/amplc_pc236_common.c @@ -0,0 +1,206 @@ +/* + * comedi/drivers/amplc_pc236_common.c + * Common support code for "amplc_pc236" and "amplc_pci236". + * + * Copyright (C) 2002-2014 MEV Ltd. <http://www.mev.co.uk/> + * + * 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. + */ + +#include <linux/module.h> +#include <linux/interrupt.h> + +#include "../comedidev.h" + +#include "amplc_pc236.h" +#include "comedi_fc.h" +#include "8255.h" + +static void pc236_intr_update(struct comedi_device *dev, bool enable) +{ + const struct pc236_board *thisboard = comedi_board(dev); + struct pc236_private *devpriv = dev->private; + unsigned long flags; + + spin_lock_irqsave(&dev->spinlock, flags); + devpriv->enable_irq = enable; + if (thisboard->intr_update_cb) + thisboard->intr_update_cb(dev, enable); + spin_unlock_irqrestore(&dev->spinlock, flags); +} + +/* + * This function is called when an interrupt occurs to check whether + * the interrupt has been marked as enabled and was generated by the + * board. If so, the function prepares the hardware for the next + * interrupt. + * Returns false if the interrupt should be ignored. + */ +static bool pc236_intr_check(struct comedi_device *dev) +{ + const struct pc236_board *thisboard = comedi_board(dev); + 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); + else + retval = true; + } + spin_unlock_irqrestore(&dev->spinlock, flags); + + return retval; +} + +static int pc236_intr_insn(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, + unsigned int *data) +{ + data[1] = 0; + return insn->n; +} + +static int pc236_intr_cmdtest(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + int err = 0; + + /* Step 1 : check if triggers are trivially valid */ + + err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); + err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); + err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW); + err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); + err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE); + + if (err) + return 1; + + /* Step 2a : make sure trigger sources are unique */ + /* Step 2b : and mutually compatible */ + + if (err) + return 2; + + /* Step 3: check it arguments are trivially valid */ + + err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); + err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); + + if (err) + return 3; + + /* step 4: ignored */ + + if (err) + return 4; + + return 0; +} + +static int pc236_intr_cmd(struct comedi_device *dev, struct comedi_subdevice *s) +{ + pc236_intr_update(dev, true); + + return 0; +} + +static int pc236_intr_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + pc236_intr_update(dev, false); + + return 0; +} + +static irqreturn_t pc236_interrupt(int irq, void *d) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->read_subdev; + bool handled; + + handled = pc236_intr_check(dev); + if (dev->attached && handled) { + comedi_buf_put(s, 0); + s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; + comedi_event(dev, s); + } + return IRQ_RETVAL(handled); +} + +int amplc_pc236_common_attach(struct comedi_device *dev, unsigned long iobase, + unsigned int irq, unsigned long req_irq_flags) +{ + struct comedi_subdevice *s; + int ret; + + dev->iobase = iobase; + + ret = comedi_alloc_subdevices(dev, 2); + if (ret) + return ret; + + s = &dev->subdevices[0]; + /* digital i/o subdevice (8255) */ + ret = subdev_8255_init(dev, s, NULL, iobase); + if (ret) + return ret; + + s = &dev->subdevices[1]; + dev->read_subdev = s; + s->type = COMEDI_SUBD_UNUSED; + pc236_intr_update(dev, false); + if (irq) { + if (request_irq(irq, pc236_interrupt, req_irq_flags, + dev->board_name, dev) >= 0) { + dev->irq = irq; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_CMD_READ; + s->n_chan = 1; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pc236_intr_insn; + s->len_chanlist = 1; + s->do_cmdtest = pc236_intr_cmdtest; + s->do_cmd = pc236_intr_cmd; + s->cancel = pc236_intr_cancel; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(amplc_pc236_common_attach); + +static int __init amplc_pc236_common_init(void) +{ + return 0; +} +module_init(amplc_pc236_common_init); + +static void __exit amplc_pc236_common_exit(void) +{ +} +module_exit(amplc_pc236_common_exit); + + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi helper for amplc_pc236 and amplc_pci236"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 7c10d28d2784..f8e551d8fd9e 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -36,10 +36,7 @@ The state of the outputs can be read. #include <linux/module.h> #include "../comedidev.h" -#define PC263_DRIVER_NAME "amplc_pc263" - /* PC263 registers */ -#define PC263_IO_SIZE 2 /* * Board descriptions for Amplicon PC263. @@ -75,7 +72,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; int ret; - ret = comedi_request_region(dev, it->options[0], PC263_IO_SIZE); + ret = comedi_request_region(dev, it->options[0], 0x2); if (ret) return ret; @@ -98,7 +95,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) } static struct comedi_driver amplc_pc263_driver = { - .driver_name = PC263_DRIVER_NAME, + .driver_name = "amplc_pc263", .module = THIS_MODULE, .attach = pc263_attach, .detach = comedi_legacy_detach, diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 339c47c1eb97..45aba1f950fc 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -108,8 +108,6 @@ Caveats: #include "comedi_fc.h" #include "8253.h" -#define DRIVER_NAME "amplc_pci224" - /* * PCI IDs. */ @@ -120,7 +118,6 @@ Caveats: /* * PCI224/234 i/o space 1 (PCIBAR2) registers. */ -#define PCI224_IO1_SIZE 0x20 /* Size of i/o space 1 (8-bit registers) */ #define PCI224_Z2_CT0 0x14 /* 82C54 counter/timer 0 */ #define PCI224_Z2_CT1 0x15 /* 82C54 counter/timer 1 */ #define PCI224_Z2_CT2 0x16 /* 82C54 counter/timer 2 */ @@ -133,7 +130,6 @@ Caveats: /* * PCI224/234 i/o space 2 (PCIBAR3) 16-bit registers. */ -#define PCI224_IO2_SIZE 0x10 /* Size of i/o space 2 (16-bit registers). */ #define PCI224_DACDATA 0x00 /* (w-o) DAC FIFO data. */ #define PCI224_SOFTTRIG 0x00 /* (r-o) DAC software scan trigger. */ #define PCI224_DACCON 0x02 /* (r/w) DAC status/configuration. */ @@ -354,7 +350,7 @@ static const struct pci224_board pci224_boards[] = { .ao_bits = 16, }, { - .name = DRIVER_NAME, + .name = "amplc_pci224", .devid = PCI_DEVICE_ID_INVALID, .model = any_model, /* wildcard */ }, @@ -1206,8 +1202,8 @@ static int pci224_attach_common(struct comedi_device *dev, if (options) { for (n = 2; n < 3 + s->n_chan; n++) { if (options[n] < 0 || options[n] > 1) { - dev_warn(dev->class_dev, DRIVER_NAME - ": warning! bad options[%u]=%d\n", + dev_warn(dev->class_dev, + "warning! bad options[%u]=%d\n", n, options[n]); } } @@ -1237,8 +1233,8 @@ static int pci224_attach_common(struct comedi_device *dev, devpriv->hwrange = hwrange_pci224_external; } else { if (options && options[2] != 0) { - dev_warn(dev->class_dev, DRIVER_NAME - ": warning! bad options[2]=%d\n", + dev_warn(dev->class_dev, + "warning! bad options[2]=%d\n", options[2]); } s->range_table = &range_pci224_internal; @@ -1250,14 +1246,13 @@ static int pci224_attach_common(struct comedi_device *dev, if (irq) { ret = request_irq(irq, pci224_interrupt, IRQF_SHARED, - DRIVER_NAME, dev); + dev->board_name, dev); if (ret < 0) { dev_err(dev->class_dev, "error! unable to allocate irq %u\n", irq); return ret; - } else { - dev->irq = irq; } + dev->irq = irq; } return 0; @@ -1268,7 +1263,7 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct pci224_private *devpriv; struct pci_dev *pci_dev; - dev_info(dev->class_dev, DRIVER_NAME ": attach\n"); + dev_info(dev->class_dev, "attach\n"); devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -1287,8 +1282,7 @@ pci224_auto_attach(struct comedi_device *dev, unsigned long context_unused) struct pci_dev *pci_dev = comedi_to_pci_dev(dev); struct pci224_private *devpriv; - dev_info(dev->class_dev, DRIVER_NAME ": attach pci %s\n", - pci_name(pci_dev)); + dev_info(dev->class_dev, "attach pci %s\n", pci_name(pci_dev)); devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -1297,7 +1291,7 @@ pci224_auto_attach(struct comedi_device *dev, unsigned long context_unused) dev->board_ptr = pci224_find_pci_board(pci_dev); if (dev->board_ptr == NULL) { dev_err(dev->class_dev, - DRIVER_NAME ": BUG! cannot determine board type!\n"); + "BUG! cannot determine board type!\n"); return -EINVAL; } /* diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 3895bc7cb3e3..684275d76e8c 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -1,188 +1,189 @@ - /* - comedi/drivers/amplc_pci230.c - Driver for Amplicon PCI230 and PCI260 Multifunction I/O boards. - - Copyright (C) 2001 Allan Willcox <allanwillcox@ozemail.com.au> - - 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. +/* + * comedi/drivers/amplc_pci230.c + * Driver for Amplicon PCI230 and PCI260 Multifunction I/O boards. + * + * Copyright (C) 2001 Allan Willcox <allanwillcox@ozemail.com.au> + * + * 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: amplc_pci230 -Description: Amplicon PCI230, PCI260 Multifunction I/O boards -Author: Allan Willcox <allanwillcox@ozemail.com.au>, - Steve D Sharples <steve.sharples@nottingham.ac.uk>, - Ian Abbott <abbotti@mev.co.uk> -Updated: Wed, 22 Oct 2008 12:34:49 +0100 -Devices: [Amplicon] PCI230 (pci230 or amplc_pci230), - PCI230+ (pci230+ or amplc_pci230), - PCI260 (pci260 or amplc_pci230), PCI260+ (pci260+ or amplc_pci230) -Status: works - -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. - -Configuring a "amplc_pci230" will match any supported card and it will -choose the best match, picking the "+" models if possible. Configuring -a "pci230" will match a PCI230 or PCI230+ card and it will be treated as -a PCI230. Configuring a "pci260" will match a PCI260 or PCI260+ card -and it will be treated as a PCI260. Configuring a "pci230+" will match -a PCI230+ card. Configuring a "pci260+" will match a PCI260+ card. - -Subdevices: - - PCI230(+) PCI260(+) - --------- --------- - Subdevices 3 1 - 0 AI AI - 1 AO - 2 DIO - -AI Subdevice: - - The AI subdevice has 16 single-ended channels or 8 differential - channels. - - The PCI230 and PCI260 cards have 12-bit resolution. The PCI230+ and - PCI260+ cards have 16-bit resolution. - - For differential mode, use inputs 2N and 2N+1 for channel N (e.g. use - inputs 14 and 15 for channel 7). If the card is physically a PCI230 - or PCI260 then it actually uses a "pseudo-differential" mode where the - inputs are sampled a few microseconds apart. The PCI230+ and PCI260+ - use true differential sampling. Another difference is that if the - card is physically a PCI230 or PCI260, the inverting input is 2N, - whereas for a PCI230+ or PCI260+ the inverting input is 2N+1. So if a - PCI230 is physically replaced by a PCI230+ (or a PCI260 with a - PCI260+) and differential mode is used, the differential inputs need - to be physically swapped on the connector. - - The following input ranges are supported: - - 0 => [-10, +10] V - 1 => [-5, +5] V - 2 => [-2.5, +2.5] V - 3 => [-1.25, +1.25] V - 4 => [0, 10] V - 5 => [0, 5] V - 6 => [0, 2.5] V - -AI Commands: - - +=========+==============+===========+============+==========+ - |start_src|scan_begin_src|convert_src|scan_end_src| stop_src | - +=========+==============+===========+============+==========+ - |TRIG_NOW | TRIG_FOLLOW |TRIG_TIMER | TRIG_COUNT |TRIG_NONE | - |TRIG_INT | |TRIG_EXT(3)| |TRIG_COUNT| - | | |TRIG_INT | | | - | |--------------|-----------| | | - | | TRIG_TIMER(1)|TRIG_TIMER | | | - | | TRIG_EXT(2) | | | | - | | TRIG_INT | | | | - +---------+--------------+-----------+------------+----------+ - - Note 1: If AI command and AO command are used simultaneously, only - one may have scan_begin_src == TRIG_TIMER. - - Note 2: For PCI230 and PCI230+, scan_begin_src == TRIG_EXT uses - DIO channel 16 (pin 49) which will need to be configured as - a digital input. For PCI260+, the EXTTRIG/EXTCONVCLK input - (pin 17) is used instead. For PCI230, scan_begin_src == - TRIG_EXT is not supported. The trigger is a rising edge - on the input. - - Note 3: For convert_src == TRIG_EXT, the EXTTRIG/EXTCONVCLK input - (pin 25 on PCI230(+), pin 17 on PCI260(+)) is used. The - convert_arg value is interpreted as follows: - - convert_arg == (CR_EDGE | 0) => rising edge - convert_arg == (CR_EDGE | CR_INVERT | 0) => falling edge - convert_arg == 0 => falling edge (backwards compatibility) - convert_arg == 1 => rising edge (backwards compatibility) - - All entries in the channel list must use the same analogue reference. - If the analogue reference is not AREF_DIFF (not differential) each - pair of channel numbers (0 and 1, 2 and 3, etc.) must use the same - input range. The input ranges used in the sequence must be all - bipolar (ranges 0 to 3) or all unipolar (ranges 4 to 6). The channel - sequence must consist of 1 or more identical subsequences. Within the - subsequence, channels must be in ascending order with no repeated - channels. For example, the following sequences are valid: 0 1 2 3 - (single valid subsequence), 0 2 3 5 0 2 3 5 (repeated valid - subsequence), 1 1 1 1 (repeated valid subsequence). The following - sequences are invalid: 0 3 2 1 (invalid subsequence), 0 2 3 5 0 2 3 - (incompletely repeated subsequence). Some versions of the PCI230+ and - PCI260+ have a bug that requires a subsequence longer than one entry - long to include channel 0. - -AO Subdevice: - - The AO subdevice has 2 channels with 12-bit resolution. - - The following output ranges are supported: - - 0 => [0, 10] V - 1 => [-10, +10] V - -AO Commands: - - +=========+==============+===========+============+==========+ - |start_src|scan_begin_src|convert_src|scan_end_src| stop_src | - +=========+==============+===========+============+==========+ - |TRIG_INT | TRIG_TIMER(1)| TRIG_NOW | TRIG_COUNT |TRIG_NONE | - | | TRIG_EXT(2) | | |TRIG_COUNT| - | | TRIG_INT | | | | - +---------+--------------+-----------+------------+----------+ - - Note 1: If AI command and AO command are used simultaneously, only - one may have scan_begin_src == TRIG_TIMER. - - Note 2: scan_begin_src == TRIG_EXT is only supported if the card is - configured as a PCI230+ and is only supported on later - versions of the card. As a card configured as a PCI230+ is - not guaranteed to support external triggering, please consider - this support to be a bonus. It uses the EXTTRIG/ EXTCONVCLK - input (PCI230+ pin 25). Triggering will be on the rising edge - unless the CR_INVERT flag is set in scan_begin_arg. - - The channels in the channel sequence must be in ascending order with - no repeats. All entries in the channel sequence must use the same - output range. - -DIO Subdevice: - - The DIO subdevice is a 8255 chip providing 24 DIO channels. The DIO - channels are configurable as inputs or outputs in four groups: - - Port A - channels 0 to 7 - Port B - channels 8 to 15 - Port CL - channels 16 to 19 - Port CH - channels 20 to 23 - - Only mode 0 of the 8255 chip is supported. - - Bit 0 of port C (DIO channel 16) is also used as an external scan - trigger input for AI commands on PCI230 and PCI230+, so would need to - be configured as an input to use it for that purpose. -*/ + * Driver: amplc_pci230 + * Description: Amplicon PCI230, PCI260 Multifunction I/O boards + * Author: Allan Willcox <allanwillcox@ozemail.com.au>, + * Steve D Sharples <steve.sharples@nottingham.ac.uk>, + * Ian Abbott <abbotti@mev.co.uk> + * Updated: Wed, 22 Oct 2008 12:34:49 +0100 + * Devices: [Amplicon] PCI230 (pci230 or amplc_pci230), + * PCI230+ (pci230+ or amplc_pci230), + * PCI260 (pci260 or amplc_pci230), PCI260+ (pci260+ or amplc_pci230) + * Status: works + * + * 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. + * + * Configuring a "amplc_pci230" will match any supported card and it will + * choose the best match, picking the "+" models if possible. Configuring + * a "pci230" will match a PCI230 or PCI230+ card and it will be treated as + * a PCI230. Configuring a "pci260" will match a PCI260 or PCI260+ card + * and it will be treated as a PCI260. Configuring a "pci230+" will match + * a PCI230+ card. Configuring a "pci260+" will match a PCI260+ card. + * + * Subdevices: + * + * PCI230(+) PCI260(+) + * --------- --------- + * Subdevices 3 1 + * 0 AI AI + * 1 AO + * 2 DIO + * + * AI Subdevice: + * + * The AI subdevice has 16 single-ended channels or 8 differential + * channels. + * + * The PCI230 and PCI260 cards have 12-bit resolution. The PCI230+ and + * PCI260+ cards have 16-bit resolution. + * + * For differential mode, use inputs 2N and 2N+1 for channel N (e.g. use + * inputs 14 and 15 for channel 7). If the card is physically a PCI230 + * or PCI260 then it actually uses a "pseudo-differential" mode where the + * inputs are sampled a few microseconds apart. The PCI230+ and PCI260+ + * use true differential sampling. Another difference is that if the + * card is physically a PCI230 or PCI260, the inverting input is 2N, + * whereas for a PCI230+ or PCI260+ the inverting input is 2N+1. So if a + * PCI230 is physically replaced by a PCI230+ (or a PCI260 with a + * PCI260+) and differential mode is used, the differential inputs need + * to be physically swapped on the connector. + * + * The following input ranges are supported: + * + * 0 => [-10, +10] V + * 1 => [-5, +5] V + * 2 => [-2.5, +2.5] V + * 3 => [-1.25, +1.25] V + * 4 => [0, 10] V + * 5 => [0, 5] V + * 6 => [0, 2.5] V + * + * AI Commands: + * + * +=========+==============+===========+============+==========+ + * |start_src|scan_begin_src|convert_src|scan_end_src| stop_src | + * +=========+==============+===========+============+==========+ + * |TRIG_NOW | TRIG_FOLLOW |TRIG_TIMER | TRIG_COUNT |TRIG_NONE | + * |TRIG_INT | |TRIG_EXT(3)| |TRIG_COUNT| + * | | |TRIG_INT | | | + * | |--------------|-----------| | | + * | | TRIG_TIMER(1)|TRIG_TIMER | | | + * | | TRIG_EXT(2) | | | | + * | | TRIG_INT | | | | + * +---------+--------------+-----------+------------+----------+ + * + * Note 1: If AI command and AO command are used simultaneously, only + * one may have scan_begin_src == TRIG_TIMER. + * + * Note 2: For PCI230 and PCI230+, scan_begin_src == TRIG_EXT uses + * DIO channel 16 (pin 49) which will need to be configured as + * a digital input. For PCI260+, the EXTTRIG/EXTCONVCLK input + * (pin 17) is used instead. For PCI230, scan_begin_src == + * TRIG_EXT is not supported. The trigger is a rising edge + * on the input. + * + * Note 3: For convert_src == TRIG_EXT, the EXTTRIG/EXTCONVCLK input + * (pin 25 on PCI230(+), pin 17 on PCI260(+)) is used. The + * convert_arg value is interpreted as follows: + * + * convert_arg == (CR_EDGE | 0) => rising edge + * convert_arg == (CR_EDGE | CR_INVERT | 0) => falling edge + * convert_arg == 0 => falling edge (backwards compatibility) + * convert_arg == 1 => rising edge (backwards compatibility) + * + * All entries in the channel list must use the same analogue reference. + * If the analogue reference is not AREF_DIFF (not differential) each + * pair of channel numbers (0 and 1, 2 and 3, etc.) must use the same + * input range. The input ranges used in the sequence must be all + * bipolar (ranges 0 to 3) or all unipolar (ranges 4 to 6). The channel + * sequence must consist of 1 or more identical subsequences. Within the + * subsequence, channels must be in ascending order with no repeated + * channels. For example, the following sequences are valid: 0 1 2 3 + * (single valid subsequence), 0 2 3 5 0 2 3 5 (repeated valid + * subsequence), 1 1 1 1 (repeated valid subsequence). The following + * sequences are invalid: 0 3 2 1 (invalid subsequence), 0 2 3 5 0 2 3 + * (incompletely repeated subsequence). Some versions of the PCI230+ and + * PCI260+ have a bug that requires a subsequence longer than one entry + * long to include channel 0. + * + * AO Subdevice: + * + * The AO subdevice has 2 channels with 12-bit resolution. + * The following output ranges are supported: + * 0 => [0, 10] V + * 1 => [-10, +10] V + * + * AO Commands: + * + * +=========+==============+===========+============+==========+ + * |start_src|scan_begin_src|convert_src|scan_end_src| stop_src | + * +=========+==============+===========+============+==========+ + * |TRIG_INT | TRIG_TIMER(1)| TRIG_NOW | TRIG_COUNT |TRIG_NONE | + * | | TRIG_EXT(2) | | |TRIG_COUNT| + * | | TRIG_INT | | | | + * +---------+--------------+-----------+------------+----------+ + * + * Note 1: If AI command and AO command are used simultaneously, only + * one may have scan_begin_src == TRIG_TIMER. + * + * Note 2: scan_begin_src == TRIG_EXT is only supported if the card is + * configured as a PCI230+ and is only supported on later + * versions of the card. As a card configured as a PCI230+ is + * not guaranteed to support external triggering, please consider + * this support to be a bonus. It uses the EXTTRIG/ EXTCONVCLK + * input (PCI230+ pin 25). Triggering will be on the rising edge + * unless the CR_INVERT flag is set in scan_begin_arg. + * + * The channels in the channel sequence must be in ascending order with + * no repeats. All entries in the channel sequence must use the same + * output range. + * + * DIO Subdevice: + * + * The DIO subdevice is a 8255 chip providing 24 DIO channels. The DIO + * channels are configurable as inputs or outputs in four groups: + * + * Port A - channels 0 to 7 + * Port B - channels 8 to 15 + * Port CL - channels 16 to 19 + * Port CH - channels 20 to 23 + * + * Only mode 0 of the 8255 chip is supported. + * + * Bit 0 of port C (DIO channel 16) is also used as an external scan + * trigger input for AI commands on PCI230 and PCI230+, so would need to + * be configured as an input to use it for that purpose. + */ + /* -Extra triggered scan functionality, interrupt bug-fix added by Steve Sharples. -Support for PCI230+/260+, more triggered scan functionality, and workarounds -for (or detection of) various hardware problems added by Ian Abbott. -*/ + * Extra triggered scan functionality, interrupt bug-fix added by Steve + * Sharples. Support for PCI230+/260+, more triggered scan functionality, + * and workarounds for (or detection of) various hardware problems added + * by Ian Abbott. + */ #include <linux/module.h> #include <linux/pci.h> @@ -195,15 +196,16 @@ for (or detection of) various hardware problems added by Ian Abbott. #include "8253.h" #include "8255.h" -/* PCI230 PCI configuration register information */ +/* + * PCI230 PCI configuration register information + */ #define PCI_DEVICE_ID_PCI230 0x0000 #define PCI_DEVICE_ID_PCI260 0x0006 #define PCI_DEVICE_ID_INVALID 0xffff -#define PCI230_IO1_SIZE 32 /* Size of I/O space 1 */ -#define PCI230_IO2_SIZE 16 /* Size of I/O space 2 */ - -/* PCI230 i/o space 1 registers. */ +/* + * PCI230 i/o space 1 registers. + */ #define PCI230_PPI_X_BASE 0x00 /* User PPI (82C55) base */ #define PCI230_PPI_X_A 0x00 /* User PPI (82C55) port A */ #define PCI230_PPI_X_B 0x01 /* User PPI (82C55) port B */ @@ -219,7 +221,9 @@ for (or detection of) various hardware problems added by Ian Abbott. #define PCI230_INT_SCE 0x1E /* Interrupt source mask (w) */ #define PCI230_INT_STAT 0x1E /* Interrupt status (r) */ -/* PCI230 i/o space 2 registers. */ +/* + * PCI230 i/o space 2 registers. + */ #define PCI230_DACCON 0x00 /* DAC control */ #define PCI230_DACOUT1 0x02 /* DAC channel 0 (w) */ #define PCI230_DACOUT2 0x04 /* DAC channel 1 (w) (not FIFO mode) */ @@ -242,57 +246,64 @@ for (or detection of) various hardware problems added by Ian Abbott. #define PCI230P2_DACSWTRIG 0x02 /* DAC soft trigger (FIFO mode) (r) */ #define PCI230P2_DACEN 0x06 /* DAC channel enable (FIFO mode) */ -/* Convertor related constants. */ -#define PCI230_DAC_SETTLE 5 /* Analogue output settling time in µs */ - /* (DAC itself is 1µs nominally). */ -#define PCI230_ADC_SETTLE 1 /* Analogue input settling time in µs */ - /* (ADC itself is 1.6µs nominally but we poll - * anyway). */ -#define PCI230_MUX_SETTLE 10 /* ADC MUX settling time in µS */ - /* - 10µs for se, 20µs de. */ - -/* DACCON read-write values. */ -#define PCI230_DAC_OR_UNI (0<<0) /* Output range unipolar */ -#define PCI230_DAC_OR_BIP (1<<0) /* Output range bipolar */ -#define PCI230_DAC_OR_MASK (1<<0) -/* The following applies only if DAC FIFO support is enabled in the EXTFUNC - * register (and only for PCI230+ hardware version 2 onwards). */ -#define PCI230P2_DAC_FIFO_EN (1<<8) /* FIFO enable */ -/* The following apply only if the DAC FIFO is enabled (and only for PCI230+ - * hardware version 2 onwards). */ -#define PCI230P2_DAC_TRIG_NONE (0<<2) /* No trigger */ -#define PCI230P2_DAC_TRIG_SW (1<<2) /* Software trigger trigger */ -#define PCI230P2_DAC_TRIG_EXTP (2<<2) /* EXTTRIG +ve edge trigger */ -#define PCI230P2_DAC_TRIG_EXTN (3<<2) /* EXTTRIG -ve edge trigger */ -#define PCI230P2_DAC_TRIG_Z2CT0 (4<<2) /* CT0-OUT +ve edge trigger */ -#define PCI230P2_DAC_TRIG_Z2CT1 (5<<2) /* CT1-OUT +ve edge trigger */ -#define PCI230P2_DAC_TRIG_Z2CT2 (6<<2) /* CT2-OUT +ve edge trigger */ -#define PCI230P2_DAC_TRIG_MASK (7<<2) -#define PCI230P2_DAC_FIFO_WRAP (1<<7) /* FIFO wraparound mode */ -#define PCI230P2_DAC_INT_FIFO_EMPTY (0<<9) /* FIFO interrupt empty */ -#define PCI230P2_DAC_INT_FIFO_NEMPTY (1<<9) -#define PCI230P2_DAC_INT_FIFO_NHALF (2<<9) /* FIFO intr not half full */ -#define PCI230P2_DAC_INT_FIFO_HALF (3<<9) -#define PCI230P2_DAC_INT_FIFO_NFULL (4<<9) /* FIFO interrupt not full */ -#define PCI230P2_DAC_INT_FIFO_FULL (5<<9) -#define PCI230P2_DAC_INT_FIFO_MASK (7<<9) - -/* DACCON read-only values. */ -#define PCI230_DAC_BUSY (1<<1) /* DAC busy. */ -/* The following apply only if the DAC FIFO is enabled (and only for PCI230+ - * hardware version 2 onwards). */ -#define PCI230P2_DAC_FIFO_UNDERRUN_LATCHED (1<<5) /* Underrun error */ -#define PCI230P2_DAC_FIFO_EMPTY (1<<13) /* FIFO empty */ -#define PCI230P2_DAC_FIFO_FULL (1<<14) /* FIFO full */ -#define PCI230P2_DAC_FIFO_HALF (1<<15) /* FIFO half full */ - -/* DACCON write-only, transient values. */ -/* The following apply only if the DAC FIFO is enabled (and only for PCI230+ - * hardware version 2 onwards). */ -#define PCI230P2_DAC_FIFO_UNDERRUN_CLEAR (1<<5) /* Clear underrun */ -#define PCI230P2_DAC_FIFO_RESET (1<<12) /* FIFO reset */ - -/* PCI230+ hardware version 2 DAC FIFO levels. */ +/* + * DACCON read-write values. + */ +#define PCI230_DAC_OR_UNI (0 << 0) /* Output range unipolar */ +#define PCI230_DAC_OR_BIP (1 << 0) /* Output range bipolar */ +#define PCI230_DAC_OR_MASK (1 << 0) +/* + * The following applies only if DAC FIFO support is enabled in the EXTFUNC + * register (and only for PCI230+ hardware version 2 onwards). + */ +#define PCI230P2_DAC_FIFO_EN (1 << 8) /* FIFO enable */ +/* + * The following apply only if the DAC FIFO is enabled (and only for PCI230+ + * hardware version 2 onwards). + */ +#define PCI230P2_DAC_TRIG_NONE (0 << 2) /* No trigger */ +#define PCI230P2_DAC_TRIG_SW (1 << 2) /* Software trigger trigger */ +#define PCI230P2_DAC_TRIG_EXTP (2 << 2) /* EXTTRIG +ve edge trigger */ +#define PCI230P2_DAC_TRIG_EXTN (3 << 2) /* EXTTRIG -ve edge trigger */ +#define PCI230P2_DAC_TRIG_Z2CT0 (4 << 2) /* CT0-OUT +ve edge trigger */ +#define PCI230P2_DAC_TRIG_Z2CT1 (5 << 2) /* CT1-OUT +ve edge trigger */ +#define PCI230P2_DAC_TRIG_Z2CT2 (6 << 2) /* CT2-OUT +ve edge trigger */ +#define PCI230P2_DAC_TRIG_MASK (7 << 2) +#define PCI230P2_DAC_FIFO_WRAP (1 << 7) /* FIFO wraparound mode */ +#define PCI230P2_DAC_INT_FIFO_EMPTY (0 << 9) /* FIFO interrupt empty */ +#define PCI230P2_DAC_INT_FIFO_NEMPTY (1 << 9) +#define PCI230P2_DAC_INT_FIFO_NHALF (2 << 9) /* FIFO intr not half full */ +#define PCI230P2_DAC_INT_FIFO_HALF (3 << 9) +#define PCI230P2_DAC_INT_FIFO_NFULL (4 << 9) /* FIFO interrupt not full */ +#define PCI230P2_DAC_INT_FIFO_FULL (5 << 9) +#define PCI230P2_DAC_INT_FIFO_MASK (7 << 9) + +/* + * DACCON read-only values. + */ +#define PCI230_DAC_BUSY (1 << 1) /* DAC busy. */ +/* + * The following apply only if the DAC FIFO is enabled (and only for PCI230+ + * hardware version 2 onwards). + */ +#define PCI230P2_DAC_FIFO_UNDERRUN_LATCHED (1 << 5) /* Underrun error */ +#define PCI230P2_DAC_FIFO_EMPTY (1 << 13) /* FIFO empty */ +#define PCI230P2_DAC_FIFO_FULL (1 << 14) /* FIFO full */ +#define PCI230P2_DAC_FIFO_HALF (1 << 15) /* FIFO half full */ + +/* + * DACCON write-only, transient values. + */ +/* + * The following apply only if the DAC FIFO is enabled (and only for PCI230+ + * hardware version 2 onwards). + */ +#define PCI230P2_DAC_FIFO_UNDERRUN_CLEAR (1 << 5) /* Clear underrun */ +#define PCI230P2_DAC_FIFO_RESET (1 << 12) /* FIFO reset */ + +/* + * PCI230+ hardware version 2 DAC FIFO levels. + */ #define PCI230P2_DAC_FIFOLEVEL_HALF 512 #define PCI230P2_DAC_FIFOLEVEL_FULL 1024 /* Free space in DAC FIFO. */ @@ -302,56 +313,62 @@ for (or detection of) various hardware problems added by Ian Abbott. #define PCI230P2_DAC_FIFOROOM_HALFTOFULL 1 #define PCI230P2_DAC_FIFOROOM_FULL 0 -/* ADCCON read/write values. */ -#define PCI230_ADC_TRIG_NONE (0<<0) /* No trigger */ -#define PCI230_ADC_TRIG_SW (1<<0) /* Software trigger trigger */ -#define PCI230_ADC_TRIG_EXTP (2<<0) /* EXTTRIG +ve edge trigger */ -#define PCI230_ADC_TRIG_EXTN (3<<0) /* EXTTRIG -ve edge trigger */ -#define PCI230_ADC_TRIG_Z2CT0 (4<<0) /* CT0-OUT +ve edge trigger */ -#define PCI230_ADC_TRIG_Z2CT1 (5<<0) /* CT1-OUT +ve edge trigger */ -#define PCI230_ADC_TRIG_Z2CT2 (6<<0) /* CT2-OUT +ve edge trigger */ -#define PCI230_ADC_TRIG_MASK (7<<0) -#define PCI230_ADC_IR_UNI (0<<3) /* Input range unipolar */ -#define PCI230_ADC_IR_BIP (1<<3) /* Input range bipolar */ -#define PCI230_ADC_IR_MASK (1<<3) -#define PCI230_ADC_IM_SE (0<<4) /* Input mode single ended */ -#define PCI230_ADC_IM_DIF (1<<4) /* Input mode differential */ -#define PCI230_ADC_IM_MASK (1<<4) -#define PCI230_ADC_FIFO_EN (1<<8) /* FIFO enable */ -#define PCI230_ADC_INT_FIFO_EMPTY (0<<9) -#define PCI230_ADC_INT_FIFO_NEMPTY (1<<9) /* FIFO interrupt not empty */ -#define PCI230_ADC_INT_FIFO_NHALF (2<<9) -#define PCI230_ADC_INT_FIFO_HALF (3<<9) /* FIFO interrupt half full */ -#define PCI230_ADC_INT_FIFO_NFULL (4<<9) -#define PCI230_ADC_INT_FIFO_FULL (5<<9) /* FIFO interrupt full */ -#define PCI230P_ADC_INT_FIFO_THRESH (7<<9) /* FIFO interrupt threshold */ -#define PCI230_ADC_INT_FIFO_MASK (7<<9) - -/* ADCCON write-only, transient values. */ -#define PCI230_ADC_FIFO_RESET (1<<12) /* FIFO reset */ -#define PCI230_ADC_GLOB_RESET (1<<13) /* Global reset */ - -/* ADCCON read-only values. */ -#define PCI230_ADC_BUSY (1<<15) /* ADC busy */ -#define PCI230_ADC_FIFO_EMPTY (1<<12) /* FIFO empty */ -#define PCI230_ADC_FIFO_FULL (1<<13) /* FIFO full */ -#define PCI230_ADC_FIFO_HALF (1<<14) /* FIFO half full */ -#define PCI230_ADC_FIFO_FULL_LATCHED (1<<5) /* Indicates overrun occurred */ - -/* PCI230 ADC FIFO levels. */ +/* + * ADCCON read/write values. + */ +#define PCI230_ADC_TRIG_NONE (0 << 0) /* No trigger */ +#define PCI230_ADC_TRIG_SW (1 << 0) /* Software trigger trigger */ +#define PCI230_ADC_TRIG_EXTP (2 << 0) /* EXTTRIG +ve edge trigger */ +#define PCI230_ADC_TRIG_EXTN (3 << 0) /* EXTTRIG -ve edge trigger */ +#define PCI230_ADC_TRIG_Z2CT0 (4 << 0) /* CT0-OUT +ve edge trigger */ +#define PCI230_ADC_TRIG_Z2CT1 (5 << 0) /* CT1-OUT +ve edge trigger */ +#define PCI230_ADC_TRIG_Z2CT2 (6 << 0) /* CT2-OUT +ve edge trigger */ +#define PCI230_ADC_TRIG_MASK (7 << 0) +#define PCI230_ADC_IR_UNI (0 << 3) /* Input range unipolar */ +#define PCI230_ADC_IR_BIP (1 << 3) /* Input range bipolar */ +#define PCI230_ADC_IR_MASK (1 << 3) +#define PCI230_ADC_IM_SE (0 << 4) /* Input mode single ended */ +#define PCI230_ADC_IM_DIF (1 << 4) /* Input mode differential */ +#define PCI230_ADC_IM_MASK (1 << 4) +#define PCI230_ADC_FIFO_EN (1 << 8) /* FIFO enable */ +#define PCI230_ADC_INT_FIFO_EMPTY (0 << 9) +#define PCI230_ADC_INT_FIFO_NEMPTY (1 << 9) /* FIFO interrupt not empty */ +#define PCI230_ADC_INT_FIFO_NHALF (2 << 9) +#define PCI230_ADC_INT_FIFO_HALF (3 << 9) /* FIFO interrupt half full */ +#define PCI230_ADC_INT_FIFO_NFULL (4 << 9) +#define PCI230_ADC_INT_FIFO_FULL (5 << 9) /* FIFO interrupt full */ +#define PCI230P_ADC_INT_FIFO_THRESH (7 << 9) /* FIFO interrupt threshold */ +#define PCI230_ADC_INT_FIFO_MASK (7 << 9) + +/* + * ADCCON write-only, transient values. + */ +#define PCI230_ADC_FIFO_RESET (1 << 12) /* FIFO reset */ +#define PCI230_ADC_GLOB_RESET (1 << 13) /* Global reset */ + +/* + * ADCCON read-only values. + */ +#define PCI230_ADC_BUSY (1 << 15) /* ADC busy */ +#define PCI230_ADC_FIFO_EMPTY (1 << 12) /* FIFO empty */ +#define PCI230_ADC_FIFO_FULL (1 << 13) /* FIFO full */ +#define PCI230_ADC_FIFO_HALF (1 << 14) /* FIFO half full */ +#define PCI230_ADC_FIFO_FULL_LATCHED (1 << 5) /* FIFO overrun occurred */ + +/* + * PCI230 ADC FIFO levels. + */ #define PCI230_ADC_FIFOLEVEL_HALFFULL 2049 /* Value for FIFO half full */ #define PCI230_ADC_FIFOLEVEL_FULL 4096 /* FIFO size */ -/* Value to write to ADCSWTRIG to trigger ADC conversion in software trigger - * mode. Can be anything. */ -#define PCI230_ADC_CONV 0xffff - -/* PCI230+ EXTFUNC values. */ -#define PCI230P_EXTFUNC_GAT_EXTTRIG (1<<0) - /* Route EXTTRIG pin to external gate inputs. */ +/* + * PCI230+ EXTFUNC values. + */ +/* Route EXTTRIG pin to external gate inputs. */ +#define PCI230P_EXTFUNC_GAT_EXTTRIG (1 << 0) /* PCI230+ hardware version 2 values. */ -#define PCI230P2_EXTFUNC_DACFIFO (1<<1) - /* Allow DAC FIFO to be enabled. */ +/* Allow DAC FIFO to be enabled. */ +#define PCI230P2_EXTFUNC_DACFIFO (1 << 1) /* * Counter/timer clock input configuration sources. @@ -395,19 +412,20 @@ for (or detection of) various hardware problems added by Ian Abbott. * Z2-CT2 Z2-CT1-OUT /Z2-CT0-OUT */ -/* Interrupt enables/status register values. */ +/* + * Interrupt enables/status register values. + */ #define PCI230_INT_DISABLE 0 -#define PCI230_INT_PPI_C0 (1<<0) -#define PCI230_INT_PPI_C3 (1<<1) -#define PCI230_INT_ADC (1<<2) -#define PCI230_INT_ZCLK_CT1 (1<<5) +#define PCI230_INT_PPI_C0 (1 << 0) +#define PCI230_INT_PPI_C3 (1 << 1) +#define PCI230_INT_ADC (1 << 2) +#define PCI230_INT_ZCLK_CT1 (1 << 5) /* For PCI230+ hardware version 2 when DAC FIFO enabled. */ -#define PCI230P2_INT_DAC (1<<4) - -#define PCI230_TEST_BIT(val, n) ((val>>n)&1) - /* Assumes bits numbered with zero offset, ie. 0-15 */ +#define PCI230P2_INT_DAC (1 << 4) -/* (Potentially) shared resources and their owners */ +/* + * (Potentially) shared resources and their owners + */ enum { RES_Z2CT0, /* Z2-CT0 */ RES_Z2CT1, /* Z2-CT1 */ @@ -449,83 +467,70 @@ struct pci230_board { int have_dio; unsigned int min_hwver; /* Minimum hardware version supported. */ }; + static const struct pci230_board pci230_boards[] = { { - .name = "pci230+", - .id = PCI_DEVICE_ID_PCI230, - .ai_chans = 16, - .ai_bits = 16, - .ao_chans = 2, - .ao_bits = 12, - .have_dio = 1, - .min_hwver = 1, - }, + .name = "pci230+", + .id = PCI_DEVICE_ID_PCI230, + .ai_chans = 16, + .ai_bits = 16, + .ao_chans = 2, + .ao_bits = 12, + .have_dio = 1, + .min_hwver = 1, + }, { - .name = "pci260+", - .id = PCI_DEVICE_ID_PCI260, - .ai_chans = 16, - .ai_bits = 16, - .ao_chans = 0, - .ao_bits = 0, - .have_dio = 0, - .min_hwver = 1, - }, + .name = "pci260+", + .id = PCI_DEVICE_ID_PCI260, + .ai_chans = 16, + .ai_bits = 16, + .min_hwver = 1, + }, { - .name = "pci230", - .id = PCI_DEVICE_ID_PCI230, - .ai_chans = 16, - .ai_bits = 12, - .ao_chans = 2, - .ao_bits = 12, - .have_dio = 1, - }, + .name = "pci230", + .id = PCI_DEVICE_ID_PCI230, + .ai_chans = 16, + .ai_bits = 12, + .ao_chans = 2, + .ao_bits = 12, + .have_dio = 1, + }, { - .name = "pci260", - .id = PCI_DEVICE_ID_PCI260, - .ai_chans = 16, - .ai_bits = 12, - .ao_chans = 0, - .ao_bits = 0, - .have_dio = 0, - }, + .name = "pci260", + .id = PCI_DEVICE_ID_PCI260, + .ai_chans = 16, + .ai_bits = 12, + }, { - .name = "amplc_pci230", /* Wildcard matches any above */ - .id = PCI_DEVICE_ID_INVALID, - }, + /* Wildcard matches any above */ + .name = "amplc_pci230", + .id = PCI_DEVICE_ID_INVALID, + }, }; -/* this structure is for data unique to this hardware driver. If - several hardware drivers keep similar information in this structure, - feel free to suggest moving the variable to the struct comedi_device struct. */ struct pci230_private { spinlock_t isr_spinlock; /* Interrupt spin lock */ spinlock_t res_spinlock; /* Shared resources spin lock */ spinlock_t ai_stop_spinlock; /* Spin lock for stopping AI command */ spinlock_t ao_stop_spinlock; /* Spin lock for stopping AO command */ - unsigned long state; /* State flags */ - unsigned long iobase1; /* PCI230's I/O space 1 */ + unsigned long state; /* State flags */ + unsigned long iobase1; /* PCI230's I/O space 1 */ unsigned int ao_readback[2]; /* Used for AO readback */ - unsigned int ai_scan_count; /* Number of analogue input scans - * remaining. */ - unsigned int ai_scan_pos; /* Current position within analogue - * input scan */ - unsigned int ao_scan_count; /* Number of analogue output scans - * remaining. */ - int intr_cpuid; /* ID of CPU running interrupt routine. */ - unsigned short hwver; /* Hardware version (for '+' models). */ - unsigned short adccon; /* ADCCON register value. */ - unsigned short daccon; /* DACCON register value. */ - unsigned short adcfifothresh; /* ADC FIFO programmable interrupt - * level threshold (PCI230+/260+). */ - unsigned short adcg; /* ADCG register value. */ - unsigned char int_en; /* Interrupt enables bits. */ - unsigned char ai_bipolar; /* Set if bipolar input range so we - * know to mangle it. */ - unsigned char ao_bipolar; /* Set if bipolar output range so we - * know to mangle it. */ - unsigned char ier; /* Copy of interrupt enables/status register. */ - unsigned char intr_running; /* Flag set in interrupt routine. */ - unsigned char res_owner[NUM_RESOURCES]; /* Shared resource owners. */ + unsigned int ai_scan_count; /* Number of AI scans remaining */ + unsigned int ai_scan_pos; /* Current position within AI scan */ + unsigned int ao_scan_count; /* Number of AO scans remaining. */ + int intr_cpuid; /* ID of CPU running ISR */ + unsigned short hwver; /* Hardware version (for '+' models) */ + unsigned short adccon; /* ADCCON register value */ + unsigned short daccon; /* DACCON register value */ + unsigned short adcfifothresh; /* ADC FIFO threshold (PCI230+/260+) */ + unsigned short adcg; /* ADCG register value */ + unsigned char int_en; /* Interrupt enable bits */ + unsigned char ai_bipolar; /* Flag AI range is bipolar */ + unsigned char ao_bipolar; /* Flag AO range is bipolar */ + unsigned char ier; /* Copy of interrupt enable register */ + unsigned char intr_running; /* Flag set in interrupt routine */ + unsigned char res_owner[NUM_RESOURCES]; /* Shared resource owners */ }; /* PCI230 clock source periods in ns */ @@ -575,13 +580,16 @@ static unsigned short pci230_ai_read(struct comedi_device *dev) /* Read sample. */ data = inw(dev->iobase + PCI230_ADCDATA); - /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower - * four bits reserved for expansion). */ - /* PCI230+ is 16 bit AI. */ + /* + * PCI230 is 12 bit - stored in upper bits of 16 bit register + * (lower four bits reserved for expansion). PCI230+ is 16 bit AI. + */ data = data >> (16 - thisboard->ai_bits); - /* If a bipolar range was specified, mangle it (twos - * complement->straight binary). */ + /* + * If a bipolar range was specified, mangle it + * (twos complement->straight binary). + */ if (devpriv->ai_bipolar) data ^= 1 << (thisboard->ai_bits - 1); @@ -594,14 +602,17 @@ static inline unsigned short pci230_ao_mangle_datum(struct comedi_device *dev, const struct pci230_board *thisboard = comedi_board(dev); struct pci230_private *devpriv = dev->private; - /* If a bipolar range was specified, mangle it (straight binary->twos - * complement). */ + /* + * If a bipolar range was specified, mangle it + * (straight binary->twos complement). + */ if (devpriv->ao_bipolar) datum ^= 1 << (thisboard->ao_bits - 1); - /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower - * four bits reserved for expansion). */ - /* PCI230+ is also 12 bit AO. */ + /* + * 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); return datum; } @@ -616,10 +627,8 @@ static inline void pci230_ao_write_nofifo(struct comedi_device *dev, devpriv->ao_readback[chan] = datum; /* Write mangled datum to appropriate DACOUT register. */ - outw(pci230_ao_mangle_datum(dev, datum), dev->iobase + (((chan) == 0) - ? PCI230_DACOUT1 - : - PCI230_DACOUT2)); + outw(pci230_ao_mangle_datum(dev, datum), + dev->iobase + (((chan) == 0) ? PCI230_DACOUT1 : PCI230_DACOUT2)); } static inline void pci230_ao_write_fifo(struct comedi_device *dev, @@ -648,18 +657,17 @@ static int get_resources(struct comedi_device *dev, unsigned int res_mask, ok = 1; claimed = 0; spin_lock_irqsave(&devpriv->res_spinlock, irqflags); - for (b = 1, i = 0; (i < NUM_RESOURCES) - && (res_mask != 0); b <<= 1, i++) { - if ((res_mask & b) != 0) { + for (b = 1, i = 0; (i < NUM_RESOURCES) && res_mask; b <<= 1, i++) { + if (res_mask & b) { res_mask &= ~b; if (devpriv->res_owner[i] == OWNER_NONE) { devpriv->res_owner[i] = owner; claimed |= b; } else if (devpriv->res_owner[i] != owner) { - for (b = 1, i = 0; claimed != 0; b <<= 1, i++) { - if ((claimed & b) != 0) { - devpriv->res_owner[i] - = OWNER_NONE; + for (b = 1, i = 0; claimed; b <<= 1, i++) { + if (claimed & b) { + devpriv->res_owner[i] = + OWNER_NONE; claimed &= ~b; } } @@ -687,13 +695,11 @@ static void put_resources(struct comedi_device *dev, unsigned int res_mask, unsigned long irqflags; spin_lock_irqsave(&devpriv->res_spinlock, irqflags); - for (b = 1, i = 0; (i < NUM_RESOURCES) - && (res_mask != 0); b <<= 1, i++) { - if ((res_mask & b) != 0) { + for (b = 1, i = 0; (i < NUM_RESOURCES) && res_mask; b <<= 1, i++) { + if (res_mask & b) { res_mask &= ~b; if (devpriv->res_owner[i] == owner) devpriv->res_owner[i] = OWNER_NONE; - } } spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags); @@ -712,15 +718,14 @@ static inline void put_all_resources(struct comedi_device *dev, } static unsigned int divide_ns(uint64_t ns, unsigned int timebase, - unsigned int round_mode) + unsigned int flags) { uint64_t div; unsigned int rem; div = ns; rem = do_div(div, timebase); - round_mode &= TRIG_ROUND_MASK; - switch (round_mode) { + switch (flags & TRIG_ROUND_MASK) { default: case TRIG_ROUND_NEAREST: div += (rem + (timebase / 2)) / timebase; @@ -734,36 +739,36 @@ static unsigned int divide_ns(uint64_t ns, unsigned int timebase, return div > UINT_MAX ? UINT_MAX : (unsigned int)div; } -/* Given desired period in ns, returns the required internal clock source - * and gets the initial count. */ +/* + * Given desired period in ns, returns the required internal clock source + * and gets the initial count. + */ static unsigned int pci230_choose_clk_count(uint64_t ns, unsigned int *count, - unsigned int round_mode) + unsigned int flags) { unsigned int clk_src, cnt; for (clk_src = CLK_10MHZ;; clk_src++) { - cnt = divide_ns(ns, pci230_timebase[clk_src], round_mode); + cnt = divide_ns(ns, pci230_timebase[clk_src], flags); if ((cnt <= 65536) || (clk_src == CLK_1KHZ)) break; - } *count = cnt; return clk_src; } -static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round) +static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int flags) { unsigned int count; unsigned int clk_src; - clk_src = pci230_choose_clk_count(*ns, &count, round); + clk_src = pci230_choose_clk_count(*ns, &count, flags); *ns = count * pci230_timebase[clk_src]; - return; } static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct, unsigned int mode, uint64_t ns, - unsigned int round) + unsigned int flags) { struct pci230_private *devpriv = dev->private; unsigned int clk_src; @@ -772,7 +777,7 @@ static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct, /* Set mode. */ i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, mode); /* Determine clock source and count. */ - clk_src = pci230_choose_clk_count(ns, &count, round); + clk_src = pci230_choose_clk_count(ns, &count, flags); /* Program clock source. */ outb(CLK_CONFIG(ct, clk_src), devpriv->iobase1 + PCI230_ZCLK_SCE); /* Set initial count. */ @@ -829,7 +834,8 @@ static int pci230_ai_rinsn(struct comedi_device *dev, } } - /* Use Z2-CT2 as a conversion trigger instead of the built-in + /* + * Use Z2-CT2 as a conversion trigger instead of the built-in * software trigger, as otherwise triggering of differential channels * doesn't work properly for some versions of PCI230/260. Also set * FIFO mode because the ADC busy bit only works for software triggers. @@ -842,12 +848,16 @@ static int pci230_ai_rinsn(struct comedi_device *dev, /* Differential. */ gainshift = chan * 2; if (devpriv->hwver == 0) { - /* Original PCI230/260 expects both inputs of the - * differential channel to be enabled. */ + /* + * Original PCI230/260 expects both inputs of the + * differential channel to be enabled. + */ adcen = 3 << gainshift; } else { - /* PCI230+/260+ expects only one input of the - * differential channel to be enabled. */ + /* + * PCI230+/260+ expects only one input of the + * differential channel to be enabled. + */ adcen = 1 << gainshift; } adccon |= PCI230_ADC_IM_DIF; @@ -857,16 +867,18 @@ static int pci230_ai_rinsn(struct comedi_device *dev, gainshift = chan & ~1; adccon |= PCI230_ADC_IM_SE; } - devpriv->adcg = (devpriv->adcg & ~(3 << gainshift)) - | (pci230_ai_gain[range] << gainshift); + devpriv->adcg = (devpriv->adcg & ~(3 << gainshift)) | + (pci230_ai_gain[range] << gainshift); if (devpriv->ai_bipolar) adccon |= PCI230_ADC_IR_BIP; else adccon |= PCI230_ADC_IR_UNI; - /* Enable only this channel in the scan list - otherwise by default - * we'll get one sample from each channel. */ + /* + * Enable only this channel in the scan list - otherwise by default + * we'll get one sample from each channel. + */ outw(adcen, dev->iobase + PCI230_ADCEN); /* Set gain for channel. */ @@ -878,8 +890,10 @@ static int pci230_ai_rinsn(struct comedi_device *dev, /* Convert n samples */ for (n = 0; n < insn->n; n++) { - /* Trigger conversion by toggling Z2-CT2 output (finish with - * output high). */ + /* + * Trigger conversion by toggling Z2-CT2 output + * (finish with output high). + */ i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE0); i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, @@ -913,13 +927,17 @@ static int pci230_ao_winsn(struct comedi_device *dev, chan = CR_CHAN(insn->chanspec); range = CR_RANGE(insn->chanspec); - /* Set range - see analogue output range table; 0 => unipolar 10V, - * 1 => bipolar +/-10V range scale */ + /* + * Set range - see analogue output range table; 0 => unipolar 10V, + * 1 => bipolar +/-10V range scale + */ devpriv->ao_bipolar = pci230_ao_bipolar[range]; outw(range, dev->iobase + PCI230_DACCON); - /* Writing a list of values to an AO channel is probably not - * very useful, but that's how the interface is defined. */ + /* + * 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++) { /* Write value to DAC and store it. */ pci230_ao_write_nofifo(dev, data[i], chan); @@ -929,8 +947,10 @@ static int pci230_ao_winsn(struct comedi_device *dev, return i; } -/* AO subdevices should have a read insn as well as a write insn. - * Usually this means copying a value stored in devpriv. */ +/* + * AO subdevices should have a read insn as well as a write insn. + * Usually this means copying a value stored in devpriv. + */ static int pci230_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -1031,10 +1051,11 @@ static int pci230_ao_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); #define MAX_SPEED_AO 8000 /* 8000 ns => 125 kHz */ +/* + * Comedi limit due to unsigned int cmd. Driver limit = + * 2^16 (16bit * counter) * 1000000ns (1kHz onboard clock) = 65.536s + */ #define MIN_SPEED_AO 4294967295u /* 4294967295ns = 4.29s */ - /*- Comedi limit due to unsigned int cmd. Driver limit - * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard - * clock) = 65.536s */ switch (cmd->scan_begin_src) { case TRIG_TIMER: @@ -1044,17 +1065,21 @@ static int pci230_ao_cmdtest(struct comedi_device *dev, MIN_SPEED_AO); break; case TRIG_EXT: - /* External trigger - for PCI230+ hardware version 2 onwards. */ + /* + * External trigger - for PCI230+ hardware version 2 onwards. + */ /* Trigger number must be 0. */ - if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) { + if (cmd->scan_begin_arg & ~CR_FLAGS_MASK) { cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0, ~CR_FLAGS_MASK); err |= -EINVAL; } - /* The only flags allowed are CR_EDGE and CR_INVERT. The - * CR_EDGE flag is ignored. */ - if ((cmd->scan_begin_arg - & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) { + /* + * The only flags allowed are CR_EDGE and CR_INVERT. + * The CR_EDGE flag is ignored. + */ + if (cmd->scan_begin_arg & + (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) { cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0, CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT)); @@ -1074,14 +1099,11 @@ static int pci230_ao_cmdtest(struct comedi_device *dev, if (err) return 3; - /* Step 4: fix up any arguments. - * "argument conflict" returned by comedilib to user mode process - * if this fails. */ + /* Step 4: fix up any arguments */ if (cmd->scan_begin_src == TRIG_TIMER) { tmp = cmd->scan_begin_arg; - pci230_ns_to_single_timer(&cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); + pci230_ns_to_single_timer(&cmd->scan_begin_arg, cmd->flags); if (tmp != cmd->scan_begin_arg) err++; } @@ -1126,8 +1148,10 @@ static void pci230_ao_stop(struct comedi_device *dev, /* Using DAC FIFO interrupt. */ intsrc = PCI230P2_INT_DAC; } - /* Disable interrupt and wait for interrupt routine to finish running - * unless we are called from the interrupt routine. */ + /* + * Disable interrupt and wait for interrupt routine to finish running + * unless we are called from the interrupt routine. + */ spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); devpriv->int_en &= ~intsrc; while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) { @@ -1140,11 +1164,13 @@ static void pci230_ao_stop(struct comedi_device *dev, } spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); if (devpriv->hwver >= 2) { - /* Using DAC FIFO. Reset FIFO, clear underrun error, - * disable FIFO. */ + /* + * Using DAC FIFO. Reset FIFO, clear underrun error, + * disable FIFO. + */ devpriv->daccon &= PCI230_DAC_OR_MASK; - outw(devpriv->daccon | PCI230P2_DAC_FIFO_RESET - | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR, + outw(devpriv->daccon | PCI230P2_DAC_FIFO_RESET | + PCI230P2_DAC_FIFO_UNDERRUN_CLEAR, dev->iobase + PCI230_DACCON); } /* Release resources. */ @@ -1168,7 +1194,7 @@ static void pci230_handle_ao_nofifo(struct comedi_device *dev, if (ret == 0) { s->async->events |= COMEDI_CB_OVERFLOW; pci230_ao_stop(dev, s); - comedi_error(dev, "AO buffer underrun"); + dev_err(dev->class_dev, "AO buffer underrun\n"); return; } /* Write value to DAC. */ @@ -1215,26 +1241,28 @@ static int pci230_handle_ao_fifo(struct comedi_device *dev, } if (events == 0) { /* Check for FIFO underrun. */ - if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) { - comedi_error(dev, "AO FIFO underrun"); + if (dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) { + dev_err(dev->class_dev, "AO FIFO underrun\n"); events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; } - /* Check for buffer underrun if FIFO less than half full + /* + * Check for buffer underrun if FIFO less than half full * (otherwise there will be loads of "DAC FIFO not half full" - * interrupts). */ - if ((num_scans == 0) - && ((dacstat & PCI230P2_DAC_FIFO_HALF) == 0)) { - comedi_error(dev, "AO buffer underrun"); + * interrupts). + */ + if ((num_scans == 0) && + ((dacstat & PCI230P2_DAC_FIFO_HALF) == 0)) { + dev_err(dev->class_dev, "AO buffer underrun\n"); events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; } } if (events == 0) { /* Determine how much room is in the FIFO (in samples). */ - if ((dacstat & PCI230P2_DAC_FIFO_FULL) != 0) + if (dacstat & PCI230P2_DAC_FIFO_FULL) room = PCI230P2_DAC_FIFOROOM_FULL; - else if ((dacstat & PCI230P2_DAC_FIFO_HALF) != 0) + else if (dacstat & PCI230P2_DAC_FIFO_HALF) room = PCI230P2_DAC_FIFOROOM_HALFTOFULL; - else if ((dacstat & PCI230P2_DAC_FIFO_EMPTY) != 0) + else if (dacstat & PCI230P2_DAC_FIFO_EMPTY) room = PCI230P2_DAC_FIFOROOM_EMPTY; else room = PCI230P2_DAC_FIFOROOM_ONETOHALF; @@ -1257,26 +1285,27 @@ static int pci230_handle_ao_fifo(struct comedi_device *dev, if (cmd->stop_src == TRIG_COUNT) { devpriv->ao_scan_count -= num_scans; if (devpriv->ao_scan_count == 0) { - /* All data for the command has been written + /* + * All data for the command has been written * to FIFO. Set FIFO interrupt trigger level - * to 'empty'. */ - devpriv->daccon = (devpriv->daccon - & - ~PCI230P2_DAC_INT_FIFO_MASK) - | PCI230P2_DAC_INT_FIFO_EMPTY; + * to 'empty'. + */ + devpriv->daccon = + (devpriv->daccon & + ~PCI230P2_DAC_INT_FIFO_MASK) | + PCI230P2_DAC_INT_FIFO_EMPTY; outw(devpriv->daccon, dev->iobase + PCI230_DACCON); } } /* Check if FIFO underrun occurred while writing to FIFO. */ dacstat = inw(dev->iobase + PCI230_DACCON); - if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) { - comedi_error(dev, "AO FIFO underrun"); + if (dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) { + dev_err(dev->class_dev, "AO FIFO underrun\n"); events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; } } - if ((events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW)) - != 0) { + if (events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW)) { /* Stopping AO due to completion or error. */ pci230_ao_stop(dev, s); running = 0; @@ -1294,7 +1323,7 @@ static int pci230_ao_inttrig_scan_begin(struct comedi_device *dev, struct pci230_private *devpriv = dev->private; unsigned long irqflags; - if (trig_num != 0) + if (trig_num) return -EINVAL; spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags); @@ -1373,11 +1402,10 @@ static void pci230_ao_start(struct comedi_device *dev, scantrig = PCI230P2_DAC_TRIG_NONE; break; } - devpriv->daccon = (devpriv->daccon - & ~PCI230P2_DAC_TRIG_MASK) | + devpriv->daccon = + (devpriv->daccon & ~PCI230P2_DAC_TRIG_MASK) | scantrig; outw(devpriv->daccon, dev->iobase + PCI230_DACCON); - } switch (cmd->scan_begin_src) { case TRIG_TIMER: @@ -1441,7 +1469,6 @@ static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* Claim Z2-CT1. */ if (!get_one_resource(dev, RES_Z2CT1, OWNER_AOCMD)) return -EBUSY; - } /* Get number of scans required. */ @@ -1450,8 +1477,10 @@ static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) else /* TRIG_NONE, user calls cancel */ devpriv->ao_scan_count = 0; - /* Set range - see analogue output range table; 0 => unipolar 10V, - * 1 => bipolar +/-10V range scale */ + /* + * Set range - see analogue output range table; 0 => unipolar 10V, + * 1 => bipolar +/-10V range scale + */ range = CR_RANGE(cmd->chanlist[0]); devpriv->ao_bipolar = pci230_ao_bipolar[range]; daccon = devpriv->ao_bipolar ? PCI230_DAC_OR_BIP : PCI230_DAC_OR_UNI; @@ -1474,26 +1503,28 @@ static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * * N.B. DAC FIFO interrupts are currently disabled. */ - daccon |= PCI230P2_DAC_FIFO_EN | PCI230P2_DAC_FIFO_RESET - | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR - | PCI230P2_DAC_TRIG_NONE | PCI230P2_DAC_INT_FIFO_NHALF; + daccon |= PCI230P2_DAC_FIFO_EN | PCI230P2_DAC_FIFO_RESET | + PCI230P2_DAC_FIFO_UNDERRUN_CLEAR | + PCI230P2_DAC_TRIG_NONE | PCI230P2_DAC_INT_FIFO_NHALF; } /* Set DACCON. */ outw(daccon, dev->iobase + PCI230_DACCON); /* Preserve most of DACCON apart from write-only, transient bits. */ - devpriv->daccon = daccon - & ~(PCI230P2_DAC_FIFO_RESET | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR); + devpriv->daccon = daccon & ~(PCI230P2_DAC_FIFO_RESET | + PCI230P2_DAC_FIFO_UNDERRUN_CLEAR); if (cmd->scan_begin_src == TRIG_TIMER) { - /* Set the counter timer 1 to the specified scan frequency. */ - /* cmd->scan_begin_arg is sampling period in ns */ - /* gate it off for now. */ + /* + * Set the counter timer 1 to the specified scan frequency. + * cmd->scan_begin_arg is sampling period in ns. + * Gate it off for now. + */ outb(GAT_CONFIG(1, GAT_GND), devpriv->iobase1 + PCI230_ZGAT_SCE); pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3, cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); + cmd->flags); } /* N.B. cmd->start_src == TRIG_INT */ @@ -1519,8 +1550,8 @@ static int pci230_ai_check_scan_period(struct comedi_cmd *cmd) chanlist_len = 1; min_scan_period = chanlist_len * cmd->convert_arg; - if ((min_scan_period < chanlist_len) - || (min_scan_period < cmd->convert_arg)) { + if ((min_scan_period < chanlist_len) || + (min_scan_period < cmd->convert_arg)) { /* Arithmetic overflow. */ min_scan_period = UINT_MAX; err++; @@ -1570,10 +1601,10 @@ static int pci230_ai_check_chanlist(struct comedi_device *dev, if (subseq_len > 0 && cmd->chanlist[i % subseq_len] != chanspec) { - dev_dbg(dev->class_dev, - "%s: channel numbers must increase or sequence must repeat exactly\n", - __func__); - return -EINVAL; + dev_dbg(dev->class_dev, + "%s: channel numbers must increase or sequence must repeat exactly\n", + __func__); + return -EINVAL; } if (aref != prev_aref) { @@ -1607,7 +1638,7 @@ static int pci230_ai_check_chanlist(struct comedi_device *dev, if (subseq_len == 0) subseq_len = cmd->chanlist_len; - if ((cmd->chanlist_len % subseq_len) != 0) { + if (cmd->chanlist_len % subseq_len) { dev_dbg(dev->class_dev, "%s: sequence must repeat exactly\n", __func__); return -EINVAL; @@ -1625,7 +1656,7 @@ static int pci230_ai_check_chanlist(struct comedi_device *dev, * the bug, but the second one does, and we can't tell them apart! */ if (devpriv->hwver > 0 && devpriv->hwver < 4) { - if (subseq_len > 1 && CR_CHAN(cmd->chanlist[0]) != 0) { + if (subseq_len > 1 && CR_CHAN(cmd->chanlist[0])) { dev_info(dev->class_dev, "amplc_pci230: ai_cmdtest: Buggy PCI230+/260+ h/w version %u requires first channel of multi-channel sequence to be 0 (corrected in h/w version 4)\n", devpriv->hwver); @@ -1680,8 +1711,8 @@ static int pci230_ai_cmdtest(struct comedi_device *dev, * If scan_begin_src is not TRIG_FOLLOW, then a monostable will be * set up to generate a fixed number of timed conversion pulses. */ - if ((cmd->scan_begin_src != TRIG_FOLLOW) - && (cmd->convert_src != TRIG_TIMER)) + if ((cmd->scan_begin_src != TRIG_FOLLOW) && + (cmd->convert_src != TRIG_TIMER)) err |= -EINVAL; if (err) @@ -1694,17 +1725,20 @@ static int pci230_ai_cmdtest(struct comedi_device *dev, #define MAX_SPEED_AI_SE 3200 /* PCI230 SE: 3200 ns => 312.5 kHz */ #define MAX_SPEED_AI_DIFF 8000 /* PCI230 DIFF: 8000 ns => 125 kHz */ #define MAX_SPEED_AI_PLUS 4000 /* PCI230+: 4000 ns => 250 kHz */ +/* + * Comedi limit due to unsigned int cmd. Driver limit = + * 2^16 (16bit * counter) * 1000000ns (1kHz onboard clock) = 65.536s + */ #define MIN_SPEED_AI 4294967295u /* 4294967295ns = 4.29s */ - /*- Comedi limit due to unsigned int cmd. Driver limit - * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard - * clock) = 65.536s */ if (cmd->convert_src == TRIG_TIMER) { unsigned int max_speed_ai; if (devpriv->hwver == 0) { - /* PCI230 or PCI260. Max speed depends whether - * single-ended or pseudo-differential. */ + /* + * PCI230 or PCI260. Max speed depends whether + * single-ended or pseudo-differential. + */ if (cmd->chanlist && (cmd->chanlist_len > 0)) { /* Peek analogue reference of first channel. */ if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF) @@ -1734,17 +1768,19 @@ static int pci230_ai_cmdtest(struct comedi_device *dev, * convert_arg == (CR_EDGE | CR_INVERT | 0) * => trigger on -ve edge. */ - if ((cmd->convert_arg & CR_FLAGS_MASK) != 0) { + if (cmd->convert_arg & CR_FLAGS_MASK) { /* Trigger number must be 0. */ - if ((cmd->convert_arg & ~CR_FLAGS_MASK) != 0) { + if (cmd->convert_arg & ~CR_FLAGS_MASK) { cmd->convert_arg = COMBINE(cmd->convert_arg, 0, ~CR_FLAGS_MASK); err |= -EINVAL; } - /* The only flags allowed are CR_INVERT and CR_EDGE. - * CR_EDGE is required. */ - if ((cmd->convert_arg & (CR_FLAGS_MASK & ~CR_INVERT)) - != CR_EDGE) { + /* + * The only flags allowed are CR_INVERT and CR_EDGE. + * CR_EDGE is required. + */ + if ((cmd->convert_arg & + (CR_FLAGS_MASK & ~CR_INVERT)) != CR_EDGE) { /* Set CR_EDGE, preserve CR_INVERT. */ cmd->convert_arg = COMBINE(cmd->start_arg, (CR_EDGE | 0), @@ -1753,9 +1789,11 @@ static int pci230_ai_cmdtest(struct comedi_device *dev, err |= -EINVAL; } } else { - /* Backwards compatibility with previous versions. */ - /* convert_arg == 0 => trigger on -ve edge. */ - /* convert_arg == 1 => trigger on +ve edge. */ + /* + * Backwards compatibility with previous versions: + * convert_arg == 0 => trigger on -ve edge. + * convert_arg == 1 => trigger on +ve edge. + */ err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 1); } } else { @@ -1768,16 +1806,18 @@ static int pci230_ai_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); if (cmd->scan_begin_src == TRIG_EXT) { - /* external "trigger" to begin each scan + /* + * external "trigger" to begin each scan: * scan_begin_arg==0 => use PPC0 input -> gate of CT0 -> gate - * of CT2 (sample convert trigger is CT2) */ - if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) { + * of CT2 (sample convert trigger is CT2) + */ + if (cmd->scan_begin_arg & ~CR_FLAGS_MASK) { cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0, ~CR_FLAGS_MASK); err |= -EINVAL; } /* The only flag allowed is CR_EDGE, which is ignored. */ - if ((cmd->scan_begin_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) { + if (cmd->scan_begin_arg & CR_FLAGS_MASK & ~CR_EDGE) { cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0, CR_FLAGS_MASK & ~CR_EDGE); err |= -EINVAL; @@ -1794,14 +1834,11 @@ static int pci230_ai_cmdtest(struct comedi_device *dev, if (err) return 3; - /* Step 4: fix up any arguments. - * "argument conflict" returned by comedilib to user mode process - * if this fails. */ + /* Step 4: fix up any arguments */ if (cmd->convert_src == TRIG_TIMER) { tmp = cmd->convert_arg; - pci230_ns_to_single_timer(&cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); + pci230_ns_to_single_timer(&cmd->convert_arg, cmd->flags); if (tmp != cmd->convert_arg) err++; } @@ -1809,8 +1846,7 @@ static int pci230_ai_cmdtest(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER) { /* N.B. cmd->convert_arg is also TRIG_TIMER */ tmp = cmd->scan_begin_arg; - pci230_ns_to_single_timer(&cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); + pci230_ns_to_single_timer(&cmd->scan_begin_arg, cmd->flags); if (!pci230_ai_check_scan_period(cmd)) { /* Was below minimum required. Round up. */ pci230_ns_to_single_timer(&cmd->scan_begin_arg, @@ -1844,7 +1880,7 @@ static void pci230_ai_update_fifo_trigger_level(struct comedi_device *dev, unsigned short triglev; unsigned short adccon; - if ((cmd->flags & TRIG_WAKE_EOS) != 0) { + if (cmd->flags & TRIG_WAKE_EOS) { /* Wake at end of scan. */ wake = scanlen - devpriv->ai_scan_pos; } else { @@ -1853,8 +1889,8 @@ static void pci230_ai_update_fifo_trigger_level(struct comedi_device *dev, scanlen >= PCI230_ADC_FIFOLEVEL_HALFFULL) { wake = PCI230_ADC_FIFOLEVEL_HALFFULL; } else { - wake = (devpriv->ai_scan_count * scanlen) - - devpriv->ai_scan_pos; + wake = (devpriv->ai_scan_count * scanlen) - + devpriv->ai_scan_pos; } } if (wake >= PCI230_ADC_FIFOLEVEL_HALFFULL) { @@ -1885,27 +1921,30 @@ static int pci230_ai_inttrig_convert(struct comedi_device *dev, struct pci230_private *devpriv = dev->private; unsigned long irqflags; - if (trig_num != 0) + if (trig_num) return -EINVAL; spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags); if (test_bit(AI_CMD_STARTED, &devpriv->state)) { unsigned int delayus; - /* Trigger conversion by toggling Z2-CT2 output. Finish - * with output high. */ + /* + * Trigger conversion by toggling Z2-CT2 output. + * Finish with output high. + */ i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE0); i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE1); - /* Delay. Should driver be responsible for this? An + /* + * Delay. Should driver be responsible for this? An * alternative would be to wait until conversion is complete, * but we can't tell when it's complete because the ADC busy * bit has a different meaning when FIFO enabled (and when - * FIFO not enabled, it only works for software triggers). */ - if (((devpriv->adccon & PCI230_ADC_IM_MASK) - == PCI230_ADC_IM_DIF) - && (devpriv->hwver == 0)) { + * FIFO not enabled, it only works for software triggers). + */ + if (((devpriv->adccon & PCI230_ADC_IM_MASK) == + PCI230_ADC_IM_DIF) && (devpriv->hwver == 0)) { /* PCI230/260 in differential mode */ delayus = 8; } else { @@ -1929,7 +1968,7 @@ static int pci230_ai_inttrig_scan_begin(struct comedi_device *dev, unsigned long irqflags; unsigned char zgat; - if (trig_num != 0) + if (trig_num) return -EINVAL; spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags); @@ -1968,8 +2007,10 @@ static void pci230_ai_stop(struct comedi_device *dev, pci230_cancel_ct(dev, 0); } spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); - /* Disable ADC interrupt and wait for interrupt routine to finish - * running unless we are called from the interrupt routine. */ + /* + * Disable ADC interrupt and wait for interrupt routine to finish + * running unless we are called from the interrupt routine. + */ devpriv->int_en &= ~PCI230_INT_ADC; while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) { spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); @@ -1980,10 +2021,12 @@ static void pci230_ai_stop(struct comedi_device *dev, outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE); } spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); - /* Reset FIFO, disable FIFO and set start conversion source to none. - * Keep se/diff and bip/uni settings */ - devpriv->adccon = (devpriv->adccon & (PCI230_ADC_IR_MASK - | PCI230_ADC_IM_MASK)) | + /* + * Reset FIFO, disable FIFO and set start conversion source to none. + * Keep se/diff and bip/uni settings. + */ + devpriv->adccon = + (devpriv->adccon & (PCI230_ADC_IR_MASK | PCI230_ADC_IM_MASK)) | PCI230_ADC_TRIG_NONE; outw(devpriv->adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON); @@ -2014,8 +2057,10 @@ static void pci230_ai_start(struct comedi_device *dev, outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE); spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); - /* Update conversion trigger source which is currently set - * to CT2 output, which is currently stuck high. */ + /* + * Update conversion trigger source which is currently set + * to CT2 output, which is currently stuck high. + */ switch (cmd->convert_src) { default: conv = PCI230_ADC_TRIG_NONE; @@ -2025,7 +2070,7 @@ static void pci230_ai_start(struct comedi_device *dev, conv = PCI230_ADC_TRIG_Z2CT2; break; case TRIG_EXT: - if ((cmd->convert_arg & CR_EDGE) != 0) { + if (cmd->convert_arg & CR_EDGE) { if ((cmd->convert_arg & CR_INVERT) == 0) { /* Trigger on +ve edge. */ conv = PCI230_ADC_TRIG_EXTP; @@ -2035,7 +2080,7 @@ static void pci230_ai_start(struct comedi_device *dev, } } else { /* Backwards compatibility. */ - if (cmd->convert_arg != 0) { + if (cmd->convert_arg) { /* Trigger on +ve edge. */ conv = PCI230_ADC_TRIG_EXTP; } else { @@ -2045,31 +2090,39 @@ static void pci230_ai_start(struct comedi_device *dev, } break; case TRIG_INT: - /* Use CT2 output for software trigger due to problems - * in differential mode on PCI230/260. */ + /* + * Use CT2 output for software trigger due to problems + * in differential mode on PCI230/260. + */ conv = PCI230_ADC_TRIG_Z2CT2; break; } - devpriv->adccon = (devpriv->adccon & ~PCI230_ADC_TRIG_MASK) - | conv; + devpriv->adccon = + (devpriv->adccon & ~PCI230_ADC_TRIG_MASK) | conv; outw(devpriv->adccon, dev->iobase + PCI230_ADCCON); if (cmd->convert_src == TRIG_INT) async->inttrig = pci230_ai_inttrig_convert; - /* Update FIFO interrupt trigger level, which is currently - * set to "full". */ + /* + * Update FIFO interrupt trigger level, which is currently + * set to "full". + */ pci230_ai_update_fifo_trigger_level(dev, s); if (cmd->convert_src == TRIG_TIMER) { /* Update timer gates. */ unsigned char zgat; if (cmd->scan_begin_src != TRIG_FOLLOW) { - /* Conversion timer CT2 needs to be gated by - * inverted output of monostable CT2. */ + /* + * Conversion timer CT2 needs to be gated by + * inverted output of monostable CT2. + */ zgat = GAT_CONFIG(2, GAT_NOUTNM2); } else { - /* Conversion timer CT2 needs to be gated on - * continuously. */ + /* + * Conversion timer CT2 needs to be gated on + * continuously. + */ zgat = GAT_CONFIG(2, GAT_VCC); } outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE); @@ -2111,11 +2164,13 @@ static void pci230_ai_start(struct comedi_device *dev, outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE); switch (cmd->scan_begin_src) { case TRIG_TIMER: - /* Scan period timer CT1 needs to be - * gated on to start counting. */ + /* + * Scan period timer CT1 needs to be + * gated on to start counting. + */ zgat = GAT_CONFIG(1, GAT_VCC); - outb(zgat, devpriv->iobase1 - + PCI230_ZGAT_SCE); + outb(zgat, devpriv->iobase1 + + PCI230_ZGAT_SCE); break; case TRIG_INT: async->inttrig = @@ -2163,12 +2218,12 @@ static void pci230_handle_ai(struct comedi_device *dev, todo = PCI230_ADC_FIFOLEVEL_HALFFULL; } else if (devpriv->ai_scan_count == 0) { todo = 0; - } else if ((devpriv->ai_scan_count > PCI230_ADC_FIFOLEVEL_HALFFULL) - || (scanlen > PCI230_ADC_FIFOLEVEL_HALFFULL)) { + } else if ((devpriv->ai_scan_count > PCI230_ADC_FIFOLEVEL_HALFFULL) || + (scanlen > PCI230_ADC_FIFOLEVEL_HALFFULL)) { todo = PCI230_ADC_FIFOLEVEL_HALFFULL; } else { - todo = (devpriv->ai_scan_count * scanlen) - - devpriv->ai_scan_pos; + todo = (devpriv->ai_scan_count * scanlen) - + devpriv->ai_scan_pos; if (todo > PCI230_ADC_FIFOLEVEL_HALFFULL) todo = PCI230_ADC_FIFOLEVEL_HALFFULL; } @@ -2179,24 +2234,26 @@ static void pci230_handle_ai(struct comedi_device *dev, if (fifoamount == 0) { /* Read FIFO state. */ status_fifo = inw(dev->iobase + PCI230_ADCCON); - if ((status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) != 0) { - /* Report error otherwise FIFO overruns will go - * unnoticed by the caller. */ - comedi_error(dev, "AI FIFO overrun"); + if (status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) { + /* + * Report error otherwise FIFO overruns will go + * unnoticed by the caller. + */ + dev_err(dev->class_dev, "AI FIFO overrun\n"); events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; break; - } else if ((status_fifo & PCI230_ADC_FIFO_EMPTY) != 0) { + } else if (status_fifo & PCI230_ADC_FIFO_EMPTY) { /* FIFO empty. */ break; - } else if ((status_fifo & PCI230_ADC_FIFO_HALF) != 0) { + } else if (status_fifo & PCI230_ADC_FIFO_HALF) { /* FIFO half full. */ fifoamount = PCI230_ADC_FIFOLEVEL_HALFFULL; } else { /* FIFO not empty. */ if (devpriv->hwver > 0) { /* Read PCI230+/260+ ADC FIFO level. */ - fifoamount = inw(dev->iobase - + PCI230P_ADCFFLEV); + fifoamount = + inw(dev->iobase + PCI230P_ADCFFLEV); if (fifoamount == 0) { /* Shouldn't happen. */ break; @@ -2209,7 +2266,7 @@ static void pci230_handle_ai(struct comedi_device *dev, /* Read sample and store in Comedi's circular buffer. */ if (comedi_buf_put(s, pci230_ai_read(dev)) == 0) { events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW; - comedi_error(dev, "AI buffer overflow"); + dev_err(dev->class_dev, "AI buffer overflow\n"); break; } fifoamount--; @@ -2229,8 +2286,8 @@ static void pci230_handle_ai(struct comedi_device *dev, events |= COMEDI_CB_BLOCK; } async->events |= events; - if ((async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | - COMEDI_CB_OVERFLOW)) != 0) { + if (async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | + COMEDI_CB_OVERFLOW)) { /* disable hardware conversions */ pci230_ai_stop(dev, s); } else { @@ -2255,8 +2312,10 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * Determine which shared resources are needed. */ res_mask = 0; - /* Need Z2-CT2 to supply a conversion trigger source at a high - * logic level, even if not doing timed conversions. */ + /* + * Need Z2-CT2 to supply a conversion trigger source at a high + * logic level, even if not doing timed conversions. + */ res_mask |= (1U << RES_Z2CT2); if (cmd->scan_begin_src != TRIG_FOLLOW) { /* Using Z2-CT0 monostable to gate Z2-CT2 conversion timer */ @@ -2278,7 +2337,8 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_scan_count = 0; devpriv->ai_scan_pos = 0; /* Position within scan. */ - /* Steps; + /* + * Steps: * - Set channel scan list. * - Set channel gains. * - Enable and reset FIFO, specify uni/bip, se/diff, and set @@ -2323,20 +2383,24 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (diff) { gainshift = 2 * chan; if (devpriv->hwver == 0) { - /* Original PCI230/260 expects both inputs of - * the differential channel to be enabled. */ + /* + * Original PCI230/260 expects both inputs of + * the differential channel to be enabled. + */ adcen |= 3 << gainshift; } else { - /* PCI230+/260+ expects only one input of the - * differential channel to be enabled. */ + /* + * PCI230+/260+ expects only one input of the + * differential channel to be enabled. + */ adcen |= 1 << gainshift; } } else { gainshift = (chan & ~1); adcen |= 1 << chan; } - devpriv->adcg = (devpriv->adcg & ~(3 << gainshift)) - | (pci230_ai_gain[range] << gainshift); + devpriv->adcg = (devpriv->adcg & ~(3 << gainshift)) | + (pci230_ai_gain[range] << gainshift); } /* Set channel scan list. */ @@ -2345,43 +2409,53 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* Set channel gains. */ outw(devpriv->adcg, dev->iobase + PCI230_ADCG); - /* Set counter/timer 2 output high for use as the initial start - * conversion source. */ + /* + * Set counter/timer 2 output high for use as the initial start + * conversion source. + */ i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE1); - /* Temporarily use CT2 output as conversion trigger source and - * temporarily set FIFO interrupt trigger level to 'full'. */ + /* + * Temporarily use CT2 output as conversion trigger source and + * temporarily set FIFO interrupt trigger level to 'full'. + */ adccon |= PCI230_ADC_INT_FIFO_FULL | PCI230_ADC_TRIG_Z2CT2; - /* Enable and reset FIFO, specify FIFO trigger level full, specify + /* + * Enable and reset FIFO, specify FIFO trigger level full, specify * uni/bip, se/diff, and temporarily set the start conversion source * to CT2 output. Note that CT2 output is currently high, and this * will produce a false conversion trigger on some versions of the - * PCI230/260, but that will be dealt with later. */ + * PCI230/260, but that will be dealt with later. + */ devpriv->adccon = adccon; outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON); - /* Delay */ - /* Failure to include this will result in the first few channels'-worth + /* + * Delay - + * Failure to include this will result in the first few channels'-worth * of data being corrupt, normally manifesting itself by large negative * voltages. It seems the board needs time to settle between the first * FIFO reset (above) and the second FIFO reset (below). Setting the * channel gains and scan list _before_ the first FIFO reset also - * helps, though only slightly. */ - udelay(25); + * helps, though only slightly. + */ + usleep_range(25, 100); /* Reset FIFO again. */ outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON); if (cmd->convert_src == TRIG_TIMER) { - /* Set up CT2 as conversion timer, but gate it off for now. + /* + * Set up CT2 as conversion timer, but gate it off for now. * Note, counter/timer output 2 can be monitored on the - * connector: PCI230 pin 21, PCI260 pin 18. */ + * connector: PCI230 pin 21, PCI260 pin 18. + */ zgat = GAT_CONFIG(2, GAT_GND); outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE); /* Set counter/timer 2 to the specified conversion period. */ pci230_ct_setup_ns_mode(dev, 2, I8254_MODE3, cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); + cmd->flags); if (cmd->scan_begin_src != TRIG_FOLLOW) { /* * Set up monostable on CT0 output for scan timing. A @@ -2398,8 +2472,8 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) zgat = GAT_CONFIG(0, GAT_VCC); outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE); pci230_ct_setup_ns_mode(dev, 0, I8254_MODE1, - ((uint64_t) cmd->convert_arg - * cmd->scan_end_arg), + ((uint64_t)cmd->convert_arg * + cmd->scan_end_arg), TRIG_ROUND_UP); if (cmd->scan_begin_src == TRIG_TIMER) { /* @@ -2412,9 +2486,7 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE); pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3, cmd->scan_begin_arg, - cmd-> - flags & - TRIG_ROUND_MASK); + cmd->flags); } } } @@ -2452,9 +2524,11 @@ static irqreturn_t pci230_interrupt(int irq, void *d) spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); valid_status_int = devpriv->int_en & status_int; - /* Disable triggered interrupts. + /* + * Disable triggered interrupts. * (Only those interrupts that need re-enabling, are, later in the - * handler). */ + * handler). + */ devpriv->ier = devpriv->int_en & ~status_int; outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE); devpriv->intr_running = 1; @@ -2469,19 +2543,19 @@ static irqreturn_t pci230_interrupt(int irq, void *d) * two. */ - if ((valid_status_int & PCI230_INT_ZCLK_CT1) != 0) { + if (valid_status_int & PCI230_INT_ZCLK_CT1) { s = dev->write_subdev; pci230_handle_ao_nofifo(dev, s); comedi_event(dev, s); } - if ((valid_status_int & PCI230P2_INT_DAC) != 0) { + if (valid_status_int & PCI230P2_INT_DAC) { s = dev->write_subdev; pci230_handle_ao_fifo(dev, s); comedi_event(dev, s); } - if ((valid_status_int & PCI230_INT_ADC) != 0) { + if (valid_status_int & PCI230_INT_ADC) { s = dev->read_subdev; pci230_handle_ai(dev, s); comedi_event(dev, s); @@ -2511,8 +2585,10 @@ static bool pci230_match_pci_board(const struct pci230_board *board, /* Looking for a '+' model. First check length of registers. */ if (pci_resource_len(pci_dev, 3) < 32) return false; /* Not a '+' model. */ - /* TODO: temporarily enable PCI device and read the hardware version - * register. For now, assume it's okay. */ + /* + * TODO: temporarily enable PCI device and read the hardware version + * register. For now, assume it's okay. + */ return true; } @@ -2601,8 +2677,10 @@ static int pci230_attach_common(struct comedi_device *dev, if (rc) return rc; - /* Read base addresses of the PCI230's two I/O regions from PCI - * configuration register. */ + /* + * Read base addresses of the PCI230's two I/O regions from PCI + * configuration register. + */ iobase1 = pci_resource_start(pci_dev, 2); iobase2 = pci_resource_start(pci_dev, 3); dev_dbg(dev->class_dev, @@ -2612,8 +2690,10 @@ static int pci230_attach_common(struct comedi_device *dev, dev->iobase = iobase2; /* Read bits of DACCON register - only the output range. */ devpriv->daccon = inw(dev->iobase + PCI230_DACCON) & PCI230_DAC_OR_MASK; - /* Read hardware version register and set extended function register - * if they exist. */ + /* + * Read hardware version register and set extended function register + * if they exist. + */ if (pci_resource_len(pci_dev, 3) >= 32) { unsigned short extfunc = 0; @@ -2627,25 +2707,29 @@ static int pci230_attach_common(struct comedi_device *dev, } if (devpriv->hwver > 0) { if (!thisboard->have_dio) { - /* No DIO ports. Route counters' external gates + /* + * No DIO ports. Route counters' external gates * to the EXTTRIG signal (PCI260+ pin 17). * (Otherwise, they would be routed to DIO * inputs PC0, PC1 and PC2 which don't exist - * on PCI260[+].) */ + * on PCI260[+].) + */ extfunc |= PCI230P_EXTFUNC_GAT_EXTTRIG; } - if ((thisboard->ao_chans > 0) - && (devpriv->hwver >= 2)) { + if ((thisboard->ao_chans > 0) && + (devpriv->hwver >= 2)) { /* Enable DAC FIFO functionality. */ extfunc |= PCI230P2_EXTFUNC_DACFIFO; } } outw(extfunc, dev->iobase + PCI230P_EXTFUNC); - if ((extfunc & PCI230P2_EXTFUNC_DACFIFO) != 0) { - /* Temporarily enable DAC FIFO, reset it and disable - * FIFO wraparound. */ - outw(devpriv->daccon | PCI230P2_DAC_FIFO_EN - | PCI230P2_DAC_FIFO_RESET, + if (extfunc & PCI230P2_EXTFUNC_DACFIFO) { + /* + * Temporarily enable DAC FIFO, reset it and disable + * FIFO wraparound. + */ + outw(devpriv->daccon | PCI230P2_DAC_FIFO_EN | + PCI230P2_DAC_FIFO_RESET, dev->iobase + PCI230_DACCON); /* Clear DAC FIFO channel enable register. */ outw(0, dev->iobase + PCI230P2_DACEN); @@ -2657,8 +2741,8 @@ static int pci230_attach_common(struct comedi_device *dev, outb(0, devpriv->iobase1 + PCI230_INT_SCE); /* Set ADC to a reasonable state. */ devpriv->adcg = 0; - devpriv->adccon = PCI230_ADC_TRIG_NONE | PCI230_ADC_IM_SE - | PCI230_ADC_IR_BIP; + devpriv->adccon = PCI230_ADC_TRIG_NONE | PCI230_ADC_IM_SE | + PCI230_ADC_IR_BIP; outw(1 << 0, dev->iobase + PCI230_ADCEN); outw(devpriv->adcg, dev->iobase + PCI230_ADCG); outw(devpriv->adccon | PCI230_ADC_FIFO_RESET, @@ -2682,13 +2766,13 @@ static int pci230_attach_common(struct comedi_device *dev, s->n_chan = thisboard->ai_chans; s->maxdata = (1 << thisboard->ai_bits) - 1; s->range_table = &pci230_ai_range; - s->insn_read = &pci230_ai_rinsn; + s->insn_read = pci230_ai_rinsn; s->len_chanlist = 256; /* but there are restrictions. */ if (dev->irq) { dev->read_subdev = s; s->subdev_flags |= SDF_CMD_READ; - s->do_cmd = &pci230_ai_cmd; - s->do_cmdtest = &pci230_ai_cmdtest; + s->do_cmd = pci230_ai_cmd; + s->do_cmdtest = pci230_ai_cmdtest; s->cancel = pci230_ai_cancel; } @@ -2700,14 +2784,14 @@ static int pci230_attach_common(struct comedi_device *dev, s->n_chan = thisboard->ao_chans; s->maxdata = (1 << thisboard->ao_bits) - 1; s->range_table = &pci230_ao_range; - s->insn_write = &pci230_ao_winsn; - s->insn_read = &pci230_ao_rinsn; + s->insn_write = pci230_ao_winsn; + s->insn_read = pci230_ao_rinsn; s->len_chanlist = thisboard->ao_chans; if (dev->irq) { dev->write_subdev = s; s->subdev_flags |= SDF_CMD_WRITE; - s->do_cmd = &pci230_ao_cmd; - s->do_cmdtest = &pci230_ao_cmdtest; + s->do_cmd = pci230_ao_cmd; + s->do_cmdtest = pci230_ao_cmdtest; s->cancel = pci230_ao_cancel; } } else { @@ -2748,7 +2832,7 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it) } static int pci230_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context_unused) { struct pci_dev *pci_dev = comedi_to_pci_dev(dev); int rc; diff --git a/drivers/staging/comedi/drivers/amplc_pci236.c b/drivers/staging/comedi/drivers/amplc_pci236.c new file mode 100644 index 000000000000..436aebaf7621 --- /dev/null +++ b/drivers/staging/comedi/drivers/amplc_pci236.c @@ -0,0 +1,161 @@ +/* + * comedi/drivers/amplc_pci236.c + * Driver for Amplicon PCI236 DIO boards. + * + * Copyright (C) 2002-2014 MEV Ltd. <http://www.mev.co.uk/> + * + * 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: amplc_pci236 + * Description: Amplicon PCI236 + * Author: Ian Abbott <abbotti@mev.co.uk> + * Devices: [Amplicon] PCI236 (amplc_pci236) + * Updated: Fri, 25 Jul 2014 15:32:40 +0000 + * Status: works + * + * Configuration options: + * none + * + * Manual configuration of PCI board (PCI236) is not supported; it is + * configured automatically. + * + * The PCI236 board has a single 8255 appearing as subdevice 0. + * + * Subdevice 1 pretends to be a digital input device, but it always + * returns 0 when read. However, if you run a command with + * scan_begin_src=TRIG_EXT, a rising edge on port C bit 3 acts as an + * external trigger, which can be used to wake up tasks. This is like + * the comedi_parport device. If no interrupt is connected, then + * subdevice 1 is unused. + */ + +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/interrupt.h> + +#include "../comedidev.h" + +#include "amplc_pc236.h" +#include "plx9052.h" + +/* Disable, and clear, interrupts */ +#define PCI236_INTR_DISABLE (PLX9052_INTCSR_LI1POL | \ + PLX9052_INTCSR_LI2POL | \ + PLX9052_INTCSR_LI1SEL | \ + PLX9052_INTCSR_LI1CLRINT) + +/* Enable, and clear, interrupts */ +#define PCI236_INTR_ENABLE (PLX9052_INTCSR_LI1ENAB | \ + PLX9052_INTCSR_LI1POL | \ + PLX9052_INTCSR_LI2POL | \ + PLX9052_INTCSR_PCIENAB | \ + PLX9052_INTCSR_LI1SEL | \ + PLX9052_INTCSR_LI1CLRINT) + +static void pci236_intr_update_cb(struct comedi_device *dev, bool enable) +{ + struct pc236_private *devpriv = dev->private; + + /* this will also clear the "local interrupt 1" latch */ + outl(enable ? PCI236_INTR_ENABLE : PCI236_INTR_DISABLE, + devpriv->lcr_iobase + PLX9052_INTCSR); +} + +static bool pci236_intr_chk_clr_cb(struct comedi_device *dev) +{ + struct pc236_private *devpriv = dev->private; + + /* check if interrupt occurred */ + if (!(inl(devpriv->lcr_iobase + PLX9052_INTCSR) & + PLX9052_INTCSR_LI1STAT)) + return false; + /* clear the interrupt */ + pci236_intr_update_cb(dev, devpriv->enable_irq); + return true; +} + +static const struct pc236_board pc236_pci_board = { + .name = "pci236", + .intr_update_cb = pci236_intr_update_cb, + .intr_chk_clr_cb = pci236_intr_chk_clr_cb, +}; + +static int pci236_auto_attach(struct comedi_device *dev, + unsigned long context_unused) +{ + struct pci_dev *pci_dev = comedi_to_pci_dev(dev); + struct pc236_private *devpriv; + unsigned long iobase; + int ret; + + dev_info(dev->class_dev, "amplc_pci236: attach pci %s\n", + pci_name(pci_dev)); + + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); + if (!devpriv) + return -ENOMEM; + + dev->board_ptr = &pc236_pci_board; + dev->board_name = pc236_pci_board.name; + ret = comedi_pci_enable(dev); + if (ret) + return ret; + + devpriv->lcr_iobase = pci_resource_start(pci_dev, 1); + iobase = pci_resource_start(pci_dev, 2); + return amplc_pc236_common_attach(dev, iobase, pci_dev->irq, + IRQF_SHARED); +} + +static void pci236_detach(struct comedi_device *dev) +{ + if (dev->irq) + free_irq(dev->irq, dev); + comedi_pci_disable(dev); +} + +static struct comedi_driver amplc_pci236_driver = { + .driver_name = "amplc_pci236", + .module = THIS_MODULE, + .auto_attach = pci236_auto_attach, + .detach = pci236_detach, +}; + +static const struct pci_device_id pci236_pci_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, 0x0009) }, + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, pci236_pci_table); + +static int amplc_pci236_pci_probe(struct pci_dev *dev, + const struct pci_device_id *id) +{ + return comedi_pci_auto_config(dev, &lc_pci236_driver, + id->driver_data); +} + +static struct pci_driver amplc_pci236_pci_driver = { + .name = "amplc_pci236", + .id_table = pci236_pci_table, + .probe = &lc_pci236_pci_probe, + .remove = comedi_pci_auto_unconfig, +}; + +module_comedi_pci_driver(amplc_pci236_driver, amplc_pci236_pci_driver); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi driver for Amplicon PCI236 DIO boards"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_pci263.c b/drivers/staging/comedi/drivers/amplc_pci263.c index 93ed03ee416a..748a6b108f32 100644 --- a/drivers/staging/comedi/drivers/amplc_pci263.c +++ b/drivers/staging/comedi/drivers/amplc_pci263.c @@ -37,11 +37,6 @@ The state of the outputs can be read. #include "../comedidev.h" -#define PCI263_DRIVER_NAME "amplc_pci263" - -/* PCI263 PCI configuration register information */ -#define PCI_DEVICE_ID_AMPLICON_PCI263 0x000c - static int pci263_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -88,14 +83,14 @@ static int pci263_auto_attach(struct comedi_device *dev, } static struct comedi_driver amplc_pci263_driver = { - .driver_name = PCI263_DRIVER_NAME, + .driver_name = "amplc_pci263", .module = THIS_MODULE, .auto_attach = pci263_auto_attach, .detach = comedi_pci_disable, }; static const struct pci_device_id pci263_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI263) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, 0x000c) }, {0} }; MODULE_DEVICE_TABLE(pci, pci263_pci_table); @@ -108,7 +103,7 @@ static int amplc_pci263_pci_probe(struct pci_dev *dev, } static struct pci_driver amplc_pci263_pci_driver = { - .name = PCI263_DRIVER_NAME, + .name = "amplc_pci263", .id_table = pci263_pci_table, .probe = &lc_pci263_pci_probe, .remove = comedi_pci_auto_unconfig, diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index eb1b92d72e87..853733e28845 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -46,8 +46,6 @@ Status: experimental #include "comedi_fc.h" #include "8253.h" -#define DAS16CS_SIZE 18 - #define DAS16CS_ADC_DATA 0 #define DAS16CS_DIO_MUX 2 #define DAS16CS_MISC1 4 diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 7377da1aff7c..4a7bd4e5dd72 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -461,7 +461,6 @@ static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s, break; default: return -EINVAL; - break; } return insn->n; } @@ -622,7 +621,7 @@ static int caldac_8800_write(struct comedi_device *dev, unsigned int address, static const int caldac_8800_udelay = 1; if (address >= num_caldac_channels) { - comedi_error(dev, "illegal caldac channel"); + dev_err(dev->class_dev, "illegal caldac channel\n"); return -1; } @@ -774,9 +773,8 @@ static int cb_pcidas_trimpot_write(struct comedi_device *dev, trimpot_8402_write(dev, channel, value); break; default: - comedi_error(dev, "driver bug?"); + dev_err(dev->class_dev, "driver bug?\n"); return -1; - break; } return 1; @@ -1251,9 +1249,8 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev, break; default: spin_unlock_irqrestore(&dev->spinlock, flags); - comedi_error(dev, "error setting dac pacer source"); + dev_err(dev->class_dev, "error setting dac pacer source\n"); return -1; - break; } spin_unlock_irqrestore(&dev->spinlock, flags); @@ -1303,7 +1300,7 @@ static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status) if (cmd->stop_src == TRIG_NONE || (cmd->stop_src == TRIG_COUNT && devpriv->ao_count)) { - comedi_error(dev, "dac fifo underflow"); + dev_err(dev->class_dev, "dac fifo underflow\n"); async->events |= COMEDI_CB_ERROR; } async->events |= COMEDI_CB_EOA; @@ -1414,8 +1411,8 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) devpriv->control_status + INT_ADCFIFO); spin_unlock_irqrestore(&dev->spinlock, flags); } else if (status & EOAI) { - comedi_error(dev, - "bug! encountered end of acquisition interrupt?"); + 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, @@ -1424,7 +1421,7 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) } /* check for fifo overflow */ if (status & LADFUL) { - comedi_error(dev, "fifo overflow"); + dev_err(dev->class_dev, "fifo overflow\n"); /* clear overflow interrupt latch */ spin_lock_irqsave(&dev->spinlock, flags); outw(devpriv->adc_fifo_bits | LADFUL, @@ -1474,11 +1471,12 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, outl(INTCSR_INBOX_INTR_STATUS, devpriv->s5933_config + AMCC_OP_REG_INTCSR); - if (request_irq(pcidev->irq, cb_pcidas_interrupt, - IRQF_SHARED, dev->driver->driver_name, dev)) { + ret = request_irq(pcidev->irq, cb_pcidas_interrupt, IRQF_SHARED, + dev->board_name, dev); + if (ret) { dev_dbg(dev->class_dev, "unable to allocate irq %d\n", pcidev->irq); - return -EINVAL; + return ret; } dev->irq = pcidev->irq; diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index 035c3a176005..fa12614cef2a 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -80,8 +80,6 @@ TODO: make ao fifo size adjustable like ai fifo */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include <linux/module.h> #include <linux/pci.h> #include <linux/delay.h> @@ -179,7 +177,7 @@ enum read_write_registers { DAC_FIFO_REG = 0x300, }; -/* devpriv->dio_counter_iobase registers */ +/* dev->mmio registers */ enum dio_counter_registers { DIO_8255_OFFSET = 0x0, DO_REG = 0x20, @@ -636,8 +634,8 @@ static inline unsigned int ai_dma_ring_count(const struct pcidas64_board *board) { if (board->layout == LAYOUT_4020) return MAX_AI_DMA_RING_COUNT; - else - return MIN_AI_DMA_RING_COUNT; + + return MIN_AI_DMA_RING_COUNT; } static const int bytes_in_sample = 2; @@ -1045,9 +1043,9 @@ static inline unsigned short se_diff_bit_6xxx(struct comedi_device *dev, if ((thisboard->layout == LAYOUT_64XX && !use_differential) || (thisboard->layout == LAYOUT_60XX && use_differential)) return ADC_SE_DIFF_BIT; - else - return 0; -}; + + return 0; +} struct ext_clock_info { /* master clock divisor to use for scans with external master clock */ @@ -1064,12 +1062,11 @@ struct pcidas64_private { /* base addresses (ioremapped) */ void __iomem *plx9080_iobase; void __iomem *main_iobase; - void __iomem *dio_counter_iobase; /* local address (used by dma controller) */ uint32_t local0_iobase; uint32_t local1_iobase; /* number of analog input samples remaining */ - volatile unsigned int ai_count; + unsigned int ai_count; /* dma buffers for analog input */ uint16_t *ai_buffer[MAX_AI_DMA_RING_COUNT]; /* physical addresses of ai dma buffers */ @@ -1081,7 +1078,7 @@ struct pcidas64_private { dma_addr_t ai_dma_desc_bus_addr; /* index of the ai dma descriptor/buffer * that is currently being used */ - volatile unsigned int ai_dma_index; + unsigned int ai_dma_index; /* dma buffers for analog output */ uint16_t *ao_buffer[AO_DMA_RING_COUNT]; /* physical addresses of ao dma buffers */ @@ -1089,35 +1086,35 @@ struct pcidas64_private { struct plx_dma_desc *ao_dma_desc; dma_addr_t ao_dma_desc_bus_addr; /* keeps track of buffer where the next ao sample should go */ - volatile unsigned int ao_dma_index; + unsigned int ao_dma_index; /* number of analog output samples remaining */ - volatile unsigned long ao_count; + unsigned long ao_count; /* remember what the analog outputs are set to, to allow readback */ - volatile unsigned int ao_value[2]; + unsigned int ao_value[2]; unsigned int hw_revision; /* stc chip hardware revision number */ /* last bits sent to INTR_ENABLE_REG register */ - volatile unsigned int intr_enable_bits; + unsigned int intr_enable_bits; /* last bits sent to ADC_CONTROL1_REG register */ - volatile uint16_t adc_control1_bits; + uint16_t adc_control1_bits; /* last bits sent to FIFO_SIZE_REG register */ - volatile uint16_t fifo_size_bits; + uint16_t fifo_size_bits; /* last bits sent to HW_CONFIG_REG register */ - volatile uint16_t hw_config_bits; - volatile uint16_t dac_control1_bits; + uint16_t hw_config_bits; + uint16_t dac_control1_bits; /* last bits written to plx9080 control register */ - volatile uint32_t plx_control_bits; + uint32_t plx_control_bits; /* last bits written to plx interrupt control and status register */ - volatile uint32_t plx_intcsr_bits; + uint32_t plx_intcsr_bits; /* index of calibration source readable through ai ch0 */ - volatile int calibration_source; + int calibration_source; /* bits written to i2c calibration/range register */ - volatile uint8_t i2c_cal_range_bits; + uint8_t i2c_cal_range_bits; /* configure digital triggers to trigger on falling edge */ - volatile unsigned int ext_trig_falling; + unsigned int ext_trig_falling; /* states of various devices stored to enable read-back */ unsigned int ad8402_state[2]; unsigned int caldac_state[8]; - volatile short ai_cmd_running; + short ai_cmd_running; unsigned int ai_fifo_segment_length; struct ext_clock_info ext_clock; unsigned short ao_bounce_buffer[DAC_FIFO_SIZE]; @@ -1160,7 +1157,7 @@ static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev, bits = 0x700; break; default: - comedi_error(dev, "bug! in ai_range_bits_6xxx"); + dev_err(dev->class_dev, "bug! in %s\n", __func__); break; } if (range->min == 0) @@ -1180,16 +1177,16 @@ static unsigned int hw_revision(const struct comedi_device *dev, } static void set_dac_range_bits(struct comedi_device *dev, - volatile uint16_t *bits, unsigned int channel, + uint16_t *bits, unsigned int channel, unsigned int range) { const struct pcidas64_board *thisboard = comedi_board(dev); unsigned int code = thisboard->ao_range_code[range]; if (channel > 1) - comedi_error(dev, "bug! bad channel?"); + dev_err(dev->class_dev, "bug! bad channel?\n"); if (code & ~0x3) - comedi_error(dev, "bug! bad range code?"); + dev_err(dev->class_dev, "bug! bad range code?\n"); *bits &= ~(0x3 << (2 * channel)); *bits |= code << (2 * channel); @@ -1531,10 +1528,10 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) static inline void warn_external_queue(struct comedi_device *dev) { - comedi_error(dev, - "AO command and AI external channel queue cannot be used simultaneously."); - comedi_error(dev, - "Use internal AI channel queue (channels must be consecutive and use same range/aref)"); + dev_err(dev->class_dev, + "AO command and AI external channel queue cannot be used simultaneously\n"); + dev_err(dev->class_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 */ @@ -1648,7 +1645,8 @@ static void i2c_write(struct comedi_device *dev, unsigned int address, /* get acknowledge */ if (i2c_read_ack(dev) != 0) { - comedi_error(dev, "i2c write failed: no acknowledge"); + dev_err(dev->class_dev, "%s failed: no acknowledge\n", + __func__); i2c_stop(dev); return; } @@ -1656,7 +1654,8 @@ static void i2c_write(struct comedi_device *dev, unsigned int address, for (i = 0; i < length; i++) { i2c_write_byte(dev, data[i]); if (i2c_read_ack(dev) != 0) { - comedi_error(dev, "i2c write failed: no acknowledge"); + dev_err(dev->class_dev, "%s failed: no acknowledge\n", + __func__); i2c_stop(dev); return; } @@ -1769,6 +1768,7 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, * as it is very slow */ if (old_cal_range_bits != devpriv->i2c_cal_range_bits) { uint8_t i2c_data = devpriv->i2c_cal_range_bits; + i2c_write(dev, RANGE_CAL_I2C_ADDR, &i2c_data, sizeof(i2c_data)); } @@ -1796,8 +1796,7 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, return ret; if (thisboard->layout == LAYOUT_4020) - data[n] = readl(devpriv->dio_counter_iobase + - ADC_FIFO_REG) & 0xffff; + data[n] = readl(dev->mmio + ADC_FIFO_REG) & 0xffff; else data[n] = readw(devpriv->main_iobase + PIPE1_READ_REG); } @@ -1874,7 +1873,6 @@ static int ai_config_master_clock_4020(struct comedi_device *dev, break; default: return -EINVAL; - break; } data[4] = divisor; @@ -1890,10 +1888,8 @@ static int ai_config_master_clock(struct comedi_device *dev, unsigned int *data) switch (thisboard->layout) { case LAYOUT_4020: return ai_config_master_clock_4020(dev, data); - break; default: return -EINVAL; - break; } return -EINVAL; @@ -1907,16 +1903,12 @@ static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s, switch (id) { case INSN_CONFIG_ALT_SOURCE: return ai_config_calibration_source(dev, data); - break; case INSN_CONFIG_BLOCK_SIZE: return ai_config_block_size(dev, data); - break; case INSN_CONFIG_TIMER_1: return ai_config_master_clock(dev, data); - break; default: return -EINVAL; - break; } return -EINVAL; } @@ -1991,8 +1983,6 @@ static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd) scan_divisor = min_scan_divisor; cmd->scan_begin_arg = scan_divisor * TIMER_BASE; } - - return; } static int cb_pcidas64_ai_check_chanlist(struct comedi_device *dev, @@ -2162,8 +2152,8 @@ static int use_hw_sample_counter(struct comedi_cmd *cmd) if (cmd->stop_src == TRIG_COUNT && cmd->stop_arg <= max_counter_value) return 1; - else - return 0; + + return 0; } static void setup_sample_counters(struct comedi_device *dev, @@ -2224,7 +2214,6 @@ static uint32_t ai_scan_counter_6xxx(struct comedi_device *dev, break; default: return 0; - break; } return count - 3; } @@ -2243,7 +2232,7 @@ static uint32_t ai_convert_counter_4020(struct comedi_device *dev, divisor = devpriv->ext_clock.divisor; break; default: /* should never happen */ - comedi_error(dev, "bug! failed to set ai pacing!"); + dev_err(dev->class_dev, "bug! failed to set ai pacing!\n"); divisor = 1000; break; } @@ -2454,6 +2443,7 @@ static int setup_channel_queue(struct comedi_device *dev, * as it is very slow */ if (old_cal_range_bits != devpriv->i2c_cal_range_bits) { uint8_t i2c_data = devpriv->i2c_cal_range_bits; + i2c_write(dev, RANGE_CAL_I2C_ADDR, &i2c_data, sizeof(i2c_data)); } @@ -2694,7 +2684,7 @@ static void pio_drain_ai_fifo_32(struct comedi_device *dev) } for (i = 0; read_code != write_code && i < max_transfer;) { - fifo_data = readl(devpriv->dio_counter_iobase + ADC_FIFO_REG); + fifo_data = readl(dev->mmio + ADC_FIFO_REG); cfc_write_to_buffer(s, fifo_data & 0xffff); i++; if (i < max_transfer) { @@ -2775,7 +2765,7 @@ static void handle_ai_interrupt(struct comedi_device *dev, /* check for fifo overrun */ if (status & ADC_OVERRUN_BIT) { - comedi_error(dev, "fifo overrun"); + dev_err(dev->class_dev, "fifo overrun\n"); async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; } /* spin lock makes sure no one else changes plx dma control reg */ @@ -3138,7 +3128,8 @@ static void set_dac_select_reg(struct comedi_device *dev, first_channel = CR_CHAN(cmd->chanlist[0]); last_channel = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]); if (last_channel < first_channel) - comedi_error(dev, "bug! last ao channel < first ao channel"); + dev_err(dev->class_dev, + "bug! last ao channel < first ao channel\n"); bits = (first_channel & 0x7) | (last_channel & 0x7) << 3; @@ -3161,7 +3152,7 @@ static void set_dac_interval_regs(struct comedi_device *dev, divisor = get_ao_divisor(cmd->scan_begin_arg, cmd->flags); if (divisor > max_counter_value) { - comedi_error(dev, "bug! ao divisor too big"); + dev_err(dev->class_dev, "bug! ao divisor too big\n"); divisor = max_counter_value; } writew(divisor & 0xffff, @@ -3381,32 +3372,31 @@ static int ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s) static int dio_callback(int dir, int port, int data, unsigned long arg) { void __iomem *iobase = (void __iomem *)arg; + if (dir) { writeb(data, iobase + port); return 0; - } else { - return readb(iobase + port); } + return readb(iobase + port); } static int dio_callback_4020(int dir, int port, int data, unsigned long arg) { void __iomem *iobase = (void __iomem *)arg; + if (dir) { writew(data, iobase + 2 * port); return 0; - } else { - return readw(iobase + 2 * port); } + return readw(iobase + 2 * port); } static int di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct pcidas64_private *devpriv = dev->private; unsigned int bits; - bits = readb(devpriv->dio_counter_iobase + DI_REG); + bits = readb(dev->mmio + DI_REG); bits &= 0xf; data[1] = bits; data[0] = 0; @@ -3419,10 +3409,8 @@ static int do_wbits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct pcidas64_private *devpriv = dev->private; - if (comedi_dio_update_state(s, data)) - writeb(s->state, devpriv->dio_counter_iobase + DO_REG); + writeb(s->state, dev->mmio + DO_REG); data[1] = s->state; @@ -3434,15 +3422,13 @@ static int dio_60xx_config_insn(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct pcidas64_private *devpriv = dev->private; int ret; ret = comedi_dio_insn_config(dev, s, insn, data, 0); if (ret) return ret; - writeb(s->io_bits, - devpriv->dio_counter_iobase + DIO_DIRECTION_60XX_REG); + writeb(s->io_bits, dev->mmio + DIO_DIRECTION_60XX_REG); return insn->n; } @@ -3452,14 +3438,10 @@ static int dio_60xx_wbits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct pcidas64_private *devpriv = dev->private; - - if (comedi_dio_update_state(s, data)) { - writeb(s->state, - devpriv->dio_counter_iobase + DIO_DATA_60XX_REG); - } + if (comedi_dio_update_state(s, data)) + writeb(s->state, dev->mmio + DIO_DATA_60XX_REG); - data[1] = readb(devpriv->dio_counter_iobase + DIO_DATA_60XX_REG); + data[1] = readb(dev->mmio + DIO_DATA_60XX_REG); return insn->n; } @@ -3496,7 +3478,7 @@ static int caldac_8800_write(struct comedi_device *dev, unsigned int address, static const int caldac_8800_udelay = 1; if (address >= num_caldac_channels) { - comedi_error(dev, "illegal caldac channel"); + dev_err(dev->class_dev, "illegal caldac channel\n"); return -1; } for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) { @@ -3568,9 +3550,8 @@ static int caldac_i2c_write(struct comedi_device *dev, serial_bytes[0] = GAIN_1_3; break; default: - comedi_error(dev, "invalid caldac channel\n"); + dev_err(dev->class_dev, "invalid caldac channel\n"); return -1; - break; } serial_bytes[1] = NOT_CLEAR_REGISTERS | ((value >> 8) & 0xf); serial_bytes[2] = value & 0xff; @@ -3863,8 +3844,7 @@ static int setup_subdevices(struct comedi_device *dev) ret = subdev_8255_init(dev, s, dio_callback_4020, (unsigned long)dio_8255_iobase); } else { - dio_8255_iobase = - devpriv->dio_counter_iobase + DIO_8255_OFFSET; + dio_8255_iobase = dev->mmio + DIO_8255_OFFSET; ret = subdev_8255_init(dev, s, dio_callback, (unsigned long)dio_8255_iobase); } @@ -3965,10 +3945,9 @@ static int auto_attach(struct comedi_device *dev, devpriv->plx9080_iobase = pci_ioremap_bar(pcidev, 0); devpriv->main_iobase = pci_ioremap_bar(pcidev, 2); - devpriv->dio_counter_iobase = pci_ioremap_bar(pcidev, 3); + dev->mmio = pci_ioremap_bar(pcidev, 3); - if (!devpriv->plx9080_iobase || !devpriv->main_iobase - || !devpriv->dio_counter_iobase) { + if (!devpriv->plx9080_iobase || !devpriv->main_iobase || !dev->mmio) { dev_warn(dev->class_dev, "failed to remap io memory\n"); return -ENOMEM; } @@ -3997,12 +3976,13 @@ static int auto_attach(struct comedi_device *dev, devpriv->hw_revision); init_plx9080(dev); init_stc_registers(dev); - /* get irq */ - if (request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED, - "cb_pcidas64", dev)) { + + retval = request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED, + dev->board_name, dev); + if (retval) { dev_dbg(dev->class_dev, "unable to allocate irq %u\n", pcidev->irq); - return -EINVAL; + return retval; } dev->irq = pcidev->irq; dev_dbg(dev->class_dev, "irq %u\n", dev->irq); @@ -4031,8 +4011,8 @@ static void detach(struct comedi_device *dev) } if (devpriv->main_iobase) iounmap(devpriv->main_iobase); - if (devpriv->dio_counter_iobase) - iounmap(devpriv->dio_counter_iobase); + if (dev->mmio) + iounmap(dev->mmio); /* free pci dma buffers */ for (i = 0; i < ai_dma_ring_count(thisboard); i++) { if (devpriv->ai_buffer[i]) diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index 50e522e6e690..ccb9c72bc0c3 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -47,9 +47,6 @@ See http://www.mccdaq.com/PDFs/Manuals/pcim-das1602-16.pdf for more details. /* Registers for the PCIM-DAS1602/16 */ -/* sizes of io regions (bytes) */ -#define BADR3_SIZE 16 - /* DAC Offsets */ #define ADC_TRIG 0 #define DAC0_OFFSET 2 diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index 67a09aa6b721..845a67905ca6 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -146,10 +146,8 @@ static unsigned short fake_waveform(struct comedi_device *dev, switch (channel) { case SAWTOOTH_CHAN: return fake_sawtooth(dev, range, current_time); - break; case SQUARE_CHAN: return fake_squarewave(dev, range, current_time); - break; default: break; } @@ -305,8 +303,8 @@ static int waveform_ai_cmd(struct comedi_device *dev, struct comedi_cmd *cmd = &s->async->cmd; if (cmd->flags & TRIG_RT) { - comedi_error(dev, - "commands at RT priority not supported in this driver"); + dev_err(dev->class_dev, + "commands at RT priority not supported in this driver\n"); return -1; } diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c index 0a9c32e9db4a..f066fb06dc1d 100644 --- a/drivers/staging/comedi/drivers/contec_pci_dio.c +++ b/drivers/staging/comedi/drivers/contec_pci_dio.c @@ -30,8 +30,6 @@ Configuration Options: not applicable, uses comedi PCI auto config #include "../comedidev.h" -#define PCI_DEVICE_ID_PIO1616L 0x8172 - /* * Register map */ @@ -110,7 +108,7 @@ static int contec_pci_dio_pci_probe(struct pci_dev *dev, } static const struct pci_device_id contec_pci_dio_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_CONTEC, PCI_DEVICE_ID_PIO1616L) }, + { PCI_DEVICE(PCI_VENDOR_ID_CONTEC, 0x8172) }, { 0 } }; MODULE_DEVICE_TABLE(pci, contec_pci_dio_pci_table); diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index a8f6036ad82b..cd369cd40114 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -113,8 +113,8 @@ Configuration options: not applicable, uses PCI auto config #define DAQBOARD2000_FIRMWARE "daqboard2000_firmware.bin" -#define DAQBOARD2000_SUBSYSTEM_IDS2 0x0002 /* Daqboard/2000 - 2 Dacs */ -#define DAQBOARD2000_SUBSYSTEM_IDS4 0x0004 /* Daqboard/2000 - 4 Dacs */ +#define DAQBOARD2000_SUBSYSTEM_IDS2 0x0002 /* Daqboard/2000 - 2 Dacs */ +#define DAQBOARD2000_SUBSYSTEM_IDS4 0x0004 /* Daqboard/2000 - 4 Dacs */ /* Initialization bits for the Serial EEPROM Control Register */ #define DAQBOARD2000_SECRProgPinHi 0x8001767e @@ -128,8 +128,8 @@ Configuration options: not applicable, uses PCI auto config #define DAQBOARD2000_EEPROM_PRESENT 0x10000000 /* CPLD status bits */ -#define DAQBOARD2000_CPLD_INIT 0x0002 -#define DAQBOARD2000_CPLD_DONE 0x0004 +#define DAQBOARD2000_CPLD_INIT 0x0002 +#define DAQBOARD2000_CPLD_DONE 0x0004 static const struct comedi_lrange range_daqboard2000_ai = { 13, { @@ -274,19 +274,16 @@ struct daqboard2000_private { enum { card_daqboard_2000 } card; - void __iomem *daq; void __iomem *plx; unsigned int ao_readback[2]; }; static void writeAcqScanListEntry(struct comedi_device *dev, u16 entry) { - struct daqboard2000_private *devpriv = dev->private; - /* udelay(4); */ - writew(entry & 0x00ff, devpriv->daq + acqScanListFIFO); + writew(entry & 0x00ff, dev->mmio + acqScanListFIFO); /* udelay(4); */ - writew((entry >> 8) & 0x00ff, devpriv->daq + acqScanListFIFO); + writew((entry >> 8) & 0x00ff, dev->mmio + acqScanListFIFO); } static void setup_sampling(struct comedi_device *dev, int chan, int gain) @@ -338,10 +335,9 @@ static int daqboard2000_ai_status(struct comedi_device *dev, struct comedi_insn *insn, unsigned long context) { - struct daqboard2000_private *devpriv = dev->private; unsigned int status; - status = readw(devpriv->daq + acqControl); + status = readw(dev->mmio + acqControl); if (status & context) return 0; return -EBUSY; @@ -352,22 +348,21 @@ static int daqboard2000_ai_insn_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct daqboard2000_private *devpriv = dev->private; int gain, chan; int ret; int i; writew(DAQBOARD2000_AcqResetScanListFifo | DAQBOARD2000_AcqResetResultsFifo | - DAQBOARD2000_AcqResetConfigPipe, devpriv->daq + acqControl); + DAQBOARD2000_AcqResetConfigPipe, dev->mmio + acqControl); /* * If pacer clock is not set to some high value (> 10 us), we * risk multiple samples to be put into the result FIFO. */ /* 1 second, should be long enough */ - writel(1000000, devpriv->daq + acqPacerClockDivLow); - writew(0, devpriv->daq + acqPacerClockDivHigh); + writel(1000000, dev->mmio + acqPacerClockDivLow); + writew(0, dev->mmio + acqPacerClockDivHigh); gain = CR_RANGE(insn->chanspec); chan = CR_CHAN(insn->chanspec); @@ -379,15 +374,14 @@ static int daqboard2000_ai_insn_read(struct comedi_device *dev, for (i = 0; i < insn->n; i++) { setup_sampling(dev, chan, gain); /* Enable reading from the scanlist FIFO */ - writew(DAQBOARD2000_SeqStartScanList, - devpriv->daq + acqControl); + writew(DAQBOARD2000_SeqStartScanList, dev->mmio + acqControl); ret = comedi_timeout(dev, s, insn, daqboard2000_ai_status, DAQBOARD2000_AcqConfigPipeFull); if (ret) return ret; - writew(DAQBOARD2000_AdcPacerEnable, devpriv->daq + acqControl); + writew(DAQBOARD2000_AdcPacerEnable, dev->mmio + acqControl); ret = comedi_timeout(dev, s, insn, daqboard2000_ai_status, DAQBOARD2000_AcqLogicScanning); @@ -399,9 +393,9 @@ static int daqboard2000_ai_insn_read(struct comedi_device *dev, if (ret) return ret; - data[i] = readw(devpriv->daq + acqResultsFIFO); - writew(DAQBOARD2000_AdcPacerDisable, devpriv->daq + acqControl); - writew(DAQBOARD2000_SeqStopScanList, devpriv->daq + acqControl); + data[i] = readw(dev->mmio + acqResultsFIFO); + writew(DAQBOARD2000_AdcPacerDisable, dev->mmio + acqControl); + writew(DAQBOARD2000_SeqStopScanList, dev->mmio + acqControl); } return i; @@ -427,11 +421,10 @@ static int daqboard2000_ao_eoc(struct comedi_device *dev, struct comedi_insn *insn, unsigned long context) { - struct daqboard2000_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); unsigned int status; - status = readw(devpriv->daq + dacControl); + status = readw(dev->mmio + dacControl); if ((status & ((chan + 1) * 0x0010)) == 0) return 0; return -EBUSY; @@ -453,11 +446,10 @@ static int daqboard2000_ao_insn_write(struct comedi_device *dev, * OK, since it works OK without enabling the DAC's, * let's keep it as simple as possible... */ - writew((chan + 2) * 0x0010 | 0x0001, - devpriv->daq + dacControl); + writew((chan + 2) * 0x0010 | 0x0001, dev->mmio + dacControl); udelay(1000); #endif - writew(data[i], devpriv->daq + dacSetting(chan)); + writew(data[i], dev->mmio + dacSetting(chan)); ret = comedi_timeout(dev, s, insn, daqboard2000_ao_eoc, 0); if (ret) @@ -469,8 +461,7 @@ static int daqboard2000_ao_insn_write(struct comedi_device *dev, * Since we never enabled the DAC's, we don't need * to disable it... */ - writew((chan + 2) * 0x0010 | 0x0000, - devpriv->daq + dacControl); + writew((chan + 2) * 0x0010 | 0x0000, dev->mmio + dacControl); udelay(1000); #endif } @@ -512,14 +503,13 @@ static void daqboard2000_pulseProgPin(struct comedi_device *dev) static int daqboard2000_pollCPLD(struct comedi_device *dev, int mask) { - struct daqboard2000_private *devpriv = dev->private; int result = 0; int i; int cpld; /* timeout after 50 tries -> 5ms */ for (i = 0; i < 50; i++) { - cpld = readw(devpriv->daq + 0x1000); + cpld = readw(dev->mmio + 0x1000); if ((cpld & mask) == mask) { result = 1; break; @@ -532,12 +522,11 @@ static int daqboard2000_pollCPLD(struct comedi_device *dev, int mask) static int daqboard2000_writeCPLD(struct comedi_device *dev, int data) { - struct daqboard2000_private *devpriv = dev->private; int result = 0; udelay(10); - writew(data, devpriv->daq + 0x1000); - if ((readw(devpriv->daq + 0x1000) & DAQBOARD2000_CPLD_INIT) == + writew(data, dev->mmio + 0x1000); + if ((readw(dev->mmio + 0x1000) & DAQBOARD2000_CPLD_INIT) == DAQBOARD2000_CPLD_INIT) { result = 1; } @@ -593,23 +582,21 @@ static void daqboard2000_adcStopDmaTransfer(struct comedi_device *dev) static void daqboard2000_adcDisarm(struct comedi_device *dev) { - struct daqboard2000_private *devpriv = dev->private; - /* Disable hardware triggers */ udelay(2); writew(DAQBOARD2000_TrigAnalog | DAQBOARD2000_TrigDisable, - devpriv->daq + trigControl); + dev->mmio + trigControl); udelay(2); writew(DAQBOARD2000_TrigTTL | DAQBOARD2000_TrigDisable, - devpriv->daq + trigControl); + dev->mmio + trigControl); /* Stop the scan list FIFO from loading the configuration pipe */ udelay(2); - writew(DAQBOARD2000_SeqStopScanList, devpriv->daq + acqControl); + writew(DAQBOARD2000_SeqStopScanList, dev->mmio + acqControl); /* Stop the pacer clock */ udelay(2); - writew(DAQBOARD2000_AdcPacerDisable, devpriv->daq + acqControl); + writew(DAQBOARD2000_AdcPacerDisable, dev->mmio + acqControl); /* Stop the input dma (abort channel 1) */ daqboard2000_adcStopDmaTransfer(dev); @@ -617,23 +604,22 @@ static void daqboard2000_adcDisarm(struct comedi_device *dev) static void daqboard2000_activateReferenceDacs(struct comedi_device *dev) { - struct daqboard2000_private *devpriv = dev->private; unsigned int val; int timeout; /* Set the + reference dac value in the FPGA */ - writew(0x80 | DAQBOARD2000_PosRefDacSelect, devpriv->daq + refDacs); + writew(0x80 | DAQBOARD2000_PosRefDacSelect, dev->mmio + refDacs); for (timeout = 0; timeout < 20; timeout++) { - val = readw(devpriv->daq + dacControl); + val = readw(dev->mmio + dacControl); if ((val & DAQBOARD2000_RefBusy) == 0) break; udelay(2); } /* Set the - reference dac value in the FPGA */ - writew(0x80 | DAQBOARD2000_NegRefDacSelect, devpriv->daq + refDacs); + writew(0x80 | DAQBOARD2000_NegRefDacSelect, dev->mmio + refDacs); for (timeout = 0; timeout < 20; timeout++) { - val = readw(devpriv->daq + dacControl); + val = readw(dev->mmio + dacControl); if ((val & DAQBOARD2000_RefBusy) == 0) break; udelay(2); @@ -673,9 +659,8 @@ static int daqboard2000_8255_cb(int dir, int port, int data, if (dir) { writew(data, mmio_base + port * 2); return 0; - } else { - return readw(mmio_base + port * 2); } + return readw(mmio_base + port * 2); } static const void *daqboard2000_find_boardinfo(struct comedi_device *dev, @@ -719,8 +704,8 @@ static int daqboard2000_auto_attach(struct comedi_device *dev, return result; devpriv->plx = pci_ioremap_bar(pcidev, 0); - devpriv->daq = pci_ioremap_bar(pcidev, 2); - if (!devpriv->plx || !devpriv->daq) + dev->mmio = pci_ioremap_bar(pcidev, 2); + if (!devpriv->plx || !dev->mmio) return -ENOMEM; result = comedi_alloc_subdevices(dev, 3); @@ -759,7 +744,7 @@ static int daqboard2000_auto_attach(struct comedi_device *dev, s = &dev->subdevices[2]; result = subdev_8255_init(dev, s, daqboard2000_8255_cb, - (unsigned long)(devpriv->daq + dioP2ExpansionIO8Bit)); + (unsigned long)(dev->mmio + dioP2ExpansionIO8Bit)); if (result) return result; @@ -773,8 +758,8 @@ static void daqboard2000_detach(struct comedi_device *dev) if (dev->irq) free_irq(dev->irq, dev); if (devpriv) { - if (devpriv->daq) - iounmap(devpriv->daq); + if (dev->mmio) + iounmap(dev->mmio); if (devpriv->plx) iounmap(devpriv->plx); } diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index c5e352fb5555..fcf916a80c8d 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -273,7 +273,7 @@ static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, else data[n] = (1 << 15) - (lsb | (msb & 0x7f) << 8); } else { - comedi_error(dev, "bug! unknown ai encoding"); + dev_err(dev->class_dev, "bug! unknown ai encoding\n"); return -1; } } @@ -452,7 +452,6 @@ static int das08_counter_config(struct comedi_device *dev, break; default: return -EINVAL; - break; } return 2; } diff --git a/drivers/staging/comedi/drivers/das08_pci.c b/drivers/staging/comedi/drivers/das08_pci.c index d94af09151b0..4ce3eb0a64cc 100644 --- a/drivers/staging/comedi/drivers/das08_pci.c +++ b/drivers/staging/comedi/drivers/das08_pci.c @@ -38,8 +38,6 @@ #include "das08.h" -#define PCI_DEVICE_ID_PCIDAS08 0x0029 - static const struct das08_board_struct das08_pci_boards[] = { { .name = "pci-das08", @@ -90,7 +88,7 @@ static int das08_pci_probe(struct pci_dev *dev, } static const struct pci_device_id das08_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_PCIDAS08) }, + { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0029) }, { 0 } }; MODULE_DEVICE_TABLE(pci, das08_pci_table); diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 2feecf199f27..057bc16f8ddc 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -506,18 +506,18 @@ static void das16_ai_disable(struct comedi_device *dev) static int disable_dma_on_even(struct comedi_device *dev) { struct das16_private_struct *devpriv = dev->private; - int residue; - int i; static const int disable_limit = 100; static const int enable_timeout = 100; + int residue; + int new_residue; + int i; + int j; disable_dma(devpriv->dma_chan); residue = get_dma_residue(devpriv->dma_chan); for (i = 0; i < disable_limit && (residue % 2); ++i) { - int j; enable_dma(devpriv->dma_chan); for (j = 0; j < enable_timeout; ++j) { - int new_residue; udelay(2); new_residue = get_dma_residue(devpriv->dma_chan); if (new_residue != residue) @@ -729,14 +729,14 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, } static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns, - int rounding_flags) + unsigned int flags) { struct das16_private_struct *devpriv = dev->private; unsigned long timer_base = dev->iobase + DAS16_TIMER_BASE_REG; i8253_cascade_ns_to_timer(devpriv->clockbase, &devpriv->divisor1, &devpriv->divisor2, - &ns, rounding_flags); + &ns, flags); i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY); i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY); @@ -782,9 +782,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) } /* set counter mode and counts */ - cmd->convert_arg = - das16_set_pacer(dev, cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); + cmd->convert_arg = das16_set_pacer(dev, cmd->convert_arg, cmd->flags); /* enable counters */ byte = 0; diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index ec039fbff0f9..5b6998b54060 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -60,7 +60,6 @@ irq can be omitted, although the cmd interface will not work without it. #include "8253.h" #include "comedi_fc.h" -#define DAS16M1_SIZE 16 #define DAS16M1_SIZE2 8 #define FIFO_SIZE 1024 /* 1024 sample fifo */ @@ -126,7 +125,7 @@ static const struct comedi_lrange range_das16m1 = { struct das16m1_private_struct { unsigned int control_state; - volatile unsigned int adc_count; /* number of samples completed */ + unsigned int adc_count; /* number of samples completed */ /* initial value in lower half of hardware conversion counter, * needed to keep track of whether new count has been loaded into * counter yet (loaded by first sample conversion) */ @@ -460,7 +459,7 @@ static void das16m1_handler(struct comedi_device *dev, unsigned int status) * overrun interrupts, but we might as well try */ if (status & OVRUN) { async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; - comedi_error(dev, "fifo overflow"); + dev_err(dev->class_dev, "fifo overflow\n"); } cfc_handle_events(dev, s); @@ -477,7 +476,7 @@ static int das16m1_poll(struct comedi_device *dev, struct comedi_subdevice *s) das16m1_handler(dev, status); spin_unlock_irqrestore(&dev->spinlock, flags); - return s->async->buf_write_count - s->async->buf_read_count; + return comedi_buf_n_bytes_ready(s); } static irqreturn_t das16m1_interrupt(int irq, void *d) @@ -486,7 +485,7 @@ static irqreturn_t das16m1_interrupt(int irq, void *d) struct comedi_device *dev = d; if (!dev->attached) { - comedi_error(dev, "premature interrupt"); + dev_err(dev->class_dev, "premature interrupt\n"); return IRQ_HANDLED; } /* prevent race with comedi_poll() */ @@ -495,7 +494,7 @@ static irqreturn_t das16m1_interrupt(int irq, void *d) status = inb(dev->iobase + DAS16M1_CS); if ((status & (IRQDATA | OVRUN)) == 0) { - comedi_error(dev, "spurious interrupt"); + dev_err(dev->class_dev, "spurious interrupt\n"); spin_unlock(&dev->spinlock); return IRQ_NONE; } @@ -549,7 +548,7 @@ static int das16m1_attach(struct comedi_device *dev, if (!devpriv) return -ENOMEM; - ret = comedi_request_region(dev, it->options[0], DAS16M1_SIZE); + ret = comedi_request_region(dev, it->options[0], 0x10); if (ret) return ret; /* Request an additional region for the 8255 */ diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 859519026c4c..0cfca33965f6 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -421,7 +421,7 @@ static const struct das1800_board das1800_boards[] = { }; struct das1800_private { - volatile unsigned int count; /* number of data points left to be taken */ + unsigned int count; /* number of data points left to be taken */ unsigned int divisor1; /* value to load into board's counter 1 for timed conversions */ unsigned int divisor2; /* value to load into board's counter 2 for timed conversions */ int irq_dma_bits; /* bits for control register b */ @@ -430,7 +430,7 @@ struct das1800_private { int dma_bits; unsigned int dma0; /* dma channels used */ unsigned int dma1; - volatile unsigned int dma_current; /* dma channel currently in use */ + unsigned int dma_current; /* dma channel currently in use */ uint16_t *ai_buf0; /* pointers to dma buffers */ uint16_t *ai_buf1; uint16_t *dma_current_buf; /* pointer to dma buffer currently being used */ @@ -492,7 +492,6 @@ static void das1800_handle_fifo_half_full(struct comedi_device *dev, numPoints * sizeof(devpriv->ai_buf0[0])); if (cmd->stop_src == TRIG_COUNT) devpriv->count -= numPoints; - return; } static void das1800_handle_fifo_not_empty(struct comedi_device *dev, @@ -517,8 +516,6 @@ static void das1800_handle_fifo_not_empty(struct comedi_device *dev, if (cmd->stop_src == TRIG_COUNT) devpriv->count--; } - - return; } /* Utility function used by das1800_flush_dma() and das1800_handle_dma(). @@ -549,8 +546,6 @@ static void das1800_flush_dma_channel(struct comedi_device *dev, cfc_write_array_to_buffer(s, buffer, num_bytes); if (cmd->stop_src == TRIG_COUNT) devpriv->count -= num_samples; - - return; } /* flushes remaining data from board when external trigger has stopped acquisition @@ -583,8 +578,6 @@ static void das1800_flush_dma(struct comedi_device *dev, /* get any remaining samples in fifo */ das1800_handle_fifo_not_empty(dev, s); - - return; } static void das1800_handle_dma(struct comedi_device *dev, @@ -619,8 +612,6 @@ static void das1800_handle_dma(struct comedi_device *dev, } } } - - return; } static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s) @@ -663,7 +654,7 @@ static void das1800_ai_handler(struct comedi_device *dev) if (status & OVF) { /* clear OVF interrupt bit */ outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS); - comedi_error(dev, "DAS1800 FIFO overflow"); + dev_err(dev->class_dev, "FIFO overflow\n"); async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; cfc_handle_events(dev, s); return; @@ -696,7 +687,7 @@ static int das1800_ai_poll(struct comedi_device *dev, das1800_ai_handler(dev); spin_unlock_irqrestore(&dev->spinlock, flags); - return s->async->buf_write_count - s->async->buf_read_count; + return comedi_buf_n_bytes_ready(s); } static irqreturn_t das1800_interrupt(int irq, void *d) @@ -705,7 +696,7 @@ static irqreturn_t das1800_interrupt(int irq, void *d) unsigned int status; if (!dev->attached) { - comedi_error(dev, "premature interrupt"); + dev_err(dev->class_dev, "premature interrupt\n"); return IRQ_HANDLED; } @@ -1060,8 +1051,6 @@ static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) enable_dma(devpriv->dma1); } release_dma_lock(lock_flags); - - return; } /* programs channel/gain list into card */ @@ -1088,8 +1077,6 @@ static void program_chanlist(struct comedi_device *dev, } outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */ spin_unlock_irqrestore(&dev->spinlock, irq_flags); - - return; } /* analog input do_cmd */ @@ -1192,7 +1179,7 @@ static int das1800_ai_rinsn(struct comedi_device *dev, break; } if (i == timeout) { - comedi_error(dev, "timeout"); + dev_err(dev->class_dev, "timeout\n"); n = -ETIME; goto exit; } @@ -1301,7 +1288,6 @@ static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0, dev_err(dev->class_dev, "dma 5,6 / 6,7 / or 7,5\n"); return -EINVAL; - break; } if (request_dma(dma0, dev->driver->driver_name)) { dev_err(dev->class_dev, @@ -1343,84 +1329,60 @@ static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0, static int das1800_probe(struct comedi_device *dev) { + const struct das1800_board *board = comedi_board(dev); + int index; int id; - int board; - id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf; /* get id bits */ - board = ((struct das1800_board *)dev->board_ptr) - das1800_boards; + /* calc the offset to the boardinfo that was found by the core */ + index = board - das1800_boards; + /* verify that the board id matches the boardinfo */ + id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf; switch (id) { case 0x3: - if (board == das1801st_da || board == das1802st_da || - board == das1701st_da || board == das1702st_da) { - dev_dbg(dev->class_dev, "Board model: %s\n", - das1800_boards[board].name); - return board; - } - printk - (" Board model (probed, not recommended): das-1800st-da series\n"); - return das1801st; + if (index == das1801st_da || index == das1802st_da || + index == das1701st_da || index == das1702st_da) + return index; + index = das1801st; break; case 0x4: - if (board == das1802hr_da || board == das1702hr_da) { - dev_dbg(dev->class_dev, "Board model: %s\n", - das1800_boards[board].name); - return board; - } - printk - (" Board model (probed, not recommended): das-1802hr-da\n"); - return das1802hr; + if (index == das1802hr_da || index == das1702hr_da) + return index; + index = das1802hr; break; case 0x5: - if (board == das1801ao || board == das1802ao || - board == das1701ao || board == das1702ao) { - dev_dbg(dev->class_dev, "Board model: %s\n", - das1800_boards[board].name); - return board; - } - printk - (" Board model (probed, not recommended): das-1800ao series\n"); - return das1801ao; + if (index == das1801ao || index == das1802ao || + index == das1701ao || index == das1702ao) + return index; + index = das1801ao; break; case 0x6: - if (board == das1802hr || board == das1702hr) { - dev_dbg(dev->class_dev, "Board model: %s\n", - das1800_boards[board].name); - return board; - } - printk - (" Board model (probed, not recommended): das-1802hr\n"); - return das1802hr; + if (index == das1802hr || index == das1702hr) + return index; + index = das1802hr; break; case 0x7: - if (board == das1801st || board == das1802st || - board == das1701st || board == das1702st) { - dev_dbg(dev->class_dev, "Board model: %s\n", - das1800_boards[board].name); - return board; - } - printk - (" Board model (probed, not recommended): das-1800st series\n"); - return das1801st; + if (index == das1801st || index == das1802st || + index == das1701st || index == das1702st) + return index; + index = das1801st; break; case 0x8: - if (board == das1801hc || board == das1802hc) { - dev_dbg(dev->class_dev, "Board model: %s\n", - das1800_boards[board].name); - return board; - } - printk - (" Board model (probed, not recommended): das-1800hc series\n"); - return das1801hc; + if (index == das1801hc || index == das1802hc) + return index; + index = das1801hc; break; default: - printk - (" Board model: probe returned 0x%x (unknown, please report)\n", - id); - return board; + dev_err(dev->class_dev, + "Board model: probe returned 0x%x (unknown, please report)\n", + id); break; } - return -1; + dev_err(dev->class_dev, + "Board model (probed, not recommended): %s series\n", + das1800_boards[index].name); + + return index; } static int das1800_attach(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index 6f7f8d531dd5..cbbb29797b83 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -65,7 +65,6 @@ cmd triggers supported: #include "8253.h" #include "comedi_fc.h" -#define DAS800_SIZE 8 #define N_CHAN_AI 8 /* number of analog input channels */ /* Registers for the das800 */ @@ -686,7 +685,7 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (!devpriv) return -ENOMEM; - ret = comedi_request_region(dev, it->options[0], DAS800_SIZE); + ret = comedi_request_region(dev, it->options[0], 0x8); if (ret) return ret; diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index ad7a5d53b97b..e9cd2517ad81 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -40,9 +40,6 @@ Configuration Options: #include "comedi_fc.h" /* Board register addresses */ - -#define DMM32AT_MEMSIZE 0x10 - #define DMM32AT_CONV 0x00 #define DMM32AT_AILSB 0x00 #define DMM32AT_AUXDOUT 0x01 @@ -237,7 +234,7 @@ static int dmm32at_ai_rinsn(struct comedi_device *dev, return n; } -static int dmm32at_ns_to_timer(unsigned int *ns, int round) +static int dmm32at_ns_to_timer(unsigned int *ns, unsigned int flags) { /* trivial timer */ return *ns; @@ -352,12 +349,12 @@ static int dmm32at_ai_cmdtest(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER) { arg = cmd->scan_begin_arg; - dmm32at_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + dmm32at_ns_to_timer(&arg, cmd->flags); err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (cmd->convert_src == TRIG_TIMER) { arg = cmd->convert_arg; - dmm32at_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + dmm32at_ns_to_timer(&arg, cmd->flags); err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); if (cmd->scan_begin_src == TRIG_TIMER) { @@ -491,7 +488,7 @@ static irqreturn_t dmm32at_isr(int irq, void *d) int i; if (!dev->attached) { - comedi_error(dev, "spurious interrupt"); + dev_err(dev->class_dev, "spurious interrupt\n"); return IRQ_HANDLED; } @@ -684,7 +681,7 @@ static int dmm32at_attach(struct comedi_device *dev, struct comedi_subdevice *s; unsigned char aihi, ailo, fifostat, aistat, intstat, airback; - ret = comedi_request_region(dev, it->options[0], DMM32AT_MEMSIZE); + ret = comedi_request_region(dev, it->options[0], 0x10); if (ret) return ret; diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index 4263014426f8..ad8ba0be4878 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -40,9 +40,6 @@ Configuration options: #define DT2801_MAX_DMA_SIZE (64 * 1024) -/* Ports */ -#define DT2801_IOSIZE 2 - /* define's */ /* ====================== */ @@ -552,7 +549,7 @@ static int dt2801_attach(struct comedi_device *dev, struct comedi_devconfig *it) int ret = 0; int n_ai_chans; - ret = comedi_request_region(dev, it->options[0], DT2801_IOSIZE); + ret = comedi_request_region(dev, it->options[0], 0x2); if (ret) return ret; diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index ba7c2ba618e6..a2e9caf3256f 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -169,8 +169,6 @@ static const struct comedi_lrange range_dt2811_pgl_ai_5_bipolar = { #define TIMEOUT 10000 -#define DT2811_SIZE 8 - #define DT2811_ADCSR 0 #define DT2811_ADGCR 1 #define DT2811_ADDATLO 2 @@ -344,7 +342,7 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it) int ret; struct comedi_subdevice *s; - ret = comedi_request_region(dev, it->options[0], DT2811_SIZE); + ret = comedi_request_region(dev, it->options[0], 0x8); if (ret) return ret; diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index 904c9f0e4afb..9216c35c414e 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -42,8 +42,6 @@ addition, the clock does not seem to be very accurate. #include "comedi_fc.h" -#define DT2814_SIZE 2 - #define DT2814_CSR 0 #define DT2814_DATA 1 @@ -171,7 +169,7 @@ static int dt2814_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ arg = cmd->scan_begin_arg; - dt2814_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + dt2814_ns_to_timer(&arg, cmd->flags); err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); if (err) @@ -187,9 +185,7 @@ static int dt2814_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) int chan; int trigvar; - trigvar = - dt2814_ns_to_timer(&cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); + trigvar = dt2814_ns_to_timer(&cmd->scan_begin_arg, cmd->flags); chan = CR_CHAN(cmd->chanlist[0]); @@ -209,7 +205,7 @@ static irqreturn_t dt2814_interrupt(int irq, void *d) int data; if (!dev->attached) { - comedi_error(dev, "spurious interrupt"); + dev_err(dev->class_dev, "spurious interrupt\n"); return IRQ_HANDLED; } @@ -245,7 +241,7 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it) int ret; int i; - ret = comedi_request_region(dev, it->options[0], DT2814_SIZE); + ret = comedi_request_region(dev, it->options[0], 0x2); if (ret) return ret; diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c index b9ac4ed8babb..a98fb66fdd53 100644 --- a/drivers/staging/comedi/drivers/dt2815.c +++ b/drivers/staging/comedi/drivers/dt2815.c @@ -56,8 +56,6 @@ Configuration options: #include <linux/delay.h> -#define DT2815_SIZE 2 - #define DT2815_DATA 0 #define DT2815_STATUS 1 @@ -154,7 +152,7 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it) const struct comedi_lrange *current_range_type, *voltage_range_type; int ret; - ret = comedi_request_region(dev, it->options[0], DT2815_SIZE); + ret = comedi_request_region(dev, it->options[0], 0x2); if (ret) return ret; @@ -195,6 +193,7 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it) status = inb(dev->iobase + DT2815_STATUS); if (status == 4) { unsigned int program; + program = (it->options[4] & 0x3) << 3 | 0x7; outb(program, dev->iobase + DT2815_DATA); dev_dbg(dev->class_dev, "program: 0x%x (@t=%d)\n", diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c index bf589936e546..5131deebf66f 100644 --- a/drivers/staging/comedi/drivers/dt2817.c +++ b/drivers/staging/comedi/drivers/dt2817.c @@ -36,8 +36,6 @@ Configuration options: #include <linux/module.h> #include "../comedidev.h" -#define DT2817_SIZE 5 - #define DT2817_CR 0 #define DT2817_DATA 1 @@ -114,7 +112,7 @@ static int dt2817_attach(struct comedi_device *dev, struct comedi_devconfig *it) int ret; struct comedi_subdevice *s; - ret = comedi_request_region(dev, it->options[0], DT2817_SIZE); + ret = comedi_request_region(dev, it->options[0], 0x5); if (ret) return ret; diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index c2a66dcf99fe..5de26745783a 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -1,55 +1,69 @@ /* - comedi/drivers/dt282x.c - Hardware driver for Data Translation DT2821 series - - 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. + * dt282x.c + * Comedi driver for Data Translation DT2821 series + * + * 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: dt282x -Description: Data Translation DT2821 series (including DT-EZ) -Author: ds -Devices: [Data Translation] DT2821 (dt2821), - DT2821-F-16SE (dt2821-f), DT2821-F-8DI (dt2821-f), - DT2821-G-16SE (dt2821-f), DT2821-G-8DI (dt2821-g), - DT2823 (dt2823), - DT2824-PGH (dt2824-pgh), DT2824-PGL (dt2824-pgl), DT2825 (dt2825), - DT2827 (dt2827), DT2828 (dt2828), DT21-EZ (dt21-ez), DT23-EZ (dt23-ez), - DT24-EZ (dt24-ez), DT24-EZ-PGL (dt24-ez-pgl) -Status: complete -Updated: Wed, 22 Aug 2001 17:11:34 -0700 - -Configuration options: - [0] - I/O port base address - [1] - IRQ - [2] - DMA 1 - [3] - DMA 2 - [4] - AI jumpered for 0=single ended, 1=differential - [5] - AI jumpered for 0=straight binary, 1=2's complement - [6] - AO 0 jumpered for 0=straight binary, 1=2's complement - [7] - AO 1 jumpered for 0=straight binary, 1=2's complement - [8] - AI jumpered for 0=[-10,10]V, 1=[0,10], 2=[-5,5], 3=[0,5] - [9] - AO 0 jumpered for 0=[-10,10]V, 1=[0,10], 2=[-5,5], 3=[0,5], - 4=[-2.5,2.5] - [10]- A0 1 jumpered for 0=[-10,10]V, 1=[0,10], 2=[-5,5], 3=[0,5], - 4=[-2.5,2.5] - -Notes: - - AO commands might be broken. - - If you try to run a command on both the AI and AO subdevices - simultaneously, bad things will happen. The driver needs to - be fixed to check for this situation and return an error. -*/ + * Driver: dt282x + * Description: Data Translation DT2821 series (including DT-EZ) + * Author: ds + * Devices: (Data Translation) DT2821 [dt2821] + * (Data Translation) DT2821-F-16SE [dt2821-f] + * (Data Translation) DT2821-F-8DI [dt2821-f] + * (Data Translation) DT2821-G-16SE [dt2821-g] + * (Data Translation) DT2821-G-8DI [dt2821-g] + * (Data Translation) DT2823 [dt2823] + * (Data Translation) DT2824-PGH [dt2824-pgh] + * (Data Translation) DT2824-PGL [dt2824-pgl] + * (Data Translation) DT2825 [dt2825] + * (Data Translation) DT2827 [dt2827] + * (Data Translation) DT2828 [dt2828] + * (Data Translation) DT2928 [dt2829] + * (Data Translation) DT21-EZ [dt21-ez] + * (Data Translation) DT23-EZ [dt23-ez] + * (Data Translation) DT24-EZ [dt24-ez] + * (Data Translation) DT24-EZ-PGL [dt24-ez-pgl] + * Status: complete + * Updated: Wed, 22 Aug 2001 17:11:34 -0700 + * + * Configuration options: + * [0] - I/O port base address + * [1] - IRQ (optional, required for async command support) + * [2] - DMA 1 (optional, required for async command support) + * [3] - DMA 2 (optional, required for async command support) + * [4] - AI jumpered for 0=single ended, 1=differential + * [5] - AI jumpered for 0=straight binary, 1=2's complement + * [6] - AO 0 data format (deprecated, see below) + * [7] - AO 1 data format (deprecated, see below) + * [8] - AI jumpered for 0=[-10,10]V, 1=[0,10], 2=[-5,5], 3=[0,5] + * [9] - AO channel 0 range (deprecated, see below) + * [10]- AO channel 1 range (deprecated, see below) + * + * Notes: + * - AO commands might be broken. + * - If you try to run a command on both the AI and AO subdevices + * simultaneously, bad things will happen. The driver needs to + * be fixed to check for this situation and return an error. + * - AO range is not programmable. The AO subdevice has a range_table + * containing all the possible analog output ranges. Use the range + * that matches your board configuration to convert between data + * values and physical units. The format of the data written to the + * board is handled automatically based on the unipolar/bipolar + * range that is selected. + */ #include <linux/module.h> #include "../comedidev.h" @@ -63,93 +77,53 @@ Notes: #include "comedi_fc.h" -#define DT2821_SIZE 0x10 - -/* - * Registers in the DT282x - */ - -#define DT2821_ADCSR 0x00 /* A/D Control/Status */ -#define DT2821_CHANCSR 0x02 /* Channel Control/Status */ -#define DT2821_ADDAT 0x04 /* A/D data */ -#define DT2821_DACSR 0x06 /* D/A Control/Status */ -#define DT2821_DADAT 0x08 /* D/A data */ -#define DT2821_DIODAT 0x0a /* digital data */ -#define DT2821_SUPCSR 0x0c /* Supervisor Control/Status */ -#define DT2821_TMRCTR 0x0e /* Timer/Counter */ - -/* - * At power up, some registers are in a well-known state. The - * masks and values are as follows: - */ - -#define DT2821_ADCSR_MASK 0xfff0 -#define DT2821_ADCSR_VAL 0x7c00 - -#define DT2821_CHANCSR_MASK 0xf0f0 -#define DT2821_CHANCSR_VAL 0x70f0 - -#define DT2821_DACSR_MASK 0x7c93 -#define DT2821_DACSR_VAL 0x7c90 - -#define DT2821_SUPCSR_MASK 0xf8ff -#define DT2821_SUPCSR_VAL 0x0000 - -#define DT2821_TMRCTR_MASK 0xff00 -#define DT2821_TMRCTR_VAL 0xf000 - /* - * Bit fields of each register + * Register map */ - -/* ADCSR */ - -#define DT2821_ADERR 0x8000 /* (R) 1 for A/D error */ -#define DT2821_ADCLK 0x0200 /* (R/W) A/D clock enable */ - /* 0x7c00 read as 1's */ -#define DT2821_MUXBUSY 0x0100 /* (R) multiplexer busy */ -#define DT2821_ADDONE 0x0080 /* (R) A/D done */ -#define DT2821_IADDONE 0x0040 /* (R/W) interrupt on A/D done */ - /* 0x0030 gain select */ - /* 0x000f channel select */ - -/* CHANCSR */ - -#define DT2821_LLE 0x8000 /* (R/W) Load List Enable */ - /* 0x7000 read as 1's */ - /* 0x0f00 (R) present address */ - /* 0x00f0 read as 1's */ - /* 0x000f (R) number of entries - 1 */ - -/* DACSR */ - -#define DT2821_DAERR 0x8000 /* (R) D/A error */ -#define DT2821_YSEL 0x0200 /* (R/W) DAC 1 select */ -#define DT2821_SSEL 0x0100 /* (R/W) single channel select */ -#define DT2821_DACRDY 0x0080 /* (R) DAC ready */ -#define DT2821_IDARDY 0x0040 /* (R/W) interrupt on DAC ready */ -#define DT2821_DACLK 0x0020 /* (R/W) D/A clock enable */ -#define DT2821_HBOE 0x0002 /* (R/W) DIO high byte output enable */ -#define DT2821_LBOE 0x0001 /* (R/W) DIO low byte output enable */ - -/* SUPCSR */ - -#define DT2821_DMAD 0x8000 /* (R) DMA done */ -#define DT2821_ERRINTEN 0x4000 /* (R/W) interrupt on error */ -#define DT2821_CLRDMADNE 0x2000 /* (W) clear DMA done */ -#define DT2821_DDMA 0x1000 /* (R/W) dual DMA */ -#define DT2821_DS1 0x0800 /* (R/W) DMA select 1 */ -#define DT2821_DS0 0x0400 /* (R/W) DMA select 0 */ -#define DT2821_BUFFB 0x0200 /* (R/W) buffer B selected */ -#define DT2821_SCDN 0x0100 /* (R) scan done */ -#define DT2821_DACON 0x0080 /* (W) DAC single conversion */ -#define DT2821_ADCINIT 0x0040 /* (W) A/D initialize */ -#define DT2821_DACINIT 0x0020 /* (W) D/A initialize */ -#define DT2821_PRLD 0x0010 /* (W) preload multiplexer */ -#define DT2821_STRIG 0x0008 /* (W) software trigger */ -#define DT2821_XTRIG 0x0004 /* (R/W) external trigger enable */ -#define DT2821_XCLK 0x0002 /* (R/W) external clock enable */ -#define DT2821_BDINIT 0x0001 /* (W) initialize board */ +#define DT2821_ADCSR_REG 0x00 +#define DT2821_ADCSR_ADERR (1 << 15) +#define DT2821_ADCSR_ADCLK (1 << 9) +#define DT2821_ADCSR_MUXBUSY (1 << 8) +#define DT2821_ADCSR_ADDONE (1 << 7) +#define DT2821_ADCSR_IADDONE (1 << 6) +#define DT2821_ADCSR_GS(x) (((x) & 0x3) << 4) +#define DT2821_ADCSR_CHAN(x) (((x) & 0xf) << 0) +#define DT2821_CHANCSR_REG 0x02 +#define DT2821_CHANCSR_LLE (1 << 15) +#define DT2821_CHANCSR_PRESLA(x) (((x) & 0xf) >> 8) +#define DT2821_CHANCSR_NUMB(x) ((((x) - 1) & 0xf) << 0) +#define DT2821_ADDAT_REG 0x04 +#define DT2821_DACSR_REG 0x06 +#define DT2821_DACSR_DAERR (1 << 15) +#define DT2821_DACSR_YSEL(x) ((x) << 9) +#define DT2821_DACSR_SSEL (1 << 8) +#define DT2821_DACSR_DACRDY (1 << 7) +#define DT2821_DACSR_IDARDY (1 << 6) +#define DT2821_DACSR_DACLK (1 << 5) +#define DT2821_DACSR_HBOE (1 << 1) +#define DT2821_DACSR_LBOE (1 << 0) +#define DT2821_DADAT_REG 0x08 +#define DT2821_DIODAT_REG 0x0a +#define DT2821_SUPCSR_REG 0x0c +#define DT2821_SUPCSR_DMAD (1 << 15) +#define DT2821_SUPCSR_ERRINTEN (1 << 14) +#define DT2821_SUPCSR_CLRDMADNE (1 << 13) +#define DT2821_SUPCSR_DDMA (1 << 12) +#define DT2821_SUPCSR_DS_PIO (0 << 10) +#define DT2821_SUPCSR_DS_AD_CLK (1 << 10) +#define DT2821_SUPCSR_DS_DA_CLK (2 << 10) +#define DT2821_SUPCSR_DS_AD_TRIG (3 << 10) +#define DT2821_SUPCSR_BUFFB (1 << 9) +#define DT2821_SUPCSR_SCDN (1 << 8) +#define DT2821_SUPCSR_DACON (1 << 7) +#define DT2821_SUPCSR_ADCINIT (1 << 6) +#define DT2821_SUPCSR_DACINIT (1 << 5) +#define DT2821_SUPCSR_PRLD (1 << 4) +#define DT2821_SUPCSR_STRIG (1 << 3) +#define DT2821_SUPCSR_XTRIG (1 << 2) +#define DT2821_SUPCSR_XCLK (1 << 1) +#define DT2821_SUPCSR_BDINIT (1 << 0) +#define DT2821_TMRCTR_REG 0x0e static const struct comedi_lrange range_dt282x_ai_lo_bipolar = { 4, { @@ -205,146 +179,326 @@ static const struct comedi_lrange range_dt282x_ai_hi_unipolar = { } }; +/* + * The Analog Output range is set per-channel using jumpers on the board. + * All of these ranges may not be available on some DT2821 series boards. + * The default jumper setting has both channels set for +/-10V output. + */ +static const struct comedi_lrange dt282x_ao_range = { + 5, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + UNI_RANGE(10), + UNI_RANGE(5), + } +}; + struct dt282x_board { const char *name; - int adbits; + unsigned int ai_maxdata; int adchan_se; int adchan_di; int ai_speed; int ispgl; int dachan; - int dabits; + unsigned int ao_maxdata; +}; + +static const struct dt282x_board boardtypes[] = { + { + .name = "dt2821", + .ai_maxdata = 0x0fff, + .adchan_se = 16, + .adchan_di = 8, + .ai_speed = 20000, + .dachan = 2, + .ao_maxdata = 0x0fff, + }, { + .name = "dt2821-f", + .ai_maxdata = 0x0fff, + .adchan_se = 16, + .adchan_di = 8, + .ai_speed = 6500, + .dachan = 2, + .ao_maxdata = 0x0fff, + }, { + .name = "dt2821-g", + .ai_maxdata = 0x0fff, + .adchan_se = 16, + .adchan_di = 8, + .ai_speed = 4000, + .dachan = 2, + .ao_maxdata = 0x0fff, + }, { + .name = "dt2823", + .ai_maxdata = 0xffff, + .adchan_di = 4, + .ai_speed = 10000, + .dachan = 2, + .ao_maxdata = 0xffff, + }, { + .name = "dt2824-pgh", + .ai_maxdata = 0x0fff, + .adchan_se = 16, + .adchan_di = 8, + .ai_speed = 20000, + }, { + .name = "dt2824-pgl", + .ai_maxdata = 0x0fff, + .adchan_se = 16, + .adchan_di = 8, + .ai_speed = 20000, + .ispgl = 1, + }, { + .name = "dt2825", + .ai_maxdata = 0x0fff, + .adchan_se = 16, + .adchan_di = 8, + .ai_speed = 20000, + .ispgl = 1, + .dachan = 2, + .ao_maxdata = 0x0fff, + }, { + .name = "dt2827", + .ai_maxdata = 0xffff, + .adchan_di = 4, + .ai_speed = 10000, + .dachan = 2, + .ao_maxdata = 0x0fff, + }, { + .name = "dt2828", + .ai_maxdata = 0x0fff, + .adchan_se = 4, + .ai_speed = 10000, + .dachan = 2, + .ao_maxdata = 0x0fff, + }, { + .name = "dt2829", + .ai_maxdata = 0xffff, + .adchan_se = 8, + .ai_speed = 33250, + .dachan = 2, + .ao_maxdata = 0xffff, + }, { + .name = "dt21-ez", + .ai_maxdata = 0x0fff, + .adchan_se = 16, + .adchan_di = 8, + .ai_speed = 10000, + .dachan = 2, + .ao_maxdata = 0x0fff, + }, { + .name = "dt23-ez", + .ai_maxdata = 0xffff, + .adchan_se = 16, + .adchan_di = 8, + .ai_speed = 10000, + }, { + .name = "dt24-ez", + .ai_maxdata = 0x0fff, + .adchan_se = 16, + .adchan_di = 8, + .ai_speed = 10000, + }, { + .name = "dt24-ez-pgl", + .ai_maxdata = 0x0fff, + .adchan_se = 16, + .adchan_di = 8, + .ai_speed = 10000, + .ispgl = 1, + }, }; struct dt282x_private { - int ad_2scomp; /* we have 2's comp jumper set */ - int da0_2scomp; /* same, for DAC0 */ - int da1_2scomp; /* same, for DAC1 */ + unsigned int ad_2scomp:1; - const struct comedi_lrange *darangelist[2]; + unsigned int divisor; - unsigned short ao[2]; + unsigned short ao_readback[2]; - volatile int dacsr; /* software copies of registers */ - volatile int adcsr; - volatile int supcsr; + int dacsr; /* software copies of registers */ + int adcsr; + int supcsr; - volatile int ntrig; - volatile int nread; + int ntrig; + int nread; struct { int chan; unsigned short *buf; /* DMA buffer */ - volatile int size; /* size of current transfer */ + int size; /* size of current transfer */ } dma[2]; int dma_maxsize; /* max size of DMA transfer (in bytes) */ - int usedma; /* driver uses DMA */ - volatile int current_dma_index; + int current_dma_index; int dma_dir; }; -/* - * Some useless abstractions - */ -#define chan_to_DAC(a) ((a)&1) +static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n) +{ + struct dt282x_private *devpriv = dev->private; + int dma_chan; + unsigned long dma_ptr; + unsigned long flags; -static int prep_ai_dma(struct comedi_device *dev, int chan, int size); -static int prep_ao_dma(struct comedi_device *dev, int chan, int size); -static int dt282x_ai_cancel(struct comedi_device *dev, - struct comedi_subdevice *s); -static int dt282x_ao_cancel(struct comedi_device *dev, - struct comedi_subdevice *s); -static int dt282x_ns_to_timer(int *nanosec, int round_mode); -static void dt282x_disable_dma(struct comedi_device *dev); + if (!devpriv->ntrig) + return 0; -static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2); + if (n == 0) + n = devpriv->dma_maxsize; + if (n > devpriv->ntrig * 2) + n = devpriv->ntrig * 2; + devpriv->ntrig -= n / 2; -static void dt282x_munge(struct comedi_device *dev, unsigned short *buf, - unsigned int nbytes) + devpriv->dma[dma_index].size = n; + dma_chan = devpriv->dma[dma_index].chan; + dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf); + + set_dma_mode(dma_chan, DMA_MODE_READ); + flags = claim_dma_lock(); + clear_dma_ff(dma_chan); + set_dma_addr(dma_chan, dma_ptr); + set_dma_count(dma_chan, n); + release_dma_lock(flags); + + enable_dma(dma_chan); + + return n; +} + +static int dt282x_prep_ao_dma(struct comedi_device *dev, int dma_index, int n) { - const struct dt282x_board *board = comedi_board(dev); struct dt282x_private *devpriv = dev->private; - unsigned int i; - unsigned short mask = (1 << board->adbits) - 1; - unsigned short sign = 1 << (board->adbits - 1); - int n; + int dma_chan; + unsigned long dma_ptr; + unsigned long flags; - if (devpriv->ad_2scomp) - sign = 1 << (board->adbits - 1); - else - sign = 0; + devpriv->dma[dma_index].size = n; + dma_chan = devpriv->dma[dma_index].chan; + dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf); - if (nbytes % 2) - comedi_error(dev, "bug! odd number of bytes from dma xfer"); - n = nbytes / 2; - for (i = 0; i < n; i++) - buf[i] = (buf[i] & mask) ^ sign; + set_dma_mode(dma_chan, DMA_MODE_WRITE); + flags = claim_dma_lock(); + clear_dma_ff(dma_chan); + set_dma_addr(dma_chan, dma_ptr); + set_dma_count(dma_chan, n); + release_dma_lock(flags); + + enable_dma(dma_chan); + + return n; } -static void dt282x_ao_dma_interrupt(struct comedi_device *dev) +static void dt282x_disable_dma(struct comedi_device *dev) { struct dt282x_private *devpriv = dev->private; - struct comedi_subdevice *s = dev->write_subdev; - void *ptr; - int size; + + disable_dma(devpriv->dma[0].chan); + disable_dma(devpriv->dma[1].chan); +} + +static unsigned int dt282x_ns_to_timer(unsigned int *ns, unsigned int flags) +{ + unsigned int prescale, base, divider; + + for (prescale = 0; prescale < 16; prescale++) { + if (prescale == 1) + continue; + base = 250 * (1 << prescale); + switch (flags & TRIG_ROUND_MASK) { + case TRIG_ROUND_NEAREST: + default: + divider = (*ns + base / 2) / base; + break; + case TRIG_ROUND_DOWN: + divider = (*ns) / base; + break; + case TRIG_ROUND_UP: + divider = (*ns + base - 1) / base; + break; + } + if (divider < 256) { + *ns = divider * base; + return (prescale << 8) | (255 - divider); + } + } + base = 250 * (1 << 15); + divider = 255; + *ns = divider * base; + return (15 << 8) | (255 - divider); +} + +static void dt282x_munge(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned short *buf, + unsigned int nbytes) +{ + struct dt282x_private *devpriv = dev->private; + unsigned int val; int i; - outw(devpriv->supcsr | DT2821_CLRDMADNE, dev->iobase + DT2821_SUPCSR); + if (nbytes % 2) + dev_err(dev->class_dev, + "bug! odd number of bytes from dma xfer\n"); - if (!s->async->prealloc_buf) { - dev_err(dev->class_dev, "no buffer in %s\n", __func__); - return; + for (i = 0; i < nbytes / 2; i++) { + val = buf[i]; + val &= s->maxdata; + if (devpriv->ad_2scomp) + val = comedi_offset_munge(s, val); + + buf[i] = val; } +} - i = devpriv->current_dma_index; - ptr = devpriv->dma[i].buf; +static void dt282x_ao_dma_interrupt(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct dt282x_private *devpriv = dev->private; + int cur_dma = devpriv->current_dma_index; + void *ptr = devpriv->dma[cur_dma].buf; + int size; - disable_dma(devpriv->dma[i].chan); + outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE, + dev->iobase + DT2821_SUPCSR_REG); - devpriv->current_dma_index = 1 - i; + disable_dma(devpriv->dma[cur_dma].chan); + + devpriv->current_dma_index = 1 - cur_dma; size = cfc_read_array_from_buffer(s, ptr, devpriv->dma_maxsize); if (size == 0) { dev_err(dev->class_dev, "AO underrun\n"); s->async->events |= COMEDI_CB_OVERFLOW; - return; + } else { + dt282x_prep_ao_dma(dev, cur_dma, size); } - prep_ao_dma(dev, i, size); - return; } -static void dt282x_ai_dma_interrupt(struct comedi_device *dev) +static void dt282x_ai_dma_interrupt(struct comedi_device *dev, + struct comedi_subdevice *s) { struct dt282x_private *devpriv = dev->private; - struct comedi_subdevice *s = dev->read_subdev; - void *ptr; - int size; - int i; + int cur_dma = devpriv->current_dma_index; + void *ptr = devpriv->dma[cur_dma].buf; + int size = devpriv->dma[cur_dma].size; int ret; - outw(devpriv->supcsr | DT2821_CLRDMADNE, dev->iobase + DT2821_SUPCSR); + outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE, + dev->iobase + DT2821_SUPCSR_REG); - if (!s->async->prealloc_buf) { - dev_err(dev->class_dev, "no buffer in %s\n", __func__); - return; - } - - i = devpriv->current_dma_index; - ptr = devpriv->dma[i].buf; - size = devpriv->dma[i].size; + disable_dma(devpriv->dma[cur_dma].chan); - disable_dma(devpriv->dma[i].chan); + devpriv->current_dma_index = 1 - cur_dma; - devpriv->current_dma_index = 1 - i; - - dt282x_munge(dev, ptr, size); + dt282x_munge(dev, s, ptr, size); ret = cfc_write_array_to_buffer(s, ptr, size); if (ret != size) { s->async->events |= COMEDI_CB_OVERFLOW; return; } - devpriv->nread -= size / 2; + devpriv->nread -= size / 2; if (devpriv->nread < 0) { dev_info(dev->class_dev, "nread off by one\n"); devpriv->nread = 0; @@ -357,67 +511,12 @@ static void dt282x_ai_dma_interrupt(struct comedi_device *dev) /* clear the dual dma flag, making this the last dma segment */ /* XXX probably wrong */ if (!devpriv->ntrig) { - devpriv->supcsr &= ~(DT2821_DDMA); - outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR); + devpriv->supcsr &= ~DT2821_SUPCSR_DDMA; + outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR_REG); } #endif /* restart the channel */ - prep_ai_dma(dev, i, 0); -} - -static int prep_ai_dma(struct comedi_device *dev, int dma_index, int n) -{ - struct dt282x_private *devpriv = dev->private; - int dma_chan; - unsigned long dma_ptr; - unsigned long flags; - - if (!devpriv->ntrig) - return 0; - - if (n == 0) - n = devpriv->dma_maxsize; - if (n > devpriv->ntrig * 2) - n = devpriv->ntrig * 2; - devpriv->ntrig -= n / 2; - - devpriv->dma[dma_index].size = n; - dma_chan = devpriv->dma[dma_index].chan; - dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf); - - set_dma_mode(dma_chan, DMA_MODE_READ); - flags = claim_dma_lock(); - clear_dma_ff(dma_chan); - set_dma_addr(dma_chan, dma_ptr); - set_dma_count(dma_chan, n); - release_dma_lock(flags); - - enable_dma(dma_chan); - - return n; -} - -static int prep_ao_dma(struct comedi_device *dev, int dma_index, int n) -{ - struct dt282x_private *devpriv = dev->private; - int dma_chan; - unsigned long dma_ptr; - unsigned long flags; - - devpriv->dma[dma_index].size = n; - dma_chan = devpriv->dma[dma_index].chan; - dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf); - - set_dma_mode(dma_chan, DMA_MODE_WRITE); - flags = claim_dma_lock(); - clear_dma_ff(dma_chan); - set_dma_addr(dma_chan, dma_ptr); - set_dma_count(dma_chan, n); - release_dma_lock(flags); - - enable_dma(dma_chan); - - return n; + dt282x_prep_ai_dma(dev, cur_dma, 0); } static irqreturn_t dt282x_interrupt(int irq, void *d) @@ -430,42 +529,42 @@ static irqreturn_t dt282x_interrupt(int irq, void *d) int handled = 0; if (!dev->attached) { - comedi_error(dev, "spurious interrupt"); + dev_err(dev->class_dev, "spurious interrupt\n"); return IRQ_HANDLED; } - adcsr = inw(dev->iobase + DT2821_ADCSR); - dacsr = inw(dev->iobase + DT2821_DACSR); - supcsr = inw(dev->iobase + DT2821_SUPCSR); - if (supcsr & DT2821_DMAD) { + adcsr = inw(dev->iobase + DT2821_ADCSR_REG); + dacsr = inw(dev->iobase + DT2821_DACSR_REG); + supcsr = inw(dev->iobase + DT2821_SUPCSR_REG); + if (supcsr & DT2821_SUPCSR_DMAD) { if (devpriv->dma_dir == DMA_MODE_READ) - dt282x_ai_dma_interrupt(dev); + dt282x_ai_dma_interrupt(dev, s); else - dt282x_ao_dma_interrupt(dev); + dt282x_ao_dma_interrupt(dev, s_ao); handled = 1; } - if (adcsr & DT2821_ADERR) { + if (adcsr & DT2821_ADCSR_ADERR) { if (devpriv->nread != 0) { - comedi_error(dev, "A/D error"); + dev_err(dev->class_dev, "A/D error\n"); s->async->events |= COMEDI_CB_ERROR; } handled = 1; } - if (dacsr & DT2821_DAERR) { - comedi_error(dev, "D/A error"); + if (dacsr & DT2821_DACSR_DAERR) { + dev_err(dev->class_dev, "D/A error\n"); s_ao->async->events |= COMEDI_CB_ERROR; handled = 1; } #if 0 - if (adcsr & DT2821_ADDONE) { + if (adcsr & DT2821_ADCSR_ADDONE) { int ret; unsigned short data; - data = inw(dev->iobase + DT2821_ADDAT); - data &= (1 << board->adbits) - 1; - + data = inw(dev->iobase + DT2821_ADDAT_REG); + data &= s->maxdata; if (devpriv->ad_2scomp) - data ^= 1 << (board->adbits - 1); + data = comedi_offset_munge(s, data); + ret = comedi_buf_put(s, data); if (ret == 0) @@ -475,9 +574,9 @@ static irqreturn_t dt282x_interrupt(int irq, void *d) if (!devpriv->nread) { s->async->events |= COMEDI_CB_EOA; } else { - if (supcsr & DT2821_SCDN) - outw(devpriv->supcsr | DT2821_STRIG, - dev->iobase + DT2821_SUPCSR); + if (supcsr & DT2821_SUPCSR_SCDN) + outw(devpriv->supcsr | DT2821_SUPCSR_STRIG, + dev->iobase + DT2821_SUPCSR_REG); } handled = 1; } @@ -492,17 +591,20 @@ static void dt282x_load_changain(struct comedi_device *dev, int n, unsigned int *chanlist) { struct dt282x_private *devpriv = dev->private; - unsigned int i; - unsigned int chan, range; + int i; - outw(DT2821_LLE | (n - 1), dev->iobase + DT2821_CHANCSR); + outw(DT2821_CHANCSR_LLE | DT2821_CHANCSR_NUMB(n), + dev->iobase + DT2821_CHANCSR_REG); for (i = 0; i < n; i++) { - chan = CR_CHAN(chanlist[i]); - range = CR_RANGE(chanlist[i]); - outw(devpriv->adcsr | (range << 4) | chan, - dev->iobase + DT2821_ADCSR); + unsigned int chan = CR_CHAN(chanlist[i]); + unsigned int range = CR_RANGE(chanlist[i]); + + outw(devpriv->adcsr | + DT2821_ADCSR_GS(range) | + DT2821_ADCSR_CHAN(chan), + dev->iobase + DT2821_ADCSR_REG); } - outw(n - 1, dev->iobase + DT2821_CHANCSR); + outw(DT2821_CHANCSR_NUMB(n), dev->iobase + DT2821_CHANCSR_REG); } static int dt282x_ai_timeout(struct comedi_device *dev, @@ -512,14 +614,14 @@ static int dt282x_ai_timeout(struct comedi_device *dev, { unsigned int status; - status = inw(dev->iobase + DT2821_ADCSR); + status = inw(dev->iobase + DT2821_ADCSR_REG); switch (context) { - case DT2821_MUXBUSY: - if ((status & DT2821_MUXBUSY) == 0) + case DT2821_ADCSR_MUXBUSY: + if ((status & DT2821_ADCSR_MUXBUSY) == 0) return 0; break; - case DT2821_ADDONE: - if (status & DT2821_ADDONE) + case DT2821_ADCSR_ADDONE: + if (status & DT2821_ADCSR_ADDONE) return 0; break; default: @@ -536,47 +638,53 @@ static int dt282x_ai_timeout(struct comedi_device *dev, */ static int dt282x_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) { - const struct dt282x_board *board = comedi_board(dev); struct dt282x_private *devpriv = dev->private; + unsigned int val; int ret; int i; /* XXX should we really be enabling the ad clock here? */ - devpriv->adcsr = DT2821_ADCLK; - outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR); + devpriv->adcsr = DT2821_ADCSR_ADCLK; + outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR_REG); dt282x_load_changain(dev, 1, &insn->chanspec); - outw(devpriv->supcsr | DT2821_PRLD, dev->iobase + DT2821_SUPCSR); - ret = comedi_timeout(dev, s, insn, dt282x_ai_timeout, DT2821_MUXBUSY); + outw(devpriv->supcsr | DT2821_SUPCSR_PRLD, + dev->iobase + DT2821_SUPCSR_REG); + ret = comedi_timeout(dev, s, insn, + dt282x_ai_timeout, DT2821_ADCSR_MUXBUSY); if (ret) return ret; for (i = 0; i < insn->n; i++) { - outw(devpriv->supcsr | DT2821_STRIG, - dev->iobase + DT2821_SUPCSR); + outw(devpriv->supcsr | DT2821_SUPCSR_STRIG, + dev->iobase + DT2821_SUPCSR_REG); - ret = comedi_timeout(dev, s, insn, dt282x_ai_timeout, - DT2821_ADDONE); + ret = comedi_timeout(dev, s, insn, + dt282x_ai_timeout, DT2821_ADCSR_ADDONE); if (ret) return ret; - data[i] = - inw(dev->iobase + - DT2821_ADDAT) & ((1 << board->adbits) - 1); + val = inw(dev->iobase + DT2821_ADDAT_REG); + val &= s->maxdata; if (devpriv->ad_2scomp) - data[i] ^= (1 << (board->adbits - 1)); + val = comedi_offset_munge(s, val); + + data[i] = val; } return i; } static int dt282x_ai_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_cmd *cmd) + struct comedi_subdevice *s, + struct comedi_cmd *cmd) { const struct dt282x_board *board = comedi_board(dev); + struct dt282x_private *devpriv = dev->private; int err = 0; unsigned int arg; @@ -634,7 +742,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ arg = cmd->convert_arg; - dt282x_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + devpriv->divisor = dt282x_ns_to_timer(&arg, cmd->flags); err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); if (err) @@ -645,81 +753,62 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev, static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - const struct dt282x_board *board = comedi_board(dev); struct dt282x_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; - int timer; int ret; - if (devpriv->usedma == 0) { - comedi_error(dev, - "driver requires 2 dma channels" - " to execute command"); - return -EIO; - } - dt282x_disable_dma(dev); - if (cmd->convert_arg < board->ai_speed) - cmd->convert_arg = board->ai_speed; - timer = dt282x_ns_to_timer(&cmd->convert_arg, TRIG_ROUND_NEAREST); - outw(timer, dev->iobase + DT2821_TMRCTR); + outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR_REG); - if (cmd->scan_begin_src == TRIG_FOLLOW) { - /* internal trigger */ - devpriv->supcsr = DT2821_ERRINTEN | DT2821_DS0; - } else { - /* external trigger */ - devpriv->supcsr = DT2821_ERRINTEN | DT2821_DS0 | DT2821_DS1; - } - outw(devpriv->supcsr | DT2821_CLRDMADNE | DT2821_BUFFB | DT2821_ADCINIT, - dev->iobase + DT2821_SUPCSR); + devpriv->supcsr = DT2821_SUPCSR_ERRINTEN; + if (cmd->scan_begin_src == TRIG_FOLLOW) + devpriv->supcsr = DT2821_SUPCSR_DS_AD_CLK; + else + devpriv->supcsr = DT2821_SUPCSR_DS_AD_TRIG; + outw(devpriv->supcsr | + DT2821_SUPCSR_CLRDMADNE | + DT2821_SUPCSR_BUFFB | + DT2821_SUPCSR_ADCINIT, + dev->iobase + DT2821_SUPCSR_REG); devpriv->ntrig = cmd->stop_arg * cmd->scan_end_arg; devpriv->nread = devpriv->ntrig; devpriv->dma_dir = DMA_MODE_READ; devpriv->current_dma_index = 0; - prep_ai_dma(dev, 0, 0); + dt282x_prep_ai_dma(dev, 0, 0); if (devpriv->ntrig) { - prep_ai_dma(dev, 1, 0); - devpriv->supcsr |= DT2821_DDMA; - outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR); + dt282x_prep_ai_dma(dev, 1, 0); + devpriv->supcsr |= DT2821_SUPCSR_DDMA; + outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR_REG); } devpriv->adcsr = 0; dt282x_load_changain(dev, cmd->chanlist_len, cmd->chanlist); - devpriv->adcsr = DT2821_ADCLK | DT2821_IADDONE; - outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR); + devpriv->adcsr = DT2821_ADCSR_ADCLK | DT2821_ADCSR_IADDONE; + outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR_REG); - outw(devpriv->supcsr | DT2821_PRLD, dev->iobase + DT2821_SUPCSR); - ret = comedi_timeout(dev, s, NULL, dt282x_ai_timeout, DT2821_MUXBUSY); + outw(devpriv->supcsr | DT2821_SUPCSR_PRLD, + dev->iobase + DT2821_SUPCSR_REG); + ret = comedi_timeout(dev, s, NULL, + dt282x_ai_timeout, DT2821_ADCSR_MUXBUSY); if (ret) return ret; if (cmd->scan_begin_src == TRIG_FOLLOW) { - outw(devpriv->supcsr | DT2821_STRIG, - dev->iobase + DT2821_SUPCSR); + outw(devpriv->supcsr | DT2821_SUPCSR_STRIG, + dev->iobase + DT2821_SUPCSR_REG); } else { - devpriv->supcsr |= DT2821_XTRIG; - outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR); + devpriv->supcsr |= DT2821_SUPCSR_XTRIG; + outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR_REG); } return 0; } -static void dt282x_disable_dma(struct comedi_device *dev) -{ - struct dt282x_private *devpriv = dev->private; - - if (devpriv->usedma) { - disable_dma(devpriv->dma[0].chan); - disable_dma(devpriv->dma[1].chan); - } -} - static int dt282x_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { @@ -728,101 +817,66 @@ static int dt282x_ai_cancel(struct comedi_device *dev, dt282x_disable_dma(dev); devpriv->adcsr = 0; - outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR); + outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR_REG); devpriv->supcsr = 0; - outw(devpriv->supcsr | DT2821_ADCINIT, dev->iobase + DT2821_SUPCSR); + outw(devpriv->supcsr | DT2821_SUPCSR_ADCINIT, + dev->iobase + DT2821_SUPCSR_REG); return 0; } -static int dt282x_ns_to_timer(int *nanosec, int round_mode) -{ - int prescale, base, divider; - - for (prescale = 0; prescale < 16; prescale++) { - if (prescale == 1) - continue; - base = 250 * (1 << prescale); - switch (round_mode) { - case TRIG_ROUND_NEAREST: - default: - divider = (*nanosec + base / 2) / base; - break; - case TRIG_ROUND_DOWN: - divider = (*nanosec) / base; - break; - case TRIG_ROUND_UP: - divider = (*nanosec + base - 1) / base; - break; - } - if (divider < 256) { - *nanosec = divider * base; - return (prescale << 8) | (255 - divider); - } - } - base = 250 * (1 << 15); - divider = 255; - *nanosec = divider * base; - return (15 << 8) | (255 - divider); -} - -/* - * Analog output routine. Selects single channel conversion, - * selects correct channel, converts from 2's compliment to - * offset binary if necessary, loads the data into the DAC - * data register, and performs the conversion. - */ static int dt282x_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct dt282x_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + int i; - data[0] = devpriv->ao[CR_CHAN(insn->chanspec)]; + for (i = 0; i < insn->n; i++) + data[i] = devpriv->ao_readback[chan]; - return 1; + return insn->n; } static int dt282x_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - const struct dt282x_board *board = comedi_board(dev); struct dt282x_private *devpriv = dev->private; - unsigned short d; - unsigned int chan; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); + unsigned int val; + int i; - chan = CR_CHAN(insn->chanspec); - d = data[0]; - d &= (1 << board->dabits) - 1; - devpriv->ao[chan] = d; + devpriv->dacsr |= DT2821_DACSR_SSEL | DT2821_DACSR_YSEL(chan); - devpriv->dacsr |= DT2821_SSEL; + for (i = 0; i < insn->n; i++) { + val = data[i]; + devpriv->ao_readback[chan] = val; - if (chan) { - /* select channel */ - devpriv->dacsr |= DT2821_YSEL; - if (devpriv->da0_2scomp) - d ^= (1 << (board->dabits - 1)); - } else { - devpriv->dacsr &= ~DT2821_YSEL; - if (devpriv->da1_2scomp) - d ^= (1 << (board->dabits - 1)); - } + if (comedi_range_is_bipolar(s, range)) + val = comedi_offset_munge(s, val); - outw(devpriv->dacsr, dev->iobase + DT2821_DACSR); + outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG); - outw(d, dev->iobase + DT2821_DADAT); + outw(val, dev->iobase + DT2821_DADAT_REG); - outw(devpriv->supcsr | DT2821_DACON, dev->iobase + DT2821_SUPCSR); + outw(devpriv->supcsr | DT2821_SUPCSR_DACON, + dev->iobase + DT2821_SUPCSR_REG); + } - return 1; + return insn->n; } static int dt282x_ao_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_cmd *cmd) + struct comedi_subdevice *s, + struct comedi_cmd *cmd) { + struct dt282x_private *devpriv = dev->private; int err = 0; unsigned int arg; @@ -865,7 +919,7 @@ static int dt282x_ao_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ arg = cmd->scan_begin_arg; - dt282x_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + devpriv->divisor = dt282x_ns_to_timer(&arg, cmd->flags); err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); if (err) @@ -892,7 +946,7 @@ static int dt282x_ao_inttrig(struct comedi_device *dev, dev_err(dev->class_dev, "AO underrun\n"); return -EPIPE; } - prep_ao_dma(dev, 0, size); + dt282x_prep_ao_dma(dev, 0, size); size = cfc_read_array_from_buffer(s, devpriv->dma[1].buf, devpriv->dma_maxsize); @@ -900,9 +954,10 @@ static int dt282x_ao_inttrig(struct comedi_device *dev, dev_err(dev->class_dev, "AO underrun\n"); return -EPIPE; } - prep_ao_dma(dev, 1, size); + dt282x_prep_ao_dma(dev, 1, size); - outw(devpriv->supcsr | DT2821_STRIG, dev->iobase + DT2821_SUPCSR); + outw(devpriv->supcsr | DT2821_SUPCSR_STRIG, + dev->iobase + DT2821_SUPCSR_REG); s->async->inttrig = NULL; return 1; @@ -911,21 +966,18 @@ static int dt282x_ao_inttrig(struct comedi_device *dev, static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct dt282x_private *devpriv = dev->private; - int timer; struct comedi_cmd *cmd = &s->async->cmd; - if (devpriv->usedma == 0) { - comedi_error(dev, - "driver requires 2 dma channels" - " to execute command"); - return -EIO; - } - dt282x_disable_dma(dev); - devpriv->supcsr = DT2821_ERRINTEN | DT2821_DS1 | DT2821_DDMA; - outw(devpriv->supcsr | DT2821_CLRDMADNE | DT2821_BUFFB | DT2821_DACINIT, - dev->iobase + DT2821_SUPCSR); + devpriv->supcsr = DT2821_SUPCSR_ERRINTEN | + DT2821_SUPCSR_DS_DA_CLK | + DT2821_SUPCSR_DDMA; + outw(devpriv->supcsr | + DT2821_SUPCSR_CLRDMADNE | + DT2821_SUPCSR_BUFFB | + DT2821_SUPCSR_DACINIT, + dev->iobase + DT2821_SUPCSR_REG); devpriv->ntrig = cmd->stop_arg * cmd->chanlist_len; devpriv->nread = devpriv->ntrig; @@ -933,11 +985,15 @@ static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->dma_dir = DMA_MODE_WRITE; devpriv->current_dma_index = 0; - timer = dt282x_ns_to_timer(&cmd->scan_begin_arg, TRIG_ROUND_NEAREST); - outw(timer, dev->iobase + DT2821_TMRCTR); + outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR_REG); + + /* clear all bits but the DIO direction bits */ + devpriv->dacsr &= (DT2821_DACSR_LBOE | DT2821_DACSR_HBOE); - devpriv->dacsr = DT2821_SSEL | DT2821_DACLK | DT2821_IDARDY; - outw(devpriv->dacsr, dev->iobase + DT2821_DACSR); + devpriv->dacsr |= (DT2821_DACSR_SSEL | + DT2821_DACSR_DACLK | + DT2821_DACSR_IDARDY); + outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG); s->async->inttrig = dt282x_ao_inttrig; @@ -951,11 +1007,14 @@ static int dt282x_ao_cancel(struct comedi_device *dev, dt282x_disable_dma(dev); - devpriv->dacsr = 0; - outw(devpriv->dacsr, dev->iobase + DT2821_DACSR); + /* clear all bits but the DIO direction bits */ + devpriv->dacsr &= (DT2821_DACSR_LBOE | DT2821_DACSR_HBOE); + + outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG); devpriv->supcsr = 0; - outw(devpriv->supcsr | DT2821_DACINIT, dev->iobase + DT2821_SUPCSR); + outw(devpriv->supcsr | DT2821_SUPCSR_DACINIT, + dev->iobase + DT2821_SUPCSR_REG); return 0; } @@ -966,9 +1025,9 @@ static int dt282x_dio_insn_bits(struct comedi_device *dev, unsigned int *data) { if (comedi_dio_update_state(s, data)) - outw(s->state, dev->iobase + DT2821_DIODAT); + outw(s->state, dev->iobase + DT2821_DIODAT_REG); - data[1] = inw(dev->iobase + DT2821_DIODAT); + data[1] = inw(dev->iobase + DT2821_DIODAT_REG); return insn->n; } @@ -992,13 +1051,13 @@ static int dt282x_dio_insn_config(struct comedi_device *dev, if (ret) return ret; - devpriv->dacsr &= ~(DT2821_LBOE | DT2821_HBOE); + devpriv->dacsr &= ~(DT2821_DACSR_LBOE | DT2821_DACSR_HBOE); if (s->io_bits & 0x00ff) - devpriv->dacsr |= DT2821_LBOE; + devpriv->dacsr |= DT2821_DACSR_LBOE; if (s->io_bits & 0xff00) - devpriv->dacsr |= DT2821_HBOE; + devpriv->dacsr |= DT2821_DACSR_HBOE; - outw(devpriv->dacsr, dev->iobase + DT2821_DACSR); + outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG); return insn->n; } @@ -1021,55 +1080,18 @@ static const struct comedi_lrange *opt_ai_range_lkup(int ispgl, int x) if (x < 0 || x >= 2) x = 0; return ai_range_pgl_table[x]; - } else { - if (x < 0 || x >= 4) - x = 0; - return ai_range_table[x]; } -} -static const struct comedi_lrange *const ao_range_table[] = { - &range_bipolar10, - &range_unipolar10, - &range_bipolar5, - &range_unipolar5, - &range_bipolar2_5 -}; - -static const struct comedi_lrange *opt_ao_range_lkup(int x) -{ - if (x < 0 || x >= 5) + if (x < 0 || x >= 4) x = 0; - return ao_range_table[x]; + return ai_range_table[x]; } -enum { /* i/o base, irq, dma channels */ - opt_iobase = 0, opt_irq, opt_dma1, opt_dma2, - opt_diff, /* differential */ - opt_ai_twos, opt_ao0_twos, opt_ao1_twos, /* twos comp */ - opt_ai_range, opt_ao0_range, opt_ao1_range, /* range */ -}; - static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2) { struct dt282x_private *devpriv = dev->private; int ret; - devpriv->usedma = 0; - - if (!dma1 && !dma2) - return 0; - - if (dma1 == dma2 || dma1 < 5 || dma2 < 5 || dma1 > 7 || dma2 > 7) - return -EINVAL; - - if (dma2 < dma1) { - int i; - i = dma1; - dma1 = dma2; - dma2 = i; - } - ret = request_dma(dma1, "dt282x A"); if (ret) return -EBUSY; @@ -1086,8 +1108,45 @@ static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2) if (!devpriv->dma[0].buf || !devpriv->dma[1].buf) return -ENOMEM; - devpriv->usedma = 1; + return 0; +} +static void dt282x_free_dma(struct comedi_device *dev) +{ + struct dt282x_private *devpriv = dev->private; + int i; + + if (!devpriv) + return; + + for (i = 0; i < 2; i++) { + if (devpriv->dma[i].chan) + free_dma(devpriv->dma[i].chan); + if (devpriv->dma[i].buf) + free_page((unsigned long)devpriv->dma[i].buf); + devpriv->dma[i].chan = 0; + devpriv->dma[i].buf = NULL; + } +} + +static int dt282x_initialize(struct comedi_device *dev) +{ + /* Initialize board */ + outw(DT2821_SUPCSR_BDINIT, dev->iobase + DT2821_SUPCSR_REG); + inw(dev->iobase + DT2821_ADCSR_REG); + + /* + * At power up, some registers are in a well-known state. + * Check them to see if a DT2821 series board is present. + */ + if (((inw(dev->iobase + DT2821_ADCSR_REG) & 0xfff0) != 0x7c00) || + ((inw(dev->iobase + DT2821_CHANCSR_REG) & 0xf0f0) != 0x70f0) || + ((inw(dev->iobase + DT2821_DACSR_REG) & 0x7c93) != 0x7c90) || + ((inw(dev->iobase + DT2821_SUPCSR_REG) & 0xf8ff) != 0x0000) || + ((inw(dev->iobase + DT2821_TMRCTR_REG) & 0xff00) != 0xf000)) { + dev_err(dev->class_dev, "board not found\n"); + return -EIO; + } return 0; } @@ -1111,263 +1170,125 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct dt282x_private *devpriv; struct comedi_subdevice *s; int ret; - int i; - ret = comedi_request_region(dev, it->options[0], DT2821_SIZE); + ret = comedi_request_region(dev, it->options[0], 0x10); if (ret) return ret; - outw(DT2821_BDINIT, dev->iobase + DT2821_SUPCSR); - i = inw(dev->iobase + DT2821_ADCSR); - - if (((inw(dev->iobase + DT2821_ADCSR) & DT2821_ADCSR_MASK) - != DT2821_ADCSR_VAL) || - ((inw(dev->iobase + DT2821_CHANCSR) & DT2821_CHANCSR_MASK) - != DT2821_CHANCSR_VAL) || - ((inw(dev->iobase + DT2821_DACSR) & DT2821_DACSR_MASK) - != DT2821_DACSR_VAL) || - ((inw(dev->iobase + DT2821_SUPCSR) & DT2821_SUPCSR_MASK) - != DT2821_SUPCSR_VAL) || - ((inw(dev->iobase + DT2821_TMRCTR) & DT2821_TMRCTR_MASK) - != DT2821_TMRCTR_VAL)) { - dev_err(dev->class_dev, "board not found\n"); - return -EIO; - } - /* should do board test */ - - if (it->options[opt_irq] > 0) { - ret = request_irq(it->options[opt_irq], dt282x_interrupt, 0, - dev->board_name, dev); - if (ret == 0) - dev->irq = it->options[opt_irq]; - } + ret = dt282x_initialize(dev); + if (ret) + return ret; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - if (dev->irq) { - ret = dt282x_grab_dma(dev, it->options[opt_dma1], - it->options[opt_dma2]); - if (ret < 0) - return ret; + /* an IRQ and 2 DMA channels are required for async command support */ + if (it->options[1] && it->options[2] && it->options[3]) { + unsigned int irq = it->options[1]; + unsigned int dma1 = it->options[2]; + unsigned int dma2 = it->options[3]; + + if (dma2 < dma1) { + unsigned int swap; + + swap = dma1; + dma1 = dma2; + dma2 = swap; + } + + if (dma1 != dma2 && + dma1 >= 5 && dma1 <= 7 && + dma2 >= 5 && dma2 <= 7) { + ret = request_irq(irq, dt282x_interrupt, 0, + dev->board_name, dev); + if (ret == 0) { + dev->irq = irq; + + ret = dt282x_grab_dma(dev, dma1, dma2); + if (ret < 0) { + dt282x_free_dma(dev); + free_irq(dev->irq, dev); + dev->irq = 0; + } + } + } } ret = comedi_alloc_subdevices(dev, 3); if (ret) return ret; + /* Analog Input subdevice */ s = &dev->subdevices[0]; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE; + if ((it->options[4] && board->adchan_di) || board->adchan_se == 0) { + s->subdev_flags |= SDF_DIFF; + s->n_chan = board->adchan_di; + } else { + s->subdev_flags |= SDF_COMMON; + s->n_chan = board->adchan_se; + } + s->maxdata = board->ai_maxdata; + + s->range_table = opt_ai_range_lkup(board->ispgl, it->options[8]); + devpriv->ad_2scomp = it->options[5] ? 1 : 0; - /* ai subdevice */ - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | - ((it->options[opt_diff]) ? SDF_DIFF : SDF_COMMON); - s->n_chan = - (it->options[opt_diff]) ? board->adchan_di : board->adchan_se; - s->insn_read = dt282x_ai_insn_read; - s->maxdata = (1 << board->adbits) - 1; - s->range_table = - opt_ai_range_lkup(board->ispgl, it->options[opt_ai_range]); - devpriv->ad_2scomp = it->options[opt_ai_twos]; + s->insn_read = dt282x_ai_insn_read; if (dev->irq) { dev->read_subdev = s; - s->subdev_flags |= SDF_CMD_READ; - s->len_chanlist = 16; - s->do_cmdtest = dt282x_ai_cmdtest; - s->do_cmd = dt282x_ai_cmd; - s->cancel = dt282x_ai_cancel; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = s->n_chan; + s->do_cmdtest = dt282x_ai_cmdtest; + s->do_cmd = dt282x_ai_cmd; + s->cancel = dt282x_ai_cancel; } + /* Analog Output subdevice */ s = &dev->subdevices[1]; + if (board->dachan) { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = board->dachan; + s->maxdata = board->ao_maxdata; - s->n_chan = board->dachan; - if (s->n_chan) { - /* ao subsystem */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE; - s->insn_read = dt282x_ao_insn_read; - s->insn_write = dt282x_ao_insn_write; - s->maxdata = (1 << board->dabits) - 1; - s->range_table_list = devpriv->darangelist; - devpriv->darangelist[0] = - opt_ao_range_lkup(it->options[opt_ao0_range]); - devpriv->darangelist[1] = - opt_ao_range_lkup(it->options[opt_ao1_range]); - devpriv->da0_2scomp = it->options[opt_ao0_twos]; - devpriv->da1_2scomp = it->options[opt_ao1_twos]; + /* ranges are per-channel, set by jumpers on the board */ + s->range_table = &dt282x_ao_range; + + s->insn_read = dt282x_ao_insn_read; + s->insn_write = dt282x_ao_insn_write; if (dev->irq) { dev->write_subdev = s; - s->subdev_flags |= SDF_CMD_WRITE; - s->len_chanlist = 2; - s->do_cmdtest = dt282x_ao_cmdtest; - s->do_cmd = dt282x_ao_cmd; - s->cancel = dt282x_ao_cancel; + s->subdev_flags |= SDF_CMD_WRITE; + s->len_chanlist = s->n_chan; + s->do_cmdtest = dt282x_ao_cmdtest; + s->do_cmd = dt282x_ao_cmd; + s->cancel = dt282x_ao_cancel; } } else { - s->type = COMEDI_SUBD_UNUSED; + 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 = 16; - s->insn_bits = dt282x_dio_insn_bits; - s->insn_config = dt282x_dio_insn_config; - s->maxdata = 1; - s->range_table = &range_digital; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = dt282x_dio_insn_bits; + s->insn_config = dt282x_dio_insn_config; return 0; } static void dt282x_detach(struct comedi_device *dev) { - struct dt282x_private *devpriv = dev->private; - - if (dev->private) { - if (devpriv->dma[0].chan) - free_dma(devpriv->dma[0].chan); - if (devpriv->dma[1].chan) - free_dma(devpriv->dma[1].chan); - if (devpriv->dma[0].buf) - free_page((unsigned long)devpriv->dma[0].buf); - if (devpriv->dma[1].buf) - free_page((unsigned long)devpriv->dma[1].buf); - } + dt282x_free_dma(dev); comedi_legacy_detach(dev); } -static const struct dt282x_board boardtypes[] = { - { - .name = "dt2821", - .adbits = 12, - .adchan_se = 16, - .adchan_di = 8, - .ai_speed = 20000, - .ispgl = 0, - .dachan = 2, - .dabits = 12, - }, { - .name = "dt2821-f", - .adbits = 12, - .adchan_se = 16, - .adchan_di = 8, - .ai_speed = 6500, - .ispgl = 0, - .dachan = 2, - .dabits = 12, - }, { - .name = "dt2821-g", - .adbits = 12, - .adchan_se = 16, - .adchan_di = 8, - .ai_speed = 4000, - .ispgl = 0, - .dachan = 2, - .dabits = 12, - }, { - .name = "dt2823", - .adbits = 16, - .adchan_se = 0, - .adchan_di = 4, - .ai_speed = 10000, - .ispgl = 0, - .dachan = 2, - .dabits = 16, - }, { - .name = "dt2824-pgh", - .adbits = 12, - .adchan_se = 16, - .adchan_di = 8, - .ai_speed = 20000, - .ispgl = 0, - .dachan = 0, - .dabits = 0, - }, { - .name = "dt2824-pgl", - .adbits = 12, - .adchan_se = 16, - .adchan_di = 8, - .ai_speed = 20000, - .ispgl = 1, - .dachan = 0, - .dabits = 0, - }, { - .name = "dt2825", - .adbits = 12, - .adchan_se = 16, - .adchan_di = 8, - .ai_speed = 20000, - .ispgl = 1, - .dachan = 2, - .dabits = 12, - }, { - .name = "dt2827", - .adbits = 16, - .adchan_se = 0, - .adchan_di = 4, - .ai_speed = 10000, - .ispgl = 0, - .dachan = 2, - .dabits = 12, - }, { - .name = "dt2828", - .adbits = 12, - .adchan_se = 4, - .adchan_di = 0, - .ai_speed = 10000, - .ispgl = 0, - .dachan = 2, - .dabits = 12, - }, { - .name = "dt2829", - .adbits = 16, - .adchan_se = 8, - .adchan_di = 0, - .ai_speed = 33250, - .ispgl = 0, - .dachan = 2, - .dabits = 16, - }, { - .name = "dt21-ez", - .adbits = 12, - .adchan_se = 16, - .adchan_di = 8, - .ai_speed = 10000, - .ispgl = 0, - .dachan = 2, - .dabits = 12, - }, { - .name = "dt23-ez", - .adbits = 16, - .adchan_se = 16, - .adchan_di = 8, - .ai_speed = 10000, - .ispgl = 0, - .dachan = 0, - .dabits = 0, - }, { - .name = "dt24-ez", - .adbits = 12, - .adchan_se = 16, - .adchan_di = 8, - .ai_speed = 10000, - .ispgl = 0, - .dachan = 0, - .dabits = 0, - }, { - .name = "dt24-ez-pgl", - .adbits = 12, - .adchan_se = 16, - .adchan_di = 8, - .ai_speed = 10000, - .ispgl = 1, - .dachan = 0, - .dabits = 0, - }, -}; - static struct comedi_driver dt282x_driver = { .driver_name = "dt282x", .module = THIS_MODULE, @@ -1380,5 +1301,5 @@ static struct comedi_driver dt282x_driver = { module_comedi_driver(dt282x_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for Data Translation DT2821 series"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 4ab4de005924..56e21cc2dcfe 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -244,7 +244,6 @@ static const struct dt3k_boardtype dt3k_boardtypes[] = { #define DT3000_CHANNEL_MODE_DI 1 struct dt3k_private { - void __iomem *io_addr; unsigned int lock; unsigned int ao_readback[2]; unsigned int ai_front; @@ -255,14 +254,13 @@ struct dt3k_private { static void dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd) { - struct dt3k_private *devpriv = dev->private; int i; unsigned int status = 0; - writew(cmd, devpriv->io_addr + DPR_Command_Mbx); + writew(cmd, dev->mmio + DPR_Command_Mbx); for (i = 0; i < TIMEOUT; i++) { - status = readw(devpriv->io_addr + DPR_Command_Mbx); + status = readw(dev->mmio + DPR_Command_Mbx); if ((status & DT3000_COMPLETION_MASK) != DT3000_NOTPROCESSED) break; udelay(1); @@ -277,28 +275,24 @@ static unsigned int dt3k_readsingle(struct comedi_device *dev, unsigned int subsys, unsigned int chan, unsigned int gain) { - struct dt3k_private *devpriv = dev->private; - - writew(subsys, devpriv->io_addr + DPR_SubSys); + writew(subsys, dev->mmio + DPR_SubSys); - writew(chan, devpriv->io_addr + DPR_Params(0)); - writew(gain, devpriv->io_addr + DPR_Params(1)); + writew(chan, dev->mmio + DPR_Params(0)); + writew(gain, dev->mmio + DPR_Params(1)); dt3k_send_cmd(dev, CMD_READSINGLE); - return readw(devpriv->io_addr + 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) { - struct dt3k_private *devpriv = dev->private; - - writew(subsys, devpriv->io_addr + DPR_SubSys); + writew(subsys, dev->mmio + DPR_SubSys); - writew(chan, devpriv->io_addr + DPR_Params(0)); - writew(0, devpriv->io_addr + DPR_Params(1)); - writew(data, devpriv->io_addr + 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); } @@ -313,7 +307,7 @@ static void dt3k_ai_empty_fifo(struct comedi_device *dev, int i; unsigned short data; - front = readw(devpriv->io_addr + DPR_AD_Buf_Front); + front = readw(dev->mmio + DPR_AD_Buf_Front); count = front - devpriv->ai_front; if (count < 0) count += AI_FIFO_DEPTH; @@ -321,7 +315,7 @@ static void dt3k_ai_empty_fifo(struct comedi_device *dev, rear = devpriv->ai_rear; for (i = 0; i < count; i++) { - data = readw(devpriv->io_addr + DPR_ADC_buffer + rear); + data = readw(dev->mmio + DPR_ADC_buffer + rear); comedi_buf_put(s, data); rear++; if (rear >= AI_FIFO_DEPTH) @@ -329,17 +323,16 @@ static void dt3k_ai_empty_fifo(struct comedi_device *dev, } devpriv->ai_rear = rear; - writew(rear, devpriv->io_addr + 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) +static int dt3k_ai_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) { - struct dt3k_private *devpriv = dev->private; - - writew(SUBS_AI, devpriv->io_addr + DPR_SubSys); + writew(SUBS_AI, dev->mmio + DPR_SubSys); dt3k_send_cmd(dev, CMD_STOP); - writew(0, devpriv->io_addr + DPR_Int_Mask); + writew(0, dev->mmio + DPR_Int_Mask); return 0; } @@ -351,14 +344,13 @@ static int debug_n_ints; static irqreturn_t dt3k_interrupt(int irq, void *d) { struct comedi_device *dev = d; - struct dt3k_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; unsigned int status; if (!dev->attached) return IRQ_NONE; - status = readw(devpriv->io_addr + DPR_Intr_Flag); + status = readw(dev->mmio + DPR_Intr_Flag); if (status & DT3000_ADFULL) { dt3k_ai_empty_fifo(dev, s); @@ -377,7 +369,7 @@ static irqreturn_t dt3k_interrupt(int irq, void *d) } static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec, - unsigned int round_mode) + unsigned int flags) { int divider, base, prescale; @@ -386,7 +378,7 @@ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec, for (prescale = 0; prescale < 16; prescale++) { base = timer_base * (prescale + 1); - switch (round_mode) { + switch (flags & TRIG_ROUND_MASK) { case TRIG_ROUND_NEAREST: default: divider = (*nanosec + base / 2) / base; @@ -467,13 +459,13 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER) { arg = cmd->scan_begin_arg; - dt3k_ns_to_timer(100, &arg, cmd->flags & TRIG_ROUND_MASK); + dt3k_ns_to_timer(100, &arg, cmd->flags); err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (cmd->convert_src == TRIG_TIMER) { arg = cmd->convert_arg; - dt3k_ns_to_timer(50, &arg, cmd->flags & TRIG_ROUND_MASK); + dt3k_ns_to_timer(50, &arg, cmd->flags); err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); if (cmd->scan_begin_src == TRIG_TIMER) { @@ -491,7 +483,6 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev, static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - struct dt3k_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; int i; unsigned int chan, range, aref; @@ -503,42 +494,40 @@ 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, - devpriv->io_addr + 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, devpriv->io_addr + 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 & TRIG_ROUND_MASK); - writew((divider >> 16), devpriv->io_addr + DPR_Params(1)); - writew((divider & 0xffff), devpriv->io_addr + DPR_Params(2)); + 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)); } if (cmd->scan_begin_src == TRIG_TIMER) { tscandiv = dt3k_ns_to_timer(100, &cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); - writew((tscandiv >> 16), devpriv->io_addr + DPR_Params(3)); - writew((tscandiv & 0xffff), devpriv->io_addr + DPR_Params(4)); + cmd->flags); + writew((tscandiv >> 16), dev->mmio + DPR_Params(3)); + writew((tscandiv & 0xffff), dev->mmio + DPR_Params(4)); } mode = DT3000_AD_RETRIG_INTERNAL | 0 | 0; - writew(mode, devpriv->io_addr + DPR_Params(5)); - writew(aref == AREF_DIFF, devpriv->io_addr + DPR_Params(6)); + writew(mode, dev->mmio + DPR_Params(5)); + writew(aref == AREF_DIFF, dev->mmio + DPR_Params(6)); - writew(AI_FIFO_DEPTH / 2, devpriv->io_addr + DPR_Params(7)); + writew(AI_FIFO_DEPTH / 2, dev->mmio + DPR_Params(7)); - writew(SUBS_AI, devpriv->io_addr + DPR_SubSys); + writew(SUBS_AI, dev->mmio + DPR_SubSys); dt3k_send_cmd(dev, CMD_CONFIG); writew(DT3000_ADFULL | DT3000_ADSWERR | DT3000_ADHWERR, - devpriv->io_addr + DPR_Int_Mask); + dev->mmio + DPR_Int_Mask); debug_n_ints = 0; - writew(SUBS_AI, devpriv->io_addr + DPR_SubSys); + writew(SUBS_AI, dev->mmio + DPR_SubSys); dt3k_send_cmd(dev, CMD_START); return 0; @@ -594,16 +583,14 @@ static int dt3k_ao_insn_read(struct comedi_device *dev, static void dt3k_dio_config(struct comedi_device *dev, int bits) { - struct dt3k_private *devpriv = dev->private; - /* XXX */ - writew(SUBS_DOUT, devpriv->io_addr + DPR_SubSys); + writew(SUBS_DOUT, dev->mmio + DPR_SubSys); - writew(bits, devpriv->io_addr + DPR_Params(0)); + writew(bits, dev->mmio + DPR_Params(0)); #if 0 /* don't know */ - writew(0, devpriv->io_addr + DPR_Params(1)); - writew(0, devpriv->io_addr + DPR_Params(2)); + writew(0, dev->mmio + DPR_Params(1)); + writew(0, dev->mmio + DPR_Params(2)); #endif dt3k_send_cmd(dev, CMD_CONFIG); @@ -647,20 +634,20 @@ static int dt3k_dio_insn_bits(struct comedi_device *dev, static int dt3k_mem_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 dt3k_private *devpriv = dev->private; unsigned int addr = CR_CHAN(insn->chanspec); int i; for (i = 0; i < insn->n; i++) { - writew(SUBS_MEM, devpriv->io_addr + DPR_SubSys); - writew(addr, devpriv->io_addr + DPR_Params(0)); - writew(1, devpriv->io_addr + DPR_Params(1)); + writew(SUBS_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); - data[i] = readw(devpriv->io_addr + DPR_Params(2)); + data[i] = readw(dev->mmio + DPR_Params(2)); } return i; @@ -690,8 +677,8 @@ static int dt3000_auto_attach(struct comedi_device *dev, if (ret < 0) return ret; - devpriv->io_addr = pci_ioremap_bar(pcidev, 0); - if (!devpriv->io_addr) + dev->mmio = pci_ioremap_bar(pcidev, 0); + if (!dev->mmio) return -ENOMEM; if (pcidev->irq) { @@ -765,14 +752,10 @@ static int dt3000_auto_attach(struct comedi_device *dev, static void dt3000_detach(struct comedi_device *dev) { - struct dt3k_private *devpriv = dev->private; - if (dev->irq) free_irq(dev->irq, dev); - if (devpriv) { - if (devpriv->io_addr) - iounmap(devpriv->io_addr); - } + if (dev->mmio) + iounmap(dev->mmio); comedi_pci_disable(dev); } diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index b3aeb6fb2ad0..bd2ca2b371e6 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -653,6 +653,7 @@ static int dt9812_find_endpoints(struct comedi_device *dev) for (i = 0; i < host->desc.bNumEndpoints; ++i) { int dir = -1; + ep = &host->endpoint[i].desc; switch (i) { case 0: diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index 22333c1ad88c..91c1e8cf5d24 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -51,7 +51,7 @@ #include "comedi_fc.h" /* - * PCI BAR2 Register map (devpriv->mmio) + * PCI BAR2 Register map (dev->mmio) */ #define FIRMWARE_REV_REG 0x00 #define FEATURES_REG_PRESENT_BIT (1 << 15) @@ -148,7 +148,6 @@ static const struct hpdi_board hpdi_boards[] = { struct hpdi_private { void __iomem *plx9080_mmio; - void __iomem *mmio; uint32_t *dio_buffer[NUM_DMA_BUFFERS]; /* dma buffers */ /* physical addresses of dma buffers */ dma_addr_t dio_buffer_phys_addr[NUM_DMA_BUFFERS]; @@ -227,11 +226,11 @@ static irqreturn_t gsc_hpdi_interrupt(int irq, void *d) if ((plx_status & (ICS_DMA0_A | ICS_DMA1_A | ICS_LIA)) == 0) return IRQ_NONE; - hpdi_intr_status = readl(devpriv->mmio + INTERRUPT_STATUS_REG); - hpdi_board_status = readl(devpriv->mmio + BOARD_STATUS_REG); + hpdi_intr_status = readl(dev->mmio + INTERRUPT_STATUS_REG); + hpdi_board_status = readl(dev->mmio + BOARD_STATUS_REG); if (hpdi_intr_status) - writel(hpdi_intr_status, devpriv->mmio + INTERRUPT_STATUS_REG); + writel(hpdi_intr_status, dev->mmio + INTERRUPT_STATUS_REG); /* spin lock makes sure no one else changes plx dma control reg */ spin_lock_irqsave(&dev->spinlock, flags); @@ -294,10 +293,8 @@ static void gsc_hpdi_abort_dma(struct comedi_device *dev, unsigned int channel) static int gsc_hpdi_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - struct hpdi_private *devpriv = dev->private; - - writel(0, devpriv->mmio + BOARD_CONTROL_REG); - writel(0, devpriv->mmio + INTERRUPT_CONTROL_REG); + writel(0, dev->mmio + BOARD_CONTROL_REG); + writel(0, dev->mmio + INTERRUPT_CONTROL_REG); gsc_hpdi_abort_dma(dev, 0); @@ -316,7 +313,7 @@ static int gsc_hpdi_cmd(struct comedi_device *dev, if (s->io_bits) return -EINVAL; - writel(RX_FIFO_RESET_BIT, devpriv->mmio + BOARD_CONTROL_REG); + writel(RX_FIFO_RESET_BIT, dev->mmio + BOARD_CONTROL_REG); gsc_hpdi_abort_dma(dev, 0); @@ -349,13 +346,12 @@ static int gsc_hpdi_cmd(struct comedi_device *dev, devpriv->dio_count = 1; /* clear over/under run status flags */ - writel(RX_UNDERRUN_BIT | RX_OVERRUN_BIT, - devpriv->mmio + BOARD_STATUS_REG); + writel(RX_UNDERRUN_BIT | RX_OVERRUN_BIT, dev->mmio + BOARD_STATUS_REG); /* enable interrupts */ - writel(RX_FULL_INTR, devpriv->mmio + INTERRUPT_CONTROL_REG); + writel(RX_FULL_INTR, dev->mmio + INTERRUPT_CONTROL_REG); - writel(RX_ENABLE_BIT, devpriv->mmio + BOARD_CONTROL_REG); + writel(RX_ENABLE_BIT, dev->mmio + BOARD_CONTROL_REG); return 0; } @@ -517,20 +513,20 @@ static int gsc_hpdi_init(struct comedi_device *dev) uint32_t plx_intcsr_bits; /* wait 10usec after reset before accessing fifos */ - writel(BOARD_RESET_BIT, devpriv->mmio + BOARD_CONTROL_REG); + writel(BOARD_RESET_BIT, dev->mmio + BOARD_CONTROL_REG); udelay(10); writel(ALMOST_EMPTY_BITS(32) | ALMOST_FULL_BITS(32), - devpriv->mmio + RX_PROG_ALMOST_REG); + dev->mmio + RX_PROG_ALMOST_REG); writel(ALMOST_EMPTY_BITS(32) | ALMOST_FULL_BITS(32), - devpriv->mmio + TX_PROG_ALMOST_REG); + dev->mmio + TX_PROG_ALMOST_REG); - devpriv->tx_fifo_size = readl(devpriv->mmio + TX_FIFO_SIZE_REG) & + devpriv->tx_fifo_size = readl(dev->mmio + TX_FIFO_SIZE_REG) & FIFO_SIZE_MASK; - devpriv->rx_fifo_size = readl(devpriv->mmio + RX_FIFO_SIZE_REG) & + devpriv->rx_fifo_size = readl(dev->mmio + RX_FIFO_SIZE_REG) & FIFO_SIZE_MASK; - writel(0, devpriv->mmio + INTERRUPT_CONTROL_REG); + writel(0, dev->mmio + INTERRUPT_CONTROL_REG); /* enable interrupts */ plx_intcsr_bits = @@ -621,8 +617,8 @@ static int gsc_hpdi_auto_attach(struct comedi_device *dev, pci_set_master(pcidev); devpriv->plx9080_mmio = pci_ioremap_bar(pcidev, 0); - devpriv->mmio = pci_ioremap_bar(pcidev, 2); - if (!devpriv->plx9080_mmio || !devpriv->mmio) { + dev->mmio = pci_ioremap_bar(pcidev, 2); + if (!devpriv->plx9080_mmio || !dev->mmio) { dev_warn(dev->class_dev, "failed to remap io memory\n"); return -ENOMEM; } @@ -696,8 +692,8 @@ static void gsc_hpdi_detach(struct comedi_device *dev) writel(0, devpriv->plx9080_mmio + PLX_INTRCS_REG); iounmap(devpriv->plx9080_mmio); } - if (devpriv->mmio) - iounmap(devpriv->mmio); + if (dev->mmio) + iounmap(dev->mmio); /* free pci dma buffers */ for (i = 0; i < NUM_DMA_BUFFERS; i++) { if (devpriv->dio_buffer[i]) diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index 0b8b2162b76b..a98cef2106a9 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -49,8 +49,6 @@ Configuration options: not applicable, uses PCI auto config #include "../comedidev.h" -#define PCI_DEVICE_ID_ICP_MULTI 0x8000 - #define ICP_MULTI_ADC_CSR 0 /* R/W: ADC command/status register */ #define ICP_MULTI_AI 2 /* R: Analogue input data */ #define ICP_MULTI_DAC_CSR 4 /* R/W: DAC command/status register */ @@ -110,7 +108,6 @@ static const char range_codes_analog[] = { 0x00, 0x20, 0x10, 0x30 }; struct icp_multi_private { char valid; /* card is usable */ - void __iomem *io_addr; /* Pointer to mapped io address */ unsigned int AdcCmdStatus; /* ADC Command/Status register */ unsigned int DacCmdStatus; /* DAC Command/Status register */ unsigned int IntEnable; /* Interrupt Enable register */ @@ -166,8 +163,7 @@ static void setup_channel_list(struct comedi_device *dev, devpriv->AdcCmdStatus |= range; /* Output channel, range, mode to ICP Multi */ - writew(devpriv->AdcCmdStatus, - devpriv->io_addr + ICP_MULTI_ADC_CSR); + writew(devpriv->AdcCmdStatus, dev->mmio + ICP_MULTI_ADC_CSR); } } @@ -176,10 +172,9 @@ static int icp_multi_ai_eoc(struct comedi_device *dev, struct comedi_insn *insn, unsigned long context) { - struct icp_multi_private *devpriv = dev->private; unsigned int status; - status = readw(devpriv->io_addr + ICP_MULTI_ADC_CSR); + status = readw(dev->mmio + ICP_MULTI_ADC_CSR); if ((status & ADC_BSY) == 0) return 0; return -EBUSY; @@ -187,7 +182,8 @@ static int icp_multi_ai_eoc(struct comedi_device *dev, static int icp_multi_insn_read_ai(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct icp_multi_private *devpriv = dev->private; int ret = 0; @@ -195,11 +191,11 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev, /* Disable A/D conversion ready interrupt */ devpriv->IntEnable &= ~ADC_READY; - writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN); + writew(devpriv->IntEnable, dev->mmio + ICP_MULTI_INT_EN); /* Clear interrupt status */ devpriv->IntStatus |= ADC_READY; - writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT); + 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); @@ -207,8 +203,7 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev, for (n = 0; n < insn->n; n++) { /* Set start ADC bit */ devpriv->AdcCmdStatus |= ADC_ST; - writew(devpriv->AdcCmdStatus, - devpriv->io_addr + ICP_MULTI_ADC_CSR); + writew(devpriv->AdcCmdStatus, dev->mmio + ICP_MULTI_ADC_CSR); devpriv->AdcCmdStatus &= ~ADC_ST; udelay(1); @@ -218,17 +213,16 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev, if (ret) break; - data[n] = - (readw(devpriv->io_addr + ICP_MULTI_AI) >> 4) & 0x0fff; + data[n] = (readw(dev->mmio + ICP_MULTI_AI) >> 4) & 0x0fff; } /* Disable interrupt */ devpriv->IntEnable &= ~ADC_READY; - writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN); + writew(devpriv->IntEnable, dev->mmio + ICP_MULTI_INT_EN); /* Clear interrupt status */ devpriv->IntStatus |= ADC_READY; - writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT); + writew(devpriv->IntStatus, dev->mmio + ICP_MULTI_INT_STAT); return ret ? ret : n; } @@ -238,10 +232,9 @@ static int icp_multi_ao_eoc(struct comedi_device *dev, struct comedi_insn *insn, unsigned long context) { - struct icp_multi_private *devpriv = dev->private; unsigned int status; - status = readw(devpriv->io_addr + ICP_MULTI_DAC_CSR); + status = readw(dev->mmio + ICP_MULTI_DAC_CSR); if ((status & DAC_BSY) == 0) return 0; return -EBUSY; @@ -249,7 +242,8 @@ static int icp_multi_ao_eoc(struct comedi_device *dev, static int icp_multi_insn_write_ao(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct icp_multi_private *devpriv = dev->private; int n, chan, range; @@ -257,11 +251,11 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev, /* Disable D/A conversion ready interrupt */ devpriv->IntEnable &= ~DAC_READY; - writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN); + writew(devpriv->IntEnable, dev->mmio + ICP_MULTI_INT_EN); /* Clear interrupt status */ devpriv->IntStatus |= DAC_READY; - writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT); + writew(devpriv->IntStatus, dev->mmio + ICP_MULTI_INT_STAT); /* Get channel number and range */ chan = CR_CHAN(insn->chanspec); @@ -276,7 +270,7 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev, devpriv->DacCmdStatus |= range_codes_analog[range]; devpriv->DacCmdStatus |= (chan << 8); - writew(devpriv->DacCmdStatus, devpriv->io_addr + ICP_MULTI_DAC_CSR); + writew(devpriv->DacCmdStatus, dev->mmio + ICP_MULTI_DAC_CSR); for (n = 0; n < insn->n; n++) { /* Wait for analogue output data register to be @@ -286,12 +280,12 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev, /* Disable interrupt */ devpriv->IntEnable &= ~DAC_READY; writew(devpriv->IntEnable, - devpriv->io_addr + ICP_MULTI_INT_EN); + dev->mmio + ICP_MULTI_INT_EN); /* Clear interrupt status */ devpriv->IntStatus |= DAC_READY; writew(devpriv->IntStatus, - devpriv->io_addr + ICP_MULTI_INT_STAT); + dev->mmio + ICP_MULTI_INT_STAT); /* Clear data received */ devpriv->ao_data[chan] = 0; @@ -300,12 +294,11 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev, } /* Write data to analogue output data register */ - writew(data[n], devpriv->io_addr + ICP_MULTI_AO); + writew(data[n], dev->mmio + ICP_MULTI_AO); /* Set DAC_ST bit to write the data to selected channel */ devpriv->DacCmdStatus |= DAC_ST; - writew(devpriv->DacCmdStatus, - devpriv->io_addr + ICP_MULTI_DAC_CSR); + writew(devpriv->DacCmdStatus, dev->mmio + ICP_MULTI_DAC_CSR); devpriv->DacCmdStatus &= ~DAC_ST; /* Save analogue output data */ @@ -334,11 +327,10 @@ static int icp_multi_insn_read_ao(struct comedi_device *dev, static int icp_multi_insn_bits_di(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - struct icp_multi_private *devpriv = dev->private; - - data[1] = readw(devpriv->io_addr + ICP_MULTI_DI); + data[1] = readw(dev->mmio + ICP_MULTI_DI); return insn->n; } @@ -348,12 +340,10 @@ static int icp_multi_insn_bits_do(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct icp_multi_private *devpriv = dev->private; - if (comedi_dio_update_state(s, data)) - writew(s->state, devpriv->io_addr + ICP_MULTI_DO); + writew(s->state, dev->mmio + ICP_MULTI_DO); - data[1] = readw(devpriv->io_addr + ICP_MULTI_DI); + data[1] = readw(dev->mmio + ICP_MULTI_DI); return insn->n; } @@ -376,11 +366,10 @@ static int icp_multi_insn_write_ctr(struct comedi_device *dev, static irqreturn_t interrupt_service_icp_multi(int irq, void *d) { struct comedi_device *dev = d; - struct icp_multi_private *devpriv = dev->private; int int_no; /* Is this interrupt from our board? */ - int_no = readw(devpriv->io_addr + ICP_MULTI_INT_STAT) & Status_IRQ; + int_no = readw(dev->mmio + ICP_MULTI_INT_STAT) & Status_IRQ; if (!int_no) /* No, exit */ return IRQ_NONE; @@ -420,7 +409,7 @@ static int check_channel_list(struct comedi_device *dev, /* Check that we at least have one channel to check */ if (n_chan < 1) { - comedi_error(dev, "range/channel list is empty!"); + dev_err(dev->class_dev, "range/channel list is empty!\n"); return 0; } /* Check all channels */ @@ -428,14 +417,14 @@ static int check_channel_list(struct comedi_device *dev, /* Check that channel number is < maximum */ if (CR_AREF(chanlist[i]) == AREF_DIFF) { if (CR_CHAN(chanlist[i]) > (s->nchan / 2)) { - comedi_error(dev, - "Incorrect differential ai ch-nr"); + dev_err(dev->class_dev, + "Incorrect differential ai ch-nr\n"); return 0; } } else { if (CR_CHAN(chanlist[i]) > s->n_chan) { - comedi_error(dev, - "Incorrect ai channel number"); + dev_err(dev->class_dev, + "Incorrect ai channel number\n"); return 0; } } @@ -450,8 +439,8 @@ static int icp_multi_reset(struct comedi_device *dev) unsigned int i; /* Clear INT enables and requests */ - writew(0, devpriv->io_addr + ICP_MULTI_INT_EN); - writew(0x00ff, devpriv->io_addr + ICP_MULTI_INT_STAT); + writew(0, dev->mmio + ICP_MULTI_INT_EN); + writew(0x00ff, dev->mmio + ICP_MULTI_INT_STAT); /* Set DACs to 0..5V range and 0V output */ for (i = 0; i < 4; i++) { @@ -461,21 +450,20 @@ static int icp_multi_reset(struct comedi_device *dev) devpriv->DacCmdStatus |= (i << 8); /* Output 0V */ - writew(0, devpriv->io_addr + ICP_MULTI_AO); + writew(0, dev->mmio + ICP_MULTI_AO); /* Set start conversion bit */ devpriv->DacCmdStatus |= DAC_ST; /* Output to command / status register */ - writew(devpriv->DacCmdStatus, - devpriv->io_addr + ICP_MULTI_DAC_CSR); + writew(devpriv->DacCmdStatus, dev->mmio + ICP_MULTI_DAC_CSR); /* Delay to allow DAC time to recover */ udelay(1); } /* Digital outputs to 0 */ - writew(0, devpriv->io_addr + ICP_MULTI_DO); + writew(0, dev->mmio + ICP_MULTI_DO); return 0; } @@ -496,8 +484,8 @@ static int icp_multi_auto_attach(struct comedi_device *dev, if (ret) return ret; - devpriv->io_addr = pci_ioremap_bar(pcidev, 2); - if (!devpriv->io_addr) + dev->mmio = pci_ioremap_bar(pcidev, 2); + if (!dev->mmio) return -ENOMEM; ret = comedi_alloc_subdevices(dev, 5); @@ -575,8 +563,8 @@ static void icp_multi_detach(struct comedi_device *dev) icp_multi_reset(dev); if (dev->irq) free_irq(dev->irq, dev); - if (devpriv && devpriv->io_addr) - iounmap(devpriv->io_addr); + if (dev->mmio) + iounmap(dev->mmio); comedi_pci_disable(dev); } @@ -594,7 +582,7 @@ static int icp_multi_pci_probe(struct pci_dev *dev, } static const struct pci_device_id icp_multi_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ICP, PCI_DEVICE_ID_ICP_MULTI) }, + { PCI_DEVICE(PCI_VENDOR_ID_ICP, 0x8000) }, { 0 } }; MODULE_DEVICE_TABLE(pci, icp_multi_pci_table); diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 2516ce834839..687db433e131 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -33,6 +33,7 @@ /* * Register I/O map */ +#define II20K_SIZE 0x400 #define II20K_MOD_OFFSET 0x100 #define II20K_ID_REG 0x00 #define II20K_ID_MOD1_EMPTY (1 << 7) @@ -135,16 +136,10 @@ struct ii20k_ao_private { unsigned int last_data[2]; }; -struct ii20k_private { - void __iomem *ioaddr; -}; - static void __iomem *ii20k_module_iobase(struct comedi_device *dev, struct comedi_subdevice *s) { - struct ii20k_private *devpriv = dev->private; - - return devpriv->ioaddr + (s->index + 1) * II20K_MOD_OFFSET; + return dev->mmio + (s->index + 1) * II20K_MOD_OFFSET; } static int ii20k_ao_insn_read(struct comedi_device *dev, @@ -281,7 +276,6 @@ static int ii20k_ai_insn_read(struct comedi_device *dev, static void ii20k_dio_config(struct comedi_device *dev, struct comedi_subdevice *s) { - struct ii20k_private *devpriv = dev->private; unsigned char ctrl01 = 0; unsigned char ctrl23 = 0; unsigned char dir_ena = 0; @@ -338,9 +332,9 @@ static void ii20k_dio_config(struct comedi_device *dev, ctrl23 |= II20K_CTRL23_SET; /* order is important */ - writeb(ctrl01, devpriv->ioaddr + II20K_CTRL01_REG); - writeb(ctrl23, devpriv->ioaddr + II20K_CTRL23_REG); - writeb(dir_ena, devpriv->ioaddr + II20K_DIR_ENA_REG); + writeb(ctrl01, dev->mmio + II20K_CTRL01_REG); + writeb(ctrl23, dev->mmio + II20K_CTRL23_REG); + writeb(dir_ena, dev->mmio + II20K_DIR_ENA_REG); } static int ii20k_dio_insn_config(struct comedi_device *dev, @@ -375,29 +369,28 @@ static int ii20k_dio_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct ii20k_private *devpriv = dev->private; unsigned int mask; mask = comedi_dio_update_state(s, data); if (mask) { if (mask & 0x000000ff) writeb((s->state >> 0) & 0xff, - devpriv->ioaddr + II20K_DIO0_REG); + dev->mmio + II20K_DIO0_REG); if (mask & 0x0000ff00) writeb((s->state >> 8) & 0xff, - devpriv->ioaddr + II20K_DIO1_REG); + dev->mmio + II20K_DIO1_REG); if (mask & 0x00ff0000) writeb((s->state >> 16) & 0xff, - devpriv->ioaddr + II20K_DIO2_REG); + dev->mmio + II20K_DIO2_REG); if (mask & 0xff000000) writeb((s->state >> 24) & 0xff, - devpriv->ioaddr + II20K_DIO3_REG); + dev->mmio + II20K_DIO3_REG); } - data[1] = readb(devpriv->ioaddr + II20K_DIO0_REG); - data[1] |= readb(devpriv->ioaddr + II20K_DIO1_REG) << 8; - data[1] |= readb(devpriv->ioaddr + II20K_DIO2_REG) << 16; - data[1] |= readb(devpriv->ioaddr + II20K_DIO3_REG) << 24; + data[1] = readb(dev->mmio + II20K_DIO0_REG); + data[1] |= readb(dev->mmio + II20K_DIO1_REG) << 8; + data[1] |= readb(dev->mmio + II20K_DIO2_REG) << 16; + data[1] |= readb(dev->mmio + II20K_DIO3_REG) << 24; return insn->n; } @@ -446,19 +439,32 @@ static int ii20k_init_module(struct comedi_device *dev, static int ii20k_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - struct ii20k_private *devpriv; struct comedi_subdevice *s; + unsigned int membase; unsigned char id; bool has_dio; int ret; - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) - return -ENOMEM; + membase = it->options[0]; + if (!membase || (membase & ~(0x100000 - II20K_SIZE))) { + dev_warn(dev->class_dev, + "%s: invalid memory address specified\n", + dev->board_name); + return -EINVAL; + } - devpriv->ioaddr = (void __iomem *)(unsigned long)it->options[0]; + if (!request_mem_region(membase, II20K_SIZE, dev->board_name)) { + dev_warn(dev->class_dev, "%s: I/O mem conflict (%#x,%u)\n", + dev->board_name, membase, II20K_SIZE); + return -EIO; + } + dev->iobase = membase; /* actually, a memory address */ - id = readb(devpriv->ioaddr + II20K_ID_REG); + dev->mmio = ioremap(membase, II20K_SIZE); + if (!dev->mmio) + return -ENOMEM; + + id = readb(dev->mmio + II20K_ID_REG); switch (id & II20K_ID_MASK) { case II20K_ID_PCI20001C_1A: has_dio = false; @@ -521,11 +527,19 @@ static int ii20k_attach(struct comedi_device *dev, return 0; } +static void ii20k_detach(struct comedi_device *dev) +{ + if (dev->mmio) + iounmap(dev->mmio); + if (dev->iobase) /* actually, a memory address */ + release_mem_region(dev->iobase, II20K_SIZE); +} + static struct comedi_driver ii20k_driver = { .driver_name = "ii_pci20kc", .module = THIS_MODULE, .attach = ii20k_attach, - .detach = comedi_legacy_detach, + .detach = ii20k_detach, }; module_comedi_driver(ii20k_driver); diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index a8db9d86aadc..7b20e19ecbf7 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -196,6 +196,7 @@ static struct six_axis_t get_min_full_scales(struct jr3_channel __iomem *channel) { struct six_axis_t result; + result.fx = get_s16(&channel->min_full_scale.fx); result.fy = get_s16(&channel->min_full_scale.fy); result.fz = get_s16(&channel->min_full_scale.fz); @@ -209,6 +210,7 @@ static struct six_axis_t get_max_full_scales(struct jr3_channel __iomem *channel) { struct six_axis_t result; + result.fx = get_s16(&channel->max_full_scale.fx); result.fy = get_s16(&channel->max_full_scale.fy); result.fz = get_s16(&channel->max_full_scale.fz); @@ -319,6 +321,8 @@ static int read_idm_word(const u8 *data, size_t size, int *pos, unsigned int *val) { int result = 0; + int value; + if (pos && val) { /* Skip over non hex */ for (; *pos < size && !isxdigit(data[*pos]); (*pos)++) @@ -326,7 +330,6 @@ static int read_idm_word(const u8 *data, size_t size, int *pos, /* Collect value */ *val = 0; for (; *pos < size; (*pos)++) { - int value; value = hex_to_bin(data[*pos]); if (value >= 0) { result = 1; diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c index ec43c38958de..f46722c2648f 100644 --- a/drivers/staging/comedi/drivers/ke_counter.c +++ b/drivers/staging/comedi/drivers/ke_counter.c @@ -93,6 +93,67 @@ static int ke_counter_insn_read(struct comedi_device *dev, return insn->n; } +static void ke_counter_reset(struct comedi_device *dev) +{ + unsigned int chan; + + for (chan = 0; chan < 3; chan++) + outb(0, dev->iobase + KE_RESET_REG(chan)); +} + +static int ke_counter_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned char src; + + switch (data[0]) { + case INSN_CONFIG_SET_CLOCK_SRC: + switch (data[1]) { + case KE_CLK_20MHZ: /* default */ + src = KE_OSC_SEL_20MHZ; + break; + case KE_CLK_4MHZ: /* option */ + src = KE_OSC_SEL_4MHZ; + break; + case KE_CLK_EXT: /* Pin 21 on D-sub */ + src = KE_OSC_SEL_EXT; + break; + default: + return -EINVAL; + } + outb(src, dev->iobase + KE_OSC_SEL_REG); + break; + case INSN_CONFIG_GET_CLOCK_SRC: + src = inb(dev->iobase + KE_OSC_SEL_REG); + switch (src) { + case KE_OSC_SEL_20MHZ: + data[1] = KE_CLK_20MHZ; + data[2] = 50; /* 50ns */ + break; + case KE_OSC_SEL_4MHZ: + data[1] = KE_CLK_4MHZ; + data[2] = 250; /* 250ns */ + break; + case KE_OSC_SEL_EXT: + data[1] = KE_CLK_EXT; + data[2] = 0; /* Unknown */ + break; + default: + return -EINVAL; + } + break; + case INSN_CONFIG_RESET: + ke_counter_reset(dev); + break; + default: + return -EINVAL; + } + + return insn->n; +} + static int ke_counter_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -130,6 +191,7 @@ static int ke_counter_auto_attach(struct comedi_device *dev, s->range_table = &range_unknown; s->insn_read = ke_counter_insn_read; s->insn_write = ke_counter_insn_write; + s->insn_config = ke_counter_insn_config; s = &dev->subdevices[1]; s->type = COMEDI_SUBD_DO; @@ -141,9 +203,7 @@ static int ke_counter_auto_attach(struct comedi_device *dev, outb(KE_OSC_SEL_20MHZ, dev->iobase + KE_OSC_SEL_REG); - outb(0, dev->iobase + KE_RESET_REG(0)); - outb(0, dev->iobase + KE_RESET_REG(1)); - outb(0, dev->iobase + KE_RESET_REG(2)); + ke_counter_reset(dev); return 0; } diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 25ce2f78db81..9a5c535451a1 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -170,7 +170,6 @@ broken. #define ME4000_AI_MIN_TICKS 66 #define ME4000_AI_MIN_SAMPLE_TIME 2000 -#define ME4000_AI_BASE_FREQUENCY (unsigned int) 33E6 #define ME4000_AI_CHANNEL_LIST_COUNT 1024 diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index 0ff126b1fdfd..37a6fa92c656 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -167,7 +167,6 @@ static const struct me_board me_boards[] = { struct me_private_data { void __iomem *plx_regbase; /* PLX configuration base address */ - void __iomem *me_regbase; /* Base address of the Meilhaus card */ unsigned short control_1; /* Mirror of CONTROL_1 register */ unsigned short control_2; /* Mirror of CONTROL_2 register */ @@ -209,7 +208,7 @@ static int me_dio_insn_config(struct comedi_device *dev, else devpriv->control_2 &= ~ENABLE_PORT_B; - writew(devpriv->control_2, devpriv->me_regbase + ME_CONTROL_2); + writew(devpriv->control_2, dev->mmio + ME_CONTROL_2); return insn->n; } @@ -219,9 +218,8 @@ static int me_dio_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct me_private_data *dev_private = dev->private; - void __iomem *mmio_porta = dev_private->me_regbase + ME_DIO_PORT_A; - void __iomem *mmio_portb = dev_private->me_regbase + ME_DIO_PORT_B; + void __iomem *mmio_porta = dev->mmio + ME_DIO_PORT_A; + void __iomem *mmio_portb = dev->mmio + ME_DIO_PORT_B; unsigned int mask; unsigned int val; @@ -253,10 +251,9 @@ static int me_ai_eoc(struct comedi_device *dev, struct comedi_insn *insn, unsigned long context) { - struct me_private_data *dev_private = dev->private; unsigned int status; - status = readw(dev_private->me_regbase + ME_STATUS); + status = readw(dev->mmio + ME_STATUS); if ((status & 0x0004) == 0) return 0; return -EBUSY; @@ -276,32 +273,32 @@ static int me_ai_insn_read(struct comedi_device *dev, /* stop any running conversion */ dev_private->control_1 &= 0xFFFC; - writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1); + writew(dev_private->control_1, dev->mmio + ME_CONTROL_1); /* clear chanlist and ad fifo */ dev_private->control_2 &= ~(ENABLE_ADFIFO | ENABLE_CHANLIST); - writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2); + writew(dev_private->control_2, dev->mmio + ME_CONTROL_2); /* reset any pending interrupt */ - writew(0x00, dev_private->me_regbase + ME_RESET_INTERRUPT); + writew(0x00, dev->mmio + ME_RESET_INTERRUPT); /* enable the chanlist and ADC fifo */ dev_private->control_2 |= (ENABLE_ADFIFO | ENABLE_CHANLIST); - writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2); + writew(dev_private->control_2, dev->mmio + ME_CONTROL_2); /* 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_private->me_regbase + ME_CHANNEL_LIST); + writew(val & 0xff, dev->mmio + ME_CHANNEL_LIST); /* set ADC mode to software trigger */ dev_private->control_1 |= SOFTWARE_TRIGGERED_ADC; - writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1); + writew(dev_private->control_1, dev->mmio + ME_CONTROL_1); /* start conversion by reading from ADC_START */ - readw(dev_private->me_regbase + ME_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); @@ -309,13 +306,13 @@ static int me_ai_insn_read(struct comedi_device *dev, return ret; /* get value from ADC fifo */ - val = readw(dev_private->me_regbase + ME_READ_AD_FIFO); + val = readw(dev->mmio + ME_READ_AD_FIFO); val = (val ^ 0x800) & 0x0fff; data[0] = val; /* stop any running conversion */ dev_private->control_1 &= 0xFFFC; - writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1); + writew(dev_private->control_1, dev->mmio + ME_CONTROL_1); return 1; } @@ -332,11 +329,11 @@ static int me_ao_insn_write(struct comedi_device *dev, /* Enable all DAC */ dev_private->control_2 |= ENABLE_DAC; - writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2); + writew(dev_private->control_2, dev->mmio + ME_CONTROL_2); /* and set DAC to "buffered" mode */ dev_private->control_2 |= BUFFERED_DAC; - writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2); + writew(dev_private->control_2, dev->mmio + ME_CONTROL_2); /* Set dac-control register */ for (i = 0; i < insn->n; i++) { @@ -349,21 +346,20 @@ static int me_ao_insn_write(struct comedi_device *dev, dev_private->dac_control |= ((DAC_BIPOLAR_A | DAC_GAIN_0_A) >> chan); } - writew(dev_private->dac_control, - dev_private->me_regbase + ME_DAC_CONTROL); + writew(dev_private->dac_control, dev->mmio + ME_DAC_CONTROL); /* Update dac-control register */ - readw(dev_private->me_regbase + ME_DAC_CONTROL_UPDATE); + readw(dev->mmio + ME_DAC_CONTROL_UPDATE); /* Set data register */ for (i = 0; i < insn->n; i++) { writew((data[0] & s->maxdata), - dev_private->me_regbase + ME_DAC_DATA_A + (chan << 1)); + dev->mmio + ME_DAC_DATA_A + (chan << 1)); dev_private->ao_readback[chan] = (data[0] & s->maxdata); } /* Update dac with data registers */ - readw(dev_private->me_regbase + ME_DAC_UPDATE); + readw(dev->mmio + ME_DAC_UPDATE); return insn->n; } @@ -396,13 +392,13 @@ static int me2600_xilinx_download(struct comedi_device *dev, writel(0x00, dev_private->plx_regbase + PLX9052_INTCSR); /* First, make a dummy read to reset xilinx */ - value = readw(dev_private->me_regbase + XILINX_DOWNLOAD_RESET); + value = readw(dev->mmio + XILINX_DOWNLOAD_RESET); /* Wait until reset is over */ sleep(1); /* Write a dummy value to Xilinx */ - writeb(0x00, dev_private->me_regbase + 0x0); + writeb(0x00, dev->mmio + 0x0); sleep(1); /* @@ -426,12 +422,11 @@ static int me2600_xilinx_download(struct comedi_device *dev, * Firmware data start at offset 16 */ for (i = 0; i < file_length; i++) - writeb((data[16 + i] & 0xff), - dev_private->me_regbase + 0x0); + writeb((data[16 + i] & 0xff), dev->mmio + 0x0); /* Write 5 dummy values to xilinx */ for (i = 0; i < 5; i++) - writeb(0x00, dev_private->me_regbase + 0x0); + writeb(0x00, dev->mmio + 0x0); /* Test if there was an error during download -> INTB was thrown */ value = readl(dev_private->plx_regbase + PLX9052_INTCSR); @@ -459,10 +454,10 @@ static int me_reset(struct comedi_device *dev) struct me_private_data *dev_private = dev->private; /* Reset board */ - writew(0x00, dev_private->me_regbase + ME_CONTROL_1); - writew(0x00, dev_private->me_regbase + ME_CONTROL_2); - writew(0x00, dev_private->me_regbase + ME_RESET_INTERRUPT); - writew(0x00, dev_private->me_regbase + ME_DAC_CONTROL); + 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); /* Save values in the board context */ dev_private->dac_control = 0; @@ -500,8 +495,8 @@ static int me_auto_attach(struct comedi_device *dev, if (!dev_private->plx_regbase) return -ENOMEM; - dev_private->me_regbase = pci_ioremap_bar(pcidev, 2); - if (!dev_private->me_regbase) + dev->mmio = pci_ioremap_bar(pcidev, 2); + if (!dev->mmio) return -ENOMEM; /* Download firmware and reset card */ @@ -559,9 +554,9 @@ static void me_detach(struct comedi_device *dev) struct me_private_data *dev_private = dev->private; if (dev_private) { - if (dev_private->me_regbase) { + if (dev->mmio) { me_reset(dev); - iounmap(dev_private->me_regbase); + iounmap(dev->mmio); } if (dev_private->plx_regbase) iounmap(dev_private->plx_regbase); diff --git a/drivers/staging/comedi/drivers/mf6x4.c b/drivers/staging/comedi/drivers/mf6x4.c index a4f7d6f138df..464f4b4745c7 100644 --- a/drivers/staging/comedi/drivers/mf6x4.c +++ b/drivers/staging/comedi/drivers/mf6x4.c @@ -93,7 +93,6 @@ struct mf6x4_private { * and MF634 yet we will call them 0, 1, 2 */ void __iomem *bar0_mem; - void __iomem *bar1_mem; void __iomem *bar2_mem; /* @@ -108,25 +107,22 @@ struct mf6x4_private { }; static int mf6x4_di_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - struct mf6x4_private *devpriv = dev->private; - - data[1] = ioread16(devpriv->bar1_mem + MF6X4_DIN_R) & MF6X4_DIN_M; + data[1] = ioread16(dev->mmio + MF6X4_DIN_R) & MF6X4_DIN_M; return insn->n; } static int mf6x4_do_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - struct mf6x4_private *devpriv = dev->private; - if (comedi_dio_update_state(s, data)) - iowrite16(s->state & MF6X4_DOUT_M, - devpriv->bar1_mem + MF6X4_DOUT_R); + iowrite16(s->state & MF6X4_DOUT_M, dev->mmio + MF6X4_DOUT_R); data[1] = s->state; @@ -149,40 +145,40 @@ static int mf6x4_ai_eoc(struct comedi_device *dev, static int mf6x4_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 mf6x4_private *devpriv = dev->private; int chan = CR_CHAN(insn->chanspec); int ret; int i; int d; /* Set the ADC channel number in the scan list */ - iowrite16((1 << chan) & MF6X4_ADCTRL_M, - devpriv->bar1_mem + MF6X4_ADCTRL_R); + iowrite16((1 << chan) & MF6X4_ADCTRL_M, dev->mmio + MF6X4_ADCTRL_R); for (i = 0; i < insn->n; i++) { /* Trigger ADC conversion by reading ADSTART */ - ioread16(devpriv->bar1_mem + MF6X4_ADSTART_R); + ioread16(dev->mmio + MF6X4_ADSTART_R); ret = comedi_timeout(dev, s, insn, mf6x4_ai_eoc, 0); if (ret) return ret; /* Read the actual value */ - d = ioread16(devpriv->bar1_mem + MF6X4_ADDATA_R); + d = ioread16(dev->mmio + MF6X4_ADDATA_R); d &= s->maxdata; data[i] = d; } - iowrite16(0x0, devpriv->bar1_mem + MF6X4_ADCTRL_R); + iowrite16(0x0, dev->mmio + MF6X4_ADCTRL_R); return insn->n; } static int mf6x4_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct mf6x4_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); @@ -195,8 +191,7 @@ static int mf6x4_ao_insn_write(struct comedi_device *dev, devpriv->gpioc_R); for (i = 0; i < insn->n; i++) { - iowrite16(data[i] & MF6X4_DA_M, - devpriv->bar1_mem + MF6X4_DAC_R(chan)); + iowrite16(data[i] & MF6X4_DA_M, dev->mmio + MF6X4_DAC_R(chan)); devpriv->ao_readback[chan] = data[i]; } @@ -246,8 +241,8 @@ static int mf6x4_auto_attach(struct comedi_device *dev, unsigned long context) if (!devpriv->bar0_mem) return -ENODEV; - devpriv->bar1_mem = pci_ioremap_bar(pcidev, board->bar_nums[1]); - if (!devpriv->bar1_mem) + dev->mmio = pci_ioremap_bar(pcidev, board->bar_nums[1]); + if (!dev->mmio) return -ENODEV; devpriv->bar2_mem = pci_ioremap_bar(pcidev, board->bar_nums[2]); @@ -310,8 +305,8 @@ static void mf6x4_detach(struct comedi_device *dev) if (devpriv->bar0_mem) iounmap(devpriv->bar0_mem); - if (devpriv->bar1_mem) - iounmap(devpriv->bar1_mem); + if (dev->mmio) + iounmap(dev->mmio); if (devpriv->bar2_mem) iounmap(devpriv->bar2_mem); diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index 19c029acbc99..4f7829010a99 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -90,10 +90,12 @@ static unsigned mite_fifo_size(struct mite_struct *mite, unsigned channel) unsigned fcr_bits = readl(mite->mite_io_addr + MITE_FCR(channel)); unsigned empty_count = (fcr_bits >> 16) & 0xff; unsigned full_count = fcr_bits & 0xff; + return empty_count + full_count; } -int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1) +int mite_setup2(struct comedi_device *dev, + struct mite_struct *mite, bool use_win1) { unsigned long length; int i; @@ -104,24 +106,24 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1) mite->mite_io_addr = pci_ioremap_bar(mite->pcidev, 0); if (!mite->mite_io_addr) { - dev_err(&mite->pcidev->dev, + dev_err(dev->class_dev, "Failed to remap mite io memory address\n"); return -ENOMEM; } mite->mite_phys_addr = pci_resource_start(mite->pcidev, 0); - mite->daq_io_addr = pci_ioremap_bar(mite->pcidev, 1); - if (!mite->daq_io_addr) { - dev_err(&mite->pcidev->dev, + dev->mmio = pci_ioremap_bar(mite->pcidev, 1); + if (!dev->mmio) { + dev_err(dev->class_dev, "Failed to remap daq io memory address\n"); return -ENOMEM; } mite->daq_phys_addr = pci_resource_start(mite->pcidev, 1); length = pci_resource_len(mite->pcidev, 1); - if (use_iodwbsr_1) { + if (use_win1) { writel(0, mite->mite_io_addr + MITE_IODWBSR); - dev_info(&mite->pcidev->dev, + dev_info(dev->class_dev, "using I/O Window Base Size register 1\n"); writel(mite->daq_phys_addr | WENAB | MITE_IODWBSR_1_WSIZE_bits(length), @@ -147,7 +149,7 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1) csigr_bits = readl(mite->mite_io_addr + MITE_CSIGR); mite->num_channels = mite_csigr_dmac(csigr_bits); if (mite->num_channels > MAX_MITE_DMA_CHANNELS) { - dev_warn(&mite->pcidev->dev, + dev_warn(dev->class_dev, "mite: bug? chip claims to have %i dma channels. Setting to %i.\n", mite->num_channels, MAX_MITE_DMA_CHANNELS); mite->num_channels = MAX_MITE_DMA_CHANNELS; @@ -162,36 +164,22 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1) mite->mite_io_addr + MITE_CHCR(i)); } mite->fifo_size = mite_fifo_size(mite, 0); - dev_info(&mite->pcidev->dev, "fifo size is %i.\n", mite->fifo_size); + dev_info(dev->class_dev, "fifo size is %i.\n", mite->fifo_size); return 0; } EXPORT_SYMBOL_GPL(mite_setup2); -int mite_setup(struct mite_struct *mite) +void mite_detach(struct mite_struct *mite) { - return mite_setup2(mite, 0); -} -EXPORT_SYMBOL_GPL(mite_setup); - -void mite_unsetup(struct mite_struct *mite) -{ - /* unsigned long offset, start, length; */ - if (!mite) return; - if (mite->mite_io_addr) { + if (mite->mite_io_addr) iounmap(mite->mite_io_addr); - mite->mite_io_addr = NULL; - } - if (mite->daq_io_addr) { - iounmap(mite->daq_io_addr); - mite->daq_io_addr = NULL; - } - if (mite->mite_phys_addr) - mite->mite_phys_addr = 0; + + kfree(mite); } -EXPORT_SYMBOL_GPL(mite_unsetup); +EXPORT_SYMBOL_GPL(mite_detach); struct mite_dma_descriptor_ring *mite_alloc_ring(struct mite_struct *mite) { @@ -450,12 +438,14 @@ EXPORT_SYMBOL_GPL(mite_prep_dma); static u32 mite_device_bytes_transferred(struct mite_channel *mite_chan) { struct mite_struct *mite = mite_chan->mite; + return readl(mite->mite_io_addr + MITE_DAR(mite_chan->channel)); } u32 mite_bytes_in_transit(struct mite_channel *mite_chan) { struct mite_struct *mite = mite_chan->mite; + return readl(mite->mite_io_addr + MITE_FCR(mite_chan->channel)) & 0x000000FF; } diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h index e6e58e989b73..b2b12045b3a5 100644 --- a/drivers/staging/comedi/drivers/mite.h +++ b/drivers/staging/comedi/drivers/mite.h @@ -55,7 +55,6 @@ struct mite_struct { resource_size_t mite_phys_addr; void __iomem *mite_io_addr; resource_size_t daq_phys_addr; - void __iomem *daq_io_addr; struct mite_channel channels[MAX_MITE_DMA_CHANNELS]; short channel_allocated[MAX_MITE_DMA_CHANNELS]; int num_channels; @@ -65,24 +64,15 @@ struct mite_struct { struct mite_struct *mite_alloc(struct pci_dev *pcidev); -static inline void mite_free(struct mite_struct *mite) -{ - kfree(mite); -} - -static inline unsigned int mite_irq(struct mite_struct *mite) -{ - return mite->pcidev->irq; -}; +int mite_setup2(struct comedi_device *, struct mite_struct *, bool use_win1); -static inline unsigned int mite_device_id(struct mite_struct *mite) +static inline int mite_setup(struct comedi_device *dev, + struct mite_struct *mite) { - return mite->pcidev->device; -}; + return mite_setup2(dev, mite, false); +} -int mite_setup(struct mite_struct *mite); -int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1); -void mite_unsetup(struct mite_struct *mite); +void mite_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, @@ -122,11 +112,6 @@ void mite_prep_dma(struct mite_channel *mite_chan, int mite_buf_change(struct mite_dma_descriptor_ring *ring, struct comedi_subdevice *s); -static inline int CHAN_OFFSET(int channel) -{ - return 0x500 + 0x100 * channel; -}; - 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. @@ -138,90 +123,25 @@ enum mite_registers { MITE_PCI_CONFIG_OFFSET = 0x300, MITE_CSIGR = 0x460 /* chip signature */ }; -static inline int MITE_CHOR(int channel) -{ /* channel operation */ - return CHAN_OFFSET(channel) + 0x0; -}; -static inline int MITE_CHCR(int channel) -{ /* channel control */ - return CHAN_OFFSET(channel) + 0x4; -}; - -static inline int MITE_TCR(int channel) -{ /* transfer count */ - return CHAN_OFFSET(channel) + 0x8; -}; - -static inline int MITE_MCR(int channel) -{ /* memory configuration */ - return CHAN_OFFSET(channel) + 0xc; -}; - -static inline int MITE_MAR(int channel) -{ /* memory address */ - return CHAN_OFFSET(channel) + 0x10; -}; - -static inline int MITE_DCR(int channel) -{ /* device configuration */ - return CHAN_OFFSET(channel) + 0x14; -}; - -static inline int MITE_DAR(int channel) -{ /* device address */ - return CHAN_OFFSET(channel) + 0x18; -}; - -static inline int MITE_LKCR(int channel) -{ /* link configuration */ - return CHAN_OFFSET(channel) + 0x1c; -}; - -static inline int MITE_LKAR(int channel) -{ /* link address */ - return CHAN_OFFSET(channel) + 0x20; -}; - -static inline int MITE_LLKAR(int channel) -{ /* see mite section of tnt5002 manual */ - return CHAN_OFFSET(channel) + 0x24; -}; - -static inline int MITE_BAR(int channel) -{ /* base address */ - return CHAN_OFFSET(channel) + 0x28; -}; - -static inline int MITE_BCR(int channel) -{ /* base count */ - return CHAN_OFFSET(channel) + 0x2c; -}; - -static inline int MITE_SAR(int channel) -{ /* ? address */ - return CHAN_OFFSET(channel) + 0x30; -}; - -static inline int MITE_WSCR(int channel) -{ /* ? */ - return CHAN_OFFSET(channel) + 0x34; -}; - -static inline int MITE_WSER(int channel) -{ /* ? */ - return CHAN_OFFSET(channel) + 0x38; -}; - -static inline int MITE_CHSR(int channel) -{ /* channel status */ - return CHAN_OFFSET(channel) + 0x3c; -}; - -static inline int MITE_FCR(int channel) -{ /* fifo count */ - return CHAN_OFFSET(channel) + 0x40; -}; +#define MITE_CHAN(x) (0x500 + 0x100 * (x)) +#define MITE_CHOR(x) (0x00 + MITE_CHAN(x)) /* channel operation */ +#define MITE_CHCR(x) (0x04 + MITE_CHAN(x)) /* channel control */ +#define MITE_TCR(x) (0x08 + MITE_CHAN(x)) /* transfer count */ +#define MITE_MCR(x) (0x0c + MITE_CHAN(x)) /* memory configuration */ +#define MITE_MAR(x) (0x10 + MITE_CHAN(x)) /* memory address */ +#define MITE_DCR(x) (0x14 + MITE_CHAN(x)) /* device configuration */ +#define MITE_DAR(x) (0x18 + MITE_CHAN(x)) /* device address */ +#define MITE_LKCR(x) (0x1c + MITE_CHAN(x)) /* link configuration */ +#define MITE_LKAR(x) (0x20 + MITE_CHAN(x)) /* link address */ +#define MITE_LLKAR(x) (0x24 + MITE_CHAN(x)) /* see tnt5002 manual */ +#define MITE_BAR(x) (0x28 + MITE_CHAN(x)) /* base address */ +#define MITE_BCR(x) (0x2c + MITE_CHAN(x)) /* base count */ +#define MITE_SAR(x) (0x30 + MITE_CHAN(x)) /* ? address */ +#define MITE_WSCR(x) (0x34 + MITE_CHAN(x)) /* ? */ +#define MITE_WSER(x) (0x38 + MITE_CHAN(x)) /* ? */ +#define MITE_CHSR(x) (0x3c + MITE_CHAN(x)) /* channel status */ +#define MITE_FCR(x) (0x40 + MITE_CHAN(x)) /* fifo count */ enum MITE_IODWBSR_bits { WENAB = 0x80, /* window enable */ @@ -269,11 +189,9 @@ static inline int mite_csigr_dmac(u32 csigr_bits) static inline int mite_csigr_wpdep(u32 csigr_bits) { /* write post fifo depth */ unsigned int wpdep_bits = (csigr_bits >> 20) & 0x7; - if (wpdep_bits == 0) - return 0; - else - return 1 << (wpdep_bits - 1); -}; + + return (wpdep_bits) ? (1 << (wpdep_bits - 1)) : 0; +} static inline int mite_csigr_wins(u32 csigr_bits) { diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c index f770400a0e81..1241f9987cab 100644 --- a/drivers/staging/comedi/drivers/mpc624.c +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -56,9 +56,6 @@ Configuration Options: #include <linux/delay.h> -/* Consecutive I/O port addresses */ -#define MPC624_SIZE 16 - /* Offsets of different ports */ #define MPC624_MASTER_CONTROL 0 /* not used */ #define MPC624_GNMUXCH 1 /* Gain, Mux, Channel of ADC */ @@ -279,7 +276,7 @@ static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; int ret; - ret = comedi_request_region(dev, it->options[0], MPC624_SIZE); + ret = comedi_request_region(dev, it->options[0], 0x10); if (ret) return ret; diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c index b74b9e9bfd4a..e841a5a3ec4f 100644 --- a/drivers/staging/comedi/drivers/multiq3.c +++ b/drivers/staging/comedi/drivers/multiq3.c @@ -28,8 +28,6 @@ Devices: [Quanser Consulting] MultiQ-3 (multiq3) #include <linux/interrupt.h> #include "../comedidev.h" -#define MULTIQ3_SIZE 16 - /* * MULTIQ-3 port offsets */ @@ -189,12 +187,12 @@ static int multiq3_encoder_insn_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - int n; 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++) { - int value; outw(control, dev->iobase + MULTIQ3_CONTROL); outb(MULTIQ3_BP_RESET, dev->iobase + MULTIQ3_ENC_CONTROL); outb(MULTIQ3_TRSFRCNTR_OL, dev->iobase + MULTIQ3_ENC_CONTROL); @@ -233,7 +231,7 @@ static int multiq3_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - ret = comedi_request_region(dev, it->options[0], MULTIQ3_SIZE); + ret = comedi_request_region(dev, it->options[0], 0x10); if (ret) return ret; diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index c8b1fa793a37..e84dac2bf3b2 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -90,7 +90,6 @@ static const struct ni6527_board ni6527_boards[] = { }; struct ni6527_private { - void __iomem *mmio_base; unsigned int filter_interval; unsigned int filter_enable; }; @@ -99,14 +98,15 @@ static void ni6527_set_filter_interval(struct comedi_device *dev, unsigned int val) { struct ni6527_private *devpriv = dev->private; - void __iomem *mmio = devpriv->mmio_base; if (val != devpriv->filter_interval) { - writeb(val & 0xff, mmio + NI6527_FILT_INTERVAL_REG(0)); - writeb((val >> 8) & 0xff, mmio + NI6527_FILT_INTERVAL_REG(1)); - writeb((val >> 16) & 0x0f, mmio + NI6527_FILT_INTERVAL_REG(2)); + writeb(val & 0xff, dev->mmio + NI6527_FILT_INTERVAL_REG(0)); + writeb((val >> 8) & 0xff, + dev->mmio + NI6527_FILT_INTERVAL_REG(1)); + writeb((val >> 16) & 0x0f, + dev->mmio + NI6527_FILT_INTERVAL_REG(2)); - writeb(NI6527_CLR_INTERVAL, mmio + NI6527_CLR_REG); + writeb(NI6527_CLR_INTERVAL, dev->mmio + NI6527_CLR_REG); devpriv->filter_interval = val; } @@ -115,12 +115,9 @@ static void ni6527_set_filter_interval(struct comedi_device *dev, static void ni6527_set_filter_enable(struct comedi_device *dev, unsigned int val) { - struct ni6527_private *devpriv = dev->private; - void __iomem *mmio = devpriv->mmio_base; - - writeb(val & 0xff, mmio + NI6527_FILT_ENA_REG(0)); - writeb((val >> 8) & 0xff, mmio + NI6527_FILT_ENA_REG(1)); - writeb((val >> 16) & 0xff, mmio + NI6527_FILT_ENA_REG(2)); + writeb(val & 0xff, dev->mmio + NI6527_FILT_ENA_REG(0)); + writeb((val >> 8) & 0xff, dev->mmio + NI6527_FILT_ENA_REG(1)); + writeb((val >> 16) & 0xff, dev->mmio + NI6527_FILT_ENA_REG(2)); } static int ni6527_di_insn_config(struct comedi_device *dev, @@ -162,13 +159,11 @@ static int ni6527_di_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct ni6527_private *devpriv = dev->private; - void __iomem *mmio = devpriv->mmio_base; unsigned int val; - val = readb(mmio + NI6527_DI_REG(0)); - val |= (readb(mmio + NI6527_DI_REG(1)) << 8); - val |= (readb(mmio + NI6527_DI_REG(2)) << 16); + val = readb(dev->mmio + NI6527_DI_REG(0)); + val |= (readb(dev->mmio + NI6527_DI_REG(1)) << 8); + val |= (readb(dev->mmio + NI6527_DI_REG(2)) << 16); data[1] = val; @@ -180,8 +175,6 @@ static int ni6527_do_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct ni6527_private *devpriv = dev->private; - void __iomem *mmio = devpriv->mmio_base; unsigned int mask; mask = comedi_dio_update_state(s, data); @@ -190,11 +183,13 @@ static int ni6527_do_insn_bits(struct comedi_device *dev, unsigned int val = s->state ^ 0xffffff; if (mask & 0x0000ff) - writeb(val & 0xff, mmio + NI6527_DO_REG(0)); + writeb(val & 0xff, dev->mmio + NI6527_DO_REG(0)); if (mask & 0x00ff00) - writeb((val >> 8) & 0xff, mmio + NI6527_DO_REG(1)); + writeb((val >> 8) & 0xff, + dev->mmio + NI6527_DO_REG(1)); if (mask & 0xff0000) - writeb((val >> 16) & 0xff, mmio + NI6527_DO_REG(2)); + writeb((val >> 16) & 0xff, + dev->mmio + NI6527_DO_REG(2)); } data[1] = s->state; @@ -205,12 +200,10 @@ static int ni6527_do_insn_bits(struct comedi_device *dev, static irqreturn_t ni6527_interrupt(int irq, void *d) { struct comedi_device *dev = d; - struct ni6527_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; - void __iomem *mmio = devpriv->mmio_base; unsigned int status; - status = readb(mmio + NI6527_STATUS_REG); + status = readb(dev->mmio + NI6527_STATUS_REG); if (!(status & NI6527_STATUS_IRQ)) return IRQ_NONE; @@ -220,7 +213,7 @@ static irqreturn_t ni6527_interrupt(int irq, void *d) comedi_event(dev, s); } - writeb(NI6527_CLR_IRQS, mmio + NI6527_CLR_REG); + writeb(NI6527_CLR_IRQS, dev->mmio + NI6527_CLR_REG); return IRQ_HANDLED; } @@ -270,11 +263,8 @@ static int ni6527_intr_cmdtest(struct comedi_device *dev, static int ni6527_intr_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - struct ni6527_private *devpriv = dev->private; - void __iomem *mmio = devpriv->mmio_base; - - writeb(NI6527_CLR_IRQS, mmio + NI6527_CLR_REG); - writeb(NI6527_CTRL_ENABLE_IRQS, mmio + NI6527_CTRL_REG); + writeb(NI6527_CLR_IRQS, dev->mmio + NI6527_CLR_REG); + writeb(NI6527_CTRL_ENABLE_IRQS, dev->mmio + NI6527_CTRL_REG); return 0; } @@ -282,10 +272,7 @@ static int ni6527_intr_cmd(struct comedi_device *dev, static int ni6527_intr_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - struct ni6527_private *devpriv = dev->private; - void __iomem *mmio = devpriv->mmio_base; - - writeb(NI6527_CTRL_DISABLE_IRQS, mmio + NI6527_CTRL_REG); + writeb(NI6527_CTRL_DISABLE_IRQS, dev->mmio + NI6527_CTRL_REG); return 0; } @@ -299,21 +286,37 @@ static int ni6527_intr_insn_bits(struct comedi_device *dev, } static void ni6527_set_edge_detection(struct comedi_device *dev, + unsigned int mask, unsigned int rising, unsigned int falling) { - struct ni6527_private *devpriv = dev->private; - void __iomem *mmio = devpriv->mmio_base; - - /* enable rising-edge detection channels */ - writeb(rising & 0xff, mmio + NI6527_RISING_EDGE_REG(0)); - writeb((rising >> 8) & 0xff, mmio + NI6527_RISING_EDGE_REG(1)); - writeb((rising >> 16) & 0xff, mmio + NI6527_RISING_EDGE_REG(2)); - - /* enable falling-edge detection channels */ - writeb(falling & 0xff, mmio + NI6527_FALLING_EDGE_REG(0)); - writeb((falling >> 8) & 0xff, mmio + NI6527_FALLING_EDGE_REG(1)); - writeb((falling >> 16) & 0xff, mmio + NI6527_FALLING_EDGE_REG(2)); + unsigned int i; + + rising &= mask; + falling &= mask; + for (i = 0; i < 2; i++) { + if (mask & 0xff) { + if (~mask & 0xff) { + /* preserve rising-edge detection channels */ + rising |= readb(dev->mmio + + NI6527_RISING_EDGE_REG(i)) & + (~mask & 0xff); + /* preserve falling-edge detection channels */ + falling |= readb(dev->mmio + + NI6527_FALLING_EDGE_REG(i)) & + (~mask & 0xff); + } + /* update rising-edge detection channels */ + writeb(rising & 0xff, + dev->mmio + NI6527_RISING_EDGE_REG(i)); + /* update falling-edge detection channels */ + writeb(falling & 0xff, + dev->mmio + NI6527_FALLING_EDGE_REG(i)); + } + rising >>= 8; + falling >>= 8; + mask >>= 8; + } } static int ni6527_intr_insn_config(struct comedi_device *dev, @@ -321,12 +324,45 @@ static int ni6527_intr_insn_config(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { + unsigned int mask = 0xffffffff; + unsigned int rising, falling, shift; + switch (data[0]) { case INSN_CONFIG_CHANGE_NOTIFY: /* check_insn_config_length() does not check this instruction */ if (insn->n != 3) return -EINVAL; - ni6527_set_edge_detection(dev, data[1], data[2]); + rising = data[1]; + falling = data[2]; + ni6527_set_edge_detection(dev, mask, rising, falling); + break; + case INSN_CONFIG_DIGITAL_TRIG: + /* check trigger number */ + if (data[1] != 0) + return -EINVAL; + /* check digital trigger operation */ + switch (data[2]) { + case COMEDI_DIGITAL_TRIG_DISABLE: + rising = 0; + falling = 0; + break; + case COMEDI_DIGITAL_TRIG_ENABLE_EDGES: + /* check shift amount */ + shift = data[3]; + if (shift >= s->n_chan) { + mask = 0; + rising = 0; + falling = 0; + } else { + mask <<= shift; + rising = data[4] << shift; + falling = data[5] << shift; + } + break; + default: + return -EINVAL; + } + ni6527_set_edge_detection(dev, mask, rising, falling); break; default: return -EINVAL; @@ -337,15 +373,15 @@ static int ni6527_intr_insn_config(struct comedi_device *dev, static void ni6527_reset(struct comedi_device *dev) { - struct ni6527_private *devpriv = dev->private; - void __iomem *mmio = devpriv->mmio_base; - /* disable deglitch filters on all channels */ ni6527_set_filter_enable(dev, 0); + /* disable edge detection */ + ni6527_set_edge_detection(dev, 0xffffffff, 0, 0); + writeb(NI6527_CLR_IRQS | NI6527_CLR_RESET_FILT, - mmio + NI6527_CLR_REG); - writeb(NI6527_CTRL_DISABLE_IRQS, mmio + NI6527_CTRL_REG); + dev->mmio + NI6527_CLR_REG); + writeb(NI6527_CTRL_DISABLE_IRQS, dev->mmio + NI6527_CTRL_REG); } static int ni6527_auto_attach(struct comedi_device *dev, @@ -372,12 +408,12 @@ static int ni6527_auto_attach(struct comedi_device *dev, if (ret) return ret; - devpriv->mmio_base = pci_ioremap_bar(pcidev, 1); - if (!devpriv->mmio_base) + dev->mmio = pci_ioremap_bar(pcidev, 1); + if (!dev->mmio) return -ENOMEM; /* make sure this is actually a 6527 device */ - if (readb(devpriv->mmio_base + NI6527_ID_REG) != 0x27) + if (readb(dev->mmio + NI6527_ID_REG) != 0x27) return -ENODEV; ni6527_reset(dev); @@ -434,12 +470,12 @@ static int ni6527_auto_attach(struct comedi_device *dev, static void ni6527_detach(struct comedi_device *dev) { - struct ni6527_private *devpriv = dev->private; - - if (devpriv && devpriv->mmio_base) + if (dev->mmio) ni6527_reset(dev); if (dev->irq) free_irq(dev->irq, dev); + if (dev->mmio) + iounmap(dev->mmio); comedi_pci_disable(dev); } diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index 9a139d6b8ef4..873941be56cb 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -1,46 +1,73 @@ /* - comedi/drivers/ni_6514.c - driver for National Instruments PCI-6514 - - Copyright (C) 2006 Jon Grierson <jd@renko.co.uk> - Copyright (C) 2006 Frank Mori Hess <fmhess@users.sourceforge.net> - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1999,2002,2003 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. + * ni_65xx.c + * Comedi driver for National Instruments PCI-65xx static dio boards + * + * Copyright (C) 2006 Jon Grierson <jd@renko.co.uk> + * Copyright (C) 2006 Frank Mori Hess <fmhess@users.sourceforge.net> + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1999,2002,2003 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: ni_65xx -Description: National Instruments 65xx static dio boards -Author: Jon Grierson <jd@renko.co.uk>, - Frank Mori Hess <fmhess@users.sourceforge.net> -Status: testing -Devices: [National Instruments] PCI-6509 (ni_65xx), PXI-6509, PCI-6510, - PCI-6511, PXI-6511, PCI-6512, PXI-6512, PCI-6513, PXI-6513, PCI-6514, - PXI-6514, PCI-6515, PXI-6515, PCI-6516, PCI-6517, PCI-6518, PCI-6519, - PCI-6520, PCI-6521, PXI-6521, PCI-6528, PXI-6528 -Updated: Wed Oct 18 08:59:11 EDT 2006 - -Based on the PCI-6527 driver by ds. -The interrupt subdevice (subdevice 3) is probably broken for all boards -except maybe the 6514. - -*/ + * Driver: ni_65xx + * Description: National Instruments 65xx static dio boards + * Author: Jon Grierson <jd@renko.co.uk>, + * Frank Mori Hess <fmhess@users.sourceforge.net> + * Status: testing + * Devices: (National Instruments) PCI-6509 [ni_65xx] + * (National Instruments) PXI-6509 [ni_65xx] + * (National Instruments) PCI-6510 [ni_65xx] + * (National Instruments) PCI-6511 [ni_65xx] + * (National Instruments) PXI-6511 [ni_65xx] + * (National Instruments) PCI-6512 [ni_65xx] + * (National Instruments) PXI-6512 [ni_65xx] + * (National Instruments) PCI-6513 [ni_65xx] + * (National Instruments) PXI-6513 [ni_65xx] + * (National Instruments) PCI-6514 [ni_65xx] + * (National Instruments) PXI-6514 [ni_65xx] + * (National Instruments) PCI-6515 [ni_65xx] + * (National Instruments) PXI-6515 [ni_65xx] + * (National Instruments) PCI-6516 [ni_65xx] + * (National Instruments) PCI-6517 [ni_65xx] + * (National Instruments) PCI-6518 [ni_65xx] + * (National Instruments) PCI-6519 [ni_65xx] + * (National Instruments) PCI-6520 [ni_65xx] + * (National Instruments) PCI-6521 [ni_65xx] + * (National Instruments) PXI-6521 [ni_65xx] + * (National Instruments) PCI-6528 [ni_65xx] + * (National Instruments) PXI-6528 [ni_65xx] + * Updated: Mon, 21 Jul 2014 12:49:58 +0000 + * + * Configuration Options: not applicable, uses PCI auto config + * + * Based on the PCI-6527 driver by ds. + * The interrupt subdevice (subdevice 3) is probably broken for all + * boards except maybe the 6514. + * + * This driver previously inverted the outputs on PCI-6513 through to + * PCI-6519 and on PXI-6513 through to PXI-6515. It no longer inverts + * outputs on those cards by default as it didn't make much sense. If + * you require the outputs to be inverted on those cards for legacy + * reasons, set the module parameter "legacy_invert_outputs=true" when + * loading the module, or set "ni_65xx.legacy_invert_outputs=true" on + * the kernel command line if the driver is built in to the kernel. + */ /* - Manuals (available from ftp://ftp.natinst.com/support/manuals) - - 370106b.pdf 6514 Register Level Programmer Manual - + * Manuals (available from ftp://ftp.natinst.com/support/manuals) + * + * 370106b.pdf 6514 Register Level Programmer Manual */ #include <linux/module.h> @@ -50,59 +77,69 @@ except maybe the 6514. #include "../comedidev.h" #include "comedi_fc.h" -#include "mite.h" - -#define NI6514_DIO_SIZE 4096 -#define NI6514_MITE_SIZE 4096 - -#define NI_65XX_MAX_NUM_PORTS 12 -static const unsigned ni_65xx_channels_per_port = 8; -static const unsigned ni_65xx_port_offset = 0x10; - -static inline unsigned Port_Data(unsigned port) -{ - return 0x40 + port * ni_65xx_port_offset; -} - -static inline unsigned Port_Select(unsigned port) -{ - return 0x41 + port * ni_65xx_port_offset; -} - -static inline unsigned Rising_Edge_Detection_Enable(unsigned port) -{ - return 0x42 + port * ni_65xx_port_offset; -} - -static inline unsigned Falling_Edge_Detection_Enable(unsigned port) -{ - return 0x43 + port * ni_65xx_port_offset; -} - -static inline unsigned Filter_Enable(unsigned port) -{ - return 0x44 + port * ni_65xx_port_offset; -} - -#define ID_Register 0x00 - -#define Clear_Register 0x01 -#define ClrEdge 0x08 -#define ClrOverflow 0x04 -#define Filter_Interval 0x08 - -#define Change_Status 0x02 -#define MasterInterruptStatus 0x04 -#define Overflow 0x02 -#define EdgeStatus 0x01 +/* + * PCI BAR1 Register Map + */ -#define Master_Interrupt_Control 0x03 -#define FallingEdgeIntEnable 0x10 -#define RisingEdgeIntEnable 0x08 -#define MasterInterruptEnable 0x04 -#define OverflowIntEnable 0x02 -#define EdgeIntEnable 0x01 +/* Non-recurring Registers (8-bit except where noted) */ +#define NI_65XX_ID_REG 0x00 +#define NI_65XX_CLR_REG 0x01 +#define NI_65XX_CLR_WDOG_INT (1 << 6) +#define NI_65XX_CLR_WDOG_PING (1 << 5) +#define NI_65XX_CLR_WDOG_EXP (1 << 4) +#define NI_65XX_CLR_EDGE_INT (1 << 3) +#define NI_65XX_CLR_OVERFLOW_INT (1 << 2) +#define NI_65XX_STATUS_REG 0x02 +#define NI_65XX_STATUS_WDOG_INT (1 << 5) +#define NI_65XX_STATUS_FALL_EDGE (1 << 4) +#define NI_65XX_STATUS_RISE_EDGE (1 << 3) +#define NI_65XX_STATUS_INT (1 << 2) +#define NI_65XX_STATUS_OVERFLOW_INT (1 << 1) +#define NI_65XX_STATUS_EDGE_INT (1 << 0) +#define NI_65XX_CTRL_REG 0x03 +#define NI_65XX_CTRL_WDOG_ENA (1 << 5) +#define NI_65XX_CTRL_FALL_EDGE_ENA (1 << 4) +#define NI_65XX_CTRL_RISE_EDGE_ENA (1 << 3) +#define NI_65XX_CTRL_INT_ENA (1 << 2) +#define NI_65XX_CTRL_OVERFLOW_ENA (1 << 1) +#define NI_65XX_CTRL_EDGE_ENA (1 << 0) +#define NI_65XX_REV_REG 0x04 /* 32-bit */ +#define NI_65XX_FILTER_REG 0x08 /* 32-bit */ +#define NI_65XX_RTSI_ROUTE_REG 0x0c /* 16-bit */ +#define NI_65XX_RTSI_EDGE_REG 0x0e /* 16-bit */ +#define NI_65XX_RTSI_WDOG_REG 0x10 /* 16-bit */ +#define NI_65XX_RTSI_TRIG_REG 0x12 /* 16-bit */ +#define NI_65XX_AUTO_CLK_SEL_REG 0x14 /* PXI-6528 only */ +#define NI_65XX_AUTO_CLK_SEL_STATUS (1 << 1) +#define NI_65XX_AUTO_CLK_SEL_DISABLE (1 << 0) +#define NI_65XX_WDOG_CTRL_REG 0x15 +#define NI_65XX_WDOG_CTRL_ENA (1 << 0) +#define NI_65XX_RTSI_CFG_REG 0x16 +#define NI_65XX_RTSI_CFG_RISE_SENSE (1 << 2) +#define NI_65XX_RTSI_CFG_FALL_SENSE (1 << 1) +#define NI_65XX_RTSI_CFG_SYNC_DETECT (1 << 0) +#define NI_65XX_WDOG_STATUS_REG 0x17 +#define NI_65XX_WDOG_STATUS_EXP (1 << 0) +#define NI_65XX_WDOG_INTERVAL_REG 0x18 /* 32-bit */ + +/* Recurring port registers (8-bit) */ +#define NI_65XX_PORT(x) ((x) * 0x10) +#define NI_65XX_IO_DATA_REG(x) (0x40 + NI_65XX_PORT(x)) +#define NI_65XX_IO_SEL_REG(x) (0x41 + NI_65XX_PORT(x)) +#define NI_65XX_IO_SEL_OUTPUT (0 << 0) +#define NI_65XX_IO_SEL_INPUT (1 << 0) +#define NI_65XX_RISE_EDGE_ENA_REG(x) (0x42 + NI_65XX_PORT(x)) +#define NI_65XX_FALL_EDGE_ENA_REG(x) (0x43 + NI_65XX_PORT(x)) +#define NI_65XX_FILTER_ENA(x) (0x44 + NI_65XX_PORT(x)) +#define NI_65XX_WDOG_HIZ_REG(x) (0x46 + NI_65XX_PORT(x)) +#define NI_65XX_WDOG_ENA(x) (0x47 + NI_65XX_PORT(x)) +#define NI_65XX_WDOG_HI_LO_REG(x) (0x48 + NI_65XX_PORT(x)) +#define NI_65XX_RTSI_ENA(x) (0x49 + NI_65XX_PORT(x)) + +#define NI_65XX_PORT_TO_CHAN(x) ((x) * 8) +#define NI_65XX_CHAN_TO_PORT(x) ((x) / 8) +#define NI_65XX_CHAN_TO_MASK(x) (1 << ((x) % 8)) enum ni_65xx_boardid { BOARD_PCI6509, @@ -134,7 +171,7 @@ struct ni_65xx_board { unsigned num_dio_ports; unsigned num_di_ports; unsigned num_do_ports; - unsigned invert_outputs:1; + unsigned legacy_invert:1; }; static const struct ni_65xx_board ni_65xx_boards[] = { @@ -169,58 +206,58 @@ static const struct ni_65xx_board ni_65xx_boards[] = { [BOARD_PCI6513] = { .name = "pci-6513", .num_do_ports = 8, - .invert_outputs = 1, + .legacy_invert = 1, }, [BOARD_PXI6513] = { .name = "pxi-6513", .num_do_ports = 8, - .invert_outputs = 1, + .legacy_invert = 1, }, [BOARD_PCI6514] = { .name = "pci-6514", .num_di_ports = 4, .num_do_ports = 4, - .invert_outputs = 1, + .legacy_invert = 1, }, [BOARD_PXI6514] = { .name = "pxi-6514", .num_di_ports = 4, .num_do_ports = 4, - .invert_outputs = 1, + .legacy_invert = 1, }, [BOARD_PCI6515] = { .name = "pci-6515", .num_di_ports = 4, .num_do_ports = 4, - .invert_outputs = 1, + .legacy_invert = 1, }, [BOARD_PXI6515] = { .name = "pxi-6515", .num_di_ports = 4, .num_do_ports = 4, - .invert_outputs = 1, + .legacy_invert = 1, }, [BOARD_PCI6516] = { .name = "pci-6516", .num_do_ports = 4, - .invert_outputs = 1, + .legacy_invert = 1, }, [BOARD_PCI6517] = { .name = "pci-6517", .num_do_ports = 4, - .invert_outputs = 1, + .legacy_invert = 1, }, [BOARD_PCI6518] = { .name = "pci-6518", .num_di_ports = 2, .num_do_ports = 2, - .invert_outputs = 1, + .legacy_invert = 1, }, [BOARD_PCI6519] = { .name = "pci-6519", .num_di_ports = 2, .num_do_ports = 2, - .invert_outputs = 1, + .legacy_invert = 1, }, [BOARD_PCI6520] = { .name = "pci-6520", @@ -249,135 +286,174 @@ static const struct ni_65xx_board ni_65xx_boards[] = { }, }; -static inline unsigned ni_65xx_port_by_channel(unsigned channel) -{ - return channel / ni_65xx_channels_per_port; -} +static bool ni_65xx_legacy_invert_outputs; +module_param_named(legacy_invert_outputs, ni_65xx_legacy_invert_outputs, + bool, 0444); +MODULE_PARM_DESC(legacy_invert_outputs, + "invert outputs of PCI/PXI-6513/6514/6515/6516/6517/6518/6519 for compatibility with old user code"); -static inline unsigned ni_65xx_total_num_ports(const struct ni_65xx_board - *board) +static unsigned int ni_65xx_num_ports(struct comedi_device *dev) { + const struct ni_65xx_board *board = comedi_board(dev); + return board->num_dio_ports + board->num_di_ports + board->num_do_ports; } -struct ni_65xx_private { - struct mite_struct *mite; - unsigned int filter_interval; - unsigned short filter_enable[NI_65XX_MAX_NUM_PORTS]; - unsigned short output_bits[NI_65XX_MAX_NUM_PORTS]; - unsigned short dio_direction[NI_65XX_MAX_NUM_PORTS]; -}; +static void ni_65xx_disable_input_filters(struct comedi_device *dev) +{ + unsigned int num_ports = ni_65xx_num_ports(dev); + int i; -struct ni_65xx_subdevice_private { - unsigned base_port; -}; + /* disable input filtering on all ports */ + for (i = 0; i < num_ports; ++i) + writeb(0x00, dev->mmio + NI_65XX_FILTER_ENA(i)); -static inline struct ni_65xx_subdevice_private *sprivate(struct comedi_subdevice - *subdev) -{ - return subdev->private; + /* set filter interval to 0 (32bit reg) */ + writel(0x00000000, dev->mmio + NI_65XX_FILTER_REG); } -static int ni_65xx_config_filter(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +/* updates edge detection for base_chan to base_chan+31 */ +static void ni_65xx_update_edge_detection(struct comedi_device *dev, + unsigned int base_chan, + unsigned int rising, + unsigned int falling) { - struct ni_65xx_private *devpriv = dev->private; - const unsigned chan = CR_CHAN(insn->chanspec); - const unsigned port = - sprivate(s)->base_port + ni_65xx_port_by_channel(chan); + unsigned int num_ports = ni_65xx_num_ports(dev); + unsigned int port; - if (data[0] != INSN_CONFIG_FILTER) - return -EINVAL; - if (data[1]) { - static const unsigned filter_resolution_ns = 200; - static const unsigned max_filter_interval = 0xfffff; - unsigned interval = - (data[1] + - (filter_resolution_ns / 2)) / filter_resolution_ns; - if (interval > max_filter_interval) - interval = max_filter_interval; - data[1] = interval * filter_resolution_ns; - - if (interval != devpriv->filter_interval) { - writeb(interval, - devpriv->mite->daq_io_addr + - Filter_Interval); - devpriv->filter_interval = interval; - } + if (base_chan >= NI_65XX_PORT_TO_CHAN(num_ports)) + return; - devpriv->filter_enable[port] |= - 1 << (chan % ni_65xx_channels_per_port); - } else { - devpriv->filter_enable[port] &= - ~(1 << (chan % ni_65xx_channels_per_port)); - } + for (port = NI_65XX_CHAN_TO_PORT(base_chan); port < num_ports; port++) { + int bitshift = (int)(NI_65XX_PORT_TO_CHAN(port) - base_chan); + unsigned int port_mask, port_rising, port_falling; - writeb(devpriv->filter_enable[port], - devpriv->mite->daq_io_addr + Filter_Enable(port)); + if (bitshift >= 32) + break; - return 2; + if (bitshift >= 0) { + port_mask = ~0U >> bitshift; + port_rising = rising >> bitshift; + port_falling = falling >> bitshift; + } else { + port_mask = ~0U << -bitshift; + port_rising = rising << -bitshift; + port_falling = falling << -bitshift; + } + if (port_mask & 0xff) { + if (~port_mask & 0xff) { + port_rising |= + readb(dev->mmio + + NI_65XX_RISE_EDGE_ENA_REG(port)) & + ~port_mask; + port_falling |= + readb(dev->mmio + + NI_65XX_FALL_EDGE_ENA_REG(port)) & + ~port_mask; + } + writeb(port_rising & 0xff, + dev->mmio + NI_65XX_RISE_EDGE_ENA_REG(port)); + writeb(port_falling & 0xff, + dev->mmio + NI_65XX_FALL_EDGE_ENA_REG(port)); + } + } +} + +static void ni_65xx_disable_edge_detection(struct comedi_device *dev) +{ + /* clear edge detection for channels 0 to 31 */ + ni_65xx_update_edge_detection(dev, 0, 0, 0); + /* clear edge detection for channels 32 to 63 */ + ni_65xx_update_edge_detection(dev, 32, 0, 0); + /* clear edge detection for channels 64 to 95 */ + ni_65xx_update_edge_detection(dev, 64, 0, 0); } static int ni_65xx_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - struct ni_65xx_private *devpriv = dev->private; - unsigned port; + unsigned long base_port = (unsigned long)s->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int chan_mask = NI_65XX_CHAN_TO_MASK(chan); + unsigned port = base_port + NI_65XX_CHAN_TO_PORT(chan); + unsigned int interval; + unsigned int val; - if (insn->n < 1) - return -EINVAL; - port = sprivate(s)->base_port + - ni_65xx_port_by_channel(CR_CHAN(insn->chanspec)); switch (data[0]) { case INSN_CONFIG_FILTER: - return ni_65xx_config_filter(dev, s, insn, data); + /* + * The deglitch filter interval is specified in nanoseconds. + * The hardware supports intervals in 200ns increments. Round + * the user values up and return the actual interval. + */ + interval = (data[1] + 100) / 200; + if (interval > 0xfffff) + interval = 0xfffff; + data[1] = interval * 200; + + /* + * Enable/disable the channel for deglitch filtering. Note + * that the filter interval is never set to '0'. This is done + * because other channels might still be enabled for filtering. + */ + val = readb(dev->mmio + NI_65XX_FILTER_ENA(port)); + if (interval) { + writel(interval, dev->mmio + NI_65XX_FILTER_REG); + val |= chan_mask; + } else { + val &= ~chan_mask; + } + writeb(val, dev->mmio + NI_65XX_FILTER_ENA(port)); break; + case INSN_CONFIG_DIO_OUTPUT: if (s->type != COMEDI_SUBD_DIO) return -EINVAL; - devpriv->dio_direction[port] = COMEDI_OUTPUT; - writeb(0, devpriv->mite->daq_io_addr + Port_Select(port)); - return 1; + writeb(NI_65XX_IO_SEL_OUTPUT, + dev->mmio + NI_65XX_IO_SEL_REG(port)); break; + case INSN_CONFIG_DIO_INPUT: if (s->type != COMEDI_SUBD_DIO) return -EINVAL; - devpriv->dio_direction[port] = COMEDI_INPUT; - writeb(1, devpriv->mite->daq_io_addr + Port_Select(port)); - return 1; + writeb(NI_65XX_IO_SEL_INPUT, + dev->mmio + NI_65XX_IO_SEL_REG(port)); break; + case INSN_CONFIG_DIO_QUERY: if (s->type != COMEDI_SUBD_DIO) return -EINVAL; - data[1] = devpriv->dio_direction[port]; - return insn->n; + val = readb(dev->mmio + NI_65XX_IO_SEL_REG(port)); + data[1] = (val == NI_65XX_IO_SEL_INPUT) ? COMEDI_INPUT + : COMEDI_OUTPUT; break; + default: - break; + return -EINVAL; } - return -EINVAL; + + return insn->n; } static int ni_65xx_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - const struct ni_65xx_board *board = comedi_board(dev); - struct ni_65xx_private *devpriv = dev->private; - int base_bitfield_channel; + unsigned long base_port = (unsigned long)s->private; + unsigned int base_chan = CR_CHAN(insn->chanspec); + int last_port_offset = NI_65XX_CHAN_TO_PORT(s->n_chan - 1); unsigned read_bits = 0; - int last_port_offset = ni_65xx_port_by_channel(s->n_chan - 1); int port_offset; - base_bitfield_channel = CR_CHAN(insn->chanspec); - for (port_offset = ni_65xx_port_by_channel(base_bitfield_channel); + for (port_offset = NI_65XX_CHAN_TO_PORT(base_chan); port_offset <= last_port_offset; port_offset++) { - unsigned port = sprivate(s)->base_port + port_offset; - int base_port_channel = port_offset * ni_65xx_channels_per_port; - unsigned port_mask, port_data, port_read_bits; - int bitshift = base_port_channel - base_bitfield_channel; + unsigned port = base_port + port_offset; + int base_port_channel = NI_65XX_PORT_TO_CHAN(port_offset); + unsigned port_mask, port_data, bits; + int bitshift = base_port_channel - base_chan; if (bitshift >= 32) break; @@ -392,32 +468,26 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev, } port_mask &= 0xff; port_data &= 0xff; + + /* update the outputs */ if (port_mask) { - unsigned bits; - devpriv->output_bits[port] &= ~port_mask; - devpriv->output_bits[port] |= - port_data & port_mask; - bits = devpriv->output_bits[port]; - if (board->invert_outputs) - bits = ~bits; - writeb(bits, - devpriv->mite->daq_io_addr + - Port_Data(port)); - } - port_read_bits = - readb(devpriv->mite->daq_io_addr + Port_Data(port)); - if (s->type == COMEDI_SUBD_DO && board->invert_outputs) { - /* Outputs inverted, so invert value read back from - * DO subdevice. (Does not apply to boards with DIO - * subdevice.) */ - port_read_bits ^= 0xFF; + bits = readb(dev->mmio + NI_65XX_IO_DATA_REG(port)); + bits ^= s->io_bits; /* invert if necessary */ + bits &= ~port_mask; + bits |= (port_data & port_mask); + bits ^= s->io_bits; /* invert back */ + writeb(bits, dev->mmio + NI_65XX_IO_DATA_REG(port)); } + + /* read back the actual state */ + bits = readb(dev->mmio + NI_65XX_IO_DATA_REG(port)); + bits ^= s->io_bits; /* invert if necessary */ if (bitshift > 0) - port_read_bits <<= bitshift; + bits <<= bitshift; else - port_read_bits >>= -bitshift; + bits >>= -bitshift; - read_bits |= port_read_bits; + read_bits |= bits; } data[1] = read_bits; return insn->n; @@ -426,18 +496,17 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev, static irqreturn_t ni_65xx_interrupt(int irq, void *d) { struct comedi_device *dev = d; - struct ni_65xx_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; unsigned int status; - status = readb(devpriv->mite->daq_io_addr + Change_Status); - if ((status & MasterInterruptStatus) == 0) + status = readb(dev->mmio + NI_65XX_STATUS_REG); + if ((status & NI_65XX_STATUS_INT) == 0) return IRQ_NONE; - if ((status & EdgeStatus) == 0) + if ((status & NI_65XX_STATUS_EDGE_INT) == 0) return IRQ_NONE; - writeb(ClrEdge | ClrOverflow, - devpriv->mite->daq_io_addr + Clear_Register); + writeb(NI_65XX_CLR_EDGE_INT | NI_65XX_CLR_OVERFLOW_INT, + dev->mmio + NI_65XX_CLR_REG); comedi_buf_put(s, 0); s->async->events |= COMEDI_CB_EOS; @@ -490,13 +559,11 @@ static int ni_65xx_intr_cmdtest(struct comedi_device *dev, static int ni_65xx_intr_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - struct ni_65xx_private *devpriv = dev->private; - - writeb(ClrEdge | ClrOverflow, - devpriv->mite->daq_io_addr + Clear_Register); - writeb(FallingEdgeIntEnable | RisingEdgeIntEnable | - MasterInterruptEnable | EdgeIntEnable, - devpriv->mite->daq_io_addr + Master_Interrupt_Control); + writeb(NI_65XX_CLR_EDGE_INT | NI_65XX_CLR_OVERFLOW_INT, + dev->mmio + NI_65XX_CLR_REG); + writeb(NI_65XX_CTRL_FALL_EDGE_ENA | NI_65XX_CTRL_RISE_EDGE_ENA | + NI_65XX_CTRL_INT_ENA | NI_65XX_CTRL_EDGE_ENA, + dev->mmio + NI_65XX_CTRL_REG); return 0; } @@ -504,16 +571,15 @@ static int ni_65xx_intr_cmd(struct comedi_device *dev, static int ni_65xx_intr_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - struct ni_65xx_private *devpriv = dev->private; - - writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control); + writeb(0x00, dev->mmio + NI_65XX_CTRL_REG); return 0; } static int ni_65xx_intr_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { data[1] = 0; return insn->n; @@ -524,40 +590,68 @@ static int ni_65xx_intr_insn_config(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct ni_65xx_private *devpriv = dev->private; + switch (data[0]) { + case INSN_CONFIG_CHANGE_NOTIFY: + /* add instruction to check_insn_config_length() */ + if (insn->n != 3) + return -EINVAL; - if (insn->n < 1) - return -EINVAL; - if (data[0] != INSN_CONFIG_CHANGE_NOTIFY) + /* update edge detection for channels 0 to 31 */ + ni_65xx_update_edge_detection(dev, 0, data[1], data[2]); + /* clear edge detection for channels 32 to 63 */ + ni_65xx_update_edge_detection(dev, 32, 0, 0); + /* clear edge detection for channels 64 to 95 */ + ni_65xx_update_edge_detection(dev, 64, 0, 0); + break; + case INSN_CONFIG_DIGITAL_TRIG: + /* check trigger number */ + if (data[1] != 0) + return -EINVAL; + /* check digital trigger operation */ + switch (data[2]) { + case COMEDI_DIGITAL_TRIG_DISABLE: + ni_65xx_disable_edge_detection(dev); + break; + case COMEDI_DIGITAL_TRIG_ENABLE_EDGES: + /* + * update edge detection for channels data[3] + * to (data[3] + 31) + */ + ni_65xx_update_edge_detection(dev, data[3], + data[4], data[5]); + break; + default: + return -EINVAL; + } + break; + default: return -EINVAL; + } + + return insn->n; +} + +/* ripped from mite.h and mite_setup2() to avoid mite dependancy */ +#define MITE_IODWBSR 0xc0 /* IO Device Window Base Size Register */ +#define WENAB (1 << 7) /* window enable */ + +static int ni_65xx_mite_init(struct pci_dev *pcidev) +{ + void __iomem *mite_base; + u32 main_phys_addr; + + /* ioremap the MITE registers (BAR 0) temporarily */ + mite_base = pci_ioremap_bar(pcidev, 0); + if (!mite_base) + return -ENOMEM; + + /* set data window to main registers (BAR 1) */ + main_phys_addr = pci_resource_start(pcidev, 1); + writel(main_phys_addr | WENAB, mite_base + MITE_IODWBSR); - writeb(data[1], - devpriv->mite->daq_io_addr + - Rising_Edge_Detection_Enable(0)); - writeb(data[1] >> 8, - devpriv->mite->daq_io_addr + - Rising_Edge_Detection_Enable(0x10)); - writeb(data[1] >> 16, - devpriv->mite->daq_io_addr + - Rising_Edge_Detection_Enable(0x20)); - writeb(data[1] >> 24, - devpriv->mite->daq_io_addr + - Rising_Edge_Detection_Enable(0x30)); - - writeb(data[2], - devpriv->mite->daq_io_addr + - Falling_Edge_Detection_Enable(0)); - writeb(data[2] >> 8, - devpriv->mite->daq_io_addr + - Falling_Edge_Detection_Enable(0x10)); - writeb(data[2] >> 16, - devpriv->mite->daq_io_addr + - Falling_Edge_Detection_Enable(0x20)); - writeb(data[2] >> 24, - devpriv->mite->daq_io_addr + - Falling_Edge_Detection_Enable(0x30)); - - return 2; + /* finished with MITE registers */ + iounmap(mite_base); + return 0; } static int ni_65xx_auto_attach(struct comedi_device *dev, @@ -565,8 +659,6 @@ static int ni_65xx_auto_attach(struct comedi_device *dev, { struct pci_dev *pcidev = comedi_to_pci_dev(dev); const struct ni_65xx_board *board = NULL; - struct ni_65xx_private *devpriv; - struct ni_65xx_subdevice_private *spriv; struct comedi_subdevice *s; unsigned i; int ret; @@ -582,23 +674,27 @@ static int ni_65xx_auto_attach(struct comedi_device *dev, if (ret) return ret; - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) - return -ENOMEM; + ret = ni_65xx_mite_init(pcidev); + if (ret) + return ret; - devpriv->mite = mite_alloc(pcidev); - if (!devpriv->mite) + dev->mmio = pci_ioremap_bar(pcidev, 1); + if (!dev->mmio) return -ENOMEM; - ret = mite_setup(devpriv->mite); - if (ret < 0) { - dev_warn(dev->class_dev, "error setting up mite\n"); - return ret; + writeb(NI_65XX_CLR_EDGE_INT | NI_65XX_CLR_OVERFLOW_INT, + dev->mmio + NI_65XX_CLR_REG); + writeb(0x00, dev->mmio + NI_65XX_CTRL_REG); + + if (pcidev->irq) { + ret = request_irq(pcidev->irq, ni_65xx_interrupt, IRQF_SHARED, + dev->board_name, dev); + if (ret == 0) + dev->irq = pcidev->irq; } - dev->irq = mite_irq(devpriv->mite); dev_info(dev->class_dev, "board: %s, ID=0x%02x", dev->board_name, - readb(devpriv->mite->daq_io_addr + ID_Register)); + readb(dev->mmio + NI_65XX_ID_REG)); ret = comedi_alloc_subdevices(dev, 4); if (ret) @@ -606,130 +702,111 @@ static int ni_65xx_auto_attach(struct comedi_device *dev, s = &dev->subdevices[0]; if (board->num_di_ports) { - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = - board->num_di_ports * ni_65xx_channels_per_port; - s->range_table = &range_digital; - s->maxdata = 1; - s->insn_config = ni_65xx_dio_insn_config; - s->insn_bits = ni_65xx_dio_insn_bits; - spriv = comedi_alloc_spriv(s, sizeof(*spriv)); - if (!spriv) - return -ENOMEM; - spriv->base_port = 0; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = NI_65XX_PORT_TO_CHAN(board->num_di_ports); + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = ni_65xx_dio_insn_bits; + s->insn_config = ni_65xx_dio_insn_config; + + /* the input ports always start at port 0 */ + s->private = (void *)0; } else { - s->type = COMEDI_SUBD_UNUSED; + s->type = COMEDI_SUBD_UNUSED; } s = &dev->subdevices[1]; if (board->num_do_ports) { - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = - board->num_do_ports * ni_65xx_channels_per_port; - s->range_table = &range_digital; - s->maxdata = 1; - s->insn_bits = ni_65xx_dio_insn_bits; - spriv = comedi_alloc_spriv(s, sizeof(*spriv)); - if (!spriv) - return -ENOMEM; - spriv->base_port = board->num_di_ports; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = NI_65XX_PORT_TO_CHAN(board->num_do_ports); + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = ni_65xx_dio_insn_bits; + + /* the output ports always start after the input ports */ + s->private = (void *)(unsigned long)board->num_di_ports; + + /* + * Use the io_bits to handle the inverted outputs. Inverted + * outputs are only supported if the "legacy_invert_outputs" + * module parameter is set to "true". + */ + if (ni_65xx_legacy_invert_outputs && board->legacy_invert) + s->io_bits = 0xff; + + /* reset all output ports to comedi '0' */ + for (i = 0; i < board->num_do_ports; ++i) { + writeb(s->io_bits, /* inverted if necessary */ + dev->mmio + + NI_65XX_IO_DATA_REG(board->num_di_ports + i)); + } } else { - s->type = COMEDI_SUBD_UNUSED; + s->type = COMEDI_SUBD_UNUSED; } s = &dev->subdevices[2]; if (board->num_dio_ports) { - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = - board->num_dio_ports * ni_65xx_channels_per_port; - s->range_table = &range_digital; - s->maxdata = 1; - s->insn_config = ni_65xx_dio_insn_config; - s->insn_bits = ni_65xx_dio_insn_bits; - spriv = comedi_alloc_spriv(s, sizeof(*spriv)); - if (!spriv) - return -ENOMEM; - spriv->base_port = 0; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = NI_65XX_PORT_TO_CHAN(board->num_dio_ports); + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = ni_65xx_dio_insn_bits; + s->insn_config = ni_65xx_dio_insn_config; + + /* the input/output ports always start at port 0 */ + s->private = (void *)0; + + /* configure all ports for input */ for (i = 0; i < board->num_dio_ports; ++i) { - /* configure all ports for input */ - writeb(0x1, - devpriv->mite->daq_io_addr + - Port_Select(i)); + writeb(NI_65XX_IO_SEL_INPUT, + dev->mmio + NI_65XX_IO_SEL_REG(i)); } } else { - s->type = COMEDI_SUBD_UNUSED; + s->type = COMEDI_SUBD_UNUSED; } s = &dev->subdevices[3]; - dev->read_subdev = s; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE | SDF_CMD_READ; - s->n_chan = 1; - s->range_table = &range_unknown; - s->maxdata = 1; - s->len_chanlist = 1; - s->do_cmdtest = ni_65xx_intr_cmdtest; - s->do_cmd = ni_65xx_intr_cmd; - s->cancel = ni_65xx_intr_cancel; - s->insn_bits = ni_65xx_intr_insn_bits; - s->insn_config = ni_65xx_intr_insn_config; - - for (i = 0; i < ni_65xx_total_num_ports(board); ++i) { - writeb(0x00, - devpriv->mite->daq_io_addr + Filter_Enable(i)); - if (board->invert_outputs) - writeb(0x01, - devpriv->mite->daq_io_addr + Port_Data(i)); - else - writeb(0x00, - devpriv->mite->daq_io_addr + Port_Data(i)); - } - writeb(ClrEdge | ClrOverflow, - devpriv->mite->daq_io_addr + Clear_Register); - writeb(0x00, - devpriv->mite->daq_io_addr + Master_Interrupt_Control); - - /* Set filter interval to 0 (32bit reg) */ - writeb(0x00000000, devpriv->mite->daq_io_addr + Filter_Interval); - - ret = request_irq(dev->irq, ni_65xx_interrupt, IRQF_SHARED, - "ni_65xx", dev); - if (ret < 0) { - dev->irq = 0; - dev_warn(dev->class_dev, "irq not available\n"); + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 1; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = ni_65xx_intr_insn_bits; + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = 1; + s->insn_config = ni_65xx_intr_insn_config; + s->do_cmdtest = ni_65xx_intr_cmdtest; + s->do_cmd = ni_65xx_intr_cmd; + s->cancel = ni_65xx_intr_cancel; } + ni_65xx_disable_input_filters(dev); + ni_65xx_disable_edge_detection(dev); + return 0; } static void ni_65xx_detach(struct comedi_device *dev) { - struct ni_65xx_private *devpriv = dev->private; - - if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr) { - writeb(0x00, - devpriv->mite->daq_io_addr + - Master_Interrupt_Control); + if (dev->mmio) { + writeb(0x00, dev->mmio + NI_65XX_CTRL_REG); + iounmap(dev->mmio); } if (dev->irq) free_irq(dev->irq, dev); - if (devpriv) { - if (devpriv->mite) { - mite_unsetup(devpriv->mite); - mite_free(devpriv->mite); - } - } comedi_pci_disable(dev); } static struct comedi_driver ni_65xx_driver = { - .driver_name = "ni_65xx", - .module = THIS_MODULE, - .auto_attach = ni_65xx_auto_attach, - .detach = ni_65xx_detach, + .driver_name = "ni_65xx", + .module = THIS_MODULE, + .auto_attach = ni_65xx_auto_attach, + .detach = ni_65xx_detach, }; static int ni_65xx_pci_probe(struct pci_dev *dev, @@ -774,5 +851,5 @@ static struct pci_driver ni_65xx_pci_driver = { module_comedi_pci_driver(ni_65xx_driver, ni_65xx_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for NI PCI-65xx static dio boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 634cde83a02b..b0b03d4d6081 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -28,7 +28,7 @@ * * Encoders work. PulseGeneration (both single pulse and pulse train) * works. Buffered commands work for input but not output. - * + * * References: * DAQ 660x Register-Level Programmer Manual (NI 370505A-01) * DAQ 6601/6602 User Manual (NI 322137B-01) @@ -161,6 +161,7 @@ enum ni_660x_register { static inline unsigned IOConfigReg(unsigned pfi_channel) { unsigned reg = NI660X_IO_CFG_0_1 + pfi_channel / 2; + BUG_ON(reg > NI660X_IO_CFG_38_39); return reg; } @@ -310,10 +311,7 @@ enum clock_config_register_bits { /* ioconfigreg */ static inline unsigned ioconfig_bitshift(unsigned pfi_channel) { - if (pfi_channel % 2) - return 0; - else - return 8; + return (pfi_channel % 2) ? 0 : 8; } static inline unsigned pfi_output_select_mask(unsigned pfi_channel) @@ -589,17 +587,14 @@ static inline void ni_660x_write_register(struct comedi_device *dev, unsigned chip, unsigned bits, enum ni_660x_register reg) { - struct ni_660x_private *devpriv = dev->private; - void __iomem *write_address = - devpriv->mite->daq_io_addr + GPCT_OFFSET[chip] + - registerData[reg].offset; + unsigned int addr = GPCT_OFFSET[chip] + registerData[reg].offset; switch (registerData[reg].size) { case DATA_2B: - writew(bits, write_address); + writew(bits, dev->mmio + addr); break; case DATA_4B: - writel(bits, write_address); + writel(bits, dev->mmio + addr); break; default: BUG(); @@ -611,18 +606,13 @@ static inline unsigned ni_660x_read_register(struct comedi_device *dev, unsigned chip, enum ni_660x_register reg) { - struct ni_660x_private *devpriv = dev->private; - void __iomem *read_address = - devpriv->mite->daq_io_addr + GPCT_OFFSET[chip] + - registerData[reg].offset; + unsigned int addr = GPCT_OFFSET[chip] + registerData[reg].offset; switch (registerData[reg].size) { case DATA_2B: - return readw(read_address); - break; + return readw(dev->mmio + addr); case DATA_4B: - return readl(read_address); - break; + return readl(dev->mmio + addr); default: BUG(); break; @@ -714,8 +704,8 @@ static int ni_660x_request_mite_channel(struct comedi_device *dev, mite_ring(devpriv, counter)); if (mite_chan == NULL) { spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); - comedi_error(dev, - "failed to reserve mite dma channel for counter."); + dev_err(dev->class_dev, + "failed to reserve mite dma channel for counter\n"); return -EBUSY; } mite_chan->dir = direction; @@ -749,11 +739,11 @@ static int ni_660x_cmd(struct comedi_device *dev, struct comedi_subdevice *s) retval = ni_660x_request_mite_channel(dev, counter, COMEDI_INPUT); if (retval) { - comedi_error(dev, - "no dma channel available for use by counter"); + dev_err(dev->class_dev, + "no dma channel available for use by counter\n"); return retval; } - ni_tio_acknowledge_and_confirm(counter, NULL, NULL, NULL, NULL); + ni_tio_acknowledge(counter); return ni_tio_cmd(dev, s); } @@ -829,8 +819,7 @@ static int ni_660x_input_poll(struct comedi_device *dev, } static int ni_660x_buf_change(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned long new_size) + struct comedi_subdevice *s) { struct ni_660x_private *devpriv = dev->private; struct ni_gpct *counter = s->private; @@ -1083,11 +1072,9 @@ static int ni_660x_auto_attach(struct comedi_device *dev, if (!devpriv->mite) return -ENOMEM; - ret = mite_setup2(devpriv->mite, 1); - if (ret < 0) { - dev_warn(dev->class_dev, "error setting up mite\n"); + ret = mite_setup2(dev, devpriv->mite, true); + if (ret < 0) return ret; - } ret = ni_660x_alloc_mite_rings(dev); if (ret < 0) @@ -1126,9 +1113,8 @@ static int ni_660x_auto_attach(struct comedi_device *dev, s = &dev->subdevices[NI_660X_GPCT_SUBDEV(i)]; if (i < ni_660x_num_counters(dev)) { s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = - SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | - SDF_CMD_READ /* | SDF_CMD_WRITE */ ; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | + SDF_LSAMPL | SDF_CMD_READ; s->n_chan = 3; s->maxdata = 0xffffffff; s->insn_read = ni_tio_insn_read; @@ -1170,13 +1156,13 @@ static int ni_660x_auto_attach(struct comedi_device *dev, for (i = 0; i < board->n_chips; ++i) set_tio_counterswap(dev, i); - ret = request_irq(mite_irq(devpriv->mite), ni_660x_interrupt, - IRQF_SHARED, "ni_660x", dev); + ret = request_irq(pcidev->irq, ni_660x_interrupt, IRQF_SHARED, + dev->board_name, dev); if (ret < 0) { dev_warn(dev->class_dev, " irq not available\n"); return ret; } - dev->irq = mite_irq(devpriv->mite); + dev->irq = pcidev->irq; global_interrupt_config_bits = Global_Int_Enable_Bit; if (board->n_chips > 1) global_interrupt_config_bits |= Cascade_Int_Enable_Bit; @@ -1195,12 +1181,11 @@ static void ni_660x_detach(struct comedi_device *dev) if (devpriv) { if (devpriv->counter_dev) ni_gpct_device_destroy(devpriv->counter_dev); - if (devpriv->mite) { - ni_660x_free_mite_rings(dev); - mite_unsetup(devpriv->mite); - mite_free(devpriv->mite); - } + ni_660x_free_mite_rings(dev); + mite_detach(devpriv->mite); } + if (dev->mmio) + iounmap(dev->mmio); comedi_pci_disable(dev); } diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index 1002ceacfdcc..f5caefad0b59 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -39,11 +39,10 @@ Commands are not supported. #include <linux/module.h> #include <linux/pci.h> #include <linux/interrupt.h> +#include <linux/slab.h> #include "../comedidev.h" -#include "mite.h" - #define AO_VALUE_OFFSET 0x00 #define AO_CHAN_OFFSET 0x0c #define AO_STATUS_OFFSET 0x10 @@ -82,8 +81,6 @@ static const struct ni_670x_board ni_670x_boards[] = { }; struct ni_670x_private { - - struct mite_struct *mite; int boardtype; int dio; unsigned int ao_readback[32]; @@ -111,9 +108,9 @@ static int ni_670x_ao_winsn(struct comedi_device *dev, for (i = 0; i < insn->n; i++) { /* First write in channel register which channel to use */ writel(((chan & 15) << 1) | ((chan & 16) >> 4), - devpriv->mite->daq_io_addr + AO_CHAN_OFFSET); + dev->mmio + AO_CHAN_OFFSET); /* write channel value */ - writel(data[i], devpriv->mite->daq_io_addr + AO_VALUE_OFFSET); + writel(data[i], dev->mmio + AO_VALUE_OFFSET); devpriv->ao_readback[chan] = data[i]; } @@ -139,14 +136,10 @@ static int ni_670x_dio_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct ni_670x_private *devpriv = dev->private; - void __iomem *io_addr = devpriv->mite->daq_io_addr + - DIO_PORT0_DATA_OFFSET; - if (comedi_dio_update_state(s, data)) - writel(s->state, io_addr); + writel(s->state, dev->mmio + DIO_PORT0_DATA_OFFSET); - data[1] = readl(io_addr); + data[1] = readl(dev->mmio + DIO_PORT0_DATA_OFFSET); return insn->n; } @@ -156,18 +149,40 @@ static int ni_670x_dio_insn_config(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct ni_670x_private *devpriv = dev->private; int ret; ret = comedi_dio_insn_config(dev, s, insn, data, 0); if (ret) return ret; - writel(s->io_bits, devpriv->mite->daq_io_addr + DIO_PORT0_DIR_OFFSET); + writel(s->io_bits, dev->mmio + DIO_PORT0_DIR_OFFSET); return insn->n; } +/* ripped from mite.h and mite_setup2() to avoid mite dependancy */ +#define MITE_IODWBSR 0xc0 /* IO Device Window Base Size Register */ +#define WENAB (1 << 7) /* window enable */ + +static int ni_670x_mite_init(struct pci_dev *pcidev) +{ + void __iomem *mite_base; + u32 main_phys_addr; + + /* ioremap the MITE registers (BAR 0) temporarily */ + mite_base = pci_ioremap_bar(pcidev, 0); + if (!mite_base) + return -ENOMEM; + + /* set data window to main registers (BAR 1) */ + main_phys_addr = pci_resource_start(pcidev, 1); + writel(main_phys_addr | WENAB, mite_base + MITE_IODWBSR); + + /* finished with MITE registers */ + iounmap(mite_base); + return 0; +} + static int ni_670x_auto_attach(struct comedi_device *dev, unsigned long context) { @@ -193,15 +208,13 @@ static int ni_670x_auto_attach(struct comedi_device *dev, if (!devpriv) return -ENOMEM; - devpriv->mite = mite_alloc(pcidev); - if (!devpriv->mite) - return -ENOMEM; - - ret = mite_setup(devpriv->mite); - if (ret < 0) { - dev_warn(dev->class_dev, "error setting up mite\n"); + ret = ni_670x_mite_init(pcidev); + if (ret) return ret; - } + + dev->mmio = pci_ioremap_bar(pcidev, 1); + if (!dev->mmio) + return -ENOMEM; ret = comedi_alloc_subdevices(dev, 2); if (ret) @@ -242,16 +255,15 @@ static int ni_670x_auto_attach(struct comedi_device *dev, s->insn_config = ni_670x_dio_insn_config; /* Config of misc registers */ - writel(0x10, devpriv->mite->daq_io_addr + MISC_CONTROL_OFFSET); + writel(0x10, dev->mmio + MISC_CONTROL_OFFSET); /* Config of ao registers */ - writel(0x00, devpriv->mite->daq_io_addr + AO_CONTROL_OFFSET); + writel(0x00, dev->mmio + AO_CONTROL_OFFSET); return 0; } static void ni_670x_detach(struct comedi_device *dev) { - struct ni_670x_private *devpriv = dev->private; struct comedi_subdevice *s; if (dev->n_subdevices) { @@ -259,10 +271,8 @@ static void ni_670x_detach(struct comedi_device *dev) if (s) kfree(s->range_table_list); } - if (devpriv && devpriv->mite) { - mite_unsetup(devpriv->mite); - mite_free(devpriv->mite); - } + if (dev->mmio) + iounmap(dev->mmio); comedi_pci_disable(dev); } diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 5bd19494dbf6..de67161f6185 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -71,7 +71,6 @@ TRIG_WAKE_EOS #include "8253.h" #include "comedi_fc.h" -#define A2150_SIZE 28 #define A2150_DMA_BUFFER_SIZE 0xff00 /* size in bytes of dma buffer */ /* Registers and bits */ @@ -156,13 +155,6 @@ struct a2150_private { int config_bits; /* config register bits */ }; -static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s); - -static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, - int flags); -static int a2150_set_chanlist(struct comedi_device *dev, - unsigned int start_channel, - unsigned int num_channels); /* interrupt service routine */ static irqreturn_t a2150_interrupt(int irq, void *d) { @@ -179,7 +171,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d) static const int sample_size = sizeof(devpriv->dma_buffer[0]); if (!dev->attached) { - comedi_error(dev, "premature interrupt"); + dev_err(dev->class_dev, "premature interrupt\n"); return IRQ_HANDLED; } /* initialize async here to make sure s is not NULL */ @@ -189,18 +181,19 @@ static irqreturn_t a2150_interrupt(int irq, void *d) status = inw(dev->iobase + STATUS_REG); if ((status & INTR_BIT) == 0) { - comedi_error(dev, "spurious interrupt"); + dev_err(dev->class_dev, "spurious interrupt\n"); return IRQ_NONE; } if (status & OVFL_BIT) { - comedi_error(dev, "fifo overflow"); + dev_err(dev->class_dev, "fifo overflow\n"); async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; cfc_handle_events(dev, s); } if ((status & DMA_TC_BIT) == 0) { - comedi_error(dev, "caught non-dma interrupt? Aborting."); + dev_err(dev->class_dev, + "caught non-dma interrupt? Aborting.\n"); async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; cfc_handle_events(dev, s); return IRQ_HANDLED; @@ -287,6 +280,117 @@ static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } +/* + * sets bits in devpriv->clock_bits to nearest approximation of requested + * period, adjusts requested period to actual timing. + */ +static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, + unsigned int flags) +{ + const struct a2150_board *thisboard = comedi_board(dev); + struct a2150_private *devpriv = dev->private; + int lub, glb, temp; + int lub_divisor_shift, lub_index, glb_divisor_shift, glb_index; + int i, j; + + /* initialize greatest lower and least upper bounds */ + lub_divisor_shift = 3; + lub_index = 0; + lub = thisboard->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); + + /* make sure period is in available range */ + if (*period < glb) + *period = glb; + if (*period > lub) + *period = lub; + + /* 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++) { + /* temp is the period in nanosec we are evaluating */ + temp = thisboard->clock[j] * (1 << i); + /* if it is the best match yet */ + if (temp < lub && temp >= *period) { + lub_divisor_shift = i; + lub_index = j; + lub = temp; + } + if (temp > glb && temp <= *period) { + glb_divisor_shift = i; + glb_index = j; + glb = temp; + } + } + } + switch (flags & TRIG_ROUND_MASK) { + case TRIG_ROUND_NEAREST: + default: + /* if least upper bound is better approximation */ + if (lub - *period < *period - glb) + *period = lub; + else + *period = glb; + break; + case TRIG_ROUND_UP: + *period = lub; + break; + case TRIG_ROUND_DOWN: + *period = glb; + break; + } + + /* set clock bits for config register appropriately */ + devpriv->config_bits &= ~CLOCK_MASK; + if (*period == lub) { + devpriv->config_bits |= + CLOCK_SELECT_BITS(lub_index) | + CLOCK_DIVISOR_BITS(lub_divisor_shift); + } else { + devpriv->config_bits |= + CLOCK_SELECT_BITS(glb_index) | + CLOCK_DIVISOR_BITS(glb_divisor_shift); + } + + return 0; +} + +static int a2150_set_chanlist(struct comedi_device *dev, + unsigned int start_channel, + unsigned int num_channels) +{ + struct a2150_private *devpriv = dev->private; + + if (start_channel + num_channels > 4) + return -1; + + devpriv->config_bits &= ~CHANNEL_MASK; + + switch (num_channels) { + case 1: + devpriv->config_bits |= CHANNEL_BITS(0x4 | start_channel); + break; + case 2: + if (start_channel == 0) + devpriv->config_bits |= CHANNEL_BITS(0x2); + else if (start_channel == 2) + devpriv->config_bits |= CHANNEL_BITS(0x3); + else + return -1; + break; + case 4: + devpriv->config_bits |= CHANNEL_BITS(0x1); + break; + default: + return -1; + } + + return 0; +} + static int a2150_ai_check_chanlist(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) @@ -408,8 +512,8 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) unsigned int trigger_bits; if (cmd->flags & TRIG_RT) { - comedi_error(dev, - " dma incompatible with hard real-time interrupt (TRIG_RT), aborting"); + dev_err(dev->class_dev, + "dma incompatible with hard real-time interrupt (TRIG_RT), aborting\n"); return -1; } /* clear fifo and reset triggering circuitry */ @@ -490,7 +594,7 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) trigger_bits |= HW_TRIG_EN; } else if (cmd->start_src == TRIG_OTHER) { /* XXX add support for level/slope start trigger using TRIG_OTHER */ - comedi_error(dev, "you shouldn't see this?"); + dev_err(dev->class_dev, "you shouldn't see this?\n"); } /* send trigger config bits */ outw(trigger_bits, dev->iobase + TRIGGER_REG); @@ -574,123 +678,11 @@ static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, return n; } -/* - * sets bits in devpriv->clock_bits to nearest approximation of requested - * period, adjusts requested period to actual timing. - */ -static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, - int flags) -{ - const struct a2150_board *thisboard = comedi_board(dev); - struct a2150_private *devpriv = dev->private; - int lub, glb, temp; - int lub_divisor_shift, lub_index, glb_divisor_shift, glb_index; - int i, j; - - /* initialize greatest lower and least upper bounds */ - lub_divisor_shift = 3; - lub_index = 0; - lub = thisboard->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); - - /* make sure period is in available range */ - if (*period < glb) - *period = glb; - if (*period > lub) - *period = lub; - - /* 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++) { - /* temp is the period in nanosec we are evaluating */ - temp = thisboard->clock[j] * (1 << i); - /* if it is the best match yet */ - if (temp < lub && temp >= *period) { - lub_divisor_shift = i; - lub_index = j; - lub = temp; - } - if (temp > glb && temp <= *period) { - glb_divisor_shift = i; - glb_index = j; - glb = temp; - } - } - } - flags &= TRIG_ROUND_MASK; - switch (flags) { - case TRIG_ROUND_NEAREST: - default: - /* if least upper bound is better approximation */ - if (lub - *period < *period - glb) - *period = lub; - else - *period = glb; - break; - case TRIG_ROUND_UP: - *period = lub; - break; - case TRIG_ROUND_DOWN: - *period = glb; - break; - } - - /* set clock bits for config register appropriately */ - devpriv->config_bits &= ~CLOCK_MASK; - if (*period == lub) { - devpriv->config_bits |= - CLOCK_SELECT_BITS(lub_index) | - CLOCK_DIVISOR_BITS(lub_divisor_shift); - } else { - devpriv->config_bits |= - CLOCK_SELECT_BITS(glb_index) | - CLOCK_DIVISOR_BITS(glb_divisor_shift); - } - - return 0; -} - -static int a2150_set_chanlist(struct comedi_device *dev, - unsigned int start_channel, - unsigned int num_channels) -{ - struct a2150_private *devpriv = dev->private; - - if (start_channel + num_channels > 4) - return -1; - - devpriv->config_bits &= ~CHANNEL_MASK; - - switch (num_channels) { - case 1: - devpriv->config_bits |= CHANNEL_BITS(0x4 | start_channel); - break; - case 2: - if (start_channel == 0) - devpriv->config_bits |= CHANNEL_BITS(0x2); - else if (start_channel == 2) - devpriv->config_bits |= CHANNEL_BITS(0x3); - else - return -1; - break; - case 4: - devpriv->config_bits |= CHANNEL_BITS(0x1); - break; - default: - return -1; - break; - } - - return 0; -} - /* probes board type, returns offset */ static int a2150_probe(struct comedi_device *dev) { int status = inw(dev->iobase + STATUS_REG); + return ID_BITS(status); } @@ -709,7 +701,7 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (!devpriv) return -ENOMEM; - ret = comedi_request_region(dev, it->options[0], A2150_SIZE); + ret = comedi_request_region(dev, it->options[0], 0x1c); if (ret) return ret; @@ -784,8 +776,8 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) udelay(1000); } if (i == timeout) { - printk - (" timed out waiting for offset calibration to complete\n"); + dev_err(dev->class_dev, + "timed out waiting for offset calibration to complete\n"); return -ETIME; } devpriv->config_bits |= ENABLE0_BIT | ENABLE1_BIT; diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c index d03935257b97..2bd9f692a7ae 100644 --- a/drivers/staging/comedi/drivers/ni_atmio.c +++ b/drivers/staging/comedi/drivers/ni_atmio.c @@ -98,233 +98,135 @@ are not supported. #include "ni_stc.h" #include "8255.h" -#define ATMIO 1 -#undef PCIMIO - /* * AT specific setup */ -#define NI_SIZE 0x20 - -#define MAX_N_CALDACS 32 - static const struct ni_board_struct ni_boards[] = { - {.device_id = 44, - .isapnp_id = 0x0000, /* XXX unknown */ - .name = "at-mio-16e-1", - .n_adchan = 16, - .adbits = 12, - .ai_fifo_depth = 8192, - .alwaysdither = 0, - .gainlkup = ai_gain_16, - .ai_speed = 800, - .n_aochan = 2, - .aobits = 12, - .ao_fifo_depth = 2048, - .ao_range_table = &range_ni_E_ao_ext, - .ao_unipolar = 1, - .ao_speed = 1000, - .has_8255 = 0, - .num_p0_dio_channels = 8, - .caldac = {mb88341}, - }, - {.device_id = 25, - .isapnp_id = 0x1900, - .name = "at-mio-16e-2", - .n_adchan = 16, - .adbits = 12, - .ai_fifo_depth = 2048, - .alwaysdither = 0, - .gainlkup = ai_gain_16, - .ai_speed = 2000, - .n_aochan = 2, - .aobits = 12, - .ao_fifo_depth = 2048, - .ao_range_table = &range_ni_E_ao_ext, - .ao_unipolar = 1, - .ao_speed = 1000, - .has_8255 = 0, - .num_p0_dio_channels = 8, - .caldac = {mb88341}, - }, - {.device_id = 36, - .isapnp_id = 0x2400, - .name = "at-mio-16e-10", - .n_adchan = 16, - .adbits = 12, - .ai_fifo_depth = 512, - .alwaysdither = 0, - .gainlkup = ai_gain_16, - .ai_speed = 10000, - .n_aochan = 2, - .aobits = 12, - .ao_fifo_depth = 0, - .ao_range_table = &range_ni_E_ao_ext, - .ao_unipolar = 1, - .ao_speed = 10000, - .num_p0_dio_channels = 8, - .caldac = {ad8804_debug}, - .has_8255 = 0, - }, - {.device_id = 37, - .isapnp_id = 0x2500, - .name = "at-mio-16de-10", - .n_adchan = 16, - .adbits = 12, - .ai_fifo_depth = 512, - .alwaysdither = 0, - .gainlkup = ai_gain_16, - .ai_speed = 10000, - .n_aochan = 2, - .aobits = 12, - .ao_fifo_depth = 0, - .ao_range_table = &range_ni_E_ao_ext, - .ao_unipolar = 1, - .ao_speed = 10000, - .num_p0_dio_channels = 8, - .caldac = {ad8804_debug}, - .has_8255 = 1, - }, - {.device_id = 38, - .isapnp_id = 0x2600, - .name = "at-mio-64e-3", - .n_adchan = 64, - .adbits = 12, - .ai_fifo_depth = 2048, - .alwaysdither = 0, - .gainlkup = ai_gain_16, - .ai_speed = 2000, - .n_aochan = 2, - .aobits = 12, - .ao_fifo_depth = 2048, - .ao_range_table = &range_ni_E_ao_ext, - .ao_unipolar = 1, - .ao_speed = 1000, - .has_8255 = 0, - .num_p0_dio_channels = 8, - .caldac = {ad8804_debug}, - }, - {.device_id = 39, - .isapnp_id = 0x2700, - .name = "at-mio-16xe-50", - .n_adchan = 16, - .adbits = 16, - .ai_fifo_depth = 512, - .alwaysdither = 1, - .gainlkup = ai_gain_8, - .ai_speed = 50000, - .n_aochan = 2, - .aobits = 12, - .ao_fifo_depth = 0, - .ao_range_table = &range_bipolar10, - .ao_unipolar = 0, - .ao_speed = 50000, - .num_p0_dio_channels = 8, - .caldac = {dac8800, dac8043}, - .has_8255 = 0, - }, - {.device_id = 50, - .isapnp_id = 0x0000, /* XXX unknown */ - .name = "at-mio-16xe-10", - .n_adchan = 16, - .adbits = 16, - .ai_fifo_depth = 512, - .alwaysdither = 1, - .gainlkup = ai_gain_14, - .ai_speed = 10000, - .n_aochan = 2, - .aobits = 16, - .ao_fifo_depth = 2048, - .ao_range_table = &range_ni_E_ao_ext, - .ao_unipolar = 1, - .ao_speed = 1000, - .num_p0_dio_channels = 8, - .caldac = {dac8800, dac8043, ad8522}, - .has_8255 = 0, - }, - {.device_id = 51, - .isapnp_id = 0x0000, /* XXX unknown */ - .name = "at-ai-16xe-10", - .n_adchan = 16, - .adbits = 16, - .ai_fifo_depth = 512, - .alwaysdither = 1, /* unknown */ - .gainlkup = ai_gain_14, - .ai_speed = 10000, - .n_aochan = 0, - .aobits = 0, - .ao_fifo_depth = 0, - .ao_unipolar = 0, - .num_p0_dio_channels = 8, - .caldac = {dac8800, dac8043, ad8522}, - .has_8255 = 0, - } + { + .name = "at-mio-16e-1", + .device_id = 44, + .isapnp_id = 0x0000, /* XXX unknown */ + .n_adchan = 16, + .ai_maxdata = 0x0fff, + .ai_fifo_depth = 8192, + .gainlkup = ai_gain_16, + .ai_speed = 800, + .n_aochan = 2, + .ao_maxdata = 0x0fff, + .ao_fifo_depth = 2048, + .ao_range_table = &range_ni_E_ao_ext, + .ao_speed = 1000, + .caldac = { mb88341 }, + }, { + .name = "at-mio-16e-2", + .device_id = 25, + .isapnp_id = 0x1900, + .n_adchan = 16, + .ai_maxdata = 0x0fff, + .ai_fifo_depth = 2048, + .gainlkup = ai_gain_16, + .ai_speed = 2000, + .n_aochan = 2, + .ao_maxdata = 0x0fff, + .ao_fifo_depth = 2048, + .ao_range_table = &range_ni_E_ao_ext, + .ao_speed = 1000, + .caldac = { mb88341 }, + }, { + .name = "at-mio-16e-10", + .device_id = 36, + .isapnp_id = 0x2400, + .n_adchan = 16, + .ai_maxdata = 0x0fff, + .ai_fifo_depth = 512, + .gainlkup = ai_gain_16, + .ai_speed = 10000, + .n_aochan = 2, + .ao_maxdata = 0x0fff, + .ao_range_table = &range_ni_E_ao_ext, + .ao_speed = 10000, + .caldac = { ad8804_debug }, + }, { + .name = "at-mio-16de-10", + .device_id = 37, + .isapnp_id = 0x2500, + .n_adchan = 16, + .ai_maxdata = 0x0fff, + .ai_fifo_depth = 512, + .gainlkup = ai_gain_16, + .ai_speed = 10000, + .n_aochan = 2, + .ao_maxdata = 0x0fff, + .ao_range_table = &range_ni_E_ao_ext, + .ao_speed = 10000, + .caldac = { ad8804_debug }, + .has_8255 = 1, + }, { + .name = "at-mio-64e-3", + .device_id = 38, + .isapnp_id = 0x2600, + .n_adchan = 64, + .ai_maxdata = 0x0fff, + .ai_fifo_depth = 2048, + .gainlkup = ai_gain_16, + .ai_speed = 2000, + .n_aochan = 2, + .ao_maxdata = 0x0fff, + .ao_fifo_depth = 2048, + .ao_range_table = &range_ni_E_ao_ext, + .ao_speed = 1000, + .caldac = { ad8804_debug }, + }, { + .name = "at-mio-16xe-50", + .device_id = 39, + .isapnp_id = 0x2700, + .n_adchan = 16, + .ai_maxdata = 0xffff, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_8, + .ai_speed = 50000, + .n_aochan = 2, + .ao_maxdata = 0x0fff, + .ao_range_table = &range_bipolar10, + .ao_speed = 50000, + .caldac = { dac8800, dac8043 }, + }, { + .name = "at-mio-16xe-10", + .device_id = 50, + .isapnp_id = 0x0000, /* XXX unknown */ + .n_adchan = 16, + .ai_maxdata = 0xffff, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_14, + .ai_speed = 10000, + .n_aochan = 2, + .ao_maxdata = 0xffff, + .ao_fifo_depth = 2048, + .ao_range_table = &range_ni_E_ao_ext, + .ao_speed = 1000, + .caldac = { dac8800, dac8043, ad8522 }, + }, { + .name = "at-ai-16xe-10", + .device_id = 51, + .isapnp_id = 0x0000, /* XXX unknown */ + .n_adchan = 16, + .ai_maxdata = 0xffff, + .ai_fifo_depth = 512, + .alwaysdither = 1, /* unknown */ + .gainlkup = ai_gain_14, + .ai_speed = 10000, + .caldac = { dac8800, dac8043, ad8522 }, + }, }; static const int ni_irqpin[] = { -1, -1, -1, 0, 1, 2, -1, 3, -1, -1, 4, 5, 6, -1, -1, 7 }; -#define interrupt_pin(a) (ni_irqpin[(a)]) - -#define IRQ_POLARITY 0 - -#define NI_E_IRQ_FLAGS 0 - -struct ni_private { - struct pnp_dev *isapnp_dev; - NI_PRIVATE_COMMON - -}; - -/* How we access registers */ - -#define ni_writel(a, b) (outl((a), (b)+dev->iobase)) -#define ni_readl(a) (inl((a)+dev->iobase)) -#define ni_writew(a, b) (outw((a), (b)+dev->iobase)) -#define ni_readw(a) (inw((a)+dev->iobase)) -#define ni_writeb(a, b) (outb((a), (b)+dev->iobase)) -#define ni_readb(a) (inb((a)+dev->iobase)) - -/* How we access windowed registers */ - -/* We automatically take advantage of STC registers that can be - * read/written directly in the I/O space of the board. The - * AT-MIO devices map the low 8 STC registers to iobase+addr*2. */ - -static void ni_atmio_win_out(struct comedi_device *dev, uint16_t data, int addr) -{ - struct ni_private *devpriv = dev->private; - unsigned long flags; - - spin_lock_irqsave(&devpriv->window_lock, flags); - if ((addr) < 8) { - ni_writew(data, addr * 2); - } else { - ni_writew(addr, Window_Address); - ni_writew(data, Window_Data); - } - spin_unlock_irqrestore(&devpriv->window_lock, flags); -} - -static uint16_t ni_atmio_win_in(struct comedi_device *dev, int addr) -{ - struct ni_private *devpriv = dev->private; - unsigned long flags; - uint16_t ret; - - spin_lock_irqsave(&devpriv->window_lock, flags); - if (addr < 8) { - ret = ni_readw(addr * 2); - } else { - ni_writew(addr, Window_Address); - ret = ni_readw(Window_Data); - } - spin_unlock_irqrestore(&devpriv->window_lock, flags); - - return ret; -} +#include "ni_mio_common.c" static struct pnp_device_id device_ids[] = { {.id = "NIC1900", .driver_data = 0}, @@ -337,8 +239,6 @@ static struct pnp_device_id device_ids[] = { MODULE_DEVICE_TABLE(pnp, device_ids); -#include "ni_mio_common.c" - static int ni_isapnp_find_board(struct pnp_dev **dev) { struct pnp_dev *isapnp_dev = NULL; @@ -353,20 +253,17 @@ static int ni_isapnp_find_board(struct pnp_dev **dev) if (isapnp_dev == NULL || isapnp_dev->card == NULL) continue; - if (pnp_device_attach(isapnp_dev) < 0) { - printk - ("ni_atmio: %s found but already active, skipping.\n", - ni_boards[i].name); + if (pnp_device_attach(isapnp_dev) < 0) continue; - } + if (pnp_activate_dev(isapnp_dev) < 0) { pnp_device_detach(isapnp_dev); return -EAGAIN; } - if (!pnp_port_valid(isapnp_dev, 0) - || !pnp_irq_valid(isapnp_dev, 0)) { + + if (!pnp_port_valid(isapnp_dev, 0) || + !pnp_irq_valid(isapnp_dev, 0)) { pnp_device_detach(isapnp_dev); - printk("ni_atmio: pnp invalid port or irq, aborting\n"); return -ENOMEM; } break; @@ -388,11 +285,13 @@ static int ni_getboardtype(struct comedi_device *dev) } if (device_id == 255) - printk(" can't find board\n"); + dev_err(dev->class_dev, "can't find board\n"); else if (device_id == 0) - printk(" EEPROM read error (?) or device not found\n"); + dev_err(dev->class_dev, + "EEPROM read error (?) or device not found\n"); else - printk(" unknown device ID %d -- contact author\n", device_id); + dev_err(dev->class_dev, + "unknown device ID %d -- contact author\n", device_id); return -1; } @@ -413,11 +312,6 @@ static int ni_atmio_attach(struct comedi_device *dev, return ret; devpriv = dev->private; - devpriv->stc_writew = &ni_atmio_win_out; - devpriv->stc_readw = &ni_atmio_win_in; - devpriv->stc_writel = &win_out2; - devpriv->stc_readl = &win_in2; - iobase = it->options[0]; irq = it->options[1]; isapnp_dev = NULL; @@ -428,10 +322,10 @@ static int ni_atmio_attach(struct comedi_device *dev, iobase = pnp_port_start(isapnp_dev, 0); irq = pnp_irq(isapnp_dev, 0); - devpriv->isapnp_dev = isapnp_dev; + comedi_set_hw_dev(dev, &isapnp_dev->dev); } - ret = comedi_request_region(dev, iobase, NI_SIZE); + ret = comedi_request_region(dev, iobase, 0x20); if (ret) return ret; @@ -443,31 +337,23 @@ static int ni_atmio_attach(struct comedi_device *dev, dev->board_ptr = ni_boards + board; boardtype = comedi_board(dev); - - printk(" %s", boardtype->name); dev->board_name = boardtype->name; /* irq stuff */ if (irq != 0) { - if (irq > 15 || ni_irqpin[irq] == -1) { - printk(" invalid irq %u\n", irq); + if (irq > 15 || ni_irqpin[irq] == -1) return -EINVAL; - } - printk(" ( irq = %u )", irq); - ret = request_irq(irq, ni_E_interrupt, NI_E_IRQ_FLAGS, - "ni_atmio", dev); - - if (ret < 0) { - printk(" irq not available\n"); + ret = request_irq(irq, ni_E_interrupt, 0, + dev->board_name, dev); + if (ret < 0) return -EINVAL; - } dev->irq = irq; } /* generic E series stuff in ni_mio_common.c */ - ret = ni_E_init(dev); + ret = ni_E_init(dev, ni_irqpin[dev->irq], 0); if (ret < 0) return ret; @@ -477,12 +363,14 @@ static int ni_atmio_attach(struct comedi_device *dev, static void ni_atmio_detach(struct comedi_device *dev) { - struct ni_private *devpriv = dev->private; + struct pnp_dev *isapnp_dev; mio_common_detach(dev); comedi_legacy_detach(dev); - if (devpriv->isapnp_dev) - pnp_device_detach(devpriv->isapnp_dev); + + isapnp_dev = dev->hw_dev ? to_pnp_dev(dev->hw_dev) : NULL; + if (isapnp_dev) + pnp_device_detach(isapnp_dev); } static struct comedi_driver ni_atmio_driver = { diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index 6ad27f50c6ec..9c08da9508f4 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -94,8 +94,6 @@ Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d) #define CLOCK_10_KHZ 0x8D25 #define CLOCK_1_KHZ 0x8E25 #define CLOCK_100_HZ 0x8F25 -/* Other miscellaneous defines */ -#define ATMIO16D_SIZE 32 /* bus address range */ struct atmio16_board_t { @@ -335,12 +333,9 @@ static int atmio16d_ai_cmd(struct comedi_device *dev, } else if (cmd->convert_arg < 655360000) { base_clock = CLOCK_100_KHZ; timer = cmd->convert_arg / 10000; - } else if (cmd->convert_arg <= 0xffffffff /* 6553600000 */) { + } else /* cmd->convert_arg < 6553600000 */ { base_clock = CLOCK_10_KHZ; timer = cmd->convert_arg / 100000; - } else if (cmd->convert_arg <= 0xffffffff /* 65536000000 */) { - base_clock = CLOCK_1_KHZ; - timer = cmd->convert_arg / 1000000; } outw(0xFF03, dev->iobase + AM9513A_COM_REG); outw(base_clock, dev->iobase + AM9513A_DATA_REG); @@ -403,12 +398,9 @@ static int atmio16d_ai_cmd(struct comedi_device *dev, } else if (cmd->scan_begin_arg < 655360000) { base_clock = CLOCK_100_KHZ; timer = cmd->scan_begin_arg / 10000; - } else if (cmd->scan_begin_arg < 0xffffffff /* 6553600000 */) { + } else /* cmd->scan_begin_arg < 6553600000 */ { base_clock = CLOCK_10_KHZ; timer = cmd->scan_begin_arg / 100000; - } else if (cmd->scan_begin_arg < 0xffffffff /* 65536000000 */) { - base_clock = CLOCK_1_KHZ; - timer = cmd->scan_begin_arg / 1000000; } outw(0xFF02, dev->iobase + AM9513A_COM_REG); outw(base_clock, dev->iobase + AM9513A_DATA_REG); @@ -630,7 +622,7 @@ static int atmio16d_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - ret = comedi_request_region(dev, it->options[0], ATMIO16D_SIZE); + ret = comedi_request_region(dev, it->options[0], 0x20); if (ret) return ret; diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 728bf7f14f7b..5e472cb7fbd7 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -18,32 +18,34 @@ */ /* -Driver: ni_daq_700 -Description: National Instruments PCMCIA DAQCard-700 DIO only -Author: Fred Brooks <nsaspook@nsaspook.com>, - based on ni_daq_dio24 by Daniel Vecino Castel <dvecino@able.es> -Devices: [National Instruments] PCMCIA DAQ-Card-700 (ni_daq_700) -Status: works -Updated: Wed, 19 Sep 2012 12:07:20 +0000 - -The daqcard-700 appears in Comedi as a digital I/O subdevice (0) with -16 channels and a analog input subdevice (1) with 16 single-ended channels. - -Digital: The channel 0 corresponds to the daqcard-700's output -port, bit 0; channel 8 corresponds to the input port, bit 0. - -Digital direction configuration: channels 0-7 output, 8-15 input (8225 device -emu as port A output, port B input, port C N/A). - -Analog: The input range is 0 to 4095 for -10 to +10 volts -IRQ is assigned but not used. - -Version 0.1 Original DIO only driver -Version 0.2 DIO and basic AI analog input support on 16 se channels - -Manuals: Register level: http://www.ni.com/pdf/manuals/340698.pdf - User Manual: http://www.ni.com/pdf/manuals/320676d.pdf -*/ + * Driver: ni_daq_700 + * Description: National Instruments PCMCIA DAQCard-700 + * Author: Fred Brooks <nsaspook@nsaspook.com>, + * based on ni_daq_dio24 by Daniel Vecino Castel <dvecino@able.es> + * Devices: [National Instruments] PCMCIA DAQ-Card-700 (ni_daq_700) + * Status: works + * Updated: Wed, 21 May 2014 12:07:20 +0000 + * + * The daqcard-700 appears in Comedi as a digital I/O subdevice (0) with + * 16 channels and a analog input subdevice (1) with 16 single-ended channels + * or 8 differential channels, and three input ranges. + * + * Digital: The channel 0 corresponds to the daqcard-700's output + * port, bit 0; channel 8 corresponds to the input port, bit 0. + * + * Digital direction configuration: channels 0-7 output, 8-15 input. + * + * Analog: The input range is 0 to 4095 with a default of -10 to +10 volts. + * Valid ranges: + * 0 for -10 to 10V bipolar + * 1 for -5 to 5V bipolar + * 2 for -2.5 to 2.5V bipolar + * + * IRQ is assigned but not used. + * + * Manuals: Register level: http://www.ni.com/pdf/manuals/340698.pdf + * User Manual: http://www.ni.com/pdf/manuals/320676d.pdf + */ #include <linux/module.h> #include <linux/delay.h> @@ -69,6 +71,17 @@ Manuals: Register level: http://www.ni.com/pdf/manuals/340698.pdf #define CDA_R2 0x0A /* RW 8bit */ #define CMO_R 0x0B /* RO 8bit */ #define TIC_R 0x06 /* WO 8bit */ +/* daqcard700 modes */ +#define CMD_R3_DIFF 0x04 /* diff mode */ + +static const struct comedi_lrange range_daq700_ai = { + 3, + { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5) + } +}; static int daq700_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, @@ -131,11 +144,22 @@ static int daq700_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - int n, chan; + int n; int d; int ret; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int aref = CR_AREF(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); + unsigned int r3_bits = 0; + + /* set channel input modes */ + if (aref == AREF_DIFF) + r3_bits |= CMD_R3_DIFF; + /* write channel mode/range */ + if (range >= 1) + range++; /* convert range to hardware value */ + outb(r3_bits | (range & 0x03), dev->iobase + CMD_R3); - chan = CR_CHAN(insn->chanspec); /* write channel to multiplexer */ /* set mask scan bit high to disable scanning */ outb(chan | 0x80, dev->iobase + CMD_R1); @@ -147,6 +171,9 @@ static int daq700_ai_rinsn(struct comedi_device *dev, /* trigger conversion with out0 L to H */ outb(0x00, dev->iobase + CMD_R2); /* enable ADC conversions */ outb(0x30, dev->iobase + CMO_R); /* mode 0 out0 L, from H */ + outb(0x00, dev->iobase + ADCLEAR_R); /* clear the ADC FIFO */ + /* read 16bit junk from FIFO to clear */ + inw(dev->iobase + ADFIFO_R); /* mode 1 out0 H, L to H, start conversion */ outb(0x32, dev->iobase + CMO_R); @@ -222,11 +249,10 @@ static int daq700_auto_attach(struct comedi_device *dev, /* DAQCard-700 ai */ s = &dev->subdevices[1]; s->type = COMEDI_SUBD_AI; - /* we support single-ended (ground) */ - s->subdev_flags = SDF_READABLE | SDF_GROUND; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; s->n_chan = 16; s->maxdata = (1 << 12) - 1; - s->range_table = &range_bipolar10; + s->range_table = &range_daq700_ai; s->insn_read = daq700_ai_rinsn; daq700_ai_config(dev, s); @@ -263,5 +289,4 @@ module_comedi_pcmcia_driver(daq700_driver, daq700_cs_driver); MODULE_AUTHOR("Fred Brooks <nsaspook@nsaspook.com>"); MODULE_DESCRIPTION( "Comedi driver for National Instruments PCMCIA DAQCard-700 DIO/AI"); -MODULE_VERSION("0.2.00"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 3e3f940fa57c..126d65cb39f2 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -72,8 +72,6 @@ #include "ni_labpc_regs.h" #include "ni_labpc_isadma.h" -#define LABPC_SIZE 0x20 /* size of ISA io region */ - enum scan_mode { MODE_SINGLE_CHAN, MODE_SINGLE_CHAN_INTERVAL, @@ -130,24 +128,26 @@ static const struct comedi_lrange range_labpc_ao = { /* functions that do inb/outb and readb/writeb so we can use * function pointers to decide which to use */ -static inline unsigned int labpc_inb(unsigned long address) +static unsigned int labpc_inb(struct comedi_device *dev, unsigned long reg) { - return inb(address); + return inb(dev->iobase + reg); } -static inline void labpc_outb(unsigned int byte, unsigned long address) +static void labpc_outb(struct comedi_device *dev, + unsigned int byte, unsigned long reg) { - outb(byte, address); + outb(byte, dev->iobase + reg); } -static inline unsigned int labpc_readb(unsigned long address) +static unsigned int labpc_readb(struct comedi_device *dev, unsigned long reg) { - return readb((void __iomem *)address); + return readb(dev->mmio + reg); } -static inline void labpc_writeb(unsigned int byte, unsigned long address) +static void labpc_writeb(struct comedi_device *dev, + unsigned int byte, unsigned long reg) { - writeb(byte, (void __iomem *)address); + writeb(byte, dev->mmio + reg); } #if IS_ENABLED(CONFIG_COMEDI_NI_LABPC_ISA) @@ -172,38 +172,29 @@ static const struct labpc_boardinfo labpc_boards[] = { #endif static void labpc_counter_load(struct comedi_device *dev, - unsigned long base_address, + unsigned long reg, unsigned int counter_number, unsigned int count, unsigned int mode) { - const struct labpc_boardinfo *board = comedi_board(dev); - - if (board->has_mmio) { - void __iomem *mmio_base = (void __iomem *)base_address; - - i8254_mm_set_mode(mmio_base, 0, counter_number, mode); - i8254_mm_write(mmio_base, 0, counter_number, count); + if (dev->mmio) { + i8254_mm_set_mode(dev->mmio + reg, 0, counter_number, mode); + i8254_mm_write(dev->mmio + reg, 0, counter_number, count); } else { - i8254_set_mode(base_address, 0, counter_number, mode); - i8254_write(base_address, 0, counter_number, count); + i8254_set_mode(dev->iobase + reg, 0, counter_number, mode); + i8254_write(dev->iobase + reg, 0, counter_number, count); } } static void labpc_counter_set_mode(struct comedi_device *dev, - unsigned long base_address, + unsigned long reg, unsigned int counter_number, unsigned int mode) { - const struct labpc_boardinfo *board = comedi_board(dev); - - if (board->has_mmio) { - void __iomem *mmio_base = (void __iomem *)base_address; - - i8254_mm_set_mode(mmio_base, 0, counter_number, mode); - } else { - i8254_set_mode(base_address, 0, counter_number, mode); - } + if (dev->mmio) + i8254_mm_set_mode(dev->mmio + reg, 0, counter_number, mode); + else + i8254_set_mode(dev->iobase + reg, 0, counter_number, mode); } static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s) @@ -213,11 +204,11 @@ static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s) spin_lock_irqsave(&dev->spinlock, flags); devpriv->cmd2 &= ~(CMD2_SWTRIG | CMD2_HWTRIG | CMD2_PRETRIG); - devpriv->write_byte(devpriv->cmd2, dev->iobase + CMD2_REG); + devpriv->write_byte(dev, devpriv->cmd2, CMD2_REG); spin_unlock_irqrestore(&dev->spinlock, flags); devpriv->cmd3 = 0; - devpriv->write_byte(devpriv->cmd3, dev->iobase + CMD3_REG); + devpriv->write_byte(dev, devpriv->cmd3, CMD3_REG); return 0; } @@ -247,7 +238,7 @@ static void labpc_ai_set_chan_and_gain(struct comedi_device *dev, devpriv->cmd1 = CMD1_MA(chan); devpriv->cmd1 |= CMD1_GAIN(range); - devpriv->write_byte(devpriv->cmd1, dev->iobase + CMD1_REG); + devpriv->write_byte(dev, devpriv->cmd1, CMD1_REG); } static void labpc_setup_cmd6_reg(struct comedi_device *dev, @@ -294,14 +285,14 @@ static void labpc_setup_cmd6_reg(struct comedi_device *dev, else devpriv->cmd6 &= ~CMD6_SCANUP; - devpriv->write_byte(devpriv->cmd6, dev->iobase + CMD6_REG); + devpriv->write_byte(dev, devpriv->cmd6, CMD6_REG); } static unsigned int labpc_read_adc_fifo(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; - unsigned int lsb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG); - unsigned int msb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG); + unsigned int lsb = devpriv->read_byte(dev, ADC_FIFO_REG); + unsigned int msb = devpriv->read_byte(dev, ADC_FIFO_REG); return (msb << 8) | lsb; } @@ -310,7 +301,7 @@ static void labpc_clear_adc_fifo(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; - devpriv->write_byte(0x1, dev->iobase + ADC_FIFO_CLEAR_REG); + devpriv->write_byte(dev, 0x1, ADC_FIFO_CLEAR_REG); labpc_read_adc_fifo(dev); } @@ -321,7 +312,7 @@ static int labpc_ai_eoc(struct comedi_device *dev, { struct labpc_private *devpriv = dev->private; - devpriv->stat1 = devpriv->read_byte(dev->iobase + STAT1_REG); + devpriv->stat1 = devpriv->read_byte(dev, STAT1_REG); if (devpriv->stat1 & STAT1_DAVAIL) return 0; return -EBUSY; @@ -353,17 +344,16 @@ static int labpc_ai_insn_read(struct comedi_device *dev, /* single-ended/differential */ if (aref == AREF_DIFF) devpriv->cmd4 |= CMD4_SEDIFF; - devpriv->write_byte(devpriv->cmd4, dev->iobase + CMD4_REG); + devpriv->write_byte(dev, devpriv->cmd4, CMD4_REG); /* initialize pacer counter to prevent any problems */ - labpc_counter_set_mode(dev, dev->iobase + COUNTER_A_BASE_REG, - 0, I8254_MODE2); + labpc_counter_set_mode(dev, COUNTER_A_BASE_REG, 0, I8254_MODE2); labpc_clear_adc_fifo(dev); for (i = 0; i < insn->n; i++) { /* trigger conversion */ - devpriv->write_byte(0x1, dev->iobase + ADC_START_CONVERT_REG); + devpriv->write_byte(dev, 0x1, ADC_START_CONVERT_REG); ret = comedi_timeout(dev, s, insn, labpc_ai_eoc, 0); if (ret) @@ -531,24 +521,26 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, static enum scan_mode labpc_ai_scan_mode(const struct comedi_cmd *cmd) { + unsigned int chan0; + unsigned int chan1; + if (cmd->chanlist_len == 1) return MODE_SINGLE_CHAN; - /* chanlist may be NULL during cmdtest. */ + /* chanlist may be NULL during cmdtest */ if (cmd->chanlist == NULL) return MODE_MULT_CHAN_UP; - if (CR_CHAN(cmd->chanlist[0]) == CR_CHAN(cmd->chanlist[1])) - return MODE_SINGLE_CHAN_INTERVAL; + chan0 = CR_CHAN(cmd->chanlist[0]); + chan1 = CR_CHAN(cmd->chanlist[1]); - if (CR_CHAN(cmd->chanlist[0]) < CR_CHAN(cmd->chanlist[1])) + if (chan0 < chan1) return MODE_MULT_CHAN_UP; - if (CR_CHAN(cmd->chanlist[0]) > CR_CHAN(cmd->chanlist[1])) + if (chan0 > chan1) return MODE_MULT_CHAN_DOWN; - pr_err("ni_labpc: bug! cannot determine AI scan mode\n"); - return 0; + return MODE_SINGLE_CHAN_INTERVAL; } static int labpc_ai_check_chanlist(struct comedi_device *dev, @@ -749,12 +741,11 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * load counter a1 with count of 3 * (pc+ manual says this is minimum allowed) using mode 0 */ - labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG, + labpc_counter_load(dev, COUNTER_A_BASE_REG, 1, 3, I8254_MODE0); } else { /* just put counter a1 in mode 0 to set its output low */ - labpc_counter_set_mode(dev, dev->iobase + COUNTER_A_BASE_REG, - 1, I8254_MODE0); + labpc_counter_set_mode(dev, COUNTER_A_BASE_REG, 1, I8254_MODE0); } /* figure out what method we will use to transfer data */ @@ -786,37 +777,35 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * list will get screwed when you switch * between scan up to scan down mode - dunno why */ udelay(1); - devpriv->write_byte(devpriv->cmd1, dev->iobase + CMD1_REG); + devpriv->write_byte(dev, devpriv->cmd1, CMD1_REG); } - devpriv->write_byte(cmd->chanlist_len, - dev->iobase + INTERVAL_COUNT_REG); + devpriv->write_byte(dev, cmd->chanlist_len, INTERVAL_COUNT_REG); /* load count */ - devpriv->write_byte(0x1, dev->iobase + INTERVAL_STROBE_REG); + devpriv->write_byte(dev, 0x1, INTERVAL_STROBE_REG); if (cmd->convert_src == TRIG_TIMER || cmd->scan_begin_src == TRIG_TIMER) { /* set up pacing */ labpc_adc_timing(dev, cmd, mode); /* load counter b0 in mode 3 */ - labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG, + labpc_counter_load(dev, COUNTER_B_BASE_REG, 0, devpriv->divisor_b0, I8254_MODE3); } /* set up conversion pacing */ if (labpc_ai_convert_period(cmd, mode)) { /* load counter a0 in mode 2 */ - labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG, + labpc_counter_load(dev, COUNTER_A_BASE_REG, 0, devpriv->divisor_a0, I8254_MODE2); } else { /* initialize pacer counter to prevent any problems */ - labpc_counter_set_mode(dev, dev->iobase + COUNTER_A_BASE_REG, - 0, I8254_MODE2); + labpc_counter_set_mode(dev, COUNTER_A_BASE_REG, 0, I8254_MODE2); } /* set up scan pacing */ if (labpc_ai_scan_period(cmd, mode)) { /* load counter b1 in mode 2 */ - labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG, + labpc_counter_load(dev, COUNTER_B_BASE_REG, 1, devpriv->divisor_b1, I8254_MODE2); } @@ -830,7 +819,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* enable fifo not empty interrupt? */ if (xfer == fifo_not_empty_transfer) devpriv->cmd3 |= CMD3_FIFOINTEN; - devpriv->write_byte(devpriv->cmd3, dev->iobase + CMD3_REG); + devpriv->write_byte(dev, devpriv->cmd3, CMD3_REG); /* setup any external triggering/pacing (cmd4 register) */ devpriv->cmd4 = 0; @@ -846,7 +835,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* single-ended/differential */ if (aref == AREF_DIFF) devpriv->cmd4 |= CMD4_SEDIFF; - devpriv->write_byte(devpriv->cmd4, dev->iobase + CMD4_REG); + devpriv->write_byte(dev, devpriv->cmd4, CMD4_REG); /* startup acquisition */ @@ -863,7 +852,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (cmd->stop_src == TRIG_EXT) devpriv->cmd2 |= (CMD2_HWTRIG | CMD2_PRETRIG); - devpriv->write_byte(devpriv->cmd2, dev->iobase + CMD2_REG); + devpriv->write_byte(dev, devpriv->cmd2, CMD2_REG); spin_unlock_irqrestore(&dev->spinlock, flags); @@ -880,7 +869,7 @@ static int labpc_drain_fifo(struct comedi_device *dev) const int timeout = 10000; unsigned int i; - devpriv->stat1 = devpriv->read_byte(dev->iobase + STAT1_REG); + devpriv->stat1 = devpriv->read_byte(dev, STAT1_REG); for (i = 0; (devpriv->stat1 & STAT1_DAVAIL) && i < timeout; i++) { @@ -892,10 +881,10 @@ static int labpc_drain_fifo(struct comedi_device *dev) } data = labpc_read_adc_fifo(dev); cfc_write_to_buffer(dev->read_subdev, data); - devpriv->stat1 = devpriv->read_byte(dev->iobase + STAT1_REG); + devpriv->stat1 = devpriv->read_byte(dev, STAT1_REG); } if (i == timeout) { - comedi_error(dev, "ai timeout, fifo never empties"); + dev_err(dev->class_dev, "ai timeout, fifo never empties\n"); async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; return -1; } @@ -926,7 +915,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d) struct comedi_cmd *cmd; if (!dev->attached) { - comedi_error(dev, "premature interrupt"); + dev_err(dev->class_dev, "premature interrupt\n"); return IRQ_HANDLED; } @@ -934,9 +923,9 @@ static irqreturn_t labpc_interrupt(int irq, void *d) cmd = &async->cmd; /* read board status */ - devpriv->stat1 = devpriv->read_byte(dev->iobase + STAT1_REG); + devpriv->stat1 = devpriv->read_byte(dev, STAT1_REG); if (board->is_labpc1200) - devpriv->stat2 = devpriv->read_byte(dev->iobase + STAT2_REG); + devpriv->stat2 = devpriv->read_byte(dev, STAT2_REG); if ((devpriv->stat1 & (STAT1_GATA0 | STAT1_CNTINT | STAT1_OVERFLOW | STAT1_OVERRUN | STAT1_DAVAIL)) == 0 @@ -947,10 +936,10 @@ static irqreturn_t labpc_interrupt(int irq, void *d) if (devpriv->stat1 & STAT1_OVERRUN) { /* clear error interrupt */ - devpriv->write_byte(0x1, dev->iobase + ADC_FIFO_CLEAR_REG); + devpriv->write_byte(dev, 0x1, ADC_FIFO_CLEAR_REG); async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; cfc_handle_events(dev, s); - comedi_error(dev, "overrun"); + dev_err(dev->class_dev, "overrun\n"); return IRQ_HANDLED; } @@ -960,17 +949,17 @@ static irqreturn_t labpc_interrupt(int irq, void *d) labpc_drain_fifo(dev); if (devpriv->stat1 & STAT1_CNTINT) { - comedi_error(dev, "handled timer interrupt?"); + dev_err(dev->class_dev, "handled timer interrupt?\n"); /* clear it */ - devpriv->write_byte(0x1, dev->iobase + TIMER_CLEAR_REG); + devpriv->write_byte(dev, 0x1, TIMER_CLEAR_REG); } if (devpriv->stat1 & STAT1_OVERFLOW) { /* clear error interrupt */ - devpriv->write_byte(0x1, dev->iobase + ADC_FIFO_CLEAR_REG); + devpriv->write_byte(dev, 0x1, ADC_FIFO_CLEAR_REG); async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; cfc_handle_events(dev, s); - comedi_error(dev, "overflow"); + dev_err(dev->class_dev, "overflow\n"); return IRQ_HANDLED; } /* handle external stop trigger */ @@ -1009,7 +998,7 @@ static int labpc_ao_insn_write(struct comedi_device *dev, * be independently enabled/disabled for its the two channels */ spin_lock_irqsave(&dev->spinlock, flags); devpriv->cmd2 &= ~CMD2_LDAC(channel); - devpriv->write_byte(devpriv->cmd2, dev->iobase + CMD2_REG); + devpriv->write_byte(dev, devpriv->cmd2, CMD2_REG); spin_unlock_irqrestore(&dev->spinlock, flags); /* set range */ @@ -1020,13 +1009,13 @@ static int labpc_ao_insn_write(struct comedi_device *dev, else devpriv->cmd6 &= ~CMD6_DACUNI(channel); /* write to register */ - devpriv->write_byte(devpriv->cmd6, dev->iobase + CMD6_REG); + devpriv->write_byte(dev, devpriv->cmd6, CMD6_REG); } /* send data */ lsb = data[0] & 0xff; msb = (data[0] >> 8) & 0xff; - devpriv->write_byte(lsb, dev->iobase + DAC_LSB_REG(channel)); - devpriv->write_byte(msb, dev->iobase + DAC_MSB_REG(channel)); + devpriv->write_byte(dev, lsb, DAC_LSB_REG(channel)); + devpriv->write_byte(dev, msb, DAC_MSB_REG(channel)); /* remember value for readback */ devpriv->ao_value[channel] = data[0]; @@ -1046,14 +1035,16 @@ static int labpc_ao_insn_read(struct comedi_device *dev, return 1; } -static int labpc_8255_mmio(int dir, int port, int data, unsigned long iobase) +static int labpc_8255_mmio(int dir, int port, int data, unsigned long arg) { + struct comedi_device *dev = (struct comedi_device *)arg; + if (dir) { - writeb(data, (void __iomem *)(iobase + port)); + writeb(data, dev->mmio + DIO_BASE_REG + port); return 0; - } else { - return readb((void __iomem *)(iobase + port)); } + + return readb(dev->mmio + DIO_BASE_REG + port); } /* lowlevel write to eeprom/dac */ @@ -1072,11 +1063,11 @@ static void labpc_serial_out(struct comedi_device *dev, unsigned int value, else devpriv->cmd5 &= ~CMD5_SDATA; udelay(1); - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); /* set clock to load bit */ devpriv->cmd5 |= CMD5_SCLK; udelay(1); - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); } } @@ -1092,14 +1083,14 @@ static unsigned int labpc_serial_in(struct comedi_device *dev) /* set serial clock */ devpriv->cmd5 |= CMD5_SCLK; udelay(1); - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); /* clear clock bit */ devpriv->cmd5 &= ~CMD5_SCLK; udelay(1); - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); /* read bits most significant bit first */ udelay(1); - devpriv->stat2 = devpriv->read_byte(dev->iobase + STAT2_REG); + devpriv->stat2 = devpriv->read_byte(dev, STAT2_REG); if (devpriv->stat2 & STAT2_PROMOUT) value |= 1 << (value_width - i); } @@ -1120,10 +1111,10 @@ static unsigned int labpc_eeprom_read(struct comedi_device *dev, /* enable read/write to eeprom */ devpriv->cmd5 &= ~CMD5_EEPROMCS; udelay(1); - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); devpriv->cmd5 |= (CMD5_EEPROMCS | CMD5_WRTPRT); udelay(1); - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); /* send read instruction */ labpc_serial_out(dev, read_instruction, write_length); @@ -1135,7 +1126,7 @@ static unsigned int labpc_eeprom_read(struct comedi_device *dev, /* disable read/write to eeprom */ devpriv->cmd5 &= ~(CMD5_EEPROMCS | CMD5_WRTPRT); udelay(1); - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); return value; } @@ -1150,10 +1141,10 @@ static unsigned int labpc_eeprom_read_status(struct comedi_device *dev) /* enable read/write to eeprom */ devpriv->cmd5 &= ~CMD5_EEPROMCS; udelay(1); - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); devpriv->cmd5 |= (CMD5_EEPROMCS | CMD5_WRTPRT); udelay(1); - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); /* send read status instruction */ labpc_serial_out(dev, read_status_instruction, write_length); @@ -1163,7 +1154,7 @@ static unsigned int labpc_eeprom_read_status(struct comedi_device *dev) /* disable read/write to eeprom */ devpriv->cmd5 &= ~(CMD5_EEPROMCS | CMD5_WRTPRT); udelay(1); - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); return value; } @@ -1186,7 +1177,7 @@ static int labpc_eeprom_write(struct comedi_device *dev, break; } if (i == timeout) { - comedi_error(dev, "eeprom write timed out"); + dev_err(dev->class_dev, "eeprom write timed out\n"); return -ETIME; } /* update software copy of eeprom */ @@ -1195,21 +1186,21 @@ static int labpc_eeprom_write(struct comedi_device *dev, /* enable read/write to eeprom */ devpriv->cmd5 &= ~CMD5_EEPROMCS; udelay(1); - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); devpriv->cmd5 |= (CMD5_EEPROMCS | CMD5_WRTPRT); udelay(1); - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); /* send write_enable instruction */ labpc_serial_out(dev, write_enable_instruction, write_length); devpriv->cmd5 &= ~CMD5_EEPROMCS; udelay(1); - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); /* send write instruction */ devpriv->cmd5 |= CMD5_EEPROMCS; udelay(1); - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); labpc_serial_out(dev, write_instruction, write_length); /* send 8 bit address to write to */ labpc_serial_out(dev, address, write_length); @@ -1217,12 +1208,12 @@ static int labpc_eeprom_write(struct comedi_device *dev, labpc_serial_out(dev, value, write_length); devpriv->cmd5 &= ~CMD5_EEPROMCS; udelay(1); - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); /* disable read/write to eeprom */ devpriv->cmd5 &= ~(CMD5_EEPROMCS | CMD5_WRTPRT); udelay(1); - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); return 0; } @@ -1240,7 +1231,7 @@ static void write_caldac(struct comedi_device *dev, unsigned int channel, /* clear caldac load bit and make sure we don't write to eeprom */ devpriv->cmd5 &= ~(CMD5_CALDACLD | CMD5_EEPROMCS | CMD5_WRTPRT); udelay(1); - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); /* write 4 bit channel */ labpc_serial_out(dev, channel, 4); @@ -1250,10 +1241,10 @@ static void write_caldac(struct comedi_device *dev, unsigned int channel, /* set and clear caldac bit to load caldac value */ devpriv->cmd5 |= CMD5_CALDACLD; udelay(1); - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); devpriv->cmd5 &= ~CMD5_CALDACLD; udelay(1); - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); } static int labpc_calib_insn_write(struct comedi_device *dev, @@ -1337,7 +1328,7 @@ int labpc_common_attach(struct comedi_device *dev, int ret; int i; - if (board->has_mmio) { + if (dev->mmio) { devpriv->read_byte = labpc_readb; devpriv->write_byte = labpc_writeb; } else { @@ -1346,13 +1337,13 @@ int labpc_common_attach(struct comedi_device *dev, } /* initialize board's command registers */ - devpriv->write_byte(devpriv->cmd1, dev->iobase + CMD1_REG); - devpriv->write_byte(devpriv->cmd2, dev->iobase + CMD2_REG); - devpriv->write_byte(devpriv->cmd3, dev->iobase + CMD3_REG); - devpriv->write_byte(devpriv->cmd4, dev->iobase + CMD4_REG); + devpriv->write_byte(dev, devpriv->cmd1, CMD1_REG); + devpriv->write_byte(dev, devpriv->cmd2, CMD2_REG); + devpriv->write_byte(dev, devpriv->cmd3, CMD3_REG); + devpriv->write_byte(dev, devpriv->cmd4, CMD4_REG); if (board->is_labpc1200) { - devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); - devpriv->write_byte(devpriv->cmd6, dev->iobase + CMD6_REG); + devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG); + devpriv->write_byte(dev, devpriv->cmd6, CMD6_REG); } if (irq) { @@ -1402,8 +1393,8 @@ int labpc_common_attach(struct comedi_device *dev, devpriv->ao_value[i] = s->maxdata / 2; lsb = devpriv->ao_value[i] & 0xff; msb = (devpriv->ao_value[i] >> 8) & 0xff; - devpriv->write_byte(lsb, dev->iobase + DAC_LSB_REG(i)); - devpriv->write_byte(msb, dev->iobase + DAC_MSB_REG(i)); + devpriv->write_byte(dev, lsb, DAC_LSB_REG(i)); + devpriv->write_byte(dev, msb, DAC_MSB_REG(i)); } } else { s->type = COMEDI_SUBD_UNUSED; @@ -1411,9 +1402,13 @@ int labpc_common_attach(struct comedi_device *dev, /* 8255 dio */ s = &dev->subdevices[2]; - ret = subdev_8255_init(dev, s, - (board->has_mmio) ? labpc_8255_mmio : NULL, - dev->iobase + DIO_BASE_REG); + if (dev->mmio) { + ret = subdev_8255_init(dev, s, labpc_8255_mmio, + (unsigned long)dev); + } else { + ret = subdev_8255_init(dev, s, NULL, + dev->iobase + DIO_BASE_REG); + } if (ret) return ret; @@ -1463,7 +1458,7 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (!devpriv) return -ENOMEM; - ret = comedi_request_region(dev, it->options[0], LABPC_SIZE); + ret = comedi_request_region(dev, it->options[0], 0x20); if (ret) return ret; diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h index 486589fa6fd8..f6e5cd15a409 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.h +++ b/drivers/staging/comedi/drivers/ni_labpc.h @@ -32,11 +32,9 @@ struct labpc_boardinfo { unsigned ai_scan_up:1; /* can auto scan up in ai channels */ unsigned has_ao:1; /* has analog outputs */ unsigned is_labpc1200:1; /* has extra regs compared to pc+ */ - unsigned has_mmio:1; /* uses memory mapped io */ }; struct labpc_private { - struct mite_struct *mite; /* for mite chip on pci-1200 */ /* number of data points left to be taken */ unsigned long long count; /* software copy of analog output values */ @@ -80,8 +78,9 @@ struct labpc_private { * function pointers so we can use inb/outb or readb/writeb as * appropriate */ - unsigned int (*read_byte) (unsigned long address); - void (*write_byte) (unsigned int byte, unsigned long address); + unsigned int (*read_byte)(struct comedi_device *, unsigned long reg); + void (*write_byte)(struct comedi_device *, + unsigned int byte, unsigned long reg); }; int labpc_common_attach(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index d9f25fdbb728..cb7d1c952cf2 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -147,7 +147,7 @@ static void handle_isa_dma(struct comedi_device *dev) enable_dma(devpriv->dma_chan); /* clear dma tc interrupt */ - devpriv->write_byte(0x1, dev->iobase + DMATC_CLEAR_REG); + devpriv->write_byte(dev, 0x1, DMATC_CLEAR_REG); } void labpc_handle_dma_status(struct comedi_device *dev) diff --git a/drivers/staging/comedi/drivers/ni_labpc_pci.c b/drivers/staging/comedi/drivers/ni_labpc_pci.c index 739597068297..65984ea0a3ee 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_pci.c +++ b/drivers/staging/comedi/drivers/ni_labpc_pci.c @@ -35,7 +35,6 @@ #include "../comedidev.h" -#include "mite.h" #include "ni_labpc.h" enum labpc_pci_boardid { @@ -49,10 +48,32 @@ static const struct labpc_boardinfo labpc_pci_boards[] = { .ai_scan_up = 1, .has_ao = 1, .is_labpc1200 = 1, - .has_mmio = 1, }, }; +/* ripped from mite.h and mite_setup2() to avoid mite dependancy */ +#define MITE_IODWBSR 0xc0 /* IO Device Window Base Size Register */ +#define WENAB (1 << 7) /* window enable */ + +static int labpc_pci_mite_init(struct pci_dev *pcidev) +{ + void __iomem *mite_base; + u32 main_phys_addr; + + /* ioremap the MITE registers (BAR 0) temporarily */ + mite_base = pci_ioremap_bar(pcidev, 0); + if (!mite_base) + return -ENOMEM; + + /* set data window to main registers (BAR 1) */ + main_phys_addr = pci_resource_start(pcidev, 1); + writel(main_phys_addr | WENAB, mite_base + MITE_IODWBSR); + + /* finished with MITE registers */ + iounmap(mite_base); + return 0; +} + static int labpc_pci_auto_attach(struct comedi_device *dev, unsigned long context) { @@ -72,29 +93,25 @@ static int labpc_pci_auto_attach(struct comedi_device *dev, if (ret) return ret; - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) + ret = labpc_pci_mite_init(pcidev); + if (ret) + return ret; + + dev->mmio = pci_ioremap_bar(pcidev, 1); + if (!dev->mmio) return -ENOMEM; - devpriv->mite = mite_alloc(pcidev); - if (!devpriv->mite) + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); + if (!devpriv) return -ENOMEM; - ret = mite_setup(devpriv->mite); - if (ret < 0) - return ret; - dev->iobase = (unsigned long)devpriv->mite->daq_io_addr; - return labpc_common_attach(dev, mite_irq(devpriv->mite), IRQF_SHARED); + return labpc_common_attach(dev, pcidev->irq, IRQF_SHARED); } static void labpc_pci_detach(struct comedi_device *dev) { - struct labpc_private *devpriv = dev->private; - - if (devpriv && devpriv->mite) { - mite_unsetup(devpriv->mite); - mite_free(devpriv->mite); - } + if (dev->mmio) + iounmap(dev->mmio); if (dev->irq) free_irq(dev->irq, dev); comedi_pci_disable(dev); diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 7ffdcc07ef92..297c95d2e0a3 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -194,113 +194,6 @@ static const struct comedi_lrange *const ni_range_lkup[] = { [ai_gain_6143] = &range_bipolar5 }; -static int ni_dio_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int ni_dio_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int ni_cdio_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_cmd *cmd); -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); -static void handle_cdio_interrupt(struct comedi_device *dev); -static int ni_cdo_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int trignum); - -static int ni_serial_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int ni_serial_hw_readwrite8(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned char data_out, - unsigned char *data_in); -static int ni_serial_sw_readwrite8(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned char data_out, - unsigned char *data_in); - -static int ni_calib_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int ni_calib_insn_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); - -static int ni_eeprom_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int ni_m_series_eeprom_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data); - -static int ni_pfi_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int ni_pfi_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static unsigned ni_old_get_pfi_routing(struct comedi_device *dev, - unsigned chan); - -static void ni_rtsi_init(struct comedi_device *dev); -static int ni_rtsi_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int ni_rtsi_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); - -static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s); -static int ni_read_eeprom(struct comedi_device *dev, int addr); - -#ifndef PCIDMA -static void ni_handle_fifo_half_full(struct comedi_device *dev); -static int ni_ao_fifo_half_empty(struct comedi_device *dev, - struct comedi_subdevice *s); -#endif -static void ni_handle_fifo_dregs(struct comedi_device *dev); -static int ni_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int trignum); -static void ni_load_channelgain_list(struct comedi_device *dev, - unsigned int n_chan, unsigned int *list); -static void shutdown_ai_command(struct comedi_device *dev); - -static int ni_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int trignum); - -static int ni_8255_callback(int dir, int port, int data, unsigned long arg); - -#ifdef PCIDMA -static int ni_gpct_cmd(struct comedi_device *dev, struct comedi_subdevice *s); -static int ni_gpct_cancel(struct comedi_device *dev, struct comedi_subdevice *s); -#endif -static void handle_gpct_interrupt(struct comedi_device *dev, - unsigned short counter_index); - -static int init_cs5529(struct comedi_device *dev); -static int cs5529_do_conversion(struct comedi_device *dev, - unsigned short *data); -static int cs5529_ai_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static void cs5529_config_write(struct comedi_device *dev, unsigned int value, - unsigned int reg_select_bits); - -static int ni_m_series_pwm_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int ni_6143_pwm_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); - -static int ni_set_master_clock(struct comedi_device *dev, unsigned source, - unsigned period_ns); -static void ack_a_interrupt(struct comedi_device *dev, unsigned short a_status); -static void ack_b_interrupt(struct comedi_device *dev, unsigned short b_status); - enum aimodes { AIMODE_NONE = 0, AIMODE_HALF_FULL = 1, @@ -330,10 +223,8 @@ static inline unsigned NI_GPCT_SUBDEV(unsigned counter_index) switch (counter_index) { case 0: return NI_GPCT0_SUBDEV; - break; case 1: return NI_GPCT1_SUBDEV; - break; default: break; } @@ -353,12 +244,394 @@ enum timebase_nanoseconds { static const int num_adc_stages_611x = 3; -static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, - unsigned ai_mite_status); -static void handle_b_interrupt(struct comedi_device *dev, unsigned short status, - unsigned ao_mite_status); -static void get_last_sample_611x(struct comedi_device *dev); -static void get_last_sample_6143(struct comedi_device *dev); +static void ni_writel(struct comedi_device *dev, uint32_t data, int reg) +{ + if (dev->mmio) + writel(data, dev->mmio + reg); + + outl(data, dev->iobase + reg); +} + +static void ni_writew(struct comedi_device *dev, uint16_t data, int reg) +{ + if (dev->mmio) + writew(data, dev->mmio + reg); + + outw(data, dev->iobase + reg); +} + +static void ni_writeb(struct comedi_device *dev, uint8_t data, int reg) +{ + if (dev->mmio) + writeb(data, dev->mmio + reg); + + outb(data, dev->iobase + reg); +} + +static uint32_t ni_readl(struct comedi_device *dev, int reg) +{ + if (dev->mmio) + return readl(dev->mmio + reg); + + return inl(dev->iobase + reg); +} + +static uint16_t ni_readw(struct comedi_device *dev, int reg) +{ + if (dev->mmio) + return readw(dev->mmio + reg); + + return inw(dev->iobase + reg); +} + +static uint8_t ni_readb(struct comedi_device *dev, int reg) +{ + if (dev->mmio) + return readb(dev->mmio + reg); + + return inb(dev->iobase + reg); +} + +/* + * We automatically take advantage of STC registers that can be + * read/written directly in the I/O space of the board. + * + * The AT-MIO and DAQCard devices map the low 8 STC registers to + * iobase+reg*2. + * + * Most PCIMIO devices also map the low 8 STC registers but the + * 611x devices map the read registers to iobase+(addr-1)*2. + * For now non-windowed STC access is disabled if a PCIMIO device + * is detected (devpriv->mite has been initialized). + * + * The M series devices do not used windowed registers for the + * STC registers. The functions below handle the mapping of the + * windowed STC registers to the m series register offsets. + */ + +static void m_series_stc_writel(struct comedi_device *dev, + uint32_t data, int reg) +{ + unsigned offset; + + 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", + __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; + break; + case RTSI_Trig_Direction_Register: + offset = M_Offset_RTSI_Trig_Direction; + 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", + __func__, reg); + return; + } + ni_writew(dev, data, offset); +} + +static uint32_t m_series_stc_readl(struct comedi_device *dev, int reg) +{ + unsigned offset; + + 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", + __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; + default: + dev_warn(dev->class_dev, + "%s: bug! unhandled register=0x%x in switch\n", + __func__, reg); + return 0; + } + return ni_readw(dev, offset); +} + +static void ni_stc_writew(struct comedi_device *dev, uint16_t data, int reg) +{ + struct ni_private *devpriv = dev->private; + unsigned long flags; + + if (devpriv->is_m_series) { + m_series_stc_writew(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); + } + spin_unlock_irqrestore(&devpriv->window_lock, flags); + } +} + +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); + } else { + ni_stc_writew(dev, data >> 16, reg); + ni_stc_writew(dev, data & 0xffff, reg + 1); + } +} + +static uint16_t ni_stc_readw(struct comedi_device *dev, int reg) +{ + struct ni_private *devpriv = dev->private; + unsigned long flags; + uint16_t val; + + if (devpriv->is_m_series) { + val = m_series_stc_readw(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); + } + spin_unlock_irqrestore(&devpriv->window_lock, flags); + } + return val; +} + +static uint32_t ni_stc_readl(struct comedi_device *dev, int reg) +{ + struct ni_private *devpriv = dev->private; + uint32_t val; + + if (devpriv->is_m_series) { + val = m_series_stc_readl(dev, reg); + } else { + val = ni_stc_readw(dev, reg) << 16; + val |= ni_stc_readw(dev, reg + 1); + } + return val; +} static inline void ni_set_bitfield(struct comedi_device *dev, int reg, unsigned bit_mask, unsigned bit_values) @@ -371,34 +644,34 @@ static inline void ni_set_bitfield(struct comedi_device *dev, int reg, case Interrupt_A_Enable_Register: devpriv->int_a_enable_reg &= ~bit_mask; devpriv->int_a_enable_reg |= bit_values & bit_mask; - devpriv->stc_writew(dev, devpriv->int_a_enable_reg, - Interrupt_A_Enable_Register); + ni_stc_writew(dev, devpriv->int_a_enable_reg, + Interrupt_A_Enable_Register); break; case Interrupt_B_Enable_Register: devpriv->int_b_enable_reg &= ~bit_mask; devpriv->int_b_enable_reg |= bit_values & bit_mask; - devpriv->stc_writew(dev, devpriv->int_b_enable_reg, - Interrupt_B_Enable_Register); + ni_stc_writew(dev, devpriv->int_b_enable_reg, + Interrupt_B_Enable_Register); break; case IO_Bidirection_Pin_Register: devpriv->io_bidirection_pin_reg &= ~bit_mask; devpriv->io_bidirection_pin_reg |= bit_values & bit_mask; - devpriv->stc_writew(dev, devpriv->io_bidirection_pin_reg, - IO_Bidirection_Pin_Register); + ni_stc_writew(dev, devpriv->io_bidirection_pin_reg, + IO_Bidirection_Pin_Register); break; case AI_AO_Select: devpriv->ai_ao_select_reg &= ~bit_mask; devpriv->ai_ao_select_reg |= bit_values & bit_mask; - ni_writeb(devpriv->ai_ao_select_reg, AI_AO_Select); + ni_writeb(dev, devpriv->ai_ao_select_reg, AI_AO_Select); break; case G0_G1_Select: devpriv->g0_g1_select_reg &= ~bit_mask; devpriv->g0_g1_select_reg |= bit_values & bit_mask; - ni_writeb(devpriv->g0_g1_select_reg, G0_G1_Select); + ni_writeb(dev, devpriv->g0_g1_select_reg, G0_G1_Select); break; default: - printk("Warning %s() called with invalid register\n", __func__); - printk("reg is %d\n", reg); + dev_err(dev->class_dev, + "%s called with invalid register %d\n", __func__, reg); break; } mmiowb(); @@ -406,8 +679,6 @@ static inline void ni_set_bitfield(struct comedi_device *dev, int reg, } #ifdef PCIDMA -static int ni_ai_drain_dma(struct comedi_device *dev); - /* DMA channel setup */ /* negative channel means no channel */ @@ -472,7 +743,7 @@ static inline void ni_set_cdo_dma_channel(struct comedi_device *dev, (ni_stc_dma_channel_select_bitfield(mite_channel) << CDO_DMA_Select_Shift) & CDO_DMA_Select_Mask; } - ni_writeb(devpriv->cdio_dma_select_reg, M_Offset_CDIO_DMA_Select); + ni_writeb(dev, devpriv->cdio_dma_select_reg, M_Offset_CDIO_DMA_Select); mmiowb(); spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags); } @@ -488,8 +759,8 @@ static int ni_request_ai_mite_channel(struct comedi_device *dev) mite_request_channel(devpriv->mite, devpriv->ai_mite_ring); if (devpriv->ai_mite_chan == NULL) { spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); - comedi_error(dev, - "failed to reserve mite dma channel for analog input."); + dev_err(dev->class_dev, + "failed to reserve mite dma channel for analog input\n"); return -EBUSY; } devpriv->ai_mite_chan->dir = COMEDI_INPUT; @@ -509,8 +780,8 @@ static int ni_request_ao_mite_channel(struct comedi_device *dev) mite_request_channel(devpriv->mite, devpriv->ao_mite_ring); if (devpriv->ao_mite_chan == NULL) { spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); - comedi_error(dev, - "failed to reserve mite dma channel for analog outut."); + dev_err(dev->class_dev, + "failed to reserve mite dma channel for analog outut\n"); return -EBUSY; } devpriv->ao_mite_chan->dir = COMEDI_OUTPUT; @@ -535,8 +806,8 @@ static int ni_request_gpct_mite_channel(struct comedi_device *dev, devpriv->gpct_mite_ring[gpct_index]); if (mite_chan == NULL) { spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); - comedi_error(dev, - "failed to reserve mite dma channel for counter."); + dev_err(dev->class_dev, + "failed to reserve mite dma channel for counter\n"); return -EBUSY; } mite_chan->dir = direction; @@ -561,8 +832,8 @@ static int ni_request_cdo_mite_channel(struct comedi_device *dev) mite_request_channel(devpriv->mite, devpriv->cdo_mite_ring); if (devpriv->cdo_mite_chan == NULL) { spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); - comedi_error(dev, - "failed to reserve mite dma channel for correlated digital outut."); + dev_err(dev->class_dev, + "failed to reserve mite dma channel for correlated digital output\n"); return -EBUSY; } devpriv->cdo_mite_chan->dir = COMEDI_OUTPUT; @@ -643,100 +914,71 @@ static void ni_release_cdo_mite_channel(struct comedi_device *dev) #endif /* PCIDMA */ } -/* e-series boards use the second irq signals to generate dma requests for their counters */ #ifdef PCIDMA static void ni_e_series_enable_second_irq(struct comedi_device *dev, unsigned gpct_index, short enable) { - const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; + uint16_t val = 0; + int reg; - if (board->reg_type & ni_reg_m_series_mask) + if (devpriv->is_m_series || gpct_index > 1) return; - switch (gpct_index) { - case 0: - if (enable) { - devpriv->stc_writew(dev, G0_Gate_Second_Irq_Enable, - Second_IRQ_A_Enable_Register); - } else { - devpriv->stc_writew(dev, 0, - Second_IRQ_A_Enable_Register); - } - break; - case 1: - if (enable) { - devpriv->stc_writew(dev, G1_Gate_Second_Irq_Enable, - Second_IRQ_B_Enable_Register); - } else { - devpriv->stc_writew(dev, 0, - Second_IRQ_B_Enable_Register); - } - break; - default: - BUG(); - break; + + /* + * e-series boards use the second irq signals to generate + * dma requests for their counters + */ + if (gpct_index == 0) { + reg = Second_IRQ_A_Enable_Register; + if (enable) + val = G0_Gate_Second_Irq_Enable; + } else { + reg = Second_IRQ_B_Enable_Register; + if (enable) + val = G1_Gate_Second_Irq_Enable; } + ni_stc_writew(dev, val, reg); } #endif /* PCIDMA */ static void ni_clear_ai_fifo(struct comedi_device *dev) { - const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; static const int timeout = 10000; int i; - if (board->reg_type == ni_reg_6143) { + if (devpriv->is_6143) { /* Flush the 6143 data FIFO */ - ni_writel(0x10, AIFIFO_Control_6143); /* Flush fifo */ - ni_writel(0x00, AIFIFO_Control_6143); /* Flush fifo */ + ni_writel(dev, 0x10, AIFIFO_Control_6143); + ni_writel(dev, 0x00, AIFIFO_Control_6143); /* Wait for complete */ for (i = 0; i < timeout; i++) { - if (!(ni_readl(AIFIFO_Status_6143) & 0x10)) + if (!(ni_readl(dev, AIFIFO_Status_6143) & 0x10)) break; udelay(1); } - if (i == timeout) { - comedi_error(dev, "FIFO flush timeout."); - } + if (i == timeout) + dev_err(dev->class_dev, "FIFO flush timeout\n"); } else { - devpriv->stc_writew(dev, 1, ADC_FIFO_Clear); - if (board->reg_type == ni_reg_625x) { - ni_writeb(0, M_Offset_Static_AI_Control(0)); - ni_writeb(1, M_Offset_Static_AI_Control(0)); + ni_stc_writew(dev, 1, ADC_FIFO_Clear); + if (devpriv->is_625x) { + ni_writeb(dev, 0, M_Offset_Static_AI_Control(0)); + ni_writeb(dev, 1, M_Offset_Static_AI_Control(0)); #if 0 /* the NI example code does 3 convert pulses for 625x boards, but that appears to be wrong in practice. */ - devpriv->stc_writew(dev, AI_CONVERT_Pulse, - AI_Command_1_Register); - devpriv->stc_writew(dev, AI_CONVERT_Pulse, - AI_Command_1_Register); - devpriv->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, AI_CONVERT_Pulse, + AI_Command_1_Register); #endif } } } -static void win_out2(struct comedi_device *dev, uint32_t data, int reg) -{ - struct ni_private *devpriv = dev->private; - - devpriv->stc_writew(dev, data >> 16, reg); - devpriv->stc_writew(dev, data & 0xffff, reg + 1); -} - -static uint32_t win_in2(struct comedi_device *dev, int reg) -{ - struct ni_private *devpriv = dev->private; - uint32_t bits; - - bits = devpriv->stc_readw(dev, reg) << 16; - bits |= devpriv->stc_readw(dev, reg + 1); - return bits; -} - -#define ao_win_out(data, addr) ni_ao_win_outw(dev, data, addr) static inline void ni_ao_win_outw(struct comedi_device *dev, uint16_t data, int addr) { @@ -744,8 +986,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(addr, AO_Window_Address_611x); - ni_writew(data, AO_Window_Data_611x); + ni_writew(dev, addr, AO_Window_Address_611x); + ni_writew(dev, data, AO_Window_Data_611x); spin_unlock_irqrestore(&devpriv->window_lock, flags); } @@ -756,8 +998,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(addr, AO_Window_Address_611x); - ni_writel(data, AO_Window_Data_611x); + ni_writew(dev, addr, AO_Window_Address_611x); + ni_writel(dev, data, AO_Window_Data_611x); spin_unlock_irqrestore(&devpriv->window_lock, flags); } @@ -768,8 +1010,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(addr, AO_Window_Address_611x); - data = ni_readw(AO_Window_Data_611x); + ni_writew(dev, addr, AO_Window_Address_611x); + data = ni_readw(dev, AO_Window_Data_611x); spin_unlock_irqrestore(&devpriv->window_lock, flags); return data; } @@ -796,83 +1038,58 @@ static inline void ni_set_bits(struct comedi_device *dev, int reg, ni_set_bitfield(dev, reg, bits, bit_values); } -static irqreturn_t ni_E_interrupt(int irq, void *d) +#ifdef PCIDMA +static void ni_sync_ai_dma(struct comedi_device *dev) { - struct comedi_device *dev = d; struct ni_private *devpriv = dev->private; - unsigned short a_status; - unsigned short b_status; - unsigned int ai_mite_status = 0; - unsigned int ao_mite_status = 0; + struct comedi_subdevice *s = dev->read_subdev; unsigned long flags; -#ifdef PCIDMA - struct mite_struct *mite = devpriv->mite; -#endif - - if (!dev->attached) - return IRQ_NONE; - smp_mb(); /* make sure dev->attached is checked before handler does anything else. */ - - /* lock to avoid race with comedi_poll */ - spin_lock_irqsave(&dev->spinlock, flags); - a_status = devpriv->stc_readw(dev, AI_Status_1_Register); - b_status = devpriv->stc_readw(dev, AO_Status_1_Register); -#ifdef PCIDMA - if (mite) { - unsigned long flags_too; - - spin_lock_irqsave(&devpriv->mite_channel_lock, flags_too); - if (devpriv->ai_mite_chan) { - ai_mite_status = mite_get_status(devpriv->ai_mite_chan); - if (ai_mite_status & CHSR_LINKC) - writel(CHOR_CLRLC, - devpriv->mite->mite_io_addr + - MITE_CHOR(devpriv-> - ai_mite_chan->channel)); - } - if (devpriv->ao_mite_chan) { - ao_mite_status = mite_get_status(devpriv->ao_mite_chan); - if (ao_mite_status & CHSR_LINKC) - writel(CHOR_CLRLC, - mite->mite_io_addr + - MITE_CHOR(devpriv-> - ao_mite_chan->channel)); - } - spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags_too); - } -#endif - ack_a_interrupt(dev, a_status); - ack_b_interrupt(dev, b_status); - if ((a_status & Interrupt_A_St) || (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)) - handle_b_interrupt(dev, b_status, ao_mite_status); - handle_gpct_interrupt(dev, 0); - handle_gpct_interrupt(dev, 1); - handle_cdio_interrupt(dev); - spin_unlock_irqrestore(&dev->spinlock, flags); - return IRQ_HANDLED; + spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + if (devpriv->ai_mite_chan) + mite_sync_input_dma(devpriv->ai_mite_chan, s); + spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); } -#ifdef PCIDMA -static void ni_sync_ai_dma(struct comedi_device *dev) +static int ni_ai_drain_dma(struct comedi_device *dev) { struct ni_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; + int i; + static const int timeout = 10000; unsigned long flags; + int retval = 0; spin_lock_irqsave(&devpriv->mite_channel_lock, flags); - if (devpriv->ai_mite_chan) - mite_sync_input_dma(devpriv->ai_mite_chan, s); + if (devpriv->ai_mite_chan) { + for (i = 0; i < timeout; i++) { + if ((ni_stc_readw(dev, AI_Status_1_Register) & + AI_FIFO_Empty_St) + && mite_bytes_in_transit(devpriv->ai_mite_chan) == + 0) + break; + udelay(5); + } + if (i == timeout) { + dev_err(dev->class_dev, "%s timed out\n", __func__); + 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)); + retval = -1; + } + } spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); + + ni_sync_ai_dma(dev); + + return retval; } static void mite_handle_b_linkc(struct mite_struct *mite, struct comedi_device *dev) { struct ni_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV]; + struct comedi_subdevice *s = dev->write_subdev; unsigned long flags; spin_lock_irqsave(&devpriv->mite_channel_lock, flags); @@ -883,13 +1100,13 @@ static void mite_handle_b_linkc(struct mite_struct *mite, static int ni_ao_wait_for_dma_load(struct comedi_device *dev) { - struct ni_private *devpriv = dev->private; static const int timeout = 10000; int i; + for (i = 0; i < timeout; i++) { unsigned short b_status; - b_status = devpriv->stc_readw(dev, AO_Status_1_Register); + b_status = ni_stc_readw(dev, AO_Status_1_Register); if (b_status & AO_FIFO_Half_Full_St) break; /* if we poll too often, the pci bus activity seems @@ -897,247 +1114,19 @@ static int ni_ao_wait_for_dma_load(struct comedi_device *dev) udelay(10); } if (i == timeout) { - comedi_error(dev, "timed out waiting for dma load"); + dev_err(dev->class_dev, "timed out waiting for dma load\n"); return -EPIPE; } return 0; } - #endif /* PCIDMA */ -static void ni_handle_eos(struct comedi_device *dev, struct comedi_subdevice *s) -{ - struct ni_private *devpriv = dev->private; - - if (devpriv->aimode == AIMODE_SCAN) { -#ifdef PCIDMA - static const int timeout = 10; - int i; - - for (i = 0; i < timeout; i++) { - ni_sync_ai_dma(dev); - if ((s->async->events & COMEDI_CB_EOS)) - break; - udelay(1); - } -#else - ni_handle_fifo_dregs(dev); - 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)) - shutdown_ai_command(dev); -} - -static void shutdown_ai_command(struct comedi_device *dev) -{ - struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; - -#ifdef PCIDMA - ni_ai_drain_dma(dev); -#endif - ni_handle_fifo_dregs(dev); - get_last_sample_611x(dev); - get_last_sample_6143(dev); - - s->async->events |= COMEDI_CB_EOA; -} - -static void handle_gpct_interrupt(struct comedi_device *dev, - unsigned short counter_index) -{ -#ifdef PCIDMA - struct ni_private *devpriv = dev->private; - struct comedi_subdevice *s; - - s = &dev->subdevices[NI_GPCT_SUBDEV(counter_index)]; - - ni_tio_handle_interrupt(&devpriv->counter_dev->counters[counter_index], - s); - cfc_handle_events(dev, s); -#endif -} - -static void ack_a_interrupt(struct comedi_device *dev, unsigned short a_status) -{ - struct ni_private *devpriv = dev->private; - 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 (ack) - devpriv->stc_writew(dev, ack, Interrupt_A_Ack_Register); -} - -static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, - unsigned ai_mite_status) -{ - struct ni_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; - - /* 67xx boards don't have ai subdevice, but their gpct0 might generate an a interrupt */ - if (s->type == COMEDI_SUBD_UNUSED) - return; - -#ifdef PCIDMA - if (ai_mite_status & CHSR_LINKC) - ni_sync_ai_dma(dev); - - if (ai_mite_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY | - CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR | - CHSR_SABORT | CHSR_XFERR | CHSR_LxERR_mask)) { - printk - ("unknown mite interrupt, ack! (ai_mite_status=%08x)\n", - ai_mite_status); - s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; - /* disable_irq(dev->irq); */ - } -#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 == 0xffff) { - printk - ("ni_mio_common: a_status=0xffff. Card removed?\n"); - /* we probably aren't even running a command now, - * so it's a good idea to be careful. */ - if (comedi_is_subdevice_running(s)) { - s->async->events |= - COMEDI_CB_ERROR | COMEDI_CB_EOA; - cfc_handle_events(dev, s); - } - return; - } - if (status & (AI_Overrun_St | AI_Overflow_St | - AI_SC_TC_Error_St)) { - printk("ni_mio_common: 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)) - s->async->events |= COMEDI_CB_OVERFLOW; - - cfc_handle_events(dev, s); - return; - } - if (status & AI_SC_TC_St) { - if (!devpriv->ai_continuous) - shutdown_ai_command(dev); - } - } -#ifndef PCIDMA - if (status & AI_FIFO_Half_Full_St) { - 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 ((devpriv->stc_readw(dev, - AI_Status_1_Register) & - AI_FIFO_Half_Full_St) == 0) - break; - } - } -#endif /* !PCIDMA */ - - if ((status & AI_STOP_St)) - ni_handle_eos(dev, s); - - cfc_handle_events(dev, s); -} - -static void ack_b_interrupt(struct comedi_device *dev, unsigned short b_status) -{ - struct ni_private *devpriv = dev->private; - 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 (ack) - devpriv->stc_writew(dev, ack, Interrupt_B_Ack_Register); -} - -static void handle_b_interrupt(struct comedi_device *dev, - unsigned short b_status, unsigned ao_mite_status) -{ - struct ni_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV]; - /* unsigned short ack=0; */ - -#ifdef PCIDMA - /* Currently, mite.c requires us to handle LINKC */ - if (ao_mite_status & CHSR_LINKC) - mite_handle_b_linkc(devpriv->mite, dev); - - if (ao_mite_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY | - CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR | - CHSR_SABORT | CHSR_XFERR | CHSR_LxERR_mask)) { - printk - ("unknown mite interrupt, ack! (ao_mite_status=%08x)\n", - ao_mite_status); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; - } -#endif - - if (b_status == 0xffff) - return; - if (b_status & AO_Overrun_St) { - printk - ("ni_mio_common: AO FIFO underrun status=0x%04x status2=0x%04x\n", - b_status, devpriv->stc_readw(dev, AO_Status_2_Register)); - s->async->events |= COMEDI_CB_OVERFLOW; - } - - if (b_status & AO_BC_TC_St) - s->async->events |= COMEDI_CB_EOA; - -#ifndef PCIDMA - if (b_status & AO_FIFO_Request_St) { - int ret; - - ret = ni_ao_fifo_half_empty(dev, s); - if (!ret) { - printk("ni_mio_common: AO buffer underrun\n"); - ni_set_bits(dev, Interrupt_B_Enable_Register, - AO_FIFO_Interrupt_Enable | - AO_Error_Interrupt_Enable, 0); - s->async->events |= COMEDI_CB_OVERFLOW; - } - } -#endif - - cfc_handle_events(dev, s); -} #ifndef PCIDMA static void ni_ao_fifo_load(struct comedi_device *dev, struct comedi_subdevice *s, int n) { - const struct ni_board_struct *board = comedi_board(dev); + struct ni_private *devpriv = dev->private; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; int chan; @@ -1155,10 +1144,10 @@ static void ni_ao_fifo_load(struct comedi_device *dev, range = CR_RANGE(cmd->chanlist[chan]); - if (board->reg_type & ni_reg_6xxx_mask) { + if (devpriv->is_6xxx) { packed_data = d & 0xffff; /* 6711 only has 16 bit wide ao fifo */ - if (board->reg_type != ni_reg_6711) { + if (!devpriv->is_6711) { err &= comedi_buf_get(s, &d); if (err == 0) break; @@ -1166,9 +1155,9 @@ static void ni_ao_fifo_load(struct comedi_device *dev, i++; packed_data |= (d << 16) & 0xffff0000; } - ni_writel(packed_data, DAC_FIFO_Data_611x); + ni_writel(dev, packed_data, DAC_FIFO_Data_611x); } else { - ni_writew(d, DAC_FIFO_Data); + ni_writew(dev, d, DAC_FIFO_Data); } chan++; chan %= cmd->chanlist_len; @@ -1225,8 +1214,8 @@ static int ni_ao_prep_fifo(struct comedi_device *dev, int n; /* reset fifo */ - devpriv->stc_writew(dev, 1, DAC_FIFO_Clear); - if (board->reg_type & ni_reg_6xxx_mask) + ni_stc_writew(dev, 1, DAC_FIFO_Clear); + if (devpriv->is_6xxx) ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x); /* load some data */ @@ -1246,17 +1235,16 @@ static int ni_ao_prep_fifo(struct comedi_device *dev, static void ni_ai_fifo_read(struct comedi_device *dev, struct comedi_subdevice *s, int n) { - const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; struct comedi_async *async = s->async; int i; - if (board->reg_type == ni_reg_611x) { + if (devpriv->is_611x) { unsigned short data[2]; u32 dl; for (i = 0; i < n / 2; i++) { - dl = ni_readl(ADC_FIFO_Data_611x); + dl = ni_readl(dev, ADC_FIFO_Data_611x); /* This may get the hi/lo data in the wrong order */ data[0] = (dl >> 16) & 0xffff; data[1] = dl & 0xffff; @@ -1264,17 +1252,17 @@ 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(ADC_FIFO_Data_611x); + dl = ni_readl(dev, ADC_FIFO_Data_611x); data[0] = dl & 0xffff; cfc_write_to_buffer(s, data[0]); } - } else if (board->reg_type == ni_reg_6143) { + } else if (devpriv->is_6143) { unsigned short data[2]; u32 dl; /* This just reads the FIFO assuming the data is present, no checks on the FIFO status are performed */ for (i = 0; i < n / 2; i++) { - dl = ni_readl(AIFIFO_Data_6143); + dl = ni_readl(dev, AIFIFO_Data_6143); data[0] = (dl >> 16) & 0xffff; data[1] = dl & 0xffff; @@ -1282,21 +1270,23 @@ static void ni_ai_fifo_read(struct comedi_device *dev, } if (n % 2) { /* Assume there is a single sample stuck in the FIFO */ - ni_writel(0x01, AIFIFO_Control_6143); /* Get stranded sample into FIFO */ - dl = ni_readl(AIFIFO_Data_6143); + /* Get stranded sample into FIFO */ + ni_writel(dev, 0x01, AIFIFO_Control_6143); + dl = ni_readl(dev, AIFIFO_Data_6143); data[0] = (dl >> 16) & 0xffff; cfc_write_to_buffer(s, data[0]); } } else { if (n > sizeof(devpriv->ai_fifo_buffer) / sizeof(devpriv->ai_fifo_buffer[0])) { - comedi_error(dev, "bug! ai_fifo_buffer too small"); + dev_err(dev->class_dev, + "bug! ai_fifo_buffer too small\n"); async->events |= COMEDI_CB_ERROR; return; } for (i = 0; i < n; i++) { devpriv->ai_fifo_buffer[i] = - ni_readw(ADC_FIFO_Data_Register); + ni_readw(dev, ADC_FIFO_Data_Register); } cfc_write_array_to_buffer(s, devpriv->ai_fifo_buffer, n * @@ -1307,7 +1297,7 @@ static void ni_ai_fifo_read(struct comedi_device *dev, static void ni_handle_fifo_half_full(struct comedi_device *dev) { const struct ni_board_struct *board = comedi_board(dev); - struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; + struct comedi_subdevice *s = dev->read_subdev; int n; n = board->ai_fifo_depth / 2; @@ -1316,70 +1306,32 @@ static void ni_handle_fifo_half_full(struct comedi_device *dev) } #endif -#ifdef PCIDMA -static int ni_ai_drain_dma(struct comedi_device *dev) -{ - struct ni_private *devpriv = dev->private; - int i; - static const int timeout = 10000; - unsigned long flags; - int retval = 0; - - spin_lock_irqsave(&devpriv->mite_channel_lock, flags); - if (devpriv->ai_mite_chan) { - for (i = 0; i < timeout; i++) { - if ((devpriv->stc_readw(dev, - AI_Status_1_Register) & - AI_FIFO_Empty_St) - && mite_bytes_in_transit(devpriv->ai_mite_chan) == - 0) - break; - udelay(5); - } - if (i == timeout) { - printk("ni_mio_common: wait for dma drain timed out\n"); - printk - ("mite_bytes_in_transit=%i, AI_Status1_Register=0x%x\n", - mite_bytes_in_transit(devpriv->ai_mite_chan), - devpriv->stc_readw(dev, AI_Status_1_Register)); - retval = -1; - } - } - spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); - - ni_sync_ai_dma(dev); - - return retval; -} -#endif /* Empties the AI fifo */ static void ni_handle_fifo_dregs(struct comedi_device *dev) { - const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; + struct comedi_subdevice *s = dev->read_subdev; unsigned short data[2]; u32 dl; unsigned short fifo_empty; int i; - if (board->reg_type == ni_reg_611x) { - while ((devpriv->stc_readw(dev, - AI_Status_1_Register) & + if (devpriv->is_611x) { + while ((ni_stc_readw(dev, AI_Status_1_Register) & AI_FIFO_Empty_St) == 0) { - dl = ni_readl(ADC_FIFO_Data_611x); + dl = ni_readl(dev, ADC_FIFO_Data_611x); /* This may get the hi/lo data in the wrong order */ data[0] = (dl >> 16); data[1] = (dl & 0xffff); cfc_write_array_to_buffer(s, data, sizeof(data)); } - } else if (board->reg_type == ni_reg_6143) { + } else if (devpriv->is_6143) { i = 0; - while (ni_readl(AIFIFO_Status_6143) & 0x04) { - dl = ni_readl(AIFIFO_Data_6143); + while (ni_readl(dev, AIFIFO_Status_6143) & 0x04) { + dl = ni_readl(dev, AIFIFO_Data_6143); /* This may get the hi/lo data in the wrong order */ data[0] = (dl >> 16); @@ -1388,30 +1340,29 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev) i += 2; } /* Check if stranded sample is present */ - if (ni_readl(AIFIFO_Status_6143) & 0x01) { - ni_writel(0x01, AIFIFO_Control_6143); /* Get stranded sample into FIFO */ - dl = ni_readl(AIFIFO_Data_6143); + if (ni_readl(dev, AIFIFO_Status_6143) & 0x01) { + /* Get stranded sample into FIFO */ + ni_writel(dev, 0x01, AIFIFO_Control_6143); + dl = ni_readl(dev, AIFIFO_Data_6143); data[0] = (dl >> 16) & 0xffff; cfc_write_to_buffer(s, data[0]); } } else { - fifo_empty = - devpriv->stc_readw(dev, - AI_Status_1_Register) & AI_FIFO_Empty_St; + fifo_empty = ni_stc_readw(dev, AI_Status_1_Register) & + AI_FIFO_Empty_St; while (fifo_empty == 0) { for (i = 0; i < sizeof(devpriv->ai_fifo_buffer) / sizeof(devpriv->ai_fifo_buffer[0]); i++) { - fifo_empty = - devpriv->stc_readw(dev, - AI_Status_1_Register) & - AI_FIFO_Empty_St; + fifo_empty = ni_stc_readw(dev, + AI_Status_1_Register) & + AI_FIFO_Empty_St; if (fifo_empty) break; devpriv->ai_fifo_buffer[i] = - ni_readw(ADC_FIFO_Data_Register); + ni_readw(dev, ADC_FIFO_Data_Register); } cfc_write_array_to_buffer(s, devpriv->ai_fifo_buffer, i * @@ -1423,18 +1374,17 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev) static void get_last_sample_611x(struct comedi_device *dev) { - const struct ni_board_struct *board = comedi_board(dev); - struct ni_private *devpriv __maybe_unused = dev->private; - struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; + struct ni_private *devpriv = dev->private; + struct comedi_subdevice *s = dev->read_subdev; unsigned short data; u32 dl; - if (board->reg_type != ni_reg_611x) + if (!devpriv->is_611x) return; /* Check if there's a single sample stuck in the FIFO */ - if (ni_readb(XXX_Status) & 0x80) { - dl = ni_readl(ADC_FIFO_Data_611x); + if (ni_readb(dev, XXX_Status) & 0x80) { + dl = ni_readl(dev, ADC_FIFO_Data_611x); data = (dl & 0xffff); cfc_write_to_buffer(s, data); } @@ -1442,19 +1392,19 @@ static void get_last_sample_611x(struct comedi_device *dev) static void get_last_sample_6143(struct comedi_device *dev) { - const struct ni_board_struct *board = comedi_board(dev); - struct ni_private *devpriv __maybe_unused = dev->private; - struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; + struct ni_private *devpriv = dev->private; + struct comedi_subdevice *s = dev->read_subdev; unsigned short data; u32 dl; - if (board->reg_type != ni_reg_6143) + if (!devpriv->is_6143) return; /* Check if there's a single sample stuck in the FIFO */ - if (ni_readl(AIFIFO_Status_6143) & 0x01) { - ni_writel(0x01, AIFIFO_Control_6143); /* Get stranded sample into FIFO */ - dl = ni_readl(AIFIFO_Data_6143); + if (ni_readl(dev, AIFIFO_Status_6143) & 0x01) { + /* Get stranded sample into FIFO */ + ni_writel(dev, 0x01, AIFIFO_Control_6143); + dl = ni_readl(dev, AIFIFO_Data_6143); /* This may get the hi/lo data in the wrong order */ data = (dl >> 16) & 0xffff; @@ -1462,6 +1412,232 @@ static void get_last_sample_6143(struct comedi_device *dev) } } +static void shutdown_ai_command(struct comedi_device *dev) +{ + struct comedi_subdevice *s = dev->read_subdev; + +#ifdef PCIDMA + ni_ai_drain_dma(dev); +#endif + ni_handle_fifo_dregs(dev); + get_last_sample_611x(dev); + get_last_sample_6143(dev); + + s->async->events |= COMEDI_CB_EOA; +} + +static void ni_handle_eos(struct comedi_device *dev, struct comedi_subdevice *s) +{ + struct ni_private *devpriv = dev->private; + + if (devpriv->aimode == AIMODE_SCAN) { +#ifdef PCIDMA + static const int timeout = 10; + int i; + + for (i = 0; i < timeout; i++) { + ni_sync_ai_dma(dev); + if ((s->async->events & COMEDI_CB_EOS)) + break; + udelay(1); + } +#else + ni_handle_fifo_dregs(dev); + 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)) + shutdown_ai_command(dev); +} + +static void handle_gpct_interrupt(struct comedi_device *dev, + unsigned short counter_index) +{ +#ifdef PCIDMA + struct ni_private *devpriv = dev->private; + struct comedi_subdevice *s; + + s = &dev->subdevices[NI_GPCT_SUBDEV(counter_index)]; + + ni_tio_handle_interrupt(&devpriv->counter_dev->counters[counter_index], + s); + cfc_handle_events(dev, s); +#endif +} + +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 (ack) + ni_stc_writew(dev, ack, Interrupt_A_Ack_Register); +} + +static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, + unsigned ai_mite_status) +{ + struct comedi_subdevice *s = dev->read_subdev; + struct comedi_cmd *cmd = &s->async->cmd; + + /* 67xx boards don't have ai subdevice, but their gpct0 might generate an a interrupt */ + if (s->type == COMEDI_SUBD_UNUSED) + return; + +#ifdef PCIDMA + if (ai_mite_status & CHSR_LINKC) + ni_sync_ai_dma(dev); + + if (ai_mite_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY | + CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR | + CHSR_SABORT | CHSR_XFERR | CHSR_LxERR_mask)) { + dev_err(dev->class_dev, + "unknown mite interrupt (ai_mite_status=%08x)\n", + ai_mite_status); + s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + /* disable_irq(dev->irq); */ + } +#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 == 0xffff) { + dev_err(dev->class_dev, "Card removed?\n"); + /* we probably aren't even running a command now, + * so it's a good idea to be careful. */ + if (comedi_is_subdevice_running(s)) { + s->async->events |= + COMEDI_CB_ERROR | COMEDI_CB_EOA; + cfc_handle_events(dev, s); + } + return; + } + if (status & (AI_Overrun_St | AI_Overflow_St | + AI_SC_TC_Error_St)) { + 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)) + s->async->events |= COMEDI_CB_OVERFLOW; + + cfc_handle_events(dev, s); + return; + } + if (status & AI_SC_TC_St) { + if (cmd->stop_src == TRIG_COUNT) + shutdown_ai_command(dev); + } + } +#ifndef PCIDMA + if (status & AI_FIFO_Half_Full_St) { + 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) + break; + } + } +#endif /* !PCIDMA */ + + if ((status & AI_STOP_St)) + ni_handle_eos(dev, s); + + cfc_handle_events(dev, s); +} + +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 (ack) + ni_stc_writew(dev, ack, Interrupt_B_Ack_Register); +} + +static void handle_b_interrupt(struct comedi_device *dev, + unsigned short b_status, unsigned ao_mite_status) +{ + struct comedi_subdevice *s = dev->write_subdev; + /* unsigned short ack=0; */ + +#ifdef PCIDMA + /* Currently, mite.c requires us to handle LINKC */ + if (ao_mite_status & CHSR_LINKC) { + struct ni_private *devpriv = dev->private; + + mite_handle_b_linkc(devpriv->mite, dev); + } + + if (ao_mite_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY | + CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR | + CHSR_SABORT | CHSR_XFERR | CHSR_LxERR_mask)) { + dev_err(dev->class_dev, + "unknown mite interrupt (ao_mite_status=%08x)\n", + ao_mite_status); + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + } +#endif + + if (b_status == 0xffff) + return; + if (b_status & AO_Overrun_St) { + 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)); + s->async->events |= COMEDI_CB_OVERFLOW; + } + + if (b_status & AO_BC_TC_St) + s->async->events |= COMEDI_CB_EOA; + +#ifndef PCIDMA + if (b_status & AO_FIFO_Request_St) { + 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); + s->async->events |= COMEDI_CB_OVERFLOW; + } + } +#endif + + cfc_handle_events(dev, s); +} + static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s, void *data, unsigned int num_bytes, unsigned int chan_index) @@ -1494,16 +1670,14 @@ static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s, static int ni_ai_setup_MITE_dma(struct comedi_device *dev) { - const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; + struct comedi_subdevice *s = dev->read_subdev; int retval; unsigned long flags; retval = ni_request_ai_mite_channel(dev); if (retval) return retval; -/* printk("comedi_debug: using mite channel %i for ai.\n", devpriv->ai_mite_chan->channel); */ /* write alloc the entire buffer */ comedi_buf_write_alloc(s, s->async->prealloc_bufsz); @@ -1514,18 +1688,13 @@ static int ni_ai_setup_MITE_dma(struct comedi_device *dev) return -EIO; } - switch (board->reg_type) { - case ni_reg_611x: - case ni_reg_6143: + if (devpriv->is_611x || devpriv->is_6143) mite_prep_dma(devpriv->ai_mite_chan, 32, 16); - break; - case ni_reg_628x: + else if (devpriv->is_628x) mite_prep_dma(devpriv->ai_mite_chan, 32, 32); - break; - default: + else mite_prep_dma(devpriv->ai_mite_chan, 16, 16); - break; - } + /*start the MITE */ mite_dma_arm(devpriv->ai_mite_chan); spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); @@ -1535,9 +1704,8 @@ static int ni_ai_setup_MITE_dma(struct comedi_device *dev) static int ni_ao_setup_MITE_dma(struct comedi_device *dev) { - const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV]; + struct comedi_subdevice *s = dev->write_subdev; int retval; unsigned long flags; @@ -1550,7 +1718,7 @@ static int ni_ao_setup_MITE_dma(struct comedi_device *dev) spin_lock_irqsave(&devpriv->mite_channel_lock, flags); if (devpriv->ao_mite_chan) { - if (board->reg_type & (ni_reg_611x | ni_reg_6713)) { + if (devpriv->is_611x || devpriv->is_6713) { mite_prep_dma(devpriv->ao_mite_chan, 32, 32); } else { /* doing 32 instead of 16 bit wide transfers from memory @@ -1575,13 +1743,12 @@ static int ni_ao_setup_MITE_dma(struct comedi_device *dev) static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s) { - const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; ni_release_ai_mite_channel(dev); /* ai configuration */ - devpriv->stc_writew(dev, AI_Configuration_Start | AI_Reset, - Joint_Reset_Register); + ni_stc_writew(dev, AI_Configuration_Start | AI_Reset, + Joint_Reset_Register); ni_set_bits(dev, Interrupt_A_Enable_Register, AI_SC_TC_Interrupt_Enable | AI_START1_Interrupt_Enable | @@ -1591,56 +1758,58 @@ static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s) ni_clear_ai_fifo(dev); - if (board->reg_type != ni_reg_6143) - ni_writeb(0, Misc_Command); + if (!devpriv->is_6143) + ni_writeb(dev, 0, Misc_Command); - devpriv->stc_writew(dev, AI_Disarm, AI_Command_1_Register); /* reset pulses */ - devpriv->stc_writew(dev, - AI_Start_Stop | AI_Mode_1_Reserved - /*| AI_Trigger_Once */ , - AI_Mode_1_Register); - devpriv->stc_writew(dev, 0x0000, AI_Mode_2_Register); + 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); /* generate FIFO interrupts on non-empty */ - devpriv->stc_writew(dev, (0 << 6) | 0x0000, AI_Mode_3_Register); - if (board->reg_type == ni_reg_611x) { - devpriv->stc_writew(dev, AI_SHIFTIN_Pulse_Width | - AI_SOC_Polarity | - AI_LOCALMUX_CLK_Pulse_Width, - AI_Personal_Register); - devpriv->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); - } else if (board->reg_type == ni_reg_6143) { - devpriv->stc_writew(dev, AI_SHIFTIN_Pulse_Width | - AI_SOC_Polarity | - AI_LOCALMUX_CLK_Pulse_Width, - AI_Personal_Register); - devpriv->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); + ni_stc_writew(dev, (0 << 6) | 0x0000, AI_Mode_3_Register); + 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); + } 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); } else { unsigned ai_output_control_bits; - devpriv->stc_writew(dev, AI_SHIFTIN_Pulse_Width | - AI_SOC_Polarity | - AI_CONVERT_Pulse_Width | - AI_LOCALMUX_CLK_Pulse_Width, - AI_Personal_Register); + + 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); - if (board->reg_type == ni_reg_622x) + if (devpriv->is_622x) ai_output_control_bits |= AI_CONVERT_Output_Select (AI_CONVERT_Output_Enable_High); @@ -1648,8 +1817,8 @@ static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s) ai_output_control_bits |= AI_CONVERT_Output_Select (AI_CONVERT_Output_Enable_Low); - devpriv->stc_writew(dev, ai_output_control_bits, - AI_Output_Control_Register); + ni_stc_writew(dev, ai_output_control_bits, + AI_Output_Control_Register); } /* the following registers should not be changed, because there * are no backup registers in devpriv. If you want to change @@ -1659,9 +1828,17 @@ static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s) * AI_Personal_Register * AI_Output_Control_Register */ - devpriv->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 */ - - devpriv->stc_writew(dev, AI_Configuration_End, Joint_Reset_Register); + 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); return 0; } @@ -1678,127 +1855,26 @@ static int ni_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) #else ni_sync_ai_dma(dev); #endif - count = s->async->buf_write_count - s->async->buf_read_count; + count = comedi_buf_n_bytes_ready(s); spin_unlock_irqrestore(&dev->spinlock, flags); return count; } -static int ni_ai_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data) -{ - const struct ni_board_struct *board = comedi_board(dev); - struct ni_private *devpriv = dev->private; - int i, n; - const unsigned int mask = (1 << board->adbits) - 1; - unsigned signbits; - unsigned short d; - unsigned long dl; - - ni_load_channelgain_list(dev, 1, &insn->chanspec); - - ni_clear_ai_fifo(dev); - - signbits = devpriv->ai_offset[0]; - if (board->reg_type == ni_reg_611x) { - for (n = 0; n < num_adc_stages_611x; n++) { - devpriv->stc_writew(dev, AI_CONVERT_Pulse, - AI_Command_1_Register); - udelay(1); - } - for (n = 0; n < insn->n; n++) { - devpriv->stc_writew(dev, AI_CONVERT_Pulse, - AI_Command_1_Register); - /* The 611x has screwy 32-bit FIFOs. */ - d = 0; - for (i = 0; i < NI_TIMEOUT; i++) { - if (ni_readb(XXX_Status) & 0x80) { - d = (ni_readl(ADC_FIFO_Data_611x) >> 16) - & 0xffff; - break; - } - if (!(devpriv->stc_readw(dev, - AI_Status_1_Register) & - AI_FIFO_Empty_St)) { - d = ni_readl(ADC_FIFO_Data_611x) & - 0xffff; - break; - } - } - if (i == NI_TIMEOUT) { - printk - ("ni_mio_common: timeout in 611x ni_ai_insn_read\n"); - return -ETIME; - } - d += signbits; - data[n] = d; - } - } else if (board->reg_type == ni_reg_6143) { - for (n = 0; n < insn->n; n++) { - devpriv->stc_writew(dev, AI_CONVERT_Pulse, - AI_Command_1_Register); - - /* 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(AIFIFO_Status_6143) & 0x01) { - ni_writel(0x01, AIFIFO_Control_6143); /* Get stranded sample into FIFO */ - dl = ni_readl(AIFIFO_Data_6143); - break; - } - } - if (i == NI_TIMEOUT) { - printk - ("ni_mio_common: timeout in 6143 ni_ai_insn_read\n"); - return -ETIME; - } - data[n] = (((dl >> 16) & 0xFFFF) + signbits) & 0xFFFF; - } - } else { - for (n = 0; n < insn->n; n++) { - devpriv->stc_writew(dev, AI_CONVERT_Pulse, - AI_Command_1_Register); - for (i = 0; i < NI_TIMEOUT; i++) { - if (!(devpriv->stc_readw(dev, - AI_Status_1_Register) & - AI_FIFO_Empty_St)) - break; - } - if (i == NI_TIMEOUT) { - printk - ("ni_mio_common: timeout in ni_ai_insn_read\n"); - return -ETIME; - } - if (board->reg_type & ni_reg_m_series_mask) { - data[n] = - ni_readl(M_Offset_AI_FIFO_Data) & mask; - } else { - d = ni_readw(ADC_FIFO_Data_Register); - d += signbits; /* subtle: needs to be short addition */ - data[n] = d; - } - } - } - return insn->n; -} - static void ni_prime_channelgain_list(struct comedi_device *dev) { - struct ni_private *devpriv = dev->private; int i; - devpriv->stc_writew(dev, AI_CONVERT_Pulse, AI_Command_1_Register); + ni_stc_writew(dev, AI_CONVERT_Pulse, AI_Command_1_Register); for (i = 0; i < NI_TIMEOUT; ++i) { - if (!(devpriv->stc_readw(dev, - AI_Status_1_Register) & + if (!(ni_stc_readw(dev, AI_Status_1_Register) & AI_FIFO_Empty_St)) { - devpriv->stc_writew(dev, 1, ADC_FIFO_Clear); + ni_stc_writew(dev, 1, ADC_FIFO_Clear); return; } udelay(1); } - printk("ni_mio_common: timeout loading channel/gain list\n"); + dev_err(dev->class_dev, "timeout loading channel/gain list\n"); } static void ni_m_series_load_channelgain_list(struct comedi_device *dev, @@ -1809,15 +1885,14 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev, struct ni_private *devpriv = dev->private; unsigned int chan, range, aref; unsigned int i; - unsigned offset; unsigned int dither; unsigned range_code; - devpriv->stc_writew(dev, 1, Configuration_Memory_Clear); + ni_stc_writew(dev, 1, Configuration_Memory_Clear); -/* offset = 1 << (board->adbits - 1); */ if ((list[0] & CR_ALT_SOURCE)) { unsigned bypass_bits; + chan = CR_CHAN(list[0]); range = CR_RANGE(list[0]); range_code = ni_gainlkup[board->gainlkup][range]; @@ -1835,20 +1910,20 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev, bypass_bits |= MSeries_AI_Bypass_Dither_Bit; /* don't use 2's complement encoding */ bypass_bits |= MSeries_AI_Bypass_Polarity_Bit; - ni_writel(bypass_bits, M_Offset_AI_Config_FIFO_Bypass); + ni_writel(dev, bypass_bits, M_Offset_AI_Config_FIFO_Bypass); } else { - ni_writel(0, M_Offset_AI_Config_FIFO_Bypass); + ni_writel(dev, 0, M_Offset_AI_Config_FIFO_Bypass); } - offset = 0; for (i = 0; i < n_chan; i++) { unsigned config_bits = 0; + chan = CR_CHAN(list[i]); aref = CR_AREF(list[i]); range = CR_RANGE(list[i]); dither = ((list[i] & CR_ALT_FILTER) != 0); range_code = ni_gainlkup[board->gainlkup][range]; - devpriv->ai_offset[i] = offset; + devpriv->ai_offset[i] = 0; switch (aref) { case AREF_DIFF: config_bits |= @@ -1875,7 +1950,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev, config_bits |= MSeries_AI_Config_Dither_Bit; /* don't use 2's complement encoding */ config_bits |= MSeries_AI_Config_Polarity_Bit; - ni_writew(config_bits, M_Offset_AI_Config_FIFO_Data); + ni_writew(dev, config_bits, M_Offset_AI_Config_FIFO_Data); } ni_prime_channelgain_list(dev); } @@ -1910,22 +1985,22 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev, * valid channels are 0-3 */ static void ni_load_channelgain_list(struct comedi_device *dev, + struct comedi_subdevice *s, unsigned int n_chan, unsigned int *list) { const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; + unsigned int offset = (s->maxdata + 1) >> 1; unsigned int chan, range, aref; unsigned int i; unsigned int hi, lo; - unsigned offset; unsigned int dither; - if (board->reg_type & ni_reg_m_series_mask) { + if (devpriv->is_m_series) { ni_m_series_load_channelgain_list(dev, n_chan, list); return; } - if (n_chan == 1 && (board->reg_type != ni_reg_611x) - && (board->reg_type != ni_reg_6143)) { + if (n_chan == 1 && !devpriv->is_611x && !devpriv->is_6143) { if (devpriv->changain_state && devpriv->changain_spec == list[0]) { /* ready to go. */ @@ -1937,61 +2012,58 @@ static void ni_load_channelgain_list(struct comedi_device *dev, devpriv->changain_state = 0; } - devpriv->stc_writew(dev, 1, Configuration_Memory_Clear); + ni_stc_writew(dev, 1, Configuration_Memory_Clear); /* Set up Calibration mode if required */ - if (board->reg_type == ni_reg_6143) { + if (devpriv->is_6143) { if ((list[0] & CR_ALT_SOURCE) && !devpriv->ai_calib_source_enabled) { /* Strobe Relay enable bit */ - ni_writew(devpriv->ai_calib_source | - Calibration_Channel_6143_RelayOn, + ni_writew(dev, devpriv->ai_calib_source | + Calibration_Channel_6143_RelayOn, Calibration_Channel_6143); - ni_writew(devpriv->ai_calib_source, + ni_writew(dev, devpriv->ai_calib_source, Calibration_Channel_6143); 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(devpriv->ai_calib_source | - Calibration_Channel_6143_RelayOff, + ni_writew(dev, devpriv->ai_calib_source | + Calibration_Channel_6143_RelayOff, Calibration_Channel_6143); - ni_writew(devpriv->ai_calib_source, + ni_writew(dev, devpriv->ai_calib_source, Calibration_Channel_6143); devpriv->ai_calib_source_enabled = 0; msleep_interruptible(100); /* Allow relays to change */ } } - offset = 1 << (board->adbits - 1); for (i = 0; i < n_chan; i++) { - if ((board->reg_type != ni_reg_6143) - && (list[i] & CR_ALT_SOURCE)) { + if (!devpriv->is_6143 && (list[i] & CR_ALT_SOURCE)) chan = devpriv->ai_calib_source; - } else { + else chan = CR_CHAN(list[i]); - } aref = CR_AREF(list[i]); range = CR_RANGE(list[i]); dither = ((list[i] & CR_ALT_FILTER) != 0); /* fix the external/internal range differences */ range = ni_gainlkup[board->gainlkup][range]; - if (board->reg_type == ni_reg_611x) + if (devpriv->is_611x) devpriv->ai_offset[i] = offset; else devpriv->ai_offset[i] = (range & 0x100) ? 0 : offset; hi = 0; if ((list[i] & CR_ALT_SOURCE)) { - if (board->reg_type == ni_reg_611x) - ni_writew(CR_CHAN(list[i]) & 0x0003, + if (devpriv->is_611x) + ni_writew(dev, CR_CHAN(list[i]) & 0x0003, Calibration_Channel_Select_611x); } else { - if (board->reg_type == ni_reg_611x) + if (devpriv->is_611x) aref = AREF_DIFF; - else if (board->reg_type == ni_reg_6143) + else if (devpriv->is_6143) aref = AREF_OTHER; switch (aref) { case AREF_DIFF: @@ -2009,33 +2081,132 @@ static void ni_load_channelgain_list(struct comedi_device *dev, } hi |= AI_CONFIG_CHANNEL(chan); - ni_writew(hi, Configuration_Memory_High); + ni_writew(dev, hi, Configuration_Memory_High); - if (board->reg_type != ni_reg_6143) { + if (!devpriv->is_6143) { lo = range; if (i == n_chan - 1) lo |= AI_LAST_CHANNEL; if (dither) lo |= AI_DITHER; - ni_writew(lo, Configuration_Memory_Low); + ni_writew(dev, lo, Configuration_Memory_Low); } } /* prime the channel/gain list */ - if ((board->reg_type != ni_reg_611x) - && (board->reg_type != ni_reg_6143)) { + if (!devpriv->is_611x && !devpriv->is_6143) ni_prime_channelgain_list(dev); +} + +static int ni_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct ni_private *devpriv = dev->private; + unsigned int mask = (s->maxdata + 1) >> 1; + int i, n; + unsigned signbits; + unsigned short d; + unsigned long dl; + + ni_load_channelgain_list(dev, s, 1, &insn->chanspec); + + ni_clear_ai_fifo(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); + udelay(1); + } + for (n = 0; n < insn->n; n++) { + ni_stc_writew(dev, AI_CONVERT_Pulse, + AI_Command_1_Register); + /* 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); + 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); + d &= 0xffff; + break; + } + } + if (i == NI_TIMEOUT) { + dev_err(dev->class_dev, "%s timeout\n", + __func__); + return -ETIME; + } + d += signbits; + data[n] = d; + } + } else if (devpriv->is_6143) { + for (n = 0; n < insn->n; n++) { + ni_stc_writew(dev, AI_CONVERT_Pulse, + AI_Command_1_Register); + + /* 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) { + /* Get stranded sample into FIFO */ + ni_writel(dev, 0x01, + AIFIFO_Control_6143); + dl = ni_readl(dev, AIFIFO_Data_6143); + break; + } + } + if (i == NI_TIMEOUT) { + dev_err(dev->class_dev, "%s timeout\n", + __func__); + return -ETIME; + } + data[n] = (((dl >> 16) & 0xFFFF) + signbits) & 0xFFFF; + } + } else { + for (n = 0; n < insn->n; n++) { + ni_stc_writew(dev, AI_CONVERT_Pulse, + AI_Command_1_Register); + for (i = 0; i < NI_TIMEOUT; i++) { + if (!(ni_stc_readw(dev, AI_Status_1_Register) & + AI_FIFO_Empty_St)) + break; + } + if (i == NI_TIMEOUT) { + dev_err(dev->class_dev, "%s timeout\n", + __func__); + return -ETIME; + } + if (devpriv->is_m_series) { + dl = ni_readl(dev, M_Offset_AI_FIFO_Data); + dl &= mask; + data[n] = dl; + } else { + d = ni_readw(dev, ADC_FIFO_Data_Register); + d += signbits; /* subtle: needs to be short addition */ + data[n] = d; + } + } } + return insn->n; } static int ni_ns_to_timer(const struct comedi_device *dev, unsigned nanosec, - int round_mode) + unsigned int flags) { struct ni_private *devpriv = dev->private; int divider; - switch (round_mode) { + switch (flags & TRIG_ROUND_MASK) { case TRIG_ROUND_NEAREST: default: divider = (nanosec + devpriv->clock_ns / 2) / devpriv->clock_ns; @@ -2061,17 +2232,13 @@ static unsigned ni_min_ai_scan_period_ns(struct comedi_device *dev, unsigned num_channels) { const struct ni_board_struct *board = comedi_board(dev); + struct ni_private *devpriv = dev->private; - switch (board->reg_type) { - case ni_reg_611x: - case ni_reg_6143: - /* simultaneously-sampled inputs */ + /* simultaneously-sampled inputs */ + if (devpriv->is_611x || devpriv->is_6143) return board->ai_speed; - break; - default: - /* multiplexed inputs */ - break; - } + + /* multiplexed inputs */ return board->ai_speed * num_channels; } @@ -2095,8 +2262,7 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, TRIG_TIMER | TRIG_EXT); sources = TRIG_TIMER | TRIG_EXT; - if (board->reg_type == ni_reg_611x || - board->reg_type == ni_reg_6143) + if (devpriv->is_611x || devpriv->is_6143) sources |= TRIG_NOW; err |= cfc_check_trigger_src(&cmd->convert_src, sources); @@ -2153,8 +2319,7 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, } if (cmd->convert_src == TRIG_TIMER) { - if ((board->reg_type == ni_reg_611x) - || (board->reg_type == ni_reg_6143)) { + if (devpriv->is_611x || devpriv->is_6143) { err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); } else { err |= cfc_check_trigger_arg_min(&cmd->convert_arg, @@ -2179,7 +2344,7 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, if (cmd->stop_src == TRIG_COUNT) { unsigned int max_count = 0x01000000; - if (board->reg_type == ni_reg_611x) + if (devpriv->is_611x) max_count -= num_adc_stages_611x; err |= cfc_check_trigger_arg_max(&cmd->stop_arg, max_count); err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1); @@ -2198,22 +2363,17 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, cmd->scan_begin_arg = ni_timer_to_ns(dev, ni_ns_to_timer(dev, cmd->scan_begin_arg, - cmd-> - flags & - TRIG_ROUND_MASK)); + cmd->flags)); if (tmp != cmd->scan_begin_arg) err++; } if (cmd->convert_src == TRIG_TIMER) { - if ((board->reg_type != ni_reg_611x) - && (board->reg_type != ni_reg_6143)) { + if (!devpriv->is_611x && !devpriv->is_6143) { tmp = cmd->convert_arg; cmd->convert_arg = ni_timer_to_ns(dev, ni_ns_to_timer(dev, cmd->convert_arg, - cmd-> - flags & - TRIG_ROUND_MASK)); + cmd->flags)); if (tmp != cmd->convert_arg) err++; if (cmd->scan_begin_src == TRIG_TIMER && @@ -2232,9 +2392,25 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, return 0; } +static int ni_ai_inttrig(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int trig_num) +{ + struct ni_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; + + if (trig_num != cmd->start_arg) + return -EINVAL; + + ni_stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2, + AI_Command_2_Register); + s->async->inttrig = NULL; + + return 1; +} + static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; const struct comedi_cmd *cmd = &s->async->cmd; int timer; @@ -2245,29 +2421,30 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) int interrupt_a_enable = 0; if (dev->irq == 0) { - comedi_error(dev, "cannot run command without an irq"); + dev_err(dev->class_dev, "cannot run command without an irq\n"); return -EIO; } ni_clear_ai_fifo(dev); - ni_load_channelgain_list(dev, cmd->chanlist_len, cmd->chanlist); + ni_load_channelgain_list(dev, s, cmd->chanlist_len, cmd->chanlist); /* start configuration */ - devpriv->stc_writew(dev, AI_Configuration_Start, Joint_Reset_Register); + ni_stc_writew(dev, AI_Configuration_Start, Joint_Reset_Register); /* disable analog triggering for now, since it * interferes with the use of pfi0 */ devpriv->an_trig_etc_reg &= ~Analog_Trigger_Enable; - devpriv->stc_writew(dev, devpriv->an_trig_etc_reg, - Analog_Trigger_Etc_Register); + ni_stc_writew(dev, devpriv->an_trig_etc_reg, + Analog_Trigger_Etc_Register); switch (cmd->start_src) { case TRIG_INT: case TRIG_NOW: - devpriv->stc_writew(dev, AI_START2_Select(0) | - AI_START1_Sync | AI_START1_Edge | - AI_START1_Select(0), - AI_Trigger_Select_Register); + ni_stc_writew(dev, + AI_START2_Select(0) | + AI_START1_Sync | AI_START1_Edge | + AI_START1_Select(0), + AI_Trigger_Select_Register); break; case TRIG_EXT: { @@ -2279,8 +2456,7 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) bits |= AI_START1_Polarity; if (cmd->start_arg & CR_EDGE) bits |= AI_START1_Edge; - devpriv->stc_writew(dev, bits, - AI_Trigger_Select_Register); + ni_stc_writew(dev, bits, AI_Trigger_Select_Register); break; } } @@ -2288,37 +2464,34 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) mode2 &= ~AI_Pre_Trigger; mode2 &= ~AI_SC_Initial_Load_Source; mode2 &= ~AI_SC_Reload_Mode; - devpriv->stc_writew(dev, mode2, AI_Mode_2_Register); + ni_stc_writew(dev, mode2, AI_Mode_2_Register); - if (cmd->chanlist_len == 1 || (board->reg_type == ni_reg_611x) - || (board->reg_type == ni_reg_6143)) { + 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; } else { start_stop_select |= AI_STOP_Select(19); /* ai configuration memory */ } - devpriv->stc_writew(dev, start_stop_select, - AI_START_STOP_Select_Register); + ni_stc_writew(dev, start_stop_select, AI_START_STOP_Select_Register); devpriv->ai_cmd2 = 0; switch (cmd->stop_src) { case TRIG_COUNT: stop_count = cmd->stop_arg - 1; - if (board->reg_type == ni_reg_611x) { + if (devpriv->is_611x) { /* have to take 3 stage adc pipeline into account */ stop_count += num_adc_stages_611x; } /* stage number of scans */ - devpriv->stc_writel(dev, stop_count, AI_SC_Load_A_Registers); + ni_stc_writel(dev, stop_count, AI_SC_Load_A_Registers); mode1 |= AI_Start_Stop | AI_Mode_1_Reserved | AI_Trigger_Once; - devpriv->stc_writew(dev, mode1, AI_Mode_1_Register); + ni_stc_writew(dev, mode1, AI_Mode_1_Register); /* load SC (Scan Count) */ - devpriv->stc_writew(dev, AI_SC_Load, AI_Command_1_Register); + ni_stc_writew(dev, AI_SC_Load, AI_Command_1_Register); - devpriv->ai_continuous = 0; if (stop_count == 0) { devpriv->ai_cmd2 |= AI_End_On_End_Of_Scan; interrupt_a_enable |= AI_STOP_Interrupt_Enable; @@ -2330,16 +2503,13 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) break; case TRIG_NONE: /* stage number of scans */ - devpriv->stc_writel(dev, 0, AI_SC_Load_A_Registers); + ni_stc_writel(dev, 0, AI_SC_Load_A_Registers); mode1 |= AI_Start_Stop | AI_Mode_1_Reserved | AI_Continuous; - devpriv->stc_writew(dev, mode1, AI_Mode_1_Register); + ni_stc_writew(dev, mode1, AI_Mode_1_Register); /* load SC (Scan Count) */ - devpriv->stc_writew(dev, AI_SC_Load, AI_Command_1_Register); - - devpriv->ai_continuous = 1; - + ni_stc_writew(dev, AI_SC_Load, AI_Command_1_Register); break; } @@ -2360,20 +2530,20 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) AI_STOP_Select=19 external pin (configuration mem) */ start_stop_select |= AI_START_Edge | AI_START_Sync; - devpriv->stc_writew(dev, start_stop_select, - AI_START_STOP_Select_Register); + ni_stc_writew(dev, start_stop_select, + AI_START_STOP_Select_Register); mode2 |= AI_SI_Reload_Mode(0); /* AI_SI_Initial_Load_Source=A */ mode2 &= ~AI_SI_Initial_Load_Source; /* mode2 |= AI_SC_Reload_Mode; */ - devpriv->stc_writew(dev, mode2, AI_Mode_2_Register); + ni_stc_writew(dev, mode2, AI_Mode_2_Register); /* load SI */ timer = ni_ns_to_timer(dev, cmd->scan_begin_arg, TRIG_ROUND_NEAREST); - devpriv->stc_writel(dev, timer, AI_SI_Load_A_Registers); - devpriv->stc_writew(dev, AI_SI_Load, AI_Command_1_Register); + ni_stc_writel(dev, timer, AI_SI_Load_A_Registers); + ni_stc_writew(dev, AI_SI_Load, AI_Command_1_Register); break; case TRIG_EXT: if (cmd->scan_begin_arg & CR_EDGE) @@ -2387,7 +2557,7 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) start_stop_select |= AI_START_Sync; start_stop_select |= AI_START_Select(1 + CR_CHAN(cmd->scan_begin_arg)); - devpriv->stc_writew(dev, start_stop_select, + ni_stc_writew(dev, start_stop_select, AI_START_STOP_Select_Register); break; } @@ -2400,31 +2570,32 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) else timer = ni_ns_to_timer(dev, cmd->convert_arg, TRIG_ROUND_NEAREST); - devpriv->stc_writew(dev, 1, AI_SI2_Load_A_Register); /* 0,0 does not work. */ - devpriv->stc_writew(dev, timer, AI_SI2_Load_B_Register); + /* 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); /* AI_SI2_Reload_Mode = alternate */ /* AI_SI2_Initial_Load_Source = A */ mode2 &= ~AI_SI2_Initial_Load_Source; mode2 |= AI_SI2_Reload_Mode; - devpriv->stc_writew(dev, mode2, AI_Mode_2_Register); + ni_stc_writew(dev, mode2, AI_Mode_2_Register); /* AI_SI2_Load */ - devpriv->stc_writew(dev, AI_SI2_Load, AI_Command_1_Register); + ni_stc_writew(dev, AI_SI2_Load, AI_Command_1_Register); mode2 |= AI_SI2_Reload_Mode; /* alternate */ mode2 |= AI_SI2_Initial_Load_Source; /* B */ - devpriv->stc_writew(dev, mode2, AI_Mode_2_Register); + ni_stc_writew(dev, mode2, AI_Mode_2_Register); break; case TRIG_EXT: mode1 |= AI_CONVERT_Source_Select(1 + cmd->convert_arg); if ((cmd->convert_arg & CR_INVERT) == 0) mode1 |= AI_CONVERT_Source_Polarity; - devpriv->stc_writew(dev, mode1, AI_Mode_1_Register); + ni_stc_writew(dev, mode1, AI_Mode_1_Register); mode2 |= AI_Start_Stop_Gate_Enable | AI_SC_Gate_Enable; - devpriv->stc_writew(dev, mode2, AI_Mode_2_Register); + ni_stc_writew(dev, mode2, AI_Mode_2_Register); break; } @@ -2451,25 +2622,25 @@ 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 - devpriv->stc_writew(dev, AI_FIFO_Mode_HF_to_E, - AI_Mode_3_Register); + ni_stc_writew(dev, AI_FIFO_Mode_HF_to_E, + AI_Mode_3_Register); #else - devpriv->stc_writew(dev, AI_FIFO_Mode_HF, - AI_Mode_3_Register); + ni_stc_writew(dev, AI_FIFO_Mode_HF, + AI_Mode_3_Register); #endif break; case AIMODE_SAMPLE: /*generate FIFO interrupts on non-empty */ - devpriv->stc_writew(dev, AI_FIFO_Mode_NE, - AI_Mode_3_Register); + ni_stc_writew(dev, AI_FIFO_Mode_NE, + AI_Mode_3_Register); break; case AIMODE_SCAN: #ifdef PCIDMA - devpriv->stc_writew(dev, AI_FIFO_Mode_NE, - AI_Mode_3_Register); + ni_stc_writew(dev, AI_FIFO_Mode_NE, + AI_Mode_3_Register); #else - devpriv->stc_writew(dev, AI_FIFO_Mode_HF, - AI_Mode_3_Register); + ni_stc_writew(dev, AI_FIFO_Mode_HF, + AI_Mode_3_Register); #endif interrupt_a_enable |= AI_STOP_Interrupt_Enable; break; @@ -2477,7 +2648,16 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) break; } - devpriv->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); /* clear interrupts */ + /* 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); @@ -2489,25 +2669,26 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } /* end configuration */ - devpriv->stc_writew(dev, AI_Configuration_End, Joint_Reset_Register); + ni_stc_writew(dev, AI_Configuration_End, Joint_Reset_Register); switch (cmd->scan_begin_src) { case TRIG_TIMER: - devpriv->stc_writew(dev, - AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm | - AI_SC_Arm, AI_Command_1_Register); + ni_stc_writew(dev, + AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm | AI_SC_Arm, + AI_Command_1_Register); break; case TRIG_EXT: /* XXX AI_SI_Arm? */ - devpriv->stc_writew(dev, - AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm | - AI_SC_Arm, AI_Command_1_Register); + ni_stc_writew(dev, + AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm | AI_SC_Arm, + AI_Command_1_Register); break; } #ifdef PCIDMA { int retval = ni_ai_setup_MITE_dma(dev); + if (retval) return retval; } @@ -2515,8 +2696,8 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (cmd->start_src == TRIG_NOW) { /* AI_START1_Pulse */ - devpriv->stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2, - AI_Command_2_Register); + ni_stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2, + AI_Command_2_Register); s->async->inttrig = NULL; } else if (cmd->start_src == TRIG_EXT) { s->async->inttrig = NULL; @@ -2527,43 +2708,18 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } -static int ni_ai_inttrig(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int trig_num) -{ - struct ni_private *devpriv = dev->private; - struct comedi_cmd *cmd = &s->async->cmd; - - if (trig_num != cmd->start_arg) - return -EINVAL; - - devpriv->stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2, - AI_Command_2_Register); - s->async->inttrig = NULL; - - return 1; -} - -static int ni_ai_config_analog_trig(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data); - static int ni_ai_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; if (insn->n < 1) return -EINVAL; switch (data[0]) { - case INSN_CONFIG_ANALOG_TRIG: - return ni_ai_config_analog_trig(dev, s, insn, data); case INSN_CONFIG_ALT_SOURCE: - if (board->reg_type & ni_reg_m_series_mask) { + 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 | @@ -2571,7 +2727,7 @@ static int ni_ai_insn_config(struct comedi_device *dev, return -EINVAL; } devpriv->ai_calib_source = data[1]; - } else if (board->reg_type == ni_reg_6143) { + } else if (devpriv->is_6143) { unsigned int calib_source; calib_source = data[1] & 0xf; @@ -2580,7 +2736,7 @@ static int ni_ai_insn_config(struct comedi_device *dev, return -EINVAL; devpriv->ai_calib_source = calib_source; - ni_writew(calib_source, Calibration_Channel_6143); + ni_writew(dev, calib_source, Calibration_Channel_6143); } else { unsigned int calib_source; unsigned int calib_source_adjust; @@ -2591,8 +2747,8 @@ static int ni_ai_insn_config(struct comedi_device *dev, if (calib_source >= 8) return -EINVAL; devpriv->ai_calib_source = calib_source; - if (board->reg_type == ni_reg_611x) { - ni_writeb(calib_source_adjust, + if (devpriv->is_611x) { + ni_writeb(dev, calib_source_adjust, Cal_Gain_Select_611x); } } @@ -2604,127 +2760,30 @@ static int ni_ai_insn_config(struct comedi_device *dev, return -EINVAL; } -static int ni_ai_config_analog_trig(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - const struct ni_board_struct *board = comedi_board(dev); - struct ni_private *devpriv = dev->private; - unsigned int a, b, modebits; - int err = 0; - - /* data[1] is flags - * data[2] is analog line - * data[3] is set level - * data[4] is reset level */ - if (!board->has_analog_trig) - return -EINVAL; - if ((data[1] & 0xffff0000) != COMEDI_EV_SCAN_BEGIN) { - data[1] &= (COMEDI_EV_SCAN_BEGIN | 0xffff); - err++; - } - if (data[2] >= board->n_adchan) { - data[2] = board->n_adchan - 1; - err++; - } - if (data[3] > 255) { /* a */ - data[3] = 255; - err++; - } - if (data[4] > 255) { /* b */ - data[4] = 255; - err++; - } - /* - * 00 ignore - * 01 set - * 10 reset - * - * modes: - * 1 level: +b- +a- - * high mode 00 00 01 10 - * low mode 00 00 10 01 - * 2 level: (a<b) - * hysteresis low mode 10 00 00 01 - * hysteresis high mode 01 00 00 10 - * middle mode 10 01 01 10 - */ - - a = data[3]; - b = data[4]; - modebits = data[1] & 0xff; - if (modebits & 0xf0) { - /* two level mode */ - if (b < a) { - /* swap order */ - a = data[4]; - b = data[3]; - modebits = - ((data[1] & 0xf) << 4) | ((data[1] & 0xf0) >> 4); - } - devpriv->atrig_low = a; - devpriv->atrig_high = b; - switch (modebits) { - case 0x81: /* low hysteresis mode */ - devpriv->atrig_mode = 6; - break; - case 0x42: /* high hysteresis mode */ - devpriv->atrig_mode = 3; - break; - case 0x96: /* middle window mode */ - devpriv->atrig_mode = 2; - break; - default: - data[1] &= ~0xff; - err++; - } - } else { - /* one level mode */ - if (b != 0) { - data[4] = 0; - err++; - } - switch (modebits) { - case 0x06: /* high window mode */ - devpriv->atrig_high = a; - devpriv->atrig_mode = 0; - break; - case 0x09: /* low window mode */ - devpriv->atrig_low = a; - devpriv->atrig_mode = 1; - break; - default: - data[1] &= ~0xff; - err++; - } - } - if (err) - return -EAGAIN; - return 5; -} - -/* munge data from unsigned to 2's complement for analog output bipolar modes */ static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, void *data, unsigned int num_bytes, unsigned int chan_index) { - const struct ni_board_struct *board = comedi_board(dev); - struct comedi_async *async = s->async; - struct comedi_cmd *cmd = &async->cmd; - unsigned int length = num_bytes / sizeof(short); - unsigned int offset = 1 << (board->aobits - 1); + struct comedi_cmd *cmd = &s->async->cmd; + unsigned int length = num_bytes / bytes_per_sample(s); unsigned short *array = data; - unsigned int range; unsigned int i; for (i = 0; i < length; i++) { - range = CR_RANGE(cmd->chanlist[chan_index]); - if (board->ao_unipolar == 0 || (range & 1) == 0) - array[i] -= offset; + unsigned int range = CR_RANGE(cmd->chanlist[chan_index]); + unsigned short val = array[i]; + + /* + * Munge data from unsigned to two's complement for + * bipolar ranges. + */ + if (comedi_range_is_bipolar(s, range)) + val = comedi_offset_munge(s, val); #ifdef PCIDMA - array[i] = cpu_to_le16(array[i]); + val = cpu_to_le16(val); #endif + array[i] = val; + chan_index++; chan_index %= cmd->chanlist_len; } @@ -2735,7 +2794,6 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev, unsigned int chanspec[], unsigned int n_chans, int timed) { - const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; unsigned int range; unsigned int chan; @@ -2744,15 +2802,16 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev, int invert = 0; if (timed) { - for (i = 0; i < board->n_aochan; ++i) { + for (i = 0; i < s->n_chan; ++i) { devpriv->ao_conf[i] &= ~MSeries_AO_Update_Timed_Bit; - ni_writeb(devpriv->ao_conf[i], + ni_writeb(dev, devpriv->ao_conf[i], M_Offset_AO_Config_Bank(i)); - ni_writeb(0xf, M_Offset_AO_Waveform_Order(i)); + ni_writeb(dev, 0xf, M_Offset_AO_Waveform_Order(i)); } } for (i = 0; i < n_chans; i++) { const struct comedi_krange *krange; + chan = CR_CHAN(chanspec[i]); range = CR_RANGE(chanspec[i]); krange = s->range_table->range + range; @@ -2761,25 +2820,28 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev, switch (krange->max - krange->min) { case 20000000: conf |= MSeries_AO_DAC_Reference_10V_Internal_Bits; - ni_writeb(0, M_Offset_AO_Reference_Attenuation(chan)); + ni_writeb(dev, 0, + M_Offset_AO_Reference_Attenuation(chan)); break; case 10000000: conf |= MSeries_AO_DAC_Reference_5V_Internal_Bits; - ni_writeb(0, M_Offset_AO_Reference_Attenuation(chan)); + ni_writeb(dev, 0, + M_Offset_AO_Reference_Attenuation(chan)); break; case 4000000: conf |= MSeries_AO_DAC_Reference_10V_Internal_Bits; - ni_writeb(MSeries_Attenuate_x5_Bit, + ni_writeb(dev, MSeries_Attenuate_x5_Bit, M_Offset_AO_Reference_Attenuation(chan)); break; case 2000000: conf |= MSeries_AO_DAC_Reference_5V_Internal_Bits; - ni_writeb(MSeries_Attenuate_x5_Bit, + ni_writeb(dev, MSeries_Attenuate_x5_Bit, M_Offset_AO_Reference_Attenuation(chan)); break; default: - printk("%s: bug! unhandled ao reference voltage\n", - __func__); + dev_err(dev->class_dev, + "%s: bug! unhandled ao reference voltage\n", + __func__); break; } switch (krange->max + krange->min) { @@ -2790,15 +2852,16 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev, conf |= MSeries_AO_DAC_Offset_5V_Bits; break; default: - printk("%s: bug! unhandled ao offset voltage\n", - __func__); + dev_err(dev->class_dev, + "%s: bug! unhandled ao offset voltage\n", + __func__); break; } if (timed) conf |= MSeries_AO_Update_Timed_Bit; - ni_writeb(conf, M_Offset_AO_Config_Bank(chan)); + ni_writeb(dev, conf, M_Offset_AO_Config_Bank(chan)); devpriv->ao_conf[chan] = conf; - ni_writeb(i, M_Offset_AO_Waveform_Order(chan)); + ni_writeb(dev, i, M_Offset_AO_Waveform_Order(chan)); } return invert; } @@ -2808,7 +2871,6 @@ static int ni_old_ao_config_chanlist(struct comedi_device *dev, unsigned int chanspec[], unsigned int n_chans) { - const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; unsigned int range; unsigned int chan; @@ -2821,19 +2883,14 @@ static int ni_old_ao_config_chanlist(struct comedi_device *dev, range = CR_RANGE(chanspec[i]); conf = AO_Channel(chan); - if (board->ao_unipolar) { - if ((range & 1) == 0) { - conf |= AO_Bipolar; - invert = (1 << (board->aobits - 1)); - } else { - invert = 0; - } - if (range & 2) - conf |= AO_Ext_Ref; - } else { + if (comedi_range_is_bipolar(s, range)) { conf |= AO_Bipolar; - invert = (1 << (board->aobits - 1)); + invert = (s->maxdata + 1) >> 1; + } else { + invert = 0; } + if (comedi_range_is_external(s, range)) + conf |= AO_Ext_Ref; /* not all boards can deglitch, but this shouldn't hurt */ if (chanspec[i] & CR_DEGLITCH) @@ -2844,7 +2901,7 @@ static int ni_old_ao_config_chanlist(struct comedi_device *dev, conf |= (CR_AREF(chanspec[i]) == AREF_OTHER) ? AO_Ground_Ref : 0; - ni_writew(conf, AO_Configuration); + ni_writew(dev, conf, AO_Configuration); devpriv->ao_conf[chan] = conf; } return invert; @@ -2855,9 +2912,9 @@ static int ni_ao_config_chanlist(struct comedi_device *dev, unsigned int chanspec[], unsigned int n_chans, int timed) { - const struct ni_board_struct *board = comedi_board(dev); + struct ni_private *devpriv = dev->private; - if (board->reg_type & ni_reg_m_series_mask) + if (devpriv->is_m_series) return ni_m_series_ao_config_chanlist(dev, s, chanspec, n_chans, timed); else @@ -2865,56 +2922,75 @@ static int ni_ao_config_chanlist(struct comedi_device *dev, } static int ni_ao_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { struct ni_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + int i; - data[0] = devpriv->ao[CR_CHAN(insn->chanspec)]; + for (i = 0; i < insn->n; i++) + data[i] = devpriv->ao[chan]; - return 1; + return insn->n; } static int ni_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); - unsigned int invert; - - invert = ni_ao_config_chanlist(dev, s, &insn->chanspec, 1, 0); - - devpriv->ao[chan] = data[0]; - - if (board->reg_type & ni_reg_m_series_mask) { - ni_writew(data[0], M_Offset_DAC_Direct_Data(chan)); - } else - ni_writew(data[0] ^ invert, - (chan) ? DAC1_Direct_Data : DAC0_Direct_Data); + unsigned int range = CR_RANGE(insn->chanspec); + int reg; + int i; - return 1; -} + if (devpriv->is_6xxx) { + ni_ao_win_outw(dev, 1 << chan, AO_Immediate_671x); -static int ni_ao_insn_write_671x(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - const struct ni_board_struct *board = comedi_board(dev); - struct ni_private *devpriv = dev->private; - unsigned int chan = CR_CHAN(insn->chanspec); - unsigned int invert; - - ao_win_out(1 << chan, AO_Immediate_671x); - invert = 1 << (board->aobits - 1); + reg = DACx_Direct_Data_671x(chan); + } else if (devpriv->is_m_series) { + reg = M_Offset_DAC_Direct_Data(chan); + } else { + reg = (chan) ? DAC1_Direct_Data : DAC0_Direct_Data; + } ni_ao_config_chanlist(dev, s, &insn->chanspec, 1, 0); - devpriv->ao[chan] = data[0]; - ao_win_out(data[0] ^ invert, DACx_Direct_Data_671x(chan)); + for (i = 0; i < insn->n; i++) { + unsigned int val = data[i]; + + devpriv->ao[chan] = val; + + if (devpriv->is_6xxx) { + /* + * 6xxx boards have bipolar outputs, munge the + * unsigned comedi values to 2's complement + */ + val = comedi_offset_munge(s, val); + + ni_ao_win_outw(dev, val, reg); + } else if (devpriv->is_m_series) { + /* + * M-series boards use offset binary values for + * bipolar and uinpolar outputs + */ + ni_writew(dev, val, reg); + } else { + /* + * Non-M series boards need two's complement values + * for bipolar ranges. + */ + if (comedi_range_is_bipolar(s, range)) + val = comedi_offset_munge(s, val); + + ni_writew(dev, val, reg); + } + } - return 1; + return insn->n; } static int ni_ao_insn_config(struct comedi_device *dev, @@ -2937,7 +3013,6 @@ static int ni_ao_insn_config(struct comedi_device *dev, break; default: return -EINVAL; - break; } return 0; default: @@ -2951,7 +3026,6 @@ static int ni_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trig_num) { - const struct ni_board_struct *board __maybe_unused = comedi_board(dev); struct ni_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; int ret; @@ -2971,8 +3045,8 @@ static int ni_ao_inttrig(struct comedi_device *dev, AO_FIFO_Interrupt_Enable | AO_Error_Interrupt_Enable, 0); interrupt_b_bits = AO_Error_Interrupt_Enable; #ifdef PCIDMA - devpriv->stc_writew(dev, 1, DAC_FIFO_Clear); - if (board->reg_type & ni_reg_6xxx_mask) + ni_stc_writew(dev, 1, DAC_FIFO_Clear); + if (devpriv->is_6xxx) ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x); ret = ni_ao_setup_MITE_dma(dev); if (ret) @@ -2988,35 +3062,36 @@ static int ni_ao_inttrig(struct comedi_device *dev, interrupt_b_bits |= AO_FIFO_Interrupt_Enable; #endif - devpriv->stc_writew(dev, devpriv->ao_mode3 | AO_Not_An_UPDATE, - AO_Mode_3_Register); - devpriv->stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); + 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); /* wait for DACs to be loaded */ for (i = 0; i < timeout; i++) { udelay(1); - if ((devpriv->stc_readw(dev, - Joint_Status_2_Register) & + if ((ni_stc_readw(dev, Joint_Status_2_Register) & AO_TMRDACWRs_In_Progress_St) == 0) break; } if (i == timeout) { - comedi_error(dev, - "timed out waiting for AO_TMRDACWRs_In_Progress_St to clear"); + dev_err(dev->class_dev, + "timed out waiting for AO_TMRDACWRs_In_Progress_St to clear\n"); return -EIO; } - /* stc manual says we are need to clear error interrupt after AO_TMRDACWRs_In_Progress_St clears */ - devpriv->stc_writew(dev, AO_Error_Interrupt_Ack, - Interrupt_B_Ack_Register); + /* + * 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_set_bits(dev, Interrupt_B_Enable_Register, interrupt_b_bits, 1); - devpriv->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, devpriv->ao_cmd1 | + AO_UI_Arm | AO_UC_Arm | AO_BC_Arm | + AO_DAC1_Update_Mode | AO_DAC0_Update_Mode, + AO_Command_1_Register); - devpriv->stc_writew(dev, devpriv->ao_cmd2 | AO_START1_Pulse, - AO_Command_2_Register); + ni_stc_writew(dev, devpriv->ao_cmd2 | AO_START1_Pulse, + AO_Command_2_Register); return 0; } @@ -3031,16 +3106,16 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) unsigned trigvar; if (dev->irq == 0) { - comedi_error(dev, "cannot run command without an irq"); + dev_err(dev->class_dev, "cannot run command without an irq\n"); return -EIO; } - devpriv->stc_writew(dev, AO_Configuration_Start, Joint_Reset_Register); + ni_stc_writew(dev, AO_Configuration_Start, Joint_Reset_Register); - devpriv->stc_writew(dev, AO_Disarm, AO_Command_1_Register); + ni_stc_writew(dev, AO_Disarm, AO_Command_1_Register); - if (board->reg_type & ni_reg_6xxx_mask) { - ao_win_out(CLEAR_WG, AO_Misc_611x); + if (devpriv->is_6xxx) { + ni_ao_win_outw(dev, CLEAR_WG, AO_Misc_611x); bits = 0; for (i = 0; i < cmd->chanlist_len; i++) { @@ -3048,9 +3123,9 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) chan = CR_CHAN(cmd->chanlist[i]); bits |= 1 << chan; - ao_win_out(chan, AO_Waveform_Generation_611x); + ni_ao_win_outw(dev, chan, AO_Waveform_Generation_611x); } - ao_win_out(bits, AO_Timed_611x); + ni_ao_win_outw(dev, bits, AO_Timed_611x); } ni_ao_config_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, 1); @@ -3062,15 +3137,15 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ao_mode1 &= ~AO_Continuous; devpriv->ao_mode1 |= AO_Trigger_Once; } - devpriv->stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); + ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); 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; - devpriv->stc_writew(dev, devpriv->ao_trigger_select, - AO_Trigger_Select_Register); + ni_stc_writew(dev, devpriv->ao_trigger_select, + AO_Trigger_Select_Register); break; case TRIG_EXT: devpriv->ao_trigger_select = @@ -3079,52 +3154,50 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 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 */ - devpriv->stc_writew(dev, devpriv->ao_trigger_select, - AO_Trigger_Select_Register); + ni_stc_writew(dev, devpriv->ao_trigger_select, + AO_Trigger_Select_Register); break; default: BUG(); break; } devpriv->ao_mode3 &= ~AO_Trigger_Length; - devpriv->stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); + ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); - devpriv->stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); + ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); devpriv->ao_mode2 &= ~AO_BC_Initial_Load_Source; - devpriv->stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); + ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); if (cmd->stop_src == TRIG_NONE) - devpriv->stc_writel(dev, 0xffffff, AO_BC_Load_A_Register); + ni_stc_writel(dev, 0xffffff, AO_BC_Load_A_Register); else - devpriv->stc_writel(dev, 0, AO_BC_Load_A_Register); - devpriv->stc_writew(dev, AO_BC_Load, AO_Command_1_Register); + 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; - devpriv->stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); + ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); switch (cmd->stop_src) { case TRIG_COUNT: - if (board->reg_type & ni_reg_m_series_mask) { + if (devpriv->is_m_series) { /* this is how the NI example code does it for m-series boards, verified correct with 6259 */ - devpriv->stc_writel(dev, cmd->stop_arg - 1, - AO_UC_Load_A_Register); - devpriv->stc_writew(dev, AO_UC_Load, - AO_Command_1_Register); + ni_stc_writel(dev, cmd->stop_arg - 1, + AO_UC_Load_A_Register); + ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register); } else { - devpriv->stc_writel(dev, cmd->stop_arg, - AO_UC_Load_A_Register); - devpriv->stc_writew(dev, AO_UC_Load, - AO_Command_1_Register); - devpriv->stc_writel(dev, cmd->stop_arg - 1, - AO_UC_Load_A_Register); + ni_stc_writel(dev, cmd->stop_arg, + AO_UC_Load_A_Register); + ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register); + ni_stc_writel(dev, cmd->stop_arg - 1, + AO_UC_Load_A_Register); } break; case TRIG_NONE: - devpriv->stc_writel(dev, 0xffffff, AO_UC_Load_A_Register); - devpriv->stc_writew(dev, AO_UC_Load, AO_Command_1_Register); - devpriv->stc_writel(dev, 0xffffff, AO_UC_Load_A_Register); + 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); break; default: - devpriv->stc_writel(dev, 0, AO_UC_Load_A_Register); - devpriv->stc_writew(dev, AO_UC_Load, AO_Command_1_Register); - devpriv->stc_writel(dev, cmd->stop_arg, AO_UC_Load_A_Register); + 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); } devpriv->ao_mode1 &= @@ -3136,9 +3209,9 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) trigvar = ni_ns_to_timer(dev, cmd->scan_begin_arg, TRIG_ROUND_NEAREST); - devpriv->stc_writel(dev, 1, AO_UI_Load_A_Register); - devpriv->stc_writew(dev, AO_UI_Load, AO_Command_1_Register); - devpriv->stc_writel(dev, trigvar, AO_UI_Load_A_Register); + 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); break; case TRIG_EXT: devpriv->ao_mode1 |= @@ -3151,40 +3224,38 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) BUG(); break; } - devpriv->stc_writew(dev, devpriv->ao_cmd2, AO_Command_2_Register); - devpriv->stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); + 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); - devpriv->stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); + ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); if (cmd->scan_end_arg > 1) { devpriv->ao_mode1 |= AO_Multiple_Channels; - devpriv->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); + 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); } else { unsigned bits; + devpriv->ao_mode1 &= ~AO_Multiple_Channels; bits = AO_UPDATE_Output_Select(AO_Update_Output_High_Z); - if (board->reg_type & - (ni_reg_m_series_mask | ni_reg_6xxx_mask)) { + if (devpriv->is_m_series || devpriv->is_6xxx) { bits |= AO_Number_Of_Channels(0); } else { bits |= AO_Number_Of_Channels(CR_CHAN(cmd->chanlist[0])); } - devpriv->stc_writew(dev, bits, AO_Output_Control_Register); + ni_stc_writew(dev, bits, AO_Output_Control_Register); } - devpriv->stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); + ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); - devpriv->stc_writew(dev, AO_DAC0_Update_Mode | AO_DAC1_Update_Mode, - AO_Command_1_Register); + ni_stc_writew(dev, AO_DAC0_Update_Mode | AO_DAC1_Update_Mode, + AO_Command_1_Register); devpriv->ao_mode3 |= AO_Stop_On_Overrun_Error; - devpriv->stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); + ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); devpriv->ao_mode2 &= ~AO_FIFO_Mode_Mask; #ifdef PCIDMA @@ -3193,7 +3264,7 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ao_mode2 |= AO_FIFO_Mode_HF; #endif devpriv->ao_mode2 &= ~AO_FIFO_Retransmit_Enable; - devpriv->stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); + ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); bits = AO_BC_Source_Select | AO_UPDATE_Pulse_Width | AO_TMRDACWR_Pulse_Width; @@ -3204,18 +3275,18 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) #if 0 /* F Hess: windows driver does not set AO_Number_Of_DAC_Packages bit for 6281, verified with bus analyzer. */ - if (board->reg_type & ni_reg_m_series_mask) + if (devpriv->is_m_series) bits |= AO_Number_Of_DAC_Packages; #endif - devpriv->stc_writew(dev, bits, AO_Personal_Register); + ni_stc_writew(dev, bits, AO_Personal_Register); /* enable sending of ao dma requests */ - devpriv->stc_writew(dev, AO_AOFREQ_Enable, AO_Start_Select_Register); + ni_stc_writew(dev, AO_AOFREQ_Enable, AO_Start_Select_Register); - devpriv->stc_writew(dev, AO_Configuration_End, Joint_Reset_Register); + ni_stc_writew(dev, AO_Configuration_End, Joint_Reset_Register); if (cmd->stop_src == TRIG_COUNT) { - devpriv->stc_writew(dev, AO_BC_TC_Interrupt_Ack, - Interrupt_B_Ack_Register); + 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); } @@ -3299,9 +3370,7 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, cmd->scan_begin_arg = ni_timer_to_ns(dev, ni_ns_to_timer(dev, cmd->scan_begin_arg, - cmd-> - flags & - TRIG_ROUND_MASK)); + cmd->flags)); if (tmp != cmd->scan_begin_arg) err++; } @@ -3313,51 +3382,45 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s) { - const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; - /* devpriv->ao0p=0x0000; */ - /* ni_writew(devpriv->ao0p,AO_Configuration); */ - - /* devpriv->ao1p=AO_Channel(1); */ - /* ni_writew(devpriv->ao1p,AO_Configuration); */ - ni_release_ao_mite_channel(dev); - devpriv->stc_writew(dev, AO_Configuration_Start, Joint_Reset_Register); - devpriv->stc_writew(dev, AO_Disarm, AO_Command_1_Register); + 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); - devpriv->stc_writew(dev, AO_BC_Source_Select, AO_Personal_Register); - devpriv->stc_writew(dev, 0x3f98, Interrupt_B_Ack_Register); - devpriv->stc_writew(dev, AO_BC_Source_Select | AO_UPDATE_Pulse_Width | - AO_TMRDACWR_Pulse_Width, AO_Personal_Register); - devpriv->stc_writew(dev, 0, AO_Output_Control_Register); - devpriv->stc_writew(dev, 0, AO_Start_Select_Register); + 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); devpriv->ao_cmd1 = 0; - devpriv->stc_writew(dev, devpriv->ao_cmd1, AO_Command_1_Register); + ni_stc_writew(dev, devpriv->ao_cmd1, AO_Command_1_Register); devpriv->ao_cmd2 = 0; - devpriv->stc_writew(dev, devpriv->ao_cmd2, AO_Command_2_Register); + ni_stc_writew(dev, devpriv->ao_cmd2, AO_Command_2_Register); devpriv->ao_mode1 = 0; - devpriv->stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); + ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); devpriv->ao_mode2 = 0; - devpriv->stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); - if (board->reg_type & ni_reg_m_series_mask) + ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); + if (devpriv->is_m_series) devpriv->ao_mode3 = AO_Last_Gate_Disable; else devpriv->ao_mode3 = 0; - devpriv->stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); + ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); devpriv->ao_trigger_select = 0; - devpriv->stc_writew(dev, devpriv->ao_trigger_select, - AO_Trigger_Select_Register); - if (board->reg_type & ni_reg_6xxx_mask) { + ni_stc_writew(dev, devpriv->ao_trigger_select, + AO_Trigger_Select_Register); + if (devpriv->is_6xxx) { unsigned immediate_bits = 0; unsigned i; + for (i = 0; i < s->n_chan; ++i) immediate_bits |= 1 << i; - ao_win_out(immediate_bits, AO_Immediate_671x); - ao_win_out(CLEAR_WG, AO_Misc_611x); + ni_ao_win_outw(dev, immediate_bits, AO_Immediate_671x); + ni_ao_win_outw(dev, CLEAR_WG, AO_Misc_611x); } - devpriv->stc_writew(dev, AO_Configuration_End, Joint_Reset_Register); + ni_stc_writew(dev, AO_Configuration_End, Joint_Reset_Register); return 0; } @@ -3378,7 +3441,7 @@ static int ni_dio_insn_config(struct comedi_device *dev, devpriv->dio_control &= ~DIO_Pins_Dir_Mask; devpriv->dio_control |= DIO_Pins_Dir(s->io_bits); - devpriv->stc_writew(dev, devpriv->dio_control, DIO_Control_Register); + ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); return insn->n; } @@ -3397,11 +3460,10 @@ static int ni_dio_insn_bits(struct comedi_device *dev, if (comedi_dio_update_state(s, data)) { devpriv->dio_output &= ~DIO_Parallel_Data_Mask; devpriv->dio_output |= DIO_Parallel_Data_Out(s->state); - devpriv->stc_writew(dev, devpriv->dio_output, - DIO_Output_Register); + ni_stc_writew(dev, devpriv->dio_output, DIO_Output_Register); } - data[1] = devpriv->stc_readw(dev, DIO_Parallel_Input_Register); + data[1] = ni_stc_readw(dev, DIO_Parallel_Input_Register); return insn->n; } @@ -3411,14 +3473,13 @@ static int ni_m_series_dio_insn_config(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct ni_private *devpriv __maybe_unused = dev->private; int ret; ret = comedi_dio_insn_config(dev, s, insn, data, 0); if (ret) return ret; - ni_writel(s->io_bits, M_Offset_DIO_Direction); + ni_writel(dev, s->io_bits, M_Offset_DIO_Direction); return insn->n; } @@ -3428,12 +3489,10 @@ static int ni_m_series_dio_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct ni_private *devpriv __maybe_unused = dev->private; - if (comedi_dio_update_state(s, data)) - ni_writel(s->state, M_Offset_Static_Digital_Output); + ni_writel(dev, s->state, M_Offset_Static_Digital_Output); - data[1] = ni_readl(M_Offset_Static_Digital_Input); + data[1] = ni_readl(dev, M_Offset_Static_Digital_Input); return insn->n; } @@ -3508,57 +3567,18 @@ static int ni_cdio_cmdtest(struct comedi_device *dev, return 0; } -static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) -{ - struct ni_private *devpriv __maybe_unused = dev->private; - const struct comedi_cmd *cmd = &s->async->cmd; - unsigned cdo_mode_bits = CDO_FIFO_Mode_Bit | CDO_Halt_On_Error_Bit; - int retval; - - ni_writel(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; - } - if (cmd->scan_begin_arg & CR_INVERT) - cdo_mode_bits |= CDO_Polarity_Bit; - ni_writel(cdo_mode_bits, M_Offset_CDO_Mode); - if (s->io_bits) { - ni_writel(s->state, M_Offset_CDO_FIFO_Data); - ni_writel(CDO_SW_Update_Bit, M_Offset_CDIO_Command); - ni_writel(s->io_bits, M_Offset_CDO_Mask_Enable); - } else { - comedi_error(dev, - "attempted to run digital output command with no lines configured as outputs"); - return -EIO; - } - retval = ni_request_cdo_mite_channel(dev); - if (retval < 0) - return retval; - - s->async->inttrig = ni_cdo_inttrig; - - return 0; -} - static int ni_cdo_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trig_num) { + struct comedi_cmd *cmd = &s->async->cmd; + const unsigned timeout = 1000; + int retval = 0; + unsigned i; #ifdef PCIDMA struct ni_private *devpriv = dev->private; unsigned long flags; #endif - struct comedi_cmd *cmd = &s->async->cmd; - int retval = 0; - unsigned i; - const unsigned timeout = 1000; if (trig_num != cmd->start_arg) return -EINVAL; @@ -3574,7 +3594,7 @@ static int ni_cdo_inttrig(struct comedi_device *dev, mite_prep_dma(devpriv->cdo_mite_chan, 32, 32); mite_dma_arm(devpriv->cdo_mite_chan); } else { - comedi_error(dev, "BUG: no cdo mite channel?"); + dev_err(dev->class_dev, "BUG: no cdo mite channel?\n"); retval = -EIO; } spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); @@ -3583,53 +3603,88 @@ static int ni_cdo_inttrig(struct comedi_device *dev, #endif /* * XXX not sure what interrupt C group does -* ni_writeb(Interrupt_Group_C_Enable_Bit, +* ni_writeb(dev, Interrupt_Group_C_Enable_Bit, * M_Offset_Interrupt_C_Enable); wait for dma to fill output fifo */ for (i = 0; i < timeout; ++i) { - if (ni_readl(M_Offset_CDIO_Status) & CDO_FIFO_Full_Bit) + if (ni_readl(dev, M_Offset_CDIO_Status) & CDO_FIFO_Full_Bit) break; udelay(10); } if (i == timeout) { - comedi_error(dev, "dma failed to fill cdo fifo!"); - ni_cdio_cancel(dev, s); + dev_err(dev->class_dev, "dma failed to fill cdo fifo!\n"); + s->cancel(dev, s); return -EIO; } - ni_writel(CDO_Arm_Bit | CDO_Error_Interrupt_Enable_Set_Bit | - CDO_Empty_FIFO_Interrupt_Enable_Set_Bit, + ni_writel(dev, CDO_Arm_Bit | CDO_Error_Interrupt_Enable_Set_Bit | + CDO_Empty_FIFO_Interrupt_Enable_Set_Bit, M_Offset_CDIO_Command); return retval; } -static int ni_cdio_cancel(struct comedi_device *dev, struct comedi_subdevice *s) +static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - struct ni_private *devpriv __maybe_unused = dev->private; + const struct comedi_cmd *cmd = &s->async->cmd; + unsigned cdo_mode_bits = CDO_FIFO_Mode_Bit | CDO_Halt_On_Error_Bit; + 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; + } + if (cmd->scan_begin_arg & CR_INVERT) + cdo_mode_bits |= CDO_Polarity_Bit; + ni_writel(dev, cdo_mode_bits, M_Offset_CDO_Mode); + 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); + } else { + dev_err(dev->class_dev, + "attempted to run digital output command with no lines configured as outputs\n"); + return -EIO; + } + retval = ni_request_cdo_mite_channel(dev); + if (retval < 0) + return retval; + + s->async->inttrig = ni_cdo_inttrig; - ni_writel(CDO_Disarm_Bit | CDO_Error_Interrupt_Enable_Clear_Bit | - CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit | - CDO_FIFO_Request_Interrupt_Enable_Clear_Bit, + return 0; +} + +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(0, +* XXX not sure what interrupt C group does ni_writeb(dev, 0, * M_Offset_Interrupt_C_Enable); */ - ni_writel(0, M_Offset_CDO_Mask_Enable); + ni_writel(dev, 0, M_Offset_CDO_Mask_Enable); ni_release_cdo_mite_channel(dev); return 0; } static void handle_cdio_interrupt(struct comedi_device *dev) { - const struct ni_board_struct *board = comedi_board(dev); - struct ni_private *devpriv __maybe_unused = dev->private; + struct ni_private *devpriv = dev->private; unsigned cdio_status; struct comedi_subdevice *s = &dev->subdevices[NI_DIO_SUBDEV]; #ifdef PCIDMA unsigned long flags; #endif - if ((board->reg_type & ni_reg_m_series_mask) == 0) + if (!devpriv->is_m_series) return; #ifdef PCIDMA spin_lock_irqsave(&devpriv->mite_channel_lock, flags); @@ -3646,112 +3701,21 @@ static void handle_cdio_interrupt(struct comedi_device *dev) spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); #endif - cdio_status = ni_readl(M_Offset_CDIO_Status); + cdio_status = ni_readl(dev, M_Offset_CDIO_Status); if (cdio_status & (CDO_Overrun_Bit | CDO_Underflow_Bit)) { - /* printk("cdio error: statux=0x%x\n", cdio_status); */ - ni_writel(CDO_Error_Interrupt_Confirm_Bit, M_Offset_CDIO_Command); /* XXX just guessing this is needed and does something useful */ + /* XXX just guessing this is needed and does something useful */ + ni_writel(dev, CDO_Error_Interrupt_Confirm_Bit, + M_Offset_CDIO_Command); s->async->events |= COMEDI_CB_OVERFLOW; } if (cdio_status & CDO_FIFO_Empty_Bit) { - /* printk("cdio fifo empty\n"); */ - ni_writel(CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit, + ni_writel(dev, CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit, M_Offset_CDIO_Command); /* s->async->events |= COMEDI_CB_EOA; */ } cfc_handle_events(dev, s); } -static int ni_serial_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct ni_private *devpriv = dev->private; - int err = insn->n; - unsigned char byte_out, byte_in = 0; - - if (insn->n != 2) - return -EINVAL; - - switch (data[0]) { - case INSN_CONFIG_SERIAL_CLOCK: - devpriv->serial_hw_mode = 1; - devpriv->dio_control |= DIO_HW_Serial_Enable; - - if (data[1] == SERIAL_DISABLED) { - devpriv->serial_hw_mode = 0; - devpriv->dio_control &= ~(DIO_HW_Serial_Enable | - DIO_Software_Serial_Control); - 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; - 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; - 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 - 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->serial_hw_mode = 0; - data[1] = (data[1] / 1000) * 1000; - devpriv->serial_interval_ns = data[1]; - } - - devpriv->stc_writew(dev, devpriv->dio_control, - DIO_Control_Register); - devpriv->stc_writew(dev, devpriv->clock_and_fout, - Clock_and_FOUT_Register); - return 1; - - break; - - case INSN_CONFIG_BIDIRECTIONAL_DATA: - - if (devpriv->serial_interval_ns == 0) - return -EINVAL; - - byte_out = data[1] & 0xFF; - - if (devpriv->serial_hw_mode) { - err = ni_serial_hw_readwrite8(dev, s, byte_out, - &byte_in); - } else if (devpriv->serial_interval_ns > 0) { - err = ni_serial_sw_readwrite8(dev, s, byte_out, - &byte_in); - } else { - printk("ni_serial_insn_config: serial disabled!\n"); - return -EINVAL; - } - if (err < 0) - return err; - data[1] = byte_in & 0xFF; - return insn->n; - - break; - default: - return -EINVAL; - } - -} - static int ni_serial_hw_readwrite8(struct comedi_device *dev, struct comedi_subdevice *s, unsigned char data_out, @@ -3763,28 +3727,27 @@ static int ni_serial_hw_readwrite8(struct comedi_device *dev, devpriv->dio_output &= ~DIO_Serial_Data_Mask; devpriv->dio_output |= DIO_Serial_Data_Out(data_out); - devpriv->stc_writew(dev, devpriv->dio_output, DIO_Output_Register); + ni_stc_writew(dev, devpriv->dio_output, DIO_Output_Register); - status1 = devpriv->stc_readw(dev, Joint_Status_1_Register); + status1 = ni_stc_readw(dev, Joint_Status_1_Register); if (status1 & DIO_Serial_IO_In_Progress_St) { err = -EBUSY; goto Error; } devpriv->dio_control |= DIO_HW_Serial_Start; - devpriv->stc_writew(dev, devpriv->dio_control, DIO_Control_Register); + ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); devpriv->dio_control &= ~DIO_HW_Serial_Start; /* Wait until STC says we're done, but don't loop infinitely. */ - while ((status1 = - devpriv->stc_readw(dev, - Joint_Status_1_Register)) & + while ((status1 = ni_stc_readw(dev, Joint_Status_1_Register)) & DIO_Serial_IO_In_Progress_St) { /* Delay one bit per loop */ udelay((devpriv->serial_interval_ns + 999) / 1000); if (--count < 0) { - printk - ("ni_serial_hw_readwrite8: SPI serial I/O didn't finish in time!\n"); + dev_err(dev->class_dev, + "%s: SPI serial I/O didn't finish in time!\n", + __func__); err = -ETIME; goto Error; } @@ -3795,10 +3758,10 @@ static int ni_serial_hw_readwrite8(struct comedi_device *dev, udelay((devpriv->serial_interval_ns + 999) / 1000); if (data_in != NULL) - *data_in = devpriv->stc_readw(dev, DIO_Serial_Input_Register); + *data_in = ni_stc_readw(dev, DIO_Serial_Input_Register); Error: - devpriv->stc_writew(dev, devpriv->dio_control, DIO_Control_Register); + ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); return err; } @@ -3821,29 +3784,23 @@ static int ni_serial_sw_readwrite8(struct comedi_device *dev, devpriv->dio_output &= ~DIO_SDOUT; if (data_out & mask) devpriv->dio_output |= DIO_SDOUT; - devpriv->stc_writew(dev, devpriv->dio_output, - DIO_Output_Register); + ni_stc_writew(dev, devpriv->dio_output, DIO_Output_Register); /* 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; - devpriv->stc_writew(dev, devpriv->dio_control, - DIO_Control_Register); + ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); udelay((devpriv->serial_interval_ns + 999) / 2000); devpriv->dio_control &= ~DIO_Software_Serial_Control; - devpriv->stc_writew(dev, devpriv->dio_control, - DIO_Control_Register); + ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); udelay((devpriv->serial_interval_ns + 999) / 2000); /* Input current bit */ - if (devpriv->stc_readw(dev, - DIO_Parallel_Input_Register) & DIO_SDIN) { - /* printk("DIO_P_I_R: 0x%x\n", devpriv->stc_readw(dev, DIO_Parallel_Input_Register)); */ + if (ni_stc_readw(dev, DIO_Parallel_Input_Register) & DIO_SDIN) input |= mask; - } } if (data_in) @@ -3852,14 +3809,96 @@ static int ni_serial_sw_readwrite8(struct comedi_device *dev, return 0; } -static void mio_common_detach(struct comedi_device *dev) +static int ni_serial_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct ni_private *devpriv = dev->private; + int err = insn->n; + unsigned char byte_out, byte_in = 0; - if (devpriv) { - if (devpriv->counter_dev) - ni_gpct_device_destroy(devpriv->counter_dev); + if (insn->n != 2) + return -EINVAL; + + switch (data[0]) { + case INSN_CONFIG_SERIAL_CLOCK: + devpriv->serial_hw_mode = 1; + devpriv->dio_control |= DIO_HW_Serial_Enable; + + if (data[1] == SERIAL_DISABLED) { + devpriv->serial_hw_mode = 0; + devpriv->dio_control &= ~(DIO_HW_Serial_Enable | + DIO_Software_Serial_Control); + 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; + 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; + 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 + 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->serial_hw_mode = 0; + data[1] = (data[1] / 1000) * 1000; + devpriv->serial_interval_ns = data[1]; + } + + ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); + ni_stc_writew(dev, devpriv->clock_and_fout, + Clock_and_FOUT_Register); + return 1; + + break; + + case INSN_CONFIG_BIDIRECTIONAL_DATA: + + if (devpriv->serial_interval_ns == 0) + return -EINVAL; + + byte_out = data[1] & 0xFF; + + if (devpriv->serial_hw_mode) { + err = ni_serial_hw_readwrite8(dev, s, byte_out, + &byte_in); + } else if (devpriv->serial_interval_ns > 0) { + err = ni_serial_sw_readwrite8(dev, s, byte_out, + &byte_in); + } else { + dev_err(dev->class_dev, "%s: serial disabled!\n", + __func__); + return -EINVAL; + } + if (err < 0) + return err; + data[1] = byte_in & 0xFF; + return insn->n; + + break; + default: + return -EINVAL; } + } static void init_ao_67xx(struct comedi_device *dev, struct comedi_subdevice *s) @@ -3870,12 +3909,13 @@ static void init_ao_67xx(struct comedi_device *dev, struct comedi_subdevice *s) ni_ao_win_outw(dev, AO_Channel(i) | 0x0, AO_Configuration_2_67xx); } - ao_win_out(0x0, AO_Later_Single_Point_Updates); + ni_ao_win_outw(dev, 0x0, AO_Later_Single_Point_Updates); } static unsigned ni_gpct_to_stc_register(enum ni_gpct_register reg) { unsigned stc_register; + switch (reg) { case NITIO_G0_AUTO_INC: stc_register = G_Autoincrement_Register(0); @@ -3960,7 +4000,6 @@ static unsigned ni_gpct_to_stc_register(enum ni_gpct_register reg) __func__, reg); BUG(); return 0; - break; } return stc_register; } @@ -3969,7 +4008,6 @@ 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; - struct ni_private *devpriv = dev->private; 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; @@ -3981,28 +4019,28 @@ static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits, switch (reg) { /* m-series-only registers */ case NITIO_G0_CNT_MODE: - ni_writew(bits, M_Offset_G0_Counting_Mode); + ni_writew(dev, bits, M_Offset_G0_Counting_Mode); break; case NITIO_G1_CNT_MODE: - ni_writew(bits, M_Offset_G1_Counting_Mode); + ni_writew(dev, bits, M_Offset_G1_Counting_Mode); break; case NITIO_G0_GATE2: - ni_writew(bits, M_Offset_G0_Second_Gate); + ni_writew(dev, bits, M_Offset_G0_Second_Gate); break; case NITIO_G1_GATE2: - ni_writew(bits, M_Offset_G1_Second_Gate); + ni_writew(dev, bits, M_Offset_G1_Second_Gate); break; case NITIO_G0_DMA_CFG: - ni_writew(bits, M_Offset_G0_DMA_Config); + ni_writew(dev, bits, M_Offset_G0_DMA_Config); break; case NITIO_G1_DMA_CFG: - ni_writew(bits, M_Offset_G1_DMA_Config); + ni_writew(dev, bits, M_Offset_G1_DMA_Config); break; case NITIO_G0_ABZ: - ni_writew(bits, M_Offset_G0_MSeries_ABZ); + ni_writew(dev, bits, M_Offset_G0_MSeries_ABZ); break; case NITIO_G1_ABZ: - ni_writew(bits, M_Offset_G1_MSeries_ABZ); + ni_writew(dev, bits, M_Offset_G1_MSeries_ABZ); break; /* 32 bit registers */ @@ -4011,7 +4049,7 @@ static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits, case NITIO_G0_LOADB: case NITIO_G1_LOADB: stc_register = ni_gpct_to_stc_register(reg); - devpriv->stc_writel(dev, bits, stc_register); + ni_stc_writel(dev, bits, stc_register); break; /* 16 bit registers */ @@ -4030,7 +4068,7 @@ static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits, /* fall-through */ default: stc_register = ni_gpct_to_stc_register(reg); - devpriv->stc_writew(dev, bits, stc_register); + ni_stc_writew(dev, bits, stc_register); } } @@ -4038,15 +4076,14 @@ static unsigned ni_gpct_read_register(struct ni_gpct *counter, enum ni_gpct_register reg) { struct comedi_device *dev = counter->counter_dev->dev; - struct ni_private *devpriv = dev->private; unsigned stc_register; switch (reg) { /* m-series only registers */ case NITIO_G0_DMA_STATUS: - return ni_readw(M_Offset_G0_DMA_Status); + return ni_readw(dev, M_Offset_G0_DMA_Status); case NITIO_G1_DMA_STATUS: - return ni_readw(M_Offset_G1_DMA_Status); + return ni_readw(dev, M_Offset_G1_DMA_Status); /* 32 bit registers */ case NITIO_G0_HW_SAVE: @@ -4054,506 +4091,101 @@ static unsigned ni_gpct_read_register(struct ni_gpct *counter, case NITIO_G0_SW_SAVE: case NITIO_G1_SW_SAVE: stc_register = ni_gpct_to_stc_register(reg); - return devpriv->stc_readl(dev, stc_register); + return ni_stc_readl(dev, stc_register); /* 16 bit registers */ default: stc_register = ni_gpct_to_stc_register(reg); - return devpriv->stc_readw(dev, stc_register); - break; + return ni_stc_readw(dev, stc_register); } return 0; } static int ni_freq_out_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 ni_private *devpriv = dev->private; + unsigned int val = devpriv->clock_and_fout & FOUT_Divider_mask; + int i; - data[0] = devpriv->clock_and_fout & FOUT_Divider_mask; - return 1; + for (i = 0; i < insn->n; i++) + data[i] = val; + + return insn->n; } static int ni_freq_out_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct ni_private *devpriv = dev->private; - devpriv->clock_and_fout &= ~FOUT_Enable; - devpriv->stc_writew(dev, devpriv->clock_and_fout, - Clock_and_FOUT_Register); - devpriv->clock_and_fout &= ~FOUT_Divider_mask; - devpriv->clock_and_fout |= FOUT_Divider(data[0]); - devpriv->clock_and_fout |= FOUT_Enable; - devpriv->stc_writew(dev, devpriv->clock_and_fout, - Clock_and_FOUT_Register); - return insn->n; -} + 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; -static int ni_set_freq_out_clock(struct comedi_device *dev, - unsigned int clock_source) -{ - struct ni_private *devpriv = dev->private; + /* use the last data value to set the fout divider */ + devpriv->clock_and_fout |= FOUT_Divider(data[insn->n - 1]); - switch (clock_source) { - case NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC: - devpriv->clock_and_fout &= ~FOUT_Timebase_Select; - break; - case NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC: - devpriv->clock_and_fout |= FOUT_Timebase_Select; - break; - default: - return -EINVAL; - } - devpriv->stc_writew(dev, devpriv->clock_and_fout, - Clock_and_FOUT_Register); - return 3; -} - -static void ni_get_freq_out_clock(struct comedi_device *dev, - unsigned int *clock_source, - unsigned int *clock_period_ns) -{ - struct ni_private *devpriv = dev->private; - - if (devpriv->clock_and_fout & FOUT_Timebase_Select) { - *clock_source = NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC; - *clock_period_ns = TIMEBASE_2_NS; - } else { - *clock_source = NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC; - *clock_period_ns = TIMEBASE_1_NS * 2; + devpriv->clock_and_fout |= FOUT_Enable; + ni_stc_writew(dev, devpriv->clock_and_fout, + Clock_and_FOUT_Register); } + return insn->n; } static int ni_freq_out_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { + struct ni_private *devpriv = dev->private; + switch (data[0]) { case INSN_CONFIG_SET_CLOCK_SRC: - return ni_set_freq_out_clock(dev, data[1]); + switch (data[1]) { + case NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC: + devpriv->clock_and_fout &= ~FOUT_Timebase_Select; + break; + case NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC: + devpriv->clock_and_fout |= FOUT_Timebase_Select; + break; + default: + return -EINVAL; + } + ni_stc_writew(dev, devpriv->clock_and_fout, + Clock_and_FOUT_Register); break; case INSN_CONFIG_GET_CLOCK_SRC: - ni_get_freq_out_clock(dev, &data[1], &data[2]); - return 3; - default: + if (devpriv->clock_and_fout & FOUT_Timebase_Select) { + data[1] = NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC; + data[2] = TIMEBASE_2_NS; + } else { + data[1] = NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC; + data[2] = TIMEBASE_1_NS * 2; + } break; - } - return -EINVAL; -} - -static int ni_alloc_private(struct comedi_device *dev) -{ - struct ni_private *devpriv; - - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) - return -ENOMEM; - - spin_lock_init(&devpriv->window_lock); - spin_lock_init(&devpriv->soft_reg_copy_lock); - spin_lock_init(&devpriv->mite_channel_lock); - - return 0; -}; - -static int ni_E_init(struct comedi_device *dev) -{ - const struct ni_board_struct *board = comedi_board(dev); - struct ni_private *devpriv = dev->private; - struct comedi_subdevice *s; - unsigned j; - enum ni_gpct_variant counter_variant; - int ret; - - if (board->n_aochan > MAX_N_AO_CHAN) { - printk("bug! n_aochan > MAX_N_AO_CHAN\n"); + default: return -EINVAL; } - - ret = comedi_alloc_subdevices(dev, NI_NUM_SUBDEVICES); - if (ret) - return ret; - - /* analog input subdevice */ - - s = &dev->subdevices[NI_AI_SUBDEV]; - dev->read_subdev = s; - if (board->n_adchan) { - s->type = COMEDI_SUBD_AI; - s->subdev_flags = - SDF_READABLE | SDF_DIFF | SDF_DITHER | SDF_CMD_READ; - if (board->reg_type != ni_reg_611x) - s->subdev_flags |= SDF_GROUND | SDF_COMMON | SDF_OTHER; - if (board->adbits > 16) - s->subdev_flags |= SDF_LSAMPL; - if (board->reg_type & ni_reg_m_series_mask) - s->subdev_flags |= SDF_SOFT_CALIBRATED; - s->n_chan = board->n_adchan; - s->len_chanlist = 512; - s->maxdata = (1 << board->adbits) - 1; - s->range_table = ni_range_lkup[board->gainlkup]; - s->insn_read = &ni_ai_insn_read; - s->insn_config = &ni_ai_insn_config; - s->do_cmdtest = &ni_ai_cmdtest; - s->do_cmd = &ni_ai_cmd; - s->cancel = &ni_ai_reset; - s->poll = &ni_ai_poll; - s->munge = &ni_ai_munge; -#ifdef PCIDMA - s->async_dma_dir = DMA_FROM_DEVICE; -#endif - } else { - s->type = COMEDI_SUBD_UNUSED; - } - - /* analog output subdevice */ - - s = &dev->subdevices[NI_AO_SUBDEV]; - if (board->n_aochan) { - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE | SDF_DEGLITCH | SDF_GROUND; - if (board->reg_type & ni_reg_m_series_mask) - s->subdev_flags |= SDF_SOFT_CALIBRATED; - s->n_chan = board->n_aochan; - s->maxdata = (1 << board->aobits) - 1; - s->range_table = board->ao_range_table; - s->insn_read = &ni_ao_insn_read; - if (board->reg_type & ni_reg_6xxx_mask) - s->insn_write = &ni_ao_insn_write_671x; - else - s->insn_write = &ni_ao_insn_write; - s->insn_config = &ni_ao_insn_config; -#ifdef PCIDMA - if (board->n_aochan) { - s->async_dma_dir = DMA_TO_DEVICE; -#else - if (board->ao_fifo_depth) { -#endif - dev->write_subdev = s; - s->subdev_flags |= SDF_CMD_WRITE; - s->do_cmd = &ni_ao_cmd; - s->do_cmdtest = &ni_ao_cmdtest; - s->len_chanlist = board->n_aochan; - if ((board->reg_type & ni_reg_m_series_mask) == 0) - s->munge = ni_ao_munge; - } - s->cancel = &ni_ao_reset; - } else { - s->type = COMEDI_SUBD_UNUSED; - } - if ((board->reg_type & ni_reg_67xx_mask)) - init_ao_67xx(dev, s); - - /* digital i/o subdevice */ - - s = &dev->subdevices[NI_DIO_SUBDEV]; - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_WRITABLE | SDF_READABLE; - s->maxdata = 1; - s->io_bits = 0; /* all bits input */ - s->range_table = &range_digital; - s->n_chan = board->num_p0_dio_channels; - if (board->reg_type & ni_reg_m_series_mask) { - s->subdev_flags |= - SDF_LSAMPL | SDF_CMD_WRITE /* | SDF_CMD_READ */; - s->insn_bits = &ni_m_series_dio_insn_bits; - s->insn_config = &ni_m_series_dio_insn_config; - s->do_cmd = &ni_cdio_cmd; - s->do_cmdtest = &ni_cdio_cmdtest; - s->cancel = &ni_cdio_cancel; - s->async_dma_dir = DMA_BIDIRECTIONAL; - s->len_chanlist = s->n_chan; - - ni_writel(CDO_Reset_Bit | CDI_Reset_Bit, M_Offset_CDIO_Command); - ni_writel(s->io_bits, M_Offset_DIO_Direction); - } else { - s->insn_bits = &ni_dio_insn_bits; - s->insn_config = &ni_dio_insn_config; - devpriv->dio_control = DIO_Pins_Dir(s->io_bits); - ni_writew(devpriv->dio_control, DIO_Control_Register); - } - - /* 8255 device */ - s = &dev->subdevices[NI_8255_DIO_SUBDEV]; - if (board->has_8255) { - ret = subdev_8255_init(dev, s, ni_8255_callback, - (unsigned long)dev); - if (ret) - return ret; - } else { - s->type = COMEDI_SUBD_UNUSED; - } - - /* formerly general purpose counter/timer device, but no longer used */ - s = &dev->subdevices[NI_UNUSED_SUBDEV]; - s->type = COMEDI_SUBD_UNUSED; - - /* calibration subdevice -- ai and ao */ - s = &dev->subdevices[NI_CALIBRATION_SUBDEV]; - s->type = COMEDI_SUBD_CALIB; - if (board->reg_type & ni_reg_m_series_mask) { - /* internal PWM analog output used for AI nonlinearity calibration */ - s->subdev_flags = SDF_INTERNAL; - s->insn_config = &ni_m_series_pwm_config; - s->n_chan = 1; - s->maxdata = 0; - ni_writel(0x0, M_Offset_Cal_PWM); - } else if (board->reg_type == ni_reg_6143) { - /* internal PWM analog output used for AI nonlinearity calibration */ - s->subdev_flags = SDF_INTERNAL; - s->insn_config = &ni_6143_pwm_config; - s->n_chan = 1; - s->maxdata = 0; - } else { - s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL; - s->insn_read = &ni_calib_insn_read; - s->insn_write = &ni_calib_insn_write; - caldac_setup(dev, s); - } - - /* EEPROM */ - s = &dev->subdevices[NI_EEPROM_SUBDEV]; - s->type = COMEDI_SUBD_MEMORY; - s->subdev_flags = SDF_READABLE | SDF_INTERNAL; - s->maxdata = 0xff; - if (board->reg_type & ni_reg_m_series_mask) { - s->n_chan = M_SERIES_EEPROM_SIZE; - s->insn_read = &ni_m_series_eeprom_insn_read; - } else { - s->n_chan = 512; - s->insn_read = &ni_eeprom_insn_read; - } - - /* PFI */ - s = &dev->subdevices[NI_PFI_DIO_SUBDEV]; - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; - if (board->reg_type & ni_reg_m_series_mask) { - unsigned i; - s->n_chan = 16; - ni_writew(s->state, M_Offset_PFI_DO); - for (i = 0; i < NUM_PFI_OUTPUT_SELECT_REGS; ++i) { - ni_writew(devpriv->pfi_output_select_reg[i], - M_Offset_PFI_Output_Select(i + 1)); - } - } else { - s->n_chan = 10; - } - s->maxdata = 1; - if (board->reg_type & ni_reg_m_series_mask) - s->insn_bits = &ni_pfi_insn_bits; - s->insn_config = &ni_pfi_insn_config; - ni_set_bits(dev, IO_Bidirection_Pin_Register, ~0, 0); - - /* cs5529 calibration adc */ - s = &dev->subdevices[NI_CS5529_CALIBRATION_SUBDEV]; - if (board->reg_type & ni_reg_67xx_mask) { - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_INTERNAL; - /* one channel for each analog output channel */ - s->n_chan = board->n_aochan; - s->maxdata = (1 << 16) - 1; - s->range_table = &range_unknown; /* XXX */ - s->insn_read = cs5529_ai_insn_read; - s->insn_config = NULL; - init_cs5529(dev); - } else { - s->type = COMEDI_SUBD_UNUSED; - } - - /* Serial */ - s = &dev->subdevices[NI_SERIAL_SUBDEV]; - s->type = COMEDI_SUBD_SERIAL; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; - s->n_chan = 1; - s->maxdata = 0xff; - s->insn_config = ni_serial_insn_config; - devpriv->serial_interval_ns = 0; - devpriv->serial_hw_mode = 0; - - /* RTSI */ - s = &dev->subdevices[NI_RTSI_SUBDEV]; - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; - s->n_chan = 8; - s->maxdata = 1; - s->insn_bits = ni_rtsi_insn_bits; - s->insn_config = ni_rtsi_insn_config; - ni_rtsi_init(dev); - - if (board->reg_type & ni_reg_m_series_mask) - counter_variant = ni_gpct_variant_m_series; - else - counter_variant = ni_gpct_variant_e_series; - devpriv->counter_dev = ni_gpct_device_construct(dev, - &ni_gpct_write_register, - &ni_gpct_read_register, - counter_variant, - NUM_GPCT); - if (!devpriv->counter_dev) - return -ENOMEM; - - /* General purpose counters */ - for (j = 0; j < NUM_GPCT; ++j) { - s = &dev->subdevices[NI_GPCT_SUBDEV(j)]; - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL; - s->n_chan = 3; - if (board->reg_type & ni_reg_m_series_mask) - s->maxdata = 0xffffffff; - else - s->maxdata = 0xffffff; - s->insn_read = ni_tio_insn_read; - s->insn_write = ni_tio_insn_read; - s->insn_config = ni_tio_insn_config; -#ifdef PCIDMA - s->subdev_flags |= SDF_CMD_READ /* | SDF_CMD_WRITE */; - s->do_cmd = &ni_gpct_cmd; - s->len_chanlist = 1; - s->do_cmdtest = ni_tio_cmdtest; - s->cancel = &ni_gpct_cancel; - s->async_dma_dir = DMA_BIDIRECTIONAL; -#endif - s->private = &devpriv->counter_dev->counters[j]; - - devpriv->counter_dev->counters[j].chip_index = 0; - devpriv->counter_dev->counters[j].counter_index = j; - ni_tio_init_counter(&devpriv->counter_dev->counters[j]); - } - - /* Frequency output */ - s = &dev->subdevices[NI_FREQ_OUT_SUBDEV]; - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 1; - s->maxdata = 0xf; - s->insn_read = &ni_freq_out_insn_read; - s->insn_write = &ni_freq_out_insn_write; - s->insn_config = &ni_freq_out_insn_config; - - /* ai configuration */ - s = &dev->subdevices[NI_AI_SUBDEV]; - ni_ai_reset(dev, s); - if ((board->reg_type & ni_reg_6xxx_mask) == 0) { - /* BEAM is this needed for PCI-6143 ?? */ - devpriv->clock_and_fout = - Slow_Internal_Time_Divide_By_2 | - Slow_Internal_Timebase | - Clock_To_Board_Divide_By_2 | - Clock_To_Board | - AI_Output_Divide_By_2 | AO_Output_Divide_By_2; - } else { - devpriv->clock_and_fout = - Slow_Internal_Time_Divide_By_2 | - Slow_Internal_Timebase | - Clock_To_Board_Divide_By_2 | Clock_To_Board; - } - devpriv->stc_writew(dev, devpriv->clock_and_fout, - Clock_and_FOUT_Register); - - /* analog output configuration */ - s = &dev->subdevices[NI_AO_SUBDEV]; - ni_ao_reset(dev, s); - - if (dev->irq) { - devpriv->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 - (dev->irq)) | - Interrupt_B_Output_Select(interrupt_pin - (dev->irq)), - Interrupt_Control_Register); - } - - /* DMA setup */ - ni_writeb(devpriv->ai_ao_select_reg, AI_AO_Select); - ni_writeb(devpriv->g0_g1_select_reg, G0_G1_Select); - - if (board->reg_type & ni_reg_6xxx_mask) { - ni_writeb(0, Magic_611x); - } else if (board->reg_type & ni_reg_m_series_mask) { - int channel; - for (channel = 0; channel < board->n_aochan; ++channel) { - ni_writeb(0xf, M_Offset_AO_Waveform_Order(channel)); - ni_writeb(0x0, - M_Offset_AO_Reference_Attenuation(channel)); - } - ni_writeb(0x0, M_Offset_AO_Calibration); - } - - return 0; + return insn->n; } static int ni_8255_callback(int dir, int port, int data, unsigned long arg) { struct comedi_device *dev = (struct comedi_device *)arg; - struct ni_private *devpriv __maybe_unused = dev->private; if (dir) { - ni_writeb(data, Port_A + 2 * port); + ni_writeb(dev, data, Port_A + 2 * port); return 0; - } else { - return ni_readb(Port_A + 2 * port); } -} -/* - presents the EEPROM as a subdevice -*/ - -static int ni_eeprom_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - data[0] = ni_read_eeprom(dev, CR_CHAN(insn->chanspec)); - - return 1; -} - -/* - reads bytes out of eeprom -*/ - -static int ni_read_eeprom(struct comedi_device *dev, int addr) -{ - struct ni_private *devpriv __maybe_unused = dev->private; - int bit; - int bitstring; - - bitstring = 0x0300 | ((addr & 0x100) << 3) | (addr & 0xff); - ni_writeb(0x04, Serial_Command); - for (bit = 0x8000; bit; bit >>= 1) { - ni_writeb(0x04 | ((bit & bitstring) ? 0x02 : 0), - Serial_Command); - ni_writeb(0x05 | ((bit & bitstring) ? 0x02 : 0), - Serial_Command); - } - bitstring = 0; - for (bit = 0x80; bit; bit >>= 1) { - ni_writeb(0x04, Serial_Command); - ni_writeb(0x05, Serial_Command); - bitstring |= ((ni_readb(XXX_Status) & PROMOUT) ? bit : 0); - } - ni_writeb(0x00, Serial_Command); - - return bitstring; -} - -static int ni_m_series_eeprom_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct ni_private *devpriv = dev->private; - - data[0] = devpriv->eeprom_buffer[CR_CHAN(insn->chanspec)]; - - return 1; + return ni_readb(dev, Port_A + 2 * port); } static int ni_get_pwm_config(struct comedi_device *dev, unsigned int *data) @@ -4567,7 +4199,8 @@ static int ni_get_pwm_config(struct comedi_device *dev, unsigned int *data) static int ni_m_series_pwm_config(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct ni_private *devpriv = dev->private; unsigned up_count, down_count; @@ -4590,7 +4223,6 @@ static int ni_m_series_pwm_config(struct comedi_device *dev, break; default: return -EINVAL; - break; } switch (data[3]) { case TRIG_ROUND_NEAREST: @@ -4608,7 +4240,6 @@ static int ni_m_series_pwm_config(struct comedi_device *dev, break; default: return -EINVAL; - break; } if (up_count * devpriv->clock_ns != data[2] || down_count * devpriv->clock_ns != data[4]) { @@ -4616,26 +4247,24 @@ static int ni_m_series_pwm_config(struct comedi_device *dev, data[4] = down_count * devpriv->clock_ns; return -EAGAIN; } - ni_writel(MSeries_Cal_PWM_High_Time_Bits(up_count) | - MSeries_Cal_PWM_Low_Time_Bits(down_count), + ni_writel(dev, MSeries_Cal_PWM_High_Time_Bits(up_count) | + MSeries_Cal_PWM_Low_Time_Bits(down_count), M_Offset_Cal_PWM); devpriv->pwm_up_count = up_count; devpriv->pwm_down_count = down_count; return 5; - break; case INSN_CONFIG_GET_PWM_OUTPUT: return ni_get_pwm_config(dev, data); - break; default: return -EINVAL; - break; } return 0; } static int ni_6143_pwm_config(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct ni_private *devpriv = dev->private; unsigned up_count, down_count; @@ -4658,7 +4287,6 @@ static int ni_6143_pwm_config(struct comedi_device *dev, break; default: return -EINVAL; - break; } switch (data[3]) { case TRIG_ROUND_NEAREST: @@ -4676,7 +4304,6 @@ static int ni_6143_pwm_config(struct comedi_device *dev, break; default: return -EINVAL; - break; } if (up_count * devpriv->clock_ns != data[2] || down_count * devpriv->clock_ns != data[4]) { @@ -4684,51 +4311,66 @@ static int ni_6143_pwm_config(struct comedi_device *dev, data[4] = down_count * devpriv->clock_ns; return -EAGAIN; } - ni_writel(up_count, Calibration_HighTime_6143); + ni_writel(dev, up_count, Calibration_HighTime_6143); devpriv->pwm_up_count = up_count; - ni_writel(down_count, Calibration_LowTime_6143); + ni_writel(dev, down_count, Calibration_LowTime_6143); devpriv->pwm_down_count = down_count; return 5; - break; case INSN_CONFIG_GET_PWM_OUTPUT: return ni_get_pwm_config(dev, data); default: return -EINVAL; - break; } return 0; } -static void ni_write_caldac(struct comedi_device *dev, int addr, int val); -/* - calibration subdevice -*/ -static int ni_calib_insn_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int pack_mb88341(int addr, int val, int *bitstring) { - ni_write_caldac(dev, CR_CHAN(insn->chanspec), data[0]); + /* + Fujitsu MB 88341 + Note that address bits are reversed. Thanks to + Ingo Keen for noticing this. - return 1; + Note also that the 88341 expects address values from + 1-12, whereas we use channel numbers 0-11. The NI + docs use 1-12, also, so be careful here. + */ + addr++; + *bitstring = ((addr & 0x1) << 11) | + ((addr & 0x2) << 9) | + ((addr & 0x4) << 7) | ((addr & 0x8) << 5) | (val & 0xff); + return 12; } -static int ni_calib_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int pack_dac8800(int addr, int val, int *bitstring) { - struct ni_private *devpriv = dev->private; + *bitstring = ((addr & 0x7) << 8) | (val & 0xff); + return 11; +} - data[0] = devpriv->caldacs[CR_CHAN(insn->chanspec)]; +static int pack_dac8043(int addr, int val, int *bitstring) +{ + *bitstring = val & 0xfff; + return 12; +} - return 1; +static int pack_ad8522(int addr, int val, int *bitstring) +{ + *bitstring = (val & 0xfff) | (addr ? 0xc000 : 0xa000); + return 16; } -static int pack_mb88341(int addr, int val, int *bitstring); -static int pack_dac8800(int addr, int val, int *bitstring); -static int pack_dac8043(int addr, int val, int *bitstring); -static int pack_ad8522(int addr, int val, int *bitstring); -static int pack_ad8804(int addr, int val, int *bitstring); -static int pack_ad8842(int addr, int val, int *bitstring); +static int pack_ad8804(int addr, int val, int *bitstring) +{ + *bitstring = ((addr & 0xf) << 8) | (val & 0xff); + return 12; +} + +static int pack_ad8842(int addr, int val, int *bitstring) +{ + *bitstring = ((addr + 1) << 8) | (val & 0xff); + return 12; +} struct caldac_struct { int n_chans; @@ -4746,6 +4388,64 @@ static struct caldac_struct caldacs[] = { [ad8804_debug] = {16, 8, pack_ad8804}, }; +static void ni_write_caldac(struct comedi_device *dev, int addr, int val) +{ + const struct ni_board_struct *board = comedi_board(dev); + struct ni_private *devpriv = dev->private; + unsigned int loadbit = 0, bits = 0, bit, bitstring = 0; + int i; + int type; + + if (devpriv->caldacs[addr] == val) + return; + devpriv->caldacs[addr] = val; + + for (i = 0; i < 3; i++) { + type = board->caldac[i]; + if (type == caldac_none) + break; + if (addr < caldacs[type].n_chans) { + bits = caldacs[type].packbits(addr, val, &bitstring); + loadbit = SerDacLd(i); + break; + } + addr -= caldacs[type].n_chans; + } + + for (bit = 1 << (bits - 1); bit; bit >>= 1) { + ni_writeb(dev, ((bit & bitstring) ? 0x02 : 0), Serial_Command); + udelay(1); + ni_writeb(dev, 1 | ((bit & bitstring) ? 0x02 : 0), + Serial_Command); + udelay(1); + } + ni_writeb(dev, loadbit, Serial_Command); + udelay(1); + ni_writeb(dev, 0, Serial_Command); +} + +static int ni_calib_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + ni_write_caldac(dev, CR_CHAN(insn->chanspec), data[0]); + + return 1; +} + +static int ni_calib_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct ni_private *devpriv = dev->private; + + data[0] = devpriv->caldacs[CR_CHAN(insn->chanspec)]; + + return 1; +} + static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s) { const struct ni_board_struct *board = comedi_board(dev); @@ -4777,7 +4477,8 @@ static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s) unsigned int *maxdata_list; if (n_chans > MAX_N_CALDACS) - printk("BUG! MAX_N_CALDACS too small\n"); + dev_err(dev->class_dev, + "BUG! MAX_N_CALDACS too small\n"); s->maxdata_list = maxdata_list = devpriv->caldac_maxdata_list; chan = 0; for (i = 0; i < n_dacs; i++) { @@ -4800,221 +4501,106 @@ static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s) } } -static void ni_write_caldac(struct comedi_device *dev, int addr, int val) +static int ni_read_eeprom(struct comedi_device *dev, int addr) { - const struct ni_board_struct *board = comedi_board(dev); - struct ni_private *devpriv = dev->private; - unsigned int loadbit = 0, bits = 0, bit, bitstring = 0; - int i; - int type; - - /* printk("ni_write_caldac: chan=%d val=%d\n",addr,val); */ - if (devpriv->caldacs[addr] == val) - return; - devpriv->caldacs[addr] = val; + int bit; + int bitstring; - for (i = 0; i < 3; i++) { - type = board->caldac[i]; - if (type == caldac_none) - break; - if (addr < caldacs[type].n_chans) { - bits = caldacs[type].packbits(addr, val, &bitstring); - loadbit = SerDacLd(i); - /* printk("caldac: using i=%d addr=%d %x\n",i,addr,bitstring); */ - break; - } - addr -= caldacs[type].n_chans; + bitstring = 0x0300 | ((addr & 0x100) << 3) | (addr & 0xff); + ni_writeb(dev, 0x04, Serial_Command); + 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); } - - for (bit = 1 << (bits - 1); bit; bit >>= 1) { - ni_writeb(((bit & bitstring) ? 0x02 : 0), Serial_Command); - udelay(1); - ni_writeb(1 | ((bit & bitstring) ? 0x02 : 0), Serial_Command); - udelay(1); + 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(loadbit, Serial_Command); - udelay(1); - ni_writeb(0, Serial_Command); -} - -static int pack_mb88341(int addr, int val, int *bitstring) -{ - /* - Fujitsu MB 88341 - Note that address bits are reversed. Thanks to - Ingo Keen for noticing this. - - Note also that the 88341 expects address values from - 1-12, whereas we use channel numbers 0-11. The NI - docs use 1-12, also, so be careful here. - */ - addr++; - *bitstring = ((addr & 0x1) << 11) | - ((addr & 0x2) << 9) | - ((addr & 0x4) << 7) | ((addr & 0x8) << 5) | (val & 0xff); - return 12; -} - -static int pack_dac8800(int addr, int val, int *bitstring) -{ - *bitstring = ((addr & 0x7) << 8) | (val & 0xff); - return 11; -} - -static int pack_dac8043(int addr, int val, int *bitstring) -{ - *bitstring = val & 0xfff; - return 12; -} + ni_writeb(dev, 0x00, Serial_Command); -static int pack_ad8522(int addr, int val, int *bitstring) -{ - *bitstring = (val & 0xfff) | (addr ? 0xc000 : 0xa000); - return 16; + return bitstring; } -static int pack_ad8804(int addr, int val, int *bitstring) +static int ni_eeprom_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - *bitstring = ((addr & 0xf) << 8) | (val & 0xff); - return 12; -} + data[0] = ni_read_eeprom(dev, CR_CHAN(insn->chanspec)); -static int pack_ad8842(int addr, int val, int *bitstring) -{ - *bitstring = ((addr + 1) << 8) | (val & 0xff); - return 12; + return 1; } -#if 0 -/* - * Read the GPCTs current value. - */ -static int GPCT_G_Watch(struct comedi_device *dev, int chan) +static int ni_m_series_eeprom_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - unsigned int hi1, hi2, lo; - - devpriv->gpct_command[chan] &= ~G_Save_Trace; - devpriv->stc_writew(dev, devpriv->gpct_command[chan], - G_Command_Register(chan)); - - devpriv->gpct_command[chan] |= G_Save_Trace; - devpriv->stc_writew(dev, devpriv->gpct_command[chan], - G_Command_Register(chan)); + struct ni_private *devpriv = dev->private; - /* This procedure is used because the two registers cannot - * be read atomically. */ - do { - hi1 = devpriv->stc_readw(dev, G_Save_Register_High(chan)); - lo = devpriv->stc_readw(dev, G_Save_Register_Low(chan)); - hi2 = devpriv->stc_readw(dev, G_Save_Register_High(chan)); - } while (hi1 != hi2); + data[0] = devpriv->eeprom_buffer[CR_CHAN(insn->chanspec)]; - return (hi1 << 16) | lo; + return 1; } -static void GPCT_Reset(struct comedi_device *dev, int chan) +static unsigned ni_old_get_pfi_routing(struct comedi_device *dev, + unsigned chan) { - int temp_ack_reg = 0; - - /* printk("GPCT_Reset..."); */ - devpriv->gpct_cur_operation[chan] = GPCT_RESET; - + /* pre-m-series boards have fixed signals on pfi pins */ switch (chan) { case 0: - devpriv->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; - devpriv->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; - devpriv->stc_writew(dev, devpriv->an_trig_etc_reg, - Analog_Trigger_Etc_Register); - break; + return NI_PFI_OUTPUT_AI_START1; case 1: - devpriv->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; - devpriv->stc_writew(dev, temp_ack_reg, - Interrupt_B_Ack_Register); - - devpriv->an_trig_etc_reg |= GPFO_1_Output_Enable; - devpriv->stc_writew(dev, devpriv->an_trig_etc_reg, - Analog_Trigger_Etc_Register); + return NI_PFI_OUTPUT_AI_START2; + case 2: + return NI_PFI_OUTPUT_AI_CONVERT; + case 3: + return NI_PFI_OUTPUT_G_SRC1; + case 4: + return NI_PFI_OUTPUT_G_GATE1; + case 5: + return NI_PFI_OUTPUT_AO_UPDATE_N; + case 6: + return NI_PFI_OUTPUT_AO_START1; + case 7: + return NI_PFI_OUTPUT_AI_START_PULSE; + case 8: + return NI_PFI_OUTPUT_G_SRC0; + case 9: + return NI_PFI_OUTPUT_G_GATE0; + default: + dev_err(dev->class_dev, + "%s: bug, unhandled case in switch.\n", __func__); break; } - - devpriv->gpct_mode[chan] = 0; - devpriv->gpct_input_select[chan] = 0; - devpriv->gpct_command[chan] = 0; - - devpriv->gpct_command[chan] |= G_Synchronized_Gate; - - devpriv->stc_writew(dev, devpriv->gpct_mode[chan], - G_Mode_Register(chan)); - devpriv->stc_writew(dev, devpriv->gpct_input_select[chan], - G_Input_Select_Register(chan)); - devpriv->stc_writew(dev, 0, G_Autoincrement_Register(chan)); - - /* printk("exit GPCT_Reset\n"); */ + return 0; } -#endif - -#ifdef PCIDMA -static int ni_gpct_cmd(struct comedi_device *dev, struct comedi_subdevice *s) +static int ni_old_set_pfi_routing(struct comedi_device *dev, + unsigned chan, unsigned source) { - struct ni_gpct *counter = s->private; - int retval; - - retval = ni_request_gpct_mite_channel(dev, counter->counter_index, - COMEDI_INPUT); - if (retval) { - comedi_error(dev, - "no dma channel available for use by counter"); - return retval; - } - ni_tio_acknowledge_and_confirm(counter, NULL, NULL, NULL, NULL); - ni_e_series_enable_second_irq(dev, counter->counter_index, 1); - - return ni_tio_cmd(dev, s); + /* pre-m-series boards have fixed signals on pfi pins */ + if (source != ni_old_get_pfi_routing(dev, chan)) + return -EINVAL; + return 2; } -#endif -#ifdef PCIDMA -static int ni_gpct_cancel(struct comedi_device *dev, struct comedi_subdevice *s) +static unsigned ni_m_series_get_pfi_routing(struct comedi_device *dev, + unsigned chan) { - struct ni_gpct *counter = s->private; - int retval; + struct ni_private *devpriv = dev->private; + const unsigned array_offset = chan / 3; - retval = ni_tio_cancel(counter); - ni_e_series_enable_second_irq(dev, counter->counter_index, 0); - ni_release_gpct_mite_channel(dev, counter->counter_index); - return retval; + return MSeries_PFI_Output_Select_Source(chan, + devpriv->pfi_output_select_reg[array_offset]); } -#endif - -/* - * - * Programmable Function Inputs - * - */ -static int ni_m_series_set_pfi_routing(struct comedi_device *dev, unsigned chan, - unsigned source) +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; @@ -5028,132 +4614,51 @@ static int ni_m_series_set_pfi_routing(struct comedi_device *dev, unsigned chan, ~MSeries_PFI_Output_Select_Mask(chan); devpriv->pfi_output_select_reg[array_offset] |= MSeries_PFI_Output_Select_Bits(chan, source); - ni_writew(devpriv->pfi_output_select_reg[array_offset], + ni_writew(dev, devpriv->pfi_output_select_reg[array_offset], M_Offset_PFI_Output_Select(pfi_reg_index)); return 2; } -static int ni_old_set_pfi_routing(struct comedi_device *dev, unsigned chan, - unsigned source) +static unsigned ni_get_pfi_routing(struct comedi_device *dev, unsigned chan) { - /* pre-m-series boards have fixed signals on pfi pins */ - if (source != ni_old_get_pfi_routing(dev, chan)) - return -EINVAL; - return 2; + struct ni_private *devpriv = dev->private; + + return (devpriv->is_m_series) + ? ni_m_series_get_pfi_routing(dev, chan) + : ni_old_get_pfi_routing(dev, chan); } static int ni_set_pfi_routing(struct comedi_device *dev, unsigned chan, unsigned source) { - const struct ni_board_struct *board = comedi_board(dev); - - if (board->reg_type & ni_reg_m_series_mask) - return ni_m_series_set_pfi_routing(dev, chan, source); - else - return ni_old_set_pfi_routing(dev, chan, source); -} - -static unsigned ni_m_series_get_pfi_routing(struct comedi_device *dev, - unsigned chan) -{ struct ni_private *devpriv = dev->private; - const unsigned array_offset = chan / 3; - - return MSeries_PFI_Output_Select_Source(chan, - devpriv-> - pfi_output_select_reg - [array_offset]); -} - -static unsigned ni_old_get_pfi_routing(struct comedi_device *dev, unsigned chan) -{ - /* pre-m-series boards have fixed signals on pfi pins */ - switch (chan) { - case 0: - return NI_PFI_OUTPUT_AI_START1; - break; - case 1: - return NI_PFI_OUTPUT_AI_START2; - break; - case 2: - return NI_PFI_OUTPUT_AI_CONVERT; - break; - case 3: - return NI_PFI_OUTPUT_G_SRC1; - break; - case 4: - return NI_PFI_OUTPUT_G_GATE1; - break; - case 5: - return NI_PFI_OUTPUT_AO_UPDATE_N; - break; - case 6: - return NI_PFI_OUTPUT_AO_START1; - break; - case 7: - return NI_PFI_OUTPUT_AI_START_PULSE; - break; - case 8: - return NI_PFI_OUTPUT_G_SRC0; - break; - case 9: - return NI_PFI_OUTPUT_G_GATE0; - break; - default: - printk("%s: bug, unhandled case in switch.\n", __func__); - break; - } - return 0; -} - -static unsigned ni_get_pfi_routing(struct comedi_device *dev, unsigned chan) -{ - const struct ni_board_struct *board = comedi_board(dev); - if (board->reg_type & ni_reg_m_series_mask) - return ni_m_series_get_pfi_routing(dev, chan); - else - return ni_old_get_pfi_routing(dev, chan); + return (devpriv->is_m_series) + ? ni_m_series_set_pfi_routing(dev, chan, source) + : ni_old_set_pfi_routing(dev, chan, source); } -static int ni_config_filter(struct comedi_device *dev, unsigned pfi_channel, +static int ni_config_filter(struct comedi_device *dev, + unsigned pfi_channel, enum ni_pfi_filter_select filter) { - const struct ni_board_struct *board = comedi_board(dev); - struct ni_private *devpriv __maybe_unused = dev->private; + struct ni_private *devpriv = dev->private; unsigned bits; - if ((board->reg_type & ni_reg_m_series_mask) == 0) + if (!devpriv->is_m_series) return -ENOTSUPP; - bits = ni_readl(M_Offset_PFI_Filter); + + 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(bits, M_Offset_PFI_Filter); + ni_writel(dev, bits, M_Offset_PFI_Filter); return 0; } -static int ni_pfi_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - const struct ni_board_struct *board = comedi_board(dev); - struct ni_private *devpriv __maybe_unused = dev->private; - - if (!(board->reg_type & ni_reg_m_series_mask)) - return -ENOTSUPP; - - if (comedi_dio_update_state(s, data)) - ni_writew(s->state, M_Offset_PFI_DO); - - data[1] = ni_readw(M_Offset_PFI_DI); - - return insn->n; -} - static int ni_pfi_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct ni_private *devpriv = dev->private; unsigned int chan; @@ -5175,78 +4680,178 @@ static int ni_pfi_insn_config(struct comedi_device *dev, (devpriv->io_bidirection_pin_reg & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; return 0; - break; case INSN_CONFIG_SET_ROUTING: return ni_set_pfi_routing(dev, chan, data[1]); - break; case INSN_CONFIG_GET_ROUTING: data[1] = ni_get_pfi_routing(dev, chan); break; case INSN_CONFIG_FILTER: return ni_config_filter(dev, chan, data[1]); - break; default: return -EINVAL; } return 0; } -/* - * - * NI RTSI Bus Functions - * - */ -static void ni_rtsi_init(struct comedi_device *dev) +static int ni_pfi_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; - /* Initialises the RTSI bus signal switch to a default state */ + if (!devpriv->is_m_series) + return -ENOTSUPP; - /* 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) - printk("ni_set_master_clock failed, bug?"); - /* 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); - devpriv->stc_writew(dev, devpriv->rtsi_trig_a_output_reg, - RTSI_Trig_A_Output_Register); - 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); - if (board->reg_type & ni_reg_m_series_mask) - devpriv->rtsi_trig_b_output_reg |= - RTSI_Trig_Output_Bits(7, NI_RTSI_OUTPUT_RTSI_OSC); - devpriv->stc_writew(dev, devpriv->rtsi_trig_b_output_reg, - RTSI_Trig_B_Output_Register); + if (comedi_dio_update_state(s, data)) + ni_writew(dev, s->state, M_Offset_PFI_DO); -/* -* Sets the source and direction of the 4 on board lines -* devpriv->stc_writew(dev, 0x0000, RTSI_Board_Register); -*/ + data[1] = ni_readw(dev, M_Offset_PFI_DI); + + return insn->n; } -static int ni_rtsi_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int cs5529_wait_for_idle(struct comedi_device *dev) { - data[1] = 0; + unsigned short status; + const int timeout = HZ; + int i; + for (i = 0; i < timeout; i++) { + status = ni_ao_win_inw(dev, CAL_ADC_Status_67xx); + if ((status & CSS_ADC_BUSY) == 0) + break; + set_current_state(TASK_INTERRUPTIBLE); + if (schedule_timeout(1)) + return -EIO; + } + if (i == timeout) { + dev_err(dev->class_dev, "%s timeout\n", __func__); + return -ETIME; + } + return 0; +} + +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); + /* give time for command to start being serially clocked into cs5529. + * this insures that the CSS_ADC_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)) + break; + udelay(1); + } + if (i == timeout) + dev_err(dev->class_dev, + "possible problem - never saw adc go busy?\n"); +} + +static int cs5529_do_conversion(struct comedi_device *dev, + unsigned short *data) +{ + int retval; + unsigned short status; + + cs5529_command(dev, CSCMD_COMMAND | CSCMD_SINGLE_CONVERSION); + 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) { + dev_err(dev->class_dev, + "cs5529 conversion error, status CSS_OSC_DETECT\n"); + return -EIO; + } + if (status & CSS_OVERRANGE) { + dev_err(dev->class_dev, + "cs5529 conversion error, overrange (ignoring)\n"); + } + if (data) { + *data = ni_ao_win_inw(dev, CAL_ADC_Data_67xx); + /* cs5529 returns 16 bit signed data in bipolar mode */ + *data ^= (1 << 15); + } + return 0; +} + +static int cs5529_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + int n, retval; + unsigned short sample; + unsigned int channel_select; + const unsigned int INTERNAL_REF = 0x1000; + + /* Set calibration adc source. Docs lie, reference select bits 8 to 11 + * do nothing. bit 12 seems to chooses internal reference voltage, bit + * 13 causes the adc input to go overrange (maybe reads external reference?) */ + if (insn->chanspec & CR_ALT_SOURCE) + channel_select = INTERNAL_REF; + else + channel_select = CR_CHAN(insn->chanspec); + ni_ao_win_outw(dev, channel_select, AO_Calibration_Channel_Select_67xx); + + for (n = 0; n < insn->n; n++) { + retval = cs5529_do_conversion(dev, &sample); + if (retval < 0) + return retval; + data[n] = sample; + } return insn->n; } -/* Find best multiplier/divider to try and get the PLL running at 80 MHz - * given an arbitrary frequency input clock */ +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); + if (cs5529_wait_for_idle(dev)) + dev_err(dev->class_dev, + "timeout or signal in %s\n", __func__); +} + +static int init_cs5529(struct comedi_device *dev) +{ + unsigned int config_bits = + CSCFG_PORT_MODE | CSCFG_WORD_RATE_2180_CYCLES; + +#if 1 + /* do self-calibration */ + cs5529_config_write(dev, config_bits | CSCFG_SELF_CAL_OFFSET_GAIN, + CSCMD_CONFIG_REGISTER); + /* 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); + if (cs5529_wait_for_idle(dev)) + dev_err(dev->class_dev, + "timeout or signal in %s\n", __func__); +#endif + return 0; +} + +/* + * Find best multiplier/divider to try and get the PLL running at 80 MHz + * given an arbitrary frequency input clock. + */ static int ni_mseries_get_pll_parameters(unsigned reference_period_ns, unsigned *freq_divider, unsigned *freq_multiplier, @@ -5266,6 +4871,7 @@ static int ni_mseries_get_pll_parameters(unsigned reference_period_ns, static const unsigned target_picosec = 12500; 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) { unsigned new_period_ps = @@ -5278,10 +4884,9 @@ static int ni_mseries_get_pll_parameters(unsigned reference_period_ns, } } } - if (best_period_picosec == 0) { - printk("%s: bug, failed to find pll parameters\n", __func__); + if (best_period_picosec == 0) return -EIO; - } + *freq_divider = best_div; *freq_multiplier = best_mult; *actual_period_ns = @@ -5290,16 +4895,6 @@ static int ni_mseries_get_pll_parameters(unsigned reference_period_ns, return 0; } -static inline unsigned num_configurable_rtsi_channels(struct comedi_device *dev) -{ - const struct ni_board_struct *board = comedi_board(dev); - - if (board->reg_type & ni_reg_m_series_mask) - return 8; - else - return 7; -} - static int ni_mseries_set_pll_master_clock(struct comedi_device *dev, unsigned source, unsigned period_ns) { @@ -5317,15 +4912,14 @@ static int ni_mseries_set_pll_master_clock(struct comedi_device *dev, period_ns = 100; /* these limits are somewhat arbitrary, but NI advertises 1 to 20MHz range so we'll use that */ if (period_ns < min_period_ns || period_ns > max_period_ns) { - printk - ("%s: you must specify an input clock frequency between %i and %i nanosec " - "for the phased-lock loop.\n", __func__, - min_period_ns, max_period_ns); + dev_err(dev->class_dev, + "%s: you must specify an input clock frequency between %i and %i nanosec for the phased-lock loop\n", + __func__, min_period_ns, max_period_ns); return -EINVAL; } devpriv->rtsi_trig_direction_reg &= ~Use_RTSI_Clock_Bit; - devpriv->stc_writew(dev, devpriv->rtsi_trig_direction_reg, - RTSI_Trig_Direction_Register); + 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 |= @@ -5335,26 +4929,17 @@ static int ni_mseries_set_pll_master_clock(struct comedi_device *dev, case NI_MIO_PLL_PXI_STAR_TRIGGER_CLOCK: devpriv->clock_and_fout2 |= MSeries_PLL_In_Source_Select_Star_Trigger_Bits; - retval = ni_mseries_get_pll_parameters(period_ns, &freq_divider, - &freq_multiplier, - &devpriv->clock_ns); - if (retval < 0) - return retval; break; case NI_MIO_PLL_PXI10_CLOCK: /* pxi clock is 10MHz */ devpriv->clock_and_fout2 |= MSeries_PLL_In_Source_Select_PXI_Clock10; - retval = ni_mseries_get_pll_parameters(period_ns, &freq_divider, - &freq_multiplier, - &devpriv->clock_ns); - if (retval < 0) - return retval; 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 == @@ -5367,81 +4952,78 @@ static int ni_mseries_set_pll_master_clock(struct comedi_device *dev, } if (rtsi_channel > max_rtsi_channel) return -EINVAL; - retval = ni_mseries_get_pll_parameters(period_ns, - &freq_divider, - &freq_multiplier, - &devpriv-> - clock_ns); - if (retval < 0) - return retval; } break; } - ni_writew(devpriv->clock_and_fout2, M_Offset_Clock_and_Fout2); + retval = ni_mseries_get_pll_parameters(period_ns, + &freq_divider, + &freq_multiplier, + &devpriv->clock_ns); + if (retval < 0) { + dev_err(dev->class_dev, + "%s: bug, failed to find pll parameters\n", __func__); + 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); - /* printk("using divider=%i, multiplier=%i for PLL. pll_control_bits = 0x%x\n", - * freq_divider, freq_multiplier, pll_control_bits); */ - /* printk("clock_ns=%d\n", devpriv->clock_ns); */ - ni_writew(pll_control_bits, M_Offset_PLL_Control); + ni_writew(dev, pll_control_bits, M_Offset_PLL_Control); 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(M_Offset_PLL_Status) & MSeries_PLL_Locked_Bit) + if (ni_readw(dev, M_Offset_PLL_Status) & MSeries_PLL_Locked_Bit) break; udelay(1); } if (i == timeout) { - printk - ("%s: timed out waiting for PLL to lock to reference clock source %i with period %i ns.\n", - __func__, source, period_ns); + dev_err(dev->class_dev, + "%s: timed out waiting for PLL to lock to reference clock source %i with period %i ns\n", + __func__, source, period_ns); return -ETIMEDOUT; } return 3; } -static int ni_set_master_clock(struct comedi_device *dev, unsigned source, - unsigned period_ns) +static int ni_set_master_clock(struct comedi_device *dev, + unsigned source, unsigned period_ns) { - const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; if (source == NI_MIO_INTERNAL_CLOCK) { devpriv->rtsi_trig_direction_reg &= ~Use_RTSI_Clock_Bit; - devpriv->stc_writew(dev, devpriv->rtsi_trig_direction_reg, - RTSI_Trig_Direction_Register); + ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg, + RTSI_Trig_Direction_Register); devpriv->clock_ns = TIMEBASE_1_NS; - if (board->reg_type & ni_reg_m_series_mask) { + if (devpriv->is_m_series) { devpriv->clock_and_fout2 &= ~(MSeries_Timebase1_Select_Bit | MSeries_Timebase3_Select_Bit); - ni_writew(devpriv->clock_and_fout2, + ni_writew(dev, devpriv->clock_and_fout2, M_Offset_Clock_and_Fout2); - ni_writew(0, M_Offset_PLL_Control); + ni_writew(dev, 0, M_Offset_PLL_Control); } devpriv->clock_source = source; } else { - if (board->reg_type & ni_reg_m_series_mask) { + if (devpriv->is_m_series) { return ni_mseries_set_pll_master_clock(dev, source, period_ns); } else { if (source == NI_MIO_RTSI_CLOCK) { devpriv->rtsi_trig_direction_reg |= Use_RTSI_Clock_Bit; - devpriv->stc_writew(dev, - devpriv-> - rtsi_trig_direction_reg, - RTSI_Trig_Direction_Register); + ni_stc_writew(dev, + devpriv->rtsi_trig_direction_reg, + RTSI_Trig_Direction_Register); if (period_ns == 0) { - printk - ("%s: we don't handle an unspecified clock period correctly yet, returning error.\n", - __func__); + dev_err(dev->class_dev, + "%s: we don't handle an unspecified clock period correctly yet, returning error\n", + __func__); return -EINVAL; - } else { - devpriv->clock_ns = period_ns; } + devpriv->clock_ns = period_ns; devpriv->clock_source = source; } else return -EINVAL; @@ -5450,21 +5032,27 @@ static int ni_set_master_clock(struct comedi_device *dev, unsigned source, return 3; } -static int ni_valid_rtsi_output_source(struct comedi_device *dev, unsigned chan, - unsigned source) +static unsigned num_configurable_rtsi_channels(struct comedi_device *dev) { - const struct ni_board_struct *board = comedi_board(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 (source == NI_RTSI_OUTPUT_RTSI_OSC) return 1; - else { - printk - ("%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); - return 0; - } + + 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); + return 0; } return 0; } @@ -5479,21 +5067,15 @@ static int ni_valid_rtsi_output_source(struct comedi_device *dev, unsigned chan, case NI_RTSI_OUTPUT_RGOUT0: case NI_RTSI_OUTPUT_RTSI_BRD_0: return 1; - break; case NI_RTSI_OUTPUT_RTSI_OSC: - if (board->reg_type & ni_reg_m_series_mask) - return 1; - else - return 0; - break; + return (devpriv->is_m_series) ? 1 : 0; default: return 0; - break; } } -static int ni_set_rtsi_routing(struct comedi_device *dev, unsigned chan, - unsigned source) +static int ni_set_rtsi_routing(struct comedi_device *dev, + unsigned chan, unsigned source) { struct ni_private *devpriv = dev->private; @@ -5503,14 +5085,14 @@ static int ni_set_rtsi_routing(struct comedi_device *dev, unsigned chan, devpriv->rtsi_trig_a_output_reg &= ~RTSI_Trig_Output_Mask(chan); devpriv->rtsi_trig_a_output_reg |= RTSI_Trig_Output_Bits(chan, source); - devpriv->stc_writew(dev, devpriv->rtsi_trig_a_output_reg, - RTSI_Trig_A_Output_Register); + ni_stc_writew(dev, devpriv->rtsi_trig_a_output_reg, + RTSI_Trig_A_Output_Register); } 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->stc_writew(dev, devpriv->rtsi_trig_b_output_reg, - RTSI_Trig_B_Output_Register); + ni_stc_writew(dev, devpriv->rtsi_trig_b_output_reg, + RTSI_Trig_B_Output_Register); } return 2; } @@ -5528,16 +5110,17 @@ static unsigned ni_get_rtsi_routing(struct comedi_device *dev, unsigned chan) } else { if (chan == old_RTSI_clock_channel) return NI_RTSI_OUTPUT_RTSI_OSC; - printk("%s: bug! should never get here?\n", __func__); + dev_err(dev->class_dev, "%s: bug! should never get here?\n", + __func__); return 0; } } static int ni_rtsi_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); @@ -5545,33 +5128,30 @@ static int ni_rtsi_insn_config(struct comedi_device *dev, case INSN_CONFIG_DIO_OUTPUT: if (chan < num_configurable_rtsi_channels(dev)) { devpriv->rtsi_trig_direction_reg |= - RTSI_Output_Bit(chan, - (board->reg_type & ni_reg_m_series_mask) != 0); + RTSI_Output_Bit(chan, devpriv->is_m_series); } else if (chan == old_RTSI_clock_channel) { devpriv->rtsi_trig_direction_reg |= Drive_RTSI_Clock_Bit; } - devpriv->stc_writew(dev, devpriv->rtsi_trig_direction_reg, - RTSI_Trig_Direction_Register); + ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg, + RTSI_Trig_Direction_Register); break; case INSN_CONFIG_DIO_INPUT: if (chan < num_configurable_rtsi_channels(dev)) { devpriv->rtsi_trig_direction_reg &= - ~RTSI_Output_Bit(chan, - (board->reg_type & ni_reg_m_series_mask) != 0); + ~RTSI_Output_Bit(chan, devpriv->is_m_series); } else if (chan == old_RTSI_clock_channel) { devpriv->rtsi_trig_direction_reg &= ~Drive_RTSI_Clock_Bit; } - devpriv->stc_writew(dev, devpriv->rtsi_trig_direction_reg, - RTSI_Trig_Direction_Register); + ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg, + RTSI_Trig_Direction_Register); break; case INSN_CONFIG_DIO_QUERY: if (chan < num_configurable_rtsi_channels(dev)) { data[1] = (devpriv->rtsi_trig_direction_reg & - RTSI_Output_Bit(chan, - (board->reg_type & ni_reg_m_series_mask) != 0)) + RTSI_Output_Bit(chan, devpriv->is_m_series)) ? INSN_CONFIG_DIO_OUTPUT : INSN_CONFIG_DIO_INPUT; } else if (chan == old_RTSI_clock_channel) { @@ -5581,160 +5161,600 @@ static int ni_rtsi_insn_config(struct comedi_device *dev, ? INSN_CONFIG_DIO_OUTPUT : INSN_CONFIG_DIO_INPUT; } return 2; - break; case INSN_CONFIG_SET_CLOCK_SRC: return ni_set_master_clock(dev, data[1], data[2]); - break; case INSN_CONFIG_GET_CLOCK_SRC: data[1] = devpriv->clock_source; data[2] = devpriv->clock_ns; return 3; - break; case INSN_CONFIG_SET_ROUTING: return ni_set_rtsi_routing(dev, chan, data[1]); - break; case INSN_CONFIG_GET_ROUTING: data[1] = ni_get_rtsi_routing(dev, chan); return 2; - break; default: return -EINVAL; - break; } return 1; } -static int cs5529_wait_for_idle(struct comedi_device *dev) +static int ni_rtsi_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - unsigned short status; - const int timeout = HZ; - int i; + data[1] = 0; - for (i = 0; i < timeout; i++) { - status = ni_ao_win_inw(dev, CAL_ADC_Status_67xx); - if ((status & CSS_ADC_BUSY) == 0) - break; - set_current_state(TASK_INTERRUPTIBLE); - if (schedule_timeout(1)) - return -EIO; + return insn->n; +} + +static void ni_rtsi_init(struct comedi_device *dev) +{ + struct ni_private *devpriv = dev->private; + + /* Initialises the RTSI bus signal switch to a default state */ + + /* 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); + ni_stc_writew(dev, devpriv->rtsi_trig_a_output_reg, + RTSI_Trig_A_Output_Register); + 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); + if (devpriv->is_m_series) + devpriv->rtsi_trig_b_output_reg |= + RTSI_Trig_Output_Bits(7, NI_RTSI_OUTPUT_RTSI_OSC); + ni_stc_writew(dev, devpriv->rtsi_trig_b_output_reg, + RTSI_Trig_B_Output_Register); + +/* +* Sets the source and direction of the 4 on board lines +* ni_stc_writew(dev, 0x0000, RTSI_Board_Register); +*/ +} + +#ifdef PCIDMA +static int ni_gpct_cmd(struct comedi_device *dev, struct comedi_subdevice *s) +{ + struct ni_gpct *counter = s->private; + int retval; + + retval = ni_request_gpct_mite_channel(dev, counter->counter_index, + COMEDI_INPUT); + if (retval) { + dev_err(dev->class_dev, + "no dma channel available for use by counter\n"); + return retval; } -/* printk("looped %i times waiting for idle\n", i); */ - if (i == timeout) { - printk("%s: %s: timeout\n", __FILE__, __func__); - return -ETIME; + ni_tio_acknowledge(counter); + ni_e_series_enable_second_irq(dev, counter->counter_index, 1); + + return ni_tio_cmd(dev, s); +} + +static int ni_gpct_cancel(struct comedi_device *dev, struct comedi_subdevice *s) +{ + struct ni_gpct *counter = s->private; + int retval; + + retval = ni_tio_cancel(counter); + ni_e_series_enable_second_irq(dev, counter->counter_index, 0); + ni_release_gpct_mite_channel(dev, counter->counter_index); + return retval; +} +#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; } - return 0; + + 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 void cs5529_command(struct comedi_device *dev, unsigned short value) +static irqreturn_t ni_E_interrupt(int irq, void *d) { - static const int timeout = 100; - int i; + struct comedi_device *dev = d; + unsigned short a_status; + unsigned short b_status; + unsigned int ai_mite_status = 0; + unsigned int ao_mite_status = 0; + unsigned long flags; +#ifdef PCIDMA + struct ni_private *devpriv = dev->private; + struct mite_struct *mite = devpriv->mite; +#endif - ni_ao_win_outw(dev, value, CAL_ADC_Command_67xx); - /* give time for command to start being serially clocked into cs5529. - * this insures that the CSS_ADC_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)) - break; - udelay(1); + if (!dev->attached) + return IRQ_NONE; + smp_mb(); /* make sure dev->attached is checked before handler does anything else. */ + + /* 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); +#ifdef PCIDMA + if (mite) { + struct ni_private *devpriv = dev->private; + unsigned long flags_too; + + spin_lock_irqsave(&devpriv->mite_channel_lock, flags_too); + if (devpriv->ai_mite_chan) { + ai_mite_status = mite_get_status(devpriv->ai_mite_chan); + if (ai_mite_status & CHSR_LINKC) + writel(CHOR_CLRLC, + devpriv->mite->mite_io_addr + + MITE_CHOR(devpriv-> + ai_mite_chan->channel)); + } + if (devpriv->ao_mite_chan) { + ao_mite_status = mite_get_status(devpriv->ao_mite_chan); + if (ao_mite_status & CHSR_LINKC) + writel(CHOR_CLRLC, + mite->mite_io_addr + + MITE_CHOR(devpriv-> + ao_mite_chan->channel)); + } + spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags_too); } -/* printk("looped %i times writing command to cs5529\n", i); */ - if (i == timeout) - comedi_error(dev, "possible problem - never saw adc go busy?"); +#endif + ack_a_interrupt(dev, a_status); + ack_b_interrupt(dev, b_status); + if ((a_status & Interrupt_A_St) || (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)) + handle_b_interrupt(dev, b_status, ao_mite_status); + handle_gpct_interrupt(dev, 0); + handle_gpct_interrupt(dev, 1); + handle_cdio_interrupt(dev); + + spin_unlock_irqrestore(&dev->spinlock, flags); + return IRQ_HANDLED; } -/* write to cs5529 register */ -static void cs5529_config_write(struct comedi_device *dev, unsigned int value, - unsigned int reg_select_bits) +static int ni_alloc_private(struct comedi_device *dev) { - 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); - if (cs5529_wait_for_idle(dev)) - comedi_error(dev, "time or signal in cs5529_config_write()"); + struct ni_private *devpriv; + + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); + if (!devpriv) + return -ENOMEM; + + spin_lock_init(&devpriv->window_lock); + spin_lock_init(&devpriv->soft_reg_copy_lock); + spin_lock_init(&devpriv->mite_channel_lock); + + return 0; } -static int cs5529_do_conversion(struct comedi_device *dev, unsigned short *data) +static int ni_E_init(struct comedi_device *dev, + unsigned interrupt_pin, unsigned irq_polarity) { - int retval; - unsigned short status; + const struct ni_board_struct *board = comedi_board(dev); + struct ni_private *devpriv = dev->private; + struct comedi_subdevice *s; + int ret; + int i; - cs5529_command(dev, CSCMD_COMMAND | CSCMD_SINGLE_CONVERSION); - retval = cs5529_wait_for_idle(dev); - if (retval) { - comedi_error(dev, - "timeout or signal in cs5529_do_conversion()"); - return -ETIME; + if (board->n_aochan > MAX_N_AO_CHAN) { + dev_err(dev->class_dev, "bug! n_aochan > MAX_N_AO_CHAN\n"); + return -EINVAL; } - status = ni_ao_win_inw(dev, CAL_ADC_Status_67xx); - if (status & CSS_OSC_DETECT) { - printk - ("ni_mio_common: cs5529 conversion error, status CSS_OSC_DETECT\n"); - return -EIO; + + /* 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; + 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); } - if (status & CSS_OVERRANGE) { - printk - ("ni_mio_common: cs5529 conversion error, overrange (ignoring)\n"); + ni_stc_writew(dev, devpriv->clock_and_fout, Clock_and_FOUT_Register); + + ret = comedi_alloc_subdevices(dev, NI_NUM_SUBDEVICES); + if (ret) + return ret; + + /* Analog Input subdevice */ + s = &dev->subdevices[NI_AI_SUBDEV]; + if (board->n_adchan) { + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_DITHER; + if (!devpriv->is_611x) + s->subdev_flags |= SDF_GROUND | SDF_COMMON | SDF_OTHER; + if (board->ai_maxdata > 0xffff) + s->subdev_flags |= SDF_LSAMPL; + if (devpriv->is_m_series) + s->subdev_flags |= SDF_SOFT_CALIBRATED; + s->n_chan = board->n_adchan; + s->maxdata = board->ai_maxdata; + s->range_table = ni_range_lkup[board->gainlkup]; + s->insn_read = ni_ai_insn_read; + s->insn_config = ni_ai_insn_config; + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = 512; + s->do_cmdtest = ni_ai_cmdtest; + s->do_cmd = ni_ai_cmd; + s->cancel = ni_ai_reset; + s->poll = ni_ai_poll; + s->munge = ni_ai_munge; + + if (devpriv->mite) + s->async_dma_dir = DMA_FROM_DEVICE; + } + + /* reset the analog input configuration */ + ni_ai_reset(dev, s); + } else { + s->type = COMEDI_SUBD_UNUSED; } - if (data) { - *data = ni_ao_win_inw(dev, CAL_ADC_Data_67xx); - /* cs5529 returns 16 bit signed data in bipolar mode */ - *data ^= (1 << 15); + + /* Analog Output subdevice */ + s = &dev->subdevices[NI_AO_SUBDEV]; + if (board->n_aochan) { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_DEGLITCH | SDF_GROUND; + if (devpriv->is_m_series) + s->subdev_flags |= SDF_SOFT_CALIBRATED; + s->n_chan = board->n_aochan; + s->maxdata = board->ao_maxdata; + s->range_table = board->ao_range_table; + s->insn_read = ni_ao_insn_read; + s->insn_write = ni_ao_insn_write; + s->insn_config = ni_ao_insn_config; + + /* + * Along with the IRQ we need either a FIFO or DMA for + * async command support. + */ + if (dev->irq && (board->ao_fifo_depth || devpriv->mite)) { + dev->write_subdev = s; + s->subdev_flags |= SDF_CMD_WRITE; + s->len_chanlist = s->n_chan; + s->do_cmdtest = ni_ao_cmdtest; + s->do_cmd = ni_ao_cmd; + s->cancel = ni_ao_reset; + if (!devpriv->is_m_series) + s->munge = ni_ao_munge; + + if (devpriv->mite) + s->async_dma_dir = DMA_TO_DEVICE; + } + + if (devpriv->is_67xx) + init_ao_67xx(dev, s); + + /* reset the analog output configuration */ + ni_ao_reset(dev, s); + } else { + s->type = COMEDI_SUBD_UNUSED; } - return 0; -} -static int cs5529_ai_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - int n, retval; - unsigned short sample; - unsigned int channel_select; - const unsigned int INTERNAL_REF = 0x1000; + /* Digital I/O subdevice */ + s = &dev->subdevices[NI_DIO_SUBDEV]; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = board->has_32dio_chan ? 32 : 8; + s->maxdata = 1; + s->range_table = &range_digital; + if (devpriv->is_m_series) { + s->subdev_flags |= SDF_LSAMPL; + s->insn_bits = ni_m_series_dio_insn_bits; + s->insn_config = ni_m_series_dio_insn_config; + if (dev->irq) { + s->subdev_flags |= SDF_CMD_WRITE /* | SDF_CMD_READ */; + s->len_chanlist = s->n_chan; + s->do_cmdtest = ni_cdio_cmdtest; + s->do_cmd = ni_cdio_cmd; + s->cancel = ni_cdio_cancel; + + /* M-series boards use DMA */ + s->async_dma_dir = DMA_BIDIRECTIONAL; + } - /* Set calibration adc source. Docs lie, reference select bits 8 to 11 - * do nothing. bit 12 seems to chooses internal reference voltage, bit - * 13 causes the adc input to go overrange (maybe reads external reference?) */ - if (insn->chanspec & CR_ALT_SOURCE) - channel_select = INTERNAL_REF; - else - channel_select = CR_CHAN(insn->chanspec); - ni_ao_win_outw(dev, channel_select, AO_Calibration_Channel_Select_67xx); + /* 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); + } else { + s->insn_bits = ni_dio_insn_bits; + s->insn_config = ni_dio_insn_config; - for (n = 0; n < insn->n; n++) { - retval = cs5529_do_conversion(dev, &sample); - if (retval < 0) - return retval; - data[n] = sample; + /* set all channels to inputs */ + devpriv->dio_control = DIO_Pins_Dir(s->io_bits); + ni_writew(dev, devpriv->dio_control, DIO_Control_Register); } - return insn->n; -} -static int init_cs5529(struct comedi_device *dev) -{ - unsigned int config_bits = - CSCFG_PORT_MODE | CSCFG_WORD_RATE_2180_CYCLES; + /* 8255 device */ + s = &dev->subdevices[NI_8255_DIO_SUBDEV]; + if (board->has_8255) { + ret = subdev_8255_init(dev, s, ni_8255_callback, + (unsigned long)dev); + if (ret) + return ret; + } else { + s->type = COMEDI_SUBD_UNUSED; + } -#if 1 - /* do self-calibration */ - cs5529_config_write(dev, config_bits | CSCFG_SELF_CAL_OFFSET_GAIN, - CSCMD_CONFIG_REGISTER); - /* 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); - if (cs5529_wait_for_idle(dev)) - comedi_error(dev, "timeout or signal in init_cs5529()\n"); + /* formerly general purpose counter/timer device, but no longer used */ + s = &dev->subdevices[NI_UNUSED_SUBDEV]; + s->type = COMEDI_SUBD_UNUSED; + + /* Calibration subdevice */ + s = &dev->subdevices[NI_CALIBRATION_SUBDEV]; + s->type = COMEDI_SUBD_CALIB; + s->subdev_flags = SDF_INTERNAL; + s->n_chan = 1; + s->maxdata = 0; + if (devpriv->is_m_series) { + /* internal PWM output used for AI nonlinearity calibration */ + s->insn_config = ni_m_series_pwm_config; + + ni_writel(dev, 0x0, M_Offset_Cal_PWM); + } else if (devpriv->is_6143) { + /* internal PWM output used for AI nonlinearity calibration */ + s->insn_config = ni_6143_pwm_config; + } else { + s->subdev_flags |= SDF_WRITABLE; + s->insn_read = ni_calib_insn_read; + s->insn_write = ni_calib_insn_write; + + /* setup the caldacs and find the real n_chan and maxdata */ + caldac_setup(dev, s); + } + + /* EEPROM subdevice */ + s = &dev->subdevices[NI_EEPROM_SUBDEV]; + s->type = COMEDI_SUBD_MEMORY; + s->subdev_flags = SDF_READABLE | SDF_INTERNAL; + s->maxdata = 0xff; + if (devpriv->is_m_series) { + s->n_chan = M_SERIES_EEPROM_SIZE; + s->insn_read = ni_m_series_eeprom_insn_read; + } else { + s->n_chan = 512; + s->insn_read = ni_eeprom_insn_read; + } + + /* Digital I/O (PFI) subdevice */ + s = &dev->subdevices[NI_PFI_DIO_SUBDEV]; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + s->maxdata = 1; + if (devpriv->is_m_series) { + s->n_chan = 16; + s->insn_bits = ni_pfi_insn_bits; + + ni_writew(dev, s->state, M_Offset_PFI_DO); + 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)); + } + } else { + s->n_chan = 10; + } + s->insn_config = ni_pfi_insn_config; + + ni_set_bits(dev, IO_Bidirection_Pin_Register, ~0, 0); + + /* cs5529 calibration adc */ + s = &dev->subdevices[NI_CS5529_CALIBRATION_SUBDEV]; + if (devpriv->is_67xx) { + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_INTERNAL; + /* one channel for each analog output channel */ + s->n_chan = board->n_aochan; + s->maxdata = (1 << 16) - 1; + s->range_table = &range_unknown; /* XXX */ + s->insn_read = cs5529_ai_insn_read; + s->insn_config = NULL; + init_cs5529(dev); + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + /* Serial */ + s = &dev->subdevices[NI_SERIAL_SUBDEV]; + s->type = COMEDI_SUBD_SERIAL; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = 1; + s->maxdata = 0xff; + s->insn_config = ni_serial_insn_config; + devpriv->serial_interval_ns = 0; + devpriv->serial_hw_mode = 0; + + /* RTSI */ + s = &dev->subdevices[NI_RTSI_SUBDEV]; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = 8; + s->maxdata = 1; + s->insn_bits = ni_rtsi_insn_bits; + s->insn_config = ni_rtsi_insn_config; + ni_rtsi_init(dev); + + /* allocate and initialize the gpct counter device */ + devpriv->counter_dev = ni_gpct_device_construct(dev, + ni_gpct_write_register, + ni_gpct_read_register, + (devpriv->is_m_series) + ? ni_gpct_variant_m_series + : ni_gpct_variant_e_series, + NUM_GPCT); + if (!devpriv->counter_dev) + return -ENOMEM; + + /* Counter (gpct) subdevices */ + for (i = 0; i < NUM_GPCT; ++i) { + struct ni_gpct *gpct = &devpriv->counter_dev->counters[i]; + + /* setup and initialize the counter */ + gpct->chip_index = 0; + gpct->counter_index = i; + ni_tio_init_counter(gpct); + + s = &dev->subdevices[NI_GPCT_SUBDEV(i)]; + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL; + s->n_chan = 3; + s->maxdata = (devpriv->is_m_series) ? 0xffffffff + : 0x00ffffff; + s->insn_read = ni_tio_insn_read; + s->insn_write = ni_tio_insn_read; + s->insn_config = ni_tio_insn_config; +#ifdef PCIDMA + if (dev->irq && devpriv->mite) { + s->subdev_flags |= SDF_CMD_READ /* | SDF_CMD_WRITE */; + s->len_chanlist = 1; + s->do_cmdtest = ni_tio_cmdtest; + s->do_cmd = ni_gpct_cmd; + s->cancel = ni_gpct_cancel; + + s->async_dma_dir = DMA_BIDIRECTIONAL; + } #endif + s->private = gpct; + } + + /* Frequency output subdevice */ + s = &dev->subdevices[NI_FREQ_OUT_SUBDEV]; + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 1; + s->maxdata = 0xf; + s->insn_read = ni_freq_out_insn_read; + s->insn_write = ni_freq_out_insn_write; + s->insn_config = ni_freq_out_insn_config; + + 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); + } + + /* DMA setup */ + ni_writeb(dev, devpriv->ai_ao_select_reg, AI_AO_Select); + ni_writeb(dev, devpriv->g0_g1_select_reg, G0_G1_Select); + + if (devpriv->is_6xxx) { + ni_writeb(dev, 0, Magic_611x); + } 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_writeb(dev, 0x0, + M_Offset_AO_Reference_Attenuation(channel)); + } + ni_writeb(dev, 0x0, M_Offset_AO_Calibration); + } + return 0; } + +static void mio_common_detach(struct comedi_device *dev) +{ + struct ni_private *devpriv = dev->private; + + if (devpriv) { + if (devpriv->counter_dev) + ni_gpct_device_destroy(devpriv->counter_dev); + } +} diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index de421486b758..9b201e48233e 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -47,156 +47,85 @@ See the notes in the ni_atmio.o driver. #include <pcmcia/cistpl.h> #include <pcmcia/ds.h> -#define ATMIO 1 -#undef PCIMIO - /* * AT specific setup */ -#define NI_SIZE 0x20 - -#define MAX_N_CALDACS 32 - static const struct ni_board_struct ni_boards[] = { { - .device_id = 0x010d, .name = "DAQCard-ai-16xe-50", + .device_id = 0x010d, .n_adchan = 16, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 1024, .gainlkup = ai_gain_8, .ai_speed = 5000, - .num_p0_dio_channels = 8, .caldac = { dac8800, dac8043 }, }, { - .device_id = 0x010c, .name = "DAQCard-ai-16e-4", + .device_id = 0x010c, .n_adchan = 16, - .adbits = 12, + .ai_maxdata = 0x0fff, .ai_fifo_depth = 1024, .gainlkup = ai_gain_16, .ai_speed = 4000, - .num_p0_dio_channels = 8, .caldac = { mb88341 }, /* verified */ }, { - .device_id = 0x02c4, .name = "DAQCard-6062E", + .device_id = 0x02c4, .n_adchan = 16, - .adbits = 12, + .ai_maxdata = 0x0fff, .ai_fifo_depth = 8192, .gainlkup = ai_gain_16, .ai_speed = 2000, .n_aochan = 2, - .aobits = 12, + .ao_maxdata = 0x0fff, .ao_fifo_depth = 2048, .ao_range_table = &range_bipolar10, .ao_speed = 1176, - .num_p0_dio_channels = 8, .caldac = { ad8804_debug }, /* verified */ }, { /* specs incorrect! */ - .device_id = 0x075e, .name = "DAQCard-6024E", + .device_id = 0x075e, .n_adchan = 16, - .adbits = 12, + .ai_maxdata = 0x0fff, .ai_fifo_depth = 1024, .gainlkup = ai_gain_4, .ai_speed = 5000, .n_aochan = 2, - .aobits = 12, + .ao_maxdata = 0x0fff, .ao_range_table = &range_bipolar10, .ao_speed = 1000000, - .num_p0_dio_channels = 8, .caldac = { ad8804_debug }, }, { /* specs incorrect! */ - .device_id = 0x0245, .name = "DAQCard-6036E", + .device_id = 0x0245, .n_adchan = 16, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 1024, .alwaysdither = 1, .gainlkup = ai_gain_4, .ai_speed = 5000, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_range_table = &range_bipolar10, .ao_speed = 1000000, - .num_p0_dio_channels = 8, .caldac = { ad8804_debug }, }, #if 0 { - .device_id = 0x0000, /* unknown */ .name = "DAQCard-6715", + .device_id = 0x0000, /* unknown */ .n_aochan = 8, - .aobits = 12, + .ao_maxdata = 0x0fff, .ao_671x = 8192, - .num_p0_dio_channels = 8, .caldac = { mb88341, mb88341 }, }, #endif }; -#define interrupt_pin(a) 0 - -#define IRQ_POLARITY 1 - -struct ni_private { - - struct pcmcia_device *link; - -NI_PRIVATE_COMMON}; - -/* How we access registers */ - -#define ni_writel(a, b) (outl((a), (b)+dev->iobase)) -#define ni_readl(a) (inl((a)+dev->iobase)) -#define ni_writew(a, b) (outw((a), (b)+dev->iobase)) -#define ni_readw(a) (inw((a)+dev->iobase)) -#define ni_writeb(a, b) (outb((a), (b)+dev->iobase)) -#define ni_readb(a) (inb((a)+dev->iobase)) - -/* How we access windowed registers */ - -/* We automatically take advantage of STC registers that can be - * read/written directly in the I/O space of the board. The - * DAQCard devices map the low 8 STC registers to iobase+addr*2. */ - -static void mio_cs_win_out(struct comedi_device *dev, uint16_t data, int addr) -{ - struct ni_private *devpriv = dev->private; - unsigned long flags; - - spin_lock_irqsave(&devpriv->window_lock, flags); - if (addr < 8) { - ni_writew(data, addr * 2); - } else { - ni_writew(addr, Window_Address); - ni_writew(data, Window_Data); - } - spin_unlock_irqrestore(&devpriv->window_lock, flags); -} - -static uint16_t mio_cs_win_in(struct comedi_device *dev, int addr) -{ - struct ni_private *devpriv = dev->private; - unsigned long flags; - uint16_t ret; - - spin_lock_irqsave(&devpriv->window_lock, flags); - if (addr < 8) { - ret = ni_readw(addr * 2); - } else { - ni_writew(addr, Window_Address); - ret = ni_readw(Window_Data); - } - spin_unlock_irqrestore(&devpriv->window_lock, flags); - - return ret; -} - #include "ni_mio_common.c" static const void *ni_getboardtype(struct comedi_device *dev, @@ -260,12 +189,8 @@ static int mio_cs_auto_attach(struct comedi_device *dev, return ret; devpriv = dev->private; - devpriv->stc_writew = mio_cs_win_out; - devpriv->stc_readw = mio_cs_win_in; - devpriv->stc_writel = win_out2; - devpriv->stc_readl = win_in2; - return ni_E_init(dev); + return ni_E_init(dev, 0, 1); } static void mio_cs_detach(struct comedi_device *dev) diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 5fc74d6ff6af..b5b36af80205 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -58,9 +58,6 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org #include "comedi_fc.h" #include "mite.h" -#define PCI_DIO_SIZE 4096 -#define PCI_MITE_SIZE 4096 - /* defines for the PCI-DIO-32HS */ #define Window_Address 4 /* W */ @@ -297,16 +294,6 @@ struct nidio96_private { spinlock_t mite_channel_lock; }; -static int ni_pcidio_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd); -static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s); -static int ni_pcidio_inttrig(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned int trignum); -static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode); -static int setup_mite_dma(struct comedi_device *dev, - struct comedi_subdevice *s); - static int ni_pcidio_request_di_mite_channel(struct comedi_device *dev) { struct nidio96_private *devpriv = dev->private; @@ -319,13 +306,13 @@ static int ni_pcidio_request_di_mite_channel(struct comedi_device *dev) devpriv->di_mite_ring, 1, 2); if (devpriv->di_mite_chan == NULL) { spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); - comedi_error(dev, "failed to reserve mite dma channel."); + dev_err(dev->class_dev, "failed to reserve mite dma channel\n"); return -EBUSY; } devpriv->di_mite_chan->dir = COMEDI_INPUT; writeb(primary_DMAChannel_bits(devpriv->di_mite_chan->channel) | secondary_DMAChannel_bits(devpriv->di_mite_chan->channel), - devpriv->mite->daq_io_addr + DMA_Line_Control_Group1); + dev->mmio + DMA_Line_Control_Group1); mmiowb(); spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); return 0; @@ -344,12 +331,36 @@ static void ni_pcidio_release_di_mite_channel(struct comedi_device *dev) devpriv->di_mite_chan = NULL; writeb(primary_DMAChannel_bits(0) | secondary_DMAChannel_bits(0), - devpriv->mite->daq_io_addr + DMA_Line_Control_Group1); + dev->mmio + DMA_Line_Control_Group1); mmiowb(); } spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); } +static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s) +{ + struct nidio96_private *devpriv = dev->private; + int retval; + unsigned long flags; + + retval = ni_pcidio_request_di_mite_channel(dev); + if (retval) + return retval; + + /* write alloc the entire buffer */ + comedi_buf_write_alloc(s, s->async->prealloc_bufsz); + + spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + if (devpriv->di_mite_chan) { + mite_prep_dma(devpriv->di_mite_chan, 32, 32); + mite_dma_arm(devpriv->di_mite_chan); + } else + retval = -EIO; + spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); + + return retval; +} + static int ni_pcidio_poll(struct comedi_device *dev, struct comedi_subdevice *s) { struct nidio96_private *devpriv = dev->private; @@ -361,7 +372,7 @@ static int ni_pcidio_poll(struct comedi_device *dev, struct comedi_subdevice *s) if (devpriv->di_mite_chan) mite_sync_input_dma(devpriv->di_mite_chan, s); spin_unlock(&devpriv->mite_channel_lock); - count = s->async->buf_write_count - s->async->buf_read_count; + count = comedi_buf_n_bytes_ready(s); spin_unlock_irqrestore(&dev->spinlock, irq_flags); return count; } @@ -392,9 +403,8 @@ static irqreturn_t nidio_interrupt(int irq, void *d) /* Lock to avoid race with comedi_poll */ spin_lock(&dev->spinlock); - status = readb(devpriv->mite->daq_io_addr + - Interrupt_And_Window_Status); - flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags); + status = readb(dev->mmio + Interrupt_And_Window_Status); + flags = readb(dev->mmio + Group_1_Flags); spin_lock(&devpriv->mite_channel_lock); if (devpriv->di_mite_chan) @@ -423,8 +433,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d) if (work > 20) { dev_dbg(dev->class_dev, "too much work in interrupt\n"); writeb(0x00, - devpriv->mite->daq_io_addr + - Master_DMA_And_Interrupt_Control); + dev->mmio + Master_DMA_And_Interrupt_Control); break; } @@ -436,64 +445,50 @@ static irqreturn_t nidio_interrupt(int irq, void *d) if (work > 100) { dev_dbg(dev->class_dev, "too much work in interrupt\n"); - writeb(0x00, - devpriv->mite->daq_io_addr + + writeb(0x00, dev->mmio + Master_DMA_And_Interrupt_Control ); goto out; } - auxdata = - readl(devpriv->mite->daq_io_addr + - Group_1_FIFO); + auxdata = readl(dev->mmio + Group_1_FIFO); data1 = auxdata & 0xffff; data2 = (auxdata & 0xffff0000) >> 16; comedi_buf_put(s, data1); comedi_buf_put(s, data2); - flags = readb(devpriv->mite->daq_io_addr + - Group_1_Flags); + flags = readb(dev->mmio + Group_1_Flags); } async->events |= COMEDI_CB_BLOCK; } if (flags & CountExpired) { - writeb(ClearExpired, - devpriv->mite->daq_io_addr + - Group_1_Second_Clear); + writeb(ClearExpired, dev->mmio + Group_1_Second_Clear); async->events |= COMEDI_CB_EOA; - writeb(0x00, devpriv->mite->daq_io_addr + OpMode); + writeb(0x00, dev->mmio + OpMode); break; } else if (flags & Waited) { - writeb(ClearWaited, - devpriv->mite->daq_io_addr + - Group_1_First_Clear); + writeb(ClearWaited, dev->mmio + Group_1_First_Clear); async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; break; } else if (flags & PrimaryTC) { writeb(ClearPrimaryTC, - devpriv->mite->daq_io_addr + - Group_1_First_Clear); + dev->mmio + Group_1_First_Clear); async->events |= COMEDI_CB_EOA; } else if (flags & SecondaryTC) { writeb(ClearSecondaryTC, - devpriv->mite->daq_io_addr + - Group_1_First_Clear); + dev->mmio + Group_1_First_Clear); async->events |= COMEDI_CB_EOA; } - flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags); - status = readb(devpriv->mite->daq_io_addr + - Interrupt_And_Window_Status); + flags = readb(dev->mmio + Group_1_Flags); + status = readb(dev->mmio + Interrupt_And_Window_Status); } out: cfc_handle_events(dev, s); #if 0 - if (!tag) { - writeb(0x03, - devpriv->mite->daq_io_addr + - Master_DMA_And_Interrupt_Control); - } + if (!tag) + writeb(0x03, dev->mmio + Master_DMA_And_Interrupt_Control); #endif spin_unlock(&dev->spinlock); @@ -505,14 +500,13 @@ static int ni_pcidio_insn_config(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct nidio96_private *devpriv = dev->private; int ret; ret = comedi_dio_insn_config(dev, s, insn, data, 0); if (ret) return ret; - writel(s->io_bits, devpriv->mite->daq_io_addr + Port_Pin_Directions(0)); + writel(s->io_bits, dev->mmio + Port_Pin_Directions(0)); return insn->n; } @@ -522,16 +516,37 @@ static int ni_pcidio_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct nidio96_private *devpriv = dev->private; - if (comedi_dio_update_state(s, data)) - writel(s->state, devpriv->mite->daq_io_addr + Port_IO(0)); + writel(s->state, dev->mmio + Port_IO(0)); - data[1] = readl(devpriv->mite->daq_io_addr + Port_IO(0)); + data[1] = readl(dev->mmio + Port_IO(0)); return insn->n; } +static int ni_pcidio_ns_to_timer(int *nanosec, unsigned int flags) +{ + int divider, base; + + base = TIMER_BASE; + + switch (flags & TRIG_ROUND_MASK) { + case TRIG_ROUND_NEAREST: + default: + divider = (*nanosec + base / 2) / base; + break; + case TRIG_ROUND_DOWN: + divider = (*nanosec) / base; + break; + case TRIG_ROUND_UP: + divider = (*nanosec + base - 1) / base; + break; + } + + *nanosec = base * divider; + return divider; +} + static int ni_pcidio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { @@ -596,7 +611,7 @@ static int ni_pcidio_cmdtest(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER) { arg = cmd->scan_begin_arg; - ni_pcidio_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + ni_pcidio_ns_to_timer(&arg, cmd->flags); err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } @@ -606,27 +621,20 @@ static int ni_pcidio_cmdtest(struct comedi_device *dev, return 0; } -static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode) +static int ni_pcidio_inttrig(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int trig_num) { - int divider, base; + struct nidio96_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; - base = TIMER_BASE; + if (trig_num != cmd->start_arg) + return -EINVAL; - switch (round_mode) { - case TRIG_ROUND_NEAREST: - default: - divider = (*nanosec + base / 2) / base; - break; - case TRIG_ROUND_DOWN: - divider = (*nanosec) / base; - break; - case TRIG_ROUND_UP: - divider = (*nanosec + base - 1) / base; - break; - } + writeb(devpriv->OpModeBits, dev->mmio + OpMode); + s->async->inttrig = NULL; - *nanosec = base * divider; - return divider; + return 1; } static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) @@ -635,98 +643,94 @@ static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) struct comedi_cmd *cmd = &s->async->cmd; /* XXX configure ports for input */ - writel(0x0000, devpriv->mite->daq_io_addr + Port_Pin_Directions(0)); + writel(0x0000, dev->mmio + Port_Pin_Directions(0)); if (1) { /* enable fifos A B C D */ - writeb(0x0f, devpriv->mite->daq_io_addr + Data_Path); + writeb(0x0f, dev->mmio + Data_Path); /* set transfer width a 32 bits */ writeb(TransferWidth(0) | TransferLength(0), - devpriv->mite->daq_io_addr + Transfer_Size_Control); + dev->mmio + Transfer_Size_Control); } else { - writeb(0x03, devpriv->mite->daq_io_addr + Data_Path); + writeb(0x03, dev->mmio + Data_Path); writeb(TransferWidth(3) | TransferLength(0), - devpriv->mite->daq_io_addr + Transfer_Size_Control); + dev->mmio + Transfer_Size_Control); } /* protocol configuration */ if (cmd->scan_begin_src == TRIG_TIMER) { /* page 4-5, "input with internal REQs" */ - writeb(0, devpriv->mite->daq_io_addr + OpMode); - writeb(0x00, devpriv->mite->daq_io_addr + ClockReg); - writeb(1, devpriv->mite->daq_io_addr + Sequence); - writeb(0x04, devpriv->mite->daq_io_addr + ReqReg); - writeb(4, devpriv->mite->daq_io_addr + BlockMode); - writeb(3, devpriv->mite->daq_io_addr + LinePolarities); - writeb(0xc0, devpriv->mite->daq_io_addr + AckSer); + writeb(0, dev->mmio + OpMode); + writeb(0x00, dev->mmio + ClockReg); + writeb(1, dev->mmio + Sequence); + writeb(0x04, dev->mmio + ReqReg); + writeb(4, dev->mmio + BlockMode); + writeb(3, dev->mmio + LinePolarities); + writeb(0xc0, dev->mmio + AckSer); writel(ni_pcidio_ns_to_timer(&cmd->scan_begin_arg, TRIG_ROUND_NEAREST), - devpriv->mite->daq_io_addr + StartDelay); - writeb(1, devpriv->mite->daq_io_addr + ReqDelay); - writeb(1, devpriv->mite->daq_io_addr + ReqNotDelay); - writeb(1, devpriv->mite->daq_io_addr + AckDelay); - writeb(0x0b, devpriv->mite->daq_io_addr + AckNotDelay); - writeb(0x01, devpriv->mite->daq_io_addr + Data1Delay); + dev->mmio + StartDelay); + writeb(1, dev->mmio + ReqDelay); + writeb(1, dev->mmio + ReqNotDelay); + writeb(1, dev->mmio + AckDelay); + writeb(0x0b, dev->mmio + AckNotDelay); + writeb(0x01, dev->mmio + Data1Delay); /* manual, page 4-5: ClockSpeed comment is incorrectly listed * on DAQOptions */ - writew(0, devpriv->mite->daq_io_addr + ClockSpeed); - writeb(0, devpriv->mite->daq_io_addr + DAQOptions); + writew(0, dev->mmio + ClockSpeed); + writeb(0, dev->mmio + DAQOptions); } else { /* TRIG_EXT */ /* page 4-5, "input with external REQs" */ - writeb(0, devpriv->mite->daq_io_addr + OpMode); - writeb(0x00, devpriv->mite->daq_io_addr + ClockReg); - writeb(0, devpriv->mite->daq_io_addr + Sequence); - writeb(0x00, devpriv->mite->daq_io_addr + ReqReg); - writeb(4, devpriv->mite->daq_io_addr + BlockMode); - if (!(cmd->scan_begin_arg & CR_INVERT)) { - /* Leading Edge pulse mode */ - writeb(0, devpriv->mite->daq_io_addr + LinePolarities); - } else { - /* Trailing Edge pulse mode */ - writeb(2, devpriv->mite->daq_io_addr + LinePolarities); - } - writeb(0x00, devpriv->mite->daq_io_addr + AckSer); - writel(1, devpriv->mite->daq_io_addr + StartDelay); - writeb(1, devpriv->mite->daq_io_addr + ReqDelay); - writeb(1, devpriv->mite->daq_io_addr + ReqNotDelay); - writeb(1, devpriv->mite->daq_io_addr + AckDelay); - writeb(0x0C, devpriv->mite->daq_io_addr + AckNotDelay); - writeb(0x10, devpriv->mite->daq_io_addr + Data1Delay); - writew(0, devpriv->mite->daq_io_addr + ClockSpeed); - writeb(0x60, devpriv->mite->daq_io_addr + DAQOptions); + writeb(0, dev->mmio + OpMode); + writeb(0x00, dev->mmio + ClockReg); + writeb(0, dev->mmio + Sequence); + writeb(0x00, dev->mmio + ReqReg); + writeb(4, dev->mmio + BlockMode); + if (!(cmd->scan_begin_arg & CR_INVERT)) /* Leading Edge */ + writeb(0, dev->mmio + LinePolarities); + else /* Trailing Edge */ + writeb(2, dev->mmio + LinePolarities); + writeb(0x00, dev->mmio + AckSer); + writel(1, dev->mmio + StartDelay); + writeb(1, dev->mmio + ReqDelay); + writeb(1, dev->mmio + ReqNotDelay); + writeb(1, dev->mmio + AckDelay); + writeb(0x0C, dev->mmio + AckNotDelay); + writeb(0x10, dev->mmio + Data1Delay); + writew(0, dev->mmio + ClockSpeed); + writeb(0x60, dev->mmio + DAQOptions); } if (cmd->stop_src == TRIG_COUNT) { writel(cmd->stop_arg, - devpriv->mite->daq_io_addr + Transfer_Count); + dev->mmio + Transfer_Count); } else { /* XXX */ } #ifdef USE_DMA writeb(ClearPrimaryTC | ClearSecondaryTC, - devpriv->mite->daq_io_addr + Group_1_First_Clear); + dev->mmio + Group_1_First_Clear); { int retval = setup_mite_dma(dev, s); + if (retval) return retval; } #else - writeb(0x00, devpriv->mite->daq_io_addr + DMA_Line_Control_Group1); + writeb(0x00, dev->mmio + DMA_Line_Control_Group1); #endif - writeb(0x00, devpriv->mite->daq_io_addr + DMA_Line_Control_Group2); + writeb(0x00, dev->mmio + DMA_Line_Control_Group2); /* clear and enable interrupts */ - writeb(0xff, devpriv->mite->daq_io_addr + Group_1_First_Clear); - /* writeb(ClearExpired, - devpriv->mite->daq_io_addr+Group_1_Second_Clear); */ + writeb(0xff, dev->mmio + Group_1_First_Clear); + /* writeb(ClearExpired, dev->mmio+Group_1_Second_Clear); */ - writeb(IntEn, devpriv->mite->daq_io_addr + Interrupt_Control); - writeb(0x03, - devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control); + writeb(IntEn, dev->mmio + Interrupt_Control); + writeb(0x03, dev->mmio + Master_DMA_And_Interrupt_Control); if (cmd->stop_src == TRIG_NONE) { devpriv->OpModeBits = DataLatching(0) | RunMode(7); @@ -735,8 +739,7 @@ static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } if (cmd->start_src == TRIG_NOW) { /* start */ - writeb(devpriv->OpModeBits, - devpriv->mite->daq_io_addr + OpMode); + writeb(devpriv->OpModeBits, dev->mmio + OpMode); s->async->inttrig = NULL; } else { /* TRIG_INT */ @@ -746,60 +749,17 @@ static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } -static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s) -{ - struct nidio96_private *devpriv = dev->private; - int retval; - unsigned long flags; - - retval = ni_pcidio_request_di_mite_channel(dev); - if (retval) - return retval; - - /* write alloc the entire buffer */ - comedi_buf_write_alloc(s, s->async->prealloc_bufsz); - - spin_lock_irqsave(&devpriv->mite_channel_lock, flags); - if (devpriv->di_mite_chan) { - mite_prep_dma(devpriv->di_mite_chan, 32, 32); - mite_dma_arm(devpriv->di_mite_chan); - } else - retval = -EIO; - spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); - - return retval; -} - -static int ni_pcidio_inttrig(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int trig_num) -{ - struct nidio96_private *devpriv = dev->private; - struct comedi_cmd *cmd = &s->async->cmd; - - if (trig_num != cmd->start_arg) - return -EINVAL; - - writeb(devpriv->OpModeBits, devpriv->mite->daq_io_addr + OpMode); - s->async->inttrig = NULL; - - return 1; -} - static int ni_pcidio_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - struct nidio96_private *devpriv = dev->private; - - writeb(0x00, - devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control); + writeb(0x00, dev->mmio + Master_DMA_And_Interrupt_Control); ni_pcidio_release_di_mite_channel(dev); return 0; } static int ni_pcidio_change(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned long new_size) + struct comedi_subdevice *s) { struct nidio96_private *devpriv = dev->private; int ret; @@ -817,19 +777,16 @@ static int pci_6534_load_fpga(struct comedi_device *dev, const u8 *data, size_t data_len, unsigned long context) { - struct nidio96_private *devpriv = dev->private; static const int timeout = 1000; int fpga_index = context; int i; size_t j; - writew(0x80 | fpga_index, - devpriv->mite->daq_io_addr + Firmware_Control_Register); - writew(0xc0 | fpga_index, - devpriv->mite->daq_io_addr + Firmware_Control_Register); + writew(0x80 | fpga_index, dev->mmio + Firmware_Control_Register); + writew(0xc0 | fpga_index, dev->mmio + Firmware_Control_Register); for (i = 0; - (readw(devpriv->mite->daq_io_addr + - Firmware_Status_Register) & 0x2) == 0 && i < timeout; ++i) { + (readw(dev->mmio + Firmware_Status_Register) & 0x2) == 0 && + i < timeout; ++i) { udelay(1); } if (i == timeout) { @@ -838,11 +795,10 @@ static int pci_6534_load_fpga(struct comedi_device *dev, fpga_index); return -EIO; } - writew(0x80 | fpga_index, - devpriv->mite->daq_io_addr + Firmware_Control_Register); + writew(0x80 | fpga_index, dev->mmio + Firmware_Control_Register); for (i = 0; - readw(devpriv->mite->daq_io_addr + Firmware_Status_Register) != - 0x3 && i < timeout; ++i) { + readw(dev->mmio + Firmware_Status_Register) != 0x3 && + i < timeout; ++i) { udelay(1); } if (i == timeout) { @@ -853,12 +809,11 @@ static int pci_6534_load_fpga(struct comedi_device *dev, } for (j = 0; j + 1 < data_len;) { unsigned int value = data[j++]; + value |= data[j++] << 8; - writew(value, - devpriv->mite->daq_io_addr + Firmware_Data_Register); + writew(value, dev->mmio + Firmware_Data_Register); for (i = 0; - (readw(devpriv->mite->daq_io_addr + - Firmware_Status_Register) & 0x2) == 0 + (readw(dev->mmio + Firmware_Status_Register) & 0x2) == 0 && i < timeout; ++i) { udelay(1); } @@ -871,7 +826,7 @@ static int pci_6534_load_fpga(struct comedi_device *dev, if (need_resched()) schedule(); } - writew(0x0, devpriv->mite->daq_io_addr + Firmware_Control_Register); + writew(0x0, dev->mmio + Firmware_Control_Register); return 0; } @@ -882,30 +837,27 @@ static int pci_6534_reset_fpga(struct comedi_device *dev, int fpga_index) static int pci_6534_reset_fpgas(struct comedi_device *dev) { - struct nidio96_private *devpriv = dev->private; int ret; int i; - writew(0x0, devpriv->mite->daq_io_addr + Firmware_Control_Register); + writew(0x0, dev->mmio + Firmware_Control_Register); for (i = 0; i < 3; ++i) { ret = pci_6534_reset_fpga(dev, i); if (ret < 0) break; } - writew(0x0, devpriv->mite->daq_io_addr + Firmware_Mask_Register); + writew(0x0, dev->mmio + Firmware_Mask_Register); return ret; } static void pci_6534_init_main_fpga(struct comedi_device *dev) { - struct nidio96_private *devpriv = dev->private; - - writel(0, devpriv->mite->daq_io_addr + FPGA_Control1_Register); - writel(0, devpriv->mite->daq_io_addr + FPGA_Control2_Register); - writel(0, devpriv->mite->daq_io_addr + FPGA_SCALS_Counter_Register); - writel(0, devpriv->mite->daq_io_addr + FPGA_SCAMS_Counter_Register); - writel(0, devpriv->mite->daq_io_addr + FPGA_SCBLS_Counter_Register); - writel(0, devpriv->mite->daq_io_addr + FPGA_SCBMS_Counter_Register); + writel(0, dev->mmio + FPGA_Control1_Register); + writel(0, dev->mmio + FPGA_Control2_Register); + writel(0, dev->mmio + FPGA_SCALS_Counter_Register); + writel(0, dev->mmio + FPGA_SCAMS_Counter_Register); + writel(0, dev->mmio + FPGA_SCBLS_Counter_Register); + writel(0, dev->mmio + FPGA_SCBMS_Counter_Register); } static int pci_6534_upload_firmware(struct comedi_device *dev) @@ -937,15 +889,12 @@ static int pci_6534_upload_firmware(struct comedi_device *dev) static void nidio_reset_board(struct comedi_device *dev) { - struct nidio96_private *devpriv = dev->private; - void __iomem *daq_mmio = devpriv->mite->daq_io_addr; - - writel(0, daq_mmio + Port_IO(0)); - writel(0, daq_mmio + Port_Pin_Directions(0)); - writel(0, daq_mmio + Port_Pin_Mask(0)); + writel(0, dev->mmio + Port_IO(0)); + writel(0, dev->mmio + Port_Pin_Directions(0)); + writel(0, dev->mmio + Port_Pin_Mask(0)); /* disable interrupts on board */ - writeb(0, daq_mmio + Master_DMA_And_Interrupt_Control); + writeb(0, dev->mmio + Master_DMA_And_Interrupt_Control); } static int nidio_auto_attach(struct comedi_device *dev, @@ -979,11 +928,9 @@ static int nidio_auto_attach(struct comedi_device *dev, if (!devpriv->mite) return -ENOMEM; - ret = mite_setup(devpriv->mite); - if (ret < 0) { - dev_warn(dev->class_dev, "error setting up mite\n"); + ret = mite_setup(dev, devpriv->mite); + if (ret < 0) return ret; - } devpriv->di_mite_ring = mite_alloc_ring(devpriv->mite); if (devpriv->di_mite_ring == NULL) @@ -1002,7 +949,7 @@ static int nidio_auto_attach(struct comedi_device *dev, return ret; dev_info(dev->class_dev, "%s rev=%d\n", dev->board_name, - readb(devpriv->mite->daq_io_addr + Chip_Version)); + readb(dev->mmio + Chip_Version)); s = &dev->subdevices[0]; @@ -1024,7 +971,7 @@ static int nidio_auto_attach(struct comedi_device *dev, s->async_dma_dir = DMA_BIDIRECTIONAL; s->poll = &ni_pcidio_poll; - irq = mite_irq(devpriv->mite); + irq = pcidev->irq; if (irq) { ret = request_irq(irq, nidio_interrupt, IRQF_SHARED, dev->board_name, dev); @@ -1046,11 +993,10 @@ static void nidio_detach(struct comedi_device *dev) mite_free_ring(devpriv->di_mite_ring); devpriv->di_mite_ring = NULL; } - if (devpriv->mite) { - mite_unsetup(devpriv->mite); - mite_free(devpriv->mite); - } + mite_detach(devpriv->mite); } + if (dev->mmio) + iounmap(dev->mmio); comedi_pci_disable(dev); } diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index 89300dc78e35..da61fa70decf 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -118,13 +118,6 @@ Bugs: #define PCIDMA -#define PCIMIO 1 -#undef ATMIO - -#define MAX_N_CALDACS (16+16+2) - -#define DRV_NAME "ni_pcimio" - /* These are not all the possible ao ranges for 628x boards. They can do OFFSET +- REFERENCE where OFFSET can be 0V, 5V, APFI<0,1>, or AO<0...3> and RANGE can @@ -218,87 +211,79 @@ static const struct ni_board_struct ni_boards[] = { [BOARD_PCIMIO_16XE_50] = { .name = "pci-mio-16xe-50", .n_adchan = 16, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 2048, .alwaysdither = 1, .gainlkup = ai_gain_8, .ai_speed = 50000, .n_aochan = 2, - .aobits = 12, + .ao_maxdata = 0x0fff, .ao_range_table = &range_bipolar10, .ao_speed = 50000, - .num_p0_dio_channels = 8, .caldac = { dac8800, dac8043 }, }, [BOARD_PCIMIO_16XE_10] = { .name = "pci-mio-16xe-10", /* aka pci-6030E */ .n_adchan = 16, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 512, .alwaysdither = 1, .gainlkup = ai_gain_14, .ai_speed = 10000, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 2048, .ao_range_table = &range_ni_E_ao_ext, - .ao_unipolar = 1, .ao_speed = 10000, - .num_p0_dio_channels = 8, .caldac = { dac8800, dac8043, ad8522 }, }, [BOARD_PCI6014] = { .name = "pci-6014", .n_adchan = 16, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 512, .alwaysdither = 1, .gainlkup = ai_gain_4, .ai_speed = 5000, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_range_table = &range_bipolar10, .ao_speed = 100000, - .num_p0_dio_channels = 8, .caldac = { ad8804_debug }, }, [BOARD_PXI6030E] = { .name = "pxi-6030e", .n_adchan = 16, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 512, .alwaysdither = 1, .gainlkup = ai_gain_14, .ai_speed = 10000, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 2048, .ao_range_table = &range_ni_E_ao_ext, - .ao_unipolar = 1, .ao_speed = 10000, - .num_p0_dio_channels = 8, .caldac = { dac8800, dac8043, ad8522 }, }, [BOARD_PCIMIO_16E_1] = { .name = "pci-mio-16e-1", /* aka pci-6070e */ .n_adchan = 16, - .adbits = 12, + .ai_maxdata = 0x0fff, .ai_fifo_depth = 512, .gainlkup = ai_gain_16, .ai_speed = 800, .n_aochan = 2, - .aobits = 12, + .ao_maxdata = 0x0fff, .ao_fifo_depth = 2048, .ao_range_table = &range_ni_E_ao_ext, - .ao_unipolar = 1, .ao_speed = 1000, - .num_p0_dio_channels = 8, .caldac = { mb88341 }, }, [BOARD_PCIMIO_16E_4] = { .name = "pci-mio-16e-4", /* aka pci-6040e */ .n_adchan = 16, - .adbits = 12, + .ai_maxdata = 0x0fff, .ai_fifo_depth = 512, .gainlkup = ai_gain_16, /* @@ -307,216 +292,195 @@ static const struct ni_board_struct ni_boards[] = { */ .ai_speed = 2000, .n_aochan = 2, - .aobits = 12, + .ao_maxdata = 0x0fff, .ao_fifo_depth = 512, .ao_range_table = &range_ni_E_ao_ext, - .ao_unipolar = 1, .ao_speed = 1000, - .num_p0_dio_channels = 8, .caldac = { ad8804_debug }, /* doc says mb88341 */ }, [BOARD_PXI6040E] = { .name = "pxi-6040e", .n_adchan = 16, - .adbits = 12, + .ai_maxdata = 0x0fff, .ai_fifo_depth = 512, .gainlkup = ai_gain_16, .ai_speed = 2000, .n_aochan = 2, - .aobits = 12, + .ao_maxdata = 0x0fff, .ao_fifo_depth = 512, .ao_range_table = &range_ni_E_ao_ext, - .ao_unipolar = 1, .ao_speed = 1000, - .num_p0_dio_channels = 8, .caldac = { mb88341 }, }, [BOARD_PCI6031E] = { .name = "pci-6031e", .n_adchan = 64, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 512, .alwaysdither = 1, .gainlkup = ai_gain_14, .ai_speed = 10000, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 2048, .ao_range_table = &range_ni_E_ao_ext, - .ao_unipolar = 1, .ao_speed = 10000, - .num_p0_dio_channels = 8, .caldac = { dac8800, dac8043, ad8522 }, }, [BOARD_PCI6032E] = { .name = "pci-6032e", .n_adchan = 16, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 512, .alwaysdither = 1, .gainlkup = ai_gain_14, .ai_speed = 10000, - .num_p0_dio_channels = 8, .caldac = { dac8800, dac8043, ad8522 }, }, [BOARD_PCI6033E] = { .name = "pci-6033e", .n_adchan = 64, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 512, .alwaysdither = 1, .gainlkup = ai_gain_14, .ai_speed = 10000, - .num_p0_dio_channels = 8, .caldac = { dac8800, dac8043, ad8522 }, }, [BOARD_PCI6071E] = { .name = "pci-6071e", .n_adchan = 64, - .adbits = 12, + .ai_maxdata = 0x0fff, .ai_fifo_depth = 512, .alwaysdither = 1, .gainlkup = ai_gain_16, .ai_speed = 800, .n_aochan = 2, - .aobits = 12, + .ao_maxdata = 0x0fff, .ao_fifo_depth = 2048, .ao_range_table = &range_ni_E_ao_ext, - .ao_unipolar = 1, .ao_speed = 1000, - .num_p0_dio_channels = 8, .caldac = { ad8804_debug }, }, [BOARD_PCI6023E] = { .name = "pci-6023e", .n_adchan = 16, - .adbits = 12, + .ai_maxdata = 0x0fff, .ai_fifo_depth = 512, .gainlkup = ai_gain_4, .ai_speed = 5000, - .num_p0_dio_channels = 8, .caldac = { ad8804_debug }, /* manual is wrong */ }, [BOARD_PCI6024E] = { .name = "pci-6024e", .n_adchan = 16, - .adbits = 12, + .ai_maxdata = 0x0fff, .ai_fifo_depth = 512, .gainlkup = ai_gain_4, .ai_speed = 5000, .n_aochan = 2, - .aobits = 12, + .ao_maxdata = 0x0fff, .ao_range_table = &range_bipolar10, .ao_speed = 100000, - .num_p0_dio_channels = 8, .caldac = { ad8804_debug }, /* manual is wrong */ }, [BOARD_PCI6025E] = { .name = "pci-6025e", .n_adchan = 16, - .adbits = 12, + .ai_maxdata = 0x0fff, .ai_fifo_depth = 512, .gainlkup = ai_gain_4, .ai_speed = 5000, .n_aochan = 2, - .aobits = 12, + .ao_maxdata = 0x0fff, .ao_range_table = &range_bipolar10, .ao_speed = 100000, - .num_p0_dio_channels = 8, .caldac = { ad8804_debug }, /* manual is wrong */ .has_8255 = 1, }, [BOARD_PXI6025E] = { .name = "pxi-6025e", .n_adchan = 16, - .adbits = 12, + .ai_maxdata = 0x0fff, .ai_fifo_depth = 512, .gainlkup = ai_gain_4, .ai_speed = 5000, .n_aochan = 2, - .aobits = 12, + .ao_maxdata = 0x0fff, .ao_range_table = &range_ni_E_ao_ext, - .ao_unipolar = 1, .ao_speed = 100000, - .num_p0_dio_channels = 8, .caldac = { ad8804_debug }, /* manual is wrong */ .has_8255 = 1, }, [BOARD_PCI6034E] = { .name = "pci-6034e", .n_adchan = 16, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 512, .alwaysdither = 1, .gainlkup = ai_gain_4, .ai_speed = 5000, - .num_p0_dio_channels = 8, .caldac = { ad8804_debug }, }, [BOARD_PCI6035E] = { .name = "pci-6035e", .n_adchan = 16, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 512, .alwaysdither = 1, .gainlkup = ai_gain_4, .ai_speed = 5000, .n_aochan = 2, - .aobits = 12, + .ao_maxdata = 0x0fff, .ao_range_table = &range_bipolar10, .ao_speed = 100000, - .num_p0_dio_channels = 8, .caldac = { ad8804_debug }, }, [BOARD_PCI6052E] = { .name = "pci-6052e", .n_adchan = 16, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 512, .alwaysdither = 1, .gainlkup = ai_gain_16, .ai_speed = 3000, .n_aochan = 2, - .aobits = 16, - .ao_unipolar = 1, + .ao_maxdata = 0xffff, .ao_fifo_depth = 2048, .ao_range_table = &range_ni_E_ao_ext, .ao_speed = 3000, - .num_p0_dio_channels = 8, /* manual is wrong */ .caldac = { ad8804_debug, ad8804_debug, ad8522 }, }, [BOARD_PCI6110] = { .name = "pci-6110", .n_adchan = 4, - .adbits = 12, + .ai_maxdata = 0x0fff, .ai_fifo_depth = 8192, .alwaysdither = 0, .gainlkup = ai_gain_611x, .ai_speed = 200, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .reg_type = ni_reg_611x, .ao_range_table = &range_bipolar10, .ao_fifo_depth = 2048, .ao_speed = 250, - .num_p0_dio_channels = 8, .caldac = { ad8804, ad8804 }, }, [BOARD_PCI6111] = { .name = "pci-6111", .n_adchan = 2, - .adbits = 12, + .ai_maxdata = 0x0fff, .ai_fifo_depth = 8192, .gainlkup = ai_gain_611x, .ai_speed = 200, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .reg_type = ni_reg_611x, .ao_range_table = &range_bipolar10, .ao_fifo_depth = 2048, .ao_speed = 250, - .num_p0_dio_channels = 8, .caldac = { ad8804, ad8804 }, }, #if 0 @@ -524,16 +488,15 @@ static const struct ni_board_struct ni_boards[] = { [BOARD_PCI6115] = { /* .device_id = 0x2ed0, */ .name = "pci-6115", .n_adchan = 4, - .adbits = 12, + .ai_maxdata = 0x0fff, .ai_fifo_depth = 8192, .gainlkup = ai_gain_611x, .ai_speed = 100, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_671x = 1, .ao_fifo_depth = 2048, .ao_speed = 250, - .num_p0_dio_channels = 8, .reg_611x = 1, /* XXX */ .caldac = { ad8804_debug, ad8804_debug, ad8804_debug }, @@ -543,17 +506,16 @@ static const struct ni_board_struct ni_boards[] = { [BOARD_PXI6115] = { /* .device_id = ????, */ .name = "pxi-6115", .n_adchan = 4, - .adbits = 12, + .ai_maxdata = 0x0fff, .ai_fifo_depth = 8192, .gainlkup = ai_gain_611x, .ai_speed = 100, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_671x = 1, .ao_fifo_depth = 2048, .ao_speed = 250, .reg_611x = 1, - .num_p0_dio_channels = 8, /* XXX */ .caldac = { ad8804_debug, ad8804_debug, ad8804_debug }, }, @@ -561,56 +523,51 @@ static const struct ni_board_struct ni_boards[] = { [BOARD_PCI6711] = { .name = "pci-6711", .n_aochan = 4, - .aobits = 12, + .ao_maxdata = 0x0fff, /* data sheet says 8192, but fifo really holds 16384 samples */ .ao_fifo_depth = 16384, .ao_range_table = &range_bipolar10, .ao_speed = 1000, - .num_p0_dio_channels = 8, .reg_type = ni_reg_6711, .caldac = { ad8804_debug }, }, [BOARD_PXI6711] = { .name = "pxi-6711", .n_aochan = 4, - .aobits = 12, + .ao_maxdata = 0x0fff, .ao_fifo_depth = 16384, .ao_range_table = &range_bipolar10, .ao_speed = 1000, - .num_p0_dio_channels = 8, .reg_type = ni_reg_6711, .caldac = { ad8804_debug }, }, [BOARD_PCI6713] = { .name = "pci-6713", .n_aochan = 8, - .aobits = 12, + .ao_maxdata = 0x0fff, .ao_fifo_depth = 16384, .ao_range_table = &range_bipolar10, .ao_speed = 1000, - .num_p0_dio_channels = 8, .reg_type = ni_reg_6713, .caldac = { ad8804_debug, ad8804_debug }, }, [BOARD_PXI6713] = { .name = "pxi-6713", .n_aochan = 8, - .aobits = 12, + .ao_maxdata = 0x0fff, .ao_fifo_depth = 16384, .ao_range_table = &range_bipolar10, .ao_speed = 1000, - .num_p0_dio_channels = 8, .reg_type = ni_reg_6713, .caldac = { ad8804_debug, ad8804_debug }, }, [BOARD_PCI6731] = { .name = "pci-6731", .n_aochan = 4, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 8192, .ao_range_table = &range_bipolar10, .ao_speed = 1000, - .num_p0_dio_channels = 8, .reg_type = ni_reg_6711, .caldac = { ad8804_debug }, }, @@ -618,10 +575,9 @@ static const struct ni_board_struct ni_boards[] = { [BOARD_PXI6731] = { /* .device_id = ????, */ .name = "pxi-6731", .n_aochan = 4, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 8192, .ao_range_table = &range_bipolar10, - .num_p0_dio_channels = 8, .reg_type = ni_reg_6711, .caldac = { ad8804_debug }, }, @@ -629,759 +585,462 @@ static const struct ni_board_struct ni_boards[] = { [BOARD_PCI6733] = { .name = "pci-6733", .n_aochan = 8, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 16384, .ao_range_table = &range_bipolar10, .ao_speed = 1000, - .num_p0_dio_channels = 8, .reg_type = ni_reg_6713, .caldac = { ad8804_debug, ad8804_debug }, }, [BOARD_PXI6733] = { .name = "pxi-6733", .n_aochan = 8, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 16384, .ao_range_table = &range_bipolar10, .ao_speed = 1000, - .num_p0_dio_channels = 8, .reg_type = ni_reg_6713, .caldac = { ad8804_debug, ad8804_debug }, }, [BOARD_PXI6071E] = { .name = "pxi-6071e", .n_adchan = 64, - .adbits = 12, + .ai_maxdata = 0x0fff, .ai_fifo_depth = 512, .alwaysdither = 1, .gainlkup = ai_gain_16, .ai_speed = 800, .n_aochan = 2, - .aobits = 12, + .ao_maxdata = 0x0fff, .ao_fifo_depth = 2048, .ao_range_table = &range_ni_E_ao_ext, - .ao_unipolar = 1, .ao_speed = 1000, - .num_p0_dio_channels = 8, .caldac = { ad8804_debug }, }, [BOARD_PXI6070E] = { .name = "pxi-6070e", .n_adchan = 16, - .adbits = 12, + .ai_maxdata = 0x0fff, .ai_fifo_depth = 512, .alwaysdither = 1, .gainlkup = ai_gain_16, .ai_speed = 800, .n_aochan = 2, - .aobits = 12, + .ao_maxdata = 0x0fff, .ao_fifo_depth = 2048, .ao_range_table = &range_ni_E_ao_ext, - .ao_unipolar = 1, .ao_speed = 1000, - .num_p0_dio_channels = 8, .caldac = { ad8804_debug }, }, [BOARD_PXI6052E] = { .name = "pxi-6052e", .n_adchan = 16, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 512, .alwaysdither = 1, .gainlkup = ai_gain_16, .ai_speed = 3000, .n_aochan = 2, - .aobits = 16, - .ao_unipolar = 1, + .ao_maxdata = 0xffff, .ao_fifo_depth = 2048, .ao_range_table = &range_ni_E_ao_ext, .ao_speed = 3000, - .num_p0_dio_channels = 8, .caldac = { mb88341, mb88341, ad8522 }, }, [BOARD_PXI6031E] = { .name = "pxi-6031e", .n_adchan = 64, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 512, .alwaysdither = 1, .gainlkup = ai_gain_14, .ai_speed = 10000, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 2048, .ao_range_table = &range_ni_E_ao_ext, - .ao_unipolar = 1, .ao_speed = 10000, - .num_p0_dio_channels = 8, .caldac = { dac8800, dac8043, ad8522 }, }, [BOARD_PCI6036E] = { .name = "pci-6036e", .n_adchan = 16, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 512, .alwaysdither = 1, .gainlkup = ai_gain_4, .ai_speed = 5000, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_range_table = &range_bipolar10, .ao_speed = 100000, - .num_p0_dio_channels = 8, .caldac = { ad8804_debug }, }, [BOARD_PCI6220] = { .name = "pci-6220", .n_adchan = 16, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 512, /* FIXME: guess */ .gainlkup = ai_gain_622x, .ai_speed = 4000, - .num_p0_dio_channels = 8, .reg_type = ni_reg_622x, .caldac = { caldac_none }, }, [BOARD_PCI6221] = { .name = "pci-6221", .n_adchan = 16, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 4095, .gainlkup = ai_gain_622x, .ai_speed = 4000, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 8191, .ao_range_table = &range_bipolar10, .reg_type = ni_reg_622x, .ao_speed = 1200, - .num_p0_dio_channels = 8, .caldac = { caldac_none }, }, [BOARD_PCI6221_37PIN] = { .name = "pci-6221_37pin", .n_adchan = 16, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 4095, .gainlkup = ai_gain_622x, .ai_speed = 4000, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 8191, .ao_range_table = &range_bipolar10, .reg_type = ni_reg_622x, .ao_speed = 1200, - .num_p0_dio_channels = 8, .caldac = { caldac_none }, }, [BOARD_PCI6224] = { .name = "pci-6224", .n_adchan = 32, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 4095, .gainlkup = ai_gain_622x, .ai_speed = 4000, .reg_type = ni_reg_622x, - .num_p0_dio_channels = 32, + .has_32dio_chan = 1, .caldac = { caldac_none }, }, [BOARD_PXI6224] = { .name = "pxi-6224", .n_adchan = 32, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 4095, .gainlkup = ai_gain_622x, .ai_speed = 4000, .reg_type = ni_reg_622x, - .num_p0_dio_channels = 32, + .has_32dio_chan = 1, .caldac = { caldac_none }, }, [BOARD_PCI6225] = { .name = "pci-6225", .n_adchan = 80, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 4095, .gainlkup = ai_gain_622x, .ai_speed = 4000, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 8191, .ao_range_table = &range_bipolar10, .reg_type = ni_reg_622x, .ao_speed = 1200, - .num_p0_dio_channels = 32, + .has_32dio_chan = 1, .caldac = { caldac_none }, }, [BOARD_PXI6225] = { .name = "pxi-6225", .n_adchan = 80, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 4095, .gainlkup = ai_gain_622x, .ai_speed = 4000, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 8191, .ao_range_table = &range_bipolar10, .reg_type = ni_reg_622x, .ao_speed = 1200, - .num_p0_dio_channels = 32, + .has_32dio_chan = 1, .caldac = { caldac_none }, }, [BOARD_PCI6229] = { .name = "pci-6229", .n_adchan = 32, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 4095, .gainlkup = ai_gain_622x, .ai_speed = 4000, .n_aochan = 4, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 8191, .ao_range_table = &range_bipolar10, .reg_type = ni_reg_622x, .ao_speed = 1200, - .num_p0_dio_channels = 32, + .has_32dio_chan = 1, .caldac = { caldac_none }, }, [BOARD_PCI6250] = { .name = "pci-6250", .n_adchan = 16, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 4095, .gainlkup = ai_gain_628x, .ai_speed = 800, .reg_type = ni_reg_625x, - .num_p0_dio_channels = 8, .caldac = { caldac_none }, }, [BOARD_PCI6251] = { .name = "pci-6251", .n_adchan = 16, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 4095, .gainlkup = ai_gain_628x, .ai_speed = 800, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 8191, .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_speed = 350, - .num_p0_dio_channels = 8, .caldac = { caldac_none }, }, [BOARD_PCIE6251] = { .name = "pcie-6251", .n_adchan = 16, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 4095, .gainlkup = ai_gain_628x, .ai_speed = 800, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 8191, .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_speed = 350, - .num_p0_dio_channels = 8, .caldac = { caldac_none }, }, [BOARD_PXIE6251] = { .name = "pxie-6251", .n_adchan = 16, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 4095, .gainlkup = ai_gain_628x, .ai_speed = 800, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 8191, .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_speed = 350, - .num_p0_dio_channels = 8, .caldac = { caldac_none }, }, [BOARD_PCI6254] = { .name = "pci-6254", .n_adchan = 32, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 4095, .gainlkup = ai_gain_628x, .ai_speed = 800, .reg_type = ni_reg_625x, - .num_p0_dio_channels = 32, + .has_32dio_chan = 1, .caldac = { caldac_none }, }, [BOARD_PCI6259] = { .name = "pci-6259", .n_adchan = 32, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 4095, .gainlkup = ai_gain_628x, .ai_speed = 800, .n_aochan = 4, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 8191, .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_speed = 350, - .num_p0_dio_channels = 32, + .has_32dio_chan = 1, .caldac = { caldac_none }, }, [BOARD_PCIE6259] = { .name = "pcie-6259", .n_adchan = 32, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 4095, .gainlkup = ai_gain_628x, .ai_speed = 800, .n_aochan = 4, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 8191, .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_speed = 350, - .num_p0_dio_channels = 32, + .has_32dio_chan = 1, .caldac = { caldac_none }, }, [BOARD_PCI6280] = { .name = "pci-6280", .n_adchan = 16, - .adbits = 18, + .ai_maxdata = 0x3ffff, .ai_fifo_depth = 2047, .gainlkup = ai_gain_628x, .ai_speed = 1600, .ao_fifo_depth = 8191, .reg_type = ni_reg_628x, - .num_p0_dio_channels = 8, .caldac = { caldac_none }, }, [BOARD_PCI6281] = { .name = "pci-6281", .n_adchan = 16, - .adbits = 18, + .ai_maxdata = 0x3ffff, .ai_fifo_depth = 2047, .gainlkup = ai_gain_628x, .ai_speed = 1600, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 8191, .ao_range_table = &range_ni_M_628x_ao, .reg_type = ni_reg_628x, - .ao_unipolar = 1, .ao_speed = 350, - .num_p0_dio_channels = 8, .caldac = { caldac_none }, }, [BOARD_PXI6281] = { .name = "pxi-6281", .n_adchan = 16, - .adbits = 18, + .ai_maxdata = 0x3ffff, .ai_fifo_depth = 2047, .gainlkup = ai_gain_628x, .ai_speed = 1600, .n_aochan = 2, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 8191, .ao_range_table = &range_ni_M_628x_ao, .reg_type = ni_reg_628x, - .ao_unipolar = 1, .ao_speed = 350, - .num_p0_dio_channels = 8, .caldac = { caldac_none }, }, [BOARD_PCI6284] = { .name = "pci-6284", .n_adchan = 32, - .adbits = 18, + .ai_maxdata = 0x3ffff, .ai_fifo_depth = 2047, .gainlkup = ai_gain_628x, .ai_speed = 1600, .reg_type = ni_reg_628x, - .num_p0_dio_channels = 32, + .has_32dio_chan = 1, .caldac = { caldac_none }, }, [BOARD_PCI6289] = { .name = "pci-6289", .n_adchan = 32, - .adbits = 18, + .ai_maxdata = 0x3ffff, .ai_fifo_depth = 2047, .gainlkup = ai_gain_628x, .ai_speed = 1600, .n_aochan = 4, - .aobits = 16, + .ao_maxdata = 0xffff, .ao_fifo_depth = 8191, .ao_range_table = &range_ni_M_628x_ao, .reg_type = ni_reg_628x, - .ao_unipolar = 1, .ao_speed = 350, - .num_p0_dio_channels = 32, + .has_32dio_chan = 1, .caldac = { caldac_none }, }, [BOARD_PCI6143] = { .name = "pci-6143", .n_adchan = 8, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 1024, .gainlkup = ai_gain_6143, .ai_speed = 4000, .reg_type = ni_reg_6143, - .num_p0_dio_channels = 8, .caldac = { ad8804_debug, ad8804_debug }, }, [BOARD_PXI6143] = { .name = "pxi-6143", .n_adchan = 8, - .adbits = 16, + .ai_maxdata = 0xffff, .ai_fifo_depth = 1024, .gainlkup = ai_gain_6143, .ai_speed = 4000, .reg_type = ni_reg_6143, - .num_p0_dio_channels = 8, .caldac = { ad8804_debug, ad8804_debug }, }, }; -struct ni_private { -NI_PRIVATE_COMMON}; - -/* How we access registers */ - -#define ni_writel(a, b) (writel((a), devpriv->mite->daq_io_addr + (b))) -#define ni_readl(a) (readl(devpriv->mite->daq_io_addr + (a))) -#define ni_writew(a, b) (writew((a), devpriv->mite->daq_io_addr + (b))) -#define ni_readw(a) (readw(devpriv->mite->daq_io_addr + (a))) -#define ni_writeb(a, b) (writeb((a), devpriv->mite->daq_io_addr + (b))) -#define ni_readb(a) (readb(devpriv->mite->daq_io_addr + (a))) - -/* How we access STC registers */ - -/* We automatically take advantage of STC registers that can be - * read/written directly in the I/O space of the board. Most - * PCIMIO devices map the low 8 STC registers to iobase+addr*2. - * The 611x devices map the write registers to iobase+addr*2, and - * the read registers to iobase+(addr-1)*2. */ -/* However, the 611x boards still aren't working, so I'm disabling - * non-windowed STC access temporarily */ +#include "ni_mio_common.c" -static void e_series_win_out(struct comedi_device *dev, uint16_t data, int reg) +static int pcimio_ai_change(struct comedi_device *dev, + struct comedi_subdevice *s) { struct ni_private *devpriv = dev->private; - unsigned long flags; + int ret; + + ret = mite_buf_change(devpriv->ai_mite_ring, s); + if (ret < 0) + return ret; - spin_lock_irqsave(&devpriv->window_lock, flags); - ni_writew(reg, Window_Address); - ni_writew(data, Window_Data); - spin_unlock_irqrestore(&devpriv->window_lock, flags); + return 0; } -static uint16_t e_series_win_in(struct comedi_device *dev, int reg) +static int pcimio_ao_change(struct comedi_device *dev, + struct comedi_subdevice *s) { struct ni_private *devpriv = dev->private; - unsigned long flags; - uint16_t ret; + int ret; - spin_lock_irqsave(&devpriv->window_lock, flags); - ni_writew(reg, Window_Address); - ret = ni_readw(Window_Data); - spin_unlock_irqrestore(&devpriv->window_lock, flags); + ret = mite_buf_change(devpriv->ao_mite_ring, s); + if (ret < 0) + return ret; - return ret; + return 0; } -static void m_series_stc_writew(struct comedi_device *dev, uint16_t data, - int reg) +static int pcimio_gpct0_change(struct comedi_device *dev, + struct comedi_subdevice *s) { struct ni_private *devpriv = dev->private; - 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 actually a 32 bit register on m series boards */ - ni_writel(data, M_Offset_AI_SI2_Load_A); - return; - break; - case AI_SI2_Load_B_Register: - /* this is actually a 32 bit register on m series boards */ - ni_writel(data, M_Offset_AI_SI2_Load_B); - return; - break; - 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; - break; - 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; - break; - case RTSI_Trig_Direction_Register: - offset = M_Offset_RTSI_Trig_Direction; - 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", - __func__, reg); - BUG(); - return; - break; - } - ni_writew(data, offset); -} + int ret; -static uint16_t m_series_stc_readw(struct comedi_device *dev, int reg) -{ - struct ni_private *devpriv = dev->private; - 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(M_Offset_SCXI_Serial_Data_In); - break; - 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; - default: - dev_warn(dev->class_dev, - "%s: bug! unhandled register=0x%x in switch.\n", - __func__, reg); - BUG(); - return 0; - break; - } - return ni_readw(offset); + ret = mite_buf_change(devpriv->gpct_mite_ring[0], s); + if (ret < 0) + return ret; + + return 0; } -static void m_series_stc_writel(struct comedi_device *dev, uint32_t data, - int reg) +static int pcimio_gpct1_change(struct comedi_device *dev, + struct comedi_subdevice *s) { struct ni_private *devpriv = dev->private; - unsigned offset; - - 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", - __func__, reg); - BUG(); - return; - break; - } - ni_writel(data, offset); + int ret; + + ret = mite_buf_change(devpriv->gpct_mite_ring[1], s); + if (ret < 0) + return ret; + + return 0; } -static uint32_t m_series_stc_readl(struct comedi_device *dev, int reg) +static int pcimio_dio_change(struct comedi_device *dev, + struct comedi_subdevice *s) { struct ni_private *devpriv = dev->private; - unsigned offset; - - 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", - __func__, reg); - BUG(); - return 0; - break; - } - return ni_readl(offset); -} - -#define interrupt_pin(a) 0 -#define IRQ_POLARITY 1 + int ret; -#define NI_E_IRQ_FLAGS IRQF_SHARED + ret = mite_buf_change(devpriv->cdo_mite_ring, s); + if (ret < 0) + return ret; -#include "ni_mio_common.c" + return 0; +} -static int pcimio_ai_change(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned long new_size); -static int pcimio_ao_change(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned long new_size); -static int pcimio_gpct0_change(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned long new_size); -static int pcimio_gpct1_change(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned long new_size); -static int pcimio_dio_change(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned long new_size); static void m_series_init_eeprom_buffer(struct comedi_device *dev) { @@ -1408,12 +1067,12 @@ static void m_series_init_eeprom_buffer(struct comedi_device *dev) BUG_ON(serial_number_eeprom_length > sizeof(devpriv->serial_number)); for (i = 0; i < serial_number_eeprom_length; ++i) { char *byte_ptr = (char *)&devpriv->serial_number + i; - *byte_ptr = ni_readb(serial_number_eeprom_offset + i); + *byte_ptr = ni_readb(dev, serial_number_eeprom_offset + i); } devpriv->serial_number = be32_to_cpu(devpriv->serial_number); for (i = 0; i < M_SERIES_EEPROM_SIZE; ++i) - devpriv->eeprom_buffer[i] = ni_readb(Start_Cal_EEPROM + i); + devpriv->eeprom_buffer[i] = ni_readb(dev, Start_Cal_EEPROM + i); writel(old_iodwbsr1_bits, devpriv->mite->mite_io_addr + MITE_IODWBSR_1); writel(old_iodwbsr_bits, devpriv->mite->mite_io_addr + MITE_IODWBSR); @@ -1427,21 +1086,26 @@ static void init_6143(struct comedi_device *dev) struct ni_private *devpriv = dev->private; /* Disable interrupts */ - devpriv->stc_writew(dev, 0, Interrupt_Control_Register); + ni_stc_writew(dev, 0, Interrupt_Control_Register); /* Initialise 6143 AI specific bits */ - ni_writeb(0x00, Magic_6143); /* Set G0,G1 DMA mode to E series version */ - ni_writeb(0x80, PipelineDelay_6143); /* Set EOCMode, ADCMode and pipelinedelay */ - ni_writeb(0x00, EOC_Set_6143); /* Set EOC Delay */ + + /* Set G0,G1 DMA mode to E series version */ + ni_writeb(dev, 0x00, Magic_6143); + /* Set EOCMode, ADCMode and pipelinedelay */ + ni_writeb(dev, 0x80, PipelineDelay_6143); + /* Set EOC Delay */ + ni_writeb(dev, 0x00, EOC_Set_6143); /* Set the FIFO half full level */ - ni_writel(board->ai_fifo_depth / 2, AIFIFO_Flag_6143); + ni_writel(dev, board->ai_fifo_depth / 2, AIFIFO_Flag_6143); /* Strobe Relay disable bit */ devpriv->ai_calib_source_enabled = 0; - ni_writew(devpriv->ai_calib_source | Calibration_Channel_6143_RelayOff, + ni_writew(dev, devpriv->ai_calib_source | + Calibration_Channel_6143_RelayOff, Calibration_Channel_6143); - ni_writew(devpriv->ai_calib_source, Calibration_Channel_6143); + ni_writew(dev, devpriv->ai_calib_source, Calibration_Channel_6143); } static void pcimio_detach(struct comedi_device *dev) @@ -1457,11 +1121,10 @@ static void pcimio_detach(struct comedi_device *dev) mite_free_ring(devpriv->cdo_mite_ring); mite_free_ring(devpriv->gpct_mite_ring[0]); mite_free_ring(devpriv->gpct_mite_ring[1]); - if (devpriv->mite) { - mite_unsetup(devpriv->mite); - mite_free(devpriv->mite); - } + mite_detach(devpriv->mite); } + if (dev->mmio) + iounmap(dev->mmio); comedi_pci_disable(dev); } @@ -1494,23 +1157,30 @@ static int pcimio_auto_attach(struct comedi_device *dev, if (!devpriv->mite) return -ENOMEM; - if (board->reg_type & ni_reg_m_series_mask) { - devpriv->stc_writew = &m_series_stc_writew; - devpriv->stc_readw = &m_series_stc_readw; - devpriv->stc_writel = &m_series_stc_writel; - devpriv->stc_readl = &m_series_stc_readl; - } else { - devpriv->stc_writew = &e_series_win_out; - devpriv->stc_readw = &e_series_win_in; - devpriv->stc_writel = &win_out2; - devpriv->stc_readl = &win_in2; - } - - ret = mite_setup(devpriv->mite); - if (ret < 0) { - pr_warn("error setting up mite\n"); + if (board->reg_type & ni_reg_m_series_mask) + devpriv->is_m_series = 1; + if (board->reg_type & ni_reg_6xxx_mask) + devpriv->is_6xxx = 1; + if (board->reg_type == ni_reg_611x) + devpriv->is_611x = 1; + if (board->reg_type == ni_reg_6143) + devpriv->is_6143 = 1; + if (board->reg_type == ni_reg_622x) + devpriv->is_622x = 1; + if (board->reg_type == ni_reg_625x) + devpriv->is_625x = 1; + if (board->reg_type == ni_reg_628x) + devpriv->is_628x = 1; + if (board->reg_type & ni_reg_67xx_mask) + devpriv->is_67xx = 1; + if (board->reg_type == ni_reg_6711) + devpriv->is_6711 = 1; + if (board->reg_type == ni_reg_6713) + devpriv->is_6713 = 1; + + ret = mite_setup(dev, devpriv->mite); + if (ret < 0) return ret; - } devpriv->ai_mite_ring = mite_alloc_ring(devpriv->mite); if (devpriv->ai_mite_ring == NULL) @@ -1528,20 +1198,20 @@ static int pcimio_auto_attach(struct comedi_device *dev, if (devpriv->gpct_mite_ring[1] == NULL) return -ENOMEM; - if (board->reg_type & ni_reg_m_series_mask) + if (devpriv->is_m_series) m_series_init_eeprom_buffer(dev); - if (board->reg_type == ni_reg_6143) + if (devpriv->is_6143) init_6143(dev); - irq = mite_irq(devpriv->mite); + irq = pcidev->irq; if (irq) { - ret = request_irq(irq, ni_E_interrupt, NI_E_IRQ_FLAGS, + ret = request_irq(irq, ni_E_interrupt, IRQF_SHARED, dev->board_name, dev); if (ret == 0) dev->irq = irq; } - ret = ni_E_init(dev); + ret = ni_E_init(dev, 0, 1); if (ret < 0) return ret; @@ -1554,73 +1224,6 @@ static int pcimio_auto_attach(struct comedi_device *dev, return 0; } -static int pcimio_ai_change(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned long new_size) -{ - struct ni_private *devpriv = dev->private; - int ret; - - ret = mite_buf_change(devpriv->ai_mite_ring, s); - if (ret < 0) - return ret; - - return 0; -} - -static int pcimio_ao_change(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned long new_size) -{ - struct ni_private *devpriv = dev->private; - int ret; - - ret = mite_buf_change(devpriv->ao_mite_ring, s); - if (ret < 0) - return ret; - - return 0; -} - -static int pcimio_gpct0_change(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned long new_size) -{ - struct ni_private *devpriv = dev->private; - int ret; - - ret = mite_buf_change(devpriv->gpct_mite_ring[0], s); - if (ret < 0) - return ret; - - return 0; -} - -static int pcimio_gpct1_change(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned long new_size) -{ - struct ni_private *devpriv = dev->private; - int ret; - - ret = mite_buf_change(devpriv->gpct_mite_ring[1], s); - if (ret < 0) - return ret; - - return 0; -} - -static int pcimio_dio_change(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned long new_size) -{ - struct ni_private *devpriv = dev->private; - int ret; - - ret = mite_buf_change(devpriv->cdo_mite_ring, s); - if (ret < 0) - return ret; - - return 0; -} - static struct comedi_driver ni_pcimio_driver = { .driver_name = "ni_pcimio", .module = THIS_MODULE, diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h index f0630b7897b5..a2841292ddd4 100644 --- a/drivers/staging/comedi/drivers/ni_stc.h +++ b/drivers/staging/comedi/drivers/ni_stc.h @@ -1285,14 +1285,6 @@ static inline unsigned MSeries_PFI_Output_Select_Source(unsigned channel, return (bits >> ((channel % 3) * 5)) & 0x1f; }; -enum MSeries_Gi_DMA_Config_Bits { - Gi_DMA_BankSW_Error_Bit = 0x10, - Gi_DMA_Reset_Bit = 0x8, - Gi_DMA_Int_Enable_Bit = 0x4, - Gi_DMA_Write_Bit = 0x2, - Gi_DMA_Enable_Bit = 0x1, -}; - static inline unsigned MSeries_PFI_Filter_Select_Mask(unsigned channel) { return 0x3 << (channel * 2); @@ -1388,12 +1380,12 @@ enum Interrupt_C_Status_Bits { #define M_SERIES_EEPROM_SIZE 1024 struct ni_board_struct { + const char *name; int device_id; int isapnp_id; - char *name; int n_adchan; - int adbits; + unsigned int ai_maxdata; int ai_fifo_depth; unsigned int alwaysdither:1; @@ -1401,107 +1393,100 @@ struct ni_board_struct { int ai_speed; int n_aochan; - int aobits; + unsigned int ao_maxdata; int ao_fifo_depth; const struct comedi_lrange *ao_range_table; unsigned ao_speed; - unsigned num_p0_dio_channels; - int reg_type; - unsigned int ao_unipolar:1; unsigned int has_8255:1; - unsigned int has_analog_trig:1; + unsigned int has_32dio_chan:1; enum caldac_enum caldac[3]; }; -#define MAX_N_AO_CHAN 8 -#define NUM_GPCT 2 - -#define NI_PRIVATE_COMMON \ - uint16_t (*stc_readw)(struct comedi_device *dev, int register); \ - uint32_t (*stc_readl)(struct comedi_device *dev, int register); \ - void (*stc_writew)(struct comedi_device *dev, uint16_t value, int register); \ - void (*stc_writel)(struct comedi_device *dev, uint32_t value, int register); \ - \ - unsigned short dio_output; \ - unsigned short dio_control; \ - int ao0p, ao1p; \ - int lastchan; \ - int last_do; \ - int rt_irq; \ - int irqmask; \ - int aimode; \ - int ai_continuous; \ - int blocksize; \ - int n_left; \ - unsigned int ai_calib_source; \ - unsigned int ai_calib_source_enabled; \ - spinlock_t window_lock; \ - spinlock_t soft_reg_copy_lock; \ - spinlock_t mite_channel_lock; \ - \ - int changain_state; \ - unsigned int changain_spec; \ - \ - unsigned int caldac_maxdata_list[MAX_N_CALDACS]; \ - unsigned short ao[MAX_N_AO_CHAN]; \ - unsigned short caldacs[MAX_N_CALDACS]; \ - \ - unsigned short ai_cmd2; \ - \ - unsigned short ao_conf[MAX_N_AO_CHAN]; \ - unsigned short ao_mode1; \ - unsigned short ao_mode2; \ - unsigned short ao_mode3; \ - unsigned short ao_cmd1; \ - unsigned short ao_cmd2; \ - unsigned short ao_cmd3; \ - unsigned short ao_trigger_select; \ - \ - struct ni_gpct_device *counter_dev; \ - unsigned short an_trig_etc_reg; \ - \ - unsigned ai_offset[512]; \ - \ - unsigned long serial_interval_ns; \ - unsigned char serial_hw_mode; \ - unsigned short clock_and_fout; \ - unsigned short clock_and_fout2; \ - \ - unsigned short int_a_enable_reg; \ - unsigned short int_b_enable_reg; \ - unsigned short io_bidirection_pin_reg; \ - unsigned short rtsi_trig_direction_reg; \ - unsigned short rtsi_trig_a_output_reg; \ - unsigned short rtsi_trig_b_output_reg; \ - unsigned short pfi_output_select_reg[NUM_PFI_OUTPUT_SELECT_REGS]; \ - unsigned short ai_ao_select_reg; \ - unsigned short g0_g1_select_reg; \ - unsigned short cdio_dma_select_reg; \ - \ - unsigned clock_ns; \ - unsigned clock_source; \ - \ - unsigned short atrig_mode; \ - unsigned short atrig_high; \ - unsigned short atrig_low; \ - \ - unsigned short pwm_up_count; \ - unsigned short pwm_down_count; \ - \ - unsigned short ai_fifo_buffer[0x2000]; \ - uint8_t eeprom_buffer[M_SERIES_EEPROM_SIZE]; \ - uint32_t serial_number; \ - \ - struct mite_struct *mite; \ - struct mite_channel *ai_mite_chan; \ - struct mite_channel *ao_mite_chan;\ - struct mite_channel *cdo_mite_chan;\ - struct mite_dma_descriptor_ring *ai_mite_ring; \ - struct mite_dma_descriptor_ring *ao_mite_ring; \ - struct mite_dma_descriptor_ring *cdo_mite_ring; \ +#define MAX_N_CALDACS 34 +#define MAX_N_AO_CHAN 8 +#define NUM_GPCT 2 + +struct ni_private { + unsigned short dio_output; + unsigned short dio_control; + int aimode; + unsigned int ai_calib_source; + unsigned int ai_calib_source_enabled; + spinlock_t window_lock; + spinlock_t soft_reg_copy_lock; + spinlock_t mite_channel_lock; + + int changain_state; + unsigned int changain_spec; + + unsigned int caldac_maxdata_list[MAX_N_CALDACS]; + unsigned short ao[MAX_N_AO_CHAN]; + unsigned short caldacs[MAX_N_CALDACS]; + + unsigned short ai_cmd2; + + unsigned short ao_conf[MAX_N_AO_CHAN]; + unsigned short ao_mode1; + unsigned short ao_mode2; + unsigned short ao_mode3; + unsigned short ao_cmd1; + unsigned short ao_cmd2; + unsigned short ao_trigger_select; + + struct ni_gpct_device *counter_dev; + unsigned short an_trig_etc_reg; + + unsigned ai_offset[512]; + + unsigned long serial_interval_ns; + unsigned char serial_hw_mode; + unsigned short clock_and_fout; + unsigned short clock_and_fout2; + + unsigned short int_a_enable_reg; + unsigned short int_b_enable_reg; + unsigned short io_bidirection_pin_reg; + unsigned short rtsi_trig_direction_reg; + unsigned short rtsi_trig_a_output_reg; + unsigned short rtsi_trig_b_output_reg; + unsigned short pfi_output_select_reg[NUM_PFI_OUTPUT_SELECT_REGS]; + unsigned short ai_ao_select_reg; + unsigned short g0_g1_select_reg; + unsigned short cdio_dma_select_reg; + + unsigned clock_ns; + unsigned clock_source; + + unsigned short pwm_up_count; + unsigned short pwm_down_count; + + unsigned short ai_fifo_buffer[0x2000]; + uint8_t eeprom_buffer[M_SERIES_EEPROM_SIZE]; + uint32_t serial_number; + + struct mite_struct *mite; + struct mite_channel *ai_mite_chan; + struct mite_channel *ao_mite_chan; + struct mite_channel *cdo_mite_chan; + struct mite_dma_descriptor_ring *ai_mite_ring; + struct mite_dma_descriptor_ring *ao_mite_ring; + struct mite_dma_descriptor_ring *cdo_mite_ring; struct mite_dma_descriptor_ring *gpct_mite_ring[NUM_GPCT]; + /* ni_pcimio board type flags (based on the boardinfo reg_type) */ + unsigned int is_m_series:1; + unsigned int is_6xxx:1; + unsigned int is_611x:1; + unsigned int is_6143:1; + unsigned int is_622x:1; + unsigned int is_625x:1; + unsigned int is_628x:1; + unsigned int is_67xx:1; + unsigned int is_6711:1; + unsigned int is_6713:1; +}; + #endif /* _COMEDI_NI_STC_H */ diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 92691b491c24..0525292c1d8b 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -49,363 +49,336 @@ TODO: #include "ni_tio_internal.h" -static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter, - unsigned generic_clock_source); -static unsigned ni_tio_generic_clock_src_select(const struct ni_gpct *counter); +/* + * clock sources for ni e and m series boards, + * get bits with GI_SRC_SEL() + */ +#define NI_M_TIMEBASE_1_CLK 0x0 /* 20MHz */ +#define NI_M_PFI_CLK(x) (((x) < 10) ? (1 + (x)) : (0xb + (x))) +#define NI_M_RTSI_CLK(x) (((x) == 7) ? 0x1b : (0xb + (x))) +#define NI_M_TIMEBASE_2_CLK 0x12 /* 100KHz */ +#define NI_M_NEXT_TC_CLK 0x13 +#define NI_M_NEXT_GATE_CLK 0x14 /* Gi_Src_SubSelect=0 */ +#define NI_M_PXI_STAR_TRIGGER_CLK 0x14 /* Gi_Src_SubSelect=1 */ +#define NI_M_PXI10_CLK 0x1d +#define NI_M_TIMEBASE_3_CLK 0x1e /* 80MHz, Gi_Src_SubSelect=0 */ +#define NI_M_ANALOG_TRIGGER_OUT_CLK 0x1e /* Gi_Src_SubSelect=1 */ +#define NI_M_LOGIC_LOW_CLK 0x1f +#define NI_M_MAX_PFI_CHAN 15 +#define NI_M_MAX_RTSI_CHAN 7 -static inline enum Gi_Counting_Mode_Reg_Bits Gi_Alternate_Sync_Bit(enum - ni_gpct_variant - variant) +/* + * clock sources for ni_660x boards, + * get bits with GI_SRC_SEL() + */ +#define NI_660X_TIMEBASE_1_CLK 0x0 /* 20MHz */ +#define NI_660X_SRC_PIN_I_CLK 0x1 +#define NI_660X_SRC_PIN_CLK(x) (0x2 + (x)) +#define NI_660X_NEXT_GATE_CLK 0xa +#define NI_660X_RTSI_CLK(x) (0xb + (x)) +#define NI_660X_TIMEBASE_2_CLK 0x12 /* 100KHz */ +#define NI_660X_NEXT_TC_CLK 0x13 +#define NI_660X_TIMEBASE_3_CLK 0x1e /* 80MHz */ +#define NI_660X_LOGIC_LOW_CLK 0x1f +#define NI_660X_MAX_SRC_PIN 7 +#define NI_660X_MAX_RTSI_CHAN 6 + +/* ni m series gate_select */ +#define NI_M_TIMESTAMP_MUX_GATE_SEL 0x0 +#define NI_M_PFI_GATE_SEL(x) (((x) < 10) ? (1 + (x)) : (0xb + (x))) +#define NI_M_RTSI_GATE_SEL(x) (((x) == 7) ? 0x1b : (0xb + (x))) +#define NI_M_AI_START2_GATE_SEL 0x12 +#define NI_M_PXI_STAR_TRIGGER_GATE_SEL 0x13 +#define NI_M_NEXT_OUT_GATE_SEL 0x14 +#define NI_M_AI_START1_GATE_SEL 0x1c +#define NI_M_NEXT_SRC_GATE_SEL 0x1d +#define NI_M_ANALOG_TRIG_OUT_GATE_SEL 0x1e +#define NI_M_LOGIC_LOW_GATE_SEL 0x1f + +/* ni_660x gate select */ +#define NI_660X_SRC_PIN_I_GATE_SEL 0x0 +#define NI_660X_GATE_PIN_I_GATE_SEL 0x1 +#define NI_660X_PIN_GATE_SEL(x) (0x2 + (x)) +#define NI_660X_NEXT_SRC_GATE_SEL 0xa +#define NI_660X_RTSI_GATE_SEL(x) (0xb + (x)) +#define NI_660X_NEXT_OUT_GATE_SEL 0x14 +#define NI_660X_LOGIC_LOW_GATE_SEL 0x1f +#define NI_660X_MAX_GATE_PIN 7 + +/* ni_660x second gate select */ +#define NI_660X_SRC_PIN_I_GATE2_SEL 0x0 +#define NI_660X_UD_PIN_I_GATE2_SEL 0x1 +#define NI_660X_UD_PIN_GATE2_SEL(x) (0x2 + (x)) +#define NI_660X_NEXT_SRC_GATE2_SEL 0xa +#define NI_660X_RTSI_GATE2_SEL(x) (0xb + (x)) +#define NI_660X_NEXT_OUT_GATE2_SEL 0x14 +#define NI_660X_SELECTED_GATE2_SEL 0x1e +#define NI_660X_LOGIC_LOW_GATE2_SEL 0x1f +#define NI_660X_MAX_UP_DOWN_PIN 7 + +static inline unsigned GI_ALT_SYNC(enum ni_gpct_variant variant) { switch (variant) { case ni_gpct_variant_e_series: + default: return 0; - break; case ni_gpct_variant_m_series: - return Gi_M_Series_Alternate_Sync_Bit; - break; + return GI_M_ALT_SYNC; case ni_gpct_variant_660x: - return Gi_660x_Alternate_Sync_Bit; - break; - default: - BUG(); - break; + return GI_660X_ALT_SYNC; } - return 0; } -static inline enum Gi_Counting_Mode_Reg_Bits Gi_Prescale_X2_Bit(enum - ni_gpct_variant - variant) +static inline unsigned GI_PRESCALE_X2(enum ni_gpct_variant variant) { switch (variant) { case ni_gpct_variant_e_series: + default: return 0; - break; case ni_gpct_variant_m_series: - return Gi_M_Series_Prescale_X2_Bit; - break; + return GI_M_PRESCALE_X2; case ni_gpct_variant_660x: - return Gi_660x_Prescale_X2_Bit; - break; - default: - BUG(); - break; + return GI_660X_PRESCALE_X2; } - return 0; } -static inline enum Gi_Counting_Mode_Reg_Bits Gi_Prescale_X8_Bit(enum - ni_gpct_variant - variant) +static inline unsigned GI_PRESCALE_X8(enum ni_gpct_variant variant) { switch (variant) { case ni_gpct_variant_e_series: + default: return 0; - break; case ni_gpct_variant_m_series: - return Gi_M_Series_Prescale_X8_Bit; - break; + return GI_M_PRESCALE_X8; case ni_gpct_variant_660x: - return Gi_660x_Prescale_X8_Bit; - break; - default: - BUG(); - break; + return GI_660X_PRESCALE_X8; } - return 0; } -static inline enum Gi_Counting_Mode_Reg_Bits Gi_HW_Arm_Select_Mask(enum - ni_gpct_variant - variant) +static inline unsigned GI_HW_ARM_SEL_MASK(enum ni_gpct_variant variant) { switch (variant) { case ni_gpct_variant_e_series: + default: return 0; - break; case ni_gpct_variant_m_series: - return Gi_M_Series_HW_Arm_Select_Mask; - break; + return GI_M_HW_ARM_SEL_MASK; case ni_gpct_variant_660x: - return Gi_660x_HW_Arm_Select_Mask; - break; - default: - BUG(); - break; + return GI_660X_HW_ARM_SEL_MASK; } - return 0; } -/* clock sources for ni_660x boards, get bits with Gi_Source_Select_Bits() */ -enum ni_660x_clock_source { - NI_660x_Timebase_1_Clock = 0x0, /* 20MHz */ - NI_660x_Source_Pin_i_Clock = 0x1, - NI_660x_Next_Gate_Clock = 0xa, - NI_660x_Timebase_2_Clock = 0x12, /* 100KHz */ - NI_660x_Next_TC_Clock = 0x13, - NI_660x_Timebase_3_Clock = 0x1e, /* 80MHz */ - NI_660x_Logic_Low_Clock = 0x1f, -}; -static const unsigned ni_660x_max_rtsi_channel = 6; -static inline unsigned NI_660x_RTSI_Clock(unsigned n) +static int ni_tio_has_gate2_registers(const struct ni_gpct_device *counter_dev) { - BUG_ON(n > ni_660x_max_rtsi_channel); - return 0xb + n; -} - -static const unsigned ni_660x_max_source_pin = 7; -static inline unsigned NI_660x_Source_Pin_Clock(unsigned n) -{ - BUG_ON(n > ni_660x_max_source_pin); - return 0x2 + n; -} - -/* clock sources for ni e and m series boards, get bits with Gi_Source_Select_Bits() */ -enum ni_m_series_clock_source { - NI_M_Series_Timebase_1_Clock = 0x0, /* 20MHz */ - NI_M_Series_Timebase_2_Clock = 0x12, /* 100KHz */ - NI_M_Series_Next_TC_Clock = 0x13, - NI_M_Series_Next_Gate_Clock = 0x14, /* when Gi_Src_SubSelect = 0 */ - NI_M_Series_PXI_Star_Trigger_Clock = 0x14, /* when Gi_Src_SubSelect = 1 */ - NI_M_Series_PXI10_Clock = 0x1d, - NI_M_Series_Timebase_3_Clock = 0x1e, /* 80MHz, when Gi_Src_SubSelect = 0 */ - NI_M_Series_Analog_Trigger_Out_Clock = 0x1e, /* when Gi_Src_SubSelect = 1 */ - NI_M_Series_Logic_Low_Clock = 0x1f, -}; -static const unsigned ni_m_series_max_pfi_channel = 15; -static inline unsigned NI_M_Series_PFI_Clock(unsigned n) -{ - BUG_ON(n > ni_m_series_max_pfi_channel); - if (n < 10) - return 1 + n; - else - return 0xb + n; -} - -static const unsigned ni_m_series_max_rtsi_channel = 7; -static inline unsigned NI_M_Series_RTSI_Clock(unsigned n) -{ - BUG_ON(n > ni_m_series_max_rtsi_channel); - if (n == 7) - return 0x1b; - else - return 0xb + n; -} - -enum ni_660x_gate_select { - NI_660x_Source_Pin_i_Gate_Select = 0x0, - NI_660x_Gate_Pin_i_Gate_Select = 0x1, - NI_660x_Next_SRC_Gate_Select = 0xa, - NI_660x_Next_Out_Gate_Select = 0x14, - NI_660x_Logic_Low_Gate_Select = 0x1f, -}; -static const unsigned ni_660x_max_gate_pin = 7; -static inline unsigned NI_660x_Gate_Pin_Gate_Select(unsigned n) -{ - BUG_ON(n > ni_660x_max_gate_pin); - return 0x2 + n; -} - -static inline unsigned NI_660x_RTSI_Gate_Select(unsigned n) -{ - BUG_ON(n > ni_660x_max_rtsi_channel); - return 0xb + n; -} - -enum ni_m_series_gate_select { - NI_M_Series_Timestamp_Mux_Gate_Select = 0x0, - NI_M_Series_AI_START2_Gate_Select = 0x12, - NI_M_Series_PXI_Star_Trigger_Gate_Select = 0x13, - NI_M_Series_Next_Out_Gate_Select = 0x14, - NI_M_Series_AI_START1_Gate_Select = 0x1c, - NI_M_Series_Next_SRC_Gate_Select = 0x1d, - NI_M_Series_Analog_Trigger_Out_Gate_Select = 0x1e, - NI_M_Series_Logic_Low_Gate_Select = 0x1f, -}; -static inline unsigned NI_M_Series_RTSI_Gate_Select(unsigned n) -{ - BUG_ON(n > ni_m_series_max_rtsi_channel); - if (n == 7) - return 0x1b; - return 0xb + n; -} - -static inline unsigned NI_M_Series_PFI_Gate_Select(unsigned n) -{ - BUG_ON(n > ni_m_series_max_pfi_channel); - if (n < 10) - return 1 + n; - return 0xb + n; -} - -static inline unsigned Gi_Source_Select_Bits(unsigned source) -{ - return (source << Gi_Source_Select_Shift) & Gi_Source_Select_Mask; -} - -static inline unsigned Gi_Gate_Select_Bits(unsigned gate_select) -{ - return (gate_select << Gi_Gate_Select_Shift) & Gi_Gate_Select_Mask; + switch (counter_dev->variant) { + case ni_gpct_variant_e_series: + default: + return 0; + case ni_gpct_variant_m_series: + case ni_gpct_variant_660x: + return 1; + } } -enum ni_660x_second_gate_select { - NI_660x_Source_Pin_i_Second_Gate_Select = 0x0, - NI_660x_Up_Down_Pin_i_Second_Gate_Select = 0x1, - NI_660x_Next_SRC_Second_Gate_Select = 0xa, - NI_660x_Next_Out_Second_Gate_Select = 0x14, - NI_660x_Selected_Gate_Second_Gate_Select = 0x1e, - NI_660x_Logic_Low_Second_Gate_Select = 0x1f, -}; -static const unsigned ni_660x_max_up_down_pin = 7; -static inline unsigned NI_660x_Up_Down_Pin_Second_Gate_Select(unsigned n) +static void ni_tio_reset_count_and_disarm(struct ni_gpct *counter) { - BUG_ON(n > ni_660x_max_up_down_pin); - return 0x2 + n; -} + unsigned cidx = counter->counter_index; -static inline unsigned NI_660x_RTSI_Second_Gate_Select(unsigned n) -{ - BUG_ON(n > ni_660x_max_rtsi_channel); - return 0xb + n; + write_register(counter, GI_RESET(cidx), NITIO_RESET_REG(cidx)); } -static const unsigned int counter_status_mask = - COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING; - -struct ni_gpct_device *ni_gpct_device_construct(struct comedi_device *dev, - void (*write_register) (struct - ni_gpct - * - counter, - unsigned - bits, - enum - ni_gpct_register - reg), - unsigned (*read_register) - (struct ni_gpct *counter, - enum ni_gpct_register reg), - enum ni_gpct_variant variant, - unsigned num_counters) +static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter, + unsigned generic_clock_source) { - unsigned i; + uint64_t clock_period_ps; - struct ni_gpct_device *counter_dev = - kzalloc(sizeof(struct ni_gpct_device), GFP_KERNEL); - if (counter_dev == NULL) - return NULL; - counter_dev->dev = dev; - counter_dev->write_register = write_register; - counter_dev->read_register = read_register; - counter_dev->variant = variant; - spin_lock_init(&counter_dev->regs_lock); - BUG_ON(num_counters == 0); - counter_dev->counters = - kzalloc(sizeof(struct ni_gpct) * num_counters, GFP_KERNEL); - if (counter_dev->counters == NULL) { - kfree(counter_dev); - return NULL; - } - for (i = 0; i < num_counters; ++i) { - counter_dev->counters[i].counter_dev = counter_dev; - spin_lock_init(&counter_dev->counters[i].lock); + switch (generic_clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK) { + case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS: + clock_period_ps = 50000; + break; + case NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS: + clock_period_ps = 10000000; + break; + case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS: + clock_period_ps = 12500; + break; + case NI_GPCT_PXI10_CLOCK_SRC_BITS: + clock_period_ps = 100000; + break; + default: + /* + * clock period is specified by user with prescaling + * already taken into account. + */ + return counter->clock_period_ps; } - counter_dev->num_counters = num_counters; - return counter_dev; -} -EXPORT_SYMBOL_GPL(ni_gpct_device_construct); - -void ni_gpct_device_destroy(struct ni_gpct_device *counter_dev) -{ - if (counter_dev->counters == NULL) - return; - kfree(counter_dev->counters); - kfree(counter_dev); -} -EXPORT_SYMBOL_GPL(ni_gpct_device_destroy); -static int ni_tio_second_gate_registers_present(const struct ni_gpct_device - *counter_dev) -{ - switch (counter_dev->variant) { - case ni_gpct_variant_e_series: - return 0; + switch (generic_clock_source & NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK) { + case NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS: break; - case ni_gpct_variant_m_series: - case ni_gpct_variant_660x: - return 1; + case NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS: + clock_period_ps *= 2; + break; + case NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS: + clock_period_ps *= 8; break; default: BUG(); break; } - return 0; + return clock_period_ps; } -static void ni_tio_reset_count_and_disarm(struct ni_gpct *counter) +static unsigned ni_tio_clock_src_modifiers(const struct ni_gpct *counter) { + struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned cidx = counter->counter_index; + const unsigned counting_mode_bits = + ni_tio_get_soft_copy(counter, NITIO_CNT_MODE_REG(cidx)); + unsigned bits = 0; - write_register(counter, Gi_Reset_Bit(cidx), NITIO_RESET_REG(cidx)); + if (ni_tio_get_soft_copy(counter, NITIO_INPUT_SEL_REG(cidx)) & + GI_SRC_POL_INVERT) + bits |= NI_GPCT_INVERT_CLOCK_SRC_BIT; + if (counting_mode_bits & GI_PRESCALE_X2(counter_dev->variant)) + bits |= NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS; + if (counting_mode_bits & GI_PRESCALE_X8(counter_dev->variant)) + bits |= NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS; + return bits; } -void ni_tio_init_counter(struct ni_gpct *counter) +static unsigned ni_m_series_clock_src_select(const struct ni_gpct *counter) { struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned cidx = counter->counter_index; + const unsigned second_gate_reg = NITIO_GATE2_REG(cidx); + unsigned clock_source = 0; + unsigned src; + unsigned i; - ni_tio_reset_count_and_disarm(counter); - - /* initialize counter registers */ - counter_dev->regs[NITIO_AUTO_INC_REG(cidx)] = 0x0; - write_register(counter, counter_dev->regs[NITIO_AUTO_INC_REG(cidx)], - NITIO_AUTO_INC_REG(cidx)); - - ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), - ~0, Gi_Synchronize_Gate_Bit); - - ni_tio_set_bits(counter, NITIO_MODE_REG(cidx), ~0, 0); - - counter_dev->regs[NITIO_LOADA_REG(cidx)] = 0x0; - write_register(counter, counter_dev->regs[NITIO_LOADA_REG(cidx)], - NITIO_LOADA_REG(cidx)); + src = GI_BITS_TO_SRC(ni_tio_get_soft_copy(counter, + NITIO_INPUT_SEL_REG(cidx))); - counter_dev->regs[NITIO_LOADB_REG(cidx)] = 0x0; - write_register(counter, counter_dev->regs[NITIO_LOADB_REG(cidx)], - NITIO_LOADB_REG(cidx)); + switch (src) { + case NI_M_TIMEBASE_1_CLK: + clock_source = NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS; + break; + case NI_M_TIMEBASE_2_CLK: + clock_source = NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS; + break; + case NI_M_TIMEBASE_3_CLK: + if (counter_dev->regs[second_gate_reg] & GI_SRC_SUBSEL) + clock_source = + NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS; + else + clock_source = NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS; + break; + case NI_M_LOGIC_LOW_CLK: + clock_source = NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS; + break; + case NI_M_NEXT_GATE_CLK: + if (counter_dev->regs[second_gate_reg] & GI_SRC_SUBSEL) + clock_source = NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS; + else + clock_source = NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS; + break; + case NI_M_PXI10_CLK: + clock_source = NI_GPCT_PXI10_CLOCK_SRC_BITS; + break; + case NI_M_NEXT_TC_CLK: + clock_source = NI_GPCT_NEXT_TC_CLOCK_SRC_BITS; + break; + default: + for (i = 0; i <= NI_M_MAX_RTSI_CHAN; ++i) { + if (src == NI_M_RTSI_CLK(i)) { + clock_source = NI_GPCT_RTSI_CLOCK_SRC_BITS(i); + break; + } + } + if (i <= NI_M_MAX_RTSI_CHAN) + break; + for (i = 0; i <= NI_M_MAX_PFI_CHAN; ++i) { + if (src == NI_M_PFI_CLK(i)) { + clock_source = NI_GPCT_PFI_CLOCK_SRC_BITS(i); + break; + } + } + if (i <= NI_M_MAX_PFI_CHAN) + break; + BUG(); + break; + } + clock_source |= ni_tio_clock_src_modifiers(counter); + return clock_source; +} - ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), ~0, 0); +static unsigned ni_660x_clock_src_select(const struct ni_gpct *counter) +{ + unsigned clock_source = 0; + unsigned cidx = counter->counter_index; + unsigned src; + unsigned i; - if (ni_tio_counting_mode_registers_present(counter_dev)) - ni_tio_set_bits(counter, NITIO_CNT_MODE_REG(cidx), ~0, 0); + src = GI_BITS_TO_SRC(ni_tio_get_soft_copy(counter, + NITIO_INPUT_SEL_REG(cidx))); - if (ni_tio_second_gate_registers_present(counter_dev)) { - counter_dev->regs[NITIO_GATE2_REG(cidx)] = 0x0; - write_register(counter, - counter_dev->regs[NITIO_GATE2_REG(cidx)], - NITIO_GATE2_REG(cidx)); + switch (src) { + case NI_660X_TIMEBASE_1_CLK: + clock_source = NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS; + break; + case NI_660X_TIMEBASE_2_CLK: + clock_source = NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS; + break; + case NI_660X_TIMEBASE_3_CLK: + clock_source = NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS; + break; + case NI_660X_LOGIC_LOW_CLK: + clock_source = NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS; + break; + case NI_660X_SRC_PIN_I_CLK: + clock_source = NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS; + break; + case NI_660X_NEXT_GATE_CLK: + clock_source = NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS; + break; + case NI_660X_NEXT_TC_CLK: + clock_source = NI_GPCT_NEXT_TC_CLOCK_SRC_BITS; + break; + default: + for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) { + if (src == NI_660X_RTSI_CLK(i)) { + clock_source = NI_GPCT_RTSI_CLOCK_SRC_BITS(i); + break; + } + } + if (i <= NI_660X_MAX_RTSI_CHAN) + break; + for (i = 0; i <= NI_660X_MAX_SRC_PIN; ++i) { + if (src == NI_660X_SRC_PIN_CLK(i)) { + clock_source = + NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(i); + break; + } + } + if (i <= NI_660X_MAX_SRC_PIN) + break; + BUG(); + break; } - - ni_tio_set_bits(counter, NITIO_DMA_CFG_REG(cidx), ~0, 0x0); - - ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx), ~0, 0x0); + clock_source |= ni_tio_clock_src_modifiers(counter); + return clock_source; } -EXPORT_SYMBOL_GPL(ni_tio_init_counter); -static unsigned int ni_tio_counter_status(struct ni_gpct *counter) +static unsigned ni_tio_generic_clock_src_select(const struct ni_gpct *counter) { - unsigned cidx = counter->counter_index; - const unsigned bits = read_register(counter, - NITIO_SHARED_STATUS_REG(cidx)); - unsigned int status = 0; - - if (bits & Gi_Armed_Bit(cidx)) { - status |= COMEDI_COUNTER_ARMED; - if (bits & Gi_Counting_Bit(cidx)) - status |= COMEDI_COUNTER_COUNTING; + switch (counter->counter_dev->variant) { + case ni_gpct_variant_e_series: + case ni_gpct_variant_m_series: + default: + return ni_m_series_clock_src_select(counter); + case ni_gpct_variant_660x: + return ni_660x_clock_src_select(counter); } - return status; } static void ni_tio_set_sync_mode(struct ni_gpct *counter, int force_alt_sync) @@ -414,34 +387,40 @@ static void ni_tio_set_sync_mode(struct ni_gpct *counter, int force_alt_sync) unsigned cidx = counter->counter_index; const unsigned counting_mode_reg = NITIO_CNT_MODE_REG(cidx); static const uint64_t min_normal_sync_period_ps = 25000; - const uint64_t clock_period_ps = ni_tio_clock_period_ps(counter, - ni_tio_generic_clock_src_select - (counter)); + unsigned mode; + uint64_t clock_period_ps; if (ni_tio_counting_mode_registers_present(counter_dev) == 0) return; - switch (ni_tio_get_soft_copy(counter, counting_mode_reg) & Gi_Counting_Mode_Mask) { - case Gi_Counting_Mode_QuadratureX1_Bits: - case Gi_Counting_Mode_QuadratureX2_Bits: - case Gi_Counting_Mode_QuadratureX4_Bits: - case Gi_Counting_Mode_Sync_Source_Bits: + mode = ni_tio_get_soft_copy(counter, counting_mode_reg); + switch (mode & GI_CNT_MODE_MASK) { + case GI_CNT_MODE_QUADX1: + case GI_CNT_MODE_QUADX2: + case GI_CNT_MODE_QUADX4: + case GI_CNT_MODE_SYNC_SRC: force_alt_sync = 1; break; default: break; } - /* It's not clear what we should do if clock_period is unknown, so we are not - using the alt sync bit in that case, but allow the caller to decide by using the - force_alt_sync parameter. */ + + clock_period_ps = ni_tio_clock_period_ps(counter, + ni_tio_generic_clock_src_select(counter)); + + /* + * It's not clear what we should do if clock_period is unknown, so we + * are not using the alt sync bit in that case, but allow the caller + * to decide by using the force_alt_sync parameter. + */ if (force_alt_sync || (clock_period_ps && clock_period_ps < min_normal_sync_period_ps)) { ni_tio_set_bits(counter, counting_mode_reg, - Gi_Alternate_Sync_Bit(counter_dev->variant), - Gi_Alternate_Sync_Bit(counter_dev->variant)); + GI_ALT_SYNC(counter_dev->variant), + GI_ALT_SYNC(counter_dev->variant)); } else { ni_tio_set_bits(counter, counting_mode_reg, - Gi_Alternate_Sync_Bit(counter_dev->variant), + GI_ALT_SYNC(counter_dev->variant), 0x0); } } @@ -460,18 +439,18 @@ static int ni_tio_set_counter_mode(struct ni_gpct *counter, unsigned mode) NI_GPCT_HARDWARE_DISARM_MASK | NI_GPCT_LOADING_ON_TC_BIT | NI_GPCT_LOADING_ON_GATE_BIT | NI_GPCT_LOAD_B_SELECT_BIT; - mode_reg_mask = mode_reg_direct_mask | Gi_Reload_Source_Switching_Bit; + mode_reg_mask = mode_reg_direct_mask | GI_RELOAD_SRC_SWITCHING; mode_reg_values = mode & mode_reg_direct_mask; switch (mode & NI_GPCT_RELOAD_SOURCE_MASK) { case NI_GPCT_RELOAD_SOURCE_FIXED_BITS: break; case NI_GPCT_RELOAD_SOURCE_SWITCHING_BITS: - mode_reg_values |= Gi_Reload_Source_Switching_Bit; + mode_reg_values |= GI_RELOAD_SRC_SWITCHING; break; case NI_GPCT_RELOAD_SOURCE_GATE_SELECT_BITS: - input_select_bits |= Gi_Gate_Select_Load_Source_Bit; - mode_reg_mask |= Gi_Gating_Mode_Mask; - mode_reg_values |= Gi_Level_Gating_Bits; + input_select_bits |= GI_GATE_SEL_LOAD_SRC; + mode_reg_mask |= GI_GATING_MODE_MASK; + mode_reg_values |= GI_LEVEL_GATING; break; default: break; @@ -480,33 +459,28 @@ static int ni_tio_set_counter_mode(struct ni_gpct *counter, unsigned mode) mode_reg_mask, mode_reg_values); if (ni_tio_counting_mode_registers_present(counter_dev)) { - unsigned counting_mode_bits = 0; - counting_mode_bits |= - (mode >> NI_GPCT_COUNTING_MODE_SHIFT) & - Gi_Counting_Mode_Mask; - counting_mode_bits |= - ((mode >> NI_GPCT_INDEX_PHASE_BITSHIFT) << - Gi_Index_Phase_Bitshift) & Gi_Index_Phase_Mask; + unsigned bits = 0; + + bits |= GI_CNT_MODE(mode >> NI_GPCT_COUNTING_MODE_SHIFT); + bits |= GI_INDEX_PHASE((mode >> NI_GPCT_INDEX_PHASE_BITSHIFT)); if (mode & NI_GPCT_INDEX_ENABLE_BIT) - counting_mode_bits |= Gi_Index_Mode_Bit; + bits |= GI_INDEX_MODE; ni_tio_set_bits(counter, NITIO_CNT_MODE_REG(cidx), - Gi_Counting_Mode_Mask | Gi_Index_Phase_Mask | - Gi_Index_Mode_Bit, counting_mode_bits); + GI_CNT_MODE_MASK | GI_INDEX_PHASE_MASK | + GI_INDEX_MODE, bits); ni_tio_set_sync_mode(counter, 0); } - ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), - Gi_Up_Down_Mask, - (mode >> NI_GPCT_COUNTING_DIRECTION_SHIFT) << - Gi_Up_Down_Shift); + ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), GI_CNT_DIR_MASK, + GI_CNT_DIR(mode >> NI_GPCT_COUNTING_DIRECTION_SHIFT)); if (mode & NI_GPCT_OR_GATE_BIT) - input_select_bits |= Gi_Or_Gate_Bit; + input_select_bits |= GI_OR_GATE; if (mode & NI_GPCT_INVERT_OUTPUT_BIT) - input_select_bits |= Gi_Output_Polarity_Bit; + input_select_bits |= GI_OUTPUT_POL_INVERT; ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), - Gi_Gate_Select_Load_Source_Bit | Gi_Or_Gate_Bit | - Gi_Output_Polarity_Bit, input_select_bits); + GI_GATE_SEL_LOAD_SRC | GI_OR_GATE | + GI_OUTPUT_POL_INVERT, input_select_bits); return 0; } @@ -520,16 +494,19 @@ int ni_tio_arm(struct ni_gpct *counter, int arm, unsigned start_trigger) if (arm) { switch (start_trigger) { case NI_GPCT_ARM_IMMEDIATE: - command_transient_bits |= Gi_Arm_Bit; + command_transient_bits |= GI_ARM; break; case NI_GPCT_ARM_PAIRED_IMMEDIATE: - command_transient_bits |= Gi_Arm_Bit | Gi_Arm_Copy_Bit; + command_transient_bits |= GI_ARM | GI_ARM_COPY; break; default: break; } if (ni_tio_counting_mode_registers_present(counter_dev)) { - unsigned counting_mode_bits = 0; + unsigned bits = 0; + unsigned sel_mask; + + sel_mask = GI_HW_ARM_SEL_MASK(counter_dev->variant); switch (start_trigger) { case NI_GPCT_ARM_IMMEDIATE: @@ -537,29 +514,24 @@ int ni_tio_arm(struct ni_gpct *counter, int arm, unsigned start_trigger) break; default: if (start_trigger & NI_GPCT_ARM_UNKNOWN) { - /* pass-through the least significant bits so we can figure out what select later */ - unsigned hw_arm_select_bits = - (start_trigger << - Gi_HW_Arm_Select_Shift) & - Gi_HW_Arm_Select_Mask - (counter_dev->variant); - - counting_mode_bits |= - Gi_HW_Arm_Enable_Bit | - hw_arm_select_bits; + /* + * pass-through the least significant + * bits so we can figure out what + * select later + */ + bits |= GI_HW_ARM_ENA | + (GI_HW_ARM_SEL(start_trigger) & + sel_mask); } else { return -EINVAL; } break; } ni_tio_set_bits(counter, NITIO_CNT_MODE_REG(cidx), - Gi_HW_Arm_Select_Mask - (counter_dev->variant) | - Gi_HW_Arm_Enable_Bit, - counting_mode_bits); + GI_HW_ARM_ENA | sel_mask, bits); } } else { - command_transient_bits |= Gi_Disarm_Bit; + command_transient_bits |= GI_DISARM; } ni_tio_set_bits_transient(counter, NITIO_CMD_REG(cidx), 0, 0, command_transient_bits); @@ -567,118 +539,116 @@ int ni_tio_arm(struct ni_gpct *counter, int arm, unsigned start_trigger) } EXPORT_SYMBOL_GPL(ni_tio_arm); -static unsigned ni_660x_source_select_bits(unsigned int clock_source) +static unsigned ni_660x_clk_src(unsigned int clock_source) { + unsigned clk_src = clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK; unsigned ni_660x_clock; unsigned i; - const unsigned clock_select_bits = - clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK; - switch (clock_select_bits) { + switch (clk_src) { case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS: - ni_660x_clock = NI_660x_Timebase_1_Clock; + ni_660x_clock = NI_660X_TIMEBASE_1_CLK; break; case NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS: - ni_660x_clock = NI_660x_Timebase_2_Clock; + ni_660x_clock = NI_660X_TIMEBASE_2_CLK; break; case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS: - ni_660x_clock = NI_660x_Timebase_3_Clock; + ni_660x_clock = NI_660X_TIMEBASE_3_CLK; break; case NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS: - ni_660x_clock = NI_660x_Logic_Low_Clock; + ni_660x_clock = NI_660X_LOGIC_LOW_CLK; break; case NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS: - ni_660x_clock = NI_660x_Source_Pin_i_Clock; + ni_660x_clock = NI_660X_SRC_PIN_I_CLK; break; case NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS: - ni_660x_clock = NI_660x_Next_Gate_Clock; + ni_660x_clock = NI_660X_NEXT_GATE_CLK; break; case NI_GPCT_NEXT_TC_CLOCK_SRC_BITS: - ni_660x_clock = NI_660x_Next_TC_Clock; + ni_660x_clock = NI_660X_NEXT_TC_CLK; break; default: - for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { - if (clock_select_bits == NI_GPCT_RTSI_CLOCK_SRC_BITS(i)) { - ni_660x_clock = NI_660x_RTSI_Clock(i); + for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) { + if (clk_src == NI_GPCT_RTSI_CLOCK_SRC_BITS(i)) { + ni_660x_clock = NI_660X_RTSI_CLK(i); break; } } - if (i <= ni_660x_max_rtsi_channel) + if (i <= NI_660X_MAX_RTSI_CHAN) break; - for (i = 0; i <= ni_660x_max_source_pin; ++i) { - if (clock_select_bits == - NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(i)) { - ni_660x_clock = NI_660x_Source_Pin_Clock(i); + for (i = 0; i <= NI_660X_MAX_SRC_PIN; ++i) { + if (clk_src == NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(i)) { + ni_660x_clock = NI_660X_SRC_PIN_CLK(i); break; } } - if (i <= ni_660x_max_source_pin) + if (i <= NI_660X_MAX_SRC_PIN) break; ni_660x_clock = 0; BUG(); break; } - return Gi_Source_Select_Bits(ni_660x_clock); + return GI_SRC_SEL(ni_660x_clock); } -static unsigned ni_m_series_source_select_bits(unsigned int clock_source) +static unsigned ni_m_clk_src(unsigned int clock_source) { + unsigned clk_src = clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK; unsigned ni_m_series_clock; unsigned i; - const unsigned clock_select_bits = - clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK; - switch (clock_select_bits) { + + switch (clk_src) { case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS: - ni_m_series_clock = NI_M_Series_Timebase_1_Clock; + ni_m_series_clock = NI_M_TIMEBASE_1_CLK; break; case NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS: - ni_m_series_clock = NI_M_Series_Timebase_2_Clock; + ni_m_series_clock = NI_M_TIMEBASE_2_CLK; break; case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS: - ni_m_series_clock = NI_M_Series_Timebase_3_Clock; + ni_m_series_clock = NI_M_TIMEBASE_3_CLK; break; case NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS: - ni_m_series_clock = NI_M_Series_Logic_Low_Clock; + ni_m_series_clock = NI_M_LOGIC_LOW_CLK; break; case NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS: - ni_m_series_clock = NI_M_Series_Next_Gate_Clock; + ni_m_series_clock = NI_M_NEXT_GATE_CLK; break; case NI_GPCT_NEXT_TC_CLOCK_SRC_BITS: - ni_m_series_clock = NI_M_Series_Next_TC_Clock; + ni_m_series_clock = NI_M_NEXT_TC_CLK; break; case NI_GPCT_PXI10_CLOCK_SRC_BITS: - ni_m_series_clock = NI_M_Series_PXI10_Clock; + ni_m_series_clock = NI_M_PXI10_CLK; break; case NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS: - ni_m_series_clock = NI_M_Series_PXI_Star_Trigger_Clock; + ni_m_series_clock = NI_M_PXI_STAR_TRIGGER_CLK; break; case NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS: - ni_m_series_clock = NI_M_Series_Analog_Trigger_Out_Clock; + ni_m_series_clock = NI_M_ANALOG_TRIGGER_OUT_CLK; break; default: - for (i = 0; i <= ni_m_series_max_rtsi_channel; ++i) { - if (clock_select_bits == NI_GPCT_RTSI_CLOCK_SRC_BITS(i)) { - ni_m_series_clock = NI_M_Series_RTSI_Clock(i); + for (i = 0; i <= NI_M_MAX_RTSI_CHAN; ++i) { + if (clk_src == NI_GPCT_RTSI_CLOCK_SRC_BITS(i)) { + ni_m_series_clock = NI_M_RTSI_CLK(i); break; } } - if (i <= ni_m_series_max_rtsi_channel) + if (i <= NI_M_MAX_RTSI_CHAN) break; - for (i = 0; i <= ni_m_series_max_pfi_channel; ++i) { - if (clock_select_bits == NI_GPCT_PFI_CLOCK_SRC_BITS(i)) { - ni_m_series_clock = NI_M_Series_PFI_Clock(i); + for (i = 0; i <= NI_M_MAX_PFI_CHAN; ++i) { + if (clk_src == NI_GPCT_PFI_CLOCK_SRC_BITS(i)) { + ni_m_series_clock = NI_M_PFI_CLK(i); break; } } - if (i <= ni_m_series_max_pfi_channel) + if (i <= NI_M_MAX_PFI_CHAN) break; - printk(KERN_ERR "invalid clock source 0x%lx\n", + pr_err("invalid clock source 0x%lx\n", (unsigned long)clock_source); BUG(); ni_m_series_clock = 0; break; } - return Gi_Source_Select_Bits(ni_m_series_clock); + return GI_SRC_SEL(ni_m_series_clock); }; static void ni_tio_set_source_subselect(struct ni_gpct *counter, @@ -694,17 +664,16 @@ static void ni_tio_set_source_subselect(struct ni_gpct *counter, /* Gi_Source_Subselect is zero */ case NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS: case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS: - counter_dev->regs[second_gate_reg] &= ~Gi_Source_Subselect_Bit; + counter_dev->regs[second_gate_reg] &= ~GI_SRC_SUBSEL; break; /* Gi_Source_Subselect is one */ case NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS: case NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS: - counter_dev->regs[second_gate_reg] |= Gi_Source_Subselect_Bit; + counter_dev->regs[second_gate_reg] |= GI_SRC_SUBSEL; break; /* Gi_Source_Subselect doesn't matter */ default: return; - break; } write_register(counter, counter_dev->regs[second_gate_reg], second_gate_reg); @@ -716,344 +685,109 @@ static int ni_tio_set_clock_src(struct ni_gpct *counter, { struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned cidx = counter->counter_index; - unsigned input_select_bits = 0; - static const uint64_t pico_per_nano = 1000; + unsigned bits = 0; -/*FIXME: validate clock source */ + /* FIXME: validate clock source */ switch (counter_dev->variant) { case ni_gpct_variant_660x: - input_select_bits |= ni_660x_source_select_bits(clock_source); + bits |= ni_660x_clk_src(clock_source); break; case ni_gpct_variant_e_series: case ni_gpct_variant_m_series: - input_select_bits |= - ni_m_series_source_select_bits(clock_source); - break; default: - BUG(); + bits |= ni_m_clk_src(clock_source); break; } if (clock_source & NI_GPCT_INVERT_CLOCK_SRC_BIT) - input_select_bits |= Gi_Source_Polarity_Bit; + bits |= GI_SRC_POL_INVERT; ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), - Gi_Source_Select_Mask | Gi_Source_Polarity_Bit, - input_select_bits); + GI_SRC_SEL_MASK | GI_SRC_POL_INVERT, bits); ni_tio_set_source_subselect(counter, clock_source); - if (ni_tio_counting_mode_registers_present(counter_dev)) { - const unsigned prescaling_mode = - clock_source & NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK; - unsigned counting_mode_bits = 0; - switch (prescaling_mode) { + if (ni_tio_counting_mode_registers_present(counter_dev)) { + bits = 0; + switch (clock_source & NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK) { case NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS: break; case NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS: - counting_mode_bits |= - Gi_Prescale_X2_Bit(counter_dev->variant); + bits |= GI_PRESCALE_X2(counter_dev->variant); break; case NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS: - counting_mode_bits |= - Gi_Prescale_X8_Bit(counter_dev->variant); + bits |= GI_PRESCALE_X8(counter_dev->variant); break; default: return -EINVAL; - break; } ni_tio_set_bits(counter, NITIO_CNT_MODE_REG(cidx), - Gi_Prescale_X2_Bit(counter_dev->variant) | - Gi_Prescale_X8_Bit(counter_dev->variant), - counting_mode_bits); + GI_PRESCALE_X2(counter_dev->variant) | + GI_PRESCALE_X8(counter_dev->variant), bits); } - counter->clock_period_ps = pico_per_nano * period_ns; + counter->clock_period_ps = period_ns * 1000; ni_tio_set_sync_mode(counter, 0); return 0; } -static unsigned ni_tio_clock_src_modifiers(const struct ni_gpct *counter) -{ - struct ni_gpct_device *counter_dev = counter->counter_dev; - unsigned cidx = counter->counter_index; - const unsigned counting_mode_bits = - ni_tio_get_soft_copy(counter, NITIO_CNT_MODE_REG(cidx)); - unsigned bits = 0; - - if (ni_tio_get_soft_copy(counter, NITIO_INPUT_SEL_REG(cidx)) & - Gi_Source_Polarity_Bit) - bits |= NI_GPCT_INVERT_CLOCK_SRC_BIT; - if (counting_mode_bits & Gi_Prescale_X2_Bit(counter_dev->variant)) - bits |= NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS; - if (counting_mode_bits & Gi_Prescale_X8_Bit(counter_dev->variant)) - bits |= NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS; - return bits; -} - -static unsigned ni_m_series_clock_src_select(const struct ni_gpct *counter) -{ - struct ni_gpct_device *counter_dev = counter->counter_dev; - unsigned cidx = counter->counter_index; - const unsigned second_gate_reg = NITIO_GATE2_REG(cidx); - unsigned clock_source = 0; - unsigned i; - const unsigned input_select = - (ni_tio_get_soft_copy(counter, NITIO_INPUT_SEL_REG(cidx)) & - Gi_Source_Select_Mask) >> Gi_Source_Select_Shift; - - switch (input_select) { - case NI_M_Series_Timebase_1_Clock: - clock_source = NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS; - break; - case NI_M_Series_Timebase_2_Clock: - clock_source = NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS; - break; - case NI_M_Series_Timebase_3_Clock: - if (counter_dev->regs[second_gate_reg] & - Gi_Source_Subselect_Bit) - clock_source = - NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS; - else - clock_source = NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS; - break; - case NI_M_Series_Logic_Low_Clock: - clock_source = NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS; - break; - case NI_M_Series_Next_Gate_Clock: - if (counter_dev->regs[second_gate_reg] & - Gi_Source_Subselect_Bit) - clock_source = NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS; - else - clock_source = NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS; - break; - case NI_M_Series_PXI10_Clock: - clock_source = NI_GPCT_PXI10_CLOCK_SRC_BITS; - break; - case NI_M_Series_Next_TC_Clock: - clock_source = NI_GPCT_NEXT_TC_CLOCK_SRC_BITS; - break; - default: - for (i = 0; i <= ni_m_series_max_rtsi_channel; ++i) { - if (input_select == NI_M_Series_RTSI_Clock(i)) { - clock_source = NI_GPCT_RTSI_CLOCK_SRC_BITS(i); - break; - } - } - if (i <= ni_m_series_max_rtsi_channel) - break; - for (i = 0; i <= ni_m_series_max_pfi_channel; ++i) { - if (input_select == NI_M_Series_PFI_Clock(i)) { - clock_source = NI_GPCT_PFI_CLOCK_SRC_BITS(i); - break; - } - } - if (i <= ni_m_series_max_pfi_channel) - break; - BUG(); - break; - } - clock_source |= ni_tio_clock_src_modifiers(counter); - return clock_source; -} - -static unsigned ni_660x_clock_src_select(const struct ni_gpct *counter) -{ - unsigned clock_source = 0; - unsigned cidx = counter->counter_index; - const unsigned input_select = - (ni_tio_get_soft_copy(counter, NITIO_INPUT_SEL_REG(cidx)) & - Gi_Source_Select_Mask) >> Gi_Source_Select_Shift; - unsigned i; - - switch (input_select) { - case NI_660x_Timebase_1_Clock: - clock_source = NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS; - break; - case NI_660x_Timebase_2_Clock: - clock_source = NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS; - break; - case NI_660x_Timebase_3_Clock: - clock_source = NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS; - break; - case NI_660x_Logic_Low_Clock: - clock_source = NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS; - break; - case NI_660x_Source_Pin_i_Clock: - clock_source = NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS; - break; - case NI_660x_Next_Gate_Clock: - clock_source = NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS; - break; - case NI_660x_Next_TC_Clock: - clock_source = NI_GPCT_NEXT_TC_CLOCK_SRC_BITS; - break; - default: - for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { - if (input_select == NI_660x_RTSI_Clock(i)) { - clock_source = NI_GPCT_RTSI_CLOCK_SRC_BITS(i); - break; - } - } - if (i <= ni_660x_max_rtsi_channel) - break; - for (i = 0; i <= ni_660x_max_source_pin; ++i) { - if (input_select == NI_660x_Source_Pin_Clock(i)) { - clock_source = - NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(i); - break; - } - } - if (i <= ni_660x_max_source_pin) - break; - BUG(); - break; - } - clock_source |= ni_tio_clock_src_modifiers(counter); - return clock_source; -} - -static unsigned ni_tio_generic_clock_src_select(const struct ni_gpct *counter) -{ - switch (counter->counter_dev->variant) { - case ni_gpct_variant_e_series: - case ni_gpct_variant_m_series: - return ni_m_series_clock_src_select(counter); - break; - case ni_gpct_variant_660x: - return ni_660x_clock_src_select(counter); - break; - default: - BUG(); - break; - } - return 0; -} - -static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter, - unsigned generic_clock_source) -{ - uint64_t clock_period_ps; - - switch (generic_clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK) { - case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS: - clock_period_ps = 50000; - break; - case NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS: - clock_period_ps = 10000000; - break; - case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS: - clock_period_ps = 12500; - break; - case NI_GPCT_PXI10_CLOCK_SRC_BITS: - clock_period_ps = 100000; - break; - default: - /* clock period is specified by user with prescaling already taken into account. */ - return counter->clock_period_ps; - break; - } - - switch (generic_clock_source & NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK) { - case NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS: - break; - case NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS: - clock_period_ps *= 2; - break; - case NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS: - clock_period_ps *= 8; - break; - default: - BUG(); - break; - } - return clock_period_ps; -} - static void ni_tio_get_clock_src(struct ni_gpct *counter, unsigned int *clock_source, unsigned int *period_ns) { - static const unsigned pico_per_nano = 1000; uint64_t temp64; + *clock_source = ni_tio_generic_clock_src_select(counter); temp64 = ni_tio_clock_period_ps(counter, *clock_source); - do_div(temp64, pico_per_nano); + do_div(temp64, 1000); /* ps to ns */ *period_ns = temp64; } -static void ni_tio_set_first_gate_modifiers(struct ni_gpct *counter, - unsigned int gate_source) +static int ni_660x_set_gate(struct ni_gpct *counter, unsigned int gate_source) { - const unsigned mode_mask = Gi_Gate_Polarity_Bit | Gi_Gating_Mode_Mask; + unsigned int chan = CR_CHAN(gate_source); unsigned cidx = counter->counter_index; - unsigned mode_values = 0; - - if (gate_source & CR_INVERT) - mode_values |= Gi_Gate_Polarity_Bit; - if (gate_source & CR_EDGE) - mode_values |= Gi_Rising_Edge_Gating_Bits; - else - mode_values |= Gi_Level_Gating_Bits; - ni_tio_set_bits(counter, NITIO_MODE_REG(cidx), - mode_mask, mode_values); -} - -static int ni_660x_set_first_gate(struct ni_gpct *counter, - unsigned int gate_source) -{ - const unsigned selected_gate = CR_CHAN(gate_source); - unsigned cidx = counter->counter_index; - /* bits of selected_gate that may be meaningful to input select register */ - const unsigned selected_gate_mask = 0x1f; - unsigned ni_660x_gate_select; + unsigned gate_sel; unsigned i; - switch (selected_gate) { + switch (chan) { case NI_GPCT_NEXT_SOURCE_GATE_SELECT: - ni_660x_gate_select = NI_660x_Next_SRC_Gate_Select; + gate_sel = NI_660X_NEXT_SRC_GATE_SEL; break; case NI_GPCT_NEXT_OUT_GATE_SELECT: case NI_GPCT_LOGIC_LOW_GATE_SELECT: case NI_GPCT_SOURCE_PIN_i_GATE_SELECT: case NI_GPCT_GATE_PIN_i_GATE_SELECT: - ni_660x_gate_select = selected_gate & selected_gate_mask; + gate_sel = chan & 0x1f; break; default: - for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { - if (selected_gate == NI_GPCT_RTSI_GATE_SELECT(i)) { - ni_660x_gate_select = - selected_gate & selected_gate_mask; + for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) { + if (chan == NI_GPCT_RTSI_GATE_SELECT(i)) { + gate_sel = chan & 0x1f; break; } } - if (i <= ni_660x_max_rtsi_channel) + if (i <= NI_660X_MAX_RTSI_CHAN) break; - for (i = 0; i <= ni_660x_max_gate_pin; ++i) { - if (selected_gate == NI_GPCT_GATE_PIN_GATE_SELECT(i)) { - ni_660x_gate_select = - selected_gate & selected_gate_mask; + for (i = 0; i <= NI_660X_MAX_GATE_PIN; ++i) { + if (chan == NI_GPCT_GATE_PIN_GATE_SELECT(i)) { + gate_sel = chan & 0x1f; break; } } - if (i <= ni_660x_max_gate_pin) + if (i <= NI_660X_MAX_GATE_PIN) break; return -EINVAL; - break; } ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), - Gi_Gate_Select_Mask, - Gi_Gate_Select_Bits(ni_660x_gate_select)); + GI_GATE_SEL_MASK, GI_GATE_SEL(gate_sel)); return 0; } -static int ni_m_series_set_first_gate(struct ni_gpct *counter, - unsigned int gate_source) +static int ni_m_set_gate(struct ni_gpct *counter, unsigned int gate_source) { - const unsigned selected_gate = CR_CHAN(gate_source); + unsigned int chan = CR_CHAN(gate_source); unsigned cidx = counter->counter_index; - /* bits of selected_gate that may be meaningful to input select register */ - const unsigned selected_gate_mask = 0x1f; - unsigned ni_m_series_gate_select; + unsigned gate_sel; unsigned i; - switch (selected_gate) { + switch (chan) { case NI_GPCT_TIMESTAMP_MUX_GATE_SELECT: case NI_GPCT_AI_START2_GATE_SELECT: case NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT: @@ -1062,120 +796,99 @@ static int ni_m_series_set_first_gate(struct ni_gpct *counter, case NI_GPCT_NEXT_SOURCE_GATE_SELECT: case NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT: case NI_GPCT_LOGIC_LOW_GATE_SELECT: - ni_m_series_gate_select = selected_gate & selected_gate_mask; + gate_sel = chan & 0x1f; break; default: - for (i = 0; i <= ni_m_series_max_rtsi_channel; ++i) { - if (selected_gate == NI_GPCT_RTSI_GATE_SELECT(i)) { - ni_m_series_gate_select = - selected_gate & selected_gate_mask; + for (i = 0; i <= NI_M_MAX_RTSI_CHAN; ++i) { + if (chan == NI_GPCT_RTSI_GATE_SELECT(i)) { + gate_sel = chan & 0x1f; break; } } - if (i <= ni_m_series_max_rtsi_channel) + if (i <= NI_M_MAX_RTSI_CHAN) break; - for (i = 0; i <= ni_m_series_max_pfi_channel; ++i) { - if (selected_gate == NI_GPCT_PFI_GATE_SELECT(i)) { - ni_m_series_gate_select = - selected_gate & selected_gate_mask; + for (i = 0; i <= NI_M_MAX_PFI_CHAN; ++i) { + if (chan == NI_GPCT_PFI_GATE_SELECT(i)) { + gate_sel = chan & 0x1f; break; } } - if (i <= ni_m_series_max_pfi_channel) + if (i <= NI_M_MAX_PFI_CHAN) break; return -EINVAL; - break; } ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), - Gi_Gate_Select_Mask, - Gi_Gate_Select_Bits(ni_m_series_gate_select)); + GI_GATE_SEL_MASK, GI_GATE_SEL(gate_sel)); return 0; } -static int ni_660x_set_second_gate(struct ni_gpct *counter, - unsigned int gate_source) +static int ni_660x_set_gate2(struct ni_gpct *counter, unsigned int gate_source) { struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned cidx = counter->counter_index; - const unsigned second_gate_reg = NITIO_GATE2_REG(cidx); - const unsigned selected_second_gate = CR_CHAN(gate_source); - /* bits of second_gate that may be meaningful to second gate register */ - static const unsigned selected_second_gate_mask = 0x1f; - unsigned ni_660x_second_gate_select; + unsigned int chan = CR_CHAN(gate_source); + unsigned gate2_reg = NITIO_GATE2_REG(cidx); + unsigned gate2_sel; unsigned i; - switch (selected_second_gate) { + switch (chan) { case NI_GPCT_SOURCE_PIN_i_GATE_SELECT: case NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT: case NI_GPCT_SELECTED_GATE_GATE_SELECT: case NI_GPCT_NEXT_OUT_GATE_SELECT: case NI_GPCT_LOGIC_LOW_GATE_SELECT: - ni_660x_second_gate_select = - selected_second_gate & selected_second_gate_mask; + gate2_sel = chan & 0x1f; break; case NI_GPCT_NEXT_SOURCE_GATE_SELECT: - ni_660x_second_gate_select = - NI_660x_Next_SRC_Second_Gate_Select; + gate2_sel = NI_660X_NEXT_SRC_GATE2_SEL; break; default: - for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { - if (selected_second_gate == NI_GPCT_RTSI_GATE_SELECT(i)) { - ni_660x_second_gate_select = - selected_second_gate & - selected_second_gate_mask; + for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) { + if (chan == NI_GPCT_RTSI_GATE_SELECT(i)) { + gate2_sel = chan & 0x1f; break; } } - if (i <= ni_660x_max_rtsi_channel) + if (i <= NI_660X_MAX_RTSI_CHAN) break; - for (i = 0; i <= ni_660x_max_up_down_pin; ++i) { - if (selected_second_gate == - NI_GPCT_UP_DOWN_PIN_GATE_SELECT(i)) { - ni_660x_second_gate_select = - selected_second_gate & - selected_second_gate_mask; + for (i = 0; i <= NI_660X_MAX_UP_DOWN_PIN; ++i) { + if (chan == NI_GPCT_UP_DOWN_PIN_GATE_SELECT(i)) { + gate2_sel = chan & 0x1f; break; } } - if (i <= ni_660x_max_up_down_pin) + if (i <= NI_660X_MAX_UP_DOWN_PIN) break; return -EINVAL; - break; } - counter_dev->regs[second_gate_reg] |= Gi_Second_Gate_Mode_Bit; - counter_dev->regs[second_gate_reg] &= ~Gi_Second_Gate_Select_Mask; - counter_dev->regs[second_gate_reg] |= - Gi_Second_Gate_Select_Bits(ni_660x_second_gate_select); - write_register(counter, counter_dev->regs[second_gate_reg], - second_gate_reg); + counter_dev->regs[gate2_reg] |= GI_GATE2_MODE; + counter_dev->regs[gate2_reg] &= ~GI_GATE2_SEL_MASK; + counter_dev->regs[gate2_reg] |= GI_GATE2_SEL(gate2_sel); + write_register(counter, counter_dev->regs[gate2_reg], gate2_reg); return 0; } -static int ni_m_series_set_second_gate(struct ni_gpct *counter, - unsigned int gate_source) +static int ni_m_set_gate2(struct ni_gpct *counter, unsigned int gate_source) { struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned cidx = counter->counter_index; - const unsigned second_gate_reg = NITIO_GATE2_REG(cidx); - const unsigned selected_second_gate = CR_CHAN(gate_source); - /* bits of second_gate that may be meaningful to second gate register */ - static const unsigned selected_second_gate_mask = 0x1f; - unsigned ni_m_series_second_gate_select; - - /* FIXME: We don't know what the m-series second gate codes are, so we'll just pass - the bits through for now. */ - switch (selected_second_gate) { + unsigned int chan = CR_CHAN(gate_source); + unsigned gate2_reg = NITIO_GATE2_REG(cidx); + unsigned gate2_sel; + + /* + * FIXME: We don't know what the m-series second gate codes are, + * so we'll just pass the bits through for now. + */ + switch (chan) { default: - ni_m_series_second_gate_select = - selected_second_gate & selected_second_gate_mask; + gate2_sel = chan & 0x1f; break; } - counter_dev->regs[second_gate_reg] |= Gi_Second_Gate_Mode_Bit; - counter_dev->regs[second_gate_reg] &= ~Gi_Second_Gate_Select_Mask; - counter_dev->regs[second_gate_reg] |= - Gi_Second_Gate_Select_Bits(ni_m_series_second_gate_select); - write_register(counter, counter_dev->regs[second_gate_reg], - second_gate_reg); + counter_dev->regs[gate2_reg] |= GI_GATE2_MODE; + counter_dev->regs[gate2_reg] &= ~GI_GATE2_SEL_MASK; + counter_dev->regs[gate2_reg] |= GI_GATE2_SEL(gate2_sel); + write_register(counter, counter_dev->regs[gate2_reg], gate2_reg); return 0; } @@ -1184,56 +897,55 @@ int ni_tio_set_gate_src(struct ni_gpct *counter, unsigned gate_index, { struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned cidx = counter->counter_index; - const unsigned second_gate_reg = NITIO_GATE2_REG(cidx); + unsigned int chan = CR_CHAN(gate_source); + unsigned gate2_reg = NITIO_GATE2_REG(cidx); + unsigned mode = 0; switch (gate_index) { case 0: - if (CR_CHAN(gate_source) == NI_GPCT_DISABLED_GATE_SELECT) { + if (chan == NI_GPCT_DISABLED_GATE_SELECT) { ni_tio_set_bits(counter, NITIO_MODE_REG(cidx), - Gi_Gating_Mode_Mask, - Gi_Gating_Disabled_Bits); + GI_GATING_MODE_MASK, + GI_GATING_DISABLED); return 0; } - ni_tio_set_first_gate_modifiers(counter, gate_source); + if (gate_source & CR_INVERT) + mode |= GI_GATE_POL_INVERT; + if (gate_source & CR_EDGE) + mode |= GI_RISING_EDGE_GATING; + else + mode |= GI_LEVEL_GATING; + ni_tio_set_bits(counter, NITIO_MODE_REG(cidx), + GI_GATE_POL_INVERT | GI_GATING_MODE_MASK, + mode); switch (counter_dev->variant) { case ni_gpct_variant_e_series: case ni_gpct_variant_m_series: - return ni_m_series_set_first_gate(counter, gate_source); - break; - case ni_gpct_variant_660x: - return ni_660x_set_first_gate(counter, gate_source); - break; default: - BUG(); - break; + return ni_m_set_gate(counter, gate_source); + case ni_gpct_variant_660x: + return ni_660x_set_gate(counter, gate_source); } break; case 1: - if (ni_tio_second_gate_registers_present(counter_dev) == 0) + if (!ni_tio_has_gate2_registers(counter_dev)) return -EINVAL; - if (CR_CHAN(gate_source) == NI_GPCT_DISABLED_GATE_SELECT) { - counter_dev->regs[second_gate_reg] &= - ~Gi_Second_Gate_Mode_Bit; - write_register(counter, - counter_dev->regs[second_gate_reg], - second_gate_reg); + + if (chan == NI_GPCT_DISABLED_GATE_SELECT) { + counter_dev->regs[gate2_reg] &= ~GI_GATE2_MODE; + write_register(counter, counter_dev->regs[gate2_reg], + gate2_reg); return 0; } - if (gate_source & CR_INVERT) { - counter_dev->regs[second_gate_reg] |= - Gi_Second_Gate_Polarity_Bit; - } else { - counter_dev->regs[second_gate_reg] &= - ~Gi_Second_Gate_Polarity_Bit; - } + if (gate_source & CR_INVERT) + counter_dev->regs[gate2_reg] |= GI_GATE2_POL_INVERT; + else + counter_dev->regs[gate2_reg] &= ~GI_GATE2_POL_INVERT; switch (counter_dev->variant) { case ni_gpct_variant_m_series: - return ni_m_series_set_second_gate(counter, - gate_source); - break; + return ni_m_set_gate2(counter, gate_source); case ni_gpct_variant_660x: - return ni_660x_set_second_gate(counter, gate_source); - break; + return ni_660x_set_gate2(counter, gate_source); default: BUG(); break; @@ -1241,7 +953,6 @@ int ni_tio_set_gate_src(struct ni_gpct *counter, unsigned gate_index, break; default: return -EINVAL; - break; } return 0; } @@ -1252,196 +963,142 @@ static int ni_tio_set_other_src(struct ni_gpct *counter, unsigned index, { struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned cidx = counter->counter_index; + unsigned int abz_reg, shift, mask; - if (counter_dev->variant == ni_gpct_variant_m_series) { - unsigned int abz_reg, shift, mask; + if (counter_dev->variant != ni_gpct_variant_m_series) + return -EINVAL; - abz_reg = NITIO_ABZ_REG(cidx); - switch (index) { - case NI_GPCT_SOURCE_ENCODER_A: - shift = 10; - break; - case NI_GPCT_SOURCE_ENCODER_B: - shift = 5; - break; - case NI_GPCT_SOURCE_ENCODER_Z: - shift = 0; - break; - default: - return -EINVAL; - break; - } - mask = 0x1f << shift; - if (source > 0x1f) { - /* Disable gate */ - source = 0x1f; - } - counter_dev->regs[abz_reg] &= ~mask; - counter_dev->regs[abz_reg] |= (source << shift) & mask; - write_register(counter, counter_dev->regs[abz_reg], abz_reg); - return 0; + abz_reg = NITIO_ABZ_REG(cidx); + switch (index) { + case NI_GPCT_SOURCE_ENCODER_A: + shift = 10; + break; + case NI_GPCT_SOURCE_ENCODER_B: + shift = 5; + break; + case NI_GPCT_SOURCE_ENCODER_Z: + shift = 0; + break; + default: + return -EINVAL; } - return -EINVAL; + mask = 0x1f << shift; + if (source > 0x1f) + source = 0x1f; /* Disable gate */ + + counter_dev->regs[abz_reg] &= ~mask; + counter_dev->regs[abz_reg] |= (source << shift) & mask; + write_register(counter, counter_dev->regs[abz_reg], abz_reg); + return 0; } -static unsigned ni_660x_first_gate_to_generic_gate_source(unsigned - ni_660x_gate_select) +static unsigned ni_660x_gate_to_generic_gate(unsigned gate) { unsigned i; - switch (ni_660x_gate_select) { - case NI_660x_Source_Pin_i_Gate_Select: + switch (gate) { + case NI_660X_SRC_PIN_I_GATE_SEL: return NI_GPCT_SOURCE_PIN_i_GATE_SELECT; - break; - case NI_660x_Gate_Pin_i_Gate_Select: + case NI_660X_GATE_PIN_I_GATE_SEL: return NI_GPCT_GATE_PIN_i_GATE_SELECT; - break; - case NI_660x_Next_SRC_Gate_Select: + case NI_660X_NEXT_SRC_GATE_SEL: return NI_GPCT_NEXT_SOURCE_GATE_SELECT; - break; - case NI_660x_Next_Out_Gate_Select: + case NI_660X_NEXT_OUT_GATE_SEL: return NI_GPCT_NEXT_OUT_GATE_SELECT; - break; - case NI_660x_Logic_Low_Gate_Select: + case NI_660X_LOGIC_LOW_GATE_SEL: return NI_GPCT_LOGIC_LOW_GATE_SELECT; - break; default: - for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { - if (ni_660x_gate_select == NI_660x_RTSI_Gate_Select(i)) { + for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) { + if (gate == NI_660X_RTSI_GATE_SEL(i)) return NI_GPCT_RTSI_GATE_SELECT(i); - break; - } } - if (i <= ni_660x_max_rtsi_channel) - break; - for (i = 0; i <= ni_660x_max_gate_pin; ++i) { - if (ni_660x_gate_select == - NI_660x_Gate_Pin_Gate_Select(i)) { + for (i = 0; i <= NI_660X_MAX_GATE_PIN; ++i) { + if (gate == NI_660X_PIN_GATE_SEL(i)) return NI_GPCT_GATE_PIN_GATE_SELECT(i); - break; - } } - if (i <= ni_660x_max_gate_pin) - break; BUG(); break; } return 0; }; -static unsigned ni_m_series_first_gate_to_generic_gate_source(unsigned - ni_m_series_gate_select) +static unsigned ni_m_gate_to_generic_gate(unsigned gate) { unsigned i; - switch (ni_m_series_gate_select) { - case NI_M_Series_Timestamp_Mux_Gate_Select: + switch (gate) { + case NI_M_TIMESTAMP_MUX_GATE_SEL: return NI_GPCT_TIMESTAMP_MUX_GATE_SELECT; - break; - case NI_M_Series_AI_START2_Gate_Select: + case NI_M_AI_START2_GATE_SEL: return NI_GPCT_AI_START2_GATE_SELECT; - break; - case NI_M_Series_PXI_Star_Trigger_Gate_Select: + case NI_M_PXI_STAR_TRIGGER_GATE_SEL: return NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT; - break; - case NI_M_Series_Next_Out_Gate_Select: + case NI_M_NEXT_OUT_GATE_SEL: return NI_GPCT_NEXT_OUT_GATE_SELECT; - break; - case NI_M_Series_AI_START1_Gate_Select: + case NI_M_AI_START1_GATE_SEL: return NI_GPCT_AI_START1_GATE_SELECT; - break; - case NI_M_Series_Next_SRC_Gate_Select: + case NI_M_NEXT_SRC_GATE_SEL: return NI_GPCT_NEXT_SOURCE_GATE_SELECT; - break; - case NI_M_Series_Analog_Trigger_Out_Gate_Select: + case NI_M_ANALOG_TRIG_OUT_GATE_SEL: return NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT; - break; - case NI_M_Series_Logic_Low_Gate_Select: + case NI_M_LOGIC_LOW_GATE_SEL: return NI_GPCT_LOGIC_LOW_GATE_SELECT; - break; default: - for (i = 0; i <= ni_m_series_max_rtsi_channel; ++i) { - if (ni_m_series_gate_select == - NI_M_Series_RTSI_Gate_Select(i)) { + for (i = 0; i <= NI_M_MAX_RTSI_CHAN; ++i) { + if (gate == NI_M_RTSI_GATE_SEL(i)) return NI_GPCT_RTSI_GATE_SELECT(i); - break; - } } - if (i <= ni_m_series_max_rtsi_channel) - break; - for (i = 0; i <= ni_m_series_max_pfi_channel; ++i) { - if (ni_m_series_gate_select == - NI_M_Series_PFI_Gate_Select(i)) { + for (i = 0; i <= NI_M_MAX_PFI_CHAN; ++i) { + if (gate == NI_M_PFI_GATE_SEL(i)) return NI_GPCT_PFI_GATE_SELECT(i); - break; - } } - if (i <= ni_m_series_max_pfi_channel) - break; BUG(); break; } return 0; }; -static unsigned ni_660x_second_gate_to_generic_gate_source(unsigned - ni_660x_gate_select) +static unsigned ni_660x_gate2_to_generic_gate(unsigned gate) { unsigned i; - switch (ni_660x_gate_select) { - case NI_660x_Source_Pin_i_Second_Gate_Select: + switch (gate) { + case NI_660X_SRC_PIN_I_GATE2_SEL: return NI_GPCT_SOURCE_PIN_i_GATE_SELECT; - break; - case NI_660x_Up_Down_Pin_i_Second_Gate_Select: + case NI_660X_UD_PIN_I_GATE2_SEL: return NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT; - break; - case NI_660x_Next_SRC_Second_Gate_Select: + case NI_660X_NEXT_SRC_GATE2_SEL: return NI_GPCT_NEXT_SOURCE_GATE_SELECT; - break; - case NI_660x_Next_Out_Second_Gate_Select: + case NI_660X_NEXT_OUT_GATE2_SEL: return NI_GPCT_NEXT_OUT_GATE_SELECT; - break; - case NI_660x_Selected_Gate_Second_Gate_Select: + case NI_660X_SELECTED_GATE2_SEL: return NI_GPCT_SELECTED_GATE_GATE_SELECT; - break; - case NI_660x_Logic_Low_Second_Gate_Select: + case NI_660X_LOGIC_LOW_GATE2_SEL: return NI_GPCT_LOGIC_LOW_GATE_SELECT; - break; default: - for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { - if (ni_660x_gate_select == - NI_660x_RTSI_Second_Gate_Select(i)) { + for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) { + if (gate == NI_660X_RTSI_GATE2_SEL(i)) return NI_GPCT_RTSI_GATE_SELECT(i); - break; - } } - if (i <= ni_660x_max_rtsi_channel) - break; - for (i = 0; i <= ni_660x_max_up_down_pin; ++i) { - if (ni_660x_gate_select == - NI_660x_Up_Down_Pin_Second_Gate_Select(i)) { + for (i = 0; i <= NI_660X_MAX_UP_DOWN_PIN; ++i) { + if (gate == NI_660X_UD_PIN_GATE2_SEL(i)) return NI_GPCT_UP_DOWN_PIN_GATE_SELECT(i); - break; - } } - if (i <= ni_660x_max_up_down_pin) - break; BUG(); break; } return 0; }; -static unsigned ni_m_series_second_gate_to_generic_gate_source(unsigned - ni_m_series_gate_select) +static unsigned ni_m_gate2_to_generic_gate(unsigned gate) { - /*FIXME: the second gate sources for the m series are undocumented, so we just return - * the raw bits for now. */ - switch (ni_m_series_gate_select) { + /* + * FIXME: the second gate sources for the m series are undocumented, + * so we just return the raw bits for now. + */ + switch (gate) { default: - return ni_m_series_gate_select; - break; + return gate; } return 0; }; @@ -1451,84 +1108,62 @@ static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned gate_index, { struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned cidx = counter->counter_index; - const unsigned mode_bits = - ni_tio_get_soft_copy(counter, NITIO_MODE_REG(cidx)); - const unsigned second_gate_reg = NITIO_GATE2_REG(cidx); - unsigned gate_select_bits; + unsigned mode = ni_tio_get_soft_copy(counter, NITIO_MODE_REG(cidx)); + unsigned gate2_reg = NITIO_GATE2_REG(cidx); + unsigned gate; switch (gate_index) { case 0: - if ((mode_bits & Gi_Gating_Mode_Mask) == - Gi_Gating_Disabled_Bits) { + if ((mode & GI_GATING_MODE_MASK) == GI_GATING_DISABLED) { *gate_source = NI_GPCT_DISABLED_GATE_SELECT; return 0; - } else { - gate_select_bits = - (ni_tio_get_soft_copy(counter, - NITIO_INPUT_SEL_REG(cidx)) & - Gi_Gate_Select_Mask) >> Gi_Gate_Select_Shift; } + + gate = GI_BITS_TO_GATE(ni_tio_get_soft_copy(counter, + NITIO_INPUT_SEL_REG(cidx))); + switch (counter_dev->variant) { case ni_gpct_variant_e_series: case ni_gpct_variant_m_series: - *gate_source = - ni_m_series_first_gate_to_generic_gate_source - (gate_select_bits); + default: + *gate_source = ni_m_gate_to_generic_gate(gate); break; case ni_gpct_variant_660x: - *gate_source = - ni_660x_first_gate_to_generic_gate_source - (gate_select_bits); - break; - default: - BUG(); + *gate_source = ni_660x_gate_to_generic_gate(gate); break; } - if (mode_bits & Gi_Gate_Polarity_Bit) + if (mode & GI_GATE_POL_INVERT) *gate_source |= CR_INVERT; - if ((mode_bits & Gi_Gating_Mode_Mask) != Gi_Level_Gating_Bits) + if ((mode & GI_GATING_MODE_MASK) != GI_LEVEL_GATING) *gate_source |= CR_EDGE; break; case 1: - if ((mode_bits & Gi_Gating_Mode_Mask) == Gi_Gating_Disabled_Bits - || (counter_dev->regs[second_gate_reg] & - Gi_Second_Gate_Mode_Bit) - == 0) { + if ((mode & GI_GATING_MODE_MASK) == GI_GATING_DISABLED || + !(counter_dev->regs[gate2_reg] & GI_GATE2_MODE)) { *gate_source = NI_GPCT_DISABLED_GATE_SELECT; return 0; - } else { - gate_select_bits = - (counter_dev->regs[second_gate_reg] & - Gi_Second_Gate_Select_Mask) >> - Gi_Second_Gate_Select_Shift; } + + gate = GI_BITS_TO_GATE2(counter_dev->regs[gate2_reg]); + switch (counter_dev->variant) { case ni_gpct_variant_e_series: case ni_gpct_variant_m_series: - *gate_source = - ni_m_series_second_gate_to_generic_gate_source - (gate_select_bits); + default: + *gate_source = ni_m_gate2_to_generic_gate(gate); break; case ni_gpct_variant_660x: - *gate_source = - ni_660x_second_gate_to_generic_gate_source - (gate_select_bits); - break; - default: - BUG(); + *gate_source = ni_660x_gate2_to_generic_gate(gate); break; } - if (counter_dev->regs[second_gate_reg] & - Gi_Second_Gate_Polarity_Bit) { + if (counter_dev->regs[gate2_reg] & GI_GATE2_POL_INVERT) *gate_source |= CR_INVERT; - } /* second gate can't have edge/level mode set independently */ - if ((mode_bits & Gi_Gating_Mode_Mask) != Gi_Level_Gating_Bits) + if ((mode & GI_GATING_MODE_MASK) != GI_LEVEL_GATING) *gate_source |= CR_EDGE; break; default: return -EINVAL; - break; } return 0; } @@ -1539,43 +1174,41 @@ int ni_tio_insn_config(struct comedi_device *dev, unsigned int *data) { struct ni_gpct *counter = s->private; + unsigned cidx = counter->counter_index; + unsigned status; switch (data[0]) { case INSN_CONFIG_SET_COUNTER_MODE: return ni_tio_set_counter_mode(counter, data[1]); - break; case INSN_CONFIG_ARM: return ni_tio_arm(counter, 1, data[1]); - break; case INSN_CONFIG_DISARM: ni_tio_arm(counter, 0, 0); return 0; - break; case INSN_CONFIG_GET_COUNTER_STATUS: - data[1] = ni_tio_counter_status(counter); - data[2] = counter_status_mask; + data[1] = 0; + status = read_register(counter, NITIO_SHARED_STATUS_REG(cidx)); + if (status & GI_ARMED(cidx)) { + data[1] |= COMEDI_COUNTER_ARMED; + if (status & GI_COUNTING(cidx)) + data[1] |= COMEDI_COUNTER_COUNTING; + } + data[2] = COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING; return 0; - break; case INSN_CONFIG_SET_CLOCK_SRC: return ni_tio_set_clock_src(counter, data[1], data[2]); - break; case INSN_CONFIG_GET_CLOCK_SRC: ni_tio_get_clock_src(counter, &data[1], &data[2]); return 0; - break; case INSN_CONFIG_SET_GATE_SRC: return ni_tio_set_gate_src(counter, data[1], data[2]); - break; case INSN_CONFIG_GET_GATE_SRC: return ni_tio_get_gate_src(counter, data[1], &data[2]); - break; case INSN_CONFIG_SET_OTHER_SRC: return ni_tio_set_other_src(counter, data[1], data[2]); - break; case INSN_CONFIG_RESET: ni_tio_reset_count_and_disarm(counter); return 0; - break; default: break; } @@ -1583,6 +1216,33 @@ int ni_tio_insn_config(struct comedi_device *dev, } EXPORT_SYMBOL_GPL(ni_tio_insn_config); +static unsigned int ni_tio_read_sw_save_reg(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct ni_gpct *counter = s->private; + unsigned cidx = counter->counter_index; + unsigned int val; + + ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), GI_SAVE_TRACE, 0); + ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), + GI_SAVE_TRACE, GI_SAVE_TRACE); + + /* + * The count doesn't get latched until the next clock edge, so it is + * possible the count may change (once) while we are reading. Since + * the read of the SW_Save_Reg isn't atomic (apparently even when it's + * a 32 bit register according to 660x docs), we need to read twice + * and make sure the reading hasn't changed. If it has, a third read + * will be correct since the count value will definitely have latched + * by then. + */ + val = read_register(counter, NITIO_SW_SAVE_REG(cidx)); + if (val != read_register(counter, NITIO_SW_SAVE_REG(cidx))) + val = read_register(counter, NITIO_SW_SAVE_REG(cidx)); + + return val; +} + int ni_tio_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -1590,43 +1250,24 @@ int ni_tio_insn_read(struct comedi_device *dev, { struct ni_gpct *counter = s->private; struct ni_gpct_device *counter_dev = counter->counter_dev; - const unsigned channel = CR_CHAN(insn->chanspec); + unsigned int channel = CR_CHAN(insn->chanspec); unsigned cidx = counter->counter_index; - unsigned first_read; - unsigned second_read; - unsigned correct_read; + int i; - if (insn->n < 1) - return 0; - switch (channel) { - case 0: - ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), - Gi_Save_Trace_Bit, 0); - ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), - Gi_Save_Trace_Bit, Gi_Save_Trace_Bit); - /* The count doesn't get latched until the next clock edge, so it is possible the count - may change (once) while we are reading. Since the read of the SW_Save_Reg isn't - atomic (apparently even when it's a 32 bit register according to 660x docs), - we need to read twice and make sure the reading hasn't changed. If it has, - a third read will be correct since the count value will definitely have latched by then. */ - first_read = read_register(counter, NITIO_SW_SAVE_REG(cidx)); - second_read = read_register(counter, NITIO_SW_SAVE_REG(cidx)); - if (first_read != second_read) - correct_read = - read_register(counter, NITIO_SW_SAVE_REG(cidx)); - else - correct_read = first_read; - data[0] = correct_read; - return 0; - break; - case 1: - data[0] = counter_dev->regs[NITIO_LOADA_REG(cidx)]; - break; - case 2: - data[0] = counter_dev->regs[NITIO_LOADB_REG(cidx)]; - break; + for (i = 0; i < insn->n; i++) { + switch (channel) { + case 0: + data[i] = ni_tio_read_sw_save_reg(dev, s); + break; + case 1: + data[i] = counter_dev->regs[NITIO_LOADA_REG(cidx)]; + break; + case 2: + data[i] = counter_dev->regs[NITIO_LOADB_REG(cidx)]; + break; + } } - return 0; + return insn->n; } EXPORT_SYMBOL_GPL(ni_tio_insn_read); @@ -1636,10 +1277,9 @@ static unsigned ni_tio_next_load_register(struct ni_gpct *counter) const unsigned bits = read_register(counter, NITIO_SHARED_STATUS_REG(cidx)); - if (bits & Gi_Next_Load_Source_Bit(cidx)) - return NITIO_LOADB_REG(cidx); - else - return NITIO_LOADA_REG(cidx); + return (bits & GI_NEXT_LOAD_SRC(cidx)) + ? NITIO_LOADB_REG(cidx) + : NITIO_LOADA_REG(cidx); } int ni_tio_insn_write(struct comedi_device *dev, @@ -1657,13 +1297,20 @@ int ni_tio_insn_write(struct comedi_device *dev, return 0; switch (channel) { case 0: - /* Unsafe if counter is armed. Should probably check status and return -EBUSY if armed. */ - /* Don't disturb load source select, just use whichever load register is already selected. */ + /* + * Unsafe if counter is armed. + * Should probably check status and return -EBUSY if armed. + */ + + /* + * Don't disturb load source select, just use whichever + * load register is already selected. + */ load_reg = ni_tio_next_load_register(counter); write_register(counter, data[0], load_reg); ni_tio_set_bits_transient(counter, NITIO_CMD_REG(cidx), - 0, 0, Gi_Load_Bit); - /* restore state of load reg to whatever the user set last set it to */ + 0, 0, GI_LOAD); + /* restore load reg */ write_register(counter, counter_dev->regs[load_reg], load_reg); break; case 1: @@ -1676,12 +1323,104 @@ int ni_tio_insn_write(struct comedi_device *dev, break; default: return -EINVAL; - break; } return 0; } EXPORT_SYMBOL_GPL(ni_tio_insn_write); +void ni_tio_init_counter(struct ni_gpct *counter) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + unsigned cidx = counter->counter_index; + + ni_tio_reset_count_and_disarm(counter); + + /* initialize counter registers */ + counter_dev->regs[NITIO_AUTO_INC_REG(cidx)] = 0x0; + write_register(counter, 0x0, NITIO_AUTO_INC_REG(cidx)); + + ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), + ~0, GI_SYNC_GATE); + + ni_tio_set_bits(counter, NITIO_MODE_REG(cidx), ~0, 0); + + counter_dev->regs[NITIO_LOADA_REG(cidx)] = 0x0; + write_register(counter, 0x0, NITIO_LOADA_REG(cidx)); + + counter_dev->regs[NITIO_LOADB_REG(cidx)] = 0x0; + write_register(counter, 0x0, NITIO_LOADB_REG(cidx)); + + ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), ~0, 0); + + if (ni_tio_counting_mode_registers_present(counter_dev)) + ni_tio_set_bits(counter, NITIO_CNT_MODE_REG(cidx), ~0, 0); + + if (ni_tio_has_gate2_registers(counter_dev)) { + counter_dev->regs[NITIO_GATE2_REG(cidx)] = 0x0; + write_register(counter, 0x0, NITIO_GATE2_REG(cidx)); + } + + ni_tio_set_bits(counter, NITIO_DMA_CFG_REG(cidx), ~0, 0x0); + + ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx), ~0, 0x0); +} +EXPORT_SYMBOL_GPL(ni_tio_init_counter); + +struct ni_gpct_device * +ni_gpct_device_construct(struct comedi_device *dev, + void (*write_register)(struct ni_gpct *counter, + unsigned bits, + enum ni_gpct_register reg), + unsigned (*read_register)(struct ni_gpct *counter, + enum ni_gpct_register reg), + enum ni_gpct_variant variant, + unsigned num_counters) +{ + struct ni_gpct_device *counter_dev; + struct ni_gpct *counter; + unsigned i; + + if (num_counters == 0) + return NULL; + + counter_dev = kzalloc(sizeof(*counter_dev), GFP_KERNEL); + if (!counter_dev) + return NULL; + + counter_dev->dev = dev; + counter_dev->write_register = write_register; + counter_dev->read_register = read_register; + counter_dev->variant = variant; + + spin_lock_init(&counter_dev->regs_lock); + + counter_dev->counters = kcalloc(num_counters, sizeof(*counter), + GFP_KERNEL); + if (!counter_dev->counters) { + kfree(counter_dev); + return NULL; + } + + for (i = 0; i < num_counters; ++i) { + counter = &counter_dev->counters[i]; + counter->counter_dev = counter_dev; + spin_lock_init(&counter->lock); + } + counter_dev->num_counters = num_counters; + + return counter_dev; +} +EXPORT_SYMBOL_GPL(ni_gpct_device_construct); + +void ni_gpct_device_destroy(struct ni_gpct_device *counter_dev) +{ + if (!counter_dev->counters) + return; + kfree(counter_dev->counters); + kfree(counter_dev); +} +EXPORT_SYMBOL_GPL(ni_gpct_device_destroy); + static int __init ni_tio_init_module(void) { return 0; diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h index 1056bf001e5e..25aedd0e5867 100644 --- a/drivers/staging/comedi/drivers/ni_tio.h +++ b/drivers/staging/comedi/drivers/ni_tio.h @@ -149,8 +149,6 @@ int ni_tio_cmdtest(struct comedi_device *, struct comedi_subdevice *, int ni_tio_cancel(struct ni_gpct *); void ni_tio_handle_interrupt(struct ni_gpct *, struct comedi_subdevice *); void ni_tio_set_mite_channel(struct ni_gpct *, struct mite_channel *); -void ni_tio_acknowledge_and_confirm(struct ni_gpct *, - int *gate_error, int *tc_error, - int *perm_stale_data, int *stale_data); +void ni_tio_acknowledge(struct ni_gpct *); #endif /* _COMEDI_NI_TIO_H */ diff --git a/drivers/staging/comedi/drivers/ni_tio_internal.h b/drivers/staging/comedi/drivers/ni_tio_internal.h index 15b81b8fc5c4..2bceae493e23 100644 --- a/drivers/staging/comedi/drivers/ni_tio_internal.h +++ b/drivers/staging/comedi/drivers/ni_tio_internal.h @@ -22,296 +22,139 @@ #include "ni_tio.h" #define NITIO_AUTO_INC_REG(x) (NITIO_G0_AUTO_INC + (x)) +#define GI_AUTO_INC_MASK 0xff #define NITIO_CMD_REG(x) (NITIO_G0_CMD + (x)) +#define GI_ARM (1 << 0) +#define GI_SAVE_TRACE (1 << 1) +#define GI_LOAD (1 << 2) +#define GI_DISARM (1 << 4) +#define GI_CNT_DIR(x) (((x) & 0x3) << 5) +#define GI_CNT_DIR_MASK (3 << 5) +#define GI_WRITE_SWITCH (1 << 7) +#define GI_SYNC_GATE (1 << 8) +#define GI_LITTLE_BIG_ENDIAN (1 << 9) +#define GI_BANK_SWITCH_START (1 << 10) +#define GI_BANK_SWITCH_MODE (1 << 11) +#define GI_BANK_SWITCH_ENABLE (1 << 12) +#define GI_ARM_COPY (1 << 13) +#define GI_SAVE_TRACE_COPY (1 << 14) +#define GI_DISARM_COPY (1 << 15) #define NITIO_HW_SAVE_REG(x) (NITIO_G0_HW_SAVE + (x)) #define NITIO_SW_SAVE_REG(x) (NITIO_G0_SW_SAVE + (x)) #define NITIO_MODE_REG(x) (NITIO_G0_MODE + (x)) +#define GI_GATING_DISABLED (0 << 0) +#define GI_LEVEL_GATING (1 << 0) +#define GI_RISING_EDGE_GATING (2 << 0) +#define GI_FALLING_EDGE_GATING (3 << 0) +#define GI_GATING_MODE_MASK (3 << 0) +#define GI_GATE_ON_BOTH_EDGES (1 << 2) +#define GI_EDGE_GATE_STARTS_STOPS (0 << 3) +#define GI_EDGE_GATE_STOPS_STARTS (1 << 3) +#define GI_EDGE_GATE_STARTS (2 << 3) +#define GI_EDGE_GATE_NO_STARTS_OR_STOPS (3 << 3) +#define GI_EDGE_GATE_MODE_MASK (3 << 3) +#define GI_STOP_ON_GATE (0 << 5) +#define GI_STOP_ON_GATE_OR_TC (1 << 5) +#define GI_STOP_ON_GATE_OR_SECOND_TC (2 << 5) +#define GI_STOP_MODE_MASK (3 << 5) +#define GI_LOAD_SRC_SEL (1 << 7) +#define GI_OUTPUT_TC_PULSE (1 << 8) +#define GI_OUTPUT_TC_TOGGLE (2 << 8) +#define GI_OUTPUT_TC_OR_GATE_TOGGLE (3 << 8) +#define GI_OUTPUT_MODE_MASK (3 << 8) +#define GI_NO_HARDWARE_DISARM (0 << 10) +#define GI_DISARM_AT_TC (1 << 10) +#define GI_DISARM_AT_GATE (2 << 10) +#define GI_DISARM_AT_TC_OR_GATE (3 << 10) +#define GI_COUNTING_ONCE_MASK (3 << 10) +#define GI_LOADING_ON_TC (1 << 12) +#define GI_GATE_POL_INVERT (1 << 13) +#define GI_LOADING_ON_GATE (1 << 14) +#define GI_RELOAD_SRC_SWITCHING (1 << 15) #define NITIO_LOADA_REG(x) (NITIO_G0_LOADA + (x)) #define NITIO_LOADB_REG(x) (NITIO_G0_LOADB + (x)) #define NITIO_INPUT_SEL_REG(x) (NITIO_G0_INPUT_SEL + (x)) +#define GI_READ_ACKS_IRQ (1 << 0) +#define GI_WRITE_ACKS_IRQ (1 << 1) +#define GI_BITS_TO_SRC(x) (((x) >> 2) & 0x1f) +#define GI_SRC_SEL(x) (((x) & 0x1f) << 2) +#define GI_SRC_SEL_MASK (0x1f << 2) +#define GI_BITS_TO_GATE(x) (((x) >> 7) & 0x1f) +#define GI_GATE_SEL(x) (((x) & 0x1f) << 7) +#define GI_GATE_SEL_MASK (0x1f << 7) +#define GI_GATE_SEL_LOAD_SRC (1 << 12) +#define GI_OR_GATE (1 << 13) +#define GI_OUTPUT_POL_INVERT (1 << 14) +#define GI_SRC_POL_INVERT (1 << 15) #define NITIO_CNT_MODE_REG(x) (NITIO_G0_CNT_MODE + (x)) +#define GI_CNT_MODE(x) (((x) & 0x7) << 0) +#define GI_CNT_MODE_NORMAL GI_CNT_MODE(0) +#define GI_CNT_MODE_QUADX1 GI_CNT_MODE(1) +#define GI_CNT_MODE_QUADX2 GI_CNT_MODE(2) +#define GI_CNT_MODE_QUADX4 GI_CNT_MODE(3) +#define GI_CNT_MODE_TWO_PULSE GI_CNT_MODE(4) +#define GI_CNT_MODE_SYNC_SRC GI_CNT_MODE(6) +#define GI_CNT_MODE_MASK (7 << 0) +#define GI_INDEX_MODE (1 << 4) +#define GI_INDEX_PHASE(x) (((x) & 0x3) << 5) +#define GI_INDEX_PHASE_MASK (3 << 5) +#define GI_HW_ARM_ENA (1 << 7) +#define GI_HW_ARM_SEL(x) ((x) << 8) +#define GI_660X_HW_ARM_SEL_MASK (0x7 << 8) +#define GI_M_HW_ARM_SEL_MASK (0x1f << 8) +#define GI_660X_PRESCALE_X8 (1 << 12) +#define GI_M_PRESCALE_X8 (1 << 13) +#define GI_660X_ALT_SYNC (1 << 13) +#define GI_M_ALT_SYNC (1 << 14) +#define GI_660X_PRESCALE_X2 (1 << 14) +#define GI_M_PRESCALE_X2 (1 << 15) #define NITIO_GATE2_REG(x) (NITIO_G0_GATE2 + (x)) +#define GI_GATE2_MODE (1 << 0) +#define GI_BITS_TO_GATE2(x) (((x) >> 7) & 0x1f) +#define GI_GATE2_SEL(x) (((x) & 0x1f) << 7) +#define GI_GATE2_SEL_MASK (0x1f << 7) +#define GI_GATE2_POL_INVERT (1 << 13) +#define GI_GATE2_SUBSEL (1 << 14) +#define GI_SRC_SUBSEL (1 << 15) #define NITIO_SHARED_STATUS_REG(x) (NITIO_G01_STATUS + ((x) / 2)) +#define GI_SAVE(x) (((x) % 2) ? (1 << 1) : (1 << 0)) +#define GI_COUNTING(x) (((x) % 2) ? (1 << 3) : (1 << 2)) +#define GI_NEXT_LOAD_SRC(x) (((x) % 2) ? (1 << 5) : (1 << 4)) +#define GI_STALE_DATA(x) (((x) % 2) ? (1 << 7) : (1 << 6)) +#define GI_ARMED(x) (((x) % 2) ? (1 << 9) : (1 << 8)) +#define GI_NO_LOAD_BETWEEN_GATES(x) (((x) % 2) ? (1 << 11) : (1 << 10)) +#define GI_TC_ERROR(x) (((x) % 2) ? (1 << 13) : (1 << 12)) +#define GI_GATE_ERROR(x) (((x) % 2) ? (1 << 15) : (1 << 14)) #define NITIO_RESET_REG(x) (NITIO_G01_RESET + ((x) / 2)) +#define GI_RESET(x) (1 << (2 + ((x) % 2))) #define NITIO_STATUS1_REG(x) (NITIO_G01_STATUS1 + ((x) / 2)) #define NITIO_STATUS2_REG(x) (NITIO_G01_STATUS2 + ((x) / 2)) +#define GI_OUTPUT(x) (((x) % 2) ? (1 << 1) : (1 << 0)) +#define GI_HW_SAVE(x) (((x) % 2) ? (1 << 13) : (1 << 12)) +#define GI_PERMANENT_STALE(x) (((x) % 2) ? (1 << 15) : (1 << 14)) #define NITIO_DMA_CFG_REG(x) (NITIO_G0_DMA_CFG + (x)) +#define GI_DMA_ENABLE (1 << 0) +#define GI_DMA_WRITE (1 << 1) +#define GI_DMA_INT_ENA (1 << 2) +#define GI_DMA_RESET (1 << 3) +#define GI_DMA_BANKSW_ERROR (1 << 4) #define NITIO_DMA_STATUS_REG(x) (NITIO_G0_DMA_STATUS + (x)) +#define GI_DMA_READBANK (1 << 13) +#define GI_DRQ_ERROR (1 << 14) +#define GI_DRQ_STATUS (1 << 15) #define NITIO_ABZ_REG(x) (NITIO_G0_ABZ + (x)) #define NITIO_INT_ACK_REG(x) (NITIO_G0_INT_ACK + (x)) +#define GI_GATE_ERROR_CONFIRM(x) (((x) % 2) ? (1 << 1) : (1 << 5)) +#define GI_TC_ERROR_CONFIRM(x) (((x) % 2) ? (1 << 2) : (1 << 6)) +#define GI_TC_INTERRUPT_ACK (1 << 14) +#define GI_GATE_INTERRUPT_ACK (1 << 15) #define NITIO_STATUS_REG(x) (NITIO_G0_STATUS + (x)) +#define GI_GATE_INTERRUPT (1 << 2) +#define GI_TC (1 << 3) +#define GI_INTERRUPT (1 << 15) #define NITIO_INT_ENA_REG(x) (NITIO_G0_INT_ENA + (x)) - -enum Gi_Auto_Increment_Reg_Bits { - Gi_Auto_Increment_Mask = 0xff -}; - -#define Gi_Up_Down_Shift 5 -enum Gi_Command_Reg_Bits { - Gi_Arm_Bit = 0x1, - Gi_Save_Trace_Bit = 0x2, - Gi_Load_Bit = 0x4, - Gi_Disarm_Bit = 0x10, - Gi_Up_Down_Mask = 0x3 << Gi_Up_Down_Shift, - Gi_Always_Down_Bits = 0x0 << Gi_Up_Down_Shift, - Gi_Always_Up_Bits = 0x1 << Gi_Up_Down_Shift, - Gi_Up_Down_Hardware_IO_Bits = 0x2 << Gi_Up_Down_Shift, - Gi_Up_Down_Hardware_Gate_Bits = 0x3 << Gi_Up_Down_Shift, - Gi_Write_Switch_Bit = 0x80, - Gi_Synchronize_Gate_Bit = 0x100, - Gi_Little_Big_Endian_Bit = 0x200, - Gi_Bank_Switch_Start_Bit = 0x400, - Gi_Bank_Switch_Mode_Bit = 0x800, - Gi_Bank_Switch_Enable_Bit = 0x1000, - Gi_Arm_Copy_Bit = 0x2000, - Gi_Save_Trace_Copy_Bit = 0x4000, - Gi_Disarm_Copy_Bit = 0x8000 -}; - -#define Gi_Index_Phase_Bitshift 5 -#define Gi_HW_Arm_Select_Shift 8 -enum Gi_Counting_Mode_Reg_Bits { - Gi_Counting_Mode_Mask = 0x7, - Gi_Counting_Mode_Normal_Bits = 0x0, - Gi_Counting_Mode_QuadratureX1_Bits = 0x1, - Gi_Counting_Mode_QuadratureX2_Bits = 0x2, - Gi_Counting_Mode_QuadratureX4_Bits = 0x3, - Gi_Counting_Mode_Two_Pulse_Bits = 0x4, - Gi_Counting_Mode_Sync_Source_Bits = 0x6, - Gi_Index_Mode_Bit = 0x10, - Gi_Index_Phase_Mask = 0x3 << Gi_Index_Phase_Bitshift, - Gi_Index_Phase_LowA_LowB = 0x0 << Gi_Index_Phase_Bitshift, - Gi_Index_Phase_LowA_HighB = 0x1 << Gi_Index_Phase_Bitshift, - Gi_Index_Phase_HighA_LowB = 0x2 << Gi_Index_Phase_Bitshift, - Gi_Index_Phase_HighA_HighB = 0x3 << Gi_Index_Phase_Bitshift, - /* from m-series example code, not documented in 660x register level - * manual */ - Gi_HW_Arm_Enable_Bit = 0x80, - /* from m-series example code, not documented in 660x register level - * manual */ - Gi_660x_HW_Arm_Select_Mask = 0x7 << Gi_HW_Arm_Select_Shift, - Gi_660x_Prescale_X8_Bit = 0x1000, - Gi_M_Series_Prescale_X8_Bit = 0x2000, - Gi_M_Series_HW_Arm_Select_Mask = 0x1f << Gi_HW_Arm_Select_Shift, - /* must be set for clocks over 40MHz, which includes synchronous - * counting and quadrature modes */ - Gi_660x_Alternate_Sync_Bit = 0x2000, - Gi_M_Series_Alternate_Sync_Bit = 0x4000, - /* from m-series example code, not documented in 660x register level - * manual */ - Gi_660x_Prescale_X2_Bit = 0x4000, - Gi_M_Series_Prescale_X2_Bit = 0x8000, -}; - -#define Gi_Source_Select_Shift 2 -#define Gi_Gate_Select_Shift 7 -enum Gi_Input_Select_Bits { - Gi_Read_Acknowledges_Irq = 0x1, /* not present on 660x */ - Gi_Write_Acknowledges_Irq = 0x2, /* not present on 660x */ - Gi_Source_Select_Mask = 0x7c, - Gi_Gate_Select_Mask = 0x1f << Gi_Gate_Select_Shift, - Gi_Gate_Select_Load_Source_Bit = 0x1000, - Gi_Or_Gate_Bit = 0x2000, - Gi_Output_Polarity_Bit = 0x4000, /* set to invert */ - Gi_Source_Polarity_Bit = 0x8000 /* set to invert */ -}; - -enum Gi_Mode_Bits { - Gi_Gating_Mode_Mask = 0x3, - Gi_Gating_Disabled_Bits = 0x0, - Gi_Level_Gating_Bits = 0x1, - Gi_Rising_Edge_Gating_Bits = 0x2, - Gi_Falling_Edge_Gating_Bits = 0x3, - Gi_Gate_On_Both_Edges_Bit = 0x4, /* used in conjunction with - * rising edge gating mode */ - Gi_Trigger_Mode_for_Edge_Gate_Mask = 0x18, - Gi_Edge_Gate_Starts_Stops_Bits = 0x0, - Gi_Edge_Gate_Stops_Starts_Bits = 0x8, - Gi_Edge_Gate_Starts_Bits = 0x10, - Gi_Edge_Gate_No_Starts_or_Stops_Bits = 0x18, - Gi_Stop_Mode_Mask = 0x60, - Gi_Stop_on_Gate_Bits = 0x00, - Gi_Stop_on_Gate_or_TC_Bits = 0x20, - Gi_Stop_on_Gate_or_Second_TC_Bits = 0x40, - Gi_Load_Source_Select_Bit = 0x80, - Gi_Output_Mode_Mask = 0x300, - Gi_Output_TC_Pulse_Bits = 0x100, - Gi_Output_TC_Toggle_Bits = 0x200, - Gi_Output_TC_or_Gate_Toggle_Bits = 0x300, - Gi_Counting_Once_Mask = 0xc00, - Gi_No_Hardware_Disarm_Bits = 0x000, - Gi_Disarm_at_TC_Bits = 0x400, - Gi_Disarm_at_Gate_Bits = 0x800, - Gi_Disarm_at_TC_or_Gate_Bits = 0xc00, - Gi_Loading_On_TC_Bit = 0x1000, - Gi_Gate_Polarity_Bit = 0x2000, - Gi_Loading_On_Gate_Bit = 0x4000, - Gi_Reload_Source_Switching_Bit = 0x8000 -}; - -#define Gi_Second_Gate_Select_Shift 7 -/*FIXME: m-series has a second gate subselect bit */ -/*FIXME: m-series second gate sources are undocumented (by NI)*/ -enum Gi_Second_Gate_Bits { - Gi_Second_Gate_Mode_Bit = 0x1, - Gi_Second_Gate_Select_Mask = 0x1f << Gi_Second_Gate_Select_Shift, - Gi_Second_Gate_Polarity_Bit = 0x2000, - Gi_Second_Gate_Subselect_Bit = 0x4000, /* m-series only */ - Gi_Source_Subselect_Bit = 0x8000 /* m-series only */ -}; -static inline unsigned Gi_Second_Gate_Select_Bits(unsigned second_gate_select) -{ - return (second_gate_select << Gi_Second_Gate_Select_Shift) & - Gi_Second_Gate_Select_Mask; -} - -enum Gxx_Status_Bits { - G0_Save_Bit = 0x1, - G1_Save_Bit = 0x2, - G0_Counting_Bit = 0x4, - G1_Counting_Bit = 0x8, - G0_Next_Load_Source_Bit = 0x10, - G1_Next_Load_Source_Bit = 0x20, - G0_Stale_Data_Bit = 0x40, - G1_Stale_Data_Bit = 0x80, - G0_Armed_Bit = 0x100, - G1_Armed_Bit = 0x200, - G0_No_Load_Between_Gates_Bit = 0x400, - G1_No_Load_Between_Gates_Bit = 0x800, - G0_TC_Error_Bit = 0x1000, - G1_TC_Error_Bit = 0x2000, - G0_Gate_Error_Bit = 0x4000, - G1_Gate_Error_Bit = 0x8000 -}; -static inline enum Gxx_Status_Bits Gi_Counting_Bit(unsigned counter_index) -{ - if (counter_index % 2) - return G1_Counting_Bit; - return G0_Counting_Bit; -} - -static inline enum Gxx_Status_Bits Gi_Armed_Bit(unsigned counter_index) -{ - if (counter_index % 2) - return G1_Armed_Bit; - return G0_Armed_Bit; -} - -static inline enum Gxx_Status_Bits Gi_Next_Load_Source_Bit(unsigned - counter_index) -{ - if (counter_index % 2) - return G1_Next_Load_Source_Bit; - return G0_Next_Load_Source_Bit; -} - -static inline enum Gxx_Status_Bits Gi_Stale_Data_Bit(unsigned counter_index) -{ - if (counter_index % 2) - return G1_Stale_Data_Bit; - return G0_Stale_Data_Bit; -} - -static inline enum Gxx_Status_Bits Gi_TC_Error_Bit(unsigned counter_index) -{ - if (counter_index % 2) - return G1_TC_Error_Bit; - return G0_TC_Error_Bit; -} - -static inline enum Gxx_Status_Bits Gi_Gate_Error_Bit(unsigned counter_index) -{ - if (counter_index % 2) - return G1_Gate_Error_Bit; - return G0_Gate_Error_Bit; -} - -/* joint reset register bits */ -static inline unsigned Gi_Reset_Bit(unsigned counter_index) -{ - return 0x1 << (2 + (counter_index % 2)); -} - -enum Gxx_Joint_Status2_Bits { - G0_Output_Bit = 0x1, - G1_Output_Bit = 0x2, - G0_HW_Save_Bit = 0x1000, - G1_HW_Save_Bit = 0x2000, - G0_Permanent_Stale_Bit = 0x4000, - G1_Permanent_Stale_Bit = 0x8000 -}; -static inline enum Gxx_Joint_Status2_Bits Gi_Permanent_Stale_Bit(unsigned - counter_index) -{ - if (counter_index % 2) - return G1_Permanent_Stale_Bit; - return G0_Permanent_Stale_Bit; -} - -enum Gi_DMA_Config_Reg_Bits { - Gi_DMA_Enable_Bit = 0x1, - Gi_DMA_Write_Bit = 0x2, - Gi_DMA_Int_Bit = 0x4 -}; - -enum Gi_DMA_Status_Reg_Bits { - Gi_DMA_Readbank_Bit = 0x2000, - Gi_DRQ_Error_Bit = 0x4000, - Gi_DRQ_Status_Bit = 0x8000 -}; - -enum G02_Interrupt_Acknowledge_Bits { - G0_Gate_Error_Confirm_Bit = 0x20, - G0_TC_Error_Confirm_Bit = 0x40 -}; -enum G13_Interrupt_Acknowledge_Bits { - G1_Gate_Error_Confirm_Bit = 0x2, - G1_TC_Error_Confirm_Bit = 0x4 -}; -static inline unsigned Gi_Gate_Error_Confirm_Bit(unsigned counter_index) -{ - if (counter_index % 2) - return G1_Gate_Error_Confirm_Bit; - return G0_Gate_Error_Confirm_Bit; -} - -static inline unsigned Gi_TC_Error_Confirm_Bit(unsigned counter_index) -{ - if (counter_index % 2) - return G1_TC_Error_Confirm_Bit; - return G0_TC_Error_Confirm_Bit; -} - -/* bits that are the same in G0/G2 and G1/G3 interrupt acknowledge registers */ -enum Gxx_Interrupt_Acknowledge_Bits { - Gi_TC_Interrupt_Ack_Bit = 0x4000, - Gi_Gate_Interrupt_Ack_Bit = 0x8000 -}; - -enum Gi_Status_Bits { - Gi_Gate_Interrupt_Bit = 0x4, - Gi_TC_Bit = 0x8, - Gi_Interrupt_Bit = 0x8000 -}; - -enum G02_Interrupt_Enable_Bits { - G0_TC_Interrupt_Enable_Bit = 0x40, - G0_Gate_Interrupt_Enable_Bit = 0x100 -}; -enum G13_Interrupt_Enable_Bits { - G1_TC_Interrupt_Enable_Bit = 0x200, - G1_Gate_Interrupt_Enable_Bit = 0x400 -}; -static inline unsigned Gi_Gate_Interrupt_Enable_Bit(unsigned counter_index) -{ - unsigned bit; - - if (counter_index % 2) - bit = G1_Gate_Interrupt_Enable_Bit; - else - bit = G0_Gate_Interrupt_Enable_Bit; - return bit; -} +#define GI_TC_INTERRUPT_ENABLE(x) (((x) % 2) ? (1 << 9) : (1 << 6)) +#define GI_GATE_INTERRUPT_ENABLE(x) (((x) % 2) ? (1 << 10) : (1 << 8)) static inline void write_register(struct ni_gpct *counter, unsigned bits, enum ni_gpct_register reg) @@ -334,11 +177,9 @@ static inline int ni_tio_counting_mode_registers_present(const struct switch (counter_dev->variant) { case ni_gpct_variant_e_series: return 0; - break; case ni_gpct_variant_m_series: case ni_gpct_variant_660x: return 1; - break; default: BUG(); break; diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c index 2557ab48cb6c..299ceddfb233 100644 --- a/drivers/staging/comedi/drivers/ni_tiocmd.c +++ b/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -49,40 +49,38 @@ TODO: #include "ni_tio_internal.h" #include "mite.h" -static void ni_tio_configure_dma(struct ni_gpct *counter, short enable, - short read_not_write) +static void ni_tio_configure_dma(struct ni_gpct *counter, + bool enable, bool read) { struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned cidx = counter->counter_index; - unsigned input_select_bits = 0; + unsigned mask; + unsigned bits; + + mask = GI_READ_ACKS_IRQ | GI_WRITE_ACKS_IRQ; + bits = 0; if (enable) { - if (read_not_write) - input_select_bits |= Gi_Read_Acknowledges_Irq; + if (read) + bits |= GI_READ_ACKS_IRQ; else - input_select_bits |= Gi_Write_Acknowledges_Irq; + bits |= GI_WRITE_ACKS_IRQ; } - ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), - Gi_Read_Acknowledges_Irq | Gi_Write_Acknowledges_Irq, - input_select_bits); + ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), mask, bits); + switch (counter_dev->variant) { case ni_gpct_variant_e_series: break; case ni_gpct_variant_m_series: case ni_gpct_variant_660x: - { - unsigned gi_dma_config_bits = 0; - - if (enable) { - gi_dma_config_bits |= Gi_DMA_Enable_Bit; - gi_dma_config_bits |= Gi_DMA_Int_Bit; - } - if (read_not_write == 0) - gi_dma_config_bits |= Gi_DMA_Write_Bit; - ni_tio_set_bits(counter, NITIO_DMA_CFG_REG(cidx), - Gi_DMA_Enable_Bit | Gi_DMA_Int_Bit | - Gi_DMA_Write_Bit, gi_dma_config_bits); - } + mask = GI_DMA_ENABLE | GI_DMA_INT_ENA | GI_DMA_WRITE; + bits = 0; + + if (enable) + bits |= GI_DMA_ENABLE | GI_DMA_INT_ENA; + if (!read) + bits |= GI_DMA_WRITE; + ni_tio_set_bits(counter, NITIO_DMA_CFG_REG(cidx), mask, bits); break; } } @@ -94,9 +92,7 @@ static int ni_tio_input_inttrig(struct comedi_device *dev, struct ni_gpct *counter = s->private; struct comedi_cmd *cmd = &s->async->cmd; unsigned long flags; - int retval = 0; - - BUG_ON(counter == NULL); + int ret = 0; if (trig_num != cmd->start_src) return -EINVAL; @@ -105,14 +101,14 @@ static int ni_tio_input_inttrig(struct comedi_device *dev, if (counter->mite_chan) mite_dma_arm(counter->mite_chan); else - retval = -EIO; + ret = -EIO; spin_unlock_irqrestore(&counter->lock, flags); - if (retval < 0) - return retval; - retval = ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE); + if (ret < 0) + return ret; + ret = ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE); s->async->inttrig = NULL; - return retval; + return ret; } static int ni_tio_input_cmd(struct comedi_subdevice *s) @@ -122,7 +118,7 @@ static int ni_tio_input_cmd(struct comedi_subdevice *s) unsigned cidx = counter->counter_index; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; - int retval = 0; + int ret = 0; /* write alloc the entire buffer */ comedi_buf_write_alloc(s, async->prealloc_bufsz); @@ -139,31 +135,21 @@ static int ni_tio_input_cmd(struct comedi_subdevice *s) BUG(); break; } - ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), Gi_Save_Trace_Bit, 0); - ni_tio_configure_dma(counter, 1, 1); - switch (cmd->start_src) { - case TRIG_NOW: - async->inttrig = NULL; - mite_dma_arm(counter->mite_chan); - retval = ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE); - break; - case TRIG_INT: + ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), GI_SAVE_TRACE, 0); + ni_tio_configure_dma(counter, true, true); + + if (cmd->start_src == TRIG_INT) { async->inttrig = &ni_tio_input_inttrig; - break; - case TRIG_EXT: + } else { /* TRIG_NOW || TRIG_EXT || TRIG_OTHER */ async->inttrig = NULL; mite_dma_arm(counter->mite_chan); - retval = ni_tio_arm(counter, 1, cmd->start_arg); - break; - case TRIG_OTHER: - async->inttrig = NULL; - mite_dma_arm(counter->mite_chan); - break; - default: - BUG(); - break; + + if (cmd->start_src == TRIG_NOW) + ret = ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE); + else if (cmd->start_src == TRIG_EXT) + ret = ni_tio_arm(counter, 1, cmd->start_arg); } - return retval; + return ret; } static int ni_tio_output_cmd(struct comedi_subdevice *s) @@ -176,7 +162,7 @@ static int ni_tio_output_cmd(struct comedi_subdevice *s) counter->mite_chan->dir = COMEDI_OUTPUT; mite_prep_dma(counter->mite_chan, 32, 32); - ni_tio_configure_dma(counter, 1, 0); + ni_tio_configure_dma(counter, true, false); mite_dma_arm(counter->mite_chan); return ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE); } @@ -201,8 +187,8 @@ static int ni_tio_cmd_setup(struct comedi_subdevice *s) retval = ni_tio_set_gate_src(counter, 0, gate_source); if (cmd->flags & TRIG_WAKE_EOS) { ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx), - Gi_Gate_Interrupt_Enable_Bit(cidx), - Gi_Gate_Interrupt_Enable_Bit(cidx)); + GI_GATE_INTERRUPT_ENABLE(cidx), + GI_GATE_INTERRUPT_ENABLE(cidx)); } return retval; } @@ -319,10 +305,10 @@ int ni_tio_cancel(struct ni_gpct *counter) if (counter->mite_chan) mite_dma_disarm(counter->mite_chan); spin_unlock_irqrestore(&counter->lock, flags); - ni_tio_configure_dma(counter, 0, 0); + ni_tio_configure_dma(counter, false, false); ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx), - Gi_Gate_Interrupt_Enable_Bit(cidx), 0x0); + GI_GATE_INTERRUPT_ENABLE(cidx), 0x0); return 0; } EXPORT_SYMBOL_GPL(ni_tio_cancel); @@ -342,7 +328,6 @@ static int should_ack_gate(struct ni_gpct *counter) in register-level manual) */ case ni_gpct_variant_660x: return 1; - break; case ni_gpct_variant_e_series: spin_lock_irqsave(&counter->lock, flags); { @@ -358,9 +343,11 @@ static int should_ack_gate(struct ni_gpct *counter) return retval; } -void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, int *gate_error, - int *tc_error, int *perm_stale_data, - int *stale_data) +static void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, + int *gate_error, + int *tc_error, + int *perm_stale_data, + int *stale_data) { unsigned cidx = counter->counter_index; const unsigned short gxx_status = read_register(counter, @@ -378,8 +365,8 @@ void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, int *gate_error, if (stale_data) *stale_data = 0; - if (gxx_status & Gi_Gate_Error_Bit(cidx)) { - ack |= Gi_Gate_Error_Confirm_Bit(cidx); + if (gxx_status & GI_GATE_ERROR(cidx)) { + ack |= GI_GATE_ERROR_CONFIRM(cidx); if (gate_error) { /*660x don't support automatic acknowledgement of gate interrupt via dma read/write @@ -390,27 +377,27 @@ void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, int *gate_error, } } } - if (gxx_status & Gi_TC_Error_Bit(cidx)) { - ack |= Gi_TC_Error_Confirm_Bit(cidx); + if (gxx_status & GI_TC_ERROR(cidx)) { + ack |= GI_TC_ERROR_CONFIRM(cidx); if (tc_error) *tc_error = 1; } - if (gi_status & Gi_TC_Bit) - ack |= Gi_TC_Interrupt_Ack_Bit; - if (gi_status & Gi_Gate_Interrupt_Bit) { + if (gi_status & GI_TC) + ack |= GI_TC_INTERRUPT_ACK; + if (gi_status & GI_GATE_INTERRUPT) { if (should_ack_gate(counter)) - ack |= Gi_Gate_Interrupt_Ack_Bit; + ack |= GI_GATE_INTERRUPT_ACK; } if (ack) write_register(counter, ack, NITIO_INT_ACK_REG(cidx)); if (ni_tio_get_soft_copy(counter, NITIO_MODE_REG(cidx)) & - Gi_Loading_On_Gate_Bit) { - if (gxx_status & Gi_Stale_Data_Bit(cidx)) { + GI_LOADING_ON_GATE) { + if (gxx_status & GI_STALE_DATA(cidx)) { if (stale_data) *stale_data = 1; } if (read_register(counter, NITIO_STATUS2_REG(cidx)) & - Gi_Permanent_Stale_Bit(cidx)) { + GI_PERMANENT_STALE(cidx)) { dev_info(counter->counter_dev->dev->class_dev, "%s: Gi_Permanent_Stale_Data detected.\n", __func__); @@ -419,7 +406,12 @@ void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, int *gate_error, } } } -EXPORT_SYMBOL_GPL(ni_tio_acknowledge_and_confirm); + +void ni_tio_acknowledge(struct ni_gpct *counter) +{ + ni_tio_acknowledge_and_confirm(counter, NULL, NULL, NULL, NULL); +} +EXPORT_SYMBOL_GPL(ni_tio_acknowledge); void ni_tio_handle_interrupt(struct ni_gpct *counter, struct comedi_subdevice *s) @@ -444,7 +436,7 @@ void ni_tio_handle_interrupt(struct ni_gpct *counter, case ni_gpct_variant_m_series: case ni_gpct_variant_660x: if (read_register(counter, NITIO_DMA_STATUS_REG(cidx)) & - Gi_DRQ_Error_Bit) { + GI_DRQ_ERROR) { dev_notice(counter->counter_dev->dev->class_dev, "%s: Gi_DRQ_Error detected.\n", __func__); s->async->events |= COMEDI_CB_OVERFLOW; diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index c38d97a9a899..40f9136f0bb6 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -206,7 +206,7 @@ static irqreturn_t pcl711_interrupt(int irq, void *d) unsigned int data; if (!dev->attached) { - comedi_error(dev, "spurious interrupt"); + dev_err(dev->class_dev, "spurious interrupt\n"); return IRQ_HANDLED; } diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c index 8af13e790ad1..c7f8eb1cf8de 100644 --- a/drivers/staging/comedi/drivers/pcl724.c +++ b/drivers/staging/comedi/drivers/pcl724.c @@ -15,6 +15,7 @@ * (ADLink) ACL-7124 [acl7124] * (ADLink) PET-48DIO [pet48dio] * (WinSystems) PCM-IO48 [pcmio48] + * (Diamond Systems) ONYX-MM-DIO [onyx-mm-dio] * Author: Michal Dobes <dobes@tesnet.cz> * Status: untested * @@ -73,6 +74,10 @@ static const struct pcl724_board boardtypes[] = { .name = "pcmio48", .io_range = 0x08, .numofports = 2, /* 48 DIO channels */ + }, { + .name = "onyx-mm-dio", + .io_range = 0x10, + .numofports = 2, /* 48 DIO channels */ }, }; @@ -83,14 +88,12 @@ static int pcl724_8255mapped_io(int dir, int port, int data, iobase &= 0x0fff; + outb(port + movport, iobase); if (dir) { - outb(port + movport, iobase); outb(data, iobase + 1); return 0; - } else { - outb(port + movport, iobase); - return inb(iobase + 1); } + return inb(iobase + 1); } static int pcl724_attach(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c index 7fb044ce399b..bdce24c42940 100644 --- a/drivers/staging/comedi/drivers/pcl730.c +++ b/drivers/staging/comedi/drivers/pcl730.c @@ -19,6 +19,7 @@ * (Advantech) PCL-734 [pcl734] * (Diamond Systems) OPMM-1616-XT [opmm-1616-xt] * (Diamond Systems) PEARL-MM-P [prearl-mm-p] + * (Diamond Systems) IR104-PBF [ir104-pbf] * Author: José Luis Sánchez (jsanchezv@teleline.es) * Status: untested * @@ -93,6 +94,15 @@ * * BASE+0 Isolated outputs 0-7 (write) * BASE+1 Isolated outputs 8-15 (write) + * + * The ir104-pbf board has this register mapping: + * + * BASE+0 Isolated outputs 0-7 (write) (read back) + * BASE+1 Isolated outputs 8-15 (write) (read back) + * BASE+2 Isolated outputs 16-19 (write) (read back) + * BASE+4 Isolated inputs 0-7 (read) + * BASE+5 Isolated inputs 8-15 (read) + * BASE+6 Isolated inputs 16-19 (read) */ struct pcl730_board { @@ -100,6 +110,7 @@ struct pcl730_board { unsigned int io_range; unsigned is_pcl725:1; unsigned is_acl7225b:1; + unsigned is_ir104:1; unsigned has_readback:1; unsigned has_ttl_io:1; int n_subdevs; @@ -194,6 +205,13 @@ static const struct pcl730_board pcl730_boards[] = { .io_range = 0x02, .n_subdevs = 1, .n_iso_out_chan = 16, + }, { + .name = "ir104-pbf", + .io_range = 0x08, + .is_ir104 = 1, + .has_readback = 1, + .n_iso_out_chan = 20, + .n_iso_in_chan = 20, }, }; @@ -292,7 +310,8 @@ static int pcl730_attach(struct comedi_device *dev, s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = pcl730_di_insn_bits; - s->private = board->is_acl7225b ? (void *)2 : + s->private = board->is_ir104 ? (void *)4 : + board->is_acl7225b ? (void *)2 : board->is_pcl725 ? (void *)1 : (void *)0; } diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 4c1b94706478..803e7790538c 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -985,7 +985,7 @@ static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) spin_unlock_irqrestore(&dev->spinlock, flags); - return s->async->buf_write_count - s->async->buf_read_count; + return comedi_buf_n_bytes_ready(s); } static int pcl812_ai_cancel(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index d9ca7fe16c96..54732c5cab97 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -130,10 +130,6 @@ struct pcl816_private { unsigned int ai_cmd_canceled:1; }; -static int check_channel_list(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int *chanlist, unsigned int chanlen); - static void pcl816_start_pacer(struct comedi_device *dev, bool load_counters) { struct pcl816_private *devpriv = dev->private; @@ -363,6 +359,62 @@ static irqreturn_t pcl816_interrupt(int irq, void *d) return IRQ_HANDLED; } +static int check_channel_list(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int *chanlist, + unsigned int chanlen) +{ + unsigned int chansegment[16]; + unsigned int i, nowmustbechan, seglen, segpos; + + /* correct channel and range number check itself comedi/range.c */ + if (chanlen < 1) { + dev_err(dev->class_dev, "range/channel list is empty!\n"); + return 0; + } + + if (chanlen > 1) { + /* first channel is every time ok */ + 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]) + break; + nowmustbechan = + (CR_CHAN(chansegment[i - 1]) + 1) % chanlen; + if (nowmustbechan != CR_CHAN(chanlist[i])) { + /* channel list isn't continuous :-( */ + dev_dbg(dev->class_dev, + "channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n", + i, CR_CHAN(chanlist[i]), nowmustbechan, + CR_CHAN(chanlist[0])); + return 0; + } + /* well, this is next correct channel in list */ + chansegment[i] = chanlist[i]; + } + + /* check whole chanlist */ + for (i = 0, segpos = 0; i < chanlen; i++) { + 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]), + CR_RANGE(chansegment[i]), + CR_AREF(chansegment[i]), + CR_CHAN(chanlist[i % seglen]), + CR_RANGE(chanlist[i % seglen]), + CR_AREF(chansegment[i % seglen])); + return 0; /* chan/gain list is strange */ + } + } + } else { + seglen = 1; + } + + return seglen; /* we can serve this with MUX logic */ +} + static int pcl816_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { @@ -516,7 +568,7 @@ static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) cfc_handle_events(dev, s); - return s->async->buf_write_count - s->async->buf_read_count; + return comedi_buf_n_bytes_ready(s); } static int pcl816_ai_cancel(struct comedi_device *dev, @@ -542,62 +594,6 @@ static int pcl816_ai_cancel(struct comedi_device *dev, return 0; } -static int -check_channel_list(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned int *chanlist, - unsigned int chanlen) -{ - unsigned int chansegment[16]; - unsigned int i, nowmustbechan, seglen, segpos; - - /* correct channel and range number check itself comedi/range.c */ - if (chanlen < 1) { - comedi_error(dev, "range/channel list is empty!"); - return 0; - } - - if (chanlen > 1) { - /* first channel is every time ok */ - 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]) - break; - nowmustbechan = - (CR_CHAN(chansegment[i - 1]) + 1) % chanlen; - if (nowmustbechan != CR_CHAN(chanlist[i])) { - /* channel list isn't continuous :-( */ - dev_dbg(dev->class_dev, - "channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n", - i, CR_CHAN(chanlist[i]), nowmustbechan, - CR_CHAN(chanlist[0])); - return 0; - } - /* well, this is next correct channel in list */ - chansegment[i] = chanlist[i]; - } - - /* check whole chanlist */ - for (i = 0, segpos = 0; i < chanlen; i++) { - 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]), - CR_RANGE(chansegment[i]), - CR_AREF(chansegment[i]), - CR_CHAN(chanlist[i % seglen]), - CR_RANGE(chanlist[i % seglen]), - CR_AREF(chansegment[i % seglen])); - return 0; /* chan/gain list is strange */ - } - } - } else { - seglen = 1; - } - - return seglen; /* we can serve this with MUX logic */ -} - static int pcl816_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 7d00ae639d38..000dbf841e45 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -551,7 +551,7 @@ static void pcl818_handle_eoc(struct comedi_device *dev, unsigned int val; if (pcl818_ai_eoc(dev, s, NULL, 0)) { - comedi_error(dev, "A/D mode1/3 IRQ without DRDY!"); + dev_err(dev->class_dev, "A/D mode1/3 IRQ without DRDY!\n"); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; return; } @@ -608,13 +608,14 @@ static void pcl818_handle_fifo(struct comedi_device *dev, status = inb(dev->iobase + PCL818_FI_STATUS); if (status & 4) { - comedi_error(dev, "A/D mode1/3 FIFO overflow!"); + dev_err(dev->class_dev, "A/D mode1/3 FIFO overflow!\n"); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; return; } if (status & 1) { - comedi_error(dev, "A/D mode1/3 FIFO interrupt without data!"); + dev_err(dev->class_dev, + "A/D mode1/3 FIFO interrupt without data!\n"); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; return; } @@ -682,7 +683,7 @@ static int check_channel_list(struct comedi_device *dev, /* correct channel and range number check itself comedi/range.c */ if (n_chan < 1) { - comedi_error(dev, "range/channel list is empty!"); + dev_err(dev->class_dev, "range/channel list is empty!\n"); return 0; } diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c index 53e73737a906..6e0d78f6095b 100644 --- a/drivers/staging/comedi/drivers/pcm3724.c +++ b/drivers/staging/comedi/drivers/pcm3724.c @@ -33,7 +33,6 @@ Copy/pasted/hacked from pcm724.c #include "8255.h" -#define PCM3724_SIZE 16 #define SIZE_8255 4 #define BUF_C0 0x1 @@ -66,19 +65,6 @@ struct priv_pcm3724 { int dio_2; }; -static int subdev_8255_cb(int dir, int port, int data, unsigned long arg) -{ - unsigned long iobase = arg; - unsigned char inbres; - if (dir) { - outb(data, iobase + port); - return 0; - } else { - inbres = inb(iobase + port); - return inbres; - } -} - static int compute_buffer(int config, int devno, struct comedi_subdevice *s) { /* 1 in io_bits indicates output */ @@ -215,7 +201,7 @@ static int pcm3724_attach(struct comedi_device *dev, if (!priv) return -ENOMEM; - ret = comedi_request_region(dev, it->options[0], PCM3724_SIZE); + ret = comedi_request_region(dev, it->options[0], 0x10); if (ret) return ret; @@ -225,7 +211,7 @@ static int pcm3724_attach(struct comedi_device *dev, for (i = 0; i < dev->n_subdevices; i++) { s = &dev->subdevices[i]; - ret = subdev_8255_init(dev, s, subdev_8255_cb, + ret = subdev_8255_init(dev, s, NULL, dev->iobase + SIZE_8255 * i); if (ret) return ret; diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 62914bb342d2..1bca3fba0950 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -333,6 +333,7 @@ static void pcmuio_handle_intr_subdev(struct comedi_device *dev, for (i = 0; i < cmd->chanlist_len; i++) { unsigned int chan = CR_CHAN(cmd->chanlist[i]); + if (triggered & (1 << chan)) val |= (1 << i); } diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index b3bbec0a0d23..b1db61d9d834 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -351,7 +351,7 @@ static int daqp_ai_insn_read(struct comedi_device *dev, * time that the device will use. */ -static int daqp_ns_to_timer(unsigned int *ns, int round) +static int daqp_ns_to_timer(unsigned int *ns, unsigned int flags) { int timer; @@ -436,13 +436,13 @@ static int daqp_ai_cmdtest(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER) { arg = cmd->scan_begin_arg; - daqp_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + daqp_ns_to_timer(&arg, cmd->flags); err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (cmd->convert_src == TRIG_TIMER) { arg = cmd->convert_arg; - daqp_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + daqp_ns_to_timer(&arg, cmd->flags); err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); } @@ -488,15 +488,13 @@ static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) */ if (cmd->convert_src == TRIG_TIMER) { - counter = daqp_ns_to_timer(&cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); + 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); scanlist_start_on_every_entry = 1; } else { - counter = daqp_ns_to_timer(&cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); + 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); diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index d55c5893203b..6fc4ed33f66c 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -373,7 +373,6 @@ static const struct rtd_boardinfo rtd520Boards[] = { struct rtd_private { /* memory mapped board structures */ - void __iomem *las0; void __iomem *las1; void __iomem *lcfg; @@ -397,11 +396,11 @@ struct rtd_private { Note: you have to check if the value is larger than the counter range! */ static int rtd_ns_to_timer_base(unsigned int *nanosec, - int round_mode, int base) + unsigned int flags, int base) { int divider; - switch (round_mode) { + switch (flags & TRIG_ROUND_MASK) { case TRIG_ROUND_NEAREST: default: divider = (*nanosec + base / 2) / base; @@ -428,9 +427,9 @@ static int rtd_ns_to_timer_base(unsigned int *nanosec, 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, int round_mode) +static int rtd_ns_to_timer(unsigned int *ns, unsigned int flags) { - return rtd_ns_to_timer_base(ns, round_mode, RTD_CLOCK_BASE); + return rtd_ns_to_timer_base(ns, flags, RTD_CLOCK_BASE); } /* @@ -490,21 +489,19 @@ static unsigned short rtd_convert_chan_gain(struct comedi_device *dev, static void rtd_load_channelgain_list(struct comedi_device *dev, unsigned int n_chan, unsigned int *list) { - struct rtd_private *devpriv = dev->private; - if (n_chan > 1) { /* setup channel gain table */ int ii; - writel(0, devpriv->las0 + LAS0_CGT_CLEAR); - writel(1, devpriv->las0 + LAS0_CGT_ENABLE); + writel(0, dev->mmio + LAS0_CGT_CLEAR); + writel(1, dev->mmio + LAS0_CGT_ENABLE); for (ii = 0; ii < n_chan; ii++) { writel(rtd_convert_chan_gain(dev, list[ii], ii), - devpriv->las0 + LAS0_CGT_WRITE); + dev->mmio + LAS0_CGT_WRITE); } } else { /* just use the channel gain latch */ - writel(0, devpriv->las0 + LAS0_CGT_ENABLE); + writel(0, dev->mmio + LAS0_CGT_ENABLE); writel(rtd_convert_chan_gain(dev, list[0], 0), - devpriv->las0 + LAS0_CGL_WRITE); + dev->mmio + LAS0_CGL_WRITE); } } @@ -512,23 +509,22 @@ static void rtd_load_channelgain_list(struct comedi_device *dev, empty status flag clears */ static int rtd520_probe_fifo_depth(struct comedi_device *dev) { - struct rtd_private *devpriv = dev->private; unsigned int chanspec = CR_PACK(0, 0, AREF_GROUND); unsigned i; static const unsigned limit = 0x2000; unsigned fifo_size = 0; - writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR); + writel(0, dev->mmio + LAS0_ADC_FIFO_CLEAR); rtd_load_channelgain_list(dev, 1, &chanspec); /* ADC conversion trigger source: SOFTWARE */ - writel(0, devpriv->las0 + LAS0_ADC_CONVERSION); + writel(0, dev->mmio + LAS0_ADC_CONVERSION); /* convert samples */ for (i = 0; i < limit; ++i) { unsigned fifo_status; /* trigger conversion */ - writew(0, devpriv->las0 + LAS0_ADC); + writew(0, dev->mmio + LAS0_ADC); udelay(1); - fifo_status = readl(devpriv->las0 + LAS0_ADC); + fifo_status = readl(dev->mmio + LAS0_ADC); if ((fifo_status & FS_ADC_HEMPTY) == 0) { fifo_size = 2 * i; break; @@ -538,7 +534,7 @@ static int rtd520_probe_fifo_depth(struct comedi_device *dev) dev_info(dev->class_dev, "failed to probe fifo size.\n"); return -EIO; } - writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR); + writel(0, dev->mmio + LAS0_ADC_FIFO_CLEAR); if (fifo_size != 0x400 && fifo_size != 0x2000) { dev_info(dev->class_dev, "unexpected fifo size of %i, expected 1024 or 8192.\n", @@ -553,10 +549,9 @@ static int rtd_ai_eoc(struct comedi_device *dev, struct comedi_insn *insn, unsigned long context) { - struct rtd_private *devpriv = dev->private; unsigned int status; - status = readl(devpriv->las0 + LAS0_ADC); + status = readl(dev->mmio + LAS0_ADC); if (status & FS_ADC_NOT_EMPTY) return 0; return -EBUSY; @@ -571,19 +566,19 @@ static int rtd_ai_rinsn(struct comedi_device *dev, int n; /* clear any old fifo data */ - writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR); + writel(0, dev->mmio + LAS0_ADC_FIFO_CLEAR); /* write channel to multiplexer and clear channel gain table */ rtd_load_channelgain_list(dev, 1, &insn->chanspec); /* ADC conversion trigger source: SOFTWARE */ - writel(0, devpriv->las0 + LAS0_ADC_CONVERSION); + writel(0, dev->mmio + LAS0_ADC_CONVERSION); /* convert n samples */ for (n = 0; n < insn->n; n++) { unsigned short d; /* trigger conversion */ - writew(0, devpriv->las0 + LAS0_ADC); + writew(0, dev->mmio + LAS0_ADC); ret = comedi_timeout(dev, s, insn, rtd_ai_eoc, 0); if (ret) @@ -645,7 +640,7 @@ static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s) { struct rtd_private *devpriv = dev->private; - while (readl(devpriv->las0 + LAS0_ADC) & FS_ADC_NOT_EMPTY) { + while (readl(dev->mmio + LAS0_ADC) & FS_ADC_NOT_EMPTY) { unsigned short d = readw(devpriv->las1 + LAS1_ADC_FIFO); if (0 == devpriv->ai_count) { /* done */ @@ -685,12 +680,12 @@ static irqreturn_t rtd_interrupt(int irq, void *d) if (!dev->attached) return IRQ_NONE; - fifo_status = readl(devpriv->las0 + LAS0_ADC); + fifo_status = readl(dev->mmio + LAS0_ADC); /* check for FIFO full, this automatically halts the ADC! */ if (!(fifo_status & FS_ADC_NOT_FULL)) /* 0 -> full */ goto xfer_abort; - status = readw(devpriv->las0 + LAS0_IT); + status = readw(dev->mmio + LAS0_IT); /* if interrupt was not caused by our board, or handled above */ if (0 == status) return IRQ_HANDLED; @@ -725,30 +720,30 @@ static irqreturn_t rtd_interrupt(int irq, void *d) } } - overrun = readl(devpriv->las0 + LAS0_OVERRUN) & 0xffff; + overrun = readl(dev->mmio + LAS0_OVERRUN) & 0xffff; if (overrun) goto xfer_abort; /* clear the interrupt */ - writew(status, devpriv->las0 + LAS0_CLEAR); - readw(devpriv->las0 + LAS0_CLEAR); + writew(status, dev->mmio + LAS0_CLEAR); + readw(dev->mmio + LAS0_CLEAR); return IRQ_HANDLED; xfer_abort: - writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR); + writel(0, dev->mmio + LAS0_ADC_FIFO_CLEAR); s->async->events |= COMEDI_CB_ERROR; devpriv->ai_count = 0; /* stop and don't transfer any more */ /* fall into xfer_done */ xfer_done: /* pacer stop source: SOFTWARE */ - writel(0, devpriv->las0 + LAS0_PACER_STOP); - writel(0, devpriv->las0 + LAS0_PACER); /* stop pacer */ - writel(0, devpriv->las0 + LAS0_ADC_CONVERSION); - writew(0, devpriv->las0 + LAS0_IT); + writel(0, dev->mmio + LAS0_PACER_STOP); + writel(0, dev->mmio + LAS0_PACER); /* stop pacer */ + writel(0, dev->mmio + LAS0_ADC_CONVERSION); + writew(0, dev->mmio + LAS0_IT); if (devpriv->ai_count > 0) { /* there shouldn't be anything left */ - fifo_status = readl(devpriv->las0 + LAS0_ADC); + fifo_status = readl(dev->mmio + LAS0_ADC); ai_read_dregs(dev, s); /* read anything left in FIFO */ } @@ -756,12 +751,12 @@ xfer_done: comedi_event(dev, s); /* clear the interrupt */ - status = readw(devpriv->las0 + LAS0_IT); - writew(status, devpriv->las0 + LAS0_CLEAR); - readw(devpriv->las0 + LAS0_CLEAR); + status = readw(dev->mmio + LAS0_IT); + writew(status, dev->mmio + LAS0_CLEAR); + readw(dev->mmio + LAS0_CLEAR); - fifo_status = readl(devpriv->las0 + LAS0_ADC); - overrun = readl(devpriv->las0 + LAS0_OVERRUN) & 0xffff; + fifo_status = readl(dev->mmio + LAS0_ADC); + overrun = readl(dev->mmio + LAS0_OVERRUN) & 0xffff; return IRQ_HANDLED; } @@ -895,13 +890,13 @@ static int rtd_ai_cmdtest(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER) { arg = cmd->scan_begin_arg; - rtd_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + rtd_ns_to_timer(&arg, cmd->flags); err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (cmd->convert_src == TRIG_TIMER) { arg = cmd->convert_arg; - rtd_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + rtd_ns_to_timer(&arg, cmd->flags); err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); if (cmd->scan_begin_src == TRIG_TIMER) { @@ -931,12 +926,12 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* stop anything currently running */ /* pacer stop source: SOFTWARE */ - writel(0, devpriv->las0 + LAS0_PACER_STOP); - writel(0, devpriv->las0 + LAS0_PACER); /* stop pacer */ - writel(0, devpriv->las0 + LAS0_ADC_CONVERSION); - writew(0, devpriv->las0 + LAS0_IT); - writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR); - writel(0, devpriv->las0 + LAS0_OVERRUN); + writel(0, dev->mmio + LAS0_PACER_STOP); + writel(0, dev->mmio + LAS0_PACER); /* stop pacer */ + writel(0, dev->mmio + LAS0_ADC_CONVERSION); + writew(0, dev->mmio + LAS0_IT); + writel(0, dev->mmio + LAS0_ADC_FIFO_CLEAR); + writel(0, dev->mmio + LAS0_OVERRUN); /* start configuration */ /* load channel list and reset CGT */ @@ -945,18 +940,18 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* setup the common case and override if needed */ if (cmd->chanlist_len > 1) { /* pacer start source: SOFTWARE */ - writel(0, devpriv->las0 + LAS0_PACER_START); + writel(0, dev->mmio + LAS0_PACER_START); /* burst trigger source: PACER */ - writel(1, devpriv->las0 + LAS0_BURST_START); + writel(1, dev->mmio + LAS0_BURST_START); /* ADC conversion trigger source: BURST */ - writel(2, devpriv->las0 + LAS0_ADC_CONVERSION); + writel(2, dev->mmio + LAS0_ADC_CONVERSION); } else { /* single channel */ /* pacer start source: SOFTWARE */ - writel(0, devpriv->las0 + LAS0_PACER_START); + writel(0, dev->mmio + LAS0_PACER_START); /* ADC conversion trigger source: PACER */ - writel(1, devpriv->las0 + LAS0_ADC_CONVERSION); + writel(1, dev->mmio + LAS0_ADC_CONVERSION); } - writel((devpriv->fifosz / 2 - 1) & 0xffff, devpriv->las0 + LAS0_ACNT); + writel((devpriv->fifosz / 2 - 1) & 0xffff, dev->mmio + LAS0_ACNT); if (TRIG_TIMER == cmd->scan_begin_src) { /* scan_begin_arg is in nanoseconds */ @@ -993,16 +988,16 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } else { /* interrupt for each transfer */ writel((devpriv->xfer_count - 1) & 0xffff, - devpriv->las0 + LAS0_ACNT); + dev->mmio + LAS0_ACNT); } } else { /* unknown timing, just use 1/2 FIFO */ devpriv->xfer_count = 0; devpriv->flags &= ~SEND_EOS; } /* pacer clock source: INTERNAL 8MHz */ - writel(1, devpriv->las0 + LAS0_PACER_SELECT); + writel(1, dev->mmio + LAS0_PACER_SELECT); /* just interrupt, don't stop */ - writel(1, devpriv->las0 + LAS0_ACNT_STOP_ENABLE); + writel(1, dev->mmio + LAS0_ACNT_STOP_ENABLE); /* BUG??? these look like enumerated values, but they are bit fields */ @@ -1027,13 +1022,13 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) timer = rtd_ns_to_timer(&cmd->scan_begin_arg, TRIG_ROUND_NEAREST); /* set PACER clock */ - writel(timer & 0xffffff, devpriv->las0 + LAS0_PCLK); + writel(timer & 0xffffff, dev->mmio + LAS0_PCLK); break; case TRIG_EXT: /* pacer start source: EXTERNAL */ - writel(1, devpriv->las0 + LAS0_PACER_START); + writel(1, dev->mmio + LAS0_PACER_START); break; } @@ -1045,33 +1040,32 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) timer = rtd_ns_to_timer(&cmd->convert_arg, TRIG_ROUND_NEAREST); /* setup BURST clock */ - writel(timer & 0x3ff, devpriv->las0 + LAS0_BCLK); + writel(timer & 0x3ff, dev->mmio + LAS0_BCLK); } break; case TRIG_EXT: /* external */ /* burst trigger source: EXTERNAL */ - writel(2, devpriv->las0 + LAS0_BURST_START); + writel(2, dev->mmio + LAS0_BURST_START); break; } /* end configuration */ /* This doesn't seem to work. There is no way to clear an interrupt that the priority controller has queued! */ - writew(~0, devpriv->las0 + LAS0_CLEAR); - readw(devpriv->las0 + LAS0_CLEAR); + writew(~0, dev->mmio + LAS0_CLEAR); + readw(dev->mmio + LAS0_CLEAR); /* TODO: allow multiple interrupt sources */ - if (devpriv->xfer_count > 0) { /* transfer every N samples */ - writew(IRQM_ADC_ABOUT_CNT, devpriv->las0 + LAS0_IT); - } else { /* 1/2 FIFO transfers */ - writew(IRQM_ADC_ABOUT_CNT, devpriv->las0 + LAS0_IT); - } + if (devpriv->xfer_count > 0) /* transfer every N samples */ + writew(IRQM_ADC_ABOUT_CNT, dev->mmio + LAS0_IT); + else /* 1/2 FIFO transfers */ + writew(IRQM_ADC_ABOUT_CNT, dev->mmio + LAS0_IT); /* BUG: start_src is ASSUMED to be TRIG_NOW */ /* BUG? it seems like things are running before the "start" */ - readl(devpriv->las0 + LAS0_PACER); /* start pacer */ + readl(dev->mmio + LAS0_PACER); /* start pacer */ return 0; } @@ -1085,13 +1079,13 @@ static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) u16 status; /* pacer stop source: SOFTWARE */ - writel(0, devpriv->las0 + LAS0_PACER_STOP); - writel(0, devpriv->las0 + LAS0_PACER); /* stop pacer */ - writel(0, devpriv->las0 + LAS0_ADC_CONVERSION); - writew(0, devpriv->las0 + LAS0_IT); + writel(0, dev->mmio + LAS0_PACER_STOP); + writel(0, dev->mmio + LAS0_PACER); /* stop pacer */ + writel(0, dev->mmio + LAS0_ADC_CONVERSION); + writew(0, dev->mmio + LAS0_IT); devpriv->ai_count = 0; /* stop and don't transfer any more */ - status = readw(devpriv->las0 + LAS0_IT); - overrun = readl(devpriv->las0 + LAS0_OVERRUN) & 0xffff; + status = readw(dev->mmio + LAS0_IT); + overrun = readl(dev->mmio + LAS0_OVERRUN) & 0xffff; return 0; } @@ -1100,12 +1094,11 @@ static int rtd_ao_eoc(struct comedi_device *dev, struct comedi_insn *insn, unsigned long context) { - struct rtd_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); unsigned int bit = (chan == 0) ? FS_DAC1_NOT_EMPTY : FS_DAC2_NOT_EMPTY; unsigned int status; - status = readl(devpriv->las0 + LAS0_ADC); + status = readl(dev->mmio + LAS0_ADC); if (status & bit) return 0; return -EBUSY; @@ -1122,8 +1115,8 @@ static int rtd_ao_winsn(struct comedi_device *dev, int ret; /* Configure the output range (table index matches the range values) */ - writew(range & 7, devpriv->las0 + - ((chan == 0) ? LAS0_DAC1_CTRL : LAS0_DAC2_CTRL)); + writew(range & 7, + dev->mmio + ((chan == 0) ? LAS0_DAC1_CTRL : LAS0_DAC2_CTRL)); /* Writing a list of values to an AO channel is probably not * very useful, but that's how the interface is defined. */ @@ -1143,8 +1136,7 @@ static int rtd_ao_winsn(struct comedi_device *dev, /* a typical programming sequence */ writew(val, devpriv->las1 + ((chan == 0) ? LAS1_DAC1_FIFO : LAS1_DAC2_FIFO)); - writew(0, devpriv->las0 + - ((chan == 0) ? LAS0_DAC1 : LAS0_DAC2)); + writew(0, dev->mmio + ((chan == 0) ? LAS0_DAC1 : LAS0_DAC2)); devpriv->ao_readback[chan] = data[i]; @@ -1179,12 +1171,10 @@ static int rtd_dio_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct rtd_private *devpriv = dev->private; - if (comedi_dio_update_state(s, data)) - writew(s->state & 0xff, devpriv->las0 + LAS0_DIO0); + writew(s->state & 0xff, dev->mmio + LAS0_DIO0); - data[1] = readw(devpriv->las0 + LAS0_DIO0) & 0xff; + data[1] = readw(dev->mmio + LAS0_DIO0) & 0xff; return insn->n; } @@ -1194,7 +1184,6 @@ static int rtd_dio_insn_config(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct rtd_private *devpriv = dev->private; int ret; ret = comedi_dio_insn_config(dev, s, insn, data, 0); @@ -1204,11 +1193,11 @@ static int rtd_dio_insn_config(struct comedi_device *dev, /* TODO support digital match interrupts and strobes */ /* set direction */ - writew(0x01, devpriv->las0 + LAS0_DIO_STATUS); - writew(s->io_bits & 0xff, devpriv->las0 + LAS0_DIO0_CTRL); + writew(0x01, dev->mmio + LAS0_DIO_STATUS); + writew(s->io_bits & 0xff, dev->mmio + LAS0_DIO0_CTRL); /* clear interrupts */ - writew(0x00, devpriv->las0 + LAS0_DIO_STATUS); + writew(0x00, dev->mmio + LAS0_DIO_STATUS); /* port1 can only be all input or all output */ @@ -1221,12 +1210,12 @@ static void rtd_reset(struct comedi_device *dev) { struct rtd_private *devpriv = dev->private; - writel(0, devpriv->las0 + LAS0_BOARD_RESET); + writel(0, dev->mmio + LAS0_BOARD_RESET); udelay(100); /* needed? */ writel(0, devpriv->lcfg + PLX_INTRCS_REG); - writew(0, devpriv->las0 + LAS0_IT); - writew(~0, devpriv->las0 + LAS0_CLEAR); - readw(devpriv->las0 + LAS0_CLEAR); + writew(0, dev->mmio + LAS0_IT); + writew(~0, dev->mmio + LAS0_CLEAR); + readw(dev->mmio + LAS0_CLEAR); } /* @@ -1235,21 +1224,19 @@ static void rtd_reset(struct comedi_device *dev) */ static void rtd_init_board(struct comedi_device *dev) { - struct rtd_private *devpriv = dev->private; - rtd_reset(dev); - writel(0, devpriv->las0 + LAS0_OVERRUN); - writel(0, devpriv->las0 + LAS0_CGT_CLEAR); - writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR); - writel(0, devpriv->las0 + LAS0_DAC1_RESET); - writel(0, devpriv->las0 + LAS0_DAC2_RESET); + 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); /* clear digital IO fifo */ - writew(0, devpriv->las0 + LAS0_DIO_STATUS); - writeb((0 << 6) | 0x30, devpriv->las0 + LAS0_UTC_CTRL); - writeb((1 << 6) | 0x30, devpriv->las0 + LAS0_UTC_CTRL); - writeb((2 << 6) | 0x30, devpriv->las0 + LAS0_UTC_CTRL); - writeb((3 << 6) | 0x00, devpriv->las0 + LAS0_UTC_CTRL); + 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 ??? */ } @@ -1292,10 +1279,10 @@ static int rtd_auto_attach(struct comedi_device *dev, if (ret) return ret; - devpriv->las0 = pci_ioremap_bar(pcidev, 2); + dev->mmio = pci_ioremap_bar(pcidev, 2); devpriv->las1 = pci_ioremap_bar(pcidev, 3); devpriv->lcfg = pci_ioremap_bar(pcidev, 0); - if (!devpriv->las0 || !devpriv->las1 || !devpriv->lcfg) + if (!dev->mmio || !devpriv->las1 || !devpriv->lcfg) return -ENOMEM; rtd_pci_latency_quirk(dev, pcidev); @@ -1375,7 +1362,7 @@ static void rtd_detach(struct comedi_device *dev) if (devpriv) { /* Shut down any board ops by resetting it */ - if (devpriv->las0 && devpriv->lcfg) + if (dev->mmio && devpriv->lcfg) rtd_reset(dev); if (dev->irq) { writel(readl(devpriv->lcfg + PLX_INTRCS_REG) & @@ -1383,8 +1370,8 @@ static void rtd_detach(struct comedi_device *dev) devpriv->lcfg + PLX_INTRCS_REG); free_irq(dev->irq, dev); } - if (devpriv->las0) - iounmap(devpriv->las0); + if (dev->mmio) + iounmap(dev->mmio); if (devpriv->las1) iounmap(devpriv->las1); if (devpriv->lcfg) diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index bd447b2add7b..2b1db9783bd6 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -81,8 +81,6 @@ #define RTI800_9513A_CNTRL 0x0d #define RTI800_9513A_STATUS 0x0d -#define RTI800_IOSIZE 0x10 - static const struct comedi_lrange range_rti800_ai_10_bipolar = { 4, { BIP_RANGE(10), @@ -281,7 +279,7 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; int ret; - ret = comedi_request_region(dev, it->options[0], RTI800_IOSIZE); + ret = comedi_request_region(dev, it->options[0], 0x10); if (ret) return ret; diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index 85d2b7a3c125..83f7433c2452 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -40,13 +40,10 @@ comedi_config /dev/comedi0 s526 0x2C0,0x3 #include "../comedidev.h" #include <asm/byteorder.h> -#define S526_SIZE 64 - #define S526_START_AI_CONV 0 #define S526_AI_READ 0 /* Ports */ -#define S526_IOSIZE 0x40 #define S526_NUM_PORTS 27 /* registers */ @@ -345,7 +342,6 @@ static int s526_gpct_insn_config(struct comedi_device *dev, default: return -EINVAL; - break; } return insn->n; @@ -557,7 +553,7 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; int ret; - ret = comedi_request_region(dev, it->options[0], S526_IOSIZE); + ret = comedi_request_region(dev, it->options[0], 0x40); if (ret) return ret; diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 0838f8aa6951..080608a840ac 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -77,7 +77,6 @@ struct s626_buffer_dma { }; struct s626_private { - void __iomem *mmio; uint8_t ai_cmd_running; /* ai_cmd is running */ uint8_t ai_continuous; /* continuous acquisition */ int ai_sample_count; /* number of samples to acquire */ @@ -102,60 +101,9 @@ struct s626_private { unsigned int ao_readback[S626_DAC_CHANNELS]; }; -/* COUNTER OBJECT ------------------------------------------------ */ -struct s626_enc_info { - /* Pointers to functions that differ for A and B counters: */ - /* Return clock enable. */ - uint16_t (*get_enable)(struct comedi_device *dev, - const struct s626_enc_info *k); - /* Return interrupt source. */ - uint16_t (*get_int_src)(struct comedi_device *dev, - const struct s626_enc_info *k); - /* Return preload trigger source. */ - uint16_t (*get_load_trig)(struct comedi_device *dev, - const struct s626_enc_info *k); - /* Return standardized operating mode. */ - uint16_t (*get_mode)(struct comedi_device *dev, - const struct s626_enc_info *k); - /* Generate soft index strobe. */ - void (*pulse_index)(struct comedi_device *dev, - const struct s626_enc_info *k); - /* Program clock enable. */ - void (*set_enable)(struct comedi_device *dev, - const struct s626_enc_info *k, uint16_t enab); - /* Program interrupt source. */ - void (*set_int_src)(struct comedi_device *dev, - const struct s626_enc_info *k, uint16_t int_source); - /* Program preload trigger source. */ - void (*set_load_trig)(struct comedi_device *dev, - const struct s626_enc_info *k, uint16_t trig); - /* Program standardized operating mode. */ - void (*set_mode)(struct comedi_device *dev, - const struct s626_enc_info *k, uint16_t setup, - uint16_t disable_int_src); - /* Reset event capture flags. */ - void (*reset_cap_flags)(struct comedi_device *dev, - const struct s626_enc_info *k); - - uint16_t my_cra; /* address of CRA register */ - uint16_t my_crb; /* address of CRB register */ - uint16_t my_latch_lsw; /* address of Latch least-significant-word - * register */ - uint16_t my_event_bits[4]; /* bit translations for IntSrc -->RDMISC2 */ -}; - /* Counter overflow/index event flag masks for RDMISC2. */ #define S626_INDXMASK(C) (1 << (((C) > 2) ? ((C) * 2 - 1) : ((C) * 2 + 4))) #define S626_OVERMASK(C) (1 << (((C) > 2) ? ((C) * 2 + 5) : ((C) * 2 + 10))) -#define S626_EVBITS(C) { 0, S626_OVERMASK(C), S626_INDXMASK(C), \ - S626_OVERMASK(C) | S626_INDXMASK(C) } - -/* - * Translation table to map IntSrc into equivalent RDMISC2 event flag bits. - * static const uint16_t s626_event_bits[][4] = - * { S626_EVBITS(0), S626_EVBITS(1), S626_EVBITS(2), S626_EVBITS(3), - * S626_EVBITS(4), S626_EVBITS(5) }; - */ /* * Enable/disable a function or test status bit(s) that are accessed @@ -164,29 +112,25 @@ struct s626_enc_info { static void s626_mc_enable(struct comedi_device *dev, unsigned int cmd, unsigned int reg) { - struct s626_private *devpriv = dev->private; unsigned int val = (cmd << 16) | cmd; mmiowb(); - writel(val, devpriv->mmio + reg); + writel(val, dev->mmio + reg); } static void s626_mc_disable(struct comedi_device *dev, unsigned int cmd, unsigned int reg) { - struct s626_private *devpriv = dev->private; - - writel(cmd << 16 , devpriv->mmio + reg); + writel(cmd << 16 , dev->mmio + reg); mmiowb(); } static bool s626_mc_test(struct comedi_device *dev, unsigned int cmd, unsigned int reg) { - struct s626_private *devpriv = dev->private; unsigned int val; - val = readl(devpriv->mmio + reg); + val = readl(dev->mmio + reg); return (val & cmd) ? true : false; } @@ -208,7 +152,6 @@ static const struct comedi_lrange s626_range_table = { */ static void s626_debi_transfer(struct comedi_device *dev) { - struct s626_private *devpriv = dev->private; static const int timeout = 10000; int i; @@ -225,17 +168,17 @@ static void s626_debi_transfer(struct comedi_device *dev) udelay(1); } if (i == timeout) - comedi_error(dev, - "Timeout while uploading to DEBI control register."); + dev_err(dev->class_dev, + "Timeout while uploading to DEBI control register\n"); /* Wait until DEBI transfer is done */ for (i = 0; i < timeout; i++) { - if (!(readl(devpriv->mmio + S626_P_PSR) & S626_PSR_DEBI_S)) + if (!(readl(dev->mmio + S626_P_PSR) & S626_PSR_DEBI_S)) break; udelay(1); } if (i == timeout) - comedi_error(dev, "DEBI transfer timeout."); + dev_err(dev->class_dev, "DEBI transfer timeout\n"); } /* @@ -243,15 +186,13 @@ static void s626_debi_transfer(struct comedi_device *dev) */ static uint16_t s626_debi_read(struct comedi_device *dev, uint16_t addr) { - struct s626_private *devpriv = dev->private; - /* Set up DEBI control register value in shadow RAM */ - writel(S626_DEBI_CMD_RDWORD | addr, devpriv->mmio + S626_P_DEBICMD); + writel(S626_DEBI_CMD_RDWORD | addr, dev->mmio + S626_P_DEBICMD); /* Execute the DEBI transfer. */ s626_debi_transfer(dev); - return readl(devpriv->mmio + S626_P_DEBIAD); + return readl(dev->mmio + S626_P_DEBIAD); } /* @@ -260,11 +201,9 @@ static uint16_t s626_debi_read(struct comedi_device *dev, uint16_t addr) static void s626_debi_write(struct comedi_device *dev, uint16_t addr, uint16_t wdata) { - struct s626_private *devpriv = dev->private; - /* Set up DEBI control register value in shadow RAM */ - writel(S626_DEBI_CMD_WRWORD | addr, devpriv->mmio + S626_P_DEBICMD); - writel(wdata, devpriv->mmio + S626_P_DEBIAD); + writel(S626_DEBI_CMD_WRWORD | addr, dev->mmio + S626_P_DEBICMD); + writel(wdata, dev->mmio + S626_P_DEBIAD); /* Execute the DEBI transfer. */ s626_debi_transfer(dev); @@ -278,18 +217,17 @@ static void s626_debi_write(struct comedi_device *dev, uint16_t addr, static void s626_debi_replace(struct comedi_device *dev, unsigned int addr, unsigned int mask, unsigned int wdata) { - struct s626_private *devpriv = dev->private; unsigned int val; addr &= 0xffff; - writel(S626_DEBI_CMD_RDWORD | addr, devpriv->mmio + S626_P_DEBICMD); + writel(S626_DEBI_CMD_RDWORD | addr, dev->mmio + S626_P_DEBICMD); s626_debi_transfer(dev); - writel(S626_DEBI_CMD_WRWORD | addr, devpriv->mmio + S626_P_DEBICMD); - val = readl(devpriv->mmio + S626_P_DEBIAD); + writel(S626_DEBI_CMD_WRWORD | addr, dev->mmio + S626_P_DEBICMD); + val = readl(dev->mmio + S626_P_DEBIAD); val &= mask; val |= wdata; - writel(val & 0xffff, devpriv->mmio + S626_P_DEBIAD); + writel(val & 0xffff, dev->mmio + S626_P_DEBIAD); s626_debi_transfer(dev); } @@ -310,12 +248,11 @@ static int s626_i2c_handshake_eoc(struct comedi_device *dev, static int s626_i2c_handshake(struct comedi_device *dev, uint32_t val) { - struct s626_private *devpriv = dev->private; unsigned int ctrl; int ret; /* Write I2C command to I2C Transfer Control shadow register */ - writel(val, devpriv->mmio + S626_P_I2CCTRL); + writel(val, dev->mmio + S626_P_I2CCTRL); /* * Upload I2C shadow registers into working registers and @@ -328,7 +265,7 @@ static int s626_i2c_handshake(struct comedi_device *dev, uint32_t val) /* Wait until I2C bus transfer is finished or an error occurs */ do { - ctrl = readl(devpriv->mmio + S626_P_I2CCTRL); + ctrl = readl(dev->mmio + S626_P_I2CCTRL); } while ((ctrl & (S626_I2C_BUSY | S626_I2C_ERR)) == S626_I2C_BUSY); /* Return non-zero if I2C error occurred */ @@ -366,7 +303,7 @@ static uint8_t s626_i2c_read(struct comedi_device *dev, uint8_t addr) /* Abort function and declare error if handshake failed. */ return 0; - return (readl(devpriv->mmio + S626_P_I2CCTRL) >> 16) & 0xff; + return (readl(dev->mmio + S626_P_I2CCTRL) >> 16) & 0xff; } /* *********** DAC FUNCTIONS *********** */ @@ -391,27 +328,26 @@ static int s626_send_dac_eoc(struct comedi_device *dev, struct comedi_insn *insn, unsigned long context) { - struct s626_private *devpriv = dev->private; unsigned int status; switch (context) { case s626_send_dac_wait_not_mc1_a2out: - status = readl(devpriv->mmio + S626_P_MC1); + status = readl(dev->mmio + S626_P_MC1); if (!(status & S626_MC1_A2OUT)) return 0; break; case s626_send_dac_wait_ssr_af2_out: - status = readl(devpriv->mmio + S626_P_SSR); + status = readl(dev->mmio + S626_P_SSR); if (status & S626_SSR_AF2_OUT) return 0; break; case s626_send_dac_wait_fb_buffer2_msb_00: - status = readl(devpriv->mmio + S626_P_FB_BUFFER2); + status = readl(dev->mmio + S626_P_FB_BUFFER2); if (!(status & 0xff000000)) return 0; break; case s626_send_dac_wait_fb_buffer2_msb_ff: - status = readl(devpriv->mmio + S626_P_FB_BUFFER2); + status = readl(dev->mmio + S626_P_FB_BUFFER2); if (status & 0xff000000) return 0; break; @@ -448,7 +384,7 @@ static int s626_send_dac(struct comedi_device *dev, uint32_t val) /* TRANSFER OUTPUT DWORD VALUE INTO A2'S OUTPUT FIFO ---------------- */ /* Copy DAC setpoint value to DAC's output DMA buffer. */ - /* writel(val, devpriv->mmio + (uint32_t)devpriv->dac_wbuf); */ + /* writel(val, dev->mmio + (uint32_t)devpriv->dac_wbuf); */ *devpriv->dac_wbuf = val; /* @@ -466,7 +402,7 @@ static int s626_send_dac(struct comedi_device *dev, uint32_t val) * other FIFO underflow/overflow flags). When set, this flag * will indicate that we have emerged from slot 0. */ - writel(S626_ISR_AFOU, devpriv->mmio + S626_P_ISR); + writel(S626_ISR_AFOU, dev->mmio + S626_P_ISR); /* * Wait for the DMA transfer to finish so that there will be data @@ -478,7 +414,7 @@ static int s626_send_dac(struct comedi_device *dev, uint32_t val) ret = comedi_timeout(dev, NULL, NULL, s626_send_dac_eoc, s626_send_dac_wait_not_mc1_a2out); if (ret) { - comedi_error(dev, "DMA transfer timeout."); + dev_err(dev->class_dev, "DMA transfer timeout\n"); return ret; } @@ -491,7 +427,7 @@ static int s626_send_dac(struct comedi_device *dev, uint32_t val) * detection. */ writel(S626_XSD2 | S626_RSD3 | S626_SIB_A2, - devpriv->mmio + S626_VECTPORT(0)); + dev->mmio + S626_VECTPORT(0)); /* * Wait for slot 1 to execute to ensure that the Packet will be @@ -503,7 +439,8 @@ static int s626_send_dac(struct comedi_device *dev, uint32_t val) ret = comedi_timeout(dev, NULL, NULL, s626_send_dac_eoc, s626_send_dac_wait_ssr_af2_out); if (ret) { - comedi_error(dev, "TSL timeout waiting for slot 1 to execute."); + dev_err(dev->class_dev, + "TSL timeout waiting for slot 1 to execute\n"); return ret; } @@ -515,7 +452,7 @@ static int s626_send_dac(struct comedi_device *dev, uint32_t val) * buffer register. */ writel(S626_XSD2 | S626_XFIFO_2 | S626_RSD2 | S626_SIB_A2 | S626_EOS, - devpriv->mmio + S626_VECTPORT(0)); + dev->mmio + S626_VECTPORT(0)); /* WAIT FOR THE TRANSACTION TO FINISH ----------------------- */ @@ -537,7 +474,7 @@ static int s626_send_dac(struct comedi_device *dev, uint32_t val) * we test for the FB_BUFFER2 MSB contents to be equal to 0xFF. If * the TSL has not yet finished executing slot 5 ... */ - if (readl(devpriv->mmio + S626_P_FB_BUFFER2) & 0xff000000) { + if (readl(dev->mmio + S626_P_FB_BUFFER2) & 0xff000000) { /* * The trap was set on time and we are still executing somewhere * in slots 2-5, so we now wait for slot 0 to execute and trap @@ -548,8 +485,8 @@ static int s626_send_dac(struct comedi_device *dev, uint32_t val) ret = comedi_timeout(dev, NULL, NULL, s626_send_dac_eoc, s626_send_dac_wait_fb_buffer2_msb_00); if (ret) { - comedi_error(dev, - "TSL timeout waiting for slot 0 to execute."); + dev_err(dev->class_dev, + "TSL timeout waiting for slot 0 to execute\n"); return ret; } } @@ -563,7 +500,7 @@ static int s626_send_dac(struct comedi_device *dev, uint32_t val) * SD3, which is driven only by a pull-up resistor. */ writel(S626_RSD3 | S626_SIB_A2 | S626_EOS, - devpriv->mmio + S626_VECTPORT(0)); + dev->mmio + S626_VECTPORT(0)); /* * Wait for slot 0 to execute, at which time the TSL is setup for @@ -573,7 +510,8 @@ static int s626_send_dac(struct comedi_device *dev, uint32_t val) ret = comedi_timeout(dev, NULL, NULL, s626_send_dac_eoc, s626_send_dac_wait_fb_buffer2_msb_ff); if (ret) { - comedi_error(dev, "TSL timeout waiting for slot 0 to execute."); + dev_err(dev->class_dev, + "TSL timeout waiting for slot 0 to execute\n"); return ret; } return 0; @@ -620,16 +558,16 @@ static int s626_set_dac(struct comedi_device *dev, uint16_t chan, ws_image = (chan & 2) ? S626_WS1 : S626_WS2; /* Slot 2: Transmit high data byte to target DAC */ writel(S626_XSD2 | S626_XFIFO_1 | ws_image, - devpriv->mmio + S626_VECTPORT(2)); + dev->mmio + S626_VECTPORT(2)); /* Slot 3: Transmit low data byte to target DAC */ writel(S626_XSD2 | S626_XFIFO_0 | ws_image, - devpriv->mmio + S626_VECTPORT(3)); + dev->mmio + S626_VECTPORT(3)); /* Slot 4: Transmit to non-existent TrimDac channel to keep clock */ writel(S626_XSD2 | S626_XFIFO_3 | S626_WS3, - devpriv->mmio + S626_VECTPORT(4)); + dev->mmio + S626_VECTPORT(4)); /* Slot 5: running after writing target DAC's low data byte */ writel(S626_XSD2 | S626_XFIFO_2 | S626_WS3 | S626_EOS, - devpriv->mmio + S626_VECTPORT(5)); + dev->mmio + S626_VECTPORT(5)); /* * Construct and transmit target DAC's serial packet: @@ -671,16 +609,16 @@ static int s626_write_trim_dac(struct comedi_device *dev, uint8_t logical_chan, /* Slot 2: Send high uint8_t to target TrimDac */ writel(S626_XSD2 | S626_XFIFO_1 | S626_WS3, - devpriv->mmio + S626_VECTPORT(2)); + dev->mmio + S626_VECTPORT(2)); /* Slot 3: Send low uint8_t to target TrimDac */ writel(S626_XSD2 | S626_XFIFO_0 | S626_WS3, - devpriv->mmio + S626_VECTPORT(3)); + dev->mmio + S626_VECTPORT(3)); /* Slot 4: Send NOP high uint8_t to DAC0 to keep clock running */ writel(S626_XSD2 | S626_XFIFO_3 | S626_WS1, - devpriv->mmio + S626_VECTPORT(4)); + dev->mmio + S626_VECTPORT(4)); /* Slot 5: Send NOP low uint8_t to DAC0 */ writel(S626_XSD2 | S626_XFIFO_2 | S626_WS1 | S626_EOS, - devpriv->mmio + S626_VECTPORT(5)); + dev->mmio + S626_VECTPORT(5)); /* * Construct and transmit target DAC's serial packet: @@ -723,32 +661,14 @@ static int s626_load_trim_dacs(struct comedi_device *dev) */ /* - * Read a counter's output latch. - */ -static uint32_t s626_read_latch(struct comedi_device *dev, - const struct s626_enc_info *k) -{ - uint32_t value; - - /* Latch counts and fetch LSW of latched counts value. */ - value = s626_debi_read(dev, k->my_latch_lsw); - - /* Fetch MSW of latched counts and combine with LSW. */ - value |= ((uint32_t)s626_debi_read(dev, k->my_latch_lsw + 2) << 16); - - /* Return latched counts. */ - return value; -} - -/* * Return/set a counter pair's latch trigger source. 0: On read * access, 1: A index latches A, 2: B index latches B, 3: A overflow * latches B. */ static void s626_set_latch_source(struct comedi_device *dev, - const struct s626_enc_info *k, uint16_t value) + unsigned int chan, uint16_t value) { - s626_debi_replace(dev, k->my_crb, + s626_debi_replace(dev, S626_LP_CRB(chan), ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_LATCHSRC), S626_SET_CRB_LATCHSRC(value)); } @@ -757,10 +677,10 @@ static void s626_set_latch_source(struct comedi_device *dev, * Write value into counter preload register. */ static void s626_preload(struct comedi_device *dev, - const struct s626_enc_info *k, uint32_t value) + unsigned int chan, uint32_t value) { - s626_debi_write(dev, k->my_latch_lsw, value); - s626_debi_write(dev, k->my_latch_lsw + 2, value >> 16); + s626_debi_write(dev, S626_LP_CNTR(chan), value); + s626_debi_write(dev, S626_LP_CNTR(chan) + 2, value >> 16); } /* ****** PRIVATE COUNTER FUNCTIONS ****** */ @@ -768,28 +688,27 @@ static void s626_preload(struct comedi_device *dev, /* * Reset a counter's index and overflow event capture flags. */ -static void s626_reset_cap_flags_a(struct comedi_device *dev, - const struct s626_enc_info *k) +static void s626_reset_cap_flags(struct comedi_device *dev, + unsigned int chan) { - s626_debi_replace(dev, k->my_crb, ~S626_CRBMSK_INTCTRL, - (S626_SET_CRB_INTRESETCMD(1) | - S626_SET_CRB_INTRESET_A(1))); -} + uint16_t set; -static void s626_reset_cap_flags_b(struct comedi_device *dev, - const struct s626_enc_info *k) -{ - s626_debi_replace(dev, k->my_crb, ~S626_CRBMSK_INTCTRL, - (S626_SET_CRB_INTRESETCMD(1) | - S626_SET_CRB_INTRESET_B(1))); + set = S626_SET_CRB_INTRESETCMD(1); + if (chan < 3) + set |= S626_SET_CRB_INTRESET_A(1); + else + set |= S626_SET_CRB_INTRESET_B(1); + + s626_debi_replace(dev, S626_LP_CRB(chan), ~S626_CRBMSK_INTCTRL, set); } +#ifdef unused /* * Return counter setup in a format (COUNTER_SETUP) that is consistent * for both A and B counters. */ static uint16_t s626_get_mode_a(struct comedi_device *dev, - const struct s626_enc_info *k) + unsigned int chan) { uint16_t cra; uint16_t crb; @@ -797,8 +716,8 @@ static uint16_t s626_get_mode_a(struct comedi_device *dev, unsigned cntsrc, clkmult, clkpol, encmode; /* Fetch CRA and CRB register images. */ - cra = s626_debi_read(dev, k->my_cra); - crb = s626_debi_read(dev, k->my_crb); + cra = s626_debi_read(dev, S626_LP_CRA(chan)); + crb = s626_debi_read(dev, S626_LP_CRB(chan)); /* * Populate the standardized counter setup bit fields. @@ -844,7 +763,7 @@ static uint16_t s626_get_mode_a(struct comedi_device *dev, } static uint16_t s626_get_mode_b(struct comedi_device *dev, - const struct s626_enc_info *k) + unsigned int chan) { uint16_t cra; uint16_t crb; @@ -852,8 +771,8 @@ static uint16_t s626_get_mode_b(struct comedi_device *dev, unsigned cntsrc, clkmult, clkpol, encmode; /* Fetch CRA and CRB register images. */ - cra = s626_debi_read(dev, k->my_cra); - crb = s626_debi_read(dev, k->my_crb); + cra = s626_debi_read(dev, S626_LP_CRA(chan)); + crb = s626_debi_read(dev, S626_LP_CRB(chan)); /* * Populate the standardized counter setup bit fields. @@ -903,6 +822,14 @@ static uint16_t s626_get_mode_b(struct comedi_device *dev, return setup; } +static uint16_t s626_get_mode(struct comedi_device *dev, + unsigned int chan) +{ + return (chan < 3) ? s626_get_mode_a(dev, chan) + : s626_get_mode_b(dev, chan); +} +#endif + /* * Set the operating mode for the specified counter. The setup * parameter is treated as a COUNTER_SETUP data type. The following @@ -910,7 +837,7 @@ static uint16_t s626_get_mode_b(struct comedi_device *dev, * ClkPol, ClkEnab, IndexSrc, IndexPol, LoadSrc. */ static void s626_set_mode_a(struct comedi_device *dev, - const struct s626_enc_info *k, uint16_t setup, + unsigned int chan, uint16_t setup, uint16_t disable_int_src) { struct s626_private *devpriv = dev->private; @@ -974,20 +901,21 @@ static void s626_set_mode_a(struct comedi_device *dev, * enable mask to indicate the counter interrupt is disabled. */ if (disable_int_src) - devpriv->counter_int_enabs &= ~k->my_event_bits[3]; + devpriv->counter_int_enabs &= ~(S626_OVERMASK(chan) | + S626_INDXMASK(chan)); /* * While retaining CounterB and LatchSrc configurations, program the * new counter operating mode. */ - s626_debi_replace(dev, k->my_cra, + s626_debi_replace(dev, S626_LP_CRA(chan), S626_CRAMSK_INDXSRC_B | S626_CRAMSK_CNTSRC_B, cra); - s626_debi_replace(dev, k->my_crb, + s626_debi_replace(dev, S626_LP_CRB(chan), ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_CLKENAB_A), crb); } static void s626_set_mode_b(struct comedi_device *dev, - const struct s626_enc_info *k, uint16_t setup, + unsigned int chan, uint16_t setup, uint16_t disable_int_src) { struct s626_private *devpriv = dev->private; @@ -1058,54 +986,64 @@ static void s626_set_mode_b(struct comedi_device *dev, * enable mask to indicate the counter interrupt is disabled. */ if (disable_int_src) - devpriv->counter_int_enabs &= ~k->my_event_bits[3]; + devpriv->counter_int_enabs &= ~(S626_OVERMASK(chan) | + S626_INDXMASK(chan)); /* * While retaining CounterA and LatchSrc configurations, program the * new counter operating mode. */ - s626_debi_replace(dev, k->my_cra, + s626_debi_replace(dev, S626_LP_CRA(chan), ~(S626_CRAMSK_INDXSRC_B | S626_CRAMSK_CNTSRC_B), cra); - s626_debi_replace(dev, k->my_crb, + s626_debi_replace(dev, S626_LP_CRB(chan), S626_CRBMSK_CLKENAB_A | S626_CRBMSK_LATCHSRC, crb); } +static void s626_set_mode(struct comedi_device *dev, + unsigned int chan, + uint16_t setup, uint16_t disable_int_src) +{ + if (chan < 3) + s626_set_mode_a(dev, chan, setup, disable_int_src); + else + s626_set_mode_b(dev, chan, setup, disable_int_src); +} + /* * Return/set a counter's enable. enab: 0=always enabled, 1=enabled by index. */ -static void s626_set_enable_a(struct comedi_device *dev, - const struct s626_enc_info *k, uint16_t enab) +static void s626_set_enable(struct comedi_device *dev, + unsigned int chan, uint16_t enab) { - s626_debi_replace(dev, k->my_crb, - ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_CLKENAB_A), - S626_SET_CRB_CLKENAB_A(enab)); -} + unsigned int mask = S626_CRBMSK_INTCTRL; + unsigned int set; -static void s626_set_enable_b(struct comedi_device *dev, - const struct s626_enc_info *k, uint16_t enab) -{ - s626_debi_replace(dev, k->my_crb, - ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_CLKENAB_B), - S626_SET_CRB_CLKENAB_B(enab)); + if (chan < 3) { + mask |= S626_CRBMSK_CLKENAB_A; + set = S626_SET_CRB_CLKENAB_A(enab); + } else { + mask |= S626_CRBMSK_CLKENAB_B; + set = S626_SET_CRB_CLKENAB_B(enab); + } + s626_debi_replace(dev, S626_LP_CRB(chan), ~mask, set); } -static uint16_t s626_get_enable_a(struct comedi_device *dev, - const struct s626_enc_info *k) +#ifdef unused +static uint16_t s626_get_enable(struct comedi_device *dev, + unsigned int chan) { - return S626_GET_CRB_CLKENAB_A(s626_debi_read(dev, k->my_crb)); -} + uint16_t crb = s626_debi_read(dev, S626_LP_CRB(chan)); -static uint16_t s626_get_enable_b(struct comedi_device *dev, - const struct s626_enc_info *k) -{ - return S626_GET_CRB_CLKENAB_B(s626_debi_read(dev, k->my_crb)); + return (chan < 3) ? S626_GET_CRB_CLKENAB_A(crb) + : S626_GET_CRB_CLKENAB_B(crb); } +#endif #ifdef unused static uint16_t s626_get_latch_source(struct comedi_device *dev, - const struct s626_enc_info *k) + unsigned int chan) { - return S626_GET_CRB_LATCHSRC(s626_debi_read(dev, k->my_crb)); + return S626_GET_CRB_LATCHSRC(s626_debi_read(dev, S626_LP_CRB(chan))); } #endif @@ -1114,295 +1052,244 @@ static uint16_t s626_get_latch_source(struct comedi_device *dev, * register into the counter. 0=ThisCntr_Index, 1=ThisCntr_Overflow, * 2=OverflowA (B counters only), 3=disabled. */ -static void s626_set_load_trig_a(struct comedi_device *dev, - const struct s626_enc_info *k, uint16_t trig) -{ - s626_debi_replace(dev, k->my_cra, ~S626_CRAMSK_LOADSRC_A, - S626_SET_CRA_LOADSRC_A(trig)); -} - -static void s626_set_load_trig_b(struct comedi_device *dev, - const struct s626_enc_info *k, uint16_t trig) +static void s626_set_load_trig(struct comedi_device *dev, + unsigned int chan, uint16_t trig) { - s626_debi_replace(dev, k->my_crb, - ~(S626_CRBMSK_LOADSRC_B | S626_CRBMSK_INTCTRL), - S626_SET_CRB_LOADSRC_B(trig)); -} + uint16_t reg; + uint16_t mask; + uint16_t set; -static uint16_t s626_get_load_trig_a(struct comedi_device *dev, - const struct s626_enc_info *k) -{ - return S626_GET_CRA_LOADSRC_A(s626_debi_read(dev, k->my_cra)); + if (chan < 3) { + reg = S626_LP_CRA(chan); + mask = S626_CRAMSK_LOADSRC_A; + set = S626_SET_CRA_LOADSRC_A(trig); + } else { + reg = S626_LP_CRB(chan); + mask = S626_CRBMSK_LOADSRC_B | S626_CRBMSK_INTCTRL; + set = S626_SET_CRB_LOADSRC_B(trig); + } + s626_debi_replace(dev, reg, ~mask, set); } -static uint16_t s626_get_load_trig_b(struct comedi_device *dev, - const struct s626_enc_info *k) +#ifdef unused +static uint16_t s626_get_load_trig(struct comedi_device *dev, + unsigned int chan) { - return S626_GET_CRB_LOADSRC_B(s626_debi_read(dev, k->my_crb)); + if (chan < 3) + return S626_GET_CRA_LOADSRC_A(s626_debi_read(dev, + S626_LP_CRA(chan))); + else + return S626_GET_CRB_LOADSRC_B(s626_debi_read(dev, + S626_LP_CRB(chan))); } +#endif /* * Return/set counter interrupt source and clear any captured * index/overflow events. int_source: 0=Disabled, 1=OverflowOnly, * 2=IndexOnly, 3=IndexAndOverflow. */ -static void s626_set_int_src_a(struct comedi_device *dev, - const struct s626_enc_info *k, - uint16_t int_source) -{ - struct s626_private *devpriv = dev->private; - - /* Reset any pending counter overflow or index captures. */ - s626_debi_replace(dev, k->my_crb, ~S626_CRBMSK_INTCTRL, - (S626_SET_CRB_INTRESETCMD(1) | - S626_SET_CRB_INTRESET_A(1))); - - /* Program counter interrupt source. */ - s626_debi_replace(dev, k->my_cra, ~S626_CRAMSK_INTSRC_A, - S626_SET_CRA_INTSRC_A(int_source)); - - /* Update MISC2 interrupt enable mask. */ - devpriv->counter_int_enabs = - (devpriv->counter_int_enabs & ~k->my_event_bits[3]) | - k->my_event_bits[int_source]; -} - -static void s626_set_int_src_b(struct comedi_device *dev, - const struct s626_enc_info *k, - uint16_t int_source) +static void s626_set_int_src(struct comedi_device *dev, + unsigned int chan, uint16_t int_source) { struct s626_private *devpriv = dev->private; - uint16_t crb; + uint16_t cra_reg = S626_LP_CRA(chan); + uint16_t crb_reg = S626_LP_CRB(chan); + + if (chan < 3) { + /* Reset any pending counter overflow or index captures */ + s626_debi_replace(dev, crb_reg, ~S626_CRBMSK_INTCTRL, + S626_SET_CRB_INTRESETCMD(1) | + S626_SET_CRB_INTRESET_A(1)); + + /* Program counter interrupt source */ + s626_debi_replace(dev, cra_reg, ~S626_CRAMSK_INTSRC_A, + S626_SET_CRA_INTSRC_A(int_source)); + } else { + uint16_t crb; - /* Cache writeable CRB register image. */ - crb = s626_debi_read(dev, k->my_crb) & ~S626_CRBMSK_INTCTRL; + /* Cache writeable CRB register image */ + crb = s626_debi_read(dev, crb_reg); + crb &= ~S626_CRBMSK_INTCTRL; - /* Reset any pending counter overflow or index captures. */ - s626_debi_write(dev, k->my_crb, (crb | S626_SET_CRB_INTRESETCMD(1) | - S626_SET_CRB_INTRESET_B(1))); + /* Reset any pending counter overflow or index captures */ + s626_debi_write(dev, crb_reg, + crb | S626_SET_CRB_INTRESETCMD(1) | + S626_SET_CRB_INTRESET_B(1)); - /* Program counter interrupt source. */ - s626_debi_write(dev, k->my_crb, ((crb & ~S626_CRBMSK_INTSRC_B) | - S626_SET_CRB_INTSRC_B(int_source))); + /* Program counter interrupt source */ + s626_debi_write(dev, crb_reg, + (crb & ~S626_CRBMSK_INTSRC_B) | + S626_SET_CRB_INTSRC_B(int_source)); + } /* Update MISC2 interrupt enable mask. */ - devpriv->counter_int_enabs = - (devpriv->counter_int_enabs & ~k->my_event_bits[3]) | - k->my_event_bits[int_source]; -} - -static uint16_t s626_get_int_src_a(struct comedi_device *dev, - const struct s626_enc_info *k) -{ - return S626_GET_CRA_INTSRC_A(s626_debi_read(dev, k->my_cra)); + devpriv->counter_int_enabs &= ~(S626_OVERMASK(chan) | + S626_INDXMASK(chan)); + switch (int_source) { + case 0: + default: + break; + case 1: + devpriv->counter_int_enabs |= S626_OVERMASK(chan); + break; + case 2: + devpriv->counter_int_enabs |= S626_INDXMASK(chan); + break; + case 3: + devpriv->counter_int_enabs |= (S626_OVERMASK(chan) | + S626_INDXMASK(chan)); + break; + } } -static uint16_t s626_get_int_src_b(struct comedi_device *dev, - const struct s626_enc_info *k) +#ifdef unused +static uint16_t s626_get_int_src(struct comedi_device *dev, + unsigned int chan) { - return S626_GET_CRB_INTSRC_B(s626_debi_read(dev, k->my_crb)); + if (chan < 3) + return S626_GET_CRA_INTSRC_A(s626_debi_read(dev, + S626_LP_CRA(chan))); + else + return S626_GET_CRB_INTSRC_B(s626_debi_read(dev, + S626_LP_CRB(chan))); } +#endif #ifdef unused /* * Return/set the clock multiplier. */ static void s626_set_clk_mult(struct comedi_device *dev, - const struct s626_enc_info *k, uint16_t value) + unsigned int chan, uint16_t value) { - k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_CLKMULT) | - S626_SET_STD_CLKMULT(value)), false); + uint16_t mode; + + mode = s626_get_mode(dev, chan); + mode &= ~S626_STDMSK_CLKMULT; + mode |= S626_SET_STD_CLKMULT(value); + + s626_set_mode(dev, chan, mode, false); } static uint16_t s626_get_clk_mult(struct comedi_device *dev, - const struct s626_enc_info *k) + unsigned int chan) { - return S626_GET_STD_CLKMULT(k->get_mode(dev, k)); + return S626_GET_STD_CLKMULT(s626_get_mode(dev, chan)); } /* * Return/set the clock polarity. */ static void s626_set_clk_pol(struct comedi_device *dev, - const struct s626_enc_info *k, uint16_t value) + unsigned int chan, uint16_t value) { - k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_CLKPOL) | - S626_SET_STD_CLKPOL(value)), false); + uint16_t mode; + + mode = s626_get_mode(dev, chan); + mode &= ~S626_STDMSK_CLKPOL; + mode |= S626_SET_STD_CLKPOL(value); + + s626_set_mode(dev, chan, mode, false); } static uint16_t s626_get_clk_pol(struct comedi_device *dev, - const struct s626_enc_info *k) + unsigned int chan) { - return S626_GET_STD_CLKPOL(k->get_mode(dev, k)); + return S626_GET_STD_CLKPOL(s626_get_mode(dev, chan)); } /* * Return/set the encoder mode. */ static void s626_set_enc_mode(struct comedi_device *dev, - const struct s626_enc_info *k, uint16_t value) + unsigned int chan, uint16_t value) { - k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_ENCMODE) | - S626_SET_STD_ENCMODE(value)), false); + uint16_t mode; + + mode = s626_get_mode(dev, chan); + mode &= ~S626_STDMSK_ENCMODE; + mode |= S626_SET_STD_ENCMODE(value); + + s626_set_mode(dev, chan, mode, false); } static uint16_t s626_get_enc_mode(struct comedi_device *dev, - const struct s626_enc_info *k) + unsigned int chan) { - return S626_GET_STD_ENCMODE(k->get_mode(dev, k)); + return S626_GET_STD_ENCMODE(s626_get_mode(dev, chan)); } /* * Return/set the index polarity. */ static void s626_set_index_pol(struct comedi_device *dev, - const struct s626_enc_info *k, uint16_t value) + unsigned int chan, uint16_t value) { - k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_INDXPOL) | - S626_SET_STD_INDXPOL(value != 0)), false); + uint16_t mode; + + mode = s626_get_mode(dev, chan); + mode &= ~S626_STDMSK_INDXPOL; + mode |= S626_SET_STD_INDXPOL(value != 0); + + s626_set_mode(dev, chan, mode, false); } static uint16_t s626_get_index_pol(struct comedi_device *dev, - const struct s626_enc_info *k) + unsigned int chan) { - return S626_GET_STD_INDXPOL(k->get_mode(dev, k)); + return S626_GET_STD_INDXPOL(s626_get_mode(dev, chan)); } /* * Return/set the index source. */ static void s626_set_index_src(struct comedi_device *dev, - const struct s626_enc_info *k, uint16_t value) + unsigned int chan, uint16_t value) { - k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_INDXSRC) | - S626_SET_STD_INDXSRC(value != 0)), false); + uint16_t mode; + + mode = s626_get_mode(dev, chan); + mode &= ~S626_STDMSK_INDXSRC; + mode |= S626_SET_STD_INDXSRC(value != 0); + + s626_set_mode(dev, chan, mode, false); } static uint16_t s626_get_index_src(struct comedi_device *dev, - const struct s626_enc_info *k) + unsigned int chan) { - return S626_GET_STD_INDXSRC(k->get_mode(dev, k)); + return S626_GET_STD_INDXSRC(s626_get_mode(dev, chan)); } #endif /* * Generate an index pulse. */ -static void s626_pulse_index_a(struct comedi_device *dev, - const struct s626_enc_info *k) +static void s626_pulse_index(struct comedi_device *dev, + unsigned int chan) { - uint16_t cra; + if (chan < 3) { + uint16_t cra; - cra = s626_debi_read(dev, k->my_cra); - /* Pulse index. */ - s626_debi_write(dev, k->my_cra, (cra ^ S626_CRAMSK_INDXPOL_A)); - s626_debi_write(dev, k->my_cra, cra); -} + cra = s626_debi_read(dev, S626_LP_CRA(chan)); -static void s626_pulse_index_b(struct comedi_device *dev, - const struct s626_enc_info *k) -{ - uint16_t crb; + /* Pulse index */ + s626_debi_write(dev, S626_LP_CRA(chan), + (cra ^ S626_CRAMSK_INDXPOL_A)); + s626_debi_write(dev, S626_LP_CRA(chan), cra); + } else { + uint16_t crb; - crb = s626_debi_read(dev, k->my_crb) & ~S626_CRBMSK_INTCTRL; - /* Pulse index. */ - s626_debi_write(dev, k->my_crb, (crb ^ S626_CRBMSK_INDXPOL_B)); - s626_debi_write(dev, k->my_crb, crb); -} + crb = s626_debi_read(dev, S626_LP_CRB(chan)); + crb &= ~S626_CRBMSK_INTCTRL; -static const struct s626_enc_info s626_enc_chan_info[] = { - { - .get_enable = s626_get_enable_a, - .get_int_src = s626_get_int_src_a, - .get_load_trig = s626_get_load_trig_a, - .get_mode = s626_get_mode_a, - .pulse_index = s626_pulse_index_a, - .set_enable = s626_set_enable_a, - .set_int_src = s626_set_int_src_a, - .set_load_trig = s626_set_load_trig_a, - .set_mode = s626_set_mode_a, - .reset_cap_flags = s626_reset_cap_flags_a, - .my_cra = S626_LP_CR0A, - .my_crb = S626_LP_CR0B, - .my_latch_lsw = S626_LP_CNTR0ALSW, - .my_event_bits = S626_EVBITS(0), - }, { - .get_enable = s626_get_enable_a, - .get_int_src = s626_get_int_src_a, - .get_load_trig = s626_get_load_trig_a, - .get_mode = s626_get_mode_a, - .pulse_index = s626_pulse_index_a, - .set_enable = s626_set_enable_a, - .set_int_src = s626_set_int_src_a, - .set_load_trig = s626_set_load_trig_a, - .set_mode = s626_set_mode_a, - .reset_cap_flags = s626_reset_cap_flags_a, - .my_cra = S626_LP_CR1A, - .my_crb = S626_LP_CR1B, - .my_latch_lsw = S626_LP_CNTR1ALSW, - .my_event_bits = S626_EVBITS(1), - }, { - .get_enable = s626_get_enable_a, - .get_int_src = s626_get_int_src_a, - .get_load_trig = s626_get_load_trig_a, - .get_mode = s626_get_mode_a, - .pulse_index = s626_pulse_index_a, - .set_enable = s626_set_enable_a, - .set_int_src = s626_set_int_src_a, - .set_load_trig = s626_set_load_trig_a, - .set_mode = s626_set_mode_a, - .reset_cap_flags = s626_reset_cap_flags_a, - .my_cra = S626_LP_CR2A, - .my_crb = S626_LP_CR2B, - .my_latch_lsw = S626_LP_CNTR2ALSW, - .my_event_bits = S626_EVBITS(2), - }, { - .get_enable = s626_get_enable_b, - .get_int_src = s626_get_int_src_b, - .get_load_trig = s626_get_load_trig_b, - .get_mode = s626_get_mode_b, - .pulse_index = s626_pulse_index_b, - .set_enable = s626_set_enable_b, - .set_int_src = s626_set_int_src_b, - .set_load_trig = s626_set_load_trig_b, - .set_mode = s626_set_mode_b, - .reset_cap_flags = s626_reset_cap_flags_b, - .my_cra = S626_LP_CR0A, - .my_crb = S626_LP_CR0B, - .my_latch_lsw = S626_LP_CNTR0BLSW, - .my_event_bits = S626_EVBITS(3), - }, { - .get_enable = s626_get_enable_b, - .get_int_src = s626_get_int_src_b, - .get_load_trig = s626_get_load_trig_b, - .get_mode = s626_get_mode_b, - .pulse_index = s626_pulse_index_b, - .set_enable = s626_set_enable_b, - .set_int_src = s626_set_int_src_b, - .set_load_trig = s626_set_load_trig_b, - .set_mode = s626_set_mode_b, - .reset_cap_flags = s626_reset_cap_flags_b, - .my_cra = S626_LP_CR1A, - .my_crb = S626_LP_CR1B, - .my_latch_lsw = S626_LP_CNTR1BLSW, - .my_event_bits = S626_EVBITS(4), - }, { - .get_enable = s626_get_enable_b, - .get_int_src = s626_get_int_src_b, - .get_load_trig = s626_get_load_trig_b, - .get_mode = s626_get_mode_b, - .pulse_index = s626_pulse_index_b, - .set_enable = s626_set_enable_b, - .set_int_src = s626_set_int_src_b, - .set_load_trig = s626_set_load_trig_b, - .set_mode = s626_set_mode_b, - .reset_cap_flags = s626_reset_cap_flags_b, - .my_cra = S626_LP_CR2A, - .my_crb = S626_LP_CR2B, - .my_latch_lsw = S626_LP_CNTR2BLSW, - .my_event_bits = S626_EVBITS(5), - }, -}; + /* Pulse index */ + s626_debi_write(dev, S626_LP_CRB(chan), + (crb ^ S626_CRBMSK_INDXPOL_B)); + s626_debi_write(dev, S626_LP_CRB(chan), crb); + } +} static unsigned int s626_ai_reg_to_uint(unsigned int data) { @@ -1490,11 +1377,8 @@ static void s626_handle_dio_interrupt(struct comedi_device *dev, } if (cmd->convert_src == TRIG_TIMER) { - const struct s626_enc_info *k = - &s626_enc_chan_info[5]; - devpriv->ai_convert_count = cmd->chanlist_len; - k->set_enable(dev, k, S626_CLKENAB_ALWAYS); + s626_set_enable(dev, 5, S626_CLKENAB_ALWAYS); } } if ((irqbit >> (cmd->convert_arg - (16 * group))) == 1 && @@ -1533,7 +1417,6 @@ static void s626_check_counter_interrupts(struct comedi_device *dev) struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; - const struct s626_enc_info *k; uint16_t irqbit; /* read interrupt type */ @@ -1541,39 +1424,29 @@ static void s626_check_counter_interrupts(struct comedi_device *dev) /* check interrupt on counters */ if (irqbit & S626_IRQ_COINT1A) { - k = &s626_enc_chan_info[0]; - /* clear interrupt capture flag */ - k->reset_cap_flags(dev, k); + s626_reset_cap_flags(dev, 0); } if (irqbit & S626_IRQ_COINT2A) { - k = &s626_enc_chan_info[1]; - /* clear interrupt capture flag */ - k->reset_cap_flags(dev, k); + s626_reset_cap_flags(dev, 1); } if (irqbit & S626_IRQ_COINT3A) { - k = &s626_enc_chan_info[2]; - /* clear interrupt capture flag */ - k->reset_cap_flags(dev, k); + s626_reset_cap_flags(dev, 2); } if (irqbit & S626_IRQ_COINT1B) { - k = &s626_enc_chan_info[3]; - /* clear interrupt capture flag */ - k->reset_cap_flags(dev, k); + s626_reset_cap_flags(dev, 3); } if (irqbit & S626_IRQ_COINT2B) { - k = &s626_enc_chan_info[4]; - /* clear interrupt capture flag */ - k->reset_cap_flags(dev, k); + s626_reset_cap_flags(dev, 4); if (devpriv->ai_convert_count > 0) { devpriv->ai_convert_count--; if (devpriv->ai_convert_count == 0) - k->set_enable(dev, k, S626_CLKENAB_INDEX); + s626_set_enable(dev, 4, S626_CLKENAB_INDEX); if (cmd->convert_src == TRIG_TIMER) { /* Trigger ADC scan loop start */ @@ -1583,10 +1456,8 @@ static void s626_check_counter_interrupts(struct comedi_device *dev) } } if (irqbit & S626_IRQ_COINT3B) { - k = &s626_enc_chan_info[5]; - /* clear interrupt capture flag */ - k->reset_cap_flags(dev, k); + s626_reset_cap_flags(dev, 5); if (cmd->scan_begin_src == TRIG_TIMER) { /* Trigger ADC scan loop start */ @@ -1594,9 +1465,8 @@ static void s626_check_counter_interrupts(struct comedi_device *dev) } if (cmd->convert_src == TRIG_TIMER) { - k = &s626_enc_chan_info[4]; devpriv->ai_convert_count = cmd->chanlist_len; - k->set_enable(dev, k, S626_CLKENAB_ALWAYS); + s626_set_enable(dev, 4, S626_CLKENAB_ALWAYS); } } } @@ -1661,7 +1531,6 @@ static bool s626_handle_eos_interrupt(struct comedi_device *dev) static irqreturn_t s626_irq_handler(int irq, void *d) { struct comedi_device *dev = d; - struct s626_private *devpriv = dev->private; unsigned long flags; uint32_t irqtype, irqstatus; @@ -1671,16 +1540,16 @@ static irqreturn_t s626_irq_handler(int irq, void *d) spin_lock_irqsave(&dev->spinlock, flags); /* save interrupt enable register state */ - irqstatus = readl(devpriv->mmio + S626_P_IER); + irqstatus = readl(dev->mmio + S626_P_IER); /* read interrupt type */ - irqtype = readl(devpriv->mmio + S626_P_ISR); + irqtype = readl(dev->mmio + S626_P_ISR); /* disable master interrupt */ - writel(0, devpriv->mmio + S626_P_IER); + writel(0, dev->mmio + S626_P_IER); /* clear interrupt */ - writel(irqtype, devpriv->mmio + S626_P_ISR); + writel(irqtype, dev->mmio + S626_P_ISR); switch (irqtype) { case S626_IRQ_RPS1: /* end_of_scan occurs */ @@ -1695,7 +1564,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d) } /* enable interrupt */ - writel(irqstatus, devpriv->mmio + S626_P_IER); + writel(irqstatus, dev->mmio + S626_P_IER); spin_unlock_irqrestore(&dev->spinlock, flags); return IRQ_HANDLED; @@ -1723,7 +1592,7 @@ static void s626_reset_adc(struct comedi_device *dev, uint8_t *ppl) /* Initialize RPS instruction pointer */ writel((uint32_t)devpriv->rps_buf.physical_base, - devpriv->mmio + S626_P_RPSADDR1); + dev->mmio + S626_P_RPSADDR1); /* Construct RPS program in rps_buf DMA buffer */ if (cmd != NULL && cmd->scan_begin_src != TRIG_FOLLOW) { @@ -1944,10 +1813,9 @@ static int s626_ai_eoc(struct comedi_device *dev, struct comedi_insn *insn, unsigned long context) { - struct s626_private *devpriv = dev->private; unsigned int status; - status = readl(devpriv->mmio + S626_P_PSR); + status = readl(dev->mmio + S626_P_PSR); if (status & S626_PSR_GPIO2) return 0; return -EBUSY; @@ -1955,9 +1823,9 @@ static int s626_ai_eoc(struct comedi_device *dev, static int s626_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 s626_private *devpriv = dev->private; uint16_t chan = CR_CHAN(insn->chanspec); uint16_t range = CR_RANGE(insn->chanspec); uint16_t adc_spec = 0; @@ -1986,17 +1854,14 @@ static int s626_ai_insn_read(struct comedi_device *dev, udelay(10); /* Start ADC by pulsing GPIO1 low */ - gpio_image = readl(devpriv->mmio + S626_P_GPIO); + gpio_image = readl(dev->mmio + S626_P_GPIO); /* Assert ADC Start command */ - writel(gpio_image & ~S626_GPIO1_HI, - devpriv->mmio + S626_P_GPIO); + writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO); /* and stretch it out */ - writel(gpio_image & ~S626_GPIO1_HI, - devpriv->mmio + S626_P_GPIO); - writel(gpio_image & ~S626_GPIO1_HI, - devpriv->mmio + S626_P_GPIO); + writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO); + writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO); /* Negate ADC Start command */ - writel(gpio_image | S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO); + writel(gpio_image | S626_GPIO1_HI, dev->mmio + S626_P_GPIO); /* * Wait for ADC to complete (GPIO2 is asserted high when @@ -2011,7 +1876,7 @@ static int s626_ai_insn_read(struct comedi_device *dev, /* Fetch ADC data */ if (n != 0) { - tmp = readl(devpriv->mmio + S626_P_FB_BUFFER1); + tmp = readl(dev->mmio + S626_P_FB_BUFFER1); data[n - 1] = s626_ai_reg_to_uint(tmp); } @@ -2031,14 +1896,14 @@ static int s626_ai_insn_read(struct comedi_device *dev, * Start a dummy conversion to cause the data from the * previous conversion to be shifted in. */ - gpio_image = readl(devpriv->mmio + S626_P_GPIO); + gpio_image = readl(dev->mmio + S626_P_GPIO); /* Assert ADC Start command */ - writel(gpio_image & ~S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO); + writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO); /* and stretch it out */ - writel(gpio_image & ~S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO); - writel(gpio_image & ~S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO); + writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO); + writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO); /* Negate ADC Start command */ - writel(gpio_image | S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO); + writel(gpio_image | S626_GPIO1_HI, dev->mmio + S626_P_GPIO); /* Wait for the data to arrive in FB BUFFER 1 register. */ @@ -2051,7 +1916,7 @@ static int s626_ai_insn_read(struct comedi_device *dev, /* Fetch ADC data */ if (n != 0) { - tmp = readl(devpriv->mmio + S626_P_FB_BUFFER1); + tmp = readl(dev->mmio + S626_P_FB_BUFFER1); data[n - 1] = s626_ai_reg_to_uint(tmp); } @@ -2098,13 +1963,13 @@ static int s626_ai_inttrig(struct comedi_device *dev, * Also, it should adjust ns so that it cooresponds to the actual time * that the device will use. */ -static int s626_ns_to_timer(unsigned int *nanosec, int round_mode) +static int s626_ns_to_timer(unsigned int *nanosec, unsigned int flags) { int divider, base; base = 500; /* 2MHz internal clock */ - switch (round_mode) { + switch (flags & TRIG_ROUND_MASK) { case TRIG_ROUND_NEAREST: default: divider = (*nanosec + base / 2) / base; @@ -2122,7 +1987,7 @@ static int s626_ns_to_timer(unsigned int *nanosec, int round_mode) } static void s626_timer_load(struct comedi_device *dev, - const struct s626_enc_info *k, int tick) + unsigned int chan, int tick) { uint16_t setup = /* Preload upon index. */ @@ -2140,26 +2005,26 @@ static void s626_timer_load(struct comedi_device *dev, uint16_t value_latchsrc = S626_LATCHSRC_A_INDXA; /* uint16_t enab = S626_CLKENAB_ALWAYS; */ - k->set_mode(dev, k, setup, false); + s626_set_mode(dev, chan, setup, false); /* Set the preload register */ - s626_preload(dev, k, tick); + s626_preload(dev, chan, tick); /* * Software index pulse forces the preload register to load * into the counter */ - k->set_load_trig(dev, k, 0); - k->pulse_index(dev, k); + s626_set_load_trig(dev, chan, 0); + s626_pulse_index(dev, chan); /* set reload on counter overflow */ - k->set_load_trig(dev, k, 1); + s626_set_load_trig(dev, chan, 1); /* set interrupt on overflow */ - k->set_int_src(dev, k, S626_INTSRC_OVER); + s626_set_int_src(dev, chan, S626_INTSRC_OVER); - s626_set_latch_source(dev, k, value_latchsrc); - /* k->set_enable(dev, k, (uint16_t)(enab != 0)); */ + s626_set_latch_source(dev, chan, value_latchsrc); + /* s626_set_enable(dev, chan, (uint16_t)(enab != 0)); */ } /* TO COMPLETE */ @@ -2168,7 +2033,6 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) struct s626_private *devpriv = dev->private; uint8_t ppl[16]; struct comedi_cmd *cmd = &s->async->cmd; - const struct s626_enc_info *k; int tick; if (devpriv->ai_cmd_running) { @@ -2177,10 +2041,10 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return -EBUSY; } /* disable interrupt */ - writel(0, devpriv->mmio + S626_P_IER); + writel(0, dev->mmio + S626_P_IER); /* clear interrupt request */ - writel(S626_IRQ_RPS1 | S626_IRQ_GPIO3, devpriv->mmio + S626_P_ISR); + writel(S626_IRQ_RPS1 | S626_IRQ_GPIO3, dev->mmio + S626_P_ISR); /* clear any pending interrupt */ s626_dio_clear_irq(dev); @@ -2205,13 +2069,11 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * set a counter to generate adc trigger at scan_begin_arg * interval */ - k = &s626_enc_chan_info[5]; - tick = s626_ns_to_timer(&cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); + tick = s626_ns_to_timer(&cmd->scan_begin_arg, cmd->flags); /* load timer value and enable interrupt */ - s626_timer_load(dev, k, tick); - k->set_enable(dev, k, S626_CLKENAB_ALWAYS); + s626_timer_load(dev, 5, tick); + s626_set_enable(dev, 5, S626_CLKENAB_ALWAYS); break; case TRIG_EXT: /* set the digital line and interrupt for scan trigger */ @@ -2228,13 +2090,11 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * set a counter to generate adc trigger at convert_arg * interval */ - k = &s626_enc_chan_info[4]; - tick = s626_ns_to_timer(&cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); + tick = s626_ns_to_timer(&cmd->convert_arg, cmd->flags); /* load timer value and enable interrupt */ - s626_timer_load(dev, k, tick); - k->set_enable(dev, k, S626_CLKENAB_INDEX); + s626_timer_load(dev, 4, tick); + s626_set_enable(dev, 4, S626_CLKENAB_INDEX); break; case TRIG_EXT: /* set the digital line and interrupt for convert trigger */ @@ -2279,7 +2139,7 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } /* enable interrupt */ - writel(S626_IRQ_GPIO3 | S626_IRQ_RPS1, devpriv->mmio + S626_P_IER); + writel(S626_IRQ_GPIO3 | S626_IRQ_RPS1, dev->mmio + S626_P_IER); return 0; } @@ -2372,13 +2232,13 @@ static int s626_ai_cmdtest(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER) { arg = cmd->scan_begin_arg; - s626_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + s626_ns_to_timer(&arg, cmd->flags); err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (cmd->convert_src == TRIG_TIMER) { arg = cmd->convert_arg; - s626_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + s626_ns_to_timer(&arg, cmd->flags); err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); if (cmd->scan_begin_src == TRIG_TIMER) { @@ -2402,7 +2262,7 @@ static int s626_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) s626_mc_disable(dev, S626_MC1_ERPS1, S626_P_MC1); /* disable master interrupt */ - writel(0, devpriv->mmio + S626_P_IER); + writel(0, dev->mmio + S626_P_IER); devpriv->ai_cmd_running = 0; @@ -2516,6 +2376,7 @@ static int s626_enc_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + unsigned int chan = CR_CHAN(insn->chanspec); uint16_t setup = /* Preload upon index. */ S626_SET_STD_LOADSRC(S626_LOADSRC_INDX) | @@ -2533,51 +2394,58 @@ static int s626_enc_insn_config(struct comedi_device *dev, /* uint32_t Preloadvalue; //Counter initial value */ uint16_t value_latchsrc = S626_LATCHSRC_AB_READ; uint16_t enab = S626_CLKENAB_ALWAYS; - const struct s626_enc_info *k = - &s626_enc_chan_info[CR_CHAN(insn->chanspec)]; /* (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); */ - k->set_mode(dev, k, setup, true); - s626_preload(dev, k, data[0]); - k->pulse_index(dev, k); - s626_set_latch_source(dev, k, value_latchsrc); - k->set_enable(dev, k, (enab != 0)); + s626_set_mode(dev, chan, setup, true); + s626_preload(dev, chan, data[0]); + s626_pulse_index(dev, chan); + s626_set_latch_source(dev, chan, value_latchsrc); + s626_set_enable(dev, chan, (enab != 0)); return insn->n; } static int s626_enc_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; - const struct s626_enc_info *k = - &s626_enc_chan_info[CR_CHAN(insn->chanspec)]; + unsigned int chan = CR_CHAN(insn->chanspec); + uint16_t cntr_latch_reg = S626_LP_CNTR(chan); + int i; - for (n = 0; n < insn->n; n++) - data[n] = s626_read_latch(dev, k); + for (i = 0; i < insn->n; i++) { + unsigned int val; - return n; + /* + * Read the counter's output latch LSW/MSW. + * Latches on LSW read. + */ + val = s626_debi_read(dev, cntr_latch_reg); + val |= (s626_debi_read(dev, cntr_latch_reg + 2) << 16); + data[i] = val; + } + + return insn->n; } static int s626_enc_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - const struct s626_enc_info *k = - &s626_enc_chan_info[CR_CHAN(insn->chanspec)]; + unsigned int chan = CR_CHAN(insn->chanspec); /* Set the preload register */ - s626_preload(dev, k, data[0]); + s626_preload(dev, chan, data[0]); /* * Software index pulse forces the preload register to load * into the counter */ - k->set_load_trig(dev, k, 0); - k->pulse_index(dev, k); - k->set_load_trig(dev, k, 2); + s626_set_load_trig(dev, chan, 0); + s626_pulse_index(dev, chan); + s626_set_load_trig(dev, chan, 2); return 1; } @@ -2612,7 +2480,6 @@ static void s626_close_dma_b(struct comedi_device *dev, static void s626_counters_init(struct comedi_device *dev) { int chan; - const struct s626_enc_info *k; uint16_t setup = /* Preload upon index. */ S626_SET_STD_LOADSRC(S626_LOADSRC_INDX) | @@ -2631,11 +2498,10 @@ static void s626_counters_init(struct comedi_device *dev) * Disable all counter interrupts and clear any captured counter events. */ for (chan = 0; chan < S626_ENCODER_CHANNELS; chan++) { - k = &s626_enc_chan_info[chan]; - k->set_mode(dev, k, setup, true); - k->set_int_src(dev, k, 0); - k->reset_cap_flags(dev, k); - k->set_enable(dev, k, S626_CLKENAB_ALWAYS); + s626_set_mode(dev, chan, setup, true); + s626_set_int_src(dev, chan, 0); + s626_reset_cap_flags(dev, chan); + s626_set_enable(dev, chan, S626_CLKENAB_ALWAYS); } } @@ -2683,13 +2549,13 @@ static int s626_initialize(struct comedi_device *dev) */ writel(S626_DEBI_CFG_SLAVE16 | (S626_DEBI_TOUT << S626_DEBI_CFG_TOUT_BIT) | S626_DEBI_SWAP | - S626_DEBI_CFG_INTEL, devpriv->mmio + S626_P_DEBICFG); + S626_DEBI_CFG_INTEL, dev->mmio + S626_P_DEBICFG); /* Disable MMU paging */ - writel(S626_DEBI_PAGE_DISABLE, devpriv->mmio + S626_P_DEBIPAGE); + writel(S626_DEBI_PAGE_DISABLE, dev->mmio + S626_P_DEBIPAGE); /* Init GPIO so that ADC Start* is negated */ - writel(S626_GPIO_BASE | S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO); + writel(S626_GPIO_BASE | S626_GPIO1_HI, dev->mmio + S626_P_GPIO); /* I2C device address for onboard eeprom (revb) */ devpriv->i2c_adrs = 0xA0; @@ -2699,7 +2565,7 @@ static int s626_initialize(struct comedi_device *dev) * operation in progress and reset BUSY flag. */ writel(S626_I2C_CLKSEL | S626_I2C_ABORT, - devpriv->mmio + S626_P_I2CSTAT); + dev->mmio + S626_P_I2CSTAT); s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2); ret = comedi_timeout(dev, NULL, NULL, s626_i2c_handshake_eoc, 0); if (ret) @@ -2710,7 +2576,7 @@ static int s626_initialize(struct comedi_device *dev) * reg twice to reset all I2C error flags. */ for (i = 0; i < 2; i++) { - writel(S626_I2C_CLKSEL, devpriv->mmio + S626_P_I2CSTAT); + writel(S626_I2C_CLKSEL, dev->mmio + S626_P_I2CSTAT); s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2); ret = comedi_timeout(dev, NULL, NULL, s626_i2c_handshake_eoc, 0); if (ret) @@ -2723,7 +2589,7 @@ static int s626_initialize(struct comedi_device *dev) * DAC data setup times are satisfied, enable DAC serial * clock out. */ - writel(S626_ACON2_INIT, devpriv->mmio + S626_P_ACON2); + writel(S626_ACON2_INIT, dev->mmio + S626_P_ACON2); /* * Set up TSL1 slot list, which is used to control the @@ -2731,12 +2597,12 @@ static int s626_initialize(struct comedi_device *dev) * S626_SIB_A1 = store data uint8_t at next available location * in FB BUFFER1 register. */ - writel(S626_RSD1 | S626_SIB_A1, devpriv->mmio + S626_P_TSL1); + writel(S626_RSD1 | S626_SIB_A1, dev->mmio + S626_P_TSL1); writel(S626_RSD1 | S626_SIB_A1 | S626_EOS, - devpriv->mmio + S626_P_TSL1 + 4); + dev->mmio + S626_P_TSL1 + 4); /* Enable TSL1 slot list so that it executes all the time */ - writel(S626_ACON1_ADCSTART, devpriv->mmio + S626_P_ACON1); + writel(S626_ACON1_ADCSTART, dev->mmio + S626_P_ACON1); /* * Initialize RPS registers used for ADC @@ -2744,11 +2610,11 @@ static int s626_initialize(struct comedi_device *dev) /* Physical start of RPS program */ writel((uint32_t)devpriv->rps_buf.physical_base, - devpriv->mmio + S626_P_RPSADDR1); + dev->mmio + S626_P_RPSADDR1); /* RPS program performs no explicit mem writes */ - writel(0, devpriv->mmio + S626_P_RPSPAGE1); + writel(0, dev->mmio + S626_P_RPSPAGE1); /* Disable RPS timeouts */ - writel(0, devpriv->mmio + S626_P_RPS1_TOUT); + writel(0, dev->mmio + S626_P_RPS1_TOUT); #if 0 /* @@ -2804,7 +2670,7 @@ static int s626_initialize(struct comedi_device *dev) * burst length = 1 DWORD * threshold = 1 DWORD. */ - writel(0, devpriv->mmio + S626_P_PCI_BT_A); + writel(0, dev->mmio + S626_P_PCI_BT_A); /* * Init Audio2's output DMA physical addresses. The protection @@ -2814,9 +2680,9 @@ static int s626_initialize(struct comedi_device *dev) */ phys_buf = devpriv->ana_buf.physical_base + (S626_DAC_WDMABUF_OS * sizeof(uint32_t)); - writel((uint32_t)phys_buf, devpriv->mmio + S626_P_BASEA2_OUT); + writel((uint32_t)phys_buf, dev->mmio + S626_P_BASEA2_OUT); writel((uint32_t)(phys_buf + sizeof(uint32_t)), - devpriv->mmio + S626_P_PROTA2_OUT); + dev->mmio + S626_P_PROTA2_OUT); /* * Cache Audio2's output DMA buffer logical address. This is @@ -2831,7 +2697,7 @@ static int s626_initialize(struct comedi_device *dev) * DMAC will automatically halt and its PCI address pointer * will be reset when the protection address is reached. */ - writel(8, devpriv->mmio + S626_P_PAGEA2_OUT); + writel(8, dev->mmio + S626_P_PAGEA2_OUT); /* * Initialize time slot list 2 (TSL2), which is used to control @@ -2847,7 +2713,7 @@ static int s626_initialize(struct comedi_device *dev) /* Slot 0: Trap TSL execution, shift 0xFF into FB_BUFFER2 */ writel(S626_XSD2 | S626_RSD3 | S626_SIB_A2 | S626_EOS, - devpriv->mmio + S626_VECTPORT(0)); + dev->mmio + S626_VECTPORT(0)); /* * Initialize slot 1, which is constant. Slot 1 causes a @@ -2859,10 +2725,10 @@ static int s626_initialize(struct comedi_device *dev) */ /* Slot 1: Fetch DWORD from Audio2's output FIFO */ - writel(S626_LF_A2, devpriv->mmio + S626_VECTPORT(1)); + writel(S626_LF_A2, dev->mmio + S626_VECTPORT(1)); /* Start DAC's audio interface (TSL2) running */ - writel(S626_ACON1_DACSTART, devpriv->mmio + S626_P_ACON1); + writel(S626_ACON1_DACSTART, dev->mmio + S626_P_ACON1); /* * Init Trim DACs to calibrated values. Do it twice because the @@ -2926,15 +2792,15 @@ static int s626_auto_attach(struct comedi_device *dev, if (ret) return ret; - devpriv->mmio = pci_ioremap_bar(pcidev, 0); - if (!devpriv->mmio) + dev->mmio = pci_ioremap_bar(pcidev, 0); + if (!dev->mmio) return -ENOMEM; /* disable master interrupt */ - writel(0, devpriv->mmio + S626_P_IER); + writel(0, dev->mmio + S626_P_IER); /* soft reset */ - writel(S626_MC1_SOFT_RESET, devpriv->mmio + S626_P_MC1); + writel(S626_MC1_SOFT_RESET, dev->mmio + S626_P_MC1); /* DMA FIXME DMA// */ @@ -3043,20 +2909,20 @@ static void s626_detach(struct comedi_device *dev) /* stop ai_command */ devpriv->ai_cmd_running = 0; - if (devpriv->mmio) { + if (dev->mmio) { /* interrupt mask */ /* Disable master interrupt */ - writel(0, devpriv->mmio + S626_P_IER); + writel(0, dev->mmio + S626_P_IER); /* Clear board's IRQ status flag */ writel(S626_IRQ_GPIO3 | S626_IRQ_RPS1, - devpriv->mmio + S626_P_ISR); + dev->mmio + S626_P_ISR); /* Disable the watchdog timer and battery charger. */ s626_write_misc2(dev, 0); /* Close all interfaces on 7146 device */ - writel(S626_MC1_SHUTDOWN, devpriv->mmio + S626_P_MC1); - writel(S626_ACON1_BASE, devpriv->mmio + S626_P_ACON1); + writel(S626_MC1_SHUTDOWN, dev->mmio + S626_P_MC1); + writel(S626_ACON1_BASE, dev->mmio + S626_P_ACON1); s626_close_dma_b(dev, &devpriv->rps_buf, S626_DMABUF_SIZE); @@ -3066,8 +2932,8 @@ static void s626_detach(struct comedi_device *dev) if (dev->irq) free_irq(dev->irq, dev); - if (devpriv->mmio) - iounmap(devpriv->mmio); + if (dev->mmio) + iounmap(dev->mmio); } comedi_pci_disable(dev); } diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h index 33b72739c1cb..b83424e7507b 100644 --- a/drivers/staging/comedi/drivers/s626.h +++ b/drivers/staging/comedi/drivers/s626.h @@ -229,27 +229,13 @@ #define S626_LP_RDEDGSEL(x) (0x004c + (x) * 0x10) /* R: edge selection */ #define S626_LP_RDCAPSEL(x) (0x004e + (x) * 0x10) /* R: capture enable */ -/* Counter Registers (read/write): */ -#define S626_LP_CR0A 0x0000 /* 0A setup register. */ -#define S626_LP_CR0B 0x0002 /* 0B setup register. */ -#define S626_LP_CR1A 0x0004 /* 1A setup register. */ -#define S626_LP_CR1B 0x0006 /* 1B setup register. */ -#define S626_LP_CR2A 0x0008 /* 2A setup register. */ -#define S626_LP_CR2B 0x000A /* 2B setup register. */ - -/* Counter PreLoad (write) and Latch (read) Registers: */ -#define S626_LP_CNTR0ALSW 0x000C /* 0A lsw. */ -#define S626_LP_CNTR0AMSW 0x000E /* 0A msw. */ -#define S626_LP_CNTR0BLSW 0x0010 /* 0B lsw. */ -#define S626_LP_CNTR0BMSW 0x0012 /* 0B msw. */ -#define S626_LP_CNTR1ALSW 0x0014 /* 1A lsw. */ -#define S626_LP_CNTR1AMSW 0x0016 /* 1A msw. */ -#define S626_LP_CNTR1BLSW 0x0018 /* 1B lsw. */ -#define S626_LP_CNTR1BMSW 0x001A /* 1B msw. */ -#define S626_LP_CNTR2ALSW 0x001C /* 2A lsw. */ -#define S626_LP_CNTR2AMSW 0x001E /* 2A msw. */ -#define S626_LP_CNTR2BLSW 0x0020 /* 2B lsw. */ -#define S626_LP_CNTR2BMSW 0x0022 /* 2B msw. */ +/* Counter registers (read/write): 0A 1A 2A 0B 1B 2B */ +#define S626_LP_CRA(x) (0x0000 + (((x) % 3) * 0x4)) +#define S626_LP_CRB(x) (0x0002 + (((x) % 3) * 0x4)) + +/* Counter PreLoad (write) and Latch (read) Registers: 0A 1A 2A 0B 1B 2B */ +#define S626_LP_CNTR(x) (0x000c + (((x) < 3) ? 0x0 : 0x4) + \ + (((x) % 3) * 0x8)) /* Miscellaneous Registers (read/write): */ #define S626_LP_MISC1 0x0088 /* Read/write Misc1. */ diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index 441813ffb175..167f82418cb4 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -174,6 +174,7 @@ static int serial2002_tty_read(struct file *f, int timeout) } else { /* Device does not support poll, busy wait */ int retries = 0; + while (1) { retries++; if (retries >= timeout) @@ -311,6 +312,7 @@ static void serial2002_write(struct file *f, struct serial_data data) } else { unsigned char ch[6]; int i = 0; + if (data.value >= (1L << 30)) { ch[i] = 0x80 | ((data.value >> 30) & 0x03); i++; @@ -359,7 +361,8 @@ static int serial2002_setup_subdevice(struct comedi_subdevice *s, s->n_chan = chan; s->maxdata = 0; kfree(s->maxdata_list); - maxdata_list = kmalloc(sizeof(unsigned int) * s->n_chan, GFP_KERNEL); + maxdata_list = kmalloc_array(s->n_chan, sizeof(unsigned int), + GFP_KERNEL); if (!maxdata_list) return -ENOMEM; s->maxdata_list = maxdata_list; @@ -369,9 +372,8 @@ static int serial2002_setup_subdevice(struct comedi_subdevice *s, if (kind == 1 || kind == 2) { s->range_table = &range_digital; } else if (range) { - range_table_list = - kmalloc(sizeof(struct serial2002_range_table_t) * - s->n_chan, GFP_KERNEL); + range_table_list = kmalloc_array(s->n_chan, sizeof(*range), + GFP_KERNEL); if (!range_table_list) return -ENOMEM; s->range_table_list = range_table_list; @@ -420,67 +422,65 @@ static int serial2002_setup_subdevs(struct comedi_device *dev) serial2002_tty_setspeed(devpriv->tty, devpriv->speed); serial2002_poll_channel(devpriv->tty, 31); while (1) { - struct serial_data data; + struct serial_data data = serial2002_read(devpriv->tty, 1000); + int kind = S2002_CFG_KIND(data.value); + int channel = S2002_CFG_CHAN(data.value); + int range = S2002_CFG_BASE(data.value); + int cmd = S2002_CFG_CMD(data.value); - data = serial2002_read(devpriv->tty, 1000); if (data.kind != is_channel || data.index != 31 || - S2002_CFG_KIND(data.value) == S2002_CFG_KIND_INVALID) { + kind == S2002_CFG_KIND_INVALID) break; - } else { - int channel = S2002_CFG_CHAN(data.value); - int range = S2002_CFG_BASE(data.value); - switch (S2002_CFG_KIND(data.value)) { - case S2002_CFG_KIND_DIGITAL_IN: - cfg = di_cfg; - break; - case S2002_CFG_KIND_DIGITAL_OUT: - cfg = do_cfg; - break; - case S2002_CFG_KIND_ANALOG_IN: - cfg = ai_cfg; - break; - case S2002_CFG_KIND_ANALOG_OUT: - cfg = ao_cfg; - break; - case S2002_CFG_KIND_ENCODER_IN: - cfg = ai_cfg; - break; - default: - cfg = NULL; - break; - } - if (!cfg) - continue; /* unknown kind, skip it */ + switch (kind) { + case S2002_CFG_KIND_DIGITAL_IN: + cfg = di_cfg; + break; + case S2002_CFG_KIND_DIGITAL_OUT: + cfg = do_cfg; + break; + case S2002_CFG_KIND_ANALOG_IN: + cfg = ai_cfg; + break; + case S2002_CFG_KIND_ANALOG_OUT: + cfg = ao_cfg; + break; + case S2002_CFG_KIND_ENCODER_IN: + cfg = ai_cfg; + break; + default: + cfg = NULL; + break; + } + if (!cfg) + continue; /* unknown kind, skip it */ - cfg[channel].kind = S2002_CFG_KIND(data.value); + cfg[channel].kind = kind; - switch (S2002_CFG_CMD(data.value)) { - case S2002_CFG_CMD_BITS: - cfg[channel].bits = S2002_CFG_BITS(data.value); + switch (cmd) { + case S2002_CFG_CMD_BITS: + cfg[channel].bits = S2002_CFG_BITS(data.value); + break; + case S2002_CFG_CMD_MIN: + case S2002_CFG_CMD_MAX: + switch (S2002_CFG_UNITS(data.value)) { + case 0: + range *= 1000000; break; - case S2002_CFG_CMD_MIN: - case S2002_CFG_CMD_MAX: - switch (S2002_CFG_UNITS(data.value)) { - case 0: - range *= 1000000; - break; - case 1: - range *= 1000; - break; - case 2: - range *= 1; - break; - } - if (S2002_CFG_SIGN(data.value)) - range = -range; - if (S2002_CFG_CMD(data.value) == - S2002_CFG_CMD_MIN) - cfg[channel].min = range; - else - cfg[channel].max = range; + case 1: + range *= 1000; + break; + case 2: + range *= 1; break; } + if (S2002_CFG_SIGN(data.value)) + range = -range; + if (cmd == S2002_CFG_CMD_MIN) + cfg[channel].min = range; + else + cfg[channel].max = range; + break; } } diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c index 3bfa221faf4d..a118678c24a1 100644 --- a/drivers/staging/comedi/drivers/skel.c +++ b/drivers/staging/comedi/drivers/skel.c @@ -75,9 +75,6 @@ Configuration Options: #include "comedi_fc.h" /* Imaginary registers for the imaginary board */ - -#define SKEL_SIZE 0 - #define SKEL_START_AI_CONV 0 #define SKEL_AI_READ 0 @@ -129,7 +126,7 @@ struct skel_private { * convert ns nanoseconds to a counter value suitable for programming * the device. Also, it should adjust ns so that it cooresponds to * the actual time that the device will use. */ -static int skel_ns_to_timer(unsigned int *ns, int round) +static int skel_ns_to_timer(unsigned int *ns, unsigned int flags) { /* trivial timer */ /* if your timing is done through two cascaded timers, the @@ -287,12 +284,12 @@ static int skel_ai_cmdtest(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER) { arg = cmd->scan_begin_arg; - skel_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + skel_ns_to_timer(&arg, cmd->flags); err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg); } if (cmd->convert_src == TRIG_TIMER) { arg = cmd->convert_arg; - skel_ns_to_timer(&arg, cmd->flags & TRIG_ROUND_MASK); + skel_ns_to_timer(&arg, cmd->flags); err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); if (cmd->scan_begin_src == TRIG_TIMER) { diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c index adf7cb7086cc..7c2276a086ac 100644 --- a/drivers/staging/comedi/drivers/unioxx5.c +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -43,7 +43,6 @@ Devices: [Fastwel] UNIOxx-5 (unioxx5), #include <linux/delay.h> #include "../comedidev.h" -#define DRIVER_NAME "unioxx5" #define UNIOXX5_SIZE 0x10 #define UNIOXX5_SUBDEV_BASE 0xA000 /* base addr of first subdev */ #define UNIOXX5_SUBDEV_ODDS 0x400 @@ -496,7 +495,7 @@ static void unioxx5_detach(struct comedi_device *dev) } static struct comedi_driver unioxx5_driver = { - .driver_name = DRIVER_NAME, + .driver_name = "unioxx5", .module = THIS_MODULE, .attach = unioxx5_attach, .detach = unioxx5_detach, diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 5f65e4213c6e..053bc5090530 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1327,13 +1327,13 @@ static int usbdux_pwm_period(struct comedi_device *dev, struct usbdux_private *devpriv = dev->private; int fx2delay = 255; - if (period < MIN_PWM_PERIOD) { + if (period < MIN_PWM_PERIOD) return -EAGAIN; - } else { - fx2delay = (period / (6 * 512 * 1000 / 33)) - 6; - if (fx2delay > 255) - return -EAGAIN; - } + + fx2delay = (period / (6 * 512 * 1000 / 33)) - 6; + if (fx2delay > 255) + return -EAGAIN; + devpriv->pwm_delay = fx2delay; devpriv->pwm_period = period; diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index 85f9dcf59403..f85818dd5e11 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -33,8 +33,6 @@ * udev coldplug problem */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> @@ -275,8 +273,9 @@ static void usbduxfast_ai_interrupt(struct urb *urb) return; default: - pr_err("non-zero urb status received in ai intr context: %d\n", - urb->status); + dev_err(dev->class_dev, + "non-zero urb status received in ai intr context: %d\n", + urb->status); async->events |= COMEDI_CB_EOA; async->events |= COMEDI_CB_ERROR; comedi_event(dev, s); @@ -746,6 +745,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev, 0x00, (0xff - 0x02) & rngmask, 0x00); usbduxfast_cmd_data(dev, 6, 0x01, 0x00, rngmask, 0x00); + break; case 16: if (CR_RANGE(cmd->chanlist[0]) > 0) diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index ccc3ef7ba55c..94a09c16de8b 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -136,7 +136,7 @@ static const struct comedi_lrange usbduxsigma_ai_range = { 1, { - BIP_RANGE(2.65 / 2.0) + BIP_RANGE(2.5 * 0x800000 / 0x780000 / 2.0) } }; @@ -1176,13 +1176,13 @@ static int usbduxsigma_pwm_period(struct comedi_device *dev, struct usbduxsigma_private *devpriv = dev->private; int fx2delay = 255; - if (period < MIN_PWM_PERIOD) { + if (period < MIN_PWM_PERIOD) return -EAGAIN; - } else { - fx2delay = (period / (6 * 512 * 1000 / 33)) - 6; - if (fx2delay > 255) - return -EAGAIN; - } + + fx2delay = (period / (6 * 512 * 1000 / 33)) - 6; + if (fx2delay > 255) + return -EAGAIN; + devpriv->pwm_delay = fx2delay; devpriv->pwm_period = period; return 0; diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c index 0adf3cffddb0..831c3b702899 100644 --- a/drivers/staging/comedi/drivers/vmk80xx.c +++ b/drivers/staging/comedi/drivers/vmk80xx.c @@ -959,5 +959,4 @@ module_comedi_usb_driver(vmk80xx_driver, vmk80xx_usb_driver); MODULE_AUTHOR("Manuel Gebele <forensixs@gmx.de>"); MODULE_DESCRIPTION("Velleman USB Board Low-Level Driver"); MODULE_SUPPORTED_DEVICE("K8055/K8061 aka VM110/VM140"); -MODULE_VERSION("0.8.01"); MODULE_LICENSE("GPL"); |