设为首页 加入收藏

TOP

Linux字符设备驱动程序源文件(一)
2014-11-24 08:39:33 来源: 作者: 【 】 浏览:1
Tags:Linux 字符 设备 驱动程序 源文件

/*
* linux/fs/char_dev.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/


#include
#include
#include
#include
#include


#include
#include
#include
#include


#include
#include
#include
#include
#include
#include


#include "internal.h"


/*
* capabilities for /dev/mem, /dev/kmem and similar directly mappable character
* devices
* - permits shared-mmap for read, write and/or exec
* - does not permit private mmap in NOMMU mode (can't do COW)
* - no readahead or I/O queue unplugging required
*/
struct backing_dev_info directly_mappable_cdev_bdi = {
.name = "char",
.capabilities = (
#ifdef CONFIG_MMU
/* permit private copies of the data to be taken */
BDI_CAP_MAP_COPY |
#endif
/* permit direct mmap, for read, write or exec */
BDI_CAP_MAP_DIRECT |
BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP |
/* no writeback happens */
BDI_CAP_NO_ACCT_AND_WRITEBACK),
};


static struct kobj_map *cdev_map;


static DEFINE_MUTEX(chrdevs_lock);


static struct char_device_struct {
struct char_device_struct *next;
unsigned int major;
unsigned int baseminor;
int minorct;
char name[64];
struct cdev *cdev; /* will die */
} *chrdevs[CHRDEV_MAJOR_HASH_SIZE];


/* index in the above */
static inline int major_to_index(int major)
{
return major % CHRDEV_MAJOR_HASH_SIZE;
}


#ifdef CONFIG_PROC_FS


void chrdev_show(struct seq_file *f, off_t offset)
{
struct char_device_struct *cd;


if (offset < CHRDEV_MAJOR_HASH_SIZE) {
mutex_lock(&chrdevs_lock);
for (cd = chrdevs[offset]; cd; cd = cd->next)
seq_printf(f, "%3d %s\n", cd->major, cd->name);
mutex_unlock(&chrdevs_lock);
}
}


#endif /* CONFIG_PROC_FS */


/*
* Register a single major with a specified minor range.
*
* If major == 0 this functions will dynamically allocate a major and return
* its number.
*
* If major > 0 this function will attempt to reserve the passed range of
* minors and will return zero on success.
*
* Returns a -ve errno on failure.
*/
static struct char_device_struct *
__register_chrdev_region(unsigned int major, unsigned int baseminor,
int minorct, const char *name)
{
struct char_device_struct *cd, **cp;
int ret = 0;
int i;


cd = kzalloc(sizeof(struct char_device_struct), GFP_KERNEL);
if (cd == NULL)
return ERR_PTR(-ENOMEM);


mutex_lock(&chrdevs_lock);


/* temporary */
if (major == 0) {
for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) {
if (chrdevs[i] == NULL)
break;
}


if (i == 0) {
ret = -EBUSY;
goto out;
}
major = i;
ret = major;
}


cd->major = major;
cd->baseminor = baseminor;
cd->minorct = minorct;
strlcpy(cd->name, name, sizeof(cd->name));


i = major_to_index(major);


for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
if ((*cp)->major > major ||
((*cp)->major == major &&
(((*cp)->baseminor >= baseminor) ||
((*cp)->baseminor + (*cp)->minorct > baseminor))))
break;


/* Check for overlapping minor ranges. */
if (*cp && (*cp)->major == major) {
int old_min = (*cp)->baseminor;
int old_max = (*cp)->baseminor + (*cp)->minorct - 1;
int new_min = baseminor;
int new_max = baseminor + minorct - 1;


/* New driver overlaps from the left. */
if (new_max >= old_min && new_max <= old_max) {
ret = -EBUSY;
got

首页 上一页 1 2 3 4 5 6 下一页 尾页 1/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Linux 内核2.6.35 skb_copy_bits .. 下一篇Linux Shell脚本系列-grep用法总结

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·【C语言】动态内存管 (2025-12-27 06:23:20)
·C语言中的内存管理 - (2025-12-27 06:23:16)
·C语言指南:C语言内 (2025-12-27 06:23:14)
·Redis on AWS:Elast (2025-12-27 04:19:30)
·在 Spring Boot 项目 (2025-12-27 04:19:27)