2011年(10)
分类: 嵌入式
2011-03-28 16:49:50
第一步:分配设备号
(1)dev_t结构
【结构】 相关文件
dev_t:无符号32位数
前12位是主设备号,后20位是次设备号。
索引:typedef __kernel_dev_t dev_t; /* 把__kernel_dev_t 定义到dev_t */
typedef __u32 __kernel_dev_t; /* 把__u32定义成 __kernel_dev_t */
#ifndef __u32 /* 把 unsigned int定义成__u32 */
#define __u32 unsigned int
#endif
【宏】 相关文件
MAJOR (dev_t dev)
MINOR (dev_t dev)
MKDEV(int major, int minor);
#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS)) /*右移20位,以0填补*/
#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK)) /*屏蔽高12位*/
#define MINORBITS 20
#define MINORMASK ((1U << MINORBITS) - 1) /* 000FFFFF */
#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))
(2)静态分配设备号
【函数】register_chrdev_region
extern int register_chrdev_region(dev_t,
unsigned, const char *);
【原型】:
/**
* register_chrdev_region() - register a range of device numbers
* @from: the first in the desired range of device numbers; must include
* the major number.
* @count: the number of consecutive device numbers required
* @name: the name of the device or driver.
*
* Return value is zero on success, a negative error code on failure.
*/
int register_chrdev_region(dev_t from, unsigned count, const char *name)
{
struct char_device_struct *cd;
dev_t to = from + count;
dev_t n, next;
for (n = from; n < to; n = next) {
next = MKDEV(MAJOR(n)+1, 0);
if (next > to)
next = to;
cd = __register_chrdev_region(MAJOR(n), MINOR(n),
next - n, name);
if (IS_ERR(cd))
goto fail;
}
return 0;
fail:
to = n;
for (n = from; n < to; n = next) {
next = MKDEV(MAJOR(n)+1, 0);
kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
}
return PTR_ERR(cd);
}
int register_chrdev_region(dev_t first, unsigned count, const char *name)
这里, first 是你要分配的起始设备编号. first 的次编号部分常常是 0, 但是没有要求是那个效果. count 是你请求的连续设备编号的总数. 注意, 如果 count 太大, 你要求的范围可能溢出到下一个次编号; 但是只要你要求的编号范围可用, 一切都仍然会正确工作. 最后, name 是应当连接到这个编号范围的设备的名子; 它会出现在 /proc/devices 和 sysfs 中.
【例子】:
int result;
dev_t devno = MAKEDEV (globalmem_major , 0)
result = register_chrdev_region (devno, 1, “globalmem”)
(3) 动态分配设备号
【函数】 alloc_chrdev_region
【原型】
extern int alloc_chrdev_region(dev_t *,
unsigned, unsigned, const char *);
/**
* alloc_chrdev_region() - register a range of char device numbers
* @dev: output parameter for first assigned number
* @baseminor: first of the requested range of minor numbers
* @count: the number of minor numbers required
* @name: the name of the associated device or driver
*
* Allocates a range of char device numbers. The major number will be
* chosen dynamically, and returned (along with the first minor number)
* in @dev. Returns zero or a negative error code.
*/
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
const char *name)
{
struct char_device_struct *cd;
cd = __register_chrdev_region(0, baseminor, count, name);
if (IS_ERR(cd))
return PTR_ERR(cd);
*dev = MKDEV(cd->major, cd->baseminor);
return 0;
【例子】:
int result;
dev_t devno;
result = alloc_chardev_region (&devno,0,1,”globalmem”)
(4)释放设备号
【函数】 unregister_chrdev_region
【原型】
extern void unregister_chrdev_region(dev_t, unsigned);
/**
* unregister_chrdev_region() - return a range of device numbers
* @from: the first in the range of numbers to unregister
* @count: the number of device numbers to unregister
*
* This function will unregister a range of @count device numbers,
* starting with @from. The caller should normally be the one who
* allocated those numbers in the first place...
*/
void unregister_chrdev_region(dev_t from, unsigned count)
{
dev_t to = from + count;
dev_t n, next;
for (n = from; n < to; n = next) {
next = MKDEV(MAJOR(n)+1, 0);
if (next > to)
next = to;
kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
}
}
【例子】
Unregister_chrdev_region (MKDEV(globalmem_major,0),1);