X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FBus%2FPci%2FPciBusDxe%2FPciEnumeratorSupport.c;h=9b59e85bcd7a13e0bd41e0d9010df83b272e61ae;hp=f46025e2f61c54f3b32b4a3cd45792c5a0e072da;hb=fcdfcdbfc2e5dc6a96ce550a1f46edb4007f35a9;hpb=5c13180cfc9827f11174995a5211d6dde2a1ef31 diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c index f46025e2f6..9b59e85bcd 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c @@ -1,7 +1,8 @@ /** @file PCI emumeration support functions implementation for PCI Bus module. -Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -16,6 +17,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. extern CHAR16 *mBarTypeStr[]; +#define OLD_ALIGN 0xFFFFFFFFFFFFFFFFULL +#define EVEN_ALIGN 0xFFFFFFFFFFFFFFFEULL +#define SQUAD_ALIGN 0xFFFFFFFFFFFFFFFDULL +#define DQUAD_ALIGN 0xFFFFFFFFFFFFFFFCULL + /** This routine is used to check whether the pci device is present. @@ -82,7 +88,7 @@ PciDevicePresent ( root bridge will then be created. @param Bridge Parent bridge instance. - @param StartBusNumber Bus number of begining. + @param StartBusNumber Bus number of beginning. @retval EFI_SUCCESS PCI device is found. @retval other Some error occurred when reading PCI bridge information. @@ -119,6 +125,14 @@ PciPciDeviceInfoCollector ( (UINT8) Device, (UINT8) Func ); + + if (EFI_ERROR (Status) && Func == 0) { + // + // go to next device if there is no Function 0 + // + break; + } + if (!EFI_ERROR (Status)) { // @@ -155,6 +169,14 @@ PciPciDeviceInfoCollector ( return Status; } + // + // Ensure secondary bus number is greater than the primary bus number to avoid + // any potential dead loop when PcdPciDisableBusEnumeration is set to TRUE + // + if (SecBus <= StartBusNumber) { + break; + } + // // Get resource padding for PPB // @@ -186,7 +208,7 @@ PciPciDeviceInfoCollector ( } /** - Seach required device and create PCI device instance. + Search required device and create PCI device instance. @param Bridge Parent bridge instance. @param Pci Input PCI device information block. @@ -315,6 +337,81 @@ PciSearchDevice ( return EFI_SUCCESS; } +/** + Dump the PPB padding resource information. + + @param PciIoDevice PCI IO instance. + @param ResourceType The desired resource type to dump. + PciBarTypeUnknown means to dump all types of resources. +**/ +VOID +DumpPpbPaddingResource ( + IN PCI_IO_DEVICE *PciIoDevice, + IN PCI_BAR_TYPE ResourceType + ) +{ + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor; + PCI_BAR_TYPE Type; + + if (PciIoDevice->ResourcePaddingDescriptors == NULL) { + return; + } + + if (ResourceType == PciBarTypeIo16 || ResourceType == PciBarTypeIo32) { + ResourceType = PciBarTypeIo; + } + + for (Descriptor = PciIoDevice->ResourcePaddingDescriptors; Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR; Descriptor++) { + + Type = PciBarTypeUnknown; + if (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) { + Type = PciBarTypeIo; + } else if (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) { + + if (Descriptor->AddrSpaceGranularity == 32) { + // + // prefetchable + // + if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) { + Type = PciBarTypePMem32; + } + + // + // Non-prefetchable + // + if (Descriptor->SpecificFlag == 0) { + Type = PciBarTypeMem32; + } + } + + if (Descriptor->AddrSpaceGranularity == 64) { + // + // prefetchable + // + if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) { + Type = PciBarTypePMem64; + } + + // + // Non-prefetchable + // + if (Descriptor->SpecificFlag == 0) { + Type = PciBarTypeMem64; + } + } + } + + if ((Type != PciBarTypeUnknown) && ((ResourceType == PciBarTypeUnknown) || (ResourceType == Type))) { + DEBUG (( + EFI_D_INFO, + " Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n", + mBarTypeStr[Type], Descriptor->AddrRangeMax, Descriptor->AddrLen + )); + } + } + +} + /** Dump the PCI BAR information. @@ -471,7 +568,7 @@ GatherPpbInfo ( PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED); // - // Initalize the bridge control register + // Initialize the bridge control register // PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED); @@ -507,14 +604,14 @@ GatherPpbInfo ( // // if PcdPciBridgeIoAlignmentProbe is TRUE, PCI bus driver probes - // PCI bridge supporting non-stardard I/O window alignment less than 4K. + // PCI bridge supporting non-standard I/O window alignment less than 4K. // PciIoDevice->BridgeIoAlignment = 0xFFF; if (FeaturePcdGet (PcdPciBridgeIoAlignmentProbe)) { // // Check any bits of bit 3-1 of I/O Base Register are writable. - // if so, it is assumed non-stardard I/O window alignment is supported by this bridge. + // if so, it is assumed non-standard I/O window alignment is supported by this bridge. // Per spec, bit 3-1 of I/O Base Register are reserved bits, so its content can't be assumed. // Value = (UINT8)(Temp ^ (BIT3 | BIT2 | BIT1)); @@ -577,7 +674,10 @@ GatherPpbInfo ( GetResourcePaddingPpb (PciIoDevice); - DEBUG_CODE (DumpPciBars (PciIoDevice);); + DEBUG_CODE ( + DumpPpbPaddingResource (PciIoDevice, PciBarTypeUnknown); + DumpPciBars (PciIoDevice); + ); return PciIoDevice; } @@ -622,7 +722,7 @@ GatherP2CInfo ( PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED); // - // Initalize the bridge control register + // Initialize the bridge control register // PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED); } @@ -646,7 +746,7 @@ GatherP2CInfo ( } /** - Create device path for pci deivce. + Create device path for pci device. @param ParentDevicePath Parent bridge's path. @param PciIoDevice Pci device instance. @@ -822,7 +922,7 @@ BarExisted ( @param PciIoDevice Pci device instance. @param Command Input command register value, and returned supported register value. - @param BridgeControl Inout bridge control value for PPB or P2C, and + @param BridgeControl Input bridge control value for PPB or P2C, and returned supported bridge control value. @param OldCommand Returned and stored old command register offset. @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C. @@ -1105,7 +1205,7 @@ DetermineDeviceAttribute ( EFI_STATUS Status; // - // For Root Bridge, just copy it by RootBridgeIo proctocol + // For Root Bridge, just copy it by RootBridgeIo protocol // so as to keep consistent with the actual attribute // if (PciIoDevice->Parent == NULL) { @@ -1154,9 +1254,11 @@ DetermineDeviceAttribute ( PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES); // - // Enable other supported attributes but not defined in PCI_IO_PROTOCOL - // - PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE); + // Enable other PCI supported attributes but not defined in PCI_IO_PROTOCOL + // For PCI Express devices, Memory Write and Invalidate is hardwired to 0b so only enable it for PCI devices. + if (!PciIoDevice->IsPciExp) { + PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE); + } } FastB2BSupport = TRUE; @@ -1180,7 +1282,7 @@ DetermineDeviceAttribute ( return Status; } // - // Detect Fast Bact to Bact support for the device under the bridge + // Detect Fast Back to Back support for the device under the bridge // Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET); if (FastB2BSupport && EFI_ERROR (Status)) { @@ -1241,7 +1343,6 @@ UpdatePciInfo ( { EFI_STATUS Status; UINTN BarIndex; - UINTN BarEndIndex; BOOLEAN SetFlag; VOID *Configuration; EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr; @@ -1249,7 +1350,7 @@ UpdatePciInfo ( Configuration = NULL; Status = EFI_SUCCESS; - if (gEfiIncompatiblePciDeviceSupport == NULL) { + if (gIncompatiblePciDeviceSupport == NULL) { // // It can only be supported after the Incompatible PCI Device // Support Protocol has been installed @@ -1257,7 +1358,7 @@ UpdatePciInfo ( Status = gBS->LocateProtocol ( &gEfiIncompatiblePciDeviceSupportProtocolGuid, NULL, - (VOID **) &gEfiIncompatiblePciDeviceSupport + (VOID **) &gIncompatiblePciDeviceSupport ); } if (Status == EFI_SUCCESS) { @@ -1265,15 +1366,15 @@ UpdatePciInfo ( // Check whether the device belongs to incompatible devices from protocol or not // If it is , then get its special requirement in the ACPI table // - Status = gEfiIncompatiblePciDeviceSupport->CheckDevice ( - gEfiIncompatiblePciDeviceSupport, - PciIoDevice->Pci.Hdr.VendorId, - PciIoDevice->Pci.Hdr.DeviceId, - PciIoDevice->Pci.Hdr.RevisionID, - PciIoDevice->Pci.Device.SubsystemVendorID, - PciIoDevice->Pci.Device.SubsystemID, - &Configuration - ); + Status = gIncompatiblePciDeviceSupport->CheckDevice ( + gIncompatiblePciDeviceSupport, + PciIoDevice->Pci.Hdr.VendorId, + PciIoDevice->Pci.Hdr.DeviceId, + PciIoDevice->Pci.Hdr.RevisionID, + PciIoDevice->Pci.Device.SubsystemVendorID, + PciIoDevice->Pci.Device.SubsystemID, + &Configuration + ); } @@ -1295,23 +1396,19 @@ UpdatePciInfo ( break; } - BarIndex = (UINTN) Ptr->AddrTranslationOffset; - BarEndIndex = BarIndex; - - // - // Update all the bars in the device - // - if (BarIndex == PCI_BAR_ALL) { - BarIndex = 0; - BarEndIndex = PCI_MAX_BAR - 1; - } - - if (BarIndex > PCI_MAX_BAR) { - Ptr++; - continue; - } + for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) { + if ((Ptr->AddrTranslationOffset != MAX_UINT64) && + (Ptr->AddrTranslationOffset != MAX_UINT8) && + (Ptr->AddrTranslationOffset != BarIndex) + ) { + // + // Skip updating when AddrTranslationOffset is not MAX_UINT64 or MAX_UINT8 (wide match). + // Skip updating when current BarIndex doesn't equal to AddrTranslationOffset. + // Comparing against MAX_UINT8 is to keep backward compatibility. + // + continue; + } - for (; BarIndex <= BarEndIndex; BarIndex++) { SetFlag = FALSE; switch (Ptr->ResType) { case ACPI_ADDRESS_SPACE_TYPE_MEM: @@ -1321,6 +1418,38 @@ UpdatePciInfo ( // if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) { SetFlag = TRUE; + + // + // Ignored if granularity is 0. + // Ignored if PCI BAR is I/O or 32-bit memory. + // If PCI BAR is 64-bit memory and granularity is 32, then + // the PCI BAR resource is allocated below 4GB. + // If PCI BAR is 64-bit memory and granularity is 64, then + // the PCI BAR resource is allocated above 4GB. + // + if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeMem64) { + switch (Ptr->AddrSpaceGranularity) { + case 32: + PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32; + case 64: + PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE; + break; + default: + break; + } + } + + if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypePMem64) { + switch (Ptr->AddrSpaceGranularity) { + case 32: + PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32; + case 64: + PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE; + break; + default: + break; + } + } } break; @@ -1345,7 +1474,7 @@ UpdatePciInfo ( // // Update the new length for the device // - if (Ptr->AddrLen != PCI_BAR_NOCHANGE) { + if (Ptr->AddrLen != 0) { PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen; } } @@ -1361,6 +1490,8 @@ UpdatePciInfo ( /** This routine will update the alignment with the new alignment. + Compare with OLD_ALIGN/EVEN_ALIGN/SQUAD_ALIGN/DQUAD_ALIGN is to keep + backward compatibility. @param Alignment Input Old alignment. Output updated alignment. @param NewAlignment New alignment. @@ -1379,15 +1510,15 @@ SetNewAlign ( // The new alignment is the same as the original, // so skip it // - if (NewAlignment == PCI_BAR_OLD_ALIGN) { + if ((NewAlignment == 0) || (NewAlignment == OLD_ALIGN)) { return ; } // // Check the validity of the parameter // - if (NewAlignment != PCI_BAR_EVEN_ALIGN && - NewAlignment != PCI_BAR_SQUAD_ALIGN && - NewAlignment != PCI_BAR_DQUAD_ALIGN ) { + if (NewAlignment != EVEN_ALIGN && + NewAlignment != SQUAD_ALIGN && + NewAlignment != DQUAD_ALIGN ) { *Alignment = NewAlignment; return ; } @@ -1406,15 +1537,15 @@ SetNewAlign ( // // Adjust the alignment to even, quad or double quad boundary // - if (NewAlignment == PCI_BAR_EVEN_ALIGN) { + if (NewAlignment == EVEN_ALIGN) { if ((OldAlignment & 0x01) != 0) { OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01); } - } else if (NewAlignment == PCI_BAR_SQUAD_ALIGN) { + } else if (NewAlignment == SQUAD_ALIGN) { if ((OldAlignment & 0x03) != 0) { OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03); } - } else if (NewAlignment == PCI_BAR_DQUAD_ALIGN) { + } else if (NewAlignment == DQUAD_ALIGN) { if ((OldAlignment & 0x07) != 0) { OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07); } @@ -1564,7 +1695,7 @@ PciIovParseVfBar ( } // - // Fix the length to support some spefic 64 bit BAR + // Fix the length to support some special 64 bit BAR // Value |= ((UINT32) -1 << HighBitSet32 (Value)); @@ -1605,7 +1736,7 @@ PciIovParseVfBar ( break; } } - + // // Check the length again so as to keep compatible with some special bars // @@ -1614,7 +1745,7 @@ PciIovParseVfBar ( PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0; PciIoDevice->VfPciBar[BarIndex].Alignment = 0; } - + // // Increment number of bar // @@ -1665,6 +1796,7 @@ PciParseBar ( return Offset + 4; } + PciIoDevice->PciBar[BarIndex].BarTypeFixed = FALSE; PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset; if ((Value & 0x01) != 0) { // @@ -1690,14 +1822,13 @@ PciParseBar ( } // - // Workaround. Some platforms inplement IO bar with 0 length + // Workaround. Some platforms implement IO bar with 0 length // Need to treat it as no-bar // if (PciIoDevice->PciBar[BarIndex].Length == 0) { PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE) 0; } - PciIoDevice->PciBar[BarIndex].Prefetchable = FALSE; PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask; } else { @@ -1775,7 +1906,7 @@ PciParseBar ( } // - // Fix the length to support some spefic 64 bit BAR + // Fix the length to support some special 64 bit BAR // if (Value == 0) { DEBUG ((EFI_D_INFO, "[PciBus]BAR probing for upper 32bit of MEM64 BAR returns 0, change to 0xFFFFFFFF.\n")); @@ -1856,7 +1987,7 @@ InitializePciDevice ( // // Put all the resource apertures // Resource base is set to all ones so as to indicate its resource - // has not been alloacted + // has not been allocated // for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) { PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne); @@ -1946,10 +2077,10 @@ InitializeP2C ( } /** - Create and initiliaze general PCI I/O device instance for + Create and initialize general PCI I/O device instance for PCI device/bridge device/hotplug bridge device. - @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Bridge Parent bridge instance. @param Pci Input Pci information block. @param Bus Device Bus NO. @param Device Device device NO. @@ -2054,7 +2185,7 @@ CreatePciIoDevice ( // ParentPciIo = &Bridge->PciIo; ParentPciIo->Pci.Read ( - ParentPciIo, + ParentPciIo, EfiPciIoWidthUint32, Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET, 1, @@ -2312,7 +2443,7 @@ PciEnumeratorLight ( } // - // Record the root bridgeio protocol + // Record the root bridge-io protocol // RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo; @@ -2345,7 +2476,7 @@ PciEnumeratorLight ( } else { // - // If unsuccessly, destroy the entire node + // If unsuccessfully, destroy the entire node // DestroyRootBridge (RootBridgeDev); } @@ -2597,6 +2728,13 @@ ResetAllPpbBusNumber ( Func ); + if (EFI_ERROR (Status) && Func == 0) { + // + // go to next device if there is no Function 0 + // + break; + } + if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) { Register = 0;