#undef DEBUG
#define __NO_VERSION__
+#include "comedi_fops.h"
+
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/vmalloc.h>
#include <linux/fs.h>
-
#include <linux/comedidev.h>
+#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/uaccess.h>
comedi_device *comedi_devices;
spinlock_t big_comedi_lock; /* Dynamic initialization */
-static int do_devconfig_ioctl(comedi_device *dev,comedi_devconfig *arg,unsigned int minor);
+static int do_devconfig_ioctl(comedi_device *dev,comedi_devconfig *arg);
static int do_bufconfig_ioctl(comedi_device *dev,void *arg);
static int do_devinfo_ioctl(comedi_device *dev,comedi_devinfo *arg);
static int do_subdinfo_ioctl(comedi_device *dev,comedi_subdinfo *arg,void *file);
static void init_async_buf( comedi_async *async );
static int comedi_ioctl(struct inode * inode,struct file * file,
- unsigned int cmd,unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
- unsigned int minor=MINOR(inode->i_rdev);
- comedi_device *dev=comedi_get_device_by_minor(minor);
+ const unsigned minor = iminor(inode);
+ comedi_device *dev = comedi_get_device_by_minor(minor);
/* Device config is special, because it must work on
* an unconfigured device. */
if(cmd==COMEDI_DEVCONFIG){
- return do_devconfig_ioctl(dev,(void *)arg,minor);
+ return do_devconfig_ioctl(dev,(void *)arg);
}
if(!dev->attached){
- DPRINTK("no driver configured on /dev/comedi%i\n", minor);
+ DPRINTK("no driver configured on /dev/comedi%i\n", dev->minor);
return -ENODEV;
}
writes:
none
*/
-static int do_devconfig_ioctl(comedi_device *dev,comedi_devconfig *arg, unsigned int minor)
+static int do_devconfig_ioctl(comedi_device *dev, comedi_devconfig *arg)
{
comedi_devconfig it;
int ret;
}
DPRINTK("comedi%i subd %d buffer resized to %i bytes\n",
- MINOR(dev->devt), bc.subdevice, async->prealloc_bufsz);
+ dev->minor, bc.subdevice, async->prealloc_bufsz);
}
bc.size = async->prealloc_bufsz;
us->len_chanlist = s->len_chanlist;
us->maxdata = s->maxdata;
if(s->range_table){
- us->range_type = (MINOR(dev->devt) << 28) | (i << 24) | (0 << 16) |
+ us->range_type = (dev->minor << 28) | (i << 24) | (0 << 16) |
(s->range_table->length);
}else{
us->range_type = 0; /* XXX */
for(i=0;i<s->n_chan;i++){
int x;
- x=(MINOR(dev->devt) << 28) | (it.subdev << 24) | (i << 16) |
+ x=(dev->minor << 28) | (it.subdev << 24) | (i << 16) |
(s->range_table_list[i]->length);
put_user(x,it.rangelist+i);
}
if(bi.subdevice >= dev->n_subdevices || bi.subdevice < 0)
return -EINVAL;
- s=dev->subdevices + bi.subdevice;
- async=s->async;
-
- if(s!=dev->read_subdev && s!=dev->write_subdev)return -EINVAL;
+ s = dev->subdevices + bi.subdevice;
+ async = s->async;
if(!async){
DPRINTK("subdevice does not have async capability\n");
goto copyback;
}
- if(bi.bytes_read && s==dev->read_subdev){
+ if(bi.bytes_read && (s->subdev_flags & SDF_CMD_READ)){
comedi_buf_read_free(async, bi.bytes_read);
if(!(s->subdev_flags&SDF_RUNNING) &&
}
}
- if(bi.bytes_written && s==dev->write_subdev){
+ if(bi.bytes_written && (s->subdev_flags & SDF_CMD_WRITE)){
bi.bytes_written = comedi_buf_write_alloc( async, bi.bytes_written );
comedi_buf_munge(dev, s, async->buf_write_alloc_count - async->munge_count);
comedi_buf_write_free(async, bi.bytes_written);
bi.buf_write_ptr = async->buf_write_ptr;
bi.buf_read_count = async->buf_read_count;
bi.buf_read_ptr = async->buf_read_ptr;
- if(s==dev->read_subdev){
+ /* FIXME this will bug if we ever have a subdevice that supports both read and write commands.
+ We need a flag saying which direction the current command is going (CMDF_WRITE?) */
+ if((s->subdev_flags & SDF_CMD_READ)){
unsigned int n_munge_bytes;
-
n_munge_bytes = bi.buf_write_count - s->async->munge_count;
comedi_buf_munge(dev, s, n_munge_bytes);
}
}
-#define RDEV_OF_FILE(x) ((x)->f_dentry->d_inode->i_rdev)
-
void comedi_unmap(struct vm_area_struct *area)
{
comedi_async *async;
static int comedi_mmap(struct file * file, struct vm_area_struct *vma)
{
- unsigned int minor = MINOR(RDEV_OF_FILE(file));
+ const unsigned minor = iminor(file->f_dentry->d_inode);
comedi_device *dev = comedi_get_device_by_minor(minor);
comedi_async *async = NULL;
unsigned long start = vma->vm_start;
if(!dev->attached)
{
- DPRINTK("no driver configured on comedi%i\n", minor);
+ DPRINTK("no driver configured on comedi%i\n", dev->minor);
return -ENODEV;
}
-
- if(vma->vm_flags & VM_WRITE){
- async=dev->write_subdev->async;
- }else{
- async=dev->read_subdev->async;
+ comedi_subdevice *s = comedi_get_subdevice_by_minor(minor);
+ if(s == NULL)
+ { if(vma->vm_flags & VM_WRITE){
+ s = dev->write_subdev;
+ }else{
+ s = dev->read_subdev;
+ }
+ if(s == NULL) return -EINVAL;
}
+ async = s->async;
if(async==NULL){
return -EINVAL;
}
static unsigned int comedi_poll(struct file *file, poll_table * wait)
{
- comedi_device *dev;
comedi_subdevice *s;
comedi_async *async;
unsigned int mask;
-
- dev=comedi_get_device_by_minor(MINOR(RDEV_OF_FILE(file)));
+ const unsigned minor = iminor(file->f_dentry->d_inode);
+ comedi_device *dev = comedi_get_device_by_minor(minor);
if(!dev->attached)
{
- DPRINTK("no driver configured on comedi%i\n", MINOR(dev->devt));
+ DPRINTK("no driver configured on comedi%i\n", dev->minor);
return -ENODEV;
}
comedi_async *async;
int n,m,count=0,retval=0;
DECLARE_WAITQUEUE(wait,current);
-
- dev=comedi_get_device_by_minor(MINOR(RDEV_OF_FILE(file)));
+ const unsigned minor = iminor(file->f_dentry->d_inode);
+ dev = comedi_get_device_by_minor(minor);
if(!dev->attached)
{
- DPRINTK("no driver configured on comedi%i\n", MINOR(dev->devt));
+ DPRINTK("no driver configured on comedi%i\n", dev->minor);
return -ENODEV;
}
- if(dev->write_subdev == NULL)return -EIO;
- s = dev->write_subdev;
+ s = comedi_get_subdevice_by_minor(minor);
+ if(s == NULL)
+ s = dev->write_subdev;
+ if(s == NULL || s->async == NULL || (s->subdev_flags & SDF_CMD_WRITE) == 0) return -EIO;
async = s->async;
if(!nbytes)return 0;
static ssize_t comedi_read(struct file * file,char *buf,size_t nbytes,loff_t *offset)
{
- comedi_device *dev;
comedi_subdevice *s;
comedi_async *async;
int n,m,count=0,retval=0;
DECLARE_WAITQUEUE(wait,current);
-
- dev=comedi_get_device_by_minor(MINOR(RDEV_OF_FILE(file)));
+ const unsigned minor = iminor(file->f_dentry->d_inode);
+ comedi_device *dev = comedi_get_device_by_minor(minor);
if(!dev->attached)
{
- DPRINTK("no driver configured on comedi%i\n", MINOR(dev->devt));
+ DPRINTK("no driver configured on comedi%i\n", dev->minor);
return -ENODEV;
}
- s = dev->read_subdev;
- if(s == NULL)return -EIO;
+ s = comedi_get_subdevice_by_minor(minor);
+ if(s == NULL)
+ s = dev->read_subdev;
+ if(s == NULL || s->async == NULL || (s->subdev_flags & SDF_CMD_READ) == 0) return -EIO;
async = s->async;
if(!nbytes)return 0;
static loff_t comedi_lseek(struct file *file,loff_t offset,int origin)
{
- comedi_device *dev;
loff_t new_offset;
-
- dev=comedi_get_device_by_minor(MINOR(RDEV_OF_FILE(file)));
+ const unsigned minor = iminor(file->f_dentry->d_inode);
+ comedi_device *dev = comedi_get_device_by_minor(minor);
switch(origin){
case SEEK_SET:
return file->f_pos=new_offset;
}
-static int comedi_open(struct inode *inode,struct file *file)
+static int comedi_open(struct inode *inode, struct file *file)
{
- unsigned int minor=MINOR(inode->i_rdev);
- comedi_device *dev;
char mod[32];
-
- if(minor>=COMEDI_NDEVICES){
+ const unsigned minor = iminor(inode);
+ comedi_device *dev = comedi_get_device_by_minor(minor);
+ if(dev == NULL)
+ {
DPRINTK("invalid minor number\n");
return -ENODEV;
}
- dev=comedi_get_device_by_minor(minor);
/* This is slightly hacky, but we want module autoloading
* to work for root.
dev->in_request_module=1;
- sprintf(mod,"char-major-%i-%i",COMEDI_MAJOR,minor);
+ sprintf(mod,"char-major-%i-%i", COMEDI_MAJOR, dev->minor);
#ifdef CONFIG_KMOD
request_module(mod);
#endif
static int comedi_close(struct inode *inode,struct file *file)
{
- comedi_device *dev=comedi_get_device_by_minor(MINOR(inode->i_rdev));
+ const unsigned minor = iminor(inode);
+ comedi_device *dev = comedi_get_device_by_minor(minor);
comedi_subdevice *s = NULL;
int i;
static int comedi_fasync (int fd, struct file *file, int on)
{
- comedi_device *dev=comedi_get_device_by_minor(MINOR(RDEV_OF_FILE(file)));
+ const unsigned minor = iminor(file->f_dentry->d_inode);
+ comedi_device *dev = comedi_get_device_by_minor(minor);
return fasync_helper(fd,file,on,&dev->async_queue);
}
-static struct file_operations comedi_fops={
+struct file_operations comedi_fops={
owner : THIS_MODULE,
llseek : comedi_lseek,
ioctl : comedi_ioctl,
fasync : comedi_fasync,
};
-static struct class *comedi_class;
+struct class *comedi_class = NULL;
+static struct cdev comedi_cdev;
static int __init comedi_init(void)
{
int i;
+ int retval;
printk("comedi: version " COMEDI_RELEASE " - David Schleef <ds@schleef.org>\n");
spin_lock_init(&big_comedi_lock);
- if(devfs_register_chrdev(COMEDI_MAJOR,"comedi",&comedi_fops)){
- printk("comedi: unable to get major %d\n",COMEDI_MAJOR);
+ retval = register_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS, "comedi");
+ if(retval) return -EIO;
+ cdev_init(&comedi_cdev, &comedi_fops);
+ comedi_cdev.owner = THIS_MODULE;
+ kobject_set_name(&comedi_cdev.kobj, "comedi");
+ if(cdev_add(&comedi_cdev, MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS))
+ {
+ unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
return -EIO;
}
comedi_class = class_create(THIS_MODULE, "comedi");
if(IS_ERR(comedi_class))
{
printk("comedi: failed to create class");
- devfs_unregister_chrdev(COMEDI_MAJOR,"comedi");
+ unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
+ cdev_del(&comedi_cdev);
return PTR_ERR(comedi_class);
}
comedi_devices=(comedi_device *)kmalloc(sizeof(comedi_device)*COMEDI_NDEVICES,GFP_KERNEL);
if(!comedi_devices)
{
+ unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
+ cdev_del(&comedi_cdev);
class_destroy(comedi_class);
- devfs_unregister_chrdev(COMEDI_MAJOR,"comedi");
return -ENOMEM;
}
memset(comedi_devices,0,sizeof(comedi_device)*COMEDI_NDEVICES);
for(i=0;i<COMEDI_NDEVICES;i++){
char name[20];
- struct class_device *class_dev;
sprintf(name, "comedi%d", i);
- devfs_register(NULL, name, DEVFS_FL_DEFAULT,
- COMEDI_MAJOR, i, 0666 | S_IFCHR, &comedi_fops, NULL);
- class_dev = COMEDI_CLASS_DEVICE_CREATE(comedi_class, 0,
+ comedi_devices[i].minor = i;
+ comedi_devices[i].class_dev = COMEDI_CLASS_DEVICE_CREATE(comedi_class, 0,
MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i", i);
- comedi_devices[i].devt = class_dev->devt;
- comedi_devices[i].minor = MINOR(class_dev->devt);
spin_lock_init(&comedi_devices[i].spinlock);
}
for(i = 0; i < COMEDI_NDEVICES; i++){
comedi_device *dev;
- dev=comedi_get_device_by_minor(i);
+ dev = comedi_devices + i;
if(dev->attached)
comedi_device_detach(dev);
}
for(i = 0; i < COMEDI_NDEVICES; i++){
char name[20];
- class_device_destroy(comedi_class, comedi_devices[i].devt);
+ class_device_destroy(comedi_class, comedi_devices[i].class_dev->devt);
sprintf(name, "comedi%d", i);
- devfs_unregister(devfs_find_handle(NULL, name,
- COMEDI_MAJOR, i, DEVFS_SPECIAL_CHR, 0));
}
class_destroy(comedi_class);
- devfs_unregister_chrdev(COMEDI_MAJOR,"comedi");
+ cdev_del(&comedi_cdev);
+ unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
comedi_proc_cleanup();
void comedi_error(const comedi_device *dev,const char *s)
{
- rt_printk("comedi%d: %s: %s\n", MINOR(dev->devt), dev->driver->driver_name, s);
+ rt_printk("comedi%d: %s: %s\n", dev->minor, dev->driver->driver_name, s);
}
void comedi_event(comedi_device *dev,comedi_subdevice *s, unsigned int mask)
if(dev->rt){
#ifdef CONFIG_COMEDI_RT
// pend wake up
- if(s==dev->read_subdev)
+ if(s->subdev_flags & SDF_CMD_READ)
comedi_rt_pend_wakeup(&dev->read_wait);
- if(s==dev->write_subdev)
+ if(s->subdev_flags & SDF_CMD_WRITE)
comedi_rt_pend_wakeup(&dev->write_wait);
#else
printk("BUG: comedi_event() code unreachable\n");
#endif
}else{
- if(s==dev->read_subdev){
+ if(s->subdev_flags & SDF_CMD_READ){
wake_up_interruptible(&dev->read_wait);
kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
}
- if(s==dev->write_subdev){
+ if(s->subdev_flags & SDF_CMD_WRITE){
wake_up_interruptible(&dev->write_wait);
kill_fasync(&dev->async_queue, SIGIO, POLL_OUT);
}
--- /dev/null
+
+#ifndef _COMEDI_FOPS_H
+#define _COMEDI_FOPS_H
+
+extern struct class *comedi_class;
+extern struct file_operations comedi_fops;
+
+#endif //_COMEDI_FOPS_H
#define _GNU_SOURCE
#define __NO_VERSION__
+#include "comedi_fops.h"
+#include <linux/device.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/wrapper.h>
#include <linux/highmem.h> /* for SuSE brokenness */
#include <linux/vmalloc.h>
+#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/system.h>
for(i = 0; i < dev->n_subdevices; i++)
{
s = dev->subdevices + i;
+ if(s->class_dev)
+ {
+ class_device_destroy(comedi_class, s->class_dev->devt);
+ }
if(s->async)
{
comedi_buf_alloc(dev, s, 0);
for(i=0;i<COMEDI_NDEVICES;i++){
comedi_device *dev;
- dev=comedi_get_device_by_minor(i);
+ dev = comedi_devices + i;
if(dev->attached && dev->driver==driver){
if(dev->use_count)
printk("BUG! detaching device with use_count=%d\n",dev->use_count);
comedi_device *comedi_allocate_dev(comedi_driver *driver)
{
- comedi_device *dev;
-
- // XXX we need to do actual allocation here.
-
- dev=comedi_get_device_by_minor(0);
-
- dev->driver=driver;
-
- return dev;
+ return NULL;
}
void comedi_deallocate_dev(comedi_device *dev)
s->len_chanlist=1;
if(s->do_cmd){
+ unsigned minor;
+ dev_t devt;
+
async = kmalloc(sizeof(comedi_async), GFP_KERNEL);
if(async == NULL)
{
ret = s->buf_change(dev,s,DEFAULT_BUF_SIZE);
if(ret < 0)return ret;
}
+ minor = comedi_construct_minor_for_subdevice(dev, i);
+ devt = MKDEV(COMEDI_MAJOR, minor);
+ s->class_dev = COMEDI_CLASS_DEVICE_CREATE(comedi_class, dev->class_dev,
+ devt, NULL, "comedi%i_sub%i", dev->minor, i);
}
if(!s->range_table && !s->range_table_list)
dev->read_subdev = subdevice;
subdevice->type = COMEDI_SUBD_AI;
- subdevice->subdev_flags = SDF_READABLE|SDF_COMMON;
+ subdevice->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
//
// TODO: Add external multiplexer data
s->cancel=pci9118_ai_cancel;
s->insn_read=pci9118_insn_read_ai;
if (dev->irq) {
+ s->subdev_flags |= SDF_CMD_READ;
s->do_cmdtest=pci9118_ai_cmdtest;
s->do_cmd=pci9118_ai_cmd;
s->munge=pci9118_ai_munge;
s->cancel=pci171x_ai_cancel;
s->insn_read=pci171x_insn_read_ai;
if (irq) {
+ s->subdev_flags |= SDF_CMD_READ;
s->do_cmdtest=pci171x_ai_cmdtest;
s->do_cmd=pci171x_ai_cmd;
}
s->private = subpriv;
s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE;
+ s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
if (has_int_sce) {
s->n_chan = DIO200_MAX_ISNS;
s->len_chanlist = DIO200_MAX_ISNS;
PC236_DRIVER_NAME, dev) >= 0) {
dev->irq = irq;
s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE;
+ s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
s->n_chan = 1;
s->maxdata = 1;
s->range_table = &range_digital;
s = dev->subdevices + 0;
/* Analog output subdevice. */
s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
+ s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
s->n_chan = thisboard->ao_chans;
s->maxdata = (1 << thisboard->ao_bits) - 1;
s->insn_write = &pci224_ao_insn_write;
*/
/*
-extra triggered scan functionality, interrupt bug-fix added by Steve Sharples
+extra triggered scan functionality, interrupt bug-fix added by Steve Sharples
*/
#include <linux/comedidev.h>
#define PCI230_ZCLK_SCE 0x1A /* Group Z Clock Configuration Register */
#define PCI230_ZGAT_SCE 0x1D /* Group Z Gate Configuration Register */
#define PCI230_INT_SCE 0x1E /* ISR Interrupt source mask register/Interrupt status */
-
+
/* PCI230 i/o space 2 registers. */
#define PCI230_DACCON 0x00
#define PCI230_DACOUT1 0x02
#define PCI230_ADCG 0x0E
/* Convertor related constants. */
-#define PCI230_DAC_SETTLE 5 /* Analogue output settling time in µs (DAC itself is 1µs nominally). */
-#define PCI230_ADC_SETTLE 1 /* Analogue input settling time in µs (ADC itself is 1.6µs nominally but we poll anyway). */
+#define PCI230_DAC_SETTLE 5 /* Analogue output settling time in µs (DAC itself is 1µs nominally). */
+#define PCI230_ADC_SETTLE 1 /* Analogue input settling time in µs (ADC itself is 1.6µs nominally but we poll anyway). */
#define PCI230_MUX_SETTLE 10 /* ADC MUX settling time in µS - 10µs for se, 20µs de. */
/* DACCON values. */
#define PCI230_ZCLK_CT2 16
#define PCI230_ZCLK_RES 24
#define PCI230_ZCLK_SRC_PPCN 0 /* The counter/timer's CLK input from the SK1 connector. */
-#define PCI230_ZCLK_SRC_10MHZ 1 /* The internal 10MHz clock. */
-#define PCI230_ZCLK_SRC_1MHZ 2 /* The internal 1MHz clock. */
-#define PCI230_ZCLK_SRC_100KHZ 3 /* The internal 100kHz clock. */
-#define PCI230_ZCLK_SRC_10KHZ 4 /* The internal 10kHz clock. */
-#define PCI230_ZCLK_SRC_1KHZ 5 /* The internal 1kHz clock. */
-#define PCI230_ZCLK_SRC_OUTNM1 6 /* The output of the preceding counter/timer channel (OUT n-1). */
-#define PCI230_ZCLK_SRC_EXTCLK 7 /* The dedicated external clock input for the group (X1/X2, Y1/Y2, Z1/Z2). */
+#define PCI230_ZCLK_SRC_10MHZ 1 /* The internal 10MHz clock. */
+#define PCI230_ZCLK_SRC_1MHZ 2 /* The internal 1MHz clock. */
+#define PCI230_ZCLK_SRC_100KHZ 3 /* The internal 100kHz clock. */
+#define PCI230_ZCLK_SRC_10KHZ 4 /* The internal 10kHz clock. */
+#define PCI230_ZCLK_SRC_1KHZ 5 /* The internal 1kHz clock. */
+#define PCI230_ZCLK_SRC_OUTNM1 6 /* The output of the preceding counter/timer channel (OUT n-1). */
+#define PCI230_ZCLK_SRC_EXTCLK 7 /* The dedicated external clock input for the group (X1/X2, Y1/Y2, Z1/Z2). */
/* Group Z gate configuration register values. */
#define PCI230_ZGAT_CT0 0
int ai_bits;
int have_ao;
int ao_chans;
- int ao_bits;
+ int ao_bits;
int have_dio;
}pci230_board;
static pci230_board pci230_boards[] = {
struct pci230_private{
struct pci_dev *pci_dev;
lsampl_t ao_readback[2]; /* Used for AO readback */
- unsigned long pci_iobase; /* PCI230's I/O space 1 */
- /* Divisors for 8254 counter/timer. */
+ unsigned long pci_iobase; /* PCI230's I/O space 1 */
+ /* Divisors for 8254 counter/timer. */
unsigned int clk_src0; /* which clock to use for the counter/timers: 10MHz, 1MHz, 100kHz etc */
unsigned int clk_src1;
unsigned int clk_src2;
unsigned int divisor0;
unsigned int divisor1;
unsigned int divisor2;
- unsigned int int_en; /* Interrupt enables bits. */
+ unsigned int int_en; /* Interrupt enables bits. */
unsigned int ai_count; /* Number of analogue input samples remaining. */
unsigned int ao_count; /* Number of analogue output samples remaining. */
unsigned int ai_stop; /* Flag set when cmd->stop_src == TRIG_NONE - user chooses to stop continuous conversion by cancelation. */
#define devpriv ((struct pci230_private *)dev->private)
-/* PCI230 analogue input range table */
+/* PCI230 analogue input range table */
static comedi_lrange pci230_ai_range = { 7, {
BIP_RANGE(10),
BIP_RANGE(5),
UNI_RANGE(2.5)
}};
-/* PCI230 analogue output range table */
+/* PCI230 analogue output range table */
static comedi_lrange pci230_ao_range = { 2, {
UNI_RANGE(10),
BIP_RANGE(10)
static void pci230_handle_ai(comedi_device *dev, comedi_subdevice *s);
static void pci230_handle_fifo_half_full(comedi_device *dev, comedi_subdevice *s);
static void pci230_handle_fifo_not_empty(comedi_device *dev, comedi_subdevice *s);
-
+
static sampl_t pci230_ai_read(comedi_device *dev)
{
/* Read sample. */
/* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower four bits reserved for expansion). */
data = data>>4;
- /* If a bipolar range was specified, mangle it (twos complement->straight binary). */
+ /* If a bipolar range was specified, mangle it (twos complement->straight binary). */
if (devpriv->ai_bipolar) {
data ^= 1<<(thisboard->ai_bits-1);
}
static void pci230_ao_write(comedi_device *dev, sampl_t data, int chan)
{
- /* If a bipolar range was specified, mangle it (straight binary->twos complement). */
+ /* If a bipolar range was specified, mangle it (straight binary->twos complement). */
if (devpriv->ao_bipolar) {
data ^= 1<<(thisboard->ao_bits-1);
}
-
+
/* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower four bits reserved for expansion). */
data = data<<4;
-
+
/* Write data. */
outw((unsigned int) data, dev->iobase + (((chan) == 0) ? PCI230_DACOUT1 : PCI230_DACOUT2));
}
int i=0,irq_hdl;
printk("comedi%d: amplc_pci230\n",dev->minor);
-
+
/* Allocate the private structure area using alloc_private().
* Macro defined in comedidev.h - memsets struct fields to 0. */
if((alloc_private(dev,sizeof(struct pci230_private)))<0){
return -ENOMEM;
}
/* Find card */
- for(pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); pci_dev != NULL ;
+ for(pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); pci_dev != NULL ;
pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) {
if(pci_dev->vendor != PCI_VENDOR_ID_AMPLICON)
continue;
}
devpriv->pci_dev = pci_dev;
dev->board_ptr = pci230_boards+i;
-
+
/* Read base addressses of the PCI230's two I/O regions from PCI configuration register. */
if(pci_enable_device(pci_dev)<0){
return -EIO;
dev->irq = devpriv->pci_dev->irq;
printk("comedi%d: amplc_pci230: registered irq %u\n", dev->minor, devpriv->pci_dev->irq);
}
-
+
/*
* Allocate the subdevice structures. alloc_subdevice() is a
* convenient macro defined in comedidev.h.
/* Only register commands if the interrupt handler is installed. */
if(irq_hdl==0) {
dev->read_subdev=s;
+ s->subdev_flags |= SDF_CMD_READ;
s->do_cmd = &pci230_ai_cmd;
s->do_cmdtest = &pci230_ai_cmdtest;
s->cancel = pci230_ai_cancel;
/* Only register commands if the interrupt handler is installed. */
if(irq_hdl==0) {
dev->write_subdev=s;
+ s->subdev_flags |= SDF_CMD_WRITE;
s->do_cmd = &pci230_ao_cmd;
s->do_cmdtest = &pci230_ao_cmdtest;
s->cancel = pci230_ao_cancel;
/*
* _detach is called to deconfigure a device. It should deallocate
- * resources.
+ * resources.
* This function is also called when _attach() fails, so it should be
* careful not to release resources that were not necessarily
* allocated by _attach(). dev->private and dev->subdevices are
pci_dev_put(devpriv->pci_dev);
}
}
-
+
return 0;
}
/*
- * COMEDI_SUBD_AI instruction;
- */
+ * COMEDI_SUBD_AI instruction;
+ */
static int pci230_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
{
int n,i;
if (aref==AREF_DIFF) {
/* Differential. */
adcen = 3<<2*chan;
- adccon |= PCI230_ADC_IM_DIF;
+ adccon |= PCI230_ADC_IM_DIF;
if (devpriv->ai_bipolar) {
adccon |= PCI230_ADC_IR_BIP;
adcg = range<<(2*chan-2*chan%2);
else {
/* Single ended. */
adcen = 1<<chan;
- adccon |= PCI230_ADC_IM_SE;
+ adccon |= PCI230_ADC_IM_SE;
if (devpriv->ai_bipolar) {
adccon |= PCI230_ADC_IR_BIP;
adcg = range<<(chan-chan%2);
}
/*
- * COMEDI_SUBD_AO instructions;
- */
+ * COMEDI_SUBD_AO instructions;
+ */
static int pci230_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
{
int i;
int chan, range;
-
+
/* Unpack channel and range. */
chan = CR_CHAN(insn->chanspec);
range = CR_RANGE(insn->chanspec);
}
/*
- * COMEDI_SUBD_TIMER instructions;
- *
+ * COMEDI_SUBD_TIMER instructions;
+ *
* insn_config allows user to start and stop counter/timer 2 (SK1 pin 21).
* Period specified in ns.
*
- * rinsn returns counter/timer's actual period in ns.
+ * rinsn returns counter/timer's actual period in ns.
*/
static int pci230_ct_insn_config(comedi_device *dev,comedi_subdevice *s,
comedi_insn *insn,lsampl_t *data)
{
unsigned int ns;
-
+
if(insn->n!=1)return -EINVAL;
ns = data[0];
static int pci230_ct_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
{
if(insn->n!=1)return -EINVAL;
-
+
/* Return the actual period set in ns. */
data[0] = PCI230_TIMEBASE_10MHZ*devpriv->divisor1*devpriv->divisor2;
return 1;
* the command passes. */
/* Step 1: make sure trigger sources are trivially valid.
- * "invalid source" returned by comedilib to user mode process
+ * "invalid source" returned by comedilib to user mode process
* if this fails. */
tmp=cmd->start_src;
if(err)return 1;
/* Step 2: make sure trigger sources are unique and mutually compatible
- * "source conflict" returned by comedilib to user mode process
+ * "source conflict" returned by comedilib to user mode process
* if this fails. */
if(cmd->stop_src!=TRIG_COUNT &&
if(err)return 2;
/* Step 3: make sure arguments are trivially compatible.
- * "invalid argument" returned by comedilib to user mode process
+ * "invalid argument" returned by comedilib to user mode process
* if this fails. */
if(cmd->start_arg!=0){
if(err)return 3;
/* Step 4: fix up any arguments.
- * "argument conflict" returned by comedilib to user mode process
+ * "argument conflict" returned by comedilib to user mode process
* if this fails. */
if(cmd->scan_begin_src==TRIG_TIMER){
devpriv->ao_count = 0;
devpriv->ao_stop = 1;
}
-
+
/* Disable DAC interrupt. */
devpriv->ier &= ~PCI230_INT_ZCLK_CT1;
outb(devpriv->ier, devpriv->pci_iobase + PCI230_INT_SCE);
* the command passes. */
/* Step 1: make sure trigger sources are trivially valid.
- * "invalid source" returned by comedilib to user mode process
+ * "invalid source" returned by comedilib to user mode process
* if this fails. */
tmp=cmd->start_src;
if(err)return 1;
/* Step 2: make sure trigger sources are unique and mutually compatible
- * "source conflict" returned by comedilib to user mode process
+ * "source conflict" returned by comedilib to user mode process
* if this fails. */
if(cmd->start_src!=TRIG_NOW)err++;
cmd->convert_src!=TRIG_EXT)err++;
if(cmd->stop_src!=TRIG_COUNT &&
cmd->stop_src!=TRIG_NONE)err++;
-
+
/* Although the scan and convert triggers come from different sources, the
* driver relies on the knowledge of convert rate to trigger the correct number
- * of channels. If the is not known (ie if convert_src==TRIG_EXT) then the
+ * of channels. If the is not known (ie if convert_src==TRIG_EXT) then the
* scan trigger will not work correctly.
* The convert trigger is the input into the "EXT TRIG" line (pin 25), whilst
* the scan trigger is "PPC0" (pin 49). */
if(err)return 2;
/* Step 3: make sure arguments are trivially compatible.
- * "invalid argument" returned by comedilib to user mode process
+ * "invalid argument" returned by comedilib to user mode process
* if this fails. */
if(cmd->start_arg!=0){
if(err)return 3;
/* Step 4: fix up any arguments.
- * "argument conflict" returned by comedilib to user mode process
+ * "argument conflict" returned by comedilib to user mode process
* if this fails. */
if(cmd->convert_src==TRIG_TIMER){
* - PAUSE (25us) - failure to do this leads to "dodgy data" for the first few channels at high convert rates.
* - Enable conversion complete interrupt.
* - Set the counter timers to the specified sampling frequency.
- * - Enable AND RESET FIFO (yes you do need to do this twice), set FIFO interrupt trigger level, set start conversion source to counter 2.
+ * - Enable AND RESET FIFO (yes you do need to do this twice), set FIFO interrupt trigger level, set start conversion source to counter 2.
*/
/* Disable ADC interrupt. */
if (CR_AREF(cmd->chanlist[0])==AREF_DIFF) {
/* Differential - all channels must be differential. */
diff = 1;
- adccon = PCI230_ADC_IM_DIF;
+ adccon = PCI230_ADC_IM_DIF;
}
else {
/* Single ended - all channels must be single-ended. */
diff = 0;
- adccon = PCI230_ADC_IM_SE;
+ adccon = PCI230_ADC_IM_SE;
}
adccon |= PCI230_ADC_FIFO_RESET | PCI230_ADC_FIFO_EN;
/* If bit 2 of range unset, range is referring to bipolar element in range table */
range = CR_RANGE(cmd->chanlist[0]);
- devpriv->ai_bipolar = !PCI230_TEST_BIT(range, 2);
+ devpriv->ai_bipolar = !PCI230_TEST_BIT(range, 2);
if (devpriv->ai_bipolar) {
adccon |= PCI230_ADC_IR_BIP;
for (i = 0; i < cmd->chanlist_len; i++) {
* This pulse is then used as to gate the counter responsible for your
* convert source.
*
- * So, if your conversion rate is set to 100kHz (10us/conversion) and you
+ * So, if your conversion rate is set to 100kHz (10us/conversion) and you
* have 8 channels in your channel list, a positive edge on PPC0 will
* trigger a pulse of length 80us (8 x 10us). Because the two counters
* involved have the same clock source, the monostable pulse will always
else {
/* Trigger on -ve edge. */
adccon = adccon | PCI230_ADC_TRIG_EXTN;
- }
+ }
}
break;
case TRIG_ROUND_DOWN:
div=(*nanosec + i8253_osc_base + 1 ) / i8253_osc_base;
- break;
+ break;
}
*nanosec = div * i8253_osc_base;
#if 0
-/*
+/*
* Set ZCLK_CT0 to square wave mode with period of ns.
*/
static void pci230_z2_ct0(comedi_device *dev, unsigned int *ns,int round)
}
#endif
-/*
+/*
* Set ZCLK_CT1 to square wave mode with period of ns.
* Default clk source for DAC.
*/
i8254_load(devpriv->pci_iobase + PCI230_Z2_CT0, 1, devpriv->divisor1, 0); /* Counter 1, divisor1, 8254 mode 0. */
}
-/*
+/*
* Set ZCLK_CT2 to square wave mode with period of ns.
* Default clk source for ADC.
*/
/* Disable all of board's interrupts.
* (Only those interrrupts that need re-enabling, are, later in the handler). */
- devpriv->ier = PCI230_INT_DISABLE;
+ devpriv->ier = PCI230_INT_DISABLE;
outb(devpriv->ier, devpriv->pci_iobase + PCI230_INT_SCE);
- /*
+ /*
* Check the source of interrupt and handle it.
* The PCI230 can cope with concurrent ADC, DAC, PPI C0 and C3 interrupts.
* However, at present (Comedi-0.7.60) does not allow concurrent
* execution of commands, instructions or a mixture of the two.
*/
-
+
if (status_int & PCI230_INT_ZCLK_CT1) {
s = dev->write_subdev;
s->async->events = 0;
static void pci230_handle_ai(comedi_device *dev, comedi_subdevice *s) {
int error = 0;
int status_fifo;
-
+
/* Read FIFO state. */
status_fifo = inw(dev->iobase + PCI230_ADCCON);
if (error) {
/* Cancel sampled conversion. */
s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
- pci230_ai_cancel(dev, s);
+ pci230_ai_cancel(dev, s);
}else if(devpriv->ai_count == 0 && devpriv->ai_stop == 0) {
/* Acquisition complete. */
s->async->events |= COMEDI_CB_EOA;
int i;
printk("comedi%d: cb_das16_cs: ",dev->minor);
-
+
link = dev_list; /* XXX hack */
if(!link)return -EIO;
dev->read_subdev=s;
/* analog input subdevice */
s->type=COMEDI_SUBD_AI;
- s->subdev_flags=SDF_READABLE|SDF_GROUND|SDF_DIFF;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
s->n_chan=16;
s->maxdata=0xffff;
s->range_table=&das16cs_ai_range;
}else{
s->type = COMEDI_SUBD_UNUSED;
}
-
+
s=dev->subdevices+3;
/* timer subdevice */
if(0){
if(dev->irq){
comedi_free_irq(dev->irq, dev);
}
-
+
return 0;
}
unsigned int div1, div2;
tmp=cmd->scan_begin_arg;
- i8253_cascade_ns_to_timer(100, &div1, &div2,
+ i8253_cascade_ns_to_timer(100, &div1, &div2,
&cmd->scan_begin_arg, cmd->flags&TRIG_ROUND_MASK);
if(tmp!=cmd->scan_begin_arg)err++;
}
unsigned int div1, div2;
tmp=cmd->convert_arg;
- i8253_cascade_ns_to_timer(100, &div1, &div2,
+ i8253_cascade_ns_to_timer(100, &div1, &div2,
&cmd->scan_begin_arg, cmd->flags&TRIG_ROUND_MASK);
if(tmp!=cmd->convert_arg)err++;
if(cmd->scan_begin_src==TRIG_TIMER &&
.owner = THIS_MODULE,
.drv = {
.name = dev_info,
- },
+ },
};
static int __init init_das16cs_pcmcia_cs(void)
The boards may be autocalibrated using the comedi_calibrate
utility.
-
+
Configuration options:
[0] - PCI bus of device (optional)
[1] - PCI slot of device (optional)
*/
printk("\n");
- for(pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); pcidev != NULL ;
- pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev))
+ for(pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); pcidev != NULL ;
+ pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev))
{
// is it not a computer boards card?
if(pcidev->vendor != PCI_VENDOR_ID_CB)
* Initialize devpriv->control_status and devpriv->adc_fifo to point to
* their base address.
*/
- devpriv->s5933_config = pci_resource_start(devpriv->pci_dev, S5933_BADRINDEX);
- devpriv->control_status = pci_resource_start(devpriv->pci_dev, CONT_STAT_BADRINDEX);
- devpriv->adc_fifo = pci_resource_start(devpriv->pci_dev, ADC_FIFO_BADRINDEX);
- devpriv->pacer_counter_dio = pci_resource_start(devpriv->pci_dev, PACER_BADRINDEX);
+ devpriv->s5933_config = pci_resource_start(devpriv->pci_dev, S5933_BADRINDEX);
+ devpriv->control_status = pci_resource_start(devpriv->pci_dev, CONT_STAT_BADRINDEX);
+ devpriv->adc_fifo = pci_resource_start(devpriv->pci_dev, ADC_FIFO_BADRINDEX);
+ devpriv->pacer_counter_dio = pci_resource_start(devpriv->pci_dev, PACER_BADRINDEX);
if(thisboard->ao_nchan)
{
- devpriv->ao_registers = pci_resource_start(devpriv->pci_dev, AO_BADRINDEX);
+ devpriv->ao_registers = pci_resource_start(devpriv->pci_dev, AO_BADRINDEX);
}
// get irq
/* analog input subdevice */
dev->read_subdev = s;
s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
/* WARNING: Number of inputs in differential mode is ignored */
s->n_chan = thisboard->ai_se_chans;
s->len_chanlist = thisboard->ai_se_chans;
if(thisboard->has_ao_fifo)
{
dev->write_subdev = s;
+ s->subdev_flags |= SDF_CMD_WRITE;
s->insn_write = cb_pcidas_ao_fifo_winsn;
s->do_cmdtest = cb_pcidas_ao_cmdtest;
s->do_cmd = cb_pcidas_ao_cmd;
PCI-DAS6402/12, PCI-DAS64/M1/16, PCI-DAS64/M2/16,
PCI-DAS64/M3/16, PCI-DAS6402/16/JR, PCI-DAS64/M1/16/JR,
PCI-DAS64/M2/16/JR, PCI-DAS64/M3/16/JR, PCI-DAS64/M1/14,
- PCI-DAS64/M2/14, PCI-DAS64/M3/14, PCI-DAS6014,
+ PCI-DAS64/M2/14, PCI-DAS64/M3/14, PCI-DAS6014,
PCI-DAS6023, PCI-DAS6025, PCI-DAS6030,
PCI-DAS6031, PCI-DAS6032, PCI-DAS6033, PCI-DAS6034,
PCI-DAS6035, PCI-DAS6036, PCI-DAS6040, PCI-DAS6052,
/* analog input subdevice */
dev->read_subdev = s;
s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DITHER;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DITHER | SDF_CMD_READ;
if(board(dev)->layout == LAYOUT_60XX)
s->subdev_flags |= SDF_COMMON | SDF_DIFF;
else if(board(dev)->layout == LAYOUT_64XX)
if(board(dev)->ao_nchan)
{
s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
s->n_chan = board(dev)->ao_nchan;
s->maxdata = (1 << board(dev)->ao_bits) - 1;
s->range_table = board(dev)->ao_range_table;
* Probe the device to determine what device in the series it is.
*/
- for(pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); pcidev != NULL ;
- pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev))
+ for(pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); pcidev != NULL ;
+ pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev))
{
// is it not a computer boards card?
if( pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS )
{
lsampl_t source = data[1];
int num_calibration_sources;
-
+
if( board(dev)->layout == LAYOUT_60XX)
num_calibration_sources = 16;
else
static inline void dma_start_sync(comedi_device *dev, unsigned int channel)
{
unsigned long flags;
-
+
// spinlock for plx dma control/status reg
comedi_spin_lock_irqsave( &dev->spinlock, flags );
if(channel)
writew(SELECT_8800_BIT, priv(dev)->main_iobase + CALIBRATION_REG);
comedi_udelay(caldac_8800_udelay);
writew(0, priv(dev)->main_iobase + CALIBRATION_REG);
- comedi_udelay(caldac_8800_udelay);
+ comedi_udelay(caldac_8800_udelay);
return 0;
}
*/
printk("\n");
- for(pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); pcidev != NULL ;
+ for(pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); pcidev != NULL ;
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
if(pcidev->vendor==PCI_VENDOR_ID_CB){
if(it->options[0] || it->options[1]){
s->maxdata = (1 << thisboard->ao_bits) - 1;
s->range_table = thisboard->ranges;
s->insn_write = cb_pcidda_ao_winsn;
-// s->do_cmd = cb_pcidda_ai_cmd;
- s->do_cmdtest = cb_pcidda_ai_cmdtest;
+// s->subdev_flags |= SDF_CMD_READ;
+// s->do_cmd = cb_pcidda_ai_cmd;
+// s->do_cmdtest = cb_pcidda_ai_cmdtest;
// two 8255 digital io subdevices
s = dev->subdevices + 1;
return 2;
}
-
+
static int parport_insn_config_a(comedi_device *dev,comedi_subdevice *s,
comedi_insn *insn,lsampl_t *data)
{
return 1;
}
-
+
static int parport_insn_b(comedi_device *dev,comedi_subdevice *s,
comedi_insn *insn,lsampl_t *data)
{
s->insn_bits = parport_insn_c;
s=dev->subdevices+3;
- dev->read_subdev=s;
if(irq){
+ dev->read_subdev=s;
s->type=COMEDI_SUBD_DI;
- s->subdev_flags=SDF_READABLE;
+ s->subdev_flags=SDF_READABLE | SDF_CMD_READ;
s->n_chan=1;
s->maxdata=1;
s->range_table=&range_digital;
static int parport_detach(comedi_device *dev)
{
printk("comedi%d: parport: remove\n",dev->minor);
-
+
if(dev->iobase)release_region(dev->iobase,PARPORT_SIZE);
if(dev->irq)comedi_free_irq(dev->irq,dev);
case COMEDI_SUBD_AI:
s->insn_read=timer_insn;
dev->read_subdev = s;
+ s->subdev_flags |= SDF_CMD_READ;
devpriv->io_function = timer_data_read;
break;
case COMEDI_SUBD_AO:
s->insn_write=timer_insn;
s->insn_read=timer_insn;
dev->write_subdev = s;
+ s->subdev_flags |= SDF_CMD_WRITE;
devpriv->io_function = timer_data_write;
break;
case COMEDI_SUBD_DIO:
s->insn_read=timer_insn;
s->insn_bits=timer_insn;
dev->read_subdev = s;
+ s->subdev_flags |= SDF_CMD_READ;
devpriv->io_function = timer_dio_read;
break;
default:
if(devpriv->timer_running)
stop_rt_timer();
if(devpriv->device)
- comedi_close(devpriv->device);
+ comedi_close(devpriv->device);
}
return 0;
}
dev->read_subdev = s;
/* analog input subdevice */
s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
s->n_chan = thisboard->ai_chans;
s->maxdata = (1 << thisboard->ai_bits) - 1;
s->range_table = &waveform_ai_ranges;
/* ai */
if(thisboard->ai){
s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE;
+ s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
if(devpriv->ai_singleended){
s->n_chan = 16;
s->len_chanlist = 16;
dev->read_subdev = s;
/* ai */
s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE;
+ s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
s->n_chan = 8;
s->subdev_flags = SDF_DIFF;
s->len_chanlist = 256;
s = dev->subdevices + 0;
dev->read_subdev = s;
s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;
+ s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND | SDF_CMD_READ;
if(thisboard->common)
s->subdev_flags |= SDF_COMMON;
s->n_chan = thisboard->qram_len;
s = dev->subdevices + 0;
dev->read_subdev = s;
s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
s->n_chan = 8;
s->len_chanlist = 8;
s->maxdata = (1 << thisboard->resolution) - 1;
/* analog input subdevice */
s->type=COMEDI_SUBD_AI;
/* we support single-ended (ground) and differential */
- s->subdev_flags=SDF_READABLE|SDF_GROUND|SDF_DIFF;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
s->n_chan=thisboard->ai_chans;
s->maxdata=(1<<thisboard->ai_bits)-1;
s->range_table=thisboard->ai_ranges;
data[n]=(hi<<4)|(lo>>4);
}
-
+
return n;
}
devpriv->ntrig=cmd->stop_arg;
outb(chan|DT2814_ENB|(trigvar<<5),
dev->iobase+DT2814_CSR);
-
+
return 0;
}
save_flags(flags);
sti();
irqs=probe_irq_on();
-
+
outb(0,dev->iobase+DT2814_CSR);
comedi_udelay(100);
s=dev->subdevices+0;
dev->read_subdev = s;
s->type=COMEDI_SUBD_AI;
- s->subdev_flags=SDF_READABLE|SDF_GROUND;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
s->n_chan=16; /* XXX */
s->len_chanlist=1;
s->insn_read = dt2814_ai_insn_read;
static int dt2814_detach(comedi_device *dev)
{
printk("comedi%d: dt2814: remove\n",dev->minor);
-
+
if(dev->irq){
comedi_free_irq(dev->irq,dev);
}
dev->read_subdev=s;
/* ai subdevice */
s->type=COMEDI_SUBD_AI;
- s->subdev_flags=SDF_READABLE|((it->options[opt_diff])?SDF_DIFF:SDF_COMMON);
+ 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;
s->insn_read=dt282x_ai_insn_read;
s->do_cmdtest=dt282x_ai_cmdtest;
/* ao subsystem */
s->type=COMEDI_SUBD_AO;
dev->write_subdev=s;
- s->subdev_flags=SDF_WRITABLE;
+ s->subdev_flags = SDF_WRITABLE | SDF_CMD_WRITE;
s->insn_read=dt282x_ao_insn_read;
s->insn_write=dt282x_ao_insn_write;
s->do_cmdtest=dt282x_ao_cmdtest;
unsigned int status = 0;
writew(cmd,devpriv->io_addr+DPR_Command_Mbx);
-
+
for(i=0;i<TIMEOUT;i++){
status=readw(devpriv->io_addr+DPR_Command_Mbx);
if((status&DT3000_COMPLETION_MASK)!=DT3000_NOTPROCESSED)
}
printk("dt3k_send_cmd() timeout/error status=0x%04x\n",status);
-
+
return -ETIME;
}
unsigned int chan,unsigned int gain)
{
writew(subsys,devpriv->io_addr+DPR_SubSys);
-
+
writew(chan,devpriv->io_addr+DPR_Params(0));
writew(gain,devpriv->io_addr+DPR_Params(1));
-
+
dt3k_send_cmd(dev,CMD_READSINGLE);
return readw(devpriv->io_addr+DPR_Params(2));
unsigned int chan,unsigned int data)
{
writew(subsys,devpriv->io_addr+DPR_SubSys);
-
+
writew(chan,devpriv->io_addr+DPR_Params(0));
writew(0,devpriv->io_addr+DPR_Params(1));
writew(data,devpriv->io_addr+DPR_Params(2));
-
+
dt3k_send_cmd(dev,CMD_WRITESINGLE);
}
rear++;
if(rear>=AI_FIFO_DEPTH)rear = 0;
}
-
+
devpriv->ai_rear = rear;
writew(rear,devpriv->io_addr + DPR_AD_Buf_Rear);
}
return (prescale<<16)|(divider);
}
}
-
+
prescale = 15;
base = timer_base * (1<<prescale);
divider = 65535;
for(i=0;i<cmd->chanlist_len;i++){
chan=CR_CHAN(cmd->chanlist[i]);
range=CR_RANGE(cmd->chanlist[i]);
-
+
writew((range<<6)|chan,devpriv->io_addr+DPR_ADC_buffer+i);
}
aref=CR_AREF(cmd->chanlist[0]);
-
+
writew(cmd->scan_end_arg,devpriv->io_addr+DPR_Params(0));
printk("param[0]=0x%04x\n",cmd->scan_end_arg);
}else{
/* not supported */
}
-
+
mode = DT3000_AD_RETRIG_INTERNAL | 0 | 0;
writew(mode,devpriv->io_addr+DPR_Params(5));
printk("param[5]=0x%04x\n",mode);
writew(AI_FIFO_DEPTH/2,devpriv->io_addr+DPR_Params(7));
printk("param[7]=0x%04x\n",AI_FIFO_DEPTH/2);
-
+
writew(SUBS_AI,devpriv->io_addr+DPR_SubSys);
ret = dt3k_send_cmd(dev,CMD_CONFIG);
{
/* XXX */
writew(SUBS_DOUT,devpriv->io_addr+DPR_SubSys);
-
+
writew(bits,devpriv->io_addr+DPR_Params(0));
#if 0
/* don't know */
writew(0,devpriv->io_addr+DPR_Params(1));
writew(0,devpriv->io_addr+DPR_Params(2));
#endif
-
+
dt3k_send_cmd(dev,CMD_CONFIG);
}
int mask;
mask=(CR_CHAN(insn->chanspec)<4)?0x0f:0xf0;
-
+
switch(data[0])
{
case INSN_CONFIG_DIO_OUTPUT:
default:
return -EINVAL;
break;
- }
+ }
mask=(s->io_bits&0x01)|((s->io_bits&0x10)>>3);
dt3k_dio_config(dev,mask);
data[i]=readw(devpriv->io_addr+DPR_Params(2));
}
-
+
return i;
}
{
comedi_subdevice *s;
int ret=0;
-
+
printk("dt3000:");
-
+
if((ret=alloc_private(dev,sizeof(dt3k_private)))<0)
return ret;
/* ai subdevice */
s->type=COMEDI_SUBD_AI;
- s->subdev_flags=SDF_READABLE|SDF_GROUND|SDF_DIFF;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
s->n_chan=this_board->adchan;
s->insn_read=dt3k_ai_insn;
s->maxdata=(1<<this_board->adbits)-1;
pci_dev_put(devpriv->pci_dev);
}
if(devpriv->io_addr) iounmap(devpriv->io_addr);
- }
+ }
/* XXX */
return 0;
static struct pci_dev *dt_pci_find_device(struct pci_dev *from,int *board)
{
int i;
-
+
for(from=pci_get_device(PCI_VENDOR_ID_DT,PCI_ANY_ID,from); from!=NULL;
from=pci_get_device(PCI_VENDOR_ID_DT,PCI_ANY_ID,from)){
for(i=0;i<n_dt3k_boards;i++){
dev->read_subdev = s;
/* dev->write_subdev = s; */
s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITEABLE | SDF_LSAMPL;
+ s->subdev_flags = SDF_READABLE | SDF_WRITEABLE | SDF_LSAMPL | SDF_CMD_READ;
s->n_chan = 32;
s->len_chanlist = 32;
s->maxdata = 1;
}
else{
dev->read_subdev = s;
+ s->subdev_flags |= SDF_CMD_READ;
s->cancel = me4000_ai_cancel;
s->do_cmdtest = me4000_ai_do_cmd_test;
s->do_cmd = me4000_ai_do_cmd;
subdevice = dev->subdevices + 0;
subdevice->type = COMEDI_SUBD_AI;
- subdevice->subdev_flags = SDF_READABLE | SDF_COMMON;
+ subdevice->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
subdevice->n_chan = board->ai_channel_nbr;
subdevice->maxdata = board->ai_resolution_mask;
subdevice->len_chanlist = board->ai_channel_nbr;
writel(chor, mite->mite_io_addr + MITE_CHOR(channel));
/* short link chaining mode */
- chcr = CHCR_SET_DMA_IE| CHCR_LINKSHORT | CHCR_SET_DONE_IE | CHCR_BURSTEN;
+ chcr = CHCR_SET_DMA_IE | CHCR_LINKSHORT | CHCR_SET_DONE_IE | CHCR_BURSTEN;
/*
* Link Complete Interrupt: interrupt every time a link
* in MITE_RING is completed. This can generate a lot of
{
return CHAN_OFFSET(channel) + 0x20;
};
-static inline int MITE_LLKAR(int channel) // ?
+static inline int MITE_LLKAR(int channel) // see mite section of tnt5002 manual
{
return CHAN_OFFSET(channel) + 0x24;
};
CHOR_CLRRB = (1<<6),
CHOR_CLRLC = (1<<5),
CHOR_FRESET = (1<<4),
- CHOR_ABORT = (1<<3),
- CHOR_STOP = (1<<2),
+ CHOR_ABORT = (1<<3), /* stop without emptying fifo */
+ CHOR_STOP = (1<<2), /* stop after emptying fifo */
CHOR_CONT = (1<<1),
CHOR_START = (1<<0),
CHOR_PON = (CHOR_CLR_SEND_TC|CHOR_CLR_LPAUSE),
s=dev->subdevices + 2;
dev->read_subdev = s;
s->type=COMEDI_SUBD_DI;
- s->subdev_flags=SDF_READABLE;
+ s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
s->n_chan=1;
s->range_table=&range_unknown;
s->maxdata=1;
s=dev->subdevices + 3;
dev->read_subdev = s;
s->type=COMEDI_SUBD_DI;
- s->subdev_flags=SDF_READABLE;
+ s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
s->n_chan=1;
s->range_table=&range_unknown;
s->maxdata=1;
s=dev->subdevices+0;
/* GENERAL-PURPOSE COUNTER/TIME (GPCT) */
s->type = COMEDI_SUBD_COUNTER;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_CMD_READ | SDF_CMD_WRITE;
/* KG: What does SDF_LSAMPL (see multiq3.c) mean? */
s->n_chan = thisboard->n_ctrs;
s->maxdata = 0xffffffff; /* 32 bit counter */
}
printk("attached\n");
-
- /* What does this "return value" mean? Is this fixed by API??
- - skel_attach in skel.c returns 1;
- - ni_E_init in ni_mio_common.c returns "0" ... */
- return 1;
+ return 0;
}
// Check what Application of Counter this channel is configured for
switch(ni_660x_gpct_config[subdev_channel].App)
{
- case PositionMeasurement: case CountingAndTimeMeasurement:
+ case PositionMeasurement: case CountingAndTimeMeasurement:
// Check if (n > 0)
if ( insn->n <= 0 )
{
static void init_tio_chip(comedi_device *dev, int chipset)
{
/* See P. 3.5 of the Register-Level Programming manual. The
- CounterSwap bit has to be set on the second chip, otherwise
+ CounterSwap bit has to be set on the second chip, otherwise
it will try to use the same pins as the first chip.
*/
if(chipset)
+ registerData[ClockConfigRegister].offset);
else
writel(0,devpriv->mite->daq_io_addr + GPCT_OFFSET[0]
- + registerData[ClockConfigRegister].offset);
+ + registerData[ClockConfigRegister].offset);
}
static int
break;
case GPCT_SIMPLE_EVENT:
DPRINTK("NI_660x: INSN_CONFIG: Config Simple Event Counter\n");
- ni_660x_gpct_config[subdev_channel].App =
+ ni_660x_gpct_config[subdev_channel].App =
CountingAndTimeMeasurement;
// Reset the counter
writew(GxReset(counter_channel),
lsampl_t *data)
{
int chan=CR_CHAN(insn->chanspec);
-
+
/* 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 = dev->subdevices + 0;
dev->read_subdev = s;
s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_OTHER;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_OTHER | SDF_CMD_READ;
s->n_chan = 4;
s->len_chanlist = 4;
s->maxdata = 0xffff;
dev->read_subdev = s;
/* ai subdevice */
s->type=COMEDI_SUBD_AI;
- s->subdev_flags=SDF_READABLE|SDF_GROUND;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
s->n_chan=(devpriv->adc_mux? 16 : 8);
s->len_chanlist=16;
s->insn_read = atmio16d_ai_insn_read;
s = dev->subdevices + 0;
dev->read_subdev = s;
s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF;
+ 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
devpriv->ao_cmd1=0;
devpriv->stc_writew(dev, devpriv->ao_cmd1,AO_Command_1_Register);
devpriv->ao_cmd2=0;
+ devpriv->stc_writew(dev, devpriv->ao_cmd2, AO_Command_2_Register);
devpriv->ao_mode1=0;
+ 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)
devpriv->ao_mode3 = AO_Last_Gate_Disable;
else
devpriv->ao_mode3 = 0;
devpriv->stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register);
- devpriv->ao_trigger_select=0;
+ 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){
ao_win_out(0x3, AO_Immediate_671x);
ao_win_out(CLEAR_WG, AO_Misc_611x);
dev->read_subdev=s;
if(boardtype.n_adchan){
s->type=COMEDI_SUBD_AI;
- s->subdev_flags=SDF_READABLE | SDF_DIFF | SDF_DITHER;
+ s->subdev_flags=SDF_READABLE | SDF_DIFF | SDF_DITHER | SDF_CMD_READ;
if(boardtype.reg_type != ni_reg_611x)
s->subdev_flags |= SDF_GROUND | SDF_COMMON | SDF_OTHER;
if(boardtype.adbits > 16)
s=dev->subdevices+1;
if(boardtype.n_aochan){
- dev->write_subdev=s;
s->type=COMEDI_SUBD_AO;
s->subdev_flags=SDF_WRITABLE|SDF_DEGLITCH|SDF_GROUND;
if(boardtype.reg_type == ni_reg_m_series)
#else
if(boardtype.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;
/* general purpose counter/timer device */
s=dev->subdevices+4;
s->type = COMEDI_SUBD_COUNTER;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_CMD_READ;
s->insn_read = ni_gpct_insn_read;
s->insn_write = ni_gpct_insn_write;
s->insn_config = ni_gpct_insn_config;
dev->read_subdev = s;
s->type=COMEDI_SUBD_DIO;
- s->subdev_flags=SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_PACKED;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_PACKED | SDF_CMD_READ;
s->n_chan=32;
s->range_table=&range_digital;
s->maxdata=1;
s = dev->subdevices + 0;
/* AI subdevice */
s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE|SDF_GROUND;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND;
s->n_chan = this_board->n_aichan;
s->maxdata = 0xfff;
s->len_chanlist = 1;
s->range_table = this_board->ai_range_type;
s->insn_read = pcl711_ai_insn;
if(irq){
+ dev->read_subdev = s;
+ s->subdev_flags |= SDF_CMD_READ;
s->do_cmdtest = pcl711_ai_cmdtest;
s->do_cmd = pcl711_ai_cmd;
}
/* analog input */
if (this_board->n_aichan>0) {
s = dev->subdevices + subdev;
- dev->read_subdev = s;
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE;
switch (this_board->board_type) {
devpriv->use_MPC = this_board->haveMPC508;
s->cancel = pcl812_ai_cancel;
if (dev->irq) {
+ dev->read_subdev = s;
+ s->subdev_flags |= SDF_CMD_READ;
s->do_cmdtest = pcl812_ai_cmdtest;
s->do_cmd = pcl812_ai_cmd;
s->poll = pcl812_ai_poll;
s->type = COMEDI_SUBD_AI;
devpriv->sub_ai = s;
dev->read_subdev = s;
- s->subdev_flags = SDF_READABLE;
+ s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
s->n_chan = this_board->n_aichan;
s->subdev_flags |= SDF_DIFF;
//printk (", %dchans DIFF DAC - %d", s->n_chan, i);
subpriv->intr.first_chan = byte_no * 8;
subpriv->intr.asic_chan = thisasic_chanct;
subpriv->intr.num_asic_chans = s->n_chan - subpriv->intr.first_chan;
+ dev->read_subdev = s;
+ s->subdev_flags |= SDF_CMD_READ;
s->cancel = pcmuio_cancel;
s->do_cmd = pcmuio_cmd;
s->do_cmdtest = pcmuio_cmdtest;
* (only the A/D converter is supported), and 'count' is how many
* samples remain to be taken (or -1 if it's unlimited).
*/
-
+
typedef struct local_info_t {
dev_link_t link;
dev_node_t node;
tuple.TupleOffset = 2;
if (pcmcia_get_tuple_data(local->link.handle, &tuple) == 0) {
- for (i=0; i<tuple.TupleDataLen - 4; i++)
+ for (i=0; i<tuple.TupleDataLen - 4; i++)
if (buf[i] == 0) break;
- for (i++; i<tuple.TupleDataLen - 4; i++)
+ for (i++; i<tuple.TupleDataLen - 4; i++)
if (buf[i] == 0) break;
i++;
if ((i < tuple.TupleDataLen - 4)
dev->read_subdev = s;
s->private = local;
s->type=COMEDI_SUBD_AI;
- s->subdev_flags=SDF_READABLE | SDF_GROUND | SDF_DIFF;
+ s->subdev_flags=SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
s->n_chan=8;
s->len_chanlist=2048;
s->maxdata=0xffff;
static int daqp_detach(comedi_device *dev)
{
printk("comedi%d: detaching daqp\n",dev->minor);
-
+
return 0;
}
and other provisions required by the GPL. If you do not delete
the provisions above, a recipient may use your version of this
file under either the MPL or the GPL.
-
+
======================================================================*/
/*
The dev_link structure is initialized, but we don't actually
configure the card at this point -- we wait until we receive a
card insertion event.
-
+
======================================================================*/
static int daqp_cs_attach(struct pcmcia_device *p_dev)
local_info_t *local;
dev_link_t *link;
int i;
-
+
DEBUG(0, "daqp_cs_attach()\n");
for (i = 0; i < MAX_DEV; i++)
printk(KERN_NOTICE "daqp_cs: no devices available\n");
return -ENODEV;
}
-
+
/* Allocate space for private device-specific data */
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) return -ENOMEM;
dev_table[i] = local;
link = &local->link;
link->priv = local;
-
+
/* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = daqp_interrupt;
link->irq.Instance = local;
-
+
/*
General socket configuration defaults can go here. In this
client, we assume very little, and rely on the CIS for almost
local_info_t *dev = link->priv;
DEBUG(0, "daqp_cs_detach(0x%p)\n", link);
-
+
/*
If the device is currently configured and active, we won't
actually delete it yet. Instead, it is marked so that when
/* Unlink device structure, and free it */
dev_table[dev->table_index] = NULL;
kfree(dev);
-
+
} /* daqp_cs_detach */
/*======================================================================
daqp_cs_config() is scheduled to run after a CARD_INSERTION event
is received, to configure the PCMCIA socket, and to make the
device available to the system.
-
+
======================================================================*/
static void daqp_cs_config(dev_link_t *link)
int last_ret;
u_char buf[64];
config_info_t conf;
-
+
DEBUG(0, "daqp_cs_config(0x%p)\n", link);
/*
}
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
-
+
/* Configure card */
link->state |= DEV_CONFIG;
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
if (cfg->index == 0) goto next_entry;
link->conf.ConfigIndex = cfg->index;
-
+
/* Use power settings for Vcc and Vpp if present */
/* Note that the CIS values need to be rescaled */
if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000)
goto next_entry;
}
-
+
if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
link->conf.Vpp1 = link->conf.Vpp2 =
cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
link->conf.Vpp1 = link->conf.Vpp2 =
dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
-
+
/* Do we need to allocate an interrupt? */
if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
link->conf.Attributes |= CONF_ENABLE_IRQ;
-
+
/* IO window settings */
link->io.NumPorts1 = link->io.NumPorts2 = 0;
if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
/* If we got this far, we're cool! */
break;
-
+
next_entry:
if((last_ret = pcmcia_get_next_tuple(handle, &tuple)))
{
goto cs_failed;
}
}
-
+
/*
Allocate an interrupt line. Note that this does not assign a
handler to the interrupt, unless the 'Handler' member of the
cs_error(handle, RequestIRQ, last_ret);
goto cs_failed;
}
-
+
/*
This actually configures the PCMCIA socket -- setting up
the I/O windows and the interrupt mapping, and putting the
printk(" & 0x%04x-0x%04x", link->io.BasePort2,
link->io.BasePort2+link->io.NumPorts2-1);
printk("\n");
-
+
link->state &= ~DEV_CONFIG_PENDING;
return;
After a card is removed, daqp_cs_release() will unregister the
device, and release the PCMCIA configuration. If the device is
still open, this will be postponed until it is closed.
-
+
======================================================================*/
static void daqp_cs_release(u_long arg)
/*
In a normal driver, additional code may be needed to release
- other kernel data structures associated with this device.
+ other kernel data structures associated with this device.
*/
-
+
/* Don't bother checking to see if these succeed or not */
pcmcia_release_configuration(link->handle);
if (link->irq.AssignedIRQ)
pcmcia_release_irq(link->handle, &link->irq);
link->state &= ~DEV_CONFIG;
-
+
} /* daqp_cs_release */
/*======================================================================
private flag to block future accesses to this device. All the
functions that actually access the device should check this flag
to make sure the card is still present.
-
+
======================================================================*/
static int daqp_cs_suspend(struct pcmcia_device *p_dev)
.owner = THIS_MODULE,
.drv = {
.name = dev_info,
- },
+ },
};
int __init init_module(void)
dev->read_subdev=s;
/* analog input subdevice */
s->type=COMEDI_SUBD_AI;
- s->subdev_flags=SDF_READABLE|SDF_GROUND|SDF_COMMON|SDF_DIFF;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF | SDF_CMD_READ;
s->n_chan=thisboard->aiChans;
s->maxdata=(1<<thisboard->aiBits)-1;
if (thisboard->aiMaxGain <= 32) {
COMEDI - Linux Control and Measurement Device Interface
Copyright (C) 2000 David A. Schleef <ds@schleef.org>
-
+
Based on Sensoray Model 626 Linux driver Version 0.2
- Copyright (C) 2002-2004 Sensoray Co., Inc.
+ Copyright (C) 2002-2004 Sensoray Co., Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Configuration Options:
analog input:
none
-
+
analog output:
none
-
+
digital channel:
- s626 has 3 dio subdevices (2,3 and 4) each with 16 i/o channels
+ s626 has 3 dio subdevices (2,3 and 4) each with 16 i/o channels
supported configuration options:
- INSN_CONFIG_DIO_QUERY
+ INSN_CONFIG_DIO_QUERY
COMEDI_INPUT
COMEDI_OUTPUT
encoder:
Every channel must be configured before reading.
-
+
Example code
insn.insn=INSN_CONFIG; //configuration instruction
insn.n=1; //number of operation (must be 1)
- insn.data=&initialvalue; //initial value loaded into encoder
+ insn.data=&initialvalue; //initial value loaded into encoder
//during configuration
insn.subdev=5; //encoder subdevice
- insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); //encoder_channel
+ insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); //encoder_channel
//to configure
-
+
comedi_do_insn(cf,&insn); //executing configuration
*/
ao_bits: 13,
dio_chans: S626_DIO_CHANNELS,
dio_banks: S626_DIO_BANKS,
- enc_chans: S626_ENCODER_CHANNELS,
+ enc_chans: S626_ENCODER_CHANNELS,
}
};
{ 0 }
};
-MODULE_DEVICE_TABLE(pci, s626_pci_table);
+MODULE_DEVICE_TABLE(pci, s626_pci_table);
static int s626_attach(comedi_device *dev,comedi_devconfig *it);
static int s626_detach(comedi_device *dev);
WREdgSel: LP_WREDGSELA,
RDCapSel: LP_RDCAPSELA,
WRCapSel: LP_WRCAPSELA,
- RDCapFlg: LP_RDCAPFLGA,
+ RDCapFlg: LP_RDCAPFLGA,
RDIntSel: LP_RDINTSELA,
WRIntSel: LP_WRINTSELA,
};
WREdgSel: LP_WREDGSELB,
RDCapSel: LP_RDCAPSELB,
WRCapSel: LP_WRCAPSELB,
- RDCapFlg: LP_RDCAPFLGB,
+ RDCapFlg: LP_RDCAPFLGB,
RDIntSel: LP_RDINTSELB,
WRIntSel: LP_WRINTSELB,
};
WREdgSel: LP_WREDGSELC,
RDCapSel: LP_RDCAPSELC,
WRCapSel: LP_WRCAPSELC,
- RDCapFlg: LP_RDCAPFLGC,
+ RDCapFlg: LP_RDCAPFLGC,
RDIntSel: LP_RDINTSELC,
WRIntSel: LP_WRINTSELC,
};
/* to group dio devices (48 bits mask and data are not allowed ???)
static dio_private *dio_private_word[]={
- &dio_private_A,
- &dio_private_B,
+ &dio_private_A,
+ &dio_private_B,
&dio_private_C,
};
*/
static lsampl_t s626_ai_reg_to_uint(int data);
/* static lsampl_t s626_uint_to_reg(comedi_subdevice *s, int data); */
-//end ioctl routines
-
+//end ioctl routines
+
//internal routines
static void s626_dio_init(comedi_device *dev);
static void ResetADC(comedi_device *dev,uint8_t *ppl );
void (*SetLoadTrig)(comedi_device *dev,struct enc_private_struct *,uint16_t Trig); //Program preload trigger source.
void (*SetMode)(comedi_device *dev,struct enc_private_struct *,uint16_t Setup,uint16_t DisableIntSrc); //Program standardized operating mode.
void (*ResetCapFlags)(comedi_device *dev,struct enc_private_struct *); //Reset event capture flags.
-
+
uint16_t MyCRA; // Address of CRA register.
uint16_t MyCRB; // Address of CRB register.
uint16_t MyLatchLsw; // Address of Latch least-significant-word
// bits.
//static const uint16_t EventBits[][4] = { EVBITS(0), EVBITS(1), EVBITS(2), EVBITS(3), EVBITS(4), EVBITS(5) };
-/* enc_private; */
+/* enc_private; */
static enc_private enc_private_data[]={
- {
+ {
GetEnable: GetEnable_A,
GetIntSrc: GetIntSrc_A,
GetLoadTrig: GetLoadTrig_A,
MyLatchLsw: LP_CNTR0ALSW,
MyEventBits: EVBITS(0),
},
- {
+ {
GetEnable: GetEnable_A,
GetIntSrc: GetIntSrc_A,
GetLoadTrig: GetLoadTrig_A,
MyLatchLsw: LP_CNTR1ALSW,
MyEventBits: EVBITS(1),
},
- {
+ {
GetEnable: GetEnable_A,
GetIntSrc: GetIntSrc_A,
GetLoadTrig: GetLoadTrig_A,
MyLatchLsw: LP_CNTR2ALSW,
MyEventBits: EVBITS(2),
},
- {
+ {
GetEnable: GetEnable_B,
GetIntSrc: GetIntSrc_B,
GetLoadTrig: GetLoadTrig_B,
MyLatchLsw: LP_CNTR0BLSW,
MyEventBits: EVBITS(3),
},
- {
+ {
GetEnable: GetEnable_B,
GetIntSrc: GetIntSrc_B,
GetLoadTrig: GetLoadTrig_B,
}};
static int s626_attach(comedi_device *dev,comedi_devconfig *it)
-{
+{
/* uint8_t PollList; */
/* uint16_t AdcData; */
/* uint16_t StartVal; */
dma_addr_t appdma;
comedi_subdevice *s;
struct pci_dev *pdev;
-
+
if(alloc_private(dev,sizeof(s626_private))<0)
return -ENOMEM;
-
+
pdev=pci_get_device(PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626, NULL);
devpriv->pdev = pdev;
-
+
if(pdev==NULL) {
- printk("s626_attach: Board not present!!!");
+ printk("s626_attach: Board not present!!!");
return -ENODEV;
}
-
+
if((result = pci_enable_device(pdev))<0){
printk("s626_attach: pci_enable_device fails\n");
return -ENODEV;
devpriv->got_regions = 1;
resourceStart=pci_resource_start(devpriv->pdev,0);
-
+
devpriv->base_addr=ioremap(resourceStart, SIZEOF_ADDRESS_SPACE);
if (devpriv->base_addr==NULL) {
printk("s626_attach: IOREMAP failed\n");
return -ENODEV;
}
-
+
if (devpriv->base_addr){
- //disable master interrupt
+ //disable master interrupt
writel(0,devpriv->base_addr+P_IER);
-
- //soft reset
+
+ //soft reset
writel(MC1_SOFT_RESET,devpriv->base_addr+P_MC1);
-
+
//DMA FIXME DMA//
DEBUG("s626_attach: DMA ALLOCATION\n");
//adc buffer allocation
devpriv->allocatedBuf=0;
-
+
if((devpriv->ANABuf.LogicalBase = pci_alloc_consistent (devpriv->pdev, DMABUF_SIZE, &appdma))==NULL){
printk("s626_attach: DMA Memory mapping error\n");
return -ENOMEM;
}
-
+
devpriv->ANABuf.PhysicalBase=(void*)appdma;
-
+
DEBUG("s626_attach: AllocDMAB ADC Logical=0x%x, bsize=%d, Physical=0x%x\n",
(uint32_t) devpriv->ANABuf.LogicalBase, DMABUF_SIZE, (uint32_t)devpriv->ANABuf.PhysicalBase);
-
+
devpriv->allocatedBuf++;
-
+
if((devpriv->RPSBuf.LogicalBase = pci_alloc_consistent (devpriv->pdev, DMABUF_SIZE, &appdma)) ==NULL){
printk("s626_attach: DMA Memory mapping error\n");
return -ENOMEM;
}
-
+
devpriv->RPSBuf.PhysicalBase=(void*)appdma;
-
+
DEBUG("s626_attach: AllocDMAB RPS Logical=0x%x, bsize=%d, Physical=0x%x\n",
(uint32_t) devpriv->RPSBuf.LogicalBase, DMABUF_SIZE, (uint32_t)devpriv->RPSBuf.PhysicalBase);
-
+
devpriv->allocatedBuf++;
-
- }
-
+
+ }
+
dev->board_ptr = s626_boards;
dev->board_name = thisboard->name;
s=dev->subdevices+0;
/* analog input subdevice */
dev->read_subdev = s;
- /* we support single-ended (ground) and differential */
+ /* we support single-ended (ground) and differential */
s->type=COMEDI_SUBD_AI;
- s->subdev_flags=SDF_READABLE|SDF_DIFF;
+ s->subdev_flags = SDF_READABLE | SDF_DIFF |SDF_CMD_READ;
s->n_chan=thisboard->ai_chans;
s->maxdata=(0xffff >> 2);
s->range_table=&s626_range_table;
s->len_chanlist=thisboard->ai_chans; /* This is the maximum chanlist
length that the board can
handle */
- s->insn_config = s626_ai_insn_config;
+ 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;
/* analog output subdevice */
s->type=COMEDI_SUBD_AO;
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->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->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->maxdata = 0xffffff;
s->range_table = &range_unknown;
- //stop ai_command
- devpriv->ai_cmd_running=0;
-
+ //stop ai_command
+ devpriv->ai_cmd_running=0;
+
if (devpriv->base_addr && (devpriv->allocatedBuf==2)){
uint32_t *pPhysBuf;
uint16_t chan;
// local bus (DEBI
// never times out).
DEBUG("s626_attach: %d debi init -- %d\n", DEBI_CFG_SLAVE16| ( DEBI_TOUT << DEBI_CFG_TOUT_BIT )| DEBI_SWAP| DEBI_CFG_INTEL, DEBI_CFG_INTEL | DEBI_CFG_TOQ | DEBI_CFG_INCQ| DEBI_CFG_16Q);
-
+
//DEBI INIT S626 WR7146( P_DEBICFG, DEBI_CFG_INTEL | DEBI_CFG_TOQ
//| DEBI_CFG_INCQ| DEBI_CFG_16Q); //end
-
+
// Paging is disabled.
WR7146( P_DEBIPAGE, DEBI_PAGE_DISABLE ); // Disable MMU paging.
// Init GPIO so that ADC Start* is negated.
WR7146( P_GPIO, GPIO_BASE | GPIO1_HI );
-
+
//IsBoardRevA is a boolean that indicates whether the board is
//RevA.
-
+
// VERSION 2.01 CHANGE: REV A & B BOARDS NOW SUPPORTED BY DYNAMIC
// EEPROM ADDRESS SELECTION. Initialize the I2C interface, which
// is used to access the onboard serial EEPROM. The EEPROM's I2C
// configuration EEPROM to reside. On RevA boards, the EEPROM
// device address, which is hardwired to 4, prevents the SAA7146
// from retrieving PCI sub-IDs, so the SAA7146 uses its built-in
- // default values, instead.
-
+ // default values, instead.
+
// devpriv->I2Cards= IsBoardRevA ? 0xA8 : 0xA0; // Set I2C EEPROM
// DeviceType (0xA0)
// and DeviceAddress<<1.
-
+
devpriv->I2CAdrs=0xA0; // I2C device address for onboard
- // eeprom(revb)
-
+ // eeprom(revb)
+
// Issue an I2C ABORT command to halt any I2C operation in
//progress and reset BUSY flag.
WR7146( P_I2CSTAT, I2C_CLKSEL | I2C_ABORT );// Write I2C control:
while ( ( RR7146(P_MC2) & MC2_UPLD_IIC ) == 0 );// and wait for
// upload to
// complete.
-
+
// Per SAA7146 data sheet, write to STATUS reg twice to reset all
// I2C error flags.
for ( i = 0; i < 2; i++ )
while ( !MC_TEST( P_MC2, MC2_UPLD_IIC ) ); // and wait for
// upload to
// complete.
- }
-
+ }
+
// Init audio interface functional attributes: set DAC/ADC serial
// clock rates, invert DAC serial clock so that DAC data setup
// times are satisfied, enable DAC serial clock out.
WR7146( P_ACON2, ACON2_INIT );
-
+
// Set up TSL1 slot list, which is used to control the
// accumulation of ADC data: RSD1 = shift data in on SD1. SIB_A1
// = store data uint8_t at next available location in FB BUFFER1
WR7146( P_TSL1 + 4, RSD1 | SIB_A1 | EOS ); // Fetch ADC low data
// uint8_t; end of
// TSL1.
-
+
// enab TSL1 slot list so that it executes all the time.
WR7146( P_ACON1, ACON1_ADCSTART );
-
+
// Initialize RPS registers used for ADC.
//Physical start of RPS program.
- WR7146( P_RPSADDR1, (uint32_t)devpriv->RPSBuf.PhysicalBase );
+ WR7146( P_RPSADDR1, (uint32_t)devpriv->RPSBuf.PhysicalBase );
WR7146( P_RPSPAGE1, 0 ); // RPS program performs no
// explicit mem writes.
// that it is correctly receiving ADC data. This is necessary
// because the SAA7146 ADC interface does not start up in a
// defined state after a PCI reset.
-
+
/* PollList = EOPL; // Create a simple polling */
/* // list for analog input */
/* // channel 0. */
/* ResetADC( dev, &PollList ); */
-
+
/* s626_ai_rinsn(dev,dev->subdevices,NULL,data); //( &AdcData ); // */
/* //Get initial ADC */
/* //value. */
-
+
/* StartVal = data[0]; */
/* // VERSION 2.01 CHANGE: TIMEOUT ADDED TO PREVENT HANGED EXECUTION. */
/* // possibility that the driver is restarting and the ADC data is a */
/* // fixed value resulting from the applied ADC analog input being */
/* // unusually quiet or at the rail. */
-
+
/* for ( index = 0; index < 500; index++ ) */
/* { */
/* s626_ai_rinsn(dev,dev->subdevices,NULL,data); */
/* if ( AdcData != StartVal ) */
/* break; */
/* } */
-
- // end initADC
-
- // init the DAC interface
-
+
+ // end initADC
+
+ // init the DAC interface
+
// Init Audio2's output DMAC attributes: burst length = 1 DWORD,
// threshold = 1 DWORD.
WR7146( P_PCI_BT_A, 0 );
-
+
// Init Audio2's output DMA physical addresses. The protection
// address is set to 1 DWORD past the base address so that a
// single DWORD will be transferred each time a DMA transfer is
// enabled.
-
+
pPhysBuf = (uint32_t *)devpriv->ANABuf.PhysicalBase + DAC_WDMABUF_OS;
-
+
WR7146( P_BASEA2_OUT, (uint32_t) pPhysBuf ); // Buffer base adrs.
WR7146( P_PROTA2_OUT, (uint32_t) (pPhysBuf + 1) ); // Protection address.
-
+
// Cache Audio2's output DMA buffer logical address. This is
// where DAC data is buffered for A2 output DMA transfers.
devpriv->pDacWBuf = (uint32_t *)devpriv->ANABuf.LogicalBase + DAC_WDMABUF_OS;
-
+
// Audio2's output channels does not use paging. The protection
// violation handling bit is set so that the DMAC will
// automatically halt and its PCI address pointer will be reset
// when the protection address is reached.
WR7146( P_PAGEA2_OUT, 8 );
-
+
// Initialize time slot list 2 (TSL2), which is used to control
// the clock generation for and serialization of data to be sent
// to the DAC devices. Slot 0 is a NOP that is used to trap TSL
SETVECT( 0, XSD2 | RSD3 | SIB_A2 | EOS ); // Slot 0: Trap TSL
// execution, shift 0xFF
// into FB_BUFFER2.
-
+
// Initialize slot 1, which is constant. Slot 1 causes a DWORD to
// be transferred from audio channel 2's output FIFO to the FIFO's
// output buffer so that it can be serialized and sent to the DAC
// populated as required by the target DAC device.
SETVECT( 1, LF_A2 ); // Slot 1: Fetch DWORD from Audio2's
// output FIFO.
-
+
// Start DAC's audio interface (TSL2) running.
WR7146( P_ACON1, ACON1_DACSTART );
-
+
////////////////////////////////////////////////////////
-
+
// end init DAC interface
-
+
// Init Trim DACs to calibrated values. Do it twice because the
// SAA7146 audio channel does not always reset properly and
// sometimes causes the first few TrimDAC writes to malfunction.
-
+
LoadTrimDACs( dev);
LoadTrimDACs( dev); // Insurance.
-
+
//////////////////////////////////////////////////////////////////
// Manually init all gate array hardware in case this is a soft
// reset (we have no way of determining whether this is a warm or
// cold start). This is necessary because the gate array will
// reset only in response to a PCI hard reset; there is no soft
// reset function.
-
+
// Init all DAC outputs to 0V and init all DAC setpoint and
// polarity images.
for ( chan = 0; chan < S626_DAC_CHANNELS; chan++)
SetDAC(dev,chan, 0 );
-
+
// Init image of WRMISC2 Battery Charger Enabled control bit.
// This image is used when the state of the charger control bit,
// which has no direct hardware readback mechanism, is queried.
devpriv->ChargeEnabled = 0;
-
+
// Init image of watchdog timer interval in WRMISC2. This image
// maintains the value of the control bits of MISC2 are
// continuously reset to zero as long as the WD timer is disabled.
devpriv->WDInterval = 0;
-
+
// Init Counter Interrupt enab mask for RDMISC2. This mask is
// applied against MISC2 when testing to determine which timer
// events are requesting interrupt service.
devpriv->CounterIntEnabs = 0;
-
+
// Init counters.
- CountersInit(dev);
-
+ CountersInit(dev);
+
// Without modifying the state of the Battery Backup enab, disable
// the watchdog timer, set DIO channels 0-5 to operate in the
// standard DIO (vs. counter overflow) mode, disable the battery
// charger, and reset the watchdog interval selector to zero.
WriteMISC2(dev, (uint16_t)( DEBIread( dev,LP_RDMISC2 ) & MISC2_BATT_ENABLE ) );
-
+
// Initialize the digital I/O subsystem.
s626_dio_init(dev);
- //enable interrupt test
+ //enable interrupt test
// writel(IRQ_GPIO3 | IRQ_RPS1,devpriv->base_addr+P_IER);
}
-
+
DEBUG("s626_attach: comedi%d s626 attached %04x\n",dev->minor,(uint32_t)devpriv->base_addr);
-
+
return 1;
}
static lsampl_t s626_ai_reg_to_uint(int data){
lsampl_t tempdata;
- tempdata=(data >> 18);
+ tempdata=(data >> 18);
if(tempdata&0x2000)
tempdata&=0x1fff;
else
- tempdata+=(1<<13);
+ tempdata+=(1<<13);
return tempdata;
}
//save interrupt enable register state
irqstatus=readl(devpriv->base_addr+P_IER);
-
+
//read interrupt type
irqtype=readl(devpriv->base_addr+P_ISR);
- //disable master interrupt
+ //disable master interrupt
writel(0,devpriv->base_addr+P_IER);
//clear interrupt
//do somethings
DEBUG("s626_irq_handler: interrupt type %d\n",irqtype);
- switch(irqtype){
+ switch(irqtype){
case IRQ_RPS1: // end_of_scan occurs
DEBUG("s626_irq_handler: RPS1 irq detected\n");
}
if(devpriv->ai_cmd_running && cmd->scan_begin_src==TRIG_EXT){
- DEBUG("s626_irq_handler: enable interrupt on dio channel %d\n",cmd->scan_begin_arg);
-
- s626_dio_set_irq(dev,cmd->scan_begin_arg);
-
+ DEBUG("s626_irq_handler: enable interrupt on dio channel %d\n",cmd->scan_begin_arg);
+
+ s626_dio_set_irq(dev,cmd->scan_begin_arg);
+
DEBUG("s626_irq_handler: External trigger is set!!!\n");
}
s=dev->subdevices;
cmd=&(s->async->cmd);
- //s626_dio_clear_irq(dev);
+ //s626_dio_clear_irq(dev);
for(group=0;group<S626_DIO_BANKS;group++){
irqbit=0;
//read interrupt type
irqbit=DEBIread(dev,((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){
- DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n",cmd->start_arg);
-
+ DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n",cmd->start_arg);
+
// Start executing the RPS program.
- MC_ENABLE( P_MC1, MC1_ERPS1 );
-
+ MC_ENABLE( P_MC1, MC1_ERPS1 );
+
DEBUG("s626_irq_handler: aquisition start triggered!!!\n");
-
- if(cmd->scan_begin_src==TRIG_EXT){
+
+ if(cmd->scan_begin_src==TRIG_EXT){
DEBUG("s626_ai_cmd: enable interrupt on dio channel %d\n",cmd->scan_begin_arg);
-
+
s626_dio_set_irq(dev,cmd->scan_begin_arg);
-
+
DEBUG("s626_irq_handler: External scan trigger is set!!!\n");
}
}
if((irqbit>>(cmd->scan_begin_arg-(16*group)))==1 && cmd->scan_begin_src==TRIG_EXT){
- DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n",cmd->scan_begin_arg);
-
+ DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n",cmd->scan_begin_arg);
+
// Trigger ADC scan loop start by setting RPS Signal 0.
- MC_ENABLE( P_MC2, MC2_ADC_RPS );
+ MC_ENABLE( P_MC2, MC2_ADC_RPS );
DEBUG("s626_irq_handler: scan triggered!!! %d\n",devpriv->ai_sample_count);
if(cmd->convert_src==TRIG_EXT){
-
- DEBUG("s626_ai_cmd: enable interrupt on dio channel %d group %d\n",cmd->convert_arg-(16*group),group);
+
+ DEBUG("s626_ai_cmd: enable interrupt on dio channel %d group %d\n",cmd->convert_arg-(16*group),group);
devpriv->ai_convert_count=cmd->chanlist_len;
-
- s626_dio_set_irq(dev,cmd->convert_arg);
-
+
+ s626_dio_set_irq(dev,cmd->convert_arg);
+
DEBUG("s626_irq_handler: External convert trigger is set!!!\n");
}
}
}
if((irqbit>>(cmd->convert_arg-(16*group)))==1 && cmd->convert_src==TRIG_EXT){
- DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n",cmd->convert_arg);
-
+ DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n",cmd->convert_arg);
+
// Trigger ADC scan loop start by setting RPS Signal 0.
- MC_ENABLE( P_MC2, MC2_ADC_RPS );
+ MC_ENABLE( P_MC2, MC2_ADC_RPS );
DEBUG("s626_irq_handler: adc convert triggered!!!\n");
- devpriv->ai_convert_count--;
+ devpriv->ai_convert_count--;
if(devpriv->ai_convert_count>0){
-
- DEBUG("s626_ai_cmd: enable interrupt on dio channel %d group %d\n",cmd->convert_arg-(16*group),group);
-
- s626_dio_set_irq(dev,cmd->convert_arg);
+
+ DEBUG("s626_ai_cmd: enable interrupt on dio channel %d group %d\n",cmd->convert_arg-(16*group),group);
+
+ s626_dio_set_irq(dev,cmd->convert_arg);
DEBUG("s626_irq_handler: External trigger is set!!!\n");
}
//read interrupt type
irqbit=DEBIread(dev,LP_RDMISC2);
-
+
//check interrupt on counters
DEBUG("s626_irq_handler: check counters interrupt %d\n",irqbit);
//clear interrupt capture flag
k->ResetCapFlags(dev,k);
}
- if(irqbit&IRQ_COINT3A){
+ if(irqbit&IRQ_COINT3A){
DEBUG("s626_irq_handler: interrupt on counter 3A overflow\n");
k=&encpriv[2];
k->ResetCapFlags(dev,k);
if(devpriv->ai_convert_count>0){
- devpriv->ai_convert_count--;
+ devpriv->ai_convert_count--;
if(devpriv->ai_convert_count==0) k->SetEnable(dev,k,CLKENAB_INDEX);
if(cmd->convert_src==TRIG_TIMER){
k->SetEnable(dev,k,CLKENAB_ALWAYS);
}
}
- }
+ }
//enable interrupt
- writel(irqstatus,devpriv->base_addr+P_IER);
-
+ writel(irqstatus,devpriv->base_addr+P_IER);
+
DEBUG("s626_irq_handler: exit interrupt service routine.\n");
comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
if(devpriv){
//stop ai_command
devpriv->ai_cmd_running=0;
-
+
if(devpriv->base_addr){
//interrupt mask
WR7146( P_IER, 0 ); // Disable master interrupt.
WR7146( P_ISR, IRQ_GPIO3 | IRQ_RPS1 ); // Clear board's IRQ status flag.
-
+
// 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 );
-
+
CloseDMAB(dev,&devpriv->RPSBuf,DMABUF_SIZE);
CloseDMAB(dev,&devpriv->ANABuf,DMABUF_SIZE);
}
-
+
if(dev->irq){
comedi_free_irq(dev->irq,dev);
}
-
+
if(devpriv->base_addr){
iounmap(devpriv->base_addr);
}
-
+
if(devpriv->pdev){
if(devpriv->got_regions)
{
pci_dev_put(devpriv->pdev);
}
}
-
+
DEBUG("s626_detach: S626 detached!\n");
-
+
return 0;
}
pRPS = (uint32_t *)devpriv->RPSBuf.LogicalBase;
// Initialize RPS instruction pointer.
- WR7146( P_RPSADDR1, (uint32_t)devpriv->RPSBuf.PhysicalBase );
+ WR7146( P_RPSADDR1, (uint32_t)devpriv->RPSBuf.PhysicalBase );
+
+ // Construct RPS program in RPSBuf DMA buffer
- // Construct RPS program in RPSBuf DMA buffer
-
if(cmd!=NULL && cmd->scan_begin_src!=TRIG_FOLLOW){
DEBUG("ResetADC: scan_begin pause inserted\n");
// Wait for Start trigger.
*pRPS++= RPS_PAUSE | RPS_SIGADC ;
- *pRPS++= RPS_CLRSIGNAL | RPS_SIGADC ;
+ *pRPS++= RPS_CLRSIGNAL | RPS_SIGADC ;
}
// SAA7146 BUG WORKAROUND Do a dummy DEBI Write. This is necessary
// (EOPL,x,x,RANGE,CHAN<3:0>), where RANGE code indicates 0 =
// +-10V, 1 = +-5V, and EOPL = End of Poll List marker.
LocalPPL = ( *ppl << 8 ) | ( *ppl & 0x10 ? GSEL_BIPOLAR5V : GSEL_BIPOLAR10V );
-
+
// Switch ADC analog gain.
*pRPS++= RPS_LDREG | (P_DEBICMD >> 2) ; // Write DEBI command
// and address to
*pRPS++= RPS_UPLOAD | RPS_DEBI ; // Invoke shadow RAM upload.
*pRPS++= RPS_PAUSE | RPS_DEBI ; // Wait for shadow upload to
// finish.
-
+
// Select ADC analog input channel.
*pRPS++= RPS_LDREG | (P_DEBICMD >> 2) ; // Write DEBI command
// and address to
*pRPS++= RPS_UPLOAD | RPS_DEBI ; // Invoke shadow RAM upload.
*pRPS++= RPS_PAUSE | RPS_DEBI ; // Wait for shadow upload to
// finish.
-
+
// Delay at least 10 microseconds for analog input settling.
// Instead of padding with NOPs, we use RPS_JUMP instructions
// here; this allows us to produce a longer delay than is
DEBUG("ResetADC: convert pause inserted\n");
// Wait for Start trigger.
*pRPS++= RPS_PAUSE | RPS_SIGADC ;
- *pRPS++= RPS_CLRSIGNAL | RPS_SIGADC ;
+ *pRPS++= RPS_CLRSIGNAL | RPS_SIGADC ;
}
// Start ADC by pulsing GPIO1.
*pRPS++= RPS_LDREG | (P_GPIO >> 2) ; // Begin ADC Start pulse.
*pRPS++= GPIO_BASE | GPIO1_LO ;
- *pRPS++= RPS_NOP ;
+ *pRPS++= RPS_NOP ;
// VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE.
*pRPS++= RPS_LDREG | (P_GPIO >> 2) ; // End ADC Start pulse.
*pRPS++= GPIO_BASE | GPIO1_HI ;
-
+
// 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.
*pRPS++= RPS_PAUSE | RPS_GPIO2 ; // Wait for ADC done.
-
+
// Transfer ADC data from FB BUFFER 1 register to DMA buffer.
*pRPS++=RPS_STREG | ( BUGFIX_STREG( P_FB_BUFFER1 ) >> 2 ) ;
*pRPS++= (uint32_t)devpriv->ANABuf.PhysicalBase + ( devpriv->AdcItems << 2 ) ;
-
+
// If this slot's EndOfPollList flag is set, all channels have
// now been processed.
if ( *ppl++ & EOPL ) {
devpriv->AdcItems++; // Adjust poll list item count.
break; // Exit poll list processing loop.
- }
+ }
}
DEBUG("ResetADC: ADC items %d \n",devpriv->AdcItems);
-
+
// VERSION 2.01 CHANGE: DELAY CHANGED FROM 250NS to 2US. Allow the
// ADC to stabilize for 2 microseconds before starting the final
// (dummy) conversion. This delay is necessary to allow sufficient
// Wait for the data from the last conversion of interest to arrive
// in FB BUFFER 1 register.
*pRPS++= RPS_PAUSE | RPS_GPIO2 ; // Wait for ADC done.
-
+
// Transfer final ADC data from FB BUFFER 1 register to DMA buffer.
*pRPS++=RPS_STREG | ( BUGFIX_STREG( P_FB_BUFFER1 ) >> 2 ) ;//
*pRPS++=(uint32_t)devpriv->ANABuf.PhysicalBase + ( devpriv->AdcItems << 2 ) ;
// ------------------------------------------------------------
}
-/* TO COMPLETE, IF NECESSARY */
-static int s626_ai_insn_config(comedi_device*dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){
+/* TO COMPLETE, IF NECESSARY */
+static int s626_ai_insn_config(comedi_device*dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){
return -EINVAL;
}
-
+
/* static int s626_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) */
/* { */
/* register uint8_t i; */
/* register int32_t *readaddr; */
/* DEBUG("as626_ai_rinsn: ai_rinsn enter \n"); */
-
+
/* // Trigger ADC scan loop start by setting RPS Signal 0. */
/* MC_ENABLE( P_MC2, MC2_ADC_RPS ); */
-
+
/* // Wait until ADC scan loop is finished (RPS Signal 0 reset). */
/* while ( MC_TEST( P_MC2, MC2_ADC_RPS ) ); */
-
+
/* // 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++ ) { */
/* DEBUG("s626_ai_rinsn: data %d \n",*data); */
/* data++; */
/* } */
-
+
/* DEBUG("s626_ai_rinsn: ai_rinsn escape \n"); */
/* return i; */
/* } */
/* //enabled */
DEBUG("s626_ai_insn_read: entering\n");
-
+
// Convert application's ADC specification into form
// appropriate for register programming.
if(range==0) AdcSpec = ( chan << 8 ) | ( GSEL_BIPOLAR5V );
else AdcSpec = ( chan << 8 ) | ( GSEL_BIPOLAR10V );
-
+
// Switch ADC analog gain.
DEBIwrite( dev, LP_GSEL, AdcSpec ); // Set gain.
-
+
// Select ADC analog input channel.
DEBIwrite( dev, LP_ISEL, AdcSpec ); // Select channel.
-
- for(n=0; n<insn->n; n++){
-
- // Delay 10 microseconds for analog input settling.
+
+ for(n=0; n<insn->n; n++){
+
+ // Delay 10 microseconds for analog input settling.
comedi_udelay(10);
-
+
// Start ADC by pulsing GPIO1 low.
GpioImage = RR7146( P_GPIO );
// Assert ADC Start command
- WR7146( P_GPIO, GpioImage & ~GPIO1_HI );
+ WR7146( P_GPIO, GpioImage & ~GPIO1_HI );
// and stretch it out.
- WR7146( P_GPIO, GpioImage & ~GPIO1_HI );
+ WR7146( P_GPIO, GpioImage & ~GPIO1_HI );
WR7146( P_GPIO, GpioImage & ~GPIO1_HI );
// Negate ADC Start command.
- WR7146( P_GPIO, GpioImage | GPIO1_HI );
-
+ WR7146( P_GPIO, GpioImage | GPIO1_HI );
+
// 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 ) );
-
+ while ( !( RR7146( P_PSR ) & PSR_GPIO2 ) );
+
// Fetch ADC data.
if(n!=0) data[n-1]=s626_ai_reg_to_uint(RR7146( P_FB_BUFFER1 ));
// conversion. Without this delay, the last conversion's
// data value is sometimes set to the previous
// conversion's data value.
- comedi_udelay(4);
+ comedi_udelay(4);
}
-
+
// Start a dummy conversion to cause the data from the
// previous conversion to be shifted in.
GpioImage = RR7146( P_GPIO );
-
+
//Assert ADC Start command
WR7146( P_GPIO, GpioImage & ~GPIO1_HI );
// and stretch it out.
WR7146( P_GPIO, GpioImage & ~GPIO1_HI );
// Negate ADC Start command.
WR7146( P_GPIO, GpioImage | GPIO1_HI );
-
+
// Wait for the data to arrive in FB BUFFER 1 register.
-
+
// Wait for ADC done.
while ( !( RR7146( 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 ));
-
+
DEBUG("s626_ai_insn_read: samples %d, data %d\n",n,data[n-1]);
-
+
return n;
}
static int s626_ai_load_polllist(uint8_t *ppl, comedi_cmd *cmd){
-
+
int n;
for(n=0;n<cmd->chanlist_len;n++){
if(trignum!=0) return -EINVAL;
DEBUG("s626_ai_inttrig: trigger adc start...");
-
+
// Start executing the RPS program.
- MC_ENABLE( P_MC1, MC1_ERPS1 );
+ MC_ENABLE( P_MC1, MC1_ERPS1 );
s->async->inttrig=NULL;
uint8_t ppl[16];
comedi_cmd *cmd=&s->async->cmd;
enc_private *k;
- int tick;
+ int tick;
DEBUG("s626_ai_cmd: entering command function\n");
// s626_enc_clear_irq(dev);
//reset ai_cmd_running flag
- devpriv->ai_cmd_running=0;
+ devpriv->ai_cmd_running=0;
// test if cmd is valid
if(cmd==NULL){
}
s626_ai_load_polllist(ppl,cmd);
- devpriv->ai_cmd_running=1;
+ devpriv->ai_cmd_running=1;
devpriv->ai_convert_count=0;
switch(cmd->scan_begin_src){
break;
case TRIG_EXT:
- // set the digital line and interrupt for scan trigger
- if(cmd->start_src!=TRIG_EXT) s626_dio_set_irq(dev,cmd->scan_begin_arg);
+ // set the digital line and interrupt for scan trigger
+ if(cmd->start_src!=TRIG_EXT) s626_dio_set_irq(dev,cmd->scan_begin_arg);
DEBUG("s626_ai_cmd: External scan trigger is set!!!\n");
-
+
break;
}
break;
case TRIG_EXT:
// set the digital line and interrupt for convert trigger
- if(cmd->scan_begin_src!=TRIG_EXT && cmd->start_src==TRIG_EXT)
+ if(cmd->scan_begin_src!=TRIG_EXT && cmd->start_src==TRIG_EXT)
s626_dio_set_irq(dev, cmd->convert_arg);
DEBUG("s626_ai_cmd: External convert trigger is set!!!\n");
break;
}
- ResetADC(dev,ppl);
+ ResetADC(dev,ppl);
switch(cmd->start_src){
case TRIG_NOW:
// MC_ENABLE( P_MC2, MC2_ADC_RPS );
// Start executing the RPS program.
- MC_ENABLE( P_MC1, MC1_ERPS1 );
+ MC_ENABLE( P_MC1, MC1_ERPS1 );
DEBUG("s626_ai_cmd: ADC triggered\n");
s->async->inttrig=NULL;
s->async->inttrig=s626_ai_inttrig;
break;
}
-
+
//enable interrupt
writel(IRQ_GPIO3 | IRQ_RPS1,devpriv->base_addr+P_IER);
MC_DISABLE( P_MC1, MC1_ERPS1 );
//disable master interrupt
- writel(0,devpriv->base_addr+P_IER);
+ writel(0,devpriv->base_addr+P_IER);
devpriv->ai_cmd_running=0;
static int s626_ns_to_timer(int *nanosec,int round_mode)
{
int divider,base;
-
+
base=500; //2MHz internal clock
switch(round_mode){
}
static int s626_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){
-
+
int i;
uint16_t chan = CR_CHAN(insn->chanspec);
int16_t dacdata;
for(i=0;i<insn->n;i++){
dacdata=(int16_t)data[i];
devpriv->ao_readback[CR_CHAN(insn->chanspec)]=data[i];
- dacdata-= ( 0x1fff );
-
+ dacdata-= ( 0x1fff );
+
SetDAC(dev,chan,dacdata);
}
-
+
return i;
}
static int s626_ao_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
{
- int i;
+ int i;
for(i=0;i<insn->n;i++){
- data[i] = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
+ data[i] = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
}
-
+
return i;
}
{
uint16_t group;
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++ )
{
* 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(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){
-
+static int s626_dio_insn_bits(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){
+
/* Length of data must be 2 (mask and new data, see below) */
if(insn->n == 0){
return 0;
printk("comedi%d: s626: s626_dio_insn_bits(): Invalid instruction length\n", dev->minor);
return -EINVAL;
}
-
- /*
+
+ /*
* 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
/* Check if requested ports are configured for output */
if((s->io_bits & data[0]) != data[0])
return -EIO;
-
+
s->state &= ~data[0];
s->state |= data[0] & data[1];
-
+
/* Write out the new digital output lines */
-
+
DEBIwrite(dev,diopriv->WRDOut,s->state);
}
data[1]=DEBIread(dev,diopriv->RDDIn);
-
+
return 2;
}
static int s626_dio_insn_config(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
-{
+{
switch(data[0]){
case INSN_CONFIG_DIO_QUERY:
return insn->n;
break;
case COMEDI_INPUT:
- s->io_bits&= ~(1 << CR_CHAN(insn->chanspec));
+ s->io_bits&= ~(1 << CR_CHAN(insn->chanspec));
break;
case COMEDI_OUTPUT:
s->io_bits|= 1 << CR_CHAN(insn->chanspec);
break;
}
DEBIwrite(dev,diopriv->WRDOut,s->io_bits);
-
+
return 1;
}
static int s626_dio_set_irq(comedi_device *dev, unsigned int chan)
{
unsigned int group;
- unsigned int bitmask;
- unsigned int status;
+ unsigned int bitmask;
+ unsigned int status;
//select dio bank
group=chan/16;
bitmask=1<<(chan-(16*group));
- DEBUG("s626_dio_set_irq: enable interrupt on dio channel %d group %d\n",chan-(16*group),group);
-
+ DEBUG("s626_dio_set_irq: enable interrupt on dio channel %d group %d\n",chan-(16*group),group);
+
//set channel to capture positive edge
status=DEBIread(dev,((dio_private *)(dev->subdevices+2+group)->private)->RDEdgSel);
DEBIwrite(dev,((dio_private *)(dev->subdevices+2+group)->private)->WREdgSel,bitmask|status);
-
+
//enable interrupt on selected channel
status=DEBIread(dev,((dio_private *)(dev->subdevices+2+group)->private)->RDIntSel);
DEBIwrite(dev,((dio_private *)(dev->subdevices+2+group)->private)->WRIntSel,bitmask|status);
-
+
//enable edge capture write command
DEBIwrite(dev,LP_MISC1,MISC1_EDCAP);
-
+
//enable edge capture on selected channel
status=DEBIread(dev,((dio_private *)(dev->subdevices+2+group)->private)->RDCapSel);
DEBIwrite(dev,((dio_private *)(dev->subdevices+2+group)->private)->WRCapSel,bitmask|status);
-
+
return 0;
}
static int s626_dio_reset_irq(comedi_device *dev, unsigned int group, unsigned int mask)
{
- DEBUG("s626_dio_reset_irq: disable interrupt on dio channel %d group %d\n",mask,group);
+ DEBUG("s626_dio_reset_irq: disable interrupt on dio channel %d group %d\n",mask,group);
//disable edge capture write command
DEBIwrite(dev,LP_MISC1,MISC1_NOEDCAP);
-
+
//enable edge capture on selected channel
DEBIwrite(dev,((dio_private *)(dev->subdevices+2+group)->private)->WRCapSel,mask);
-
+
return 0;
}
//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,((dio_private *)(dev->subdevices+2+group)->private)->WRCapSel,0xffff);
and set the subdevice. To complete with trigger and interrupt
configuration */
static int s626_enc_insn_config(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
-{
+{
uint16_t Setup = ( LOADSRC_INDX << BF_LOADSRC ) | // Preload upon
// index.
( INDXSRC_SOFT << BF_INDXSRC ) | // Disable hardware index.
/* uint16_t DisableIntSrc=TRUE; */
// uint32_t Preloadvalue; //Counter initial value
uint16_t valueSrclatch=LATCHSRC_AB_READ ;
- uint16_t enab=CLKENAB_ALWAYS;
- enc_private *k=&encpriv[CR_CHAN(insn->chanspec)];
+ uint16_t enab=CLKENAB_ALWAYS;
+ enc_private *k=&encpriv[CR_CHAN(insn->chanspec)];
DEBUG("s626_enc_insn_config: encoder config\n");
int n;
enc_private *k=&encpriv[CR_CHAN(insn->chanspec)];
-
- DEBUG("s626_enc_insn_read: encoder read channel %d \n",CR_CHAN(insn->chanspec));
- for (n=0;n<insn->n;n++) data[n]=ReadLatch(dev,k);
-
+ DEBUG("s626_enc_insn_read: encoder read channel %d \n",CR_CHAN(insn->chanspec));
+
+ for (n=0;n<insn->n;n++) data[n]=ReadLatch(dev,k);
+
DEBUG("s626_enc_insn_read: encoder sample %d\n",data[n]);
return n;
enc_private *k=&encpriv[CR_CHAN(insn->chanspec)];
- DEBUG("s626_enc_insn_write: encoder write channel %d \n",CR_CHAN(insn->chanspec));
+ DEBUG("s626_enc_insn_write: encoder write channel %d \n",CR_CHAN(insn->chanspec));
// Set the preload register
Preload(dev,k,data[0]);
-
+
// Software index pulse forces the preload register to load
// into the counter
k->SetLoadTrig(dev, k, 0);
( CLKMULT_1X << BF_CLKMULT ) | // Clock multiplier is 1x.
( CLKENAB_INDEX << BF_CLKENAB );
uint16_t valueSrclatch=LATCHSRC_A_INDXA ;
- // uint16_t enab=CLKENAB_ALWAYS;
+ // uint16_t enab=CLKENAB_ALWAYS;
k->SetMode(dev,k,Setup,FALSE);
// Set the preload register
Preload(dev,k,tick);
-
+
// Software index pulse forces the preload register to load
// into the counter
k->SetLoadTrig(dev, k, 0);
// value (that writes a channel 0 NOP command to a non-existent main
// DAC channel) that serves to keep the clock running after the
// packet has been sent to the target DAC.
-
+
SendDAC(dev, ( (uint32_t)chan << 8 ) // Address the DAC channel
// within the trimdac device.
| (uint32_t)DacData ); // Include DAC setpoint data.
static uint8_t I2Cread(comedi_device *dev, uint8_t addr )
{
uint8_t rtnval;
-
+
// Send EEPROM target address.
if ( I2Chandshake(dev, I2C_B2( I2C_ATTRSTART, I2CW ) // Byte2 = I2C
// command:
// sent.
{
// Abort function and declare error if handshake failed.
- DEBUG("I2Cread: error handshake I2Cread a\n");
+ DEBUG("I2Cread: error handshake I2Cread a\n");
return 0;
}
// sent.
{
// Abort function and declare error if handshake failed.
- DEBUG("I2Cread: error handshake I2Cread b\n");
+ DEBUG("I2Cread: error handshake I2Cread b\n");
return 0;
}
// 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 ) );
// Wait until I2C bus transfer is finished or an error occurs.
while ( ( RR7146(P_I2CCTRL) & ( I2C_BUSY | I2C_ERR ) ) == I2C_BUSY );
-
+
// Return non-zero if I2C error occured.
return RR7146(P_I2CCTRL) & I2C_ERR;
static void SendDAC( comedi_device *dev, uint32_t val )
{
-
+
// START THE SERIAL CLOCK RUNNING -------------
// Assert DAC polarity control and enable gating of DAC serial clock
DEBIwrite(dev, LP_DACPOL, devpriv->Dacpol );
// TRANSFER OUTPUT DWORD VALUE INTO A2'S OUTPUT FIFO ----------------
-
+
// Copy DAC setpoint value to DAC's output DMA buffer.
-
- //WR7146( (uint32_t)devpriv->pDacWBuf, val );
+
+ //WR7146( (uint32_t)devpriv->pDacWBuf, val );
*devpriv->pDacWBuf=val;
// enab the output DMA transfer. This will cause the DMAC to copy
// Write a value to a gate array register.
static void DEBIwrite(comedi_device *dev, uint16_t addr, uint16_t wdata )
{
-
+
// Set up DEBI control register value in shadow RAM.
WR7146( P_DEBICMD, DEBI_CMD_WRWORD | addr );
WR7146( P_DEBIAD, wdata );
if (pdma == NULL)
return;
//find the matching allocation from the board struct
-
+
vbptr=pdma->LogicalBase;
vpptr=pdma->PhysicalBase;
if (vbptr)
(int) vpptr);
pdma->LogicalBase = 0;
pdma->PhysicalBase = 0;
-
+
DEBUG ("CloseDMAB(): Logical=0x%x, bsize=%d, Physical=0x%x\n", (uint32_t) vbptr, bsize, (uint32_t) vpptr);
}
}
value |= ( (uint32_t) DEBIread(dev,k->MyLatchLsw + 2 ) << 16 );
// DEBUG FIXME DEBUG("ReadLatch: Read Latch exit\n");
-
+
// Return latched counts.
return value;
}
}
static void ResetCapFlags_B(comedi_device *dev, enc_private *k )
-{
+{
DEBIreplace(dev, k->MyCRB, (uint16_t)( ~CRBMSK_INTCTRL ), CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B );
}
register uint16_t crb;
register uint16_t setup;
- // Fetch CRA and CRB register images.
+ // Fetch CRA and CRB register images.
cra = DEBIread(dev,k->MyCRA );
crb = DEBIread(dev,k->MyCRB );
// Populate the standardized counter setup bit fields. Note:
// IndexSrc is restricted to ENC_X or IndxPol.
- setup =
+ setup =
( ( ( crb << ( STDBIT_INTSRC - CRBBIT_INTSRC_B ) ) & STDMSK_INTSRC ) // IntSrc = IntSrcB.
| ( ( crb << ( STDBIT_LATCHSRC - CRBBIT_LATCHSRC ) ) & STDMSK_LATCHSRC ) // LatchSrc = LatchSrcB.
| ( ( crb << ( STDBIT_LOADSRC - CRBBIT_LOADSRC_B ) ) & STDMSK_LOADSRC ) // LoadSrc = LoadSrcB.
else // If Counter mode (ClkSrcB<1> == 0):
setup |= ( ( CLKSRC_COUNTER << STDBIT_CLKSRC ) // Indicate Timer mode.
- | ( ( crb >> ( CRBBIT_CLKMULT_B - STDBIT_CLKMULT ) ) & STDMSK_CLKMULT ) // Clock multiplier is passed through.
- | ( ( crb << ( STDBIT_CLKPOL - CRBBIT_CLKPOL_B ) ) & STDMSK_CLKPOL ) ); // Clock polarity is passed through.
+ | ( ( crb >> ( CRBBIT_CLKMULT_B - STDBIT_CLKMULT ) ) & STDMSK_CLKMULT ) // Clock multiplier is passed through.
+ | ( ( crb << ( STDBIT_CLKPOL - CRBBIT_CLKPOL_B ) ) & STDMSK_CLKPOL ) ); // Clock polarity is passed through.
// Return adjusted counter setup.
return setup;
static void SetMode_A(comedi_device *dev, enc_private *k, uint16_t Setup, uint16_t DisableIntSrc )
{
- register uint16_t cra;
+ register uint16_t cra;
register uint16_t crb;
register uint16_t setup = Setup; // Cache the Standard Setup.
// Initialize CRA and CRB images.
cra = ( ( setup & CRAMSK_LOADSRC_A ) // Preload trigger is passed through.
| ( ( setup & STDMSK_INDXSRC ) >> ( STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1) ) ) ); // IndexSrc is restricted to ENC_X or IndxPol.
-
+
crb = ( CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A // Reset any pending CounterA event captures.
| ( ( setup & STDMSK_CLKENAB ) << ( CRBBIT_CLKENAB_A - STDBIT_CLKENAB ) ) ); // Clock enable is passed through.
-
+
// Force IntSrc to Disabled if DisableIntSrc is asserted.
if ( !DisableIntSrc )
cra |= ( ( setup & STDMSK_INTSRC ) >> ( STDBIT_INTSRC - CRABIT_INTSRC_A ) );
// 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, (uint16_t)( ~( CRBMSK_INTCTRL | CRBMSK_CLKENAB_A ) ), crb );
}
static void SetMode_B(comedi_device *dev, enc_private *k, uint16_t Setup, uint16_t DisableIntSrc )
{
- register uint16_t cra;
+ register uint16_t cra;
register uint16_t crb;
register uint16_t setup = Setup; // Cache the Standard Setup.
static void SetIntSrc_B( comedi_device *dev,enc_private *k, uint16_t IntSource )
{
uint16_t crb;
-
+
// Cache writeable CRB register image.
crb = DEBIread(dev, k->MyCRB ) & ~CRBMSK_INTCTRL;
-
+
// Reset any pending counter overflow or index captures.
DEBIwrite(dev, k->MyCRB, (uint16_t)( crb | CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B ) );
static void PulseIndex_A( comedi_device *dev,enc_private *k )
{
register uint16_t cra;
-
+
DEBUG("PulseIndex_A: pulse index enter\n");
static void PulseIndex_B( comedi_device *dev,enc_private *k )
{
register uint16_t crb;
-
+
crb = DEBIread(dev, k->MyCRB ) & ~CRBMSK_INTCTRL; // Pulse index.
DEBIwrite(dev, k->MyCRB, (uint16_t)( crb ^ CRBMSK_INDXPOL_B ) );
- DEBIwrite(dev, k->MyCRB, crb);
+ DEBIwrite(dev, k->MyCRB, crb);
}
/////////////////////////////////////////////////////////
s->len_chanlist=16; /* This is the maximum chanlist length that
the board can handle */
s->insn_read = skel_ai_rinsn;
- //s->do_cmd = skel_ai_cmd;
+// s->subdev_flags |= SDF_CMD_READ;
+// s->do_cmd = skel_ai_cmd;
s->do_cmdtest = skel_ai_cmdtest;
s=dev->subdevices+1;
printk("attached\n");
- return 1;
+ return 0;
}
ret=usbduxsub_unlink_InURBs(this_usbduxsub);
}
- this_usbduxsub->ai_cmd_running=0;
+ this_usbduxsub->ai_cmd_running=0;
return ret;
}
// This will cancel a running acquisition operation.
// This is called by comedi but never from inside the
// driver.
-static int usbdux_ai_cancel(comedi_device *dev,
+static int usbdux_ai_cancel(comedi_device *dev,
comedi_subdevice *s)
{
usbduxsub_t* this_usbduxsub;
static void usbduxsub_ai_IsocIrq(struct urb *urb)
#else
static void usbduxsub_ai_IsocIrq(struct urb *urb, struct pt_regs *regs)
-#endif
+#endif
{
int i,err,n;
usbduxsub_t* this_usbduxsub;
comedi_device *this_comedidev;
comedi_subdevice *s;
-
+
// sanity checks
// is the urb there?
if (!urb) {
printk("comedi_: usbdux_: ao int-handler called with urb=NULL!\n");
return;
}
-
+
// the context variable points to the subdevice
this_comedidev=urb->context;
if (unlikely(!this_comedidev)) {
printk("comedi_: usbdux_: BUG! urb context is a NULL pointer!\n");
return;
}
-
+
// the private structure of the subdevice is usbduxsub_t
this_usbduxsub=this_comedidev->private;
if (unlikely(!this_usbduxsub)) {
printk("comedi_: usbdux_: BUG! private of comedi subdev is a NULL pointer!\n");
return;
}
-
+
// subdevice which is the AD converter
s=this_comedidev->subdevices + SUBDEV_AD;
-
+
// first we test if something unusual has just happened
switch (urb->status) {
case 0:
printk("comedi%d: usbdux: CRC error in ISO IN stream.\n",
this_usbduxsub->comedidev->minor);
#endif
-
+
break;
-
+
// happens after an unlink command
case -ECONNRESET:
case -ENOENT:
// tell this comedi
s->async->events |= COMEDI_CB_EOA;
s->async->events |= COMEDI_CB_ERROR;
- comedi_event(this_usbduxsub->comedidev,
+ comedi_event(this_usbduxsub->comedidev,
s,
s->async->events);
// stop the transfer w/o unlink
urb->status);
s->async->events |= COMEDI_CB_EOA;
s->async->events |= COMEDI_CB_ERROR;
- comedi_event(this_usbduxsub->comedidev,
- s,
+ comedi_event(this_usbduxsub->comedidev,
+ s,
s->async->events);
// don't do an unlink here
usbdux_ai_stop(this_usbduxsub,0);
}
s->async->events |= COMEDI_CB_EOA;
s->async->events |= COMEDI_CB_ERROR;
- comedi_event(this_usbduxsub->comedidev,
- s,
+ comedi_event(this_usbduxsub->comedidev,
+ s,
s->async->events);
// don't do an unlink here
usbdux_ai_stop(this_usbduxsub,0);
return;
}
-
+
this_usbduxsub->ai_counter--;
if (likely(this_usbduxsub->ai_counter>0)) {
return;
// timer zero, transfer measurements to comedi
this_usbduxsub->ai_counter=this_usbduxsub->ai_timer;
-
+
// test, if we transmit only a fixed number of samples
if (!(this_usbduxsub->ai_continous)) {
// not continous, fixed number of samples
0);
// say comedi that the acquistion is over
s->async->events |= COMEDI_CB_EOA;
- comedi_event(this_usbduxsub->comedidev,
- s,
+ comedi_event(this_usbduxsub->comedidev,
+ s,
s->async->events);
return;
}
// transfer data
if (CR_RANGE(s->async->cmd.chanlist[i])<=1) {
comedi_buf_put
- (s->async,
+ (s->async,
le16_to_cpu(this_usbduxsub->inBuffer[i])^0x800);
} else {
comedi_buf_put
- (s->async,
+ (s->async,
le16_to_cpu(this_usbduxsub->inBuffer[i]));
}
}
// tell comedi that data is there
- comedi_event(this_usbduxsub->comedidev,
- s,
+ comedi_event(this_usbduxsub->comedidev,
+ s,
s->async->events);
}
case -ECONNABORTED:
if (this_usbduxsub->ao_cmd_running) {
s->async->events |= COMEDI_CB_EOA;
- comedi_event(this_usbduxsub->comedidev,
- s,
+ comedi_event(this_usbduxsub->comedidev,
+ s,
s->async->events);
usbdux_ao_stop(this_usbduxsub,0);
}
urb->status);
s->async->events |= COMEDI_CB_ERROR;
s->async->events |= COMEDI_CB_EOA;
- comedi_event(this_usbduxsub->comedidev,
- s,
+ comedi_event(this_usbduxsub->comedidev,
+ s,
s->async->events);
// we do an unlink if we are in the high speed mode
usbdux_ao_stop(this_usbduxsub,0);
// normal operation: executing a command in this subdevice
this_usbduxsub->ao_counter--;
- if (this_usbduxsub->ao_counter<=0) {
+ if (this_usbduxsub->ao_counter<=0) {
// timer zero
this_usbduxsub->ao_counter=this_usbduxsub->ao_timer;
usbdux_ao_stop(this_usbduxsub,
0);
s->async->events |= COMEDI_CB_EOA;
- comedi_event(this_usbduxsub->comedidev,
- s,
+ comedi_event(this_usbduxsub->comedidev,
+ s,
s->async->events);
// no resubmit of the urb
return;
}
// transmit data to comedi
s->async->events |= COMEDI_CB_BLOCK;
- comedi_event(this_usbduxsub->comedidev,
- s,
+ comedi_event(this_usbduxsub->comedidev,
+ s,
s->async->events);
}
}
urb->transfer_buffer_length = SIZEOUTBUF;
urb->dev = this_usbduxsub->usbdev;
urb->status = 0;
- if (this_usbduxsub->ao_cmd_running) {
+ if (this_usbduxsub->ao_cmd_running) {
if (this_usbduxsub->high_speed) {
// uframes
urb->interval=8;
// frames
urb->interval=1;
}
- urb->number_of_packets = 1;
+ urb->number_of_packets = 1;
urb->iso_frame_desc[0].offset = 0;
urb->iso_frame_desc[0].length = SIZEOUTBUF;
urb->iso_frame_desc[0].status = 0;
}
s->async->events |= COMEDI_CB_EOA;
s->async->events |= COMEDI_CB_ERROR;
- comedi_event(this_usbduxsub->comedidev,
- s,
+ comedi_event(this_usbduxsub->comedidev,
+ s,
s->async->events);
// don't do an unlink here
usbdux_ao_stop(this_usbduxsub,0);
if (usbduxsub->probed) {
// 7f92 to zero
- local_transfer_buffer[0]=0;
+ local_transfer_buffer[0]=0;
errcode=USB_CONTROL_MSG
(usbduxsub->usbdev,
// create a pipe for a control transfer
usb_sndctrlpipe(usbduxsub->usbdev,0),
// bRequest, "Firmware"
- USBDUXSUB_FIRMWARE,
+ USBDUXSUB_FIRMWARE,
// bmRequestType
- VENDOR_DIR_OUT,
+ VENDOR_DIR_OUT,
// Value
- USBDUXSUB_CPUCS,
+ USBDUXSUB_CPUCS,
// Index
0x0000,
// address of the transfer buffer
// Length
1,
// Timeout
- EZTIMEOUT
+ EZTIMEOUT
);
if (errcode<0) {
printk("comedi_: usbdux_: control msg failed (start)\n");
uint8_t local_transfer_buffer[16];
if (usbduxsub->probed) {
// 7f92 to one
- local_transfer_buffer[0]=1;
+ local_transfer_buffer[0]=1;
errcode=USB_CONTROL_MSG
(usbduxsub->usbdev,
usb_sndctrlpipe(usbduxsub->usbdev,0),
// bRequest, "Firmware"
- USBDUXSUB_FIRMWARE,
+ USBDUXSUB_FIRMWARE,
// bmRequestType
VENDOR_DIR_OUT,
// Value
USBDUXSUB_CPUCS,
// Index
- 0x0000,
+ 0x0000,
local_transfer_buffer,
// Length
1,
// Timeout
- EZTIMEOUT
+ EZTIMEOUT
);
if (errcode<0) {
printk("comedi_: usbdux: control msg failed (stop)\n");
}
return 0;
}
-
+
-int firmwareUpload(usbduxsub_t* usbduxsub,
+int firmwareUpload(usbduxsub_t* usbduxsub,
uint8_t* firmwareBinary,
int sizeFirmware) {
int ret;
}
return 0;
}
-
+
int usbduxsub_submit_InURBs(usbduxsub_t* usbduxsub) {
-static int usbdux_ai_cmdtest(comedi_device *dev,
- comedi_subdevice *s,
+static int usbdux_ai_cmdtest(comedi_device *dev,
+ comedi_subdevice *s,
comedi_cmd *cmd)
{
int err=0,tmp,i;
- unsigned int tmpTimer;
+ unsigned int tmpTimer;
usbduxsub_t* this_usbduxsub=dev->private;
if (!(this_usbduxsub->probed)) {
return -ENODEV;
err++;
}
-
+
if(cmd->stop_src==TRIG_COUNT){
/* any count is allowed */
}else{
// creates the ADC command for the MAX1271
// range is the range value from comedi
static int8_t create_adc_command(unsigned int chan, int range) {
- int8_t p=(range<=1);
+ int8_t p=(range<=1);
int8_t r=((range%2)==0);
return (chan<<4)|
((p==1)<<2)|
COMMAND_OUT_EP),
this_usbduxsub->dux_commands,
SIZEOFDUXBUFFER,
- &nsent,
+ &nsent,
10*HZ);
if (result<0) {
printk("comedi%d: could not transmit dux_command to the usb-device, err=%d\n",
int result=-EFAULT;
int nrec;
int i;
-
+
for(i=0;i<RETRIES;i++) {
result = USB_BULK_MSG(this_usbduxsub->usbdev,
usb_rcvbulkpipe(this_usbduxsub->usbdev,
COMMAND_IN_EP),
this_usbduxsub->insnBuffer,
SIZEINSNBUF,
- &nrec,
+ &nrec,
1*HZ);
if (result<0) {
printk("comedi%d: insn: USB error %d while receiving DUX command\n",
// set current channel of the running aquisition to zero
s->async->cur_chan=0;
-
+
this_usbduxsub->dux_commands[1]=cmd->chanlist_len;
for(i=0; i < cmd->chanlist_len; ++i ) {
chan = CR_CHAN(cmd->chanlist[i]);
this_usbduxsub->ai_timer = cmd->scan_begin_arg/1000000;
}
if (this_usbduxsub->ai_timer<1) {
- printk("comedi%d: usbdux: ai_cmd: timer=%d, scan_begin_arg=%d. Not properly tested by cmdtest?\n",
- dev->minor,
+ printk("comedi%d: usbdux: ai_cmd: timer=%d, scan_begin_arg=%d. Not properly tested by cmdtest?\n",
+ dev->minor,
this_usbduxsub->ai_timer,
cmd->scan_begin_arg);
up(&this_usbduxsub->sem);
if(cmd->stop_src==TRIG_COUNT){
// data arrives as one packet
this_usbduxsub->ai_sample_count = cmd->stop_arg;
- this_usbduxsub->ai_continous=0;
+ this_usbduxsub->ai_continous=0;
} else {
// continous aquisition
this_usbduxsub->ai_continous=1;
/* Mode 0 is used to get a single conversion on demand */
-static int usbdux_ai_insn_read(comedi_device * dev,
+static int usbdux_ai_insn_read(comedi_device * dev,
comedi_subdevice *s,
- comedi_insn *insn,
+ comedi_insn *insn,
lsampl_t *data)
{
int i;
printk("comedi%d: ai_insn_read: no usb dev.\n",
dev->minor);
return 0;
- }
+ }
#ifdef NOISY_DUX_DEBUGBUG
printk("comedi%d: ai_insn_read, insn->n=%d, insn->subdev=%d\n",
dev->minor,
static int usbdux_ao_insn_read(comedi_device *dev, comedi_subdevice *s,
- comedi_insn *insn, lsampl_t *data)
+ comedi_insn *insn, lsampl_t *data)
{
int i;
int chan = CR_CHAN(insn->chanspec);
usbduxsub_t* this_usbduxsub=dev->private;
-
+
if (!this_usbduxsub) {
return -EFAULT;
}
int i,err;
int chan = CR_CHAN(insn->chanspec);
usbduxsub_t* this_usbduxsub=dev->private;
-
+
#ifdef NOISY_DUX_DEBUGBUG
printk("comedi%d: ao_insn_write\n",dev->minor);
#endif
up(&this_usbduxsub->sem);
return 0;
}
-
+
for(i=0;i<insn->n;i++){
#ifdef NOISY_DUX_DEBUGBUG
printk("comedi%d: ao_insn_write: data[chan=%d,i=%d]=%d\n",dev->minor,chan,i,data[i]);
}
}
up(&this_usbduxsub->sem);
-
+
return i;
}
-static int usbdux_ao_cmdtest(comedi_device *dev,
- comedi_subdevice *s,
+static int usbdux_ao_cmdtest(comedi_device *dev,
+ comedi_subdevice *s,
comedi_cmd *cmd)
{
int err=0, tmp;
} else {
// all conversion events happen simultaneously with a rate of 1kHz/n
cmd->convert_src &= TRIG_NOW;
- }
+ }
if(!cmd->convert_src || tmp!=cmd->convert_src)err++;
// issue a trigger when scan is finished and start a new scan
err++;
}
-
+
if(cmd->stop_src==TRIG_COUNT){
/* any count is allowed */
}else{
}
}
-#ifdef NOISY_DUX_DEBUGBUG
- printk("comedi%d: err=%d, scan_begin_src=%d, scan_begin_arg=%d, convert_src=%d, convert_arg=%d\n",
- dev->minor,
+#ifdef NOISY_DUX_DEBUGBUG
+ printk("comedi%d: err=%d, scan_begin_src=%d, scan_begin_arg=%d, convert_src=%d, convert_arg=%d\n",
+ dev->minor,
err,
- cmd->scan_begin_src,
- cmd->scan_begin_arg,
- cmd->convert_src,
- cmd->convert_arg);
+ cmd->scan_begin_src,
+ cmd->scan_begin_arg,
+ cmd->convert_src,
+ cmd->convert_arg);
#endif
if(err)return 3;
#endif
// set current channel of the running aquisition to zero
- s->async->cur_chan = 0;
+ s->async->cur_chan = 0;
for(i=0; i < cmd->chanlist_len; ++i ) {
chan = CR_CHAN(cmd->chanlist[i]);
gain = CR_RANGE(cmd->chanlist[i]);
cmd->scan_begin_src,
cmd->scan_begin_arg,
cmd->convert_src,
- cmd->convert_arg);
+ cmd->convert_arg);
printk("comedi%d: usbdux: ao_timer=%d (ms)\n",
dev->minor,
this_usbduxsub->ao_timer);
// counter
// high speed also scans everything at once
if (0) /* (this_usbduxsub->high_speed) */ {
- this_usbduxsub->ao_sample_count =
+ this_usbduxsub->ao_sample_count =
(cmd->stop_arg)*(cmd->scan_end_arg);
} else {
- // there's no scan as the scan has been
+ // there's no scan as the scan has been
// perf inside the FX2
// data arrives as one packet
- this_usbduxsub->ao_sample_count =
+ this_usbduxsub->ao_sample_count =
cmd->stop_arg;
- }
- this_usbduxsub->ao_continous=0;
+ }
+ this_usbduxsub->ao_continous=0;
} else {
// continous aquisition
this_usbduxsub->ao_continous=1;
comedi_insn *insn,
lsampl_t *data) {
int chan=CR_CHAN(insn->chanspec);
-
+
/* 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
+ * 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:
comedi_subdevice *s,
comedi_insn *insn,
lsampl_t *data) {
-
+
usbduxsub_t* this_usbduxsub=dev->private;
int err;
}
-static int usbdux_counter_write(comedi_device *dev,comedi_subdevice *s,
+static int usbdux_counter_write(comedi_device *dev,comedi_subdevice *s,
comedi_insn *insn,lsampl_t *data) {
usbduxsub_t* this_usbduxsub=dev->private;
int err;
}
up(&this_usbduxsub->sem);
-
+
return 1;
}
);
return -ENOMEM;
}
-
+
for (;;) {
char buf[256],*cp;
char type;
printk("comedi_: usbdux: firmware upload goes beyond FX2 RAM boundaries.");
return -EFAULT;
}
-
+
//printk("comedi_: usbdux: off=%x, len=%x:",off,len);
/* Read the record type */
// allocate memory for the urbs and initialise them
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-static void* usbduxsub_probe(struct usb_device *udev,
+static void* usbduxsub_probe(struct usb_device *udev,
unsigned int interfnum,
const struct usb_device_id *id) {
#else
-static int usbduxsub_probe(struct usb_interface *uinterf,
+static int usbduxsub_probe(struct usb_interface *uinterf,
const struct usb_device_id *id) {
struct usb_device *udev = interface_to_usbdev(uinterf);
#endif
usbduxsub[index].numOfInBuffers=NUMOFINBUFFERSHIGH;
} else {
usbduxsub[index].numOfInBuffers=NUMOFINBUFFERSFULL;
- }
+ }
usbduxsub[index].urbIn=kmalloc(sizeof(struct urb*)*usbduxsub[index].numOfInBuffers,
GFP_KERNEL);
if (!(usbduxsub[index].urbIn)) {
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return PROBE_ERR_RETURN( -ENOMEM);
- }
+ }
for (i=0; i < usbduxsub[index].numOfInBuffers; i++) {
// one frame: 1ms
usbduxsub[index].urbIn[i]=USB_ALLOC_URB(1);
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return PROBE_ERR_RETURN( -ENOMEM);
- }
+ }
usbduxsub[index].urbIn[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].urbIn[i]->pipe =
usb_rcvisocpipe(usbduxsub[index].usbdev, ISOINEP);
usbduxsub[index].urbIn[i]->transfer_flags = URB_ISO_ASAP;
usbduxsub[index].urbIn[i]->transfer_buffer=
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return PROBE_ERR_RETURN( -ENOMEM);
- }
+ }
for (i=0; i < usbduxsub[index].numOfOutBuffers; i++) {
// one frame: 1ms
usbduxsub[index].urbOut[i]=USB_ALLOC_URB(1);
tidy_up(&(usbduxsub[index]));
up(&start_stop_sem);
return PROBE_ERR_RETURN( -ENOMEM);
- }
+ }
usbduxsub[index].urbOut[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].urbOut[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].urbOut[i]->complete = usbduxsub_ao_IsocIrq;
usbduxsub[index].urbOut[i]->number_of_packets = 1;
- usbduxsub[index].urbOut[i]->transfer_buffer_length =
+ 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].urbOut[i]->iso_frame_desc[0].length =
SIZEOUTBUF;
if (usbduxsub[index].high_speed) {
// uframes
// we've reached the bottom of the function
usbduxsub[index].probed=1;
- up(&start_stop_sem);
+ up(&start_stop_sem);
printk("comedi_: usbdux%d has been successfully initialised.\n",index);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
return (void*)(&usbduxsub[index]);
if (!usbduxsub_tmp) {
printk("comedi_: usbdux: disconnect called with null pointer.\n");
return;
- }
+ }
if (usbduxsub_tmp->usbdev!=udev) {
printk("comedi_: usbdux: BUG! called with wrong ptr!!!\n");
return;
usbduxsub[index].comedidev=dev;
// trying to upload the firmware into the chip
- if(comedi_aux_data(it->options, 0) &&
+ if(comedi_aux_data(it->options, 0) &&
it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]){
read_firmware(usbduxsub+index,
comedi_aux_data(it->options, 0),
it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]);
- }
+ }
dev->board_name = BOARDNAME;
-
+
/* set number of subdevices */
dev->n_subdevices=N_SUBDEVICES;
// analog input
s->type=COMEDI_SUBD_AI;
// readable and ref is to ground
- s->subdev_flags=SDF_READABLE|SDF_GROUND;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
// 8 channels
s->n_chan=8;
// length of the channellist
// usb-structure
s->private=NULL;
// are writable
- s->subdev_flags=SDF_WRITABLE|SDF_GROUND;
+ s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
// 4 channels
s->n_chan=4;
// length of the channellist
static struct usb_device_id usbduxsub_table [] = {
{ USB_DEVICE(0x13d8, 0x0001),
},
- { USB_DEVICE(0x13d8, 0x0002)
+ { USB_DEVICE(0x13d8, 0x0002)
},
{ } /* Terminating entry */
};
module_init(init_usbdux);
-module_exit(exit_usbdux);
+module_exit(exit_usbdux);
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
CHANNELLISTEP),
this_usbduxfastsub->dux_commands,
SIZEOFDUXBUFFER,
- &nsent,
+ &nsent,
10000);
if (result<0) {
printk("comedi%d: could not transmit dux_commands to the usb-device, err=%d\n",
#endif
- this_usbduxfastsub->ai_cmd_running=0;
+ this_usbduxfastsub->ai_cmd_running=0;
if (do_unlink) {
// stop aquistion
// unlink
res=usbduxfast_ai_stop(this_usbduxfastsub,1);
up(&this_usbduxfastsub->sem);
-
+
return res;
}
// tell this comedi
s->async->events |= COMEDI_CB_EOA;
s->async->events |= COMEDI_CB_ERROR;
- comedi_event(this_usbduxfastsub->comedidev,
+ comedi_event(this_usbduxfastsub->comedidev,
s,
s->async->events);
// stop the transfer w/o unlink
urb->status);
s->async->events |= COMEDI_CB_EOA;
s->async->events |= COMEDI_CB_ERROR;
- comedi_event(this_usbduxfastsub->comedidev,
- s,
+ comedi_event(this_usbduxfastsub->comedidev,
+ s,
s->async->events);
usbduxfast_ai_stop(this_usbduxfastsub,0);
return;
0);
// say comedi that the acquistion is over
s->async->events |= COMEDI_CB_EOA;
- comedi_event(this_usbduxfastsub->comedidev,
- s,
+ comedi_event(this_usbduxfastsub->comedidev,
+ s,
s->async->events);
return;
}
this_usbduxfastsub->ai_sample_count-=n;
}
-
+
// write the full buffer to comedi
cfc_write_array_to_buffer(s,
urb->transfer_buffer,
urb->actual_length);
-
+
// tell comedi that data is there
- comedi_event(this_usbduxfastsub->comedidev,
+ comedi_event(this_usbduxfastsub->comedidev,
s,
s->async->events);
err);
s->async->events |= COMEDI_CB_EOA;
s->async->events |= COMEDI_CB_ERROR;
- comedi_event(this_usbduxfastsub->comedidev,
+ comedi_event(this_usbduxfastsub->comedidev,
s,
s->async->events);
usbduxfast_ai_stop(this_usbduxfastsub,0);
if (usbduxfastsub->probed) {
// 7f92 to zero
- local_transfer_buffer[0]=0;
+ local_transfer_buffer[0]=0;
errcode=USB_CONTROL_MSG
(usbduxfastsub->usbdev,
// create a pipe for a control transfer
usb_sndctrlpipe(usbduxfastsub->usbdev,0),
// bRequest, "Firmware"
- USBDUXFASTSUB_FIRMWARE,
+ USBDUXFASTSUB_FIRMWARE,
// bmRequestType
- VENDOR_DIR_OUT,
+ VENDOR_DIR_OUT,
// Value
- USBDUXFASTSUB_CPUCS,
+ USBDUXFASTSUB_CPUCS,
// Index
0x0000,
// address of the transfer buffer
// Length
1,
// Timeout
- EZTIMEOUT
+ EZTIMEOUT
);
if (errcode<0) {
printk("comedi_: usbduxfast_: control msg failed (start)\n");
unsigned char local_transfer_buffer[16];
if (usbduxfastsub->probed) {
// 7f92 to one
- local_transfer_buffer[0]=1;
+ local_transfer_buffer[0]=1;
errcode=USB_CONTROL_MSG
(usbduxfastsub->usbdev,
usb_sndctrlpipe(usbduxfastsub->usbdev,0),
// bRequest, "Firmware"
- USBDUXFASTSUB_FIRMWARE,
+ USBDUXFASTSUB_FIRMWARE,
// bmRequestType
VENDOR_DIR_OUT,
// Value
USBDUXFASTSUB_CPUCS,
// Index
- 0x0000,
+ 0x0000,
local_transfer_buffer,
// Length
1,
// Timeout
- EZTIMEOUT
+ EZTIMEOUT
);
if (errcode<0) {
printk("comedi_: usbduxfast: control msg failed (stop)\n");
}
return 0;
}
-
+
-int firmwareUpload(usbduxfastsub_t* usbduxfastsub,
+int firmwareUpload(usbduxfastsub_t* usbduxfastsub,
unsigned char* firmwareBinary,
int sizeFirmware) {
int ret;
}
return 0;
}
-
+
int usbduxfastsub_submit_InURBs(usbduxfastsub_t* usbduxfastsub) {
-static int usbduxfast_ai_cmdtest(comedi_device *dev,
- comedi_subdevice *s,
+static int usbduxfast_ai_cmdtest(comedi_device *dev,
+ comedi_subdevice *s,
comedi_cmd *cmd)
{
int err=0, stop_mask=0;
}
steps=0;
if(cmd->scan_begin_src == TRIG_TIMER) {
- printk("comedi%d: usbduxfast: scan_begin_src==TRIG_TIMER not valid.\n",
+ printk("comedi%d: usbduxfast: scan_begin_src==TRIG_TIMER not valid.\n",
dev->minor);
up(&this_usbduxfastsub->sem);
return -EINVAL;
steps=(cmd->convert_arg*30)/1000;
}
if ((steps<MIN_SAMPLING_PERIOD)&&(cmd->chanlist_len!=1)) {
- printk("comedi%d: usbduxfast: ai_cmd: steps=%ld, scan_begin_arg=%d. Not properly tested by cmdtest?\n",
- dev->minor,
+ printk("comedi%d: usbduxfast: ai_cmd: steps=%ld, scan_begin_arg=%d. Not properly tested by cmdtest?\n",
+ dev->minor,
steps,
cmd->scan_begin_arg);
up(&this_usbduxfastsub->sem);
this_usbduxfastsub->dux_commands[OPBASE+0]=0x02; // data
this_usbduxfastsub->dux_commands[OUTBASE+0]=0xFF & rngmask;
this_usbduxfastsub->dux_commands[LOGBASE+0]=0;
- }
+ }
this_usbduxfastsub->dux_commands[LENBASE+1]=0x00; // branch back to state 0
this_usbduxfastsub->dux_commands[OPBASE+1]=0x01; // deceision state w/o data
this_usbduxfastsub->dux_commands[OUTBASE+1]=0xFF & rngmask;
this_usbduxfastsub->dux_commands[OPBASE+0]=0x02; // data
this_usbduxfastsub->dux_commands[OUTBASE+0]=0xFF & rngmask;
this_usbduxfastsub->dux_commands[LOGBASE+0]=0;
-
+
// we have 6 states with duration 1
steps=steps-6;
-
+
// do the first part of the delay
this_usbduxfastsub->dux_commands[LENBASE+1]=steps/2;
this_usbduxfastsub->dux_commands[OPBASE+1]=0;
this_usbduxfastsub->dux_commands[OUTBASE+1]=0xFF & rngmask;
this_usbduxfastsub->dux_commands[LOGBASE+1]=0;
-
+
// and the second part
this_usbduxfastsub->dux_commands[LENBASE+2]=steps-steps/2;
this_usbduxfastsub->dux_commands[OPBASE+2]=0;
this_usbduxfastsub->dux_commands[OUTBASE+2]=0xFF & rngmask;
this_usbduxfastsub->dux_commands[LOGBASE+2]=0;
-
+
this_usbduxfastsub->dux_commands[LENBASE+3]=1;
this_usbduxfastsub->dux_commands[OPBASE+3]=0;
this_usbduxfastsub->dux_commands[OUTBASE+3]=0xFF & rngmask;
this_usbduxfastsub->dux_commands[LOGBASE+3]=0;
-
+
this_usbduxfastsub->dux_commands[LENBASE+4]=1;
this_usbduxfastsub->dux_commands[OPBASE+4]=0;
this_usbduxfastsub->dux_commands[OUTBASE+4]=0xFF & rngmask;
this_usbduxfastsub->dux_commands[LOGBASE+4]=0;
-
+
this_usbduxfastsub->dux_commands[LENBASE+5]=1;
this_usbduxfastsub->dux_commands[OPBASE+5]=0;
this_usbduxfastsub->dux_commands[OUTBASE+5]=0xFF & rngmask;
this_usbduxfastsub->dux_commands[LOGBASE+5]=0;
-
+
this_usbduxfastsub->dux_commands[LENBASE+6]=1;
this_usbduxfastsub->dux_commands[OPBASE+6]=0;
this_usbduxfastsub->dux_commands[OUTBASE+6]=0xFF & rngmask;
this_usbduxfastsub->dux_commands[OPBASE+2]=0;
this_usbduxfastsub->dux_commands[OUTBASE+2]=0xFF & rngmask;
this_usbduxfastsub->dux_commands[LOGBASE+2]=0;
-
+
this_usbduxfastsub->dux_commands[LENBASE+3]=1;
this_usbduxfastsub->dux_commands[OPBASE+3]=0x02; // data
this_usbduxfastsub->dux_commands[OUTBASE+3]=0xFF & rngmask;
this_usbduxfastsub->dux_commands[OPBASE+5]=0;
this_usbduxfastsub->dux_commands[OUTBASE+5]=0xFF & rngmask;
this_usbduxfastsub->dux_commands[LOGBASE+5]=0;
-
+
this_usbduxfastsub->dux_commands[LENBASE+6]=1;
this_usbduxfastsub->dux_commands[OPBASE+6]=0;
this_usbduxfastsub->dux_commands[OUTBASE+6]=0xFF & rngmask;
this_usbduxfastsub->dux_commands[OUTBASE+j*2+1]=0xFE & rngmask; //count
this_usbduxfastsub->dux_commands[LOGBASE+j*2+1]=0;
}
-
+
// 2 steps with duration 1: the idele step and step 6:
steps_tmp=steps-2;
// commit data to the FIFO and do the first part of the delay
this_usbduxfastsub->dux_commands[OPBASE+4]=0x02; // data
this_usbduxfastsub->dux_commands[OUTBASE+4]=0xFF & rngmask; // no change
this_usbduxfastsub->dux_commands[LOGBASE+4]=0;
-
+
if (CR_RANGE(cmd->chanlist[0])>0) rngmask=0xff-0x04; else rngmask=0xff;
// do the second part of the delay
this_usbduxfastsub->dux_commands[LENBASE+5]=steps_tmp-steps_tmp/2;
this_usbduxfastsub->dux_commands[OPBASE+6]=0;
this_usbduxfastsub->dux_commands[OUTBASE+6]=0xFF & rngmask;
this_usbduxfastsub->dux_commands[LOGBASE+6]=0;
-
+
case 16:
if (CR_RANGE(cmd->chanlist[0])>0) rngmask=0xff-0x04; else rngmask=0xff;
// commit data to the FIFO
this_usbduxfastsub->dux_commands[OPBASE+2]=0;
this_usbduxfastsub->dux_commands[OUTBASE+2]=0xFE & rngmask;
this_usbduxfastsub->dux_commands[LOGBASE+2]=0;
-
+
this_usbduxfastsub->dux_commands[LENBASE+3]=1;
this_usbduxfastsub->dux_commands[OPBASE+3]=0;
this_usbduxfastsub->dux_commands[OUTBASE+3]=0xFE & rngmask;
this_usbduxfastsub->dux_commands[LOGBASE+3]=0;
-
+
this_usbduxfastsub->dux_commands[LENBASE+4]=1;
this_usbduxfastsub->dux_commands[OPBASE+4]=0;
this_usbduxfastsub->dux_commands[OUTBASE+4]=0xFE & rngmask;
this_usbduxfastsub->dux_commands[LOGBASE+4]=0;
-
+
// and the second part
this_usbduxfastsub->dux_commands[LENBASE+5]=steps-steps/2;
this_usbduxfastsub->dux_commands[OPBASE+5]=0;
up(&this_usbduxfastsub->sem);
return -EFAULT;
}
-
+
#ifdef CONFIG_COMEDI_DEBUG
printk("comedi %d: sending commands to the usb device\n",
up(&this_usbduxfastsub->sem);
return -EFAULT;
}
- this_usbduxfastsub->ai_continous=0;
+ this_usbduxfastsub->ai_continous=0;
} else {
// continous aquisition
this_usbduxfastsub->ai_continous=1;
usbduxfastsub->dux_commands[OPBASE+0]=0x02; // data
usbduxfastsub->dux_commands[OUTBASE+0]=0xFF & rngmask;
usbduxfastsub->dux_commands[LOGBASE+0]=0;
-
+
// do the first part of the delay
usbduxfastsub->dux_commands[LENBASE+1]=12;
usbduxfastsub->dux_commands[OPBASE+1]=0;
usbduxfastsub->dux_commands[OUTBASE+1]=0xFE & rngmask;
usbduxfastsub->dux_commands[LOGBASE+1]=0;
-
+
usbduxfastsub->dux_commands[LENBASE+2]=1;
usbduxfastsub->dux_commands[OPBASE+2]=0;
usbduxfastsub->dux_commands[OUTBASE+2]=0xFE & rngmask;
usbduxfastsub->dux_commands[LOGBASE+2]=0;
-
+
usbduxfastsub->dux_commands[LENBASE+3]=1;
usbduxfastsub->dux_commands[OPBASE+3]=0;
usbduxfastsub->dux_commands[OUTBASE+3]=0xFE & rngmask;
usbduxfastsub->dux_commands[LOGBASE+3]=0;
-
+
usbduxfastsub->dux_commands[LENBASE+4]=1;
usbduxfastsub->dux_commands[OPBASE+4]=0;
usbduxfastsub->dux_commands[OUTBASE+4]=0xFE & rngmask;
usbduxfastsub->dux_commands[LOGBASE+4]=0;
-
+
// second part
usbduxfastsub->dux_commands[LENBASE+5]=12;
usbduxfastsub->dux_commands[OPBASE+5]=0;
(int)(usbduxfastsub->urbIn->dev));
#endif
for(i=0;i<PACKETS_TO_IGNORE;i++) {
- err=USB_BULK_MSG(usbduxfastsub->usbdev,
+ err=USB_BULK_MSG(usbduxfastsub->usbdev,
usb_rcvbulkpipe(usbduxfastsub->usbdev,BULKINEP),
usbduxfastsub->transfer_buffer,
SIZEINBUF,
}
// data points
for(i=0;i<insn->n;) {
- err=USB_BULK_MSG(usbduxfastsub->usbdev,
+ err=USB_BULK_MSG(usbduxfastsub->usbdev,
usb_rcvbulkpipe(usbduxfastsub->usbdev,BULKINEP),
usbduxfastsub->transfer_buffer,
SIZEINBUF,
dev->minor);
up(&usbduxfastsub->sem);
return -EINVAL;
- }
+ }
for(j=chan;(j<n)&&(i<insn->n);j=j+16) {
data[i]=((uint16_t*)(usbduxfastsub->transfer_buffer))[j];
i++;
);
return -ENOMEM;
}
-
+
for (;;) {
char buf[256],*cp;
char type;
printk("comedi_: usbduxfast: firmware upload goes beyond FX2 RAM boundaries.");
return -EFAULT;
}
-
+
//printk("comedi_: usbduxfast: off=%x, len=%x:",off,len);
/* Read the record type */
// allocate memory for the urbs and initialise them
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-static void* usbduxfastsub_probe(struct usb_device *udev,
+static void* usbduxfastsub_probe(struct usb_device *udev,
unsigned int interfnum,
const struct usb_device_id *id) {
#else
-static int usbduxfastsub_probe(struct usb_interface *uinterf,
+static int usbduxfastsub_probe(struct usb_interface *uinterf,
const struct usb_device_id *id) {
struct usb_device *udev = interface_to_usbdev(uinterf);
#endif
tidy_up(&(usbduxfastsub[index]));
up(&start_stop_sem);
return PROBE_ERR_RETURN( -ENOMEM);
- }
+ }
usbduxfastsub[index].transfer_buffer=
kmalloc(SIZEINBUF,GFP_KERNEL);
if (!(usbduxfastsub[index].transfer_buffer)) {
}
// we've reached the bottom of the function
usbduxfastsub[index].probed=1;
- up(&start_stop_sem);
+ up(&start_stop_sem);
printk("comedi_: usbduxfast%d has been successfully initialized.\n",index);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
return (void*)(&usbduxfastsub[index]);
if (!usbduxfastsub_tmp) {
printk("comedi_: usbduxfast: disconnect called with null pointer.\n");
return;
- }
+ }
if (usbduxfastsub_tmp->usbdev!=udev) {
printk("comedi_: usbduxfast: BUG! called with wrong ptr!!!\n");
return;
usbduxfastsub[index].comedidev=dev;
// trying to upload the firmware into the chip
- if(comedi_aux_data(it->options, 0) &&
+ if(comedi_aux_data(it->options, 0) &&
it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]){
read_firmware(usbduxfastsub,
comedi_aux_data(it->options, 0),
it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]);
- }
+ }
dev->board_name = BOARDNAME;
-
+
/* set number of subdevices */
dev->n_subdevices=N_SUBDEVICES;
// analog input
s->type=COMEDI_SUBD_AI;
// readable and ref is to ground
- s->subdev_flags=SDF_READABLE|SDF_GROUND;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
// 8 channels
s->n_chan=16;
// length of the channellist
module_init(init_usbduxfast);
-module_exit(exit_usbduxfast);
+module_exit(exit_usbduxfast);
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
/*
This is some serious bloatware.
-
+
Taken from Dave A.'s PCL-711 driver, 'cuz I thought it
was cool.
*/
int devices_q=0;
int l=0;
comedi_driver *driv;
-
+
l+=sprintf(buf+l,
"comedi version " COMEDI_RELEASE "\n"
"format string: %s\n",
for(i=0;i<COMEDI_NDEVICES;i++){
comedi_device *dev;
- dev=comedi_get_device_by_minor(i);
+ dev = comedi_devices + i;
if(dev->attached){
devices_q=1;
l+=sprintf(buf+l,"%2d: %-20s %-20s %4d\n",
void comedi_proc_init(void)
{
struct proc_dir_entry *comedi_proc;
-
+
comedi_proc = create_proc_entry("comedi",S_IFREG | S_IRUGO,0);
if(comedi_proc)
comedi_proc->read_proc = comedi_read_procmem;
reads:
range info structure
-
+
writes:
n comedi_krange structures to rangeinfo->range_ptr
*/
-int do_rangeinfo_ioctl(comedi_device *dev,comedi_rangeinfo *arg)
+int do_rangeinfo_ioctl(comedi_device *dev, comedi_rangeinfo *arg)
{
comedi_rangeinfo it;
int minor,subd,chan;
if(copy_from_user(&it,arg,sizeof(comedi_rangeinfo)))
return -EFAULT;
+ /* FIXME why do we have to support queries to devices that are different
+ * than the one passed as the dev argument? */
+ minor=(it.range_type>>28) & 0xf;
+ subd=(it.range_type>>24) & 0xf;
+ chan=(it.range_type>>16) & 0xff;
- minor=(it.range_type>>28)&0xf;
- subd=(it.range_type>>24)&0xf;
- chan=(it.range_type>>16)&0xff;
-
- if(minor>COMEDI_NDEVICES)
+ if(minor > COMEDI_NDEVICES)
return -EINVAL;
- dev=comedi_get_device_by_minor(minor);
- if(!dev->attached)return -EINVAL;
- if(subd>=dev->n_subdevices)return -EINVAL;
- s=dev->subdevices+subd;
+ comedi_device *query_dev = comedi_devices + minor;
+ if(!query_dev->attached) return -EINVAL;
+ if(subd>=query_dev->n_subdevices) return -EINVAL;
+ s = query_dev->subdevices + subd;
if(s->range_table){
- lr=s->range_table;
+ lr = s->range_table;
}else if(s->range_table_list){
- if(chan>=s->n_chan)return -EINVAL;
- lr=s->range_table_list[chan];
+ if(chan >= s->n_chan) return -EINVAL;
+ lr = s->range_table_list[chan];
}else{
return -EINVAL;
}
if( RANGE_LENGTH(it.range_type) != lr->length){
DPRINTK("wrong length %d should be %d (0x%08x)\n",
- RANGE_LENGTH(it.range_type),lr->length,it.range_type);
+ RANGE_LENGTH(it.range_type), lr->length, it.range_type);
return -EINVAL;
}
- if(copy_to_user(it.range_ptr,lr->range,
- sizeof(comedi_krange)*lr->length))
+ if(copy_to_user(it.range_ptr, lr->range,
+ sizeof(comedi_krange) * lr->length))
return -EFAULT;
-
+
return 0;
}
#define SDF_MODE2 0x0200 /* can do mode 2 */
#define SDF_MODE3 0x0400 /* can do mode 3 */
#define SDF_MODE4 0x0800 /* can do mode 4 */
-#define SDF_CMD 0x1000 /* can do commands */
+#define SDF_CMD 0x1000 /* can do commands (deprecated) */
#define SDF_SOFT_CALIBRATED 0x2000 /* subdevice uses software calibration */
+#define SDF_CMD_WRITE 0x4000 /* can do output commands */
+#define SDF_CMD_READ 0x8000 /* can do input commands */
#define SDF_READABLE 0x00010000 /* subdevice can be read (e.g. analog input) */
#define SDF_WRITABLE 0x00020000 /* subdevice can be written (e.g. analog output) */
struct comedi_subdevice_struct{
+ comedi_device *device;
int type;
int n_chan;
volatile int subdev_flags;
unsigned int state;
- dev_t devt;
+ struct class_device *class_dev;
};
struct comedi_async_struct{
int use_count;
comedi_driver *driver;
void *private;
+
+ struct class_device *class_dev;
unsigned minor;
- dev_t devt;
+
const char *board_name;
const void * board_ptr;
int attached;
void (*close)(comedi_device *dev);
};
-
+struct comedi_inode_private
+{
+ comedi_device *device;
+ comedi_subdevice *subdevice;
+};
extern comedi_device *comedi_devices;
extern spinlock_t big_comedi_lock;
void comedi_event(comedi_device *dev,comedi_subdevice *s,unsigned int mask);
void comedi_error(const comedi_device *dev,const char *s);
-static inline comedi_device * comedi_get_device_by_minor( unsigned int minor )
+/* we can expand the number of bits used to encode devices/subdevices into
+ the minor number soon, after more distros support > 8 bit minor numbers
+ (like after Debian Etch gets released) */
+enum comedi_minor_bits
+{
+ COMEDI_DEVICE_MINOR_MASK = 0xf,
+ COMEDI_SUBDEVICE_MINOR_MASK = 0xf0
+};
+static const unsigned COMEDI_SUBDEVICE_MINOR_SHIFT = 4;
+static const unsigned COMEDI_SUBDEVICE_MINOR_OFFSET = 1;
+static const unsigned COMEDI_NUM_MINORS = 0x100;
+
+static inline comedi_device * comedi_get_device_by_minor(unsigned minor)
{
- return comedi_devices + minor;
+ unsigned device_index;
+ if(minor >= COMEDI_NUM_MINORS) return NULL;
+ device_index = minor & COMEDI_DEVICE_MINOR_MASK;
+ if(device_index >= COMEDI_NDEVICES) return NULL;
+ return comedi_devices + device_index;
+}
+
+static inline comedi_subdevice * comedi_get_subdevice_by_minor(unsigned minor)
+{
+ unsigned subdevice_index;
+ comedi_device * dev;
+
+ if((minor & COMEDI_SUBDEVICE_MINOR_MASK) == 0) return NULL;
+ dev = comedi_get_device_by_minor(minor);
+ if(dev == NULL) return NULL;
+ subdevice_index = ((minor & COMEDI_SUBDEVICE_MINOR_MASK) >> COMEDI_SUBDEVICE_MINOR_SHIFT) - COMEDI_SUBDEVICE_MINOR_OFFSET;
+ if(subdevice_index >= dev->n_subdevices) return NULL;
+ return dev->subdevices + subdevice_index;
+}
+
+static inline unsigned comedi_construct_minor_for_subdevice(comedi_device *dev, unsigned subdevice_index)
+{
+ unsigned minor = 0;
+ minor |= dev->minor & COMEDI_DEVICE_MINOR_MASK;
+ minor |= ((subdevice_index + COMEDI_SUBDEVICE_MINOR_OFFSET) << COMEDI_SUBDEVICE_MINOR_SHIFT) & COMEDI_SUBDEVICE_MINOR_MASK;
+ BUG_ON(minor >= COMEDI_NUM_MINORS);
+ return minor;
}
int comedi_device_detach(comedi_device *dev);
static inline int alloc_subdevices(comedi_device *dev, unsigned int num_subdevices)
{
- int size=sizeof(comedi_subdevice)*num_subdevices;
+ const int size = sizeof(comedi_subdevice) * num_subdevices;
dev->n_subdevices = num_subdevices;
- dev->subdevices=kmalloc(size,GFP_KERNEL);
+ dev->subdevices = kmalloc(size,GFP_KERNEL);
if(!dev->subdevices)
return -ENOMEM;
memset(dev->subdevices,0,size);
+ unsigned i;
+ for(i = 0; i < num_subdevices; ++i)
+ {
+ dev->subdevices[i].device = dev;
+ }
return 0;
}