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

📄 cb_pcidas64.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
static int ai_config_insn( comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data){	int id = data[0];	switch( id )	{		case INSN_CONFIG_ALT_SOURCE:			return ai_config_calibration_source( dev, data );			break;		case INSN_CONFIG_BLOCK_SIZE:			return ai_config_block_size( dev, data );			break;		case INSN_CONFIG_TIMER_1:			return ai_config_master_clock( dev, data );			break;		default:			return -EINVAL;			break;	}	return -EINVAL;}static int ai_cmdtest(comedi_device *dev,comedi_subdevice *s, comedi_cmd *cmd){	int err = 0;	int tmp;	unsigned int tmp_arg, tmp_arg2;	int i;	int aref;	unsigned int triggers;	/* step 1: make sure trigger sources are trivially valid */	tmp = cmd->start_src;	cmd->start_src &= TRIG_NOW | TRIG_EXT;	if(!cmd->start_src || tmp != cmd->start_src) err++;	tmp = cmd->scan_begin_src;	triggers = TRIG_TIMER;	if(board(dev)->layout == LAYOUT_4020)		triggers |= TRIG_OTHER;	else		triggers |= TRIG_FOLLOW;	cmd->scan_begin_src &= triggers;	if(!cmd->scan_begin_src || tmp != cmd->scan_begin_src) err++;	tmp = cmd->convert_src;	if(board(dev)->layout == LAYOUT_4020)		triggers = TRIG_NOW | TRIG_OTHER;	else		triggers = TRIG_TIMER | TRIG_EXT;	cmd->convert_src &= triggers;	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_EXT | 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 */	// uniqueness check	if(cmd->start_src != TRIG_NOW &&		cmd->start_src != TRIG_EXT) err++;	if(cmd->scan_begin_src != TRIG_TIMER &&		cmd->scan_begin_src != TRIG_OTHER &&		cmd->scan_begin_src != TRIG_FOLLOW) err++;	if(cmd->convert_src != TRIG_TIMER &&		cmd->convert_src != TRIG_EXT &&		cmd->convert_src != TRIG_NOW &&		cmd->convert_src != TRIG_OTHER) err++;	if(cmd->stop_src != TRIG_COUNT &&		cmd->stop_src != TRIG_NONE &&		cmd->stop_src != TRIG_EXT) err++;	// compatibility check	if(cmd->convert_src == TRIG_EXT &&		cmd->scan_begin_src == TRIG_TIMER)		err++;	if(cmd->stop_src != TRIG_COUNT &&		cmd->stop_src != TRIG_NONE &&		cmd->stop_src != TRIG_EXT) err++;	if( cmd->convert_src == TRIG_OTHER &&		cmd->scan_begin_arg == TRIG_OTHER ) err++;			if(err) return 2;	/* step 3: make sure arguments are trivially compatible */	if(cmd->convert_src == TRIG_TIMER)	{		if(cmd->convert_arg < board(dev)->ai_speed)		{			cmd->convert_arg = board(dev)->ai_speed;			err++;		}		if(cmd->scan_begin_src == TRIG_TIMER)		{			// if scans are timed faster than conversion rate allows			if(cmd->convert_arg * cmd->chanlist_len > cmd->scan_begin_arg)			{				cmd->scan_begin_arg = cmd->convert_arg * cmd->chanlist_len;				err++;			}		}	}	if(!cmd->chanlist_len)	{		cmd->chanlist_len = 1;		err++;	}	if(cmd->scan_end_arg != cmd->chanlist_len)	{		cmd->scan_end_arg = cmd->chanlist_len;		err++;	}	switch(cmd->stop_src)	{		case TRIG_EXT:			break;		case TRIG_COUNT:			if(!cmd->stop_arg)			{				cmd->stop_arg = 1;				err++;			}			break;		case TRIG_NONE:			if(cmd->stop_arg != 0)			{				cmd->stop_arg = 0;				err++;			}			break;		default:			break;	}	if(err) return 3;	/* step 4: fix up any arguments */	if(cmd->convert_src == TRIG_TIMER)	{		tmp_arg = cmd->convert_arg;		tmp_arg2 = cmd->scan_begin_arg;		check_adc_timing(cmd);		if(tmp_arg != cmd->convert_arg) err++;		if(tmp_arg2 != cmd->scan_begin_arg) err++;	}	if(err) return 4;	// make sure user is doesn't change analog reference mid chanlist	if(cmd->chanlist)	{		aref = CR_AREF(cmd->chanlist[0]);		for(i = 1; i < cmd->chanlist_len; i++)		{			if(aref != CR_AREF(cmd->chanlist[i]))			{				comedi_error(dev, "all elements in chanlist must use the same analog reference");				err++;				break;			}		}		// check 4020 chanlist		if( board(dev)->layout == LAYOUT_4020 )		{			unsigned int first_channel = CR_CHAN( cmd->chanlist[0] );			for( i = 1; i < cmd->chanlist_len; i++ )			{				if( CR_CHAN( cmd->chanlist[ i ] ) != first_channel + i )				{					comedi_error( dev, "chanlist must use consecutive channels" );					err++;					break;				}			}			if( cmd->chanlist_len == 3 )			{				comedi_error( dev, "chanlist cannot be 3 channels long, use 1, 2, or 4 channels" );				err++;			}		}	}	if(err) return 5;	return 0;}static int use_hw_sample_counter( comedi_cmd *cmd ){	static const int max_hardware_count = 0xffffff;// disable for now until I work out a racereturn 0;	if( cmd->stop_src == TRIG_COUNT &&		cmd->stop_arg <= max_hardware_count )		return 1;	else		return 0;}static void setup_sample_counters( comedi_device *dev, comedi_cmd *cmd ){	if( cmd->stop_src == TRIG_COUNT )	{		// set software count		priv(dev)->ai_count = cmd->stop_arg * cmd->chanlist_len;	}	// load hardware conversion counter	if( use_hw_sample_counter( cmd ) )	{		writew( cmd->stop_arg & 0xffff, priv(dev)->main_iobase + ADC_COUNT_LOWER_REG);		writew( ( cmd->stop_arg >> 16 ) & 0xff,			priv(dev)->main_iobase + ADC_COUNT_UPPER_REG);	} else	{		writew( 1, priv(dev)->main_iobase + ADC_COUNT_LOWER_REG);	}}static inline unsigned int dma_transfer_size( comedi_device *dev ){	unsigned int num_samples;	num_samples = priv(dev)->ai_fifo_segment_length * board(dev)->ai_fifo->sample_packing_ratio;	if( num_samples > DMA_BUFFER_SIZE / sizeof( uint16_t ) )		num_samples = DMA_BUFFER_SIZE / sizeof( uint16_t );	return num_samples;}static void disable_ai_pacing( comedi_device *dev ){	unsigned long flags;	disable_ai_interrupts( dev );	/* disable pacing, triggering, etc */	writew( ADC_DMA_DISABLE_BIT | ADC_SOFT_GATE_BITS | ADC_GATE_LEVEL_BIT,		priv(dev)->main_iobase + ADC_CONTROL0_REG );	comedi_spin_lock_irqsave( &dev->spinlock, flags );	priv(dev)->adc_control1_bits &= ~SW_GATE_BIT;	writew( priv(dev)->adc_control1_bits, priv(dev)->main_iobase + ADC_CONTROL1_REG );	comedi_spin_unlock_irqrestore( &dev->spinlock, flags );}static void disable_ai_interrupts( comedi_device *dev ){	unsigned long flags;	comedi_spin_lock_irqsave( &dev->spinlock, flags );	priv(dev)->intr_enable_bits &=		~EN_ADC_INTR_SRC_BIT & ~EN_ADC_DONE_INTR_BIT & ~EN_ADC_ACTIVE_INTR_BIT		& ~EN_ADC_STOP_INTR_BIT & ~EN_ADC_OVERRUN_BIT & ~ADC_INTR_SRC_MASK;	writew( priv(dev)->intr_enable_bits, priv(dev)->main_iobase + INTR_ENABLE_REG );	comedi_spin_unlock_irqrestore( &dev->spinlock, flags );	DEBUG_PRINT( "intr enable bits 0x%x\n", priv(dev)->intr_enable_bits );}static void enable_ai_interrupts( comedi_device *dev, const comedi_cmd *cmd ){	uint32_t bits;	unsigned long flags;	bits = EN_ADC_OVERRUN_BIT | EN_ADC_DONE_INTR_BIT |		EN_ADC_ACTIVE_INTR_BIT | EN_ADC_STOP_INTR_BIT;	// Use pio transfer and interrupt on end of conversion if TRIG_WAKE_EOS flag is set.	if( cmd->flags & TRIG_WAKE_EOS )	{		// 4020 doesn't support pio transfers except for fifo dregs		if( board(dev)->layout != LAYOUT_4020 )			bits |= ADC_INTR_EOSCAN_BITS | EN_ADC_INTR_SRC_BIT;	}	comedi_spin_lock_irqsave( &dev->spinlock, flags );	priv(dev)->intr_enable_bits |= bits;	writew( priv(dev)->intr_enable_bits, priv(dev)->main_iobase + INTR_ENABLE_REG );	DEBUG_PRINT( "intr enable bits 0x%x\n", priv(dev)->intr_enable_bits );	comedi_spin_unlock_irqrestore( &dev->spinlock, flags );}static uint32_t ai_convert_counter_6xxx( const comedi_device *dev, const comedi_cmd *cmd ){	// supposed to load counter with desired divisor minus 3	return	cmd->convert_arg / TIMER_BASE - 3;}static uint32_t ai_scan_counter_6xxx( comedi_device *dev, comedi_cmd *cmd ){	// figure out how long we need to delay at end of scan	switch( cmd->scan_begin_src )	{		case TRIG_TIMER:			return ( cmd->scan_begin_arg - ( cmd->convert_arg * ( cmd->chanlist_len - 1 ) ) )				/ TIMER_BASE;			break;		case TRIG_FOLLOW:			return cmd->convert_arg / TIMER_BASE;			break;		default:			break;	}	return 0;}static uint32_t ai_convert_counter_4020( comedi_device *dev, comedi_cmd *cmd ){	unsigned int divisor;	switch( cmd->scan_begin_src )	{		case TRIG_TIMER:			divisor = cmd->scan_begin_arg;			break;		case TRIG_OTHER:			divisor = priv(dev)->ext_clock.scan_divisor;			break;		default:	// should never happen			comedi_error( dev, "bug! failed to set ai pacing!" );			divisor = 1000;			break;	}	// supposed to load counter with desired divisor minus 2 for 4020	return divisor / TIMER_BASE - 2;}static void select_master_clock_4020( comedi_device *dev, const comedi_cmd *cmd ){	int chanspec = priv(dev)->ext_clock.chanspec;	// select internal/external master clock	priv(dev)->hw_config_bits &= ~MASTER_CLOCK_4020_MASK;	if( cmd->scan_begin_src == TRIG_OTHER )	{		if( CR_CHAN( chanspec ) == bnc_trigger_channel_4020 )			priv(dev)->hw_config_bits |= BNC_CLOCK_4020_BITS;		else			priv(dev)->hw_config_bits |= EXT_CLOCK_4020_BITS;	}else	{		priv(dev)->hw_config_bits |= INTERNAL_CLOCK_4020_BITS;	}	writew(priv(dev)->hw_config_bits, priv(dev)->main_iobase + HW_CONFIG_REG);}static void select_master_clock( comedi_device *dev, const comedi_cmd *cmd ){	switch( board(dev)->layout )	{		case LAYOUT_4020:			select_master_clock_4020( dev, cmd );			break;		default:			break;	}}static void set_ai_pacing( comedi_device *dev, comedi_cmd *cmd ){	uint32_t convert_counter = 0, scan_counter = 0;	check_adc_timing( cmd );	select_master_clock( dev, cmd );	if( board(dev)->layout == LAYOUT_4020 )	{		convert_counter = ai_convert_counter_4020( dev, cmd );	}else	{		convert_counter = ai_convert_counter_6xxx( dev, cmd );		scan_counter = ai_scan_counter_6xxx( dev, cmd );	}	// load lower 16 bits of convert interval	writew( convert_counter & 0xffff, priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG );	DEBUG_PRINT("convert counter 0x%x\n", convert_counter );	// load upper 8 bits of convert interval	writew( ( convert_counter >> 16 ) & 0xff,		priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG );	// load lower 16 bits of scan delay	writew( scan_counter & 0xffff, priv(dev)->main_iobase + ADC_DELAY_INTERVAL_LOWER_REG );	// load upper 8 bits of scan delay	writew( ( scan_counter >> 16 ) & 0xff,		priv(dev)->main_iobase + ADC_DELAY_INTERVAL_UPPER_REG );	DEBUG_PRINT("scan counter 0x%x\n", scan_counter );}static int ai_cmd(comedi_device *dev,comedi_subdevice *s){	comedi_async *async = s->async;	comedi_cmd *cmd = &async->cmd;	uint32_t bits;	unsigned int i;	unsigned long flags;	disable_ai_pacing( dev );	// make sure internal calibration source is turned off	writew(0, priv(dev)->main_iobase + CALIBRATION_REG);	set_ai_pacing( dev, cmd );	setup_sample_counters( dev, cmd );	if(board(dev)->layout != LAYOUT_4020)	{		// use external queue		priv(dev)->hw_config_bits |= EXT_QUEUE_BIT;		writew(priv(dev)->hw_config_bits, priv(dev)->main_iobase + HW_CONFIG_REG);		/* XXX cannot write to queue fifo while dac fifo is being written to		* ( need spinlock, or try to use internal queue instead */		// clear queue pointer		writew(0, priv(dev)->main_iobase + ADC_QUEUE_CLEAR_REG);		// load external queue		for(i = 0; i < cmd->chanlist_len; i++)		{			bits = 0;			// set channel			bits |= adc_chan_bits( CR_CHAN( cmd->chanlist[i] ) );			// set gain			bits |= ai_range_bits_6xxx( dev, CR_RANGE( cmd->chanlist[i] ) );			// set single-ended / differential			if( ( board(dev)->layout == LAYOUT_64XX && CR_AREF(cmd->chanlist[i]) != AREF_DIFF ) ||				( board(dev)->layout == LAYOUT_60XX && CR_AREF(cmd->chanlist[i]) == AREF_DIFF ) )				bits |= ADC_SE_DIFF_BIT;			if(CR_AREF(cmd->chanlist[i]) == AREF_COMMON)				bits |= ADC_COMMON_BIT;			// mark end of queue			if(i == cmd->chanlist_len - 1)				bits |= QUEUE_EOSCAN_BIT | QUEUE_EOSEQ_BIT;			writew(bits, priv(dev)->main_iobase + ADC_QUEUE_FIFO_REG);		}		// prime queue holding register		writew(0, priv(dev)->main_iobase + ADC_QUEUE_LOAD_REG);	}else	{		uint8_t old_cal_range_bits = priv(dev)->i2c_cal_range_bits;		priv(dev)->i2c_cal_range_bits &= ~ADC_SR

⌨️ 快捷键说明

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