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