欢迎来到天天文库
浏览记录
ID:50337981
大小:75.00 KB
页数:4页
时间:2020-03-08
《ioremap的原理及意义.doc》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库。
1、ioremap()的原理及意义2011-02-2117:25:291分类:s3c-linuxI标签:I字号大中小订阅void*—ioremap(unsignedlongphys_addr,unsignedlongsize,unsignedlongflags)入口:phys_addr:要映射的起始的IO地址;size:要映射的空间的大小;flags:要映射的10空间的和权限有关的标志;功能:将一个IO地址空间映射到内核的虚拟地址空间上去,便于访问;实现:対要映射的10地址空间进行判断,低PCI/ISA地址不需要重新映射,也不允许用户将10
2、地址空间映射到止在使用的RAM中,报后申请一个vm_area_struct结构,调用remap_area_pages填写页表,若填写过程不成功则释放申请的vm_area_struct空间;意义:比如isa设备和pci设备,或者是fb,硬件的跳线或者是物理连接方式决定了硬件上的内存影射到的cpu物理地址。在内核访问这些地址必须分配给这段内存以虚拟地址,这止是—ioremap的意义所在,需要注意的是,物理内存已经”存在”了,无需allocpage给这段地址了.文件中的注释也是比较详尽的,并且只暴露了—ioremapjounmap两个函数供其
3、他模块调用,函数remap_area_pte,reniap_area_pmd,reniap_area_pages只为—ioremap所用.为了使软件访问I/O内存,必须为设备分配虚拟地址.这就是ioremap的工作.这个函数专门用来为I/O内存区域分配媲拟地址(空间).对于直接映射的I/O地址ioremap不做任何事情(uClinux中是这么实现的??)有了ioremap(和ioimmap),设备就可以访问任何I/O内存空间,不论它是否f(接映射到虚拟地址空间.但是,这些地址永远不能直接使用(指物理地址),而要用readb这种函数.根据
4、计算机平台和所使用总线的不同,1/0内存可能是,也可能不是通过页表访问的,通过页表访问的是统一编址(PowerPC),否则是独立编ill:(Intel)o如果访问是经山页衣进行的,内核必须首先安排物理地址使其对设备驱动程序可见(这通常意味看在进行任何I/O之前必须先调用ioremap)。如果访问无需页表,那么I/O内存区域就很象I/O端口,可以使用适当形式的函数读写它们。不管访问I/O内存吋是否需要调用ioremap,都不鼓励直接使用指向I/O内存的指针。尽管(在T/O端口和I/O内存”介绍过)1/0内存在硬件一•级是象普通RAM一样寻
5、址的,但在T/O寄存器和常规内存”中描述过的那些需要额外小心的情况中已经建议不要使用普通指针。相反,使用“包装的”函数访问I/O内存,一方面在所有平台上都是安全的,另一方面,在可以直接对指针指向的内存区域执行操作的时候,该函数是经过优化的自□原以为当给显卡上的存储空间分配了总线地址A以后,它所对应的虚拟空间就随之确定了.也就是A+3G可是事实上,在ioremap.c文件里面的实现并不是这样的.所用的函数是—ioremap(unsignedlongphys_addr,unsignedlongsize,unsignedlongflags)实
6、现的时候是为从phys_addr开始的size大小的物理地址分配一块虚拟地址.注意这里是分配,而不是指疋•我所认为的分配应该是指立即根据phys_addr得到其所对应的虚拟地址是phys_addr+3G.本人认为一合理的解释是这样的:系统虚拟空I'可中映射的非10卡上的地址空间满足3G差关系,而IO卡上的存储空间就不满足了.欢迎讨论在X86体系下的,CPU的物理地址和PCI总线地址共用一个空间。linux内核将3G-4G的虚拟地址固定映射到了物理地址的0—1G的地方。但是如果外围设备上的地址高于1G,例如某块PCI卡分配到了一个高于1G
7、的地址,就需要调用ioremap來重新建立该物理地址(总线地址)和虚拟地址之间的映射。这个映射过程是这样的:在ioremap.c文件的_ioremap函数中首先对将来映射的物理地址进行检杳,也就是不能重新映射640K-1M地址(山于历史的原因,物理地址640k到1M空间被保留给了显卡),普通的血m地也不能重新被映射。之后调用get_vm_area获得可用的虚拟地址,然后根这虚拟地址和欲映射的物理地址修改页表,之后内核就可以用这个虚拟地址来访问映射的物理地址了。offset:物理空间(I/O设备上的一块物理内存)的起始地址size:物理空
8、间的大小给一段物理地址(起始地址offset)建立页表(地址映射)staticinlinevoid—iomem*ioremap(unsignedlongoffset,unsignedlongsize){re
此文档下载收益归作者所有