Added support for udev/sysfs to core and ni_pcimio driver. Driver now
authorFrank Mori Hess <fmhess@speakeasy.net>
Thu, 16 Oct 2008 20:58:26 +0000 (20:58 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Thu, 16 Oct 2008 20:58:26 +0000 (20:58 +0000)
auto-configures itself on a /dev/comediN device (starting at /dev/comedi16)
as if the user had done a
"comedi_config /dev/comediN ni_pcimio <bus>,<slot>"

comedi/comedi_fops.c
comedi/comedi_ksyms.c
comedi/drivers.c
comedi/drivers/comedi_bond.c
comedi/drivers/ni_pcimio.c
comedi/kcomedilib/kcomedilib_main.c
comedi/proc.c
comedi/range.c
include/linux/comedidev.h
include/linux/device.h

index c6af6dd3c2bd9f4445bd8ca5b96169d0be89b940..985cf3f7eefae10254250a2bf41950b7aa2e96c4 100644 (file)
@@ -50,7 +50,7 @@
 
 //#include "kvmem.h"
 
-MODULE_AUTHOR("David Schleef <ds@schleef.org>");
+MODULE_AUTHOR("http://www.comedi.org");
 MODULE_DESCRIPTION("Comedi core module");
 MODULE_LICENSE("GPL");
 
@@ -59,7 +59,8 @@ int comedi_debug;
 module_param(comedi_debug, int, 0644);
 #endif
 
-comedi_device *comedi_devices;
+static DEFINE_SPINLOCK(comedi_file_info_table_lock);
+static struct comedi_device_file_info* comedi_file_info_table[COMEDI_NUM_MINORS];
 
 static int do_devconfig_ioctl(comedi_device * dev, comedi_devconfig * arg);
 static int do_bufconfig_ioctl(comedi_device * dev, void *arg);
@@ -94,7 +95,8 @@ static int comedi_ioctl(struct inode *inode, struct file *file,
 #endif
 {
        const unsigned minor = iminor(file->f_dentry->d_inode);
-       comedi_device *dev = comedi_get_device_by_minor(minor);
+       struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(minor);
+       comedi_device *dev = dev_file_info->device;
        int rc;
 
        mutex_lock(&dev->mutex);
@@ -191,7 +193,8 @@ static int do_devconfig_ioctl(comedi_device * dev, comedi_devconfig * arg)
        if (arg == NULL) {
                if (is_device_busy(dev))
                        return -EBUSY;
-               return comedi_device_detach(dev);
+               comedi_device_detach(dev);
+               return 0;
        }
 
        if (copy_from_user(&it, arg, sizeof(comedi_devconfig)))
@@ -340,8 +343,9 @@ static int do_devinfo_ioctl(comedi_device * dev, comedi_devinfo * arg,
 {
        comedi_devinfo devinfo;
        const unsigned minor = iminor(file->f_dentry->d_inode);
-       comedi_subdevice *read_subdev = comedi_get_read_subdevice(dev, minor);
-       comedi_subdevice *write_subdev = comedi_get_write_subdevice(dev, minor);
+       struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(minor);
+       comedi_subdevice *read_subdev = comedi_get_read_subdevice(dev_file_info);
+       comedi_subdevice *write_subdev = comedi_get_write_subdevice(dev_file_info);
 
        memset(&devinfo, 0, sizeof(devinfo));
 
@@ -409,8 +413,7 @@ static int do_subdinfo_ioctl(comedi_device * dev, comedi_subdinfo * arg,
                us->maxdata = s->maxdata;
                if (s->range_table) {
                        us->range_type =
-                               (dev->
-                               minor << 28) | (i << 24) | (0 << 16) | (s->
+                               (i << 24) | (0 << 16) | (s->
                                range_table->length);
                } else {
                        us->range_type = 0;     /* XXX */
@@ -1378,7 +1381,8 @@ static struct vm_operations_struct comedi_vm_ops = {
 static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
 {
        const unsigned minor = iminor(file->f_dentry->d_inode);
-       comedi_device *dev = comedi_get_device_by_minor(minor);
+       struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(minor);
+       comedi_device *dev = dev_file_info->device;
        comedi_async *async = NULL;
        unsigned long start = vma->vm_start;
        unsigned long size;
@@ -1394,9 +1398,9 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
                goto done;
        }
        if (vma->vm_flags & VM_WRITE) {
-               s = comedi_get_write_subdevice(dev, minor);
+               s = comedi_get_write_subdevice(dev_file_info);
        } else {
-               s = comedi_get_read_subdevice(dev, minor);
+               s = comedi_get_read_subdevice(dev_file_info);
        }
        if (s == NULL) {
                retval = -EINVAL;
@@ -1451,7 +1455,8 @@ static unsigned int comedi_poll(struct file *file, poll_table * wait)
 {
        unsigned int mask = 0;
        const unsigned minor = iminor(file->f_dentry->d_inode);
-       comedi_device *dev = comedi_get_device_by_minor(minor);
+       struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(minor);
+       comedi_device *dev = dev_file_info->device;
        comedi_subdevice *read_subdev;
        comedi_subdevice *write_subdev;
 
@@ -1463,7 +1468,7 @@ static unsigned int comedi_poll(struct file *file, poll_table * wait)
        }
 
        mask = 0;
-       read_subdev = comedi_get_read_subdevice(dev, minor);
+       read_subdev = comedi_get_read_subdevice(dev_file_info);
        if (read_subdev) {
                poll_wait(file, &read_subdev->async->wait_head, wait);
                if (!read_subdev->busy
@@ -1473,7 +1478,7 @@ static unsigned int comedi_poll(struct file *file, poll_table * wait)
                        mask |= POLLIN | POLLRDNORM;
                }
        }
-       write_subdev = comedi_get_write_subdevice(dev, minor);
+       write_subdev = comedi_get_write_subdevice(dev_file_info);
        if (write_subdev) {
                poll_wait(file, &write_subdev->async->wait_head, wait);
                comedi_buf_write_alloc(write_subdev->async, write_subdev->async->prealloc_bufsz);
@@ -1493,21 +1498,21 @@ static unsigned int comedi_poll(struct file *file, poll_table * wait)
 static ssize_t comedi_write(struct file *file, const 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);
        const unsigned minor = iminor(file->f_dentry->d_inode);
+       struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(minor);
+       comedi_device *dev = dev_file_info->device;
 
-       dev = comedi_get_device_by_minor(minor);
        if (!dev->attached) {
                DPRINTK("no driver configured on comedi%i\n", dev->minor);
                retval = -ENODEV;
                goto done;
        }
 
-       s = comedi_get_write_subdevice(dev, minor);
+       s = comedi_get_write_subdevice(dev_file_info);
        if (s == NULL) {
                retval = -EIO;
                goto done;
@@ -1602,7 +1607,8 @@ static ssize_t comedi_read(struct file *file, char *buf, size_t nbytes,
        int n, m, count = 0, retval = 0;
        DECLARE_WAITQUEUE(wait, current);
        const unsigned minor = iminor(file->f_dentry->d_inode);
-       comedi_device *dev = comedi_get_device_by_minor(minor);
+       struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(minor);
+       comedi_device *dev = dev_file_info->device;
 
        if (!dev->attached) {
                DPRINTK("no driver configured on comedi%i\n", dev->minor);
@@ -1610,7 +1616,7 @@ static ssize_t comedi_read(struct file *file, char *buf, size_t nbytes,
                goto done;
        }
 
-       s = comedi_get_read_subdevice(dev, minor);
+       s = comedi_get_read_subdevice(dev_file_info);
        if (s == NULL) {
                retval = -EIO;
                goto done;
@@ -1729,7 +1735,8 @@ static int comedi_open(struct inode *inode, struct file *file)
 {
        char mod[32];
        const unsigned minor = iminor(inode);
-       comedi_device *dev = comedi_get_device_by_minor(minor);
+       struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(minor);
+       comedi_device *dev = dev_file_info->device;
        if (dev == NULL) {
                DPRINTK("invalid minor number\n");
                return -ENODEV;
@@ -1800,7 +1807,8 @@ static int comedi_open(struct inode *inode, struct file *file)
 static int comedi_close(struct inode *inode, struct file *file)
 {
        const unsigned minor = iminor(inode);
-       comedi_device *dev = comedi_get_device_by_minor(minor);
+       struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(minor);
+       comedi_device *dev = dev_file_info->device;
        comedi_subdevice *s = NULL;
        int i;
 
@@ -1841,7 +1849,8 @@ static int comedi_close(struct inode *inode, struct file *file)
 static int comedi_fasync(int fd, struct file *file, int on)
 {
        const unsigned minor = iminor(file->f_dentry->d_inode);
-       comedi_device *dev = comedi_get_device_by_minor(minor);
+       struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(minor);
+       comedi_device *dev = dev_file_info->device;
 
        return fasync_helper(fd, file, on, &dev->async_queue);
 }
@@ -1868,13 +1877,24 @@ const struct file_operations comedi_fops = {
 struct class *comedi_class = NULL;
 static struct cdev comedi_cdev;
 
+static void comedi_cleanup_legacy_minors(void)
+{
+       unsigned i;
+       for (i = 0; i < COMEDI_NUM_LEGACY_MINORS; i++) {
+               comedi_free_board_minor(i);
+       }
+}
+
 static int __init comedi_init(void)
 {
        int i;
        int retval;
 
        printk("comedi: version " COMEDI_RELEASE
-               " - David Schleef <ds@schleef.org>\n");
+               " - http://www.comedi.org\n");
+
+       memset(comedi_file_info_table, 0, sizeof(struct comedi_device_file_info*) * COMEDI_NUM_MINORS);
+
        retval = register_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
                COMEDI_NUM_MINORS, "comedi");
        if (retval)
@@ -1890,33 +1910,27 @@ static int __init comedi_init(void)
        comedi_class = class_create(THIS_MODULE, "comedi");
        if (IS_ERR(comedi_class)) {
                printk("comedi: failed to create class");
-               unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
-                       COMEDI_NUM_MINORS);
                cdev_del(&comedi_cdev);
-               return PTR_ERR(comedi_class);
-       }
-       comedi_devices =
-               kcalloc(COMEDI_NDEVICES, sizeof(comedi_device), GFP_KERNEL);
-       if (!comedi_devices) {
                unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
                        COMEDI_NUM_MINORS);
-               cdev_del(&comedi_cdev);
-               class_destroy(comedi_class);
-               return -ENOMEM;
+               return PTR_ERR(comedi_class);
        }
 
        /* XXX requires /proc interface */
        comedi_proc_init();
 
-       for (i = 0; i < COMEDI_NDEVICES; i++) {
-               struct device *csdev;
-               comedi_devices[i].minor = i;
-               csdev = COMEDI_DEVICE_CREATE(comedi_class, 0,
-                               MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i", i);
-               if (!IS_ERR(csdev))
-                       comedi_devices[i].class_dev = csdev;
-               spin_lock_init(&comedi_devices[i].spinlock);
-               mutex_init(&comedi_devices[i].mutex);
+       // create devices files for legacy/manual use
+       for (i = 0; i < COMEDI_NUM_LEGACY_MINORS; i++) {
+               int minor;
+               minor = comedi_alloc_board_minor(NULL);
+               if(minor < 0)
+               {
+                       comedi_cleanup_legacy_minors();
+                       cdev_del(&comedi_cdev);
+                       unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
+                               COMEDI_NUM_MINORS);
+                       return minor;
+               }
        }
 
        comedi_rt_init();
@@ -1930,25 +1944,18 @@ static void __exit comedi_cleanup(void)
 {
        int i;
 
-       for (i = 0; i < COMEDI_NDEVICES; i++) {
-               comedi_device *dev;
-
-               dev = comedi_devices + i;
-               mutex_lock(&dev->mutex);
-               if (dev->attached)
-                       comedi_device_detach(dev);
-               mutex_unlock(&dev->mutex);
-               mutex_destroy(&dev->mutex);
-               device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, i));
+       comedi_cleanup_legacy_minors();
+       for(i = 0; i < COMEDI_NUM_MINORS; ++i)
+       {
+               BUG_ON(comedi_file_info_table[i]);
        }
+
        class_destroy(comedi_class);
        cdev_del(&comedi_cdev);
        unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
 
        comedi_proc_cleanup();
 
-       kfree(comedi_devices);
-
        comedi_rt_cleanup();
 
        comedi_unregister_ioctl32();
@@ -2064,3 +2071,171 @@ static int is_device_busy(comedi_device * dev)
 
        return 0;
 }
+
+void comedi_device_init(comedi_device *dev)
+{
+       memset(dev, 0, sizeof(comedi_device));
+       spin_lock_init(&dev->spinlock);
+       mutex_init(&dev->mutex);
+       dev->minor = -1;
+}
+
+void comedi_device_cleanup(comedi_device *dev)
+{
+       if(dev == NULL) return;
+       mutex_lock(&dev->mutex);
+       if (dev->attached)
+               comedi_device_detach(dev);
+       mutex_unlock(&dev->mutex);
+       mutex_destroy(&dev->mutex);
+}
+
+int comedi_alloc_board_minor(struct device *hardware_device)
+{
+       unsigned long flags;
+       struct comedi_device_file_info *info;
+       device_create_result_type *csdev;
+       unsigned i;
+
+       info = kzalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
+       if(info == NULL) return -ENOMEM;
+       info->device = kzalloc(sizeof(comedi_device), GFP_KERNEL);
+       if(info->device == NULL)
+       {
+               kfree(info);
+               return -ENOMEM;
+       }
+       comedi_device_init(info->device);
+       comedi_spin_lock_irqsave(&comedi_file_info_table_lock, flags);
+       for(i = 0; i < COMEDI_NUM_BOARD_MINORS; ++i)
+       {
+               if(comedi_file_info_table[i] == NULL)
+               {
+                       comedi_file_info_table[i] = info;
+                       break;
+               }
+       }
+       comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
+       if(i == COMEDI_NUM_BOARD_MINORS)
+       {
+               comedi_device_cleanup(info->device);
+               kfree(info->device);
+               kfree(info);
+               rt_printk("comedi: error: ran out of minor numbers for board device files.\n");
+               return -EBUSY;
+       }
+       info->device->minor = i;
+       csdev = COMEDI_DEVICE_CREATE(comedi_class, NULL,
+               MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i", i);
+       if(!IS_ERR(csdev)) {
+               info->device->class_dev = csdev;
+               if(hardware_device)
+               {
+                       sysfs_create_link(&csdev->kobj,
+                               &hardware_device->kobj, "device");
+               }
+       }
+       return i;
+}
+
+void comedi_free_board_minor(unsigned minor)
+{
+       unsigned long flags;
+       struct comedi_device_file_info *info;
+
+       BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
+       comedi_spin_lock_irqsave(&comedi_file_info_table_lock, flags);
+       info = comedi_file_info_table[minor];
+       comedi_file_info_table[minor] = NULL;
+       comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
+
+       if(info)
+       {
+               comedi_device *dev = info->device;
+               if(dev)
+               {
+                       if(dev->class_dev)
+                       {
+                               sysfs_remove_link(&dev->class_dev->kobj, "device");
+                               device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, dev->minor));
+                       }
+                       comedi_device_cleanup(dev)
+                       kfree(dev);
+               }
+               kfree(info);
+       }
+}
+
+int comedi_alloc_subdevice_minor(comedi_device *dev, comedi_subdevice *s)
+{
+       unsigned long flags;
+       struct comedi_device_file_info *info;
+       device_create_result_type *csdev;
+       unsigned i;
+
+       info = kmalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
+       if(info == NULL) return -ENOMEM;
+       info->device = dev;
+       info->read_subdevice = s;
+       info->write_subdevice = s;
+       comedi_spin_lock_irqsave(&comedi_file_info_table_lock, flags);
+       for(i = COMEDI_FIRST_SUBDEVICE_MINOR; i < COMEDI_NUM_BOARD_MINORS; ++i)
+       {
+               if(comedi_file_info_table[i] == NULL)
+               {
+                       comedi_file_info_table[i] = info;
+                       break;
+               }
+       }
+       comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
+       if(i == COMEDI_NUM_MINORS)
+       {
+               kfree(info);
+               rt_printk("comedi: error: ran out of minor numbers for board device files.\n");
+               return -EBUSY;
+       }
+       s->minor = i;
+       csdev = COMEDI_DEVICE_CREATE(comedi_class, dev->class_dev,
+               MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i_subd%i", dev->minor, s - dev->subdevices);
+       if(!IS_ERR(csdev))
+       {
+               s->class_dev = csdev;
+       }
+       return i;
+}
+
+void comedi_free_subdevice_minor(comedi_subdevice *s)
+{
+       unsigned long flags;
+       struct comedi_device_file_info *info;
+
+       if(s == NULL) return;
+       if(s->minor < 0) return;
+
+       BUG_ON(s->minor >= COMEDI_NUM_MINORS);
+       BUG_ON(s->minor < COMEDI_FIRST_SUBDEVICE_MINOR);
+
+       comedi_spin_lock_irqsave(&comedi_file_info_table_lock, flags);
+       info = comedi_file_info_table[s->minor];
+       comedi_file_info_table[s->minor] = NULL;
+       comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
+
+       if(s->class_dev)
+       {
+               device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, s->minor));
+               s->class_dev = NULL;
+       }
+       kfree(info);
+}
+
+struct comedi_device_file_info *comedi_get_device_file_info(unsigned minor)
+{
+       unsigned long flags;
+       struct comedi_device_file_info *info;
+
+       BUG_ON(minor >= COMEDI_NUM_MINORS);
+       comedi_spin_lock_irqsave(&comedi_file_info_table_lock, flags);
+       info = comedi_file_info_table[minor];
+       comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
+       return info;
+}
index 1189a896de329c3652d776651c3df2bce740669d..7c3658596990d0149dcf6d158452a1ad0ff2d88c 100644 (file)
@@ -31,8 +31,6 @@
 /* for drivers */
 EXPORT_SYMBOL(comedi_driver_register);
 EXPORT_SYMBOL(comedi_driver_unregister);
-EXPORT_SYMBOL(comedi_allocate_dev);
-EXPORT_SYMBOL(comedi_deallocate_dev);
 //EXPORT_SYMBOL(comedi_bufcheck);
 //EXPORT_SYMBOL(comedi_done);
 //EXPORT_SYMBOL(comedi_error_done);
@@ -58,10 +56,14 @@ EXPORT_SYMBOL(rt_pend_call);
 #ifdef CONFIG_COMEDI_DEBUG
 EXPORT_SYMBOL(comedi_debug);
 #endif
+EXPORT_SYMBOL_GPL(comedi_alloc_board_minor);
+EXPORT_SYMBOL_GPL(comedi_free_board_minor);
+EXPORT_SYMBOL_GPL(comedi_pci_auto_config);
+EXPORT_SYMBOL_GPL(comedi_pci_auto_unconfig);
 
 /* for kcomedilib */
-EXPORT_SYMBOL(comedi_devices);
 EXPORT_SYMBOL(check_chanlist);
+EXPORT_SYMBOL_GPL(comedi_get_device_file_info);
 
 EXPORT_SYMBOL(comedi_buf_put);
 EXPORT_SYMBOL(comedi_buf_get);
index 16df91e75f76020c0d5468dce41835c46e4b3f1e..ed203125cd2ff970d3959504f7bcca948c57bd5e 100644 (file)
@@ -27,6 +27,7 @@
 #include "comedi_fops.h"
 #include <linux/device.h>
 #include <linux/module.h>
+#include <linux/pci.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -69,13 +70,7 @@ static void cleanup_device(comedi_device * dev)
        if (dev->subdevices) {
                for (i = 0; i < dev->n_subdevices; i++) {
                        s = dev->subdevices + i;
-                       if (s->class_dev) {
-                               unsigned minor =
-                                       comedi_construct_minor_for_subdevice
-                                       (dev, i);
-                               dev_t devt = MKDEV(COMEDI_MAJOR, minor);
-                               device_destroy(comedi_class, devt);
-                       }
+                       comedi_free_subdevice_minor(s);
                        if (s->async) {
                                comedi_buf_alloc(dev, s, 0);
                                kfree(s->async);
@@ -89,7 +84,6 @@ static void cleanup_device(comedi_device * dev)
                kfree(dev->private);
                dev->private = NULL;
        }
-       module_put(dev->driver->module);
        dev->driver = 0;
        dev->board_name = NULL;
        dev->board_ptr = NULL;
@@ -102,7 +96,7 @@ static void cleanup_device(comedi_device * dev)
        comedi_set_hw_dev(dev, NULL);
 }
 
-static int __comedi_device_detach(comedi_device * dev)
+static void __comedi_device_detach(comedi_device * dev)
 {
        dev->attached = 0;
        if (dev->driver) {
@@ -111,14 +105,13 @@ static int __comedi_device_detach(comedi_device * dev)
                printk("BUG: dev->driver=NULL in comedi_device_detach()\n");
        }
        cleanup_device(dev);
-       return 0;
 }
 
-int comedi_device_detach(comedi_device * dev)
+void comedi_device_detach(comedi_device * dev)
 {
        if (!dev->attached)
-               return 0;
-       return __comedi_device_detach(dev);
+               return;
+       __comedi_device_detach(dev);
 }
 
 int comedi_device_attach(comedi_device * dev, comedi_devconfig * it)
@@ -168,7 +161,7 @@ int comedi_device_attach(comedi_device * dev, comedi_devconfig * it)
        }
        return -EIO;
 
-      attached:
+attached:
        /* do a little post-config cleanup */
        ret = postconfig(dev);
        if (ret < 0) {
@@ -182,6 +175,7 @@ int comedi_device_attach(comedi_device * dev, comedi_devconfig * it)
        }
        smp_wmb();
        dev->attached = 1;
+       module_put(dev->driver->module);
 
        return 0;
 }
@@ -200,10 +194,13 @@ int comedi_driver_unregister(comedi_driver * driver)
        int i;
 
        /* check for devices using this driver */
-       for (i = 0; i < COMEDI_NDEVICES; i++) {
+       for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
+               struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(i);
                comedi_device *dev;
 
-               dev = comedi_devices + i;
+               if(dev_file_info == NULL) continue;
+               dev = dev_file_info->device;
+
                mutex_lock(&dev->mutex);
                if (dev->attached && dev->driver == driver) {
                        if (dev->use_count)
@@ -227,16 +224,6 @@ int comedi_driver_unregister(comedi_driver * driver)
        return -EINVAL;
 }
 
-comedi_device *comedi_allocate_dev(comedi_driver * driver)
-{
-       return NULL;
-}
-
-void comedi_deallocate_dev(comedi_device * dev)
-{
-
-}
-
 static int postconfig(comedi_device * dev)
 {
        int i;
@@ -254,12 +241,8 @@ static int postconfig(comedi_device * dev)
                        s->len_chanlist = 1;
 
                if (s->do_cmd) {
-                       unsigned minor;
-                       dev_t devt;
-                       struct device *csdev;
-
                        BUG_ON((s->subdev_flags & (SDF_CMD_READ |
-                                               SDF_CMD_WRITE)) == 0);
+                               SDF_CMD_WRITE)) == 0);
                        BUG_ON(!s->do_cmdtest);
 
                        async = kzalloc(sizeof(comedi_async), GFP_KERNEL);
@@ -287,13 +270,7 @@ static int postconfig(comedi_device * dev)
                                if (ret < 0)
                                        return ret;
                        }
-                       minor = comedi_construct_minor_for_subdevice(dev, i);
-                       devt = MKDEV(COMEDI_MAJOR, minor);
-                       csdev = COMEDI_DEVICE_CREATE(comedi_class,
-                               dev->class_dev, devt, NULL, "comedi%i_sub%i",
-                               dev->minor, i);
-                       if (!IS_ERR(csdev))
-                               s->class_dev = csdev;
+                       comedi_alloc_subdevice_minor(dev, s);
                }
 
                if (!s->range_table && !s->range_table_list)
@@ -811,3 +788,44 @@ void comedi_reset_async_buf(comedi_async * async)
 
        async->events = 0;
 }
+
+int comedi_pci_auto_config(const char *board_name, struct pci_dev *pcidev)
+{
+       comedi_devconfig it;
+       int minor;
+       struct comedi_device_file_info *dev_file_info;
+       int retval;
+
+       minor = comedi_alloc_board_minor(&pcidev->dev);
+       if(minor < 0) return minor;
+       pci_set_drvdata(pcidev, (void*)minor);
+
+       dev_file_info = comedi_get_device_file_info(minor);
+
+       memset(&it, 0, sizeof(it));
+       strncpy(it.board_name, board_name, COMEDI_NAMELEN);
+       it.board_name[COMEDI_NAMELEN - 1] = '\0';
+       // pci bus
+       it.options[0] = pcidev->bus->number;
+       // pci slot
+       it.options[1] = PCI_SLOT(pcidev->devfn);
+
+       mutex_lock(&dev_file_info->device->mutex);
+       retval = comedi_device_attach(dev_file_info->device, &it);
+       mutex_unlock(&dev_file_info->device->mutex);
+       if(retval < 0)
+       {
+               comedi_free_board_minor(minor);
+       }
+       return retval;
+}
+
+void comedi_pci_auto_unconfig(struct pci_dev *pcidev)
+{
+       unsigned long minor = (unsigned long)pci_get_drvdata(pcidev);
+       struct comedi_device_file_info *dev_file_info;
+
+       BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
+
+       comedi_free_board_minor(minor);
+}
index d7bae245442037cdb32a699b372c6aaec885c02c..bd7e3d524eed271c8e6c97e423ee81a60602d69f 100644 (file)
@@ -389,7 +389,7 @@ static void *Realloc(const void *oldmem, size_t newlen, size_t oldlen)
 static int doDevConfig(comedi_device * dev, comedi_devconfig * it)
 {
        int i;
-       comedi_t *devs_opened[COMEDI_NDEVICES];
+       comedi_t *devs_opened[COMEDI_NUM_BOARD_MINORS];
 
        memset(devs_opened, 0, sizeof(devs_opened));
        devpriv->name[0] = 0;;
@@ -402,7 +402,7 @@ static int doDevConfig(comedi_device * dev, comedi_devconfig * it)
                int sdev = -1, nchans, tmp;
                BondedDevice *bdev = 0;
 
-               if (minor < 0 || minor > COMEDI_NDEVICES) {
+               if (minor < 0 || minor > COMEDI_NUM_BOARD_MINORS) {
                        ERROR("Minor %d is invalid!\n", minor);
                        return 0;
                }
index 3067e1a29014076e99f6e5453e52f28bf752df41..436d436ca1e71e3829798c58c3925db452f08ad7 100644 (file)
@@ -125,6 +125,8 @@ Bugs:
 
 #define MAX_N_CALDACS (16+16+2)
 
+#define DRV_NAME "ni_pcimio"
+
 /* The following two tables must be in the same order */
 static DEFINE_PCI_DEVICE_TABLE(ni_pci_table) = {
        {PCI_VENDOR_ID_NATINST, 0x0162, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
@@ -1190,13 +1192,41 @@ static const ni_board ni_boards[] = {
 static int pcimio_attach(comedi_device * dev, comedi_devconfig * it);
 static int pcimio_detach(comedi_device * dev);
 static comedi_driver driver_pcimio = {
-      driver_name:"ni_pcimio",
-      module:THIS_MODULE,
-      attach:pcimio_attach,
-      detach:pcimio_detach,
+       driver_name: DRV_NAME,
+       module:THIS_MODULE,
+       attach:pcimio_attach,
+       detach:pcimio_detach,
+};
+static int ni_pcimio_pci_probe(struct pci_dev *dev,
+       const struct pci_device_id *ent);
+static void ni_pcimio_pci_remove(struct pci_dev *dev);
+
+static struct pci_driver ni_pcimio_pci_driver =
+{
+       .name = DRV_NAME,
+       .id_table = ni_pci_table,
+       .probe = &ni_pcimio_pci_probe,
+       .remove = __devexit_p(&ni_pcimio_pci_remove)
 };
 
-COMEDI_INITCLEANUP(driver_pcimio);
+MODULE_AUTHOR("Comedi http://www.comedi.org");
+MODULE_DESCRIPTION("Comedi driver for National Instruments E-series, M-series, and related boards");
+MODULE_LICENSE("GPL");
+static int __init driver_pcimio_init_module(void)
+{
+       int retval;
+
+       retval = comedi_driver_register(&driver_pcimio);
+       if(retval < 0) return retval;
+       return pci_register_driver(&ni_pcimio_pci_driver);
+}
+static void __exit driver_pcimio_cleanup_module(void)
+{
+       pci_unregister_driver(&ni_pcimio_pci_driver);
+       comedi_driver_unregister(&driver_pcimio);
+}
+module_init(driver_pcimio_init_module);
+module_exit(driver_pcimio_cleanup_module);
 
 typedef struct {
 NI_PRIVATE_COMMON} ni_private;
@@ -1650,7 +1680,7 @@ static int pcimio_attach(comedi_device * dev, comedi_devconfig * it)
        } else {
                printk(" ( irq = %u )", dev->irq);
                if ((ret = comedi_request_irq(dev->irq, ni_E_interrupt,
-                                       NI_E_IRQ_FLAGS, "ni_pcimio",
+                                       NI_E_IRQ_FLAGS, DRV_NAME,
                                        dev)) < 0) {
                        printk(" irq not available\n");
                        dev->irq = 0;
@@ -1757,3 +1787,16 @@ static int pcimio_dio_change(comedi_device * dev, comedi_subdevice * s,
 
        return 0;
 }
+
+// pci_driver functions
+
+static int __devinit ni_pcimio_pci_probe(struct pci_dev *dev,
+       const struct pci_device_id *ent)
+{
+       return comedi_pci_auto_config(DRV_NAME, dev);
+}
+
+static void __devexit ni_pcimio_pci_remove(struct pci_dev *dev)
+{
+       comedi_pci_auto_unconfig(dev);
+}
index bcb14f4dd7a1c524afbe47adb3c3a8fa2a7bb4f9..c209c8b625893be1184daa4709a2c1c6cfbad3c6 100644 (file)
@@ -44,6 +44,7 @@ MODULE_LICENSE("GPL");
 
 comedi_t *comedi_open(const char *filename)
 {
+       struct comedi_device_file_info *dev_file_info;
        comedi_device *dev;
        unsigned int minor;
 
@@ -52,12 +53,15 @@ comedi_t *comedi_open(const char *filename)
 
        minor = simple_strtoul(filename + 11, NULL, 0);
 
-       if (minor >= COMEDI_NDEVICES)
+       if (minor >= COMEDI_NUM_BOARD_MINORS)
                return NULL;
 
-       dev = comedi_get_device_by_minor(minor);
+       dev_file_info = comedi_get_device_file_info(minor);
+       if(dev_file_info == NULL)
+               return NULL;
+       dev = dev_file_info->device;
 
-       if (!dev->attached)
+       if(dev == NULL || !dev->attached)
                return NULL;
 
        if (!try_module_get(dev->driver->module))
@@ -68,14 +72,18 @@ comedi_t *comedi_open(const char *filename)
 
 comedi_t *comedi_open_old(unsigned int minor)
 {
+       struct comedi_device_file_info *dev_file_info;
        comedi_device *dev;
 
-       if (minor >= COMEDI_NDEVICES)
+       if (minor >= COMEDI_NUM_MINORS)
                return NULL;
 
-       dev = comedi_get_device_by_minor(minor);
+       dev_file_info = comedi_get_device_file_info(minor);
+       if(dev_file_info == NULL)
+               return NULL;
+       dev = dev_file_info->device;
 
-       if (!dev->attached)
+       if(dev == NULL || !dev->attached)
                return NULL;
 
        return (comedi_t *) dev;
index 472367a07729558645c6017eaf61e7506bf94ae4..bd276d2c12fc0dd6d63e7271db620ab498fc72bb 100644 (file)
@@ -51,10 +51,13 @@ int comedi_read_procmem(char *buf, char **start, off_t offset, int len,
                "format string: %s\n",
                "\"%2d: %-20s %-20s %4d\",i,driver_name,board_name,n_subdevices");
 
-       for (i = 0; i < COMEDI_NDEVICES; i++) {
+       for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
+               struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(i);
                comedi_device *dev;
 
-               dev = comedi_devices + i;
+               if(dev_file_info == NULL) continue;
+               dev = dev_file_info->device;
+
                if (dev->attached) {
                        devices_q = 1;
                        l += sprintf(buf + l, "%2d: %-20s %-20s %4d\n",
index 09f54594818b4e474151972f1121046ff1ef24a4..54ff2bbbb2a4f6e2bd882839c53e7109f17fa9bc 100644 (file)
@@ -47,27 +47,20 @@ const comedi_lrange range_unknown = { 1, {{0, 1000000, UNIT_none}} };
 int do_rangeinfo_ioctl(comedi_device * dev, comedi_rangeinfo * arg)
 {
        comedi_rangeinfo it;
-       int minor, subd, chan;
+       int subd, chan;
        const comedi_lrange *lr;
        comedi_subdevice *s;
-       comedi_device *query_dev;
 
        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;
 
-       if (minor > COMEDI_NDEVICES)
+       if (!dev->attached)
                return -EINVAL;
-       query_dev = comedi_devices + minor;
-       if (!query_dev->attached)
+       if (subd >= dev->n_subdevices)
                return -EINVAL;
-       if (subd >= query_dev->n_subdevices)
-               return -EINVAL;
-       s = query_dev->subdevices + subd;
+       s = dev->subdevices + subd;
        if (s->range_table) {
                lr = s->range_table;
        } else if (s->range_table_list) {
index 26e836f172a83962b911d23b31b9954a73de9c92..0e1bc3f01e7bbe2411aa72967715d22ca8ad7e39 100644 (file)
 #define PCI_VENDOR_ID_CONTEC           0x1221
 #define PCI_VENDOR_ID_MEILHAUS         0x1402
 
+#define COMEDI_NUM_MINORS 0x100
+#define COMEDI_NUM_LEGACY_MINORS 0x10
+#define COMEDI_NUM_BOARD_MINORS 0x30
+#define COMEDI_FIRST_SUBDEVICE_MINOR COMEDI_NUM_BOARD_MINORS
+
 typedef struct comedi_device_struct comedi_device;
 typedef struct comedi_subdevice_struct comedi_subdevice;
 typedef struct comedi_async_struct comedi_async;
@@ -150,7 +155,8 @@ struct comedi_subdevice_struct {
 
        unsigned int state;
 
-       struct device *class_dev;
+       device_create_result_type *class_dev;
+       int minor;
 };
 
 struct comedi_buf_page {
@@ -222,8 +228,8 @@ struct comedi_device_struct {
        comedi_driver *driver;
        void *private;
 
-       struct device *class_dev;
-       unsigned minor;
+       device_create_result_type *class_dev;
+       int minor;
        /* hw_dev is passed to dma_alloc_coherent when allocating async buffers for subdevices
           that have async_dma_dir set to something other than DMA_NONE */
        struct device *hw_dev;
@@ -252,13 +258,12 @@ struct comedi_device_struct {
        void (*close) (comedi_device * dev);
 };
 
-struct comedi_inode_private {
+struct comedi_device_file_info {
        comedi_device *device;
-       comedi_subdevice *subdevice;
+       comedi_subdevice *read_subdevice;
+       comedi_subdevice *write_subdevice;
 };
 
-extern comedi_device *comedi_devices;
-
 #ifdef CONFIG_COMEDI_DEBUG
 extern int comedi_debug;
 #else
@@ -281,83 +286,28 @@ enum comedi_minor_bits {
 };
 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)
-{
-       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;
-}
+struct comedi_device_file_info* comedi_get_device_file_info(unsigned minor);
 
-static inline comedi_subdevice *comedi_get_subdevice_by_minor(unsigned minor)
+static inline comedi_subdevice* comedi_get_read_subdevice(const struct comedi_device_file_info *info)
 {
-       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;
+       if(info->read_subdevice) return info->read_subdevice;
+       if(info->device == NULL) return NULL;
+       return info->device->read_subdev;
 }
 
-static inline comedi_subdevice *comedi_get_read_subdevice(comedi_device * dev,
-       unsigned minor)
+static inline comedi_subdevice* comedi_get_write_subdevice(const struct comedi_device_file_info *info)
 {
-       comedi_subdevice *read_subdev = comedi_get_subdevice_by_minor(minor);
-       if (read_subdev == NULL) {
-               read_subdev = dev->read_subdev;
-       }
-       if (read_subdev == NULL || read_subdev->async == NULL
-               || (read_subdev->subdev_flags & SDF_CMD_READ) == 0)
-               return NULL;
-       return read_subdev;
+       if(info->write_subdevice) return info->write_subdevice;
+       if(info->device == NULL) return NULL;
+       return info->device->write_subdev;
 }
 
-static inline comedi_subdevice *comedi_get_write_subdevice(comedi_device * dev,
-       unsigned minor)
-{
-       comedi_subdevice *write_subdev = comedi_get_subdevice_by_minor(minor);
-       if (write_subdev == NULL) {
-               write_subdev = dev->write_subdev;
-       }
-       if (write_subdev == NULL || write_subdev->async == NULL
-               || (write_subdev->subdev_flags & SDF_CMD_WRITE) == 0)
-               return NULL;
-       return write_subdev;
-}
-
-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);
+void comedi_device_detach(comedi_device * dev);
 int comedi_device_attach(comedi_device * dev, comedi_devconfig * it);
 int comedi_driver_register(comedi_driver *);
 int comedi_driver_unregister(comedi_driver *);
 
-comedi_device *comedi_allocate_dev(comedi_driver *);
-void comedi_deallocate_dev(comedi_device *);
-
 void init_polling(void);
 void cleanup_polling(void);
 void start_polling(comedi_device *);
@@ -444,6 +394,7 @@ static inline int alloc_subdevices(comedi_device * dev,
                dev->subdevices[i].device = dev;
                dev->subdevices[i].async_dma_dir = DMA_NONE;
                spin_lock_init(&dev->subdevices[i].spin_lock);
+               dev->subdevices[i].minor = -1;
        }
        return 0;
 }
@@ -529,6 +480,13 @@ static inline void *comedi_aux_data(int options[], int n)
        return (void *)address;
 }
 
+int comedi_alloc_board_minor(struct device *hardware_device);
+void comedi_free_board_minor(unsigned minor);
+int comedi_alloc_subdevice_minor(comedi_device *dev, comedi_subdevice *s);
+void comedi_free_subdevice_minor(comedi_subdevice *s);
+int comedi_pci_auto_config(const char *board_name, struct pci_dev *pcidev);
+void comedi_pci_auto_unconfig(struct pci_dev *pcidev);
+
 //#ifdef CONFIG_COMEDI_RT
 #include <linux/comedi_rt.h>
 //#endif
index 2b7a17f23c8b3f02a159f3635630706e96019506..79fc252d4b626587fbfacd4a97b708dee1f10dcd 100644 (file)
@@ -87,18 +87,21 @@ static inline void device_destroy(struct class *cs, dev_t devt)
        (struct class *)class_simple_create(owner, name)
 #define class_destroy(cs) \
        class_simple_destroy((struct class_simple *)(cs))
+
+typedef struct class_device device_create_result_type;
 #define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, fmt...) \
-       (struct device *)class_simple_device_add((struct class_simple *)(cs), \
+       class_simple_device_add((struct class_simple *)(cs), \
                devt, NULL, fmt)
 #define device_destroy(cs, devt) \
        class_simple_device_remove(devt)
 
 #else
-
+/* versions earlier than 2.6.15 are currently broken as of 2008-10-16 FMH*/
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
 
+typedef struct class_device device_create_result_type;
 #define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, fmt...) \
-       (struct device *)class_device_create(cs, devt, NULL, fmt)
+       class_device_create(cs, devt, NULL, fmt)
 #define device_destroy(cs, devt) \
        class_device_destroy(cs, devt)
 
@@ -107,9 +110,10 @@ static inline void device_destroy(struct class *cs, dev_t devt)
 exactly which kernel version it was fixed in. */
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
 
+typedef struct class_device device_create_result_type;
 #define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, fmt...) \
-       (struct device *)class_device_create( \
-                       cs, (struct class_device *)parent, devt, NULL, fmt)
+       class_device_create( \
+                       cs, parent, devt, NULL, fmt)
 #define device_destroy(cs, devt) \
        class_device_destroy(cs, devt)
 
@@ -117,6 +121,7 @@ exactly which kernel version it was fixed in. */
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
 
+typedef struct device device_create_result_type;
 #define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, fmt...) \
        device_create(cs, parent, devt, fmt)
 
@@ -124,6 +129,7 @@ exactly which kernel version it was fixed in. */
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
 
+typedef struct device device_create_result_type;
 #define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, fmt...) \
        device_create_drvdata(cs, parent, devt, drvdata, fmt)