Chinaunix首页 | 论坛 | 博客
  • 博客访问: 37971
  • 博文数量: 9
  • 博客积分: 125
  • 博客等级: 入伍新兵
  • 技术积分: 83
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-07 16:17
文章分类

全部博文(9)

文章存档

2012年(9)

我的朋友

分类: LINUX

2012-05-31 09:55:06

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为设备名:

点击(此处)折叠或打开

  1. struct resource * __request_region(struct resource *parent, unsigned long start, unsigned long n, const char *name)
  2. {
  3. struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
  4. if (res) {
  5. memset(res, 0, sizeof(*res));
  6. res->name = name;
  7. res->start = start;
  8. res->end = start + n - 1;
  9. res->flags = IORESOURCE_BUSY;
  10. write_lock(&resource_lock);
  11. for (;;) {
  12. struct resource *conflict;
  13. conflict = __request_resource(parent, res);
  14. if (!conflict)/* 返回NULL证明找到了合适的空间 */
  15. break;
  16. if (conflict != parent) {
  17. parent = conflict;
  18. if (!(conflict->flags & IORESOURCE_BUSY))
  19. continue;
  20. }
  21. /* Uhhuh, that didn't work out.. */
  22. kfree(res);//函数调用失败
  23. res = NULL;
  24. break;
  25. }
  26. write_unlock(&resource_lock);
  27. }
  28. return res;
  29. }
__request_resource定义如下:

点击(此处)折叠或打开

  1. /* Return the conflict entry if you can't request it */
  2. static struct resource * __request_resource(struct resource *root, struct resource *new)
  3. {
  4. unsigned long start = new->start;
  5. unsigned long end = new->end;
  6. struct resource *tmp, **p;
  7. /* 三个if进行出错处理 ,如果返回root,则request_resource函数返回NULL*/
  8. if (end < start)
  9. return root;
  10. if (start < root->start)
  11. return root;
  12. if (end > root->end)
  13. return root;
  14. p = &root->child;
  15. for (;;) {
  16. tmp = *p;
  17. if (!tmp || tmp->start > end) {
  18. new->sibling = tmp;/* parent的所有child通过sibling链接在一起 */
  19. *p = new;
  20. new->parent = root;
  21. return NULL;
  22. }
  23. p = &tmp->sibling; //取下一个sibling
  24. if (tmp->end < start)
  25. continue; /* 继续在parent的child链表中给new找到合适的位置
  26. return tmp; 如果tmp和new有交集:
  27. 有两种情况,其一如果new只是tmp的一个区段(包含关系),则
  28. 再次运行到该函数时会把tmp作为new的parent.则new会链接到tmp的child中去,
  29. 其二是tmp和new有交集,但二者没有包含关系,则出错
  30. 如果tmp和new完全没有交集,则for循环再次执行,得到root的下一个child.如此循环。
  31. */
  32. }
  33. }
总的来说:每个struct resource结构代表IO资源(一个区间),每个parent的child通过sibling(兄弟)连接在一起,而每个child又可以有child.
这样,内核就可以统一来管理各种io资源,各驱动使用io资源部会混乱。

阅读(2924) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~