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

📄 ni_labpc.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			devpriv->count * sample_size < devpriv->dma_transfer_size)		{			devpriv->dma_transfer_size = devpriv->count * sample_size;		}		set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);		enable_dma(devpriv->dma_chan);		release_dma_lock(irq_flags);		// enable board's dma		devpriv->command3_bits |= DMA_EN_BIT | DMATC_INTR_EN_BIT;	}else		devpriv->command3_bits &= ~DMA_EN_BIT & ~DMATC_INTR_EN_BIT;	// enable error interrupts	devpriv->command3_bits |= ERR_INTR_EN_BIT;	// enable fifo not empty interrupt?	if(xfer == fifo_not_empty_transfer)		devpriv->command3_bits |= ADC_FNE_INTR_EN_BIT;	else		devpriv->command3_bits &= ~ADC_FNE_INTR_EN_BIT;	thisboard->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);	// startup aquisition	// command2 reg	// use 2 cascaded counters for pacing	comedi_spin_lock_irqsave( &dev->spinlock, flags );	devpriv->command2_bits |= CASCADE_BIT;	switch(cmd->start_src)	{		case TRIG_EXT:			devpriv->command2_bits |= HWTRIG_BIT;			devpriv->command2_bits &= ~PRETRIG_BIT & ~SWTRIG_BIT;			break;		case TRIG_NOW:			devpriv->command2_bits |= SWTRIG_BIT;			devpriv->command2_bits &= ~PRETRIG_BIT & ~HWTRIG_BIT;			break;		default:			comedi_error(dev, "bug with start_src");			return -1;			break;	}	switch(cmd->stop_src)	{		case TRIG_EXT:			devpriv->command2_bits |= HWTRIG_BIT | PRETRIG_BIT;			break;		case TRIG_COUNT:		case TRIG_NONE:			break;		default:			comedi_error(dev, "bug with stop_src");			return -1;	}	thisboard->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);	comedi_spin_unlock_irqrestore( &dev->spinlock, flags );	return 0;}/* interrupt service routine */static void labpc_interrupt(int irq, void *d, struct pt_regs *regs){	comedi_device *dev = d;	comedi_subdevice *s = dev->read_subdev;	comedi_async *async;	comedi_cmd *cmd;	if(dev->attached == 0)	{		comedi_error(dev, "premature interrupt");		return;	}	async = s->async;	cmd = &async->cmd;	async->events = 0;	// read board status	devpriv->status1_bits = thisboard->read_byte(dev->iobase + STATUS1_REG);	if(thisboard->register_layout == labpc_1200_layout)		devpriv->status2_bits = thisboard->read_byte(dev->iobase + STATUS2_REG);	if((devpriv->status1_bits & (DMATC_BIT | TIMER_BIT | OVERFLOW_BIT | OVERRUN_BIT | DATA_AVAIL_BIT)) == 0 &&		(devpriv->status2_bits & A1_TC_BIT) == 0 &&		(devpriv->status2_bits & FNHF_BIT))	{		return;	}	if(devpriv->status1_bits & OVERRUN_BIT)	{		// clear error interrupt		thisboard->write_byte(0x1, dev->iobase + ADC_CLEAR_REG);		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;		comedi_event(dev, s, async->events);		comedi_error(dev, "overrun");		return;	}	if(devpriv->current_transfer == isa_dma_transfer)	{		// if a dma terminal count of external stop trigger has occurred		if(devpriv->status1_bits & DMATC_BIT ||			(thisboard->register_layout == labpc_1200_layout && devpriv->status2_bits & A1_TC_BIT))		{			handle_isa_dma(dev);		}	}else labpc_drain_fifo(dev);	if(devpriv->status1_bits & TIMER_BIT)	{		comedi_error(dev, "handled timer interrupt?");		// clear it		thisboard->write_byte(0x1, dev->iobase + TIMER_CLEAR_REG);	}	if(devpriv->status1_bits & OVERFLOW_BIT)	{		// clear error interrupt		thisboard->write_byte(0x1, dev->iobase + ADC_CLEAR_REG);		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;		comedi_error(dev, "overflow");		return;	}	// handle external stop trigger	if(cmd->stop_src == TRIG_EXT)	{		if(devpriv->status2_bits & A1_TC_BIT)		{			labpc_drain_dregs(dev);			labpc_cancel(dev, s);			async->events |= COMEDI_CB_EOA;		}	}	/* TRIG_COUNT end of acquisition */	if(cmd->stop_src == TRIG_COUNT)	{		if(devpriv->count == 0)		{			labpc_cancel(dev, s);			async->events |= COMEDI_CB_EOA;		}	}	comedi_event(dev, s, async->events);}// read all available samples from ai fifostatic int labpc_drain_fifo(comedi_device *dev){	unsigned int lsb, msb;	sampl_t data;	comedi_async *async = dev->read_subdev->async;	const int timeout = 10000;	unsigned int i;	devpriv->status1_bits = thisboard->read_byte(dev->iobase + STATUS1_REG);	for(i = 0; (devpriv->status1_bits & DATA_AVAIL_BIT) && i < timeout; i++)	{		// quit if we have all the data we want		if(async->cmd.stop_src == TRIG_COUNT)		{			if(devpriv->count == 0) break;			devpriv->count--;		}		lsb = thisboard->read_byte(dev->iobase + ADC_FIFO_REG);		msb = thisboard->read_byte(dev->iobase + ADC_FIFO_REG);		data = (msb << 8) | lsb;		cfc_write_to_buffer( dev->read_subdev, data );		devpriv->status1_bits = thisboard->read_byte(dev->iobase + STATUS1_REG);	}	if(i == timeout)	{		comedi_error(dev, "ai timeout, fifo never empties");		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;		return -1;	}	return 0;}static void labpc_drain_dma(comedi_device *dev){	comedi_subdevice *s = dev->read_subdev;	comedi_async *async = s->async;	int status;	unsigned long flags;	unsigned int max_points, num_points, residue, leftover;	int i;	status = devpriv->status1_bits;	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);	// figure out how many points to read	max_points = devpriv->dma_transfer_size  / sample_size;	/* residue is the number of points left to be done on the dma	* transfer.  It should always be zero at this point unless	* the stop_src is set to external triggering.	*/	residue = get_dma_residue(devpriv->dma_chan) / sample_size;	num_points = max_points - residue;	if(devpriv->count < num_points &&		async->cmd.stop_src == TRIG_COUNT)		num_points = devpriv->count;	// figure out how many points will be stored next time	leftover = 0;	if(async->cmd.stop_src != TRIG_COUNT)	{		leftover = devpriv->dma_transfer_size / sample_size;	}else if(devpriv->count > num_points)	{		leftover = devpriv->count - num_points;		if(leftover > max_points)			leftover = max_points;	}	/* write data to comedi buffer */	for( i = 0; i < num_points; i++)	{		cfc_write_to_buffer( s, devpriv->dma_buffer[i] );	}	if(async->cmd.stop_src == TRIG_COUNT) devpriv->count -= num_points;	// set address and count for next transfer	set_dma_addr(devpriv->dma_chan, virt_to_bus(devpriv->dma_buffer));	set_dma_count(devpriv->dma_chan, leftover * sample_size);	release_dma_lock(flags);	async->events |= COMEDI_CB_BLOCK;}static void handle_isa_dma(comedi_device *dev){	labpc_drain_dma(dev);	enable_dma(devpriv->dma_chan);	// clear dma tc interrupt	thisboard->write_byte(0x1, dev->iobase + DMATC_CLEAR_REG);}/* makes sure all data aquired by board is transfered to comedi (used * when aquisition is terminated by stop_src == TRIG_EXT). */static void labpc_drain_dregs(comedi_device *dev){	if(devpriv->current_transfer == isa_dma_transfer)		labpc_drain_dma(dev);	labpc_drain_fifo(dev);}static int labpc_ai_rinsn(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data){ 	int i, n;	int chan, range;	int lsb, msb;	int timeout = 1000;	unsigned long flags;	// disable timed conversions	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 );	// disable interrupt generation and dma	devpriv->command3_bits = 0;	thisboard->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);		/* set gain and channel */	devpriv->command1_bits = 0;	chan = CR_CHAN(insn->chanspec);	range = CR_RANGE(insn->chanspec);	devpriv->command1_bits |= thisboard->ai_range_code[range];	// munge channel bits for differential/scan disabled mode	if(CR_AREF(insn->chanspec) == AREF_DIFF)		chan *= 2;	devpriv->command1_bits |= ADC_CHAN_BITS(chan);	thisboard->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG);	// setup command6 register for 1200 boards	if(thisboard->register_layout == labpc_1200_layout)	{		// reference inputs to ground or common?		if(CR_AREF(insn->chanspec) != 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;		// don't interrupt on fifo half full		devpriv->command6_bits &= ~ADC_FHF_INTR_EN_BIT;		// don't enable interrupt on counter a1 terminal count?		devpriv->command6_bits &= ~A1_INTR_EN_BIT;		// write to register		thisboard->write_byte(devpriv->command6_bits, dev->iobase + COMMAND6_REG);	}	// setup command4 register	devpriv->command4_bits = 0;	devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT;	// single-ended/differential	if(CR_AREF(insn->chanspec) == AREF_DIFF)		devpriv->command4_bits |= ADC_DIFF_BIT;	thisboard->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG);	// initialize pacer counter output to make sure it doesn't cause any problems	thisboard->write_byte(INIT_A0_BITS, dev->iobase + COUNTER_A_CONTROL_REG);	labpc_clear_adc_fifo( dev );	for(n = 0; n < insn->n; n++)	{		/* trigger conversion */		thisboard->write_byte(0x1, dev->iobase + ADC_CONVERT_REG);		for(i = 0; i < timeout; i++)		{			if(thisboard->read_byte(dev->iobase + STATUS1_REG) & DATA_AVAIL_BIT)				break;			comedi_udelay( 1 );		}		if(i == timeout)		{			comedi_error(dev, "timeout");			return -ETIME;		}		lsb = thisboard->read_byte(dev->iobase + ADC_FIFO_REG);		msb = thisboard->read_byte(dev->iobase + ADC_FIFO_REG);		data[n] = (msb << 8) | lsb;	}	return n;}// analog output insnstatic int labpc_ao_winsn(comedi_device *dev, comedi_subdevice *s,	comedi_insn *insn, lsampl_t *data){	int channel, range;	unsigned long flags;	int lsb, msb;	channel = CR_CHAN(insn->chanspec);	// turn off pacing of analog output channel	/* note: hardware bug in daqcard-1200 means pacing cannot	 * be independently enabled/disabled for its the two channels */	comedi_spin_lock_irqsave( &dev->spinlock, flags );	devpriv->command2_bits &= ~DAC_PACED_BIT(channel);	thisboard->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);	comedi_spin_unlock_irqrestore( &dev->spinlock, flags );	// set range	if(thisboard->register_layout == labpc_1200_layout)	{		range = CR_RANGE(insn->chanspec);		if(range & AO_RANGE_IS_UNIPOLAR)			devpriv->command6_bits |= DAC_UNIP_BIT(channel);		else			devpriv->command6_bits &= ~DAC_UNIP_BIT(channel);		// write to register		thisboard->write_byte(devpriv->command6_bits, dev->iobase + COMMAND6_REG);	}	// send data	lsb = data[0] & 0xff;	msb = (data[0] >> 8 ) & 0xff;	thisboard->write_byte(lsb, dev->iobase + DAC_LSB_REG(channel));	thisboard->write_byte(msb, dev->iobase + DAC_MSB_REG(channel));	// remember value for readback	devpriv->ao_value[channel] = data[0];	return 1;}// analog output readback insnstatic int labpc_ao_rinsn(comedi_device *dev, comedi_subdevice *s,	comedi_insn *insn, lsampl_t *data){	data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];	return 1;}static int labpc_calib_read_insn(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data){	data[0] = devpriv->caldac[CR_CHAN(insn->chanspec)];	return 1;}static int labpc_calib_write_insn(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data){	int channel = CR_CHAN(insn->chanspec);	write_caldac( dev, channel, data[ 0 ] );	return 1;}static int labpc_eeprom_read_insn(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data){	data[0] = devpriv->eeprom_data[CR_CHAN(insn->chanspec)];	return 1;}static int labpc_eeprom_write_insn(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data){	int channel = CR_CHAN(insn->chanspec);	int ret;	// only allow writes to user area of eeprom	if(channel < 16 || channel > 127)	{		printk("eeprom writes are only allowed to channels 16 through 127 (the pointer and user areas)");		return -EINVAL;	}	ret = labpc_eeprom_write(dev, channel, data[0]);	if(ret < 0) return ret;

⌨️ 快捷键说明

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