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

📄 dvma.c

📁 microwindows移植到S3C44B0的源码
💻 C
字号:
/* * Virtual DMA allocation * * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de)  * * 11/26/2000 -- disabled the existing code because it didn't work for  * me in 2.4.  Replaced with a significantly more primitive version  * similar to the sun3 code.  the old functionality was probably more  * desirable, but....   -- Sam Creasey (sammy@oh.verio.com) * */#include <linux/kernel.h>#include <linux/init.h>#include <linux/bitops.h>#include <linux/mm.h>#include <linux/bootmem.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <asm/sun3x.h>#include <asm/dvma.h>#include <asm/io.h>#include <asm/page.h>#include <asm/pgtable.h>#include <asm/pgalloc.h>/* IOMMU support */#define IOMMU_ADDR_MASK            0x03ffe000#define IOMMU_CACHE_INHIBIT        0x00000040#define IOMMU_FULL_BLOCK           0x00000020#define IOMMU_MODIFIED             0x00000010#define IOMMU_USED                 0x00000008#define IOMMU_WRITE_PROTECT        0x00000004#define IOMMU_DT_MASK              0x00000003#define IOMMU_DT_INVALID           0x00000000#define IOMMU_DT_VALID             0x00000001#define IOMMU_DT_BAD               0x00000002static volatile unsigned long *iommu_pte = (unsigned long *)SUN3X_IOMMU;#define dvma_entry_paddr(index) 	(iommu_pte[index] & IOMMU_ADDR_MASK)#define dvma_entry_vaddr(index,paddr) 	((index << DVMA_PAGE_SHIFT) |  \					 (paddr & (DVMA_PAGE_SIZE-1)))#if 0#define dvma_entry_set(index,addr)	(iommu_pte[index] =            \					    (addr & IOMMU_ADDR_MASK) | \				             IOMMU_DT_VALID | IOMMU_CACHE_INHIBIT)#else#define dvma_entry_set(index,addr)	(iommu_pte[index] =            \					    (addr & IOMMU_ADDR_MASK) | \				             IOMMU_DT_VALID)#endif#define dvma_entry_clr(index)		(iommu_pte[index] = IOMMU_DT_INVALID)#define dvma_entry_hash(addr)		((addr >> DVMA_PAGE_SHIFT) ^ \					 ((addr & 0x03c00000) >>     \						(DVMA_PAGE_SHIFT+4)))#undef DEBUG#ifdef DEBUG/* code to print out a dvma mapping for debugging purposes */void dvma_print (unsigned long dvma_addr){        unsigned long index;        index = dvma_addr >> DVMA_PAGE_SHIFT;        printk("idx %lx dvma_addr %08lx paddr %08lx\n", index, dvma_addr,               dvma_entry_paddr(index));}#endif/* create a virtual mapping for a page assigned within the IOMMU   so that the cpu can reach it easily */inline int dvma_map_cpu(unsigned long kaddr, 			       unsigned long vaddr, int len){	pgd_t *pgd;	unsigned long end;	int ret = 0;	kaddr &= PAGE_MASK;	vaddr &= PAGE_MASK;	end = PAGE_ALIGN(vaddr + len);#ifdef DEBUG	printk("dvma: mapping kern %08lx to virt %08lx\n",	       kaddr, vaddr);#endif	pgd = pgd_offset_k(vaddr);		do {		pmd_t *pmd;		unsigned long end2;		if((pmd = pmd_alloc_kernel(pgd, vaddr)) == NULL) {			ret = -ENOMEM;			goto out;		}		if((end & PGDIR_MASK) > (vaddr & PGDIR_MASK)) 			end2 = (vaddr + (PGDIR_SIZE-1)) & PGDIR_MASK;		else			end2 = end;		do {			pte_t *pte;			unsigned long end3;			if((pte = pte_alloc_kernel(pmd, vaddr)) == NULL) {				ret = -ENOMEM;				goto out;			}			if((end2 & PMD_MASK) > (vaddr & PMD_MASK)) 				end3 = (vaddr + (PMD_SIZE-1)) & PMD_MASK;			else				end3 = end2;			do {#ifdef DEBUG				printk("mapping %08lx phys to %08lx\n",				       __pa(kaddr), vaddr);#endif				set_pte(pte, __mk_pte(kaddr, PAGE_KERNEL));				pte++;				kaddr += PAGE_SIZE;				vaddr += PAGE_SIZE;			} while(vaddr < end3);					} while(vaddr < end2);	} while(vaddr < end);		flush_tlb_all(); out:	return ret;}inline int dvma_map_iommu(unsigned long kaddr, unsigned long baddr,				 int len) {	unsigned long end, index;	index = baddr >> DVMA_PAGE_SHIFT;	end = ((baddr+len) >> DVMA_PAGE_SHIFT);		if(len & ~DVMA_PAGE_MASK)		end++;	for(; index < end ; index++) {//		if(dvma_entry_use(index))//			BUG();//		printk("mapping pa %lx to ba %lx\n", __pa(kaddr), index << DVMA_PAGE_SHIFT);		dvma_entry_set(index, __pa(kaddr));		iommu_pte[index] |= IOMMU_FULL_BLOCK;//		dvma_entry_inc(index);				kaddr += DVMA_PAGE_SIZE;	}#ifdef DEBUG		for(index = (baddr >> DVMA_PAGE_SHIFT); index < end; index++) 		dvma_print(index << DVMA_PAGE_SHIFT);#endif	return 0;}void dvma_unmap_iommu(unsigned long baddr, int len){	int index, end;			index = baddr >> DVMA_PAGE_SHIFT;	end = (DVMA_PAGE_ALIGN(baddr+len) >> DVMA_PAGE_SHIFT);		for(; index < end ; index++) {#ifdef DEBUG		printk("freeing bus mapping %08x\n", index << DVMA_PAGE_SHIFT);#endif#if 0		if(!dvma_entry_use(index)) 			printk("dvma_unmap freeing unused entry %04x\n",			       index);		else			dvma_entry_dec(index);#endif		dvma_entry_clr(index);	}}

⌨️ 快捷键说明

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