//#include "kvmem.h"
-MODULE_AUTHOR("David Schleef <ds@schleef.org>");
+MODULE_AUTHOR("http://www.comedi.org");
MODULE_DESCRIPTION("Comedi core module");
MODULE_LICENSE("GPL");
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);
#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);
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)))
{
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));
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 */
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;
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;
{
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;
}
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
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);
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;
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);
goto done;
}
- s = comedi_get_read_subdevice(dev, minor);
+ s = comedi_get_read_subdevice(dev_file_info);
if (s == NULL) {
retval = -EIO;
goto done;
{
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;
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;
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);
}
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)
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();
{
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();
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;
+}
/* 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);
#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);
#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>
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);
kfree(dev->private);
dev->private = NULL;
}
- module_put(dev->driver->module);
dev->driver = 0;
dev->board_name = NULL;
dev->board_ptr = NULL;
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) {
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)
}
return -EIO;
- attached:
+attached:
/* do a little post-config cleanup */
ret = postconfig(dev);
if (ret < 0) {
}
smp_wmb();
dev->attached = 1;
+ module_put(dev->driver->module);
return 0;
}
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)
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;
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);
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)
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);
+}
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;;
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;
}
#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},
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;
} 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;
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);
+}
comedi_t *comedi_open(const char *filename)
{
+ struct comedi_device_file_info *dev_file_info;
comedi_device *dev;
unsigned int minor;
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))
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;
"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",
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) {
#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;
unsigned int state;
- struct device *class_dev;
+ device_create_result_type *class_dev;
+ int minor;
};
struct comedi_buf_page {
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;
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
};
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 *);
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;
}
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
(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)
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)
#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)
#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)