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

📄 ni_at_a2150.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	if(dev->iobase)	{		// put board in power-down mode		outw(APD_BIT | DPD_BIT, dev->iobase + CONFIG_REG);		release_region(dev->iobase, A2150_SIZE);	}	if(dev->irq)		comedi_free_irq(dev->irq, dev);	if(devpriv)	{		if(devpriv->dma)			free_dma(devpriv->dma);		if(devpriv->dma_buffer)			kfree(devpriv->dma_buffer);	}	return 0;};static int a2150_cancel(comedi_device *dev, comedi_subdevice *s){	// disable dma on card	devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT;	outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);	// disable computer's dma	disable_dma(devpriv->dma);	// clear fifo and reset triggering circuitry	outw(0, dev->iobase + FIFO_RESET_REG);	return 0;}static int a2150_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd){	int err = 0;	int tmp;	int startChan;	int i;	/* 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;	if(!cmd->scan_begin_src || tmp != cmd->scan_begin_src) err++;	tmp = cmd->convert_src;	cmd->convert_src &= TRIG_NOW;	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 */	if(cmd->start_src != TRIG_NOW &&		cmd->start_src != TRIG_EXT) 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_arg != 0)	{		cmd->start_arg = 0;		err++;	}	if(cmd->convert_src == TRIG_TIMER)	{		if(cmd->convert_arg < thisboard->ai_speed)		{			cmd->convert_arg = thisboard->ai_speed;			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++;	}	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)return 3;	/* step 4: fix up any arguments */	if(cmd->scan_begin_src == TRIG_TIMER)	{		tmp = cmd->scan_begin_arg;		a2150_get_timing(dev, &cmd->scan_begin_arg, cmd->flags);		if(tmp != cmd->scan_begin_arg) err++;	}	if(err)return 4;	// check channel/gain list against card's limitations	if(cmd->chanlist)	{		startChan = CR_CHAN(cmd->chanlist[0]);		for(i = 1; i < cmd->chanlist_len; i++)		{			if(CR_CHAN(cmd->chanlist[i]) != (startChan + i))			{				comedi_error(dev, "entries in chanlist must be consecutive channels, counting upwards\n");				err++;			}		}		if(cmd->chanlist_len == 2 && CR_CHAN(cmd->chanlist[0]) == 1)		{			comedi_error(dev, "length 2 chanlist must be channels 0,1 or channels 2,3");			err++;		}		if(cmd->chanlist_len == 3)		{			comedi_error(dev, "chanlist must have 1,2 or 4 channels");			err++;		}		if(CR_AREF(cmd->chanlist[0]) != CR_AREF(cmd->chanlist[1]) ||			CR_AREF(cmd->chanlist[2]) != CR_AREF(cmd->chanlist[3]))		{			comedi_error(dev, "channels 0/1 and 2/3 must have the same analog reference");			err++;		}	}	if(err)return 5;	return 0;}static int a2150_ai_cmd(comedi_device *dev, comedi_subdevice *s){	comedi_async *async = s->async;	comedi_cmd *cmd = &async->cmd;	unsigned long lock_flags;	unsigned int old_config_bits = devpriv->config_bits;	unsigned int trigger_bits;	if(!dev->irq || !devpriv->dma)	{		comedi_error(dev, " irq and dma required, cannot do hardware conversions");		return -1;	}	if(cmd->flags & TRIG_RT)	{		comedi_error(dev, " dma incompatible with hard real-time interrupt (TRIG_RT), aborting");		return -1;	}	// clear fifo and reset triggering circuitry	outw(0, dev->iobase + FIFO_RESET_REG);	/* setup chanlist */	if(a2150_set_chanlist(dev, CR_CHAN(cmd->chanlist[0]), cmd->chanlist_len) < 0)		return -1;	// setup ac/dc coupling	if(CR_AREF(cmd->chanlist[0]) == AREF_OTHER)		devpriv->config_bits |= AC0_BIT;	else		devpriv->config_bits &= ~AC0_BIT;	if(CR_AREF(cmd->chanlist[2]) == AREF_OTHER)		devpriv->config_bits |= AC1_BIT;	else		devpriv->config_bits &= ~AC1_BIT;	// setup timing	a2150_get_timing(dev, &cmd->scan_begin_arg, cmd->flags);	// send timing, channel, config bits	outw(devpriv->config_bits, dev->iobase + CONFIG_REG);	// initialize number of samples remaining	devpriv->count = cmd->stop_arg * cmd->chanlist_len;	// enable computer's dma	lock_flags = claim_dma_lock();	disable_dma(devpriv->dma);	/* clear flip-flop to make sure 2-byte registers for	 * count and address get set correctly */	clear_dma_ff(devpriv->dma);	set_dma_addr(devpriv->dma, virt_to_bus(devpriv->dma_buffer));	// set size of transfer to fill in 1/3 second#define ONE_THIRD_SECOND 333333333	devpriv->dma_transfer_size = sizeof(devpriv->dma_buffer[0]) * cmd->chanlist_len *		ONE_THIRD_SECOND / cmd->scan_begin_arg;	if(devpriv->dma_transfer_size > A2150_DMA_BUFFER_SIZE)		devpriv->dma_transfer_size = A2150_DMA_BUFFER_SIZE;	if(devpriv->dma_transfer_size < sizeof(devpriv->dma_buffer[0]))		devpriv->dma_transfer_size = sizeof(devpriv->dma_buffer[0]);	devpriv->dma_transfer_size -= devpriv->dma_transfer_size % sizeof(devpriv->dma_buffer[0]);	set_dma_count(devpriv->dma, devpriv->dma_transfer_size);	enable_dma(devpriv->dma);	release_dma_lock(lock_flags); 	/* clear dma interrupt before enabling it, to try and get rid of that	 * one spurious interrupt that has been happening */	outw(0x00, dev->iobase + DMA_TC_CLEAR_REG);	// enable dma on card	devpriv->irq_dma_bits |= DMA_INTR_EN_BIT | DMA_EN_BIT;	outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);	// may need to wait 72 sampling periods if timing was changed	i8254_load(dev->iobase + I8253_BASE_REG, 2, 72, 0);	// setup start triggering	trigger_bits = 0;	// decide if we need to wait 72 periods for valid data	if(cmd->start_src == TRIG_NOW &&		(old_config_bits & CLOCK_MASK) != (devpriv->config_bits & CLOCK_MASK))	{		// set trigger source to delay trigger		trigger_bits |= DELAY_TRIGGER_BITS;	}else	{		// otherwise no delay		trigger_bits |= POST_TRIGGER_BITS;	}	// enable external hardware trigger	if(cmd->start_src == TRIG_EXT)	{		trigger_bits |= HW_TRIG_EN;	}else if(cmd->start_src == TRIG_OTHER)	{		// XXX add support for level/slope start trigger using TRIG_OTHER		comedi_error(dev, "you shouldn't see this?");	}	// send trigger config bits	outw(trigger_bits, dev->iobase + TRIGGER_REG);	// start aquisition for soft trigger	if(cmd->start_src == TRIG_NOW)	{		outw(0, dev->iobase + FIFO_START_REG);	}#ifdef A2150_DEBUG	ni_dump_regs(dev);#endif	return 0;}static int a2150_ai_rinsn(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data){	unsigned int i, n;	static const int timeout = 100000;	static const int filter_delay = 36;	// clear fifo and reset triggering circuitry	outw(0, dev->iobase + FIFO_RESET_REG);	/* setup chanlist */	if(a2150_set_chanlist(dev, CR_CHAN(insn->chanspec), 1) < 0)		return -1;	// set dc coupling	devpriv->config_bits &= ~AC0_BIT;	devpriv->config_bits &= ~AC1_BIT;	// send timing, channel, config bits	outw(devpriv->config_bits, dev->iobase + CONFIG_REG);	// disable dma on card	devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT;	outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);	// setup start triggering	outw(0, dev->iobase + TRIGGER_REG);	// start aquisition for soft trigger	outw(0, dev->iobase + FIFO_START_REG);	/* there is a 35.6 sample delay for data to get through the antialias filter */ 	for(n = 0; n < filter_delay; n++)	{		for(i = 0; i < timeout; i++)		{			if(inw(dev->iobase + STATUS_REG) & FNE_BIT)				break;			comedi_udelay(1);		}		if(i == timeout)		{			comedi_error(dev, "timeout");			return -ETIME;		}		inw(dev->iobase + FIFO_DATA_REG);	}	// read data 	for(n = 0; n < insn->n; n++)	{		for(i = 0; i < timeout; i++)		{			if(inw(dev->iobase + STATUS_REG) & FNE_BIT)				break;			comedi_udelay(1);		}		if(i == timeout)		{			comedi_error(dev, "timeout");			return -ETIME;		}#ifdef A2150_DEBUG	ni_dump_regs(dev);#endif		data[n] = inw(dev->iobase + FIFO_DATA_REG);#ifdef A2150_DEBUG	rt_printk(" data is %i\n", data[n]);#endif		data[n] ^= 0x8000;	}	// clear fifo and reset triggering circuitry	outw(0, dev->iobase + FIFO_RESET_REG);	return n;}/* sets bits in devpriv->clock_bits to nearest approximation of requested period, * adjusts requested period to actual timing. */static int a2150_get_timing(comedi_device *dev, unsigned int *period, int flags){	int lub, glb, temp;	int lub_divisor_shift, lub_index, glb_divisor_shift, glb_index;	int i, j;	// initialize greatest lower and least upper bounds	lub_divisor_shift = 3;	lub_index = 0;	lub = thisboard->clock[lub_index] * (1 << lub_divisor_shift);	glb_divisor_shift = 0;	glb_index = thisboard->num_clocks - 1;	glb = thisboard->clock[glb_index] * (1 << glb_divisor_shift);	// make sure period is in available range	if(*period < glb)		*period = glb;	if(*period > lub)		*period = lub;	// we can multiply period by 1, 2, 4, or 8, using (1 << i)	for(i = 0; i < 4; i = i++)	{		// there are a maximum of 4 master clocks		for(j = 0; j < thisboard->num_clocks; j++)		{			// temp is the period in nanosec we are evaluating			temp = thisboard->clock[j] * (1 << i);			// if it is the best match yet			if(temp < lub && temp >= *period)			{				lub_divisor_shift = i;				lub_index = j;				lub = temp;			}			if(temp > glb && temp <= *period)			{				glb_divisor_shift = i;				glb_index = j;				glb = temp;			}		}	}	flags &= TRIG_ROUND_MASK;	switch (flags)	{		case TRIG_ROUND_NEAREST:		default:			// if least upper bound is better approximation			if(lub - *period < *period - glb)			{				*period = lub;			}else			{				*period = glb;			}			break;		case TRIG_ROUND_UP:				*period = lub;			break;		case TRIG_ROUND_DOWN:				*period = glb;			break;	}	// set clock bits for config register appropriately	devpriv->config_bits &= ~CLOCK_MASK;	if(*period == lub)	{		devpriv->config_bits |= CLOCK_SELECT_BITS(lub_index) | CLOCK_DIVISOR_BITS(lub_divisor_shift);	}else	{		devpriv->config_bits |= CLOCK_SELECT_BITS(glb_index) | CLOCK_DIVISOR_BITS(glb_divisor_shift);	}	return 0;}static int a2150_set_chanlist(comedi_device *dev, unsigned int start_channel, unsigned int num_channels){	if(start_channel + num_channels > 4)		return -1;	devpriv->config_bits &= ~CHANNEL_MASK;	switch(num_channels)	{		case 1:			devpriv->config_bits |= CHANNEL_BITS(0x4 | start_channel);			break;		case 2:			if(start_channel == 0)			{				devpriv->config_bits |= CHANNEL_BITS(0x2);			}else if(start_channel == 2)			{				devpriv->config_bits |= CHANNEL_BITS(0x3);			}else			{				return -1;			}			break;		case 4:			devpriv->config_bits |= CHANNEL_BITS(0x1);			break;		default:			return -1;			break;	}	return 0;}

⌨️ 快捷键说明

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