2011年10月31日 星期一

PCI Configuration Space


可以透過I/O方式或Memory方式來存取PCI Configuration Space,但在此之前要先算出該Device的PFA (PCI Function Address)。

I/O可透過I/O Port的0xCF8來指定所要存取的PCI Device的Address,然後再透過0xCFC將Data讀出。
其公式為:
Address = 0x80000000 + (Bus << 16) + (Device << 11) + (Function << 8) + Index
其中0x80000000稱之為Enable bit。

I/O Mapped I/O

Memory存取起來則比較方便,但缺點要先取得PCI的Base Address。
其公式為:
Address = Base Address + (Bus << 20) + (Device << 15) + (Function << 12) + Index
Memory Mapped I/O

各個參數的長度:
Bus: 0 ~ 255, Device: 0 ~ 31, Function: 0 ~ 7
可以注意到兩者的Index長度是不同的,透過I/O的話只能存取0 ~ 255的範圍,Memory則可到0 ~ 4095。

在這介紹一下PCI Configuration Registers。
PCI Device與PCI Bridge的前16個Bytes的格式是相同的。

PCI Device Register (Type 0):
0E: Header Type
可藉由bit 0 ~ 7這三個定義來判斷是甚麼Device:
#define HEADER_TYPE_DEVICE 0x00
#define HEADER_TYPE_PCI_TO_PCI_BRIDGE 0x01
#define HEADER_TYPE_CARDBUS_BRIDGE 0x02
且可由第8個Bit判斷該Device是不是Multi Function:
#define HEADER_TYPE_MULTI_FUNCTION 0x80
#define IS_PCI_MULTI_FUNC(_p) ((_p)->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)

10 ~ 27: Base Address Register
上圖為BAR的Layout,長度為32 bits。
Bit 0: 判斷BAR為Memory還是I/O。

Memory:
Bits 0 ~ 3為ReadOnly。
Bits 1 ~ 2: Address Space的長度,00 - 32 bits、01, 11 - Reserved、10 - 64 bits。
Bit 3: 指出是否為Prefetchable,是的話該Device的Bridge Prefetchable Memory將會指定一段範圍。
Bits 4 ~ 31: Base Address。

I/O:
Bits 0: Reserved。
Bits 2 ~ 31: Base Address。

對BAR填入0xFFFFFFFF會得出一組數值,對此數值做1的補數即可得出這個BAR的長度。
BIOS在Enumerate PCI Device時候,便是以此來取得系統所要分配的PCI Resource。

2C ~ 2F: Subsystem Vendor ID and Subsystem ID

PCI Bridge Register (Type 1):
18 ~ 1A: Primary Bus, Secondary Bus and Subordinate Bus
Primary Bus: 此Bridge的前一個Bus Number是多少。
Secondary Bus: 此Bridge的下一個Bus Number是多少。
Subordinate Bus: 此Bridge底下的最後一個Bus Number是多少。

1C ~ 1D: I/O Base and Limit
指此Bridge所涵蓋的I/O Resource是多少,1C為Base、1D為Limit,一般每個Byte只要看前4個bits就好,I/O Limit會自動補上0xFFF,也就是說I/O Resource至少是以0x1000為一個單位。
如:0x4040的範圍為0x4000 ~ 0x4FFF、0x6050為0x5000 ~ 0x6FFF。

20 ~ 23: Memory Base and Limit
指此Bridge所涵蓋的Memory Resource是多少,20 ~ 21為Base、22 ~ 23為Limit,也只需要看前12個bits就好,Limit會自動補上0xFFFFF,也就是說Memory Resource至少是以0x100000(1MB)為一個單位。
如:Base: 0x5A00, Limit: 0x5AF0範圍是0x5A000000 ~ 0x5AFFFFFF

24 ~ 27: Prefetchable Memory Base and Limit
Prefetchable Memory的範圍。

PCI Device Enumeration:
for (Bus = 0; Bus <= PCI_MAX_BUS; ++Bus) {
for (Device = 0; Device <= PCI_MAX_DEVICE; ++Device) {
for (Func = 0; Func <= PCI_MAX_FUNC; ++Func) {

PciAddress = PCI_ACCRESS_ENABLE_BIT | PciCfgAddr (Bus, Device, Func);

//
// Get Vendor ID and Device ID
//
IoOutput32 (PCI_ADDRESS_INDEX, PciAddress);
VendorId = IoInput16 (PCI_DATA_INDEX);
DeviceId = IoInput16 (PCI_DATA_INDEX + PCI_DEVICE_ID_OFFSET);

if (VendorId == 0xFFFF || DeviceId == 0xFFFF) {
continue;
}

//
// Get HeaderType
//
IoOutput32 (PCI_ADDRESS_INDEX, PciAddress | 0x0C);
HeaderType = IoInput8 (PCI_DATA_INDEX + 0x02);

if (Func == 0 && !(HeaderType & HEADER_TYPE_MULTI_FUNCTION)) {
break;
}
}
}
}

沒有留言:

張貼留言