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_ALT_SOURCE:
639 case INSN_CONFIG_8254_SET_MODE:
640 case INSN_CONFIG_8254_READ_STATUS:
641 case INSN_CONFIG_SET_GATE_SRC:
642 case INSN_CONFIG_GET_GATE_SRC:
643 case INSN_CONFIG_SET_ROUTING:
644 case INSN_CONFIG_GET_ROUTING:
645 if(insn->n == 2) return 0;
647 case INSN_CONFIG_SET_CLOCK_SRC:
648 case INSN_CONFIG_GET_CLOCK_SRC:
649 if(insn->n == 3) return 0;
651 case INSN_CONFIG_PWM_OUTPUT:
652 if(insn->n == 5) return 0;
654 //by default we allow the insn since we don't have checks for all possible cases yet
656 rt_printk("comedi: no check for data length of config insn id %i is implemented.\n"
657 " Add a check to %s in %s.\n"
658 " Assuming n=%i is correct.\n",
659 data[0], __FUNCTION__, __FILE__, insn->n);
666 static int parse_insn(comedi_device *dev,comedi_insn *insn,lsampl_t *data,void *file)
671 if(insn->insn&INSN_MASK_SPECIAL){
672 /* a non-subdevice instruction */
684 do_gettimeofday(&tv);
692 if(insn->n!=1 || data[0]>=100000){
696 udelay(data[0]/1000);
704 if(insn->subdev>=dev->n_subdevices){
705 DPRINTK("%d not usable subdevice\n",insn->subdev);
709 s=dev->subdevices+insn->subdev;
711 DPRINTK("no async\n");
715 if(!s->async->inttrig){
716 DPRINTK("no inttrig\n");
720 ret = s->async->inttrig(dev,s,insn->data[0]);
724 DPRINTK("invalid insn\n");
729 /* a subdevice instruction */
730 if(insn->subdev>=dev->n_subdevices){
731 DPRINTK("subdevice %d out of range\n",insn->subdev);
735 s=dev->subdevices+insn->subdev;
737 if(s->type==COMEDI_SUBD_UNUSED){
738 DPRINTK("%d not usable subdevice\n",insn->subdev);
743 /* are we locked? (ioctl lock) */
744 if(s->lock && s->lock!=file){
745 DPRINTK("device locked\n");
750 if((ret=check_chanlist(s,1,&insn->chanspec))<0){
752 DPRINTK("bad chanspec\n");
760 /* This looks arbitrary. It is. */
764 ret=s->insn_read(dev,s,insn,data);
767 //XXX check against subdevice's maxdata
768 ret=s->insn_write(dev,s,insn,data);
771 ret=s->insn_bits(dev,s,insn,data);
774 ret=check_insn_config_length(insn, data);
776 ret=s->insn_config(dev,s,insn,data);
792 * synchronous instructions
798 * comedi_insn struct at arg
804 static int do_insn_ioctl(comedi_device *dev,void *arg,void *file)
807 lsampl_t *data = NULL;
810 data=kmalloc(sizeof(lsampl_t)*MAX_SAMPLES,GFP_KERNEL);
816 if(copy_from_user(&insn,arg,sizeof(comedi_insn))){
821 /* This is where the behavior of insn and insnlist deviate. */
822 if(insn.n>MAX_SAMPLES)insn.n=MAX_SAMPLES;
823 if(insn.insn&INSN_MASK_WRITE){
824 if(copy_from_user(data,insn.data,insn.n*sizeof(lsampl_t))){
829 ret = parse_insn(dev,&insn,data,file);
831 if(insn.insn&INSN_MASK_READ){
832 if(copy_to_user(insn.data,data,insn.n*sizeof(lsampl_t))){
850 pointer to cmd structure
857 modified cmd structure at arg
860 static int do_cmd_ioctl(comedi_device *dev,void *arg,void *file)
866 unsigned int *chanlist_saver=NULL;
868 if(copy_from_user(&user_cmd,arg,sizeof(comedi_cmd))){
869 DPRINTK("bad cmd address\n");
873 // save user's chanlist pointer so it can be restored later
874 chanlist_saver = user_cmd.chanlist;
876 if(user_cmd.subdev>=dev->n_subdevices){
877 DPRINTK("%d no such subdevice\n",user_cmd.subdev);
881 s=dev->subdevices+user_cmd.subdev;
884 if(s->type==COMEDI_SUBD_UNUSED){
885 DPRINTK("%d not valid subdevice\n",user_cmd.subdev);
889 if(!s->do_cmd || !s->async){
890 DPRINTK("subdevice %i does not support commands\n", user_cmd.subdev);
894 /* are we locked? (ioctl lock) */
895 if(s->lock && s->lock!=file){
896 DPRINTK("subdevice locked\n");
902 DPRINTK("subdevice busy\n");
907 /* make sure channel/gain list isn't too long */
908 if(user_cmd.chanlist_len > s->len_chanlist){
909 DPRINTK("channel/gain list too long %d > %d\n",user_cmd.chanlist_len,s->len_chanlist);
914 if(async->cmd.chanlist) kfree(async->cmd.chanlist);
916 async->cmd.data=NULL;
917 /* load channel/gain list */
918 async->cmd.chanlist=kmalloc(async->cmd.chanlist_len*sizeof(int),GFP_KERNEL);
919 if(!async->cmd.chanlist){
920 DPRINTK("allocation failed\n");
925 if(copy_from_user(async->cmd.chanlist,user_cmd.chanlist,async->cmd.chanlist_len*sizeof(int))){
926 DPRINTK("fault reading chanlist\n");
931 /* make sure each element in channel/gain list is valid */
932 if((ret=check_chanlist(s,async->cmd.chanlist_len,async->cmd.chanlist))<0){
933 DPRINTK("bad chanlist\n");
937 ret=s->do_cmdtest(dev,s,&async->cmd);
939 if(async->cmd.flags&TRIG_BOGUS || ret){
940 DPRINTK("test returned %d\n",ret);
942 // restore chanlist pointer before copying back
943 user_cmd.chanlist = chanlist_saver;
944 user_cmd.data = NULL;
945 if(copy_to_user(arg,&user_cmd,sizeof(comedi_cmd))){
946 DPRINTK("fault writing cmd\n");
954 if(!async->prealloc_bufsz){
956 DPRINTK("no buffer (?)\n");
960 init_async_buf( async );
962 async->cb_mask = COMEDI_CB_EOA | COMEDI_CB_BLOCK | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
963 if(async->cmd.flags & TRIG_WAKE_EOS){
964 async->cb_mask |= COMEDI_CB_EOS;
967 s->runflags=SRF_USER;
969 s->subdev_flags|=SDF_RUNNING;
971 #ifdef CONFIG_COMEDI_RT
972 if(async->cmd.flags&TRIG_RT){
973 comedi_switch_to_rt(dev);
974 s->runflags |= SRF_RT;
978 ret=s->do_cmd(dev,s);
983 do_become_nonbusy(dev,s);
990 command testing ioctl
993 pointer to cmd structure
1000 modified cmd structure at arg
1003 static int do_cmdtest_ioctl(comedi_device *dev,void *arg,void *file)
1005 comedi_cmd user_cmd;
1006 comedi_subdevice *s;
1008 unsigned int *chanlist=NULL;
1009 unsigned int *chanlist_saver=NULL;
1011 if(copy_from_user(&user_cmd,arg,sizeof(comedi_cmd))){
1012 DPRINTK("bad cmd address\n");
1016 // save user's chanlist pointer so it can be restored later
1017 chanlist_saver = user_cmd.chanlist;
1019 if(user_cmd.subdev>=dev->n_subdevices){
1020 DPRINTK("%d no such subdevice\n",user_cmd.subdev);
1024 s=dev->subdevices+user_cmd.subdev;
1025 if(s->type==COMEDI_SUBD_UNUSED){
1026 DPRINTK("%d not valid subdevice\n",user_cmd.subdev);
1031 DPRINTK("subdevice %i does not support commands\n", user_cmd.subdev);
1035 /* make sure channel/gain list isn't too long */
1036 if(user_cmd.chanlist_len > s->len_chanlist){
1037 DPRINTK("channel/gain list too long %d > %d\n",user_cmd.chanlist_len,s->len_chanlist);
1042 /* load channel/gain list */
1043 if(user_cmd.chanlist){
1044 chanlist=kmalloc(user_cmd.chanlist_len*sizeof(int),GFP_KERNEL);
1046 DPRINTK("allocation failed\n");
1051 if(copy_from_user(chanlist,user_cmd.chanlist,user_cmd.chanlist_len*sizeof(int))){
1052 DPRINTK("fault reading chanlist\n");
1057 /* make sure each element in channel/gain list is valid */
1058 if((ret=check_chanlist(s,user_cmd.chanlist_len,chanlist))<0){
1059 DPRINTK("bad chanlist\n");
1063 user_cmd.chanlist=chanlist;
1066 ret=s->do_cmdtest(dev,s,&user_cmd);
1068 // restore chanlist pointer before copying back
1069 user_cmd.chanlist = chanlist_saver;
1071 if(copy_to_user(arg,&user_cmd,sizeof(comedi_cmd))){
1072 DPRINTK("bad cmd address\n");
1098 static int do_lock_ioctl(comedi_device *dev,unsigned int arg,void * file)
1101 unsigned long flags;
1102 comedi_subdevice *s;
1104 if(arg>=dev->n_subdevices)
1106 s=dev->subdevices+arg;
1108 comedi_spin_lock_irqsave(&big_comedi_lock, flags);
1111 comedi_spin_unlock_irqrestore(&big_comedi_lock, flags);
1119 comedi_spin_unlock_irqrestore(&big_comedi_lock, flags);
1126 ret=s->lock_f(dev,s);
1146 This function isn't protected by the semaphore, since
1147 we already own the lock.
1149 static int do_unlock_ioctl(comedi_device *dev,unsigned int arg,void * file)
1151 comedi_subdevice *s;
1153 if(arg>=dev->n_subdevices)
1155 s=dev->subdevices+arg;
1160 if(s->lock && s->lock!=file)
1177 cancel acquisition ioctl
1189 static int do_cancel_ioctl(comedi_device *dev,unsigned int arg,void *file)
1191 comedi_subdevice *s;
1193 if(arg>=dev->n_subdevices)
1195 s=dev->subdevices+arg;
1197 if(s->lock && s->lock!=file)
1206 return do_cancel(dev,s);
1211 instructs driver to synchronize buffers
1223 static int do_poll_ioctl(comedi_device *dev,unsigned int arg,void *file)
1225 comedi_subdevice *s;
1227 if(arg>=dev->n_subdevices)
1229 s=dev->subdevices+arg;
1231 if(s->lock && s->lock!=file)
1240 if(s->poll)return s->poll(dev,s);
1245 static int do_cancel(comedi_device *dev,comedi_subdevice *s)
1249 if((s->subdev_flags&SDF_RUNNING) && s->cancel)
1250 ret=s->cancel(dev,s);
1252 do_become_nonbusy(dev,s);
1258 #define RDEV_OF_FILE(x) ((x)->f_dentry->d_inode->i_rdev)
1260 void comedi_unmap(struct vm_area_struct *area)
1262 comedi_async *async;
1264 async = area->vm_private_data;
1266 async->mmap_count--;
1269 static struct vm_operations_struct comedi_vm_ops={
1270 close: comedi_unmap,
1273 static int comedi_mmap(struct file * file, struct vm_area_struct *vma)
1275 unsigned int minor=MINOR(RDEV_OF_FILE(file));
1276 comedi_device *dev=comedi_get_device_by_minor(minor);
1277 comedi_async *async = NULL;
1278 unsigned long start = vma->vm_start;
1285 DPRINTK("no driver configured on comedi%i\n", dev->minor);
1289 if(vma->vm_flags & VM_WRITE){
1290 async=dev->write_subdev->async;
1292 async=dev->read_subdev->async;
1298 if(vma->vm_pgoff != 0){
1299 DPRINTK("comedi: mmap() offset must be 0.\n");
1303 size = vma->vm_end - vma->vm_start;
1304 if(size>async->prealloc_bufsz)
1306 if(size&(~PAGE_MASK))
1309 n_pages = size >> PAGE_SHIFT;
1310 for(i=0;i<n_pages;i++){
1311 if(remap_pfn_range(vma, start, __pa(async->buf_page_list[i]) >> PAGE_SHIFT,
1312 PAGE_SIZE, PAGE_SHARED)){
1318 vma->vm_ops = &comedi_vm_ops;
1319 vma->vm_private_data = async;
1321 async->mmap_count++;
1327 static unsigned int comedi_poll(struct file *file, poll_table * wait)
1330 comedi_subdevice *s;
1331 comedi_async *async;
1334 dev=comedi_get_device_by_minor(MINOR(RDEV_OF_FILE(file)));
1338 DPRINTK("no driver configured on comedi%i\n", dev->minor);
1342 poll_wait(file, &dev->read_wait, wait);
1343 poll_wait(file, &dev->write_wait, wait);
1345 if(dev->read_subdev && dev->read_subdev->async){
1346 s = dev->read_subdev;
1349 || comedi_buf_read_n_available(s)>0
1350 || !(s->subdev_flags&SDF_RUNNING)){
1351 mask |= POLLIN | POLLRDNORM;
1354 if(dev->write_subdev && dev->write_subdev->async){
1355 s = dev->write_subdev;
1358 || !(s->subdev_flags&SDF_RUNNING)
1359 || comedi_buf_write_n_available(s)>0){
1360 mask |= POLLOUT | POLLWRNORM;
1367 static ssize_t comedi_write(struct file *file,const char *buf,size_t nbytes,loff_t *offset)
1370 comedi_subdevice *s;
1371 comedi_async *async;
1372 int n,m,count=0,retval=0;
1373 DECLARE_WAITQUEUE(wait,current);
1375 dev=comedi_get_device_by_minor(MINOR(RDEV_OF_FILE(file)));
1379 DPRINTK("no driver configured on comedi%i\n", dev->minor);
1383 if(dev->write_subdev == NULL)return -EIO;
1384 s = dev->write_subdev;
1387 if(!nbytes)return 0;
1395 add_wait_queue(&dev->write_wait,&wait);
1396 while(nbytes>0 && !retval){
1397 current->state=TASK_INTERRUPTIBLE;
1402 if(async->buf_write_ptr + m > async->prealloc_bufsz){
1403 m = async->prealloc_bufsz - async->buf_write_ptr;
1405 m = comedi_buf_write_alloc(async, m);
1410 if(file->f_flags&O_NONBLOCK){
1414 if(signal_pending(current)){
1415 retval=-ERESTARTSYS;
1418 if(!(s->subdev_flags&SDF_RUNNING)){
1419 if(s->runflags & SRF_ERROR){
1424 do_become_nonbusy(dev,s);
1431 m = copy_from_user(async->prealloc_buf + async->buf_write_ptr,
1437 comedi_buf_munge(dev, s, async->buf_write_alloc_count - async->munge_count);
1438 comedi_buf_write_free(async, n);
1444 break; /* makes device work like a pipe */
1446 current->state=TASK_RUNNING;
1447 remove_wait_queue(&dev->write_wait,&wait);
1449 return (count ? count : retval);
1453 static ssize_t comedi_read(struct file * file,char *buf,size_t nbytes,loff_t *offset)
1456 comedi_subdevice *s;
1457 comedi_async *async;
1458 int n,m,count=0,retval=0;
1459 DECLARE_WAITQUEUE(wait,current);
1461 dev=comedi_get_device_by_minor(MINOR(RDEV_OF_FILE(file)));
1465 DPRINTK("no driver configured on comedi%i\n", dev->minor);
1469 s = dev->read_subdev;
1470 if(s == NULL)return -EIO;
1473 if(!nbytes)return 0;
1481 add_wait_queue(&dev->read_wait,&wait);
1482 while(nbytes>0 && !retval){
1483 current->state=TASK_INTERRUPTIBLE;
1487 m = comedi_buf_read_n_available(s);
1488 //printk("%d available\n",m);
1489 if(async->buf_read_ptr + m > async->prealloc_bufsz){
1490 m = async->prealloc_bufsz - async->buf_read_ptr;
1492 //printk("%d contiguous\n",m);
1496 if(!(s->subdev_flags&SDF_RUNNING)){
1497 do_become_nonbusy(dev,s);
1498 if(s->runflags & SRF_ERROR){
1505 if(file->f_flags&O_NONBLOCK){
1509 if(signal_pending(current)){
1510 retval=-ERESTARTSYS;
1516 comedi_buf_munge(dev, s, async->buf_write_count - async->munge_count);
1517 m = copy_to_user(buf, async->prealloc_buf +
1518 async->buf_read_ptr, n);
1524 comedi_buf_read_free(async, n);
1530 break; /* makes device work like a pipe */
1532 if(!(s->subdev_flags&SDF_RUNNING) &&
1533 !(s->runflags & SRF_ERROR) &&
1534 async->buf_read_count - async->buf_write_count == 0)
1536 do_become_nonbusy(dev,s);
1538 current->state=TASK_RUNNING;
1539 remove_wait_queue(&dev->read_wait,&wait);
1541 return (count ? count : retval);
1545 This function restores a subdevice to an idle state.
1547 void do_become_nonbusy(comedi_device *dev,comedi_subdevice *s)
1549 comedi_async *async = s->async;
1550 /* we do this because it's useful for the non-standard cases */
1551 s->subdev_flags &= ~SDF_RUNNING;
1553 #ifdef CONFIG_COMEDI_RT
1554 if(s->runflags&SRF_RT){
1555 comedi_switch_to_non_rt(dev);
1556 s->runflags &= ~SRF_RT;
1561 init_async_buf( async );
1563 printk("BUG: (?) do_become_nonbusy called with async=0\n");
1569 /* no chance that these will change soon */
1574 static loff_t comedi_lseek(struct file *file,loff_t offset,int origin)
1579 dev=comedi_get_device_by_minor(MINOR(RDEV_OF_FILE(file)));
1583 new_offset = offset;
1586 new_offset = file->f_pos + offset;
1589 new_offset = dev->n_subdevices + offset;
1594 if(new_offset<0 || new_offset >= dev->n_subdevices)
1597 return file->f_pos=new_offset;
1600 static int comedi_open(struct inode *inode,struct file *file)
1602 unsigned int minor=MINOR(inode->i_rdev);
1606 if(minor>=COMEDI_NDEVICES){
1607 DPRINTK("invalid minor number\n");
1610 dev=comedi_get_device_by_minor(minor);
1612 /* This is slightly hacky, but we want module autoloading
1614 * case: user opens device, attached -> ok
1615 * case: user opens device, unattached, in_request_module=0 -> autoload
1616 * case: user opens device, unattached, in_request_module=1 -> fail
1617 * case: root opens device, attached -> ok
1618 * case: root opens device, unattached, in_request_module=1 -> ok
1619 * (typically called from modprobe)
1620 * case: root opens device, unattached, in_request_module=0 -> autoload
1622 * The last could be changed to "-> ok", which would deny root
1627 if(!capable(CAP_SYS_MODULE) && dev->in_request_module){
1628 DPRINTK("in request module\n");
1631 if(capable(CAP_SYS_MODULE) && dev->in_request_module)
1634 dev->in_request_module=1;
1636 sprintf(mod,"char-major-%i-%i",COMEDI_MAJOR,minor);
1638 request_module(mod);
1641 dev->in_request_module=0;
1643 if(!dev->attached && !capable(CAP_SYS_MODULE)){
1644 DPRINTK("not attached and not CAP_SYS_MODULE\n");
1648 if(!try_module_get(THIS_MODULE))
1652 try_module_get( dev->driver->module );
1655 if(dev->attached && dev->use_count==0 && dev->open){
1664 static int comedi_close(struct inode *inode,struct file *file)
1666 comedi_device *dev=comedi_get_device_by_minor(MINOR(inode->i_rdev));
1667 comedi_subdevice *s = NULL;
1672 for(i=0;i<dev->n_subdevices;i++){
1673 s=dev->subdevices+i;
1683 if(dev->attached && dev->use_count==1 && dev->close){
1687 module_put(THIS_MODULE);
1689 module_put(dev->driver->module);
1694 if(file->f_flags & FASYNC){
1695 comedi_fasync(-1,file,0);
1701 static int comedi_fasync (int fd, struct file *file, int on)
1703 comedi_device *dev=comedi_get_device_by_minor(MINOR(RDEV_OF_FILE(file)));
1705 return fasync_helper(fd,file,on,&dev->async_queue);
1709 static struct file_operations comedi_fops={
1710 owner : THIS_MODULE,
1711 llseek : comedi_lseek,
1712 ioctl : comedi_ioctl,
1714 release : comedi_close,
1716 write : comedi_write,
1719 fasync : comedi_fasync,
1722 static struct class *comedi_class;
1724 static int __init comedi_init(void)
1728 printk("comedi: version " COMEDI_RELEASE " - David Schleef <ds@schleef.org>\n");
1729 spin_lock_init(&big_comedi_lock);
1730 if(devfs_register_chrdev(COMEDI_MAJOR,"comedi",&comedi_fops)){
1731 printk("comedi: unable to get major %d\n",COMEDI_MAJOR);
1734 comedi_class = class_create(THIS_MODULE, "comedi");
1735 if(IS_ERR(comedi_class))
1737 printk("comedi: failed to create class");
1738 devfs_unregister_chrdev(COMEDI_MAJOR,"comedi");
1739 return PTR_ERR(comedi_class);
1741 comedi_devices=(comedi_device *)kmalloc(sizeof(comedi_device)*COMEDI_NDEVICES,GFP_KERNEL);
1744 class_destroy(comedi_class);
1745 devfs_unregister_chrdev(COMEDI_MAJOR,"comedi");
1748 memset(comedi_devices,0,sizeof(comedi_device)*COMEDI_NDEVICES);
1749 for(i=0;i<COMEDI_NDEVICES;i++){
1750 comedi_devices[i].minor=i;
1751 spin_lock_init(&(comedi_devices[i].spinlock));
1754 /* XXX requires /proc interface */
1757 for(i=0;i<COMEDI_NDEVICES;i++){
1759 sprintf(name, "comedi%d", i);
1760 devfs_register(NULL, name, DEVFS_FL_DEFAULT,
1761 COMEDI_MAJOR, i, 0666 | S_IFCHR, &comedi_fops, NULL);
1762 COMEDI_CLASS_DEVICE_CREATE(comedi_class, 0,
1763 MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i", i);
1771 static void __exit comedi_cleanup(void)
1776 printk("comedi: module in use -- remove delayed\n");
1778 for(i=0;i<COMEDI_NDEVICES;i++){
1780 class_device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, i));
1781 sprintf(name, "comedi%d", i);
1782 devfs_unregister(devfs_find_handle(NULL, name,
1783 COMEDI_MAJOR, i, DEVFS_SPECIAL_CHR, 0));
1785 class_destroy(comedi_class);
1786 devfs_unregister_chrdev(COMEDI_MAJOR,"comedi");
1788 comedi_proc_cleanup();
1790 for(i=0;i<COMEDI_NDEVICES;i++){
1793 dev=comedi_get_device_by_minor(i);
1795 comedi_device_detach(dev);
1797 kfree(comedi_devices);
1799 comedi_rt_cleanup();
1802 module_init(comedi_init);
1803 module_exit(comedi_cleanup);
1805 void comedi_error(const comedi_device *dev,const char *s)
1807 rt_printk("comedi%d: %s: %s\n",dev->minor,dev->driver->driver_name,s);
1810 void comedi_event(comedi_device *dev,comedi_subdevice *s, unsigned int mask)
1812 comedi_async *async = s->async;
1814 mask = s->async->events;
1815 s->async->events = 0;
1817 //DPRINTK("comedi_event %x\n",mask);
1819 if( (s->subdev_flags & SDF_RUNNING) == 0)
1822 if(mask&(COMEDI_CB_EOA|COMEDI_CB_ERROR|COMEDI_CB_OVERFLOW)){
1823 s->subdev_flags &= ~SDF_RUNNING;
1826 /* remember if an error event has occured, so an error
1827 * can be returned the next time the user does a read() */
1828 if(mask & (COMEDI_CB_ERROR|COMEDI_CB_OVERFLOW)){
1829 s->runflags |= SRF_ERROR;
1831 if(async->cb_mask&mask){
1832 if(s->runflags&SRF_USER){
1835 #ifdef CONFIG_COMEDI_RT
1837 if(s==dev->read_subdev)
1838 comedi_rt_pend_wakeup(&dev->read_wait);
1839 if(s==dev->write_subdev)
1840 comedi_rt_pend_wakeup(&dev->write_wait);
1842 printk("BUG: comedi_event() code unreachable\n");
1845 if(s==dev->read_subdev){
1846 wake_up_interruptible(&dev->read_wait);
1847 kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
1849 if(s==dev->write_subdev){
1850 wake_up_interruptible(&dev->write_wait);
1851 kill_fasync(&dev->async_queue, SIGIO, POLL_OUT);
1855 if(async->cb_func)async->cb_func(mask,async->cb_arg);
1856 /* XXX bug here. If subdevice A is rt, and
1857 * subdevice B tries to callback to a normal
1858 * linux kernel function, it will be at the
1859 * wrong priority. Since this isn't very
1860 * common, I'm not going to worry about it. */
1865 static void init_async_buf( comedi_async *async )
1867 async->buf_write_alloc_count = 0;
1868 async->buf_write_count = 0;
1869 async->buf_read_count = 0;
1871 async->buf_write_ptr = 0;
1872 async->buf_read_ptr = 0;
1874 async->cur_chan = 0;
1875 async->scan_progress = 0;
1876 async->munge_chan = 0;
1877 async->munge_count = 0;
1878 async->munge_ptr = 0;