📄 adv_pci1710.c
字号:
int n,rangereg,chan; chan=CR_CHAN(insn->chanspec); rangereg=devpriv->da_ranges & (~(0x03<<(chan<<1))); rangereg|=(CR_RANGE(insn->chanspec)<<(chan<<1)); if (rangereg!=devpriv->da_ranges) { outb(rangereg, dev->iobase+PCI1720_RANGE); devpriv->da_ranges=rangereg; } for (n=0; n<insn->n; n++) { outw(data[n], dev->iobase+PCI1720_DA0+(chan<<1)); outb(0, dev->iobase + PCI1720_SYNCOUT); // update outputs } devpriv->ao_data[chan]=data[n]; return n;}/*==============================================================================*/static void interrupt_pci1710_every_sample(void *d){ comedi_device *dev = d; comedi_subdevice *s = dev->subdevices + 0; int m;#ifdef PCI171x_PARANOIDCHECK sampl_t sampl;#endif DPRINTK("adv_pci1710 EDBG: BGN: interrupt_pci1710_every_sample(...)\n"); m=inw(dev->iobase+PCI171x_STATUS); if (m & Status_FE) { rt_printk("comedi%d: A/D FIFO empty (%4x)\n", dev->minor, m); pci171x_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev,s,s->async->events); return; } if (m & Status_FF) { rt_printk("comedi%d: A/D FIFO Full status (Fatal Error!) (%4x)\n", dev->minor, m); pci171x_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev,s,s->async->events); return; } outb(0, dev->iobase + PCI171x_CLRINT); // clear our INT request DPRINTK("FOR "); for (;!(inw(dev->iobase+PCI171x_STATUS)&Status_FE);) {#ifdef PCI171x_PARANOIDCHECK sampl=inw(dev->iobase+PCI171x_AD_DATA); DPRINTK("%04x:",sampl); if (this_board->cardtype!=TYPE_PCI1713) if ((sampl & 0xf000)!=devpriv->act_chanlist[s->async->cur_chan]) { rt_printk("comedi: A/D data dropout: received data from channel %d, expected %d!\n",(sampl & 0xf000)>>12,(devpriv->act_chanlist[s->async->cur_chan] & 0xf000)>>12); pci171x_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev,s,s->async->events); return; } DPRINTK("%8d %2d %8d~",s->async->buf_int_ptr,s->async->cur_chan,s->async->buf_int_count); comedi_buf_put( s->async, sampl & 0x0fff);#else comedi_buf_put( s->async, inw(dev->iobase+PCI171x_AD_DATA) & 0x0fff);#endif if(s->async->cur_chan == 0){ // one scan done devpriv->ai_act_scan++; DPRINTK("adv_pci1710 EDBG: EOS1 bic %d bip %d buc %d bup %d\n",s->async->buf_int_count,s->async->buf_int_ptr, s->async->buf_user_count, s->async->buf_user_ptr); DPRINTK("adv_pci1710 EDBG: EOS2\n"); if ((!devpriv->neverending_ai)&&(devpriv->ai_act_scan>=devpriv->ai_scans)) { // all data sampled pci171x_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA; comedi_event(dev,s,s->async->events); return; } } } outb(0, dev->iobase + PCI171x_CLRINT); // clear our INT request DPRINTK("adv_pci1710 EDBG: END: interrupt_pci1710_every_sample(...)\n"); comedi_event(dev,s,s->async->events);}/* ==============================================================================*/static int move_block_from_fifo(comedi_device *dev,comedi_subdevice *s, int n, int turn){ int i,j;#ifdef PCI171x_PARANOIDCHECK int sampl;#endif DPRINTK("adv_pci1710 EDBG: BGN: move_block_from_fifo(...,%d,%d)\n",n,turn); j=s->async->cur_chan; for(i=0;i<n;i++) {#ifdef PCI171x_PARANOIDCHECK sampl=inw(dev->iobase+PCI171x_AD_DATA); if (this_board->cardtype!=TYPE_PCI1713) if ((sampl & 0xf000)!=devpriv->act_chanlist[j]) { rt_printk("comedi%d: A/D FIFO data dropout: received data from channel %d, expected %d! (%d/%d/%d/%d/%d/%4x)\n", dev->minor, (sampl & 0xf000)>>12,(devpriv->act_chanlist[j] & 0xf000)>>12, i, j, devpriv->ai_act_scan, n, turn, sampl); pci171x_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev,s,s->async->events); return 1; } comedi_buf_put( s->async, sampl & 0x0fff );#else comedi_buf_put( s->async, inw(dev->iobase+PCI171x_AD_DATA) & 0x0fff );#endif j++; if(j>=devpriv->ai_n_chan){ j=0; devpriv->ai_act_scan++; } } DPRINTK("adv_pci1710 EDBG: END: move_block_from_fifo(...)\n"); return 0;}/* ==============================================================================*/static void interrupt_pci1710_half_fifo(void *d) { comedi_device *dev = d; comedi_subdevice *s = dev->subdevices + 0; int m,samplesinbuf; DPRINTK("adv_pci1710 EDBG: BGN: interrupt_pci1710_half_fifo(...)\n"); m=inw(dev->iobase+PCI171x_STATUS); if (!(m & Status_FH)) { rt_printk("comedi%d: A/D FIFO not half full! (%4x)\n", dev->minor, m); pci171x_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev,s,s->async->events); return; } if (m & Status_FF) { rt_printk("comedi%d: A/D FIFO Full status (Fatal Error!) (%4x)\n", dev->minor, m); pci171x_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev,s,s->async->events); return; } samplesinbuf=this_board->fifo_half_size; if(samplesinbuf*sizeof(sampl_t)>=devpriv->ai_data_len){ m=devpriv->ai_data_len/sizeof(sampl_t); if (move_block_from_fifo(dev,s,m,0)) return; samplesinbuf-=m; } if (samplesinbuf) { if (move_block_from_fifo(dev,s,samplesinbuf,1)) return; } if (!devpriv->neverending_ai) if ( devpriv->ai_act_scan>=devpriv->ai_scans ) { /* all data sampled */ pci171x_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA; comedi_event(dev,s,s->async->events); return; } outb(0, dev->iobase + PCI171x_CLRINT); // clear our INT request DPRINTK("adv_pci1710 EDBG: END: interrupt_pci1710_half_fifo(...)\n"); comedi_event(dev,s,s->async->events); }/* ==============================================================================*/static void interrupt_service_pci1710(int irq, void *d, struct pt_regs *regs) { comedi_device *dev = d; DPRINTK("adv_pci1710 EDBG: BGN: interrupt_service_pci1710(%d,...)\n",irq); if (!(inw(dev->iobase + PCI171x_STATUS) & Status_IRQ)) // is this interrupt from our board? return; // no, exit DPRINTK("adv_pci1710 EDBG: interrupt_service_pci1710() ST: %4x\n",inw(dev->iobase + PCI171x_STATUS)); if (devpriv->ai_et) { // Switch from initial TRIG_EXT to TRIG_xxx. devpriv->ai_et = 0; outw(Control_SW, dev->iobase+PCI171x_CONTROL); devpriv->CntrlReg=devpriv->ai_et_CntrlReg; outb(0,dev->iobase + PCI171x_CLRFIFO); outb(0,dev->iobase + PCI171x_CLRINT); outw(devpriv->ai_et_MuxVal, dev->iobase+PCI171x_MUX); outw(devpriv->CntrlReg, dev->iobase+PCI171x_CONTROL); // start pacer start_pacer(dev, 1, devpriv->ai_et_div1, devpriv->ai_et_div2); return; } if (devpriv->ai_eos) { // We use FIFO half full INT or not? interrupt_pci1710_every_sample(d); } else { interrupt_pci1710_half_fifo(d); } DPRINTK("adv_pci1710 EDBG: END: interrupt_service_pci1710(...)\n");}/* ==============================================================================*/static int pci171x_ai_docmd_and_mode(int mode, comedi_device * dev, comedi_subdevice * s) { unsigned int divisor1, divisor2; unsigned int seglen; DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_docmd_and_mode(%d,...)\n",mode); start_pacer(dev, -1, 0, 0); // stop pacer seglen = check_channel_list(dev, s, devpriv->ai_chanlist, devpriv->ai_n_chan); if(seglen<1)return -EINVAL; setup_channel_list(dev, s, devpriv->ai_chanlist, devpriv->ai_n_chan,seglen); outb(0, dev->iobase + PCI171x_CLRFIFO); outb(0, dev->iobase + PCI171x_CLRINT); devpriv->ai_do=mode; devpriv->ai_act_scan=0; s->async->cur_chan=0; devpriv->ai_buf_ptr=0; devpriv->neverending_ai=0; devpriv->CntrlReg&=Control_CNT0; if ((devpriv->ai_flags & TRIG_WAKE_EOS)) { // don't we want wake up every scan? devpriv->ai_eos=1; devpriv->ai_eos=1; } else { devpriv->CntrlReg|=Control_ONEFH; devpriv->ai_eos=0; } if ((devpriv->ai_scans==0)||(devpriv->ai_scans==-1)) { devpriv->neverending_ai=1; } //well, user want neverending else { devpriv->neverending_ai=0; } switch (mode) { case 1: case 2: if (devpriv->ai_timer1<this_board->ai_ns_min) devpriv->ai_timer1=this_board->ai_ns_min; devpriv->CntrlReg|=Control_PACER|Control_IRQEN; if (mode == 2) { devpriv->ai_et_CntrlReg=devpriv->CntrlReg; devpriv->CntrlReg&=~(Control_PACER|Control_ONEFH|Control_GATE); devpriv->CntrlReg|=Control_EXT; devpriv->ai_et=1; } else { devpriv->ai_et=0; } i8253_cascade_ns_to_timer(devpriv->i8254_osc_base,&divisor1,&divisor2,&devpriv->ai_timer1,devpriv->ai_flags&TRIG_ROUND_MASK); DPRINTK("adv_pci1710 EDBG: OSC base=%u div1=%u div2=%u timer=%u\n",devpriv->i8254_osc_base,divisor1,divisor2,devpriv->ai_timer1); outw(devpriv->CntrlReg, dev->iobase+PCI171x_CONTROL); if (mode != 2) { // start pacer start_pacer(dev, mode, divisor1, divisor2); } else { devpriv->ai_et_div1 = divisor1; devpriv->ai_et_div2 = divisor2; } break; case 3: devpriv->CntrlReg|=Control_EXT|Control_IRQEN; outw(devpriv->CntrlReg, dev->iobase+PCI171x_CONTROL); break; } DPRINTK("adv_pci1710 EDBG: END: pci171x_ai_docmd_and_mode(...)\n"); return 0;}#ifdef PCI171X_EXTDEBUG/* ==============================================================================*/static void pci171x_cmdtest_out(int e,comedi_cmd *cmd) { rt_printk("adv_pci1710 e=%d startsrc=%x scansrc=%x convsrc=%x\n",e,cmd->start_src,cmd->scan_begin_src,cmd->convert_src); rt_printk("adv_pci1710 e=%d startarg=%d scanarg=%d convarg=%d\n",e,cmd->start_arg,cmd->scan_begin_arg,cmd->convert_arg); rt_printk("adv_pci1710 e=%d stopsrc=%x scanend=%x\n",e,cmd->stop_src,cmd->scan_end_src); rt_printk("adv_pci1710 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n",e,cmd->stop_arg,cmd->scan_end_arg,cmd->chanlist_len);}#endif/* ==============================================================================*/static int pci171x_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd){ int err=0; int tmp,divisor1,divisor2; DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...)\n");#ifdef PCI171X_EXTDEBUG pci171x_cmdtest_out(-1, cmd);#endif /* 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; if(!cmd->scan_begin_src || tmp!=cmd->scan_begin_src)err++; tmp=cmd->convert_src; cmd->convert_src &= TRIG_TIMER|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) {#ifdef PCI171X_EXTDEBUG pci171x_cmdtest_out(1, cmd);#endif DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=1\n",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) { cmd->start_src=TRIG_NOW; err++; } if(cmd->scan_begin_src!=TRIG_FOLLOW) { cmd->scan_begin_src=TRIG_FOLLOW; err++; } if(cmd->convert_src!=TRIG_TIMER && cmd->convert_src!=TRIG_EXT) err++; if(cmd->scan_end_src!=TRIG_COUNT) { cmd->scan_end_src=TRIG_COUNT; err++; } if(cmd->stop_src!=TRIG_NONE && cmd->stop_src!=TRIG_COUNT) err++; if(err) {#ifdef PCI171X_EXTDEBUG pci171x_cmdtest_out(2, cmd);#endif DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=2\n",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!=0){ cmd->scan_begin_arg=0; err++; } if(cmd->convert_src==TRIG_TIMER){ if(cmd->convert_arg<this_board->ai_ns_min){ cmd->convert_arg=this_board->ai_ns_min; err++; } } else { /* TRIG_FOLLOW */ if(cmd->convert_arg!=0){ cmd->convert_arg=0; err++; } } if(!cmd->chanlist_len){ cmd->chanlist_len=1; err++; } if(cmd->chanlist_len>this_board->n_aichan){ cmd->chanlist_len=this_board->n_aichan; 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){ cmd->stop_arg=1; err++; } } else { /* TRIG_NONE */ if(cmd->stop_arg!=0){ cmd->stop_arg=0; err++; } } if(err) {#ifdef PCI171X_EXTDEBUG pci171x_cmdtest_out(3, cmd);#endif DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=3\n",err); return 3; } /* step 4: fix up any arguments */ if(cmd->convert_src==TRIG_TIMER){ tmp=cmd->convert_arg; i8253_cascade_ns_to_timer(devpriv->i8254_osc_base,&divisor1,&divisor2,&cmd->convert_arg,cmd->flags&TRIG_ROUND_MASK); if(cmd->convert_arg<this_board->ai_ns_min) cmd->convert_arg=this_board->ai_ns_min; if(tmp!=cmd->convert_arg)err++; } if(err) { DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=4\n",err);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -