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

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

?? uio.c

?? linux 內核源代碼
?? C
字號:
/* * drivers/uio/uio.c * * Copyright(C) 2005, Benedikt Spranger <b.spranger@linutronix.de> * Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de> * Copyright(C) 2006, Hans J. Koch <hjk@linutronix.de> * Copyright(C) 2006, Greg Kroah-Hartman <greg@kroah.com> * * Userspace IO * * Base Functions * * Licensed under the GPLv2 only. */#include <linux/module.h>#include <linux/init.h>#include <linux/poll.h>#include <linux/device.h>#include <linux/mm.h>#include <linux/idr.h>#include <linux/string.h>#include <linux/kobject.h>#include <linux/uio_driver.h>#define UIO_MAX_DEVICES 255struct uio_device {	struct module		*owner;	struct device		*dev;	int			minor;	atomic_t		event;	struct fasync_struct	*async_queue;	wait_queue_head_t	wait;	int			vma_count;	struct uio_info		*info;	struct kset 		map_attr_kset;};static int uio_major;static DEFINE_IDR(uio_idr);static struct file_operations uio_fops;/* UIO class infrastructure */static struct uio_class {	struct kref kref;	struct class *class;} *uio_class;/* * attributes */static struct attribute attr_addr = {	.name  = "addr",	.mode  = S_IRUGO,};static struct attribute attr_size = {	.name  = "size",	.mode  = S_IRUGO,};static struct attribute* map_attrs[] = {	&attr_addr, &attr_size, NULL};static ssize_t map_attr_show(struct kobject *kobj, struct attribute *attr,			     char *buf){	struct uio_mem *mem = container_of(kobj, struct uio_mem, kobj);	if (strncmp(attr->name,"addr",4) == 0)		return sprintf(buf, "0x%lx\n", mem->addr);	if (strncmp(attr->name,"size",4) == 0)		return sprintf(buf, "0x%lx\n", mem->size);	return -ENODEV;}static void map_attr_release(struct kobject *kobj){	/* TODO ??? */}static struct sysfs_ops map_attr_ops = {	.show  = map_attr_show,};static struct kobj_type map_attr_type = {	.release	= map_attr_release,	.sysfs_ops	= &map_attr_ops,	.default_attrs	= map_attrs,};static ssize_t show_name(struct device *dev,			 struct device_attribute *attr, char *buf){	struct uio_device *idev = dev_get_drvdata(dev);	if (idev)		return sprintf(buf, "%s\n", idev->info->name);	else		return -ENODEV;}static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);static ssize_t show_version(struct device *dev,			    struct device_attribute *attr, char *buf){	struct uio_device *idev = dev_get_drvdata(dev);	if (idev)		return sprintf(buf, "%s\n", idev->info->version);	else		return -ENODEV;}static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);static ssize_t show_event(struct device *dev,			  struct device_attribute *attr, char *buf){	struct uio_device *idev = dev_get_drvdata(dev);	if (idev)		return sprintf(buf, "%u\n",				(unsigned int)atomic_read(&idev->event));	else		return -ENODEV;}static DEVICE_ATTR(event, S_IRUGO, show_event, NULL);static struct attribute *uio_attrs[] = {	&dev_attr_name.attr,	&dev_attr_version.attr,	&dev_attr_event.attr,	NULL,};static struct attribute_group uio_attr_grp = {	.attrs = uio_attrs,};/* * device functions */static int uio_dev_add_attributes(struct uio_device *idev){	int ret;	int mi;	int map_found = 0;	struct uio_mem *mem;	ret = sysfs_create_group(&idev->dev->kobj, &uio_attr_grp);	if (ret)		goto err_group;	for (mi = 0; mi < MAX_UIO_MAPS; mi++) {		mem = &idev->info->mem[mi];		if (mem->size == 0)			break;		if (!map_found) {			map_found = 1;			kobject_set_name(&idev->map_attr_kset.kobj,"maps");			idev->map_attr_kset.ktype = &map_attr_type;			idev->map_attr_kset.kobj.parent = &idev->dev->kobj;			ret = kset_register(&idev->map_attr_kset);			if (ret)				goto err_remove_group;		}		kobject_init(&mem->kobj);		kobject_set_name(&mem->kobj,"map%d",mi);		mem->kobj.parent = &idev->map_attr_kset.kobj;		mem->kobj.kset = &idev->map_attr_kset;		ret = kobject_add(&mem->kobj);		if (ret)			goto err_remove_maps;	}	return 0;err_remove_maps:	for (mi--; mi>=0; mi--) {		mem = &idev->info->mem[mi];		kobject_unregister(&mem->kobj);	}	kset_unregister(&idev->map_attr_kset); /* Needed ? */err_remove_group:	sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);err_group:	dev_err(idev->dev, "error creating sysfs files (%d)\n", ret);	return ret;}static void uio_dev_del_attributes(struct uio_device *idev){	int mi;	struct uio_mem *mem;	for (mi = 0; mi < MAX_UIO_MAPS; mi++) {		mem = &idev->info->mem[mi];		if (mem->size == 0)			break;		kobject_unregister(&mem->kobj);	}	kset_unregister(&idev->map_attr_kset);	sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);}static int uio_get_minor(struct uio_device *idev){	static DEFINE_MUTEX(minor_lock);	int retval = -ENOMEM;	int id;	mutex_lock(&minor_lock);	if (idr_pre_get(&uio_idr, GFP_KERNEL) == 0)		goto exit;	retval = idr_get_new(&uio_idr, idev, &id);	if (retval < 0) {		if (retval == -EAGAIN)			retval = -ENOMEM;		goto exit;	}	idev->minor = id & MAX_ID_MASK;exit:	mutex_unlock(&minor_lock);	return retval;}static void uio_free_minor(struct uio_device *idev){	idr_remove(&uio_idr, idev->minor);}/** * uio_event_notify - trigger an interrupt event * @info: UIO device capabilities */void uio_event_notify(struct uio_info *info){	struct uio_device *idev = info->uio_dev;	atomic_inc(&idev->event);	wake_up_interruptible(&idev->wait);	kill_fasync(&idev->async_queue, SIGIO, POLL_IN);}EXPORT_SYMBOL_GPL(uio_event_notify);/** * uio_interrupt - hardware interrupt handler * @irq: IRQ number, can be UIO_IRQ_CYCLIC for cyclic timer * @dev_id: Pointer to the devices uio_device structure */static irqreturn_t uio_interrupt(int irq, void *dev_id){	struct uio_device *idev = (struct uio_device *)dev_id;	irqreturn_t ret = idev->info->handler(irq, idev->info);	if (ret == IRQ_HANDLED)		uio_event_notify(idev->info);	return ret;}struct uio_listener {	struct uio_device *dev;	s32 event_count;};static int uio_open(struct inode *inode, struct file *filep){	struct uio_device *idev;	struct uio_listener *listener;	int ret = 0;	idev = idr_find(&uio_idr, iminor(inode));	if (!idev)		return -ENODEV;	listener = kmalloc(sizeof(*listener), GFP_KERNEL);	if (!listener)		return -ENOMEM;	listener->dev = idev;	listener->event_count = atomic_read(&idev->event);	filep->private_data = listener;	if (idev->info->open) {		if (!try_module_get(idev->owner))			return -ENODEV;		ret = idev->info->open(idev->info, inode);		module_put(idev->owner);	}	if (ret)		kfree(listener);	return ret;}static int uio_fasync(int fd, struct file *filep, int on){	struct uio_listener *listener = filep->private_data;	struct uio_device *idev = listener->dev;	return fasync_helper(fd, filep, on, &idev->async_queue);}static int uio_release(struct inode *inode, struct file *filep){	int ret = 0;	struct uio_listener *listener = filep->private_data;	struct uio_device *idev = listener->dev;	if (idev->info->release) {		if (!try_module_get(idev->owner))			return -ENODEV;		ret = idev->info->release(idev->info, inode);		module_put(idev->owner);	}	if (filep->f_flags & FASYNC)		ret = uio_fasync(-1, filep, 0);	kfree(listener);	return ret;}static unsigned int uio_poll(struct file *filep, poll_table *wait){	struct uio_listener *listener = filep->private_data;	struct uio_device *idev = listener->dev;	if (idev->info->irq == UIO_IRQ_NONE)		return -EIO;	poll_wait(filep, &idev->wait, wait);	if (listener->event_count != atomic_read(&idev->event))		return POLLIN | POLLRDNORM;	return 0;}static ssize_t uio_read(struct file *filep, char __user *buf,			size_t count, loff_t *ppos){	struct uio_listener *listener = filep->private_data;	struct uio_device *idev = listener->dev;	DECLARE_WAITQUEUE(wait, current);	ssize_t retval;	s32 event_count;	if (idev->info->irq == UIO_IRQ_NONE)		return -EIO;	if (count != sizeof(s32))		return -EINVAL;	add_wait_queue(&idev->wait, &wait);	do {		set_current_state(TASK_INTERRUPTIBLE);		event_count = atomic_read(&idev->event);		if (event_count != listener->event_count) {			if (copy_to_user(buf, &event_count, count))				retval = -EFAULT;			else {				listener->event_count = event_count;				retval = count;			}			break;		}		if (filep->f_flags & O_NONBLOCK) {			retval = -EAGAIN;			break;		}		if (signal_pending(current)) {			retval = -ERESTARTSYS;			break;		}		schedule();	} while (1);	__set_current_state(TASK_RUNNING);	remove_wait_queue(&idev->wait, &wait);	return retval;}static int uio_find_mem_index(struct vm_area_struct *vma){	int mi;	struct uio_device *idev = vma->vm_private_data;	for (mi = 0; mi < MAX_UIO_MAPS; mi++) {		if (idev->info->mem[mi].size == 0)			return -1;		if (vma->vm_pgoff == mi)			return mi;	}	return -1;}static void uio_vma_open(struct vm_area_struct *vma){	struct uio_device *idev = vma->vm_private_data;	idev->vma_count++;}static void uio_vma_close(struct vm_area_struct *vma){	struct uio_device *idev = vma->vm_private_data;	idev->vma_count--;}static struct page *uio_vma_nopage(struct vm_area_struct *vma,				   unsigned long address, int *type){	struct uio_device *idev = vma->vm_private_data;	struct page* page = NOPAGE_SIGBUS;	int mi = uio_find_mem_index(vma);	if (mi < 0)		return page;	if (idev->info->mem[mi].memtype == UIO_MEM_LOGICAL)		page = virt_to_page(idev->info->mem[mi].addr);	else		page = vmalloc_to_page((void*)idev->info->mem[mi].addr);	get_page(page);	if (type)		*type = VM_FAULT_MINOR;	return page;}static struct vm_operations_struct uio_vm_ops = {	.open = uio_vma_open,	.close = uio_vma_close,	.nopage = uio_vma_nopage,};static int uio_mmap_physical(struct vm_area_struct *vma){	struct uio_device *idev = vma->vm_private_data;	int mi = uio_find_mem_index(vma);	if (mi < 0)		return -EINVAL;	vma->vm_flags |= VM_IO | VM_RESERVED;	return remap_pfn_range(vma,			       vma->vm_start,			       idev->info->mem[mi].addr >> PAGE_SHIFT,			       vma->vm_end - vma->vm_start,			       vma->vm_page_prot);}static int uio_mmap_logical(struct vm_area_struct *vma){	vma->vm_flags |= VM_RESERVED;	vma->vm_ops = &uio_vm_ops;	uio_vma_open(vma);	return 0;}static int uio_mmap(struct file *filep, struct vm_area_struct *vma){	struct uio_listener *listener = filep->private_data;	struct uio_device *idev = listener->dev;	int mi;	unsigned long requested_pages, actual_pages;	int ret = 0;	if (vma->vm_end < vma->vm_start)		return -EINVAL;	vma->vm_private_data = idev;	mi = uio_find_mem_index(vma);	if (mi < 0)		return -EINVAL;	requested_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;	actual_pages = (idev->info->mem[mi].size + PAGE_SIZE -1) >> PAGE_SHIFT;	if (requested_pages > actual_pages)		return -EINVAL;	if (idev->info->mmap) {		if (!try_module_get(idev->owner))			return -ENODEV;		ret = idev->info->mmap(idev->info, vma);		module_put(idev->owner);		return ret;	}	switch (idev->info->mem[mi].memtype) {		case UIO_MEM_PHYS:			return uio_mmap_physical(vma);		case UIO_MEM_LOGICAL:		case UIO_MEM_VIRTUAL:			return uio_mmap_logical(vma);		default:			return -EINVAL;	}}static struct file_operations uio_fops = {	.owner		= THIS_MODULE,	.open		= uio_open,	.release	= uio_release,	.read		= uio_read,	.mmap		= uio_mmap,	.poll		= uio_poll,	.fasync		= uio_fasync,};static int uio_major_init(void){	uio_major = register_chrdev(0, "uio", &uio_fops);	if (uio_major < 0)		return uio_major;	return 0;}static void uio_major_cleanup(void){	unregister_chrdev(uio_major, "uio");}static int init_uio_class(void){	int ret = 0;	if (uio_class != NULL) {		kref_get(&uio_class->kref);		goto exit;	}	/* This is the first time in here, set everything up properly */	ret = uio_major_init();	if (ret)		goto exit;	uio_class = kzalloc(sizeof(*uio_class), GFP_KERNEL);	if (!uio_class) {		ret = -ENOMEM;		goto err_kzalloc;	}	kref_init(&uio_class->kref);	uio_class->class = class_create(THIS_MODULE, "uio");	if (IS_ERR(uio_class->class)) {		ret = IS_ERR(uio_class->class);		printk(KERN_ERR "class_create failed for uio\n");		goto err_class_create;	}	return 0;err_class_create:	kfree(uio_class);	uio_class = NULL;err_kzalloc:	uio_major_cleanup();exit:	return ret;}static void release_uio_class(struct kref *kref){	/* Ok, we cheat as we know we only have one uio_class */	class_destroy(uio_class->class);	kfree(uio_class);	uio_major_cleanup();	uio_class = NULL;}static void uio_class_destroy(void){	if (uio_class)		kref_put(&uio_class->kref, release_uio_class);}/** * uio_register_device - register a new userspace IO device * @owner:	module that creates the new device * @parent:	parent device * @info:	UIO device capabilities * * returns zero on success or a negative error code. */int __uio_register_device(struct module *owner,			  struct device *parent,			  struct uio_info *info){	struct uio_device *idev;	int ret = 0;	if (!parent || !info || !info->name || !info->version)		return -EINVAL;	info->uio_dev = NULL;	ret = init_uio_class();	if (ret)		return ret;	idev = kzalloc(sizeof(*idev), GFP_KERNEL);	if (!idev) {		ret = -ENOMEM;		goto err_kzalloc;	}	idev->owner = owner;	idev->info = info;	init_waitqueue_head(&idev->wait);	atomic_set(&idev->event, 0);	ret = uio_get_minor(idev);	if (ret)		goto err_get_minor;	idev->dev = device_create(uio_class->class, parent,				  MKDEV(uio_major, idev->minor),				  "uio%d", idev->minor);	if (IS_ERR(idev->dev)) {		printk(KERN_ERR "UIO: device register failed\n");		ret = PTR_ERR(idev->dev);		goto err_device_create;	}	dev_set_drvdata(idev->dev, idev);	ret = uio_dev_add_attributes(idev);	if (ret)		goto err_uio_dev_add_attributes;	info->uio_dev = idev;	if (idev->info->irq >= 0) {		ret = request_irq(idev->info->irq, uio_interrupt,				  idev->info->irq_flags, idev->info->name, idev);		if (ret)			goto err_request_irq;	}	return 0;err_request_irq:	uio_dev_del_attributes(idev);err_uio_dev_add_attributes:	device_destroy(uio_class->class, MKDEV(uio_major, idev->minor));err_device_create:	uio_free_minor(idev);err_get_minor:	kfree(idev);err_kzalloc:	uio_class_destroy();	return ret;}EXPORT_SYMBOL_GPL(__uio_register_device);/** * uio_unregister_device - unregister a industrial IO device * @info:	UIO device capabilities * */void uio_unregister_device(struct uio_info *info){	struct uio_device *idev;	if (!info || !info->uio_dev)		return;	idev = info->uio_dev;	uio_free_minor(idev);	if (info->irq >= 0)		free_irq(info->irq, idev);	uio_dev_del_attributes(idev);	dev_set_drvdata(idev->dev, NULL);	device_destroy(uio_class->class, MKDEV(uio_major, idev->minor));	kfree(idev);	uio_class_destroy();	return;}EXPORT_SYMBOL_GPL(uio_unregister_device);static int __init uio_init(void){	return 0;}static void __exit uio_exit(void){}module_init(uio_init)module_exit(uio_exit)MODULE_LICENSE("GPL v2");

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
日本乱码高清不卡字幕| 91在线观看成人| 国产精品福利影院| 欧美一区二区不卡视频| 成人动漫一区二区在线| 理论电影国产精品| 一区二区在线观看视频| 久久精品欧美一区二区三区麻豆| 欧美网站一区二区| 99视频在线精品| 国产一二三精品| 青青草97国产精品免费观看无弹窗版| 国产精品久久久久久久久快鸭| 欧美一区二区免费| 欧美日韩一区不卡| 一本到不卡免费一区二区| 国产河南妇女毛片精品久久久| 日韩影院免费视频| 亚洲综合色成人| 亚洲欧美日韩国产一区二区三区| 久久久国产精品麻豆| 欧美一区二区日韩一区二区| 欧美肥妇bbw| 欧美美女一区二区| 91黄色在线观看| 色偷偷一区二区三区| 99久久综合色| 99在线热播精品免费| 豆国产96在线|亚洲| 国产乱子伦一区二区三区国色天香| 日韩精品国产欧美| 日韩av中文字幕一区二区| 亚洲成在人线在线播放| 亚洲一二三四在线| 亚洲一区二区三区激情| 亚洲va国产天堂va久久en| 一区二区视频在线| 亚洲夂夂婷婷色拍ww47| 一区二区三区91| 亚洲一区二区三区四区在线免费观看 | 五月天婷婷综合| 亚洲成av人影院在线观看网| 亚洲激情五月婷婷| 亚洲乱码中文字幕综合| 伊人婷婷欧美激情| 午夜av区久久| 蜜臀91精品一区二区三区| 麻豆一区二区在线| 久久成人免费网站| 国产精品中文欧美| 成人白浆超碰人人人人| va亚洲va日韩不卡在线观看| 不卡视频一二三| 色噜噜狠狠成人中文综合| 色就色 综合激情| 在线成人免费视频| 日韩免费高清电影| 久久精子c满五个校花| 国产精品网曝门| 亚洲欧美成aⅴ人在线观看| 成人欧美一区二区三区视频网页| 亚洲欧美欧美一区二区三区| 亚洲成人三级小说| 麻豆精品一区二区综合av| 精品一区二区三区在线观看国产 | 精品国产凹凸成av人导航| 久久网站最新地址| 亚洲欧洲色图综合| 亚洲一区二区三区视频在线播放| 日韩av一区二区三区四区| 国模一区二区三区白浆| 丁香激情综合国产| 在线观看精品一区| 欧美成人国产一区二区| 国产欧美日韩在线| 亚洲国产视频网站| 九九久久精品视频| 成人精品免费网站| 91精品国产综合久久国产大片| 2021久久国产精品不只是精品| 国产精品传媒入口麻豆| 天堂久久一区二区三区| 国产精品12区| 欧美日韩国产免费一区二区| 26uuu久久天堂性欧美| 最新高清无码专区| 美国十次了思思久久精品导航| 成人午夜激情在线| 欧美另类一区二区三区| 欧美激情中文不卡| 丝袜美腿高跟呻吟高潮一区| 国产夫妻精品视频| 欧美日韩亚洲丝袜制服| 久久精品亚洲乱码伦伦中文| 亚洲综合免费观看高清在线观看 | 欧美视频一区二区三区在线观看| 欧美va亚洲va香蕉在线| 亚洲免费成人av| 国产福利一区二区三区视频 | 欧美日韩国产色站一区二区三区| 久久精品一区八戒影视| 午夜精品久久久久久久久久 | 欧美自拍偷拍一区| 国产欧美精品日韩区二区麻豆天美| 午夜不卡在线视频| 色天使色偷偷av一区二区| 久久综合狠狠综合久久综合88| 一区二区三区波多野结衣在线观看| 高清不卡在线观看| 日韩精品一区二区三区中文精品| 一区二区三区在线视频免费| 国产69精品久久久久777| 日韩午夜激情视频| 亚洲福利视频一区| 91黄色小视频| 亚洲色图欧美偷拍| 大白屁股一区二区视频| 久久亚洲精精品中文字幕早川悠里| 亚洲成人激情自拍| 在线免费观看视频一区| 国产精品成人免费在线| 国产精品一二三| 精品国产凹凸成av人网站| 日韩国产精品大片| 欧美日韩电影在线| 亚洲一二三四在线观看| 在线精品视频一区二区三四| 自拍偷拍亚洲综合| 成人av电影观看| 中国av一区二区三区| 国产九色精品成人porny| 欧美成人激情免费网| 久久精品国产久精国产爱| 91精品国产综合久久福利软件| 偷拍一区二区三区四区| 欧美日韩一区二区三区四区五区| 一级女性全黄久久生活片免费| 96av麻豆蜜桃一区二区| 亚洲美女视频一区| 91在线观看下载| 亚洲三级在线看| 色婷婷亚洲精品| 亚洲一区视频在线| 欧美日本乱大交xxxxx| 午夜精品福利视频网站| 在线播放中文一区| 日韩高清国产一区在线| 欧美一区二区黄色| 国产一区二区三区四区在线观看| 久久综合国产精品| 成人免费三级在线| 亚洲欧洲国产专区| 在线国产电影不卡| 婷婷综合五月天| 欧美va在线播放| 成人99免费视频| 亚洲精品国产第一综合99久久| 欧美亚洲综合在线| 青青草国产精品亚洲专区无| 精品精品欲导航| 成人福利视频网站| 亚洲午夜久久久久久久久久久 | 国产精品私房写真福利视频| 96av麻豆蜜桃一区二区| 午夜激情一区二区| 精品国产亚洲一区二区三区在线观看 | 国产精品国产成人国产三级| 91视频www| 日韩avvvv在线播放| 精品国产成人在线影院| av午夜一区麻豆| 日精品一区二区三区| 久久综合av免费| 色综合激情久久| 免费高清视频精品| 国产精品久久久久天堂| 欧美无人高清视频在线观看| 国产在线播精品第三| 亚洲人成在线播放网站岛国 | 欧美日韩国产bt| 国产超碰在线一区| 亚洲一级二级在线| 久久久久久久久久久久久女国产乱| 91美女福利视频| 久久国内精品视频| 亚洲精品精品亚洲| 久久夜色精品一区| 在线观看www91| 国产一区二区三区久久久 | 亚洲国产日韩在线一区模特| 欧美精品一区二区三区久久久| 91麻豆免费看| 国内精品写真在线观看| 亚洲午夜久久久久久久久电影院| 久久久电影一区二区三区| 欧美美女激情18p| 99麻豆久久久国产精品免费| 精品综合久久久久久8888| 亚洲综合色视频| 中文欧美字幕免费|