--- /dev/null
+/** @file\r
+\r
+ Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation.\r
+\r
+Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PciHostBridge.h"\r
+#include "PciRootBridge.h"\r
+#include "PciHostResource.h"\r
+\r
+\r
+EFI_METRONOME_ARCH_PROTOCOL *mMetronome;\r
+EFI_CPU_IO2_PROTOCOL *mCpuIo;\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mAcpiAddressSpaceTypeStr[] = {\r
+ L"Mem", L"I/O", L"Bus"\r
+};\r
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mPciResourceTypeStr[] = {\r
+ L"I/O", L"Mem", L"PMem", L"Mem64", L"PMem64", L"Bus"\r
+};\r
+\r
+/**\r
+\r
+ Entry point of this driver.\r
+\r
+ @param ImageHandle Image handle of this driver.\r
+ @param SystemTable Pointer to standard EFI system table.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_DEVICE_ERROR Fail to install PCI_ROOT_BRIDGE_IO protocol.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializePciHostBridge (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ PCI_ROOT_BRIDGE *RootBridges;\r
+ UINTN RootBridgeCount;\r
+ UINTN Index;\r
+ PCI_ROOT_BRIDGE_APERTURE *MemApertures[4];\r
+ UINTN MemApertureIndex;\r
+\r
+ RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);\r
+ if ((RootBridges == NULL) || (RootBridgeCount == 0)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **) &mMetronome);\r
+ ASSERT_EFI_ERROR (Status);\r
+ Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **) &mCpuIo);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Most systems in the world including complex servers have only one Host Bridge.\r
+ //\r
+ HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));\r
+ ASSERT (HostBridge != NULL);\r
+\r
+ HostBridge->Signature = PCI_HOST_BRIDGE_SIGNATURE;\r
+ HostBridge->CanRestarted = TRUE;\r
+ InitializeListHead (&HostBridge->RootBridges);\r
+\r
+ HostBridge->ResAlloc.NotifyPhase = NotifyPhase;\r
+ HostBridge->ResAlloc.GetNextRootBridge = GetNextRootBridge;\r
+ HostBridge->ResAlloc.GetAllocAttributes = GetAttributes;\r
+ HostBridge->ResAlloc.StartBusEnumeration = StartBusEnumeration;\r
+ HostBridge->ResAlloc.SetBusNumbers = SetBusNumbers;\r
+ HostBridge->ResAlloc.SubmitResources = SubmitResources;\r
+ HostBridge->ResAlloc.GetProposedResources = GetProposedResources;\r
+ HostBridge->ResAlloc.PreprocessController = PreprocessController;\r
+\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &HostBridge->Handle,\r
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (HostBridge);\r
+ PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Create Root Bridge Device Handle in this Host Bridge\r
+ //\r
+ for (Index = 0; Index < RootBridgeCount; Index++) {\r
+ //\r
+ // Create Root Bridge Handle Instance\r
+ //\r
+ RootBridge = CreateRootBridge (&RootBridges[Index], HostBridge->Handle);\r
+ ASSERT (RootBridge != NULL);\r
+ if (RootBridge == NULL) {\r
+ continue;\r
+ }\r
+\r
+ if (RootBridges[Index].Io.Limit > RootBridges[Index].Io.Base) {\r
+ Status = gDS->AddIoSpace (\r
+ EfiGcdIoTypeIo,\r
+ RootBridges[Index].Io.Base,\r
+ RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ //\r
+ // Add all the Mem/PMem aperture to GCD\r
+ // Mem/PMem shouldn't overlap with each other\r
+ // Root bridge which needs to combine MEM and PMEM should only report\r
+ // the MEM aperture in Mem\r
+ //\r
+ MemApertures[0] = &RootBridges[Index].Mem;\r
+ MemApertures[1] = &RootBridges[Index].MemAbove4G;\r
+ MemApertures[2] = &RootBridges[Index].PMem;\r
+ MemApertures[3] = &RootBridges[Index].PMemAbove4G;\r
+\r
+ for (MemApertureIndex = 0; MemApertureIndex < sizeof (MemApertures) / sizeof (MemApertures[0]); MemApertureIndex++) {\r
+ if (MemApertures[MemApertureIndex]->Limit > MemApertures[MemApertureIndex]->Base) {\r
+ Status = gDS->AddMemorySpace (\r
+ EfiGcdMemoryTypeMemoryMappedIo,\r
+ MemApertures[MemApertureIndex]->Base,\r
+ MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,\r
+ EFI_MEMORY_UC\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ Status = gDS->SetMemorySpaceAttributes (\r
+ MemApertures[MemApertureIndex]->Base,\r
+ MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,\r
+ EFI_MEMORY_UC\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ }\r
+ //\r
+ // Insert Root Bridge Handle Instance\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &RootBridge->Handle,\r
+ &gEfiDevicePathProtocolGuid, RootBridge->DevicePath,\r
+ &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->RootBridgeIo,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);\r
+ }\r
+ PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This routine constructs the resource descriptors for all root bridges and call PciHostBridgeResourceConflict().\r
+\r
+ @param HostBridge The Host Bridge Instance where the resource adjustment happens.\r
+**/\r
+VOID\r
+ResourceConflict (\r
+ IN PCI_HOST_BRIDGE_INSTANCE *HostBridge\r
+ )\r
+{\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+ EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ LIST_ENTRY *Link;\r
+ UINTN RootBridgeCount;\r
+ PCI_RESOURCE_TYPE Index;\r
+ PCI_RES_NODE *ResAllocNode;\r
+\r
+ RootBridgeCount = 0;\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridgeCount++;\r
+ }\r
+\r
+ Resources = AllocatePool (\r
+ RootBridgeCount * (TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)) +\r
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
+ );\r
+ ASSERT (Resources != NULL);\r
+\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges), Descriptor = Resources\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ for (Index = TypeIo; Index < TypeMax; Index++) {\r
+ ResAllocNode = &RootBridge->ResAllocNode[Index];\r
+\r
+ Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+ Descriptor->AddrRangeMin = ResAllocNode->Base;\r
+ Descriptor->AddrRangeMax = ResAllocNode->Alignment;\r
+ Descriptor->AddrLen = ResAllocNode->Length;\r
+ switch (ResAllocNode->Type) {\r
+\r
+ case TypeIo:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
+ break;\r
+\r
+ case TypePMem32:\r
+ Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+ case TypeMem32:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ Descriptor->AddrSpaceGranularity = 32;\r
+ break;\r
+\r
+ case TypePMem64:\r
+ Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+ case TypeMem64:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ Descriptor->AddrSpaceGranularity = 64;\r
+ break;\r
+\r
+ case TypeBus:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ Descriptor++;\r
+ }\r
+ //\r
+ // Terminate the root bridge resources.\r
+ //\r
+ End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;\r
+ End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+ End->Checksum = 0x0;\r
+\r
+ Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (End + 1);\r
+ }\r
+ //\r
+ // Terminate the host bridge resources.\r
+ //\r
+ End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;\r
+ End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+ End->Checksum = 0x0;\r
+\r
+ DEBUG ((DEBUG_ERROR, "Call PciHostBridgeResourceConflict().\n"));\r
+ PciHostBridgeResourceConflict (HostBridge->Handle, Resources);\r
+ FreePool (Resources);\r
+}\r
+\r
+UINT64\r
+AllocateResource (\r
+ BOOLEAN Mmio,\r
+ UINT64 Length,\r
+ UINTN BitsOfAlignment,\r
+ UINT64 BaseAddress,\r
+ UINT64 Limit\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ if (BaseAddress < Limit) {\r
+ //\r
+ // Have to make sure Aligment is handled since we are doing direct address allocation\r
+ //\r
+ BaseAddress = ALIGN_VALUE (BaseAddress, LShiftU64 (1, BitsOfAlignment));\r
+\r
+ while (BaseAddress + Length <= Limit + 1) {\r
+ if (Mmio) {\r
+ Status = gDS->AllocateMemorySpace (\r
+ EfiGcdAllocateAddress,\r
+ EfiGcdMemoryTypeMemoryMappedIo,\r
+ BitsOfAlignment,\r
+ Length,\r
+ &BaseAddress,\r
+ gImageHandle,\r
+ NULL\r
+ );\r
+ } else {\r
+ Status = gDS->AllocateIoSpace (\r
+ EfiGcdAllocateAddress,\r
+ EfiGcdIoTypeIo,\r
+ BitsOfAlignment,\r
+ Length,\r
+ &BaseAddress,\r
+ gImageHandle,\r
+ NULL\r
+ );\r
+ }\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ return BaseAddress;\r
+ }\r
+ BaseAddress += LShiftU64 (1, BitsOfAlignment);\r
+ }\r
+ }\r
+ return MAX_UINT64;\r
+}\r
+/**\r
+\r
+ Enter a certain phase of the PCI enumeration process.\r
+\r
+ @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.\r
+ @param Phase The phase during enumeration.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_INVALID_PARAMETER Wrong phase parameter passed in.\r
+ @retval EFI_NOT_READY Resources have not been submitted yet.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NotifyPhase (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase\r
+ )\r
+{\r
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ LIST_ENTRY *Link;\r
+ EFI_PHYSICAL_ADDRESS BaseAddress;\r
+ UINT64 AddrLen;\r
+ UINTN BitsOfAlignment;\r
+ UINT64 Alignment;\r
+ EFI_STATUS Status;\r
+ EFI_STATUS ReturnStatus;\r
+ PCI_RESOURCE_TYPE Index;\r
+ PCI_RESOURCE_TYPE Index1;\r
+ PCI_RESOURCE_TYPE Index2;\r
+ BOOLEAN ResNodeHandled[TypeMax];\r
+ UINT64 MaxAlignment;\r
+\r
+ HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+\r
+ switch (Phase) {\r
+ case EfiPciHostBridgeBeginEnumeration:\r
+ if (!HostBridge->CanRestarted) {\r
+ return EFI_NOT_READY;\r
+ }\r
+ //\r
+ // Reset Root Bridge\r
+ //\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ for (Index = TypeIo; Index < TypeMax; Index++) {\r
+ RootBridge->ResAllocNode[Index].Type = Index;\r
+ RootBridge->ResAllocNode[Index].Base = 0;\r
+ RootBridge->ResAllocNode[Index].Length = 0;\r
+ RootBridge->ResAllocNode[Index].Status = ResNone;\r
+\r
+ RootBridge->ResourceSubmitted = FALSE;\r
+ }\r
+ }\r
+\r
+ HostBridge->CanRestarted = TRUE;\r
+ break;\r
+\r
+ case EfiPciHostBridgeBeginBusAllocation:\r
+ //\r
+ // No specific action is required here, can perform any chipset specific programing\r
+ //\r
+ HostBridge->CanRestarted = FALSE;\r
+ break;\r
+\r
+ case EfiPciHostBridgeEndBusAllocation:\r
+ //\r
+ // No specific action is required here, can perform any chipset specific programing\r
+ //\r
+ break;\r
+\r
+ case EfiPciHostBridgeBeginResourceAllocation:\r
+ //\r
+ // No specific action is required here, can perform any chipset specific programing\r
+ //\r
+ break;\r
+\r
+ case EfiPciHostBridgeAllocateResources:\r
+ ReturnStatus = EFI_SUCCESS;\r
+\r
+ //\r
+ // Make sure the resource for all root bridges has been submitted.\r
+ //\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ if (!RootBridge->ResourceSubmitted) {\r
+ return EFI_NOT_READY;\r
+ }\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, "PciHostBridge: NotifyPhase (AllocateResources)\n"));\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ for (Index = TypeIo; Index < TypeBus; Index++) {\r
+ ResNodeHandled[Index] = FALSE;\r
+ }\r
+\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ DEBUG ((EFI_D_INFO, " RootBridge: %s\n", RootBridge->DevicePathStr));\r
+\r
+ for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {\r
+ if (RootBridge->ResAllocNode[Index1].Status == ResNone) {\r
+ ResNodeHandled[Index1] = TRUE;\r
+ } else {\r
+ //\r
+ // Allocate the resource node with max alignment at first\r
+ //\r
+ MaxAlignment = 0;\r
+ Index = TypeMax;\r
+ for (Index2 = TypeIo; Index2 < TypeBus; Index2++) {\r
+ if (ResNodeHandled[Index2]) {\r
+ continue;\r
+ }\r
+ if (MaxAlignment <= RootBridge->ResAllocNode[Index2].Alignment) {\r
+ MaxAlignment = RootBridge->ResAllocNode[Index2].Alignment;\r
+ Index = Index2;\r
+ }\r
+ }\r
+\r
+ ASSERT (Index < TypeMax);\r
+ ResNodeHandled[Index] = TRUE;\r
+ AddrLen = RootBridge->ResAllocNode[Index].Length;\r
+ Alignment = RootBridge->ResAllocNode[Index].Alignment;\r
+ BitsOfAlignment = LowBitSet64 (Alignment + 1);\r
+ BaseAddress = MAX_UINT64;\r
+\r
+ switch (Index) {\r
+ case TypeIo:\r
+ BaseAddress = AllocateResource (\r
+ FALSE,\r
+ RootBridge->ResAllocNode[Index].Length,\r
+ MIN (15, BitsOfAlignment),\r
+ ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1),\r
+ RootBridge->Io.Limit\r
+ );\r
+ break;\r
+\r
+ case TypeMem64:\r
+ BaseAddress = AllocateResource (\r
+ TRUE,\r
+ RootBridge->ResAllocNode[Index].Length,\r
+ MIN (63, BitsOfAlignment),\r
+ ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1),\r
+ RootBridge->MemAbove4G.Limit\r
+ );\r
+ if (BaseAddress != MAX_UINT64) {\r
+ break;\r
+ }\r
+ //\r
+ // If memory above 4GB is not available, try memory below 4GB\r
+ //\r
+\r
+ case TypeMem32:\r
+ BaseAddress = AllocateResource (\r
+ TRUE,\r
+ RootBridge->ResAllocNode[Index].Length,\r
+ MIN (31, BitsOfAlignment),\r
+ ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1),\r
+ RootBridge->Mem.Limit\r
+ );\r
+ break;\r
+\r
+ case TypePMem64:\r
+ BaseAddress = AllocateResource (\r
+ TRUE,\r
+ RootBridge->ResAllocNode[Index].Length,\r
+ MIN (63, BitsOfAlignment),\r
+ ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1),\r
+ RootBridge->PMemAbove4G.Limit\r
+ );\r
+ if (BaseAddress != MAX_UINT64) {\r
+ break;\r
+ }\r
+ //\r
+ // If memory above 4GB is not available, try memory below 4GB\r
+ //\r
+ case TypePMem32:\r
+ BaseAddress = AllocateResource (\r
+ TRUE,\r
+ RootBridge->ResAllocNode[Index].Length,\r
+ MIN (31, BitsOfAlignment),\r
+ ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1),\r
+ RootBridge->PMem.Limit\r
+ );\r
+ break;\r
+\r
+ default:\r
+ ASSERT (FALSE);\r
+ break;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, " %s: Base/Length/Alignment = %lx/%lx/%lx - ",\r
+ mPciResourceTypeStr[Index], BaseAddress, RootBridge->ResAllocNode[Index].Length, Alignment));\r
+ if (BaseAddress != MAX_UINT64) {\r
+ RootBridge->ResAllocNode[Index].Base = BaseAddress;\r
+ RootBridge->ResAllocNode[Index].Status = ResAllocated;\r
+ DEBUG ((DEBUG_INFO, "Success\n"));\r
+ } else {\r
+ ReturnStatus = EFI_OUT_OF_RESOURCES;\r
+ DEBUG ((DEBUG_ERROR, "Out Of Resource!\n"));\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (ReturnStatus == EFI_OUT_OF_RESOURCES) {\r
+ ResourceConflict (HostBridge);\r
+ }\r
+\r
+ //\r
+ // Set resource to zero for nodes where allocation fails\r
+ //\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ for (Index = TypeIo; Index < TypeBus; Index++) {\r
+ if (RootBridge->ResAllocNode[Index].Status != ResAllocated) {\r
+ RootBridge->ResAllocNode[Index].Length = 0;\r
+ }\r
+ }\r
+ }\r
+ return ReturnStatus;\r
+\r
+ case EfiPciHostBridgeSetResources:\r
+ //\r
+ // HostBridgeInstance->CanRestarted = FALSE;\r
+ //\r
+ break;\r
+\r
+ case EfiPciHostBridgeFreeResources:\r
+ //\r
+ // HostBridgeInstance->CanRestarted = FALSE;\r
+ //\r
+ ReturnStatus = EFI_SUCCESS;\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ for (Index = TypeIo; Index < TypeBus; Index++) {\r
+ if (RootBridge->ResAllocNode[Index].Status == ResAllocated) {\r
+ switch (Index) {\r
+ case TypeIo:\r
+ Status = gDS->FreeIoSpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);\r
+ if (EFI_ERROR (Status)) {\r
+ ReturnStatus = Status;\r
+ }\r
+ break;\r
+\r
+ case TypeMem32:\r
+ case TypePMem32:\r
+ case TypeMem64:\r
+ case TypePMem64:\r
+ Status = gDS->FreeMemorySpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);\r
+ if (EFI_ERROR (Status)) {\r
+ ReturnStatus = Status;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ ASSERT (FALSE);\r
+ break;\r
+ }\r
+\r
+ RootBridge->ResAllocNode[Index].Type = Index;\r
+ RootBridge->ResAllocNode[Index].Base = 0;\r
+ RootBridge->ResAllocNode[Index].Length = 0;\r
+ RootBridge->ResAllocNode[Index].Status = ResNone;\r
+ }\r
+ }\r
+\r
+ RootBridge->ResourceSubmitted = FALSE;\r
+ }\r
+\r
+ HostBridge->CanRestarted = TRUE;\r
+ return ReturnStatus;\r
+\r
+ case EfiPciHostBridgeEndResourceAllocation:\r
+ //\r
+ // The resource allocation phase is completed. No specific action is required\r
+ // here. This notification can be used to perform any chipset specific programming.\r
+ //\r
+ break;\r
+\r
+ case EfiPciHostBridgeEndEnumeration:\r
+ //\r
+ // The Host Bridge Enumeration is completed. No specific action is required here.\r
+ // This notification can be used to perform any chipset specific programming.\r
+ //\r
+ break;\r
+\r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+ Return the device handle of the next PCI root bridge that is associated with\r
+ this Host Bridge.\r
+\r
+ @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+ @param RootBridgeHandle Returns the device handle of the next PCI Root Bridge.\r
+ On input, it holds the RootBridgeHandle returned by the most\r
+ recent call to GetNextRootBridge().The handle for the first\r
+ PCI Root Bridge is returned if RootBridgeHandle is NULL on input.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_NOT_FOUND Next PCI root bridge not found.\r
+ @retval EFI_INVALID_PARAMETER Wrong parameter passed in.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetNextRootBridge (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN OUT EFI_HANDLE *RootBridgeHandle\r
+ )\r
+{\r
+ BOOLEAN ReturnNext;\r
+ LIST_ENTRY *Link;\r
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+\r
+ if (RootBridgeHandle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+ ReturnNext = (BOOLEAN) (*RootBridgeHandle == NULL);\r
+\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ if (ReturnNext) {\r
+ *RootBridgeHandle = RootBridge->Handle;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ ReturnNext = (BOOLEAN) (*RootBridgeHandle == RootBridge->Handle);\r
+ }\r
+\r
+ if (ReturnNext) {\r
+ ASSERT (IsNull (&HostBridge->RootBridges, Link));\r
+ return EFI_NOT_FOUND;\r
+ } else {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ Returns the attributes of a PCI Root Bridge.\r
+\r
+ @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+ @param RootBridgeHandle The device handle of the PCI Root Bridge\r
+ that the caller is interested in.\r
+ @param Attributes The pointer to attributes of the PCI Root Bridge.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_INVALID_PARAMETER Attributes parameter passed in is NULL or\r
+ RootBridgeHandle is not an EFI_HANDLE\r
+ that was returned on a previous call to\r
+ GetNextRootBridge().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetAttributes (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ OUT UINT64 *Attributes\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+\r
+ if (Attributes == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ if (RootBridgeHandle == RootBridge->Handle) {\r
+ *Attributes = RootBridge->AllocationAttributes;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+\r
+ This is the request from the PCI enumerator to set up\r
+ the specified PCI Root Bridge for bus enumeration process.\r
+\r
+ @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+ @param RootBridgeHandle The PCI Root Bridge to be set up.\r
+ @param Configuration Pointer to the pointer to the PCI bus resource descriptor.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.\r
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+StartBusEnumeration (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ OUT VOID **Configuration\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+ EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
+\r
+ if (Configuration == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ if (RootBridgeHandle == RootBridge->Handle) {\r
+ *Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
+ if (*Configuration == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) *Configuration;\r
+ Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
+ Descriptor->GenFlag = 0;\r
+ Descriptor->SpecificFlag = 0;\r
+ Descriptor->AddrSpaceGranularity = 0;\r
+ Descriptor->AddrRangeMin = RootBridge->Bus.Base;\r
+ Descriptor->AddrRangeMax = 0;\r
+ Descriptor->AddrTranslationOffset = 0;\r
+ Descriptor->AddrLen = RootBridge->Bus.Limit - RootBridge->Bus.Base + 1;\r
+\r
+ End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);\r
+ End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+ End->Checksum = 0x0;\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+\r
+ This function programs the PCI Root Bridge hardware so that\r
+ it decodes the specified PCI bus range.\r
+\r
+ @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+ @param RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed.\r
+ @param Configuration The pointer to the PCI bus resource descriptor.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_INVALID_PARAMETER Wrong parameters passed in.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetBusNumbers (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ IN VOID *Configuration\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+ EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
+ UINTN BusStart;\r
+ UINTN BusEnd;\r
+ UINTN BusLen;\r
+\r
+ if (Configuration == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
+ End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);\r
+\r
+ //\r
+ // Check the Configuration is valid\r
+ //\r
+ if ((Descriptor->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) ||\r
+ (Descriptor->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) ||\r
+ (End->Desc != ACPI_END_TAG_DESCRIPTOR)\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ if (RootBridgeHandle == RootBridge->Handle) {\r
+ BusStart = (UINTN) Descriptor->AddrRangeMin;\r
+ BusLen = (UINTN) Descriptor->AddrLen;\r
+ BusEnd = BusStart + BusLen - 1;\r
+\r
+ if (Descriptor->AddrLen == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((Descriptor->AddrRangeMin < RootBridge->Bus.Base) ||\r
+ (Descriptor->AddrRangeMin + Descriptor->AddrLen - 1 > RootBridge->Bus.Limit)\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Update the Bus Range\r
+ //\r
+ RootBridge->ResAllocNode[TypeBus].Base = Descriptor->AddrRangeMin;\r
+ RootBridge->ResAllocNode[TypeBus].Length = Descriptor->AddrLen;\r
+ RootBridge->ResAllocNode[TypeBus].Status = ResAllocated;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+\r
+ Submits the I/O and memory resource requirements for the specified PCI Root Bridge.\r
+\r
+ @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+ @param RootBridgeHandle The PCI Root Bridge whose I/O and memory resource requirements.\r
+ are being submitted.\r
+ @param Configuration The pointer to the PCI I/O and PCI memory resource descriptor.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_INVALID_PARAMETER Wrong parameters passed in.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SubmitResources (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ IN VOID *Configuration\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+ PCI_RESOURCE_TYPE Type;\r
+\r
+ //\r
+ // Check the input parameter: Configuration\r
+ //\r
+ if (Configuration == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ if (RootBridgeHandle == RootBridge->Handle) {\r
+ DEBUG ((EFI_D_INFO, "PciHostBridge: SubmitResources for %s\n", RootBridge->DevicePathStr));\r
+ //\r
+ // Check the resource descriptors.\r
+ // If the Configuration includes one or more invalid resource descriptors, all the resource\r
+ // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.\r
+ //\r
+ for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {\r
+ if (Descriptor->ResType > ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, " %s: Granularity/SpecificFlag = %ld / %02x%s\n",\r
+ mAcpiAddressSpaceTypeStr[Descriptor->ResType], Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,\r
+ (Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0 ? L" (Prefetchable)" : L""\r
+ ));\r
+ DEBUG ((EFI_D_INFO, " Length/Alignment = 0x%lx / 0x%lx\n", Descriptor->AddrLen, Descriptor->AddrRangeMax));\r
+ switch (Descriptor->ResType) {\r
+ case ACPI_ADDRESS_SPACE_TYPE_MEM:\r
+ if (Descriptor->AddrSpaceGranularity != 32 && Descriptor->AddrSpaceGranularity != 64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (Descriptor->AddrSpaceGranularity == 32 && Descriptor->AddrLen >= SIZE_4GB) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // If the PCI root bridge does not support separate windows for nonprefetchable and\r
+ // prefetchable memory, then the PCI bus driver needs to include requests for\r
+ // prefetchable memory in the nonprefetchable memory pool.\r
+ //\r
+ if (((RootBridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) &&\r
+ ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0)\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ case ACPI_ADDRESS_SPACE_TYPE_IO:\r
+ //\r
+ // Check aligment, it should be of the form 2^n-1\r
+ //\r
+ if (GetPowerOfTwo64 (Descriptor->AddrRangeMax + 1) != (Descriptor->AddrRangeMax + 1)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+ default:\r
+ ASSERT (FALSE);\r
+ break;\r
+ }\r
+ }\r
+ if (Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {\r
+ if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
+ if (Descriptor->AddrSpaceGranularity == 32) {\r
+ if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {\r
+ Type = TypePMem32;\r
+ } else {\r
+ Type = TypeMem32;\r
+ }\r
+ } else {\r
+ ASSERT (Descriptor->AddrSpaceGranularity == 64);\r
+ if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {\r
+ Type = TypePMem64;\r
+ } else {\r
+ Type = TypeMem64;\r
+ }\r
+ }\r
+ } else {\r
+ ASSERT (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO);\r
+ Type = TypeIo;\r
+ }\r
+ RootBridge->ResAllocNode[Type].Length = Descriptor->AddrLen;\r
+ RootBridge->ResAllocNode[Type].Alignment = Descriptor->AddrRangeMax;\r
+ RootBridge->ResAllocNode[Type].Status = ResSubmitted;\r
+ }\r
+ RootBridge->ResourceSubmitted = TRUE;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+\r
+ This function returns the proposed resource settings for the specified\r
+ PCI Root Bridge.\r
+\r
+ @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+ @param RootBridgeHandle The PCI Root Bridge handle.\r
+ @param Configuration The pointer to the pointer to the PCI I/O\r
+ and memory resource descriptor.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.\r
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetProposedResources (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ OUT VOID **Configuration\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ UINTN Index;\r
+ UINTN Number;\r
+ VOID *Buffer;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+ EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
+ UINT64 ResStatus;\r
+\r
+ HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ if (RootBridgeHandle == RootBridge->Handle) {\r
+ for (Index = 0, Number = 0; Index < TypeBus; Index++) {\r
+ if (RootBridge->ResAllocNode[Index].Status != ResNone) {\r
+ Number++;\r
+ }\r
+ }\r
+\r
+ Buffer = AllocateZeroPool (Number * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
+ if (Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Buffer;\r
+ for (Index = 0; Index < TypeBus; Index++) {\r
+ ResStatus = RootBridge->ResAllocNode[Index].Status;\r
+ if (ResStatus != ResNone) {\r
+ Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;;\r
+ Descriptor->GenFlag = 0;\r
+ Descriptor->AddrRangeMin = RootBridge->ResAllocNode[Index].Base;\r
+ Descriptor->AddrRangeMax = 0;\r
+ Descriptor->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : PCI_RESOURCE_LESS;\r
+ Descriptor->AddrLen = RootBridge->ResAllocNode[Index].Length;\r
+\r
+ switch (Index) {\r
+\r
+ case TypeIo:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
+ break;\r
+\r
+ case TypePMem32:\r
+ Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+ case TypeMem32:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ Descriptor->AddrSpaceGranularity = 32;\r
+ break;\r
+\r
+ case TypePMem64:\r
+ Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+ case TypeMem64:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ Descriptor->AddrSpaceGranularity = 64;\r
+ break;\r
+ }\r
+\r
+ Descriptor++;\r
+ }\r
+ }\r
+ End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;\r
+ End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+ End->Checksum = 0;\r
+\r
+ *Configuration = Buffer;\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+\r
+ This function is called for all the PCI controllers that the PCI\r
+ bus driver finds. Can be used to Preprogram the controller.\r
+\r
+ @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+ @param RootBridgeHandle The PCI Root Bridge handle.\r
+ @param PciAddress Address of the controller on the PCI bus.\r
+ @param Phase The Phase during resource allocation.\r
+\r
+ @retval EFI_SUCCESS Succeed.\r
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PreprocessController (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,\r
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+\r
+ if ((UINT32) Phase > EfiPciBeforeResourceCollection) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
+ for (Link = GetFirstNode (&HostBridge->RootBridges)\r
+ ; !IsNull (&HostBridge->RootBridges, Link)\r
+ ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
+ ) {\r
+ RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
+ if (RootBridgeHandle == RootBridge->Handle) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
--- /dev/null
+/** @file\r
+\r
+ The Header file of the Pci Host Bridge Driver.\r
+\r
+Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _PCI_HOST_BRIDGE_H_\r
+#define _PCI_HOST_BRIDGE_H_\r
+\r
+\r
+#include <PiDxe.h>\r
+#include <IndustryStandard/Acpi.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PciHostBridgeLib.h>\r
+#include <Protocol/PciHostBridgeResourceAllocation.h>\r
+\r
+#include "PciRootBridge.h"\r
+\r
+#define PCI_HOST_BRIDGE_SIGNATURE SIGNATURE_32 ('p', 'h', 'b', 'g')\r
+typedef struct {\r
+ UINTN Signature;\r
+ EFI_HANDLE Handle;\r
+ LIST_ENTRY RootBridges;\r
+ BOOLEAN CanRestarted;\r
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL ResAlloc;\r
+} PCI_HOST_BRIDGE_INSTANCE;\r
+\r
+#define PCI_HOST_BRIDGE_FROM_THIS(a) CR (a, PCI_HOST_BRIDGE_INSTANCE, ResAlloc, PCI_HOST_BRIDGE_SIGNATURE)\r
+\r
+//\r
+// Driver Entry Point\r
+//\r
+/**\r
+\r
+ Entry point of this driver.\r
+\r
+ @param ImageHandle - Image handle of this driver.\r
+ @param SystemTable - Pointer to standard EFI system table.\r
+\r
+ @retval EFI_SUCCESS - Succeed.\r
+ @retval EFI_DEVICE_ERROR - Fail to install PCI_ROOT_BRIDGE_IO protocol.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializePciHostBridge (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ );\r
+\r
+//\r
+// HostBridge Resource Allocation interface\r
+//\r
+/**\r
+\r
+ Enter a certain phase of the PCI enumeration process.\r
+\r
+ @param This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.\r
+ @param Phase - The phase during enumeration.\r
+\r
+ @retval EFI_SUCCESS - Succeed.\r
+ @retval EFI_INVALID_PARAMETER - Wrong phase parameter passed in.\r
+ @retval EFI_NOT_READY - Resources have not been submitted yet.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NotifyPhase (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase\r
+ );\r
+\r
+/**\r
+\r
+ Return the device handle of the next PCI root bridge that is associated with\r
+ this Host Bridge.\r
+\r
+ @param This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+ RootBridgeHandle - Returns the device handle of the next PCI Root Bridge.\r
+ On input, it holds the RootBridgeHandle returned by the most\r
+ recent call to GetNextRootBridge().The handle for the first\r
+ PCI Root Bridge is returned if RootBridgeHandle is NULL on input.\r
+\r
+ @retval EFI_SUCCESS - Succeed.\r
+ @retval EFI_NOT_FOUND - Next PCI root bridge not found.\r
+ @retval EFI_INVALID_PARAMETER - Wrong parameter passed in.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetNextRootBridge (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN OUT EFI_HANDLE *RootBridgeHandle\r
+ );\r
+\r
+/**\r
+\r
+ Returns the attributes of a PCI Root Bridge.\r
+\r
+ @param This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance\r
+ @param RootBridgeHandle - The device handle of the PCI Root Bridge\r
+ that the caller is interested in\r
+ @param Attributes - The pointer to attributes of the PCI Root Bridge\r
+\r
+ @retval EFI_SUCCESS - Succeed.\r
+ @retval EFI_INVALID_PARAMETER - Attributes parameter passed in is NULL or\r
+ @retval RootBridgeHandle is not an EFI_HANDLE\r
+ @retval that was returned on a previous call to\r
+ @retval GetNextRootBridge().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetAttributes (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ OUT UINT64 *Attributes\r
+ );\r
+\r
+/**\r
+\r
+ This is the request from the PCI enumerator to set up\r
+ the specified PCI Root Bridge for bus enumeration process.\r
+\r
+ @param This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+ @param RootBridgeHandle - The PCI Root Bridge to be set up.\r
+ @param Configuration - Pointer to the pointer to the PCI bus resource descriptor.\r
+\r
+ @retval EFI_SUCCESS - Succeed.\r
+ @retval EFI_OUT_OF_RESOURCES - Not enough pool to be allocated.\r
+ @retval EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+StartBusEnumeration (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ OUT VOID **Configuration\r
+ );\r
+\r
+/**\r
+\r
+ This function programs the PCI Root Bridge hardware so that\r
+ it decodes the specified PCI bus range.\r
+\r
+ @param This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+ @param RootBridgeHandle - The PCI Root Bridge whose bus range is to be programmed.\r
+ @param Configuration - The pointer to the PCI bus resource descriptor.\r
+\r
+ @retval EFI_SUCCESS - Succeed.\r
+ @retval EFI_INVALID_PARAMETER - Wrong parameters passed in.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetBusNumbers (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ IN VOID *Configuration\r
+ );\r
+\r
+/**\r
+\r
+ Submits the I/O and memory resource requirements for the specified PCI Root Bridge.\r
+\r
+ @param This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance\r
+ @param RootBridgeHandle - The PCI Root Bridge whose I/O and memory resource requirements\r
+ are being submitted\r
+ @param Configuration - The pointer to the PCI I/O and PCI memory resource descriptor\r
+\r
+ @retval EFI_SUCCESS - Succeed.\r
+ @retval EFI_INVALID_PARAMETER - Wrong parameters passed in.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SubmitResources (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ IN VOID *Configuration\r
+ );\r
+\r
+/**\r
+\r
+ This function returns the proposed resource settings for the specified\r
+ PCI Root Bridge.\r
+\r
+ @param This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+ @param RootBridgeHandle - The PCI Root Bridge handle.\r
+ @param Configuration - The pointer to the pointer to the PCI I/O\r
+ and memory resource descriptor.\r
+\r
+ @retval EFI_SUCCESS - Succeed.\r
+ @retval EFI_OUT_OF_RESOURCES - Not enough pool to be allocated.\r
+ @retval EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetProposedResources (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ OUT VOID **Configuration\r
+ );\r
+\r
+/**\r
+\r
+ This function is called for all the PCI controllers that the PCI\r
+ bus driver finds. Can be used to Preprogram the controller.\r
+\r
+ @param This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
+ @param RootBridgeHandle - The PCI Root Bridge handle.\r
+ @param PciAddress - Address of the controller on the PCI bus.\r
+ @param Phase - The Phase during resource allocation.\r
+\r
+ @retval EFI_SUCCESS - Succeed.\r
+ @retval EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PreprocessController (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,\r
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase\r
+ );\r
+\r
+/**\r
+ This routine constructs the resource descriptors for all root bridges and call PciHostBridgeResourceConflict().\r
+\r
+ @param HostBridge The Host Bridge Instance where the resource adjustment happens.\r
+**/\r
+VOID\r
+ResourceConflict (\r
+ IN PCI_HOST_BRIDGE_INSTANCE *HostBridge\r
+ );\r
+\r
+extern EFI_METRONOME_ARCH_PROTOCOL *mMetronome;\r
+extern EFI_CPU_IO2_PROTOCOL *mCpuIo;\r
+#endif\r
--- /dev/null
+## @file\r
+# Generic PCI Host Bridge driver.\r
+#\r
+# Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = PciHostBridgeDxe\r
+ FILE_GUID = 128FB770-5E79-4176-9E51-9BB268A17DD1\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ ENTRY_POINT = InitializePciHostBridge\r
+\r
+[Sources]\r
+ PciHostBridge.h\r
+ PciRootBridge.h\r
+ PciHostBridge.c\r
+ PciRootBridgeIo.c\r
+ PciHostResource.h\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+ UefiDriverEntryPoint\r
+ UefiBootServicesTableLib\r
+ DebugLib\r
+ DxeServicesTableLib\r
+ DevicePathLib\r
+ BaseMemoryLib\r
+ BaseLib\r
+ PciSegmentLib\r
+ PciHostBridgeLib\r
+\r
+[Protocols]\r
+ gEfiMetronomeArchProtocolGuid ## CONSUMES\r
+ gEfiCpuIo2ProtocolGuid ## CONSUMES\r
+ gEfiDevicePathProtocolGuid ## BY_START\r
+ gEfiPciRootBridgeIoProtocolGuid ## BY_START\r
+ gEfiPciHostBridgeResourceAllocationProtocolGuid ## BY_START\r
+\r
+[Depex]\r
+ gEfiCpuIo2ProtocolGuid AND\r
+ gEfiMetronomeArchProtocolGuid\r
--- /dev/null
+/** @file\r
+\r
+ The Header file of the Pci Host Bridge Driver.\r
+\r
+Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#ifndef _PCI_HOST_RESOURCE_H_\r
+#define _PCI_HOST_RESOURCE_H_\r
+\r
+#include <PiDxe.h>\r
+\r
+#define PCI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFE\r
+\r
+typedef enum {\r
+ TypeIo = 0,\r
+ TypeMem32,\r
+ TypePMem32,\r
+ TypeMem64,\r
+ TypePMem64,\r
+ TypeBus,\r
+ TypeMax\r
+} PCI_RESOURCE_TYPE;\r
+\r
+typedef enum {\r
+ ResNone,\r
+ ResSubmitted,\r
+ ResAllocated,\r
+ ResStatusMax\r
+} RES_STATUS;\r
+\r
+typedef struct {\r
+ PCI_RESOURCE_TYPE Type;\r
+ UINT64 Base;\r
+ UINT64 Length;\r
+ UINT64 Alignment;\r
+ RES_STATUS Status;\r
+} PCI_RES_NODE;\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+\r
+ The PCI Root Bridge header file.\r
+\r
+Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _PCI_ROOT_BRIDGE_H_\r
+#define _PCI_ROOT_BRIDGE_H_\r
+\r
+#include <PiDxe.h>\r
+#include <IndustryStandard/Acpi.h>\r
+#include <IndustryStandard/Pci.h>\r
+\r
+//\r
+// Driver Consumed Protocol Prototypes\r
+//\r
+#include <Protocol/Metronome.h>\r
+#include <Protocol/CpuIo2.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/PciRootBridgeIo.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/PciSegmentLib.h>\r
+#include "PciHostResource.h"\r
+\r
+\r
+typedef enum {\r
+ IoOperation,\r
+ MemOperation,\r
+ PciOperation\r
+} OPERATION_TYPE;\r
+\r
+#define MAP_INFO_SIGNATURE SIGNATURE_32 ('_', 'm', 'a', 'p')\r
+typedef struct {\r
+ UINT32 Signature;\r
+ LIST_ENTRY Link;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation;\r
+ UINTN NumberOfBytes;\r
+ UINTN NumberOfPages;\r
+ EFI_PHYSICAL_ADDRESS HostAddress;\r
+ EFI_PHYSICAL_ADDRESS MappedHostAddress;\r
+} MAP_INFO;\r
+#define MAP_INFO_FROM_LINK(a) CR (a, MAP_INFO, Link, MAP_INFO_SIGNATURE)\r
+\r
+#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32 ('_', 'p', 'r', 'b')\r
+\r
+typedef struct {\r
+ UINT32 Signature;\r
+ LIST_ENTRY Link;\r
+ EFI_HANDLE Handle;\r
+ UINT64 AllocationAttributes;\r
+ UINT64 Attributes;\r
+ UINT64 Supports;\r
+ PCI_RES_NODE ResAllocNode[TypeMax];\r
+ PCI_ROOT_BRIDGE_APERTURE Bus;\r
+ PCI_ROOT_BRIDGE_APERTURE Io;\r
+ PCI_ROOT_BRIDGE_APERTURE Mem;\r
+ PCI_ROOT_BRIDGE_APERTURE PMem;\r
+ PCI_ROOT_BRIDGE_APERTURE MemAbove4G;\r
+ PCI_ROOT_BRIDGE_APERTURE PMemAbove4G;\r
+ BOOLEAN DmaAbove4G;\r
+ VOID *ConfigBuffer;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ CHAR16 *DevicePathStr;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL RootBridgeIo;\r
+\r
+ BOOLEAN ResourceSubmitted;\r
+ LIST_ENTRY Maps;\r
+} PCI_ROOT_BRIDGE_INSTANCE;\r
+\r
+#define ROOT_BRIDGE_FROM_THIS(a) CR (a, PCI_ROOT_BRIDGE_INSTANCE, RootBridgeIo, PCI_ROOT_BRIDGE_SIGNATURE)\r
+\r
+#define ROOT_BRIDGE_FROM_LINK(a) CR (a, PCI_ROOT_BRIDGE_INSTANCE, Link, PCI_ROOT_BRIDGE_SIGNATURE)\r
+\r
+/**\r
+\r
+ Construct the Pci Root Bridge Io protocol.\r
+\r
+ @param Protocol - Protocol to initialize.\r
+ @param HostBridgeHandle - Handle to the HostBridge.\r
+\r
+ @retval EFI_SUCCESS - Success.\r
+ @retval Others - Fail.\r
+\r
+**/\r
+PCI_ROOT_BRIDGE_INSTANCE *\r
+CreateRootBridge (\r
+ IN PCI_ROOT_BRIDGE *Bridge,\r
+ IN EFI_HANDLE HostBridgeHandle\r
+ );\r
+\r
+//\r
+// Protocol Member Function Prototypes\r
+//\r
+/**\r
+\r
+ Poll an address in memory mapped space until an exit condition is met\r
+ or a timeout occurs.\r
+\r
+ @param This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.\r
+ @param Width - Width of the memory operation.\r
+ @param Address - The base address of the memory operation.\r
+ @param Mask - Mask used for polling criteria.\r
+ @param Value - Comparison value used for polling exit criteria.\r
+ @param Delay - Number of 100ns units to poll.\r
+ @param Result - Pointer to the last value read from memory location.\r
+\r
+ @retval EFI_SUCCESS - Success.\r
+ @retval EFI_INVALID_PARAMETER - Invalid parameter found.\r
+ @retval EFI_TIMEOUT - Delay expired before a match occurred.\r
+ @retval EFI_OUT_OF_RESOURCES - Fail due to lack of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoPollMem (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+ )\r
+;\r
+\r
+/**\r
+\r
+ Poll an address in I/O space until an exit condition is met\r
+ or a timeout occurs.\r
+\r
+ @param This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.\r
+ @param Width - Width of I/O operation.\r
+ @param Address - The base address of the I/O operation.\r
+ @param Mask - Mask used for polling criteria.\r
+ @param Value - Comparison value used for polling exit criteria.\r
+ @param Delay - Number of 100ns units to poll.\r
+ @param Result - Pointer to the last value read from memory location.\r
+\r
+ @retval EFI_SUCCESS - Success.\r
+ @retval EFI_INVALID_PARAMETER - Invalid parameter found.\r
+ @retval EFI_TIMEOUT - Delay expired before a match occurred.\r
+ @retval EFI_OUT_OF_RESOURCES - Fail due to lack of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoPollIo (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+ )\r
+;\r
+\r
+/**\r
+\r
+ Allow read from memory mapped I/O space.\r
+\r
+ @param This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.\r
+ @param Width - The width of memory operation.\r
+ @param Address - Base address of the memory operation.\r
+ @param Count - Number of memory opeartion to perform.\r
+ @param Buffer - The destination buffer to store data.\r
+\r
+ @retval EFI_SUCCESS - Success.\r
+ @retval EFI_INVALID_PARAMETER - Invalid parameter found.\r
+ @retval EFI_OUT_OF_RESOURCES - Fail due to lack of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoMemRead (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+;\r
+\r
+/**\r
+\r
+ Allow write to memory mapped I/O space.\r
+\r
+ @param This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.\r
+ @param Width - The width of memory operation.\r
+ @param Address - Base address of the memory operation.\r
+ @param Count - Number of memory opeartion to perform.\r
+ @param Buffer - The source buffer to write data from.\r
+\r
+ @retval EFI_SUCCESS - Success.\r
+ @retval EFI_INVALID_PARAMETER - Invalid parameter found.\r
+ @retval EFI_OUT_OF_RESOURCES - Fail due to lack of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoMemWrite (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+;\r
+\r
+/**\r
+\r
+ Enable a PCI driver to read PCI controller registers in the\r
+ PCI root bridge I/O space.\r
+\r
+ @param This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL\r
+ @param Width - Signifies the width of the memory operation.\r
+ @param UserAddress - The base address of the I/O operation.\r
+ @param Count - The number of I/O operations to perform.\r
+ @param UserBuffer - The destination buffer to store the results.\r
+\r
+ @retval EFI_SUCCESS - The data was read from the PCI root bridge.\r
+ @retval EFI_INVALID_PARAMETER - Invalid parameters found.\r
+ @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of\r
+ @retval resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoIoRead (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ IN OUT VOID *UserBuffer\r
+ )\r
+;\r
+\r
+/**\r
+\r
+ Enable a PCI driver to write to PCI controller registers in the\r
+ PCI root bridge I/O space.\r
+\r
+ @param This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL\r
+ @param Width - Signifies the width of the memory operation.\r
+ @param UserAddress - The base address of the I/O operation.\r
+ @param Count - The number of I/O operations to perform.\r
+ @param UserBuffer - The source buffer to write data from.\r
+\r
+ @retval EFI_SUCCESS - The data was written to the PCI root bridge.\r
+ @retval EFI_INVALID_PARAMETER - Invalid parameters found.\r
+ @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of\r
+ @retval resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoIoWrite (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ IN OUT VOID *UserBuffer\r
+ )\r
+;\r
+\r
+/**\r
+\r
+ Copy one region of PCI root bridge memory space to be copied to\r
+ another region of PCI root bridge memory space.\r
+\r
+ @param This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.\r
+ @param Width - Signifies the width of the memory operation.\r
+ @param DestAddress - Destination address of the memory operation.\r
+ @param SrcAddress - Source address of the memory operation.\r
+ @param Count - Number of memory operations to perform.\r
+\r
+ @retval EFI_SUCCESS - The data was copied successfully.\r
+ @retval EFI_INVALID_PARAMETER - Invalid parameters found.\r
+ @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of\r
+ @retval resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoCopyMem (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 DestAddress,\r
+ IN UINT64 SrcAddress,\r
+ IN UINTN Count\r
+ )\r
+;\r
+\r
+/**\r
+\r
+ Allows read from PCI configuration space.\r
+\r
+ @param This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL\r
+ @param Width - Signifies the width of the memory operation.\r
+ @param Address - The address within the PCI configuration space\r
+ for the PCI controller.\r
+ @param Count - The number of PCI configuration operations\r
+ to perform.\r
+ @param Buffer - The destination buffer to store the results.\r
+\r
+ @retval EFI_SUCCESS - The data was read from the PCI root bridge.\r
+ @retval EFI_INVALID_PARAMETER - Invalid parameters found.\r
+ @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of\r
+ @retval resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoPciRead (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+;\r
+\r
+/**\r
+\r
+ Allows write to PCI configuration space.\r
+\r
+ @param This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL\r
+ @param Width - Signifies the width of the memory operation.\r
+ @param Address - The address within the PCI configuration space\r
+ for the PCI controller.\r
+ @param Count - The number of PCI configuration operations\r
+ to perform.\r
+ @param Buffer - The source buffer to get the results.\r
+\r
+ @retval EFI_SUCCESS - The data was written to the PCI root bridge.\r
+ @retval EFI_INVALID_PARAMETER - Invalid parameters found.\r
+ @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of\r
+ @retval resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoPciWrite (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+;\r
+\r
+/**\r
+\r
+ Provides the PCI controller-specific address needed to access\r
+ system memory for DMA.\r
+\r
+ @param This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+ @param Operation - Indicate if the bus master is going to read or write\r
+ to system memory.\r
+ @param HostAddress - The system memory address to map on the PCI controller.\r
+ @param NumberOfBytes - On input the number of bytes to map.\r
+ On output the number of bytes that were mapped.\r
+ @param DeviceAddress - The resulting map address for the bus master PCI\r
+ controller to use to access the system memory's HostAddress.\r
+ @param Mapping - The value to pass to Unmap() when the bus master DMA\r
+ operation is complete.\r
+\r
+ @retval EFI_SUCCESS - Success.\r
+ @retval EFI_INVALID_PARAMETER - Invalid parameters found.\r
+ @retval EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common\r
+ @retval buffer.\r
+ @retval EFI_DEVICE_ERROR - The System hardware could not map the requested\r
+ @retval address.\r
+ @retval EFI_OUT_OF_RESOURCES - The request could not be completed due to\r
+ @retval lack of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoMap (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,\r
+ IN VOID *HostAddress,\r
+ IN OUT UINTN *NumberOfBytes,\r
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
+ OUT VOID **Mapping\r
+ )\r
+;\r
+\r
+/**\r
+\r
+ Completes the Map() operation and releases any corresponding resources.\r
+\r
+ @param This - Pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.\r
+ Mapping - The value returned from Map() operation.\r
+\r
+ @retval EFI_SUCCESS - The range was unmapped successfully.\r
+ @retval EFI_INVALID_PARAMETER - Mapping is not a value that was returned\r
+ @retval by Map operation.\r
+ @retval EFI_DEVICE_ERROR - The data was not committed to the target\r
+ @retval system memory.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoUnmap (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN VOID *Mapping\r
+ )\r
+;\r
+\r
+/**\r
+\r
+ Allocates pages that are suitable for a common buffer mapping.\r
+\r
+ @param This - Pointer to EFI_ROOT_BRIDGE_IO_PROTOCOL instance.\r
+ @param Type - Not used and can be ignored.\r
+ @param MemoryType - Type of memory to allocate.\r
+ @param Pages - Number of pages to allocate.\r
+ @param HostAddress - Pointer to store the base system memory address\r
+ of the allocated range.\r
+ @param Attributes - Requested bit mask of attributes of the allocated\r
+ range.\r
+\r
+ @retval EFI_SUCCESS - The requested memory range were allocated.\r
+ @retval EFI_INVALID_PARAMETER - Invalid parameter found.\r
+ @retval EFI_UNSUPPORTED - Attributes is unsupported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoAllocateBuffer (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_ALLOCATE_TYPE Type,\r
+ IN EFI_MEMORY_TYPE MemoryType,\r
+ IN UINTN Pages,\r
+ OUT VOID **HostAddress,\r
+ IN UINT64 Attributes\r
+ )\r
+;\r
+\r
+/**\r
+\r
+ Free memory allocated in AllocateBuffer.\r
+\r
+ @param This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL\r
+ instance.\r
+ @param Pages - Number of pages to free.\r
+ @param HostAddress - The base system memory address of the\r
+ allocated range.\r
+\r
+ @retval EFI_SUCCESS - Requested memory pages were freed.\r
+ @retval EFI_INVALID_PARAMETER - Invalid parameter found.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoFreeBuffer (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN UINTN Pages,\r
+ OUT VOID *HostAddress\r
+ )\r
+;\r
+\r
+/**\r
+\r
+ Flushes all PCI posted write transactions from a PCI host\r
+ bridge to system memory.\r
+\r
+ @param This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.\r
+\r
+ @retval EFI_SUCCESS - PCI posted write transactions were flushed\r
+ @retval from PCI host bridge to system memory.\r
+ @retval EFI_DEVICE_ERROR - Fail due to hardware error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoFlush (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This\r
+ )\r
+;\r
+\r
+/**\r
+\r
+ Get the attributes that a PCI root bridge supports and\r
+ the attributes the PCI root bridge is currently using.\r
+\r
+ @param This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL\r
+ instance.\r
+ @param Supports - A pointer to the mask of attributes that\r
+ this PCI root bridge supports.\r
+ @param Attributes - A pointer to the mask of attributes that\r
+ this PCI root bridge is currently using.\r
+ @retval EFI_SUCCESS - Success.\r
+ @retval EFI_INVALID_PARAMETER - Invalid parameter found.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoGetAttributes (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ OUT UINT64 *Supported,\r
+ OUT UINT64 *Attributes\r
+ )\r
+;\r
+\r
+/**\r
+\r
+ Sets the attributes for a resource range on a PCI root bridge.\r
+\r
+ @param This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.\r
+ @param Attributes - The mask of attributes to set.\r
+ @param ResourceBase - Pointer to the base address of the resource range\r
+ to be modified by the attributes specified by Attributes.\r
+ @param ResourceLength - Pointer to the length of the resource range to be modified.\r
+\r
+ @retval EFI_SUCCESS - Success.\r
+ @retval EFI_INVALID_PARAMETER - Invalid parameter found.\r
+ @retval EFI_OUT_OF_RESOURCES - Not enough resources to set the attributes upon.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoSetAttributes (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN UINT64 Attributes,\r
+ IN OUT UINT64 *ResourceBase,\r
+ IN OUT UINT64 *ResourceLength\r
+ )\r
+;\r
+\r
+/**\r
+\r
+ Retrieves the current resource settings of this PCI root bridge\r
+ in the form of a set of ACPI 2.0 resource descriptor.\r
+\r
+ @param This - Pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.\r
+ @param Resources - Pointer to the ACPI 2.0 resource descriptor that\r
+ describe the current configuration of this PCI root\r
+ bridge.\r
+\r
+ @retval EFI_SUCCESS - Success.\r
+ @retval EFI_UNSUPPORTED - Current configuration of the PCI root bridge\r
+ @retval could not be retrieved.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoConfiguration (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ OUT VOID **Resources\r
+ )\r
+;\r
+\r
+\r
+extern EFI_METRONOME_ARCH_PROTOCOL *mMetronome;\r
+extern EFI_CPU_IO2_PROTOCOL *mCpuIo;\r
+#endif\r
--- /dev/null
+/** @file\r
+\r
+ PCI Root Bridge Io Protocol code.\r
+\r
+Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PciHostBridge.h"\r
+#include "PciRootBridge.h"\r
+#include "PciHostResource.h"\r
+\r
+#define NO_MAPPING (VOID *) -1\r
+\r
+//\r
+// Lookup table for increment values based on transfer widths\r
+//\r
+UINT8 mInStride[] = {\r
+ 1, // EfiPciWidthUint8\r
+ 2, // EfiPciWidthUint16\r
+ 4, // EfiPciWidthUint32\r
+ 8, // EfiPciWidthUint64\r
+ 0, // EfiPciWidthFifoUint8\r
+ 0, // EfiPciWidthFifoUint16\r
+ 0, // EfiPciWidthFifoUint32\r
+ 0, // EfiPciWidthFifoUint64\r
+ 1, // EfiPciWidthFillUint8\r
+ 2, // EfiPciWidthFillUint16\r
+ 4, // EfiPciWidthFillUint32\r
+ 8 // EfiPciWidthFillUint64\r
+};\r
+\r
+//\r
+// Lookup table for increment values based on transfer widths\r
+//\r
+UINT8 mOutStride[] = {\r
+ 1, // EfiPciWidthUint8\r
+ 2, // EfiPciWidthUint16\r
+ 4, // EfiPciWidthUint32\r
+ 8, // EfiPciWidthUint64\r
+ 1, // EfiPciWidthFifoUint8\r
+ 2, // EfiPciWidthFifoUint16\r
+ 4, // EfiPciWidthFifoUint32\r
+ 8, // EfiPciWidthFifoUint64\r
+ 0, // EfiPciWidthFillUint8\r
+ 0, // EfiPciWidthFillUint16\r
+ 0, // EfiPciWidthFillUint32\r
+ 0 // EfiPciWidthFillUint64\r
+};\r
+\r
+/**\r
+ Construct the Pci Root Bridge instance.\r
+\r
+ @param Bridge The root bridge instance.\r
+ @param HostBridgeHandle Handle to the HostBridge.\r
+\r
+ @return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created\r
+ or NULL if creation fails.\r
+**/\r
+PCI_ROOT_BRIDGE_INSTANCE *\r
+CreateRootBridge (\r
+ IN PCI_ROOT_BRIDGE *Bridge,\r
+ IN EFI_HANDLE HostBridgeHandle\r
+ )\r
+{\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ PCI_RESOURCE_TYPE Index;\r
+ CHAR16 *DevicePathStr;\r
+\r
+ DevicePathStr = NULL;\r
+\r
+ DEBUG ((EFI_D_INFO, "RootBridge: "));\r
+ DEBUG ((EFI_D_INFO, "%s\n", DevicePathStr = ConvertDevicePathToText (Bridge->DevicePath, FALSE, FALSE)));\r
+ DEBUG ((EFI_D_INFO, "Support/Attr: %lx / %lx\n", Bridge->Supports, Bridge->Attributes));\r
+ DEBUG ((EFI_D_INFO, " DmaAbove4G: %s\n", Bridge->DmaAbove4G ? L"Yes" : L"No"));\r
+ DEBUG ((EFI_D_INFO, " AllocAttr: %lx (%s%s)\n", Bridge->AllocationAttributes,\r
+ (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0 ? L"CombineMemPMem " : L"",\r
+ (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0 ? L"Mem64Decode" : L""\r
+ ));\r
+ DEBUG ((EFI_D_INFO, " Bus: %lx - %lx\n", Bridge->Bus.Base, Bridge->Bus.Limit));\r
+ DEBUG ((EFI_D_INFO, " Io: %lx - %lx\n", Bridge->Io.Base, Bridge->Io.Limit));\r
+ DEBUG ((EFI_D_INFO, " Mem: %lx - %lx\n", Bridge->Mem.Base, Bridge->Mem.Limit));\r
+ DEBUG ((EFI_D_INFO, " MemAbove4G: %lx - %lx\n", Bridge->MemAbove4G.Base, Bridge->MemAbove4G.Limit));\r
+ DEBUG ((EFI_D_INFO, " PMem: %lx - %lx\n", Bridge->PMem.Base, Bridge->PMem.Limit));\r
+ DEBUG ((EFI_D_INFO, " PMemAbove4G: %lx - %lx\n", Bridge->PMemAbove4G.Base, Bridge->PMemAbove4G.Limit));\r
+\r
+ //\r
+ // Make sure Mem and MemAbove4G apertures are valid\r
+ //\r
+ if (Bridge->Mem.Base < Bridge->Mem.Limit) {\r
+ ASSERT (Bridge->Mem.Limit < SIZE_4GB);\r
+ if (Bridge->Mem.Limit >= SIZE_4GB) {\r
+ return NULL;\r
+ }\r
+ }\r
+ if (Bridge->MemAbove4G.Base < Bridge->MemAbove4G.Limit) {\r
+ ASSERT (Bridge->MemAbove4G.Base >= SIZE_4GB);\r
+ if (Bridge->MemAbove4G.Base < SIZE_4GB) {\r
+ return NULL;\r
+ }\r
+ }\r
+ if (Bridge->PMem.Base < Bridge->PMem.Limit) {\r
+ ASSERT (Bridge->PMem.Limit < SIZE_4GB);\r
+ if (Bridge->PMem.Limit >= SIZE_4GB) {\r
+ return NULL;\r
+ }\r
+ }\r
+ if (Bridge->PMemAbove4G.Base < Bridge->PMemAbove4G.Limit) {\r
+ ASSERT (Bridge->PMemAbove4G.Base >= SIZE_4GB);\r
+ if (Bridge->PMemAbove4G.Base < SIZE_4GB) {\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) {\r
+ //\r
+ // If this bit is set, then the PCI Root Bridge does not\r
+ // support separate windows for Non-prefetchable and Prefetchable\r
+ // memory.\r
+ //\r
+ ASSERT (Bridge->PMem.Base >= Bridge->PMem.Limit);\r
+ ASSERT (Bridge->PMemAbove4G.Base >= Bridge->PMemAbove4G.Limit);\r
+ if ((Bridge->PMem.Base < Bridge->PMem.Limit) ||\r
+ (Bridge->PMemAbove4G.Base < Bridge->PMemAbove4G.Limit)\r
+ ) {\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) == 0) {\r
+ //\r
+ // If this bit is not set, then the PCI Root Bridge does not support\r
+ // 64 bit memory windows.\r
+ //\r
+ ASSERT (Bridge->MemAbove4G.Base >= Bridge->MemAbove4G.Limit);\r
+ ASSERT (Bridge->PMemAbove4G.Base >= Bridge->PMemAbove4G.Limit);\r
+ if ((Bridge->MemAbove4G.Base < Bridge->MemAbove4G.Limit) ||\r
+ (Bridge->PMemAbove4G.Base < Bridge->PMemAbove4G.Limit)\r
+ ) {\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ RootBridge = AllocateZeroPool (sizeof (PCI_ROOT_BRIDGE_INSTANCE));\r
+ ASSERT (RootBridge != NULL);\r
+\r
+ RootBridge->Signature = PCI_ROOT_BRIDGE_SIGNATURE;\r
+ RootBridge->Supports = Bridge->Supports;\r
+ RootBridge->Attributes = Bridge->Attributes;\r
+ RootBridge->DmaAbove4G = Bridge->DmaAbove4G;\r
+ RootBridge->AllocationAttributes = Bridge->AllocationAttributes;\r
+ RootBridge->DevicePath = DuplicateDevicePath (Bridge->DevicePath);\r
+ RootBridge->DevicePathStr = DevicePathStr;\r
+ RootBridge->ConfigBuffer = AllocatePool (\r
+ TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
+ );\r
+ ASSERT (RootBridge->ConfigBuffer != NULL);\r
+ InitializeListHead (&RootBridge->Maps);\r
+\r
+ CopyMem (&RootBridge->Bus, &Bridge->Bus, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
+ CopyMem (&RootBridge->Io, &Bridge->Io, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
+ CopyMem (&RootBridge->Mem, &Bridge->Mem, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
+ CopyMem (&RootBridge->MemAbove4G, &Bridge->MemAbove4G, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
+\r
+\r
+ for (Index = TypeIo; Index < TypeMax; Index++) {\r
+ RootBridge->ResAllocNode[Index].Type = Index;\r
+ RootBridge->ResAllocNode[Index].Base = 0;\r
+ RootBridge->ResAllocNode[Index].Length = 0;\r
+ RootBridge->ResAllocNode[Index].Status = ResNone;\r
+ }\r
+\r
+ RootBridge->RootBridgeIo.SegmentNumber = Bridge->Segment;\r
+ RootBridge->RootBridgeIo.ParentHandle = HostBridgeHandle;\r
+ RootBridge->RootBridgeIo.PollMem = RootBridgeIoPollMem;\r
+ RootBridge->RootBridgeIo.PollIo = RootBridgeIoPollIo;\r
+ RootBridge->RootBridgeIo.Mem.Read = RootBridgeIoMemRead;\r
+ RootBridge->RootBridgeIo.Mem.Write = RootBridgeIoMemWrite;\r
+ RootBridge->RootBridgeIo.Io.Read = RootBridgeIoIoRead;\r
+ RootBridge->RootBridgeIo.Io.Write = RootBridgeIoIoWrite;\r
+ RootBridge->RootBridgeIo.CopyMem = RootBridgeIoCopyMem;\r
+ RootBridge->RootBridgeIo.Pci.Read = RootBridgeIoPciRead;\r
+ RootBridge->RootBridgeIo.Pci.Write = RootBridgeIoPciWrite;\r
+ RootBridge->RootBridgeIo.Map = RootBridgeIoMap;\r
+ RootBridge->RootBridgeIo.Unmap = RootBridgeIoUnmap;\r
+ RootBridge->RootBridgeIo.AllocateBuffer = RootBridgeIoAllocateBuffer;\r
+ RootBridge->RootBridgeIo.FreeBuffer = RootBridgeIoFreeBuffer;\r
+ RootBridge->RootBridgeIo.Flush = RootBridgeIoFlush;\r
+ RootBridge->RootBridgeIo.GetAttributes = RootBridgeIoGetAttributes;\r
+ RootBridge->RootBridgeIo.SetAttributes = RootBridgeIoSetAttributes;\r
+ RootBridge->RootBridgeIo.Configuration = RootBridgeIoConfiguration;\r
+\r
+ return RootBridge;\r
+}\r
+\r
+/**\r
+ Check parameters for IO,MMIO,PCI read/write services of PCI Root Bridge IO.\r
+\r
+ The I/O operations are carried out exactly as requested. The caller is\r
+ responsible for satisfying any alignment and I/O width restrictions that a PI\r
+ System on a platform might require. For example on some platforms, width\r
+ requests of EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other\r
+ hand, will be handled by the driver.\r
+\r
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+\r
+ @param[in] OperationType I/O operation type: IO/MMIO/PCI.\r
+\r
+ @param[in] Width Signifies the width of the I/O or Memory operation.\r
+\r
+ @param[in] Address The base address of the I/O operation.\r
+\r
+ @param[in] Count The number of I/O operations to perform. The number\r
+ of bytes moved is Width size * Count, starting at\r
+ Address.\r
+\r
+ @param[in] Buffer For read operations, the destination buffer to\r
+ store the results. For write operations, the source\r
+ buffer from which to write data.\r
+\r
+ @retval EFI_SUCCESS The parameters for this request pass the\r
+ checks.\r
+\r
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.\r
+\r
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
+\r
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,\r
+ and Count is not valid for this PI system.\r
+**/\r
+EFI_STATUS\r
+RootBridgeIoCheckParameter (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN OPERATION_TYPE OperationType,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN VOID *Buffer\r
+ )\r
+{\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *PciRbAddr;\r
+ UINT64 Base;\r
+ UINT64 Limit;\r
+ UINT32 Size;\r
+\r
+ //\r
+ // Check to see if Buffer is NULL\r
+ //\r
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check to see if Width is in the valid range\r
+ //\r
+ if ((UINT32) Width >= EfiPciWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // For FIFO type, the target address won't increase during the access,\r
+ // so treat Count as 1\r
+ //\r
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
+ Count = 1;\r
+ }\r
+\r
+ Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
+ Size = 1 << Width;\r
+\r
+ //\r
+ // Check to see if Address is aligned\r
+ //\r
+ if ((Address & (Size - 1)) != 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
+\r
+ //\r
+ // Check to see if any address associated with this transfer exceeds the\r
+ // maximum allowed address. The maximum address implied by the parameters\r
+ // passed in is Address + Size * Count. If the following condition is met,\r
+ // then the transfer is not supported.\r
+ //\r
+ // Address + Size * Count > Limit + 1\r
+ //\r
+ // Since Limit can be the maximum integer value supported by the CPU and\r
+ // Count can also be the maximum integer value supported by the CPU, this\r
+ // range check must be adjusted to avoid all oveflow conditions.\r
+ //\r
+ if (OperationType == IoOperation) {\r
+ //\r
+ // Allow Legacy IO access\r
+ //\r
+ if (Address + MultU64x32 (Count, Size) <= 0x1000) {\r
+ if ((RootBridge->Attributes & (\r
+ EFI_PCI_ATTRIBUTE_ISA_IO | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_ATTRIBUTE_VGA_IO |\r
+ EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |\r
+ EFI_PCI_ATTRIBUTE_ISA_IO_16 | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 | EFI_PCI_ATTRIBUTE_VGA_IO_16)) != 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ Base = RootBridge->Io.Base;\r
+ Limit = RootBridge->Io.Limit;\r
+ } else if (OperationType == MemOperation) {\r
+ //\r
+ // Allow Legacy MMIO access\r
+ //\r
+ if ((Address >= 0xA0000) && (Address + MultU64x32 (Count, Size)) <= 0xC0000) {\r
+ if ((RootBridge->Attributes & EFI_PCI_ATTRIBUTE_VGA_MEMORY) != 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ //\r
+ // By comparing the Address against Limit we know which range to be used\r
+ // for checking\r
+ //\r
+ if (Address + MultU64x32 (Count, Size) <= RootBridge->Mem.Limit + 1) {\r
+ Base = RootBridge->Mem.Base;\r
+ Limit = RootBridge->Mem.Limit;\r
+ } else {\r
+ Base = RootBridge->MemAbove4G.Base;\r
+ Limit = RootBridge->MemAbove4G.Limit;\r
+ }\r
+ } else {\r
+ PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &Address;\r
+ if (PciRbAddr->Bus < RootBridge->Bus.Base ||\r
+ PciRbAddr->Bus > RootBridge->Bus.Limit) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (PciRbAddr->Device > PCI_MAX_DEVICE ||\r
+ PciRbAddr->Function > PCI_MAX_FUNC) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (PciRbAddr->ExtendedRegister != 0) {\r
+ Address = PciRbAddr->ExtendedRegister;\r
+ } else {\r
+ Address = PciRbAddr->Register;\r
+ }\r
+ Base = 0;\r
+ Limit = 0xFFF;\r
+ }\r
+\r
+ if (Address < Base) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Address + MultU64x32 (Count, Size) > Limit + 1) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Polls an address in memory mapped I/O space until an exit condition is met,\r
+ or a timeout occurs.\r
+\r
+ This function provides a standard way to poll a PCI memory location. A PCI\r
+ memory read operation is performed at the PCI memory address specified by\r
+ Address for the width specified by Width. The result of this PCI memory read\r
+ operation is stored in Result. This PCI memory read operation is repeated\r
+ until either a timeout of Delay 100 ns units has expired, or (Result & Mask)\r
+ is equal to Value.\r
+\r
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+ @param[in] Width Signifies the width of the memory operations.\r
+ @param[in] Address The base address of the memory operations. The caller\r
+ is responsible for aligning Address if required.\r
+ @param[in] Mask Mask used for the polling criteria. Bytes above Width\r
+ in Mask are ignored. The bits in the bytes below Width\r
+ which are zero in Mask are ignored when polling the\r
+ memory address.\r
+ @param[in] Value The comparison value used for the polling exit\r
+ criteria.\r
+ @param[in] Delay The number of 100 ns units to poll. Note that timer\r
+ available may be of poorer granularity.\r
+ @param[out] Result Pointer to the last value read from the memory\r
+ location.\r
+\r
+ @retval EFI_SUCCESS The last data returned from the access matched\r
+ the poll exit criteria.\r
+ @retval EFI_INVALID_PARAMETER Width is invalid.\r
+ @retval EFI_INVALID_PARAMETER Result is NULL.\r
+ @retval EFI_TIMEOUT Delay expired before a match occurred.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
+ lack of resources.\r
+**/\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoPollMem (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT64 NumberOfTicks;\r
+ UINT32 Remainder;\r
+\r
+ if (Result == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((UINT32)Width > EfiPciWidthUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // No matter what, always do a single poll.\r
+ //\r
+ Status = This->Mem.Read (This, Width, Address, 1, Result);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if ((*Result & Mask) == Value) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (Delay == 0) {\r
+ return EFI_SUCCESS;\r
+\r
+ } else {\r
+\r
+ //\r
+ // Determine the proper # of metronome ticks to wait for polling the\r
+ // location. The nuber of ticks is Roundup (Delay /\r
+ // mMetronome->TickPeriod)+1\r
+ // The "+1" to account for the possibility of the first tick being short\r
+ // because we started in the middle of a tick.\r
+ //\r
+ // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome\r
+ // protocol definition is updated.\r
+ //\r
+ NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) mMetronome->TickPeriod,\r
+ &Remainder);\r
+ if (Remainder != 0) {\r
+ NumberOfTicks += 1;\r
+ }\r
+ NumberOfTicks += 1;\r
+\r
+ while (NumberOfTicks != 0) {\r
+\r
+ mMetronome->WaitForTick (mMetronome, 1);\r
+\r
+ Status = This->Mem.Read (This, Width, Address, 1, Result);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if ((*Result & Mask) == Value) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ NumberOfTicks -= 1;\r
+ }\r
+ }\r
+ return EFI_TIMEOUT;\r
+}\r
+\r
+/**\r
+ Reads from the I/O space of a PCI Root Bridge. Returns when either the\r
+ polling exit criteria is satisfied or after a defined duration.\r
+\r
+ This function provides a standard way to poll a PCI I/O location. A PCI I/O\r
+ read operation is performed at the PCI I/O address specified by Address for\r
+ the width specified by Width.\r
+ The result of this PCI I/O read operation is stored in Result. This PCI I/O\r
+ read operation is repeated until either a timeout of Delay 100 ns units has\r
+ expired, or (Result & Mask) is equal to Value.\r
+\r
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+ @param[in] Width Signifies the width of the I/O operations.\r
+ @param[in] Address The base address of the I/O operations. The caller is\r
+ responsible for aligning Address if required.\r
+ @param[in] Mask Mask used for the polling criteria. Bytes above Width in\r
+ Mask are ignored. The bits in the bytes below Width\r
+ which are zero in Mask are ignored when polling the I/O\r
+ address.\r
+ @param[in] Value The comparison value used for the polling exit criteria.\r
+ @param[in] Delay The number of 100 ns units to poll. Note that timer\r
+ available may be of poorer granularity.\r
+ @param[out] Result Pointer to the last value read from the memory location.\r
+\r
+ @retval EFI_SUCCESS The last data returned from the access matched\r
+ the poll exit criteria.\r
+ @retval EFI_INVALID_PARAMETER Width is invalid.\r
+ @retval EFI_INVALID_PARAMETER Result is NULL.\r
+ @retval EFI_TIMEOUT Delay expired before a match occurred.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
+ lack of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoPollIo (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT64 NumberOfTicks;\r
+ UINT32 Remainder;\r
+\r
+ //\r
+ // No matter what, always do a single poll.\r
+ //\r
+\r
+ if (Result == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((UINT32)Width > EfiPciWidthUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = This->Io.Read (This, Width, Address, 1, Result);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if ((*Result & Mask) == Value) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (Delay == 0) {\r
+ return EFI_SUCCESS;\r
+\r
+ } else {\r
+\r
+ //\r
+ // Determine the proper # of metronome ticks to wait for polling the\r
+ // location. The number of ticks is Roundup (Delay /\r
+ // mMetronome->TickPeriod)+1\r
+ // The "+1" to account for the possibility of the first tick being short\r
+ // because we started in the middle of a tick.\r
+ //\r
+ NumberOfTicks = DivU64x32Remainder (Delay, (UINT32)mMetronome->TickPeriod,\r
+ &Remainder);\r
+ if (Remainder != 0) {\r
+ NumberOfTicks += 1;\r
+ }\r
+ NumberOfTicks += 1;\r
+\r
+ while (NumberOfTicks != 0) {\r
+\r
+ mMetronome->WaitForTick (mMetronome, 1);\r
+\r
+ Status = This->Io.Read (This, Width, Address, 1, Result);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if ((*Result & Mask) == Value) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ NumberOfTicks -= 1;\r
+ }\r
+ }\r
+ return EFI_TIMEOUT;\r
+}\r
+\r
+/**\r
+ Enables a PCI driver to access PCI controller registers in the PCI root\r
+ bridge memory space.\r
+\r
+ The Mem.Read(), and Mem.Write() functions enable a driver to access PCI\r
+ controller registers in the PCI root bridge memory space.\r
+ The memory operations are carried out exactly as requested. The caller is\r
+ responsible for satisfying any alignment and memory width restrictions that a\r
+ PCI Root Bridge on a platform might require.\r
+\r
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+ @param[in] Width Signifies the width of the memory operation.\r
+ @param[in] Address The base address of the memory operation. The caller\r
+ is responsible for aligning the Address if required.\r
+ @param[in] Count The number of memory operations to perform. Bytes\r
+ moved is Width size * Count, starting at Address.\r
+ @param[out] Buffer For read operations, the destination buffer to store\r
+ the results. For write operations, the source buffer\r
+ to write data from.\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PCI\r
+ root bridge.\r
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
+ lack of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoMemRead (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address,\r
+ Count, Buffer);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ return mCpuIo->Mem.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);\r
+}\r
+\r
+/**\r
+ Enables a PCI driver to access PCI controller registers in the PCI root\r
+ bridge memory space.\r
+\r
+ The Mem.Read(), and Mem.Write() functions enable a driver to access PCI\r
+ controller registers in the PCI root bridge memory space.\r
+ The memory operations are carried out exactly as requested. The caller is\r
+ responsible for satisfying any alignment and memory width restrictions that a\r
+ PCI Root Bridge on a platform might require.\r
+\r
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+ @param[in] Width Signifies the width of the memory operation.\r
+ @param[in] Address The base address of the memory operation. The caller\r
+ is responsible for aligning the Address if required.\r
+ @param[in] Count The number of memory operations to perform. Bytes\r
+ moved is Width size * Count, starting at Address.\r
+ @param[in] Buffer For read operations, the destination buffer to store\r
+ the results. For write operations, the source buffer\r
+ to write data from.\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PCI\r
+ root bridge.\r
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
+ lack of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoMemWrite (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address,\r
+ Count, Buffer);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ return mCpuIo->Mem.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);\r
+}\r
+\r
+/**\r
+ Enables a PCI driver to access PCI controller registers in the PCI root\r
+ bridge I/O space.\r
+\r
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+ @param[in] Width Signifies the width of the memory operations.\r
+ @param[in] Address The base address of the I/O operation. The caller is\r
+ responsible for aligning the Address if required.\r
+ @param[in] Count The number of I/O operations to perform. Bytes moved\r
+ is Width size * Count, starting at Address.\r
+ @param[out] Buffer For read operations, the destination buffer to store\r
+ the results. For write operations, the source buffer\r
+ to write data from.\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PCI\r
+ root bridge.\r
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
+ lack of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoIoRead (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ Status = RootBridgeIoCheckParameter (\r
+ This, IoOperation, Width,\r
+ Address, Count, Buffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ return mCpuIo->Io.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);\r
+}\r
+\r
+/**\r
+ Enables a PCI driver to access PCI controller registers in the PCI root\r
+ bridge I/O space.\r
+\r
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+ @param[in] Width Signifies the width of the memory operations.\r
+ @param[in] Address The base address of the I/O operation. The caller is\r
+ responsible for aligning the Address if required.\r
+ @param[in] Count The number of I/O operations to perform. Bytes moved\r
+ is Width size * Count, starting at Address.\r
+ @param[in] Buffer For read operations, the destination buffer to store\r
+ the results. For write operations, the source buffer\r
+ to write data from.\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PCI\r
+ root bridge.\r
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
+ lack of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoIoWrite (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ Status = RootBridgeIoCheckParameter (\r
+ This, IoOperation, Width,\r
+ Address, Count, Buffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ return mCpuIo->Io.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);\r
+}\r
+\r
+/**\r
+ Enables a PCI driver to copy one region of PCI root bridge memory space to\r
+ another region of PCI root bridge memory space.\r
+\r
+ The CopyMem() function enables a PCI driver to copy one region of PCI root\r
+ bridge memory space to another region of PCI root bridge memory space. This\r
+ is especially useful for video scroll operation on a memory mapped video\r
+ buffer.\r
+ The memory operations are carried out exactly as requested. The caller is\r
+ responsible for satisfying any alignment and memory width restrictions that a\r
+ PCI root bridge on a platform might require.\r
+\r
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL\r
+ instance.\r
+ @param[in] Width Signifies the width of the memory operations.\r
+ @param[in] DestAddress The destination address of the memory operation. The\r
+ caller is responsible for aligning the DestAddress if\r
+ required.\r
+ @param[in] SrcAddress The source address of the memory operation. The caller\r
+ is responsible for aligning the SrcAddress if\r
+ required.\r
+ @param[in] Count The number of memory operations to perform. Bytes\r
+ moved is Width size * Count, starting at DestAddress\r
+ and SrcAddress.\r
+\r
+ @retval EFI_SUCCESS The data was copied from one memory region\r
+ to another memory region.\r
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
+ lack of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoCopyMem (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 DestAddress,\r
+ IN UINT64 SrcAddress,\r
+ IN UINTN Count\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN Forward;\r
+ UINTN Stride;\r
+ UINTN Index;\r
+ UINT64 Result;\r
+\r
+ if ((UINT32) Width > EfiPciWidthUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (DestAddress == SrcAddress) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Stride = (UINTN) (1 << Width);\r
+\r
+ Forward = TRUE;\r
+ if ((DestAddress > SrcAddress) &&\r
+ (DestAddress < (SrcAddress + Count * Stride))) {\r
+ Forward = FALSE;\r
+ SrcAddress = SrcAddress + (Count - 1) * Stride;\r
+ DestAddress = DestAddress + (Count - 1) * Stride;\r
+ }\r
+\r
+ for (Index = 0; Index < Count; Index++) {\r
+ Status = RootBridgeIoMemRead (\r
+ This,\r
+ Width,\r
+ SrcAddress,\r
+ 1,\r
+ &Result\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = RootBridgeIoMemWrite (\r
+ This,\r
+ Width,\r
+ DestAddress,\r
+ 1,\r
+ &Result\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Forward) {\r
+ SrcAddress += Stride;\r
+ DestAddress += Stride;\r
+ } else {\r
+ SrcAddress -= Stride;\r
+ DestAddress -= Stride;\r
+ }\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ PCI configuration space access.\r
+\r
+ @param This A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL\r
+ @param Read TRUE indicating it's a read operation.\r
+ @param Width Signifies the width of the memory operation.\r
+ @param Address The address within the PCI configuration space\r
+ for the PCI controller.\r
+ @param Count The number of PCI configuration operations\r
+ to perform.\r
+ @param Buffer The destination buffer to store the results.\r
+\r
+ @retval EFI_SUCCESS The data was read/written from/to the PCI root bridge.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameters found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoPciAccess (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN BOOLEAN Read,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;\r
+ UINT8 *Uint8Buffer;\r
+ UINT8 InStride;\r
+ UINT8 OutStride;\r
+ UINTN Size;\r
+\r
+ Status = RootBridgeIoCheckParameter (This, PciOperation, Width, Address, Count, Buffer);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Read Pci configuration space\r
+ //\r
+ RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
+ CopyMem (&PciAddress, &Address, sizeof (PciAddress));\r
+\r
+ if (PciAddress.ExtendedRegister == 0) {\r
+ PciAddress.ExtendedRegister = PciAddress.Register;\r
+ }\r
+\r
+ Address = PCI_SEGMENT_LIB_ADDRESS (\r
+ RootBridge->RootBridgeIo.SegmentNumber,\r
+ PciAddress.Bus,\r
+ PciAddress.Device,\r
+ PciAddress.Function,\r
+ PciAddress.ExtendedRegister\r
+ );\r
+\r
+ //\r
+ // Select loop based on the width of the transfer\r
+ //\r
+ InStride = mInStride[Width];\r
+ OutStride = mOutStride[Width];\r
+ Size = (UINTN) (1 << (Width & 0x03));\r
+ for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
+ if (Read) {\r
+ PciSegmentReadBuffer (Address, Size, Uint8Buffer);\r
+ } else {\r
+ PciSegmentWriteBuffer (Address, Size, Uint8Buffer);\r
+ }\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Allows read from PCI configuration space.\r
+\r
+ @param This A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL\r
+ @param Width Signifies the width of the memory operation.\r
+ @param Address The address within the PCI configuration space\r
+ for the PCI controller.\r
+ @param Count The number of PCI configuration operations\r
+ to perform.\r
+ @param Buffer The destination buffer to store the results.\r
+\r
+ @retval EFI_SUCCESS The data was read from the PCI root bridge.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameters found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoPciRead (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ return RootBridgeIoPciAccess (This, TRUE, Width, Address, Count, Buffer);\r
+}\r
+\r
+/**\r
+ Allows write to PCI configuration space.\r
+\r
+ @param This A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL\r
+ @param Width Signifies the width of the memory operation.\r
+ @param Address The address within the PCI configuration space\r
+ for the PCI controller.\r
+ @param Count The number of PCI configuration operations\r
+ to perform.\r
+ @param Buffer The source buffer to get the results.\r
+\r
+ @retval EFI_SUCCESS The data was written to the PCI root bridge.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameters found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoPciWrite (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ return RootBridgeIoPciAccess (This, FALSE, Width, Address, Count, Buffer);\r
+}\r
+\r
+/**\r
+\r
+ Provides the PCI controller-specific address needed to access\r
+ system memory for DMA.\r
+\r
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+ @param Operation Indicate if the bus master is going to read or write\r
+ to system memory.\r
+ @param HostAddress The system memory address to map on the PCI controller.\r
+ @param NumberOfBytes On input the number of bytes to map.\r
+ On output the number of bytes that were mapped.\r
+ @param DeviceAddress The resulting map address for the bus master PCI\r
+ controller to use to access the system memory's HostAddress.\r
+ @param Mapping The value to pass to Unmap() when the bus master DMA\r
+ operation is complete.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameters found.\r
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.\r
+ @retval EFI_DEVICE_ERROR The System hardware could not map the requested address.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoMap (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,\r
+ IN VOID *HostAddress,\r
+ IN OUT UINTN *NumberOfBytes,\r
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
+ OUT VOID **Mapping\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
+ MAP_INFO *MapInfo;\r
+\r
+ if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL ||\r
+ Mapping == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Make sure that Operation is valid\r
+ //\r
+ if ((UINT32) Operation >= EfiPciOperationMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
+\r
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;\r
+ if (!RootBridge->DmaAbove4G && ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {\r
+ //\r
+ // If the root bridge can not handle performing DMA above 4GB but\r
+ // any part of the DMA transfer being mapped is above 4GB, then\r
+ // map the DMA transfer to a buffer below 4GB.\r
+ //\r
+\r
+ if (Operation == EfiPciOperationBusMasterCommonBuffer ||\r
+ Operation == EfiPciOperationBusMasterCommonBuffer64) {\r
+ //\r
+ // Common Buffer operations can not be remapped. If the common buffer\r
+ // if above 4GB, then it is not possible to generate a mapping, so return\r
+ // an error.\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Allocate a MAP_INFO structure to remember the mapping when Unmap() is\r
+ // called later.\r
+ //\r
+ MapInfo = AllocatePool (sizeof (MAP_INFO));\r
+ if (MapInfo == NULL) {\r
+ *NumberOfBytes = 0;\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Initialize the MAP_INFO structure\r
+ //\r
+ MapInfo->Signature = MAP_INFO_SIGNATURE;\r
+ MapInfo->Operation = Operation;\r
+ MapInfo->NumberOfBytes = *NumberOfBytes;\r
+ MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes);\r
+ MapInfo->HostAddress = PhysicalAddress;\r
+ MapInfo->MappedHostAddress = SIZE_4GB - 1;\r
+\r
+ //\r
+ // Allocate a buffer below 4GB to map the transfer to.\r
+ //\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiBootServicesData,\r
+ MapInfo->NumberOfPages,\r
+ &MapInfo->MappedHostAddress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (MapInfo);\r
+ *NumberOfBytes = 0;\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // If this is a read operation from the Bus Master's point of view,\r
+ // then copy the contents of the real buffer into the mapped buffer\r
+ // so the Bus Master can read the contents of the real buffer.\r
+ //\r
+ if (Operation == EfiPciOperationBusMasterRead ||\r
+ Operation == EfiPciOperationBusMasterRead64) {\r
+ CopyMem (\r
+ (VOID *) (UINTN) MapInfo->MappedHostAddress,\r
+ (VOID *) (UINTN) MapInfo->HostAddress,\r
+ MapInfo->NumberOfBytes\r
+ );\r
+ }\r
+\r
+ InsertTailList (&RootBridge->Maps, &MapInfo->Link);\r
+\r
+ //\r
+ // The DeviceAddress is the address of the maped buffer below 4GB\r
+ //\r
+ *DeviceAddress = MapInfo->MappedHostAddress;\r
+ //\r
+ // Return a pointer to the MAP_INFO structure in Mapping\r
+ //\r
+ *Mapping = MapInfo;\r
+ } else {\r
+ //\r
+ // If the root bridge CAN handle performing DMA above 4GB or\r
+ // the transfer is below 4GB, so the DeviceAddress is simply the\r
+ // HostAddress\r
+ //\r
+ *DeviceAddress = PhysicalAddress;\r
+ *Mapping = NO_MAPPING;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Completes the Map() operation and releases any corresponding resources.\r
+\r
+ The Unmap() function completes the Map() operation and releases any\r
+ corresponding resources.\r
+ If the operation was an EfiPciOperationBusMasterWrite or\r
+ EfiPciOperationBusMasterWrite64, the data is committed to the target system\r
+ memory.\r
+ Any resources used for the mapping are freed.\r
+\r
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+ @param[in] Mapping The mapping value returned from Map().\r
+\r
+ @retval EFI_SUCCESS The range was unmapped.\r
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().\r
+ @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoUnmap (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN VOID *Mapping\r
+ )\r
+{\r
+ MAP_INFO *MapInfo;\r
+ LIST_ENTRY *Link;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+\r
+ RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
+ //\r
+ // See if the Map() operation associated with this Unmap() required a mapping\r
+ // buffer. If a mapping buffer was not required, then this function simply\r
+ // returns EFI_SUCCESS.\r
+ //\r
+ if (Mapping == NO_MAPPING) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ MapInfo = NO_MAPPING;\r
+ for (Link = GetFirstNode (&RootBridge->Maps)\r
+ ; !IsNull (&RootBridge->Maps, Link)\r
+ ; Link = GetNextNode (&RootBridge->Maps, Link)\r
+ ) {\r
+ MapInfo = MAP_INFO_FROM_LINK (Link);\r
+ if (MapInfo == Mapping) {\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // Mapping is not a valid value returned by Map()\r
+ //\r
+ if (MapInfo != Mapping) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ RemoveEntryList (&MapInfo->Link);\r
+\r
+ //\r
+ // If this is a write operation from the Bus Master's point of view,\r
+ // then copy the contents of the mapped buffer into the real buffer\r
+ // so the processor can read the contents of the real buffer.\r
+ //\r
+ if (MapInfo->Operation == EfiPciOperationBusMasterWrite ||\r
+ MapInfo->Operation == EfiPciOperationBusMasterWrite64) {\r
+ CopyMem (\r
+ (VOID *) (UINTN) MapInfo->HostAddress,\r
+ (VOID *) (UINTN) MapInfo->MappedHostAddress,\r
+ MapInfo->NumberOfBytes\r
+ );\r
+ }\r
+\r
+ //\r
+ // Free the mapped buffer and the MAP_INFO structure.\r
+ //\r
+ gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);\r
+ FreePool (Mapping);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer\r
+ or EfiPciOperationBusMasterCommonBuffer64 mapping.\r
+\r
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+ @param Type This parameter is not used and must be ignored.\r
+ @param MemoryType The type of memory to allocate, EfiBootServicesData or\r
+ EfiRuntimeServicesData.\r
+ @param Pages The number of pages to allocate.\r
+ @param HostAddress A pointer to store the base system memory address of the\r
+ allocated range.\r
+ @param Attributes The requested bit mask of attributes for the allocated\r
+ range. Only the attributes\r
+ EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE,\r
+ EFI_PCI_ATTRIBUTE_MEMORY_CACHED, and\r
+ EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this\r
+ function.\r
+\r
+ @retval EFI_SUCCESS The requested memory pages were allocated.\r
+ @retval EFI_INVALID_PARAMETER MemoryType is invalid.\r
+ @retval EFI_INVALID_PARAMETER HostAddress is NULL.\r
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal\r
+ attribute bits are MEMORY_WRITE_COMBINE,\r
+ MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.\r
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoAllocateBuffer (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_ALLOCATE_TYPE Type,\r
+ IN EFI_MEMORY_TYPE MemoryType,\r
+ IN UINTN Pages,\r
+ OUT VOID **HostAddress,\r
+ IN UINT64 Attributes\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ EFI_ALLOCATE_TYPE AllocateType;\r
+\r
+ //\r
+ // Validate Attributes\r
+ //\r
+ if ((Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Check for invalid inputs\r
+ //\r
+ if (HostAddress == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // The only valid memory types are EfiBootServicesData and\r
+ // EfiRuntimeServicesData\r
+ //\r
+ if (MemoryType != EfiBootServicesData &&\r
+ MemoryType != EfiRuntimeServicesData) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
+\r
+ AllocateType = AllocateAnyPages;\r
+ if (!RootBridge->DmaAbove4G) {\r
+ //\r
+ // Limit allocations to memory below 4GB\r
+ //\r
+ AllocateType = AllocateMaxAddress;\r
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1);\r
+ }\r
+ Status = gBS->AllocatePages (\r
+ AllocateType,\r
+ MemoryType,\r
+ Pages,\r
+ &PhysicalAddress\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ *HostAddress = (VOID *) (UINTN) PhysicalAddress;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Frees memory that was allocated with AllocateBuffer().\r
+\r
+ The FreeBuffer() function frees memory that was allocated with\r
+ AllocateBuffer().\r
+\r
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+ @param Pages The number of pages to free.\r
+ @param HostAddress The base system memory address of the allocated range.\r
+\r
+ @retval EFI_SUCCESS The requested memory pages were freed.\r
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and\r
+ Pages was not allocated with AllocateBuffer().\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoFreeBuffer (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN UINTN Pages,\r
+ OUT VOID *HostAddress\r
+ )\r
+{\r
+ return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);\r
+}\r
+\r
+/**\r
+ Flushes all PCI posted write transactions from a PCI host bridge to system\r
+ memory.\r
+\r
+ The Flush() function flushes any PCI posted write transactions from a PCI\r
+ host bridge to system memory. Posted write transactions are generated by PCI\r
+ bus masters when they perform write transactions to target addresses in\r
+ system memory.\r
+ This function does not flush posted write transactions from any PCI bridges.\r
+ A PCI controller specific action must be taken to guarantee that the posted\r
+ write transactions have been flushed from the PCI controller and from all the\r
+ PCI bridges into the PCI host bridge. This is typically done with a PCI read\r
+ transaction from the PCI controller prior to calling Flush().\r
+\r
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+\r
+ @retval EFI_SUCCESS The PCI posted write transactions were flushed\r
+ from the PCI host bridge to system memory.\r
+ @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed\r
+ from the PCI host bridge due to a hardware error.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoFlush (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This\r
+ )\r
+{\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Gets the attributes that a PCI root bridge supports setting with\r
+ SetAttributes(), and the attributes that a PCI root bridge is currently\r
+ using.\r
+\r
+ The GetAttributes() function returns the mask of attributes that this PCI\r
+ root bridge supports and the mask of attributes that the PCI root bridge is\r
+ currently using.\r
+\r
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+ @param Supported A pointer to the mask of attributes that this PCI root\r
+ bridge supports setting with SetAttributes().\r
+ @param Attributes A pointer to the mask of attributes that this PCI root\r
+ bridge is currently using.\r
+\r
+ @retval EFI_SUCCESS If Supports is not NULL, then the attributes\r
+ that the PCI root bridge supports is returned\r
+ in Supports. If Attributes is not NULL, then\r
+ the attributes that the PCI root bridge is\r
+ currently using is returned in Attributes.\r
+ @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoGetAttributes (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ OUT UINT64 *Supported,\r
+ OUT UINT64 *Attributes\r
+ )\r
+{\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+\r
+ if (Attributes == NULL && Supported == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
+ //\r
+ // Set the return value for Supported and Attributes\r
+ //\r
+ if (Supported != NULL) {\r
+ *Supported = RootBridge->Supports;\r
+ }\r
+\r
+ if (Attributes != NULL) {\r
+ *Attributes = RootBridge->Attributes;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Sets attributes for a resource range on a PCI root bridge.\r
+\r
+ The SetAttributes() function sets the attributes specified in Attributes for\r
+ the PCI root bridge on the resource range specified by ResourceBase and\r
+ ResourceLength. Since the granularity of setting these attributes may vary\r
+ from resource type to resource type, and from platform to platform, the\r
+ actual resource range and the one passed in by the caller may differ. As a\r
+ result, this function may set the attributes specified by Attributes on a\r
+ larger resource range than the caller requested. The actual range is returned\r
+ in ResourceBase and ResourceLength. The caller is responsible for verifying\r
+ that the actual range for which the attributes were set is acceptable.\r
+\r
+ @param This A pointer to the\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+ @param Attributes The mask of attributes to set. If the\r
+ attribute bit MEMORY_WRITE_COMBINE,\r
+ MEMORY_CACHED, or MEMORY_DISABLE is set,\r
+ then the resource range is specified by\r
+ ResourceBase and ResourceLength. If\r
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, and\r
+ MEMORY_DISABLE are not set, then\r
+ ResourceBase and ResourceLength are ignored,\r
+ and may be NULL.\r
+ @param ResourceBase A pointer to the base address of the\r
+ resource range to be modified by the\r
+ attributes specified by Attributes.\r
+ @param ResourceLength A pointer to the length of the resource\r
+ range to be modified by the attributes\r
+ specified by Attributes.\r
+\r
+ @retval EFI_SUCCESS The current configuration of this PCI root bridge\r
+ was returned in Resources.\r
+ @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge\r
+ could not be retrieved.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoSetAttributes (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN UINT64 Attributes,\r
+ IN OUT UINT64 *ResourceBase,\r
+ IN OUT UINT64 *ResourceLength\r
+ )\r
+{\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+\r
+ RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
+\r
+ if ((Attributes & (~RootBridge->Supports)) != 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ RootBridge->Attributes = Attributes;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Retrieves the current resource settings of this PCI root bridge in the form\r
+ of a set of ACPI 2.0 resource descriptors.\r
+\r
+ There are only two resource descriptor types from the ACPI Specification that\r
+ may be used to describe the current resources allocated to a PCI root bridge.\r
+ These are the QWORD Address Space Descriptor (ACPI 2.0 Section 6.4.3.5.1),\r
+ and the End Tag (ACPI 2.0 Section 6.4.2.8). The QWORD Address Space\r
+ Descriptor can describe memory, I/O, and bus number ranges for dynamic or\r
+ fixed resources. The configuration of a PCI root bridge is described with one\r
+ or more QWORD Address Space Descriptors followed by an End Tag.\r
+\r
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+ @param[out] Resources A pointer to the ACPI 2.0 resource descriptors that\r
+ describe the current configuration of this PCI root\r
+ bridge. The storage for the ACPI 2.0 resource\r
+ descriptors is allocated by this function. The\r
+ caller must treat the return buffer as read-only\r
+ data, and the buffer must not be freed by the\r
+ caller.\r
+\r
+ @retval EFI_SUCCESS The current configuration of this PCI root bridge\r
+ was returned in Resources.\r
+ @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge\r
+ could not be retrieved.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RootBridgeIoConfiguration (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ OUT VOID **Resources\r
+ )\r
+{\r
+ PCI_RESOURCE_TYPE Index;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ PCI_RES_NODE *ResAllocNode;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+ EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
+\r
+ //\r
+ // Get this instance of the Root Bridge.\r
+ //\r
+ RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
+ ZeroMem (\r
+ RootBridge->ConfigBuffer,\r
+ TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
+ );\r
+ Descriptor = RootBridge->ConfigBuffer;\r
+ for (Index = TypeIo; Index < TypeMax; Index++) {\r
+\r
+ ResAllocNode = &RootBridge->ResAllocNode[Index];\r
+\r
+ if (ResAllocNode->Status != ResAllocated) {\r
+ continue;\r
+ }\r
+\r
+ Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+ Descriptor->AddrRangeMin = ResAllocNode->Base;\r
+ Descriptor->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;\r
+ Descriptor->AddrLen = ResAllocNode->Length;\r
+ switch (ResAllocNode->Type) {\r
+\r
+ case TypeIo:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
+ break;\r
+\r
+ case TypePMem32:\r
+ Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+ case TypeMem32:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ Descriptor->AddrSpaceGranularity = 32;\r
+ break;\r
+\r
+ case TypePMem64:\r
+ Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+ case TypeMem64:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ Descriptor->AddrSpaceGranularity = 64;\r
+ break;\r
+\r
+ case TypeBus:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ Descriptor++;\r
+ }\r
+ //\r
+ // Terminate the entries.\r
+ //\r
+ End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;\r
+ End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+ End->Checksum = 0x0;\r
+\r
+ *Resources = RootBridge->ConfigBuffer;\r
+ return EFI_SUCCESS;\r
+}\r
IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf\r
PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf\r
PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf\r
+ PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf\r
CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf\r
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf\r
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf\r
MdeModulePkg/Application/HelloWorld/HelloWorld.inf\r
MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf\r
\r
+ MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf\r
MdeModulePkg/Bus/Pci/PciSioSerialDxe/PciSioSerialDxe.inf\r
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf\r
MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf\r