【Tips】关于PCI和PCIe的配置空间差异和io/memory io读写
最近在看同事2023年讲的PCI基础课,感觉确实是豁然开朗了,赞美同事。
PCIe实际上是PCI的扩展(extended),PCIe设备相当于是迭代升级产品。
而PCIe的配置空间基于PCI原有的0xFF(256字节)配置空间扩展到了OxFFF(4K),也就是普通PCI设备拥有256字节配置空间,PCIe设备有4K配置空间(0到FF是PCI配置空间,100到1FF是作为PCIe扩展配置空间)。
如图所示,而100到1FFF那段扩展空间多用于capabilities(注意,PCIe区域的capabilities结构和PCI区域的有区别),PCIe设备的PCI部分配置空间最后的capability会指到PCIe部分(100-1FF)去。下图是PCI的capability,如果只是PCI设备的话,到寻址为00H的部分它就结束capabilities了。
下图右侧是PCIe部分的capability,可以看到它的布局和PCI部分的不一样,比如ID占16bit(PCI里是8bit),因为它的寻址最多会到FFF去。
然后要讲的就是关于它们的io/memory io读写。
PCI设备的话,用IO方式读写没问题,但是对于PCIe设备的扩展空间部分,Register就明显不足了(我们以前写register写的是XX H,因为PCI设备的配置空间最多到FF H)。这个时候我们就必须选择Memory IO的方式来读写(当然Memory IO的方式也可以读PCI设备,可以看作是一种兼容)。注意:如果还要用IO方式来读写PCIe设备,只能读前面的0至FF区域,写入CF8的是以80开头而不是MMIO方式的F开头。
MMIO读取(用C语言的函数)具体怎么写:
这里最前面4位(31:28)的1111是规定,接8位Bus,接5位Device,接3位Function,后面剩下的12位是寄存器(000到最大的FFF皆为12位)。
这12位可以细分为11:8这4bit的PCI扩展(extended)寄存器,和7:0的PCI寄存器(图里1:0被单独写出来的原因可以看我另外一篇博客:关于PCI的IO Port读取为什么写入0CF8的32位里最后2bit规定是0-CSDN博客)。
和IO读写写入的值(注意这里IO输入的80开头的只是一个格式,并不是实际地址,MMIO输入的F开头的才是实际内存地址)的区别大概就是前四位由1000变为1111,bus device function集体左移4位,function之后的12位写register(IO里function后面只剩8位)。