diff options
Diffstat (limited to 'drivers/staging/comedi/drivers.c')
-rw-r--r-- | drivers/staging/comedi/drivers.c | 187 |
1 files changed, 108 insertions, 79 deletions
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 36a93b9..6e13e45 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -28,6 +28,7 @@ #include <linux/device.h> #include <linux/module.h> #include <linux/pci.h> +#include <linux/usb.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/sched.h> @@ -46,26 +47,26 @@ #include <asm/io.h> #include <asm/system.h> -static int postconfig(comedi_device * dev); -static int insn_rw_emulate_bits(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data); -static void *comedi_recognize(comedi_driver * driv, const char *name); -static void comedi_report_boards(comedi_driver * driv); -static int poll_invalid(comedi_device * dev, comedi_subdevice * s); -int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s, +static int postconfig(struct comedi_device *dev); +static int insn_rw_emulate_bits(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static void *comedi_recognize(struct comedi_driver * driv, const char *name); +static void comedi_report_boards(struct comedi_driver *driv); +static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s); +int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long new_size); -comedi_driver *comedi_drivers; +struct comedi_driver *comedi_drivers; int comedi_modprobe(int minor) { return -EINVAL; } -static void cleanup_device(comedi_device * dev) +static void cleanup_device(struct comedi_device *dev) { int i; - comedi_subdevice *s; + struct comedi_subdevice *s; if (dev->subdevices) { for (i = 0; i < dev->n_subdevices; i++) { @@ -80,10 +81,8 @@ static void cleanup_device(comedi_device * dev) dev->subdevices = NULL; dev->n_subdevices = 0; } - if (dev->private) { - kfree(dev->private); - dev->private = NULL; - } + kfree(dev->private); + dev->private = NULL; dev->driver = 0; dev->board_name = NULL; dev->board_ptr = NULL; @@ -96,7 +95,7 @@ static void cleanup_device(comedi_device * dev) comedi_set_hw_dev(dev, NULL); } -static void __comedi_device_detach(comedi_device * dev) +static void __comedi_device_detach(struct comedi_device *dev) { dev->attached = 0; if (dev->driver) { @@ -107,16 +106,16 @@ static void __comedi_device_detach(comedi_device * dev) cleanup_device(dev); } -void comedi_device_detach(comedi_device * dev) +void comedi_device_detach(struct comedi_device *dev) { if (!dev->attached) return; __comedi_device_detach(dev); } -int comedi_device_attach(comedi_device * dev, comedi_devconfig * it) +int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - comedi_driver *driv; + struct comedi_driver *driv; int ret; if (dev->attached) @@ -139,7 +138,7 @@ int comedi_device_attach(comedi_device * dev, comedi_devconfig * it) continue; } } - //initialize dev->driver here so comedi_error() can be called from attach + /* initialize dev->driver here so comedi_error() can be called from attach */ dev->driver = driv; ret = driv->attach(dev, it); if (ret < 0) { @@ -150,8 +149,8 @@ int comedi_device_attach(comedi_device * dev, comedi_devconfig * it) goto attached; } - // recognize has failed if we get here - // report valid board names before returning error + /* recognize has failed if we get here */ + /* report valid board names before returning error */ for (driv = comedi_drivers; driv; driv = driv->next) { if (!try_module_get(driv->module)) { printk("comedi: failed to increment module count\n"); @@ -181,7 +180,7 @@ attached: return 0; } -int comedi_driver_register(comedi_driver * driver) +int comedi_driver_register(struct comedi_driver *driver) { driver->next = comedi_drivers; comedi_drivers = driver; @@ -189,15 +188,15 @@ int comedi_driver_register(comedi_driver * driver) return 0; } -int comedi_driver_unregister(comedi_driver * driver) +int comedi_driver_unregister(struct comedi_driver *driver) { - comedi_driver *prev; + struct comedi_driver *prev; int i; /* check for devices using this driver */ 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; + struct comedi_device *dev; if(dev_file_info == NULL) continue; dev = dev_file_info->device; @@ -225,11 +224,11 @@ int comedi_driver_unregister(comedi_driver * driver) return -EINVAL; } -static int postconfig(comedi_device * dev) +static int postconfig(struct comedi_device *dev) { int i; - comedi_subdevice *s; - comedi_async *async = NULL; + struct comedi_subdevice *s; + struct comedi_async *async = NULL; int ret; for (i = 0; i < dev->n_subdevices; i++) { @@ -246,7 +245,7 @@ static int postconfig(comedi_device * dev) SDF_CMD_WRITE)) == 0); BUG_ON(!s->do_cmdtest); - async = kzalloc(sizeof(comedi_async), GFP_KERNEL); + async = kzalloc(sizeof(struct comedi_async), GFP_KERNEL); if (async == NULL) { printk("failed to allocate async struct\n"); return -ENOMEM; @@ -298,8 +297,8 @@ static int postconfig(comedi_device * dev) return 0; } -// generic recognize function for drivers that register their supported board names -void *comedi_recognize(comedi_driver * driv, const char *name) +/* generic recognize function for drivers that register their supported board names */ +void *comedi_recognize(struct comedi_driver * driv, const char *name) { unsigned i; const char *const *name_ptr = driv->board_name; @@ -314,7 +313,7 @@ void *comedi_recognize(comedi_driver * driv, const char *name) return NULL; } -void comedi_report_boards(comedi_driver * driv) +void comedi_report_boards(struct comedi_driver *driv) { unsigned int i; const char *const *name_ptr; @@ -332,28 +331,28 @@ void comedi_report_boards(comedi_driver * driv) printk(" %s\n", driv->driver_name); } -static int poll_invalid(comedi_device * dev, comedi_subdevice * s) +static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s) { return -EINVAL; } -int insn_inval(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { return -EINVAL; } -static int insn_rw_emulate_bits(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +static int insn_rw_emulate_bits(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { - comedi_insn new_insn; + struct comedi_insn new_insn; int ret; static const unsigned channels_per_bitfield = 32; unsigned chan = CR_CHAN(insn->chanspec); const unsigned base_bitfield_channel = (chan < channels_per_bitfield) ? 0 : chan; - lsampl_t new_data[2]; + unsigned int new_data[2]; memset(new_data, 0, sizeof(new_data)); memset(&new_insn, 0, sizeof(new_insn)); new_insn.insn = INSN_BITS; @@ -380,7 +379,7 @@ static int insn_rw_emulate_bits(comedi_device * dev, comedi_subdevice * s, return 1; } -static inline unsigned long uvirt_to_kva(pgd_t * pgd, unsigned long adr) +static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr) { unsigned long ret = 0UL; pmd_t *pmd; @@ -413,10 +412,10 @@ static inline unsigned long kvirt_to_kva(unsigned long adr) return kva; } -int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s, +int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long new_size) { - comedi_async *async = s->async; + struct comedi_async *async = s->async; /* Round up new_size to multiple of PAGE_SIZE */ new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK; @@ -425,7 +424,7 @@ int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s, if (async->prealloc_buf && async->prealloc_bufsz == new_size) { return 0; } - // deallocate old buffer + /* deallocate old buffer */ if (async->prealloc_buf) { vunmap(async->prealloc_buf); async->prealloc_buf = NULL; @@ -454,7 +453,7 @@ int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s, async->buf_page_list = NULL; async->n_buf_pages = 0; } - // allocate new buffer + /* allocate new buffer */ if (new_size) { unsigned i = 0; unsigned n_pages = new_size >> PAGE_SHIFT; @@ -537,16 +536,15 @@ int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s, /* munging is applied to data by core as it passes between user * and kernel space */ -unsigned int comedi_buf_munge(comedi_async * async, unsigned int num_bytes) +unsigned int comedi_buf_munge(struct comedi_async *async, unsigned int num_bytes) { - comedi_subdevice *s = async->subdevice; + struct comedi_subdevice *s = async->subdevice; unsigned int count = 0; const unsigned num_sample_bytes = bytes_per_sample(s); if (s->munge == NULL || (async->cmd.flags & CMDF_RAWDATA)) { async->munge_count += num_bytes; - if ((int)(async->munge_count - async->buf_write_count) > 0) - BUG(); + BUG_ON((int)(async->munge_count - async->buf_write_count) > 0); return num_bytes; } /* don't munge partial samples */ @@ -567,7 +565,7 @@ unsigned int comedi_buf_munge(comedi_async * async, unsigned int num_bytes) s->munge(s->device, s, async->prealloc_buf + async->munge_ptr, block_size, async->munge_chan); - smp_wmb(); //barrier insures data is munged in buffer before munge_count is incremented + smp_wmb(); /* barrier insures data is munged in buffer before munge_count is incremented */ async->munge_chan += block_size / num_sample_bytes; async->munge_chan %= async->cmd.chanlist_len; @@ -576,12 +574,11 @@ unsigned int comedi_buf_munge(comedi_async * async, unsigned int num_bytes) async->munge_ptr %= async->prealloc_bufsz; count += block_size; } - if ((int)(async->munge_count - async->buf_write_count) > 0) - BUG(); + BUG_ON((int)(async->munge_count - async->buf_write_count) > 0); return count; } -unsigned int comedi_buf_write_n_available(comedi_async * async) +unsigned int comedi_buf_write_n_available(struct comedi_async *async) { unsigned int free_end; unsigned int nbytes; @@ -601,7 +598,7 @@ unsigned int comedi_buf_write_n_available(comedi_async * async) } /* allocates chunk for the writer from free buffer space */ -unsigned int comedi_buf_write_alloc(comedi_async * async, unsigned int nbytes) +unsigned int comedi_buf_write_alloc(struct comedi_async *async, unsigned int nbytes) { unsigned int free_end = async->buf_read_count + async->prealloc_bufsz; @@ -616,7 +613,7 @@ unsigned int comedi_buf_write_alloc(comedi_async * async, unsigned int nbytes) } /* allocates nothing unless it can completely fulfill the request */ -unsigned int comedi_buf_write_alloc_strict(comedi_async * async, +unsigned int comedi_buf_write_alloc_strict(struct comedi_async *async, unsigned int nbytes) { unsigned int free_end = async->buf_read_count + async->prealloc_bufsz; @@ -632,7 +629,7 @@ unsigned int comedi_buf_write_alloc_strict(comedi_async * async, } /* transfers a chunk from writer to filled buffer space */ -unsigned comedi_buf_write_free(comedi_async * async, unsigned int nbytes) +unsigned comedi_buf_write_free(struct comedi_async *async, unsigned int nbytes) { if ((int)(async->buf_write_count + nbytes - async->buf_write_alloc_count) > 0) { @@ -650,7 +647,7 @@ unsigned comedi_buf_write_free(comedi_async * async, unsigned int nbytes) } /* allocates a chunk for the reader from filled (and munged) buffer space */ -unsigned comedi_buf_read_alloc(comedi_async * async, unsigned nbytes) +unsigned comedi_buf_read_alloc(struct comedi_async *async, unsigned nbytes) { if ((int)(async->buf_read_alloc_count + nbytes - async->munge_count) > 0) { @@ -664,9 +661,9 @@ unsigned comedi_buf_read_alloc(comedi_async * async, unsigned nbytes) } /* transfers control of a chunk from reader to free buffer space */ -unsigned comedi_buf_read_free(comedi_async * async, unsigned int nbytes) +unsigned comedi_buf_read_free(struct comedi_async *async, unsigned int nbytes) { - // barrier insures data has been read out of buffer before read count is incremented + /* barrier insures data has been read out of buffer before read count is incremented */ smp_mb(); if ((int)(async->buf_read_count + nbytes - async->buf_read_alloc_count) > 0) { @@ -680,7 +677,7 @@ unsigned comedi_buf_read_free(comedi_async * async, unsigned int nbytes) return nbytes; } -void comedi_buf_memcpy_to(comedi_async * async, unsigned int offset, +void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset, const void *data, unsigned int num_bytes) { unsigned int write_ptr = async->buf_write_ptr + offset; @@ -705,7 +702,7 @@ void comedi_buf_memcpy_to(comedi_async * async, unsigned int offset, } } -void comedi_buf_memcpy_from(comedi_async * async, unsigned int offset, +void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset, void *dest, unsigned int nbytes) { void *src; @@ -731,7 +728,7 @@ void comedi_buf_memcpy_from(comedi_async * async, unsigned int offset, } } -unsigned int comedi_buf_read_n_available(comedi_async * async) +unsigned int comedi_buf_read_n_available(struct comedi_async *async) { unsigned num_bytes; @@ -746,32 +743,32 @@ unsigned int comedi_buf_read_n_available(comedi_async * async) return num_bytes; } -int comedi_buf_get(comedi_async * async, sampl_t * x) +int comedi_buf_get(struct comedi_async *async, short *x) { unsigned int n = comedi_buf_read_n_available(async); - if (n < sizeof(sampl_t)) + if (n < sizeof(short)) return 0; - comedi_buf_read_alloc(async, sizeof(sampl_t)); - *x = *(sampl_t *) (async->prealloc_buf + async->buf_read_ptr); - comedi_buf_read_free(async, sizeof(sampl_t)); + comedi_buf_read_alloc(async, sizeof(short)); + *x = *(short *) (async->prealloc_buf + async->buf_read_ptr); + comedi_buf_read_free(async, sizeof(short)); return 1; } -int comedi_buf_put(comedi_async * async, sampl_t x) +int comedi_buf_put(struct comedi_async *async, short x) { - unsigned int n = comedi_buf_write_alloc_strict(async, sizeof(sampl_t)); + unsigned int n = comedi_buf_write_alloc_strict(async, sizeof(short)); - if (n < sizeof(sampl_t)) { + if (n < sizeof(short)) { async->events |= COMEDI_CB_ERROR; return 0; } - *(sampl_t *) (async->prealloc_buf + async->buf_write_ptr) = x; - comedi_buf_write_free(async, sizeof(sampl_t)); + *(short *) (async->prealloc_buf + async->buf_write_ptr) = x; + comedi_buf_write_free(async, sizeof(short)); return 1; } -void comedi_reset_async_buf(comedi_async * async) +void comedi_reset_async_buf(struct comedi_async *async) { async->buf_write_alloc_count = 0; async->buf_write_count = 0; @@ -792,14 +789,27 @@ void comedi_reset_async_buf(comedi_async * async) int comedi_auto_config(struct device *hardware_device, const char *board_name, const int *options, unsigned num_options) { - comedi_devconfig it; + struct comedi_devconfig it; int minor; struct comedi_device_file_info *dev_file_info; int retval; + unsigned *private_data = NULL; + + if (!comedi_autoconfig) { + dev_set_drvdata(hardware_device, NULL); + return 0; + } minor = comedi_alloc_board_minor(hardware_device); if(minor < 0) return minor; - dev_set_drvdata(hardware_device, (void*)(unsigned long)minor); + + private_data = kmalloc(sizeof(unsigned), GFP_KERNEL); + if (private_data == NULL) { + retval = -ENOMEM; + goto cleanup; + } + *private_data = minor; + dev_set_drvdata(hardware_device, private_data); dev_file_info = comedi_get_device_file_info(minor); @@ -812,8 +822,11 @@ int comedi_auto_config(struct device *hardware_device, const char *board_name, c mutex_lock(&dev_file_info->device->mutex); retval = comedi_device_attach(dev_file_info->device, &it); mutex_unlock(&dev_file_info->device->mutex); + +cleanup: if(retval < 0) { + kfree(private_data); comedi_free_board_minor(minor); } return retval; @@ -821,20 +834,23 @@ int comedi_auto_config(struct device *hardware_device, const char *board_name, c void comedi_auto_unconfig(struct device *hardware_device) { - unsigned long minor = (unsigned long)dev_get_drvdata(hardware_device); + unsigned *minor = (unsigned *)dev_get_drvdata(hardware_device); + if(minor == NULL) return; - BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS); + BUG_ON(*minor >= COMEDI_NUM_BOARD_MINORS); - comedi_free_board_minor(minor); + comedi_free_board_minor(*minor); + dev_set_drvdata(hardware_device, NULL); + kfree(minor); } int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name) { int options[2]; - // pci bus + /* pci bus */ options[0] = pcidev->bus->number; - // pci slot + /* pci slot */ options[1] = PCI_SLOT(pcidev->devfn); return comedi_auto_config(&pcidev->dev, board_name, options, sizeof(options) / sizeof(options[0])); @@ -844,3 +860,16 @@ void comedi_pci_auto_unconfig(struct pci_dev *pcidev) { comedi_auto_unconfig(&pcidev->dev); } + +int comedi_usb_auto_config(struct usb_device *usbdev, + const char *board_name) +{ + BUG_ON(usbdev == NULL); + return comedi_auto_config(&usbdev->dev, board_name, NULL, 0); +} + +void comedi_usb_auto_unconfig(struct usb_device *usbdev) +{ + BUG_ON(usbdev == NULL); + comedi_auto_unconfig(&usbdev->dev); +} |