/** @file\r
Internal library implementation for PCI Bus module.\r
\r
-Copyright (c) 2006 - 2010, 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
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include "PciBus.h"\r
\r
+GLOBAL_REMOVE_IF_UNREFERENCED\r
+CHAR16 *mBarTypeStr[] = {\r
+ L"Unknow",\r
+ L" Io16",\r
+ L" Io32",\r
+ L" Mem32",\r
+ L"PMem32",\r
+ L" Mem64",\r
+ L"PMem64",\r
+ L" OpRom",\r
+ L" Io",\r
+ L" Mem",\r
+ L"Unknow"\r
+ };\r
+\r
+/**\r
+ Retrieve the max bus number that is assigned to the Root Bridge hierarchy.\r
+ It can support the case that there are multiple bus ranges.\r
+\r
+ @param Bridge Bridge device instance.\r
+\r
+ @retval The max bus number that is assigned to this Root Bridge hierarchy.\r
+\r
+**/\r
+UINT16\r
+PciGetMaxBusNumber (\r
+ IN PCI_IO_DEVICE *Bridge\r
+ )\r
+{\r
+ PCI_IO_DEVICE *RootBridge;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BusNumberRanges;\r
+ UINT64 MaxNumberInRange;\r
+\r
+ //\r
+ // Get PCI Root Bridge device\r
+ //\r
+ RootBridge = Bridge;\r
+ while (RootBridge->Parent != NULL) {\r
+ RootBridge = RootBridge->Parent;\r
+ }\r
+ MaxNumberInRange = 0;\r
+ //\r
+ // Iterate the bus number ranges to get max PCI bus number\r
+ //\r
+ BusNumberRanges = RootBridge->BusNumberRanges;\r
+ while (BusNumberRanges->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
+ MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;\r
+ BusNumberRanges++;\r
+ }\r
+ return (UINT16) MaxNumberInRange;\r
+}\r
\r
/**\r
Retrieve the PCI Card device BAR information via PciIo interface.\r
}\r
}\r
\r
+/**\r
+ Dump the resourc map of the bridge device.\r
+\r
+ @param[in] BridgeResource Resource descriptor of the bridge device.\r
+**/\r
+VOID\r
+DumpBridgeResource (\r
+ IN PCI_RESOURCE_NODE *BridgeResource\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ PCI_RESOURCE_NODE *Resource;\r
+ PCI_BAR *Bar;\r
+\r
+ if ((BridgeResource != NULL) && (BridgeResource->Length != 0)) {\r
+ DEBUG ((\r
+ EFI_D_INFO, "Type = %s; Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx\n",\r
+ mBarTypeStr[MIN (BridgeResource->ResType, PciBarTypeMaxType)],\r
+ BridgeResource->PciDev->PciBar[BridgeResource->Bar].BaseAddress,\r
+ BridgeResource->Length, BridgeResource->Alignment\r
+ ));\r
+ for ( Link = GetFirstNode (&BridgeResource->ChildList)\r
+ ; !IsNull (&BridgeResource->ChildList, Link)\r
+ ; Link = GetNextNode (&BridgeResource->ChildList, Link)\r
+ ) {\r
+ Resource = RESOURCE_NODE_FROM_LINK (Link);\r
+ if (Resource->ResourceUsage == PciResUsageTypical) {\r
+ Bar = Resource->Virtual ? Resource->PciDev->VfPciBar : Resource->PciDev->PciBar;\r
+ DEBUG ((\r
+ EFI_D_INFO, " Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx;\tOwner = %s [%02x|%02x|%02x:",\r
+ Bar[Resource->Bar].BaseAddress, Resource->Length, Resource->Alignment,\r
+ IS_PCI_BRIDGE (&Resource->PciDev->Pci) ? L"PPB" :\r
+ IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) ? L"P2C" :\r
+ L"PCI",\r
+ Resource->PciDev->BusNumber, Resource->PciDev->DeviceNumber,\r
+ Resource->PciDev->FunctionNumber\r
+ ));\r
+\r
+ if ((!IS_PCI_BRIDGE (&Resource->PciDev->Pci) && !IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci)) ||\r
+ (IS_PCI_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar < PPB_IO_RANGE)) ||\r
+ (IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar < P2C_MEM_1))\r
+ ) {\r
+ //\r
+ // The resource requirement comes from the device itself.\r
+ //\r
+ DEBUG ((EFI_D_INFO, "%02x]", Bar[Resource->Bar].Offset));\r
+ } else {\r
+ //\r
+ // The resource requirement comes from the subordinate devices.\r
+ //\r
+ DEBUG ((EFI_D_INFO, "**]"));\r
+ }\r
+ } else {\r
+ DEBUG ((EFI_D_INFO, " Base = Padding;\tLength = 0x%lx;\tAlignment = 0x%lx", Resource->Length, Resource->Alignment));\r
+ }\r
+ if (BridgeResource->ResType != Resource->ResType) {\r
+ DEBUG ((EFI_D_INFO, "; Type = %s", mBarTypeStr[MIN (Resource->ResType, PciBarTypeMaxType)]));\r
+ }\r
+ DEBUG ((EFI_D_INFO, "\n"));\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Find the corresponding resource node for the Device in child list of BridgeResource.\r
+\r
+ @param[in] Device Pointer to PCI_IO_DEVICE.\r
+ @param[in] BridgeResource Pointer to PCI_RESOURCE_NODE.\r
+ @param[out] DeviceResources Pointer to a buffer to receive resources for the Device.\r
+\r
+ @return Count of the resource descriptors returned.\r
+**/\r
+UINTN\r
+FindResourceNode (\r
+ IN PCI_IO_DEVICE *Device,\r
+ IN PCI_RESOURCE_NODE *BridgeResource,\r
+ OUT PCI_RESOURCE_NODE **DeviceResources OPTIONAL\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ PCI_RESOURCE_NODE *Resource;\r
+ UINTN Count;\r
+\r
+ Count = 0;\r
+ for ( Link = BridgeResource->ChildList.ForwardLink\r
+ ; Link != &BridgeResource->ChildList\r
+ ; Link = Link->ForwardLink\r
+ ) {\r
+ Resource = RESOURCE_NODE_FROM_LINK (Link);\r
+ if (Resource->PciDev == Device) {\r
+ if (DeviceResources != NULL) {\r
+ DeviceResources[Count] = Resource;\r
+ }\r
+ Count++;\r
+ }\r
+ }\r
+\r
+ return Count;\r
+}\r
+\r
+/**\r
+ Dump the resource map of all the devices under Bridge.\r
+\r
+ @param[in] Bridge Bridge device instance.\r
+ @param[in] Resources Resource descriptors for the bridge device.\r
+ @param[in] ResourceCount Count of resource descriptors.\r
+**/\r
+VOID\r
+DumpResourceMap (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN PCI_RESOURCE_NODE **Resources,\r
+ IN UINTN ResourceCount\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ PCI_IO_DEVICE *Device;\r
+ UINTN Index;\r
+ CHAR16 *Str;\r
+ PCI_RESOURCE_NODE **ChildResources;\r
+ UINTN ChildResourceCount;\r
+\r
+ DEBUG ((EFI_D_INFO, "PciBus: Resource Map for "));\r
+\r
+ Status = gBS->OpenProtocol (\r
+ Bridge->Handle,\r
+ &gEfiPciRootBridgeIoProtocolGuid,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ EFI_D_INFO, "Bridge [%02x|%02x|%02x]\n",\r
+ Bridge->BusNumber, Bridge->DeviceNumber, Bridge->FunctionNumber\r
+ ));\r
+ } else {\r
+ Str = ConvertDevicePathToText (\r
+ DevicePathFromHandle (Bridge->Handle),\r
+ FALSE,\r
+ FALSE\r
+ );\r
+ DEBUG ((EFI_D_INFO, "Root Bridge %s\n", Str != NULL ? Str : L""));\r
+ if (Str != NULL) {\r
+ FreePool (Str);\r
+ }\r
+ }\r
+\r
+ for (Index = 0; Index < ResourceCount; Index++) {\r
+ DumpBridgeResource (Resources[Index]);\r
+ }\r
+ DEBUG ((EFI_D_INFO, "\n"));\r
+\r
+ for ( Link = Bridge->ChildList.ForwardLink\r
+ ; Link != &Bridge->ChildList\r
+ ; Link = Link->ForwardLink\r
+ ) {\r
+ Device = PCI_IO_DEVICE_FROM_LINK (Link);\r
+ if (IS_PCI_BRIDGE (&Device->Pci)) {\r
+\r
+ ChildResourceCount = 0;\r
+ for (Index = 0; Index < ResourceCount; Index++) {\r
+ ChildResourceCount += FindResourceNode (Device, Resources[Index], NULL);\r
+ }\r
+ ChildResources = AllocatePool (sizeof (PCI_RESOURCE_NODE *) * ChildResourceCount);\r
+ ASSERT (ChildResources != NULL);\r
+ ChildResourceCount = 0;\r
+ for (Index = 0; Index < ResourceCount; Index++) {\r
+ ChildResourceCount += FindResourceNode (Device, Resources[Index], &ChildResources[ChildResourceCount]);\r
+ }\r
+\r
+ DumpResourceMap (Device, ChildResources, ChildResourceCount);\r
+ FreePool (ChildResources);\r
+ }\r
+ }\r
+}\r
+\r
/**\r
Submits the I/O and memory resource requirements for the specified PCI Host Bridge.\r
\r
UINT64 PMem32ResStatus;\r
UINT64 Mem64ResStatus;\r
UINT64 PMem64ResStatus;\r
- UINT64 MaxOptionRomSize;\r
+ UINT32 MaxOptionRomSize;\r
PCI_RESOURCE_NODE *IoBridge;\r
PCI_RESOURCE_NODE *Mem32Bridge;\r
PCI_RESOURCE_NODE *PMem32Bridge;\r
PCI_RESOURCE_NODE PMem32Pool;\r
PCI_RESOURCE_NODE Mem64Pool;\r
PCI_RESOURCE_NODE PMem64Pool;\r
- BOOLEAN ReAllocate;\r
EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData;\r
EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;\r
\r
- //\r
- // Reallocate flag\r
- //\r
- ReAllocate = FALSE;\r
-\r
//\r
// It may try several times if the resource allocation fails\r
//\r
//\r
\r
//\r
- // If non-stardard PCI Bridge I/O window alignment is supported,\r
+ // If non-standard PCI Bridge I/O window alignment is supported,\r
// set I/O aligment to minimum possible alignment for root bridge.\r
//\r
IoBridge = CreateResourceNode (\r
RootBridgeDev,\r
0,\r
FeaturePcdGet (PcdPciBridgeIoAlignmentProbe) ? 0x1FF: 0xFFF,\r
- 0,\r
+ RB_IO_RANGE,\r
PciBarTypeIo16,\r
PciResUsageTypical\r
);\r
RootBridgeDev,\r
0,\r
0xFFFFF,\r
- 0,\r
+ RB_MEM32_RANGE,\r
PciBarTypeMem32,\r
PciResUsageTypical\r
);\r
RootBridgeDev,\r
0,\r
0xFFFFF,\r
- 0,\r
+ RB_PMEM32_RANGE,\r
PciBarTypePMem32,\r
PciResUsageTypical\r
);\r
RootBridgeDev,\r
0,\r
0xFFFFF,\r
- 0,\r
+ RB_MEM64_RANGE,\r
PciBarTypeMem64,\r
PciResUsageTypical\r
);\r
RootBridgeDev,\r
0,\r
0xFFFFF,\r
- 0,\r
+ RB_PMEM64_RANGE,\r
PciBarTypePMem64,\r
PciResUsageTypical\r
);\r
\r
+ //\r
+ // Get the max ROM size that the root bridge can process\r
+ // Insert to resource map so that there will be dedicate MEM32 resource range for Option ROM.\r
+ // All devices' Option ROM share the same MEM32 resource.\r
+ //\r
+ MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);\r
+ if (MaxOptionRomSize != 0) {\r
+ RootBridgeDev->PciBar[0].BarType = PciBarTypeOpRom;\r
+ RootBridgeDev->PciBar[0].Length = MaxOptionRomSize;\r
+ RootBridgeDev->PciBar[0].Alignment = MaxOptionRomSize - 1;\r
+ GetResourceFromDevice (RootBridgeDev, IoBridge, Mem32Bridge, PMem32Bridge, Mem64Bridge, PMem64Bridge);\r
+ }\r
+\r
//\r
// Create resourcemap by going through all the devices subject to this root bridge\r
//\r
);\r
\r
//\r
- // Get the max ROM size that the root bridge can process\r
- //\r
- RootBridgeDev->RomSize = Mem32Bridge->Length;\r
-\r
- //\r
- // Skip to enlarge the resource request during realloction\r
- //\r
- if (!ReAllocate) {\r
- //\r
- // Get Max Option Rom size for current root bridge\r
- //\r
- MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);\r
-\r
- //\r
- // Enlarger the mem32 resource to accomdate the option rom\r
- // if the mem32 resource is not enough to hold the rom\r
- //\r
- if (MaxOptionRomSize > Mem32Bridge->Length) {\r
-\r
- Mem32Bridge->Length = MaxOptionRomSize;\r
- RootBridgeDev->RomSize = MaxOptionRomSize;\r
-\r
- //\r
- // Alignment should be adjusted as well\r
- //\r
- if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {\r
- Mem32Bridge->Alignment = MaxOptionRomSize - 1;\r
- }\r
- }\r
- }\r
-\r
- //\r
- // Based on the all the resource tree, contruct ACPI resource node to\r
+ // Based on the all the resource tree, construct ACPI resource node to\r
// submit the resource aperture to pci host bridge protocol\r
//\r
Status = ConstructAcpiResourceRequestor (\r
RootBridgeDev->Handle,\r
AcpiConfig\r
);\r
+ //\r
+ // If SubmitResources returns error, PciBus isn't able to start.\r
+ // It's a fatal error so assertion is added.\r
+ //\r
+ DEBUG ((EFI_D_INFO, "PciBus: HostBridge->SubmitResources() - %r\n", Status));\r
+ ASSERT_EFI_ERROR (Status);\r
}\r
\r
//\r
// Notify platform to start to program the resource\r
//\r
Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);\r
+ DEBUG ((EFI_D_INFO, "PciBus: HostBridge->NotifyPhase(AllocateResources) - %r\n", Status));\r
if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
//\r
// If Hot Plug is not supported\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
-\r
- ReAllocate = TRUE;\r
}\r
}\r
//\r
//\r
// Notify pci bus driver starts to program the resource\r
//\r
- NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);\r
+ Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
RootBridgeDev = NULL;\r
\r
&PMem64Base\r
);\r
\r
- //\r
- // Process option rom for this root bridge\r
- //\r
- ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);\r
-\r
//\r
// Create the entire system resource map from the information collected by\r
// enumerator. Several resource tree was created\r
//\r
- GetResourceMap (\r
- RootBridgeDev,\r
- &IoBridge,\r
- &Mem32Bridge,\r
- &PMem32Bridge,\r
- &Mem64Bridge,\r
- &PMem64Bridge,\r
- &IoPool,\r
- &Mem32Pool,\r
- &PMem32Pool,\r
- &Mem64Pool,\r
- &PMem64Pool\r
- );\r
+ FindResourceNode (RootBridgeDev, &IoPool, &IoBridge);\r
+ FindResourceNode (RootBridgeDev, &Mem32Pool, &Mem32Bridge);\r
+ FindResourceNode (RootBridgeDev, &PMem32Pool, &PMem32Bridge);\r
+ FindResourceNode (RootBridgeDev, &Mem64Pool, &Mem64Bridge);\r
+ FindResourceNode (RootBridgeDev, &PMem64Pool, &PMem64Bridge);\r
+\r
+ ASSERT (IoBridge != NULL);\r
+ ASSERT (Mem32Bridge != NULL);\r
+ ASSERT (PMem32Bridge != NULL);\r
+ ASSERT (Mem64Bridge != NULL);\r
+ ASSERT (PMem64Bridge != NULL);\r
\r
//\r
// Program IO resources\r
PMem64Bridge\r
);\r
\r
+ //\r
+ // Process Option ROM for this root bridge after all BARs are programmed.\r
+ // The PPB's MEM32 RANGE BAR is re-programmed to the Option ROM BAR Base in order to\r
+ // shadow the Option ROM of the devices under the PPB.\r
+ // After the shadow, Option ROM BAR decoding is turned off and the PPB's MEM32 RANGE\r
+ // BAR is restored back to the original value.\r
+ // The original value is programmed by ProgramResource() above.\r
+ //\r
+ DEBUG ((\r
+ DEBUG_INFO, "Process Option ROM: BAR Base/Length = %lx/%lx\n",\r
+ RootBridgeDev->PciBar[0].BaseAddress, RootBridgeDev->PciBar[0].Length\r
+ ));\r
+ ProcessOptionRom (RootBridgeDev, RootBridgeDev->PciBar[0].BaseAddress, RootBridgeDev->PciBar[0].Length);\r
+\r
+ IoBridge ->PciDev->PciBar[IoBridge ->Bar].BaseAddress = IoBase;\r
+ Mem32Bridge ->PciDev->PciBar[Mem32Bridge ->Bar].BaseAddress = Mem32Base;\r
+ PMem32Bridge->PciDev->PciBar[PMem32Bridge->Bar].BaseAddress = PMem32Base;\r
+ Mem64Bridge ->PciDev->PciBar[Mem64Bridge ->Bar].BaseAddress = Mem64Base;\r
+ PMem64Bridge->PciDev->PciBar[PMem64Bridge->Bar].BaseAddress = PMem64Base;\r
+\r
+ //\r
+ // Dump the resource map for current root bridge\r
+ //\r
+ DEBUG_CODE (\r
+ PCI_RESOURCE_NODE *Resources[5];\r
+ Resources[0] = IoBridge;\r
+ Resources[1] = Mem32Bridge;\r
+ Resources[2] = PMem32Bridge;\r
+ Resources[3] = Mem64Bridge;\r
+ Resources[4] = PMem64Bridge;\r
+ DumpResourceMap (RootBridgeDev, Resources, ARRAY_SIZE (Resources));\r
+ );\r
+\r
FreePool (AcpiConfig);\r
}\r
\r
//\r
// Notify the resource allocation phase is to end\r
//\r
- NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);\r
+ Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);\r
\r
- return EFI_SUCCESS;\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Allocate NumberOfBuses buses and return the next available PCI bus number.\r
+\r
+ @param Bridge Bridge device instance.\r
+ @param StartBusNumber Current available PCI bus number.\r
+ @param NumberOfBuses Number of buses enumerated below the StartBusNumber.\r
+ @param NextBusNumber Next available PCI bus number.\r
+\r
+ @retval EFI_SUCCESS Available bus number resource is enough. Next available PCI bus number\r
+ is returned in NextBusNumber.\r
+ @retval EFI_OUT_OF_RESOURCES Available bus number resource is not enough for allocation.\r
+\r
+**/\r
+EFI_STATUS\r
+PciAllocateBusNumber (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN UINT8 StartBusNumber,\r
+ IN UINT8 NumberOfBuses,\r
+ OUT UINT8 *NextBusNumber\r
+ )\r
+{\r
+ PCI_IO_DEVICE *RootBridge;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BusNumberRanges;\r
+ UINT8 NextNumber;\r
+ UINT64 MaxNumberInRange;\r
+\r
+ //\r
+ // Get PCI Root Bridge device\r
+ //\r
+ RootBridge = Bridge;\r
+ while (RootBridge->Parent != NULL) {\r
+ RootBridge = RootBridge->Parent;\r
+ }\r
+\r
+ //\r
+ // Get next available PCI bus number\r
+ //\r
+ BusNumberRanges = RootBridge->BusNumberRanges;\r
+ while (BusNumberRanges->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
+ MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;\r
+ if (StartBusNumber >= BusNumberRanges->AddrRangeMin && StartBusNumber <= MaxNumberInRange) {\r
+ NextNumber = (UINT8)(StartBusNumber + NumberOfBuses);\r
+ while (NextNumber > MaxNumberInRange) {\r
+ ++BusNumberRanges;\r
+ if (BusNumberRanges->Desc == ACPI_END_TAG_DESCRIPTOR) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ NextNumber = (UINT8)(NextNumber + (BusNumberRanges->AddrRangeMin - (MaxNumberInRange + 1)));\r
+ MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;\r
+ }\r
+ *NextBusNumber = NextNumber;\r
+ return EFI_SUCCESS;\r
+ }\r
+ BusNumberRanges++;\r
+ }\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r
\r
/**\r
UINT8 Device;\r
UINT8 Func;\r
UINT64 Address;\r
- UINTN SecondBus;\r
+ UINT8 SecondBus;\r
+ UINT8 PaddedSubBus;\r
UINT16 Register;\r
UINTN HpIndex;\r
PCI_IO_DEVICE *PciDevice;\r
UINT64 PciAddress;\r
EFI_HPC_PADDING_ATTRIBUTES Attributes;\r
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *NextDescriptors;\r
UINT16 BusRange;\r
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
BOOLEAN BusPadding;\r
Func\r
);\r
\r
+ if (EFI_ERROR (Status) && Func == 0) {\r
+ //\r
+ // go to next device if there is no Function 0\r
+ //\r
+ break;\r
+ }\r
+\r
if (EFI_ERROR (Status)) {\r
continue;\r
}\r
\r
- DEBUG((EFI_D_INFO, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber, Device, Func ));\r
-\r
//\r
// Get the PCI device information\r
//\r
&PciDevice\r
);\r
\r
- ASSERT (!EFI_ERROR (Status));\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
\r
PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);\r
\r
//\r
// For PPB\r
//\r
- if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
- //\r
- // If Hot Plug is not supported,\r
- // get the bridge information\r
- //\r
- Status = PciSearchDevice (\r
- Bridge,\r
- &Pci,\r
- StartBusNumber,\r
- Device,\r
- Func,\r
- &PciDevice\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- } else {\r
+ if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
//\r
// If Hot Plug is supported,\r
// Get the bridge information\r
BusPadding = FALSE;\r
if (gPciHotPlugInit != NULL) {\r
\r
- if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {\r
+ if (IsPciHotPlugBus (PciDevice)) {\r
\r
//\r
// If it is initialized, get the padded bus range\r
//\r
Status = gPciHotPlugInit->GetResourcePadding (\r
gPciHotPlugInit,\r
- gPciRootHpcPool[HpIndex].HpbDevicePath,\r
+ PciDevice->DevicePath,\r
PciAddress,\r
&State,\r
(VOID **) &Descriptors,\r
}\r
\r
BusRange = 0;\r
+ NextDescriptors = Descriptors;\r
Status = PciGetBusRange (\r
- &Descriptors,\r
+ &NextDescriptors,\r
NULL,\r
NULL,\r
&BusRange\r
\r
FreePool (Descriptors);\r
\r
- if (EFI_ERROR (Status)) {\r
+ if (!EFI_ERROR (Status)) {\r
+ BusPadding = TRUE;\r
+ } else if (Status != EFI_NOT_FOUND) {\r
+ //\r
+ // EFI_NOT_FOUND is not a real error. It indicates no bus number padding requested.\r
+ //\r
return Status;\r
}\r
-\r
- BusPadding = TRUE;\r
}\r
}\r
}\r
\r
- //\r
- // Add feature to support customized secondary bus number\r
- //\r
- if (*SubBusNumber == 0) {\r
- *SubBusNumber = *PaddedBusRange;\r
- *PaddedBusRange = 0;\r
+ Status = PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusNumber);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
}\r
-\r
- (*SubBusNumber)++;\r
SecondBus = *SubBusNumber;\r
\r
Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
// Temporarily initialize SubBusNumber to maximum bus number to ensure the\r
// PCI configuration transaction to go through any PPB\r
//\r
- Register = 0xFF;\r
+ Register = PciGetMaxBusNumber (Bridge);\r
Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
Status = PciRootBridgeIo->Pci.Write (\r
PciRootBridgeIo,\r
EfiPciBeforeChildBusEnumeration\r
);\r
\r
- DEBUG((EFI_D_INFO, "Scan PPB(%02d,%02d,%02d)\n", PciDevice->BusNumber, PciDevice->DeviceNumber,PciDevice->FunctionNumber));\r
Status = PciScanBus (\r
PciDevice,\r
- (UINT8) (SecondBus),\r
+ SecondBus,\r
SubBusNumber,\r
PaddedBusRange\r
);\r
if ((Attributes == EfiPaddingPciRootBridge) &&\r
(State & EFI_HPC_STATE_ENABLED) != 0 &&\r
(State & EFI_HPC_STATE_INITIALIZED) != 0) {\r
- *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange);\r
+ *PaddedBusRange = (UINT8) ((UINT8) (BusRange) + *PaddedBusRange);\r
} else {\r
- *SubBusNumber = (UINT8) ((UINT8) (BusRange) +*SubBusNumber);\r
+ //\r
+ // Reserve the larger one between the actual occupied bus number and padded bus number\r
+ //\r
+ Status = PciAllocateBusNumber (PciDevice, SecondBus, (UINT8) (BusRange), &PaddedSubBus);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ *SubBusNumber = MAX (PaddedSubBus, *SubBusNumber);\r
}\r
}\r
\r
if (PcdGetBool (PcdSrIovSupport) && PciDevice->SrIovCapabilityOffset != 0) {\r
if (TempReservedBusNum < PciDevice->ReservedBusNum) {\r
\r
- (*SubBusNumber) = (UINT8)((*SubBusNumber) + PciDevice->ReservedBusNum - TempReservedBusNum);\r
+ Status = PciAllocateBusNumber (PciDevice, *SubBusNumber, (UINT8) (PciDevice->ReservedBusNum - TempReservedBusNum), SubBusNumber);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
TempReservedBusNum = PciDevice->ReservedBusNum;\r
\r
if (Func == 0) {\r
//\r
// Notify the bus allocation phase is about to start\r
//\r
- NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
+ Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
DEBUG((EFI_D_INFO, "PCI Bus First Scanning\n"));\r
RootBridgeHandle = NULL;\r
//\r
// Notify the bus allocation phase is about to start for the 2nd time\r
//\r
- NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
+ Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
DEBUG((EFI_D_INFO, "PCI Bus Second Scanning\n"));\r
RootBridgeHandle = NULL;\r
//\r
// Notify the resource allocation phase is to start\r
//\r
- NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);\r
+ Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
RootBridgeHandle = NULL;\r
while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r