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

📄 ni_labpc.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	range = CR_RANGE( cmd->chanlist[ 0 ] );	aref = CR_AREF( cmd->chanlist[ 0 ] );	for( i = 0; i < cmd->chanlist_len; i++ )	{		switch( mode )		{			case MODE_SINGLE_CHAN_INTERVAL:				if( CR_CHAN( cmd->chanlist[ i ] ) != channel )				{					comedi_error(dev, "channel scanning order specified in chanlist is not supported by hardware.\n");					return 1;				}				break;			case MODE_MULT_CHAN_UP:				if( CR_CHAN( cmd->chanlist[ i ] ) != i )				{					comedi_error(dev, "channel scanning order specified in chanlist is not supported by hardware.\n");					return 1;				}				break;			case MODE_MULT_CHAN_DOWN:				if( CR_CHAN( cmd->chanlist[i] ) !=					cmd->chanlist_len - i - 1 )				{					comedi_error(dev, "channel scanning order specified in chanlist is not supported by hardware.\n");					return 1;				}				break;			default:				rt_printk( "ni_labpc: bug! in chanlist check\n");				return 1;				break;		}		if( CR_RANGE( cmd->chanlist[i] ) != range )		{			comedi_error(dev, "entries in chanlist must all have the same range\n");			return 1;		}		if( CR_AREF( cmd->chanlist[i] ) != aref )		{			comedi_error(dev, "entries in chanlist must all have the same reference\n");			return 1;		}	}	return 0;}static int labpc_use_continuous_mode( const comedi_cmd *cmd ){	if( labpc_ai_scan_mode( cmd ) == MODE_SINGLE_CHAN ) return 1;	if( cmd->scan_begin_src == TRIG_FOLLOW ) return 1;	return 0;}static unsigned int labpc_ai_convert_period( const comedi_cmd *cmd ){	if( cmd->convert_src != TRIG_TIMER ) return 0;	if( labpc_ai_scan_mode( cmd ) == MODE_SINGLE_CHAN &&		cmd->scan_begin_src == TRIG_TIMER )		return cmd->scan_begin_arg;	return cmd->convert_arg;}static void labpc_set_ai_convert_period( comedi_cmd *cmd, unsigned int ns ){	if( cmd->convert_src != TRIG_TIMER ) return;	if( labpc_ai_scan_mode( cmd ) == MODE_SINGLE_CHAN &&		cmd->scan_begin_src == TRIG_TIMER )	{		cmd->scan_begin_arg = ns;		if( cmd->convert_arg > cmd->scan_begin_arg )			cmd->convert_arg = cmd->scan_begin_arg;	}else		cmd->convert_arg = ns;}static unsigned int labpc_ai_scan_period( const comedi_cmd *cmd ){	if( cmd->scan_begin_src != TRIG_TIMER ) return 0;	if( labpc_ai_scan_mode( cmd ) == MODE_SINGLE_CHAN &&		cmd->convert_src == TRIG_TIMER )		return 0;	return cmd->scan_begin_arg;}static void labpc_set_ai_scan_period( comedi_cmd *cmd, unsigned int ns ){	if( cmd->scan_begin_src != TRIG_TIMER ) return;	if( labpc_ai_scan_mode( cmd ) == MODE_SINGLE_CHAN &&		cmd->convert_src == TRIG_TIMER )		return;	cmd->scan_begin_arg = ns;}static int labpc_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd){	int err = 0;	int tmp, tmp2;	int stop_mask;	/* 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;	cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT;	if(!cmd->scan_begin_src || tmp != cmd->scan_begin_src) err++;	tmp = cmd->convert_src;	cmd->convert_src &= TRIG_TIMER | TRIG_EXT;	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;	stop_mask = TRIG_COUNT | TRIG_NONE;	if(thisboard->register_layout == labpc_1200_layout)		stop_mask |= TRIG_EXT;	cmd->stop_src &= stop_mask;	if(!cmd->stop_src || tmp!=cmd->stop_src) err++;	if(err) return 1;	/* step 2: make sure trigger sources are unique and mutually compatible */	if(cmd->start_src != TRIG_NOW &&		cmd->start_src != TRIG_EXT) err++;	if(cmd->scan_begin_src != TRIG_TIMER &&		cmd->scan_begin_src != TRIG_FOLLOW &&		cmd->scan_begin_src != TRIG_EXT) err++;	if(cmd->convert_src != TRIG_TIMER &&	   cmd->convert_src != TRIG_EXT) err++;	if(cmd->stop_src != TRIG_COUNT &&		cmd->stop_src != TRIG_EXT &&		cmd->stop_src != TRIG_NONE) err++;	// can't have external stop and start triggers at once	if(cmd->start_src == TRIG_EXT &&		cmd->stop_src == TRIG_EXT) err++;	if(err)return 2;	/* step 3: make sure arguments are trivially compatible */	if(cmd->start_arg == TRIG_NOW && cmd->start_arg != 0)	{		cmd->start_arg = 0;		err++;	}	if(!cmd->chanlist_len)	{		err++;	}	if(cmd->scan_end_arg != cmd->chanlist_len)	{		cmd->scan_end_arg = cmd->chanlist_len;		err++;	}	if(cmd->convert_src == TRIG_TIMER)	{		if(cmd->convert_arg < thisboard->ai_speed)		{			cmd->convert_arg = thisboard->ai_speed;			err++;		}	}	// make sure scan timing is not too fast	if(cmd->scan_begin_src == TRIG_TIMER)	{		if(cmd->convert_src == TRIG_TIMER &&			cmd->scan_begin_arg < cmd->convert_arg * cmd->chanlist_len)		{			cmd->scan_begin_arg = cmd->convert_arg * cmd->chanlist_len;			err++;		}		if(cmd->scan_begin_arg < thisboard->ai_speed * cmd->chanlist_len)		{			cmd->scan_begin_arg = thisboard->ai_speed * cmd->chanlist_len;			err++;		}	}	// stop source	switch(cmd->stop_src)	{		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;		// TRIG_EXT doesn't care since it doesn't trigger off a numbered channel		default:			break;	}	if(err)return 3;	/* step 4: fix up any arguments */	tmp = cmd->convert_arg;	tmp2 = cmd->scan_begin_arg;	labpc_adc_timing(dev, cmd);	if(tmp != cmd->convert_arg ||		tmp2 != cmd->scan_begin_arg) err++;	if(err)return 4;	if( labpc_ai_chanlist_invalid( dev, cmd ) )		return 5;	return 0;}static int labpc_ai_cmd(comedi_device *dev, comedi_subdevice *s){	int channel, range, aref;	unsigned long irq_flags;	int ret;	comedi_async *async = s->async;	comedi_cmd *cmd = &async->cmd;	enum transfer_type xfer;	unsigned long flags;	if(!dev->irq)	{		comedi_error(dev, "no irq assigned, cannot perform command");		return -1;	}	range = CR_RANGE(cmd->chanlist[0]);	aref = CR_AREF(cmd->chanlist[0]);	// make sure board is disabled before setting up aquisition	comedi_spin_lock_irqsave( &dev->spinlock, flags );	devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT;	thisboard->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);	comedi_spin_unlock_irqrestore( &dev->spinlock, flags );	devpriv->command3_bits = 0;	thisboard->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);	// initialize software conversion count	if(cmd->stop_src == TRIG_COUNT)	{		devpriv->count = cmd->stop_arg * cmd->chanlist_len;	}	// setup hardware conversion counter	if(cmd->stop_src == TRIG_EXT)	{		// load counter a1 with count of 3 (pc+ manual says this is minimum allowed) using mode 0		ret = i8254_load(dev->iobase + COUNTER_A_BASE_REG, 1, 3, 0);		if(ret < 0)		{			comedi_error(dev, "error loading counter a1");			return -1;		}	}else	// otherwise, just put a1 in mode 0 with no count to set its output low		thisboard->write_byte(INIT_A1_BITS, dev->iobase + COUNTER_A_CONTROL_REG);	// figure out what method we will use to transfer data	if(devpriv->dma_chan &&	// need a dma channel allocated		// dma unsafe at RT priority, and too much setup time for TRIG_WAKE_EOS for		(cmd->flags & (TRIG_WAKE_EOS | TRIG_RT)) == 0 &&		// only available on the isa boards		thisboard->bustype == isa_bustype)	{		xfer = isa_dma_transfer;	}else if(thisboard->register_layout == labpc_1200_layout &&	// pc-plus has no fifo-half full interrupt		// wake-end-of-scan should interrupt on fifo not empty		(cmd->flags & TRIG_WAKE_EOS) == 0 &&		// make sure we are taking more than just a few points		(cmd->stop_src != TRIG_COUNT || devpriv->count > 256))	{		xfer = fifo_half_full_transfer;	}else		xfer = fifo_not_empty_transfer;	devpriv->current_transfer = xfer;	// setup command6 register for 1200 boards	if(thisboard->register_layout == labpc_1200_layout)	{		// reference inputs to ground or common?		if(aref != AREF_GROUND)			devpriv->command6_bits |= ADC_COMMON_BIT;		else			devpriv->command6_bits &= ~ADC_COMMON_BIT;		// bipolar or unipolar range?		if(thisboard->ai_range_is_unipolar[range])			devpriv->command6_bits |= ADC_UNIP_BIT;		else			devpriv->command6_bits &= ~ADC_UNIP_BIT;		// interrupt on fifo half full?		if(xfer == fifo_half_full_transfer)			devpriv->command6_bits |= ADC_FHF_INTR_EN_BIT;		else			devpriv->command6_bits &= ~ADC_FHF_INTR_EN_BIT;		// enable interrupt on counter a1 terminal count?		if(cmd->stop_src == TRIG_EXT)			devpriv->command6_bits |= A1_INTR_EN_BIT;		else			devpriv->command6_bits &= ~A1_INTR_EN_BIT;		// are we scanning up or down through channels?		if( labpc_ai_scan_mode( cmd ) == MODE_MULT_CHAN_UP )			devpriv->command6_bits |= ADC_SCAN_UP_BIT;		else			devpriv->command6_bits &= ~ADC_SCAN_UP_BIT;		// write to register		thisboard->write_byte(devpriv->command6_bits, dev->iobase + COMMAND6_REG);	}	/* setup channel list, etc (command1 register) */	devpriv->command1_bits = 0;	if( labpc_ai_scan_mode( cmd ) == MODE_MULT_CHAN_UP )		channel = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]);	else		channel = CR_CHAN(cmd->chanlist[0]);	// munge channel bits for differential / scan disabled mode	if( labpc_ai_scan_mode( cmd ) != MODE_SINGLE_CHAN && aref == AREF_DIFF )		channel *= 2;	devpriv->command1_bits |= ADC_CHAN_BITS(channel);	devpriv->command1_bits |= thisboard->ai_range_code[range];	thisboard->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG);	// manual says to set scan enable bit on second pass	if( labpc_ai_scan_mode( cmd ) == MODE_MULT_CHAN_UP ||		labpc_ai_scan_mode( cmd ) == MODE_MULT_CHAN_DOWN )	{		devpriv->command1_bits |= ADC_SCAN_EN_BIT;		/* need a brief delay before enabling scan, or scan list will get screwed when you switch		 * between scan up to scan down mode - dunno why */		comedi_udelay(1);		thisboard->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG);	}	// setup any external triggering/pacing (command4 register)	devpriv->command4_bits = 0;	if(cmd->convert_src != TRIG_EXT)		devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT;	/* XXX should discard first scan when using interval scanning	 * since manual says it is not synced with scan clock */	if( labpc_use_continuous_mode( cmd ) == 0 )	{		devpriv->command4_bits |= INTERVAL_SCAN_EN_BIT;		if( cmd->scan_begin_src == TRIG_EXT )			devpriv->command4_bits |= EXT_SCAN_EN_BIT;	}	// single-ended/differential	if(aref == AREF_DIFF)		devpriv->command4_bits |= ADC_DIFF_BIT;	thisboard->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG);	thisboard->write_byte( cmd->chanlist_len, dev->iobase + INTERVAL_COUNT_REG);	// load count	thisboard->write_byte(INTERVAL_LOAD_BITS, dev->iobase + INTERVAL_LOAD_REG);	if(cmd->convert_src == TRIG_TIMER || cmd->scan_begin_src == TRIG_TIMER)	{		// set up pacing		labpc_adc_timing(dev, cmd);		// load counter b0 in mode 3		ret = i8254_load(dev->iobase + COUNTER_B_BASE_REG, 0, devpriv->divisor_b0, 3);		if(ret < 0)		{			comedi_error(dev, "error loading counter b0");			return -1;		}	}	// set up conversion pacing	if( labpc_ai_convert_period( cmd ) )	{		// load counter a0 in mode 2		ret = i8254_load(dev->iobase + COUNTER_A_BASE_REG, 0, devpriv->divisor_a0, 2);		if(ret < 0)		{			comedi_error(dev, "error loading counter a0");			return -1;		}	}else		thisboard->write_byte(INIT_A0_BITS, dev->iobase + COUNTER_A_CONTROL_REG);	// set up scan pacing	if( labpc_ai_scan_period( cmd ) )	{		// load counter b1 in mode 2		ret = i8254_load(dev->iobase + COUNTER_B_BASE_REG, 1, devpriv->divisor_b1, 2);		if(ret < 0)		{			comedi_error(dev, "error loading counter b1");			return -1;		}	}	labpc_clear_adc_fifo( dev );	// set up dma transfer	if(xfer == isa_dma_transfer)	{		irq_flags = claim_dma_lock();		disable_dma(devpriv->dma_chan);		/* clear flip-flop to make sure 2-byte registers for		* count and address get set correctly */		clear_dma_ff(devpriv->dma_chan);		set_dma_addr(devpriv->dma_chan, virt_to_bus(devpriv->dma_buffer));		// set appropriate size of transfer		devpriv->dma_transfer_size = labpc_suggest_transfer_size(*cmd);		if(cmd->stop_src == TRIG_COUNT &&

⌨️ 快捷键说明

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