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

📄 ni_mio_common.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#if 0static void ni_handle_block_dma(comedi_device *dev){	comedi_subdevice *s = dev->subdevices + 0;	MDPRINTK("ni_handle_block_dma\n");	mite_dma_disarm(devpriv->mite);	ni_set_bits(dev, Interrupt_A_Enable_Register,		AI_SC_TC_Interrupt_Enable | AI_START1_Interrupt_Enable|		AI_START2_Interrupt_Enable| AI_START_Interrupt_Enable|		AI_STOP_Interrupt_Enable| AI_Error_Interrupt_Enable|		AI_FIFO_Interrupt_Enable,0);	ni_ai_reset(dev,dev->subdevices);	s->async->events |= COMEDI_CB_EOA;	MDPRINTK("exit ni_handle_block_dma\n");}#endifstatic void ni_ai_setup_MITE_dma(comedi_device *dev,comedi_cmd *cmd){	struct mite_struct *mite = devpriv->mite;	struct mite_channel *mite_chan = &mite->channels[ AI_DMA_CHAN ];	comedi_subdevice *s = dev->subdevices + 0;	/* write alloc the entire buffer */	comedi_buf_write_alloc(s->async, s->async->prealloc_bufsz);	mite_chan->current_link = 0;	mite_chan->dir = COMEDI_INPUT;	if( boardtype.reg_611x )		mite_prep_dma(mite, AI_DMA_CHAN, 32, 16);	else		mite_prep_dma(mite, AI_DMA_CHAN, 16, 16);	/*start the MITE*/	mite_dma_arm(mite, AI_DMA_CHAN);}static void ni_ao_setup_MITE_dma(comedi_device *dev,comedi_cmd *cmd){	struct mite_struct *mite = devpriv->mite;	struct mite_channel *mite_chan = &mite->channels[ AO_DMA_CHAN ];	comedi_subdevice *s = dev->subdevices + 1;	devpriv->last_buf_write_count = s->async->buf_write_count;	mite_chan->current_link = 0;	mite_chan->dir = COMEDI_OUTPUT;	if( boardtype.ao_671x )		mite_prep_dma(mite, AO_DMA_CHAN, 32, 32);	else		mite_prep_dma(mite, AO_DMA_CHAN, 16, 16);	/*start the MITE*/	mite_dma_arm(mite, AO_DMA_CHAN);}#endif // PCIDMA/*   used for both cancel ioctl and board initialization   this is pretty harsh for a cancel, but it works... */static int ni_ai_reset(comedi_device *dev,comedi_subdevice *s){#ifdef PCIDMA	mite_dma_disarm(devpriv->mite, AI_DMA_CHAN);#endif	/* ai configuration */	win_out( AI_Configuration_Start | AI_Reset, Joint_Reset_Register );	ni_set_bits(dev, Interrupt_A_Enable_Register,		AI_SC_TC_Interrupt_Enable | AI_START1_Interrupt_Enable|		AI_START2_Interrupt_Enable| AI_START_Interrupt_Enable|		AI_STOP_Interrupt_Enable|   AI_Error_Interrupt_Enable|		AI_FIFO_Interrupt_Enable,0);	win_out(1,ADC_FIFO_Clear);	ni_writeb(0, Misc_Command);	win_out(AI_Disarm, AI_Command_1_Register); /* reset pulses */	win_out(AI_Start_Stop | AI_Mode_1_Reserved /*| AI_Trigger_Once */,		AI_Mode_1_Register);	win_out(0x0000,AI_Mode_2_Register);#if 0	/* generate FIFO interrupts on half full */	win_out((1<<6)|0x0000,AI_Mode_3_Register);#else	/* generate FIFO interrupts on non-empty */	win_out((0<<6)|0x0000,AI_Mode_3_Register);#endif	if(!boardtype.reg_611x){		win_out(AI_SHIFTIN_Pulse_Width |			AI_SOC_Polarity |			AI_CONVERT_Pulse_Width |			AI_LOCALMUX_CLK_Pulse_Width, AI_Personal_Register);		win_out(AI_SCAN_IN_PROG_Output_Select(3) |			AI_EXTMUX_CLK_Output_Select(0) |			AI_LOCALMUX_CLK_Output_Select(2) |			AI_SC_TC_Output_Select(3) |			AI_CONVERT_Output_Select(2),AI_Output_Control_Register);	}else{		win_out(AI_SHIFTIN_Pulse_Width |			AI_SOC_Polarity |			AI_LOCALMUX_CLK_Pulse_Width, AI_Personal_Register);		win_out(AI_SCAN_IN_PROG_Output_Select(3) |			AI_EXTMUX_CLK_Output_Select(0) |			AI_LOCALMUX_CLK_Output_Select(2) |			AI_SC_TC_Output_Select(3) |			AI_CONVERT_Output_Select(3),AI_Output_Control_Register);	}	/* the following registers should not be changed, because there	 * are no backup registers in devpriv.  If you want to change	 * any of these, add a backup register and other appropriate code:	 *	Clock_and_FOUT_Register	 *	AI_Mode_1_Register	 *	AI_Mode_3_Register	 *	AI_Personal_Register	 *	AI_Output_Control_Register	*/	win_out(0x3f80,Interrupt_A_Ack_Register); /* clear interrupts */	win_out(AI_Configuration_End,Joint_Reset_Register);	return 0;}static int ni_ai_poll(comedi_device *dev,comedi_subdevice *s){#ifndef PCIDMA	ni_handle_fifo_dregs(dev);	//comedi_event(dev,s,s->async->events);	return s->async->buf_write_count - s->async->buf_read_count;#else	/* XXX we don't support this yet. */	return -EINVAL;#endif}static int ni_ai_insn_read(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){	int i,n;	unsigned int mask;	unsigned short signbits;	unsigned short d;	ni_load_channelgain_list(dev,1,&insn->chanspec);	win_out(1,ADC_FIFO_Clear);	mask=(1<<boardtype.adbits)-1;	signbits=devpriv->ai_offset[0];	if(boardtype.reg_611x){		for(n=0; n < num_adc_stages_611x; n++){			win_out(AI_CONVERT_Pulse, AI_Command_1_Register);			comedi_udelay(1);		}		for(n=0; n<insn->n; n++){			win_out(AI_CONVERT_Pulse, AI_Command_1_Register);			/* The 611x has screwy 32-bit FIFOs. */			d = 0;			for(i=0; i<NI_TIMEOUT; i++){				if(ni_readb(XXX_Status)&0x80)				{					d = ( ni_readl(ADC_FIFO_Data_611x) >> 16 ) & 0xffff;					break;				}				if(!(win_in(AI_Status_1_Register)&AI_FIFO_Empty_St))				{					d = ni_readl(ADC_FIFO_Data_611x) & 0xffff;					break;				}			}			if(i==NI_TIMEOUT){				rt_printk("ni_mio_common: timeout in 611x ni_ai_insn_read\n");				return -ETIME;			}			d += signbits; /* subtle: needs to be short addition */			data[ n ] = d;		}	}else{		for(n=0;n<insn->n;n++){			win_out(AI_CONVERT_Pulse, AI_Command_1_Register);			for(i=0;i<NI_TIMEOUT;i++){				if(!(win_in(AI_Status_1_Register)&AI_FIFO_Empty_St))			 		break;			}			if(i==NI_TIMEOUT){				rt_printk("ni_mio_common: timeout in ni_ai_insn_read\n");				return -ETIME;			}			d = ni_readw(ADC_FIFO_Data_Register);			d += signbits; /* subtle: needs to be short addition */			data[n] = d;		}	}	return insn->n;}/* * Notes on the 6110 and 6111: * These boards a slightly different than the rest of the series, since * they have multiple A/D converters.  Register level documentation is * not written down for these boards, other than what is here.  If you * have any questions, ask Tim Ousley. * From the driver side, it is only the configuration memory that is a * little different. * Configuration Memory Low: *   bits 15-9: same *   bit 8: unipolar/bipolar (should be 0 for bipolar) *   bits 0-3: gain.  This is 4 bits instead of 3 for the other boards *       1001 gain=0.1 (+/- 50) *       1010 0.2 *       1011 0.1 *       0001 1 *       0010 2 *       0011 5 *       0100 10 *       0101 20 *       0110 50 * Configuration Memory High: *   bits 12-14: Channel Type *       001 for differential *       000 for calibration *   bit 11: coupling  (this is not currently handled) *       1 AC coupling *       0 DC coupling *   bits 0-2: channel *       valid channels are 0-3 */static void ni_load_channelgain_list(comedi_device *dev,unsigned int n_chan,	unsigned int *list){	unsigned int chan,range,aref;	unsigned int i;	unsigned int hi,lo;	unsigned short offset;	unsigned int dither;	if(n_chan == 1 && boardtype.reg_611x == 0){		if(devpriv->changain_state && devpriv->changain_spec==list[0]){			// ready to go.			return;		}		devpriv->changain_state=1;		devpriv->changain_spec=list[0];	}else{		devpriv->changain_state=0;	}	win_out(1,Configuration_Memory_Clear);	offset=1<<(boardtype.adbits-1);	for(i=0;i<n_chan;i++){		if(list[i]&CR_ALT_SOURCE){			chan=devpriv->ai_calib_source;		}else{			chan=CR_CHAN(list[i]);		}		aref=CR_AREF(list[i]);		range=CR_RANGE(list[i]);		dither=((list[i]&CR_ALT_FILTER)!=0);		/* fix the external/internal range differences */		range = ni_gainlkup[boardtype.gainlkup][range];		if( boardtype.reg_611x )			devpriv->ai_offset[i] = offset;		else			devpriv->ai_offset[i] = (range&0x100)?0:offset;		hi = 0;		if( ( list[i] & CR_ALT_SOURCE ) )		{			if( boardtype.reg_611x )				ni_writew(CR_CHAN(list[i])&0x0003, Calibration_Channel_Select_611x);		}else		{			if( boardtype.reg_611x )				aref = AREF_DIFF;			switch( aref )			{				case AREF_DIFF:					hi |= AI_DIFFERENTIAL;					break;				case AREF_COMMON:					hi |= AI_COMMON;					break;				case AREF_GROUND:					hi |= AI_GROUND;					break;				case AREF_OTHER:					break;			}		}		hi |= AI_CONFIG_CHANNEL( chan );		ni_writew(hi,Configuration_Memory_High);		lo = range;		if(i == n_chan - 1) lo |= AI_LAST_CHANNEL;		if( dither ) lo |= AI_DITHER;		ni_writew(lo,Configuration_Memory_Low);	}	/* prime the channel/gain list */	if(boardtype.reg_611x == 0){		win_out(AI_CONVERT_Pulse, AI_Command_1_Register);		for(i=0;i<NI_TIMEOUT;i++){			if(!(win_in(AI_Status_1_Register)&AI_FIFO_Empty_St)){				win_out(1,ADC_FIFO_Clear);				return;			}			comedi_udelay(1);		}		rt_printk("ni_mio_common: timeout loading channel/gain list\n");	}}#define TIMER_BASE 50 /* 20 Mhz base */static int ni_ns_to_timer(int *nanosec,int round_mode){	int divider,base;	base=TIMER_BASE;	switch(round_mode){	case TRIG_ROUND_NEAREST:	default:		divider=(*nanosec+base/2)/base;		break;	case TRIG_ROUND_DOWN:		divider=(*nanosec)/base;		break;	case TRIG_ROUND_UP:		divider=(*nanosec+base-1)/base;		break;	}	*nanosec=base*divider;	return divider-1;}static int ni_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd){	int err=0;	int tmp;	int sources;	/* step 1: make sure trigger sources are trivially valid */	tmp=cmd->start_src;	cmd->start_src &= TRIG_NOW|TRIG_INT|TRIG_EXT;	if(!cmd->start_src || tmp!=cmd->start_src)err++;	tmp=cmd->scan_begin_src;	cmd->scan_begin_src &= TRIG_TIMER|TRIG_EXT;	if(!cmd->scan_begin_src || tmp!=cmd->scan_begin_src)err++;	tmp=cmd->convert_src;	sources = TRIG_TIMER | TRIG_EXT;	if( boardtype.reg_611x ) sources |= TRIG_NOW;	cmd->convert_src &= sources;	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)return 1;	/* step 2: make sure trigger sources are unique and mutually compatible */	/* note that mutual compatiblity is not an issue here */	if(cmd->start_src!=TRIG_NOW &&	   cmd->start_src!=TRIG_INT &&	   cmd->start_src!=TRIG_EXT)err++;	if(cmd->scan_begin_src!=TRIG_TIMER &&	   cmd->scan_begin_src!=TRIG_EXT &&	   cmd->scan_begin_src!=TRIG_OTHER)err++;	if(cmd->convert_src!=TRIG_TIMER &&	   cmd->convert_src!=TRIG_EXT &&	   cmd->convert_src!=TRIG_NOW)err++;	if(cmd->stop_src!=TRIG_COUNT &&	   cmd->stop_src!=TRIG_NONE)err++;	if(err)return 2;	/* step 3: make sure arguments are trivially compatible */	if(cmd->start_src==TRIG_EXT){		/* external trigger */		unsigned int tmp = CR_CHAN(cmd->start_arg);		if(tmp>9)tmp=9;		/* XXX for now, use the top bit to invert the signal */		tmp |= (cmd->start_arg&0x80000000);		if(cmd->start_arg!=tmp){			cmd->start_arg = tmp;			err++;		}	}else{		if(cmd->start_arg!=0){			/* true for both TRIG_NOW and TRIG_INT */			cmd->start_arg=0;			err++;		}	}	if(cmd->scan_begin_src==TRIG_TIMER){		if(cmd->scan_begin_arg<boardtype.ai_speed){			cmd->scan_begin_arg=boardtype.ai_speed;			err++;		}		if(cmd->scan_begin_arg>TIMER_BASE*0xffffff){			cmd->scan_begin_arg=TIMER_BASE*0xffffff;			err++;		}	}else if(cmd->scan_begin_src==TRIG_EXT){		/* external trigger */		unsigned int tmp = CR_CHAN(cmd->scan_begin_arg);		if(tmp>9)tmp=9;		/* XXX for now, use the top bit to invert the signal */		tmp |= (cmd->scan_begin_arg&0x80000000);		if(cmd->scan_begin_arg!=tmp){			cmd->scan_begin_arg = tmp;			err++;		}	}else{ /* TRIG_OTHER */		if(cmd->scan_begin_arg){			cmd->scan_begin_arg=0;			err++;		}	}	if(cmd->convert_src==TRIG_TIMER){		if( boardtype.reg_611x ){			if(cmd->convert_arg != 0){				cmd->convert_arg = 0;				err++;			}		}else{			if(cmd->convert_arg<boardtype.ai_speed){				cmd->convert_arg=boardtype.ai_speed;				err++;			}			if(cmd->convert_arg>TIMER_BASE*0xffff){				cmd->convert_arg=TIMER_BASE*0xffff;				err++;			}		}	}else if(cmd->convert_src == TRIG_EXT){		/* external trigger */		unsigned int tmp = CR_CHAN(cmd->convert_arg);		if(tmp>9)tmp=9;		tmp |= (cmd->convert_arg&(CR_ALT_FILTER|CR_INVERT));		if(cmd->convert_arg!=tmp){			cmd->convert_arg = tmp;			err++;		}	}else if(cmd->convert_src == TRIG_NOW){		if(cmd->convert_arg != 0){			cmd->convert_arg = 0;			err++;		}	}	if(cmd->scan_end_arg!=cmd->chanlist_len){		cmd->scan_end_arg=cmd->chanlist_len;		err++;	}	if(cmd->stop_src==TRIG_COUNT){		unsigned int max_count = 0x01000000;		if( boardtype.reg_611x )			max_count -= num_adc_stages_611x;		if(cmd->stop_arg > max_count){			cmd->stop_arg = max_count;			err++;		}	}else{		/* TRIG_NONE */		if(cmd->stop_arg!=0){			cmd->stop_arg=0;			err++;		}	}	if(err)return 3;	/* step 4: fix up any arguments */

⌨️ 快捷键说明

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