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

📄 frontend.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * AGPGART driver frontend * Copyright (C) 2004 Silicon Graphics, Inc. * Copyright (C) 2002-2003 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. * */#include <linux/types.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/mman.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/miscdevice.h>#include <linux/agp_backend.h>#include <linux/agpgart.h>#include <linux/slab.h>#include <linux/mm.h>#include <asm/uaccess.h>#include <asm/pgtable.h>#include "agp.h"static struct agp_front_data agp_fe;static struct agp_memory *agp_find_mem_by_key(int key){	struct agp_memory *curr;	if (agp_fe.current_controller == NULL)		return NULL;	curr = agp_fe.current_controller->pool;	while (curr != NULL) {		if (curr->key == key)			break;		curr = curr->next;	}	DBG("key=%d -> mem=%p", key, curr);	return curr;}static void agp_remove_from_pool(struct agp_memory *temp){	struct agp_memory *prev;	struct agp_memory *next;	/* Check to see if this is even in the memory pool */	DBG("mem=%p", temp);	if (agp_find_mem_by_key(temp->key) != NULL) {		next = temp->next;		prev = temp->prev;		if (prev != NULL) {			prev->next = next;			if (next != NULL)				next->prev = prev;		} else {			/* This is the first item on the list */			if (next != NULL)				next->prev = NULL;			agp_fe.current_controller->pool = next;		}	}}/* * Routines for managing each client's segment list - * These routines handle adding and removing segments * to each auth'ed client. */static structagp_segment_priv *agp_find_seg_in_client(const struct agp_client *client,						unsigned long offset,					    int size, pgprot_t page_prot){	struct agp_segment_priv *seg;	int num_segments, i;	off_t pg_start;	size_t pg_count;	pg_start = offset / 4096;	pg_count = size / 4096;	seg = *(client->segments);	num_segments = client->num_segments;	for (i = 0; i < client->num_segments; i++) {		if ((seg[i].pg_start == pg_start) &&		    (seg[i].pg_count == pg_count) &&		    (pgprot_val(seg[i].prot) == pgprot_val(page_prot))) {			return seg + i;		}	}	return NULL;}static void agp_remove_seg_from_client(struct agp_client *client){	DBG("client=%p", client);	if (client->segments != NULL) {		if (*(client->segments) != NULL) {			DBG("Freeing %p from client %p", *(client->segments), client);			kfree(*(client->segments));		}		DBG("Freeing %p from client %p", client->segments, client);		kfree(client->segments);		client->segments = NULL;	}}static void agp_add_seg_to_client(struct agp_client *client,			       struct agp_segment_priv ** seg, int num_segments){	struct agp_segment_priv **prev_seg;	prev_seg = client->segments;	if (prev_seg != NULL)		agp_remove_seg_from_client(client);	DBG("Adding seg %p (%d segments) to client %p", seg, num_segments, client);	client->num_segments = num_segments;	client->segments = seg;}/* Originally taken from linux/mm/mmap.c from the array * protection_map. * The original really should be exported to modules, or * some routine which does the conversion for you */static const pgprot_t my_protect_map[16] ={	__P000, __P001, __P010, __P011, __P100, __P101, __P110, __P111,	__S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111};static pgprot_t agp_convert_mmap_flags(int prot){#define _trans(x,bit1,bit2) \((bit1==bit2)?(x&bit1):(x&bit1)?bit2:0)	unsigned long prot_bits;	pgprot_t temp;	prot_bits = _trans(prot, PROT_READ, VM_READ) |	    _trans(prot, PROT_WRITE, VM_WRITE) |	    _trans(prot, PROT_EXEC, VM_EXEC);	prot_bits |= VM_SHARED;	temp = my_protect_map[prot_bits & 0x0000000f];	return temp;}static int agp_create_segment(struct agp_client *client, struct agp_region *region){	struct agp_segment_priv **ret_seg;	struct agp_segment_priv *seg;	struct agp_segment *user_seg;	size_t i;	seg = kzalloc((sizeof(struct agp_segment_priv) * region->seg_count), GFP_KERNEL);	if (seg == NULL) {		kfree(region->seg_list);		region->seg_list = NULL;		return -ENOMEM;	}	user_seg = region->seg_list;	for (i = 0; i < region->seg_count; i++) {		seg[i].pg_start = user_seg[i].pg_start;		seg[i].pg_count = user_seg[i].pg_count;		seg[i].prot = agp_convert_mmap_flags(user_seg[i].prot);	}	kfree(region->seg_list);	region->seg_list = NULL;	ret_seg = kmalloc(sizeof(void *), GFP_KERNEL);	if (ret_seg == NULL) {		kfree(seg);		return -ENOMEM;	}	*ret_seg = seg;	agp_add_seg_to_client(client, ret_seg, region->seg_count);	return 0;}/* End - Routines for managing each client's segment list *//* This function must only be called when current_controller != NULL */static void agp_insert_into_pool(struct agp_memory * temp){	struct agp_memory *prev;	prev = agp_fe.current_controller->pool;	if (prev != NULL) {		prev->prev = temp;		temp->next = prev;	}	agp_fe.current_controller->pool = temp;}/* File private list routines */static struct agp_file_private *agp_find_private(pid_t pid){	struct agp_file_private *curr;	curr = agp_fe.file_priv_list;	while (curr != NULL) {		if (curr->my_pid == pid)			return curr;		curr = curr->next;	}	return NULL;}static void agp_insert_file_private(struct agp_file_private * priv){	struct agp_file_private *prev;	prev = agp_fe.file_priv_list;	if (prev != NULL)		prev->prev = priv;	priv->next = prev;	agp_fe.file_priv_list = priv;}static void agp_remove_file_private(struct agp_file_private * priv){	struct agp_file_private *next;	struct agp_file_private *prev;	next = priv->next;	prev = priv->prev;	if (prev != NULL) {		prev->next = next;		if (next != NULL)			next->prev = prev;	} else {		if (next != NULL)			next->prev = NULL;		agp_fe.file_priv_list = next;	}}/* End - File flag list routines *//* * Wrappers for agp_free_memory & agp_allocate_memory * These make sure that internal lists are kept updated. */static void agp_free_memory_wrap(struct agp_memory *memory){	agp_remove_from_pool(memory);	agp_free_memory(memory);}static struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type){	struct agp_memory *memory;	memory = agp_allocate_memory(agp_bridge, pg_count, type);	if (memory == NULL)		return NULL;	agp_insert_into_pool(memory);	return memory;}/* Routines for managing the list of controllers - * These routines manage the current controller, and the list of * controllers */static struct agp_controller *agp_find_controller_by_pid(pid_t id){	struct agp_controller *controller;	controller = agp_fe.controllers;	while (controller != NULL) {		if (controller->pid == id)			return controller;		controller = controller->next;	}	return NULL;}static struct agp_controller *agp_create_controller(pid_t id){	struct agp_controller *controller;	controller = kzalloc(sizeof(struct agp_controller), GFP_KERNEL);	if (controller == NULL)		return NULL;	controller->pid = id;	return controller;}static int agp_insert_controller(struct agp_controller *controller){	struct agp_controller *prev_controller;	prev_controller = agp_fe.controllers;	controller->next = prev_controller;	if (prev_controller != NULL)		prev_controller->prev = controller;	agp_fe.controllers = controller;	return 0;}static void agp_remove_all_clients(struct agp_controller *controller){	struct agp_client *client;	struct agp_client *temp;	client = controller->clients;	while (client) {		struct agp_file_private *priv;		temp = client;		agp_remove_seg_from_client(temp);		priv = agp_find_private(temp->pid);		if (priv != NULL) {			clear_bit(AGP_FF_IS_VALID, &priv->access_flags);			clear_bit(AGP_FF_IS_CLIENT, &priv->access_flags);		}		client = client->next;		kfree(temp);	}}static void agp_remove_all_memory(struct agp_controller *controller){	struct agp_memory *memory;	struct agp_memory *temp;	memory = controller->pool;	while (memory) {		temp = memory;		memory = memory->next;		agp_free_memory_wrap(temp);	}}static int agp_remove_controller(struct agp_controller *controller){	struct agp_controller *prev_controller;	struct agp_controller *next_controller;	prev_controller = controller->prev;	next_controller = controller->next;	if (prev_controller != NULL) {		prev_controller->next = next_controller;		if (next_controller != NULL)			next_controller->prev = prev_controller;	} else {		if (next_controller != NULL)			next_controller->prev = NULL;		agp_fe.controllers = next_controller;	}	agp_remove_all_memory(controller);	agp_remove_all_clients(controller);	if (agp_fe.current_controller == controller) {		agp_fe.current_controller = NULL;		agp_fe.backend_acquired = FALSE;		agp_backend_release(agp_bridge);	}	kfree(controller);	return 0;}static void agp_controller_make_current(struct agp_controller *controller){	struct agp_client *clients;	clients = controller->clients;	while (clients != NULL) {		struct agp_file_private *priv;		priv = agp_find_private(clients->pid);		if (priv != NULL) {			set_bit(AGP_FF_IS_VALID, &priv->access_flags);			set_bit(AGP_FF_IS_CLIENT, &priv->access_flags);		}		clients = clients->next;	}	agp_fe.current_controller = controller;}static void agp_controller_release_current(struct agp_controller *controller,				      struct agp_file_private *controller_priv){	struct agp_client *clients;	clear_bit(AGP_FF_IS_VALID, &controller_priv->access_flags);	clients = controller->clients;	while (clients != NULL) {		struct agp_file_private *priv;		priv = agp_find_private(clients->pid);		if (priv != NULL)			clear_bit(AGP_FF_IS_VALID, &priv->access_flags);		clients = clients->next;	}	agp_fe.current_controller = NULL;	agp_fe.used_by_controller = FALSE;	agp_backend_release(agp_bridge);}/* * Routines for managing client lists - * These routines are for managing the list of auth'ed clients. */static struct agp_client*agp_find_client_in_controller(struct agp_controller *controller, pid_t id){	struct agp_client *client;	if (controller == NULL)		return NULL;	client = controller->clients;	while (client != NULL) {		if (client->pid == id)			return client;		client = client->next;	}	return NULL;}static struct agp_controller *agp_find_controller_for_client(pid_t id){	struct agp_controller *controller;	controller = agp_fe.controllers;	while (controller != NULL) {		if ((agp_find_client_in_controller(controller, id)) != NULL)			return controller;		controller = controller->next;	}	return NULL;}static struct agp_client *agp_find_client_by_pid(pid_t id){	struct agp_client *temp;	if (agp_fe.current_controller == NULL)		return NULL;	temp = agp_find_client_in_controller(agp_fe.current_controller, id);	return temp;}static void agp_insert_client(struct agp_client *client){	struct agp_client *prev_client;	prev_client = agp_fe.current_controller->clients;	client->next = prev_client;	if (prev_client != NULL)		prev_client->prev = client;	agp_fe.current_controller->clients = client;	agp_fe.current_controller->num_clients++;}static struct agp_client *agp_create_client(pid_t id){	struct agp_client *new_client;	new_client = kzalloc(sizeof(struct agp_client), GFP_KERNEL);	if (new_client == NULL)		return NULL;	new_client->pid = id;	agp_insert_client(new_client);	return new_client;}static int agp_remove_client(pid_t id){

⌨️ 快捷键说明

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