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

📄 ni_mio_common.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*    comedi/drivers/ni_mio_common.c    Hardware driver for DAQ-STC based boards    COMEDI - Linux Control and Measurement Device Interface    Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org>    Copyright (C) 2002, 2003 Frank Mori Hess <fmhess@users.sourceforge.net    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*//*	This file is meant to be included by another file, e.g.,	ni_atmio.c or ni_pcimio.c.	Interrupt support originally added by Truxton Fulton	<trux@truxton.com>	References (from ftp://ftp.natinst.com/support/manuals):	   340747b.pdf  AT-MIO E series Register Level Programmer Manual	   341079b.pdf  PCI E Series RLPM	   340934b.pdf  DAQ-STC reference manual	Other possibly relevant info:	   320517c.pdf  User manual (obsolete)	   320517f.pdf  User manual (new)	   320889a.pdf  delete	   320906c.pdf  maximum signal ratings	   321066a.pdf  about 16x	   321791a.pdf  discontinuation of at-mio-16e-10 rev. c	   321808a.pdf  about at-mio-16e-10 rev P	   321837a.pdf  discontinuation of at-mio-16de-10 rev d	   321838a.pdf  about at-mio-16de-10 rev N	ISSUES:	 - the interrupt routine needs to be cleaned up	 - many printk's need to be changed to rt_printk()*///#define DEBUG_INTERRUPT//#define DEBUG_STATUS_A//#define DEBUG_STATUS_B#include "8255.h"#include "mite.h"#ifndef MDPRINTK#define MDPRINTK(format,args...)#endif/* A timeout count */#define NI_TIMEOUT 1000/* Note: this table must match the ai_gain_* definitions */static short ni_gainlkup[][16]={	/* ai_gain_16 */	{ 0, 1, 2, 3, 4, 5, 6, 7, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105,		0x106, 0x107 },	/* ai_gain_8 */	{ 1, 2, 4, 7, 0x101, 0x102, 0x104, 0x107 },	/* ai_gain_14 */	{ 1, 2, 3, 4, 5, 6, 7, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106,		0x107 },	/* ai_gain_4 */	{ 0, 1, 4, 7 },	/* ai_gain_611x */	{ 0x00a, 0x00b, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006 }};static comedi_lrange range_ni_E_ai={	16, {	RANGE( -10,	10	),	RANGE( -5,	5	),	RANGE( -2.5,	2.5	),	RANGE( -1,	1	),	RANGE( -0.5,	0.5	),	RANGE( -0.25,	0.25	),	RANGE( -0.1,	0.1	),	RANGE( -0.05,	0.05	),	RANGE( 0,	20	),	RANGE( 0,	10	),	RANGE( 0,	5	),	RANGE( 0,	2	),	RANGE( 0,	1	),	RANGE( 0,	0.5	),	RANGE( 0,	0.2	),	RANGE( 0,	0.1	),}};static comedi_lrange range_ni_E_ai_limited={	8, {	RANGE( -10,	10	),	RANGE( -5,	5	),	RANGE( -1,	1	),	RANGE( -0.1,	0.1	),	RANGE( 0,	10	),	RANGE( 0,	5	),	RANGE( 0,	1	),	RANGE( 0,	0.1	),}};static comedi_lrange range_ni_E_ai_limited14={	14, {	RANGE( -10,	10	),	RANGE( -5,	5	),	RANGE( -2,	2	),	RANGE( -1,	1	),	RANGE( -0.5,	0.5	),	RANGE( -0.2,	0.2	),	RANGE( -0.1,	0.1	),	RANGE( 0,	10	),	RANGE( 0,	5	),	RANGE( 0,	2	),	RANGE( 0,	1	),	RANGE( 0,	0.5	),	RANGE( 0,	0.2	),	RANGE( 0,	0.1	),}};static comedi_lrange range_ni_E_ai_bipolar4={ 4, {	RANGE( -10,	10	),	RANGE( -5,	5	),	RANGE( -0.5,	0.5	),	RANGE( -0.05,	0.05	),}};static comedi_lrange range_ni_E_ai_611x={ 8, {	RANGE( -50,	50	),	RANGE( -20,	20	),	RANGE( -10,	10	),	RANGE( -5,	5	),	RANGE( -2,	2	),	RANGE( -1,	1	),	RANGE( -0.5,	0.5	),	RANGE( -0.2,	0.2	),}};static comedi_lrange range_ni_E_ao_ext = { 4, {	RANGE( -10,	10	),	RANGE( 0,	10	),	RANGE_ext( -1,	1	),	RANGE_ext( 0,	1	),}};static comedi_lrange *ni_range_lkup[]={	&range_ni_E_ai,	&range_ni_E_ai_limited,	&range_ni_E_ai_limited14,	&range_ni_E_ai_bipolar4,	&range_ni_E_ai_611x,};static int ni_dio_insn_config(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data);static int ni_dio_insn_bits(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data);static int ni_calib_insn_read(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data);static int ni_calib_insn_write(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data);static int ni_eeprom_insn_read(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data);static int ni_pfi_insn_bits(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data);static int ni_pfi_insn_config(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data);static void caldac_setup(comedi_device *dev,comedi_subdevice *s);static int ni_read_eeprom(comedi_device *dev,int addr);#ifdef DEBUG_STATUS_Astatic void ni_mio_print_status_a(int status);#else#define ni_mio_print_status_a(a)#endif#ifdef DEBUG_STATUS_Bstatic void ni_mio_print_status_b(int status);#else#define ni_mio_print_status_b(a)#endifstatic int ni_ai_reset(comedi_device *dev,comedi_subdevice *s);#ifndef PCIDMAstatic void ni_handle_fifo_half_full(comedi_device *dev);static int ni_ao_fifo_half_empty(comedi_device *dev,comedi_subdevice *s);#endifstatic void ni_handle_fifo_dregs(comedi_device *dev);static int ni_ai_inttrig(comedi_device *dev,comedi_subdevice *s,	unsigned int trignum);static void ni_load_channelgain_list(comedi_device *dev,unsigned int n_chan,	unsigned int *list);static int ni_ao_inttrig(comedi_device *dev,comedi_subdevice *s,	unsigned int trignum);static int ni_ao_reset(comedi_device *dev,comedi_subdevice *s);static int ni_8255_callback(int dir,int port,int data,unsigned long arg);static int ni_ns_to_timer(int *nanosec,int round_mode);/*GPCT function def's*/static int GPCT_G_Watch(comedi_device *dev, int chan);static void GPCT_Reset(comedi_device *dev, int chan);static void GPCT_Gen_Cont_Pulse(comedi_device *dev, int chan, unsigned int length);static void GPCT_Gen_Single_Pulse(comedi_device *dev, int chan, unsigned int length);static void GPCT_Period_Meas(comedi_device *dev, int chan);static void GPCT_Pulse_Width_Meas(comedi_device *dev, int chan);static void GPCT_Event_Counting(comedi_device *dev,int chan);static int GPCT_Set_Direction(comedi_device *dev,int chan,int direction);static int GPCT_Set_Gate(comedi_device *dev,int chan ,int gate);static int GPCT_Set_Source(comedi_device *dev,int chan ,int source);static int ni_gpct_insn_write(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data);static int ni_gpct_insn_read(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data);static int ni_gpct_insn_config(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data);enum aimodes{	AIMODE_NONE = 0,	AIMODE_HALF_FULL = 1,	AIMODE_SCAN = 2,	AIMODE_SAMPLE = 3,};static const int num_adc_stages_611x = 3;static void handle_a_interrupt(comedi_device *dev,unsigned short status,	unsigned int m_status);static void handle_b_interrupt(comedi_device *dev,unsigned short status,	unsigned int m_status);static void get_last_sample_611x( comedi_device *dev );#ifdef PCIDMA//static void mite_handle_interrupt(comedi_device *dev,unsigned int status);static int ni_ai_drain_dma(comedi_device *dev );#endif/* ni_set_bits( ) allows different parts of the ni_mio_common driver to* share registers (such as Interrupt_A_Register) without interfering with* each other.  ** NOTE: the switch/case statements are optimized out for a constant argument* so this is actually quite fast---  If you must wrap another function around this* make it inline to avoid a large speed penalty.** value should only be 1 or 0.*/static inline void ni_set_bits(comedi_device *dev, int reg, int bits, int value){	unsigned long flags;	comedi_spin_lock_irqsave( &dev->spinlock, flags );	switch (reg){		case Interrupt_A_Enable_Register:			if(value)				devpriv->int_a_enable_reg |= bits;			else				devpriv->int_a_enable_reg &= ~bits;			comedi_spin_unlock_irqrestore( &dev->spinlock, flags );			win_out(devpriv->int_a_enable_reg,Interrupt_A_Enable_Register);			break;		case Interrupt_B_Enable_Register:			if(value)				devpriv->int_b_enable_reg |= bits;			else				devpriv->int_b_enable_reg &= ~bits;			comedi_spin_unlock_irqrestore( &dev->spinlock, flags );			win_out(devpriv->int_b_enable_reg,Interrupt_B_Enable_Register);			break;		case IO_Bidirection_Pin_Register:			if(value)				devpriv->io_bidirection_pin_reg |= bits;			else				devpriv->io_bidirection_pin_reg &= ~bits;			comedi_spin_unlock_irqrestore( &dev->spinlock, flags );			win_out(devpriv->io_bidirection_pin_reg,IO_Bidirection_Pin_Register);			break;		default:			printk("Warning ni_set_bits() called with invalid arguments\n");			printk("reg is %d\n",reg);			comedi_spin_unlock_irqrestore( &dev->spinlock, flags );			break;	}}static void ni_E_interrupt(int irq,void *d,struct pt_regs * regs){	comedi_device *dev=d;	unsigned short a_status;	unsigned short b_status;	unsigned int m0_status;	unsigned int m1_status;#ifdef PCIDMA	struct mite_struct *mite = devpriv->mite;#endif	a_status=win_in(AI_Status_1_Register);	b_status=win_in(AO_Status_1_Register);#ifdef PCIDMA	m0_status=readl(mite->mite_io_addr+MITE_CHSR+CHAN_OFFSET(AI_DMA_CHAN));	m1_status=readl(mite->mite_io_addr+MITE_CHSR+CHAN_OFFSET(AO_DMA_CHAN));#else	m0_status = 0;	m1_status = 0;#endif	if(a_status&Interrupt_A_St || m0_status & CHSR_INT )		handle_a_interrupt(dev, a_status, m0_status);	if(b_status&Interrupt_B_St || m1_status & CHSR_INT )		handle_b_interrupt(dev, b_status, m1_status);}#ifdef PCIDMAstatic void ni_sync_ai_dma(struct mite_struct *mite, comedi_device *dev){	int count;	comedi_subdevice *s = dev->subdevices + 0;	comedi_async *async = s->async;	unsigned int nbytes, old_alloc_count;	unsigned int bytes_per_scan = 2 * async->cmd.chanlist_len;	writel(CHOR_CLRLC, mite->mite_io_addr + MITE_CHOR + CHAN_OFFSET(AI_DMA_CHAN));	old_alloc_count = async->buf_write_alloc_count;	// write alloc as much as we can	comedi_buf_write_alloc(s->async, s->async->prealloc_bufsz);	nbytes = mite_bytes_transferred(mite, AI_DMA_CHAN);	if( (int)(nbytes - old_alloc_count) > 0 ){		printk("ni_mio_common: DMA overwrite of free area\n");		ni_ai_reset(dev,s);		async->events |= COMEDI_CB_OVERFLOW;		return;	}	count = nbytes - async->buf_write_count;	if( count < 0 ){		rt_printk("ni_mio_common: BUG: negative ai count\n");		count = 0;	}	comedi_buf_munge(dev, s, count);	comedi_buf_write_free(async, count);	async->scan_progress += count;	if( async->scan_progress >= bytes_per_scan )	{		async->scan_progress %= bytes_per_scan;		async->events |= COMEDI_CB_EOS;	}	async->events |= COMEDI_CB_BLOCK;}static void mite_handle_b_linkc(struct mite_struct *mite, comedi_device *dev){	int count;	comedi_subdevice *s = dev->subdevices + 1;	comedi_async *async = s->async;	unsigned int nbytes, new_write_count;	writel(CHOR_CLRLC, mite->mite_io_addr + MITE_CHOR + CHAN_OFFSET(AO_DMA_CHAN));	new_write_count = async->buf_write_count;	nbytes = mite_bytes_read(mite, AO_DMA_CHAN);	if( async->cmd.stop_src == TRIG_COUNT &&		(int) (nbytes - async->cmd.stop_arg * sizeof( sampl_t ) ) > 0 )		nbytes = async->cmd.stop_arg * sizeof( sampl_t );	if( (int)(nbytes - devpriv->last_buf_write_count) > 0 ){		rt_printk("ni_mio_common: DMA underrun\n");		ni_ao_reset(dev,s);		async->events |= COMEDI_CB_OVERFLOW;		return;	}	devpriv->last_buf_write_count = new_write_count;	count = nbytes - async->buf_read_count;	if( count < 0 ){		rt_printk("ni_mio_common: BUG: negative ao count\n");		count = 0;	}	comedi_buf_read_free(async, count);	async->events |= COMEDI_CB_BLOCK;}#if 0static void mite_handle_interrupt(comedi_device *dev,unsigned int m_status){	int len;	comedi_subdevice *s = dev->subdevices+0;	comedi_async *async = s->async;	struct mite_struct *mite = devpriv->mite;	async->events |= COMEDI_CB_BLOCK;	MDPRINTK("mite_handle_interrupt: m_status=%08x\n",m_status);	if(m_status & CHSR_DONE){		writel(CHOR_CLRDONE, mite->mite_io_addr + MITE_CHOR +			CHAN_OFFSET(0));	}#if 0	len = sizeof(sampl_t)*async->cmd.stop_arg*async->cmd.scan_end_arg;	if((devpriv->mite->DMA_CheckNearEnd) &&			(s->async->buf_int_count > (len - s->async->prealloc_bufsz))) {		long offset;		int i;		offset = len % async->prealloc_bufsz;		if(offset < mite->ring[0].count) {			mite->ring[0].count = offset;			mite->ring[1].count = 0;		}else{			offset -= mite->ring[0].count;			i = offset >> PAGE_SHIFT;			mite->ring[i].count = offset & ~PAGE_MASK;			mite->ring[(i+1)%mite->n_links].count = 0;		}		mite->DMA_CheckNearEnd = 0;	}#endif#if  0	MDPRINTK("CHSR is 0x%08x, count is %d\n",m_status,async->buf_int_count);	if(m_status&CHSR_DONE){		writel(CHOR_CLRDONE, mite->mite_io_addr+MITE_CHOR+CHAN_OFFSET(mite->chan));		//printk("buf_int_count is %d, buf_int_ptr is %d\n",		//		s->async->buf_int_count,s->async->buf_int_ptr);		ni_handle_block_dma(dev);	}	MDPRINTK("exit mite_handle_interrupt\n");#endif	//comedi_event(dev,s,async->events);}#endifstatic int ni_ao_wait_for_dma_load( comedi_device *dev ){	static const int timeout = 10000;	int i;	for( i = 0; i < timeout; i++ )	{		unsigned short b_status;		b_status = win_in( AO_Status_1_Register );		if( b_status & AO_FIFO_Half_Full_St )			break;	}	if( i == timeout ) return -EPIPE;	return 0;}#endif //PCIDMAstatic void shutdown_ai_command( comedi_device *dev ){	comedi_subdevice *s = dev->subdevices + 0;#ifdef PCIDMA	ni_ai_drain_dma( dev );	mite_dma_disarm(devpriv->mite, AI_DMA_CHAN);#endif	ni_handle_fifo_dregs(dev);	get_last_sample_611x(dev);	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);	s->async->events |= COMEDI_CB_EOA;}static void handle_a_interrupt(comedi_device *dev,unsigned short status,	unsigned int m_status){	comedi_subdevice *s=dev->subdevices+0;	//comedi_async *async = s->async;	unsigned short ack=0;	s->async->events = 0;

⌨️ 快捷键说明

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