📄 hwdrv_apci3120.c
字号:
| |+----------------------------------------------------------------------------+*/int i_APCI3120_CyclicAnalogInput(int mode, comedi_device * dev,comedi_subdevice * s){ BYTE b_Tmp; UINT ui_Tmp,ui_DelayTiming=0,ui_TimerValue1=0,dmalen0=0,dmalen1=0,ui_TimerValue2=0,ui_TimerValue0,ui_ConvertTiming; USHORT us_TmpValue; //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver //devpriv->b_AiCyclicAcquisition=APCI3120_ENABLE; //END JK 07.05.04: Comparison between WIN32 and Linux driver /*******************/ /* Resets the FIFO */ /*******************/ inb(dev->iobase + APCI3120_RESET_FIFO); //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver //inw(dev->iobase+APCI3120_RD_STATUS); //END JK 07.05.04: Comparison between WIN32 and Linux driver /***************************/ /* Acquisition initialized */ /***************************/ //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver devpriv->b_AiCyclicAcquisition = APCI3120_ENABLE; //END JK 07.05.04: Comparison between WIN32 and Linux driver // clear software registers devpriv->b_TimerSelectMode=0; devpriv->us_OutputRegister=0; devpriv->b_ModeSelectRegister=0; //devpriv->b_DigitalOutputRegister=0; //COMMENT JK 07.05.04: Followings calls are in i_APCI3120_StartAnalogInputAcquisition /****************************/ /* Clear Timer Write TC INT */ /****************************/ outl(APCI3120_CLEAR_WRITE_TC_INT,devpriv->i_IobaseAmcc+ APCI3120_AMCC_OP_REG_INTCSR); /************************************/ /* Clears the timer status register */ /************************************/ //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver //inw(dev->iobase+APCI3120_TIMER_STATUS_REGISTER); inb(dev->iobase+APCI3120_TIMER_STATUS_REGISTER); //END JK 07.05.04: Comparison between WIN32 and Linux driver /**************************/ /* Disables All Timer */ /* Sets PR and PA to 0 */ /**************************/ devpriv->us_OutputRegister = devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER0 & APCI3120_DISABLE_TIMER1 & APCI3120_CLEAR_PA_PR; outw(devpriv->us_OutputRegister,dev->iobase + APCI3120_WR_ADDRESS); /*******************/ /* Resets the FIFO */ /*******************/ //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver inb (devpriv->iobase + APCI3120_RESET_FIFO); //END JK 07.05.04: Comparison between WIN32 and Linux driver devpriv->ui_AiActualScan=0; devpriv->ui_AiActualScanPosition=0; s->async->cur_chan=0; devpriv->ui_AiBufferPtr=0; devpriv->ui_DmaActualBuffer=0; // value for timer2 minus -2 has to be done .....dunno y?? ui_TimerValue2 = devpriv->ui_AiNbrofScans-2; ui_ConvertTiming=devpriv->ui_AiTimer0; if (mode==2) ui_DelayTiming = devpriv->ui_AiTimer1; /**********************************/ /* Initializes the sequence array */ /**********************************/ if (!i_APCI3120_SetupChannelList(dev, s, devpriv->ui_AiNbrofChannels, devpriv->pui_AiChannelList, 0)) return -EINVAL; us_TmpValue=(USHORT) inw(dev->iobase+APCI3120_RD_STATUS); /*** EL241003 : add this section in comment because floats must not be used if((us_TmpValue & 0x00B0)==0x00B0) { f_ConvertValue=(((float)ui_ConvertTiming * 0.002) - 2); ui_TimerValue0=(UINT)f_ConvertValue; if (mode==2) { f_DelayValue = (((float)ui_DelayTiming * 0.00002) - 2); ui_TimerValue1 = (UINT) f_DelayValue; } } else { f_ConvertValue=(((float)ui_ConvertTiming * 0.0012926) - 1); ui_TimerValue0=(UINT)f_ConvertValue; if (mode == 2) { f_DelayValue = (((float)ui_DelayTiming * 0.000012926) - 1); ui_TimerValue1 = (UINT) f_DelayValue; } }***********************************************************************************************//*** EL241003 Begin : add this section to replace floats calculation by integer calculations **/ //EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001 if((us_TmpValue & 0x00B0)==0x00B0 || !strcmp(this_board->pc_DriverName,"apci3001") ) { ui_TimerValue0 = ui_ConvertTiming * 2 - 2000; ui_TimerValue0 = ui_TimerValue0 / 1000; if (mode==2) { ui_DelayTiming = ui_DelayTiming / 1000; ui_TimerValue1 = ui_DelayTiming * 2 - 200; ui_TimerValue1 = ui_TimerValue1 / 100; } } else { ui_ConvertTiming = ui_ConvertTiming / 1000; ui_TimerValue0 = ui_ConvertTiming * 12926 - 10000; ui_TimerValue0 = ui_TimerValue0 / 10000; if (mode == 2) { ui_DelayTiming = ui_DelayTiming / 1000; ui_TimerValue1 = ui_DelayTiming * 12926 -1; ui_TimerValue1 = ui_TimerValue1 / 1000000; } }/*** EL241003 End ******************************************************************************/ if(devpriv->b_ExttrigEnable==APCI3120_ENABLE) { i_APCI3120_ExttrigEnable(dev); // activate EXT trigger } switch(mode) { case 1: // init timer0 in mode 2 devpriv->b_TimerSelectMode=(devpriv->b_TimerSelectMode& 0xFC) | APCI3120_TIMER_0_MODE_2; outb(devpriv->b_TimerSelectMode,dev->iobase+APCI3120_TIMER_CRT1); //Select Timer 0 b_Tmp=((devpriv->b_DigitalOutputRegister) & 0xF0) | APCI3120_SELECT_TIMER_0_WORD; outb(b_Tmp,dev->iobase+APCI3120_TIMER_CRT0); //Set the convertion time outw(((USHORT)ui_TimerValue0),dev->iobase+APCI3120_TIMER_VALUE); break; case 2: // init timer1 in mode 2 devpriv->b_TimerSelectMode=(devpriv->b_TimerSelectMode& 0xF3) | APCI3120_TIMER_1_MODE_2; outb(devpriv->b_TimerSelectMode,dev->iobase+APCI3120_TIMER_CRT1); //Select Timer 1 b_Tmp=((devpriv->b_DigitalOutputRegister) & 0xF0) | APCI3120_SELECT_TIMER_1_WORD; outb(b_Tmp,dev->iobase+APCI3120_TIMER_CRT0); //Set the convertion time outw(((USHORT)ui_TimerValue1),dev->iobase+APCI3120_TIMER_VALUE); // init timer0 in mode 2 devpriv->b_TimerSelectMode=(devpriv->b_TimerSelectMode& 0xFC) | APCI3120_TIMER_0_MODE_2; outb(devpriv->b_TimerSelectMode,dev->iobase+APCI3120_TIMER_CRT1); //Select Timer 0 b_Tmp=((devpriv->b_DigitalOutputRegister) & 0xF0) | APCI3120_SELECT_TIMER_0_WORD; outb(b_Tmp,dev->iobase+APCI3120_TIMER_CRT0); //Set the convertion time outw(((USHORT)ui_TimerValue0),dev->iobase+APCI3120_TIMER_VALUE); break; } // ##########common for all modes################# /***********************/ /* Clears the SCAN bit */ /***********************/ //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver //devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister | APCI3120_DISABLE_SCAN; devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister & APCI3120_DISABLE_SCAN; //END JK 07.05.04: Comparison between WIN32 and Linux driver outb(devpriv->b_ModeSelectRegister,dev->iobase+APCI3120_WRITE_MODE_SELECT); // If DMA is disabled if(devpriv->us_UseDma==APCI3120_DISABLE) { // disable EOC and enable EOS devpriv->b_InterruptMode=APCI3120_EOS_MODE; devpriv->b_EocEosInterrupt=APCI3120_ENABLE; devpriv->b_ModeSelectRegister = (devpriv->b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT) | APCI3120_ENABLE_EOS_INT; outb(devpriv->b_ModeSelectRegister,dev->iobase+APCI3120_WRITE_MODE_SELECT); if (!devpriv->b_AiContinuous) { // configure Timer2 For counting EOS //Reset gate 2 of Timer 2 to disable it (Set Bit D14 to 0) devpriv->us_OutputRegister=devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER2 ; outw(devpriv->us_OutputRegister,dev->iobase+APCI3120_WR_ADDRESS); // DISABLE TIMER INTERRUPT devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT & 0xEF; outb(devpriv->b_ModeSelectRegister,dev->iobase + APCI3120_WRITE_MODE_SELECT); //(1) Init timer 2 in mode 0 and write timer value devpriv->b_TimerSelectMode=(devpriv->b_TimerSelectMode & 0x0F) | APCI3120_TIMER_2_MODE_0; outb(devpriv->b_TimerSelectMode,dev->iobase+APCI3120_TIMER_CRT1); //Writing LOW WORD b_Tmp=((devpriv->b_DigitalOutputRegister) & 0xF0) | APCI3120_SELECT_TIMER_2_LOW_WORD; outb(b_Tmp,dev->iobase+APCI3120_TIMER_CRT0); outw(LOWORD(ui_TimerValue2),dev->iobase+APCI3120_TIMER_VALUE); //Writing HIGH WORD b_Tmp=((devpriv->b_DigitalOutputRegister) & 0xF0) | APCI3120_SELECT_TIMER_2_HIGH_WORD; outb(b_Tmp,dev->iobase+APCI3120_TIMER_CRT0); outw(HIWORD(ui_TimerValue2),dev->iobase+APCI3120_TIMER_VALUE); //(2) Reset FC_TIMER BIT Clearing timer status register inb(dev->iobase+APCI3120_TIMER_STATUS_REGISTER); // enable timer counter and disable watch dog devpriv->b_ModeSelectRegister=(devpriv->b_ModeSelectRegister| APCI3120_ENABLE_TIMER_COUNTER) & APCI3120_DISABLE_WATCHDOG; // select EOS clock input for timer 2 devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister| APCI3120_TIMER2_SELECT_EOS; // Enable timer2 interrupt devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister| APCI3120_ENABLE_TIMER_INT; outb(devpriv->b_ModeSelectRegister,dev->iobase+APCI3120_WRITE_MODE_SELECT); devpriv->b_Timer2Mode=APCI3120_COUNTER; devpriv->b_Timer2Interrupt=APCI3120_ENABLE; } } else { // If DMA Enabled //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver //inw(dev->iobase+0);// reset EOC bit //END JK 07.05.04: Comparison between WIN32 and Linux driver devpriv->b_InterruptMode=APCI3120_DMA_MODE; /************************************/ /* Disables the EOC, EOS interrupt */ /************************************/ devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT & APCI3120_DISABLE_EOS_INT; outb(devpriv->b_ModeSelectRegister,dev->iobase+APCI3120_WRITE_MODE_SELECT); dmalen0=devpriv->ui_DmaBufferSize[0]; dmalen1=devpriv->ui_DmaBufferSize[1]; if (!devpriv->b_AiContinuous) { if (dmalen0>(devpriv->ui_AiNbrofScans*devpriv->ui_AiScanLength*2)) { // must we fill full first buffer? dmalen0=devpriv->ui_AiNbrofScans*devpriv->ui_AiScanLength*2; } else if (dmalen1>(devpriv->ui_AiNbrofScans*devpriv->ui_AiScanLength*2-dmalen0)) // and must we fill full second buffer when first is once filled? dmalen1=devpriv->ui_AiNbrofScans*devpriv->ui_AiScanLength*2-dmalen0; } if (devpriv->ui_AiFlags & TRIG_WAKE_EOS) { // don't we want wake up every scan? if (dmalen0>(devpriv->ui_AiScanLength*2)) { dmalen0=devpriv->ui_AiScanLength*2; if (devpriv->ui_AiScanLength&1) dmalen0+=2; } if (dmalen1>(devpriv->ui_AiScanLength*2)) { dmalen1=devpriv->ui_AiScanLength*2; if (devpriv->ui_AiScanLength&1) dmalen1-=2; if (dmalen1<4) dmalen1=4; } } else { // isn't output buff smaller that our DMA buff? if (dmalen0>(devpriv->ui_AiDataLength)) { dmalen0=devpriv->ui_AiDataLength; } if (dmalen1>(devpriv->ui_AiDataLength)) { dmalen1=devpriv->ui_AiDataLength; } } devpriv->ui_DmaBufferUsesize[0]=dmalen0; devpriv->ui_DmaBufferUsesize[1]=dmalen1; //Initialize DMA // Set Transfer count enable bit and A2P_fifo reset bit in AGCSTS register //1 ui_Tmp=AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO ; outl(ui_Tmp,devpriv->i_IobaseAmcc+AMCC_OP_REG_AGCSTS); // changed since 16 bit interface for add on /*********************/ /* ENABLE BUS MASTER */ /*********************/ 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); // TO VERIFIED //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver outw(0x1000,devpriv->i_IobaseAddon+2); //END JK 07.05.04: Comparison between WIN32 and Linux driver //2 No change // A2P FIFO MANAGEMENT // A2P fifo reset & transfer control enable /***********************/ /* A2P FIFO MANAGEMENT */ /***********************/ outl(APCI3120_A2P_FIFO_MANAGEMENT,devpriv->i_IobaseAmcc + APCI3120_AMCC_OP_MCSR); //3 //beginning address of dma buf //The 32 bit address of dma buffer is converted into two 16 bit addresses // Can done by using _attach and put into into an array // array used may be for differnet pages // DMA Start Adress Low outw(APCI3120_ADD_ON_MWAR_LOW,devpriv->i_IobaseAddon+0); outw((devpriv->ul_DmaBufferHw[0]& 0xFFFF),devpriv->i_IobaseAddon+2); /*************************/ /* DMA Start Adress High */ /*************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -