📄 hwdrv_apci3120.c
字号:
if ((!int_daq)&&(!(int_amcc&ANY_S593X_INT))) { comedi_error(dev,"IRQ from unknow source"); return; } outl(int_amcc|0x00ff0000, devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR);// shutdown IRQ reasons in AMCC int_daq = (int_daq >> 12) & 0xF; if(devpriv->b_ExttrigEnable == APCI3120_ENABLE) { //Disable ext trigger i_APCI3120_ExttrigDisable(dev); devpriv->b_ExttrigEnable = APCI3120_DISABLE; } //clear the timer 2 interrupt inb(devpriv->i_IobaseAmcc+ APCI3120_TIMER_STATUS_REGISTER); if (int_amcc&MASTER_ABORT_INT) comedi_error(dev,"AMCC IRQ - MASTER DMA ABORT!"); if (int_amcc&TARGET_ABORT_INT) comedi_error(dev,"AMCC IRQ - TARGET DMA ABORT!"); // Ckeck if EOC interrupt if(((int_daq & 0x8) == 0) && (devpriv->b_InterruptMode==APCI3120_EOC_MODE)) { if(devpriv->b_EocEosInterrupt==APCI3120_ENABLE) { // Read the AI Value devpriv->ui_AiReadData[0]=(UINT)inw(devpriv->iobase+0); devpriv->b_EocEosInterrupt = APCI3120_DISABLE; send_sig(SIGIO,devpriv->tsk_Current,0); // send signal to the sample } else { //Disable EOC Interrupt devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT; outb(devpriv->b_ModeSelectRegister,devpriv->iobase+APCI3120_WRITE_MODE_SELECT); } } // Check If EOS interrupt if( (int_daq & 0x2) && (devpriv->b_InterruptMode==APCI3120_EOS_MODE) ) { if(devpriv->b_EocEosInterrupt==APCI3120_ENABLE)// enable this in without DMA ??? { if(devpriv->b_AiCyclicAcquisition==APCI3120_ENABLE) { ui_Check=0; i_APCI3120_InterruptHandleEos(dev); devpriv->ui_AiActualScan++; devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister | APCI3120_ENABLE_EOS_INT; outb(devpriv->b_ModeSelectRegister,dev->iobase+APCI3120_WRITE_MODE_SELECT); } else { ui_Check=0; for(i=0;i< devpriv->ui_AiNbrofChannels;i++) { us_TmpValue=inw(devpriv->iobase+0); devpriv->ui_AiReadData[i]=(UINT) us_TmpValue; } devpriv->b_EocEosInterrupt = APCI3120_DISABLE; devpriv->b_InterruptMode=APCI3120_EOC_MODE; send_sig(SIGIO,devpriv->tsk_Current,0); // send signal to the sample } } else { devpriv->b_ModeSelectRegister= devpriv->b_ModeSelectRegister & APCI3120_DISABLE_EOS_INT; outb(devpriv->b_ModeSelectRegister,dev->iobase+APCI3120_WRITE_MODE_SELECT); devpriv->b_EocEosInterrupt = APCI3120_DISABLE; //Default settings devpriv->b_InterruptMode=APCI3120_EOC_MODE; } } //Timer2 interrupt if(int_daq & 0x1) { switch(devpriv->b_Timer2Mode) { case APCI3120_COUNTER: devpriv->b_AiCyclicAcquisition=APCI3120_DISABLE; devpriv->b_ModeSelectRegister= devpriv->b_ModeSelectRegister & APCI3120_DISABLE_EOS_INT; outb(devpriv->b_ModeSelectRegister,dev->iobase+APCI3120_WRITE_MODE_SELECT); // stop timer 2 devpriv->us_OutputRegister=devpriv->us_OutputRegister & APCI3120_DISABLE_ALL_TIMER; outw(devpriv->us_OutputRegister,dev->iobase+APCI3120_WR_ADDRESS); //stop timer 0 and timer 1 i_APCI3120_StopCyclicAcquisition(dev,s); devpriv->b_AiCyclicAcquisition=APCI3120_DISABLE; //UPDATE-0.7.57->0.7.68comedi_done(dev,s); s->async->events |= COMEDI_CB_EOA; comedi_event(dev,s,s->async->events); break; case APCI3120_TIMER: //Send a signal to from kernel to user space send_sig(SIGIO,devpriv->tsk_Current,0); break; case APCI3120_WATCHDOG: //Send a signal to from kernel to user space send_sig(SIGIO,devpriv->tsk_Current,0); break; default : // disable Timer Interrupt devpriv->b_ModeSelectRegister = devpriv-> b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT; outb(devpriv->b_ModeSelectRegister, dev->iobase+ APCI3120_WRITE_MODE_SELECT); } b_DummyRead= inb(dev->iobase+APCI3120_TIMER_STATUS_REGISTER); } if ((int_daq & 0x4) &&(devpriv->b_InterruptMode == APCI3120_DMA_MODE)) { if(devpriv->b_AiCyclicAcquisition==APCI3120_ENABLE) { /****************************/ /* Clear Timer Write TC INT */ /****************************/ outl(APCI3120_CLEAR_WRITE_TC_INT,devpriv->i_IobaseAmcc+ APCI3120_AMCC_OP_REG_INTCSR); /************************************/ /* Clears the timer status register */ /************************************/ inw(dev->iobase+APCI3120_TIMER_STATUS_REGISTER); v_APCI3120_InterruptDma(irq,d,regs); // do some data transfer } else { /* Stops the Timer */ outw(devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER0 & APCI3120_DISABLE_TIMER1,dev->iobase+APCI3120_WR_ADDRESS); } } return;}/*+----------------------------------------------------------------------------+| Function name :int i_APCI3120_InterruptHandleEos(comedi_device *dev) || || |+----------------------------------------------------------------------------+| Task : This function handles EOS interrupt. || This function copies the acquired data(from FIFO) || to Comedi buffer. || |+----------------------------------------------------------------------------+| Input Parameters : comedi_device *dev || || |+----------------------------------------------------------------------------+| Return Value : 0 || |+----------------------------------------------------------------------------+*//*int i_APCI3120_InterruptHandleEos(comedi_device *dev){ int n_chan,i; sampl_t *data; comedi_subdevice *s=dev->subdevices+0; comedi_async *async = s->async; data=async->data+async->buf_int_ptr;//new samples added from here onwards n_chan=devpriv->ui_AiNbrofChannels; for(i=0;i<n_chan;i++) { data[i]=inw(dev->iobase+0); } async->buf_int_count+=n_chan*sizeof(sampl_t); async->buf_int_ptr+=n_chan*sizeof(sampl_t); comedi_eos(dev,s); if (s->async->buf_int_ptr>=s->async->data_len) // for buffer rool over { */ /* buffer rollover *//* s->async->buf_int_ptr=0; comedi_eobuf(dev,s); } return 0;}*/ int i_APCI3120_InterruptHandleEos(comedi_device *dev){ int n_chan,i; comedi_subdevice *s=dev->subdevices+0; int err=1; n_chan=devpriv->ui_AiNbrofChannels; s->async->events = 0; for(i=0;i<n_chan;i++) err &= comedi_buf_put(s->async, inw(dev->iobase+0)); s->async->events |= COMEDI_CB_EOS; if (err==0) s->async->events |= COMEDI_CB_OVERFLOW; comedi_event(dev,s,s->async->events); return 0;}/*+----------------------------------------------------------------------------+| Function name : void v_APCI3120_InterruptDma(int irq, void *d, || struct pt_regs *regs) || |+----------------------------------------------------------------------------+| Task : This is a handler for the DMA interrupt || This function copies the data to Comedi Buffer. || For continuous DMA it reinitializes the DMA operation. || For single mode DMA it stop the acquisition. || |+----------------------------------------------------------------------------+| Input Parameters : int irq, void *d, struct pt_regs *regs || |+----------------------------------------------------------------------------+| Return Value : void || |+----------------------------------------------------------------------------+*/ void v_APCI3120_InterruptDma(int irq, void *d, struct pt_regs *regs) { comedi_device *dev = d; comedi_subdevice *s = dev->subdevices + 0; unsigned int next_dma_buf, samplesinbuf; unsigned long low_word,high_word,var; UINT ui_Tmp; samplesinbuf=devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer]-inl(devpriv->i_IobaseAmcc+AMCC_OP_REG_MWTC); if (samplesinbuf<devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer]) { comedi_error(dev,"Interrupted DMA transfer!"); } if (samplesinbuf & 1) { comedi_error(dev,"Odd count of bytes in DMA ring!"); i_APCI3120_StopCyclicAcquisition(dev,s); devpriv->b_AiCyclicAcquisition=APCI3120_DISABLE; return; } samplesinbuf=samplesinbuf>>1; // number of received samples if (devpriv->b_DmaDoubleBuffer) { // switch DMA buffers if is used double buffering next_dma_buf=1-devpriv->ui_DmaActualBuffer; ui_Tmp=AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO ; outl(ui_Tmp,devpriv->i_IobaseAddon+AMCC_OP_REG_AGCSTS); // changed since 16 bit interface for add on outw(APCI3120_ADD_ON_AGCSTS_LOW,devpriv->i_IobaseAddon+0); outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,devpriv->i_IobaseAddon+2); outw(APCI3120_ADD_ON_AGCSTS_HIGH,devpriv->i_IobaseAddon+0); outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH ,devpriv->i_IobaseAddon+2); // 0x1000 is out putted in windows driver var=devpriv->ul_DmaBufferHw[next_dma_buf]; low_word=var & 0xffff; var=devpriv->ul_DmaBufferHw[next_dma_buf]; high_word=var /65536; /* DMA Start Adress Low */ outw(APCI3120_ADD_ON_MWAR_LOW,devpriv->i_IobaseAddon+0); outw(low_word,devpriv->i_IobaseAddon+2); /* DMA Start Adress High */ outw(APCI3120_ADD_ON_MWAR_HIGH,devpriv->i_IobaseAddon+0); outw(high_word,devpriv->i_IobaseAddon+2); var=devpriv->ui_DmaBufferUsesize[next_dma_buf]; low_word=var & 0xffff; var=devpriv->ui_DmaBufferUsesize[next_dma_buf]; high_word=var /65536; /* Nbr of acquisition LOW */ outw(APCI3120_ADD_ON_MWTC_LOW,devpriv->i_IobaseAddon+0); outw(low_word,devpriv->i_IobaseAddon+2); /* Nbr of acquisition HIGH */ outw(APCI3120_ADD_ON_MWTC_HIGH,devpriv->i_IobaseAddon+0); outw(high_word,devpriv->i_IobaseAddon+2); // To configure A2P FIFO // ENABLE A2P FIFO WRITE AND ENABLE AMWEN // AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03 outw(3,devpriv->i_IobaseAddon + 4); //initialise end of dma interrupt AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI) outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2| APCI3120_ENABLE_WRITE_TC_INT), devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR); }/*UPDATE-0.7.57->0.7.68 ptr=(sampl_t *)devpriv->ul_DmaBufferVirtual[devpriv->ui_DmaActualBuffer]; // if there is not enough space left in the buffer to copy all data contained in the DMABufferVirtual if(s->async->buf_int_ptr+samplesinbuf*sizeof(sampl_t)>=devpriv->ui_AiDataLength) { m=(devpriv->ui_AiDataLength-s->async->buf_int_ptr)/sizeof(sampl_t); v_APCI3120_InterruptDmaMoveBlock16bit(dev,s,(void *)ptr,((void *)(devpriv->AiData))+s->async->buf_int_ptr,m); s->async->buf_int_count+=m*sizeof(sampl_t); ptr+=m*sizeof(sampl_t); samplesinbuf-=m; s->async->buf_int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -