📄 pcl818.c
字号:
============================================================================== ANALOG OUTPUT MODE0, 818 cards only one sample per call is supported*/static int pcl818_ao_insn_read(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data){ int n; int chan = CR_CHAN(insn->chanspec); for(n=0;n<insn->n;n++){ data[n] = devpriv->ao_readback[chan]; } return n;}static int pcl818_ao_insn_write(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data){ int n; int chan = CR_CHAN(insn->chanspec); for(n=0;n<insn->n;n++){ devpriv->ao_readback[chan] = data[n]; outb((data[n] & 0x000f) << 4, dev->iobase+ (chan)?PCL718_DA2_LO:PCL818_DA_LO); outb((data[n] & 0x0ff0) >> 4, dev->iobase+ (chan)?PCL718_DA2_HI:PCL818_DA_HI); } return n;}/* ============================================================================== DIGITAL INPUT MODE0, 818 cards only one sample per call is supported*/static int pcl818_di_insn_bits(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data){ if(insn->n!=2)return -EINVAL; data[1] = inb(dev->iobase + PCL818_DI_LO) | (inb(dev->iobase + PCL818_DI_HI) << 8); return 2;}/* ============================================================================== DIGITAL OUTPUT MODE0, 818 cards only one sample per call is supported*/static int pcl818_do_insn_bits(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data){ if(insn->n!=2)return -EINVAL; s->state &= ~data[0]; s->state |= (data[0]&data[1]); outb(s->state & 0xff, dev->iobase + PCL818_DO_LO); outb((s->state >> 8), dev->iobase + PCL818_DO_HI); data[1] = s->state; return 2;}/*============================================================================== analog input interrupt mode 1 & 3, 818 cards one sample per interrupt version */static void interrupt_pcl818_ai_mode13_int(int irq, void *d, struct pt_regs *regs) { comedi_device *dev = d; comedi_subdevice *s = dev->subdevices + 0; int low; int timeout=50; /* wait max 50us */ while (timeout--) { if (inb(dev->iobase + PCL818_STATUS) & 0x10) goto conv_finish; comedi_udelay(1); } outb(0,dev->iobase+PCL818_STATUS); /* clear INT request */ comedi_error(dev,"A/D mode1/3 IRQ without DRDY!"); pcl818_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev, s, s->async->events); return;conv_finish: low=inb(dev->iobase + PCL818_AD_LO); comedi_buf_put( s->async, ((inb(dev->iobase + PCL818_AD_HI) << 4) | (low >> 4)) ); // get one sample outb(0,dev->iobase+PCL818_CLRINT); /* clear INT request */ if ((low & 0xf)!=devpriv->act_chanlist[devpriv->act_chanlist_pos]) { // dropout! rt_printk("comedi: A/D mode1/3 IRQ - channel dropout %x!=%x !\n",(low & 0xf),devpriv->act_chanlist[devpriv->act_chanlist_pos]); pcl818_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev, s, s->async->events); return; } if (s->async->cur_chan == 0) { // rt_printk("E"); devpriv->int13_act_scan--; } if (!devpriv->neverending_ai){ if ( devpriv->int13_act_scan == 0 ) { /* all data sampled */ pcl818_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA; return; } } comedi_event(dev, s, s->async->events);}/*============================================================================== analog input dma mode 1 & 3, 818 cards*/static void interrupt_pcl818_ai_mode13_dma(int irq, void *d, struct pt_regs *regs){ comedi_device *dev = d; comedi_subdevice *s = dev->subdevices + 0; int i,len,bufptr; unsigned long flags; sampl_t *ptr; disable_dma(devpriv->dma); devpriv->next_dma_buf=1-devpriv->next_dma_buf; if ((devpriv->dma_runs_to_end)>-1) { // switch dma bufs set_dma_mode(devpriv->dma, DMA_MODE_READ); flags=claim_dma_lock(); set_dma_addr(devpriv->dma, devpriv->hwdmaptr[devpriv->next_dma_buf]); if (devpriv->dma_runs_to_end) { set_dma_count(devpriv->dma, devpriv->hwdmasize[devpriv->next_dma_buf]); } else { set_dma_count(devpriv->dma, devpriv->last_dma_run); } release_dma_lock(flags); enable_dma(devpriv->dma); } devpriv->dma_runs_to_end--; outb(0,dev->iobase+PCL818_CLRINT); /* clear INT request */ ptr=(sampl_t *)devpriv->dmabuf[1-devpriv->next_dma_buf]; len=devpriv->hwdmasize[0] >> 1; bufptr=0; for (i=0;i<len;i++) { if ((ptr[bufptr] & 0xf)!=devpriv->act_chanlist[devpriv->act_chanlist_pos]) { // dropout! rt_printk("comedi: A/D mode1/3 DMA - channel dropout %d!=%d !\n",(ptr[bufptr] & 0xf),devpriv->act_chanlist[devpriv->act_chanlist_pos]); pcl818_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev, s, s->async->events); return; } comedi_buf_put( s->async, ptr[bufptr++] >> 4 ); // get one sample devpriv->act_chanlist_pos++; if (!devpriv->neverending_ai) if ( devpriv->int13_act_scan == 0 ) { /* all data sampled */ pcl818_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA; comedi_event(dev, s, s->async->events); // printk("done int ai13 dma\n"); return; } } if (len>0) comedi_event(dev, s, s->async->events);}/*============================================================================== analog input dma mode 1 & 3 over RTC, 818 cards*/static void interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d, struct pt_regs *regs){ comedi_device *dev = d; comedi_subdevice *s = dev->subdevices + 0; unsigned long tmp; unsigned int top1,top2,i,bufptr; long ofs_dats; sampl_t *dmabuf=(sampl_t *)devpriv->dmabuf[0]; //outb(2,0x378); switch(devpriv->int818_mode) { case INT_TYPE_AI1_DMA_RTC: case INT_TYPE_AI3_DMA_RTC: tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); mod_timer(&devpriv->rtc_irq_timer, jiffies + HZ/devpriv->rtc_freq + 2*HZ/100); for (i=0; i<10; i++) { top1=get_dma_residue(devpriv->dma); top2=get_dma_residue(devpriv->dma); if (top1==top2) break; } if (top1!=top2) return; top1=devpriv->hwdmasize[0]-top1; // where is now DMA in buffer top1>>=1; ofs_dats=top1-devpriv->last_top_dma; // new samples from last call if (ofs_dats<0) ofs_dats=(devpriv->dmasamplsize)+ofs_dats; if (!ofs_dats) return; // exit=no new samples from last call // obsluz data i=devpriv->last_top_dma-1; i&=(devpriv->dmasamplsize-1); if (dmabuf[i]!=MAGIC_DMA_WORD) { // DMA overflow! comedi_error(dev,"A/D mode1/3 DMA buffer overflow!"); //rt_printk("I %d dmabuf[i] %d %d\n",i,dmabuf[i],devpriv->dmasamplsize); pcl818_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev, s, s->async->events); return; } //rt_printk("r %ld ",ofs_dats); bufptr=devpriv->last_top_dma; for (i=0; i<ofs_dats; i++) { if ((dmabuf[bufptr] & 0xf)!=devpriv->act_chanlist[devpriv->act_chanlist_pos]) { // dropout! rt_printk("comedi: A/D mode1/3 DMA - channel dropout %d!=%d !\n",(dmabuf[bufptr] & 0xf),devpriv->act_chanlist[devpriv->act_chanlist_pos]); pcl818_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev, s, s->async->events); return; } comedi_buf_put( s->async, dmabuf[bufptr++] >> 4); // get one sample bufptr&=(devpriv->dmasamplsize-1); if(s->async->cur_chan == 0){ devpriv->int13_act_scan--; } if (!devpriv->neverending_ai) if ( devpriv->int13_act_scan == 0 ) { /* all data sampled */ pcl818_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA; comedi_event(dev, s, s->async->events); //printk("done int ai13 dma\n"); return; } } devpriv->last_top_dma=bufptr; bufptr--; bufptr&=(devpriv->dmasamplsize-1); dmabuf[bufptr]=MAGIC_DMA_WORD; comedi_event(dev, s, s->async->events); //outb(0,0x378); return; } //outb(0,0x378);}/*============================================================================== analog input interrupt mode 1 & 3, 818HD/HG cards*/static void interrupt_pcl818_ai_mode13_fifo(int irq, void *d, struct pt_regs *regs){ comedi_device *dev = d; comedi_subdevice *s = dev->subdevices + 0; int i,len,lo; outb(0, dev->iobase + PCL818_FI_INTCLR); // clear fifo int request lo=inb(dev->iobase + PCL818_FI_STATUS); if (lo&4) { comedi_error(dev,"A/D mode1/3 FIFO overflow!"); pcl818_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev, s, s->async->events); return; } if (lo&1) { comedi_error(dev,"A/D mode1/3 FIFO interrupt without data!"); pcl818_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev, s, s->async->events); return; } if (lo&2) { len=512; } else { len=0; } for (i=0;i<len;i++) { lo=inb(dev->iobase + PCL818_FI_DATALO); if ((lo & 0xf)!=devpriv->act_chanlist[devpriv->act_chanlist_pos]) { // dropout! rt_printk("comedi: A/D mode1/3 FIFO - channel dropout %d!=%d !\n",(lo & 0xf),devpriv->act_chanlist[devpriv->act_chanlist_pos]); pcl818_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev, s, s->async->events); return; } comedi_buf_put( s->async, (lo >> 4)|(inb(dev->iobase + PCL818_FI_DATAHI) << 4) ); // get one sample if(s->async->cur_chan == 0){ devpriv->int13_act_scan--; } if (!devpriv->neverending_ai) if ( devpriv->int13_act_scan == 0 ) { /* all data sampled */ pcl818_ai_cancel(dev,s); s->async->events |= COMEDI_CB_EOA; comedi_event(dev, s, s->async->events); return; } } if (len>0) comedi_event(dev, s, s->async->events);}/*============================================================================== INT procedure*/static void interrupt_pcl818(int irq, void *d, struct pt_regs *regs){ comedi_device *dev = d; if(!dev->attached) { comedi_error(dev, "premature interrupt"); return; } //rt_printk("I\n"); switch (devpriv->int818_mode) { case INT_TYPE_AI1_DMA: case INT_TYPE_AI3_DMA: interrupt_pcl818_ai_mode13_dma(irq, d, regs); return; case INT_TYPE_AI1_INT: case INT_TYPE_AI3_INT: interrupt_pcl818_ai_mode13_int(irq, d, regs); return; case INT_TYPE_AI1_FIFO: case INT_TYPE_AI3_FIFO: interrupt_pcl818_ai_mode13_fifo(irq, d, regs); return;#ifdef PCL818_MODE13_AO case INT_TYPE_AO1_INT: case INT_TYPE_AO3_INT: interrupt_pcl818_ao_mode13_int(irq, d, regs); return;#endif } outb(0,dev->iobase+PCL818_CLRINT); /* clear INT request */ if ((!dev->irq)|(!devpriv->irq_free)|(!devpriv->irq_blocked)|(!devpriv->int818_mode)) { if (devpriv->irq_was_now_closed) { devpriv->irq_was_now_closed=0; // comedi_error(dev,"last IRQ.."); return; } comedi_error(dev,"bad IRQ!"); return; } comedi_error(dev,"IRQ from unknow source!");}/*============================================================================== ANALOG INPUT MODE 1 or 3 DMA , 818 cards*/#ifdef unusedstatic void pcl818_ai_mode13dma_int(int mode, comedi_device * dev, comedi_subdevice * s, comedi_trig * it) { unsigned int flags; unsigned int bytes; bytes=devpriv->hwdmasize[0]; if (!devpriv->neverending_ai) { bytes=it->n_chan*it->n*sizeof(sampl_t); // how many devpriv->dma_runs_to_end=bytes / devpriv->hwdmasize[0]; // how many DMA pages we must fiil devpriv->last_dma_run=bytes % devpriv->hwdmasize[0]; //on last dma transfer must be moved devpriv->dma_runs_to_end--; if (devpriv->dma_runs_to_end>=0) bytes=devpriv->hwdmasize[0]; //rt_printk("%d %d %d\n",devpriv->dma_runs_to_end,devpriv->last_dma_run,bytes); } devpriv->next_dma_buf=0; set_dma_mode(devpriv->dma, DMA_MODE_READ); flags=claim_dma_lock(); clear_dma_ff(devpriv->dma); set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]); set_dma_count(devpriv->dma, bytes); release_dma_lock(flags); enable_dma(devpriv->dma);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -