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

📄 generic.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * AGPGART driver. * Copyright (C) 2004 Silicon Graphics, Inc. * Copyright (C) 2002-2005 Dave Jones. * Copyright (C) 1999 Jeff Hartmann. * Copyright (C) 1999 Precision Insight, Inc. * Copyright (C) 1999 Xi Graphics, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * TODO: * - Allocate more than order 0 pages to avoid too much linear map splitting. */#include <linux/config.h>#include <linux/module.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/pagemap.h>#include <linux/miscdevice.h>#include <linux/pm.h>#include <linux/agp_backend.h>#include <linux/vmalloc.h>#include <linux/dma-mapping.h>#include <linux/mm.h>#include <asm/io.h>#include <asm/cacheflush.h>#include <asm/pgtable.h>#include "agp.h"__u32 *agp_gatt_table;int agp_memory_reserved;/* * Needed by the Nforce GART driver for the time being. Would be * nice to do this some other way instead of needing this export. */EXPORT_SYMBOL_GPL(agp_memory_reserved);#if defined(CONFIG_X86)int map_page_into_agp(struct page *page){	int i;	i = change_page_attr(page, 1, PAGE_KERNEL_NOCACHE);	/* Caller's responsibility to call global_flush_tlb() for	 * performance reasons */	return i;}EXPORT_SYMBOL_GPL(map_page_into_agp);int unmap_page_from_agp(struct page *page){	int i;	i = change_page_attr(page, 1, PAGE_KERNEL);	/* Caller's responsibility to call global_flush_tlb() for	 * performance reasons */	return i;}EXPORT_SYMBOL_GPL(unmap_page_from_agp);#endif/* * Generic routines for handling agp_memory structures - * They use the basic page allocation routines to do the brunt of the work. */void agp_free_key(int key){	if (key < 0)		return;	if (key < MAXKEY)		clear_bit(key, agp_bridge->key_list);}EXPORT_SYMBOL(agp_free_key);static int agp_get_key(void){	int bit;	bit = find_first_zero_bit(agp_bridge->key_list, MAXKEY);	if (bit < MAXKEY) {		set_bit(bit, agp_bridge->key_list);		return bit;	}	return -1;}struct agp_memory *agp_create_memory(int scratch_pages){	struct agp_memory *new;	new = kzalloc(sizeof(struct agp_memory), GFP_KERNEL);	if (new == NULL)		return NULL;	new->key = agp_get_key();	if (new->key < 0) {		kfree(new);		return NULL;	}	new->memory = vmalloc(PAGE_SIZE * scratch_pages);	if (new->memory == NULL) {		agp_free_key(new->key);		kfree(new);		return NULL;	}	new->num_scratch_pages = scratch_pages;	return new;}EXPORT_SYMBOL(agp_create_memory);/** *	agp_free_memory - free memory associated with an agp_memory pointer. * *	@curr:		agp_memory pointer to be freed. * *	It is the only function that can be called when the backend is not owned *	by the caller.  (So it can free memory on client death.) */void agp_free_memory(struct agp_memory *curr){	size_t i;	if (curr == NULL)		return;	if (curr->is_bound == TRUE)		agp_unbind_memory(curr);	if (curr->type != 0) {		curr->bridge->driver->free_by_type(curr);		return;	}	if (curr->page_count != 0) {		for (i = 0; i < curr->page_count; i++) {			curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]));		}		flush_agp_mappings();	}	agp_free_key(curr->key);	vfree(curr->memory);	kfree(curr);}EXPORT_SYMBOL(agp_free_memory);#define ENTRIES_PER_PAGE		(PAGE_SIZE / sizeof(unsigned long))/** *	agp_allocate_memory  -  allocate a group of pages of a certain type. * *	@page_count:	size_t argument of the number of pages *	@type:	u32 argument of the type of memory to be allocated. * *	Every agp bridge device will allow you to allocate AGP_NORMAL_MEMORY which *	maps to physical ram.  Any other type is device dependent. * *	It returns NULL whenever memory is unavailable. */struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,					size_t page_count, u32 type){	int scratch_pages;	struct agp_memory *new;	size_t i;	if (!bridge)		return NULL;	if ((atomic_read(&bridge->current_memory_agp) + page_count) > bridge->max_memory_agp)		return NULL;	if (type != 0) {		new = bridge->driver->alloc_by_type(page_count, type);		if (new)			new->bridge = bridge;		return new;	}	scratch_pages = (page_count + ENTRIES_PER_PAGE - 1) / ENTRIES_PER_PAGE;	new = agp_create_memory(scratch_pages);	if (new == NULL)		return NULL;	for (i = 0; i < page_count; i++) {		void *addr = bridge->driver->agp_alloc_page(bridge);		if (addr == NULL) {			agp_free_memory(new);			return NULL;		}		new->memory[i] = virt_to_gart(addr);		new->page_count++;	}	new->bridge = bridge;	flush_agp_mappings();	return new;}EXPORT_SYMBOL(agp_allocate_memory);/* End - Generic routines for handling agp_memory structures */static int agp_return_size(void){	int current_size;	void *temp;	temp = agp_bridge->current_size;	switch (agp_bridge->driver->size_type) {	case U8_APER_SIZE:		current_size = A_SIZE_8(temp)->size;		break;	case U16_APER_SIZE:		current_size = A_SIZE_16(temp)->size;		break;	case U32_APER_SIZE:		current_size = A_SIZE_32(temp)->size;		break;	case LVL2_APER_SIZE:		current_size = A_SIZE_LVL2(temp)->size;		break;	case FIXED_APER_SIZE:		current_size = A_SIZE_FIX(temp)->size;		break;	default:		current_size = 0;		break;	}	current_size -= (agp_memory_reserved / (1024*1024));	if (current_size <0)		current_size = 0;	return current_size;}int agp_num_entries(void){	int num_entries;	void *temp;	temp = agp_bridge->current_size;	switch (agp_bridge->driver->size_type) {	case U8_APER_SIZE:		num_entries = A_SIZE_8(temp)->num_entries;		break;	case U16_APER_SIZE:		num_entries = A_SIZE_16(temp)->num_entries;		break;	case U32_APER_SIZE:		num_entries = A_SIZE_32(temp)->num_entries;		break;	case LVL2_APER_SIZE:		num_entries = A_SIZE_LVL2(temp)->num_entries;		break;	case FIXED_APER_SIZE:		num_entries = A_SIZE_FIX(temp)->num_entries;		break;	default:		num_entries = 0;		break;	}	num_entries -= agp_memory_reserved>>PAGE_SHIFT;	if (num_entries<0)		num_entries = 0;	return num_entries;}EXPORT_SYMBOL_GPL(agp_num_entries);/** *	agp_copy_info  -  copy bridge state information * *	@info:		agp_kern_info pointer.  The caller should insure that this pointer is valid.  * *	This function copies information about the agp bridge device and the state of *	the agp backend into an agp_kern_info pointer. */int agp_copy_info(struct agp_bridge_data *bridge, struct agp_kern_info *info){	memset(info, 0, sizeof(struct agp_kern_info));	if (!bridge) {		info->chipset = NOT_SUPPORTED;		return -EIO;	}	info->version.major = bridge->version->major;	info->version.minor = bridge->version->minor;	info->chipset = SUPPORTED;	info->device = bridge->dev;	if (bridge->mode & AGPSTAT_MODE_3_0)		info->mode = bridge->mode & ~AGP3_RESERVED_MASK;	else		info->mode = bridge->mode & ~AGP2_RESERVED_MASK;	info->aper_base = bridge->gart_bus_addr;	info->aper_size = agp_return_size();	info->max_memory = bridge->max_memory_agp;	info->current_memory = atomic_read(&bridge->current_memory_agp);	info->cant_use_aperture = bridge->driver->cant_use_aperture;	info->vm_ops = bridge->vm_ops;	info->page_mask = ~0UL;	return 0;}EXPORT_SYMBOL(agp_copy_info);/* End - Routine to copy over information structure *//* * Routines for handling swapping of agp_memory into the GATT - * These routines take agp_memory and insert them into the GATT. * They call device specific routines to actually write to the GATT. *//** *	agp_bind_memory  -  Bind an agp_memory structure into the GATT. * *	@curr:		agp_memory pointer *	@pg_start:	an offset into the graphics aperture translation table * *	It returns -EINVAL if the pointer == NULL. *	It returns -EBUSY if the area of the table requested is already in use. */int agp_bind_memory(struct agp_memory *curr, off_t pg_start){	int ret_val;	if (curr == NULL)		return -EINVAL;	if (curr->is_bound == TRUE) {		printk(KERN_INFO PFX "memory %p is already bound!\n", curr);		return -EINVAL;	}	if (curr->is_flushed == FALSE) {		curr->bridge->driver->cache_flush();		curr->is_flushed = TRUE;	}	ret_val = curr->bridge->driver->insert_memory(curr, pg_start, curr->type);	if (ret_val != 0)		return ret_val;	curr->is_bound = TRUE;	curr->pg_start = pg_start;	return 0;}EXPORT_SYMBOL(agp_bind_memory);/** *	agp_unbind_memory  -  Removes an agp_memory structure from the GATT * * @curr:	agp_memory pointer to be removed from the GATT. * * It returns -EINVAL if this piece of agp_memory is not currently bound to * the graphics aperture translation table or if the agp_memory pointer == NULL */int agp_unbind_memory(struct agp_memory *curr){	int ret_val;	if (curr == NULL)		return -EINVAL;	if (curr->is_bound != TRUE) {		printk(KERN_INFO PFX "memory %p was not bound!\n", curr);		return -EINVAL;	}	ret_val = curr->bridge->driver->remove_memory(curr, curr->pg_start, curr->type);	if (ret_val != 0)		return ret_val;	curr->is_bound = FALSE;	curr->pg_start = 0;

⌨️ 快捷键说明

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