request_mem_region 与 ioremap ,struct resource

来源:互联网 发布:战神诀披风进阶数据 编辑:程序博客网 时间:2024/05/22 20:09
 转载:
http://apps.hi.baidu.com/share/detail/30686754
request_mem_region 与 ioremap

       如果从根本上说起的话应该从Intel的处理器芯片与其它的芯片的不同说起,与这两个函数相关的是对 I/OPort与内存的寻址方式,intel的处理器中内存与外部IOPort是独立编址与寻址的,这就有了两种地址空间分别是内存地址空间与IO地址空间,访问IO地址空间需使用不同的指令。与intel不同的是有些处理器(如PowerPC等)就只有一个地址空间,即内存空间,在这种情况下,外设的I/OPort物理地址就需要被映射到内存地址空间才能被访问,这主就是所说的Memery-Mapped, 而Intel的把I/OPort物理地址映射到I/O地址空间中就是所说的IO-Mapped。

       要使用I/OPort内存则需先申请再映射,即先调用request_mem_region,内核发现这样的函数调用会将该I/OPort地址标记为以被使用,如其它人再来申请则告之其该内存已使用。调用申请函数之后可以放心的映射(ioremap)了,当然不调用申请函数直接映射该I/OPort地址到虚拟空间也是可以的,但鬼才知道一个I/OPort地址指向多个虚拟空间什么发生什么事情! 把I/OPort地址映射到虚拟地址空间还有一个好处就是访问I/OPort可以虚拟地址上加一偏移就O啦。

struct--resource
2007年08月29日 星期三 14:23

linux对挂接在4G总线空间上的设备实体的管理方式 -- struct resource
转载:http://hi.baidu.com/zengzhaonong/blog/item/654c63d92307f0eb39012fff.html
/usr/src/linux-2.6.21.5/include/linux/ioport.h

struct resource {
    resource_size_t start;
    resource_size_t end;
    const char      *name;
    unsigned long   flags;
    struct resource *parent, *sibling, *child;
};


struct resource_list {
    struct resource_list *next;
    struct resource      *res;
    struct pci_dev       *dev;
};


文章来源:http://gliethttp.cublog.cn

    一个独立的挂接在cpu总线上的设备单元,一般都需要一段线性的地址空间来描述设备自身,linux是怎么管理所有的这些外部"物理地址范围段",进而给用户和linux自身一个比较好的观察4G总线上挂接的一个个设备实体的简洁、统一级联视图的呢?
    linux采用struct resource结构体来描述一个挂接在cpu总线上的设备实体(32位cpu的总线地址范围是0~4G):
resource->start描述设备实体在cpu总线上的线性起始物理地址;
resource->end -描述设备实体在cpu总线上的线性结尾物理地址;
resource->name 描述这个设备实体的名称,这个名字开发人员可以随意起,但最好贴切;
resource->flag 描述这个设备实体的一些共性和特性的标志位;

    只需要了解一个设备实体的以上4项,linux就能够知晓这个挂接在cpu总线的上的设备实体的基本使用情况,也就是[resource->start, resource->end]这段物理地址现在是空闲着呢,还是被什么设备占用着呢?
    linux会坚决避免将一个已经被一个设备实体使用的总线物理地址区间段[resource->start, resource->end],再分配给另一个后来的也需要这个区间段或者区间段内部分地址的设备实体,进而避免设备之间出现对同一总线物理地址段的重复引用,而造成对唯一物理地址的设备实体二义性.
    以上的4个属性仅仅用来描述一个设备实体自身,或者是设备实体可以用来自治的单元,但是这不是linux所想的,linux需要管理4G物理总线的所有空间,所以挂接到总线上的形形色色的各种设备实体,这就需要链在一起,因此resource结构体提供了另外3个成员:指针parent、sibling和child:分别为指向父亲、兄弟和子资源的指针。      
    以root source为例,root->child(*pchild)指向root所有孩子中地址空间最小的一个;pchild->sibling是兄弟链表的开头,指向比自己地址空间大的兄弟。






    物理内存页面是重要的资源。从另一个角度看,地址空间本身,或者物理存储器在地址空间中的位置,也是一种资源,也要加以管理 -- resource管理地址空间资源。

    内核中有两棵resource树,一棵是iomem_resource, 另一棵是ioport_resource,分别代表着两类不同性质的地址资源。两棵树的根也都是resource数据结构,不过这两个数据结构描述的并不是用于具体操作对象的地址资源,而是概念上的整个地址空间。
    将主板上的ROM空间纳入iomem_resource树中;系统固有的I/O类资源则纳入ioport_resource树

/usr/src/linux/kernel/resource.c
----------------------------------------
struct resource ioport_resource = {
    .name   = "PCI IO",
    .start -= 0,
    .end    = IO_SPACE_LIMIT,
    .flags 
-= IORESOURCE_IO,
};

struct resource iomem_resource = {
    .name   = "PCI mem",
    .start 
-= 0,
    .end    = -1,
    .flags 
-= IORESOURCE_MEM,
};


/usr/src/linux/include/asm-i386/io.h
#define IO_SPACE_LIMIT 0xffff
0 ~ 0xffff   <===> 64K
1、platform_get_resource
 
    出处 drivers/base/platform.c
    原型
struct resource *
platform_get_resource(struct platform_device *dev, unsigned int type,
        unsigned int num)
    说明:

 platform_get_resource - get a resource for a device
 @dev: platform device
 @type: resource type
 @num: resource index
 
2、request_mem_region
 
   出处  include/linux/ioport.h
   原型  #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name))
kernel/resource.c中有如下函数:

 __request_region - create a new busy resource region
 @parent: parent resource descriptor
 @start: resource start address
 @n: resource region size
 @name: reserving caller's ID string

struct resource * __request_region(struct resource *parent,
       resource_size_t start, resource_size_t n,
       const char *name)
3、request_region
 
    出处  include/linux/ioport.h
    原型  #define release_region(start,n) __release_region(&ioport_resource, (start), (n))