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