📄 adl_pci9118.c
字号:
} if (!cmd->chanlist_len) { cmd->chanlist_len=1; err++; } if (cmd->chanlist_len>this_board->n_aichanlist) { cmd->chanlist_len=this_board->n_aichanlist; err++; } if (cmd->scan_end_arg<cmd->chanlist_len) { cmd->scan_end_arg=cmd->chanlist_len; err++; } if ((cmd->scan_end_arg % cmd->chanlist_len)) { cmd->scan_end_arg=cmd->chanlist_len*(cmd->scan_end_arg/cmd->chanlist_len); err++; } if(err) return 3; /* step 4: fix up any arguments */ if (cmd->scan_begin_src==TRIG_TIMER) { tmp=cmd->scan_begin_arg;// rt_printk("S1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); i8253_cascade_ns_to_timer(devpriv->i8254_osc_base,&divisor1,&divisor2,&cmd->scan_begin_arg,cmd->flags&TRIG_ROUND_MASK);// rt_printk("S2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); if(cmd->scan_begin_arg<this_board->ai_ns_min) cmd->scan_begin_arg=this_board->ai_ns_min; if(tmp!=cmd->scan_begin_arg)err++; } if (cmd->convert_src&(TRIG_TIMER|TRIG_NOW)) { tmp=cmd->convert_arg; i8253_cascade_ns_to_timer(devpriv->i8254_osc_base,&divisor1,&divisor2,&cmd->convert_arg,cmd->flags&TRIG_ROUND_MASK);// rt_printk("s1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); if (cmd->convert_arg<this_board->ai_ns_min) cmd->convert_arg=this_board->ai_ns_min; if (tmp!=cmd->convert_arg) err++; if (cmd->scan_begin_src==TRIG_TIMER && cmd->convert_src==TRIG_NOW) { if (cmd->convert_arg==0) { if (cmd->scan_begin_arg<this_board->ai_ns_min*(cmd->scan_end_arg+2)) { cmd->scan_begin_arg=this_board->ai_ns_min*(cmd->scan_end_arg+2);// rt_printk("s2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); err++; } } else { if (cmd->scan_begin_arg<cmd->convert_arg*cmd->chanlist_len) { cmd->scan_begin_arg=cmd->convert_arg*cmd->chanlist_len;// rt_printk("s3 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); err++; } } } } if (err) return 4; if (cmd->chanlist) if (!check_channel_list(dev, s, cmd->chanlist_len, cmd->chanlist,0,0)) return 5; // incorrect channels list return 0;}/*==============================================================================*/static int Compute_and_setup_dma(comedi_device *dev){ unsigned int dmalen0,dmalen1,i; DPRINTK("adl_pci9118 EDBG: BGN: Compute_and_setup_dma()\n"); dmalen0=devpriv->dmabuf_size[0]; dmalen1=devpriv->dmabuf_size[1]; DPRINTK("1 dmalen0=%d dmalen1=%d ai_data_len=%d\n", dmalen0, dmalen1, devpriv->ai_data_len); // isn't output buff smaller that our DMA buff? if (dmalen0>(devpriv->ai_data_len)) { dmalen0=devpriv->ai_data_len&~3L; // allign to 32bit down } if (dmalen1>(devpriv->ai_data_len)) { dmalen1=devpriv->ai_data_len&~3L; // allign to 32bit down } DPRINTK("2 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1); // we want wake up every scan? if (devpriv->ai_flags & TRIG_WAKE_EOS) { if (dmalen0<(devpriv->ai_n_realscanlen<<1)) { // uff, too short DMA buffer, disable EOS support! devpriv->ai_flags&=(~TRIG_WAKE_EOS); rt_printk("comedi%d: WAR: DMA0 buf too short, cann't support TRIG_WAKE_EOS (%d<%d)\n",dev->minor,dmalen0,devpriv->ai_n_realscanlen<<1); } else { // short first DMA buffer to one scan dmalen0=devpriv->ai_n_realscanlen<<1; DPRINTK("21 dmalen0=%d ai_n_realscanlen=%d useeoshandle=%d\n", dmalen0, devpriv->ai_n_realscanlen,devpriv->useeoshandle); if (devpriv->useeoshandle) dmalen0+=2; if (dmalen0<4) { rt_printk("comedi%d: ERR: DMA0 buf len bug? (%d<4)\n",dev->minor,dmalen0); dmalen0=4; } } } if (devpriv->ai_flags & TRIG_WAKE_EOS) { if (dmalen1<(devpriv->ai_n_realscanlen<<1)) { // uff, too short DMA buffer, disable EOS support! devpriv->ai_flags&=(~TRIG_WAKE_EOS); rt_printk("comedi%d: WAR: DMA1 buf too short, cann't support TRIG_WAKE_EOS (%d<%d)\n",dev->minor,dmalen1,devpriv->ai_n_realscanlen<<1); } else { // short second DMA buffer to one scan dmalen1=devpriv->ai_n_realscanlen<<1; DPRINTK("22 dmalen1=%d ai_n_realscanlen=%d useeoshandle=%d\n", dmalen1, devpriv->ai_n_realscanlen,devpriv->useeoshandle); if (devpriv->useeoshandle) dmalen1-=2; if (dmalen1<4) { rt_printk("comedi%d: ERR: DMA1 buf len bug? (%d<4)\n",dev->minor,dmalen1); dmalen1=4; } } } DPRINTK("3 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1); // transfer without TRIG_WAKE_EOS if (!(devpriv->ai_flags&TRIG_WAKE_EOS)) { // if it's possible then allign DMA buffers to length of scan i=dmalen0; dmalen0=(dmalen0/(devpriv->ai_n_realscanlen<<1))*(devpriv->ai_n_realscanlen<<1); dmalen0&=~3L; if (!dmalen0) dmalen0=i; // uff. very long scan? i=dmalen1; dmalen1=(dmalen1/(devpriv->ai_n_realscanlen<<1))*(devpriv->ai_n_realscanlen<<1); dmalen1&=~3L; if (!dmalen1) dmalen1=i; // uff. very long scan? // if measure isn't neverending then test, if it whole fits into one or two DMA buffers if (!devpriv->ai_neverending) { // fits whole measure into one DMA buffer? if (dmalen0>((devpriv->ai_n_realscanlen<<1)*devpriv->ai_scans)) { DPRINTK("3.0 ai_n_realscanlen=%d ai_scans=%d \n", devpriv->ai_n_realscanlen, devpriv->ai_scans); dmalen0=(devpriv->ai_n_realscanlen<<1)*devpriv->ai_scans; DPRINTK("3.1 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1); dmalen0&=~3L; } else { // fits whole measure into two DMA buffer? if (dmalen1>((devpriv->ai_n_realscanlen<<1)*devpriv->ai_scans-dmalen0)) dmalen1=(devpriv->ai_n_realscanlen<<1)*devpriv->ai_scans-dmalen0; DPRINTK("3.2 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1); dmalen1&=~3L; } } } DPRINTK("4 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1); // these DMA buffer size we'll be used devpriv->dma_actbuf=0; devpriv->dmabuf_use_size[0]=dmalen0; devpriv->dmabuf_use_size[1]=dmalen1; DPRINTK("5 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1);#if 0 if (devpriv->ai_n_scanlen<this_board->half_fifo_size) { devpriv->dmabuf_panic_size[0]=(this_board->half_fifo_size/devpriv->ai_n_scanlen+1)*devpriv->ai_n_scanlen*sizeof(sampl_t); devpriv->dmabuf_panic_size[1]=(this_board->half_fifo_size/devpriv->ai_n_scanlen+1)*devpriv->ai_n_scanlen*sizeof(sampl_t); } else { devpriv->dmabuf_panic_size[0]=(devpriv->ai_n_scanlen<<1)%devpriv->dmabuf_size[0]; devpriv->dmabuf_panic_size[1]=(devpriv->ai_n_scanlen<<1)%devpriv->dmabuf_size[1]; }#endif outl(inl(devpriv->iobase_a+AMCC_OP_REG_MCSR)&(~EN_A2P_TRANSFERS), devpriv->iobase_a+AMCC_OP_REG_MCSR); // stop DMA 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); // init DMA transfer outl(0x00000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR);// outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); outl(inl(devpriv->iobase_a+AMCC_OP_REG_MCSR)|RESET_A2P_FLAGS|A2P_HI_PRIORITY|EN_A2P_TRANSFERS, devpriv->iobase_a+AMCC_OP_REG_MCSR); outl(inl(devpriv->iobase_a+AMCC_OP_REG_INTCSR)|EN_A2P_TRANSFERS, devpriv->iobase_a+AMCC_OP_REG_INTCSR); // allow bus mastering DPRINTK("adl_pci9118 EDBG: END: Compute_and_setup_dma()\n"); return 0;}/* ==============================================================================*/static int pci9118_ai_docmd_sampl(comedi_device * dev, comedi_subdevice * s) { DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_sampl(%d,) [%d]\n",dev->minor,devpriv->ai_do); switch (devpriv->ai_do) { case 1: devpriv->AdControlReg|=AdControl_TmrTr; break; case 2: comedi_error(dev,"pci9118_ai_docmd_sampl() mode 2 bug!\n"); return -EIO; case 3: devpriv->AdControlReg|=AdControl_ExtM; break; case 4: comedi_error(dev,"pci9118_ai_docmd_sampl() mode 4 bug!\n"); return -EIO; default: comedi_error(dev,"pci9118_ai_docmd_sampl() mode number bug!\n"); return -EIO; }; devpriv->int_ai_func=interrupt_pci9118_ai_onesample; //transfer function if (devpriv->ai12_startstop) pci9118_exttrg_add(dev,EXTTRG_AI); // activate EXT trigger if ((devpriv->ai_do==1)||(devpriv->ai_do==2)) devpriv->IntControlReg|=Int_Timer; devpriv->AdControlReg|=AdControl_Int; outl(inl(devpriv->iobase_a+AMCC_OP_REG_INTCSR)|0x1f00, devpriv->iobase_a+AMCC_OP_REG_INTCSR); // allow INT in AMCC if (!(devpriv->ai12_startstop&(START_AI_EXT|START_AI_INT))) { 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->IntControlReg,dev->iobase+PCI9118_INTCTRL); } DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_docmd_sampl()\n"); return 0;}/* ==============================================================================*/static int pci9118_ai_docmd_dma(comedi_device * dev, comedi_subdevice * s) { DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma(%d,) [%d,%d]\n",dev->minor,devpriv->ai_do,devpriv->usedma); Compute_and_setup_dma(dev); switch (devpriv->ai_do) { case 1: devpriv->AdControlReg|=((AdControl_TmrTr|AdControl_Dma) & 0xff); break; case 2: devpriv->AdControlReg|=((AdControl_TmrTr|AdControl_Dma) & 0xff); devpriv->AdFunctionReg=AdFunction_PDTrg|AdFunction_PETrg|AdFunction_BM|AdFunction_BS; if (devpriv->usessh&&(!devpriv->softsshdelay)) devpriv->AdFunctionReg|=AdFunction_BSSH; outl(devpriv->ai_n_realscanlen, dev->iobase+PCI9118_BURST); break; case 3: devpriv->AdControlReg|=((AdControl_ExtM|AdControl_Dma) & 0xff); devpriv->AdFunctionReg=AdFunction_PDTrg|AdFunction_PETrg; break; case 4: devpriv->AdControlReg|=((AdControl_TmrTr|AdControl_Dma) & 0xff); devpriv->AdFunctionReg=AdFunction_PDTrg|AdFunction_PETrg|AdFunction_AM; outl(devpriv->AdFunctionReg,dev->iobase+PCI9118_ADFUNC); outl(0x30, dev->iobase + PCI9118_CNTCTRL); outl((devpriv->dmabuf_hw[0]>>1)&0xff, dev->iobase + PCI9118_CNT0); outl((devpriv->dmabuf_hw[0]>>9)&0xff, dev->iobase + PCI9118_CNT0); devpriv->AdFunctionReg|=AdFunction_Start; break; default: comedi_error(dev,"pci9118_ai_docmd_dma() mode number bug!\n"); return -EIO; }; if (devpriv->ai12_startstop) { pci9118_exttrg_add(dev,EXTTRG_AI); // activate EXT trigger } devpriv->int_ai_func=interrupt_pci9118_ai_dma; //transfer function switch (devpriv->usedma) { case 2: // 32 bit DMA mode if (devpriv->ai16bits) { // select interrupt function devpriv->dma_ai_read_block=move_block_from_dma_16bit_32b; } else { devpriv->dma_ai_read_block=move_block_from_dma_12bit_32b; } outl(0x00000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); break; case 1: // 16 bit DMA mode if (devpriv->ai16bits) { // select interrupt function devpriv->dma_ai_read_block=move_block_from_dma_16bit_16b; } else { devpriv->dma_ai_read_block=move_block_from_dma_12bit_16b; } outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); break; default: comedi_error(dev,"pci9118_ai_docmd_dma() usedma!={1,2}\n"); return -EIO; } if (!(devpriv->ai12_startstop&(START_AI_EXT|START_AI_INT))) { outl(devpriv->AdFunctionReg,dev->iobase+PCI9118_ADFUNC); outl(devpriv->IntControlReg,dev->iobase+PCI9118_INTCTRL); 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); } DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma()\n"); return 0;}/*==============================================================================*/static int pci9118_ai_cmd(comedi_device *dev,comedi_subdevice *s){ comedi_cmd *cmd=&s->async->cmd; unsigned int addchans=0; int ret=0; DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_cmd(%d,)\n",dev->minor); devpriv->ai12_startstop=0; devpriv->ai_flags=cmd->flags; devpriv->ai_n_chan=cmd->chanlist_len; devpriv->ai_n_scanlen=cmd->scan_end_arg; devpriv->ai_chanlist=cmd->chanlist; devpriv->ai_data=s->async->prealloc_buf; devpriv->ai_data_len=s->async->prealloc_bufsz; devpriv->ai_timer1=0; devpriv->ai_timer2=0; devpriv->ai_add_front=0; devpriv->ai_add_back=0; devpriv->ai_maskerr=0x10e; // prepare for start/stop conditions if (cmd->start_src==TRIG_EXT) devpriv->ai12_startstop|=START_AI_EXT; if (cmd->stop_src==TRIG_EXT) { devpriv->ai_neverending=1; devpriv->ai12_startstop|=STOP_AI_EXT; } if (cmd->start_src==TRIG_INT) { devpriv->ai12_startstop|=START_AI_INT; devpriv->ai_inttrig_start=cmd->start_arg; s->async->inttrig=pci9118_ai_inttrig; }#if 0 if (cmd->stop_src==TRIG_INT) { devpriv->ai_neverending=1; devpriv->ai12_startstop|=STOP_AI_INT; }#endif if (cmd->stop_src==TRIG_NONE) devpriv->ai_neverending=1; if (cmd->stop_src==TRIG_COUNT) { devpriv->ai_scans=cmd->stop_arg; devpriv->ai_neverending=0; } else { devpriv->ai_scans=0; } // use sample&hold signal? if (cmd->convert_src==TRIG_NOW) { devpriv->usessh=1; } // yes else { devpriv->usessh=0; } // no DPRINTK("1 neverending=%d scans=%u usessh=%d ai_startstop=0x%2x\n", devpriv->ai_neverending, devpriv->ai_scans, devpriv->usessh, devpriv->ai12_startstop); // use additional sample at end of every scan to satisty DMA 32 bit transfer? devpriv->ai_add_front=0; devpriv->ai_add_back=0; devpriv->useeoshandle=0; if (devpriv->master) { devpriv->usedma=2; // assume 32 bit DMA transfer now if ((cmd->flags&TRIG_WAKE_EOS) && (devpriv->ai_n_scanlen==1)) { if (cmd->convert_src==TRIG_NOW) { devpriv->usedma=1; // 16 BIT dma MODE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -