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

📄 pcl812.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	for(i=0;i<insn->n;i++){		outb((data[i] & 0xff), dev->iobase + (chan ? PCL812_DA2_LO : PCL812_DA1_LO));		outb((data[i] >> 8) & 0x0f, dev->iobase + (chan ? PCL812_DA2_HI : PCL812_DA1_HI));		devpriv->ao_readback[chan]=data[i];	}	return i;}/* ==============================================================================*/static int pcl812_ao_insn_read(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data){	int chan = CR_CHAN(insn->chanspec);	int i;	for(i=0;i<insn->n;i++){		data[i] = devpriv->ao_readback[chan];	}	return i;}/* ==============================================================================*/static int pcl812_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 + PCL812_DI_LO);	data[1] |= inb(dev->iobase + PCL812_DI_HI) << 8;	return 2;}/* ==============================================================================*/static int pcl812_do_insn_bits(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data){	if(insn->n!=2)return -EINVAL;	if(data[0]){		s->state &= ~data[0];		s->state |= data[0]&data[1];		outb(s->state & 0xff, dev->iobase + PCL812_DO_LO);		outb((s->state >> 8), dev->iobase + PCL812_DO_HI);	}	data[1]=s->state;	return 2;}#ifdef PCL812_EXTDEBUG/* ==============================================================================*/static void pcl812_cmdtest_out(int e,comedi_cmd *cmd) {	rt_printk("pcl812 e=%d startsrc=%x scansrc=%x convsrc=%x\n",e,cmd->start_src,cmd->scan_begin_src,cmd->convert_src);	rt_printk("pcl812 e=%d startarg=%d scanarg=%d convarg=%d\n",e,cmd->start_arg,cmd->scan_begin_arg,cmd->convert_arg);	rt_printk("pcl812 e=%d stopsrc=%x scanend=%x\n",e,cmd->stop_src,cmd->scan_end_src);	rt_printk("pcl812 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n",e,cmd->stop_arg,cmd->scan_end_arg,cmd->chanlist_len);}#endif/* ==============================================================================*/static int pcl812_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd){	int err=0;	int tmp,divisor1,divisor2;#ifdef PCL812_EXTDEBUG	rt_printk("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...)\n");	pcl812_cmdtest_out(-1, cmd);#endif	/* step 1: make sure trigger sources are trivially valid */	tmp=cmd->start_src;	cmd->start_src &= TRIG_NOW;	if(!cmd->start_src || tmp!=cmd->start_src)err++;	tmp=cmd->scan_begin_src;	cmd->scan_begin_src &= TRIG_FOLLOW;	if(!cmd->scan_begin_src || tmp!=cmd->scan_begin_src)err++;	tmp=cmd->convert_src;	if (devpriv->use_ext_trg) { cmd->convert_src &= TRIG_EXT; }	                     else { cmd->convert_src &= TRIG_TIMER; }	if(!cmd->convert_src || tmp!=cmd->convert_src)err++;	tmp=cmd->scan_end_src;	cmd->scan_end_src &= TRIG_COUNT;	if(!cmd->scan_end_src || tmp!=cmd->scan_end_src)err++;	tmp=cmd->stop_src;	cmd->stop_src &= TRIG_COUNT|TRIG_NONE;	if(!cmd->stop_src || tmp!=cmd->stop_src)err++;	if(err) {#ifdef PCL812_EXTDEBUG		pcl812_cmdtest_out(1, cmd);		rt_printk("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=1\n",err);#endif		return 1;	}	/* step 2: make sure trigger sources are unique and mutually compatible */	if(cmd->start_src!=TRIG_NOW) {		cmd->start_src=TRIG_NOW;		err++;	}	if(cmd->scan_begin_src!=TRIG_FOLLOW) {		cmd->scan_begin_src=TRIG_FOLLOW;		err++;	}	if (devpriv->use_ext_trg) {		if(cmd->convert_src!=TRIG_EXT) {			cmd->convert_src=TRIG_EXT;			err++;		}	} else {		if(cmd->convert_src!=TRIG_TIMER) {			cmd->convert_src=TRIG_TIMER;			err++;		}	}	if(cmd->scan_end_src!=TRIG_COUNT) {		cmd->scan_end_src=TRIG_COUNT;		err++;	}	if(cmd->stop_src!=TRIG_NONE &&	   cmd->stop_src!=TRIG_COUNT) err++;	if(err) {#ifdef PCL812_EXTDEBUG		pcl812_cmdtest_out(2, cmd);		rt_printk("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=2\n",err);#endif		return 2;	}	/* step 3: make sure arguments are trivially compatible */	if(cmd->start_arg!=0){		cmd->start_arg=0;		err++;	}	if(cmd->scan_begin_arg!=0){		cmd->scan_begin_arg=0;		err++;	}	if(cmd->convert_src==TRIG_TIMER){		if(cmd->convert_arg<this_board->ai_ns_min){			cmd->convert_arg=this_board->ai_ns_min;			err++;		}	} else { /* TRIG_EXT */		if(cmd->convert_arg!=0){			cmd->convert_arg=0;			err++;		}	}	if(!cmd->chanlist_len){		cmd->chanlist_len=1;		err++;	}	if(cmd->chanlist_len>MAX_CHANLIST_LEN){		cmd->chanlist_len=this_board->n_aichan;		err++;	}	if(cmd->scan_end_arg!=cmd->chanlist_len){		cmd->scan_end_arg=cmd->chanlist_len;		err++;	}	if(cmd->stop_src==TRIG_COUNT){		if(!cmd->stop_arg){			cmd->stop_arg=1;			err++;		}	} else { /* TRIG_NONE */		if(cmd->stop_arg!=0){			cmd->stop_arg=0;			err++;		}	}	if(err) {#ifdef PCL812_EXTDEBUG		pcl812_cmdtest_out(3, cmd);		rt_printk("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=3\n",err);#endif		return 3;	}	/* step 4: fix up any arguments */	if(cmd->convert_src==TRIG_TIMER){		tmp=cmd->convert_arg;		i8253_cascade_ns_to_timer(this_board->i8254_osc_base,&divisor1,&divisor2,&cmd->convert_arg,cmd->flags&TRIG_ROUND_MASK);		if(cmd->convert_arg<this_board->ai_ns_min)			cmd->convert_arg=this_board->ai_ns_min;		if(tmp!=cmd->convert_arg)err++;	}	if(err) {#ifdef PCL812_EXTDEBUG		rt_printk("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=4\n",err);#endif		return 4;	}	return 0;}/* ==============================================================================*/static int pcl812_ai_cmd(comedi_device *dev,comedi_subdevice *s){	unsigned int	divisor1, divisor2, i, dma_flags, bytes;	comedi_cmd 	*cmd=&s->async->cmd;	#ifdef PCL812_EXTDEBUG	rt_printk("pcl812 EDBG: BGN: pcl812_ai_cmd(...)\n");#endif	if(cmd->start_src!=TRIG_NOW) return -EINVAL;	if(cmd->scan_begin_src!=TRIG_FOLLOW) return -EINVAL;	if (devpriv->use_ext_trg) {		if(cmd->convert_src!=TRIG_EXT) return -EINVAL;	} else {		if(cmd->convert_src!=TRIG_TIMER) return -EINVAL;	}	if(cmd->scan_end_src!=TRIG_COUNT) return -EINVAL;	if(cmd->scan_end_arg!=cmd->chanlist_len) return -EINVAL;	if(cmd->chanlist_len>MAX_CHANLIST_LEN) return -EINVAL;	if (cmd->convert_src==TRIG_TIMER) {		if(cmd->convert_arg<this_board->ai_ns_min) cmd->convert_arg=this_board->ai_ns_min;		i8253_cascade_ns_to_timer(this_board->i8254_osc_base, 			&divisor1, &divisor2, &cmd->convert_arg, 			cmd->flags&TRIG_ROUND_MASK);	}	start_pacer(dev, -1, 0, 0); // stop pacer	devpriv->ai_n_chan=cmd->chanlist_len;	memcpy(devpriv->ai_chanlist,cmd->chanlist,sizeof(unsigned int)*cmd->scan_end_arg);	setup_range_channel(dev, s, devpriv->ai_chanlist[0], 1); // select first channel and range	if (devpriv->dma) { // check if we can use DMA transfer		devpriv->ai_dma=1;		for (i=1; i<devpriv->ai_n_chan; i++) 			if (devpriv->ai_chanlist[0]!=devpriv->ai_chanlist[i]) {				devpriv->ai_dma=0;	// we cann't use DMA :-(				break;			}	} else devpriv->ai_dma=0;			devpriv->ai_flags=cmd->flags;	devpriv->ai_data_len=s->async->prealloc_bufsz;	devpriv->ai_data=s->async->prealloc_buf;	if (cmd->stop_src==TRIG_COUNT) { devpriv->ai_scans=cmd->stop_arg; devpriv->ai_neverending=0; }				else   { devpriv->ai_scans=0; devpriv->ai_neverending=1; }        devpriv->ai_act_scan=0;	devpriv->ai_poll_ptr=0;        s->async->cur_chan=0;	if ((devpriv->ai_flags & TRIG_WAKE_EOS)) { 	// don't we want wake up every scan?				devpriv->ai_eos=1;		if (devpriv->ai_n_chan==1)			devpriv->ai_dma=0;	// DMA is useless for this situation	}	if (devpriv->ai_dma) {			if (devpriv->ai_eos) {  // we use EOS, so adapt DMA buffer to one scan			devpriv->dmabytestomove[0]=devpriv->ai_n_chan*sizeof(sampl_t);			devpriv->dmabytestomove[1]=devpriv->ai_n_chan*sizeof(sampl_t);			devpriv->dma_runs_to_end=1; 		} else {			devpriv->dmabytestomove[0]=devpriv->hwdmasize[0]; 			devpriv->dmabytestomove[1]=devpriv->hwdmasize[1];			if (devpriv->ai_data_len<devpriv->hwdmasize[0])				devpriv->dmabytestomove[0]=devpriv->ai_data_len;			if (devpriv->ai_data_len<devpriv->hwdmasize[1])				devpriv->dmabytestomove[1]=devpriv->ai_data_len;			if (devpriv->ai_neverending) {				devpriv->dma_runs_to_end=1; 			} else {				bytes=devpriv->ai_n_chan*devpriv->ai_scans*sizeof(sampl_t); // how many samples we must transfer?				devpriv->dma_runs_to_end=bytes / devpriv->dmabytestomove[0]; // how many DMA pages we must fill				devpriv->last_dma_run=bytes % devpriv->dmabytestomove[0]; //on last dma transfer must be moved				if (devpriv->dma_runs_to_end==0) 					devpriv->dmabytestomove[0]=devpriv->last_dma_run;				devpriv->dma_runs_to_end--;			}		}		if (devpriv->dmabytestomove[0]>devpriv->hwdmasize[0]) {			devpriv->dmabytestomove[0]=devpriv->hwdmasize[0];			devpriv->ai_eos=0;		}		if (devpriv->dmabytestomove[1]>devpriv->hwdmasize[1]) {			devpriv->dmabytestomove[1]=devpriv->hwdmasize[1];			devpriv->ai_eos=0;		}	        devpriv->next_dma_buf=0;		set_dma_mode(devpriv->dma, DMA_MODE_READ);	        dma_flags=claim_dma_lock();	        clear_dma_ff(devpriv->dma);	        set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);	        set_dma_count(devpriv->dma, devpriv->dmabytestomove[0]);	        release_dma_lock(dma_flags);	        enable_dma(devpriv->dma);#ifdef PCL812_EXTDEBUG		rt_printk("pcl812 EDBG:   DMA %d PTR 0x%0x/0x%0x LEN %u/%u EOS %d\n",			devpriv->dma,devpriv->hwdmaptr[0],devpriv->hwdmaptr[1],			devpriv->dmabytestomove[0],devpriv->dmabytestomove[1],			devpriv->ai_eos);#endif	}		switch (cmd->convert_src) {	case TRIG_TIMER:		start_pacer(dev, 1, divisor1, divisor2);		break;	}		if (devpriv->ai_dma) {			outb(devpriv->mode_reg_int|2, dev->iobase + PCL812_MODE);	// let's go!	} else {		outb(devpriv->mode_reg_int|6, dev->iobase + PCL812_MODE);	// let's go!	}#ifdef PCL812_EXTDEBUG	rt_printk("pcl812 EDBG: END: pcl812_ai_cmd(...)\n");#endif        return 0;}/* ==============================================================================*/static void interrupt_pcl812_ai_int(int irq, void *d, struct pt_regs *regs){	char err=1;	unsigned int mask, timeout;	comedi_device *dev = d;	comedi_subdevice *s = dev->subdevices + 0;	s->async->events = 0;	timeout = 50;	/* wait max 50us, it must finish under 33us */	if (devpriv->ai_is16b) {		mask=0xffff;		while (timeout--) {			if (!(inb(dev->iobase + ACL8216_STATUS) & ACL8216_DRDY)) {			    err=0; break;			}			comedi_udelay(1);		}	} else {		mask=0x0fff;		while (timeout--) {			if (!(inb(dev->iobase + PCL812_AD_HI) & PCL812_DRDY)) {			    err=0; break;			}			comedi_udelay(1);		}	}		if (err) {		rt_printk("comedi%d: pcl812: (%s at 0x%x) A/D cmd IRQ without DRDY!\n", dev->minor, dev->board_name, dev->iobase);		pcl812_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,		((inb(dev->iobase + PCL812_AD_HI) << 8) | inb(dev->iobase + PCL812_AD_LO)) & mask);	outb(0, dev->iobase + PCL812_CLRINT);	/* clear INT request */	if (s->async->cur_chan == 0 ) {	/* one scan done */		devpriv->ai_act_scan++;		if (!(devpriv->ai_neverending))			if (devpriv->ai_act_scan>=devpriv->ai_scans) {	/* all data sampled */				pcl812_ai_cancel(dev,s);				s->async->events |= COMEDI_CB_EOA;			}	}	comedi_event(dev,s,s->async->events);}/* ==============================================================================*/static void transfer_from_dma_buf(comedi_device *dev,comedi_subdevice *s,	sampl_t *ptr, unsigned int bufptr, unsigned int len){	unsigned int i;		s->async->events = 0;        for (i=len; i; i--) {		comedi_buf_put( s->async, ptr[bufptr++] ); // get one sample		if(s->async->cur_chan == 0){			devpriv->ai_act_scan++;			if (!devpriv->ai_neverending)				if (devpriv->ai_act_scan>=devpriv->ai_scans) {	/* all data sampled */					pcl812_ai_cancel(dev,s);					s->async->events |= COMEDI_CB_EOA;					break;				}		}	}	comedi_event(dev,s,s->async->events);}/* ==============================================================================*/static void interrupt_pcl812_ai_dma(int irq, void *d, struct pt_regs *regs){	comedi_device *dev = d;	comedi_subdevice *s = dev->subdevices + 0;	unsigned long dma_flags;	int len,bufptr;        sampl_t *ptr;#ifdef PCL812_EXTDEBUG	rt_printk("pcl812 EDBG: BGN: interrupt_pcl812_ai_dma(...)\n");#endif        ptr=(sampl_t *)devpriv->dmabuf[devpriv->next_dma_buf];        len=(devpriv->dmabytestomove[devpriv->next_dma_buf] >> 1) - devpriv->ai_poll_ptr;        devpriv->next_dma_buf=1-devpriv->next_dma_buf;        disable_dma(devpriv->dma);	set_dma_mode(devpriv->dma, DMA_MODE_READ);	dma_flags=claim_dma_lock();	set_dma_addr(devpriv->dma, devpriv->hwdmaptr[devpriv->next_dma_buf]);	if (devpriv->ai_eos) {		set_dma_count(devpriv->dma, devpriv->dmabytestomove[devpriv->next_dma_buf]); 	} else {		if (devpriv->dma_runs_to_end) { set_dma_count(devpriv->dma, devpriv->dmabytestomove[devpriv->next_dma_buf]); }					else { set_dma_count(devpriv->dma, devpriv->last_dma_run); }	        devpriv->dma_runs_to_end--;	}	release_dma_lock(dma_flags);	enable_dma(devpriv->dma);        outb(0,dev->iobase+PCL812_CLRINT); /* clear INT request */        bufptr=devpriv->ai_poll_ptr;	devpriv->ai_poll_ptr=0;	transfer_from_dma_buf(dev, s, ptr, bufptr, len);#ifdef PCL812_EXTDEBUG	rt_printk("pcl812 EDBG: END: interrupt_pcl812_ai_dma(...)\n");#endif}/* ==============================================================================*/static void interrupt_pcl812(int irq, void *d, struct pt_regs *regs){	comedi_device *dev = d;

⌨️ 快捷键说明

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