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

📄 dvma.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
字号:
/* * Virtual DMA allocation * * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de)  */#include <linux/kernel.h>#include <linux/init.h>#include <linux/bitops.h>#include <linux/mm.h>#include <asm/sun3x.h>#include <asm/dvma.h>#include <asm/io.h>#include <asm/page.h>/* IOMMU support */#define IOMMU_ENTRIES		   2048#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               0x00000002#define DVMA_PAGE_SHIFT	13#define DVMA_PAGE_SIZE	(1UL << DVMA_PAGE_SHIFT)#define DVMA_PAGE_MASK	(~(DVMA_PAGE_SIZE-1))static volatile unsigned long *iommu_pte = (unsigned long *)SUN3X_IOMMU;static unsigned long iommu_use[IOMMU_ENTRIES];static unsigned long iommu_bitmap[IOMMU_ENTRIES/32];#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)))#define dvma_entry_set(index,addr)	(iommu_pte[index] =            \					    (addr & IOMMU_ADDR_MASK) | \				             IOMMU_DT_VALID)#define dvma_entry_clr(index)		(iommu_pte[index] = IOMMU_DT_INVALID)#define dvma_entry_use(index)		(iommu_use[index])#define dvma_entry_inc(index)		(iommu_use[index]++)#define dvma_entry_dec(index)		(iommu_use[index]--)#define dvma_entry_hash(addr)		((addr >> DVMA_PAGE_SHIFT) ^ \					 ((addr & 0x03c00000) >>     \						(DVMA_PAGE_SHIFT+4)))#define dvma_map			iommu_bitmap#define dvma_map_size			(IOMMU_ENTRIES/2)#define dvma_slow_offset		(IOMMU_ENTRIES/2)#define dvma_is_slow(addr)		((addr) & 		      \					 (dvma_slow_offset << DVMA_PAGE_SHIFT))static int fixed_dvma;void __init dvma_init(void){    unsigned long tmp;    if ((unsigned long)high_memory < (IOMMU_ENTRIES << DVMA_PAGE_SHIFT)) {	printk ("Sun3x fixed DVMA mapping\n");	fixed_dvma = 1;	for (tmp = 0; tmp < (unsigned long)high_memory; tmp += DVMA_PAGE_SIZE)	dvma_entry_set (tmp >> DVMA_PAGE_SHIFT, virt_to_phys((void *)tmp));	fixed_dvma = 1;    } else {	printk ("Sun3x variable DVMA mapping\n");	for (tmp = 0; tmp < IOMMU_ENTRIES; tmp++)	    dvma_entry_clr (tmp);	fixed_dvma = 0;    }}unsigned long dvma_slow_alloc (unsigned long paddr, int npages){    int scan, base;        scan = 0;    for (;;) {	scan = find_next_zero_bit(dvma_map, dvma_map_size, scan);	if ((base = scan) + npages > dvma_map_size) {	    printk ("dvma_slow_alloc failed for %d pages\n",npages);	    return 0;	}	for  (;;) {	    if (scan >= base + npages) goto found;	    if (test_bit(scan, dvma_map)) break;	    scan++;	}    }found:    for (scan = base; scan < base+npages; scan++) {	dvma_entry_set(scan+dvma_slow_offset, paddr);	paddr += DVMA_PAGE_SIZE;	set_bit(scan, dvma_map);    }    return (dvma_entry_vaddr((base+dvma_slow_offset),paddr));}unsigned long dvma_alloc (unsigned long paddr, unsigned long size){    int index;    int pages = ((paddr & ~DVMA_PAGE_MASK) + size + (DVMA_PAGE_SIZE-1)) >>		DVMA_PAGE_SHIFT;    if (fixed_dvma)	return ((unsigned long)phys_to_virt (paddr));    if (pages > 1) /* multi page, allocate from slow pool */	return dvma_slow_alloc (paddr, pages);        index = dvma_entry_hash (paddr);    if (dvma_entry_use(index)) {	if (dvma_entry_paddr(index) == (paddr & DVMA_PAGE_MASK)) {	    dvma_entry_inc(index);	    return dvma_entry_vaddr(index,paddr);	}	/* collision, allocate from slow pool */	return dvma_slow_alloc (paddr, pages);    }        dvma_entry_set(index,paddr);     dvma_entry_inc(index);    return dvma_entry_vaddr(index,paddr);}void dvma_free (unsigned long dvma_addr, unsigned long size){    int npages;    int index;        if (fixed_dvma)	return;    if (!dvma_is_slow(dvma_addr)) {	index = (dvma_addr >> DVMA_PAGE_SHIFT);	if (dvma_entry_use(index) == 0) {	    printk ("dvma_free: %lx entry already free\n",dvma_addr);	    return;	}        dvma_entry_dec(index);	if (dvma_entry_use(index) == 0)	    dvma_entry_clr(index);	return;    }    /* free in slow pool */    npages = ((dvma_addr & ~DVMA_PAGE_MASK) + size + (DVMA_PAGE_SIZE-1)) >>	    DVMA_PAGE_SHIFT;    for (index = (dvma_addr >> DVMA_PAGE_SHIFT); npages--; index++) {	dvma_entry_clr(index);	clear_bit (index,dvma_map);    }}

⌨️ 快捷键说明

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