UEFI-PciHostBridge

UEFI-PciHostBridge

简介

PciHostBridge: 提供PCI配置空间,IO,MEM空间访问接口以及统一维护平台相关的PCI资源,提供gEfiPciHostBridgeResourceAllocationProtocolGuid,创建RootBridge等为PciBusDxe提供服务;

PciHostBridgeGetRootBridges

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

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));
        }

PciHostBridgeLib(平台主桥相关支撑)

在目前龙芯虚拟地址平台下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

ResourceAssigned: 控制资源是否需要分配->控制是否安装gEfiPciHostBridgeResourceAllocationProtocolGuid->控制PCIE是否枚举;
ResourceAssigned 控制是否注册回掉函数(Hostbridge->ResAlloc)供PciEnumerator使用;
安装每个Rootbridge的设备路径;

ResAlloc

///
/// 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;
};

RootBridgeIo(RootBridge->RootBridgeIo)

///
/// 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有其资源信息以及访问接口;

(TO_HOST_ADDRESS)&&(TO_DEVICE_ADDRESS)

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

来杯清咖_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值