command changes, range fixes
authorDavid Schleef <ds@schleef.org>
Thu, 17 Feb 2000 08:03:09 +0000 (08:03 +0000)
committerDavid Schleef <ds@schleef.org>
Thu, 17 Feb 2000 08:03:09 +0000 (08:03 +0000)
Makefile
comedi/comedi_fops.c
comedi/drivers/ni_mio_common.c
comedi/drivers/ni_pcimio.c
comedi/range.c
comedi/realtime/vd_dds.c
comedi/realtime/vd_timer.c
include/comedi.h

index 03347ba67f9db662368d95dac6dd98c3fc70aeb9..9c6a11d560ee8e0e8a995ef46253c4ea410efaf7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -7,9 +7,10 @@ VERS3 = 39
 
 INSTALLDIR=/usr
 
-LINUXDIR = /usr/src/linux
+#LINUXDIR = /usr/src/linux
 #LINUXDIR = /d/ds/cvs/rtl/linux22
-#LINUXDIR = /d/ds/cvs/linux22
+#LINUXDIR = /home/ds/cvs/linux23
+LINUXDIR = /home/ds/cvs/linux22
 
 # define the following if you want to compile using RTL
 # headers that aren't in the default location
@@ -17,7 +18,7 @@ RTLDIR = /d/ds/cvs/rtlinux
 
 # define the following if you want to compile using RTAI
 # headers that aren't in the default location
-RTAIDIR = /d/ds/cvs/rtai
+RTAIDIR = /home/ds/cvs/rtai
 
 TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
 
index a565050ff1b778f8ae912d67602e55ba01cfa035..8ae2298b08a7601c81810b6e50d72afb0e6b710c 100644 (file)
@@ -52,6 +52,7 @@ static int do_cmd_ioctl(comedi_device *dev,void *arg,void *file);
 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 void do_become_nonbusy(comedi_device *dev,comedi_subdevice *s);
 
@@ -83,6 +84,8 @@ static int comedi_ioctl(struct inode * inode,struct file * file,unsigned int cmd
                return do_cancel_ioctl(dev,arg,file);
        case COMEDI_CMD:
                return do_cmd_ioctl(dev,(void *)arg,file);
+       case COMEDI_CMDTEST:
+               return do_cmdtest_ioctl(dev,(void *)arg,file);
        default:
                return -EIO;
        }
@@ -618,6 +621,94 @@ cleanup:
        return ret;
 }
 
+/*
+       COMEDI_CMDTEST
+       command testing ioctl
+       
+       arg:
+               pointer to cmd structure
+       
+       reads:
+               cmd structure at arg
+               channel/range list
+       
+       writes:
+               modified cmd structure at arg
+
+*/
+static int do_cmdtest_ioctl(comedi_device *dev,void *arg,void *file)
+{
+       comedi_cmd user_cmd;
+       comedi_subdevice *s;
+       int ret=0;
+       unsigned int *chanlist=NULL;
+       
+DPRINTK("entering do_cmdtest_ioctl()\n");
+       if(copy_from_user(&user_cmd,arg,sizeof(comedi_cmd))){
+               DPRINTK("bad cmd address\n");
+               return -EFAULT;
+       }
+       
+       if(user_cmd.subdev>=dev->n_subdevices){
+               DPRINTK("%d no such subdevice\n",user_cmd.subdev);
+               return -ENODEV;
+       }
+
+       s=dev->subdevices+user_cmd.subdev;
+       if(s->type==COMEDI_SUBD_UNUSED){
+               DPRINTK("%d not valid subdevice\n",user_cmd.subdev);
+               return -EIO;
+       }
+       
+       if(!s->do_cmd){
+               DPRINTK("subdevice does not support commands\n");
+               return -EIO;
+       }
+       
+       /* make sure channel/gain list isn't too long */
+       if(user_cmd.chanlist_len > s->len_chanlist){
+               DPRINTK("channel/gain list too long %d > %d\n",user_cmd.chanlist_len,s->len_chanlist);
+               ret = -EINVAL;
+               goto cleanup;
+       }
+
+       /* load channel/gain list */
+       if(user_cmd.chanlist){
+               chanlist=kmalloc(user_cmd.chanlist_len*sizeof(int),GFP_KERNEL);
+               if(!chanlist){
+                       DPRINTK("allocation failed\n");
+                       ret = -ENOMEM;
+                       goto cleanup;
+               }
+       
+               if(copy_from_user(chanlist,user_cmd.chanlist,user_cmd.chanlist_len*sizeof(int))){
+                       DPRINTK("fault reading chanlist\n");
+                       ret = -EFAULT;
+                       goto cleanup;
+               }
+       
+               /* make sure each element in channel/gain list is valid */
+               if((ret=check_chanlist(s,user_cmd.chanlist_len,chanlist))<0){
+                       DPRINTK("bad chanlist\n");
+                       goto cleanup;
+               }
+
+               user_cmd.chanlist=chanlist;
+       }
+
+       ret=s->do_cmdtest(dev,s,&user_cmd);
+       
+       if(copy_to_user(arg,&user_cmd,sizeof(comedi_cmd))){
+               DPRINTK("bad cmd address\n");
+               ret=-EFAULT;
+               goto cleanup;
+       }
+cleanup:
+       if(chanlist)
+               kfree(chanlist);
+       
+       return ret;
+}
 
 /*
        COMEDI_LOCK
index b7b3c6e46e5a6b6e9773a453a588737aef8b6a14..54fb2a3be34759d4c0eb2ad7dad3cdeefc7aab8c 100644 (file)
@@ -554,11 +554,13 @@ static void ni_load_channelgain_list(comedi_device *dev,unsigned int n_chan,unsi
 }
 
 #ifdef CONFIG_COMEDI_VER08
+#define TIMER_BASE 50 /* 20 Mhz base */
+
 static int ni_ns_to_timer(int *nanosec,int round_mode)
 {
        int divider,base;
 
-       base=50; /* 20 Mhz base */
+       base=TIMER_BASE;
 
        switch(round_mode){
        case TRIG_ROUND_NEAREST:
@@ -625,8 +627,8 @@ static int ni_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd)
                        cmd->scan_begin_arg=boardtype.ai_speed;
                        err++;
                }
-               if(cmd->scan_begin_arg>1000000000){     /* XXX */
-                       cmd->scan_begin_arg=1000000000;
+               if(cmd->scan_begin_arg>TIMER_BASE*0xffff){      /* XXX */
+                       cmd->scan_begin_arg=TIMER_BASE*0xffff;
                        err++;
                }
        }else{
@@ -638,12 +640,12 @@ static int ni_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd)
                        err++;
                }
        }
-       if(cmd->scan_begin_arg<boardtype.ai_speed){
-               cmd->scan_begin_arg=boardtype.ai_speed;
+       if(cmd->convert_arg<boardtype.ai_speed){
+               cmd->convert_arg=boardtype.ai_speed;
                err++;
        }
-       if(cmd->scan_begin_arg>1000000000){     /* XXX */
-               cmd->scan_begin_arg=1000000000;
+       if(cmd->convert_arg>TIMER_BASE*0xffff){ /* XXX */
+               cmd->convert_arg=TIMER_BASE*0xffff;
                err++;
        }
 
@@ -690,13 +692,151 @@ static int ni_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd)
 static int ni_ai_cmd(comedi_device *dev,comedi_subdevice *s)
 {
        int wsave;
+       comedi_cmd *cmd=&s->cmd;
+       int timer;
 
        wsave = win_save();
 
        win_out(1,ADC_FIFO_Clear);
 
+       ni_load_channelgain_list(dev,cmd->chanlist_len,cmd->chanlist,
+               (cmd->flags&TRIG_DITHER)==TRIG_DITHER);
+
+       /* start configuration */
+       win_out(AI_Configuration_Start,Joint_Reset_Register);
+
+       switch(cmd->stop_src){
+       case TRIG_COUNT:
+               /* stage number of scans */
+               win_out((cmd->stop_arg-1)>>16,AI_SC_Load_A_Registers);
+               win_out((cmd->stop_arg-1)&0xffff,AI_SC_Load_A_Registers+1);
+       
+               /* load SC (Scan Count) */
+               win_out(0x20,AI_Command_1_Register);
+
+               break;
+       }
+
+       switch(cmd->scan_begin_src){
+       case TRIG_TIMER:
+               /*
+               AI_SI_Special_Trigger_Delay=0
+               AI_Pre_Trigger=0
+               AI_START_STOP_Select_Register:
+                   AI_START_Polarity=0 (?)     rising edge
+                   AI_START_Edge=1             edge triggered
+                   AI_START_Sync=1 (?)         
+                   AI_START_Select=0           SI_TC
+                   AI_STOP_Polarity=0          rising edge
+                   AI_STOP_Edge=0              level
+                   AI_STOP_Sync=1              
+                   AI_STOP_Select=19           external pin (configuration mem)
+                */
+               win_out(AI_START_Edge|AI_START_Sync|
+                       AI_STOP_Select(19)|AI_STOP_Sync,
+                       AI_START_STOP_Select_Register);
+
+               timer=ni_ns_to_timer(&cmd->scan_begin_arg,TRIG_ROUND_NEAREST);
+               win_out((timer>>16),AI_SI_Load_A_Registers);
+               win_out((timer&0xffff),AI_SI_Load_A_Registers+1);
+               /* AI_SI_Initial_Load_Source=A */
+               win_out(0,AI_Mode_2_Register);
+               /* load SI */
+               win_out(0x200,AI_Command_1_Register);
+
+               /* stage freq. counter into SI B */
+               win_out((timer>>16),AI_SI_Load_B_Registers);
+               win_out((timer&0xffff),AI_SI_Load_B_Registers+1);
+
+               break;
+       case TRIG_EXT:
+               win_out(AI_START_Edge|AI_START_Sync|AI_START_Select(1)|
+                       AI_STOP_Select(19)|AI_STOP_Sync,
+                       AI_START_STOP_Select_Register);
+               break;
+       }
+
+       timer=ni_ns_to_timer(&cmd->convert_arg,TRIG_ROUND_NEAREST);
+       win_out(timer,AI_SI2_Load_A_Register); /* 0,0 does not work. */
+       win_out(timer,AI_SI2_Load_B_Register);
+
+       /* AI_SI2_Reload_Mode = alternate */
+       /* AI_SI2_Initial_Load_Source = A */
+       win_out(0x0100,AI_Mode_2_Register);
+
+       /* AI_SI2_Load */
+       win_out(0x0800,AI_Command_1_Register);
+
+       /* AI_SI_Initial_Load_Source=0
+          AI_SI_Reload_Mode(0)
+          AI_SI2_Reload_Mode = alternate, AI_SI2_Initial_Load_Source = B */
+       win_out(0x0300,AI_Mode_2_Register);
+
+       if(dev->irq){
+               int bits;
+
+               /* interrupt on FIFO, errors, SC_TC */
+               bits=0x00a1;
+
+               if(cmd->flags&TRIG_WAKE_EOS){
+                       /* wake on end-of-scan */
+                       devpriv->aimode=AIMODE_SCAN;
+               }else if(s->cb_mask&COMEDI_CB_EOS){
+                       devpriv->aimode=AIMODE_SAMPLE;
+               }else{
+                       devpriv->aimode=AIMODE_HALF_FULL;
+               }
+               switch(devpriv->aimode){
+               case AIMODE_HALF_FULL:
+                       /*generate FIFO interrupts on half-full */
+                       win_out(AI_FIFO_Mode_HF|0x0000,AI_Mode_3_Register);
+                       break;
+               case AIMODE_SAMPLE:
+                       /*generate FIFO interrupts on non-empty */
+                       win_out(AI_FIFO_Mode_NE|0x0000,AI_Mode_3_Register);
+                       break;
+               case AIMODE_SCAN:
+                       /*generate FIFO interrupts on half-full */
+                       win_out(AI_FIFO_Mode_HF|0x0000,AI_Mode_3_Register);
+                       bits|=AI_STOP_Interrupt_Enable;
+                       break;
+               default:
+                       break;
+               }
+
+               win_out(0x3f80,Interrupt_A_Ack_Register); /* clear interrupts */
 
+               win_out(bits,Interrupt_A_Enable_Register) ;
+       }else{
+               /* interrupt on nothing */
+               win_out(0x0000,Interrupt_A_Enable_Register) ;
 
+               /* XXX start polling if necessary */
+       }
+
+       /* end configuration */
+       win_out(AI_Configuration_End,Joint_Reset_Register);
+       
+       switch(cmd->scan_begin_src){
+       case TRIG_TIMER:
+               /* AI_SI2_Arm, AI_SI_Arm, AI_DIV_Arm, AI_SC_Arm */
+               win_out(0x1540,AI_Command_1_Register);
+               break;
+       case TRIG_EXT:
+               /* AI_SI2_Arm, AI_DIV_Arm, AI_SC_Arm */
+               win_out(0x1500,AI_Command_1_Register);
+               break;
+       }
+
+       /* AI_START1_Pulse */
+       win_out(AI_START1_Pulse,AI_Command_2_Register);
+
+#if 0
+       /* XXX hack alert */
+       s->cur_chan=s->cur_trig.n_chan*sizeof(sampl_t);
+#endif
+
+       win_restore(wsave);
        return 0;
 }
 #endif
@@ -1429,7 +1569,9 @@ static int ni_calib(comedi_device *dev,comedi_subdevice *s,comedi_trig *it)
 static int pack_mb88341(int addr,int val,int *bitstring);
 static int pack_dac8800(int addr,int val,int *bitstring);
 static int pack_dac8043(int addr,int val,int *bitstring);
+#ifdef PCIMIO
 static int pack_ad8522(int addr,int val,int *bitstring);
+#endif
 
 struct caldac_struct{
        int n_chans;
@@ -1440,7 +1582,9 @@ struct caldac_struct{
 static struct caldac_struct caldac_mb88341={ 12, 8, pack_mb88341 };
 static struct caldac_struct caldac_dac8800={ 8, 8, pack_dac8800 };
 static struct caldac_struct caldac_dac8043={ 1, 12, pack_dac8043 };
+#ifdef PCIMIO
 static struct caldac_struct caldac_ad8522={ 2, 12, pack_ad8522 };
+#endif
 
 
 static void caldac_setup(comedi_device *dev,comedi_subdevice *s)
@@ -1535,11 +1679,13 @@ static int pack_dac8043(int addr,int val,int *bitstring)
        return 12;
 }
        
+#ifdef PCIMIO
 static int pack_ad8522(int addr,int val,int *bitstring)
 {
        *bitstring=(val&0xfff)|(addr ? 0xc000:0xa000);
        return 16;
 }
+#endif
 
 
 
index b733cd96ba804c0d6af07260f00a273ffcbd364e..311548b2520dbb686af035b0b013cc5d796597d5 100644 (file)
@@ -86,7 +86,9 @@
 static struct caldac_struct *type1[]={&caldac_dac8800,&caldac_dac8043,NULL};
 static struct caldac_struct *type2[]={&caldac_dac8800,&caldac_dac8043,&caldac_ad8522};
 static struct caldac_struct *type3[]={&caldac_mb88341,NULL,NULL};
+#if 0
 static struct caldac_struct *type4[]={&caldac_mb88341,&caldac_mb88341,&caldac_ad8522};
+#endif
 
 
 static ni_board ni_boards[]={
index 3c3a8d9f5c32e2183996d4284ecacdeb0c35d924..136ed044394fae11ced76e77cfa5b10fc5a1941b 100644 (file)
@@ -32,7 +32,7 @@ comedi_lrange range_bipolar5={ 1, {BIP_RANGE(5)}};
 comedi_lrange range_bipolar2_5={ 1, {BIP_RANGE(2.5)}};
 comedi_lrange range_unipolar10={ 1, {UNI_RANGE(10)}};
 comedi_lrange range_unipolar5={ 1, {UNI_RANGE(5)}};
-comedi_lrange range_unknown={ 1, {0,1,0}};     /* XXX */
+comedi_lrange range_unknown={ 1, {{0,1,0}}};   /* XXX */
 
 /*
        COMEDI_RANGEINFO
index 5deb1d1280c40ab9e2784cfcc49732c1d8c03aef..d4778577ae62abdc993d2db100ce89a9516da8b1 100644 (file)
 #include <rtl_sched.h>
 #include <rtl_compat.h>
 #endif
+#ifdef CONFIG_COMEDI_RTAI
+#include <rtai.h>
+#include <rtai_sched.h>
+#endif
 
 static int dds_attach(comedi_device *dev,comedi_devconfig *it);
 static int dds_detach(comedi_device *dev);
@@ -111,7 +115,12 @@ static void dds_ao_task_func(int d)
                if(ret<0){
                        /* eek! */
                }
+#ifdef CONFIG_COMEDI_RTL
                rt_task_wait();
+#endif
+#ifdef CONFIG_COMEDI_RTL
+               rt_task_yield();
+#endif
        }
 }
 
@@ -206,19 +215,10 @@ int dds_attach(comedi_device *dev,comedi_devconfig *it)
        s->trig[2]=dds_ao_mode2;
        s->cancel=dds_ao_cancel;
        s->maxdata=devpriv->s->maxdata;
-       s->range_type=devpriv->s->range_type;
+       s->range_table=devpriv->s->range_table;
+       s->range_table_list=devpriv->s->range_table_list;
        s->timer_type=TIMER_nanosec;
 
-       s=dev->subdevices+0;
-       s->type=COMEDI_SUBD_AO;
-       s->subdev_flags=SDF_READABLE;
-       s->n_chan=devpriv->s->n_chan;
-       s->len_chanlist=1024;
-       s->trig[2]=dds_ao_mode2;
-       s->cancel=dds_ao_cancel;
-       s->maxdata=devpriv->s->maxdata;
-       s->range_type=devpriv->s->range_type;
-
        devpriv->soft_irq=rtl_get_soft_irq(dds_interrupt,"dds");
        broken_rtl_dev=dev;
 
index bbee0499dde131a5839bfebfced9e938a24f880f..e45c7f4d8e57e4df43450ee5f864bccfa2376e05 100644 (file)
 #include <linux/timer.h>
 #include <asm/io.h>
 #include <comedi_module.h>
-
 #ifdef CONFIG_COMEDI_RTL_V1
 #include <rtl_sched.h>
 #include <asm/rt_irq.h>
 #endif
-
 #ifdef CONFIG_COMEDI_RTL
 #include <rtl.h>
 #include <rtl_sched.h>
 #include <rtl_compat.h>
 #endif
+#ifdef CONFIG_COMEDI_RTAI
+#include <rtai.h>
+#include <rtai_sched.h>
+#endif
 
 static int timer_attach(comedi_device *dev,comedi_devconfig *it);
 static int timer_detach(comedi_device *dev);
@@ -133,11 +135,53 @@ static int timer_ai_mode0(comedi_device *dev,comedi_subdevice *s,comedi_trig *it
        return comedi_trig_ioctl(devpriv->device,devpriv->subd,it);
 }
 
-static int timer_ai_mode1(comedi_device *dev,comedi_subdevice *s,comedi_trig *it)
+#ifdef CONFIG_COMEDI_VER08
+static int timer_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd)
 {
-       return -EINVAL;
+       if(cmd->scan_start_arg<100000)  /* 10 khz */
+               cmd->scan_start_arg=100000;
+       if(cmd->scan_start_arg>1e9)     /* 1 hz */
+               cmd->scan_start_arg=1e9;
+
 }
 
+static int timer_cmd(comedi_device *dev,comedi_subdevice *s)
+{
+       int ret;
+       RTIME now,period;
+       struct timespec ts;
+
+       ret=comedi_lock_ioctl(devpriv->device,devpriv->subd);
+       if(ret<0)return ret;
+
+       /* XXX this does not get freed */
+       devpriv->data=kmalloc(sizeof(sampl_t)*cmd->chanlist_len,GFP_KERNEL);
+       if(!devpriv->data){
+               ret=-ENOMEM;
+               goto unlock;
+       }
+
+       devpriv->trig.subdev=devpriv->subd;
+       devpriv->trig.mode=0;
+       devpriv->trig.flags=0;
+       devpriv->trig.n=1;
+
+       ts.tv_sec=0;
+       ts.tv_nsec=it->trigvar;
+       period=timespec_to_RTIME(ts);
+
+       rt_task_init(&devpriv->rt_task,timer_ai_task_func,(int)dev,3000,4);
+
+       now=rt_get_time();
+       rt_task_make_periodic(&devpriv->rt_task,now+period,period);
+
+       return 0;
+
+unlock:
+       comedi_unlock_ioctl(devpriv->device,devpriv->subd);
+       return ret;
+}
+#endif
 
 static int timer_ai_mode2(comedi_device *dev,comedi_subdevice *s,comedi_trig *it)
 {
@@ -222,11 +266,15 @@ static int timer_attach(comedi_device *dev,comedi_devconfig *it)
        s->n_chan=devpriv->s->n_chan;
        s->len_chanlist=1024;
        s->trig[0]=timer_ai_mode0;
-       s->trig[1]=timer_ai_mode1;
        s->trig[2]=timer_ai_mode2;
+#ifdef CONFIG_COMEDI_VER08
+       s->do_cmd=timer_cmd;
+       s->do_cmdtest=timer_cmdtest;
+#endif
        s->cancel=timer_cancel;
        s->maxdata=devpriv->s->maxdata;
-       s->range_type=devpriv->s->range_type;
+       s->range_table=devpriv->s->range_table;
+       s->range_table_list=devpriv->s->range_table_list;
        s->timer_type=TIMER_nanosec;
 
        devpriv->soft_irq=rtl_get_soft_irq(timer_interrupt,"timer");
index 468772784efc55d2057327bc52f5554d75901a9f..28e276ccbce1b43a51fd15659a08bbcceaa8e558 100644 (file)
@@ -153,6 +153,7 @@ typedef unsigned short sampl_t;
 #define COMEDI_CANCEL _IO(CIO,7)
 #define COMEDI_RANGEINFO _IOR(CIO,8,comedi_rangeinfo)
 #define COMEDI_CMD _IOR(CIO,9,comedi_cmd)
+#define COMEDI_CMDTEST _IOR(CIO,10,comedi_cmd)