diff options
Diffstat (limited to 'drivers/staging/comedi')
145 files changed, 10330 insertions, 12970 deletions
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 1967852eeb1..7871579bb83 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -230,9 +230,9 @@ config COMEDI_AMPLC_PC236_ISA config COMEDI_AMPLC_PC263_ISA tristate "Amplicon PC263 relay board support" - select COMEDI_AMPLC_PC263 ---help--- - Enable support for Amplicon PC263 ISA relay board. + Enable support for Amplicon PC263 ISA relay board. This board has + 16 reed relay output channels. To compile this driver as a module, choose M here: the module will be called amplc_pc263. @@ -484,6 +484,19 @@ config COMEDI_NI_ATMIO16D To compile this driver as a module, choose M here: the module will be called ni_atmio16d. +config COMEDI_NI_LABPC_ISA + tristate "NI Lab-PC and compatibles ISA support" + select COMEDI_NI_LABPC + depends on VIRT_TO_BUS + ---help--- + Enable support for National Instruments Lab-PC and compatibles + Lab-PC-1200, Lab-PC-1200AI, Lab-PC+. + Kernel-level ISA plug-and-play support for the lab-pc-1200 boards has + not yet been added to the driver. + + To compile this driver as a module, choose M here: the module will be + called ni_labpc. + config COMEDI_PCMAD tristate "Winsystems PCM-A/D12 and PCM-A/D16 PC/104 board support" ---help--- @@ -728,6 +741,16 @@ config COMEDI_ADV_PCI1723 To compile this driver as a module, choose M here: the module will be called adv_pci1723. +config COMEDI_ADV_PCI1724 + tristate "Advantech PCI-1724U support" + ---help--- + Enable support for Advantech PCI-1724U cards. These are 32-channel + analog output cards with voltage and current loop output ranges and + 14-bit resolution. + + To compile this driver as a module, choose M here: the module will be + called adv_pci1724. + config COMEDI_ADV_PCI_DIO tristate "Advantech PCI DIO card support" select COMEDI_8255 @@ -748,7 +771,7 @@ config COMEDI_AMPLC_DIO200_PCI and PCIe296 DIO boards. To compile this driver as a module, choose M here: the module will be - called amplc_dio200. + called amplc_dio200_pci. config COMEDI_AMPLC_PC236_PCI tristate "Amplicon PCI236 DIO board support" @@ -761,12 +784,12 @@ config COMEDI_AMPLC_PC236_PCI config COMEDI_AMPLC_PC263_PCI tristate "Amplicon PCI263 relay board support" - select COMEDI_AMPLC_PC263 ---help--- - Enable support for Amplicon PCI263 relay board. + Enable support for Amplicon PCI263 relay board. This is a PCI board + with 16 reed relay output channels. To compile this driver as a module, choose M here: the module will be - called amplc_pc263. + called amplc_pci263. config COMEDI_AMPLC_PCI224 tristate "Amplicon PCI224 and PCI234 support" @@ -983,7 +1006,7 @@ config COMEDI_NI_660X select COMEDI_NI_TIOCMD ---help--- Enable support for National Instruments PCI-6601 (ni_660x), PCI-6602, - PXI-6602 and PXI-6608. + PXI-6602, PXI-6608 and PXI-6624. To compile this driver as a module, choose M here: the module will be called ni_660x. @@ -997,20 +1020,15 @@ config COMEDI_NI_670X To compile this driver as a module, choose M here: the module will be called ni_670x. -config COMEDI_NI_LABPC - tristate "NI Lab-PC and compatibles ISA and PCI support" +config COMEDI_NI_LABPC_PCI + tristate "NI Lab-PC PCI-1200 support" + select COMEDI_NI_LABPC select COMEDI_MITE - select COMEDI_8255 - select COMEDI_FC - depends on VIRT_TO_BUS ---help--- - Enable support for National Instruments Lab-PC and compatibles - Lab-PC-1200, Lab-PC-1200AI, Lab-PC+ and PCI-1200. - Kernel-level ISA plug-and-play support for the lab-pc-1200 boards has - not yet been added to the driver. + Enable support for National Instruments Lab-PC PCI-1200. To compile this driver as a module, choose M here: the module will be - called ni_labpc. + called ni_labpc_pci. config COMEDI_NI_PCIDIO tristate "NI PCI-DIO32HS, PCI-6533, PCI-6534 support" @@ -1132,7 +1150,7 @@ config COMEDI_NI_DAQ_DIO24_CS config COMEDI_NI_LABPC_CS tristate "NI DAQCard-1200 PCMCIA support" - depends on COMEDI_NI_LABPC + select COMEDI_NI_LABPC ---help--- Enable support for the National Instruments PCMCIA DAQCard-1200 @@ -1241,12 +1259,14 @@ config COMEDI_AMPLC_PC236 tristate select COMEDI_8255 -config COMEDI_AMPLC_PC263 +config COMEDI_DAS08 tristate + select COMEDI_8255 -config COMEDI_DAS08 +config COMEDI_NI_LABPC tristate select COMEDI_8255 + select COMEDI_FC config COMEDI_NI_TIO tristate diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c index 9b997ae6779..ca709901fb3 100644 --- a/drivers/staging/comedi/comedi_buf.c +++ b/drivers/staging/comedi/comedi_buf.c @@ -192,7 +192,7 @@ unsigned int comedi_buf_write_alloc(struct comedi_async *async, { return __comedi_buf_write_alloc(async, nbytes, 0); } -EXPORT_SYMBOL(comedi_buf_write_alloc); +EXPORT_SYMBOL_GPL(comedi_buf_write_alloc); /* * munging is applied to data by core as it passes between user @@ -263,7 +263,7 @@ unsigned int comedi_buf_write_free(struct comedi_async *async, return nbytes; } -EXPORT_SYMBOL(comedi_buf_write_free); +EXPORT_SYMBOL_GPL(comedi_buf_write_free); unsigned int comedi_buf_read_n_available(struct comedi_async *async) { @@ -282,7 +282,7 @@ unsigned int comedi_buf_read_n_available(struct comedi_async *async) return num_bytes; } -EXPORT_SYMBOL(comedi_buf_read_n_available); +EXPORT_SYMBOL_GPL(comedi_buf_read_n_available); /* allocates a chunk for the reader from filled (and munged) buffer space */ unsigned int comedi_buf_read_alloc(struct comedi_async *async, @@ -304,7 +304,7 @@ unsigned int comedi_buf_read_alloc(struct comedi_async *async, return nbytes; } -EXPORT_SYMBOL(comedi_buf_read_alloc); +EXPORT_SYMBOL_GPL(comedi_buf_read_alloc); static unsigned int comedi_buf_read_n_allocated(struct comedi_async *async) { @@ -332,7 +332,7 @@ unsigned int comedi_buf_read_free(struct comedi_async *async, async->buf_read_ptr %= async->prealloc_bufsz; return nbytes; } -EXPORT_SYMBOL(comedi_buf_read_free); +EXPORT_SYMBOL_GPL(comedi_buf_read_free); int comedi_buf_put(struct comedi_async *async, short x) { @@ -346,7 +346,7 @@ int comedi_buf_put(struct comedi_async *async, short x) comedi_buf_write_free(async, sizeof(short)); return 1; } -EXPORT_SYMBOL(comedi_buf_put); +EXPORT_SYMBOL_GPL(comedi_buf_put); int comedi_buf_get(struct comedi_async *async, short *x) { @@ -359,7 +359,7 @@ int comedi_buf_get(struct comedi_async *async, short *x) comedi_buf_read_free(async, sizeof(short)); return 1; } -EXPORT_SYMBOL(comedi_buf_get); +EXPORT_SYMBOL_GPL(comedi_buf_get); void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset, const void *data, unsigned int num_bytes) @@ -385,7 +385,7 @@ void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset, write_ptr = 0; } } -EXPORT_SYMBOL(comedi_buf_memcpy_to); +EXPORT_SYMBOL_GPL(comedi_buf_memcpy_to); void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset, void *dest, unsigned int nbytes) @@ -412,4 +412,4 @@ void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset, read_ptr = 0; } } -EXPORT_SYMBOL(comedi_buf_memcpy_from); +EXPORT_SYMBOL_GPL(comedi_buf_memcpy_from); diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index e336b281b84..00f2547024e 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -49,9 +49,13 @@ #include "comedi_internal.h" +#define COMEDI_NUM_MINORS 0x100 +#define COMEDI_NUM_SUBDEVICE_MINORS \ + (COMEDI_NUM_MINORS - COMEDI_NUM_BOARD_MINORS) + #ifdef CONFIG_COMEDI_DEBUG int comedi_debug; -EXPORT_SYMBOL(comedi_debug); +EXPORT_SYMBOL_GPL(comedi_debug); module_param(comedi_debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(comedi_debug, "enable comedi core and driver debugging if non-zero (default 0)" @@ -77,57 +81,151 @@ MODULE_PARM_DESC(comedi_default_buf_maxsize_kb, "default maximum size of asynchronous buffer in KiB (default " __MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB) ")"); -struct comedi_file_info { - struct comedi_device *device; - struct comedi_subdevice *read_subdevice; - struct comedi_subdevice *write_subdevice; - struct device *hardware_device; -}; +static DEFINE_MUTEX(comedi_board_minor_table_lock); +static struct comedi_device +*comedi_board_minor_table[COMEDI_NUM_BOARD_MINORS]; + +static DEFINE_MUTEX(comedi_subdevice_minor_table_lock); +/* Note: indexed by minor - COMEDI_NUM_BOARD_MINORS. */ +static struct comedi_subdevice +*comedi_subdevice_minor_table[COMEDI_NUM_SUBDEVICE_MINORS]; + +static struct class *comedi_class; +static struct cdev comedi_cdev; + +static void comedi_device_init(struct comedi_device *dev) +{ + spin_lock_init(&dev->spinlock); + mutex_init(&dev->mutex); + dev->minor = -1; +} + +static void comedi_device_cleanup(struct comedi_device *dev) +{ + struct module *driver_module = NULL; + + if (dev == NULL) + return; + mutex_lock(&dev->mutex); + if (dev->attached) + driver_module = dev->driver->module; + comedi_device_detach(dev); + while (dev->use_count > 0) { + if (driver_module) + module_put(driver_module); + module_put(THIS_MODULE); + dev->use_count--; + } + mutex_unlock(&dev->mutex); + mutex_destroy(&dev->mutex); +} + +static bool comedi_clear_board_dev(struct comedi_device *dev) +{ + unsigned int i = dev->minor; + bool cleared = false; + + mutex_lock(&comedi_board_minor_table_lock); + if (dev == comedi_board_minor_table[i]) { + comedi_board_minor_table[i] = NULL; + cleared = true; + } + mutex_unlock(&comedi_board_minor_table_lock); + return cleared; +} + +static struct comedi_device *comedi_clear_board_minor(unsigned minor) +{ + struct comedi_device *dev; + + mutex_lock(&comedi_board_minor_table_lock); + dev = comedi_board_minor_table[minor]; + comedi_board_minor_table[minor] = NULL; + mutex_unlock(&comedi_board_minor_table_lock); + return dev; +} + +static void comedi_free_board_dev(struct comedi_device *dev) +{ + if (dev) { + if (dev->class_dev) { + device_destroy(comedi_class, + MKDEV(COMEDI_MAJOR, dev->minor)); + } + comedi_device_cleanup(dev); + kfree(dev); + } +} -static DEFINE_SPINLOCK(comedi_file_info_table_lock); -static struct comedi_file_info *comedi_file_info_table[COMEDI_NUM_MINORS]; +static struct comedi_subdevice +*comedi_subdevice_from_minor(unsigned minor) +{ + struct comedi_subdevice *s; + unsigned int i = minor - COMEDI_NUM_BOARD_MINORS; + + BUG_ON(i >= COMEDI_NUM_SUBDEVICE_MINORS); + mutex_lock(&comedi_subdevice_minor_table_lock); + s = comedi_subdevice_minor_table[i]; + mutex_unlock(&comedi_subdevice_minor_table_lock); + return s; +} -static struct comedi_file_info *comedi_file_info_from_minor(unsigned minor) +static struct comedi_device *comedi_dev_from_board_minor(unsigned minor) { - struct comedi_file_info *info; + struct comedi_device *dev; - BUG_ON(minor >= COMEDI_NUM_MINORS); - spin_lock(&comedi_file_info_table_lock); - info = comedi_file_info_table[minor]; - spin_unlock(&comedi_file_info_table_lock); - return info; + BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS); + mutex_lock(&comedi_board_minor_table_lock); + dev = comedi_board_minor_table[minor]; + mutex_unlock(&comedi_board_minor_table_lock); + return dev; } -static struct comedi_device * -comedi_dev_from_file_info(struct comedi_file_info *info) +static struct comedi_device *comedi_dev_from_subdevice_minor(unsigned minor) { - return info ? info->device : NULL; + struct comedi_subdevice *s; + + s = comedi_subdevice_from_minor(minor); + return s ? s->device : NULL; } struct comedi_device *comedi_dev_from_minor(unsigned minor) { - return comedi_dev_from_file_info(comedi_file_info_from_minor(minor)); + if (minor < COMEDI_NUM_BOARD_MINORS) + return comedi_dev_from_board_minor(minor); + else + return comedi_dev_from_subdevice_minor(minor); } EXPORT_SYMBOL_GPL(comedi_dev_from_minor); static struct comedi_subdevice * -comedi_read_subdevice(const struct comedi_file_info *info) +comedi_read_subdevice(const struct comedi_device *dev, unsigned int minor) { - if (info->read_subdevice) - return info->read_subdevice; - if (info->device) - return info->device->read_subdev; - return NULL; + struct comedi_subdevice *s; + + if (minor >= COMEDI_NUM_BOARD_MINORS) { + s = comedi_subdevice_from_minor(minor); + if (!s || s->device != dev) + return NULL; + if (s->subdev_flags & SDF_CMD_READ) + return s; + } + return dev->read_subdev; } static struct comedi_subdevice * -comedi_write_subdevice(const struct comedi_file_info *info) +comedi_write_subdevice(const struct comedi_device *dev, unsigned int minor) { - if (info->write_subdevice) - return info->write_subdevice; - if (info->device) - return info->device->write_subdev; - return NULL; + struct comedi_subdevice *s; + + if (minor >= COMEDI_NUM_BOARD_MINORS) { + s = comedi_subdevice_from_minor(minor); + if (!s || s->device != dev) + return NULL; + if (s->subdev_flags & SDF_CMD_WRITE) + return s; + } + return dev->write_subdev; } static int resize_async_buffer(struct comedi_device *dev, @@ -172,27 +270,34 @@ static int resize_async_buffer(struct comedi_device *dev, /* sysfs attribute files */ -static ssize_t show_max_read_buffer_kb(struct device *dev, +static ssize_t show_max_read_buffer_kb(struct device *csdev, struct device_attribute *attr, char *buf) { - struct comedi_file_info *info = dev_get_drvdata(dev); - struct comedi_subdevice *s = comedi_read_subdevice(info); + unsigned int minor = MINOR(csdev->devt); + struct comedi_device *dev; + struct comedi_subdevice *s; unsigned int size = 0; - mutex_lock(&info->device->mutex); + dev = comedi_dev_from_minor(minor); + if (!dev) + return -ENODEV; + + mutex_lock(&dev->mutex); + s = comedi_read_subdevice(dev, minor); if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) size = s->async->max_bufsize / 1024; - mutex_unlock(&info->device->mutex); + mutex_unlock(&dev->mutex); return snprintf(buf, PAGE_SIZE, "%i\n", size); } -static ssize_t store_max_read_buffer_kb(struct device *dev, +static ssize_t store_max_read_buffer_kb(struct device *csdev, struct device_attribute *attr, const char *buf, size_t count) { - struct comedi_file_info *info = dev_get_drvdata(dev); - struct comedi_subdevice *s = comedi_read_subdevice(info); + unsigned int minor = MINOR(csdev->devt); + struct comedi_device *dev; + struct comedi_subdevice *s; unsigned int size; int err; @@ -203,37 +308,49 @@ static ssize_t store_max_read_buffer_kb(struct device *dev, return -EINVAL; size *= 1024; - mutex_lock(&info->device->mutex); + dev = comedi_dev_from_minor(minor); + if (!dev) + return -ENODEV; + + mutex_lock(&dev->mutex); + s = comedi_read_subdevice(dev, minor); if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) s->async->max_bufsize = size; else err = -EINVAL; - mutex_unlock(&info->device->mutex); + mutex_unlock(&dev->mutex); return err ? err : count; } -static ssize_t show_read_buffer_kb(struct device *dev, +static ssize_t show_read_buffer_kb(struct device *csdev, struct device_attribute *attr, char *buf) { - struct comedi_file_info *info = dev_get_drvdata(dev); - struct comedi_subdevice *s = comedi_read_subdevice(info); + unsigned int minor = MINOR(csdev->devt); + struct comedi_device *dev; + struct comedi_subdevice *s; unsigned int size = 0; - mutex_lock(&info->device->mutex); + dev = comedi_dev_from_minor(minor); + if (!dev) + return -ENODEV; + + mutex_lock(&dev->mutex); + s = comedi_read_subdevice(dev, minor); if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) size = s->async->prealloc_bufsz / 1024; - mutex_unlock(&info->device->mutex); + mutex_unlock(&dev->mutex); return snprintf(buf, PAGE_SIZE, "%i\n", size); } -static ssize_t store_read_buffer_kb(struct device *dev, +static ssize_t store_read_buffer_kb(struct device *csdev, struct device_attribute *attr, const char *buf, size_t count) { - struct comedi_file_info *info = dev_get_drvdata(dev); - struct comedi_subdevice *s = comedi_read_subdevice(info); + unsigned int minor = MINOR(csdev->devt); + struct comedi_device *dev; + struct comedi_subdevice *s; unsigned int size; int err; @@ -244,38 +361,50 @@ static ssize_t store_read_buffer_kb(struct device *dev, return -EINVAL; size *= 1024; - mutex_lock(&info->device->mutex); + dev = comedi_dev_from_minor(minor); + if (!dev) + return -ENODEV; + + mutex_lock(&dev->mutex); + s = comedi_read_subdevice(dev, minor); if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) - err = resize_async_buffer(info->device, s, s->async, size); + err = resize_async_buffer(dev, s, s->async, size); else err = -EINVAL; - mutex_unlock(&info->device->mutex); + mutex_unlock(&dev->mutex); return err ? err : count; } -static ssize_t show_max_write_buffer_kb(struct device *dev, +static ssize_t show_max_write_buffer_kb(struct device *csdev, struct device_attribute *attr, char *buf) { - struct comedi_file_info *info = dev_get_drvdata(dev); - struct comedi_subdevice *s = comedi_write_subdevice(info); + unsigned int minor = MINOR(csdev->devt); + struct comedi_device *dev; + struct comedi_subdevice *s; unsigned int size = 0; - mutex_lock(&info->device->mutex); + dev = comedi_dev_from_minor(minor); + if (!dev) + return -ENODEV; + + mutex_lock(&dev->mutex); + s = comedi_write_subdevice(dev, minor); if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) size = s->async->max_bufsize / 1024; - mutex_unlock(&info->device->mutex); + mutex_unlock(&dev->mutex); return snprintf(buf, PAGE_SIZE, "%i\n", size); } -static ssize_t store_max_write_buffer_kb(struct device *dev, +static ssize_t store_max_write_buffer_kb(struct device *csdev, struct device_attribute *attr, const char *buf, size_t count) { - struct comedi_file_info *info = dev_get_drvdata(dev); - struct comedi_subdevice *s = comedi_write_subdevice(info); + unsigned int minor = MINOR(csdev->devt); + struct comedi_device *dev; + struct comedi_subdevice *s; unsigned int size; int err; @@ -286,37 +415,49 @@ static ssize_t store_max_write_buffer_kb(struct device *dev, return -EINVAL; size *= 1024; - mutex_lock(&info->device->mutex); + dev = comedi_dev_from_minor(minor); + if (!dev) + return -ENODEV; + + mutex_lock(&dev->mutex); + s = comedi_write_subdevice(dev, minor); if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) s->async->max_bufsize = size; else err = -EINVAL; - mutex_unlock(&info->device->mutex); + mutex_unlock(&dev->mutex); return err ? err : count; } -static ssize_t show_write_buffer_kb(struct device *dev, +static ssize_t show_write_buffer_kb(struct device *csdev, struct device_attribute *attr, char *buf) { - struct comedi_file_info *info = dev_get_drvdata(dev); - struct comedi_subdevice *s = comedi_write_subdevice(info); + unsigned int minor = MINOR(csdev->devt); + struct comedi_device *dev; + struct comedi_subdevice *s; unsigned int size = 0; - mutex_lock(&info->device->mutex); + dev = comedi_dev_from_minor(minor); + if (!dev) + return -ENODEV; + + mutex_lock(&dev->mutex); + s = comedi_write_subdevice(dev, minor); if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) size = s->async->prealloc_bufsz / 1024; - mutex_unlock(&info->device->mutex); + mutex_unlock(&dev->mutex); return snprintf(buf, PAGE_SIZE, "%i\n", size); } -static ssize_t store_write_buffer_kb(struct device *dev, +static ssize_t store_write_buffer_kb(struct device *csdev, struct device_attribute *attr, const char *buf, size_t count) { - struct comedi_file_info *info = dev_get_drvdata(dev); - struct comedi_subdevice *s = comedi_write_subdevice(info); + unsigned int minor = MINOR(csdev->devt); + struct comedi_device *dev; + struct comedi_subdevice *s; unsigned int size; int err; @@ -327,12 +468,17 @@ static ssize_t store_write_buffer_kb(struct device *dev, return -EINVAL; size *= 1024; - mutex_lock(&info->device->mutex); + dev = comedi_dev_from_minor(minor); + if (!dev) + return -ENODEV; + + mutex_lock(&dev->mutex); + s = comedi_write_subdevice(dev, minor); if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) - err = resize_async_buffer(info->device, s, s->async, size); + err = resize_async_buffer(dev, s, s->async, size); else err = -EINVAL; - mutex_unlock(&info->device->mutex); + mutex_unlock(&dev->mutex); return err ? err : count; } @@ -463,7 +609,6 @@ static int do_devconfig_ioctl(struct comedi_device *dev, struct comedi_devconfig __user *arg) { struct comedi_devconfig it; - int ret; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -490,15 +635,12 @@ static int do_devconfig_ioctl(struct comedi_device *dev, return -EINVAL; } - ret = comedi_device_attach(dev, &it); - if (ret == 0) { - if (!try_module_get(dev->driver->module)) { - comedi_device_detach(dev); - ret = -ENOSYS; - } - } + if (dev->minor >= comedi_num_legacy_minors) + /* don't re-use dynamically allocated comedi devices */ + return -EBUSY; - return ret; + /* This increments the driver module count on success. */ + return comedi_device_attach(dev, &it); } /* @@ -581,7 +723,6 @@ static int do_devinfo_ioctl(struct comedi_device *dev, struct file *file) { const unsigned minor = iminor(file_inode(file)); - struct comedi_file_info *info = comedi_file_info_from_minor(minor); struct comedi_subdevice *s; struct comedi_devinfo devinfo; @@ -593,13 +734,13 @@ static int do_devinfo_ioctl(struct comedi_device *dev, strlcpy(devinfo.driver_name, dev->driver->driver_name, COMEDI_NAMELEN); strlcpy(devinfo.board_name, dev->board_name, COMEDI_NAMELEN); - s = comedi_read_subdevice(info); + s = comedi_read_subdevice(dev, minor); if (s) devinfo.read_subdevice = s->index; else devinfo.read_subdevice = -1; - s = comedi_write_subdevice(info); + s = comedi_write_subdevice(dev, minor); if (s) devinfo.write_subdevice = s->index; else @@ -1616,8 +1757,7 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { const unsigned minor = iminor(file_inode(file)); - struct comedi_file_info *info = comedi_file_info_from_minor(minor); - struct comedi_device *dev = comedi_dev_from_file_info(info); + struct comedi_device *dev = comedi_dev_from_minor(minor); int rc; if (!dev) @@ -1635,9 +1775,18 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, } rc = do_devconfig_ioctl(dev, (struct comedi_devconfig __user *)arg); - if (rc == 0) - /* Evade comedi_auto_unconfig(). */ - info->hardware_device = NULL; + if (rc == 0) { + if (arg == 0 && + dev->minor >= comedi_num_legacy_minors) { + /* Successfully unconfigured a dynamically + * allocated device. Try and remove it. */ + if (comedi_clear_board_dev(dev)) { + mutex_unlock(&dev->mutex); + comedi_free_board_dev(dev); + return rc; + } + } + } goto done; } @@ -1744,8 +1893,7 @@ static struct vm_operations_struct comedi_vm_ops = { static int comedi_mmap(struct file *file, struct vm_area_struct *vma) { const unsigned minor = iminor(file_inode(file)); - struct comedi_file_info *info = comedi_file_info_from_minor(minor); - struct comedi_device *dev = comedi_dev_from_file_info(info); + struct comedi_device *dev = comedi_dev_from_minor(minor); struct comedi_subdevice *s; struct comedi_async *async; unsigned long start = vma->vm_start; @@ -1766,9 +1914,9 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) } if (vma->vm_flags & VM_WRITE) - s = comedi_write_subdevice(info); + s = comedi_write_subdevice(dev, minor); else - s = comedi_read_subdevice(info); + s = comedi_read_subdevice(dev, minor); if (!s) { retval = -EINVAL; goto done; @@ -1824,8 +1972,7 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait) { unsigned int mask = 0; const unsigned minor = iminor(file_inode(file)); - struct comedi_file_info *info = comedi_file_info_from_minor(minor); - struct comedi_device *dev = comedi_dev_from_file_info(info); + struct comedi_device *dev = comedi_dev_from_minor(minor); struct comedi_subdevice *s; if (!dev) @@ -1838,7 +1985,7 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait) goto done; } - s = comedi_read_subdevice(info); + s = comedi_read_subdevice(dev, minor); if (s && s->async) { poll_wait(file, &s->async->wait_head, wait); if (!s->busy || !comedi_is_subdevice_running(s) || @@ -1846,7 +1993,7 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait) mask |= POLLIN | POLLRDNORM; } - s = comedi_write_subdevice(info); + s = comedi_write_subdevice(dev, minor); if (s && s->async) { unsigned int bps = bytes_per_sample(s->async->subdevice); @@ -1870,8 +2017,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, int n, m, count = 0, retval = 0; DECLARE_WAITQUEUE(wait, current); const unsigned minor = iminor(file_inode(file)); - struct comedi_file_info *info = comedi_file_info_from_minor(minor); - struct comedi_device *dev = comedi_dev_from_file_info(info); + struct comedi_device *dev = comedi_dev_from_minor(minor); if (!dev) return -ENODEV; @@ -1881,7 +2027,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, return -ENODEV; } - s = comedi_write_subdevice(info); + s = comedi_write_subdevice(dev, minor); if (!s || !s->async) return -EIO; @@ -1965,8 +2111,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, int n, m, count = 0, retval = 0; DECLARE_WAITQUEUE(wait, current); const unsigned minor = iminor(file_inode(file)); - struct comedi_file_info *info = comedi_file_info_from_minor(minor); - struct comedi_device *dev = comedi_dev_from_file_info(info); + struct comedi_device *dev = comedi_dev_from_minor(minor); if (!dev) return -ENODEV; @@ -1976,7 +2121,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, return -ENODEV; } - s = comedi_read_subdevice(info); + s = comedi_read_subdevice(dev, minor); if (!s || !s->async) return -EIO; @@ -2067,12 +2212,12 @@ static int comedi_open(struct inode *inode, struct file *file) /* This is slightly hacky, but we want module autoloading * to work for root. * case: user opens device, attached -> ok - * case: user opens device, unattached, in_request_module=0 -> autoload - * case: user opens device, unattached, in_request_module=1 -> fail + * case: user opens device, unattached, !in_request_module -> autoload + * case: user opens device, unattached, in_request_module -> fail * case: root opens device, attached -> ok - * case: root opens device, unattached, in_request_module=1 -> ok + * case: root opens device, unattached, in_request_module -> ok * (typically called from modprobe) - * case: root opens device, unattached, in_request_module=0 -> autoload + * case: root opens device, unattached, !in_request_module -> autoload * * The last could be changed to "-> ok", which would deny root * autoloading. @@ -2088,7 +2233,7 @@ static int comedi_open(struct inode *inode, struct file *file) if (capable(CAP_NET_ADMIN) && dev->in_request_module) goto ok; - dev->in_request_module = 1; + dev->in_request_module = true; #ifdef CONFIG_KMOD mutex_unlock(&dev->mutex); @@ -2096,7 +2241,7 @@ static int comedi_open(struct inode *inode, struct file *file) mutex_lock(&dev->mutex); #endif - dev->in_request_module = 0; + dev->in_request_module = false; if (!dev->attached && !capable(CAP_NET_ADMIN)) { DPRINTK("not attached and not CAP_NET_ADMIN\n"); @@ -2195,14 +2340,11 @@ static const struct file_operations comedi_fops = { .llseek = noop_llseek, }; -static struct class *comedi_class; -static struct cdev comedi_cdev; - 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(comedi_error); +EXPORT_SYMBOL_GPL(comedi_error); void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s) { @@ -2245,150 +2387,104 @@ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s) } s->async->events = 0; } -EXPORT_SYMBOL(comedi_event); - -static void comedi_device_init(struct comedi_device *dev) -{ - memset(dev, 0, sizeof(*dev)); - spin_lock_init(&dev->spinlock); - mutex_init(&dev->mutex); - dev->minor = -1; -} - -static void comedi_device_cleanup(struct comedi_device *dev) -{ - if (dev == NULL) - return; - mutex_lock(&dev->mutex); - comedi_device_detach(dev); - mutex_unlock(&dev->mutex); - mutex_destroy(&dev->mutex); -} +EXPORT_SYMBOL_GPL(comedi_event); -int comedi_alloc_board_minor(struct device *hardware_device) +/* Note: the ->mutex is pre-locked on successful return */ +struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device) { - struct comedi_file_info *info; + struct comedi_device *dev; struct device *csdev; unsigned i; - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (info == NULL) - return -ENOMEM; - info->device = kzalloc(sizeof(struct comedi_device), GFP_KERNEL); - if (info->device == NULL) { - kfree(info); - return -ENOMEM; - } - info->hardware_device = hardware_device; - comedi_device_init(info->device); - spin_lock(&comedi_file_info_table_lock); - for (i = 0; i < COMEDI_NUM_BOARD_MINORS; ++i) { - if (comedi_file_info_table[i] == NULL) { - comedi_file_info_table[i] = info; + dev = kzalloc(sizeof(struct comedi_device), GFP_KERNEL); + if (dev == NULL) + return ERR_PTR(-ENOMEM); + comedi_device_init(dev); + comedi_set_hw_dev(dev, hardware_device); + mutex_lock(&dev->mutex); + mutex_lock(&comedi_board_minor_table_lock); + for (i = hardware_device ? comedi_num_legacy_minors : 0; + i < COMEDI_NUM_BOARD_MINORS; ++i) { + if (comedi_board_minor_table[i] == NULL) { + comedi_board_minor_table[i] = dev; break; } } - spin_unlock(&comedi_file_info_table_lock); + mutex_unlock(&comedi_board_minor_table_lock); if (i == COMEDI_NUM_BOARD_MINORS) { - comedi_device_cleanup(info->device); - kfree(info->device); - kfree(info); + mutex_unlock(&dev->mutex); + comedi_device_cleanup(dev); + kfree(dev); pr_err("comedi: error: ran out of minor numbers for board device files.\n"); - return -EBUSY; + return ERR_PTR(-EBUSY); } - info->device->minor = i; + dev->minor = i; csdev = device_create(comedi_class, hardware_device, MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i", i); if (!IS_ERR(csdev)) - info->device->class_dev = csdev; - dev_set_drvdata(csdev, info); + dev->class_dev = csdev; - return i; + /* Note: dev->mutex needs to be unlocked by the caller. */ + return dev; } -void comedi_free_board_minor(unsigned minor) +static void comedi_free_board_minor(unsigned minor) { - struct comedi_file_info *info; - BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS); - spin_lock(&comedi_file_info_table_lock); - info = comedi_file_info_table[minor]; - comedi_file_info_table[minor] = NULL; - spin_unlock(&comedi_file_info_table_lock); - - if (info) { - struct comedi_device *dev = info->device; - if (dev) { - if (dev->class_dev) { - device_destroy(comedi_class, - MKDEV(COMEDI_MAJOR, dev->minor)); - } - comedi_device_cleanup(dev); - kfree(dev); - } - kfree(info); - } + comedi_free_board_dev(comedi_clear_board_minor(minor)); } -int comedi_find_board_minor(struct device *hardware_device) +void comedi_release_hardware_device(struct device *hardware_device) { int minor; - struct comedi_file_info *info; - - for (minor = 0; minor < COMEDI_NUM_BOARD_MINORS; minor++) { - spin_lock(&comedi_file_info_table_lock); - info = comedi_file_info_table[minor]; - if (info && info->hardware_device == hardware_device) { - spin_unlock(&comedi_file_info_table_lock); - return minor; + struct comedi_device *dev; + + for (minor = comedi_num_legacy_minors; minor < COMEDI_NUM_BOARD_MINORS; + minor++) { + mutex_lock(&comedi_board_minor_table_lock); + dev = comedi_board_minor_table[minor]; + if (dev && dev->hw_dev == hardware_device) { + comedi_board_minor_table[minor] = NULL; + mutex_unlock(&comedi_board_minor_table_lock); + comedi_free_board_dev(dev); + break; } - spin_unlock(&comedi_file_info_table_lock); + mutex_unlock(&comedi_board_minor_table_lock); } - return -ENODEV; } int comedi_alloc_subdevice_minor(struct comedi_subdevice *s) { struct comedi_device *dev = s->device; - struct comedi_file_info *info; struct device *csdev; unsigned i; - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - info->device = dev; - if (s->subdev_flags & SDF_CMD_READ) - info->read_subdevice = s; - if (s->subdev_flags & SDF_CMD_WRITE) - info->write_subdevice = s; - spin_lock(&comedi_file_info_table_lock); - for (i = COMEDI_FIRST_SUBDEVICE_MINOR; i < COMEDI_NUM_MINORS; ++i) { - if (comedi_file_info_table[i] == NULL) { - comedi_file_info_table[i] = info; + mutex_lock(&comedi_subdevice_minor_table_lock); + for (i = 0; i < COMEDI_NUM_SUBDEVICE_MINORS; ++i) { + if (comedi_subdevice_minor_table[i] == NULL) { + comedi_subdevice_minor_table[i] = s; break; } } - spin_unlock(&comedi_file_info_table_lock); - if (i == COMEDI_NUM_MINORS) { - kfree(info); + 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"); return -EBUSY; } + i += COMEDI_NUM_BOARD_MINORS; s->minor = i; csdev = device_create(comedi_class, dev->class_dev, MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i_subd%i", dev->minor, s->index); if (!IS_ERR(csdev)) s->class_dev = csdev; - dev_set_drvdata(csdev, info); return 0; } void comedi_free_subdevice_minor(struct comedi_subdevice *s) { - struct comedi_file_info *info; + unsigned int i; if (s == NULL) return; @@ -2396,18 +2492,17 @@ void comedi_free_subdevice_minor(struct comedi_subdevice *s) return; BUG_ON(s->minor >= COMEDI_NUM_MINORS); - BUG_ON(s->minor < COMEDI_FIRST_SUBDEVICE_MINOR); - - spin_lock(&comedi_file_info_table_lock); - info = comedi_file_info_table[s->minor]; - comedi_file_info_table[s->minor] = NULL; - spin_unlock(&comedi_file_info_table_lock); + BUG_ON(s->minor < COMEDI_NUM_BOARD_MINORS); + i = s->minor - COMEDI_NUM_BOARD_MINORS; + mutex_lock(&comedi_subdevice_minor_table_lock); + if (s == comedi_subdevice_minor_table[i]) + comedi_subdevice_minor_table[i] = NULL; + mutex_unlock(&comedi_subdevice_minor_table_lock); if (s->class_dev) { device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, s->minor)); s->class_dev = NULL; } - kfree(info); } static void comedi_cleanup_board_minors(void) @@ -2432,9 +2527,6 @@ static int __init comedi_init(void) return -EINVAL; } - memset(comedi_file_info_table, 0, - sizeof(struct comedi_file_info *) * COMEDI_NUM_MINORS); - retval = register_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS, "comedi"); if (retval) @@ -2463,14 +2555,17 @@ static int __init comedi_init(void) /* create devices files for legacy/manual use */ for (i = 0; i < comedi_num_legacy_minors; i++) { - int minor; - minor = comedi_alloc_board_minor(NULL); - if (minor < 0) { + struct comedi_device *dev; + dev = comedi_alloc_board_minor(NULL); + if (IS_ERR(dev)) { comedi_cleanup_board_minors(); cdev_del(&comedi_cdev); unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS); - return minor; + return PTR_ERR(dev); + } else { + /* comedi_alloc_board_minor() locked the mutex */ + mutex_unlock(&dev->mutex); } } @@ -2483,8 +2578,10 @@ static void __exit comedi_cleanup(void) int i; comedi_cleanup_board_minors(); - for (i = 0; i < COMEDI_NUM_MINORS; ++i) - BUG_ON(comedi_file_info_table[i]); + for (i = 0; i < COMEDI_NUM_BOARD_MINORS; ++i) + BUG_ON(comedi_board_minor_table[i]); + for (i = 0; i < COMEDI_NUM_SUBDEVICE_MINORS; ++i) + BUG_ON(comedi_subdevice_minor_table[i]); class_destroy(comedi_class); cdev_del(&comedi_cdev); diff --git a/drivers/staging/comedi/comedi_internal.h b/drivers/staging/comedi/comedi_internal.h index b3743135f4a..d5e03e558b3 100644 --- a/drivers/staging/comedi/comedi_internal.h +++ b/drivers/staging/comedi/comedi_internal.h @@ -8,9 +8,8 @@ */ int do_rangeinfo_ioctl(struct comedi_device *dev, struct comedi_rangeinfo __user *arg); -int comedi_alloc_board_minor(struct device *hardware_device); -void comedi_free_board_minor(unsigned minor); -int comedi_find_board_minor(struct device *hardware_device); +struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device); +void comedi_release_hardware_device(struct device *hardware_device); int comedi_alloc_subdevice_minor(struct comedi_subdevice *s); void comedi_free_subdevice_minor(struct comedi_subdevice *s); diff --git a/drivers/staging/comedi/comedi_pci.c b/drivers/staging/comedi/comedi_pci.c index 37d2e467736..5fad084cfbd 100644 --- a/drivers/staging/comedi/comedi_pci.c +++ b/drivers/staging/comedi/comedi_pci.c @@ -36,20 +36,25 @@ EXPORT_SYMBOL_GPL(comedi_to_pci_dev); /** * comedi_pci_enable() - Enable the PCI device and request the regions. - * @pcidev: pci_dev struct - * @res_name: name for the requested reqource + * @dev: comedi_device struct */ -int comedi_pci_enable(struct pci_dev *pcidev, const char *res_name) +int comedi_pci_enable(struct comedi_device *dev) { + struct pci_dev *pcidev = comedi_to_pci_dev(dev); int rc; + if (!pcidev) + return -ENODEV; + rc = pci_enable_device(pcidev); if (rc < 0) return rc; - rc = pci_request_regions(pcidev, res_name); + rc = pci_request_regions(pcidev, dev->board_name); if (rc < 0) pci_disable_device(pcidev); + else + dev->ioenabled = true; return rc; } @@ -57,14 +62,17 @@ EXPORT_SYMBOL_GPL(comedi_pci_enable); /** * comedi_pci_disable() - Release the regions and disable the PCI device. - * @pcidev: pci_dev struct - * - * This must be matched with a previous successful call to comedi_pci_enable(). + * @dev: comedi_device struct */ -void comedi_pci_disable(struct pci_dev *pcidev) +void comedi_pci_disable(struct comedi_device *dev) { - pci_release_regions(pcidev); - pci_disable_device(pcidev); + struct pci_dev *pcidev = comedi_to_pci_dev(dev); + + if (pcidev && dev->ioenabled) { + pci_release_regions(pcidev); + pci_disable_device(pcidev); + } + dev->ioenabled = false; } EXPORT_SYMBOL_GPL(comedi_pci_disable); @@ -72,13 +80,15 @@ EXPORT_SYMBOL_GPL(comedi_pci_disable); * comedi_pci_auto_config() - Configure/probe a comedi PCI driver. * @pcidev: pci_dev struct * @driver: comedi_driver struct + * @context: driver specific data, passed to comedi_auto_config() * * Typically called from the pci_driver (*probe) function. */ int comedi_pci_auto_config(struct pci_dev *pcidev, - struct comedi_driver *driver) + struct comedi_driver *driver, + unsigned long context) { - return comedi_auto_config(&pcidev->dev, driver, 0); + return comedi_auto_config(&pcidev->dev, driver, context); } EXPORT_SYMBOL_GPL(comedi_pci_auto_config); diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index f3a990b45df..cdd472094ce 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -53,9 +53,7 @@ COMEDI_MINORVERSION, COMEDI_MICROVERSION) #define COMEDI_RELEASE VERSION -#define COMEDI_NUM_MINORS 0x100 #define COMEDI_NUM_BOARD_MINORS 0x30 -#define COMEDI_FIRST_SUBDEVICE_MINOR COMEDI_NUM_BOARD_MINORS struct comedi_subdevice { struct comedi_device *device; @@ -207,16 +205,18 @@ struct comedi_device { const char *board_name; const void *board_ptr; - int attached; + bool attached:1; + bool in_request_module:1; + bool ioenabled:1; spinlock_t spinlock; struct mutex mutex; - int in_request_module; int n_subdevices; struct comedi_subdevice *subdevices; /* dumb */ unsigned long iobase; + unsigned long iolen; unsigned int irq; struct comedi_subdevice *read_subdev; @@ -293,6 +293,10 @@ extern const struct comedi_lrange range_bipolar5; extern const struct comedi_lrange range_bipolar2_5; extern const struct comedi_lrange range_unipolar10; extern const struct comedi_lrange range_unipolar5; +extern const struct comedi_lrange range_unipolar2_5; +extern const struct comedi_lrange range_0_20mA; +extern const struct comedi_lrange range_4_20mA; +extern const struct comedi_lrange range_0_32mA; extern const struct comedi_lrange range_unknown; #define range_digital range_unipolar5 @@ -345,6 +349,14 @@ void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset, int comedi_alloc_subdevices(struct comedi_device *, int); +void comedi_spriv_free(struct comedi_device *, int subdev_num); + +int __comedi_request_region(struct comedi_device *, + unsigned long start, unsigned long len); +int comedi_request_region(struct comedi_device *, + unsigned long start, unsigned long len); +void comedi_legacy_detach(struct comedi_device *); + int comedi_auto_config(struct device *, struct comedi_driver *, unsigned long context); void comedi_auto_unconfig(struct device *); @@ -384,10 +396,11 @@ struct pci_driver; struct pci_dev *comedi_to_pci_dev(struct comedi_device *); -int comedi_pci_enable(struct pci_dev *, const char *); -void comedi_pci_disable(struct pci_dev *); +int comedi_pci_enable(struct comedi_device *); +void comedi_pci_disable(struct comedi_device *); -int comedi_pci_auto_config(struct pci_dev *, struct comedi_driver *); +int comedi_pci_auto_config(struct pci_dev *, struct comedi_driver *, + unsigned long context); void comedi_pci_auto_unconfig(struct pci_dev *); int comedi_pci_driver_register(struct comedi_driver *, struct pci_driver *); @@ -420,12 +433,12 @@ static inline struct pci_dev *comedi_to_pci_dev(struct comedi_device *dev) return NULL; } -static inline int comedi_pci_enable(struct pci_dev *dev, const char *name) +static inline int comedi_pci_enable(struct comedi_device *dev) { return -ENOSYS; } -static inline void comedi_pci_disable(struct pci_dev *dev) +static inline void comedi_pci_disable(struct comedi_device *dev) { } diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 64be7c5e891..06d190f8fd3 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -37,6 +37,7 @@ #include <linux/cdev.h> #include <linux/dma-mapping.h> #include <linux/io.h> +#include <linux/interrupt.h> #include "comedidev.h" #include "comedi_internal.h" @@ -86,6 +87,18 @@ int comedi_alloc_subdevices(struct comedi_device *dev, int num_subdevices) } EXPORT_SYMBOL_GPL(comedi_alloc_subdevices); +void comedi_spriv_free(struct comedi_device *dev, int subdev_num) +{ + struct comedi_subdevice *s; + + if (dev->subdevices && subdev_num < dev->n_subdevices) { + s = &dev->subdevices[subdev_num]; + kfree(s->private); + s->private = NULL; + } +} +EXPORT_SYMBOL_GPL(comedi_spriv_free); + static void cleanup_device(struct comedi_device *dev) { int i; @@ -110,6 +123,8 @@ static void cleanup_device(struct comedi_device *dev) dev->board_name = NULL; dev->board_ptr = NULL; dev->iobase = 0; + dev->iolen = 0; + dev->ioenabled = false; dev->irq = 0; dev->read_subdev = NULL; dev->write_subdev = NULL; @@ -118,24 +133,14 @@ static void cleanup_device(struct comedi_device *dev) comedi_clear_hw_dev(dev); } -static void __comedi_device_detach(struct comedi_device *dev) +void comedi_device_detach(struct comedi_device *dev) { - dev->attached = 0; + dev->attached = false; if (dev->driver) dev->driver->detach(dev); - else - dev_warn(dev->class_dev, - "BUG: dev->driver=NULL in comedi_device_detach()\n"); cleanup_device(dev); } -void comedi_device_detach(struct comedi_device *dev) -{ - if (!dev->attached) - return; - __comedi_device_detach(dev); -} - static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s) { return -EINVAL; @@ -276,21 +281,15 @@ static int __comedi_device_postconfig(struct comedi_device *dev) } /* do a little post-config cleanup */ -/* called with module refcount incremented, decrements it */ static int comedi_device_postconfig(struct comedi_device *dev) { - int ret = __comedi_device_postconfig(dev); - module_put(dev->driver->module); - if (ret < 0) { - __comedi_device_detach(dev); + int ret; + + ret = __comedi_device_postconfig(dev); + if (ret < 0) return ret; - } - if (!dev->board_name) { - dev_warn(dev->class_dev, "BUG: dev->board_name=NULL\n"); - dev->board_name = "BUG"; - } smp_wmb(); - dev->attached = 1; + dev->attached = true; return 0; } @@ -352,6 +351,71 @@ static void comedi_report_boards(struct comedi_driver *driv) pr_info(" %s\n", driv->driver_name); } +/** + * __comedi_request_region() - Request an I/O reqion for a legacy driver. + * @dev: comedi_device struct + * @start: base address of the I/O reqion + * @len: length of the I/O region + */ +int __comedi_request_region(struct comedi_device *dev, + unsigned long start, unsigned long len) +{ + if (!start) { + dev_warn(dev->class_dev, + "%s: a I/O base address must be specified\n", + dev->board_name); + return -EINVAL; + } + + if (!request_region(start, len, dev->board_name)) { + dev_warn(dev->class_dev, "%s: I/O port conflict (%#lx,%lu)\n", + dev->board_name, start, len); + return -EIO; + } + + return 0; +} +EXPORT_SYMBOL_GPL(__comedi_request_region); + +/** + * comedi_request_region() - Request an I/O reqion for a legacy driver. + * @dev: comedi_device struct + * @start: base address of the I/O reqion + * @len: length of the I/O region + */ +int comedi_request_region(struct comedi_device *dev, + unsigned long start, unsigned long len) +{ + int ret; + + ret = __comedi_request_region(dev, start, len); + if (ret == 0) { + dev->iobase = start; + dev->iolen = len; + } + + return ret; +} +EXPORT_SYMBOL_GPL(comedi_request_region); + +/** + * comedi_legacy_detach() - A generic (*detach) function for legacy drivers. + * @dev: comedi_device struct + */ +void comedi_legacy_detach(struct comedi_device *dev) +{ + if (dev->irq) { + free_irq(dev->irq, dev); + dev->irq = 0; + } + if (dev->iobase && dev->iolen) { + release_region(dev->iobase, dev->iolen); + dev->iobase = 0; + dev->iolen = 0; + } +} +EXPORT_SYMBOL_GPL(comedi_legacy_detach); + int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_driver *driv; @@ -393,22 +457,35 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* 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; ret = driv->attach(dev, it); + if (ret >= 0) + ret = comedi_device_postconfig(dev); if (ret < 0) { + comedi_device_detach(dev); module_put(dev->driver->module); - __comedi_device_detach(dev); - return ret; } - return comedi_device_postconfig(dev); + /* On success, the driver module count has been incremented. */ + return ret; } int comedi_auto_config(struct device *hardware_device, struct comedi_driver *driver, unsigned long context) { - int minor; - struct comedi_device *comedi_dev; + struct comedi_device *dev; int ret; + if (!hardware_device) { + pr_warn("BUG! comedi_auto_config called with NULL hardware_device\n"); + return -EINVAL; + } + if (!driver) { + dev_warn(hardware_device, + "BUG! comedi_auto_config called with NULL comedi driver\n"); + return -EINVAL; + } + if (!driver->auto_attach) { dev_warn(hardware_device, "BUG! comedi driver '%s' has no auto_attach handler\n", @@ -416,46 +493,31 @@ int comedi_auto_config(struct device *hardware_device, return -EINVAL; } - minor = comedi_alloc_board_minor(hardware_device); - if (minor < 0) - return minor; - - comedi_dev = comedi_dev_from_minor(minor); - - mutex_lock(&comedi_dev->mutex); - if (comedi_dev->attached) - ret = -EBUSY; - else if (!try_module_get(driver->module)) - ret = -EIO; - else { - comedi_set_hw_dev(comedi_dev, hardware_device); - comedi_dev->driver = driver; - ret = driver->auto_attach(comedi_dev, context); - if (ret < 0) { - module_put(driver->module); - __comedi_device_detach(comedi_dev); - } else { - ret = comedi_device_postconfig(comedi_dev); - } - } - mutex_unlock(&comedi_dev->mutex); + dev = comedi_alloc_board_minor(hardware_device); + if (IS_ERR(dev)) + return PTR_ERR(dev); + /* Note: comedi_alloc_board_minor() locked dev->mutex. */ + dev->driver = driver; + dev->board_name = dev->driver->driver_name; + ret = driver->auto_attach(dev, context); + if (ret >= 0) + ret = comedi_device_postconfig(dev); if (ret < 0) - comedi_free_board_minor(minor); + comedi_device_detach(dev); + mutex_unlock(&dev->mutex); + + if (ret < 0) + comedi_release_hardware_device(hardware_device); return ret; } EXPORT_SYMBOL_GPL(comedi_auto_config); void comedi_auto_unconfig(struct device *hardware_device) { - int minor; - if (hardware_device == NULL) return; - minor = comedi_find_board_minor(hardware_device); - if (minor < 0) - return; - comedi_free_board_minor(minor); + comedi_release_hardware_device(hardware_device); } EXPORT_SYMBOL_GPL(comedi_auto_unconfig); @@ -466,7 +528,7 @@ int comedi_driver_register(struct comedi_driver *driver) return 0; } -EXPORT_SYMBOL(comedi_driver_register); +EXPORT_SYMBOL_GPL(comedi_driver_register); int comedi_driver_unregister(struct comedi_driver *driver) { @@ -504,4 +566,4 @@ int comedi_driver_unregister(struct comedi_driver *driver) } return -EINVAL; } -EXPORT_SYMBOL(comedi_driver_unregister); +EXPORT_SYMBOL_GPL(comedi_driver_unregister); diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index c7aa41ad842..1d48aa602ec 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -129,7 +129,7 @@ void subdev_8255_interrupt(struct comedi_device *dev, comedi_event(dev, s); } -EXPORT_SYMBOL(subdev_8255_interrupt); +EXPORT_SYMBOL_GPL(subdev_8255_interrupt); static int subdev_8255_insn(struct comedi_device *dev, struct comedi_subdevice *s, @@ -314,7 +314,7 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, return 0; } -EXPORT_SYMBOL(subdev_8255_init); +EXPORT_SYMBOL_GPL(subdev_8255_init); int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice *s, int (*io) (int, int, int, unsigned long), @@ -332,13 +332,7 @@ int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice *s, return 0; } -EXPORT_SYMBOL(subdev_8255_init_irq); - -void subdev_8255_cleanup(struct comedi_device *dev, struct comedi_subdevice *s) -{ - kfree(s->private); -} -EXPORT_SYMBOL(subdev_8255_cleanup); +EXPORT_SYMBOL_GPL(subdev_8255_init_irq); /* @@ -354,8 +348,6 @@ static int dev_8255_attach(struct comedi_device *dev, unsigned long iobase; int i; - dev->board_name = "8255"; - for (i = 0; i < COMEDI_NDEVCONFOPTS; i++) { iobase = it->options[i]; if (!iobase) @@ -374,16 +366,13 @@ static int dev_8255_attach(struct comedi_device *dev, s = &dev->subdevices[i]; iobase = it->options[i]; - if (!request_region(iobase, _8255_SIZE, "8255")) { - dev_warn(dev->class_dev, - "0x%04lx (I/O port conflict)\n", iobase); - + ret = __comedi_request_region(dev, iobase, _8255_SIZE); + if (ret) { s->type = COMEDI_SUBD_UNUSED; } else { ret = subdev_8255_init(dev, s, NULL, iobase); if (ret) return ret; - dev_info(dev->class_dev, "0x%04lx\n", iobase); } } @@ -402,7 +391,7 @@ static void dev_8255_detach(struct comedi_device *dev) spriv = s->private; release_region(spriv->iobase, _8255_SIZE); } - subdev_8255_cleanup(dev, s); + comedi_spriv_free(dev, i); } } diff --git a/drivers/staging/comedi/drivers/8255.h b/drivers/staging/comedi/drivers/8255.h index 1e589b4b8b7..0f6e7492b7d 100644 --- a/drivers/staging/comedi/drivers/8255.h +++ b/drivers/staging/comedi/drivers/8255.h @@ -32,7 +32,6 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice *s, int (*io) (int, int, int, unsigned long), unsigned long iobase); -void subdev_8255_cleanup(struct comedi_device *dev, struct comedi_subdevice *s); void subdev_8255_interrupt(struct comedi_device *dev, struct comedi_subdevice *s); diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c index 0ae356ae56e..76dec96aeb2 100644 --- a/drivers/staging/comedi/drivers/8255_pci.c +++ b/drivers/staging/comedi/drivers/8255_pci.c @@ -60,126 +60,98 @@ Configuration Options: not applicable, uses PCI auto config #include "8255.h" -/* - * PCI Device ID's supported by this driver - */ -#define PCI_DEVICE_ID_ADLINK_PCI7224 0x7224 -#define PCI_DEVICE_ID_ADLINK_PCI7248 0x7248 -#define PCI_DEVICE_ID_ADLINK_PCI7296 0x7296 - -#define PCI_DEVICE_ID_CB_PCIDIO48H 0x000b -#define PCI_DEVICE_ID_CB_PCIDIO24H 0x0014 -#define PCI_DEVICE_ID_CB_PCIDIO96H 0x0017 -#define PCI_DEVICE_ID_CB_PCIDIO24 0x0028 - -#define PCI_DEVICE_ID_NI_PCIDIO96 0x0160 -#define PCI_DEVICE_ID_NI_PCI6503 0x0400 -#define PCI_DEVICE_ID_NI_PCI6503B 0x1250 -#define PCI_DEVICE_ID_NI_PXI6508 0x13c0 -#define PCI_DEVICE_ID_NI_PCIDIO96B 0x1630 -#define PCI_DEVICE_ID_NI_PCI6503X 0x17d0 -#define PCI_DEVICE_ID_NI_PXI_6503 0x1800 +enum pci_8255_boardid { + BOARD_ADLINK_PCI7224, + BOARD_ADLINK_PCI7248, + BOARD_ADLINK_PCI7296, + BOARD_CB_PCIDIO24, + BOARD_CB_PCIDIO24H, + BOARD_CB_PCIDIO48H, + BOARD_CB_PCIDIO96H, + BOARD_NI_PCIDIO96, + BOARD_NI_PCIDIO96B, + BOARD_NI_PXI6508, + BOARD_NI_PCI6503, + BOARD_NI_PCI6503B, + BOARD_NI_PCI6503X, + BOARD_NI_PXI_6503, +}; struct pci_8255_boardinfo { const char *name; - unsigned short vendor; - unsigned short device; int dio_badr; - int is_mmio; int n_8255; }; static const struct pci_8255_boardinfo pci_8255_boards[] = { - { + [BOARD_ADLINK_PCI7224] = { .name = "adl_pci-7224", - .vendor = PCI_VENDOR_ID_ADLINK, - .device = PCI_DEVICE_ID_ADLINK_PCI7224, .dio_badr = 2, .n_8255 = 1, - }, { + }, + [BOARD_ADLINK_PCI7248] = { .name = "adl_pci-7248", - .vendor = PCI_VENDOR_ID_ADLINK, - .device = PCI_DEVICE_ID_ADLINK_PCI7248, .dio_badr = 2, .n_8255 = 2, - }, { + }, + [BOARD_ADLINK_PCI7296] = { .name = "adl_pci-7296", - .vendor = PCI_VENDOR_ID_ADLINK, - .device = PCI_DEVICE_ID_ADLINK_PCI7296, .dio_badr = 2, .n_8255 = 4, - }, { + }, + [BOARD_CB_PCIDIO24] = { .name = "cb_pci-dio24", - .vendor = PCI_VENDOR_ID_CB, - .device = PCI_DEVICE_ID_CB_PCIDIO24, .dio_badr = 2, .n_8255 = 1, - }, { + }, + [BOARD_CB_PCIDIO24H] = { .name = "cb_pci-dio24h", - .vendor = PCI_VENDOR_ID_CB, - .device = PCI_DEVICE_ID_CB_PCIDIO24H, .dio_badr = 2, .n_8255 = 1, - }, { + }, + [BOARD_CB_PCIDIO48H] = { .name = "cb_pci-dio48h", - .vendor = PCI_VENDOR_ID_CB, - .device = PCI_DEVICE_ID_CB_PCIDIO48H, .dio_badr = 1, .n_8255 = 2, - }, { + }, + [BOARD_CB_PCIDIO96H] = { .name = "cb_pci-dio96h", - .vendor = PCI_VENDOR_ID_CB, - .device = PCI_DEVICE_ID_CB_PCIDIO96H, .dio_badr = 2, .n_8255 = 4, - }, { + }, + [BOARD_NI_PCIDIO96] = { .name = "ni_pci-dio-96", - .vendor = PCI_VENDOR_ID_NI, - .device = PCI_DEVICE_ID_NI_PCIDIO96, .dio_badr = 1, - .is_mmio = 1, .n_8255 = 4, - }, { + }, + [BOARD_NI_PCIDIO96B] = { .name = "ni_pci-dio-96b", - .vendor = PCI_VENDOR_ID_NI, - .device = PCI_DEVICE_ID_NI_PCIDIO96B, .dio_badr = 1, - .is_mmio = 1, .n_8255 = 4, - }, { + }, + [BOARD_NI_PXI6508] = { .name = "ni_pxi-6508", - .vendor = PCI_VENDOR_ID_NI, - .device = PCI_DEVICE_ID_NI_PXI6508, .dio_badr = 1, - .is_mmio = 1, .n_8255 = 4, - }, { + }, + [BOARD_NI_PCI6503] = { .name = "ni_pci-6503", - .vendor = PCI_VENDOR_ID_NI, - .device = PCI_DEVICE_ID_NI_PCI6503, .dio_badr = 1, - .is_mmio = 1, .n_8255 = 1, - }, { + }, + [BOARD_NI_PCI6503B] = { .name = "ni_pci-6503b", - .vendor = PCI_VENDOR_ID_NI, - .device = PCI_DEVICE_ID_NI_PCI6503B, .dio_badr = 1, - .is_mmio = 1, .n_8255 = 1, - }, { + }, + [BOARD_NI_PCI6503X] = { .name = "ni_pci-6503x", - .vendor = PCI_VENDOR_ID_NI, - .device = PCI_DEVICE_ID_NI_PCI6503X, .dio_badr = 1, - .is_mmio = 1, .n_8255 = 1, - }, { + }, + [BOARD_NI_PXI_6503] = { .name = "ni_pxi-6503", - .vendor = PCI_VENDOR_ID_NI, - .device = PCI_DEVICE_ID_NI_PXI_6503, .dio_badr = 1, - .is_mmio = 1, .n_8255 = 1, }, }; @@ -200,34 +172,19 @@ static int pci_8255_mmio(int dir, int port, int data, unsigned long iobase) } } -static const void *pci_8255_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct pci_8255_boardinfo *board; - int i; - - for (i = 0; i < ARRAY_SIZE(pci_8255_boards); i++) { - board = &pci_8255_boards[i]; - if (pcidev->vendor == board->vendor && - pcidev->device == board->device) - return board; - } - return NULL; -} - static int pci_8255_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct pci_8255_boardinfo *board; + const struct pci_8255_boardinfo *board = NULL; struct pci_8255_private *devpriv; struct comedi_subdevice *s; - resource_size_t iobase; - unsigned long len; + bool is_mmio; int ret; int i; - board = pci_8255_find_boardinfo(dev, pcidev); + if (context < ARRAY_SIZE(pci_8255_boards)) + board = &pci_8255_boards[context]; if (!board) return -ENODEV; dev->board_ptr = board; @@ -238,18 +195,19 @@ static int pci_8255_auto_attach(struct comedi_device *dev, return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; - iobase = pci_resource_start(pcidev, board->dio_badr); - len = pci_resource_len(pcidev, board->dio_badr); - if (board->is_mmio) { - devpriv->mmio_base = ioremap(iobase, len); + 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) return -ENOMEM; + } else { + dev->iobase = pci_resource_start(pcidev, board->dio_badr); } - dev->iobase = iobase; /* * One, two, or four subdevices are setup by this driver depending @@ -261,8 +219,10 @@ static int pci_8255_auto_attach(struct comedi_device *dev, return ret; for (i = 0; i < board->n_8255; i++) { + unsigned long iobase; + s = &dev->subdevices[i]; - if (board->is_mmio) { + if (is_mmio) { iobase = (unsigned long)(devpriv->mmio_base + (i * 4)); ret = subdev_8255_init(dev, s, pci_8255_mmio, iobase); } else { @@ -281,26 +241,14 @@ static int pci_8255_auto_attach(struct comedi_device *dev, static void pci_8255_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct pci_8255_boardinfo *board = comedi_board(dev); struct pci_8255_private *devpriv = dev->private; - struct comedi_subdevice *s; int i; - if (!board || !devpriv) - return; - if (dev->subdevices) { - for (i = 0; i < board->n_8255; i++) { - s = &dev->subdevices[i]; - subdev_8255_cleanup(dev, s); - } - } - if (pcidev) { - if (devpriv->mmio_base) - iounmap(devpriv->mmio_base); - if (dev->iobase) - comedi_pci_disable(pcidev); - } + for (i = 0; i < dev->n_subdevices; i++) + comedi_spriv_free(dev, i); + if (devpriv && devpriv->mmio_base) + iounmap(devpriv->mmio_base); + comedi_pci_disable(dev); } static struct comedi_driver pci_8255_driver = { @@ -311,26 +259,26 @@ static struct comedi_driver pci_8255_driver = { }; static int pci_8255_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &pci_8255_driver); + return comedi_pci_auto_config(dev, &pci_8255_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(pci_8255_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_ADLINK_PCI7224) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_ADLINK_PCI7248) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_ADLINK_PCI7296) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_CB_PCIDIO24) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_CB_PCIDIO24H) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_CB_PCIDIO48H) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_CB_PCIDIO96H) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCIDIO96) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCIDIO96B) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI6508) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI6503) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI6503B) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI6503X) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI_6503) }, + { PCI_VDEVICE(ADLINK, 0x7224), BOARD_ADLINK_PCI7224 }, + { PCI_VDEVICE(ADLINK, 0x7248), BOARD_ADLINK_PCI7248 }, + { PCI_VDEVICE(ADLINK, 0x7296), BOARD_ADLINK_PCI7296 }, + { PCI_VDEVICE(CB, 0x0028), BOARD_CB_PCIDIO24 }, + { PCI_VDEVICE(CB, 0x0014), BOARD_CB_PCIDIO24H }, + { PCI_VDEVICE(CB, 0x000b), BOARD_CB_PCIDIO48H }, + { PCI_VDEVICE(CB, 0x0017), BOARD_CB_PCIDIO96H }, + { PCI_VDEVICE(NI, 0x0160), BOARD_NI_PCIDIO96 }, + { PCI_VDEVICE(NI, 0x1630), BOARD_NI_PCIDIO96B }, + { PCI_VDEVICE(NI, 0x13c0), BOARD_NI_PXI6508 }, + { PCI_VDEVICE(NI, 0x0400), BOARD_NI_PCI6503 }, + { PCI_VDEVICE(NI, 0x1250), BOARD_NI_PCI6503B }, + { PCI_VDEVICE(NI, 0x17d0), BOARD_NI_PCI6503X }, + { PCI_VDEVICE(NI, 0x1800), BOARD_NI_PXI_6503 }, { 0 } }; MODULE_DEVICE_TABLE(pci, pci_8255_pci_table); diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile index 315e836ff99..57e984f0f46 100644 --- a/drivers/staging/comedi/drivers/Makefile +++ b/drivers/staging/comedi/drivers/Makefile @@ -12,6 +12,8 @@ obj-$(CONFIG_COMEDI_SKEL) += skel.o # Comedi ISA drivers obj-$(CONFIG_COMEDI_ACL7225B) += acl7225b.o +obj-$(CONFIG_COMEDI_AMPLC_DIO200_ISA) += amplc_dio200.o +obj-$(CONFIG_COMEDI_AMPLC_PC263_ISA) += amplc_pc263.o obj-$(CONFIG_COMEDI_PCL711) += pcl711.o obj-$(CONFIG_COMEDI_PCL724) += pcl724.o obj-$(CONFIG_COMEDI_PCL725) += pcl725.o @@ -75,10 +77,11 @@ obj-$(CONFIG_COMEDI_ADL_PCI9111) += adl_pci9111.o obj-$(CONFIG_COMEDI_ADL_PCI9118) += adl_pci9118.o obj-$(CONFIG_COMEDI_ADV_PCI1710) += adv_pci1710.o 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) += amplc_dio200.o +obj-$(CONFIG_COMEDI_AMPLC_DIO200_PCI) += amplc_dio200_pci.o obj-$(CONFIG_COMEDI_AMPLC_PC236) += amplc_pc236.o -obj-$(CONFIG_COMEDI_AMPLC_PC263) += amplc_pc263.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 obj-$(CONFIG_COMEDI_CONTEC_PCI_DIO) += contec_pci_dio.o @@ -103,6 +106,7 @@ obj-$(CONFIG_COMEDI_NI_6527) += ni_6527.o obj-$(CONFIG_COMEDI_NI_65XX) += ni_65xx.o obj-$(CONFIG_COMEDI_NI_660X) += ni_660x.o obj-$(CONFIG_COMEDI_NI_670X) += ni_670x.o +obj-$(CONFIG_COMEDI_NI_LABPC_PCI) += ni_labpc_pci.o obj-$(CONFIG_COMEDI_NI_PCIDIO) += ni_pcidio.o obj-$(CONFIG_COMEDI_NI_PCIMIO) += ni_pcimio.o obj-$(CONFIG_COMEDI_RTD520) += rtd520.o @@ -133,5 +137,6 @@ obj-$(CONFIG_COMEDI_NI_TIOCMD) += ni_tiocmd.o obj-$(CONFIG_COMEDI_NI_LABPC) += ni_labpc.o obj-$(CONFIG_COMEDI_8255) += 8255.o +obj-$(CONFIG_COMEDI_AMPLC_DIO200) += amplc_dio200_common.o obj-$(CONFIG_COMEDI_DAS08) += das08.o obj-$(CONFIG_COMEDI_FC) += comedi_fc.o diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c index 28c7fd3a96b..9e2c7aeea53 100644 --- a/drivers/staging/comedi/drivers/acl7225b.c +++ b/drivers/staging/comedi/drivers/acl7225b.c @@ -15,43 +15,59 @@ Devices: [Adlink] ACL-7225b (acl7225b), [ICP] P16R16DIO (p16r16dio) #include <linux/ioport.h> -#define ACL7225_SIZE 8 /* Requires 8 ioports, but only 4 are used */ -#define P16R16DIO_SIZE 4 #define ACL7225_RIO_LO 0 /* Relays input/output low byte (R0-R7) */ #define ACL7225_RIO_HI 1 /* Relays input/output high byte (R8-R15) */ #define ACL7225_DI_LO 2 /* Digital input low byte (DI0-DI7) */ #define ACL7225_DI_HI 3 /* Digital input high byte (DI8-DI15) */ -struct boardtype { - const char *name; /* driver name */ - int io_range; /* len of I/O space */ +struct acl7225b_boardinfo { + const char *name; + int io_range; }; -static int acl7225b_do_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static const struct acl7225b_boardinfo acl7225b_boards[] = { + { + .name = "acl7225b", + .io_range = 8, /* only 4 are used */ + }, { + .name = "p16r16dio", + .io_range = 4, + }, +}; + +static int acl7225b_do_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); + unsigned long reg = (unsigned long)s->private; + unsigned int mask = data[0]; + unsigned int bits = data[1]; + + if (mask) { + s->state &= ~mask; + s->state |= (bits & mask); + + if (mask & 0x00ff) + outb(s->state & 0xff, dev->iobase + reg); + if (mask & 0xff00) + outb((s->state >> 8), dev->iobase + reg + 1); } - if (data[0] & 0x00ff) - outb(s->state & 0xff, dev->iobase + (unsigned long)s->private); - if (data[0] & 0xff00) - outb((s->state >> 8), - dev->iobase + (unsigned long)s->private + 1); data[1] = s->state; return insn->n; } -static int acl7225b_di_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int acl7225b_di_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - data[1] = inb(dev->iobase + (unsigned long)s->private) | - (inb(dev->iobase + (unsigned long)s->private + 1) << 8); + unsigned long reg = (unsigned long)s->private; + + data[1] = inb(dev->iobase + reg) | + (inb(dev->iobase + reg + 1) << 8); return insn->n; } @@ -59,23 +75,13 @@ static int acl7225b_di_insn(struct comedi_device *dev, static int acl7225b_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - const struct boardtype *board = comedi_board(dev); + const struct acl7225b_boardinfo *board = comedi_board(dev); struct comedi_subdevice *s; - int iobase, iorange; int ret; - iobase = it->options[0]; - iorange = board->io_range; - printk(KERN_INFO "comedi%d: acl7225b: board=%s 0x%04x\n", dev->minor, - board->name, iobase); - if (!request_region(iobase, iorange, "acl7225b")) { - printk(KERN_ERR "comedi%d: request_region failed - I/O port conflict\n", - dev->minor); - return -EIO; - } - dev->board_name = board->name; - dev->iobase = iobase; - dev->irq = 0; + ret = comedi_request_region(dev, it->options[0], board->io_range); + if (ret) + return ret; ret = comedi_alloc_subdevices(dev, 3); if (ret) @@ -83,61 +89,48 @@ static int acl7225b_attach(struct comedi_device *dev, s = &dev->subdevices[0]; /* Relays outputs */ - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - s->maxdata = 1; - s->n_chan = 16; - s->insn_bits = acl7225b_do_insn; - s->range_table = &range_digital; - s->private = (void *)ACL7225_RIO_LO; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->maxdata = 1; + s->n_chan = 16; + s->insn_bits = acl7225b_do_insn_bits; + s->range_table = &range_digital; + s->private = (void *)ACL7225_RIO_LO; s = &dev->subdevices[1]; /* Relays status */ - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->maxdata = 1; - s->n_chan = 16; - s->insn_bits = acl7225b_di_insn; - s->range_table = &range_digital; - s->private = (void *)ACL7225_RIO_LO; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->maxdata = 1; + s->n_chan = 16; + s->insn_bits = acl7225b_di_insn_bits; + s->range_table = &range_digital; + s->private = (void *)ACL7225_RIO_LO; s = &dev->subdevices[2]; /* Isolated digital inputs */ - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->maxdata = 1; - s->n_chan = 16; - s->insn_bits = acl7225b_di_insn; - s->range_table = &range_digital; - s->private = (void *)ACL7225_DI_LO; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->maxdata = 1; + s->n_chan = 16; + s->insn_bits = acl7225b_di_insn_bits; + s->range_table = &range_digital; + s->private = (void *)ACL7225_DI_LO; return 0; } -static void acl7225b_detach(struct comedi_device *dev) -{ - const struct boardtype *board = comedi_board(dev); - - if (dev->iobase) - release_region(dev->iobase, board->io_range); -} - -static const struct boardtype boardtypes[] = { - { "acl7225b", ACL7225_SIZE, }, - { "p16r16dio", P16R16DIO_SIZE, }, -}; - static struct comedi_driver acl7225b_driver = { .driver_name = "acl7225b", .module = THIS_MODULE, .attach = acl7225b_attach, - .detach = acl7225b_detach, - .board_name = &boardtypes[0].name, - .num_names = ARRAY_SIZE(boardtypes), - .offset = sizeof(struct boardtype), + .detach = comedi_legacy_detach, + .board_name = &acl7225b_boards[0].name, + .num_names = ARRAY_SIZE(acl7225b_boards), + .offset = sizeof(struct acl7225b_boardinfo), }; module_comedi_driver(acl7225b_driver); +MODULE_DESCRIPTION("Comedi: NuDAQ ACL-7225B, 16 Relay & 16 Isolated DI Card"); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c index 1e05732e9f3..97e7eec343d 100644 --- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c @@ -704,9 +704,9 @@ static int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, | unsigned char *_ pb_ChannelStatus) | +----------------------------------------------------------------------------+ | Task : - (0) Set the digital output from selected SSI moule | + (0) Set the digital output from selected SSI module | | (b_ModuleNbr) ON - (1) Set the digital output from selected SSI moule | + (1) Set the digital output from selected SSI module | | (b_ModuleNbr) OFF (2)Read the status from selected SSI digital input | | (b_InputChannel) diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c index 1051fa5ce8f..0c3db57a50f 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_common.c +++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c @@ -84,37 +84,16 @@ static int i_ADDI_Reset(struct comedi_device *dev) return 0; } -static const void *addi_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const void *p = dev->driver->board_name; - const struct addi_board *this_board; - int i; - - for (i = 0; i < dev->driver->num_names; i++) { - this_board = p; - if (this_board->i_VendorId == pcidev->vendor && - this_board->i_DeviceId == pcidev->device) - return this_board; - p += dev->driver->offset; - } - return NULL; -} - static int addi_auto_attach(struct comedi_device *dev, unsigned long context_unused) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct addi_board *this_board; + const struct addi_board *this_board = comedi_board(dev); struct addi_private *devpriv; struct comedi_subdevice *s; int ret, n_subdevices; unsigned int dw_Dummy; - this_board = addi_find_boardinfo(dev, pcidev); - if (!this_board) - return -ENODEV; - dev->board_ptr = this_board; dev->board_name = this_board->pc_DriverName; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); @@ -122,7 +101,7 @@ static int addi_auto_attach(struct comedi_device *dev, return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; @@ -141,8 +120,7 @@ static int addi_auto_attach(struct comedi_device *dev, /* board has an ADDIDATA_9054 eeprom */ dev->iobase = pci_resource_start(pcidev, 2); devpriv->iobase = pci_resource_start(pcidev, 2); - devpriv->dw_AiBase = ioremap(pci_resource_start(pcidev, 3), - this_board->i_IorangeBase3); + devpriv->dw_AiBase = pci_ioremap_bar(pcidev, 3); } devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3); @@ -338,7 +316,6 @@ static int addi_auto_attach(struct comedi_device *dev, static void i_ADDI_Detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct addi_private *devpriv = dev->private; if (devpriv) { @@ -349,8 +326,5 @@ static void i_ADDI_Detach(struct comedi_device *dev) if (devpriv->dw_AiBase) iounmap(devpriv->dw_AiBase); } - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } + comedi_pci_disable(dev); } diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h index 6d8b29f945d..c034bf1426e 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_common.h +++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h @@ -45,12 +45,7 @@ /* structure for the boardtype */ struct addi_board { const char *pc_DriverName; /* driver name */ - int i_VendorId; /* PCI vendor a device ID of card */ - int i_DeviceId; - int i_IorangeBase0; int i_IorangeBase1; - int i_IorangeBase2; /* base 2 range */ - int i_IorangeBase3; /* base 3 range */ int i_PCIEeprom; /* eeprom present or not */ char *pc_EepromChip; /* type of chip */ int i_NbrAiChannel; /* num of A/D chans */ diff --git a/drivers/staging/comedi/drivers/addi_apci_035.c b/drivers/staging/comedi/drivers/addi_apci_035.c index 5a53e58258a..43c2c10a7c3 100644 --- a/drivers/staging/comedi/drivers/addi_apci_035.c +++ b/drivers/staging/comedi/drivers/addi_apci_035.c @@ -15,9 +15,6 @@ static const struct addi_board apci035_boardtypes[] = { { .pc_DriverName = "apci035", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x0300, - .i_IorangeBase0 = 127, .i_IorangeBase1 = APCI035_ADDRESS_RANGE, .i_PCIEeprom = 1, .pc_EepromChip = ADDIDATA_S5920, @@ -39,20 +36,25 @@ static const struct addi_board apci035_boardtypes[] = { }, }; +static int apci035_auto_attach(struct comedi_device *dev, + unsigned long context) +{ + dev->board_ptr = &apci035_boardtypes[0]; + + return addi_auto_attach(dev, context); +} + static struct comedi_driver apci035_driver = { .driver_name = "addi_apci_035", .module = THIS_MODULE, - .auto_attach = addi_auto_attach, + .auto_attach = apci035_auto_attach, .detach = i_ADDI_Detach, - .num_names = ARRAY_SIZE(apci035_boardtypes), - .board_name = &apci035_boardtypes[0].pc_DriverName, - .offset = sizeof(struct addi_board), }; static int apci035_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &apci035_driver); + return comedi_pci_auto_config(dev, &apci035_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(apci035_pci_table) = { diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c index c0d0429c35c..3d4878facc2 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1032.c +++ b/drivers/staging/comedi/drivers/addi_apci_1032.c @@ -296,14 +296,12 @@ static int apci1032_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - dev->board_name = dev->driver->driver_name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; @@ -353,16 +351,11 @@ static int apci1032_auto_attach(struct comedi_device *dev, static void apci1032_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (dev->iobase) apci1032_reset(dev); if (dev->irq) free_irq(dev->irq, dev); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } + comedi_pci_disable(dev); } static struct comedi_driver apci1032_driver = { @@ -373,9 +366,9 @@ static struct comedi_driver apci1032_driver = { }; static int apci1032_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &apci1032_driver); + return comedi_pci_auto_config(dev, &apci1032_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(apci1032_pci_table) = { diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index 9c2f8eeb797..b52cfe01e6c 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -13,11 +13,7 @@ static const struct addi_board apci1500_boardtypes[] = { { .pc_DriverName = "apci1500", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA_OLD, - .i_DeviceId = 0x80fc, - .i_IorangeBase0 = 128, .i_IorangeBase1 = APCI1500_ADDRESS_RANGE, - .i_IorangeBase2 = 4, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .i_NbrDiChannel = 16, .i_NbrDoChannel = 16, @@ -39,24 +35,29 @@ static const struct addi_board apci1500_boardtypes[] = { }, }; +static int apci1500_auto_attach(struct comedi_device *dev, + unsigned long context) +{ + dev->board_ptr = &apci1500_boardtypes[0]; + + return addi_auto_attach(dev, context); +} + static struct comedi_driver apci1500_driver = { .driver_name = "addi_apci_1500", .module = THIS_MODULE, - .auto_attach = addi_auto_attach, + .auto_attach = apci1500_auto_attach, .detach = i_ADDI_Detach, - .num_names = ARRAY_SIZE(apci1500_boardtypes), - .board_name = &apci1500_boardtypes[0].pc_DriverName, - .offset = sizeof(struct addi_board), }; static int apci1500_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &apci1500_driver); + return comedi_pci_auto_config(dev, &apci1500_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(apci1500_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA_OLD, 0x80fc) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMCC, 0x80fc) }, { 0 } }; MODULE_DEVICE_TABLE(pci, apci1500_pci_table); diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c index 69e39963841..ed01c56630b 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1516.c +++ b/drivers/staging/comedi/drivers/addi_apci_1516.c @@ -36,13 +36,6 @@ #include "comedi_fc.h" /* - * PCI device ids supported by this driver - */ -#define PCI_DEVICE_ID_APCI1016 0x1000 -#define PCI_DEVICE_ID_APCI1516 0x1001 -#define PCI_DEVICE_ID_APCI2016 0x1002 - -/* * PCI bar 1 I/O Register map - Digital input/output */ #define APCI1516_DI_REG 0x00 @@ -53,28 +46,32 @@ */ #define APCI1516_WDOG_REG 0x00 +enum apci1516_boardid { + BOARD_APCI1016, + BOARD_APCI1516, + BOARD_APCI2016, +}; + struct apci1516_boardinfo { const char *name; - unsigned short device; int di_nchan; int do_nchan; int has_wdog; }; static const struct apci1516_boardinfo apci1516_boardtypes[] = { - { + [BOARD_APCI1016] = { .name = "apci1016", - .device = PCI_DEVICE_ID_APCI1016, .di_nchan = 16, - }, { + }, + [BOARD_APCI1516] = { .name = "apci1516", - .device = PCI_DEVICE_ID_APCI1516, .di_nchan = 8, .do_nchan = 8, .has_wdog = 1, - }, { + }, + [BOARD_APCI2016] = { .name = "apci2016", - .device = PCI_DEVICE_ID_APCI2016, .do_nchan = 16, .has_wdog = 1, }, @@ -130,30 +127,17 @@ static int apci1516_reset(struct comedi_device *dev) return 0; } -static const void *apci1516_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct apci1516_boardinfo *this_board; - int i; - - for (i = 0; i < dev->driver->num_names; i++) { - this_board = &apci1516_boardtypes[i]; - if (this_board->device == pcidev->device) - return this_board; - } - return NULL; -} - static int apci1516_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct apci1516_boardinfo *this_board; + const struct apci1516_boardinfo *this_board = NULL; struct apci1516_private *devpriv; struct comedi_subdevice *s; int ret; - this_board = apci1516_find_boardinfo(dev, pcidev); + if (context < ARRAY_SIZE(apci1516_boardtypes)) + this_board = &apci1516_boardtypes[context]; if (!this_board) return -ENODEV; dev->board_ptr = this_board; @@ -164,7 +148,7 @@ static int apci1516_auto_attach(struct comedi_device *dev, return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; @@ -217,14 +201,10 @@ static int apci1516_auto_attach(struct comedi_device *dev, static void apci1516_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (dev->iobase) apci1516_reset(dev); - if (dev->subdevices) - addi_watchdog_cleanup(&dev->subdevices[2]); - if (dev->iobase) - comedi_pci_disable(pcidev); + comedi_spriv_free(dev, 2); + comedi_pci_disable(dev); } static struct comedi_driver apci1516_driver = { @@ -235,15 +215,15 @@ static struct comedi_driver apci1516_driver = { }; static int apci1516_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &apci1516_driver); + return comedi_pci_auto_config(dev, &apci1516_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(apci1516_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, PCI_DEVICE_ID_APCI1016) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, PCI_DEVICE_ID_APCI1516) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, PCI_DEVICE_ID_APCI2016) }, + { PCI_VDEVICE(ADDIDATA, 0x1000), BOARD_APCI1016 }, + { PCI_VDEVICE(ADDIDATA, 0x1001), BOARD_APCI1516 }, + { PCI_VDEVICE(ADDIDATA, 0x1002), BOARD_APCI2016 }, { 0 } }; MODULE_DEVICE_TABLE(pci, apci1516_pci_table); diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c index ddea64df918..22bace62210 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1564.c +++ b/drivers/staging/comedi/drivers/addi_apci_1564.c @@ -13,9 +13,6 @@ static const struct addi_board apci1564_boardtypes[] = { { .pc_DriverName = "apci1564", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x1006, - .i_IorangeBase0 = 128, .i_IorangeBase1 = APCI1564_ADDRESS_RANGE, .i_PCIEeprom = ADDIDATA_EEPROM, .pc_EepromChip = ADDIDATA_93C76, @@ -36,20 +33,25 @@ static const struct addi_board apci1564_boardtypes[] = { }, }; +static int apci1564_auto_attach(struct comedi_device *dev, + unsigned long context) +{ + dev->board_ptr = &apci1564_boardtypes[0]; + + return addi_auto_attach(dev, context); +} + static struct comedi_driver apci1564_driver = { .driver_name = "addi_apci_1564", .module = THIS_MODULE, - .auto_attach = addi_auto_attach, + .auto_attach = apci1564_auto_attach, .detach = i_ADDI_Detach, - .num_names = ARRAY_SIZE(apci1564_boardtypes), - .board_name = &apci1564_boardtypes[0].pc_DriverName, - .offset = sizeof(struct addi_board), }; static int apci1564_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &apci1564_driver); + return comedi_pci_auto_config(dev, &apci1564_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(apci1564_pci_table) = { diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c index e51f8000136..4c6a9b5a06a 100644 --- a/drivers/staging/comedi/drivers/addi_apci_16xx.c +++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c @@ -34,35 +34,29 @@ #include "../comedidev.h" /* - * PCI device ids supported by this driver - */ -#define PCI_DEVICE_ID_APCI1648 0x1009 -#define PCI_DEVICE_ID_APCI1696 0x100a - -/* * Register I/O map */ #define APCI16XX_IN_REG(x) (((x) * 4) + 0x08) #define APCI16XX_OUT_REG(x) (((x) * 4) + 0x14) #define APCI16XX_DIR_REG(x) (((x) * 4) + 0x20) +enum apci16xx_boardid { + BOARD_APCI1648, + BOARD_APCI1696, +}; + struct apci16xx_boardinfo { const char *name; - unsigned short vendor; - unsigned short device; int n_chan; }; static const struct apci16xx_boardinfo apci16xx_boardtypes[] = { - { + [BOARD_APCI1648] = { .name = "apci1648", - .vendor = PCI_VENDOR_ID_ADDIDATA, - .device = PCI_DEVICE_ID_APCI1648, .n_chan = 48, /* 2 subdevices */ - }, { + }, + [BOARD_APCI1696] = { .name = "apci1696", - .vendor = PCI_VENDOR_ID_ADDIDATA, - .device = PCI_DEVICE_ID_APCI1696, .n_chan = 96, /* 3 subdevices */ }, }; @@ -130,39 +124,25 @@ static int apci16xx_dio_insn_bits(struct comedi_device *dev, return insn->n; } -static const void *apci16xx_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct apci16xx_boardinfo *board; - int i; - - for (i = 0; i < ARRAY_SIZE(apci16xx_boardtypes); i++) { - board = &apci16xx_boardtypes[i]; - if (board->vendor == pcidev->vendor && - board->device == pcidev->device) - return board; - } - return NULL; -} - static int apci16xx_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct apci16xx_boardinfo *board; + const struct apci16xx_boardinfo *board = NULL; struct comedi_subdevice *s; unsigned int n_subdevs; unsigned int last; int i; int ret; - board = apci16xx_find_boardinfo(dev, pcidev); + if (context < ARRAY_SIZE(apci16xx_boardtypes)) + board = &apci16xx_boardtypes[context]; if (!board) return -ENODEV; dev->board_ptr = board; dev->board_name = board->name; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; @@ -204,35 +184,22 @@ static int apci16xx_auto_attach(struct comedi_device *dev, return 0; } -static void apci16xx_detach(struct comedi_device *dev) -{ - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } -} - static struct comedi_driver apci16xx_driver = { .driver_name = "addi_apci_16xx", .module = THIS_MODULE, .auto_attach = apci16xx_auto_attach, - .detach = apci16xx_detach, - .num_names = ARRAY_SIZE(apci16xx_boardtypes), - .board_name = &apci16xx_boardtypes[0].name, - .offset = sizeof(struct apci16xx_boardinfo), + .detach = comedi_pci_disable, }; static int apci16xx_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &apci16xx_driver); + return comedi_pci_auto_config(dev, &apci16xx_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(apci16xx_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, PCI_DEVICE_ID_APCI1648) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, PCI_DEVICE_ID_APCI1696) }, + { PCI_VDEVICE(ADDIDATA, 0x1009), BOARD_APCI1648 }, + { PCI_VDEVICE(ADDIDATA, 0x100a), BOARD_APCI1696 }, { 0 } }; MODULE_DEVICE_TABLE(pci, apci16xx_pci_table); diff --git a/drivers/staging/comedi/drivers/addi_apci_1710.c b/drivers/staging/comedi/drivers/addi_apci_1710.c index e83e829831b..c9e6471eb06 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1710.c +++ b/drivers/staging/comedi/drivers/addi_apci_1710.c @@ -21,72 +21,29 @@ static void fpu_end(void) #include "addi-data/addi_eeprom.c" #include "addi-data/hwdrv_APCI1710.c" -static const struct addi_board apci1710_boardtypes[] = { - { - .pc_DriverName = "apci1710", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA_OLD, - .i_DeviceId = APCI1710_BOARD_DEVICE_ID, - .interrupt = v_APCI1710_Interrupt, - }, -}; - static irqreturn_t v_ADDI_Interrupt(int irq, void *d) { - struct comedi_device *dev = d; - const struct addi_board *this_board = comedi_board(dev); - - this_board->interrupt(irq, d); + v_APCI1710_Interrupt(irq, d); return IRQ_RETVAL(1); } -static const void *apci1710_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct addi_board *this_board; - int i; - - for (i = 0; i < ARRAY_SIZE(apci1710_boardtypes); i++) { - this_board = &apci1710_boardtypes[i]; - if (this_board->i_VendorId == pcidev->vendor && - this_board->i_DeviceId == pcidev->device) - return this_board; - } - return NULL; -} - static int apci1710_auto_attach(struct comedi_device *dev, unsigned long context_unused) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct addi_board *this_board; struct addi_private *devpriv; struct comedi_subdevice *s; int ret; - this_board = apci1710_find_boardinfo(dev, pcidev); - if (!this_board) - return -ENODEV; - dev->board_ptr = this_board; - dev->board_name = this_board->pc_DriverName; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; - - if (this_board->i_IorangeBase1) - dev->iobase = pci_resource_start(pcidev, 1); - else - dev->iobase = pci_resource_start(pcidev, 0); - - devpriv->iobase = dev->iobase; - devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0); - devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2); - devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3); + devpriv->s_BoardInfos.ui_Address = pci_resource_start(pcidev, 2); if (pcidev->irq > 0) { ret = request_irq(pcidev->irq, v_ADDI_Interrupt, IRQF_SHARED, @@ -97,24 +54,17 @@ static int apci1710_auto_attach(struct comedi_device *dev, i_ADDI_AttachPCI1710(dev); - devpriv->s_BoardInfos.ui_Address = pci_resource_start(pcidev, 2); - i_APCI1710_Reset(dev); return 0; } static void apci1710_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (dev->iobase) i_APCI1710_Reset(dev); if (dev->irq) free_irq(dev->irq, dev); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } + comedi_pci_disable(dev); } static struct comedi_driver apci1710_driver = { @@ -125,13 +75,13 @@ static struct comedi_driver apci1710_driver = { }; static int apci1710_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &apci1710_driver); + return comedi_pci_auto_config(dev, &apci1710_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(apci1710_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA_OLD, APCI1710_BOARD_DEVICE_ID) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMCC, APCI1710_BOARD_DEVICE_ID) }, { 0 } }; MODULE_DEVICE_TABLE(pci, apci1710_pci_table); diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c index 9ce1d26aff2..b666637f61b 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2032.c +++ b/drivers/staging/comedi/drivers/addi_apci_2032.c @@ -287,9 +287,7 @@ static int apci2032_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - dev->board_name = dev->driver->driver_name; - - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pcidev, 1); @@ -350,20 +348,14 @@ static int apci2032_auto_attach(struct comedi_device *dev, static void apci2032_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (dev->iobase) apci2032_reset(dev); if (dev->irq) free_irq(dev->irq, dev); if (dev->read_subdev) kfree(dev->read_subdev->private); - if (dev->subdevices) - addi_watchdog_cleanup(&dev->subdevices[1]); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } + comedi_spriv_free(dev, 1); + comedi_pci_disable(dev); } static struct comedi_driver apci2032_driver = { @@ -374,9 +366,9 @@ static struct comedi_driver apci2032_driver = { }; static int apci2032_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &apci2032_driver); + return comedi_pci_auto_config(dev, &apci2032_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(apci2032_pci_table) = { diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c index b1c4226902e..1cdc08d7979 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2200.c +++ b/drivers/staging/comedi/drivers/addi_apci_2200.c @@ -88,9 +88,7 @@ static int apci2200_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - dev->board_name = dev->driver->driver_name; - - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; @@ -130,16 +128,10 @@ static int apci2200_auto_attach(struct comedi_device *dev, static void apci2200_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (dev->iobase) apci2200_reset(dev); - if (dev->subdevices) - addi_watchdog_cleanup(&dev->subdevices[2]); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } + comedi_spriv_free(dev, 2); + comedi_pci_disable(dev); } static struct comedi_driver apci2200_driver = { @@ -150,9 +142,9 @@ static struct comedi_driver apci2200_driver = { }; static int apci2200_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &apci2200_driver); + return comedi_pci_auto_config(dev, &apci2200_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(apci2200_pci_table) = { diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c index 917234d24e9..317a26d97c2 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3120.c +++ b/drivers/staging/comedi/drivers/addi_apci_3120.c @@ -8,11 +8,14 @@ #include "addi-data/hwdrv_apci3120.c" +enum apci3120_boardid { + BOARD_APCI3120, + BOARD_APCI3001, +}; + static const struct addi_board apci3120_boardtypes[] = { - { + [BOARD_APCI3120] = { .pc_DriverName = "apci3120", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA_OLD, - .i_DeviceId = 0x818D, .i_NbrAiChannel = 16, .i_NbrAiChannelDiff = 8, .i_AiChannelList = 16, @@ -23,10 +26,9 @@ static const struct addi_board apci3120_boardtypes[] = { .i_NbrDoChannel = 4, .i_DoMaxdata = 0x0f, .interrupt = v_APCI3120_Interrupt, - }, { + }, + [BOARD_APCI3001] = { .pc_DriverName = "apci3001", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA_OLD, - .i_DeviceId = 0x828D, .i_NbrAiChannel = 16, .i_NbrAiChannelDiff = 8, .i_AiChannelList = 16, @@ -47,31 +49,17 @@ static irqreturn_t v_ADDI_Interrupt(int irq, void *d) return IRQ_RETVAL(1); } -static const void *apci3120_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct addi_board *this_board; - int i; - - for (i = 0; i < ARRAY_SIZE(apci3120_boardtypes); i++) { - this_board = &apci3120_boardtypes[i]; - if (this_board->i_VendorId == pcidev->vendor && - this_board->i_DeviceId == pcidev->device) - return this_board; - } - return NULL; -} - static int apci3120_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct addi_board *this_board; + const struct addi_board *this_board = NULL; struct addi_private *devpriv; struct comedi_subdevice *s; int ret, pages, i; - this_board = apci3120_find_boardinfo(dev, pcidev); + if (context < ARRAY_SIZE(apci3120_boardtypes)) + this_board = &apci3120_boardtypes[context]; if (!this_board) return -ENODEV; dev->board_ptr = this_board; @@ -82,7 +70,7 @@ static int apci3120_auto_attach(struct comedi_device *dev, return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; pci_set_master(pcidev); @@ -215,7 +203,6 @@ static int apci3120_auto_attach(struct comedi_device *dev, static void apci3120_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct addi_private *devpriv = dev->private; if (devpriv) { @@ -234,10 +221,7 @@ static void apci3120_detach(struct comedi_device *dev) devpriv->ui_DmaBufferPages[1]); } } - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } + comedi_pci_disable(dev); } static struct comedi_driver apci3120_driver = { @@ -248,14 +232,14 @@ static struct comedi_driver apci3120_driver = { }; static int apci3120_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &apci3120_driver); + return comedi_pci_auto_config(dev, &apci3120_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(apci3120_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA_OLD, 0x818d) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA_OLD, 0x828d) }, + { PCI_VDEVICE(AMCC, 0x818d), BOARD_APCI3120 }, + { PCI_VDEVICE(AMCC, 0x828d), BOARD_APCI3001 }, { 0 } }; MODULE_DEVICE_TABLE(pci, apci3120_pci_table); diff --git a/drivers/staging/comedi/drivers/addi_apci_3200.c b/drivers/staging/comedi/drivers/addi_apci_3200.c index 90ee4f844f9..17b540d3c6a 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3200.c +++ b/drivers/staging/comedi/drivers/addi_apci_3200.c @@ -22,15 +22,15 @@ static void fpu_end(void) #include "addi-data/hwdrv_apci3200.c" #include "addi-data/addi_common.c" +enum apci3200_boardid { + BOARD_APCI3200, + BOARD_APCI3300, +}; + static const struct addi_board apci3200_boardtypes[] = { - { + [BOARD_APCI3200] = { .pc_DriverName = "apci3200", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x3000, - .i_IorangeBase0 = 128, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 4, - .i_IorangeBase3 = 4, .i_PCIEeprom = ADDIDATA_EEPROM, .pc_EepromChip = ADDIDATA_S5920, .i_NbrAiChannel = 16, @@ -53,14 +53,10 @@ static const struct addi_board apci3200_boardtypes[] = { .ai_cancel = i_APCI3200_StopCyclicAcquisition, .di_bits = apci3200_di_insn_bits, .do_bits = apci3200_do_insn_bits, - }, { + }, + [BOARD_APCI3300] = { .pc_DriverName = "apci3300", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x3007, - .i_IorangeBase0 = 128, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 4, - .i_IorangeBase3 = 4, .i_PCIEeprom = ADDIDATA_EEPROM, .pc_EepromChip = ADDIDATA_S5920, .i_NbrAiChannelDiff = 8, @@ -85,29 +81,40 @@ static const struct addi_board apci3200_boardtypes[] = { }, }; -static DEFINE_PCI_DEVICE_TABLE(apci3200_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3000) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3007) }, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, apci3200_pci_table); +static int apci3200_auto_attach(struct comedi_device *dev, + unsigned long context) +{ + const struct addi_board *board = NULL; + + if (context < ARRAY_SIZE(apci3200_boardtypes)) + board = &apci3200_boardtypes[context]; + if (!board) + return -ENODEV; + dev->board_ptr = board; + + return addi_auto_attach(dev, context); +} static struct comedi_driver apci3200_driver = { .driver_name = "addi_apci_3200", .module = THIS_MODULE, - .auto_attach = addi_auto_attach, + .auto_attach = apci3200_auto_attach, .detach = i_ADDI_Detach, - .num_names = ARRAY_SIZE(apci3200_boardtypes), - .board_name = &apci3200_boardtypes[0].pc_DriverName, - .offset = sizeof(struct addi_board), }; static int apci3200_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &apci3200_driver); + return comedi_pci_auto_config(dev, &apci3200_driver, id->driver_data); } +static DEFINE_PCI_DEVICE_TABLE(apci3200_pci_table) = { + { PCI_VDEVICE(ADDIDATA, 0x3000), BOARD_APCI3200 }, + { PCI_VDEVICE(ADDIDATA, 0x3007), BOARD_APCI3300 }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, apci3200_pci_table); + static struct pci_driver apci3200_pci_driver = { .name = "addi_apci_3200", .id_table = apci3200_pci_table, diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c index 786fcaf82c3..a0cf6ecdef0 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3501.c +++ b/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -339,14 +339,12 @@ static int apci3501_auto_attach(struct comedi_device *dev, int ao_n_chan; int ret; - dev->board_name = dev->driver->driver_name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; @@ -423,16 +421,11 @@ static int apci3501_auto_attach(struct comedi_device *dev, static void apci3501_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (dev->iobase) apci3501_reset(dev); if (dev->irq) free_irq(dev->irq, dev); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } + comedi_pci_disable(dev); } static struct comedi_driver apci3501_driver = { @@ -443,9 +436,9 @@ static struct comedi_driver apci3501_driver = { }; static int apci3501_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &apci3501_driver); + return comedi_pci_auto_config(dev, &apci3501_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(apci3501_pci_table) = { diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c index 09d4b21fce2..ec4d6ca6863 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c +++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c @@ -10,15 +10,38 @@ #include "addi-data/hwdrv_apci3xxx.c" #include "addi-data/addi_common.c" +enum apci3xxx_boardid { + BOARD_APCI3000_16, + BOARD_APCI3000_8, + BOARD_APCI3000_4, + BOARD_APCI3006_16, + BOARD_APCI3006_8, + BOARD_APCI3006_4, + BOARD_APCI3010_16, + BOARD_APCI3010_8, + BOARD_APCI3010_4, + BOARD_APCI3016_16, + BOARD_APCI3016_8, + BOARD_APCI3016_4, + BOARD_APCI3100_16_4, + BOARD_APCI3100_8_4, + BOARD_APCI3106_16_4, + BOARD_APCI3106_8_4, + BOARD_APCI3110_16_4, + BOARD_APCI3110_8_4, + BOARD_APCI3116_16_4, + BOARD_APCI3116_8_4, + BOARD_APCI3003, + BOARD_APCI3002_16, + BOARD_APCI3002_8, + BOARD_APCI3002_4, + BOARD_APCI3500, +}; + static const struct addi_board apci3xxx_boardtypes[] = { - { + [BOARD_APCI3000_16] = { .pc_DriverName = "apci3000-16", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x3010, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 16, @@ -37,14 +60,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3000_8] = { .pc_DriverName = "apci3000-8", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x300F, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 8, @@ -63,14 +82,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3000_4] = { .pc_DriverName = "apci3000-4", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x300E, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 4, @@ -89,14 +104,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3006_16] = { .pc_DriverName = "apci3006-16", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x3013, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 16, @@ -115,14 +126,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3006_8] = { .pc_DriverName = "apci3006-8", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x3014, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 8, @@ -141,14 +148,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3006_4] = { .pc_DriverName = "apci3006-4", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x3015, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 4, @@ -167,14 +170,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3010_16] = { .pc_DriverName = "apci3010-16", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x3016, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 16, @@ -198,14 +197,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3010_8] = { .pc_DriverName = "apci3010-8", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x3017, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 8, @@ -229,14 +224,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3010_4] = { .pc_DriverName = "apci3010-4", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x3018, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 4, @@ -260,14 +251,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3016_16] = { .pc_DriverName = "apci3016-16", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x3019, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 16, @@ -291,14 +278,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3016_8] = { .pc_DriverName = "apci3016-8", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x301A, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 8, @@ -322,14 +305,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3016_4] = { .pc_DriverName = "apci3016-4", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x301B, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 4, @@ -353,14 +332,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3100_16_4] = { .pc_DriverName = "apci3100-16-4", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x301C, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 16, @@ -383,14 +358,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3100_8_4] = { .pc_DriverName = "apci3100-8-4", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x301D, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 8, @@ -413,14 +384,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3106_16_4] = { .pc_DriverName = "apci3106-16-4", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x301E, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 16, @@ -443,14 +410,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3106_8_4] = { .pc_DriverName = "apci3106-8-4", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x301F, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 8, @@ -473,14 +436,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3110_16_4] = { .pc_DriverName = "apci3110-16-4", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x3020, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 16, @@ -508,14 +467,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3110_8_4] = { .pc_DriverName = "apci3110-8-4", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x3021, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 8, @@ -543,14 +498,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3116_16_4] = { .pc_DriverName = "apci3116-16-4", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x3022, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 16, @@ -578,14 +529,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3116_8_4] = { .pc_DriverName = "apci3116-8-4", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x3023, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannel = 8, @@ -613,14 +560,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ttl_bits = i_APCI3XXX_InsnBitsTTLIO, .ttl_read = i_APCI3XXX_InsnReadTTLIO, .ttl_write = i_APCI3XXX_InsnWriteTTLIO, - }, { + }, + [BOARD_APCI3003] = { .pc_DriverName = "apci3003", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x300B, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannelDiff = 4, @@ -638,14 +581,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ai_read = i_APCI3XXX_InsnReadAnalogInput, .di_bits = apci3xxx_di_insn_bits, .do_bits = apci3xxx_do_insn_bits, - }, { + }, + [BOARD_APCI3002_16] = { .pc_DriverName = "apci3002-16", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x3002, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannelDiff = 16, @@ -663,14 +602,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ai_read = i_APCI3XXX_InsnReadAnalogInput, .di_bits = apci3xxx_di_insn_bits, .do_bits = apci3xxx_do_insn_bits, - }, { + }, + [BOARD_APCI3002_8] = { .pc_DriverName = "apci3002-8", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x3003, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannelDiff = 8, @@ -688,14 +623,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ai_read = i_APCI3XXX_InsnReadAnalogInput, .di_bits = apci3xxx_di_insn_bits, .do_bits = apci3xxx_do_insn_bits, - }, { + }, + [BOARD_APCI3002_4] = { .pc_DriverName = "apci3002-4", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x3004, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAiChannelDiff = 4, @@ -713,14 +644,10 @@ static const struct addi_board apci3xxx_boardtypes[] = { .ai_read = i_APCI3XXX_InsnReadAnalogInput, .di_bits = apci3xxx_di_insn_bits, .do_bits = apci3xxx_do_insn_bits, - }, { + }, + [BOARD_APCI3500] = { .pc_DriverName = "apci3500", - .i_VendorId = PCI_VENDOR_ID_ADDIDATA, - .i_DeviceId = 0x3024, - .i_IorangeBase0 = 256, .i_IorangeBase1 = 256, - .i_IorangeBase2 = 256, - .i_IorangeBase3 = 256, .i_PCIEeprom = ADDIDATA_NO_EEPROM, .pc_EepromChip = ADDIDATA_9054, .i_NbrAoChannel = 4, @@ -737,48 +664,59 @@ static const struct addi_board apci3xxx_boardtypes[] = { }, }; +static int apci3xxx_auto_attach(struct comedi_device *dev, + unsigned long context) +{ + const struct addi_board *board = NULL; + + if (context < ARRAY_SIZE(apci3xxx_boardtypes)) + board = &apci3xxx_boardtypes[context]; + if (!board) + return -ENODEV; + dev->board_ptr = board; + + return addi_auto_attach(dev, context); +} + static struct comedi_driver apci3xxx_driver = { .driver_name = "addi_apci_3xxx", .module = THIS_MODULE, - .auto_attach = addi_auto_attach, + .auto_attach = apci3xxx_auto_attach, .detach = i_ADDI_Detach, - .num_names = ARRAY_SIZE(apci3xxx_boardtypes), - .board_name = &apci3xxx_boardtypes[0].pc_DriverName, - .offset = sizeof(struct addi_board), }; static int apci3xxx_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &apci3xxx_driver); + return comedi_pci_auto_config(dev, &apci3xxx_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(apci3xxx_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3010) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x300f) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x300e) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3013) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3014) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3015) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3016) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3017) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3018) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3019) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301a) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301b) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301c) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301d) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301e) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301f) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3020) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3021) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3022) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3023) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x300B) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3002) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3003) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3004) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3024) }, + { PCI_VDEVICE(ADDIDATA, 0x3010), BOARD_APCI3000_16 }, + { PCI_VDEVICE(ADDIDATA, 0x300f), BOARD_APCI3000_8 }, + { PCI_VDEVICE(ADDIDATA, 0x300e), BOARD_APCI3000_4 }, + { PCI_VDEVICE(ADDIDATA, 0x3013), BOARD_APCI3006_16 }, + { PCI_VDEVICE(ADDIDATA, 0x3014), BOARD_APCI3006_8 }, + { PCI_VDEVICE(ADDIDATA, 0x3015), BOARD_APCI3006_4 }, + { PCI_VDEVICE(ADDIDATA, 0x3016), BOARD_APCI3010_16 }, + { PCI_VDEVICE(ADDIDATA, 0x3017), BOARD_APCI3010_8 }, + { PCI_VDEVICE(ADDIDATA, 0x3018), BOARD_APCI3010_4 }, + { PCI_VDEVICE(ADDIDATA, 0x3019), BOARD_APCI3016_16 }, + { PCI_VDEVICE(ADDIDATA, 0x301a), BOARD_APCI3016_8 }, + { PCI_VDEVICE(ADDIDATA, 0x301b), BOARD_APCI3016_4 }, + { PCI_VDEVICE(ADDIDATA, 0x301c), BOARD_APCI3100_16_4 }, + { PCI_VDEVICE(ADDIDATA, 0x301d), BOARD_APCI3100_8_4 }, + { PCI_VDEVICE(ADDIDATA, 0x301e), BOARD_APCI3106_16_4 }, + { PCI_VDEVICE(ADDIDATA, 0x301f), BOARD_APCI3106_8_4 }, + { PCI_VDEVICE(ADDIDATA, 0x3020), BOARD_APCI3110_16_4 }, + { PCI_VDEVICE(ADDIDATA, 0x3021), BOARD_APCI3110_8_4 }, + { PCI_VDEVICE(ADDIDATA, 0x3022), BOARD_APCI3116_16_4 }, + { PCI_VDEVICE(ADDIDATA, 0x3023), BOARD_APCI3116_8_4 }, + { PCI_VDEVICE(ADDIDATA, 0x300B), BOARD_APCI3003 }, + { PCI_VDEVICE(ADDIDATA, 0x3002), BOARD_APCI3002_16 }, + { PCI_VDEVICE(ADDIDATA, 0x3003), BOARD_APCI3002_8 }, + { PCI_VDEVICE(ADDIDATA, 0x3004), BOARD_APCI3002_4 }, + { PCI_VDEVICE(ADDIDATA, 0x3024), BOARD_APCI3500 }, { 0 } }; MODULE_DEVICE_TABLE(pci, apci3xxx_pci_table); diff --git a/drivers/staging/comedi/drivers/addi_watchdog.c b/drivers/staging/comedi/drivers/addi_watchdog.c index 375ab665e09..1666b5f510d 100644 --- a/drivers/staging/comedi/drivers/addi_watchdog.c +++ b/drivers/staging/comedi/drivers/addi_watchdog.c @@ -150,12 +150,6 @@ int addi_watchdog_init(struct comedi_subdevice *s, unsigned long iobase) } EXPORT_SYMBOL_GPL(addi_watchdog_init); -void addi_watchdog_cleanup(struct comedi_subdevice *s) -{ - kfree(s->private); -} -EXPORT_SYMBOL_GPL(addi_watchdog_cleanup); - static int __init addi_watchdog_module_init(void) { return 0; diff --git a/drivers/staging/comedi/drivers/addi_watchdog.h b/drivers/staging/comedi/drivers/addi_watchdog.h index f374a7bff44..83b47befa4d 100644 --- a/drivers/staging/comedi/drivers/addi_watchdog.h +++ b/drivers/staging/comedi/drivers/addi_watchdog.h @@ -5,6 +5,5 @@ void addi_watchdog_reset(unsigned long iobase); int addi_watchdog_init(struct comedi_subdevice *, unsigned long iobase); -void addi_watchdog_cleanup(struct comedi_subdevice *s); #endif diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index 7b3e331616e..8a438ff1bd4 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -47,12 +47,6 @@ References: #include "../comedidev.h" /* - * ADLINK PCI Device ID's supported by this driver - */ -#define PCI_DEVICE_ID_PCI6208 0x6208 -#define PCI_DEVICE_ID_PCI6216 0x6216 - -/* * PCI-6208/6216-GL register map */ #define PCI6208_AO_CONTROL(x) (0x00 + (2 * (x))) @@ -66,20 +60,23 @@ References: #define PCI6208_MAX_AO_CHANNELS 16 +enum pci6208_boardid { + BOARD_PCI6208, + BOARD_PCI6216, +}; + struct pci6208_board { const char *name; - unsigned short dev_id; int ao_chans; }; static const struct pci6208_board pci6208_boards[] = { - { + [BOARD_PCI6208] = { .name = "adl_pci6208", - .dev_id = PCI_DEVICE_ID_PCI6208, .ao_chans = 8, - }, { + }, + [BOARD_PCI6216] = { .name = "adl_pci6216", - .dev_id = PCI_DEVICE_ID_PCI6216, .ao_chans = 16, }, }; @@ -162,31 +159,18 @@ static int pci6208_do_insn_bits(struct comedi_device *dev, return insn->n; } -static const void *pci6208_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct pci6208_board *boardinfo; - int i; - - for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) { - boardinfo = &pci6208_boards[i]; - if (boardinfo->dev_id == pcidev->device) - return boardinfo; - } - return NULL; -} - static int pci6208_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct pci6208_board *boardinfo; + const struct pci6208_board *boardinfo = NULL; struct pci6208_private *devpriv; struct comedi_subdevice *s; unsigned int val; int ret; - boardinfo = pci6208_find_boardinfo(dev, pcidev); + if (context < ARRAY_SIZE(pci6208_boards)) + boardinfo = &pci6208_boards[context]; if (!boardinfo) return -ENODEV; dev->board_ptr = boardinfo; @@ -197,7 +181,7 @@ static int pci6208_auto_attach(struct comedi_device *dev, return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pcidev, 2); @@ -249,32 +233,23 @@ static int pci6208_auto_attach(struct comedi_device *dev, return 0; } -static void pci6208_detach(struct comedi_device *dev) -{ - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } -} - static struct comedi_driver adl_pci6208_driver = { .driver_name = "adl_pci6208", .module = THIS_MODULE, .auto_attach = pci6208_auto_attach, - .detach = pci6208_detach, + .detach = comedi_pci_disable, }; static int adl_pci6208_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &adl_pci6208_driver); + return comedi_pci_auto_config(dev, &adl_pci6208_driver, + id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(adl_pci6208_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI6208) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI6216) }, + { PCI_VDEVICE(ADLINK, 0x6208), BOARD_PCI6208 }, + { PCI_VDEVICE(ADLINK, 0x6216), BOARD_PCI6216 }, { 0 } }; MODULE_DEVICE_TABLE(pci, adl_pci6208_pci_table); diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c index f27f48e6e70..e3960745f50 100644 --- a/drivers/staging/comedi/drivers/adl_pci7x3x.c +++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c @@ -53,60 +53,57 @@ Configuration Options: not applicable, uses comedi PCI auto config #include "../comedidev.h" /* - * PCI Device ID's supported by this driver - */ -#define PCI_DEVICE_ID_PCI7230 0x7230 -#define PCI_DEVICE_ID_PCI7233 0x7233 -#define PCI_DEVICE_ID_PCI7234 0x7234 -#define PCI_DEVICE_ID_PCI7432 0x7432 -#define PCI_DEVICE_ID_PCI7433 0x7433 -#define PCI_DEVICE_ID_PCI7434 0x7434 - -/* * Register I/O map (32-bit access only) */ #define PCI7X3X_DIO_REG 0x00 #define PCI743X_DIO_REG 0x04 +enum apci1516_boardid { + BOARD_PCI7230, + BOARD_PCI7233, + BOARD_PCI7234, + BOARD_PCI7432, + BOARD_PCI7433, + BOARD_PCI7434, +}; + struct adl_pci7x3x_boardinfo { const char *name; - unsigned short device; int nsubdevs; int di_nchan; int do_nchan; }; static const struct adl_pci7x3x_boardinfo adl_pci7x3x_boards[] = { - { + [BOARD_PCI7230] = { .name = "adl_pci7230", - .device = PCI_DEVICE_ID_PCI7230, .nsubdevs = 2, .di_nchan = 16, .do_nchan = 16, - }, { + }, + [BOARD_PCI7233] = { .name = "adl_pci7233", - .device = PCI_DEVICE_ID_PCI7233, .nsubdevs = 1, .di_nchan = 32, - }, { + }, + [BOARD_PCI7234] = { .name = "adl_pci7234", - .device = PCI_DEVICE_ID_PCI7234, .nsubdevs = 1, .do_nchan = 32, - }, { + }, + [BOARD_PCI7432] = { .name = "adl_pci7432", - .device = PCI_DEVICE_ID_PCI7432, .nsubdevs = 2, .di_nchan = 32, .do_nchan = 32, - }, { + }, + [BOARD_PCI7433] = { .name = "adl_pci7433", - .device = PCI_DEVICE_ID_PCI7433, .nsubdevs = 2, .di_nchan = 64, - }, { + }, + [BOARD_PCI7434] = { .name = "adl_pci7434", - .device = PCI_DEVICE_ID_PCI7434, .nsubdevs = 2, .do_nchan = 64, } @@ -150,37 +147,24 @@ static int adl_pci7x3x_di_insn_bits(struct comedi_device *dev, return insn->n; } -static const void *adl_pci7x3x_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct adl_pci7x3x_boardinfo *board; - int i; - - for (i = 0; i < ARRAY_SIZE(adl_pci7x3x_boards); i++) { - board = &adl_pci7x3x_boards[i]; - if (pcidev->device == board->device) - return board; - } - return NULL; -} - static int adl_pci7x3x_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct adl_pci7x3x_boardinfo *board; + const struct adl_pci7x3x_boardinfo *board = NULL; struct comedi_subdevice *s; int subdev; int nchan; int ret; - board = adl_pci7x3x_find_boardinfo(dev, pcidev); + if (context < ARRAY_SIZE(adl_pci7x3x_boards)) + board = &adl_pci7x3x_boards[context]; if (!board) return -ENODEV; dev->board_ptr = board; dev->board_name = board->name; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pcidev, 2); @@ -275,36 +259,27 @@ static int adl_pci7x3x_auto_attach(struct comedi_device *dev, return 0; } -static void adl_pci7x3x_detach(struct comedi_device *dev) -{ - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } -} - static struct comedi_driver adl_pci7x3x_driver = { .driver_name = "adl_pci7x3x", .module = THIS_MODULE, .auto_attach = adl_pci7x3x_auto_attach, - .detach = adl_pci7x3x_detach, + .detach = comedi_pci_disable, }; static int adl_pci7x3x_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &adl_pci7x3x_driver); + return comedi_pci_auto_config(dev, &adl_pci7x3x_driver, + id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(adl_pci7x3x_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7230) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7233) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7234) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7432) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7433) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7434) }, + { PCI_VDEVICE(ADLINK, 0x7230), BOARD_PCI7230 }, + { PCI_VDEVICE(ADLINK, 0x7233), BOARD_PCI7233 }, + { PCI_VDEVICE(ADLINK, 0x7234), BOARD_PCI7234 }, + { PCI_VDEVICE(ADLINK, 0x7432), BOARD_PCI7432 }, + { PCI_VDEVICE(ADLINK, 0x7433), BOARD_PCI7433 }, + { PCI_VDEVICE(ADLINK, 0x7434), BOARD_PCI7434 }, { 0 } }; MODULE_DEVICE_TABLE(pci, adl_pci7x3x_pci_table); diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c index d06b83f3865..b3ec60afe3a 100644 --- a/drivers/staging/comedi/drivers/adl_pci8164.c +++ b/drivers/staging/comedi/drivers/adl_pci8164.c @@ -1,217 +1,74 @@ /* - comedi/drivers/adl_pci8164.c - - Hardware comedi driver fot PCI-8164 Adlink card - Copyright (C) 2004 Michel Lachine <mike@mikelachaine.ca> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * comedi/drivers/adl_pci8164.c + * + * Hardware comedi driver for PCI-8164 Adlink card + * Copyright (C) 2004 Michel Lachine <mike@mikelachaine.ca> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ -*/ /* -Driver: adl_pci8164 -Description: Driver for the Adlink PCI-8164 4 Axes Motion Control board -Devices: [ADLink] PCI-8164 (adl_pci8164) -Author: Michel Lachaine <mike@mikelachaine.ca> -Status: experimental -Updated: Mon, 14 Apr 2008 15:10:32 +0100 - -Configuration Options: not applicable, uses PCI auto config -*/ + * Driver: adl_pci8164 + * Description: Driver for the Adlink PCI-8164 4 Axes Motion Control board + * Devices: (ADLink) PCI-8164 [adl_pci8164] + * Author: Michel Lachaine <mike@mikelachaine.ca> + * Status: experimental + * Updated: Mon, 14 Apr 2008 15:10:32 +0100 + * + * Configuration Options: not applicable, uses PCI auto config + */ #include <linux/kernel.h> #include <linux/pci.h> -#include <linux/delay.h> #include "../comedidev.h" -#include "comedi_fc.h" -#include "8253.h" - -#define PCI8164_AXIS_X 0x00 -#define PCI8164_AXIS_Y 0x08 -#define PCI8164_AXIS_Z 0x10 -#define PCI8164_AXIS_U 0x18 -#define PCI8164_MSTS 0x00 -#define PCI8164_SSTS 0x02 -#define PCI8164_BUF0 0x04 -#define PCI8164_BUF1 0x06 - -#define PCI8164_CMD 0x00 -#define PCI8164_OTP 0x02 - -#define PCI_DEVICE_ID_PCI8164 0x8164 - -/* - all the read commands are the same except for the addition a constant - * const to the data for inw() - */ -static void adl_pci8164_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data, - char *action, unsigned short offset) -{ - int axis, axis_reg; - char axisname; - - axis = CR_CHAN(insn->chanspec); - - switch (axis) { - case 0: - axis_reg = PCI8164_AXIS_X; - axisname = 'X'; - break; - case 1: - axis_reg = PCI8164_AXIS_Y; - axisname = 'Y'; - break; - case 2: - axis_reg = PCI8164_AXIS_Z; - axisname = 'Z'; - break; - case 3: - axis_reg = PCI8164_AXIS_U; - axisname = 'U'; - break; - default: - axis_reg = PCI8164_AXIS_X; - axisname = 'X'; - } - - data[0] = inw(dev->iobase + axis_reg + offset); - dev_dbg(dev->class_dev, - "pci8164 %s read -> %04X:%04X on axis %c\n", - action, data[0], data[1], axisname); -} - -static int adl_pci8164_insn_read_msts(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - adl_pci8164_insn_read(dev, s, insn, data, "MSTS", PCI8164_MSTS); - return 2; -} - -static int adl_pci8164_insn_read_ssts(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - adl_pci8164_insn_read(dev, s, insn, data, "SSTS", PCI8164_SSTS); - return 2; -} - -static int adl_pci8164_insn_read_buf0(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - adl_pci8164_insn_read(dev, s, insn, data, "BUF0", PCI8164_BUF0); - return 2; -} +#define PCI8164_AXIS(x) ((x) * 0x08) +#define PCI8164_CMD_MSTS_REG 0x00 +#define PCI8164_OTP_SSTS_REG 0x02 +#define PCI8164_BUF0_REG 0x04 +#define PCI8164_BUF1_REG 0x06 -static int adl_pci8164_insn_read_buf1(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - adl_pci8164_insn_read(dev, s, insn, data, "BUF1", PCI8164_BUF1); - return 2; -} - -/* - all the write commands are the same except for the addition a constant - * const to the data for outw() - */ -static void adl_pci8164_insn_out(struct comedi_device *dev, +static int adl_pci8164_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data, - char *action, unsigned short offset) + unsigned int *data) { - unsigned int axis, axis_reg; - - char axisname; - - axis = CR_CHAN(insn->chanspec); + unsigned long offset = (unsigned long)s->private; + unsigned int chan = CR_CHAN(insn->chanspec); + int i; - switch (axis) { - case 0: - axis_reg = PCI8164_AXIS_X; - axisname = 'X'; - break; - case 1: - axis_reg = PCI8164_AXIS_Y; - axisname = 'Y'; - break; - case 2: - axis_reg = PCI8164_AXIS_Z; - axisname = 'Z'; - break; - case 3: - axis_reg = PCI8164_AXIS_U; - axisname = 'U'; - break; - default: - axis_reg = PCI8164_AXIS_X; - axisname = 'X'; - } - - outw(data[0], dev->iobase + axis_reg + offset); - - dev_dbg(dev->class_dev, - "pci8164 %s write -> %04X:%04X on axis %c\n", - action, data[0], data[1], axisname); + for (i = 0; i < insn->n; i++) + data[i] = inw(dev->iobase + PCI8164_AXIS(chan) + offset); + return insn->n; } -static int adl_pci8164_insn_write_cmd(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - adl_pci8164_insn_out(dev, s, insn, data, "CMD", PCI8164_CMD); - return 2; -} - -static int adl_pci8164_insn_write_otp(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) +static int adl_pci8164_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - adl_pci8164_insn_out(dev, s, insn, data, "OTP", PCI8164_OTP); - return 2; -} + unsigned long offset = (unsigned long)s->private; + unsigned int chan = CR_CHAN(insn->chanspec); + int i; -static int adl_pci8164_insn_write_buf0(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - adl_pci8164_insn_out(dev, s, insn, data, "BUF0", PCI8164_BUF0); - return 2; -} + for (i = 0; i < insn->n; i++) + outw(data[i], dev->iobase + PCI8164_AXIS(chan) + offset); -static int adl_pci8164_insn_write_buf1(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - adl_pci8164_insn_out(dev, s, insn, data, "BUF1", PCI8164_BUF1); - return 2; + return insn->n; } static int adl_pci8164_auto_attach(struct comedi_device *dev, @@ -221,9 +78,7 @@ static int adl_pci8164_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - dev->board_name = dev->driver->driver_name; - - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pcidev, 2); @@ -232,77 +87,70 @@ static int adl_pci8164_auto_attach(struct comedi_device *dev, if (ret) return ret; + /* read MSTS register / write CMD register for each axis (channel) */ s = &dev->subdevices[0]; - s->type = COMEDI_SUBD_PROC; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 4; - s->maxdata = 0xffff; - s->len_chanlist = 4; - /* s->range_table = &range_axis; */ - s->insn_read = adl_pci8164_insn_read_msts; - s->insn_write = adl_pci8164_insn_write_cmd; - + s->type = COMEDI_SUBD_PROC; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 4; + s->maxdata = 0xffff; + s->len_chanlist = 4; + s->insn_read = adl_pci8164_insn_read; + s->insn_write = adl_pci8164_insn_write; + s->private = (void *)PCI8164_CMD_MSTS_REG; + + /* read SSTS register / write OTP register for each axis (channel) */ s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_PROC; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 4; - s->maxdata = 0xffff; - s->len_chanlist = 4; - /* s->range_table = &range_axis; */ - s->insn_read = adl_pci8164_insn_read_ssts; - s->insn_write = adl_pci8164_insn_write_otp; - + s->type = COMEDI_SUBD_PROC; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 4; + s->maxdata = 0xffff; + s->len_chanlist = 4; + s->insn_read = adl_pci8164_insn_read; + s->insn_write = adl_pci8164_insn_write; + s->private = (void *)PCI8164_OTP_SSTS_REG; + + /* read/write BUF0 register for each axis (channel) */ s = &dev->subdevices[2]; - s->type = COMEDI_SUBD_PROC; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 4; - s->maxdata = 0xffff; - s->len_chanlist = 4; - /* s->range_table = &range_axis; */ - s->insn_read = adl_pci8164_insn_read_buf0; - s->insn_write = adl_pci8164_insn_write_buf0; - + s->type = COMEDI_SUBD_PROC; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 4; + s->maxdata = 0xffff; + s->len_chanlist = 4; + s->insn_read = adl_pci8164_insn_read; + s->insn_write = adl_pci8164_insn_write; + s->private = (void *)PCI8164_BUF0_REG; + + /* read/write BUF1 register for each axis (channel) */ s = &dev->subdevices[3]; - s->type = COMEDI_SUBD_PROC; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 4; - s->maxdata = 0xffff; - s->len_chanlist = 4; - /* s->range_table = &range_axis; */ - s->insn_read = adl_pci8164_insn_read_buf1; - s->insn_write = adl_pci8164_insn_write_buf1; - - dev_info(dev->class_dev, "%s attached\n", dev->board_name); + s->type = COMEDI_SUBD_PROC; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 4; + s->maxdata = 0xffff; + s->len_chanlist = 4; + s->insn_read = adl_pci8164_insn_read; + s->insn_write = adl_pci8164_insn_write; + s->private = (void *)PCI8164_BUF1_REG; return 0; } -static void adl_pci8164_detach(struct comedi_device *dev) -{ - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } -} - static struct comedi_driver adl_pci8164_driver = { .driver_name = "adl_pci8164", .module = THIS_MODULE, .auto_attach = adl_pci8164_auto_attach, - .detach = adl_pci8164_detach, + .detach = comedi_pci_disable, }; static int adl_pci8164_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &adl_pci8164_driver); + return comedi_pci_auto_config(dev, &adl_pci8164_driver, + id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(adl_pci8164_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI8164) }, - {0} + { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x8164) }, + { 0 } }; MODULE_DEVICE_TABLE(pci, adl_pci8164_pci_table); diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index eeb10ec7f17..6247fdcedcb 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -75,6 +75,7 @@ TODO: #include "../comedidev.h" #include "8253.h" +#include "plx9052.h" #include "comedi_fc.h" #define PCI9111_DRIVER_NAME "adl_pci9111" @@ -120,6 +121,14 @@ TODO: #define PCI9111_8254_BASE_REG 0x40 #define PCI9111_INT_CLR_REG 0x48 +/* PLX 9052 Local Interrupt 1 enabled and active */ +#define PCI9111_LI1_ACTIVE (PLX9052_INTCSR_LI1ENAB | \ + PLX9052_INTCSR_LI1STAT) + +/* PLX 9052 Local Interrupt 2 enabled and active */ +#define PCI9111_LI2_ACTIVE (PLX9052_INTCSR_LI2ENAB | \ + PLX9052_INTCSR_LI2STAT) + static const struct comedi_lrange pci9111_ai_range = { 5, { @@ -150,17 +159,6 @@ struct pci9111_private_data { short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE]; }; -#define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c - -#define PLX9050_LINTI1_ENABLE (1 << 0) -#define PLX9050_LINTI1_ACTIVE_HIGH (1 << 1) -#define PLX9050_LINTI1_STATUS (1 << 2) -#define PLX9050_LINTI2_ENABLE (1 << 3) -#define PLX9050_LINTI2_ACTIVE_HIGH (1 << 4) -#define PLX9050_LINTI2_STATUS (1 << 5) -#define PLX9050_PCI_INTERRUPT_ENABLE (1 << 6) -#define PLX9050_SOFTWARE_INTERRUPT (1 << 7) - static void plx9050_interrupt_control(unsigned long io_base, bool LINTi1_enable, bool LINTi1_active_high, @@ -171,18 +169,18 @@ static void plx9050_interrupt_control(unsigned long io_base, int flags = 0; if (LINTi1_enable) - flags |= PLX9050_LINTI1_ENABLE; + flags |= PLX9052_INTCSR_LI1ENAB; if (LINTi1_active_high) - flags |= PLX9050_LINTI1_ACTIVE_HIGH; + flags |= PLX9052_INTCSR_LI1POL; if (LINTi2_enable) - flags |= PLX9050_LINTI2_ENABLE; + flags |= PLX9052_INTCSR_LI2ENAB; if (LINTi2_active_high) - flags |= PLX9050_LINTI2_ACTIVE_HIGH; + flags |= PLX9052_INTCSR_LI2POL; if (interrupt_enable) - flags |= PLX9050_PCI_INTERRUPT_ENABLE; + flags |= PLX9052_INTCSR_PCIENAB; - outb(flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL); + outb(flags, io_base + PLX9052_INTCSR); } static void pci9111_timer_set(struct comedi_device *dev) @@ -607,21 +605,17 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device) spin_lock_irqsave(&dev->spinlock, irq_flags); /* Check if we are source of interrupt */ - intcsr = inb(dev_private->lcr_io_base + - PLX9050_REGISTER_INTERRUPT_CONTROL); - if (!(((intcsr & PLX9050_PCI_INTERRUPT_ENABLE) != 0) - && (((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) - == (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) - || ((intcsr & (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS)) - == (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))))) { + intcsr = inb(dev_private->lcr_io_base + PLX9052_INTCSR); + if (!(((intcsr & PLX9052_INTCSR_PCIENAB) != 0) && + (((intcsr & PCI9111_LI1_ACTIVE) == PCI9111_LI1_ACTIVE) || + ((intcsr & PCI9111_LI2_ACTIVE) == PCI9111_LI2_ACTIVE)))) { /* Not the source of the interrupt. */ - /* (N.B. not using PLX9050_SOFTWARE_INTERRUPT) */ + /* (N.B. not using PLX9052_INTCSR_SOFTINT) */ spin_unlock_irqrestore(&dev->spinlock, irq_flags); return IRQ_NONE; } - if ((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) == - (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) { + if ((intcsr & PCI9111_LI1_ACTIVE) == PCI9111_LI1_ACTIVE) { /* Interrupt comes from fifo_half-full signal */ status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG); @@ -865,14 +859,12 @@ static int pci9111_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - dev->board_name = dev->driver->driver_name; - dev_private = kzalloc(sizeof(*dev_private), GFP_KERNEL); if (!dev_private) return -ENOMEM; dev->private = dev_private; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; dev_private->lcr_io_base = pci_resource_start(pcidev, 1); @@ -939,16 +931,11 @@ static int pci9111_auto_attach(struct comedi_device *dev, static void pci9111_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (dev->iobase) pci9111_reset(dev); if (dev->irq != 0) free_irq(dev->irq, dev); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } + comedi_pci_disable(dev); } static struct comedi_driver adl_pci9111_driver = { @@ -959,9 +946,10 @@ static struct comedi_driver adl_pci9111_driver = { }; static int pci9111_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &adl_pci9111_driver); + return comedi_pci_auto_config(dev, &adl_pci9111_driver, + id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = { diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 4dbac7459a4..cb4ef2dcbf0 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -1970,12 +1970,9 @@ static int pci9118_common_attach(struct comedi_device *dev, int disable_irq, u16 u16w; dev->board_name = this_board->name; - ret = comedi_pci_enable(pcidev, dev->board_name); - if (ret) { - dev_err(dev->class_dev, - "cannot enable PCI device %s\n", pci_name(pcidev)); + ret = comedi_pci_enable(dev); + if (ret) return ret; - } if (master) pci_set_master(pcidev); @@ -2202,12 +2199,9 @@ static void pci9118_detach(struct comedi_device *dev) free_pages((unsigned long)devpriv->dmabuf_virt[1], devpriv->dmabuf_pages[1]); } - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - + comedi_pci_disable(dev); + if (pcidev) pci_dev_put(pcidev); - } } static struct comedi_driver adl_pci9118_driver = { @@ -2222,9 +2216,10 @@ static struct comedi_driver adl_pci9118_driver = { }; static int adl_pci9118_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &adl_pci9118_driver); + return comedi_pci_auto_config(dev, &adl_pci9118_driver, + id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(adl_pci9118_pci_table) = { diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c index f7950dfe2dd..71142e36e7f 100644 --- a/drivers/staging/comedi/drivers/adq12b.c +++ b/drivers/staging/comedi/drivers/adq12b.c @@ -213,43 +213,19 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct adq12b_private *devpriv; struct comedi_subdevice *s; - unsigned long iobase; - int unipolar, differential; int ret; - dev->board_name = dev->driver->driver_name; - - iobase = it->options[0]; - unipolar = it->options[1]; - differential = it->options[2]; - - printk(KERN_INFO "comedi%d: adq12b called with options base=0x%03lx, " - "%s and %s\n", dev->minor, iobase, - (unipolar == 1) ? "unipolar" : "bipolar", - (differential == 1) ? "differential" : "single-ended"); - - /* if no address was specified, try the default 0x300 */ - if (iobase == 0) { - printk(KERN_WARNING "comedi%d: adq12b warning: I/O base " - "address not specified. Trying the default 0x300.\n", - dev->minor); - iobase = 0x300; - } - - printk("comedi%d: adq12b: 0x%04lx ", dev->minor, iobase); - if (!request_region(iobase, ADQ12B_SIZE, "adq12b")) { - printk("I/O port conflict\n"); - return -EIO; - } - dev->iobase = iobase; + ret = comedi_request_region(dev, it->options[0], ADQ12B_SIZE); + if (ret) + return ret; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - devpriv->unipolar = unipolar; - devpriv->differential = differential; + devpriv->unipolar = it->options[1]; + devpriv->differential = it->options[2]; devpriv->digital_state = 0; /* * initialize channel and range to -1 so we make sure we @@ -265,7 +241,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) s = &dev->subdevices[0]; /* analog input subdevice */ s->type = COMEDI_SUBD_AI; - if (differential) { + if (devpriv->differential) { s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; s->n_chan = 8; } else { @@ -273,7 +249,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->n_chan = 16; } - if (unipolar) + if (devpriv->unipolar) s->range_table = &range_adq12b_ai_unipolar; else s->range_table = &range_adq12b_ai_bipolar; @@ -302,22 +278,14 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->range_table = &range_digital; s->insn_bits = adq12b_do_insn_bits; - printk(KERN_INFO "attached\n"); - return 0; } -static void adq12b_detach(struct comedi_device *dev) -{ - if (dev->iobase) - release_region(dev->iobase, ADQ12B_SIZE); -} - static struct comedi_driver adq12b_driver = { .driver_name = "adq12b", .module = THIS_MODULE, .attach = adq12b_attach, - .detach = adq12b_detach, + .detach = comedi_legacy_detach, }; module_comedi_driver(adq12b_driver); diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 3d788c76d64..f847bbc175e 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -59,9 +59,6 @@ Configuration options: #define TYPE_PCI1713 2 #define TYPE_PCI1720 3 -#define IORANGE_171x 32 -#define IORANGE_1720 16 - #define PCI171x_AD_DATA 0 /* R: A/D data */ #define PCI171x_SOFTTRG 0 /* W: soft trigger for A/D */ #define PCI171x_RANGE 2 /* W: A/D gain/range register */ @@ -178,10 +175,17 @@ static const struct comedi_lrange range_pci171x_da = { 2, { } }; +enum pci1710_boardid { + BOARD_PCI1710, + BOARD_PCI1710HG, + BOARD_PCI1711, + BOARD_PCI1713, + BOARD_PCI1720, + BOARD_PCI1731, +}; + struct boardtype { const char *name; /* board name */ - int device_id; - int iorange; /* I/O range len */ char have_irq; /* 1=card support IRQ */ char cardtype; /* 0=1710& co. 2=1713, ... */ int n_aichan; /* num of A/D chans */ @@ -200,10 +204,8 @@ struct boardtype { }; static const struct boardtype boardtypes[] = { - { + [BOARD_PCI1710] = { .name = "pci1710", - .device_id = 0x1710, - .iorange = IORANGE_171x, .have_irq = 1, .cardtype = TYPE_PCI171X, .n_aichan = 16, @@ -219,10 +221,9 @@ static const struct boardtype boardtypes[] = { .rangelist_ao = &range_pci171x_da, .ai_ns_min = 10000, .fifo_half_size = 2048, - }, { + }, + [BOARD_PCI1710HG] = { .name = "pci1710hg", - .device_id = 0x1710, - .iorange = IORANGE_171x, .have_irq = 1, .cardtype = TYPE_PCI171X, .n_aichan = 16, @@ -238,10 +239,9 @@ static const struct boardtype boardtypes[] = { .rangelist_ao = &range_pci171x_da, .ai_ns_min = 10000, .fifo_half_size = 2048, - }, { + }, + [BOARD_PCI1711] = { .name = "pci1711", - .device_id = 0x1711, - .iorange = IORANGE_171x, .have_irq = 1, .cardtype = TYPE_PCI171X, .n_aichan = 16, @@ -256,10 +256,9 @@ static const struct boardtype boardtypes[] = { .rangelist_ao = &range_pci171x_da, .ai_ns_min = 10000, .fifo_half_size = 512, - }, { + }, + [BOARD_PCI1713] = { .name = "pci1713", - .device_id = 0x1713, - .iorange = IORANGE_171x, .have_irq = 1, .cardtype = TYPE_PCI1713, .n_aichan = 32, @@ -269,18 +268,16 @@ static const struct boardtype boardtypes[] = { .rangecode_ai = range_codes_pci1710_3, .ai_ns_min = 10000, .fifo_half_size = 2048, - }, { + }, + [BOARD_PCI1720] = { .name = "pci1720", - .device_id = 0x1720, - .iorange = IORANGE_1720, .cardtype = TYPE_PCI1720, .n_aochan = 4, .ao_maxdata = 0x0fff, .rangelist_ao = &range_pci1720, - }, { + }, + [BOARD_PCI1731] = { .name = "pci1731", - .device_id = 0x1731, - .iorange = IORANGE_171x, .have_irq = 1, .cardtype = TYPE_PCI171X, .n_aichan = 16, @@ -307,7 +304,7 @@ struct pci1710_private { unsigned int ai_et_CntrlReg; unsigned int ai_et_MuxVal; unsigned int ai_et_div1, ai_et_div2; - unsigned int act_chanlist[32]; /* list of scaned channel */ + unsigned int act_chanlist[32]; /* list of scanned channel */ unsigned char act_chanlist_len; /* len of scanlist */ unsigned char act_chanlist_pos; /* actual position in MUX list */ unsigned char da_ranges; /* copy of D/A outpit range register */ @@ -334,7 +331,7 @@ static const unsigned int muxonechan[] = { /* ============================================================================== - Check if channel list from user is builded correctly + Check if channel list from user is built correctly If it's ok, then program scan/gain logic. This works for all cards. */ @@ -1220,30 +1217,17 @@ static int pci1710_reset(struct comedi_device *dev) } } -static const void *pci1710_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct boardtype *this_board; - int i; - - for (i = 0; i < ARRAY_SIZE(boardtypes); i++) { - this_board = &boardtypes[i]; - if (pcidev->device == this_board->device_id) - return this_board; - } - return NULL; -} - static int pci1710_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct boardtype *this_board; + const struct boardtype *this_board = NULL; struct pci1710_private *devpriv; struct comedi_subdevice *s; int ret, subdev, n_subdevices; - this_board = pci1710_find_boardinfo(dev, pcidev); + if (context < ARRAY_SIZE(boardtypes)) + this_board = &boardtypes[context]; if (!this_board) return -ENODEV; dev->board_ptr = this_board; @@ -1254,7 +1238,7 @@ static int pci1710_auto_attach(struct comedi_device *dev, return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pcidev, 2); @@ -1378,16 +1362,11 @@ static int pci1710_auto_attach(struct comedi_device *dev, static void pci1710_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (dev->iobase) pci1710_reset(dev); if (dev->irq) free_irq(dev->irq, dev); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } + comedi_pci_disable(dev); } static struct comedi_driver adv_pci1710_driver = { @@ -1398,17 +1377,68 @@ static struct comedi_driver adv_pci1710_driver = { }; static int adv_pci1710_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &adv_pci1710_driver); + return comedi_pci_auto_config(dev, &adv_pci1710_driver, + id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(adv_pci1710_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1710) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1711) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1713) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1720) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1731) }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, + PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050), + .driver_data = BOARD_PCI1710, + }, { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0x0000), + .driver_data = BOARD_PCI1710, + }, { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0xb100), + .driver_data = BOARD_PCI1710, + }, { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0xb200), + .driver_data = BOARD_PCI1710, + }, { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0xc100), + .driver_data = BOARD_PCI1710, + }, { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0xc200), + .driver_data = BOARD_PCI1710, + }, { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, 0x1000, 0xd100), + .driver_data = BOARD_PCI1710, + }, { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0x0002), + .driver_data = BOARD_PCI1710HG, + }, { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0xb102), + .driver_data = BOARD_PCI1710HG, + }, { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0xb202), + .driver_data = BOARD_PCI1710HG, + }, { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0xc102), + .driver_data = BOARD_PCI1710HG, + }, { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, + PCI_VENDOR_ID_ADVANTECH, 0xc202), + .driver_data = BOARD_PCI1710HG, + }, { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, 0x1000, 0xd102), + .driver_data = BOARD_PCI1710HG, + }, + { PCI_VDEVICE(ADVANTECH, 0x1711), BOARD_PCI1711 }, + { PCI_VDEVICE(ADVANTECH, 0x1713), BOARD_PCI1713 }, + { PCI_VDEVICE(ADVANTECH, 0x1720), BOARD_PCI1720 }, + { PCI_VDEVICE(ADVANTECH, 0x1731), BOARD_PCI1731 }, { 0 } }; MODULE_DEVICE_TABLE(pci, adv_pci1710_pci_table); diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index 02ce55a01d2..ccc114d6c08 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -242,14 +242,12 @@ static int pci1723_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - dev->board_name = dev->driver->driver_name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pcidev, 2); @@ -306,14 +304,9 @@ static int pci1723_auto_attach(struct comedi_device *dev, static void pci1723_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - - if (pcidev) { - if (dev->iobase) { - pci1723_reset(dev); - comedi_pci_disable(pcidev); - } - } + if (dev->iobase) + pci1723_reset(dev); + comedi_pci_disable(dev); } static struct comedi_driver adv_pci1723_driver = { @@ -324,9 +317,10 @@ static struct comedi_driver adv_pci1723_driver = { }; static int adv_pci1723_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &adv_pci1723_driver); + return comedi_pci_auto_config(dev, &adv_pci1723_driver, + id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(adv_pci1723_pci_table) = { diff --git a/drivers/staging/comedi/drivers/adv_pci1724.c b/drivers/staging/comedi/drivers/adv_pci1724.c new file mode 100644 index 00000000000..e60f12578d4 --- /dev/null +++ b/drivers/staging/comedi/drivers/adv_pci1724.c @@ -0,0 +1,409 @@ +/* + comedi/drivers/adv_pci1724.c + This is a driver for the Advantech PCI-1724U card. + + Author: Frank Mori Hess <fmh6jj@gmail.com> + Copyright (C) 2013 GnuBIO Inc + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1997-8 David A. Schleef <ds@schleef.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +************************************************************************/ + +/* + +Driver: adv_1724 +Description: Advantech PCI-1724U +Author: Frank Mori Hess <fmh6jj@gmail.com> +Status: works +Updated: 2013-02-09 +Devices: [Advantech] PCI-1724U (adv_pci1724) + +Subdevice 0 is the analog output. +Subdevice 1 is the offset calibration for the analog output. +Subdevice 2 is the gain calibration for the analog output. + +The calibration offset and gains have quite a large effect +on the analog output, so it is possible to adjust the analog output to +have an output range significantly different from the board's +nominal output ranges. For a calibrated +/- 10V range, the analog +output's offset will be set somewhere near mid-range (0x2000) and its +gain will be near maximum (0x3fff). + +There is really no difference between the board's documented 0-20mA +versus 4-20mA output ranges. To pick one or the other is simply a matter +of adjusting the offset and gain calibration until the board outputs in +the desired range. + +Configuration options: + None + +Manual configuration of comedi devices is not supported by this driver; +supported PCI devices are configured as comedi devices automatically. + +*/ + +#include <linux/pci.h> + +#include "../comedidev.h" + +#define PCI_VENDOR_ID_ADVANTECH 0x13fe + +#define NUM_AO_CHANNELS 32 + +/* register offsets */ +enum board_registers { + DAC_CONTROL_REG = 0x0, + SYNC_OUTPUT_REG = 0x4, + EEPROM_CONTROL_REG = 0x8, + SYNC_OUTPUT_TRIGGER_REG = 0xc, + BOARD_ID_REG = 0x10 +}; + +/* bit definitions for registers */ +enum dac_control_contents { + DAC_DATA_MASK = 0x3fff, + DAC_DESTINATION_MASK = 0xc000, + DAC_NORMAL_MODE = 0xc000, + DAC_OFFSET_MODE = 0x8000, + DAC_GAIN_MODE = 0x4000, + DAC_CHANNEL_SELECT_MASK = 0xf0000, + DAC_GROUP_SELECT_MASK = 0xf00000 +}; + +static uint32_t dac_data_bits(uint16_t dac_data) +{ + return dac_data & DAC_DATA_MASK; +} + +static uint32_t dac_channel_select_bits(unsigned channel) +{ + return (channel << 16) & DAC_CHANNEL_SELECT_MASK; +} + +static uint32_t dac_group_select_bits(unsigned group) +{ + return (1 << (20 + group)) & DAC_GROUP_SELECT_MASK; +} + +static uint32_t dac_channel_and_group_select_bits(unsigned comedi_channel) +{ + return dac_channel_select_bits(comedi_channel % 8) | + dac_group_select_bits(comedi_channel / 8); +} + +enum sync_output_contents { + SYNC_MODE = 0x1, + DAC_BUSY = 0x2, /* dac state machine is not ready */ +}; + +enum sync_output_trigger_contents { + SYNC_TRIGGER_BITS = 0x0 /* any value works */ +}; + +enum board_id_contents { + BOARD_ID_MASK = 0xf +}; + +static const struct comedi_lrange ao_ranges_1724 = { 4, + { + BIP_RANGE(10), + RANGE_mA(0, 20), + RANGE_mA(4, 20), + RANGE_unitless(0, 1) + } +}; + +static const struct comedi_lrange *const ao_range_list_1724[NUM_AO_CHANNELS] = { + [0 ... NUM_AO_CHANNELS - 1] = &ao_ranges_1724, +}; + +/* this structure is for data unique to this hardware driver. */ +struct adv_pci1724_private { + int ao_value[NUM_AO_CHANNELS]; + int offset_value[NUM_AO_CHANNELS]; + int gain_value[NUM_AO_CHANNELS]; +}; + +static int wait_for_dac_idle(struct comedi_device *dev) +{ + static const int timeout = 10000; + int i; + + for (i = 0; i < timeout; ++i) { + if ((inl(dev->iobase + SYNC_OUTPUT_REG) & DAC_BUSY) == 0) + break; + udelay(1); + } + if (i == timeout) { + comedi_error(dev, "Timed out waiting for dac to become idle."); + return -EIO; + } + return 0; +} + +static int set_dac(struct comedi_device *dev, unsigned mode, unsigned channel, + unsigned data) +{ + int retval; + unsigned control_bits; + + retval = wait_for_dac_idle(dev); + if (retval < 0) + return retval; + + control_bits = mode; + control_bits |= dac_channel_and_group_select_bits(channel); + control_bits |= dac_data_bits(data); + outl(control_bits, dev->iobase + DAC_CONTROL_REG); + return 0; +} + +static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) +{ + struct adv_pci1724_private *devpriv = dev->private; + int channel = CR_CHAN(insn->chanspec); + int retval; + int i; + + /* turn off synchronous mode */ + outl(0, dev->iobase + SYNC_OUTPUT_REG); + + for (i = 0; i < insn->n; ++i) { + retval = set_dac(dev, DAC_NORMAL_MODE, channel, data[i]); + if (retval < 0) + return retval; + devpriv->ao_value[channel] = data[i]; + } + return insn->n; +} + +static int ao_readback_insn(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) +{ + struct adv_pci1724_private *devpriv = dev->private; + int channel = CR_CHAN(insn->chanspec); + int i; + + if (devpriv->ao_value[channel] < 0) { + comedi_error(dev, + "Cannot read back channels which have not yet been written to."); + return -EIO; + } + for (i = 0; i < insn->n; i++) + data[i] = devpriv->ao_value[channel]; + + return insn->n; +} + +static int offset_write_insn(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) +{ + struct adv_pci1724_private *devpriv = dev->private; + int channel = CR_CHAN(insn->chanspec); + int retval; + int i; + + /* turn off synchronous mode */ + outl(0, dev->iobase + SYNC_OUTPUT_REG); + + for (i = 0; i < insn->n; ++i) { + retval = set_dac(dev, DAC_OFFSET_MODE, channel, data[i]); + if (retval < 0) + return retval; + devpriv->offset_value[channel] = data[i]; + } + + return insn->n; +} + +static int offset_read_insn(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) +{ + struct adv_pci1724_private *devpriv = dev->private; + unsigned int channel = CR_CHAN(insn->chanspec); + int i; + + if (devpriv->offset_value[channel] < 0) { + comedi_error(dev, + "Cannot read back channels which have not yet been written to."); + return -EIO; + } + for (i = 0; i < insn->n; i++) + data[i] = devpriv->offset_value[channel]; + + return insn->n; +} + +static int gain_write_insn(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) +{ + struct adv_pci1724_private *devpriv = dev->private; + int channel = CR_CHAN(insn->chanspec); + int retval; + int i; + + /* turn off synchronous mode */ + outl(0, dev->iobase + SYNC_OUTPUT_REG); + + for (i = 0; i < insn->n; ++i) { + retval = set_dac(dev, DAC_GAIN_MODE, channel, data[i]); + if (retval < 0) + return retval; + devpriv->gain_value[channel] = data[i]; + } + + return insn->n; +} + +static int gain_read_insn(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, + unsigned int *data) +{ + struct adv_pci1724_private *devpriv = dev->private; + unsigned int channel = CR_CHAN(insn->chanspec); + int i; + + if (devpriv->gain_value[channel] < 0) { + comedi_error(dev, + "Cannot read back channels which have not yet been written to."); + return -EIO; + } + for (i = 0; i < insn->n; i++) + data[i] = devpriv->gain_value[channel]; + + return insn->n; +} + +/* Allocate and initialize the subdevice structures. + */ +static int setup_subdevices(struct comedi_device *dev) +{ + struct comedi_subdevice *s; + int ret; + + ret = comedi_alloc_subdevices(dev, 3); + if (ret) + return ret; + + /* analog output subdevice */ + s = &dev->subdevices[0]; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND; + s->n_chan = NUM_AO_CHANNELS; + s->maxdata = 0x3fff; + s->range_table_list = ao_range_list_1724; + s->insn_read = ao_readback_insn; + s->insn_write = ao_winsn; + + /* offset calibration */ + s = &dev->subdevices[1]; + s->type = COMEDI_SUBD_CALIB; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = NUM_AO_CHANNELS; + s->insn_read = offset_read_insn; + s->insn_write = offset_write_insn; + s->maxdata = 0x3fff; + + /* gain calibration */ + s = &dev->subdevices[2]; + s->type = COMEDI_SUBD_CALIB; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = NUM_AO_CHANNELS; + s->insn_read = gain_read_insn; + s->insn_write = gain_write_insn; + s->maxdata = 0x3fff; + + return 0; +} + +static int adv_pci1724_auto_attach(struct comedi_device *dev, + unsigned long context_unused) +{ + struct pci_dev *pcidev = comedi_to_pci_dev(dev); + struct adv_pci1724_private *devpriv; + int i; + int retval; + unsigned int board_id; + + devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + if (!devpriv) + return -ENOMEM; + dev->private = devpriv; + + /* init software copies of output values to indicate we don't know + * what the output value is since it has never been written. */ + for (i = 0; i < NUM_AO_CHANNELS; ++i) { + devpriv->ao_value[i] = -1; + devpriv->offset_value[i] = -1; + devpriv->gain_value[i] = -1; + } + + retval = comedi_pci_enable(dev); + if (retval) + return retval; + + dev->iobase = pci_resource_start(pcidev, 2); + board_id = inl(dev->iobase + BOARD_ID_REG) & BOARD_ID_MASK; + dev_info(dev->class_dev, "board id: %d\n", board_id); + + retval = setup_subdevices(dev); + if (retval < 0) + return retval; + + dev_info(dev->class_dev, "%s (pci %s) attached, board id: %u\n", + dev->board_name, pci_name(pcidev), board_id); + return 0; +} + +static struct comedi_driver adv_pci1724_driver = { + .driver_name = "adv_pci1724", + .module = THIS_MODULE, + .auto_attach = adv_pci1724_auto_attach, + .detach = comedi_pci_disable, +}; + +static int adv_pci1724_pci_probe(struct pci_dev *dev, + const struct pci_device_id *id) +{ + return comedi_pci_auto_config(dev, &adv_pci1724_driver, + id->driver_data); +} + +static DEFINE_PCI_DEVICE_TABLE(adv_pci1724_pci_table) = { + { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1724) }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, adv_pci1724_pci_table); + +static struct pci_driver adv_pci1724_pci_driver = { + .name = "adv_pci1724", + .id_table = adv_pci1724_pci_table, + .probe = adv_pci1724_pci_probe, + .remove = comedi_pci_auto_unconfig, +}; + +module_comedi_pci_driver(adv_pci1724_driver, adv_pci1724_pci_driver); + +MODULE_AUTHOR("Frank Mori Hess <fmh6jj@gmail.com>"); +MODULE_DESCRIPTION("Advantech PCI-1724U Comedi driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index 338c43e716b..f70c67471c1 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -236,8 +236,6 @@ struct diosubd_data { struct dio_boardtype { const char *name; /* board name */ - int vendor_id; /* vendor/device PCI ID */ - int device_id; int main_pci_region; /* main I/O PCI region */ enum hw_cards_id cardtype; int nsubdevs; @@ -250,10 +248,8 @@ struct dio_boardtype { }; static const struct dio_boardtype boardtypes[] = { - { + [TYPE_PCI1730] = { .name = "pci1730", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1730, .main_pci_region = PCIDIO_MAINREG, .cardtype = TYPE_PCI1730, .nsubdevs = 5, @@ -263,30 +259,27 @@ static const struct dio_boardtype boardtypes[] = { .sdo[1] = { 16, PCI1730_IDO, 2, 0, }, .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, }, .io_access = IO_8b, - }, { + }, + [TYPE_PCI1733] = { .name = "pci1733", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1733, .main_pci_region = PCIDIO_MAINREG, .cardtype = TYPE_PCI1733, .nsubdevs = 2, .sdi[1] = { 32, PCI1733_IDI, 4, 0, }, .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, }, .io_access = IO_8b, - }, { + }, + [TYPE_PCI1734] = { .name = "pci1734", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1734, .main_pci_region = PCIDIO_MAINREG, .cardtype = TYPE_PCI1734, .nsubdevs = 2, .sdo[1] = { 32, PCI1734_IDO, 4, 0, }, .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, }, .io_access = IO_8b, - }, { + }, + [TYPE_PCI1735] = { .name = "pci1735", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1735, .main_pci_region = PCIDIO_MAINREG, .cardtype = TYPE_PCI1735, .nsubdevs = 4, @@ -295,10 +288,9 @@ static const struct dio_boardtype boardtypes[] = { .boardid = { 4, PCI1735_BOARDID, 1, SDF_INTERNAL, }, .s8254[0] = { 3, PCI1735_C8254, 1, 0, }, .io_access = IO_8b, - }, { + }, + [TYPE_PCI1736] = { .name = "pci1736", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1736, .main_pci_region = PCI1736_MAINREG, .cardtype = TYPE_PCI1736, .nsubdevs = 3, @@ -306,39 +298,35 @@ static const struct dio_boardtype boardtypes[] = { .sdo[1] = { 16, PCI1736_IDO, 2, 0, }, .boardid = { 4, PCI1736_BOARDID, 1, SDF_INTERNAL, }, .io_access = IO_8b, - }, { + }, + [TYPE_PCI1739] = { .name = "pci1739", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1739, .main_pci_region = PCIDIO_MAINREG, .cardtype = TYPE_PCI1739, .nsubdevs = 2, .sdio[0] = { 48, PCI1739_DIO, 2, 0, }, .io_access = IO_8b, - }, { + }, + [TYPE_PCI1750] = { .name = "pci1750", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1750, .main_pci_region = PCIDIO_MAINREG, .cardtype = TYPE_PCI1750, .nsubdevs = 2, .sdi[1] = { 16, PCI1750_IDI, 2, 0, }, .sdo[1] = { 16, PCI1750_IDO, 2, 0, }, .io_access = IO_8b, - }, { + }, + [TYPE_PCI1751] = { .name = "pci1751", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1751, .main_pci_region = PCIDIO_MAINREG, .cardtype = TYPE_PCI1751, .nsubdevs = 3, .sdio[0] = { 48, PCI1751_DIO, 2, 0, }, .s8254[0] = { 3, PCI1751_CNT, 1, 0, }, .io_access = IO_8b, - }, { + }, + [TYPE_PCI1752] = { .name = "pci1752", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1752, .main_pci_region = PCIDIO_MAINREG, .cardtype = TYPE_PCI1752, .nsubdevs = 3, @@ -346,29 +334,26 @@ static const struct dio_boardtype boardtypes[] = { .sdo[1] = { 32, PCI1752_IDO2, 2, 0, }, .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, }, .io_access = IO_16b, - }, { + }, + [TYPE_PCI1753] = { .name = "pci1753", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1753, .main_pci_region = PCIDIO_MAINREG, .cardtype = TYPE_PCI1753, .nsubdevs = 4, .sdio[0] = { 96, PCI1753_DIO, 4, 0, }, .io_access = IO_8b, - }, { + }, + [TYPE_PCI1753E] = { .name = "pci1753e", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1753, .main_pci_region = PCIDIO_MAINREG, .cardtype = TYPE_PCI1753E, .nsubdevs = 8, .sdio[0] = { 96, PCI1753_DIO, 4, 0, }, .sdio[1] = { 96, PCI1753E_DIO, 4, 0, }, .io_access = IO_8b, - }, { + }, + [TYPE_PCI1754] = { .name = "pci1754", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1754, .main_pci_region = PCIDIO_MAINREG, .cardtype = TYPE_PCI1754, .nsubdevs = 3, @@ -376,10 +361,9 @@ static const struct dio_boardtype boardtypes[] = { .sdi[1] = { 32, PCI1754_IDI2, 2, 0, }, .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, }, .io_access = IO_16b, - }, { + }, + [TYPE_PCI1756] = { .name = "pci1756", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1756, .main_pci_region = PCIDIO_MAINREG, .cardtype = TYPE_PCI1756, .nsubdevs = 3, @@ -387,19 +371,17 @@ static const struct dio_boardtype boardtypes[] = { .sdo[1] = { 32, PCI1756_IDO, 2, 0, }, .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, }, .io_access = IO_16b, - }, { + }, + [TYPE_PCI1760] = { /* This card has its own 'attach' */ .name = "pci1760", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1760, .main_pci_region = 0, .cardtype = TYPE_PCI1760, .nsubdevs = 4, .io_access = IO_8b, - }, { + }, + [TYPE_PCI1762] = { .name = "pci1762", - .vendor_id = PCI_VENDOR_ID_ADVANTECH, - .device_id = 0x1762, .main_pci_region = PCIDIO_MAINREG, .cardtype = TYPE_PCI1762, .nsubdevs = 3, @@ -1076,31 +1058,50 @@ static int pci_dio_add_8254(struct comedi_device *dev, return 0; } -static const void *pci_dio_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) +static unsigned long pci_dio_override_cardtype(struct pci_dev *pcidev, + unsigned long cardtype) { - const struct dio_boardtype *this_board; - int i; - - for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) { - this_board = &boardtypes[i]; - if (this_board->vendor_id == pcidev->vendor && - this_board->device_id == pcidev->device) - return this_board; + /* + * Change cardtype from TYPE_PCI1753 to TYPE_PCI1753E if expansion + * board available. Need to enable PCI device and request the main + * registers PCI BAR temporarily to perform the test. + */ + if (cardtype != TYPE_PCI1753) + return cardtype; + if (pci_enable_device(pcidev) < 0) + return cardtype; + if (pci_request_region(pcidev, PCIDIO_MAINREG, "adv_pci_dio") == 0) { + /* + * This test is based on Advantech's "advdaq" driver source + * (which declares its module licence as "GPL" although the + * driver source does not include a "COPYING" file). + */ + unsigned long reg = + pci_resource_start(pcidev, PCIDIO_MAINREG) + 53; + + outb(0x05, reg); + if ((inb(reg) & 0x07) == 0x02) { + outb(0x02, reg); + if ((inb(reg) & 0x07) == 0x05) + cardtype = TYPE_PCI1753E; + } + pci_release_region(pcidev, PCIDIO_MAINREG); } - return NULL; + pci_disable_device(pcidev); + return cardtype; } static int pci_dio_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct dio_boardtype *this_board; + const struct dio_boardtype *this_board = NULL; struct pci_dio_private *devpriv; struct comedi_subdevice *s; int ret, subdev, i, j; - this_board = pci_dio_find_boardinfo(dev, pcidev); + if (context < ARRAY_SIZE(boardtypes)) + this_board = &boardtypes[context]; if (!this_board) return -ENODEV; dev->board_ptr = this_board; @@ -1111,7 +1112,7 @@ static int pci_dio_auto_attach(struct comedi_device *dev, return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pcidev, this_board->main_pci_region); @@ -1172,7 +1173,6 @@ static int pci_dio_auto_attach(struct comedi_device *dev, static void pci_dio_detach(struct comedi_device *dev) { struct pci_dio_private *devpriv = dev->private; - struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct comedi_subdevice *s; int i; @@ -1180,18 +1180,13 @@ static void pci_dio_detach(struct comedi_device *dev) if (devpriv->valid) pci_dio_reset(dev); } - if (dev->subdevices) { - for (i = 0; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; - if (s->type == COMEDI_SUBD_DIO) - subdev_8255_cleanup(dev, s); - s->private = NULL; - } - } - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); + for (i = 0; i < dev->n_subdevices; i++) { + s = &dev->subdevices[i]; + if (s->type == COMEDI_SUBD_DIO) + comedi_spriv_free(dev, i); + s->private = NULL; /* some private data is static */ } + comedi_pci_disable(dev); } static struct comedi_driver adv_pci_dio_driver = { @@ -1202,26 +1197,29 @@ static struct comedi_driver adv_pci_dio_driver = { }; static int adv_pci_dio_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &adv_pci_dio_driver); + unsigned long cardtype; + + cardtype = pci_dio_override_cardtype(dev, id->driver_data); + return comedi_pci_auto_config(dev, &adv_pci_dio_driver, cardtype); } static DEFINE_PCI_DEVICE_TABLE(adv_pci_dio_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1730) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1733) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1734) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1735) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1736) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1739) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1750) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1751) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1752) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1753) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1754) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1756) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1760) }, - { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1762) }, + { PCI_VDEVICE(ADVANTECH, 0x1730), TYPE_PCI1730 }, + { PCI_VDEVICE(ADVANTECH, 0x1733), TYPE_PCI1733 }, + { PCI_VDEVICE(ADVANTECH, 0x1734), TYPE_PCI1734 }, + { PCI_VDEVICE(ADVANTECH, 0x1735), TYPE_PCI1735 }, + { PCI_VDEVICE(ADVANTECH, 0x1736), TYPE_PCI1736 }, + { PCI_VDEVICE(ADVANTECH, 0x1739), TYPE_PCI1739 }, + { PCI_VDEVICE(ADVANTECH, 0x1750), TYPE_PCI1750 }, + { PCI_VDEVICE(ADVANTECH, 0x1751), TYPE_PCI1751 }, + { PCI_VDEVICE(ADVANTECH, 0x1752), TYPE_PCI1752 }, + { PCI_VDEVICE(ADVANTECH, 0x1753), TYPE_PCI1753 }, + { PCI_VDEVICE(ADVANTECH, 0x1754), TYPE_PCI1754 }, + { PCI_VDEVICE(ADVANTECH, 0x1756), TYPE_PCI1756 }, + { PCI_VDEVICE(ADVANTECH, 0x1760), TYPE_PCI1760 }, + { PCI_VDEVICE(ADVANTECH, 0x1762), TYPE_PCI1762 }, { 0 } }; MODULE_DEVICE_TABLE(pci, adv_pci_dio_pci_table); diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c index 601f03d5897..e2dc08a058b 100644 --- a/drivers/staging/comedi/drivers/aio_aio12_8.c +++ b/drivers/staging/comedi/drivers/aio_aio12_8.c @@ -200,17 +200,11 @@ static int aio_aio12_8_attach(struct comedi_device *dev, const struct aio12_8_boardtype *board = comedi_board(dev); struct aio12_8_private *devpriv; struct comedi_subdevice *s; - int iobase; int ret; - dev->board_name = board->name; - - iobase = it->options[0]; - if (!request_region(iobase, 32, dev->board_name)) { - printk(KERN_ERR "I/O port conflict"); - return -EIO; - } - dev->iobase = iobase; + ret = comedi_request_region(dev, it->options[0], 32); + if (ret) + return ret; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) @@ -250,8 +244,8 @@ static int aio_aio12_8_attach(struct comedi_device *dev, s = &dev->subdevices[2]; /* 8255 Digital i/o subdevice */ - iobase = dev->iobase + AIO12_8_8255_BASE_REG; - ret = subdev_8255_init(dev, s, NULL, iobase); + ret = subdev_8255_init(dev, s, NULL, + dev->iobase + AIO12_8_8255_BASE_REG); if (ret) return ret; @@ -267,10 +261,8 @@ static int aio_aio12_8_attach(struct comedi_device *dev, static void aio_aio12_8_detach(struct comedi_device *dev) { - if (dev->subdevices) - subdev_8255_cleanup(dev, &dev->subdevices[2]); - if (dev->iobase) - release_region(dev->iobase, 24); + comedi_spriv_free(dev, 2); + comedi_legacy_detach(dev); } static struct comedi_driver aio_aio12_8_driver = { diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 64c1ae58ce7..126854c0509 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -77,22 +77,12 @@ static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev, static int aio_iiro_16_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - int iobase; struct comedi_subdevice *s; int ret; - printk(KERN_INFO "comedi%d: aio_iiro_16: ", dev->minor); - - dev->board_name = dev->driver->driver_name; - - iobase = it->options[0]; - - if (!request_region(iobase, AIO_IIRO_16_SIZE, dev->board_name)) { - printk("I/O port conflict"); - return -EIO; - } - - dev->iobase = iobase; + ret = comedi_request_region(dev, it->options[0], AIO_IIRO_16_SIZE); + if (ret) + return ret; ret = comedi_alloc_subdevices(dev, 2); if (ret) @@ -114,22 +104,14 @@ static int aio_iiro_16_attach(struct comedi_device *dev, s->range_table = &range_digital; s->insn_bits = aio_iiro_16_dio_insn_bits_read; - printk("attached\n"); - return 1; } -static void aio_iiro_16_detach(struct comedi_device *dev) -{ - if (dev->iobase) - release_region(dev->iobase, AIO_IIRO_16_SIZE); -} - static struct comedi_driver aio_iiro_16_driver = { .driver_name = "aio_iiro_16", .module = THIS_MODULE, .attach = aio_iiro_16_attach, - .detach = aio_iiro_16_detach, + .detach = comedi_legacy_detach, }; module_comedi_driver(aio_iiro_16_driver); diff --git a/drivers/staging/comedi/drivers/am9513.h b/drivers/staging/comedi/drivers/am9513.h deleted file mode 100644 index 0bb839e5149..00000000000 --- a/drivers/staging/comedi/drivers/am9513.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - module/am9513.h - value added preprocessor definitions for Am9513 timer chip - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1998 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef _AM9513_H_ -#define _AM9513_H_ - -#if 0 - -/* - * Before including this file, the following need to be defined: - */ -#define Am9513_8BITBUS xxx -/* or */ -#define Am9513_16BITBUS xxx - -#define Am9513_output_control(a) xxx -#define Am9513_input_status() xxx -#define Am9513_output_data(a) xxx -#define Am9513_input_data() xxx - -#endif - -/* - * - */ - -#ifdef Am9513_8BITBUS - -#define Am9513_write_register(reg, val) \ - do { \ - Am9513_output_control(reg); \ - Am9513_output_data(val>>8); \ - Am9513_output_data(val&0xff); \ - } while (0) - -#define Am9513_read_register(reg, val) \ - do { \ - Am9513_output_control(reg); \ - val = Am9513_input_data()<<8; \ - val |= Am9513_input_data(); \ - } while (0) - -#else /* Am9513_16BITBUS */ - -#define Am9513_write_register(reg, val) \ - do { \ - Am9513_output_control(reg); \ - Am9513_output_data(val); \ - } while (0) - -#define Am9513_read_register(reg, val) \ - do { \ - Am9513_output_control(reg); \ - val = Am9513_input_data(); \ - } while (0) - -#endif - -#endif diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 7c53dea12c7..297750bef0f 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -1,10 +1,9 @@ /* comedi/drivers/amplc_dio200.c - Driver for Amplicon PC272E and PCI272 DIO boards. - (Support for other boards in Amplicon 200 series may be added at - a later date, e.g. PCI215.) - Copyright (C) 2005 MEV Ltd. <http://www.mev.co.uk/> + Driver for Amplicon PC212E, PC214E, PC215E, PC218E, PC272E. + + Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> COMEDI - Linux Control and Measurement Device Interface Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> @@ -26,26 +25,23 @@ */ /* * Driver: amplc_dio200 - * Description: Amplicon 200 Series Digital I/O + * Description: Amplicon 200 Series ISA Digital I/O * Author: Ian Abbott <abbotti@mev.co.uk> * Devices: [Amplicon] PC212E (pc212e), PC214E (pc214e), PC215E (pc215e), - * PCI215 (pci215), PCIe215 (pcie215), PC218E (pc218e), PCIe236 (pcie236), - * PC272E (pc272e), PCI272 (pci272), PCIe296 (pcie296) - * Updated: Wed, 24 Oct 2012 16:22:34 +0100 + * PC218E (pc218e), PC272E (pc272e) + * Updated: Mon, 18 Mar 2013 14:40:41 +0000 + * * Status: works * - * Configuration options - PC212E, PC214E, PC215E, PC218E, PC272E: + * Configuration options: * [0] - I/O port base address * [1] - IRQ (optional, but commands won't work without it) * - * Manual configuration of PCI(e) cards is not supported; they are configured - * automatically. - * * Passing a zero for an option is the same as leaving it unspecified. * * SUBDEVICES * - * PC212E PC214E PC215E/PCI215 + * PC212E PC214E PC215E * ------------- ------------- ------------- * Subdevices 6 4 5 * 0 PPI-X PPI-X PPI-X @@ -55,29 +51,16 @@ * 4 CTR-Z2 INTERRUPT * 5 INTERRUPT * - * PCIe215 PC218E PCIe236 - * ------------- ------------- ------------- - * Subdevices 8 7 8 - * 0 PPI-X CTR-X1 PPI-X - * 1 UNUSED CTR-X2 UNUSED - * 2 PPI-Y CTR-Y1 UNUSED - * 3 UNUSED CTR-Y2 UNUSED - * 4 CTR-Z1 CTR-Z1 CTR-Z1 - * 5 CTR-Z2 CTR-Z2 CTR-Z2 - * 6 TIMER INTERRUPT TIMER - * 7 INTERRUPT INTERRUPT - * - * PC272E/PCI272 PCIe296 + * PC218E PC272E * ------------- ------------- - * Subdevices 4 8 - * 0 PPI-X PPI-X1 - * 1 PPI-Y PPI-X2 - * 2 PPI-Z PPI-Y1 - * 3 INTERRUPT PPI-Y2 - * 4 CTR-Z1 - * 5 CTR-Z2 - * 6 TIMER - * 7 INTERRUPT + * Subdevices 7 4 + * 0 CTR-X1 PPI-X + * 1 CTR-X2 PPI-Y + * 2 CTR-Y1 PPI-Z + * 3 CTR-Y2 INTERRUPT + * 4 CTR-Z1 + * 5 CTR-Z2 + * 6 INTERRUPT * * Each PPI is a 8255 chip providing 24 DIO channels. The DIO channels * are configurable as inputs or outputs in four groups: @@ -120,14 +103,6 @@ * the SK1 connector. This pin is shared by all three counter * channels on the chip. * - * For the PCIe boards, clock sources in the range 0 to 31 are allowed - * and the following additional clock sources are defined: - * - * 8. HIGH logic level. - * 9. LOW logic level. - * 10. "Pattern present" signal. - * 11. Internal 20 MHz clock. - * * INSN_CONFIG_GET_CLOCK_SRC. Returns the counter channel's current * clock source in data[1]. For internal clock sources, data[2] is set * to the period in ns. @@ -149,27 +124,6 @@ * 6. Reserved. * 7. Reserved. * - * For the PCIe boards, gate sources in the range 0 to 31 are allowed; - * the following additional clock sources and clock sources 6 and 7 are - * (re)defined: - * - * 6. /GAT n, negated version of the counter channel's dedicated - * GAT input (negated version of gate source 2). - * 7. OUT n-2, the non-inverted output of counter channel n-2 - * (negated version of gate source 3). - * 8. "Pattern present" signal, HIGH while pattern present. - * 9. "Pattern occurred" latched signal, latches HIGH when pattern - * occurs. - * 10. "Pattern gone away" latched signal, latches LOW when pattern - * goes away after it occurred. - * 11. Negated "pattern present" signal, LOW while pattern present - * (negated version of gate source 8). - * 12. Negated "pattern occurred" latched signal, latches LOW when - * pattern occurs (negated version of gate source 9). - * 13. Negated "pattern gone away" latched signal, latches LOW when - * pattern goes away after it occurred (negated version of gate - * source 10). - * * INSN_CONFIG_GET_GATE_SRC. Returns the counter channel's current gate * source in data[2]. * @@ -186,8 +140,6 @@ * 3. The counter subdevices are connected in a ring, so the highest * counter subdevice precedes the lowest. * - * The 'TIMER' subdevice is a free-running 32-bit timer subdevice. - * * The 'INTERRUPT' subdevice pretends to be a digital input subdevice. The * digital inputs come from the interrupt status register. The number of * channels matches the number of interrupt sources. The PC214E does not @@ -196,7 +148,7 @@ * * INTERRUPT SOURCES * - * PC212E PC214E PC215E/PCI215 + * PC212E PC214E PC215E * ------------- ------------- ------------- * Sources 6 1 6 * 0 PPI-X-C0 JUMPER-J5 PPI-X-C0 @@ -206,25 +158,15 @@ * 4 CTR-Z1-OUT1 CTR-Z1-OUT1 * 5 CTR-Z2-OUT1 CTR-Z2-OUT1 * - * PCIe215 PC218E PCIe236 - * ------------- ------------- ------------- - * Sources 6 6 6 - * 0 PPI-X-C0 CTR-X1-OUT1 PPI-X-C0 - * 1 PPI-X-C3 CTR-X2-OUT1 PPI-X-C3 - * 2 PPI-Y-C0 CTR-Y1-OUT1 unused - * 3 PPI-Y-C3 CTR-Y2-OUT1 unused - * 4 CTR-Z1-OUT1 CTR-Z1-OUT1 CTR-Z1-OUT1 - * 5 CTR-Z2-OUT1 CTR-Z2-OUT1 CTR-Z2-OUT1 - * - * PC272E/PCI272 PCIe296 + * PC218E PC272E * ------------- ------------- * Sources 6 6 - * 0 PPI-X-C0 PPI-X1-C0 - * 1 PPI-X-C3 PPI-X1-C3 - * 2 PPI-Y-C0 PPI-Y1-C0 - * 3 PPI-Y-C3 PPI-Y1-C3 - * 4 PPI-Z-C0 CTR-Z1-OUT1 - * 5 PPI-Z-C3 CTR-Z2-OUT1 + * 0 CTR-X1-OUT1 PPI-X-C0 + * 1 CTR-X2-OUT1 PPI-X-C3 + * 2 CTR-Y1-OUT1 PPI-Y-C0 + * 3 CTR-Y2-OUT1 PPI-Y-C3 + * 4 CTR-Z1-OUT1 PPI-Z-C0 + * 5 CTR-Z2-OUT1 PPI-Z-C3 * * When an interrupt source is enabled in the interrupt source enable * register, a rising edge on the source signal latches the corresponding @@ -232,14 +174,11 @@ * * When the interrupt status register value as a whole (actually, just the * 6 least significant bits) goes from zero to non-zero, the board will - * generate an interrupt. For level-triggered hardware interrupts (PCI - * card), the interrupt will remain asserted until the interrupt status - * register is cleared to zero. For edge-triggered hardware interrupts - * (ISA card), no further interrupts will occur until the interrupt status - * register is cleared to zero. To clear a bit to zero in the interrupt - * status register, the corresponding interrupt source must be disabled - * in the interrupt source enable register (there is no separate interrupt - * clear register). + * generate an interrupt. No further interrupts will occur until the + * interrupt status register is cleared to zero. To clear a bit to zero in + * the interrupt status register, the corresponding interrupt source must + * be disabled in the interrupt source enable register (there is no + * separate interrupt clear register). * * The PC214E does not have an interrupt source enable register or an * interrupt status register; its 'INTERRUPT' subdevice has a single @@ -258,1835 +197,116 @@ * order they appear in the channel list. */ -#include <linux/pci.h> -#include <linux/interrupt.h> #include <linux/slab.h> #include "../comedidev.h" -#include "comedi_fc.h" -#include "8253.h" - -#define DIO200_DRIVER_NAME "amplc_dio200" - -#define DO_ISA IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) -#define DO_PCI IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) - -/* 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 - -/* 8255 control register bits */ -#define CR_C_LO_IO 0x01 -#define CR_B_IO 0x02 -#define CR_B_MODE 0x04 -#define CR_C_HI_IO 0x08 -#define CR_A_IO 0x10 -#define CR_A_MODE(a) ((a)<<5) -#define CR_CW 0x80 - -/* 200 series registers */ -#define DIO200_IO_SIZE 0x20 -#define DIO200_PCIE_IO_SIZE 0x4000 -#define DIO200_XCLK_SCE 0x18 /* Group X clock selection register */ -#define DIO200_YCLK_SCE 0x19 /* Group Y clock selection register */ -#define DIO200_ZCLK_SCE 0x1a /* Group Z clock selection register */ -#define DIO200_XGAT_SCE 0x1b /* Group X gate selection register */ -#define DIO200_YGAT_SCE 0x1c /* Group Y gate selection register */ -#define DIO200_ZGAT_SCE 0x1d /* Group Z gate selection register */ -#define DIO200_INT_SCE 0x1e /* Interrupt enable/status register */ -/* Extra registers for new PCIe boards */ -#define DIO200_ENHANCE 0x20 /* 1 to enable enhanced features */ -#define DIO200_VERSION 0x24 /* Hardware version register */ -#define DIO200_TS_CONFIG 0x600 /* Timestamp timer config register */ -#define DIO200_TS_COUNT 0x602 /* Timestamp timer count register */ - -/* - * Functions for constructing value for DIO_200_?CLK_SCE and - * DIO_200_?GAT_SCE registers: - * - * 'which' is: 0 for CTR-X1, CTR-Y1, CTR-Z1; 1 for CTR-X2, CTR-Y2 or CTR-Z2. - * 'chan' is the channel: 0, 1 or 2. - * 'source' is the signal source: 0 to 7, or 0 to 31 for "enhanced" boards. - */ -static unsigned char clk_gat_sce(unsigned int which, unsigned int chan, - unsigned int source) -{ - return (which << 5) | (chan << 3) | - ((source & 030) << 3) | (source & 007); -} - -static unsigned char clk_sce(unsigned int which, unsigned int chan, - unsigned int source) -{ - return clk_gat_sce(which, chan, source); -} - -static unsigned char gat_sce(unsigned int which, unsigned int chan, - unsigned int source) -{ - return clk_gat_sce(which, chan, source); -} - -/* - * Periods of the internal clock sources in nanoseconds. - */ -static const unsigned int clock_period[32] = { - [1] = 100, /* 10 MHz */ - [2] = 1000, /* 1 MHz */ - [3] = 10000, /* 100 kHz */ - [4] = 100000, /* 10 kHz */ - [5] = 1000000, /* 1 kHz */ - [11] = 50, /* 20 MHz (enhanced boards) */ - /* clock sources 12 and later reserved for enhanced boards */ -}; - -/* - * Timestamp timer configuration register (for new PCIe boards). - */ -#define TS_CONFIG_RESET 0x100 /* Reset counter to zero. */ -#define TS_CONFIG_CLK_SRC_MASK 0x0FF /* Clock source. */ -#define TS_CONFIG_MAX_CLK_SRC 2 /* Maximum clock source value. */ - -/* - * Periods of the timestamp timer clock sources in nanoseconds. - */ -static const unsigned int ts_clock_period[TS_CONFIG_MAX_CLK_SRC + 1] = { - 1, /* 1 nanosecond (but with 20 ns granularity). */ - 1000, /* 1 microsecond. */ - 1000000, /* 1 millisecond. */ -}; - -/* - * 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; -}; +#include "amplc_dio200.h" /* * Board descriptions. */ - -enum dio200_bustype { isa_bustype, pci_bustype }; - -enum dio200_model { - pc212e_model, - pc214e_model, - pc215e_model, pci215_model, pcie215_model, - pc218e_model, - pcie236_model, - pc272e_model, pci272_model, - pcie296_model, -}; - -enum dio200_layout_idx { -#if DO_ISA - pc212_layout, - pc214_layout, -#endif - pc215_layout, -#if DO_ISA - pc218_layout, -#endif - pc272_layout, -#if DO_PCI - pcie215_layout, - pcie236_layout, - pcie296_layout, -#endif -}; - -struct dio200_board { - const char *name; - unsigned short devid; - enum dio200_bustype bustype; - enum dio200_model model; - enum dio200_layout_idx layout; - unsigned char mainbar; - unsigned char mainshift; - unsigned int mainsize; -}; - -static const struct dio200_board dio200_boards[] = { -#if DO_ISA - { - .name = "pc212e", - .bustype = isa_bustype, - .model = pc212e_model, - .layout = pc212_layout, - .mainsize = DIO200_IO_SIZE, - }, - { - .name = "pc214e", - .bustype = isa_bustype, - .model = pc214e_model, - .layout = pc214_layout, - .mainsize = DIO200_IO_SIZE, - }, - { - .name = "pc215e", - .bustype = isa_bustype, - .model = pc215e_model, - .layout = pc215_layout, - .mainsize = DIO200_IO_SIZE, - }, - { - .name = "pc218e", - .bustype = isa_bustype, - .model = pc218e_model, - .layout = pc218_layout, - .mainsize = DIO200_IO_SIZE, - }, +static const struct dio200_board dio200_isa_boards[] = { { - .name = "pc272e", - .bustype = isa_bustype, - .model = pc272e_model, - .layout = pc272_layout, - .mainsize = DIO200_IO_SIZE, - }, -#endif -#if DO_PCI + .name = "pc212e", + .bustype = isa_bustype, + .mainsize = DIO200_IO_SIZE, + .layout = { + .n_subdevs = 6, + .sdtype = {sd_8255, sd_8254, sd_8254, sd_8254, sd_8254, + sd_intr}, + .sdinfo = {0x00, 0x08, 0x0C, 0x10, 0x14, 0x3F}, + .has_int_sce = true, + .has_clk_gat_sce = true, + }, + }, { - .name = "pci215", - .devid = PCI_DEVICE_ID_AMPLICON_PCI215, - .bustype = pci_bustype, - .model = pci215_model, - .layout = pc215_layout, - .mainbar = 2, - .mainsize = DIO200_IO_SIZE, - }, + .name = "pc214e", + .bustype = isa_bustype, + .mainsize = DIO200_IO_SIZE, + .layout = { + .n_subdevs = 4, + .sdtype = {sd_8255, sd_8255, sd_8254, sd_intr}, + .sdinfo = {0x00, 0x08, 0x10, 0x01}, + }, + }, { - .name = "pci272", - .devid = PCI_DEVICE_ID_AMPLICON_PCI272, - .bustype = pci_bustype, - .model = pci272_model, - .layout = pc272_layout, - .mainbar = 2, - .mainsize = DIO200_IO_SIZE, - }, + .name = "pc215e", + .bustype = isa_bustype, + .mainsize = DIO200_IO_SIZE, + .layout = { + .n_subdevs = 5, + .sdtype = {sd_8255, sd_8255, sd_8254, sd_8254, sd_intr}, + .sdinfo = {0x00, 0x08, 0x10, 0x14, 0x3F}, + .has_int_sce = true, + .has_clk_gat_sce = true, + }, + }, { - .name = "pcie215", - .devid = PCI_DEVICE_ID_AMPLICON_PCIE215, - .bustype = pci_bustype, - .model = pcie215_model, - .layout = pcie215_layout, - .mainbar = 1, - .mainshift = 3, - .mainsize = DIO200_PCIE_IO_SIZE, - }, + .name = "pc218e", + .bustype = isa_bustype, + .mainsize = DIO200_IO_SIZE, + .layout = { + .n_subdevs = 7, + .sdtype = {sd_8254, sd_8254, sd_8255, sd_8254, sd_8254, + sd_intr}, + .sdinfo = {0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x3F}, + .has_int_sce = true, + .has_clk_gat_sce = true, + }, + }, { - .name = "pcie236", - .devid = PCI_DEVICE_ID_AMPLICON_PCIE236, - .bustype = pci_bustype, - .model = pcie236_model, - .layout = pcie236_layout, - .mainbar = 1, - .mainshift = 3, - .mainsize = DIO200_PCIE_IO_SIZE, - }, - { - .name = "pcie296", - .devid = PCI_DEVICE_ID_AMPLICON_PCIE296, - .bustype = pci_bustype, - .model = pcie296_model, - .layout = pcie296_layout, - .mainbar = 1, - .mainshift = 3, - .mainsize = DIO200_PCIE_IO_SIZE, - }, -#endif -}; - -/* - * Layout descriptions - some ISA and PCI board descriptions share the same - * layout. - */ - -enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254, sd_timer }; - -#define DIO200_MAX_SUBDEVS 8 -#define DIO200_MAX_ISNS 6 - -struct dio200_layout { - unsigned short n_subdevs; /* number of subdevices */ - unsigned char sdtype[DIO200_MAX_SUBDEVS]; /* enum dio200_sdtype */ - unsigned char sdinfo[DIO200_MAX_SUBDEVS]; /* depends on sdtype */ - char has_int_sce; /* has interrupt enable/status register */ - char has_clk_gat_sce; /* has clock/gate selection registers */ - char has_enhancements; /* has enhanced features */ -}; - -static const struct dio200_layout dio200_layouts[] = { -#if DO_ISA - [pc212_layout] = { - .n_subdevs = 6, - .sdtype = {sd_8255, sd_8254, sd_8254, sd_8254, - sd_8254, - sd_intr}, - .sdinfo = {0x00, 0x08, 0x0C, 0x10, 0x14, - 0x3F}, - .has_int_sce = 1, - .has_clk_gat_sce = 1, - }, - [pc214_layout] = { - .n_subdevs = 4, - .sdtype = {sd_8255, sd_8255, sd_8254, - sd_intr}, - .sdinfo = {0x00, 0x08, 0x10, 0x01}, - .has_int_sce = 0, - .has_clk_gat_sce = 0, - }, -#endif - [pc215_layout] = { - .n_subdevs = 5, - .sdtype = {sd_8255, sd_8255, sd_8254, - sd_8254, - sd_intr}, - .sdinfo = {0x00, 0x08, 0x10, 0x14, 0x3F}, - .has_int_sce = 1, - .has_clk_gat_sce = 1, - }, -#if DO_ISA - [pc218_layout] = { - .n_subdevs = 7, - .sdtype = {sd_8254, sd_8254, sd_8255, sd_8254, - sd_8254, - sd_intr}, - .sdinfo = {0x00, 0x04, 0x08, 0x0C, 0x10, - 0x14, - 0x3F}, - .has_int_sce = 1, - .has_clk_gat_sce = 1, - }, -#endif - [pc272_layout] = { - .n_subdevs = 4, - .sdtype = {sd_8255, sd_8255, sd_8255, - sd_intr}, - .sdinfo = {0x00, 0x08, 0x10, 0x3F}, - .has_int_sce = 1, - .has_clk_gat_sce = 0, - }, -#if DO_PCI - [pcie215_layout] = { - .n_subdevs = 8, - .sdtype = {sd_8255, sd_none, sd_8255, sd_none, - sd_8254, sd_8254, sd_timer, sd_intr}, - .sdinfo = {0x00, 0x00, 0x08, 0x00, - 0x10, 0x14, 0x00, 0x3F}, - .has_int_sce = 1, - .has_clk_gat_sce = 1, - .has_enhancements = 1, - }, - [pcie236_layout] = { - .n_subdevs = 8, - .sdtype = {sd_8255, sd_none, sd_none, sd_none, - sd_8254, sd_8254, sd_timer, sd_intr}, - .sdinfo = {0x00, 0x00, 0x00, 0x00, - 0x10, 0x14, 0x00, 0x3F}, - .has_int_sce = 1, - .has_clk_gat_sce = 1, - .has_enhancements = 1, - }, - [pcie296_layout] = { - .n_subdevs = 8, - .sdtype = {sd_8255, sd_8255, sd_8255, sd_8255, - sd_8254, sd_8254, sd_timer, sd_intr}, - .sdinfo = {0x00, 0x04, 0x08, 0x0C, - 0x10, 0x14, 0x00, 0x3F}, - .has_int_sce = 1, - .has_clk_gat_sce = 1, - .has_enhancements = 1, - }, -#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 dio200_private { - struct dio200_region io; /* Register region */ - int intr_sd; -}; - -struct dio200_subdev_8254 { - unsigned int ofs; /* Counter base offset */ - unsigned int clk_sce_ofs; /* CLK_SCE base address */ - unsigned int gat_sce_ofs; /* GAT_SCE base address */ - int which; /* Bit 5 of CLK_SCE or GAT_SCE */ - unsigned int clock_src[3]; /* Current clock sources */ - unsigned int gate_src[3]; /* Current gate sources */ - spinlock_t spinlock; -}; - -struct dio200_subdev_8255 { - unsigned int ofs; /* DIO base offset */ + .name = "pc272e", + .bustype = isa_bustype, + .mainsize = DIO200_IO_SIZE, + .layout = { + .n_subdevs = 4, + .sdtype = {sd_8255, sd_8255, sd_8255, sd_intr}, + .sdinfo = {0x00, 0x08, 0x10, 0x3F}, + .has_int_sce = true, + }, + }, }; -struct dio200_subdev_intr { - unsigned int ofs; - spinlock_t spinlock; - int active; - unsigned int valid_isns; - unsigned int enabled_isns; - unsigned int stopcount; - int continuous; -}; - -static inline const struct dio200_layout * -dio200_board_layout(const struct dio200_board *board) -{ - return &dio200_layouts[board->layout]; -} - -static inline const struct dio200_layout * -dio200_dev_layout(struct comedi_device *dev) -{ - return dio200_board_layout(comedi_board(dev)); -} - -static inline bool is_pci_board(const struct dio200_board *board) -{ - return DO_PCI && board->bustype == pci_bustype; -} - -static inline bool is_isa_board(const struct dio200_board *board) -{ - return DO_ISA && board->bustype == isa_bustype; -} - -/* - * Read 8-bit register. - */ -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); -} - -/* - * Write 8-bit register. - */ -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); - else - writeb(val, devpriv->io.u.membase + offset); -} - -/* - * Read 32-bit register. - */ -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); -} - -/* - * Write 32-bit register. - */ -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); - else - writel(val, devpriv->io.u.membase + offset); -} - -/* - * This function looks for a board matching the supplied PCI device. - */ -static const struct dio200_board * -dio200_find_pci_board(struct pci_dev *pci_dev) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(dio200_boards); i++) - if (is_pci_board(&dio200_boards[i]) && - pci_dev->device == dio200_boards[i].devid) - return &dio200_boards[i]; - return NULL; -} - -/* - * This function checks and requests an I/O region, reporting an error - * if there is a conflict. - */ -static int -dio200_request_region(struct comedi_device *dev, - unsigned long from, unsigned long extent) -{ - if (!from || !request_region(from, extent, DIO200_DRIVER_NAME)) { - dev_err(dev->class_dev, "I/O port conflict (%#lx,%lu)!\n", - from, extent); - return -EIO; - } - return 0; -} - -/* - * 'insn_bits' function for an 'INTERRUPT' subdevice. - */ -static int -dio200_subdev_intr_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - const struct dio200_layout *layout = dio200_dev_layout(dev); - struct dio200_subdev_intr *subpriv = s->private; - - if (layout->has_int_sce) { - /* Just read the interrupt status register. */ - data[1] = dio200_read8(dev, subpriv->ofs) & subpriv->valid_isns; - } else { - /* No interrupt status register. */ - data[0] = 0; - } - - return insn->n; -} - -/* - * Called to stop acquisition for an 'INTERRUPT' subdevice. - */ -static void dio200_stop_intr(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - const struct dio200_layout *layout = dio200_dev_layout(dev); - struct dio200_subdev_intr *subpriv = s->private; - - subpriv->active = 0; - subpriv->enabled_isns = 0; - if (layout->has_int_sce) - dio200_write8(dev, subpriv->ofs, 0); -} - -/* - * Called to start acquisition for an 'INTERRUPT' subdevice. - */ -static int dio200_start_intr(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - unsigned int n; - unsigned isn_bits; - const struct dio200_layout *layout = dio200_dev_layout(dev); - struct dio200_subdev_intr *subpriv = s->private; - struct comedi_cmd *cmd = &s->async->cmd; - int retval = 0; - - if (!subpriv->continuous && subpriv->stopcount == 0) { - /* An empty acquisition! */ - s->async->events |= COMEDI_CB_EOA; - subpriv->active = 0; - retval = 1; - } else { - /* Determine interrupt sources to enable. */ - isn_bits = 0; - if (cmd->chanlist) { - for (n = 0; n < cmd->chanlist_len; n++) - isn_bits |= (1U << CR_CHAN(cmd->chanlist[n])); - } - isn_bits &= subpriv->valid_isns; - /* Enable interrupt sources. */ - subpriv->enabled_isns = isn_bits; - if (layout->has_int_sce) - dio200_write8(dev, subpriv->ofs, isn_bits); - } - - return retval; -} - -/* - * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice. - */ -static int -dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int trignum) -{ - struct dio200_subdev_intr *subpriv; - unsigned long flags; - int event = 0; - - if (trignum != 0) - return -EINVAL; - - subpriv = s->private; - - spin_lock_irqsave(&subpriv->spinlock, flags); - s->async->inttrig = NULL; - if (subpriv->active) - event = dio200_start_intr(dev, s); - - spin_unlock_irqrestore(&subpriv->spinlock, flags); - - if (event) - comedi_event(dev, s); - - return 1; -} - -/* - * This is called from the interrupt service routine to handle a read - * scan on an 'INTERRUPT' subdevice. - */ -static int dio200_handle_read_intr(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - const struct dio200_layout *layout = dio200_dev_layout(dev); - struct dio200_subdev_intr *subpriv = s->private; - unsigned triggered; - unsigned intstat; - unsigned cur_enabled; - unsigned int oldevents; - unsigned long flags; - - triggered = 0; - - spin_lock_irqsave(&subpriv->spinlock, flags); - oldevents = s->async->events; - if (layout->has_int_sce) { - /* - * Collect interrupt sources that have triggered and disable - * them temporarily. Loop around until no extra interrupt - * sources have triggered, at which point, the valid part of - * the interrupt status register will read zero, clearing the - * cause of the interrupt. - * - * Mask off interrupt sources already seen to avoid infinite - * loop in case of misconfiguration. - */ - cur_enabled = subpriv->enabled_isns; - while ((intstat = (dio200_read8(dev, subpriv->ofs) & - subpriv->valid_isns & ~triggered)) != 0) { - triggered |= intstat; - cur_enabled &= ~triggered; - dio200_write8(dev, subpriv->ofs, cur_enabled); - } - } else { - /* - * No interrupt status register. Assume the single interrupt - * source has triggered. - */ - triggered = subpriv->enabled_isns; - } - - if (triggered) { - /* - * Some interrupt sources have triggered and have been - * temporarily disabled to clear the cause of the interrupt. - * - * Reenable them NOW to minimize the time they are disabled. - */ - cur_enabled = subpriv->enabled_isns; - if (layout->has_int_sce) - dio200_write8(dev, subpriv->ofs, cur_enabled); - - if (subpriv->active) { - /* - * The command is still active. - * - * Ignore interrupt sources that the command isn't - * interested in (just in case there's a race - * condition). - */ - if (triggered & subpriv->enabled_isns) { - /* Collect scan data. */ - short val; - unsigned int n, ch, len; - - val = 0; - len = s->async->cmd.chanlist_len; - for (n = 0; n < len; n++) { - ch = CR_CHAN(s->async->cmd.chanlist[n]); - if (triggered & (1U << ch)) - val |= (1U << n); - } - /* Write the scan to the buffer. */ - if (comedi_buf_put(s->async, val)) { - s->async->events |= (COMEDI_CB_BLOCK | - COMEDI_CB_EOS); - } else { - /* Error! Stop acquisition. */ - dio200_stop_intr(dev, s); - s->async->events |= COMEDI_CB_ERROR - | COMEDI_CB_OVERFLOW; - comedi_error(dev, "buffer overflow"); - } - - /* Check for end of acquisition. */ - if (!subpriv->continuous) { - /* stop_src == TRIG_COUNT */ - if (subpriv->stopcount > 0) { - subpriv->stopcount--; - if (subpriv->stopcount == 0) { - s->async->events |= - COMEDI_CB_EOA; - dio200_stop_intr(dev, - s); - } - } - } - } - } - } - spin_unlock_irqrestore(&subpriv->spinlock, flags); - - if (oldevents != s->async->events) - comedi_event(dev, s); - - return (triggered != 0); -} - -/* - * 'cancel' function for an 'INTERRUPT' subdevice. - */ -static int dio200_subdev_intr_cancel(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct dio200_subdev_intr *subpriv = s->private; - unsigned long flags; - - spin_lock_irqsave(&subpriv->spinlock, flags); - if (subpriv->active) - dio200_stop_intr(dev, s); - - spin_unlock_irqrestore(&subpriv->spinlock, flags); - - return 0; -} - -/* - * 'do_cmdtest' function for an 'INTERRUPT' subdevice. - */ -static int -dio200_subdev_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 | TRIG_INT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); - - if (err) - return 1; - - /* Step 2a : make sure trigger sources are unique */ - - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); - - /* Step 2b : and mutually compatible */ - - if (err) - return 2; - - /* Step 3: check if arguments are trivially valid */ - - err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); - err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); - err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); - err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); - - switch (cmd->stop_src) { - case TRIG_COUNT: - /* any count allowed */ - break; - case TRIG_NONE: - err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); - break; - default: - break; - } - - if (err) - return 3; - - /* step 4: fix up any arguments */ - - /* if (err) return 4; */ - - return 0; -} - -/* - * 'do_cmd' function for an 'INTERRUPT' subdevice. - */ -static int dio200_subdev_intr_cmd(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct comedi_cmd *cmd = &s->async->cmd; - struct dio200_subdev_intr *subpriv = s->private; - unsigned long flags; - int event = 0; - - spin_lock_irqsave(&subpriv->spinlock, flags); - subpriv->active = 1; - - /* Set up end of acquisition. */ - switch (cmd->stop_src) { - case TRIG_COUNT: - subpriv->continuous = 0; - subpriv->stopcount = cmd->stop_arg; - break; - default: - /* TRIG_NONE */ - subpriv->continuous = 1; - subpriv->stopcount = 0; - break; - } - - /* Set up start of acquisition. */ - switch (cmd->start_src) { - case TRIG_INT: - s->async->inttrig = dio200_inttrig_start_intr; - break; - default: - /* TRIG_NOW */ - event = dio200_start_intr(dev, s); - break; - } - spin_unlock_irqrestore(&subpriv->spinlock, flags); - - if (event) - comedi_event(dev, s); - - return 0; -} - -/* - * This function initializes an 'INTERRUPT' subdevice. - */ -static int -dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int offset, unsigned valid_isns) -{ - const struct dio200_layout *layout = dio200_dev_layout(dev); - struct dio200_subdev_intr *subpriv; - - subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL); - if (!subpriv) - return -ENOMEM; - - subpriv->ofs = offset; - subpriv->valid_isns = valid_isns; - spin_lock_init(&subpriv->spinlock); - - if (layout->has_int_sce) - /* Disable interrupt sources. */ - dio200_write8(dev, subpriv->ofs, 0); - - s->private = subpriv; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE | SDF_CMD_READ; - if (layout->has_int_sce) { - s->n_chan = DIO200_MAX_ISNS; - s->len_chanlist = DIO200_MAX_ISNS; - } else { - /* No interrupt source register. Support single channel. */ - s->n_chan = 1; - s->len_chanlist = 1; - } - s->range_table = &range_digital; - s->maxdata = 1; - s->insn_bits = dio200_subdev_intr_insn_bits; - s->do_cmdtest = dio200_subdev_intr_cmdtest; - s->do_cmd = dio200_subdev_intr_cmd; - s->cancel = dio200_subdev_intr_cancel; - - return 0; -} - -/* - * This function cleans up an 'INTERRUPT' subdevice. - */ -static void -dio200_subdev_intr_cleanup(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct dio200_subdev_intr *subpriv = s->private; - kfree(subpriv); -} - -/* - * Interrupt service routine. - */ -static irqreturn_t dio200_interrupt(int irq, void *d) -{ - struct comedi_device *dev = d; - struct dio200_private *devpriv = dev->private; - struct comedi_subdevice *s; - int handled; - - if (!dev->attached) - return IRQ_NONE; - - if (devpriv->intr_sd >= 0) { - s = &dev->subdevices[devpriv->intr_sd]; - handled = dio200_handle_read_intr(dev, s); - } else { - handled = 0; - } - - return IRQ_RETVAL(handled); -} - -/* - * Read an '8254' counter subdevice channel. - */ -static unsigned int -dio200_subdev_8254_read_chan(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned int chan) -{ - struct dio200_subdev_8254 *subpriv = s->private; - unsigned int val; - - /* latch counter */ - val = chan << 6; - dio200_write8(dev, subpriv->ofs + i8254_control_reg, val); - /* read lsb, msb */ - val = dio200_read8(dev, subpriv->ofs + chan); - val += dio200_read8(dev, subpriv->ofs + chan) << 8; - return val; -} - -/* - * Write an '8254' subdevice channel. - */ -static void -dio200_subdev_8254_write_chan(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned int chan, - unsigned int count) -{ - struct dio200_subdev_8254 *subpriv = s->private; - - /* write lsb, msb */ - dio200_write8(dev, subpriv->ofs + chan, count & 0xff); - dio200_write8(dev, subpriv->ofs + chan, (count >> 8) & 0xff); -} - -/* - * Set mode of an '8254' subdevice channel. - */ -static void -dio200_subdev_8254_set_mode(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned int chan, - unsigned int mode) -{ - struct dio200_subdev_8254 *subpriv = s->private; - unsigned int byte; - - byte = chan << 6; - byte |= 0x30; /* access order: lsb, msb */ - byte |= (mode & 0xf); /* counter mode and BCD|binary */ - dio200_write8(dev, subpriv->ofs + i8254_control_reg, byte); -} - -/* - * Read status byte of an '8254' counter subdevice channel. - */ -static unsigned int -dio200_subdev_8254_status(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned int chan) -{ - struct dio200_subdev_8254 *subpriv = s->private; - - /* latch status */ - dio200_write8(dev, subpriv->ofs + i8254_control_reg, - 0xe0 | (2 << chan)); - /* read status */ - return dio200_read8(dev, subpriv->ofs + chan); -} - -/* - * Handle 'insn_read' for an '8254' counter subdevice. - */ -static int -dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct dio200_subdev_8254 *subpriv = s->private; - int chan = CR_CHAN(insn->chanspec); - unsigned int n; - unsigned long flags; - - for (n = 0; n < insn->n; n++) { - spin_lock_irqsave(&subpriv->spinlock, flags); - data[n] = dio200_subdev_8254_read_chan(dev, s, chan); - spin_unlock_irqrestore(&subpriv->spinlock, flags); - } - return insn->n; -} - -/* - * Handle 'insn_write' for an '8254' counter subdevice. - */ -static int -dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct dio200_subdev_8254 *subpriv = s->private; - int chan = CR_CHAN(insn->chanspec); - unsigned int n; - unsigned long flags; - - for (n = 0; n < insn->n; n++) { - spin_lock_irqsave(&subpriv->spinlock, flags); - dio200_subdev_8254_write_chan(dev, s, chan, data[n]); - spin_unlock_irqrestore(&subpriv->spinlock, flags); - } - return insn->n; -} - -/* - * Set gate source for an '8254' counter subdevice channel. - */ -static int -dio200_subdev_8254_set_gate_src(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int counter_number, - unsigned int gate_src) -{ - const struct dio200_layout *layout = dio200_dev_layout(dev); - struct dio200_subdev_8254 *subpriv = s->private; - unsigned char byte; - - if (!layout->has_clk_gat_sce) - return -1; - if (counter_number > 2) - return -1; - if (gate_src > (layout->has_enhancements ? 31 : 7)) - return -1; - - subpriv->gate_src[counter_number] = gate_src; - byte = gat_sce(subpriv->which, counter_number, gate_src); - dio200_write8(dev, subpriv->gat_sce_ofs, byte); - - return 0; -} - -/* - * Get gate source for an '8254' counter subdevice channel. - */ -static int -dio200_subdev_8254_get_gate_src(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int counter_number) -{ - const struct dio200_layout *layout = dio200_dev_layout(dev); - struct dio200_subdev_8254 *subpriv = s->private; - - if (!layout->has_clk_gat_sce) - return -1; - if (counter_number > 2) - return -1; - - return subpriv->gate_src[counter_number]; -} - -/* - * Set clock source for an '8254' counter subdevice channel. - */ -static int -dio200_subdev_8254_set_clock_src(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int counter_number, - unsigned int clock_src) -{ - const struct dio200_layout *layout = dio200_dev_layout(dev); - struct dio200_subdev_8254 *subpriv = s->private; - unsigned char byte; - - if (!layout->has_clk_gat_sce) - return -1; - if (counter_number > 2) - return -1; - if (clock_src > (layout->has_enhancements ? 31 : 7)) - return -1; - - subpriv->clock_src[counter_number] = clock_src; - byte = clk_sce(subpriv->which, counter_number, clock_src); - dio200_write8(dev, subpriv->clk_sce_ofs, byte); - - return 0; -} - -/* - * Get clock source for an '8254' counter subdevice channel. - */ -static int -dio200_subdev_8254_get_clock_src(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int counter_number, - unsigned int *period_ns) -{ - const struct dio200_layout *layout = dio200_dev_layout(dev); - struct dio200_subdev_8254 *subpriv = s->private; - unsigned clock_src; - - if (!layout->has_clk_gat_sce) - return -1; - if (counter_number > 2) - return -1; - - clock_src = subpriv->clock_src[counter_number]; - *period_ns = clock_period[clock_src]; - return clock_src; -} - -/* - * Handle 'insn_config' for an '8254' counter subdevice. - */ -static int -dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct dio200_subdev_8254 *subpriv = s->private; - int ret = 0; - int chan = CR_CHAN(insn->chanspec); - unsigned long flags; - - spin_lock_irqsave(&subpriv->spinlock, flags); - switch (data[0]) { - case INSN_CONFIG_SET_COUNTER_MODE: - if (data[1] > (I8254_MODE5 | I8254_BINARY)) - ret = -EINVAL; - else - dio200_subdev_8254_set_mode(dev, s, chan, data[1]); - break; - case INSN_CONFIG_8254_READ_STATUS: - data[1] = dio200_subdev_8254_status(dev, s, chan); - break; - case INSN_CONFIG_SET_GATE_SRC: - ret = dio200_subdev_8254_set_gate_src(dev, s, chan, data[2]); - if (ret < 0) - ret = -EINVAL; - break; - case INSN_CONFIG_GET_GATE_SRC: - ret = dio200_subdev_8254_get_gate_src(dev, s, chan); - if (ret < 0) { - ret = -EINVAL; - break; - } - data[2] = ret; - break; - case INSN_CONFIG_SET_CLOCK_SRC: - ret = dio200_subdev_8254_set_clock_src(dev, s, chan, data[1]); - if (ret < 0) - ret = -EINVAL; - break; - case INSN_CONFIG_GET_CLOCK_SRC: - ret = dio200_subdev_8254_get_clock_src(dev, s, chan, &data[2]); - if (ret < 0) { - ret = -EINVAL; - break; - } - data[1] = ret; - break; - default: - ret = -EINVAL; - break; - } - spin_unlock_irqrestore(&subpriv->spinlock, flags); - return ret < 0 ? ret : insn->n; -} - -/* - * This function initializes an '8254' counter subdevice. - */ -static int -dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int offset) -{ - const struct dio200_layout *layout = dio200_dev_layout(dev); - struct dio200_subdev_8254 *subpriv; - unsigned int chan; - - subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL); - if (!subpriv) - return -ENOMEM; - - s->private = subpriv; - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_WRITABLE | SDF_READABLE; - s->n_chan = 3; - s->maxdata = 0xFFFF; - s->insn_read = dio200_subdev_8254_read; - s->insn_write = dio200_subdev_8254_write; - s->insn_config = dio200_subdev_8254_config; - - spin_lock_init(&subpriv->spinlock); - subpriv->ofs = offset; - if (layout->has_clk_gat_sce) { - /* Derive CLK_SCE and GAT_SCE register offsets from - * 8254 offset. */ - subpriv->clk_sce_ofs = DIO200_XCLK_SCE + (offset >> 3); - subpriv->gat_sce_ofs = DIO200_XGAT_SCE + (offset >> 3); - subpriv->which = (offset >> 2) & 1; - } - - /* Initialize channels. */ - for (chan = 0; chan < 3; chan++) { - dio200_subdev_8254_set_mode(dev, s, chan, - I8254_MODE0 | I8254_BINARY); - if (layout->has_clk_gat_sce) { - /* Gate source 0 is VCC (logic 1). */ - dio200_subdev_8254_set_gate_src(dev, s, chan, 0); - /* Clock source 0 is the dedicated clock input. */ - dio200_subdev_8254_set_clock_src(dev, s, chan, 0); - } - } - - return 0; -} - -/* - * This function cleans up an '8254' counter subdevice. - */ -static void -dio200_subdev_8254_cleanup(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct dio200_subdev_intr *subpriv = s->private; - kfree(subpriv); -} - -/* - * This function sets I/O directions for an '8255' DIO subdevice. - */ -static void dio200_subdev_8255_set_dir(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct dio200_subdev_8255 *subpriv = s->private; - int config; - - config = CR_CW; - /* 1 in io_bits indicates output, 1 in config indicates input */ - if (!(s->io_bits & 0x0000ff)) - config |= CR_A_IO; - if (!(s->io_bits & 0x00ff00)) - config |= CR_B_IO; - if (!(s->io_bits & 0x0f0000)) - config |= CR_C_LO_IO; - if (!(s->io_bits & 0xf00000)) - config |= CR_C_HI_IO; - dio200_write8(dev, subpriv->ofs + 3, config); -} - -/* - * Handle 'insn_bits' for an '8255' DIO subdevice. - */ -static int dio200_subdev_8255_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct dio200_subdev_8255 *subpriv = s->private; - - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); - if (data[0] & 0xff) - dio200_write8(dev, subpriv->ofs, s->state & 0xff); - if (data[0] & 0xff00) - dio200_write8(dev, subpriv->ofs + 1, - (s->state >> 8) & 0xff); - if (data[0] & 0xff0000) - dio200_write8(dev, subpriv->ofs + 2, - (s->state >> 16) & 0xff); - } - data[1] = dio200_read8(dev, subpriv->ofs); - data[1] |= dio200_read8(dev, subpriv->ofs + 1) << 8; - data[1] |= dio200_read8(dev, subpriv->ofs + 2) << 16; - return 2; -} - -/* - * Handle 'insn_config' for an '8255' DIO subdevice. - */ -static int dio200_subdev_8255_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - unsigned int mask; - unsigned int bits; - - mask = 1 << CR_CHAN(insn->chanspec); - if (mask & 0x0000ff) - bits = 0x0000ff; - else if (mask & 0x00ff00) - bits = 0x00ff00; - else if (mask & 0x0f0000) - bits = 0x0f0000; - else - bits = 0xf00000; - switch (data[0]) { - case INSN_CONFIG_DIO_INPUT: - s->io_bits &= ~bits; - break; - case INSN_CONFIG_DIO_OUTPUT: - s->io_bits |= bits; - break; - case INSN_CONFIG_DIO_QUERY: - data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT; - return insn->n; - break; - default: - return -EINVAL; - } - dio200_subdev_8255_set_dir(dev, s); - return 1; -} - -/* - * This function initializes an '8255' DIO subdevice. - * - * offset is the offset to the 8255 chip. - */ -static int dio200_subdev_8255_init(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int offset) -{ - struct dio200_subdev_8255 *subpriv; - - subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL); - if (!subpriv) - return -ENOMEM; - subpriv->ofs = offset; - s->private = subpriv; - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 24; - s->range_table = &range_digital; - s->maxdata = 1; - s->insn_bits = dio200_subdev_8255_bits; - s->insn_config = dio200_subdev_8255_config; - s->state = 0; - s->io_bits = 0; - dio200_subdev_8255_set_dir(dev, s); - return 0; -} - -/* - * This function cleans up an '8255' DIO subdevice. - */ -static void dio200_subdev_8255_cleanup(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct dio200_subdev_8255 *subpriv = s->private; - - kfree(subpriv); -} - -/* - * Handle 'insn_read' for a timer subdevice. - */ -static int dio200_subdev_timer_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - unsigned int n; - - for (n = 0; n < insn->n; n++) - data[n] = dio200_read32(dev, DIO200_TS_COUNT); - return n; -} - -/* - * Reset timer subdevice. - */ -static void dio200_subdev_timer_reset(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - unsigned int clock; - - clock = dio200_read32(dev, DIO200_TS_CONFIG) & TS_CONFIG_CLK_SRC_MASK; - dio200_write32(dev, DIO200_TS_CONFIG, clock | TS_CONFIG_RESET); - dio200_write32(dev, DIO200_TS_CONFIG, clock); -} - -/* - * Get timer subdevice clock source and period. - */ -static void dio200_subdev_timer_get_clock_src(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int *src, - unsigned int *period) -{ - unsigned int clk; - - clk = dio200_read32(dev, DIO200_TS_CONFIG) & TS_CONFIG_CLK_SRC_MASK; - *src = clk; - *period = (clk < ARRAY_SIZE(ts_clock_period)) ? - ts_clock_period[clk] : 0; -} - -/* - * Set timer subdevice clock source. - */ -static int dio200_subdev_timer_set_clock_src(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int src) -{ - if (src > TS_CONFIG_MAX_CLK_SRC) - return -EINVAL; - dio200_write32(dev, DIO200_TS_CONFIG, src); - return 0; -} - -/* - * Handle 'insn_config' for a timer subdevice. - */ -static int dio200_subdev_timer_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - int ret = 0; - - switch (data[0]) { - case INSN_CONFIG_RESET: - dio200_subdev_timer_reset(dev, s); - break; - case INSN_CONFIG_SET_CLOCK_SRC: - ret = dio200_subdev_timer_set_clock_src(dev, s, data[1]); - if (ret < 0) - ret = -EINVAL; - break; - case INSN_CONFIG_GET_CLOCK_SRC: - dio200_subdev_timer_get_clock_src(dev, s, &data[1], &data[2]); - break; - default: - ret = -EINVAL; - break; - } - return ret < 0 ? ret : insn->n; -} - -/* - * This function initializes a timer subdevice. - * - * Uses the timestamp timer registers. There is only one timestamp timer. - */ -static int dio200_subdev_timer_init(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - s->type = COMEDI_SUBD_TIMER; - s->subdev_flags = SDF_READABLE | SDF_LSAMPL; - s->n_chan = 1; - s->maxdata = 0xFFFFFFFF; - s->insn_read = dio200_subdev_timer_read; - s->insn_config = dio200_subdev_timer_config; - return 0; -} - -/* - * This function cleans up a timer subdevice. - */ -static void dio200_subdev_timer_cleanup(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - /* Nothing to do. */ -} - -/* - * This function does some special set-up for the PCIe boards - * PCIe215, PCIe236, PCIe296. - */ -static int dio200_pcie_board_setup(struct comedi_device *dev) -{ - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - void __iomem *brbase; - resource_size_t brlen; - - /* - * The board uses Altera Cyclone IV with PCI-Express hard IP. - * The FPGA configuration has the PCI-Express Avalon-MM Bridge - * Control registers in PCI BAR 0, offset 0, and the length of - * these registers is 0x4000. - * - * We need to write 0x80 to the "Avalon-MM to PCI-Express Interrupt - * Enable" register at offset 0x50 to allow generation of PCIe - * interrupts when RXmlrq_i is asserted in the SOPC Builder system. - */ - brlen = pci_resource_len(pcidev, 0); - if (brlen < 0x4000 || - !(pci_resource_flags(pcidev, 0) & IORESOURCE_MEM)) { - dev_err(dev->class_dev, "error! bad PCI region!\n"); - return -EINVAL; - } - brbase = ioremap_nocache(pci_resource_start(pcidev, 0), brlen); - if (!brbase) { - dev_err(dev->class_dev, "error! failed to map registers!\n"); - return -ENOMEM; - } - writel(0x80, brbase + 0x50); - iounmap(brbase); - /* Enable "enhanced" features of board. */ - dio200_write8(dev, DIO200_ENHANCE, 1); - return 0; -} - -static void dio200_report_attach(struct comedi_device *dev, unsigned int irq) -{ - const struct dio200_board *thisboard = comedi_board(dev); - struct dio200_private *devpriv = dev->private; - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - char tmpbuf[60]; - int tmplen; - - if (is_isa_board(thisboard)) - tmplen = scnprintf(tmpbuf, sizeof(tmpbuf), - "(base %#lx) ", devpriv->io.u.iobase); - else if (is_pci_board(thisboard)) - tmplen = scnprintf(tmpbuf, sizeof(tmpbuf), - "(pci %s) ", pci_name(pcidev)); - else - tmplen = 0; - if (irq) - tmplen += scnprintf(&tmpbuf[tmplen], sizeof(tmpbuf) - tmplen, - "(irq %u%s) ", irq, - (dev->irq ? "" : " UNAVAILABLE")); - else - tmplen += scnprintf(&tmpbuf[tmplen], sizeof(tmpbuf) - tmplen, - "(no irq) "); - dev_info(dev->class_dev, "%s %sattached\n", dev->board_name, tmpbuf); -} - -static int dio200_common_attach(struct comedi_device *dev, unsigned int irq, - unsigned long req_irq_flags) -{ - const struct dio200_board *thisboard = comedi_board(dev); - struct dio200_private *devpriv = dev->private; - const struct dio200_layout *layout = dio200_board_layout(thisboard); - struct comedi_subdevice *s; - int sdx; - unsigned int n; - int ret; - - devpriv->intr_sd = -1; - dev->board_name = thisboard->name; - - ret = comedi_alloc_subdevices(dev, layout->n_subdevs); - if (ret) - return ret; - - for (n = 0; n < dev->n_subdevices; n++) { - s = &dev->subdevices[n]; - switch (layout->sdtype[n]) { - case sd_8254: - /* counter subdevice (8254) */ - ret = dio200_subdev_8254_init(dev, s, - layout->sdinfo[n]); - if (ret < 0) - return ret; - break; - case sd_8255: - /* digital i/o subdevice (8255) */ - ret = dio200_subdev_8255_init(dev, s, - layout->sdinfo[n]); - if (ret < 0) - return ret; - break; - case sd_intr: - /* 'INTERRUPT' subdevice */ - if (irq) { - ret = dio200_subdev_intr_init(dev, s, - DIO200_INT_SCE, - layout->sdinfo[n] - ); - if (ret < 0) - return ret; - devpriv->intr_sd = n; - } else { - s->type = COMEDI_SUBD_UNUSED; - } - break; - case sd_timer: - /* Only on PCIe boards. */ - if (DO_PCI) { - ret = dio200_subdev_timer_init(dev, s); - if (ret < 0) - return ret; - } else { - s->type = COMEDI_SUBD_UNUSED; - } - break; - default: - s->type = COMEDI_SUBD_UNUSED; - break; - } - } - sdx = devpriv->intr_sd; - if (sdx >= 0 && sdx < dev->n_subdevices) - dev->read_subdev = &dev->subdevices[sdx]; - if (irq) { - if (request_irq(irq, dio200_interrupt, req_irq_flags, - DIO200_DRIVER_NAME, dev) >= 0) { - dev->irq = irq; - } else { - dev_warn(dev->class_dev, - "warning! irq %u unavailable!\n", irq); - } - } - dio200_report_attach(dev, irq); - return 1; -} - -/* - * 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 dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct dio200_board *thisboard = comedi_board(dev); struct dio200_private *devpriv; + unsigned int irq; int ret; - dev_info(dev->class_dev, DIO200_DRIVER_NAME ": attach\n"); + irq = it->options[1]; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - /* Process options and reserve resources according to bus type. */ - if (is_isa_board(thisboard)) { - unsigned long iobase; - unsigned int irq; - - iobase = it->options[0]; - irq = it->options[1]; - ret = dio200_request_region(dev, iobase, thisboard->mainsize); - if (ret < 0) - return ret; - devpriv->io.u.iobase = iobase; - devpriv->io.regtype = io_regtype; - return dio200_common_attach(dev, irq, 0); - } else if (is_pci_board(thisboard)) { - dev_err(dev->class_dev, - "Manual configuration of PCI board '%s' is not supported\n", - thisboard->name); - return -EIO; - } else { - dev_err(dev->class_dev, DIO200_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 dio200_auto_attach(struct comedi_device *dev, - unsigned long context_unused) -{ - struct pci_dev *pci_dev = comedi_to_pci_dev(dev); - const struct dio200_board *thisboard; - struct dio200_private *devpriv; - resource_size_t base, len; - unsigned int bar; - int ret; - - if (!DO_PCI) - return -EINVAL; - - dev_info(dev->class_dev, DIO200_DRIVER_NAME ": attach pci %s\n", - pci_name(pci_dev)); - - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); - if (!devpriv) - return -ENOMEM; - dev->private = devpriv; - - dev->board_ptr = dio200_find_pci_board(pci_dev); - if (dev->board_ptr == NULL) { - dev_err(dev->class_dev, "BUG! cannot determine board type!\n"); - return -EINVAL; - } - thisboard = comedi_board(dev); - ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME); - if (ret < 0) { - dev_err(dev->class_dev, - "error! cannot enable PCI device and request regions!\n"); + ret = comedi_request_region(dev, it->options[0], thisboard->mainsize); + if (ret) return ret; - } - bar = thisboard->mainbar; - base = pci_resource_start(pci_dev, bar); - len = pci_resource_len(pci_dev, bar); - if (len < thisboard->mainsize) { - dev_err(dev->class_dev, "error! PCI region size too small!\n"); - return -EINVAL; - } - if ((pci_resource_flags(pci_dev, bar) & IORESOURCE_MEM) != 0) { - devpriv->io.u.membase = ioremap_nocache(base, len); - if (!devpriv->io.u.membase) { - dev_err(dev->class_dev, - "error! cannot remap registers\n"); - return -ENOMEM; - } - devpriv->io.regtype = mmio_regtype; - } else { - devpriv->io.u.iobase = (unsigned long)base; - devpriv->io.regtype = io_regtype; - } - switch (thisboard->model) { - case pcie215_model: - case pcie236_model: - case pcie296_model: - ret = dio200_pcie_board_setup(dev); - if (ret < 0) - return ret; - break; - default: - break; - } - return dio200_common_attach(dev, pci_dev->irq, IRQF_SHARED); + devpriv->io.u.iobase = dev->iobase; + devpriv->io.regtype = io_regtype; + return amplc_dio200_common_attach(dev, irq, 0); } static void dio200_detach(struct comedi_device *dev) { - const struct dio200_board *thisboard = comedi_board(dev); - struct dio200_private *devpriv = dev->private; - const struct dio200_layout *layout; - unsigned n; - - if (!thisboard || !devpriv) - return; - if (dev->irq) - free_irq(dev->irq, dev); - if (dev->subdevices) { - layout = dio200_board_layout(thisboard); - for (n = 0; n < dev->n_subdevices; n++) { - struct comedi_subdevice *s = &dev->subdevices[n]; - switch (layout->sdtype[n]) { - case sd_8254: - dio200_subdev_8254_cleanup(dev, s); - break; - case sd_8255: - dio200_subdev_8255_cleanup(dev, s); - break; - case sd_intr: - dio200_subdev_intr_cleanup(dev, s); - break; - case sd_timer: - /* Only on PCIe boards. */ - if (DO_PCI) - dio200_subdev_timer_cleanup(dev, s); - break; - default: - break; - } - } - } - if (is_isa_board(thisboard)) { - if (devpriv->io.regtype == io_regtype) - release_region(devpriv->io.u.iobase, - thisboard->mainsize); - } else if (is_pci_board(thisboard)) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (pcidev) { - if (devpriv->io.regtype != no_regtype) { - if (devpriv->io.regtype == mmio_regtype) - iounmap(devpriv->io.u.membase); - comedi_pci_disable(pcidev); - } - } - } + amplc_dio200_common_detach(dev); + comedi_legacy_detach(dev); } -/* - * 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_dio200_driver = { - .driver_name = DIO200_DRIVER_NAME, + .driver_name = "amplc_dio200", .module = THIS_MODULE, .attach = dio200_attach, - .auto_attach = dio200_auto_attach, .detach = dio200_detach, - .board_name = &dio200_boards[0].name, + .board_name = &dio200_isa_boards[0].name, .offset = sizeof(struct dio200_board), - .num_names = ARRAY_SIZE(dio200_boards), -}; - -#if DO_PCI -static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE236) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE215) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE296) }, - {0} -}; - -MODULE_DEVICE_TABLE(pci, dio200_pci_table); - -static int amplc_dio200_pci_probe(struct pci_dev *dev, - const struct pci_device_id - *ent) -{ - return comedi_pci_auto_config(dev, &lc_dio200_driver); -} - -static struct pci_driver amplc_dio200_pci_driver = { - .name = DIO200_DRIVER_NAME, - .id_table = dio200_pci_table, - .probe = &lc_dio200_pci_probe, - .remove = comedi_pci_auto_unconfig, + .num_names = ARRAY_SIZE(dio200_isa_boards), }; -module_comedi_pci_driver(amplc_dio200_driver, amplc_dio200_pci_driver); -#else module_comedi_driver(amplc_dio200_driver); -#endif MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for Amplicon 200 Series ISA DIO boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_dio200.h b/drivers/staging/comedi/drivers/amplc_dio200.h new file mode 100644 index 00000000000..cf2e7261740 --- /dev/null +++ b/drivers/staging/comedi/drivers/amplc_dio200.h @@ -0,0 +1,95 @@ +/* + comedi/drivers/amplc_dio.h + + Header for amplc_dio200.c, amplc_dio200_common.c and + amplc_dio200_pci.c. + + Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef AMPLC_DIO200_H_INCLUDED +#define AMPLC_DIO200_H_INCLUDED + +/* 200 series register area sizes */ +#define DIO200_IO_SIZE 0x20 +#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 }; + +#define DIO200_MAX_SUBDEVS 8 +#define DIO200_MAX_ISNS 6 + +/* + * Board descriptions. + */ + +struct dio200_layout { + unsigned short n_subdevs; /* number of subdevices */ + unsigned char sdtype[DIO200_MAX_SUBDEVS]; /* enum dio200_sdtype */ + unsigned char sdinfo[DIO200_MAX_SUBDEVS]; /* depends on sdtype */ + bool has_int_sce:1; /* has interrupt enable/status reg */ + bool has_clk_gat_sce:1; /* has clock/gate selection registers */ + bool has_enhancements:1; /* has enhanced features */ +}; + +enum dio200_bustype { isa_bustype, pci_bustype }; + +struct dio200_board { + const char *name; + struct dio200_layout layout; + enum dio200_bustype bustype; + unsigned char mainbar; + unsigned char mainshift; + unsigned int mainsize; +}; + +/* + * Comedi device private data. + */ +struct dio200_private { + struct dio200_region io; /* Register region */ + int intr_sd; +}; + +int amplc_dio200_common_attach(struct comedi_device *dev, unsigned int irq, + unsigned long req_irq_flags); + +void amplc_dio200_common_detach(struct comedi_device *dev); + +/* Used by initialization of PCIe boards. */ +void amplc_dio200_set_enhance(struct comedi_device *dev, unsigned char val); + +#endif diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c new file mode 100644 index 00000000000..3403e5ccfa9 --- /dev/null +++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c @@ -0,0 +1,1271 @@ +/* + comedi/drivers/amplc_dio200_common.c + + Common support code for "amplc_dio200" and "amplc_dio200_pci". + + Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include <linux/interrupt.h> +#include <linux/slab.h> + +#include "../comedidev.h" + +#include "amplc_dio200.h" +#include "comedi_fc.h" +#include "8253.h" + +/* 8255 control register bits */ +#define CR_C_LO_IO 0x01 +#define CR_B_IO 0x02 +#define CR_B_MODE 0x04 +#define CR_C_HI_IO 0x08 +#define CR_A_IO 0x10 +#define CR_A_MODE(a) ((a)<<5) +#define CR_CW 0x80 + +/* 200 series registers */ +#define DIO200_IO_SIZE 0x20 +#define DIO200_PCIE_IO_SIZE 0x4000 +#define DIO200_XCLK_SCE 0x18 /* Group X clock selection register */ +#define DIO200_YCLK_SCE 0x19 /* Group Y clock selection register */ +#define DIO200_ZCLK_SCE 0x1a /* Group Z clock selection register */ +#define DIO200_XGAT_SCE 0x1b /* Group X gate selection register */ +#define DIO200_YGAT_SCE 0x1c /* Group Y gate selection register */ +#define DIO200_ZGAT_SCE 0x1d /* Group Z gate selection register */ +#define DIO200_INT_SCE 0x1e /* Interrupt enable/status register */ +/* Extra registers for new PCIe boards */ +#define DIO200_ENHANCE 0x20 /* 1 to enable enhanced features */ +#define DIO200_VERSION 0x24 /* Hardware version register */ +#define DIO200_TS_CONFIG 0x600 /* Timestamp timer config register */ +#define DIO200_TS_COUNT 0x602 /* Timestamp timer count register */ + +/* + * Functions for constructing value for DIO_200_?CLK_SCE and + * DIO_200_?GAT_SCE registers: + * + * 'which' is: 0 for CTR-X1, CTR-Y1, CTR-Z1; 1 for CTR-X2, CTR-Y2 or CTR-Z2. + * 'chan' is the channel: 0, 1 or 2. + * 'source' is the signal source: 0 to 7, or 0 to 31 for "enhanced" boards. + */ +static unsigned char clk_gat_sce(unsigned int which, unsigned int chan, + unsigned int source) +{ + return (which << 5) | (chan << 3) | + ((source & 030) << 3) | (source & 007); +} + +static unsigned char clk_sce(unsigned int which, unsigned int chan, + unsigned int source) +{ + return clk_gat_sce(which, chan, source); +} + +static unsigned char gat_sce(unsigned int which, unsigned int chan, + unsigned int source) +{ + return clk_gat_sce(which, chan, source); +} + +/* + * Periods of the internal clock sources in nanoseconds. + */ +static const unsigned int clock_period[32] = { + [1] = 100, /* 10 MHz */ + [2] = 1000, /* 1 MHz */ + [3] = 10000, /* 100 kHz */ + [4] = 100000, /* 10 kHz */ + [5] = 1000000, /* 1 kHz */ + [11] = 50, /* 20 MHz (enhanced boards) */ + /* clock sources 12 and later reserved for enhanced boards */ +}; + +/* + * Timestamp timer configuration register (for new PCIe boards). + */ +#define TS_CONFIG_RESET 0x100 /* Reset counter to zero. */ +#define TS_CONFIG_CLK_SRC_MASK 0x0FF /* Clock source. */ +#define TS_CONFIG_MAX_CLK_SRC 2 /* Maximum clock source value. */ + +/* + * Periods of the timestamp timer clock sources in nanoseconds. + */ +static const unsigned int ts_clock_period[TS_CONFIG_MAX_CLK_SRC + 1] = { + 1, /* 1 nanosecond (but with 20 ns granularity). */ + 1000, /* 1 microsecond. */ + 1000000, /* 1 millisecond. */ +}; + +struct dio200_subdev_8254 { + unsigned int ofs; /* Counter base offset */ + unsigned int clk_sce_ofs; /* CLK_SCE base address */ + unsigned int gat_sce_ofs; /* GAT_SCE base address */ + int which; /* Bit 5 of CLK_SCE or GAT_SCE */ + unsigned int clock_src[3]; /* Current clock sources */ + unsigned int gate_src[3]; /* Current gate sources */ + spinlock_t spinlock; +}; + +struct dio200_subdev_8255 { + unsigned int ofs; /* DIO base offset */ +}; + +struct dio200_subdev_intr { + spinlock_t spinlock; + unsigned int ofs; + unsigned int valid_isns; + unsigned int enabled_isns; + unsigned int stopcount; + bool active:1; + bool continuous:1; +}; + +static inline const struct dio200_layout * +dio200_board_layout(const struct dio200_board *board) +{ + return &board->layout; +} + +static inline const struct dio200_layout * +dio200_dev_layout(struct comedi_device *dev) +{ + return dio200_board_layout(comedi_board(dev)); +} + +/* + * Read 8-bit register. + */ +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); +} + +/* + * Write 8-bit register. + */ +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); + else + writeb(val, devpriv->io.u.membase + offset); +} + +/* + * Read 32-bit register. + */ +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); +} + +/* + * Write 32-bit register. + */ +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); + else + writel(val, devpriv->io.u.membase + offset); +} + +/* + * 'insn_bits' function for an 'INTERRUPT' subdevice. + */ +static int +dio200_subdev_intr_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) +{ + const struct dio200_layout *layout = dio200_dev_layout(dev); + struct dio200_subdev_intr *subpriv = s->private; + + if (layout->has_int_sce) { + /* Just read the interrupt status register. */ + data[1] = dio200_read8(dev, subpriv->ofs) & subpriv->valid_isns; + } else { + /* No interrupt status register. */ + data[0] = 0; + } + + return insn->n; +} + +/* + * Called to stop acquisition for an 'INTERRUPT' subdevice. + */ +static void dio200_stop_intr(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + const struct dio200_layout *layout = dio200_dev_layout(dev); + struct dio200_subdev_intr *subpriv = s->private; + + subpriv->active = false; + subpriv->enabled_isns = 0; + if (layout->has_int_sce) + dio200_write8(dev, subpriv->ofs, 0); +} + +/* + * Called to start acquisition for an 'INTERRUPT' subdevice. + */ +static int dio200_start_intr(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + unsigned int n; + unsigned isn_bits; + const struct dio200_layout *layout = dio200_dev_layout(dev); + struct dio200_subdev_intr *subpriv = s->private; + struct comedi_cmd *cmd = &s->async->cmd; + int retval = 0; + + if (!subpriv->continuous && subpriv->stopcount == 0) { + /* An empty acquisition! */ + s->async->events |= COMEDI_CB_EOA; + subpriv->active = false; + retval = 1; + } else { + /* Determine interrupt sources to enable. */ + isn_bits = 0; + if (cmd->chanlist) { + for (n = 0; n < cmd->chanlist_len; n++) + isn_bits |= (1U << CR_CHAN(cmd->chanlist[n])); + } + isn_bits &= subpriv->valid_isns; + /* Enable interrupt sources. */ + subpriv->enabled_isns = isn_bits; + if (layout->has_int_sce) + dio200_write8(dev, subpriv->ofs, isn_bits); + } + + return retval; +} + +/* + * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice. + */ +static int +dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s, + unsigned int trignum) +{ + struct dio200_subdev_intr *subpriv; + unsigned long flags; + int event = 0; + + if (trignum != 0) + return -EINVAL; + + subpriv = s->private; + + spin_lock_irqsave(&subpriv->spinlock, flags); + s->async->inttrig = NULL; + if (subpriv->active) + event = dio200_start_intr(dev, s); + + spin_unlock_irqrestore(&subpriv->spinlock, flags); + + if (event) + comedi_event(dev, s); + + return 1; +} + +static void dio200_read_scan_intr(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int triggered) +{ + struct dio200_subdev_intr *subpriv = s->private; + unsigned short val; + unsigned int n, ch, len; + + val = 0; + len = s->async->cmd.chanlist_len; + for (n = 0; n < len; n++) { + ch = CR_CHAN(s->async->cmd.chanlist[n]); + if (triggered & (1U << ch)) + val |= (1U << n); + } + /* Write the scan to the buffer. */ + if (comedi_buf_put(s->async, val)) { + s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS); + } else { + /* Error! Stop acquisition. */ + dio200_stop_intr(dev, s); + s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW; + comedi_error(dev, "buffer overflow"); + } + + /* Check for end of acquisition. */ + if (!subpriv->continuous) { + /* stop_src == TRIG_COUNT */ + if (subpriv->stopcount > 0) { + subpriv->stopcount--; + if (subpriv->stopcount == 0) { + s->async->events |= COMEDI_CB_EOA; + dio200_stop_intr(dev, s); + } + } + } +} + +/* + * This is called from the interrupt service routine to handle a read + * scan on an 'INTERRUPT' subdevice. + */ +static int dio200_handle_read_intr(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + const struct dio200_layout *layout = dio200_dev_layout(dev); + struct dio200_subdev_intr *subpriv = s->private; + unsigned triggered; + unsigned intstat; + unsigned cur_enabled; + unsigned int oldevents; + unsigned long flags; + + triggered = 0; + + spin_lock_irqsave(&subpriv->spinlock, flags); + oldevents = s->async->events; + if (layout->has_int_sce) { + /* + * Collect interrupt sources that have triggered and disable + * them temporarily. Loop around until no extra interrupt + * sources have triggered, at which point, the valid part of + * the interrupt status register will read zero, clearing the + * cause of the interrupt. + * + * Mask off interrupt sources already seen to avoid infinite + * loop in case of misconfiguration. + */ + cur_enabled = subpriv->enabled_isns; + while ((intstat = (dio200_read8(dev, subpriv->ofs) & + subpriv->valid_isns & ~triggered)) != 0) { + triggered |= intstat; + cur_enabled &= ~triggered; + dio200_write8(dev, subpriv->ofs, cur_enabled); + } + } else { + /* + * No interrupt status register. Assume the single interrupt + * source has triggered. + */ + triggered = subpriv->enabled_isns; + } + + if (triggered) { + /* + * Some interrupt sources have triggered and have been + * temporarily disabled to clear the cause of the interrupt. + * + * Reenable them NOW to minimize the time they are disabled. + */ + cur_enabled = subpriv->enabled_isns; + if (layout->has_int_sce) + dio200_write8(dev, subpriv->ofs, cur_enabled); + + if (subpriv->active) { + /* + * The command is still active. + * + * Ignore interrupt sources that the command isn't + * interested in (just in case there's a race + * condition). + */ + if (triggered & subpriv->enabled_isns) + /* Collect scan data. */ + dio200_read_scan_intr(dev, s, triggered); + } + } + spin_unlock_irqrestore(&subpriv->spinlock, flags); + + if (oldevents != s->async->events) + comedi_event(dev, s); + + return (triggered != 0); +} + +/* + * 'cancel' function for an 'INTERRUPT' subdevice. + */ +static int dio200_subdev_intr_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct dio200_subdev_intr *subpriv = s->private; + unsigned long flags; + + spin_lock_irqsave(&subpriv->spinlock, flags); + if (subpriv->active) + dio200_stop_intr(dev, s); + + spin_unlock_irqrestore(&subpriv->spinlock, flags); + + return 0; +} + +/* + * 'do_cmdtest' function for an 'INTERRUPT' subdevice. + */ +static int +dio200_subdev_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 | TRIG_INT); + err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); + err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); + err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); + err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); + + if (err) + return 1; + + /* Step 2a : make sure trigger sources are unique */ + + err |= cfc_check_trigger_is_unique(cmd->start_src); + err |= cfc_check_trigger_is_unique(cmd->stop_src); + + /* Step 2b : and mutually compatible */ + + if (err) + return 2; + + /* Step 3: check if arguments are trivially valid */ + + err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); + + switch (cmd->stop_src) { + case TRIG_COUNT: + /* any count allowed */ + break; + case TRIG_NONE: + err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); + break; + default: + break; + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + /* if (err) return 4; */ + + return 0; +} + +/* + * 'do_cmd' function for an 'INTERRUPT' subdevice. + */ +static int dio200_subdev_intr_cmd(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + struct dio200_subdev_intr *subpriv = s->private; + unsigned long flags; + int event = 0; + + spin_lock_irqsave(&subpriv->spinlock, flags); + subpriv->active = 1; + + /* Set up end of acquisition. */ + switch (cmd->stop_src) { + case TRIG_COUNT: + subpriv->continuous = false; + subpriv->stopcount = cmd->stop_arg; + break; + default: + /* TRIG_NONE */ + subpriv->continuous = true; + subpriv->stopcount = 0; + break; + } + + /* Set up start of acquisition. */ + switch (cmd->start_src) { + case TRIG_INT: + s->async->inttrig = dio200_inttrig_start_intr; + break; + default: + /* TRIG_NOW */ + event = dio200_start_intr(dev, s); + break; + } + spin_unlock_irqrestore(&subpriv->spinlock, flags); + + if (event) + comedi_event(dev, s); + + return 0; +} + +/* + * This function initializes an 'INTERRUPT' subdevice. + */ +static int +dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s, + unsigned int offset, unsigned valid_isns) +{ + const struct dio200_layout *layout = dio200_dev_layout(dev); + struct dio200_subdev_intr *subpriv; + + subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL); + if (!subpriv) + return -ENOMEM; + + subpriv->ofs = offset; + subpriv->valid_isns = valid_isns; + spin_lock_init(&subpriv->spinlock); + + if (layout->has_int_sce) + /* Disable interrupt sources. */ + dio200_write8(dev, subpriv->ofs, 0); + + s->private = subpriv; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_CMD_READ; + if (layout->has_int_sce) { + s->n_chan = DIO200_MAX_ISNS; + s->len_chanlist = DIO200_MAX_ISNS; + } else { + /* No interrupt source register. Support single channel. */ + s->n_chan = 1; + s->len_chanlist = 1; + } + s->range_table = &range_digital; + s->maxdata = 1; + s->insn_bits = dio200_subdev_intr_insn_bits; + s->do_cmdtest = dio200_subdev_intr_cmdtest; + s->do_cmd = dio200_subdev_intr_cmd; + s->cancel = dio200_subdev_intr_cancel; + + return 0; +} + +/* + * Interrupt service routine. + */ +static irqreturn_t dio200_interrupt(int irq, void *d) +{ + struct comedi_device *dev = d; + struct dio200_private *devpriv = dev->private; + struct comedi_subdevice *s; + int handled; + + if (!dev->attached) + return IRQ_NONE; + + if (devpriv->intr_sd >= 0) { + s = &dev->subdevices[devpriv->intr_sd]; + handled = dio200_handle_read_intr(dev, s); + } else { + handled = 0; + } + + return IRQ_RETVAL(handled); +} + +/* + * Read an '8254' counter subdevice channel. + */ +static unsigned int +dio200_subdev_8254_read_chan(struct comedi_device *dev, + struct comedi_subdevice *s, unsigned int chan) +{ + struct dio200_subdev_8254 *subpriv = s->private; + unsigned int val; + + /* latch counter */ + val = chan << 6; + dio200_write8(dev, subpriv->ofs + i8254_control_reg, val); + /* read lsb, msb */ + val = dio200_read8(dev, subpriv->ofs + chan); + val += dio200_read8(dev, subpriv->ofs + chan) << 8; + return val; +} + +/* + * Write an '8254' subdevice channel. + */ +static void +dio200_subdev_8254_write_chan(struct comedi_device *dev, + struct comedi_subdevice *s, unsigned int chan, + unsigned int count) +{ + struct dio200_subdev_8254 *subpriv = s->private; + + /* write lsb, msb */ + dio200_write8(dev, subpriv->ofs + chan, count & 0xff); + dio200_write8(dev, subpriv->ofs + chan, (count >> 8) & 0xff); +} + +/* + * Set mode of an '8254' subdevice channel. + */ +static void +dio200_subdev_8254_set_mode(struct comedi_device *dev, + struct comedi_subdevice *s, unsigned int chan, + unsigned int mode) +{ + struct dio200_subdev_8254 *subpriv = s->private; + unsigned int byte; + + byte = chan << 6; + byte |= 0x30; /* access order: lsb, msb */ + byte |= (mode & 0xf); /* counter mode and BCD|binary */ + dio200_write8(dev, subpriv->ofs + i8254_control_reg, byte); +} + +/* + * Read status byte of an '8254' counter subdevice channel. + */ +static unsigned int +dio200_subdev_8254_status(struct comedi_device *dev, + struct comedi_subdevice *s, unsigned int chan) +{ + struct dio200_subdev_8254 *subpriv = s->private; + + /* latch status */ + dio200_write8(dev, subpriv->ofs + i8254_control_reg, + 0xe0 | (2 << chan)); + /* read status */ + return dio200_read8(dev, subpriv->ofs + chan); +} + +/* + * Handle 'insn_read' for an '8254' counter subdevice. + */ +static int +dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) +{ + struct dio200_subdev_8254 *subpriv = s->private; + int chan = CR_CHAN(insn->chanspec); + unsigned int n; + unsigned long flags; + + for (n = 0; n < insn->n; n++) { + spin_lock_irqsave(&subpriv->spinlock, flags); + data[n] = dio200_subdev_8254_read_chan(dev, s, chan); + spin_unlock_irqrestore(&subpriv->spinlock, flags); + } + return insn->n; +} + +/* + * Handle 'insn_write' for an '8254' counter subdevice. + */ +static int +dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) +{ + struct dio200_subdev_8254 *subpriv = s->private; + int chan = CR_CHAN(insn->chanspec); + unsigned int n; + unsigned long flags; + + for (n = 0; n < insn->n; n++) { + spin_lock_irqsave(&subpriv->spinlock, flags); + dio200_subdev_8254_write_chan(dev, s, chan, data[n]); + spin_unlock_irqrestore(&subpriv->spinlock, flags); + } + return insn->n; +} + +/* + * Set gate source for an '8254' counter subdevice channel. + */ +static int +dio200_subdev_8254_set_gate_src(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int counter_number, + unsigned int gate_src) +{ + const struct dio200_layout *layout = dio200_dev_layout(dev); + struct dio200_subdev_8254 *subpriv = s->private; + unsigned char byte; + + if (!layout->has_clk_gat_sce) + return -1; + if (counter_number > 2) + return -1; + if (gate_src > (layout->has_enhancements ? 31 : 7)) + return -1; + + subpriv->gate_src[counter_number] = gate_src; + byte = gat_sce(subpriv->which, counter_number, gate_src); + dio200_write8(dev, subpriv->gat_sce_ofs, byte); + + return 0; +} + +/* + * Get gate source for an '8254' counter subdevice channel. + */ +static int +dio200_subdev_8254_get_gate_src(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int counter_number) +{ + const struct dio200_layout *layout = dio200_dev_layout(dev); + struct dio200_subdev_8254 *subpriv = s->private; + + if (!layout->has_clk_gat_sce) + return -1; + if (counter_number > 2) + return -1; + + return subpriv->gate_src[counter_number]; +} + +/* + * Set clock source for an '8254' counter subdevice channel. + */ +static int +dio200_subdev_8254_set_clock_src(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int counter_number, + unsigned int clock_src) +{ + const struct dio200_layout *layout = dio200_dev_layout(dev); + struct dio200_subdev_8254 *subpriv = s->private; + unsigned char byte; + + if (!layout->has_clk_gat_sce) + return -1; + if (counter_number > 2) + return -1; + if (clock_src > (layout->has_enhancements ? 31 : 7)) + return -1; + + subpriv->clock_src[counter_number] = clock_src; + byte = clk_sce(subpriv->which, counter_number, clock_src); + dio200_write8(dev, subpriv->clk_sce_ofs, byte); + + return 0; +} + +/* + * Get clock source for an '8254' counter subdevice channel. + */ +static int +dio200_subdev_8254_get_clock_src(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int counter_number, + unsigned int *period_ns) +{ + const struct dio200_layout *layout = dio200_dev_layout(dev); + struct dio200_subdev_8254 *subpriv = s->private; + unsigned clock_src; + + if (!layout->has_clk_gat_sce) + return -1; + if (counter_number > 2) + return -1; + + clock_src = subpriv->clock_src[counter_number]; + *period_ns = clock_period[clock_src]; + return clock_src; +} + +/* + * Handle 'insn_config' for an '8254' counter subdevice. + */ +static int +dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) +{ + struct dio200_subdev_8254 *subpriv = s->private; + int ret = 0; + int chan = CR_CHAN(insn->chanspec); + unsigned long flags; + + spin_lock_irqsave(&subpriv->spinlock, flags); + switch (data[0]) { + case INSN_CONFIG_SET_COUNTER_MODE: + if (data[1] > (I8254_MODE5 | I8254_BINARY)) + ret = -EINVAL; + else + dio200_subdev_8254_set_mode(dev, s, chan, data[1]); + break; + case INSN_CONFIG_8254_READ_STATUS: + data[1] = dio200_subdev_8254_status(dev, s, chan); + break; + case INSN_CONFIG_SET_GATE_SRC: + ret = dio200_subdev_8254_set_gate_src(dev, s, chan, data[2]); + if (ret < 0) + ret = -EINVAL; + break; + case INSN_CONFIG_GET_GATE_SRC: + ret = dio200_subdev_8254_get_gate_src(dev, s, chan); + if (ret < 0) { + ret = -EINVAL; + break; + } + data[2] = ret; + break; + case INSN_CONFIG_SET_CLOCK_SRC: + ret = dio200_subdev_8254_set_clock_src(dev, s, chan, data[1]); + if (ret < 0) + ret = -EINVAL; + break; + case INSN_CONFIG_GET_CLOCK_SRC: + ret = dio200_subdev_8254_get_clock_src(dev, s, chan, &data[2]); + if (ret < 0) { + ret = -EINVAL; + break; + } + data[1] = ret; + break; + default: + ret = -EINVAL; + break; + } + spin_unlock_irqrestore(&subpriv->spinlock, flags); + return ret < 0 ? ret : insn->n; +} + +/* + * This function initializes an '8254' counter subdevice. + */ +static int +dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s, + unsigned int offset) +{ + const struct dio200_layout *layout = dio200_dev_layout(dev); + struct dio200_subdev_8254 *subpriv; + unsigned int chan; + + subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL); + if (!subpriv) + return -ENOMEM; + + s->private = subpriv; + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = 3; + s->maxdata = 0xFFFF; + s->insn_read = dio200_subdev_8254_read; + s->insn_write = dio200_subdev_8254_write; + s->insn_config = dio200_subdev_8254_config; + + spin_lock_init(&subpriv->spinlock); + subpriv->ofs = offset; + if (layout->has_clk_gat_sce) { + /* Derive CLK_SCE and GAT_SCE register offsets from + * 8254 offset. */ + subpriv->clk_sce_ofs = DIO200_XCLK_SCE + (offset >> 3); + subpriv->gat_sce_ofs = DIO200_XGAT_SCE + (offset >> 3); + subpriv->which = (offset >> 2) & 1; + } + + /* Initialize channels. */ + for (chan = 0; chan < 3; chan++) { + dio200_subdev_8254_set_mode(dev, s, chan, + I8254_MODE0 | I8254_BINARY); + if (layout->has_clk_gat_sce) { + /* Gate source 0 is VCC (logic 1). */ + dio200_subdev_8254_set_gate_src(dev, s, chan, 0); + /* Clock source 0 is the dedicated clock input. */ + dio200_subdev_8254_set_clock_src(dev, s, chan, 0); + } + } + + return 0; +} + +/* + * This function sets I/O directions for an '8255' DIO subdevice. + */ +static void dio200_subdev_8255_set_dir(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct dio200_subdev_8255 *subpriv = s->private; + int config; + + config = CR_CW; + /* 1 in io_bits indicates output, 1 in config indicates input */ + if (!(s->io_bits & 0x0000ff)) + config |= CR_A_IO; + if (!(s->io_bits & 0x00ff00)) + config |= CR_B_IO; + if (!(s->io_bits & 0x0f0000)) + config |= CR_C_LO_IO; + if (!(s->io_bits & 0xf00000)) + config |= CR_C_HI_IO; + dio200_write8(dev, subpriv->ofs + 3, config); +} + +/* + * Handle 'insn_bits' for an '8255' DIO subdevice. + */ +static int dio200_subdev_8255_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) +{ + struct dio200_subdev_8255 *subpriv = s->private; + + if (data[0]) { + s->state &= ~data[0]; + s->state |= (data[0] & data[1]); + if (data[0] & 0xff) + dio200_write8(dev, subpriv->ofs, s->state & 0xff); + if (data[0] & 0xff00) + dio200_write8(dev, subpriv->ofs + 1, + (s->state >> 8) & 0xff); + if (data[0] & 0xff0000) + dio200_write8(dev, subpriv->ofs + 2, + (s->state >> 16) & 0xff); + } + data[1] = dio200_read8(dev, subpriv->ofs); + data[1] |= dio200_read8(dev, subpriv->ofs + 1) << 8; + data[1] |= dio200_read8(dev, subpriv->ofs + 2) << 16; + return 2; +} + +/* + * Handle 'insn_config' for an '8255' DIO subdevice. + */ +static int dio200_subdev_8255_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned int mask; + unsigned int bits; + + mask = 1 << CR_CHAN(insn->chanspec); + if (mask & 0x0000ff) + bits = 0x0000ff; + else if (mask & 0x00ff00) + bits = 0x00ff00; + else if (mask & 0x0f0000) + bits = 0x0f0000; + else + bits = 0xf00000; + switch (data[0]) { + case INSN_CONFIG_DIO_INPUT: + s->io_bits &= ~bits; + break; + case INSN_CONFIG_DIO_OUTPUT: + s->io_bits |= bits; + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT; + return insn->n; + break; + default: + return -EINVAL; + } + dio200_subdev_8255_set_dir(dev, s); + return 1; +} + +/* + * This function initializes an '8255' DIO subdevice. + * + * offset is the offset to the 8255 chip. + */ +static int dio200_subdev_8255_init(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int offset) +{ + struct dio200_subdev_8255 *subpriv; + + subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL); + if (!subpriv) + return -ENOMEM; + subpriv->ofs = offset; + s->private = subpriv; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 24; + s->range_table = &range_digital; + s->maxdata = 1; + s->insn_bits = dio200_subdev_8255_bits; + s->insn_config = dio200_subdev_8255_config; + s->state = 0; + s->io_bits = 0; + dio200_subdev_8255_set_dir(dev, s); + return 0; +} + +/* + * Handle 'insn_read' for a timer subdevice. + */ +static int dio200_subdev_timer_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned int n; + + for (n = 0; n < insn->n; n++) + data[n] = dio200_read32(dev, DIO200_TS_COUNT); + return n; +} + +/* + * Reset timer subdevice. + */ +static void dio200_subdev_timer_reset(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + unsigned int clock; + + clock = dio200_read32(dev, DIO200_TS_CONFIG) & TS_CONFIG_CLK_SRC_MASK; + dio200_write32(dev, DIO200_TS_CONFIG, clock | TS_CONFIG_RESET); + dio200_write32(dev, DIO200_TS_CONFIG, clock); +} + +/* + * Get timer subdevice clock source and period. + */ +static void dio200_subdev_timer_get_clock_src(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int *src, + unsigned int *period) +{ + unsigned int clk; + + clk = dio200_read32(dev, DIO200_TS_CONFIG) & TS_CONFIG_CLK_SRC_MASK; + *src = clk; + *period = (clk < ARRAY_SIZE(ts_clock_period)) ? + ts_clock_period[clk] : 0; +} + +/* + * Set timer subdevice clock source. + */ +static int dio200_subdev_timer_set_clock_src(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int src) +{ + if (src > TS_CONFIG_MAX_CLK_SRC) + return -EINVAL; + dio200_write32(dev, DIO200_TS_CONFIG, src); + return 0; +} + +/* + * Handle 'insn_config' for a timer subdevice. + */ +static int dio200_subdev_timer_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + int ret = 0; + + switch (data[0]) { + case INSN_CONFIG_RESET: + dio200_subdev_timer_reset(dev, s); + break; + case INSN_CONFIG_SET_CLOCK_SRC: + ret = dio200_subdev_timer_set_clock_src(dev, s, data[1]); + if (ret < 0) + ret = -EINVAL; + break; + case INSN_CONFIG_GET_CLOCK_SRC: + dio200_subdev_timer_get_clock_src(dev, s, &data[1], &data[2]); + break; + default: + ret = -EINVAL; + break; + } + return ret < 0 ? ret : insn->n; +} + +/* + * This function initializes a timer subdevice. + * + * Uses the timestamp timer registers. There is only one timestamp timer. + */ +static int dio200_subdev_timer_init(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + s->type = COMEDI_SUBD_TIMER; + s->subdev_flags = SDF_READABLE | SDF_LSAMPL; + s->n_chan = 1; + s->maxdata = 0xFFFFFFFF; + s->insn_read = dio200_subdev_timer_read; + s->insn_config = dio200_subdev_timer_config; + return 0; +} + +void amplc_dio200_set_enhance(struct comedi_device *dev, unsigned char val) +{ + dio200_write8(dev, DIO200_ENHANCE, val); +} +EXPORT_SYMBOL_GPL(amplc_dio200_set_enhance); + +int amplc_dio200_common_attach(struct comedi_device *dev, unsigned int irq, + unsigned long req_irq_flags) +{ + const struct dio200_board *thisboard = comedi_board(dev); + struct dio200_private *devpriv = dev->private; + const struct dio200_layout *layout = dio200_board_layout(thisboard); + struct comedi_subdevice *s; + int sdx; + unsigned int n; + int ret; + + devpriv->intr_sd = -1; + + ret = comedi_alloc_subdevices(dev, layout->n_subdevs); + if (ret) + return ret; + + for (n = 0; n < dev->n_subdevices; n++) { + s = &dev->subdevices[n]; + switch (layout->sdtype[n]) { + case sd_8254: + /* counter subdevice (8254) */ + ret = dio200_subdev_8254_init(dev, s, + layout->sdinfo[n]); + if (ret < 0) + return ret; + break; + case sd_8255: + /* digital i/o subdevice (8255) */ + ret = dio200_subdev_8255_init(dev, s, + layout->sdinfo[n]); + if (ret < 0) + return ret; + break; + case sd_intr: + /* 'INTERRUPT' subdevice */ + if (irq) { + ret = dio200_subdev_intr_init(dev, s, + DIO200_INT_SCE, + layout->sdinfo[n] + ); + if (ret < 0) + return ret; + devpriv->intr_sd = n; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + break; + case sd_timer: + ret = dio200_subdev_timer_init(dev, s); + if (ret < 0) + return ret; + break; + default: + s->type = COMEDI_SUBD_UNUSED; + break; + } + } + sdx = devpriv->intr_sd; + if (sdx >= 0 && sdx < dev->n_subdevices) + dev->read_subdev = &dev->subdevices[sdx]; + if (irq) { + if (request_irq(irq, dio200_interrupt, req_irq_flags, + dev->board_name, dev) >= 0) { + dev->irq = irq; + } else { + dev_warn(dev->class_dev, + "warning! irq %u unavailable!\n", irq); + } + } + dev_info(dev->class_dev, "attached\n"); + return 0; +} +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; + const struct dio200_layout *layout; + unsigned n; + + if (!thisboard || !devpriv) + return; + if (dev->irq) + free_irq(dev->irq, dev); + if (dev->subdevices) { + layout = dio200_board_layout(thisboard); + for (n = 0; n < dev->n_subdevices; n++) { + switch (layout->sdtype[n]) { + case sd_8254: + case sd_8255: + case sd_intr: + comedi_spriv_free(dev, n); + break; + case sd_timer: + default: + break; + } + } + } +} +EXPORT_SYMBOL_GPL(amplc_dio200_common_detach); + +static int __init amplc_dio200_common_init(void) +{ + return 0; +} +module_init(amplc_dio200_common_init); + +static void __exit amplc_dio200_common_exit(void) +{ +} +module_exit(amplc_dio200_common_exit); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi helper for amplc_dio200 and amplc_dio200_pci"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_dio200_pci.c b/drivers/staging/comedi/drivers/amplc_dio200_pci.c new file mode 100644 index 00000000000..4be44e87737 --- /dev/null +++ b/drivers/staging/comedi/drivers/amplc_dio200_pci.c @@ -0,0 +1,486 @@ +/* comedi/drivers/amplc_dio200_pci.c + + Driver for Amplicon PCI215, PCI272, PCIe215, PCIe236, PCIe296. + + Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +/* + * Driver: amplc_dio200_pci + * Description: Amplicon 200 Series PCI Digital I/O + * Author: Ian Abbott <abbotti@mev.co.uk> + * Devices: [Amplicon] PCI215 (amplc_dio200_pci), PCIe215, PCIe236, + * PCI272, PCIe296 + * Updated: Mon, 18 Mar 2013 15:03:50 +0000 + * Status: works + * + * Configuration options: + * none + * + * Manual configuration of PCI(e) cards is not supported; they are configured + * automatically. + * + * SUBDEVICES + * + * PCI215 PCIe215 PCIe236 + * ------------- ------------- ------------- + * Subdevices 5 8 8 + * 0 PPI-X PPI-X PPI-X + * 1 PPI-Y UNUSED UNUSED + * 2 CTR-Z1 PPI-Y UNUSED + * 3 CTR-Z2 UNUSED UNUSED + * 4 INTERRUPT CTR-Z1 CTR-Z1 + * 5 CTR-Z2 CTR-Z2 + * 6 TIMER TIMER + * 7 INTERRUPT INTERRUPT + * + * + * PCI272 PCIe296 + * ------------- ------------- + * Subdevices 4 8 + * 0 PPI-X PPI-X1 + * 1 PPI-Y PPI-X2 + * 2 PPI-Z PPI-Y1 + * 3 INTERRUPT PPI-Y2 + * 4 CTR-Z1 + * 5 CTR-Z2 + * 6 TIMER + * 7 INTERRUPT + * + * Each PPI 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 chips is supported. + * + * Each CTR is a 8254 chip providing 3 16-bit counter channels. Each + * channel is configured individually with INSN_CONFIG instructions. The + * specific type of configuration instruction is specified in data[0]. + * Some configuration instructions expect an additional parameter in + * data[1]; others return a value in data[1]. The following configuration + * instructions are supported: + * + * INSN_CONFIG_SET_COUNTER_MODE. Sets the counter channel's mode and + * BCD/binary setting specified in data[1]. + * + * INSN_CONFIG_8254_READ_STATUS. Reads the status register value for the + * counter channel into data[1]. + * + * INSN_CONFIG_SET_CLOCK_SRC. Sets the counter channel's clock source as + * specified in data[1] (this is a hardware-specific value). Not + * supported on PC214E. For the other boards, valid clock sources are + * 0 to 7 as follows: + * + * 0. CLK n, the counter channel's dedicated CLK input from the SK1 + * connector. (N.B. for other values, the counter channel's CLKn + * pin on the SK1 connector is an output!) + * 1. Internal 10 MHz clock. + * 2. Internal 1 MHz clock. + * 3. Internal 100 kHz clock. + * 4. Internal 10 kHz clock. + * 5. Internal 1 kHz clock. + * 6. OUT n-1, the output of counter channel n-1 (see note 1 below). + * 7. Ext Clock, the counter chip's dedicated Ext Clock input from + * the SK1 connector. This pin is shared by all three counter + * channels on the chip. + * + * For the PCIe boards, clock sources in the range 0 to 31 are allowed + * and the following additional clock sources are defined: + * + * 8. HIGH logic level. + * 9. LOW logic level. + * 10. "Pattern present" signal. + * 11. Internal 20 MHz clock. + * + * INSN_CONFIG_GET_CLOCK_SRC. Returns the counter channel's current + * clock source in data[1]. For internal clock sources, data[2] is set + * to the period in ns. + * + * INSN_CONFIG_SET_GATE_SRC. Sets the counter channel's gate source as + * specified in data[2] (this is a hardware-specific value). Not + * supported on PC214E. For the other boards, valid gate sources are 0 + * to 7 as follows: + * + * 0. VCC (internal +5V d.c.), i.e. gate permanently enabled. + * 1. GND (internal 0V d.c.), i.e. gate permanently disabled. + * 2. GAT n, the counter channel's dedicated GAT input from the SK1 + * connector. (N.B. for other values, the counter channel's GATn + * pin on the SK1 connector is an output!) + * 3. /OUT n-2, the inverted output of counter channel n-2 (see note + * 2 below). + * 4. Reserved. + * 5. Reserved. + * 6. Reserved. + * 7. Reserved. + * + * For the PCIe boards, gate sources in the range 0 to 31 are allowed; + * the following additional clock sources and clock sources 6 and 7 are + * (re)defined: + * + * 6. /GAT n, negated version of the counter channel's dedicated + * GAT input (negated version of gate source 2). + * 7. OUT n-2, the non-inverted output of counter channel n-2 + * (negated version of gate source 3). + * 8. "Pattern present" signal, HIGH while pattern present. + * 9. "Pattern occurred" latched signal, latches HIGH when pattern + * occurs. + * 10. "Pattern gone away" latched signal, latches LOW when pattern + * goes away after it occurred. + * 11. Negated "pattern present" signal, LOW while pattern present + * (negated version of gate source 8). + * 12. Negated "pattern occurred" latched signal, latches LOW when + * pattern occurs (negated version of gate source 9). + * 13. Negated "pattern gone away" latched signal, latches LOW when + * pattern goes away after it occurred (negated version of gate + * source 10). + * + * INSN_CONFIG_GET_GATE_SRC. Returns the counter channel's current gate + * source in data[2]. + * + * Clock and gate interconnection notes: + * + * 1. Clock source OUT n-1 is the output of the preceding channel on the + * same counter subdevice if n > 0, or the output of channel 2 on the + * preceding counter subdevice (see note 3) if n = 0. + * + * 2. Gate source /OUT n-2 is the inverted output of channel 0 on the + * same counter subdevice if n = 2, or the inverted output of channel n+1 + * on the preceding counter subdevice (see note 3) if n < 2. + * + * 3. The counter subdevices are connected in a ring, so the highest + * counter subdevice precedes the lowest. + * + * The 'TIMER' subdevice is a free-running 32-bit timer subdevice. + * + * The 'INTERRUPT' subdevice pretends to be a digital input subdevice. The + * digital inputs come from the interrupt status register. The number of + * channels matches the number of interrupt sources. The PC214E does not + * have an interrupt status register; see notes on 'INTERRUPT SOURCES' + * below. + * + * INTERRUPT SOURCES + * + * PCI215 PCIe215 PCIe236 + * ------------- ------------- ------------- + * Sources 6 6 6 + * 0 PPI-X-C0 PPI-X-C0 PPI-X-C0 + * 1 PPI-X-C3 PPI-X-C3 PPI-X-C3 + * 2 PPI-Y-C0 PPI-Y-C0 unused + * 3 PPI-Y-C3 PPI-Y-C3 unused + * 4 CTR-Z1-OUT1 CTR-Z1-OUT1 CTR-Z1-OUT1 + * 5 CTR-Z2-OUT1 CTR-Z2-OUT1 CTR-Z2-OUT1 + * + * PCI272 PCIe296 + * ------------- ------------- + * Sources 6 6 + * 0 PPI-X-C0 PPI-X1-C0 + * 1 PPI-X-C3 PPI-X1-C3 + * 2 PPI-Y-C0 PPI-Y1-C0 + * 3 PPI-Y-C3 PPI-Y1-C3 + * 4 PPI-Z-C0 CTR-Z1-OUT1 + * 5 PPI-Z-C3 CTR-Z2-OUT1 + * + * When an interrupt source is enabled in the interrupt source enable + * register, a rising edge on the source signal latches the corresponding + * bit to 1 in the interrupt status register. + * + * When the interrupt status register value as a whole (actually, just the + * 6 least significant bits) goes from zero to non-zero, the board will + * generate an interrupt. The interrupt will remain asserted until the + * interrupt status register is cleared to zero. To clear a bit to zero in + * the interrupt status register, the corresponding interrupt source must + * be disabled in the interrupt source enable register (there is no + * separate interrupt clear register). + * + * COMMANDS + * + * The driver supports a read streaming acquisition command on the + * 'INTERRUPT' subdevice. The channel list selects the interrupt sources + * to be enabled. All channels will be sampled together (convert_src == + * TRIG_NOW). The scan begins a short time after the hardware interrupt + * occurs, subject to interrupt latencies (scan_begin_src == TRIG_EXT, + * scan_begin_arg == 0). The value read from the interrupt status register + * is packed into a short value, one bit per requested channel, in the + * order they appear in the channel list. + */ + +#include <linux/pci.h> +#include <linux/interrupt.h> +#include <linux/slab.h> + +#include "../comedidev.h" + +#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. + */ + +enum dio200_pci_model { + pci215_model, + pci272_model, + pcie215_model, + pcie236_model, + pcie296_model +}; + +static const struct dio200_board dio200_pci_boards[] = { + [pci215_model] = { + .name = "pci215", + .bustype = pci_bustype, + .mainbar = 2, + .mainsize = DIO200_IO_SIZE, + .layout = { + .n_subdevs = 5, + .sdtype = {sd_8255, sd_8255, sd_8254, sd_8254, sd_intr}, + .sdinfo = {0x00, 0x08, 0x10, 0x14, 0x3F}, + .has_int_sce = true, + .has_clk_gat_sce = true, + }, + }, + [pci272_model] = { + .name = "pci272", + .bustype = pci_bustype, + .mainbar = 2, + .mainsize = DIO200_IO_SIZE, + .layout = { + .n_subdevs = 4, + .sdtype = {sd_8255, sd_8255, sd_8255, sd_intr}, + .sdinfo = {0x00, 0x08, 0x10, 0x3F}, + .has_int_sce = true, + }, + }, + [pcie215_model] = { + .name = "pcie215", + .bustype = pci_bustype, + .mainbar = 1, + .mainshift = 3, + .mainsize = DIO200_PCIE_IO_SIZE, + .layout = { + .n_subdevs = 8, + .sdtype = {sd_8255, sd_none, sd_8255, sd_none, + sd_8254, sd_8254, sd_timer, sd_intr}, + .sdinfo = {0x00, 0x00, 0x08, 0x00, + 0x10, 0x14, 0x00, 0x3F}, + .has_int_sce = true, + .has_clk_gat_sce = true, + .has_enhancements = true, + }, + }, + [pcie236_model] = { + .name = "pcie236", + .bustype = pci_bustype, + .mainbar = 1, + .mainshift = 3, + .mainsize = DIO200_PCIE_IO_SIZE, + .layout = { + .n_subdevs = 8, + .sdtype = {sd_8255, sd_none, sd_none, sd_none, + sd_8254, sd_8254, sd_timer, sd_intr}, + .sdinfo = {0x00, 0x00, 0x00, 0x00, + 0x10, 0x14, 0x00, 0x3F}, + .has_int_sce = true, + .has_clk_gat_sce = true, + .has_enhancements = true, + }, + }, + [pcie296_model] = { + .name = "pcie296", + .bustype = pci_bustype, + .mainbar = 1, + .mainshift = 3, + .mainsize = DIO200_PCIE_IO_SIZE, + .layout = { + .n_subdevs = 8, + .sdtype = {sd_8255, sd_8255, sd_8255, sd_8255, + sd_8254, sd_8254, sd_timer, sd_intr}, + .sdinfo = {0x00, 0x04, 0x08, 0x0C, + 0x10, 0x14, 0x00, 0x3F}, + .has_int_sce = true, + .has_clk_gat_sce = true, + .has_enhancements = true, + }, + }, +}; + +/* + * This function does some special set-up for the PCIe boards + * PCIe215, PCIe236, PCIe296. + */ +static int dio200_pcie_board_setup(struct comedi_device *dev) +{ + struct pci_dev *pcidev = comedi_to_pci_dev(dev); + void __iomem *brbase; + + /* + * The board uses Altera Cyclone IV with PCI-Express hard IP. + * The FPGA configuration has the PCI-Express Avalon-MM Bridge + * Control registers in PCI BAR 0, offset 0, and the length of + * these registers is 0x4000. + * + * We need to write 0x80 to the "Avalon-MM to PCI-Express Interrupt + * Enable" register at offset 0x50 to allow generation of PCIe + * interrupts when RXmlrq_i is asserted in the SOPC Builder system. + */ + if (pci_resource_len(pcidev, 0) < 0x4000) { + dev_err(dev->class_dev, "error! bad PCI region!\n"); + return -EINVAL; + } + brbase = pci_ioremap_bar(pcidev, 0); + if (!brbase) { + dev_err(dev->class_dev, "error! failed to map registers!\n"); + return -ENOMEM; + } + writel(0x80, brbase + 0x50); + iounmap(brbase); + /* Enable "enhanced" features of board. */ + amplc_dio200_set_enhance(dev, 1); + return 0; +} + +static int dio200_pci_auto_attach(struct comedi_device *dev, + unsigned long context_model) +{ + struct pci_dev *pci_dev = comedi_to_pci_dev(dev); + const struct dio200_board *thisboard = NULL; + struct dio200_private *devpriv; + unsigned int bar; + int ret; + + if (context_model < ARRAY_SIZE(dio200_pci_boards)) + thisboard = &dio200_pci_boards[context_model]; + if (!thisboard) + return -EINVAL; + dev->board_ptr = thisboard; + dev->board_name = thisboard->name; + + dev_info(dev->class_dev, "%s: attach pci %s (%s)\n", + dev->driver->driver_name, pci_name(pci_dev), dev->board_name); + + devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + if (!devpriv) + return -ENOMEM; + dev->private = devpriv; + + ret = comedi_pci_enable(dev); + if (ret) + return ret; + + bar = thisboard->mainbar; + if (pci_resource_len(pci_dev, bar) < thisboard->mainsize) { + dev_err(dev->class_dev, "error! PCI region size too small!\n"); + 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_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; + } + switch (context_model) { + case pcie215_model: + case pcie236_model: + case pcie296_model: + ret = dio200_pcie_board_setup(dev); + if (ret < 0) + return ret; + break; + default: + break; + } + return amplc_dio200_common_attach(dev, pci_dev->irq, IRQF_SHARED); +} + +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); + comedi_pci_disable(dev); +} + +static struct comedi_driver dio200_pci_comedi_driver = { + .driver_name = "amplc_dio200_pci", + .module = THIS_MODULE, + .auto_attach = dio200_pci_auto_attach, + .detach = dio200_pci_detach, +}; + +static DEFINE_PCI_DEVICE_TABLE(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 + }, + {0} +}; + +MODULE_DEVICE_TABLE(pci, dio200_pci_table); + +static int dio200_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + return comedi_pci_auto_config(dev, &dio200_pci_comedi_driver, + id->driver_data); +} + +static struct pci_driver dio200_pci_pci_driver = { + .name = "amplc_dio200_pci", + .id_table = dio200_pci_table, + .probe = dio200_pci_probe, + .remove = comedi_pci_auto_unconfig, +}; +module_comedi_pci_driver(dio200_pci_comedi_driver, dio200_pci_pci_driver); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi driver for Amplicon 200 Series PCI(e) DIO boards"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index 479e10fddd2..115ecd51677 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -75,23 +75,19 @@ unused. #define PC236_IO_SIZE 4 #define PC236_LCR_IO_SIZE 128 -/* - * INTCSR values for PCI236. - */ -/* Disable interrupt, also clear any interrupt there */ -#define PCI236_INTR_DISABLE (PLX9052_INTCSR_LI1ENAB_DISABLED \ - | PLX9052_INTCSR_LI1POL_HIGH \ - | PLX9052_INTCSR_LI2POL_HIGH \ - | PLX9052_INTCSR_PCIENAB_DISABLED \ - | PLX9052_INTCSR_LI1SEL_EDGE \ - | PLX9052_INTCSR_LI1CLRINT_ASSERTED) -/* Enable interrupt, also clear any interrupt there. */ -#define PCI236_INTR_ENABLE (PLX9052_INTCSR_LI1ENAB_ENABLED \ - | PLX9052_INTCSR_LI1POL_HIGH \ - | PLX9052_INTCSR_LI2POL_HIGH \ - | PLX9052_INTCSR_PCIENAB_ENABLED \ - | PLX9052_INTCSR_LI1SEL_EDGE \ - | PLX9052_INTCSR_LI1CLRINT_ASSERTED) +/* 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. @@ -209,21 +205,6 @@ static struct pci_dev *pc236_find_pci_dev(struct comedi_device *dev, } /* - * This function checks and requests an I/O region, reporting an error - * if there is a conflict. - */ -static int pc236_request_region(struct comedi_device *dev, unsigned long from, - unsigned long extent) -{ - if (!from || !request_region(from, extent, PC236_DRIVER_NAME)) { - dev_err(dev->class_dev, "I/O port conflict (%#lx,%lu)!\n", - from, extent); - return -EIO; - } - return 0; -} - -/* * 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!). @@ -272,14 +253,14 @@ static int pc236_intr_check(struct comedi_device *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)) { - if ((inl(devpriv->lcr_iobase + PLX9052_INTCSR) - & PLX9052_INTCSR_LI1STAT_MASK) - == PLX9052_INTCSR_LI1STAT_INACTIVE) { + intcsr = inl(devpriv->lcr_iobase + PLX9052_INTCSR); + if (!(intcsr & PLX9052_INTCSR_LI1STAT)) { retval = 0; } else { /* Clear interrupt and keep it enabled. */ @@ -470,12 +451,10 @@ static int pc236_pci_common_attach(struct comedi_device *dev, comedi_set_hw_dev(dev, &pci_dev->dev); - ret = comedi_pci_enable(pci_dev, PC236_DRIVER_NAME); - if (ret < 0) { - dev_err(dev->class_dev, - "error! cannot enable PCI device and request regions!\n"); + 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 pc236_common_attach(dev, iobase, pci_dev->irq, IRQF_SHARED); @@ -493,8 +472,6 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct pc236_private *devpriv; int ret; - dev_info(dev->class_dev, PC236_DRIVER_NAME ": attach\n"); - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; @@ -502,12 +479,11 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* Process options according to bus type. */ if (is_isa_board(thisboard)) { - unsigned long iobase = it->options[0]; - unsigned int irq = it->options[1]; - ret = pc236_request_region(dev, iobase, PC236_IO_SIZE); - if (ret < 0) + ret = comedi_request_region(dev, it->options[0], PC236_IO_SIZE); + if (ret) return ret; - return pc236_common_attach(dev, iobase, irq, 0); + + return pc236_common_attach(dev, dev->iobase, it->options[1], 0); } else if (is_pci_board(thisboard)) { struct pci_dev *pci_dev; @@ -567,20 +543,16 @@ static void pc236_detach(struct comedi_device *dev) return; if (dev->iobase) pc236_intr_disable(dev); - if (dev->irq) - free_irq(dev->irq, dev); - if (dev->subdevices) - subdev_8255_cleanup(dev, &dev->subdevices[0]); + comedi_spriv_free(dev, 0); if (is_isa_board(thisboard)) { - if (dev->iobase) - release_region(dev->iobase, PC236_IO_SIZE); + comedi_legacy_detach(dev); } else if (is_pci_board(thisboard)) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); + if (dev->irq) + free_irq(dev->irq, dev); + comedi_pci_disable(dev); + if (pcidev) pci_dev_put(pcidev); - } } } @@ -610,9 +582,10 @@ static DEFINE_PCI_DEVICE_TABLE(pc236_pci_table) = { MODULE_DEVICE_TABLE(pci, pc236_pci_table); static int amplc_pc236_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &lc_pc236_driver); + return comedi_pci_auto_config(dev, &lc_pc236_driver, + id->driver_data); } static struct pci_driver amplc_pc236_pci_driver = { diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 11c1f4764ea..94a752d852b 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -24,163 +24,41 @@ */ /* Driver: amplc_pc263 -Description: Amplicon PC263, PCI263 +Description: Amplicon PC263 Author: Ian Abbott <abbotti@mev.co.uk> -Devices: [Amplicon] PC263 (pc263), PCI263 (pci263 or amplc_pc263) -Updated: Wed, 22 Oct 2008 14:10:53 +0100 +Devices: [Amplicon] PC263 (pc263) +Updated: Fri, 12 Apr 2013 15:19:36 +0100 Status: works -Configuration options - PC263: +Configuration options: [0] - I/O port base address -Configuration options - PCI263: - [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. - -Each board appears as one subdevice, with 16 digital outputs, each +The board appears as one subdevice, with 16 digital outputs, each connected to a reed-relay. Relay contacts are closed when output is 1. The state of the outputs can be read. */ -#include <linux/pci.h> - #include "../comedidev.h" #define PC263_DRIVER_NAME "amplc_pc263" -#define DO_ISA IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA) -#define DO_PCI IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) - -/* PCI263 PCI configuration register information */ -#define PCI_DEVICE_ID_AMPLICON_PCI263 0x000c -#define PCI_DEVICE_ID_INVALID 0xffff - -/* PC263 / PCI263 registers */ +/* PC263 registers */ #define PC263_IO_SIZE 2 /* - * Board descriptions for Amplicon PC263 / PCI263. + * Board descriptions for Amplicon PC263. */ -enum pc263_bustype { isa_bustype, pci_bustype }; -enum pc263_model { pc263_model, pci263_model, anypci_model }; - struct pc263_board { const char *name; - unsigned short devid; - enum pc263_bustype bustype; - enum pc263_model model; }; + static const struct pc263_board pc263_boards[] = { -#if DO_ISA { .name = "pc263", - .bustype = isa_bustype, - .model = pc263_model, }, -#endif -#if DO_PCI - { - .name = "pci263", - .devid = PCI_DEVICE_ID_AMPLICON_PCI263, - .bustype = pci_bustype, - .model = pci263_model, - }, - { - .name = PC263_DRIVER_NAME, - .devid = PCI_DEVICE_ID_INVALID, - .bustype = pci_bustype, - .model = anypci_model, /* wildcard */ - }, -#endif }; -/* test if ISA supported and this is an ISA board */ -static inline bool is_isa_board(const struct pc263_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 pc263_board *board) -{ - return DO_PCI && board->bustype == pci_bustype; -} - -/* - * This function looks for a board matching the supplied PCI device. - */ -static const struct pc263_board *pc263_find_pci_board(struct pci_dev *pci_dev) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(pc263_boards); i++) - if (is_pci_board(&pc263_boards[i]) && - pci_dev->device == pc263_boards[i].devid) - return &pc263_boards[i]; - return NULL; -} - - -/* - * This function looks for a PCI device matching the requested board name, - * bus and slot. - */ -static struct pci_dev *pc263_find_pci_dev(struct comedi_device *dev, - struct comedi_devconfig *it) -{ - const struct pc263_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 pc263_board *foundboard; - - foundboard = pc263_find_pci_board(pci_dev); - if (foundboard == NULL) - continue; - /* Replace wildcard board_ptr. */ - dev->board_ptr = thisboard = 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 checks and requests an I/O region, reporting an error - * if there is a conflict. - */ -static int pc263_request_region(struct comedi_device *dev, unsigned long from, - unsigned long extent) -{ - if (!from || !request_region(from, extent, PC263_DRIVER_NAME)) { - dev_err(dev->class_dev, "I/O port conflict (%#lx,%lu)!\n", - from, extent); - return -EIO; - } - return 0; -} - static int pc263_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -197,30 +75,14 @@ static int pc263_do_insn_bits(struct comedi_device *dev, return insn->n; } -static void pc263_report_attach(struct comedi_device *dev) -{ - const struct pc263_board *thisboard = comedi_board(dev); - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - char tmpbuf[40]; - - if (is_isa_board(thisboard)) - snprintf(tmpbuf, sizeof(tmpbuf), "(base %#lx) ", dev->iobase); - else if (is_pci_board(thisboard)) - snprintf(tmpbuf, sizeof(tmpbuf), "(pci %s) ", - pci_name(pcidev)); - else - tmpbuf[0] = '\0'; - dev_info(dev->class_dev, "%s %sattached\n", dev->board_name, tmpbuf); -} - -static int pc263_common_attach(struct comedi_device *dev, unsigned long iobase) +static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - const struct pc263_board *thisboard = comedi_board(dev); struct comedi_subdevice *s; int ret; - dev->board_name = thisboard->name; - dev->iobase = iobase; + ret = comedi_request_region(dev, it->options[0], PC263_IO_SIZE); + if (ret) + return ret; ret = comedi_alloc_subdevices(dev, 1); if (ret) @@ -237,154 +99,23 @@ static int pc263_common_attach(struct comedi_device *dev, unsigned long iobase) /* read initial relay state */ s->state = inb(dev->iobase) | (inb(dev->iobase + 1) << 8); - pc263_report_attach(dev); - return 1; -} - -static int pc263_pci_common_attach(struct comedi_device *dev, - struct pci_dev *pci_dev) -{ - unsigned long iobase; - int ret; - - comedi_set_hw_dev(dev, &pci_dev->dev); - - ret = comedi_pci_enable(pci_dev, PC263_DRIVER_NAME); - if (ret < 0) { - dev_err(dev->class_dev, - "error! cannot enable PCI device and request regions!\n"); - return ret; - } - iobase = pci_resource_start(pci_dev, 2); - return pc263_common_attach(dev, iobase); -} - -/* - * 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 pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it) -{ - const struct pc263_board *thisboard = comedi_board(dev); - int ret; - - dev_info(dev->class_dev, PC263_DRIVER_NAME ": attach\n"); - - /* Process options and reserve resources according to bus type. */ - if (is_isa_board(thisboard)) { - unsigned long iobase = it->options[0]; - ret = pc263_request_region(dev, iobase, PC263_IO_SIZE); - if (ret < 0) - return ret; - return pc263_common_attach(dev, iobase); - } else if (is_pci_board(thisboard)) { - struct pci_dev *pci_dev; - - pci_dev = pc263_find_pci_dev(dev, it); - if (!pci_dev) - return -EIO; - return pc263_pci_common_attach(dev, pci_dev); - } else { - dev_err(dev->class_dev, PC263_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 pc263_auto_attach(struct comedi_device *dev, - unsigned long context_unused) -{ - struct pci_dev *pci_dev; - - if (!DO_PCI) - return -EINVAL; - - pci_dev = comedi_to_pci_dev(dev); - dev_info(dev->class_dev, PC263_DRIVER_NAME ": attach pci %s\n", - pci_name(pci_dev)); - dev->board_ptr = pc263_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 pc263_detach(). - * TODO: Remove the pci_dev_get() and matching pci_dev_put() once - * support for manual attachment of PCI devices via pc263_attach() - * has been removed. - */ - pci_dev_get(pci_dev); - return pc263_pci_common_attach(dev, pci_dev); -} - -static void pc263_detach(struct comedi_device *dev) -{ - const struct pc263_board *thisboard = comedi_board(dev); - - if (!thisboard) - return; - if (is_isa_board(thisboard)) { - if (dev->iobase) - release_region(dev->iobase, PC263_IO_SIZE); - } else if (is_pci_board(thisboard)) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - pci_dev_put(pcidev); - } - } + dev_info(dev->class_dev, "%s (base %#lx) attached\n", dev->board_name, + dev->iobase); + return 0; } -/* - * 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_pc263_driver = { .driver_name = PC263_DRIVER_NAME, .module = THIS_MODULE, .attach = pc263_attach, - .auto_attach = pc263_auto_attach, - .detach = pc263_detach, + .detach = comedi_legacy_detach, .board_name = &pc263_boards[0].name, .offset = sizeof(struct pc263_board), .num_names = ARRAY_SIZE(pc263_boards), }; -#if DO_PCI -static DEFINE_PCI_DEVICE_TABLE(pc263_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI263) }, - {0} -}; -MODULE_DEVICE_TABLE(pci, pc263_pci_table); - -static int amplc_pc263_pci_probe(struct pci_dev *dev, - const struct pci_device_id - *ent) -{ - return comedi_pci_auto_config(dev, &lc_pc263_driver); -} - -static struct pci_driver amplc_pc263_pci_driver = { - .name = PC263_DRIVER_NAME, - .id_table = pc263_pci_table, - .probe = &lc_pc263_pci_probe, - .remove = comedi_pci_auto_unconfig, -}; -module_comedi_pci_driver(amplc_pc263_driver, amplc_pc263_pci_driver); -#else module_comedi_driver(amplc_pc263_driver); -#endif MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for Amplicon PC263 relay board"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index c9da4cd74ba..4d7eab9b556 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -1280,13 +1280,10 @@ static int pci224_attach_common(struct comedi_device *dev, comedi_set_hw_dev(dev, &pci_dev->dev); - ret = comedi_pci_enable(pci_dev, DRIVER_NAME); - if (ret < 0) { - dev_err(dev->class_dev, - "error! cannot enable PCI device and request regions!\n" - ); + ret = comedi_pci_enable(dev); + if (ret) return ret; - } + spin_lock_init(&devpriv->ao_spinlock); devpriv->iobase1 = pci_resource_start(pci_dev, 2); @@ -1488,11 +1485,9 @@ static void pci224_detach(struct comedi_device *dev) kfree(devpriv->ao_scan_vals); kfree(devpriv->ao_scan_order); } - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); + comedi_pci_disable(dev); + if (pcidev) pci_dev_put(pcidev); - } } static struct comedi_driver amplc_pci224_driver = { @@ -1507,10 +1502,10 @@ static struct comedi_driver amplc_pci224_driver = { }; static int amplc_pci224_pci_probe(struct pci_dev *dev, - const struct pci_device_id - *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &lc_pci224_driver); + return comedi_pci_auto_config(dev, &lc_pci224_driver, + id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(amplc_pci224_pci_table) = { diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index e2244c6e536..49200fbd60b 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -2645,12 +2645,11 @@ static int pci230_attach_common(struct comedi_device *dev, comedi_set_hw_dev(dev, &pci_dev->dev); dev->board_name = thisboard->name; - /* Enable PCI device and reserve I/O spaces. */ - if (comedi_pci_enable(pci_dev, "amplc_pci230") < 0) { - dev_err(dev->class_dev, - "failed to enable PCI device and request regions\n"); - return -EIO; - } + + rc = comedi_pci_enable(dev); + if (rc) + return rc; + /* Read base addresses of the PCI230's two I/O regions from PCI * configuration register. */ iobase1 = pci_resource_start(pci_dev, 2); @@ -2833,18 +2832,14 @@ static int pci230_auto_attach(struct comedi_device *dev, static void pci230_detach(struct comedi_device *dev) { - const struct pci230_board *thisboard = comedi_board(dev); struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (dev->subdevices && thisboard->have_dio) - subdev_8255_cleanup(dev, &dev->subdevices[2]); + comedi_spriv_free(dev, 2); if (dev->irq) free_irq(dev->irq, dev); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); + comedi_pci_disable(dev); + if (pcidev) pci_dev_put(pcidev); - } } static struct comedi_driver amplc_pci230_driver = { @@ -2859,9 +2854,10 @@ static struct comedi_driver amplc_pci230_driver = { }; static int amplc_pci230_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &lc_pci230_driver); + return comedi_pci_auto_config(dev, &lc_pci230_driver, + id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(amplc_pci230_pci_table) = { diff --git a/drivers/staging/comedi/drivers/amplc_pci263.c b/drivers/staging/comedi/drivers/amplc_pci263.c new file mode 100644 index 00000000000..8b57533bf40 --- /dev/null +++ b/drivers/staging/comedi/drivers/amplc_pci263.c @@ -0,0 +1,127 @@ +/* + comedi/drivers/amplc_pci263.c + Driver for Amplicon PCI263 relay board. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +/* +Driver: amplc_pci263 +Description: Amplicon PCI263 +Author: Ian Abbott <abbotti@mev.co.uk> +Devices: [Amplicon] PCI263 (amplc_pci263) +Updated: Fri, 12 Apr 2013 15:19:36 +0100 +Status: works + +Configuration options: not applicable, uses PCI auto config + +The board appears as one subdevice, with 16 digital outputs, each +connected to a reed-relay. Relay contacts are closed when output is 1. +The state of the outputs can be read. +*/ + +#include <linux/pci.h> + +#include "../comedidev.h" + +#define 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, unsigned int *data) +{ + /* The insn data is a mask in data[0] and the new data + * in data[1], each channel cooresponding to a bit. */ + if (data[0]) { + s->state &= ~data[0]; + s->state |= data[0] & data[1]; + /* Write out the new digital output lines */ + outb(s->state & 0xFF, dev->iobase); + outb(s->state >> 8, dev->iobase + 1); + } + return insn->n; +} + +static int pci263_auto_attach(struct comedi_device *dev, + unsigned long context_unused) +{ + struct pci_dev *pci_dev = comedi_to_pci_dev(dev); + struct comedi_subdevice *s; + int ret; + + ret = comedi_pci_enable(dev); + if (ret) + return ret; + + dev->iobase = pci_resource_start(pci_dev, 2); + ret = comedi_alloc_subdevices(dev, 1); + if (ret) + return ret; + + s = &dev->subdevices[0]; + /* digital output subdevice */ + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pci263_do_insn_bits; + /* read initial relay state */ + s->state = inb(dev->iobase) | (inb(dev->iobase + 1) << 8); + + dev_info(dev->class_dev, "%s (pci %s) attached\n", dev->board_name, + pci_name(pci_dev)); + return 0; +} + +static struct comedi_driver amplc_pci263_driver = { + .driver_name = PCI263_DRIVER_NAME, + .module = THIS_MODULE, + .auto_attach = pci263_auto_attach, + .detach = comedi_pci_disable, +}; + +static DEFINE_PCI_DEVICE_TABLE(pci263_pci_table) = { + { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI263) }, + {0} +}; +MODULE_DEVICE_TABLE(pci, pci263_pci_table); + +static int amplc_pci263_pci_probe(struct pci_dev *dev, + const struct pci_device_id *id) +{ + return comedi_pci_auto_config(dev, &lc_pci263_driver, + id->driver_data); +} + +static struct pci_driver amplc_pci263_pci_driver = { + .name = PCI263_DRIVER_NAME, + .id_table = pci263_pci_table, + .probe = &lc_pci263_pci_probe, + .remove = comedi_pci_auto_unconfig, +}; +module_comedi_pci_driver(amplc_pci263_driver, amplc_pci263_pci_driver); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi driver for Amplicon PCI263 relay board"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c index 070037c22db..92376dc86dd 100644 --- a/drivers/staging/comedi/drivers/c6xdigio.c +++ b/drivers/staging/comedi/drivers/c6xdigio.c @@ -397,12 +397,6 @@ static void board_init(struct comedi_device *dev) } -/* - options[0] - I/O port - options[1] - irq - options[2] - number of encoder chips installed - */ - static const struct pnp_device_id c6xdigio_pnp_tbl[] = { /* Standard LPT Printer Port */ {.id = "PNP0400", .driver_data = 0}, @@ -419,34 +413,20 @@ static struct pnp_driver c6xdigio_pnp_driver = { static int c6xdigio_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - int result = 0; - unsigned long iobase; - unsigned int irq; struct comedi_subdevice *s; + int ret; - iobase = it->options[0]; - printk(KERN_DEBUG "comedi%d: c6xdigio: 0x%04lx\n", dev->minor, iobase); - if (!request_region(iobase, C6XDIGIO_SIZE, "c6xdigio")) { - printk(KERN_ERR "comedi%d: I/O port conflict\n", dev->minor); - return -EIO; - } - dev->iobase = iobase; - dev->board_name = "c6xdigio"; + ret = comedi_request_region(dev, it->options[0], C6XDIGIO_SIZE); + if (ret) + return ret; - result = comedi_alloc_subdevices(dev, 2); - if (result) - return result; + ret = comedi_alloc_subdevices(dev, 2); + if (ret) + return ret; /* Make sure that PnP ports get activated */ pnp_register_driver(&c6xdigio_pnp_driver); - irq = it->options[1]; - if (irq > 0) - printk(KERN_DEBUG "comedi%d: irq = %u ignored\n", - dev->minor, irq); - else if (irq == 0) - printk(KERN_DEBUG "comedi%d: no irq\n", dev->minor); - s = &dev->subdevices[0]; /* pwm output subdevice */ s->type = COMEDI_SUBD_AO; /* Not sure what to put here */ @@ -488,10 +468,7 @@ static int c6xdigio_attach(struct comedi_device *dev, static void c6xdigio_detach(struct comedi_device *dev) { - if (dev->iobase) - release_region(dev->iobase, C6XDIGIO_SIZE); - if (dev->irq) - free_irq(dev->irq, dev); + comedi_legacy_detach(dev); pnp_unregister_driver(&c6xdigio_pnp_driver); } diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 79c72118a09..53dd298d2b5 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -231,9 +231,19 @@ enum trimpot_model { AD8402, }; +enum cb_pcidas_boardid { + BOARD_PCIDAS1602_16, + BOARD_PCIDAS1200, + BOARD_PCIDAS1602_12, + BOARD_PCIDAS1200_JR, + BOARD_PCIDAS1602_16_JR, + BOARD_PCIDAS1000, + BOARD_PCIDAS1001, + BOARD_PCIDAS1002, +}; + struct cb_pcidas_board { const char *name; - unsigned short device_id; int ai_nchan; /* Inputs in single-ended mode */ int ai_bits; /* analog input resolution */ int ai_speed; /* fastest conversion period in ns */ @@ -248,9 +258,8 @@ struct cb_pcidas_board { }; static const struct cb_pcidas_board cb_pcidas_boards[] = { - { + [BOARD_PCIDAS1602_16] = { .name = "pci-das1602/16", - .device_id = 0x1, .ai_nchan = 16, .ai_bits = 16, .ai_speed = 5000, @@ -262,9 +271,9 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .trimpot = AD8402, .has_dac08 = 1, .is_1602 = 1, - }, { + }, + [BOARD_PCIDAS1200] = { .name = "pci-das1200", - .device_id = 0xF, .ai_nchan = 16, .ai_bits = 12, .ai_speed = 3200, @@ -272,9 +281,9 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .fifo_size = 1024, .ranges = &cb_pcidas_ranges, .trimpot = AD7376, - }, { + }, + [BOARD_PCIDAS1602_12] = { .name = "pci-das1602/12", - .device_id = 0x10, .ai_nchan = 16, .ai_bits = 12, .ai_speed = 3200, @@ -285,18 +294,18 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .ranges = &cb_pcidas_ranges, .trimpot = AD7376, .is_1602 = 1, - }, { + }, + [BOARD_PCIDAS1200_JR] = { .name = "pci-das1200/jr", - .device_id = 0x19, .ai_nchan = 16, .ai_bits = 12, .ai_speed = 3200, .fifo_size = 1024, .ranges = &cb_pcidas_ranges, .trimpot = AD7376, - }, { + }, + [BOARD_PCIDAS1602_16_JR] = { .name = "pci-das1602/16/jr", - .device_id = 0x1C, .ai_nchan = 16, .ai_bits = 16, .ai_speed = 5000, @@ -305,18 +314,18 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .trimpot = AD8402, .has_dac08 = 1, .is_1602 = 1, - }, { + }, + [BOARD_PCIDAS1000] = { .name = "pci-das1000", - .device_id = 0x4C, .ai_nchan = 16, .ai_bits = 12, .ai_speed = 4000, .fifo_size = 1024, .ranges = &cb_pcidas_ranges, .trimpot = AD7376, - }, { + }, + [BOARD_PCIDAS1001] = { .name = "pci-das1001", - .device_id = 0x1a, .ai_nchan = 16, .ai_bits = 12, .ai_speed = 6800, @@ -324,9 +333,9 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = { .fifo_size = 1024, .ranges = &cb_pcidas_alt_ranges, .trimpot = AD7376, - }, { + }, + [BOARD_PCIDAS1002] = { .name = "pci-das1002", - .device_id = 0x1b, .ai_nchan = 16, .ai_bits = 12, .ai_speed = 6800, @@ -1332,7 +1341,7 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) static const int timeout = 10000; unsigned long flags; - if (dev->attached == 0) + if (!dev->attached) return IRQ_NONE; async = s->async; @@ -1424,31 +1433,18 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) return IRQ_HANDLED; } -static const void *cb_pcidas_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct cb_pcidas_board *thisboard; - int i; - - for (i = 0; i < ARRAY_SIZE(cb_pcidas_boards); i++) { - thisboard = &cb_pcidas_boards[i]; - if (thisboard->device_id == pcidev->device) - return thisboard; - } - return NULL; -} - static int cb_pcidas_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct cb_pcidas_board *thisboard; + const struct cb_pcidas_board *thisboard = NULL; struct cb_pcidas_private *devpriv; struct comedi_subdevice *s; int i; int ret; - thisboard = cb_pcidas_find_boardinfo(dev, pcidev); + if (context < ARRAY_SIZE(cb_pcidas_boards)) + thisboard = &cb_pcidas_boards[context]; if (!thisboard) return -ENODEV; dev->board_ptr = thisboard; @@ -1459,7 +1455,7 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; @@ -1603,7 +1599,6 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, static void cb_pcidas_detach(struct comedi_device *dev) { struct cb_pcidas_private *devpriv = dev->private; - struct pci_dev *pcidev = comedi_to_pci_dev(dev); if (devpriv) { if (devpriv->s5933_config) { @@ -1613,12 +1608,8 @@ static void cb_pcidas_detach(struct comedi_device *dev) } if (dev->irq) free_irq(dev->irq, dev); - if (dev->subdevices) - subdev_8255_cleanup(dev, &dev->subdevices[2]); - if (pcidev) { - if (devpriv->s5933_config) - comedi_pci_disable(pcidev); - } + comedi_spriv_free(dev, 2); + comedi_pci_disable(dev); } static struct comedi_driver cb_pcidas_driver = { @@ -1629,20 +1620,21 @@ static struct comedi_driver cb_pcidas_driver = { }; static int cb_pcidas_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &cb_pcidas_driver); + return comedi_pci_auto_config(dev, &cb_pcidas_driver, + id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(cb_pcidas_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0001) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x000f) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0010) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0019) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001c) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x004c) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001a) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001b) }, + { PCI_VDEVICE(CB, 0x0001), BOARD_PCIDAS1602_16 }, + { PCI_VDEVICE(CB, 0x000f), BOARD_PCIDAS1200 }, + { PCI_VDEVICE(CB, 0x0010), BOARD_PCIDAS1602_12 }, + { PCI_VDEVICE(CB, 0x0019), BOARD_PCIDAS1200_JR }, + { PCI_VDEVICE(CB, 0x001c), BOARD_PCIDAS1602_16_JR }, + { PCI_VDEVICE(CB, 0x004c), BOARD_PCIDAS1000 }, + { PCI_VDEVICE(CB, 0x001a), BOARD_PCIDAS1001 }, + { PCI_VDEVICE(CB, 0x001b), BOARD_PCIDAS1002 }, { 0 } }; MODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table); diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index 9f3112cb7a2..c3e5495b4f0 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -118,13 +118,6 @@ static const int max_counter_value = 0xffffff; /* PCI-DAS64xxx base addresses */ -/* indices of base address regions */ -enum base_address_regions { - PLX9080_BADDRINDEX = 0, - MAIN_BADDRINDEX = 2, - DIO_COUNTER_BADDRINDEX = 3, -}; - /* devpriv->main_iobase registers */ enum write_only_registers { INTR_ENABLE_REG = 0x0, /* interrupt enable register */ @@ -543,13 +536,6 @@ static const int ao_range_code_64xx[] = { 0x3, }; -static const struct comedi_lrange ao_ranges_60xx = { - 1, - { - BIP_RANGE(10), - } -}; - static const int ao_range_code_60xx[] = { 0x0, }; @@ -593,9 +579,39 @@ struct hw_fifo_info { uint16_t fifo_size_reg_mask; }; +enum pcidas64_boardid { + BOARD_PCIDAS6402_16, + BOARD_PCIDAS6402_12, + BOARD_PCIDAS64_M1_16, + BOARD_PCIDAS64_M2_16, + BOARD_PCIDAS64_M3_16, + BOARD_PCIDAS6013, + BOARD_PCIDAS6014, + BOARD_PCIDAS6023, + BOARD_PCIDAS6025, + BOARD_PCIDAS6030, + BOARD_PCIDAS6031, + BOARD_PCIDAS6032, + BOARD_PCIDAS6033, + BOARD_PCIDAS6034, + BOARD_PCIDAS6035, + BOARD_PCIDAS6036, + BOARD_PCIDAS6040, + BOARD_PCIDAS6052, + BOARD_PCIDAS6070, + BOARD_PCIDAS6071, + BOARD_PCIDAS4020_12, + BOARD_PCIDAS6402_16_JR, + BOARD_PCIDAS64_M1_16_JR, + BOARD_PCIDAS64_M2_16_JR, + BOARD_PCIDAS64_M3_16_JR, + BOARD_PCIDAS64_M1_14, + BOARD_PCIDAS64_M2_14, + BOARD_PCIDAS64_M3_14, +}; + struct pcidas64_board { const char *name; - int device_id; /* pci device id */ int ai_se_chans; /* number of ai inputs in single-ended mode */ int ai_bits; /* analog input resolution */ int ai_speed; /* fastest conversion period in ns */ @@ -648,421 +664,397 @@ static inline unsigned int ai_dma_ring_count(const struct pcidas64_board *board) static const int bytes_in_sample = 2; static const struct pcidas64_board pcidas64_boards[] = { - { - .name = "pci-das6402/16", - .device_id = 0x1d, - .ai_se_chans = 64, - .ai_bits = 16, - .ai_speed = 5000, - .ao_nchan = 2, - .ao_bits = 16, - .ao_scan_speed = 10000, - .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, - .ao_range_table = &ao_ranges_64xx, - .ao_range_code = ao_range_code_64xx, - .ai_fifo = &ai_fifo_64xx, - .has_8255 = 1, - }, - { - .name = "pci-das6402/12", /* XXX check */ - .device_id = 0x1e, - .ai_se_chans = 64, - .ai_bits = 12, - .ai_speed = 5000, - .ao_nchan = 2, - .ao_bits = 12, - .ao_scan_speed = 10000, - .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, - .ao_range_table = &ao_ranges_64xx, - .ao_range_code = ao_range_code_64xx, - .ai_fifo = &ai_fifo_64xx, - .has_8255 = 1, - }, - { - .name = "pci-das64/m1/16", - .device_id = 0x35, - .ai_se_chans = 64, - .ai_bits = 16, - .ai_speed = 1000, - .ao_nchan = 2, - .ao_bits = 16, - .ao_scan_speed = 10000, - .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, - .ao_range_table = &ao_ranges_64xx, - .ao_range_code = ao_range_code_64xx, - .ai_fifo = &ai_fifo_64xx, - .has_8255 = 1, - }, - { - .name = "pci-das64/m2/16", - .device_id = 0x36, - .ai_se_chans = 64, - .ai_bits = 16, - .ai_speed = 500, - .ao_nchan = 2, - .ao_bits = 16, - .ao_scan_speed = 10000, - .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, - .ao_range_table = &ao_ranges_64xx, - .ao_range_code = ao_range_code_64xx, - .ai_fifo = &ai_fifo_64xx, - .has_8255 = 1, - }, - { - .name = "pci-das64/m3/16", - .device_id = 0x37, - .ai_se_chans = 64, - .ai_bits = 16, - .ai_speed = 333, - .ao_nchan = 2, - .ao_bits = 16, - .ao_scan_speed = 10000, - .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, - .ao_range_table = &ao_ranges_64xx, - .ao_range_code = ao_range_code_64xx, - .ai_fifo = &ai_fifo_64xx, - .has_8255 = 1, - }, - { - .name = "pci-das6013", - .device_id = 0x78, - .ai_se_chans = 16, - .ai_bits = 16, - .ai_speed = 5000, - .ao_nchan = 0, - .ao_bits = 16, - .layout = LAYOUT_60XX, - .ai_range_table = &ai_ranges_60xx, - .ao_range_table = &ao_ranges_60xx, - .ao_range_code = ao_range_code_60xx, - .ai_fifo = &ai_fifo_60xx, - .has_8255 = 0, - }, - { - .name = "pci-das6014", - .device_id = 0x79, - .ai_se_chans = 16, - .ai_bits = 16, - .ai_speed = 5000, - .ao_nchan = 2, - .ao_bits = 16, - .ao_scan_speed = 100000, - .layout = LAYOUT_60XX, - .ai_range_table = &ai_ranges_60xx, - .ao_range_table = &ao_ranges_60xx, - .ao_range_code = ao_range_code_60xx, - .ai_fifo = &ai_fifo_60xx, - .has_8255 = 0, - }, - { - .name = "pci-das6023", - .device_id = 0x5d, - .ai_se_chans = 16, - .ai_bits = 12, - .ai_speed = 5000, - .ao_nchan = 0, - .ao_scan_speed = 100000, - .layout = LAYOUT_60XX, - .ai_range_table = &ai_ranges_60xx, - .ao_range_table = &ao_ranges_60xx, - .ao_range_code = ao_range_code_60xx, - .ai_fifo = &ai_fifo_60xx, - .has_8255 = 1, - }, - { - .name = "pci-das6025", - .device_id = 0x5e, - .ai_se_chans = 16, - .ai_bits = 12, - .ai_speed = 5000, - .ao_nchan = 2, - .ao_bits = 12, - .ao_scan_speed = 100000, - .layout = LAYOUT_60XX, - .ai_range_table = &ai_ranges_60xx, - .ao_range_table = &ao_ranges_60xx, - .ao_range_code = ao_range_code_60xx, - .ai_fifo = &ai_fifo_60xx, - .has_8255 = 1, - }, - { - .name = "pci-das6030", - .device_id = 0x5f, - .ai_se_chans = 16, - .ai_bits = 16, - .ai_speed = 10000, - .ao_nchan = 2, - .ao_bits = 16, - .ao_scan_speed = 10000, - .layout = LAYOUT_60XX, - .ai_range_table = &ai_ranges_6030, - .ao_range_table = &ao_ranges_6030, - .ao_range_code = ao_range_code_6030, - .ai_fifo = &ai_fifo_60xx, - .has_8255 = 0, - }, - { - .name = "pci-das6031", - .device_id = 0x60, - .ai_se_chans = 64, - .ai_bits = 16, - .ai_speed = 10000, - .ao_nchan = 2, - .ao_bits = 16, - .ao_scan_speed = 10000, - .layout = LAYOUT_60XX, - .ai_range_table = &ai_ranges_6030, - .ao_range_table = &ao_ranges_6030, - .ao_range_code = ao_range_code_6030, - .ai_fifo = &ai_fifo_60xx, - .has_8255 = 0, - }, - { - .name = "pci-das6032", - .device_id = 0x61, - .ai_se_chans = 16, - .ai_bits = 16, - .ai_speed = 10000, - .ao_nchan = 0, - .layout = LAYOUT_60XX, - .ai_range_table = &ai_ranges_6030, - .ai_fifo = &ai_fifo_60xx, - .has_8255 = 0, - }, - { - .name = "pci-das6033", - .device_id = 0x62, - .ai_se_chans = 64, - .ai_bits = 16, - .ai_speed = 10000, - .ao_nchan = 0, - .layout = LAYOUT_60XX, - .ai_range_table = &ai_ranges_6030, - .ai_fifo = &ai_fifo_60xx, - .has_8255 = 0, - }, - { - .name = "pci-das6034", - .device_id = 0x63, - .ai_se_chans = 16, - .ai_bits = 16, - .ai_speed = 5000, - .ao_nchan = 0, - .ao_scan_speed = 0, - .layout = LAYOUT_60XX, - .ai_range_table = &ai_ranges_60xx, - .ai_fifo = &ai_fifo_60xx, - .has_8255 = 0, - }, - { - .name = "pci-das6035", - .device_id = 0x64, - .ai_se_chans = 16, - .ai_bits = 16, - .ai_speed = 5000, - .ao_nchan = 2, - .ao_bits = 12, - .ao_scan_speed = 100000, - .layout = LAYOUT_60XX, - .ai_range_table = &ai_ranges_60xx, - .ao_range_table = &ao_ranges_60xx, - .ao_range_code = ao_range_code_60xx, - .ai_fifo = &ai_fifo_60xx, - .has_8255 = 0, - }, - { - .name = "pci-das6036", - .device_id = 0x6f, - .ai_se_chans = 16, - .ai_bits = 16, - .ai_speed = 5000, - .ao_nchan = 2, - .ao_bits = 16, - .ao_scan_speed = 100000, - .layout = LAYOUT_60XX, - .ai_range_table = &ai_ranges_60xx, - .ao_range_table = &ao_ranges_60xx, - .ao_range_code = ao_range_code_60xx, - .ai_fifo = &ai_fifo_60xx, - .has_8255 = 0, - }, - { - .name = "pci-das6040", - .device_id = 0x65, - .ai_se_chans = 16, - .ai_bits = 12, - .ai_speed = 2000, - .ao_nchan = 2, - .ao_bits = 12, - .ao_scan_speed = 1000, - .layout = LAYOUT_60XX, - .ai_range_table = &ai_ranges_6052, - .ao_range_table = &ao_ranges_6030, - .ao_range_code = ao_range_code_6030, - .ai_fifo = &ai_fifo_60xx, - .has_8255 = 0, - }, - { - .name = "pci-das6052", - .device_id = 0x66, - .ai_se_chans = 16, - .ai_bits = 16, - .ai_speed = 3333, - .ao_nchan = 2, - .ao_bits = 16, - .ao_scan_speed = 3333, - .layout = LAYOUT_60XX, - .ai_range_table = &ai_ranges_6052, - .ao_range_table = &ao_ranges_6030, - .ao_range_code = ao_range_code_6030, - .ai_fifo = &ai_fifo_60xx, - .has_8255 = 0, - }, - { - .name = "pci-das6070", - .device_id = 0x67, - .ai_se_chans = 16, - .ai_bits = 12, - .ai_speed = 800, - .ao_nchan = 2, - .ao_bits = 12, - .ao_scan_speed = 1000, - .layout = LAYOUT_60XX, - .ai_range_table = &ai_ranges_6052, - .ao_range_table = &ao_ranges_6030, - .ao_range_code = ao_range_code_6030, - .ai_fifo = &ai_fifo_60xx, - .has_8255 = 0, - }, - { - .name = "pci-das6071", - .device_id = 0x68, - .ai_se_chans = 64, - .ai_bits = 12, - .ai_speed = 800, - .ao_nchan = 2, - .ao_bits = 12, - .ao_scan_speed = 1000, - .layout = LAYOUT_60XX, - .ai_range_table = &ai_ranges_6052, - .ao_range_table = &ao_ranges_6030, - .ao_range_code = ao_range_code_6030, - .ai_fifo = &ai_fifo_60xx, - .has_8255 = 0, - }, - { - .name = "pci-das4020/12", - .device_id = 0x52, - .ai_se_chans = 4, - .ai_bits = 12, - .ai_speed = 50, - .ao_bits = 12, - .ao_nchan = 2, - .ao_scan_speed = 0, /* no hardware pacing on ao */ - .layout = LAYOUT_4020, - .ai_range_table = &ai_ranges_4020, - .ao_range_table = &ao_ranges_4020, - .ao_range_code = ao_range_code_4020, - .ai_fifo = &ai_fifo_4020, - .has_8255 = 1, - }, + [BOARD_PCIDAS6402_16] = { + .name = "pci-das6402/16", + .ai_se_chans = 64, + .ai_bits = 16, + .ai_speed = 5000, + .ao_nchan = 2, + .ao_bits = 16, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, + .has_8255 = 1, + }, + [BOARD_PCIDAS6402_12] = { + .name = "pci-das6402/12", /* XXX check */ + .ai_se_chans = 64, + .ai_bits = 12, + .ai_speed = 5000, + .ao_nchan = 2, + .ao_bits = 12, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, + .has_8255 = 1, + }, + [BOARD_PCIDAS64_M1_16] = { + .name = "pci-das64/m1/16", + .ai_se_chans = 64, + .ai_bits = 16, + .ai_speed = 1000, + .ao_nchan = 2, + .ao_bits = 16, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, + .has_8255 = 1, + }, + [BOARD_PCIDAS64_M2_16] = { + .name = "pci-das64/m2/16", + .ai_se_chans = 64, + .ai_bits = 16, + .ai_speed = 500, + .ao_nchan = 2, + .ao_bits = 16, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, + .has_8255 = 1, + }, + [BOARD_PCIDAS64_M3_16] = { + .name = "pci-das64/m3/16", + .ai_se_chans = 64, + .ai_bits = 16, + .ai_speed = 333, + .ao_nchan = 2, + .ao_bits = 16, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, + .has_8255 = 1, + }, + [BOARD_PCIDAS6013] = { + .name = "pci-das6013", + .ai_se_chans = 16, + .ai_bits = 16, + .ai_speed = 5000, + .ao_nchan = 0, + .ao_bits = 16, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, + [BOARD_PCIDAS6014] = { + .name = "pci-das6014", + .ai_se_chans = 16, + .ai_bits = 16, + .ai_speed = 5000, + .ao_nchan = 2, + .ao_bits = 16, + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, + [BOARD_PCIDAS6023] = { + .name = "pci-das6023", + .ai_se_chans = 16, + .ai_bits = 12, + .ai_speed = 5000, + .ao_nchan = 0, + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 1, + }, + [BOARD_PCIDAS6025] = { + .name = "pci-das6025", + .ai_se_chans = 16, + .ai_bits = 12, + .ai_speed = 5000, + .ao_nchan = 2, + .ao_bits = 12, + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 1, + }, + [BOARD_PCIDAS6030] = { + .name = "pci-das6030", + .ai_se_chans = 16, + .ai_bits = 16, + .ai_speed = 10000, + .ao_nchan = 2, + .ao_bits = 16, + .ao_scan_speed = 10000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6030, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, + [BOARD_PCIDAS6031] = { + .name = "pci-das6031", + .ai_se_chans = 64, + .ai_bits = 16, + .ai_speed = 10000, + .ao_nchan = 2, + .ao_bits = 16, + .ao_scan_speed = 10000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6030, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, + [BOARD_PCIDAS6032] = { + .name = "pci-das6032", + .ai_se_chans = 16, + .ai_bits = 16, + .ai_speed = 10000, + .ao_nchan = 0, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6030, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, + [BOARD_PCIDAS6033] = { + .name = "pci-das6033", + .ai_se_chans = 64, + .ai_bits = 16, + .ai_speed = 10000, + .ao_nchan = 0, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6030, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, + [BOARD_PCIDAS6034] = { + .name = "pci-das6034", + .ai_se_chans = 16, + .ai_bits = 16, + .ai_speed = 5000, + .ao_nchan = 0, + .ao_scan_speed = 0, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, + [BOARD_PCIDAS6035] = { + .name = "pci-das6035", + .ai_se_chans = 16, + .ai_bits = 16, + .ai_speed = 5000, + .ao_nchan = 2, + .ao_bits = 12, + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, + [BOARD_PCIDAS6036] = { + .name = "pci-das6036", + .ai_se_chans = 16, + .ai_bits = 16, + .ai_speed = 5000, + .ao_nchan = 2, + .ao_bits = 16, + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, + [BOARD_PCIDAS6040] = { + .name = "pci-das6040", + .ai_se_chans = 16, + .ai_bits = 12, + .ai_speed = 2000, + .ao_nchan = 2, + .ao_bits = 12, + .ao_scan_speed = 1000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6052, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, + [BOARD_PCIDAS6052] = { + .name = "pci-das6052", + .ai_se_chans = 16, + .ai_bits = 16, + .ai_speed = 3333, + .ao_nchan = 2, + .ao_bits = 16, + .ao_scan_speed = 3333, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6052, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, + [BOARD_PCIDAS6070] = { + .name = "pci-das6070", + .ai_se_chans = 16, + .ai_bits = 12, + .ai_speed = 800, + .ao_nchan = 2, + .ao_bits = 12, + .ao_scan_speed = 1000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6052, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, + [BOARD_PCIDAS6071] = { + .name = "pci-das6071", + .ai_se_chans = 64, + .ai_bits = 12, + .ai_speed = 800, + .ao_nchan = 2, + .ao_bits = 12, + .ao_scan_speed = 1000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6052, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, + [BOARD_PCIDAS4020_12] = { + .name = "pci-das4020/12", + .ai_se_chans = 4, + .ai_bits = 12, + .ai_speed = 50, + .ao_bits = 12, + .ao_nchan = 2, + .ao_scan_speed = 0, /* no hardware pacing on ao */ + .layout = LAYOUT_4020, + .ai_range_table = &ai_ranges_4020, + .ao_range_table = &ao_ranges_4020, + .ao_range_code = ao_range_code_4020, + .ai_fifo = &ai_fifo_4020, + .has_8255 = 1, + }, #if 0 - { - .name = "pci-das6402/16/jr", - .device_id = 0 /* XXX, */ - .ai_se_chans = 64, - .ai_bits = 16, - .ai_speed = 5000, - .ao_nchan = 0, - .ao_scan_speed = 10000, - .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, - .ai_fifo = ai_fifo_64xx, - .has_8255 = 1, - }, - { - .name = "pci-das64/m1/16/jr", - .device_id = 0 /* XXX, */ - .ai_se_chans = 64, - .ai_bits = 16, - .ai_speed = 1000, - .ao_nchan = 0, - .ao_scan_speed = 10000, - .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, - .ai_fifo = ai_fifo_64xx, - .has_8255 = 1, - }, - { - .name = "pci-das64/m2/16/jr", - .device_id = 0 /* XXX, */ - .ai_se_chans = 64, - .ai_bits = 16, - .ai_speed = 500, - .ao_nchan = 0, - .ao_scan_speed = 10000, - .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, - .ai_fifo = ai_fifo_64xx, - .has_8255 = 1, - }, - { - .name = "pci-das64/m3/16/jr", - .device_id = 0 /* XXX, */ - .ai_se_chans = 64, - .ai_bits = 16, - .ai_speed = 333, - .ao_nchan = 0, - .ao_scan_speed = 10000, - .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, - .ai_fifo = ai_fifo_64xx, - .has_8255 = 1, - }, - { - .name = "pci-das64/m1/14", - .device_id = 0, /* XXX */ - .ai_se_chans = 64, - .ai_bits = 14, - .ai_speed = 1000, - .ao_nchan = 2, - .ao_scan_speed = 10000, - .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, - .ai_fifo = ai_fifo_64xx, - .has_8255 = 1, - }, - { - .name = "pci-das64/m2/14", - .device_id = 0, /* XXX */ - .ai_se_chans = 64, - .ai_bits = 14, - .ai_speed = 500, - .ao_nchan = 2, - .ao_scan_speed = 10000, - .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, - .ai_fifo = ai_fifo_64xx, - .has_8255 = 1, - }, - { - .name = "pci-das64/m3/14", - .device_id = 0, /* XXX */ - .ai_se_chans = 64, - .ai_bits = 14, - .ai_speed = 333, - .ao_nchan = 2, - .ao_scan_speed = 10000, - .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, - .ai_fifo = ai_fifo_64xx, - .has_8255 = 1, - }, + /* + * The device id for these boards is unknown + */ + + [BOARD_PCIDAS6402_16_JR] = { + .name = "pci-das6402/16/jr", + .ai_se_chans = 64, + .ai_bits = 16, + .ai_speed = 5000, + .ao_nchan = 0, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, + [BOARD_PCIDAS64_M1_16_JR] = { + .name = "pci-das64/m1/16/jr", + .ai_se_chans = 64, + .ai_bits = 16, + .ai_speed = 1000, + .ao_nchan = 0, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, + [BOARD_PCIDAS64_M2_16_JR] = { + .name = "pci-das64/m2/16/jr", + .ai_se_chans = 64, + .ai_bits = 16, + .ai_speed = 500, + .ao_nchan = 0, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, + [BOARD_PCIDAS64_M3_16_JR] = { + .name = "pci-das64/m3/16/jr", + .ai_se_chans = 64, + .ai_bits = 16, + .ai_speed = 333, + .ao_nchan = 0, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, + [BOARD_PCIDAS64_M1_14] = { + .name = "pci-das64/m1/14", + .ai_se_chans = 64, + .ai_bits = 14, + .ai_speed = 1000, + .ao_nchan = 2, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, + [BOARD_PCIDAS64_M2_14] = { + .name = "pci-das64/m2/14", + .ai_se_chans = 64, + .ai_bits = 14, + .ai_speed = 500, + .ao_nchan = 2, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, + [BOARD_PCIDAS64_M3_14] = { + .name = "pci-das64/m3/14", + .ai_se_chans = 64, + .ai_bits = 14, + .ai_speed = 333, + .ao_nchan = 2, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, #endif }; @@ -1088,7 +1080,6 @@ struct ext_clock_info { /* this structure is for data unique to this hardware driver. */ struct pcidas64_private { /* base addresses (physical) */ - resource_size_t plx9080_phys_iobase; resource_size_t main_phys_iobase; resource_size_t dio_counter_phys_iobase; /* base addresses (ioremapped) */ @@ -1523,7 +1514,7 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) struct pcidas64_private *devpriv = dev->private; int i; - /* alocate pci dma buffers */ + /* allocate pci dma buffers */ for (i = 0; i < ai_dma_ring_count(thisboard); i++) { devpriv->ai_buffer[i] = pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE, @@ -3107,7 +3098,7 @@ static irqreturn_t handle_interrupt(int irq, void *d) /* an interrupt before all the postconfig stuff gets done could * cause a NULL dereference if we continue through the * interrupt handler */ - if (dev->attached == 0) { + if (!dev->attached) { DEBUG_PRINT("premature interrupt, ignoring\n"); return IRQ_HANDLED; } @@ -4033,68 +4024,40 @@ static int setup_subdevices(struct comedi_device *dev) return 0; } -static const struct pcidas64_board -*cb_pcidas64_find_pci_board(struct pci_dev *pcidev) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(pcidas64_boards); i++) - if (pcidev->device == pcidas64_boards[i].device_id) - return &pcidas64_boards[i]; - return NULL; -} - static int auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { - const struct pcidas64_board *thisboard; - struct pcidas64_private *devpriv; struct pci_dev *pcidev = comedi_to_pci_dev(dev); + const struct pcidas64_board *thisboard = NULL; + struct pcidas64_private *devpriv; uint32_t local_range, local_decode; int retval; - dev->board_ptr = cb_pcidas64_find_pci_board(pcidev); - if (!dev->board_ptr) { - dev_err(dev->class_dev, - "cb_pcidas64: does not support pci %s\n", - pci_name(pcidev)); - return -EINVAL; - } - thisboard = comedi_board(dev); + if (context < ARRAY_SIZE(pcidas64_boards)) + thisboard = &pcidas64_boards[context]; + if (!thisboard) + return -ENODEV; + dev->board_ptr = thisboard; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - if (comedi_pci_enable(pcidev, dev->driver->driver_name)) { - dev_warn(dev->class_dev, - "failed to enable PCI device and request regions\n"); - return -EIO; - } + retval = comedi_pci_enable(dev); + if (retval) + return retval; pci_set_master(pcidev); /* Initialize dev->board_name */ dev->board_name = thisboard->name; - dev->iobase = pci_resource_start(pcidev, MAIN_BADDRINDEX); - - devpriv->plx9080_phys_iobase = - pci_resource_start(pcidev, PLX9080_BADDRINDEX); - devpriv->main_phys_iobase = dev->iobase; - devpriv->dio_counter_phys_iobase = - pci_resource_start(pcidev, DIO_COUNTER_BADDRINDEX); - - /* remap, won't work with 2.0 kernels but who cares */ - devpriv->plx9080_iobase = - ioremap(devpriv->plx9080_phys_iobase, - pci_resource_len(pcidev, PLX9080_BADDRINDEX)); - devpriv->main_iobase = - ioremap(devpriv->main_phys_iobase, - pci_resource_len(pcidev, MAIN_BADDRINDEX)); - devpriv->dio_counter_iobase = - ioremap(devpriv->dio_counter_phys_iobase, - pci_resource_len(pcidev, DIO_COUNTER_BADDRINDEX)); + devpriv->main_phys_iobase = pci_resource_start(pcidev, 2); + devpriv->dio_counter_phys_iobase = pci_resource_start(pcidev, 3); + + 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); if (!devpriv->plx9080_iobase || !devpriv->main_iobase || !devpriv->dio_counter_iobase) { @@ -4200,12 +4163,8 @@ static void detach(struct comedi_device *dev) devpriv->ao_dma_desc_bus_addr); } } - if (dev->subdevices) - subdev_8255_cleanup(dev, &dev->subdevices[4]); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } + comedi_spriv_free(dev, 4); + comedi_pci_disable(dev); } static struct comedi_driver cb_pcidas64_driver = { @@ -4216,31 +4175,34 @@ static struct comedi_driver cb_pcidas64_driver = { }; static int cb_pcidas64_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &cb_pcidas64_driver); + return comedi_pci_auto_config(dev, &cb_pcidas64_driver, + id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(cb_pcidas64_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001d) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001e) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0035) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0036) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0037) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0052) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x005d) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x005e) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x005f) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0061) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0062) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0063) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0064) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0066) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0067) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0068) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x006f) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0078) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0079) }, + { PCI_VDEVICE(CB, 0x001d), BOARD_PCIDAS6402_16 }, + { PCI_VDEVICE(CB, 0x001e), BOARD_PCIDAS6402_12 }, + { PCI_VDEVICE(CB, 0x0035), BOARD_PCIDAS64_M1_16 }, + { PCI_VDEVICE(CB, 0x0036), BOARD_PCIDAS64_M2_16 }, + { PCI_VDEVICE(CB, 0x0037), BOARD_PCIDAS64_M3_16 }, + { PCI_VDEVICE(CB, 0x0052), BOARD_PCIDAS4020_12 }, + { PCI_VDEVICE(CB, 0x005d), BOARD_PCIDAS6023 }, + { PCI_VDEVICE(CB, 0x005e), BOARD_PCIDAS6025 }, + { PCI_VDEVICE(CB, 0x005f), BOARD_PCIDAS6030 }, + { PCI_VDEVICE(CB, 0x0060), BOARD_PCIDAS6031 }, + { PCI_VDEVICE(CB, 0x0061), BOARD_PCIDAS6032 }, + { PCI_VDEVICE(CB, 0x0062), BOARD_PCIDAS6033 }, + { PCI_VDEVICE(CB, 0x0063), BOARD_PCIDAS6034 }, + { PCI_VDEVICE(CB, 0x0064), BOARD_PCIDAS6035 }, + { PCI_VDEVICE(CB, 0x0065), BOARD_PCIDAS6040 }, + { PCI_VDEVICE(CB, 0x0066), BOARD_PCIDAS6052 }, + { PCI_VDEVICE(CB, 0x0067), BOARD_PCIDAS6070 }, + { PCI_VDEVICE(CB, 0x0068), BOARD_PCIDAS6071 }, + { PCI_VDEVICE(CB, 0x006f), BOARD_PCIDAS6036 }, + { PCI_VDEVICE(CB, 0x0078), BOARD_PCIDAS6013 }, + { PCI_VDEVICE(CB, 0x0079), BOARD_PCIDAS6014 }, { 0 } }; MODULE_DEVICE_TABLE(pci, cb_pcidas64_pci_table); diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index e2cadc72845..f9b459888b8 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -48,16 +48,6 @@ #include "comedi_fc.h" #include "8255.h" -/* - * ComputerBoards PCI Device ID's supported by this driver - */ -#define PCI_DEVICE_ID_DDA02_12 0x0020 -#define PCI_DEVICE_ID_DDA04_12 0x0021 -#define PCI_DEVICE_ID_DDA08_12 0x0022 -#define PCI_DEVICE_ID_DDA02_16 0x0023 -#define PCI_DEVICE_ID_DDA04_16 0x0024 -#define PCI_DEVICE_ID_DDA08_16 0x0025 - #define EEPROM_SIZE 128 /* number of entries in eeprom */ /* maximum number of ao channels for supported boards */ #define MAX_AO_CHANNELS 8 @@ -118,42 +108,49 @@ static const struct comedi_lrange cb_pcidda_ranges = { } }; +enum cb_pcidda_boardid { + BOARD_DDA02_12, + BOARD_DDA04_12, + BOARD_DDA08_12, + BOARD_DDA02_16, + BOARD_DDA04_16, + BOARD_DDA08_16, +}; + struct cb_pcidda_board { const char *name; - unsigned short device_id; int ao_chans; int ao_bits; }; static const struct cb_pcidda_board cb_pcidda_boards[] = { - { + [BOARD_DDA02_12] = { .name = "pci-dda02/12", - .device_id = PCI_DEVICE_ID_DDA02_12, .ao_chans = 2, .ao_bits = 12, - }, { + }, + [BOARD_DDA04_12] = { .name = "pci-dda04/12", - .device_id = PCI_DEVICE_ID_DDA04_12, .ao_chans = 4, .ao_bits = 12, - }, { + }, + [BOARD_DDA08_12] = { .name = "pci-dda08/12", - .device_id = PCI_DEVICE_ID_DDA08_12, .ao_chans = 8, .ao_bits = 12, - }, { + }, + [BOARD_DDA02_16] = { .name = "pci-dda02/16", - .device_id = PCI_DEVICE_ID_DDA02_16, .ao_chans = 2, .ao_bits = 16, - }, { + }, + [BOARD_DDA04_16] = { .name = "pci-dda04/16", - .device_id = PCI_DEVICE_ID_DDA04_16, .ao_chans = 4, .ao_bits = 16, - }, { + }, + [BOARD_DDA08_16] = { .name = "pci-dda08/16", - .device_id = PCI_DEVICE_ID_DDA08_16, .ao_chans = 8, .ao_bits = 16, }, @@ -337,32 +334,19 @@ static int cb_pcidda_ao_insn_write(struct comedi_device *dev, return insn->n; } -static const void *cb_pcidda_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct cb_pcidda_board *thisboard; - int i; - - for (i = 0; i < ARRAY_SIZE(cb_pcidda_boards); i++) { - thisboard = &cb_pcidda_boards[i]; - if (thisboard->device_id != pcidev->device) - return thisboard; - } - return NULL; -} - static int cb_pcidda_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct cb_pcidda_board *thisboard; + const struct cb_pcidda_board *thisboard = NULL; struct cb_pcidda_private *devpriv; struct comedi_subdevice *s; unsigned long iobase_8255; int i; int ret; - thisboard = cb_pcidda_find_boardinfo(dev, pcidev); + if (context < ARRAY_SIZE(cb_pcidda_boards)) + thisboard = &cb_pcidda_boards[context]; if (!thisboard) return -ENODEV; dev->board_ptr = thisboard; @@ -373,7 +357,7 @@ static int cb_pcidda_auto_attach(struct comedi_device *dev, return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pcidev, 3); @@ -415,16 +399,9 @@ static int cb_pcidda_auto_attach(struct comedi_device *dev, static void cb_pcidda_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - - if (dev->subdevices) { - subdev_8255_cleanup(dev, &dev->subdevices[1]); - subdev_8255_cleanup(dev, &dev->subdevices[2]); - } - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } + comedi_spriv_free(dev, 1); + comedi_spriv_free(dev, 2); + comedi_pci_disable(dev); } static struct comedi_driver cb_pcidda_driver = { @@ -435,18 +412,19 @@ static struct comedi_driver cb_pcidda_driver = { }; static int cb_pcidda_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &cb_pcidda_driver); + return comedi_pci_auto_config(dev, &cb_pcidda_driver, + id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(cb_pcidda_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA02_12) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA04_12) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA08_12) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA02_16) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA04_16) }, - { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA08_16) }, + { PCI_VDEVICE(CB, 0x0020), BOARD_DDA02_12 }, + { PCI_VDEVICE(CB, 0x0021), BOARD_DDA04_12 }, + { PCI_VDEVICE(CB, 0x0022), BOARD_DDA08_12 }, + { PCI_VDEVICE(CB, 0x0023), BOARD_DDA02_16 }, + { PCI_VDEVICE(CB, 0x0024), BOARD_DDA04_16 }, + { PCI_VDEVICE(CB, 0x0025), BOARD_DDA08_16 }, { 0 } }; MODULE_DEVICE_TABLE(pci, cb_pcidda_pci_table); diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index aae063ca85a..29813c9d4a2 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -215,14 +215,12 @@ static int cb_pcimdas_auto_attach(struct comedi_device *dev, unsigned long iobase_8255; int ret; - dev->board_name = dev->driver->driver_name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; @@ -277,14 +275,9 @@ static int cb_pcimdas_auto_attach(struct comedi_device *dev, static void cb_pcimdas_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (dev->irq) free_irq(dev->irq, dev); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } + comedi_pci_disable(dev); } static struct comedi_driver cb_pcimdas_driver = { @@ -295,9 +288,10 @@ static struct comedi_driver cb_pcimdas_driver = { }; static int cb_pcimdas_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &cb_pcimdas_driver); + return comedi_pci_auto_config(dev, &cb_pcimdas_driver, + id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(cb_pcimdas_pci_table) = { diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c index 63cfbaf3a3f..88f03ae6f3e 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdda.c +++ b/drivers/staging/comedi/drivers/cb_pcimdda.c @@ -161,14 +161,12 @@ static int cb_pcimdda_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - dev->board_name = dev->driver->driver_name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pcidev, 3); @@ -201,14 +199,8 @@ static int cb_pcimdda_auto_attach(struct comedi_device *dev, static void cb_pcimdda_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - - if (dev->subdevices) - subdev_8255_cleanup(dev, &dev->subdevices[1]); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } + comedi_spriv_free(dev, 1); + comedi_pci_disable(dev); } static struct comedi_driver cb_pcimdda_driver = { @@ -219,9 +211,10 @@ static struct comedi_driver cb_pcimdda_driver = { }; static int cb_pcimdda_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &cb_pcimdda_driver); + return comedi_pci_auto_config(dev, &cb_pcimdda_driver, + id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(cb_pcimdda_pci_table) = { diff --git a/drivers/staging/comedi/drivers/comedi_fc.c b/drivers/staging/comedi/drivers/comedi_fc.c index 83728298eef..37dc79637d2 100644 --- a/drivers/staging/comedi/drivers/comedi_fc.c +++ b/drivers/staging/comedi/drivers/comedi_fc.c @@ -65,7 +65,7 @@ unsigned int cfc_write_array_to_buffer(struct comedi_subdevice *subd, return num_bytes; } -EXPORT_SYMBOL(cfc_write_array_to_buffer); +EXPORT_SYMBOL_GPL(cfc_write_array_to_buffer); unsigned int cfc_read_array_from_buffer(struct comedi_subdevice *subd, void *data, unsigned int num_bytes) @@ -83,7 +83,7 @@ unsigned int cfc_read_array_from_buffer(struct comedi_subdevice *subd, return num_bytes; } -EXPORT_SYMBOL(cfc_read_array_from_buffer); +EXPORT_SYMBOL_GPL(cfc_read_array_from_buffer); unsigned int cfc_handle_events(struct comedi_device *dev, struct comedi_subdevice *subd) @@ -100,7 +100,7 @@ unsigned int cfc_handle_events(struct comedi_device *dev, return events; } -EXPORT_SYMBOL(cfc_handle_events); +EXPORT_SYMBOL_GPL(cfc_handle_events); MODULE_AUTHOR("Frank Mori Hess <fmhess@users.sourceforge.net>"); MODULE_DESCRIPTION("Shared functions for Comedi low-level drivers"); diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index 76d59dcbea0..3e061cc9b48 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -261,19 +261,13 @@ static int parport_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct parport_private *devpriv; - int ret; - unsigned int irq; - unsigned long iobase; struct comedi_subdevice *s; + unsigned int irq; + int ret; - dev->board_name = dev->driver->driver_name; - - iobase = it->options[0]; - if (!request_region(iobase, PARPORT_SIZE, dev->board_name)) { - dev_err(dev->class_dev, "I/O port conflict\n"); - return -EIO; - } - dev->iobase = iobase; + ret = comedi_request_region(dev, it->options[0], PARPORT_SIZE); + if (ret) + return ret; irq = it->options[1]; if (irq) { @@ -341,25 +335,14 @@ static int parport_attach(struct comedi_device *dev, devpriv->c_data = 0; outb(devpriv->c_data, dev->iobase + PARPORT_C); - dev_info(dev->class_dev, "%s: iobase=0x%04lx, irq %sabled", - dev->board_name, dev->iobase, dev->irq ? "en" : "dis"); - return 0; } -static void parport_detach(struct comedi_device *dev) -{ - if (dev->iobase) - release_region(dev->iobase, PARPORT_SIZE); - if (dev->irq) - free_irq(dev->irq, dev); -} - static struct comedi_driver parport_driver = { .driver_name = "comedi_parport", .module = THIS_MODULE, .attach = parport_attach, - .detach = parport_detach, + .detach = comedi_legacy_detach, }; module_comedi_driver(parport_driver); diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index 270fea5c6b5..c1d8e86f53a 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -384,8 +384,6 @@ static int waveform_attach(struct comedi_device *dev, int i; int ret; - dev->board_name = dev->driver->driver_name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c index 182dea669ef..f2230bfd4eb 100644 --- a/drivers/staging/comedi/drivers/contec_pci_dio.c +++ b/drivers/staging/comedi/drivers/contec_pci_dio.c @@ -77,9 +77,7 @@ static int contec_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - dev->board_name = dev->driver->driver_name; - - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pcidev, 0); @@ -109,27 +107,18 @@ static int contec_auto_attach(struct comedi_device *dev, return 0; } -static void contec_detach(struct comedi_device *dev) -{ - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } -} - static struct comedi_driver contec_pci_dio_driver = { .driver_name = "contec_pci_dio", .module = THIS_MODULE, .auto_attach = contec_auto_attach, - .detach = contec_detach, + .detach = comedi_pci_disable, }; static int contec_pci_dio_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &contec_pci_dio_driver); + return comedi_pci_auto_config(dev, &contec_pci_dio_driver, + id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(contec_pci_dio_pci_table) = { diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index 50b450f09c6..b87f95c3e17 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -462,9 +462,9 @@ static void daqboard2000_resetLocalBus(struct comedi_device *dev) struct daqboard2000_private *devpriv = dev->private; writel(DAQBOARD2000_SECRLocalBusHi, devpriv->plx + 0x6c); - udelay(10000); + mdelay(10); writel(DAQBOARD2000_SECRLocalBusLo, devpriv->plx + 0x6c); - udelay(10000); + mdelay(10); } static void daqboard2000_reloadPLX(struct comedi_device *dev) @@ -472,11 +472,11 @@ static void daqboard2000_reloadPLX(struct comedi_device *dev) struct daqboard2000_private *devpriv = dev->private; writel(DAQBOARD2000_SECRReloadLo, devpriv->plx + 0x6c); - udelay(10000); + mdelay(10); writel(DAQBOARD2000_SECRReloadHi, devpriv->plx + 0x6c); - udelay(10000); + mdelay(10); writel(DAQBOARD2000_SECRReloadLo, devpriv->plx + 0x6c); - udelay(10000); + mdelay(10); } static void daqboard2000_pulseProgPin(struct comedi_device *dev) @@ -484,9 +484,9 @@ static void daqboard2000_pulseProgPin(struct comedi_device *dev) struct daqboard2000_private *devpriv = dev->private; writel(DAQBOARD2000_SECRProgPinHi, devpriv->plx + 0x6c); - udelay(10000); + mdelay(10); writel(DAQBOARD2000_SECRProgPinLo, devpriv->plx + 0x6c); - udelay(10000); /* Not in the original code, but I like symmetry... */ + mdelay(10); /* Not in the original code, but I like symmetry... */ } static int daqboard2000_pollCPLD(struct comedi_device *dev, int mask) @@ -709,15 +709,12 @@ static int daqboard2000_auto_attach(struct comedi_device *dev, return -ENOMEM; dev->private = devpriv; - result = comedi_pci_enable(pcidev, dev->driver->driver_name); - if (result < 0) + result = comedi_pci_enable(dev); + if (result) return result; - dev->iobase = 1; /* the "detach" needs this */ - devpriv->plx = ioremap(pci_resource_start(pcidev, 0), - pci_resource_len(pcidev, 0)); - devpriv->daq = ioremap(pci_resource_start(pcidev, 2), - pci_resource_len(pcidev, 2)); + devpriv->plx = pci_ioremap_bar(pcidev, 0); + devpriv->daq = pci_ioremap_bar(pcidev, 2); if (!devpriv->plx || !devpriv->daq) return -ENOMEM; @@ -767,11 +764,9 @@ static int daqboard2000_auto_attach(struct comedi_device *dev, static void daqboard2000_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct daqboard2000_private *devpriv = dev->private; - if (dev->subdevices) - subdev_8255_cleanup(dev, &dev->subdevices[2]); + comedi_spriv_free(dev, 2); if (dev->irq) free_irq(dev->irq, dev); if (devpriv) { @@ -780,11 +775,7 @@ static void daqboard2000_detach(struct comedi_device *dev) if (devpriv->plx) iounmap(devpriv->plx); } - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - pci_dev_put(pcidev); - } + comedi_pci_disable(dev); } static struct comedi_driver daqboard2000_driver = { @@ -795,9 +786,10 @@ static struct comedi_driver daqboard2000_driver = { }; static int daqboard2000_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &daqboard2000_driver); + return comedi_pci_auto_config(dev, &daqboard2000_driver, + id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(daqboard2000_pci_table) = { diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 9823aa06787..ba12c1d605f 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -568,8 +568,7 @@ EXPORT_SYMBOL_GPL(das08_common_attach); void das08_common_detach(struct comedi_device *dev) { - if (dev->subdevices) - subdev_8255_cleanup(dev, &dev->subdevices[4]); + comedi_spriv_free(dev, 4); } EXPORT_SYMBOL_GPL(das08_common_detach); diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h index b102ad4918c..89bb8d6fdfc 100644 --- a/drivers/staging/comedi/drivers/das08.h +++ b/drivers/staging/comedi/drivers/das08.h @@ -32,7 +32,6 @@ enum das08_lrange { das08_pg_none, das08_bipolar5, das08_pgh, das08_pgl, struct das08_board_struct { const char *name; - unsigned int id; /* id for pci/pcmcia boards */ bool is_jr; /* true for 'JR' boards */ unsigned int ai_nbits; enum das08_lrange ai_pg; diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index cfeebe4d1dd..d9f3e92317d 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -59,7 +59,6 @@ Command support does not exist, but could be added for this board. static const struct das08_board_struct das08_cs_boards[] = { { .name = "pcm-das08", - .id = 0x0, /* XXX */ .ai_nbits = 12, .ai_pg = das08_bipolar5, .ai_encoding = das08_pcm_encode12, diff --git a/drivers/staging/comedi/drivers/das08_isa.c b/drivers/staging/comedi/drivers/das08_isa.c index f1207824716..f09f6966ed6 100644 --- a/drivers/staging/comedi/drivers/das08_isa.c +++ b/drivers/staging/comedi/drivers/das08_isa.c @@ -179,26 +179,24 @@ static int das08_isa_attach(struct comedi_device *dev, { const struct das08_board_struct *thisboard = comedi_board(dev); struct das08_private_struct *devpriv; + int ret; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - if (!request_region(it->options[0], thisboard->iosize, - thisboard->name)) - return -EIO; + ret = comedi_request_region(dev, it->options[0], thisboard->iosize); + if (ret) + return ret; - return das08_common_attach(dev, it->options[0]); + return das08_common_attach(dev, dev->iobase); } static void das08_isa_detach(struct comedi_device *dev) { - const struct das08_board_struct *thisboard = comedi_board(dev); - das08_common_detach(dev); - if (dev->iobase) - release_region(dev->iobase, thisboard->iosize); + comedi_legacy_detach(dev); } static struct comedi_driver das08_isa_driver = { diff --git a/drivers/staging/comedi/drivers/das08_pci.c b/drivers/staging/comedi/drivers/das08_pci.c index c405876ddcf..53fa943dd0b 100644 --- a/drivers/staging/comedi/drivers/das08_pci.c +++ b/drivers/staging/comedi/drivers/das08_pci.c @@ -46,7 +46,6 @@ static const struct das08_board_struct das08_pci_boards[] = { { .name = "pci-das08", - .id = PCI_DEVICE_ID_PCIDAS08, .ai_nbits = 12, .ai_pg = das08_bipolar5, .ai_encoding = das08_encode12, @@ -72,7 +71,7 @@ static int das08_pci_auto_attach(struct comedi_device *dev, /* The das08 driver needs the board_ptr */ dev->board_ptr = &das08_pci_boards[0]; - ret = comedi_pci_enable(pdev, dev->driver->driver_name); + ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pdev, 2); @@ -82,11 +81,8 @@ static int das08_pci_auto_attach(struct comedi_device *dev, static void das08_pci_detach(struct comedi_device *dev) { - struct pci_dev *pdev = comedi_to_pci_dev(dev); - das08_common_detach(dev); - if (dev->iobase) - comedi_pci_disable(pdev); + comedi_pci_disable(dev); } static struct comedi_driver das08_pci_comedi_driver = { @@ -97,9 +93,10 @@ static struct comedi_driver das08_pci_comedi_driver = { }; static int das08_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &das08_pci_comedi_driver); + return comedi_pci_auto_config(dev, &das08_pci_comedi_driver, + id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(das08_pci_table) = { diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index f238a1fbccb..762b5a6eac5 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -393,6 +393,8 @@ struct das16_private_struct { struct timer_list timer; /* for timed interrupt */ volatile short timer_running; volatile short timer_mode; /* true if using timer mode */ + + unsigned long extra_iobase; }; static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, @@ -876,7 +878,7 @@ static void das16_interrupt(struct comedi_device *dev) int num_bytes, residue; int buffer_index; - if (dev->attached == 0) { + if (!dev->attached) { comedi_error(dev, "premature interrupt"); return; } @@ -1079,13 +1081,11 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; int ret; unsigned int irq; - unsigned long iobase; unsigned int dma_chan; int timer_mode; unsigned long flags; struct comedi_krange *user_ai_range, *user_ao_range; - iobase = it->options[0]; #if 0 irq = it->options[1]; timer_mode = it->options[8]; @@ -1097,8 +1097,6 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (timer_mode) irq = 0; - printk(KERN_INFO "comedi%d: das16:", dev->minor); - /* check that clock setting is valid */ if (it->options[3]) { if (it->options[3] != 0 && @@ -1116,39 +1114,26 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->private = devpriv; if (board->size < 0x400) { - printk(" 0x%04lx-0x%04lx\n", iobase, iobase + board->size); - if (!request_region(iobase, board->size, "das16")) { - printk(KERN_ERR " I/O port conflict\n"); - return -EIO; - } + ret = comedi_request_region(dev, it->options[0], board->size); + if (ret) + return ret; } else { - printk(KERN_INFO " 0x%04lx-0x%04lx 0x%04lx-0x%04lx\n", - iobase, iobase + 0x0f, - iobase + 0x400, - iobase + 0x400 + (board->size & 0x3ff)); - if (!request_region(iobase, 0x10, "das16")) { - printk(KERN_ERR " I/O port conflict: 0x%04lx-0x%04lx\n", - iobase, iobase + 0x0f); - return -EIO; - } - if (!request_region(iobase + 0x400, board->size & 0x3ff, - "das16")) { - release_region(iobase, 0x10); - printk(KERN_ERR " I/O port conflict: 0x%04lx-0x%04lx\n", - iobase + 0x400, - iobase + 0x400 + (board->size & 0x3ff)); - return -EIO; - } + ret = comedi_request_region(dev, it->options[0], 0x10); + if (ret) + return ret; + /* Request an additional region for the 8255 */ + ret = __comedi_request_region(dev, dev->iobase + 0x400, + board->size & 0x3ff); + if (ret) + return ret; + devpriv->extra_iobase = dev->iobase + 0x400; } - dev->iobase = iobase; - /* probe id bits to make sure they are consistent */ if (das16_probe(dev, it)) { printk(KERN_ERR " id bits do not match selected board, aborting\n"); return -EINVAL; } - dev->board_name = board->name; /* get master clock speed */ if (board->size < 0x400) { @@ -1162,7 +1147,8 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* now for the irq */ if (irq > 1 && irq < 8) { - ret = request_irq(irq, das16_dma_interrupt, 0, "das16", dev); + ret = request_irq(irq, das16_dma_interrupt, 0, + dev->board_name, dev); if (ret < 0) return ret; @@ -1188,7 +1174,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (devpriv->dma_buffer[i] == NULL) return -ENOMEM; } - if (request_dma(dma_chan, "das16")) { + if (request_dma(dma_chan, dev->board_name)) { printk(KERN_ERR " failed to allocate dma channel %i\n", dma_chan); return -EINVAL; @@ -1353,8 +1339,7 @@ static void das16_detach(struct comedi_device *dev) struct das16_private_struct *devpriv = dev->private; das16_reset(dev); - if (dev->subdevices) - subdev_8255_cleanup(dev, &dev->subdevices[4]); + comedi_spriv_free(dev, 4); if (devpriv) { int i; for (i = 0; i < 2; i++) { @@ -1369,17 +1354,9 @@ static void das16_detach(struct comedi_device *dev) kfree(devpriv->user_ai_range_table); kfree(devpriv->user_ao_range_table); } - if (dev->irq) - free_irq(dev->irq, dev); - if (dev->iobase) { - if (board->size < 0x400) { - release_region(dev->iobase, board->size); - } else { - release_region(dev->iobase, 0x10); - release_region(dev->iobase + 0x400, - board->size & 0x3ff); - } - } + if (devpriv->extra_iobase) + release_region(devpriv->extra_iobase, board->size & 0x3ff); + comedi_legacy_detach(dev); } static const struct das16_board das16_boards[] = { diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index b0a861a779b..9cb9c3b0479 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -143,6 +143,7 @@ struct das16m1_private_struct { unsigned int do_bits; /* saves status of digital output bits */ unsigned int divisor1; /* divides master clock to obtain conversion speed */ unsigned int divisor2; /* divides master clock to obtain conversion speed */ + unsigned long extra_iobase; }; static inline short munge_sample(short data) @@ -499,7 +500,7 @@ static irqreturn_t das16m1_interrupt(int irq, void *d) int status; struct comedi_device *dev = d; - if (dev->attached == 0) { + if (!dev->attached) { comedi_error(dev, "premature interrupt"); return IRQ_HANDLED; } @@ -571,28 +572,21 @@ static int das16m1_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; unsigned int irq; - unsigned long iobase; - - dev->board_name = dev->driver->driver_name; - - iobase = it->options[0]; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - if (!request_region(iobase, DAS16M1_SIZE, dev->board_name)) { - comedi_error(dev, "I/O port conflict\n"); - return -EIO; - } - if (!request_region(iobase + DAS16M1_82C55, DAS16M1_SIZE2, - dev->board_name)) { - release_region(iobase, DAS16M1_SIZE); - comedi_error(dev, "I/O port conflict\n"); - return -EIO; - } - dev->iobase = iobase; + ret = comedi_request_region(dev, it->options[0], DAS16M1_SIZE); + if (ret) + return ret; + /* Request an additional region for the 8255 */ + ret = __comedi_request_region(dev, dev->iobase + DAS16M1_82C55, + DAS16M1_SIZE2); + if (ret) + return ret; + devpriv->extra_iobase = dev->iobase + DAS16M1_82C55; /* now for the irq */ irq = it->options[1]; @@ -654,7 +648,9 @@ static int das16m1_attach(struct comedi_device *dev, s = &dev->subdevices[3]; /* 8255 */ - subdev_8255_init(dev, s, NULL, dev->iobase + DAS16M1_82C55); + ret = subdev_8255_init(dev, s, NULL, devpriv->extra_iobase); + if (ret) + return ret; /* disable upper half of hardware conversion counter so it doesn't mess with us */ outb(TOTAL_CLEAR, dev->iobase + DAS16M1_8254_FIRST_CNTRL); @@ -674,14 +670,12 @@ static int das16m1_attach(struct comedi_device *dev, static void das16m1_detach(struct comedi_device *dev) { - if (dev->subdevices) - subdev_8255_cleanup(dev, &dev->subdevices[3]); - if (dev->irq) - free_irq(dev->irq, dev); - if (dev->iobase) { - release_region(dev->iobase, DAS16M1_SIZE); - release_region(dev->iobase + DAS16M1_82C55, DAS16M1_SIZE2); - } + struct das16m1_private_struct *devpriv = dev->private; + + comedi_spriv_free(dev, 3); + if (devpriv && devpriv->extra_iobase) + release_region(devpriv->extra_iobase, DAS16M1_SIZE2); + comedi_legacy_detach(dev); } static struct comedi_driver das16m1_driver = { diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 7900f959555..abf7638a9f7 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -429,11 +429,6 @@ static const struct das1800_board das1800_boards[] = { }, }; -/* - * Useful for shorthand access to the particular board structure - */ -#define thisboard ((const struct das1800_board *)dev->board_ptr) - struct das1800_private { volatile 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 */ @@ -454,14 +449,6 @@ struct das1800_private { short ao_update_bits; /* remembers the last write to the 'update' dac */ }; -/* analog out range for boards with basic analog out */ -static const struct comedi_lrange range_ao_1 = { - 1, - { - RANGE(-10, 10), - } -}; - /* analog out range for 'ao' boards */ /* static const struct comedi_lrange range_ao_2 = { @@ -476,6 +463,8 @@ static const struct comedi_lrange range_ao_2 = { static inline uint16_t munge_bipolar_sample(const struct comedi_device *dev, uint16_t sample) { + const struct das1800_board *thisboard = comedi_board(dev); + sample += 1 << (thisboard->resolution - 1); return sample; } @@ -731,7 +720,7 @@ static irqreturn_t das1800_interrupt(int irq, void *d) struct comedi_device *dev = d; unsigned int status; - if (dev->attached == 0) { + if (!dev->attached) { comedi_error(dev, "premature interrupt"); return IRQ_HANDLED; } @@ -789,6 +778,7 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + const struct das1800_board *thisboard = comedi_board(dev); struct das1800_private *devpriv = dev->private; int err = 0; unsigned int tmp_arg; @@ -1232,6 +1222,7 @@ static int das1800_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + const struct das1800_board *thisboard = comedi_board(dev); int i, n; int chan, range, aref, chan_range; int timeout = 1000; @@ -1295,6 +1286,7 @@ static int das1800_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + const struct das1800_board *thisboard = comedi_board(dev); struct das1800_private *devpriv = dev->private; int chan = CR_CHAN(insn->chanspec); /* int range = CR_RANGE(insn->chanspec); */ @@ -1516,46 +1508,23 @@ static int das1800_probe(struct comedi_device *dev) static int das1800_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct das1800_board *thisboard = comedi_board(dev); struct das1800_private *devpriv; struct comedi_subdevice *s; - unsigned long iobase = it->options[0]; unsigned int irq = it->options[1]; unsigned int dma0 = it->options[2]; unsigned int dma1 = it->options[3]; - unsigned long iobase2; int board; - int retval; + int ret; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - printk(KERN_DEBUG "comedi%d: %s: io 0x%lx", dev->minor, - dev->driver->driver_name, iobase); - if (irq) { - printk(KERN_CONT ", irq %u", irq); - if (dma0) { - printk(KERN_CONT ", dma %u", dma0); - if (dma1) - printk(KERN_CONT " and %u", dma1); - } - } - printk(KERN_CONT "\n"); - - if (iobase == 0) { - dev_err(dev->class_dev, "io base address required\n"); - return -EINVAL; - } - - /* check if io addresses are available */ - if (!request_region(iobase, DAS1800_SIZE, dev->driver->driver_name)) { - printk - (" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", - iobase, iobase + DAS1800_SIZE - 1); - return -EIO; - } - dev->iobase = iobase; + ret = comedi_request_region(dev, it->options[0], DAS1800_SIZE); + if (ret) + return ret; board = das1800_probe(dev); if (board < 0) { @@ -1564,18 +1533,16 @@ static int das1800_attach(struct comedi_device *dev, } dev->board_ptr = das1800_boards + board; + thisboard = comedi_board(dev); dev->board_name = thisboard->name; /* if it is an 'ao' board with fancy analog out then we need extra io ports */ if (thisboard->ao_ability == 2) { - iobase2 = iobase + IOBASE2; - if (!request_region(iobase2, DAS1800_SIZE, - dev->driver->driver_name)) { - printk - (" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", - iobase2, iobase2 + DAS1800_SIZE - 1); - return -EIO; - } + unsigned long iobase2 = dev->iobase + IOBASE2; + + ret = __comedi_request_region(dev, iobase2, DAS1800_SIZE); + if (ret) + return ret; devpriv->iobase2 = iobase2; } @@ -1618,9 +1585,9 @@ static int das1800_attach(struct comedi_device *dev, break; } - retval = das1800_init_dma(dev, dma0, dma1); - if (retval < 0) - return retval; + ret = das1800_init_dma(dev, dma0, dma1); + if (ret < 0) + return ret; if (devpriv->ai_buf0 == NULL) { devpriv->ai_buf0 = @@ -1629,9 +1596,9 @@ static int das1800_attach(struct comedi_device *dev, return -ENOMEM; } - retval = comedi_alloc_subdevices(dev, 4); - if (retval) - return retval; + ret = comedi_alloc_subdevices(dev, 4); + if (ret) + return ret; /* analog input subdevice */ s = &dev->subdevices[0]; @@ -1657,7 +1624,7 @@ static int das1800_attach(struct comedi_device *dev, s->subdev_flags = SDF_WRITABLE; s->n_chan = thisboard->ao_n_chan; s->maxdata = (1 << thisboard->resolution) - 1; - s->range_table = &range_ao_1; + s->range_table = &range_bipolar10; s->insn_write = das1800_ao_winsn; } else { s->type = COMEDI_SUBD_UNUSED; @@ -1701,21 +1668,18 @@ static void das1800_detach(struct comedi_device *dev) { struct das1800_private *devpriv = dev->private; - if (dev->iobase) - release_region(dev->iobase, DAS1800_SIZE); - if (dev->irq) - free_irq(dev->irq, dev); if (devpriv) { - if (devpriv->iobase2) - release_region(devpriv->iobase2, DAS1800_SIZE); if (devpriv->dma0) free_dma(devpriv->dma0); if (devpriv->dma1) free_dma(devpriv->dma1); kfree(devpriv->ai_buf0); kfree(devpriv->ai_buf1); + if (devpriv->iobase2) + release_region(devpriv->iobase2, DAS1800_SIZE); } -}; + comedi_legacy_detach(dev); +} static struct comedi_driver das1800_driver = { .driver_name = "das1800", diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c index 2efddb89bbc..11424fb5b4d 100644 --- a/drivers/staging/comedi/drivers/das6402.c +++ b/drivers/staging/comedi/drivers/das6402.c @@ -284,23 +284,12 @@ static int das6402_attach(struct comedi_device *dev, { struct das6402_private *devpriv; unsigned int irq; - unsigned long iobase; int ret; struct comedi_subdevice *s; - dev->board_name = "das6402"; - - iobase = it->options[0]; - if (iobase == 0) - iobase = 0x300; - - if (!request_region(iobase, DAS6402_SIZE, "das6402")) { - dev_err(dev->class_dev, "I/O port conflict\n"); - return -EIO; - } - dev->iobase = iobase; - - /* should do a probe here */ + ret = comedi_request_region(dev, it->options[0], DAS6402_SIZE); + if (ret) + return ret; irq = it->options[0]; dev_dbg(dev->class_dev, "( irq = %u )\n", irq); @@ -335,19 +324,11 @@ static int das6402_attach(struct comedi_device *dev, return 0; } -static void das6402_detach(struct comedi_device *dev) -{ - if (dev->irq) - free_irq(dev->irq, dev); - if (dev->iobase) - release_region(dev->iobase, DAS6402_SIZE); -} - static struct comedi_driver das6402_driver = { .driver_name = "das6402", .module = THIS_MODULE, .attach = das6402_attach, - .detach = das6402_detach, + .detach = comedi_legacy_detach, }; module_comedi_driver(das6402_driver) diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index 38f625be812..9ce6cbcc7ee 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -95,8 +95,8 @@ cmd triggers supported: #define IRQ 0x8 #define BUSY 0x80 #define DAS800_GAIN 3 -#define CIO_FFOV 0x8 /* fifo overflow for cio-das802/16 */ -#define CIO_ENHF 0x90 /* interrupt fifo half full for cio-das802/16 */ +#define CIO_FFOV 0x8 /* cio-das802/16 fifo overflow */ +#define CIO_ENHF 0x90 /* cio-das802/16 fifo half full int ena */ #define CONTROL1 0x80 #define CONV_CONTROL 0xa0 #define SCAN_LIMITS 0xc0 @@ -107,6 +107,8 @@ cmd triggers supported: #define STATUS2_INTE 0X20 #define DAS800_ID 7 +#define DAS802_16_HALF_FIFO_SZ 128 + struct das800_board { const char *name; int ai_speed; @@ -114,491 +116,204 @@ struct das800_board { int resolution; }; -/* analog input ranges */ -static const struct comedi_lrange range_das800_ai = { - 1, - { - RANGE(-5, 5), - } -}; - static const struct comedi_lrange range_das801_ai = { - 9, - { - RANGE(-5, 5), - RANGE(-10, 10), - RANGE(0, 10), - RANGE(-0.5, 0.5), - RANGE(0, 1), - RANGE(-0.05, 0.05), - RANGE(0, 0.1), - RANGE(-0.01, 0.01), - RANGE(0, 0.02), - } + 9, { + BIP_RANGE(5), + BIP_RANGE(10), + UNI_RANGE(10), + BIP_RANGE(0.5), + UNI_RANGE(1), + BIP_RANGE(0.05), + UNI_RANGE(0.1), + BIP_RANGE(0.01), + UNI_RANGE(0.02) + } }; static const struct comedi_lrange range_cio_das801_ai = { - 9, - { - RANGE(-5, 5), - RANGE(-10, 10), - RANGE(0, 10), - RANGE(-0.5, 0.5), - RANGE(0, 1), - RANGE(-0.05, 0.05), - RANGE(0, 0.1), - RANGE(-0.005, 0.005), - RANGE(0, 0.01), - } + 9, { + BIP_RANGE(5), + BIP_RANGE(10), + UNI_RANGE(10), + BIP_RANGE(0.5), + UNI_RANGE(1), + BIP_RANGE(0.05), + UNI_RANGE(0.1), + BIP_RANGE(0.005), + UNI_RANGE(0.01) + } }; static const struct comedi_lrange range_das802_ai = { - 9, - { - RANGE(-5, 5), - RANGE(-10, 10), - RANGE(0, 10), - RANGE(-2.5, 2.5), - RANGE(0, 5), - RANGE(-1.25, 1.25), - RANGE(0, 2.5), - RANGE(-0.625, 0.625), - RANGE(0, 1.25), - } + 9, { + BIP_RANGE(5), + BIP_RANGE(10), + UNI_RANGE(10), + BIP_RANGE(2.5), + UNI_RANGE(5), + BIP_RANGE(1.25), + UNI_RANGE(2.5), + BIP_RANGE(0.625), + UNI_RANGE(1.25) + } }; static const struct comedi_lrange range_das80216_ai = { - 8, - { - RANGE(-10, 10), - RANGE(0, 10), - RANGE(-5, 5), - RANGE(0, 5), - RANGE(-2.5, 2.5), - RANGE(0, 2.5), - RANGE(-1.25, 1.25), - RANGE(0, 1.25), - } + 8, { + BIP_RANGE(10), + UNI_RANGE(10), + BIP_RANGE(5), + UNI_RANGE(5), + BIP_RANGE(2.5), + UNI_RANGE(2.5), + BIP_RANGE(1.25), + UNI_RANGE(1.25) + } }; -enum { das800, ciodas800, das801, ciodas801, das802, ciodas802, ciodas80216 }; +enum das800_boardinfo { + BOARD_DAS800, + BOARD_CIODAS800, + BOARD_DAS801, + BOARD_CIODAS801, + BOARD_DAS802, + BOARD_CIODAS802, + BOARD_CIODAS80216, +}; static const struct das800_board das800_boards[] = { - { - .name = "das-800", - .ai_speed = 25000, - .ai_range = &range_das800_ai, - .resolution = 12, - }, - { - .name = "cio-das800", - .ai_speed = 20000, - .ai_range = &range_das800_ai, - .resolution = 12, - }, - { - .name = "das-801", - .ai_speed = 25000, - .ai_range = &range_das801_ai, - .resolution = 12, - }, - { - .name = "cio-das801", - .ai_speed = 20000, - .ai_range = &range_cio_das801_ai, - .resolution = 12, - }, - { - .name = "das-802", - .ai_speed = 25000, - .ai_range = &range_das802_ai, - .resolution = 12, - }, - { - .name = "cio-das802", - .ai_speed = 20000, - .ai_range = &range_das802_ai, - .resolution = 12, - }, - { - .name = "cio-das802/16", - .ai_speed = 10000, - .ai_range = &range_das80216_ai, - .resolution = 16, - }, + [BOARD_DAS800] = { + .name = "das-800", + .ai_speed = 25000, + .ai_range = &range_bipolar5, + .resolution = 12, + }, + [BOARD_CIODAS800] = { + .name = "cio-das800", + .ai_speed = 20000, + .ai_range = &range_bipolar5, + .resolution = 12, + }, + [BOARD_DAS801] = { + .name = "das-801", + .ai_speed = 25000, + .ai_range = &range_das801_ai, + .resolution = 12, + }, + [BOARD_CIODAS801] = { + .name = "cio-das801", + .ai_speed = 20000, + .ai_range = &range_cio_das801_ai, + .resolution = 12, + }, + [BOARD_DAS802] = { + .name = "das-802", + .ai_speed = 25000, + .ai_range = &range_das802_ai, + .resolution = 12, + }, + [BOARD_CIODAS802] = { + .name = "cio-das802", + .ai_speed = 20000, + .ai_range = &range_das802_ai, + .resolution = 12, + }, + [BOARD_CIODAS80216] = { + .name = "cio-das802/16", + .ai_speed = 10000, + .ai_range = &range_das80216_ai, + .resolution = 16, + }, }; -/* - * Useful for shorthand access to the particular board structure - */ -#define thisboard ((const struct das800_board *)dev->board_ptr) - struct das800_private { - volatile unsigned int count; /* number of data points left to be taken */ - volatile int forever; /* flag indicating whether we should take data forever */ - 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 */ - volatile int do_bits; /* digital output bits */ -}; - -static int das800_attach(struct comedi_device *dev, - struct comedi_devconfig *it); -static void das800_detach(struct comedi_device *dev); -static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s); - -static struct comedi_driver driver_das800 = { - .driver_name = "das800", - .module = THIS_MODULE, - .attach = das800_attach, - .detach = das800_detach, - .num_names = ARRAY_SIZE(das800_boards), - .board_name = &das800_boards[0].name, - .offset = sizeof(struct das800_board), + unsigned int count; /* number of data points left to be taken */ + unsigned int divisor1; /* counter 1 value for timed conversions */ + unsigned int divisor2; /* counter 2 value for timed conversions */ + unsigned int do_bits; /* digital output bits */ + bool forever; /* flag that we should take data forever */ }; -static irqreturn_t das800_interrupt(int irq, void *d); -static void enable_das800(struct comedi_device *dev); -static void disable_das800(struct comedi_device *dev); -static int das800_ai_do_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd); -static int das800_ai_do_cmd(struct comedi_device *dev, - struct comedi_subdevice *s); -static int das800_ai_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data); -static int das800_di_rbits(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data); -static int das800_do_wbits(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data); -static int das800_probe(struct comedi_device *dev); -static int das800_set_frequency(struct comedi_device *dev); - -/* checks and probes das-800 series board type */ -static int das800_probe(struct comedi_device *dev) +static void das800_ind_write(struct comedi_device *dev, + unsigned val, unsigned reg) { - int id_bits; - unsigned long irq_flags; - int board; - - /* 'comedi spin lock irqsave' disables even rt interrupts, we use them to protect indirect addressing */ - spin_lock_irqsave(&dev->spinlock, irq_flags); - outb(ID, dev->iobase + DAS800_GAIN); /* select base address + 7 to be ID register */ - id_bits = inb(dev->iobase + DAS800_ID) & 0x3; /* get id bits */ - spin_unlock_irqrestore(&dev->spinlock, irq_flags); - - board = thisboard - das800_boards; - - switch (id_bits) { - case 0x0: - if (board == das800) { - dev_dbg(dev->class_dev, "Board model: DAS-800\n"); - return board; - } - if (board == ciodas800) { - dev_dbg(dev->class_dev, "Board model: CIO-DAS800\n"); - return board; - } - dev_dbg(dev->class_dev, "Board model (probed): DAS-800\n"); - return das800; - break; - case 0x2: - if (board == das801) { - dev_dbg(dev->class_dev, "Board model: DAS-801\n"); - return board; - } - if (board == ciodas801) { - dev_dbg(dev->class_dev, "Board model: CIO-DAS801\n"); - return board; - } - dev_dbg(dev->class_dev, "Board model (probed): DAS-801\n"); - return das801; - break; - case 0x3: - if (board == das802) { - dev_dbg(dev->class_dev, "Board model: DAS-802\n"); - return board; - } - if (board == ciodas802) { - dev_dbg(dev->class_dev, "Board model: CIO-DAS802\n"); - return board; - } - if (board == ciodas80216) { - dev_dbg(dev->class_dev, "Board model: CIO-DAS802/16\n"); - return board; - } - dev_dbg(dev->class_dev, "Board model (probed): DAS-802\n"); - return das802; - break; - default: - dev_dbg(dev->class_dev, - "Board model: probe returned 0x%x (unknown)\n", - id_bits); - return board; - break; - } - return -1; + /* + * Select dev->iobase + 2 to be desired register + * then write to that register. + */ + outb(reg, dev->iobase + DAS800_GAIN); + outb(val, dev->iobase + 2); } -module_comedi_driver(driver_das800); +static unsigned das800_ind_read(struct comedi_device *dev, unsigned reg) +{ + /* + * Select dev->iobase + 7 to be desired register + * then read from that register. + */ + outb(reg, dev->iobase + DAS800_GAIN); + return inb(dev->iobase + 7); +} -/* interrupt service routine */ -static irqreturn_t das800_interrupt(int irq, void *d) +static void das800_enable(struct comedi_device *dev) { - short i; /* loop index */ - short dataPoint = 0; - struct comedi_device *dev = d; + const struct das800_board *thisboard = comedi_board(dev); struct das800_private *devpriv = dev->private; - struct comedi_subdevice *s = dev->read_subdev; /* analog input subdevice */ - struct comedi_async *async; - int status; unsigned long irq_flags; - static const int max_loops = 128; /* half-fifo size for cio-das802/16 */ - /* flags */ - int fifo_empty = 0; - int fifo_overflow = 0; - status = inb(dev->iobase + DAS800_STATUS); - /* if interrupt was not generated by board or driver not attached, quit */ - if (!(status & IRQ)) - return IRQ_NONE; - if (!(dev->attached)) - return IRQ_HANDLED; - - /* wait until here to initialize async, since we will get null dereference - * if interrupt occurs before driver is fully attached! - */ - async = s->async; - - /* if hardware conversions are not enabled, then quit */ spin_lock_irqsave(&dev->spinlock, irq_flags); - outb(CONTROL1, dev->iobase + DAS800_GAIN); /* select base address + 7 to be STATUS2 register */ - status = inb(dev->iobase + DAS800_STATUS2) & STATUS2_HCEN; - /* don't release spinlock yet since we want to make sure no one else disables hardware conversions */ - if (status == 0) { - spin_unlock_irqrestore(&dev->spinlock, irq_flags); - return IRQ_HANDLED; - } - - /* loop while card's fifo is not empty (and limit to half fifo for cio-das802/16) */ - for (i = 0; i < max_loops; i++) { - /* read 16 bits from dev->iobase and dev->iobase + 1 */ - dataPoint = inb(dev->iobase + DAS800_LSB); - dataPoint += inb(dev->iobase + DAS800_MSB) << 8; - if (thisboard->resolution == 12) { - fifo_empty = dataPoint & FIFO_EMPTY; - fifo_overflow = dataPoint & FIFO_OVF; - if (fifo_overflow) - break; - } else { - fifo_empty = 0; /* cio-das802/16 has no fifo empty status bit */ - } - if (fifo_empty) - break; - /* strip off extraneous bits for 12 bit cards */ - if (thisboard->resolution == 12) - dataPoint = (dataPoint >> 4) & 0xfff; - /* if there are more data points to collect */ - if (devpriv->count > 0 || devpriv->forever == 1) { - /* write data point to buffer */ - cfc_write_to_buffer(s, dataPoint); - if (devpriv->count > 0) - devpriv->count--; - } - } - async->events |= COMEDI_CB_BLOCK; - /* check for fifo overflow */ - if (thisboard->resolution == 12) { - fifo_overflow = dataPoint & FIFO_OVF; - /* else cio-das802/16 */ - } else { - fifo_overflow = inb(dev->iobase + DAS800_GAIN) & CIO_FFOV; - } - if (fifo_overflow) { - spin_unlock_irqrestore(&dev->spinlock, irq_flags); - comedi_error(dev, "DAS800 FIFO overflow"); - das800_cancel(dev, s); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; - comedi_event(dev, s); - async->events = 0; - return IRQ_HANDLED; - } - if (devpriv->count > 0 || devpriv->forever == 1) { - /* Re-enable card's interrupt. - * We already have spinlock, so indirect addressing is safe */ - outb(CONTROL1, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be control register 1 */ - outb(CONTROL1_INTE | devpriv->do_bits, - dev->iobase + DAS800_CONTROL1); - spin_unlock_irqrestore(&dev->spinlock, irq_flags); - /* otherwise, stop taking data */ - } else { - spin_unlock_irqrestore(&dev->spinlock, irq_flags); - disable_das800(dev); /* disable hardware triggered conversions */ - async->events |= COMEDI_CB_EOA; - } - comedi_event(dev, s); - async->events = 0; - return IRQ_HANDLED; + /* enable fifo-half full interrupts for cio-das802/16 */ + if (thisboard->resolution == 16) + outb(CIO_ENHF, dev->iobase + DAS800_GAIN); + /* enable hardware triggering */ + das800_ind_write(dev, CONV_HCEN, CONV_CONTROL); + /* enable card's interrupt */ + das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits, CONTROL1); + spin_unlock_irqrestore(&dev->spinlock, irq_flags); } -static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) +static void das800_disable(struct comedi_device *dev) { - struct das800_private *devpriv; - struct comedi_subdevice *s; - unsigned long iobase = it->options[0]; - unsigned int irq = it->options[1]; unsigned long irq_flags; - int board; - int ret; - - dev_info(dev->class_dev, "das800: io 0x%lx\n", iobase); - if (irq) - dev_dbg(dev->class_dev, "irq %u\n", irq); - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); - if (!devpriv) - return -ENOMEM; - dev->private = devpriv; - - if (iobase == 0) { - dev_err(dev->class_dev, - "io base address required for das800\n"); - return -EINVAL; - } - - /* check if io addresses are available */ - if (!request_region(iobase, DAS800_SIZE, "das800")) { - dev_err(dev->class_dev, "I/O port conflict\n"); - return -EIO; - } - dev->iobase = iobase; - - board = das800_probe(dev); - if (board < 0) { - dev_dbg(dev->class_dev, "unable to determine board type\n"); - return -ENODEV; - } - dev->board_ptr = das800_boards + board; - - /* grab our IRQ */ - if (irq == 1 || irq > 7) { - dev_err(dev->class_dev, "irq out of range\n"); - return -EINVAL; - } - if (irq) { - if (request_irq(irq, das800_interrupt, 0, "das800", dev)) { - dev_err(dev->class_dev, "unable to allocate irq %u\n", - irq); - return -EINVAL; - } - } - dev->irq = irq; - - dev->board_name = thisboard->name; - - ret = comedi_alloc_subdevices(dev, 3); - if (ret) - return ret; - - /* analog input subdevice */ - s = &dev->subdevices[0]; - dev->read_subdev = s; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; - s->n_chan = 8; - s->len_chanlist = 8; - s->maxdata = (1 << thisboard->resolution) - 1; - s->range_table = thisboard->ai_range; - s->do_cmd = das800_ai_do_cmd; - s->do_cmdtest = das800_ai_do_cmdtest; - s->insn_read = das800_ai_rinsn; - s->cancel = das800_cancel; - - /* di */ - s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 3; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = das800_di_rbits; - - /* do */ - s = &dev->subdevices[2]; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE | SDF_READABLE; - s->n_chan = 4; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = das800_do_wbits; - - disable_das800(dev); - - /* initialize digital out channels */ spin_lock_irqsave(&dev->spinlock, irq_flags); - outb(CONTROL1, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be control register 1 */ - outb(CONTROL1_INTE | devpriv->do_bits, dev->iobase + DAS800_CONTROL1); + /* disable hardware triggering of conversions */ + das800_ind_write(dev, 0x0, CONV_CONTROL); spin_unlock_irqrestore(&dev->spinlock, irq_flags); +} - return 0; -}; - -static void das800_detach(struct comedi_device *dev) -{ - if (dev->iobase) - release_region(dev->iobase, DAS800_SIZE); - if (dev->irq) - free_irq(dev->irq, dev); -}; - -static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s) +static int das800_set_frequency(struct comedi_device *dev) { struct das800_private *devpriv = dev->private; + int err = 0; + + if (i8254_load(dev->iobase + DAS800_8254, 0, 1, devpriv->divisor1, 2)) + err++; + if (i8254_load(dev->iobase + DAS800_8254, 0, 2, devpriv->divisor2, 2)) + err++; + if (err) + return -1; - devpriv->forever = 0; - devpriv->count = 0; - disable_das800(dev); return 0; } -/* enable_das800 makes the card start taking hardware triggered conversions */ -static void enable_das800(struct comedi_device *dev) +static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct das800_private *devpriv = dev->private; - unsigned long irq_flags; - spin_lock_irqsave(&dev->spinlock, irq_flags); - /* enable fifo-half full interrupts for cio-das802/16 */ - if (thisboard->resolution == 16) - outb(CIO_ENHF, dev->iobase + DAS800_GAIN); - outb(CONV_CONTROL, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be conversion control register */ - outb(CONV_HCEN, dev->iobase + DAS800_CONV_CONTROL); /* enable hardware triggering */ - outb(CONTROL1, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be control register 1 */ - outb(CONTROL1_INTE | devpriv->do_bits, dev->iobase + DAS800_CONTROL1); /* enable card's interrupt */ - spin_unlock_irqrestore(&dev->spinlock, irq_flags); -} - -/* disable_das800 stops hardware triggered conversions */ -static void disable_das800(struct comedi_device *dev) -{ - unsigned long irq_flags; - spin_lock_irqsave(&dev->spinlock, irq_flags); - outb(CONV_CONTROL, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be conversion control register */ - outb(0x0, dev->iobase + DAS800_CONV_CONTROL); /* disable hardware triggering of conversions */ - spin_unlock_irqrestore(&dev->spinlock, irq_flags); + devpriv->forever = false; + devpriv->count = 0; + das800_disable(dev); + return 0; } static int das800_ai_do_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + const struct das800_board *thisboard = comedi_board(dev); struct das800_private *devpriv = dev->private; int err = 0; - int tmp; - int gain, startChan; - int i; /* Step 1 : check if triggers are trivially valid */ @@ -644,11 +359,13 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev, /* step 4: fix up any arguments */ if (cmd->convert_src == TRIG_TIMER) { - tmp = cmd->convert_arg; + int tmp = cmd->convert_arg; + /* calculate counter values that give desired timing */ - i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1), - &(devpriv->divisor2), - &(cmd->convert_arg), + i8253_cascade_ns_to_timer_2div(TIMER_BASE, + &devpriv->divisor1, + &devpriv->divisor2, + &cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); if (tmp != cmd->convert_arg) err++; @@ -659,18 +376,21 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev, /* check channel/gain list against card's limitations */ if (cmd->chanlist) { - gain = CR_RANGE(cmd->chanlist[0]); - startChan = CR_CHAN(cmd->chanlist[0]); + unsigned int chan = CR_CHAN(cmd->chanlist[0]); + unsigned int range = CR_RANGE(cmd->chanlist[0]); + unsigned int next; + int i; + for (i = 1; i < cmd->chanlist_len; i++) { - if (CR_CHAN(cmd->chanlist[i]) != - (startChan + i) % N_CHAN_AI) { - comedi_error(dev, - "entries in chanlist must be consecutive channels, counting upwards\n"); + next = cmd->chanlist[i]; + if (CR_CHAN(next) != (chan + i) % N_CHAN_AI) { + dev_err(dev->class_dev, + "chanlist must be consecutive, counting upwards\n"); err++; } - if (CR_RANGE(cmd->chanlist[i]) != gain) { - comedi_error(dev, - "entries in chanlist must all have the same gain\n"); + if (CR_RANGE(next) != range) { + dev_err(dev->class_dev, + "chanlist must all have the same gain\n"); err++; } } @@ -685,32 +405,24 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev, static int das800_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { + const struct das800_board *thisboard = comedi_board(dev); struct das800_private *devpriv = dev->private; - int startChan, endChan, scan, gain; + struct comedi_async *async = s->async; + unsigned int gain = CR_RANGE(async->cmd.chanlist[0]); + unsigned int start_chan = CR_CHAN(async->cmd.chanlist[0]); + unsigned int end_chan = (start_chan + async->cmd.chanlist_len - 1) % 8; + unsigned int scan_chans = (end_chan << 3) | start_chan; int conv_bits; unsigned long irq_flags; - struct comedi_async *async = s->async; - if (!dev->irq) { - comedi_error(dev, - "no irq assigned for das-800, cannot do hardware conversions"); - return -1; - } - - disable_das800(dev); - - /* set channel scan limits */ - startChan = CR_CHAN(async->cmd.chanlist[0]); - endChan = (startChan + async->cmd.chanlist_len - 1) % 8; - scan = (endChan << 3) | startChan; + das800_disable(dev); spin_lock_irqsave(&dev->spinlock, irq_flags); - outb(SCAN_LIMITS, dev->iobase + DAS800_GAIN); /* select base address + 2 to be scan limits register */ - outb(scan, dev->iobase + DAS800_SCAN_LIMITS); /* set scan limits */ + /* set scan limits */ + das800_ind_write(dev, scan_chans, SCAN_LIMITS); spin_unlock_irqrestore(&dev->spinlock, irq_flags); /* set gain */ - gain = CR_RANGE(async->cmd.chanlist[0]); if (thisboard->resolution == 12 && gain > 0) gain += 0x7; gain &= 0xf; @@ -719,10 +431,10 @@ static int das800_ai_do_cmd(struct comedi_device *dev, switch (async->cmd.stop_src) { case TRIG_COUNT: devpriv->count = async->cmd.stop_arg * async->cmd.chanlist_len; - devpriv->forever = 0; + devpriv->forever = false; break; case TRIG_NONE: - devpriv->forever = 1; + devpriv->forever = true; devpriv->count = 0; break; default: @@ -740,11 +452,6 @@ static int das800_ai_do_cmd(struct comedi_device *dev, case TRIG_TIMER: conv_bits |= CASC | ITE; /* set conversion frequency */ - i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1), - &(devpriv->divisor2), - &(async->cmd.convert_arg), - async->cmd. - flags & TRIG_ROUND_MASK); if (das800_set_frequency(dev) < 0) { comedi_error(dev, "Error setting up counters"); return -1; @@ -757,125 +464,333 @@ static int das800_ai_do_cmd(struct comedi_device *dev, } spin_lock_irqsave(&dev->spinlock, irq_flags); - outb(CONV_CONTROL, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be conversion control register */ - outb(conv_bits, dev->iobase + DAS800_CONV_CONTROL); + das800_ind_write(dev, conv_bits, CONV_CONTROL); spin_unlock_irqrestore(&dev->spinlock, irq_flags); + async->events = 0; - enable_das800(dev); + das800_enable(dev); return 0; } -static int das800_ai_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data) +static unsigned int das800_ai_get_sample(struct comedi_device *dev) { + unsigned int lsb = inb(dev->iobase + DAS800_LSB); + unsigned int msb = inb(dev->iobase + DAS800_MSB); + + return (msb << 8) | lsb; +} + +static irqreturn_t das800_interrupt(int irq, void *d) +{ + struct comedi_device *dev = d; struct das800_private *devpriv = dev->private; - int i, n; - int chan; - int range; - int lsb, msb; - int timeout = 1000; + struct comedi_subdevice *s = dev->read_subdev; + struct comedi_async *async = s ? s->async : NULL; unsigned long irq_flags; + unsigned int status; + unsigned int val; + bool fifo_empty; + bool fifo_overflow; + int i; - disable_das800(dev); /* disable hardware conversions (enables software conversions) */ + status = inb(dev->iobase + DAS800_STATUS); + if (!(status & IRQ)) + return IRQ_NONE; + if (!dev->attached) + return IRQ_HANDLED; - /* set multiplexer */ - chan = CR_CHAN(insn->chanspec); + spin_lock_irqsave(&dev->spinlock, irq_flags); + status = das800_ind_read(dev, CONTROL1) & STATUS2_HCEN; + /* + * Don't release spinlock yet since we want to make sure + * no one else disables hardware conversions. + */ + /* if hardware conversions are not enabled, then quit */ + if (status == 0) { + spin_unlock_irqrestore(&dev->spinlock, irq_flags); + return IRQ_HANDLED; + } + + for (i = 0; i < DAS802_16_HALF_FIFO_SZ; i++) { + val = das800_ai_get_sample(dev); + if (s->maxdata == 0x0fff) { + fifo_empty = !!(val & FIFO_EMPTY); + fifo_overflow = !!(val & FIFO_OVF); + } else { + /* cio-das802/16 has no fifo empty status bit */ + fifo_empty = false; + fifo_overflow = !!(inb(dev->iobase + DAS800_GAIN) & + CIO_FFOV); + } + if (fifo_empty || fifo_overflow) + break; + + if (s->maxdata == 0x0fff) + val >>= 4; /* 12-bit sample */ + + /* if there are more data points to collect */ + if (devpriv->count > 0 || devpriv->forever) { + /* write data point to buffer */ + cfc_write_to_buffer(s, val & s->maxdata); + devpriv->count--; + } + } + async->events |= COMEDI_CB_BLOCK; + + if (fifo_overflow) { + spin_unlock_irqrestore(&dev->spinlock, irq_flags); + das800_cancel(dev, s); + async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + comedi_event(dev, s); + async->events = 0; + return IRQ_HANDLED; + } + + if (devpriv->count > 0 || devpriv->forever) { + /* Re-enable card's interrupt. + * We already have spinlock, so indirect addressing is safe */ + das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits, + CONTROL1); + spin_unlock_irqrestore(&dev->spinlock, irq_flags); + } else { + /* otherwise, stop taking data */ + spin_unlock_irqrestore(&dev->spinlock, irq_flags); + das800_disable(dev); + async->events |= COMEDI_CB_EOA; + } + comedi_event(dev, s); + async->events = 0; + return IRQ_HANDLED; +} + +static int das800_wait_for_conv(struct comedi_device *dev, int timeout) +{ + int i; + + for (i = 0; i < timeout; i++) { + if (!(inb(dev->iobase + DAS800_STATUS) & BUSY)) + return 0; + } + return -ETIME; +} + +static int das800_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct das800_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); + unsigned long irq_flags; + unsigned int val; + int ret; + int i; + + das800_disable(dev); + + /* set multiplexer */ spin_lock_irqsave(&dev->spinlock, irq_flags); - outb(CONTROL1, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be control register 1 */ - outb(chan | devpriv->do_bits, dev->iobase + DAS800_CONTROL1); + das800_ind_write(dev, chan | devpriv->do_bits, CONTROL1); spin_unlock_irqrestore(&dev->spinlock, irq_flags); /* set gain / range */ - range = CR_RANGE(insn->chanspec); - if (thisboard->resolution == 12 && range) + if (s->maxdata == 0x0fff && range) range += 0x7; range &= 0xf; outb(range, dev->iobase + DAS800_GAIN); udelay(5); - for (n = 0; n < insn->n; n++) { + for (i = 0; i < insn->n; i++) { /* trigger conversion */ outb_p(0, dev->iobase + DAS800_MSB); - for (i = 0; i < timeout; i++) { - if (!(inb(dev->iobase + DAS800_STATUS) & BUSY)) - break; - } - if (i == timeout) { - comedi_error(dev, "timeout"); - return -ETIME; - } - lsb = inb(dev->iobase + DAS800_LSB); - msb = inb(dev->iobase + DAS800_MSB); - if (thisboard->resolution == 12) { - data[n] = (lsb >> 4) & 0xff; - data[n] |= (msb << 4); - } else { - data[n] = (msb << 8) | lsb; - } + ret = das800_wait_for_conv(dev, 1000); + if (ret) + return ret; + + val = das800_ai_get_sample(dev); + if (s->maxdata == 0x0fff) + val >>= 4; /* 12-bit sample */ + data[i] = val & s->maxdata; } - return n; + return insn->n; } -static int das800_di_rbits(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data) +static int das800_di_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - unsigned int bits; - - bits = inb(dev->iobase + DAS800_STATUS) >> 4; - bits &= 0x7; - data[1] = bits; - data[0] = 0; + data[1] = (inb(dev->iobase + DAS800_STATUS) >> 4) & 0x7; return insn->n; } -static int das800_do_wbits(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data) +static int das800_do_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct das800_private *devpriv = dev->private; - int wbits; + unsigned int mask = data[0]; + unsigned int bits = data[1]; unsigned long irq_flags; - /* only set bits that have been masked */ - data[0] &= 0xf; - wbits = devpriv->do_bits >> 4; - wbits &= ~data[0]; - wbits |= data[0] & data[1]; - devpriv->do_bits = wbits << 4; + if (mask) { + s->state &= ~mask; + s->state |= (bits & mask); + devpriv->do_bits = s->state << 4; - spin_lock_irqsave(&dev->spinlock, irq_flags); - outb(CONTROL1, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be control register 1 */ - outb(devpriv->do_bits | CONTROL1_INTE, dev->iobase + DAS800_CONTROL1); - spin_unlock_irqrestore(&dev->spinlock, irq_flags); + spin_lock_irqsave(&dev->spinlock, irq_flags); + das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits, + CONTROL1); + spin_unlock_irqrestore(&dev->spinlock, irq_flags); + } - data[1] = wbits; + data[1] = s->state; return insn->n; } -/* loads counters with divisor1, divisor2 from private structure */ -static int das800_set_frequency(struct comedi_device *dev) +static int das800_probe(struct comedi_device *dev) { - struct das800_private *devpriv = dev->private; - int err = 0; + const struct das800_board *thisboard = comedi_board(dev); + int board = thisboard ? thisboard - das800_boards : -EINVAL; + int id_bits; + unsigned long irq_flags; - if (i8254_load(dev->iobase + DAS800_8254, 0, 1, devpriv->divisor1, 2)) - err++; - if (i8254_load(dev->iobase + DAS800_8254, 0, 2, devpriv->divisor2, 2)) - err++; - if (err) - return -1; + spin_lock_irqsave(&dev->spinlock, irq_flags); + id_bits = das800_ind_read(dev, ID) & 0x3; + spin_unlock_irqrestore(&dev->spinlock, irq_flags); - return 0; + switch (id_bits) { + case 0x0: + if (board == BOARD_DAS800 || board == BOARD_CIODAS800) + break; + dev_dbg(dev->class_dev, "Board model (probed): DAS-800\n"); + board = BOARD_DAS800; + break; + case 0x2: + if (board == BOARD_DAS801 || board == BOARD_CIODAS801) + break; + dev_dbg(dev->class_dev, "Board model (probed): DAS-801\n"); + board = BOARD_DAS801; + break; + case 0x3: + if (board == BOARD_DAS802 || board == BOARD_CIODAS802 || + board == BOARD_CIODAS80216) + break; + dev_dbg(dev->class_dev, "Board model (probed): DAS-802\n"); + board = BOARD_DAS802; + break; + default: + dev_dbg(dev->class_dev, "Board model: 0x%x (unknown)\n", + id_bits); + board = -EINVAL; + break; + } + return board; } +static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) +{ + const struct das800_board *thisboard = comedi_board(dev); + struct das800_private *devpriv; + struct comedi_subdevice *s; + unsigned int irq = it->options[1]; + unsigned long irq_flags; + int board; + int ret; + + devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + if (!devpriv) + return -ENOMEM; + dev->private = devpriv; + + ret = comedi_request_region(dev, it->options[0], DAS800_SIZE); + if (ret) + return ret; + + board = das800_probe(dev); + if (board < 0) { + dev_dbg(dev->class_dev, "unable to determine board type\n"); + return -ENODEV; + } + dev->board_ptr = das800_boards + board; + thisboard = comedi_board(dev); + dev->board_name = thisboard->name; + + if (irq > 1 && irq <= 7) { + ret = request_irq(irq, das800_interrupt, 0, dev->board_name, + dev); + if (ret == 0) + dev->irq = irq; + } + + ret = comedi_alloc_subdevices(dev, 3); + if (ret) + return ret; + + /* Analog Input subdevice */ + s = &dev->subdevices[0]; + dev->read_subdev = s; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND; + s->n_chan = 8; + s->maxdata = (1 << thisboard->resolution) - 1; + s->range_table = thisboard->ai_range; + s->insn_read = das800_ai_insn_read; + if (dev->irq) { + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = 8; + s->do_cmdtest = das800_ai_do_cmdtest; + s->do_cmd = das800_ai_do_cmd; + s->cancel = das800_cancel; + } + + /* Digital Input subdevice */ + s = &dev->subdevices[1]; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 3; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = das800_di_insn_bits; + + /* Digital Output subdevice */ + s = &dev->subdevices[2]; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = 4; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = das800_do_insn_bits; + + das800_disable(dev); + + /* initialize digital out channels */ + spin_lock_irqsave(&dev->spinlock, irq_flags); + das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits, CONTROL1); + spin_unlock_irqrestore(&dev->spinlock, irq_flags); + + return 0; +}; + +static struct comedi_driver driver_das800 = { + .driver_name = "das800", + .module = THIS_MODULE, + .attach = das800_attach, + .detach = comedi_legacy_detach, + .num_names = ARRAY_SIZE(das800_boards), + .board_name = &das800_boards[0].name, + .offset = sizeof(struct das800_board), +}; +module_comedi_driver(driver_das800); + MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 9e2124179a0..6c85dd2d549 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -695,25 +695,13 @@ static int dmm32at_attach(struct comedi_device *dev, int ret; struct comedi_subdevice *s; unsigned char aihi, ailo, fifostat, aistat, intstat, airback; - unsigned long iobase; unsigned int irq; - dev->board_name = dev->driver->driver_name; - - iobase = it->options[0]; irq = it->options[1]; - printk(KERN_INFO "comedi%d: dmm32at: attaching\n", dev->minor); - printk(KERN_DEBUG "dmm32at: probing at address 0x%04lx, irq %u\n", - iobase, irq); - - /* register address space */ - if (!request_region(iobase, DMM32AT_MEMSIZE, dev->board_name)) { - printk(KERN_ERR "comedi%d: dmm32at: I/O port conflict\n", - dev->minor); - return -EIO; - } - dev->iobase = iobase; + ret = comedi_request_region(dev, it->options[0], DMM32AT_MEMSIZE); + if (ret) + return ret; /* the following just makes sure the board is there and gets it to a known state */ @@ -832,19 +820,11 @@ static int dmm32at_attach(struct comedi_device *dev, } -static void dmm32at_detach(struct comedi_device *dev) -{ - if (dev->irq) - free_irq(dev->irq, dev); - if (dev->iobase) - release_region(dev->iobase, DMM32AT_MEMSIZE); -} - static struct comedi_driver dmm32at_driver = { .driver_name = "dmm32at", .module = THIS_MODULE, .attach = dmm32at_attach, - .detach = dmm32at_detach, + .detach = comedi_legacy_detach, }; module_comedi_driver(dmm32at_driver); diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index f6942aaf0ec..8f5006d70da 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -225,8 +225,6 @@ static const struct dt2801_board boardtypes[] = { .dabits = 12}, }; -#define boardtype (*(const struct dt2801_board *)dev->board_ptr) - struct dt2801_private { const struct comedi_lrange *dac_range_types[2]; @@ -592,19 +590,16 @@ static int dt2801_dio_insn_config(struct comedi_device *dev, */ static int dt2801_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct dt2801_board *board = comedi_board(dev); struct dt2801_private *devpriv; struct comedi_subdevice *s; - unsigned long iobase; int board_code, type; int ret = 0; int n_ai_chans; - iobase = it->options[0]; - if (!request_region(iobase, DT2801_IOSIZE, "dt2801")) { - comedi_error(dev, "I/O port conflict"); - return -EIO; - } - dev->iobase = iobase; + ret = comedi_request_region(dev, it->options[0], DT2801_IOSIZE); + if (ret) + return ret; /* do some checking */ @@ -624,10 +619,9 @@ static int dt2801_attach(struct comedi_device *dev, struct comedi_devconfig *it) havetype: dev->board_ptr = boardtypes + type; - printk("dt2801: %s at port 0x%lx", boardtype.name, iobase); + board = comedi_board(dev); n_ai_chans = probe_number_of_ai_chans(dev); - printk(" (ai channels = %d)\n", n_ai_chans); ret = comedi_alloc_subdevices(dev, 4); if (ret) @@ -638,7 +632,7 @@ havetype: return -ENOMEM; dev->private = devpriv; - dev->board_name = boardtype.name; + dev->board_name = board->name; s = &dev->subdevices[0]; /* ai subdevice */ @@ -648,12 +642,12 @@ havetype: s->n_chan = n_ai_chans; #else if (it->options[2]) - s->n_chan = boardtype.ad_chan; + s->n_chan = board->ad_chan; else - s->n_chan = boardtype.ad_chan / 2; + s->n_chan = board->ad_chan / 2; #endif - s->maxdata = (1 << boardtype.adbits) - 1; - s->range_table = ai_range_lkup(boardtype.adrangetype, it->options[3]); + s->maxdata = (1 << board->adbits) - 1; + s->range_table = ai_range_lkup(board->adrangetype, it->options[3]); s->insn_read = dt2801_ai_insn_read; s = &dev->subdevices[1]; @@ -661,7 +655,7 @@ havetype: s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; s->n_chan = 2; - s->maxdata = (1 << boardtype.dabits) - 1; + s->maxdata = (1 << board->dabits) - 1; s->range_table_list = devpriv->dac_range_types; devpriv->dac_range_types[0] = dac_range_lkup(it->options[4]); devpriv->dac_range_types[1] = dac_range_lkup(it->options[5]); @@ -693,17 +687,11 @@ out: return ret; } -static void dt2801_detach(struct comedi_device *dev) -{ - if (dev->iobase) - release_region(dev->iobase, DT2801_IOSIZE); -} - static struct comedi_driver dt2801_driver = { .driver_name = "dt2801", .module = THIS_MODULE, .attach = dt2801_attach, - .detach = dt2801_detach, + .detach = comedi_legacy_detach, }; module_comedi_driver(dt2801_driver); diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index f90ecf494aa..8757b54ad4a 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -50,8 +50,6 @@ Configuration options: #include <linux/ioport.h> -static const char *driver_name = "dt2811"; - static const struct comedi_lrange range_dt2811_pgh_ai_5_unipolar = { 4, { RANGE(0, 5), @@ -401,19 +399,10 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct dt2811_private *devpriv; int ret; struct comedi_subdevice *s; - unsigned long iobase; - - iobase = it->options[0]; - - printk(KERN_INFO "comedi%d: dt2811:base=0x%04lx\n", dev->minor, iobase); - - if (!request_region(iobase, DT2811_SIZE, driver_name)) { - printk(KERN_ERR "I/O port conflict\n"); - return -EIO; - } - dev->iobase = iobase; - dev->board_name = board->name; + ret = comedi_request_region(dev, it->options[0], DT2811_SIZE); + if (ret) + return ret; #if 0 outb(0, dev->iobase + DT2811_ADCSR); @@ -449,7 +438,7 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it) i = inb(dev->iobase + DT2811_ADDATHI); printk(KERN_INFO "(irq = %d)\n", irq); ret = request_irq(irq, dt2811_interrupt, 0, - driver_name, dev); + dev->board_name, dev); if (ret < 0) return -EIO; dev->irq = irq; @@ -567,14 +556,6 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it) return 0; } -static void dt2811_detach(struct comedi_device *dev) -{ - if (dev->irq) - free_irq(dev->irq, dev); - if (dev->iobase) - release_region(dev->iobase, DT2811_SIZE); -} - static const struct dt2811_board boardtypes[] = { { .name = "dt2811-pgh", @@ -593,7 +574,7 @@ static struct comedi_driver dt2811_driver = { .driver_name = "dt2811", .module = THIS_MODULE, .attach = dt2811_attach, - .detach = dt2811_detach, + .detach = comedi_legacy_detach, .board_name = &boardtypes[0].name, .num_names = ARRAY_SIZE(boardtypes), .offset = sizeof(struct dt2811_board), diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index e520dbaaa19..7c95b3b6813 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -246,16 +246,10 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it) int i, irq; int ret; struct comedi_subdevice *s; - unsigned long iobase; - iobase = it->options[0]; - printk(KERN_INFO "comedi%d: dt2814: 0x%04lx ", dev->minor, iobase); - if (!request_region(iobase, DT2814_SIZE, "dt2814")) { - printk(KERN_ERR "I/O port conflict\n"); - return -EIO; - } - dev->iobase = iobase; - dev->board_name = "dt2814"; + ret = comedi_request_region(dev, it->options[0], DT2814_SIZE); + if (ret) + return ret; outb(0, dev->iobase + DT2814_CSR); udelay(100); @@ -329,19 +323,11 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it) return 0; } -static void dt2814_detach(struct comedi_device *dev) -{ - if (dev->irq) - free_irq(dev->irq, dev); - if (dev->iobase) - release_region(dev->iobase, DT2814_SIZE); -} - static struct comedi_driver dt2814_driver = { .driver_name = "dt2814", .module = THIS_MODULE, .attach = dt2814_attach, - .detach = dt2814_detach, + .detach = comedi_legacy_detach, }; module_comedi_driver(dt2814_driver); diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c index 1e0cfe4972a..b24e87681fe 100644 --- a/drivers/staging/comedi/drivers/dt2815.c +++ b/drivers/staging/comedi/drivers/dt2815.c @@ -61,12 +61,6 @@ Configuration options: #include <linux/ioport.h> #include <linux/delay.h> -static const struct comedi_lrange - range_dt2815_ao_32_current = {1, {RANGE_mA(0, 32)} }; - -static const struct comedi_lrange - range_dt2815_ao_20_current = {1, {RANGE_mA(4, 20)} }; - #define DT2815_SIZE 2 #define DT2815_DATA 0 @@ -166,18 +160,11 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; int i; const struct comedi_lrange *current_range_type, *voltage_range_type; - unsigned long iobase; int ret; - iobase = it->options[0]; - printk(KERN_INFO "comedi%d: dt2815: 0x%04lx ", dev->minor, iobase); - if (!request_region(iobase, DT2815_SIZE, "dt2815")) { - printk(KERN_WARNING "I/O port conflict\n"); - return -EIO; - } - - dev->iobase = iobase; - dev->board_name = "dt2815"; + ret = comedi_request_region(dev, it->options[0], DT2815_SIZE); + if (ret) + return ret; ret = comedi_alloc_subdevices(dev, 1); if (ret) @@ -199,7 +186,7 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->range_table_list = devpriv->range_type_list; current_range_type = (it->options[3]) - ? &range_dt2815_ao_20_current : &range_dt2815_ao_32_current; + ? &range_4_20mA : &range_0_32mA; voltage_range_type = (it->options[2]) ? &range_bipolar5 : &range_unipolar5; for (i = 0; i < 8; i++) { @@ -233,17 +220,11 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it) return 0; } -static void dt2815_detach(struct comedi_device *dev) -{ - if (dev->iobase) - release_region(dev->iobase, DT2815_SIZE); -} - static struct comedi_driver dt2815_driver = { .driver_name = "dt2815", .module = THIS_MODULE, .attach = dt2815_attach, - .detach = dt2815_detach, + .detach = comedi_legacy_detach, }; module_comedi_driver(dt2815_driver); diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c index 502e42e0753..b5c8e8213fa 100644 --- a/drivers/staging/comedi/drivers/dt2817.c +++ b/drivers/staging/comedi/drivers/dt2817.c @@ -126,16 +126,10 @@ static int dt2817_attach(struct comedi_device *dev, struct comedi_devconfig *it) { int ret; struct comedi_subdevice *s; - unsigned long iobase; - iobase = it->options[0]; - printk(KERN_INFO "comedi%d: dt2817: 0x%04lx ", dev->minor, iobase); - if (!request_region(iobase, DT2817_SIZE, "dt2817")) { - printk("I/O port conflict\n"); - return -EIO; - } - dev->iobase = iobase; - dev->board_name = "dt2817"; + ret = comedi_request_region(dev, it->options[0], DT2817_SIZE); + if (ret) + return ret; ret = comedi_alloc_subdevices(dev, 1); if (ret) @@ -154,22 +148,14 @@ static int dt2817_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->state = 0; outb(0, dev->iobase + DT2817_CR); - printk(KERN_INFO "\n"); - return 0; } -static void dt2817_detach(struct comedi_device *dev) -{ - if (dev->iobase) - release_region(dev->iobase, DT2817_SIZE); -} - static struct comedi_driver dt2817_driver = { .driver_name = "dt2817", .module = THIS_MODULE, .attach = dt2817_attach, - .detach = dt2817_detach, + .detach = comedi_legacy_detach, }; module_comedi_driver(dt2817_driver); diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 122d980a95a..90f2de9bc40 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -248,8 +248,6 @@ struct dt282x_private { int dma_dir; }; -#define boardtype (*(const struct dt282x_board *)dev->board_ptr) - /* * Some useless abstractions */ @@ -289,14 +287,15 @@ static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2); static void dt282x_munge(struct comedi_device *dev, short *buf, unsigned int nbytes) { + const struct dt282x_board *board = comedi_board(dev); struct dt282x_private *devpriv = dev->private; unsigned int i; - unsigned short mask = (1 << boardtype.adbits) - 1; - unsigned short sign = 1 << (boardtype.adbits - 1); + unsigned short mask = (1 << board->adbits) - 1; + unsigned short sign = 1 << (board->adbits - 1); int n; if (devpriv->ad_2scomp) - sign = 1 << (boardtype.adbits - 1); + sign = 1 << (board->adbits - 1); else sign = 0; @@ -501,10 +500,10 @@ static irqreturn_t dt282x_interrupt(int irq, void *d) short data; data = (short)inw(dev->iobase + DT2821_ADDAT); - data &= (1 << boardtype.adbits) - 1; + data &= (1 << board->adbits) - 1; if (devpriv->ad_2scomp) - data ^= 1 << (boardtype.adbits - 1); + data ^= 1 << (board->adbits - 1); ret = comedi_buf_put(s->async, data); if (ret == 0) @@ -554,6 +553,7 @@ static int dt282x_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + const struct dt282x_board *board = comedi_board(dev); struct dt282x_private *devpriv = dev->private; int i; @@ -574,9 +574,9 @@ static int dt282x_ai_insn_read(struct comedi_device *dev, data[i] = inw(dev->iobase + - DT2821_ADDAT) & ((1 << boardtype.adbits) - 1); + DT2821_ADDAT) & ((1 << board->adbits) - 1); if (devpriv->ad_2scomp) - data[i] ^= (1 << (boardtype.adbits - 1)); + data[i] ^= (1 << (board->adbits - 1)); } return i; @@ -795,13 +795,14 @@ static int dt282x_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + const struct dt282x_board *board = comedi_board(dev); struct dt282x_private *devpriv = dev->private; short d; unsigned int chan; chan = CR_CHAN(insn->chanspec); d = data[0]; - d &= (1 << boardtype.dabits) - 1; + d &= (1 << board->dabits) - 1; devpriv->ao[chan] = d; devpriv->dacsr |= DT2821_SSEL; @@ -810,11 +811,11 @@ static int dt282x_ao_insn_write(struct comedi_device *dev, /* select channel */ devpriv->dacsr |= DT2821_YSEL; if (devpriv->da0_2scomp) - d ^= (1 << (boardtype.dabits - 1)); + d ^= (1 << (board->dabits - 1)); } else { devpriv->dacsr &= ~DT2821_YSEL; if (devpriv->da1_2scomp) - d ^= (1 << (boardtype.dabits - 1)); + d ^= (1 << (board->dabits - 1)); } outw(devpriv->dacsr, dev->iobase + DT2821_DACSR); @@ -1122,20 +1123,10 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) int i, irq; int ret; struct comedi_subdevice *s; - unsigned long iobase; - - dev->board_name = board->name; - iobase = it->options[opt_iobase]; - if (!iobase) - iobase = 0x240; - - printk(KERN_INFO "comedi%d: dt282x: 0x%04lx", dev->minor, iobase); - if (!request_region(iobase, DT2821_SIZE, "dt282x")) { - printk(KERN_INFO " I/O port conflict\n"); - return -EBUSY; - } - dev->iobase = iobase; + ret = comedi_request_region(dev, it->options[0], DT2821_SIZE); + if (ret) + return ret; outw(DT2821_BDINIT, dev->iobase + DT2821_SUPCSR); i = inw(dev->iobase + DT2821_ADCSR); @@ -1185,7 +1176,8 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) #endif if (irq > 0) { printk(KERN_INFO " ( irq = %d )", irq); - ret = request_irq(irq, dt282x_interrupt, 0, "dt282x", dev); + ret = request_irq(irq, dt282x_interrupt, 0, + dev->board_name, dev); if (ret < 0) { printk(KERN_ERR " failed to get irq\n"); return -EIO; @@ -1223,20 +1215,20 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->subdev_flags = SDF_READABLE | SDF_CMD_READ | ((it->options[opt_diff]) ? SDF_DIFF : SDF_COMMON); s->n_chan = - (it->options[opt_diff]) ? boardtype.adchan_di : boardtype.adchan_se; + (it->options[opt_diff]) ? board->adchan_di : board->adchan_se; s->insn_read = dt282x_ai_insn_read; s->do_cmdtest = dt282x_ai_cmdtest; s->do_cmd = dt282x_ai_cmd; s->cancel = dt282x_ai_cancel; - s->maxdata = (1 << boardtype.adbits) - 1; + s->maxdata = (1 << board->adbits) - 1; s->len_chanlist = 16; s->range_table = - opt_ai_range_lkup(boardtype.ispgl, it->options[opt_ai_range]); + opt_ai_range_lkup(board->ispgl, it->options[opt_ai_range]); devpriv->ad_2scomp = it->options[opt_ai_twos]; s = &dev->subdevices[1]; - s->n_chan = boardtype.dachan; + s->n_chan = board->dachan; if (s->n_chan) { /* ao subsystem */ s->type = COMEDI_SUBD_AO; @@ -1247,7 +1239,7 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->do_cmdtest = dt282x_ao_cmdtest; s->do_cmd = dt282x_ao_cmd; s->cancel = dt282x_ao_cancel; - s->maxdata = (1 << boardtype.dabits) - 1; + s->maxdata = (1 << board->dabits) - 1; s->len_chanlist = 2; s->range_table_list = devpriv->darangelist; devpriv->darangelist[0] = @@ -1279,10 +1271,6 @@ static void dt282x_detach(struct comedi_device *dev) { struct dt282x_private *devpriv = dev->private; - if (dev->irq) - free_irq(dev->irq, dev); - if (dev->iobase) - release_region(dev->iobase, DT2821_SIZE); if (dev->private) { if (devpriv->dma[0].chan) free_dma(devpriv->dma[0].chan); @@ -1293,6 +1281,7 @@ static void dt282x_detach(struct comedi_device *dev) if (devpriv->dma[1].buf) free_page((unsigned long)devpriv->dma[1].buf); } + comedi_legacy_detach(dev); } static const struct dt282x_board boardtypes[] = { diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 3ce499fa5db..7e03929c9a1 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -63,17 +63,6 @@ AO commands are not supported. #include "comedi_fc.h" -/* - * PCI device id's supported by this driver - */ -#define PCI_DEVICE_ID_DT3001 0x0022 -#define PCI_DEVICE_ID_DT3002 0x0023 -#define PCI_DEVICE_ID_DT3003 0x0024 -#define PCI_DEVICE_ID_DT3004 0x0025 -#define PCI_DEVICE_ID_DT3005 0x0026 -#define PCI_DEVICE_ID_DT3001_PGL 0x0027 -#define PCI_DEVICE_ID_DT3003_PGL 0x0028 - static const struct comedi_lrange range_dt3000_ai = { 4, { BIP_RANGE(10), @@ -92,9 +81,18 @@ static const struct comedi_lrange range_dt3000_ai_pgl = { } }; +enum dt3k_boardid { + BOARD_DT3001, + BOARD_DT3001_PGL, + BOARD_DT3002, + BOARD_DT3003, + BOARD_DT3003_PGL, + BOARD_DT3004, + BOARD_DT3005, +}; + struct dt3k_boardtype { const char *name; - unsigned int device_id; int adchan; int adbits; int ai_speed; @@ -104,61 +102,60 @@ struct dt3k_boardtype { }; static const struct dt3k_boardtype dt3k_boardtypes[] = { - { + [BOARD_DT3001] = { .name = "dt3001", - .device_id = PCI_DEVICE_ID_DT3001, .adchan = 16, .adbits = 12, .adrange = &range_dt3000_ai, .ai_speed = 3000, .dachan = 2, .dabits = 12, - }, { + }, + [BOARD_DT3001_PGL] = { .name = "dt3001-pgl", - .device_id = PCI_DEVICE_ID_DT3001_PGL, .adchan = 16, .adbits = 12, .adrange = &range_dt3000_ai_pgl, .ai_speed = 3000, .dachan = 2, .dabits = 12, - }, { + }, + [BOARD_DT3002] = { .name = "dt3002", - .device_id = PCI_DEVICE_ID_DT3002, .adchan = 32, .adbits = 12, .adrange = &range_dt3000_ai, .ai_speed = 3000, - }, { + }, + [BOARD_DT3003] = { .name = "dt3003", - .device_id = PCI_DEVICE_ID_DT3003, .adchan = 64, .adbits = 12, .adrange = &range_dt3000_ai, .ai_speed = 3000, .dachan = 2, .dabits = 12, - }, { + }, + [BOARD_DT3003_PGL] = { .name = "dt3003-pgl", - .device_id = PCI_DEVICE_ID_DT3003_PGL, .adchan = 64, .adbits = 12, .adrange = &range_dt3000_ai_pgl, .ai_speed = 3000, .dachan = 2, .dabits = 12, - }, { + }, + [BOARD_DT3004] = { .name = "dt3004", - .device_id = PCI_DEVICE_ID_DT3004, .adchan = 16, .adbits = 16, .adrange = &range_dt3000_ai, .ai_speed = 10000, .dachan = 2, .dabits = 12, - }, { + }, + [BOARD_DT3005] = { .name = "dt3005", /* a.k.a. 3004-200 */ - .device_id = PCI_DEVICE_ID_DT3005, .adchan = 16, .adbits = 16, .adrange = &range_dt3000_ai, @@ -168,8 +165,6 @@ static const struct dt3k_boardtype dt3k_boardtypes[] = { }, }; -#define DT3000_SIZE (4*0x1000) - /* dual-ported RAM location definitions */ #define DPR_DAC_buffer (4*0x000) @@ -716,31 +711,17 @@ static int dt3k_mem_insn_read(struct comedi_device *dev, return i; } -static const void *dt3000_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct dt3k_boardtype *this_board; - int i; - - for (i = 0; i < ARRAY_SIZE(dt3k_boardtypes); i++) { - this_board = &dt3k_boardtypes[i]; - if (this_board->device_id == pcidev->device) - return this_board; - } - return NULL; -} - static int dt3000_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct dt3k_boardtype *this_board; + const struct dt3k_boardtype *this_board = NULL; struct dt3k_private *devpriv; struct comedi_subdevice *s; - resource_size_t pci_base; int ret = 0; - this_board = dt3000_find_boardinfo(dev, pcidev); + if (context < ARRAY_SIZE(dt3k_boardtypes)) + this_board = &dt3k_boardtypes[context]; if (!this_board) return -ENODEV; dev->board_ptr = this_board; @@ -751,13 +732,11 @@ static int dt3000_auto_attach(struct comedi_device *dev, return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret < 0) return ret; - dev->iobase = 1; /* the "detach" needs this */ - pci_base = pci_resource_start(pcidev, 0); - devpriv->io_addr = ioremap(pci_base, DT3000_SIZE); + devpriv->io_addr = pci_ioremap_bar(pcidev, 0); if (!devpriv->io_addr) return -ENOMEM; @@ -830,7 +809,6 @@ static int dt3000_auto_attach(struct comedi_device *dev, static void dt3000_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct dt3k_private *devpriv = dev->private; if (dev->irq) @@ -839,10 +817,7 @@ static void dt3000_detach(struct comedi_device *dev) if (devpriv->io_addr) iounmap(devpriv->io_addr); } - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } + comedi_pci_disable(dev); } static struct comedi_driver dt3000_driver = { @@ -853,19 +828,19 @@ static struct comedi_driver dt3000_driver = { }; static int dt3000_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &dt3000_driver); + return comedi_pci_auto_config(dev, &dt3000_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(dt3000_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3001) }, - { PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3001_PGL) }, - { PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3002) }, - { PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3003) }, - { PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3003_PGL) }, - { PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3004) }, - { PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3005) }, + { PCI_VDEVICE(DT, 0x0022), BOARD_DT3001 }, + { PCI_VDEVICE(DT, 0x0023), BOARD_DT3002 }, + { PCI_VDEVICE(DT, 0x0024), BOARD_DT3003 }, + { PCI_VDEVICE(DT, 0x0025), BOARD_DT3004 }, + { PCI_VDEVICE(DT, 0x0026), BOARD_DT3005 }, + { PCI_VDEVICE(DT, 0x0027), BOARD_DT3001_PGL }, + { PCI_VDEVICE(DT, 0x0028), BOARD_DT3003_PGL }, { 0 } }; MODULE_DEVICE_TABLE(pci, dt3000_pci_table); diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index 192cf088f83..81eb5ed6ec9 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -303,26 +303,6 @@ struct slot_dt9812 { struct comedi_dt9812 *comedi; }; -static const struct comedi_lrange dt9812_10_ain_range = { 1, { - BIP_RANGE(10), - } -}; - -static const struct comedi_lrange dt9812_2pt5_ain_range = { 1, { - UNI_RANGE(2.5), - } -}; - -static const struct comedi_lrange dt9812_10_aout_range = { 1, { - BIP_RANGE(10), - } -}; - -static const struct comedi_lrange dt9812_2pt5_aout_range = { 1, { - UNI_RANGE(2.5), - } -}; - static struct slot_dt9812 dt9812[DT9812_NUM_SLOTS]; static inline struct usb_dt9812 *to_dt9812_dev(struct kref *d) @@ -912,12 +892,12 @@ static int dt9812_comedi_open(struct comedi_device *dev) switch (devpriv->slot->usb->device) { case 0:{ s->maxdata = 4095; - s->range_table = &dt9812_10_ain_range; + s->range_table = &range_bipolar10; } break; case 1:{ s->maxdata = 4095; - s->range_table = &dt9812_2pt5_ain_range; + s->range_table = &range_unipolar2_5; } break; } @@ -927,12 +907,12 @@ static int dt9812_comedi_open(struct comedi_device *dev) switch (devpriv->slot->usb->device) { case 0:{ s->maxdata = 4095; - s->range_table = &dt9812_10_aout_range; + s->range_table = &range_bipolar10; } break; case 1:{ s->maxdata = 4095; - s->range_table = &dt9812_2pt5_aout_range; + s->range_table = &range_unipolar2_5; } break; } @@ -947,12 +927,13 @@ static int dt9812_di_rinsn(struct comedi_device *dev, unsigned int *data) { struct comedi_dt9812 *devpriv = dev->private; + unsigned int channel = CR_CHAN(insn->chanspec); int n; u8 bits = 0; dt9812_digital_in(devpriv->slot, &bits); for (n = 0; n < insn->n; n++) - data[n] = ((1 << insn->chanspec) & bits) != 0; + data[n] = ((1 << channel) & bits) != 0; return n; } @@ -961,12 +942,13 @@ static int dt9812_do_winsn(struct comedi_device *dev, unsigned int *data) { struct comedi_dt9812 *devpriv = dev->private; + unsigned int channel = CR_CHAN(insn->chanspec); int n; u8 bits = 0; dt9812_digital_out_shadow(devpriv->slot, &bits); for (n = 0; n < insn->n; n++) { - u8 mask = 1 << insn->chanspec; + u8 mask = 1 << channel; bits &= ~mask; if (data[n]) @@ -981,13 +963,13 @@ static int dt9812_ai_rinsn(struct comedi_device *dev, unsigned int *data) { struct comedi_dt9812 *devpriv = dev->private; + unsigned int channel = CR_CHAN(insn->chanspec); int n; for (n = 0; n < insn->n; n++) { u16 value = 0; - dt9812_analog_in(devpriv->slot, insn->chanspec, &value, - DT9812_GAIN_1); + dt9812_analog_in(devpriv->slot, channel, &value, DT9812_GAIN_1); data[n] = value; } return n; @@ -998,12 +980,13 @@ static int dt9812_ao_rinsn(struct comedi_device *dev, unsigned int *data) { struct comedi_dt9812 *devpriv = dev->private; + unsigned int channel = CR_CHAN(insn->chanspec); int n; u16 value; for (n = 0; n < insn->n; n++) { value = 0; - dt9812_analog_out_shadow(devpriv->slot, insn->chanspec, &value); + dt9812_analog_out_shadow(devpriv->slot, channel, &value); data[n] = value; } return n; @@ -1014,10 +997,11 @@ static int dt9812_ao_winsn(struct comedi_device *dev, unsigned int *data) { struct comedi_dt9812 *devpriv = dev->private; + unsigned int channel = CR_CHAN(insn->chanspec); int n; for (n = 0; n < insn->n; n++) - dt9812_analog_out(devpriv->slot, insn->chanspec, data[n]); + dt9812_analog_out(devpriv->slot, channel, data[n]); return n; } @@ -1028,8 +1012,6 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; int ret; - dev->board_name = "dt9812"; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c index decc17f1867..93ec8e492cc 100644 --- a/drivers/staging/comedi/drivers/dyna_pci10xx.c +++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c @@ -187,14 +187,12 @@ static int dyna_pci10xx_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - dev->board_name = dev->driver->driver_name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pcidev, 2); @@ -254,15 +252,11 @@ static int dyna_pci10xx_auto_attach(struct comedi_device *dev, static void dyna_pci10xx_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct dyna_pci10xx_private *devpriv = dev->private; if (devpriv) mutex_destroy(&devpriv->mutex); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } + comedi_pci_disable(dev); } static struct comedi_driver dyna_pci10xx_driver = { @@ -273,9 +267,10 @@ static struct comedi_driver dyna_pci10xx_driver = { }; static int dyna_pci10xx_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &dyna_pci10xx_driver); + return comedi_pci_auto_config(dev, &dyna_pci10xx_driver, + id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(dyna_pci10xx_pci_table) = { diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c index 019c96eda6f..ff6f0bd7c86 100644 --- a/drivers/staging/comedi/drivers/fl512.c +++ b/drivers/staging/comedi/drivers/fl512.c @@ -111,31 +111,18 @@ static int fl512_ao_insn_readback(struct comedi_device *dev, static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct fl512_private *devpriv; - unsigned long iobase; - int ret; - - /* pointer to the subdevice: Analog in, Analog out, - (not made ->and Digital IO) */ struct comedi_subdevice *s; + int ret; - iobase = it->options[0]; - printk(KERN_INFO "comedi:%d fl512: 0x%04lx", dev->minor, iobase); - if (!request_region(iobase, FL512_SIZE, "fl512")) { - printk(KERN_WARNING " I/O port conflict\n"); - return -EIO; - } - dev->iobase = iobase; - dev->board_name = "fl512"; + ret = comedi_request_region(dev, it->options[0], FL512_SIZE); + if (ret) + return ret; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; -#if DEBUG - printk(KERN_DEBUG "malloc ok\n"); -#endif - ret = comedi_alloc_subdevices(dev, 2); if (ret) return ret; @@ -157,7 +144,6 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->range_table = &range_fl512; /* function to call when read AD */ s->insn_read = fl512_ai_insn; - printk(KERN_INFO "comedi: fl512: subdevice 0 initialized\n"); /* Analog output */ s = &dev->subdevices[1]; @@ -175,22 +161,15 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_write = fl512_ao_insn; /* function to call when reading DA */ s->insn_read = fl512_ao_insn_readback; - printk(KERN_INFO "comedi: fl512: subdevice 1 initialized\n"); return 1; } -static void fl512_detach(struct comedi_device *dev) -{ - if (dev->iobase) - release_region(dev->iobase, FL512_SIZE); -} - static struct comedi_driver fl512_driver = { .driver_name = "fl512", .module = THIS_MODULE, .attach = fl512_attach, - .detach = fl512_detach, + .detach = comedi_legacy_detach, }; module_comedi_driver(fl512_driver); diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index b60c9756267..0c061df0978 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -78,12 +78,6 @@ static int dio_config_block_size(struct comedi_device *dev, unsigned int *data); #define NUM_DMA_BUFFERS 4 #define NUM_DMA_DESCRIPTORS 256 -/* indices of base address regions */ -enum base_address_regions { - PLX9080_BADDRINDEX = 0, - HPDI_BADDRINDEX = 2, -}; - enum hpdi_registers { FIRMWARE_REV_REG = 0x0, BOARD_CONTROL_REG = 0x4, @@ -499,20 +493,13 @@ static int hpdi_auto_attach(struct comedi_device *dev, return -ENOMEM; dev->private = devpriv; - if (comedi_pci_enable(pcidev, dev->board_name)) { - dev_warn(dev->class_dev, - "failed enable PCI device and request regions\n"); - return -EIO; - } - dev->iobase = 1; /* the "detach" needs this */ + retval = comedi_pci_enable(dev); + if (retval) + return retval; pci_set_master(pcidev); - devpriv->plx9080_iobase = - ioremap(pci_resource_start(pcidev, PLX9080_BADDRINDEX), - pci_resource_len(pcidev, PLX9080_BADDRINDEX)); - devpriv->hpdi_iobase = - ioremap(pci_resource_start(pcidev, HPDI_BADDRINDEX), - pci_resource_len(pcidev, HPDI_BADDRINDEX)); + devpriv->plx9080_iobase = pci_ioremap_bar(pcidev, 0); + devpriv->hpdi_iobase = pci_ioremap_bar(pcidev, 2); if (!devpriv->plx9080_iobase || !devpriv->hpdi_iobase) { dev_warn(dev->class_dev, "failed to remap io memory\n"); return -ENOMEM; @@ -596,9 +583,8 @@ static void hpdi_detach(struct comedi_device *dev) NUM_DMA_DESCRIPTORS, devpriv->dma_desc, devpriv->dma_desc_phys_addr); - if (dev->iobase) - comedi_pci_disable(pcidev); } + comedi_pci_disable(dev); } static int dio_config_block_size(struct comedi_device *dev, unsigned int *data) @@ -943,9 +929,9 @@ static struct comedi_driver gsc_hpdi_driver = { }; static int gsc_hpdi_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &gsc_hpdi_driver); + return comedi_pci_auto_config(dev, &gsc_hpdi_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(gsc_hpdi_pci_table) = { diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index 1e08f9141fa..08ab9d6e719 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -68,8 +68,6 @@ Configuration options: not applicable, uses PCI auto config #define ICP_MULTI_CNTR2 0x14 /* R/W: Counter 2 */ #define ICP_MULTI_CNTR3 0x16 /* R/W: Counter 3 */ -#define ICP_MULTI_SIZE 0x20 /* 32 bytes */ - /* Define bits from ADC command/status register */ #define ADC_ST 0x0001 /* Start ADC */ #define ADC_BSY 0x0001 /* ADC busy */ @@ -120,7 +118,7 @@ struct icp_multi_private { unsigned int DacCmdStatus; /* DAC Command/Status register */ unsigned int IntEnable; /* Interrupt Enable register */ unsigned int IntStatus; /* Interrupt Status register */ - unsigned int act_chanlist[32]; /* list of scaned channel */ + unsigned int act_chanlist[32]; /* list of scanned channel */ unsigned char act_chanlist_len; /* len of scanlist */ unsigned char act_chanlist_pos; /* actual position in MUX list */ unsigned int *ai_chanlist; /* actaul chanlist */ @@ -500,23 +498,18 @@ static int icp_multi_auto_attach(struct comedi_device *dev, struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct icp_multi_private *devpriv; struct comedi_subdevice *s; - resource_size_t iobase; int ret; - dev->board_name = dev->driver->driver_name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; - iobase = pci_resource_start(pcidev, 2); - dev->iobase = iobase; - devpriv->io_addr = ioremap(iobase, ICP_MULTI_SIZE); + devpriv->io_addr = pci_ioremap_bar(pcidev, 2); if (!devpriv->io_addr) return -ENOMEM; @@ -594,7 +587,6 @@ static int icp_multi_auto_attach(struct comedi_device *dev, static void icp_multi_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct icp_multi_private *devpriv = dev->private; if (devpriv) @@ -604,10 +596,7 @@ static void icp_multi_detach(struct comedi_device *dev) free_irq(dev->irq, dev); if (devpriv && devpriv->io_addr) iounmap(devpriv->io_addr); - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } + comedi_pci_disable(dev); } static struct comedi_driver icp_multi_driver = { @@ -618,9 +607,9 @@ static struct comedi_driver icp_multi_driver = { }; static int icp_multi_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &icp_multi_driver); + return comedi_pci_auto_config(dev, &icp_multi_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(icp_multi_pci_table) = { diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 93584e2be35..ee7537daf47 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -77,9 +77,6 @@ options for PCI-20341M: 3 200 */ -/* XXX needs to use ioremap() for compatibility with 2.4 kernels. Should also - * check_mem_region() etc. - fmhess */ - #include "../comedidev.h" #define PCI20000_ID 0x1d @@ -212,7 +209,6 @@ static int pci20xxx_attach(struct comedi_device *dev, dev->private = devpriv; devpriv->ioaddr = (void __iomem *)(unsigned long)it->options[0]; - dev->board_name = "pci20kc"; /* Check PCI-20001 C-2A Carrier Board ID */ if ((readb(devpriv->ioaddr) & PCI20000_ID) != PCI20000_ID) { diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index 17ba75e0ab8..90b303ab230 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -700,16 +700,12 @@ static int jr3_pci_auto_attach(struct comedi_device *dev, return -EINVAL; break; } - dev->board_name = "jr3_pci"; - result = comedi_pci_enable(pcidev, "jr3_pci"); - if (result < 0) + result = comedi_pci_enable(dev); + if (result) return result; - dev->iobase = 1; /* the "detach" needs this */ - devpriv->iobase = ioremap(pci_resource_start(pcidev, 0), - offsetof(struct jr3_t, - channel[devpriv->n_channels])); + devpriv->iobase = pci_ioremap_bar(pcidev, 0); if (!devpriv->iobase) return -ENOMEM; @@ -816,7 +812,6 @@ static int jr3_pci_auto_attach(struct comedi_device *dev, static void jr3_pci_detach(struct comedi_device *dev) { int i; - struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct jr3_pci_dev_private *devpriv = dev->private; if (devpriv) { @@ -828,9 +823,8 @@ static void jr3_pci_detach(struct comedi_device *dev) } if (devpriv->iobase) iounmap(devpriv->iobase); - if (dev->iobase) - comedi_pci_disable(pcidev); } + comedi_pci_disable(dev); } static struct comedi_driver jr3_pci_driver = { @@ -841,9 +835,9 @@ static struct comedi_driver jr3_pci_driver = { }; static int jr3_pci_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &jr3_pci_driver); + return comedi_pci_auto_config(dev, &jr3_pci_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(jr3_pci_pci_table) = { diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c index 8c09c026508..e0e64752e31 100644 --- a/drivers/staging/comedi/drivers/ke_counter.c +++ b/drivers/staging/comedi/drivers/ke_counter.c @@ -96,9 +96,7 @@ static int cnt_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - dev->board_name = dev->driver->driver_name; - - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pcidev, 0); @@ -131,27 +129,18 @@ static int cnt_auto_attach(struct comedi_device *dev, return 0; } -static void cnt_detach(struct comedi_device *dev) -{ - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } -} - static struct comedi_driver ke_counter_driver = { .driver_name = "ke_counter", .module = THIS_MODULE, .auto_attach = cnt_auto_attach, - .detach = cnt_detach, + .detach = comedi_pci_disable, }; static int ke_counter_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &ke_counter_driver); + return comedi_pci_auto_config(dev, &ke_counter_driver, + id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(ke_counter_pci_table) = { diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index b766bb93efd..641e693d5d0 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -55,26 +55,13 @@ broken. #include "comedi_fc.h" #include "8253.h" +#include "plx9052.h" #if 0 /* file removed due to GPL incompatibility */ #include "me4000_fw.h" #endif -#define PCI_DEVICE_ID_MEILHAUS_ME4650 0x4650 -#define PCI_DEVICE_ID_MEILHAUS_ME4660 0x4660 -#define PCI_DEVICE_ID_MEILHAUS_ME4660I 0x4661 -#define PCI_DEVICE_ID_MEILHAUS_ME4660S 0x4662 -#define PCI_DEVICE_ID_MEILHAUS_ME4660IS 0x4663 -#define PCI_DEVICE_ID_MEILHAUS_ME4670 0x4670 -#define PCI_DEVICE_ID_MEILHAUS_ME4670I 0x4671 -#define PCI_DEVICE_ID_MEILHAUS_ME4670S 0x4672 -#define PCI_DEVICE_ID_MEILHAUS_ME4670IS 0x4673 -#define PCI_DEVICE_ID_MEILHAUS_ME4680 0x4680 -#define PCI_DEVICE_ID_MEILHAUS_ME4680I 0x4681 -#define PCI_DEVICE_ID_MEILHAUS_ME4680S 0x4682 -#define PCI_DEVICE_ID_MEILHAUS_ME4680IS 0x4683 - /* * ME4000 Register map and bit defines */ @@ -183,28 +170,6 @@ broken. #define ME4000_AO_DEMUX_ADJUST_VALUE 0x4c #define ME4000_AI_SAMPLE_COUNTER_REG 0xc0 -/* - * PLX Register map and bit defines - */ -#define PLX_INTCSR 0x4c -#define PLX_INTCSR_LOCAL_INT1_EN (1 << 0) -#define PLX_INTCSR_LOCAL_INT1_POL (1 << 1) -#define PLX_INTCSR_LOCAL_INT1_STATE (1 << 2) -#define PLX_INTCSR_LOCAL_INT2_EN (1 << 3) -#define PLX_INTCSR_LOCAL_INT2_POL (1 << 4) -#define PLX_INTCSR_LOCAL_INT2_STATE (1 << 5) -#define PLX_INTCSR_PCI_INT_EN (1 << 6) -#define PLX_INTCSR_SOFT_INT (1 << 7) -#define PLX_ICR 0x50 -#define PLX_ICR_BIT_EEPROM_CLOCK_SET (1 << 24) -#define PLX_ICR_BIT_EEPROM_CHIP_SELECT (1 << 25) -#define PLX_ICR_BIT_EEPROM_WRITE (1 << 26) -#define PLX_ICR_BIT_EEPROM_READ (1 << 27) -#define PLX_ICR_BIT_EEPROM_VALID (1 << 28) -#define PLX_ICR_MASK_EEPROM (0x1f << 24) - -#define EEPROM_DELAY 1 - #define ME4000_AI_FIFO_COUNT 2048 #define ME4000_AI_MIN_TICKS 66 @@ -220,9 +185,24 @@ struct me4000_info { unsigned int ao_readback[4]; }; +enum me4000_boardid { + BOARD_ME4650, + BOARD_ME4660, + BOARD_ME4660I, + BOARD_ME4660S, + BOARD_ME4660IS, + BOARD_ME4670, + BOARD_ME4670I, + BOARD_ME4670S, + BOARD_ME4670IS, + BOARD_ME4680, + BOARD_ME4680I, + BOARD_ME4680S, + BOARD_ME4680IS, +}; + struct me4000_board { const char *name; - unsigned short device_id; int ao_nchan; int ao_fifo; int ai_nchan; @@ -234,62 +214,61 @@ struct me4000_board { }; static const struct me4000_board me4000_boards[] = { - { + [BOARD_ME4650] = { .name = "ME-4650", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4650, .ai_nchan = 16, .dio_nchan = 32, - }, { + }, + [BOARD_ME4660] = { .name = "ME-4660", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660, .ai_nchan = 32, .ai_diff_nchan = 16, .dio_nchan = 32, .has_counter = 1, - }, { + }, + [BOARD_ME4660I] = { .name = "ME-4660i", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660I, .ai_nchan = 32, .ai_diff_nchan = 16, .dio_nchan = 32, .has_counter = 1, - }, { + }, + [BOARD_ME4660S] = { .name = "ME-4660s", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660S, .ai_nchan = 32, .ai_diff_nchan = 16, .ai_sh_nchan = 8, .dio_nchan = 32, .has_counter = 1, - }, { + }, + [BOARD_ME4660IS] = { .name = "ME-4660is", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660IS, .ai_nchan = 32, .ai_diff_nchan = 16, .ai_sh_nchan = 8, .dio_nchan = 32, .has_counter = 1, - }, { + }, + [BOARD_ME4670] = { .name = "ME-4670", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670, .ao_nchan = 4, .ai_nchan = 32, .ai_diff_nchan = 16, .ex_trig_analog = 1, .dio_nchan = 32, .has_counter = 1, - }, { + }, + [BOARD_ME4670I] = { .name = "ME-4670i", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670I, .ao_nchan = 4, .ai_nchan = 32, .ai_diff_nchan = 16, .ex_trig_analog = 1, .dio_nchan = 32, .has_counter = 1, - }, { + }, + [BOARD_ME4670S] = { .name = "ME-4670s", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670S, .ao_nchan = 4, .ai_nchan = 32, .ai_diff_nchan = 16, @@ -297,9 +276,9 @@ static const struct me4000_board me4000_boards[] = { .ex_trig_analog = 1, .dio_nchan = 32, .has_counter = 1, - }, { + }, + [BOARD_ME4670IS] = { .name = "ME-4670is", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670IS, .ao_nchan = 4, .ai_nchan = 32, .ai_diff_nchan = 16, @@ -307,9 +286,9 @@ static const struct me4000_board me4000_boards[] = { .ex_trig_analog = 1, .dio_nchan = 32, .has_counter = 1, - }, { + }, + [BOARD_ME4680] = { .name = "ME-4680", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680, .ao_nchan = 4, .ao_fifo = 4, .ai_nchan = 32, @@ -317,9 +296,9 @@ static const struct me4000_board me4000_boards[] = { .ex_trig_analog = 1, .dio_nchan = 32, .has_counter = 1, - }, { + }, + [BOARD_ME4680I] = { .name = "ME-4680i", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680I, .ao_nchan = 4, .ao_fifo = 4, .ai_nchan = 32, @@ -327,9 +306,9 @@ static const struct me4000_board me4000_boards[] = { .ex_trig_analog = 1, .dio_nchan = 32, .has_counter = 1, - }, { + }, + [BOARD_ME4680S] = { .name = "ME-4680s", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680S, .ao_nchan = 4, .ao_fifo = 4, .ai_nchan = 32, @@ -338,9 +317,9 @@ static const struct me4000_board me4000_boards[] = { .ex_trig_analog = 1, .dio_nchan = 32, .has_counter = 1, - }, { + }, + [BOARD_ME4680IS] = { .name = "ME-4680is", - .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680IS, .ao_nchan = 4, .ao_fifo = 4, .ai_nchan = 32, @@ -376,6 +355,7 @@ static int xilinx_download(struct comedi_device *dev) wait_queue_head_t queue; int idx = 0; int size = 0; + unsigned int intcsr; if (!xilinx_iobase) return -ENODEV; @@ -386,27 +366,28 @@ static int xilinx_download(struct comedi_device *dev) * Set PLX local interrupt 2 polarity to high. * Interrupt is thrown by init pin of xilinx. */ - outl(0x10, info->plx_regbase + PLX_INTCSR); + outl(PLX9052_INTCSR_LI2POL, info->plx_regbase + PLX9052_INTCSR); /* Set /CS and /WRITE of the Xilinx */ - value = inl(info->plx_regbase + PLX_ICR); - value |= 0x100; - outl(value, info->plx_regbase + PLX_ICR); + value = inl(info->plx_regbase + PLX9052_CNTRL); + value |= PLX9052_CNTRL_UIO2_DATA; + outl(value, info->plx_regbase + PLX9052_CNTRL); /* Init Xilinx with CS1 */ inb(xilinx_iobase + 0xC8); /* Wait until /INIT pin is set */ udelay(20); - if (!(inl(info->plx_regbase + PLX_INTCSR) & 0x20)) { + intcsr = inl(info->plx_regbase + PLX9052_INTCSR); + if (!(intcsr & PLX9052_INTCSR_LI2STAT)) { dev_err(dev->class_dev, "Can't init Xilinx\n"); return -EIO; } /* Reset /CS and /WRITE of the Xilinx */ - value = inl(info->plx_regbase + PLX_ICR); - value &= ~0x100; - outl(value, info->plx_regbase + PLX_ICR); + value = inl(info->plx_regbase + PLX9052_CNTRL); + value &= ~PLX9052_CNTRL_UIO2_DATA; + outl(value, info->plx_regbase + PLX9052_CNTRL); if (FIRMWARE_NOT_AVAILABLE) { dev_err(dev->class_dev, "xilinx firmware unavailable due to licensing, aborting"); @@ -422,7 +403,7 @@ static int xilinx_download(struct comedi_device *dev) udelay(10); /* Check if BUSY flag is low */ - if (inl(info->plx_regbase + PLX_ICR) & 0x20) { + if (inl(info->plx_regbase + PLX9052_CNTRL) & PLX9052_CNTRL_UIO1_DATA) { dev_err(dev->class_dev, "Xilinx is still busy (idx = %d)\n", idx); @@ -432,7 +413,7 @@ static int xilinx_download(struct comedi_device *dev) } /* If done flag is high download was successful */ - if (inl(info->plx_regbase + PLX_ICR) & 0x4) { + if (inl(info->plx_regbase + PLX9052_CNTRL) & PLX9052_CNTRL_UIO0_DATA) { } else { dev_err(dev->class_dev, "DONE flag is not set\n"); dev_err(dev->class_dev, "Download not successful\n"); @@ -440,9 +421,9 @@ static int xilinx_download(struct comedi_device *dev) } /* Set /CS and /WRITE */ - value = inl(info->plx_regbase + PLX_ICR); - value |= 0x100; - outl(value, info->plx_regbase + PLX_ICR); + value = inl(info->plx_regbase + PLX9052_CNTRL); + value |= PLX9052_CNTRL_UIO2_DATA; + outl(value, info->plx_regbase + PLX9052_CNTRL); return 0; } @@ -454,11 +435,11 @@ static void me4000_reset(struct comedi_device *dev) int chan; /* Make a hardware reset */ - val = inl(info->plx_regbase + PLX_ICR); - val |= 0x40000000; - outl(val, info->plx_regbase + PLX_ICR); - val &= ~0x40000000; - outl(val , info->plx_regbase + PLX_ICR); + val = inl(info->plx_regbase + PLX9052_CNTRL); + val |= PLX9052_CNTRL_PCI_RESET; + outl(val, info->plx_regbase + PLX9052_CNTRL); + val &= ~PLX9052_CNTRL_PCI_RESET; + outl(val , info->plx_regbase + PLX9052_CNTRL); /* 0x8000 to the DACs means an output voltage of 0V */ for (chan = 0; chan < 4; chan++) @@ -474,7 +455,9 @@ static void me4000_reset(struct comedi_device *dev) outl(val, dev->iobase + ME4000_AO_CTRL_REG(chan)); /* Enable interrupts on the PLX */ - outl(0x43, info->plx_regbase + PLX_INTCSR); + outl(PLX9052_INTCSR_LI1ENAB | + PLX9052_INTCSR_LI1POL | + PLX9052_INTCSR_PCIENAB, info->plx_regbase + PLX9052_INTCSR); /* Set the adustment register for AO demux */ outl(ME4000_AO_DEMUX_ADJUST_VALUE, @@ -1550,30 +1533,17 @@ static int me4000_cnt_insn_write(struct comedi_device *dev, return 1; } -static const void *me4000_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct me4000_board *thisboard; - int i; - - for (i = 0; i < ARRAY_SIZE(me4000_boards); i++) { - thisboard = &me4000_boards[i]; - if (thisboard->device_id == pcidev->device) - return thisboard; - } - return NULL; -} - static int me4000_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct me4000_board *thisboard; + const struct me4000_board *thisboard = NULL; struct me4000_info *info; struct comedi_subdevice *s; int result; - thisboard = me4000_find_boardinfo(dev, pcidev); + if (context < ARRAY_SIZE(me4000_boards)) + thisboard = &me4000_boards[context]; if (!thisboard) return -ENODEV; dev->board_ptr = thisboard; @@ -1584,7 +1554,7 @@ static int me4000_auto_attach(struct comedi_device *dev, return -ENOMEM; dev->private = info; - result = comedi_pci_enable(pcidev, dev->board_name); + result = comedi_pci_enable(dev); if (result) return result; @@ -1710,16 +1680,11 @@ static int me4000_auto_attach(struct comedi_device *dev, static void me4000_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (dev->irq) free_irq(dev->irq, dev); - if (pcidev) { - if (dev->iobase) { - me4000_reset(dev); - comedi_pci_disable(pcidev); - } - } + if (dev->iobase) + me4000_reset(dev); + comedi_pci_disable(dev); } static struct comedi_driver me4000_driver = { @@ -1730,26 +1695,26 @@ static struct comedi_driver me4000_driver = { }; static int me4000_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &me4000_driver); + return comedi_pci_auto_config(dev, &me4000_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = { - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4650)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660I)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660S)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660IS)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670I)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670S)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670IS)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680I)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680S)}, - {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680IS)}, - {0} + { PCI_VDEVICE(MEILHAUS, 0x4650), BOARD_ME4650 }, + { PCI_VDEVICE(MEILHAUS, 0x4660), BOARD_ME4660 }, + { PCI_VDEVICE(MEILHAUS, 0x4661), BOARD_ME4660I }, + { PCI_VDEVICE(MEILHAUS, 0x4662), BOARD_ME4660S }, + { PCI_VDEVICE(MEILHAUS, 0x4663), BOARD_ME4660IS }, + { PCI_VDEVICE(MEILHAUS, 0x4670), BOARD_ME4670 }, + { PCI_VDEVICE(MEILHAUS, 0x4671), BOARD_ME4670I }, + { PCI_VDEVICE(MEILHAUS, 0x4672), BOARD_ME4670S }, + { PCI_VDEVICE(MEILHAUS, 0x4673), BOARD_ME4670IS }, + { PCI_VDEVICE(MEILHAUS, 0x4680), BOARD_ME4680 }, + { PCI_VDEVICE(MEILHAUS, 0x4681), BOARD_ME4680I }, + { PCI_VDEVICE(MEILHAUS, 0x4682), BOARD_ME4680S }, + { PCI_VDEVICE(MEILHAUS, 0x4683), BOARD_ME4680IS }, + { 0 } }; MODULE_DEVICE_TABLE(pci, me4000_pci_table); diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index 06490ebc8cc..09f2a9feaf7 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -41,12 +41,10 @@ #include "../comedidev.h" -#define ME2600_FIRMWARE "me2600_firmware.bin" +#include "plx9052.h" -#define ME2000_DEVICE_ID 0x2000 -#define ME2600_DEVICE_ID 0x2600 +#define ME2600_FIRMWARE "me2600_firmware.bin" -#define PLX_INTCSR 0x4C /* PLX interrupt status register */ #define XILINX_DOWNLOAD_RESET 0x42 /* Xilinx registers */ #define ME_CONTROL_1 0x0000 /* - | W */ @@ -149,21 +147,26 @@ static const struct comedi_lrange me_ao_range = { } }; +enum me_boardid { + BOARD_ME2600, + BOARD_ME2000, +}; + struct me_board { const char *name; - int device_id; + int needs_firmware; int has_ao; }; static const struct me_board me_boards[] = { - { + [BOARD_ME2600] = { .name = "me-2600i", - .device_id = ME2600_DEVICE_ID, + .needs_firmware = 1, .has_ao = 1, - }, { + }, + [BOARD_ME2000] = { .name = "me-2000i", - .device_id = ME2000_DEVICE_ID, - } + }, }; struct me_private_data { @@ -396,7 +399,7 @@ static int me2600_xilinx_download(struct comedi_device *dev, unsigned int i; /* disable irq's on PLX */ - writel(0x00, dev_private->plx_regbase + PLX_INTCSR); + 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); @@ -426,7 +429,7 @@ static int me2600_xilinx_download(struct comedi_device *dev, /* * Loop for writing firmware byte by byte to xilinx - * Firmware data start at offfset 16 + * Firmware data start at offset 16 */ for (i = 0; i < file_length; i++) writeb((data[16 + i] & 0xff), @@ -437,10 +440,10 @@ static int me2600_xilinx_download(struct comedi_device *dev, writeb(0x00, dev_private->me_regbase + 0x0); /* Test if there was an error during download -> INTB was thrown */ - value = readl(dev_private->plx_regbase + PLX_INTCSR); - if (value & 0x20) { + value = readl(dev_private->plx_regbase + PLX9052_INTCSR); + if (value & PLX9052_INTCSR_LI2STAT) { /* Disable interrupt */ - writel(0x00, dev_private->plx_regbase + PLX_INTCSR); + writel(0x00, dev_private->plx_regbase + PLX9052_INTCSR); dev_err(dev->class_dev, "Xilinx download failed\n"); return -EIO; } @@ -449,7 +452,10 @@ static int me2600_xilinx_download(struct comedi_device *dev, sleep(1); /* Enable PLX-Interrupts */ - writel(0x43, dev_private->plx_regbase + PLX_INTCSR); + writel(PLX9052_INTCSR_LI1ENAB | + PLX9052_INTCSR_LI1POL | + PLX9052_INTCSR_PCIENAB, + dev_private->plx_regbase + PLX9052_INTCSR); return 0; } @@ -488,30 +494,17 @@ static int me_reset(struct comedi_device *dev) return 0; } -static const void *me_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct me_board *board; - int i; - - for (i = 0; i < ARRAY_SIZE(me_boards); i++) { - board = &me_boards[i]; - if (board->device_id == pcidev->device) - return board; - } - return NULL; -} - static int me_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct me_board *board; + const struct me_board *board = NULL; struct me_private_data *dev_private; struct comedi_subdevice *s; int ret; - board = me_find_boardinfo(dev, pcidev); + if (context < ARRAY_SIZE(me_boards)) + board = &me_boards[context]; if (!board) return -ENODEV; dev->board_ptr = board; @@ -522,23 +515,20 @@ static int me_auto_attach(struct comedi_device *dev, return -ENOMEM; dev->private = dev_private; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; - dev->iobase = 1; /* detach needs this */ - dev_private->plx_regbase = ioremap(pci_resource_start(pcidev, 0), - pci_resource_len(pcidev, 0)); + dev_private->plx_regbase = pci_ioremap_bar(pcidev, 0); if (!dev_private->plx_regbase) return -ENOMEM; - dev_private->me_regbase = ioremap(pci_resource_start(pcidev, 2), - pci_resource_len(pcidev, 2)); + dev_private->me_regbase = pci_ioremap_bar(pcidev, 2); if (!dev_private->me_regbase) return -ENOMEM; /* Download firmware and reset card */ - if (board->device_id == ME2600_DEVICE_ID) { + if (board->needs_firmware) { ret = me2600_upload_firmware(dev); if (ret < 0) return ret; @@ -591,7 +581,6 @@ static int me_auto_attach(struct comedi_device *dev, static void me_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct me_private_data *dev_private = dev->private; if (dev_private) { @@ -602,10 +591,7 @@ static void me_detach(struct comedi_device *dev) if (dev_private->plx_regbase) iounmap(dev_private->plx_regbase); } - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } + comedi_pci_disable(dev); } static struct comedi_driver me_daq_driver = { @@ -616,14 +602,14 @@ static struct comedi_driver me_daq_driver = { }; static int me_daq_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &me_daq_driver); + return comedi_pci_auto_config(dev, &me_daq_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(me_daq_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, ME2600_DEVICE_ID) }, - { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, ME2000_DEVICE_ID) }, + { PCI_VDEVICE(MEILHAUS, 0x2600), BOARD_ME2600 }, + { PCI_VDEVICE(MEILHAUS, 0x2000), BOARD_ME2000 }, { 0 } }; MODULE_DEVICE_TABLE(pci, me_daq_pci_table); diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index be2c15f8461..523c6564ffc 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -58,10 +58,6 @@ #include "comedi_fc.h" #include "mite.h" -#define PCI_MITE_SIZE 4096 -#define PCI_DAQ_SIZE 4096 -#define PCI_DAQ_SIZE_660X 8192 - #define TOP_OF_PAGE(x) ((x)|(~(PAGE_MASK))) struct mite_struct *mite_alloc(struct pci_dev *pcidev) @@ -81,7 +77,7 @@ struct mite_struct *mite_alloc(struct pci_dev *pcidev) } return mite; } -EXPORT_SYMBOL(mite_alloc); +EXPORT_SYMBOL_GPL(mite_alloc); static void dump_chip_signature(u32 csigr_bits) { @@ -104,40 +100,28 @@ static unsigned mite_fifo_size(struct mite_struct *mite, unsigned channel) int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1) { unsigned long length; - resource_size_t addr; int i; u32 csigr_bits; unsigned unknown_dma_burst_bits; - if (comedi_pci_enable(mite->pcidev, "mite")) { - dev_err(&mite->pcidev->dev, - "error enabling mite and requesting io regions\n"); - return -EIO; - } pci_set_master(mite->pcidev); - addr = pci_resource_start(mite->pcidev, 0); - mite->mite_phys_addr = addr; - mite->mite_io_addr = ioremap(addr, PCI_MITE_SIZE); + mite->mite_io_addr = pci_ioremap_bar(mite->pcidev, 0); if (!mite->mite_io_addr) { dev_err(&mite->pcidev->dev, "Failed to remap mite io memory address\n"); return -ENOMEM; } + mite->mite_phys_addr = pci_resource_start(mite->pcidev, 0); - addr = pci_resource_start(mite->pcidev, 1); - mite->daq_phys_addr = addr; - length = pci_resource_len(mite->pcidev, 1); - /* - * In case of a 660x board, DAQ size is 8k instead of 4k - * (see as shown by lspci output) - */ - mite->daq_io_addr = ioremap(mite->daq_phys_addr, length); + mite->daq_io_addr = pci_ioremap_bar(mite->pcidev, 1); if (!mite->daq_io_addr) { dev_err(&mite->pcidev->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) { writel(0, mite->mite_io_addr + MITE_IODWBSR); @@ -185,13 +169,13 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1) dev_info(&mite->pcidev->dev, "fifo size is %i.\n", mite->fifo_size); return 0; } -EXPORT_SYMBOL(mite_setup2); +EXPORT_SYMBOL_GPL(mite_setup2); int mite_setup(struct mite_struct *mite) { return mite_setup2(mite, 0); } -EXPORT_SYMBOL(mite_setup); +EXPORT_SYMBOL_GPL(mite_setup); void mite_unsetup(struct mite_struct *mite) { @@ -208,12 +192,10 @@ void mite_unsetup(struct mite_struct *mite) iounmap(mite->daq_io_addr); mite->daq_io_addr = NULL; } - if (mite->mite_phys_addr) { - comedi_pci_disable(mite->pcidev); + if (mite->mite_phys_addr) mite->mite_phys_addr = 0; - } } -EXPORT_SYMBOL(mite_unsetup); +EXPORT_SYMBOL_GPL(mite_unsetup); struct mite_dma_descriptor_ring *mite_alloc_ring(struct mite_struct *mite) { @@ -232,7 +214,7 @@ struct mite_dma_descriptor_ring *mite_alloc_ring(struct mite_struct *mite) ring->descriptors_dma_addr = 0; return ring; }; -EXPORT_SYMBOL(mite_alloc_ring); +EXPORT_SYMBOL_GPL(mite_alloc_ring); void mite_free_ring(struct mite_dma_descriptor_ring *ring) { @@ -248,7 +230,7 @@ void mite_free_ring(struct mite_dma_descriptor_ring *ring) kfree(ring); } }; -EXPORT_SYMBOL(mite_free_ring); +EXPORT_SYMBOL_GPL(mite_free_ring); struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite, struct @@ -275,7 +257,7 @@ struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite, spin_unlock_irqrestore(&mite->lock, flags); return channel; } -EXPORT_SYMBOL(mite_request_channel_in_range); +EXPORT_SYMBOL_GPL(mite_request_channel_in_range); void mite_release_channel(struct mite_channel *mite_chan) { @@ -302,7 +284,7 @@ void mite_release_channel(struct mite_channel *mite_chan) } spin_unlock_irqrestore(&mite->lock, flags); } -EXPORT_SYMBOL(mite_release_channel); +EXPORT_SYMBOL_GPL(mite_release_channel); void mite_dma_arm(struct mite_channel *mite_chan) { @@ -325,7 +307,7 @@ void mite_dma_arm(struct mite_channel *mite_chan) spin_unlock_irqrestore(&mite->lock, flags); /* mite_dma_tcr(mite, channel); */ } -EXPORT_SYMBOL(mite_dma_arm); +EXPORT_SYMBOL_GPL(mite_dma_arm); /**************************************/ @@ -382,7 +364,7 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring, smp_wmb(); return 0; } -EXPORT_SYMBOL(mite_buf_change); +EXPORT_SYMBOL_GPL(mite_buf_change); void mite_prep_dma(struct mite_channel *mite_chan, unsigned int num_device_bits, unsigned int num_memory_bits) @@ -473,7 +455,7 @@ void mite_prep_dma(struct mite_channel *mite_chan, MDPRINTK("exit mite_prep_dma\n"); } -EXPORT_SYMBOL(mite_prep_dma); +EXPORT_SYMBOL_GPL(mite_prep_dma); static u32 mite_device_bytes_transferred(struct mite_channel *mite_chan) { @@ -487,7 +469,7 @@ u32 mite_bytes_in_transit(struct mite_channel *mite_chan) return readl(mite->mite_io_addr + MITE_FCR(mite_chan->channel)) & 0x000000FF; } -EXPORT_SYMBOL(mite_bytes_in_transit); +EXPORT_SYMBOL_GPL(mite_bytes_in_transit); /* returns lower bound for number of bytes transferred from device to memory */ u32 mite_bytes_written_to_memory_lb(struct mite_channel *mite_chan) @@ -497,7 +479,7 @@ u32 mite_bytes_written_to_memory_lb(struct mite_channel *mite_chan) device_byte_count = mite_device_bytes_transferred(mite_chan); return device_byte_count - mite_bytes_in_transit(mite_chan); } -EXPORT_SYMBOL(mite_bytes_written_to_memory_lb); +EXPORT_SYMBOL_GPL(mite_bytes_written_to_memory_lb); /* returns upper bound for number of bytes transferred from device to memory */ u32 mite_bytes_written_to_memory_ub(struct mite_channel *mite_chan) @@ -507,7 +489,7 @@ u32 mite_bytes_written_to_memory_ub(struct mite_channel *mite_chan) in_transit_count = mite_bytes_in_transit(mite_chan); return mite_device_bytes_transferred(mite_chan) - in_transit_count; } -EXPORT_SYMBOL(mite_bytes_written_to_memory_ub); +EXPORT_SYMBOL_GPL(mite_bytes_written_to_memory_ub); /* returns lower bound for number of bytes read from memory to device */ u32 mite_bytes_read_from_memory_lb(struct mite_channel *mite_chan) @@ -517,7 +499,7 @@ u32 mite_bytes_read_from_memory_lb(struct mite_channel *mite_chan) device_byte_count = mite_device_bytes_transferred(mite_chan); return device_byte_count + mite_bytes_in_transit(mite_chan); } -EXPORT_SYMBOL(mite_bytes_read_from_memory_lb); +EXPORT_SYMBOL_GPL(mite_bytes_read_from_memory_lb); /* returns upper bound for number of bytes read from memory to device */ u32 mite_bytes_read_from_memory_ub(struct mite_channel *mite_chan) @@ -527,7 +509,7 @@ u32 mite_bytes_read_from_memory_ub(struct mite_channel *mite_chan) in_transit_count = mite_bytes_in_transit(mite_chan); return mite_device_bytes_transferred(mite_chan) + in_transit_count; } -EXPORT_SYMBOL(mite_bytes_read_from_memory_ub); +EXPORT_SYMBOL_GPL(mite_bytes_read_from_memory_ub); unsigned mite_dma_tcr(struct mite_channel *mite_chan) { @@ -542,7 +524,7 @@ unsigned mite_dma_tcr(struct mite_channel *mite_chan) return tcr; } -EXPORT_SYMBOL(mite_dma_tcr); +EXPORT_SYMBOL_GPL(mite_dma_tcr); void mite_dma_disarm(struct mite_channel *mite_chan) { @@ -553,7 +535,7 @@ void mite_dma_disarm(struct mite_channel *mite_chan) chor = CHOR_ABORT; writel(chor, mite->mite_io_addr + MITE_CHOR(mite_chan->channel)); } -EXPORT_SYMBOL(mite_dma_disarm); +EXPORT_SYMBOL_GPL(mite_dma_disarm); int mite_sync_input_dma(struct mite_channel *mite_chan, struct comedi_async *async) @@ -591,7 +573,7 @@ int mite_sync_input_dma(struct mite_channel *mite_chan, async->events |= COMEDI_CB_BLOCK; return 0; } -EXPORT_SYMBOL(mite_sync_input_dma); +EXPORT_SYMBOL_GPL(mite_sync_input_dma); int mite_sync_output_dma(struct mite_channel *mite_chan, struct comedi_async *async) @@ -629,7 +611,7 @@ int mite_sync_output_dma(struct mite_channel *mite_chan, } return 0; } -EXPORT_SYMBOL(mite_sync_output_dma); +EXPORT_SYMBOL_GPL(mite_sync_output_dma); unsigned mite_get_status(struct mite_channel *mite_chan) { @@ -648,7 +630,7 @@ unsigned mite_get_status(struct mite_channel *mite_chan) spin_unlock_irqrestore(&mite->lock, flags); return status; } -EXPORT_SYMBOL(mite_get_status); +EXPORT_SYMBOL_GPL(mite_get_status); int mite_done(struct mite_channel *mite_chan) { @@ -662,7 +644,7 @@ int mite_done(struct mite_channel *mite_chan) spin_unlock_irqrestore(&mite->lock, flags); return done; } -EXPORT_SYMBOL(mite_done); +EXPORT_SYMBOL_GPL(mite_done); #ifdef DEBUG_MITE @@ -795,7 +777,7 @@ void mite_dump_regs(struct mite_channel *mite_chan) value = readl(mite_io_addr + offset); pr_debug("mite status[FCR] at 0x%08x =0x%08x\n", offset, value); } -EXPORT_SYMBOL(mite_dump_regs); +EXPORT_SYMBOL_GPL(mite_dump_regs); #endif static int __init mite_module_init(void) diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c index 67dc5ad81b0..4717be4ad26 100644 --- a/drivers/staging/comedi/drivers/mpc624.c +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -285,18 +285,11 @@ static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct mpc624_private *devpriv; struct comedi_subdevice *s; - unsigned long iobase; int ret; - iobase = it->options[0]; - printk(KERN_INFO "comedi%d: mpc624 [0x%04lx, ", dev->minor, iobase); - if (request_region(iobase, MPC624_SIZE, "mpc624") == NULL) { - printk(KERN_ERR "I/O port(s) in use\n"); - return -EIO; - } - - dev->iobase = iobase; - dev->board_name = "mpc624"; + ret = comedi_request_region(dev, it->options[0], MPC624_SIZE); + if (ret) + return ret; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) @@ -306,48 +299,35 @@ static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it) switch (it->options[1]) { case 0: devpriv->ulConvertionRate = MPC624_SPEED_3_52_kHz; - printk(KERN_INFO "3.52 kHz, "); break; case 1: devpriv->ulConvertionRate = MPC624_SPEED_1_76_kHz; - printk(KERN_INFO "1.76 kHz, "); break; case 2: devpriv->ulConvertionRate = MPC624_SPEED_880_Hz; - printk(KERN_INFO "880 Hz, "); break; case 3: devpriv->ulConvertionRate = MPC624_SPEED_440_Hz; - printk(KERN_INFO "440 Hz, "); break; case 4: devpriv->ulConvertionRate = MPC624_SPEED_220_Hz; - printk(KERN_INFO "220 Hz, "); break; case 5: devpriv->ulConvertionRate = MPC624_SPEED_110_Hz; - printk(KERN_INFO "110 Hz, "); break; case 6: devpriv->ulConvertionRate = MPC624_SPEED_55_Hz; - printk(KERN_INFO "55 Hz, "); break; case 7: devpriv->ulConvertionRate = MPC624_SPEED_27_5_Hz; - printk(KERN_INFO "27.5 Hz, "); break; case 8: devpriv->ulConvertionRate = MPC624_SPEED_13_75_Hz; - printk(KERN_INFO "13.75 Hz, "); break; case 9: devpriv->ulConvertionRate = MPC624_SPEED_6_875_Hz; - printk(KERN_INFO "6.875 Hz, "); break; default: - printk - (KERN_ERR "illegal conversion rate setting!" - " Valid numbers are 0..9. Using 9 => 6.875 Hz, "); devpriv->ulConvertionRate = MPC624_SPEED_3_52_kHz; } @@ -362,37 +342,26 @@ static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it) switch (it->options[1]) { default: s->maxdata = 0x3FFFFFFF; - printk(KERN_INFO "30 bit, "); } switch (it->options[1]) { case 0: s->range_table = &range_mpc624_bipolar1; - printk(KERN_INFO "1.01V]: "); break; default: s->range_table = &range_mpc624_bipolar10; - printk(KERN_INFO "10.1V]: "); } s->len_chanlist = 1; s->insn_read = mpc624_ai_rinsn; - printk(KERN_INFO "attached\n"); - return 1; } -static void mpc624_detach(struct comedi_device *dev) -{ - if (dev->iobase) - release_region(dev->iobase, MPC624_SIZE); -} - static struct comedi_driver mpc624_driver = { .driver_name = "mpc624", .module = THIS_MODULE, .attach = mpc624_attach, - .detach = mpc624_detach + .detach = comedi_legacy_detach, }; module_comedi_driver(mpc624_driver); diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c index 1f5f402f3d1..7a8292086e1 100644 --- a/drivers/staging/comedi/drivers/multiq3.c +++ b/drivers/staging/comedi/drivers/multiq3.c @@ -222,41 +222,20 @@ static void encoder_reset(struct comedi_device *dev) } } -/* - options[0] - I/O port - options[1] - irq - options[2] - number of encoder chips installed - */ - static int multiq3_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct multiq3_private *devpriv; - int result = 0; - unsigned long iobase; - unsigned int irq; struct comedi_subdevice *s; + int ret; - iobase = it->options[0]; - printk(KERN_INFO "comedi%d: multiq3: 0x%04lx ", dev->minor, iobase); - if (!request_region(iobase, MULTIQ3_SIZE, "multiq3")) { - printk(KERN_ERR "comedi%d: I/O port conflict\n", dev->minor); - return -EIO; - } - - dev->iobase = iobase; + ret = comedi_request_region(dev, it->options[0], MULTIQ3_SIZE); + if (ret) + return ret; - irq = it->options[1]; - if (irq) - printk(KERN_WARNING "comedi%d: irq = %u ignored\n", - dev->minor, irq); - else - printk(KERN_WARNING "comedi%d: no irq\n", dev->minor); - dev->board_name = "multiq3"; - - result = comedi_alloc_subdevices(dev, 5); - if (result) - return result; + ret = comedi_alloc_subdevices(dev, 5); + if (ret) + return ret; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) @@ -315,19 +294,11 @@ static int multiq3_attach(struct comedi_device *dev, return 0; } -static void multiq3_detach(struct comedi_device *dev) -{ - if (dev->iobase) - release_region(dev->iobase, MULTIQ3_SIZE); - if (dev->irq) - free_irq(dev->irq, dev); -} - static struct comedi_driver multiq3_driver = { .driver_name = "multiq3", .module = THIS_MODULE, .attach = multiq3_attach, - .detach = multiq3_detach, + .detach = comedi_legacy_detach, }; module_comedi_driver(multiq3_driver); diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index bcd4df290ec..d10f777b7f1 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -81,33 +81,24 @@ Updated: Sat, 25 Jan 2003 13:24:40 -0800 #define Rising_Edge_Detection_Enable(x) (0x018+(x)) #define Falling_Edge_Detection_Enable(x) (0x020+(x)) -struct ni6527_board { +enum ni6527_boardid { + BOARD_PCI6527, + BOARD_PXI6527, +}; - int dev_id; +struct ni6527_board { const char *name; }; static const struct ni6527_board ni6527_boards[] = { - { - .dev_id = 0x2b20, - .name = "pci-6527", - }, - { - .dev_id = 0x2b10, - .name = "pxi-6527", - }, -}; - -#define this_board ((const struct ni6527_board *)dev->board_ptr) - -static DEFINE_PCI_DEVICE_TABLE(ni6527_pci_table) = { - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2b10)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2b20)}, - {0} + [BOARD_PCI6527] = { + .name = "pci-6527", + }, + [BOARD_PXI6527] = { + .name = "pxi-6527", + }, }; -MODULE_DEVICE_TABLE(pci, ni6527_pci_table); - struct ni6527_private { struct mite_struct *mite; unsigned int filter_interval; @@ -329,37 +320,31 @@ static int ni6527_intr_insn_config(struct comedi_device *dev, return 2; } -static const struct ni6527_board * -ni6527_find_boardinfo(struct pci_dev *pcidev) -{ - unsigned int dev_id = pcidev->device; - unsigned int n; - - for (n = 0; n < ARRAY_SIZE(ni6527_boards); n++) { - const struct ni6527_board *board = &ni6527_boards[n]; - if (board->dev_id == dev_id) - return board; - } - return NULL; -} - static int ni6527_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); + const struct ni6527_board *board = NULL; struct ni6527_private *devpriv; struct comedi_subdevice *s; int ret; + if (context < ARRAY_SIZE(ni6527_boards)) + board = &ni6527_boards[context]; + if (!board) + return -ENODEV; + dev->board_ptr = board; + dev->board_name = board->name; + + ret = comedi_pci_enable(dev); + if (ret) + return ret; + devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - dev->board_ptr = ni6527_find_boardinfo(pcidev); - if (!dev->board_ptr) - return -ENODEV; - devpriv->mite = mite_alloc(pcidev); if (!devpriv->mite) return -ENOMEM; @@ -370,7 +355,6 @@ static int ni6527_auto_attach(struct comedi_device *dev, return ret; } - dev->board_name = this_board->name; dev_info(dev->class_dev, "board: %s, ID=0x%02x\n", dev->board_name, readb(devpriv->mite->daq_io_addr + ID_Register)); @@ -439,6 +423,7 @@ static void ni6527_detach(struct comedi_device *dev) mite_unsetup(devpriv->mite); mite_free(devpriv->mite); } + comedi_pci_disable(dev); } static struct comedi_driver ni6527_driver = { @@ -449,15 +434,22 @@ static struct comedi_driver ni6527_driver = { }; static int ni6527_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &ni6527_driver); + return comedi_pci_auto_config(dev, &ni6527_driver, id->driver_data); } +static DEFINE_PCI_DEVICE_TABLE(ni6527_pci_table) = { + { PCI_VDEVICE(NI, 0x2b10), BOARD_PXI6527 }, + { PCI_VDEVICE(NI, 0x2b20), BOARD_PCI6527 }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, ni6527_pci_table); + static struct pci_driver ni6527_pci_driver = { - .name = DRIVER_NAME, - .id_table = ni6527_pci_table, - .probe = ni6527_pci_probe, + .name = DRIVER_NAME, + .id_table = ni6527_pci_table, + .probe = ni6527_pci_probe, .remove = comedi_pci_auto_unconfig, }; module_comedi_pci_driver(ni6527_driver, ni6527_pci_driver); diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index bfa790ecf41..3f71f0f54d3 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -112,8 +112,32 @@ static inline unsigned Filter_Enable(unsigned port) #define OverflowIntEnable 0x02 #define EdgeIntEnable 0x01 +enum ni_65xx_boardid { + BOARD_PCI6509, + BOARD_PXI6509, + BOARD_PCI6510, + BOARD_PCI6511, + BOARD_PXI6511, + BOARD_PCI6512, + BOARD_PXI6512, + BOARD_PCI6513, + BOARD_PXI6513, + BOARD_PCI6514, + BOARD_PXI6514, + BOARD_PCI6515, + BOARD_PXI6515, + BOARD_PCI6516, + BOARD_PCI6517, + BOARD_PCI6518, + BOARD_PCI6519, + BOARD_PCI6520, + BOARD_PCI6521, + BOARD_PXI6521, + BOARD_PCI6528, + BOARD_PXI6528, +}; + struct ni_65xx_board { - int dev_id; const char *name; unsigned num_dio_ports; unsigned num_di_ports; @@ -122,130 +146,117 @@ struct ni_65xx_board { }; static const struct ni_65xx_board ni_65xx_boards[] = { - { - .dev_id = 0x7085, - .name = "pci-6509", - .num_dio_ports = 12, - .invert_outputs = 0}, - { - .dev_id = 0x1710, - .name = "pxi-6509", - .num_dio_ports = 12, - .invert_outputs = 0}, - { - .dev_id = 0x7124, - .name = "pci-6510", - .num_di_ports = 4}, - { - .dev_id = 0x70c3, - .name = "pci-6511", - .num_di_ports = 8}, - { - .dev_id = 0x70d3, - .name = "pxi-6511", - .num_di_ports = 8}, - { - .dev_id = 0x70cc, - .name = "pci-6512", - .num_do_ports = 8}, - { - .dev_id = 0x70d2, - .name = "pxi-6512", - .num_do_ports = 8}, - { - .dev_id = 0x70c8, - .name = "pci-6513", - .num_do_ports = 8, - .invert_outputs = 1}, - { - .dev_id = 0x70d1, - .name = "pxi-6513", - .num_do_ports = 8, - .invert_outputs = 1}, - { - .dev_id = 0x7088, - .name = "pci-6514", - .num_di_ports = 4, - .num_do_ports = 4, - .invert_outputs = 1}, - { - .dev_id = 0x70CD, - .name = "pxi-6514", - .num_di_ports = 4, - .num_do_ports = 4, - .invert_outputs = 1}, - { - .dev_id = 0x7087, - .name = "pci-6515", - .num_di_ports = 4, - .num_do_ports = 4, - .invert_outputs = 1}, - { - .dev_id = 0x70c9, - .name = "pxi-6515", - .num_di_ports = 4, - .num_do_ports = 4, - .invert_outputs = 1}, - { - .dev_id = 0x7125, - .name = "pci-6516", - .num_do_ports = 4, - .invert_outputs = 1}, - { - .dev_id = 0x7126, - .name = "pci-6517", - .num_do_ports = 4, - .invert_outputs = 1}, - { - .dev_id = 0x7127, - .name = "pci-6518", - .num_di_ports = 2, - .num_do_ports = 2, - .invert_outputs = 1}, - { - .dev_id = 0x7128, - .name = "pci-6519", - .num_di_ports = 2, - .num_do_ports = 2, - .invert_outputs = 1}, - { - .dev_id = 0x71c5, - .name = "pci-6520", - .num_di_ports = 1, - .num_do_ports = 1, - }, - { - .dev_id = 0x718b, - .name = "pci-6521", - .num_di_ports = 1, - .num_do_ports = 1, - }, - { - .dev_id = 0x718c, - .name = "pxi-6521", - .num_di_ports = 1, - .num_do_ports = 1, - }, - { - .dev_id = 0x70a9, - .name = "pci-6528", - .num_di_ports = 3, - .num_do_ports = 3, - }, - { - .dev_id = 0x7086, - .name = "pxi-6528", - .num_di_ports = 3, - .num_do_ports = 3, - }, + [BOARD_PCI6509] = { + .name = "pci-6509", + .num_dio_ports = 12, + }, + [BOARD_PXI6509] = { + .name = "pxi-6509", + .num_dio_ports = 12, + }, + [BOARD_PCI6510] = { + .name = "pci-6510", + .num_di_ports = 4, + }, + [BOARD_PCI6511] = { + .name = "pci-6511", + .num_di_ports = 8, + }, + [BOARD_PXI6511] = { + .name = "pxi-6511", + .num_di_ports = 8, + }, + [BOARD_PCI6512] = { + .name = "pci-6512", + .num_do_ports = 8, + }, + [BOARD_PXI6512] = { + .name = "pxi-6512", + .num_do_ports = 8, + }, + [BOARD_PCI6513] = { + .name = "pci-6513", + .num_do_ports = 8, + .invert_outputs = 1, + }, + [BOARD_PXI6513] = { + .name = "pxi-6513", + .num_do_ports = 8, + .invert_outputs = 1, + }, + [BOARD_PCI6514] = { + .name = "pci-6514", + .num_di_ports = 4, + .num_do_ports = 4, + .invert_outputs = 1, + }, + [BOARD_PXI6514] = { + .name = "pxi-6514", + .num_di_ports = 4, + .num_do_ports = 4, + .invert_outputs = 1, + }, + [BOARD_PCI6515] = { + .name = "pci-6515", + .num_di_ports = 4, + .num_do_ports = 4, + .invert_outputs = 1, + }, + [BOARD_PXI6515] = { + .name = "pxi-6515", + .num_di_ports = 4, + .num_do_ports = 4, + .invert_outputs = 1, + }, + [BOARD_PCI6516] = { + .name = "pci-6516", + .num_do_ports = 4, + .invert_outputs = 1, + }, + [BOARD_PCI6517] = { + .name = "pci-6517", + .num_do_ports = 4, + .invert_outputs = 1, + }, + [BOARD_PCI6518] = { + .name = "pci-6518", + .num_di_ports = 2, + .num_do_ports = 2, + .invert_outputs = 1, + }, + [BOARD_PCI6519] = { + .name = "pci-6519", + .num_di_ports = 2, + .num_do_ports = 2, + .invert_outputs = 1, + }, + [BOARD_PCI6520] = { + .name = "pci-6520", + .num_di_ports = 1, + .num_do_ports = 1, + }, + [BOARD_PCI6521] = { + .name = "pci-6521", + .num_di_ports = 1, + .num_do_ports = 1, + }, + [BOARD_PXI6521] = { + .name = "pxi-6521", + .num_di_ports = 1, + .num_do_ports = 1, + }, + [BOARD_PCI6528] = { + .name = "pci-6528", + .num_di_ports = 3, + .num_do_ports = 3, + }, + [BOARD_PXI6528] = { + .name = "pxi-6528", + .num_di_ports = 3, + .num_do_ports = 3, + }, }; -#define n_ni_65xx_boards ARRAY_SIZE(ni_65xx_boards) -static inline const struct ni_65xx_board *board(struct comedi_device *dev) -{ - return dev->board_ptr; -} - static inline unsigned ni_65xx_port_by_channel(unsigned channel) { return channel / ni_65xx_channels_per_port; @@ -257,34 +268,6 @@ static inline unsigned ni_65xx_total_num_ports(const struct ni_65xx_board return board->num_dio_ports + board->num_di_ports + board->num_do_ports; } -static DEFINE_PCI_DEVICE_TABLE(ni_65xx_pci_table) = { - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1710)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x7085)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x7086)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x7087)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x7088)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70a9)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70c3)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70c8)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70c9)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70cc)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70CD)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70d1)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70d2)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70d3)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x7124)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x7125)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x7126)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x7127)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x7128)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x718b)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x718c)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x71c5)}, - {0} -}; - -MODULE_DEVICE_TABLE(pci, ni_65xx_pci_table); - struct ni_65xx_private { struct mite_struct *mite; unsigned int filter_interval; @@ -398,6 +381,7 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + const struct ni_65xx_board *board = comedi_board(dev); struct ni_65xx_private *devpriv = dev->private; unsigned base_bitfield_channel; const unsigned max_ports_per_bitfield = 5; @@ -413,7 +397,7 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev, unsigned base_port_channel; unsigned port_mask, port_data, port_read_bits; int bitshift; - if (port >= ni_65xx_total_num_ports(board(dev))) + if (port >= ni_65xx_total_num_ports(board)) break; base_port_channel = port_offset * ni_65xx_channels_per_port; port_mask = data[0]; @@ -436,7 +420,7 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev, devpriv->output_bits[port] |= port_data & port_mask; bits = devpriv->output_bits[port]; - if (board(dev)->invert_outputs) + if (board->invert_outputs) bits = ~bits; writeb(bits, devpriv->mite->daq_io_addr + @@ -444,7 +428,7 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev, } port_read_bits = readb(devpriv->mite->daq_io_addr + Port_Data(port)); - if (s->type == COMEDI_SUBD_DO && board(dev)->invert_outputs) { + 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.) */ @@ -599,38 +583,32 @@ static int ni_65xx_intr_insn_config(struct comedi_device *dev, return 2; } -static const struct ni_65xx_board * -ni_65xx_find_boardinfo(struct pci_dev *pcidev) -{ - unsigned int dev_id = pcidev->device; - unsigned int n; - - for (n = 0; n < ARRAY_SIZE(ni_65xx_boards); n++) { - const struct ni_65xx_board *board = &ni_65xx_boards[n]; - if (board->dev_id == dev_id) - return board; - } - return NULL; -} - static int ni_65xx_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); + const struct ni_65xx_board *board = NULL; struct ni_65xx_private *devpriv; struct comedi_subdevice *s; unsigned i; int ret; + if (context < ARRAY_SIZE(ni_65xx_boards)) + board = &ni_65xx_boards[context]; + if (!board) + return -ENODEV; + dev->board_ptr = board; + dev->board_name = board->name; + + ret = comedi_pci_enable(dev); + if (ret) + return ret; + devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - dev->board_ptr = ni_65xx_find_boardinfo(pcidev); - if (!dev->board_ptr) - return -ENODEV; - devpriv->mite = mite_alloc(pcidev); if (!devpriv->mite) return -ENOMEM; @@ -641,7 +619,6 @@ static int ni_65xx_auto_attach(struct comedi_device *dev, return ret; } - dev->board_name = board(dev)->name; 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)); @@ -651,11 +628,11 @@ static int ni_65xx_auto_attach(struct comedi_device *dev, return ret; s = &dev->subdevices[0]; - if (board(dev)->num_di_ports) { + if (board->num_di_ports) { s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = - board(dev)->num_di_ports * ni_65xx_channels_per_port; + 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; @@ -669,28 +646,28 @@ static int ni_65xx_auto_attach(struct comedi_device *dev, } s = &dev->subdevices[1]; - if (board(dev)->num_do_ports) { + if (board->num_do_ports) { s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = - board(dev)->num_do_ports * ni_65xx_channels_per_port; + 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; s->private = ni_65xx_alloc_subdevice_private(); if (s->private == NULL) return -ENOMEM; - sprivate(s)->base_port = board(dev)->num_di_ports; + sprivate(s)->base_port = board->num_di_ports; } else { s->type = COMEDI_SUBD_UNUSED; } s = &dev->subdevices[2]; - if (board(dev)->num_dio_ports) { + if (board->num_dio_ports) { s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = - board(dev)->num_dio_ports * ni_65xx_channels_per_port; + 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; @@ -699,7 +676,7 @@ static int ni_65xx_auto_attach(struct comedi_device *dev, if (s->private == NULL) return -ENOMEM; sprivate(s)->base_port = 0; - for (i = 0; i < board(dev)->num_dio_ports; ++i) { + for (i = 0; i < board->num_dio_ports; ++i) { /* configure all ports for input */ writeb(0x1, devpriv->mite->daq_io_addr + @@ -722,10 +699,10 @@ static int ni_65xx_auto_attach(struct comedi_device *dev, 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(dev)); ++i) { + for (i = 0; i < ni_65xx_total_num_ports(board); ++i) { writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(i)); - if (board(dev)->invert_outputs) + if (board->invert_outputs) writeb(0x01, devpriv->mite->daq_io_addr + Port_Data(i)); else @@ -753,6 +730,7 @@ static int ni_65xx_auto_attach(struct comedi_device *dev, static void ni_65xx_detach(struct comedi_device *dev) { struct ni_65xx_private *devpriv = dev->private; + int i; if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr) { writeb(0x00, @@ -761,20 +739,15 @@ static void ni_65xx_detach(struct comedi_device *dev) } if (dev->irq) free_irq(dev->irq, dev); + for (i = 0; i < dev->n_subdevices; ++i) + comedi_spriv_free(dev, i); if (devpriv) { - struct comedi_subdevice *s; - unsigned i; - - for (i = 0; i < dev->n_subdevices; ++i) { - s = &dev->subdevices[i]; - kfree(s->private); - s->private = NULL; - } if (devpriv->mite) { mite_unsetup(devpriv->mite); mite_free(devpriv->mite); } } + comedi_pci_disable(dev); } static struct comedi_driver ni_65xx_driver = { @@ -785,15 +758,42 @@ static struct comedi_driver ni_65xx_driver = { }; static int ni_65xx_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &ni_65xx_driver); + return comedi_pci_auto_config(dev, &ni_65xx_driver, id->driver_data); } +static DEFINE_PCI_DEVICE_TABLE(ni_65xx_pci_table) = { + { PCI_VDEVICE(NI, 0x1710), BOARD_PXI6509 }, + { PCI_VDEVICE(NI, 0x7085), BOARD_PCI6509 }, + { PCI_VDEVICE(NI, 0x7086), BOARD_PXI6528 }, + { PCI_VDEVICE(NI, 0x7087), BOARD_PCI6515 }, + { PCI_VDEVICE(NI, 0x7088), BOARD_PCI6514 }, + { PCI_VDEVICE(NI, 0x70a9), BOARD_PCI6528 }, + { PCI_VDEVICE(NI, 0x70c3), BOARD_PCI6511 }, + { PCI_VDEVICE(NI, 0x70c8), BOARD_PCI6513 }, + { PCI_VDEVICE(NI, 0x70c9), BOARD_PXI6515 }, + { PCI_VDEVICE(NI, 0x70cc), BOARD_PCI6512 }, + { PCI_VDEVICE(NI, 0x70cd), BOARD_PXI6514 }, + { PCI_VDEVICE(NI, 0x70d1), BOARD_PXI6513 }, + { PCI_VDEVICE(NI, 0x70d2), BOARD_PXI6512 }, + { PCI_VDEVICE(NI, 0x70d3), BOARD_PXI6511 }, + { PCI_VDEVICE(NI, 0x7124), BOARD_PCI6510 }, + { PCI_VDEVICE(NI, 0x7125), BOARD_PCI6516 }, + { PCI_VDEVICE(NI, 0x7126), BOARD_PCI6517 }, + { PCI_VDEVICE(NI, 0x7127), BOARD_PCI6518 }, + { PCI_VDEVICE(NI, 0x7128), BOARD_PCI6519 }, + { PCI_VDEVICE(NI, 0x718b), BOARD_PCI6521 }, + { PCI_VDEVICE(NI, 0x718c), BOARD_PXI6521 }, + { PCI_VDEVICE(NI, 0x71c5), BOARD_PCI6520 }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, ni_65xx_pci_table); + static struct pci_driver ni_65xx_pci_driver = { - .name = "ni_65xx", - .id_table = ni_65xx_pci_table, - .probe = ni_65xx_pci_probe, + .name = "ni_65xx", + .id_table = ni_65xx_pci_table, + .probe = ni_65xx_pci_probe, .remove = comedi_pci_auto_unconfig, }; module_comedi_pci_driver(ni_65xx_driver, ni_65xx_pci_driver); diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index e46dd7a1a72..5cdda7fe97a 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -18,27 +18,25 @@ */ /* -Driver: ni_660x -Description: National Instruments 660x counter/timer boards -Devices: -[National Instruments] PCI-6601 (ni_660x), PCI-6602, PXI-6602, - PXI-6608 -Author: J.P. Mellor <jpmellor@rose-hulman.edu>, - Herman.Bruyninckx@mech.kuleuven.ac.be, - Wim.Meeussen@mech.kuleuven.ac.be, - Klaas.Gadeyne@mech.kuleuven.ac.be, - Frank Mori Hess <fmhess@users.sourceforge.net> -Updated: Thu Oct 18 12:56:06 EDT 2007 -Status: experimental - -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) - -*/ + * Driver: ni_660x + * Description: National Instruments 660x counter/timer boards + * Devices: [National Instruments] PCI-6601 (ni_660x), PCI-6602, PXI-6602, + * PXI-6608, PXI-6624 + * Author: J.P. Mellor <jpmellor@rose-hulman.edu>, + * Herman.Bruyninckx@mech.kuleuven.ac.be, + * Wim.Meeussen@mech.kuleuven.ac.be, + * Klaas.Gadeyne@mech.kuleuven.ac.be, + * Frank Mori Hess <fmhess@users.sourceforge.net> + * Updated: Fri, 15 Mar 2013 10:47:56 +0000 + * Status: experimental + * + * 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) + */ #include <linux/pci.h> #include <linux/interrupt.h> @@ -389,34 +387,40 @@ enum global_interrupt_config_register_bits { /* First chip is at base-address + 0x00, etc. */ static const unsigned GPCT_OFFSET[2] = { 0x0, 0x800 }; -/* Board description*/ +enum ni_660x_boardid { + BOARD_PCI6601, + BOARD_PCI6602, + BOARD_PXI6602, + BOARD_PXI6608, + BOARD_PXI6624 +}; + struct ni_660x_board { - unsigned short dev_id; /* `lspci` will show you this */ const char *name; unsigned n_chips; /* total number of TIO chips */ }; static const struct ni_660x_board ni_660x_boards[] = { - { - .dev_id = 0x2c60, - .name = "PCI-6601", - .n_chips = 1, - }, - { - .dev_id = 0x1310, - .name = "PCI-6602", - .n_chips = 2, - }, - { - .dev_id = 0x1360, - .name = "PXI-6602", - .n_chips = 2, - }, - { - .dev_id = 0x2cc0, - .name = "PXI-6608", - .n_chips = 2, - }, + [BOARD_PCI6601] = { + .name = "PCI-6601", + .n_chips = 1, + }, + [BOARD_PCI6602] = { + .name = "PCI-6602", + .n_chips = 2, + }, + [BOARD_PXI6602] = { + .name = "PXI-6602", + .n_chips = 2, + }, + [BOARD_PXI6608] = { + .name = "PXI-6608", + .n_chips = 2, + }, + [BOARD_PXI6624] = { + .name = "PXI-6624", + .n_chips = 2, + }, }; #define NI_660X_MAX_NUM_CHIPS 2 @@ -883,7 +887,7 @@ static irqreturn_t ni_660x_interrupt(int irq, void *d) unsigned i; unsigned long flags; - if (dev->attached == 0) + if (!dev->attached) return IRQ_NONE; /* lock to avoid race with comedi_poll */ spin_lock_irqsave(&devpriv->interrupt_lock, flags); @@ -974,20 +978,6 @@ static void ni_660x_free_mite_rings(struct comedi_device *dev) } } -static const struct ni_660x_board * -ni_660x_find_boardinfo(struct pci_dev *pcidev) -{ - unsigned int dev_id = pcidev->device; - unsigned int n; - - for (n = 0; n < ARRAY_SIZE(ni_660x_boards); n++) { - const struct ni_660x_board *board = &ni_660x_boards[n]; - if (board->dev_id == dev_id) - return board; - } - return NULL; -} - static int ni_660x_GPCT_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -1170,32 +1160,36 @@ static int ni_660x_dio_insn_config(struct comedi_device *dev, } static int ni_660x_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct ni_660x_board *board; + const struct ni_660x_board *board = NULL; struct ni_660x_private *devpriv; struct comedi_subdevice *s; int ret; unsigned i; unsigned global_interrupt_config_bits; + if (context < ARRAY_SIZE(ni_660x_boards)) + board = &ni_660x_boards[context]; + if (!board) + return -ENODEV; + dev->board_ptr = board; + dev->board_name = board->name; + + ret = comedi_pci_enable(dev); + if (ret) + return ret; + ret = ni_660x_allocate_private(dev); if (ret < 0) return ret; devpriv = dev->private; - dev->board_ptr = ni_660x_find_boardinfo(pcidev); - if (!dev->board_ptr) - return -ENODEV; - board = comedi_board(dev); - devpriv->mite = mite_alloc(pcidev); if (!devpriv->mite) return -ENOMEM; - dev->board_name = board->name; - ret = mite_setup2(devpriv->mite, 1); if (ret < 0) { dev_warn(dev->class_dev, "error setting up mite\n"); @@ -1315,6 +1309,7 @@ static void ni_660x_detach(struct comedi_device *dev) mite_free(devpriv->mite); } } + comedi_pci_disable(dev); } static struct comedi_driver ni_660x_driver = { @@ -1325,17 +1320,18 @@ static struct comedi_driver ni_660x_driver = { }; static int ni_660x_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &ni_660x_driver); + return comedi_pci_auto_config(dev, &ni_660x_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(ni_660x_pci_table) = { - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2c60)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1310)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1360)}, - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2cc0)}, - {0} + { PCI_VDEVICE(NI, 0x1310), BOARD_PCI6602 }, + { PCI_VDEVICE(NI, 0x1360), BOARD_PXI6602 }, + { PCI_VDEVICE(NI, 0x2c60), BOARD_PCI6601 }, + { PCI_VDEVICE(NI, 0x2cc0), BOARD_PXI6608 }, + { PCI_VDEVICE(NI, 0x1e40), BOARD_PXI6624 }, + { 0 } }; MODULE_DEVICE_TABLE(pci, ni_660x_pci_table); diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index 2faf86c83dc..42ab6dbf9d3 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -60,26 +60,28 @@ Commands are not supported. #define MISC_STATUS_OFFSET 0x14 #define MISC_CONTROL_OFFSET 0x14 -/* Board description*/ +enum ni_670x_boardid { + BOARD_PCI6703, + BOARD_PXI6704, + BOARD_PCI6704, +}; struct ni_670x_board { const char *name; - unsigned short dev_id; unsigned short ao_chans; }; static const struct ni_670x_board ni_670x_boards[] = { - { + [BOARD_PCI6703] = { .name = "PCI-6703", - .dev_id = 0x2c90, .ao_chans = 16, - }, { + }, + [BOARD_PXI6704] = { .name = "PXI-6704", - .dev_id = 0x1920, .ao_chans = 32, - }, { + }, + [BOARD_PCI6704] = { .name = "PCI-6704", - .dev_id = 0x1290, .ao_chans = 32, }, }; @@ -92,8 +94,6 @@ struct ni_670x_private { unsigned int ao_readback[32]; }; -static struct comedi_lrange range_0_20mA = { 1, {RANGE_mA(0, 20)} }; - static int ni_670x_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -189,49 +189,41 @@ static int ni_670x_dio_insn_config(struct comedi_device *dev, return insn->n; } -static const struct ni_670x_board * -ni_670x_find_boardinfo(struct pci_dev *pcidev) -{ - unsigned int dev_id = pcidev->device; - unsigned int n; - - for (n = 0; n < ARRAY_SIZE(ni_670x_boards); n++) { - const struct ni_670x_board *board = &ni_670x_boards[n]; - if (board->dev_id == dev_id) - return board; - } - return NULL; -} - static int ni_670x_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct ni_670x_board *thisboard; + const struct ni_670x_board *thisboard = NULL; struct ni_670x_private *devpriv; struct comedi_subdevice *s; int ret; int i; + if (context < ARRAY_SIZE(ni_670x_boards)) + thisboard = &ni_670x_boards[context]; + if (!thisboard) + return -ENODEV; + dev->board_ptr = thisboard; + dev->board_name = thisboard->name; + + ret = comedi_pci_enable(dev); + if (ret) + return ret; + devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - dev->board_ptr = ni_670x_find_boardinfo(pcidev); - if (!dev->board_ptr) - return -ENODEV; devpriv->mite = mite_alloc(pcidev); if (!devpriv->mite) return -ENOMEM; - thisboard = comedi_board(dev); ret = mite_setup(devpriv->mite); if (ret < 0) { dev_warn(dev->class_dev, "error setting up mite\n"); return ret; } - dev->board_name = thisboard->name; ret = comedi_alloc_subdevices(dev, 2); if (ret) @@ -296,6 +288,7 @@ static void ni_670x_detach(struct comedi_device *dev) mite_unsetup(devpriv->mite); mite_free(devpriv->mite); } + comedi_pci_disable(dev); } static struct comedi_driver ni_670x_driver = { @@ -306,14 +299,15 @@ static struct comedi_driver ni_670x_driver = { }; static int ni_670x_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &ni_670x_driver); + return comedi_pci_auto_config(dev, &ni_670x_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(ni_670x_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2c90) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1920) }, + { PCI_VDEVICE(NI, 0x1290), BOARD_PCI6704 }, + { PCI_VDEVICE(NI, 0x1920), BOARD_PXI6704 }, + { PCI_VDEVICE(NI, 0x2c90), BOARD_PCI6703 }, { 0 } }; MODULE_DEVICE_TABLE(pci, ni_670x_pci_table); diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 06de25bb2f5..2d375168f36 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -154,11 +154,6 @@ static const struct a2150_board a2150_boards[] = { }, }; -/* - * Useful for shorthand access to the particular board structure - */ -#define thisboard ((const struct a2150_board *)dev->board_ptr) - struct a2150_private { volatile unsigned int count; /* number of data points left to be taken */ @@ -204,7 +199,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d) short dpnt; static const int sample_size = sizeof(devpriv->dma_buffer[0]); - if (dev->attached == 0) { + if (!dev->attached) { comedi_error(dev, "premature interrupt"); return IRQ_HANDLED; } @@ -319,6 +314,7 @@ static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s) static int a2150_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + const struct a2150_board *thisboard = comedi_board(dev); int err = 0; int tmp; int startChan; @@ -604,6 +600,7 @@ static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 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; @@ -719,45 +716,23 @@ static int a2150_probe(struct comedi_device *dev) static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct a2150_board *thisboard = comedi_board(dev); struct a2150_private *devpriv; struct comedi_subdevice *s; - unsigned long iobase = it->options[0]; unsigned int irq = it->options[1]; unsigned int dma = it->options[2]; static const int timeout = 2000; int i; int ret; - printk("comedi%d: %s: io 0x%lx", dev->minor, dev->driver->driver_name, - iobase); - if (irq) { - printk(", irq %u", irq); - } else { - printk(", no irq"); - } - if (dma) { - printk(", dma %u", dma); - } else { - printk(", no dma"); - } - printk("\n"); - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - if (iobase == 0) { - printk(" io base address required\n"); - return -EINVAL; - } - - /* check if io addresses are available */ - if (!request_region(iobase, A2150_SIZE, dev->driver->driver_name)) { - printk(" I/O port conflict\n"); - return -EIO; - } - dev->iobase = iobase; + ret = comedi_request_region(dev, it->options[0], A2150_SIZE); + if (ret) + return ret; /* grab our IRQ */ if (irq) { @@ -797,6 +772,7 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) } dev->board_ptr = a2150_boards + a2150_probe(dev); + thisboard = comedi_board(dev); dev->board_name = thisboard->name; ret = comedi_alloc_subdevices(dev, 1); @@ -851,17 +827,14 @@ static void a2150_detach(struct comedi_device *dev) { struct a2150_private *devpriv = dev->private; - if (dev->iobase) { + if (dev->iobase) outw(APD_BIT | DPD_BIT, dev->iobase + CONFIG_REG); - release_region(dev->iobase, A2150_SIZE); - } - if (dev->irq) - free_irq(dev->irq, dev); if (devpriv) { if (devpriv->dma) free_dma(devpriv->dma); kfree(devpriv->dma_buffer); } + comedi_legacy_detach(dev); }; static struct comedi_driver ni_at_a2150_driver = { diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index 907f65cdbdc..7e5783a4f4e 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -337,24 +337,14 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it) const struct atao_board *board = comedi_board(dev); struct atao_private *devpriv; struct comedi_subdevice *s; - unsigned long iobase; int ao_unipolar; int ret; - iobase = it->options[0]; - if (iobase == 0) - iobase = 0x1c0; ao_unipolar = it->options[3]; - printk(KERN_INFO "comedi%d: ni_at_ao: 0x%04lx", dev->minor, iobase); - - if (!request_region(iobase, ATAO_SIZE, "ni_at_ao")) { - printk(" I/O port conflict\n"); - return -EIO; - } - dev->iobase = iobase; - - dev->board_name = board->name; + ret = comedi_request_region(dev, it->options[0], ATAO_SIZE); + if (ret) + return ret; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) @@ -409,12 +399,6 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it) return 0; } -static void atao_detach(struct comedi_device *dev) -{ - if (dev->iobase) - release_region(dev->iobase, ATAO_SIZE); -} - static const struct atao_board atao_boards[] = { { .name = "ai-ao-6", @@ -429,7 +413,7 @@ static struct comedi_driver ni_at_ao_driver = { .driver_name = "ni_at_ao", .module = THIS_MODULE, .attach = atao_attach, - .detach = atao_detach, + .detach = comedi_legacy_detach, .board_name = &atao_boards[0].name, .offset = sizeof(struct atao_board), .num_names = ARRAY_SIZE(atao_boards), diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c index 2cc29965e15..4ced7ba119b 100644 --- a/drivers/staging/comedi/drivers/ni_atmio.c +++ b/drivers/staging/comedi/drivers/ni_atmio.c @@ -350,7 +350,7 @@ static int ni_isapnp_find_board(struct pnp_dev **dev) struct pnp_dev *isapnp_dev = NULL; int i; - for (i = 0; i < n_ni_boards; i++) { + for (i = 0; i < ARRAY_SIZE(ni_boards); i++) { isapnp_dev = pnp_find_dev(NULL, ISAPNP_VENDOR('N', 'I', 'C'), ISAPNP_FUNCTION(ni_boards[i]. @@ -377,7 +377,7 @@ static int ni_isapnp_find_board(struct pnp_dev **dev) } break; } - if (i == n_ni_boards) + if (i == ARRAY_SIZE(ni_boards)) return -ENODEV; *dev = isapnp_dev; return 0; @@ -388,7 +388,7 @@ static int ni_getboardtype(struct comedi_device *dev) int device_id = ni_read_eeprom(dev, 511); int i; - for (i = 0; i < n_ni_boards; i++) { + for (i = 0; i < ARRAY_SIZE(ni_boards); i++) { if (ni_boards[i].device_id == device_id) return i; @@ -406,6 +406,7 @@ static int ni_getboardtype(struct comedi_device *dev) static int ni_atmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + const struct ni_board_struct *boardtype; struct ni_private *devpriv; struct pnp_dev *isapnp_dev; int ret; @@ -436,15 +437,9 @@ static int ni_atmio_attach(struct comedi_device *dev, devpriv->isapnp_dev = isapnp_dev; } - /* reserve our I/O region */ - - printk("comedi%d: ni_atmio: 0x%04lx", dev->minor, iobase); - if (!request_region(iobase, NI_SIZE, "ni_atmio")) { - printk(" I/O port conflict\n"); - return -EIO; - } - - dev->iobase = iobase; + ret = comedi_request_region(dev, iobase, NI_SIZE); + if (ret) + return ret; #ifdef DEBUG /* board existence sanity check */ @@ -466,9 +461,10 @@ static int ni_atmio_attach(struct comedi_device *dev, return -EIO; dev->board_ptr = ni_boards + board; + boardtype = comedi_board(dev); - printk(" %s", boardtype.name); - dev->board_name = boardtype.name; + printk(" %s", boardtype->name); + dev->board_name = boardtype->name; /* irq stuff */ @@ -503,10 +499,7 @@ static void ni_atmio_detach(struct comedi_device *dev) struct ni_private *devpriv = dev->private; mio_common_detach(dev); - if (dev->iobase) - release_region(dev->iobase, NI_SIZE); - if (dev->irq) - free_irq(dev->irq, dev); + comedi_legacy_detach(dev); if (devpriv->isapnp_dev) pnp_device_detach(devpriv->isapnp_dev); } diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index 4a17494f55e..6c97a0925aa 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -638,22 +638,13 @@ static int atmio16d_attach(struct comedi_device *dev, { const struct atmio16_board_t *board = comedi_board(dev); struct atmio16d_private *devpriv; + struct comedi_subdevice *s; unsigned int irq; - unsigned long iobase; int ret; - struct comedi_subdevice *s; - - /* make sure the address range is free and allocate it */ - iobase = it->options[0]; - printk(KERN_INFO "comedi%d: atmio16d: 0x%04lx ", dev->minor, iobase); - if (!request_region(iobase, ATMIO16D_SIZE, "ni_atmio16d")) { - printk("I/O port conflict\n"); - return -EIO; - } - dev->iobase = iobase; - - dev->board_name = board->name; + ret = comedi_request_region(dev, it->options[0], ATMIO16D_SIZE); + if (ret) + return ret; ret = comedi_alloc_subdevices(dev, 4); if (ret) @@ -776,18 +767,9 @@ static int atmio16d_attach(struct comedi_device *dev, static void atmio16d_detach(struct comedi_device *dev) { - const struct atmio16_board_t *board = comedi_board(dev); - struct comedi_subdevice *s; - - if (dev->subdevices && board->has_8255) { - s = &dev->subdevices[3]; - subdev_8255_cleanup(dev, s); - } - if (dev->irq) - free_irq(dev->irq, dev); + comedi_spriv_free(dev, 3); reset_atmio16d(dev); - if (dev->iobase) - release_region(dev->iobase, ATMIO16D_SIZE); + comedi_legacy_detach(dev); } static const struct atmio16_board_t atmio16_boards[] = { diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 9cc6092eacd..d067ef70e19 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -202,8 +202,6 @@ static int daq700_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - dev->board_name = dev->driver->driver_name; - link->config_flags |= CONF_AUTO_SET_IO; ret = comedi_pcmcia_enable(dev, NULL); if (ret) diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c index e1cc9d01f20..9b7805fda93 100644 --- a/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -52,8 +52,6 @@ static int dio24_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - dev->board_name = dev->driver->driver_name; - link->config_flags |= CONF_AUTO_SET_IO; ret = comedi_pcmcia_enable(dev, NULL); if (ret) @@ -75,8 +73,7 @@ static int dio24_auto_attach(struct comedi_device *dev, static void dio24_detach(struct comedi_device *dev) { - if (dev->subdevices) - subdev_8255_cleanup(dev, &dev->subdevices[0]); + comedi_spriv_free(dev, 0); comedi_pcmcia_disable(dev); } diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index f957b8859b3..3d978f34d21 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -1,79 +1,66 @@ /* - comedi/drivers/ni_labpc.c - Driver for National Instruments Lab-PC series boards and compatibles - Copyright (C) 2001, 2002, 2003 Frank Mori Hess <fmhess@users.sourceforge.net> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -************************************************************************ -*/ -/* -Driver: ni_labpc -Description: National Instruments Lab-PC (& compatibles) -Author: Frank Mori Hess <fmhess@users.sourceforge.net> -Devices: [National Instruments] Lab-PC-1200 (labpc-1200), - Lab-PC-1200AI (labpc-1200ai), Lab-PC+ (lab-pc+), PCI-1200 (ni_labpc) -Status: works - -Tested with lab-pc-1200. For the older Lab-PC+, not all input ranges -and analog references will work, the available ranges/arefs will -depend on how you have configured the jumpers on your board -(see your owner's manual). - -Kernel-level ISA plug-and-play support for the lab-pc-1200 -boards has not -yet been added to the driver, mainly due to the fact that -I don't know the device id numbers. If you have one -of these boards, -please file a bug report at http://comedi.org/ -so I can get the necessary information from you. - -The 1200 series boards have onboard calibration dacs for correcting -analog input/output offsets and gains. The proper settings for these -caldacs are stored on the board's eeprom. To read the caldac values -from the eeprom and store them into a file that can be then be used by -comedilib, use the comedi_calibrate program. - -Configuration options - ISA boards: - [0] - I/O port base address - [1] - IRQ (optional, required for timed or externally triggered conversions) - [2] - DMA channel (optional) - -Configuration options - PCI boards: - [0] - bus (optional) - [1] - slot (optional) - -The Lab-pc+ has quirky chanlist requirements -when scanning multiple channels. Multiple channel scan -sequence must start at highest channel, then decrement down to -channel 0. The rest of the cards can scan down like lab-pc+ or scan -up from channel zero. Chanlists consisting of all one channel -are also legal, and allow you to pace conversions in bursts. - -*/ + * comedi/drivers/ni_labpc.c + * Driver for National Instruments Lab-PC series boards and compatibles + * Copyright (C) 2001-2003 Frank Mori Hess <fmhess@users.sourceforge.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ /* + * Driver: ni_labpc + * Description: National Instruments Lab-PC (& compatibles) + * Devices: (National Instruments) Lab-PC-1200 [lab-pc-1200] + * (National Instruments) Lab-PC-1200AI [lab-pc-1200ai] + * (National Instruments) Lab-PC+ [lab-pc+] + * Author: Frank Mori Hess <fmhess@users.sourceforge.net> + * Status: works + * + * Configuration options - ISA boards: + * [0] - I/O port base address + * [1] - IRQ (optional, required for timed or externally triggered + * conversions) + * [2] - DMA channel (optional) + * + * Tested with lab-pc-1200. For the older Lab-PC+, not all input + * ranges and analog references will work, the available ranges/arefs + * will depend on how you have configured the jumpers on your board + * (see your owner's manual). + * + * Kernel-level ISA plug-and-play support for the lab-pc-1200 boards + * has not yet been added to the driver, mainly due to the fact that + * I don't know the device id numbers. If you have one of these boards, + * please file a bug report at http://comedi.org/ so I can get the + * necessary information from you. + * + * The 1200 series boards have onboard calibration dacs for correcting + * analog input/output offsets and gains. The proper settings for these + * caldacs are stored on the board's eeprom. To read the caldac values + * from the eeprom and store them into a file that can be then be used + * by comedilib, use the comedi_calibrate program. + * + * The Lab-pc+ has quirky chanlist requirements when scanning multiple + * channels. Multiple channel scan sequence must start at highest channel, + * then decrement down to channel 0. The rest of the cards can scan down + * like lab-pc+ or scan up from channel zero. Chanlists consisting of all + * one channel are also legal, and allow you to pace conversions in bursts. + * + * NI manuals: + * 341309a (labpc-1200 register manual) + * 320502b (lab-pc+) + */ -NI manuals: -341309a (labpc-1200 register manual) -340914a (pci-1200) -320502b (lab-pc+) - -*/ - -#include <linux/pci.h> #include <linux/interrupt.h> #include <linux/slab.h> #include <linux/io.h> @@ -85,128 +72,79 @@ NI manuals: #include "8253.h" #include "8255.h" -#include "mite.h" #include "comedi_fc.h" #include "ni_labpc.h" -#define DRV_NAME "ni_labpc" - -/* size of io region used by board */ -#define LABPC_SIZE 32 -/* 2 MHz master clock */ -#define LABPC_TIMER_BASE 500 - -/* Registers for the lab-pc+ */ - -/* write-only registers */ -#define COMMAND1_REG 0x0 -#define ADC_GAIN_MASK (0x7 << 4) -#define ADC_CHAN_BITS(x) ((x) & 0x7) -/* enables multi channel scans */ -#define ADC_SCAN_EN_BIT 0x80 -#define COMMAND2_REG 0x1 -/* enable pretriggering (used in conjunction with SWTRIG) */ -#define PRETRIG_BIT 0x1 -/* enable paced conversions on external trigger */ -#define HWTRIG_BIT 0x2 -/* enable paced conversions */ -#define SWTRIG_BIT 0x4 -/* use two cascaded counters for pacing */ -#define CASCADE_BIT 0x8 -#define DAC_PACED_BIT(channel) (0x40 << ((channel) & 0x1)) -#define COMMAND3_REG 0x2 -/* enable dma transfers */ -#define DMA_EN_BIT 0x1 -/* enable interrupts for 8255 */ -#define DIO_INTR_EN_BIT 0x2 -/* enable dma terminal count interrupt */ -#define DMATC_INTR_EN_BIT 0x4 -/* enable timer interrupt */ -#define TIMER_INTR_EN_BIT 0x8 -/* enable error interrupt */ -#define ERR_INTR_EN_BIT 0x10 -/* enable fifo not empty interrupt */ -#define ADC_FNE_INTR_EN_BIT 0x20 -#define ADC_CONVERT_REG 0x3 -#define DAC_LSB_REG(channel) (0x4 + 2 * ((channel) & 0x1)) -#define DAC_MSB_REG(channel) (0x5 + 2 * ((channel) & 0x1)) -#define ADC_CLEAR_REG 0x8 -#define DMATC_CLEAR_REG 0xa -#define TIMER_CLEAR_REG 0xc -/* 1200 boards only */ -#define COMMAND6_REG 0xe -/* select ground or common-mode reference */ -#define ADC_COMMON_BIT 0x1 -/* adc unipolar */ -#define ADC_UNIP_BIT 0x2 -/* dac unipolar */ -#define DAC_UNIP_BIT(channel) (0x4 << ((channel) & 0x1)) -/* enable fifo half full interrupt */ -#define ADC_FHF_INTR_EN_BIT 0x20 -/* enable interrupt on end of hardware count */ -#define A1_INTR_EN_BIT 0x40 -/* scan up from channel zero instead of down to zero */ -#define ADC_SCAN_UP_BIT 0x80 -#define COMMAND4_REG 0xf -/* enables 'interval' scanning */ -#define INTERVAL_SCAN_EN_BIT 0x1 -/* enables external signal on counter b1 output to trigger scan */ -#define EXT_SCAN_EN_BIT 0x2 -/* chooses direction (output or input) for EXTCONV* line */ -#define EXT_CONVERT_OUT_BIT 0x4 -/* chooses differential inputs for adc (in conjunction with board jumper) */ -#define ADC_DIFF_BIT 0x8 -#define EXT_CONVERT_DISABLE_BIT 0x10 -/* 1200 boards only, calibration stuff */ -#define COMMAND5_REG 0x1c -/* enable eeprom for write */ -#define EEPROM_WRITE_UNPROTECT_BIT 0x4 -/* enable dithering */ -#define DITHER_EN_BIT 0x8 -/* load calibration dac */ -#define CALDAC_LOAD_BIT 0x10 -/* serial clock - rising edge writes, falling edge reads */ -#define SCLOCK_BIT 0x20 -/* serial data bit for writing to eeprom or calibration dacs */ -#define SDATA_BIT 0x40 -/* enable eeprom for read/write */ -#define EEPROM_EN_BIT 0x80 -#define INTERVAL_COUNT_REG 0x1e -#define INTERVAL_LOAD_REG 0x1f -#define INTERVAL_LOAD_BITS 0x1 - -/* read-only registers */ -#define STATUS1_REG 0x0 -/* data is available in fifo */ -#define DATA_AVAIL_BIT 0x1 -/* overrun has occurred */ -#define OVERRUN_BIT 0x2 -/* fifo overflow */ -#define OVERFLOW_BIT 0x4 -/* timer interrupt has occurred */ -#define TIMER_BIT 0x8 -/* dma terminal count has occurred */ -#define DMATC_BIT 0x10 -/* external trigger has occurred */ -#define EXT_TRIG_BIT 0x40 -/* 1200 boards only */ -#define STATUS2_REG 0x1d -/* programmable eeprom serial output */ -#define EEPROM_OUT_BIT 0x1 -/* counter A1 terminal count */ -#define A1_TC_BIT 0x2 -/* fifo not half full */ -#define FNHF_BIT 0x4 -#define ADC_FIFO_REG 0xa - -#define DIO_BASE_REG 0x10 -#define COUNTER_A_BASE_REG 0x14 -#define COUNTER_A_CONTROL_REG (COUNTER_A_BASE_REG + 0x3) -/* check modes put conversion pacer output in harmless state (a0 mode 2) */ -#define INIT_A0_BITS 0x14 -/* put hardware conversion counter output in harmless state (a1 mode 0) */ -#define INIT_A1_BITS 0x70 -#define COUNTER_B_BASE_REG 0x18 +/* + * Register map (all registers are 8-bit) + */ +#define STAT1_REG 0x00 /* R: Status 1 reg */ +#define STAT1_DAVAIL (1 << 0) +#define STAT1_OVERRUN (1 << 1) +#define STAT1_OVERFLOW (1 << 2) +#define STAT1_CNTINT (1 << 3) +#define STAT1_GATA0 (1 << 5) +#define STAT1_EXTGATA0 (1 << 6) +#define CMD1_REG 0x00 /* W: Command 1 reg */ +#define CMD1_MA(x) (((x) & 0x7) << 0) +#define CMD1_TWOSCMP (1 << 3) +#define CMD1_GAIN_MASK (7 << 4) +#define CMD1_SCANEN (1 << 7) +#define CMD2_REG 0x01 /* W: Command 2 reg */ +#define CMD2_PRETRIG (1 << 0) +#define CMD2_HWTRIG (1 << 1) +#define CMD2_SWTRIG (1 << 2) +#define CMD2_TBSEL (1 << 3) +#define CMD2_2SDAC0 (1 << 4) +#define CMD2_2SDAC1 (1 << 5) +#define CMD2_LDAC(x) (1 << (6 + (x))) +#define CMD3_REG 0x02 /* W: Command 3 reg */ +#define CMD3_DMAEN (1 << 0) +#define CMD3_DIOINTEN (1 << 1) +#define CMD3_DMATCINTEN (1 << 2) +#define CMD3_CNTINTEN (1 << 3) +#define CMD3_ERRINTEN (1 << 4) +#define CMD3_FIFOINTEN (1 << 5) +#define ADC_START_CONVERT_REG 0x03 /* W: Start Convert reg */ +#define DAC_LSB_REG(x) (0x04 + 2 * (x)) /* W: DAC0/1 LSB reg */ +#define DAC_MSB_REG(x) (0x05 + 2 * (x)) /* W: DAC0/1 MSB reg */ +#define ADC_FIFO_CLEAR_REG 0x08 /* W: A/D FIFO Clear reg */ +#define ADC_FIFO_REG 0x0a /* R: A/D FIFO reg */ +#define DMATC_CLEAR_REG 0x0a /* W: DMA Interrupt Clear reg */ +#define TIMER_CLEAR_REG 0x0c /* W: Timer Interrupt Clear reg */ +#define CMD6_REG 0x0e /* W: Command 6 reg */ +#define CMD6_NRSE (1 << 0) +#define CMD6_ADCUNI (1 << 1) +#define CMD6_DACUNI(x) (1 << (2 + (x))) +#define CMD6_HFINTEN (1 << 5) +#define CMD6_DQINTEN (1 << 6) +#define CMD6_SCANUP (1 << 7) +#define CMD4_REG 0x0f /* W: Command 3 reg */ +#define CMD4_INTSCAN (1 << 0) +#define CMD4_EOIRCV (1 << 1) +#define CMD4_ECLKDRV (1 << 2) +#define CMD4_SEDIFF (1 << 3) +#define CMD4_ECLKRCV (1 << 4) +#define DIO_BASE_REG 0x10 /* R/W: 8255 DIO base reg */ +#define COUNTER_A_BASE_REG 0x14 /* R/W: 8253 Counter A base reg */ +#define COUNTER_B_BASE_REG 0x18 /* R/W: 8253 Counter B base reg */ +#define CMD5_REG 0x1c /* W: Command 5 reg */ +#define CMD5_WRTPRT (1 << 2) +#define CMD5_DITHEREN (1 << 3) +#define CMD5_CALDACLD (1 << 4) +#define CMD5_SCLK (1 << 5) +#define CMD5_SDATA (1 << 6) +#define CMD5_EEPROMCS (1 << 7) +#define STAT2_REG 0x1d /* R: Status 2 reg */ +#define STAT2_PROMOUT (1 << 0) +#define STAT2_OUTA1 (1 << 1) +#define STAT2_FIFONHF (1 << 2) +#define INTERVAL_COUNT_REG 0x1e /* W: Interval Counter Data reg */ +#define INTERVAL_STROBE_REG 0x1f /* W: Interval Counter Strobe reg */ + +#define LABPC_SIZE 0x20 /* size of ISA io region */ +#define LABPC_TIMER_BASE 500 /* 2 MHz master clock */ +#define LABPC_ADC_TIMEOUT 1000 enum scan_mode { MODE_SINGLE_CHAN, @@ -215,187 +153,63 @@ enum scan_mode { MODE_MULT_CHAN_DOWN, }; -static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s); -static irqreturn_t labpc_interrupt(int irq, void *d); -static int labpc_drain_fifo(struct comedi_device *dev); -#ifdef CONFIG_ISA_DMA_API -static void labpc_drain_dma(struct comedi_device *dev); -static void handle_isa_dma(struct comedi_device *dev); -#endif -static void labpc_drain_dregs(struct comedi_device *dev); -static int labpc_ai_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_cmd *cmd); -static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s); -static int labpc_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int labpc_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int labpc_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int labpc_calib_read_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int labpc_calib_write_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int labpc_eeprom_read_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int labpc_eeprom_write_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data); -static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, - enum scan_mode scan_mode); -#ifdef CONFIG_ISA_DMA_API -static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd); -#endif -static int labpc_dio_mem_callback(int dir, int port, int data, - unsigned long arg); -static void labpc_serial_out(struct comedi_device *dev, unsigned int value, - unsigned int num_bits); -static unsigned int labpc_serial_in(struct comedi_device *dev); -static unsigned int labpc_eeprom_read(struct comedi_device *dev, - unsigned int address); -static unsigned int labpc_eeprom_read_status(struct comedi_device *dev); -static int labpc_eeprom_write(struct comedi_device *dev, - unsigned int address, - unsigned int value); -static void write_caldac(struct comedi_device *dev, unsigned int channel, - unsigned int value); - -/* analog input ranges */ -#define NUM_LABPC_PLUS_AI_RANGES 16 -/* indicates unipolar ranges */ -static const int labpc_plus_is_unipolar[NUM_LABPC_PLUS_AI_RANGES] = { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, -}; - -/* map range index to gain bits */ -static const int labpc_plus_ai_gain_bits[NUM_LABPC_PLUS_AI_RANGES] = { - 0x00, - 0x10, - 0x20, - 0x30, - 0x40, - 0x50, - 0x60, - 0x70, - 0x00, - 0x10, - 0x20, - 0x30, - 0x40, - 0x50, - 0x60, - 0x70, +static const int labpc_plus_ai_gain_bits[] = { + 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, + 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, }; static const struct comedi_lrange range_labpc_plus_ai = { - NUM_LABPC_PLUS_AI_RANGES, - { - BIP_RANGE(5), - BIP_RANGE(4), - BIP_RANGE(2.5), - BIP_RANGE(1), - BIP_RANGE(0.5), - BIP_RANGE(0.25), - BIP_RANGE(0.1), - BIP_RANGE(0.05), - UNI_RANGE(10), - UNI_RANGE(8), - UNI_RANGE(5), - UNI_RANGE(2), - UNI_RANGE(1), - UNI_RANGE(0.5), - UNI_RANGE(0.2), - UNI_RANGE(0.1), - } + 16, { + BIP_RANGE(5), + BIP_RANGE(4), + BIP_RANGE(2.5), + BIP_RANGE(1), + BIP_RANGE(0.5), + BIP_RANGE(0.25), + BIP_RANGE(0.1), + BIP_RANGE(0.05), + UNI_RANGE(10), + UNI_RANGE(8), + UNI_RANGE(5), + UNI_RANGE(2), + UNI_RANGE(1), + UNI_RANGE(0.5), + UNI_RANGE(0.2), + UNI_RANGE(0.1) + } }; -#define NUM_LABPC_1200_AI_RANGES 14 -/* indicates unipolar ranges */ -const int labpc_1200_is_unipolar[NUM_LABPC_1200_AI_RANGES] = { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, -}; -EXPORT_SYMBOL_GPL(labpc_1200_is_unipolar); - -/* map range index to gain bits */ -const int labpc_1200_ai_gain_bits[NUM_LABPC_1200_AI_RANGES] = { - 0x00, - 0x20, - 0x30, - 0x40, - 0x50, - 0x60, - 0x70, - 0x00, - 0x20, - 0x30, - 0x40, - 0x50, - 0x60, - 0x70, +const int labpc_1200_ai_gain_bits[] = { + 0x00, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, + 0x00, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, }; EXPORT_SYMBOL_GPL(labpc_1200_ai_gain_bits); const struct comedi_lrange range_labpc_1200_ai = { - NUM_LABPC_1200_AI_RANGES, - { - BIP_RANGE(5), - BIP_RANGE(2.5), - BIP_RANGE(1), - BIP_RANGE(0.5), - BIP_RANGE(0.25), - BIP_RANGE(0.1), - BIP_RANGE(0.05), - UNI_RANGE(10), - UNI_RANGE(5), - UNI_RANGE(2), - UNI_RANGE(1), - UNI_RANGE(0.5), - UNI_RANGE(0.2), - UNI_RANGE(0.1), - } + 14, { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1), + BIP_RANGE(0.5), + BIP_RANGE(0.25), + BIP_RANGE(0.1), + BIP_RANGE(0.05), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2), + UNI_RANGE(1), + UNI_RANGE(0.5), + UNI_RANGE(0.2), + UNI_RANGE(0.1) + } }; EXPORT_SYMBOL_GPL(range_labpc_1200_ai); -/* analog output ranges */ -#define AO_RANGE_IS_UNIPOLAR 0x1 static const struct comedi_lrange range_labpc_ao = { - 2, - { - BIP_RANGE(5), - UNI_RANGE(10), - } + 2, { + BIP_RANGE(5), + UNI_RANGE(10) + } }; /* functions that do inb/outb and readb/writeb so we can use @@ -420,413 +234,417 @@ static inline void labpc_writeb(unsigned int byte, unsigned long address) writeb(byte, (void __iomem *)address); } -static const struct labpc_board_struct labpc_boards[] = { - { - .name = "lab-pc-1200", - .ai_speed = 10000, - .bustype = isa_bustype, - .register_layout = labpc_1200_layout, - .has_ao = 1, - .ai_range_table = &range_labpc_1200_ai, - .ai_range_code = labpc_1200_ai_gain_bits, - .ai_range_is_unipolar = labpc_1200_is_unipolar, - .ai_scan_up = 1, - .memory_mapped_io = 0, - }, +#if IS_ENABLED(CONFIG_COMEDI_NI_LABPC_ISA) +static const struct labpc_boardinfo labpc_boards[] = { { - .name = "lab-pc-1200ai", - .ai_speed = 10000, - .bustype = isa_bustype, - .register_layout = labpc_1200_layout, - .has_ao = 0, - .ai_range_table = &range_labpc_1200_ai, - .ai_range_code = labpc_1200_ai_gain_bits, - .ai_range_is_unipolar = labpc_1200_is_unipolar, - .ai_scan_up = 1, - .memory_mapped_io = 0, - }, - { - .name = "lab-pc+", - .ai_speed = 12000, - .bustype = isa_bustype, - .register_layout = labpc_plus_layout, - .has_ao = 1, - .ai_range_table = &range_labpc_plus_ai, - .ai_range_code = labpc_plus_ai_gain_bits, - .ai_range_is_unipolar = labpc_plus_is_unipolar, - .ai_scan_up = 0, - .memory_mapped_io = 0, - }, -#ifdef CONFIG_COMEDI_PCI_DRIVERS - { - .name = "pci-1200", - .device_id = 0x161, - .ai_speed = 10000, - .bustype = pci_bustype, - .register_layout = labpc_1200_layout, - .has_ao = 1, - .ai_range_table = &range_labpc_1200_ai, - .ai_range_code = labpc_1200_ai_gain_bits, - .ai_range_is_unipolar = labpc_1200_is_unipolar, - .ai_scan_up = 1, - .memory_mapped_io = 1, - }, -/* dummy entry so pci board works when comedi_config is passed driver name */ - { - .name = DRV_NAME, - .bustype = pci_bustype, - }, -#endif + .name = "lab-pc-1200", + .ai_speed = 10000, + .register_layout = labpc_1200_layout, + .has_ao = 1, + .ai_range_table = &range_labpc_1200_ai, + .ai_range_code = labpc_1200_ai_gain_bits, + .ai_scan_up = 1, + }, { + .name = "lab-pc-1200ai", + .ai_speed = 10000, + .register_layout = labpc_1200_layout, + .ai_range_table = &range_labpc_1200_ai, + .ai_range_code = labpc_1200_ai_gain_bits, + .ai_scan_up = 1, + }, { + .name = "lab-pc+", + .ai_speed = 12000, + .register_layout = labpc_plus_layout, + .has_ao = 1, + .ai_range_table = &range_labpc_plus_ai, + .ai_range_code = labpc_plus_ai_gain_bits, + }, }; - -/* - * Useful for shorthand access to the particular board structure - */ -#define thisboard ((struct labpc_board_struct *)dev->board_ptr) +#endif /* size in bytes of dma buffer */ static const int dma_buffer_size = 0xff00; /* 2 bytes per sample */ static const int sample_size = 2; -static inline int labpc_counter_load(struct comedi_device *dev, - unsigned long base_address, - unsigned int counter_number, - unsigned int count, unsigned int mode) +static int labpc_counter_load(struct comedi_device *dev, + unsigned long base_address, + unsigned int counter_number, + unsigned int count, unsigned int mode) { - if (thisboard->memory_mapped_io) + const struct labpc_boardinfo *board = comedi_board(dev); + + if (board->has_mmio) return i8254_mm_load((void __iomem *)base_address, 0, counter_number, count, mode); else return i8254_load(base_address, 0, counter_number, count, mode); } -int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, - unsigned int irq, unsigned int dma_chan) +static int labpc_counter_set_mode(struct comedi_device *dev, + unsigned long base_address, + unsigned int counter_number, + unsigned int mode) +{ + const struct labpc_boardinfo *board = comedi_board(dev); + + if (board->has_mmio) + return i8254_mm_set_mode((void __iomem *)base_address, 0, + counter_number, mode); + else + return i8254_set_mode(base_address, 0, counter_number, mode); +} + +static bool labpc_range_is_unipolar(struct comedi_subdevice *s, + unsigned int range) +{ + return s->range_table->range[range].min >= 0; +} + +static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct labpc_private *devpriv = dev->private; - struct comedi_subdevice *s; - int i; - unsigned long isr_flags; -#ifdef CONFIG_ISA_DMA_API - unsigned long dma_flags; -#endif - short lsb, msb; - int ret; + unsigned long flags; - dev_info(dev->class_dev, "ni_labpc: %s\n", thisboard->name); - if (iobase == 0) { - dev_err(dev->class_dev, "io base address is zero!\n"); - return -EINVAL; - } - /* request io regions for isa boards */ - if (thisboard->bustype == isa_bustype) { - /* check if io addresses are available */ - if (!request_region(iobase, LABPC_SIZE, DRV_NAME)) { - dev_err(dev->class_dev, "I/O port conflict\n"); - return -EIO; - } - } - dev->iobase = iobase; + spin_lock_irqsave(&dev->spinlock, flags); + devpriv->cmd2 &= ~(CMD2_SWTRIG | CMD2_HWTRIG | CMD2_PRETRIG); + devpriv->write_byte(devpriv->cmd2, dev->iobase + CMD2_REG); + spin_unlock_irqrestore(&dev->spinlock, flags); - if (thisboard->memory_mapped_io) { - devpriv->read_byte = labpc_readb; - devpriv->write_byte = labpc_writeb; - } else { - devpriv->read_byte = labpc_inb; - devpriv->write_byte = labpc_outb; - } - /* initialize board's command registers */ - devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG); - devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); - devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG); - devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG); - if (thisboard->register_layout == labpc_1200_layout) { - devpriv->write_byte(devpriv->command5_bits, - dev->iobase + COMMAND5_REG); - devpriv->write_byte(devpriv->command6_bits, - dev->iobase + COMMAND6_REG); - } + devpriv->cmd3 = 0; + devpriv->write_byte(devpriv->cmd3, dev->iobase + CMD3_REG); - /* grab our IRQ */ - if (irq) { - isr_flags = 0; - if (thisboard->bustype == pci_bustype - || thisboard->bustype == pcmcia_bustype) - isr_flags |= IRQF_SHARED; - if (request_irq(irq, labpc_interrupt, isr_flags, - DRV_NAME, dev)) { - dev_err(dev->class_dev, "unable to allocate irq %u\n", - irq); - return -EINVAL; - } - } - dev->irq = irq; + return 0; +} -#ifdef CONFIG_ISA_DMA_API - /* grab dma channel */ - if (dma_chan > 3) { - dev_err(dev->class_dev, "invalid dma channel %u\n", dma_chan); - return -EINVAL; - } else if (dma_chan) { - /* allocate dma buffer */ - devpriv->dma_buffer = kmalloc(dma_buffer_size, - GFP_KERNEL | GFP_DMA); - if (devpriv->dma_buffer == NULL) - return -ENOMEM; +static void labpc_ai_set_chan_and_gain(struct comedi_device *dev, + enum scan_mode mode, + unsigned int chan, + unsigned int range, + unsigned int aref) +{ + const struct labpc_boardinfo *board = comedi_board(dev); + struct labpc_private *devpriv = dev->private; - if (request_dma(dma_chan, DRV_NAME)) { - dev_err(dev->class_dev, - "failed to allocate dma channel %u\n", - dma_chan); - return -EINVAL; - } - devpriv->dma_chan = dma_chan; - dma_flags = claim_dma_lock(); - disable_dma(devpriv->dma_chan); - set_dma_mode(devpriv->dma_chan, DMA_MODE_READ); - release_dma_lock(dma_flags); - } -#endif + /* munge channel bits for differential/scan disabled mode */ + if ((mode == MODE_SINGLE_CHAN || mode == MODE_SINGLE_CHAN_INTERVAL) && + aref == AREF_DIFF) + chan *= 2; + devpriv->cmd1 = CMD1_MA(chan); + devpriv->cmd1 |= board->ai_range_code[range]; - dev->board_name = thisboard->name; + devpriv->write_byte(devpriv->cmd1, dev->iobase + CMD1_REG); +} - ret = comedi_alloc_subdevices(dev, 5); - if (ret) - return ret; +static void labpc_setup_cmd6_reg(struct comedi_device *dev, + struct comedi_subdevice *s, + enum scan_mode mode, + enum transfer_type xfer, + unsigned int range, + unsigned int aref, + bool ena_intr) +{ + const struct labpc_boardinfo *board = comedi_board(dev); + struct labpc_private *devpriv = dev->private; - /* analog input subdevice */ - s = &dev->subdevices[0]; - dev->read_subdev = s; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = - SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF | SDF_CMD_READ; - s->n_chan = 8; - s->len_chanlist = 8; - s->maxdata = (1 << 12) - 1; /* 12 bit resolution */ - s->range_table = thisboard->ai_range_table; - s->do_cmd = labpc_ai_cmd; - s->do_cmdtest = labpc_ai_cmdtest; - s->insn_read = labpc_ai_rinsn; - s->cancel = labpc_cancel; + if (board->register_layout != labpc_1200_layout) + return; - /* analog output */ - s = &dev->subdevices[1]; - if (thisboard->has_ao) { - /* - * Could provide command support, except it only has a - * one sample hardware buffer for analog output and no - * underrun flag. - */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND; - s->n_chan = NUM_AO_CHAN; - s->maxdata = (1 << 12) - 1; /* 12 bit resolution */ - s->range_table = &range_labpc_ao; - s->insn_read = labpc_ao_rinsn; - s->insn_write = labpc_ao_winsn; - /* initialize analog outputs to a known value */ - for (i = 0; i < s->n_chan; i++) { - 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)); - } - } else { - s->type = COMEDI_SUBD_UNUSED; - } + /* reference inputs to ground or common? */ + if (aref != AREF_GROUND) + devpriv->cmd6 |= CMD6_NRSE; + else + devpriv->cmd6 &= ~CMD6_NRSE; - /* 8255 dio */ - s = &dev->subdevices[2]; - /* if board uses io memory we have to give a custom callback - * function to the 8255 driver */ - if (thisboard->memory_mapped_io) - subdev_8255_init(dev, s, labpc_dio_mem_callback, - (unsigned long)(dev->iobase + DIO_BASE_REG)); + /* bipolar or unipolar range? */ + if (labpc_range_is_unipolar(s, range)) + devpriv->cmd6 |= CMD6_ADCUNI; else - subdev_8255_init(dev, s, NULL, dev->iobase + DIO_BASE_REG); + devpriv->cmd6 &= ~CMD6_ADCUNI; - /* calibration subdevices for boards that have one */ - s = &dev->subdevices[3]; - if (thisboard->register_layout == labpc_1200_layout) { - s->type = COMEDI_SUBD_CALIB; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; - s->n_chan = 16; - s->maxdata = 0xff; - s->insn_read = labpc_calib_read_insn; - s->insn_write = labpc_calib_write_insn; + /* interrupt on fifo half full? */ + if (xfer == fifo_half_full_transfer) + devpriv->cmd6 |= CMD6_HFINTEN; + else + devpriv->cmd6 &= ~CMD6_HFINTEN; - for (i = 0; i < s->n_chan; i++) - write_caldac(dev, i, s->maxdata / 2); - } else - s->type = COMEDI_SUBD_UNUSED; + /* enable interrupt on counter a1 terminal count? */ + if (ena_intr) + devpriv->cmd6 |= CMD6_DQINTEN; + else + devpriv->cmd6 &= ~CMD6_DQINTEN; - /* EEPROM */ - s = &dev->subdevices[4]; - if (thisboard->register_layout == labpc_1200_layout) { - s->type = COMEDI_SUBD_MEMORY; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; - s->n_chan = EEPROM_SIZE; - s->maxdata = 0xff; - s->insn_read = labpc_eeprom_read_insn; - s->insn_write = labpc_eeprom_write_insn; - - for (i = 0; i < EEPROM_SIZE; i++) - devpriv->eeprom_data[i] = labpc_eeprom_read(dev, i); - } else - s->type = COMEDI_SUBD_UNUSED; + /* are we scanning up or down through channels? */ + if (mode == MODE_MULT_CHAN_UP) + devpriv->cmd6 |= CMD6_SCANUP; + else + devpriv->cmd6 &= ~CMD6_SCANUP; - return 0; + devpriv->write_byte(devpriv->cmd6, dev->iobase + CMD6_REG); } -EXPORT_SYMBOL_GPL(labpc_common_attach); -static const struct labpc_board_struct * -labpc_pci_find_boardinfo(struct pci_dev *pcidev) +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); + + return (msb << 8) | lsb; +} + +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); + labpc_read_adc_fifo(dev); +} + +static int labpc_ai_wait_for_data(struct comedi_device *dev, + int timeout) { - unsigned int device_id = pcidev->device; - unsigned int n; - - for (n = 0; n < ARRAY_SIZE(labpc_boards); n++) { - const struct labpc_board_struct *board = &labpc_boards[n]; - if (board->bustype == pci_bustype && - board->device_id == device_id) - return board; + struct labpc_private *devpriv = dev->private; + int i; + + for (i = 0; i < timeout; i++) { + devpriv->stat1 = devpriv->read_byte(dev->iobase + STAT1_REG); + if (devpriv->stat1 & STAT1_DAVAIL) + return 0; + udelay(1); } - return NULL; + return -ETIME; } -static int labpc_auto_attach(struct comedi_device *dev, - unsigned long context_unused) +static int labpc_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - struct labpc_private *devpriv; - unsigned long iobase; - unsigned int irq; + struct labpc_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); + unsigned int aref = CR_AREF(insn->chanspec); int ret; + int i; - if (!IS_ENABLED(CONFIG_COMEDI_PCI_DRIVERS)) - return -ENODEV; + /* disable timed conversions, interrupt generation and dma */ + labpc_cancel(dev, s); - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); - if (!devpriv) - return -ENOMEM; - dev->private = devpriv; + labpc_ai_set_chan_and_gain(dev, MODE_SINGLE_CHAN, chan, range, aref); - dev->board_ptr = labpc_pci_find_boardinfo(pcidev); - if (!dev->board_ptr) - return -ENODEV; - devpriv->mite = mite_alloc(pcidev); - if (!devpriv->mite) - return -ENOMEM; - ret = mite_setup(devpriv->mite); - if (ret < 0) + labpc_setup_cmd6_reg(dev, s, MODE_SINGLE_CHAN, fifo_not_empty_transfer, + range, aref, false); + + /* setup cmd4 register */ + devpriv->cmd4 = 0; + devpriv->cmd4 |= CMD4_ECLKRCV; + /* single-ended/differential */ + if (aref == AREF_DIFF) + devpriv->cmd4 |= CMD4_SEDIFF; + devpriv->write_byte(devpriv->cmd4, dev->iobase + CMD4_REG); + + /* initialize pacer counter to prevent any problems */ + ret = labpc_counter_set_mode(dev, dev->iobase + COUNTER_A_BASE_REG, + 0, I8254_MODE2); + if (ret) return ret; - iobase = (unsigned long)devpriv->mite->daq_io_addr; - irq = mite_irq(devpriv->mite); - return labpc_common_attach(dev, iobase, irq, 0); + + labpc_clear_adc_fifo(dev); + + for (i = 0; i < insn->n; i++) { + /* trigger conversion */ + devpriv->write_byte(0x1, dev->iobase + ADC_START_CONVERT_REG); + + ret = labpc_ai_wait_for_data(dev, LABPC_ADC_TIMEOUT); + if (ret) + return ret; + + data[i] = labpc_read_adc_fifo(dev); + } + + return insn->n; } -static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) +#ifdef CONFIG_ISA_DMA_API +/* utility function that suggests a dma transfer size in bytes */ +static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd) { - struct labpc_private *devpriv; - unsigned long iobase = 0; - unsigned int irq = 0; - unsigned int dma_chan = 0; + unsigned int size; + unsigned int freq; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); - if (!devpriv) - return -ENOMEM; - dev->private = devpriv; + if (cmd->convert_src == TRIG_TIMER) + freq = 1000000000 / cmd->convert_arg; + /* return some default value */ + else + freq = 0xffffffff; - /* get base address, irq etc. based on bustype */ - switch (thisboard->bustype) { - case isa_bustype: -#ifdef CONFIG_ISA_DMA_API - iobase = it->options[0]; - irq = it->options[1]; - dma_chan = it->options[2]; -#else - dev_err(dev->class_dev, - "ni_labpc driver has not been built with ISA DMA support.\n"); - return -EINVAL; -#endif - break; - case pci_bustype: -#ifdef CONFIG_COMEDI_PCI_DRIVERS - dev_err(dev->class_dev, - "manual configuration of PCI board '%s' is not supported\n", - thisboard->name); - return -EINVAL; -#else - dev_err(dev->class_dev, - "ni_labpc driver has not been built with PCI support.\n"); - return -EINVAL; + /* make buffer fill in no more than 1/3 second */ + size = (freq / 3) * sample_size; + + /* set a minimum and maximum size allowed */ + if (size > dma_buffer_size) + size = dma_buffer_size - dma_buffer_size % sample_size; + else if (size < sample_size) + size = sample_size; + + return size; +} #endif - break; - default: - dev_err(dev->class_dev, - "ni_labpc: bug! couldn't determine board type\n"); - return -EINVAL; - break; - } - return labpc_common_attach(dev, iobase, irq, dma_chan); +static bool labpc_use_continuous_mode(const struct comedi_cmd *cmd, + enum scan_mode mode) +{ + if (mode == MODE_SINGLE_CHAN || cmd->scan_begin_src == TRIG_FOLLOW) + return true; + + return false; } -void labpc_common_detach(struct comedi_device *dev) +static unsigned int labpc_ai_convert_period(const struct comedi_cmd *cmd, + enum scan_mode mode) { - struct labpc_private *devpriv = dev->private; - struct comedi_subdevice *s; + if (cmd->convert_src != TRIG_TIMER) + return 0; + + if (mode == MODE_SINGLE_CHAN && cmd->scan_begin_src == TRIG_TIMER) + return cmd->scan_begin_arg; - if (!thisboard) + return cmd->convert_arg; +} + +static void labpc_set_ai_convert_period(struct comedi_cmd *cmd, + enum scan_mode mode, unsigned int ns) +{ + if (cmd->convert_src != TRIG_TIMER) return; - if (dev->subdevices) { - s = &dev->subdevices[2]; - subdev_8255_cleanup(dev, s); - } -#ifdef CONFIG_ISA_DMA_API - /* only free stuff if it has been allocated by _attach */ - kfree(devpriv->dma_buffer); - if (devpriv->dma_chan) - free_dma(devpriv->dma_chan); -#endif - if (dev->irq) - free_irq(dev->irq, dev); - if (thisboard->bustype == isa_bustype && dev->iobase) - release_region(dev->iobase, LABPC_SIZE); -#ifdef CONFIG_COMEDI_PCI_DRIVERS - if (devpriv->mite) { - mite_unsetup(devpriv->mite); - mite_free(devpriv->mite); - } -#endif -}; -EXPORT_SYMBOL_GPL(labpc_common_detach); -static void labpc_clear_adc_fifo(const struct comedi_device *dev) + if (mode == MODE_SINGLE_CHAN && + cmd->scan_begin_src == TRIG_TIMER) { + cmd->scan_begin_arg = ns; + if (cmd->convert_arg > cmd->scan_begin_arg) + cmd->convert_arg = cmd->scan_begin_arg; + } else + cmd->convert_arg = ns; +} + +static unsigned int labpc_ai_scan_period(const struct comedi_cmd *cmd, + enum scan_mode mode) { - struct labpc_private *devpriv = dev->private; + if (cmd->scan_begin_src != TRIG_TIMER) + return 0; - devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG); - devpriv->read_byte(dev->iobase + ADC_FIFO_REG); - devpriv->read_byte(dev->iobase + ADC_FIFO_REG); + if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER) + return 0; + + return cmd->scan_begin_arg; } -static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s) +static void labpc_set_ai_scan_period(struct comedi_cmd *cmd, + enum scan_mode mode, unsigned int ns) +{ + if (cmd->scan_begin_src != TRIG_TIMER) + return; + + if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER) + return; + + cmd->scan_begin_arg = ns; +} + +/* figures out what counter values to use based on command */ +static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, + enum scan_mode mode) { struct labpc_private *devpriv = dev->private; - unsigned long flags; + /* max value for 16 bit counter in mode 2 */ + const int max_counter_value = 0x10000; + /* min value for 16 bit counter in mode 2 */ + const int min_counter_value = 2; + unsigned int base_period; + unsigned int scan_period; + unsigned int convert_period; - spin_lock_irqsave(&dev->spinlock, flags); - devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT; - devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); - spin_unlock_irqrestore(&dev->spinlock, flags); + /* + * if both convert and scan triggers are TRIG_TIMER, then they + * both rely on counter b0 + */ + convert_period = labpc_ai_convert_period(cmd, mode); + scan_period = labpc_ai_scan_period(cmd, mode); + if (convert_period && scan_period) { + /* + * pick the lowest b0 divisor value we can (for maximum input + * clock speed on convert and scan counters) + */ + devpriv->divisor_b0 = (scan_period - 1) / + (LABPC_TIMER_BASE * max_counter_value) + 1; + if (devpriv->divisor_b0 < min_counter_value) + devpriv->divisor_b0 = min_counter_value; + if (devpriv->divisor_b0 > max_counter_value) + devpriv->divisor_b0 = max_counter_value; - devpriv->command3_bits = 0; - devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG); + base_period = LABPC_TIMER_BASE * devpriv->divisor_b0; - return 0; + /* set a0 for conversion frequency and b1 for scan frequency */ + switch (cmd->flags & TRIG_ROUND_MASK) { + default: + case TRIG_ROUND_NEAREST: + devpriv->divisor_a0 = + (convert_period + (base_period / 2)) / base_period; + devpriv->divisor_b1 = + (scan_period + (base_period / 2)) / base_period; + break; + case TRIG_ROUND_UP: + devpriv->divisor_a0 = + (convert_period + (base_period - 1)) / base_period; + devpriv->divisor_b1 = + (scan_period + (base_period - 1)) / base_period; + break; + case TRIG_ROUND_DOWN: + devpriv->divisor_a0 = convert_period / base_period; + devpriv->divisor_b1 = scan_period / base_period; + break; + } + /* make sure a0 and b1 values are acceptable */ + if (devpriv->divisor_a0 < min_counter_value) + devpriv->divisor_a0 = min_counter_value; + if (devpriv->divisor_a0 > max_counter_value) + devpriv->divisor_a0 = max_counter_value; + if (devpriv->divisor_b1 < min_counter_value) + devpriv->divisor_b1 = min_counter_value; + if (devpriv->divisor_b1 > max_counter_value) + devpriv->divisor_b1 = max_counter_value; + /* write corrected timings to command */ + labpc_set_ai_convert_period(cmd, mode, + base_period * devpriv->divisor_a0); + labpc_set_ai_scan_period(cmd, mode, + base_period * devpriv->divisor_b1); + /* + * if only one TRIG_TIMER is used, we can employ the generic + * cascaded timing functions + */ + } else if (scan_period) { + /* + * calculate cascaded counter values + * that give desired scan timing + */ + i8253_cascade_ns_to_timer_2div(LABPC_TIMER_BASE, + &(devpriv->divisor_b1), + &(devpriv->divisor_b0), + &scan_period, + cmd->flags & TRIG_ROUND_MASK); + labpc_set_ai_scan_period(cmd, mode, scan_period); + } else if (convert_period) { + /* + * calculate cascaded counter values + * that give desired conversion timing + */ + i8253_cascade_ns_to_timer_2div(LABPC_TIMER_BASE, + &(devpriv->divisor_a0), + &(devpriv->divisor_b0), + &convert_period, + cmd->flags & TRIG_ROUND_MASK); + labpc_set_ai_convert_period(cmd, mode, convert_period); + } } static enum scan_mode labpc_ai_scan_mode(const struct comedi_cmd *cmd) @@ -923,72 +741,10 @@ static int labpc_ai_chanlist_invalid(const struct comedi_device *dev, return 0; } -static int labpc_use_continuous_mode(const struct comedi_cmd *cmd, - enum scan_mode mode) -{ - if (mode == MODE_SINGLE_CHAN) - return 1; - - if (cmd->scan_begin_src == TRIG_FOLLOW) - return 1; - - return 0; -} - -static unsigned int labpc_ai_convert_period(const struct comedi_cmd *cmd, - enum scan_mode mode) -{ - if (cmd->convert_src != TRIG_TIMER) - return 0; - - if (mode == MODE_SINGLE_CHAN && cmd->scan_begin_src == TRIG_TIMER) - return cmd->scan_begin_arg; - - return cmd->convert_arg; -} - -static void labpc_set_ai_convert_period(struct comedi_cmd *cmd, - enum scan_mode mode, unsigned int ns) -{ - if (cmd->convert_src != TRIG_TIMER) - return; - - if (mode == MODE_SINGLE_CHAN && - cmd->scan_begin_src == TRIG_TIMER) { - cmd->scan_begin_arg = ns; - if (cmd->convert_arg > cmd->scan_begin_arg) - cmd->convert_arg = cmd->scan_begin_arg; - } else - cmd->convert_arg = ns; -} - -static unsigned int labpc_ai_scan_period(const struct comedi_cmd *cmd, - enum scan_mode mode) -{ - if (cmd->scan_begin_src != TRIG_TIMER) - return 0; - - if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER) - return 0; - - return cmd->scan_begin_arg; -} - -static void labpc_set_ai_scan_period(struct comedi_cmd *cmd, - enum scan_mode mode, unsigned int ns) -{ - if (cmd->scan_begin_src != TRIG_TIMER) - return; - - if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER) - return; - - cmd->scan_begin_arg = ns; -} - static int labpc_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + const struct labpc_boardinfo *board = comedi_board(dev); int err = 0; int tmp, tmp2; unsigned int stop_mask; @@ -1003,7 +759,7 @@ static int labpc_ai_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); stop_mask = TRIG_COUNT | TRIG_NONE; - if (thisboard->register_layout == labpc_1200_layout) + if (board->register_layout == labpc_1200_layout) stop_mask |= TRIG_EXT; err |= cfc_check_trigger_src(&cmd->stop_src, stop_mask); @@ -1037,7 +793,7 @@ static int labpc_ai_cmdtest(struct comedi_device *dev, if (cmd->convert_src == TRIG_TIMER) err |= cfc_check_trigger_arg_min(&cmd->convert_arg, - thisboard->ai_speed); + board->ai_speed); /* make sure scan timing is not too fast */ if (cmd->scan_begin_src == TRIG_TIMER) { @@ -1045,7 +801,7 @@ static int labpc_ai_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, cmd->convert_arg * cmd->chanlist_len); err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, - thisboard->ai_speed * cmd->chanlist_len); + board->ai_speed * cmd->chanlist_len); } switch (cmd->stop_src) { @@ -1086,34 +842,23 @@ static int labpc_ai_cmdtest(struct comedi_device *dev, static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { + const struct labpc_boardinfo *board = comedi_board(dev); struct labpc_private *devpriv = dev->private; - int channel, range, aref; -#ifdef CONFIG_ISA_DMA_API - unsigned long irq_flags; -#endif - int ret; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; + enum scan_mode mode = labpc_ai_scan_mode(cmd); + unsigned int chanspec = (mode == MODE_MULT_CHAN_UP) + ? cmd->chanlist[cmd->chanlist_len - 1] + : cmd->chanlist[0]; + unsigned int chan = CR_CHAN(chanspec); + unsigned int range = CR_RANGE(chanspec); + unsigned int aref = CR_AREF(chanspec); enum transfer_type xfer; - enum scan_mode mode; unsigned long flags; - - if (!dev->irq) { - comedi_error(dev, "no irq assigned, cannot perform command"); - return -1; - } - - range = CR_RANGE(cmd->chanlist[0]); - aref = CR_AREF(cmd->chanlist[0]); + int ret; /* make sure board is disabled before setting up acquisition */ - spin_lock_irqsave(&dev->spinlock, flags); - devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT; - devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); - spin_unlock_irqrestore(&dev->spinlock, flags); - - devpriv->command3_bits = 0; - devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG); + labpc_cancel(dev, s); /* initialize software conversion count */ if (cmd->stop_src == TRIG_COUNT) @@ -1126,17 +871,17 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * (pc+ manual says this is minimum allowed) using mode 0 */ ret = labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG, - 1, 3, 0); - if (ret < 0) { - comedi_error(dev, "error loading counter a1"); - return -1; - } - } else /* - * otherwise, just put a1 in mode 0 - * with no count to set its output low - */ - devpriv->write_byte(INIT_A1_BITS, - dev->iobase + COUNTER_A_CONTROL_REG); + 1, 3, I8254_MODE0); + } else { + /* just put counter a1 in mode 0 to set its output low */ + ret = labpc_counter_set_mode(dev, + dev->iobase + COUNTER_A_BASE_REG, + 1, I8254_MODE0); + } + if (ret) { + comedi_error(dev, "error loading counter a1"); + return ret; + } #ifdef CONFIG_ISA_DMA_API /* figure out what method we will use to transfer data */ @@ -1145,14 +890,12 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * dma unsafe at RT priority, * and too much setup time for TRIG_WAKE_EOS for */ - (cmd->flags & (TRIG_WAKE_EOS | TRIG_RT)) == 0 && - /* only available on the isa boards */ - thisboard->bustype == isa_bustype) { + (cmd->flags & (TRIG_WAKE_EOS | TRIG_RT)) == 0) { xfer = isa_dma_transfer; /* pc-plus has no fifo-half full interrupt */ } else #endif - if (thisboard->register_layout == labpc_1200_layout && + if (board->register_layout == labpc_1200_layout && /* wake-end-of-scan should interrupt on fifo not empty */ (cmd->flags & TRIG_WAKE_EOS) == 0 && /* make sure we are taking more than just a few points */ @@ -1161,76 +904,34 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } else xfer = fifo_not_empty_transfer; devpriv->current_transfer = xfer; - mode = labpc_ai_scan_mode(cmd); - /* setup command6 register for 1200 boards */ - if (thisboard->register_layout == labpc_1200_layout) { - /* reference inputs to ground or common? */ - if (aref != AREF_GROUND) - devpriv->command6_bits |= ADC_COMMON_BIT; - else - devpriv->command6_bits &= ~ADC_COMMON_BIT; - /* bipolar or unipolar range? */ - if (thisboard->ai_range_is_unipolar[range]) - devpriv->command6_bits |= ADC_UNIP_BIT; - else - devpriv->command6_bits &= ~ADC_UNIP_BIT; - /* interrupt on fifo half full? */ - if (xfer == fifo_half_full_transfer) - devpriv->command6_bits |= ADC_FHF_INTR_EN_BIT; - else - devpriv->command6_bits &= ~ADC_FHF_INTR_EN_BIT; - /* enable interrupt on counter a1 terminal count? */ - if (cmd->stop_src == TRIG_EXT) - devpriv->command6_bits |= A1_INTR_EN_BIT; - else - devpriv->command6_bits &= ~A1_INTR_EN_BIT; - /* are we scanning up or down through channels? */ - if (mode == MODE_MULT_CHAN_UP) - devpriv->command6_bits |= ADC_SCAN_UP_BIT; - else - devpriv->command6_bits &= ~ADC_SCAN_UP_BIT; - /* write to register */ - devpriv->write_byte(devpriv->command6_bits, - dev->iobase + COMMAND6_REG); - } + labpc_ai_set_chan_and_gain(dev, mode, chan, range, aref); + + labpc_setup_cmd6_reg(dev, s, mode, xfer, range, aref, + (cmd->stop_src == TRIG_EXT)); - /* setup channel list, etc (command1 register) */ - devpriv->command1_bits = 0; - if (mode == MODE_MULT_CHAN_UP) - channel = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]); - else - channel = CR_CHAN(cmd->chanlist[0]); - /* munge channel bits for differential / scan disabled mode */ - if ((mode == MODE_SINGLE_CHAN || mode == MODE_SINGLE_CHAN_INTERVAL) && - aref == AREF_DIFF) - channel *= 2; - devpriv->command1_bits |= ADC_CHAN_BITS(channel); - devpriv->command1_bits |= thisboard->ai_range_code[range]; - devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG); /* manual says to set scan enable bit on second pass */ if (mode == MODE_MULT_CHAN_UP || mode == MODE_MULT_CHAN_DOWN) { - devpriv->command1_bits |= ADC_SCAN_EN_BIT; + devpriv->cmd1 |= CMD1_SCANEN; /* need a brief delay before enabling scan, or scan * list will get screwed when you switch * between scan up to scan down mode - dunno why */ udelay(1); - devpriv->write_byte(devpriv->command1_bits, - dev->iobase + COMMAND1_REG); + devpriv->write_byte(devpriv->cmd1, dev->iobase + CMD1_REG); } devpriv->write_byte(cmd->chanlist_len, dev->iobase + INTERVAL_COUNT_REG); /* load count */ - devpriv->write_byte(INTERVAL_LOAD_BITS, - dev->iobase + INTERVAL_LOAD_REG); + devpriv->write_byte(0x1, dev->iobase + INTERVAL_STROBE_REG); - if (cmd->convert_src == TRIG_TIMER || cmd->scan_begin_src == TRIG_TIMER) { + 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 */ ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG, - 0, devpriv->divisor_b0, 3); + 0, devpriv->divisor_b0, I8254_MODE3); if (ret < 0) { comedi_error(dev, "error loading counter b0"); return -1; @@ -1240,20 +941,23 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (labpc_ai_convert_period(cmd, mode)) { /* load counter a0 in mode 2 */ ret = labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG, - 0, devpriv->divisor_a0, 2); - if (ret < 0) { - comedi_error(dev, "error loading counter a0"); - return -1; - } - } else - devpriv->write_byte(INIT_A0_BITS, - dev->iobase + COUNTER_A_CONTROL_REG); + 0, devpriv->divisor_a0, I8254_MODE2); + } else { + /* initialize pacer counter to prevent any problems */ + ret = labpc_counter_set_mode(dev, + dev->iobase + COUNTER_A_BASE_REG, + 0, I8254_MODE2); + } + if (ret) { + comedi_error(dev, "error loading counter a0"); + return ret; + } /* set up scan pacing */ if (labpc_ai_scan_period(cmd, mode)) { /* load counter b1 in mode 2 */ ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG, - 1, devpriv->divisor_b1, 2); + 1, devpriv->divisor_b1, I8254_MODE2); if (ret < 0) { comedi_error(dev, "error loading counter b1"); return -1; @@ -1265,6 +969,8 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) #ifdef CONFIG_ISA_DMA_API /* set up dma transfer */ if (xfer == isa_dma_transfer) { + unsigned long irq_flags; + irq_flags = claim_dma_lock(); disable_dma(devpriv->dma_chan); /* clear flip-flop to make sure 2-byte registers for @@ -1283,197 +989,54 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) enable_dma(devpriv->dma_chan); release_dma_lock(irq_flags); /* enable board's dma */ - devpriv->command3_bits |= DMA_EN_BIT | DMATC_INTR_EN_BIT; + devpriv->cmd3 |= (CMD3_DMAEN | CMD3_DMATCINTEN); } else - devpriv->command3_bits &= ~DMA_EN_BIT & ~DMATC_INTR_EN_BIT; + devpriv->cmd3 &= ~(CMD3_DMAEN | CMD3_DMATCINTEN); #endif /* enable error interrupts */ - devpriv->command3_bits |= ERR_INTR_EN_BIT; + devpriv->cmd3 |= CMD3_ERRINTEN; /* enable fifo not empty interrupt? */ if (xfer == fifo_not_empty_transfer) - devpriv->command3_bits |= ADC_FNE_INTR_EN_BIT; + devpriv->cmd3 |= CMD3_FIFOINTEN; else - devpriv->command3_bits &= ~ADC_FNE_INTR_EN_BIT; - devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG); + devpriv->cmd3 &= ~CMD3_FIFOINTEN; + devpriv->write_byte(devpriv->cmd3, dev->iobase + CMD3_REG); - /* setup any external triggering/pacing (command4 register) */ - devpriv->command4_bits = 0; + /* setup any external triggering/pacing (cmd4 register) */ + devpriv->cmd4 = 0; if (cmd->convert_src != TRIG_EXT) - devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT; + devpriv->cmd4 |= CMD4_ECLKRCV; /* XXX should discard first scan when using interval scanning * since manual says it is not synced with scan clock */ - if (labpc_use_continuous_mode(cmd, mode) == 0) { - devpriv->command4_bits |= INTERVAL_SCAN_EN_BIT; + if (!labpc_use_continuous_mode(cmd, mode)) { + devpriv->cmd4 |= CMD4_INTSCAN; if (cmd->scan_begin_src == TRIG_EXT) - devpriv->command4_bits |= EXT_SCAN_EN_BIT; + devpriv->cmd4 |= CMD4_EOIRCV; } /* single-ended/differential */ if (aref == AREF_DIFF) - devpriv->command4_bits |= ADC_DIFF_BIT; - devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG); + devpriv->cmd4 |= CMD4_SEDIFF; + devpriv->write_byte(devpriv->cmd4, dev->iobase + CMD4_REG); /* startup acquisition */ - /* command2 reg */ - /* use 2 cascaded counters for pacing */ spin_lock_irqsave(&dev->spinlock, flags); - devpriv->command2_bits |= CASCADE_BIT; - switch (cmd->start_src) { - case TRIG_EXT: - devpriv->command2_bits |= HWTRIG_BIT; - devpriv->command2_bits &= ~PRETRIG_BIT & ~SWTRIG_BIT; - break; - case TRIG_NOW: - devpriv->command2_bits |= SWTRIG_BIT; - devpriv->command2_bits &= ~PRETRIG_BIT & ~HWTRIG_BIT; - break; - default: - comedi_error(dev, "bug with start_src"); - spin_unlock_irqrestore(&dev->spinlock, flags); - return -1; - break; - } - switch (cmd->stop_src) { - case TRIG_EXT: - devpriv->command2_bits |= HWTRIG_BIT | PRETRIG_BIT; - break; - case TRIG_COUNT: - case TRIG_NONE: - break; - default: - comedi_error(dev, "bug with stop_src"); - spin_unlock_irqrestore(&dev->spinlock, flags); - return -1; - } - devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); - spin_unlock_irqrestore(&dev->spinlock, flags); - - return 0; -} - -/* interrupt service routine */ -static irqreturn_t labpc_interrupt(int irq, void *d) -{ - struct comedi_device *dev = d; - struct labpc_private *devpriv = dev->private; - struct comedi_subdevice *s = dev->read_subdev; - struct comedi_async *async; - struct comedi_cmd *cmd; - - if (dev->attached == 0) { - comedi_error(dev, "premature interrupt"); - return IRQ_HANDLED; - } - - async = s->async; - cmd = &async->cmd; - async->events = 0; - - /* read board status */ - devpriv->status1_bits = devpriv->read_byte(dev->iobase + STATUS1_REG); - if (thisboard->register_layout == labpc_1200_layout) - devpriv->status2_bits = - devpriv->read_byte(dev->iobase + STATUS2_REG); - - if ((devpriv->status1_bits & (DMATC_BIT | TIMER_BIT | OVERFLOW_BIT | - OVERRUN_BIT | DATA_AVAIL_BIT)) == 0 - && (devpriv->status2_bits & A1_TC_BIT) == 0 - && (devpriv->status2_bits & FNHF_BIT)) { - return IRQ_NONE; - } - - if (devpriv->status1_bits & OVERRUN_BIT) { - /* clear error interrupt */ - devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; - comedi_event(dev, s); - comedi_error(dev, "overrun"); - return IRQ_HANDLED; - } - -#ifdef CONFIG_ISA_DMA_API - if (devpriv->current_transfer == isa_dma_transfer) { - /* - * if a dma terminal count of external stop trigger - * has occurred - */ - if (devpriv->status1_bits & DMATC_BIT || - (thisboard->register_layout == labpc_1200_layout - && devpriv->status2_bits & A1_TC_BIT)) { - handle_isa_dma(dev); - } - } else -#endif - labpc_drain_fifo(dev); - - if (devpriv->status1_bits & TIMER_BIT) { - comedi_error(dev, "handled timer interrupt?"); - /* clear it */ - devpriv->write_byte(0x1, dev->iobase + TIMER_CLEAR_REG); - } - - if (devpriv->status1_bits & OVERFLOW_BIT) { - /* clear error interrupt */ - devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; - comedi_event(dev, s); - comedi_error(dev, "overflow"); - return IRQ_HANDLED; - } - /* handle external stop trigger */ - if (cmd->stop_src == TRIG_EXT) { - if (devpriv->status2_bits & A1_TC_BIT) { - labpc_drain_dregs(dev); - labpc_cancel(dev, s); - async->events |= COMEDI_CB_EOA; - } - } - - /* TRIG_COUNT end of acquisition */ - if (cmd->stop_src == TRIG_COUNT) { - if (devpriv->count == 0) { - labpc_cancel(dev, s); - async->events |= COMEDI_CB_EOA; - } - } - comedi_event(dev, s); - return IRQ_HANDLED; -} + /* use 2 cascaded counters for pacing */ + devpriv->cmd2 |= CMD2_TBSEL; -/* read all available samples from ai fifo */ -static int labpc_drain_fifo(struct comedi_device *dev) -{ - struct labpc_private *devpriv = dev->private; - unsigned int lsb, msb; - short data; - struct comedi_async *async = dev->read_subdev->async; - const int timeout = 10000; - unsigned int i; + devpriv->cmd2 &= ~(CMD2_SWTRIG | CMD2_HWTRIG | CMD2_PRETRIG); + if (cmd->start_src == TRIG_EXT) + devpriv->cmd2 |= CMD2_HWTRIG; + else + devpriv->cmd2 |= CMD2_SWTRIG; + if (cmd->stop_src == TRIG_EXT) + devpriv->cmd2 |= (CMD2_HWTRIG | CMD2_PRETRIG); - devpriv->status1_bits = devpriv->read_byte(dev->iobase + STATUS1_REG); + devpriv->write_byte(devpriv->cmd2, dev->iobase + CMD2_REG); - for (i = 0; (devpriv->status1_bits & DATA_AVAIL_BIT) && i < timeout; - i++) { - /* quit if we have all the data we want */ - if (async->cmd.stop_src == TRIG_COUNT) { - if (devpriv->count == 0) - break; - devpriv->count--; - } - lsb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG); - msb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG); - data = (msb << 8) | lsb; - cfc_write_to_buffer(dev->read_subdev, data); - devpriv->status1_bits = - devpriv->read_byte(dev->iobase + STATUS1_REG); - } - if (i == timeout) { - comedi_error(dev, "ai timeout, fifo never empties"); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; - return -1; - } + spin_unlock_irqrestore(&dev->spinlock, flags); return 0; } @@ -1489,7 +1052,7 @@ static void labpc_drain_dma(struct comedi_device *dev) unsigned int max_points, num_points, residue, leftover; int i; - status = devpriv->status1_bits; + status = devpriv->stat1; flags = claim_dma_lock(); disable_dma(devpriv->dma_chan); @@ -1546,6 +1109,38 @@ static void handle_isa_dma(struct comedi_device *dev) } #endif +/* read all available samples from ai fifo */ +static int labpc_drain_fifo(struct comedi_device *dev) +{ + struct labpc_private *devpriv = dev->private; + short data; + struct comedi_async *async = dev->read_subdev->async; + const int timeout = 10000; + unsigned int i; + + devpriv->stat1 = devpriv->read_byte(dev->iobase + STAT1_REG); + + for (i = 0; (devpriv->stat1 & STAT1_DAVAIL) && i < timeout; + i++) { + /* quit if we have all the data we want */ + if (async->cmd.stop_src == TRIG_COUNT) { + if (devpriv->count == 0) + break; + devpriv->count--; + } + data = labpc_read_adc_fifo(dev); + cfc_write_to_buffer(dev->read_subdev, data); + devpriv->stat1 = devpriv->read_byte(dev->iobase + STAT1_REG); + } + if (i == timeout) { + comedi_error(dev, "ai timeout, fifo never empties"); + async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + return -1; + } + + return 0; +} + /* makes sure all data acquired by board is transferred to comedi (used * when acquisition is terminated by stop_src == TRIG_EXT). */ static void labpc_drain_dregs(struct comedi_device *dev) @@ -1560,99 +1155,102 @@ static void labpc_drain_dregs(struct comedi_device *dev) labpc_drain_fifo(dev); } -static int labpc_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +/* interrupt service routine */ +static irqreturn_t labpc_interrupt(int irq, void *d) { + struct comedi_device *dev = d; + const struct labpc_boardinfo *board = comedi_board(dev); struct labpc_private *devpriv = dev->private; - int i, n; - int chan, range; - int lsb, msb; - int timeout = 1000; - unsigned long flags; + struct comedi_subdevice *s = dev->read_subdev; + struct comedi_async *async; + struct comedi_cmd *cmd; - /* disable timed conversions */ - spin_lock_irqsave(&dev->spinlock, flags); - devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT; - devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); - spin_unlock_irqrestore(&dev->spinlock, flags); + if (!dev->attached) { + comedi_error(dev, "premature interrupt"); + return IRQ_HANDLED; + } - /* disable interrupt generation and dma */ - devpriv->command3_bits = 0; - devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG); + async = s->async; + cmd = &async->cmd; + async->events = 0; - /* set gain and channel */ - devpriv->command1_bits = 0; - chan = CR_CHAN(insn->chanspec); - range = CR_RANGE(insn->chanspec); - devpriv->command1_bits |= thisboard->ai_range_code[range]; - /* munge channel bits for differential/scan disabled mode */ - if (CR_AREF(insn->chanspec) == AREF_DIFF) - chan *= 2; - devpriv->command1_bits |= ADC_CHAN_BITS(chan); - devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG); - - /* setup command6 register for 1200 boards */ - if (thisboard->register_layout == labpc_1200_layout) { - /* reference inputs to ground or common? */ - if (CR_AREF(insn->chanspec) != AREF_GROUND) - devpriv->command6_bits |= ADC_COMMON_BIT; - else - devpriv->command6_bits &= ~ADC_COMMON_BIT; - /* bipolar or unipolar range? */ - if (thisboard->ai_range_is_unipolar[range]) - devpriv->command6_bits |= ADC_UNIP_BIT; - else - devpriv->command6_bits &= ~ADC_UNIP_BIT; - /* don't interrupt on fifo half full */ - devpriv->command6_bits &= ~ADC_FHF_INTR_EN_BIT; - /* don't enable interrupt on counter a1 terminal count? */ - devpriv->command6_bits &= ~A1_INTR_EN_BIT; - /* write to register */ - devpriv->write_byte(devpriv->command6_bits, - dev->iobase + COMMAND6_REG); + /* read board status */ + devpriv->stat1 = devpriv->read_byte(dev->iobase + STAT1_REG); + if (board->register_layout == labpc_1200_layout) + devpriv->stat2 = devpriv->read_byte(dev->iobase + STAT2_REG); + + if ((devpriv->stat1 & (STAT1_GATA0 | STAT1_CNTINT | STAT1_OVERFLOW | + STAT1_OVERRUN | STAT1_DAVAIL)) == 0 + && (devpriv->stat2 & STAT2_OUTA1) == 0 + && (devpriv->stat2 & STAT2_FIFONHF)) { + return IRQ_NONE; } - /* setup command4 register */ - devpriv->command4_bits = 0; - devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT; - /* single-ended/differential */ - if (CR_AREF(insn->chanspec) == AREF_DIFF) - devpriv->command4_bits |= ADC_DIFF_BIT; - devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG); - /* - * initialize pacer counter output to make sure it doesn't - * cause any problems - */ - devpriv->write_byte(INIT_A0_BITS, dev->iobase + COUNTER_A_CONTROL_REG); + if (devpriv->stat1 & STAT1_OVERRUN) { + /* clear error interrupt */ + devpriv->write_byte(0x1, dev->iobase + ADC_FIFO_CLEAR_REG); + async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + comedi_event(dev, s); + comedi_error(dev, "overrun"); + return IRQ_HANDLED; + } - labpc_clear_adc_fifo(dev); +#ifdef CONFIG_ISA_DMA_API + if (devpriv->current_transfer == isa_dma_transfer) { + /* + * if a dma terminal count of external stop trigger + * has occurred + */ + if (devpriv->stat1 & STAT1_GATA0 || + (board->register_layout == labpc_1200_layout + && devpriv->stat2 & STAT2_OUTA1)) { + handle_isa_dma(dev); + } + } else +#endif + labpc_drain_fifo(dev); - for (n = 0; n < insn->n; n++) { - /* trigger conversion */ - devpriv->write_byte(0x1, dev->iobase + ADC_CONVERT_REG); + if (devpriv->stat1 & STAT1_CNTINT) { + comedi_error(dev, "handled timer interrupt?"); + /* clear it */ + devpriv->write_byte(0x1, dev->iobase + TIMER_CLEAR_REG); + } - for (i = 0; i < timeout; i++) { - if (devpriv->read_byte(dev->iobase + - STATUS1_REG) & DATA_AVAIL_BIT) - break; - udelay(1); + if (devpriv->stat1 & STAT1_OVERFLOW) { + /* clear error interrupt */ + devpriv->write_byte(0x1, dev->iobase + ADC_FIFO_CLEAR_REG); + async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + comedi_event(dev, s); + comedi_error(dev, "overflow"); + return IRQ_HANDLED; + } + /* handle external stop trigger */ + if (cmd->stop_src == TRIG_EXT) { + if (devpriv->stat2 & STAT2_OUTA1) { + labpc_drain_dregs(dev); + labpc_cancel(dev, s); + async->events |= COMEDI_CB_EOA; } - if (i == timeout) { - comedi_error(dev, "timeout"); - return -ETIME; + } + + /* TRIG_COUNT end of acquisition */ + if (cmd->stop_src == TRIG_COUNT) { + if (devpriv->count == 0) { + labpc_cancel(dev, s); + async->events |= COMEDI_CB_EOA; } - lsb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG); - msb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG); - data[n] = (msb << 8) | lsb; } - return n; + comedi_event(dev, s); + return IRQ_HANDLED; } -/* analog output insn */ -static int labpc_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int labpc_ao_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { + const struct labpc_boardinfo *board = comedi_board(dev); struct labpc_private *devpriv = dev->private; int channel, range; unsigned long flags; @@ -1664,20 +1262,19 @@ static int labpc_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, /* note: hardware bug in daqcard-1200 means pacing cannot * be independently enabled/disabled for its the two channels */ spin_lock_irqsave(&dev->spinlock, flags); - devpriv->command2_bits &= ~DAC_PACED_BIT(channel); - devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); + devpriv->cmd2 &= ~CMD2_LDAC(channel); + devpriv->write_byte(devpriv->cmd2, dev->iobase + CMD2_REG); spin_unlock_irqrestore(&dev->spinlock, flags); /* set range */ - if (thisboard->register_layout == labpc_1200_layout) { + if (board->register_layout == labpc_1200_layout) { range = CR_RANGE(insn->chanspec); - if (range & AO_RANGE_IS_UNIPOLAR) - devpriv->command6_bits |= DAC_UNIP_BIT(channel); + if (labpc_range_is_unipolar(s, range)) + devpriv->cmd6 |= CMD6_DACUNI(channel); else - devpriv->command6_bits &= ~DAC_UNIP_BIT(channel); + devpriv->cmd6 &= ~CMD6_DACUNI(channel); /* write to register */ - devpriv->write_byte(devpriv->command6_bits, - dev->iobase + COMMAND6_REG); + devpriv->write_byte(devpriv->cmd6, dev->iobase + CMD6_REG); } /* send data */ lsb = data[0] & 0xff; @@ -1691,9 +1288,10 @@ static int labpc_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, return 1; } -/* analog output readback insn */ -static int labpc_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int labpc_ao_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct labpc_private *devpriv = dev->private; @@ -1702,183 +1300,7 @@ static int labpc_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, return 1; } -static int labpc_calib_read_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct labpc_private *devpriv = dev->private; - - data[0] = devpriv->caldac[CR_CHAN(insn->chanspec)]; - - return 1; -} - -static int labpc_calib_write_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - int channel = CR_CHAN(insn->chanspec); - - write_caldac(dev, channel, data[0]); - return 1; -} - -static int labpc_eeprom_read_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct labpc_private *devpriv = dev->private; - - data[0] = devpriv->eeprom_data[CR_CHAN(insn->chanspec)]; - - return 1; -} - -static int labpc_eeprom_write_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - int channel = CR_CHAN(insn->chanspec); - int ret; - - /* only allow writes to user area of eeprom */ - if (channel < 16 || channel > 127) { - dev_dbg(dev->class_dev, - "eeprom writes are only allowed to channels 16 through 127 (the pointer and user areas)\n"); - return -EINVAL; - } - - ret = labpc_eeprom_write(dev, channel, data[0]); - if (ret < 0) - return ret; - - return 1; -} - -#ifdef CONFIG_ISA_DMA_API -/* utility function that suggests a dma transfer size in bytes */ -static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd) -{ - unsigned int size; - unsigned int freq; - - if (cmd->convert_src == TRIG_TIMER) - freq = 1000000000 / cmd->convert_arg; - /* return some default value */ - else - freq = 0xffffffff; - - /* make buffer fill in no more than 1/3 second */ - size = (freq / 3) * sample_size; - - /* set a minimum and maximum size allowed */ - if (size > dma_buffer_size) - size = dma_buffer_size - dma_buffer_size % sample_size; - else if (size < sample_size) - size = sample_size; - - return size; -} -#endif - -/* figures out what counter values to use based on command */ -static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, - enum scan_mode mode) -{ - struct labpc_private *devpriv = dev->private; - /* max value for 16 bit counter in mode 2 */ - const int max_counter_value = 0x10000; - /* min value for 16 bit counter in mode 2 */ - const int min_counter_value = 2; - unsigned int base_period; - unsigned int scan_period; - unsigned int convert_period; - - /* - * if both convert and scan triggers are TRIG_TIMER, then they - * both rely on counter b0 - */ - convert_period = labpc_ai_convert_period(cmd, mode); - scan_period = labpc_ai_scan_period(cmd, mode); - if (convert_period && scan_period) { - /* - * pick the lowest b0 divisor value we can (for maximum input - * clock speed on convert and scan counters) - */ - devpriv->divisor_b0 = (scan_period - 1) / - (LABPC_TIMER_BASE * max_counter_value) + 1; - if (devpriv->divisor_b0 < min_counter_value) - devpriv->divisor_b0 = min_counter_value; - if (devpriv->divisor_b0 > max_counter_value) - devpriv->divisor_b0 = max_counter_value; - - base_period = LABPC_TIMER_BASE * devpriv->divisor_b0; - - /* set a0 for conversion frequency and b1 for scan frequency */ - switch (cmd->flags & TRIG_ROUND_MASK) { - default: - case TRIG_ROUND_NEAREST: - devpriv->divisor_a0 = - (convert_period + (base_period / 2)) / base_period; - devpriv->divisor_b1 = - (scan_period + (base_period / 2)) / base_period; - break; - case TRIG_ROUND_UP: - devpriv->divisor_a0 = - (convert_period + (base_period - 1)) / base_period; - devpriv->divisor_b1 = - (scan_period + (base_period - 1)) / base_period; - break; - case TRIG_ROUND_DOWN: - devpriv->divisor_a0 = convert_period / base_period; - devpriv->divisor_b1 = scan_period / base_period; - break; - } - /* make sure a0 and b1 values are acceptable */ - if (devpriv->divisor_a0 < min_counter_value) - devpriv->divisor_a0 = min_counter_value; - if (devpriv->divisor_a0 > max_counter_value) - devpriv->divisor_a0 = max_counter_value; - if (devpriv->divisor_b1 < min_counter_value) - devpriv->divisor_b1 = min_counter_value; - if (devpriv->divisor_b1 > max_counter_value) - devpriv->divisor_b1 = max_counter_value; - /* write corrected timings to command */ - labpc_set_ai_convert_period(cmd, mode, - base_period * devpriv->divisor_a0); - labpc_set_ai_scan_period(cmd, mode, - base_period * devpriv->divisor_b1); - /* - * if only one TRIG_TIMER is used, we can employ the generic - * cascaded timing functions - */ - } else if (scan_period) { - /* - * calculate cascaded counter values - * that give desired scan timing - */ - i8253_cascade_ns_to_timer_2div(LABPC_TIMER_BASE, - &(devpriv->divisor_b1), - &(devpriv->divisor_b0), - &scan_period, - cmd->flags & TRIG_ROUND_MASK); - labpc_set_ai_scan_period(cmd, mode, scan_period); - } else if (convert_period) { - /* - * calculate cascaded counter values - * that give desired conversion timing - */ - i8253_cascade_ns_to_timer_2div(LABPC_TIMER_BASE, - &(devpriv->divisor_a0), - &(devpriv->divisor_b0), - &convert_period, - cmd->flags & TRIG_ROUND_MASK); - labpc_set_ai_convert_period(cmd, mode, convert_period); - } -} - -static int labpc_dio_mem_callback(int dir, int port, int data, - unsigned long iobase) +static int labpc_8255_mmio(int dir, int port, int data, unsigned long iobase) { if (dir) { writeb(data, (void __iomem *)(iobase + port)); @@ -1897,20 +1319,18 @@ static void labpc_serial_out(struct comedi_device *dev, unsigned int value, for (i = 1; i <= value_width; i++) { /* clear serial clock */ - devpriv->command5_bits &= ~SCLOCK_BIT; + devpriv->cmd5 &= ~CMD5_SCLK; /* send bits most significant bit first */ if (value & (1 << (value_width - i))) - devpriv->command5_bits |= SDATA_BIT; + devpriv->cmd5 |= CMD5_SDATA; else - devpriv->command5_bits &= ~SDATA_BIT; + devpriv->cmd5 &= ~CMD5_SDATA; udelay(1); - devpriv->write_byte(devpriv->command5_bits, - dev->iobase + COMMAND5_REG); + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); /* set clock to load bit */ - devpriv->command5_bits |= SCLOCK_BIT; + devpriv->cmd5 |= CMD5_SCLK; udelay(1); - devpriv->write_byte(devpriv->command5_bits, - dev->iobase + COMMAND5_REG); + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); } } @@ -1924,20 +1344,17 @@ static unsigned int labpc_serial_in(struct comedi_device *dev) for (i = 1; i <= value_width; i++) { /* set serial clock */ - devpriv->command5_bits |= SCLOCK_BIT; + devpriv->cmd5 |= CMD5_SCLK; udelay(1); - devpriv->write_byte(devpriv->command5_bits, - dev->iobase + COMMAND5_REG); + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); /* clear clock bit */ - devpriv->command5_bits &= ~SCLOCK_BIT; + devpriv->cmd5 &= ~CMD5_SCLK; udelay(1); - devpriv->write_byte(devpriv->command5_bits, - dev->iobase + COMMAND5_REG); + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); /* read bits most significant bit first */ udelay(1); - devpriv->status2_bits = - devpriv->read_byte(dev->iobase + STATUS2_REG); - if (devpriv->status2_bits & EEPROM_OUT_BIT) + devpriv->stat2 = devpriv->read_byte(dev->iobase + STAT2_REG); + if (devpriv->stat2 & STAT2_PROMOUT) value |= 1 << (value_width - i); } @@ -1955,12 +1372,12 @@ static unsigned int labpc_eeprom_read(struct comedi_device *dev, const int write_length = 8; /* enable read/write to eeprom */ - devpriv->command5_bits &= ~EEPROM_EN_BIT; + devpriv->cmd5 &= ~CMD5_EEPROMCS; udelay(1); - devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); - devpriv->command5_bits |= EEPROM_EN_BIT | EEPROM_WRITE_UNPROTECT_BIT; + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->cmd5 |= (CMD5_EEPROMCS | CMD5_WRTPRT); udelay(1); - devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); /* send read instruction */ labpc_serial_out(dev, read_instruction, write_length); @@ -1970,9 +1387,37 @@ static unsigned int labpc_eeprom_read(struct comedi_device *dev, value = labpc_serial_in(dev); /* disable read/write to eeprom */ - devpriv->command5_bits &= ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT; + devpriv->cmd5 &= ~(CMD5_EEPROMCS | CMD5_WRTPRT); + udelay(1); + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + + return value; +} + +static unsigned int labpc_eeprom_read_status(struct comedi_device *dev) +{ + struct labpc_private *devpriv = dev->private; + unsigned int value; + const int read_status_instruction = 0x5; + const int write_length = 8; /* 8 bit write lengths to eeprom */ + + /* enable read/write to eeprom */ + devpriv->cmd5 &= ~CMD5_EEPROMCS; + udelay(1); + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->cmd5 |= (CMD5_EEPROMCS | CMD5_WRTPRT); + udelay(1); + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + + /* send read status instruction */ + labpc_serial_out(dev, read_status_instruction, write_length); + /* read result */ + value = labpc_serial_in(dev); + + /* disable read/write to eeprom */ + devpriv->cmd5 &= ~(CMD5_EEPROMCS | CMD5_WRTPRT); udelay(1); - devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); return value; } @@ -2002,68 +1447,40 @@ static int labpc_eeprom_write(struct comedi_device *dev, devpriv->eeprom_data[address] = value; /* enable read/write to eeprom */ - devpriv->command5_bits &= ~EEPROM_EN_BIT; + devpriv->cmd5 &= ~CMD5_EEPROMCS; udelay(1); - devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); - devpriv->command5_bits |= EEPROM_EN_BIT | EEPROM_WRITE_UNPROTECT_BIT; + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->cmd5 |= (CMD5_EEPROMCS | CMD5_WRTPRT); udelay(1); - devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); /* send write_enable instruction */ labpc_serial_out(dev, write_enable_instruction, write_length); - devpriv->command5_bits &= ~EEPROM_EN_BIT; + devpriv->cmd5 &= ~CMD5_EEPROMCS; udelay(1); - devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); /* send write instruction */ - devpriv->command5_bits |= EEPROM_EN_BIT; + devpriv->cmd5 |= CMD5_EEPROMCS; udelay(1); - devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); labpc_serial_out(dev, write_instruction, write_length); /* send 8 bit address to write to */ labpc_serial_out(dev, address, write_length); /* write value */ labpc_serial_out(dev, value, write_length); - devpriv->command5_bits &= ~EEPROM_EN_BIT; + devpriv->cmd5 &= ~CMD5_EEPROMCS; udelay(1); - devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); /* disable read/write to eeprom */ - devpriv->command5_bits &= ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT; + devpriv->cmd5 &= ~(CMD5_EEPROMCS | CMD5_WRTPRT); udelay(1); - devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); return 0; } -static unsigned int labpc_eeprom_read_status(struct comedi_device *dev) -{ - struct labpc_private *devpriv = dev->private; - unsigned int value; - const int read_status_instruction = 0x5; - const int write_length = 8; /* 8 bit write lengths to eeprom */ - - /* enable read/write to eeprom */ - devpriv->command5_bits &= ~EEPROM_EN_BIT; - udelay(1); - devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); - devpriv->command5_bits |= EEPROM_EN_BIT | EEPROM_WRITE_UNPROTECT_BIT; - udelay(1); - devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); - - /* send read status instruction */ - labpc_serial_out(dev, read_status_instruction, write_length); - /* read result */ - value = labpc_serial_in(dev); - - /* disable read/write to eeprom */ - devpriv->command5_bits &= ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT; - udelay(1); - devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); - - return value; -} - /* writes to 8 bit calibration dacs */ static void write_caldac(struct comedi_device *dev, unsigned int channel, unsigned int value) @@ -2075,10 +1492,9 @@ static void write_caldac(struct comedi_device *dev, unsigned int channel, devpriv->caldac[channel] = value; /* clear caldac load bit and make sure we don't write to eeprom */ - devpriv->command5_bits &= - ~CALDAC_LOAD_BIT & ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT; + devpriv->cmd5 &= ~(CMD5_CALDACLD | CMD5_EEPROMCS | CMD5_WRTPRT); udelay(1); - devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); /* write 4 bit channel */ labpc_serial_out(dev, channel, 4); @@ -2086,49 +1502,295 @@ static void write_caldac(struct comedi_device *dev, unsigned int channel, labpc_serial_out(dev, value, 8); /* set and clear caldac bit to load caldac value */ - devpriv->command5_bits |= CALDAC_LOAD_BIT; + devpriv->cmd5 |= CMD5_CALDACLD; udelay(1); - devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); - devpriv->command5_bits &= ~CALDAC_LOAD_BIT; + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->cmd5 &= ~CMD5_CALDACLD; udelay(1); - devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); } -static struct comedi_driver labpc_driver = { - .driver_name = DRV_NAME, - .module = THIS_MODULE, - .attach = labpc_attach, - .auto_attach = labpc_auto_attach, - .detach = labpc_common_detach, - .num_names = ARRAY_SIZE(labpc_boards), - .board_name = &labpc_boards[0].name, - .offset = sizeof(struct labpc_board_struct), -}; +static int labpc_calib_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned int chan = CR_CHAN(insn->chanspec); -#ifdef CONFIG_COMEDI_PCI_DRIVERS -static DEFINE_PCI_DEVICE_TABLE(labpc_pci_table) = { - {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x161)}, - {0} -}; -MODULE_DEVICE_TABLE(pci, labpc_pci_table); + /* + * Only write the last data value to the caldac. Preceding + * data would be overwritten anyway. + */ + if (insn->n > 0) + write_caldac(dev, chan, data[insn->n - 1]); + + return insn->n; +} -static int labpc_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) +static int labpc_calib_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - return comedi_pci_auto_config(dev, &labpc_driver); + struct labpc_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + int i; + + for (i = 0; i < insn->n; i++) + data[i] = devpriv->caldac[chan]; + + return insn->n; } -static struct pci_driver labpc_pci_driver = { - .name = DRV_NAME, - .id_table = labpc_pci_table, - .probe = labpc_pci_probe, - .remove = comedi_pci_auto_unconfig, +static int labpc_eeprom_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned int chan = CR_CHAN(insn->chanspec); + int ret; + + /* only allow writes to user area of eeprom */ + if (chan < 16 || chan > 127) + return -EINVAL; + + /* + * Only write the last data value to the eeprom. Preceding + * data would be overwritten anyway. + */ + if (insn->n > 0) { + ret = labpc_eeprom_write(dev, chan, data[insn->n - 1]); + if (ret) + return ret; + } + + return insn->n; +} + +static int labpc_eeprom_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct labpc_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + int i; + + for (i = 0; i < insn->n; i++) + data[i] = devpriv->eeprom_data[chan]; + + return insn->n; +} + +int labpc_common_attach(struct comedi_device *dev, + unsigned int irq, unsigned long isr_flags) +{ + const struct labpc_boardinfo *board = comedi_board(dev); + struct labpc_private *devpriv = dev->private; + struct comedi_subdevice *s; + int ret; + int i; + + if (board->has_mmio) { + devpriv->read_byte = labpc_readb; + devpriv->write_byte = labpc_writeb; + } else { + devpriv->read_byte = labpc_inb; + devpriv->write_byte = labpc_outb; + } + + /* 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); + if (board->register_layout == labpc_1200_layout) { + devpriv->write_byte(devpriv->cmd5, dev->iobase + CMD5_REG); + devpriv->write_byte(devpriv->cmd6, dev->iobase + CMD6_REG); + } + + if (irq) { + ret = request_irq(irq, labpc_interrupt, isr_flags, + dev->board_name, dev); + if (ret == 0) + dev->irq = irq; + } + + ret = comedi_alloc_subdevices(dev, 5); + if (ret) + return ret; + + /* analog input subdevice */ + s = &dev->subdevices[0]; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF; + s->n_chan = 8; + s->len_chanlist = 8; + s->maxdata = 0x0fff; + s->range_table = board->ai_range_table; + s->insn_read = labpc_ai_insn_read; + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->do_cmd = labpc_ai_cmd; + s->do_cmdtest = labpc_ai_cmdtest; + s->cancel = labpc_cancel; + } + + /* analog output */ + s = &dev->subdevices[1]; + if (board->has_ao) { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND; + s->n_chan = NUM_AO_CHAN; + s->maxdata = 0x0fff; + s->range_table = &range_labpc_ao; + s->insn_read = labpc_ao_insn_read; + s->insn_write = labpc_ao_insn_write; + + /* initialize analog outputs to a known value */ + for (i = 0; i < s->n_chan; i++) { + short lsb, msb; + + 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)); + } + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + /* 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 (ret) + return ret; + + /* calibration subdevices for boards that have one */ + s = &dev->subdevices[3]; + if (board->register_layout == labpc_1200_layout) { + s->type = COMEDI_SUBD_CALIB; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = 16; + s->maxdata = 0xff; + s->insn_read = labpc_calib_insn_read; + s->insn_write = labpc_calib_insn_write; + + for (i = 0; i < s->n_chan; i++) + write_caldac(dev, i, s->maxdata / 2); + } else + s->type = COMEDI_SUBD_UNUSED; + + /* EEPROM */ + s = &dev->subdevices[4]; + if (board->register_layout == labpc_1200_layout) { + s->type = COMEDI_SUBD_MEMORY; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = EEPROM_SIZE; + s->maxdata = 0xff; + s->insn_read = labpc_eeprom_insn_read; + s->insn_write = labpc_eeprom_insn_write; + + for (i = 0; i < s->n_chan; i++) + devpriv->eeprom_data[i] = labpc_eeprom_read(dev, i); + } else + s->type = COMEDI_SUBD_UNUSED; + + return 0; +} +EXPORT_SYMBOL_GPL(labpc_common_attach); + +void labpc_common_detach(struct comedi_device *dev) +{ + comedi_spriv_free(dev, 2); +} +EXPORT_SYMBOL_GPL(labpc_common_detach); + +#if IS_ENABLED(CONFIG_COMEDI_NI_LABPC_ISA) +static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) +{ + struct labpc_private *devpriv; + unsigned int irq = it->options[1]; + unsigned int dma_chan = it->options[2]; + int ret; + + devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + if (!devpriv) + return -ENOMEM; + dev->private = devpriv; + + ret = comedi_request_region(dev, it->options[0], LABPC_SIZE); + if (ret) + return ret; + + ret = labpc_common_attach(dev, irq, 0); + if (ret) + return ret; + +#ifdef CONFIG_ISA_DMA_API + if (dev->irq && (dma_chan == 1 || dma_chan == 3)) { + devpriv->dma_buffer = kmalloc(dma_buffer_size, + GFP_KERNEL | GFP_DMA); + if (devpriv->dma_buffer) { + ret = request_dma(dma_chan, dev->board_name); + if (ret == 0) { + unsigned long dma_flags; + + devpriv->dma_chan = dma_chan; + dma_flags = claim_dma_lock(); + disable_dma(devpriv->dma_chan); + set_dma_mode(devpriv->dma_chan, DMA_MODE_READ); + release_dma_lock(dma_flags); + } else { + kfree(devpriv->dma_buffer); + } + } + } +#endif + + return 0; +} + +static void labpc_detach(struct comedi_device *dev) +{ + struct labpc_private *devpriv = dev->private; + + labpc_common_detach(dev); + + if (devpriv) { + kfree(devpriv->dma_buffer); + if (devpriv->dma_chan) + free_dma(devpriv->dma_chan); + } + comedi_legacy_detach(dev); +} + +static struct comedi_driver labpc_driver = { + .driver_name = "ni_labpc", + .module = THIS_MODULE, + .attach = labpc_attach, + .detach = labpc_detach, + .num_names = ARRAY_SIZE(labpc_boards), + .board_name = &labpc_boards[0].name, + .offset = sizeof(struct labpc_boardinfo), }; -module_comedi_pci_driver(labpc_driver, labpc_pci_driver); -#else module_comedi_driver(labpc_driver); -#endif +#else +static int __init labpc_common_init(void) +{ + return 0; +} +module_init(labpc_common_init); +static void __exit labpc_common_exit(void) +{ +} +module_exit(labpc_common_exit); +#endif MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h index e052ed3ba54..615f16f271c 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.h +++ b/drivers/staging/comedi/drivers/ni_labpc.h @@ -27,48 +27,45 @@ #define EEPROM_SIZE 256 /* 256 byte eeprom */ #define NUM_AO_CHAN 2 /* boards have two analog output channels */ -enum labpc_bustype { isa_bustype, pci_bustype, pcmcia_bustype }; enum labpc_register_layout { labpc_plus_layout, labpc_1200_layout }; enum transfer_type { fifo_not_empty_transfer, fifo_half_full_transfer, isa_dma_transfer }; -struct labpc_board_struct { +struct labpc_boardinfo { const char *name; int device_id; /* device id for pci and pcmcia boards */ int ai_speed; /* maximum input speed in nanoseconds */ - enum labpc_bustype bustype; /* ISA/PCI/etc. */ /* 1200 has extra registers compared to pc+ */ enum labpc_register_layout register_layout; int has_ao; /* has analog output true/false */ const struct comedi_lrange *ai_range_table; const int *ai_range_code; - const int *ai_range_is_unipolar; /* board can auto scan up in ai channels, not just down */ unsigned ai_scan_up:1; /* uses memory mapped io instead of ioports */ - unsigned memory_mapped_io:1; + unsigned has_mmio:1; }; struct labpc_private { struct mite_struct *mite; /* for mite chip on pci-1200 */ /* number of data points left to be taken */ - volatile unsigned long long count; + unsigned long long count; /* software copy of analog output values */ unsigned int ao_value[NUM_AO_CHAN]; /* software copys of bits written to command registers */ - volatile unsigned int command1_bits; - volatile unsigned int command2_bits; - volatile unsigned int command3_bits; - volatile unsigned int command4_bits; - volatile unsigned int command5_bits; - volatile unsigned int command6_bits; + unsigned int cmd1; + unsigned int cmd2; + unsigned int cmd3; + unsigned int cmd4; + unsigned int cmd5; + unsigned int cmd6; /* store last read of board status registers */ - volatile unsigned int status1_bits; - volatile unsigned int status2_bits; + unsigned int stat1; + unsigned int stat2; /* * value to load into board's counter a0 (conversion pacing) for timed * conversions @@ -101,11 +98,10 @@ struct labpc_private { void (*write_byte) (unsigned int byte, unsigned long address); }; -int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, - unsigned int irq, unsigned int dma); +int labpc_common_attach(struct comedi_device *dev, + unsigned int irq, unsigned long isr_flags); void labpc_common_detach(struct comedi_device *dev); -extern const int labpc_1200_is_unipolar[]; extern const int labpc_1200_ai_gain_bits[]; extern const struct comedi_lrange range_labpc_1200_ai; diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c index be7d1413b2e..9e3737c6918 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -73,17 +73,15 @@ NI manuals: #include <pcmcia/cisreg.h> #include <pcmcia/ds.h> -static const struct labpc_board_struct labpc_cs_boards[] = { +static const struct labpc_boardinfo labpc_cs_boards[] = { { .name = "daqcard-1200", .device_id = 0x103, .ai_speed = 10000, - .bustype = pcmcia_bustype, .register_layout = labpc_1200_layout, .has_ao = 1, .ai_range_table = &range_labpc_1200_ai, .ai_range_code = labpc_1200_ai_gain_bits, - .ai_range_is_unipolar = labpc_1200_is_unipolar, }, }; @@ -112,7 +110,7 @@ static int labpc_auto_attach(struct comedi_device *dev, return -ENOMEM; dev->private = devpriv; - return labpc_common_attach(dev, dev->iobase, link->irq, 0); + return labpc_common_attach(dev, link->irq, IRQF_SHARED); } static void labpc_detach(struct comedi_device *dev) diff --git a/drivers/staging/comedi/drivers/ni_labpc_pci.c b/drivers/staging/comedi/drivers/ni_labpc_pci.c new file mode 100644 index 00000000000..8e916f86cce --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_labpc_pci.c @@ -0,0 +1,142 @@ +/* + * comedi/drivers/ni_labpc_pci.c + * Driver for National Instruments Lab-PC PCI-1200 + * Copyright (C) 2001, 2002, 2003 Frank Mori Hess <fmhess@users.sourceforge.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Driver: ni_labpc_pci + * Description: National Instruments Lab-PC PCI-1200 + * Devices: (National Instruments) PCI-1200 [ni_pci-1200] + * Author: Frank Mori Hess <fmhess@users.sourceforge.net> + * Status: works + * + * This is the PCI-specific support split off from the ni_labpc driver. + * + * Configuration Options: not applicable, uses PCI auto config + * + * NI manuals: + * 340914a (pci-1200) + */ + +#include <linux/interrupt.h> +#include <linux/slab.h> +#include <linux/pci.h> + +#include "../comedidev.h" + +#include "mite.h" +#include "ni_labpc.h" + +enum labpc_pci_boardid { + BOARD_NI_PCI1200, +}; + +static const struct labpc_boardinfo labpc_pci_boards[] = { + [BOARD_NI_PCI1200] = { + .name = "ni_pci-1200", + .ai_speed = 10000, + .register_layout = labpc_1200_layout, + .has_ao = 1, + .ai_range_table = &range_labpc_1200_ai, + .ai_range_code = labpc_1200_ai_gain_bits, + .ai_scan_up = 1, + .has_mmio = 1, + }, +}; + +static int labpc_pci_auto_attach(struct comedi_device *dev, + unsigned long context) +{ + struct pci_dev *pcidev = comedi_to_pci_dev(dev); + const struct labpc_boardinfo *board = NULL; + struct labpc_private *devpriv; + int ret; + + if (context < ARRAY_SIZE(labpc_pci_boards)) + board = &labpc_pci_boards[context]; + if (!board) + return -ENODEV; + dev->board_ptr = board; + dev->board_name = board->name; + + ret = comedi_pci_enable(dev); + if (ret) + return ret; + + devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + if (!devpriv) + return -ENOMEM; + dev->private = devpriv; + + devpriv->mite = mite_alloc(pcidev); + if (!devpriv->mite) + 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); +} + +static void labpc_pci_detach(struct comedi_device *dev) +{ + struct labpc_private *devpriv = dev->private; + + labpc_common_detach(dev); + + if (devpriv && devpriv->mite) { + mite_unsetup(devpriv->mite); + mite_free(devpriv->mite); + } + if (dev->irq) + free_irq(dev->irq, dev); + comedi_pci_disable(dev); +} + +static struct comedi_driver labpc_pci_comedi_driver = { + .driver_name = "labpc_pci", + .module = THIS_MODULE, + .auto_attach = labpc_pci_auto_attach, + .detach = labpc_pci_detach, +}; + +static DEFINE_PCI_DEVICE_TABLE(labpc_pci_table) = { + { PCI_VDEVICE(NI, 0x161), BOARD_NI_PCI1200 }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, labpc_pci_table); + +static int labpc_pci_probe(struct pci_dev *dev, + const struct pci_device_id *id) +{ + return comedi_pci_auto_config(dev, &labpc_pci_comedi_driver, + id->driver_data); +} + +static struct pci_driver labpc_pci_driver = { + .name = "labpc_pci", + .id_table = labpc_pci_table, + .probe = labpc_pci_probe, + .remove = comedi_pci_auto_unconfig, +}; +module_comedi_pci_driver(labpc_pci_comedi_driver, labpc_pci_driver); + +MODULE_DESCRIPTION("Comedi: National Instruments Lab-PC PCI-1200 driver"); +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index b7403597e90..a46d579016d 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -189,11 +189,6 @@ static const struct comedi_lrange range_ni_M_ai_628x = { 7, { } }; -static const struct comedi_lrange range_ni_S_ai_6143 = { 1, { - RANGE(-5, +5), - } -}; - static const struct comedi_lrange range_ni_E_ao_ext = { 4, { RANGE(-10, 10), RANGE(0, 10), @@ -210,7 +205,7 @@ static const struct comedi_lrange *const ni_range_lkup[] = { [ai_gain_611x] = &range_ni_E_ai_611x, [ai_gain_622x] = &range_ni_M_ai_622x, [ai_gain_628x] = &range_ni_M_ai_628x, - [ai_gain_6143] = &range_ni_S_ai_6143 + [ai_gain_6143] = &range_bipolar5 }; static int ni_dio_insn_config(struct comedi_device *dev, @@ -696,9 +691,10 @@ static void ni_release_cdo_mite_channel(struct comedi_device *dev) 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; - if (boardtype.reg_type & ni_reg_m_series_mask) + if (board->reg_type & ni_reg_m_series_mask) return; switch (gpct_index) { case 0: @@ -728,16 +724,17 @@ static void ni_e_series_enable_second_irq(struct comedi_device *dev, 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; - if (boardtype.reg_type == ni_reg_6143) { + if (board->reg_type == ni_reg_6143) { /* Flush the 6143 data FIFO */ ni_writel(0x10, AIFIFO_Control_6143); /* Flush fifo */ ni_writel(0x00, AIFIFO_Control_6143); /* Flush fifo */ while (ni_readl(AIFIFO_Status_6143) & 0x10) ; /* Wait for complete */ } else { devpriv->stc_writew(dev, 1, ADC_FIFO_Clear); - if (boardtype.reg_type == ni_reg_625x) { + 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)); #if 0 @@ -845,7 +842,7 @@ static irqreturn_t ni_E_interrupt(int irq, void *d) struct mite_struct *mite = devpriv->mite; #endif - if (dev->attached == 0) + if (!dev->attached) return IRQ_NONE; smp_mb(); /* make sure dev->attached is checked before handler does anything else. */ @@ -1292,6 +1289,7 @@ static void ni_mio_print_status_b(int status) 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 comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; int chan; @@ -1309,10 +1307,10 @@ static void ni_ao_fifo_load(struct comedi_device *dev, range = CR_RANGE(cmd->chanlist[chan]); - if (boardtype.reg_type & ni_reg_6xxx_mask) { + if (board->reg_type & ni_reg_6xxx_mask) { packed_data = d & 0xffff; /* 6711 only has 16 bit wide ao fifo */ - if (boardtype.reg_type != ni_reg_6711) { + if (board->reg_type != ni_reg_6711) { err &= comedi_buf_get(async, &d); if (err == 0) break; @@ -1352,6 +1350,7 @@ static void ni_ao_fifo_load(struct comedi_device *dev, static int ni_ao_fifo_half_empty(struct comedi_device *dev, struct comedi_subdevice *s) { + const struct ni_board_struct *board = comedi_board(dev); int n; n = comedi_buf_read_n_available(s->async); @@ -1361,8 +1360,8 @@ static int ni_ao_fifo_half_empty(struct comedi_device *dev, } n /= sizeof(short); - if (n > boardtype.ao_fifo_depth / 2) - n = boardtype.ao_fifo_depth / 2; + if (n > board->ao_fifo_depth / 2) + n = board->ao_fifo_depth / 2; ni_ao_fifo_load(dev, s, n); @@ -1374,12 +1373,13 @@ static int ni_ao_fifo_half_empty(struct comedi_device *dev, static int ni_ao_prep_fifo(struct comedi_device *dev, struct comedi_subdevice *s) { + const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; int n; /* reset fifo */ devpriv->stc_writew(dev, 1, DAC_FIFO_Clear); - if (boardtype.reg_type & ni_reg_6xxx_mask) + if (board->reg_type & ni_reg_6xxx_mask) ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x); /* load some data */ @@ -1388,8 +1388,8 @@ static int ni_ao_prep_fifo(struct comedi_device *dev, return 0; n /= sizeof(short); - if (n > boardtype.ao_fifo_depth) - n = boardtype.ao_fifo_depth; + if (n > board->ao_fifo_depth) + n = board->ao_fifo_depth; ni_ao_fifo_load(dev, s, n); @@ -1399,11 +1399,12 @@ 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 (boardtype.reg_type == ni_reg_611x) { + if (board->reg_type == ni_reg_611x) { short data[2]; u32 dl; @@ -1420,7 +1421,7 @@ static void ni_ai_fifo_read(struct comedi_device *dev, data[0] = dl & 0xffff; cfc_write_to_buffer(s, data[0]); } - } else if (boardtype.reg_type == ni_reg_6143) { + } else if (board->reg_type == ni_reg_6143) { short data[2]; u32 dl; @@ -1458,10 +1459,11 @@ static void ni_ai_fifo_read(struct comedi_device *dev, static void ni_handle_fifo_half_full(struct comedi_device *dev) { - int n; + const struct ni_board_struct *board = comedi_board(dev); struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; + int n; - n = boardtype.ai_fifo_depth / 2; + n = board->ai_fifo_depth / 2; ni_ai_fifo_read(dev, s, n); } @@ -1508,6 +1510,7 @@ static int ni_ai_drain_dma(struct comedi_device *dev) */ 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]; short data[2]; @@ -1515,7 +1518,7 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev) short fifo_empty; int i; - if (boardtype.reg_type == ni_reg_611x) { + if (board->reg_type == ni_reg_611x) { while ((devpriv->stc_readw(dev, AI_Status_1_Register) & AI_FIFO_Empty_St) == 0) { @@ -1526,7 +1529,7 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev) data[1] = (dl & 0xffff); cfc_write_array_to_buffer(s, data, sizeof(data)); } - } else if (boardtype.reg_type == ni_reg_6143) { + } else if (board->reg_type == ni_reg_6143) { i = 0; while (ni_readl(AIFIFO_Status_6143) & 0x04) { dl = ni_readl(AIFIFO_Data_6143); @@ -1573,12 +1576,13 @@ 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]; short data; u32 dl; - if (boardtype.reg_type != ni_reg_611x) + if (board->reg_type != ni_reg_611x) return; /* Check if there's a single sample stuck in the FIFO */ @@ -1591,12 +1595,13 @@ 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]; short data; u32 dl; - if (boardtype.reg_type != ni_reg_6143) + if (board->reg_type != ni_reg_6143) return; /* Check if there's a single sample stuck in the FIFO */ @@ -1641,6 +1646,7 @@ 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]; int retval; @@ -1660,7 +1666,7 @@ static int ni_ai_setup_MITE_dma(struct comedi_device *dev) return -EIO; } - switch (boardtype.reg_type) { + switch (board->reg_type) { case ni_reg_611x: case ni_reg_6143: mite_prep_dma(devpriv->ai_mite_chan, 32, 16); @@ -1681,6 +1687,7 @@ 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]; int retval; @@ -1695,7 +1702,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 (boardtype.reg_type & (ni_reg_611x | ni_reg_6713)) { + if (board->reg_type & (ni_reg_611x | ni_reg_6713)) { mite_prep_dma(devpriv->ao_mite_chan, 32, 32); } else { /* doing 32 instead of 16 bit wide transfers from memory @@ -1720,6 +1727,7 @@ 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); @@ -1735,7 +1743,7 @@ static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s) ni_clear_ai_fifo(dev); - if (boardtype.reg_type != ni_reg_6143) + if (board->reg_type != ni_reg_6143) ni_writeb(0, Misc_Command); devpriv->stc_writew(dev, AI_Disarm, AI_Command_1_Register); /* reset pulses */ @@ -1746,7 +1754,7 @@ static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->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 (boardtype.reg_type == ni_reg_611x) { + if (board->reg_type == ni_reg_611x) { devpriv->stc_writew(dev, AI_SHIFTIN_Pulse_Width | AI_SOC_Polarity | AI_LOCALMUX_CLK_Pulse_Width, @@ -1759,7 +1767,7 @@ static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s) AI_CONVERT_Output_Select (AI_CONVERT_Output_Enable_High), AI_Output_Control_Register); - } else if (boardtype.reg_type == ni_reg_6143) { + } else if (board->reg_type == ni_reg_6143) { devpriv->stc_writew(dev, AI_SHIFTIN_Pulse_Width | AI_SOC_Polarity | AI_LOCALMUX_CLK_Pulse_Width, @@ -1784,7 +1792,7 @@ static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s) AI_EXTMUX_CLK_Output_Select(0) | AI_LOCALMUX_CLK_Output_Select(2) | AI_SC_TC_Output_Select(3); - if (boardtype.reg_type == ni_reg_622x) + if (board->reg_type == ni_reg_622x) ai_output_control_bits |= AI_CONVERT_Output_Select (AI_CONVERT_Output_Enable_High); @@ -1832,9 +1840,10 @@ 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 << boardtype.adbits) - 1; + const unsigned int mask = (1 << board->adbits) - 1; unsigned signbits; unsigned short d; unsigned long dl; @@ -1844,7 +1853,7 @@ static int ni_ai_insn_read(struct comedi_device *dev, ni_clear_ai_fifo(dev); signbits = devpriv->ai_offset[0]; - if (boardtype.reg_type == ni_reg_611x) { + 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); @@ -1877,7 +1886,7 @@ static int ni_ai_insn_read(struct comedi_device *dev, d += signbits; data[n] = d; } - } else if (boardtype.reg_type == ni_reg_6143) { + } 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); @@ -1913,7 +1922,7 @@ static int ni_ai_insn_read(struct comedi_device *dev, ("ni_mio_common: timeout in ni_ai_insn_read\n"); return -ETIME; } - if (boardtype.reg_type & ni_reg_m_series_mask) { + if (board->reg_type & ni_reg_m_series_mask) { data[n] = ni_readl(M_Offset_AI_FIFO_Data) & mask; } else { @@ -1948,6 +1957,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev, unsigned int n_chan, unsigned int *list) { + const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; unsigned int chan, range, aref; unsigned int i; @@ -1957,12 +1967,12 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev, devpriv->stc_writew(dev, 1, Configuration_Memory_Clear); -/* offset = 1 << (boardtype.adbits - 1); */ +/* 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[boardtype.gainlkup][range]; + range_code = ni_gainlkup[board->gainlkup][range]; dither = ((list[0] & CR_ALT_FILTER) != 0); bypass_bits = MSeries_AI_Bypass_Config_FIFO_Bit; bypass_bits |= chan; @@ -1989,7 +1999,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev, range = CR_RANGE(list[i]); dither = ((list[i] & CR_ALT_FILTER) != 0); - range_code = ni_gainlkup[boardtype.gainlkup][range]; + range_code = ni_gainlkup[board->gainlkup][range]; devpriv->ai_offset[i] = offset; switch (aref) { case AREF_DIFF: @@ -2009,7 +2019,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev, } config_bits |= MSeries_AI_Config_Channel_Bits(chan); config_bits |= - MSeries_AI_Config_Bank_Bits(boardtype.reg_type, chan); + MSeries_AI_Config_Bank_Bits(board->reg_type, chan); config_bits |= MSeries_AI_Config_Gain_Bits(range_code); if (i == n_chan - 1) config_bits |= MSeries_AI_Config_Last_Channel_Bit; @@ -2054,6 +2064,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev, static void ni_load_channelgain_list(struct comedi_device *dev, unsigned int n_chan, unsigned int *list) { + const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; unsigned int chan, range, aref; unsigned int i; @@ -2061,12 +2072,12 @@ static void ni_load_channelgain_list(struct comedi_device *dev, unsigned offset; unsigned int dither; - if (boardtype.reg_type & ni_reg_m_series_mask) { + if (board->reg_type & ni_reg_m_series_mask) { ni_m_series_load_channelgain_list(dev, n_chan, list); return; } - if (n_chan == 1 && (boardtype.reg_type != ni_reg_611x) - && (boardtype.reg_type != ni_reg_6143)) { + if (n_chan == 1 && (board->reg_type != ni_reg_611x) + && (board->reg_type != ni_reg_6143)) { if (devpriv->changain_state && devpriv->changain_spec == list[0]) { /* ready to go. */ @@ -2081,7 +2092,7 @@ static void ni_load_channelgain_list(struct comedi_device *dev, devpriv->stc_writew(dev, 1, Configuration_Memory_Clear); /* Set up Calibration mode if required */ - if (boardtype.reg_type == ni_reg_6143) { + if (board->reg_type == ni_reg_6143) { if ((list[0] & CR_ALT_SOURCE) && !devpriv->ai_calib_source_enabled) { /* Strobe Relay enable bit */ @@ -2105,9 +2116,9 @@ static void ni_load_channelgain_list(struct comedi_device *dev, } } - offset = 1 << (boardtype.adbits - 1); + offset = 1 << (board->adbits - 1); for (i = 0; i < n_chan; i++) { - if ((boardtype.reg_type != ni_reg_6143) + if ((board->reg_type != ni_reg_6143) && (list[i] & CR_ALT_SOURCE)) { chan = devpriv->ai_calib_source; } else { @@ -2118,21 +2129,21 @@ static void ni_load_channelgain_list(struct comedi_device *dev, dither = ((list[i] & CR_ALT_FILTER) != 0); /* fix the external/internal range differences */ - range = ni_gainlkup[boardtype.gainlkup][range]; - if (boardtype.reg_type == ni_reg_611x) + range = ni_gainlkup[board->gainlkup][range]; + if (board->reg_type == ni_reg_611x) devpriv->ai_offset[i] = offset; else devpriv->ai_offset[i] = (range & 0x100) ? 0 : offset; hi = 0; if ((list[i] & CR_ALT_SOURCE)) { - if (boardtype.reg_type == ni_reg_611x) + if (board->reg_type == ni_reg_611x) ni_writew(CR_CHAN(list[i]) & 0x0003, Calibration_Channel_Select_611x); } else { - if (boardtype.reg_type == ni_reg_611x) + if (board->reg_type == ni_reg_611x) aref = AREF_DIFF; - else if (boardtype.reg_type == ni_reg_6143) + else if (board->reg_type == ni_reg_6143) aref = AREF_OTHER; switch (aref) { case AREF_DIFF: @@ -2152,7 +2163,7 @@ static void ni_load_channelgain_list(struct comedi_device *dev, ni_writew(hi, Configuration_Memory_High); - if (boardtype.reg_type != ni_reg_6143) { + if (board->reg_type != ni_reg_6143) { lo = range; if (i == n_chan - 1) lo |= AI_LAST_CHANNEL; @@ -2164,8 +2175,8 @@ static void ni_load_channelgain_list(struct comedi_device *dev, } /* prime the channel/gain list */ - if ((boardtype.reg_type != ni_reg_611x) - && (boardtype.reg_type != ni_reg_6143)) { + if ((board->reg_type != ni_reg_611x) + && (board->reg_type != ni_reg_6143)) { ni_prime_channelgain_list(dev); } } @@ -2201,22 +2212,25 @@ static unsigned ni_timer_to_ns(const struct comedi_device *dev, int timer) static unsigned ni_min_ai_scan_period_ns(struct comedi_device *dev, unsigned num_channels) { - switch (boardtype.reg_type) { + const struct ni_board_struct *board = comedi_board(dev); + + switch (board->reg_type) { case ni_reg_611x: case ni_reg_6143: /* simultaneously-sampled inputs */ - return boardtype.ai_speed; + return board->ai_speed; break; default: /* multiplexed inputs */ break; } - return boardtype.ai_speed * num_channels; + return board->ai_speed * num_channels; } static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; int err = 0; int tmp; @@ -2233,8 +2247,8 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, TRIG_TIMER | TRIG_EXT); sources = TRIG_TIMER | TRIG_EXT; - if (boardtype.reg_type == ni_reg_611x || - boardtype.reg_type == ni_reg_6143) + if (board->reg_type == ni_reg_611x || + board->reg_type == ni_reg_6143) sources |= TRIG_NOW; err |= cfc_check_trigger_src(&cmd->convert_src, sources); @@ -2289,12 +2303,12 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, } if (cmd->convert_src == TRIG_TIMER) { - if ((boardtype.reg_type == ni_reg_611x) - || (boardtype.reg_type == ni_reg_6143)) { + if ((board->reg_type == ni_reg_611x) + || (board->reg_type == ni_reg_6143)) { err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); } else { err |= cfc_check_trigger_arg_min(&cmd->convert_arg, - boardtype.ai_speed); + board->ai_speed); err |= cfc_check_trigger_arg_max(&cmd->convert_arg, devpriv->clock_ns * 0xffff); } @@ -2315,7 +2329,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 (boardtype.reg_type == ni_reg_611x) + if (board->reg_type == ni_reg_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); @@ -2341,8 +2355,8 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, err++; } if (cmd->convert_src == TRIG_TIMER) { - if ((boardtype.reg_type != ni_reg_611x) - && (boardtype.reg_type != ni_reg_6143)) { + if ((board->reg_type != ni_reg_611x) + && (board->reg_type != ni_reg_6143)) { tmp = cmd->convert_arg; cmd->convert_arg = ni_timer_to_ns(dev, ni_ns_to_timer(dev, @@ -2370,6 +2384,7 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, 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; @@ -2426,8 +2441,8 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) mode2 &= ~AI_SC_Reload_Mode; devpriv->stc_writew(dev, mode2, AI_Mode_2_Register); - if (cmd->chanlist_len == 1 || (boardtype.reg_type == ni_reg_611x) - || (boardtype.reg_type == ni_reg_6143)) { + if (cmd->chanlist_len == 1 || (board->reg_type == ni_reg_611x) + || (board->reg_type == ni_reg_6143)) { start_stop_select |= AI_STOP_Polarity; start_stop_select |= AI_STOP_Select(31); /* logic low */ start_stop_select |= AI_STOP_Sync; @@ -2442,7 +2457,7 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) case TRIG_COUNT: stop_count = cmd->stop_arg - 1; - if (boardtype.reg_type == ni_reg_611x) { + if (board->reg_type == ni_reg_611x) { /* have to take 3 stage adc pipeline into account */ stop_count += num_adc_stages_611x; } @@ -2698,6 +2713,7 @@ 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) @@ -2707,7 +2723,7 @@ static int ni_ai_insn_config(struct comedi_device *dev, case INSN_CONFIG_ANALOG_TRIG: return ni_ai_config_analog_trig(dev, s, insn, data); case INSN_CONFIG_ALT_SOURCE: - if (boardtype.reg_type & ni_reg_m_series_mask) { + if (board->reg_type & ni_reg_m_series_mask) { if (data[1] & ~(MSeries_AI_Bypass_Cal_Sel_Pos_Mask | MSeries_AI_Bypass_Cal_Sel_Neg_Mask | MSeries_AI_Bypass_Mode_Mux_Mask | @@ -2715,7 +2731,7 @@ static int ni_ai_insn_config(struct comedi_device *dev, return -EINVAL; } devpriv->ai_calib_source = data[1]; - } else if (boardtype.reg_type == ni_reg_6143) { + } else if (board->reg_type == ni_reg_6143) { unsigned int calib_source; calib_source = data[1] & 0xf; @@ -2735,7 +2751,7 @@ static int ni_ai_insn_config(struct comedi_device *dev, if (calib_source >= 8) return -EINVAL; devpriv->ai_calib_source = calib_source; - if (boardtype.reg_type == ni_reg_611x) { + if (board->reg_type == ni_reg_611x) { ni_writeb(calib_source_adjust, Cal_Gain_Select_611x); } @@ -2753,6 +2769,7 @@ static int ni_ai_config_analog_trig(struct comedi_device *dev, 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; @@ -2761,14 +2778,14 @@ static int ni_ai_config_analog_trig(struct comedi_device *dev, * data[2] is analog line * data[3] is set level * data[4] is reset level */ - if (!boardtype.has_analog_trig) + 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] >= boardtype.n_adchan) { - data[2] = boardtype.n_adchan - 1; + if (data[2] >= board->n_adchan) { + data[2] = board->n_adchan - 1; err++; } if (data[3] > 255) { /* a */ @@ -2852,6 +2869,7 @@ 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; unsigned int range; unsigned int i; @@ -2859,10 +2877,10 @@ static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int length = num_bytes / sizeof(short); short *array = data; - offset = 1 << (boardtype.aobits - 1); + offset = 1 << (board->aobits - 1); for (i = 0; i < length; i++) { range = CR_RANGE(async->cmd.chanlist[chan_index]); - if (boardtype.ao_unipolar == 0 || (range & 1) == 0) + if (board->ao_unipolar == 0 || (range & 1) == 0) array[i] -= offset; #ifdef PCIDMA array[i] = cpu_to_le16(array[i]); @@ -2877,6 +2895,7 @@ 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; @@ -2885,7 +2904,7 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev, int invert = 0; if (timed) { - for (i = 0; i < boardtype.n_aochan; ++i) { + for (i = 0; i < board->n_aochan; ++i) { devpriv->ao_conf[i] &= ~MSeries_AO_Update_Timed_Bit; ni_writeb(devpriv->ao_conf[i], M_Offset_AO_Config_Bank(i)); @@ -2949,6 +2968,7 @@ 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; @@ -2961,10 +2981,10 @@ static int ni_old_ao_config_chanlist(struct comedi_device *dev, range = CR_RANGE(chanspec[i]); conf = AO_Channel(chan); - if (boardtype.ao_unipolar) { + if (board->ao_unipolar) { if ((range & 1) == 0) { conf |= AO_Bipolar; - invert = (1 << (boardtype.aobits - 1)); + invert = (1 << (board->aobits - 1)); } else { invert = 0; } @@ -2972,7 +2992,7 @@ static int ni_old_ao_config_chanlist(struct comedi_device *dev, conf |= AO_Ext_Ref; } else { conf |= AO_Bipolar; - invert = (1 << (boardtype.aobits - 1)); + invert = (1 << (board->aobits - 1)); } /* not all boards can deglitch, but this shouldn't hurt */ @@ -2995,7 +3015,9 @@ static int ni_ao_config_chanlist(struct comedi_device *dev, unsigned int chanspec[], unsigned int n_chans, int timed) { - if (boardtype.reg_type & ni_reg_m_series_mask) + const struct ni_board_struct *board = comedi_board(dev); + + if (board->reg_type & ni_reg_m_series_mask) return ni_m_series_ao_config_chanlist(dev, s, chanspec, n_chans, timed); else @@ -3017,6 +3039,7 @@ static int ni_ao_insn_write(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; @@ -3025,7 +3048,7 @@ static int ni_ao_insn_write(struct comedi_device *dev, devpriv->ao[chan] = data[0]; - if (boardtype.reg_type & ni_reg_m_series_mask) { + 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, @@ -3038,12 +3061,13 @@ 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 << (boardtype.aobits - 1); + invert = 1 << (board->aobits - 1); ni_ao_config_chanlist(dev, s, &insn->chanspec, 1, 0); @@ -3057,13 +3081,14 @@ static int ni_ao_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; switch (data[0]) { case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE: switch (data[1]) { case COMEDI_OUTPUT: - data[2] = 1 + boardtype.ao_fifo_depth * sizeof(short); + data[2] = 1 + board->ao_fifo_depth * sizeof(short); if (devpriv->mite) data[2] += devpriv->mite->fifo_size; break; @@ -3085,6 +3110,7 @@ static int ni_ao_insn_config(struct comedi_device *dev, static int ni_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trignum) { + const struct ni_board_struct *board __maybe_unused = comedi_board(dev); struct ni_private *devpriv = dev->private; int ret; int interrupt_b_bits; @@ -3104,7 +3130,7 @@ static int ni_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, interrupt_b_bits = AO_Error_Interrupt_Enable; #ifdef PCIDMA devpriv->stc_writew(dev, 1, DAC_FIFO_Clear); - if (boardtype.reg_type & ni_reg_6xxx_mask) + if (board->reg_type & ni_reg_6xxx_mask) ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x); ret = ni_ao_setup_MITE_dma(dev); if (ret) @@ -3155,6 +3181,7 @@ static int ni_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, static int ni_ao_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 bits; @@ -3170,7 +3197,7 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->stc_writew(dev, AO_Disarm, AO_Command_1_Register); - if (boardtype.reg_type & ni_reg_6xxx_mask) { + if (board->reg_type & ni_reg_6xxx_mask) { ao_win_out(CLEAR_WG, AO_Misc_611x); bits = 0; @@ -3233,7 +3260,7 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); switch (cmd->stop_src) { case TRIG_COUNT: - if (boardtype.reg_type & ni_reg_m_series_mask) { + if (board->reg_type & ni_reg_m_series_mask) { /* 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); @@ -3301,8 +3328,8 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) unsigned bits; devpriv->ao_mode1 &= ~AO_Multiple_Channels; bits = AO_UPDATE_Output_Select(AO_Update_Output_High_Z); - if (boardtype. - reg_type & (ni_reg_m_series_mask | ni_reg_6xxx_mask)) { + if (board->reg_type & + (ni_reg_m_series_mask | ni_reg_6xxx_mask)) { bits |= AO_Number_Of_Channels(0); } else { bits |= @@ -3329,14 +3356,14 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) bits = AO_BC_Source_Select | AO_UPDATE_Pulse_Width | AO_TMRDACWR_Pulse_Width; - if (boardtype.ao_fifo_depth) + if (board->ao_fifo_depth) bits |= AO_FIFO_Enable; else bits |= AO_DMA_PIO_Control; #if 0 /* F Hess: windows driver does not set AO_Number_Of_DAC_Packages bit for 6281, verified with bus analyzer. */ - if (boardtype.reg_type & ni_reg_m_series_mask) + if (board->reg_type & ni_reg_m_series_mask) bits |= AO_Number_Of_DAC_Packages; #endif devpriv->stc_writew(dev, bits, AO_Personal_Register); @@ -3360,6 +3387,7 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; int err = 0; int tmp; @@ -3407,7 +3435,7 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, if (cmd->scan_begin_src == TRIG_TIMER) { err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, - boardtype.ao_speed); + board->ao_speed); err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, devpriv->clock_ns * 0xffffff); } @@ -3448,6 +3476,7 @@ 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; */ @@ -3475,7 +3504,7 @@ static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->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 (boardtype.reg_type & ni_reg_m_series_mask) + if (board->reg_type & ni_reg_m_series_mask) devpriv->ao_mode3 = AO_Last_Gate_Disable; else devpriv->ao_mode3 = 0; @@ -3483,7 +3512,7 @@ static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ao_trigger_select = 0; devpriv->stc_writew(dev, devpriv->ao_trigger_select, AO_Trigger_Select_Register); - if (boardtype.reg_type & ni_reg_6xxx_mask) { + if (board->reg_type & ni_reg_6xxx_mask) { unsigned immediate_bits = 0; unsigned i; for (i = 0; i < s->n_chan; ++i) { @@ -3784,6 +3813,7 @@ static int ni_cdio_cancel(struct comedi_device *dev, struct comedi_subdevice *s) 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; unsigned cdio_status; struct comedi_subdevice *s = &dev->subdevices[NI_DIO_SUBDEV]; @@ -3791,7 +3821,7 @@ static void handle_cdio_interrupt(struct comedi_device *dev) unsigned long flags; #endif - if ((boardtype.reg_type & ni_reg_m_series_mask) == 0) { + if ((board->reg_type & ni_reg_m_series_mask) == 0) { return; } #ifdef PCIDMA @@ -4039,17 +4069,13 @@ static int ni_serial_sw_readwrite8(struct comedi_device *dev, static void mio_common_detach(struct comedi_device *dev) { struct ni_private *devpriv = dev->private; - struct comedi_subdevice *s; if (devpriv) { if (devpriv->counter_dev) { ni_gpct_device_destroy(devpriv->counter_dev); } } - if (dev->subdevices && boardtype.has_8255) { - s = &dev->subdevices[NI_8255_DIO_SUBDEV]; - subdev_8255_cleanup(dev, s); - } + comedi_spriv_free(dev, NI_8255_DIO_SUBDEV); } static void init_ao_67xx(struct comedi_device *dev, struct comedi_subdevice *s) @@ -4355,14 +4381,15 @@ static int ni_alloc_private(struct comedi_device *dev) 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 (boardtype.n_aochan > MAX_N_AO_CHAN) { - printk("bug! boardtype.n_aochan > MAX_N_AO_CHAN\n"); + if (board->n_aochan > MAX_N_AO_CHAN) { + printk("bug! n_aochan > MAX_N_AO_CHAN\n"); return -EINVAL; } @@ -4374,20 +4401,20 @@ static int ni_E_init(struct comedi_device *dev) s = &dev->subdevices[NI_AI_SUBDEV]; dev->read_subdev = s; - if (boardtype.n_adchan) { + if (board->n_adchan) { s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_DITHER | SDF_CMD_READ; - if (boardtype.reg_type != ni_reg_611x) + if (board->reg_type != ni_reg_611x) s->subdev_flags |= SDF_GROUND | SDF_COMMON | SDF_OTHER; - if (boardtype.adbits > 16) + if (board->adbits > 16) s->subdev_flags |= SDF_LSAMPL; - if (boardtype.reg_type & ni_reg_m_series_mask) + if (board->reg_type & ni_reg_m_series_mask) s->subdev_flags |= SDF_SOFT_CALIBRATED; - s->n_chan = boardtype.n_adchan; + s->n_chan = board->n_adchan; s->len_chanlist = 512; - s->maxdata = (1 << boardtype.adbits) - 1; - s->range_table = ni_range_lkup[boardtype.gainlkup]; + 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; @@ -4405,40 +4432,40 @@ static int ni_E_init(struct comedi_device *dev) /* analog output subdevice */ s = &dev->subdevices[NI_AO_SUBDEV]; - if (boardtype.n_aochan) { + if (board->n_aochan) { s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_DEGLITCH | SDF_GROUND; - if (boardtype.reg_type & ni_reg_m_series_mask) + if (board->reg_type & ni_reg_m_series_mask) s->subdev_flags |= SDF_SOFT_CALIBRATED; - s->n_chan = boardtype.n_aochan; - s->maxdata = (1 << boardtype.aobits) - 1; - s->range_table = boardtype.ao_range_table; + 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 (boardtype.reg_type & ni_reg_6xxx_mask) { + 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 (boardtype.n_aochan) { + if (board->n_aochan) { s->async_dma_dir = DMA_TO_DEVICE; #else - if (boardtype.ao_fifo_depth) { + 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 = boardtype.n_aochan; - if ((boardtype.reg_type & ni_reg_m_series_mask) == 0) + 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 ((boardtype.reg_type & ni_reg_67xx_mask)) + if ((board->reg_type & ni_reg_67xx_mask)) init_ao_67xx(dev, s); /* digital i/o subdevice */ @@ -4449,8 +4476,8 @@ static int ni_E_init(struct comedi_device *dev) s->maxdata = 1; s->io_bits = 0; /* all bits input */ s->range_table = &range_digital; - s->n_chan = boardtype.num_p0_dio_channels; - if (boardtype.reg_type & ni_reg_m_series_mask) { + 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; @@ -4472,7 +4499,7 @@ static int ni_E_init(struct comedi_device *dev) /* 8255 device */ s = &dev->subdevices[NI_8255_DIO_SUBDEV]; - if (boardtype.has_8255) { + if (board->has_8255) { subdev_8255_init(dev, s, ni_8255_callback, (unsigned long)dev); } else { s->type = COMEDI_SUBD_UNUSED; @@ -4485,14 +4512,14 @@ static int ni_E_init(struct comedi_device *dev) /* calibration subdevice -- ai and ao */ s = &dev->subdevices[NI_CALIBRATION_SUBDEV]; s->type = COMEDI_SUBD_CALIB; - if (boardtype.reg_type & ni_reg_m_series_mask) { + 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 (boardtype.reg_type == ni_reg_6143) { + } 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; @@ -4510,7 +4537,7 @@ static int ni_E_init(struct comedi_device *dev) s->type = COMEDI_SUBD_MEMORY; s->subdev_flags = SDF_READABLE | SDF_INTERNAL; s->maxdata = 0xff; - if (boardtype.reg_type & ni_reg_m_series_mask) { + 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 { @@ -4522,7 +4549,7 @@ static int ni_E_init(struct comedi_device *dev) s = &dev->subdevices[NI_PFI_DIO_SUBDEV]; s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; - if (boardtype.reg_type & ni_reg_m_series_mask) { + if (board->reg_type & ni_reg_m_series_mask) { unsigned i; s->n_chan = 16; ni_writew(s->state, M_Offset_PFI_DO); @@ -4534,7 +4561,7 @@ static int ni_E_init(struct comedi_device *dev) s->n_chan = 10; } s->maxdata = 1; - if (boardtype.reg_type & ni_reg_m_series_mask) { + if (board->reg_type & ni_reg_m_series_mask) { s->insn_bits = &ni_pfi_insn_bits; } s->insn_config = &ni_pfi_insn_config; @@ -4542,11 +4569,11 @@ static int ni_E_init(struct comedi_device *dev) /* cs5529 calibration adc */ s = &dev->subdevices[NI_CS5529_CALIBRATION_SUBDEV]; - if (boardtype.reg_type & ni_reg_67xx_mask) { + 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 = boardtype.n_aochan; + s->n_chan = board->n_aochan; s->maxdata = (1 << 16) - 1; s->range_table = &range_unknown; /* XXX */ s->insn_read = cs5529_ai_insn_read; @@ -4576,7 +4603,7 @@ static int ni_E_init(struct comedi_device *dev) s->insn_config = ni_rtsi_insn_config; ni_rtsi_init(dev); - if (boardtype.reg_type & ni_reg_m_series_mask) { + if (board->reg_type & ni_reg_m_series_mask) { counter_variant = ni_gpct_variant_m_series; } else { counter_variant = ni_gpct_variant_e_series; @@ -4594,7 +4621,7 @@ static int ni_E_init(struct comedi_device *dev) SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_CMD_READ /* | SDF_CMD_WRITE */ ; s->n_chan = 3; - if (boardtype.reg_type & ni_reg_m_series_mask) + if (board->reg_type & ni_reg_m_series_mask) s->maxdata = 0xffffffff; else s->maxdata = 0xffffff; @@ -4626,7 +4653,7 @@ static int ni_E_init(struct comedi_device *dev) /* ai configuration */ s = &dev->subdevices[NI_AI_SUBDEV]; ni_ai_reset(dev, s); - if ((boardtype.reg_type & ni_reg_6xxx_mask) == 0) { + 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 | @@ -4663,11 +4690,11 @@ static int ni_E_init(struct comedi_device *dev) ni_writeb(devpriv->ai_ao_select_reg, AI_AO_Select); ni_writeb(devpriv->g0_g1_select_reg, G0_G1_Select); - if (boardtype.reg_type & ni_reg_6xxx_mask) { + if (board->reg_type & ni_reg_6xxx_mask) { ni_writeb(0, Magic_611x); - } else if (boardtype.reg_type & ni_reg_m_series_mask) { + } else if (board->reg_type & ni_reg_m_series_mask) { int channel; - for (channel = 0; channel < boardtype.n_aochan; ++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)); @@ -4938,6 +4965,7 @@ static struct caldac_struct caldacs[] = { static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s) { + const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; int i, j; int n_dacs; @@ -4947,12 +4975,12 @@ static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s) int type; int chan; - type = boardtype.caldac[0]; + type = board->caldac[0]; if (type == caldac_none) return; n_bits = caldacs[type].n_bits; for (i = 0; i < 3; i++) { - type = boardtype.caldac[i]; + type = board->caldac[i]; if (type == caldac_none) break; if (caldacs[type].n_bits != n_bits) @@ -4971,7 +4999,7 @@ static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s) s->maxdata_list = maxdata_list = devpriv->caldac_maxdata_list; chan = 0; for (i = 0; i < n_dacs; i++) { - type = boardtype.caldac[i]; + type = board->caldac[i]; for (j = 0; j < caldacs[type].n_chans; j++) { maxdata_list[chan] = (1 << caldacs[type].n_bits) - 1; @@ -4982,7 +5010,7 @@ static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s) for (chan = 0; chan < s->n_chan; chan++) ni_write_caldac(dev, i, s->maxdata_list[i] / 2); } else { - type = boardtype.caldac[0]; + type = board->caldac[0]; s->maxdata = (1 << caldacs[type].n_bits) - 1; for (chan = 0; chan < s->n_chan; chan++) @@ -4992,6 +5020,7 @@ 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) { + 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; @@ -5003,7 +5032,7 @@ static void ni_write_caldac(struct comedi_device *dev, int addr, int val) devpriv->caldacs[addr] = val; for (i = 0; i < 3; i++) { - type = boardtype.caldac[i]; + type = board->caldac[i]; if (type == caldac_none) break; if (addr < caldacs[type].n_chans) { @@ -5275,7 +5304,9 @@ static int ni_old_set_pfi_routing(struct comedi_device *dev, unsigned chan, static int ni_set_pfi_routing(struct comedi_device *dev, unsigned chan, unsigned source) { - if (boardtype.reg_type & ni_reg_m_series_mask) + 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); @@ -5336,7 +5367,9 @@ static unsigned ni_old_get_pfi_routing(struct comedi_device *dev, unsigned chan) static unsigned ni_get_pfi_routing(struct comedi_device *dev, unsigned chan) { - if (boardtype.reg_type & ni_reg_m_series_mask) + 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); @@ -5345,10 +5378,11 @@ static unsigned ni_get_pfi_routing(struct comedi_device *dev, unsigned chan) 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; unsigned bits; - if ((boardtype.reg_type & ni_reg_m_series_mask) == 0) { + if ((board->reg_type & ni_reg_m_series_mask) == 0) { return -ENOTSUPP; } bits = ni_readl(M_Offset_PFI_Filter); @@ -5362,9 +5396,10 @@ 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 ((boardtype.reg_type & ni_reg_m_series_mask) == 0) { + if ((board->reg_type & ni_reg_m_series_mask) == 0) { return -ENOTSUPP; } if (data[0]) { @@ -5423,6 +5458,7 @@ static int ni_pfi_insn_config(struct comedi_device *dev, */ static void ni_rtsi_init(struct comedi_device *dev) { + 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 */ @@ -5449,7 +5485,7 @@ static void ni_rtsi_init(struct comedi_device *dev) RTSI_Trig_Output_Bits(5, NI_RTSI_OUTPUT_G_SRC0) | RTSI_Trig_Output_Bits(6, NI_RTSI_OUTPUT_G_GATE0); - if (boardtype.reg_type & ni_reg_m_series_mask) + 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, @@ -5517,7 +5553,9 @@ static int ni_mseries_get_pll_parameters(unsigned reference_period_ns, static inline unsigned num_configurable_rtsi_channels(struct comedi_device *dev) { - if (boardtype.reg_type & ni_reg_m_series_mask) + const struct ni_board_struct *board = comedi_board(dev); + + if (board->reg_type & ni_reg_m_series_mask) return 8; else return 7; @@ -5629,6 +5667,7 @@ static int ni_mseries_set_pll_master_clock(struct comedi_device *dev, 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) { @@ -5636,7 +5675,7 @@ static int ni_set_master_clock(struct comedi_device *dev, unsigned source, devpriv->stc_writew(dev, devpriv->rtsi_trig_direction_reg, RTSI_Trig_Direction_Register); devpriv->clock_ns = TIMEBASE_1_NS; - if (boardtype.reg_type & ni_reg_m_series_mask) { + if (board->reg_type & ni_reg_m_series_mask) { devpriv->clock_and_fout2 &= ~(MSeries_Timebase1_Select_Bit | MSeries_Timebase3_Select_Bit); @@ -5646,7 +5685,7 @@ static int ni_set_master_clock(struct comedi_device *dev, unsigned source, } devpriv->clock_source = source; } else { - if (boardtype.reg_type & ni_reg_m_series_mask) { + if (board->reg_type & ni_reg_m_series_mask) { return ni_mseries_set_pll_master_clock(dev, source, period_ns); } else { @@ -5676,6 +5715,8 @@ static int ni_set_master_clock(struct comedi_device *dev, unsigned source, static int ni_valid_rtsi_output_source(struct comedi_device *dev, unsigned chan, unsigned source) { + const struct ni_board_struct *board = comedi_board(dev); + if (chan >= num_configurable_rtsi_channels(dev)) { if (chan == old_RTSI_clock_channel) { if (source == NI_RTSI_OUTPUT_RTSI_OSC) @@ -5702,7 +5743,7 @@ static int ni_valid_rtsi_output_source(struct comedi_device *dev, unsigned chan, return 1; break; case NI_RTSI_OUTPUT_RTSI_OSC: - if (boardtype.reg_type & ni_reg_m_series_mask) + if (board->reg_type & ni_reg_m_series_mask) return 1; else return 0; @@ -5758,6 +5799,7 @@ static int ni_rtsi_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; unsigned int chan = CR_CHAN(insn->chanspec); @@ -5766,9 +5808,7 @@ static int ni_rtsi_insn_config(struct comedi_device *dev, if (chan < num_configurable_rtsi_channels(dev)) { devpriv->rtsi_trig_direction_reg |= RTSI_Output_Bit(chan, - (boardtype. - reg_type & ni_reg_m_series_mask) != - 0); + (board->reg_type & ni_reg_m_series_mask) != 0); } else if (chan == old_RTSI_clock_channel) { devpriv->rtsi_trig_direction_reg |= Drive_RTSI_Clock_Bit; @@ -5780,9 +5820,7 @@ static int ni_rtsi_insn_config(struct comedi_device *dev, if (chan < num_configurable_rtsi_channels(dev)) { devpriv->rtsi_trig_direction_reg &= ~RTSI_Output_Bit(chan, - (boardtype. - reg_type & ni_reg_m_series_mask) - != 0); + (board->reg_type & ni_reg_m_series_mask) != 0); } else if (chan == old_RTSI_clock_channel) { devpriv->rtsi_trig_direction_reg &= ~Drive_RTSI_Clock_Bit; @@ -5795,10 +5833,9 @@ static int ni_rtsi_insn_config(struct comedi_device *dev, data[1] = (devpriv->rtsi_trig_direction_reg & RTSI_Output_Bit(chan, - (boardtype.reg_type & - ni_reg_m_series_mask) - != 0)) ? INSN_CONFIG_DIO_OUTPUT : - INSN_CONFIG_DIO_INPUT; + (board->reg_type & ni_reg_m_series_mask) != 0)) + ? INSN_CONFIG_DIO_OUTPUT + : INSN_CONFIG_DIO_INPUT; } else if (chan == old_RTSI_clock_channel) { data[1] = (devpriv->rtsi_trig_direction_reg & diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 0a00260d11f..b5f340c186e 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -280,29 +280,30 @@ enum FPGA_Control_Bits { static int ni_pcidio_cancel(struct comedi_device *dev, struct comedi_subdevice *s); +enum nidio_boardid { + BOARD_PCIDIO_32HS, + BOARD_PXI6533, + BOARD_PCI6534, +}; + struct nidio_board { - int dev_id; const char *name; unsigned int uses_firmware:1; }; static const struct nidio_board nidio_boards[] = { - { - .dev_id = 0x1150, + [BOARD_PCIDIO_32HS] = { .name = "pci-dio-32hs", - }, { - .dev_id = 0x1320, + }, + [BOARD_PXI6533] = { .name = "pxi-6533", - }, { - .dev_id = 0x12b0, + }, + [BOARD_PCI6534] = { .name = "pci-6534", .uses_firmware = 1, }, }; -#define n_nidio_boards ARRAY_SIZE(nidio_boards) -#define this_board ((const struct nidio_board *)dev->board_ptr) - struct nidio96_private { struct mite_struct *mite; int boardtype; @@ -419,7 +420,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d) unsigned int m_status = 0; /* interrupcions parasites */ - if (dev->attached == 0) { + if (!dev->attached) { /* assume it's from another card */ return IRQ_NONE; } @@ -1094,29 +1095,27 @@ static int pci_6534_upload_firmware(struct comedi_device *dev) return ret; } -static const struct nidio_board * -nidio_find_boardinfo(struct pci_dev *pcidev) -{ - unsigned int dev_id = pcidev->device; - unsigned int n; - - for (n = 0; n < ARRAY_SIZE(nidio_boards); n++) { - const struct nidio_board *board = &nidio_boards[n]; - if (board->dev_id == dev_id) - return board; - } - return NULL; -} - static int nidio_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); + const struct nidio_board *board = NULL; struct nidio96_private *devpriv; struct comedi_subdevice *s; int ret; unsigned int irq; + if (context < ARRAY_SIZE(nidio_boards)) + board = &nidio_boards[context]; + if (!board) + return -ENODEV; + dev->board_ptr = board; + dev->board_name = board->name; + + ret = comedi_pci_enable(dev); + if (ret) + return ret; + devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; @@ -1124,9 +1123,6 @@ static int nidio_auto_attach(struct comedi_device *dev, spin_lock_init(&devpriv->mite_channel_lock); - dev->board_ptr = nidio_find_boardinfo(pcidev); - if (!dev->board_ptr) - return -ENODEV; devpriv->mite = mite_alloc(pcidev); if (!devpriv->mite) return -ENOMEM; @@ -1141,9 +1137,8 @@ static int nidio_auto_attach(struct comedi_device *dev, if (devpriv->di_mite_ring == NULL) return -ENOMEM; - dev->board_name = this_board->name; irq = mite_irq(devpriv->mite); - if (this_board->uses_firmware) { + if (board->uses_firmware) { ret = pci_6534_upload_firmware(dev); if (ret < 0) return ret; @@ -1211,6 +1206,7 @@ static void nidio_detach(struct comedi_device *dev) mite_free(devpriv->mite); } } + comedi_pci_disable(dev); } static struct comedi_driver ni_pcidio_driver = { @@ -1221,15 +1217,15 @@ static struct comedi_driver ni_pcidio_driver = { }; static int ni_pcidio_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &ni_pcidio_driver); + return comedi_pci_auto_config(dev, &ni_pcidio_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(ni_pcidio_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1150) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1320) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x12b0) }, + { PCI_VDEVICE(NI, 0x1150), BOARD_PCIDIO_32HS }, + { PCI_VDEVICE(NI, 0x12b0), BOARD_PCI6534 }, + { PCI_VDEVICE(NI, 0x1320), BOARD_PXI6533 }, { 0 } }; MODULE_DEVICE_TABLE(pci, ni_pcidio_pci_table); diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index 98b43f2fc65..634d02303aa 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -111,7 +111,6 @@ Bugs: */ #include <linux/delay.h> -#include <linux/delay.h> #include "../comedidev.h" @@ -158,1036 +157,894 @@ static const struct comedi_lrange range_ni_M_625x_ao = { 3, { } }; -static const struct comedi_lrange range_ni_M_622x_ao = { 1, { - RANGE(-10, 10), - } +enum ni_pcimio_boardid { + BOARD_PCIMIO_16XE_50, + BOARD_PCIMIO_16XE_10, + BOARD_PCI6014, + BOARD_PXI6030E, + BOARD_PCIMIO_16E_1, + BOARD_PCIMIO_16E_4, + BOARD_PXI6040E, + BOARD_PCI6031E, + BOARD_PCI6032E, + BOARD_PCI6033E, + BOARD_PCI6071E, + BOARD_PCI6023E, + BOARD_PCI6024E, + BOARD_PCI6025E, + BOARD_PXI6025E, + BOARD_PCI6034E, + BOARD_PCI6035E, + BOARD_PCI6052E, + BOARD_PCI6110, + BOARD_PCI6111, + /* BOARD_PCI6115, */ + /* BOARD_PXI6115, */ + BOARD_PCI6711, + BOARD_PXI6711, + BOARD_PCI6713, + BOARD_PXI6713, + BOARD_PCI6731, + /* BOARD_PXI6731, */ + BOARD_PCI6733, + BOARD_PXI6733, + BOARD_PXI6071E, + BOARD_PXI6070E, + BOARD_PXI6052E, + BOARD_PXI6031E, + BOARD_PCI6036E, + BOARD_PCI6220, + BOARD_PCI6221, + BOARD_PCI6221_37PIN, + BOARD_PCI6224, + BOARD_PXI6224, + BOARD_PCI6225, + BOARD_PXI6225, + BOARD_PCI6229, + BOARD_PCI6250, + BOARD_PCI6251, + BOARD_PCIE6251, + BOARD_PXIE6251, + BOARD_PCI6254, + BOARD_PCI6259, + BOARD_PCIE6259, + BOARD_PCI6280, + BOARD_PCI6281, + BOARD_PXI6281, + BOARD_PCI6284, + BOARD_PCI6289, + BOARD_PCI6143, + BOARD_PXI6143, }; static const struct ni_board_struct ni_boards[] = { - { - .device_id = 0x0162, /* NI also says 0x1620. typo? */ - .name = "pci-mio-16xe-50", - .n_adchan = 16, - .adbits = 16, - .ai_fifo_depth = 2048, - .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 = 0x1170, - .name = "pci-mio-16xe-10", /* aka pci-6030E */ - .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 = 10000, - .num_p0_dio_channels = 8, - .caldac = {dac8800, dac8043, ad8522}, - .has_8255 = 0, - }, - { - .device_id = 0x28c0, - .name = "pci-6014", - .n_adchan = 16, - .adbits = 16, - .ai_fifo_depth = 512, - .alwaysdither = 1, - .gainlkup = ai_gain_4, - .ai_speed = 5000, - .n_aochan = 2, - .aobits = 16, - .ao_fifo_depth = 0, - .ao_range_table = &range_bipolar10, - .ao_unipolar = 0, - .ao_speed = 100000, - .num_p0_dio_channels = 8, - .caldac = {ad8804_debug}, - .has_8255 = 0, - }, - { - .device_id = 0x11d0, - .name = "pxi-6030e", - .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 = 10000, - .num_p0_dio_channels = 8, - .caldac = {dac8800, dac8043, ad8522}, - .has_8255 = 0, - }, - { - .device_id = 0x1180, - .name = "pci-mio-16e-1", /* aka pci-6070e */ - .n_adchan = 16, - .adbits = 12, - .ai_fifo_depth = 512, - .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, - .num_p0_dio_channels = 8, - .caldac = {mb88341}, - .has_8255 = 0, - }, - { - .device_id = 0x1190, - .name = "pci-mio-16e-4", /* aka pci-6040e */ - .n_adchan = 16, - .adbits = 12, - .ai_fifo_depth = 512, - .alwaysdither = 0, - .gainlkup = ai_gain_16, - /* .Note = there have been reported problems with full speed - * on this board */ - .ai_speed = 2000, - .n_aochan = 2, - .aobits = 12, - .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 */ - .has_8255 = 0, - }, - { - .device_id = 0x11c0, - .name = "pxi-6040e", - .n_adchan = 16, - .adbits = 12, - .ai_fifo_depth = 512, - .alwaysdither = 0, - .gainlkup = ai_gain_16, - .ai_speed = 2000, - .n_aochan = 2, - .aobits = 12, - .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}, - .has_8255 = 0, - }, - - { - .device_id = 0x1330, - .name = "pci-6031e", - .n_adchan = 64, - .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 = 10000, - .num_p0_dio_channels = 8, - .caldac = {dac8800, dac8043, ad8522}, - .has_8255 = 0, - }, - { - .device_id = 0x1270, - .name = "pci-6032e", - .n_adchan = 16, - .adbits = 16, - .ai_fifo_depth = 512, - .alwaysdither = 1, - .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, - }, - { - .device_id = 0x1340, - .name = "pci-6033e", - .n_adchan = 64, - .adbits = 16, - .ai_fifo_depth = 512, - .alwaysdither = 1, - .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, - }, - { - .device_id = 0x1350, - .name = "pci-6071e", - .n_adchan = 64, - .adbits = 12, - .ai_fifo_depth = 512, - .alwaysdither = 1, - .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, - .num_p0_dio_channels = 8, - .caldac = {ad8804_debug}, - .has_8255 = 0, - }, - { - .device_id = 0x2a60, - .name = "pci-6023e", - .n_adchan = 16, - .adbits = 12, - .ai_fifo_depth = 512, - .alwaysdither = 0, - .gainlkup = ai_gain_4, - .ai_speed = 5000, - .n_aochan = 0, - .aobits = 0, - .ao_unipolar = 0, - .num_p0_dio_channels = 8, - .caldac = {ad8804_debug}, /* manual is wrong */ - .has_8255 = 0, - }, - { - .device_id = 0x2a70, - .name = "pci-6024e", - .n_adchan = 16, - .adbits = 12, - .ai_fifo_depth = 512, - .alwaysdither = 0, - .gainlkup = ai_gain_4, - .ai_speed = 5000, - .n_aochan = 2, - .aobits = 12, - .ao_fifo_depth = 0, - .ao_range_table = &range_bipolar10, - .ao_unipolar = 0, - .ao_speed = 100000, - .num_p0_dio_channels = 8, - .caldac = {ad8804_debug}, /* manual is wrong */ - .has_8255 = 0, - }, - { - .device_id = 0x2a80, - .name = "pci-6025e", - .n_adchan = 16, - .adbits = 12, - .ai_fifo_depth = 512, - .alwaysdither = 0, - .gainlkup = ai_gain_4, - .ai_speed = 5000, - .n_aochan = 2, - .aobits = 12, - .ao_fifo_depth = 0, - .ao_range_table = &range_bipolar10, - .ao_unipolar = 0, - .ao_speed = 100000, - .num_p0_dio_channels = 8, - .caldac = {ad8804_debug}, /* manual is wrong */ - .has_8255 = 1, - }, - { - .device_id = 0x2ab0, - .name = "pxi-6025e", - .n_adchan = 16, - .adbits = 12, - .ai_fifo_depth = 512, - .alwaysdither = 0, - .gainlkup = ai_gain_4, - .ai_speed = 5000, - .n_aochan = 2, - .aobits = 12, - .ao_fifo_depth = 0, - .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, - }, - - { - .device_id = 0x2ca0, - .name = "pci-6034e", - .n_adchan = 16, - .adbits = 16, - .ai_fifo_depth = 512, - .alwaysdither = 1, - .gainlkup = ai_gain_4, - .ai_speed = 5000, - .n_aochan = 0, - .aobits = 0, - .ao_fifo_depth = 0, - .ao_unipolar = 0, - .num_p0_dio_channels = 8, - .caldac = {ad8804_debug}, - .has_8255 = 0, - }, - { - .device_id = 0x2c80, - .name = "pci-6035e", - .n_adchan = 16, - .adbits = 16, - .ai_fifo_depth = 512, - .alwaysdither = 1, - .gainlkup = ai_gain_4, - .ai_speed = 5000, - .n_aochan = 2, - .aobits = 12, - .ao_fifo_depth = 0, - .ao_range_table = &range_bipolar10, - .ao_unipolar = 0, - .ao_speed = 100000, - .num_p0_dio_channels = 8, - .caldac = {ad8804_debug}, - .has_8255 = 0, - }, - { - .device_id = 0x18b0, - .name = "pci-6052e", - .n_adchan = 16, - .adbits = 16, - .ai_fifo_depth = 512, - .alwaysdither = 1, - .gainlkup = ai_gain_16, - .ai_speed = 3000, - .n_aochan = 2, - .aobits = 16, - .ao_unipolar = 1, - .ao_fifo_depth = 2048, - .ao_range_table = &range_ni_E_ao_ext, - .ao_speed = 3000, - .num_p0_dio_channels = 8, - .caldac = {ad8804_debug, ad8804_debug, ad8522}, /* manual is wrong */ - }, - {.device_id = 0x14e0, - .name = "pci-6110", - .n_adchan = 4, - .adbits = 12, - .ai_fifo_depth = 8192, - .alwaysdither = 0, - .gainlkup = ai_gain_611x, - .ai_speed = 200, - .n_aochan = 2, - .aobits = 16, - .reg_type = ni_reg_611x, - .ao_range_table = &range_bipolar10, - .ao_unipolar = 0, - .ao_fifo_depth = 2048, - .ao_speed = 250, - .num_p0_dio_channels = 8, - .caldac = {ad8804, ad8804}, - }, - { - .device_id = 0x14f0, - .name = "pci-6111", - .n_adchan = 2, - .adbits = 12, - .ai_fifo_depth = 8192, - .alwaysdither = 0, - .gainlkup = ai_gain_611x, - .ai_speed = 200, - .n_aochan = 2, - .aobits = 16, - .reg_type = ni_reg_611x, - .ao_range_table = &range_bipolar10, - .ao_unipolar = 0, - .ao_fifo_depth = 2048, - .ao_speed = 250, - .num_p0_dio_channels = 8, - .caldac = {ad8804, ad8804}, - }, + [BOARD_PCIMIO_16XE_50] = { + .name = "pci-mio-16xe-50", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 2048, + .alwaysdither = 1, + .gainlkup = ai_gain_8, + .ai_speed = 50000, + .n_aochan = 2, + .aobits = 12, + .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_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 = 10000, + .num_p0_dio_channels = 8, + .caldac = { dac8800, dac8043, ad8522 }, + }, + [BOARD_PCI6014] = { + .name = "pci-6014", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_4, + .ai_speed = 5000, + .n_aochan = 2, + .aobits = 16, + .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_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 = 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_fifo_depth = 512, + .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, + .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_fifo_depth = 512, + .gainlkup = ai_gain_16, + /* + * there have been reported problems with + * full speed on this board + */ + .ai_speed = 2000, + .n_aochan = 2, + .aobits = 12, + .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_fifo_depth = 512, + .gainlkup = ai_gain_16, + .ai_speed = 2000, + .n_aochan = 2, + .aobits = 12, + .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_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 = 10000, + .num_p0_dio_channels = 8, + .caldac = { dac8800, dac8043, ad8522 }, + }, + [BOARD_PCI6032E] = { + .name = "pci-6032e", + .n_adchan = 16, + .adbits = 16, + .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_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_fifo_depth = 512, + .alwaysdither = 1, + .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, + .num_p0_dio_channels = 8, + .caldac = { ad8804_debug }, + }, + [BOARD_PCI6023E] = { + .name = "pci-6023e", + .n_adchan = 16, + .adbits = 12, + .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_fifo_depth = 512, + .gainlkup = ai_gain_4, + .ai_speed = 5000, + .n_aochan = 2, + .aobits = 12, + .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_fifo_depth = 512, + .gainlkup = ai_gain_4, + .ai_speed = 5000, + .n_aochan = 2, + .aobits = 12, + .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_fifo_depth = 512, + .gainlkup = ai_gain_4, + .ai_speed = 5000, + .n_aochan = 2, + .aobits = 12, + .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_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_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_4, + .ai_speed = 5000, + .n_aochan = 2, + .aobits = 12, + .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_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_16, + .ai_speed = 3000, + .n_aochan = 2, + .aobits = 16, + .ao_unipolar = 1, + .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_fifo_depth = 8192, + .alwaysdither = 0, + .gainlkup = ai_gain_611x, + .ai_speed = 200, + .n_aochan = 2, + .aobits = 16, + .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_fifo_depth = 8192, + .gainlkup = ai_gain_611x, + .ai_speed = 200, + .n_aochan = 2, + .aobits = 16, + .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 /* The 6115 boards probably need their own driver */ - { - .device_id = 0x2ed0, - .name = "pci-6115", - .n_adchan = 4, - .adbits = 12, - .ai_fifo_depth = 8192, - .alwaysdither = 0, - .gainlkup = ai_gain_611x, - .ai_speed = 100, - .n_aochan = 2, - .aobits = 16, - .ao_671x = 1, - .ao_unipolar = 0, - .ao_fifo_depth = 2048, - .ao_speed = 250, - .num_p0_dio_channels = 8, - .reg_611x = 1, - .caldac = {ad8804_debug, ad8804_debug, ad8804_debug}, /* XXX */ - }, + [BOARD_PCI6115] = { /* .device_id = 0x2ed0, */ + .name = "pci-6115", + .n_adchan = 4, + .adbits = 12, + .ai_fifo_depth = 8192, + .gainlkup = ai_gain_611x, + .ai_speed = 100, + .n_aochan = 2, + .aobits = 16, + .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 }, + }, #endif #if 0 - { - .device_id = 0x0000, - .name = "pxi-6115", - .n_adchan = 4, - .adbits = 12, - .ai_fifo_depth = 8192, - .alwaysdither = 0, - .gainlkup = ai_gain_611x, - .ai_speed = 100, - .n_aochan = 2, - .aobits = 16, - .ao_671x = 1, - .ao_unipolar = 0, - .ao_fifo_depth = 2048, - .ao_speed = 250, - .reg_611x = 1, - .num_p0_dio_channels = 8, - caldac = {ad8804_debug, ad8804_debug, ad8804_debug}, /* XXX */ - }, + [BOARD_PXI6115] = { /* .device_id = ????, */ + .name = "pxi-6115", + .n_adchan = 4, + .adbits = 12, + .ai_fifo_depth = 8192, + .gainlkup = ai_gain_611x, + .ai_speed = 100, + .n_aochan = 2, + .aobits = 16, + .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 }, + }, #endif - { - .device_id = 0x1880, - .name = "pci-6711", - .n_adchan = 0, /* no analog input */ - .n_aochan = 4, - .aobits = 12, - .ao_unipolar = 0, - .ao_fifo_depth = 16384, - /* data sheet says 8192, but fifo really holds 16384 samples */ - .ao_range_table = &range_bipolar10, - .ao_speed = 1000, - .num_p0_dio_channels = 8, - .reg_type = ni_reg_6711, - .caldac = {ad8804_debug}, - }, - { - .device_id = 0x2b90, - .name = "pxi-6711", - .n_adchan = 0, /* no analog input */ - .n_aochan = 4, - .aobits = 12, - .ao_unipolar = 0, - .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}, - }, - { - .device_id = 0x1870, - .name = "pci-6713", - .n_adchan = 0, /* no analog input */ - .n_aochan = 8, - .aobits = 12, - .ao_unipolar = 0, - .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}, - }, - { - .device_id = 0x2b80, - .name = "pxi-6713", - .n_adchan = 0, /* no analog input */ - .n_aochan = 8, - .aobits = 12, - .ao_unipolar = 0, - .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}, - }, - { - .device_id = 0x2430, - .name = "pci-6731", - .n_adchan = 0, /* no analog input */ - .n_aochan = 4, - .aobits = 16, - .ao_unipolar = 0, - .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}, - }, -#if 0 /* need device ids */ - { - .device_id = 0x0, - .name = "pxi-6731", - .n_adchan = 0, /* no analog input */ - .n_aochan = 4, - .aobits = 16, - .ao_unipolar = 0, - .ao_fifo_depth = 8192, - .ao_range_table = &range_bipolar10, - .num_p0_dio_channels = 8, - .reg_type = ni_reg_6711, - .caldac = {ad8804_debug}, - }, + [BOARD_PCI6711] = { + .name = "pci-6711", + .n_aochan = 4, + .aobits = 12, + /* 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_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_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_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_fifo_depth = 8192, + .ao_range_table = &range_bipolar10, + .ao_speed = 1000, + .num_p0_dio_channels = 8, + .reg_type = ni_reg_6711, + .caldac = { ad8804_debug }, + }, +#if 0 + [BOARD_PXI6731] = { /* .device_id = ????, */ + .name = "pxi-6731", + .n_aochan = 4, + .aobits = 16, + .ao_fifo_depth = 8192, + .ao_range_table = &range_bipolar10, + .num_p0_dio_channels = 8, + .reg_type = ni_reg_6711, + .caldac = { ad8804_debug }, + }, #endif - { - .device_id = 0x2410, - .name = "pci-6733", - .n_adchan = 0, /* no analog input */ - .n_aochan = 8, - .aobits = 16, - .ao_unipolar = 0, - .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}, - }, - { - .device_id = 0x2420, - .name = "pxi-6733", - .n_adchan = 0, /* no analog input */ - .n_aochan = 8, - .aobits = 16, - .ao_unipolar = 0, - .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}, - }, - { - .device_id = 0x15b0, - .name = "pxi-6071e", - .n_adchan = 64, - .adbits = 12, - .ai_fifo_depth = 512, - .alwaysdither = 1, - .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, - .num_p0_dio_channels = 8, - .caldac = {ad8804_debug}, - .has_8255 = 0, - }, - { - .device_id = 0x11b0, - .name = "pxi-6070e", - .n_adchan = 16, - .adbits = 12, - .ai_fifo_depth = 512, - .alwaysdither = 1, - .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, - .num_p0_dio_channels = 8, - .caldac = {ad8804_debug}, - .has_8255 = 0, - }, - { - .device_id = 0x18c0, - .name = "pxi-6052e", - .n_adchan = 16, - .adbits = 16, - .ai_fifo_depth = 512, - .alwaysdither = 1, - .gainlkup = ai_gain_16, - .ai_speed = 3000, - .n_aochan = 2, - .aobits = 16, - .ao_unipolar = 1, - .ao_fifo_depth = 2048, - .ao_range_table = &range_ni_E_ao_ext, - .ao_speed = 3000, - .num_p0_dio_channels = 8, - .caldac = {mb88341, mb88341, ad8522}, - }, - { - .device_id = 0x1580, - .name = "pxi-6031e", - .n_adchan = 64, - .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 = 10000, - .num_p0_dio_channels = 8, - .caldac = {dac8800, dac8043, ad8522}, - }, - { - .device_id = 0x2890, - .name = "pci-6036e", - .n_adchan = 16, - .adbits = 16, - .ai_fifo_depth = 512, - .alwaysdither = 1, - .gainlkup = ai_gain_4, - .ai_speed = 5000, - .n_aochan = 2, - .aobits = 16, - .ao_fifo_depth = 0, - .ao_range_table = &range_bipolar10, - .ao_unipolar = 0, - .ao_speed = 100000, - .num_p0_dio_channels = 8, - .caldac = {ad8804_debug}, - .has_8255 = 0, - }, - { - .device_id = 0x70b0, - .name = "pci-6220", - .n_adchan = 16, - .adbits = 16, - .ai_fifo_depth = 512, - /* .FIXME = guess */ - .gainlkup = ai_gain_622x, - .ai_speed = 4000, - .n_aochan = 0, - .aobits = 0, - .ao_fifo_depth = 0, - .num_p0_dio_channels = 8, - .reg_type = ni_reg_622x, - .ao_unipolar = 0, - .caldac = {caldac_none}, - .has_8255 = 0, - }, - { - .device_id = 0x70af, - .name = "pci-6221", - .n_adchan = 16, - .adbits = 16, - .ai_fifo_depth = 4095, - .gainlkup = ai_gain_622x, - .ai_speed = 4000, - .n_aochan = 2, - .aobits = 16, - .ao_fifo_depth = 8191, - .ao_range_table = &range_ni_M_622x_ao, - .reg_type = ni_reg_622x, - .ao_unipolar = 0, - .ao_speed = 1200, - .num_p0_dio_channels = 8, - .caldac = {caldac_none}, - .has_8255 = 0, - }, - { - .device_id = 0x71bc, - .name = "pci-6221_37pin", - .n_adchan = 16, - .adbits = 16, - .ai_fifo_depth = 4095, - .gainlkup = ai_gain_622x, - .ai_speed = 4000, - .n_aochan = 2, - .aobits = 16, - .ao_fifo_depth = 8191, - .ao_range_table = &range_ni_M_622x_ao, - .reg_type = ni_reg_622x, - .ao_unipolar = 0, - .ao_speed = 1200, - .num_p0_dio_channels = 8, - .caldac = {caldac_none}, - .has_8255 = 0, - }, - { - .device_id = 0x70f2, - .name = "pci-6224", - .n_adchan = 32, - .adbits = 16, - .ai_fifo_depth = 4095, - .gainlkup = ai_gain_622x, - .ai_speed = 4000, - .n_aochan = 0, - .aobits = 0, - .ao_fifo_depth = 0, - .reg_type = ni_reg_622x, - .ao_unipolar = 0, - .num_p0_dio_channels = 32, - .caldac = {caldac_none}, - .has_8255 = 0, - }, - { - .device_id = 0x70f3, - .name = "pxi-6224", - .n_adchan = 32, - .adbits = 16, - .ai_fifo_depth = 4095, - .gainlkup = ai_gain_622x, - .ai_speed = 4000, - .n_aochan = 0, - .aobits = 0, - .ao_fifo_depth = 0, - .reg_type = ni_reg_622x, - .ao_unipolar = 0, - .num_p0_dio_channels = 32, - .caldac = {caldac_none}, - .has_8255 = 0, - }, - { - .device_id = 0x716c, - .name = "pci-6225", - .n_adchan = 80, - .adbits = 16, - .ai_fifo_depth = 4095, - .gainlkup = ai_gain_622x, - .ai_speed = 4000, - .n_aochan = 2, - .aobits = 16, - .ao_fifo_depth = 8191, - .ao_range_table = &range_ni_M_622x_ao, - .reg_type = ni_reg_622x, - .ao_unipolar = 0, - .ao_speed = 1200, - .num_p0_dio_channels = 32, - .caldac = {caldac_none}, - .has_8255 = 0, - }, - { - .device_id = 0x716d, - .name = "pxi-6225", - .n_adchan = 80, - .adbits = 16, - .ai_fifo_depth = 4095, - .gainlkup = ai_gain_622x, - .ai_speed = 4000, - .n_aochan = 2, - .aobits = 16, - .ao_fifo_depth = 8191, - .ao_range_table = &range_ni_M_622x_ao, - .reg_type = ni_reg_622x, - .ao_unipolar = 0, - .ao_speed = 1200, - .num_p0_dio_channels = 32, - .caldac = {caldac_none}, - .has_8255 = 0, + [BOARD_PCI6733] = { + .name = "pci-6733", + .n_aochan = 8, + .aobits = 16, + .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_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_fifo_depth = 512, + .alwaysdither = 1, + .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, + .num_p0_dio_channels = 8, + .caldac = { ad8804_debug }, + }, + [BOARD_PXI6070E] = { + .name = "pxi-6070e", + .n_adchan = 16, + .adbits = 12, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .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, + .num_p0_dio_channels = 8, + .caldac = { ad8804_debug }, + }, + [BOARD_PXI6052E] = { + .name = "pxi-6052e", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_16, + .ai_speed = 3000, + .n_aochan = 2, + .aobits = 16, + .ao_unipolar = 1, + .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_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 = 10000, + .num_p0_dio_channels = 8, + .caldac = { dac8800, dac8043, ad8522 }, + }, + [BOARD_PCI6036E] = { + .name = "pci-6036e", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_4, + .ai_speed = 5000, + .n_aochan = 2, + .aobits = 16, + .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_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_fifo_depth = 4095, + .gainlkup = ai_gain_622x, + .ai_speed = 4000, + .n_aochan = 2, + .aobits = 16, + .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_fifo_depth = 4095, + .gainlkup = ai_gain_622x, + .ai_speed = 4000, + .n_aochan = 2, + .aobits = 16, + .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_fifo_depth = 4095, + .gainlkup = ai_gain_622x, + .ai_speed = 4000, + .reg_type = ni_reg_622x, + .num_p0_dio_channels = 32, + .caldac = { caldac_none }, + }, + [BOARD_PXI6224] = { + .name = "pxi-6224", + .n_adchan = 32, + .adbits = 16, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_622x, + .ai_speed = 4000, + .reg_type = ni_reg_622x, + .num_p0_dio_channels = 32, + .caldac = { caldac_none }, + }, + [BOARD_PCI6225] = { + .name = "pci-6225", + .n_adchan = 80, + .adbits = 16, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_622x, + .ai_speed = 4000, + .n_aochan = 2, + .aobits = 16, + .ao_fifo_depth = 8191, + .ao_range_table = &range_bipolar10, + .reg_type = ni_reg_622x, + .ao_speed = 1200, + .num_p0_dio_channels = 32, + .caldac = { caldac_none }, + }, + [BOARD_PXI6225] = { + .name = "pxi-6225", + .n_adchan = 80, + .adbits = 16, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_622x, + .ai_speed = 4000, + .n_aochan = 2, + .aobits = 16, + .ao_fifo_depth = 8191, + .ao_range_table = &range_bipolar10, + .reg_type = ni_reg_622x, + .ao_speed = 1200, + .num_p0_dio_channels = 32, + .caldac = { caldac_none }, + }, + [BOARD_PCI6229] = { + .name = "pci-6229", + .n_adchan = 32, + .adbits = 16, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_622x, + .ai_speed = 4000, + .n_aochan = 4, + .aobits = 16, + .ao_fifo_depth = 8191, + .ao_range_table = &range_bipolar10, + .reg_type = ni_reg_622x, + .ao_speed = 1200, + .num_p0_dio_channels = 32, + .caldac = { caldac_none }, + }, + [BOARD_PCI6250] = { + .name = "pci-6250", + .n_adchan = 16, + .adbits = 16, + .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_fifo_depth = 4095, + .gainlkup = ai_gain_628x, + .ai_speed = 800, + .n_aochan = 2, + .aobits = 16, + .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_fifo_depth = 4095, + .gainlkup = ai_gain_628x, + .ai_speed = 800, + .n_aochan = 2, + .aobits = 16, + .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_fifo_depth = 4095, + .gainlkup = ai_gain_628x, + .ai_speed = 800, + .n_aochan = 2, + .aobits = 16, + .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_fifo_depth = 4095, + .gainlkup = ai_gain_628x, + .ai_speed = 800, + .reg_type = ni_reg_625x, + .num_p0_dio_channels = 32, + .caldac = { caldac_none }, + }, + [BOARD_PCI6259] = { + .name = "pci-6259", + .n_adchan = 32, + .adbits = 16, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_628x, + .ai_speed = 800, + .n_aochan = 4, + .aobits = 16, + .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, + .caldac = { caldac_none }, + }, + [BOARD_PCIE6259] = { + .name = "pcie-6259", + .n_adchan = 32, + .adbits = 16, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_628x, + .ai_speed = 800, + .n_aochan = 4, + .aobits = 16, + .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, + .caldac = { caldac_none }, + }, + [BOARD_PCI6280] = { + .name = "pci-6280", + .n_adchan = 16, + .adbits = 18, + .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_fifo_depth = 2047, + .gainlkup = ai_gain_628x, + .ai_speed = 1600, + .n_aochan = 2, + .aobits = 16, + .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_fifo_depth = 2047, + .gainlkup = ai_gain_628x, + .ai_speed = 1600, + .n_aochan = 2, + .aobits = 16, + .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_fifo_depth = 2047, + .gainlkup = ai_gain_628x, + .ai_speed = 1600, + .reg_type = ni_reg_628x, + .num_p0_dio_channels = 32, + .caldac = { caldac_none }, + }, + [BOARD_PCI6289] = { + .name = "pci-6289", + .n_adchan = 32, + .adbits = 18, + .ai_fifo_depth = 2047, + .gainlkup = ai_gain_628x, + .ai_speed = 1600, + .n_aochan = 4, + .aobits = 16, + .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, + .caldac = { caldac_none }, + }, + [BOARD_PCI6143] = { + .name = "pci-6143", + .n_adchan = 8, + .adbits = 16, + .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_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 }, }, - { - .device_id = 0x70aa, - .name = "pci-6229", - .n_adchan = 32, - .adbits = 16, - .ai_fifo_depth = 4095, - .gainlkup = ai_gain_622x, - .ai_speed = 4000, - .n_aochan = 4, - .aobits = 16, - .ao_fifo_depth = 8191, - .ao_range_table = &range_ni_M_622x_ao, - .reg_type = ni_reg_622x, - .ao_unipolar = 0, - .ao_speed = 1200, - .num_p0_dio_channels = 32, - .caldac = {caldac_none}, - .has_8255 = 0, - }, - { - .device_id = 0x70b4, - .name = "pci-6250", - .n_adchan = 16, - .adbits = 16, - .ai_fifo_depth = 4095, - .gainlkup = ai_gain_628x, - .ai_speed = 800, - .n_aochan = 0, - .aobits = 0, - .ao_fifo_depth = 0, - .reg_type = ni_reg_625x, - .ao_unipolar = 0, - .num_p0_dio_channels = 8, - .caldac = {caldac_none}, - .has_8255 = 0, - }, - { - .device_id = 0x70b8, - .name = "pci-6251", - .n_adchan = 16, - .adbits = 16, - .ai_fifo_depth = 4095, - .gainlkup = ai_gain_628x, - .ai_speed = 800, - .n_aochan = 2, - .aobits = 16, - .ao_fifo_depth = 8191, - .ao_range_table = &range_ni_M_625x_ao, - .reg_type = ni_reg_625x, - .ao_unipolar = 0, - .ao_speed = 350, - .num_p0_dio_channels = 8, - .caldac = {caldac_none}, - .has_8255 = 0, - }, - { - .device_id = 0x717d, - .name = "pcie-6251", - .n_adchan = 16, - .adbits = 16, - .ai_fifo_depth = 4095, - .gainlkup = ai_gain_628x, - .ai_speed = 800, - .n_aochan = 2, - .aobits = 16, - .ao_fifo_depth = 8191, - .ao_range_table = &range_ni_M_625x_ao, - .reg_type = ni_reg_625x, - .ao_unipolar = 0, - .ao_speed = 350, - .num_p0_dio_channels = 8, - .caldac = {caldac_none}, - .has_8255 = 0, - }, - { - .device_id = 0x72e8, - .name = "pxie-6251", - .n_adchan = 16, - .adbits = 16, - .ai_fifo_depth = 4095, - .gainlkup = ai_gain_628x, - .ai_speed = 800, - .n_aochan = 2, - .aobits = 16, - .ao_fifo_depth = 8191, - .ao_range_table = &range_ni_M_625x_ao, - .reg_type = ni_reg_625x, - .ao_unipolar = 0, - .ao_speed = 350, - .num_p0_dio_channels = 8, - .caldac = {caldac_none}, - .has_8255 = 0, - }, - { - .device_id = 0x70b7, - .name = "pci-6254", - .n_adchan = 32, - .adbits = 16, - .ai_fifo_depth = 4095, - .gainlkup = ai_gain_628x, - .ai_speed = 800, - .n_aochan = 0, - .aobits = 0, - .ao_fifo_depth = 0, - .reg_type = ni_reg_625x, - .ao_unipolar = 0, - .num_p0_dio_channels = 32, - .caldac = {caldac_none}, - .has_8255 = 0, - }, - { - .device_id = 0x70ab, - .name = "pci-6259", - .n_adchan = 32, - .adbits = 16, - .ai_fifo_depth = 4095, - .gainlkup = ai_gain_628x, - .ai_speed = 800, - .n_aochan = 4, - .aobits = 16, - .ao_fifo_depth = 8191, - .ao_range_table = &range_ni_M_625x_ao, - .reg_type = ni_reg_625x, - .ao_unipolar = 0, - .ao_speed = 350, - .num_p0_dio_channels = 32, - .caldac = {caldac_none}, - .has_8255 = 0, - }, - { - .device_id = 0x717f, - .name = "pcie-6259", - .n_adchan = 32, - .adbits = 16, - .ai_fifo_depth = 4095, - .gainlkup = ai_gain_628x, - .ai_speed = 800, - .n_aochan = 4, - .aobits = 16, - .ao_fifo_depth = 8191, - .ao_range_table = &range_ni_M_625x_ao, - .reg_type = ni_reg_625x, - .ao_unipolar = 0, - .ao_speed = 350, - .num_p0_dio_channels = 32, - .caldac = {caldac_none}, - .has_8255 = 0, - }, - { - .device_id = 0x70b6, - .name = "pci-6280", - .n_adchan = 16, - .adbits = 18, - .ai_fifo_depth = 2047, - .gainlkup = ai_gain_628x, - .ai_speed = 1600, - .n_aochan = 0, - .aobits = 0, - .ao_fifo_depth = 8191, - .reg_type = ni_reg_628x, - .ao_unipolar = 0, - .num_p0_dio_channels = 8, - .caldac = {caldac_none}, - .has_8255 = 0, - }, - { - .device_id = 0x70bd, - .name = "pci-6281", - .n_adchan = 16, - .adbits = 18, - .ai_fifo_depth = 2047, - .gainlkup = ai_gain_628x, - .ai_speed = 1600, - .n_aochan = 2, - .aobits = 16, - .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}, - .has_8255 = 0, - }, - { - .device_id = 0x70bf, - .name = "pxi-6281", - .n_adchan = 16, - .adbits = 18, - .ai_fifo_depth = 2047, - .gainlkup = ai_gain_628x, - .ai_speed = 1600, - .n_aochan = 2, - .aobits = 16, - .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}, - .has_8255 = 0, - }, - { - .device_id = 0x70bc, - .name = "pci-6284", - .n_adchan = 32, - .adbits = 18, - .ai_fifo_depth = 2047, - .gainlkup = ai_gain_628x, - .ai_speed = 1600, - .n_aochan = 0, - .aobits = 0, - .ao_fifo_depth = 0, - .reg_type = ni_reg_628x, - .ao_unipolar = 0, - .num_p0_dio_channels = 32, - .caldac = {caldac_none}, - .has_8255 = 0, - }, - { - .device_id = 0x70ac, - .name = "pci-6289", - .n_adchan = 32, - .adbits = 18, - .ai_fifo_depth = 2047, - .gainlkup = ai_gain_628x, - .ai_speed = 1600, - .n_aochan = 4, - .aobits = 16, - .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, - .caldac = {caldac_none}, - .has_8255 = 0, - }, - { - .device_id = 0x70C0, - .name = "pci-6143", - .n_adchan = 8, - .adbits = 16, - .ai_fifo_depth = 1024, - .alwaysdither = 0, - .gainlkup = ai_gain_6143, - .ai_speed = 4000, - .n_aochan = 0, - .aobits = 0, - .reg_type = ni_reg_6143, - .ao_unipolar = 0, - .ao_fifo_depth = 0, - .num_p0_dio_channels = 8, - .caldac = {ad8804_debug, ad8804_debug}, - }, - { - .device_id = 0x710D, - .name = "pxi-6143", - .n_adchan = 8, - .adbits = 16, - .ai_fifo_depth = 1024, - .alwaysdither = 0, - .gainlkup = ai_gain_6143, - .ai_speed = 4000, - .n_aochan = 0, - .aobits = 0, - .reg_type = ni_reg_6143, - .ao_unipolar = 0, - .ao_fifo_depth = 0, - .num_p0_dio_channels = 8, - .caldac = {ad8804_debug, ad8804_debug}, - }, }; struct ni_private { @@ -1569,6 +1426,7 @@ static void m_series_init_eeprom_buffer(struct comedi_device *dev) static void init_6143(struct comedi_device *dev) { + const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; /* Disable interrupts */ @@ -1579,7 +1437,8 @@ static void init_6143(struct comedi_device *dev) ni_writeb(0x80, PipelineDelay_6143); /* Set EOCMode, ADCMode and pipelinedelay */ ni_writeb(0x00, EOC_Set_6143); /* Set EOC Delay */ - ni_writel(boardtype.ai_fifo_depth / 2, AIFIFO_Flag_6143); /* Set the FIFO half full level */ + /* Set the FIFO half full level */ + ni_writel(board->ai_fifo_depth / 2, AIFIFO_Flag_6143); /* Strobe Relay disable bit */ devpriv->ai_calib_source_enabled = 0; @@ -1606,48 +1465,38 @@ static void pcimio_detach(struct comedi_device *dev) mite_free(devpriv->mite); } } -} - -static const struct ni_board_struct * -pcimio_find_boardinfo(struct pci_dev *pcidev) -{ - unsigned int device_id = pcidev->device; - unsigned int n; - - for (n = 0; n < ARRAY_SIZE(ni_boards); n++) { - const struct ni_board_struct *board = &ni_boards[n]; - if (board->device_id == device_id) - return board; - } - return NULL; + comedi_pci_disable(dev); } static int pcimio_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); + const struct ni_board_struct *board = NULL; struct ni_private *devpriv; int ret; - dev_info(dev->class_dev, "ni_pcimio: attach %s\n", pci_name(pcidev)); + if (context < ARRAY_SIZE(ni_boards)) + board = &ni_boards[context]; + if (!board) + return -ENODEV; + dev->board_ptr = board; + dev->board_name = board->name; + + ret = comedi_pci_enable(dev); + if (ret) + return ret; ret = ni_alloc_private(dev); if (ret) return ret; devpriv = dev->private; - dev->board_ptr = pcimio_find_boardinfo(pcidev); - if (!dev->board_ptr) - return -ENODEV; - devpriv->mite = mite_alloc(pcidev); if (!devpriv->mite) return -ENOMEM; - dev_dbg(dev->class_dev, "%s\n", boardtype.name); - dev->board_name = boardtype.name; - - if (boardtype.reg_type & ni_reg_m_series_mask) { + 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; @@ -1681,9 +1530,9 @@ static int pcimio_auto_attach(struct comedi_device *dev, if (devpriv->gpct_mite_ring[1] == NULL) return -ENOMEM; - if (boardtype.reg_type & ni_reg_m_series_mask) + if (board->reg_type & ni_reg_m_series_mask) m_series_init_eeprom_buffer(dev); - if (boardtype.reg_type == ni_reg_6143) + if (board->reg_type == ni_reg_6143) init_6143(dev); dev->irq = mite_irq(devpriv->mite); @@ -1788,65 +1637,66 @@ static struct comedi_driver ni_pcimio_driver = { }; static int ni_pcimio_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &ni_pcimio_driver); + return comedi_pci_auto_config(dev, &ni_pcimio_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(ni_pcimio_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x0162) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1170) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1180) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1190) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x11b0) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x11c0) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x11d0) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1270) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1330) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1340) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1350) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x14e0) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x14f0) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1580) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x15b0) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1880) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1870) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x18b0) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x18c0) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2410) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2420) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2430) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2890) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x28c0) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2a60) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2a70) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2a80) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2ab0) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2b80) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2b90) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2c80) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2ca0) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70aa) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70ab) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70ac) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70af) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b0) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b4) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b6) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b7) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70b8) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70bc) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70bd) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70bf) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70c0) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x70f2) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x710d) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x716c) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x716d) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x717f) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x71bc) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x717d) }, - { PCI_DEVICE(PCI_VENDOR_ID_NI, 0x72e8) }, + { PCI_VDEVICE(NI, 0x0162), BOARD_PCIMIO_16XE_50 }, /* 0x1620? */ + { PCI_VDEVICE(NI, 0x1170), BOARD_PCIMIO_16XE_10 }, + { PCI_VDEVICE(NI, 0x1180), BOARD_PCIMIO_16E_1 }, + { PCI_VDEVICE(NI, 0x1190), BOARD_PCIMIO_16E_4 }, + { PCI_VDEVICE(NI, 0x11b0), BOARD_PXI6070E }, + { PCI_VDEVICE(NI, 0x11c0), BOARD_PXI6040E }, + { PCI_VDEVICE(NI, 0x11d0), BOARD_PXI6030E }, + { PCI_VDEVICE(NI, 0x1270), BOARD_PCI6032E }, + { PCI_VDEVICE(NI, 0x1330), BOARD_PCI6031E }, + { PCI_VDEVICE(NI, 0x1340), BOARD_PCI6033E }, + { PCI_VDEVICE(NI, 0x1350), BOARD_PCI6071E }, + { PCI_VDEVICE(NI, 0x14e0), BOARD_PCI6110 }, + { PCI_VDEVICE(NI, 0x14f0), BOARD_PCI6111 }, + { PCI_VDEVICE(NI, 0x1580), BOARD_PXI6031E }, + { PCI_VDEVICE(NI, 0x15b0), BOARD_PXI6071E }, + { PCI_VDEVICE(NI, 0x1880), BOARD_PCI6711 }, + { PCI_VDEVICE(NI, 0x1870), BOARD_PCI6713 }, + { PCI_VDEVICE(NI, 0x18b0), BOARD_PCI6052E }, + { PCI_VDEVICE(NI, 0x18c0), BOARD_PXI6052E }, + { PCI_VDEVICE(NI, 0x2410), BOARD_PCI6733 }, + { PCI_VDEVICE(NI, 0x2420), BOARD_PXI6733 }, + { PCI_VDEVICE(NI, 0x2430), BOARD_PCI6731 }, + { PCI_VDEVICE(NI, 0x2890), BOARD_PCI6036E }, + { PCI_VDEVICE(NI, 0x28c0), BOARD_PCI6014 }, + { PCI_VDEVICE(NI, 0x2a60), BOARD_PCI6023E }, + { PCI_VDEVICE(NI, 0x2a70), BOARD_PCI6024E }, + { PCI_VDEVICE(NI, 0x2a80), BOARD_PCI6025E }, + { PCI_VDEVICE(NI, 0x2ab0), BOARD_PXI6025E }, + { PCI_VDEVICE(NI, 0x2b80), BOARD_PXI6713 }, + { PCI_VDEVICE(NI, 0x2b90), BOARD_PXI6711 }, + { PCI_VDEVICE(NI, 0x2c80), BOARD_PCI6035E }, + { PCI_VDEVICE(NI, 0x2ca0), BOARD_PCI6034E }, + { PCI_VDEVICE(NI, 0x70aa), BOARD_PCI6229 }, + { PCI_VDEVICE(NI, 0x70ab), BOARD_PCI6259 }, + { PCI_VDEVICE(NI, 0x70ac), BOARD_PCI6289 }, + { PCI_VDEVICE(NI, 0x70af), BOARD_PCI6221 }, + { PCI_VDEVICE(NI, 0x70b0), BOARD_PCI6220 }, + { PCI_VDEVICE(NI, 0x70b4), BOARD_PCI6250 }, + { PCI_VDEVICE(NI, 0x70b6), BOARD_PCI6280 }, + { PCI_VDEVICE(NI, 0x70b7), BOARD_PCI6254 }, + { PCI_VDEVICE(NI, 0x70b8), BOARD_PCI6251 }, + { PCI_VDEVICE(NI, 0x70bc), BOARD_PCI6284 }, + { PCI_VDEVICE(NI, 0x70bd), BOARD_PCI6281 }, + { PCI_VDEVICE(NI, 0x70bf), BOARD_PXI6281 }, + { PCI_VDEVICE(NI, 0x70c0), BOARD_PCI6143 }, + { PCI_VDEVICE(NI, 0x70f2), BOARD_PCI6224 }, + { PCI_VDEVICE(NI, 0x70f3), BOARD_PXI6224 }, + { PCI_VDEVICE(NI, 0x710d), BOARD_PXI6143 }, + { PCI_VDEVICE(NI, 0x716c), BOARD_PCI6225 }, + { PCI_VDEVICE(NI, 0x716d), BOARD_PXI6225 }, + { PCI_VDEVICE(NI, 0x717f), BOARD_PCIE6259 }, + { PCI_VDEVICE(NI, 0x71bc), BOARD_PCI6221_37PIN }, + { PCI_VDEVICE(NI, 0x717d), BOARD_PCIE6251 }, + { PCI_VDEVICE(NI, 0x72e8), BOARD_PXIE6251 }, { 0 } }; MODULE_DEVICE_TABLE(pci, ni_pcimio_pci_table); diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h index 504ea715533..0a613c07760 100644 --- a/drivers/staging/comedi/drivers/ni_stc.h +++ b/drivers/staging/comedi/drivers/ni_stc.h @@ -1421,10 +1421,6 @@ struct ni_board_struct { enum caldac_enum caldac[3]; }; -#define n_ni_boards (sizeof(ni_boards)/sizeof(struct ni_board_struct)) - -#define boardtype (*(struct ni_board_struct *)dev->board_ptr) - #define MAX_N_AO_CHAN 8 #define NUM_GPCT 2 diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index 6ee5da24a96..8be2a4c503c 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -451,23 +451,12 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) const struct pcl711_board *board = comedi_board(dev); struct pcl711_private *devpriv; int ret; - unsigned long iobase; unsigned int irq; struct comedi_subdevice *s; - /* claim our I/O space */ - - iobase = it->options[0]; - printk(KERN_INFO "comedi%d: pcl711: 0x%04lx ", dev->minor, iobase); - if (!request_region(iobase, PCL711_SIZE, "pcl711")) { - printk("I/O port conflict\n"); - return -EIO; - } - dev->iobase = iobase; - - /* there should be a sanity check here */ - - dev->board_name = board->name; + ret = comedi_request_region(dev, it->options[0], PCL711_SIZE); + if (ret) + return ret; /* grab our IRQ */ irq = it->options[1]; @@ -476,7 +465,8 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -EINVAL; } if (irq) { - if (request_irq(irq, pcl711_interrupt, 0, "pcl711", dev)) { + if (request_irq(irq, pcl711_interrupt, 0, dev->board_name, + dev)) { printk(KERN_ERR "unable to allocate irq %u\n", irq); return -EINVAL; } else { @@ -560,14 +550,6 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) return 0; } -static void pcl711_detach(struct comedi_device *dev) -{ - if (dev->irq) - free_irq(dev->irq, dev); - if (dev->iobase) - release_region(dev->iobase, PCL711_SIZE); -} - static const struct pcl711_board boardtypes[] = { { "pcl711", 0, 0, 0, 5, 8, 1, 0, &range_bipolar5 }, { "pcl711b", 1, 0, 0, 5, 8, 1, 7, &range_pcl711b_ai }, @@ -579,7 +561,7 @@ static struct comedi_driver pcl711_driver = { .driver_name = "pcl711", .module = THIS_MODULE, .attach = pcl711_attach, - .detach = pcl711_detach, + .detach = comedi_legacy_detach, .board_name = &boardtypes[0].name, .num_names = ARRAY_SIZE(boardtypes), .offset = sizeof(struct pcl711_board), diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c index 7b3c4293c01..4f033d88eec 100644 --- a/drivers/staging/comedi/drivers/pcl724.c +++ b/drivers/staging/comedi/drivers/pcl724.c @@ -100,28 +100,19 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct pcl724_board *board = comedi_board(dev); struct comedi_subdevice *s; - unsigned long iobase; unsigned int iorange; int ret, i, n_subdevices; #ifdef PCL724_IRQ unsigned int irq; #endif - iobase = it->options[0]; iorange = board->io_range; - if ((board->can_have96) && ((it->options[1] == 1) - || (it->options[1] == 96))) + if ((board->can_have96) && + ((it->options[1] == 1) || (it->options[1] == 96))) iorange = PCL722_96_SIZE; /* PCL-724 in 96 DIO configuration */ - printk(KERN_INFO "comedi%d: pcl724: board=%s, 0x%03lx ", dev->minor, - board->name, iobase); - if (!request_region(iobase, iorange, "pcl724")) { - printk("I/O port conflict\n"); - return -EIO; - } - - dev->iobase = iobase; - - dev->board_name = board->name; + ret = comedi_request_region(dev, it->options[0], iorange); + if (ret) + return ret; #ifdef PCL724_IRQ irq = 0; @@ -134,8 +125,8 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it) "DISABLING IT", irq); irq = 0; /* Bad IRQ */ } else { - if (request_irq - (irq, interrupt_pcl724, 0, "pcl724", dev)) { + if (request_irq(irq, interrupt_pcl724, 0, + dev->board_name, dev)) { printk(KERN_WARNING ", unable to allocate IRQ %u, " "DISABLING IT", irq); @@ -178,19 +169,11 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void pcl724_detach(struct comedi_device *dev) { - const struct pcl724_board *board = comedi_board(dev); - struct comedi_subdevice *s; int i; - for (i = 0; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; - subdev_8255_cleanup(dev, s); - } -#ifdef PCL724_IRQ - if (dev->irq) - free_irq(dev->irq, dev); -#endif - release_region(dev->iobase, board->io_range); + for (i = 0; i < dev->n_subdevices; i++) + comedi_spriv_free(dev, i); + comedi_legacy_detach(dev); } static const struct pcl724_board boardtypes[] = { diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c index 21fbc1ae1e7..6b02f0631b4 100644 --- a/drivers/staging/comedi/drivers/pcl725.c +++ b/drivers/staging/comedi/drivers/pcl725.c @@ -45,18 +45,11 @@ static int pcl725_di_insn(struct comedi_device *dev, struct comedi_subdevice *s, static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_subdevice *s; - unsigned long iobase; int ret; - iobase = it->options[0]; - printk(KERN_INFO "comedi%d: pcl725: 0x%04lx ", dev->minor, iobase); - if (!request_region(iobase, PCL725_SIZE, "pcl725")) { - printk("I/O port conflict\n"); - return -EIO; - } - dev->board_name = "pcl725"; - dev->iobase = iobase; - dev->irq = 0; + ret = comedi_request_region(dev, it->options[0], PCL725_SIZE); + if (ret) + return ret; ret = comedi_alloc_subdevices(dev, 2); if (ret) @@ -85,17 +78,11 @@ static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it) return 0; } -static void pcl725_detach(struct comedi_device *dev) -{ - if (dev->iobase) - release_region(dev->iobase, PCL725_SIZE); -} - static struct comedi_driver pcl725_driver = { .driver_name = "pcl725", .module = THIS_MODULE, .attach = pcl725_attach, - .detach = pcl725_detach, + .detach = comedi_legacy_detach, }; module_comedi_driver(pcl725_driver); diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index 50e01968f19..4aa994393fa 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -90,9 +90,6 @@ Interrupts are not supported. #define PCL727_DI_HI 0 #define PCL727_DI_LO 1 -static const struct comedi_lrange range_4_20mA = { 1, {RANGE_mA(4, 20)} }; -static const struct comedi_lrange range_0_20mA = { 1, {RANGE_mA(0, 20)} }; - static const struct comedi_lrange *const rangelist_726[] = { &range_unipolar5, &range_unipolar10, &range_bipolar5, &range_bipolar10, @@ -228,25 +225,14 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) const struct pcl726_board *board = comedi_board(dev); struct pcl726_private *devpriv; struct comedi_subdevice *s; - unsigned long iobase; - unsigned int iorange; int ret, i; #ifdef ACL6126_IRQ unsigned int irq; #endif - iobase = it->options[0]; - iorange = board->io_range; - printk(KERN_WARNING "comedi%d: pcl726: board=%s, 0x%03lx ", dev->minor, - board->name, iobase); - if (!request_region(iobase, iorange, "pcl726")) { - printk(KERN_WARNING "I/O port conflict\n"); - return -EIO; - } - - dev->iobase = iobase; - - dev->board_name = board->name; + ret = comedi_request_region(dev, it->options[0], board->io_range); + if (ret) + return ret; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) @@ -271,7 +257,7 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) irq = 0; /* Bad IRQ */ } else { if (request_irq(irq, interrupt_pcl818, 0, - "pcl726", dev)) { + dev->board_name, dev)) { printk(KERN_WARNING ", unable to allocate IRQ %d," " DISABLING IT", irq); @@ -349,23 +335,11 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) return 0; } -static void pcl726_detach(struct comedi_device *dev) -{ - const struct pcl726_board *board = comedi_board(dev); - -#ifdef ACL6126_IRQ - if (dev->irq) - free_irq(dev->irq, dev); -#endif - if (dev->iobase) - release_region(dev->iobase, board->io_range); -} - static struct comedi_driver pcl726_driver = { .driver_name = "pcl726", .module = THIS_MODULE, .attach = pcl726_attach, - .detach = pcl726_detach, + .detach = comedi_legacy_detach, .board_name = &boardtypes[0].name, .num_names = ARRAY_SIZE(boardtypes), .offset = sizeof(struct pcl726_board), diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c index e3de4993745..2879db75da3 100644 --- a/drivers/staging/comedi/drivers/pcl730.c +++ b/drivers/staging/comedi/drivers/pcl730.c @@ -64,21 +64,11 @@ static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct pcl730_board *board = comedi_board(dev); struct comedi_subdevice *s; - unsigned long iobase; - unsigned int iorange; int ret; - iobase = it->options[0]; - iorange = board->io_range; - printk(KERN_INFO "comedi%d: pcl730: board=%s 0x%04lx ", dev->minor, - board->name, iobase); - if (!request_region(iobase, iorange, "pcl730")) { - printk("I/O port conflict\n"); - return -EIO; - } - dev->board_name = board->name; - dev->iobase = iobase; - dev->irq = 0; + ret = comedi_request_region(dev, it->options[0], board->io_range); + if (ret) + return ret; ret = comedi_alloc_subdevices(dev, 4); if (ret) @@ -129,14 +119,6 @@ static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it) return 0; } -static void pcl730_detach(struct comedi_device *dev) -{ - const struct pcl730_board *board = comedi_board(dev); - - if (dev->iobase) - release_region(dev->iobase, board->io_range); -} - static const struct pcl730_board boardtypes[] = { { "pcl730", PCL730_SIZE, }, { "iso730", PCL730_SIZE, }, @@ -147,7 +129,7 @@ static struct comedi_driver pcl730_driver = { .driver_name = "pcl730", .module = THIS_MODULE, .attach = pcl730_attach, - .detach = pcl730_detach, + .detach = comedi_legacy_detach, .board_name = &boardtypes[0].name, .num_names = ARRAY_SIZE(boardtypes), .offset = sizeof(struct pcl730_board), diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 560930e6a8e..cd02786702c 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -1041,28 +1041,6 @@ static void start_pacer(struct comedi_device *dev, int mode, /* ============================================================================== */ -static void free_resources(struct comedi_device *dev) -{ - const struct pcl812_board *board = comedi_board(dev); - struct pcl812_private *devpriv = dev->private; - - if (devpriv) { - if (devpriv->dmabuf[0]) - free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]); - if (devpriv->dmabuf[1]) - free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]); - if (devpriv->dma) - free_dma(devpriv->dma); - } - if (dev->irq) - free_irq(dev->irq, dev); - if (dev->iobase) - release_region(dev->iobase, board->io_range); -} - -/* -============================================================================== -*/ static int pcl812_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { @@ -1122,32 +1100,21 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) const struct pcl812_board *board = comedi_board(dev); struct pcl812_private *devpriv; int ret, subdev; - unsigned long iobase; unsigned int irq; unsigned int dma; unsigned long pages; struct comedi_subdevice *s; int n_subdevices; - iobase = it->options[0]; - printk(KERN_INFO "comedi%d: pcl812: board=%s, ioport=0x%03lx", - dev->minor, board->name, iobase); - - if (!request_region(iobase, board->io_range, "pcl812")) { - printk("I/O port conflict\n"); - return -EIO; - } - dev->iobase = iobase; + ret = comedi_request_region(dev, it->options[0], board->io_range); + if (ret) + return ret; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); - if (!devpriv) { - free_resources(dev); + if (!devpriv) return -ENOMEM; - } dev->private = devpriv; - dev->board_name = board->name; - irq = 0; if (board->IRQbits != 0) { /* board support IRQ */ irq = it->options[1]; @@ -1158,8 +1125,8 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) "DISABLING IT", irq); irq = 0; /* Bad IRQ */ } else { - if (request_irq - (irq, interrupt_pcl812, 0, "pcl812", dev)) { + if (request_irq(irq, interrupt_pcl812, 0, + dev->board_name, dev)) { printk (", unable to allocate IRQ %u, " "DISABLING IT", irq); @@ -1183,7 +1150,7 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) printk(", DMA is out of allowed range, FAIL!\n"); return -EINVAL; /* Bad DMA */ } - ret = request_dma(dma, "pcl812"); + ret = request_dma(dma, dev->board_name); if (ret) { printk(KERN_ERR ", unable to allocate DMA %u, FAIL!\n", dma); @@ -1199,7 +1166,6 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) * maybe experiment with try_to_free_pages() * will help .... */ - free_resources(dev); return -EBUSY; /* no buffer :-( */ } devpriv->dmapages[0] = pages; @@ -1208,7 +1174,6 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages); if (!devpriv->dmabuf[1]) { printk(KERN_ERR ", unable to allocate DMA buffer, FAIL!\n"); - free_resources(dev); return -EBUSY; } devpriv->dmapages[1] = pages; @@ -1228,10 +1193,8 @@ no_dma: n_subdevices++; ret = comedi_alloc_subdevices(dev, n_subdevices); - if (ret) { - free_resources(dev); + if (ret) return ret; - } subdev = 0; @@ -1465,7 +1428,17 @@ no_dma: static void pcl812_detach(struct comedi_device *dev) { - free_resources(dev); + struct pcl812_private *devpriv = dev->private; + + if (devpriv) { + if (devpriv->dmabuf[0]) + free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]); + if (devpriv->dmabuf[1]) + free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]); + if (devpriv->dma) + free_dma(devpriv->dma); + } + comedi_legacy_detach(dev); } static const struct pcl812_board boardtypes[] = { diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index f625fdab335..91bd2071f57 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -35,10 +35,10 @@ Configuration Options: #include "../comedidev.h" #include <linux/ioport.h> -#include <linux/mc146818rtc.h> #include <linux/gfp.h> #include <linux/delay.h> #include <linux/io.h> +#include <linux/interrupt.h> #include <asm/dma.h> #include "comedi_fc.h" @@ -82,14 +82,6 @@ Configuration Options: #define INT_TYPE_AI1_DMA 2 #define INT_TYPE_AI3_INT 4 #define INT_TYPE_AI3_DMA 5 -#ifdef unused -#define INT_TYPE_AI1_DMA_RTC 9 -#define INT_TYPE_AI3_DMA_RTC 10 - -/* RTC stuff... */ -#define RTC_IRQ 8 -#define RTC_IO_EXTENT 0x10 -#endif #define MAGIC_DMA_WORD 0x5a5a @@ -126,26 +118,14 @@ struct pcl816_board { int i8254_osc_base; /* 1/frequency of on board oscilator in ns */ }; -#ifdef unused -static int RTC_lock; /* RTC lock */ -static int RTC_timer_lock; /* RTC int lock */ -#endif - struct pcl816_private { unsigned int dma; /* used DMA, 0=don't use DMA */ - int dma_rtc; /* 1=RTC used with DMA, 0=no RTC alloc */ -#ifdef unused - unsigned long rtc_iobase; /* RTC port region */ - unsigned int rtc_iosize; - unsigned int rtc_irq; -#endif unsigned long dmabuf[2]; /* pointers to begin of DMA buffers */ unsigned int dmapages[2]; /* len of DMA buffers in PAGE_SIZEs */ unsigned int hwdmaptr[2]; /* hardware address of DMA buffers */ unsigned int hwdmasize[2]; /* len of DMA buffers in Bytes */ unsigned int dmasamplsize; /* size in samples hwdmasize[0]/2 */ - unsigned int last_top_dma; /* DMA pointer in last RTC int */ int next_dma_buf; /* which DMA buffer will be used next round */ long dma_runs_to_end; /* how many we must permorm DMA transfer to end of record */ unsigned long last_dma_run; /* how many bytes we must transfer on last DMA page */ @@ -154,9 +134,6 @@ struct pcl816_private { unsigned char ai_neverending; /* if=1, then we do neverending record (you must use cancel()) */ int irq_free; /* 1=have allocated IRQ */ int irq_blocked; /* 1=IRQ now uses any subdev */ -#ifdef unused - int rtc_irq_blocked; /* 1=we now do AI with DMA&RTC */ -#endif int irq_was_now_closed; /* when IRQ finish, there's stored int816_mode for last interrupt */ int int816_mode; /* who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma */ struct comedi_subdevice *last_int_sub; /* ptr to subdevice which now finish */ @@ -167,10 +144,6 @@ struct pcl816_private { unsigned int ai_n_chan; /* how many channels per scan */ unsigned int ai_poll_ptr; /* how many sampes transfer poll */ struct comedi_subdevice *sub_ai; /* ptr to AI subdevice */ -#ifdef unused - struct timer_list rtc_irq_timer; /* timer for RTC sanity check */ - unsigned long rtc_freq; /* RTC int freq */ -#endif }; /* @@ -186,9 +159,6 @@ static int pcl816_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s); static void start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1, unsigned int divisor2); -#ifdef unused -static int set_rtc_irq_bit(unsigned char bit); -#endif static int pcl816_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, @@ -718,12 +688,6 @@ static int pcl816_ai_cancel(struct comedi_device *dev, if (devpriv->irq_blocked > 0) { switch (devpriv->int816_mode) { -#ifdef unused - case INT_TYPE_AI1_DMA_RTC: - case INT_TYPE_AI3_DMA_RTC: - set_rtc_irq_bit(0); /* stop RTC */ - del_timer(&devpriv->rtc_irq_timer); -#endif case INT_TYPE_AI1_DMA: case INT_TYPE_AI3_DMA: disable_dma(devpriv->dma); @@ -837,7 +801,7 @@ start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1, /* ============================================================================== - Check if channel list from user is builded correctly + Check if channel list from user is built correctly If it's ok, then return non-zero length of repeated segment of channel list */ static int @@ -939,67 +903,21 @@ setup_channel_list(struct comedi_device *dev, dev->iobase + PCL816_MUX); } -#ifdef unused -/* -============================================================================== - Enable(1)/disable(0) periodic interrupts from RTC -*/ -static int set_rtc_irq_bit(unsigned char bit) -{ - unsigned char val; - unsigned long flags; - - if (bit == 1) { - RTC_timer_lock++; - if (RTC_timer_lock > 1) - return 0; - } else { - RTC_timer_lock--; - if (RTC_timer_lock < 0) - RTC_timer_lock = 0; - if (RTC_timer_lock > 0) - return 0; - } - - save_flags(flags); - cli(); - val = CMOS_READ(RTC_CONTROL); - if (bit) - val |= RTC_PIE; - else - val &= ~RTC_PIE; - - CMOS_WRITE(val, RTC_CONTROL); - CMOS_READ(RTC_INTR_FLAGS); - restore_flags(flags); - return 0; -} -#endif - static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct pcl816_board *board = comedi_board(dev); struct pcl816_private *devpriv; int ret; - unsigned long iobase; unsigned int irq, dma; unsigned long pages; /* int i; */ struct comedi_subdevice *s; - /* claim our I/O space */ - iobase = it->options[0]; - printk("comedi%d: pcl816: board=%s, ioport=0x%03lx", dev->minor, - board->name, iobase); - - if (!request_region(iobase, board->io_range, "pcl816")) { - printk("I/O port conflict\n"); - return -EIO; - } - - dev->iobase = iobase; + ret = comedi_request_region(dev, it->options[0], board->io_range); + if (ret) + return ret; - if (pcl816_check(iobase)) { + if (pcl816_check(dev->iobase)) { printk(KERN_ERR ", I cann't detect board. FAIL!\n"); return -EIO; } @@ -1009,8 +927,6 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -ENOMEM; dev->private = devpriv; - dev->board_name = board->name; - /* grab our IRQ */ irq = 0; if (board->IRQbits != 0) { /* board support IRQ */ @@ -1022,8 +938,8 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) "DISABLING IT", irq); irq = 0; /* Bad IRQ */ } else { - if (request_irq - (irq, interrupt_pcl816, 0, "pcl816", dev)) { + if (request_irq(irq, interrupt_pcl816, 0, + dev->board_name, dev)) { printk (", unable to allocate IRQ %u, " "DISABLING IT", irq); @@ -1044,46 +960,10 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->irq_blocked = 0; /* number of subdevice which use IRQ */ devpriv->int816_mode = 0; /* mode of irq */ -#ifdef unused - /* grab RTC for DMA operations */ - devpriv->dma_rtc = 0; - if (it->options[2] > 0) { /* we want to use DMA */ - if (RTC_lock == 0) { - if (!request_region(RTC_PORT(0), RTC_IO_EXTENT, - "pcl816 (RTC)")) - goto no_rtc; - } - devpriv->rtc_iobase = RTC_PORT(0); - devpriv->rtc_iosize = RTC_IO_EXTENT; - RTC_lock++; -#ifdef UNTESTED_CODE - if (!request_irq(RTC_IRQ, interrupt_pcl816_ai_mode13_dma_rtc, 0, - "pcl816 DMA (RTC)", dev)) { - devpriv->dma_rtc = 1; - devpriv->rtc_irq = RTC_IRQ; - printk(", dma_irq=%u", devpriv->rtc_irq); - } else { - RTC_lock--; - if (RTC_lock == 0) { - if (devpriv->rtc_iobase) - release_region(devpriv->rtc_iobase, - devpriv->rtc_iosize); - } - devpriv->rtc_iobase = 0; - devpriv->rtc_iosize = 0; - } -#else - printk("pcl816: RTC code missing"); -#endif - - } - -no_rtc: -#endif /* grab our DMA */ dma = 0; devpriv->dma = dma; - if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0)) + if (!devpriv->irq_free) goto no_dma; /* if we haven't IRQ, we can't use DMA */ if (board->DMAbits != 0) { /* board support DMA */ @@ -1095,7 +975,7 @@ no_rtc: printk(", DMA is out of allowed range, FAIL!\n"); return -EINVAL; /* Bad DMA */ } - ret = request_dma(dma, "pcl816"); + ret = request_dma(dma, dev->board_name); if (ret) { printk(KERN_ERR ", unable to allocate DMA %u, FAIL!\n", dma); @@ -1120,19 +1000,16 @@ no_rtc: devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE; /* printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */ - if (devpriv->dma_rtc == 0) { /* we must do duble buff :-( */ - devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages); - if (!devpriv->dmabuf[1]) { - printk(KERN_ERR - ", unable to allocate DMA buffer, " - "FAIL!\n"); - return -EBUSY; - } - devpriv->dmapages[1] = pages; - devpriv->hwdmaptr[1] = - virt_to_bus((void *)devpriv->dmabuf[1]); - devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE; + devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages); + if (!devpriv->dmabuf[1]) { + printk(KERN_ERR + ", unable to allocate DMA buffer, " + "FAIL!\n"); + return -EBUSY; } + devpriv->dmapages[1] = pages; + devpriv->hwdmaptr[1] = virt_to_bus((void *)devpriv->dmabuf[1]); + devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE; } no_dma: @@ -1205,7 +1082,6 @@ case COMEDI_SUBD_DO: static void pcl816_detach(struct comedi_device *dev) { - const struct pcl816_board *board = comedi_board(dev); struct pcl816_private *devpriv = dev->private; if (dev->private) { @@ -1217,24 +1093,8 @@ static void pcl816_detach(struct comedi_device *dev) free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]); if (devpriv->dmabuf[1]) free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]); -#ifdef unused - if (devpriv->rtc_irq) - free_irq(devpriv->rtc_irq, dev); - if ((devpriv->dma_rtc) && (RTC_lock == 1)) { - if (devpriv->rtc_iobase) - release_region(devpriv->rtc_iobase, - devpriv->rtc_iosize); - } -#endif } - if (dev->irq) - free_irq(dev->irq, dev); - if (dev->iobase) - release_region(dev->iobase, board->io_range); -#ifdef unused - if (devpriv->dma_rtc) - RTC_lock--; -#endif + comedi_legacy_detach(dev); } static const struct pcl816_board boardtypes[] = { diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index b5af22eb7c3..91cb1bd6717 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -98,15 +98,15 @@ A word or two about DMA. Driver support DMA operations at two ways: */ -#include "../comedidev.h" - #include <linux/ioport.h> -#include <linux/mc146818rtc.h> #include <linux/gfp.h> #include <linux/delay.h> #include <linux/io.h> +#include <linux/interrupt.h> #include <asm/dma.h> +#include "../comedidev.h" + #include "comedi_fc.h" #include "8253.h" @@ -186,15 +186,6 @@ A word or two about DMA. Driver support DMA operations at two ways: #define INT_TYPE_AO3_INT 8 #endif -#ifdef unused -/* RTC stuff... */ -#define INT_TYPE_AI1_DMA_RTC 9 -#define INT_TYPE_AI3_DMA_RTC 10 - -#define RTC_IRQ 8 -#define RTC_IO_EXTENT 0x10 -#endif - #define MAGIC_DMA_WORD 0x5a5a static const struct comedi_lrange range_pcl818h_ai = { 9, { @@ -248,11 +239,6 @@ static const struct comedi_lrange range718_bipolar0_5 = { static const struct comedi_lrange range718_unipolar2 = { 1, {UNI_RANGE(2),} }; static const struct comedi_lrange range718_unipolar1 = { 1, {BIP_RANGE(1),} }; -#ifdef unused -static int RTC_lock; /* RTC lock */ -static int RTC_timer_lock; /* RTC int lock */ -#endif - struct pcl818_board { const char *name; /* driver name */ @@ -277,22 +263,11 @@ struct pcl818_board { struct pcl818_private { unsigned int dma; /* used DMA, 0=don't use DMA */ - int dma_rtc; /* 1=RTC used with DMA, 0=no RTC alloc */ unsigned int io_range; -#ifdef unused - unsigned long rtc_iobase; /* RTC port region */ - unsigned int rtc_iosize; - unsigned int rtc_irq; - struct timer_list rtc_irq_timer; /* timer for RTC sanity check */ - unsigned long rtc_freq; /* RTC int freq */ - int rtc_irq_blocked; /* 1=we now do AI with DMA&RTC */ -#endif unsigned long dmabuf[2]; /* pointers to begin of DMA buffers */ unsigned int dmapages[2]; /* len of DMA buffers in PAGE_SIZEs */ unsigned int hwdmaptr[2]; /* hardware address of DMA buffers */ unsigned int hwdmasize[2]; /* len of DMA buffers in Bytes */ - unsigned int dmasamplsize; /* size in samples hwdmasize[0]/2 */ - unsigned int last_top_dma; /* DMA pointer in last RTC int */ int next_dma_buf; /* which DMA buffer will be used next round */ long dma_runs_to_end; /* how many we must permorm DMA transfer to end of record */ unsigned long last_dma_run; /* how many bytes we must transfer on last DMA page */ @@ -342,12 +317,6 @@ static int pcl818_ai_cancel(struct comedi_device *dev, static void start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1, unsigned int divisor2); -#ifdef unused -static int set_rtc_irq_bit(unsigned char bit); -static void rtc_dropped_irq(unsigned long data); -static int rtc_setfreq_irq(int freq); -#endif - /* ============================================================================== ANALOG INPUT MODE0, 818 cards, slow version @@ -610,113 +579,6 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d) return IRQ_HANDLED; } -#ifdef unused -/* -============================================================================== - analog input dma mode 1 & 3 over RTC, 818 cards -*/ -static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d) -{ - struct comedi_device *dev = d; - struct pcl818_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[0]; - unsigned long tmp; - unsigned int top1, top2, i, bufptr; - long ofs_dats; - short *dmabuf = (short *)devpriv->dmabuf[0]; - - /* outb(2,0x378); */ - switch (devpriv->ai_mode) { - case INT_TYPE_AI1_DMA_RTC: - case INT_TYPE_AI3_DMA_RTC: - tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); - mod_timer(&devpriv->rtc_irq_timer, - jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100); - - for (i = 0; i < 10; i++) { - top1 = get_dma_residue(devpriv->dma); - top2 = get_dma_residue(devpriv->dma); - if (top1 == top2) - break; - } - - if (top1 != top2) - return IRQ_HANDLED; - top1 = devpriv->hwdmasize[0] - top1; /* where is now DMA in buffer */ - top1 >>= 1; - ofs_dats = top1 - devpriv->last_top_dma; /* new samples from last call */ - if (ofs_dats < 0) - ofs_dats = (devpriv->dmasamplsize) + ofs_dats; - if (!ofs_dats) - return IRQ_HANDLED; /* exit=no new samples from last call */ - /* obsluz data */ - i = devpriv->last_top_dma - 1; - i &= (devpriv->dmasamplsize - 1); - - if (dmabuf[i] != MAGIC_DMA_WORD) { /* DMA overflow! */ - comedi_error(dev, "A/D mode1/3 DMA buffer overflow!"); - /* printk("I %d dmabuf[i] %d %d\n",i,dmabuf[i],devpriv->dmasamplsize); */ - pcl818_ai_cancel(dev, s); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; - comedi_event(dev, s); - return IRQ_HANDLED; - } - /* printk("r %ld ",ofs_dats); */ - - bufptr = devpriv->last_top_dma; - - for (i = 0; i < ofs_dats; i++) { - if ((dmabuf[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */ - printk - ("comedi: A/D mode1/3 DMA - channel dropout %d!=%d !\n", - (dmabuf[bufptr] & 0xf), - devpriv-> - act_chanlist[devpriv->act_chanlist_pos]); - pcl818_ai_cancel(dev, s); - s->async->events |= - COMEDI_CB_EOA | COMEDI_CB_ERROR; - comedi_event(dev, s); - return IRQ_HANDLED; - } - - comedi_buf_put(s->async, dmabuf[bufptr++] >> 4); /* get one sample */ - bufptr &= (devpriv->dmasamplsize - 1); - - devpriv->act_chanlist_pos++; - if (devpriv->act_chanlist_pos >= - devpriv->act_chanlist_len) { - devpriv->act_chanlist_pos = 0; - } - s->async->cur_chan++; - if (s->async->cur_chan >= devpriv->ai_n_chan) { - s->async->cur_chan = 0; - devpriv->ai_act_scan--; - } - - if (!devpriv->neverending_ai) - if (devpriv->ai_act_scan == 0) { /* all data sampled */ - pcl818_ai_cancel(dev, s); - s->async->events |= COMEDI_CB_EOA; - comedi_event(dev, s); - /* printk("done int ai13 dma\n"); */ - return IRQ_HANDLED; - } - } - - devpriv->last_top_dma = bufptr; - bufptr--; - bufptr &= (devpriv->dmasamplsize - 1); - dmabuf[bufptr] = MAGIC_DMA_WORD; - comedi_event(dev, s); - /* outb(0,0x378); */ - return IRQ_HANDLED; - } - - /* outb(0,0x378); */ - return IRQ_HANDLED; -} -#endif - /* ============================================================================== analog input interrupt mode 1 & 3, 818HD/HG cards @@ -900,49 +762,6 @@ static void pcl818_ai_mode13dma_int(int mode, struct comedi_device *dev, }; } -#ifdef unused -/* -============================================================================== - ANALOG INPUT MODE 1 or 3 DMA rtc, 818 cards -*/ -static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct pcl818_private *devpriv = dev->private; - unsigned int flags; - short *pole; - - set_dma_mode(devpriv->dma, DMA_MODE_READ | DMA_AUTOINIT); - flags = claim_dma_lock(); - clear_dma_ff(devpriv->dma); - set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]); - set_dma_count(devpriv->dma, devpriv->hwdmasize[0]); - release_dma_lock(flags); - enable_dma(devpriv->dma); - devpriv->last_top_dma = 0; /* devpriv->hwdmasize[0]; */ - pole = (short *)devpriv->dmabuf[0]; - devpriv->dmasamplsize = devpriv->hwdmasize[0] / 2; - pole[devpriv->dmasamplsize - 1] = MAGIC_DMA_WORD; -#ifdef unused - devpriv->rtc_freq = rtc_setfreq_irq(2048); - devpriv->rtc_irq_timer.expires = - jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100; - devpriv->rtc_irq_timer.data = (unsigned long)dev; - devpriv->rtc_irq_timer.function = rtc_dropped_irq; - - add_timer(&devpriv->rtc_irq_timer); -#endif - - if (mode == 1) { - devpriv->int818_mode = INT_TYPE_AI1_DMA_RTC; - outb(0x07 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+DMA */ - } else { - devpriv->int818_mode = INT_TYPE_AI3_DMA_RTC; - outb(0x06 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+DMA */ - }; -} -#endif - /* ============================================================================== ANALOG INPUT MODE 1 or 3, 818 cards @@ -956,7 +775,7 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev, unsigned int seglen; dev_dbg(dev->class_dev, "pcl818_ai_cmd_mode()\n"); - if ((!dev->irq) && (!devpriv->dma_rtc)) { + if (!dev->irq) { comedi_error(dev, "IRQ not defined!"); return -EINVAL; } @@ -1005,15 +824,7 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev, switch (devpriv->dma) { case 1: /* DMA */ case 3: - if (devpriv->dma_rtc == 0) - pcl818_ai_mode13dma_int(mode, dev, s); -#ifdef unused - else - pcl818_ai_mode13dma_rtc(mode, dev, s); -#else - else - return -EINVAL; -#endif + pcl818_ai_mode13dma_int(mode, dev, s); break; case 0: if (!devpriv->usefifo) { @@ -1047,97 +858,10 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev, start_pacer(dev, mode, divisor1, divisor2); -#ifdef unused - switch (devpriv->ai_mode) { - case INT_TYPE_AI1_DMA_RTC: - case INT_TYPE_AI3_DMA_RTC: - set_rtc_irq_bit(1); /* start RTC */ - break; - } -#endif dev_dbg(dev->class_dev, "pcl818_ai_cmd_mode() end\n"); return 0; } -#ifdef unused -/* -============================================================================== - ANALOG OUTPUT MODE 1 or 3, 818 cards -*/ -#ifdef PCL818_MODE13_AO -static int pcl818_ao_mode13(int mode, struct comedi_device *dev, - struct comedi_subdevice *s, comedi_trig *it) -{ - struct pcl818_private *devpriv = dev->private; - int divisor1 = 0, divisor2 = 0; - - if (!dev->irq) { - comedi_error(dev, "IRQ not defined!"); - return -EINVAL; - } - - if (devpriv->irq_blocked) - return -EBUSY; - - start_pacer(dev, -1, 0, 0); /* stop pacer */ - - devpriv->int13_act_scan = it->n; - devpriv->int13_act_chan = 0; - devpriv->irq_blocked = 1; - devpriv->irq_was_now_closed = 0; - devpriv->neverending_ai = 0; - devpriv->act_chanlist_pos = 0; - - if (mode == 1) { - i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1, - &divisor2, &it->trigvar, - TRIG_ROUND_NEAREST); - if (divisor1 == 1) { /* PCL818 crash if any divisor is set to 1 */ - divisor1 = 2; - divisor2 /= 2; - } - if (divisor2 == 1) { - divisor2 = 2; - divisor1 /= 2; - } - } - - outb(0, dev->iobase + PCL818_CNTENABLE); /* enable pacer */ - if (mode == 1) { - devpriv->int818_mode = INT_TYPE_AO1_INT; - outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+IRQ */ - } else { - devpriv->int818_mode = INT_TYPE_AO3_INT; - outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+IRQ */ - }; - - start_pacer(dev, mode, divisor1, divisor2); - - return 0; -} - -/* -============================================================================== - ANALOG OUTPUT MODE 1, 818 cards -*/ -static int pcl818_ao_mode1(struct comedi_device *dev, - struct comedi_subdevice *s, comedi_trig *it) -{ - return pcl818_ao_mode13(1, dev, s, it); -} - -/* -============================================================================== - ANALOG OUTPUT MODE 3, 818 cards -*/ -static int pcl818_ao_mode3(struct comedi_device *dev, - struct comedi_subdevice *s, comedi_trig *it) -{ - return pcl818_ao_mode13(3, dev, s, it); -} -#endif -#endif - /* ============================================================================== Start/stop pacer onboard pacer @@ -1391,12 +1115,6 @@ static int pcl818_ai_cancel(struct comedi_device *dev, devpriv->irq_was_now_closed = 1; switch (devpriv->ai_mode) { -#ifdef unused - case INT_TYPE_AI1_DMA_RTC: - case INT_TYPE_AI3_DMA_RTC: - set_rtc_irq_bit(0); /* stop RTC */ - del_timer(&devpriv->rtc_irq_timer); -#endif case INT_TYPE_AI1_DMA: case INT_TYPE_AI3_DMA: if (devpriv->neverending_ai || @@ -1499,102 +1217,11 @@ static void pcl818_reset(struct comedi_device *dev) } } -#ifdef unused -/* -============================================================================== - Enable(1)/disable(0) periodic interrupts from RTC -*/ -static int set_rtc_irq_bit(unsigned char bit) -{ - unsigned char val; - unsigned long flags; - - if (bit == 1) { - RTC_timer_lock++; - if (RTC_timer_lock > 1) - return 0; - } else { - RTC_timer_lock--; - if (RTC_timer_lock < 0) - RTC_timer_lock = 0; - if (RTC_timer_lock > 0) - return 0; - } - - save_flags(flags); - cli(); - val = CMOS_READ(RTC_CONTROL); - if (bit) - val |= RTC_PIE; - else - val &= ~RTC_PIE; - - CMOS_WRITE(val, RTC_CONTROL); - CMOS_READ(RTC_INTR_FLAGS); - restore_flags(flags); - return 0; -} - -/* -============================================================================== - Restart RTC if something stop it (xntpd every 11 mins or large IDE transfers) -*/ -static void rtc_dropped_irq(unsigned long data) -{ - struct comedi_device *dev = (void *)data; - struct pcl818_private *devpriv = dev->private; - unsigned long flags, tmp; - - switch (devpriv->int818_mode) { - case INT_TYPE_AI1_DMA_RTC: - case INT_TYPE_AI3_DMA_RTC: - mod_timer(&devpriv->rtc_irq_timer, - jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100); - save_flags(flags); - cli(); - tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); /* restart */ - restore_flags(flags); - break; - } -} - -/* -============================================================================== - Set frequency of interrupts from RTC -*/ -static int rtc_setfreq_irq(int freq) -{ - int tmp = 0; - int rtc_freq; - unsigned char val; - unsigned long flags; - - if (freq < 2) - freq = 2; - if (freq > 8192) - freq = 8192; - - while (freq > (1 << tmp)) - tmp++; - - rtc_freq = 1 << tmp; - - save_flags(flags); - cli(); - val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0; - val |= (16 - tmp); - CMOS_WRITE(val, RTC_FREQ_SELECT); - restore_flags(flags); - return rtc_freq; -} -#endif - static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct pcl818_board *board = comedi_board(dev); struct pcl818_private *devpriv; int ret; - unsigned long iobase; unsigned int irq; int dma; unsigned long pages; @@ -1605,31 +1232,21 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -ENOMEM; dev->private = devpriv; - /* claim our I/O space */ - iobase = it->options[0]; - printk - ("comedi%d: pcl818: board=%s, ioport=0x%03lx", - dev->minor, board->name, iobase); devpriv->io_range = board->io_range; if ((board->fifo) && (it->options[2] == -1)) { /* we've board with FIFO and we want to use FIFO */ devpriv->io_range = PCLx1xFIFO_RANGE; devpriv->usefifo = 1; } - if (!request_region(iobase, devpriv->io_range, "pcl818")) { - comedi_error(dev, "I/O port conflict\n"); - return -EIO; - } - - dev->iobase = iobase; + ret = comedi_request_region(dev, it->options[0], devpriv->io_range); + if (ret) + return ret; - if (pcl818_check(iobase)) { + if (pcl818_check(dev->iobase)) { comedi_error(dev, "I can't detect board. FAIL!\n"); return -EIO; } - dev->board_name = board->name; - /* grab our IRQ */ irq = 0; if (board->IRQbits != 0) { /* board support IRQ */ @@ -1641,8 +1258,8 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) irq); irq = 0; /* Bad IRQ */ } else { - if (request_irq - (irq, interrupt_pcl818, 0, "pcl818", dev)) { + if (request_irq(irq, interrupt_pcl818, 0, + dev->board_name, dev)) { printk (", unable to allocate IRQ %u, DISABLING IT", irq); @@ -1663,41 +1280,10 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->irq_blocked = 0; /* number of subdevice which use IRQ */ devpriv->ai_mode = 0; /* mode of irq */ -#ifdef unused - /* grab RTC for DMA operations */ - devpriv->dma_rtc = 0; - if (it->options[2] > 0) { /* we want to use DMA */ - if (RTC_lock == 0) { - if (!request_region(RTC_PORT(0), RTC_IO_EXTENT, - "pcl818 (RTC)")) - goto no_rtc; - } - devpriv->rtc_iobase = RTC_PORT(0); - devpriv->rtc_iosize = RTC_IO_EXTENT; - RTC_lock++; - if (!request_irq(RTC_IRQ, interrupt_pcl818_ai_mode13_dma_rtc, 0, - "pcl818 DMA (RTC)", dev)) { - devpriv->dma_rtc = 1; - devpriv->rtc_irq = RTC_IRQ; - printk(KERN_DEBUG "dma_irq=%u", devpriv->rtc_irq); - } else { - RTC_lock--; - if (RTC_lock == 0) { - if (devpriv->rtc_iobase) - release_region(devpriv->rtc_iobase, - devpriv->rtc_iosize); - } - devpriv->rtc_iobase = 0; - devpriv->rtc_iosize = 0; - } - } - -no_rtc: -#endif /* grab our DMA */ dma = 0; devpriv->dma = dma; - if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0)) + if (!devpriv->irq_free) goto no_dma; /* if we haven't IRQ, we can't use DMA */ if (board->DMAbits != 0) { /* board support DMA */ dma = it->options[2]; @@ -1707,7 +1293,7 @@ no_rtc: printk(KERN_ERR "DMA is out of allowed range, FAIL!\n"); return -EINVAL; /* Bad DMA */ } - ret = request_dma(dma, "pcl818"); + ret = request_dma(dma, dev->board_name); if (ret) return -EBUSY; /* DMA isn't free */ devpriv->dma = dma; @@ -1720,15 +1306,12 @@ no_rtc: devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]); devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE; /* printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */ - if (devpriv->dma_rtc == 0) { /* we must do duble buff :-( */ - devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages); - if (!devpriv->dmabuf[1]) - return -EBUSY; - devpriv->dmapages[1] = pages; - devpriv->hwdmaptr[1] = - virt_to_bus((void *)devpriv->dmabuf[1]); - devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE; - } + devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages); + if (!devpriv->dmabuf[1]) + return -EBUSY; + devpriv->dmapages[1] = pages; + devpriv->hwdmaptr[1] = virt_to_bus((void *)devpriv->dmabuf[1]); + devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE; } no_dma: @@ -1758,7 +1341,7 @@ no_dma: s->range_table = board->ai_range_type; s->cancel = pcl818_ai_cancel; s->insn_read = pcl818_ai_insn_read; - if ((irq) || (devpriv->dma_rtc)) { + if (irq) { dev->read_subdev = s; s->subdev_flags |= SDF_CMD_READ; s->do_cmdtest = ai_cmdtest; @@ -1815,14 +1398,6 @@ no_dma: s->range_table = board->ao_range_type; s->insn_read = pcl818_ao_insn_read; s->insn_write = pcl818_ao_insn_write; -#ifdef unused -#ifdef PCL818_MODE13_AO - if (irq) { - s->trig[1] = pcl818_ao_mode1; - s->trig[3] = pcl818_ao_mode3; - } -#endif -#endif if (board->is_818) { if ((it->options[4] == 1) || (it->options[4] == 10)) s->range_table = &range_unipolar10; @@ -1896,22 +1471,8 @@ static void pcl818_detach(struct comedi_device *dev) free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]); if (devpriv->dmabuf[1]) free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]); -#ifdef unused - if (devpriv->rtc_irq) - free_irq(devpriv->rtc_irq, dev); - if ((devpriv->dma_rtc) && (RTC_lock == 1)) { - if (devpriv->rtc_iobase) - release_region(devpriv->rtc_iobase, - devpriv->rtc_iosize); - } - if (devpriv->dma_rtc) - RTC_lock--; -#endif } - if (dev->irq) - free_irq(dev->irq, dev); - if (dev->iobase) - release_region(dev->iobase, devpriv->io_range); + comedi_legacy_detach(dev); } static const struct pcl818_board boardtypes[] = { diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c index 5f062df1ead..4ef0df30b07 100644 --- a/drivers/staging/comedi/drivers/pcm3724.c +++ b/drivers/staging/comedi/drivers/pcm3724.c @@ -226,29 +226,16 @@ static int pcm3724_attach(struct comedi_device *dev, { struct priv_pcm3724 *priv; struct comedi_subdevice *s; - unsigned long iobase; - unsigned int iorange; int ret, i; - dev->board_name = dev->driver->driver_name; - - iobase = it->options[0]; - iorange = PCM3724_SIZE; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; dev->private = priv; - printk(KERN_INFO "comedi%d: pcm3724: board=%s, 0x%03lx ", dev->minor, - dev->board_name, iobase); - if (!iobase || !request_region(iobase, iorange, "pcm3724")) { - printk("I/O port conflict\n"); - return -EIO; - } - - dev->iobase = iobase; - printk(KERN_INFO "\n"); + ret = comedi_request_region(dev, it->options[0], PCM3724_SIZE); + if (ret) + return ret; ret = comedi_alloc_subdevices(dev, 2); if (ret) @@ -265,17 +252,11 @@ static int pcm3724_attach(struct comedi_device *dev, static void pcm3724_detach(struct comedi_device *dev) { - struct comedi_subdevice *s; int i; - if (dev->subdevices) { - for (i = 0; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; - subdev_8255_cleanup(dev, s); - } - } - if (dev->iobase) - release_region(dev->iobase, PCM3724_SIZE); + for (i = 0; i < dev->n_subdevices; i++) + comedi_spriv_free(dev, i); + comedi_legacy_detach(dev); } static struct comedi_driver pcm3724_driver = { diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c index 067f14d2261..3a3ce2c769a 100644 --- a/drivers/staging/comedi/drivers/pcm3730.c +++ b/drivers/staging/comedi/drivers/pcm3730.c @@ -54,19 +54,11 @@ static int pcm3730_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_subdevice *s; - unsigned long iobase; int ret; - iobase = it->options[0]; - printk(KERN_INFO "comedi%d: pcm3730: 0x%04lx ", dev->minor, iobase); - if (!request_region(iobase, PCM3730_SIZE, "pcm3730")) { - printk("I/O port conflict\n"); - return -EIO; - } - dev->iobase = iobase; - dev->board_name = "pcm3730"; - dev->iobase = dev->iobase; - dev->irq = 0; + ret = comedi_request_region(dev, it->options[0], PCM3730_SIZE); + if (ret) + return ret; ret = comedi_alloc_subdevices(dev, 6); if (ret) @@ -131,17 +123,11 @@ static int pcm3730_attach(struct comedi_device *dev, return 0; } -static void pcm3730_detach(struct comedi_device *dev) -{ - if (dev->iobase) - release_region(dev->iobase, PCM3730_SIZE); -} - static struct comedi_driver pcm3730_driver = { .driver_name = "pcm3730", .module = THIS_MODULE, .attach = pcm3730_attach, - .detach = pcm3730_detach, + .detach = comedi_legacy_detach, }; module_comedi_driver(pcm3730_driver); diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c index 13e84215fac..b7c932e152e 100644 --- a/drivers/staging/comedi/drivers/pcmad.c +++ b/drivers/staging/comedi/drivers/pcmad.c @@ -105,18 +105,12 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct pcmad_board_struct *board = comedi_board(dev); struct pcmad_priv_struct *devpriv; - int ret; struct comedi_subdevice *s; - unsigned long iobase; + int ret; - iobase = it->options[0]; - printk(KERN_INFO "comedi%d: pcmad: 0x%04lx ", dev->minor, iobase); - if (!request_region(iobase, PCMAD_SIZE, "pcmad")) { - printk(KERN_CONT "I/O port conflict\n"); - return -EIO; - } - printk(KERN_CONT "\n"); - dev->iobase = iobase; + ret = comedi_request_region(dev, it->options[0], PCMAD_SIZE); + if (ret) + return ret; ret = comedi_alloc_subdevices(dev, 1); if (ret) @@ -127,8 +121,6 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -ENOMEM; dev->private = devpriv; - dev->board_name = board->name; - s = &dev->subdevices[0]; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | AREF_GROUND; @@ -141,14 +133,6 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it) return 0; } -static void pcmad_detach(struct comedi_device *dev) -{ - if (dev->irq) - free_irq(dev->irq, dev); - if (dev->iobase) - release_region(dev->iobase, PCMAD_SIZE); -} - static const struct pcmad_board_struct pcmad_boards[] = { { .name = "pcmad12", @@ -162,7 +146,7 @@ static struct comedi_driver pcmad_driver = { .driver_name = "pcmad", .module = THIS_MODULE, .attach = pcmad_attach, - .detach = pcmad_detach, + .detach = comedi_legacy_detach, .board_name = &pcmad_boards[0].name, .num_names = ARRAY_SIZE(pcmad_boards), .offset = sizeof(pcmad_boards[0]), diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c index 13f79f49748..61e7fd14a1e 100644 --- a/drivers/staging/comedi/drivers/pcmda12.c +++ b/drivers/staging/comedi/drivers/pcmda12.c @@ -154,21 +154,11 @@ static int pcmda12_attach(struct comedi_device *dev, { struct pcmda12_private *devpriv; struct comedi_subdevice *s; - unsigned long iobase; int ret; - iobase = it->options[0]; - printk(KERN_INFO - "comedi%d: %s: io: %lx %s ", dev->minor, dev->driver->driver_name, - iobase, it->options[1] ? "simultaneous xfer mode enabled" : ""); - - if (!request_region(iobase, IOSIZE, dev->driver->driver_name)) { - printk("I/O port conflict\n"); - return -EIO; - } - dev->iobase = iobase; - - dev->board_name = dev->driver->driver_name; + ret = comedi_request_region(dev, it->options[0], IOSIZE); + if (ret) + return ret; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) @@ -193,22 +183,14 @@ static int pcmda12_attach(struct comedi_device *dev, zero_chans(dev); /* clear out all the registers, basically */ - printk(KERN_INFO "attached\n"); - return 1; } -static void pcmda12_detach(struct comedi_device *dev) -{ - if (dev->iobase) - release_region(dev->iobase, IOSIZE); -} - static struct comedi_driver pcmda12_driver = { .driver_name = "pcmda12", .module = THIS_MODULE, .attach = pcmda12_attach, - .detach = pcmda12_detach, + .detach = comedi_legacy_detach, }; module_comedi_driver(pcmda12_driver); diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 5fa1fe08eb9..5a236cd5b33 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -1034,24 +1034,14 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; int sdev_no, chans_left, n_dio_subdevs, n_subdevs, port, asic, thisasic_chanct = 0; - unsigned long iobase; unsigned int irq[MAX_ASICS]; int ret; - dev->board_name = dev->driver->driver_name; - - iobase = it->options[0]; irq[0] = it->options[1]; - printk(KERN_INFO "comedi%d: %s: io: %lx attaching...\n", dev->minor, - dev->board_name, iobase); - - dev->iobase = iobase; - - if (!iobase || !request_region(iobase, 32, dev->board_name)) { - printk(KERN_ERR "comedi%d: I/O port conflict\n", dev->minor); - return -EIO; - } + ret = comedi_request_region(dev, it->options[0], 32); + if (ret) + return ret; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) @@ -1203,13 +1193,6 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->asics[asic].irq = irq[asic]; } - dev->irq = irq[0]; /* - * grr.. wish comedi dev struct supported - * multiple irqs.. - */ - - printk(KERN_INFO "comedi%d: attached\n", dev->minor); - return 1; } @@ -1218,14 +1201,13 @@ static void pcmmio_detach(struct comedi_device *dev) struct pcmmio_private *devpriv = dev->private; int i; - if (dev->iobase) - release_region(dev->iobase, 32); for (i = 0; i < MAX_ASICS; ++i) { if (devpriv && devpriv->asics[i].irq) free_irq(devpriv->asics[i].irq, dev); } if (devpriv && devpriv->sprivs) kfree(devpriv->sprivs); + comedi_legacy_detach(dev); } static struct comedi_driver pcmmio_driver = { diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 433270ceda4..0c98e26bbba 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -800,27 +800,16 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct pcmuio_private *devpriv; struct comedi_subdevice *s; int sdev_no, chans_left, n_subdevs, port, asic, thisasic_chanct = 0; - unsigned long iobase; unsigned int irq[MAX_ASICS]; int ret; - iobase = it->options[0]; irq[0] = it->options[1]; irq[1] = it->options[2]; - dev_dbg(dev->class_dev, "%s: io: %lx attach\n", - dev->driver->driver_name, iobase); - - dev->iobase = iobase; - - if (!iobase || !request_region(iobase, - board->num_asics * ASIC_IOSIZE, - dev->driver->driver_name)) { - dev_err(dev->class_dev, "I/O port conflict\n"); - return -EIO; - } - - dev->board_name = board->name; + ret = comedi_request_region(dev, it->options[0], + board->num_asics * ASIC_IOSIZE); + if (ret) + return ret; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) @@ -928,9 +917,6 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->asics[asic].irq = irq[asic]; } - dev->irq = irq[0]; /* grr.. wish comedi dev struct supported multiple - irqs.. */ - if (irq[0]) { dev_dbg(dev->class_dev, "irq: %u\n", irq[0]); if (irq[1] && board->num_asics == 2) @@ -946,18 +932,16 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void pcmuio_detach(struct comedi_device *dev) { - const struct pcmuio_board *board = comedi_board(dev); struct pcmuio_private *devpriv = dev->private; int i; - if (dev->iobase) - release_region(dev->iobase, ASIC_IOSIZE * board->num_asics); for (i = 0; i < MAX_ASICS; ++i) { if (devpriv->asics[i].irq) free_irq(devpriv->asics[i].irq, dev); } if (devpriv && devpriv->sprivs) kfree(devpriv->sprivs); + comedi_legacy_detach(dev); } static const struct pcmuio_board pcmuio_boards[] = { diff --git a/drivers/staging/comedi/drivers/plx9052.h b/drivers/staging/comedi/drivers/plx9052.h index 5894739ff42..ff76fbb4b3e 100644 --- a/drivers/staging/comedi/drivers/plx9052.h +++ b/drivers/staging/comedi/drivers/plx9052.h @@ -27,60 +27,58 @@ #define _PLX9052_H_ /* - * PLX PCI9052 INTCSR register. + * INTCSR - Interrupt Control/Status register */ -#define PLX9052_INTCSR 0x4C /* Offset in Local Configuration Registers */ -/* Local Interrupt 1 Enable */ -#define PLX9052_INTCSR_LI1ENAB_MASK 0x0001 -#define PLX9052_INTCSR_LI1ENAB_DISABLED 0x0000 -#define PLX9052_INTCSR_LI1ENAB_ENABLED 0x0001 -/* Local Interrupt 1 Polarity */ -#define PLX9052_INTCSR_LI1POL_MASK 0x0002 -#define PLX9052_INTCSR_LI1POL_LOW 0x0000 -#define PLX9052_INTCSR_LI1POL_HIGH 0x0002 -/* Local Interrupt 1 Status (read-only) */ -#define PLX9052_INTCSR_LI1STAT_MASK 0x0004 -#define PLX9052_INTCSR_LI1STAT_INACTIVE 0x0000 -#define PLX9052_INTCSR_LI1STAT_ACTIVE 0x0004 -/* Local Interrupt 2 Enable */ -#define PLX9052_INTCSR_LI2ENAB_MASK 0x0008 -#define PLX9052_INTCSR_LI2ENAB_DISABLED 0x0000 -#define PLX9052_INTCSR_LI2ENAB_ENABLED 0x0008 -/* Local Interrupt 2 Polarity */ -#define PLX9052_INTCSR_LI2POL_MASK 0x0010 -#define PLX9052_INTCSR_LI2POL_LOW 0x0000 -#define PLX9052_INTCSR_LI2POL_HIGH 0x0010 -/* Local Interrupt 2 Status (read-only) */ -#define PLX9052_INTCSR_LI2STAT_MASK 0x0020 -#define PLX9052_INTCSR_LI2STAT_INACTIVE 0x0000 -#define PLX9052_INTCSR_LI2STAT_ACTIVE 0x0020 -/* PCI Interrupt Enable */ -#define PLX9052_INTCSR_PCIENAB_MASK 0x0040 -#define PLX9052_INTCSR_PCIENAB_DISABLED 0x0000 -#define PLX9052_INTCSR_PCIENAB_ENABLED 0x0040 -/* Software Interrupt */ -#define PLX9052_INTCSR_SOFTINT_MASK 0x0080 -#define PLX9052_INTCSR_SOFTINT_UNASSERTED 0x0000 -#define PLX9052_INTCSR_SOFTINT_ASSERTED 0x0080 -/* Local Interrupt 1 Select Enable */ -#define PLX9052_INTCSR_LI1SEL_MASK 0x0100 -#define PLX9052_INTCSR_LI1SEL_LEVEL 0x0000 -#define PLX9052_INTCSR_LI1SEL_EDGE 0x0100 -/* Local Interrupt 2 Select Enable */ -#define PLX9052_INTCSR_LI2SEL_MASK 0x0200 -#define PLX9052_INTCSR_LI2SEL_LEVEL 0x0000 -#define PLX9052_INTCSR_LI2SEL_EDGE 0x0200 -/* Local Edge Triggerable Interrupt 1 Clear Bit */ -#define PLX9052_INTCSR_LI1CLRINT_MASK 0x0400 -#define PLX9052_INTCSR_LI1CLRINT_UNASSERTED 0x0000 -#define PLX9052_INTCSR_LI1CLRINT_ASSERTED 0x0400 -/* Local Edge Triggerable Interrupt 2 Clear Bit */ -#define PLX9052_INTCSR_LI2CLRINT_MASK 0x0800 -#define PLX9052_INTCSR_LI2CLRINT_UNASSERTED 0x0000 -#define PLX9052_INTCSR_LI2CLRINT_ASSERTED 0x0800 -/* ISA Interface Mode Enable (read-only over PCI bus) */ -#define PLX9052_INTCSR_ISAMODE_MASK 0x1000 -#define PLX9052_INTCSR_ISAMODE_DISABLED 0x0000 -#define PLX9052_INTCSR_ISAMODE_ENABLED 0x1000 +#define PLX9052_INTCSR 0x4c +#define PLX9052_INTCSR_LI1ENAB (1 << 0) /* LI1 enabled */ +#define PLX9052_INTCSR_LI1POL (1 << 1) /* LI1 active high */ +#define PLX9052_INTCSR_LI1STAT (1 << 2) /* LI1 active */ +#define PLX9052_INTCSR_LI2ENAB (1 << 3) /* LI2 enabled */ +#define PLX9052_INTCSR_LI2POL (1 << 4) /* LI2 active high */ +#define PLX9052_INTCSR_LI2STAT (1 << 5) /* LI2 active */ +#define PLX9052_INTCSR_PCIENAB (1 << 6) /* PCIINT enabled */ +#define PLX9052_INTCSR_SOFTINT (1 << 7) /* generate soft int */ +#define PLX9052_INTCSR_LI1SEL (1 << 8) /* LI1 edge */ +#define PLX9052_INTCSR_LI2SEL (1 << 9) /* LI2 edge */ +#define PLX9052_INTCSR_LI1CLRINT (1 << 10) /* LI1 clear int */ +#define PLX9052_INTCSR_LI2CLRINT (1 << 11) /* LI2 clear int */ +#define PLX9052_INTCSR_ISAMODE (1 << 12) /* ISA interface mode */ + +/* + * CNTRL - User I/O, Direct Slave Response, Serial EEPROM, and + * Initialization Control register + */ +#define PLX9052_CNTRL 0x50 +#define PLX9052_CNTRL_WAITO (1 << 0) /* UIO0 or WAITO# select */ +#define PLX9052_CNTRL_UIO0_DIR (1 << 1) /* UIO0 direction */ +#define PLX9052_CNTRL_UIO0_DATA (1 << 2) /* UIO0 data */ +#define PLX9052_CNTRL_LLOCKO (1 << 3) /* UIO1 or LLOCKo# select */ +#define PLX9052_CNTRL_UIO1_DIR (1 << 4) /* UIO1 direction */ +#define PLX9052_CNTRL_UIO1_DATA (1 << 5) /* UIO1 data */ +#define PLX9052_CNTRL_CS2 (1 << 6) /* UIO2 or CS2# select */ +#define PLX9052_CNTRL_UIO2_DIR (1 << 7) /* UIO2 direction */ +#define PLX9052_CNTRL_UIO2_DATA (1 << 8) /* UIO2 data */ +#define PLX9052_CNTRL_CS3 (1 << 9) /* UIO3 or CS3# select */ +#define PLX9052_CNTRL_UIO3_DIR (1 << 10) /* UIO3 direction */ +#define PLX9052_CNTRL_UIO3_DATA (1 << 11) /* UIO3 data */ +#define PLX9052_CNTRL_PCIBAR01 (0 << 12) /* bar 0 (mem) and 1 (I/O) */ +#define PLX9052_CNTRL_PCIBAR0 (1 << 12) /* bar 0 (mem) only */ +#define PLX9052_CNTRL_PCIBAR1 (2 << 12) /* bar 1 (I/O) only */ +#define PLX9052_CNTRL_PCI2_1_FEATURES (1 << 14) /* PCI r2.1 features enabled */ +#define PLX9052_CNTRL_PCI_R_W_FLUSH (1 << 15) /* read w/write flush mode */ +#define PLX9052_CNTRL_PCI_R_NO_FLUSH (1 << 16) /* read no flush mode */ +#define PLX9052_CNTRL_PCI_R_NO_WRITE (1 << 17) /* read no write mode */ +#define PLX9052_CNTRL_PCI_W_RELEASE (1 << 18) /* write release bus mode */ +#define PLX9052_CNTRL_RETRY_CLKS(x) (((x) & 0xf) << 19) /* slave retry clks */ +#define PLX9052_CNTRL_LOCK_ENAB (1 << 23) /* slave LOCK# enable */ +#define PLX9052_CNTRL_EEPROM_MASK (0x1f << 24) /* EEPROM bits */ +#define PLX9052_CNTRL_EEPROM_CLK (1 << 24) /* EEPROM clock */ +#define PLX9052_CNTRL_EEPROM_CS (1 << 25) /* EEPROM chip select */ +#define PLX9052_CNTRL_EEPROM_DOUT (1 << 26) /* EEPROM write bit */ +#define PLX9052_CNTRL_EEPROM_DIN (1 << 27) /* EEPROM read bit */ +#define PLX9052_CNTRL_EEPROM_PRESENT (1 << 28) /* EEPROM present */ +#define PLX9052_CNTRL_RELOAD_CFG (1 << 29) /* reload configuration */ +#define PLX9052_CNTRL_PCI_RESET (1 << 30) /* PCI adapter reset */ +#define PLX9052_CNTRL_MASK_REV (1 << 31) /* mask revision */ #endif /* _PLX9052_H_ */ diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c index d7842c95d98..b55a16baeb1 100644 --- a/drivers/staging/comedi/drivers/poc.c +++ b/drivers/staging/comedi/drivers/poc.c @@ -139,29 +139,11 @@ static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it) const struct boarddef_struct *board = comedi_board(dev); struct poc_private *devpriv; struct comedi_subdevice *s; - unsigned long iobase; - unsigned int iosize; int ret; - iobase = it->options[0]; - printk(KERN_INFO "comedi%d: poc: using %s iobase 0x%lx\n", dev->minor, - board->name, iobase); - - dev->board_name = board->name; - - if (iobase == 0) { - printk(KERN_ERR "io base address required\n"); - return -EINVAL; - } - - iosize = board->iosize; - /* check if io addresses are available */ - if (!request_region(iobase, iosize, "dac02")) { - printk(KERN_ERR "I/O port conflict: failed to allocate ports " - "0x%lx to 0x%lx\n", iobase, iobase + iosize - 1); - return -EIO; - } - dev->iobase = iobase; + ret = comedi_request_region(dev, it->options[0], board->iosize); + if (ret) + return ret; ret = comedi_alloc_subdevices(dev, 1); if (ret) @@ -187,14 +169,6 @@ static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it) return 0; } -static void poc_detach(struct comedi_device *dev) -{ - const struct boarddef_struct *board = comedi_board(dev); - - if (dev->iobase) - release_region(dev->iobase, board->iosize); -} - static const struct boarddef_struct boards[] = { { .name = "dac02", @@ -229,7 +203,7 @@ static struct comedi_driver poc_driver = { .driver_name = "poc", .module = THIS_MODULE, .attach = poc_attach, - .detach = poc_detach, + .detach = comedi_legacy_detach, .board_name = &boards[0].name, .num_names = ARRAY_SIZE(boards), .offset = sizeof(boards[0]), diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index 911eb6b3229..e092ce87722 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -715,8 +715,6 @@ static int daqp_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - dev->board_name = dev->driver->driver_name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 6a5c914fa50..30a17284fac 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -1,105 +1,103 @@ /* - comedi/drivers/rtd520.c - Comedi driver for Real Time Devices (RTD) PCI4520/DM7520 - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2001 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + * comedi/drivers/rtd520.c + * Comedi driver for Real Time Devices (RTD) PCI4520/DM7520 + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2001 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ -/* -Driver: rtd520 -Description: Real Time Devices PCI4520/DM7520 -Author: Dan Christian -Devices: [Real Time Devices] DM7520HR-1 (rtd520), DM7520HR-8, - PCI4520, PCI4520-8 -Status: Works. Only tested on DM7520-8. Not SMP safe. - -Configuration options: - [0] - PCI bus of device (optional) - If bus / slot is not specified, the first available PCI - device will be used. - [1] - PCI slot of device (optional) -*/ /* - Created by Dan Christian, NASA Ames Research Center. - - The PCI4520 is a PCI card. The DM7520 is a PC/104-plus card. - Both have: - 8/16 12 bit ADC with FIFO and channel gain table - 8 bits high speed digital out (for external MUX) (or 8 in or 8 out) - 8 bits high speed digital in with FIFO and interrupt on change (or 8 IO) - 2 12 bit DACs with FIFOs - 2 bits output - 2 bits input - bus mastering DMA - timers: ADC sample, pacer, burst, about, delay, DA1, DA2 - sample counter - 3 user timer/counters (8254) - external interrupt - - The DM7520 has slightly fewer features (fewer gain steps). - - These boards can support external multiplexors and multi-board - synchronization, but this driver doesn't support that. - - Board docs: http://www.rtdusa.com/PC104/DM/analog%20IO/dm7520.htm - Data sheet: http://www.rtdusa.com/pdf/dm7520.pdf - Example source: http://www.rtdusa.com/examples/dm/dm7520.zip - Call them and ask for the register level manual. - PCI chip: http://www.plxtech.com/products/io/pci9080 - - Notes: - This board is memory mapped. There is some IO stuff, but it isn't needed. - - I use a pretty loose naming style within the driver (rtd_blah). - All externally visible names should be rtd520_blah. - I use camelCase for structures (and inside them). - I may also use upper CamelCase for function names (old habit). - - This board is somewhat related to the RTD PCI4400 board. - - I borrowed heavily from the ni_mio_common, ni_atmio16d, mite, and - das1800, since they have the best documented code. Driver - cb_pcidas64.c uses the same DMA controller. - - As far as I can tell, the About interrupt doesn't work if Sample is - also enabled. It turns out that About really isn't needed, since - we always count down samples read. - - There was some timer/counter code, but it didn't follow the right API. - -*/ + * Driver: rtd520 + * Description: Real Time Devices PCI4520/DM7520 + * Devices: (Real Time Devices) DM7520HR-1 [DM7520] + * (Real Time Devices) DM7520HR-8 [DM7520] + * (Real Time Devices) PCI4520 [PCI4520] + * (Real Time Devices) PCI4520-8 [PCI4520] + * Author: Dan Christian + * Status: Works. Only tested on DM7520-8. Not SMP safe. + * + * Configuration options: not applicable, uses PCI auto config + */ /* - driver status: - - Analog-In supports instruction and command mode. - - With DMA, you can sample at 1.15Mhz with 70% idle on a 400Mhz K6-2 - (single channel, 64K read buffer). I get random system lockups when - using DMA with ALI-15xx based systems. I haven't been able to test - any other chipsets. The lockups happen soon after the start of an - acquistion, not in the middle of a long run. - - Without DMA, you can do 620Khz sampling with 20% idle on a 400Mhz K6-2 - (with a 256K read buffer). - - Digital-IO and Analog-Out only support instruction mode. + * Created by Dan Christian, NASA Ames Research Center. + * + * The PCI4520 is a PCI card. The DM7520 is a PC/104-plus card. + * Both have: + * 8/16 12 bit ADC with FIFO and channel gain table + * 8 bits high speed digital out (for external MUX) (or 8 in or 8 out) + * 8 bits high speed digital in with FIFO and interrupt on change (or 8 IO) + * 2 12 bit DACs with FIFOs + * 2 bits output + * 2 bits input + * bus mastering DMA + * timers: ADC sample, pacer, burst, about, delay, DA1, DA2 + * sample counter + * 3 user timer/counters (8254) + * external interrupt + * + * The DM7520 has slightly fewer features (fewer gain steps). + * + * These boards can support external multiplexors and multi-board + * synchronization, but this driver doesn't support that. + * + * Board docs: http://www.rtdusa.com/PC104/DM/analog%20IO/dm7520.htm + * Data sheet: http://www.rtdusa.com/pdf/dm7520.pdf + * Example source: http://www.rtdusa.com/examples/dm/dm7520.zip + * Call them and ask for the register level manual. + * PCI chip: http://www.plxtech.com/products/io/pci9080 + * + * Notes: + * This board is memory mapped. There is some IO stuff, but it isn't needed. + * + * I use a pretty loose naming style within the driver (rtd_blah). + * All externally visible names should be rtd520_blah. + * I use camelCase for structures (and inside them). + * I may also use upper CamelCase for function names (old habit). + * + * This board is somewhat related to the RTD PCI4400 board. + * + * I borrowed heavily from the ni_mio_common, ni_atmio16d, mite, and + * das1800, since they have the best documented code. Driver cb_pcidas64.c + * uses the same DMA controller. + * + * As far as I can tell, the About interrupt doesn't work if Sample is + * also enabled. It turns out that About really isn't needed, since + * we always count down samples read. + * + * There was some timer/counter code, but it didn't follow the right API. + */ -*/ +/* + * driver status: + * + * Analog-In supports instruction and command mode. + * + * With DMA, you can sample at 1.15Mhz with 70% idle on a 400Mhz K6-2 + * (single channel, 64K read buffer). I get random system lockups when + * using DMA with ALI-15xx based systems. I haven't been able to test + * any other chipsets. The lockups happen soon after the start of an + * acquistion, not in the middle of a long run. + * + * Without DMA, you can do 620Khz sampling with 20% idle on a 400Mhz K6-2 + * (with a 256K read buffer). + * + * Digital-IO and Analog-Out only support instruction mode. + */ #include <linux/pci.h> #include <linux/delay.h> @@ -108,9 +106,123 @@ Configuration options: #include "../comedidev.h" #include "comedi_fc.h" -#include "rtd520.h" #include "plx9080.h" +/* + * Local Address Space 0 Offsets + */ +#define LAS0_USER_IO 0x0008 /* User I/O */ +#define LAS0_ADC 0x0010 /* FIFO Status/Software A/D Start */ +#define FS_DAC1_NOT_EMPTY (1 << 0) /* DAC1 FIFO not empty */ +#define FS_DAC1_HEMPTY (1 << 1) /* DAC1 FIFO half empty */ +#define FS_DAC1_NOT_FULL (1 << 2) /* DAC1 FIFO not full */ +#define FS_DAC2_NOT_EMPTY (1 << 4) /* DAC2 FIFO not empty */ +#define FS_DAC2_HEMPTY (1 << 5) /* DAC2 FIFO half empty */ +#define FS_DAC2_NOT_FULL (1 << 6) /* DAC2 FIFO not full */ +#define FS_ADC_NOT_EMPTY (1 << 8) /* ADC FIFO not empty */ +#define FS_ADC_HEMPTY (1 << 9) /* ADC FIFO half empty */ +#define FS_ADC_NOT_FULL (1 << 10) /* ADC FIFO not full */ +#define FS_DIN_NOT_EMPTY (1 << 12) /* DIN FIFO not empty */ +#define FS_DIN_HEMPTY (1 << 13) /* DIN FIFO half empty */ +#define FS_DIN_NOT_FULL (1 << 14) /* DIN FIFO not full */ +#define LAS0_DAC1 0x0014 /* Software D/A1 Update (w) */ +#define LAS0_DAC2 0x0018 /* Software D/A2 Update (w) */ +#define LAS0_DAC 0x0024 /* Software Simultaneous Update (w) */ +#define LAS0_PACER 0x0028 /* Software Pacer Start/Stop */ +#define LAS0_TIMER 0x002c /* Timer Status/HDIN Software Trig. */ +#define LAS0_IT 0x0030 /* Interrupt Status/Enable */ +#define IRQM_ADC_FIFO_WRITE (1 << 0) /* ADC FIFO Write */ +#define IRQM_CGT_RESET (1 << 1) /* Reset CGT */ +#define IRQM_CGT_PAUSE (1 << 3) /* Pause CGT */ +#define IRQM_ADC_ABOUT_CNT (1 << 4) /* About Counter out */ +#define IRQM_ADC_DELAY_CNT (1 << 5) /* Delay Counter out */ +#define IRQM_ADC_SAMPLE_CNT (1 << 6) /* ADC Sample Counter */ +#define IRQM_DAC1_UCNT (1 << 7) /* DAC1 Update Counter */ +#define IRQM_DAC2_UCNT (1 << 8) /* DAC2 Update Counter */ +#define IRQM_UTC1 (1 << 9) /* User TC1 out */ +#define IRQM_UTC1_INV (1 << 10) /* User TC1 out, inverted */ +#define IRQM_UTC2 (1 << 11) /* User TC2 out */ +#define IRQM_DIGITAL_IT (1 << 12) /* Digital Interrupt */ +#define IRQM_EXTERNAL_IT (1 << 13) /* External Interrupt */ +#define IRQM_ETRIG_RISING (1 << 14) /* Ext Trigger rising-edge */ +#define IRQM_ETRIG_FALLING (1 << 15) /* Ext Trigger falling-edge */ +#define LAS0_CLEAR 0x0034 /* Clear/Set Interrupt Clear Mask */ +#define LAS0_OVERRUN 0x0038 /* Pending interrupts/Clear Overrun */ +#define LAS0_PCLK 0x0040 /* Pacer Clock (24bit) */ +#define LAS0_BCLK 0x0044 /* Burst Clock (10bit) */ +#define LAS0_ADC_SCNT 0x0048 /* A/D Sample counter (10bit) */ +#define LAS0_DAC1_UCNT 0x004c /* D/A1 Update counter (10 bit) */ +#define LAS0_DAC2_UCNT 0x0050 /* D/A2 Update counter (10 bit) */ +#define LAS0_DCNT 0x0054 /* Delay counter (16 bit) */ +#define LAS0_ACNT 0x0058 /* About counter (16 bit) */ +#define LAS0_DAC_CLK 0x005c /* DAC clock (16bit) */ +#define LAS0_UTC0 0x0060 /* 8254 TC Counter 0 */ +#define LAS0_UTC1 0x0064 /* 8254 TC Counter 1 */ +#define LAS0_UTC2 0x0068 /* 8254 TC Counter 2 */ +#define LAS0_UTC_CTRL 0x006c /* 8254 TC Control */ +#define LAS0_DIO0 0x0070 /* Digital I/O Port 0 */ +#define LAS0_DIO1 0x0074 /* Digital I/O Port 1 */ +#define LAS0_DIO0_CTRL 0x0078 /* Digital I/O Control */ +#define LAS0_DIO_STATUS 0x007c /* Digital I/O Status */ +#define LAS0_BOARD_RESET 0x0100 /* Board reset */ +#define LAS0_DMA0_SRC 0x0104 /* DMA 0 Sources select */ +#define LAS0_DMA1_SRC 0x0108 /* DMA 1 Sources select */ +#define LAS0_ADC_CONVERSION 0x010c /* A/D Conversion Signal select */ +#define LAS0_BURST_START 0x0110 /* Burst Clock Start Trigger select */ +#define LAS0_PACER_START 0x0114 /* Pacer Clock Start Trigger select */ +#define LAS0_PACER_STOP 0x0118 /* Pacer Clock Stop Trigger select */ +#define LAS0_ACNT_STOP_ENABLE 0x011c /* About Counter Stop Enable */ +#define LAS0_PACER_REPEAT 0x0120 /* Pacer Start Trigger Mode select */ +#define LAS0_DIN_START 0x0124 /* HiSpd DI Sampling Signal select */ +#define LAS0_DIN_FIFO_CLEAR 0x0128 /* Digital Input FIFO Clear */ +#define LAS0_ADC_FIFO_CLEAR 0x012c /* A/D FIFO Clear */ +#define LAS0_CGT_WRITE 0x0130 /* Channel Gain Table Write */ +#define LAS0_CGL_WRITE 0x0134 /* Channel Gain Latch Write */ +#define LAS0_CG_DATA 0x0138 /* Digital Table Write */ +#define LAS0_CGT_ENABLE 0x013c /* Channel Gain Table Enable */ +#define LAS0_CG_ENABLE 0x0140 /* Digital Table Enable */ +#define LAS0_CGT_PAUSE 0x0144 /* Table Pause Enable */ +#define LAS0_CGT_RESET 0x0148 /* Reset Channel Gain Table */ +#define LAS0_CGT_CLEAR 0x014c /* Clear Channel Gain Table */ +#define LAS0_DAC1_CTRL 0x0150 /* D/A1 output type/range */ +#define LAS0_DAC1_SRC 0x0154 /* D/A1 update source */ +#define LAS0_DAC1_CYCLE 0x0158 /* D/A1 cycle mode */ +#define LAS0_DAC1_RESET 0x015c /* D/A1 FIFO reset */ +#define LAS0_DAC1_FIFO_CLEAR 0x0160 /* D/A1 FIFO clear */ +#define LAS0_DAC2_CTRL 0x0164 /* D/A2 output type/range */ +#define LAS0_DAC2_SRC 0x0168 /* D/A2 update source */ +#define LAS0_DAC2_CYCLE 0x016c /* D/A2 cycle mode */ +#define LAS0_DAC2_RESET 0x0170 /* D/A2 FIFO reset */ +#define LAS0_DAC2_FIFO_CLEAR 0x0174 /* D/A2 FIFO clear */ +#define LAS0_ADC_SCNT_SRC 0x0178 /* A/D Sample Counter Source select */ +#define LAS0_PACER_SELECT 0x0180 /* Pacer Clock select */ +#define LAS0_SBUS0_SRC 0x0184 /* SyncBus 0 Source select */ +#define LAS0_SBUS0_ENABLE 0x0188 /* SyncBus 0 enable */ +#define LAS0_SBUS1_SRC 0x018c /* SyncBus 1 Source select */ +#define LAS0_SBUS1_ENABLE 0x0190 /* SyncBus 1 enable */ +#define LAS0_SBUS2_SRC 0x0198 /* SyncBus 2 Source select */ +#define LAS0_SBUS2_ENABLE 0x019c /* SyncBus 2 enable */ +#define LAS0_ETRG_POLARITY 0x01a4 /* Ext. Trigger polarity select */ +#define LAS0_EINT_POLARITY 0x01a8 /* Ext. Interrupt polarity select */ +#define LAS0_UTC0_CLOCK 0x01ac /* UTC0 Clock select */ +#define LAS0_UTC0_GATE 0x01b0 /* UTC0 Gate select */ +#define LAS0_UTC1_CLOCK 0x01b4 /* UTC1 Clock select */ +#define LAS0_UTC1_GATE 0x01b8 /* UTC1 Gate select */ +#define LAS0_UTC2_CLOCK 0x01bc /* UTC2 Clock select */ +#define LAS0_UTC2_GATE 0x01c0 /* UTC2 Gate select */ +#define LAS0_UOUT0_SELECT 0x01c4 /* User Output 0 source select */ +#define LAS0_UOUT1_SELECT 0x01c8 /* User Output 1 source select */ +#define LAS0_DMA0_RESET 0x01cc /* DMA0 Request state machine reset */ +#define LAS0_DMA1_RESET 0x01d0 /* DMA1 Request state machine reset */ + +/* + * Local Address Space 1 Offsets + */ +#define LAS1_ADC_FIFO 0x0000 /* A/D FIFO (16bit) */ +#define LAS1_HDIO_FIFO 0x0004 /* HiSpd DI FIFO (16bit) */ +#define LAS1_DAC1_FIFO 0x0008 /* D/A1 FIFO (16bit) */ +#define LAS1_DAC2_FIFO 0x000c /* D/A2 FIFO (16bit) */ + /*====================================================================== Driver specific stuff (tunable) ======================================================================*/ @@ -249,61 +361,48 @@ static const struct comedi_lrange rtd_ao_range = { } }; -struct rtdBoard { +enum rtd_boardid { + BOARD_DM7520, + BOARD_PCI4520, +}; + +struct rtd_boardinfo { const char *name; - int device_id; - int range10Start; /* start of +-10V range */ - int rangeUniStart; /* start of +10V range */ + int range_bip10; /* start of +-10V range */ + int range_uni10; /* start of +10V range */ const struct comedi_lrange *ai_range; }; -static const struct rtdBoard rtd520Boards[] = { - { +static const struct rtd_boardinfo rtd520Boards[] = { + [BOARD_DM7520] = { .name = "DM7520", - .device_id = 0x7520, - .range10Start = 6, - .rangeUniStart = 12, + .range_bip10 = 6, + .range_uni10 = 12, .ai_range = &rtd_ai_7520_range, - }, { + }, + [BOARD_PCI4520] = { .name = "PCI4520", - .device_id = 0x4520, - .range10Start = 8, - .rangeUniStart = 16, + .range_bip10 = 8, + .range_uni10 = 16, .ai_range = &rtd_ai_4520_range, }, }; -/* - This structure is for data unique to this hardware driver. - This is also unique for each board in the system. -*/ -struct rtdPrivate { +struct rtd_private { /* memory mapped board structures */ void __iomem *las0; void __iomem *las1; void __iomem *lcfg; - long aiCount; /* total transfer size (samples) */ - int transCount; /* # to transfer data. 0->1/2FIFO */ + long ai_count; /* total transfer size (samples) */ + int xfer_count; /* # to transfer data. 0->1/2FIFO */ int flags; /* flag event modes */ - /* channel list info */ - /* chanBipolar tracks whether a channel is bipolar (and needs +2048) */ - unsigned char chanBipolar[RTD_MAX_CHANLIST / 8]; /* bit array */ + unsigned char chan_is_bipolar[RTD_MAX_CHANLIST / 8]; /* bit array */ - /* read back data */ - unsigned int aoValue[2]; /* Used for AO read back */ + unsigned int ao_readback[2]; - /* timer gate (when enabled) */ - u8 utcGate[4]; /* 1 extra allows simple range check */ - - /* shadow registers affect other registers, but can't be read back */ - /* The macros below update these on writes */ - u16 intMask; /* interrupt mask */ - u16 intClearMask; /* interrupt clear mask */ - u8 utcCtrl[4]; /* crtl mode for 3 utc + read back */ - u8 dioStatus; /* could be read back (dio0Ctrl) */ - unsigned fifoLen; + unsigned fifosz; }; /* bit defines for "flags" */ @@ -365,36 +464,34 @@ static int rtd_ns_to_timer(unsigned int *ns, int round_mode) /* Convert a single comedi channel-gain entry to a RTD520 table entry */ -static unsigned short rtdConvertChanGain(struct comedi_device *dev, - unsigned int comediChan, int chanIndex) -{ /* index in channel list */ - const struct rtdBoard *thisboard = comedi_board(dev); - struct rtdPrivate *devpriv = dev->private; - unsigned int chan, range, aref; +static unsigned short rtd_convert_chan_gain(struct comedi_device *dev, + unsigned int chanspec, int index) +{ + const struct rtd_boardinfo *board = comedi_board(dev); + struct rtd_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(chanspec); + unsigned int range = CR_RANGE(chanspec); + unsigned int aref = CR_AREF(chanspec); unsigned short r = 0; - chan = CR_CHAN(comediChan); - range = CR_RANGE(comediChan); - aref = CR_AREF(comediChan); - r |= chan & 0xf; /* Note: we also setup the channel list bipolar flag array */ - if (range < thisboard->range10Start) { + if (range < board->range_bip10) { /* +-5 range */ r |= 0x000; r |= (range & 0x7) << 4; - CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex); - } else if (range < thisboard->rangeUniStart) { + CHAN_ARRAY_SET(devpriv->chan_is_bipolar, index); + } else if (range < board->range_uni10) { /* +-10 range */ r |= 0x100; - r |= ((range - thisboard->range10Start) & 0x7) << 4; - CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex); + r |= ((range - board->range_bip10) & 0x7) << 4; + CHAN_ARRAY_SET(devpriv->chan_is_bipolar, index); } else { /* +10 range */ r |= 0x200; - r |= ((range - thisboard->rangeUniStart) & 0x7) << 4; - CHAN_ARRAY_CLEAR(devpriv->chanBipolar, chanIndex); + r |= ((range - board->range_uni10) & 0x7) << 4; + CHAN_ARRAY_CLEAR(devpriv->chan_is_bipolar, index); } switch (aref) { @@ -423,7 +520,7 @@ static unsigned short rtdConvertChanGain(struct comedi_device *dev, static void rtd_load_channelgain_list(struct comedi_device *dev, unsigned int n_chan, unsigned int *list) { - struct rtdPrivate *devpriv = dev->private; + struct rtd_private *devpriv = dev->private; if (n_chan > 1) { /* setup channel gain table */ int ii; @@ -431,12 +528,12 @@ static void rtd_load_channelgain_list(struct comedi_device *dev, writel(0, devpriv->las0 + LAS0_CGT_CLEAR); writel(1, devpriv->las0 + LAS0_CGT_ENABLE); for (ii = 0; ii < n_chan; ii++) { - writel(rtdConvertChanGain(dev, list[ii], ii), + writel(rtd_convert_chan_gain(dev, list[ii], ii), devpriv->las0 + LAS0_CGT_WRITE); } } else { /* just use the channel gain latch */ writel(0, devpriv->las0 + LAS0_CGT_ENABLE); - writel(rtdConvertChanGain(dev, list[0], 0), + writel(rtd_convert_chan_gain(dev, list[0], 0), devpriv->las0 + LAS0_CGL_WRITE); } } @@ -445,7 +542,7 @@ 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 rtdPrivate *devpriv = dev->private; + struct rtd_private *devpriv = dev->private; unsigned int chanspec = CR_PACK(0, 0, AREF_GROUND); unsigned i; static const unsigned limit = 0x2000; @@ -493,7 +590,7 @@ static int rtd_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct rtdPrivate *devpriv = dev->private; + struct rtd_private *devpriv = dev->private; int n, ii; int stat; @@ -525,7 +622,7 @@ static int rtd_ai_rinsn(struct comedi_device *dev, d = readw(devpriv->las1 + LAS1_ADC_FIFO); /*printk ("rtd520: Got 0x%x after %d usec\n", d, ii+1); */ d = d >> 3; /* low 3 bits are marker lines */ - if (CHAN_ARRAY_TEST(devpriv->chanBipolar, 0)) + if (CHAN_ARRAY_TEST(devpriv->chan_is_bipolar, 0)) /* convert to comedi unsigned data */ data[n] = d + 2048; else @@ -545,21 +642,22 @@ static int rtd_ai_rinsn(struct comedi_device *dev, static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s, int count) { - struct rtdPrivate *devpriv = dev->private; + struct rtd_private *devpriv = dev->private; int ii; for (ii = 0; ii < count; ii++) { short sample; s16 d; - if (0 == devpriv->aiCount) { /* done */ + if (0 == devpriv->ai_count) { /* done */ d = readw(devpriv->las1 + LAS1_ADC_FIFO); continue; } d = readw(devpriv->las1 + LAS1_ADC_FIFO); d = d >> 3; /* low 3 bits are marker lines */ - if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) { + if (CHAN_ARRAY_TEST(devpriv->chan_is_bipolar, + s->async->cur_chan)) { /* convert to comedi unsigned data */ sample = d + 2048; } else @@ -568,8 +666,8 @@ static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s, if (!comedi_buf_put(s->async, sample)) return -1; - if (devpriv->aiCount > 0) /* < 0, means read forever */ - devpriv->aiCount--; + if (devpriv->ai_count > 0) /* < 0, means read forever */ + devpriv->ai_count--; } return 0; } @@ -579,18 +677,19 @@ static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s, */ static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s) { - struct rtdPrivate *devpriv = dev->private; + struct rtd_private *devpriv = dev->private; while (readl(devpriv->las0 + LAS0_ADC) & FS_ADC_NOT_EMPTY) { short sample; s16 d = readw(devpriv->las1 + LAS1_ADC_FIFO); - if (0 == devpriv->aiCount) { /* done */ + if (0 == devpriv->ai_count) { /* done */ continue; /* read rest */ } d = d >> 3; /* low 3 bits are marker lines */ - if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) { + if (CHAN_ARRAY_TEST(devpriv->chan_is_bipolar, + s->async->cur_chan)) { /* convert to comedi unsigned data */ sample = d + 2048; } else @@ -599,8 +698,8 @@ static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s) if (!comedi_buf_put(s->async, sample)) return -1; - if (devpriv->aiCount > 0) /* < 0, means read forever */ - devpriv->aiCount--; + if (devpriv->ai_count > 0) /* < 0, means read forever */ + devpriv->ai_count--; } return 0; } @@ -611,23 +710,22 @@ static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s) This is a "slow handler"; other interrupts may be active. The data conversion may someday happen in a "bottom half". */ -static irqreturn_t rtd_interrupt(int irq, /* interrupt number (ignored) */ - void *d) -{ /* our data *//* cpu context (ignored) */ +static irqreturn_t rtd_interrupt(int irq, void *d) +{ struct comedi_device *dev = d; struct comedi_subdevice *s = &dev->subdevices[0]; - struct rtdPrivate *devpriv = dev->private; + struct rtd_private *devpriv = dev->private; u32 overrun; u16 status; - u16 fifoStatus; + u16 fifo_status; if (!dev->attached) return IRQ_NONE; - fifoStatus = readl(devpriv->las0 + LAS0_ADC); + fifo_status = readl(devpriv->las0 + LAS0_ADC); /* check for FIFO full, this automatically halts the ADC! */ - if (!(fifoStatus & FS_ADC_NOT_FULL)) /* 0 -> full */ - goto abortTransfer; + if (!(fifo_status & FS_ADC_NOT_FULL)) /* 0 -> full */ + goto xfer_abort; status = readw(devpriv->las0 + LAS0_IT); /* if interrupt was not caused by our board, or handled above */ @@ -641,23 +739,23 @@ static irqreturn_t rtd_interrupt(int irq, /* interrupt number (ignored) */ * finished, we must handle the possibility that there is * no data here */ - if (!(fifoStatus & FS_ADC_HEMPTY)) { + if (!(fifo_status & FS_ADC_HEMPTY)) { /* FIFO half full */ - if (ai_read_n(dev, s, devpriv->fifoLen / 2) < 0) - goto abortTransfer; + if (ai_read_n(dev, s, devpriv->fifosz / 2) < 0) + goto xfer_abort; - if (0 == devpriv->aiCount) - goto transferDone; + if (0 == devpriv->ai_count) + goto xfer_done; comedi_event(dev, s); - } else if (devpriv->transCount > 0) { - if (fifoStatus & FS_ADC_NOT_EMPTY) { + } else if (devpriv->xfer_count > 0) { + if (fifo_status & FS_ADC_NOT_EMPTY) { /* FIFO not empty */ - if (ai_read_n(dev, s, devpriv->transCount) < 0) - goto abortTransfer; + if (ai_read_n(dev, s, devpriv->xfer_count) < 0) + goto xfer_abort; - if (0 == devpriv->aiCount) - goto transferDone; + if (0 == devpriv->ai_count) + goto xfer_done; comedi_event(dev, s); } @@ -666,30 +764,28 @@ static irqreturn_t rtd_interrupt(int irq, /* interrupt number (ignored) */ overrun = readl(devpriv->las0 + LAS0_OVERRUN) & 0xffff; if (overrun) - goto abortTransfer; + goto xfer_abort; /* clear the interrupt */ - devpriv->intClearMask = status; - writew(devpriv->intClearMask, devpriv->las0 + LAS0_CLEAR); + writew(status, devpriv->las0 + LAS0_CLEAR); readw(devpriv->las0 + LAS0_CLEAR); return IRQ_HANDLED; -abortTransfer: +xfer_abort: writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR); s->async->events |= COMEDI_CB_ERROR; - devpriv->aiCount = 0; /* stop and don't transfer any more */ - /* fall into transferDone */ + devpriv->ai_count = 0; /* stop and don't transfer any more */ + /* fall into xfer_done */ -transferDone: +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); - devpriv->intMask = 0; - writew(devpriv->intMask, devpriv->las0 + LAS0_IT); + writew(0, devpriv->las0 + LAS0_IT); - if (devpriv->aiCount > 0) { /* there shouldn't be anything left */ - fifoStatus = readl(devpriv->las0 + LAS0_ADC); + if (devpriv->ai_count > 0) { /* there shouldn't be anything left */ + fifo_status = readl(devpriv->las0 + LAS0_ADC); ai_read_dregs(dev, s); /* read anything left in FIFO */ } @@ -698,11 +794,10 @@ transferDone: /* clear the interrupt */ status = readw(devpriv->las0 + LAS0_IT); - devpriv->intClearMask = status; - writew(devpriv->intClearMask, devpriv->las0 + LAS0_CLEAR); + writew(status, devpriv->las0 + LAS0_CLEAR); readw(devpriv->las0 + LAS0_CLEAR); - fifoStatus = readl(devpriv->las0 + LAS0_ADC); + fifo_status = readl(devpriv->las0 + LAS0_ADC); overrun = readl(devpriv->las0 + LAS0_OVERRUN) & 0xffff; return IRQ_HANDLED; @@ -875,7 +970,7 @@ static int rtd_ai_cmdtest(struct comedi_device *dev, */ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - struct rtdPrivate *devpriv = dev->private; + struct rtd_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; int timer; @@ -884,8 +979,7 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) writel(0, devpriv->las0 + LAS0_PACER_STOP); writel(0, devpriv->las0 + LAS0_PACER); /* stop pacer */ writel(0, devpriv->las0 + LAS0_ADC_CONVERSION); - devpriv->intMask = 0; - writew(devpriv->intMask, devpriv->las0 + LAS0_IT); + writew(0, devpriv->las0 + LAS0_IT); writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR); writel(0, devpriv->las0 + LAS0_OVERRUN); @@ -907,7 +1001,7 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* ADC conversion trigger source: PACER */ writel(1, devpriv->las0 + LAS0_ADC_CONVERSION); } - writel((devpriv->fifoLen / 2 - 1) & 0xffff, devpriv->las0 + LAS0_ACNT); + writel((devpriv->fifosz / 2 - 1) & 0xffff, devpriv->las0 + LAS0_ACNT); if (TRIG_TIMER == cmd->scan_begin_src) { /* scan_begin_arg is in nanoseconds */ @@ -918,37 +1012,36 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) * the application is responsible for doing the * right thing */ - devpriv->transCount = cmd->chanlist_len; + devpriv->xfer_count = cmd->chanlist_len; devpriv->flags |= SEND_EOS; } else { /* arrange to transfer data periodically */ - devpriv->transCount - = + devpriv->xfer_count = (TRANS_TARGET_PERIOD * cmd->chanlist_len) / cmd->scan_begin_arg; - if (devpriv->transCount < cmd->chanlist_len) { + if (devpriv->xfer_count < cmd->chanlist_len) { /* transfer after each scan (and avoid 0) */ - devpriv->transCount = cmd->chanlist_len; + devpriv->xfer_count = cmd->chanlist_len; } else { /* make a multiple of scan length */ - devpriv->transCount = - (devpriv->transCount + + devpriv->xfer_count = + (devpriv->xfer_count + cmd->chanlist_len - 1) / cmd->chanlist_len; - devpriv->transCount *= cmd->chanlist_len; + devpriv->xfer_count *= cmd->chanlist_len; } devpriv->flags |= SEND_EOS; } - if (devpriv->transCount >= (devpriv->fifoLen / 2)) { + if (devpriv->xfer_count >= (devpriv->fifosz / 2)) { /* out of counter range, use 1/2 fifo instead */ - devpriv->transCount = 0; + devpriv->xfer_count = 0; devpriv->flags &= ~SEND_EOS; } else { /* interrupt for each transfer */ - writel((devpriv->transCount - 1) & 0xffff, + writel((devpriv->xfer_count - 1) & 0xffff, devpriv->las0 + LAS0_ACNT); } } else { /* unknown timing, just use 1/2 FIFO */ - devpriv->transCount = 0; + devpriv->xfer_count = 0; devpriv->flags &= ~SEND_EOS; } /* pacer clock source: INTERNAL 8MHz */ @@ -961,15 +1054,15 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* First, setup when to stop */ switch (cmd->stop_src) { case TRIG_COUNT: /* stop after N scans */ - devpriv->aiCount = cmd->stop_arg * cmd->chanlist_len; - if ((devpriv->transCount > 0) - && (devpriv->transCount > devpriv->aiCount)) { - devpriv->transCount = devpriv->aiCount; + devpriv->ai_count = cmd->stop_arg * cmd->chanlist_len; + if ((devpriv->xfer_count > 0) + && (devpriv->xfer_count > devpriv->ai_count)) { + devpriv->xfer_count = devpriv->ai_count; } break; case TRIG_NONE: /* stop when cancel is called */ - devpriv->aiCount = -1; /* read forever */ + devpriv->ai_count = -1; /* read forever */ break; } @@ -1011,17 +1104,14 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* This doesn't seem to work. There is no way to clear an interrupt that the priority controller has queued! */ - devpriv->intClearMask = ~0; - writew(devpriv->intClearMask, devpriv->las0 + LAS0_CLEAR); + writew(~0, devpriv->las0 + LAS0_CLEAR); readw(devpriv->las0 + LAS0_CLEAR); /* TODO: allow multiple interrupt sources */ - if (devpriv->transCount > 0) { /* transfer every N samples */ - devpriv->intMask = IRQM_ADC_ABOUT_CNT; - writew(devpriv->intMask, devpriv->las0 + LAS0_IT); + if (devpriv->xfer_count > 0) { /* transfer every N samples */ + writew(IRQM_ADC_ABOUT_CNT, devpriv->las0 + LAS0_IT); } else { /* 1/2 FIFO transfers */ - devpriv->intMask = IRQM_ADC_ABOUT_CNT; - writew(devpriv->intMask, devpriv->las0 + LAS0_IT); + writew(IRQM_ADC_ABOUT_CNT, devpriv->las0 + LAS0_IT); } /* BUG: start_src is ASSUMED to be TRIG_NOW */ @@ -1035,7 +1125,7 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) */ static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - struct rtdPrivate *devpriv = dev->private; + struct rtd_private *devpriv = dev->private; u32 overrun; u16 status; @@ -1043,9 +1133,8 @@ static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) writel(0, devpriv->las0 + LAS0_PACER_STOP); writel(0, devpriv->las0 + LAS0_PACER); /* stop pacer */ writel(0, devpriv->las0 + LAS0_ADC_CONVERSION); - devpriv->intMask = 0; - writew(devpriv->intMask, devpriv->las0 + LAS0_IT); - devpriv->aiCount = 0; /* stop and don't transfer any more */ + writew(0, devpriv->las0 + 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; return 0; @@ -1058,7 +1147,7 @@ static int rtd_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct rtdPrivate *devpriv = dev->private; + struct rtd_private *devpriv = dev->private; int i; int chan = CR_CHAN(insn->chanspec); int range = CR_RANGE(insn->chanspec); @@ -1090,7 +1179,7 @@ static int rtd_ao_winsn(struct comedi_device *dev, writew(0, devpriv->las0 + ((chan == 0) ? LAS0_DAC1 : LAS0_DAC2)); - devpriv->aoValue[chan] = data[i]; /* save for read back */ + devpriv->ao_readback[chan] = data[i]; for (ii = 0; ii < RTD_DAC_TIMEOUT; ++ii) { stat = readl(devpriv->las0 + LAS0_ADC); @@ -1114,73 +1203,56 @@ static int rtd_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct rtdPrivate *devpriv = dev->private; + struct rtd_private *devpriv = dev->private; int i; int chan = CR_CHAN(insn->chanspec); for (i = 0; i < insn->n; i++) - data[i] = devpriv->aoValue[chan]; + data[i] = devpriv->ao_readback[chan]; return i; } -/* - Write a masked set of bits and the read back the port. - We track what the bits should be (i.e. we don't read the port first). - - DIO devices are slightly special. Although it is possible to - * implement the insn_read/insn_write interface, it is much more - * useful to applications if you implement the insn_bits interface. - * This allows packed reading/writing of the DIO channels. The - * comedi core can convert between insn_bits and insn_read/write - */ static int rtd_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) { - struct rtdPrivate *devpriv = dev->private; + struct rtd_private *devpriv = dev->private; + unsigned int mask = data[0]; + unsigned int bits = data[1]; - /* The insn data is a mask in data[0] and the new data - * in data[1], each channel cooresponding to a bit. */ - if (data[0]) { - s->state &= ~data[0]; - s->state |= data[0] & data[1]; + if (mask) { + s->state &= ~mask; + s->state |= (bits & mask); - /* Write out the new digital output lines */ writew(s->state & 0xff, devpriv->las0 + LAS0_DIO0); } - /* on return, data[1] contains the value of the digital - * input lines. */ + data[1] = readw(devpriv->las0 + LAS0_DIO0) & 0xff; return insn->n; } -/* - Configure one bit on a IO port as Input or Output (hence the name :-). -*/ static int rtd_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 rtdPrivate *devpriv = dev->private; - int chan = CR_CHAN(insn->chanspec); + struct rtd_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int mask = 1 << chan; - /* The input or output configuration of each digital line is - * configured by a special insn_config instruction. chanspec - * contains the channel to be changed, and data[0] contains the - * value COMEDI_INPUT or COMEDI_OUTPUT. */ switch (data[0]) { case INSN_CONFIG_DIO_OUTPUT: - s->io_bits |= 1 << chan; /* 1 means Out */ + s->io_bits |= mask; break; case INSN_CONFIG_DIO_INPUT: - s->io_bits &= ~(1 << chan); + s->io_bits &= ~mask; break; case INSN_CONFIG_DIO_QUERY: - data[1] = - (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; + data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT; return insn->n; break; default: @@ -1188,30 +1260,30 @@ static int rtd_dio_insn_config(struct comedi_device *dev, } /* TODO support digital match interrupts and strobes */ - devpriv->dioStatus = 0x01; /* set direction */ - writew(devpriv->dioStatus, devpriv->las0 + LAS0_DIO_STATUS); + + /* set direction */ + writew(0x01, devpriv->las0 + LAS0_DIO_STATUS); writew(s->io_bits & 0xff, devpriv->las0 + LAS0_DIO0_CTRL); - devpriv->dioStatus = 0x00; /* clear interrupts */ - writew(devpriv->dioStatus, devpriv->las0 + LAS0_DIO_STATUS); + + /* clear interrupts */ + writew(0x00, devpriv->las0 + LAS0_DIO_STATUS); /* port1 can only be all input or all output */ /* there are also 2 user input lines and 2 user output lines */ - return 1; + return insn->n; } static void rtd_reset(struct comedi_device *dev) { - struct rtdPrivate *devpriv = dev->private; + struct rtd_private *devpriv = dev->private; writel(0, devpriv->las0 + LAS0_BOARD_RESET); udelay(100); /* needed? */ - writel(0, devpriv->lcfg + LCFG_ITCSR); - devpriv->intMask = 0; - writew(devpriv->intMask, devpriv->las0 + LAS0_IT); - devpriv->intClearMask = ~0; - writew(devpriv->intClearMask, devpriv->las0 + LAS0_CLEAR); + writel(0, devpriv->lcfg + PLX_INTRCS_REG); + writew(0, devpriv->las0 + LAS0_IT); + writew(~0, devpriv->las0 + LAS0_CLEAR); readw(devpriv->las0 + LAS0_CLEAR); } @@ -1221,7 +1293,7 @@ static void rtd_reset(struct comedi_device *dev) */ static void rtd_init_board(struct comedi_device *dev) { - struct rtdPrivate *devpriv = dev->private; + struct rtd_private *devpriv = dev->private; rtd_reset(dev); @@ -1231,16 +1303,11 @@ static void rtd_init_board(struct comedi_device *dev) writel(0, devpriv->las0 + LAS0_DAC1_RESET); writel(0, devpriv->las0 + LAS0_DAC2_RESET); /* clear digital IO fifo */ - devpriv->dioStatus = 0; - writew(devpriv->dioStatus, devpriv->las0 + LAS0_DIO_STATUS); - devpriv->utcCtrl[0] = (0 << 6) | 0x30; - devpriv->utcCtrl[1] = (1 << 6) | 0x30; - devpriv->utcCtrl[2] = (2 << 6) | 0x30; - devpriv->utcCtrl[3] = (3 << 6) | 0x00; - writeb(devpriv->utcCtrl[0], devpriv->las0 + LAS0_UTC_CTRL); - writeb(devpriv->utcCtrl[1], devpriv->las0 + LAS0_UTC_CTRL); - writeb(devpriv->utcCtrl[2], devpriv->las0 + LAS0_UTC_CTRL); - writeb(devpriv->utcCtrl[3], devpriv->las0 + LAS0_UTC_CTRL); + 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); /* TODO: set user out source ??? */ } @@ -1259,51 +1326,34 @@ static void rtd_pci_latency_quirk(struct comedi_device *dev, } } -static const void *rtd_find_boardinfo(struct comedi_device *dev, - struct pci_dev *pcidev) -{ - const struct rtdBoard *thisboard; - int i; - - for (i = 0; i < ARRAY_SIZE(rtd520Boards); i++) { - thisboard = &rtd520Boards[i]; - if (pcidev->device == thisboard->device_id) - return thisboard; - } - return NULL; -} - static int rtd_auto_attach(struct comedi_device *dev, - unsigned long context_unused) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct rtdBoard *thisboard; - struct rtdPrivate *devpriv; + const struct rtd_boardinfo *board = NULL; + struct rtd_private *devpriv; struct comedi_subdevice *s; int ret; - thisboard = rtd_find_boardinfo(dev, pcidev); - if (!thisboard) + if (context < ARRAY_SIZE(rtd520Boards)) + board = &rtd520Boards[context]; + if (!board) return -ENODEV; - dev->board_ptr = thisboard; - dev->board_name = thisboard->name; + dev->board_ptr = board; + dev->board_name = board->name; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; - dev->iobase = 1; /* the "detach" needs this */ - - devpriv->las0 = ioremap_nocache(pci_resource_start(pcidev, 2), - pci_resource_len(pcidev, 2)); - devpriv->las1 = ioremap_nocache(pci_resource_start(pcidev, 3), - pci_resource_len(pcidev, 3)); - devpriv->lcfg = ioremap_nocache(pci_resource_start(pcidev, 0), - pci_resource_len(pcidev, 0)); + + devpriv->las0 = 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) return -ENOMEM; @@ -1326,7 +1376,7 @@ static int rtd_auto_attach(struct comedi_device *dev, s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF; s->n_chan = 16; s->maxdata = 0x0fff; - s->range_table = thisboard->ai_range; + s->range_table = board->ai_range; s->len_chanlist = RTD_MAX_CHANLIST; s->insn_read = rtd_ai_rinsn; if (dev->irq) { @@ -1370,10 +1420,10 @@ static int rtd_auto_attach(struct comedi_device *dev, ret = rtd520_probe_fifo_depth(dev); if (ret < 0) return ret; - devpriv->fifoLen = ret; + devpriv->fifosz = ret; if (dev->irq) - writel(ICS_PIE | ICS_PLIE, devpriv->lcfg + LCFG_ITCSR); + writel(ICS_PIE | ICS_PLIE, devpriv->lcfg + PLX_INTRCS_REG); dev_info(dev->class_dev, "%s attached\n", dev->board_name); @@ -1382,17 +1432,16 @@ static int rtd_auto_attach(struct comedi_device *dev, static void rtd_detach(struct comedi_device *dev) { - struct rtdPrivate *devpriv = dev->private; - struct pci_dev *pcidev = comedi_to_pci_dev(dev); + struct rtd_private *devpriv = dev->private; if (devpriv) { /* Shut down any board ops by resetting it */ if (devpriv->las0 && devpriv->lcfg) rtd_reset(dev); if (dev->irq) { - writel(readl(devpriv->lcfg + LCFG_ITCSR) & + writel(readl(devpriv->lcfg + PLX_INTRCS_REG) & ~(ICS_PLIE | ICS_DMA0_E | ICS_DMA1_E), - devpriv->lcfg + LCFG_ITCSR); + devpriv->lcfg + PLX_INTRCS_REG); free_irq(dev->irq, dev); } if (devpriv->las0) @@ -1402,10 +1451,7 @@ static void rtd_detach(struct comedi_device *dev) if (devpriv->lcfg) iounmap(devpriv->lcfg); } - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); - } + comedi_pci_disable(dev); } static struct comedi_driver rtd520_driver = { @@ -1416,14 +1462,14 @@ static struct comedi_driver rtd520_driver = { }; static int rtd520_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &rtd520_driver); + return comedi_pci_auto_config(dev, &rtd520_driver, id->driver_data); } static DEFINE_PCI_DEVICE_TABLE(rtd520_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_RTD, 0x7520) }, - { PCI_DEVICE(PCI_VENDOR_ID_RTD, 0x4520) }, + { PCI_VDEVICE(RTD, 0x7520), BOARD_DM7520 }, + { PCI_VDEVICE(RTD, 0x4520), BOARD_PCI4520 }, { 0 } }; MODULE_DEVICE_TABLE(pci, rtd520_pci_table); diff --git a/drivers/staging/comedi/drivers/rtd520.h b/drivers/staging/comedi/drivers/rtd520.h deleted file mode 100644 index 25188a58145..00000000000 --- a/drivers/staging/comedi/drivers/rtd520.h +++ /dev/null @@ -1,381 +0,0 @@ -/* - comedi/drivers/rtd520.h - Comedi driver defines for Real Time Devices (RTD) PCI4520/DM7520 - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2001 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - Created by Dan Christian, NASA Ames Research Center. - See board notes in rtd520.c -*/ - -/* - * Local Address Space 0 Offsets - */ -#define LAS0_USER_IO 0x0008 /* User I/O */ -#define LAS0_ADC 0x0010 /* FIFO Status/Software A/D Start */ -#define LAS0_DAC1 0x0014 /* Software D/A1 Update (w) */ -#define LAS0_DAC2 0x0018 /* Software D/A2 Update (w) */ -#define LAS0_DAC 0x0024 /* Software Simultaneous Update (w) */ -#define LAS0_PACER 0x0028 /* Software Pacer Start/Stop */ -#define LAS0_TIMER 0x002c /* Timer Status/HDIN Software Trig. */ -#define LAS0_IT 0x0030 /* Interrupt Status/Enable */ -#define LAS0_CLEAR 0x0034 /* Clear/Set Interrupt Clear Mask */ -#define LAS0_OVERRUN 0x0038 /* Pending interrupts/Clear Overrun */ -#define LAS0_PCLK 0x0040 /* Pacer Clock (24bit) */ -#define LAS0_BCLK 0x0044 /* Burst Clock (10bit) */ -#define LAS0_ADC_SCNT 0x0048 /* A/D Sample counter (10bit) */ -#define LAS0_DAC1_UCNT 0x004c /* D/A1 Update counter (10 bit) */ -#define LAS0_DAC2_UCNT 0x0050 /* D/A2 Update counter (10 bit) */ -#define LAS0_DCNT 0x0054 /* Delay counter (16 bit) */ -#define LAS0_ACNT 0x0058 /* About counter (16 bit) */ -#define LAS0_DAC_CLK 0x005c /* DAC clock (16bit) */ -#define LAS0_UTC0 0x0060 /* 8254 TC Counter 0 */ -#define LAS0_UTC1 0x0064 /* 8254 TC Counter 1 */ -#define LAS0_UTC2 0x0068 /* 8254 TC Counter 2 */ -#define LAS0_UTC_CTRL 0x006c /* 8254 TC Control */ -#define LAS0_DIO0 0x0070 /* Digital I/O Port 0 */ -#define LAS0_DIO1 0x0074 /* Digital I/O Port 1 */ -#define LAS0_DIO0_CTRL 0x0078 /* Digital I/O Control */ -#define LAS0_DIO_STATUS 0x007c /* Digital I/O Status */ -#define LAS0_BOARD_RESET 0x0100 /* Board reset */ -#define LAS0_DMA0_SRC 0x0104 /* DMA 0 Sources select */ -#define LAS0_DMA1_SRC 0x0108 /* DMA 1 Sources select */ -#define LAS0_ADC_CONVERSION 0x010c /* A/D Conversion Signal select */ -#define LAS0_BURST_START 0x0110 /* Burst Clock Start Trigger select */ -#define LAS0_PACER_START 0x0114 /* Pacer Clock Start Trigger select */ -#define LAS0_PACER_STOP 0x0118 /* Pacer Clock Stop Trigger select */ -#define LAS0_ACNT_STOP_ENABLE 0x011c /* About Counter Stop Enable */ -#define LAS0_PACER_REPEAT 0x0120 /* Pacer Start Trigger Mode select */ -#define LAS0_DIN_START 0x0124 /* HiSpd DI Sampling Signal select */ -#define LAS0_DIN_FIFO_CLEAR 0x0128 /* Digital Input FIFO Clear */ -#define LAS0_ADC_FIFO_CLEAR 0x012c /* A/D FIFO Clear */ -#define LAS0_CGT_WRITE 0x0130 /* Channel Gain Table Write */ -#define LAS0_CGL_WRITE 0x0134 /* Channel Gain Latch Write */ -#define LAS0_CG_DATA 0x0138 /* Digital Table Write */ -#define LAS0_CGT_ENABLE 0x013c /* Channel Gain Table Enable */ -#define LAS0_CG_ENABLE 0x0140 /* Digital Table Enable */ -#define LAS0_CGT_PAUSE 0x0144 /* Table Pause Enable */ -#define LAS0_CGT_RESET 0x0148 /* Reset Channel Gain Table */ -#define LAS0_CGT_CLEAR 0x014c /* Clear Channel Gain Table */ -#define LAS0_DAC1_CTRL 0x0150 /* D/A1 output type/range */ -#define LAS0_DAC1_SRC 0x0154 /* D/A1 update source */ -#define LAS0_DAC1_CYCLE 0x0158 /* D/A1 cycle mode */ -#define LAS0_DAC1_RESET 0x015c /* D/A1 FIFO reset */ -#define LAS0_DAC1_FIFO_CLEAR 0x0160 /* D/A1 FIFO clear */ -#define LAS0_DAC2_CTRL 0x0164 /* D/A2 output type/range */ -#define LAS0_DAC2_SRC 0x0168 /* D/A2 update source */ -#define LAS0_DAC2_CYCLE 0x016c /* D/A2 cycle mode */ -#define LAS0_DAC2_RESET 0x0170 /* D/A2 FIFO reset */ -#define LAS0_DAC2_FIFO_CLEAR 0x0174 /* D/A2 FIFO clear */ -#define LAS0_ADC_SCNT_SRC 0x0178 /* A/D Sample Counter Source select */ -#define LAS0_PACER_SELECT 0x0180 /* Pacer Clock select */ -#define LAS0_SBUS0_SRC 0x0184 /* SyncBus 0 Source select */ -#define LAS0_SBUS0_ENABLE 0x0188 /* SyncBus 0 enable */ -#define LAS0_SBUS1_SRC 0x018c /* SyncBus 1 Source select */ -#define LAS0_SBUS1_ENABLE 0x0190 /* SyncBus 1 enable */ -#define LAS0_SBUS2_SRC 0x0198 /* SyncBus 2 Source select */ -#define LAS0_SBUS2_ENABLE 0x019c /* SyncBus 2 enable */ -#define LAS0_ETRG_POLARITY 0x01a4 /* Ext. Trigger polarity select */ -#define LAS0_EINT_POLARITY 0x01a8 /* Ext. Interrupt polarity select */ -#define LAS0_UTC0_CLOCK 0x01ac /* UTC0 Clock select */ -#define LAS0_UTC0_GATE 0x01b0 /* UTC0 Gate select */ -#define LAS0_UTC1_CLOCK 0x01b4 /* UTC1 Clock select */ -#define LAS0_UTC1_GATE 0x01b8 /* UTC1 Gate select */ -#define LAS0_UTC2_CLOCK 0x01bc /* UTC2 Clock select */ -#define LAS0_UTC2_GATE 0x01c0 /* UTC2 Gate select */ -#define LAS0_UOUT0_SELECT 0x01c4 /* User Output 0 source select */ -#define LAS0_UOUT1_SELECT 0x01c8 /* User Output 1 source select */ -#define LAS0_DMA0_RESET 0x01cc /* DMA0 Request state machine reset */ -#define LAS0_DMA1_RESET 0x01d0 /* DMA1 Request state machine reset */ - -/* - * Local Address Space 1 Offsets - */ -#define LAS1_ADC_FIFO 0x0000 /* A/D FIFO (16bit) */ -#define LAS1_HDIO_FIFO 0x0004 /* HiSpd DI FIFO (16bit) */ -#define LAS1_DAC1_FIFO 0x0008 /* D/A1 FIFO (16bit) */ -#define LAS1_DAC2_FIFO 0x000c /* D/A2 FIFO (16bit) */ - -/* - * PLX 9080 local config & runtime registers - */ -#define LCFG_ITCSR 0x0068 /* Interrupt Control/Status */ -#define LCFG_DMAMODE0 0x0080 /* DMA0 Mode */ -#define LCFG_DMAPADR0 0x0084 /* DMA0 PCI Address */ -#define LCFG_DMALADR0 0x0088 /* DMA0 Local Address */ -#define LCFG_DMASIZ0 0x008c /* DMA0 Transfer Size (Bytes) */ -#define LCFG_DMADPR0 0x0090 /* DMA0 Descriptor Pointer */ -#define LCFG_DMAMODE1 0x0094 /* DMA1 Mode */ -#define LCFG_DMAPADR1 0x0098 /* DMA1 PCI Address */ -#define LCFG_DMALADR1 0x009c /* DMA1 Local Address */ -#define LCFG_DMASIZ1 0x00a0 /* DMA1 Transfer Size (Bytes) */ -#define LCFG_DMADPR1 0x00a4 /* DMA1 Descriptor Pointer */ -#define LCFG_DMACSR0 0x00a8 /* DMA0 Command/Status */ -#define LCFG_DMACSR1 0x00a9 /* DMA0 Command/Status */ -#define LCFG_DMAARB 0x00ac /* DMA Arbitration */ -#define LCFG_DMATHR 0x00b0 /* DMA Threshold */ - -/* FIFO Status Word Bits (RtdFifoStatus) */ -#define FS_DAC1_NOT_EMPTY (1 << 0) /* DAC1 FIFO not empty */ -#define FS_DAC1_HEMPTY (1 << 1) /* DAC1 FIFO half empty */ -#define FS_DAC1_NOT_FULL (1 << 2) /* DAC1 FIFO not full */ -#define FS_DAC2_NOT_EMPTY (1 << 4) /* DAC2 FIFO not empty */ -#define FS_DAC2_HEMPTY (1 << 5) /* DAC2 FIFO half empty */ -#define FS_DAC2_NOT_FULL (1 << 6) /* DAC2 FIFO not full */ -#define FS_ADC_NOT_EMPTY (1 << 8) /* ADC FIFO not empty */ -#define FS_ADC_HEMPTY (1 << 9) /* ADC FIFO half empty */ -#define FS_ADC_NOT_FULL (1 << 10) /* ADC FIFO not full */ -#define FS_DIN_NOT_EMPTY (1 << 12) /* DIN FIFO not empty */ -#define FS_DIN_HEMPTY (1 << 13) /* DIN FIFO half empty */ -#define FS_DIN_NOT_FULL (1 << 14) /* DIN FIFO not full */ - -/* Timer Status Word Bits (GetTimerStatus) */ -#define TS_PCLK_GATE (1 << 0) /* Pacer Clock Gate enabled */ -#define TS_BCLK_GATE (1 << 1) /* Burst Clock Gate running */ -#define TS_DCNT_GATE (1 << 2) /* Pacer Clock Delayed Start Trig. */ -#define TS_ACNT_GATE (1 << 3) /* Pacer Clock About Trig. */ -#define TS_PCLK_RUN (1 << 4) /* Pacer Clock Shutdown Flag */ - -/* External Trigger polarity select */ -/* External Interrupt polarity select */ -#define POL_POSITIVE 0x0 /* positive edge */ -#define POL_NEGATIVE 0x1 /* negative edge */ - -/* User Output Signal select (SetUout0Source, SetUout1Source) */ -#define UOUT_ADC 0x0 /* A/D Conversion Signal */ -#define UOUT_DAC1 0x1 /* D/A1 Update */ -#define UOUT_DAC2 0x2 /* D/A2 Update */ -#define UOUT_SOFTWARE 0x3 /* Software Programmable */ - -/* Pacer clock select (SetPacerSource) */ -#define PCLK_INTERNAL 1 /* Internal Pacer Clock */ -#define PCLK_EXTERNAL 0 /* External Pacer Clock */ - -/* A/D Sample Counter Sources (SetAdcntSource, SetupSampleCounter) */ -#define ADC_SCNT_CGT_RESET 0x0 /* needs restart with StartPacer */ -#define ADC_SCNT_FIFO_WRITE 0x1 - -/* A/D Conversion Signal Select (for SetConversionSelect) */ -#define ADC_START_SOFTWARE 0x0 /* Software A/D Start */ -#define ADC_START_PCLK 0x1 /* Pacer Clock (Ext. Int. see Func.509) */ -#define ADC_START_BCLK 0x2 /* Burst Clock */ -#define ADC_START_DIGITAL_IT 0x3 /* Digital Interrupt */ -#define ADC_START_DAC1_MARKER1 0x4 /* D/A 1 Data Marker 1 */ -#define ADC_START_DAC2_MARKER1 0x5 /* D/A 2 Data Marker 1 */ -#define ADC_START_SBUS0 0x6 /* SyncBus 0 */ -#define ADC_START_SBUS1 0x7 /* SyncBus 1 */ -#define ADC_START_SBUS2 0x8 /* SyncBus 2 */ - -/* Burst Clock start trigger select (SetBurstStart) */ -#define BCLK_START_SOFTWARE 0x0 /* Software A/D Start (StartBurst) */ -#define BCLK_START_PCLK 0x1 /* Pacer Clock */ -#define BCLK_START_ETRIG 0x2 /* External Trigger */ -#define BCLK_START_DIGITAL_IT 0x3 /* Digital Interrupt */ -#define BCLK_START_SBUS0 0x4 /* SyncBus 0 */ -#define BCLK_START_SBUS1 0x5 /* SyncBus 1 */ -#define BCLK_START_SBUS2 0x6 /* SyncBus 2 */ - -/* Pacer Clock start trigger select (SetPacerStart) */ -#define PCLK_START_SOFTWARE 0x0 /* Software Pacer Start (StartPacer) */ -#define PCLK_START_ETRIG 0x1 /* External trigger */ -#define PCLK_START_DIGITAL_IT 0x2 /* Digital interrupt */ -#define PCLK_START_UTC2 0x3 /* User TC 2 out */ -#define PCLK_START_SBUS0 0x4 /* SyncBus 0 */ -#define PCLK_START_SBUS1 0x5 /* SyncBus 1 */ -#define PCLK_START_SBUS2 0x6 /* SyncBus 2 */ -#define PCLK_START_D_SOFTWARE 0x8 /* Delayed Software Pacer Start */ -#define PCLK_START_D_ETRIG 0x9 /* Delayed external trigger */ -#define PCLK_START_D_DIGITAL_IT 0xA /* Delayed digital interrupt */ -#define PCLK_START_D_UTC2 0xB /* Delayed User TC 2 out */ -#define PCLK_START_D_SBUS0 0xC /* Delayed SyncBus 0 */ -#define PCLK_START_D_SBUS1 0xD /* Delayed SyncBus 1 */ -#define PCLK_START_D_SBUS2 0xE /* Delayed SyncBus 2 */ -#define PCLK_START_ETRIG_GATED 0xF /* External Trigger Gated controlled mode */ - -/* Pacer Clock Stop Trigger select (SetPacerStop) */ -#define PCLK_STOP_SOFTWARE 0x0 /* Software Pacer Stop (StopPacer) */ -#define PCLK_STOP_ETRIG 0x1 /* External Trigger */ -#define PCLK_STOP_DIGITAL_IT 0x2 /* Digital Interrupt */ -#define PCLK_STOP_ACNT 0x3 /* About Counter */ -#define PCLK_STOP_UTC2 0x4 /* User TC2 out */ -#define PCLK_STOP_SBUS0 0x5 /* SyncBus 0 */ -#define PCLK_STOP_SBUS1 0x6 /* SyncBus 1 */ -#define PCLK_STOP_SBUS2 0x7 /* SyncBus 2 */ -#define PCLK_STOP_A_SOFTWARE 0x8 /* About Software Pacer Stop */ -#define PCLK_STOP_A_ETRIG 0x9 /* About External Trigger */ -#define PCLK_STOP_A_DIGITAL_IT 0xA /* About Digital Interrupt */ -#define PCLK_STOP_A_UTC2 0xC /* About User TC2 out */ -#define PCLK_STOP_A_SBUS0 0xD /* About SyncBus 0 */ -#define PCLK_STOP_A_SBUS1 0xE /* About SyncBus 1 */ -#define PCLK_STOP_A_SBUS2 0xF /* About SyncBus 2 */ - -/* About Counter Stop Enable */ -#define ACNT_STOP 0x0 /* stop enable */ -#define ACNT_NO_STOP 0x1 /* stop disabled */ - -/* DAC update source (SetDAC1Start & SetDAC2Start) */ -#define DAC_START_SOFTWARE 0x0 /* Software Update */ -#define DAC_START_CGT 0x1 /* CGT controlled Update */ -#define DAC_START_DAC_CLK 0x2 /* D/A Clock */ -#define DAC_START_EPCLK 0x3 /* External Pacer Clock */ -#define DAC_START_SBUS0 0x4 /* SyncBus 0 */ -#define DAC_START_SBUS1 0x5 /* SyncBus 1 */ -#define DAC_START_SBUS2 0x6 /* SyncBus 2 */ - -/* DAC Cycle Mode (SetDAC1Cycle, SetDAC2Cycle, SetupDAC) */ -#define DAC_CYCLE_SINGLE 0x0 /* not cycle */ -#define DAC_CYCLE_MULTI 0x1 /* cycle */ - -/* 8254 Operation Modes (Set8254Mode, SetupTimerCounter) */ -#define M8254_EVENT_COUNTER 0 /* Event Counter */ -#define M8254_HW_ONE_SHOT 1 /* Hardware-Retriggerable One-Shot */ -#define M8254_RATE_GENERATOR 2 /* Rate Generator */ -#define M8254_SQUARE_WAVE 3 /* Square Wave Mode */ -#define M8254_SW_STROBE 4 /* Software Triggered Strobe */ -#define M8254_HW_STROBE 5 /* Hardware Triggered Strobe (Retriggerable) */ - -/* User Timer/Counter 0 Clock Select (SetUtc0Clock) */ -#define CUTC0_8MHZ 0x0 /* 8MHz */ -#define CUTC0_EXT_TC_CLOCK1 0x1 /* Ext. TC Clock 1 */ -#define CUTC0_EXT_TC_CLOCK2 0x2 /* Ext. TC Clock 2 */ -#define CUTC0_EXT_PCLK 0x3 /* Ext. Pacer Clock */ - -/* User Timer/Counter 1 Clock Select (SetUtc1Clock) */ -#define CUTC1_8MHZ 0x0 /* 8MHz */ -#define CUTC1_EXT_TC_CLOCK1 0x1 /* Ext. TC Clock 1 */ -#define CUTC1_EXT_TC_CLOCK2 0x2 /* Ext. TC Clock 2 */ -#define CUTC1_EXT_PCLK 0x3 /* Ext. Pacer Clock */ -#define CUTC1_UTC0_OUT 0x4 /* User Timer/Counter 0 out */ -#define CUTC1_DIN_SIGNAL 0x5 /* High-Speed Digital Input Sampling signal */ - -/* User Timer/Counter 2 Clock Select (SetUtc2Clock) */ -#define CUTC2_8MHZ 0x0 /* 8MHz */ -#define CUTC2_EXT_TC_CLOCK1 0x1 /* Ext. TC Clock 1 */ -#define CUTC2_EXT_TC_CLOCK2 0x2 /* Ext. TC Clock 2 */ -#define CUTC2_EXT_PCLK 0x3 /* Ext. Pacer Clock */ -#define CUTC2_UTC1_OUT 0x4 /* User Timer/Counter 1 out */ - -/* User Timer/Counter 0 Gate Select (SetUtc0Gate) */ -#define GUTC0_NOT_GATED 0x0 /* Not gated */ -#define GUTC0_GATED 0x1 /* Gated */ -#define GUTC0_EXT_TC_GATE1 0x2 /* Ext. TC Gate 1 */ -#define GUTC0_EXT_TC_GATE2 0x3 /* Ext. TC Gate 2 */ - -/* User Timer/Counter 1 Gate Select (SetUtc1Gate) */ -#define GUTC1_NOT_GATED 0x0 /* Not gated */ -#define GUTC1_GATED 0x1 /* Gated */ -#define GUTC1_EXT_TC_GATE1 0x2 /* Ext. TC Gate 1 */ -#define GUTC1_EXT_TC_GATE2 0x3 /* Ext. TC Gate 2 */ -#define GUTC1_UTC0_OUT 0x4 /* User Timer/Counter 0 out */ - -/* User Timer/Counter 2 Gate Select (SetUtc2Gate) */ -#define GUTC2_NOT_GATED 0x0 /* Not gated */ -#define GUTC2_GATED 0x1 /* Gated */ -#define GUTC2_EXT_TC_GATE1 0x2 /* Ext. TC Gate 1 */ -#define GUTC2_EXT_TC_GATE2 0x3 /* Ext. TC Gate 2 */ -#define GUTC2_UTC1_OUT 0x4 /* User Timer/Counter 1 out */ - -/* Interrupt Source Masks (SetITMask, ClearITMask, GetITStatus) */ -#define IRQM_ADC_FIFO_WRITE 0x0001 /* ADC FIFO Write */ -#define IRQM_CGT_RESET 0x0002 /* Reset CGT */ -#define IRQM_CGT_PAUSE 0x0008 /* Pause CGT */ -#define IRQM_ADC_ABOUT_CNT 0x0010 /* About Counter out */ -#define IRQM_ADC_DELAY_CNT 0x0020 /* Delay Counter out */ -#define IRQM_ADC_SAMPLE_CNT 0x0040 /* ADC Sample Counter */ -#define IRQM_DAC1_UCNT 0x0080 /* DAC1 Update Counter */ -#define IRQM_DAC2_UCNT 0x0100 /* DAC2 Update Counter */ -#define IRQM_UTC1 0x0200 /* User TC1 out */ -#define IRQM_UTC1_INV 0x0400 /* User TC1 out, inverted */ -#define IRQM_UTC2 0x0800 /* User TC2 out */ -#define IRQM_DIGITAL_IT 0x1000 /* Digital Interrupt */ -#define IRQM_EXTERNAL_IT 0x2000 /* External Interrupt */ -#define IRQM_ETRIG_RISING 0x4000 /* External Trigger rising-edge */ -#define IRQM_ETRIG_FALLING 0x8000 /* External Trigger falling-edge */ - -/* DMA Request Sources (LAS0) */ -#define DMAS_DISABLED 0x0 /* DMA Disabled */ -#define DMAS_ADC_SCNT 0x1 /* ADC Sample Counter */ -#define DMAS_DAC1_UCNT 0x2 /* D/A1 Update Counter */ -#define DMAS_DAC2_UCNT 0x3 /* D/A2 Update Counter */ -#define DMAS_UTC1 0x4 /* User TC1 out */ -#define DMAS_ADFIFO_HALF_FULL 0x8 /* A/D FIFO half full */ -#define DMAS_DAC1_FIFO_HALF_EMPTY 0x9 /* D/A1 FIFO half empty */ -#define DMAS_DAC2_FIFO_HALF_EMPTY 0xA /* D/A2 FIFO half empty */ - -/* DMA Local Addresses (0x40000000+LAS1 offset) */ -#define DMALADDR_ADC 0x40000000 /* A/D FIFO */ -#define DMALADDR_HDIN 0x40000004 /* High Speed Digital Input FIFO */ -#define DMALADDR_DAC1 0x40000008 /* D/A1 FIFO */ -#define DMALADDR_DAC2 0x4000000C /* D/A2 FIFO */ - -/* Port 0 compare modes (SetDIO0CompareMode) */ -#define DIO_MODE_EVENT 0 /* Event Mode */ -#define DIO_MODE_MATCH 1 /* Match Mode */ - -/* Digital Table Enable (Port 1 disable) */ -#define DTBL_DISABLE 0 /* Enable Digital Table */ -#define DTBL_ENABLE 1 /* Disable Digital Table */ - -/* Sampling Signal for High Speed Digital Input (SetHdinStart) */ -#define HDIN_SOFTWARE 0x0 /* Software Trigger */ -#define HDIN_ADC 0x1 /* A/D Conversion Signal */ -#define HDIN_UTC0 0x2 /* User TC out 0 */ -#define HDIN_UTC1 0x3 /* User TC out 1 */ -#define HDIN_UTC2 0x4 /* User TC out 2 */ -#define HDIN_EPCLK 0x5 /* External Pacer Clock */ -#define HDIN_ETRG 0x6 /* External Trigger */ - -/* Channel Gain Table / Channel Gain Latch */ -#define CSC_LATCH 0 /* Channel Gain Latch mode */ -#define CSC_CGT 1 /* Channel Gain Table mode */ - -/* Channel Gain Table Pause Enable */ -#define CGT_PAUSE_DISABLE 0 /* Channel Gain Table Pause Disable */ -#define CGT_PAUSE_ENABLE 1 /* Channel Gain Table Pause Enable */ - -/* DAC output type/range (p63) */ -#define AOUT_UNIP5 0 /* 0..+5 Volt */ -#define AOUT_UNIP10 1 /* 0..+10 Volt */ -#define AOUT_BIP5 2 /* -5..+5 Volt */ -#define AOUT_BIP10 3 /* -10..+10 Volt */ - -/* Ghannel Gain Table field definitions (p61) */ -/* Gain */ -#define GAIN1 0 -#define GAIN2 1 -#define GAIN4 2 -#define GAIN8 3 -#define GAIN16 4 -#define GAIN32 5 -#define GAIN64 6 -#define GAIN128 7 - -/* Input range/polarity */ -#define AIN_BIP5 0 /* -5..+5 Volt */ -#define AIN_BIP10 1 /* -10..+10 Volt */ -#define AIN_UNIP10 2 /* 0..+10 Volt */ - -/* non referenced single ended select bit */ -#define NRSE_AGND 0 /* AGND referenced SE input */ -#define NRSE_AINS 1 /* AIN SENSE referenced SE input */ - -/* single ended vs differential */ -#define GND_SE 0 /* Single-Ended */ -#define GND_DIFF 1 /* Differential */ diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index 7e577e44490..f4163fd35a0 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -1,186 +1,184 @@ /* - comedi/drivers/rti800.c - Hardware driver for Analog Devices RTI-800/815 board - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1998 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - + * comedi/drivers/rti800.c + * Hardware driver for Analog Devices RTI-800/815 board + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1998 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + /* -Driver: rti800 -Description: Analog Devices RTI-800/815 -Author: ds -Status: unknown -Updated: Fri, 05 Sep 2008 14:50:44 +0100 -Devices: [Analog Devices] RTI-800 (rti800), RTI-815 (rti815) - -Configuration options: - [0] - I/O port base address - [1] - IRQ - [2] - A/D reference - 0 = differential - 1 = pseudodifferential (common) - 2 = single-ended - [3] - A/D range - 0 = [-10,10] - 1 = [-5,5] - 2 = [0,10] - [4] - A/D encoding - 0 = two's complement - 1 = straight binary - [5] - DAC 0 range - 0 = [-10,10] - 1 = [0,10] - [6] - DAC 0 encoding - 0 = two's complement - 1 = straight binary - [7] - DAC 1 range (same as DAC 0) - [8] - DAC 1 encoding (same as DAC 0) -*/ + * Driver: rti800 + * Description: Analog Devices RTI-800/815 + * Devices: (Analog Devices) RTI-800 [rti800] + * (Analog Devices) RTI-815 [rti815] + * Author: David A. Schleef <ds@schleef.org> + * Status: unknown + * Updated: Fri, 05 Sep 2008 14:50:44 +0100 + * + * Configuration options: + * [0] - I/O port base address + * [1] - IRQ (not supported / unused) + * [2] - A/D mux/reference (number of channels) + * 0 = differential + * 1 = pseudodifferential (common) + * 2 = single-ended + * [3] - A/D range + * 0 = [-10,10] + * 1 = [-5,5] + * 2 = [0,10] + * [4] - A/D encoding + * 0 = two's complement + * 1 = straight binary + * [5] - DAC 0 range + * 0 = [-10,10] + * 1 = [0,10] + * [6] - DAC 0 encoding + * 0 = two's complement + * 1 = straight binary + * [7] - DAC 1 range (same as DAC 0) + * [8] - DAC 1 encoding (same as DAC 0) + */ #include <linux/interrupt.h> #include "../comedidev.h" #include <linux/ioport.h> -#define RTI800_SIZE 16 - -#define RTI800_CSR 0 -#define RTI800_MUXGAIN 1 -#define RTI800_CONVERT 2 -#define RTI800_ADCLO 3 -#define RTI800_ADCHI 4 -#define RTI800_DAC0LO 5 -#define RTI800_DAC0HI 6 -#define RTI800_DAC1LO 7 -#define RTI800_DAC1HI 8 -#define RTI800_CLRFLAGS 9 -#define RTI800_DI 10 -#define RTI800_DO 11 -#define RTI800_9513A_DATA 12 -#define RTI800_9513A_CNTRL 13 -#define RTI800_9513A_STATUS 13 - /* - * flags for CSR register + * Register map */ +#define RTI800_CSR 0x00 +#define RTI800_CSR_BUSY (1 << 7) +#define RTI800_CSR_DONE (1 << 6) +#define RTI800_CSR_OVERRUN (1 << 5) +#define RTI800_CSR_TCR (1 << 4) +#define RTI800_CSR_DMA_ENAB (1 << 3) +#define RTI800_CSR_INTR_TC (1 << 2) +#define RTI800_CSR_INTR_EC (1 << 1) +#define RTI800_CSR_INTR_OVRN (1 << 0) +#define RTI800_MUXGAIN 0x01 +#define RTI800_CONVERT 0x02 +#define RTI800_ADCLO 0x03 +#define RTI800_ADCHI 0x04 +#define RTI800_DAC0LO 0x05 +#define RTI800_DAC0HI 0x06 +#define RTI800_DAC1LO 0x07 +#define RTI800_DAC1HI 0x08 +#define RTI800_CLRFLAGS 0x09 +#define RTI800_DI 0x0a +#define RTI800_DO 0x0b +#define RTI800_9513A_DATA 0x0c +#define RTI800_9513A_CNTRL 0x0d +#define RTI800_9513A_STATUS 0x0d + +#define RTI800_IOSIZE 0x10 + +#define RTI800_AI_TIMEOUT 100 + +static const struct comedi_lrange range_rti800_ai_10_bipolar = { + 4, { + BIP_RANGE(10), + BIP_RANGE(1), + BIP_RANGE(0.1), + BIP_RANGE(0.02) + } +}; -#define RTI800_BUSY 0x80 -#define RTI800_DONE 0x40 -#define RTI800_OVERRUN 0x20 -#define RTI800_TCR 0x10 -#define RTI800_DMA_ENAB 0x08 -#define RTI800_INTR_TC 0x04 -#define RTI800_INTR_EC 0x02 -#define RTI800_INTR_OVRN 0x01 - -#define Am9513_8BITBUS - -#define Am9513_output_control(a) outb(a, dev->iobase+RTI800_9513A_CNTRL) -#define Am9513_output_data(a) outb(a, dev->iobase+RTI800_9513A_DATA) -#define Am9513_input_data() inb(dev->iobase+RTI800_9513A_DATA) -#define Am9513_input_status() inb(dev->iobase+RTI800_9513A_STATUS) - -#include "am9513.h" - -static const struct comedi_lrange range_rti800_ai_10_bipolar = { 4, { - BIP_RANGE - (10), - BIP_RANGE - (1), - BIP_RANGE - (0.1), - BIP_RANGE - (0.02) - } +static const struct comedi_lrange range_rti800_ai_5_bipolar = { + 4, { + BIP_RANGE(5), + BIP_RANGE(0.5), + BIP_RANGE(0.05), + BIP_RANGE(0.01) + } }; -static const struct comedi_lrange range_rti800_ai_5_bipolar = { 4, { - BIP_RANGE - (5), - BIP_RANGE - (0.5), - BIP_RANGE - (0.05), - BIP_RANGE - (0.01) - } +static const struct comedi_lrange range_rti800_ai_unipolar = { + 4, { + UNI_RANGE(10), + UNI_RANGE(1), + UNI_RANGE(0.1), + UNI_RANGE(0.02) + } }; -static const struct comedi_lrange range_rti800_ai_unipolar = { 4, { - UNI_RANGE - (10), - UNI_RANGE(1), - UNI_RANGE - (0.1), - UNI_RANGE - (0.02) - } +static const struct comedi_lrange *const rti800_ai_ranges[] = { + &range_rti800_ai_10_bipolar, + &range_rti800_ai_5_bipolar, + &range_rti800_ai_unipolar, }; -struct rti800_board { +static const struct comedi_lrange *const rti800_ao_ranges[] = { + &range_bipolar10, + &range_unipolar10, +}; +struct rti800_board { const char *name; int has_ao; }; -static irqreturn_t rti800_interrupt(int irq, void *dev); +static const struct rti800_board rti800_boardtypes[] = { + { + .name = "rti800", + }, { + .name = "rti815", + .has_ao = 1, + }, +}; struct rti800_private { - enum { - adc_diff, adc_pseudodiff, adc_singleended - } adc_mux; - enum { - adc_bipolar10, adc_bipolar5, adc_unipolar10 - } adc_range; - enum { - adc_2comp, adc_straight - } adc_coding; - enum { - dac_bipolar10, dac_unipolar10 - } dac0_range, dac1_range; - enum { - dac_2comp, dac_straight - } dac0_coding, dac1_coding; + bool adc_2comp; + bool dac_2comp[2]; const struct comedi_lrange *ao_range_type_list[2]; unsigned int ao_readback[2]; - int muxgain_bits; + unsigned char muxgain_bits; }; -#define RTI800_TIMEOUT 100 - -static irqreturn_t rti800_interrupt(int irq, void *dev) +static int rti800_ai_wait_for_conversion(struct comedi_device *dev, + int timeout) { - return IRQ_HANDLED; -} + unsigned char status; + int i; -/* settling delay times in usec for different gains */ -static const int gaindelay[] = { 10, 20, 40, 80 }; + for (i = 0; i < timeout; i++) { + status = inb(dev->iobase + RTI800_CSR); + if (status & RTI800_CSR_OVERRUN) { + outb(0, dev->iobase + RTI800_CLRFLAGS); + return -EIO; + } + if (status & RTI800_CSR_DONE) + return 0; + udelay(1); + } + return -ETIME; +} static int rti800_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 rti800_private *devpriv = dev->private; - int i, t; - int status; - int chan = CR_CHAN(insn->chanspec); - unsigned gain = CR_RANGE(insn->chanspec); - unsigned muxgain_bits; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int gain = CR_RANGE(insn->chanspec); + unsigned char muxgain_bits; + int ret; + int i; inb(dev->iobase + RTI800_ADCHI); outb(0, dev->iobase + RTI800_CLRFLAGS); @@ -189,80 +187,80 @@ static int rti800_ai_insn_read(struct comedi_device *dev, if (muxgain_bits != devpriv->muxgain_bits) { devpriv->muxgain_bits = muxgain_bits; outb(devpriv->muxgain_bits, dev->iobase + RTI800_MUXGAIN); - /* without a delay here, the RTI_OVERRUN bit - * gets set, and you will have an error. */ + /* + * Without a delay here, the RTI_CSR_OVERRUN bit + * gets set, and you will have an error. + */ if (insn->n > 0) { - BUG_ON(gain >= ARRAY_SIZE(gaindelay)); - udelay(gaindelay[gain]); + int delay = (gain == 0) ? 10 : + (gain == 1) ? 20 : + (gain == 2) ? 40 : 80; + + udelay(delay); } } for (i = 0; i < insn->n; i++) { outb(0, dev->iobase + RTI800_CONVERT); - for (t = RTI800_TIMEOUT; t; t--) { - status = inb(dev->iobase + RTI800_CSR); - if (status & RTI800_OVERRUN) { - printk(KERN_WARNING "rti800: a/d overrun\n"); - outb(0, dev->iobase + RTI800_CLRFLAGS); - return -EIO; - } - if (status & RTI800_DONE) - break; - udelay(1); - } - if (t == 0) { - printk(KERN_WARNING "rti800: timeout\n"); - return -ETIME; - } + ret = rti800_ai_wait_for_conversion(dev, RTI800_AI_TIMEOUT); + if (ret) + return ret; + data[i] = inb(dev->iobase + RTI800_ADCLO); - data[i] |= (0xf & inb(dev->iobase + RTI800_ADCHI)) << 8; + data[i] |= (inb(dev->iobase + RTI800_ADCHI) & 0xf) << 8; - if (devpriv->adc_coding == adc_2comp) + if (devpriv->adc_2comp) data[i] ^= 0x800; } - return i; + return insn->n; } static int rti800_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 rti800_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); int i; - int chan = CR_CHAN(insn->chanspec); for (i = 0; i < insn->n; i++) data[i] = devpriv->ao_readback[chan]; - return i; + return insn->n; } static int rti800_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 rti800_private *devpriv = dev->private; - int chan = CR_CHAN(insn->chanspec); - int d; + unsigned int chan = CR_CHAN(insn->chanspec); + int reg_lo = chan ? RTI800_DAC1LO : RTI800_DAC0LO; + int reg_hi = chan ? RTI800_DAC1HI : RTI800_DAC0HI; + int val = devpriv->ao_readback[chan]; int i; for (i = 0; i < insn->n; i++) { - devpriv->ao_readback[chan] = d = data[i]; - if (devpriv->dac0_coding == dac_2comp) - d ^= 0x800; - - outb(d & 0xff, - dev->iobase + (chan ? RTI800_DAC1LO : RTI800_DAC0LO)); - outb(d >> 8, - dev->iobase + (chan ? RTI800_DAC1HI : RTI800_DAC0HI)); + val = data[i]; + if (devpriv->dac_2comp[chan]) + val ^= 0x800; + + outb(val & 0xff, dev->iobase + reg_lo); + outb((val >> 8) & 0xff, dev->iobase + reg_hi); } - return i; + + devpriv->ao_readback[chan] = val; + + return insn->n; } static int rti800_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { data[1] = inb(dev->iobase + RTI800_DI); return insn->n; @@ -270,11 +268,16 @@ static int rti800_di_insn_bits(struct comedi_device *dev, static int rti800_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - if (data[0]) { - s->state &= ~data[0]; - s->state |= data[0] & data[1]; + unsigned int mask = data[0]; + unsigned int bits = data[1]; + + if (mask) { + s->state &= ~mask; + s->state |= (bits & mask); + /* Outputs are inverted... */ outb(s->state ^ 0xff, dev->iobase + RTI800_DO); } @@ -284,186 +287,106 @@ static int rti800_do_insn_bits(struct comedi_device *dev, return insn->n; } -/* - options[0] - I/O port - options[1] - irq - options[2] - a/d mux - 0=differential, 1=pseudodiff, 2=single - options[3] - a/d range - 0=bipolar10, 1=bipolar5, 2=unipolar10 - options[4] - a/d coding - 0=2's comp, 1=straight binary - options[5] - dac0 range - 0=bipolar10, 1=unipolar10 - options[6] - dac0 coding - 0=2's comp, 1=straight binary - options[7] - dac1 range - options[8] - dac1 coding - */ - static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct rti800_board *board = comedi_board(dev); struct rti800_private *devpriv; - unsigned int irq; - unsigned long iobase; - int ret; struct comedi_subdevice *s; + int ret; - iobase = it->options[0]; - printk(KERN_INFO "comedi%d: rti800: 0x%04lx\n", dev->minor, iobase); - if (!request_region(iobase, RTI800_SIZE, "rti800")) { - printk(KERN_WARNING "I/O port conflict\n"); - return -EIO; - } - dev->iobase = iobase; - -#ifdef DEBUG - printk(KERN_DEBUG "fingerprint=%x,%x,%x,%x,%x ", - inb(dev->iobase + 0), - inb(dev->iobase + 1), - inb(dev->iobase + 2), - inb(dev->iobase + 3), inb(dev->iobase + 4)); -#endif + ret = comedi_request_region(dev, it->options[0], RTI800_IOSIZE); + if (ret) + return ret; outb(0, dev->iobase + RTI800_CSR); inb(dev->iobase + RTI800_ADCHI); outb(0, dev->iobase + RTI800_CLRFLAGS); - irq = it->options[1]; - if (irq) { - printk(KERN_INFO "( irq = %u )\n", irq); - ret = request_irq(irq, rti800_interrupt, 0, "rti800", dev); - if (ret < 0) { - printk(KERN_WARNING " Failed to allocate IRQ\n"); - return ret; - } - dev->irq = irq; - } else { - printk(KERN_INFO "( no irq )\n"); - } - - dev->board_name = board->name; - - ret = comedi_alloc_subdevices(dev, 4); - if (ret) - return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - devpriv->adc_mux = it->options[2]; - devpriv->adc_range = it->options[3]; - devpriv->adc_coding = it->options[4]; - devpriv->dac0_range = it->options[5]; - devpriv->dac0_coding = it->options[6]; - devpriv->dac1_range = it->options[7]; - devpriv->dac1_coding = it->options[8]; - devpriv->muxgain_bits = -1; + devpriv->adc_2comp = (it->options[4] == 0); + devpriv->dac_2comp[0] = (it->options[6] == 0); + devpriv->dac_2comp[1] = (it->options[8] == 0); + /* invalid, forces the MUXGAIN register to be set when first used */ + devpriv->muxgain_bits = 0xff; + + ret = comedi_alloc_subdevices(dev, 4); + if (ret) + return ret; s = &dev->subdevices[0]; /* ai subdevice */ - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND; - s->n_chan = (devpriv->adc_mux ? 16 : 8); - s->insn_read = rti800_ai_insn_read; - s->maxdata = 0xfff; - switch (devpriv->adc_range) { - case adc_bipolar10: - s->range_table = &range_rti800_ai_10_bipolar; - break; - case adc_bipolar5: - s->range_table = &range_rti800_ai_5_bipolar; - break; - case adc_unipolar10: - s->range_table = &range_rti800_ai_unipolar; - break; - } + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND; + s->n_chan = (it->options[2] ? 16 : 8); + s->insn_read = rti800_ai_insn_read; + s->maxdata = 0x0fff; + s->range_table = (it->options[3] < ARRAY_SIZE(rti800_ai_ranges)) + ? rti800_ai_ranges[it->options[3]] + : &range_unknown; s = &dev->subdevices[1]; if (board->has_ao) { /* ao subdevice (only on rti815) */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 2; - s->insn_read = rti800_ao_insn_read; - s->insn_write = rti800_ao_insn_write; - s->maxdata = 0xfff; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 2; + s->insn_read = rti800_ao_insn_read; + s->insn_write = rti800_ao_insn_write; + s->maxdata = 0x0fff; s->range_table_list = devpriv->ao_range_type_list; - switch (devpriv->dac0_range) { - case dac_bipolar10: - devpriv->ao_range_type_list[0] = &range_bipolar10; - break; - case dac_unipolar10: - devpriv->ao_range_type_list[0] = &range_unipolar10; - break; - } - switch (devpriv->dac1_range) { - case dac_bipolar10: - devpriv->ao_range_type_list[1] = &range_bipolar10; - break; - case dac_unipolar10: - devpriv->ao_range_type_list[1] = &range_unipolar10; - break; - } + devpriv->ao_range_type_list[0] = + (it->options[5] < ARRAY_SIZE(rti800_ao_ranges)) + ? rti800_ao_ranges[it->options[5]] + : &range_unknown; + devpriv->ao_range_type_list[1] = + (it->options[7] < ARRAY_SIZE(rti800_ao_ranges)) + ? rti800_ao_ranges[it->options[7]] + : &range_unknown; } else { - s->type = COMEDI_SUBD_UNUSED; + s->type = COMEDI_SUBD_UNUSED; } s = &dev->subdevices[2]; /* di */ - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 8; - s->insn_bits = rti800_di_insn_bits; - s->maxdata = 1; - s->range_table = &range_digital; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 8; + s->insn_bits = rti800_di_insn_bits; + s->maxdata = 1; + s->range_table = &range_digital; s = &dev->subdevices[3]; /* do */ - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 8; - s->insn_bits = rti800_do_insn_bits; - s->maxdata = 1; - s->range_table = &range_digital; - -/* don't yet know how to deal with counter/timers */ -#if 0 - s = &dev->subdevices[4]; - /* do */ - s->type = COMEDI_SUBD_TIMER; -#endif + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 8; + s->insn_bits = rti800_do_insn_bits; + s->maxdata = 1; + s->range_table = &range_digital; + + /* + * There is also an Am9513 timer on these boards. This subdevice + * is not currently supported. + */ return 0; } -static void rti800_detach(struct comedi_device *dev) -{ - if (dev->iobase) - release_region(dev->iobase, RTI800_SIZE); - if (dev->irq) - free_irq(dev->irq, dev); -} - -static const struct rti800_board boardtypes[] = { - { "rti800", 0 }, - { "rti815", 1 }, -}; - static struct comedi_driver rti800_driver = { .driver_name = "rti800", .module = THIS_MODULE, .attach = rti800_attach, - .detach = rti800_detach, - .num_names = ARRAY_SIZE(boardtypes), - .board_name = &boardtypes[0].name, + .detach = comedi_legacy_detach, + .num_names = ARRAY_SIZE(rti800_boardtypes), + .board_name = &rti800_boardtypes[0].name, .offset = sizeof(struct rti800_board), }; module_comedi_driver(rti800_driver); +MODULE_DESCRIPTION("Comedi: RTI-800 Multifunction Analog/Digital board"); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c index 2185ca1bcf0..46dbbe6cdd7 100644 --- a/drivers/staging/comedi/drivers/rti802.c +++ b/drivers/staging/comedi/drivers/rti802.c @@ -92,18 +92,11 @@ static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct rti802_private *devpriv; struct comedi_subdevice *s; int i; - unsigned long iobase; int ret; - iobase = it->options[0]; - printk(KERN_INFO "comedi%d: rti802: 0x%04lx ", dev->minor, iobase); - if (!request_region(iobase, RTI802_SIZE, "rti802")) { - printk(KERN_WARNING "I/O port conflict\n"); - return -EIO; - } - dev->iobase = iobase; - - dev->board_name = "rti802"; + ret = comedi_request_region(dev, it->options[0], RTI802_SIZE); + if (ret) + return ret; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) @@ -135,17 +128,11 @@ static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it) return 0; } -static void rti802_detach(struct comedi_device *dev) -{ - if (dev->iobase) - release_region(dev->iobase, RTI802_SIZE); -} - static struct comedi_driver rti802_driver = { .driver_name = "rti802", .module = THIS_MODULE, .attach = rti802_attach, - .detach = rti802_detach, + .detach = comedi_legacy_detach, }; module_comedi_driver(rti802_driver); diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index 39232b35945..d240ce87bd6 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -552,17 +552,11 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct s526_private *devpriv; struct comedi_subdevice *s; - int iobase; int ret; - dev->board_name = dev->driver->driver_name; - - iobase = it->options[0]; - if (!iobase || !request_region(iobase, S526_IOSIZE, dev->board_name)) { - comedi_error(dev, "I/O port conflict"); - return -EIO; - } - dev->iobase = iobase; + ret = comedi_request_region(dev, it->options[0], S526_IOSIZE); + if (ret) + return ret; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) @@ -616,22 +610,14 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_bits = s526_dio_insn_bits; s->insn_config = s526_dio_insn_config; - dev_info(dev->class_dev, "%s attached\n", dev->board_name); - return 1; } -static void s526_detach(struct comedi_device *dev) -{ - if (dev->iobase > 0) - release_region(dev->iobase, S526_IOSIZE); -} - static struct comedi_driver s526_driver = { .driver_name = "s526", .module = THIS_MODULE, .attach = s526_attach, - .detach = s526_detach, + .detach = comedi_legacy_detach, }; module_comedi_driver(s526_driver); diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 81a1fe66157..0cf4b3d1279 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -80,7 +80,7 @@ INSN_CONFIG instructions: #define PCI_SUBDEVICE_ID_S626 0x0272 struct s626_private { - void __iomem *base_addr; + void __iomem *mmio; uint8_t ai_cmd_running; /* ai_cmd is running */ uint8_t ai_continous; /* continous acquisition */ int ai_sample_count; /* number of samples to acquire */ @@ -106,64 +106,6 @@ struct s626_private { unsigned int ao_readback[S626_DAC_CHANNELS]; }; -struct dio_private { - uint16_t RDDIn; - uint16_t WRDOut; - uint16_t RDEdgSel; - uint16_t WREdgSel; - uint16_t RDCapSel; - uint16_t WRCapSel; - uint16_t RDCapFlg; - uint16_t RDIntSel; - uint16_t WRIntSel; -}; - -static struct dio_private dio_private_A = { - .RDDIn = LP_RDDINA, - .WRDOut = LP_WRDOUTA, - .RDEdgSel = LP_RDEDGSELA, - .WREdgSel = LP_WREDGSELA, - .RDCapSel = LP_RDCAPSELA, - .WRCapSel = LP_WRCAPSELA, - .RDCapFlg = LP_RDCAPFLGA, - .RDIntSel = LP_RDINTSELA, - .WRIntSel = LP_WRINTSELA, -}; - -static struct dio_private dio_private_B = { - .RDDIn = LP_RDDINB, - .WRDOut = LP_WRDOUTB, - .RDEdgSel = LP_RDEDGSELB, - .WREdgSel = LP_WREDGSELB, - .RDCapSel = LP_RDCAPSELB, - .WRCapSel = LP_WRCAPSELB, - .RDCapFlg = LP_RDCAPFLGB, - .RDIntSel = LP_RDINTSELB, - .WRIntSel = LP_WRINTSELB, -}; - -static struct dio_private dio_private_C = { - .RDDIn = LP_RDDINC, - .WRDOut = LP_WRDOUTC, - .RDEdgSel = LP_RDEDGSELC, - .WREdgSel = LP_WREDGSELC, - .RDCapSel = LP_RDCAPSELC, - .WRCapSel = LP_WRCAPSELC, - .RDCapFlg = LP_RDCAPFLGC, - .RDIntSel = LP_RDINTSELC, - .WRIntSel = LP_WRINTSELC, -}; - -/* to group dio devices (48 bits mask and data are not allowed ???) -static struct dio_private *dio_private_word[]={ - &dio_private_A, - &dio_private_B, - &dio_private_C, -}; -*/ - -#define diopriv ((struct dio_private *)s->private) - /* COUNTER OBJECT ------------------------------------------------ */ struct enc_private { /* Pointers to functions that differ for A and B counters: */ @@ -195,37 +137,53 @@ struct enc_private { /* Translation table to map IntSrc into equivalent RDMISC2 event flag bits. */ /* static const uint16_t EventBits[][4] = { EVBITS(0), EVBITS(1), EVBITS(2), EVBITS(3), EVBITS(4), EVBITS(5) }; */ -/* enab/disable a function or test status bit(s) that are accessed */ -/* through Main Control Registers 1 or 2. */ -#define MC_ENABLE(REGADRS, CTRLWORD) writel(((uint32_t)(CTRLWORD) << 16) | (uint32_t)(CTRLWORD), devpriv->base_addr+(REGADRS)) +/* + * Enable/disable a function or test status bit(s) that are accessed + * through Main Control Registers 1 or 2. + */ +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; -#define MC_DISABLE(REGADRS, CTRLWORD) writel((uint32_t)(CTRLWORD) << 16 , devpriv->base_addr+(REGADRS)) + writel(val, devpriv->mmio + reg); +} -#define MC_TEST(REGADRS, CTRLWORD) ((readl(devpriv->base_addr+(REGADRS)) & CTRLWORD) != 0) +static void s626_mc_disable(struct comedi_device *dev, + unsigned int cmd, unsigned int reg) +{ + struct s626_private *devpriv = dev->private; -/* #define WR7146(REGARDS,CTRLWORD) - writel(CTRLWORD,(uint32_t)(devpriv->base_addr+(REGARDS))) */ -#define WR7146(REGARDS, CTRLWORD) writel(CTRLWORD, devpriv->base_addr+(REGARDS)) + writel(cmd << 16 , devpriv->mmio + reg); +} -/* #define RR7146(REGARDS) - readl((uint32_t)(devpriv->base_addr+(REGARDS))) */ -#define RR7146(REGARDS) readl(devpriv->base_addr+(REGARDS)) +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); + + return (val & cmd) ? true : false; +} #define BUGFIX_STREG(REGADRS) (REGADRS - 4) /* Write a time slot control record to TSL2. */ #define VECTPORT(VECTNUM) (P_TSL2 + ((VECTNUM) << 2)) -#define SETVECT(VECTNUM, VECTVAL) WR7146(VECTPORT(VECTNUM), (VECTVAL)) /* Code macros used for constructing I2C command bytes. */ #define I2C_B2(ATTR, VAL) (((ATTR) << 6) | ((VAL) << 24)) #define I2C_B1(ATTR, VAL) (((ATTR) << 4) | ((VAL) << 16)) #define I2C_B0(ATTR, VAL) (((ATTR) << 2) | ((VAL) << 8)) -static const struct comedi_lrange s626_range_table = { 2, { - RANGE(-5, 5), - RANGE(-10, 10), - } +static const struct comedi_lrange s626_range_table = { + 2, { + BIP_RANGE(5), + BIP_RANGE(10), + } }; /* Execute a DEBI transfer. This must be called from within a */ @@ -234,16 +192,18 @@ static void DEBItransfer(struct comedi_device *dev) { struct s626_private *devpriv = dev->private; - /* Initiate upload of shadow RAM to DEBI control register. */ - MC_ENABLE(P_MC2, MC2_UPLD_DEBI); + /* Initiate upload of shadow RAM to DEBI control register */ + s626_mc_enable(dev, MC2_UPLD_DEBI, P_MC2); - /* Wait for completion of upload from shadow RAM to DEBI control */ - /* register. */ - while (!MC_TEST(P_MC2, MC2_UPLD_DEBI)) + /* + * Wait for completion of upload from shadow RAM to + * DEBI control register. + */ + while (!s626_mc_test(dev, MC2_UPLD_DEBI, P_MC2)) ; - /* Wait until DEBI transfer is done. */ - while (RR7146(P_PSR) & PSR_DEBI_S) + /* Wait until DEBI transfer is done */ + while (readl(devpriv->mmio + P_PSR) & PSR_DEBI_S) ; } @@ -252,19 +212,14 @@ static void DEBItransfer(struct comedi_device *dev) static uint16_t DEBIread(struct comedi_device *dev, uint16_t addr) { struct s626_private *devpriv = dev->private; - uint16_t retval; - /* Set up DEBI control register value in shadow RAM. */ - WR7146(P_DEBICMD, DEBI_CMD_RDWORD | addr); + /* Set up DEBI control register value in shadow RAM */ + writel(DEBI_CMD_RDWORD | addr, devpriv->mmio + P_DEBICMD); /* Execute the DEBI transfer. */ DEBItransfer(dev); - /* Fetch target register value. */ - retval = (uint16_t) RR7146(P_DEBIAD); - - /* Return register value. */ - return retval; + return readl(devpriv->mmio + P_DEBIAD); } /* Write a value to a gate array register. */ @@ -272,9 +227,9 @@ static void DEBIwrite(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. */ - WR7146(P_DEBICMD, DEBI_CMD_WRWORD | addr); - WR7146(P_DEBIAD, wdata); + /* Set up DEBI control register value in shadow RAM */ + writel(DEBI_CMD_WRWORD | addr, devpriv->mmio + P_DEBICMD); + writel(wdata, devpriv->mmio + P_DEBIAD); /* Execute the DEBI transfer. */ DEBItransfer(dev); @@ -284,23 +239,22 @@ static void DEBIwrite(struct comedi_device *dev, uint16_t addr, uint16_t wdata) * specifies bits that are to be preserved, wdata is new value to be * or'd with the masked original. */ -static void DEBIreplace(struct comedi_device *dev, uint16_t addr, uint16_t mask, - uint16_t wdata) +static void DEBIreplace(struct comedi_device *dev, unsigned int addr, + unsigned int mask, unsigned int wdata) { struct s626_private *devpriv = dev->private; + unsigned int val; - /* Copy target gate array register into P_DEBIAD register. */ - WR7146(P_DEBICMD, DEBI_CMD_RDWORD | addr); - /* Set up DEBI control reg value in shadow RAM. */ - DEBItransfer(dev); /* Execute the DEBI Read transfer. */ - - /* Write back the modified image. */ - WR7146(P_DEBICMD, DEBI_CMD_WRWORD | addr); - /* Set up DEBI control reg value in shadow RAM. */ + addr &= 0xffff; + writel(DEBI_CMD_RDWORD | addr, devpriv->mmio + P_DEBICMD); + DEBItransfer(dev); - WR7146(P_DEBIAD, wdata | ((uint16_t) RR7146(P_DEBIAD) & mask)); - /* Modify the register image. */ - DEBItransfer(dev); /* Execute the DEBI Write transfer. */ + writel(DEBI_CMD_WRWORD | addr, devpriv->mmio + P_DEBICMD); + val = readl(devpriv->mmio + P_DEBIAD); + val &= mask; + val |= wdata; + writel(val & 0xffff, devpriv->mmio + P_DEBIAD); + DEBItransfer(dev); } /* ************** EEPROM ACCESS FUNCTIONS ************** */ @@ -308,31 +262,32 @@ static void DEBIreplace(struct comedi_device *dev, uint16_t addr, uint16_t mask, static uint32_t I2Chandshake(struct comedi_device *dev, uint32_t val) { struct s626_private *devpriv = dev->private; + unsigned int ctrl; - /* Write I2C command to I2C Transfer Control shadow register. */ - WR7146(P_I2CCTRL, val); - - /* Upload I2C shadow registers into working registers and wait for */ - /* upload confirmation. */ - - MC_ENABLE(P_MC2, MC2_UPLD_IIC); - while (!MC_TEST(P_MC2, MC2_UPLD_IIC)) - ; + /* Write I2C command to I2C Transfer Control shadow register */ + writel(val, devpriv->mmio + P_I2CCTRL); - /* Wait until I2C bus transfer is finished or an error occurs. */ - while ((RR7146(P_I2CCTRL) & (I2C_BUSY | I2C_ERR)) == I2C_BUSY) + /* + * Upload I2C shadow registers into working registers and + * wait for upload confirmation. + */ + s626_mc_enable(dev, MC2_UPLD_IIC, P_MC2); + while (!s626_mc_test(dev, MC2_UPLD_IIC, P_MC2)) ; - /* Return non-zero if I2C error occurred. */ - return RR7146(P_I2CCTRL) & I2C_ERR; + /* Wait until I2C bus transfer is finished or an error occurs */ + do { + ctrl = readl(devpriv->mmio + P_I2CCTRL); + } while ((ctrl & (I2C_BUSY | I2C_ERR)) == I2C_BUSY); + /* Return non-zero if I2C error occurred */ + return ctrl & I2C_ERR; } /* Read uint8_t from EEPROM. */ static uint8_t I2Cread(struct comedi_device *dev, uint8_t addr) { struct s626_private *devpriv = dev->private; - uint8_t rtnval; /* Send EEPROM target address. */ if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CW) @@ -360,9 +315,8 @@ static uint8_t I2Cread(struct comedi_device *dev, uint8_t addr) /* Abort function and declare error if handshake failed. */ return 0; } - /* Return copy of EEPROM value. */ - rtnval = (uint8_t) (RR7146(P_I2CCTRL) >> 16); - return rtnval; + + return (readl(devpriv->mmio + P_I2CCTRL) >> 16) & 0xff; } /* *********** DAC FUNCTIONS *********** */ @@ -402,23 +356,25 @@ static void SendDAC(struct comedi_device *dev, uint32_t val) /* Copy DAC setpoint value to DAC's output DMA buffer. */ - /* WR7146( (uint32_t)devpriv->pDacWBuf, val ); */ + /* writel(val, devpriv->mmio + (uint32_t)devpriv->pDacWBuf); */ *devpriv->pDacWBuf = val; - /* enab the output DMA transfer. This will cause the DMAC to copy - * the DAC's data value to A2's output FIFO. The DMA transfer will + /* + * Enable the output DMA transfer. This will cause the DMAC to copy + * the DAC's data value to A2's output FIFO. The DMA transfer will * then immediately terminate because the protection address is * reached upon transfer of the first DWORD value. */ - MC_ENABLE(P_MC1, MC1_A2OUT); + s626_mc_enable(dev, MC1_A2OUT, P_MC1); /* While the DMA transfer is executing ... */ - /* Reset Audio2 output FIFO's underflow flag (along with any other - * FIFO underflow/overflow flags). When set, this flag will - * indicate that we have emerged from slot 0. + /* + * Reset Audio2 output FIFO's underflow flag (along with any + * other FIFO underflow/overflow flags). When set, this flag + * will indicate that we have emerged from slot 0. */ - WR7146(P_ISR, ISR_AFOU); + writel(ISR_AFOU, devpriv->mmio + P_ISR); /* Wait for the DMA transfer to finish so that there will be data * available in the FIFO when time slot 1 tries to transfer a DWORD @@ -426,7 +382,7 @@ static void SendDAC(struct comedi_device *dev, uint32_t val) * Done by polling the DMAC enable flag; this flag is automatically * cleared when the transfer has finished. */ - while ((RR7146(P_MC1) & MC1_A2OUT) != 0) + while (readl(devpriv->mmio + P_MC1) & MC1_A2OUT) ; /* START THE OUTPUT STREAM TO THE TARGET DAC -------------------- */ @@ -436,7 +392,7 @@ static void SendDAC(struct comedi_device *dev, uint32_t val) * will be shifted in and stored in FB_BUFFER2 for end-of-slot-list * detection. */ - SETVECT(0, XSD2 | RSD3 | SIB_A2); + writel(XSD2 | RSD3 | SIB_A2, devpriv->mmio + VECTPORT(0)); /* Wait for slot 1 to execute to ensure that the Packet will be * transmitted. This is detected by polling the Audio2 output FIFO @@ -444,7 +400,7 @@ static void SendDAC(struct comedi_device *dev, uint32_t val) * finished transferring the DAC's data DWORD from the output FIFO * to the output buffer register. */ - while ((RR7146(P_SSR) & SSR_AF2_OUT) == 0) + while (!(readl(devpriv->mmio + P_SSR) & SSR_AF2_OUT)) ; /* Set up to trap execution at slot 0 when the TSL sequencer cycles @@ -453,7 +409,8 @@ static void SendDAC(struct comedi_device *dev, uint32_t val) * stored in the last byte to be shifted out of the FIFO's DWORD * buffer register. */ - SETVECT(0, XSD2 | XFIFO_2 | RSD2 | SIB_A2 | EOS); + writel(XSD2 | XFIFO_2 | RSD2 | SIB_A2 | EOS, + devpriv->mmio + VECTPORT(0)); /* WAIT FOR THE TRANSACTION TO FINISH ----------------------- */ @@ -474,14 +431,14 @@ static void SendDAC(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 ((RR7146(P_FB_BUFFER2) & 0xFF000000) != 0) { + if (readl(devpriv->mmio + 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 * TSL execution. This is detected when FB_BUFFER2 MSB changes * from 0xFF to 0x00, which slot 0 causes to happen by shifting * out/in on SD2 the 0x00 that is always referenced by slot 5. */ - while ((RR7146(P_FB_BUFFER2) & 0xFF000000) != 0) + while (readl(devpriv->mmio + P_FB_BUFFER2) & 0xff000000) ; } /* Either (1) we were too late setting the slot 0 trap; the TSL @@ -492,13 +449,13 @@ static void SendDAC(struct comedi_device *dev, uint32_t val) * In order to do this, we reprogram slot 0 so that it will shift in * SD3, which is driven only by a pull-up resistor. */ - SETVECT(0, RSD3 | SIB_A2 | EOS); + writel(RSD3 | SIB_A2 | EOS, devpriv->mmio + VECTPORT(0)); /* Wait for slot 0 to execute, at which time the TSL is setup for * the next DAC write. This is detected when FB_BUFFER2 MSB changes * from 0x00 to 0xFF. */ - while ((RR7146(P_FB_BUFFER2) & 0xFF000000) == 0) + while (!(readl(devpriv->mmio + P_FB_BUFFER2) & 0xff000000)) ; } @@ -532,16 +489,16 @@ static void SetDAC(struct comedi_device *dev, uint16_t chan, short dacdata) * disables gating for the DAC clock and all DAC chip selects. */ + /* Choose DAC chip select to be asserted */ WSImage = (chan & 2) ? WS1 : WS2; - /* Choose DAC chip select to be asserted. */ - SETVECT(2, XSD2 | XFIFO_1 | WSImage); - /* Slot 2: Transmit high data byte to target DAC. */ - SETVECT(3, XSD2 | XFIFO_0 | WSImage); - /* Slot 3: Transmit low data byte to target DAC. */ - SETVECT(4, XSD2 | XFIFO_3 | WS3); + /* Slot 2: Transmit high data byte to target DAC */ + writel(XSD2 | XFIFO_1 | WSImage, devpriv->mmio + VECTPORT(2)); + /* Slot 3: Transmit low data byte to target DAC */ + writel(XSD2 | XFIFO_0 | WSImage, devpriv->mmio + VECTPORT(3)); /* Slot 4: Transmit to non-existent TrimDac channel to keep clock */ - SETVECT(5, XSD2 | XFIFO_2 | WS3 | EOS); - /* Slot 5: running after writing target DAC's low data byte. */ + writel(XSD2 | XFIFO_3 | WS3, devpriv->mmio + VECTPORT(4)); + /* Slot 5: running after writing target DAC's low data byte */ + writel(XSD2 | XFIFO_2 | WS3 | EOS, devpriv->mmio + VECTPORT(5)); /* Construct and transmit target DAC's serial packet: * ( A10D DDDD ),( DDDD DDDD ),( 0x0F ),( 0x00 ) where A is chan<0>, @@ -577,14 +534,14 @@ static void WriteTrimDAC(struct comedi_device *dev, uint8_t LogicalChan, * can be detected. */ - SETVECT(2, XSD2 | XFIFO_1 | WS3); - /* Slot 2: Send high uint8_t to target TrimDac. */ - SETVECT(3, XSD2 | XFIFO_0 | WS3); - /* Slot 3: Send low uint8_t to target TrimDac. */ - SETVECT(4, XSD2 | XFIFO_3 | WS1); - /* Slot 4: Send NOP high uint8_t to DAC0 to keep clock running. */ - SETVECT(5, XSD2 | XFIFO_2 | WS1 | EOS); - /* Slot 5: Send NOP low uint8_t to DAC0. */ + /* Slot 2: Send high uint8_t to target TrimDac */ + writel(XSD2 | XFIFO_1 | WS3, devpriv->mmio + VECTPORT(2)); + /* Slot 3: Send low uint8_t to target TrimDac */ + writel(XSD2 | XFIFO_0 | WS3, devpriv->mmio + VECTPORT(3)); + /* Slot 4: Send NOP high uint8_t to DAC0 to keep clock running */ + writel(XSD2 | XFIFO_3 | WS1, devpriv->mmio + VECTPORT(4)); + /* Slot 5: Send NOP low uint8_t to DAC0 */ + writel(XSD2 | XFIFO_2 | WS1 | EOS, devpriv->mmio + VECTPORT(5)); /* Construct and transmit target DAC's serial packet: * ( 0000 AAAA ), ( DDDD DDDD ),( 0x00 ),( 0x00 ) where A<3:0> is the @@ -638,8 +595,8 @@ static void SetLatchSource(struct comedi_device *dev, struct enc_private *k, uint16_t value) { DEBIreplace(dev, k->MyCRB, - (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_LATCHSRC)), - (uint16_t) (value << CRBBIT_LATCHSRC)); + ~(CRBMSK_INTCTRL | CRBMSK_LATCHSRC), + value << CRBBIT_LATCHSRC); } /* Write value into counter preload register. */ @@ -670,43 +627,24 @@ static unsigned int s626_ai_reg_to_uint(int data) static int s626_dio_set_irq(struct comedi_device *dev, unsigned int chan) { - unsigned int group; - unsigned int bitmask; + unsigned int group = chan / 16; + unsigned int mask = 1 << (chan - (16 * group)); unsigned int status; - /* select dio bank */ - group = chan / 16; - bitmask = 1 << (chan - (16 * group)); - /* set channel to capture positive edge */ - status = DEBIread(dev, - ((struct dio_private *)(dev->subdevices + 2 + - group)->private)->RDEdgSel); - DEBIwrite(dev, - ((struct dio_private *)(dev->subdevices + 2 + - group)->private)->WREdgSel, - bitmask | status); + status = DEBIread(dev, LP_RDEDGSEL(group)); + DEBIwrite(dev, LP_WREDGSEL(group), mask | status); /* enable interrupt on selected channel */ - status = DEBIread(dev, - ((struct dio_private *)(dev->subdevices + 2 + - group)->private)->RDIntSel); - DEBIwrite(dev, - ((struct dio_private *)(dev->subdevices + 2 + - group)->private)->WRIntSel, - bitmask | status); + status = DEBIread(dev, LP_RDINTSEL(group)); + DEBIwrite(dev, LP_WRINTSEL(group), mask | status); /* enable edge capture write command */ DEBIwrite(dev, LP_MISC1, MISC1_EDCAP); /* enable edge capture on selected channel */ - status = DEBIread(dev, - ((struct dio_private *)(dev->subdevices + 2 + - group)->private)->RDCapSel); - DEBIwrite(dev, - ((struct dio_private *)(dev->subdevices + 2 + - group)->private)->WRCapSel, - bitmask | status); + status = DEBIread(dev, LP_RDCAPSEL(group)); + DEBIwrite(dev, LP_WRCAPSEL(group), mask | status); return 0; } @@ -718,9 +656,7 @@ static int s626_dio_reset_irq(struct comedi_device *dev, unsigned int group, DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP); /* enable edge capture on selected channel */ - DEBIwrite(dev, - ((struct dio_private *)(dev->subdevices + 2 + - group)->private)->WRCapSel, mask); + DEBIwrite(dev, LP_WRCAPSEL(group), mask); return 0; } @@ -732,244 +668,249 @@ static int s626_dio_clear_irq(struct comedi_device *dev) /* disable edge capture write command */ DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP); - for (group = 0; group < S626_DIO_BANKS; group++) { - /* clear pending events and interrupt */ - DEBIwrite(dev, - ((struct dio_private *)(dev->subdevices + 2 + - group)->private)->WRCapSel, - 0xffff); - } + /* clear all dio pending events and interrupt */ + for (group = 0; group < S626_DIO_BANKS; group++) + DEBIwrite(dev, LP_WRCAPSEL(group), 0xffff); return 0; } -static irqreturn_t s626_irq_handler(int irq, void *d) +static void handle_dio_interrupt(struct comedi_device *dev, + uint16_t irqbit, uint8_t group) { - struct comedi_device *dev = d; struct s626_private *devpriv = dev->private; - struct comedi_subdevice *s; - struct comedi_cmd *cmd; - struct enc_private *k; - unsigned long flags; - int32_t *readaddr; - uint32_t irqtype, irqstatus; - int i = 0; - short tempdata; - uint8_t group; - uint16_t irqbit; + struct comedi_subdevice *s = dev->read_subdev; + struct comedi_cmd *cmd = &s->async->cmd; - if (dev->attached == 0) - return IRQ_NONE; - /* lock to avoid race with comedi_poll */ - spin_lock_irqsave(&dev->spinlock, flags); + s626_dio_reset_irq(dev, group, irqbit); - /* save interrupt enable register state */ - irqstatus = readl(devpriv->base_addr + P_IER); + if (devpriv->ai_cmd_running) { + /* check if interrupt is an ai acquisition start trigger */ + if ((irqbit >> (cmd->start_arg - (16 * group))) == 1 && + cmd->start_src == TRIG_EXT) { + /* Start executing the RPS program */ + s626_mc_enable(dev, MC1_ERPS1, P_MC1); + + if (cmd->scan_begin_src == TRIG_EXT) + s626_dio_set_irq(dev, cmd->scan_begin_arg); + } + if ((irqbit >> (cmd->scan_begin_arg - (16 * group))) == 1 && + cmd->scan_begin_src == TRIG_EXT) { + /* Trigger ADC scan loop start */ + s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); - /* read interrupt type */ - irqtype = readl(devpriv->base_addr + P_ISR); + if (cmd->convert_src == TRIG_EXT) { + devpriv->ai_convert_count = cmd->chanlist_len; - /* disable master interrupt */ - writel(0, devpriv->base_addr + P_IER); + s626_dio_set_irq(dev, cmd->convert_arg); + } - /* clear interrupt */ - writel(irqtype, devpriv->base_addr + P_ISR); + if (cmd->convert_src == TRIG_TIMER) { + struct enc_private *k = &encpriv[5]; - switch (irqtype) { - case IRQ_RPS1: /* end_of_scan occurs */ - /* manage ai subdevice */ - s = dev->subdevices; - cmd = &(s->async->cmd); + devpriv->ai_convert_count = cmd->chanlist_len; + k->SetEnable(dev, k, CLKENAB_ALWAYS); + } + } + if ((irqbit >> (cmd->convert_arg - (16 * group))) == 1 && + cmd->convert_src == TRIG_EXT) { + /* Trigger ADC scan loop start */ + s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); + + devpriv->ai_convert_count--; + if (devpriv->ai_convert_count > 0) + s626_dio_set_irq(dev, cmd->convert_arg); + } + } +} - /* Init ptr to DMA buffer that holds new ADC data. We skip the - * first uint16_t in the buffer because it contains junk data from - * the final ADC of the previous poll list scan. - */ - readaddr = (int32_t *) devpriv->ANABuf.LogicalBase + 1; - - /* get the data and hand it over to comedi */ - for (i = 0; i < (s->async->cmd.chanlist_len); i++) { - /* Convert ADC data to 16-bit integer values and copy to application */ - /* buffer. */ - tempdata = s626_ai_reg_to_uint((int)*readaddr); - readaddr++; - - /* put data into read buffer */ - /* comedi_buf_put(s->async, tempdata); */ - if (cfc_write_to_buffer(s, tempdata) == 0) - printk - ("s626_irq_handler: cfc_write_to_buffer error!\n"); +static void check_dio_interrupts(struct comedi_device *dev) +{ + uint16_t irqbit; + uint8_t group; + + for (group = 0; group < S626_DIO_BANKS; group++) { + irqbit = 0; + /* read interrupt type */ + irqbit = DEBIread(dev, LP_RDCAPFLG(group)); + + /* check if interrupt is generated from dio channels */ + if (irqbit) { + handle_dio_interrupt(dev, irqbit, group); + return; } + } +} - /* end of scan occurs */ - s->async->events |= COMEDI_CB_EOS; +static void check_counter_interrupts(struct comedi_device *dev) +{ + struct s626_private *devpriv = dev->private; + struct comedi_subdevice *s = dev->read_subdev; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + struct enc_private *k; + uint16_t irqbit; - if (!(devpriv->ai_continous)) - devpriv->ai_sample_count--; - if (devpriv->ai_sample_count <= 0) { - devpriv->ai_cmd_running = 0; + /* read interrupt type */ + irqbit = DEBIread(dev, LP_RDMISC2); - /* Stop RPS program. */ - MC_DISABLE(P_MC1, MC1_ERPS1); + /* check interrupt on counters */ + if (irqbit & IRQ_COINT1A) { + k = &encpriv[0]; - /* send end of acquisition */ - s->async->events |= COMEDI_CB_EOA; + /* clear interrupt capture flag */ + k->ResetCapFlags(dev, k); + } + if (irqbit & IRQ_COINT2A) { + k = &encpriv[1]; - /* disable master interrupt */ - irqstatus = 0; - } + /* clear interrupt capture flag */ + k->ResetCapFlags(dev, k); + } + if (irqbit & IRQ_COINT3A) { + k = &encpriv[2]; - if (devpriv->ai_cmd_running && cmd->scan_begin_src == TRIG_EXT) - s626_dio_set_irq(dev, cmd->scan_begin_arg); - /* tell comedi that data is there */ - comedi_event(dev, s); - break; - case IRQ_GPIO3: /* check dio and conter interrupt */ - /* manage ai subdevice */ - s = dev->subdevices; - cmd = &(s->async->cmd); + /* clear interrupt capture flag */ + k->ResetCapFlags(dev, k); + } + if (irqbit & IRQ_COINT1B) { + k = &encpriv[3]; - /* s626_dio_clear_irq(dev); */ + /* clear interrupt capture flag */ + k->ResetCapFlags(dev, k); + } + if (irqbit & IRQ_COINT2B) { + k = &encpriv[4]; + + /* clear interrupt capture flag */ + k->ResetCapFlags(dev, k); + + if (devpriv->ai_convert_count > 0) { + devpriv->ai_convert_count--; + if (devpriv->ai_convert_count == 0) + k->SetEnable(dev, k, CLKENAB_INDEX); - for (group = 0; group < S626_DIO_BANKS; group++) { - irqbit = 0; - /* read interrupt type */ - irqbit = DEBIread(dev, - ((struct dio_private *)(dev-> - subdevices + - 2 + - group)-> - private)->RDCapFlg); - - /* check if interrupt is generated from dio channels */ - if (irqbit) { - s626_dio_reset_irq(dev, group, irqbit); - if (devpriv->ai_cmd_running) { - /* check if interrupt is an ai acquisition start trigger */ - if ((irqbit >> (cmd->start_arg - - (16 * group))) - == 1 && cmd->start_src == TRIG_EXT) { - /* Start executing the RPS program. */ - MC_ENABLE(P_MC1, MC1_ERPS1); - - if (cmd->scan_begin_src == - TRIG_EXT) { - s626_dio_set_irq(dev, - cmd->scan_begin_arg); - } - } - if ((irqbit >> (cmd->scan_begin_arg - - (16 * group))) - == 1 - && cmd->scan_begin_src == - TRIG_EXT) { - /* Trigger ADC scan loop start by setting RPS Signal 0. */ - MC_ENABLE(P_MC2, MC2_ADC_RPS); - - if (cmd->convert_src == - TRIG_EXT) { - devpriv->ai_convert_count - = cmd->chanlist_len; - - s626_dio_set_irq(dev, - cmd->convert_arg); - } - - if (cmd->convert_src == - TRIG_TIMER) { - k = &encpriv[5]; - devpriv->ai_convert_count - = cmd->chanlist_len; - k->SetEnable(dev, k, - CLKENAB_ALWAYS); - } - } - if ((irqbit >> (cmd->convert_arg - - (16 * group))) - == 1 - && cmd->convert_src == TRIG_EXT) { - /* Trigger ADC scan loop start by setting RPS Signal 0. */ - MC_ENABLE(P_MC2, MC2_ADC_RPS); - - devpriv->ai_convert_count--; - - if (devpriv->ai_convert_count > - 0) { - s626_dio_set_irq(dev, - cmd->convert_arg); - } - } - } - break; + if (cmd->convert_src == TRIG_TIMER) { + /* Trigger ADC scan loop start */ + s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); } } + } + if (irqbit & IRQ_COINT3B) { + k = &encpriv[5]; - /* read interrupt type */ - irqbit = DEBIread(dev, LP_RDMISC2); - - /* check interrupt on counters */ - if (irqbit & IRQ_COINT1A) { - k = &encpriv[0]; + /* clear interrupt capture flag */ + k->ResetCapFlags(dev, k); - /* clear interrupt capture flag */ - k->ResetCapFlags(dev, k); + if (cmd->scan_begin_src == TRIG_TIMER) { + /* Trigger ADC scan loop start */ + s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); } - if (irqbit & IRQ_COINT2A) { - k = &encpriv[1]; - /* clear interrupt capture flag */ - k->ResetCapFlags(dev, k); + if (cmd->convert_src == TRIG_TIMER) { + k = &encpriv[4]; + devpriv->ai_convert_count = cmd->chanlist_len; + k->SetEnable(dev, k, CLKENAB_ALWAYS); } - if (irqbit & IRQ_COINT3A) { - k = &encpriv[2]; + } +} - /* clear interrupt capture flag */ - k->ResetCapFlags(dev, k); - } - if (irqbit & IRQ_COINT1B) { - k = &encpriv[3]; +static bool handle_eos_interrupt(struct comedi_device *dev) +{ + struct s626_private *devpriv = dev->private; + struct comedi_subdevice *s = dev->read_subdev; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + /* + * Init ptr to DMA buffer that holds new ADC data. We skip the + * first uint16_t in the buffer because it contains junk data + * from the final ADC of the previous poll list scan. + */ + int32_t *readaddr = (int32_t *)devpriv->ANABuf.LogicalBase + 1; + bool finished = false; + int i; - /* clear interrupt capture flag */ - k->ResetCapFlags(dev, k); - } - if (irqbit & IRQ_COINT2B) { - k = &encpriv[4]; + /* get the data and hand it over to comedi */ + for (i = 0; i < cmd->chanlist_len; i++) { + short tempdata; - /* clear interrupt capture flag */ - k->ResetCapFlags(dev, k); + /* + * Convert ADC data to 16-bit integer values and copy + * to application buffer. + */ + tempdata = s626_ai_reg_to_uint((int)*readaddr); + readaddr++; - if (devpriv->ai_convert_count > 0) { - devpriv->ai_convert_count--; - if (devpriv->ai_convert_count == 0) - k->SetEnable(dev, k, CLKENAB_INDEX); + /* put data into read buffer */ + /* comedi_buf_put(async, tempdata); */ + cfc_write_to_buffer(s, tempdata); + } - if (cmd->convert_src == TRIG_TIMER) { - /* Trigger ADC scan loop start by setting RPS Signal 0. */ - MC_ENABLE(P_MC2, MC2_ADC_RPS); - } - } - } - if (irqbit & IRQ_COINT3B) { - k = &encpriv[5]; + /* end of scan occurs */ + async->events |= COMEDI_CB_EOS; - /* clear interrupt capture flag */ - k->ResetCapFlags(dev, k); + if (!devpriv->ai_continous) + devpriv->ai_sample_count--; + if (devpriv->ai_sample_count <= 0) { + devpriv->ai_cmd_running = 0; - if (cmd->scan_begin_src == TRIG_TIMER) { - /* Trigger ADC scan loop start by setting RPS Signal 0. */ - MC_ENABLE(P_MC2, MC2_ADC_RPS); - } + /* Stop RPS program */ + s626_mc_disable(dev, MC1_ERPS1, P_MC1); - if (cmd->convert_src == TRIG_TIMER) { - k = &encpriv[4]; - devpriv->ai_convert_count = cmd->chanlist_len; - k->SetEnable(dev, k, CLKENAB_ALWAYS); - } - } + /* send end of acquisition */ + async->events |= COMEDI_CB_EOA; + + /* disable master interrupt */ + finished = true; + } + + if (devpriv->ai_cmd_running && cmd->scan_begin_src == TRIG_EXT) + s626_dio_set_irq(dev, cmd->scan_begin_arg); + + /* tell comedi that data is there */ + comedi_event(dev, s); + + return finished; +} + +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; + + if (!dev->attached) + return IRQ_NONE; + /* lock to avoid race with comedi_poll */ + spin_lock_irqsave(&dev->spinlock, flags); + + /* save interrupt enable register state */ + irqstatus = readl(devpriv->mmio + P_IER); + + /* read interrupt type */ + irqtype = readl(devpriv->mmio + P_ISR); + + /* disable master interrupt */ + writel(0, devpriv->mmio + P_IER); + + /* clear interrupt */ + writel(irqtype, devpriv->mmio + P_ISR); + + switch (irqtype) { + case IRQ_RPS1: /* end_of_scan occurs */ + if (handle_eos_interrupt(dev)) + irqstatus = 0; + break; + case IRQ_GPIO3: /* check dio and conter interrupt */ + /* s626_dio_clear_irq(dev); */ + check_dio_interrupts(dev); + check_counter_interrupts(dev); + break; } /* enable interrupt */ - writel(irqstatus, devpriv->base_addr + P_IER); + writel(irqstatus, devpriv->mmio + P_IER); spin_unlock_irqrestore(&dev->spinlock, flags); return IRQ_HANDLED; @@ -988,14 +929,15 @@ static void ResetADC(struct comedi_device *dev, uint8_t *ppl) uint32_t LocalPPL; struct comedi_cmd *cmd = &(dev->subdevices->async->cmd); - /* Stop RPS program in case it is currently running. */ - MC_DISABLE(P_MC1, MC1_ERPS1); + /* Stop RPS program in case it is currently running */ + s626_mc_disable(dev, MC1_ERPS1, P_MC1); /* Set starting logical address to write RPS commands. */ pRPS = (uint32_t *) devpriv->RPSBuf.LogicalBase; - /* Initialize RPS instruction pointer. */ - WR7146(P_RPSADDR1, (uint32_t) devpriv->RPSBuf.PhysicalBase); + /* Initialize RPS instruction pointer */ + writel((uint32_t)devpriv->RPSBuf.PhysicalBase, + devpriv->mmio + P_RPSADDR1); /* Construct RPS program in RPSBuf DMA buffer */ @@ -1165,41 +1107,42 @@ static void ResetADC(struct comedi_device *dev, uint8_t *ppl) /* End of RPS program build */ } -/* TO COMPLETE, IF NECESSARY */ -static int s626_ai_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +#ifdef unused_code +static int s626_ai_rinsn(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { + struct s626_private *devpriv = dev->private; + register uint8_t i; + register int32_t *readaddr; - return -EINVAL; -} - -/* static int s626_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) */ -/* { */ -/* struct s626_private *devpriv = dev->private; */ -/* register uint8_t i; */ -/* register int32_t *readaddr; */ - -/* Trigger ADC scan loop start by setting RPS Signal 0. */ -/* MC_ENABLE( P_MC2, MC2_ADC_RPS ); */ + /* Trigger ADC scan loop start */ + s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); -/* Wait until ADC scan loop is finished (RPS Signal 0 reset). */ -/* while ( MC_TEST( P_MC2, MC2_ADC_RPS ) ); */ + /* Wait until ADC scan loop is finished (RPS Signal 0 reset) */ + while (s626_mc_test(dev, MC2_ADC_RPS, P_MC2)) + ; -/* Init ptr to DMA buffer that holds new ADC data. We skip the - * first uint16_t in the buffer because it contains junk data from - * the final ADC of the previous poll list scan. - */ -/* readaddr = (uint32_t *)devpriv->ANABuf.LogicalBase + 1; */ + /* + * Init ptr to DMA buffer that holds new ADC data. We skip the + * first uint16_t in the buffer because it contains junk data from + * the final ADC of the previous poll list scan. + */ + readaddr = (uint32_t *)devpriv->ANABuf.LogicalBase + 1; -/* Convert ADC data to 16-bit integer values and copy to application buffer. */ -/* for ( i = 0; i < devpriv->AdcItems; i++ ) { */ -/* *data = s626_ai_reg_to_uint( *readaddr++ ); */ -/* data++; */ -/* } */ + /* + * Convert ADC data to 16-bit integer values and + * copy to application buffer. + */ + for (i = 0; i < devpriv->AdcItems; i++) { + *data = s626_ai_reg_to_uint(*readaddr++); + data++; + } -/* return i; */ -/* } */ + return i; +} +#endif static int s626_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, @@ -1210,14 +1153,9 @@ static int s626_ai_insn_read(struct comedi_device *dev, uint16_t range = CR_RANGE(insn->chanspec); uint16_t AdcSpec = 0; uint32_t GpioImage; + int tmp; int n; - /* interrupt call test */ -/* writel(IRQ_GPIO3,devpriv->base_addr+P_PSR); */ - /* Writing a logical 1 into any of the RPS_PSR bits causes the - * corresponding interrupt to be generated if enabled - */ - /* Convert application's ADC specification into form * appropriate for register programming. */ @@ -1237,27 +1175,29 @@ static int s626_ai_insn_read(struct comedi_device *dev, /* Delay 10 microseconds for analog input settling. */ udelay(10); - /* Start ADC by pulsing GPIO1 low. */ - GpioImage = RR7146(P_GPIO); - /* Assert ADC Start command */ - WR7146(P_GPIO, GpioImage & ~GPIO1_HI); - /* and stretch it out. */ - WR7146(P_GPIO, GpioImage & ~GPIO1_HI); - WR7146(P_GPIO, GpioImage & ~GPIO1_HI); - /* Negate ADC Start command. */ - WR7146(P_GPIO, GpioImage | GPIO1_HI); + /* Start ADC by pulsing GPIO1 low */ + GpioImage = readl(devpriv->mmio + P_GPIO); + /* Assert ADC Start command */ + writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO); + /* and stretch it out */ + writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO); + writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO); + /* Negate ADC Start command */ + writel(GpioImage | GPIO1_HI, devpriv->mmio + P_GPIO); /* Wait for ADC to complete (GPIO2 is asserted high when */ /* ADC not busy) and for data from previous conversion to */ /* shift into FB BUFFER 1 register. */ - /* Wait for ADC done. */ - while (!(RR7146(P_PSR) & PSR_GPIO2)) + /* Wait for ADC done */ + while (!(readl(devpriv->mmio + P_PSR) & PSR_GPIO2)) ; - /* Fetch ADC data. */ - if (n != 0) - data[n - 1] = s626_ai_reg_to_uint(RR7146(P_FB_BUFFER1)); + /* Fetch ADC data */ + if (n != 0) { + tmp = readl(devpriv->mmio + P_FB_BUFFER1); + data[n - 1] = s626_ai_reg_to_uint(tmp); + } /* Allow the ADC to stabilize for 4 microseconds before * starting the next (final) conversion. This delay is @@ -1272,27 +1212,28 @@ 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. */ - GpioImage = RR7146(P_GPIO); - + GpioImage = readl(devpriv->mmio + P_GPIO); /* Assert ADC Start command */ - WR7146(P_GPIO, GpioImage & ~GPIO1_HI); - /* and stretch it out. */ - WR7146(P_GPIO, GpioImage & ~GPIO1_HI); - WR7146(P_GPIO, GpioImage & ~GPIO1_HI); - /* Negate ADC Start command. */ - WR7146(P_GPIO, GpioImage | GPIO1_HI); + writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO); + /* and stretch it out */ + writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO); + writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO); + /* Negate ADC Start command */ + writel(GpioImage | GPIO1_HI, devpriv->mmio + P_GPIO); /* Wait for the data to arrive in FB BUFFER 1 register. */ - /* Wait for ADC done. */ - while (!(RR7146(P_PSR) & PSR_GPIO2)) + /* Wait for ADC done */ + while (!(readl(devpriv->mmio + P_PSR) & PSR_GPIO2)) ; /* Fetch ADC data from audio interface's input shift register. */ - /* Fetch ADC data. */ - if (n != 0) - data[n - 1] = s626_ai_reg_to_uint(RR7146(P_FB_BUFFER1)); + /* Fetch ADC data */ + if (n != 0) { + tmp = readl(devpriv->mmio + P_FB_BUFFER1); + data[n - 1] = s626_ai_reg_to_uint(tmp); + } return n; } @@ -1317,13 +1258,11 @@ static int s626_ai_load_polllist(uint8_t *ppl, struct comedi_cmd *cmd) static int s626_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trignum) { - struct s626_private *devpriv = dev->private; - if (trignum != 0) return -EINVAL; - /* Start executing the RPS program. */ - MC_ENABLE(P_MC1, MC1_ERPS1); + /* Start executing the RPS program */ + s626_mc_enable(dev, MC1_ERPS1, P_MC1); s->async->inttrig = NULL; @@ -1407,10 +1346,10 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return -EBUSY; } /* disable interrupt */ - writel(0, devpriv->base_addr + P_IER); + writel(0, devpriv->mmio + P_IER); /* clear interrupt request */ - writel(IRQ_RPS1 | IRQ_GPIO3, devpriv->base_addr + P_ISR); + writel(IRQ_RPS1 | IRQ_GPIO3, devpriv->mmio + P_ISR); /* clear any pending interrupt */ s626_dio_clear_irq(dev); @@ -1483,7 +1422,7 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) case TRIG_NONE: /* continous acquisition */ devpriv->ai_continous = 1; - devpriv->ai_sample_count = 0; + devpriv->ai_sample_count = 1; break; } @@ -1491,11 +1430,11 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) switch (cmd->start_src) { case TRIG_NOW: - /* Trigger ADC scan loop start by setting RPS Signal 0. */ - /* MC_ENABLE( P_MC2, MC2_ADC_RPS ); */ + /* Trigger ADC scan loop start */ + /* s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); */ - /* Start executing the RPS program. */ - MC_ENABLE(P_MC1, MC1_ERPS1); + /* Start executing the RPS program */ + s626_mc_enable(dev, MC1_ERPS1, P_MC1); s->async->inttrig = NULL; break; @@ -1511,7 +1450,7 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } /* enable interrupt */ - writel(IRQ_GPIO3 | IRQ_RPS1, devpriv->base_addr + P_IER); + writel(IRQ_GPIO3 | IRQ_RPS1, devpriv->mmio + P_IER); return 0; } @@ -1628,11 +1567,11 @@ static int s626_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct s626_private *devpriv = dev->private; - /* Stop RPS program in case it is currently running. */ - MC_DISABLE(P_MC1, MC1_ERPS1); + /* Stop RPS program in case it is currently running */ + s626_mc_disable(dev, MC1_ERPS1, P_MC1); /* disable master interrupt */ - writel(0, devpriv->base_addr + P_IER); + writel(0, devpriv->mmio + P_IER); devpriv->ai_cmd_running = 0; @@ -1679,84 +1618,74 @@ static int s626_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, static void s626_dio_init(struct comedi_device *dev) { uint16_t group; - struct comedi_subdevice *s; /* Prepare to treat writes to WRCapSel as capture disables. */ DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP); /* For each group of sixteen channels ... */ for (group = 0; group < S626_DIO_BANKS; group++) { - s = dev->subdevices + 2 + group; - DEBIwrite(dev, diopriv->WRIntSel, 0); /* Disable all interrupts. */ - DEBIwrite(dev, diopriv->WRCapSel, 0xFFFF); /* Disable all event */ - /* captures. */ - DEBIwrite(dev, diopriv->WREdgSel, 0); /* Init all DIOs to */ - /* default edge */ - /* polarity. */ - DEBIwrite(dev, diopriv->WRDOut, 0); /* Program all outputs */ - /* to inactive state. */ + /* Disable all interrupts */ + DEBIwrite(dev, LP_WRINTSEL(group), 0); + /* Disable all event captures */ + DEBIwrite(dev, LP_WRCAPSEL(group), 0xffff); + /* Init all DIOs to default edge polarity */ + DEBIwrite(dev, LP_WREDGSEL(group), 0); + /* Program all outputs to inactive state */ + DEBIwrite(dev, LP_WRDOUT(group), 0); } } -/* DIO devices are slightly special. Although it is possible to - * implement the insn_read/insn_write interface, it is much more - * useful to applications if you implement the insn_bits interface. - * This allows packed reading/writing of the DIO channels. The comedi - * core can convert between insn_bits and insn_read/write */ - static int s626_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) { - /* - * The insn data consists of a mask in data[0] and the new data in - * data[1]. The mask defines which bits we are concerning about. - * The new data must be anded with the mask. Each channel - * corresponds to a bit. - */ - if (data[0]) { - /* Check if requested ports are configured for output */ - if ((s->io_bits & data[0]) != data[0]) - return -EIO; + unsigned long group = (unsigned long)s->private; + unsigned long mask = data[0]; + unsigned long bits = data[1]; - s->state &= ~data[0]; - s->state |= data[0] & data[1]; + if (mask) { + /* Check if requested channels are configured for output */ + if ((s->io_bits & mask) != mask) + return -EIO; - /* Write out the new digital output lines */ + s->state &= ~mask; + s->state |= (bits & mask); - DEBIwrite(dev, diopriv->WRDOut, s->state); + DEBIwrite(dev, LP_WRDOUT(group), s->state); } - data[1] = DEBIread(dev, diopriv->RDDIn); + data[1] = DEBIread(dev, LP_RDDIN(group)); return insn->n; } static int s626_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { + unsigned long group = (unsigned long)s->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int mask = 1 << chan; switch (data[0]) { case INSN_CONFIG_DIO_QUERY: - data[1] = - (s-> - io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT : - COMEDI_INPUT; + data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT; return insn->n; break; case COMEDI_INPUT: - s->io_bits &= ~(1 << CR_CHAN(insn->chanspec)); + s->io_bits &= ~mask; break; case COMEDI_OUTPUT: - s->io_bits |= 1 << CR_CHAN(insn->chanspec); + s->io_bits |= mask; break; default: return -EINVAL; break; } - DEBIwrite(dev, diopriv->WRDOut, s->io_bits); + DEBIwrite(dev, LP_WRDOUT(group), s->io_bits); - return 1; + return insn->n; } /* Now this function initializes the value of the counter (data[0]) @@ -1861,13 +1790,13 @@ static void CloseDMAB(struct comedi_device *dev, struct bufferDMA *pdma, static void ResetCapFlags_A(struct comedi_device *dev, struct enc_private *k) { - DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL), + DEBIreplace(dev, k->MyCRB, ~CRBMSK_INTCTRL, CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A); } static void ResetCapFlags_B(struct comedi_device *dev, struct enc_private *k) { - DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL), + DEBIreplace(dev, k->MyCRB, ~CRBMSK_INTCTRL, CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B); } @@ -2012,8 +1941,7 @@ static void SetMode_A(struct comedi_device *dev, struct enc_private *k, /* While retaining CounterB and LatchSrc configurations, program the */ /* new counter operating mode. */ DEBIreplace(dev, k->MyCRA, CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B, cra); - DEBIreplace(dev, k->MyCRB, - (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A)), crb); + DEBIreplace(dev, k->MyCRB, ~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A), crb); } static void SetMode_B(struct comedi_device *dev, struct enc_private *k, @@ -2074,8 +2002,7 @@ static void SetMode_B(struct comedi_device *dev, struct enc_private *k, /* While retaining CounterA and LatchSrc configurations, program the */ /* new counter operating mode. */ - DEBIreplace(dev, k->MyCRA, - (uint16_t) (~(CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B)), cra); + DEBIreplace(dev, k->MyCRA, ~(CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B), cra); DEBIreplace(dev, k->MyCRB, CRBMSK_CLKENAB_A | CRBMSK_LATCHSRC, crb); } @@ -2084,17 +2011,15 @@ static void SetMode_B(struct comedi_device *dev, struct enc_private *k, static void SetEnable_A(struct comedi_device *dev, struct enc_private *k, uint16_t enab) { - DEBIreplace(dev, k->MyCRB, - (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A)), - (uint16_t) (enab << CRBBIT_CLKENAB_A)); + DEBIreplace(dev, k->MyCRB, ~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A), + enab << CRBBIT_CLKENAB_A); } static void SetEnable_B(struct comedi_device *dev, struct enc_private *k, uint16_t enab) { - DEBIreplace(dev, k->MyCRB, - (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_B)), - (uint16_t) (enab << CRBBIT_CLKENAB_B)); + DEBIreplace(dev, k->MyCRB, ~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_B), + enab << CRBBIT_CLKENAB_B); } static uint16_t GetEnable_A(struct comedi_device *dev, struct enc_private *k) @@ -2123,16 +2048,15 @@ static uint16_t GetEnable_B(struct comedi_device *dev, struct enc_private *k) static void SetLoadTrig_A(struct comedi_device *dev, struct enc_private *k, uint16_t Trig) { - DEBIreplace(dev, k->MyCRA, (uint16_t) (~CRAMSK_LOADSRC_A), - (uint16_t) (Trig << CRABIT_LOADSRC_A)); + DEBIreplace(dev, k->MyCRA, ~CRAMSK_LOADSRC_A, + Trig << CRABIT_LOADSRC_A); } static void SetLoadTrig_B(struct comedi_device *dev, struct enc_private *k, uint16_t Trig) { - DEBIreplace(dev, k->MyCRB, - (uint16_t) (~(CRBMSK_LOADSRC_B | CRBMSK_INTCTRL)), - (uint16_t) (Trig << CRBBIT_LOADSRC_B)); + DEBIreplace(dev, k->MyCRB, ~(CRBMSK_LOADSRC_B | CRBMSK_INTCTRL), + Trig << CRBBIT_LOADSRC_B); } static uint16_t GetLoadTrig_A(struct comedi_device *dev, struct enc_private *k) @@ -2156,12 +2080,12 @@ static void SetIntSrc_A(struct comedi_device *dev, struct enc_private *k, struct s626_private *devpriv = dev->private; /* Reset any pending counter overflow or index captures. */ - DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL), + DEBIreplace(dev, k->MyCRB, ~CRBMSK_INTCTRL, CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A); /* Program counter interrupt source. */ DEBIreplace(dev, k->MyCRA, ~CRAMSK_INTSRC_A, - (uint16_t) (IntSource << CRABIT_INTSRC_A)); + IntSource << CRABIT_INTSRC_A); /* Update MISC2 interrupt enable mask. */ devpriv->CounterIntEnabs = @@ -2430,7 +2354,7 @@ static void s626_initialize(struct comedi_device *dev) int i; /* Enable DEBI and audio pins, enable I2C interface */ - MC_ENABLE(P_MC1, MC1_DEBI | MC1_AUDIO | MC1_I2C); + s626_mc_enable(dev, MC1_DEBI | MC1_AUDIO | MC1_I2C, P_MC1); /* * Configure DEBI operating mode @@ -2440,15 +2364,16 @@ static void s626_initialize(struct comedi_device *dev) * Set up byte lane steering * Intel-compatible local bus (DEBI never times out) */ - WR7146(P_DEBICFG, DEBI_CFG_SLAVE16 | - (DEBI_TOUT << DEBI_CFG_TOUT_BIT) | - DEBI_SWAP | DEBI_CFG_INTEL); + writel(DEBI_CFG_SLAVE16 | + (DEBI_TOUT << DEBI_CFG_TOUT_BIT) | + DEBI_SWAP | DEBI_CFG_INTEL, + devpriv->mmio + P_DEBICFG); /* Disable MMU paging */ - WR7146(P_DEBIPAGE, DEBI_PAGE_DISABLE); + writel(DEBI_PAGE_DISABLE, devpriv->mmio + P_DEBIPAGE); /* Init GPIO so that ADC Start* is negated */ - WR7146(P_GPIO, GPIO_BASE | GPIO1_HI); + writel(GPIO_BASE | GPIO1_HI, devpriv->mmio + P_GPIO); /* I2C device address for onboard eeprom (revb) */ devpriv->I2CAdrs = 0xA0; @@ -2457,9 +2382,9 @@ static void s626_initialize(struct comedi_device *dev) * Issue an I2C ABORT command to halt any I2C * operation in progress and reset BUSY flag. */ - WR7146(P_I2CSTAT, I2C_CLKSEL | I2C_ABORT); - MC_ENABLE(P_MC2, MC2_UPLD_IIC); - while ((RR7146(P_MC2) & MC2_UPLD_IIC) == 0) + writel(I2C_CLKSEL | I2C_ABORT, devpriv->mmio + P_I2CSTAT); + s626_mc_enable(dev, MC2_UPLD_IIC, P_MC2); + while (!(readl(devpriv->mmio + P_MC2) & MC2_UPLD_IIC)) ; /* @@ -2467,9 +2392,9 @@ static void s626_initialize(struct comedi_device *dev) * reg twice to reset all I2C error flags. */ for (i = 0; i < 2; i++) { - WR7146(P_I2CSTAT, I2C_CLKSEL); - MC_ENABLE(P_MC2, MC2_UPLD_IIC); - while (!MC_TEST(P_MC2, MC2_UPLD_IIC)) + writel(I2C_CLKSEL, devpriv->mmio + P_I2CSTAT); + s626_mc_enable(dev, MC2_UPLD_IIC, P_MC2); + while (!s626_mc_test(dev, MC2_UPLD_IIC, P_MC2)) ; } @@ -2479,7 +2404,7 @@ static void s626_initialize(struct comedi_device *dev) * DAC data setup times are satisfied, enable DAC serial * clock out. */ - WR7146(P_ACON2, ACON2_INIT); + writel(ACON2_INIT, devpriv->mmio + P_ACON2); /* * Set up TSL1 slot list, which is used to control the @@ -2487,22 +2412,23 @@ static void s626_initialize(struct comedi_device *dev) * SIB_A1 = store data uint8_t at next available location * in FB BUFFER1 register. */ - WR7146(P_TSL1, RSD1 | SIB_A1); - WR7146(P_TSL1 + 4, RSD1 | SIB_A1 | EOS); + writel(RSD1 | SIB_A1, devpriv->mmio + P_TSL1); + writel(RSD1 | SIB_A1 | EOS, devpriv->mmio + P_TSL1 + 4); /* Enable TSL1 slot list so that it executes all the time */ - WR7146(P_ACON1, ACON1_ADCSTART); + writel(ACON1_ADCSTART, devpriv->mmio + P_ACON1); /* * Initialize RPS registers used for ADC */ /* Physical start of RPS program */ - WR7146(P_RPSADDR1, (uint32_t)devpriv->RPSBuf.PhysicalBase); + writel((uint32_t)devpriv->RPSBuf.PhysicalBase, + devpriv->mmio + P_RPSADDR1); /* RPS program performs no explicit mem writes */ - WR7146(P_RPSPAGE1, 0); + writel(0, devpriv->mmio + P_RPSPAGE1); /* Disable RPS timeouts */ - WR7146(P_RPS1_TOUT, 0); + writel(0, devpriv->mmio + P_RPS1_TOUT); #if 0 /* @@ -2558,7 +2484,7 @@ static void s626_initialize(struct comedi_device *dev) * burst length = 1 DWORD * threshold = 1 DWORD. */ - WR7146(P_PCI_BT_A, 0); + writel(0, devpriv->mmio + P_PCI_BT_A); /* * Init Audio2's output DMA physical addresses. The protection @@ -2568,8 +2494,9 @@ static void s626_initialize(struct comedi_device *dev) */ pPhysBuf = devpriv->ANABuf.PhysicalBase + (DAC_WDMABUF_OS * sizeof(uint32_t)); - WR7146(P_BASEA2_OUT, (uint32_t) pPhysBuf); - WR7146(P_PROTA2_OUT, (uint32_t) (pPhysBuf + sizeof(uint32_t))); + writel((uint32_t)pPhysBuf, devpriv->mmio + P_BASEA2_OUT); + writel((uint32_t)(pPhysBuf + sizeof(uint32_t)), + devpriv->mmio + P_PROTA2_OUT); /* * Cache Audio2's output DMA buffer logical address. This is @@ -2584,7 +2511,7 @@ static void s626_initialize(struct comedi_device *dev) * DMAC will automatically halt and its PCI address pointer * will be reset when the protection address is reached. */ - WR7146(P_PAGEA2_OUT, 8); + writel(8, devpriv->mmio + P_PAGEA2_OUT); /* * Initialize time slot list 2 (TSL2), which is used to control @@ -2599,7 +2526,7 @@ static void s626_initialize(struct comedi_device *dev) */ /* Slot 0: Trap TSL execution, shift 0xFF into FB_BUFFER2 */ - SETVECT(0, XSD2 | RSD3 | SIB_A2 | EOS); + writel(XSD2 | RSD3 | SIB_A2 | EOS, devpriv->mmio + VECTPORT(0)); /* * Initialize slot 1, which is constant. Slot 1 causes a @@ -2611,10 +2538,10 @@ static void s626_initialize(struct comedi_device *dev) */ /* Slot 1: Fetch DWORD from Audio2's output FIFO */ - SETVECT(1, LF_A2); + writel(LF_A2, devpriv->mmio + VECTPORT(1)); /* Start DAC's audio interface (TSL2) running */ - WR7146(P_ACON1, ACON1_DACSTART); + writel(ACON1_DACSTART, devpriv->mmio + P_ACON1); /* * Init Trim DACs to calibrated values. Do it twice because the @@ -2653,9 +2580,6 @@ static void s626_initialize(struct comedi_device *dev) /* Initialize the digital I/O subsystem */ s626_dio_init(dev); - - /* enable interrupt test */ - /* writel(IRQ_GPIO3 | IRQ_RPS1, devpriv->base_addr + P_IER); */ } static int s626_auto_attach(struct comedi_device *dev, @@ -2666,28 +2590,24 @@ static int s626_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - dev->board_name = dev->driver->driver_name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; - dev->iobase = 1; /* detach needs this */ - devpriv->base_addr = ioremap(pci_resource_start(pcidev, 0), - pci_resource_len(pcidev, 0)); - if (!devpriv->base_addr) + devpriv->mmio = pci_ioremap_bar(pcidev, 0); + if (!devpriv->mmio) return -ENOMEM; /* disable master interrupt */ - writel(0, devpriv->base_addr + P_IER); + writel(0, devpriv->mmio + P_IER); /* soft reset */ - writel(MC1_SOFT_RESET, devpriv->base_addr + P_MC1); + writel(MC1_SOFT_RESET, devpriv->mmio + P_MC1); /* DMA FIXME DMA// */ @@ -2707,79 +2627,79 @@ static int s626_auto_attach(struct comedi_device *dev, if (ret) return ret; - s = dev->subdevices + 0; + s = &dev->subdevices[0]; /* analog input subdevice */ - dev->read_subdev = s; - /* we support single-ended (ground) and differential */ - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_CMD_READ; - s->n_chan = S626_ADC_CHANNELS; - s->maxdata = (0xffff >> 2); - s->range_table = &s626_range_table; - s->len_chanlist = S626_ADC_CHANNELS; - s->insn_config = s626_ai_insn_config; - s->insn_read = s626_ai_insn_read; - s->do_cmd = s626_ai_cmd; - s->do_cmdtest = s626_ai_cmdtest; - s->cancel = s626_ai_cancel; - - s = dev->subdevices + 1; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_CMD_READ; + s->n_chan = S626_ADC_CHANNELS; + s->maxdata = 0x3fff; + s->range_table = &s626_range_table; + s->len_chanlist = S626_ADC_CHANNELS; + s->insn_read = s626_ai_insn_read; + if (dev->irq) { + dev->read_subdev = s; + s->do_cmd = s626_ai_cmd; + s->do_cmdtest = s626_ai_cmdtest; + s->cancel = s626_ai_cancel; + } + + s = &dev->subdevices[1]; /* analog output subdevice */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE | SDF_READABLE; - s->n_chan = S626_DAC_CHANNELS; - s->maxdata = (0x3fff); - s->range_table = &range_bipolar10; - s->insn_write = s626_ao_winsn; - s->insn_read = s626_ao_rinsn; - - s = dev->subdevices + 2; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = S626_DAC_CHANNELS; + s->maxdata = 0x3fff; + s->range_table = &range_bipolar10; + s->insn_write = s626_ao_winsn; + s->insn_read = s626_ao_rinsn; + + s = &dev->subdevices[2]; /* digital I/O subdevice */ - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_WRITABLE | SDF_READABLE; - s->n_chan = 16; - s->maxdata = 1; - s->io_bits = 0xffff; - s->private = &dio_private_A; - s->range_table = &range_digital; - s->insn_config = s626_dio_insn_config; - s->insn_bits = s626_dio_insn_bits; - - s = dev->subdevices + 3; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = 16; + s->maxdata = 1; + s->io_bits = 0xffff; + s->private = (void *)0; /* DIO group 0 */ + s->range_table = &range_digital; + s->insn_config = s626_dio_insn_config; + s->insn_bits = s626_dio_insn_bits; + + s = &dev->subdevices[3]; /* digital I/O subdevice */ - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_WRITABLE | SDF_READABLE; - s->n_chan = 16; - s->maxdata = 1; - s->io_bits = 0xffff; - s->private = &dio_private_B; - s->range_table = &range_digital; - s->insn_config = s626_dio_insn_config; - s->insn_bits = s626_dio_insn_bits; - - s = dev->subdevices + 4; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = 16; + s->maxdata = 1; + s->io_bits = 0xffff; + s->private = (void *)1; /* DIO group 1 */ + s->range_table = &range_digital; + s->insn_config = s626_dio_insn_config; + s->insn_bits = s626_dio_insn_bits; + + s = &dev->subdevices[4]; /* digital I/O subdevice */ - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_WRITABLE | SDF_READABLE; - s->n_chan = 16; - s->maxdata = 1; - s->io_bits = 0xffff; - s->private = &dio_private_C; - s->range_table = &range_digital; - s->insn_config = s626_dio_insn_config; - s->insn_bits = s626_dio_insn_bits; - - s = dev->subdevices + 5; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = 16; + s->maxdata = 1; + s->io_bits = 0xffff; + s->private = (void *)2; /* DIO group 2 */ + s->range_table = &range_digital; + s->insn_config = s626_dio_insn_config; + s->insn_bits = s626_dio_insn_bits; + + s = &dev->subdevices[5]; /* encoder (counter) subdevice */ - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_WRITABLE | SDF_READABLE | SDF_LSAMPL; - s->n_chan = S626_ENCODER_CHANNELS; - s->private = enc_private_data; - s->insn_config = s626_enc_insn_config; - s->insn_read = s626_enc_insn_read; - s->insn_write = s626_enc_insn_write; - s->maxdata = 0xffffff; - s->range_table = &range_unknown; + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE | SDF_LSAMPL; + s->n_chan = S626_ENCODER_CHANNELS; + s->maxdata = 0xffffff; + s->private = enc_private_data; + s->range_table = &range_unknown; + s->insn_config = s626_enc_insn_config; + s->insn_read = s626_enc_insn_read; + s->insn_write = s626_enc_insn_write; s626_initialize(dev); @@ -2790,24 +2710,26 @@ static int s626_auto_attach(struct comedi_device *dev, static void s626_detach(struct comedi_device *dev) { - struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct s626_private *devpriv = dev->private; if (devpriv) { /* stop ai_command */ devpriv->ai_cmd_running = 0; - if (devpriv->base_addr) { + if (devpriv->mmio) { /* interrupt mask */ - WR7146(P_IER, 0); /* Disable master interrupt. */ - WR7146(P_ISR, IRQ_GPIO3 | IRQ_RPS1); /* Clear board's IRQ status flag. */ + /* Disable master interrupt */ + writel(0, devpriv->mmio + P_IER); + /* Clear board's IRQ status flag */ + writel(IRQ_GPIO3 | IRQ_RPS1, + devpriv->mmio + P_ISR); /* Disable the watchdog timer and battery charger. */ WriteMISC2(dev, 0); - /* Close all interfaces on 7146 device. */ - WR7146(P_MC1, MC1_SHUTDOWN); - WR7146(P_ACON1, ACON1_BASE); + /* Close all interfaces on 7146 device */ + writel(MC1_SHUTDOWN, devpriv->mmio + P_MC1); + writel(ACON1_BASE, devpriv->mmio + P_ACON1); CloseDMAB(dev, &devpriv->RPSBuf, DMABUF_SIZE); CloseDMAB(dev, &devpriv->ANABuf, DMABUF_SIZE); @@ -2815,13 +2737,10 @@ static void s626_detach(struct comedi_device *dev) if (dev->irq) free_irq(dev->irq, dev); - if (devpriv->base_addr) - iounmap(devpriv->base_addr); - } - if (pcidev) { - if (dev->iobase) - comedi_pci_disable(pcidev); + if (devpriv->mmio) + iounmap(devpriv->mmio); } + comedi_pci_disable(dev); } static struct comedi_driver s626_driver = { @@ -2832,9 +2751,9 @@ static struct comedi_driver s626_driver = { }; static int s626_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *id) { - return comedi_pci_auto_config(dev, &s626_driver); + return comedi_pci_auto_config(dev, &s626_driver, id->driver_data); } /* diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h index ff4b3a5e4e5..99cd57b092e 100644 --- a/drivers/staging/comedi/drivers/s626.h +++ b/drivers/staging/comedi/drivers/s626.h @@ -267,36 +267,17 @@ #define LP_DACPOL 0x0082 /* Write DAC polarity. */ #define LP_GSEL 0x0084 /* Write ADC gain. */ #define LP_ISEL 0x0086 /* Write ADC channel select. */ -/* Digital I/O (write only): */ -#define LP_WRINTSELA 0x0042 /* Write A interrupt enable. */ -#define LP_WREDGSELA 0x0044 /* Write A edge selection. */ -#define LP_WRCAPSELA 0x0046 /* Write A capture enable. */ -#define LP_WRDOUTA 0x0048 /* Write A digital output. */ -#define LP_WRINTSELB 0x0052 /* Write B interrupt enable. */ -#define LP_WREDGSELB 0x0054 /* Write B edge selection. */ -#define LP_WRCAPSELB 0x0056 /* Write B capture enable. */ -#define LP_WRDOUTB 0x0058 /* Write B digital output. */ -#define LP_WRINTSELC 0x0062 /* Write C interrupt enable. */ -#define LP_WREDGSELC 0x0064 /* Write C edge selection. */ -#define LP_WRCAPSELC 0x0066 /* Write C capture enable. */ -#define LP_WRDOUTC 0x0068 /* Write C digital output. */ - -/* Digital I/O (read only): */ -#define LP_RDDINA 0x0040 /* Read digital input. */ -#define LP_RDCAPFLGA 0x0048 /* Read edges captured. */ -#define LP_RDINTSELA 0x004A /* Read interrupt enable register. */ -#define LP_RDEDGSELA 0x004C /* Read edge selection register. */ -#define LP_RDCAPSELA 0x004E /* Read capture enable register. */ -#define LP_RDDINB 0x0050 /* Read digital input. */ -#define LP_RDCAPFLGB 0x0058 /* Read edges captured. */ -#define LP_RDINTSELB 0x005A /* Read interrupt enable register. */ -#define LP_RDEDGSELB 0x005C /* Read edge selection register. */ -#define LP_RDCAPSELB 0x005E /* Read capture enable register. */ -#define LP_RDDINC 0x0060 /* Read digital input. */ -#define LP_RDCAPFLGC 0x0068 /* Read edges captured. */ -#define LP_RDINTSELC 0x006A /* Read interrupt enable register. */ -#define LP_RDEDGSELC 0x006C /* Read edge selection register. */ -#define LP_RDCAPSELC 0x006E /* Read capture enable register. */ + +/* Digital I/O registers */ +#define LP_RDDIN(x) (0x0040 + (x) * 0x10) /* R: digital input */ +#define LP_WRINTSEL(x) (0x0042 + (x) * 0x10) /* W: int enable */ +#define LP_WREDGSEL(x) (0x0044 + (x) * 0x10) /* W: edge selection */ +#define LP_WRCAPSEL(x) (0x0046 + (x) * 0x10) /* W: capture enable */ +#define LP_RDCAPFLG(x) (0x0048 + (x) * 0x10) /* R: edges captured */ +#define LP_WRDOUT(x) (0x0048 + (x) * 0x10) /* W: digital output */ +#define LP_RDINTSEL(x) (0x004a + (x) * 0x10) /* R: int enable */ +#define LP_RDEDGSEL(x) (0x004c + (x) * 0x10) /* R: edge selection */ +#define LP_RDCAPSEL(x) (0x004e + (x) * 0x10) /* R: capture enable */ /* Counter Registers (read/write): */ #define LP_CR0A 0x0000 /* 0A setup register. */ @@ -661,27 +642,27 @@ /* Bit field masks for CRA and CRB. */ -#define CRAMSK_INDXSRC_B ((uint16_t)(3 << CRABIT_INDXSRC_B)) -#define CRAMSK_CLKSRC_B ((uint16_t)(3 << CRABIT_CLKSRC_B)) -#define CRAMSK_INDXPOL_A ((uint16_t)(1 << CRABIT_INDXPOL_A)) -#define CRAMSK_LOADSRC_A ((uint16_t)(3 << CRABIT_LOADSRC_A)) -#define CRAMSK_CLKMULT_A ((uint16_t)(3 << CRABIT_CLKMULT_A)) -#define CRAMSK_INTSRC_A ((uint16_t)(3 << CRABIT_INTSRC_A)) -#define CRAMSK_CLKPOL_A ((uint16_t)(3 << CRABIT_CLKPOL_A)) -#define CRAMSK_INDXSRC_A ((uint16_t)(3 << CRABIT_INDXSRC_A)) -#define CRAMSK_CLKSRC_A ((uint16_t)(3 << CRABIT_CLKSRC_A)) - -#define CRBMSK_INTRESETCMD ((uint16_t)(1 << CRBBIT_INTRESETCMD)) -#define CRBMSK_INTRESET_B ((uint16_t)(1 << CRBBIT_INTRESET_B)) -#define CRBMSK_INTRESET_A ((uint16_t)(1 << CRBBIT_INTRESET_A)) -#define CRBMSK_CLKENAB_A ((uint16_t)(1 << CRBBIT_CLKENAB_A)) -#define CRBMSK_INTSRC_B ((uint16_t)(3 << CRBBIT_INTSRC_B)) -#define CRBMSK_LATCHSRC ((uint16_t)(3 << CRBBIT_LATCHSRC)) -#define CRBMSK_LOADSRC_B ((uint16_t)(3 << CRBBIT_LOADSRC_B)) -#define CRBMSK_CLKMULT_B ((uint16_t)(3 << CRBBIT_CLKMULT_B)) -#define CRBMSK_CLKENAB_B ((uint16_t)(1 << CRBBIT_CLKENAB_B)) -#define CRBMSK_INDXPOL_B ((uint16_t)(1 << CRBBIT_INDXPOL_B)) -#define CRBMSK_CLKPOL_B ((uint16_t)(1 << CRBBIT_CLKPOL_B)) +#define CRAMSK_INDXSRC_B (3 << CRABIT_INDXSRC_B) +#define CRAMSK_CLKSRC_B (3 << CRABIT_CLKSRC_B) +#define CRAMSK_INDXPOL_A (1 << CRABIT_INDXPOL_A) +#define CRAMSK_LOADSRC_A (3 << CRABIT_LOADSRC_A) +#define CRAMSK_CLKMULT_A (3 << CRABIT_CLKMULT_A) +#define CRAMSK_INTSRC_A (3 << CRABIT_INTSRC_A) +#define CRAMSK_CLKPOL_A (3 << CRABIT_CLKPOL_A) +#define CRAMSK_INDXSRC_A (3 << CRABIT_INDXSRC_A) +#define CRAMSK_CLKSRC_A (3 << CRABIT_CLKSRC_A) + +#define CRBMSK_INTRESETCMD (1 << CRBBIT_INTRESETCMD) +#define CRBMSK_INTRESET_B (1 << CRBBIT_INTRESET_B) +#define CRBMSK_INTRESET_A (1 << CRBBIT_INTRESET_A) +#define CRBMSK_CLKENAB_A (1 << CRBBIT_CLKENAB_A) +#define CRBMSK_INTSRC_B (3 << CRBBIT_INTSRC_B) +#define CRBMSK_LATCHSRC (3 << CRBBIT_LATCHSRC) +#define CRBMSK_LOADSRC_B (3 << CRBBIT_LOADSRC_B) +#define CRBMSK_CLKMULT_B (3 << CRBBIT_CLKMULT_B) +#define CRBMSK_CLKENAB_B (1 << CRBBIT_CLKENAB_B) +#define CRBMSK_INDXPOL_B (1 << CRBBIT_INDXPOL_B) +#define CRBMSK_CLKPOL_B (1 << CRBBIT_CLKPOL_B) #define CRBMSK_INTCTRL (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A | CRBMSK_INTRESET_B) /* Interrupt reset control bits. */ @@ -699,15 +680,15 @@ /* Bit field masks for standardized SETUP structure. */ -#define STDMSK_INTSRC ((uint16_t)(3 << STDBIT_INTSRC)) -#define STDMSK_LATCHSRC ((uint16_t)(3 << STDBIT_LATCHSRC)) -#define STDMSK_LOADSRC ((uint16_t)(3 << STDBIT_LOADSRC)) -#define STDMSK_INDXSRC ((uint16_t)(1 << STDBIT_INDXSRC)) -#define STDMSK_INDXPOL ((uint16_t)(1 << STDBIT_INDXPOL)) -#define STDMSK_CLKSRC ((uint16_t)(3 << STDBIT_CLKSRC)) -#define STDMSK_CLKPOL ((uint16_t)(1 << STDBIT_CLKPOL)) -#define STDMSK_CLKMULT ((uint16_t)(3 << STDBIT_CLKMULT)) -#define STDMSK_CLKENAB ((uint16_t)(1 << STDBIT_CLKENAB)) +#define STDMSK_INTSRC (3 << STDBIT_INTSRC) +#define STDMSK_LATCHSRC (3 << STDBIT_LATCHSRC) +#define STDMSK_LOADSRC (3 << STDBIT_LOADSRC) +#define STDMSK_INDXSRC (1 << STDBIT_INDXSRC) +#define STDMSK_INDXPOL (1 << STDBIT_INDXPOL) +#define STDMSK_CLKSRC (3 << STDBIT_CLKSRC) +#define STDMSK_CLKPOL (1 << STDBIT_CLKPOL) +#define STDMSK_CLKMULT (3 << STDBIT_CLKMULT) +#define STDMSK_CLKENAB (1 << STDBIT_CLKENAB) struct bufferDMA { dma_addr_t PhysicalBase; diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index e6177b48cca..8900086374d 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -31,8 +31,6 @@ Status: in development */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include "../comedidev.h" #include <linux/delay.h> @@ -72,7 +70,40 @@ struct serial_data { unsigned long value; }; -static long tty_ioctl(struct file *f, unsigned op, unsigned long param) +/* + * The configuration serial_data.value read from the device is + * a bitmask that defines specific options of a channel: + * + * 4:0 - the channel to configure + * 7:5 - the kind of channel + * 9:8 - the command used to configure the channel + * + * The remaining bits vary in use depending on the command: + * + * BITS 15:10 - the channel bits (maxdata) + * MIN/MAX 12:10 - the units multiplier for the scale + * 13 - the sign of the scale + * 33:14 - the base value for the range + */ +#define S2002_CFG_CHAN(x) ((x) & 0x1f) +#define S2002_CFG_KIND(x) (((x) >> 5) & 0x7) +#define S2002_CFG_KIND_INVALID 0 +#define S2002_CFG_KIND_DIGITAL_IN 1 +#define S2002_CFG_KIND_DIGITAL_OUT 2 +#define S2002_CFG_KIND_ANALOG_IN 3 +#define S2002_CFG_KIND_ANALOG_OUT 4 +#define S2002_CFG_KIND_ENCODER_IN 5 +#define S2002_CFG_CMD(x) (((x) >> 8) & 0x3) +#define S2002_CFG_CMD_BITS 0 +#define S2002_CFG_CMD_MIN 1 +#define S2002_CFG_CMD_MAX 2 +#define S2002_CFG_BITS(x) (((x) >> 10) & 0x3f) +#define S2002_CFG_UNITS(x) (((x) >> 10) & 0x7) +#define S2002_CFG_SIGN(x) (((x) >> 13) & 0x1) +#define S2002_CFG_BASE(x) (((x) >> 14) & 0xfffff) + +static long serial2002_tty_ioctl(struct file *f, unsigned op, + unsigned long param) { if (f->f_op->unlocked_ioctl) return f->f_op->unlocked_ioctl(f, op, param); @@ -80,39 +111,58 @@ static long tty_ioctl(struct file *f, unsigned op, unsigned long param) return -ENOSYS; } -static int tty_write(struct file *f, unsigned char *buf, int count) +static int serial2002_tty_write(struct file *f, unsigned char *buf, int count) { + const char __user *p = (__force const char __user *)buf; int result; mm_segment_t oldfs; oldfs = get_fs(); set_fs(KERNEL_DS); f->f_pos = 0; - result = f->f_op->write(f, buf, count, &f->f_pos); + result = f->f_op->write(f, p, count, &f->f_pos); set_fs(oldfs); return result; } -#if 0 -/* - * On 2.6.26.3 this occaisonally gave me page faults, worked around by - * settings.c_cc[VMIN] = 0; settings.c_cc[VTIME] = 0 - */ -static int tty_available(struct file *f) +static int serial2002_tty_readb(struct file *f, unsigned char *buf) { - long result = 0; - mm_segment_t oldfs; + char __user *p = (__force char __user *)buf; - oldfs = get_fs(); - set_fs(KERNEL_DS); - tty_ioctl(f, FIONREAD, (unsigned long)&result); - set_fs(oldfs); - return result; + f->f_pos = 0; + return f->f_op->read(f, p, 1, &f->f_pos); +} + +static void serial2002_tty_read_poll_wait(struct file *f, int timeout) +{ + struct poll_wqueues table; + struct timeval start, now; + + do_gettimeofday(&start); + poll_initwait(&table); + while (1) { + long elapsed; + int mask; + + mask = f->f_op->poll(f, &table.pt); + if (mask & (POLLRDNORM | POLLRDBAND | POLLIN | + POLLHUP | POLLERR)) { + break; + } + do_gettimeofday(&now); + elapsed = (1000000 * (now.tv_sec - start.tv_sec) + + now.tv_usec - start.tv_usec); + if (elapsed > timeout) + break; + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(((timeout - elapsed) * HZ) / 10000); + } + poll_freewait(&table); } -#endif -static int tty_read(struct file *f, int timeout) +static int serial2002_tty_read(struct file *f, int timeout) { + unsigned char ch; int result; result = -1; @@ -122,50 +172,19 @@ static int tty_read(struct file *f, int timeout) oldfs = get_fs(); set_fs(KERNEL_DS); if (f->f_op->poll) { - struct poll_wqueues table; - struct timeval start, now; - - do_gettimeofday(&start); - poll_initwait(&table); - while (1) { - long elapsed; - int mask; - - mask = f->f_op->poll(f, &table.pt); - if (mask & (POLLRDNORM | POLLRDBAND | POLLIN | - POLLHUP | POLLERR)) { - break; - } - do_gettimeofday(&now); - elapsed = - (1000000 * (now.tv_sec - start.tv_sec) + - now.tv_usec - start.tv_usec); - if (elapsed > timeout) - break; - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(((timeout - - elapsed) * HZ) / 10000); - } - poll_freewait(&table); - { - unsigned char ch; + serial2002_tty_read_poll_wait(f, timeout); - f->f_pos = 0; - if (f->f_op->read(f, &ch, 1, &f->f_pos) == 1) - result = ch; - } + if (serial2002_tty_readb(f, &ch) == 1) + result = ch; } else { /* Device does not support poll, busy wait */ int retries = 0; while (1) { - unsigned char ch; - retries++; if (retries >= timeout) break; - f->f_pos = 0; - if (f->f_op->read(f, &ch, 1, &f->f_pos) == 1) { + if (serial2002_tty_readb(f, &ch) == 1) { result = ch; break; } @@ -177,90 +196,76 @@ static int tty_read(struct file *f, int timeout) return result; } -static void tty_setspeed(struct file *f, int speed) +static void serial2002_tty_setspeed(struct file *f, int speed) { + struct termios termios; + struct serial_struct serial; mm_segment_t oldfs; oldfs = get_fs(); set_fs(KERNEL_DS); - { - /* Set speed */ - struct termios settings; - - tty_ioctl(f, TCGETS, (unsigned long)&settings); -/* printk("Speed: %d\n", settings.c_cflag & (CBAUD | CBAUDEX)); */ - settings.c_iflag = 0; - settings.c_oflag = 0; - settings.c_lflag = 0; - settings.c_cflag = CLOCAL | CS8 | CREAD; - settings.c_cc[VMIN] = 0; - settings.c_cc[VTIME] = 0; - switch (speed) { - case 2400:{ - settings.c_cflag |= B2400; - } - break; - case 4800:{ - settings.c_cflag |= B4800; - } - break; - case 9600:{ - settings.c_cflag |= B9600; - } - break; - case 19200:{ - settings.c_cflag |= B19200; - } - break; - case 38400:{ - settings.c_cflag |= B38400; - } - break; - case 57600:{ - settings.c_cflag |= B57600; - } - break; - case 115200:{ - settings.c_cflag |= B115200; - } - break; - default:{ - settings.c_cflag |= B9600; - } - break; - } - tty_ioctl(f, TCSETS, (unsigned long)&settings); -/* printk("Speed: %d\n", settings.c_cflag & (CBAUD | CBAUDEX)); */ - } - { - /* Set low latency */ - struct serial_struct settings; - tty_ioctl(f, TIOCGSERIAL, (unsigned long)&settings); - settings.flags |= ASYNC_LOW_LATENCY; - tty_ioctl(f, TIOCSSERIAL, (unsigned long)&settings); + /* Set speed */ + serial2002_tty_ioctl(f, TCGETS, (unsigned long)&termios); + termios.c_iflag = 0; + termios.c_oflag = 0; + termios.c_lflag = 0; + termios.c_cflag = CLOCAL | CS8 | CREAD; + termios.c_cc[VMIN] = 0; + termios.c_cc[VTIME] = 0; + switch (speed) { + case 2400: + termios.c_cflag |= B2400; + break; + case 4800: + termios.c_cflag |= B4800; + break; + case 9600: + termios.c_cflag |= B9600; + break; + case 19200: + termios.c_cflag |= B19200; + break; + case 38400: + termios.c_cflag |= B38400; + break; + case 57600: + termios.c_cflag |= B57600; + break; + case 115200: + termios.c_cflag |= B115200; + break; + default: + termios.c_cflag |= B9600; + break; } + serial2002_tty_ioctl(f, TCSETS, (unsigned long)&termios); + + /* Set low latency */ + serial2002_tty_ioctl(f, TIOCGSERIAL, (unsigned long)&serial); + serial.flags |= ASYNC_LOW_LATENCY; + serial2002_tty_ioctl(f, TIOCSSERIAL, (unsigned long)&serial); set_fs(oldfs); } -static void poll_digital(struct file *f, int channel) +static void serial2002_poll_digital(struct file *f, int channel) { char cmd; cmd = 0x40 | (channel & 0x1f); - tty_write(f, &cmd, 1); + serial2002_tty_write(f, &cmd, 1); } -static void poll_channel(struct file *f, int channel) +static void serial2002_poll_channel(struct file *f, int channel) { char cmd; cmd = 0x60 | (channel & 0x1f); - tty_write(f, &cmd, 1); + serial2002_tty_write(f, &cmd, 1); } -static struct serial_data serial_read(struct file *f, int timeout) +static struct serial_data serial2002_read(struct file *f, int timeout) { struct serial_data result; int length; @@ -270,26 +275,23 @@ static struct serial_data serial_read(struct file *f, int timeout) result.value = 0; length = 0; while (1) { - int data = tty_read(f, timeout); + int data = serial2002_tty_read(f, timeout); length++; if (data < 0) { - pr_err("Failed to read serial.\n"); break; } else if (data & 0x80) { result.value = (result.value << 7) | (data & 0x7f); } else { if (length == 1) { switch ((data >> 5) & 0x03) { - case 0:{ - result.value = 0; - result.kind = is_digital; - } + case 0: + result.value = 0; + result.kind = is_digital; break; - case 1:{ - result.value = 1; - result.kind = is_digital; - } + case 1: + result.value = 1; + result.kind = is_digital; break; } } else { @@ -305,12 +307,12 @@ static struct serial_data serial_read(struct file *f, int timeout) } -static void serial_write(struct file *f, struct serial_data data) +static void serial2002_write(struct file *f, struct serial_data data) { if (data.kind == is_digital) { unsigned char ch = ((data.value << 5) & 0x20) | (data.index & 0x1f); - tty_write(f, &ch, 1); + serial2002_tty_write(f, &ch, 1); } else { unsigned char ch[6]; int i = 0; @@ -334,319 +336,250 @@ static void serial_write(struct file *f, struct serial_data data) i++; ch[i] = ((data.value << 5) & 0x60) | (data.index & 0x1f); i++; - tty_write(f, ch, i); + serial2002_tty_write(f, ch, i); } } -static int serial_2002_open(struct comedi_device *dev) +struct config_t { + short int kind; + short int bits; + int min; + int max; +}; + +static int serial2002_setup_subdevice(struct comedi_subdevice *s, + struct config_t *cfg, + struct serial2002_range_table_t *range, + unsigned char *mapping, + int kind) { - struct serial2002_private *devpriv = dev->private; - int result; - char port[20]; + const struct comedi_lrange **range_table_list = NULL; + unsigned int *maxdata_list; + int j, chan; - sprintf(port, "/dev/ttyS%d", devpriv->port); - devpriv->tty = filp_open(port, O_RDWR, 0); - if (IS_ERR(devpriv->tty)) { - result = (int)PTR_ERR(devpriv->tty); - dev_err(dev->class_dev, "file open error = %d\n", result); - } else { - struct config_t { - - short int kind; - short int bits; - int min; - int max; - }; - - struct config_t *dig_in_config; - struct config_t *dig_out_config; - struct config_t *chan_in_config; - struct config_t *chan_out_config; - int i; - - result = 0; - dig_in_config = kcalloc(32, sizeof(struct config_t), - GFP_KERNEL); - dig_out_config = kcalloc(32, sizeof(struct config_t), - GFP_KERNEL); - chan_in_config = kcalloc(32, sizeof(struct config_t), - GFP_KERNEL); - chan_out_config = kcalloc(32, sizeof(struct config_t), - GFP_KERNEL); - if (!dig_in_config || !dig_out_config - || !chan_in_config || !chan_out_config) { - result = -ENOMEM; - goto err_alloc_configs; + for (chan = 0, j = 0; j < 32; j++) { + if (cfg[j].kind == kind) + chan++; + } + s->n_chan = chan; + s->maxdata = 0; + kfree(s->maxdata_list); + maxdata_list = kmalloc(sizeof(unsigned int) * s->n_chan, GFP_KERNEL); + if (!maxdata_list) + return -ENOMEM; + s->maxdata_list = maxdata_list; + kfree(s->range_table_list); + s->range_table = NULL; + s->range_table_list = NULL; + 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); + if (!range_table_list) + return -ENOMEM; + s->range_table_list = range_table_list; + } + for (chan = 0, j = 0; j < 32; j++) { + if (cfg[j].kind == kind) { + if (mapping) + mapping[chan] = j; + if (range) { + range[j].length = 1; + range[j].range.min = cfg[j].min; + range[j].range.max = cfg[j].max; + range_table_list[chan] = + (const struct comedi_lrange *)&range[j]; + } + maxdata_list[chan] = ((long long)1 << cfg[j].bits) - 1; + chan++; } + } + return 0; +} - tty_setspeed(devpriv->tty, devpriv->speed); - poll_channel(devpriv->tty, 31); /* Start reading configuration */ - while (1) { - struct serial_data data; +static int serial2002_setup_subdevs(struct comedi_device *dev) +{ + struct serial2002_private *devpriv = dev->private; + struct config_t *di_cfg; + struct config_t *do_cfg; + struct config_t *ai_cfg; + struct config_t *ao_cfg; + struct config_t *cfg; + struct comedi_subdevice *s; + int result = 0; + int i; - data = serial_read(devpriv->tty, 1000); - if (data.kind != is_channel || data.index != 31 - || !(data.value & 0xe0)) { - break; - } else { - int command, channel, kind; - struct config_t *cur_config = NULL; - - channel = data.value & 0x1f; - kind = (data.value >> 5) & 0x7; - command = (data.value >> 8) & 0x3; - switch (kind) { - case 1:{ - cur_config = dig_in_config; - } - break; - case 2:{ - cur_config = dig_out_config; - } - break; - case 3:{ - cur_config = chan_in_config; - } - break; - case 4:{ - cur_config = chan_out_config; - } - break; - case 5:{ - cur_config = chan_in_config; - } - break; - } + /* Allocate the temporary structs to hold the configuration data */ + di_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL); + do_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL); + ai_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL); + ao_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL); + if (!di_cfg || !do_cfg || !ai_cfg || !ao_cfg) { + result = -ENOMEM; + goto err_alloc_configs; + } - if (cur_config) { - cur_config[channel].kind = kind; - switch (command) { - case 0:{ - cur_config[channel].bits - = - (data.value >> 10) & - 0x3f; - } - break; - case 1:{ - int unit, sign, min; - unit = - (data.value >> 10) & - 0x7; - sign = - (data.value >> 13) & - 0x1; - min = - (data.value >> 14) & - 0xfffff; - - switch (unit) { - case 0:{ - min = - min - * - 1000000; - } - break; - case 1:{ - min = - min - * - 1000; - } - break; - case 2:{ - min = - min - * 1; - } - break; - } - if (sign) - min = -min; - cur_config[channel].min - = min; - } - break; - case 2:{ - int unit, sign, max; - unit = - (data.value >> 10) & - 0x7; - sign = - (data.value >> 13) & - 0x1; - max = - (data.value >> 14) & - 0xfffff; - - switch (unit) { - case 0:{ - max = - max - * - 1000000; - } - break; - case 1:{ - max = - max - * - 1000; - } - break; - case 2:{ - max = - max - * 1; - } - break; - } - if (sign) - max = -max; - cur_config[channel].max - = max; - } - break; - } - } - } - } - for (i = 0; i <= 4; i++) { - /* Fill in subdev data */ - struct config_t *c; - unsigned char *mapping = NULL; - struct serial2002_range_table_t *range = NULL; - int kind = 0; - - switch (i) { - case 0:{ - c = dig_in_config; - mapping = devpriv->digital_in_mapping; - kind = 1; - } + /* Read the configuration from the connected device */ + serial2002_tty_setspeed(devpriv->tty, devpriv->speed); + serial2002_poll_channel(devpriv->tty, 31); + while (1) { + struct serial_data data; + + data = serial2002_read(devpriv->tty, 1000); + if (data.kind != is_channel || data.index != 31 || + S2002_CFG_KIND(data.value) == 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 1:{ - c = dig_out_config; - mapping = devpriv->digital_out_mapping; - kind = 2; - } + case S2002_CFG_KIND_DIGITAL_OUT: + cfg = do_cfg; break; - case 2:{ - c = chan_in_config; - mapping = devpriv->analog_in_mapping; - range = devpriv->in_range; - kind = 3; - } + case S2002_CFG_KIND_ANALOG_IN: + cfg = ai_cfg; break; - case 3:{ - c = chan_out_config; - mapping = devpriv->analog_out_mapping; - range = devpriv->out_range; - kind = 4; - } + case S2002_CFG_KIND_ANALOG_OUT: + cfg = ao_cfg; break; - case 4:{ - c = chan_in_config; - mapping = devpriv->encoder_in_mapping; - range = devpriv->in_range; - kind = 5; - } + case S2002_CFG_KIND_ENCODER_IN: + cfg = ai_cfg; break; - default:{ - c = NULL; - } + default: + cfg = NULL; break; } - if (c) { - struct comedi_subdevice *s; - const struct comedi_lrange **range_table_list = - NULL; - unsigned int *maxdata_list; - int j, chan; - - for (chan = 0, j = 0; j < 32; j++) { - if (c[j].kind == kind) - chan++; - } - s = &dev->subdevices[i]; - s->n_chan = chan; - s->maxdata = 0; - kfree(s->maxdata_list); - s->maxdata_list = maxdata_list = - kmalloc(sizeof(unsigned int) * s->n_chan, - GFP_KERNEL); - if (!s->maxdata_list) - break; /* error handled below */ - kfree(s->range_table_list); - s->range_table = NULL; - s->range_table_list = NULL; - if (kind == 1 || kind == 2) { - s->range_table = &range_digital; - } else if (range) { - s->range_table_list = range_table_list = - kmalloc(sizeof - (struct - serial2002_range_table_t) * - s->n_chan, GFP_KERNEL); - if (!s->range_table_list) - break; /* err handled below */ - } - for (chan = 0, j = 0; j < 32; j++) { - if (c[j].kind == kind) { - if (mapping) - mapping[chan] = j; - if (range) { - range[j].length = 1; - range[j].range.min = - c[j].min; - range[j].range.max = - c[j].max; - range_table_list[chan] = - (const struct - comedi_lrange *) - &range[j]; - } - maxdata_list[chan] = - ((long long)1 << c[j].bits) - - 1; - chan++; - } + if (!cfg) + continue; /* unknown kind, skip it */ + + cfg[channel].kind = S2002_CFG_KIND(data.value); + + switch (S2002_CFG_CMD(data.value)) { + 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 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; + break; } } - if (i <= 4) { - /* Failed to allocate maxdata_list or range_table_list - * for a subdevice that needed it. */ - result = -ENOMEM; - for (i = 0; i <= 4; i++) { - struct comedi_subdevice *s; - - s = &dev->subdevices[i]; - kfree(s->maxdata_list); - s->maxdata_list = NULL; - kfree(s->range_table_list); - s->range_table_list = NULL; - } + } + + /* Fill in subdevice data */ + for (i = 0; i <= 4; i++) { + unsigned char *mapping = NULL; + struct serial2002_range_table_t *range = NULL; + int kind = 0; + + s = &dev->subdevices[i]; + + switch (i) { + case 0: + cfg = di_cfg; + mapping = devpriv->digital_in_mapping; + kind = S2002_CFG_KIND_DIGITAL_IN; + break; + case 1: + cfg = do_cfg; + mapping = devpriv->digital_out_mapping; + kind = S2002_CFG_KIND_DIGITAL_OUT; + break; + case 2: + cfg = ai_cfg; + mapping = devpriv->analog_in_mapping; + range = devpriv->in_range; + kind = S2002_CFG_KIND_ANALOG_IN; + break; + case 3: + cfg = ao_cfg; + mapping = devpriv->analog_out_mapping; + range = devpriv->out_range; + kind = S2002_CFG_KIND_ANALOG_OUT; + break; + case 4: + cfg = ai_cfg; + mapping = devpriv->encoder_in_mapping; + range = devpriv->in_range; + kind = S2002_CFG_KIND_ENCODER_IN; + break; } + if (serial2002_setup_subdevice(s, cfg, range, mapping, kind)) + break; /* err handled below */ + } + if (i <= 4) { + /* + * Failed to allocate maxdata_list or range_table_list + * for a subdevice that needed it. + */ + result = -ENOMEM; + for (i = 0; i <= 4; i++) { + s = &dev->subdevices[i]; + kfree(s->maxdata_list); + s->maxdata_list = NULL; + kfree(s->range_table_list); + s->range_table_list = NULL; + } + } + err_alloc_configs: - kfree(dig_in_config); - kfree(dig_out_config); - kfree(chan_in_config); - kfree(chan_out_config); - - if (result) { - if (devpriv->tty) { - filp_close(devpriv->tty, NULL); - devpriv->tty = NULL; - } + kfree(di_cfg); + kfree(do_cfg); + kfree(ai_cfg); + kfree(ao_cfg); + + if (result) { + if (devpriv->tty) { + filp_close(devpriv->tty, NULL); + devpriv->tty = NULL; } } + + return result; +} + +static int serial2002_open(struct comedi_device *dev) +{ + struct serial2002_private *devpriv = dev->private; + int result; + char port[20]; + + sprintf(port, "/dev/ttyS%d", devpriv->port); + devpriv->tty = filp_open(port, O_RDWR, 0); + if (IS_ERR(devpriv->tty)) { + result = (int)PTR_ERR(devpriv->tty); + dev_err(dev->class_dev, "file open error = %d\n", result); + } else { + result = serial2002_setup_subdevs(dev); + } return result; } -static void serial_2002_close(struct comedi_device *dev) +static void serial2002_close(struct comedi_device *dev) { struct serial2002_private *devpriv = dev->private; @@ -654,9 +587,10 @@ static void serial_2002_close(struct comedi_device *dev) filp_close(devpriv->tty, NULL); } -static int serial2002_di_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int serial2002_di_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct serial2002_private *devpriv = dev->private; int n; @@ -666,9 +600,9 @@ static int serial2002_di_rinsn(struct comedi_device *dev, for (n = 0; n < insn->n; n++) { struct serial_data read; - poll_digital(devpriv->tty, chan); + serial2002_poll_digital(devpriv->tty, chan); while (1) { - read = serial_read(devpriv->tty, 1000); + read = serial2002_read(devpriv->tty, 1000); if (read.kind != is_digital || read.index == chan) break; } @@ -677,9 +611,10 @@ static int serial2002_di_rinsn(struct comedi_device *dev, return n; } -static int serial2002_do_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int serial2002_do_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct serial2002_private *devpriv = dev->private; int n; @@ -692,14 +627,15 @@ static int serial2002_do_winsn(struct comedi_device *dev, write.kind = is_digital; write.index = chan; write.value = data[n]; - serial_write(devpriv->tty, write); + serial2002_write(devpriv->tty, write); } return n; } -static int serial2002_ai_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int serial2002_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct serial2002_private *devpriv = dev->private; int n; @@ -709,9 +645,9 @@ static int serial2002_ai_rinsn(struct comedi_device *dev, for (n = 0; n < insn->n; n++) { struct serial_data read; - poll_channel(devpriv->tty, chan); + serial2002_poll_channel(devpriv->tty, chan); while (1) { - read = serial_read(devpriv->tty, 1000); + read = serial2002_read(devpriv->tty, 1000); if (read.kind != is_channel || read.index == chan) break; } @@ -720,9 +656,10 @@ static int serial2002_ai_rinsn(struct comedi_device *dev, return n; } -static int serial2002_ao_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int serial2002_ao_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct serial2002_private *devpriv = dev->private; int n; @@ -735,15 +672,16 @@ static int serial2002_ao_winsn(struct comedi_device *dev, write.kind = is_channel; write.index = chan; write.value = data[n]; - serial_write(devpriv->tty, write); + serial2002_write(devpriv->tty, write); devpriv->ao_readback[chan] = data[n]; } return n; } -static int serial2002_ao_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int serial2002_ao_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct serial2002_private *devpriv = dev->private; int n; @@ -755,9 +693,10 @@ static int serial2002_ao_rinsn(struct comedi_device *dev, return n; } -static int serial2002_ei_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int serial2002_encoder_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct serial2002_private *devpriv = dev->private; int n; @@ -767,9 +706,9 @@ static int serial2002_ei_rinsn(struct comedi_device *dev, for (n = 0; n < insn->n; n++) { struct serial_data read; - poll_channel(devpriv->tty, chan); + serial2002_poll_channel(devpriv->tty, chan); while (1) { - read = serial_read(devpriv->tty, 1000); + read = serial2002_read(devpriv->tty, 1000); if (read.kind != is_channel || read.index == chan) break; } @@ -785,20 +724,13 @@ static int serial2002_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - dev_dbg(dev->class_dev, "serial2002: attach\n"); - dev->board_name = dev->driver->driver_name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - dev->open = serial_2002_open; - dev->close = serial_2002_close; devpriv->port = it->options[0]; devpriv->speed = it->options[1]; - dev_dbg(dev->class_dev, "/dev/ttyS%d @ %d\n", devpriv->port, - devpriv->speed); ret = comedi_alloc_subdevices(dev, 5); if (ret) @@ -806,51 +738,54 @@ static int serial2002_attach(struct comedi_device *dev, /* digital input subdevice */ s = &dev->subdevices[0]; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 0; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_read = &serial2002_di_rinsn; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 0; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_read = serial2002_di_insn_read; /* digital output subdevice */ s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITEABLE; - s->n_chan = 0; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_write = &serial2002_do_winsn; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITEABLE; + s->n_chan = 0; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_write = serial2002_do_insn_write; /* analog input subdevice */ s = &dev->subdevices[2]; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND; - s->n_chan = 0; - s->maxdata = 1; - s->range_table = NULL; - s->insn_read = &serial2002_ai_rinsn; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND; + s->n_chan = 0; + s->maxdata = 1; + s->range_table = NULL; + s->insn_read = serial2002_ai_insn_read; /* analog output subdevice */ s = &dev->subdevices[3]; - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITEABLE; - s->n_chan = 0; - s->maxdata = 1; - s->range_table = NULL; - s->insn_write = &serial2002_ao_winsn; - s->insn_read = &serial2002_ao_rinsn; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITEABLE; + s->n_chan = 0; + s->maxdata = 1; + s->range_table = NULL; + s->insn_write = serial2002_ao_insn_write; + s->insn_read = serial2002_ao_insn_read; /* encoder input subdevice */ s = &dev->subdevices[4]; - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_READABLE | SDF_LSAMPL; - s->n_chan = 0; - s->maxdata = 1; - s->range_table = NULL; - s->insn_read = &serial2002_ei_rinsn; + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_READABLE | SDF_LSAMPL; + s->n_chan = 0; + s->maxdata = 1; + s->range_table = NULL; + s->insn_read = serial2002_encoder_insn_read; + + dev->open = serial2002_open; + dev->close = serial2002_close; - return 1; + return 0; } static void serial2002_detach(struct comedi_device *dev) @@ -858,7 +793,7 @@ static void serial2002_detach(struct comedi_device *dev) struct comedi_subdevice *s; int i; - for (i = 0; i < 5; i++) { + for (i = 0; i < dev->n_subdevices; i++) { s = &dev->subdevices[i]; kfree(s->maxdata_list); kfree(s->range_table_list); diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c index cb83f6ae48b..dbc8c54d6da 100644 --- a/drivers/staging/comedi/drivers/skel.c +++ b/drivers/staging/comedi/drivers/skel.c @@ -90,29 +90,30 @@ Configuration Options: * boards in this way is optional, and completely driver-dependent. * Some drivers use arrays such as this, other do not. */ +enum skel_boardid { + BOARD_SKEL100, + BOARD_SKEL200, +}; + struct skel_board { const char *name; - unsigned int devid; int ai_chans; int ai_bits; int have_dio; }; static const struct skel_board skel_boards[] = { - { - .name = "skel-100", - .devid = 0x100, - .ai_chans = 16, - .ai_bits = 12, - .have_dio = 1, - }, - { - .name = "skel-200", - .devid = 0x200, - .ai_chans = 8, - .ai_bits = 16, - .have_dio = 0, - }, + [BOARD_SKEL100] = { + .name = "skel-100", + .ai_chans = 16, + .ai_bits = 12, + .have_dio = 1, + }, + [BOARD_SKEL200] = { + .name = "skel-200", + .ai_chans = 8, + .ai_bits = 16, + }, }; /* this structure is for data unique to this hardware driver. If @@ -394,22 +395,6 @@ static int skel_dio_insn_config(struct comedi_device *dev, return insn->n; } -static const struct skel_board *skel_find_pci_board(struct pci_dev *pcidev) -{ - unsigned int i; - -/* - * This example code assumes all the entries in skel_boards[] are PCI boards - * and all use the same PCI vendor ID. If skel_boards[] contains a mixture - * of PCI and non-PCI boards, this loop should skip over the non-PCI boards. - */ - for (i = 0; i < ARRAY_SIZE(skel_boards); i++) - if (/* skel_boards[i].bustype == pci_bustype && */ - pcidev->device == skel_boards[i].devid) - return &skel_boards[i]; - return NULL; -} - /* * Handle common part of skel_attach() and skel_auto_attach(). */ @@ -496,10 +481,12 @@ static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it) thisboard = comedi_board(dev); -/* - * Initialize dev->board_name. - */ - dev->board_name = thisboard->name; + /* + * The dev->board_name is initialized by the comedi core before + * calling the (*attach) function. It can be optionally set by + * the driver if additional probing has been done. + */ + /* dev->board_name = thisboard->name; */ /* Allocate the private data */ devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); @@ -541,16 +528,13 @@ static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it) * comedi_usb_auto_config(), etc.) to handle devices that can be attached * to the Comedi core automatically without the COMEDI_DEVCONFIG ioctl. * - * The context parameter is usually unused, but if the driver called - * comedi_auto_config() directly instead of the comedi_pci_auto_config() - * wrapper function, this will be a copy of the context passed to - * comedi_auto_config(). + * The context parameter is driver dependent. */ static int skel_auto_attach(struct comedi_device *dev, - unsigned long context) + unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct skel_board *thisboard; + const struct skel_board *thisboard = NULL; struct skel_private *devpriv; int ret; @@ -558,12 +542,18 @@ static int skel_auto_attach(struct comedi_device *dev, if (!IS_ENABLED(CONFIG_COMEDI_PCI_DRIVERS)) return -EINVAL; - /* Find a matching board in skel_boards[]. */ - thisboard = skel_find_pci_board(pcidev); - if (!thisboard) { - dev_err(dev->class_dev, "BUG! cannot determine board type!\n"); - return -EINVAL; - } + /* + * In this example, the _auto_attach is for a PCI device. + * + * The 'context' passed to this function is the id->driver_data + * associated with the PCI device found in the id_table during + * the modprobe. This 'context' is the index of the entry in + * skel_boards[i] that contains the boardinfo for the PCI device. + */ + if (context < ARRAY_SIZE(skel_boards)) + thisboard = &skel_boards[context]; + if (!thisboard) + return -ENODEV; /* * Point the struct comedi_device to the matching board info @@ -579,7 +569,7 @@ static int skel_auto_attach(struct comedi_device *dev, dev->private = devpriv; /* Enable the PCI device. */ - ret = comedi_pci_enable(pcidev, dev->board_name); + ret = comedi_pci_enable(dev); if (ret) return ret; @@ -618,7 +608,6 @@ static void skel_detach(struct comedi_device *dev) { const struct skel_board *thisboard = comedi_board(dev); struct skel_private *devpriv = dev->private; - struct pci_dev *pcidev = comedi_to_pci_dev(dev); if (!thisboard || !devpriv) return; @@ -638,17 +627,17 @@ static void skel_detach(struct comedi_device *dev) * If PCI device enabled by _auto_attach() (or _attach()), * disable it here. */ - if (pcidev && dev->iobase) - comedi_pci_disable(pcidev); + comedi_pci_disable(dev); } else { /* * ISA board * - * If I/O regions successfully requested by _attach(), - * release them here. + * Release the first I/O region requested during the + * _attach(). This is safe to call even if the request + * failed. If any additional I/O regions are requested + * they need to be released by the driver. */ - if (dev->iobase) - release_region(dev->iobase, SKEL_SIZE); + comedi_legacy_detach(dev); } } @@ -689,28 +678,33 @@ static struct comedi_driver skel_driver = { #ifdef CONFIG_COMEDI_PCI_DRIVERS -/* This is used by modprobe to translate PCI IDs to drivers. Should - * only be used for PCI and ISA-PnP devices */ -/* Please add your PCI vendor ID to comedidev.h, and it will be forwarded - * upstream. */ -#define PCI_VENDOR_ID_SKEL 0xdafe +static int skel_pci_probe(struct pci_dev *dev, + const struct pci_device_id *id) +{ + return comedi_pci_auto_config(dev, &skel_driver, id->driver_data); +} + +/* + * Please add your PCI vendor ID to comedidev.h, and it will + * be forwarded upstream. + */ +#define PCI_VENDOR_ID_SKEL 0xdafe + +/* + * This is used by modprobe to translate PCI IDs to drivers. + * Should only be used for PCI and ISA-PnP devices + */ static DEFINE_PCI_DEVICE_TABLE(skel_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_SKEL, 0x0100) }, - { PCI_DEVICE(PCI_VENDOR_ID_SKEL, 0x0200) }, + { PCI_VDEVICE(SKEL, 0x0100), BOARD_SKEL100 }, + { PCI_VDEVICE(SKEL, 0x0200), BOARD_SKEL200 }, { 0 } }; MODULE_DEVICE_TABLE(pci, skel_pci_table); -static int skel_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) -{ - return comedi_pci_auto_config(dev, &skel_driver); -} - static struct pci_driver skel_pci_driver = { - .name = "dummy", - .id_table = skel_pci_table, - .probe = &skel_pci_probe, + .name = "dummy", + .id_table = skel_pci_table, + .probe = skel_pci_probe, .remove = comedi_pci_auto_unconfig, }; module_comedi_pci_driver(skel_driver, skel_pci_driver); diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c index afa4016f906..a76df092a57 100644 --- a/drivers/staging/comedi/drivers/ssv_dnp.c +++ b/drivers/staging/comedi/drivers/ssv_dnp.c @@ -167,8 +167,6 @@ static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; int ret; - dev->board_name = dev->driver->driver_name; - ret = comedi_alloc_subdevices(dev, 1); if (ret) return ret; diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c index 74b974bf103..0c243477cbe 100644 --- a/drivers/staging/comedi/drivers/unioxx5.c +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -367,24 +367,24 @@ static int unioxx5_insn_config(struct comedi_device *dev, } /* initializing subdevice with given address */ -static int __unioxx5_subdev_init(struct comedi_subdevice *subdev, - int subdev_iobase, int minor) +static int __unioxx5_subdev_init(struct comedi_device *dev, + struct comedi_subdevice *s, + int iobase) { struct unioxx5_subd_priv *usp; int i, to, ndef_flag = 0; - - if (!request_region(subdev_iobase, UNIOXX5_SIZE, DRIVER_NAME)) { - dev_err(subdev->class_dev, - "comedi%d: I/O port conflict\n", minor); - return -EIO; - } + int ret; usp = kzalloc(sizeof(*usp), GFP_KERNEL); if (usp == NULL) - return -1; + return -ENOMEM; - usp->usp_iobase = subdev_iobase; - dev_info(subdev->class_dev, "comedi%d: |", minor); + ret = __comedi_request_region(dev, iobase, UNIOXX5_SIZE); + if (ret) { + kfree(usp); + return ret; + } + usp->usp_iobase = iobase; /* defining modules types */ for (i = 0; i < 12; i++) { @@ -392,14 +392,14 @@ static int __unioxx5_subdev_init(struct comedi_subdevice *subdev, __unioxx5_analog_config(usp, i * 2); /* sends channel number to card */ - outb(i + 1, subdev_iobase + 5); - outb('H', subdev_iobase + 6); /* requests EEPROM world */ - while (!(inb(subdev_iobase + 0) & TxBE)) + outb(i + 1, iobase + 5); + outb('H', iobase + 6); /* requests EEPROM world */ + while (!(inb(iobase + 0) & TxBE)) ; /* waits while writting will be allowed */ - outb(0, subdev_iobase + 6); + outb(0, iobase + 6); /* waits while reading of two bytes will be allowed */ - while (!(inb(subdev_iobase + 0) & Rx2CA)) { + while (!(inb(iobase + 0) & Rx2CA)) { if (--to <= 0) { ndef_flag = 1; break; @@ -410,25 +410,22 @@ static int __unioxx5_subdev_init(struct comedi_subdevice *subdev, usp->usp_module_type[i] = 0; ndef_flag = 0; } else - usp->usp_module_type[i] = inb(subdev_iobase + 6); + usp->usp_module_type[i] = inb(iobase + 6); - printk(" [%d] 0x%02x |", i, usp->usp_module_type[i]); udelay(1); } - printk("\n"); - /* initial subdevice for digital or analog i/o */ - subdev->type = COMEDI_SUBD_DIO; - subdev->private = usp; - subdev->subdev_flags = SDF_READABLE | SDF_WRITABLE; - subdev->n_chan = UNIOXX5_NUM_OF_CHANS; - subdev->maxdata = 0xFFF; - subdev->range_table = &range_digital; - subdev->insn_read = unioxx5_subdev_read; - subdev->insn_write = unioxx5_subdev_write; + s->type = COMEDI_SUBD_DIO; + s->private = usp; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = UNIOXX5_NUM_OF_CHANS; + s->maxdata = 0xFFF; + s->range_table = &range_digital; + s->insn_read = unioxx5_subdev_read; + s->insn_write = unioxx5_subdev_write; /* for digital modules only!!! */ - subdev->insn_config = unioxx5_insn_config; + s->insn_config = unioxx5_insn_config; return 0; } @@ -436,13 +433,13 @@ static int __unioxx5_subdev_init(struct comedi_subdevice *subdev, static int unioxx5_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + struct comedi_subdevice *s; int iobase, i, n_subd; int id, num, ba; int ret; iobase = it->options[0]; - dev->board_name = DRIVER_NAME; dev->iobase = iobase; iobase += UNIOXX5_SUBDEV_BASE; @@ -470,9 +467,10 @@ static int unioxx5_attach(struct comedi_device *dev, /* initializing each of for same subdevices */ for (i = 0; i < n_subd; i++, iobase += UNIOXX5_SUBDEV_ODDS) { - if (__unioxx5_subdev_init(&dev->subdevices[i], iobase, - dev->minor) < 0) - return -1; + s = &dev->subdevices[i]; + ret = __unioxx5_subdev_init(dev, s, iobase); + if (ret) + return ret; } return 0; diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 1a0062a0445..6f5da67e26c 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -56,7 +56,7 @@ sampling rate. If you sample two channels you get 4kHz and so on. * functions firmware upload is by fxload and no longer by comedi (due to * enumeration) * 0.97: USB IDs received, adjusted table - * 0.98: SMP, locking, memroy alloc: moved all usb memory alloc + * 0.98: SMP, locking, memory alloc: moved all usb memory alloc * to the usb subsystem and moved all comedi related memory * alloc to comedi. * | kernel | registration | usbdux-usb | usbdux-comedi | comedi | @@ -250,26 +250,26 @@ struct usbduxsub { /* pointer to the usb-device */ struct usb_device *usbdev; /* actual number of in-buffers */ - int numOfInBuffers; + int num_in_buffers; /* actual number of out-buffers */ - int numOfOutBuffers; + int num_out_buffers; /* ISO-transfer handling: buffers */ - struct urb **urbIn; - struct urb **urbOut; + struct urb **urb_in; + struct urb **urb_out; /* pwm-transfer handling */ - struct urb *urbPwm; + struct urb *urb_pwm; /* PWM period */ - unsigned int pwmPeriod; + unsigned int pwm_period; /* PWM internal delay for the GPIF in the FX2 */ - int8_t pwmDelay; + int8_t pwn_delay; /* size of the PWM buffer which holds the bit pattern */ - int sizePwmBuf; + int size_pwm_buf; /* input buffer for the ISO-transfer */ - int16_t *inBuffer; + int16_t *in_buffer; /* input buffer for single insn */ - int16_t *insnBuffer; + int16_t *insn_buffer; /* output buffer for single DA outputs */ - int16_t *outBuffer; + int16_t *out_buffer; /* interface number */ int ifnum; /* interface structure in 2.6 */ @@ -319,17 +319,17 @@ static DEFINE_SEMAPHORE(start_stop_sem); * Stops the data acquision * It should be safe to call this function from any context */ -static int usbduxsub_unlink_InURBs(struct usbduxsub *usbduxsub_tmp) +static int usbduxsub_unlink_inurbs(struct usbduxsub *usbduxsub_tmp) { int i = 0; int err = 0; - if (usbduxsub_tmp && usbduxsub_tmp->urbIn) { - for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) { - if (usbduxsub_tmp->urbIn[i]) { + if (usbduxsub_tmp && usbduxsub_tmp->urb_in) { + for (i = 0; i < usbduxsub_tmp->num_in_buffers; i++) { + if (usbduxsub_tmp->urb_in[i]) { /* We wait here until all transfers have been * cancelled. */ - usb_kill_urb(usbduxsub_tmp->urbIn[i]); + usb_kill_urb(usbduxsub_tmp->urb_in[i]); } dev_dbg(&usbduxsub_tmp->interface->dev, "comedi: usbdux: unlinked InURB %d, err=%d\n", @@ -356,7 +356,7 @@ static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink) if (do_unlink) { /* stop aquistion */ - ret = usbduxsub_unlink_InURBs(this_usbduxsub); + ret = usbduxsub_unlink_inurbs(this_usbduxsub); } this_usbduxsub->ai_cmd_running = 0; @@ -394,7 +394,7 @@ static int usbdux_ai_cancel(struct comedi_device *dev, } /* analogue IN - interrupt service routine */ -static void usbduxsub_ai_IsocIrq(struct urb *urb) +static void usbduxsub_ai_isoc_irq(struct urb *urb) { int i, err, n; struct usbduxsub *this_usbduxsub; @@ -412,7 +412,7 @@ static void usbduxsub_ai_IsocIrq(struct urb *urb) switch (urb->status) { case 0: /* copy the result in the transfer buffer */ - memcpy(this_usbduxsub->inBuffer, + memcpy(this_usbduxsub->in_buffer, urb->transfer_buffer, SIZEINBUF); break; case -EILSEQ: @@ -517,11 +517,11 @@ static void usbduxsub_ai_IsocIrq(struct urb *urb) if (CR_RANGE(s->async->cmd.chanlist[i]) <= 1) { err = comedi_buf_put (s->async, - le16_to_cpu(this_usbduxsub->inBuffer[i]) ^ 0x800); + le16_to_cpu(this_usbduxsub->in_buffer[i]) ^ 0x800); } else { err = comedi_buf_put (s->async, - le16_to_cpu(this_usbduxsub->inBuffer[i])); + le16_to_cpu(this_usbduxsub->in_buffer[i])); } if (unlikely(err == 0)) { /* buffer overflow */ @@ -534,15 +534,15 @@ static void usbduxsub_ai_IsocIrq(struct urb *urb) comedi_event(this_usbduxsub->comedidev, s); } -static int usbduxsub_unlink_OutURBs(struct usbduxsub *usbduxsub_tmp) +static int usbduxsub_unlink_outurbs(struct usbduxsub *usbduxsub_tmp) { int i = 0; int err = 0; - if (usbduxsub_tmp && usbduxsub_tmp->urbOut) { - for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) { - if (usbduxsub_tmp->urbOut[i]) - usb_kill_urb(usbduxsub_tmp->urbOut[i]); + if (usbduxsub_tmp && usbduxsub_tmp->urb_out) { + for (i = 0; i < usbduxsub_tmp->num_out_buffers; i++) { + if (usbduxsub_tmp->urb_out[i]) + usb_kill_urb(usbduxsub_tmp->urb_out[i]); dev_dbg(&usbduxsub_tmp->interface->dev, "comedi: usbdux: unlinked OutURB %d: res=%d\n", @@ -564,7 +564,7 @@ static int usbdux_ao_stop(struct usbduxsub *this_usbduxsub, int do_unlink) dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ao_cancel\n"); if (do_unlink) - ret = usbduxsub_unlink_OutURBs(this_usbduxsub); + ret = usbduxsub_unlink_outurbs(this_usbduxsub); this_usbduxsub->ao_cmd_running = 0; @@ -593,7 +593,7 @@ static int usbdux_ao_cancel(struct comedi_device *dev, return res; } -static void usbduxsub_ao_IsocIrq(struct urb *urb) +static void usbduxsub_ao_isoc_irq(struct urb *urb) { int i, ret; int8_t *datap; @@ -730,10 +730,14 @@ static void usbduxsub_ao_IsocIrq(struct urb *urb) static int usbduxsub_start(struct usbduxsub *usbduxsub) { int errcode = 0; - uint8_t local_transfer_buffer[16]; + uint8_t *local_transfer_buffer; + + local_transfer_buffer = kmalloc(1, GFP_KERNEL); + if (!local_transfer_buffer) + return -ENOMEM; /* 7f92 to zero */ - local_transfer_buffer[0] = 0; + *local_transfer_buffer = 0; errcode = usb_control_msg(usbduxsub->usbdev, /* create a pipe for a control transfer */ usb_sndctrlpipe(usbduxsub->usbdev, 0), @@ -751,22 +755,25 @@ static int usbduxsub_start(struct usbduxsub *usbduxsub) 1, /* Timeout */ BULK_TIMEOUT); - if (errcode < 0) { + if (errcode < 0) dev_err(&usbduxsub->interface->dev, "comedi_: control msg failed (start)\n"); - return errcode; - } - return 0; + + kfree(local_transfer_buffer); + return errcode; } static int usbduxsub_stop(struct usbduxsub *usbduxsub) { int errcode = 0; + uint8_t *local_transfer_buffer; - uint8_t local_transfer_buffer[16]; + local_transfer_buffer = kmalloc(1, GFP_KERNEL); + if (!local_transfer_buffer) + return -ENOMEM; /* 7f92 to one */ - local_transfer_buffer[0] = 1; + *local_transfer_buffer = 1; errcode = usb_control_msg(usbduxsub->usbdev, usb_sndctrlpipe(usbduxsub->usbdev, 0), /* bRequest, "Firmware" */ @@ -781,17 +788,17 @@ static int usbduxsub_stop(struct usbduxsub *usbduxsub) 1, /* Timeout */ BULK_TIMEOUT); - if (errcode < 0) { + if (errcode < 0) dev_err(&usbduxsub->interface->dev, "comedi_: control msg failed (stop)\n"); - return errcode; - } - return 0; + + kfree(local_transfer_buffer); + return errcode; } static int usbduxsub_upload(struct usbduxsub *usbduxsub, uint8_t *local_transfer_buffer, - unsigned int startAddr, unsigned int len) + unsigned int start_addr, unsigned int len) { int errcode; @@ -802,7 +809,7 @@ static int usbduxsub_upload(struct usbduxsub *usbduxsub, /* bmRequestType */ VENDOR_DIR_OUT, /* value */ - startAddr, + start_addr, /* index */ 0x0000, /* our local safe buffer */ @@ -821,24 +828,24 @@ static int usbduxsub_upload(struct usbduxsub *usbduxsub, #define FIRMWARE_MAX_LEN 0x2000 -static int firmwareUpload(struct usbduxsub *usbduxsub, - const u8 *firmwareBinary, int sizeFirmware) +static int firmware_upload(struct usbduxsub *usbduxsub, + const u8 *firmware_binary, int size_firmware) { int ret; - uint8_t *fwBuf; + uint8_t *fw_buf; - if (!firmwareBinary) + if (!firmware_binary) return 0; - if (sizeFirmware > FIRMWARE_MAX_LEN) { + if (size_firmware > FIRMWARE_MAX_LEN) { dev_err(&usbduxsub->interface->dev, "usbdux firmware binary it too large for FX2.\n"); return -ENOMEM; } /* we generate a local buffer for the firmware */ - fwBuf = kmemdup(firmwareBinary, sizeFirmware, GFP_KERNEL); - if (!fwBuf) { + fw_buf = kmemdup(firmware_binary, size_firmware, GFP_KERNEL); + if (!fw_buf) { dev_err(&usbduxsub->interface->dev, "comedi_: mem alloc for firmware failed\n"); return -ENOMEM; @@ -848,81 +855,81 @@ static int firmwareUpload(struct usbduxsub *usbduxsub, if (ret < 0) { dev_err(&usbduxsub->interface->dev, "comedi_: can not stop firmware\n"); - kfree(fwBuf); + kfree(fw_buf); return ret; } - ret = usbduxsub_upload(usbduxsub, fwBuf, 0, sizeFirmware); + ret = usbduxsub_upload(usbduxsub, fw_buf, 0, size_firmware); if (ret < 0) { dev_err(&usbduxsub->interface->dev, "comedi_: firmware upload failed\n"); - kfree(fwBuf); + kfree(fw_buf); return ret; } ret = usbduxsub_start(usbduxsub); if (ret < 0) { dev_err(&usbduxsub->interface->dev, "comedi_: can not start firmware\n"); - kfree(fwBuf); + kfree(fw_buf); return ret; } - kfree(fwBuf); + kfree(fw_buf); return 0; } -static int usbduxsub_submit_InURBs(struct usbduxsub *usbduxsub) +static int usbduxsub_submit_inurbs(struct usbduxsub *usbduxsub) { - int i, errFlag; + int i, err_flag; if (!usbduxsub) return -EFAULT; /* Submit all URBs and start the transfer on the bus */ - for (i = 0; i < usbduxsub->numOfInBuffers; i++) { + for (i = 0; i < usbduxsub->num_in_buffers; i++) { /* in case of a resubmission after an unlink... */ - usbduxsub->urbIn[i]->interval = usbduxsub->ai_interval; - usbduxsub->urbIn[i]->context = usbduxsub->comedidev; - usbduxsub->urbIn[i]->dev = usbduxsub->usbdev; - usbduxsub->urbIn[i]->status = 0; - usbduxsub->urbIn[i]->transfer_flags = URB_ISO_ASAP; + usbduxsub->urb_in[i]->interval = usbduxsub->ai_interval; + usbduxsub->urb_in[i]->context = usbduxsub->comedidev; + usbduxsub->urb_in[i]->dev = usbduxsub->usbdev; + usbduxsub->urb_in[i]->status = 0; + usbduxsub->urb_in[i]->transfer_flags = URB_ISO_ASAP; dev_dbg(&usbduxsub->interface->dev, "comedi%d: submitting in-urb[%d]: %p,%p intv=%d\n", usbduxsub->comedidev->minor, i, - (usbduxsub->urbIn[i]->context), - (usbduxsub->urbIn[i]->dev), - (usbduxsub->urbIn[i]->interval)); - errFlag = usb_submit_urb(usbduxsub->urbIn[i], GFP_ATOMIC); - if (errFlag) { + (usbduxsub->urb_in[i]->context), + (usbduxsub->urb_in[i]->dev), + (usbduxsub->urb_in[i]->interval)); + err_flag = usb_submit_urb(usbduxsub->urb_in[i], GFP_ATOMIC); + if (err_flag) { dev_err(&usbduxsub->interface->dev, "comedi_: ai: usb_submit_urb(%d) error %d\n", - i, errFlag); - return errFlag; + i, err_flag); + return err_flag; } } return 0; } -static int usbduxsub_submit_OutURBs(struct usbduxsub *usbduxsub) +static int usbduxsub_submit_outurbs(struct usbduxsub *usbduxsub) { - int i, errFlag; + int i, err_flag; if (!usbduxsub) return -EFAULT; - for (i = 0; i < usbduxsub->numOfOutBuffers; i++) { + for (i = 0; i < usbduxsub->num_out_buffers; i++) { dev_dbg(&usbduxsub->interface->dev, "comedi_: submitting out-urb[%d]\n", i); /* in case of a resubmission after an unlink... */ - usbduxsub->urbOut[i]->context = usbduxsub->comedidev; - usbduxsub->urbOut[i]->dev = usbduxsub->usbdev; - usbduxsub->urbOut[i]->status = 0; - usbduxsub->urbOut[i]->transfer_flags = URB_ISO_ASAP; - errFlag = usb_submit_urb(usbduxsub->urbOut[i], GFP_ATOMIC); - if (errFlag) { + usbduxsub->urb_out[i]->context = usbduxsub->comedidev; + usbduxsub->urb_out[i]->dev = usbduxsub->usbdev; + usbduxsub->urb_out[i]->status = 0; + usbduxsub->urb_out[i]->transfer_flags = URB_ISO_ASAP; + err_flag = usb_submit_urb(usbduxsub->urb_out[i], GFP_ATOMIC); + if (err_flag) { dev_err(&usbduxsub->interface->dev, "comedi_: ao: usb_submit_urb(%d) error %d\n", - i, errFlag); - return errFlag; + i, err_flag); + return err_flag; } } return 0; @@ -933,7 +940,7 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev, { struct usbduxsub *this_usbduxsub = dev->private; int err = 0, i; - unsigned int tmpTimer; + unsigned int tmp_timer; if (!(this_usbduxsub->probed)) return -ENODEV; @@ -983,7 +990,7 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev, 1000000 / 8 * i); /* now calc the real sampling rate with all the * rounding errors */ - tmpTimer = + tmp_timer = ((unsigned int)(cmd->scan_begin_arg / 125000)) * 125000; } else { @@ -994,11 +1001,11 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev, /* * calc the real sampling rate with the rounding errors */ - tmpTimer = ((unsigned int)(cmd->scan_begin_arg / + tmp_timer = ((unsigned int)(cmd->scan_begin_arg / 1000000)) * 1000000; } err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, - tmpTimer); + tmp_timer); } err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); @@ -1074,7 +1081,7 @@ static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command) result = usb_bulk_msg(this_usbduxsub->usbdev, usb_rcvbulkpipe(this_usbduxsub->usbdev, COMMAND_IN_EP), - this_usbduxsub->insnBuffer, SIZEINSNBUF, + this_usbduxsub->insn_buffer, SIZEINSNBUF, &nrec, BULK_TIMEOUT); if (result < 0) { dev_err(&this_usbduxsub->interface->dev, "comedi%d: " @@ -1082,7 +1089,7 @@ static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command) "\n", this_usbduxsub->comedidev->minor, result); return result; } - if (le16_to_cpu(this_usbduxsub->insnBuffer[0]) == command) + if (le16_to_cpu(this_usbduxsub->insn_buffer[0]) == command) return result; } /* this is only reached if the data has been requested a couple of @@ -1090,7 +1097,7 @@ static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command) dev_err(&this_usbduxsub->interface->dev, "comedi%d: insn: " "wrong data returned from firmware: want cmd %d, got cmd %d.\n", this_usbduxsub->comedidev->minor, command, - le16_to_cpu(this_usbduxsub->insnBuffer[0])); + le16_to_cpu(this_usbduxsub->insn_buffer[0])); return -EFAULT; } @@ -1119,7 +1126,7 @@ static int usbdux_ai_inttrig(struct comedi_device *dev, } if (!(this_usbduxsub->ai_cmd_running)) { this_usbduxsub->ai_cmd_running = 1; - ret = usbduxsub_submit_InURBs(this_usbduxsub); + ret = usbduxsub_submit_inurbs(this_usbduxsub); if (ret < 0) { dev_err(&this_usbduxsub->interface->dev, "comedi%d: usbdux_ai_inttrig: " @@ -1236,7 +1243,7 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (cmd->start_src == TRIG_NOW) { /* enable this acquisition operation */ this_usbduxsub->ai_cmd_running = 1; - ret = usbduxsub_submit_InURBs(this_usbduxsub); + ret = usbduxsub_submit_inurbs(this_usbduxsub); if (ret < 0) { this_usbduxsub->ai_cmd_running = 0; /* fixme: unlink here?? */ @@ -1304,7 +1311,7 @@ static int usbdux_ai_insn_read(struct comedi_device *dev, up(&this_usbduxsub->sem); return 0; } - one = le16_to_cpu(this_usbduxsub->insnBuffer[1]); + one = le16_to_cpu(this_usbduxsub->insn_buffer[1]); if (CR_RANGE(insn->chanspec) <= 1) one = one ^ 0x800; @@ -1334,7 +1341,7 @@ static int usbdux_ao_insn_read(struct comedi_device *dev, return -ENODEV; } for (i = 0; i < insn->n; i++) - data[i] = this_usbduxsub->outBuffer[chan]; + data[i] = this_usbduxsub->out_buffer[chan]; up(&this_usbduxsub->sem); return i; @@ -1377,7 +1384,7 @@ static int usbdux_ao_insn_write(struct comedi_device *dev, /* one 16 bit value */ *((int16_t *) (this_usbduxsub->dux_commands + 2)) = cpu_to_le16(data[i]); - this_usbduxsub->outBuffer[chan] = data[i]; + this_usbduxsub->out_buffer[chan] = data[i]; /* channel number */ this_usbduxsub->dux_commands[4] = (chan << 6); err = send_dux_commands(this_usbduxsub, SENDDACOMMANDS); @@ -1414,7 +1421,7 @@ static int usbdux_ao_inttrig(struct comedi_device *dev, } if (!(this_usbduxsub->ao_cmd_running)) { this_usbduxsub->ao_cmd_running = 1; - ret = usbduxsub_submit_OutURBs(this_usbduxsub); + ret = usbduxsub_submit_outurbs(this_usbduxsub); if (ret < 0) { dev_err(&this_usbduxsub->interface->dev, "comedi%d: usbdux_ao_inttrig: submitURB: " @@ -1609,7 +1616,7 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (cmd->start_src == TRIG_NOW) { /* enable this acquisition operation */ this_usbduxsub->ao_cmd_running = 1; - ret = usbduxsub_submit_OutURBs(this_usbduxsub); + ret = usbduxsub_submit_outurbs(this_usbduxsub); if (ret < 0) { this_usbduxsub->ao_cmd_running = 0; /* fixme: unlink here?? */ @@ -1697,7 +1704,7 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev, return err; } - data[1] = le16_to_cpu(this_usbduxsub->insnBuffer[1]); + data[1] = le16_to_cpu(this_usbduxsub->insn_buffer[1]); up(&this_usbduxsub->sem); return insn->n; } @@ -1733,7 +1740,7 @@ static int usbdux_counter_read(struct comedi_device *dev, return err; } - data[0] = le16_to_cpu(this_usbduxsub->insnBuffer[chan + 1]); + data[0] = le16_to_cpu(this_usbduxsub->insn_buffer[chan + 1]); up(&this_usbduxsub->sem); return 1; } @@ -1780,13 +1787,13 @@ static int usbdux_counter_config(struct comedi_device *dev, /***********************************/ /* PWM */ -static int usbduxsub_unlink_PwmURBs(struct usbduxsub *usbduxsub_tmp) +static int usbduxsub_unlink_pwm_urbs(struct usbduxsub *usbduxsub_tmp) { int err = 0; - if (usbduxsub_tmp && usbduxsub_tmp->urbPwm) { - if (usbduxsub_tmp->urbPwm) - usb_kill_urb(usbduxsub_tmp->urbPwm); + if (usbduxsub_tmp && usbduxsub_tmp->urb_pwm) { + if (usbduxsub_tmp->urb_pwm) + usb_kill_urb(usbduxsub_tmp->urb_pwm); dev_dbg(&usbduxsub_tmp->interface->dev, "comedi: unlinked PwmURB: res=%d\n", err); } @@ -1805,7 +1812,7 @@ static int usbdux_pwm_stop(struct usbduxsub *this_usbduxsub, int do_unlink) dev_dbg(&this_usbduxsub->interface->dev, "comedi: %s\n", __func__); if (do_unlink) - ret = usbduxsub_unlink_PwmURBs(this_usbduxsub); + ret = usbduxsub_unlink_pwm_urbs(this_usbduxsub); this_usbduxsub->pwm_cmd_running = 0; @@ -1878,7 +1885,7 @@ static void usbduxsub_pwm_irq(struct urb *urb) if (!(this_usbduxsub->pwm_cmd_running)) return; - urb->transfer_buffer_length = this_usbduxsub->sizePwmBuf; + urb->transfer_buffer_length = this_usbduxsub->size_pwm_buf; urb->dev = this_usbduxsub->usbdev; urb->status = 0; if (this_usbduxsub->pwm_cmd_running) { @@ -1898,9 +1905,9 @@ static void usbduxsub_pwm_irq(struct urb *urb) } } -static int usbduxsub_submit_PwmURBs(struct usbduxsub *usbduxsub) +static int usbduxsub_submit_pwm_urbs(struct usbduxsub *usbduxsub) { - int errFlag; + int err_flag; if (!usbduxsub) return -EFAULT; @@ -1908,19 +1915,19 @@ static int usbduxsub_submit_PwmURBs(struct usbduxsub *usbduxsub) dev_dbg(&usbduxsub->interface->dev, "comedi_: submitting pwm-urb\n"); /* in case of a resubmission after an unlink... */ - usb_fill_bulk_urb(usbduxsub->urbPwm, + usb_fill_bulk_urb(usbduxsub->urb_pwm, usbduxsub->usbdev, usb_sndbulkpipe(usbduxsub->usbdev, PWM_EP), - usbduxsub->urbPwm->transfer_buffer, - usbduxsub->sizePwmBuf, usbduxsub_pwm_irq, + usbduxsub->urb_pwm->transfer_buffer, + usbduxsub->size_pwm_buf, usbduxsub_pwm_irq, usbduxsub->comedidev); - errFlag = usb_submit_urb(usbduxsub->urbPwm, GFP_ATOMIC); - if (errFlag) { + err_flag = usb_submit_urb(usbduxsub->urb_pwm, GFP_ATOMIC); + if (err_flag) { dev_err(&usbduxsub->interface->dev, "comedi_: usbdux: pwm: usb_submit_urb error %d\n", - errFlag); - return errFlag; + err_flag); + return err_flag; } return 0; } @@ -1945,8 +1952,8 @@ static int usbdux_pwm_period(struct comedi_device *dev, return -EAGAIN; } } - this_usbduxsub->pwmDelay = fx2delay; - this_usbduxsub->pwmPeriod = period; + this_usbduxsub->pwn_delay = fx2delay; + this_usbduxsub->pwm_period = period; dev_dbg(&this_usbduxsub->interface->dev, "%s: frequ=%d, period=%d\n", __func__, period, fx2delay); return 0; @@ -1967,17 +1974,17 @@ static int usbdux_pwm_start(struct comedi_device *dev, return 0; } - this_usbduxsub->dux_commands[1] = ((int8_t) this_usbduxsub->pwmDelay); + this_usbduxsub->dux_commands[1] = ((int8_t) this_usbduxsub->pwn_delay); ret = send_dux_commands(this_usbduxsub, SENDPWMON); if (ret < 0) return ret; /* initialise the buffer */ - for (i = 0; i < this_usbduxsub->sizePwmBuf; i++) - ((char *)(this_usbduxsub->urbPwm->transfer_buffer))[i] = 0; + for (i = 0; i < this_usbduxsub->size_pwm_buf; i++) + ((char *)(this_usbduxsub->urb_pwm->transfer_buffer))[i] = 0; this_usbduxsub->pwm_cmd_running = 1; - ret = usbduxsub_submit_PwmURBs(this_usbduxsub); + ret = usbduxsub_submit_pwm_urbs(this_usbduxsub); if (ret < 0) { this_usbduxsub->pwm_cmd_running = 0; return ret; @@ -1992,7 +1999,7 @@ static int usbdux_pwm_pattern(struct comedi_device *dev, { struct usbduxsub *this_usbduxsub = dev->private; int i, szbuf; - char *pBuf; + char *p_buf; char pwm_mask; char sgn_mask; char c; @@ -2006,10 +2013,10 @@ static int usbdux_pwm_pattern(struct comedi_device *dev, sgn_mask = (16 << channel); /* this is the buffer which will be filled with the with bit */ /* pattern for one period */ - szbuf = this_usbduxsub->sizePwmBuf; - pBuf = (char *)(this_usbduxsub->urbPwm->transfer_buffer); + szbuf = this_usbduxsub->size_pwm_buf; + p_buf = (char *)(this_usbduxsub->urb_pwm->transfer_buffer); for (i = 0; i < szbuf; i++) { - c = *pBuf; + c = *p_buf; /* reset bits */ c = c & (~pwm_mask); /* set the bit as long as the index is lower than the value */ @@ -2023,7 +2030,7 @@ static int usbdux_pwm_pattern(struct comedi_device *dev, /* negative value */ c = c | sgn_mask; } - *(pBuf++) = c; + *(p_buf++) = c; } return 1; } @@ -2095,7 +2102,7 @@ static int usbdux_pwm_config(struct comedi_device *dev, "comedi%d: %s: setting period\n", dev->minor, __func__); return usbdux_pwm_period(dev, s, data[1]); case INSN_CONFIG_PWM_GET_PERIOD: - data[1] = this_usbduxsub->pwmPeriod; + data[1] = this_usbduxsub->pwm_period; return 0; case INSN_CONFIG_PWM_SET_H_BRIDGE: /* value in the first byte and the sign in the second for a @@ -2131,55 +2138,55 @@ static void tidy_up(struct usbduxsub *usbduxsub_tmp) usbduxsub_tmp->probed = 0; - if (usbduxsub_tmp->urbIn) { + if (usbduxsub_tmp->urb_in) { if (usbduxsub_tmp->ai_cmd_running) { usbduxsub_tmp->ai_cmd_running = 0; - usbduxsub_unlink_InURBs(usbduxsub_tmp); + usbduxsub_unlink_inurbs(usbduxsub_tmp); } - for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) { - kfree(usbduxsub_tmp->urbIn[i]->transfer_buffer); - usbduxsub_tmp->urbIn[i]->transfer_buffer = NULL; - usb_kill_urb(usbduxsub_tmp->urbIn[i]); - usb_free_urb(usbduxsub_tmp->urbIn[i]); - usbduxsub_tmp->urbIn[i] = NULL; + for (i = 0; i < usbduxsub_tmp->num_in_buffers; i++) { + kfree(usbduxsub_tmp->urb_in[i]->transfer_buffer); + usbduxsub_tmp->urb_in[i]->transfer_buffer = NULL; + usb_kill_urb(usbduxsub_tmp->urb_in[i]); + usb_free_urb(usbduxsub_tmp->urb_in[i]); + usbduxsub_tmp->urb_in[i] = NULL; } - kfree(usbduxsub_tmp->urbIn); - usbduxsub_tmp->urbIn = NULL; + kfree(usbduxsub_tmp->urb_in); + usbduxsub_tmp->urb_in = NULL; } - if (usbduxsub_tmp->urbOut) { + if (usbduxsub_tmp->urb_out) { if (usbduxsub_tmp->ao_cmd_running) { usbduxsub_tmp->ao_cmd_running = 0; - usbduxsub_unlink_OutURBs(usbduxsub_tmp); + usbduxsub_unlink_outurbs(usbduxsub_tmp); } - for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) { - kfree(usbduxsub_tmp->urbOut[i]->transfer_buffer); - usbduxsub_tmp->urbOut[i]->transfer_buffer = NULL; - if (usbduxsub_tmp->urbOut[i]) { - usb_kill_urb(usbduxsub_tmp->urbOut[i]); - usb_free_urb(usbduxsub_tmp->urbOut[i]); - usbduxsub_tmp->urbOut[i] = NULL; + for (i = 0; i < usbduxsub_tmp->num_out_buffers; i++) { + kfree(usbduxsub_tmp->urb_out[i]->transfer_buffer); + usbduxsub_tmp->urb_out[i]->transfer_buffer = NULL; + if (usbduxsub_tmp->urb_out[i]) { + usb_kill_urb(usbduxsub_tmp->urb_out[i]); + usb_free_urb(usbduxsub_tmp->urb_out[i]); + usbduxsub_tmp->urb_out[i] = NULL; } } - kfree(usbduxsub_tmp->urbOut); - usbduxsub_tmp->urbOut = NULL; + kfree(usbduxsub_tmp->urb_out); + usbduxsub_tmp->urb_out = NULL; } - if (usbduxsub_tmp->urbPwm) { + if (usbduxsub_tmp->urb_pwm) { if (usbduxsub_tmp->pwm_cmd_running) { usbduxsub_tmp->pwm_cmd_running = 0; - usbduxsub_unlink_PwmURBs(usbduxsub_tmp); + usbduxsub_unlink_pwm_urbs(usbduxsub_tmp); } - kfree(usbduxsub_tmp->urbPwm->transfer_buffer); - usbduxsub_tmp->urbPwm->transfer_buffer = NULL; - usb_kill_urb(usbduxsub_tmp->urbPwm); - usb_free_urb(usbduxsub_tmp->urbPwm); - usbduxsub_tmp->urbPwm = NULL; - } - kfree(usbduxsub_tmp->inBuffer); - usbduxsub_tmp->inBuffer = NULL; - kfree(usbduxsub_tmp->insnBuffer); - usbduxsub_tmp->insnBuffer = NULL; - kfree(usbduxsub_tmp->outBuffer); - usbduxsub_tmp->outBuffer = NULL; + kfree(usbduxsub_tmp->urb_pwm->transfer_buffer); + usbduxsub_tmp->urb_pwm->transfer_buffer = NULL; + usb_kill_urb(usbduxsub_tmp->urb_pwm); + usb_free_urb(usbduxsub_tmp->urb_pwm); + usbduxsub_tmp->urb_pwm = NULL; + } + kfree(usbduxsub_tmp->in_buffer); + usbduxsub_tmp->in_buffer = NULL; + kfree(usbduxsub_tmp->insn_buffer); + usbduxsub_tmp->insn_buffer = NULL; + kfree(usbduxsub_tmp->out_buffer); + usbduxsub_tmp->out_buffer = NULL; kfree(usbduxsub_tmp->dac_commands); usbduxsub_tmp->dac_commands = NULL; kfree(usbduxsub_tmp->dux_commands); @@ -2200,8 +2207,6 @@ static int usbdux_attach_common(struct comedi_device *dev, /* pointer back to the corresponding comedi device */ udev->comedidev = dev; - dev->board_name = "usbdux"; - /* set number of subdevices */ if (udev->high_speed) { /* with pwm */ @@ -2302,7 +2307,7 @@ static int usbdux_attach_common(struct comedi_device *dev, s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE; s->n_chan = 8; /* this defines the max duty cycle resolution */ - s->maxdata = udev->sizePwmBuf; + s->maxdata = udev->size_pwm_buf; s->insn_write = usbdux_pwm_write; s->insn_read = usbdux_pwm_read; s->insn_config = usbdux_pwm_config; @@ -2381,7 +2386,7 @@ static void usbdux_firmware_request_complete_handler(const struct firmware *fw, * we need to upload the firmware here because fw will be * freed once we've left this function */ - ret = firmwareUpload(usbduxsub_tmp, fw->data, fw->size); + ret = firmware_upload(usbduxsub_tmp, fw->data, fw->size); if (ret) { dev_err(&uinterf->dev, @@ -2457,22 +2462,22 @@ static int usbdux_usb_probe(struct usb_interface *uinterf, return -ENOMEM; } /* create space for the in buffer and set it to zero */ - usbduxsub[index].inBuffer = kzalloc(SIZEINBUF, GFP_KERNEL); - if (!(usbduxsub[index].inBuffer)) { + usbduxsub[index].in_buffer = kzalloc(SIZEINBUF, GFP_KERNEL); + if (!(usbduxsub[index].in_buffer)) { tidy_up(&(usbduxsub[index])); up(&start_stop_sem); return -ENOMEM; } /* create space of the instruction buffer */ - usbduxsub[index].insnBuffer = kzalloc(SIZEINSNBUF, GFP_KERNEL); - if (!(usbduxsub[index].insnBuffer)) { + usbduxsub[index].insn_buffer = kzalloc(SIZEINSNBUF, GFP_KERNEL); + if (!(usbduxsub[index].insn_buffer)) { tidy_up(&(usbduxsub[index])); up(&start_stop_sem); return -ENOMEM; } /* create space for the outbuffer */ - usbduxsub[index].outBuffer = kzalloc(SIZEOUTBUF, GFP_KERNEL); - if (!(usbduxsub[index].outBuffer)) { + usbduxsub[index].out_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL); + if (!(usbduxsub[index].out_buffer)) { tidy_up(&(usbduxsub[index])); up(&start_stop_sem); return -ENOMEM; @@ -2489,124 +2494,124 @@ static int usbdux_usb_probe(struct usb_interface *uinterf, return -ENODEV; } if (usbduxsub[index].high_speed) - usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSHIGH; + usbduxsub[index].num_in_buffers = NUMOFINBUFFERSHIGH; else - usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSFULL; + usbduxsub[index].num_in_buffers = NUMOFINBUFFERSFULL; - usbduxsub[index].urbIn = - kcalloc(usbduxsub[index].numOfInBuffers, sizeof(struct urb *), + usbduxsub[index].urb_in = + kcalloc(usbduxsub[index].num_in_buffers, sizeof(struct urb *), GFP_KERNEL); - if (!(usbduxsub[index].urbIn)) { + if (!(usbduxsub[index].urb_in)) { tidy_up(&(usbduxsub[index])); up(&start_stop_sem); return -ENOMEM; } - for (i = 0; i < usbduxsub[index].numOfInBuffers; i++) { + for (i = 0; i < usbduxsub[index].num_in_buffers; i++) { /* one frame: 1ms */ - usbduxsub[index].urbIn[i] = usb_alloc_urb(1, GFP_KERNEL); - if (usbduxsub[index].urbIn[i] == NULL) { + usbduxsub[index].urb_in[i] = usb_alloc_urb(1, GFP_KERNEL); + if (usbduxsub[index].urb_in[i] == NULL) { dev_err(dev, "comedi_: usbdux%d: " "Could not alloc. urb(%d)\n", index, i); tidy_up(&(usbduxsub[index])); up(&start_stop_sem); return -ENOMEM; } - usbduxsub[index].urbIn[i]->dev = usbduxsub[index].usbdev; + usbduxsub[index].urb_in[i]->dev = usbduxsub[index].usbdev; /* will be filled later with a pointer to the comedi-device */ /* and ONLY then the urb should be submitted */ - usbduxsub[index].urbIn[i]->context = NULL; - usbduxsub[index].urbIn[i]->pipe = + usbduxsub[index].urb_in[i]->context = NULL; + usbduxsub[index].urb_in[i]->pipe = usb_rcvisocpipe(usbduxsub[index].usbdev, ISOINEP); - usbduxsub[index].urbIn[i]->transfer_flags = URB_ISO_ASAP; - usbduxsub[index].urbIn[i]->transfer_buffer = + usbduxsub[index].urb_in[i]->transfer_flags = URB_ISO_ASAP; + usbduxsub[index].urb_in[i]->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL); - if (!(usbduxsub[index].urbIn[i]->transfer_buffer)) { + if (!(usbduxsub[index].urb_in[i]->transfer_buffer)) { tidy_up(&(usbduxsub[index])); up(&start_stop_sem); return -ENOMEM; } - usbduxsub[index].urbIn[i]->complete = usbduxsub_ai_IsocIrq; - usbduxsub[index].urbIn[i]->number_of_packets = 1; - usbduxsub[index].urbIn[i]->transfer_buffer_length = SIZEINBUF; - usbduxsub[index].urbIn[i]->iso_frame_desc[0].offset = 0; - usbduxsub[index].urbIn[i]->iso_frame_desc[0].length = SIZEINBUF; + usbduxsub[index].urb_in[i]->complete = usbduxsub_ai_isoc_irq; + usbduxsub[index].urb_in[i]->number_of_packets = 1; + usbduxsub[index].urb_in[i]->transfer_buffer_length = SIZEINBUF; + usbduxsub[index].urb_in[i]->iso_frame_desc[0].offset = 0; + usbduxsub[index].urb_in[i]->iso_frame_desc[0].length = SIZEINBUF; } /* out */ if (usbduxsub[index].high_speed) - usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSHIGH; + usbduxsub[index].num_out_buffers = NUMOFOUTBUFFERSHIGH; else - usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSFULL; + usbduxsub[index].num_out_buffers = NUMOFOUTBUFFERSFULL; - usbduxsub[index].urbOut = - kcalloc(usbduxsub[index].numOfOutBuffers, sizeof(struct urb *), + usbduxsub[index].urb_out = + kcalloc(usbduxsub[index].num_out_buffers, sizeof(struct urb *), GFP_KERNEL); - if (!(usbduxsub[index].urbOut)) { + if (!(usbduxsub[index].urb_out)) { tidy_up(&(usbduxsub[index])); up(&start_stop_sem); return -ENOMEM; } - for (i = 0; i < usbduxsub[index].numOfOutBuffers; i++) { + for (i = 0; i < usbduxsub[index].num_out_buffers; i++) { /* one frame: 1ms */ - usbduxsub[index].urbOut[i] = usb_alloc_urb(1, GFP_KERNEL); - if (usbduxsub[index].urbOut[i] == NULL) { + usbduxsub[index].urb_out[i] = usb_alloc_urb(1, GFP_KERNEL); + if (usbduxsub[index].urb_out[i] == NULL) { dev_err(dev, "comedi_: usbdux%d: " "Could not alloc. urb(%d)\n", index, i); tidy_up(&(usbduxsub[index])); up(&start_stop_sem); return -ENOMEM; } - usbduxsub[index].urbOut[i]->dev = usbduxsub[index].usbdev; + usbduxsub[index].urb_out[i]->dev = usbduxsub[index].usbdev; /* will be filled later with a pointer to the comedi-device */ /* and ONLY then the urb should be submitted */ - usbduxsub[index].urbOut[i]->context = NULL; - usbduxsub[index].urbOut[i]->pipe = + usbduxsub[index].urb_out[i]->context = NULL; + usbduxsub[index].urb_out[i]->pipe = usb_sndisocpipe(usbduxsub[index].usbdev, ISOOUTEP); - usbduxsub[index].urbOut[i]->transfer_flags = URB_ISO_ASAP; - usbduxsub[index].urbOut[i]->transfer_buffer = + usbduxsub[index].urb_out[i]->transfer_flags = URB_ISO_ASAP; + usbduxsub[index].urb_out[i]->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL); - if (!(usbduxsub[index].urbOut[i]->transfer_buffer)) { + if (!(usbduxsub[index].urb_out[i]->transfer_buffer)) { tidy_up(&(usbduxsub[index])); up(&start_stop_sem); return -ENOMEM; } - usbduxsub[index].urbOut[i]->complete = usbduxsub_ao_IsocIrq; - usbduxsub[index].urbOut[i]->number_of_packets = 1; - usbduxsub[index].urbOut[i]->transfer_buffer_length = SIZEOUTBUF; - usbduxsub[index].urbOut[i]->iso_frame_desc[0].offset = 0; - usbduxsub[index].urbOut[i]->iso_frame_desc[0].length = + usbduxsub[index].urb_out[i]->complete = usbduxsub_ao_isoc_irq; + usbduxsub[index].urb_out[i]->number_of_packets = 1; + usbduxsub[index].urb_out[i]->transfer_buffer_length = SIZEOUTBUF; + usbduxsub[index].urb_out[i]->iso_frame_desc[0].offset = 0; + usbduxsub[index].urb_out[i]->iso_frame_desc[0].length = SIZEOUTBUF; if (usbduxsub[index].high_speed) { /* uframes */ - usbduxsub[index].urbOut[i]->interval = 8; + usbduxsub[index].urb_out[i]->interval = 8; } else { /* frames */ - usbduxsub[index].urbOut[i]->interval = 1; + usbduxsub[index].urb_out[i]->interval = 1; } } /* pwm */ if (usbduxsub[index].high_speed) { /* max bulk ep size in high speed */ - usbduxsub[index].sizePwmBuf = 512; - usbduxsub[index].urbPwm = usb_alloc_urb(0, GFP_KERNEL); - if (usbduxsub[index].urbPwm == NULL) { + usbduxsub[index].size_pwm_buf = 512; + usbduxsub[index].urb_pwm = usb_alloc_urb(0, GFP_KERNEL); + if (usbduxsub[index].urb_pwm == NULL) { dev_err(dev, "comedi_: usbdux%d: " "Could not alloc. pwm urb\n", index); tidy_up(&(usbduxsub[index])); up(&start_stop_sem); return -ENOMEM; } - usbduxsub[index].urbPwm->transfer_buffer = - kzalloc(usbduxsub[index].sizePwmBuf, GFP_KERNEL); - if (!(usbduxsub[index].urbPwm->transfer_buffer)) { + usbduxsub[index].urb_pwm->transfer_buffer = + kzalloc(usbduxsub[index].size_pwm_buf, GFP_KERNEL); + if (!(usbduxsub[index].urb_pwm->transfer_buffer)) { tidy_up(&(usbduxsub[index])); up(&start_stop_sem); return -ENOMEM; } } else { - usbduxsub[index].urbPwm = NULL; - usbduxsub[index].sizePwmBuf = 0; + usbduxsub[index].urb_pwm = NULL; + usbduxsub[index].size_pwm_buf = 0; } usbduxsub[index].ai_cmd_running = 0; diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index 4bf5dd094dc..7f95af33085 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -436,10 +436,14 @@ static void usbduxfastsub_ai_Irq(struct urb *urb) static int usbduxfastsub_start(struct usbduxfastsub_s *udfs) { int ret; - unsigned char local_transfer_buffer[16]; + unsigned char *local_transfer_buffer; + + local_transfer_buffer = kmalloc(1, GFP_KERNEL); + if (!local_transfer_buffer) + return -ENOMEM; /* 7f92 to zero */ - local_transfer_buffer[0] = 0; + *local_transfer_buffer = 0; /* bRequest, "Firmware" */ ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0), USBDUXFASTSUB_FIRMWARE, @@ -450,22 +454,25 @@ static int usbduxfastsub_start(struct usbduxfastsub_s *udfs) local_transfer_buffer, 1, /* Length */ EZTIMEOUT); /* Timeout */ - if (ret < 0) { + if (ret < 0) dev_err(&udfs->interface->dev, "control msg failed (start)\n"); - return ret; - } - return 0; + kfree(local_transfer_buffer); + return ret; } static int usbduxfastsub_stop(struct usbduxfastsub_s *udfs) { int ret; - unsigned char local_transfer_buffer[16]; + unsigned char *local_transfer_buffer; + + local_transfer_buffer = kmalloc(1, GFP_KERNEL); + if (!local_transfer_buffer) + return -ENOMEM; /* 7f92 to one */ - local_transfer_buffer[0] = 1; + *local_transfer_buffer = 1; /* bRequest, "Firmware" */ ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0), USBDUXFASTSUB_FIRMWARE, @@ -474,13 +481,12 @@ static int usbduxfastsub_stop(struct usbduxfastsub_s *udfs) 0x0000, /* Index */ local_transfer_buffer, 1, /* Length */ EZTIMEOUT); /* Timeout */ - if (ret < 0) { + if (ret < 0) dev_err(&udfs->interface->dev, "control msg failed (stop)\n"); - return ret; - } - return 0; + kfree(local_transfer_buffer); + return ret; } static int usbduxfastsub_upload(struct usbduxfastsub_s *udfs, @@ -1381,7 +1387,7 @@ static int usbduxfast_attach_common(struct comedi_device *dev, down(&udfs->sem); /* pointer back to the corresponding comedi device */ udfs->comedidev = dev; - dev->board_name = "usbduxfast"; + ret = comedi_alloc_subdevices(dev, 1); if (ret) { up(&udfs->sem); diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index d066351a71b..d3bc1b9910a 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -176,12 +176,6 @@ static const struct comedi_lrange range_usbdux_ai_range = { 1, { } }; -static const struct comedi_lrange range_usbdux_ao_range = { 1, { - UNI_RANGE - (2.5), - } -}; - /* * private structure of one subdevice */ @@ -681,7 +675,11 @@ static void usbduxsub_ao_IsocIrq(struct urb *urb) static int usbduxsub_start(struct usbduxsub *usbduxsub) { int errcode = 0; - uint8_t local_transfer_buffer[16]; + uint8_t *local_transfer_buffer; + + local_transfer_buffer = kmalloc(16, GFP_KERNEL); + if (!local_transfer_buffer) + return -ENOMEM; /* 7f92 to zero */ local_transfer_buffer[0] = 0; @@ -702,19 +700,22 @@ static int usbduxsub_start(struct usbduxsub *usbduxsub) 1, /* Timeout */ BULK_TIMEOUT); - if (errcode < 0) { + if (errcode < 0) dev_err(&usbduxsub->interface->dev, "comedi_: control msg failed (start)\n"); - return errcode; - } - return 0; + + kfree(local_transfer_buffer); + return errcode; } static int usbduxsub_stop(struct usbduxsub *usbduxsub) { int errcode = 0; + uint8_t *local_transfer_buffer; - uint8_t local_transfer_buffer[16]; + local_transfer_buffer = kmalloc(16, GFP_KERNEL); + if (!local_transfer_buffer) + return -ENOMEM; /* 7f92 to one */ local_transfer_buffer[0] = 1; @@ -732,12 +733,12 @@ static int usbduxsub_stop(struct usbduxsub *usbduxsub) 1, /* Timeout */ BULK_TIMEOUT); - if (errcode < 0) { + if (errcode < 0) dev_err(&usbduxsub->interface->dev, "comedi_: control msg failed (stop)\n"); - return errcode; - } - return 0; + + kfree(local_transfer_buffer); + return errcode; } static int usbduxsub_upload(struct usbduxsub *usbduxsub, @@ -1369,7 +1370,7 @@ static int usbdux_getstatusinfo(struct comedi_device *dev, int chan) /* 32 bits big endian from the A/D converter */ one = be32_to_cpu(*((int32_t *)((this_usbduxsub->insnBuffer)+1))); - /* mask out the staus byte */ + /* mask out the status byte */ one = one & 0x00ffffff; one = one ^ 0x00800000; @@ -2204,7 +2205,7 @@ static int usbduxsigma_attach_common(struct comedi_device *dev, down(&uds->sem); /* pointer back to the corresponding comedi device */ uds->comedidev = dev; - dev->board_name = "usbduxsigma"; + /* set number of subdevices */ if (uds->high_speed) n_subdevs = 4; /* with pwm */ @@ -2262,7 +2263,7 @@ static int usbduxsigma_attach_common(struct comedi_device *dev, /* 8 bit resolution */ s->maxdata = 0x00ff; /* unipolar range */ - s->range_table = (&range_usbdux_ao_range); + s->range_table = &range_unipolar2_5; /* callback */ s->do_cmdtest = usbdux_ao_cmdtest; s->do_cmd = usbdux_ao_cmd; diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c index 8932a510d96..3231a483f56 100644 --- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c +++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c @@ -63,7 +63,7 @@ struct comedi_device *comedi_open(const char *filename) return dev; } -EXPORT_SYMBOL(comedi_open); +EXPORT_SYMBOL_GPL(comedi_open); int comedi_close(struct comedi_device *d) { @@ -73,7 +73,7 @@ int comedi_close(struct comedi_device *d) return 0; } -EXPORT_SYMBOL(comedi_close); +EXPORT_SYMBOL_GPL(comedi_close); static int comedi_do_insn(struct comedi_device *dev, struct comedi_insn *insn, @@ -143,7 +143,7 @@ int comedi_dio_config(struct comedi_device *dev, unsigned int subdev, return comedi_do_insn(dev, &insn, &io); } -EXPORT_SYMBOL(comedi_dio_config); +EXPORT_SYMBOL_GPL(comedi_dio_config); int comedi_dio_bitfield(struct comedi_device *dev, unsigned int subdev, unsigned int mask, unsigned int *bits) @@ -166,7 +166,7 @@ int comedi_dio_bitfield(struct comedi_device *dev, unsigned int subdev, return ret; } -EXPORT_SYMBOL(comedi_dio_bitfield); +EXPORT_SYMBOL_GPL(comedi_dio_bitfield); int comedi_find_subdevice_by_type(struct comedi_device *dev, int type, unsigned int subd) @@ -183,7 +183,7 @@ int comedi_find_subdevice_by_type(struct comedi_device *dev, int type, } return -1; } -EXPORT_SYMBOL(comedi_find_subdevice_by_type); +EXPORT_SYMBOL_GPL(comedi_find_subdevice_by_type); int comedi_get_n_channels(struct comedi_device *dev, unsigned int subdevice) { @@ -191,4 +191,4 @@ int comedi_get_n_channels(struct comedi_device *dev, unsigned int subdevice) return s->n_chan; } -EXPORT_SYMBOL(comedi_get_n_channels); +EXPORT_SYMBOL_GPL(comedi_get_n_channels); diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c index 59ff0cf7338..1dc391b7644 100644 --- a/drivers/staging/comedi/range.c +++ b/drivers/staging/comedi/range.c @@ -26,17 +26,25 @@ #include "comedi_internal.h" const struct comedi_lrange range_bipolar10 = { 1, {BIP_RANGE(10)} }; -EXPORT_SYMBOL(range_bipolar10); +EXPORT_SYMBOL_GPL(range_bipolar10); const struct comedi_lrange range_bipolar5 = { 1, {BIP_RANGE(5)} }; -EXPORT_SYMBOL(range_bipolar5); +EXPORT_SYMBOL_GPL(range_bipolar5); const struct comedi_lrange range_bipolar2_5 = { 1, {BIP_RANGE(2.5)} }; -EXPORT_SYMBOL(range_bipolar2_5); +EXPORT_SYMBOL_GPL(range_bipolar2_5); const struct comedi_lrange range_unipolar10 = { 1, {UNI_RANGE(10)} }; -EXPORT_SYMBOL(range_unipolar10); +EXPORT_SYMBOL_GPL(range_unipolar10); const struct comedi_lrange range_unipolar5 = { 1, {UNI_RANGE(5)} }; -EXPORT_SYMBOL(range_unipolar5); +EXPORT_SYMBOL_GPL(range_unipolar5); +const struct comedi_lrange range_unipolar2_5 = { 1, {UNI_RANGE(2.5)} }; +EXPORT_SYMBOL_GPL(range_unipolar2_5); +const struct comedi_lrange range_0_20mA = { 1, {RANGE_mA(0, 20)} }; +EXPORT_SYMBOL_GPL(range_0_20mA); +const struct comedi_lrange range_4_20mA = { 1, {RANGE_mA(4, 20)} }; +EXPORT_SYMBOL_GPL(range_4_20mA); +const struct comedi_lrange range_0_32mA = { 1, {RANGE_mA(0, 32)} }; +EXPORT_SYMBOL_GPL(range_0_32mA); const struct comedi_lrange range_unknown = { 1, {{0, 1000000, UNIT_none} } }; -EXPORT_SYMBOL(range_unknown); +EXPORT_SYMBOL_GPL(range_unknown); /* COMEDI_RANGEINFO @@ -165,4 +173,4 @@ int comedi_check_chanlist(struct comedi_subdevice *s, int n, } return 0; } -EXPORT_SYMBOL(comedi_check_chanlist); +EXPORT_SYMBOL_GPL(comedi_check_chanlist); |