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

📄 ni_pcidio.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    comedi/drivers/ni_pcidio.c    driver for National Instruments PCI-DIO-96/PCI-6508               National Instruments PCI-DIO-32HS               National Instruments PCI-6503    COMEDI - Linux Control and Measurement Device Interface    Copyright (C) 1999,2002 David A. Schleef <ds@schleef.org>    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.*//*Driver: ni_pcidio.oDescription: National Instruments PCI-DIO32HS, PCI-DIO96, PCI-6533, PCI-6503Author: dsStatus: worksDevices: [National Instruments] PCI-DIO-32HS (ni_pcidio), PXI-6533,  PCI-DIO-96, PCI-DIO-96B, PXI-6508, PCI-6503, PCI-6503B, PCI-6503X,  PXI-6503, PCI-6534, PCI-6533Updated: Sun, 21 Apr 2002 21:03:38 -0700The DIO-96 appears as four 8255 subdevices.  See the 8255driver notes for details.The DIO32HS board appears as one subdevice, with 32 channels.Each channel is individually I/O configurable.  The channel orderis 0=A0, 1=A1, 2=A2, ... 8=B0, 16=C0, 24=D0.  The driver onlysupports simple digital I/O; no handshaking is supported.DMA mostly works for the PCI-DIO32HS, but only in timed input mode.This driver could be easily modified to support AT-MIO32HS andAT-MIO96.*//*   This driver is for both the NI PCI-DIO-32HS and the PCI-DIO-96,   which have very different architectures.  But, since the '96 is   so simple, it is included here.   Manuals (available from ftp://ftp.natinst.com/support/manuals)	320938c.pdf	PCI-DIO-96/PXI-6508/PCI-6503 User Manual	321464b.pdf	AT/PCI-DIO-32HS User Manual	341329A.pdf	PCI-6533 Register-Level Programmer Manual	341330A.pdf	DAQ-DIO Technical Reference Manual */#define USE_DMA#define DEBUG 1#define DEBUG_FLAGS#include <linux/comedidev.h>#include <linux/irq.h> /* for disable_irq */#include "mite.h"#include "8255.h"#undef DPRINTK#ifdef DEBUG#define DPRINTK(format, args...)	printk(format, ## args)#else#define DPRINTK(format, args...)#endif#define PCI_VENDOR_ID_NATINST	0x1093#define PCI_DIO_SIZE 4096#define PCI_MITE_SIZE 4096/* defines for the PCI-DIO-96 */#define NIDIO_8255_BASE(x)	((x)*4)#define NIDIO_A 0#define NIDIO_B 4#define NIDIO_C 8#define NIDIO_D 12/* defines for the PCI-DIO-32HS */#define Window_Address			4	/* W */#define Interrupt_And_Window_Status	4	/* R */  #define IntStatus1				(1<<0)  #define IntStatus2				(1<<1)  #define WindowAddressStatus_mask		0x7c#define Master_DMA_And_Interrupt_Control 5	/* W */  #define InterruptLine(x)			((x)&3)  #define OpenInt				(1<<2)#define Group_Status			5	/* R */  #define DataLeft				(1<<0)  #define Req					(1<<2)  #define StopTrig				(1<<3)#define Group_1_Flags			6	/* R */#define Group_2_Flags			7	/* R */  #define TransferReady				(1<<0)  #define CountExpired				(1<<1)  #define Waited				(1<<5)  #define PrimaryTC				(1<<6)  #define SecondaryTC				(1<<7)  //#define SerialRose  //#define ReqRose  //#define Paused#define Group_1_First_Clear		6	/* W */#define Group_2_First_Clear		7	/* W */  #define ClearWaited				(1<<3)  #define ClearPrimaryTC			(1<<4)  #define ClearSecondaryTC			(1<<5)  #define DMAReset				(1<<6)  #define FIFOReset				(1<<7)  #define ClearAll				0xf8#define Group_1_FIFO			8	/* W */#define Group_2_FIFO			12	/* W */#define Transfer_Count			20#define Chip_ID_D			24#define Chip_ID_I			25#define Chip_ID_O			26#define Chip_Version			27#define Port_IO(x)			(28+(x))#define Port_Pin_Directions(x)		(32+(x))#define Port_Pin_Mask(x)		(36+(x))#define Port_Pin_Polarities(x)		(40+(x))#define Master_Clock_Routing		45  #define RTSIClocking(x)			(((x)&3)<<4)#define Group_1_Second_Clear		46	/* W */#define Group_2_Second_Clear		47	/* W */  #define ClearExpired				(1<<0)#define Port_Pattern(x)			(48+(x))#define Data_Path			64  #define FIFOEnableA		(1<<0)  #define FIFOEnableB		(1<<1)  #define FIFOEnableC		(1<<2)  #define FIFOEnableD		(1<<3)  #define Funneling(x)		(((x)&3)<<4)  #define GroupDirection	(1<<7)#define Protocol_Register_1		65#define OpMode				Protocol_Register_1  #define RunMode(x)		((x)&7)  #define Numbered		(1<<3)#define Protocol_Register_2		66#define ClockReg			Protocol_Register_2  #define ClockLine(x)		(((x)&3)<<5)  #define InvertStopTrig	(1<<7)#define Protocol_Register_3		67#define Sequence			Protocol_Register_3#define Protocol_Register_14		68 /* 16 bit */#define ClockSpeed			Protocol_Register_14#define Protocol_Register_4		70#define ReqReg				Protocol_Register_4  #define ReqConditioning(x)	(((x)&7)<<3)#define Protocol_Register_5		71#define BlockMode			Protocol_Register_5#define FIFO_Control			72  #define ReadyLevel(x)		((x)&7)#define Protocol_Register_6		73#define LinePolarities			Protocol_Register_6  #define InvertAck		(1<<0)  #define InvertReq		(1<<1)  #define InvertClock		(1<<2)  #define InvertSerial		(1<<3)  #define OpenAck		(1<<4)  #define OpenClock		(1<<5)#define Protocol_Register_7		74#define AckSer				Protocol_Register_7  #define AckLine(x)		(((x)&3)<<2)  #define ExchangePins		(1<<7)#define Interrupt_Control		75  /* bits same as flags */#define DMA_Line_Control		76  #define DMAChannel(x)		((x)&0xf)#define Transfer_Size_Control		77  #define TransferWidth(x)	((x)&3)  #define TransferLength(x)	(((x)&3)<<3)  #define RequireRLevel		(1<<5)#define Protocol_Register_15		79#define DAQOptions			Protocol_Register_15  #define StartSource(x)			((x)&0x3)  #define InvertStart				(1<<2)  #define StopSource(x)				(((x)&0x3)<<3)  #define ReqStart				(1<<6)  #define PreStart				(1<<7)#define Pattern_Detection		81  #define DetectionMethod			(1<<0)  #define InvertMatch				(1<<1)  #define IE_Pattern_Detection			(1<<2)#define Protocol_Register_9		82#define ReqDelay			Protocol_Register_9#define Protocol_Register_10		83#define ReqNotDelay			Protocol_Register_10#define Protocol_Register_11		84#define AckDelay			Protocol_Register_11#define Protocol_Register_12		85#define AckNotDelay			Protocol_Register_12#define Protocol_Register_13		86#define Data1Delay			Protocol_Register_13#define Protocol_Register_8		88 /* 32 bit */#define StartDelay			Protocol_Register_8#define TIMER_BASE 50		/* nanoseconds */#ifdef USE_DMA#define IntEn (CountExpired|Waited|PrimaryTC|SecondaryTC)#else#define IntEn (TransferReady|CountExpired|Waited|PrimaryTC|SecondaryTC)#endifenum mite_dma_channels{	DI_DMA_CHAN = 1,};static int nidio_attach(comedi_device *dev,comedi_devconfig *it);static int nidio_detach(comedi_device *dev);static comedi_driver driver_pcidio={	driver_name:	"ni_pcidio",	module:		THIS_MODULE,	attach:		nidio_attach,	detach:		nidio_detach,};COMEDI_INITCLEANUP(driver_pcidio);typedef struct{	int dev_id;	char *name;	int n_8255;	unsigned int is_diodaq : 1;}nidio_board;static nidio_board nidio_boards[]={	{	dev_id:		0x1150,	name:		"pci-dio-32hs",	n_8255:		0,	is_diodaq:	1,	},	{	dev_id:		0x1320,	name:		"pxi-6533",	n_8255:		0,	is_diodaq:	1,	},	{	dev_id:		0x12b0,	name:		"pci-6534",	n_8255:		0,	is_diodaq:	1,	},	{	dev_id:		0x0160,	name:		"pci-dio-96",	n_8255:		4,	is_diodaq:	0,	},	{	dev_id:		0x1630,	name:		"pci-dio-96b",	n_8255:		4,	is_diodaq:	0,	},	{	dev_id:		0x13c0,	name:		"pxi-6508",	n_8255:		4,	is_diodaq:	0,	},	{	dev_id:		0x0400,	name:		"pci-6503",	n_8255:		1,	is_diodaq:	0,	},	{	dev_id:		0x1250,	name:		"pci-6503b",	n_8255:		1,	is_diodaq:	0,	},	{	dev_id:		0x17d0,	name:		"pci-6503x",	n_8255:		1,	is_diodaq:	0,	},	{	dev_id:		0x1800,	name:		"pxi-6503",	n_8255:		1,	is_diodaq:	0,	},};#define n_nidio_boards (sizeof(nidio_boards)/sizeof(nidio_boards[0]))#define this_board ((nidio_board *)dev->board_ptr)static struct pci_device_id ni_pcidio_pci_table[] __devinitdata = {	{ PCI_VENDOR_ID_NATINST, 0x1150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NATINST, 0x1320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NATINST, 0x12b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NATINST, 0x0160, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NATINST, 0x1630, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NATINST, 0x13c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NATINST, 0x0400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NATINST, 0x1250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NATINST, 0x17d0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NATINST, 0x1800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ 0 }};MODULE_DEVICE_TABLE(pci, ni_pcidio_pci_table);typedef struct{	struct mite_struct *mite;	int boardtype;	int dio;}nidio96_private;#define devpriv ((nidio96_private *)dev->private)static int ni_pcidio_cmdtest(comedi_device *dev,comedi_subdevice *s,				  comedi_cmd *cmd);static int ni_pcidio_cmd(comedi_device *dev,comedi_subdevice *s);static int ni_pcidio_inttrig(comedi_device *dev, comedi_subdevice *s,	unsigned int trignum);static int nidio_find_device(comedi_device *dev,int bus,int slot);static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode);static void setup_mite_dma(comedi_device *dev,comedi_subdevice *s);#ifdef DEBUG_FLAGSstatic void ni_pcidio_print_flags(unsigned int flags);static void ni_pcidio_print_status(unsigned int status);#else#define ni_pcidio_print_flags(x)#define ni_pcidio_print_status(x)#endifstatic int nidio96_8255_cb(int dir,int port,int data,unsigned long iobase){	if(dir){		writeb(data,iobase+port);		return 0;	}else{		return readb(iobase+port);	}}static void nidio_interrupt(int irq, void *d, struct pt_regs *regs){	comedi_device *dev=d;	comedi_subdevice *s = dev->subdevices;	comedi_async *async = s->async;	struct mite_struct *mite = devpriv->mite;	struct mite_channel *mite_chan = &mite->channels[ DI_DMA_CHAN ];	//int i, j;	long int AuxData = 0;	sampl_t data1 = 0;	sampl_t data2 = 0;	int flags;	int status;	int work = 0;	unsigned int m_status;	status = readb(dev->iobase+Interrupt_And_Window_Status);	flags = readb(dev->iobase+Group_1_Flags);	m_status = readl(mite->mite_io_addr + MITE_CHSR + CHAN_OFFSET( DI_DMA_CHAN ));	//interrupcions parasites	if(dev->attached == 0){		comedi_error(dev,"premature interrupt");		async->events |= COMEDI_CB_ERROR|COMEDI_CB_EOA;	}	DPRINTK("ni_pcidio_interrupt: status=0x%02x,flags=0x%02x,m_status=0x%08x\n",		status,flags,m_status);	ni_pcidio_print_flags(flags);	ni_pcidio_print_status(status);#ifdef MITE_DEBUG	mite_print_chsr(m_status);#endif	//printk("mite_bytes_transferred: %d\n",mite_bytes_transferred(mite,DI_DMA_CHAN));	//mite_dump_regs(mite);	//printk("buf[0]=%08x\n",*(unsigned int *)async->prealloc_buf);	//printk("buf[4096]=%08x\n",*(unsigned int *)(async->prealloc_buf+4096));	if(m_status & CHSR_INT){		if(m_status & CHSR_LINKC){			unsigned int count;			writel(CHOR_CLRLC, mite->mite_io_addr + MITE_CHOR + CHAN_OFFSET(DI_DMA_CHAN));			count = le32_to_cpu(mite_chan->ring[mite_chan->current_link].count);			/* XXX need to byteswap */			async->buf_write_count += count;			async->buf_write_ptr += count;			if(async->buf_write_ptr >= async->prealloc_bufsz){				async->buf_write_ptr -= async->prealloc_bufsz;			}			mite_chan->current_link++;			if(mite_chan->current_link >= mite_chan->n_links){				mite_chan->current_link=0;			}		}		if(m_status & CHSR_DONE){			writel(CHOR_CLRDONE, mite->mite_io_addr + MITE_CHOR +				CHAN_OFFSET( DI_DMA_CHAN ));		}		if(m_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_DRDY | CHSR_DRQ1)){			DPRINTK("unknown mite interrupt, disabling IRQ\n");			writel(CHOR_DMARESET, mite->mite_io_addr + MITE_CHOR +				CHAN_OFFSET( DI_DMA_CHAN ));			disable_irq(dev->irq);		}		async->events |= COMEDI_CB_BLOCK;	}	while(status&DataLeft){		work++;		if(work>20){			DPRINTK("too much work in interrupt\n");			writeb(0x00,dev->iobase+Master_DMA_And_Interrupt_Control);			break;		}		flags &= IntEn;		if(flags & TransferReady){			//DPRINTK("TransferReady\n");			while(flags & TransferReady){				work++;				if(work>100){					DPRINTK("too much work in interrupt\n");					writeb(0x00,dev->iobase+Master_DMA_And_Interrupt_Control);					goto out;				}				AuxData = readl(dev->iobase+Group_1_FIFO);				data1 = AuxData & 0xffff;				data2 = (AuxData & 0xffff0000) >> 16;				comedi_buf_put(async,data1);				comedi_buf_put(async,data2);				//DPRINTK("read:%d, %d\n",data1,data2);				flags = readb(dev->iobase+Group_1_Flags);			}			//DPRINTK("buf_int_count: %d\n",async->buf_int_count);			//DPRINTK("1) IntEn=%d,flags=%d,status=%d\n",IntEn,flags,status);			//ni_pcidio_print_flags(flags);			//ni_pcidio_print_status(status);			async->events |= COMEDI_CB_BLOCK;		}		if(flags & CountExpired){			DPRINTK("CountExpired\n");			writeb(ClearExpired,dev->iobase+Group_1_Second_Clear);			async->events |= COMEDI_CB_EOA;			writeb(0x00,dev->iobase+OpMode);			writeb(0x00,dev->iobase+Master_DMA_And_Interrupt_Control);#ifdef USE_DMA			mite_dma_disarm(mite, DI_DMA_CHAN);			writel(CHOR_DMARESET, mite->mite_io_addr + MITE_CHOR +				CHAN_OFFSET( DI_DMA_CHAN ));#endif			break;		}else if(flags & Waited){			DPRINTK("Waited\n");			writeb(ClearWaited,dev->iobase+Group_1_First_Clear);			writeb(0x00,dev->iobase+Master_DMA_And_Interrupt_Control);			async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;#ifdef USE_DMA			mite_dma_disarm(mite, DI_DMA_CHAN);			writel(CHOR_DMARESET, mite->mite_io_addr + MITE_CHOR +				CHAN_OFFSET( DI_DMA_CHAN ));#endif			break;		}else if(flags & PrimaryTC){			DPRINTK("PrimaryTC\n");			writeb(ClearPrimaryTC,dev->iobase+Group_1_First_Clear);			async->events |= COMEDI_CB_EOA;			writeb(0x00,dev->iobase+Master_DMA_And_Interrupt_Control);		}else if(flags & SecondaryTC){			DPRINTK("SecondaryTC\n");			writeb(ClearSecondaryTC,dev->iobase+Group_1_First_Clear);

⌨️ 快捷键说明

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