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 <linux/module.h>
28 #include <linux/errno.h>
29 #include <linux/kernel.h>
30 #include <linux/sched.h>
31 #include <linux/fcntl.h>
32 #include <linux/delay.h>
33 #include <linux/ioport.h>
35 #include <linux/slab.h>
36 #include <linux/kmod.h>
37 #include <linux/poll.h>
38 #include <linux/init.h>
39 #include <linux/devfs_fs_kernel.h>
40 #include <linux/device.h>
41 #include <linux/vmalloc.h>
44 #include <linux/comedidev.h>
47 #include <asm/uaccess.h>
51 MODULE_AUTHOR("David Schleef <ds@schleef.org>");
52 MODULE_DESCRIPTION("Comedi core module");
53 MODULE_LICENSE("GPL");
55 #ifdef CONFIG_COMEDI_DEBUG
57 module_param(comedi_debug, int, 0644);
60 comedi_device *comedi_devices;
61 spinlock_t big_comedi_lock; /* Dynamic initialization */
63 static int do_devconfig_ioctl(comedi_device *dev,comedi_devconfig *arg,unsigned int minor);
64 static int do_bufconfig_ioctl(comedi_device *dev,void *arg);
65 static int do_devinfo_ioctl(comedi_device *dev,comedi_devinfo *arg);
66 static int do_subdinfo_ioctl(comedi_device *dev,comedi_subdinfo *arg,void *file);
67 static int do_chaninfo_ioctl(comedi_device *dev,comedi_chaninfo *arg);
68 static int do_bufinfo_ioctl(comedi_device *dev,void *arg);
69 static int do_cmd_ioctl(comedi_device *dev,void *arg,void *file);
70 static int do_lock_ioctl(comedi_device *dev,unsigned int arg,void * file);
71 static int do_unlock_ioctl(comedi_device *dev,unsigned int arg,void * file);
72 static int do_cancel_ioctl(comedi_device *dev,unsigned int arg,void *file);
73 static int do_cmdtest_ioctl(comedi_device *dev,void *arg,void *file);
74 static int do_insnlist_ioctl(comedi_device *dev,void *arg,void *file);
75 static int do_insn_ioctl(comedi_device *dev,void *arg,void *file);
76 static int do_poll_ioctl(comedi_device *dev,unsigned int subd,void *file);
78 void do_become_nonbusy(comedi_device *dev,comedi_subdevice *s);
79 static int do_cancel(comedi_device *dev,comedi_subdevice *s);
81 static int comedi_fasync (int fd, struct file *file, int on);
82 static void init_async_buf( comedi_async *async );
84 static int comedi_ioctl(struct inode * inode,struct file * file,
85 unsigned int cmd,unsigned long arg)
87 unsigned int minor=MINOR(inode->i_rdev);
88 comedi_device *dev=comedi_get_device_by_minor(minor);
90 /* Device config is special, because it must work on
91 * an unconfigured device. */
92 if(cmd==COMEDI_DEVCONFIG){
93 return do_devconfig_ioctl(dev,(void *)arg,minor);
97 DPRINTK("no driver configured on /dev/comedi%i\n", dev->minor);
103 case COMEDI_BUFCONFIG:
104 return do_bufconfig_ioctl(dev,(void*)arg);
106 return do_devinfo_ioctl(dev,(void *)arg);
107 case COMEDI_SUBDINFO:
108 return do_subdinfo_ioctl(dev,(void *)arg,file);
109 case COMEDI_CHANINFO:
110 return do_chaninfo_ioctl(dev,(void *)arg);
111 case COMEDI_RANGEINFO:
112 return do_rangeinfo_ioctl(dev,(void *)arg);
114 return do_bufinfo_ioctl(dev,(void*)arg);
116 return do_lock_ioctl(dev,arg,file);
118 return do_unlock_ioctl(dev,arg,file);
120 return do_cancel_ioctl(dev,arg,file);
122 return do_cmd_ioctl(dev,(void *)arg,file);
124 return do_cmdtest_ioctl(dev,(void *)arg,file);
125 case COMEDI_INSNLIST:
126 return do_insnlist_ioctl(dev,(void *)arg,file);
128 return do_insn_ioctl(dev,(void *)arg,file);
130 return do_poll_ioctl(dev,arg,file);
142 pointer to devconfig structure
145 devconfig structure at arg
150 static int do_devconfig_ioctl(comedi_device *dev,comedi_devconfig *arg, unsigned int minor)
154 unsigned char *aux_data = NULL;
157 if(!capable(CAP_SYS_ADMIN))
161 return comedi_device_detach(dev);
164 if(copy_from_user(&it,arg,sizeof(comedi_devconfig)))
167 it.board_name[COMEDI_NAMELEN-1]=0;
169 if(comedi_aux_data(it.options, 0) &&
170 it.options[COMEDI_DEVCONF_AUX_DATA_LENGTH]){
172 aux_len = it.options[COMEDI_DEVCONF_AUX_DATA_LENGTH];
173 if(aux_len<0)return -EFAULT;
175 aux_data = vmalloc(aux_len);
176 if(!aux_data) return -ENOMEM;
178 if(copy_from_user(aux_data,
179 comedi_aux_data(it.options, 0), aux_len)){
183 it.options[COMEDI_DEVCONF_AUX_DATA_LO] = (unsigned long)aux_data;
184 if(sizeof(void*) > sizeof(int))
186 bit_shift = sizeof(int) * 8;
187 it.options[COMEDI_DEVCONF_AUX_DATA_HI] = ((unsigned long)aux_data) >> bit_shift;
189 it.options[COMEDI_DEVCONF_AUX_DATA_HI] = 0;
192 ret = comedi_device_attach(dev,&it);
194 if(aux_data) vfree(aux_data);
201 buffer configuration ioctl
204 pointer to bufconfig structure
210 modified bufconfig at arg
213 static int do_bufconfig_ioctl(comedi_device *dev,void *arg)
220 if(copy_from_user(&bc,arg,sizeof(comedi_bufconfig)))
223 if(bc.subdevice>=dev->n_subdevices || bc.subdevice<0)
226 s=dev->subdevices+bc.subdevice;
230 DPRINTK("subdevice does not have async capability\n");
237 if(!capable(CAP_SYS_ADMIN))return -EPERM;
239 async->max_bufsize = bc.maximum_size;
243 if(bc.size > async->max_bufsize)
248 DPRINTK("subdevice is busy, cannot resize buffer\n");
251 if(async->mmap_count){
252 DPRINTK("subdevice is mmapped, cannot resize buffer\n");
256 if(!async->prealloc_buf)
259 /* make sure buffer is an integral number of pages
261 bc.size = (bc.size + PAGE_SIZE - 1) & PAGE_MASK;
263 ret = comedi_buf_alloc(dev, s, bc.size);
264 if(ret < 0) return ret;
267 ret = s->buf_change(dev,s,bc.size);
268 if(ret < 0) return ret;
271 DPRINTK("comedi%i subd %d buffer resized to %i bytes\n",
272 dev->minor, bc.subdevice, async->prealloc_bufsz);
275 bc.size = async->prealloc_bufsz;
276 bc.maximum_size = async->max_bufsize;
279 if(copy_to_user(arg,&bc,sizeof(comedi_bufconfig)))
290 pointer to devinfo structure
299 static int do_devinfo_ioctl(comedi_device *dev,comedi_devinfo *arg)
301 comedi_devinfo devinfo;
303 memset(&devinfo,0,sizeof(devinfo));
305 /* fill devinfo structure */
306 devinfo.version_code=COMEDI_VERSION_CODE;
307 devinfo.n_subdevs=dev->n_subdevices;
308 memcpy(devinfo.driver_name,dev->driver->driver_name,COMEDI_NAMELEN);
309 memcpy(devinfo.board_name,dev->board_name,COMEDI_NAMELEN);
311 if(dev->read_subdev){
312 devinfo.read_subdevice = dev->read_subdev - dev->subdevices;
314 devinfo.read_subdevice = -1;
316 if(dev->write_subdev){
317 devinfo.write_subdevice = dev->write_subdev - dev->subdevices;
319 devinfo.write_subdevice = -1;
322 if(copy_to_user(arg,&devinfo,sizeof(comedi_devinfo)))
334 pointer to array of subdevice info structures
340 array of subdevice info structures at arg
343 static int do_subdinfo_ioctl(comedi_device *dev,comedi_subdinfo *arg,void *file)
346 comedi_subdinfo *tmp,*us;
350 tmp=kmalloc(dev->n_subdevices*sizeof(comedi_subdinfo),GFP_KERNEL);
354 memset(tmp,0,sizeof(comedi_subdinfo)*dev->n_subdevices);
356 /* fill subdinfo structs */
357 for(i=0;i<dev->n_subdevices;i++){
362 us->n_chan = s->n_chan;
363 us->subd_flags = s->subdev_flags;
364 #define TIMER_nanosec 5 /* backwards compatibility */
365 us->timer_type = TIMER_nanosec;
366 us->len_chanlist = s->len_chanlist;
367 us->maxdata = s->maxdata;
369 us->range_type = (dev->minor<<28)|(i<<24)|(0<<16)|
370 (s->range_table->length);
372 us->range_type = 0; /* XXX */
374 us->flags = s->flags;
377 us->subd_flags |= SDF_BUSY;
379 us->subd_flags |= SDF_BUSY_OWNER;
381 us->subd_flags |= SDF_LOCKED;
383 us->subd_flags |= SDF_LOCK_OWNER;
384 if(!s->maxdata && s->maxdata_list)
385 us->subd_flags |= SDF_MAXDATA;
387 us->subd_flags |= SDF_FLAGS;
388 if(s->range_table_list)
389 us->subd_flags |= SDF_RANGETYPE;
391 us->subd_flags |= SDF_CMD;
393 us->settling_time_0 = s->settling_time_0;
396 ret=copy_to_user(arg,tmp,dev->n_subdevices*sizeof(comedi_subdinfo));
400 return ret?-EFAULT:0;
409 pointer to chaninfo structure
412 chaninfo structure at arg
415 arrays at elements of chaninfo structure
418 static int do_chaninfo_ioctl(comedi_device *dev,comedi_chaninfo *arg)
423 if(copy_from_user(&it,arg,sizeof(comedi_chaninfo)))
426 if(it.subdev>=dev->n_subdevices)
428 s=dev->subdevices+it.subdev;
431 if(s->maxdata || !s->maxdata_list)
433 if(copy_to_user(it.maxdata_list,s->maxdata_list,s->n_chan*sizeof(lsampl_t)))
438 if(!s->flaglist)return -EINVAL;
439 if(copy_to_user(it.flaglist,s->flaglist,s->n_chan*sizeof(unsigned int)))
446 if(!s->range_table_list)return -EINVAL;
447 for(i=0;i<s->n_chan;i++){
450 x=(dev->minor<<28)|(it.subdev<<24)|(i<<16)|
451 (s->range_table_list[i]->length);
452 put_user(x,it.rangelist+i);
454 //if(copy_to_user(it.rangelist,s->range_type_list,s->n_chan*sizeof(unsigned int)))
463 buffer information ioctl
466 pointer to bufinfo structure
472 modified bufinfo at arg
475 static int do_bufinfo_ioctl(comedi_device *dev,void *arg)
481 if(copy_from_user(&bi,arg, sizeof(comedi_bufinfo)))
484 if(bi.subdevice >= dev->n_subdevices || bi.subdevice < 0)
487 s=dev->subdevices + bi.subdevice;
490 if(s!=dev->read_subdev && s!=dev->write_subdev)return -EINVAL;
493 DPRINTK("subdevice does not have async capability\n");
494 bi.buf_write_ptr = 0;
496 bi.buf_write_count = 0;
497 bi.buf_read_count = 0;
501 if(bi.bytes_read && s==dev->read_subdev){
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==dev->write_subdev){
512 bi.bytes_written = comedi_buf_write_alloc( async, bi.bytes_written );
513 comedi_buf_munge(dev, s, async->buf_write_alloc_count - async->munge_count);
514 comedi_buf_write_free(async, bi.bytes_written);
517 bi.buf_write_count = async->buf_write_count;
518 bi.buf_write_ptr = async->buf_write_ptr;
519 bi.buf_read_count = async->buf_read_count;
520 bi.buf_read_ptr = async->buf_read_ptr;
521 if(s==dev->read_subdev){
522 unsigned int n_munge_bytes;
524 n_munge_bytes = bi.buf_write_count - s->async->munge_count;
525 comedi_buf_munge(dev, s, n_munge_bytes);
529 if(copy_to_user(arg, &bi, sizeof(comedi_bufinfo)))
536 static int parse_insn(comedi_device *dev,comedi_insn *insn,lsampl_t *data,void *file);
539 * synchronous instructions
542 * pointer to sync cmd structure
545 * sync cmd struct at arg
552 /* arbitrary limits */
553 #define MAX_SAMPLES 256
554 static int do_insnlist_ioctl(comedi_device *dev,void *arg,void *file)
556 comedi_insnlist insnlist;
557 comedi_insn *insns = NULL;
558 lsampl_t *data = NULL;
562 if(copy_from_user(&insnlist,arg,sizeof(comedi_insnlist)))
565 data=kmalloc(sizeof(lsampl_t)*MAX_SAMPLES,GFP_KERNEL);
567 DPRINTK("kmalloc failed\n");
572 insns=kmalloc(sizeof(comedi_insn)*insnlist.n_insns,GFP_KERNEL);
574 DPRINTK("kmalloc failed\n");
579 if(copy_from_user(insns,insnlist.insns,sizeof(comedi_insn)*insnlist.n_insns)){
580 DPRINTK("copy_from_user failed\n");
585 for(i=0;i<insnlist.n_insns;i++){
586 if(insns[i].n>MAX_SAMPLES){
587 DPRINTK("number of samples too large\n");
591 if(insns[i].insn&INSN_MASK_WRITE){
592 if(copy_from_user(data,insns[i].data,
593 insns[i].n*sizeof(lsampl_t))){
594 DPRINTK("copy_from_user failed\n");
599 ret = parse_insn(dev,insns+i,data,file);
602 printk("BUG: result of insn != insn.n\n");
606 if(insns[i].insn&INSN_MASK_READ){
607 if(copy_to_user(insns[i].data,data,
608 insns[i].n*sizeof(lsampl_t))){
609 DPRINTK("copy_to_user failed\n");
619 if(insns)kfree(insns);
626 static int check_insn_config_length(comedi_insn *insn, lsampl_t *data)
630 case INSN_CONFIG_DIO_OUTPUT:
631 case INSN_CONFIG_DIO_INPUT:
632 if(insn->n == 1) return 0;
634 case INSN_CONFIG_DIO_QUERY:
635 case INSN_CONFIG_BLOCK_SIZE:
636 case INSN_CONFIG_SERIAL_CLOCK:
637 case INSN_CONFIG_BIDIRECTIONAL_DATA:
638 case INSN_CONFIG_SET_RTSI_CLOCK_MODE:
639 case INSN_CONFIG_ALT_SOURCE:
640 if( insn->n == 2 ) return 0;
642 case INSN_CONFIG_PWM_OUTPUT:
643 if(insn->n == 5) return 0;
645 //by default we allow the insn since we don't have checks for all possible cases yet
647 rt_printk("comedi: no check for data length of config insn id %i implemented. Assuming n=%i is correct.\n",
655 static int parse_insn(comedi_device *dev,comedi_insn *insn,lsampl_t *data,void *file)
660 if(insn->insn&INSN_MASK_SPECIAL){
661 /* a non-subdevice instruction */
673 do_gettimeofday(&tv);
681 if(insn->n!=1 || data[0]>=100000){
685 udelay(data[0]/1000);
693 if(insn->subdev>=dev->n_subdevices){
694 DPRINTK("%d not usable subdevice\n",insn->subdev);
698 s=dev->subdevices+insn->subdev;
700 DPRINTK("no async\n");
704 if(!s->async->inttrig){
705 DPRINTK("no inttrig\n");
709 ret = s->async->inttrig(dev,s,insn->data[0]);
713 DPRINTK("invalid insn\n");
718 /* a subdevice instruction */
719 if(insn->subdev>=dev->n_subdevices){
720 DPRINTK("subdevice %d out of range\n",insn->subdev);
724 s=dev->subdevices+insn->subdev;
726 if(s->type==COMEDI_SUBD_UNUSED){
727 DPRINTK("%d not usable subdevice\n",insn->subdev);
732 /* are we locked? (ioctl lock) */
733 if(s->lock && s->lock!=file){
734 DPRINTK("device locked\n");
739 if((ret=check_chanlist(s,1,&insn->chanspec))<0){
741 DPRINTK("bad chanspec\n");
749 /* This looks arbitrary. It is. */
753 ret=s->insn_read(dev,s,insn,data);
756 //XXX check against subdevice's maxdata
757 ret=s->insn_write(dev,s,insn,data);
760 ret=s->insn_bits(dev,s,insn,data);
763 ret=check_insn_config_length(insn, data);
765 ret=s->insn_config(dev,s,insn,data);
781 * synchronous instructions
787 * comedi_insn struct at arg
793 static int do_insn_ioctl(comedi_device *dev,void *arg,void *file)
796 lsampl_t *data = NULL;
799 data=kmalloc(sizeof(lsampl_t)*MAX_SAMPLES,GFP_KERNEL);
805 if(copy_from_user(&insn,arg,sizeof(comedi_insn))){
810 /* This is where the behavior of insn and insnlist deviate. */
811 if(insn.n>MAX_SAMPLES)insn.n=MAX_SAMPLES;
812 if(insn.insn&INSN_MASK_WRITE){
813 if(copy_from_user(data,insn.data,insn.n*sizeof(lsampl_t))){
818 ret = parse_insn(dev,&insn,data,file);
820 if(insn.insn&INSN_MASK_READ){
821 if(copy_to_user(insn.data,data,insn.n*sizeof(lsampl_t))){
839 pointer to cmd structure
846 modified cmd structure at arg
849 static int do_cmd_ioctl(comedi_device *dev,void *arg,void *file)
855 unsigned int *chanlist_saver=NULL;
857 if(copy_from_user(&user_cmd,arg,sizeof(comedi_cmd))){
858 DPRINTK("bad cmd address\n");
862 // save user's chanlist pointer so it can be restored later
863 chanlist_saver = user_cmd.chanlist;
865 if(user_cmd.subdev>=dev->n_subdevices){
866 DPRINTK("%d no such subdevice\n",user_cmd.subdev);
870 s=dev->subdevices+user_cmd.subdev;
873 if(s->type==COMEDI_SUBD_UNUSED){
874 DPRINTK("%d not valid subdevice\n",user_cmd.subdev);
878 if(!s->do_cmd || !s->async){
879 DPRINTK("subdevice %i does not support commands\n", user_cmd.subdev);
883 /* are we locked? (ioctl lock) */
884 if(s->lock && s->lock!=file){
885 DPRINTK("subdevice locked\n");
891 DPRINTK("subdevice busy\n");
896 /* make sure channel/gain list isn't too long */
897 if(user_cmd.chanlist_len > s->len_chanlist){
898 DPRINTK("channel/gain list too long %d > %d\n",user_cmd.chanlist_len,s->len_chanlist);
903 if(async->cmd.chanlist) kfree(async->cmd.chanlist);
905 async->cmd.data=NULL;
906 /* load channel/gain list */
907 async->cmd.chanlist=kmalloc(async->cmd.chanlist_len*sizeof(int),GFP_KERNEL);
908 if(!async->cmd.chanlist){
909 DPRINTK("allocation failed\n");
914 if(copy_from_user(async->cmd.chanlist,user_cmd.chanlist,async->cmd.chanlist_len*sizeof(int))){
915 DPRINTK("fault reading chanlist\n");
920 /* make sure each element in channel/gain list is valid */
921 if((ret=check_chanlist(s,async->cmd.chanlist_len,async->cmd.chanlist))<0){
922 DPRINTK("bad chanlist\n");
926 ret=s->do_cmdtest(dev,s,&async->cmd);
928 if(async->cmd.flags&TRIG_BOGUS || ret){
929 DPRINTK("test returned %d\n",ret);
931 // restore chanlist pointer before copying back
932 user_cmd.chanlist = chanlist_saver;
933 user_cmd.data = NULL;
934 if(copy_to_user(arg,&user_cmd,sizeof(comedi_cmd))){
935 DPRINTK("fault writing cmd\n");
943 if(!async->prealloc_bufsz){
945 DPRINTK("no buffer (?)\n");
949 init_async_buf( async );
951 async->cb_mask = COMEDI_CB_EOA | COMEDI_CB_BLOCK | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
952 if(async->cmd.flags & TRIG_WAKE_EOS){
953 async->cb_mask |= COMEDI_CB_EOS;
956 s->runflags=SRF_USER;
958 s->subdev_flags|=SDF_RUNNING;
960 #ifdef CONFIG_COMEDI_RT
961 if(async->cmd.flags&TRIG_RT){
962 comedi_switch_to_rt(dev);
963 s->runflags |= SRF_RT;
967 ret=s->do_cmd(dev,s);
972 do_become_nonbusy(dev,s);
979 command testing ioctl
982 pointer to cmd structure
989 modified cmd structure at arg
992 static int do_cmdtest_ioctl(comedi_device *dev,void *arg,void *file)
997 unsigned int *chanlist=NULL;
998 unsigned int *chanlist_saver=NULL;
1000 if(copy_from_user(&user_cmd,arg,sizeof(comedi_cmd))){
1001 DPRINTK("bad cmd address\n");
1005 // save user's chanlist pointer so it can be restored later
1006 chanlist_saver = user_cmd.chanlist;
1008 if(user_cmd.subdev>=dev->n_subdevices){
1009 DPRINTK("%d no such subdevice\n",user_cmd.subdev);
1013 s=dev->subdevices+user_cmd.subdev;
1014 if(s->type==COMEDI_SUBD_UNUSED){
1015 DPRINTK("%d not valid subdevice\n",user_cmd.subdev);
1020 DPRINTK("subdevice %i does not support commands\n", user_cmd.subdev);
1024 /* make sure channel/gain list isn't too long */
1025 if(user_cmd.chanlist_len > s->len_chanlist){
1026 DPRINTK("channel/gain list too long %d > %d\n",user_cmd.chanlist_len,s->len_chanlist);
1031 /* load channel/gain list */
1032 if(user_cmd.chanlist){
1033 chanlist=kmalloc(user_cmd.chanlist_len*sizeof(int),GFP_KERNEL);
1035 DPRINTK("allocation failed\n");
1040 if(copy_from_user(chanlist,user_cmd.chanlist,user_cmd.chanlist_len*sizeof(int))){
1041 DPRINTK("fault reading chanlist\n");
1046 /* make sure each element in channel/gain list is valid */
1047 if((ret=check_chanlist(s,user_cmd.chanlist_len,chanlist))<0){
1048 DPRINTK("bad chanlist\n");
1052 user_cmd.chanlist=chanlist;
1055 ret=s->do_cmdtest(dev,s,&user_cmd);
1057 // restore chanlist pointer before copying back
1058 user_cmd.chanlist = chanlist_saver;
1060 if(copy_to_user(arg,&user_cmd,sizeof(comedi_cmd))){
1061 DPRINTK("bad cmd address\n");
1087 static int do_lock_ioctl(comedi_device *dev,unsigned int arg,void * file)
1090 unsigned long flags;
1091 comedi_subdevice *s;
1093 if(arg>=dev->n_subdevices)
1095 s=dev->subdevices+arg;
1097 comedi_spin_lock_irqsave(&big_comedi_lock, flags);
1100 comedi_spin_unlock_irqrestore(&big_comedi_lock, flags);
1108 comedi_spin_unlock_irqrestore(&big_comedi_lock, flags);
1115 ret=s->lock_f(dev,s);
1135 This function isn't protected by the semaphore, since
1136 we already own the lock.
1138 static int do_unlock_ioctl(comedi_device *dev,unsigned int arg,void * file)
1140 comedi_subdevice *s;
1142 if(arg>=dev->n_subdevices)
1144 s=dev->subdevices+arg;
1149 if(s->lock && s->lock!=file)
1166 cancel acquisition ioctl
1178 static int do_cancel_ioctl(comedi_device *dev,unsigned int arg,void *file)
1180 comedi_subdevice *s;
1182 if(arg>=dev->n_subdevices)
1184 s=dev->subdevices+arg;
1186 if(s->lock && s->lock!=file)
1195 return do_cancel(dev,s);
1200 instructs driver to synchronize buffers
1212 static int do_poll_ioctl(comedi_device *dev,unsigned int arg,void *file)
1214 comedi_subdevice *s;
1216 if(arg>=dev->n_subdevices)
1218 s=dev->subdevices+arg;
1220 if(s->lock && s->lock!=file)
1229 if(s->poll)return s->poll(dev,s);
1234 static int do_cancel(comedi_device *dev,comedi_subdevice *s)
1238 if((s->subdev_flags&SDF_RUNNING) && s->cancel)
1239 ret=s->cancel(dev,s);
1241 do_become_nonbusy(dev,s);
1247 #define RDEV_OF_FILE(x) ((x)->f_dentry->d_inode->i_rdev)
1249 void comedi_unmap(struct vm_area_struct *area)
1251 comedi_async *async;
1253 async = area->vm_private_data;
1255 async->mmap_count--;
1258 static struct vm_operations_struct comedi_vm_ops={
1259 close: comedi_unmap,
1262 static int comedi_mmap(struct file * file, struct vm_area_struct *vma)
1264 unsigned int minor=MINOR(RDEV_OF_FILE(file));
1265 comedi_device *dev=comedi_get_device_by_minor(minor);
1266 comedi_async *async = NULL;
1267 unsigned long start = vma->vm_start;
1274 DPRINTK("no driver configured on comedi%i\n", dev->minor);
1278 if(vma->vm_flags & VM_WRITE){
1279 async=dev->write_subdev->async;
1281 async=dev->read_subdev->async;
1287 if(vma->vm_pgoff != 0){
1288 DPRINTK("comedi: mmap() offset must be 0.\n");
1292 size = vma->vm_end - vma->vm_start;
1293 if(size>async->prealloc_bufsz)
1295 if(size&(~PAGE_MASK))
1298 n_pages = size >> PAGE_SHIFT;
1299 for(i=0;i<n_pages;i++){
1300 if(remap_pfn_range(vma, start, __pa(async->buf_page_list[i]) >> PAGE_SHIFT,
1301 PAGE_SIZE, PAGE_SHARED)){
1307 vma->vm_ops = &comedi_vm_ops;
1308 vma->vm_private_data = async;
1310 async->mmap_count++;
1316 static unsigned int comedi_poll(struct file *file, poll_table * wait)
1319 comedi_subdevice *s;
1320 comedi_async *async;
1323 dev=comedi_get_device_by_minor(MINOR(RDEV_OF_FILE(file)));
1327 DPRINTK("no driver configured on comedi%i\n", dev->minor);
1331 poll_wait(file, &dev->read_wait, wait);
1332 poll_wait(file, &dev->write_wait, wait);
1334 if(dev->read_subdev && dev->read_subdev->async){
1335 s = dev->read_subdev;
1338 || comedi_buf_read_n_available(s)>0
1339 || !(s->subdev_flags&SDF_RUNNING)){
1340 mask |= POLLIN | POLLRDNORM;
1343 if(dev->write_subdev && dev->write_subdev->async){
1344 s = dev->write_subdev;
1347 || !(s->subdev_flags&SDF_RUNNING)
1348 || comedi_buf_write_n_available(s)>0){
1349 mask |= POLLOUT | POLLWRNORM;
1356 static ssize_t comedi_write(struct file *file,const char *buf,size_t nbytes,loff_t *offset)
1359 comedi_subdevice *s;
1360 comedi_async *async;
1361 int n,m,count=0,retval=0;
1362 DECLARE_WAITQUEUE(wait,current);
1364 dev=comedi_get_device_by_minor(MINOR(RDEV_OF_FILE(file)));
1368 DPRINTK("no driver configured on comedi%i\n", dev->minor);
1372 if(dev->write_subdev == NULL)return -EIO;
1373 s = dev->write_subdev;
1376 if(!nbytes)return 0;
1384 add_wait_queue(&dev->write_wait,&wait);
1385 while(nbytes>0 && !retval){
1386 current->state=TASK_INTERRUPTIBLE;
1391 if(async->buf_write_ptr + m > async->prealloc_bufsz){
1392 m = async->prealloc_bufsz - async->buf_write_ptr;
1394 m = comedi_buf_write_alloc(async, m);
1399 if(file->f_flags&O_NONBLOCK){
1403 if(signal_pending(current)){
1404 retval=-ERESTARTSYS;
1407 if(!(s->subdev_flags&SDF_RUNNING)){
1408 if(s->runflags & SRF_ERROR){
1413 do_become_nonbusy(dev,s);
1420 m = copy_from_user(async->prealloc_buf + async->buf_write_ptr,
1426 comedi_buf_munge(dev, s, async->buf_write_alloc_count - async->munge_count);
1427 comedi_buf_write_free(async, n);
1433 break; /* makes device work like a pipe */
1435 current->state=TASK_RUNNING;
1436 remove_wait_queue(&dev->write_wait,&wait);
1438 return (count ? count : retval);
1442 static ssize_t comedi_read(struct file * file,char *buf,size_t nbytes,loff_t *offset)
1445 comedi_subdevice *s;
1446 comedi_async *async;
1447 int n,m,count=0,retval=0;
1448 DECLARE_WAITQUEUE(wait,current);
1450 dev=comedi_get_device_by_minor(MINOR(RDEV_OF_FILE(file)));
1454 DPRINTK("no driver configured on comedi%i\n", dev->minor);
1458 s = dev->read_subdev;
1459 if(s == NULL)return -EIO;
1462 if(!nbytes)return 0;
1470 add_wait_queue(&dev->read_wait,&wait);
1471 while(nbytes>0 && !retval){
1472 current->state=TASK_INTERRUPTIBLE;
1476 m = comedi_buf_read_n_available(s);
1477 //printk("%d available\n",m);
1478 if(async->buf_read_ptr + m > async->prealloc_bufsz){
1479 m = async->prealloc_bufsz - async->buf_read_ptr;
1481 //printk("%d contiguous\n",m);
1485 if(!(s->subdev_flags&SDF_RUNNING)){
1486 do_become_nonbusy(dev,s);
1487 if(s->runflags & SRF_ERROR){
1494 if(file->f_flags&O_NONBLOCK){
1498 if(signal_pending(current)){
1499 retval=-ERESTARTSYS;
1505 comedi_buf_munge(dev, s, async->buf_write_count - async->munge_count);
1506 m = copy_to_user(buf, async->prealloc_buf +
1507 async->buf_read_ptr, n);
1513 comedi_buf_read_free(async, n);
1519 break; /* makes device work like a pipe */
1521 if(!(s->subdev_flags&SDF_RUNNING) &&
1522 !(s->runflags & SRF_ERROR) &&
1523 async->buf_read_count - async->buf_write_count == 0)
1525 do_become_nonbusy(dev,s);
1527 current->state=TASK_RUNNING;
1528 remove_wait_queue(&dev->read_wait,&wait);
1530 return (count ? count : retval);
1534 This function restores a subdevice to an idle state.
1536 void do_become_nonbusy(comedi_device *dev,comedi_subdevice *s)
1538 comedi_async *async = s->async;
1539 /* we do this because it's useful for the non-standard cases */
1540 s->subdev_flags &= ~SDF_RUNNING;
1542 #ifdef CONFIG_COMEDI_RT
1543 if(s->runflags&SRF_RT){
1544 comedi_switch_to_non_rt(dev);
1545 s->runflags &= ~SRF_RT;
1550 init_async_buf( async );
1552 printk("BUG: (?) do_become_nonbusy called with async=0\n");
1558 /* no chance that these will change soon */
1563 static loff_t comedi_lseek(struct file *file,loff_t offset,int origin)
1568 dev=comedi_get_device_by_minor(MINOR(RDEV_OF_FILE(file)));
1572 new_offset = offset;
1575 new_offset = file->f_pos + offset;
1578 new_offset = dev->n_subdevices + offset;
1583 if(new_offset<0 || new_offset >= dev->n_subdevices)
1586 return file->f_pos=new_offset;
1589 static int comedi_open(struct inode *inode,struct file *file)
1591 unsigned int minor=MINOR(inode->i_rdev);
1595 if(minor>=COMEDI_NDEVICES){
1596 DPRINTK("invalid minor number\n");
1599 dev=comedi_get_device_by_minor(minor);
1601 /* This is slightly hacky, but we want module autoloading
1603 * case: user opens device, attached -> ok
1604 * case: user opens device, unattached, in_request_module=0 -> autoload
1605 * case: user opens device, unattached, in_request_module=1 -> fail
1606 * case: root opens device, attached -> ok
1607 * case: root opens device, unattached, in_request_module=1 -> ok
1608 * (typically called from modprobe)
1609 * case: root opens device, unattached, in_request_module=0 -> autoload
1611 * The last could be changed to "-> ok", which would deny root
1616 if(!capable(CAP_SYS_MODULE) && dev->in_request_module){
1617 DPRINTK("in request module\n");
1620 if(capable(CAP_SYS_MODULE) && dev->in_request_module)
1623 dev->in_request_module=1;
1625 sprintf(mod,"char-major-%i-%i",COMEDI_MAJOR,minor);
1627 request_module(mod);
1630 dev->in_request_module=0;
1632 if(!dev->attached && !capable(CAP_SYS_MODULE)){
1633 DPRINTK("not attached and not CAP_SYS_MODULE\n");
1637 if(!try_module_get(THIS_MODULE))
1641 try_module_get( dev->driver->module );
1644 if(dev->attached && dev->use_count==0 && dev->open){
1653 static int comedi_close(struct inode *inode,struct file *file)
1655 comedi_device *dev=comedi_get_device_by_minor(MINOR(inode->i_rdev));
1656 comedi_subdevice *s = NULL;
1661 for(i=0;i<dev->n_subdevices;i++){
1662 s=dev->subdevices+i;
1672 if(dev->attached && dev->use_count==1 && dev->close){
1676 module_put(THIS_MODULE);
1678 module_put(dev->driver->module);
1683 if(file->f_flags & FASYNC){
1684 comedi_fasync(-1,file,0);
1690 static int comedi_fasync (int fd, struct file *file, int on)
1692 comedi_device *dev=comedi_get_device_by_minor(MINOR(RDEV_OF_FILE(file)));
1694 return fasync_helper(fd,file,on,&dev->async_queue);
1698 static struct file_operations comedi_fops={
1699 owner : THIS_MODULE,
1700 llseek : comedi_lseek,
1701 ioctl : comedi_ioctl,
1703 release : comedi_close,
1705 write : comedi_write,
1708 fasync : comedi_fasync,
1711 static struct class *comedi_class;
1713 static int __init comedi_init(void)
1717 printk("comedi: version " COMEDI_RELEASE " - David Schleef <ds@schleef.org>\n");
1718 spin_lock_init(&big_comedi_lock);
1719 if(devfs_register_chrdev(COMEDI_MAJOR,"comedi",&comedi_fops)){
1720 printk("comedi: unable to get major %d\n",COMEDI_MAJOR);
1723 comedi_class = class_create(THIS_MODULE, "comedi");
1724 if(IS_ERR(comedi_class))
1726 printk("comedi: failed to create class");
1727 devfs_unregister_chrdev(COMEDI_MAJOR,"comedi");
1728 return PTR_ERR(comedi_class);
1730 comedi_devices=(comedi_device *)kmalloc(sizeof(comedi_device)*COMEDI_NDEVICES,GFP_KERNEL);
1733 class_destroy(comedi_class);
1734 devfs_unregister_chrdev(COMEDI_MAJOR,"comedi");
1737 memset(comedi_devices,0,sizeof(comedi_device)*COMEDI_NDEVICES);
1738 for(i=0;i<COMEDI_NDEVICES;i++){
1739 comedi_devices[i].minor=i;
1740 spin_lock_init(&(comedi_devices[i].spinlock));
1743 /* XXX requires /proc interface */
1746 for(i=0;i<COMEDI_NDEVICES;i++){
1748 sprintf(name, "comedi%d", i);
1749 devfs_register(NULL, name, DEVFS_FL_DEFAULT,
1750 COMEDI_MAJOR, i, 0666 | S_IFCHR, &comedi_fops, NULL);
1751 COMEDI_CLASS_DEVICE_CREATE(comedi_class, 0,
1752 MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i", i);
1760 static void __exit comedi_cleanup(void)
1765 printk("comedi: module in use -- remove delayed\n");
1767 for(i=0;i<COMEDI_NDEVICES;i++){
1769 class_device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, i));
1770 sprintf(name, "comedi%d", i);
1771 devfs_unregister(devfs_find_handle(NULL, name,
1772 COMEDI_MAJOR, i, DEVFS_SPECIAL_CHR, 0));
1774 class_destroy(comedi_class);
1775 devfs_unregister_chrdev(COMEDI_MAJOR,"comedi");
1777 comedi_proc_cleanup();
1779 for(i=0;i<COMEDI_NDEVICES;i++){
1782 dev=comedi_get_device_by_minor(i);
1784 comedi_device_detach(dev);
1786 kfree(comedi_devices);
1788 comedi_rt_cleanup();
1791 module_init(comedi_init);
1792 module_exit(comedi_cleanup);
1794 void comedi_error(const comedi_device *dev,const char *s)
1796 rt_printk("comedi%d: %s: %s\n",dev->minor,dev->driver->driver_name,s);
1799 void comedi_event(comedi_device *dev,comedi_subdevice *s, unsigned int mask)
1801 comedi_async *async = s->async;
1803 mask = s->async->events;
1804 s->async->events = 0;
1806 //DPRINTK("comedi_event %x\n",mask);
1808 if( (s->subdev_flags & SDF_RUNNING) == 0)
1811 if(mask&(COMEDI_CB_EOA|COMEDI_CB_ERROR|COMEDI_CB_OVERFLOW)){
1812 s->subdev_flags &= ~SDF_RUNNING;
1815 /* remember if an error event has occured, so an error
1816 * can be returned the next time the user does a read() */
1817 if(mask & (COMEDI_CB_ERROR|COMEDI_CB_OVERFLOW)){
1818 s->runflags |= SRF_ERROR;
1820 if(async->cb_mask&mask){
1821 if(s->runflags&SRF_USER){
1824 #ifdef CONFIG_COMEDI_RT
1826 if(s==dev->read_subdev)
1827 comedi_rt_pend_wakeup(&dev->read_wait);
1828 if(s==dev->write_subdev)
1829 comedi_rt_pend_wakeup(&dev->write_wait);
1831 printk("BUG: comedi_event() code unreachable\n");
1834 if(s==dev->read_subdev){
1835 wake_up_interruptible(&dev->read_wait);
1836 kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
1838 if(s==dev->write_subdev){
1839 wake_up_interruptible(&dev->write_wait);
1840 kill_fasync(&dev->async_queue, SIGIO, POLL_OUT);
1844 if(async->cb_func)async->cb_func(mask,async->cb_arg);
1845 /* XXX bug here. If subdevice A is rt, and
1846 * subdevice B tries to callback to a normal
1847 * linux kernel function, it will be at the
1848 * wrong priority. Since this isn't very
1849 * common, I'm not going to worry about it. */
1854 static void init_async_buf( comedi_async *async )
1856 async->buf_write_alloc_count = 0;
1857 async->buf_write_count = 0;
1858 async->buf_read_count = 0;
1860 async->buf_write_ptr = 0;
1861 async->buf_read_ptr = 0;
1863 async->cur_chan = 0;
1864 async->scan_progress = 0;
1865 async->munge_chan = 0;
1866 async->munge_count = 0;
1867 async->munge_ptr = 0;