insn support, rt virtualization, runflags
authorDavid Schleef <ds@schleef.org>
Thu, 15 Jun 2000 05:10:19 +0000 (05:10 +0000)
committerDavid Schleef <ds@schleef.org>
Thu, 15 Jun 2000 05:10:19 +0000 (05:10 +0000)
comedi/comedi_fops.c
comedi/comedi_module.h
comedi/comedi_rt.h
comedi/drivers.c

index 0727102b553e6a83935a2c771a8195caeec1444a..aaf8ee6f7a423009ccf9ab78a4379f2e14545702 100644 (file)
@@ -53,6 +53,7 @@ static int do_lock_ioctl(comedi_device *dev,unsigned int arg,void * file);
 static int do_unlock_ioctl(comedi_device *dev,unsigned int arg,void * file);
 static int do_cancel_ioctl(comedi_device *dev,unsigned int arg,void *file);
 static int do_cmdtest_ioctl(comedi_device *dev,void *arg,void *file);
+static int do_insnlist_ioctl(comedi_device *dev,void *arg,void *file);
 
 static void do_become_nonbusy(comedi_device *dev,comedi_subdevice *s);
 
@@ -85,6 +86,8 @@ static int comedi_ioctl(struct inode * inode,struct file * file,unsigned int cmd
                return do_cmd_ioctl(dev,(void *)arg,file);
        case COMEDI_CMDTEST:
                return do_cmdtest_ioctl(dev,(void *)arg,file);
+       case COMEDI_INSNLIST:
+               return do_insnlist_ioctl(dev,(void *)arg,file);
        default:
                return -EIO;
        }
@@ -349,7 +352,7 @@ DPRINTK("entering do_trig_ioctl()\n");
 
        s=dev->subdevices+user_trig.subdev;
        if(s->type==COMEDI_SUBD_UNUSED){
-               DPRINTK("%d not usedevice\n",user_trig.subdev);
+               DPRINTK("%d not useable subdevice\n",user_trig.subdev);
                return -EIO;
        }
        
@@ -458,20 +461,7 @@ static int do_trig_ioctl_mode0(comedi_device *dev,comedi_subdevice *s,comedi_tri
                }
        }
 
-       if(s->cur_trig.mode>=5 || s->trig[s->cur_trig.mode]==NULL){
-               DPRINTK("bad mode %d\n",s->cur_trig.mode);
-               ret=-EINVAL;
-               goto cleanup;
-       }
-
-       /* mark as non-RT operation */
-       s->cur_trig.flags &= ~TRIG_RT;
-
-       s->subdev_flags|=SDF_RUNNING;
-
-       ret=s->trig[s->cur_trig.mode](dev,s,&s->cur_trig);
-
-       if(ret==0)return 0;
+       ret=s->trig[0](dev,s,&s->cur_trig);
 
        if(ret<0)goto cleanup;
 
@@ -563,6 +553,146 @@ cleanup:
 }
 
 
+/*
+ *     COMEDI_INSNLIST
+ *     synchronous instructions
+ *
+ *     arg:
+ *             pointer to sync cmd structure
+ *
+ *     reads:
+ *             sync cmd struct at arg
+ *             instruction list
+ *             data (for writes)
+ *
+ *     writes:
+ *             data (for reads)
+ */
+static int do_insnlist_ioctl(comedi_device *dev,void *arg,void *file)
+{
+       comedi_insnlist insnlist;
+       comedi_insn     insn;
+       comedi_subdevice *s;
+       lsampl_t        *data;
+       int i;
+       int ret=0;
+
+       if(copy_from_user(&insnlist,arg,sizeof(comedi_insnlist)))
+               return -EFAULT;
+       
+       if(insnlist.n_insns>=10)
+               return -EINVAL;
+
+       data=kmalloc(sizeof(lsampl_t)*256,GFP_KERNEL);
+       if(!data)
+               return -ENOMEM;
+
+       for(i=0;i<insnlist.n_insns;i++){
+               if(copy_from_user(&insn,insnlist.insns+i,sizeof(comedi_insn))){
+                       ret=-EFAULT;
+                       break;
+               }
+               if(insn.n>256){
+                       ret=-EINVAL;
+                       break;
+               }
+               if(insn.insn&INSN_MASK_WRITE){
+                       if(copy_from_user(data,insn.data,insn.n*sizeof(lsampl_t))){
+                               ret=-EFAULT;
+                               break;
+                       }
+               }
+               if(insn.insn&INSN_MASK_SPECIAL){
+                       /* a non-subdevice instruction */
+
+                       switch(insn.insn){
+                       case INSN_GTOD:
+                       {
+                               struct timeval tv;
+
+                               do_gettimeofday(&tv);
+                               data[0]=tv.tv_sec;
+                               data[1]=tv.tv_usec;
+                               ret=2;
+                               
+                               break;
+                       }
+                       case INSN_WAIT:
+                               if(insn.n<1 || data[0]>=100){
+                                       ret=-EINVAL;
+                                       break;
+                               }
+                               udelay(data[0]);
+                               ret=1;
+                               break;
+                       default:
+                               ret=-EINVAL;
+                       }
+               }else{
+                       /* a subdevice instruction */
+                       if(insn.subdev>=dev->n_subdevices){
+                               ret=-EINVAL;
+                               break;
+                       }
+                       s=dev->subdevices+insn.subdev;
+       
+                       if(s->type==COMEDI_SUBD_UNUSED){
+                               DPRINTK("%d not useable subdevice\n",insn.subdev);
+                               return -EIO;
+                       }
+               
+                       /* are we locked? (ioctl lock) */
+                       if(s->lock && s->lock!=file){
+                               DPRINTK("device locked\n");
+                               return -EACCES;
+                       }
+       
+                       if(s->busy){
+                               ret=-EBUSY;
+                               break;
+                       }
+                       s->busy=file;
+       
+                       if((ret=check_chanlist(s,1,&insn.chanspec))<0){
+                               ret=-EINVAL;
+                               DPRINTK("bad chanspec\n");
+                               break;
+                       }
+
+                       switch(insn.insn){
+                               case INSN_READ:
+                                       ret=s->insn_read(dev,s,&insn,data);
+                                       break;
+                               case INSN_WRITE:
+                                       ret=s->insn_write(dev,s,&insn,data);
+                                       break;
+                               default:
+                                       ret=-EINVAL;
+                                       break;
+                       }
+
+                       s->busy=NULL;
+               }
+               if(ret<0)break;
+               if(ret!=insn.n){
+                       printk("result of insn != insn.n\n");
+                       ret=-EINVAL;
+                       break;
+               }
+               if(insn.insn&INSN_MASK_READ){
+                       if(copy_to_user(insn.data,data,insn.n*sizeof(lsampl_t))){
+                               ret=-EFAULT;
+                               break;
+                       }
+               }
+       }
+
+       kfree(data);
+
+       if(i==0)return ret;
+       return i;
+}
+
 /*
        COMEDI_CMD
        command ioctl
@@ -1409,19 +1539,8 @@ int init_module(void)
        /* XXX requires /proc interface */
        comedi_proc_init();
        
-#ifdef CONFIG_COMEDI_RTL
-       comedi_rtl_init();
-#endif
-#ifdef CONFIG_COMEDI_RTL_V1
-       comedi_rtlv1_init();
-#endif
-#ifdef CONFIG_COMEDI_RTAI
-       comedi_rtai_init();
-#endif
-#if 0
-#ifdef CONFIG_COMEDI_MITE
-       mite_init();
-#endif
+#ifdef CONFIG_COMEDI_RT
+       comedi_rt_init();
 #endif
        init_drivers();
 
@@ -1450,19 +1569,8 @@ void cleanup_module(void)
        }
        kfree(comedi_devices);
 
-#ifdef CONFIG_COMEDI_RTL
-       comedi_rtl_cleanup();
-#endif
-#ifdef CONFIG_COMEDI_RTL_V1
-       comedi_rtlv1_cleanup();
-#endif
-#ifdef CONFIG_COMEDI_RTAI
-       comedi_rtai_cleanup();
-#endif
-#if 0
-#ifdef CONFIG_COMEDI_MITE
-       mite_cleanup();
-#endif
+#ifdef CONFIG_COMEDI_RT
+       comedi_rt_cleanup();
 #endif
 
 }
index ed3a175aa5d4c154c6ee68ead3353ee6ca0ef999..a944b412646a2c0dd1cfa282a7e1c090fad13fda 100644 (file)
@@ -65,6 +65,7 @@ struct comedi_subdevice_struct{
 
        void *lock;
        void *busy;
+       unsigned int runflags;
        
        int io_bits;
        
@@ -88,12 +89,11 @@ struct comedi_subdevice_struct{
        unsigned int buf_user_count;            /* byte count for read() and write() */
        unsigned int cur_chan;          /* useless channel marker for interrupt */
        
-#if 0
-       unsigned int *range_list;       /* is this necessary? */
-#endif
-       
        int (*trig[5])(comedi_device *,comedi_subdevice *,comedi_trig *);
 
+       int (*insn_read)(comedi_device *,comedi_subdevice *,comedi_insn *,lsampl_t *data);
+       int (*insn_write)(comedi_device *,comedi_subdevice *,comedi_insn *,lsampl_t *data);
+
        int (*do_cmd)(comedi_device *,comedi_subdevice *);
        int (*do_cmdtest)(comedi_device *,comedi_subdevice *,comedi_cmd *);
        int (*poll)(comedi_device *,comedi_subdevice *);
@@ -194,6 +194,10 @@ int do_pack(unsigned int *bits,comedi_trig *it);
 #endif
 
 
+#define SRF_USER               0x00000001
+#define SRF_RT                 0x00000002
+#define SRF_RTIRQ              0x00000004
+
 
 /*
    various internal comedi functions
index b7803a01728888e41156b55d57f771b72a7ba5c5..04fed933b104bedd71e26d0555db3242b4493edd 100644 (file)
@@ -43,7 +43,7 @@ struct comedi_irq_struct{
        void *dev_id;
        unsigned long flags;
        void (*handler)(int,void *,struct pt_regs *);
-       char *device;
+       const char *device;
 };
 
 int get_priority_irq(struct comedi_irq_struct *);
@@ -97,9 +97,11 @@ extern void wake_up_int_handler(int arg1, void * arg2);
 #define rt_printk_cleanup()            
 #endif
 
-int comedi_request_irq(unsigned int irq,void (*handler)(int,void *,struct pt_reg
-       unsigned long flags,const char *device,void *dev_id);
-int comedi_change_irq_flags(unsigned int irq,void *dev_id,unsigned long new_flag
+int comedi_request_irq(unsigned int irq,void (*handler)(int,void *,
+       struct pt_regs *regs),unsigned long flags,const char *device,
+       void *dev_id);
+int comedi_change_irq_flags(unsigned int irq,void *dev_id,
+       unsigned long new_flags);
 void comedi_free_irq(unsigned int irq,void *dev_id);
 
 
index 4d4f3fc7a6d93bc641309ae657f354fded78ef0f..6f474c455793db942095fc023725ee5f6dbd18ed 100644 (file)
@@ -40,6 +40,7 @@
 static void postconfig(comedi_device *dev);
 static int command_trig(comedi_device *dev,comedi_subdevice *s,comedi_trig *it);
 static int mode_to_command(comedi_cmd *cmd,comedi_trig *it);
+static int insn_emulate(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
 
 comedi_driver *comedi_drivers;
 
@@ -220,6 +221,9 @@ static void postconfig(comedi_device *dev)
 
                if(!s->range_table && !s->range_table_list)
                        s->range_table=&range_unknown;
+
+               if(!s->insn_read)s->insn_read=insn_emulate;
+               if(!s->insn_write)s->insn_write=insn_emulate;
        }
 
 }
@@ -256,6 +260,53 @@ int do_pack(unsigned int *bits,comedi_trig *it)
        return i;
 }
 
+static int insn_emulate(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
+{
+       comedi_trig trig;
+       int i;
+       int ret;
+
+       switch(insn->insn){
+       case INSN_WRITE:
+               if(!(s->subdev_flags & SDF_WRITEABLE))
+                       return -EINVAL;
+               trig.flags=TRIG_WRITE;
+               break;
+       case INSN_READ:
+               if(!(s->subdev_flags & SDF_READABLE))
+                       return -EINVAL;
+               trig.flags=0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       trig.subdev=insn->subdev;
+       trig.mode=0;
+       trig.n_chan=1;
+       trig.chanlist=&insn->chanspec;
+       trig.n=1;
+
+       if(s->subdev_flags & SDF_LSAMPL){
+               for(i=0;i<insn->n;i++){
+                       trig.data=(void *)(data+i);
+                       ret=s->trig[0](dev,s,&trig);
+                       if(ret<0)return ret;
+               }
+       }else{
+               sampl_t sdata;
+
+               trig.data=&sdata;
+               for(i=0;i<insn->n;i++){
+                       ret=s->trig[0](dev,s,&trig);
+                       if(ret<0)return ret;
+                       data[i]=sdata;
+               }
+       }
+
+       return -EINVAL;
+}
+
 static int command_trig(comedi_device *dev,comedi_subdevice *s,comedi_trig *it)
 {
        int ret;