📄 cb_pcidas.c
字号:
if( retval < 0 ) return retval; data[ 0 ] = nvram_data; return 1;}static int caldac_write_insn( comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data ){ const unsigned int channel = CR_CHAN( insn->chanspec ); return caldac_8800_write( dev, channel, data[0] );}static int caldac_read_insn( comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data ){ data[ 0 ] = devpriv->caldac_value[ CR_CHAN( insn->chanspec ) ]; return 1;}/* 1602/16 pregain offset */static int dac08_write( comedi_device *dev, lsampl_t value ){ if( devpriv->dac08_value == value ) return 1; devpriv->dac08_value = value; outw( SELECT_DAC08_BIT | ( value & 0xff ), devpriv->control_status + CALIBRATION_REG ); return 1;}static int dac08_write_insn( comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data ){ return dac08_write( dev, data[ 0 ] );}static int dac08_read_insn( comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data ){ data[ 0 ] = devpriv->dac08_value; return 1;}static int cb_pcidas_trimpot_write( comedi_device *dev, unsigned int channel, lsampl_t value ){ if( devpriv->trimpot_value[ channel ] == value ) return 1; devpriv->trimpot_value[ channel ] = value; switch( thisboard->trimpot ) { case AD7376: trimpot_7376_write( dev, value ); break; case AD8402: trimpot_8402_write( dev, channel, value ); break; default: comedi_error( dev, "driver bug?" ); return -1; break; } return 1;}static int trimpot_write_insn( comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data ){ unsigned int channel = CR_CHAN( insn->chanspec ); return cb_pcidas_trimpot_write( dev, channel, data[ 0 ] );}static int trimpot_read_insn( comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data ){ unsigned int channel = CR_CHAN( insn->chanspec ); data[ 0 ] = devpriv->trimpot_value[ channel ]; return 1;}static int cb_pcidas_ai_cmdtest(comedi_device *dev,comedi_subdevice *s, comedi_cmd *cmd){ int err=0; int tmp; int i, gain, start_chan; /* cmdtest tests a particular command to see if it is valid. * Using the cmdtest ioctl, a user can create a valid cmd * and then have it executes by the cmd ioctl. * * cmdtest returns 1,2,3,4 or 0, depending on which tests * the command passes. */ /* step 1: make sure trigger sources are trivially valid */ tmp = cmd->start_src; cmd->start_src &= TRIG_NOW | TRIG_EXT; if(!cmd->start_src || tmp != cmd->start_src) err++; tmp = cmd->scan_begin_src; cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT; if(!cmd->scan_begin_src || tmp != cmd->scan_begin_src) err++; tmp = cmd->convert_src; cmd->convert_src &= TRIG_TIMER | TRIG_NOW | TRIG_EXT; 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 */ if(cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) err++; if(cmd->scan_begin_src != TRIG_FOLLOW && cmd->scan_begin_src != TRIG_TIMER && cmd->scan_begin_src != TRIG_EXT) err++; if(cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) err++; if(cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) err++; // make sure trigger sources are compatible with each other if(cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW) err++; if(cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW) err++; if(cmd->start_src == TRIG_EXT && (cmd->convert_src == TRIG_EXT || cmd->scan_begin_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_src == TRIG_TIMER) { if (cmd->scan_begin_arg < thisboard->ai_speed * cmd->chanlist_len) { cmd->scan_begin_arg = thisboard->ai_speed * cmd->chanlist_len; err++; } } if (cmd->convert_src == TRIG_TIMER) { if (cmd->convert_arg < thisboard->ai_speed) { cmd->convert_arg = thisboard->ai_speed; err++; } } if(cmd->scan_end_arg != cmd->chanlist_len) { cmd->scan_end_arg = cmd->chanlist_len; err++; } if(cmd->stop_src == TRIG_NONE) { /* TRIG_NONE */ if (cmd->stop_arg != 0) { cmd->stop_arg=0; err++; } } if(err)return 3; /* step 4: fix up any arguments */ if(cmd->scan_begin_src == TRIG_TIMER) { tmp = cmd->scan_begin_arg; i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1), &(devpriv->divisor2), &(cmd->scan_begin_arg), cmd->flags & TRIG_ROUND_MASK); if(tmp != cmd->scan_begin_arg) err++; } if(cmd->convert_src == TRIG_TIMER) { tmp=cmd->convert_arg; i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1), &(devpriv->divisor2), &(cmd->convert_arg), cmd->flags & TRIG_ROUND_MASK); if(tmp != cmd->convert_arg) err++; } if(err) return 4; // check channel/gain list against card's limitations if(cmd->chanlist) { gain = CR_RANGE(cmd->chanlist[0]); start_chan = CR_CHAN(cmd->chanlist[0]); for(i = 1; i < cmd->chanlist_len; i++) { if(CR_CHAN(cmd->chanlist[i]) != (start_chan + i) % s->n_chan) { comedi_error(dev, "entries in chanlist must be consecutive channels, counting upwards\n"); err++; } if(CR_RANGE(cmd->chanlist[i]) != gain) { comedi_error(dev, "entries in chanlist must all have the same gain\n"); err++; } } } if(err) return 5; return 0;}static int cb_pcidas_ai_cmd(comedi_device *dev,comedi_subdevice *s){ comedi_async *async = s->async; comedi_cmd *cmd = &async->cmd; unsigned int bits; unsigned long flags; // make sure CAL_EN_BIT is disabled outw(0, devpriv->control_status + CALIBRATION_REG); // initialize before settings pacer source and count values outw(0, devpriv->control_status + TRIG_CONTSTAT); // clear fifo outw(0, devpriv->adc_fifo + ADCFIFOCLR); // set mux limits, gain and pacer source bits = BEGIN_SCAN(CR_CHAN(cmd->chanlist[0])) | END_SCAN(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) | GAIN_BITS(CR_RANGE(cmd->chanlist[0])); // set unipolar/bipolar if(CR_RANGE(cmd->chanlist[0]) & IS_UNIPOLAR) bits |= UNIP; // set singleended/differential if(CR_AREF(cmd->chanlist[0]) != AREF_DIFF) bits |= SE; // set pacer source if(cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT) bits |= PACER_EXT_RISE; else bits |= PACER_INT; outw(bits, devpriv->control_status + ADCMUX_CONT);#ifdef CB_PCIDAS_DEBUG rt_printk("comedi: sent 0x%x to adcmux control\n", bits);#endif // load counters if(cmd->convert_src == TRIG_TIMER) cb_pcidas_load_counters(dev, &cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); else if(cmd->scan_begin_src == TRIG_TIMER) cb_pcidas_load_counters(dev, &cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); // set number of conversions if(cmd->stop_src == TRIG_COUNT) { devpriv->count = cmd->chanlist_len * cmd->stop_arg; } // enable interrupts comedi_spin_lock_irqsave( &dev->spinlock, flags ); devpriv->adc_fifo_bits |= INTE; devpriv->adc_fifo_bits &= ~INT_MASK; if(cmd->flags & TRIG_WAKE_EOS) { if(cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1) devpriv->adc_fifo_bits |= INT_EOS; // interrupt end of burst else devpriv->adc_fifo_bits |= INT_FNE; // interrupt fifo not empty }else { devpriv->adc_fifo_bits |= INT_FHF; //interrupt fifo half full }#ifdef CB_PCIDAS_DEBUG rt_printk("comedi: adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits);#endif // enable (and clear) interrupts outw(devpriv->adc_fifo_bits | EOAI | INT | LADFUL, devpriv->control_status + INT_ADCFIFO); comedi_spin_unlock_irqrestore( &dev->spinlock, flags ); // set start trigger and burst mode bits = 0; if(cmd->start_src == TRIG_NOW) bits |= SW_TRIGGER; else if(cmd->start_src == TRIG_EXT) bits |= EXT_TRIGGER | TGEN | XTRCL; else { comedi_error(dev, "bug!"); return -1; } if(cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1) bits |= BURSTE; outw(bits, devpriv->control_status + TRIG_CONTSTAT);#ifdef CB_PCIDAS_DEBUG rt_printk("comedi: sent 0x%x to trig control\n", bits);#endif return 0;}static int cb_pcidas_ao_cmdtest(comedi_device *dev,comedi_subdevice *s, comedi_cmd *cmd){ int err=0; int tmp; /* cmdtest tests a particular command to see if it is valid. * Using the cmdtest ioctl, a user can create a valid cmd * and then have it executes by the cmd ioctl. * * cmdtest returns 1,2,3,4 or 0, depending on which tests * the command passes. */ /* step 1: make sure trigger sources are trivially valid */ tmp = cmd->start_src; cmd->start_src &= TRIG_INT; if(!cmd->start_src || tmp != cmd->start_src) err++; tmp = cmd->scan_begin_src; cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; 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 */ if(cmd->scan_begin_src != TRIG_TIMER && cmd->scan_begin_src != TRIG_EXT) err++; if(cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) 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_src == TRIG_TIMER) { if (cmd->scan_begin_arg < thisboard->ao_scan_speed) { cmd->scan_begin_arg = thisboard->ao_scan_speed; err++; } } if(cmd->scan_end_arg != cmd->chanlist_len) { cmd->scan_end_arg = cmd->chanlist_len; err++; } if(cmd->stop_src == TRIG_NONE) { /* TRIG_NONE */ if (cmd->stop_arg != 0) { cmd->stop_arg=0; err++; } } if(err)return 3; /* step 4: fix up any arguments */ if(cmd->scan_begin_src == TRIG_TIMER) { tmp = cmd->scan_begin_arg; i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->ao_divisor1), &(devpriv->ao_divisor2), &(cmd->scan_begin_arg), cmd->flags & TRIG_ROUND_MASK); if(tmp != cmd->scan_begin_arg) err++; } if(err) return 4; // check channel/gain list against card's limitations if(cmd->chanlist && cmd->chanlist_len > 1) { if(CR_CHAN(cmd->chanlist[0]) != 0 || CR_CHAN(cmd->chanlist[1]) != 1) { comedi_error(dev, "channels must be ordered channel 0, channel 1 in chanlist\n"); err++; } } if(err) return 5; return 0;}static int cb_pcidas_ao_cmd(comedi_device *dev,comedi_subdevice *s){ comedi_async *async = s->async;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -