IORESOURCE_IO和IORESOURCE_MEM

内核中有很多资源,但属于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
void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head) { struct pci_dev *dev; unsigned long mask, prefmask, type2 = 0, type3 = 0; resource_size_t additional_mem_size = 0, additional_io_size = 0; struct resource *b_res; int ret; list_for_each_entry(dev, &bus->devices, bus_list) { struct pci_bus *b = dev->subordinate; if (!b) continue; switch (dev->hdr_type) { case PCI_HEADER_TYPE_CARDBUS: pci_bus_size_cardbus(b, realloc_head); break; case PCI_HEADER_TYPE_BRIDGE: default: __pci_bus_size_bridges(b, realloc_head); break; } } /* The root bus? */ if (pci_is_root_bus(bus)) return; switch (bus->self->hdr_type) { case PCI_HEADER_TYPE_CARDBUS: /* Don't size CardBuses yet */ break; case PCI_HEADER_TYPE_BRIDGE: pci_bridge_check_ranges(bus); if (bus->self->is_hotplug_bridge) { additional_io_size = pci_hotplug_io_size; additional_mem_size = pci_hotplug_mem_size; } /* Fall through */ default: pbus_size_io(bus, realloc_head ? 0 : additional_io_size, additional_io_size, realloc_head); /* * If there's a 64-bit prefetchable MMIO window, compute * the size required to put all 64-bit prefetchable * resources in it. */ b_res = &bus->self->resource[PCI_BRIDGE_RESOURCES]; mask = IORESOURCE_MEM; prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH; if (b_res[2].flags & IORESOURCE_MEM_64) { prefmask |= IORESOURCE_MEM_64; ret = pbus_size_mem(bus, prefmask, prefmask, prefmask, prefmask, realloc_head ? 0 : additional_mem_size, additional_mem_size, realloc_head); /* * If successful, all non-prefetchable resources * and any 32-bit prefetchable resources will go in * the non-prefetchable window. */ if (ret == 0) { mask = prefmask; type2 = prefmask & ~IORESOURCE_MEM_64; type3 = prefmask & ~IORESOURCE_PREFETCH; } } /* * If there is no 64-bit prefetchable window, compute the * size required to put all prefetchable resources in the * 32-bit prefetchable window (if there is one). */ if (!type2) { prefmask &= ~IORESOURCE_MEM_64; ret = pbus_size_mem(bus, prefmask, prefmask, prefmask, prefmask, realloc_head ? 0 : additional_mem_size, additional_mem_size, realloc_head); /* * If successful, only non-prefetchable resources * will go in the non-prefetchable window. */ if (ret == 0) mask = prefmask; else additional_mem_size += additional_mem_size; type2 = type3 = IORESOURCE_MEM; } /* * Compute the size required to put everything else in the * non-prefetchable window. This includes: * * - all non-prefetchable resources * - 32-bit prefetchable resources if there's a 64-bit * prefetchable window or no prefetchable window at all * - 64-bit prefetchable resources if there's no prefetchable * window at all * * Note that the strategy in __pci_assign_resource() must match * that used here. Specifically, we cannot put a 32-bit * prefetchable resource in a 64-bit prefetchable window. */ pbus_size_mem(bus, mask, IORESOURCE_MEM, type2, type3, realloc_head ? 0 : additional_mem_size, additional_mem_size, realloc_head); break; } }
03-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值