request_region()函数用于申请IO端口,而request_mem_region用于申请IO内存(一般为控制寄存器)。申请之后还要通过ioremap函数去映射到内核虚拟地址。
这两个函数都是宏定义,
#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name))
#define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name))
struct resource {
const char *name;
unsigned long start, end;
unsigned long flags;
struct resource *parent, *sibling, *child;
};
其中ioport_resouce 和iomem_resource定义如下:
struct resource ioport_resource = {
.name = "PCI IO",
.start = 0x0000,
.end = IO_SPACE_LIMIT,//在ARM平台IO_SPACE_LIMIT=0xffffffff
.flags = IORESOURCE_IO,
};
struct resource iomem_resource = {
.name = "PCI mem",
.start = 0UL,
.end = ~0UL,
.flags = IORESOURCE_MEM,
};
__request_region函数定义如下:start为起始地址,long为长度,name为设备名:
- struct resource * __request_region(struct resource *parent, unsigned long start, unsigned long n, const char *name)
- {
- struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
- if (res) {
- memset(res, 0, sizeof(*res));
- res->name = name;
- res->start = start;
- res->end = start + n - 1;
- res->flags = IORESOURCE_BUSY;
- write_lock(&resource_lock);
- for (;;) {
- struct resource *conflict;
- conflict = __request_resource(parent, res);
- if (!conflict)/* 返回NULL证明找到了合适的空间 */
- break;
- if (conflict != parent) {
- parent = conflict;
- if (!(conflict->flags & IORESOURCE_BUSY))
- continue;
- }
- /* Uhhuh, that didn't work out.. */
- kfree(res);//函数调用失败
- res = NULL;
- break;
- }
- write_unlock(&resource_lock);
- }
- return res;
- }
__request_resource定义如下:
- /* Return the conflict entry if you can't request it */
- static struct resource * __request_resource(struct resource *root, struct resource *new)
- {
- unsigned long start = new->start;
- unsigned long end = new->end;
- struct resource *tmp, **p;
- /* 三个if进行出错处理 ,如果返回root,则request_resource函数返回NULL*/
- if (end < start)
- return root;
- if (start < root->start)
- return root;
- if (end > root->end)
- return root;
- p = &root->child;
- for (;;) {
- tmp = *p;
- if (!tmp || tmp->start > end) {
- new->sibling = tmp;/* parent的所有child通过sibling链接在一起 */
- *p = new;
- new->parent = root;
- return NULL;
- }
- p = &tmp->sibling; //取下一个sibling
- if (tmp->end < start)
- continue; /* 继续在parent的child链表中给new找到合适的位置
- return tmp; 如果tmp和new有交集:
- 有两种情况,其一如果new只是tmp的一个区段(包含关系),则
- 再次运行到该函数时会把tmp作为new的parent.则new会链接到tmp的child中去,
- 其二是tmp和new有交集,但二者没有包含关系,则出错
- 如果tmp和new完全没有交集,则for循环再次执行,得到root的下一个child.如此循环。
- */
- }
- }
总的来说:每个struct resource结构代表IO资源(一个区间),每个parent的child通过sibling(兄弟)连接在一起,而每个child又可以有child.
这样,内核就可以统一来管理各种io资源,各驱动使用io资源部会混乱。
阅读(2981) | 评论(0) | 转发(1) |