• 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;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    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));
            }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    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*/                                                                      
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    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;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    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;
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    一个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

  • 相关阅读:
    程序设计思路-球连球组成的群
    SSM学习
    python 基础之垃圾回收机制
    JS-事件委托-阻止事件冒泡和阻止默认行为-滚动事件-加载事件-元素尺寸位置
    32 | 未来之路:HTTP/3展望
    大数据集群(Hadoop生态)安装部署
    请求传参.
    共识算法 Raft
    使用tc命令模拟linux网络延迟环境
    虚幻4学习笔记(13)用户UI 交互动画、制作2D UI、制作3D UI
  • 原文地址:https://blog.csdn.net/weixin_45384176/article/details/126849021