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
# 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)
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);
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;
}
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
}
#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:
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{
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++;
}
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
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;
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)
return 12;
}
+#ifdef PCIMIO
static int pack_ad8522(int addr,int val,int *bitstring)
{
*bitstring=(val&0xfff)|(addr ? 0xc000:0xa000);
return 16;
}
+#endif
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[]={
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
#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);
if(ret<0){
/* eek! */
}
+#ifdef CONFIG_COMEDI_RTL
rt_task_wait();
+#endif
+#ifdef CONFIG_COMEDI_RTL
+ rt_task_yield();
+#endif
}
}
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;
#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);
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)
{
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");
#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)