added cmd support, insn support
authorDavid Schleef <ds@schleef.org>
Thu, 30 Nov 2000 00:27:40 +0000 (00:27 +0000)
committerDavid Schleef <ds@schleef.org>
Thu, 30 Nov 2000 00:27:40 +0000 (00:27 +0000)
comedi/drivers/dt2814.c

index e4a341b8020ee89174fd9e777a8247557923ac40..8ab758f40c644df03e94ac81c719586bdbc53e7f 100644 (file)
@@ -72,7 +72,34 @@ typedef struct{
 
 
 #define DT2814_TIMEOUT 100
+#define DT2814_MAX_SPEED 100000 /* XXX 10 khz */
 
+static int dt2814_ai_insn_read(comedi_device *dev,comedi_subdevice *s,
+       comedi_insn *insn, lsampl_t *data)
+{
+       int n,i,hi,lo;
+       int chan;
+
+       for(n=0;n<insn->n;n++){
+               chan=CR_CHAN(insn->chanspec);
+
+               outb(chan,dev->iobase+DT2814_CSR);
+               for(i=0;i<DT2814_TIMEOUT;i++){
+                       if(inb(dev->iobase+DT2814_CSR)&DT2814_FINISH)
+                               break;
+               }
+               if(i>=DT2814_TIMEOUT)return -ETIMEDOUT;
+
+               hi=inb(dev->iobase+DT2814_DATA);
+               lo=inb(dev->iobase+DT2814_DATA);
+
+               data[i]=(hi<<4)|(lo>>4);
+       }
+       
+       return n;
+}
+
+#ifdef CONFIG_COMEDI_MODE0
 static int dt2814_ai_mode0(comedi_device *dev,comedi_subdevice *s,comedi_trig *it)
 {
        int i,hi,lo;
@@ -92,7 +119,127 @@ static int dt2814_ai_mode0(comedi_device *dev,comedi_subdevice *s,comedi_trig *i
        
        return 1;
 }
+#endif
+
+static int dt2814_ns_to_timer(unsigned int *ns,unsigned int flags)
+{
+       int i;
+       unsigned int f;
+
+       /* XXX ignores flags */
+
+       f = 1e4; /* ns */
+       for(i=0;i<8;i++){
+               if((2*(*ns))<(f*11))break;
+               f *= 10;
+       }
+
+       *ns = f;
+
+       return i;
+}
+
+static int dt2814_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,
+       comedi_cmd *cmd)
+{
+       int err=0;
+       int tmp;
+
+       /* step 1: make sure trigger sources are trivially valid */
+
+       tmp=cmd->start_src;
+       cmd->start_src &= TRIG_NOW;
+       if(!cmd->start_src && tmp!=cmd->start_src)err++;
+
+       tmp=cmd->scan_begin_src;
+       cmd->scan_begin_src &= TRIG_TIMER;
+       if(!cmd->scan_begin_src && tmp!=cmd->scan_begin_src)err++;
+
+       tmp=cmd->convert_src;
+       cmd->convert_src &= TRIG_NOW;
+       if(!cmd->convert_src && tmp!=cmd->convert_src)err++;
+
+       tmp=cmd->scan_end_src;
+       cmd->scan_end_src &= TRIG_COUNT;
+       if(!cmd->scan_end_src && tmp!=cmd->scan_end_src)err++;
+
+       tmp=cmd->stop_src;
+       cmd->stop_src &= TRIG_COUNT|TRIG_NONE;
+       if(!cmd->stop_src && tmp!=cmd->stop_src)err++;
+
+       if(err)return 1;
+
+       /* step 2: make sure trigger sources are unique and mutually compatible */
+
+       /* note that mutual compatiblity is not an issue here */
+       if(cmd->stop_src!=TRIG_TIMER &&
+          cmd->stop_src!=TRIG_EXT)err++;
+
+       if(err)return 2;
+
+       /* step 3: make sure arguments are trivially compatible */
+
+       if(cmd->start_arg!=0){
+               cmd->start_arg=0;
+               err++;
+       }
+       if(cmd->scan_begin_arg>1000000000){
+               cmd->scan_begin_arg=1000000000;
+               err++;
+       }
+       if(cmd->scan_begin_arg<DT2814_MAX_SPEED){
+               cmd->scan_begin_arg=DT2814_MAX_SPEED;
+               err++;
+       }
+       if(cmd->scan_end_arg!=cmd->chanlist_len){
+               cmd->scan_end_arg=cmd->chanlist_len;
+               err++;
+       }
+       if(cmd->stop_src==TRIG_COUNT){
+               if(cmd->stop_arg<2){
+                       cmd->stop_arg=2;
+                       err++;
+               }
+       }else{
+               /* TRIG_NONE */
+               if(cmd->stop_arg!=0){
+                       cmd->stop_arg=0;
+                       err++;
+               }
+       }
+
+       if(err)return 3;
+
+       /* step 4: fix up any arguments */
+
+       tmp=cmd->scan_begin_arg;
+       dt2814_ns_to_timer(&cmd->scan_begin_arg,cmd->flags&TRIG_ROUND_MASK);
+       if(tmp!=cmd->scan_begin_arg)err++;
+
+       if(err)return 4;
+
+       return 0;
+}
+
+static int dt2814_ai_cmd(comedi_device *dev,comedi_subdevice *s)
+{
+       comedi_cmd *cmd = &s->cmd;
+       int chan;
+       int trigvar;
+
+       trigvar = dt2814_ns_to_timer(&cmd->scan_begin_arg,cmd->flags&TRIG_ROUND_MASK);
+
+       chan=CR_CHAN(cmd->chanlist[0]);
+
+       devpriv->ntrig=cmd->stop_arg;
+       outb(chan|DT2814_ENB|(trigvar<<5),
+               dev->iobase+DT2814_CSR);
+       
+       return 0;
+
+}
 
+#ifdef CONFIG_COMEDI_MODES
 static int dt2814_ai_mode1(comedi_device *dev,comedi_subdevice *s,comedi_trig *it)
 {
        int chan;
@@ -105,6 +252,7 @@ static int dt2814_ai_mode1(comedi_device *dev,comedi_subdevice *s,comedi_trig *i
        
        return 0;
 }
+#endif
 
 static int dt2814_attach(comedi_device *dev,comedi_devconfig *it)
 {
@@ -174,8 +322,15 @@ static int dt2814_attach(comedi_device *dev,comedi_devconfig *it)
        s->subdev_flags=SDF_READABLE;
        s->n_chan=16;                   /* XXX */
        s->len_chanlist=1;
+#ifdef CONFIG_COMEDI_MODE0
        s->trig[0]=dt2814_ai_mode0;
+#endif
+#ifdef CONFIG_COMEDI_MODES
        s->trig[1]=dt2814_ai_mode1;
+#endif
+       s->insn_read = dt2814_ai_insn_read;
+       s->do_cmd = dt2814_ai_cmd;
+       s->do_cmdtest = dt2814_ai_cmdtest;
        s->maxdata=0xfff;
        s->range_table=&range_unknown;  /* XXX */