From 4e6083d631eb79663995d47917fc2f1c9a90ac4b Mon Sep 17 00:00:00 2001 From: David Schleef Date: Thu, 17 Feb 2000 08:03:09 +0000 Subject: [PATCH] command changes, range fixes --- Makefile | 7 +- comedi/comedi_fops.c | 91 +++++++++++++++++++ comedi/drivers/ni_mio_common.c | 160 +++++++++++++++++++++++++++++++-- comedi/drivers/ni_pcimio.c | 2 + comedi/range.c | 2 +- comedi/realtime/vd_dds.c | 22 ++--- comedi/realtime/vd_timer.c | 60 +++++++++++-- include/comedi.h | 1 + 8 files changed, 317 insertions(+), 28 deletions(-) diff --git a/Makefile b/Makefile index 03347ba6..9c6a11d5 100644 --- 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) diff --git a/comedi/comedi_fops.c b/comedi/comedi_fops.c index a565050f..8ae2298b 100644 --- a/comedi/comedi_fops.c +++ b/comedi/comedi_fops.c @@ -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 diff --git a/comedi/drivers/ni_mio_common.c b/comedi/drivers/ni_mio_common.c index b7b3c6e4..54fb2a3b 100644 --- a/comedi/drivers/ni_mio_common.c +++ b/comedi/drivers/ni_mio_common.c @@ -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_argscan_begin_arg=boardtype.ai_speed; + if(cmd->convert_argconvert_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 diff --git a/comedi/drivers/ni_pcimio.c b/comedi/drivers/ni_pcimio.c index b733cd96..311548b2 100644 --- a/comedi/drivers/ni_pcimio.c +++ b/comedi/drivers/ni_pcimio.c @@ -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[]={ diff --git a/comedi/range.c b/comedi/range.c index 3c3a8d9f..136ed044 100644 --- a/comedi/range.c +++ b/comedi/range.c @@ -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 diff --git a/comedi/realtime/vd_dds.c b/comedi/realtime/vd_dds.c index 5deb1d12..d4778577 100644 --- a/comedi/realtime/vd_dds.c +++ b/comedi/realtime/vd_dds.c @@ -42,6 +42,10 @@ #include #include #endif +#ifdef CONFIG_COMEDI_RTAI +#include +#include +#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; diff --git a/comedi/realtime/vd_timer.c b/comedi/realtime/vd_timer.c index bbee0499..e45c7f4d 100644 --- a/comedi/realtime/vd_timer.c +++ b/comedi/realtime/vd_timer.c @@ -34,17 +34,19 @@ #include #include #include - #ifdef CONFIG_COMEDI_RTL_V1 #include #include #endif - #ifdef CONFIG_COMEDI_RTL #include #include #include #endif +#ifdef CONFIG_COMEDI_RTAI +#include +#include +#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"); diff --git a/include/comedi.h b/include/comedi.h index 46877278..28e276cc 100644 --- a/include/comedi.h +++ b/include/comedi.h @@ -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) -- 2.26.2