⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcl818.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
        if (mode==1) { 		devpriv->int818_mode=INT_TYPE_AI1_DMA;		outb(0x87 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);  /* Pacer+IRQ+DMA */         } else { 		devpriv->int818_mode=INT_TYPE_AI3_DMA;		outb(0x86 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);  /* Ext trig+IRQ+DMA */         };}/* ==============================================================================   ANALOG INPUT MODE 1 or 3 DMA rtc, 818 cards*/static void pcl818_ai_mode13dma_rtc(int mode, comedi_device * dev, comedi_subdevice * s, comedi_trig * it) {        unsigned int flags;        sampl_t *pole;         set_dma_mode(devpriv->dma, DMA_MODE_READ|DMA_AUTOINIT);        flags=claim_dma_lock();        clear_dma_ff(devpriv->dma);        set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);        set_dma_count(devpriv->dma, devpriv->hwdmasize[0]);        release_dma_lock(flags);        enable_dma(devpriv->dma);        devpriv->last_top_dma=0; //devpriv->hwdmasize[0];        pole=(sampl_t *)devpriv->dmabuf[0];        devpriv->dmasamplsize=devpriv->hwdmasize[0]/2;        pole[devpriv->dmasamplsize-1]=MAGIC_DMA_WORD;        devpriv->rtc_freq=rtc_setfreq_irq(2048);        devpriv->rtc_irq_timer.expires=jiffies + HZ/devpriv->rtc_freq + 2*HZ/100;        devpriv->rtc_irq_timer.data=(unsigned long)dev;        devpriv->rtc_irq_timer.function=rtc_dropped_irq;            add_timer(&devpriv->rtc_irq_timer);            if (mode==1) { 		devpriv->int818_mode=INT_TYPE_AI1_DMA_RTC;		outb(0x07 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);  /* Pacer+DMA */         } else { 		devpriv->int818_mode=INT_TYPE_AI3_DMA_RTC;		outb(0x06 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);  /* Ext trig+DMA */     };}/* ==============================================================================   ANALOG INPUT MODE 1 or 3, 818 cards*/static int pcl818_ai_mode13(int mode, comedi_device * dev, comedi_subdevice * s, comedi_trig * it) {        int divisor1, divisor2;        if ((!dev->irq)&&(!devpriv->dma_rtc)) {		comedi_error(dev,"IRQ not defined!");		return -EINVAL;        }        if (devpriv->irq_blocked)		return -EBUSY;	start_pacer(dev, -1, 0, 0); // stop pacer        if (!check_and_setup_channel_list(dev, s, it)) return -EINVAL;	comedi_udelay(1);        devpriv->int13_act_scan=it->n;        devpriv->int13_act_chan=0;	devpriv->irq_blocked=1;        devpriv->irq_was_now_closed=0;        devpriv->neverending_ai=0;        devpriv->act_chanlist_pos=0;        devpriv->buf_ptr=0;  	if ((it->n==0)||(it->n==-1)) devpriv->neverending_ai=1; //well, user want neverending          if (mode==1) {		if (it->trigvar<devpriv->ns_min) it->trigvar=devpriv->ns_min;		i8253_cascade_ns_to_timer(devpriv->i8253_osc_base,&divisor1,&divisor2,&it->trigvar,TRIG_ROUND_NEAREST);		if (divisor1==1) {	/* PCL718/818 crash if any divisor is set to 1 */		        divisor1=2;			divisor2/=2;		}		if (divisor2==1) {			divisor2=2;			divisor1/=2;		}	}           outb(0 , dev->iobase + PCL818_CNTENABLE); /* enable pacer */        switch (devpriv->dma>0) {	case 1:		// DMA	case 3:	        if (devpriv->dma_rtc==0) { pcl818_ai_mode13dma_int(mode, dev, s, it); }				else { pcl818_ai_mode13dma_rtc(mode, dev, s, it); }		break;	case 0:		// IRQ		// rt_printk("IRQ\n");		if (mode==1) { 			devpriv->int818_mode=INT_TYPE_AI1_INT;			outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);  /* Pacer+IRQ */		} else {			devpriv->int818_mode=INT_TYPE_AI3_INT;			outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);  /* Ext trig+IRQ */ 		};		break;	case -1:		// FIFO		outb(1, dev->iobase + PCL818_FI_ENABLE);	// enable FIFO		if (mode==1) { 			devpriv->int818_mode=INT_TYPE_AI1_FIFO;			outb(0x03, dev->iobase + PCL818_CONTROL);  /* Pacer */ 		} else { 			devpriv->int818_mode=INT_TYPE_AI3_FIFO;			outb(0x02, dev->iobase + PCL818_CONTROL); 		}; /* Ext trig */ 		break;        }        start_pacer(dev, mode, divisor1, divisor2);    	switch(devpriv->int818_mode) {	case INT_TYPE_AI1_DMA_RTC:	case INT_TYPE_AI3_DMA_RTC:		set_rtc_irq_bit(1); /* start RTC */		break;	}	return 0;}/* ==============================================================================   ANALOG INPUT MODE 1, 818 cards*/static int pcl818_ai_mode1(comedi_device * dev, comedi_subdevice * s, comedi_trig * it) {        return pcl818_ai_mode13(1, dev, s, it);}/* ==============================================================================   ANALOG INPUT MODE 3, 818 cards*/static int pcl818_ai_mode3(comedi_device * dev, comedi_subdevice * s, comedi_trig * it) {        return pcl818_ai_mode13(3, dev, s, it);}/*==============================================================================   ANALOG OUTPUT MODE 1 or 3, 818 cards*/#ifdef PCL818_MODE13_AOstatic int pcl818_ao_mode13(int mode, comedi_device * dev, comedi_subdevice * s, comedi_trig * it) {        int divisor1, divisor2; 	if (!dev->irq) {		comedi_error(dev,"IRQ not defined!");		return -EINVAL;        }        if (devpriv->irq_blocked)		return -EBUSY;        start_pacer(dev, -1, 0, 0); // stop pacer	devpriv->int13_act_scan=it->n;        devpriv->int13_act_chan=0;        devpriv->irq_blocked=1;        devpriv->irq_was_now_closed=0;        devpriv->neverending_ai=0;        devpriv->act_chanlist_pos=0;        devpriv->buf_ptr=0;              if (mode==1) {		i8253_cascade_ns_to_timer(devpriv->i8253_osc_base,&divisor1,&divisor2,&it->trigvar,TRIG_ROUND_NEAREST);		if (divisor1==1) {	/* PCL818 crash if any divisor is set to 1 */			divisor1=2;			divisor2/=2;		}		if (divisor2==1) {			divisor2=2;			divisor1/=2;		}	}	outb(0 , dev->iobase + PCL818_CNTENABLE); /* enable pacer */	if (mode==1) { 		devpriv->int818_mode=INT_TYPE_AO1_INT;		outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);  /* Pacer+IRQ */ 	} else { 		devpriv->int818_mode=INT_TYPE_AO3_INT;		outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);  /* Ext trig+IRQ */	};        start_pacer(dev, mode, divisor1, divisor2);        return 0;}/* ==============================================================================   ANALOG OUTPUT MODE 1, 818 cards*/static int pcl818_ao_mode1(comedi_device * dev, comedi_subdevice * s, comedi_trig * it) {        return pcl818_ao_mode13(1, dev, s, it);}/* ==============================================================================   ANALOG OUTPUT MODE 3, 818 cards*/static int pcl818_ao_mode3(comedi_device * dev, comedi_subdevice * s, comedi_trig * it) {        return pcl818_ao_mode13(3, dev, s, it);}#endif#endif/*============================================================================== Start/stop pacer onboard pacer*/#ifdef unusedstatic void start_pacer(comedi_device * dev, int mode, unsigned int divisor1, unsigned int divisor2) {        outb(0xb4, dev->iobase + PCL818_CTRCTL);        outb(0x74, dev->iobase + PCL818_CTRCTL);	outb(0x30, dev->iobase + PCL818_CTRCTL);        comedi_udelay(1);          if (mode==1) {		outb(divisor2 & 0xff, dev->iobase + PCL818_CTR2);		outb((divisor2 >> 8) & 0xff, dev->iobase + PCL818_CTR2);		outb(divisor1  & 0xff, dev->iobase + PCL818_CTR1);		outb((divisor1 >> 8) & 0xff, dev->iobase + PCL818_CTR1);        }}/*============================================================================== Check if channel list from user is builded correctly If it's ok, then program scan/gain logic*/static int check_and_setup_channel_list(comedi_device * dev, comedi_subdevice * s, comedi_trig * it){        unsigned int chansegment[16];          unsigned int i, nowmustbechan, seglen, segpos;        /* correct channel and range number check itself comedi/range.c */	if (it->n_chan<1) {		comedi_error(dev,"range/channel list is empty!");		return 0;                     }        if (it->n_chan > 1) {		// first channel is everytime ok		chansegment[0]=it->chanlist[0];		// build part of chanlist		for (i=1, seglen=1; i<it->n_chan; i++, seglen++) {			// rt_printk("%d. %d %d\n",i,CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i]));			// we detect loop, this must by finish			if (it->chanlist[0]==it->chanlist[i]) break;			nowmustbechan=(CR_CHAN(chansegment[i-1])+1) % s->n_chan;			// channel list isn't continous :-(			if (nowmustbechan!=CR_CHAN(it->chanlist[i])) {				rt_printk("comedi%d: pcl818: channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n",					    dev->minor,i,CR_CHAN(it->chanlist[i]),					    nowmustbechan,CR_CHAN(it->chanlist[0]) );				return 0;             			}			// well, this is next correct channel in list			chansegment[i]=it->chanlist[i];		}		// check whole chanlist		for (i=0, segpos=0; i<it->n_chan; i++) {			//rt_printk("%d %d=%d %d\n",CR_CHAN(chansegment[i%seglen]),CR_RANGE(chansegment[i%seglen]),CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i]));			if (it->chanlist[i]!=chansegment[i%seglen]) {				rt_printk("comedi%d: pcl818: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",				  dev->minor,i,CR_CHAN(chansegment[i]),				  CR_RANGE(chansegment[i]),				  CR_AREF(chansegment[i]),				  CR_CHAN(it->chanlist[i%seglen]),				  CR_RANGE(it->chanlist[i%seglen]),				  CR_AREF(chansegment[i%seglen]));				return 0; // chan/gain list is strange			}		}	} else {		seglen=1;	}    	devpriv->act_chanlist_len=seglen;	devpriv->act_chanlist_pos=0;	for (i=0; i<seglen; i++) {  // store range list to card		devpriv->act_chanlist[i]=CR_CHAN(it->chanlist[i]);		outb(muxonechan[CR_CHAN(it->chanlist[i])], dev->iobase+PCL818_MUX); /* select channel */		outb(CR_RANGE(it->chanlist[i]), dev->iobase+PCL818_RANGE); /* select gain */	}	comedi_udelay(1);	/* select channel interval to sca n*/	outb(devpriv->act_chanlist[0] | (devpriv->act_chanlist[seglen-1] << 4),		dev->iobase+PCL818_MUX);	// printk(" MUX %x\n",devpriv->act_chanlist[0] | (devpriv->act_chanlist[seglen-1] << 4));		// we can serve this with MUX logic	return 1;}#endif/* ============================================================================== Check if board is switched to SE (1) or DIFF(0) mode*/static int check_single_ended(unsigned int port){        if (inb(port+PCL818_STATUS)&0x20) { return 1; }					else { return 0; }}/* ============================================================================== cancel any mode 1-4 AI*/static int pcl818_ai_cancel(comedi_device * dev, comedi_subdevice * s) {        if (devpriv->irq_blocked>0) {		// rt_printk("pcl818_ai_cancel()\n");		switch (devpriv->int818_mode) {		case INT_TYPE_AI1_DMA_RTC:		case INT_TYPE_AI3_DMA_RTC:			set_rtc_irq_bit(0); // stop RTC			del_timer(&devpriv->rtc_irq_timer);		case INT_TYPE_AI1_DMA:		case INT_TYPE_AI3_DMA:			disable_dma(devpriv->dma);		case INT_TYPE_AI1_INT:		case INT_TYPE_AI3_INT:		case INT_TYPE_AI1_FIFO:		case INT_TYPE_AI3_FIFO:#ifdef PCL818_MODE13_AO		case INT_TYPE_AO1_INT:		case INT_TYPE_AO3_INT:#endif			outb(inb(dev->iobase+PCL818_CONTROL)& 0x73, dev->iobase+PCL818_CONTROL); /* Stop A/D */			comedi_udelay(1);			outb(0, dev->iobase+PCL818_CONTROL); /* Stop A/D */			outb(0xb4, dev->iobase + PCL818_CTRCTL);/* Stop pacer */			outb(0x74, dev->iobase + PCL818_CTRCTL);			outb(0, dev->iobase+PCL818_AD_LO);			inb(dev->iobase+PCL818_AD_LO);			inb(dev->iobase+PCL818_AD_HI);			outb(0, dev->iobase+PCL818_CLRINT); /* clear INT request */			outb(0, dev->iobase+PCL818_CONTROL); /* Stop A/D */			if (devpriv->usefifo) { // FIFO shutdown			        outb(0, dev->iobase + PCL818_FI_INTCLR);				outb(0, dev->iobase + PCL818_FI_FLUSH);				outb(0, dev->iobase + PCL818_FI_ENABLE);			}			devpriv->irq_blocked=0;			devpriv->irq_was_now_closed=devpriv->int818_mode;			devpriv->int818_mode=0;			devpriv->last_int_sub=s;			break;		}        }        //rt_printk("pcl818_ai_cancel() end\n");        return 0;}/* ============================================================================== chech for PCL818*/static int pcl818_check(int iobase) {        outb(0x00, iobase + PCL818_MUX);        comedi_udelay(1);         if (inb(iobase + PCL818_MUX)!=0x00) return 1; //there isn't card        outb(0x55, iobase + PCL818_MUX);        comedi_udelay(1);         if (inb(iobase + PCL818_MUX)!=0x55) return 1; //there isn't card        outb(0x00, iobase + PCL818_MUX);        comedi_udelay(1);         outb(0x18, iobase + PCL818_CONTROL);         comedi_udelay(1);         if (inb(iobase + PCL818_CONTROL)!=0x18) return 1; //there isn't card        return 0; // ok, card exist}/* ============================================================================== reset whole PCL-818 cards*/static void pcl818_reset(comedi_device * dev) {        if (devpriv->usefifo) { // FIFO shutdown		outb(0, dev->iobase + PCL818_FI_INTCLR);		outb(0, dev->iobase + PCL818_FI_FLUSH);		outb(0, dev->iobase + PCL818_FI_ENABLE);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -