IORESOURCE_IO和IORESOURCE_MEM

来源:互联网 发布:windows韩文版 编辑:程序博客网 时间:2024/06/07 02:16
内核中有很多资源,但属于IO资源的有:#define IORESOURCE_IO 0x00000100 /* Resource type */#define IORESOURCE_MEM 0x00000200#define IORESOURCE_IRQ 0x00000400#define IORESOURCE_DMA 0x00000800本文我主要研究IORESOURCE_IO IORESOURCE_MEM,及地址空间的管理,涉及的文件只有kernel/resource.c.这两种资源本质上都是一段地址空间. 只是类型不一样IORESOURCE_IO 指的是IO地址空间,这个空间从kernel编程上来看,只能通过专门的接口函数才能访问.硬件层面上,cpu需要用特殊指令才能访问或需要用特殊访问方式才能访问,不能直接用指针来寻址.在PC机上,其指的就是PCI/CPU IO address space.在嵌入式中,基本上没有io address space. IORESOURCE_MEM 指的是属于外设或者用于和设备通讯的支持直接寻址的地址空间.PC机上,主板上北桥上连的内存都是交给kernel直接管理,或者都是用于软件执行,所以这部分内存不属于IORESOURCE_MEM, IORESOURCE_MEM主要是指PCI设备的 memory address space. 但在嵌入式上, 主板上的sdram一般是设备与cpu共享的. 故交给kernel直接管理的内存只是一部分.余下的内存以及寄存器空间都作为IORESOURCE_MEM来管理.只所以需要管理,是因为像PCI总路线设备的这些地址空间是设备向系统申请的,故是可配置的,并且设备并身可能热插拨或更换,故其变成一种可分配的资源. 故内核用算法来管理分配与释放操作,防止冲突和便于查询维护.但实际PC中,BIOS一般会做分配操作,内核需要是把分配结果添加进来,故提供了注册(或者叫做添加)接口. 在嵌入式系统中,外设的地址也通常是固定的,只需要添加即可.这两种资源,内核采用同样的管理算法--二叉树.相当于内核维护两个独立的二叉树. 按地址基地址与地址长度范围作为管理数据.可以添加,分配,释放节点.分配过程中可以避免空间冲突,添加时可以识别空间冲突.根节点在kernel/resource.c中以全局变量方式定义.根节点用于限制地址空间的范围.主要接口:int insert_resource(struct resource *parent, struct resource *new)int adjust_resource(struct resource *res, unsigned long start, unsigned long size)int allocate_resource(struct resource *root, struct resource *new, unsigned long size, unsigned long min, unsigned long max, unsigned long align, void (*alignf)(void *, struct resource *, unsigned long, unsigned long), void *alignf_data)int release_resource(struct resource *old)int request_resource(struct resource *root, struct resource *new)上面的接口对上述4种资源类型都有效,对于IORESOURCE_IO 和 IORESOURCE_MEM这两种资源,使用这两个接口更为方便request_region(start,n,name)release_region(start,n) io spacerequest_mem_region(start,n,name)release_mem_region(start,n) mem space在 /proc 文件系统中,ioports和iomem分别显示系统当前这两种资源.嵌入式设备的外设一般先作为platform device添加到platform bus上,其主要目的就是向系统注册资源,在platform_add_devices时做,如:/* Watchdog timer parameters */static struct resource wdt_resource[] = { /* Watchdog timer only needs a register address */ [0] = { .start = 0xFFC00008, .end = 0xFFC00010, .flags = IORESOURCE_MEM, }};struct platform_device wdt_device = { .name = "wdt", .id = -1, .num_resources = ARRAY_SIZE(wdt_resource), .resource = wdt_resource,};platform_add_devices(wdt_device,1);故如已知设备的物理地址,并不一定需要request_mem_region,因为这个操作并没有涉及到任何硬件,与软件访问也没有任何关系..但一般还是推荐做.I/O port 访问流程( 不用mem模拟方式):request_region() #在设备驱动模块加载或opn() 函数中进行,物理i/o port地址由pci bios模块分配inb(),outb()等 #在设备驱动初始化,write(),red(),ioctl() 等函数中进行relase_region #在设备驱动模块卸载或release() 函数中进行I/O port 访问流程( 用mem模拟方式):request_region() ioport_map #在设备驱动模块加载或opn() 函数中进行,物理i/o port地址由pci bios模块分配ioread8,iowrite8等 #在设备驱动初始化,write(),red(),ioctl() 等函数中进行ioport_unmap()relase_region #在设备驱动模块卸载或release() 函数中进行request_mem_regionioremap #在设备驱动模块加载或opn() 函数中进行,物理i/o port地址由pci bios模块分配ioread8,iowrite8等 #在设备驱动初始化,write(),red(),ioctl() 等函数中进行iounmap()relase_region #在设备驱动模块卸载或release() 函数中进行文章出处:飞诺网(www.diybl.com):http://www.diybl.com/course/6_system/linux/Linuxjs/2008827/137930.html
0 1
原创粉丝点击