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

📄 mite.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
字号:
/*    module/mite.c    Hardware driver for NI Mite PCI interface chip    COMEDI - Linux Control and Measurement Device Interface    Copyright (C) 1997-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.*//*	The PCI-MIO E series driver was originally written by	Tomasz Motylewski <...>, and ported to comedi by ds.	References for specifications:		   321747b.pdf  Register Level Programmer Manual (obsolete)	   321747c.pdf  Register Level Programmer Manual (new)	   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:*///#define USE_KMALLOC#include <linux/comedidev.h>#include <linux/pci.h>#include "mite.h"#define PCI_MITE_SIZE		4096#define PCI_DAQ_SIZE		4096MODULE_LICENSE("GPL");struct mite_struct *mite_devices = NULL;#define TOP_OF_PAGE(x) ((x)|(~(PAGE_MASK)))void mite_init(void){	struct pci_dev *pcidev;	struct mite_struct *mite;	pci_for_each_dev(pcidev){		if(pcidev->vendor==PCI_VENDOR_ID_NATINST){			mite=kmalloc(sizeof(*mite),GFP_KERNEL);			if(!mite){				printk("mite: allocation failed\n");				return;			}			memset(mite,0,sizeof(*mite));			mite->pcidev=pcidev;			mite->next=mite_devices;			mite_devices=mite;		}	}}int mite_setup(struct mite_struct *mite){	unsigned long			offset, start, length;	u32				addr;	int i;	if(pci_enable_device(mite->pcidev)){		printk("error enabling mite\n");		return -EIO;	}	pci_set_master(mite->pcidev);	if( pci_request_regions( mite->pcidev, "mite" ) ) {		printk("failed to request mite io regions\n");		return -EIO;	};	addr = pci_resource_start(mite->pcidev, 0);	mite->mite_phys_addr = addr;	offset = mite->mite_phys_addr & ~PAGE_MASK;	start = mite->mite_phys_addr & PAGE_MASK;	length = PCI_MITE_SIZE + offset;	mite->mite_io_addr = ioremap(start, length) + offset;	printk("MITE:0x%08lx mapped to %p ",mite->mite_phys_addr,mite->mite_io_addr);	addr=pci_resource_start(mite->pcidev, 1);	mite->daq_phys_addr=addr;	offset = mite->daq_phys_addr & ~PAGE_MASK;	start = mite->daq_phys_addr & PAGE_MASK;	length = PCI_DAQ_SIZE + offset;	mite->daq_io_addr = ioremap(start, length) + offset;	printk("DAQ:0x%08lx mapped to %p\n",mite->daq_phys_addr,mite->daq_io_addr);	/* XXX don't know what the 0xc0 and 0x80 mean */	/* It must be here for the driver to work though */	writel(mite->daq_phys_addr | 0x80 , mite->mite_io_addr + 0xc0 );	for( i = 0; i < NUM_MITE_DMA_CHANNELS; i++ ) {		writel(CHOR_DMARESET, mite->mite_io_addr + MITE_CHOR + CHAN_OFFSET(i));		/* disable interrupts */		writel(0,mite->mite_io_addr + MITE_CHCR + CHAN_OFFSET(i));	}	mite->used = 1;	return 0;}void mite_cleanup(void){	struct mite_struct *mite,*next;	for(mite=mite_devices;mite;mite=next){		next=mite->next;		kfree(mite);	}}void mite_unsetup(struct mite_struct *mite){	//unsigned long offset, start, length;	if(!mite)return;	if(mite->mite_io_addr){		iounmap(mite->mite_io_addr);		mite->mite_io_addr=NULL;	}	if(mite->daq_io_addr){		iounmap(mite->daq_io_addr);		mite->daq_io_addr=NULL;	}	if( mite->used )		pci_release_regions( mite->pcidev );	mite->used = 0;}void mite_list_devices(void){	struct mite_struct *mite,*next;	printk("Available NI device IDs:");	if(mite_devices)for(mite=mite_devices;mite;mite=next){		next=mite->next;		printk(" 0x%04x",mite_device_id(mite));		if(mite->used)printk("(used)");	}	printk("\n");}void mite_dma_arm( struct mite_struct *mite, unsigned int channel ){	int chor;	MDPRINTK("mite_dma_arm ch%i\n", channel);	/* arm */	chor = CHOR_START;	writel(chor, mite->mite_io_addr + CHAN_OFFSET(channel) + MITE_CHOR);	mite_dma_tcr(mite, channel);}/**************************************/int mite_load_buffer(struct mite_struct *mite, unsigned int channel, comedi_async *async){	unsigned int n_links;	int i;	struct mite_channel *mite_chan = &mite->channels[ channel ];	MDPRINTK("mite_load_buffer ch%i\n", channel);	if(mite_chan->ring){		kfree(mite_chan->ring);		mite_chan->ring = NULL;	}	if(async->prealloc_bufsz==0){		return 0;	}	n_links = async->prealloc_bufsz >> PAGE_SHIFT;	MDPRINTK("buf=%p buf(bus)=%08lx bufsz=0x%08x n_links=0x%04x\n",		async->prealloc_buf, virt_to_bus(async->prealloc_buf), async->prealloc_bufsz, n_links);	mite_chan->ring = kmalloc(n_links * sizeof(struct mite_dma_chain), GFP_KERNEL);	if(!mite_chan->ring){		printk("mite: ring buffer allocation failed\n");		return -ENOMEM;	}	mite_chan->n_links = n_links;	mite_chan->current_link = 0;	for(i=0;i<n_links;i++){		mite_chan->ring[i].count = cpu_to_le32(PAGE_SIZE);		mite_chan->ring[i].addr = cpu_to_le32(virt_to_bus(				(void *)async->buf_page_list[i]));		mite_chan->ring[i].next = cpu_to_le32(virt_to_bus(				mite_chan->ring+i+1));	}	mite_chan->ring[n_links-1].next = cpu_to_le32(virt_to_bus(				mite_chan->ring));	return 0;}int mite_buf_change(struct mite_struct *mite, unsigned int channel,	comedi_async *async, unsigned long new_size){	MDPRINTK("mite_buf_change ch%i\n", channel);	mite_load_buffer(mite, channel, async);	return 0;}void mite_prep_dma( struct mite_struct *mite, unsigned int channel,	unsigned int num_device_bits, unsigned int num_memory_bits ){	unsigned int chor,chcr,mcr,dcr,lkcr;	struct mite_channel *mite_chan = &mite->channels[ channel ];	MDPRINTK("mite_prep_dma ch%i\n", channel );	/* reset DMA and FIFO */	chor = CHOR_DMARESET | CHOR_FRESET;	writel(chor, mite->mite_io_addr + MITE_CHOR + CHAN_OFFSET(channel));	/* short link chaining mode */	chcr = CHCR_SET_DMA_IE| CHCR_LINKSHORT | CHCR_SET_DONE_IE;	/*	 * Link Complete Interrupt: interrupt every time a link	 * in MITE_RING is completed. This can generate a lot of	 * extra interrupts, but right now we update the values	 * of buf_int_ptr and buf_int_count at each interrupt.  A	 * better method is to poll the MITE before each user	 * "read()" to calculate the number of bytes available.	 * mite_bytes_transferred(), mite_bytes_read(), and	 * mite_bytes_in_transit() are provided to get the number	 * of bytes transferred by the mite so far.	 */	chcr |= CHCR_SET_LC_IE;	if(mite_chan->dir == COMEDI_INPUT){		chcr |= CHCR_DEV_TO_MEM;	}	writel(chcr, mite->mite_io_addr + MITE_CHCR + CHAN_OFFSET(channel));	/* to/from memory */	mcr = CR_RL64 | CR_ASEQxP1;	switch( num_memory_bits ){		case 8:			mcr |= CR_PSIZEBYTE;			break;		case 16:			mcr |= CR_PSIZEHALF;			break;		case 32:			mcr |= CR_PSIZEWORD;			break;		default:			rt_printk( "mite: bug! invalid mem bit width for dma transfer\n" );			break;	}	writel(mcr, mite->mite_io_addr + MITE_MCR + CHAN_OFFSET(channel));	/* from/to device */	dcr = CR_RL64 |  CR_ASEQx(1);	dcr |= CR_PORTIO | CR_AMDEVICE | CR_REQS(0x4 + channel);	switch( num_device_bits ){		case 8:			dcr |= CR_PSIZEBYTE;			break;		case 16:			dcr |= CR_PSIZEHALF;			break;		case 32:			dcr |= CR_PSIZEWORD;			break;		default:			rt_printk( "mite: bug! invalid dev bit width for dma transfer\n" );			break;	}	writel(dcr, mite->mite_io_addr + MITE_DCR + CHAN_OFFSET(channel));	/* reset the DAR */	writel(0, mite->mite_io_addr + MITE_DAR + CHAN_OFFSET(channel));	/* the link is 32bits */	lkcr = CR_RL64 | CR_ASEQUP | CR_PSIZEWORD;	writel(lkcr, mite->mite_io_addr + MITE_LKCR + CHAN_OFFSET(channel));	/* starting address for link chaining */	writel(virt_to_bus(mite_chan->ring),		mite->mite_io_addr + MITE_LKAR + CHAN_OFFSET(channel));	MDPRINTK("exit mite_prep_dma\n");}unsigned int mite_bytes_read(struct mite_struct *mite, unsigned int chan){       return readl(mite->mite_io_addr+MITE_DAR+CHAN_OFFSET(chan));}unsigned int mite_bytes_in_transit(struct mite_struct *mite, unsigned int chan){	return readl(mite->mite_io_addr + MITE_FCR + CHAN_OFFSET(chan)) & 0x000000FF;}unsigned int mite_bytes_transferred(struct mite_struct *mite, unsigned int chan){	unsigned int bytes_read;	/* to avoid race, we want to read bytes read before reading bytes	 * in transit */	bytes_read = mite_bytes_read( mite, chan );	return bytes_read - mite_bytes_in_transit( mite, chan );}int mite_dma_tcr(struct mite_struct *mite, unsigned int channel){	int tcr;	int lkar;	lkar=readl(mite->mite_io_addr + CHAN_OFFSET(channel) + MITE_LKAR);	tcr=readl(mite->mite_io_addr + CHAN_OFFSET(channel) + MITE_TCR);	MDPRINTK("mite_dma_tcr ch%i, lkar=0x%08x tcr=%d\n", channel, lkar, tcr);	return tcr;}void mite_dma_disarm(struct mite_struct *mite, unsigned int channel){	int chor;	/* disarm */	chor = CHOR_ABORT;	writel(chor, mite->mite_io_addr + CHAN_OFFSET(channel) + MITE_CHOR);}#ifdef DEBUG_MITEstatic void mite_decode(char **bit_str, unsigned int bits);/* names of bits in mite registers */static char *mite_CHOR_strings[] = {	"start", "cont", "stop", "abort",	"freset", "clrlc", "clrrb", "clrdone",	"clr_lpause", "set_lpause", "clr_send_tc",	"set_send_tc", "12", "13", "14",	"15", "16", "17", "18",	"19", "20", "21", "22",	"23", "24", "25", "26",	"27", "28", "29", "30",	"dmareset",};static char *mite_CHCR_strings[] = {	"continue", "ringbuff", "2", "3",	"4", "5", "6", "7",	"8", "9", "10", "11",	"12", "13", "bursten", "fifodis",	"clr_cont_rb_ie", "set_cont_rb_ie", "clr_lc_ie", "set_lc_ie",	"clr_drdy_ie", "set_drdy_ie", "clr_mrdy_ie", "set_mrdy_ie",	"clr_done_ie", "set_done_ie", "clr_sar_ie", "set_sar_ie",	"clr_linkp_ie", "set_linkp_ie", "clr_dma_ie", "set_dma_ie",};static char *mite_MCR_strings[] = {	"amdevice", "1", "2", "3",	"4", "5", "portio", "portvxi",	"psizebyte", "psizehalf (byte & half = word)", "aseqxp1", "11",	"12", "13", "blocken", "berhand",	"reqsintlim/reqs0", "reqs1", "reqs2", "rd32",	"rd512", "rl1", "rl2", "rl8",	"24", "25", "26", "27",	"28", "29", "30", "stopen",};static char *mite_DCR_strings[] = {	"amdevice", "1", "2", "3",	"4", "5", "portio", "portvxi",	"psizebyte", "psizehalf (byte & half = word)", "aseqxp1", "aseqxp2",	"aseqxp8", "13", "blocken", "berhand",	"reqsintlim", "reqs1", "reqs2", "rd32",	"rd512", "rl1", "rl2", "rl8",	"23", "24", "25", "27",	"28", "wsdevc", "wsdevs", "rwdevpack",};static char *mite_LKCR_strings[] = {	"amdevice", "1", "2", "3",	"4", "5", "portio", "portvxi",	"psizebyte", "psizehalf (byte & half = word)", "asequp", "aseqdown",	"12", "13", "14", "berhand",	"16", "17", "18", "rd32",	"rd512", "rl1", "rl2", "rl8",	"24", "25", "26", "27",	"28", "29", "30", "chngend",};static char *mite_CHSR_strings[] = {	"d.err0", "d.err1", "m.err0", "m.err1",	"l.err0", "l.err1", "drq0", "drq1",	"end", "xferr", "operr0", "operr1",	"stops", "habort", "sabort", "error",	"16", "conts_rb", "18", "linkc",	"20", "drdy", "22", "mrdy",	"24", "done", "26", "sars",	"28", "lpauses", "30", "int",};void mite_dump_regs(struct mite_struct *mite, int channel){	unsigned long mite_io_addr = (unsigned long) mite->mite_io_addr;	unsigned long addr=0;	unsigned long temp=0;	printk("mite_dump_regs ch%i\n", channel);	printk("mite address is  =0x%08lx\n",mite_io_addr);	addr = mite_io_addr+MITE_CHOR+CHAN_OFFSET(channel);	printk("mite status[CHOR]at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));	mite_decode(mite_CHOR_strings,temp);	addr = mite_io_addr+MITE_CHCR+CHAN_OFFSET(channel);	printk("mite status[CHCR]at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));	mite_decode(mite_CHCR_strings,temp);	addr = mite_io_addr+MITE_TCR+CHAN_OFFSET(channel);	printk("mite status[TCR] at 0x%08lx =0x%08x\n",addr, readl(addr));	addr = mite_io_addr+MITE_MCR+CHAN_OFFSET(channel);	printk("mite status[MCR] at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));	mite_decode(mite_MCR_strings,temp);	addr = mite_io_addr+MITE_MAR+CHAN_OFFSET(channel);	printk("mite status[MAR] at 0x%08lx =0x%08x\n",addr, readl(addr));	addr = mite_io_addr+MITE_DCR+CHAN_OFFSET(channel);	printk("mite status[DCR] at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));	mite_decode(mite_DCR_strings,temp);	addr = mite_io_addr+MITE_DAR+CHAN_OFFSET(channel);	printk("mite status[DAR] at 0x%08lx =0x%08x\n",addr, readl(addr));	addr = mite_io_addr+MITE_LKCR+CHAN_OFFSET(channel);	printk("mite status[LKCR]at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));	mite_decode(mite_LKCR_strings,temp);	addr = mite_io_addr+MITE_LKAR+CHAN_OFFSET(channel);	printk("mite status[LKAR]at 0x%08lx =0x%08x\n",addr, readl(addr));	addr = mite_io_addr+MITE_CHSR+CHAN_OFFSET(channel);	printk("mite status[CHSR]at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));	mite_decode(mite_CHSR_strings,temp);	addr = mite_io_addr+MITE_FCR+CHAN_OFFSET(channel);	printk("mite status[FCR] at 0x%08lx =0x%08x\n\n",addr, readl(addr));}static void mite_decode(char **bit_str, unsigned int bits){	int i;	for(i=31;i>=0;i--){		if(bits&(1<<i)){			printk(" %s", bit_str[i]);		}	}	printk("\n");}#endif#ifdef MODULEint init_module(void){	mite_init();	mite_list_devices();	return 0;}void cleanup_module(void){	mite_cleanup();}EXPORT_SYMBOL(mite_dma_tcr);EXPORT_SYMBOL(mite_dma_arm);EXPORT_SYMBOL(mite_dma_disarm);EXPORT_SYMBOL(mite_setup);EXPORT_SYMBOL(mite_unsetup);#if 0EXPORT_SYMBOL(mite_kvmem_segment_load);EXPORT_SYMBOL(mite_ll_from_kvmem);EXPORT_SYMBOL(mite_setregs);#endifEXPORT_SYMBOL(mite_devices);EXPORT_SYMBOL(mite_list_devices);EXPORT_SYMBOL(mite_prep_dma);EXPORT_SYMBOL(mite_buf_change);EXPORT_SYMBOL(mite_bytes_transferred);EXPORT_SYMBOL(mite_bytes_read);EXPORT_SYMBOL(mite_bytes_in_transit);#ifdef DEBUG_MITEEXPORT_SYMBOL(mite_decode);EXPORT_SYMBOL(mite_dump_regs);#endif#endif

⌨️ 快捷键说明

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