自问这个问题已经有一段时间了,但是我讨厌孤立的问题:)
首先,让我们过度简化一个现代的x86平台,并假设它具有从0x00000000到0xFFFFFFFF的32位地址空间。我们将忽略所有特殊/保留区域,TOLUD(较低可用DRAM的顶部,Intel说法)孔等。我们将其称为系统内存映射。
其次,PCI Express 扩展了 PCI。从软件的角度来看,它们非常相似。
首先,我将跳到您的第3个- 配置空间。指向配置空间的所有地址都是从系统内存映射中分配的。PCI设备的配置空间为256字节-PCI Express扩展为4KB。这4KB的空间消耗了系统内存映射中的内存地址,但是实际值/位/内容通常在外围设备的寄存器中实现。例如,当您读取供应商ID或设备ID时,即使使用的内存地址来自系统内存映射,目标外围设备也将返回数据。
您说这些是“分配到RAM中的”-不是,实际的位/有状态元素在外围设备中。但是,它们被映射到系统内存映射中。接下来,您询问它是否是所有PCIe设备上通用的寄存器集-是和否。PCI配置空间的工作方式,每个部分的末尾都有一个指针,指示是否还有更多的“东西”要读取。所有PCIe设备都必须实现最低限度,然后更高级的设备可以实现更多。至于它对功能操作的有用性,它是强制性的并且被大量使用。:)
现在,您关于BAR(基地址寄存器)的问题是一个可以隔离到内存空间和I / O空间的好空间。由于是以x86为中心的,因此该规范允许除了类型之外还指定BAR大小。这允许设备请求常规的内存映射BAR或IO空间BAR,这会占用x86机器拥有的4K I / O空间。您会注意到,在PowerPC机器上,I / O空格键毫无用处。
BAR基本上是设备告诉主机它需要多少内存以及什么类型(上面讨论过)的方式。如果我要求说1MB的内存映射空间,BIOS可能会将地址0x10000000分配给我0x10100000。这不是在消耗物理RAM,而是在消耗地址空间(您现在知道为什么32位系统会遇到扩展卡(例如具有GB RAM的高端GPU)的问题吗?)。现在,将写/读为0x10000004的内存发送到PCI Express设备,该内存可能是连接到LED的字节宽寄存器。因此,如果我将0xFF写入物理内存地址0x10000004,则将打开8个LED。这是内存映射I / O的基本前提。
I / O空间的行为类似,只是它在单独的内存空间x86 I / O空间中运行。地址0x3F8(COM1)在I / O空间和内存空间中都存在,并且是两个不同的事物。
最后一个问题,消息是指一种新型的中断机制,即消息信号中断或简称MSI。传统PCI设备具有四个中断引脚,即INTA,INTB,INTC,INTD。这些通常在插槽中交错,因此INTA进入插槽0的INTA,然后进入插槽1的INTB,然后进入插槽2的INTC,然后进入插槽3的INTD,然后回到插槽4的INTA。原因是大多数PCI这些设备仅实现了INTA,并且通过搅动它(具有三个设备),每个设备最终都会将自己的中断信号发送给中断控制器。MSI只是使用PCI Express协议层发出中断信号的一种方式,而PCIe根联合体(主机)负责中断CPU。
这个答案可能为时已晚,无法为您提供帮助,但可能会对将来的Googler / Binger有所帮助。
最后,我建议您先阅读一下英特尔的这本书,以获得对PCIe的良好而详尽的介绍,然后再继续进行。另一个参考文献是LWN的在线电子书《Linux设备驱动程序》。