亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? sbus.c

?? 一個2.4.21版本的嵌入式linux內核
?? C
?? 第 1 頁 / 共 3 頁
字號:
/* $Id: sbus.c,v 1.17.2.1 2002/03/03 10:31:56 davem Exp $ * sbus.c: UltraSparc SBUS controller support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) */#include <linux/kernel.h>#include <linux/types.h>#include <linux/mm.h>#include <linux/spinlock.h>#include <linux/slab.h>#include <linux/init.h>#include <asm/page.h>#include <asm/sbus.h>#include <asm/io.h>#include <asm/upa.h>#include <asm/cache.h>#include <asm/dma.h>#include <asm/irq.h>#include <asm/starfire.h>#include "iommu_common.h"/* These should be allocated on an SMP_CACHE_BYTES * aligned boundry for optimal performance. * * On SYSIO, using an 8K page size we have 1GB of SBUS * DMA space mapped.  We divide this space into equally * sized clusters.  Currently we allow clusters up to a * size of 1MB.  If anything begins to generate DMA * mapping requests larger than this we will need to * increase things a bit. */#define NCLUSTERS	8UL#define ONE_GIG		(1UL * 1024UL * 1024UL * 1024UL)#define CLUSTER_SIZE	(ONE_GIG / NCLUSTERS)#define CLUSTER_MASK	(CLUSTER_SIZE - 1)#define CLUSTER_NPAGES	(CLUSTER_SIZE >> IO_PAGE_SHIFT)#define MAP_BASE	((u32)0xc0000000)struct sbus_iommu {/*0x00*/spinlock_t		lock;/*0x08*/iopte_t			*page_table;/*0x10*/unsigned long		strbuf_regs;/*0x18*/unsigned long		iommu_regs;/*0x20*/unsigned long		sbus_control_reg;/*0x28*/volatile unsigned long	strbuf_flushflag;	/* If NCLUSTERS is ever decresed to 4 or lower,	 * you must increase the size of the type of	 * these counters.  You have been duly warned. -DaveM	 *//*0x30*/struct {		u16	next;		u16	flush;	} alloc_info[NCLUSTERS];	/* The lowest used consistent mapping entry.  Since	 * we allocate consistent maps out of cluster 0 this	 * is relative to the beginning of closter 0.	 *//*0x50*/u32		lowest_consistent_map;};/* Offsets from iommu_regs */#define SYSIO_IOMMUREG_BASE	0x2400UL#define IOMMU_CONTROL	(0x2400UL - 0x2400UL)	/* IOMMU control register */#define IOMMU_TSBBASE	(0x2408UL - 0x2400UL)	/* TSB base address register */#define IOMMU_FLUSH	(0x2410UL - 0x2400UL)	/* IOMMU flush register */#define IOMMU_VADIAG	(0x4400UL - 0x2400UL)	/* SBUS virtual address diagnostic */#define IOMMU_TAGCMP	(0x4408UL - 0x2400UL)	/* TLB tag compare diagnostics */#define IOMMU_LRUDIAG	(0x4500UL - 0x2400UL)	/* IOMMU LRU queue diagnostics */#define IOMMU_TAGDIAG	(0x4580UL - 0x2400UL)	/* TLB tag diagnostics */#define IOMMU_DRAMDIAG	(0x4600UL - 0x2400UL)	/* TLB data RAM diagnostics */#define IOMMU_DRAM_VALID	(1UL << 30UL)static void __iommu_flushall(struct sbus_iommu *iommu){	unsigned long tag = iommu->iommu_regs + IOMMU_TAGDIAG;	int entry;	for (entry = 0; entry < 16; entry++) {		upa_writeq(0, tag);		tag += 8UL;	}	upa_readq(iommu->sbus_control_reg);	for (entry = 0; entry < NCLUSTERS; entry++) {		iommu->alloc_info[entry].flush =			iommu->alloc_info[entry].next;	}}static void iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages){	while (npages--)		upa_writeq(base + (npages << IO_PAGE_SHIFT),			   iommu->iommu_regs + IOMMU_FLUSH);	upa_readq(iommu->sbus_control_reg);}/* Offsets from strbuf_regs */#define SYSIO_STRBUFREG_BASE	0x2800UL#define STRBUF_CONTROL	(0x2800UL - 0x2800UL)	/* Control */#define STRBUF_PFLUSH	(0x2808UL - 0x2800UL)	/* Page flush/invalidate */#define STRBUF_FSYNC	(0x2810UL - 0x2800UL)	/* Flush synchronization */#define STRBUF_DRAMDIAG	(0x5000UL - 0x2800UL)	/* data RAM diagnostic */#define STRBUF_ERRDIAG	(0x5400UL - 0x2800UL)	/* error status diagnostics */#define STRBUF_PTAGDIAG	(0x5800UL - 0x2800UL)	/* Page tag diagnostics */#define STRBUF_LTAGDIAG	(0x5900UL - 0x2800UL)	/* Line tag diagnostics */#define STRBUF_TAG_VALID	0x02ULstatic void strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages){	iommu->strbuf_flushflag = 0UL;	while (npages--)		upa_writeq(base + (npages << IO_PAGE_SHIFT),			   iommu->strbuf_regs + STRBUF_PFLUSH);	/* Whoopee cushion! */	upa_writeq(__pa(&iommu->strbuf_flushflag),		   iommu->strbuf_regs + STRBUF_FSYNC);	upa_readq(iommu->sbus_control_reg);	while (iommu->strbuf_flushflag == 0UL)		membar("#LoadLoad");}static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages){	iopte_t *iopte, *limit, *first;	unsigned long cnum, ent, flush_point;	cnum = 0;	while ((1UL << cnum) < npages)		cnum++;	iopte  = iommu->page_table + (cnum * CLUSTER_NPAGES);	if (cnum == 0)		limit = (iommu->page_table +			 iommu->lowest_consistent_map);	else		limit = (iopte + CLUSTER_NPAGES);	iopte += ((ent = iommu->alloc_info[cnum].next) << cnum);	flush_point = iommu->alloc_info[cnum].flush;	first = iopte;	for (;;) {		if (iopte_val(*iopte) == 0UL) {			if ((iopte + (1 << cnum)) >= limit)				ent = 0;			else				ent = ent + 1;			iommu->alloc_info[cnum].next = ent;			if (ent == flush_point)				__iommu_flushall(iommu);			break;		}		iopte += (1 << cnum);		ent++;		if (iopte >= limit) {			iopte = (iommu->page_table + (cnum * CLUSTER_NPAGES));			ent = 0;		}		if (ent == flush_point)			__iommu_flushall(iommu);		if (iopte == first)			goto bad;	}	/* I've got your streaming cluster right here buddy boy... */	return iopte;bad:	printk(KERN_EMERG "sbus: alloc_streaming_cluster of npages(%ld) failed!\n",	       npages);	return NULL;}static void free_streaming_cluster(struct sbus_iommu *iommu, u32 base, unsigned long npages){	unsigned long cnum, ent;	iopte_t *iopte;	cnum = 0;	while ((1UL << cnum) < npages)		cnum++;	ent = (base & CLUSTER_MASK) >> (IO_PAGE_SHIFT + cnum);	iopte = iommu->page_table + ((base - MAP_BASE) >> IO_PAGE_SHIFT);	iopte_val(*iopte) = 0UL;	/* If the global flush might not have caught this entry,	 * adjust the flush point such that we will flush before	 * ever trying to reuse it.	 */#define between(X,Y,Z)	(((Z) - (Y)) >= ((X) - (Y)))	if (between(ent, iommu->alloc_info[cnum].next, iommu->alloc_info[cnum].flush))		iommu->alloc_info[cnum].flush = ent;#undef between}/* We allocate consistent mappings from the end of cluster zero. */static iopte_t *alloc_consistent_cluster(struct sbus_iommu *iommu, unsigned long npages){	iopte_t *iopte;	iopte = iommu->page_table + (1 * CLUSTER_NPAGES);	while (iopte > iommu->page_table) {		iopte--;		if (!(iopte_val(*iopte) & IOPTE_VALID)) {			unsigned long tmp = npages;			while (--tmp) {				iopte--;				if (iopte_val(*iopte) & IOPTE_VALID)					break;			}			if (tmp == 0) {				u32 entry = (iopte - iommu->page_table);				if (entry < iommu->lowest_consistent_map)					iommu->lowest_consistent_map = entry;				return iopte;			}		}	}	return NULL;}static void free_consistent_cluster(struct sbus_iommu *iommu, u32 base, unsigned long npages){	iopte_t *iopte = iommu->page_table + ((base - MAP_BASE) >> IO_PAGE_SHIFT);	if ((iopte - iommu->page_table) == iommu->lowest_consistent_map) {		iopte_t *walk = iopte + npages;		iopte_t *limit;		limit = iommu->page_table + CLUSTER_NPAGES;		while (walk < limit) {			if (iopte_val(*walk) != 0UL)				break;			walk++;		}		iommu->lowest_consistent_map =			(walk - iommu->page_table);	}	while (npages--)		*iopte++ = __iopte(0UL);}void *sbus_alloc_consistent(struct sbus_dev *sdev, size_t size, dma_addr_t *dvma_addr){	unsigned long order, first_page, flags;	struct sbus_iommu *iommu;	iopte_t *iopte;	void *ret;	int npages;	if (size <= 0 || sdev == NULL || dvma_addr == NULL)		return NULL;	size = IO_PAGE_ALIGN(size);	order = get_order(size);	if (order >= 10)		return NULL;	first_page = __get_free_pages(GFP_KERNEL, order);	if (first_page == 0UL)		return NULL;	memset((char *)first_page, 0, PAGE_SIZE << order);	iommu = sdev->bus->iommu;	spin_lock_irqsave(&iommu->lock, flags);	iopte = alloc_consistent_cluster(iommu, size >> IO_PAGE_SHIFT);	if (iopte == NULL) {		spin_unlock_irqrestore(&iommu->lock, flags);		free_pages(first_page, order);		return NULL;	}	/* Ok, we're committed at this point. */	*dvma_addr = MAP_BASE +	((iopte - iommu->page_table) << IO_PAGE_SHIFT);	ret = (void *) first_page;	npages = size >> IO_PAGE_SHIFT;	while (npages--) {		*iopte++ = __iopte(IOPTE_VALID | IOPTE_CACHE | IOPTE_WRITE |				   (__pa(first_page) & IOPTE_PAGE));		first_page += IO_PAGE_SIZE;	}	iommu_flush(iommu, *dvma_addr, size >> IO_PAGE_SHIFT);	spin_unlock_irqrestore(&iommu->lock, flags);	return ret;}void sbus_free_consistent(struct sbus_dev *sdev, size_t size, void *cpu, dma_addr_t dvma){	unsigned long order, npages;	struct sbus_iommu *iommu;	if (size <= 0 || sdev == NULL || cpu == NULL)		return;	npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;	iommu = sdev->bus->iommu;	spin_lock_irq(&iommu->lock);	free_consistent_cluster(iommu, dvma, npages);	iommu_flush(iommu, dvma, npages);	spin_unlock_irq(&iommu->lock);	order = get_order(size);	if (order < 10)		free_pages((unsigned long)cpu, order);}dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t size, int dir){	struct sbus_iommu *iommu = sdev->bus->iommu;	unsigned long npages, pbase, flags;	iopte_t *iopte;	u32 dma_base, offset;	unsigned long iopte_bits;	if (dir == SBUS_DMA_NONE)		BUG();	pbase = (unsigned long) ptr;	offset = (u32) (pbase & ~IO_PAGE_MASK);	size = (IO_PAGE_ALIGN(pbase + size) - (pbase & IO_PAGE_MASK));	pbase = (unsigned long) __pa(pbase & IO_PAGE_MASK);	spin_lock_irqsave(&iommu->lock, flags);	npages = size >> IO_PAGE_SHIFT;	iopte = alloc_streaming_cluster(iommu, npages);	if (iopte == NULL)		goto bad;	dma_base = MAP_BASE + ((iopte - iommu->page_table) << IO_PAGE_SHIFT);	npages = size >> IO_PAGE_SHIFT;	iopte_bits = IOPTE_VALID | IOPTE_STBUF | IOPTE_CACHE;	if (dir != SBUS_DMA_TODEVICE)		iopte_bits |= IOPTE_WRITE;	while (npages--) {		*iopte++ = __iopte(iopte_bits | (pbase & IOPTE_PAGE));		pbase += IO_PAGE_SIZE;	}	npages = size >> IO_PAGE_SHIFT;	spin_unlock_irqrestore(&iommu->lock, flags);	return (dma_base | offset);bad:	spin_unlock_irqrestore(&iommu->lock, flags);	BUG();	return 0;}void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size, int direction){	struct sbus_iommu *iommu = sdev->bus->iommu;	u32 dma_base = dma_addr & IO_PAGE_MASK;	unsigned long flags;	size = (IO_PAGE_ALIGN(dma_addr + size) - dma_base);	spin_lock_irqsave(&iommu->lock, flags);	free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT);	strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT);	spin_unlock_irqrestore(&iommu->lock, flags);}#define SG_ENT_PHYS_ADDRESS(SG)	\	((SG)->address ? \	 __pa((SG)->address) : \	 (__pa(page_address((SG)->page)) + (SG)->offset))static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused, int nelems, unsigned long iopte_bits){	struct scatterlist *dma_sg = sg;	struct scatterlist *sg_end = sg + nelems;	int i;	for (i = 0; i < nused; i++) {		unsigned long pteval = ~0UL;		u32 dma_npages;		dma_npages = ((dma_sg->dma_address & (IO_PAGE_SIZE - 1UL)) +			      dma_sg->dma_length +			      ((IO_PAGE_SIZE - 1UL))) >> IO_PAGE_SHIFT;		do {			unsigned long offset;			signed int len;

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
国产欧美日韩在线看| 久久精品国产一区二区三| 日韩情涩欧美日韩视频| 日本一区二区视频在线| 午夜精品成人在线| av在线综合网| 26uuu久久综合| 肉色丝袜一区二区| 一本到三区不卡视频| 国产欧美日韩在线| 国产精品免费视频观看| 蜜臀国产一区二区三区在线播放| 秋霞国产午夜精品免费视频 | 91麻豆国产福利在线观看| 91精品国产全国免费观看| 伊人夜夜躁av伊人久久| 亚洲一区在线免费观看| 99久久精品99国产精品| 国产人久久人人人人爽| 亚洲欧美影音先锋| 国产成人无遮挡在线视频| 欧美国产综合一区二区| 激情伊人五月天久久综合| 欧美人动与zoxxxx乱| 日韩欧美综合一区| 亚洲高清三级视频| 欧美性受xxxx| 亚洲线精品一区二区三区| 91美女片黄在线观看| 亚洲精品高清在线观看| 在线中文字幕不卡| 一级女性全黄久久生活片免费| 日本欧美一区二区| 国产一区二区三区免费| 91久久精品网| 亚洲午夜久久久久久久久电影网| 久久99国产乱子伦精品免费| 91 com成人网| 奇米888四色在线精品| 精品日产卡一卡二卡麻豆| 黑人巨大精品欧美一区| 国产婷婷色一区二区三区在线| 亚洲私人黄色宅男| 91在线你懂得| 欧美sm美女调教| 国产一区91精品张津瑜| 国产情人综合久久777777| 99久久婷婷国产综合精品电影| 欧美一二三四区在线| 麻豆精品国产传媒mv男同| 91影院在线观看| 亚洲国产精品欧美一二99| 宅男噜噜噜66一区二区66| 理论片日本一区| 国产精品不卡在线| 欧美日韩精品欧美日韩精品| 国产在线视频一区二区三区| 欧美人动与zoxxxx乱| 久草在线在线精品观看| 亚洲天堂免费看| 6080亚洲精品一区二区| 国产大陆亚洲精品国产| 亚洲黄色性网站| 精品国产伦一区二区三区观看方式| 一区二区三区免费| 日韩欧美国产高清| av午夜一区麻豆| 中文一区在线播放| 欧美专区日韩专区| 亚洲蜜臀av乱码久久精品蜜桃| 国产一区二区三区久久久| 亚洲欧美另类小说视频| 日韩欧美区一区二| 日本韩国欧美一区| 国产成人精品亚洲午夜麻豆| 午夜久久电影网| 国产精品免费aⅴ片在线观看| 国v精品久久久网| 日韩和欧美一区二区| 欧美精品123区| 成人高清视频在线观看| 美女免费视频一区二区| 国产精品国产三级国产普通话三级 | 欧美顶级少妇做爰| 成人av网站在线观看免费| 免费成人av在线播放| 曰韩精品一区二区| 国产精品久久久久久久久图文区 | 经典三级一区二区| 一区二区三区在线看| 欧美日韩一区二区在线观看 | 日韩一级完整毛片| 色婷婷国产精品久久包臀| 国产91精品在线观看| 日本伊人色综合网| 欧美亚洲免费在线一区| 久久久久久毛片| 欧洲精品在线观看| 成人av网站免费| 国内精品视频666| 国产午夜精品一区二区三区嫩草 | 午夜精品福利在线| 日韩国产欧美在线播放| 国产一区二区在线电影| 成人免费视频caoporn| 欧美丝袜自拍制服另类| www.亚洲国产| 欧美中文一区二区三区| 精品国产区一区| 4438x成人网最大色成网站| 91国产成人在线| 精品国产一区二区三区久久影院 | 日韩欧美一级二级| 日本一区二区三区高清不卡| 精品久久国产老人久久综合| 7777精品伊人久久久大香线蕉的 | 一区二区三区精品在线观看| 亚洲天堂免费在线观看视频| 日韩精品欧美成人高清一区二区| 亚洲精品综合在线| 亚洲欧美电影一区二区| 日韩中文字幕91| 成人精品免费看| 99久久国产综合色|国产精品| 不卡一二三区首页| 91精品在线免费| 亚洲免费大片在线观看| 国产一本一道久久香蕉| 欧美丝袜丝交足nylons图片| 欧美日韩视频在线第一区 | 国产日韩欧美精品在线| 亚洲一区二区三区四区五区黄| 一区二区欧美在线观看| 国产福利一区在线观看| 国产成都精品91一区二区三| 欧美欧美欧美欧美| 亚洲视频在线一区观看| 国产在线播放一区三区四| 欧美区视频在线观看| 亚洲人成精品久久久久久| 国产成人亚洲精品狼色在线| 欧美日韩国产综合视频在线观看 | 亚洲午夜三级在线| 99久久婷婷国产精品综合| 亚洲精品一线二线三线无人区| 亚洲精品一区二区三区精华液| 久久中文字幕电影| 日本午夜精品一区二区三区电影| 蜜臀av性久久久久蜜臀aⅴ流畅| 久久精品国产亚洲5555| 欧美群妇大交群的观看方式| 亚洲欧美色综合| 99精品欧美一区二区三区综合在线| 91免费国产在线观看| 国产欧美精品区一区二区三区 | 欧美日韩国产综合久久| 日韩女优毛片在线| 国产精品丝袜91| 高清不卡一区二区| 久久久99精品免费观看不卡| 一区二区成人在线观看| 日本韩国欧美一区二区三区| 亚洲免费观看高清在线观看| 日韩国产欧美在线播放| 欧美二区三区91| 日韩不卡免费视频| 日韩欧美视频一区| 精品一区二区影视| 色综合久久综合| 亚洲一级二级在线| 欧美日韩一级二级三级| 偷拍一区二区三区四区| 欧美一级生活片| 亚洲精选视频免费看| 欧美亚洲综合一区| 一区二区三区在线视频观看| 在线一区二区三区| 亚洲一区二区三区四区在线观看| 国产成人精品综合在线观看| 国产精品无圣光一区二区| 99re热这里只有精品免费视频 | 国产亚洲一区二区三区在线观看| 亚洲综合免费观看高清完整版| 国产盗摄精品一区二区三区在线| 欧美日韩高清在线| 亚洲视频综合在线| 在线观看av不卡| 麻豆精品一区二区三区| 国产亚洲成年网址在线观看| 99视频精品全部免费在线| 一区二区成人在线| 日韩午夜激情av| 高清在线观看日韩| 亚洲一区二区三区四区在线免费观看 | 久久99精品久久久久久久久久久久| 91久久一区二区| 热久久久久久久| 中文字幕乱码亚洲精品一区| 欧美体内she精高潮| 美女久久久精品|