最近在看同事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位)。