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>
47 #include <linux/stat.h>
50 #include <linux/uaccess.h>
52 /* #include "kvmem.h" */
54 MODULE_AUTHOR("http://www.comedi.org");
55 MODULE_DESCRIPTION("Comedi core module");
56 MODULE_LICENSE("GPL");
58 #ifdef CONFIG_COMEDI_DEBUG
60 module_param(comedi_debug
, int, 0644);
63 int comedi_autoconfig
= 1;
64 module_param(comedi_autoconfig
, bool, 0444);
66 int comedi_num_legacy_minors
= 0;
67 module_param(comedi_num_legacy_minors
, int, 0444);
69 static DEFINE_SPINLOCK(comedi_file_info_table_lock
);
70 static struct comedi_device_file_info
71 *comedi_file_info_table
[COMEDI_NUM_MINORS
];
73 static int do_devconfig_ioctl(struct comedi_device
*dev
,
74 struct comedi_devconfig
*arg
);
75 static int do_bufconfig_ioctl(struct comedi_device
*dev
, void *arg
);
76 static int do_devinfo_ioctl(struct comedi_device
*dev
,
77 struct comedi_devinfo
*arg
, struct file
*file
);
78 static int do_subdinfo_ioctl(struct comedi_device
*dev
,
79 struct comedi_subdinfo
*arg
, void *file
);
80 static int do_chaninfo_ioctl(struct comedi_device
*dev
,
81 struct comedi_chaninfo
*arg
);
82 static int do_bufinfo_ioctl(struct comedi_device
*dev
, void *arg
);
83 static int do_cmd_ioctl(struct comedi_device
*dev
, void *arg
, void *file
);
84 static int do_lock_ioctl(struct comedi_device
*dev
, unsigned int arg
,
86 static int do_unlock_ioctl(struct comedi_device
*dev
, unsigned int arg
,
88 static int do_cancel_ioctl(struct comedi_device
*dev
, unsigned int arg
,
90 static int do_cmdtest_ioctl(struct comedi_device
*dev
, void *arg
, void *file
);
91 static int do_insnlist_ioctl(struct comedi_device
*dev
, void *arg
, void *file
);
92 static int do_insn_ioctl(struct comedi_device
*dev
, void *arg
, void *file
);
93 static int do_poll_ioctl(struct comedi_device
*dev
, unsigned int subd
,
96 extern void do_become_nonbusy(struct comedi_device
*dev
,
97 struct comedi_subdevice
*s
);
98 static int do_cancel(struct comedi_device
*dev
, struct comedi_subdevice
*s
);
100 static int comedi_fasync(int fd
, struct file
*file
, int on
);
102 static int is_device_busy(struct comedi_device
*dev
);
103 static int resize_async_buffer(struct comedi_device
*dev
,
104 struct comedi_subdevice
*s
,
105 struct comedi_async
*async
, unsigned new_size
);
107 /* declarations for sysfs attribute files */
108 static struct device_attribute dev_attr_max_read_buffer_kb
;
109 static struct device_attribute dev_attr_read_buffer_kb
;
110 static struct device_attribute dev_attr_max_write_buffer_kb
;
111 static struct device_attribute dev_attr_write_buffer_kb
;
113 #ifdef HAVE_UNLOCKED_IOCTL
114 static long comedi_unlocked_ioctl(struct file
*file
, unsigned int cmd
,
117 static int comedi_ioctl(struct inode
*inode
, struct file
*file
,
118 unsigned int cmd
, unsigned long arg
)
121 const unsigned minor
= iminor(file
->f_dentry
->d_inode
);
122 struct comedi_device_file_info
*dev_file_info
=
123 comedi_get_device_file_info(minor
);
124 struct comedi_device
*dev
;
127 if (dev_file_info
== NULL
|| dev_file_info
->device
== NULL
)
129 dev
= dev_file_info
->device
;
131 mutex_lock(&dev
->mutex
);
133 /* Device config is special, because it must work on
134 * an unconfigured device. */
135 if (cmd
== COMEDI_DEVCONFIG
) {
136 rc
= do_devconfig_ioctl(dev
, (void *)arg
);
140 if (!dev
->attached
) {
141 DPRINTK("no driver configured on /dev/comedi%i\n", dev
->minor
);
147 case COMEDI_BUFCONFIG
:
148 rc
= do_bufconfig_ioctl(dev
, (void *)arg
);
151 rc
= do_devinfo_ioctl(dev
, (void *)arg
, file
);
153 case COMEDI_SUBDINFO
:
154 rc
= do_subdinfo_ioctl(dev
, (void *)arg
, file
);
156 case COMEDI_CHANINFO
:
157 rc
= do_chaninfo_ioctl(dev
, (void *)arg
);
159 case COMEDI_RANGEINFO
:
160 rc
= do_rangeinfo_ioctl(dev
, (void *)arg
);
163 rc
= do_bufinfo_ioctl(dev
, (void *)arg
);
166 rc
= do_lock_ioctl(dev
, arg
, file
);
169 rc
= do_unlock_ioctl(dev
, arg
, file
);
172 rc
= do_cancel_ioctl(dev
, arg
, file
);
175 rc
= do_cmd_ioctl(dev
, (void *)arg
, file
);
178 rc
= do_cmdtest_ioctl(dev
, (void *)arg
, file
);
180 case COMEDI_INSNLIST
:
181 rc
= do_insnlist_ioctl(dev
, (void *)arg
, file
);
184 rc
= do_insn_ioctl(dev
, (void *)arg
, file
);
187 rc
= do_poll_ioctl(dev
, arg
, file
);
195 mutex_unlock(&dev
->mutex
);
204 pointer to devconfig structure
207 devconfig structure at arg
212 static int do_devconfig_ioctl(struct comedi_device
*dev
,
213 struct comedi_devconfig
*arg
)
215 struct comedi_devconfig it
;
217 unsigned char *aux_data
= NULL
;
220 if (!capable(CAP_SYS_ADMIN
))
224 if (is_device_busy(dev
))
227 struct module
*driver_module
= dev
->driver
->module
;
228 comedi_device_detach(dev
);
229 module_put(driver_module
);
234 if (copy_from_user(&it
, arg
, sizeof(struct comedi_devconfig
)))
237 it
.board_name
[COMEDI_NAMELEN
- 1] = 0;
239 if (comedi_aux_data(it
.options
, 0) &&
240 it
.options
[COMEDI_DEVCONF_AUX_DATA_LENGTH
]) {
242 aux_len
= it
.options
[COMEDI_DEVCONF_AUX_DATA_LENGTH
];
246 aux_data
= vmalloc(aux_len
);
250 if (copy_from_user(aux_data
,
251 comedi_aux_data(it
.options
, 0), aux_len
)) {
255 it
.options
[COMEDI_DEVCONF_AUX_DATA_LO
] =
256 (unsigned long)aux_data
;
257 if (sizeof(void *) > sizeof(int)) {
258 bit_shift
= sizeof(int) * 8;
259 it
.options
[COMEDI_DEVCONF_AUX_DATA_HI
] =
260 ((unsigned long)aux_data
) >> bit_shift
;
262 it
.options
[COMEDI_DEVCONF_AUX_DATA_HI
] = 0;
265 ret
= comedi_device_attach(dev
, &it
);
267 if (!try_module_get(dev
->driver
->module
)) {
268 comedi_device_detach(dev
);
281 buffer configuration ioctl
284 pointer to bufconfig structure
290 modified bufconfig at arg
293 static int do_bufconfig_ioctl(struct comedi_device
*dev
, void *arg
)
295 struct comedi_bufconfig bc
;
296 struct comedi_async
*async
;
297 struct comedi_subdevice
*s
;
300 if (copy_from_user(&bc
, arg
, sizeof(struct comedi_bufconfig
)))
303 if (bc
.subdevice
>= dev
->n_subdevices
|| bc
.subdevice
< 0)
306 s
= dev
->subdevices
+ bc
.subdevice
;
310 DPRINTK("subdevice does not have async capability\n");
316 if (bc
.maximum_size
) {
317 if (!capable(CAP_SYS_ADMIN
))
320 async
->max_bufsize
= bc
.maximum_size
;
324 retval
= resize_async_buffer(dev
, s
, async
, bc
.size
);
329 bc
.size
= async
->prealloc_bufsz
;
330 bc
.maximum_size
= async
->max_bufsize
;
333 if (copy_to_user(arg
, &bc
, sizeof(struct comedi_bufconfig
)))
344 pointer to devinfo structure
353 static int do_devinfo_ioctl(struct comedi_device
*dev
,
354 struct comedi_devinfo
*arg
, struct file
*file
)
356 struct comedi_devinfo devinfo
;
357 const unsigned minor
= iminor(file
->f_dentry
->d_inode
);
358 struct comedi_device_file_info
*dev_file_info
=
359 comedi_get_device_file_info(minor
);
360 struct comedi_subdevice
*read_subdev
=
361 comedi_get_read_subdevice(dev_file_info
);
362 struct comedi_subdevice
*write_subdev
=
363 comedi_get_write_subdevice(dev_file_info
);
365 memset(&devinfo
, 0, sizeof(devinfo
));
367 /* fill devinfo structure */
368 devinfo
.version_code
= COMEDI_VERSION_CODE
;
369 devinfo
.n_subdevs
= dev
->n_subdevices
;
370 memcpy(devinfo
.driver_name
, dev
->driver
->driver_name
, COMEDI_NAMELEN
);
371 memcpy(devinfo
.board_name
, dev
->board_name
, COMEDI_NAMELEN
);
374 devinfo
.read_subdevice
= read_subdev
- dev
->subdevices
;
376 devinfo
.read_subdevice
= -1;
379 devinfo
.write_subdevice
= write_subdev
- dev
->subdevices
;
381 devinfo
.write_subdevice
= -1;
383 if (copy_to_user(arg
, &devinfo
, sizeof(struct comedi_devinfo
)))
394 pointer to array of subdevice info structures
400 array of subdevice info structures at arg
403 static int do_subdinfo_ioctl(struct comedi_device
*dev
,
404 struct comedi_subdinfo
*arg
, void *file
)
407 struct comedi_subdinfo
*tmp
, *us
;
408 struct comedi_subdevice
*s
;
411 kcalloc(dev
->n_subdevices
, sizeof(struct comedi_subdinfo
),
416 /* fill subdinfo structs */
417 for (i
= 0; i
< dev
->n_subdevices
; i
++) {
418 s
= dev
->subdevices
+ i
;
422 us
->n_chan
= s
->n_chan
;
423 us
->subd_flags
= s
->subdev_flags
;
424 if (comedi_get_subdevice_runflags(s
) & SRF_RUNNING
)
425 us
->subd_flags
|= SDF_RUNNING
;
426 #define TIMER_nanosec 5 /* backwards compatibility */
427 us
->timer_type
= TIMER_nanosec
;
428 us
->len_chanlist
= s
->len_chanlist
;
429 us
->maxdata
= s
->maxdata
;
430 if (s
->range_table
) {
432 (i
<< 24) | (0 << 16) | (s
->range_table
->length
);
434 us
->range_type
= 0; /* XXX */
436 us
->flags
= s
->flags
;
439 us
->subd_flags
|= SDF_BUSY
;
441 us
->subd_flags
|= SDF_BUSY_OWNER
;
443 us
->subd_flags
|= SDF_LOCKED
;
445 us
->subd_flags
|= SDF_LOCK_OWNER
;
446 if (!s
->maxdata
&& s
->maxdata_list
)
447 us
->subd_flags
|= SDF_MAXDATA
;
449 us
->subd_flags
|= SDF_FLAGS
;
450 if (s
->range_table_list
)
451 us
->subd_flags
|= SDF_RANGETYPE
;
453 us
->subd_flags
|= SDF_CMD
;
455 if (s
->insn_bits
!= &insn_inval
)
456 us
->insn_bits_support
= COMEDI_SUPPORTED
;
458 us
->insn_bits_support
= COMEDI_UNSUPPORTED
;
460 us
->settling_time_0
= s
->settling_time_0
;
463 ret
= copy_to_user(arg
, tmp
,
464 dev
->n_subdevices
* sizeof(struct comedi_subdinfo
));
468 return ret
? -EFAULT
: 0;
476 pointer to chaninfo structure
479 chaninfo structure at arg
482 arrays at elements of chaninfo structure
485 static int do_chaninfo_ioctl(struct comedi_device
*dev
,
486 struct comedi_chaninfo
*arg
)
488 struct comedi_subdevice
*s
;
489 struct comedi_chaninfo it
;
491 if (copy_from_user(&it
, arg
, sizeof(struct comedi_chaninfo
)))
494 if (it
.subdev
>= dev
->n_subdevices
)
496 s
= dev
->subdevices
+ it
.subdev
;
498 if (it
.maxdata_list
) {
499 if (s
->maxdata
|| !s
->maxdata_list
)
501 if (copy_to_user(it
.maxdata_list
, s
->maxdata_list
,
502 s
->n_chan
* sizeof(unsigned int)))
509 if (copy_to_user(it
.flaglist
, s
->flaglist
,
510 s
->n_chan
* sizeof(unsigned int)))
517 if (!s
->range_table_list
)
519 for (i
= 0; i
< s
->n_chan
; i
++) {
522 x
= (dev
->minor
<< 28) | (it
.subdev
<< 24) | (i
<< 16) |
523 (s
->range_table_list
[i
]->length
);
524 put_user(x
, it
.rangelist
+ i
);
527 if (copy_to_user(it
.rangelist
, s
->range_type_list
,
528 s
->n_chan
* sizeof(unsigned int)))
538 buffer information ioctl
541 pointer to bufinfo structure
547 modified bufinfo at arg
550 static int do_bufinfo_ioctl(struct comedi_device
*dev
, void *arg
)
552 struct comedi_bufinfo bi
;
553 struct comedi_subdevice
*s
;
554 struct comedi_async
*async
;
556 if (copy_from_user(&bi
, arg
, sizeof(struct comedi_bufinfo
)))
559 if (bi
.subdevice
>= dev
->n_subdevices
|| bi
.subdevice
< 0)
562 s
= dev
->subdevices
+ bi
.subdevice
;
566 DPRINTK("subdevice does not have async capability\n");
567 bi
.buf_write_ptr
= 0;
569 bi
.buf_write_count
= 0;
570 bi
.buf_read_count
= 0;
574 if (bi
.bytes_read
&& (s
->subdev_flags
& SDF_CMD_READ
)) {
575 bi
.bytes_read
= comedi_buf_read_alloc(async
, bi
.bytes_read
);
576 comedi_buf_read_free(async
, bi
.bytes_read
);
578 if (!(comedi_get_subdevice_runflags(s
) & (SRF_ERROR
|
580 && async
->buf_write_count
== async
->buf_read_count
) {
581 do_become_nonbusy(dev
, s
);
585 if (bi
.bytes_written
&& (s
->subdev_flags
& SDF_CMD_WRITE
)) {
587 comedi_buf_write_alloc(async
, bi
.bytes_written
);
588 comedi_buf_write_free(async
, bi
.bytes_written
);
591 bi
.buf_write_count
= async
->buf_write_count
;
592 bi
.buf_write_ptr
= async
->buf_write_ptr
;
593 bi
.buf_read_count
= async
->buf_read_count
;
594 bi
.buf_read_ptr
= async
->buf_read_ptr
;
597 if (copy_to_user(arg
, &bi
, sizeof(struct comedi_bufinfo
)))
603 static int parse_insn(struct comedi_device
*dev
, struct comedi_insn
*insn
,
604 unsigned int *data
, void *file
);
607 * synchronous instructions
610 * pointer to sync cmd structure
613 * sync cmd struct at arg
620 /* arbitrary limits */
621 #define MAX_SAMPLES 256
622 static int do_insnlist_ioctl(struct comedi_device
*dev
, void *arg
, void *file
)
624 struct comedi_insnlist insnlist
;
625 struct comedi_insn
*insns
= NULL
;
626 unsigned int *data
= NULL
;
630 if (copy_from_user(&insnlist
, arg
, sizeof(struct comedi_insnlist
)))
633 data
= kmalloc(sizeof(unsigned int) * MAX_SAMPLES
, GFP_KERNEL
);
635 DPRINTK("kmalloc failed\n");
641 kmalloc(sizeof(struct comedi_insn
) * insnlist
.n_insns
, GFP_KERNEL
);
643 DPRINTK("kmalloc failed\n");
648 if (copy_from_user(insns
, insnlist
.insns
,
649 sizeof(struct comedi_insn
) * insnlist
.n_insns
)) {
650 DPRINTK("copy_from_user failed\n");
655 for (i
= 0; i
< insnlist
.n_insns
; i
++) {
656 if (insns
[i
].n
> MAX_SAMPLES
) {
657 DPRINTK("number of samples too large\n");
661 if (insns
[i
].insn
& INSN_MASK_WRITE
) {
662 if (copy_from_user(data
, insns
[i
].data
,
663 insns
[i
].n
* sizeof(unsigned int))) {
664 DPRINTK("copy_from_user failed\n");
669 ret
= parse_insn(dev
, insns
+ i
, data
, file
);
672 if (insns
[i
].insn
& INSN_MASK_READ
) {
673 if (copy_to_user(insns
[i
].data
, data
,
674 insns
[i
].n
* sizeof(unsigned int))) {
675 DPRINTK("copy_to_user failed\n");
693 static int check_insn_config_length(struct comedi_insn
*insn
,
700 case INSN_CONFIG_DIO_OUTPUT
:
701 case INSN_CONFIG_DIO_INPUT
:
702 case INSN_CONFIG_DISARM
:
703 case INSN_CONFIG_RESET
:
707 case INSN_CONFIG_ARM
:
708 case INSN_CONFIG_DIO_QUERY
:
709 case INSN_CONFIG_BLOCK_SIZE
:
710 case INSN_CONFIG_FILTER
:
711 case INSN_CONFIG_SERIAL_CLOCK
:
712 case INSN_CONFIG_BIDIRECTIONAL_DATA
:
713 case INSN_CONFIG_ALT_SOURCE
:
714 case INSN_CONFIG_SET_COUNTER_MODE
:
715 case INSN_CONFIG_8254_READ_STATUS
:
716 case INSN_CONFIG_SET_ROUTING
:
717 case INSN_CONFIG_GET_ROUTING
:
718 case INSN_CONFIG_GET_PWM_STATUS
:
719 case INSN_CONFIG_PWM_SET_PERIOD
:
720 case INSN_CONFIG_PWM_GET_PERIOD
:
724 case INSN_CONFIG_SET_GATE_SRC
:
725 case INSN_CONFIG_GET_GATE_SRC
:
726 case INSN_CONFIG_SET_CLOCK_SRC
:
727 case INSN_CONFIG_GET_CLOCK_SRC
:
728 case INSN_CONFIG_SET_OTHER_SRC
:
729 case INSN_CONFIG_GET_COUNTER_STATUS
:
730 case INSN_CONFIG_PWM_SET_H_BRIDGE
:
731 case INSN_CONFIG_PWM_GET_H_BRIDGE
:
732 case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE
:
736 case INSN_CONFIG_PWM_OUTPUT
:
737 case INSN_CONFIG_ANALOG_TRIG
:
741 /* by default we allow the insn since we don't have checks for
742 * all possible cases yet */
744 printk("comedi: no check for data length of config insn id "
745 "%i is implemented.\n"
746 " Add a check to %s in %s.\n"
747 " Assuming n=%i is correct.\n", data
[0], __func__
,
755 static int parse_insn(struct comedi_device
*dev
, struct comedi_insn
*insn
,
756 unsigned int *data
, void *file
)
758 struct comedi_subdevice
*s
;
762 if (insn
->insn
& INSN_MASK_SPECIAL
) {
763 /* a non-subdevice instruction */
765 switch (insn
->insn
) {
775 do_gettimeofday(&tv
);
777 data
[1] = tv
.tv_usec
;
783 if (insn
->n
!= 1 || data
[0] >= 100000) {
787 udelay(data
[0] / 1000);
795 if (insn
->subdev
>= dev
->n_subdevices
) {
796 DPRINTK("%d not usable subdevice\n",
801 s
= dev
->subdevices
+ insn
->subdev
;
803 DPRINTK("no async\n");
807 if (!s
->async
->inttrig
) {
808 DPRINTK("no inttrig\n");
812 ret
= s
->async
->inttrig(dev
, s
, insn
->data
[0]);
817 DPRINTK("invalid insn\n");
822 /* a subdevice instruction */
823 unsigned int maxdata
;
825 if (insn
->subdev
>= dev
->n_subdevices
) {
826 DPRINTK("subdevice %d out of range\n", insn
->subdev
);
830 s
= dev
->subdevices
+ insn
->subdev
;
832 if (s
->type
== COMEDI_SUBD_UNUSED
) {
833 DPRINTK("%d not usable subdevice\n", insn
->subdev
);
838 /* are we locked? (ioctl lock) */
839 if (s
->lock
&& s
->lock
!= file
) {
840 DPRINTK("device locked\n");
845 ret
= check_chanlist(s
, 1, &insn
->chanspec
);
848 DPRINTK("bad chanspec\n");
856 /* This looks arbitrary. It is. */
857 s
->busy
= &parse_insn
;
858 switch (insn
->insn
) {
860 ret
= s
->insn_read(dev
, s
, insn
, data
);
863 maxdata
= s
->maxdata_list
864 ? s
->maxdata_list
[CR_CHAN(insn
->chanspec
)]
866 for (i
= 0; i
< insn
->n
; ++i
) {
867 if (data
[i
] > maxdata
) {
869 DPRINTK("bad data value(s)\n");
874 ret
= s
->insn_write(dev
, s
, insn
, data
);
881 ret
= s
->insn_bits(dev
, s
, insn
, data
);
884 ret
= check_insn_config_length(insn
, data
);
887 ret
= s
->insn_config(dev
, s
, insn
, data
);
903 * synchronous instructions
909 * struct comedi_insn struct at arg
915 static int do_insn_ioctl(struct comedi_device
*dev
, void *arg
, void *file
)
917 struct comedi_insn insn
;
918 unsigned int *data
= NULL
;
921 data
= kmalloc(sizeof(unsigned int) * MAX_SAMPLES
, GFP_KERNEL
);
927 if (copy_from_user(&insn
, arg
, sizeof(struct comedi_insn
))) {
932 /* This is where the behavior of insn and insnlist deviate. */
933 if (insn
.n
> MAX_SAMPLES
)
934 insn
.n
= MAX_SAMPLES
;
935 if (insn
.insn
& INSN_MASK_WRITE
) {
937 (data
, insn
.data
, insn
.n
* sizeof(unsigned int))) {
942 ret
= parse_insn(dev
, &insn
, data
, file
);
945 if (insn
.insn
& INSN_MASK_READ
) {
947 (insn
.data
, data
, insn
.n
* sizeof(unsigned int))) {
965 pointer to cmd structure
972 modified cmd structure at arg
975 static int do_cmd_ioctl(struct comedi_device
*dev
, void *arg
, void *file
)
977 struct comedi_cmd user_cmd
;
978 struct comedi_subdevice
*s
;
979 struct comedi_async
*async
;
981 unsigned int *chanlist_saver
= NULL
;
983 if (copy_from_user(&user_cmd
, arg
, sizeof(struct comedi_cmd
))) {
984 DPRINTK("bad cmd address\n");
987 /* save user's chanlist pointer so it can be restored later */
988 chanlist_saver
= user_cmd
.chanlist
;
990 if (user_cmd
.subdev
>= dev
->n_subdevices
) {
991 DPRINTK("%d no such subdevice\n", user_cmd
.subdev
);
995 s
= dev
->subdevices
+ user_cmd
.subdev
;
998 if (s
->type
== COMEDI_SUBD_UNUSED
) {
999 DPRINTK("%d not valid subdevice\n", user_cmd
.subdev
);
1003 if (!s
->do_cmd
|| !s
->do_cmdtest
|| !s
->async
) {
1004 DPRINTK("subdevice %i does not support commands\n",
1009 /* are we locked? (ioctl lock) */
1010 if (s
->lock
&& s
->lock
!= file
) {
1011 DPRINTK("subdevice locked\n");
1017 DPRINTK("subdevice busy\n");
1022 /* make sure channel/gain list isn't too long */
1023 if (user_cmd
.chanlist_len
> s
->len_chanlist
) {
1024 DPRINTK("channel/gain list too long %u > %d\n",
1025 user_cmd
.chanlist_len
, s
->len_chanlist
);
1030 /* make sure channel/gain list isn't too short */
1031 if (user_cmd
.chanlist_len
< 1) {
1032 DPRINTK("channel/gain list too short %u < 1\n",
1033 user_cmd
.chanlist_len
);
1038 kfree(async
->cmd
.chanlist
);
1039 async
->cmd
= user_cmd
;
1040 async
->cmd
.data
= NULL
;
1041 /* load channel/gain list */
1042 async
->cmd
.chanlist
=
1043 kmalloc(async
->cmd
.chanlist_len
* sizeof(int), GFP_KERNEL
);
1044 if (!async
->cmd
.chanlist
) {
1045 DPRINTK("allocation failed\n");
1050 if (copy_from_user(async
->cmd
.chanlist
, user_cmd
.chanlist
,
1051 async
->cmd
.chanlist_len
* sizeof(int))) {
1052 DPRINTK("fault reading chanlist\n");
1057 /* make sure each element in channel/gain list is valid */
1058 ret
= check_chanlist(s
, async
->cmd
.chanlist_len
, async
->cmd
.chanlist
);
1060 DPRINTK("bad chanlist\n");
1064 ret
= s
->do_cmdtest(dev
, s
, &async
->cmd
);
1066 if (async
->cmd
.flags
& TRIG_BOGUS
|| ret
) {
1067 DPRINTK("test returned %d\n", ret
);
1068 user_cmd
= async
->cmd
;
1069 /* restore chanlist pointer before copying back */
1070 user_cmd
.chanlist
= chanlist_saver
;
1071 user_cmd
.data
= NULL
;
1072 if (copy_to_user(arg
, &user_cmd
, sizeof(struct comedi_cmd
))) {
1073 DPRINTK("fault writing cmd\n");
1081 if (!async
->prealloc_bufsz
) {
1083 DPRINTK("no buffer (?)\n");
1087 comedi_reset_async_buf(async
);
1090 COMEDI_CB_EOA
| COMEDI_CB_BLOCK
| COMEDI_CB_ERROR
|
1092 if (async
->cmd
.flags
& TRIG_WAKE_EOS
)
1093 async
->cb_mask
|= COMEDI_CB_EOS
;
1095 comedi_set_subdevice_runflags(s
, ~0, SRF_USER
| SRF_RUNNING
);
1097 ret
= s
->do_cmd(dev
, s
);
1102 do_become_nonbusy(dev
, s
);
1109 command testing ioctl
1112 pointer to cmd structure
1115 cmd structure at arg
1119 modified cmd structure at arg
1122 static int do_cmdtest_ioctl(struct comedi_device
*dev
, void *arg
, void *file
)
1124 struct comedi_cmd user_cmd
;
1125 struct comedi_subdevice
*s
;
1127 unsigned int *chanlist
= NULL
;
1128 unsigned int *chanlist_saver
= NULL
;
1130 if (copy_from_user(&user_cmd
, arg
, sizeof(struct comedi_cmd
))) {
1131 DPRINTK("bad cmd address\n");
1134 /* save user's chanlist pointer so it can be restored later */
1135 chanlist_saver
= user_cmd
.chanlist
;
1137 if (user_cmd
.subdev
>= dev
->n_subdevices
) {
1138 DPRINTK("%d no such subdevice\n", user_cmd
.subdev
);
1142 s
= dev
->subdevices
+ user_cmd
.subdev
;
1143 if (s
->type
== COMEDI_SUBD_UNUSED
) {
1144 DPRINTK("%d not valid subdevice\n", user_cmd
.subdev
);
1148 if (!s
->do_cmd
|| !s
->do_cmdtest
) {
1149 DPRINTK("subdevice %i does not support commands\n",
1154 /* make sure channel/gain list isn't too long */
1155 if (user_cmd
.chanlist_len
> s
->len_chanlist
) {
1156 DPRINTK("channel/gain list too long %d > %d\n",
1157 user_cmd
.chanlist_len
, s
->len_chanlist
);
1162 /* load channel/gain list */
1163 if (user_cmd
.chanlist
) {
1165 kmalloc(user_cmd
.chanlist_len
* sizeof(int), GFP_KERNEL
);
1167 DPRINTK("allocation failed\n");
1172 if (copy_from_user(chanlist
, user_cmd
.chanlist
,
1173 user_cmd
.chanlist_len
* sizeof(int))) {
1174 DPRINTK("fault reading chanlist\n");
1179 /* make sure each element in channel/gain list is valid */
1180 ret
= check_chanlist(s
, user_cmd
.chanlist_len
, chanlist
);
1182 DPRINTK("bad chanlist\n");
1186 user_cmd
.chanlist
= chanlist
;
1189 ret
= s
->do_cmdtest(dev
, s
, &user_cmd
);
1191 /* restore chanlist pointer before copying back */
1192 user_cmd
.chanlist
= chanlist_saver
;
1194 if (copy_to_user(arg
, &user_cmd
, sizeof(struct comedi_cmd
))) {
1195 DPRINTK("bad cmd address\n");
1220 static int do_lock_ioctl(struct comedi_device
*dev
, unsigned int arg
,
1224 unsigned long flags
;
1225 struct comedi_subdevice
*s
;
1227 if (arg
>= dev
->n_subdevices
)
1229 s
= dev
->subdevices
+ arg
;
1231 spin_lock_irqsave(&s
->spin_lock
, flags
);
1232 if (s
->busy
|| s
->lock
)
1236 spin_unlock_irqrestore(&s
->spin_lock
, flags
);
1243 ret
= s
->lock_f(dev
, s
);
1262 This function isn't protected by the semaphore, since
1263 we already own the lock.
1265 static int do_unlock_ioctl(struct comedi_device
*dev
, unsigned int arg
,
1268 struct comedi_subdevice
*s
;
1270 if (arg
>= dev
->n_subdevices
)
1272 s
= dev
->subdevices
+ arg
;
1277 if (s
->lock
&& s
->lock
!= file
)
1280 if (s
->lock
== file
) {
1294 cancel acquisition ioctl
1306 static int do_cancel_ioctl(struct comedi_device
*dev
, unsigned int arg
,
1309 struct comedi_subdevice
*s
;
1311 if (arg
>= dev
->n_subdevices
)
1313 s
= dev
->subdevices
+ arg
;
1314 if (s
->async
== NULL
)
1317 if (s
->lock
&& s
->lock
!= file
)
1323 if (s
->busy
!= file
)
1326 return do_cancel(dev
, s
);
1331 instructs driver to synchronize buffers
1343 static int do_poll_ioctl(struct comedi_device
*dev
, unsigned int arg
,
1346 struct comedi_subdevice
*s
;
1348 if (arg
>= dev
->n_subdevices
)
1350 s
= dev
->subdevices
+ arg
;
1352 if (s
->lock
&& s
->lock
!= file
)
1358 if (s
->busy
!= file
)
1362 return s
->poll(dev
, s
);
1367 static int do_cancel(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
1371 if ((comedi_get_subdevice_runflags(s
) & SRF_RUNNING
) && s
->cancel
)
1372 ret
= s
->cancel(dev
, s
);
1374 do_become_nonbusy(dev
, s
);
1379 void comedi_unmap(struct vm_area_struct
*area
)
1381 struct comedi_async
*async
;
1382 struct comedi_device
*dev
;
1384 async
= area
->vm_private_data
;
1385 dev
= async
->subdevice
->device
;
1387 mutex_lock(&dev
->mutex
);
1388 async
->mmap_count
--;
1389 mutex_unlock(&dev
->mutex
);
1392 static struct vm_operations_struct comedi_vm_ops
= {
1393 .close
= comedi_unmap
,
1396 static int comedi_mmap(struct file
*file
, struct vm_area_struct
*vma
)
1398 const unsigned minor
= iminor(file
->f_dentry
->d_inode
);
1399 struct comedi_device_file_info
*dev_file_info
=
1400 comedi_get_device_file_info(minor
);
1401 struct comedi_device
*dev
= dev_file_info
->device
;
1402 struct comedi_async
*async
= NULL
;
1403 unsigned long start
= vma
->vm_start
;
1408 struct comedi_subdevice
*s
;
1410 mutex_lock(&dev
->mutex
);
1411 if (!dev
->attached
) {
1412 DPRINTK("no driver configured on comedi%i\n", dev
->minor
);
1416 if (vma
->vm_flags
& VM_WRITE
)
1417 s
= comedi_get_write_subdevice(dev_file_info
);
1419 s
= comedi_get_read_subdevice(dev_file_info
);
1426 if (async
== NULL
) {
1431 if (vma
->vm_pgoff
!= 0) {
1432 DPRINTK("comedi: mmap() offset must be 0.\n");
1437 size
= vma
->vm_end
- vma
->vm_start
;
1438 if (size
> async
->prealloc_bufsz
) {
1442 if (size
& (~PAGE_MASK
)) {
1447 n_pages
= size
>> PAGE_SHIFT
;
1448 for (i
= 0; i
< n_pages
; ++i
) {
1449 if (remap_pfn_range(vma
, start
,
1450 page_to_pfn(virt_to_page
1451 (async
->buf_page_list
1452 [i
].virt_addr
)), PAGE_SIZE
,
1460 vma
->vm_ops
= &comedi_vm_ops
;
1461 vma
->vm_private_data
= async
;
1463 async
->mmap_count
++;
1467 mutex_unlock(&dev
->mutex
);
1471 static unsigned int comedi_poll(struct file
*file
, poll_table
* wait
)
1473 unsigned int mask
= 0;
1474 const unsigned minor
= iminor(file
->f_dentry
->d_inode
);
1475 struct comedi_device_file_info
*dev_file_info
=
1476 comedi_get_device_file_info(minor
);
1477 struct comedi_device
*dev
= dev_file_info
->device
;
1478 struct comedi_subdevice
*read_subdev
;
1479 struct comedi_subdevice
*write_subdev
;
1481 mutex_lock(&dev
->mutex
);
1482 if (!dev
->attached
) {
1483 DPRINTK("no driver configured on comedi%i\n", dev
->minor
);
1484 mutex_unlock(&dev
->mutex
);
1489 read_subdev
= comedi_get_read_subdevice(dev_file_info
);
1491 poll_wait(file
, &read_subdev
->async
->wait_head
, wait
);
1492 if (!read_subdev
->busy
1493 || comedi_buf_read_n_available(read_subdev
->async
) > 0
1494 || !(comedi_get_subdevice_runflags(read_subdev
) &
1496 mask
|= POLLIN
| POLLRDNORM
;
1499 write_subdev
= comedi_get_write_subdevice(dev_file_info
);
1501 poll_wait(file
, &write_subdev
->async
->wait_head
, wait
);
1502 comedi_buf_write_alloc(write_subdev
->async
,
1503 write_subdev
->async
->prealloc_bufsz
);
1504 if (!write_subdev
->busy
1505 || !(comedi_get_subdevice_runflags(write_subdev
) &
1507 || comedi_buf_write_n_allocated(write_subdev
->async
) >=
1508 bytes_per_sample(write_subdev
->async
->subdevice
)) {
1509 mask
|= POLLOUT
| POLLWRNORM
;
1513 mutex_unlock(&dev
->mutex
);
1517 static ssize_t
comedi_write(struct file
*file
, const char *buf
, size_t nbytes
,
1520 struct comedi_subdevice
*s
;
1521 struct comedi_async
*async
;
1522 int n
, m
, count
= 0, retval
= 0;
1523 DECLARE_WAITQUEUE(wait
, current
);
1524 const unsigned minor
= iminor(file
->f_dentry
->d_inode
);
1525 struct comedi_device_file_info
*dev_file_info
=
1526 comedi_get_device_file_info(minor
);
1527 struct comedi_device
*dev
= dev_file_info
->device
;
1529 if (!dev
->attached
) {
1530 DPRINTK("no driver configured on comedi%i\n", dev
->minor
);
1535 s
= comedi_get_write_subdevice(dev_file_info
);
1550 if (s
->busy
!= file
) {
1554 add_wait_queue(&async
->wait_head
, &wait
);
1555 while (nbytes
> 0 && !retval
) {
1556 set_current_state(TASK_INTERRUPTIBLE
);
1561 if (async
->buf_write_ptr
+ m
> async
->prealloc_bufsz
)
1562 m
= async
->prealloc_bufsz
- async
->buf_write_ptr
;
1563 comedi_buf_write_alloc(async
, async
->prealloc_bufsz
);
1564 if (m
> comedi_buf_write_n_allocated(async
))
1565 m
= comedi_buf_write_n_allocated(async
);
1570 if (!(comedi_get_subdevice_runflags(s
) & SRF_RUNNING
)) {
1571 if (comedi_get_subdevice_runflags(s
) &
1577 do_become_nonbusy(dev
, s
);
1580 if (file
->f_flags
& O_NONBLOCK
) {
1584 if (signal_pending(current
)) {
1585 retval
= -ERESTARTSYS
;
1591 if (s
->busy
!= file
) {
1598 m
= copy_from_user(async
->prealloc_buf
+ async
->buf_write_ptr
,
1604 comedi_buf_write_free(async
, n
);
1610 break; /* makes device work like a pipe */
1612 set_current_state(TASK_RUNNING
);
1613 remove_wait_queue(&async
->wait_head
, &wait
);
1616 return count
? count
: retval
;
1619 static ssize_t
comedi_read(struct file
*file
, char *buf
, size_t nbytes
,
1622 struct comedi_subdevice
*s
;
1623 struct comedi_async
*async
;
1624 int n
, m
, count
= 0, retval
= 0;
1625 DECLARE_WAITQUEUE(wait
, current
);
1626 const unsigned minor
= iminor(file
->f_dentry
->d_inode
);
1627 struct comedi_device_file_info
*dev_file_info
=
1628 comedi_get_device_file_info(minor
);
1629 struct comedi_device
*dev
= dev_file_info
->device
;
1631 if (!dev
->attached
) {
1632 DPRINTK("no driver configured on comedi%i\n", dev
->minor
);
1637 s
= comedi_get_read_subdevice(dev_file_info
);
1651 if (s
->busy
!= file
) {
1656 add_wait_queue(&async
->wait_head
, &wait
);
1657 while (nbytes
> 0 && !retval
) {
1658 set_current_state(TASK_INTERRUPTIBLE
);
1662 m
= comedi_buf_read_n_available(async
);
1663 /* printk("%d available\n",m); */
1664 if (async
->buf_read_ptr
+ m
> async
->prealloc_bufsz
)
1665 m
= async
->prealloc_bufsz
- async
->buf_read_ptr
;
1666 /* printk("%d contiguous\n",m); */
1671 if (!(comedi_get_subdevice_runflags(s
) & SRF_RUNNING
)) {
1672 do_become_nonbusy(dev
, s
);
1673 if (comedi_get_subdevice_runflags(s
) &
1681 if (file
->f_flags
& O_NONBLOCK
) {
1685 if (signal_pending(current
)) {
1686 retval
= -ERESTARTSYS
;
1694 if (s
->busy
!= file
) {
1700 m
= copy_to_user(buf
, async
->prealloc_buf
+
1701 async
->buf_read_ptr
, n
);
1707 comedi_buf_read_alloc(async
, n
);
1708 comedi_buf_read_free(async
, n
);
1714 break; /* makes device work like a pipe */
1716 if (!(comedi_get_subdevice_runflags(s
) & (SRF_ERROR
| SRF_RUNNING
)) &&
1717 async
->buf_read_count
- async
->buf_write_count
== 0) {
1718 do_become_nonbusy(dev
, s
);
1720 set_current_state(TASK_RUNNING
);
1721 remove_wait_queue(&async
->wait_head
, &wait
);
1724 return count
? count
: retval
;
1728 This function restores a subdevice to an idle state.
1730 void do_become_nonbusy(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
1732 struct comedi_async
*async
= s
->async
;
1734 comedi_set_subdevice_runflags(s
, SRF_RUNNING
, 0);
1736 comedi_reset_async_buf(async
);
1737 async
->inttrig
= NULL
;
1740 "BUG: (?) do_become_nonbusy called with async=0\n");
1746 static int comedi_open(struct inode
*inode
, struct file
*file
)
1748 const unsigned minor
= iminor(inode
);
1749 struct comedi_device_file_info
*dev_file_info
=
1750 comedi_get_device_file_info(minor
);
1751 struct comedi_device
*dev
=
1752 dev_file_info
? dev_file_info
->device
: NULL
;
1755 DPRINTK("invalid minor number\n");
1759 /* This is slightly hacky, but we want module autoloading
1761 * case: user opens device, attached -> ok
1762 * case: user opens device, unattached, in_request_module=0 -> autoload
1763 * case: user opens device, unattached, in_request_module=1 -> fail
1764 * case: root opens device, attached -> ok
1765 * case: root opens device, unattached, in_request_module=1 -> ok
1766 * (typically called from modprobe)
1767 * case: root opens device, unattached, in_request_module=0 -> autoload
1769 * The last could be changed to "-> ok", which would deny root
1772 mutex_lock(&dev
->mutex
);
1775 if (!capable(CAP_NET_ADMIN
) && dev
->in_request_module
) {
1776 DPRINTK("in request module\n");
1777 mutex_unlock(&dev
->mutex
);
1780 if (capable(CAP_NET_ADMIN
) && dev
->in_request_module
)
1783 dev
->in_request_module
= 1;
1786 mutex_unlock(&dev
->mutex
);
1787 request_module("char-major-%i-%i", COMEDI_MAJOR
, dev
->minor
);
1788 mutex_lock(&dev
->mutex
);
1791 dev
->in_request_module
= 0;
1793 if (!dev
->attached
&& !capable(CAP_NET_ADMIN
)) {
1794 DPRINTK("not attached and not CAP_NET_ADMIN\n");
1795 mutex_unlock(&dev
->mutex
);
1799 __module_get(THIS_MODULE
);
1801 if (dev
->attached
) {
1802 if (!try_module_get(dev
->driver
->module
)) {
1803 module_put(THIS_MODULE
);
1804 mutex_unlock(&dev
->mutex
);
1809 if (dev
->attached
&& dev
->use_count
== 0 && dev
->open
)
1814 mutex_unlock(&dev
->mutex
);
1819 static int comedi_close(struct inode
*inode
, struct file
*file
)
1821 const unsigned minor
= iminor(inode
);
1822 struct comedi_device_file_info
*dev_file_info
=
1823 comedi_get_device_file_info(minor
);
1824 struct comedi_device
*dev
= dev_file_info
->device
;
1825 struct comedi_subdevice
*s
= NULL
;
1828 mutex_lock(&dev
->mutex
);
1830 if (dev
->subdevices
) {
1831 for (i
= 0; i
< dev
->n_subdevices
; i
++) {
1832 s
= dev
->subdevices
+ i
;
1834 if (s
->busy
== file
)
1836 if (s
->lock
== file
)
1840 if (dev
->attached
&& dev
->use_count
== 1 && dev
->close
)
1843 module_put(THIS_MODULE
);
1845 module_put(dev
->driver
->module
);
1849 mutex_unlock(&dev
->mutex
);
1851 if (file
->f_flags
& FASYNC
)
1852 comedi_fasync(-1, file
, 0);
1857 static int comedi_fasync(int fd
, struct file
*file
, int on
)
1859 const unsigned minor
= iminor(file
->f_dentry
->d_inode
);
1860 struct comedi_device_file_info
*dev_file_info
=
1861 comedi_get_device_file_info(minor
);
1863 struct comedi_device
*dev
= dev_file_info
->device
;
1865 return fasync_helper(fd
, file
, on
, &dev
->async_queue
);
1868 const struct file_operations comedi_fops
= {
1869 .owner
= THIS_MODULE
,
1870 #ifdef HAVE_UNLOCKED_IOCTL
1871 .unlocked_ioctl
= comedi_unlocked_ioctl
,
1873 .ioctl
= comedi_ioctl
,
1875 #ifdef HAVE_COMPAT_IOCTL
1876 .compat_ioctl
= comedi_compat_ioctl
,
1878 .open
= comedi_open
,
1879 .release
= comedi_close
,
1880 .read
= comedi_read
,
1881 .write
= comedi_write
,
1882 .mmap
= comedi_mmap
,
1883 .poll
= comedi_poll
,
1884 .fasync
= comedi_fasync
,
1887 struct class *comedi_class
;
1888 static struct cdev comedi_cdev
;
1890 static void comedi_cleanup_legacy_minors(void)
1894 for (i
= 0; i
< comedi_num_legacy_minors
; i
++)
1895 comedi_free_board_minor(i
);
1898 static int __init
comedi_init(void)
1903 printk(KERN_INFO
"comedi: version " COMEDI_RELEASE
1904 " - http://www.comedi.org\n");
1906 if (comedi_num_legacy_minors
< 0 ||
1907 comedi_num_legacy_minors
> COMEDI_NUM_BOARD_MINORS
) {
1908 printk(KERN_ERR
"comedi: error: invalid value for module "
1909 "parameter \"comedi_num_legacy_minors\". Valid values "
1910 "are 0 through %i.\n", COMEDI_NUM_BOARD_MINORS
);
1915 * comedi is unusable if both comedi_autoconfig and
1916 * comedi_num_legacy_minors are zero, so we might as well adjust the
1917 * defaults in that case
1919 if (comedi_autoconfig
== 0 && comedi_num_legacy_minors
== 0)
1920 comedi_num_legacy_minors
= 16;
1922 memset(comedi_file_info_table
, 0,
1923 sizeof(struct comedi_device_file_info
*) * COMEDI_NUM_MINORS
);
1925 retval
= register_chrdev_region(MKDEV(COMEDI_MAJOR
, 0),
1926 COMEDI_NUM_MINORS
, "comedi");
1929 cdev_init(&comedi_cdev
, &comedi_fops
);
1930 comedi_cdev
.owner
= THIS_MODULE
;
1931 kobject_set_name(&comedi_cdev
.kobj
, "comedi");
1932 if (cdev_add(&comedi_cdev
, MKDEV(COMEDI_MAJOR
, 0), COMEDI_NUM_MINORS
)) {
1933 unregister_chrdev_region(MKDEV(COMEDI_MAJOR
, 0),
1937 comedi_class
= class_create(THIS_MODULE
, "comedi");
1938 if (IS_ERR(comedi_class
)) {
1939 printk("comedi: failed to create class");
1940 cdev_del(&comedi_cdev
);
1941 unregister_chrdev_region(MKDEV(COMEDI_MAJOR
, 0),
1943 return PTR_ERR(comedi_class
);
1946 /* XXX requires /proc interface */
1949 /* create devices files for legacy/manual use */
1950 for (i
= 0; i
< comedi_num_legacy_minors
; i
++) {
1952 minor
= comedi_alloc_board_minor(NULL
);
1954 comedi_cleanup_legacy_minors();
1955 cdev_del(&comedi_cdev
);
1956 unregister_chrdev_region(MKDEV(COMEDI_MAJOR
, 0),
1962 comedi_register_ioctl32();
1967 static void __exit
comedi_cleanup(void)
1971 comedi_cleanup_legacy_minors();
1972 for (i
= 0; i
< COMEDI_NUM_MINORS
; ++i
)
1973 BUG_ON(comedi_file_info_table
[i
]);
1975 class_destroy(comedi_class
);
1976 cdev_del(&comedi_cdev
);
1977 unregister_chrdev_region(MKDEV(COMEDI_MAJOR
, 0), COMEDI_NUM_MINORS
);
1979 comedi_proc_cleanup();
1981 comedi_unregister_ioctl32();
1984 module_init(comedi_init
);
1985 module_exit(comedi_cleanup
);
1987 void comedi_error(const struct comedi_device
*dev
, const char *s
)
1989 printk("comedi%d: %s: %s\n", dev
->minor
, dev
->driver
->driver_name
, s
);
1992 void comedi_event(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
1994 struct comedi_async
*async
= s
->async
;
1995 unsigned runflags
= 0;
1996 unsigned runflags_mask
= 0;
1998 /* DPRINTK("comedi_event 0x%x\n",mask); */
2000 if ((comedi_get_subdevice_runflags(s
) & SRF_RUNNING
) == 0)
2004 async
->events
& (COMEDI_CB_EOA
| COMEDI_CB_ERROR
|
2005 COMEDI_CB_OVERFLOW
)) {
2006 runflags_mask
|= SRF_RUNNING
;
2008 /* remember if an error event has occured, so an error
2009 * can be returned the next time the user does a read() */
2010 if (s
->async
->events
& (COMEDI_CB_ERROR
| COMEDI_CB_OVERFLOW
)) {
2011 runflags_mask
|= SRF_ERROR
;
2012 runflags
|= SRF_ERROR
;
2014 if (runflags_mask
) {
2015 /*sets SRF_ERROR and SRF_RUNNING together atomically */
2016 comedi_set_subdevice_runflags(s
, runflags_mask
, runflags
);
2019 if (async
->cb_mask
& s
->async
->events
) {
2020 if (comedi_get_subdevice_runflags(s
) & SRF_USER
) {
2021 wake_up_interruptible(&async
->wait_head
);
2022 if (s
->subdev_flags
& SDF_CMD_READ
) {
2023 kill_fasync(&dev
->async_queue
, SIGIO
, POLL_IN
);
2025 if (s
->subdev_flags
& SDF_CMD_WRITE
) {
2026 kill_fasync(&dev
->async_queue
, SIGIO
, POLL_OUT
);
2030 async
->cb_func(s
->async
->events
, async
->cb_arg
);
2033 s
->async
->events
= 0;
2036 void comedi_set_subdevice_runflags(struct comedi_subdevice
*s
, unsigned mask
,
2039 unsigned long flags
;
2041 spin_lock_irqsave(&s
->spin_lock
, flags
);
2042 s
->runflags
&= ~mask
;
2043 s
->runflags
|= (bits
& mask
);
2044 spin_unlock_irqrestore(&s
->spin_lock
, flags
);
2047 unsigned comedi_get_subdevice_runflags(struct comedi_subdevice
*s
)
2049 unsigned long flags
;
2052 spin_lock_irqsave(&s
->spin_lock
, flags
);
2053 runflags
= s
->runflags
;
2054 spin_unlock_irqrestore(&s
->spin_lock
, flags
);
2058 static int is_device_busy(struct comedi_device
*dev
)
2060 struct comedi_subdevice
*s
;
2066 for (i
= 0; i
< dev
->n_subdevices
; i
++) {
2067 s
= dev
->subdevices
+ i
;
2070 if (s
->async
&& s
->async
->mmap_count
)
2077 void comedi_device_init(struct comedi_device
*dev
)
2079 memset(dev
, 0, sizeof(struct comedi_device
));
2080 spin_lock_init(&dev
->spinlock
);
2081 mutex_init(&dev
->mutex
);
2085 void comedi_device_cleanup(struct comedi_device
*dev
)
2089 mutex_lock(&dev
->mutex
);
2090 comedi_device_detach(dev
);
2091 mutex_unlock(&dev
->mutex
);
2092 mutex_destroy(&dev
->mutex
);
2095 int comedi_alloc_board_minor(struct device
*hardware_device
)
2097 unsigned long flags
;
2098 struct comedi_device_file_info
*info
;
2099 struct device
*csdev
;
2103 info
= kzalloc(sizeof(struct comedi_device_file_info
), GFP_KERNEL
);
2106 info
->device
= kzalloc(sizeof(struct comedi_device
), GFP_KERNEL
);
2107 if (info
->device
== NULL
) {
2111 comedi_device_init(info
->device
);
2112 spin_lock_irqsave(&comedi_file_info_table_lock
, flags
);
2113 for (i
= 0; i
< COMEDI_NUM_BOARD_MINORS
; ++i
) {
2114 if (comedi_file_info_table
[i
] == NULL
) {
2115 comedi_file_info_table
[i
] = info
;
2119 spin_unlock_irqrestore(&comedi_file_info_table_lock
, flags
);
2120 if (i
== COMEDI_NUM_BOARD_MINORS
) {
2121 comedi_device_cleanup(info
->device
);
2122 kfree(info
->device
);
2125 "comedi: error: ran out of minor numbers for board device files.\n");
2128 info
->device
->minor
= i
;
2129 csdev
= COMEDI_DEVICE_CREATE(comedi_class
, NULL
,
2130 MKDEV(COMEDI_MAJOR
, i
), NULL
,
2131 hardware_device
, "comedi%i", i
);
2133 info
->device
->class_dev
= csdev
;
2134 dev_set_drvdata(csdev
, info
);
2135 retval
= device_create_file(csdev
, &dev_attr_max_read_buffer_kb
);
2138 "comedi: failed to create sysfs attribute file \"%s\".\n",
2139 dev_attr_max_read_buffer_kb
.attr
.name
);
2140 comedi_free_board_minor(i
);
2143 retval
= device_create_file(csdev
, &dev_attr_read_buffer_kb
);
2146 "comedi: failed to create sysfs attribute file \"%s\".\n",
2147 dev_attr_read_buffer_kb
.attr
.name
);
2148 comedi_free_board_minor(i
);
2151 retval
= device_create_file(csdev
, &dev_attr_max_write_buffer_kb
);
2154 "comedi: failed to create sysfs attribute file \"%s\".\n",
2155 dev_attr_max_write_buffer_kb
.attr
.name
);
2156 comedi_free_board_minor(i
);
2159 retval
= device_create_file(csdev
, &dev_attr_write_buffer_kb
);
2162 "comedi: failed to create sysfs attribute file \"%s\".\n",
2163 dev_attr_write_buffer_kb
.attr
.name
);
2164 comedi_free_board_minor(i
);
2170 void comedi_free_board_minor(unsigned minor
)
2172 unsigned long flags
;
2173 struct comedi_device_file_info
*info
;
2175 BUG_ON(minor
>= COMEDI_NUM_BOARD_MINORS
);
2176 spin_lock_irqsave(&comedi_file_info_table_lock
, flags
);
2177 info
= comedi_file_info_table
[minor
];
2178 comedi_file_info_table
[minor
] = NULL
;
2179 spin_unlock_irqrestore(&comedi_file_info_table_lock
, flags
);
2182 struct comedi_device
*dev
= info
->device
;
2184 if (dev
->class_dev
) {
2185 device_destroy(comedi_class
,
2186 MKDEV(COMEDI_MAJOR
, dev
->minor
));
2188 comedi_device_cleanup(dev
);
2195 int comedi_alloc_subdevice_minor(struct comedi_device
*dev
,
2196 struct comedi_subdevice
*s
)
2198 unsigned long flags
;
2199 struct comedi_device_file_info
*info
;
2200 struct device
*csdev
;
2204 info
= kmalloc(sizeof(struct comedi_device_file_info
), GFP_KERNEL
);
2208 info
->read_subdevice
= s
;
2209 info
->write_subdevice
= s
;
2210 spin_lock_irqsave(&comedi_file_info_table_lock
, flags
);
2211 for (i
= COMEDI_FIRST_SUBDEVICE_MINOR
; i
< COMEDI_NUM_MINORS
; ++i
) {
2212 if (comedi_file_info_table
[i
] == NULL
) {
2213 comedi_file_info_table
[i
] = info
;
2217 spin_unlock_irqrestore(&comedi_file_info_table_lock
, flags
);
2218 if (i
== COMEDI_NUM_MINORS
) {
2221 "comedi: error: ran out of minor numbers for board device files.\n");
2225 csdev
= COMEDI_DEVICE_CREATE(comedi_class
, dev
->class_dev
,
2226 MKDEV(COMEDI_MAJOR
, i
), NULL
, NULL
,
2227 "comedi%i_subd%i", dev
->minor
,
2228 (int)(s
- dev
->subdevices
));
2230 s
->class_dev
= csdev
;
2231 dev_set_drvdata(csdev
, info
);
2232 retval
= device_create_file(csdev
, &dev_attr_max_read_buffer_kb
);
2235 "comedi: failed to create sysfs attribute file \"%s\".\n",
2236 dev_attr_max_read_buffer_kb
.attr
.name
);
2237 comedi_free_subdevice_minor(s
);
2240 retval
= device_create_file(csdev
, &dev_attr_read_buffer_kb
);
2243 "comedi: failed to create sysfs attribute file \"%s\".\n",
2244 dev_attr_read_buffer_kb
.attr
.name
);
2245 comedi_free_subdevice_minor(s
);
2248 retval
= device_create_file(csdev
, &dev_attr_max_write_buffer_kb
);
2251 "comedi: failed to create sysfs attribute file \"%s\".\n",
2252 dev_attr_max_write_buffer_kb
.attr
.name
);
2253 comedi_free_subdevice_minor(s
);
2256 retval
= device_create_file(csdev
, &dev_attr_write_buffer_kb
);
2259 "comedi: failed to create sysfs attribute file \"%s\".\n",
2260 dev_attr_write_buffer_kb
.attr
.name
);
2261 comedi_free_subdevice_minor(s
);
2267 void comedi_free_subdevice_minor(struct comedi_subdevice
*s
)
2269 unsigned long flags
;
2270 struct comedi_device_file_info
*info
;
2277 BUG_ON(s
->minor
>= COMEDI_NUM_MINORS
);
2278 BUG_ON(s
->minor
< COMEDI_FIRST_SUBDEVICE_MINOR
);
2280 spin_lock_irqsave(&comedi_file_info_table_lock
, flags
);
2281 info
= comedi_file_info_table
[s
->minor
];
2282 comedi_file_info_table
[s
->minor
] = NULL
;
2283 spin_unlock_irqrestore(&comedi_file_info_table_lock
, flags
);
2286 device_destroy(comedi_class
, MKDEV(COMEDI_MAJOR
, s
->minor
));
2287 s
->class_dev
= NULL
;
2292 struct comedi_device_file_info
*comedi_get_device_file_info(unsigned minor
)
2294 unsigned long flags
;
2295 struct comedi_device_file_info
*info
;
2297 BUG_ON(minor
>= COMEDI_NUM_MINORS
);
2298 spin_lock_irqsave(&comedi_file_info_table_lock
, flags
);
2299 info
= comedi_file_info_table
[minor
];
2300 spin_unlock_irqrestore(&comedi_file_info_table_lock
, flags
);
2304 static int resize_async_buffer(struct comedi_device
*dev
,
2305 struct comedi_subdevice
*s
,
2306 struct comedi_async
*async
, unsigned new_size
)
2310 if (new_size
> async
->max_bufsize
)
2314 DPRINTK("subdevice is busy, cannot resize buffer\n");
2317 if (async
->mmap_count
) {
2318 DPRINTK("subdevice is mmapped, cannot resize buffer\n");
2322 if (!async
->prealloc_buf
)
2325 /* make sure buffer is an integral number of pages
2327 new_size
= (new_size
+ PAGE_SIZE
- 1) & PAGE_MASK
;
2329 retval
= comedi_buf_alloc(dev
, s
, new_size
);
2333 if (s
->buf_change
) {
2334 retval
= s
->buf_change(dev
, s
, new_size
);
2339 DPRINTK("comedi%i subd %d buffer resized to %i bytes\n",
2340 dev
->minor
, (int)(s
- dev
->subdevices
), async
->prealloc_bufsz
);
2344 /* sysfs attribute files */
2346 static const unsigned bytes_per_kibi
= 1024;
2348 static ssize_t
show_max_read_buffer_kb(struct device
*dev
,
2349 struct device_attribute
*attr
, char *buf
)
2352 struct comedi_device_file_info
*info
= dev_get_drvdata(dev
);
2353 unsigned max_buffer_size_kb
= 0;
2354 struct comedi_subdevice
*const read_subdevice
=
2355 comedi_get_read_subdevice(info
);
2357 mutex_lock(&info
->device
->mutex
);
2358 if (read_subdevice
&&
2359 (read_subdevice
->subdev_flags
& SDF_CMD_READ
) &&
2360 read_subdevice
->async
) {
2361 max_buffer_size_kb
= read_subdevice
->async
->max_bufsize
/
2364 retval
= snprintf(buf
, PAGE_SIZE
, "%i\n", max_buffer_size_kb
);
2365 mutex_unlock(&info
->device
->mutex
);
2370 static ssize_t
store_max_read_buffer_kb(struct device
*dev
,
2371 struct device_attribute
*attr
,
2372 const char *buf
, size_t count
)
2374 struct comedi_device_file_info
*info
= dev_get_drvdata(dev
);
2375 unsigned long new_max_size_kb
;
2376 uint64_t new_max_size
;
2377 struct comedi_subdevice
*const read_subdevice
=
2378 comedi_get_read_subdevice(info
);
2380 if (strict_strtoul(buf
, 10, &new_max_size_kb
))
2382 if (new_max_size_kb
!= (uint32_t) new_max_size_kb
)
2384 new_max_size
= ((uint64_t) new_max_size_kb
) * bytes_per_kibi
;
2385 if (new_max_size
!= (uint32_t) new_max_size
)
2388 mutex_lock(&info
->device
->mutex
);
2389 if (read_subdevice
== NULL
||
2390 (read_subdevice
->subdev_flags
& SDF_CMD_READ
) == 0 ||
2391 read_subdevice
->async
== NULL
) {
2392 mutex_unlock(&info
->device
->mutex
);
2395 read_subdevice
->async
->max_bufsize
= new_max_size
;
2396 mutex_unlock(&info
->device
->mutex
);
2401 static struct device_attribute dev_attr_max_read_buffer_kb
= {
2403 .name
= "max_read_buffer_kb",
2404 .mode
= S_IRUGO
| S_IWUSR
},
2405 .show
= &show_max_read_buffer_kb
,
2406 .store
= &store_max_read_buffer_kb
2409 static ssize_t
show_read_buffer_kb(struct device
*dev
,
2410 struct device_attribute
*attr
, char *buf
)
2413 struct comedi_device_file_info
*info
= dev_get_drvdata(dev
);
2414 unsigned buffer_size_kb
= 0;
2415 struct comedi_subdevice
*const read_subdevice
=
2416 comedi_get_read_subdevice(info
);
2418 mutex_lock(&info
->device
->mutex
);
2419 if (read_subdevice
&&
2420 (read_subdevice
->subdev_flags
& SDF_CMD_READ
) &&
2421 read_subdevice
->async
) {
2422 buffer_size_kb
= read_subdevice
->async
->prealloc_bufsz
/
2425 retval
= snprintf(buf
, PAGE_SIZE
, "%i\n", buffer_size_kb
);
2426 mutex_unlock(&info
->device
->mutex
);
2431 static ssize_t
store_read_buffer_kb(struct device
*dev
,
2432 struct device_attribute
*attr
,
2433 const char *buf
, size_t count
)
2435 struct comedi_device_file_info
*info
= dev_get_drvdata(dev
);
2436 unsigned long new_size_kb
;
2439 struct comedi_subdevice
*const read_subdevice
=
2440 comedi_get_read_subdevice(info
);
2442 if (strict_strtoul(buf
, 10, &new_size_kb
))
2444 if (new_size_kb
!= (uint32_t) new_size_kb
)
2446 new_size
= ((uint64_t) new_size_kb
) * bytes_per_kibi
;
2447 if (new_size
!= (uint32_t) new_size
)
2450 mutex_lock(&info
->device
->mutex
);
2451 if (read_subdevice
== NULL
||
2452 (read_subdevice
->subdev_flags
& SDF_CMD_READ
) == 0 ||
2453 read_subdevice
->async
== NULL
) {
2454 mutex_unlock(&info
->device
->mutex
);
2457 retval
= resize_async_buffer(info
->device
, read_subdevice
,
2458 read_subdevice
->async
, new_size
);
2459 mutex_unlock(&info
->device
->mutex
);
2466 static struct device_attribute dev_attr_read_buffer_kb
= {
2468 .name
= "read_buffer_kb",
2469 .mode
= S_IRUGO
| S_IWUSR
| S_IWGRP
},
2470 .show
= &show_read_buffer_kb
,
2471 .store
= &store_read_buffer_kb
2474 static ssize_t
show_max_write_buffer_kb(struct device
*dev
,
2475 struct device_attribute
*attr
,
2479 struct comedi_device_file_info
*info
= dev_get_drvdata(dev
);
2480 unsigned max_buffer_size_kb
= 0;
2481 struct comedi_subdevice
*const write_subdevice
=
2482 comedi_get_write_subdevice(info
);
2484 mutex_lock(&info
->device
->mutex
);
2485 if (write_subdevice
&&
2486 (write_subdevice
->subdev_flags
& SDF_CMD_WRITE
) &&
2487 write_subdevice
->async
) {
2488 max_buffer_size_kb
= write_subdevice
->async
->max_bufsize
/
2491 retval
= snprintf(buf
, PAGE_SIZE
, "%i\n", max_buffer_size_kb
);
2492 mutex_unlock(&info
->device
->mutex
);
2497 static ssize_t
store_max_write_buffer_kb(struct device
*dev
,
2498 struct device_attribute
*attr
,
2499 const char *buf
, size_t count
)
2501 struct comedi_device_file_info
*info
= dev_get_drvdata(dev
);
2502 unsigned long new_max_size_kb
;
2503 uint64_t new_max_size
;
2504 struct comedi_subdevice
*const write_subdevice
=
2505 comedi_get_write_subdevice(info
);
2507 if (strict_strtoul(buf
, 10, &new_max_size_kb
))
2509 if (new_max_size_kb
!= (uint32_t) new_max_size_kb
)
2511 new_max_size
= ((uint64_t) new_max_size_kb
) * bytes_per_kibi
;
2512 if (new_max_size
!= (uint32_t) new_max_size
)
2515 mutex_lock(&info
->device
->mutex
);
2516 if (write_subdevice
== NULL
||
2517 (write_subdevice
->subdev_flags
& SDF_CMD_WRITE
) == 0 ||
2518 write_subdevice
->async
== NULL
) {
2519 mutex_unlock(&info
->device
->mutex
);
2522 write_subdevice
->async
->max_bufsize
= new_max_size
;
2523 mutex_unlock(&info
->device
->mutex
);
2528 static struct device_attribute dev_attr_max_write_buffer_kb
= {
2530 .name
= "max_write_buffer_kb",
2531 .mode
= S_IRUGO
| S_IWUSR
},
2532 .show
= &show_max_write_buffer_kb
,
2533 .store
= &store_max_write_buffer_kb
2536 static ssize_t
show_write_buffer_kb(struct device
*dev
,
2537 struct device_attribute
*attr
, char *buf
)
2540 struct comedi_device_file_info
*info
= dev_get_drvdata(dev
);
2541 unsigned buffer_size_kb
= 0;
2542 struct comedi_subdevice
*const write_subdevice
=
2543 comedi_get_write_subdevice(info
);
2545 mutex_lock(&info
->device
->mutex
);
2546 if (write_subdevice
&&
2547 (write_subdevice
->subdev_flags
& SDF_CMD_WRITE
) &&
2548 write_subdevice
->async
) {
2549 buffer_size_kb
= write_subdevice
->async
->prealloc_bufsz
/
2552 retval
= snprintf(buf
, PAGE_SIZE
, "%i\n", buffer_size_kb
);
2553 mutex_unlock(&info
->device
->mutex
);
2558 static ssize_t
store_write_buffer_kb(struct device
*dev
,
2559 struct device_attribute
*attr
,
2560 const char *buf
, size_t count
)
2562 struct comedi_device_file_info
*info
= dev_get_drvdata(dev
);
2563 unsigned long new_size_kb
;
2566 struct comedi_subdevice
*const write_subdevice
=
2567 comedi_get_write_subdevice(info
);
2569 if (strict_strtoul(buf
, 10, &new_size_kb
))
2571 if (new_size_kb
!= (uint32_t) new_size_kb
)
2573 new_size
= ((uint64_t) new_size_kb
) * bytes_per_kibi
;
2574 if (new_size
!= (uint32_t) new_size
)
2577 mutex_lock(&info
->device
->mutex
);
2578 if (write_subdevice
== NULL
||
2579 (write_subdevice
->subdev_flags
& SDF_CMD_WRITE
) == 0 ||
2580 write_subdevice
->async
== NULL
) {
2581 mutex_unlock(&info
->device
->mutex
);
2584 retval
= resize_async_buffer(info
->device
, write_subdevice
,
2585 write_subdevice
->async
, new_size
);
2586 mutex_unlock(&info
->device
->mutex
);
2593 static struct device_attribute dev_attr_write_buffer_kb
= {
2595 .name
= "write_buffer_kb",
2596 .mode
= S_IRUGO
| S_IWUSR
| S_IWGRP
},
2597 .show
= &show_write_buffer_kb
,
2598 .store
= &store_write_buffer_kb