Initialize Pci Host Bridge
Entry
PciHostBridgeDxe.inf
[Defines]
BASE_NAME = PciHostBridgeDxe
MODULE_TYPE = DXE_DRIVER
ENTRY_POINT = InitializePciHostBridge
PciHostBridge.c
/**
Entry point of this driver.
@retval EFI_SUCCESS Succeed.
@retval EFI_DEVICE_ERROR Fail to install PCI_ROOT_BRIDGE_IO protocol.
**/
EFI_STATUS
EFIAPI
InitializePciHostBridge (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
Step
- 因為要給Host Bridge適當的resources所以需要先掃出Host Bridge下面有哪些Root Bridge這邊就是把所有的Bus下面的Dev和Fun找一遍,如果有找到Vid且Header Type = 1才會把現在的Bus視為RootBridge。RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);if ((RootBridges == NULL) || (RootBridgeCount == 0)) {return EFI_UNSUPPORTED;}
- 找到了以後就要確定IO,Memory和MemAbove4G的Resources
1Ch : IO Base
1Dh : IO Limit
20h : Memory Base
22h : Memory Limit
24h : Prefetchable Memory Base
26h : Prefetchable Memory Limit要記得的是這邊是找到Base和Size,Limit = Base + Size - 1。
這邊配完resources以後,會做兩件事情:
a. 若是IDE controller, legacy VGA controller, PCI bridge的話會先加對應的Attributes
b. 再來看是不是multi function(Header Type bit7),是的話要重新配resources,否的話就直接開始Initialize Root Bridge了。
- 接下來步驟的前提是有抓到Vid且分配好resources。
但其實initialize root bridge就是把剛剛找到的,分配好的位置放進structure裡面,然後再allocatepool出一塊memory把所有的root bridge照順序放進去方便之後使用(Step1 return回來的RootBridge),我是覺得這邊比較像準備工作。 - 做了這麼多事情以後,終於要initialize HostBridge了:看起來就是做了一個LinkList的頭,接下來就要拿出剛剛的RootBridges裡面的data,一個一個做成Root Bridge Device Handle,且一個一個掛在Host Bridge後面。//// Most systems in the world including complex servers have only one Host Bridge.//HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));HostBridge->Signature = PCI_HOST_BRIDGE_SIGNATURE; //SIGNATURE_32 ('p', 'h', 'b', 'g')HostBridge->CanRestarted = TRUE;InitializeListHead (&HostBridge->RootBridges);
- 接下來要做的事情是把剛剛Root Bridge的結構拿出來處理然後一個一個掛在Host Bridge後面CreateRootBridge會做下面這些事情://// Create Root Bridge Device Handle in this Host Bridge//for (Index = 0; Index < RootBridgeCount; Index++) {//// Create Root Bridge Handle Instance//RootBridge = CreateRootBridge (&RootBridges[Index]);ASSERT (RootBridge != NULL);if (RootBridge == NULL) {continue;} . . .//// Insert Root Bridge Handle Instance//InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);}
a. 確認resources的Limit >= Base
b. 接著把該丟的丟進去c. 有了這些資訊後,在Allocate一塊Io或Memory space出來,最後就是InsertTailList了。RootBridge = AllocateZeroPool (sizeof (PCI_ROOT_BRIDGE_INSTANCE));ASSERT (RootBridge != NULL);RootBridge->Signature = PCI_ROOT_BRIDGE_SIGNATURE;RootBridge->Supports = Bridge->Supports;RootBridge->Attributes = Bridge->Attributes;RootBridge->DmaAbove4G = Bridge->DmaAbove4G;RootBridge->NoExtendedConfigSpace = Bridge->NoExtendedConfigSpace;RootBridge->AllocationAttributes = Bridge->AllocationAttributes;RootBridge->DevicePath = DuplicateDevicePath (Bridge->DevicePath);RootBridge->DevicePathStr = DevicePathStr;RootBridge->ConfigBuffer = AllocatePool (TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));ASSERT (RootBridge->ConfigBuffer != NULL);InitializeListHead (&RootBridge->Maps);CopyMem (&RootBridge->Bus, &Bridge->Bus, sizeof (PCI_ROOT_BRIDGE_APERTURE));CopyMem (&RootBridge->Io, &Bridge->Io, sizeof (PCI_ROOT_BRIDGE_APERTURE));CopyMem (&RootBridge->Mem, &Bridge->Mem, sizeof (PCI_ROOT_BRIDGE_APERTURE));CopyMem (&RootBridge->MemAbove4G, &Bridge->MemAbove4G, sizeof (PCI_ROOT_BRIDGE_APERTURE));CopyMem (&RootBridge->PMem, &Bridge->PMem, sizeof (PCI_ROOT_BRIDGE_APERTURE));CopyMem (&RootBridge->PMemAbove4G, &Bridge->PMemAbove4G, sizeof (PCI_ROOT_BRIDGE_APERTURE));
PS.這邊要注意的是step2拿到的Base是device address,需要處理過變成host address才能allocate出一塊memory。 - 把HostBridge和RootBridge全部都install到protocol裡面,之後把剛剛Allocate給instance的空間free掉就完成InitializePciHostBridge的部分了。Status = gBS->InstallMultipleProtocolInterfaces (&HostBridge->Handle,&gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,NULL); . . .Status = gBS->InstallMultipleProtocolInterfaces (&RootBridge->Handle,&gEfiDevicePathProtocolGuid, RootBridge->DevicePath,&gEfiPciRootBridgeIoProtocolGuid, &RootBridge->RootBridgeIo,NULL);
沒有留言:
張貼留言