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