# Type 0 PCI header register介紹
讀外插PCI controller的option Rom需先enable option rom access(ERBAR.bit0=1)=>先將Expansion Rom BAR bit0設為1再access Expansion Rom BAR address(option rom address)
Bios階段enable MMIO access(command.bit1=1), enable IO access(command.bit0=1) 以及打開Bus Master(command.bit2=1)讓device可以主動發出memory cycle
# Configuration Space accessing
1. 如果是寫DOS的程式,透過 Int 1A 可以 access 超過 0xff 這個範圍
2. CF8, CFC方法: (發 IO transaction)
Read 就是Write address to 0xCF8, Read Dword data from 0xCFC
Write 就是Write address to 0xCF8, Write Dword data to 0xCFC
+ // 示範Read, Author: Martin Lee
+ DWORD ReadPci( CFG_ADDRESS addr)
+ {
+ DWORD val;
+ DWORD daddr = addr.all | BIT(31);
+ WORD oport = 0xcf8;
+ WORD iport = 0xcfc;
+
+ __asm{
+ mov eax, daddr
+ mov dx, oport
+ out dx, eax
+ mov dx, iport
+ in eax, dx
+ mov DWORD ptr val, eax
+ }
+ return val;
+ }
3. 直接MMIO accessing: (發 Memory transaction)
這個方法必須找到MMIO base address(x86通常都會在E000_0000H,這個位址沒有絕對要看chipset的romsip決定)來算出真正Bus/Device/Function/Register的位址,
MMIO Address = MMIO_BASE_Addr + { bus number[27:20], device number[19:15], function number[14:12], extended register number[11:8], register number[7:2], offset [1:0] }.
#define PCIEX_BASE_ADDRESS 0xe0000000
#define PCIE_CFG_ADDR(bus, dev, func, reg) \
((UINTN)(PCIEX_BASE_ADDRESS + ((bus) << 20) + ((dev) << 15) + ((func) << 12) + (reg) ))
# About PCI to PCI bridge:
offset 18h: bridge上層的bus number
offset 19h: bridge下層的bus number
offset 20h: 此bridge以下最深層的bus number
PCI emulation 一般都是深度優先,在emulation開始時,由於不知道subordinate bus number是多少,因此會先設為0xff, 直到列舉完所有bus, 最後會將最深層的bus number一個一個往上回填。若某個pci to pci bridge下層的bus沒有pci to pci bridge再往下連結,這個pci to pci bridge他的Subordinate Bus Number 就會等於 Secondary Bus Number。
# About Type0/Type1 transaction:
沒有留言:
張貼留言