/** @file\r
PCI eunmeration implementation on entire PCI bus system for PCI Bus module.\r
\r
-Copyright (c) 2006 - 2009, Intel Corporation\r
-All rights reserved. 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
This routine is used to enumerate entire pci bus system\r
in a given platform.\r
\r
- @param Controller Parent controller handle.\r
+ @param Controller Parent controller handle.\r
+ @param HostBridgeHandle Host bridge handle.\r
\r
@retval EFI_SUCCESS PCI enumeration finished successfully.\r
@retval other Some error occurred when enumerating the pci bus system.\r
**/\r
EFI_STATUS\r
PciEnumerator (\r
- IN EFI_HANDLE Controller\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_HANDLE HostBridgeHandle\r
)\r
{\r
- EFI_HANDLE Handle;\r
- EFI_HANDLE HostBridgeHandle;\r
EFI_STATUS Status;\r
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc;\r
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
-\r
- //\r
- // If PCI bus has already done the full enumeration, never do it again\r
- //\r
- if (!gFullEnumeration) {\r
- return PciEnumeratorLight (Controller);\r
- }\r
-\r
- //\r
- // Get the rootbridge Io protocol to find the host bridge handle\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiPciRootBridgeIoProtocolGuid,\r
- (VOID **) &PciRootBridgeIo,\r
- gPciBusDriverBinding.DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Get the host bridge handle\r
- //\r
- HostBridgeHandle = PciRootBridgeIo->ParentHandle;\r
\r
//\r
// Get the pci host bridge resource allocation protocol\r
//\r
// Notify the pci bus enumeration is about to begin\r
//\r
- NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration);\r
+ Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
//\r
// Start the bus allocation phase\r
//\r
// Notify the pci bus enumeration is about to complete\r
//\r
- NotifyPhase (PciResAlloc, EfiPciHostBridgeEndEnumeration);\r
+ Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeEndEnumeration);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
//\r
// Process P2C\r
return Status;\r
}\r
\r
- gFullEnumeration = FALSE;\r
-\r
- Status = gBS->InstallProtocolInterface (\r
- &Handle,\r
- &gEfiPciEnumerationCompleteProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- NULL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
return EFI_SUCCESS;\r
}\r
\r
{\r
EFI_STATUS Status;\r
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration1;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration2;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration3;\r
UINT8 SubBusNumber;\r
UINT8 StartBusNumber;\r
UINT8 PaddedBusRange;\r
EFI_HANDLE RootBridgeHandle;\r
+ UINT8 Desc;\r
+ UINT64 AddrLen;\r
+ UINT64 AddrRangeMin;\r
\r
SubBusNumber = 0;\r
StartBusNumber = 0;\r
\r
REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
EFI_PROGRESS_CODE,\r
- EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_BUS_ENUM,\r
+ EFI_IO_BUS_PCI | EFI_IOB_PCI_BUS_ENUM,\r
RootBridgeDev->DevicePath\r
);\r
\r
return Status;\r
}\r
\r
+ if (Configuration == NULL || Configuration->Desc == ACPI_END_TAG_DESCRIPTOR) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ RootBridgeDev->BusNumberRanges = Configuration;\r
+\r
+ //\r
+ // Sort the descriptors in ascending order\r
+ //\r
+ for (Configuration1 = Configuration; Configuration1->Desc != ACPI_END_TAG_DESCRIPTOR; Configuration1++) {\r
+ Configuration2 = Configuration1;\r
+ for (Configuration3 = Configuration1 + 1; Configuration3->Desc != ACPI_END_TAG_DESCRIPTOR; Configuration3++) {\r
+ if (Configuration2->AddrRangeMin > Configuration3->AddrRangeMin) {\r
+ Configuration2 = Configuration3;\r
+ }\r
+ }\r
+ //\r
+ // All other fields other than AddrRangeMin and AddrLen are ignored in a descriptor,\r
+ // so only need to swap these two fields.\r
+ //\r
+ if (Configuration2 != Configuration1) {\r
+ AddrRangeMin = Configuration1->AddrRangeMin;\r
+ Configuration1->AddrRangeMin = Configuration2->AddrRangeMin;\r
+ Configuration2->AddrRangeMin = AddrRangeMin;\r
+\r
+ AddrLen = Configuration1->AddrLen;\r
+ Configuration1->AddrLen = Configuration2->AddrLen;\r
+ Configuration2->AddrLen = AddrLen;\r
+ }\r
+ }\r
+\r
//\r
// Get the bus number to start with\r
//\r
StartBusNumber = (UINT8) (Configuration->AddrRangeMin);\r
- PaddedBusRange = (UINT8) (Configuration->AddrRangeMax);\r
\r
//\r
// Initialize the subordinate bus number\r
//\r
Status = PciScanBus (\r
RootBridgeDev,\r
- (UINT8) (Configuration->AddrRangeMin),\r
+ StartBusNumber,\r
&SubBusNumber,\r
&PaddedBusRange\r
);\r
//\r
// Assign max bus number scanned\r
//\r
- Configuration->AddrLen = SubBusNumber - StartBusNumber + 1 + PaddedBusRange;\r
+\r
+ Status = PciAllocateBusNumber (RootBridgeDev, SubBusNumber, PaddedBusRange, &SubBusNumber);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Find the bus range which contains the higest bus number, then returns the number of buses\r
+ // that should be decoded.\r
+ //\r
+ while (Configuration->AddrRangeMin + Configuration->AddrLen - 1 < SubBusNumber) {\r
+ Configuration++;\r
+ }\r
+ AddrLen = Configuration->AddrLen;\r
+ Configuration->AddrLen = SubBusNumber - Configuration->AddrRangeMin + 1;\r
+\r
+ //\r
+ // Save the Desc field of the next descriptor. Mark the next descriptor as an END descriptor.\r
+ //\r
+ Configuration++;\r
+ Desc = Configuration->Desc;\r
+ Configuration->Desc = ACPI_END_TAG_DESCRIPTOR;\r
\r
//\r
// Set bus number\r
Status = PciResAlloc->SetBusNumbers (\r
PciResAlloc,\r
RootBridgeHandle,\r
- Configuration\r
+ RootBridgeDev->BusNumberRanges\r
);\r
\r
- FreePool (Configuration);\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ //\r
+ // Restore changed fields\r
+ //\r
+ Configuration->Desc = Desc;\r
+ (Configuration - 1)->AddrLen = AddrLen;\r
\r
- return EFI_SUCCESS;\r
+ return Status;\r
}\r
\r
/**\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
(IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {\r
\r
//\r
// Reserved one bus for cardbus bridge\r
//\r
- SecondBus = ++(*SubBusNumber);\r
+ Status = PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusNumber);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ SecondBus = *SubBusNumber;\r
\r
Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
\r
}\r
\r
if ((Attributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0) {\r
+ RootBridgeDev->Decodes |= EFI_BRIDGE_MEM64_DECODE_SUPPORTED;\r
RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;\r
}\r
\r
@return Max size of option rom needed.\r
\r
**/\r
-UINT64\r
+UINT32\r
GetMaxOptionRomSize (\r
IN PCI_IO_DEVICE *Bridge\r
)\r
{\r
LIST_ENTRY *CurrentLink;\r
PCI_IO_DEVICE *Temp;\r
- UINT64 MaxOptionRomSize;\r
- UINT64 TempOptionRomSize;\r
+ UINT32 MaxOptionRomSize;\r
+ UINT32 TempOptionRomSize;\r
\r
MaxOptionRomSize = 0;\r
\r
if (Temp == PciDevice) {\r
InitializePciDevice (Temp);\r
RemoveEntryList (CurrentLink);\r
- FreePciDevice (Temp);\r
return EFI_SUCCESS;\r
}\r
\r
@param Mem64ResStatus Status of 64-bit memory resource node.\r
@param PMem64ResStatus Status of 64-bit Prefetchable memory resource node.\r
\r
- @retval EFI_SUCCESS Successfully adjusted resoruce on host bridge.\r
+ @retval EFI_SUCCESS Successfully adjusted resource on host bridge.\r
@retval EFI_ABORTED Host bridge hasn't this resource type or no resource be adjusted.\r
\r
**/\r
//\r
Status = RejectPciDevice (PciResNode->PciDev);\r
if (Status == EFI_SUCCESS) {\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "PciBus: [%02x|%02x|%02x] was rejected due to resource confliction.\n",\r
+ PciResNode->PciDev->BusNumber, PciResNode->PciDev->DeviceNumber, PciResNode->PciDev->FunctionNumber\r
+ ));\r
\r
//\r
// Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
// Have no way to get ReqRes, AllocRes & Bar here\r
//\r
ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));\r
- AllocFailExtendedData.DevicePathSize = sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
+ AllocFailExtendedData.DevicePathSize = (UINT16) sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
AllocFailExtendedData.DevicePath = (UINT8 *) PciResNode->PciDev->DevicePath;\r
AllocFailExtendedData.Bar = PciResNode->Bar;\r
\r
}\r
\r
/**\r
- Summary requests for all resource type, and contruct ACPI resource\r
+ Summary requests for all resource type, and construct ACPI resource\r
requestor instance.\r
\r
@param Bridge detecting bridge\r
@param Config Output buffer holding new constructed APCI resource requestor\r
\r
@retval EFI_SUCCESS Successfully constructed ACPI resource.\r
- @retval EFI_OUT_OF_RESOURCES No memory availabe.\r
+ @retval EFI_OUT_OF_RESOURCES No memory available.\r
\r
**/\r
EFI_STATUS\r
//\r
if ((Aperture & 0x01) != 0) {\r
Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
- Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+ Ptr->Len = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);\r
//\r
// Io\r
//\r
//\r
if ((Aperture & 0x02) != 0) {\r
Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
- Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+ Ptr->Len = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);\r
//\r
// Mem\r
//\r
//\r
if ((Aperture & 0x04) != 0) {\r
Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
- Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+ Ptr->Len = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);\r
//\r
// Mem\r
//\r
//\r
if ((Aperture & 0x08) != 0) {\r
Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
- Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+ Ptr->Len = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);\r
//\r
// Mem\r
//\r
//\r
if ((Aperture & 0x10) != 0) {\r
Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
- Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+ Ptr->Len = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);\r
//\r
// Mem\r
//\r
//\r
// If there is no resource request\r
//\r
- Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
+ Configuration = AllocateZeroPool (sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
if (Configuration == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration);\r
- Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
-\r
- PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Ptr + 1);\r
+ PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Configuration);\r
PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
PtrEnd->Checksum = 0;\r
}\r
IoBridge = CreateResourceNode (\r
Bridge,\r
0,\r
- 0xFFF,\r
+ Bridge->BridgeIoAlignment,\r
0,\r
PciBarTypeIo16,\r
PciResUsageTypical\r
Phase,\r
ChipsetEntry\r
);\r
- } \r
+ }\r
\r
Status = PciResAlloc->NotifyPhase (\r
PciResAlloc,\r
);\r
}\r
\r
- return EFI_SUCCESS;\r
+ return Status;\r
}\r
\r
/**\r
return EFI_INVALID_PARAMETER;\r
}\r
}\r
- \r
+\r
Status = gBS->OpenProtocol (\r
Controller,\r
&gEfiPciIoProtocolGuid,\r
RootBridgeHandle = Temp->Handle;\r
\r
if (Operation == EfiPciHotPlugRequestAdd) {\r
+ //\r
+ // Report Status Code to indicate hot plug happens\r
+ //\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_IO_BUS_PCI | EFI_IOB_PC_HOTPLUG),\r
+ Temp->DevicePath\r
+ );\r
\r
if (NumberOfChildren != NULL) {\r
*NumberOfChildren = 0;\r