#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;
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;
return 0;
}
+#endif
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 */