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

📄 frontend.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct agp_client *client;	struct agp_client *prev_client;	struct agp_client *next_client;	struct agp_controller *controller;	controller = agp_find_controller_for_client(id);	if (controller == NULL)		return -EINVAL;	client = agp_find_client_in_controller(controller, id);	if (client == NULL)		return -EINVAL;	prev_client = client->prev;	next_client = client->next;	if (prev_client != NULL) {		prev_client->next = next_client;		if (next_client != NULL)			next_client->prev = prev_client;	} else {		if (next_client != NULL)			next_client->prev = NULL;		controller->clients = next_client;	}	controller->num_clients--;	agp_remove_seg_from_client(client);	kfree(client);	return 0;}/* End - Routines for managing client lists *//* File Operations */static int agp_mmap(struct file *file, struct vm_area_struct *vma){	unsigned int size, current_size;	unsigned long offset;	struct agp_client *client;	struct agp_file_private *priv = file->private_data;	struct agp_kern_info kerninfo;	down(&(agp_fe.agp_mutex));	if (agp_fe.backend_acquired != TRUE)		goto out_eperm;	if (!(test_bit(AGP_FF_IS_VALID, &priv->access_flags)))		goto out_eperm;	agp_copy_info(agp_bridge, &kerninfo);	size = vma->vm_end - vma->vm_start;	current_size = kerninfo.aper_size;	current_size = current_size * 0x100000;	offset = vma->vm_pgoff << PAGE_SHIFT;	DBG("%lx:%lx", offset, offset+size);	if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) {		if ((size + offset) > current_size)			goto out_inval;		client = agp_find_client_by_pid(current->pid);		if (client == NULL)			goto out_eperm;		if (!agp_find_seg_in_client(client, offset, size, vma->vm_page_prot))			goto out_inval;		DBG("client vm_ops=%p", kerninfo.vm_ops);		if (kerninfo.vm_ops) {			vma->vm_ops = kerninfo.vm_ops;		} else if (io_remap_pfn_range(vma, vma->vm_start,				(kerninfo.aper_base + offset) >> PAGE_SHIFT,					    size, vma->vm_page_prot)) {			goto out_again;		}		up(&(agp_fe.agp_mutex));		return 0;	}	if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {		if (size != current_size)			goto out_inval;		DBG("controller vm_ops=%p", kerninfo.vm_ops);		if (kerninfo.vm_ops) {			vma->vm_ops = kerninfo.vm_ops;		} else if (io_remap_pfn_range(vma, vma->vm_start,					    kerninfo.aper_base >> PAGE_SHIFT,					    size, vma->vm_page_prot)) {			goto out_again;		}		up(&(agp_fe.agp_mutex));		return 0;	}out_eperm:	up(&(agp_fe.agp_mutex));	return -EPERM;out_inval:	up(&(agp_fe.agp_mutex));	return -EINVAL;out_again:	up(&(agp_fe.agp_mutex));	return -EAGAIN;}static int agp_release(struct inode *inode, struct file *file){	struct agp_file_private *priv = file->private_data;	down(&(agp_fe.agp_mutex));	DBG("priv=%p", priv);	if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {		struct agp_controller *controller;		controller = agp_find_controller_by_pid(priv->my_pid);		if (controller != NULL) {			if (controller == agp_fe.current_controller)				agp_controller_release_current(controller, priv);			agp_remove_controller(controller);			controller = NULL;		}	}	if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags))		agp_remove_client(priv->my_pid);	agp_remove_file_private(priv);	kfree(priv);	file->private_data = NULL;	up(&(agp_fe.agp_mutex));	return 0;}static int agp_open(struct inode *inode, struct file *file){	int minor = iminor(inode);	struct agp_file_private *priv;	struct agp_client *client;	int rc = -ENXIO;	down(&(agp_fe.agp_mutex));	if (minor != AGPGART_MINOR)		goto err_out;	priv = kzalloc(sizeof(struct agp_file_private), GFP_KERNEL);	if (priv == NULL)		goto err_out_nomem;	set_bit(AGP_FF_ALLOW_CLIENT, &priv->access_flags);	priv->my_pid = current->pid;	if ((current->uid == 0) || (current->suid == 0)) {		/* Root priv, can be controller */		set_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags);	}	client = agp_find_client_by_pid(current->pid);	if (client != NULL) {		set_bit(AGP_FF_IS_CLIENT, &priv->access_flags);		set_bit(AGP_FF_IS_VALID, &priv->access_flags);	}	file->private_data = (void *) priv;	agp_insert_file_private(priv);	DBG("private=%p, client=%p", priv, client);	up(&(agp_fe.agp_mutex));	return 0;err_out_nomem:	rc = -ENOMEM;err_out:	up(&(agp_fe.agp_mutex));	return rc;}static ssize_t agp_read(struct file *file, char __user *buf,			size_t count, loff_t * ppos){	return -EINVAL;}static ssize_t agp_write(struct file *file, const char __user *buf,			 size_t count, loff_t * ppos){	return -EINVAL;}static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg){	struct agp_info userinfo;	struct agp_kern_info kerninfo;	agp_copy_info(agp_bridge, &kerninfo);	userinfo.version.major = kerninfo.version.major;	userinfo.version.minor = kerninfo.version.minor;	userinfo.bridge_id = kerninfo.device->vendor |	    (kerninfo.device->device << 16);	userinfo.agp_mode = kerninfo.mode;	userinfo.aper_base = kerninfo.aper_base;	userinfo.aper_size = kerninfo.aper_size;	userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory;	userinfo.pg_used = kerninfo.current_memory;	if (copy_to_user(arg, &userinfo, sizeof(struct agp_info)))		return -EFAULT;	return 0;}static int agpioc_acquire_wrap(struct agp_file_private *priv){	struct agp_controller *controller;	DBG("");	if (!(test_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags)))		return -EPERM;	if (agp_fe.current_controller != NULL)		return -EBUSY;	if(!agp_bridge)		return -ENODEV;        if (atomic_read(&agp_bridge->agp_in_use))                return -EBUSY;	atomic_inc(&agp_bridge->agp_in_use);	agp_fe.backend_acquired = TRUE;	controller = agp_find_controller_by_pid(priv->my_pid);	if (controller != NULL) {		agp_controller_make_current(controller);	} else {		controller = agp_create_controller(priv->my_pid);		if (controller == NULL) {			agp_fe.backend_acquired = FALSE;			agp_backend_release(agp_bridge);			return -ENOMEM;		}		agp_insert_controller(controller);		agp_controller_make_current(controller);	}	set_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags);	set_bit(AGP_FF_IS_VALID, &priv->access_flags);	return 0;}static int agpioc_release_wrap(struct agp_file_private *priv){	DBG("");	agp_controller_release_current(agp_fe.current_controller, priv);	return 0;}static int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg){	struct agp_setup mode;	DBG("");	if (copy_from_user(&mode, arg, sizeof(struct agp_setup)))		return -EFAULT;	agp_enable(agp_bridge, mode.agp_mode);	return 0;}static int agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg){	struct agp_region reserve;	struct agp_client *client;	struct agp_file_private *client_priv;	DBG("");	if (copy_from_user(&reserve, arg, sizeof(struct agp_region)))		return -EFAULT;	if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment))		return -EFAULT;	client = agp_find_client_by_pid(reserve.pid);	if (reserve.seg_count == 0) {		/* remove a client */		client_priv = agp_find_private(reserve.pid);		if (client_priv != NULL) {			set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);			set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);		}		if (client == NULL) {			/* client is already removed */			return 0;		}		return agp_remove_client(reserve.pid);	} else {		struct agp_segment *segment;		if (reserve.seg_count >= 16384)			return -EINVAL;		segment = kmalloc((sizeof(struct agp_segment) * reserve.seg_count),				  GFP_KERNEL);		if (segment == NULL)			return -ENOMEM;		if (copy_from_user(segment, (void __user *) reserve.seg_list,				   sizeof(struct agp_segment) * reserve.seg_count)) {			kfree(segment);			return -EFAULT;		}		reserve.seg_list = segment;		if (client == NULL) {			/* Create the client and add the segment */			client = agp_create_client(reserve.pid);			if (client == NULL) {				kfree(segment);				return -ENOMEM;			}			client_priv = agp_find_private(reserve.pid);			if (client_priv != NULL) {				set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);				set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);			}		}		return agp_create_segment(client, &reserve);	}	/* Will never really happen */	return -EINVAL;}static int agpioc_protect_wrap(struct agp_file_private *priv){	DBG("");	/* This function is not currently implemented */	return -EINVAL;}static int agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg){	struct agp_memory *memory;	struct agp_allocate alloc;	DBG("");	if (copy_from_user(&alloc, arg, sizeof(struct agp_allocate)))		return -EFAULT;	memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type);	if (memory == NULL)		return -ENOMEM;	alloc.key = memory->key;	alloc.physical = memory->physical;	if (copy_to_user(arg, &alloc, sizeof(struct agp_allocate))) {		agp_free_memory_wrap(memory);		return -EFAULT;	}	return 0;}static int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg){	struct agp_memory *memory;	DBG("");	memory = agp_find_mem_by_key(arg);	if (memory == NULL)		return -EINVAL;	agp_free_memory_wrap(memory);	return 0;}static int agpioc_bind_wrap(struct agp_file_private *priv, void __user *arg){	struct agp_bind bind_info;	struct agp_memory *memory;	DBG("");	if (copy_from_user(&bind_info, arg, sizeof(struct agp_bind)))		return -EFAULT;	memory = agp_find_mem_by_key(bind_info.key);	if (memory == NULL)		return -EINVAL;	return agp_bind_memory(memory, bind_info.pg_start);}static int agpioc_unbind_wrap(struct agp_file_private *priv, void __user *arg){	struct agp_memory *memory;	struct agp_unbind unbind;	DBG("");	if (copy_from_user(&unbind, arg, sizeof(struct agp_unbind)))		return -EFAULT;	memory = agp_find_mem_by_key(unbind.key);	if (memory == NULL)		return -EINVAL;	return agp_unbind_memory(memory);}static int agp_ioctl(struct inode *inode, struct file *file,		     unsigned int cmd, unsigned long arg){	struct agp_file_private *curr_priv = file->private_data;	int ret_val = -ENOTTY;	DBG("priv=%p, cmd=%x", curr_priv, cmd);	down(&(agp_fe.agp_mutex));	if ((agp_fe.current_controller == NULL) &&	    (cmd != AGPIOC_ACQUIRE)) {		ret_val = -EINVAL;		goto ioctl_out;	}	if ((agp_fe.backend_acquired != TRUE) &&	    (cmd != AGPIOC_ACQUIRE)) {		ret_val = -EBUSY;		goto ioctl_out;	}	if (cmd != AGPIOC_ACQUIRE) {		if (!(test_bit(AGP_FF_IS_CONTROLLER, &curr_priv->access_flags))) {			ret_val = -EPERM;			goto ioctl_out;		}		/* Use the original pid of the controller,		 * in case it's threaded */		if (agp_fe.current_controller->pid != curr_priv->my_pid) {			ret_val = -EBUSY;			goto ioctl_out;		}	}	switch (cmd) {	case AGPIOC_INFO:		ret_val = agpioc_info_wrap(curr_priv, (void __user *) arg);		break;	case AGPIOC_ACQUIRE:		ret_val = agpioc_acquire_wrap(curr_priv);		break;	case AGPIOC_RELEASE:		ret_val = agpioc_release_wrap(curr_priv);		break;	case AGPIOC_SETUP:		ret_val = agpioc_setup_wrap(curr_priv, (void __user *) arg);		break;	case AGPIOC_RESERVE:		ret_val = agpioc_reserve_wrap(curr_priv, (void __user *) arg);		break;	case AGPIOC_PROTECT:		ret_val = agpioc_protect_wrap(curr_priv);		break;	case AGPIOC_ALLOCATE:		ret_val = agpioc_allocate_wrap(curr_priv, (void __user *) arg);		break;	case AGPIOC_DEALLOCATE:		ret_val = agpioc_deallocate_wrap(curr_priv, (int) arg);		break;	case AGPIOC_BIND:		ret_val = agpioc_bind_wrap(curr_priv, (void __user *) arg);		break;	case AGPIOC_UNBIND:		ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg);		break;	}ioctl_out:	DBG("ioctl returns %d\n", ret_val);	up(&(agp_fe.agp_mutex));	return ret_val;}static struct file_operations agp_fops ={	.owner		= THIS_MODULE,	.llseek		= no_llseek,	.read		= agp_read,	.write		= agp_write,	.ioctl		= agp_ioctl,	.mmap		= agp_mmap,	.open		= agp_open,	.release	= agp_release,};static struct miscdevice agp_miscdev ={	.minor	= AGPGART_MINOR,	.name	= "agpgart",	.fops	= &agp_fops};int agp_frontend_initialize(void){	memset(&agp_fe, 0, sizeof(struct agp_front_data));	sema_init(&(agp_fe.agp_mutex), 1);	if (misc_register(&agp_miscdev)) {		printk(KERN_ERR PFX "unable to get minor: %d\n", AGPGART_MINOR);		return -EIO;	}	return 0;}void agp_frontend_cleanup(void){	misc_deregister(&agp_miscdev);}

⌨️ 快捷键说明

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