PciHostBridge: 提供PCI配置空间,IO,MEM空间访问接口以及统一维护平台相关的PCI资源,提供gEfiPciHostBridgeResourceAllocationProtocolGuid,创建RootBridge等为PciBusDxe提供服务;
InitializePciHostBridge->PciHostBridgeGetRootBridges(&RootBridgeCount)
PciHostBridgeGetRootBridges: 获取和架构平台相关的RootBridges信息(Segment,Bus,MemResource, DevicePath等);
如果存在多个RootBridge, 需要提供多个根桥信息, PciHostBridge将这些信息维护起来;
typedef struct {
UINT32 Segment; ///< Segment number.
UINT64 Supports; ///< Supported attributes.
///< Refer to EFI_PCI_ATTRIBUTE_xxx used by GetAt tributes()
///< and SetAttributes() in EFI_PCI_ROOT_BRIDGE_I O_PROTOCOL.
UINT64 Attributes; ///< Initial attributes.
///< Refer to EFI_PCI_ATTRIBUTE_xxx used by GetAt tributes()
///< and SetAttributes() in EFI_PCI_ROOT_BRIDGE_I O_PROTOCOL.
BOOLEAN DmaAbove4G; ///< DMA above 4GB memory.
///< Set to TRUE when root bridge supports DMA ab ove 4GB memory.
BOOLEAN NoExtendedConfigSpace; ///< When FALSE, the root bridge supports
///< Extended (4096-byte) Configuration Space.
///< When TRUE, the root bridge supports
///< 256-byte Configuration Space only.
BOOLEAN ResourceAssigned; ///< Resource assignment status of the root bridg e.
///< Set to TRUE if Bus/IO/MMIO resources for roo t bridge have been assigned.
UINT64 AllocationAttributes; ///< Allocation attributes.
///< Refer to EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PME M and
///< EFI_PCI_HOST_BRIDGE_MEM64_DECODE used by Get AllocAttributes()
///< in EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_P ROTOCOL.
PCI_ROOT_BRIDGE_APERTURE Bus; ///< Bus aperture which can be used by the root b ridge.
PCI_ROOT_BRIDGE_APERTURE Io; ///< IO aperture which can be used by the root br idge.
PCI_ROOT_BRIDGE_APERTURE Mem; ///< MMIO aperture below 4GB which can be used by the root bridge.
PCI_ROOT_BRIDGE_APERTURE MemAbove4G; ///< MMIO aperture above 4GB which can be used by the root bridge.
PCI_ROOT_BRIDGE_APERTURE PMem; ///< Prefetchable MMIO aperture below 4GB which c an be used by the root bridge.
PCI_ROOT_BRIDGE_APERTURE PMemAbove4G; ///< Prefetchable MMIO aperture above 4GB which c an be used by the root bridge.
EFI_DEVICE_PATH_PROTOCOL *DevicePath; ///< Device path.
} PCI_ROOT_BRIDGE;
CreateRootBridge(&RootBridges[Index])->AddIoSpace&AddMemoryMappedIoSpace: 将每个桥的资源信息插入全局GCD来标识该段CPU访问地址为IO&MemmapIo地址;
MemApertures[0] = &RootBridges[Index].Mem;
MemApertures[1] = &RootBridges[Index].MemAbove4G;
MemApertures[2] = &RootBridges[Index].PMem;
MemApertures[3] = &RootBridges[Index].PMemAbove4G;
for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE (MemApertures); MemApertureIndex++) {
if (MemApertures[MemApertureIndex]->Base <= MemApertures[MemApertureIndex]->Limit) {
//
// Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
// For GCD resource manipulation, we need to use host address.
//
HostAddress = TO_HOST_ADDRESS (MemApertures[MemApertureIndex]->Base,
MemApertures[MemApertureIndex]->Translation);
Status = AddMemoryMappedIoSpace (
HostAddress,
MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
EFI_MEMORY_UC
);
ASSERT_EFI_ERROR (Status);
Status = gDS->SetMemorySpaceAttributes (
HostAddress,
MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
EFI_MEMORY_UC
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "PciHostBridge driver failed to set EFI_MEMORY_UC to MMIO aperture - %r .\n", Status));
}
在目前龙芯虚拟地址平台下Cpu视角的PCIE_MEM空间=HT1空间为0x80000e0000000000+BAR_ADDRESS;
BAR_ADDRESS:是站在主桥7A的视角来看的PCIE_MEM地址;
所以TO_HOST_ADDRESS(CPU视角) = ((DeviceAddress) - (TranslationOffset)) = BAR_ADDRESS - (~0x80000e0000000000+1):
switch (i) {
case 0:
/*Bus Base*/
RootBridge->Bus.Base = 0;
RootBridge->Bus.Limit = 255;
/*Io Base*/
RootBridge->Io.Base = 0x20000;
RootBridge->Io.Limit = RootBridge->Io.Base + 0x2000000;
//RootBridge->Io.Translation = 0x7ffff10204000000; /*0x80000efdfc000000*/
/*Mem Base*/
RootBridge->Mem.Base = 0x20000000;
RootBridge->Mem.Limit = RootBridge->Mem.Base + 0x60000000;
RootBridge->Mem.Translation = (~HT1_MEM_BASE_ADDR) + 1; /*~0x80000e0000000000+1*/
/*PMem Base: Limit is 0 (invalid)*/
RootBridge->PMem.Base = 0x20000000;
/*MemAbove4G Base*/
RootBridge->MemAbove4G.Base = 0x100000000;
if (Above4GFlag) {
RootBridge->AllocationAttributes |= EFI_PCI_HOST_BRIDGE_MEM64_DECODE;
RootBridge->MemAbove4G.Limit = RootBridge->MemAbove4G.Base + 0xFC00000000;
RootBridge->MemAbove4G.Translation = (~HT1_MEM_BASE_ADDR) + 1; /*~0x80000e0000000000+1* /
Writeb(PHYS_TO_UNCACHED(0xefdfe0000a0), 0x1); /* Set the flag for ACPI to open the QWor dMemory */
}
/*PMemAbove4G Base: Limit is 0 (invalid)*/
RootBridge->PMemAbove4G.Base = 0x100000000;
/*Segment*/
RootBridge->Segment = 0;
/*DevicePath*/
RootBridge->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[0][0];
break;
case 1: //Offset 7A
/*Bus Base*/
RootBridge->Bus.Base = 0;
RootBridge->Bus.Limit = 255;
/*Io Base*/
RootBridge->Io.Base = 0x20000;
RootBridge->Io.Limit = RootBridge->Io.Base + 0x2000000;
//RootBridge->Io.Translation = 0x7fffa10204000000;
/*Mem Base*/
RootBridge->Mem.Base = 0x20000000;
RootBridge->Mem.Limit = RootBridge->Mem.Base + 0x60000000;
#if defined(LOONGSON_3C5000) && defined (FLAT_MODE)
RootBridge->Mem.Translation = (~(HT1_MEM_BASE_ADDR | (1ULL << NODE_OFFSET))) + 1; /*~0x80 001e0000000000+1*/
#else
RootBridge->Mem.Translation = (~(HT1_MEM_BASE_ADDR | (5ULL << NODE_OFFSET))) + 1; /*~0x80 005e0000000000+1*/
ResourceAssigned: 控制资源是否需要分配->控制是否安装gEfiPciHostBridgeResourceAllocationProtocolGuid->控制PCIE是否枚举;
ResourceAssigned 控制是否注册回掉函数(Hostbridge->ResAlloc)供PciEnumerator使用;
安装每个Rootbridge的设备路径;
///
/// Provides the basic interfaces to abstract a PCI host bridge resource allocation.
///
struct _EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL {
///
/// The notification from the PCI bus enumerator that it is about to enter
/// a certain phase during the enumeration process.
///
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_NOTIFY_PHASE NotifyPhase;
///
/// Retrieves the device handle for the next PCI root bridge that is produced by the
/// host bridge to which this instance of the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is attached.
///
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_NEXT_ROOT_BRIDGE GetNextRootBridge;
///
/// Retrieves the allocation-related attributes of a PCI root bridge.
///
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_ATTRIBUTES GetAllocAttributes;
///
/// Sets up a PCI root bridge for bus enumeration.
///
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_START_BUS_ENUMERATION StartBusEnumeration;
///
/// Sets up the PCI root bridge so that it decodes a specific range of bus numbers.
///
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_SET_BUS_NUMBERS SetBusNumbers;
///
/// Submits the resource requirements for the specified PCI root bridge.
///
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_SUBMIT_RESOURCES SubmitResources;
///
/// Returns the proposed resource assignment for the specified PCI root bridges.
///
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_PROPOSED_RESOURCES GetProposedResources;
///
/// Provides hooks from the PCI bus driver to every PCI controller
/// (device/function) at various stages of the PCI enumeration process that
/// allow the host bridge driver to preinitialize individual PCI controllers
/// before enumeration.
///
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_PREPROCESS_CONTROLLER PreprocessController;
};
///
/// Provides the basic Memory, I/O, PCI configuration, and DMA interfaces that are
/// used to abstract accesses to PCI controllers behind a PCI Root Bridge Controller.
///
struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL {
///
/// The EFI_HANDLE of the PCI Host Bridge of which this PCI Root Bridge is a member.
///
EFI_HANDLE ParentHandle;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM PollMem;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM PollIo;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Mem;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Io;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Pci;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_COPY_MEM CopyMem;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_MAP Map;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_UNMAP Unmap;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FREE_BUFFER FreeBuffer;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FLUSH Flush;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GET_ATTRIBUTES GetAttributes;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_SET_ATTRIBUTES SetAttributes;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_CONFIGURATION Configuration;
///
/// The segment number that this PCI root bridge resides.
///
UINT32 SegmentNumber;
};
一个Hostbridge包含多个Rootbridge; HostBridge有其分配机制,RootBridge有其资源信息以及访问接口;
以segment🚌device:func为: 0:0:15:0为例: 配置空间访问地址: 0xefdfe000000 | (15<<11);
Bar_0x10存储控制器基地址(站在主控7A桥片角度来看)例: 0x40000000;
HOST_ADDRESS: 站在CPU视角,Gcd维护的地址为: 0x80000e0040000000;
DEVICE_ADDRESS: 站在桥片7A视角, 写入ProgramBar内的数据为 0x40000000;
关于配置空间访问请查看章节Pci中segment的实现-LoongArch
关于GCD相关介绍请查看章节UEFI-GCD
Best Wishes