bloggerads

2014年5月26日 星期一

PCI 相關spec 隨手紀錄 (To Be Continued)

# 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:


沒有留言:

張貼留言