📄 adl_pci9118.c
字号:
} if (m & 0x008) { comedi_error(dev,"A/D Burst Mode Overrun Status (Fatal Error!)"); devpriv->ai_maskerr&=~0x008L; } if (m & 0x004) { comedi_error(dev,"A/D Over Speed Status (Warning!)"); devpriv->ai_maskerr&=~0x004L; } if (m & 0x002) { comedi_error(dev,"A/D Overrun Status (Fatal Error!)"); devpriv->ai_maskerr&=~0x002L; } if (m & devpriv->ai_maskharderr) { s->async->events|=COMEDI_CB_ERROR|COMEDI_CB_EOA; pci9118_ai_cancel(dev,s); comedi_event(dev,s,s->async->events); return 1; } return 0;}/*==============================================================================*/static void interrupt_pci9118_ai_onesample(comedi_device *dev,comedi_subdevice *s, unsigned short int_adstat, unsigned int int_amcc, unsigned short int_daq){ register sampl_t sampl; s->async->events=0; if (int_adstat & devpriv->ai_maskerr) if (pci9118_decode_error_status(dev,s,int_adstat)) return; sampl=inw(dev->iobase+PCI9118_AD_DATA); if (devpriv->ai16bits) { cfc_write_to_buffer( s, sampl ^ 0x8000 ); } else {#ifdef PCI9118_PARANOIDCHECK if ((sampl & 0x000f)!=devpriv->chanlist[s->async->cur_chan]) { // data dropout! rt_printk("comedi: A/D SAMPL - data dropout: received channel %d, expected %d!\n",sampl & 0x000f, devpriv->chanlist[s->async->cur_chan]); s->async->events|=COMEDI_CB_ERROR|COMEDI_CB_EOA; pci9118_ai_cancel(dev,s); comedi_event(dev,s,s->async->events); return; }#endif cfc_write_to_buffer( s, ( sampl >> 4 ) & 0x0fff ); } if (s->async->cur_chan == 0) { /* one scan done */ devpriv->ai_act_scan++; if (!(devpriv->ai_neverending)) if (devpriv->ai_act_scan>=devpriv->ai_scans) { /* all data sampled */ pci9118_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA; } } if (s->async->events) comedi_event(dev,s,s->async->events);}/*==============================================================================*/static void interrupt_pci9118_ai_dma(comedi_device *dev,comedi_subdevice *s, unsigned short int_adstat, unsigned int int_amcc, unsigned short int_daq){ lsampl_t *ptr; unsigned int next_dma_buf, samplesinbuf, sampls, m; s->async->events=0; if (int_amcc&MASTER_ABORT_INT) { comedi_error(dev,"AMCC IRQ - MASTER DMA ABORT!"); s->async->events|=COMEDI_CB_ERROR|COMEDI_CB_EOA; pci9118_ai_cancel(dev,s); comedi_event(dev,s,s->async->events); return; } if (int_amcc&TARGET_ABORT_INT) { comedi_error(dev,"AMCC IRQ - TARGET DMA ABORT!"); s->async->events|=COMEDI_CB_ERROR|COMEDI_CB_EOA; pci9118_ai_cancel(dev,s); comedi_event(dev,s,s->async->events); return; } if (int_adstat & devpriv->ai_maskerr)// if (int_adstat & 0x106) if (pci9118_decode_error_status(dev,s,int_adstat)) return; samplesinbuf=devpriv->dmabuf_use_size[devpriv->dma_actbuf]>>1; // number of received real samples// DPRINTK("dma_actbuf=%d\n",devpriv->dma_actbuf); if (devpriv->dma_doublebuf) { // switch DMA buffers if is used double buffering next_dma_buf=1-devpriv->dma_actbuf; outl(devpriv->dmabuf_hw[next_dma_buf], devpriv->iobase_a+AMCC_OP_REG_MWAR); outl(devpriv->dmabuf_use_size[next_dma_buf], devpriv->iobase_a+AMCC_OP_REG_MWTC); devpriv->dmabuf_used_size[next_dma_buf]=devpriv->dmabuf_use_size[next_dma_buf]; if (devpriv->ai_do==4) interrupt_pci9118_ai_mode4_switch(dev); } ptr=(lsampl_t *)devpriv->dmabuf_virt[devpriv->dma_actbuf]; while (samplesinbuf) { m = devpriv->ai_data_len >> 1; // how many samples is to end of buffer// DPRINTK("samps=%d m=%d %d %d\n",samplesinbuf,m,s->async->buf_int_count,s->async->buf_int_ptr); sampls=m; if (devpriv->dma_ai_read_block(dev, s, &ptr, &sampls, &samplesinbuf)) return; // Uiii, error m=m-sampls; // m= how many samples was transfered }// DPRINTK("YYY\n"); if (!devpriv->ai_neverending) if ( devpriv->ai_act_scan>=devpriv->ai_scans ) { /* all data sampled */ pci9118_ai_cancel(dev,s); s->async->events|=COMEDI_CB_EOA; } if (devpriv->dma_doublebuf) { // switch dma buffers devpriv->dma_actbuf=1-devpriv->dma_actbuf; } else { // restart DMA if is not used double buffering outl(devpriv->dmabuf_hw[0], devpriv->iobase_a+AMCC_OP_REG_MWAR); outl(devpriv->dmabuf_use_size[0], devpriv->iobase_a+AMCC_OP_REG_MWTC); if (devpriv->ai_do==4) interrupt_pci9118_ai_mode4_switch(dev); } comedi_event(dev,s,s->async->events);}/* ==============================================================================*/static void interrupt_pci9118(int irq, void *d, struct pt_regs *regs) { comedi_device *dev = d; unsigned int int_daq=0,int_amcc,int_adstat; int_daq=inl(dev->iobase+PCI9118_INTSRC) & 0xf; // get IRQ reasons from card int_amcc=inl(devpriv->iobase_a+AMCC_OP_REG_INTCSR); // get INT register from AMCC chip// DPRINTK("INT daq=0x%01x amcc=0x%08x MWAR=0x%08x MWTC=0x%08x ADSTAT=0x%02x ai_do=%d\n", int_daq, int_amcc, inl(devpriv->iobase_a+AMCC_OP_REG_MWAR), inl(devpriv->iobase_a+AMCC_OP_REG_MWTC), inw(dev->iobase+PCI9118_ADSTAT)&0x1ff,devpriv->ai_do); if ((!int_daq)&&(!(int_amcc&ANY_S593X_INT))) return; // interrupt from other source outl(int_amcc|0x00ff0000, devpriv->iobase_a+AMCC_OP_REG_INTCSR); // shutdown IRQ reasons in AMCC int_adstat=inw(dev->iobase+PCI9118_ADSTAT)&0x1ff; // get STATUS register if (devpriv->ai_do) { if (devpriv->ai12_startstop) if ((int_adstat&AdStatus_DTH)&&(int_daq&Int_DTrg)) { // start stop of measure if (devpriv->ai12_startstop&START_AI_EXT) { devpriv->ai12_startstop&=~START_AI_EXT; if (!(devpriv->ai12_startstop&STOP_AI_EXT)) pci9118_exttrg_del(dev,EXTTRG_AI); // deactivate EXT trigger start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1, devpriv->ai_divisor2); // start pacer outl(devpriv->AdControlReg, dev->iobase+PCI9118_ADCNTRL); } else { if (devpriv->ai12_startstop&STOP_AI_EXT) { devpriv->ai12_startstop&=~STOP_AI_EXT; pci9118_exttrg_del(dev,EXTTRG_AI); // deactivate EXT trigger devpriv->ai_neverending=0; //well, on next interrupt from DMA/EOC measure will stop } } } (devpriv->int_ai_func)(dev,dev->subdevices + 0,int_adstat,int_amcc,int_daq); }}/*==============================================================================*/static int pci9118_ai_inttrig(comedi_device *dev,comedi_subdevice *s, unsigned int trignum){ if (trignum!=devpriv->ai_inttrig_start) return -EINVAL; devpriv->ai12_startstop&=~START_AI_INT; s->async->inttrig=NULL; outl(devpriv->IntControlReg,dev->iobase+PCI9118_INTCTRL); outl(devpriv->AdFunctionReg,dev->iobase+PCI9118_ADFUNC); if (devpriv->ai_do!=3) { start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1, devpriv->ai_divisor2); devpriv->AdControlReg|=AdControl_SoftG; } outl(devpriv->AdControlReg, dev->iobase+PCI9118_ADCNTRL); return 1;}/*==============================================================================*/static int pci9118_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd){ int err=0; int tmp,divisor1,divisor2; /* step 1: make sure trigger sources are trivially valid */ tmp=cmd->start_src; cmd->start_src &= TRIG_NOW|TRIG_EXT|TRIG_INT; if (!cmd->start_src || tmp!=cmd->start_src) err++; tmp=cmd->scan_begin_src; if (devpriv->master) { cmd->scan_begin_src &= TRIG_TIMER|TRIG_EXT|TRIG_FOLLOW; } else { cmd->scan_begin_src &= TRIG_FOLLOW; } if (!cmd->scan_begin_src || tmp!=cmd->scan_begin_src) err++; tmp=cmd->convert_src; if (devpriv->master) { cmd->convert_src &= TRIG_TIMER|TRIG_EXT|TRIG_NOW; } else { 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|TRIG_EXT; 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_INT && cmd->start_src!=TRIG_EXT) { cmd->start_src=TRIG_NOW; err++; } if (cmd->scan_begin_src!=TRIG_TIMER && cmd->scan_begin_src!=TRIG_EXT && cmd->scan_begin_src!=TRIG_INT && cmd->scan_begin_src!=TRIG_FOLLOW) { cmd->scan_begin_src=TRIG_FOLLOW; err++; } if (cmd->convert_src!=TRIG_TIMER && cmd->convert_src!=TRIG_EXT && cmd->convert_src!=TRIG_NOW) { cmd->convert_src=TRIG_TIMER; 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 && cmd->stop_src!=TRIG_INT && cmd->stop_src!=TRIG_EXT) { cmd->stop_src=TRIG_COUNT; err++; } if (cmd->start_src==TRIG_EXT && cmd->scan_begin_src==TRIG_EXT) { cmd->start_src=TRIG_NOW; err++; } if (cmd->start_src==TRIG_INT && cmd->scan_begin_src==TRIG_INT) { cmd->start_src=TRIG_NOW; err++; } if ((cmd->scan_begin_src&(TRIG_TIMER|TRIG_EXT)) && (!(cmd->convert_src&(TRIG_TIMER|TRIG_NOW)))) { cmd->convert_src=TRIG_TIMER; err++; } if ((cmd->scan_begin_src==TRIG_FOLLOW) && (!(cmd->convert_src&(TRIG_TIMER|TRIG_EXT)))) { cmd->convert_src=TRIG_TIMER; err++; } if (cmd->stop_src==TRIG_EXT && cmd->scan_begin_src==TRIG_EXT) { cmd->stop_src=TRIG_COUNT; err++; } if (err) return 2; /* step 3: make sure arguments are trivially compatible */ if (cmd->start_src&(TRIG_NOW|TRIG_EXT)) if (cmd->start_arg!=0) { cmd->start_arg=0; err++; } if (cmd->scan_begin_src&(TRIG_FOLLOW|TRIG_EXT)) if (cmd->scan_begin_arg!=0) { cmd->scan_begin_arg=0; err++; } if ((cmd->scan_begin_src==TRIG_TIMER) && (cmd->convert_src==TRIG_TIMER) && (cmd->scan_end_arg==1)) { cmd->scan_begin_src=TRIG_FOLLOW; cmd->convert_arg=cmd->scan_begin_arg; cmd->scan_begin_arg=0; } if (cmd->scan_begin_src==TRIG_TIMER) if (cmd->scan_begin_arg<this_board->ai_ns_min) { cmd->scan_begin_arg=this_board->ai_ns_min; err++; } if (cmd->scan_begin_src==TRIG_EXT) if (cmd->scan_begin_arg) { cmd->scan_begin_arg=0; err++; if (cmd->scan_end_arg>65535) { cmd->scan_end_arg=65535; err++; } } if (cmd->convert_src&(TRIG_TIMER|TRIG_NOW)) if (cmd->convert_arg<this_board->ai_ns_min) { cmd->convert_arg=this_board->ai_ns_min; err++; } if (cmd->convert_src==TRIG_EXT) if (cmd->convert_arg) { cmd->convert_arg=0; 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++; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -