5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
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.
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.
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.
26 #define __NO_VERSION__
27 #include "comedi_fops.h"
28 #include "comedi_compat32.h"
30 #include <linux/module.h>
31 #include <linux/errno.h>
32 #include <linux/kernel.h>
33 #include <linux/sched.h>
34 #include <linux/fcntl.h>
35 #include <linux/delay.h>
36 #include <linux/ioport.h>
38 #include <linux/slab.h>
39 #include <linux/kmod.h>
40 #include <linux/poll.h>
41 #include <linux/init.h>
42 #include <linux/device.h>
43 #include <linux/vmalloc.h>
45 #include "comedidev.h"
46 #include <linux/cdev.h>
49 #include <linux/uaccess.h>
51 /* #include "kvmem.h" */
53 MODULE_AUTHOR("http://www.comedi.org");
54 MODULE_DESCRIPTION("Comedi core module");
55 MODULE_LICENSE("GPL");
57 #ifdef CONFIG_COMEDI_DEBUG
59 module_param(comedi_debug
, int, 0644);
62 int comedi_autoconfig
= 1;
63 module_param(comedi_autoconfig
, bool, 0444);
65 int comedi_num_legacy_minors
= 0;
66 module_param(comedi_num_legacy_minors
, int, 0444);
68 static DEFINE_SPINLOCK(comedi_file_info_table_lock
);
69 static struct comedi_device_file_info
70 *comedi_file_info_table
[COMEDI_NUM_MINORS
];
72 static int do_devconfig_ioctl(struct comedi_device
*dev
, comedi_devconfig
*arg
);
73 static int do_bufconfig_ioctl(struct comedi_device
*dev
, void *arg
);
74 static int do_devinfo_ioctl(struct comedi_device
*dev
, comedi_devinfo
*arg
,
76 static int do_subdinfo_ioctl(struct comedi_device
*dev
, comedi_subdinfo
*arg
,
78 static int do_chaninfo_ioctl(struct comedi_device
*dev
, comedi_chaninfo
*arg
);
79 static int do_bufinfo_ioctl(struct comedi_device
*dev
, void *arg
);
80 static int do_cmd_ioctl(struct comedi_device
*dev
, void *arg
, void *file
);
81 static int do_lock_ioctl(struct comedi_device
*dev
, unsigned int arg
, void *file
);
82 static int do_unlock_ioctl(struct comedi_device
*dev
, unsigned int arg
, void *file
);
83 static int do_cancel_ioctl(struct comedi_device
*dev
, unsigned int arg
, void *file
);
84 static int do_cmdtest_ioctl(struct comedi_device
*dev
, void *arg
, void *file
);
85 static int do_insnlist_ioctl(struct comedi_device
*dev
, void *arg
, void *file
);
86 static int do_insn_ioctl(struct comedi_device
*dev
, void *arg
, void *file
);
87 static int do_poll_ioctl(struct comedi_device
*dev
, unsigned int subd
, void *file
);
89 extern void do_become_nonbusy(struct comedi_device
*dev
, struct comedi_subdevice
*s
);
90 static int do_cancel(struct comedi_device
*dev
, struct comedi_subdevice
*s
);
92 static int comedi_fasync(int fd
, struct file
*file
, int on
);
94 static int is_device_busy(struct comedi_device
*dev
);
96 #ifdef HAVE_UNLOCKED_IOCTL
97 static long comedi_unlocked_ioctl(struct file
*file
, unsigned int cmd
,
100 static int comedi_ioctl(struct inode
*inode
, struct file
*file
,
101 unsigned int cmd
, unsigned long arg
)
104 const unsigned minor
= iminor(file
->f_dentry
->d_inode
);
105 struct comedi_device_file_info
*dev_file_info
=
106 comedi_get_device_file_info(minor
);
107 struct comedi_device
*dev
;
110 if (dev_file_info
== NULL
|| dev_file_info
->device
== NULL
)
112 dev
= dev_file_info
->device
;
114 mutex_lock(&dev
->mutex
);
116 /* Device config is special, because it must work on
117 * an unconfigured device. */
118 if (cmd
== COMEDI_DEVCONFIG
) {
119 rc
= do_devconfig_ioctl(dev
, (void *)arg
);
123 if (!dev
->attached
) {
124 DPRINTK("no driver configured on /dev/comedi%i\n", dev
->minor
);
130 case COMEDI_BUFCONFIG
:
131 rc
= do_bufconfig_ioctl(dev
, (void *)arg
);
134 rc
= do_devinfo_ioctl(dev
, (void *)arg
, file
);
136 case COMEDI_SUBDINFO
:
137 rc
= do_subdinfo_ioctl(dev
, (void *)arg
, file
);
139 case COMEDI_CHANINFO
:
140 rc
= do_chaninfo_ioctl(dev
, (void *)arg
);
142 case COMEDI_RANGEINFO
:
143 rc
= do_rangeinfo_ioctl(dev
, (void *)arg
);
146 rc
= do_bufinfo_ioctl(dev
, (void *)arg
);
149 rc
= do_lock_ioctl(dev
, arg
, file
);
152 rc
= do_unlock_ioctl(dev
, arg
, file
);
155 rc
= do_cancel_ioctl(dev
, arg
, file
);
158 rc
= do_cmd_ioctl(dev
, (void *)arg
, file
);
161 rc
= do_cmdtest_ioctl(dev
, (void *)arg
, file
);
163 case COMEDI_INSNLIST
:
164 rc
= do_insnlist_ioctl(dev
, (void *)arg
, file
);
167 rc
= do_insn_ioctl(dev
, (void *)arg
, file
);
170 rc
= do_poll_ioctl(dev
, arg
, file
);
178 mutex_unlock(&dev
->mutex
);
187 pointer to devconfig structure
190 devconfig structure at arg
195 static int do_devconfig_ioctl(struct comedi_device
*dev
, comedi_devconfig
*arg
)
199 unsigned char *aux_data
= NULL
;
202 if (!capable(CAP_SYS_ADMIN
))
206 if (is_device_busy(dev
))
209 struct module
*driver_module
= dev
->driver
->module
;
210 comedi_device_detach(dev
);
211 module_put(driver_module
);
216 if (copy_from_user(&it
, arg
, sizeof(comedi_devconfig
)))
219 it
.board_name
[COMEDI_NAMELEN
- 1] = 0;
221 if (comedi_aux_data(it
.options
, 0) &&
222 it
.options
[COMEDI_DEVCONF_AUX_DATA_LENGTH
]) {
224 aux_len
= it
.options
[COMEDI_DEVCONF_AUX_DATA_LENGTH
];
228 aux_data
= vmalloc(aux_len
);
232 if (copy_from_user(aux_data
,
233 comedi_aux_data(it
.options
, 0), aux_len
)) {
237 it
.options
[COMEDI_DEVCONF_AUX_DATA_LO
] =
238 (unsigned long)aux_data
;
239 if (sizeof(void *) > sizeof(int)) {
240 bit_shift
= sizeof(int) * 8;
241 it
.options
[COMEDI_DEVCONF_AUX_DATA_HI
] =
242 ((unsigned long)aux_data
) >> bit_shift
;
244 it
.options
[COMEDI_DEVCONF_AUX_DATA_HI
] = 0;
247 ret
= comedi_device_attach(dev
, &it
);
249 if (!try_module_get(dev
->driver
->module
)) {
250 comedi_device_detach(dev
);
263 buffer configuration ioctl
266 pointer to bufconfig structure
272 modified bufconfig at arg
275 static int do_bufconfig_ioctl(struct comedi_device
*dev
, void *arg
)
278 struct comedi_async
*async
;
279 struct comedi_subdevice
*s
;
282 if (copy_from_user(&bc
, arg
, sizeof(comedi_bufconfig
)))
285 if (bc
.subdevice
>= dev
->n_subdevices
|| bc
.subdevice
< 0)
288 s
= dev
->subdevices
+ bc
.subdevice
;
292 DPRINTK("subdevice does not have async capability\n");
298 if (bc
.maximum_size
) {
299 if (!capable(CAP_SYS_ADMIN
))
302 async
->max_bufsize
= bc
.maximum_size
;
306 if (bc
.size
> async
->max_bufsize
)
310 DPRINTK("subdevice is busy, cannot resize buffer\n");
313 if (async
->mmap_count
) {
314 DPRINTK("subdevice is mmapped, cannot resize buffer\n");
318 if (!async
->prealloc_buf
)
321 /* make sure buffer is an integral number of pages
323 bc
.size
= (bc
.size
+ PAGE_SIZE
- 1) & PAGE_MASK
;
325 ret
= comedi_buf_alloc(dev
, s
, bc
.size
);
330 ret
= s
->buf_change(dev
, s
, bc
.size
);
335 DPRINTK("comedi%i subd %d buffer resized to %i bytes\n",
336 dev
->minor
, bc
.subdevice
, async
->prealloc_bufsz
);
339 bc
.size
= async
->prealloc_bufsz
;
340 bc
.maximum_size
= async
->max_bufsize
;
343 if (copy_to_user(arg
, &bc
, sizeof(comedi_bufconfig
)))
354 pointer to devinfo structure
363 static int do_devinfo_ioctl(struct comedi_device
*dev
, comedi_devinfo
*arg
,
366 comedi_devinfo devinfo
;
367 const unsigned minor
= iminor(file
->f_dentry
->d_inode
);
368 struct comedi_device_file_info
*dev_file_info
=
369 comedi_get_device_file_info(minor
);
370 struct comedi_subdevice
*read_subdev
=
371 comedi_get_read_subdevice(dev_file_info
);
372 struct comedi_subdevice
*write_subdev
=
373 comedi_get_write_subdevice(dev_file_info
);
375 memset(&devinfo
, 0, sizeof(devinfo
));
377 /* fill devinfo structure */
378 devinfo
.version_code
= COMEDI_VERSION_CODE
;
379 devinfo
.n_subdevs
= dev
->n_subdevices
;
380 memcpy(devinfo
.driver_name
, dev
->driver
->driver_name
, COMEDI_NAMELEN
);
381 memcpy(devinfo
.board_name
, dev
->board_name
, COMEDI_NAMELEN
);
384 devinfo
.read_subdevice
= read_subdev
- dev
->subdevices
;
386 devinfo
.read_subdevice
= -1;
389 devinfo
.write_subdevice
= write_subdev
- dev
->subdevices
;
391 devinfo
.write_subdevice
= -1;
393 if (copy_to_user(arg
, &devinfo
, sizeof(comedi_devinfo
)))
404 pointer to array of subdevice info structures
410 array of subdevice info structures at arg
413 static int do_subdinfo_ioctl(struct comedi_device
*dev
, comedi_subdinfo
*arg
,
417 comedi_subdinfo
*tmp
, *us
;
418 struct comedi_subdevice
*s
;
420 tmp
= kcalloc(dev
->n_subdevices
, sizeof(comedi_subdinfo
), GFP_KERNEL
);
424 /* fill subdinfo structs */
425 for (i
= 0; i
< dev
->n_subdevices
; i
++) {
426 s
= dev
->subdevices
+ i
;
430 us
->n_chan
= s
->n_chan
;
431 us
->subd_flags
= s
->subdev_flags
;
432 if (comedi_get_subdevice_runflags(s
) & SRF_RUNNING
)
433 us
->subd_flags
|= SDF_RUNNING
;
434 #define TIMER_nanosec 5 /* backwards compatibility */
435 us
->timer_type
= TIMER_nanosec
;
436 us
->len_chanlist
= s
->len_chanlist
;
437 us
->maxdata
= s
->maxdata
;
438 if (s
->range_table
) {
440 (i
<< 24) | (0 << 16) | (s
->range_table
->length
);
442 us
->range_type
= 0; /* XXX */
444 us
->flags
= s
->flags
;
447 us
->subd_flags
|= SDF_BUSY
;
449 us
->subd_flags
|= SDF_BUSY_OWNER
;
451 us
->subd_flags
|= SDF_LOCKED
;
453 us
->subd_flags
|= SDF_LOCK_OWNER
;
454 if (!s
->maxdata
&& s
->maxdata_list
)
455 us
->subd_flags
|= SDF_MAXDATA
;
457 us
->subd_flags
|= SDF_FLAGS
;
458 if (s
->range_table_list
)
459 us
->subd_flags
|= SDF_RANGETYPE
;
461 us
->subd_flags
|= SDF_CMD
;
463 if (s
->insn_bits
!= &insn_inval
)
464 us
->insn_bits_support
= COMEDI_SUPPORTED
;
466 us
->insn_bits_support
= COMEDI_UNSUPPORTED
;
468 us
->settling_time_0
= s
->settling_time_0
;
471 ret
= copy_to_user(arg
, tmp
,
472 dev
->n_subdevices
* sizeof(comedi_subdinfo
));
476 return ret
? -EFAULT
: 0;
484 pointer to chaninfo structure
487 chaninfo structure at arg
490 arrays at elements of chaninfo structure
493 static int do_chaninfo_ioctl(struct comedi_device
*dev
, comedi_chaninfo
*arg
)
495 struct comedi_subdevice
*s
;
498 if (copy_from_user(&it
, arg
, sizeof(comedi_chaninfo
)))
501 if (it
.subdev
>= dev
->n_subdevices
)
503 s
= dev
->subdevices
+ it
.subdev
;
505 if (it
.maxdata_list
) {
506 if (s
->maxdata
|| !s
->maxdata_list
)
508 if (copy_to_user(it
.maxdata_list
, s
->maxdata_list
,
509 s
->n_chan
* sizeof(unsigned int)))
516 if (copy_to_user(it
.flaglist
, s
->flaglist
,
517 s
->n_chan
* sizeof(unsigned int)))
524 if (!s
->range_table_list
)
526 for (i
= 0; i
< s
->n_chan
; i
++) {
529 x
= (dev
->minor
<< 28) | (it
.subdev
<< 24) | (i
<< 16) |
530 (s
->range_table_list
[i
]->length
);
531 put_user(x
, it
.rangelist
+ i
);
534 if (copy_to_user(it
.rangelist
, s
->range_type_list
,
535 s
->n_chan
*sizeof(unsigned int)))
545 buffer information ioctl
548 pointer to bufinfo structure
554 modified bufinfo at arg
557 static int do_bufinfo_ioctl(struct comedi_device
*dev
, void *arg
)
560 struct comedi_subdevice
*s
;
561 struct comedi_async
*async
;
563 if (copy_from_user(&bi
, arg
, sizeof(comedi_bufinfo
)))
566 if (bi
.subdevice
>= dev
->n_subdevices
|| bi
.subdevice
< 0)
569 s
= dev
->subdevices
+ bi
.subdevice
;
573 DPRINTK("subdevice does not have async capability\n");
574 bi
.buf_write_ptr
= 0;
576 bi
.buf_write_count
= 0;
577 bi
.buf_read_count
= 0;
581 if (bi
.bytes_read
&& (s
->subdev_flags
& SDF_CMD_READ
)) {
582 bi
.bytes_read
= comedi_buf_read_alloc(async
, bi
.bytes_read
);
583 comedi_buf_read_free(async
, bi
.bytes_read
);
585 if (!(comedi_get_subdevice_runflags(s
) & (SRF_ERROR
|
587 && async
->buf_write_count
== async
->buf_read_count
) {
588 do_become_nonbusy(dev
, s
);
592 if (bi
.bytes_written
&& (s
->subdev_flags
& SDF_CMD_WRITE
)) {
594 comedi_buf_write_alloc(async
, bi
.bytes_written
);
595 comedi_buf_write_free(async
, bi
.bytes_written
);
598 bi
.buf_write_count
= async
->buf_write_count
;
599 bi
.buf_write_ptr
= async
->buf_write_ptr
;
600 bi
.buf_read_count
= async
->buf_read_count
;
601 bi
.buf_read_ptr
= async
->buf_read_ptr
;
604 if (copy_to_user(arg
, &bi
, sizeof(comedi_bufinfo
)))
610 static int parse_insn(struct comedi_device
*dev
, comedi_insn
*insn
, unsigned int *data
,
614 * synchronous instructions
617 * pointer to sync cmd structure
620 * sync cmd struct at arg
627 /* arbitrary limits */
628 #define MAX_SAMPLES 256
629 static int do_insnlist_ioctl(struct comedi_device
*dev
, void *arg
, void *file
)
631 comedi_insnlist insnlist
;
632 comedi_insn
*insns
= NULL
;
633 unsigned int *data
= NULL
;
637 if (copy_from_user(&insnlist
, arg
, sizeof(comedi_insnlist
)))
640 data
= kmalloc(sizeof(unsigned int) * MAX_SAMPLES
, GFP_KERNEL
);
642 DPRINTK("kmalloc failed\n");
647 insns
= kmalloc(sizeof(comedi_insn
) * insnlist
.n_insns
, GFP_KERNEL
);
649 DPRINTK("kmalloc failed\n");
654 if (copy_from_user(insns
, insnlist
.insns
,
655 sizeof(comedi_insn
) * insnlist
.n_insns
)) {
656 DPRINTK("copy_from_user failed\n");
661 for (i
= 0; i
< insnlist
.n_insns
; i
++) {
662 if (insns
[i
].n
> MAX_SAMPLES
) {
663 DPRINTK("number of samples too large\n");
667 if (insns
[i
].insn
& INSN_MASK_WRITE
) {
668 if (copy_from_user(data
, insns
[i
].data
,
669 insns
[i
].n
* sizeof(unsigned int))) {
670 DPRINTK("copy_from_user failed\n");
675 ret
= parse_insn(dev
, insns
+ i
, data
, file
);
678 if (insns
[i
].insn
& INSN_MASK_READ
) {
679 if (copy_to_user(insns
[i
].data
, data
,
680 insns
[i
].n
* sizeof(unsigned int))) {
681 DPRINTK("copy_to_user failed\n");
699 static int check_insn_config_length(comedi_insn
*insn
, unsigned int *data
)
705 case INSN_CONFIG_DIO_OUTPUT
:
706 case INSN_CONFIG_DIO_INPUT
:
707 case INSN_CONFIG_DISARM
:
708 case INSN_CONFIG_RESET
:
712 case INSN_CONFIG_ARM
:
713 case INSN_CONFIG_DIO_QUERY
:
714 case INSN_CONFIG_BLOCK_SIZE
:
715 case INSN_CONFIG_FILTER
:
716 case INSN_CONFIG_SERIAL_CLOCK
:
717 case INSN_CONFIG_BIDIRECTIONAL_DATA
:
718 case INSN_CONFIG_ALT_SOURCE
:
719 case INSN_CONFIG_SET_COUNTER_MODE
:
720 case INSN_CONFIG_8254_READ_STATUS
:
721 case INSN_CONFIG_SET_ROUTING
:
722 case INSN_CONFIG_GET_ROUTING
:
723 case INSN_CONFIG_GET_PWM_STATUS
:
724 case INSN_CONFIG_PWM_SET_PERIOD
:
725 case INSN_CONFIG_PWM_GET_PERIOD
:
729 case INSN_CONFIG_SET_GATE_SRC
:
730 case INSN_CONFIG_GET_GATE_SRC
:
731 case INSN_CONFIG_SET_CLOCK_SRC
:
732 case INSN_CONFIG_GET_CLOCK_SRC
:
733 case INSN_CONFIG_SET_OTHER_SRC
:
734 case INSN_CONFIG_GET_COUNTER_STATUS
:
735 case INSN_CONFIG_PWM_SET_H_BRIDGE
:
736 case INSN_CONFIG_PWM_GET_H_BRIDGE
:
737 case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE
:
741 case INSN_CONFIG_PWM_OUTPUT
:
742 case INSN_CONFIG_ANALOG_TRIG
:
746 /* by default we allow the insn since we don't have checks for
747 * all possible cases yet */
749 rt_printk("comedi: no check for data length of config insn id "
750 "%i is implemented.\n"
751 " Add a check to %s in %s.\n"
752 " Assuming n=%i is correct.\n", data
[0], __func__
,
760 static int parse_insn(struct comedi_device
*dev
, comedi_insn
*insn
, unsigned int *data
,
763 struct comedi_subdevice
*s
;
767 if (insn
->insn
& INSN_MASK_SPECIAL
) {
768 /* a non-subdevice instruction */
770 switch (insn
->insn
) {
780 do_gettimeofday(&tv
);
782 data
[1] = tv
.tv_usec
;
788 if (insn
->n
!= 1 || data
[0] >= 100000) {
792 udelay(data
[0] / 1000);
800 if (insn
->subdev
>= dev
->n_subdevices
) {
801 DPRINTK("%d not usable subdevice\n",
806 s
= dev
->subdevices
+ insn
->subdev
;
808 DPRINTK("no async\n");
812 if (!s
->async
->inttrig
) {
813 DPRINTK("no inttrig\n");
817 ret
= s
->async
->inttrig(dev
, s
, insn
->data
[0]);
822 DPRINTK("invalid insn\n");
827 /* a subdevice instruction */
828 unsigned int maxdata
;
830 if (insn
->subdev
>= dev
->n_subdevices
) {
831 DPRINTK("subdevice %d out of range\n", insn
->subdev
);
835 s
= dev
->subdevices
+ insn
->subdev
;
837 if (s
->type
== COMEDI_SUBD_UNUSED
) {
838 DPRINTK("%d not usable subdevice\n", insn
->subdev
);
843 /* are we locked? (ioctl lock) */
844 if (s
->lock
&& s
->lock
!= file
) {
845 DPRINTK("device locked\n");
850 ret
= check_chanlist(s
, 1, &insn
->chanspec
);
853 DPRINTK("bad chanspec\n");
861 /* This looks arbitrary. It is. */
862 s
->busy
= &parse_insn
;
863 switch (insn
->insn
) {
865 ret
= s
->insn_read(dev
, s
, insn
, data
);
868 maxdata
= s
->maxdata_list
869 ? s
->maxdata_list
[CR_CHAN(insn
->chanspec
)]
871 for (i
= 0; i
< insn
->n
; ++i
) {
872 if (data
[i
] > maxdata
) {
874 DPRINTK("bad data value(s)\n");
879 ret
= s
->insn_write(dev
, s
, insn
, data
);
886 ret
= s
->insn_bits(dev
, s
, insn
, data
);
889 ret
= check_insn_config_length(insn
, data
);
892 ret
= s
->insn_config(dev
, s
, insn
, data
);
908 * synchronous instructions
914 * comedi_insn struct at arg
920 static int do_insn_ioctl(struct comedi_device
*dev
, void *arg
, void *file
)
923 unsigned int *data
= NULL
;
926 data
= kmalloc(sizeof(unsigned int) * MAX_SAMPLES
, GFP_KERNEL
);
932 if (copy_from_user(&insn
, arg
, sizeof(comedi_insn
))) {
937 /* This is where the behavior of insn and insnlist deviate. */
938 if (insn
.n
> MAX_SAMPLES
)
939 insn
.n
= MAX_SAMPLES
;
940 if (insn
.insn
& INSN_MASK_WRITE
) {
941 if (copy_from_user(data
, insn
.data
, insn
.n
* sizeof(unsigned int))) {
946 ret
= parse_insn(dev
, &insn
, data
, file
);
949 if (insn
.insn
& INSN_MASK_READ
) {
950 if (copy_to_user(insn
.data
, data
, insn
.n
* sizeof(unsigned int))) {
968 pointer to cmd structure
975 modified cmd structure at arg
978 static int do_cmd_ioctl(struct comedi_device
*dev
, void *arg
, void *file
)
980 struct comedi_cmd user_cmd
;
981 struct comedi_subdevice
*s
;
982 struct comedi_async
*async
;
984 unsigned int *chanlist_saver
= NULL
;
986 if (copy_from_user(&user_cmd
, arg
, sizeof(struct comedi_cmd
))) {
987 DPRINTK("bad cmd address\n");
990 /* save user's chanlist pointer so it can be restored later */
991 chanlist_saver
= user_cmd
.chanlist
;
993 if (user_cmd
.subdev
>= dev
->n_subdevices
) {
994 DPRINTK("%d no such subdevice\n", user_cmd
.subdev
);
998 s
= dev
->subdevices
+ user_cmd
.subdev
;
1001 if (s
->type
== COMEDI_SUBD_UNUSED
) {
1002 DPRINTK("%d not valid subdevice\n", user_cmd
.subdev
);
1006 if (!s
->do_cmd
|| !s
->do_cmdtest
|| !s
->async
) {
1007 DPRINTK("subdevice %i does not support commands\n",
1012 /* are we locked? (ioctl lock) */
1013 if (s
->lock
&& s
->lock
!= file
) {
1014 DPRINTK("subdevice locked\n");
1020 DPRINTK("subdevice busy\n");
1025 /* make sure channel/gain list isn't too long */
1026 if (user_cmd
.chanlist_len
> s
->len_chanlist
) {
1027 DPRINTK("channel/gain list too long %u > %d\n",
1028 user_cmd
.chanlist_len
, s
->len_chanlist
);
1033 /* make sure channel/gain list isn't too short */
1034 if (user_cmd
.chanlist_len
< 1) {
1035 DPRINTK("channel/gain list too short %u < 1\n",
1036 user_cmd
.chanlist_len
);
1041 kfree(async
->cmd
.chanlist
);
1042 async
->cmd
= user_cmd
;
1043 async
->cmd
.data
= NULL
;
1044 /* load channel/gain list */
1045 async
->cmd
.chanlist
=
1046 kmalloc(async
->cmd
.chanlist_len
* sizeof(int), GFP_KERNEL
);
1047 if (!async
->cmd
.chanlist
) {
1048 DPRINTK("allocation failed\n");
1053 if (copy_from_user(async
->cmd
.chanlist
, user_cmd
.chanlist
,
1054 async
->cmd
.chanlist_len
* sizeof(int))) {
1055 DPRINTK("fault reading chanlist\n");
1060 /* make sure each element in channel/gain list is valid */
1061 ret
= check_chanlist(s
, async
->cmd
.chanlist_len
, async
->cmd
.chanlist
);
1063 DPRINTK("bad chanlist\n");
1067 ret
= s
->do_cmdtest(dev
, s
, &async
->cmd
);
1069 if (async
->cmd
.flags
& TRIG_BOGUS
|| ret
) {
1070 DPRINTK("test returned %d\n", ret
);
1071 user_cmd
= async
->cmd
;
1072 /* restore chanlist pointer before copying back */
1073 user_cmd
.chanlist
= chanlist_saver
;
1074 user_cmd
.data
= NULL
;
1075 if (copy_to_user(arg
, &user_cmd
, sizeof(struct comedi_cmd
))) {
1076 DPRINTK("fault writing cmd\n");
1084 if (!async
->prealloc_bufsz
) {
1086 DPRINTK("no buffer (?)\n");
1090 comedi_reset_async_buf(async
);
1093 COMEDI_CB_EOA
| COMEDI_CB_BLOCK
| COMEDI_CB_ERROR
|
1095 if (async
->cmd
.flags
& TRIG_WAKE_EOS
)
1096 async
->cb_mask
|= COMEDI_CB_EOS
;
1098 comedi_set_subdevice_runflags(s
, ~0, SRF_USER
| SRF_RUNNING
);
1100 #ifdef CONFIG_COMEDI_RT
1101 if (async
->cmd
.flags
& TRIG_RT
) {
1102 if (comedi_switch_to_rt(dev
) == 0)
1103 comedi_set_subdevice_runflags(s
, SRF_RT
, SRF_RT
);
1107 ret
= s
->do_cmd(dev
, s
);
1112 do_become_nonbusy(dev
, s
);
1119 command testing ioctl
1122 pointer to cmd structure
1125 cmd structure at arg
1129 modified cmd structure at arg
1132 static int do_cmdtest_ioctl(struct comedi_device
*dev
, void *arg
, void *file
)
1134 struct comedi_cmd user_cmd
;
1135 struct comedi_subdevice
*s
;
1137 unsigned int *chanlist
= NULL
;
1138 unsigned int *chanlist_saver
= NULL
;
1140 if (copy_from_user(&user_cmd
, arg
, sizeof(struct comedi_cmd
))) {
1141 DPRINTK("bad cmd address\n");
1144 /* save user's chanlist pointer so it can be restored later */
1145 chanlist_saver
= user_cmd
.chanlist
;
1147 if (user_cmd
.subdev
>= dev
->n_subdevices
) {
1148 DPRINTK("%d no such subdevice\n", user_cmd
.subdev
);
1152 s
= dev
->subdevices
+ user_cmd
.subdev
;
1153 if (s
->type
== COMEDI_SUBD_UNUSED
) {
1154 DPRINTK("%d not valid subdevice\n", user_cmd
.subdev
);
1158 if (!s
->do_cmd
|| !s
->do_cmdtest
) {
1159 DPRINTK("subdevice %i does not support commands\n",
1164 /* make sure channel/gain list isn't too long */
1165 if (user_cmd
.chanlist_len
> s
->len_chanlist
) {
1166 DPRINTK("channel/gain list too long %d > %d\n",
1167 user_cmd
.chanlist_len
, s
->len_chanlist
);
1172 /* load channel/gain list */
1173 if (user_cmd
.chanlist
) {
1175 kmalloc(user_cmd
.chanlist_len
* sizeof(int), GFP_KERNEL
);
1177 DPRINTK("allocation failed\n");
1182 if (copy_from_user(chanlist
, user_cmd
.chanlist
,
1183 user_cmd
.chanlist_len
* sizeof(int))) {
1184 DPRINTK("fault reading chanlist\n");
1189 /* make sure each element in channel/gain list is valid */
1190 ret
= check_chanlist(s
, user_cmd
.chanlist_len
, chanlist
);
1192 DPRINTK("bad chanlist\n");
1196 user_cmd
.chanlist
= chanlist
;
1199 ret
= s
->do_cmdtest(dev
, s
, &user_cmd
);
1201 /* restore chanlist pointer before copying back */
1202 user_cmd
.chanlist
= chanlist_saver
;
1204 if (copy_to_user(arg
, &user_cmd
, sizeof(struct comedi_cmd
))) {
1205 DPRINTK("bad cmd address\n");
1230 static int do_lock_ioctl(struct comedi_device
*dev
, unsigned int arg
, void *file
)
1233 unsigned long flags
;
1234 struct comedi_subdevice
*s
;
1236 if (arg
>= dev
->n_subdevices
)
1238 s
= dev
->subdevices
+ arg
;
1240 comedi_spin_lock_irqsave(&s
->spin_lock
, flags
);
1241 if (s
->busy
|| s
->lock
)
1245 comedi_spin_unlock_irqrestore(&s
->spin_lock
, flags
);
1252 ret
= s
->lock_f(dev
, s
);
1271 This function isn't protected by the semaphore, since
1272 we already own the lock.
1274 static int do_unlock_ioctl(struct comedi_device
*dev
, unsigned int arg
, void *file
)
1276 struct comedi_subdevice
*s
;
1278 if (arg
>= dev
->n_subdevices
)
1280 s
= dev
->subdevices
+ arg
;
1285 if (s
->lock
&& s
->lock
!= file
)
1288 if (s
->lock
== file
) {
1302 cancel acquisition ioctl
1314 static int do_cancel_ioctl(struct comedi_device
*dev
, unsigned int arg
, void *file
)
1316 struct comedi_subdevice
*s
;
1318 if (arg
>= dev
->n_subdevices
)
1320 s
= dev
->subdevices
+ arg
;
1321 if (s
->async
== NULL
)
1324 if (s
->lock
&& s
->lock
!= file
)
1330 if (s
->busy
!= file
)
1333 return do_cancel(dev
, s
);
1338 instructs driver to synchronize buffers
1350 static int do_poll_ioctl(struct comedi_device
*dev
, unsigned int arg
, void *file
)
1352 struct comedi_subdevice
*s
;
1354 if (arg
>= dev
->n_subdevices
)
1356 s
= dev
->subdevices
+ arg
;
1358 if (s
->lock
&& s
->lock
!= file
)
1364 if (s
->busy
!= file
)
1368 return s
->poll(dev
, s
);
1373 static int do_cancel(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
1377 if ((comedi_get_subdevice_runflags(s
) & SRF_RUNNING
) && s
->cancel
)
1378 ret
= s
->cancel(dev
, s
);
1380 do_become_nonbusy(dev
, s
);
1385 void comedi_unmap(struct vm_area_struct
*area
)
1387 struct comedi_async
*async
;
1388 struct comedi_device
*dev
;
1390 async
= area
->vm_private_data
;
1391 dev
= async
->subdevice
->device
;
1393 mutex_lock(&dev
->mutex
);
1394 async
->mmap_count
--;
1395 mutex_unlock(&dev
->mutex
);
1398 static struct vm_operations_struct comedi_vm_ops
= {
1399 .close
= comedi_unmap
,
1402 static int comedi_mmap(struct file
*file
, struct vm_area_struct
*vma
)
1404 const unsigned minor
= iminor(file
->f_dentry
->d_inode
);
1405 struct comedi_device_file_info
*dev_file_info
=
1406 comedi_get_device_file_info(minor
);
1407 struct comedi_device
*dev
= dev_file_info
->device
;
1408 struct comedi_async
*async
= NULL
;
1409 unsigned long start
= vma
->vm_start
;
1414 struct comedi_subdevice
*s
;
1416 mutex_lock(&dev
->mutex
);
1417 if (!dev
->attached
) {
1418 DPRINTK("no driver configured on comedi%i\n", dev
->minor
);
1422 if (vma
->vm_flags
& VM_WRITE
)
1423 s
= comedi_get_write_subdevice(dev_file_info
);
1425 s
= comedi_get_read_subdevice(dev_file_info
);
1432 if (async
== NULL
) {
1437 if (vma
->vm_pgoff
!= 0) {
1438 DPRINTK("comedi: mmap() offset must be 0.\n");
1443 size
= vma
->vm_end
- vma
->vm_start
;
1444 if (size
> async
->prealloc_bufsz
) {
1448 if (size
& (~PAGE_MASK
)) {
1453 n_pages
= size
>> PAGE_SHIFT
;
1454 for (i
= 0; i
< n_pages
; ++i
) {
1455 if (remap_pfn_range(vma
, start
,
1456 page_to_pfn(virt_to_page(async
->
1459 PAGE_SIZE
, PAGE_SHARED
)) {
1466 vma
->vm_ops
= &comedi_vm_ops
;
1467 vma
->vm_private_data
= async
;
1469 async
->mmap_count
++;
1473 mutex_unlock(&dev
->mutex
);
1477 static unsigned int comedi_poll(struct file
*file
, poll_table
*wait
)
1479 unsigned int mask
= 0;
1480 const unsigned minor
= iminor(file
->f_dentry
->d_inode
);
1481 struct comedi_device_file_info
*dev_file_info
=
1482 comedi_get_device_file_info(minor
);
1483 struct comedi_device
*dev
= dev_file_info
->device
;
1484 struct comedi_subdevice
*read_subdev
;
1485 struct comedi_subdevice
*write_subdev
;
1487 mutex_lock(&dev
->mutex
);
1488 if (!dev
->attached
) {
1489 DPRINTK("no driver configured on comedi%i\n", dev
->minor
);
1490 mutex_unlock(&dev
->mutex
);
1495 read_subdev
= comedi_get_read_subdevice(dev_file_info
);
1497 poll_wait(file
, &read_subdev
->async
->wait_head
, wait
);
1498 if (!read_subdev
->busy
1499 || comedi_buf_read_n_available(read_subdev
->async
) > 0
1500 || !(comedi_get_subdevice_runflags(read_subdev
) &
1502 mask
|= POLLIN
| POLLRDNORM
;
1505 write_subdev
= comedi_get_write_subdevice(dev_file_info
);
1507 poll_wait(file
, &write_subdev
->async
->wait_head
, wait
);
1508 comedi_buf_write_alloc(write_subdev
->async
,
1509 write_subdev
->async
->prealloc_bufsz
);
1510 if (!write_subdev
->busy
1511 || !(comedi_get_subdevice_runflags(write_subdev
) &
1513 || comedi_buf_write_n_allocated(write_subdev
->async
) >=
1514 bytes_per_sample(write_subdev
->async
->subdevice
)) {
1515 mask
|= POLLOUT
| POLLWRNORM
;
1519 mutex_unlock(&dev
->mutex
);
1523 static ssize_t
comedi_write(struct file
*file
, const char *buf
, size_t nbytes
,
1526 struct comedi_subdevice
*s
;
1527 struct comedi_async
*async
;
1528 int n
, m
, count
= 0, retval
= 0;
1529 DECLARE_WAITQUEUE(wait
, current
);
1530 const unsigned minor
= iminor(file
->f_dentry
->d_inode
);
1531 struct comedi_device_file_info
*dev_file_info
=
1532 comedi_get_device_file_info(minor
);
1533 struct comedi_device
*dev
= dev_file_info
->device
;
1535 if (!dev
->attached
) {
1536 DPRINTK("no driver configured on comedi%i\n", dev
->minor
);
1541 s
= comedi_get_write_subdevice(dev_file_info
);
1556 if (s
->busy
!= file
) {
1560 add_wait_queue(&async
->wait_head
, &wait
);
1561 while (nbytes
> 0 && !retval
) {
1562 set_current_state(TASK_INTERRUPTIBLE
);
1567 if (async
->buf_write_ptr
+ m
> async
->prealloc_bufsz
)
1568 m
= async
->prealloc_bufsz
- async
->buf_write_ptr
;
1569 comedi_buf_write_alloc(async
, async
->prealloc_bufsz
);
1570 if (m
> comedi_buf_write_n_allocated(async
))
1571 m
= comedi_buf_write_n_allocated(async
);
1576 if (!(comedi_get_subdevice_runflags(s
) & SRF_RUNNING
)) {
1577 if (comedi_get_subdevice_runflags(s
) &
1583 do_become_nonbusy(dev
, s
);
1586 if (file
->f_flags
& O_NONBLOCK
) {
1590 if (signal_pending(current
)) {
1591 retval
= -ERESTARTSYS
;
1597 if (s
->busy
!= file
) {
1604 m
= copy_from_user(async
->prealloc_buf
+ async
->buf_write_ptr
,
1610 comedi_buf_write_free(async
, n
);
1616 break; /* makes device work like a pipe */
1618 set_current_state(TASK_RUNNING
);
1619 remove_wait_queue(&async
->wait_head
, &wait
);
1622 return count
? count
: retval
;
1625 static ssize_t
comedi_read(struct file
*file
, char *buf
, size_t nbytes
,
1628 struct comedi_subdevice
*s
;
1629 struct comedi_async
*async
;
1630 int n
, m
, count
= 0, retval
= 0;
1631 DECLARE_WAITQUEUE(wait
, current
);
1632 const unsigned minor
= iminor(file
->f_dentry
->d_inode
);
1633 struct comedi_device_file_info
*dev_file_info
=
1634 comedi_get_device_file_info(minor
);
1635 struct comedi_device
*dev
= dev_file_info
->device
;
1637 if (!dev
->attached
) {
1638 DPRINTK("no driver configured on comedi%i\n", dev
->minor
);
1643 s
= comedi_get_read_subdevice(dev_file_info
);
1657 if (s
->busy
!= file
) {
1662 add_wait_queue(&async
->wait_head
, &wait
);
1663 while (nbytes
> 0 && !retval
) {
1664 set_current_state(TASK_INTERRUPTIBLE
);
1668 m
= comedi_buf_read_n_available(async
);
1669 /* printk("%d available\n",m); */
1670 if (async
->buf_read_ptr
+ m
> async
->prealloc_bufsz
)
1671 m
= async
->prealloc_bufsz
- async
->buf_read_ptr
;
1672 /* printk("%d contiguous\n",m); */
1677 if (!(comedi_get_subdevice_runflags(s
) & SRF_RUNNING
)) {
1678 do_become_nonbusy(dev
, s
);
1679 if (comedi_get_subdevice_runflags(s
) &
1687 if (file
->f_flags
& O_NONBLOCK
) {
1691 if (signal_pending(current
)) {
1692 retval
= -ERESTARTSYS
;
1700 if (s
->busy
!= file
) {
1706 m
= copy_to_user(buf
, async
->prealloc_buf
+
1707 async
->buf_read_ptr
, n
);
1713 comedi_buf_read_alloc(async
, n
);
1714 comedi_buf_read_free(async
, n
);
1720 break; /* makes device work like a pipe */
1722 if (!(comedi_get_subdevice_runflags(s
) & (SRF_ERROR
| SRF_RUNNING
)) &&
1723 async
->buf_read_count
- async
->buf_write_count
== 0) {
1724 do_become_nonbusy(dev
, s
);
1726 set_current_state(TASK_RUNNING
);
1727 remove_wait_queue(&async
->wait_head
, &wait
);
1730 return count
? count
: retval
;
1734 This function restores a subdevice to an idle state.
1736 void do_become_nonbusy(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
1738 struct comedi_async
*async
= s
->async
;
1740 comedi_set_subdevice_runflags(s
, SRF_RUNNING
, 0);
1741 #ifdef CONFIG_COMEDI_RT
1742 if (comedi_get_subdevice_runflags(s
) & SRF_RT
) {
1743 comedi_switch_to_non_rt(dev
);
1744 comedi_set_subdevice_runflags(s
, SRF_RT
, 0);
1748 comedi_reset_async_buf(async
);
1749 async
->inttrig
= NULL
;
1752 "BUG: (?) do_become_nonbusy called with async=0\n");
1758 static int comedi_open(struct inode
*inode
, struct file
*file
)
1760 const unsigned minor
= iminor(inode
);
1761 struct comedi_device_file_info
*dev_file_info
=
1762 comedi_get_device_file_info(minor
);
1763 struct comedi_device
*dev
= dev_file_info
? dev_file_info
->device
: NULL
;
1766 DPRINTK("invalid minor number\n");
1770 /* This is slightly hacky, but we want module autoloading
1772 * case: user opens device, attached -> ok
1773 * case: user opens device, unattached, in_request_module=0 -> autoload
1774 * case: user opens device, unattached, in_request_module=1 -> fail
1775 * case: root opens device, attached -> ok
1776 * case: root opens device, unattached, in_request_module=1 -> ok
1777 * (typically called from modprobe)
1778 * case: root opens device, unattached, in_request_module=0 -> autoload
1780 * The last could be changed to "-> ok", which would deny root
1783 mutex_lock(&dev
->mutex
);
1786 if (!capable(CAP_SYS_MODULE
) && dev
->in_request_module
) {
1787 DPRINTK("in request module\n");
1788 mutex_unlock(&dev
->mutex
);
1791 if (capable(CAP_SYS_MODULE
) && dev
->in_request_module
)
1794 dev
->in_request_module
= 1;
1797 mutex_unlock(&dev
->mutex
);
1798 request_module("char-major-%i-%i", COMEDI_MAJOR
, dev
->minor
);
1799 mutex_lock(&dev
->mutex
);
1802 dev
->in_request_module
= 0;
1804 if (!dev
->attached
&& !capable(CAP_SYS_MODULE
)) {
1805 DPRINTK("not attached and not CAP_SYS_MODULE\n");
1806 mutex_unlock(&dev
->mutex
);
1810 __module_get(THIS_MODULE
);
1812 if (dev
->attached
) {
1813 if (!try_module_get(dev
->driver
->module
)) {
1814 module_put(THIS_MODULE
);
1815 mutex_unlock(&dev
->mutex
);
1820 if (dev
->attached
&& dev
->use_count
== 0 && dev
->open
)
1825 mutex_unlock(&dev
->mutex
);
1830 static int comedi_close(struct inode
*inode
, struct file
*file
)
1832 const unsigned minor
= iminor(inode
);
1833 struct comedi_device_file_info
*dev_file_info
=
1834 comedi_get_device_file_info(minor
);
1835 struct comedi_device
*dev
= dev_file_info
->device
;
1836 struct comedi_subdevice
*s
= NULL
;
1839 mutex_lock(&dev
->mutex
);
1841 if (dev
->subdevices
) {
1842 for (i
= 0; i
< dev
->n_subdevices
; i
++) {
1843 s
= dev
->subdevices
+ i
;
1845 if (s
->busy
== file
)
1847 if (s
->lock
== file
)
1851 if (dev
->attached
&& dev
->use_count
== 1 && dev
->close
)
1854 module_put(THIS_MODULE
);
1856 module_put(dev
->driver
->module
);
1860 mutex_unlock(&dev
->mutex
);
1862 if (file
->f_flags
& FASYNC
)
1863 comedi_fasync(-1, file
, 0);
1868 static int comedi_fasync(int fd
, struct file
*file
, int on
)
1870 const unsigned minor
= iminor(file
->f_dentry
->d_inode
);
1871 struct comedi_device_file_info
*dev_file_info
=
1872 comedi_get_device_file_info(minor
);
1874 struct comedi_device
*dev
= dev_file_info
->device
;
1876 return fasync_helper(fd
, file
, on
, &dev
->async_queue
);
1879 const struct file_operations comedi_fops
= {
1880 .owner
= THIS_MODULE
,
1881 #ifdef HAVE_UNLOCKED_IOCTL
1882 .unlocked_ioctl
= comedi_unlocked_ioctl
,
1884 .ioctl
= comedi_ioctl
,
1886 #ifdef HAVE_COMPAT_IOCTL
1887 .compat_ioctl
= comedi_compat_ioctl
,
1889 .open
= comedi_open
,
1890 .release
= comedi_close
,
1891 .read
= comedi_read
,
1892 .write
= comedi_write
,
1893 .mmap
= comedi_mmap
,
1894 .poll
= comedi_poll
,
1895 .fasync
= comedi_fasync
,
1898 struct class *comedi_class
;
1899 static struct cdev comedi_cdev
;
1901 static void comedi_cleanup_legacy_minors(void)
1905 for (i
= 0; i
< comedi_num_legacy_minors
; i
++)
1906 comedi_free_board_minor(i
);
1909 static int __init
comedi_init(void)
1914 printk(KERN_INFO
"comedi: version " COMEDI_RELEASE
1915 " - http://www.comedi.org\n");
1917 if (comedi_num_legacy_minors
< 0 ||
1918 comedi_num_legacy_minors
> COMEDI_NUM_BOARD_MINORS
) {
1919 printk(KERN_ERR
"comedi: error: invalid value for module "
1920 "parameter \"comedi_num_legacy_minors\". Valid values "
1921 "are 0 through %i.\n", COMEDI_NUM_BOARD_MINORS
);
1926 * comedi is unusable if both comedi_autoconfig and
1927 * comedi_num_legacy_minors are zero, so we might as well adjust the
1928 * defaults in that case
1930 if (comedi_autoconfig
== 0 && comedi_num_legacy_minors
== 0)
1931 comedi_num_legacy_minors
= 16;
1933 memset(comedi_file_info_table
, 0,
1934 sizeof(struct comedi_device_file_info
*) * COMEDI_NUM_MINORS
);
1936 retval
= register_chrdev_region(MKDEV(COMEDI_MAJOR
, 0),
1937 COMEDI_NUM_MINORS
, "comedi");
1940 cdev_init(&comedi_cdev
, &comedi_fops
);
1941 comedi_cdev
.owner
= THIS_MODULE
;
1942 kobject_set_name(&comedi_cdev
.kobj
, "comedi");
1943 if (cdev_add(&comedi_cdev
, MKDEV(COMEDI_MAJOR
, 0), COMEDI_NUM_MINORS
)) {
1944 unregister_chrdev_region(MKDEV(COMEDI_MAJOR
, 0),
1948 comedi_class
= class_create(THIS_MODULE
, "comedi");
1949 if (IS_ERR(comedi_class
)) {
1950 printk("comedi: failed to create class");
1951 cdev_del(&comedi_cdev
);
1952 unregister_chrdev_region(MKDEV(COMEDI_MAJOR
, 0),
1954 return PTR_ERR(comedi_class
);
1957 /* XXX requires /proc interface */
1960 /* create devices files for legacy/manual use */
1961 for (i
= 0; i
< comedi_num_legacy_minors
; i
++) {
1963 minor
= comedi_alloc_board_minor(NULL
);
1965 comedi_cleanup_legacy_minors();
1966 cdev_del(&comedi_cdev
);
1967 unregister_chrdev_region(MKDEV(COMEDI_MAJOR
, 0),
1975 comedi_register_ioctl32();
1980 static void __exit
comedi_cleanup(void)
1984 comedi_cleanup_legacy_minors();
1985 for (i
= 0; i
< COMEDI_NUM_MINORS
; ++i
)
1986 BUG_ON(comedi_file_info_table
[i
]);
1989 class_destroy(comedi_class
);
1990 cdev_del(&comedi_cdev
);
1991 unregister_chrdev_region(MKDEV(COMEDI_MAJOR
, 0), COMEDI_NUM_MINORS
);
1993 comedi_proc_cleanup();
1995 comedi_rt_cleanup();
1997 comedi_unregister_ioctl32();
2000 module_init(comedi_init
);
2001 module_exit(comedi_cleanup
);
2003 void comedi_error(const struct comedi_device
*dev
, const char *s
)
2005 rt_printk("comedi%d: %s: %s\n", dev
->minor
, dev
->driver
->driver_name
,
2009 void comedi_event(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
2011 struct comedi_async
*async
= s
->async
;
2012 unsigned runflags
= 0;
2013 unsigned runflags_mask
= 0;
2015 /* DPRINTK("comedi_event 0x%x\n",mask); */
2017 if ((comedi_get_subdevice_runflags(s
) & SRF_RUNNING
) == 0)
2021 events
& (COMEDI_CB_EOA
| COMEDI_CB_ERROR
| COMEDI_CB_OVERFLOW
)) {
2022 runflags_mask
|= SRF_RUNNING
;
2024 /* remember if an error event has occured, so an error
2025 * can be returned the next time the user does a read() */
2026 if (s
->async
->events
& (COMEDI_CB_ERROR
| COMEDI_CB_OVERFLOW
)) {
2027 runflags_mask
|= SRF_ERROR
;
2028 runflags
|= SRF_ERROR
;
2030 if (runflags_mask
) {
2031 /*sets SRF_ERROR and SRF_RUNNING together atomically */
2032 comedi_set_subdevice_runflags(s
, runflags_mask
, runflags
);
2035 if (async
->cb_mask
& s
->async
->events
) {
2036 if (comedi_get_subdevice_runflags(s
) & SRF_USER
) {
2039 #ifdef CONFIG_COMEDI_RT
2041 comedi_rt_pend_wakeup(&async
->wait_head
);
2044 ("BUG: comedi_event() code unreachable\n");
2047 wake_up_interruptible(&async
->wait_head
);
2048 if (s
->subdev_flags
& SDF_CMD_READ
) {
2049 kill_fasync(&dev
->async_queue
, SIGIO
,
2052 if (s
->subdev_flags
& SDF_CMD_WRITE
) {
2053 kill_fasync(&dev
->async_queue
, SIGIO
,
2059 async
->cb_func(s
->async
->events
, async
->cb_arg
);
2060 /* XXX bug here. If subdevice A is rt, and
2061 * subdevice B tries to callback to a normal
2062 * linux kernel function, it will be at the
2063 * wrong priority. Since this isn't very
2064 * common, I'm not going to worry about it. */
2067 s
->async
->events
= 0;
2070 void comedi_set_subdevice_runflags(struct comedi_subdevice
*s
, unsigned mask
,
2073 unsigned long flags
;
2075 comedi_spin_lock_irqsave(&s
->spin_lock
, flags
);
2076 s
->runflags
&= ~mask
;
2077 s
->runflags
|= (bits
& mask
);
2078 comedi_spin_unlock_irqrestore(&s
->spin_lock
, flags
);
2081 unsigned comedi_get_subdevice_runflags(struct comedi_subdevice
*s
)
2083 unsigned long flags
;
2086 comedi_spin_lock_irqsave(&s
->spin_lock
, flags
);
2087 runflags
= s
->runflags
;
2088 comedi_spin_unlock_irqrestore(&s
->spin_lock
, flags
);
2092 static int is_device_busy(struct comedi_device
*dev
)
2094 struct comedi_subdevice
*s
;
2100 for (i
= 0; i
< dev
->n_subdevices
; i
++) {
2101 s
= dev
->subdevices
+ i
;
2104 if (s
->async
&& s
->async
->mmap_count
)
2111 void comedi_device_init(struct comedi_device
*dev
)
2113 memset(dev
, 0, sizeof(struct comedi_device
));
2114 spin_lock_init(&dev
->spinlock
);
2115 mutex_init(&dev
->mutex
);
2119 void comedi_device_cleanup(struct comedi_device
*dev
)
2123 mutex_lock(&dev
->mutex
);
2124 comedi_device_detach(dev
);
2125 mutex_unlock(&dev
->mutex
);
2126 mutex_destroy(&dev
->mutex
);
2129 int comedi_alloc_board_minor(struct device
*hardware_device
)
2131 unsigned long flags
;
2132 struct comedi_device_file_info
*info
;
2133 struct device
*csdev
;
2136 info
= kzalloc(sizeof(struct comedi_device_file_info
), GFP_KERNEL
);
2139 info
->device
= kzalloc(sizeof(struct comedi_device
), GFP_KERNEL
);
2140 if (info
->device
== NULL
) {
2144 comedi_device_init(info
->device
);
2145 comedi_spin_lock_irqsave(&comedi_file_info_table_lock
, flags
);
2146 for (i
= 0; i
< COMEDI_NUM_BOARD_MINORS
; ++i
) {
2147 if (comedi_file_info_table
[i
] == NULL
) {
2148 comedi_file_info_table
[i
] = info
;
2152 comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock
, flags
);
2153 if (i
== COMEDI_NUM_BOARD_MINORS
) {
2154 comedi_device_cleanup(info
->device
);
2155 kfree(info
->device
);
2158 ("comedi: error: ran out of minor numbers for board device files.\n");
2161 info
->device
->minor
= i
;
2162 csdev
= COMEDI_DEVICE_CREATE(comedi_class
, NULL
,
2163 MKDEV(COMEDI_MAJOR
, i
), NULL
,
2164 hardware_device
, "comedi%i", i
);
2166 info
->device
->class_dev
= csdev
;
2171 void comedi_free_board_minor(unsigned minor
)
2173 unsigned long flags
;
2174 struct comedi_device_file_info
*info
;
2176 BUG_ON(minor
>= COMEDI_NUM_BOARD_MINORS
);
2177 comedi_spin_lock_irqsave(&comedi_file_info_table_lock
, flags
);
2178 info
= comedi_file_info_table
[minor
];
2179 comedi_file_info_table
[minor
] = NULL
;
2180 comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock
, flags
);
2183 struct comedi_device
*dev
= info
->device
;
2185 if (dev
->class_dev
) {
2186 device_destroy(comedi_class
,
2187 MKDEV(COMEDI_MAJOR
, dev
->minor
));
2189 comedi_device_cleanup(dev
);
2196 int comedi_alloc_subdevice_minor(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
2198 unsigned long flags
;
2199 struct comedi_device_file_info
*info
;
2200 struct device
*csdev
;
2203 info
= kmalloc(sizeof(struct comedi_device_file_info
), GFP_KERNEL
);
2207 info
->read_subdevice
= s
;
2208 info
->write_subdevice
= s
;
2209 comedi_spin_lock_irqsave(&comedi_file_info_table_lock
, flags
);
2210 for (i
= COMEDI_FIRST_SUBDEVICE_MINOR
; i
< COMEDI_NUM_MINORS
; ++i
) {
2211 if (comedi_file_info_table
[i
] == NULL
) {
2212 comedi_file_info_table
[i
] = info
;
2216 comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock
, flags
);
2217 if (i
== COMEDI_NUM_MINORS
) {
2220 ("comedi: error: ran out of minor numbers for board device files.\n");
2224 csdev
= COMEDI_DEVICE_CREATE(comedi_class
, dev
->class_dev
,
2225 MKDEV(COMEDI_MAJOR
, i
), NULL
, NULL
,
2226 "comedi%i_subd%i", dev
->minor
,
2227 (int)(s
- dev
->subdevices
));
2229 s
->class_dev
= csdev
;
2234 void comedi_free_subdevice_minor(struct comedi_subdevice
*s
)
2236 unsigned long flags
;
2237 struct comedi_device_file_info
*info
;
2244 BUG_ON(s
->minor
>= COMEDI_NUM_MINORS
);
2245 BUG_ON(s
->minor
< COMEDI_FIRST_SUBDEVICE_MINOR
);
2247 comedi_spin_lock_irqsave(&comedi_file_info_table_lock
, flags
);
2248 info
= comedi_file_info_table
[s
->minor
];
2249 comedi_file_info_table
[s
->minor
] = NULL
;
2250 comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock
, flags
);
2253 device_destroy(comedi_class
, MKDEV(COMEDI_MAJOR
, s
->minor
));
2254 s
->class_dev
= NULL
;
2259 struct comedi_device_file_info
*comedi_get_device_file_info(unsigned minor
)
2261 unsigned long flags
;
2262 struct comedi_device_file_info
*info
;
2264 BUG_ON(minor
>= COMEDI_NUM_MINORS
);
2265 comedi_spin_lock_irqsave(&comedi_file_info_table_lock
, flags
);
2266 info
= comedi_file_info_table
[minor
];
2267 comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock
, flags
);