c - 为什么我们只能直接访问一个PCI物理地址中的640k-1MB区域?

标签 c linux linux-kernel kernel ioremap

http://www.mjmwired.net/kernel/Documentation/IO-mapping.txt

153  - remapping and writing:
154     /*
155      * remap framebuffer PCI memory area at 0xFC000000,
156      * size 1MB, so that we can access it: We can directly
157      * access only the 640k-1MB area, so anything else
158      * has to be remapped.
159      */
160     void __iomem *baseptr = ioremap(0xFC000000, 1024*1024);
161 
162     /* write a 'A' to the offset 10 of the area */
163     writeb('A',baseptr+10);
164 
165     /* unmap when we unload the driver */
166     iounmap(baseptr);
167 

可以解释一下为什么这样我们只能直接访问 640k-1MB 区域吗?

最佳答案

简短回答:因为 Linus 决定这样做。

长答案: 事实上,它认为你应该能够在没有司机注册的情况下访问那个区域是错误的。但没关系。

在过去,在 1990 年代的某个时候,PCI 还不存在,显卡、网卡等都在使用一种叫做 ISA 总线的东西。它没有允许您从卡中请求信息或根据它认为硬件地址应该在何处将内容配置到卡上的奇特功能。所有的 ISA 内存都在 A0000 (640K) 和 FFFFF (1MB-1) 之间。所以,在 Linux 的早期,这是图形和诸如此类的东西所在的地方,而内核并不能真正知道这些东西在哪里。无论哪种方式,由于更好的硬件的发展,我们现在没有这些硬件。祝你好运!

出于兼容性原因,这个内存空间在启动期间仍然会被使用,因为在你加载驱动程序和设置 PCI 硬件之前,它会以“传统模式”运行,所以你仍然可以运行非常旧的 DOS 和其他旧软件没有它的机器表现得很奇怪。

但是,例如,一旦配置了您的显卡,它就会设置 BAR(总线地址范围)以告知世界它在总线地址空间(物理地址)中的位置。 ioremap 会将物理地址映射到您可以在内核中使用的虚拟地址 - 本例中为 baseptr。 [我可以更详细地介绍 ioremap,因为我最近一直在研究从中派生的一些代码]。

正如另一个答案所说,您需要询问设备它的 BAR 是什么(它是 PCI 配置空间的一部分),然后将其内存映射到虚拟地址。您可以看到使用 lspci -v|grep Memory 的地方(当然,仅使用 lspci -v 将为您提供更多信息,包括哪个设备有什么内存).这些地址是物理地址。

关于c - 为什么我们只能直接访问一个PCI物理地址中的640k-1MB区域?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14030320/

相关文章:

c2059 do while loop C 错误,怎么了?

c - 为什么 printf ("%d", getchar()) 打印额外的 10

linux - 关于 shell 中的 sed 表达式评估

linux - 当他们在这种情况下说 "fragile state"时,它实际上是什么意思?

c - 我有一个文件,将其所有内容复制到一个数组中。例如,如何删除第一个字符串或中间字符串?

c - 从 Char* 数组中提取数字(C 字符串)

regex - 冯内古蒂命令 : Replace semicolons with periods *correctly*

c - 写入堆内存时调用的系统调用

c - 如何使用 EXPORT_SYMBOL 或等效项在两个内核模块之间导出结构?

linux - 线程 : some questions