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"
29 #include <linux/module.h>
30 #include <linux/errno.h>
31 #include <linux/kernel.h>
32 #include <linux/sched.h>
33 #include <linux/fcntl.h>
34 #include <linux/delay.h>
35 #include <linux/ioport.h>
37 #include <linux/slab.h>
38 #include <linux/kmod.h>
39 #include <linux/poll.h>
40 #include <linux/init.h>
41 #include <linux/devfs_fs_kernel.h>
42 #include <linux/device.h>
43 #include <linux/vmalloc.h>
45 #include <linux/comedidev.h>
46 #include <linux/cdev.h>
49 #include <asm/uaccess.h>
53 MODULE_AUTHOR("David Schleef <ds@schleef.org>");
54 MODULE_DESCRIPTION("Comedi core module");
55 MODULE_LICENSE("GPL");
57 #ifdef CONFIG_COMEDI_DEBUG
59 module_param(comedi_debug, int, 0644);
62 comedi_device *comedi_devices;
63 spinlock_t big_comedi_lock; /* Dynamic initialization */
65 static int do_devconfig_ioctl(comedi_device *dev,comedi_devconfig *arg);
66 static int do_bufconfig_ioctl(comedi_device *dev,void *arg);
67 static int do_devinfo_ioctl(comedi_device *dev,comedi_devinfo *arg);
68 static int do_subdinfo_ioctl(comedi_device *dev,comedi_subdinfo *arg,void *file);
69 static int do_chaninfo_ioctl(comedi_device *dev,comedi_chaninfo *arg);
70 static int do_bufinfo_ioctl(comedi_device *dev,void *arg);
71 static int do_cmd_ioctl(comedi_device *dev,void *arg,void *file);
72 static int do_lock_ioctl(comedi_device *dev,unsigned int arg,void * file);
73 static int do_unlock_ioctl(comedi_device *dev,unsigned int arg,void * file);
74 static int do_cancel_ioctl(comedi_device *dev,unsigned int arg,void *file);
75 static int do_cmdtest_ioctl(comedi_device *dev,void *arg,void *file);
76 static int do_insnlist_ioctl(comedi_device *dev,void *arg,void *file);
77 static int do_insn_ioctl(comedi_device *dev,void *arg,void *file);
78 static int do_poll_ioctl(comedi_device *dev,unsigned int subd,void *file);
80 void do_become_nonbusy(comedi_device *dev,comedi_subdevice *s);
81 static int do_cancel(comedi_device *dev,comedi_subdevice *s);
83 static int comedi_fasync (int fd, struct file *file, int on);
85 static int comedi_ioctl(struct inode * inode,struct file * file,
86 unsigned int cmd, unsigned long arg)
88 const unsigned minor = iminor(inode);
89 comedi_device *dev = comedi_get_device_by_minor(minor);
91 /* Device config is special, because it must work on
92 * an unconfigured device. */
93 if(cmd==COMEDI_DEVCONFIG){
94 return do_devconfig_ioctl(dev,(void *)arg);
98 DPRINTK("no driver configured on /dev/comedi%i\n", dev->minor);
104 case COMEDI_BUFCONFIG:
105 return do_bufconfig_ioctl(dev,(void*)arg);
107 return do_devinfo_ioctl(dev,(void *)arg);
108 case COMEDI_SUBDINFO:
109 return do_subdinfo_ioctl(dev,(void *)arg,file);
110 case COMEDI_CHANINFO:
111 return do_chaninfo_ioctl(dev,(void *)arg);
112 case COMEDI_RANGEINFO:
113 return do_rangeinfo_ioctl(dev,(void *)arg);
115 return do_bufinfo_ioctl(dev,(void*)arg);
117 return do_lock_ioctl(dev,arg,file);
119 return do_unlock_ioctl(dev,arg,file);
121 return do_cancel_ioctl(dev,arg,file);
123 return do_cmd_ioctl(dev,(void *)arg,file);
125 return do_cmdtest_ioctl(dev,(void *)arg,file);
126 case COMEDI_INSNLIST:
127 return do_insnlist_ioctl(dev,(void *)arg,file);
129 return do_insn_ioctl(dev,(void *)arg,file);
131 return do_poll_ioctl(dev,arg,file);
143 pointer to devconfig structure
146 devconfig structure at arg
151 static int do_devconfig_ioctl(comedi_device *dev, comedi_devconfig *arg)
155 unsigned char *aux_data = NULL;
158 if(!capable(CAP_SYS_ADMIN))
162 return comedi_device_detach(dev);
165 if(copy_from_user(&it,arg,sizeof(comedi_devconfig)))
168 it.board_name[COMEDI_NAMELEN-1]=0;
170 if(comedi_aux_data(it.options, 0) &&
171 it.options[COMEDI_DEVCONF_AUX_DATA_LENGTH]){
173 aux_len = it.options[COMEDI_DEVCONF_AUX_DATA_LENGTH];
174 if(aux_len<0)return -EFAULT;
176 aux_data = vmalloc(aux_len);
177 if(!aux_data) return -ENOMEM;
179 if(copy_from_user(aux_data,
180 comedi_aux_data(it.options, 0), aux_len)){
184 it.options[COMEDI_DEVCONF_AUX_DATA_LO] = (unsigned long)aux_data;
185 if(sizeof(void*) > sizeof(int))
187 bit_shift = sizeof(int) * 8;
188 it.options[COMEDI_DEVCONF_AUX_DATA_HI] = ((unsigned long)aux_data) >> bit_shift;
190 it.options[COMEDI_DEVCONF_AUX_DATA_HI] = 0;
193 ret = comedi_device_attach(dev,&it);
195 if(aux_data) vfree(aux_data);
202 buffer configuration ioctl
205 pointer to bufconfig structure
211 modified bufconfig at arg
214 static int do_bufconfig_ioctl(comedi_device *dev,void *arg)
221 if(copy_from_user(&bc,arg,sizeof(comedi_bufconfig)))
224 if(bc.subdevice>=dev->n_subdevices || bc.subdevice<0)
227 s=dev->subdevices+bc.subdevice;
231 DPRINTK("subdevice does not have async capability\n");
238 if(!capable(CAP_SYS_ADMIN))return -EPERM;
240 async->max_bufsize = bc.maximum_size;
244 if(bc.size > async->max_bufsize)
249 DPRINTK("subdevice is busy, cannot resize buffer\n");
252 if(async->mmap_count){
253 DPRINTK("subdevice is mmapped, cannot resize buffer\n");
257 if(!async->prealloc_buf)
260 /* make sure buffer is an integral number of pages
262 bc.size = (bc.size + PAGE_SIZE - 1) & PAGE_MASK;
264 ret = comedi_buf_alloc(dev, s, bc.size);
265 if(ret < 0) return ret;
268 ret = s->buf_change(dev,s,bc.size);
269 if(ret < 0) return ret;
272 DPRINTK("comedi%i subd %d buffer resized to %i bytes\n",
273 dev->minor, bc.subdevice, async->prealloc_bufsz);
276 bc.size = async->prealloc_bufsz;
277 bc.maximum_size = async->max_bufsize;
280 if(copy_to_user(arg,&bc,sizeof(comedi_bufconfig)))
291 pointer to devinfo structure
300 static int do_devinfo_ioctl(comedi_device *dev,comedi_devinfo *arg)
302 comedi_devinfo devinfo;
304 memset(&devinfo,0,sizeof(devinfo));
306 /* fill devinfo structure */
307 devinfo.version_code=COMEDI_VERSION_CODE;
308 devinfo.n_subdevs=dev->n_subdevices;
309 memcpy(devinfo.driver_name,dev->driver->driver_name,COMEDI_NAMELEN);
310 memcpy(devinfo.board_name,dev->board_name,COMEDI_NAMELEN);
312 if(dev->read_subdev){
313 devinfo.read_subdevice = dev->read_subdev - dev->subdevices;
315 devinfo.read_subdevice = -1;
317 if(dev->write_subdev){
318 devinfo.write_subdevice = dev->write_subdev - dev->subdevices;
320 devinfo.write_subdevice = -1;
323 if(copy_to_user(arg,&devinfo,sizeof(comedi_devinfo)))
335 pointer to array of subdevice info structures
341 array of subdevice info structures at arg
344 static int do_subdinfo_ioctl(comedi_device *dev,comedi_subdinfo *arg,void *file)
347 comedi_subdinfo *tmp,*us;
351 tmp=kmalloc(dev->n_subdevices*sizeof(comedi_subdinfo),GFP_KERNEL);
355 memset(tmp,0,sizeof(comedi_subdinfo)*dev->n_subdevices);
357 /* fill subdinfo structs */
358 for(i=0;i<dev->n_subdevices;i++){
363 us->n_chan = s->n_chan;
364 us->subd_flags = s->subdev_flags;
365 #define TIMER_nanosec 5 /* backwards compatibility */
366 us->timer_type = TIMER_nanosec;
367 us->len_chanlist = s->len_chanlist;
368 us->maxdata = s->maxdata;
370 us->range_type = (dev->minor << 28) | (i << 24) | (0 << 16) |
371 (s->range_table->length);
373 us->range_type = 0; /* XXX */
375 us->flags = s->flags;
378 us->subd_flags |= SDF_BUSY;
380 us->subd_flags |= SDF_BUSY_OWNER;
382 us->subd_flags |= SDF_LOCKED;
384 us->subd_flags |= SDF_LOCK_OWNER;
385 if(!s->maxdata && s->maxdata_list)
386 us->subd_flags |= SDF_MAXDATA;
388 us->subd_flags |= SDF_FLAGS;
389 if(s->range_table_list)
390 us->subd_flags |= SDF_RANGETYPE;
392 us->subd_flags |= SDF_CMD;
394 us->settling_time_0 = s->settling_time_0;
397 ret=copy_to_user(arg,tmp,dev->n_subdevices*sizeof(comedi_subdinfo));
401 return ret?-EFAULT:0;
410 pointer to chaninfo structure
413 chaninfo structure at arg
416 arrays at elements of chaninfo structure
419 static int do_chaninfo_ioctl(comedi_device *dev,comedi_chaninfo *arg)
424 if(copy_from_user(&it,arg,sizeof(comedi_chaninfo)))
427 if(it.subdev>=dev->n_subdevices)
429 s=dev->subdevices+it.subdev;
432 if(s->maxdata || !s->maxdata_list)
434 if(copy_to_user(it.maxdata_list,s->maxdata_list,s->n_chan*sizeof(lsampl_t)))
439 if(!s->flaglist)return -EINVAL;
440 if(copy_to_user(it.flaglist,s->flaglist,s->n_chan*sizeof(unsigned int)))
447 if(!s->range_table_list)return -EINVAL;
448 for(i=0;i<s->n_chan;i++){
451 x=(dev->minor << 28) | (it.subdev << 24) | (i << 16) |
452 (s->range_table_list[i]->length);
453 put_user(x,it.rangelist+i);
455 //if(copy_to_user(it.rangelist,s->range_type_list,s->n_chan*sizeof(unsigned int)))
464 buffer information ioctl
467 pointer to bufinfo structure
473 modified bufinfo at arg
476 static int do_bufinfo_ioctl(comedi_device *dev,void *arg)
482 if(copy_from_user(&bi,arg, sizeof(comedi_bufinfo)))
485 if(bi.subdevice >= dev->n_subdevices || bi.subdevice < 0)
488 s = dev->subdevices + bi.subdevice;
492 DPRINTK("subdevice does not have async capability\n");
493 bi.buf_write_ptr = 0;
495 bi.buf_write_count = 0;
496 bi.buf_read_count = 0;
500 if(bi.bytes_read && (s->subdev_flags & SDF_CMD_READ)){
501 bi.bytes_read = comedi_buf_read_alloc(async, bi.bytes_read);
502 comedi_buf_read_free(async, bi.bytes_read);
504 if(!(s->subdev_flags&SDF_RUNNING) &&
505 !(s->runflags & SRF_ERROR) &&
506 async->buf_write_count==async->buf_read_count){
507 do_become_nonbusy(dev,s);
511 if(bi.bytes_written && (s->subdev_flags & SDF_CMD_WRITE)){
512 bi.bytes_written = comedi_buf_write_alloc( async, bi.bytes_written );
513 comedi_buf_write_free(async, bi.bytes_written);
516 bi.buf_write_count = async->buf_write_count;
517 bi.buf_write_ptr = async->buf_write_ptr;
518 bi.buf_read_count = async->buf_read_count;
519 bi.buf_read_ptr = async->buf_read_ptr;
522 if(copy_to_user(arg, &bi, sizeof(comedi_bufinfo)))
529 static int parse_insn(comedi_device *dev,comedi_insn *insn,lsampl_t *data,void *file);
532 * synchronous instructions
535 * pointer to sync cmd structure
538 * sync cmd struct at arg
545 /* arbitrary limits */
546 #define MAX_SAMPLES 256
547 static int do_insnlist_ioctl(comedi_device *dev,void *arg,void *file)
549 comedi_insnlist insnlist;
550 comedi_insn *insns = NULL;
551 lsampl_t *data = NULL;
555 if(copy_from_user(&insnlist,arg,sizeof(comedi_insnlist)))
558 data=kmalloc(sizeof(lsampl_t)*MAX_SAMPLES,GFP_KERNEL);
560 DPRINTK("kmalloc failed\n");
565 insns=kmalloc(sizeof(comedi_insn)*insnlist.n_insns,GFP_KERNEL);
567 DPRINTK("kmalloc failed\n");
572 if(copy_from_user(insns,insnlist.insns,sizeof(comedi_insn)*insnlist.n_insns)){
573 DPRINTK("copy_from_user failed\n");
578 for(i=0;i<insnlist.n_insns;i++){
579 if(insns[i].n>MAX_SAMPLES){
580 DPRINTK("number of samples too large\n");
584 if(insns[i].insn&INSN_MASK_WRITE){
585 if(copy_from_user(data,insns[i].data,
586 insns[i].n*sizeof(lsampl_t))){
587 DPRINTK("copy_from_user failed\n");
592 ret = parse_insn(dev,insns+i,data,file);
594 if(insns[i].insn&INSN_MASK_READ){
595 if(copy_to_user(insns[i].data,data,
596 insns[i].n*sizeof(lsampl_t))){
597 DPRINTK("copy_to_user failed\n");
607 if(insns)kfree(insns);
614 static int check_insn_config_length(comedi_insn *insn, lsampl_t *data)
618 case INSN_CONFIG_DIO_OUTPUT:
619 case INSN_CONFIG_DIO_INPUT:
620 case INSN_CONFIG_DISARM:
621 case INSN_CONFIG_RESET:
622 if(insn->n == 1) return 0;
624 case INSN_CONFIG_ARM:
625 case INSN_CONFIG_DIO_QUERY:
626 case INSN_CONFIG_BLOCK_SIZE:
627 case INSN_CONFIG_FILTER:
628 case INSN_CONFIG_SERIAL_CLOCK:
629 case INSN_CONFIG_BIDIRECTIONAL_DATA:
630 case INSN_CONFIG_ALT_SOURCE:
631 case INSN_CONFIG_SET_COUNTER_MODE:
632 case INSN_CONFIG_8254_READ_STATUS:
633 case INSN_CONFIG_SET_ROUTING:
634 case INSN_CONFIG_GET_ROUTING:
635 if(insn->n == 2) return 0;
637 case INSN_CONFIG_SET_GATE_SRC:
638 case INSN_CONFIG_GET_GATE_SRC:
639 case INSN_CONFIG_SET_CLOCK_SRC:
640 case INSN_CONFIG_GET_CLOCK_SRC:
641 case INSN_CONFIG_GET_COUNTER_STATUS:
642 if(insn->n == 3) return 0;
644 case INSN_CONFIG_PWM_OUTPUT:
645 case INSN_CONFIG_ANALOG_TRIG:
646 if(insn->n == 5) return 0;
648 //by default we allow the insn since we don't have checks for all possible cases yet
650 rt_printk("comedi: no check for data length of config insn id %i is implemented.\n"
651 " Add a check to %s in %s.\n"
652 " Assuming n=%i is correct.\n",
653 data[0], __FUNCTION__, __FILE__, insn->n);
660 static int parse_insn(comedi_device *dev,comedi_insn *insn,lsampl_t *data,void *file)
665 if(insn->insn&INSN_MASK_SPECIAL){
666 /* a non-subdevice instruction */
678 do_gettimeofday(&tv);
686 if(insn->n!=1 || data[0]>=100000){
690 udelay(data[0]/1000);
698 if(insn->subdev>=dev->n_subdevices){
699 DPRINTK("%d not usable subdevice\n",insn->subdev);
703 s=dev->subdevices+insn->subdev;
705 DPRINTK("no async\n");
709 if(!s->async->inttrig){
710 DPRINTK("no inttrig\n");
714 ret = s->async->inttrig(dev,s,insn->data[0]);
718 DPRINTK("invalid insn\n");
723 /* a subdevice instruction */
724 if(insn->subdev>=dev->n_subdevices){
725 DPRINTK("subdevice %d out of range\n",insn->subdev);
729 s=dev->subdevices+insn->subdev;
731 if(s->type==COMEDI_SUBD_UNUSED){
732 DPRINTK("%d not usable subdevice\n",insn->subdev);
737 /* are we locked? (ioctl lock) */
738 if(s->lock && s->lock!=file){
739 DPRINTK("device locked\n");
744 if((ret=check_chanlist(s,1,&insn->chanspec))<0){
746 DPRINTK("bad chanspec\n");
754 /* This looks arbitrary. It is. */
758 ret=s->insn_read(dev,s,insn,data);
761 //XXX check against subdevice's maxdata
762 ret=s->insn_write(dev,s,insn,data);
770 ret=s->insn_bits(dev,s,insn,data);
773 ret=check_insn_config_length(insn, data);
775 ret=s->insn_config(dev,s,insn,data);
791 * synchronous instructions
797 * comedi_insn struct at arg
803 static int do_insn_ioctl(comedi_device *dev,void *arg,void *file)
806 lsampl_t *data = NULL;
809 data=kmalloc(sizeof(lsampl_t)*MAX_SAMPLES,GFP_KERNEL);
815 if(copy_from_user(&insn,arg,sizeof(comedi_insn))){
820 /* This is where the behavior of insn and insnlist deviate. */
821 if(insn.n>MAX_SAMPLES)insn.n=MAX_SAMPLES;
822 if(insn.insn&INSN_MASK_WRITE){
823 if(copy_from_user(data,insn.data,insn.n*sizeof(lsampl_t))){
828 ret = parse_insn(dev,&insn,data,file);
830 if(insn.insn&INSN_MASK_READ){
831 if(copy_to_user(insn.data,data,insn.n*sizeof(lsampl_t))){
849 pointer to cmd structure
856 modified cmd structure at arg
859 static int do_cmd_ioctl(comedi_device *dev,void *arg,void *file)
865 unsigned int *chanlist_saver=NULL;
867 if(copy_from_user(&user_cmd,arg,sizeof(comedi_cmd))){
868 DPRINTK("bad cmd address\n");
872 // save user's chanlist pointer so it can be restored later
873 chanlist_saver = user_cmd.chanlist;
875 if(user_cmd.subdev>=dev->n_subdevices){
876 DPRINTK("%d no such subdevice\n",user_cmd.subdev);
880 s=dev->subdevices+user_cmd.subdev;
883 if(s->type==COMEDI_SUBD_UNUSED){
884 DPRINTK("%d not valid subdevice\n",user_cmd.subdev);
888 if(!s->do_cmd || !s->async){
889 DPRINTK("subdevice %i does not support commands\n", user_cmd.subdev);
893 /* are we locked? (ioctl lock) */
894 if(s->lock && s->lock!=file){
895 DPRINTK("subdevice locked\n");
901 DPRINTK("subdevice busy\n");
906 /* make sure channel/gain list isn't too long */
907 if(user_cmd.chanlist_len > s->len_chanlist){
908 DPRINTK("channel/gain list too long %d > %d\n",user_cmd.chanlist_len,s->len_chanlist);
913 if(async->cmd.chanlist) kfree(async->cmd.chanlist);
915 async->cmd.data=NULL;
916 /* load channel/gain list */
917 async->cmd.chanlist=kmalloc(async->cmd.chanlist_len*sizeof(int),GFP_KERNEL);
918 if(!async->cmd.chanlist){
919 DPRINTK("allocation failed\n");
924 if(copy_from_user(async->cmd.chanlist,user_cmd.chanlist,async->cmd.chanlist_len*sizeof(int))){
925 DPRINTK("fault reading chanlist\n");
930 /* make sure each element in channel/gain list is valid */
931 if((ret=check_chanlist(s,async->cmd.chanlist_len,async->cmd.chanlist))<0){
932 DPRINTK("bad chanlist\n");
936 ret=s->do_cmdtest(dev,s,&async->cmd);
938 if(async->cmd.flags&TRIG_BOGUS || ret){
939 DPRINTK("test returned %d\n",ret);
941 // restore chanlist pointer before copying back
942 user_cmd.chanlist = chanlist_saver;
943 user_cmd.data = NULL;
944 if(copy_to_user(arg,&user_cmd,sizeof(comedi_cmd))){
945 DPRINTK("fault writing cmd\n");
953 if(!async->prealloc_bufsz){
955 DPRINTK("no buffer (?)\n");
959 comedi_reset_async_buf( async );
961 async->cb_mask = COMEDI_CB_EOA | COMEDI_CB_BLOCK | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
962 if(async->cmd.flags & TRIG_WAKE_EOS){
963 async->cb_mask |= COMEDI_CB_EOS;
966 s->runflags=SRF_USER;
968 s->subdev_flags|=SDF_RUNNING;
970 #ifdef CONFIG_COMEDI_RT
971 if(async->cmd.flags&TRIG_RT){
972 comedi_switch_to_rt(dev);
973 s->runflags |= SRF_RT;
977 ret=s->do_cmd(dev,s);
982 do_become_nonbusy(dev,s);
989 command testing ioctl
992 pointer to cmd structure
999 modified cmd structure at arg
1002 static int do_cmdtest_ioctl(comedi_device *dev,void *arg,void *file)
1004 comedi_cmd user_cmd;
1005 comedi_subdevice *s;
1007 unsigned int *chanlist=NULL;
1008 unsigned int *chanlist_saver=NULL;
1010 if(copy_from_user(&user_cmd,arg,sizeof(comedi_cmd))){
1011 DPRINTK("bad cmd address\n");
1015 // save user's chanlist pointer so it can be restored later
1016 chanlist_saver = user_cmd.chanlist;
1018 if(user_cmd.subdev>=dev->n_subdevices){
1019 DPRINTK("%d no such subdevice\n",user_cmd.subdev);
1023 s=dev->subdevices+user_cmd.subdev;
1024 if(s->type==COMEDI_SUBD_UNUSED){
1025 DPRINTK("%d not valid subdevice\n",user_cmd.subdev);
1030 DPRINTK("subdevice %i does not support commands\n", user_cmd.subdev);
1034 /* make sure channel/gain list isn't too long */
1035 if(user_cmd.chanlist_len > s->len_chanlist){
1036 DPRINTK("channel/gain list too long %d > %d\n",user_cmd.chanlist_len,s->len_chanlist);
1041 /* load channel/gain list */
1042 if(user_cmd.chanlist){
1043 chanlist=kmalloc(user_cmd.chanlist_len*sizeof(int),GFP_KERNEL);
1045 DPRINTK("allocation failed\n");
1050 if(copy_from_user(chanlist,user_cmd.chanlist,user_cmd.chanlist_len*sizeof(int))){
1051 DPRINTK("fault reading chanlist\n");
1056 /* make sure each element in channel/gain list is valid */
1057 if((ret=check_chanlist(s,user_cmd.chanlist_len,chanlist))<0){
1058 DPRINTK("bad chanlist\n");
1062 user_cmd.chanlist=chanlist;
1065 ret=s->do_cmdtest(dev,s,&user_cmd);
1067 // restore chanlist pointer before copying back
1068 user_cmd.chanlist = chanlist_saver;
1070 if(copy_to_user(arg,&user_cmd,sizeof(comedi_cmd))){
1071 DPRINTK("bad cmd address\n");
1097 static int do_lock_ioctl(comedi_device *dev,unsigned int arg,void * file)
1100 unsigned long flags;
1101 comedi_subdevice *s;
1103 if(arg>=dev->n_subdevices)
1105 s=dev->subdevices+arg;
1107 comedi_spin_lock_irqsave(&big_comedi_lock, flags);
1110 comedi_spin_unlock_irqrestore(&big_comedi_lock, flags);
1118 comedi_spin_unlock_irqrestore(&big_comedi_lock, flags);
1125 ret=s->lock_f(dev,s);
1145 This function isn't protected by the semaphore, since
1146 we already own the lock.
1148 static int do_unlock_ioctl(comedi_device *dev,unsigned int arg,void * file)
1150 comedi_subdevice *s;
1152 if(arg>=dev->n_subdevices)
1154 s=dev->subdevices+arg;
1159 if(s->lock && s->lock!=file)
1176 cancel acquisition ioctl
1188 static int do_cancel_ioctl(comedi_device *dev,unsigned int arg,void *file)
1190 comedi_subdevice *s;
1192 if(arg>=dev->n_subdevices)
1194 s=dev->subdevices+arg;
1196 if(s->lock && s->lock!=file)
1205 return do_cancel(dev,s);
1210 instructs driver to synchronize buffers
1222 static int do_poll_ioctl(comedi_device *dev,unsigned int arg,void *file)
1224 comedi_subdevice *s;
1226 if(arg>=dev->n_subdevices)
1228 s=dev->subdevices+arg;
1230 if(s->lock && s->lock!=file)
1239 if(s->poll)return s->poll(dev,s);
1244 static int do_cancel(comedi_device *dev,comedi_subdevice *s)
1248 if((s->subdev_flags&SDF_RUNNING) && s->cancel)
1249 ret=s->cancel(dev,s);
1251 do_become_nonbusy(dev,s);
1257 void comedi_unmap(struct vm_area_struct *area)
1259 comedi_async *async;
1261 async = area->vm_private_data;
1263 async->mmap_count--;
1266 static struct vm_operations_struct comedi_vm_ops={
1267 close: comedi_unmap,
1270 static int comedi_mmap(struct file * file, struct vm_area_struct *vma)
1272 const unsigned minor = iminor(file->f_dentry->d_inode);
1273 comedi_device *dev = comedi_get_device_by_minor(minor);
1274 comedi_async *async = NULL;
1275 unsigned long start = vma->vm_start;
1279 comedi_subdevice *s;
1283 DPRINTK("no driver configured on comedi%i\n", dev->minor);
1286 s = comedi_get_subdevice_by_minor(minor);
1288 { if(vma->vm_flags & VM_WRITE){
1289 s = dev->write_subdev;
1291 s = dev->read_subdev;
1293 if(s == NULL) return -EINVAL;
1300 if(vma->vm_pgoff != 0){
1301 DPRINTK("comedi: mmap() offset must be 0.\n");
1305 size = vma->vm_end - vma->vm_start;
1306 if(size>async->prealloc_bufsz)
1308 if(size&(~PAGE_MASK))
1311 n_pages = size >> PAGE_SHIFT;
1312 for(i = 0; i < n_pages; ++i){
1313 if(remap_pfn_range(vma, start, page_to_pfn(virt_to_page(async->prealloc_buf + PAGE_SIZE * i)),
1314 PAGE_SIZE, PAGE_SHARED)){
1320 vma->vm_ops = &comedi_vm_ops;
1321 vma->vm_private_data = async;
1323 async->mmap_count++;
1329 static unsigned int comedi_poll(struct file *file, poll_table * wait)
1331 comedi_subdevice *s;
1332 comedi_async *async;
1334 const unsigned minor = iminor(file->f_dentry->d_inode);
1335 comedi_device *dev = comedi_get_device_by_minor(minor);
1339 DPRINTK("no driver configured on comedi%i\n", dev->minor);
1343 poll_wait(file, &dev->read_wait, wait);
1344 poll_wait(file, &dev->write_wait, wait);
1346 if(dev->read_subdev && dev->read_subdev->async){
1347 s = dev->read_subdev;
1350 || comedi_buf_read_n_available(async)>0
1351 || !(s->subdev_flags&SDF_RUNNING)){
1352 mask |= POLLIN | POLLRDNORM;
1355 if(dev->write_subdev && dev->write_subdev->async){
1356 s = dev->write_subdev;
1359 || !(s->subdev_flags&SDF_RUNNING)
1360 || comedi_buf_write_n_available(async) > 0){
1361 mask |= POLLOUT | POLLWRNORM;
1368 static ssize_t comedi_write(struct file *file,const char *buf,size_t nbytes,loff_t *offset)
1371 comedi_subdevice *s;
1372 comedi_async *async;
1373 int n,m,count=0,retval=0;
1374 DECLARE_WAITQUEUE(wait,current);
1375 const unsigned minor = iminor(file->f_dentry->d_inode);
1376 dev = comedi_get_device_by_minor(minor);
1380 DPRINTK("no driver configured on comedi%i\n", dev->minor);
1384 s = comedi_get_subdevice_by_minor(minor);
1386 s = dev->write_subdev;
1387 if(s == NULL || s->async == NULL || (s->subdev_flags & SDF_CMD_WRITE) == 0) return -EIO;
1390 if(!nbytes)return 0;
1398 add_wait_queue(&dev->write_wait,&wait);
1399 while(nbytes>0 && !retval){
1400 current->state=TASK_INTERRUPTIBLE;
1405 if(async->buf_write_ptr + m > async->prealloc_bufsz){
1406 m = async->prealloc_bufsz - async->buf_write_ptr;
1408 m = comedi_buf_write_alloc(async, m);
1413 if(file->f_flags&O_NONBLOCK){
1417 if(signal_pending(current)){
1418 retval=-ERESTARTSYS;
1421 if(!(s->subdev_flags&SDF_RUNNING)){
1422 if(s->runflags & SRF_ERROR){
1427 do_become_nonbusy(dev,s);
1434 m = copy_from_user(async->prealloc_buf + async->buf_write_ptr,
1440 comedi_buf_write_free(async, n);
1446 break; /* makes device work like a pipe */
1448 current->state=TASK_RUNNING;
1449 remove_wait_queue(&dev->write_wait,&wait);
1451 return (count ? count : retval);
1455 static ssize_t comedi_read(struct file * file,char *buf,size_t nbytes,loff_t *offset)
1457 comedi_subdevice *s;
1458 comedi_async *async;
1459 int n,m,count=0,retval=0;
1460 DECLARE_WAITQUEUE(wait,current);
1461 const unsigned minor = iminor(file->f_dentry->d_inode);
1462 comedi_device *dev = comedi_get_device_by_minor(minor);
1466 DPRINTK("no driver configured on comedi%i\n", dev->minor);
1470 s = comedi_get_subdevice_by_minor(minor);
1472 s = dev->read_subdev;
1473 if(s == NULL || s->async == NULL || (s->subdev_flags & SDF_CMD_READ) == 0) return -EIO;
1476 if(!nbytes)return 0;
1484 add_wait_queue(&dev->read_wait,&wait);
1485 while(nbytes>0 && !retval){
1486 current->state=TASK_INTERRUPTIBLE;
1490 m = comedi_buf_read_n_available(async);
1491 //printk("%d available\n",m);
1492 if(async->buf_read_ptr + m > async->prealloc_bufsz){
1493 m = async->prealloc_bufsz - async->buf_read_ptr;
1495 //printk("%d contiguous\n",m);
1499 if(!(s->subdev_flags&SDF_RUNNING)){
1500 do_become_nonbusy(dev,s);
1501 if(s->runflags & SRF_ERROR){
1508 if(file->f_flags&O_NONBLOCK){
1512 if(signal_pending(current)){
1513 retval=-ERESTARTSYS;
1519 m = copy_to_user(buf, async->prealloc_buf +
1520 async->buf_read_ptr, n);
1526 comedi_buf_read_alloc(async, n);
1527 comedi_buf_read_free(async, n);
1533 break; /* makes device work like a pipe */
1535 if(!(s->subdev_flags&SDF_RUNNING) &&
1536 !(s->runflags & SRF_ERROR) &&
1537 async->buf_read_count - async->buf_write_count == 0)
1539 do_become_nonbusy(dev,s);
1541 current->state=TASK_RUNNING;
1542 remove_wait_queue(&dev->read_wait,&wait);
1544 return (count ? count : retval);
1548 This function restores a subdevice to an idle state.
1550 void do_become_nonbusy(comedi_device *dev,comedi_subdevice *s)
1552 comedi_async *async = s->async;
1554 s->subdev_flags &= ~SDF_RUNNING;
1555 #ifdef CONFIG_COMEDI_RT
1556 if(s->runflags&SRF_RT){
1557 comedi_switch_to_non_rt(dev);
1558 s->runflags &= ~SRF_RT;
1565 (*s->cmd_cleanup)(dev, s);
1569 comedi_reset_async_buf( async );
1571 printk("BUG: (?) do_become_nonbusy called with async=0\n");
1577 /* no chance that these will change soon */
1582 static loff_t comedi_lseek(struct file *file,loff_t offset,int origin)
1585 const unsigned minor = iminor(file->f_dentry->d_inode);
1586 comedi_device *dev = comedi_get_device_by_minor(minor);
1590 new_offset = offset;
1593 new_offset = file->f_pos + offset;
1596 new_offset = dev->n_subdevices + offset;
1601 if(new_offset<0 || new_offset >= dev->n_subdevices)
1604 return file->f_pos=new_offset;
1607 static int comedi_open(struct inode *inode, struct file *file)
1610 const unsigned minor = iminor(inode);
1611 comedi_device *dev = comedi_get_device_by_minor(minor);
1614 DPRINTK("invalid minor number\n");
1618 /* This is slightly hacky, but we want module autoloading
1620 * case: user opens device, attached -> ok
1621 * case: user opens device, unattached, in_request_module=0 -> autoload
1622 * case: user opens device, unattached, in_request_module=1 -> fail
1623 * case: root opens device, attached -> ok
1624 * case: root opens device, unattached, in_request_module=1 -> ok
1625 * (typically called from modprobe)
1626 * case: root opens device, unattached, in_request_module=0 -> autoload
1628 * The last could be changed to "-> ok", which would deny root
1633 if(!capable(CAP_SYS_MODULE) && dev->in_request_module){
1634 DPRINTK("in request module\n");
1637 if(capable(CAP_SYS_MODULE) && dev->in_request_module)
1640 dev->in_request_module=1;
1642 sprintf(mod,"char-major-%i-%i", COMEDI_MAJOR, dev->minor);
1644 request_module(mod);
1647 dev->in_request_module=0;
1649 if(!dev->attached && !capable(CAP_SYS_MODULE)){
1650 DPRINTK("not attached and not CAP_SYS_MODULE\n");
1654 if(!try_module_get(THIS_MODULE))
1658 try_module_get( dev->driver->module );
1661 if(dev->attached && dev->use_count==0 && dev->open){
1670 static int comedi_close(struct inode *inode,struct file *file)
1672 const unsigned minor = iminor(inode);
1673 comedi_device *dev = comedi_get_device_by_minor(minor);
1674 comedi_subdevice *s = NULL;
1679 for(i=0;i<dev->n_subdevices;i++){
1680 s=dev->subdevices+i;
1690 if(dev->attached && dev->use_count==1 && dev->close){
1694 module_put(THIS_MODULE);
1696 module_put(dev->driver->module);
1701 if(file->f_flags & FASYNC){
1702 comedi_fasync(-1,file,0);
1708 static int comedi_fasync (int fd, struct file *file, int on)
1710 const unsigned minor = iminor(file->f_dentry->d_inode);
1711 comedi_device *dev = comedi_get_device_by_minor(minor);
1713 return fasync_helper(fd,file,on,&dev->async_queue);
1717 struct file_operations comedi_fops={
1718 owner : THIS_MODULE,
1719 llseek : comedi_lseek,
1720 ioctl : comedi_ioctl,
1722 release : comedi_close,
1724 write : comedi_write,
1727 fasync : comedi_fasync,
1730 struct class *comedi_class = NULL;
1731 static struct cdev comedi_cdev;
1733 static int __init comedi_init(void)
1738 printk("comedi: version " COMEDI_RELEASE " - David Schleef <ds@schleef.org>\n");
1739 spin_lock_init(&big_comedi_lock);
1740 retval = register_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS, "comedi");
1741 if(retval) return -EIO;
1742 cdev_init(&comedi_cdev, &comedi_fops);
1743 comedi_cdev.owner = THIS_MODULE;
1744 kobject_set_name(&comedi_cdev.kobj, "comedi");
1745 if(cdev_add(&comedi_cdev, MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS))
1747 unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
1750 comedi_class = class_create(THIS_MODULE, "comedi");
1751 if(IS_ERR(comedi_class))
1753 printk("comedi: failed to create class");
1754 unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
1755 cdev_del(&comedi_cdev);
1756 return PTR_ERR(comedi_class);
1758 comedi_devices=(comedi_device *)kmalloc(sizeof(comedi_device)*COMEDI_NDEVICES,GFP_KERNEL);
1761 unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
1762 cdev_del(&comedi_cdev);
1763 class_destroy(comedi_class);
1766 memset(comedi_devices,0,sizeof(comedi_device)*COMEDI_NDEVICES);
1768 /* XXX requires /proc interface */
1771 for(i=0;i<COMEDI_NDEVICES;i++){
1773 sprintf(name, "comedi%d", i);
1774 comedi_devices[i].minor = i;
1775 comedi_devices[i].class_dev = COMEDI_CLASS_DEVICE_CREATE(comedi_class, 0,
1776 MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i", i);
1777 spin_lock_init(&comedi_devices[i].spinlock);
1785 static void __exit comedi_cleanup(void)
1790 printk("comedi: module in use -- remove delayed\n");
1792 for(i = 0; i < COMEDI_NDEVICES; i++){
1795 dev = comedi_devices + i;
1797 comedi_device_detach(dev);
1800 for(i = 0; i < COMEDI_NDEVICES; i++){
1802 class_device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, i));
1803 sprintf(name, "comedi%d", i);
1805 class_destroy(comedi_class);
1806 cdev_del(&comedi_cdev);
1807 unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
1809 comedi_proc_cleanup();
1811 kfree(comedi_devices);
1813 comedi_rt_cleanup();
1816 module_init(comedi_init);
1817 module_exit(comedi_cleanup);
1819 void comedi_error(const comedi_device *dev,const char *s)
1821 rt_printk("comedi%d: %s: %s\n", dev->minor, dev->driver->driver_name, s);
1824 void comedi_event(comedi_device *dev,comedi_subdevice *s, unsigned int mask)
1826 comedi_async *async = s->async;
1828 mask = s->async->events;
1829 s->async->events = 0;
1831 //DPRINTK("comedi_event %x\n",mask);
1833 if( (s->subdev_flags & SDF_RUNNING) == 0)
1836 if(mask&(COMEDI_CB_EOA|COMEDI_CB_ERROR|COMEDI_CB_OVERFLOW)){
1837 s->subdev_flags &= ~SDF_RUNNING;
1840 /* remember if an error event has occured, so an error
1841 * can be returned the next time the user does a read() */
1842 if(mask & (COMEDI_CB_ERROR|COMEDI_CB_OVERFLOW)){
1843 s->runflags |= SRF_ERROR;
1845 if(async->cb_mask&mask){
1846 if(s->runflags&SRF_USER){
1849 #ifdef CONFIG_COMEDI_RT
1851 if(s->subdev_flags & SDF_CMD_READ)
1852 comedi_rt_pend_wakeup(&dev->read_wait);
1853 if(s->subdev_flags & SDF_CMD_WRITE)
1854 comedi_rt_pend_wakeup(&dev->write_wait);
1856 printk("BUG: comedi_event() code unreachable\n");
1859 if(s->subdev_flags & SDF_CMD_READ){
1860 wake_up_interruptible(&dev->read_wait);
1861 kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
1863 if(s->subdev_flags & SDF_CMD_WRITE){
1864 wake_up_interruptible(&dev->write_wait);
1865 kill_fasync(&dev->async_queue, SIGIO, POLL_OUT);
1869 if(async->cb_func)async->cb_func(mask,async->cb_arg);
1870 /* XXX bug here. If subdevice A is rt, and
1871 * subdevice B tries to callback to a normal
1872 * linux kernel function, it will be at the
1873 * wrong priority. Since this isn't very
1874 * common, I'm not going to worry about it. */