pci-dma.c

来自「linux 内核源代码」· C语言 代码 · 共 94 行

C
94
字号
/* * arch/xtensa/kernel/pci-dma.c * * DMA coherent memory allocation. * * 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. * * Copyright (C) 2002 - 2005 Tensilica Inc. * * Based on version for i386. * * Chris Zankel <chris@zankel.net> * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> */#include <linux/types.h>#include <linux/mm.h>#include <linux/string.h>#include <linux/pci.h>#include <asm/io.h>#include <asm/cacheflush.h>/* * Note: We assume that the full memory space is always mapped to 'kseg' *	 Otherwise we have to use page attributes (not implemented). */void *dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *handle,gfp_t flag){	unsigned long ret;	unsigned long uncached = 0;	/* ignore region speicifiers */	flag &= ~(__GFP_DMA | __GFP_HIGHMEM);	if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))		flag |= GFP_DMA;	ret = (unsigned long)__get_free_pages(flag, get_order(size));	if (ret == 0)		return NULL;	/* We currently don't support coherent memory outside KSEG */	if (ret < XCHAL_KSEG_CACHED_VADDR	    || ret >= XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE)		BUG();	if (ret != 0) {		memset((void*) ret, 0, size);		uncached = ret+XCHAL_KSEG_BYPASS_VADDR-XCHAL_KSEG_CACHED_VADDR;		*handle = virt_to_bus((void*)ret);		__flush_invalidate_dcache_range(ret, size);	}	return (void*)uncached;}void dma_free_coherent(struct device *hwdev, size_t size,			 void *vaddr, dma_addr_t dma_handle){	long addr=(long)vaddr+XCHAL_KSEG_CACHED_VADDR-XCHAL_KSEG_BYPASS_VADDR;	if (addr < 0 || addr >= XCHAL_KSEG_SIZE)		BUG();	free_pages(addr, get_order(size));}void consistent_sync(void *vaddr, size_t size, int direction){	switch (direction) {	case PCI_DMA_NONE:		BUG();	case PCI_DMA_FROMDEVICE:        /* invalidate only */		__invalidate_dcache_range((unsigned long)vaddr,				          (unsigned long)size);		break;	case PCI_DMA_TODEVICE:          /* writeback only */	case PCI_DMA_BIDIRECTIONAL:     /* writeback and invalidate */		__flush_invalidate_dcache_range((unsigned long)vaddr,				    		(unsigned long)size);		break;	}}

⌨️ 快捷键说明

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