]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/staging/comedi/comedi_fops.c
staging: comedi: add comedi_dev_get_from_minor()
[linux.git] / drivers / staging / comedi / comedi_fops.c
1 /*
2     comedi/comedi_fops.c
3     comedi kernel module
4
5     COMEDI - Linux Control and Measurement Device Interface
6     Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
7
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
12
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17 */
18
19 #undef DEBUG
20
21 #include "comedi_compat32.h"
22
23 #include <linux/module.h>
24 #include <linux/errno.h>
25 #include <linux/kernel.h>
26 #include <linux/sched.h>
27 #include <linux/fcntl.h>
28 #include <linux/delay.h>
29 #include <linux/mm.h>
30 #include <linux/slab.h>
31 #include <linux/kmod.h>
32 #include <linux/poll.h>
33 #include <linux/init.h>
34 #include <linux/device.h>
35 #include <linux/vmalloc.h>
36 #include <linux/fs.h>
37 #include "comedidev.h"
38 #include <linux/cdev.h>
39 #include <linux/stat.h>
40
41 #include <linux/io.h>
42 #include <linux/uaccess.h>
43
44 #include "comedi_internal.h"
45
46 #define COMEDI_NUM_MINORS 0x100
47 #define COMEDI_NUM_SUBDEVICE_MINORS     \
48         (COMEDI_NUM_MINORS - COMEDI_NUM_BOARD_MINORS)
49
50 #ifdef CONFIG_COMEDI_DEBUG
51 int comedi_debug;
52 EXPORT_SYMBOL_GPL(comedi_debug);
53 module_param(comedi_debug, int, S_IRUGO | S_IWUSR);
54 MODULE_PARM_DESC(comedi_debug,
55                  "enable comedi core and driver debugging if non-zero (default 0)"
56                 );
57 #endif
58
59 static int comedi_num_legacy_minors;
60 module_param(comedi_num_legacy_minors, int, S_IRUGO);
61 MODULE_PARM_DESC(comedi_num_legacy_minors,
62                  "number of comedi minor devices to reserve for non-auto-configured devices (default 0)"
63                 );
64
65 unsigned int comedi_default_buf_size_kb = CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB;
66 module_param(comedi_default_buf_size_kb, uint, S_IRUGO | S_IWUSR);
67 MODULE_PARM_DESC(comedi_default_buf_size_kb,
68                  "default asynchronous buffer size in KiB (default "
69                  __MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB) ")");
70
71 unsigned int comedi_default_buf_maxsize_kb
72         = CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB;
73 module_param(comedi_default_buf_maxsize_kb, uint, S_IRUGO | S_IWUSR);
74 MODULE_PARM_DESC(comedi_default_buf_maxsize_kb,
75                  "default maximum size of asynchronous buffer in KiB (default "
76                  __MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB) ")");
77
78 static DEFINE_MUTEX(comedi_board_minor_table_lock);
79 static struct comedi_device
80 *comedi_board_minor_table[COMEDI_NUM_BOARD_MINORS];
81
82 static DEFINE_MUTEX(comedi_subdevice_minor_table_lock);
83 /* Note: indexed by minor - COMEDI_NUM_BOARD_MINORS. */
84 static struct comedi_subdevice
85 *comedi_subdevice_minor_table[COMEDI_NUM_SUBDEVICE_MINORS];
86
87 static struct class *comedi_class;
88 static struct cdev comedi_cdev;
89
90 static void comedi_device_init(struct comedi_device *dev)
91 {
92         kref_init(&dev->refcount);
93         spin_lock_init(&dev->spinlock);
94         mutex_init(&dev->mutex);
95         init_rwsem(&dev->attach_lock);
96         dev->minor = -1;
97 }
98
99 static void comedi_dev_kref_release(struct kref *kref)
100 {
101         struct comedi_device *dev =
102                 container_of(kref, struct comedi_device, refcount);
103
104         mutex_destroy(&dev->mutex);
105         kfree(dev);
106 }
107
108 int comedi_dev_put(struct comedi_device *dev)
109 {
110         if (dev)
111                 return kref_put(&dev->refcount, comedi_dev_kref_release);
112         return 1;
113 }
114 EXPORT_SYMBOL_GPL(comedi_dev_put);
115
116 static struct comedi_device *comedi_dev_get(struct comedi_device *dev)
117 {
118         if (dev)
119                 kref_get(&dev->refcount);
120         return dev;
121 }
122
123 static void comedi_device_cleanup(struct comedi_device *dev)
124 {
125         struct module *driver_module = NULL;
126
127         if (dev == NULL)
128                 return;
129         mutex_lock(&dev->mutex);
130         if (dev->attached)
131                 driver_module = dev->driver->module;
132         comedi_device_detach(dev);
133         while (dev->use_count > 0) {
134                 if (driver_module)
135                         module_put(driver_module);
136                 module_put(THIS_MODULE);
137                 dev->use_count--;
138         }
139         mutex_unlock(&dev->mutex);
140 }
141
142 static bool comedi_clear_board_dev(struct comedi_device *dev)
143 {
144         unsigned int i = dev->minor;
145         bool cleared = false;
146
147         mutex_lock(&comedi_board_minor_table_lock);
148         if (dev == comedi_board_minor_table[i]) {
149                 comedi_board_minor_table[i] = NULL;
150                 cleared = true;
151         }
152         mutex_unlock(&comedi_board_minor_table_lock);
153         return cleared;
154 }
155
156 static struct comedi_device *comedi_clear_board_minor(unsigned minor)
157 {
158         struct comedi_device *dev;
159
160         mutex_lock(&comedi_board_minor_table_lock);
161         dev = comedi_board_minor_table[minor];
162         comedi_board_minor_table[minor] = NULL;
163         mutex_unlock(&comedi_board_minor_table_lock);
164         return dev;
165 }
166
167 static void comedi_free_board_dev(struct comedi_device *dev)
168 {
169         if (dev) {
170                 if (dev->class_dev) {
171                         device_destroy(comedi_class,
172                                        MKDEV(COMEDI_MAJOR, dev->minor));
173                 }
174                 comedi_device_cleanup(dev);
175                 comedi_dev_put(dev);
176         }
177 }
178
179 static struct comedi_subdevice
180 *comedi_subdevice_from_minor(unsigned minor)
181 {
182         struct comedi_subdevice *s;
183         unsigned int i = minor - COMEDI_NUM_BOARD_MINORS;
184
185         BUG_ON(i >= COMEDI_NUM_SUBDEVICE_MINORS);
186         mutex_lock(&comedi_subdevice_minor_table_lock);
187         s = comedi_subdevice_minor_table[i];
188         mutex_unlock(&comedi_subdevice_minor_table_lock);
189         return s;
190 }
191
192 static struct comedi_device *comedi_dev_from_board_minor(unsigned minor)
193 {
194         struct comedi_device *dev;
195
196         BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
197         mutex_lock(&comedi_board_minor_table_lock);
198         dev = comedi_board_minor_table[minor];
199         mutex_unlock(&comedi_board_minor_table_lock);
200         return dev;
201 }
202
203 static struct comedi_device *comedi_dev_from_subdevice_minor(unsigned minor)
204 {
205         struct comedi_subdevice *s;
206
207         s = comedi_subdevice_from_minor(minor);
208         return s ? s->device : NULL;
209 }
210
211 struct comedi_device *comedi_dev_from_minor(unsigned minor)
212 {
213         if (minor < COMEDI_NUM_BOARD_MINORS)
214                 return comedi_dev_from_board_minor(minor);
215         else
216                 return comedi_dev_from_subdevice_minor(minor);
217 }
218 EXPORT_SYMBOL_GPL(comedi_dev_from_minor);
219
220 static struct comedi_device *comedi_dev_get_from_board_minor(unsigned minor)
221 {
222         struct comedi_device *dev;
223
224         BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
225         mutex_lock(&comedi_board_minor_table_lock);
226         dev = comedi_dev_get(comedi_board_minor_table[minor]);
227         mutex_unlock(&comedi_board_minor_table_lock);
228         return dev;
229 }
230
231 static struct comedi_device *comedi_dev_get_from_subdevice_minor(unsigned minor)
232 {
233         struct comedi_device *dev;
234         struct comedi_subdevice *s;
235         unsigned int i = minor - COMEDI_NUM_BOARD_MINORS;
236
237         BUG_ON(i >= COMEDI_NUM_SUBDEVICE_MINORS);
238         mutex_lock(&comedi_subdevice_minor_table_lock);
239         s = comedi_subdevice_minor_table[i];
240         dev = comedi_dev_get(s ? s->device : NULL);
241         mutex_unlock(&comedi_subdevice_minor_table_lock);
242         return dev;
243 }
244
245 struct comedi_device *comedi_dev_get_from_minor(unsigned minor)
246 {
247         if (minor < COMEDI_NUM_BOARD_MINORS)
248                 return comedi_dev_get_from_board_minor(minor);
249         else
250                 return comedi_dev_get_from_subdevice_minor(minor);
251 }
252 EXPORT_SYMBOL_GPL(comedi_dev_get_from_minor);
253
254 static struct comedi_subdevice *
255 comedi_read_subdevice(const struct comedi_device *dev, unsigned int minor)
256 {
257         struct comedi_subdevice *s;
258
259         if (minor >= COMEDI_NUM_BOARD_MINORS) {
260                 s = comedi_subdevice_from_minor(minor);
261                 if (!s || s->device != dev)
262                         return NULL;
263                 if (s->subdev_flags & SDF_CMD_READ)
264                         return s;
265         }
266         return dev->read_subdev;
267 }
268
269 static struct comedi_subdevice *
270 comedi_write_subdevice(const struct comedi_device *dev, unsigned int minor)
271 {
272         struct comedi_subdevice *s;
273
274         if (minor >= COMEDI_NUM_BOARD_MINORS) {
275                 s = comedi_subdevice_from_minor(minor);
276                 if (!s || s->device != dev)
277                         return NULL;
278                 if (s->subdev_flags & SDF_CMD_WRITE)
279                         return s;
280         }
281         return dev->write_subdev;
282 }
283
284 static int resize_async_buffer(struct comedi_device *dev,
285                                struct comedi_subdevice *s,
286                                struct comedi_async *async, unsigned new_size)
287 {
288         int retval;
289
290         if (new_size > async->max_bufsize)
291                 return -EPERM;
292
293         if (s->busy) {
294                 DPRINTK("subdevice is busy, cannot resize buffer\n");
295                 return -EBUSY;
296         }
297         if (async->mmap_count) {
298                 DPRINTK("subdevice is mmapped, cannot resize buffer\n");
299                 return -EBUSY;
300         }
301
302         /* make sure buffer is an integral number of pages
303          * (we round up) */
304         new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
305
306         retval = comedi_buf_alloc(dev, s, new_size);
307         if (retval < 0)
308                 return retval;
309
310         if (s->buf_change) {
311                 retval = s->buf_change(dev, s, new_size);
312                 if (retval < 0)
313                         return retval;
314         }
315
316         DPRINTK("comedi%i subd %d buffer resized to %i bytes\n",
317                 dev->minor, s->index, async->prealloc_bufsz);
318         return 0;
319 }
320
321 /* sysfs attribute files */
322
323 static ssize_t max_read_buffer_kb_show(struct device *csdev,
324                                        struct device_attribute *attr, char *buf)
325 {
326         unsigned int minor = MINOR(csdev->devt);
327         struct comedi_device *dev;
328         struct comedi_subdevice *s;
329         unsigned int size = 0;
330
331         dev = comedi_dev_from_minor(minor);
332         if (!dev)
333                 return -ENODEV;
334
335         mutex_lock(&dev->mutex);
336         s = comedi_read_subdevice(dev, minor);
337         if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
338                 size = s->async->max_bufsize / 1024;
339         mutex_unlock(&dev->mutex);
340
341         return snprintf(buf, PAGE_SIZE, "%i\n", size);
342 }
343
344 static ssize_t max_read_buffer_kb_store(struct device *csdev,
345                                         struct device_attribute *attr,
346                                         const char *buf, size_t count)
347 {
348         unsigned int minor = MINOR(csdev->devt);
349         struct comedi_device *dev;
350         struct comedi_subdevice *s;
351         unsigned int size;
352         int err;
353
354         err = kstrtouint(buf, 10, &size);
355         if (err)
356                 return err;
357         if (size > (UINT_MAX / 1024))
358                 return -EINVAL;
359         size *= 1024;
360
361         dev = comedi_dev_from_minor(minor);
362         if (!dev)
363                 return -ENODEV;
364
365         mutex_lock(&dev->mutex);
366         s = comedi_read_subdevice(dev, minor);
367         if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
368                 s->async->max_bufsize = size;
369         else
370                 err = -EINVAL;
371         mutex_unlock(&dev->mutex);
372
373         return err ? err : count;
374 }
375 static DEVICE_ATTR_RW(max_read_buffer_kb);
376
377 static ssize_t read_buffer_kb_show(struct device *csdev,
378                                    struct device_attribute *attr, char *buf)
379 {
380         unsigned int minor = MINOR(csdev->devt);
381         struct comedi_device *dev;
382         struct comedi_subdevice *s;
383         unsigned int size = 0;
384
385         dev = comedi_dev_from_minor(minor);
386         if (!dev)
387                 return -ENODEV;
388
389         mutex_lock(&dev->mutex);
390         s = comedi_read_subdevice(dev, minor);
391         if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
392                 size = s->async->prealloc_bufsz / 1024;
393         mutex_unlock(&dev->mutex);
394
395         return snprintf(buf, PAGE_SIZE, "%i\n", size);
396 }
397
398 static ssize_t read_buffer_kb_store(struct device *csdev,
399                                     struct device_attribute *attr,
400                                     const char *buf, size_t count)
401 {
402         unsigned int minor = MINOR(csdev->devt);
403         struct comedi_device *dev;
404         struct comedi_subdevice *s;
405         unsigned int size;
406         int err;
407
408         err = kstrtouint(buf, 10, &size);
409         if (err)
410                 return err;
411         if (size > (UINT_MAX / 1024))
412                 return -EINVAL;
413         size *= 1024;
414
415         dev = comedi_dev_from_minor(minor);
416         if (!dev)
417                 return -ENODEV;
418
419         mutex_lock(&dev->mutex);
420         s = comedi_read_subdevice(dev, minor);
421         if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
422                 err = resize_async_buffer(dev, s, s->async, size);
423         else
424                 err = -EINVAL;
425         mutex_unlock(&dev->mutex);
426
427         return err ? err : count;
428 }
429 static DEVICE_ATTR_RW(read_buffer_kb);
430
431 static ssize_t max_write_buffer_kb_show(struct device *csdev,
432                                         struct device_attribute *attr,
433                                         char *buf)
434 {
435         unsigned int minor = MINOR(csdev->devt);
436         struct comedi_device *dev;
437         struct comedi_subdevice *s;
438         unsigned int size = 0;
439
440         dev = comedi_dev_from_minor(minor);
441         if (!dev)
442                 return -ENODEV;
443
444         mutex_lock(&dev->mutex);
445         s = comedi_write_subdevice(dev, minor);
446         if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
447                 size = s->async->max_bufsize / 1024;
448         mutex_unlock(&dev->mutex);
449
450         return snprintf(buf, PAGE_SIZE, "%i\n", size);
451 }
452
453 static ssize_t max_write_buffer_kb_store(struct device *csdev,
454                                          struct device_attribute *attr,
455                                          const char *buf, size_t count)
456 {
457         unsigned int minor = MINOR(csdev->devt);
458         struct comedi_device *dev;
459         struct comedi_subdevice *s;
460         unsigned int size;
461         int err;
462
463         err = kstrtouint(buf, 10, &size);
464         if (err)
465                 return err;
466         if (size > (UINT_MAX / 1024))
467                 return -EINVAL;
468         size *= 1024;
469
470         dev = comedi_dev_from_minor(minor);
471         if (!dev)
472                 return -ENODEV;
473
474         mutex_lock(&dev->mutex);
475         s = comedi_write_subdevice(dev, minor);
476         if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
477                 s->async->max_bufsize = size;
478         else
479                 err = -EINVAL;
480         mutex_unlock(&dev->mutex);
481
482         return err ? err : count;
483 }
484 static DEVICE_ATTR_RW(max_write_buffer_kb);
485
486 static ssize_t write_buffer_kb_show(struct device *csdev,
487                                     struct device_attribute *attr, char *buf)
488 {
489         unsigned int minor = MINOR(csdev->devt);
490         struct comedi_device *dev;
491         struct comedi_subdevice *s;
492         unsigned int size = 0;
493
494         dev = comedi_dev_from_minor(minor);
495         if (!dev)
496                 return -ENODEV;
497
498         mutex_lock(&dev->mutex);
499         s = comedi_write_subdevice(dev, minor);
500         if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
501                 size = s->async->prealloc_bufsz / 1024;
502         mutex_unlock(&dev->mutex);
503
504         return snprintf(buf, PAGE_SIZE, "%i\n", size);
505 }
506
507 static ssize_t write_buffer_kb_store(struct device *csdev,
508                                      struct device_attribute *attr,
509                                      const char *buf, size_t count)
510 {
511         unsigned int minor = MINOR(csdev->devt);
512         struct comedi_device *dev;
513         struct comedi_subdevice *s;
514         unsigned int size;
515         int err;
516
517         err = kstrtouint(buf, 10, &size);
518         if (err)
519                 return err;
520         if (size > (UINT_MAX / 1024))
521                 return -EINVAL;
522         size *= 1024;
523
524         dev = comedi_dev_from_minor(minor);
525         if (!dev)
526                 return -ENODEV;
527
528         mutex_lock(&dev->mutex);
529         s = comedi_write_subdevice(dev, minor);
530         if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
531                 err = resize_async_buffer(dev, s, s->async, size);
532         else
533                 err = -EINVAL;
534         mutex_unlock(&dev->mutex);
535
536         return err ? err : count;
537 }
538 static DEVICE_ATTR_RW(write_buffer_kb);
539
540 static struct attribute *comedi_dev_attrs[] = {
541         &dev_attr_max_read_buffer_kb.attr,
542         &dev_attr_read_buffer_kb.attr,
543         &dev_attr_max_write_buffer_kb.attr,
544         &dev_attr_write_buffer_kb.attr,
545         NULL,
546 };
547 ATTRIBUTE_GROUPS(comedi_dev);
548
549 static void comedi_set_subdevice_runflags(struct comedi_subdevice *s,
550                                           unsigned mask, unsigned bits)
551 {
552         unsigned long flags;
553
554         spin_lock_irqsave(&s->spin_lock, flags);
555         s->runflags &= ~mask;
556         s->runflags |= (bits & mask);
557         spin_unlock_irqrestore(&s->spin_lock, flags);
558 }
559
560 static unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s)
561 {
562         unsigned long flags;
563         unsigned runflags;
564
565         spin_lock_irqsave(&s->spin_lock, flags);
566         runflags = s->runflags;
567         spin_unlock_irqrestore(&s->spin_lock, flags);
568         return runflags;
569 }
570
571 bool comedi_is_subdevice_running(struct comedi_subdevice *s)
572 {
573         unsigned runflags = comedi_get_subdevice_runflags(s);
574
575         return (runflags & SRF_RUNNING) ? true : false;
576 }
577 EXPORT_SYMBOL_GPL(comedi_is_subdevice_running);
578
579 static bool comedi_is_subdevice_in_error(struct comedi_subdevice *s)
580 {
581         unsigned runflags = comedi_get_subdevice_runflags(s);
582
583         return (runflags & SRF_ERROR) ? true : false;
584 }
585
586 static bool comedi_is_subdevice_idle(struct comedi_subdevice *s)
587 {
588         unsigned runflags = comedi_get_subdevice_runflags(s);
589
590         return (runflags & (SRF_ERROR | SRF_RUNNING)) ? false : true;
591 }
592
593 /**
594  * comedi_alloc_spriv() - Allocate memory for the subdevice private data.
595  * @s: comedi_subdevice struct
596  * @size: size of the memory to allocate
597  *
598  * This also sets the subdevice runflags to allow the core to automatically
599  * free the private data during the detach.
600  */
601 void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size)
602 {
603         s->private = kzalloc(size, GFP_KERNEL);
604         if (s->private)
605                 s->runflags |= SRF_FREE_SPRIV;
606         return s->private;
607 }
608 EXPORT_SYMBOL_GPL(comedi_alloc_spriv);
609
610 /*
611    This function restores a subdevice to an idle state.
612  */
613 static void do_become_nonbusy(struct comedi_device *dev,
614                               struct comedi_subdevice *s)
615 {
616         struct comedi_async *async = s->async;
617
618         comedi_set_subdevice_runflags(s, SRF_RUNNING, 0);
619         if (async) {
620                 comedi_buf_reset(async);
621                 async->inttrig = NULL;
622                 kfree(async->cmd.chanlist);
623                 async->cmd.chanlist = NULL;
624                 s->busy = NULL;
625                 wake_up_interruptible_all(&s->async->wait_head);
626         } else {
627                 dev_err(dev->class_dev,
628                         "BUG: (?) do_become_nonbusy called with async=NULL\n");
629                 s->busy = NULL;
630         }
631 }
632
633 static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
634 {
635         int ret = 0;
636
637         if (comedi_is_subdevice_running(s) && s->cancel)
638                 ret = s->cancel(dev, s);
639
640         do_become_nonbusy(dev, s);
641
642         return ret;
643 }
644
645 void comedi_device_cancel_all(struct comedi_device *dev)
646 {
647         struct comedi_subdevice *s;
648         int i;
649
650         if (!dev->attached)
651                 return;
652
653         for (i = 0; i < dev->n_subdevices; i++) {
654                 s = &dev->subdevices[i];
655                 if (s->async)
656                         do_cancel(dev, s);
657         }
658 }
659
660 static int is_device_busy(struct comedi_device *dev)
661 {
662         struct comedi_subdevice *s;
663         int i;
664
665         if (!dev->attached)
666                 return 0;
667
668         for (i = 0; i < dev->n_subdevices; i++) {
669                 s = &dev->subdevices[i];
670                 if (s->busy)
671                         return 1;
672                 if (s->async && s->async->mmap_count)
673                         return 1;
674         }
675
676         return 0;
677 }
678
679 /*
680         COMEDI_DEVCONFIG
681         device config ioctl
682
683         arg:
684                 pointer to devconfig structure
685
686         reads:
687                 devconfig structure at arg
688
689         writes:
690                 none
691 */
692 static int do_devconfig_ioctl(struct comedi_device *dev,
693                               struct comedi_devconfig __user *arg)
694 {
695         struct comedi_devconfig it;
696
697         if (!capable(CAP_SYS_ADMIN))
698                 return -EPERM;
699
700         if (arg == NULL) {
701                 if (is_device_busy(dev))
702                         return -EBUSY;
703                 if (dev->attached) {
704                         struct module *driver_module = dev->driver->module;
705                         comedi_device_detach(dev);
706                         module_put(driver_module);
707                 }
708                 return 0;
709         }
710
711         if (copy_from_user(&it, arg, sizeof(it)))
712                 return -EFAULT;
713
714         it.board_name[COMEDI_NAMELEN - 1] = 0;
715
716         if (it.options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) {
717                 dev_warn(dev->class_dev,
718                          "comedi_config --init_data is deprecated\n");
719                 return -EINVAL;
720         }
721
722         if (dev->minor >= comedi_num_legacy_minors)
723                 /* don't re-use dynamically allocated comedi devices */
724                 return -EBUSY;
725
726         /* This increments the driver module count on success. */
727         return comedi_device_attach(dev, &it);
728 }
729
730 /*
731         COMEDI_BUFCONFIG
732         buffer configuration ioctl
733
734         arg:
735                 pointer to bufconfig structure
736
737         reads:
738                 bufconfig at arg
739
740         writes:
741                 modified bufconfig at arg
742
743 */
744 static int do_bufconfig_ioctl(struct comedi_device *dev,
745                               struct comedi_bufconfig __user *arg)
746 {
747         struct comedi_bufconfig bc;
748         struct comedi_async *async;
749         struct comedi_subdevice *s;
750         int retval = 0;
751
752         if (copy_from_user(&bc, arg, sizeof(bc)))
753                 return -EFAULT;
754
755         if (bc.subdevice >= dev->n_subdevices)
756                 return -EINVAL;
757
758         s = &dev->subdevices[bc.subdevice];
759         async = s->async;
760
761         if (!async) {
762                 DPRINTK("subdevice does not have async capability\n");
763                 bc.size = 0;
764                 bc.maximum_size = 0;
765                 goto copyback;
766         }
767
768         if (bc.maximum_size) {
769                 if (!capable(CAP_SYS_ADMIN))
770                         return -EPERM;
771
772                 async->max_bufsize = bc.maximum_size;
773         }
774
775         if (bc.size) {
776                 retval = resize_async_buffer(dev, s, async, bc.size);
777                 if (retval < 0)
778                         return retval;
779         }
780
781         bc.size = async->prealloc_bufsz;
782         bc.maximum_size = async->max_bufsize;
783
784 copyback:
785         if (copy_to_user(arg, &bc, sizeof(bc)))
786                 return -EFAULT;
787
788         return 0;
789 }
790
791 /*
792         COMEDI_DEVINFO
793         device info ioctl
794
795         arg:
796                 pointer to devinfo structure
797
798         reads:
799                 none
800
801         writes:
802                 devinfo structure
803
804 */
805 static int do_devinfo_ioctl(struct comedi_device *dev,
806                             struct comedi_devinfo __user *arg,
807                             struct file *file)
808 {
809         const unsigned minor = iminor(file_inode(file));
810         struct comedi_subdevice *s;
811         struct comedi_devinfo devinfo;
812
813         memset(&devinfo, 0, sizeof(devinfo));
814
815         /* fill devinfo structure */
816         devinfo.version_code = COMEDI_VERSION_CODE;
817         devinfo.n_subdevs = dev->n_subdevices;
818         strlcpy(devinfo.driver_name, dev->driver->driver_name, COMEDI_NAMELEN);
819         strlcpy(devinfo.board_name, dev->board_name, COMEDI_NAMELEN);
820
821         s = comedi_read_subdevice(dev, minor);
822         if (s)
823                 devinfo.read_subdevice = s->index;
824         else
825                 devinfo.read_subdevice = -1;
826
827         s = comedi_write_subdevice(dev, minor);
828         if (s)
829                 devinfo.write_subdevice = s->index;
830         else
831                 devinfo.write_subdevice = -1;
832
833         if (copy_to_user(arg, &devinfo, sizeof(devinfo)))
834                 return -EFAULT;
835
836         return 0;
837 }
838
839 /*
840         COMEDI_SUBDINFO
841         subdevice info ioctl
842
843         arg:
844                 pointer to array of subdevice info structures
845
846         reads:
847                 none
848
849         writes:
850                 array of subdevice info structures at arg
851
852 */
853 static int do_subdinfo_ioctl(struct comedi_device *dev,
854                              struct comedi_subdinfo __user *arg, void *file)
855 {
856         int ret, i;
857         struct comedi_subdinfo *tmp, *us;
858         struct comedi_subdevice *s;
859
860         tmp = kcalloc(dev->n_subdevices, sizeof(*tmp), GFP_KERNEL);
861         if (!tmp)
862                 return -ENOMEM;
863
864         /* fill subdinfo structs */
865         for (i = 0; i < dev->n_subdevices; i++) {
866                 s = &dev->subdevices[i];
867                 us = tmp + i;
868
869                 us->type = s->type;
870                 us->n_chan = s->n_chan;
871                 us->subd_flags = s->subdev_flags;
872                 if (comedi_is_subdevice_running(s))
873                         us->subd_flags |= SDF_RUNNING;
874 #define TIMER_nanosec 5         /* backwards compatibility */
875                 us->timer_type = TIMER_nanosec;
876                 us->len_chanlist = s->len_chanlist;
877                 us->maxdata = s->maxdata;
878                 if (s->range_table) {
879                         us->range_type =
880                             (i << 24) | (0 << 16) | (s->range_table->length);
881                 } else {
882                         us->range_type = 0;     /* XXX */
883                 }
884
885                 if (s->busy)
886                         us->subd_flags |= SDF_BUSY;
887                 if (s->busy == file)
888                         us->subd_flags |= SDF_BUSY_OWNER;
889                 if (s->lock)
890                         us->subd_flags |= SDF_LOCKED;
891                 if (s->lock == file)
892                         us->subd_flags |= SDF_LOCK_OWNER;
893                 if (!s->maxdata && s->maxdata_list)
894                         us->subd_flags |= SDF_MAXDATA;
895                 if (s->range_table_list)
896                         us->subd_flags |= SDF_RANGETYPE;
897                 if (s->do_cmd)
898                         us->subd_flags |= SDF_CMD;
899
900                 if (s->insn_bits != &insn_inval)
901                         us->insn_bits_support = COMEDI_SUPPORTED;
902                 else
903                         us->insn_bits_support = COMEDI_UNSUPPORTED;
904         }
905
906         ret = copy_to_user(arg, tmp, dev->n_subdevices * sizeof(*tmp));
907
908         kfree(tmp);
909
910         return ret ? -EFAULT : 0;
911 }
912
913 /*
914         COMEDI_CHANINFO
915         subdevice info ioctl
916
917         arg:
918                 pointer to chaninfo structure
919
920         reads:
921                 chaninfo structure at arg
922
923         writes:
924                 arrays at elements of chaninfo structure
925
926 */
927 static int do_chaninfo_ioctl(struct comedi_device *dev,
928                              struct comedi_chaninfo __user *arg)
929 {
930         struct comedi_subdevice *s;
931         struct comedi_chaninfo it;
932
933         if (copy_from_user(&it, arg, sizeof(it)))
934                 return -EFAULT;
935
936         if (it.subdev >= dev->n_subdevices)
937                 return -EINVAL;
938         s = &dev->subdevices[it.subdev];
939
940         if (it.maxdata_list) {
941                 if (s->maxdata || !s->maxdata_list)
942                         return -EINVAL;
943                 if (copy_to_user(it.maxdata_list, s->maxdata_list,
944                                  s->n_chan * sizeof(unsigned int)))
945                         return -EFAULT;
946         }
947
948         if (it.flaglist)
949                 return -EINVAL; /* flaglist not supported */
950
951         if (it.rangelist) {
952                 int i;
953
954                 if (!s->range_table_list)
955                         return -EINVAL;
956                 for (i = 0; i < s->n_chan; i++) {
957                         int x;
958
959                         x = (dev->minor << 28) | (it.subdev << 24) | (i << 16) |
960                             (s->range_table_list[i]->length);
961                         if (put_user(x, it.rangelist + i))
962                                 return -EFAULT;
963                 }
964 #if 0
965                 if (copy_to_user(it.rangelist, s->range_type_list,
966                                  s->n_chan * sizeof(unsigned int)))
967                         return -EFAULT;
968 #endif
969         }
970
971         return 0;
972 }
973
974  /*
975     COMEDI_BUFINFO
976     buffer information ioctl
977
978     arg:
979     pointer to bufinfo structure
980
981     reads:
982     bufinfo at arg
983
984     writes:
985     modified bufinfo at arg
986
987   */
988 static int do_bufinfo_ioctl(struct comedi_device *dev,
989                             struct comedi_bufinfo __user *arg, void *file)
990 {
991         struct comedi_bufinfo bi;
992         struct comedi_subdevice *s;
993         struct comedi_async *async;
994
995         if (copy_from_user(&bi, arg, sizeof(bi)))
996                 return -EFAULT;
997
998         if (bi.subdevice >= dev->n_subdevices)
999                 return -EINVAL;
1000
1001         s = &dev->subdevices[bi.subdevice];
1002
1003         if (s->lock && s->lock != file)
1004                 return -EACCES;
1005
1006         async = s->async;
1007
1008         if (!async) {
1009                 DPRINTK("subdevice does not have async capability\n");
1010                 bi.buf_write_ptr = 0;
1011                 bi.buf_read_ptr = 0;
1012                 bi.buf_write_count = 0;
1013                 bi.buf_read_count = 0;
1014                 bi.bytes_read = 0;
1015                 bi.bytes_written = 0;
1016                 goto copyback;
1017         }
1018         if (!s->busy) {
1019                 bi.bytes_read = 0;
1020                 bi.bytes_written = 0;
1021                 goto copyback_position;
1022         }
1023         if (s->busy != file)
1024                 return -EACCES;
1025
1026         if (bi.bytes_read && (s->subdev_flags & SDF_CMD_READ)) {
1027                 bi.bytes_read = comedi_buf_read_alloc(async, bi.bytes_read);
1028                 comedi_buf_read_free(async, bi.bytes_read);
1029
1030                 if (comedi_is_subdevice_idle(s) &&
1031                     async->buf_write_count == async->buf_read_count) {
1032                         do_become_nonbusy(dev, s);
1033                 }
1034         }
1035
1036         if (bi.bytes_written && (s->subdev_flags & SDF_CMD_WRITE)) {
1037                 bi.bytes_written =
1038                     comedi_buf_write_alloc(async, bi.bytes_written);
1039                 comedi_buf_write_free(async, bi.bytes_written);
1040         }
1041
1042 copyback_position:
1043         bi.buf_write_count = async->buf_write_count;
1044         bi.buf_write_ptr = async->buf_write_ptr;
1045         bi.buf_read_count = async->buf_read_count;
1046         bi.buf_read_ptr = async->buf_read_ptr;
1047
1048 copyback:
1049         if (copy_to_user(arg, &bi, sizeof(bi)))
1050                 return -EFAULT;
1051
1052         return 0;
1053 }
1054
1055 static int check_insn_config_length(struct comedi_insn *insn,
1056                                     unsigned int *data)
1057 {
1058         if (insn->n < 1)
1059                 return -EINVAL;
1060
1061         switch (data[0]) {
1062         case INSN_CONFIG_DIO_OUTPUT:
1063         case INSN_CONFIG_DIO_INPUT:
1064         case INSN_CONFIG_DISARM:
1065         case INSN_CONFIG_RESET:
1066                 if (insn->n == 1)
1067                         return 0;
1068                 break;
1069         case INSN_CONFIG_ARM:
1070         case INSN_CONFIG_DIO_QUERY:
1071         case INSN_CONFIG_BLOCK_SIZE:
1072         case INSN_CONFIG_FILTER:
1073         case INSN_CONFIG_SERIAL_CLOCK:
1074         case INSN_CONFIG_BIDIRECTIONAL_DATA:
1075         case INSN_CONFIG_ALT_SOURCE:
1076         case INSN_CONFIG_SET_COUNTER_MODE:
1077         case INSN_CONFIG_8254_READ_STATUS:
1078         case INSN_CONFIG_SET_ROUTING:
1079         case INSN_CONFIG_GET_ROUTING:
1080         case INSN_CONFIG_GET_PWM_STATUS:
1081         case INSN_CONFIG_PWM_SET_PERIOD:
1082         case INSN_CONFIG_PWM_GET_PERIOD:
1083                 if (insn->n == 2)
1084                         return 0;
1085                 break;
1086         case INSN_CONFIG_SET_GATE_SRC:
1087         case INSN_CONFIG_GET_GATE_SRC:
1088         case INSN_CONFIG_SET_CLOCK_SRC:
1089         case INSN_CONFIG_GET_CLOCK_SRC:
1090         case INSN_CONFIG_SET_OTHER_SRC:
1091         case INSN_CONFIG_GET_COUNTER_STATUS:
1092         case INSN_CONFIG_PWM_SET_H_BRIDGE:
1093         case INSN_CONFIG_PWM_GET_H_BRIDGE:
1094         case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE:
1095                 if (insn->n == 3)
1096                         return 0;
1097                 break;
1098         case INSN_CONFIG_PWM_OUTPUT:
1099         case INSN_CONFIG_ANALOG_TRIG:
1100                 if (insn->n == 5)
1101                         return 0;
1102                 break;
1103         case INSN_CONFIG_DIGITAL_TRIG:
1104                 if (insn->n == 6)
1105                         return 0;
1106                 break;
1107                 /* by default we allow the insn since we don't have checks for
1108                  * all possible cases yet */
1109         default:
1110                 pr_warn("comedi: No check for data length of config insn id %i is implemented.\n",
1111                         data[0]);
1112                 pr_warn("comedi: Add a check to %s in %s.\n",
1113                         __func__, __FILE__);
1114                 pr_warn("comedi: Assuming n=%i is correct.\n", insn->n);
1115                 return 0;
1116         }
1117         return -EINVAL;
1118 }
1119
1120 static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn,
1121                       unsigned int *data, void *file)
1122 {
1123         struct comedi_subdevice *s;
1124         int ret = 0;
1125         int i;
1126
1127         if (insn->insn & INSN_MASK_SPECIAL) {
1128                 /* a non-subdevice instruction */
1129
1130                 switch (insn->insn) {
1131                 case INSN_GTOD:
1132                         {
1133                                 struct timeval tv;
1134
1135                                 if (insn->n != 2) {
1136                                         ret = -EINVAL;
1137                                         break;
1138                                 }
1139
1140                                 do_gettimeofday(&tv);
1141                                 data[0] = tv.tv_sec;
1142                                 data[1] = tv.tv_usec;
1143                                 ret = 2;
1144
1145                                 break;
1146                         }
1147                 case INSN_WAIT:
1148                         if (insn->n != 1 || data[0] >= 100000) {
1149                                 ret = -EINVAL;
1150                                 break;
1151                         }
1152                         udelay(data[0] / 1000);
1153                         ret = 1;
1154                         break;
1155                 case INSN_INTTRIG:
1156                         if (insn->n != 1) {
1157                                 ret = -EINVAL;
1158                                 break;
1159                         }
1160                         if (insn->subdev >= dev->n_subdevices) {
1161                                 DPRINTK("%d not usable subdevice\n",
1162                                         insn->subdev);
1163                                 ret = -EINVAL;
1164                                 break;
1165                         }
1166                         s = &dev->subdevices[insn->subdev];
1167                         if (!s->async) {
1168                                 DPRINTK("no async\n");
1169                                 ret = -EINVAL;
1170                                 break;
1171                         }
1172                         if (!s->async->inttrig) {
1173                                 DPRINTK("no inttrig\n");
1174                                 ret = -EAGAIN;
1175                                 break;
1176                         }
1177                         ret = s->async->inttrig(dev, s, data[0]);
1178                         if (ret >= 0)
1179                                 ret = 1;
1180                         break;
1181                 default:
1182                         DPRINTK("invalid insn\n");
1183                         ret = -EINVAL;
1184                         break;
1185                 }
1186         } else {
1187                 /* a subdevice instruction */
1188                 unsigned int maxdata;
1189
1190                 if (insn->subdev >= dev->n_subdevices) {
1191                         DPRINTK("subdevice %d out of range\n", insn->subdev);
1192                         ret = -EINVAL;
1193                         goto out;
1194                 }
1195                 s = &dev->subdevices[insn->subdev];
1196
1197                 if (s->type == COMEDI_SUBD_UNUSED) {
1198                         DPRINTK("%d not usable subdevice\n", insn->subdev);
1199                         ret = -EIO;
1200                         goto out;
1201                 }
1202
1203                 /* are we locked? (ioctl lock) */
1204                 if (s->lock && s->lock != file) {
1205                         DPRINTK("device locked\n");
1206                         ret = -EACCES;
1207                         goto out;
1208                 }
1209
1210                 ret = comedi_check_chanlist(s, 1, &insn->chanspec);
1211                 if (ret < 0) {
1212                         ret = -EINVAL;
1213                         DPRINTK("bad chanspec\n");
1214                         goto out;
1215                 }
1216
1217                 if (s->busy) {
1218                         ret = -EBUSY;
1219                         goto out;
1220                 }
1221                 /* This looks arbitrary.  It is. */
1222                 s->busy = &parse_insn;
1223                 switch (insn->insn) {
1224                 case INSN_READ:
1225                         ret = s->insn_read(dev, s, insn, data);
1226                         break;
1227                 case INSN_WRITE:
1228                         maxdata = s->maxdata_list
1229                             ? s->maxdata_list[CR_CHAN(insn->chanspec)]
1230                             : s->maxdata;
1231                         for (i = 0; i < insn->n; ++i) {
1232                                 if (data[i] > maxdata) {
1233                                         ret = -EINVAL;
1234                                         DPRINTK("bad data value(s)\n");
1235                                         break;
1236                                 }
1237                         }
1238                         if (ret == 0)
1239                                 ret = s->insn_write(dev, s, insn, data);
1240                         break;
1241                 case INSN_BITS:
1242                         if (insn->n != 2) {
1243                                 ret = -EINVAL;
1244                         } else {
1245                                 /* Most drivers ignore the base channel in
1246                                  * insn->chanspec.  Fix this here if
1247                                  * the subdevice has <= 32 channels.  */
1248                                 unsigned int shift;
1249                                 unsigned int orig_mask;
1250
1251                                 orig_mask = data[0];
1252                                 if (s->n_chan <= 32) {
1253                                         shift = CR_CHAN(insn->chanspec);
1254                                         if (shift > 0) {
1255                                                 insn->chanspec = 0;
1256                                                 data[0] <<= shift;
1257                                                 data[1] <<= shift;
1258                                         }
1259                                 } else
1260                                         shift = 0;
1261                                 ret = s->insn_bits(dev, s, insn, data);
1262                                 data[0] = orig_mask;
1263                                 if (shift > 0)
1264                                         data[1] >>= shift;
1265                         }
1266                         break;
1267                 case INSN_CONFIG:
1268                         ret = check_insn_config_length(insn, data);
1269                         if (ret)
1270                                 break;
1271                         ret = s->insn_config(dev, s, insn, data);
1272                         break;
1273                 default:
1274                         ret = -EINVAL;
1275                         break;
1276                 }
1277
1278                 s->busy = NULL;
1279         }
1280
1281 out:
1282         return ret;
1283 }
1284
1285 /*
1286  *      COMEDI_INSNLIST
1287  *      synchronous instructions
1288  *
1289  *      arg:
1290  *              pointer to sync cmd structure
1291  *
1292  *      reads:
1293  *              sync cmd struct at arg
1294  *              instruction list
1295  *              data (for writes)
1296  *
1297  *      writes:
1298  *              data (for reads)
1299  */
1300 /* arbitrary limits */
1301 #define MAX_SAMPLES 256
1302 static int do_insnlist_ioctl(struct comedi_device *dev,
1303                              struct comedi_insnlist __user *arg, void *file)
1304 {
1305         struct comedi_insnlist insnlist;
1306         struct comedi_insn *insns = NULL;
1307         unsigned int *data = NULL;
1308         int i = 0;
1309         int ret = 0;
1310
1311         if (copy_from_user(&insnlist, arg, sizeof(insnlist)))
1312                 return -EFAULT;
1313
1314         data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL);
1315         if (!data) {
1316                 DPRINTK("kmalloc failed\n");
1317                 ret = -ENOMEM;
1318                 goto error;
1319         }
1320
1321         insns = kcalloc(insnlist.n_insns, sizeof(*insns), GFP_KERNEL);
1322         if (!insns) {
1323                 DPRINTK("kmalloc failed\n");
1324                 ret = -ENOMEM;
1325                 goto error;
1326         }
1327
1328         if (copy_from_user(insns, insnlist.insns,
1329                            sizeof(*insns) * insnlist.n_insns)) {
1330                 DPRINTK("copy_from_user failed\n");
1331                 ret = -EFAULT;
1332                 goto error;
1333         }
1334
1335         for (i = 0; i < insnlist.n_insns; i++) {
1336                 if (insns[i].n > MAX_SAMPLES) {
1337                         DPRINTK("number of samples too large\n");
1338                         ret = -EINVAL;
1339                         goto error;
1340                 }
1341                 if (insns[i].insn & INSN_MASK_WRITE) {
1342                         if (copy_from_user(data, insns[i].data,
1343                                            insns[i].n * sizeof(unsigned int))) {
1344                                 DPRINTK("copy_from_user failed\n");
1345                                 ret = -EFAULT;
1346                                 goto error;
1347                         }
1348                 }
1349                 ret = parse_insn(dev, insns + i, data, file);
1350                 if (ret < 0)
1351                         goto error;
1352                 if (insns[i].insn & INSN_MASK_READ) {
1353                         if (copy_to_user(insns[i].data, data,
1354                                          insns[i].n * sizeof(unsigned int))) {
1355                                 DPRINTK("copy_to_user failed\n");
1356                                 ret = -EFAULT;
1357                                 goto error;
1358                         }
1359                 }
1360                 if (need_resched())
1361                         schedule();
1362         }
1363
1364 error:
1365         kfree(insns);
1366         kfree(data);
1367
1368         if (ret < 0)
1369                 return ret;
1370         return i;
1371 }
1372
1373 /*
1374  *      COMEDI_INSN
1375  *      synchronous instructions
1376  *
1377  *      arg:
1378  *              pointer to insn
1379  *
1380  *      reads:
1381  *              struct comedi_insn struct at arg
1382  *              data (for writes)
1383  *
1384  *      writes:
1385  *              data (for reads)
1386  */
1387 static int do_insn_ioctl(struct comedi_device *dev,
1388                          struct comedi_insn __user *arg, void *file)
1389 {
1390         struct comedi_insn insn;
1391         unsigned int *data = NULL;
1392         int ret = 0;
1393
1394         data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL);
1395         if (!data) {
1396                 ret = -ENOMEM;
1397                 goto error;
1398         }
1399
1400         if (copy_from_user(&insn, arg, sizeof(insn))) {
1401                 ret = -EFAULT;
1402                 goto error;
1403         }
1404
1405         /* This is where the behavior of insn and insnlist deviate. */
1406         if (insn.n > MAX_SAMPLES)
1407                 insn.n = MAX_SAMPLES;
1408         if (insn.insn & INSN_MASK_WRITE) {
1409                 if (copy_from_user(data,
1410                                    insn.data,
1411                                    insn.n * sizeof(unsigned int))) {
1412                         ret = -EFAULT;
1413                         goto error;
1414                 }
1415         }
1416         ret = parse_insn(dev, &insn, data, file);
1417         if (ret < 0)
1418                 goto error;
1419         if (insn.insn & INSN_MASK_READ) {
1420                 if (copy_to_user(insn.data,
1421                                  data,
1422                                  insn.n * sizeof(unsigned int))) {
1423                         ret = -EFAULT;
1424                         goto error;
1425                 }
1426         }
1427         ret = insn.n;
1428
1429 error:
1430         kfree(data);
1431
1432         return ret;
1433 }
1434
1435 static int do_cmd_ioctl(struct comedi_device *dev,
1436                         struct comedi_cmd __user *arg, void *file)
1437 {
1438         struct comedi_cmd cmd;
1439         struct comedi_subdevice *s;
1440         struct comedi_async *async;
1441         int ret = 0;
1442         unsigned int __user *user_chanlist;
1443
1444         if (copy_from_user(&cmd, arg, sizeof(cmd))) {
1445                 DPRINTK("bad cmd address\n");
1446                 return -EFAULT;
1447         }
1448         /* save user's chanlist pointer so it can be restored later */
1449         user_chanlist = (unsigned int __user *)cmd.chanlist;
1450
1451         if (cmd.subdev >= dev->n_subdevices) {
1452                 DPRINTK("%d no such subdevice\n", cmd.subdev);
1453                 return -ENODEV;
1454         }
1455
1456         s = &dev->subdevices[cmd.subdev];
1457         async = s->async;
1458
1459         if (s->type == COMEDI_SUBD_UNUSED) {
1460                 DPRINTK("%d not valid subdevice\n", cmd.subdev);
1461                 return -EIO;
1462         }
1463
1464         if (!s->do_cmd || !s->do_cmdtest || !s->async) {
1465                 DPRINTK("subdevice %i does not support commands\n",
1466                         cmd.subdev);
1467                 return -EIO;
1468         }
1469
1470         /* are we locked? (ioctl lock) */
1471         if (s->lock && s->lock != file) {
1472                 DPRINTK("subdevice locked\n");
1473                 return -EACCES;
1474         }
1475
1476         /* are we busy? */
1477         if (s->busy) {
1478                 DPRINTK("subdevice busy\n");
1479                 return -EBUSY;
1480         }
1481
1482         /* make sure channel/gain list isn't too long */
1483         if (cmd.chanlist_len > s->len_chanlist) {
1484                 DPRINTK("channel/gain list too long %u > %d\n",
1485                         cmd.chanlist_len, s->len_chanlist);
1486                 return -EINVAL;
1487         }
1488
1489         /* make sure channel/gain list isn't too short */
1490         if (cmd.chanlist_len < 1) {
1491                 DPRINTK("channel/gain list too short %u < 1\n",
1492                         cmd.chanlist_len);
1493                 return -EINVAL;
1494         }
1495
1496         async->cmd = cmd;
1497         async->cmd.data = NULL;
1498         /* load channel/gain list */
1499         async->cmd.chanlist = memdup_user(user_chanlist,
1500                                           async->cmd.chanlist_len * sizeof(int));
1501         if (IS_ERR(async->cmd.chanlist)) {
1502                 ret = PTR_ERR(async->cmd.chanlist);
1503                 DPRINTK("memdup_user failed with code %d\n", ret);
1504                 goto cleanup;
1505         }
1506
1507         /* make sure each element in channel/gain list is valid */
1508         ret = comedi_check_chanlist(s,
1509                                     async->cmd.chanlist_len,
1510                                     async->cmd.chanlist);
1511         if (ret < 0) {
1512                 DPRINTK("bad chanlist\n");
1513                 goto cleanup;
1514         }
1515
1516         ret = s->do_cmdtest(dev, s, &async->cmd);
1517
1518         if (async->cmd.flags & TRIG_BOGUS || ret) {
1519                 DPRINTK("test returned %d\n", ret);
1520                 cmd = async->cmd;
1521                 /* restore chanlist pointer before copying back */
1522                 cmd.chanlist = (unsigned int __force *)user_chanlist;
1523                 cmd.data = NULL;
1524                 if (copy_to_user(arg, &cmd, sizeof(cmd))) {
1525                         DPRINTK("fault writing cmd\n");
1526                         ret = -EFAULT;
1527                         goto cleanup;
1528                 }
1529                 ret = -EAGAIN;
1530                 goto cleanup;
1531         }
1532
1533         if (!async->prealloc_bufsz) {
1534                 ret = -ENOMEM;
1535                 DPRINTK("no buffer (?)\n");
1536                 goto cleanup;
1537         }
1538
1539         comedi_buf_reset(async);
1540
1541         async->cb_mask =
1542             COMEDI_CB_EOA | COMEDI_CB_BLOCK | COMEDI_CB_ERROR |
1543             COMEDI_CB_OVERFLOW;
1544         if (async->cmd.flags & TRIG_WAKE_EOS)
1545                 async->cb_mask |= COMEDI_CB_EOS;
1546
1547         comedi_set_subdevice_runflags(s, SRF_ERROR | SRF_RUNNING, SRF_RUNNING);
1548
1549         /* set s->busy _after_ setting SRF_RUNNING flag to avoid race with
1550          * comedi_read() or comedi_write() */
1551         s->busy = file;
1552         ret = s->do_cmd(dev, s);
1553         if (ret == 0)
1554                 return 0;
1555
1556 cleanup:
1557         do_become_nonbusy(dev, s);
1558
1559         return ret;
1560 }
1561
1562 /*
1563         COMEDI_CMDTEST
1564         command testing ioctl
1565
1566         arg:
1567                 pointer to cmd structure
1568
1569         reads:
1570                 cmd structure at arg
1571                 channel/range list
1572
1573         writes:
1574                 modified cmd structure at arg
1575
1576 */
1577 static int do_cmdtest_ioctl(struct comedi_device *dev,
1578                             struct comedi_cmd __user *arg, void *file)
1579 {
1580         struct comedi_cmd cmd;
1581         struct comedi_subdevice *s;
1582         int ret = 0;
1583         unsigned int *chanlist = NULL;
1584         unsigned int __user *user_chanlist;
1585
1586         if (copy_from_user(&cmd, arg, sizeof(cmd))) {
1587                 DPRINTK("bad cmd address\n");
1588                 return -EFAULT;
1589         }
1590         /* save user's chanlist pointer so it can be restored later */
1591         user_chanlist = (unsigned int __user *)cmd.chanlist;
1592
1593         if (cmd.subdev >= dev->n_subdevices) {
1594                 DPRINTK("%d no such subdevice\n", cmd.subdev);
1595                 return -ENODEV;
1596         }
1597
1598         s = &dev->subdevices[cmd.subdev];
1599         if (s->type == COMEDI_SUBD_UNUSED) {
1600                 DPRINTK("%d not valid subdevice\n", cmd.subdev);
1601                 return -EIO;
1602         }
1603
1604         if (!s->do_cmd || !s->do_cmdtest) {
1605                 DPRINTK("subdevice %i does not support commands\n",
1606                         cmd.subdev);
1607                 return -EIO;
1608         }
1609
1610         /* make sure channel/gain list isn't too long */
1611         if (cmd.chanlist_len > s->len_chanlist) {
1612                 DPRINTK("channel/gain list too long %d > %d\n",
1613                         cmd.chanlist_len, s->len_chanlist);
1614                 ret = -EINVAL;
1615                 goto cleanup;
1616         }
1617
1618         /* load channel/gain list */
1619         if (cmd.chanlist) {
1620                 chanlist = memdup_user(user_chanlist,
1621                                        cmd.chanlist_len * sizeof(int));
1622                 if (IS_ERR(chanlist)) {
1623                         ret = PTR_ERR(chanlist);
1624                         DPRINTK("memdup_user exited with code %d", ret);
1625                         goto cleanup;
1626                 }
1627
1628                 /* make sure each element in channel/gain list is valid */
1629                 ret = comedi_check_chanlist(s, cmd.chanlist_len, chanlist);
1630                 if (ret < 0) {
1631                         DPRINTK("bad chanlist\n");
1632                         goto cleanup;
1633                 }
1634
1635                 cmd.chanlist = chanlist;
1636         }
1637
1638         ret = s->do_cmdtest(dev, s, &cmd);
1639
1640         /* restore chanlist pointer before copying back */
1641         cmd.chanlist = (unsigned int __force *)user_chanlist;
1642
1643         if (copy_to_user(arg, &cmd, sizeof(cmd))) {
1644                 DPRINTK("bad cmd address\n");
1645                 ret = -EFAULT;
1646                 goto cleanup;
1647         }
1648 cleanup:
1649         kfree(chanlist);
1650
1651         return ret;
1652 }
1653
1654 /*
1655         COMEDI_LOCK
1656         lock subdevice
1657
1658         arg:
1659                 subdevice number
1660
1661         reads:
1662                 none
1663
1664         writes:
1665                 none
1666
1667 */
1668
1669 static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg,
1670                          void *file)
1671 {
1672         int ret = 0;
1673         unsigned long flags;
1674         struct comedi_subdevice *s;
1675
1676         if (arg >= dev->n_subdevices)
1677                 return -EINVAL;
1678         s = &dev->subdevices[arg];
1679
1680         spin_lock_irqsave(&s->spin_lock, flags);
1681         if (s->busy || s->lock)
1682                 ret = -EBUSY;
1683         else
1684                 s->lock = file;
1685         spin_unlock_irqrestore(&s->spin_lock, flags);
1686
1687 #if 0
1688         if (ret < 0)
1689                 return ret;
1690
1691         if (s->lock_f)
1692                 ret = s->lock_f(dev, s);
1693 #endif
1694
1695         return ret;
1696 }
1697
1698 /*
1699         COMEDI_UNLOCK
1700         unlock subdevice
1701
1702         arg:
1703                 subdevice number
1704
1705         reads:
1706                 none
1707
1708         writes:
1709                 none
1710
1711         This function isn't protected by the semaphore, since
1712         we already own the lock.
1713 */
1714 static int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg,
1715                            void *file)
1716 {
1717         struct comedi_subdevice *s;
1718
1719         if (arg >= dev->n_subdevices)
1720                 return -EINVAL;
1721         s = &dev->subdevices[arg];
1722
1723         if (s->busy)
1724                 return -EBUSY;
1725
1726         if (s->lock && s->lock != file)
1727                 return -EACCES;
1728
1729         if (s->lock == file) {
1730 #if 0
1731                 if (s->unlock)
1732                         s->unlock(dev, s);
1733 #endif
1734
1735                 s->lock = NULL;
1736         }
1737
1738         return 0;
1739 }
1740
1741 /*
1742         COMEDI_CANCEL
1743         cancel acquisition ioctl
1744
1745         arg:
1746                 subdevice number
1747
1748         reads:
1749                 nothing
1750
1751         writes:
1752                 nothing
1753
1754 */
1755 static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg,
1756                            void *file)
1757 {
1758         struct comedi_subdevice *s;
1759         int ret;
1760
1761         if (arg >= dev->n_subdevices)
1762                 return -EINVAL;
1763         s = &dev->subdevices[arg];
1764         if (s->async == NULL)
1765                 return -EINVAL;
1766
1767         if (s->lock && s->lock != file)
1768                 return -EACCES;
1769
1770         if (!s->busy)
1771                 return 0;
1772
1773         if (s->busy != file)
1774                 return -EBUSY;
1775
1776         ret = do_cancel(dev, s);
1777
1778         return ret;
1779 }
1780
1781 /*
1782         COMEDI_POLL ioctl
1783         instructs driver to synchronize buffers
1784
1785         arg:
1786                 subdevice number
1787
1788         reads:
1789                 nothing
1790
1791         writes:
1792                 nothing
1793
1794 */
1795 static int do_poll_ioctl(struct comedi_device *dev, unsigned int arg,
1796                          void *file)
1797 {
1798         struct comedi_subdevice *s;
1799
1800         if (arg >= dev->n_subdevices)
1801                 return -EINVAL;
1802         s = &dev->subdevices[arg];
1803
1804         if (s->lock && s->lock != file)
1805                 return -EACCES;
1806
1807         if (!s->busy)
1808                 return 0;
1809
1810         if (s->busy != file)
1811                 return -EBUSY;
1812
1813         if (s->poll)
1814                 return s->poll(dev, s);
1815
1816         return -EINVAL;
1817 }
1818
1819 static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
1820                                   unsigned long arg)
1821 {
1822         const unsigned minor = iminor(file_inode(file));
1823         struct comedi_device *dev = comedi_dev_from_minor(minor);
1824         int rc;
1825
1826         if (!dev)
1827                 return -ENODEV;
1828
1829         mutex_lock(&dev->mutex);
1830
1831         /* Device config is special, because it must work on
1832          * an unconfigured device. */
1833         if (cmd == COMEDI_DEVCONFIG) {
1834                 if (minor >= COMEDI_NUM_BOARD_MINORS) {
1835                         /* Device config not appropriate on non-board minors. */
1836                         rc = -ENOTTY;
1837                         goto done;
1838                 }
1839                 rc = do_devconfig_ioctl(dev,
1840                                         (struct comedi_devconfig __user *)arg);
1841                 if (rc == 0) {
1842                         if (arg == 0 &&
1843                             dev->minor >= comedi_num_legacy_minors) {
1844                                 /* Successfully unconfigured a dynamically
1845                                  * allocated device.  Try and remove it. */
1846                                 if (comedi_clear_board_dev(dev)) {
1847                                         mutex_unlock(&dev->mutex);
1848                                         comedi_free_board_dev(dev);
1849                                         return rc;
1850                                 }
1851                         }
1852                 }
1853                 goto done;
1854         }
1855
1856         if (!dev->attached) {
1857                 DPRINTK("no driver configured on /dev/comedi%i\n", dev->minor);
1858                 rc = -ENODEV;
1859                 goto done;
1860         }
1861
1862         switch (cmd) {
1863         case COMEDI_BUFCONFIG:
1864                 rc = do_bufconfig_ioctl(dev,
1865                                         (struct comedi_bufconfig __user *)arg);
1866                 break;
1867         case COMEDI_DEVINFO:
1868                 rc = do_devinfo_ioctl(dev, (struct comedi_devinfo __user *)arg,
1869                                       file);
1870                 break;
1871         case COMEDI_SUBDINFO:
1872                 rc = do_subdinfo_ioctl(dev,
1873                                        (struct comedi_subdinfo __user *)arg,
1874                                        file);
1875                 break;
1876         case COMEDI_CHANINFO:
1877                 rc = do_chaninfo_ioctl(dev, (void __user *)arg);
1878                 break;
1879         case COMEDI_RANGEINFO:
1880                 rc = do_rangeinfo_ioctl(dev, (void __user *)arg);
1881                 break;
1882         case COMEDI_BUFINFO:
1883                 rc = do_bufinfo_ioctl(dev,
1884                                       (struct comedi_bufinfo __user *)arg,
1885                                       file);
1886                 break;
1887         case COMEDI_LOCK:
1888                 rc = do_lock_ioctl(dev, arg, file);
1889                 break;
1890         case COMEDI_UNLOCK:
1891                 rc = do_unlock_ioctl(dev, arg, file);
1892                 break;
1893         case COMEDI_CANCEL:
1894                 rc = do_cancel_ioctl(dev, arg, file);
1895                 break;
1896         case COMEDI_CMD:
1897                 rc = do_cmd_ioctl(dev, (struct comedi_cmd __user *)arg, file);
1898                 break;
1899         case COMEDI_CMDTEST:
1900                 rc = do_cmdtest_ioctl(dev, (struct comedi_cmd __user *)arg,
1901                                       file);
1902                 break;
1903         case COMEDI_INSNLIST:
1904                 rc = do_insnlist_ioctl(dev,
1905                                        (struct comedi_insnlist __user *)arg,
1906                                        file);
1907                 break;
1908         case COMEDI_INSN:
1909                 rc = do_insn_ioctl(dev, (struct comedi_insn __user *)arg,
1910                                    file);
1911                 break;
1912         case COMEDI_POLL:
1913                 rc = do_poll_ioctl(dev, arg, file);
1914                 break;
1915         default:
1916                 rc = -ENOTTY;
1917                 break;
1918         }
1919
1920 done:
1921         mutex_unlock(&dev->mutex);
1922         return rc;
1923 }
1924
1925 static void comedi_vm_open(struct vm_area_struct *area)
1926 {
1927         struct comedi_async *async;
1928         struct comedi_device *dev;
1929
1930         async = area->vm_private_data;
1931         dev = async->subdevice->device;
1932
1933         mutex_lock(&dev->mutex);
1934         async->mmap_count++;
1935         mutex_unlock(&dev->mutex);
1936 }
1937
1938 static void comedi_vm_close(struct vm_area_struct *area)
1939 {
1940         struct comedi_async *async;
1941         struct comedi_device *dev;
1942
1943         async = area->vm_private_data;
1944         dev = async->subdevice->device;
1945
1946         mutex_lock(&dev->mutex);
1947         async->mmap_count--;
1948         mutex_unlock(&dev->mutex);
1949 }
1950
1951 static struct vm_operations_struct comedi_vm_ops = {
1952         .open = comedi_vm_open,
1953         .close = comedi_vm_close,
1954 };
1955
1956 static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
1957 {
1958         const unsigned minor = iminor(file_inode(file));
1959         struct comedi_device *dev = comedi_dev_from_minor(minor);
1960         struct comedi_subdevice *s;
1961         struct comedi_async *async;
1962         unsigned long start = vma->vm_start;
1963         unsigned long size;
1964         int n_pages;
1965         int i;
1966         int retval;
1967
1968         if (!dev)
1969                 return -ENODEV;
1970
1971         mutex_lock(&dev->mutex);
1972
1973         if (!dev->attached) {
1974                 DPRINTK("no driver configured on comedi%i\n", dev->minor);
1975                 retval = -ENODEV;
1976                 goto done;
1977         }
1978
1979         if (vma->vm_flags & VM_WRITE)
1980                 s = comedi_write_subdevice(dev, minor);
1981         else
1982                 s = comedi_read_subdevice(dev, minor);
1983         if (!s) {
1984                 retval = -EINVAL;
1985                 goto done;
1986         }
1987
1988         async = s->async;
1989         if (!async) {
1990                 retval = -EINVAL;
1991                 goto done;
1992         }
1993
1994         if (vma->vm_pgoff != 0) {
1995                 DPRINTK("comedi: mmap() offset must be 0.\n");
1996                 retval = -EINVAL;
1997                 goto done;
1998         }
1999
2000         size = vma->vm_end - vma->vm_start;
2001         if (size > async->prealloc_bufsz) {
2002                 retval = -EFAULT;
2003                 goto done;
2004         }
2005         if (size & (~PAGE_MASK)) {
2006                 retval = -EFAULT;
2007                 goto done;
2008         }
2009
2010         n_pages = size >> PAGE_SHIFT;
2011         for (i = 0; i < n_pages; ++i) {
2012                 struct comedi_buf_page *buf = &async->buf_page_list[i];
2013
2014                 if (remap_pfn_range(vma, start,
2015                                     page_to_pfn(virt_to_page(buf->virt_addr)),
2016                                     PAGE_SIZE, PAGE_SHARED)) {
2017                         retval = -EAGAIN;
2018                         goto done;
2019                 }
2020                 start += PAGE_SIZE;
2021         }
2022
2023         vma->vm_ops = &comedi_vm_ops;
2024         vma->vm_private_data = async;
2025
2026         async->mmap_count++;
2027
2028         retval = 0;
2029 done:
2030         mutex_unlock(&dev->mutex);
2031         return retval;
2032 }
2033
2034 static unsigned int comedi_poll(struct file *file, poll_table *wait)
2035 {
2036         unsigned int mask = 0;
2037         const unsigned minor = iminor(file_inode(file));
2038         struct comedi_device *dev = comedi_dev_from_minor(minor);
2039         struct comedi_subdevice *s;
2040
2041         if (!dev)
2042                 return -ENODEV;
2043
2044         mutex_lock(&dev->mutex);
2045
2046         if (!dev->attached) {
2047                 DPRINTK("no driver configured on comedi%i\n", dev->minor);
2048                 goto done;
2049         }
2050
2051         s = comedi_read_subdevice(dev, minor);
2052         if (s && s->async) {
2053                 poll_wait(file, &s->async->wait_head, wait);
2054                 if (!s->busy || !comedi_is_subdevice_running(s) ||
2055                     comedi_buf_read_n_available(s->async) > 0)
2056                         mask |= POLLIN | POLLRDNORM;
2057         }
2058
2059         s = comedi_write_subdevice(dev, minor);
2060         if (s && s->async) {
2061                 unsigned int bps = bytes_per_sample(s->async->subdevice);
2062
2063                 poll_wait(file, &s->async->wait_head, wait);
2064                 comedi_buf_write_alloc(s->async, s->async->prealloc_bufsz);
2065                 if (!s->busy || !comedi_is_subdevice_running(s) ||
2066                     comedi_buf_write_n_allocated(s->async) >= bps)
2067                         mask |= POLLOUT | POLLWRNORM;
2068         }
2069
2070 done:
2071         mutex_unlock(&dev->mutex);
2072         return mask;
2073 }
2074
2075 static ssize_t comedi_write(struct file *file, const char __user *buf,
2076                             size_t nbytes, loff_t *offset)
2077 {
2078         struct comedi_subdevice *s;
2079         struct comedi_async *async;
2080         int n, m, count = 0, retval = 0;
2081         DECLARE_WAITQUEUE(wait, current);
2082         const unsigned minor = iminor(file_inode(file));
2083         struct comedi_device *dev = comedi_dev_from_minor(minor);
2084         bool on_wait_queue = false;
2085         bool attach_locked;
2086         unsigned int old_detach_count;
2087
2088         if (!dev)
2089                 return -ENODEV;
2090
2091         /* Protect against device detachment during operation. */
2092         down_read(&dev->attach_lock);
2093         attach_locked = true;
2094         old_detach_count = dev->detach_count;
2095
2096         if (!dev->attached) {
2097                 DPRINTK("no driver configured on comedi%i\n", dev->minor);
2098                 retval = -ENODEV;
2099                 goto out;
2100         }
2101
2102         s = comedi_write_subdevice(dev, minor);
2103         if (!s || !s->async) {
2104                 retval = -EIO;
2105                 goto out;
2106         }
2107
2108         async = s->async;
2109
2110         if (!s->busy || !nbytes)
2111                 goto out;
2112         if (s->busy != file) {
2113                 retval = -EACCES;
2114                 goto out;
2115         }
2116
2117         add_wait_queue(&async->wait_head, &wait);
2118         on_wait_queue = true;
2119         while (nbytes > 0 && !retval) {
2120                 set_current_state(TASK_INTERRUPTIBLE);
2121
2122                 if (!comedi_is_subdevice_running(s)) {
2123                         if (count == 0) {
2124                                 struct comedi_subdevice *new_s;
2125
2126                                 if (comedi_is_subdevice_in_error(s))
2127                                         retval = -EPIPE;
2128                                 else
2129                                         retval = 0;
2130                                 /*
2131                                  * To avoid deadlock, cannot acquire dev->mutex
2132                                  * while dev->attach_lock is held.  Need to
2133                                  * remove task from the async wait queue before
2134                                  * releasing dev->attach_lock, as it might not
2135                                  * be valid afterwards.
2136                                  */
2137                                 remove_wait_queue(&async->wait_head, &wait);
2138                                 on_wait_queue = false;
2139                                 up_read(&dev->attach_lock);
2140                                 attach_locked = false;
2141                                 mutex_lock(&dev->mutex);
2142                                 /*
2143                                  * Become non-busy unless things have changed
2144                                  * behind our back.  Checking dev->detach_count
2145                                  * is unchanged ought to be sufficient (unless
2146                                  * there have been 2**32 detaches in the
2147                                  * meantime!), but check the subdevice pointer
2148                                  * as well just in case.
2149                                  */
2150                                 new_s = comedi_write_subdevice(dev, minor);
2151                                 if (dev->attached &&
2152                                     old_detach_count == dev->detach_count &&
2153                                     s == new_s && new_s->async == async)
2154                                         do_become_nonbusy(dev, s);
2155                                 mutex_unlock(&dev->mutex);
2156                         }
2157                         break;
2158                 }
2159
2160                 n = nbytes;
2161
2162                 m = n;
2163                 if (async->buf_write_ptr + m > async->prealloc_bufsz)
2164                         m = async->prealloc_bufsz - async->buf_write_ptr;
2165                 comedi_buf_write_alloc(async, async->prealloc_bufsz);
2166                 if (m > comedi_buf_write_n_allocated(async))
2167                         m = comedi_buf_write_n_allocated(async);
2168                 if (m < n)
2169                         n = m;
2170
2171                 if (n == 0) {
2172                         if (file->f_flags & O_NONBLOCK) {
2173                                 retval = -EAGAIN;
2174                                 break;
2175                         }
2176                         schedule();
2177                         if (signal_pending(current)) {
2178                                 retval = -ERESTARTSYS;
2179                                 break;
2180                         }
2181                         if (!s->busy)
2182                                 break;
2183                         if (s->busy != file) {
2184                                 retval = -EACCES;
2185                                 break;
2186                         }
2187                         continue;
2188                 }
2189
2190                 m = copy_from_user(async->prealloc_buf + async->buf_write_ptr,
2191                                    buf, n);
2192                 if (m) {
2193                         n -= m;
2194                         retval = -EFAULT;
2195                 }
2196                 comedi_buf_write_free(async, n);
2197
2198                 count += n;
2199                 nbytes -= n;
2200
2201                 buf += n;
2202                 break;          /* makes device work like a pipe */
2203         }
2204 out:
2205         if (on_wait_queue)
2206                 remove_wait_queue(&async->wait_head, &wait);
2207         set_current_state(TASK_RUNNING);
2208         if (attach_locked)
2209                 up_read(&dev->attach_lock);
2210
2211         return count ? count : retval;
2212 }
2213
2214 static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
2215                                 loff_t *offset)
2216 {
2217         struct comedi_subdevice *s;
2218         struct comedi_async *async;
2219         int n, m, count = 0, retval = 0;
2220         DECLARE_WAITQUEUE(wait, current);
2221         const unsigned minor = iminor(file_inode(file));
2222         struct comedi_device *dev = comedi_dev_from_minor(minor);
2223         unsigned int old_detach_count;
2224         bool become_nonbusy = false;
2225         bool attach_locked;
2226
2227         if (!dev)
2228                 return -ENODEV;
2229
2230         /* Protect against device detachment during operation. */
2231         down_read(&dev->attach_lock);
2232         attach_locked = true;
2233         old_detach_count = dev->detach_count;
2234
2235         if (!dev->attached) {
2236                 DPRINTK("no driver configured on comedi%i\n", dev->minor);
2237                 retval = -ENODEV;
2238                 goto out;
2239         }
2240
2241         s = comedi_read_subdevice(dev, minor);
2242         if (!s || !s->async) {
2243                 retval = -EIO;
2244                 goto out;
2245         }
2246
2247         async = s->async;
2248         if (!s->busy || !nbytes)
2249                 goto out;
2250         if (s->busy != file) {
2251                 retval = -EACCES;
2252                 goto out;
2253         }
2254
2255         add_wait_queue(&async->wait_head, &wait);
2256         while (nbytes > 0 && !retval) {
2257                 set_current_state(TASK_INTERRUPTIBLE);
2258
2259                 n = nbytes;
2260
2261                 m = comedi_buf_read_n_available(async);
2262                 /* printk("%d available\n",m); */
2263                 if (async->buf_read_ptr + m > async->prealloc_bufsz)
2264                         m = async->prealloc_bufsz - async->buf_read_ptr;
2265                 /* printk("%d contiguous\n",m); */
2266                 if (m < n)
2267                         n = m;
2268
2269                 if (n == 0) {
2270                         if (!comedi_is_subdevice_running(s)) {
2271                                 if (comedi_is_subdevice_in_error(s))
2272                                         retval = -EPIPE;
2273                                 else
2274                                         retval = 0;
2275                                 become_nonbusy = true;
2276                                 break;
2277                         }
2278                         if (file->f_flags & O_NONBLOCK) {
2279                                 retval = -EAGAIN;
2280                                 break;
2281                         }
2282                         schedule();
2283                         if (signal_pending(current)) {
2284                                 retval = -ERESTARTSYS;
2285                                 break;
2286                         }
2287                         if (!s->busy) {
2288                                 retval = 0;
2289                                 break;
2290                         }
2291                         if (s->busy != file) {
2292                                 retval = -EACCES;
2293                                 break;
2294                         }
2295                         continue;
2296                 }
2297                 m = copy_to_user(buf, async->prealloc_buf +
2298                                  async->buf_read_ptr, n);
2299                 if (m) {
2300                         n -= m;
2301                         retval = -EFAULT;
2302                 }
2303
2304                 comedi_buf_read_alloc(async, n);
2305                 comedi_buf_read_free(async, n);
2306
2307                 count += n;
2308                 nbytes -= n;
2309
2310                 buf += n;
2311                 break;          /* makes device work like a pipe */
2312         }
2313         remove_wait_queue(&async->wait_head, &wait);
2314         set_current_state(TASK_RUNNING);
2315         if (become_nonbusy || comedi_is_subdevice_idle(s)) {
2316                 struct comedi_subdevice *new_s;
2317
2318                 /*
2319                  * To avoid deadlock, cannot acquire dev->mutex
2320                  * while dev->attach_lock is held.
2321                  */
2322                 up_read(&dev->attach_lock);
2323                 attach_locked = false;
2324                 mutex_lock(&dev->mutex);
2325                 /*
2326                  * Check device hasn't become detached behind our back.
2327                  * Checking dev->detach_count is unchanged ought to be
2328                  * sufficient (unless there have been 2**32 detaches in the
2329                  * meantime!), but check the subdevice pointer as well just in
2330                  * case.
2331                  */
2332                 new_s = comedi_read_subdevice(dev, minor);
2333                 if (dev->attached && old_detach_count == dev->detach_count &&
2334                     s == new_s && new_s->async == async) {
2335                         if (become_nonbusy ||
2336                             async->buf_read_count - async->buf_write_count == 0)
2337                                 do_become_nonbusy(dev, s);
2338                 }
2339                 mutex_unlock(&dev->mutex);
2340         }
2341 out:
2342         if (attach_locked)
2343                 up_read(&dev->attach_lock);
2344
2345         return count ? count : retval;
2346 }
2347
2348 static int comedi_open(struct inode *inode, struct file *file)
2349 {
2350         const unsigned minor = iminor(inode);
2351         struct comedi_device *dev = comedi_dev_from_minor(minor);
2352
2353         if (!dev) {
2354                 DPRINTK("invalid minor number\n");
2355                 return -ENODEV;
2356         }
2357
2358         /* This is slightly hacky, but we want module autoloading
2359          * to work for root.
2360          * case: user opens device, attached -> ok
2361          * case: user opens device, unattached, !in_request_module -> autoload
2362          * case: user opens device, unattached, in_request_module -> fail
2363          * case: root opens device, attached -> ok
2364          * case: root opens device, unattached, in_request_module -> ok
2365          *   (typically called from modprobe)
2366          * case: root opens device, unattached, !in_request_module -> autoload
2367          *
2368          * The last could be changed to "-> ok", which would deny root
2369          * autoloading.
2370          */
2371         mutex_lock(&dev->mutex);
2372         if (dev->attached)
2373                 goto ok;
2374         if (!capable(CAP_NET_ADMIN) && dev->in_request_module) {
2375                 DPRINTK("in request module\n");
2376                 mutex_unlock(&dev->mutex);
2377                 return -ENODEV;
2378         }
2379         if (capable(CAP_NET_ADMIN) && dev->in_request_module)
2380                 goto ok;
2381
2382         dev->in_request_module = true;
2383
2384 #ifdef CONFIG_KMOD
2385         mutex_unlock(&dev->mutex);
2386         request_module("char-major-%i-%i", COMEDI_MAJOR, dev->minor);
2387         mutex_lock(&dev->mutex);
2388 #endif
2389
2390         dev->in_request_module = false;
2391
2392         if (!dev->attached && !capable(CAP_NET_ADMIN)) {
2393                 DPRINTK("not attached and not CAP_NET_ADMIN\n");
2394                 mutex_unlock(&dev->mutex);
2395                 return -ENODEV;
2396         }
2397 ok:
2398         __module_get(THIS_MODULE);
2399
2400         if (dev->attached) {
2401                 if (!try_module_get(dev->driver->module)) {
2402                         module_put(THIS_MODULE);
2403                         mutex_unlock(&dev->mutex);
2404                         return -ENOSYS;
2405                 }
2406         }
2407
2408         if (dev->attached && dev->use_count == 0 && dev->open) {
2409                 int rc = dev->open(dev);
2410                 if (rc < 0) {
2411                         module_put(dev->driver->module);
2412                         module_put(THIS_MODULE);
2413                         mutex_unlock(&dev->mutex);
2414                         return rc;
2415                 }
2416         }
2417
2418         dev->use_count++;
2419
2420         mutex_unlock(&dev->mutex);
2421
2422         return 0;
2423 }
2424
2425 static int comedi_fasync(int fd, struct file *file, int on)
2426 {
2427         const unsigned minor = iminor(file_inode(file));
2428         struct comedi_device *dev = comedi_dev_from_minor(minor);
2429
2430         if (!dev)
2431                 return -ENODEV;
2432
2433         return fasync_helper(fd, file, on, &dev->async_queue);
2434 }
2435
2436 static int comedi_close(struct inode *inode, struct file *file)
2437 {
2438         const unsigned minor = iminor(inode);
2439         struct comedi_device *dev = comedi_dev_from_minor(minor);
2440         struct comedi_subdevice *s = NULL;
2441         int i;
2442
2443         if (!dev)
2444                 return -ENODEV;
2445
2446         mutex_lock(&dev->mutex);
2447
2448         if (dev->subdevices) {
2449                 for (i = 0; i < dev->n_subdevices; i++) {
2450                         s = &dev->subdevices[i];
2451
2452                         if (s->busy == file)
2453                                 do_cancel(dev, s);
2454                         if (s->lock == file)
2455                                 s->lock = NULL;
2456                 }
2457         }
2458         if (dev->attached && dev->use_count == 1 && dev->close)
2459                 dev->close(dev);
2460
2461         module_put(THIS_MODULE);
2462         if (dev->attached)
2463                 module_put(dev->driver->module);
2464
2465         dev->use_count--;
2466
2467         mutex_unlock(&dev->mutex);
2468
2469         return 0;
2470 }
2471
2472 static const struct file_operations comedi_fops = {
2473         .owner = THIS_MODULE,
2474         .unlocked_ioctl = comedi_unlocked_ioctl,
2475         .compat_ioctl = comedi_compat_ioctl,
2476         .open = comedi_open,
2477         .release = comedi_close,
2478         .read = comedi_read,
2479         .write = comedi_write,
2480         .mmap = comedi_mmap,
2481         .poll = comedi_poll,
2482         .fasync = comedi_fasync,
2483         .llseek = noop_llseek,
2484 };
2485
2486 void comedi_error(const struct comedi_device *dev, const char *s)
2487 {
2488         dev_err(dev->class_dev, "%s: %s\n", dev->driver->driver_name, s);
2489 }
2490 EXPORT_SYMBOL_GPL(comedi_error);
2491
2492 void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
2493 {
2494         struct comedi_async *async = s->async;
2495         unsigned runflags = 0;
2496         unsigned runflags_mask = 0;
2497
2498         /* DPRINTK("comedi_event 0x%x\n",mask); */
2499
2500         if (!comedi_is_subdevice_running(s))
2501                 return;
2502
2503         if (s->
2504             async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
2505                              COMEDI_CB_OVERFLOW)) {
2506                 runflags_mask |= SRF_RUNNING;
2507         }
2508         /* remember if an error event has occurred, so an error
2509          * can be returned the next time the user does a read() */
2510         if (s->async->events & (COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW)) {
2511                 runflags_mask |= SRF_ERROR;
2512                 runflags |= SRF_ERROR;
2513         }
2514         if (runflags_mask) {
2515                 /*sets SRF_ERROR and SRF_RUNNING together atomically */
2516                 comedi_set_subdevice_runflags(s, runflags_mask, runflags);
2517         }
2518
2519         if (async->cb_mask & s->async->events) {
2520                 wake_up_interruptible(&async->wait_head);
2521                 if (s->subdev_flags & SDF_CMD_READ)
2522                         kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
2523                 if (s->subdev_flags & SDF_CMD_WRITE)
2524                         kill_fasync(&dev->async_queue, SIGIO, POLL_OUT);
2525         }
2526         s->async->events = 0;
2527 }
2528 EXPORT_SYMBOL_GPL(comedi_event);
2529
2530 /* Note: the ->mutex is pre-locked on successful return */
2531 struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device)
2532 {
2533         struct comedi_device *dev;
2534         struct device *csdev;
2535         unsigned i;
2536
2537         dev = kzalloc(sizeof(struct comedi_device), GFP_KERNEL);
2538         if (dev == NULL)
2539                 return ERR_PTR(-ENOMEM);
2540         comedi_device_init(dev);
2541         comedi_set_hw_dev(dev, hardware_device);
2542         mutex_lock(&dev->mutex);
2543         mutex_lock(&comedi_board_minor_table_lock);
2544         for (i = hardware_device ? comedi_num_legacy_minors : 0;
2545              i < COMEDI_NUM_BOARD_MINORS; ++i) {
2546                 if (comedi_board_minor_table[i] == NULL) {
2547                         comedi_board_minor_table[i] = dev;
2548                         break;
2549                 }
2550         }
2551         mutex_unlock(&comedi_board_minor_table_lock);
2552         if (i == COMEDI_NUM_BOARD_MINORS) {
2553                 mutex_unlock(&dev->mutex);
2554                 comedi_device_cleanup(dev);
2555                 comedi_dev_put(dev);
2556                 pr_err("comedi: error: ran out of minor numbers for board device files.\n");
2557                 return ERR_PTR(-EBUSY);
2558         }
2559         dev->minor = i;
2560         csdev = device_create(comedi_class, hardware_device,
2561                               MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i", i);
2562         if (!IS_ERR(csdev))
2563                 dev->class_dev = csdev;
2564
2565         /* Note: dev->mutex needs to be unlocked by the caller. */
2566         return dev;
2567 }
2568
2569 static void comedi_free_board_minor(unsigned minor)
2570 {
2571         BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
2572         comedi_free_board_dev(comedi_clear_board_minor(minor));
2573 }
2574
2575 void comedi_release_hardware_device(struct device *hardware_device)
2576 {
2577         int minor;
2578         struct comedi_device *dev;
2579
2580         for (minor = comedi_num_legacy_minors; minor < COMEDI_NUM_BOARD_MINORS;
2581              minor++) {
2582                 mutex_lock(&comedi_board_minor_table_lock);
2583                 dev = comedi_board_minor_table[minor];
2584                 if (dev && dev->hw_dev == hardware_device) {
2585                         comedi_board_minor_table[minor] = NULL;
2586                         mutex_unlock(&comedi_board_minor_table_lock);
2587                         comedi_free_board_dev(dev);
2588                         break;
2589                 }
2590                 mutex_unlock(&comedi_board_minor_table_lock);
2591         }
2592 }
2593
2594 int comedi_alloc_subdevice_minor(struct comedi_subdevice *s)
2595 {
2596         struct comedi_device *dev = s->device;
2597         struct device *csdev;
2598         unsigned i;
2599
2600         mutex_lock(&comedi_subdevice_minor_table_lock);
2601         for (i = 0; i < COMEDI_NUM_SUBDEVICE_MINORS; ++i) {
2602                 if (comedi_subdevice_minor_table[i] == NULL) {
2603                         comedi_subdevice_minor_table[i] = s;
2604                         break;
2605                 }
2606         }
2607         mutex_unlock(&comedi_subdevice_minor_table_lock);
2608         if (i == COMEDI_NUM_SUBDEVICE_MINORS) {
2609                 pr_err("comedi: error: ran out of minor numbers for subdevice files.\n");
2610                 return -EBUSY;
2611         }
2612         i += COMEDI_NUM_BOARD_MINORS;
2613         s->minor = i;
2614         csdev = device_create(comedi_class, dev->class_dev,
2615                               MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i_subd%i",
2616                               dev->minor, s->index);
2617         if (!IS_ERR(csdev))
2618                 s->class_dev = csdev;
2619
2620         return 0;
2621 }
2622
2623 void comedi_free_subdevice_minor(struct comedi_subdevice *s)
2624 {
2625         unsigned int i;
2626
2627         if (s == NULL)
2628                 return;
2629         if (s->minor < 0)
2630                 return;
2631
2632         BUG_ON(s->minor >= COMEDI_NUM_MINORS);
2633         BUG_ON(s->minor < COMEDI_NUM_BOARD_MINORS);
2634
2635         i = s->minor - COMEDI_NUM_BOARD_MINORS;
2636         mutex_lock(&comedi_subdevice_minor_table_lock);
2637         if (s == comedi_subdevice_minor_table[i])
2638                 comedi_subdevice_minor_table[i] = NULL;
2639         mutex_unlock(&comedi_subdevice_minor_table_lock);
2640         if (s->class_dev) {
2641                 device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, s->minor));
2642                 s->class_dev = NULL;
2643         }
2644 }
2645
2646 static void comedi_cleanup_board_minors(void)
2647 {
2648         unsigned i;
2649
2650         for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++)
2651                 comedi_free_board_minor(i);
2652 }
2653
2654 static int __init comedi_init(void)
2655 {
2656         int i;
2657         int retval;
2658
2659         pr_info("comedi: version " COMEDI_RELEASE " - http://www.comedi.org\n");
2660
2661         if (comedi_num_legacy_minors < 0 ||
2662             comedi_num_legacy_minors > COMEDI_NUM_BOARD_MINORS) {
2663                 pr_err("comedi: error: invalid value for module parameter \"comedi_num_legacy_minors\".  Valid values are 0 through %i.\n",
2664                        COMEDI_NUM_BOARD_MINORS);
2665                 return -EINVAL;
2666         }
2667
2668         retval = register_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
2669                                         COMEDI_NUM_MINORS, "comedi");
2670         if (retval)
2671                 return -EIO;
2672         cdev_init(&comedi_cdev, &comedi_fops);
2673         comedi_cdev.owner = THIS_MODULE;
2674         kobject_set_name(&comedi_cdev.kobj, "comedi");
2675         if (cdev_add(&comedi_cdev, MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS)) {
2676                 unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
2677                                          COMEDI_NUM_MINORS);
2678                 return -EIO;
2679         }
2680         comedi_class = class_create(THIS_MODULE, "comedi");
2681         if (IS_ERR(comedi_class)) {
2682                 pr_err("comedi: failed to create class\n");
2683                 cdev_del(&comedi_cdev);
2684                 unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
2685                                          COMEDI_NUM_MINORS);
2686                 return PTR_ERR(comedi_class);
2687         }
2688
2689         comedi_class->dev_groups = comedi_dev_groups;
2690
2691         /* XXX requires /proc interface */
2692         comedi_proc_init();
2693
2694         /* create devices files for legacy/manual use */
2695         for (i = 0; i < comedi_num_legacy_minors; i++) {
2696                 struct comedi_device *dev;
2697                 dev = comedi_alloc_board_minor(NULL);
2698                 if (IS_ERR(dev)) {
2699                         comedi_cleanup_board_minors();
2700                         cdev_del(&comedi_cdev);
2701                         unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
2702                                                  COMEDI_NUM_MINORS);
2703                         return PTR_ERR(dev);
2704                 } else {
2705                         /* comedi_alloc_board_minor() locked the mutex */
2706                         mutex_unlock(&dev->mutex);
2707                 }
2708         }
2709
2710         return 0;
2711 }
2712 module_init(comedi_init);
2713
2714 static void __exit comedi_cleanup(void)
2715 {
2716         int i;
2717
2718         comedi_cleanup_board_minors();
2719         for (i = 0; i < COMEDI_NUM_BOARD_MINORS; ++i)
2720                 BUG_ON(comedi_board_minor_table[i]);
2721         for (i = 0; i < COMEDI_NUM_SUBDEVICE_MINORS; ++i)
2722                 BUG_ON(comedi_subdevice_minor_table[i]);
2723
2724         class_destroy(comedi_class);
2725         cdev_del(&comedi_cdev);
2726         unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
2727
2728         comedi_proc_cleanup();
2729 }
2730 module_exit(comedi_cleanup);
2731
2732 MODULE_AUTHOR("http://www.comedi.org");
2733 MODULE_DESCRIPTION("Comedi core module");
2734 MODULE_LICENSE("GPL");