📄 pcl818.c
字号:
} outb(0, dev->iobase + PCL818_DA_LO); // DAC=0V outb(0, dev->iobase + PCL818_DA_HI); comedi_udelay(1); outb(0, dev->iobase + PCL818_DO_HI); // DO=$0000 outb(0, dev->iobase + PCL818_DO_LO); comedi_udelay(1); outb(0, dev->iobase + PCL818_CONTROL); outb(0, dev->iobase + PCL818_CNTENABLE); outb(0, dev->iobase + PCL818_MUX); outb(0, dev->iobase + PCL818_CLRINT); outb(0xb0, dev->iobase + PCL818_CTRCTL);/* Stop pacer */ outb(0x70, dev->iobase + PCL818_CTRCTL); outb(0x30, dev->iobase + PCL818_CTRCTL); if(this_board->is_818){ outb(0, dev->iobase + PCL818_RANGE); }else{ outb(0, dev->iobase + PCL718_DA2_LO); outb(0, dev->iobase + PCL718_DA2_HI); }}/* ============================================================================== Enable(1)/disable(0) periodic interrupts from RTC*/static int set_rtc_irq_bit(unsigned char bit){ unsigned char val; unsigned long flags; if (bit==1) { RTC_timer_lock++; if (RTC_timer_lock>1) return 0; } else { RTC_timer_lock--; if (RTC_timer_lock<0) RTC_timer_lock=0; if (RTC_timer_lock>0) return 0; } save_flags(flags); cli(); val = CMOS_READ(RTC_CONTROL); if (bit) { val |= RTC_PIE; } else { val &= ~RTC_PIE; } CMOS_WRITE(val, RTC_CONTROL); CMOS_READ(RTC_INTR_FLAGS); restore_flags(flags); return 0;}/*============================================================================== Restart RTC if something stop it (xntpd every 11 mins or large IDE transfers)*/#ifdef unusedstatic void rtc_dropped_irq(unsigned long data) { comedi_device *dev = (void *)data; unsigned long flags,tmp; switch(devpriv->int818_mode) { case INT_TYPE_AI1_DMA_RTC: case INT_TYPE_AI3_DMA_RTC: mod_timer(&devpriv->rtc_irq_timer, jiffies + HZ/devpriv->rtc_freq + 2*HZ/100); save_flags(flags); cli(); tmp=(CMOS_READ(RTC_INTR_FLAGS) & 0xF0); /* restart */ restore_flags(flags); break; }; }/*============================================================================== Set frequency of interrupts from RTC*/static int rtc_setfreq_irq(int freq) { int tmp = 0; int rtc_freq; unsigned char val; unsigned long flags; if (freq<2) freq=2; if (freq>8192) freq=8192; while (freq>(1<<tmp)) tmp++; rtc_freq = 1<<tmp; save_flags(flags); cli(); val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0; val |= (16 - tmp); CMOS_WRITE(val, RTC_FREQ_SELECT); restore_flags(flags); return rtc_freq;}#endif/* ============================================================================== Free any resources that we have claimed */static void free_resources(comedi_device * dev){ //rt_printk("free_resource()\n"); if(dev->private) { pcl818_ai_cancel(dev, devpriv->sub_ai); pcl818_reset(dev); if (devpriv->dma) free_dma(devpriv->dma); if (devpriv->dmabuf[0]) free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]); if (devpriv->dmabuf[1]) free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]); if (devpriv->rtc_irq) comedi_free_irq(devpriv->rtc_irq, dev); if ((devpriv->dma_rtc)&&(RTC_lock==1)) { if (devpriv->rtc_iobase) release_region(devpriv->rtc_iobase, devpriv->rtc_iosize); } if (devpriv->dma_rtc) RTC_lock--; } if (dev->irq) free_irq(dev->irq, dev); if (dev->iobase) release_region(dev->iobase, devpriv->io_range); //rt_printk("free_resource() end\n");}/* ============================================================================== Initialization */static int pcl818_attach(comedi_device * dev, comedi_devconfig * it){ int ret; int iobase; int irq,dma; unsigned long pages; comedi_subdevice *s; if((ret=alloc_private(dev,sizeof(pcl818_private)))<0) return ret; /* Can't alloc mem */ /* claim our I/O space */ iobase = it->options[0]; printk("comedi%d: pcl818: board=%s, ioport=0x%03x", dev->minor, this_board->name, iobase); devpriv->io_range=this_board->io_range; if ((this_board->fifo)&&(it->options[2]==-1)) { // we've board with FIFO and we want to use FIFO devpriv->io_range=PCLx1xFIFO_RANGE; devpriv->usefifo = 1; } if (check_region(iobase, this_board->io_range) < 0) { rt_printk("I/O port conflict\n"); return -EIO; } request_region(iobase, devpriv->io_range, "pcl818"); dev->iobase=iobase; if (pcl818_check(iobase)) { rt_printk(", I can't detect board. FAIL!\n"); return -EIO; } /* set up some name stuff */ dev->board_name = this_board->name; /* grab our IRQ */ irq=0; if (this_board->IRQbits!=0) { /* board support IRQ */ irq=it->options[1]; if (irq>0) {/* we want to use IRQ */ if (((1<<irq)&this_board->IRQbits)==0) { rt_printk(", IRQ %d is out of allowed range, DISABLING IT",irq); irq=0; /* Bad IRQ */ } else { if (comedi_request_irq(irq, interrupt_pcl818, 0, "pcl818", dev)) { rt_printk(", unable to allocate IRQ %d, DISABLING IT", irq); irq=0; /* Can't use IRQ */ } else { rt_printk(", irq=%d", irq); } } } } dev->irq = irq; if (irq) { devpriv->irq_free=1; } /* 1=we have allocated irq */ else { devpriv->irq_free=0; } devpriv->irq_blocked=0; /* number of subdevice which use IRQ */ devpriv->int818_mode=0; /* mode of irq */ /* grab RTC for DMA operations */ devpriv->dma_rtc=0; if (it->options[2]>0) { // we want to use DMA if (RTC_lock==0) { if (check_region(RTC_PORT(0), RTC_IO_EXTENT) < 0) goto no_rtc; request_region(RTC_PORT(0), RTC_IO_EXTENT, "pcl818 (RTC)"); } devpriv->rtc_iobase=RTC_PORT(0); devpriv->rtc_iosize=RTC_IO_EXTENT; RTC_lock++; if (!comedi_request_irq(RTC_IRQ, interrupt_pcl818_ai_mode13_dma_rtc, 0, "pcl818 DMA (RTC)", dev)) { devpriv->dma_rtc=1; devpriv->rtc_irq=RTC_IRQ; rt_printk(", dma_irq=%d", devpriv->rtc_irq); } else { RTC_lock--; if (RTC_lock==0) { if (devpriv->rtc_iobase) release_region(devpriv->rtc_iobase, devpriv->rtc_iosize); } devpriv->rtc_iobase=0; devpriv->rtc_iosize=0; } } no_rtc: /* grab our DMA */ dma=0; devpriv->dma=dma; if ((devpriv->irq_free==0)&&(devpriv->dma_rtc==0)) goto no_dma; /* if we haven't IRQ, we can't use DMA */ if (this_board->DMAbits!=0) { /* board support DMA */ dma=it->options[2]; if (dma<1) goto no_dma; /* DMA disabled */ if (((1<<dma)&this_board->DMAbits)==0) { rt_printk(", DMA is out of allowed range, FAIL!\n"); return -EINVAL; /* Bad DMA */ } ret=request_dma(dma, "pcl818"); if (ret) { rt_printk(", unable to allocate DMA %d, FAIL!\n",dma); return -EBUSY; /* DMA isn't free */ } devpriv->dma=dma; rt_printk(", dma=%d", dma); pages=2; /* we need 16KB */ devpriv->dmabuf[0]=__get_dma_pages(GFP_KERNEL, pages); if (!devpriv->dmabuf[0]) { rt_printk(", unable to allocate DMA buffer, FAIL!\n"); /* maybe experiment with try_to_free_pages() will help .... */ return -EBUSY; /* no buffer :-( */ } devpriv->dmapages[0]=pages; devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]); devpriv->hwdmasize[0]=(1<<pages)*PAGE_SIZE; //rt_printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); if (devpriv->dma_rtc==0) { // we must do duble buff :-( devpriv->dmabuf[1]=__get_dma_pages(GFP_KERNEL, pages); if (!devpriv->dmabuf[1]) { rt_printk(", unable to allocate DMA buffer, FAIL!\n"); return -EBUSY; } devpriv->dmapages[1]=pages; devpriv->hwdmaptr[1] = virt_to_bus((void *)devpriv->dmabuf[1]); devpriv->hwdmasize[1]=(1<<pages)*PAGE_SIZE; } }no_dma: if((ret=alloc_subdevices(dev, 4))<0) return ret; s = dev->subdevices + 0; if(!this_board->n_aichan_se){ s->type = COMEDI_SUBD_UNUSED; }else{ dev->read_subdev = s; s->type = COMEDI_SUBD_AI; devpriv->sub_ai=s; s->subdev_flags = SDF_READABLE; if (check_single_ended(dev->iobase)) { s->n_chan = this_board->n_aichan_se; s->subdev_flags|=SDF_COMMON|SDF_GROUND; printk(", %dchans S.E. DAC",s->n_chan); } else { s->n_chan = this_board->n_aichan_diff; s->subdev_flags|=SDF_DIFF; printk(", %dchans DIFF DAC",s->n_chan); } s->maxdata = this_board->ai_maxdata; s->len_chanlist = this_board->ai_chanlist; s->range_table = this_board->ai_range_type; s->cancel=pcl818_ai_cancel; s->insn_read = pcl818_ai_insn_read; //if ((irq)||(devpriv->dma_rtc)) { //s->trig[1] = pcl818_ai_mode1; //s->trig[3] = pcl818_ai_mode3; //} if(this_board->is_818){ if ((it->options[4]==1)||(it->options[4]==10)) s->range_table=&range_pcl818l_h_ai; // secondary range list jumper selectable }else{ switch (it->options[4]) { case 0: s->range_table=&range_bipolar10; break; case 1: s->range_table=&range_bipolar5; break; case 2: s->range_table=&range_bipolar2_5; break; case 3: s->range_table=&range718_bipolar1; break; case 4: s->range_table=&range718_bipolar0_5; break; case 6: s->range_table=&range_unipolar10; break; case 7: s->range_table=&range_unipolar5; break; case 8: s->range_table=&range718_unipolar2; break; case 9: s->range_table=&range718_unipolar1; break; default: s->range_table=&range_unknown; break; } } } s = dev->subdevices + 1; if(!this_board->n_aochan){ s->type = COMEDI_SUBD_UNUSED; }else{ dev->write_subdev = s; s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE|SDF_GROUND; s->n_chan = this_board->n_aochan; s->maxdata = this_board->ao_maxdata; s->len_chanlist = this_board->ao_chanlist; s->range_table = this_board->ao_range_type; s->insn_read = pcl818_ao_insn_read; s->insn_write = pcl818_ao_insn_write;#ifdef unused#ifdef PCL818_MODE13_AO if (irq) { s->trig[1] = pcl818_ao_mode1; s->trig[3] = pcl818_ao_mode3; } #endif#endif if(this_board->is_818){ if ((it->options[4]==1)||(it->options[4]==10)) s->range_table=&range_unipolar10; if (it->options[4]==2) s->range_table=&range_unknown; }else{ if ((it->options[5]==1)||(it->options[5]==10)) s->range_table=&range_unipolar10; if (it->options[5]==2) s->range_table=&range_unknown; } } s = dev->subdevices + 2; if(!this_board->n_dichan){ s->type = COMEDI_SUBD_UNUSED; }else{ s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = this_board->n_dichan; s->maxdata = 1; s->len_chanlist = this_board->n_dichan; s->range_table = &range_digital; s->insn_bits = pcl818_di_insn_bits; } s = dev->subdevices + 3; if(!this_board->n_dochan){ s->type = COMEDI_SUBD_UNUSED; }else{ s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; s->n_chan = this_board->n_dochan; s->maxdata = 1; s->len_chanlist = this_board->n_dochan; s->range_table = &range_digital; s->insn_bits = pcl818_do_insn_bits; } /* select 1/10MHz oscilator */ if ((it->options[3]==0)||(it->options[3]==10)) { devpriv->i8253_osc_base= 100; } else { devpriv->i8253_osc_base=1000; } /* max sampling speed */ devpriv->ns_min=this_board->ns_min; if(!this_board->is_818){ if ((it->options[6]==1)||(it->options[6]==100)) devpriv->ns_min=10000; /* extended PCL718 to 100kHz DAC */ } pcl818_reset(dev); rt_printk("\n"); return 0;}/*============================================================================== Removes device */static int pcl818_detach(comedi_device * dev) { // rt_printk("comedi%d: pcl818: remove\n", dev->minor); free_resources(dev); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -