summaryrefslogtreecommitdiff
path: root/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c
diff options
context:
space:
mode:
Diffstat (limited to 'DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c')
-rw-r--r--DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c1018
1 files changed, 1018 insertions, 0 deletions
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c b/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c
new file mode 100644
index 0000000000..ff53bb5c78
--- /dev/null
+++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c
@@ -0,0 +1,1018 @@
+/*++
+
+Copyright (c) 2005 - 2006, Intel Corporation
+All rights reserved. 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
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ PcatPciRootBridge.c
+
+Abstract:
+
+ EFI PC-AT PCI Root Bridge Controller
+
+--*/
+
+#include "PcatPciRootBridge.h"
+#include "DeviceIo.h"
+
+EFI_CPU_IO_PROTOCOL *gCpuIo;
+
+EFI_STATUS
+EFIAPI
+InitializePcatPciRootBridge (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ Initializes the PCI Root Bridge Controller
+
+Arguments:
+ ImageHandle -
+ SystemTable -
+
+Returns:
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINTN PciSegmentIndex;
+ UINTN PciRootBridgeIndex;
+ UINTN PrimaryBusIndex;
+ UINTN NumberOfPciRootBridges;
+ UINTN NumberOfPciDevices;
+ UINTN Device;
+ UINTN Function;
+ UINT16 VendorId;
+ PCI_TYPE01 PciConfigurationHeader;
+ UINT64 Address;
+ UINT64 Value;
+ UINT64 Base;
+ UINT64 Limit;
+
+ //
+ // Initialize gCpuIo now since the chipset init code requires it.
+ //
+ Status = gBS->LocateProtocol (&gEfiCpuIoProtocolGuid, NULL, &gCpuIo);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize variables required to search all PCI segments for PCI devices
+ //
+ PciSegmentIndex = 0;
+ PciRootBridgeIndex = 0;
+ NumberOfPciRootBridges = 0;
+ PrimaryBusIndex = 0;
+
+ while (PciSegmentIndex <= PCI_MAX_SEGMENT) {
+
+ PrivateData = NULL;
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE),
+ &PrivateData
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ ZeroMem (PrivateData, sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE));
+
+ //
+ // Initialize the signature of the private data structure
+ //
+ PrivateData->Signature = PCAT_PCI_ROOT_BRIDGE_SIGNATURE;
+ PrivateData->Handle = NULL;
+ PrivateData->DevicePath = NULL;
+ InitializeListHead (&PrivateData->MapInfo);
+
+ //
+ // Initialize the PCI root bridge number and the bus range for that root bridge
+ //
+ PrivateData->RootBridgeNumber = (UINT32)PciRootBridgeIndex;
+ PrivateData->PrimaryBus = (UINT32)PrimaryBusIndex;
+ PrivateData->SubordinateBus = (UINT32)PrimaryBusIndex;
+
+ PrivateData->IoBase = 0xffffffff;
+ PrivateData->MemBase = 0xffffffff;
+ PrivateData->Mem32Base = 0xffffffffffffffff;
+ PrivateData->Pmem32Base = 0xffffffffffffffff;
+ PrivateData->Mem64Base = 0xffffffffffffffff;
+ PrivateData->Pmem64Base = 0xffffffffffffffff;
+
+ //
+ // The default mechanism for performing PCI Configuration cycles is to
+ // use the I/O ports at 0xCF8 and 0xCFC. This is only used for IA-32.
+ // IPF uses SAL calls to perform PCI COnfiguration cycles
+ //
+ PrivateData->PciAddress = 0xCF8;
+ PrivateData->PciData = 0xCFC;
+
+ //
+ // Get the physical I/O base for performing PCI I/O cycles
+ // For IA-32, this is always 0, because IA-32 has IN and OUT instructions
+ // For IPF, a SAL call is made to retrieve the base address for PCI I/O cycles
+ //
+ Status = PcatRootBridgeIoGetIoPortMapping (
+ &PrivateData->PhysicalIoBase,
+ &PrivateData->PhysicalMemoryBase
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Get PCI Express Base Address
+ //
+ PrivateData->PciExpressBaseAddress = GetPciExpressBaseAddressForRootBridge (PciSegmentIndex, PciRootBridgeIndex);
+ if (PrivateData->PciExpressBaseAddress != 0) {
+ DEBUG ((EFI_D_ERROR, "PCIE Base - 0x%lx\n", PrivateData->PciExpressBaseAddress));
+ }
+
+ //
+ // Create a lock for performing PCI Configuration cycles
+ //
+ EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL);
+
+ //
+ // Initialize the attributes for this PCI root bridge
+ //
+ PrivateData->Attributes = 0;
+
+ //
+ // Build the EFI Device Path Protocol instance for this PCI Root Bridge
+ //
+ Status = PcatRootBridgeDevicePathConstructor (&PrivateData->DevicePath, PciRootBridgeIndex, (PrivateData->PciExpressBaseAddress != 0) ? TRUE : FALSE);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Build the PCI Root Bridge I/O Protocol instance for this PCI Root Bridge
+ //
+ Status = PcatRootBridgeIoConstructor (&PrivateData->Io, PciSegmentIndex);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Scan all the PCI devices on the primary bus of the PCI root bridge
+ //
+ for (Device = 0, NumberOfPciDevices = 0; Device <= PCI_MAX_DEVICE; Device++) {
+
+ for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {
+
+ //
+ // Compute the PCI configuration address of the PCI device to probe
+ //
+ Address = EFI_PCI_ADDRESS (PrimaryBusIndex, Device, Function, 0);
+
+ //
+ // Read the Vendor ID from the PCI Configuration Header
+ //
+ Status = PrivateData->Io.Pci.Read (
+ &PrivateData->Io,
+ EfiPciWidthUint16,
+ Address,
+ sizeof (VendorId),
+ &VendorId
+ );
+ if ((EFI_ERROR (Status)) || ((VendorId == 0xffff) && (Function == 0))) {
+ //
+ // If the PCI Configuration Read fails, or a PCI device does not exist, then
+ // skip this entire PCI device
+ //
+ break;
+ }
+ if (VendorId == 0xffff) {
+ //
+ // If PCI function != 0, VendorId == 0xFFFF, we continue to search PCI function.
+ //
+ continue;
+ }
+
+ //
+ // Read the entire PCI Configuration Header
+ //
+ Status = PrivateData->Io.Pci.Read (
+ &PrivateData->Io,
+ EfiPciWidthUint32,
+ Address,
+ sizeof (PciConfigurationHeader) / sizeof (UINT32),
+ &PciConfigurationHeader
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If the entire PCI Configuration Header can not be read, then skip this entire PCI device
+ //
+ break;
+ }
+
+ //
+ // Increment the number of PCI device found on the primary bus of the PCI root bridge
+ //
+ NumberOfPciDevices++;
+
+ //
+ // Look for devices with the VGA Palette Snoop enabled in the COMMAND register of the PCI Config Header
+ //
+ if (PciConfigurationHeader.Hdr.Command & 0x20) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
+ }
+
+ //
+ // If the device is a PCI-PCI Bridge, then look at the Subordinate Bus Number
+ //
+ if (IS_PCI_BRIDGE(&PciConfigurationHeader)) {
+ //
+ // Get the Bus range that the PPB is decoding
+ //
+ if (PciConfigurationHeader.Bridge.SubordinateBus > PrivateData->SubordinateBus) {
+ //
+ // If the suborinate bus number of the PCI-PCI bridge is greater than the PCI root bridge's
+ // current subordinate bus number, then update the PCI root bridge's subordinate bus number
+ //
+ PrivateData->SubordinateBus = PciConfigurationHeader.Bridge.SubordinateBus;
+ }
+
+ //
+ // Get the I/O range that the PPB is decoding
+ //
+ Value = PciConfigurationHeader.Bridge.IoBase & 0x0f;
+ Base = ((UINT32)PciConfigurationHeader.Bridge.IoBase & 0xf0) << 8;
+ Limit = (((UINT32)PciConfigurationHeader.Bridge.IoLimit & 0xf0) << 8) | 0x0fff;
+ if (Value == 0x01) {
+ Base |= ((UINT32)PciConfigurationHeader.Bridge.IoBaseUpper16 << 16);
+ Limit |= ((UINT32)PciConfigurationHeader.Bridge.IoLimitUpper16 << 16);
+ }
+ if (Base < Limit) {
+ if (PrivateData->IoBase > Base) {
+ PrivateData->IoBase = Base;
+ }
+ if (PrivateData->IoLimit < Limit) {
+ PrivateData->IoLimit = Limit;
+ }
+ }
+
+ //
+ // Get the Memory range that the PPB is decoding
+ //
+ Base = ((UINT32)PciConfigurationHeader.Bridge.MemoryBase & 0xfff0) << 16;
+ Limit = (((UINT32)PciConfigurationHeader.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;
+ if (Base < Limit) {
+ if (PrivateData->MemBase > Base) {
+ PrivateData->MemBase = Base;
+ }
+ if (PrivateData->MemLimit < Limit) {
+ PrivateData->MemLimit = Limit;
+ }
+ if (PrivateData->Mem32Base > Base) {
+ PrivateData->Mem32Base = Base;
+ }
+ if (PrivateData->Mem32Limit < Limit) {
+ PrivateData->Mem32Limit = Limit;
+ }
+ }
+
+ //
+ // Get the Prefetchable Memory range that the PPB is decoding
+ //
+ Value = PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0x0f;
+ Base = ((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0xfff0) << 16;
+ Limit = (((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryLimit & 0xfff0) << 16) | 0xffffff;
+ if (Value == 0x01) {
+ Base |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableBaseUpper32,32);
+ Limit |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableLimitUpper32,32);
+ }
+ if (Base < Limit) {
+ if (PrivateData->MemBase > Base) {
+ PrivateData->MemBase = Base;
+ }
+ if (PrivateData->MemLimit < Limit) {
+ PrivateData->MemLimit = Limit;
+ }
+ if (Value == 0x00) {
+ if (PrivateData->Pmem32Base > Base) {
+ PrivateData->Pmem32Base = Base;
+ }
+ if (PrivateData->Pmem32Limit < Limit) {
+ PrivateData->Pmem32Limit = Limit;
+ }
+ }
+ if (Value == 0x01) {
+ if (PrivateData->Pmem64Base > Base) {
+ PrivateData->Pmem64Base = Base;
+ }
+ if (PrivateData->Pmem64Limit < Limit) {
+ PrivateData->Pmem64Limit = Limit;
+ }
+ }
+ }
+
+ //
+ // Look at the PPB Configuration for legacy decoding attributes
+ //
+ if (PciConfigurationHeader.Bridge.BridgeControl & 0x04) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
+ }
+ if (PciConfigurationHeader.Bridge.BridgeControl & 0x08) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
+ }
+
+ } else {
+ //
+ // Parse the BARs of the PCI device to determine what I/O Ranges,
+ // Memory Ranges, and Prefetchable Memory Ranges the device is decoding
+ //
+ if ((PciConfigurationHeader.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {
+ Status = PcatPciRootBridgeParseBars (
+ PrivateData,
+ PciConfigurationHeader.Hdr.Command,
+ PrimaryBusIndex,
+ Device,
+ Function
+ );
+ }
+
+ //
+ // See if the PCI device is an IDE controller
+ //
+ if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x01 &&
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) {
+ if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x80) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
+ }
+ if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x01) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
+ }
+ if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x04) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
+ }
+ }
+
+ //
+ // See if the PCI device is a legacy VGA controller
+ //
+ if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x00 &&
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
+ }
+
+ //
+ // See if the PCI device is a standard VGA controller
+ //
+ if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x03 &&
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x00 ) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
+ }
+
+ //
+ // See if the PCI Device is a PCI - ISA or PCI - EISA
+ // or ISA_POSITIVIE_DECODE Bridge device
+ //
+ if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x06) {
+ if (PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ||
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x02 ||
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x80 ) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
+
+ if (PrivateData->MemBase > 0xa0000) {
+ PrivateData->MemBase = 0xa0000;
+ }
+ if (PrivateData->MemLimit < 0xbffff) {
+ PrivateData->MemLimit = 0xbffff;
+ }
+ }
+ }
+ }
+
+ //
+ // If this device is not a multi function device, then skip the rest of this PCI device
+ //
+ if (Function == 0 && !(PciConfigurationHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) {
+ break;
+ }
+ }
+ }
+
+ //
+ // After scanning all the PCI devices on the PCI root bridge's primary bus, update the
+ // Primary Bus Number for the next PCI root bridge to be this PCI root bridge's subordinate
+ // bus number + 1.
+ //
+ PrimaryBusIndex = PrivateData->SubordinateBus + 1;
+
+ //
+ // If at least one PCI device was found on the primary bus of this PCI root bridge, then the PCI root bridge
+ // exists.
+ //
+ if (NumberOfPciDevices > 0) {
+
+ //
+ // Adjust the I/O range used for bounds checking for the legacy decoding attributed
+ //
+ if (PrivateData->Attributes & 0x7f) {
+ PrivateData->IoBase = 0;
+ if (PrivateData->IoLimit < 0xffff) {
+ PrivateData->IoLimit = 0xffff;
+ }
+ }
+
+ //
+ // Adjust the Memory range used for bounds checking for the legacy decoding attributed
+ //
+ if (PrivateData->Attributes & EFI_PCI_ATTRIBUTE_VGA_MEMORY) {
+ if (PrivateData->MemBase > 0xa0000) {
+ PrivateData->MemBase = 0xa0000;
+ }
+ if (PrivateData->MemLimit < 0xbffff) {
+ PrivateData->MemLimit = 0xbffff;
+ }
+ }
+
+ //
+ // Build ACPI descriptors for the resources on the PCI Root Bridge
+ //
+ Status = ConstructConfiguration(PrivateData);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Create the handle for this PCI Root Bridge
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &PrivateData->Handle,
+ &gEfiDevicePathProtocolGuid,
+ PrivateData->DevicePath,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ &PrivateData->Io,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Contruct DeviceIoProtocol
+ //
+ Status = DeviceIoConstructor (
+ PrivateData->Handle,
+ &PrivateData->Io,
+ PrivateData->DevicePath,
+ (UINT16)PrivateData->PrimaryBus,
+ (UINT16)PrivateData->SubordinateBus
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Scan this PCI Root Bridge for PCI Option ROMs and add them to the PCI Option ROM Table
+ //
+ Status = ScanPciRootBridgeForRoms(&PrivateData->Io);
+
+ //
+ // Increment the index for the next PCI Root Bridge
+ //
+ PciRootBridgeIndex++;
+
+ } else {
+
+ //
+ // If no PCI Root Bridges were found on the current PCI segment, then exit
+ //
+ if (NumberOfPciRootBridges == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ }
+
+ //
+ // If the PrimaryBusIndex is greater than the maximum allowable PCI bus number, then
+ // the PCI Segment Number is incremented, and the next segment is searched starting at Bus #0
+ // Otherwise, the search is continued on the next PCI Root Bridge
+ //
+ if (PrimaryBusIndex > PCI_MAX_BUS) {
+ PciSegmentIndex++;
+ NumberOfPciRootBridges = 0;
+ PrimaryBusIndex = 0;
+ } else {
+ NumberOfPciRootBridges++;
+ }
+
+ }
+
+ return EFI_SUCCESS;
+
+Done:
+ //
+ // Clean up memory allocated for the PCI Root Bridge that was searched but not created.
+ //
+ if (PrivateData) {
+ if (PrivateData->DevicePath) {
+ gBS->FreePool(PrivateData->DevicePath);
+ }
+ gBS->FreePool (PrivateData);
+ }
+
+ //
+ // If no PCI Root Bridges were discovered, then return the error condition from scanning the
+ // first PCI Root Bridge
+ //
+ if (PciRootBridgeIndex == 0) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ConstructConfiguration(
+ IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+
+{
+ EFI_STATUS Status;
+ UINT8 NumConfig;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
+ EFI_ACPI_END_TAG_DESCRIPTOR *ConfigurationEnd;
+
+ NumConfig = 0;
+ PrivateData->Configuration = NULL;
+
+ if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {
+ NumConfig++;
+ }
+ if (PrivateData->IoLimit >= PrivateData->IoBase) {
+ NumConfig++;
+ }
+ if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {
+ NumConfig++;
+ }
+ if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {
+ NumConfig++;
+ }
+ if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {
+ NumConfig++;
+ }
+ if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {
+ NumConfig++;
+ }
+
+ if ( NumConfig == 0 ) {
+
+ //
+ // If there is no resource request
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
+ &PrivateData->Configuration
+ );
+ if (EFI_ERROR (Status )) {
+ return Status;
+ }
+
+ Configuration = PrivateData->Configuration;
+
+ ZeroMem (
+ Configuration,
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
+ );
+
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration++;
+
+ ConfigurationEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);
+ ConfigurationEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
+ ConfigurationEnd->Checksum = 0;
+ }
+
+ //
+ // If there is at least one type of resource request,
+ // allocate a acpi resource node
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
+ &PrivateData->Configuration
+ );
+ if (EFI_ERROR (Status )) {
+ return Status;
+ }
+
+ Configuration = PrivateData->Configuration;
+
+ ZeroMem (
+ Configuration,
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
+ );
+
+ if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
+ Configuration->SpecificFlag = 0;
+ Configuration->AddrRangeMin = PrivateData->PrimaryBus;
+ Configuration->AddrRangeMax = PrivateData->SubordinateBus;
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+ Configuration++;
+ }
+ //
+ // Deal with io aperture
+ //
+ if (PrivateData->IoLimit >= PrivateData->IoBase) {
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
+ Configuration->SpecificFlag = 1; //non ISA range
+ Configuration->AddrRangeMin = PrivateData->IoBase;
+ Configuration->AddrRangeMax = PrivateData->IoLimit;
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+ Configuration++;
+ }
+
+ //
+ // Deal with mem32 aperture
+ //
+ if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Configuration->SpecificFlag = 0; //Nonprefechable
+ Configuration->AddrSpaceGranularity = 32; //32 bit
+ Configuration->AddrRangeMin = PrivateData->Mem32Base;
+ Configuration->AddrRangeMax = PrivateData->Mem32Limit;
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+ Configuration++;
+ }
+
+ //
+ // Deal with Pmem32 aperture
+ //
+ if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Configuration->SpecificFlag = 0x6; //prefechable
+ Configuration->AddrSpaceGranularity = 32; //32 bit
+ Configuration->AddrRangeMin = PrivateData->Pmem32Base;
+ Configuration->AddrRangeMax = PrivateData->Pmem32Limit;
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+ Configuration++;
+ }
+
+ //
+ // Deal with mem64 aperture
+ //
+ if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Configuration->SpecificFlag = 0; //nonprefechable
+ Configuration->AddrSpaceGranularity = 64; //32 bit
+ Configuration->AddrRangeMin = PrivateData->Mem64Base;
+ Configuration->AddrRangeMax = PrivateData->Mem64Limit;
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+ Configuration++;
+ }
+
+ //
+ // Deal with Pmem64 aperture
+ //
+ if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Configuration->SpecificFlag = 0x06; //prefechable
+ Configuration->AddrSpaceGranularity = 64; //32 bit
+ Configuration->AddrRangeMin = PrivateData->Pmem64Base;
+ Configuration->AddrRangeMax = PrivateData->Pmem64Limit;
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+ Configuration++;
+ }
+
+ //
+ // put the checksum
+ //
+ ConfigurationEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);
+ ConfigurationEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
+ ConfigurationEnd->Checksum = 0;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatPciRootBridgeBarExisted (
+ IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT64 Address,
+ OUT UINT32 *OriginalValue,
+ OUT UINT32 *Value
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 AllOnes;
+ EFI_TPL OldTpl;
+
+ //
+ // Preserve the original value
+ //
+ Status = PrivateData->Io.Pci.Read (
+ &PrivateData->Io,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ OriginalValue
+ );
+
+ //
+ // Raise TPL to high level to disable timer interrupt while the BAR is probed
+ //
+ OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+ AllOnes = 0xffffffff;
+
+ Status = PrivateData->Io.Pci.Write (
+ &PrivateData->Io,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ &AllOnes
+ );
+ Status = PrivateData->Io.Pci.Read (
+ &PrivateData->Io,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ Value
+ );
+
+ //
+ //Write back the original value
+ //
+ Status = PrivateData->Io.Pci.Write (
+ &PrivateData->Io,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ OriginalValue
+ );
+
+ //
+ // Restore TPL to its original level
+ //
+ gBS->RestoreTPL (OldTpl);
+
+ if ( *Value == 0 ) {
+ return EFI_DEVICE_ERROR;
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatPciRootBridgeParseBars (
+ IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT16 Command,
+ IN UINTN Bus,
+ IN UINTN Device,
+ IN UINTN Function
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT64 Address;
+ UINT32 OriginalValue;
+ UINT32 Value;
+ UINT32 OriginalUpperValue;
+ UINT32 UpperValue;
+ UINT64 Mask;
+ UINTN Offset;
+ UINT64 Base;
+ UINT64 Length;
+ UINT64 Limit;
+
+ for (Offset = 0x10; Offset < 0x28; Offset += 4) {
+ Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);
+ Status = PcatPciRootBridgeBarExisted (
+ PrivateData,
+ Address,
+ &OriginalValue,
+ &Value
+ );
+
+ if (!EFI_ERROR (Status )) {
+ if ( Value & 0x01 ) {
+ if (Command & 0x0001) {
+ //
+ //Device I/Os
+ //
+ Mask = 0xfffffffc;
+ Base = OriginalValue & Mask;
+ Length = ((~(Value & Mask)) & Mask) + 0x04;
+ if (!(Value & 0xFFFF0000)){
+ Length &= 0x0000FFFF;
+ }
+ Limit = Base + Length - 1;
+
+ if (Base < Limit) {
+ if (PrivateData->IoBase > Base) {
+ PrivateData->IoBase = (UINT32)Base;
+ }
+ if (PrivateData->IoLimit < Limit) {
+ PrivateData->IoLimit = (UINT32)Limit;
+ }
+ }
+ }
+
+ } else {
+
+ if (Command & 0x0002) {
+
+ Mask = 0xfffffff0;
+ Base = OriginalValue & Mask;
+ Length = Value & Mask;
+
+ if ((Value & 0x07) != 0x04) {
+ Length = ((~Length) + 1) & 0xffffffff;
+ } else {
+ Offset += 4;
+ Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);
+
+ Status = PcatPciRootBridgeBarExisted (
+ PrivateData,
+ Address,
+ &OriginalUpperValue,
+ &UpperValue
+ );
+
+ Base = Base | LShiftU64((UINT64)OriginalUpperValue,32);
+ Length = Length | LShiftU64((UINT64)UpperValue,32);
+ Length = (~Length) + 1;
+ }
+
+ Limit = Base + Length - 1;
+
+ if (Base < Limit) {
+ if (PrivateData->MemBase > Base) {
+ PrivateData->MemBase = Base;
+ }
+ if (PrivateData->MemLimit < Limit) {
+ PrivateData->MemLimit = Limit;
+ }
+
+ switch (Value &0x07) {
+ case 0x00: ////memory space; anywhere in 32 bit address space
+ if (Value & 0x08) {
+ if (PrivateData->Pmem32Base > Base) {
+ PrivateData->Pmem32Base = Base;
+ }
+ if (PrivateData->Pmem32Limit < Limit) {
+ PrivateData->Pmem32Limit = Limit;
+ }
+ } else {
+ if (PrivateData->Mem32Base > Base) {
+ PrivateData->Mem32Base = Base;
+ }
+ if (PrivateData->Mem32Limit < Limit) {
+ PrivateData->Mem32Limit = Limit;
+ }
+ }
+ break;
+ case 0x04: //memory space; anywhere in 64 bit address space
+ if (Value & 0x08) {
+ if (PrivateData->Pmem64Base > Base) {
+ PrivateData->Pmem64Base = Base;
+ }
+ if (PrivateData->Pmem64Limit < Limit) {
+ PrivateData->Pmem64Limit = Limit;
+ }
+ } else {
+ if (PrivateData->Mem64Base > Base) {
+ PrivateData->Mem64Base = Base;
+ }
+ if (PrivateData->Mem64Limit < Limit) {
+ PrivateData->Mem64Limit = Limit;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+UINT64
+GetPciExpressBaseAddressForRootBridge (
+ IN UINTN HostBridgeNumber,
+ IN UINTN RootBridgeNumber
+ )
+/*++
+
+Routine Description:
+ This routine is to get PciExpress Base Address for this RootBridge
+
+Arguments:
+ HostBridgeNumber - The number of HostBridge
+ RootBridgeNumber - The number of RootBridge
+
+Returns:
+ UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge
+
+--*/
+{
+ EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION *PciExpressBaseAddressInfo;
+ UINTN BufferSize;
+ UINT32 Index;
+ UINT32 Number;
+ VOID *HobList;
+ EFI_STATUS Status;
+ EFI_PEI_HOB_POINTERS GuidHob;
+
+ //
+ // Get Hob List from configuration table
+ //
+ Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);
+ if (EFI_ERROR (Status)) {
+ return 0;
+ }
+
+ //
+ // Get PciExpressAddressInfo Hob
+ //
+ PciExpressBaseAddressInfo = NULL;
+ BufferSize = 0;
+ GuidHob.Raw = GetNextGuidHob (&gEfiPciExpressBaseAddressGuid, &HobList);
+ if (GuidHob.Raw != NULL) {
+ PciExpressBaseAddressInfo = GET_GUID_HOB_DATA (GuidHob.Guid);
+ BufferSize = GET_GUID_HOB_DATA_SIZE (GuidHob.Guid);
+ } else {
+ return 0;
+ }
+
+ //
+ // Search the PciExpress Base Address in the Hob for current RootBridge
+ //
+ Number = (UINT32)(BufferSize / sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION));
+ for (Index = 0; Index < Number; Index++) {
+ if ((PciExpressBaseAddressInfo[Index].HostBridgeNumber == HostBridgeNumber) &&
+ (PciExpressBaseAddressInfo[Index].RootBridgeNumber == RootBridgeNumber)) {
+ return PciExpressBaseAddressInfo[Index].PciExpressBaseAddress;
+ }
+ }
+
+ //
+ // Do not find the PciExpress Base Address in the Hob
+ //
+ return 0;
+}
+