--- /dev/null
+/** @file\r
+ This module is one template module for Incompatible PCI Device Support protocol.\r
+ It includes one incompatile pci devices list template.\r
+ \r
+ Incompatible PCI Device Support protocol allows the PCI bus driver to support\r
+ resource allocation for some PCI devices that do not comply with the PCI Specification.\r
+\r
+Copyright (c) 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
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <Protocol/IncompatiblePciDeviceSupport.h>\r
+\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+#include <IndustryStandard/Pci.h>\r
+#include <IndustryStandard/Acpi.h>\r
+\r
+typedef struct {\r
+ UINT64 VendorId;\r
+ UINT64 DeviceId;\r
+ UINT64 RevisionId;\r
+ UINT64 SubsystemVendorId;\r
+ UINT64 SubsystemDeviceId;\r
+} EFI_PCI_DEVICE_HEADER_INFO;\r
+\r
+typedef struct {\r
+ UINT64 ResType;\r
+ UINT64 GenFlag;\r
+ UINT64 SpecificFlag;\r
+ UINT64 AddrSpaceGranularity;\r
+ UINT64 AddrRangeMin;\r
+ UINT64 AddrRangeMax;\r
+ UINT64 AddrTranslationOffset;\r
+ UINT64 AddrLen;\r
+} EFI_PCI_RESOUCE_DESCRIPTOR;\r
+\r
+#define PCI_DEVICE_ID(VendorId, DeviceId, Revision, SubVendorId, SubDeviceId) \\r
+ VendorId, DeviceId, Revision, SubVendorId, SubDeviceId\r
+\r
+#define PCI_BAR_TYPE_IO ACPI_ADDRESS_SPACE_TYPE_IO\r
+#define PCI_BAR_TYPE_MEM ACPI_ADDRESS_SPACE_TYPE_MEM\r
+\r
+#define DEVICE_INF_TAG 0xFFF2\r
+#define DEVICE_RES_TAG 0xFFF1\r
+#define LIST_END_TAG 0x0000\r
+\r
+\r
+/**\r
+ Returns a list of ACPI resource descriptors that detail the special\r
+ resource configuration requirements for an incompatible PCI device.\r
+\r
+ @param This Pointer to the EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL instance.\r
+ @param VendorId A unique ID to identify the manufacturer of the PCI device.\r
+ @param DeviceId A unique ID to identify the particular PCI device.\r
+ @param RevisionId A PCI device-specific revision identifier.\r
+ @param SubsystemVendorId Specifies the subsystem vendor ID.\r
+ @param SubsystemDeviceId Specifies the subsystem device ID.\r
+ @param Configuration A list of ACPI resource descriptors returned that detail\r
+ the configuration requirement.\r
+\r
+ @retval EFI_SUCCESS Successfully got ACPI resource for specified PCI device.\r
+ @retval EFI_INVALID_PARAMETER Configuration is NULL. \r
+ @retval EFI_OUT_OF_RESOURCES No memory available.\r
+ @retval EFI_UNSUPPORTED The specified PCI device wasn't supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PCheckDevice (\r
+ IN EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL *This,\r
+ IN UINTN VendorId,\r
+ IN UINTN DeviceId,\r
+ IN UINTN RevisionId,\r
+ IN UINTN SubsystemVendorId,\r
+ IN UINTN SubsystemDeviceId,\r
+ OUT VOID **Configuration\r
+ );\r
+\r
+//\r
+// Handle onto which the Incompatible PCI Device List is installed\r
+//\r
+EFI_HANDLE mIncompatiblePciDeviceSupportHandle = NULL;\r
+\r
+//\r
+// The Incompatible PCI Device Support Protocol instance produced by this driver\r
+//\r
+EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL mIncompatiblePciDeviceSupport = {\r
+ PCheckDevice\r
+};\r
+\r
+//\r
+// The incompatible PCI devices list template\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED UINT64 mIncompatiblePciDeviceList[] = {\r
+ //\r
+ // DEVICE_INF_TAG,\r
+ // PCI_DEVICE_ID (VendorID, DeviceID, Revision, SubVendorId, SubDeviceId),\r
+ // DEVICE_RES_TAG,\r
+ // ResType, GFlag , SFlag, Granularity, RangeMin,\r
+ // RangeMax, Offset, AddrLen\r
+ //\r
+ //\r
+ // Device Adaptec 9004\r
+ //\r
+ DEVICE_INF_TAG,\r
+ PCI_DEVICE_ID(0x9004, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE),\r
+ DEVICE_RES_TAG,\r
+ PCI_BAR_TYPE_IO,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_BAR_EVEN_ALIGN,\r
+ PCI_BAR_ALL,\r
+ PCI_BAR_NOCHANGE,\r
+ //\r
+ // Device Adaptec 9005\r
+ //\r
+ DEVICE_INF_TAG,\r
+ PCI_DEVICE_ID(0x9005, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE),\r
+ DEVICE_RES_TAG,\r
+ PCI_BAR_TYPE_IO,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_BAR_EVEN_ALIGN,\r
+ PCI_BAR_ALL,\r
+ PCI_BAR_NOCHANGE,\r
+ //\r
+ // Device QLogic 1007\r
+ //\r
+ DEVICE_INF_TAG,\r
+ PCI_DEVICE_ID(0x1077, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE),\r
+ DEVICE_RES_TAG,\r
+ PCI_BAR_TYPE_IO,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_BAR_EVEN_ALIGN,\r
+ PCI_BAR_ALL,\r
+ PCI_BAR_NOCHANGE,\r
+ //\r
+ // Device Agilent 103C\r
+ //\r
+ DEVICE_INF_TAG,\r
+ PCI_DEVICE_ID(0x103C, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE),\r
+ DEVICE_RES_TAG,\r
+ PCI_BAR_TYPE_IO,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_BAR_EVEN_ALIGN,\r
+ PCI_BAR_ALL,\r
+ PCI_BAR_NOCHANGE,\r
+ //\r
+ // Device Agilent 15BC\r
+ //\r
+ DEVICE_INF_TAG,\r
+ PCI_DEVICE_ID(0x15BC, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE),\r
+ DEVICE_RES_TAG,\r
+ PCI_BAR_TYPE_IO,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_ACPI_UNUSED,\r
+ PCI_BAR_EVEN_ALIGN,\r
+ PCI_BAR_ALL,\r
+ PCI_BAR_NOCHANGE,\r
+ //\r
+ // The end of the list\r
+ //\r
+ LIST_END_TAG\r
+};\r
+\r
+\r
+/**\r
+ Entry point of the incompatible pci device support code. Setup an incompatible device list template\r
+ and install EFI Incompatible PCI Device Support protocol.\r
+\r
+ @param ImageHandle A handle for the image that is initializing this driver.\r
+ @param SystemTable A pointer to the EFI system table.\r
+\r
+ @retval EFI_SUCCESS Installed EFI Incompatible PCI Device Support Protocol successfully.\r
+ @retval others Failed to install protocol.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IncompatiblePciDeviceSupportEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Install EFI Incompatible PCI Device Support Protocol on a new handle\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &mIncompatiblePciDeviceSupportHandle,\r
+ &gEfiIncompatiblePciDeviceSupportProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &mIncompatiblePciDeviceSupport\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Returns a list of ACPI resource descriptors that detail the special\r
+ resource configuration requirements for an incompatible PCI device.\r
+\r
+ @param This Pointer to the EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL instance.\r
+ @param VendorId A unique ID to identify the manufacturer of the PCI device.\r
+ @param DeviceId A unique ID to identify the particular PCI device.\r
+ @param RevisionId A PCI device-specific revision identifier.\r
+ @param SubsystemVendorId Specifies the subsystem vendor ID.\r
+ @param SubsystemDeviceId Specifies the subsystem device ID.\r
+ @param Configuration A list of ACPI resource descriptors returned that detail\r
+ the configuration requirement.\r
+\r
+ @retval EFI_SUCCESS Successfully got ACPI resource for specified PCI device.\r
+ @retval EFI_INVALID_PARAMETER Configuration is NULL. \r
+ @retval EFI_OUT_OF_RESOURCES No memory available.\r
+ @retval EFI_UNSUPPORTED The specified PCI device wasn't supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PCheckDevice (\r
+ IN EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL *This,\r
+ IN UINTN VendorId,\r
+ IN UINTN DeviceId,\r
+ IN UINTN RevisionId,\r
+ IN UINTN SubsystemVendorId,\r
+ IN UINTN SubsystemDeviceId,\r
+ OUT VOID **Configuration\r
+ )\r
+{\r
+ UINT64 Tag;\r
+ UINT64 *ListPtr;\r
+ UINT64 *TempListPtr;\r
+ EFI_PCI_DEVICE_HEADER_INFO *Header;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *AcpiPtr;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *OldAcpiPtr;\r
+ EFI_PCI_RESOUCE_DESCRIPTOR *Dsc;\r
+ EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;\r
+ UINTN Index;\r
+\r
+ //\r
+ // Validate the parameters\r
+ //\r
+ if (Configuration == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Initialize the return value to NULL\r
+ //\r
+ * (VOID **) Configuration = NULL;\r
+\r
+ ListPtr = mIncompatiblePciDeviceList;\r
+ while (*ListPtr != LIST_END_TAG) {\r
+\r
+ Tag = *ListPtr;\r
+\r
+ switch (Tag) {\r
+ case DEVICE_INF_TAG:\r
+ Header = (EFI_PCI_DEVICE_HEADER_INFO *) (ListPtr + 1);\r
+ ListPtr = ListPtr + 1 + sizeof (EFI_PCI_DEVICE_HEADER_INFO) / sizeof (UINT64);\r
+ //\r
+ // See if the Header matches the parameters passed in\r
+ //\r
+ if (Header->VendorId != DEVICE_ID_NOCARE) {\r
+ if (Header->VendorId != VendorId) {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (Header->DeviceId != DEVICE_ID_NOCARE) {\r
+ if (DeviceId != Header->DeviceId) {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (Header->RevisionId != DEVICE_ID_NOCARE) {\r
+ if (RevisionId != Header->RevisionId) {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (Header->SubsystemVendorId != DEVICE_ID_NOCARE) {\r
+ if (SubsystemVendorId != Header->SubsystemVendorId) {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (Header->SubsystemDeviceId != DEVICE_ID_NOCARE) {\r
+ if (SubsystemDeviceId != Header->SubsystemDeviceId) {\r
+ continue;\r
+ }\r
+ }\r
+ //\r
+ // Matched an item, so construct the ACPI descriptor for the resource.\r
+ //\r
+ //\r
+ // Count the resource items so that to allocate space\r
+ //\r
+ for (Index = 0, TempListPtr = ListPtr; *TempListPtr == DEVICE_RES_TAG; Index++) {\r
+ TempListPtr = TempListPtr + 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR)) / sizeof (UINT64));\r
+ }\r
+ //\r
+ // If there is at least one type of resource request,\r
+ // allocate an acpi resource node\r
+ //\r
+ if (Index == 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ AcpiPtr = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * Index + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
+ if (AcpiPtr == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ OldAcpiPtr = AcpiPtr;\r
+ //\r
+ // Fill the EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR structure\r
+ // according to the EFI_PCI_RESOUCE_DESCRIPTOR structure\r
+ //\r
+ for (; *ListPtr == DEVICE_RES_TAG;) {\r
+\r
+ Dsc = (EFI_PCI_RESOUCE_DESCRIPTOR *) (ListPtr + 1);\r
+\r
+ AcpiPtr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ AcpiPtr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
+ AcpiPtr->ResType = (UINT8) Dsc->ResType;\r
+ AcpiPtr->GenFlag = (UINT8) Dsc->GenFlag;\r
+ AcpiPtr->SpecificFlag = (UINT8) Dsc->SpecificFlag;\r
+ AcpiPtr->AddrSpaceGranularity = Dsc->AddrSpaceGranularity;;\r
+ AcpiPtr->AddrRangeMin = Dsc->AddrRangeMin;\r
+ AcpiPtr->AddrRangeMax = Dsc->AddrRangeMax;\r
+ AcpiPtr->AddrTranslationOffset = Dsc->AddrTranslationOffset;\r
+ AcpiPtr->AddrLen = Dsc->AddrLen;\r
+\r
+ ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR)) / sizeof (UINT64));\r
+ AcpiPtr++;\r
+ }\r
+ //\r
+ // Put the checksum\r
+ //\r
+ PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) (AcpiPtr);\r
+ PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+ PtrEnd->Checksum = 0;\r
+\r
+ *(VOID **) Configuration = OldAcpiPtr;\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ case DEVICE_RES_TAG:\r
+ //\r
+ // Adjust the pointer to the next PCI resource descriptor item\r
+ //\r
+ ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR)) / sizeof (UINT64));\r
+ break;\r
+\r
+ default:\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
--- /dev/null
+#/** @file\r
+# PCI Incompatible device support module template.\r
+#\r
+# Installs EFI PCI Incompatible Device Support protocol and includes one incompatile \r
+# pci devices list template.\r
+#\r
+# Copyright (c) 2009, Intel Corporation.\r
+#\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
+# 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 = IncompatiblePciDeviceSupport\r
+ FILE_GUID = AD70855E-0CC5-4abf-8979-BE762A949EA3\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ ENTRY_POINT = IncompatiblePciDeviceSupportEntryPoint\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+ IncompatiblePciDeviceSupport.c\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+\r
+[LibraryClasses]\r
+ UefiDriverEntryPoint\r
+ UefiBootServicesTableLib\r
+ MemoryAllocationLib\r
+ DebugLib\r
+\r
+[Protocols]\r
+ gEfiIncompatiblePciDeviceSupportProtocolGuid ## PRODUCEDS\r
+\r
+[Depex]\r
+ TRUE\r
--- /dev/null
+/** @file\r
+ EFI Component Name functions implementation 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
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName = {\r
+ PciBusComponentNameGetDriverName,\r
+ PciBusComponentNameGetControllerName,\r
+ "eng"\r
+};\r
+\r
+//\r
+// EFI Component Name 2 Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gPciBusComponentName2 = {\r
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) PciBusComponentNameGetDriverName,\r
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) PciBusComponentNameGetControllerName,\r
+ "en"\r
+};\r
+\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mPciBusDriverNameTable[] = {\r
+ { "eng;en", (CHAR16 *) L"PCI Bus Driver" },\r
+ { NULL , NULL }\r
+};\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+ This function retrieves the user readable name of a driver in the form of a\r
+ Unicode string. If the driver specified by This has a user readable name in\r
+ the language specified by Language, then a pointer to the driver name is\r
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+ by This does not support the language specified by Language,\r
+ then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified\r
+ in RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param DriverName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ driver specified by This in the language\r
+ specified by Language.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by\r
+ This and the language specified by Language was\r
+ returned in DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ )\r
+{\r
+ return LookupUnicodeString2 (\r
+ Language,\r
+ This->SupportedLanguages,\r
+ mPciBusDriverNameTable,\r
+ DriverName,\r
+ (BOOLEAN)(This == &gPciBusComponentName)\r
+ );\r
+}\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by a driver.\r
+\r
+ This function retrieves the user readable name of the controller specified by\r
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+ driver specified by This has a user readable name in the language specified by\r
+ Language, then a pointer to the controller name is returned in ControllerName,\r
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently\r
+ managing the controller specified by ControllerHandle and ChildHandle,\r
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not\r
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param ControllerHandle[in] The handle of a controller that the driver\r
+ specified by This is managing. This handle\r
+ specifies the controller whose name is to be\r
+ returned.\r
+\r
+ @param ChildHandle[in] The handle of the child controller to retrieve\r
+ the name of. This is an optional parameter that\r
+ may be NULL. It will be NULL for device\r
+ drivers. It will also be NULL for a bus drivers\r
+ that wish to retrieve the name of the bus\r
+ controller. It will not be NULL for a bus\r
+ driver that wishes to retrieve the name of a\r
+ child controller.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified in\r
+ RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param ControllerName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ controller specified by ControllerHandle and\r
+ ChildHandle in the language specified by\r
+ Language from the point of view of the driver\r
+ specified by This.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the user readable name in\r
+ the language specified by Language for the\r
+ driver specified by This was returned in\r
+ DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+ EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently\r
+ managing the controller specified by\r
+ ControllerHandle and ChildHandle.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
--- /dev/null
+/** @file\r
+ EFI Component Name functions declaration 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
+\r
+**/\r
+\r
+\r
+#ifndef _EFI_PCI_BUS_COMPONENT_NAME_H_\r
+#define _EFI_PCI_BUS_COMPONENT_NAME_H_\r
+\r
+extern EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL gPciBusComponentName2;\r
+\r
+//\r
+// EFI Component Name Functions\r
+//\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+ This function retrieves the user readable name of a driver in the form of a\r
+ Unicode string. If the driver specified by This has a user readable name in\r
+ the language specified by Language, then a pointer to the driver name is\r
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+ by This does not support the language specified by Language,\r
+ then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified\r
+ in RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param DriverName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ driver specified by This in the language\r
+ specified by Language.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by\r
+ This and the language specified by Language was\r
+ returned in DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ );\r
+\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by a driver.\r
+\r
+ This function retrieves the user readable name of the controller specified by\r
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+ driver specified by This has a user readable name in the language specified by\r
+ Language, then a pointer to the controller name is returned in ControllerName,\r
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently\r
+ managing the controller specified by ControllerHandle and ChildHandle,\r
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not\r
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param ControllerHandle[in] The handle of a controller that the driver\r
+ specified by This is managing. This handle\r
+ specifies the controller whose name is to be\r
+ returned.\r
+\r
+ @param ChildHandle[in] The handle of the child controller to retrieve\r
+ the name of. This is an optional parameter that\r
+ may be NULL. It will be NULL for device\r
+ drivers. It will also be NULL for a bus drivers\r
+ that wish to retrieve the name of the bus\r
+ controller. It will not be NULL for a bus\r
+ driver that wishes to retrieve the name of a\r
+ child controller.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified in\r
+ RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param ControllerName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ controller specified by ControllerHandle and\r
+ ChildHandle in the language specified by\r
+ Language from the point of view of the driver\r
+ specified by This.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the user readable name in\r
+ the language specified by Language for the\r
+ driver specified by This was returned in\r
+ DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+ EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently\r
+ managing the controller specified by\r
+ ControllerHandle and ChildHandle.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ );\r
+\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Driver Binding functions for PCI Bus module.\r
+\r
+ Single PCI bus driver instance will manager all PCI Root Bridges in one EFI based firmware,\r
+ since all PCI Root Bridges' resources need to be managed together.\r
+ Supported() function will try to get PCI Root Bridge IO Protocol.\r
+ Start() function will get PCI Host Bridge Resource Allocation Protocol to manage all\r
+ PCI Root Bridges. So it means platform needs install PCI Root Bridge IO protocol for each\r
+ PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol.\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
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+//\r
+// PCI Bus Driver Global Variables\r
+//\r
+EFI_DRIVER_BINDING_PROTOCOL gPciBusDriverBinding = {\r
+ PciBusDriverBindingSupported,\r
+ PciBusDriverBindingStart,\r
+ PciBusDriverBindingStop,\r
+ 0xa,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+EFI_HANDLE gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM];\r
+EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL *gEfiIncompatiblePciDeviceSupport = NULL;\r
+UINTN gPciHostBridgeNumber = 0;\r
+BOOLEAN gFullEnumeration = TRUE;\r
+UINT64 gAllOne = 0xFFFFFFFFFFFFFFFFULL;\r
+UINT64 gAllZero = 0;\r
+\r
+EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol;\r
+EFI_PCI_OVERRIDE_PROTOCOL *gPciOverrideProtocol;\r
+\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL mPciHotPlugRequest = {\r
+ PciHotPlugRequestNotify\r
+};\r
+\r
+/**\r
+ The Entry Point for PCI Bus module. The user code starts with this function.\r
+\r
+ Installs driver module protocols and. Creates virtual device handles for ConIn,\r
+ ConOut, and StdErr. Installs Simple Text In protocol, Simple Text In Ex protocol,\r
+ Simple Pointer protocol, Absolute Pointer protocol on those virtual handlers.\r
+ Installs Graphics Output protocol and/or UGA Draw protocol if needed.\r
+\r
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
+ @param[in] SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The entry point is executed successfully.\r
+ @retval other Some error occurred when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
+\r
+ //\r
+ // Initializes PCI devices pool\r
+ //\r
+ InitializePciDevicePool ();\r
+\r
+ //\r
+ // Install driver model protocol(s).\r
+ //\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gPciBusDriverBinding,\r
+ ImageHandle,\r
+ &gPciBusComponentName,\r
+ &gPciBusComponentName2\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+ //\r
+ // If Hot Plug is supported, install EFI PCI Hot Plug Request protocol.\r
+ //\r
+ Handle = NULL;\r
+ Status = gBS->InstallProtocolInterface (\r
+ &Handle,\r
+ &gEfiPciHotPlugRequestProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &mPciHotPlugRequest\r
+ );\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
+ than contains a gEfiPciRootBridgeIoProtocolGuid protocol can be supported.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Controller Handle of device to test.\r
+ @param RemainingDevicePath Optional parameter use to pick a specific child.\r
+ device to start.\r
+\r
+ @retval EFI_SUCCESS This driver supports this device.\r
+ @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
+ @retval other This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusDriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+ EFI_DEV_PATH_PTR Node;\r
+\r
+ //\r
+ // Check RemainingDevicePath validation\r
+ //\r
+ if (RemainingDevicePath != NULL) {\r
+ //\r
+ // Check if RemainingDevicePath is the End of Device Path Node, \r
+ // if yes, go on checking other conditions\r
+ //\r
+ if (!IsDevicePathEnd (RemainingDevicePath)) {\r
+ //\r
+ // If RemainingDevicePath isn't the End of Device Path Node,\r
+ // check its validation\r
+ //\r
+ Node.DevPath = RemainingDevicePath;\r
+ if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||\r
+ Node.DevPath->SubType != HW_PCI_DP ||\r
+ DevicePathNodeLength(Node.DevPath) != sizeof(PCI_DEVICE_PATH)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Check if Pci Root Bridge IO protocol is installed by platform\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciRootBridgeIoProtocolGuid,\r
+ (VOID **) &PciRootBridgeIo,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (Status == EFI_ALREADY_STARTED) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Close the I/O Abstraction(s) used to perform the supported test\r
+ //\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiPciRootBridgeIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ //\r
+ // Open the EFI Device Path protocol needed to perform the supported test\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &ParentDevicePath,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (Status == EFI_ALREADY_STARTED) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Close protocol, don't use device path protocol in the Support() function\r
+ //\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Start this driver on ControllerHandle and enumerate Pci bus and start\r
+ all device under PCI bus.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Controller Handle of device to bind driver to.\r
+ @param RemainingDevicePath Optional parameter use to pick a specific child.\r
+ device to start.\r
+\r
+ @retval EFI_SUCCESS This driver is added to ControllerHandle.\r
+ @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.\r
+ @retval other This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusDriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Check RemainingDevicePath validation\r
+ //\r
+ if (RemainingDevicePath != NULL) {\r
+ //\r
+ // Check if RemainingDevicePath is the End of Device Path Node, \r
+ // if yes, return EFI_SUCCESS\r
+ //\r
+ if (IsDevicePathEnd (RemainingDevicePath)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiIncompatiblePciDeviceSupportProtocolGuid,\r
+ NULL,\r
+ (VOID **) &gEfiIncompatiblePciDeviceSupport\r
+ );\r
+\r
+ //\r
+ // If PCI Platform protocol is available, get it now.\r
+ // If the platform implements this, it must be installed before BDS phase\r
+ //\r
+ gPciPlatformProtocol = NULL;\r
+ gBS->LocateProtocol (\r
+ &gEfiPciPlatformProtocolGuid,\r
+ NULL,\r
+ (VOID **) &gPciPlatformProtocol\r
+ );\r
+\r
+ //\r
+ // If PCI Platform protocol doesn't exist, try to Pci Override Protocol.\r
+ //\r
+ if (gPciPlatformProtocol == NULL) { \r
+ gPciOverrideProtocol = NULL;\r
+ gBS->LocateProtocol (\r
+ &gEfiPciOverrideProtocolGuid,\r
+ NULL,\r
+ (VOID **) &gPciOverrideProtocol\r
+ );\r
+ } \r
+\r
+ gFullEnumeration = (BOOLEAN) ((SearchHostBridgeHandle (Controller) ? FALSE : TRUE));\r
+\r
+ //\r
+ // Enumerate the entire host bridge\r
+ // After enumeration, a database that records all the device information will be created\r
+ //\r
+ //\r
+ Status = PciEnumerator (Controller);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Start all the devices under the entire host bridge.\r
+ //\r
+ StartPciDevices (Controller);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Stop this driver on ControllerHandle. Support stoping any child handles\r
+ created by this driver.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Controller Handle of device to stop driver on.\r
+ @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
+ children is zero stop the entire bus driver.\r
+ @param ChildHandleBuffer List of Child Handles to Stop.\r
+\r
+ @retval EFI_SUCCESS This driver is removed ControllerHandle.\r
+ @retval other This driver was not removed from this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusDriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ BOOLEAN AllChildrenStopped;\r
+\r
+ if (NumberOfChildren == 0) {\r
+ //\r
+ // Close the bus driver\r
+ //\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiPciRootBridgeIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ DestroyRootBridgeByHandle (\r
+ Controller\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Stop all the children\r
+ //\r
+\r
+ AllChildrenStopped = TRUE;\r
+\r
+ for (Index = 0; Index < NumberOfChildren; Index++) {\r
+\r
+ //\r
+ // De register all the pci device\r
+ //\r
+ Status = DeRegisterPciDevice (Controller, ChildHandleBuffer[Index]);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ AllChildrenStopped = FALSE;\r
+ }\r
+ }\r
+\r
+ if (!AllChildrenStopped) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ Header files and data structures needed by 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
+\r
+**/\r
+\r
+\r
+#ifndef _EFI_PCI_BUS_H_\r
+#define _EFI_PCI_BUS_H_\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Protocol/LoadedImage.h>\r
+#include <Protocol/PciHostBridgeResourceAllocation.h>\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/LoadFile2.h>\r
+#include <Protocol/PciRootBridgeIo.h>\r
+#include <Protocol/PciHotPlugRequest.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/PciPlatform.h>\r
+#include <Protocol/PciHotPlugInit.h>\r
+#include <Protocol/Decompress.h>\r
+#include <Protocol/BusSpecificDriverOverride.h>\r
+#include <Protocol/IncompatiblePciDeviceSupport.h>\r
+#include <Protocol/PciOverride.h>\r
+#include <Protocol/PciEnumerationComplete.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/PeCoffLib.h>\r
+\r
+#include <IndustryStandard/Pci.h>\r
+#include <IndustryStandard/PeImage.h>\r
+#include <IndustryStandard/Acpi.h>\r
+\r
+typedef struct _PCI_IO_DEVICE PCI_IO_DEVICE;\r
+typedef struct _PCI_BAR PCI_BAR;\r
+\r
+#define EFI_PCI_RID(Bus, Device, Function) (((UINT32)Bus << 8) + ((UINT32)Device << 3) + (UINT32)Function)\r
+#define EFI_PCI_BUS_OF_RID(RID) ((UINT32)RID >> 8)\r
+\r
+#define EFI_PCI_IOV_POLICY_ARI 0x0001\r
+#define EFI_PCI_IOV_POLICY_SRIOV 0x0002\r
+#define EFI_PCI_IOV_POLICY_MRIOV 0x0004\r
+\r
+typedef enum {\r
+ PciBarTypeUnknown = 0,\r
+ PciBarTypeIo16,\r
+ PciBarTypeIo32,\r
+ PciBarTypeMem32,\r
+ PciBarTypePMem32,\r
+ PciBarTypeMem64,\r
+ PciBarTypePMem64,\r
+ PciBarTypeIo,\r
+ PciBarTypeMem,\r
+ PciBarTypeMaxType\r
+} PCI_BAR_TYPE;\r
+\r
+#include "ComponentName.h"\r
+#include "PciIo.h"\r
+#include "PciCommand.h"\r
+#include "PciDeviceSupport.h"\r
+#include "PciEnumerator.h"\r
+#include "PciEnumeratorSupport.h"\r
+#include "PciDriverOverride.h"\r
+#include "PciRomTable.h"\r
+#include "PciOptionRomSupport.h"\r
+#include "PciPowerManagement.h"\r
+#include "PciHotPlugSupport.h"\r
+#include "PciLib.h"\r
+\r
+#define VGABASE1 0x3B0\r
+#define VGALIMIT1 0x3BB\r
+\r
+#define VGABASE2 0x3C0\r
+#define VGALIMIT2 0x3DF\r
+\r
+#define ISABASE 0x100\r
+#define ISALIMIT 0x3FF\r
+\r
+//\r
+// PCI BAR parameters\r
+//\r
+struct _PCI_BAR {\r
+ UINT64 BaseAddress;\r
+ UINT64 Length;\r
+ UINT64 Alignment;\r
+ PCI_BAR_TYPE BarType;\r
+ BOOLEAN Prefetchable;\r
+ UINT8 MemType;\r
+ UINT8 Offset;\r
+};\r
+\r
+//\r
+// defined in PCI Card Specification, 8.0\r
+//\r
+#define PCI_CARD_MEMORY_BASE_0 0x1C\r
+#define PCI_CARD_MEMORY_LIMIT_0 0x20\r
+#define PCI_CARD_MEMORY_BASE_1 0x24\r
+#define PCI_CARD_MEMORY_LIMIT_1 0x28\r
+#define PCI_CARD_IO_BASE_0_LOWER 0x2C\r
+#define PCI_CARD_IO_BASE_0_UPPER 0x2E\r
+#define PCI_CARD_IO_LIMIT_0_LOWER 0x30\r
+#define PCI_CARD_IO_LIMIT_0_UPPER 0x32\r
+#define PCI_CARD_IO_BASE_1_LOWER 0x34\r
+#define PCI_CARD_IO_BASE_1_UPPER 0x36\r
+#define PCI_CARD_IO_LIMIT_1_LOWER 0x38\r
+#define PCI_CARD_IO_LIMIT_1_UPPER 0x3A\r
+#define PCI_CARD_BRIDGE_CONTROL 0x3E\r
+\r
+#define PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE BIT8\r
+#define PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE BIT9\r
+\r
+#define PPB_BAR_0 0\r
+#define PPB_BAR_1 1\r
+#define PPB_IO_RANGE 2\r
+#define PPB_MEM32_RANGE 3\r
+#define PPB_PMEM32_RANGE 4\r
+#define PPB_PMEM64_RANGE 5\r
+#define PPB_MEM64_RANGE 0xFF\r
+\r
+#define P2C_BAR_0 0\r
+#define P2C_MEM_1 1\r
+#define P2C_MEM_2 2\r
+#define P2C_IO_1 3\r
+#define P2C_IO_2 4\r
+\r
+#define EFI_BRIDGE_IO32_DECODE_SUPPORTED 0x0001\r
+#define EFI_BRIDGE_PMEM32_DECODE_SUPPORTED 0x0002\r
+#define EFI_BRIDGE_PMEM64_DECODE_SUPPORTED 0x0004\r
+#define EFI_BRIDGE_IO16_DECODE_SUPPORTED 0x0008\r
+#define EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED 0x0010\r
+#define EFI_BRIDGE_MEM64_DECODE_SUPPORTED 0x0020\r
+#define EFI_BRIDGE_MEM32_DECODE_SUPPORTED 0x0040\r
+\r
+#define PCI_MAX_HOST_BRIDGE_NUM 0x0010\r
+\r
+//\r
+// Define option for attribute\r
+//\r
+#define EFI_SET_SUPPORTS 0\r
+#define EFI_SET_ATTRIBUTES 1\r
+\r
+#define PCI_IO_DEVICE_SIGNATURE SIGNATURE_32 ('p', 'c', 'i', 'o')\r
+\r
+struct _PCI_IO_DEVICE {\r
+ UINT32 Signature;\r
+ EFI_HANDLE Handle;\r
+ EFI_PCI_IO_PROTOCOL PciIo;\r
+ LIST_ENTRY Link;\r
+\r
+ EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL PciDriverOverride;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+ EFI_LOAD_FILE2_PROTOCOL LoadFile2;\r
+\r
+ //\r
+ // PCI configuration space header type\r
+ //\r
+ PCI_TYPE00 Pci;\r
+\r
+ //\r
+ // Bus number, Device number, Function number\r
+ //\r
+ UINT8 BusNumber;\r
+ UINT8 DeviceNumber;\r
+ UINT8 FunctionNumber;\r
+\r
+ //\r
+ // BAR for this PCI Device\r
+ //\r
+ PCI_BAR PciBar[PCI_MAX_BAR];\r
+\r
+ //\r
+ // The bridge device this pci device is subject to\r
+ //\r
+ PCI_IO_DEVICE *Parent;\r
+\r
+ //\r
+ // A linked list for children Pci Device if it is bridge device\r
+ //\r
+ LIST_ENTRY ChildList;\r
+\r
+ //\r
+ // TURE if the PCI bus driver creates the handle for this PCI device\r
+ //\r
+ BOOLEAN Registered;\r
+\r
+ //\r
+ // TRUE if the PCI bus driver successfully allocates the resource required by\r
+ // this PCI device\r
+ //\r
+ BOOLEAN Allocated;\r
+\r
+ //\r
+ // The attribute this PCI device currently set\r
+ //\r
+ UINT64 Attributes;\r
+\r
+ //\r
+ // The attributes this PCI device actually supports\r
+ //\r
+ UINT64 Supports;\r
+\r
+ //\r
+ // The resource decode the bridge supports\r
+ //\r
+ UINT32 Decodes;\r
+\r
+ //\r
+ // The OptionRom Size\r
+ //\r
+ UINT64 RomSize;\r
+\r
+ //\r
+ // The OptionRom Size\r
+ //\r
+ UINT64 RomBase;\r
+\r
+ //\r
+ // TRUE if all OpROM (in device or in platform specific position) have been processed\r
+ //\r
+ BOOLEAN AllOpRomProcessed;\r
+\r
+ //\r
+ // TRUE if there is any EFI driver in the OptionRom\r
+ //\r
+ BOOLEAN BusOverride;\r
+\r
+ //\r
+ // A list tracking reserved resource on a bridge device\r
+ //\r
+ LIST_ENTRY ReservedResourceList;\r
+\r
+ //\r
+ // A list tracking image handle of platform specific overriding driver\r
+ //\r
+ LIST_ENTRY OptionRomDriverList;\r
+\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ResourcePaddingDescriptors;\r
+ EFI_HPC_PADDING_ATTRIBUTES PaddingAttributes;\r
+\r
+ BOOLEAN IsPciExp;\r
+ //\r
+ // For SR-IOV\r
+ //\r
+ UINT8 PciExpressCapabilityOffset;\r
+ UINT32 AriCapabilityOffset;\r
+ UINT32 SrIovCapabilityOffset;\r
+ UINT32 MrIovCapabilityOffset;\r
+ PCI_BAR VfPciBar[PCI_MAX_BAR];\r
+ UINT32 SystemPageSize;\r
+ UINT16 InitialVFs;\r
+ UINT16 ReservedBusNum;\r
+};\r
+\r
+#define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \\r
+ CR (a, PCI_IO_DEVICE, PciIo, PCI_IO_DEVICE_SIGNATURE)\r
+\r
+#define PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS(a) \\r
+ CR (a, PCI_IO_DEVICE, PciDriverOverride, PCI_IO_DEVICE_SIGNATURE)\r
+\r
+#define PCI_IO_DEVICE_FROM_LINK(a) \\r
+ CR (a, PCI_IO_DEVICE, Link, PCI_IO_DEVICE_SIGNATURE)\r
+\r
+#define PCI_IO_DEVICE_FROM_LOAD_FILE2_THIS(a) \\r
+ CR (a, PCI_IO_DEVICE, LoadFile2, PCI_IO_DEVICE_SIGNATURE)\r
+\r
+\r
+\r
+//\r
+// Global Variables\r
+//\r
+extern EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL *gEfiIncompatiblePciDeviceSupport;\r
+extern EFI_DRIVER_BINDING_PROTOCOL gPciBusDriverBinding;\r
+extern EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL gPciBusComponentName2;\r
+extern BOOLEAN gFullEnumeration;\r
+extern UINTN gPciHostBridgeNumber;\r
+extern EFI_HANDLE gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM];\r
+extern UINT64 gAllOne;\r
+extern UINT64 gAllZero;\r
+extern EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol;\r
+extern EFI_PCI_OVERRIDE_PROTOCOL *gPciOverrideProtocol;\r
+\r
+\r
+\r
+/**\r
+ Macro that checks whether device is a GFX device.\r
+\r
+ @param _p Specified device.\r
+\r
+ @retval TRUE Device is a a GFX device.\r
+ @retval FALSE Device is not a a GFX device.\r
+\r
+**/\r
+#define IS_PCI_GFX(_p) IS_CLASS2 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_OTHER)\r
+\r
+/**\r
+ Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
+ than contains a gEfiPciRootBridgeIoProtocolGuid protocol can be supported.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Controller Handle of device to test.\r
+ @param RemainingDevicePath Optional parameter use to pick a specific child.\r
+ device to start.\r
+\r
+ @retval EFI_SUCCESS This driver supports this device.\r
+ @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
+ @retval other This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusDriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ );\r
+\r
+/**\r
+ Start this driver on ControllerHandle and enumerate Pci bus and start\r
+ all device under PCI bus.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Controller Handle of device to bind driver to.\r
+ @param RemainingDevicePath Optional parameter use to pick a specific child.\r
+ device to start.\r
+\r
+ @retval EFI_SUCCESS This driver is added to ControllerHandle.\r
+ @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.\r
+ @retval other This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusDriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ );\r
+\r
+/**\r
+ Stop this driver on ControllerHandle. Support stoping any child handles\r
+ created by this driver.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Controller Handle of device to stop driver on.\r
+ @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
+ children is zero stop the entire bus driver.\r
+ @param ChildHandleBuffer List of Child Handles to Stop.\r
+\r
+ @retval EFI_SUCCESS This driver is removed ControllerHandle.\r
+ @retval other This driver was not removed from this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusDriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ );\r
+\r
+#endif\r
--- /dev/null
+#/** @file\r
+# Component description file for PciBus module.\r
+#\r
+# PCI bus driver. This module will probe all PCI devices and allocate MMIO and IO\r
+# space for these devices. Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable\r
+# hot plug supporting.\r
+#\r
+# Copyright (c) 2006 - 2009, Intel Corporation\r
+#\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
+# 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 = PciBusDxe\r
+ FILE_GUID = 93B80004-9FB3-11d4-9A3A-0090273FC14D\r
+ MODULE_TYPE = UEFI_DRIVER\r
+ VERSION_STRING = 1.0\r
+ EFI_SPECIFICATION_VERSION = 0x00020000\r
+ ENTRY_POINT = PciBusEntryPoint\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+# DRIVER_BINDING = gPciBusDriverBinding\r
+# COMPONENT_NAME = gPciBusComponentName\r
+# COMPONENT_NAME2 = gPciBusComponentName2\r
+#\r
+\r
+[Sources.common]\r
+ PciLib.c\r
+ PciIo.c\r
+ PciBus.c\r
+ PciDeviceSupport.c\r
+ ComponentName.c\r
+ ComponentName.h\r
+ PciCommand.c\r
+ PciResourceSupport.c\r
+ PciEnumeratorSupport.c\r
+ PciEnumerator.c\r
+ PciOptionRomSupport.c\r
+ PciDriverOverride.c\r
+ PciPowerManagement.c\r
+ PciPowerManagement.h\r
+ PciDriverOverride.h\r
+ PciRomTable.c\r
+ PciHotPlugSupport.c\r
+ PciLib.h\r
+ PciHotPlugSupport.h\r
+ PciRomTable.h\r
+ PciOptionRomSupport.h\r
+ PciEnumeratorSupport.h\r
+ PciEnumerator.h\r
+ PciResourceSupport.h\r
+ PciDeviceSupport.h\r
+ PciCommand.h\r
+ PciIo.h\r
+ PciBus.h\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+ PcdLib\r
+ DevicePathLib\r
+ UefiBootServicesTableLib\r
+ MemoryAllocationLib\r
+ ReportStatusCodeLib\r
+ BaseMemoryLib\r
+ UefiLib\r
+ BaseLib\r
+ UefiDriverEntryPoint\r
+ DebugLib\r
+ PeCoffLib\r
+\r
+[Protocols]\r
+ gEfiPciHotPlugRequestProtocolGuid ## BY_START\r
+ gEfiPciIoProtocolGuid ## BY_START\r
+ gEfiDevicePathProtocolGuid ## BY_START\r
+ gEfiBusSpecificDriverOverrideProtocolGuid ## BY_START\r
+ gEfiLoadedImageProtocolGuid ## CONSUMED\r
+ gEfiDecompressProtocolGuid ## CONSUMED\r
+ gEfiPciHotPlugInitProtocolGuid ## CONSUMED\r
+ gEfiPciHostBridgeResourceAllocationProtocolGuid ## CONSUMED\r
+ gEfiPciPlatformProtocolGuid ## CONSUMED\r
+ gEfiPciOverrideProtocolGuid ## CONSUMED \r
+ gEfiPciEnumerationCompleteProtocolGuid ## CONSUMED \r
+ gEfiPciRootBridgeIoProtocolGuid ## CONSUMED\r
+ gEfiIncompatiblePciDeviceSupportProtocolGuid ## CONSUMED\r
+ gEfiLoadFile2ProtocolGuid ## CONSUMED\r
+\r
+[FeaturePcd.common]\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSupport\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport\r
+\r
+[FixedPcd.common]\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize\r
+# [Event]\r
+# ##\r
+# # Notify event set by CreateEventForHpc () for PCI Hot Plug controller.\r
+# #\r
+# EVT_NOTIFY_SIGNAL ## PRODUCES\r
+#\r
+#\r
--- /dev/null
+/** @file\r
+ PCI command register operations supporting functions implementation 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
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+/**\r
+ Operate the PCI register via PciIo function interface.\r
+\r
+ @param PciIoDevice Pointer to instance of PCI_IO_DEVICE.\r
+ @param Command Operator command.\r
+ @param Offset The address within the PCI configuration space for the PCI controller.\r
+ @param Operation Type of Operation.\r
+ @param PtrCommand Return buffer holding old PCI command, if operation is not EFI_SET_REGISTER.\r
+\r
+ @return Status of PciIo operation.\r
+\r
+**/\r
+EFI_STATUS\r
+PciOperateRegister (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINT16 Command,\r
+ IN UINT8 Offset,\r
+ IN UINT8 Operation,\r
+ OUT UINT16 *PtrCommand\r
+ )\r
+{\r
+ UINT16 OldCommand;\r
+ EFI_STATUS Status;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+ OldCommand = 0;\r
+ PciIo = &PciIoDevice->PciIo;\r
+\r
+ if (Operation != EFI_SET_REGISTER) {\r
+ Status = PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ Offset,\r
+ 1,\r
+ &OldCommand\r
+ );\r
+\r
+ if (Operation == EFI_GET_REGISTER) {\r
+ *PtrCommand = OldCommand;\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ if (Operation == EFI_ENABLE_REGISTER) {\r
+ OldCommand = (UINT16) (OldCommand | Command);\r
+ } else if (Operation == EFI_DISABLE_REGISTER) {\r
+ OldCommand = (UINT16) (OldCommand & ~(Command));\r
+ } else {\r
+ OldCommand = Command;\r
+ }\r
+\r
+ return PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ Offset,\r
+ 1,\r
+ &OldCommand\r
+ );\r
+}\r
+\r
+/**\r
+ Check the cpability supporting by given device.\r
+\r
+ @param PciIoDevice Pointer to instance of PCI_IO_DEVICE.\r
+\r
+ @retval TRUE Cpability supportted.\r
+ @retval FALSE Cpability not supportted.\r
+\r
+**/\r
+BOOLEAN\r
+PciCapabilitySupport (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ if ((PciIoDevice->Pci.Hdr.Status & EFI_PCI_STATUS_CAPABILITY) != 0) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Locate capability register block per capability ID.\r
+\r
+ @param PciIoDevice A pointer to the PCI_IO_DEVICE.\r
+ @param CapId The capability ID.\r
+ @param Offset A pointer to the offset returned.\r
+ @param NextRegBlock A pointer to the next block returned.\r
+\r
+ @retval EFI_SUCCESS Successfuly located capability register block.\r
+ @retval EFI_UNSUPPORTED Pci device does not support capability.\r
+ @retval EFI_NOT_FOUND Pci device support but can not find register block.\r
+\r
+**/\r
+EFI_STATUS\r
+LocateCapabilityRegBlock (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINT8 CapId,\r
+ IN OUT UINT8 *Offset,\r
+ OUT UINT8 *NextRegBlock OPTIONAL\r
+ )\r
+{\r
+ UINT8 CapabilityPtr;\r
+ UINT16 CapabilityEntry;\r
+ UINT8 CapabilityID;\r
+\r
+ //\r
+ // To check the cpability of this device supports\r
+ //\r
+ if (!PciCapabilitySupport (PciIoDevice)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (*Offset != 0) {\r
+ CapabilityPtr = *Offset;\r
+ } else {\r
+\r
+ CapabilityPtr = 0;\r
+ if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
+\r
+ PciIoDevice->PciIo.Pci.Read (\r
+ &PciIoDevice->PciIo,\r
+ EfiPciIoWidthUint8,\r
+ EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR,\r
+ 1,\r
+ &CapabilityPtr\r
+ );\r
+ } else {\r
+\r
+ PciIoDevice->PciIo.Pci.Read (\r
+ &PciIoDevice->PciIo,\r
+ EfiPciIoWidthUint8,\r
+ PCI_CAPBILITY_POINTER_OFFSET,\r
+ 1,\r
+ &CapabilityPtr\r
+ );\r
+ }\r
+ }\r
+\r
+ while ((CapabilityPtr >= 0x40) && ((CapabilityPtr & 0x03) == 0x00)) {\r
+ PciIoDevice->PciIo.Pci.Read (\r
+ &PciIoDevice->PciIo,\r
+ EfiPciIoWidthUint16,\r
+ CapabilityPtr,\r
+ 1,\r
+ &CapabilityEntry\r
+ );\r
+\r
+ CapabilityID = (UINT8) CapabilityEntry;\r
+\r
+ if (CapabilityID == CapId) {\r
+ *Offset = CapabilityPtr;\r
+ if (NextRegBlock != NULL) {\r
+ *NextRegBlock = (UINT8) (CapabilityEntry >> 8);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ CapabilityPtr = (UINT8) (CapabilityEntry >> 8);\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ Locate PciExpress capability register block per capability ID.\r
+\r
+ @param PciIoDevice A pointer to the PCI_IO_DEVICE.\r
+ @param CapId The capability ID.\r
+ @param Offset A pointer to the offset returned.\r
+ @param NextRegBlock A pointer to the next block returned.\r
+\r
+ @retval EFI_SUCCESS Successfuly located capability register block.\r
+ @retval EFI_UNSUPPORTED Pci device does not support capability.\r
+ @retval EFI_NOT_FOUND Pci device support but can not find register block.\r
+\r
+**/\r
+EFI_STATUS\r
+LocatePciExpressCapabilityRegBlock (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINT16 CapId,\r
+ IN OUT UINT32 *Offset,\r
+ OUT UINT32 *NextRegBlock OPTIONAL\r
+ )\r
+{\r
+ UINT32 CapabilityPtr;\r
+ UINT32 CapabilityEntry;\r
+ UINT16 CapabilityID;\r
+\r
+ //\r
+ // To check the capability of this device supports\r
+ //\r
+ if (!PciIoDevice->IsPciExp) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (*Offset != 0) {\r
+ CapabilityPtr = *Offset;\r
+ } else {\r
+ CapabilityPtr = EFI_PCIE_CAPABILITY_BASE_OFFSET;\r
+ }\r
+\r
+ while (CapabilityPtr != 0) {\r
+ //\r
+ // Mask it to DWORD alignment per PCI spec\r
+ //\r
+ CapabilityPtr &= 0xFFC;\r
+ PciIoDevice->PciIo.Pci.Read (\r
+ &PciIoDevice->PciIo,\r
+ EfiPciIoWidthUint32,\r
+ CapabilityPtr,\r
+ 1,\r
+ &CapabilityEntry\r
+ );\r
+\r
+ CapabilityID = (UINT16) CapabilityEntry;\r
+\r
+ if (CapabilityID == CapId) {\r
+ *Offset = CapabilityPtr;\r
+ if (NextRegBlock != NULL) {\r
+ *NextRegBlock = (CapabilityEntry >> 20) & 0xFFF;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ CapabilityPtr = (CapabilityEntry >> 20) & 0xFFF;\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
--- /dev/null
+/** @file\r
+ PCI command register operations supporting functions declaration 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
+\r
+**/\r
+\r
+\r
+#ifndef _EFI_PCI_COMMAND_H_\r
+#define _EFI_PCI_COMMAND_H_\r
+\r
+//\r
+// The PCI Command register bits owned by PCI Bus driver.\r
+//\r
+// They should be cleared at the beginning. The other registers\r
+// are owned by chipset, we should not touch them.\r
+//\r
+#define EFI_PCI_COMMAND_BITS_OWNED ( \\r
+ EFI_PCI_COMMAND_IO_SPACE | \\r
+ EFI_PCI_COMMAND_MEMORY_SPACE | \\r
+ EFI_PCI_COMMAND_BUS_MASTER | \\r
+ EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE | \\r
+ EFI_PCI_COMMAND_VGA_PALETTE_SNOOP | \\r
+ EFI_PCI_COMMAND_FAST_BACK_TO_BACK \\r
+ )\r
+\r
+//\r
+// The PCI Bridge Control register bits owned by PCI Bus driver.\r
+//\r
+// They should be cleared at the beginning. The other registers\r
+// are owned by chipset, we should not touch them.\r
+//\r
+#define EFI_PCI_BRIDGE_CONTROL_BITS_OWNED ( \\r
+ EFI_PCI_BRIDGE_CONTROL_ISA | \\r
+ EFI_PCI_BRIDGE_CONTROL_VGA | \\r
+ EFI_PCI_BRIDGE_CONTROL_VGA_16 | \\r
+ EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK \\r
+ )\r
+\r
+//\r
+// The PCCard Bridge Control register bits owned by PCI Bus driver.\r
+//\r
+// They should be cleared at the beginning. The other registers\r
+// are owned by chipset, we should not touch them.\r
+//\r
+#define EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED ( \\r
+ EFI_PCI_BRIDGE_CONTROL_ISA | \\r
+ EFI_PCI_BRIDGE_CONTROL_VGA | \\r
+ EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK \\r
+ )\r
+\r
+\r
+#define EFI_GET_REGISTER 1\r
+#define EFI_SET_REGISTER 2\r
+#define EFI_ENABLE_REGISTER 3\r
+#define EFI_DISABLE_REGISTER 4\r
+\r
+/**\r
+ Operate the PCI register via PciIo function interface.\r
+\r
+ @param PciIoDevice Pointer to instance of PCI_IO_DEVICE.\r
+ @param Command Operator command.\r
+ @param Offset The address within the PCI configuration space for the PCI controller.\r
+ @param Operation Type of Operation.\r
+ @param PtrCommand Return buffer holding old PCI command, if operation is not EFI_SET_REGISTER.\r
+\r
+ @return Status of PciIo operation.\r
+\r
+**/\r
+EFI_STATUS\r
+PciOperateRegister (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINT16 Command,\r
+ IN UINT8 Offset,\r
+ IN UINT8 Operation,\r
+ OUT UINT16 *PtrCommand\r
+ );\r
+\r
+/**\r
+ Check the cpability supporting by given device.\r
+\r
+ @param PciIoDevice Pointer to instance of PCI_IO_DEVICE.\r
+\r
+ @retval TRUE Cpability supportted.\r
+ @retval FALSE Cpability not supportted.\r
+\r
+**/\r
+BOOLEAN\r
+PciCapabilitySupport (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+/**\r
+ Locate capability register block per capability ID.\r
+\r
+ @param PciIoDevice A pointer to the PCI_IO_DEVICE.\r
+ @param CapId The capability ID.\r
+ @param Offset A pointer to the offset returned.\r
+ @param NextRegBlock A pointer to the next block returned.\r
+\r
+ @retval EFI_SUCCESS Successfuly located capability register block.\r
+ @retval EFI_UNSUPPORTED Pci device does not support capability.\r
+ @retval EFI_NOT_FOUND Pci device support but can not find register block.\r
+\r
+**/\r
+EFI_STATUS\r
+LocateCapabilityRegBlock (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINT8 CapId,\r
+ IN OUT UINT8 *Offset,\r
+ OUT UINT8 *NextRegBlock OPTIONAL\r
+ );\r
+\r
+/**\r
+ Locate PciExpress capability register block per capability ID.\r
+\r
+ @param PciIoDevice A pointer to the PCI_IO_DEVICE.\r
+ @param CapId The capability ID.\r
+ @param Offset A pointer to the offset returned.\r
+ @param NextRegBlock A pointer to the next block returned.\r
+\r
+ @retval EFI_SUCCESS Successfuly located capability register block.\r
+ @retval EFI_UNSUPPORTED Pci device does not support capability.\r
+ @retval EFI_NOT_FOUND Pci device support but can not find register block.\r
+\r
+**/\r
+EFI_STATUS\r
+LocatePciExpressCapabilityRegBlock (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINT16 CapId,\r
+ IN OUT UINT32 *Offset,\r
+ OUT UINT32 *NextRegBlock OPTIONAL\r
+ );\r
+\r
+/**\r
+ Macro that reads command register.\r
+\r
+ @param a[in] Pointer to instance of PCI_IO_DEVICE.\r
+ @param b[out] Pointer to the 16-bit value read from command register.\r
+\r
+ @return status of PciIo operation\r
+\r
+**/\r
+#define PCI_READ_COMMAND_REGISTER(a,b) \\r
+ PciOperateRegister (a, 0, PCI_COMMAND_OFFSET, EFI_GET_REGISTER, b)\r
+\r
+/**\r
+ Macro that writes command register.\r
+\r
+ @param a[in] Pointer to instance of PCI_IO_DEVICE.\r
+ @param b[in] The 16-bit value written into command register.\r
+\r
+ @return status of PciIo operation\r
+\r
+**/\r
+#define PCI_SET_COMMAND_REGISTER(a,b) \\r
+ PciOperateRegister (a, b, PCI_COMMAND_OFFSET, EFI_SET_REGISTER, NULL)\r
+\r
+/**\r
+ Macro that enables command register.\r
+\r
+ @param a[in] Pointer to instance of PCI_IO_DEVICE.\r
+ @param b[in] The enabled value written into command register.\r
+\r
+ @return status of PciIo operation\r
+\r
+**/\r
+#define PCI_ENABLE_COMMAND_REGISTER(a,b) \\r
+ PciOperateRegister (a, b, PCI_COMMAND_OFFSET, EFI_ENABLE_REGISTER, NULL)\r
+\r
+/**\r
+ Macro that disalbes command register.\r
+\r
+ @param a[in] Pointer to instance of PCI_IO_DEVICE.\r
+ @param b[in] The disabled value written into command register.\r
+\r
+ @return status of PciIo operation\r
+\r
+**/\r
+#define PCI_DISABLE_COMMAND_REGISTER(a,b) \\r
+ PciOperateRegister (a, b, PCI_COMMAND_OFFSET, EFI_DISABLE_REGISTER, NULL)\r
+\r
+/**\r
+ Macro that reads PCI bridge control register.\r
+\r
+ @param a[in] Pointer to instance of PCI_IO_DEVICE.\r
+ @param b[out] The 16-bit value read from control register.\r
+\r
+ @return status of PciIo operation\r
+\r
+**/\r
+#define PCI_READ_BRIDGE_CONTROL_REGISTER(a,b) \\r
+ PciOperateRegister (a, 0, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_GET_REGISTER, b)\r
+\r
+/**\r
+ Macro that writes PCI bridge control register.\r
+\r
+ @param a[in] Pointer to instance of PCI_IO_DEVICE.\r
+ @param b[in] The 16-bit value written into control register.\r
+\r
+ @return status of PciIo operation\r
+\r
+**/\r
+#define PCI_SET_BRIDGE_CONTROL_REGISTER(a,b) \\r
+ PciOperateRegister (a, b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_SET_REGISTER, NULL)\r
+\r
+/**\r
+ Macro that enables PCI bridge control register.\r
+\r
+ @param a[in] Pointer to instance of PCI_IO_DEVICE.\r
+ @param b[in] The enabled value written into command register.\r
+\r
+ @return status of PciIo operation\r
+\r
+**/\r
+#define PCI_ENABLE_BRIDGE_CONTROL_REGISTER(a,b) \\r
+ PciOperateRegister (a, b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_ENABLE_REGISTER, NULL)\r
+\r
+/**\r
+ Macro that disalbes PCI bridge control register.\r
+\r
+ @param a[in] Pointer to instance of PCI_IO_DEVICE.\r
+ @param b[in] The disabled value written into command register.\r
+\r
+ @return status of PciIo operation\r
+\r
+**/\r
+#define PCI_DISABLE_BRIDGE_CONTROL_REGISTER(a,b) \\r
+ PciOperateRegister (a, b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_DISABLE_REGISTER, NULL)\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Supporting functions implementaion for PCI devices management.\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
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+//\r
+// This device structure is serviced as a header.\r
+// Its next field points to the first root bridge device node.\r
+//\r
+LIST_ENTRY mPciDevicePool;\r
+\r
+/**\r
+ Initialize the PCI devices pool.\r
+\r
+**/\r
+VOID\r
+InitializePciDevicePool (\r
+ VOID\r
+ )\r
+{\r
+ InitializeListHead (&mPciDevicePool);\r
+}\r
+\r
+/**\r
+ Insert a root bridge into PCI device pool.\r
+\r
+ @param RootBridge A pointer to the PCI_IO_DEVICE.\r
+\r
+**/\r
+VOID\r
+InsertRootBridge (\r
+ IN PCI_IO_DEVICE *RootBridge\r
+ )\r
+{\r
+ InsertTailList (&mPciDevicePool, &(RootBridge->Link));\r
+}\r
+\r
+/**\r
+ This function is used to insert a PCI device node under\r
+ a bridge.\r
+\r
+ @param Bridge The PCI bridge.\r
+ @param PciDeviceNode The PCI device needs inserting.\r
+\r
+**/\r
+VOID\r
+InsertPciDevice (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN PCI_IO_DEVICE *PciDeviceNode\r
+ )\r
+{\r
+ InsertTailList (&Bridge->ChildList, &(PciDeviceNode->Link));\r
+ PciDeviceNode->Parent = Bridge;\r
+}\r
+\r
+/**\r
+ Destroy root bridge and remove it from deivce tree.\r
+\r
+ @param RootBridge The bridge want to be removed.\r
+\r
+**/\r
+VOID\r
+DestroyRootBridge (\r
+ IN PCI_IO_DEVICE *RootBridge\r
+ )\r
+{\r
+ DestroyPciDeviceTree (RootBridge);\r
+\r
+ FreePciDevice (RootBridge);\r
+}\r
+\r
+/**\r
+ Destroy a pci device node.\r
+\r
+ All direct or indirect allocated resource for this node will be freed.\r
+\r
+ @param PciIoDevice A pointer to the PCI_IO_DEVICE to be destoried.\r
+\r
+**/\r
+VOID\r
+FreePciDevice (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ ASSERT (PciIoDevice != NULL);\r
+ //\r
+ // Assume all children have been removed underneath this device\r
+ //\r
+ if (PciIoDevice->ResourcePaddingDescriptors != NULL) {\r
+ FreePool (PciIoDevice->ResourcePaddingDescriptors);\r
+ }\r
+\r
+ if (PciIoDevice->DevicePath != NULL) {\r
+ FreePool (PciIoDevice->DevicePath);\r
+ }\r
+\r
+ FreePool (PciIoDevice);\r
+}\r
+\r
+/**\r
+ Destroy all the pci device node under the bridge.\r
+ Bridge itself is not included.\r
+\r
+ @param Bridge A pointer to the PCI_IO_DEVICE.\r
+\r
+**/\r
+VOID\r
+DestroyPciDeviceTree (\r
+ IN PCI_IO_DEVICE *Bridge\r
+ )\r
+{\r
+ LIST_ENTRY *CurrentLink;\r
+ PCI_IO_DEVICE *Temp;\r
+\r
+ while (!IsListEmpty (&Bridge->ChildList)) {\r
+\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+ //\r
+ // Remove this node from the linked list\r
+ //\r
+ RemoveEntryList (CurrentLink);\r
+\r
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+ if (!IsListEmpty (&Temp->ChildList)) {\r
+ DestroyPciDeviceTree (Temp);\r
+ }\r
+\r
+ FreePciDevice (Temp);\r
+ }\r
+}\r
+\r
+/**\r
+ Destroy all device nodes under the root bridge\r
+ specified by Controller.\r
+\r
+ The root bridge itself is also included.\r
+\r
+ @param Controller Root bridge handle.\r
+\r
+ @retval EFI_SUCCESS Destory all devcie nodes successfully.\r
+ @retval EFI_NOT_FOUND Cannot find any PCI device under specified\r
+ root bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+DestroyRootBridgeByHandle (\r
+ IN EFI_HANDLE Controller\r
+ )\r
+{\r
+\r
+ LIST_ENTRY *CurrentLink;\r
+ PCI_IO_DEVICE *Temp;\r
+\r
+ CurrentLink = mPciDevicePool.ForwardLink;\r
+\r
+ while (CurrentLink != NULL && CurrentLink != &mPciDevicePool) {\r
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+ if (Temp->Handle == Controller) {\r
+\r
+ RemoveEntryList (CurrentLink);\r
+\r
+ DestroyPciDeviceTree (Temp);\r
+\r
+ FreePciDevice (Temp);\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ This function registers the PCI IO device.\r
+\r
+ It creates a handle for this PCI IO device (if the handle does not exist), attaches\r
+ appropriate protocols onto the handle, does necessary initialization, and sets up\r
+ parent/child relationship with its bus controller.\r
+\r
+ @param Controller An EFI handle for the PCI bus controller.\r
+ @param PciIoDevice A PCI_IO_DEVICE pointer to the PCI IO device to be registered.\r
+ @param Handle A pointer to hold the returned EFI handle for the PCI IO device.\r
+\r
+ @retval EFI_SUCCESS The PCI device is successfully registered.\r
+ @retval other An error occurred when registering the PCI device.\r
+\r
+**/\r
+EFI_STATUS\r
+RegisterPciDevice (\r
+ IN EFI_HANDLE Controller,\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ OUT EFI_HANDLE *Handle OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VOID *PlatformOpRomBuffer;\r
+ UINTN PlatformOpRomSize;\r
+ UINT8 PciExpressCapRegOffset;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT8 Data8;\r
+ BOOLEAN HasEfiImage;\r
+ PCI_IO_DEVICE *ParrentPciIoDevice;\r
+ EFI_PCI_IO_PROTOCOL *ParrentPciIo;\r
+ UINT16 Data16;\r
+ UINT32 Data32;\r
+\r
+ //\r
+ // Install the pciio protocol, device path protocol\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &PciIoDevice->Handle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ PciIoDevice->DevicePath,\r
+ &gEfiPciIoProtocolGuid,\r
+ &PciIoDevice->PciIo,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Detect if PCI Express Device\r
+ //\r
+ PciExpressCapRegOffset = 0;\r
+ Status = LocateCapabilityRegBlock (\r
+ PciIoDevice,\r
+ EFI_PCI_CAPABILITY_ID_PCIEXP,\r
+ &PciExpressCapRegOffset,\r
+ NULL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ PciIoDevice->IsPciExp = TRUE;\r
+ }\r
+\r
+ //\r
+ // Force Interrupt line to "Unknown" or "No Connection"\r
+ //\r
+ PciIo = &(PciIoDevice->PciIo);\r
+ Data8 = PCI_INT_LINE_UNKNOWN;\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &Data8);\r
+ \r
+ //\r
+ // PCI-IOV programming\r
+ //\r
+ if (((FeaturePcdGet(PcdAriSupport) & EFI_PCI_IOV_POLICY_ARI) != 0) && (PciIoDevice->AriCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport) & EFI_PCI_IOV_POLICY_SRIOV) != 0) &&\r
+ (PciIoDevice->SrIovCapabilityOffset != 0)) {\r
+ //\r
+ // Check its parrent ARI forwarding capability\r
+ //\r
+ ParrentPciIoDevice = PciIoDevice->Parent;\r
+ ParrentPciIo = &(ParrentPciIoDevice->PciIo);\r
+ ParrentPciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ParrentPciIoDevice->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET, 1, &Data32);\r
+ if (Data32 & EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING) {\r
+ //\r
+ // ARI forward support in bridge, so enable it.\r
+ //\r
+ ParrentPciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ParrentPciIoDevice->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET, 1, &Data32);\r
+ Data32 |= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING;\r
+ ParrentPciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ParrentPciIoDevice->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET, 1, &Data32);\r
+\r
+ //\r
+ // Set ARI Capable Hierarchy for device\r
+ //\r
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL, 1, &Data16);\r
+ Data16 |= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY;\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL, 1, &Data16);\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Process OpRom\r
+ //\r
+ if (!PciIoDevice->AllOpRomProcessed) {\r
+\r
+ //\r
+ // Get the OpRom provided by platform\r
+ //\r
+ if (gPciPlatformProtocol != NULL) {\r
+ Status = gPciPlatformProtocol->GetPciRom (\r
+ gPciPlatformProtocol,\r
+ PciIoDevice->Handle,\r
+ &PlatformOpRomBuffer,\r
+ &PlatformOpRomSize\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ PciIoDevice->RomSize = PlatformOpRomSize;\r
+ PciIoDevice->PciIo.RomSize = PlatformOpRomSize;\r
+ PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;\r
+ //\r
+ // For OpROM read from gPciPlatformProtocol:\r
+ // Add the Rom Image to internal database for later PCI light enumeration\r
+ //\r
+ PciRomAddImageMapping (\r
+ NULL,\r
+ PciIoDevice->PciRootBridgeIo->SegmentNumber,\r
+ PciIoDevice->BusNumber,\r
+ PciIoDevice->DeviceNumber,\r
+ PciIoDevice->FunctionNumber,\r
+ (UINT64) (UINTN) PciIoDevice->PciIo.RomImage,\r
+ PciIoDevice->PciIo.RomSize\r
+ );\r
+ }\r
+ } else if (gPciOverrideProtocol != NULL) {\r
+ Status = gPciOverrideProtocol->GetPciRom (\r
+ gPciOverrideProtocol,\r
+ PciIoDevice->Handle,\r
+ &PlatformOpRomBuffer,\r
+ &PlatformOpRomSize\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ PciIoDevice->RomSize = PlatformOpRomSize;\r
+ PciIoDevice->PciIo.RomSize = PlatformOpRomSize;\r
+ PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;\r
+ //\r
+ // For OpROM read from gPciOverrideProtocol:\r
+ // Add the Rom Image to internal database for later PCI light enumeration\r
+ //\r
+ PciRomAddImageMapping (\r
+ NULL,\r
+ PciIoDevice->PciRootBridgeIo->SegmentNumber,\r
+ PciIoDevice->BusNumber,\r
+ PciIoDevice->DeviceNumber,\r
+ PciIoDevice->FunctionNumber,\r
+ (UINT64) (UINTN) PciIoDevice->PciIo.RomImage,\r
+ PciIoDevice->PciIo.RomSize\r
+ );\r
+ } \r
+ }\r
+ }\r
+\r
+ //\r
+ // Determine if there are EFI images in the option rom\r
+ //\r
+ HasEfiImage = ContainEfiImage (PciIoDevice->PciIo.RomImage, PciIoDevice->PciIo.RomSize);\r
+\r
+ if (HasEfiImage) {\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &PciIoDevice->Handle,\r
+ &gEfiLoadFile2ProtocolGuid,\r
+ &PciIoDevice->LoadFile2,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ &PciIoDevice->Handle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ PciIoDevice->DevicePath,\r
+ &gEfiPciIoProtocolGuid,\r
+ &PciIoDevice->PciIo,\r
+ NULL\r
+ );\r
+ return Status;\r
+ }\r
+ }\r
+\r
+\r
+ if (!PciIoDevice->AllOpRomProcessed) {\r
+\r
+ PciIoDevice->AllOpRomProcessed = TRUE;\r
+\r
+ //\r
+ // Dispatch the EFI OpRom for the PCI device.\r
+ // The OpRom is got from platform in the above code\r
+ // or loaded from device in the previous round of bus enumeration\r
+ //\r
+ if (HasEfiImage) {\r
+ ProcessOpRomImage (PciIoDevice);\r
+ }\r
+ }\r
+\r
+ if (PciIoDevice->BusOverride) {\r
+ //\r
+ // Install Bus Specific Driver Override Protocol\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &PciIoDevice->Handle,\r
+ &gEfiBusSpecificDriverOverrideProtocolGuid,\r
+ &PciIoDevice->PciDriverOverride,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ &PciIoDevice->Handle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ PciIoDevice->DevicePath,\r
+ &gEfiPciIoProtocolGuid,\r
+ &PciIoDevice->PciIo,\r
+ NULL\r
+ );\r
+ if (HasEfiImage) {\r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ &PciIoDevice->Handle,\r
+ &gEfiLoadFile2ProtocolGuid,\r
+ &PciIoDevice->LoadFile2,\r
+ NULL\r
+ );\r
+ }\r
+\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciRootBridgeIoProtocolGuid,\r
+ (VOID **) &(PciIoDevice->PciRootBridgeIo),\r
+ gPciBusDriverBinding.DriverBindingHandle,\r
+ PciIoDevice->Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Handle != NULL) {\r
+ *Handle = PciIoDevice->Handle;\r
+ }\r
+\r
+ //\r
+ // Indicate the pci device is registered\r
+ //\r
+ PciIoDevice->Registered = TRUE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function is used to remove the whole PCI devices on the specified bridge from\r
+ the root bridge.\r
+\r
+ @param RootBridgeHandle The root bridge device handle.\r
+ @param Bridge The bridge device to be removed.\r
+\r
+**/\r
+VOID\r
+RemoveAllPciDeviceOnBridge (\r
+ EFI_HANDLE RootBridgeHandle,\r
+ PCI_IO_DEVICE *Bridge\r
+ )\r
+{\r
+ LIST_ENTRY *CurrentLink;\r
+ PCI_IO_DEVICE *Temp;\r
+\r
+ while (!IsListEmpty (&Bridge->ChildList)) {\r
+\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+ //\r
+ // Check if the current node has been deregistered before\r
+ // If it is not, then deregister it\r
+ //\r
+ if (Temp->Registered) {\r
+ DeRegisterPciDevice (RootBridgeHandle, Temp->Handle);\r
+ }\r
+\r
+ //\r
+ // Remove this node from the linked list\r
+ //\r
+ RemoveEntryList (CurrentLink);\r
+\r
+ if (!IsListEmpty (&Temp->ChildList)) {\r
+ RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);\r
+ }\r
+\r
+ FreePciDevice (Temp);\r
+ }\r
+}\r
+\r
+/**\r
+ This function is used to de-register the PCI IO device.\r
+\r
+ That includes un-installing PciIo protocol from the specified PCI\r
+ device handle.\r
+\r
+ @param Controller An EFI handle for the PCI bus controller.\r
+ @param Handle PCI device handle.\r
+\r
+ @retval EFI_SUCCESS The PCI device is successfully de-registered.\r
+ @retval other An error occurred when de-registering the PCI device.\r
+\r
+**/\r
+EFI_STATUS\r
+DeRegisterPciDevice (\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_HANDLE Handle\r
+ )\r
+\r
+{\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ PCI_IO_DEVICE *Node;\r
+ LIST_ENTRY *CurrentLink;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+\r
+ Status = gBS->OpenProtocol (\r
+ Handle,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo,\r
+ gPciBusDriverBinding.DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);\r
+\r
+ //\r
+ // If it is already de-registered\r
+ //\r
+ if (!PciIoDevice->Registered) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // If it is PPB, first de-register its children\r
+ //\r
+\r
+ if (!IsListEmpty (&PciIoDevice->ChildList)) {\r
+\r
+ CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
+\r
+ while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {\r
+ Node = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+ Status = DeRegisterPciDevice (Controller, Node->Handle);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Close the child handle\r
+ //\r
+ Status = gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiPciRootBridgeIoProtocolGuid,\r
+ gPciBusDriverBinding.DriverBindingHandle,\r
+ Handle\r
+ );\r
+\r
+ //\r
+ // Un-install the Device Path protocol and PCI I/O protocol\r
+ // and Bus Specific Driver Override protocol if needed.\r
+ //\r
+ if (PciIoDevice->BusOverride) {\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ Handle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ PciIoDevice->DevicePath,\r
+ &gEfiPciIoProtocolGuid,\r
+ &PciIoDevice->PciIo,\r
+ &gEfiBusSpecificDriverOverrideProtocolGuid,\r
+ &PciIoDevice->PciDriverOverride,\r
+ NULL\r
+ );\r
+ } else {\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ Handle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ PciIoDevice->DevicePath,\r
+ &gEfiPciIoProtocolGuid,\r
+ &PciIoDevice->PciIo,\r
+ NULL\r
+ );\r
+ }\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Try to uninstall LoadFile2 protocol if exists\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Handle,\r
+ &gEfiLoadFile2ProtocolGuid,\r
+ NULL,\r
+ gPciBusDriverBinding.DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ Handle,\r
+ &gEfiLoadFile2ProtocolGuid,\r
+ &PciIoDevice->LoadFile2,\r
+ NULL\r
+ );\r
+ }\r
+ //\r
+ // Restore Status\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciRootBridgeIoProtocolGuid,\r
+ (VOID **) &PciRootBridgeIo,\r
+ gPciBusDriverBinding.DriverBindingHandle,\r
+ Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // The Device Driver should disable this device after disconnect\r
+ // so the Pci Bus driver will not touch this device any more.\r
+ // Restore the register field to the original value\r
+ //\r
+ PciIoDevice->Registered = FALSE;\r
+ PciIoDevice->Handle = NULL;\r
+ } else {\r
+\r
+ //\r
+ // Handle may be closed before\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Start to manage the PCI device on the specified root bridge or PCI-PCI Bridge.\r
+\r
+ @param Controller The root bridge handle.\r
+ @param RootBridge A pointer to the PCI_IO_DEVICE.\r
+ @param RemainingDevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL.\r
+ @param NumberOfChildren Children number.\r
+ @param ChildHandleBuffer A pointer to the child handle buffer.\r
+\r
+ @retval EFI_NOT_READY Device is not allocated.\r
+ @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.\r
+ @retval EFI_NOT_FOUND Can not find the specific device.\r
+ @retval EFI_SUCCESS Success to start Pci devices on bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+StartPciDevicesOnBridge (\r
+ IN EFI_HANDLE Controller,\r
+ IN PCI_IO_DEVICE *RootBridge,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,\r
+ IN OUT UINT8 *NumberOfChildren,\r
+ IN OUT EFI_HANDLE *ChildHandleBuffer\r
+ )\r
+\r
+{\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ EFI_DEV_PATH_PTR Node;\r
+ EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath;\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *CurrentLink;\r
+ UINT64 Supports;\r
+\r
+ PciIoDevice = NULL;\r
+ CurrentLink = RootBridge->ChildList.ForwardLink;\r
+\r
+ while (CurrentLink != NULL && CurrentLink != &RootBridge->ChildList) {\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+ if (RemainingDevicePath != NULL) {\r
+\r
+ Node.DevPath = RemainingDevicePath;\r
+\r
+ if (Node.Pci->Device != PciIoDevice->DeviceNumber ||\r
+ Node.Pci->Function != PciIoDevice->FunctionNumber) {\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Check if the device has been assigned with required resource\r
+ //\r
+ if (!PciIoDevice->Allocated) {\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ //\r
+ // Check if the current node has been registered before\r
+ // If it is not, register it\r
+ //\r
+ if (!PciIoDevice->Registered) {\r
+ Status = RegisterPciDevice (\r
+ Controller,\r
+ PciIoDevice,\r
+ NULL\r
+ );\r
+\r
+ }\r
+\r
+ if (NumberOfChildren != NULL && ChildHandleBuffer != NULL && PciIoDevice->Registered) {\r
+ ChildHandleBuffer[*NumberOfChildren] = PciIoDevice->Handle;\r
+ (*NumberOfChildren)++;\r
+ }\r
+\r
+ //\r
+ // Get the next device path\r
+ //\r
+ CurrentDevicePath = NextDevicePathNode (RemainingDevicePath);\r
+ if (IsDevicePathEnd (CurrentDevicePath)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // If it is a PPB\r
+ //\r
+ if (!IsListEmpty (&PciIoDevice->ChildList)) {\r
+ Status = StartPciDevicesOnBridge (\r
+ Controller,\r
+ PciIoDevice,\r
+ CurrentDevicePath,\r
+ NumberOfChildren,\r
+ ChildHandleBuffer\r
+ );\r
+\r
+ PciIoDevice->PciIo.Attributes (\r
+ &(PciIoDevice->PciIo),\r
+ EfiPciIoAttributeOperationSupported,\r
+ 0,\r
+ &Supports\r
+ );\r
+ Supports &= EFI_PCI_DEVICE_ENABLE;\r
+ PciIoDevice->PciIo.Attributes (\r
+ &(PciIoDevice->PciIo),\r
+ EfiPciIoAttributeOperationEnable,\r
+ Supports,\r
+ NULL\r
+ );\r
+\r
+ return Status;\r
+ } else {\r
+\r
+ //\r
+ // Currently, the PCI bus driver only support PCI-PCI bridge\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ } else {\r
+\r
+ //\r
+ // If remaining device path is NULL,\r
+ // try to enable all the pci devices under this bridge\r
+ //\r
+ if (!PciIoDevice->Registered && PciIoDevice->Allocated) {\r
+ Status = RegisterPciDevice (\r
+ Controller,\r
+ PciIoDevice,\r
+ NULL\r
+ );\r
+\r
+ }\r
+\r
+ if (NumberOfChildren != NULL && ChildHandleBuffer != NULL && PciIoDevice->Registered) {\r
+ ChildHandleBuffer[*NumberOfChildren] = PciIoDevice->Handle;\r
+ (*NumberOfChildren)++;\r
+ }\r
+\r
+ if (!IsListEmpty (&PciIoDevice->ChildList)) {\r
+ Status = StartPciDevicesOnBridge (\r
+ Controller,\r
+ PciIoDevice,\r
+ RemainingDevicePath,\r
+ NumberOfChildren,\r
+ ChildHandleBuffer\r
+ );\r
+\r
+ PciIoDevice->PciIo.Attributes (\r
+ &(PciIoDevice->PciIo),\r
+ EfiPciIoAttributeOperationSupported,\r
+ 0,\r
+ &Supports\r
+ );\r
+ Supports &= EFI_PCI_DEVICE_ENABLE;\r
+ PciIoDevice->PciIo.Attributes (\r
+ &(PciIoDevice->PciIo),\r
+ EfiPciIoAttributeOperationEnable,\r
+ Supports,\r
+ NULL\r
+ );\r
+\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+ }\r
+\r
+ if (PciIoDevice == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+}\r
+\r
+/**\r
+ Start to manage all the PCI devices it found previously under\r
+ the entire host bridge.\r
+\r
+ @param Controller The root bridge handle.\r
+\r
+ @retval EFI_NOT_READY Device is not allocated.\r
+ @retval EFI_SUCCESS Success to start Pci device on host bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+StartPciDevices (\r
+ IN EFI_HANDLE Controller\r
+ )\r
+{\r
+ PCI_IO_DEVICE *RootBridge;\r
+ EFI_HANDLE ThisHostBridge;\r
+ LIST_ENTRY *CurrentLink;\r
+\r
+ RootBridge = GetRootBridgeByHandle (Controller);\r
+ ASSERT (RootBridge != NULL);\r
+ ThisHostBridge = RootBridge->PciRootBridgeIo->ParentHandle;\r
+\r
+ CurrentLink = mPciDevicePool.ForwardLink;\r
+\r
+ while (CurrentLink != NULL && CurrentLink != &mPciDevicePool) {\r
+\r
+ RootBridge = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+ //\r
+ // Locate the right root bridge to start\r
+ //\r
+ if (RootBridge->PciRootBridgeIo->ParentHandle == ThisHostBridge) {\r
+ StartPciDevicesOnBridge (\r
+ RootBridge->Handle,\r
+ RootBridge,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ );\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Create root bridge device.\r
+\r
+ @param RootBridgeHandle Specified root bridge hanle.\r
+\r
+ @return The crated root bridge device instance, NULL means no\r
+ root bridge device instance created.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+CreateRootBridge (\r
+ IN EFI_HANDLE RootBridgeHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *Dev;\r
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+\r
+ Dev = AllocateZeroPool (sizeof (PCI_IO_DEVICE));\r
+ if (Dev == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Dev->Signature = PCI_IO_DEVICE_SIGNATURE;\r
+ Dev->Handle = RootBridgeHandle;\r
+ InitializeListHead (&Dev->ChildList);\r
+\r
+ Status = gBS->OpenProtocol (\r
+ RootBridgeHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &ParentDevicePath,\r
+ gPciBusDriverBinding.DriverBindingHandle,\r
+ RootBridgeHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Dev);\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Record the root bridge parent device path\r
+ //\r
+ Dev->DevicePath = DuplicateDevicePath (ParentDevicePath);\r
+\r
+ //\r
+ // Get the pci root bridge io protocol\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ RootBridgeHandle,\r
+ &gEfiPciRootBridgeIoProtocolGuid,\r
+ (VOID **) &PciRootBridgeIo,\r
+ gPciBusDriverBinding.DriverBindingHandle,\r
+ RootBridgeHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ FreePciDevice (Dev);\r
+ return NULL;\r
+ }\r
+\r
+ Dev->PciRootBridgeIo = PciRootBridgeIo;\r
+\r
+ //\r
+ // Initialize the PCI I/O instance structure\r
+ //\r
+ InitializePciIoInstance (Dev);\r
+ InitializePciDriverOverrideInstance (Dev);\r
+ InitializePciLoadFile2 (Dev);\r
+\r
+ //\r
+ // Initialize reserved resource list and\r
+ // option rom driver list\r
+ //\r
+ InitializeListHead (&Dev->ReservedResourceList);\r
+ InitializeListHead (&Dev->OptionRomDriverList);\r
+\r
+ return Dev;\r
+}\r
+\r
+/**\r
+ Get root bridge device instance by specific root bridge handle.\r
+\r
+ @param RootBridgeHandle Given root bridge handle.\r
+\r
+ @return The root bridge device instance, NULL means no root bridge\r
+ device instance found.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+GetRootBridgeByHandle (\r
+ EFI_HANDLE RootBridgeHandle\r
+ )\r
+{\r
+ PCI_IO_DEVICE *RootBridgeDev;\r
+ LIST_ENTRY *CurrentLink;\r
+\r
+ CurrentLink = mPciDevicePool.ForwardLink;\r
+\r
+ while (CurrentLink != NULL && CurrentLink != &mPciDevicePool) {\r
+\r
+ RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+ if (RootBridgeDev->Handle == RootBridgeHandle) {\r
+ return RootBridgeDev;\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Judege whether Pci device existed.\r
+\r
+ @param Bridge Parent bridege instance.\r
+ @param PciIoDevice Device instance.\r
+\r
+ @retval TRUE Pci device existed.\r
+ @retval FALSE Pci device did not exist.\r
+\r
+**/\r
+BOOLEAN\r
+PciDeviceExisted (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+\r
+ PCI_IO_DEVICE *Temp;\r
+ LIST_ENTRY *CurrentLink;\r
+\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+ while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
+\r
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+ if (Temp == PciIoDevice) {\r
+ return TRUE;\r
+ }\r
+\r
+ if (!IsListEmpty (&Temp->ChildList)) {\r
+ if (PciDeviceExisted (Temp, PciIoDevice)) {\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Get the active VGA device on the same segment.\r
+\r
+ @param VgaDevice PCI IO instance for the VGA device.\r
+\r
+ @return The active VGA device on the same segment.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+ActiveVGADeviceOnTheSameSegment (\r
+ IN PCI_IO_DEVICE *VgaDevice\r
+ )\r
+{\r
+ LIST_ENTRY *CurrentLink;\r
+ PCI_IO_DEVICE *Temp;\r
+\r
+ CurrentLink = mPciDevicePool.ForwardLink;\r
+\r
+ while (CurrentLink != NULL && CurrentLink != &mPciDevicePool) {\r
+\r
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+ if (Temp->PciRootBridgeIo->SegmentNumber == VgaDevice->PciRootBridgeIo->SegmentNumber) {\r
+\r
+ Temp = ActiveVGADeviceOnTheRootBridge (Temp);\r
+\r
+ if (Temp != NULL) {\r
+ return Temp;\r
+ }\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Get the active VGA device on the root bridge.\r
+\r
+ @param RootBridge PCI IO instance for the root bridge.\r
+\r
+ @return The active VGA device.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+ActiveVGADeviceOnTheRootBridge (\r
+ IN PCI_IO_DEVICE *RootBridge\r
+ )\r
+{\r
+ LIST_ENTRY *CurrentLink;\r
+ PCI_IO_DEVICE *Temp;\r
+\r
+ CurrentLink = RootBridge->ChildList.ForwardLink;\r
+\r
+ while (CurrentLink != NULL && CurrentLink != &RootBridge->ChildList) {\r
+\r
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+ if (IS_PCI_VGA(&Temp->Pci) &&\r
+ (Temp->Attributes &\r
+ (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY |\r
+ EFI_PCI_IO_ATTRIBUTE_VGA_IO |\r
+ EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) != 0) {\r
+ return Temp;\r
+ }\r
+\r
+ if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
+\r
+ Temp = ActiveVGADeviceOnTheRootBridge (Temp);\r
+\r
+ if (Temp != NULL) {\r
+ return Temp;\r
+ }\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+\r
+/**\r
+ Get HPC PCI address according to its device path.\r
+\r
+ @param RootBridge Root bridege Io instance.\r
+ @param RemainingDevicePath Given searching device path.\r
+ @param PciAddress Buffer holding searched result.\r
+\r
+ @retval EFI_SUCCESS PCI address was stored in PciAddress\r
+ @retval EFI_NOT_FOUND Can not find the specific device path.\r
+\r
+**/\r
+EFI_STATUS\r
+GetHpcPciAddressFromRootBridge (\r
+ IN PCI_IO_DEVICE *RootBridge,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,\r
+ OUT UINT64 *PciAddress\r
+ )\r
+{\r
+ EFI_DEV_PATH_PTR Node;\r
+ PCI_IO_DEVICE *Temp;\r
+ EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath;\r
+ LIST_ENTRY *CurrentLink;\r
+ BOOLEAN MisMatch;\r
+\r
+ MisMatch = FALSE;\r
+\r
+ CurrentDevicePath = RemainingDevicePath;\r
+ Node.DevPath = CurrentDevicePath;\r
+ Temp = NULL;\r
+\r
+ while (!IsDevicePathEnd (CurrentDevicePath)) {\r
+\r
+ CurrentLink = RootBridge->ChildList.ForwardLink;\r
+ Node.DevPath = CurrentDevicePath;\r
+\r
+ while (CurrentLink != NULL && CurrentLink != &RootBridge->ChildList) {\r
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+ if (Node.Pci->Device == Temp->DeviceNumber &&\r
+ Node.Pci->Function == Temp->FunctionNumber) {\r
+ RootBridge = Temp;\r
+ break;\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ //\r
+ // Check if we find the bridge\r
+ //\r
+ if (CurrentLink == &RootBridge->ChildList) {\r
+\r
+ MisMatch = TRUE;\r
+ break;\r
+\r
+ }\r
+\r
+ CurrentDevicePath = NextDevicePathNode (CurrentDevicePath);\r
+ }\r
+\r
+ if (MisMatch) {\r
+\r
+ CurrentDevicePath = NextDevicePathNode (CurrentDevicePath);\r
+\r
+ if (IsDevicePathEnd (CurrentDevicePath)) {\r
+ *PciAddress = EFI_PCI_ADDRESS (RootBridge->BusNumber, Node.Pci->Device, Node.Pci->Function, 0);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (Temp != NULL) {\r
+ *PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);\r
+ } else {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ Supporting functions declaration for PCI devices management.\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
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_DEVICE_SUPPORT_H_\r
+#define _EFI_PCI_DEVICE_SUPPORT_H_\r
+\r
+/**\r
+ Initialize the PCI devices pool.\r
+\r
+**/\r
+VOID\r
+InitializePciDevicePool (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Insert a root bridge into PCI device pool.\r
+\r
+ @param RootBridge A pointer to the PCI_IO_DEVICE.\r
+\r
+**/\r
+VOID\r
+InsertRootBridge (\r
+ IN PCI_IO_DEVICE *RootBridge\r
+ );\r
+\r
+/**\r
+ This function is used to insert a PCI device node under\r
+ a bridge.\r
+\r
+ @param Bridge The PCI bridge.\r
+ @param PciDeviceNode The PCI device needs inserting.\r
+\r
+**/\r
+VOID\r
+InsertPciDevice (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN PCI_IO_DEVICE *PciDeviceNode\r
+ );\r
+\r
+/**\r
+ Destroy root bridge and remove it from deivce tree.\r
+\r
+ @param RootBridge The bridge want to be removed.\r
+\r
+**/\r
+VOID\r
+DestroyRootBridge (\r
+ IN PCI_IO_DEVICE *RootBridge\r
+ );\r
+\r
+/**\r
+ Destroy all the pci device node under the bridge.\r
+ Bridge itself is not included.\r
+\r
+ @param Bridge A pointer to the PCI_IO_DEVICE.\r
+\r
+**/\r
+VOID\r
+DestroyPciDeviceTree (\r
+ IN PCI_IO_DEVICE *Bridge\r
+ );\r
+\r
+/**\r
+ Destroy all device nodes under the root bridge\r
+ specified by Controller.\r
+\r
+ The root bridge itself is also included.\r
+\r
+ @param Controller Root bridge handle.\r
+\r
+ @retval EFI_SUCCESS Destory all devcie nodes successfully.\r
+ @retval EFI_NOT_FOUND Cannot find any PCI device under specified\r
+ root bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+DestroyRootBridgeByHandle (\r
+ IN EFI_HANDLE Controller\r
+ );\r
+\r
+/**\r
+ This function registers the PCI IO device.\r
+\r
+ It creates a handle for this PCI IO device (if the handle does not exist), attaches\r
+ appropriate protocols onto the handle, does necessary initialization, and sets up\r
+ parent/child relationship with its bus controller.\r
+\r
+ @param Controller An EFI handle for the PCI bus controller.\r
+ @param PciIoDevice A PCI_IO_DEVICE pointer to the PCI IO device to be registered.\r
+ @param Handle A pointer to hold the returned EFI handle for the PCI IO device.\r
+\r
+ @retval EFI_SUCCESS The PCI device is successfully registered.\r
+ @retval other An error occurred when registering the PCI device.\r
+\r
+**/\r
+EFI_STATUS\r
+RegisterPciDevice (\r
+ IN EFI_HANDLE Controller,\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ OUT EFI_HANDLE *Handle OPTIONAL\r
+ );\r
+\r
+/**\r
+ This function is used to remove the whole PCI devices on the specified bridge from\r
+ the root bridge.\r
+\r
+ @param RootBridgeHandle The root bridge device handle.\r
+ @param Bridge The bridge device to be removed.\r
+\r
+**/\r
+VOID\r
+RemoveAllPciDeviceOnBridge (\r
+ EFI_HANDLE RootBridgeHandle,\r
+ PCI_IO_DEVICE *Bridge\r
+ );\r
+\r
+/**\r
+ This function is used to de-register the PCI IO device.\r
+\r
+ That includes un-installing PciIo protocol from the specified PCI\r
+ device handle.\r
+\r
+ @param Controller An EFI handle for the PCI bus controller.\r
+ @param Handle PCI device handle.\r
+\r
+ @retval EFI_SUCCESS The PCI device is successfully de-registered.\r
+ @retval other An error occurred when de-registering the PCI device.\r
+\r
+**/\r
+EFI_STATUS\r
+DeRegisterPciDevice (\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_HANDLE Handle\r
+ );\r
+\r
+/**\r
+ Start to manage the PCI device on the specified root bridge or PCI-PCI Bridge.\r
+\r
+ @param Controller The root bridge handle.\r
+ @param RootBridge A pointer to the PCI_IO_DEVICE.\r
+ @param RemainingDevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL.\r
+ @param NumberOfChildren Children number.\r
+ @param ChildHandleBuffer A pointer to the child handle buffer.\r
+\r
+ @retval EFI_NOT_READY Device is not allocated.\r
+ @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.\r
+ @retval EFI_NOT_FOUND Can not find the specific device.\r
+ @retval EFI_SUCCESS Success to start Pci devices on bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+StartPciDevicesOnBridge (\r
+ IN EFI_HANDLE Controller,\r
+ IN PCI_IO_DEVICE *RootBridge,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,\r
+ IN OUT UINT8 *NumberOfChildren,\r
+ IN OUT EFI_HANDLE *ChildHandleBuffer\r
+ );\r
+\r
+/**\r
+ Start to manage all the PCI devices it found previously under\r
+ the entire host bridge.\r
+\r
+ @param Controller The root bridge handle.\r
+\r
+ @retval EFI_NOT_READY Device is not allocated.\r
+ @retval EFI_SUCCESS Success to start Pci device on host bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+StartPciDevices (\r
+ IN EFI_HANDLE Controller\r
+ );\r
+\r
+/**\r
+ Create root bridge device.\r
+\r
+ @param RootBridgeHandle Specified root bridge hanle.\r
+\r
+ @return The crated root bridge device instance, NULL means no\r
+ root bridge device instance created.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+CreateRootBridge (\r
+ IN EFI_HANDLE RootBridgeHandle\r
+ );\r
+\r
+/**\r
+ Get root bridge device instance by specific root bridge handle.\r
+\r
+ @param RootBridgeHandle Given root bridge handle.\r
+\r
+ @return The root bridge device instance, NULL means no root bridge\r
+ device instance found.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+GetRootBridgeByHandle (\r
+ EFI_HANDLE RootBridgeHandle\r
+ );\r
+\r
+\r
+/**\r
+ Judege whether Pci device existed.\r
+\r
+ @param Bridge Parent bridege instance.\r
+ @param PciIoDevice Device instance.\r
+\r
+ @retval TRUE Pci device existed.\r
+ @retval FALSE Pci device did not exist.\r
+\r
+**/\r
+BOOLEAN\r
+PciDeviceExisted (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+/**\r
+ Get the active VGA device on the same segment.\r
+\r
+ @param VgaDevice PCI IO instance for the VGA device.\r
+\r
+ @return The active VGA device on the same segment.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+ActiveVGADeviceOnTheSameSegment (\r
+ IN PCI_IO_DEVICE *VgaDevice\r
+ );\r
+\r
+/**\r
+ Get the active VGA device on the root bridge.\r
+\r
+ @param RootBridge PCI IO instance for the root bridge.\r
+\r
+ @return The active VGA device.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+ActiveVGADeviceOnTheRootBridge (\r
+ IN PCI_IO_DEVICE *RootBridge\r
+ );\r
+\r
+/**\r
+ Get HPC PCI address according to its device path.\r
+\r
+ @param RootBridge Root bridege Io instance.\r
+ @param RemainingDevicePath Given searching device path.\r
+ @param PciAddress Buffer holding searched result.\r
+\r
+ @retval EFI_SUCCESS PCI address was stored in PciAddress.\r
+ @retval EFI_NOT_FOUND Can not find the specific device path.\r
+\r
+**/\r
+EFI_STATUS\r
+GetHpcPciAddressFromRootBridge (\r
+ IN PCI_IO_DEVICE *RootBridge,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,\r
+ OUT UINT64 *PciAddress\r
+ );\r
+\r
+/**\r
+ Destroy a pci device node.\r
+\r
+ All direct or indirect allocated resource for this node will be freed.\r
+\r
+ @param PciIoDevice A pointer to the PCI_IO_DEVICE to be destoried.\r
+\r
+**/\r
+VOID\r
+FreePciDevice (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Functions implementation for Bus Specific Driver Override protoocl.\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
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+/**\r
+ Initializes a PCI Driver Override Instance.\r
+\r
+ @param PciIoDevice PCI Device instance.\r
+\r
+**/\r
+VOID\r
+InitializePciDriverOverrideInstance (\r
+ IN OUT PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ PciIoDevice->PciDriverOverride.GetDriver = GetDriver;\r
+}\r
+\r
+\r
+/**\r
+ Uses a bus specific algorithm to retrieve a driver image handle for a controller.\r
+\r
+ @param This A pointer to the EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL instance.\r
+ @param DriverImageHandle On input, a pointer to the previous driver image handle returned\r
+ by GetDriver(). On output, a pointer to the next driver\r
+ image handle. Passing in a NULL, will return the first driver\r
+ image handle.\r
+\r
+ @retval EFI_SUCCESS A bus specific override driver is returned in DriverImageHandle.\r
+ @retval EFI_NOT_FOUND The end of the list of override drivers was reached.\r
+ A bus specific override driver is not returned in DriverImageHandle.\r
+ @retval EFI_INVALID_PARAMETER DriverImageHandle is not a handle that was returned on a\r
+ previous call to GetDriver().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetDriver (\r
+ IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This,\r
+ IN OUT EFI_HANDLE *DriverImageHandle\r
+ )\r
+{\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ LIST_ENTRY *CurrentLink;\r
+ PCI_DRIVER_OVERRIDE_LIST *Node;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS (This);\r
+\r
+ CurrentLink = PciIoDevice->OptionRomDriverList.ForwardLink;\r
+\r
+ while (CurrentLink != NULL && CurrentLink != &PciIoDevice->OptionRomDriverList) {\r
+\r
+ Node = DRIVER_OVERRIDE_FROM_LINK (CurrentLink);\r
+\r
+ if (*DriverImageHandle == NULL) {\r
+\r
+ *DriverImageHandle = Node->DriverImageHandle;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (*DriverImageHandle == Node->DriverImageHandle) {\r
+\r
+ if (CurrentLink->ForwardLink == &PciIoDevice->OptionRomDriverList ||\r
+ CurrentLink->ForwardLink == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Get next node\r
+ //\r
+ Node = DRIVER_OVERRIDE_FROM_LINK (CurrentLink->ForwardLink);\r
+ *DriverImageHandle = Node->DriverImageHandle;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+ Add an overriding driver image.\r
+\r
+ @param PciIoDevice Instance of PciIo device.\r
+ @param DriverImageHandle new added driver image.\r
+\r
+ @retval EFI_SUCCESS Successfully added driver.\r
+ @retval EFI_OUT_OF_RESOURCES No memory resource for new driver instance.\r
+ @retval other Some error occurred when locating gEfiLoadedImageProtocolGuid.\r
+\r
+**/\r
+EFI_STATUS\r
+AddDriver (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN EFI_HANDLE DriverImageHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
+ PCI_DRIVER_OVERRIDE_LIST *Node;\r
+\r
+ Status = gBS->HandleProtocol (DriverImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Node = AllocatePool (sizeof (PCI_DRIVER_OVERRIDE_LIST));\r
+ if (Node == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Node->Signature = DRIVER_OVERRIDE_SIGNATURE;\r
+ Node->DriverImageHandle = DriverImageHandle;\r
+\r
+ InsertTailList (&PciIoDevice->OptionRomDriverList, &(Node->Link));\r
+\r
+ PciIoDevice->BusOverride = TRUE;\r
+\r
+ ImageContext.Handle = LoadedImage->ImageBase;\r
+ ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;\r
+\r
+ //\r
+ // Get information about the image\r
+ //\r
+ PeCoffLoaderGetImageInfo (&ImageContext);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ Functions declaration for Bus Specific Driver Override protoocl.\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
+\r
+**/\r
+\r
+\r
+#ifndef _EFI_PCI_DRIVER_OVERRRIDE_H_\r
+#define _EFI_PCI_DRIVER_OVERRRIDE_H_\r
+\r
+#define DRIVER_OVERRIDE_SIGNATURE SIGNATURE_32 ('d', 'r', 'o', 'v')\r
+\r
+//\r
+// PCI driver override driver image list\r
+//\r
+typedef struct {\r
+ UINT32 Signature;\r
+ LIST_ENTRY Link;\r
+ EFI_HANDLE DriverImageHandle;\r
+} PCI_DRIVER_OVERRIDE_LIST;\r
+\r
+\r
+#define DRIVER_OVERRIDE_FROM_LINK(a) \\r
+ CR (a, PCI_DRIVER_OVERRIDE_LIST, Link, DRIVER_OVERRIDE_SIGNATURE)\r
+\r
+/**\r
+ Initializes a PCI Driver Override Instance.\r
+\r
+ @param PciIoDevice PCI Device instance.\r
+\r
+**/\r
+VOID\r
+InitializePciDriverOverrideInstance (\r
+ IN OUT PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+/**\r
+ Add an overriding driver image.\r
+\r
+ @param PciIoDevice Instance of PciIo device.\r
+ @param DriverImageHandle new added driver image.\r
+\r
+ @retval EFI_SUCCESS Successfully added driver.\r
+ @retval EFI_OUT_OF_RESOURCES No memory resource for new driver instance.\r
+ @retval other Some error occurred when locating gEfiLoadedImageProtocolGuid.\r
+\r
+**/\r
+EFI_STATUS\r
+AddDriver (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN EFI_HANDLE DriverImageHandle\r
+ );\r
+\r
+\r
+/**\r
+ Uses a bus specific algorithm to retrieve a driver image handle for a controller.\r
+\r
+ @param This A pointer to the EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL instance.\r
+ @param DriverImageHandle On input, a pointer to the previous driver image handle returned\r
+ by GetDriver(). On output, a pointer to the next driver\r
+ image handle. Passing in a NULL, will return the first driver\r
+ image handle.\r
+\r
+ @retval EFI_SUCCESS A bus specific override driver is returned in DriverImageHandle.\r
+ @retval EFI_NOT_FOUND The end of the list of override drivers was reached.\r
+ A bus specific override driver is not returned in DriverImageHandle.\r
+ @retval EFI_INVALID_PARAMETER DriverImageHandle is not a handle that was returned on a\r
+ previous call to GetDriver().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetDriver (\r
+ IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This,\r
+ IN OUT EFI_HANDLE *DriverImageHandle\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @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
+\r
+**/\r
+\r
+#include "PciBus.h"\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
+\r
+ @retval EFI_SUCCESS PCI enumeration finished successfully.\r
+ @retval other Some error occurred when enumerating the pci bus system.\r
+\r
+**/\r
+EFI_STATUS\r
+PciEnumerator (\r
+ IN EFI_HANDLE Controller\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
+ Status = gBS->OpenProtocol (\r
+ HostBridgeHandle,\r
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid,\r
+ (VOID **) &PciResAlloc,\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
+ // Notify the pci bus enumeration is about to begin\r
+ //\r
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration);\r
+\r
+ //\r
+ // Start the bus allocation phase\r
+ //\r
+ Status = PciHostBridgeEnumerator (PciResAlloc);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Submit the resource request\r
+ //\r
+ Status = PciHostBridgeResourceAllocator (PciResAlloc);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Notify the pci bus enumeration is about to complete\r
+ //\r
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeEndEnumeration);\r
+\r
+ //\r
+ // Process P2C\r
+ //\r
+ Status = PciHostBridgeP2CProcess (PciResAlloc);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Process attributes for devices on this host bridge\r
+ //\r
+ Status = PciHostBridgeDeviceAttribute (PciResAlloc);\r
+ if (EFI_ERROR (Status)) {\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
+ Enumerate PCI root bridge.\r
+\r
+ @param PciResAlloc Pointer to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
+ @param RootBridgeDev Instance of root bridge device.\r
+\r
+ @retval EFI_SUCCESS Successfully enumerated root bridge.\r
+ @retval other Failed to enumerate root bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciRootBridgeEnumerator (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
+ IN PCI_IO_DEVICE *RootBridgeDev\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
+ UINT8 SubBusNumber;\r
+ UINT8 StartBusNumber;\r
+ UINT8 PaddedBusRange;\r
+ EFI_HANDLE RootBridgeHandle;\r
+\r
+ SubBusNumber = 0;\r
+ StartBusNumber = 0;\r
+ PaddedBusRange = 0;\r
+\r
+ //\r
+ // Get the root bridge handle\r
+ //\r
+ RootBridgeHandle = RootBridgeDev->Handle;\r
+\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_BUS_ENUM,\r
+ RootBridgeDev->DevicePath\r
+ );\r
+\r
+ //\r
+ // Get the Bus information\r
+ //\r
+ Status = PciResAlloc->StartBusEnumeration (\r
+ PciResAlloc,\r
+ RootBridgeHandle,\r
+ (VOID **) &Configuration\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\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
+ SubBusNumber = StartBusNumber;\r
+\r
+ //\r
+ // Reset all assigned PCI bus number\r
+ //\r
+ ResetAllPpbBusNumber (\r
+ RootBridgeDev,\r
+ StartBusNumber\r
+ );\r
+\r
+ //\r
+ // Assign bus number\r
+ //\r
+ Status = PciScanBus (\r
+ RootBridgeDev,\r
+ (UINT8) (Configuration->AddrRangeMin),\r
+ &SubBusNumber,\r
+ &PaddedBusRange\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+\r
+ //\r
+ // Assign max bus number scanned\r
+ //\r
+ Configuration->AddrLen = SubBusNumber - StartBusNumber + 1 + PaddedBusRange;\r
+\r
+ //\r
+ // Set bus number\r
+ //\r
+ Status = PciResAlloc->SetBusNumbers (\r
+ PciResAlloc,\r
+ RootBridgeHandle,\r
+ Configuration\r
+ );\r
+\r
+ FreePool (Configuration);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This routine is used to process all PCI devices' Option Rom\r
+ on a certain root bridge.\r
+\r
+ @param Bridge Given parent's root bridge.\r
+ @param RomBase Base address of ROM driver loaded from.\r
+ @param MaxLength Maximum rom size.\r
+\r
+**/\r
+VOID\r
+ProcessOptionRom (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN UINT64 RomBase,\r
+ IN UINT64 MaxLength\r
+ )\r
+{\r
+ LIST_ENTRY *CurrentLink;\r
+ PCI_IO_DEVICE *Temp;\r
+\r
+ //\r
+ // Go through bridges to reach all devices\r
+ //\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+ while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+ if (!IsListEmpty (&Temp->ChildList)) {\r
+\r
+ //\r
+ // Go further to process the option rom under this bridge\r
+ //\r
+ ProcessOptionRom (Temp, RomBase, MaxLength);\r
+ }\r
+\r
+ if (Temp->RomSize != 0 && Temp->RomSize <= MaxLength) {\r
+\r
+ //\r
+ // Load and process the option rom\r
+ //\r
+ LoadOpRomImage (Temp, RomBase);\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+}\r
+\r
+/**\r
+ This routine is used to assign bus number to the given PCI bus system\r
+\r
+ @param Bridge Parent root bridge instance.\r
+ @param StartBusNumber Number of beginning.\r
+ @param SubBusNumber The number of sub bus.\r
+\r
+ @retval EFI_SUCCESS Successfully assigned bus number.\r
+ @retval EFI_DEVICE_ERROR Failed to assign bus number.\r
+\r
+**/\r
+EFI_STATUS\r
+PciAssignBusNumber (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN UINT8 StartBusNumber,\r
+ OUT UINT8 *SubBusNumber\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_TYPE00 Pci;\r
+ UINT8 Device;\r
+ UINT8 Func;\r
+ UINT64 Address;\r
+ UINTN SecondBus;\r
+ UINT16 Register;\r
+ UINT8 Register8;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+\r
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
+\r
+ SecondBus = 0;\r
+ Register = 0;\r
+\r
+ *SubBusNumber = StartBusNumber;\r
+\r
+ //\r
+ // First check to see whether the parent is ppb\r
+ //\r
+ for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
+ for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
+\r
+ //\r
+ // Check to see whether a pci device is present\r
+ //\r
+ Status = PciDevicePresent (\r
+ PciRootBridgeIo,\r
+ &Pci,\r
+ StartBusNumber,\r
+ Device,\r
+ Func\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
+\r
+ Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
+\r
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);\r
+\r
+ Status = PciRootBridgeIo->Pci.Write (\r
+ PciRootBridgeIo,\r
+ EfiPciWidthUint16,\r
+ Address,\r
+ 1,\r
+ &Register\r
+ );\r
+\r
+ //\r
+ // Initialize SubBusNumber to SecondBus\r
+ //\r
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
+ Status = PciRootBridgeIo->Pci.Write (\r
+ PciRootBridgeIo,\r
+ EfiPciWidthUint8,\r
+ Address,\r
+ 1,\r
+ SubBusNumber\r
+ );\r
+ //\r
+ // If it is PPB, resursively search down this bridge\r
+ //\r
+ if (IS_PCI_BRIDGE (&Pci)) {\r
+\r
+ Register8 = 0xFF;\r
+ Status = PciRootBridgeIo->Pci.Write (\r
+ PciRootBridgeIo,\r
+ EfiPciWidthUint8,\r
+ Address,\r
+ 1,\r
+ &Register8\r
+ );\r
+\r
+ Status = PciAssignBusNumber (\r
+ Bridge,\r
+ (UINT8) (SecondBus),\r
+ SubBusNumber\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Set the current maximum bus number under the PPB\r
+ //\r
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
+\r
+ Status = PciRootBridgeIo->Pci.Write (\r
+ PciRootBridgeIo,\r
+ EfiPciWidthUint8,\r
+ Address,\r
+ 1,\r
+ SubBusNumber\r
+ );\r
+\r
+ }\r
+\r
+ if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
+\r
+ //\r
+ // Skip sub functions, this is not a multi function device\r
+ //\r
+ Func = PCI_MAX_FUNC;\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This routine is used to determine the root bridge attribute by interfacing\r
+ the host bridge resource allocation protocol.\r
+\r
+ @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
+ @param RootBridgeDev Root bridge instance\r
+\r
+ @retval EFI_SUCCESS Successfully got root bridge's attribute.\r
+ @retval other Failed to get attribute.\r
+\r
+**/\r
+EFI_STATUS\r
+DetermineRootBridgeAttributes (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
+ IN PCI_IO_DEVICE *RootBridgeDev\r
+ )\r
+{\r
+ UINT64 Attributes;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE RootBridgeHandle;\r
+\r
+ Attributes = 0;\r
+ RootBridgeHandle = RootBridgeDev->Handle;\r
+\r
+ //\r
+ // Get root bridge attribute by calling into pci host bridge resource allocation protocol\r
+ //\r
+ Status = PciResAlloc->GetAllocAttributes (\r
+ PciResAlloc,\r
+ RootBridgeHandle,\r
+ &Attributes\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Here is the point where PCI bus driver calls HOST bridge allocation protocol\r
+ // Currently we hardcoded for ea815\r
+ //\r
+ if ((Attributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) {\r
+ RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED;\r
+ }\r
+\r
+ if ((Attributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0) {\r
+ RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;\r
+ }\r
+\r
+ RootBridgeDev->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;\r
+ RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;\r
+ RootBridgeDev->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Get Max Option Rom size on specified bridge.\r
+\r
+ @param Bridge Given bridge device instance.\r
+\r
+ @return Max size of option rom needed.\r
+\r
+**/\r
+UINT64\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
+\r
+ MaxOptionRomSize = 0;\r
+\r
+ //\r
+ // Go through bridges to reach all devices\r
+ //\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+ while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+ if (!IsListEmpty (&Temp->ChildList)) {\r
+\r
+ //\r
+ // Get max option rom size under this bridge\r
+ //\r
+ TempOptionRomSize = GetMaxOptionRomSize (Temp);\r
+\r
+ //\r
+ // Compare with the option rom size of the bridge\r
+ // Get the larger one\r
+ //\r
+ if (Temp->RomSize > TempOptionRomSize) {\r
+ TempOptionRomSize = Temp->RomSize;\r
+ }\r
+\r
+ } else {\r
+\r
+ //\r
+ // For devices get the rom size directly\r
+ //\r
+ TempOptionRomSize = Temp->RomSize;\r
+ }\r
+\r
+ //\r
+ // Get the largest rom size on this bridge\r
+ //\r
+ if (TempOptionRomSize > MaxOptionRomSize) {\r
+ MaxOptionRomSize = TempOptionRomSize;\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ return MaxOptionRomSize;\r
+}\r
+\r
+/**\r
+ Process attributes of devices on this host bridge\r
+\r
+ @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
+\r
+ @retval EFI_SUCCESS Successfully process attribute.\r
+ @retval EFI_NOT_FOUND Can not find the specific root bridge device.\r
+ @retval other Failed to determine the root bridge device's attribute.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeDeviceAttribute (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
+ )\r
+{\r
+ EFI_HANDLE RootBridgeHandle;\r
+ PCI_IO_DEVICE *RootBridgeDev;\r
+ EFI_STATUS Status;\r
+\r
+ RootBridgeHandle = NULL;\r
+\r
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
+\r
+ //\r
+ // Get RootBridg Device by handle\r
+ //\r
+ RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
+\r
+ if (RootBridgeDev == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Set the attributes for devcies behind the Root Bridge\r
+ //\r
+ Status = DetermineDeviceAttribute (RootBridgeDev);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Get resource allocation status from the ACPI resource descriptor.\r
+\r
+ @param AcpiConfig Point to Acpi configuration table.\r
+ @param IoResStatus Return the status of I/O resource.\r
+ @param Mem32ResStatus Return the status of 32-bit Memory resource.\r
+ @param PMem32ResStatus Return the status of 32-bit Prefetchable Memory resource.\r
+ @param Mem64ResStatus Return the status of 64-bit Memory resource.\r
+ @param PMem64ResStatus Return the status of 64-bit Prefetchable Memory resource.\r
+\r
+**/\r
+VOID\r
+GetResourceAllocationStatus (\r
+ VOID *AcpiConfig,\r
+ OUT UINT64 *IoResStatus,\r
+ OUT UINT64 *Mem32ResStatus,\r
+ OUT UINT64 *PMem32ResStatus,\r
+ OUT UINT64 *Mem64ResStatus,\r
+ OUT UINT64 *PMem64ResStatus\r
+ )\r
+{\r
+ UINT8 *Temp;\r
+ UINT64 ResStatus;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ACPIAddressDesc;\r
+\r
+ Temp = (UINT8 *) AcpiConfig;\r
+\r
+ while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
+\r
+ ACPIAddressDesc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;\r
+ ResStatus = ACPIAddressDesc->AddrTranslationOffset;\r
+\r
+ switch (ACPIAddressDesc->ResType) {\r
+ case 0:\r
+ if (ACPIAddressDesc->AddrSpaceGranularity == 32) {\r
+ if (ACPIAddressDesc->SpecificFlag == 0x06) {\r
+ //\r
+ // Pmem32\r
+ //\r
+ *PMem32ResStatus = ResStatus;\r
+ } else {\r
+ //\r
+ // Mem32\r
+ //\r
+ *Mem32ResStatus = ResStatus;\r
+ }\r
+ }\r
+\r
+ if (ACPIAddressDesc->AddrSpaceGranularity == 64) {\r
+ if (ACPIAddressDesc->SpecificFlag == 0x06) {\r
+ //\r
+ // PMem64\r
+ //\r
+ *PMem64ResStatus = ResStatus;\r
+ } else {\r
+ //\r
+ // Mem64\r
+ //\r
+ *Mem64ResStatus = ResStatus;\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ case 1:\r
+ //\r
+ // Io\r
+ //\r
+ *IoResStatus = ResStatus;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
+ }\r
+}\r
+\r
+/**\r
+ Remove a PCI device from device pool and mark its bar.\r
+\r
+ @param PciDevice Instance of Pci device.\r
+\r
+ @retval EFI_SUCCESS Successfully remove the PCI device.\r
+ @retval EFI_ABORTED Pci device is a root bridge or a PCI-PCI bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+RejectPciDevice (\r
+ IN PCI_IO_DEVICE *PciDevice\r
+ )\r
+{\r
+ PCI_IO_DEVICE *Bridge;\r
+ PCI_IO_DEVICE *Temp;\r
+ LIST_ENTRY *CurrentLink;\r
+\r
+ //\r
+ // Remove the padding resource from a bridge\r
+ //\r
+ if ( IS_PCI_BRIDGE(&PciDevice->Pci) &&\r
+ PciDevice->ResourcePaddingDescriptors != NULL ) {\r
+ FreePool (PciDevice->ResourcePaddingDescriptors);\r
+ PciDevice->ResourcePaddingDescriptors = NULL;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Skip RB and PPB\r
+ //\r
+ if (IS_PCI_BRIDGE (&PciDevice->Pci) || (PciDevice->Parent == NULL)) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (IS_CARDBUS_BRIDGE (&PciDevice->Pci)) {\r
+ //\r
+ // Get the root bridge device\r
+ //\r
+ Bridge = PciDevice;\r
+ while (Bridge->Parent != NULL) {\r
+ Bridge = Bridge->Parent;\r
+ }\r
+\r
+ RemoveAllPciDeviceOnBridge (Bridge->Handle, PciDevice);\r
+\r
+ //\r
+ // Mark its bar\r
+ //\r
+ InitializeP2C (PciDevice);\r
+ }\r
+\r
+ //\r
+ // Remove the device\r
+ //\r
+ Bridge = PciDevice->Parent;\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+ while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+ if (Temp == PciDevice) {\r
+ InitializePciDevice (Temp);\r
+ RemoveEntryList (CurrentLink);\r
+ FreePciDevice (Temp);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ return EFI_ABORTED;\r
+}\r
+\r
+/**\r
+ Determine whethter a PCI device can be rejected.\r
+\r
+ @param PciResNode Pointer to Pci resource node instance.\r
+\r
+ @retval TRUE The PCI device can be rejected.\r
+ @retval TRUE The PCI device cannot be rejected.\r
+\r
+**/\r
+BOOLEAN\r
+IsRejectiveDevice (\r
+ IN PCI_RESOURCE_NODE *PciResNode\r
+ )\r
+{\r
+ PCI_IO_DEVICE *Temp;\r
+\r
+ Temp = PciResNode->PciDev;\r
+\r
+ //\r
+ // Ensure the device is present\r
+ //\r
+ if (Temp == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // PPB and RB should go ahead\r
+ //\r
+ if (IS_PCI_BRIDGE (&Temp->Pci) || (Temp->Parent == NULL)) {\r
+ return TRUE;\r
+ }\r
+\r
+ //\r
+ // Skip device on Bus0\r
+ //\r
+ if ((Temp->Parent != NULL) && (Temp->BusNumber == 0)) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Skip VGA\r
+ //\r
+ if (IS_PCI_VGA (&Temp->Pci)) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Compare two resource nodes and get the larger resource consumer.\r
+\r
+ @param PciResNode1 resource node 1 want to be compared\r
+ @param PciResNode2 resource node 2 want to be compared\r
+\r
+ @return Larger resource node.\r
+\r
+**/\r
+PCI_RESOURCE_NODE *\r
+GetLargerConsumerDevice (\r
+ IN PCI_RESOURCE_NODE *PciResNode1,\r
+ IN PCI_RESOURCE_NODE *PciResNode2\r
+ )\r
+{\r
+ if (PciResNode2 == NULL) {\r
+ return PciResNode1;\r
+ }\r
+\r
+ if ((IS_PCI_BRIDGE(&(PciResNode2->PciDev->Pci)) || (PciResNode2->PciDev->Parent == NULL)) \\r
+ && (PciResNode2->ResourceUsage != PciResUsagePadding) )\r
+ {\r
+ return PciResNode1;\r
+ }\r
+\r
+ if (PciResNode1 == NULL) {\r
+ return PciResNode2;\r
+ }\r
+\r
+ if ((PciResNode1->Length) > (PciResNode2->Length)) {\r
+ return PciResNode1;\r
+ }\r
+\r
+ return PciResNode2;\r
+}\r
+\r
+\r
+/**\r
+ Get the max resource consumer in the host resource pool.\r
+\r
+ @param ResPool Pointer to resource pool node.\r
+\r
+ @return The max resource consumer in the host resource pool.\r
+\r
+**/\r
+PCI_RESOURCE_NODE *\r
+GetMaxResourceConsumerDevice (\r
+ IN PCI_RESOURCE_NODE *ResPool\r
+ )\r
+{\r
+ PCI_RESOURCE_NODE *Temp;\r
+ LIST_ENTRY *CurrentLink;\r
+ PCI_RESOURCE_NODE *PciResNode;\r
+ PCI_RESOURCE_NODE *PPBResNode;\r
+\r
+ PciResNode = NULL;\r
+\r
+ CurrentLink = ResPool->ChildList.ForwardLink;\r
+ while (CurrentLink != NULL && CurrentLink != &ResPool->ChildList) {\r
+\r
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+ if (!IsRejectiveDevice (Temp)) {\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ continue;\r
+ }\r
+\r
+ if ((IS_PCI_BRIDGE (&(Temp->PciDev->Pci)) || (Temp->PciDev->Parent == NULL)) \\r
+ && (Temp->ResourceUsage != PciResUsagePadding))\r
+ {\r
+ PPBResNode = GetMaxResourceConsumerDevice (Temp);\r
+ PciResNode = GetLargerConsumerDevice (PciResNode, PPBResNode);\r
+ } else {\r
+ PciResNode = GetLargerConsumerDevice (PciResNode, Temp);\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ return PciResNode;\r
+}\r
+\r
+/**\r
+ Adjust host bridge allocation so as to reduce resource requirement\r
+\r
+ @param IoPool Pointer to instance of I/O resource Node.\r
+ @param Mem32Pool Pointer to instance of 32-bit memory resource Node.\r
+ @param PMem32Pool Pointer to instance of 32-bit Prefetchable memory resource node.\r
+ @param Mem64Pool Pointer to instance of 64-bit memory resource node.\r
+ @param PMem64Pool Pointer to instance of 64-bit Prefetchable memory resource node.\r
+ @param IoResStatus Status of I/O resource Node.\r
+ @param Mem32ResStatus Status of 32-bit memory resource Node.\r
+ @param PMem32ResStatus Status of 32-bit Prefetchable memory resource node.\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_ABORTED Host bridge hasn't this resource type or no resource be adjusted.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeAdjustAllocation (\r
+ IN PCI_RESOURCE_NODE *IoPool,\r
+ IN PCI_RESOURCE_NODE *Mem32Pool,\r
+ IN PCI_RESOURCE_NODE *PMem32Pool,\r
+ IN PCI_RESOURCE_NODE *Mem64Pool,\r
+ IN PCI_RESOURCE_NODE *PMem64Pool,\r
+ IN UINT64 IoResStatus,\r
+ IN UINT64 Mem32ResStatus,\r
+ IN UINT64 PMem32ResStatus,\r
+ IN UINT64 Mem64ResStatus,\r
+ IN UINT64 PMem64ResStatus\r
+ )\r
+{\r
+ BOOLEAN AllocationAjusted;\r
+ PCI_RESOURCE_NODE *PciResNode;\r
+ PCI_RESOURCE_NODE *ResPool[5];\r
+ PCI_IO_DEVICE *RemovedPciDev[5];\r
+ UINT64 ResStatus[5];\r
+ UINTN RemovedPciDevNum;\r
+ UINTN DevIndex;\r
+ UINTN ResType;\r
+ EFI_STATUS Status;\r
+ EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;\r
+\r
+ PciResNode = NULL;\r
+ ZeroMem (RemovedPciDev, 5 * sizeof (PCI_IO_DEVICE *));\r
+ RemovedPciDevNum = 0;\r
+\r
+ ResPool[0] = IoPool;\r
+ ResPool[1] = Mem32Pool;\r
+ ResPool[2] = PMem32Pool;\r
+ ResPool[3] = Mem64Pool;\r
+ ResPool[4] = PMem64Pool;\r
+\r
+ ResStatus[0] = IoResStatus;\r
+ ResStatus[1] = Mem32ResStatus;\r
+ ResStatus[2] = PMem32ResStatus;\r
+ ResStatus[3] = Mem64ResStatus;\r
+ ResStatus[4] = PMem64ResStatus;\r
+\r
+ AllocationAjusted = FALSE;\r
+\r
+ for (ResType = 0; ResType < 5; ResType++) {\r
+\r
+ if (ResStatus[ResType] == EFI_RESOURCE_SATISFIED) {\r
+ continue;\r
+ }\r
+\r
+ if (ResStatus[ResType] == EFI_RESOURCE_NOT_SATISFIED) {\r
+ //\r
+ // Host bridge hasn't this resource type\r
+ //\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // Hostbridge hasn't enough resource\r
+ //\r
+ PciResNode = GetMaxResourceConsumerDevice (ResPool[ResType]);\r
+ if (PciResNode == NULL) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Check if the device has been removed before\r
+ //\r
+ for (DevIndex = 0; DevIndex < RemovedPciDevNum; DevIndex++) {\r
+ if (PciResNode->PciDev == RemovedPciDev[DevIndex]) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (DevIndex != RemovedPciDevNum) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Remove the device if it isn't in the array\r
+ //\r
+ Status = RejectPciDevice (PciResNode->PciDev);\r
+ if (Status == EFI_SUCCESS) {\r
+\r
+ //\r
+ // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
+ //\r
+ //\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.DevicePath = (UINT8 *) PciResNode->PciDev->DevicePath;\r
+ AllocFailExtendedData.Bar = PciResNode->Bar;\r
+\r
+ REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
+ EFI_PROGRESS_CODE,\r
+ EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,\r
+ (VOID *) &AllocFailExtendedData,\r
+ sizeof (AllocFailExtendedData)\r
+ );\r
+\r
+ //\r
+ // Add it to the array and indicate at least a device has been rejected\r
+ //\r
+ RemovedPciDev[RemovedPciDevNum++] = PciResNode->PciDev;\r
+ AllocationAjusted = TRUE;\r
+ }\r
+ }\r
+ //\r
+ // End for\r
+ //\r
+\r
+ if (AllocationAjusted) {\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return EFI_ABORTED;\r
+ }\r
+}\r
+\r
+/**\r
+ Summary requests for all resource type, and contruct ACPI resource\r
+ requestor instance.\r
+\r
+ @param Bridge detecting bridge\r
+ @param IoNode Pointer to instance of I/O resource Node\r
+ @param Mem32Node Pointer to instance of 32-bit memory resource Node\r
+ @param PMem32Node Pointer to instance of 32-bit Pmemory resource node\r
+ @param Mem64Node Pointer to instance of 64-bit memory resource node\r
+ @param PMem64Node Pointer to instance of 64-bit Pmemory resource node\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
+\r
+**/\r
+EFI_STATUS\r
+ConstructAcpiResourceRequestor (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN PCI_RESOURCE_NODE *IoNode,\r
+ IN PCI_RESOURCE_NODE *Mem32Node,\r
+ IN PCI_RESOURCE_NODE *PMem32Node,\r
+ IN PCI_RESOURCE_NODE *Mem64Node,\r
+ IN PCI_RESOURCE_NODE *PMem64Node,\r
+ OUT VOID **Config\r
+ )\r
+{\r
+ UINT8 NumConfig;\r
+ UINT8 Aperture;\r
+ UINT8 *Configuration;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
+ EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;\r
+\r
+ NumConfig = 0;\r
+ Aperture = 0;\r
+\r
+ *Config = NULL;\r
+\r
+ //\r
+ // if there is io request, add to the io aperture\r
+ //\r
+ if (ResourceRequestExisted (IoNode)) {\r
+ NumConfig++;\r
+ Aperture |= 0x01;\r
+ }\r
+\r
+ //\r
+ // if there is mem32 request, add to the mem32 aperture\r
+ //\r
+ if (ResourceRequestExisted (Mem32Node)) {\r
+ NumConfig++;\r
+ Aperture |= 0x02;\r
+ }\r
+\r
+ //\r
+ // if there is pmem32 request, add to the pmem32 aperture\r
+ //\r
+ if (ResourceRequestExisted (PMem32Node)) {\r
+ NumConfig++;\r
+ Aperture |= 0x04;\r
+ }\r
+\r
+ //\r
+ // if there is mem64 request, add to the mem64 aperture\r
+ //\r
+ if (ResourceRequestExisted (Mem64Node)) {\r
+ NumConfig++;\r
+ Aperture |= 0x08;\r
+ }\r
+\r
+ //\r
+ // if there is pmem64 request, add to the pmem64 aperture\r
+ //\r
+ if (ResourceRequestExisted (PMem64Node)) {\r
+ NumConfig++;\r
+ Aperture |= 0x10;\r
+ }\r
+\r
+ if (NumConfig != 0) {\r
+\r
+ //\r
+ // If there is at least one type of resource request,\r
+ // allocate a acpi resource node\r
+ //\r
+ Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + 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
+\r
+ //\r
+ // Deal with io aperture\r
+ //\r
+ if ((Aperture & 0x01) != 0) {\r
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+ //\r
+ // Io\r
+ //\r
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
+ //\r
+ // non ISA range\r
+ //\r
+ Ptr->SpecificFlag = 1;\r
+ Ptr->AddrLen = IoNode->Length;\r
+ Ptr->AddrRangeMax = IoNode->Alignment;\r
+\r
+ Ptr++;\r
+ }\r
+ //\r
+ // Deal with mem32 aperture\r
+ //\r
+ if ((Aperture & 0x02) != 0) {\r
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+ //\r
+ // Mem\r
+ //\r
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ //\r
+ // Nonprefechable\r
+ //\r
+ Ptr->SpecificFlag = 0;\r
+ //\r
+ // 32 bit\r
+ //\r
+ Ptr->AddrSpaceGranularity = 32;\r
+ Ptr->AddrLen = Mem32Node->Length;\r
+ Ptr->AddrRangeMax = Mem32Node->Alignment;\r
+\r
+ Ptr++;\r
+ }\r
+\r
+ //\r
+ // Deal with Pmem32 aperture\r
+ //\r
+ if ((Aperture & 0x04) != 0) {\r
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+ //\r
+ // Mem\r
+ //\r
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ //\r
+ // prefechable\r
+ //\r
+ Ptr->SpecificFlag = 0x6;\r
+ //\r
+ // 32 bit\r
+ //\r
+ Ptr->AddrSpaceGranularity = 32;\r
+ Ptr->AddrLen = PMem32Node->Length;\r
+ Ptr->AddrRangeMax = PMem32Node->Alignment;\r
+\r
+ Ptr++;\r
+ }\r
+ //\r
+ // Deal with mem64 aperture\r
+ //\r
+ if ((Aperture & 0x08) != 0) {\r
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+ //\r
+ // Mem\r
+ //\r
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ //\r
+ // nonprefechable\r
+ //\r
+ Ptr->SpecificFlag = 0;\r
+ //\r
+ // 64 bit\r
+ //\r
+ Ptr->AddrSpaceGranularity = 64;\r
+ Ptr->AddrLen = Mem64Node->Length;\r
+ Ptr->AddrRangeMax = Mem64Node->Alignment;\r
+\r
+ Ptr++;\r
+ }\r
+ //\r
+ // Deal with Pmem64 aperture\r
+ //\r
+ if ((Aperture & 0x10) != 0) {\r
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+ //\r
+ // Mem\r
+ //\r
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ //\r
+ // prefechable\r
+ //\r
+ Ptr->SpecificFlag = 0x06;\r
+ //\r
+ // 64 bit\r
+ //\r
+ Ptr->AddrSpaceGranularity = 64;\r
+ Ptr->AddrLen = PMem64Node->Length;\r
+ Ptr->AddrRangeMax = PMem64Node->Alignment;\r
+\r
+ Ptr++;\r
+ }\r
+\r
+ //\r
+ // put the checksum\r
+ //\r
+ PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr;\r
+\r
+ PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+ PtrEnd->Checksum = 0;\r
+\r
+ } else {\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
+ 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->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+ PtrEnd->Checksum = 0;\r
+ }\r
+\r
+ *Config = Configuration;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Get resource base from an acpi configuration descriptor.\r
+\r
+ @param Config An acpi configuration descriptor.\r
+ @param IoBase Output of I/O resource base address.\r
+ @param Mem32Base Output of 32-bit memory base address.\r
+ @param PMem32Base Output of 32-bit prefetchable memory base address.\r
+ @param Mem64Base Output of 64-bit memory base address.\r
+ @param PMem64Base Output of 64-bit prefetchable memory base address.\r
+\r
+**/\r
+VOID\r
+GetResourceBase (\r
+ IN VOID *Config,\r
+ OUT UINT64 *IoBase,\r
+ OUT UINT64 *Mem32Base,\r
+ OUT UINT64 *PMem32Base,\r
+ OUT UINT64 *Mem64Base,\r
+ OUT UINT64 *PMem64Base\r
+ )\r
+{\r
+ UINT8 *Temp;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
+ UINT64 ResStatus;\r
+\r
+ ASSERT (Config != NULL);\r
+\r
+ *IoBase = 0xFFFFFFFFFFFFFFFFULL;\r
+ *Mem32Base = 0xFFFFFFFFFFFFFFFFULL;\r
+ *PMem32Base = 0xFFFFFFFFFFFFFFFFULL;\r
+ *Mem64Base = 0xFFFFFFFFFFFFFFFFULL;\r
+ *PMem64Base = 0xFFFFFFFFFFFFFFFFULL;\r
+\r
+ Temp = (UINT8 *) Config;\r
+\r
+ while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
+\r
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;\r
+ ResStatus = Ptr->AddrTranslationOffset;\r
+\r
+ if (ResStatus == EFI_RESOURCE_SATISFIED) {\r
+\r
+ switch (Ptr->ResType) {\r
+\r
+ //\r
+ // Memory type aperture\r
+ //\r
+ case 0:\r
+\r
+ //\r
+ // Check to see the granularity\r
+ //\r
+ if (Ptr->AddrSpaceGranularity == 32) {\r
+ if ((Ptr->SpecificFlag & 0x06) != 0) {\r
+ *PMem32Base = Ptr->AddrRangeMin;\r
+ } else {\r
+ *Mem32Base = Ptr->AddrRangeMin;\r
+ }\r
+ }\r
+\r
+ if (Ptr->AddrSpaceGranularity == 64) {\r
+ if ((Ptr->SpecificFlag & 0x06) != 0) {\r
+ *PMem64Base = Ptr->AddrRangeMin;\r
+ } else {\r
+ *Mem64Base = Ptr->AddrRangeMin;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case 1:\r
+\r
+ //\r
+ // Io type aperture\r
+ //\r
+ *IoBase = Ptr->AddrRangeMin;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+\r
+ }\r
+ //\r
+ // End switch\r
+ //\r
+ }\r
+ //\r
+ // End for\r
+ //\r
+ Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
+ }\r
+}\r
+\r
+/**\r
+ Enumerate pci bridge, allocate resource and determine attribute\r
+ for devices on this bridge.\r
+\r
+ @param BridgeDev Pointer to instance of bridge device.\r
+\r
+ @retval EFI_SUCCESS Successfully enumerated PCI bridge.\r
+ @retval other Failed to enumerate.\r
+\r
+**/\r
+EFI_STATUS\r
+PciBridgeEnumerator (\r
+ IN PCI_IO_DEVICE *BridgeDev\r
+ )\r
+{\r
+ UINT8 SubBusNumber;\r
+ UINT8 StartBusNumber;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_STATUS Status;\r
+\r
+ SubBusNumber = 0;\r
+ StartBusNumber = 0;\r
+ PciIo = &(BridgeDev->PciIo);\r
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &StartBusNumber);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PciAssignBusNumber (\r
+ BridgeDev,\r
+ StartBusNumber,\r
+ &SubBusNumber\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PciPciDeviceInfoCollector (BridgeDev, StartBusNumber);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PciBridgeResourceAllocator (BridgeDev);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = DetermineDeviceAttribute (BridgeDev);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+ Allocate all kinds of resource for PCI bridge.\r
+\r
+ @param Bridge Pointer to bridge instance.\r
+\r
+ @retval EFI_SUCCESS Successfully allocated resource for PCI bridge.\r
+ @retval other Failed to allocate resource for bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciBridgeResourceAllocator (\r
+ IN PCI_IO_DEVICE *Bridge\r
+ )\r
+{\r
+ PCI_RESOURCE_NODE *IoBridge;\r
+ PCI_RESOURCE_NODE *Mem32Bridge;\r
+ PCI_RESOURCE_NODE *PMem32Bridge;\r
+ PCI_RESOURCE_NODE *Mem64Bridge;\r
+ PCI_RESOURCE_NODE *PMem64Bridge;\r
+ UINT64 IoBase;\r
+ UINT64 Mem32Base;\r
+ UINT64 PMem32Base;\r
+ UINT64 Mem64Base;\r
+ UINT64 PMem64Base;\r
+ EFI_STATUS Status;\r
+\r
+ IoBridge = CreateResourceNode (\r
+ Bridge,\r
+ 0,\r
+ 0xFFF,\r
+ 0,\r
+ PciBarTypeIo16,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ Mem32Bridge = CreateResourceNode (\r
+ Bridge,\r
+ 0,\r
+ 0xFFFFF,\r
+ 0,\r
+ PciBarTypeMem32,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ PMem32Bridge = CreateResourceNode (\r
+ Bridge,\r
+ 0,\r
+ 0xFFFFF,\r
+ 0,\r
+ PciBarTypePMem32,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ Mem64Bridge = CreateResourceNode (\r
+ Bridge,\r
+ 0,\r
+ 0xFFFFF,\r
+ 0,\r
+ PciBarTypeMem64,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ PMem64Bridge = CreateResourceNode (\r
+ Bridge,\r
+ 0,\r
+ 0xFFFFF,\r
+ 0,\r
+ PciBarTypePMem64,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ //\r
+ // Create resourcemap by going through all the devices subject to this root bridge\r
+ //\r
+ CreateResourceMap (\r
+ Bridge,\r
+ IoBridge,\r
+ Mem32Bridge,\r
+ PMem32Bridge,\r
+ Mem64Bridge,\r
+ PMem64Bridge\r
+ );\r
+\r
+ Status = GetResourceBaseFromBridge (\r
+ Bridge,\r
+ &IoBase,\r
+ &Mem32Base,\r
+ &PMem32Base,\r
+ &Mem64Base,\r
+ &PMem64Base\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Program IO resources\r
+ //\r
+ ProgramResource (\r
+ IoBase,\r
+ IoBridge\r
+ );\r
+\r
+ //\r
+ // Program Mem32 resources\r
+ //\r
+ ProgramResource (\r
+ Mem32Base,\r
+ Mem32Bridge\r
+ );\r
+\r
+ //\r
+ // Program PMem32 resources\r
+ //\r
+ ProgramResource (\r
+ PMem32Base,\r
+ PMem32Bridge\r
+ );\r
+\r
+ //\r
+ // Program Mem64 resources\r
+ //\r
+ ProgramResource (\r
+ Mem64Base,\r
+ Mem64Bridge\r
+ );\r
+\r
+ //\r
+ // Program PMem64 resources\r
+ //\r
+ ProgramResource (\r
+ PMem64Base,\r
+ PMem64Bridge\r
+ );\r
+\r
+ DestroyResourceTree (IoBridge);\r
+ DestroyResourceTree (Mem32Bridge);\r
+ DestroyResourceTree (PMem32Bridge);\r
+ DestroyResourceTree (PMem64Bridge);\r
+ DestroyResourceTree (Mem64Bridge);\r
+\r
+ gBS->FreePool (IoBridge);\r
+ gBS->FreePool (Mem32Bridge);\r
+ gBS->FreePool (PMem32Bridge);\r
+ gBS->FreePool (PMem64Bridge);\r
+ gBS->FreePool (Mem64Bridge);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Get resource base address for a pci bridge device.\r
+\r
+ @param Bridge Given Pci driver instance.\r
+ @param IoBase Output for base address of I/O type resource.\r
+ @param Mem32Base Output for base address of 32-bit memory type resource.\r
+ @param PMem32Base Ooutput for base address of 32-bit Pmemory type resource.\r
+ @param Mem64Base Output for base address of 64-bit memory type resource.\r
+ @param PMem64Base Output for base address of 64-bit Pmemory type resource.\r
+\r
+ @retval EFI_SUCCESS Successfully got resource base address.\r
+ @retval EFI_OUT_OF_RESOURCES PCI bridge is not available.\r
+\r
+**/\r
+EFI_STATUS\r
+GetResourceBaseFromBridge (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ OUT UINT64 *IoBase,\r
+ OUT UINT64 *Mem32Base,\r
+ OUT UINT64 *PMem32Base,\r
+ OUT UINT64 *Mem64Base,\r
+ OUT UINT64 *PMem64Base\r
+ )\r
+{\r
+ if (!Bridge->Allocated) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ *IoBase = gAllOne;\r
+ *Mem32Base = gAllOne;\r
+ *PMem32Base = gAllOne;\r
+ *Mem64Base = gAllOne;\r
+ *PMem64Base = gAllOne;\r
+\r
+ if (IS_PCI_BRIDGE (&Bridge->Pci)) {\r
+\r
+ if (Bridge->PciBar[PPB_IO_RANGE].Length > 0) {\r
+ *IoBase = Bridge->PciBar[PPB_IO_RANGE].BaseAddress;\r
+ }\r
+\r
+ if (Bridge->PciBar[PPB_MEM32_RANGE].Length > 0) {\r
+ *Mem32Base = Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress;\r
+ }\r
+\r
+ if (Bridge->PciBar[PPB_PMEM32_RANGE].Length > 0) {\r
+ *PMem32Base = Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress;\r
+ }\r
+\r
+ if (Bridge->PciBar[PPB_PMEM64_RANGE].Length > 0) {\r
+ *PMem64Base = Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress;\r
+ } else {\r
+ *PMem64Base = gAllOne;\r
+ }\r
+\r
+ }\r
+\r
+ if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) {\r
+ if (Bridge->PciBar[P2C_IO_1].Length > 0) {\r
+ *IoBase = Bridge->PciBar[P2C_IO_1].BaseAddress;\r
+ } else {\r
+ if (Bridge->PciBar[P2C_IO_2].Length > 0) {\r
+ *IoBase = Bridge->PciBar[P2C_IO_2].BaseAddress;\r
+ }\r
+ }\r
+\r
+ if (Bridge->PciBar[P2C_MEM_1].Length > 0) {\r
+ if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypePMem32) {\r
+ *PMem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;\r
+ }\r
+\r
+ if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypeMem32) {\r
+ *Mem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;\r
+ }\r
+ }\r
+\r
+ if (Bridge->PciBar[P2C_MEM_2].Length > 0) {\r
+ if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypePMem32) {\r
+ *PMem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;\r
+ }\r
+\r
+ if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypeMem32) {\r
+ *Mem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ These are the notifications from the PCI bus driver that it is about to enter a certain\r
+ phase of the PCI enumeration process.\r
+\r
+ This member function can be used to notify the host bridge driver to perform specific actions,\r
+ including any chipset-specific initialization, so that the chipset is ready to enter the next phase.\r
+ Eight notification points are defined at this time. See belows:\r
+ EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data\r
+ structures. The PCI enumerator should issue this notification\r
+ before starting a fresh enumeration process. Enumeration cannot\r
+ be restarted after sending any other notification such as\r
+ EfiPciHostBridgeBeginBusAllocation.\r
+ EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is\r
+ required here. This notification can be used to perform any\r
+ chipset-specific programming.\r
+ EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No\r
+ specific action is required here. This notification can be used to\r
+ perform any chipset-specific programming.\r
+ EfiPciHostBridgeBeginResourceAllocation\r
+ The resource allocation phase is about to begin. No specific\r
+ action is required here. This notification can be used to perform\r
+ any chipset-specific programming.\r
+ EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI\r
+ root bridges. These resource settings are returned on the next call to\r
+ GetProposedResources(). Before calling NotifyPhase() with a Phase of\r
+ EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible\r
+ for gathering I/O and memory requests for\r
+ all the PCI root bridges and submitting these requests using\r
+ SubmitResources(). This function pads the resource amount\r
+ to suit the root bridge hardware, takes care of dependencies between\r
+ the PCI root bridges, and calls the Global Coherency Domain (GCD)\r
+ with the allocation request. In the case of padding, the allocated range\r
+ could be bigger than what was requested.\r
+ EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated\r
+ resources (proposed resources) for all the PCI root bridges. After the\r
+ hardware is programmed, reassigning resources will not be supported.\r
+ The bus settings are not affected.\r
+ EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI\r
+ root bridges and resets the I/O and memory apertures to their initial\r
+ state. The bus settings are not affected. If the request to allocate\r
+ resources fails, the PCI enumerator can use this notification to\r
+ deallocate previous resources, adjust the requests, and retry\r
+ allocation.\r
+ EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is\r
+ required here. This notification can be used to perform any chipsetspecific\r
+ programming.\r
+\r
+ @param[in] PciResAlloc The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
+ @param[in] Phase The phase during enumeration\r
+\r
+ @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error\r
+ is valid for a Phase of EfiPciHostBridgeAllocateResources if\r
+ SubmitResources() has not been called for one or more\r
+ PCI root bridges before this call\r
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid\r
+ for a Phase of EfiPciHostBridgeSetResources.\r
+ @retval EFI_INVALID_PARAMETER Invalid phase parameter\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the\r
+ previously submitted resource requests cannot be fulfilled or\r
+ were only partially fulfilled.\r
+ @retval EFI_SUCCESS The notification was accepted without any errors.\r
+\r
+**/\r
+EFI_STATUS\r
+NotifyPhase (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase\r
+ )\r
+{\r
+ EFI_HANDLE HostBridgeHandle;\r
+ EFI_HANDLE RootBridgeHandle;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+ EFI_STATUS Status;\r
+\r
+ HostBridgeHandle = NULL;\r
+ RootBridgeHandle = NULL;\r
+ if (gPciPlatformProtocol != NULL) {\r
+ //\r
+ // Get Host Bridge Handle.\r
+ //\r
+ PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);\r
+\r
+ //\r
+ // Get the rootbridge Io protocol to find the host bridge handle\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ RootBridgeHandle,\r
+ &gEfiPciRootBridgeIoProtocolGuid,\r
+ (VOID **) &PciRootBridgeIo\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ HostBridgeHandle = PciRootBridgeIo->ParentHandle;\r
+\r
+ //\r
+ // Call PlatformPci::PlatformNotify() if the protocol is present.\r
+ //\r
+ gPciPlatformProtocol->PlatformNotify (\r
+ gPciPlatformProtocol,\r
+ HostBridgeHandle,\r
+ Phase,\r
+ ChipsetEntry\r
+ );\r
+ } else if (gPciOverrideProtocol != NULL){\r
+ //\r
+ // Get Host Bridge Handle.\r
+ //\r
+ PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);\r
+\r
+ //\r
+ // Get the rootbridge Io protocol to find the host bridge handle\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ RootBridgeHandle,\r
+ &gEfiPciRootBridgeIoProtocolGuid,\r
+ (VOID **) &PciRootBridgeIo\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ HostBridgeHandle = PciRootBridgeIo->ParentHandle;\r
+\r
+ //\r
+ // Call PlatformPci::PhaseNotify() if the protocol is present.\r
+ //\r
+ gPciOverrideProtocol->PlatformNotify (\r
+ gPciOverrideProtocol,\r
+ HostBridgeHandle,\r
+ Phase,\r
+ ChipsetEntry\r
+ );\r
+ } \r
+\r
+ Status = PciResAlloc->NotifyPhase (\r
+ PciResAlloc,\r
+ Phase\r
+ );\r
+\r
+ if (gPciPlatformProtocol != NULL) {\r
+ //\r
+ // Call PlatformPci::PlatformNotify() if the protocol is present.\r
+ //\r
+ gPciPlatformProtocol->PlatformNotify (\r
+ gPciPlatformProtocol,\r
+ HostBridgeHandle,\r
+ Phase,\r
+ ChipsetExit\r
+ );\r
+\r
+ } else if (gPciOverrideProtocol != NULL) {\r
+ //\r
+ // Call PlatformPci::PhaseNotify() if the protocol is present.\r
+ //\r
+ gPciOverrideProtocol->PlatformNotify (\r
+ gPciOverrideProtocol,\r
+ HostBridgeHandle,\r
+ Phase,\r
+ ChipsetExit\r
+ );\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various\r
+ stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual\r
+ PCI controllers before enumeration.\r
+\r
+ This function is called during the PCI enumeration process. No specific action is expected from this\r
+ member function. It allows the host bridge driver to preinitialize individual PCI controllers before\r
+ enumeration.\r
+\r
+ @param Bridge Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.\r
+ @param Bus The bus number of the pci device.\r
+ @param Device The device number of the pci device.\r
+ @param Func The function number of the pci device.\r
+ @param Phase The phase of the PCI device enumeration.\r
+\r
+ @retval EFI_SUCCESS The requested parameters were returned.\r
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.\r
+ @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in\r
+ EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.\r
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should\r
+ not enumerate this device, including its child devices if it is a PCI-to-PCI\r
+ bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PreprocessController (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN UINT8 Bus,\r
+ IN UINT8 Device,\r
+ IN UINT8 Func,\r
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase\r
+ )\r
+{\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress;\r
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc;\r
+ EFI_HANDLE RootBridgeHandle;\r
+ EFI_HANDLE HostBridgeHandle;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Get the host bridge handle\r
+ //\r
+ HostBridgeHandle = Bridge->PciRootBridgeIo->ParentHandle;\r
+\r
+ //\r
+ // Get the pci host bridge resource allocation protocol\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ HostBridgeHandle,\r
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid,\r
+ (VOID **) &PciResAlloc,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Get Root Brige Handle\r
+ //\r
+ while (Bridge->Parent != NULL) {\r
+ Bridge = Bridge->Parent;\r
+ }\r
+\r
+ RootBridgeHandle = Bridge->Handle;\r
+\r
+ RootBridgePciAddress.Register = 0;\r
+ RootBridgePciAddress.Function = Func;\r
+ RootBridgePciAddress.Device = Device;\r
+ RootBridgePciAddress.Bus = Bus;\r
+ RootBridgePciAddress.ExtendedRegister = 0;\r
+\r
+ if (gPciPlatformProtocol != NULL) {\r
+ //\r
+ // Call PlatformPci::PrepController() if the protocol is present.\r
+ //\r
+ gPciPlatformProtocol->PlatformPrepController (\r
+ gPciPlatformProtocol,\r
+ HostBridgeHandle,\r
+ RootBridgeHandle,\r
+ RootBridgePciAddress,\r
+ Phase,\r
+ ChipsetEntry\r
+ );\r
+ } else if (gPciOverrideProtocol != NULL) {\r
+ //\r
+ // Call PlatformPci::PrepController() if the protocol is present.\r
+ //\r
+ gPciOverrideProtocol->PlatformPrepController (\r
+ gPciOverrideProtocol,\r
+ HostBridgeHandle,\r
+ RootBridgeHandle,\r
+ RootBridgePciAddress,\r
+ Phase,\r
+ ChipsetEntry\r
+ );\r
+ }\r
+\r
+ Status = PciResAlloc->PreprocessController (\r
+ PciResAlloc,\r
+ RootBridgeHandle,\r
+ RootBridgePciAddress,\r
+ Phase\r
+ );\r
+\r
+ if (gPciPlatformProtocol != NULL) {\r
+ //\r
+ // Call PlatformPci::PrepController() if the protocol is present.\r
+ //\r
+ gPciPlatformProtocol->PlatformPrepController (\r
+ gPciPlatformProtocol,\r
+ HostBridgeHandle,\r
+ RootBridgeHandle,\r
+ RootBridgePciAddress,\r
+ Phase,\r
+ ChipsetExit\r
+ );\r
+ } else if (gPciOverrideProtocol != NULL) {\r
+ //\r
+ // Call PlatformPci::PrepController() if the protocol is present.\r
+ //\r
+ gPciOverrideProtocol->PlatformPrepController (\r
+ gPciOverrideProtocol,\r
+ HostBridgeHandle,\r
+ RootBridgeHandle,\r
+ RootBridgePciAddress,\r
+ Phase,\r
+ ChipsetExit\r
+ );\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has\r
+ happened on the hot-plug controller. Currently, the operations include add operation and remove operation..\r
+\r
+ @param This A pointer to the hot plug request protocol.\r
+ @param Operation The operation the PCI bus driver is requested to make.\r
+ @param Controller The handle of the hot-plug controller.\r
+ @param RemainingDevicePath The remaining device path for the PCI-like hot-plug device.\r
+ @param NumberOfChildren The number of child handles.\r
+ For a add operation, it is an output parameter.\r
+ For a remove operation, it's an input parameter.\r
+ @param ChildHandleBuffer The buffer which contains the child handles.\r
+\r
+ @retval EFI_INVALID_PARAMETER Operation is not a legal value.\r
+ Controller is NULL or not a valid handle.\r
+ NumberOfChildren is NULL.\r
+ ChildHandleBuffer is NULL while Operation is add.\r
+ @retval EFI_OUT_OF_RESOURCES There are no enough resources to start the devices.\r
+ @retval EFI_NOT_FOUND Can not find bridge according to controller handle.\r
+ @retval EFI_SUCCESS The handles for the specified device have been created or destroyed\r
+ as requested, and for an add operation, the new handles are\r
+ returned in ChildHandleBuffer.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciHotPlugRequestNotify (\r
+ IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,\r
+ IN EFI_PCI_HOTPLUG_OPERATION Operation,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,\r
+ IN OUT UINT8 *NumberOfChildren,\r
+ IN OUT EFI_HANDLE * ChildHandleBuffer\r
+ )\r
+{\r
+ PCI_IO_DEVICE *Bridge;\r
+ PCI_IO_DEVICE *Temp;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINTN Index;\r
+ EFI_HANDLE RootBridgeHandle;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Check input parameter validity\r
+ //\r
+ if ((Controller == NULL) || (NumberOfChildren == NULL)){\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((Operation != EfiPciHotPlugRequestAdd) && (Operation != EfiPciHotplugRequestRemove)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Operation == EfiPciHotPlugRequestAdd){\r
+ if (ChildHandleBuffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ } else if ((Operation == EfiPciHotplugRequestRemove) && (*NumberOfChildren != 0)) {\r
+ if (ChildHandleBuffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+ \r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo,\r
+ gPciBusDriverBinding.DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Bridge = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);\r
+\r
+ //\r
+ // Get root bridge handle\r
+ //\r
+ Temp = Bridge;\r
+ while (Temp->Parent != NULL) {\r
+ Temp = Temp->Parent;\r
+ }\r
+\r
+ RootBridgeHandle = Temp->Handle;\r
+\r
+ if (Operation == EfiPciHotPlugRequestAdd) {\r
+\r
+ if (NumberOfChildren != NULL) {\r
+ *NumberOfChildren = 0;\r
+ }\r
+\r
+ if (IsListEmpty (&Bridge->ChildList)) {\r
+\r
+ Status = PciBridgeEnumerator (Bridge);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ Status = StartPciDevicesOnBridge (\r
+ RootBridgeHandle,\r
+ Bridge,\r
+ RemainingDevicePath,\r
+ NumberOfChildren,\r
+ ChildHandleBuffer\r
+ );\r
+\r
+ return Status;\r
+ }\r
+\r
+ if (Operation == EfiPciHotplugRequestRemove) {\r
+\r
+ if (*NumberOfChildren == 0) {\r
+ //\r
+ // Remove all devices on the bridge\r
+ //\r
+ RemoveAllPciDeviceOnBridge (RootBridgeHandle, Bridge);\r
+ return EFI_SUCCESS;\r
+\r
+ }\r
+\r
+ for (Index = 0; Index < *NumberOfChildren; Index++) {\r
+ //\r
+ // De register all the pci device\r
+ //\r
+ Status = DeRegisterPciDevice (RootBridgeHandle, ChildHandleBuffer[Index]);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ }\r
+ //\r
+ // End for\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Search hostbridge according to given handle\r
+\r
+ @param RootBridgeHandle Host bridge handle.\r
+\r
+ @retval TRUE Found host bridge handle.\r
+ @retval FALSE Not found hot bridge handle.\r
+\r
+**/\r
+BOOLEAN\r
+SearchHostBridgeHandle (\r
+ IN EFI_HANDLE RootBridgeHandle\r
+ )\r
+{\r
+ EFI_HANDLE HostBridgeHandle;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Get the rootbridge Io protocol to find the host bridge handle\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ RootBridgeHandle,\r
+ &gEfiPciRootBridgeIoProtocolGuid,\r
+ (VOID **) &PciRootBridgeIo,\r
+ gPciBusDriverBinding.DriverBindingHandle,\r
+ RootBridgeHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ HostBridgeHandle = PciRootBridgeIo->ParentHandle;\r
+ for (Index = 0; Index < gPciHostBridgeNumber; Index++) {\r
+ if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Add host bridge handle to global variable for enumerating.\r
+\r
+ @param HostBridgeHandle Host bridge handle.\r
+\r
+ @retval EFI_SUCCESS Successfully added host bridge.\r
+ @retval EFI_ABORTED Host bridge is NULL, or given host bridge\r
+ has been in host bridge list.\r
+\r
+**/\r
+EFI_STATUS\r
+AddHostBridgeEnumerator (\r
+ IN EFI_HANDLE HostBridgeHandle\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ if (HostBridgeHandle == NULL) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ for (Index = 0; Index < gPciHostBridgeNumber; Index++) {\r
+ if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {\r
+ return EFI_ABORTED;\r
+ }\r
+ }\r
+\r
+ if (Index < PCI_MAX_HOST_BRIDGE_NUM) {\r
+ gPciHostBrigeHandles[Index] = HostBridgeHandle;\r
+ gPciHostBridgeNumber++;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ PCI bus enumeration logic function declaration 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
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_ENUMERATOR_H_\r
+#define _EFI_PCI_ENUMERATOR_H_\r
+\r
+#include "PciResourceSupport.h"\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
+\r
+ @retval EFI_SUCCESS PCI enumeration finished successfully.\r
+ @retval other Some error occurred when enumerating the pci bus system.\r
+\r
+**/\r
+EFI_STATUS\r
+PciEnumerator (\r
+ IN EFI_HANDLE Controller\r
+ );\r
+\r
+/**\r
+ Enumerate PCI root bridge.\r
+\r
+ @param PciResAlloc Pointer to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
+ @param RootBridgeDev Instance of root bridge device.\r
+\r
+ @retval EFI_SUCCESS Successfully enumerated root bridge.\r
+ @retval other Failed to enumerate root bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciRootBridgeEnumerator (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
+ IN PCI_IO_DEVICE *RootBridgeDev\r
+ );\r
+\r
+/**\r
+ This routine is used to process all PCI devices' Option Rom\r
+ on a certain root bridge.\r
+\r
+ @param Bridge Given parent's root bridge.\r
+ @param RomBase Base address of ROM driver loaded from.\r
+ @param MaxLength Maximum rom size.\r
+\r
+**/\r
+VOID\r
+ProcessOptionRom (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN UINT64 RomBase,\r
+ IN UINT64 MaxLength\r
+ );\r
+\r
+/**\r
+ This routine is used to assign bus number to the given PCI bus system\r
+\r
+ @param Bridge Parent root bridge instance.\r
+ @param StartBusNumber Number of beginning.\r
+ @param SubBusNumber The number of sub bus.\r
+\r
+ @retval EFI_SUCCESS Successfully assigned bus number.\r
+ @retval EFI_DEVICE_ERROR Failed to assign bus number.\r
+\r
+**/\r
+EFI_STATUS\r
+PciAssignBusNumber (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN UINT8 StartBusNumber,\r
+ OUT UINT8 *SubBusNumber\r
+ );\r
+\r
+/**\r
+ This routine is used to determine the root bridge attribute by interfacing\r
+ the host bridge resource allocation protocol.\r
+\r
+ @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
+ @param RootBridgeDev Root bridge instance\r
+\r
+ @retval EFI_SUCCESS Successfully got root bridge's attribute.\r
+ @retval other Failed to get attribute.\r
+\r
+**/\r
+EFI_STATUS\r
+DetermineRootBridgeAttributes (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
+ IN PCI_IO_DEVICE *RootBridgeDev\r
+ );\r
+\r
+/**\r
+ Get Max Option Rom size on specified bridge.\r
+\r
+ @param Bridge Given bridge device instance.\r
+\r
+ @return Max size of option rom needed.\r
+\r
+**/\r
+UINT64\r
+GetMaxOptionRomSize (\r
+ IN PCI_IO_DEVICE *Bridge\r
+ );\r
+\r
+/**\r
+ Process attributes of devices on this host bridge\r
+\r
+ @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
+\r
+ @retval EFI_SUCCESS Successfully process attribute.\r
+ @retval EFI_NOT_FOUND Can not find the specific root bridge device.\r
+ @retval other Failed to determine the root bridge device's attribute.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeDeviceAttribute (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
+ );\r
+\r
+/**\r
+ Get resource allocation status from the ACPI resource descriptor.\r
+\r
+ @param AcpiConfig Point to Acpi configuration table.\r
+ @param IoResStatus Return the status of I/O resource.\r
+ @param Mem32ResStatus Return the status of 32-bit Memory resource.\r
+ @param PMem32ResStatus Return the status of 32-bit Prefetchable Memory resource.\r
+ @param Mem64ResStatus Return the status of 64-bit Memory resource.\r
+ @param PMem64ResStatus Return the status of 64-bit Prefetchable Memory resource.\r
+\r
+**/\r
+VOID\r
+GetResourceAllocationStatus (\r
+ VOID *AcpiConfig,\r
+ OUT UINT64 *IoResStatus,\r
+ OUT UINT64 *Mem32ResStatus,\r
+ OUT UINT64 *PMem32ResStatus,\r
+ OUT UINT64 *Mem64ResStatus,\r
+ OUT UINT64 *PMem64ResStatus\r
+ );\r
+\r
+/**\r
+ Remove a PCI device from device pool and mark its bar.\r
+\r
+ @param PciDevice Instance of Pci device.\r
+\r
+ @retval EFI_SUCCESS Successfully remove the PCI device.\r
+ @retval EFI_ABORTED Pci device is a root bridge or a PCI-PCI bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+RejectPciDevice (\r
+ IN PCI_IO_DEVICE *PciDevice\r
+ );\r
+\r
+/**\r
+ Determine whethter a PCI device can be rejected.\r
+\r
+ @param PciResNode Pointer to Pci resource node instance.\r
+\r
+ @retval TRUE The PCI device can be rejected.\r
+ @retval TRUE The PCI device cannot be rejected.\r
+\r
+**/\r
+BOOLEAN\r
+IsRejectiveDevice (\r
+ IN PCI_RESOURCE_NODE *PciResNode\r
+ );\r
+\r
+/**\r
+ Compare two resource nodes and get the larger resource consumer.\r
+\r
+ @param PciResNode1 resource node 1 want to be compared\r
+ @param PciResNode2 resource node 2 want to be compared\r
+\r
+ @return Larger resource node.\r
+\r
+**/\r
+PCI_RESOURCE_NODE *\r
+GetLargerConsumerDevice (\r
+ IN PCI_RESOURCE_NODE *PciResNode1,\r
+ IN PCI_RESOURCE_NODE *PciResNode2\r
+ );\r
+\r
+/**\r
+ Get the max resource consumer in the host resource pool.\r
+\r
+ @param ResPool Pointer to resource pool node.\r
+\r
+ @return The max resource consumer in the host resource pool.\r
+\r
+**/\r
+PCI_RESOURCE_NODE *\r
+GetMaxResourceConsumerDevice (\r
+ IN PCI_RESOURCE_NODE *ResPool\r
+ );\r
+\r
+/**\r
+ Adjust host bridge allocation so as to reduce resource requirement\r
+\r
+ @param IoPool Pointer to instance of I/O resource Node.\r
+ @param Mem32Pool Pointer to instance of 32-bit memory resource Node.\r
+ @param PMem32Pool Pointer to instance of 32-bit Prefetchable memory resource node.\r
+ @param Mem64Pool Pointer to instance of 64-bit memory resource node.\r
+ @param PMem64Pool Pointer to instance of 64-bit Prefetchable memory resource node.\r
+ @param IoResStatus Status of I/O resource Node.\r
+ @param Mem32ResStatus Status of 32-bit memory resource Node.\r
+ @param PMem32ResStatus Status of 32-bit Prefetchable memory resource node.\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_ABORTED Host bridge hasn't this resource type or no resource be adjusted.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeAdjustAllocation (\r
+ IN PCI_RESOURCE_NODE *IoPool,\r
+ IN PCI_RESOURCE_NODE *Mem32Pool,\r
+ IN PCI_RESOURCE_NODE *PMem32Pool,\r
+ IN PCI_RESOURCE_NODE *Mem64Pool,\r
+ IN PCI_RESOURCE_NODE *PMem64Pool,\r
+ IN UINT64 IoResStatus,\r
+ IN UINT64 Mem32ResStatus,\r
+ IN UINT64 PMem32ResStatus,\r
+ IN UINT64 Mem64ResStatus,\r
+ IN UINT64 PMem64ResStatus\r
+ );\r
+\r
+/**\r
+ Summary requests for all resource type, and contruct ACPI resource\r
+ requestor instance.\r
+\r
+ @param Bridge detecting bridge\r
+ @param IoNode Pointer to instance of I/O resource Node\r
+ @param Mem32Node Pointer to instance of 32-bit memory resource Node\r
+ @param PMem32Node Pointer to instance of 32-bit Pmemory resource node\r
+ @param Mem64Node Pointer to instance of 64-bit memory resource node\r
+ @param PMem64Node Pointer to instance of 64-bit Pmemory resource node\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
+\r
+**/\r
+EFI_STATUS\r
+ConstructAcpiResourceRequestor (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN PCI_RESOURCE_NODE *IoNode,\r
+ IN PCI_RESOURCE_NODE *Mem32Node,\r
+ IN PCI_RESOURCE_NODE *PMem32Node,\r
+ IN PCI_RESOURCE_NODE *Mem64Node,\r
+ IN PCI_RESOURCE_NODE *PMem64Node,\r
+ OUT VOID **Config\r
+ );\r
+\r
+/**\r
+ Get resource base from an acpi configuration descriptor.\r
+\r
+ @param Config An acpi configuration descriptor.\r
+ @param IoBase Output of I/O resource base address.\r
+ @param Mem32Base Output of 32-bit memory base address.\r
+ @param PMem32Base Output of 32-bit prefetchable memory base address.\r
+ @param Mem64Base Output of 64-bit memory base address.\r
+ @param PMem64Base Output of 64-bit prefetchable memory base address.\r
+\r
+**/\r
+VOID\r
+GetResourceBase (\r
+ IN VOID *Config,\r
+ OUT UINT64 *IoBase,\r
+ OUT UINT64 *Mem32Base,\r
+ OUT UINT64 *PMem32Base,\r
+ OUT UINT64 *Mem64Base,\r
+ OUT UINT64 *PMem64Base\r
+ );\r
+\r
+/**\r
+ Enumerate pci bridge, allocate resource and determine attribute\r
+ for devices on this bridge.\r
+\r
+ @param BridgeDev Pointer to instance of bridge device.\r
+\r
+ @retval EFI_SUCCESS Successfully enumerated PCI bridge.\r
+ @retval other Failed to enumerate.\r
+\r
+**/\r
+EFI_STATUS\r
+PciBridgeEnumerator (\r
+ IN PCI_IO_DEVICE *BridgeDev\r
+ );\r
+\r
+/**\r
+ Allocate all kinds of resource for PCI bridge.\r
+\r
+ @param Bridge Pointer to bridge instance.\r
+\r
+ @retval EFI_SUCCESS Successfully allocated resource for PCI bridge.\r
+ @retval other Failed to allocate resource for bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciBridgeResourceAllocator (\r
+ IN PCI_IO_DEVICE *Bridge\r
+ );\r
+\r
+/**\r
+ Get resource base address for a pci bridge device.\r
+\r
+ @param Bridge Given Pci driver instance.\r
+ @param IoBase Output for base address of I/O type resource.\r
+ @param Mem32Base Output for base address of 32-bit memory type resource.\r
+ @param PMem32Base Ooutput for base address of 32-bit Pmemory type resource.\r
+ @param Mem64Base Output for base address of 64-bit memory type resource.\r
+ @param PMem64Base Output for base address of 64-bit Pmemory type resource.\r
+\r
+ @retval EFI_SUCCESS Successfully got resource base address.\r
+ @retval EFI_OUT_OF_RESOURCES PCI bridge is not available.\r
+\r
+**/\r
+EFI_STATUS\r
+GetResourceBaseFromBridge (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ OUT UINT64 *IoBase,\r
+ OUT UINT64 *Mem32Base,\r
+ OUT UINT64 *PMem32Base,\r
+ OUT UINT64 *Mem64Base,\r
+ OUT UINT64 *PMem64Base\r
+ );\r
+\r
+/**\r
+ Process Option Rom on this host bridge\r
+\r
+ @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
+\r
+ @retval EFI_NOT_FOUND Can not find the root bridge instance.\r
+ @retval EFI_SUCCESS Success process.\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeP2CProcess (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
+ );\r
+\r
+/**\r
+ These are the notifications from the PCI bus driver that it is about to enter a certain\r
+ phase of the PCI enumeration process.\r
+\r
+ This member function can be used to notify the host bridge driver to perform specific actions,\r
+ including any chipset-specific initialization, so that the chipset is ready to enter the next phase.\r
+ Eight notification points are defined at this time. See belows:\r
+ EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data\r
+ structures. The PCI enumerator should issue this notification\r
+ before starting a fresh enumeration process. Enumeration cannot\r
+ be restarted after sending any other notification such as\r
+ EfiPciHostBridgeBeginBusAllocation.\r
+ EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is\r
+ required here. This notification can be used to perform any\r
+ chipset-specific programming.\r
+ EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No\r
+ specific action is required here. This notification can be used to\r
+ perform any chipset-specific programming.\r
+ EfiPciHostBridgeBeginResourceAllocation\r
+ The resource allocation phase is about to begin. No specific\r
+ action is required here. This notification can be used to perform\r
+ any chipset-specific programming.\r
+ EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI\r
+ root bridges. These resource settings are returned on the next call to\r
+ GetProposedResources(). Before calling NotifyPhase() with a Phase of\r
+ EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible\r
+ for gathering I/O and memory requests for\r
+ all the PCI root bridges and submitting these requests using\r
+ SubmitResources(). This function pads the resource amount\r
+ to suit the root bridge hardware, takes care of dependencies between\r
+ the PCI root bridges, and calls the Global Coherency Domain (GCD)\r
+ with the allocation request. In the case of padding, the allocated range\r
+ could be bigger than what was requested.\r
+ EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated\r
+ resources (proposed resources) for all the PCI root bridges. After the\r
+ hardware is programmed, reassigning resources will not be supported.\r
+ The bus settings are not affected.\r
+ EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI\r
+ root bridges and resets the I/O and memory apertures to their initial\r
+ state. The bus settings are not affected. If the request to allocate\r
+ resources fails, the PCI enumerator can use this notification to\r
+ deallocate previous resources, adjust the requests, and retry\r
+ allocation.\r
+ EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is\r
+ required here. This notification can be used to perform any chipsetspecific\r
+ programming.\r
+\r
+ @param[in] PciResAlloc The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
+ @param[in] Phase The phase during enumeration\r
+\r
+ @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error\r
+ is valid for a Phase of EfiPciHostBridgeAllocateResources if\r
+ SubmitResources() has not been called for one or more\r
+ PCI root bridges before this call\r
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid\r
+ for a Phase of EfiPciHostBridgeSetResources.\r
+ @retval EFI_INVALID_PARAMETER Invalid phase parameter\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the\r
+ previously submitted resource requests cannot be fulfilled or\r
+ were only partially fulfilled.\r
+ @retval EFI_SUCCESS The notification was accepted without any errors.\r
+\r
+**/\r
+EFI_STATUS\r
+NotifyPhase (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase\r
+ );\r
+\r
+/**\r
+ Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various\r
+ stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual\r
+ PCI controllers before enumeration.\r
+\r
+ This function is called during the PCI enumeration process. No specific action is expected from this\r
+ member function. It allows the host bridge driver to preinitialize individual PCI controllers before\r
+ enumeration.\r
+\r
+ @param Bridge Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.\r
+ @param Bus The bus number of the pci device.\r
+ @param Device The device number of the pci device.\r
+ @param Func The function number of the pci device.\r
+ @param Phase The phase of the PCI device enumeration.\r
+\r
+ @retval EFI_SUCCESS The requested parameters were returned.\r
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.\r
+ @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in\r
+ EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.\r
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should\r
+ not enumerate this device, including its child devices if it is a PCI-to-PCI\r
+ bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PreprocessController (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN UINT8 Bus,\r
+ IN UINT8 Device,\r
+ IN UINT8 Func,\r
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase\r
+ );\r
+\r
+/**\r
+ This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has\r
+ happened on the hot-plug controller. Currently, the operations include add operation and remove operation..\r
+\r
+ @param This A pointer to the hot plug request protocol.\r
+ @param Operation The operation the PCI bus driver is requested to make.\r
+ @param Controller The handle of the hot-plug controller.\r
+ @param RemainingDevicePath The remaining device path for the PCI-like hot-plug device.\r
+ @param NumberOfChildren The number of child handles.\r
+ For a add operation, it is an output parameter.\r
+ For a remove operation, it's an input parameter.\r
+ @param ChildHandleBuffer The buffer which contains the child handles.\r
+\r
+ @retval EFI_INVALID_PARAMETER Operation is not a legal value.\r
+ Controller is NULL or not a valid handle.\r
+ NumberOfChildren is NULL.\r
+ ChildHandleBuffer is NULL while Operation is add.\r
+ @retval EFI_OUT_OF_RESOURCES There are no enough resources to start the devices.\r
+ @retval EFI_NOT_FOUND Can not find bridge according to controller handle.\r
+ @retval EFI_SUCCESS The handles for the specified device have been created or destroyed\r
+ as requested, and for an add operation, the new handles are\r
+ returned in ChildHandleBuffer.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciHotPlugRequestNotify (\r
+ IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,\r
+ IN EFI_PCI_HOTPLUG_OPERATION Operation,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,\r
+ IN OUT UINT8 *NumberOfChildren,\r
+ IN OUT EFI_HANDLE * ChildHandleBuffer\r
+ );\r
+\r
+/**\r
+ Search hostbridge according to given handle\r
+\r
+ @param RootBridgeHandle Host bridge handle.\r
+\r
+ @retval TRUE Found host bridge handle.\r
+ @retval FALSE Not found hot bridge handle.\r
+\r
+**/\r
+BOOLEAN\r
+SearchHostBridgeHandle (\r
+ IN EFI_HANDLE RootBridgeHandle\r
+ );\r
+\r
+/**\r
+ Add host bridge handle to global variable for enumerating.\r
+\r
+ @param HostBridgeHandle Host bridge handle.\r
+\r
+ @retval EFI_SUCCESS Successfully added host bridge.\r
+ @retval EFI_ABORTED Host bridge is NULL, or given host bridge\r
+ has been in host bridge list.\r
+\r
+**/\r
+EFI_STATUS\r
+AddHostBridgeEnumerator (\r
+ IN EFI_HANDLE HostBridgeHandle\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ PCI emumeration support functions implementation 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
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+/**\r
+ This routine is used to check whether the pci device is present.\r
+\r
+ @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+ @param Pci Output buffer for PCI device configuration space.\r
+ @param Bus PCI bus NO.\r
+ @param Device PCI device NO.\r
+ @param Func PCI Func NO.\r
+\r
+ @retval EFI_NOT_FOUND PCI device not present.\r
+ @retval EFI_SUCCESS PCI device is found.\r
+\r
+**/\r
+EFI_STATUS\r
+PciDevicePresent (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
+ OUT PCI_TYPE00 *Pci,\r
+ IN UINT8 Bus,\r
+ IN UINT8 Device,\r
+ IN UINT8 Func\r
+ )\r
+{\r
+ UINT64 Address;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Create PCI address map in terms of Bus, Device and Func\r
+ //\r
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);\r
+\r
+ //\r
+ // Read the Vendor ID register\r
+ //\r
+ Status = PciRootBridgeIo->Pci.Read (\r
+ PciRootBridgeIo,\r
+ EfiPciWidthUint32,\r
+ Address,\r
+ 1,\r
+ Pci\r
+ );\r
+\r
+ if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {\r
+ //\r
+ // Read the entire config header for the device\r
+ //\r
+ Status = PciRootBridgeIo->Pci.Read (\r
+ PciRootBridgeIo,\r
+ EfiPciWidthUint32,\r
+ Address,\r
+ sizeof (PCI_TYPE00) / sizeof (UINT32),\r
+ Pci\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ Collect all the resource information under this root bridge.\r
+\r
+ A database that records all the information about pci device subject to this\r
+ root bridge will then be created.\r
+\r
+ @param Bridge Parent bridge instance.\r
+ @param StartBusNumber Bus number of begining.\r
+\r
+ @retval EFI_SUCCESS PCI device is found.\r
+ @retval other Some error occurred when reading PCI bridge information.\r
+\r
+**/\r
+EFI_STATUS\r
+PciPciDeviceInfoCollector (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN UINT8 StartBusNumber\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_TYPE00 Pci;\r
+ UINT8 Device;\r
+ UINT8 Func;\r
+ UINT8 SecBus;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+ Status = EFI_SUCCESS;\r
+ SecBus = 0;\r
+\r
+ for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
+\r
+ for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
+\r
+ //\r
+ // Check to see whether PCI device is present\r
+ //\r
+ Status = PciDevicePresent (\r
+ Bridge->PciRootBridgeIo,\r
+ &Pci,\r
+ (UINT8) StartBusNumber,\r
+ (UINT8) Device,\r
+ (UINT8) Func\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+\r
+ //\r
+ // Call back to host bridge function\r
+ //\r
+ PreprocessController (Bridge, (UINT8) StartBusNumber, Device, Func, EfiPciBeforeResourceCollection);\r
+\r
+ //\r
+ // Collect all the information about the PCI device discovered\r
+ //\r
+ Status = PciSearchDevice (\r
+ Bridge,\r
+ &Pci,\r
+ (UINT8) StartBusNumber,\r
+ Device,\r
+ Func,\r
+ &PciIoDevice\r
+ );\r
+\r
+ //\r
+ // Recursively scan PCI busses on the other side of PCI-PCI bridges\r
+ //\r
+ //\r
+ if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {\r
+\r
+ //\r
+ // If it is PPB, we need to get the secondary bus to continue the enumeration\r
+ //\r
+ PciIo = &(PciIoDevice->PciIo);\r
+\r
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, 1, &SecBus);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get resource padding for PPB\r
+ //\r
+ GetResourcePaddingPpb (PciIoDevice);\r
+\r
+ //\r
+ // Deep enumerate the next level bus\r
+ //\r
+ Status = PciPciDeviceInfoCollector (\r
+ PciIoDevice,\r
+ (UINT8) (SecBus)\r
+ );\r
+\r
+ }\r
+\r
+ if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
+\r
+ //\r
+ // Skip sub functions, this is not a multi function device\r
+ //\r
+ Func = PCI_MAX_FUNC;\r
+ }\r
+ }\r
+\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Seach required device and create PCI device instance.\r
+\r
+ @param Bridge Parent bridge instance.\r
+ @param Pci Input PCI device information block.\r
+ @param Bus PCI bus NO.\r
+ @param Device PCI device NO.\r
+ @param Func PCI func NO.\r
+ @param PciDevice Output of searched PCI device instance.\r
+\r
+ @retval EFI_SUCCESS Successfully created PCI device instance.\r
+ @retval EFI_OUT_OF_RESOURCES Cannot get PCI device information.\r
+\r
+**/\r
+EFI_STATUS\r
+PciSearchDevice (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN PCI_TYPE00 *Pci,\r
+ IN UINT8 Bus,\r
+ IN UINT8 Device,\r
+ IN UINT8 Func,\r
+ OUT PCI_IO_DEVICE **PciDevice\r
+ )\r
+{\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = NULL;\r
+\r
+ if (!IS_PCI_BRIDGE (Pci)) {\r
+\r
+ if (IS_CARDBUS_BRIDGE (Pci)) {\r
+ PciIoDevice = GatherP2CInfo (\r
+ Bridge,\r
+ Pci,\r
+ Bus,\r
+ Device,\r
+ Func\r
+ );\r
+ if ((PciIoDevice != NULL) && gFullEnumeration) {\r
+ InitializeP2C (PciIoDevice);\r
+ }\r
+ } else {\r
+\r
+ //\r
+ // Create private data for Pci Device\r
+ //\r
+ PciIoDevice = GatherDeviceInfo (\r
+ Bridge,\r
+ Pci,\r
+ Bus,\r
+ Device,\r
+ Func\r
+ );\r
+\r
+ }\r
+\r
+ } else {\r
+\r
+ //\r
+ // Create private data for PPB\r
+ //\r
+ PciIoDevice = GatherPpbInfo (\r
+ Bridge,\r
+ Pci,\r
+ Bus,\r
+ Device,\r
+ Func\r
+ );\r
+\r
+ //\r
+ // Special initialization for PPB including making the PPB quiet\r
+ //\r
+ if ((PciIoDevice != NULL) && gFullEnumeration) {\r
+ InitializePpb (PciIoDevice);\r
+ }\r
+ }\r
+\r
+ if (PciIoDevice == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Update the bar information for this PCI device so as to support some specific device\r
+ //\r
+ UpdatePciInfo (PciIoDevice);\r
+\r
+ if (PciIoDevice->DevicePath == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Detect this function has option rom\r
+ //\r
+ if (gFullEnumeration) {\r
+\r
+ if (!IS_CARDBUS_BRIDGE (Pci)) {\r
+\r
+ GetOpRomInfo (PciIoDevice);\r
+\r
+ }\r
+\r
+ ResetPowerManagementFeature (PciIoDevice);\r
+\r
+ }\r
+\r
+ //\r
+ // Insert it into a global tree for future reference\r
+ //\r
+ InsertPciDevice (Bridge, PciIoDevice);\r
+\r
+ //\r
+ // Determine PCI device attributes\r
+ //\r
+\r
+ if (PciDevice != NULL) {\r
+ *PciDevice = PciIoDevice;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Create PCI device instance for PCI device.\r
+\r
+ @param Bridge Parent bridge instance.\r
+ @param Pci Input PCI device information block.\r
+ @param Bus PCI device Bus NO.\r
+ @param Device PCI device Device NO.\r
+ @param Func PCI device's func NO.\r
+\r
+ @return Created PCI device instance.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+GatherDeviceInfo (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN PCI_TYPE00 *Pci,\r
+ IN UINT8 Bus,\r
+ IN UINT8 Device,\r
+ IN UINT8 Func\r
+ )\r
+{\r
+ UINTN Offset;\r
+ UINTN BarIndex;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+\r
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
+ PciIoDevice = CreatePciIoDevice (\r
+ PciRootBridgeIo,\r
+ Pci,\r
+ Bus,\r
+ Device,\r
+ Func\r
+ );\r
+\r
+ if (PciIoDevice == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Create a device path for this PCI device and store it into its private data\r
+ //\r
+ CreatePciDevicePath (\r
+ Bridge->DevicePath,\r
+ PciIoDevice\r
+ );\r
+\r
+ //\r
+ // If it is a full enumeration, disconnect the device in advance\r
+ //\r
+ if (gFullEnumeration) {\r
+\r
+ PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
+\r
+ }\r
+\r
+ //\r
+ // Start to parse the bars\r
+ //\r
+ for (Offset = 0x10, BarIndex = 0; Offset <= 0x24 && BarIndex < PCI_MAX_BAR; BarIndex++) {\r
+ Offset = PciParseBar (PciIoDevice, Offset, BarIndex);\r
+ }\r
+\r
+ //\r
+ // Parse the SR-IOV VF bars\r
+ //\r
+ if ((PciIoDevice->SrIovCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {\r
+ for (Offset = PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0, BarIndex = 0;\r
+ Offset <= PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5;\r
+ BarIndex++) {\r
+\r
+ ASSERT (BarIndex < PCI_MAX_BAR);\r
+ Offset = PciIovParseVfBar (PciIoDevice, Offset, BarIndex);\r
+ }\r
+ }\r
+ return PciIoDevice;\r
+}\r
+\r
+/**\r
+ Create PCI device instance for PCI-PCI bridge.\r
+\r
+ @param Bridge Parent bridge instance.\r
+ @param Pci Input PCI device information block.\r
+ @param Bus PCI device Bus NO.\r
+ @param Device PCI device Device NO.\r
+ @param Func PCI device's func NO.\r
+\r
+ @return Created PCI device instance.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+GatherPpbInfo (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN PCI_TYPE00 *Pci,\r
+ IN UINT8 Bus,\r
+ IN UINT8 Device,\r
+ IN UINT8 Func\r
+ )\r
+{\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ EFI_STATUS Status;\r
+ UINT8 Value;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT8 Temp;\r
+\r
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
+ PciIoDevice = CreatePciIoDevice (\r
+ PciRootBridgeIo,\r
+ Pci,\r
+ Bus,\r
+ Device,\r
+ Func\r
+ );\r
+\r
+ if (PciIoDevice == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Create a device path for this PCI device and store it into its private data\r
+ //\r
+ CreatePciDevicePath (\r
+ Bridge->DevicePath,\r
+ PciIoDevice\r
+ );\r
+\r
+ if (gFullEnumeration) {\r
+ PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
+\r
+ //\r
+ // Initalize the bridge control register\r
+ //\r
+ PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);\r
+\r
+ }\r
+\r
+ //\r
+ // PPB can have two BARs\r
+ //\r
+ if (PciParseBar (PciIoDevice, 0x10, PPB_BAR_0) == 0x14) {\r
+ //\r
+ // Not 64-bit bar\r
+ //\r
+ PciParseBar (PciIoDevice, 0x14, PPB_BAR_1);\r
+ }\r
+\r
+ PciIo = &PciIoDevice->PciIo;\r
+\r
+ //\r
+ // Test whether it support 32 decode or not\r
+ //\r
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);\r
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);\r
+\r
+ if (Value != 0) {\r
+ if ((Value & 0x01) != 0) {\r
+ PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;\r
+ } else {\r
+ PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;\r
+ }\r
+ }\r
+\r
+ Status = BarExisted (\r
+ PciIoDevice,\r
+ 0x24,\r
+ NULL,\r
+ NULL\r
+ );\r
+\r
+ //\r
+ // Test if it supports 64 memory or not\r
+ //\r
+ if (!EFI_ERROR (Status)) {\r
+\r
+ Status = BarExisted (\r
+ PciIoDevice,\r
+ 0x28,\r
+ NULL,\r
+ NULL\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;\r
+ PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;\r
+ } else {\r
+ PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Memory 32 code is required for ppb\r
+ //\r
+ PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;\r
+\r
+ GetResourcePaddingPpb (PciIoDevice);\r
+\r
+ return PciIoDevice;\r
+}\r
+\r
+\r
+/**\r
+ Create PCI device instance for PCI Card bridge device.\r
+\r
+ @param Bridge Parent bridge instance.\r
+ @param Pci Input PCI device information block.\r
+ @param Bus PCI device Bus NO.\r
+ @param Device PCI device Device NO.\r
+ @param Func PCI device's func NO.\r
+\r
+ @return Created PCI device instance.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+GatherP2CInfo (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN PCI_TYPE00 *Pci,\r
+ IN UINT8 Bus,\r
+ IN UINT8 Device,\r
+ IN UINT8 Func\r
+ )\r
+{\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
+ PciIoDevice = CreatePciIoDevice (\r
+ PciRootBridgeIo,\r
+ Pci,\r
+ Bus,\r
+ Device,\r
+ Func\r
+ );\r
+\r
+ if (PciIoDevice == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Create a device path for this PCI device and store it into its private data\r
+ //\r
+ CreatePciDevicePath (\r
+ Bridge->DevicePath,\r
+ PciIoDevice\r
+ );\r
+\r
+ if (gFullEnumeration) {\r
+ PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
+\r
+ //\r
+ // Initalize the bridge control register\r
+ //\r
+ PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);\r
+ }\r
+\r
+ //\r
+ // P2C only has one bar that is in 0x10\r
+ //\r
+ PciParseBar (PciIoDevice, 0x10, P2C_BAR_0);\r
+\r
+ //\r
+ // Read PciBar information from the bar register\r
+ //\r
+ GetBackPcCardBar (PciIoDevice);\r
+ PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED |\r
+ EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |\r
+ EFI_BRIDGE_IO32_DECODE_SUPPORTED;\r
+\r
+ return PciIoDevice;\r
+}\r
+\r
+/**\r
+ Create device path for pci deivce.\r
+\r
+ @param ParentDevicePath Parent bridge's path.\r
+ @param PciIoDevice Pci device instance.\r
+\r
+ @return Device path protocol instance for specific pci device.\r
+\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+CreatePciDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+\r
+ PCI_DEVICE_PATH PciNode;\r
+\r
+ //\r
+ // Create PCI device path\r
+ //\r
+ PciNode.Header.Type = HARDWARE_DEVICE_PATH;\r
+ PciNode.Header.SubType = HW_PCI_DP;\r
+ SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));\r
+\r
+ PciNode.Device = PciIoDevice->DeviceNumber;\r
+ PciNode.Function = PciIoDevice->FunctionNumber;\r
+ PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);\r
+\r
+ return PciIoDevice->DevicePath;\r
+}\r
+\r
+/**\r
+ Check whether the PCI IOV VF bar is existed or not.\r
+\r
+ @param PciIoDevice A pointer to the PCI_IO_DEVICE.\r
+ @param Offset The offset.\r
+ @param BarLengthValue The bar length value returned.\r
+ @param OriginalBarValue The original bar value returned.\r
+\r
+ @retval EFI_NOT_FOUND The bar doesn't exist.\r
+ @retval EFI_SUCCESS The bar exist.\r
+\r
+**/\r
+EFI_STATUS\r
+VfBarExisted (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINTN Offset,\r
+ OUT UINT32 *BarLengthValue,\r
+ OUT UINT32 *OriginalBarValue\r
+ )\r
+{\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT32 OriginalValue;\r
+ UINT32 Value;\r
+ EFI_TPL OldTpl;\r
+\r
+ //\r
+ // Ensure it is called properly\r
+ //\r
+ ASSERT (PciIoDevice->SrIovCapabilityOffset != 0);\r
+ if (PciIoDevice->SrIovCapabilityOffset == 0) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ PciIo = &PciIoDevice->PciIo;\r
+\r
+ //\r
+ // Preserve the original value\r
+ //\r
+\r
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue);\r
+\r
+ //\r
+ // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &gAllOne);\r
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &Value);\r
+\r
+ //\r
+ // Write back the original value\r
+ //\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue);\r
+\r
+ //\r
+ // Restore TPL to its original level\r
+ //\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ if (BarLengthValue != NULL) {\r
+ *BarLengthValue = Value;\r
+ }\r
+\r
+ if (OriginalBarValue != NULL) {\r
+ *OriginalBarValue = OriginalValue;\r
+ }\r
+\r
+ if (Value == 0) {\r
+ return EFI_NOT_FOUND;\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+}\r
+\r
+/**\r
+ Check whether the bar is existed or not.\r
+\r
+ @param PciIoDevice A pointer to the PCI_IO_DEVICE.\r
+ @param Offset The offset.\r
+ @param BarLengthValue The bar length value returned.\r
+ @param OriginalBarValue The original bar value returned.\r
+\r
+ @retval EFI_NOT_FOUND The bar doesn't exist.\r
+ @retval EFI_SUCCESS The bar exist.\r
+\r
+**/\r
+EFI_STATUS\r
+BarExisted (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINTN Offset,\r
+ OUT UINT32 *BarLengthValue,\r
+ OUT UINT32 *OriginalBarValue\r
+ )\r
+{\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT32 OriginalValue;\r
+ UINT32 Value;\r
+ EFI_TPL OldTpl;\r
+\r
+ PciIo = &PciIoDevice->PciIo;\r
+\r
+ //\r
+ // Preserve the original value\r
+ //\r
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);\r
+\r
+ //\r
+ // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);\r
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);\r
+\r
+ //\r
+ // Write back the original value\r
+ //\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);\r
+\r
+ //\r
+ // Restore TPL to its original level\r
+ //\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ if (BarLengthValue != NULL) {\r
+ *BarLengthValue = Value;\r
+ }\r
+\r
+ if (OriginalBarValue != NULL) {\r
+ *OriginalBarValue = OriginalValue;\r
+ }\r
+\r
+ if (Value == 0) {\r
+ return EFI_NOT_FOUND;\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+}\r
+\r
+/**\r
+ Test whether the device can support given attributes.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+ @param Command Input command register value, and\r
+ returned supported register value.\r
+ @param BridgeControl Inout bridge control value for PPB or P2C, and\r
+ returned supported bridge control value.\r
+ @param OldCommand Returned and stored old command register offset.\r
+ @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C.\r
+\r
+**/\r
+VOID\r
+PciTestSupportedAttribute (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN OUT UINT16 *Command,\r
+ IN OUT UINT16 *BridgeControl,\r
+ OUT UINT16 *OldCommand,\r
+ OUT UINT16 *OldBridgeControl\r
+ )\r
+{\r
+ EFI_TPL OldTpl;\r
+\r
+ //\r
+ // Preserve the original value\r
+ //\r
+ PCI_READ_COMMAND_REGISTER (PciIoDevice, OldCommand);\r
+\r
+ //\r
+ // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
+ PCI_SET_COMMAND_REGISTER (PciIoDevice, *Command);\r
+ PCI_READ_COMMAND_REGISTER (PciIoDevice, Command);\r
+\r
+ //\r
+ // Write back the original value\r
+ //\r
+ PCI_SET_COMMAND_REGISTER (PciIoDevice, *OldCommand);\r
+\r
+ //\r
+ // Restore TPL to its original level\r
+ //\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
+\r
+ //\r
+ // Preserve the original value\r
+ //\r
+ PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, OldBridgeControl);\r
+\r
+ //\r
+ // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
+ PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *BridgeControl);\r
+ PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);\r
+\r
+ //\r
+ // Write back the original value\r
+ //\r
+ PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *OldBridgeControl);\r
+\r
+ //\r
+ // Restore TPL to its original level\r
+ //\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ } else {\r
+ *OldBridgeControl = 0;\r
+ *BridgeControl = 0;\r
+ }\r
+}\r
+\r
+/**\r
+ Set the supported or current attributes of a PCI device.\r
+\r
+ @param PciIoDevice Structure pointer for PCI device.\r
+ @param Command Command register value.\r
+ @param BridgeControl Bridge control value for PPB or P2C.\r
+ @param Option Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.\r
+\r
+**/\r
+VOID\r
+PciSetDeviceAttribute (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINT16 Command,\r
+ IN UINT16 BridgeControl,\r
+ IN UINTN Option\r
+ )\r
+{\r
+ UINT64 Attributes;\r
+\r
+ Attributes = 0;\r
+\r
+ if ((Command & EFI_PCI_COMMAND_IO_SPACE) != 0) {\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;\r
+ }\r
+\r
+ if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) != 0) {\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;\r
+ }\r
+\r
+ if ((Command & EFI_PCI_COMMAND_BUS_MASTER) != 0) {\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;\r
+ }\r
+\r
+ if ((Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;\r
+ }\r
+\r
+ if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) != 0) {\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;\r
+ }\r
+\r
+ if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) != 0) {\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;\r
+ }\r
+\r
+ if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16) != 0) {\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16;\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16;\r
+ }\r
+\r
+ if (Option == EFI_SET_SUPPORTS) {\r
+\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE |\r
+ EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED |\r
+ EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE |\r
+ EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |\r
+ EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |\r
+ EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
+\r
+ if ((Attributes & EFI_PCI_IO_ATTRIBUTE_IO) != 0) {\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;\r
+ }\r
+\r
+ if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
+ //\r
+ // For bridge, it should support IDE attributes\r
+ //\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;\r
+ } else {\r
+\r
+ if (IS_PCI_IDE (&PciIoDevice->Pci)) {\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;\r
+ }\r
+\r
+ if (IS_PCI_VGA (&PciIoDevice->Pci)) {\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;\r
+ }\r
+ }\r
+\r
+ PciIoDevice->Supports = Attributes;\r
+ PciIoDevice->Supports &= ( (PciIoDevice->Parent->Supports) | \\r
+ EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | \\r
+ EFI_PCI_IO_ATTRIBUTE_BUS_MASTER );\r
+\r
+ } else {\r
+ PciIoDevice->Attributes = Attributes;\r
+ }\r
+}\r
+\r
+/**\r
+ Determine if the device can support Fast Back to Back attribute.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+ @param StatusIndex Status register value.\r
+\r
+ @retval EFI_SUCCESS This device support Fast Back to Back attribute.\r
+ @retval EFI_UNSUPPORTED This device doesn't support Fast Back to Back attribute.\r
+\r
+**/\r
+EFI_STATUS\r
+GetFastBackToBackSupport (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINT8 StatusIndex\r
+ )\r
+{\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_STATUS Status;\r
+ UINT32 StatusRegister;\r
+\r
+ //\r
+ // Read the status register\r
+ //\r
+ PciIo = &PciIoDevice->PciIo;\r
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, StatusIndex, 1, &StatusRegister);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Check the Fast B2B bit\r
+ //\r
+ if ((StatusRegister & EFI_PCI_FAST_BACK_TO_BACK_CAPABLE) != 0) {\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+}\r
+\r
+/**\r
+ Process the option ROM for all the children of the specified parent PCI device.\r
+ It can only be used after the first full Option ROM process.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+\r
+**/\r
+VOID\r
+ProcessOptionRomLight (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ PCI_IO_DEVICE *Temp;\r
+ LIST_ENTRY *CurrentLink;\r
+\r
+ //\r
+ // For RootBridge, PPB , P2C, go recursively to traverse all its children\r
+ //\r
+ CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
+ while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {\r
+\r
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+ if (!IsListEmpty (&Temp->ChildList)) {\r
+ ProcessOptionRomLight (Temp);\r
+ }\r
+\r
+ PciRomGetImageMapping (Temp);\r
+\r
+ //\r
+ // The OpRom has already been processed in the first round\r
+ //\r
+ Temp->AllOpRomProcessed = TRUE;\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+}\r
+\r
+/**\r
+ Determine the related attributes of all devices under a Root Bridge.\r
+\r
+ @param PciIoDevice PCI device instance.\r
+\r
+**/\r
+EFI_STATUS\r
+DetermineDeviceAttribute (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ UINT16 Command;\r
+ UINT16 BridgeControl;\r
+ UINT16 OldCommand;\r
+ UINT16 OldBridgeControl;\r
+ BOOLEAN FastB2BSupport;\r
+ PCI_IO_DEVICE *Temp;\r
+ LIST_ENTRY *CurrentLink;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // For Root Bridge, just copy it by RootBridgeIo proctocol\r
+ // so as to keep consistent with the actual attribute\r
+ //\r
+ if (PciIoDevice->Parent == NULL) {\r
+ Status = PciIoDevice->PciRootBridgeIo->GetAttributes (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ &PciIoDevice->Supports,\r
+ &PciIoDevice->Attributes\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ } else {\r
+\r
+ //\r
+ // Set the attributes to be checked for common PCI devices and PPB or P2C\r
+ // Since some devices only support part of them, it is better to set the\r
+ // attribute according to its command or bridge control register\r
+ //\r
+ Command = EFI_PCI_COMMAND_IO_SPACE |\r
+ EFI_PCI_COMMAND_MEMORY_SPACE |\r
+ EFI_PCI_COMMAND_BUS_MASTER |\r
+ EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+\r
+ BridgeControl = EFI_PCI_BRIDGE_CONTROL_ISA | EFI_PCI_BRIDGE_CONTROL_VGA | EFI_PCI_BRIDGE_CONTROL_VGA_16;\r
+\r
+ //\r
+ // Test whether the device can support attributes above\r
+ //\r
+ PciTestSupportedAttribute (PciIoDevice, &Command, &BridgeControl, &OldCommand, &OldBridgeControl);\r
+\r
+ //\r
+ // Set the supported attributes for specified PCI device\r
+ //\r
+ PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, EFI_SET_SUPPORTS);\r
+\r
+ //\r
+ // Set the current attributes for specified PCI device\r
+ //\r
+ PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES);\r
+\r
+ //\r
+ // Enable other supported attributes but not defined in PCI_IO_PROTOCOL\r
+ //\r
+ PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);\r
+ }\r
+\r
+ FastB2BSupport = TRUE;\r
+\r
+ //\r
+ // P2C can not support FB2B on the secondary side\r
+ //\r
+ if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
+ FastB2BSupport = FALSE;\r
+ }\r
+\r
+ //\r
+ // For RootBridge, PPB , P2C, go recursively to traverse all its children\r
+ //\r
+ CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
+ while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {\r
+\r
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+ Status = DetermineDeviceAttribute (Temp);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Detect Fast Bact to Bact support for the device under the bridge\r
+ //\r
+ Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET);\r
+ if (FastB2BSupport && EFI_ERROR (Status)) {\r
+ FastB2BSupport = FALSE;\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+ //\r
+ // Set or clear Fast Back to Back bit for the whole bridge\r
+ //\r
+ if (!IsListEmpty (&PciIoDevice->ChildList)) {\r
+\r
+ if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
+\r
+ Status = GetFastBackToBackSupport (PciIoDevice, PCI_BRIDGE_STATUS_REGISTER_OFFSET);\r
+\r
+ if (EFI_ERROR (Status) || (!FastB2BSupport)) {\r
+ FastB2BSupport = FALSE;\r
+ PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);\r
+ } else {\r
+ PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);\r
+ }\r
+ }\r
+\r
+ CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
+ while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {\r
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+ if (FastB2BSupport) {\r
+ PCI_ENABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);\r
+ } else {\r
+ PCI_DISABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+ }\r
+ //\r
+ // End for IsListEmpty\r
+ //\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This routine is used to update the bar information for those incompatible PCI device.\r
+\r
+ @param PciIoDevice Input Pci device instance. Output Pci device instance with updated\r
+ Bar information.\r
+\r
+ @retval EFI_SUCCESS Successfully updated bar information.\r
+ @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.\r
+\r
+**/\r
+EFI_STATUS\r
+UpdatePciInfo (\r
+ IN OUT PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN BarIndex;\r
+ UINTN BarEndIndex;\r
+ BOOLEAN SetFlag;\r
+ VOID *Configuration;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
+\r
+ Configuration = NULL;\r
+ Status = EFI_SUCCESS;\r
+\r
+ if (gEfiIncompatiblePciDeviceSupport == NULL) {\r
+ //\r
+ // It can only be supported after the Incompatible PCI Device\r
+ // Support Protocol has been installed\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiIncompatiblePciDeviceSupportProtocolGuid,\r
+ NULL,\r
+ (VOID **) &gEfiIncompatiblePciDeviceSupport\r
+ );\r
+ }\r
+ if (Status == EFI_SUCCESS) {\r
+ //\r
+ // Check whether the device belongs to incompatible devices from protocol or not\r
+ // If it is , then get its special requirement in the ACPI table\r
+ //\r
+ Status = gEfiIncompatiblePciDeviceSupport->CheckDevice (\r
+ gEfiIncompatiblePciDeviceSupport,\r
+ PciIoDevice->Pci.Hdr.VendorId,\r
+ PciIoDevice->Pci.Hdr.DeviceId,\r
+ PciIoDevice->Pci.Hdr.RevisionID,\r
+ PciIoDevice->Pci.Device.SubsystemVendorID,\r
+ PciIoDevice->Pci.Device.SubsystemID,\r
+ &Configuration\r
+ );\r
+\r
+ }\r
+\r
+ if (EFI_ERROR (Status) || Configuration == NULL ) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Update PCI device information from the ACPI table\r
+ //\r
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
+\r
+ while (Ptr->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
+\r
+ if (Ptr->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
+ //\r
+ // The format is not support\r
+ //\r
+ break;\r
+ }\r
+\r
+ BarIndex = (UINTN) Ptr->AddrTranslationOffset;\r
+ BarEndIndex = BarIndex;\r
+\r
+ //\r
+ // Update all the bars in the device\r
+ //\r
+ if (BarIndex == PCI_BAR_ALL) {\r
+ BarIndex = 0;\r
+ BarEndIndex = PCI_MAX_BAR - 1;\r
+ }\r
+\r
+ if (BarIndex > PCI_MAX_BAR) {\r
+ Ptr++;\r
+ continue;\r
+ }\r
+\r
+ for (; BarIndex <= BarEndIndex; BarIndex++) {\r
+ SetFlag = FALSE;\r
+ switch (Ptr->ResType) {\r
+ case ACPI_ADDRESS_SPACE_TYPE_MEM:\r
+\r
+ //\r
+ // Make sure the bar is memory type\r
+ //\r
+ if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) {\r
+ SetFlag = TRUE;\r
+ }\r
+ break;\r
+\r
+ case ACPI_ADDRESS_SPACE_TYPE_IO:\r
+\r
+ //\r
+ // Make sure the bar is IO type\r
+ //\r
+ if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeIo)) {\r
+ SetFlag = TRUE;\r
+ }\r
+ break;\r
+ }\r
+\r
+ if (SetFlag) {\r
+\r
+ //\r
+ // Update the new alignment for the device\r
+ //\r
+ SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr->AddrRangeMax);\r
+\r
+ //\r
+ // Update the new length for the device\r
+ //\r
+ if (Ptr->AddrLen != PCI_BAR_NOCHANGE) {\r
+ PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;\r
+ }\r
+ }\r
+ }\r
+\r
+ Ptr++;\r
+ }\r
+\r
+ FreePool (Configuration);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This routine will update the alignment with the new alignment.\r
+\r
+ @param Alignment Input Old alignment. Output updated alignment.\r
+ @param NewAlignment New alignment.\r
+\r
+**/\r
+VOID\r
+SetNewAlign (\r
+ IN OUT UINT64 *Alignment,\r
+ IN UINT64 NewAlignment\r
+ )\r
+{\r
+ UINT64 OldAlignment;\r
+ UINTN ShiftBit;\r
+\r
+ //\r
+ // The new alignment is the same as the original,\r
+ // so skip it\r
+ //\r
+ if (NewAlignment == PCI_BAR_OLD_ALIGN) {\r
+ return ;\r
+ }\r
+ //\r
+ // Check the validity of the parameter\r
+ //\r
+ if (NewAlignment != PCI_BAR_EVEN_ALIGN &&\r
+ NewAlignment != PCI_BAR_SQUAD_ALIGN &&\r
+ NewAlignment != PCI_BAR_DQUAD_ALIGN ) {\r
+ *Alignment = NewAlignment;\r
+ return ;\r
+ }\r
+\r
+ OldAlignment = (*Alignment) + 1;\r
+ ShiftBit = 0;\r
+\r
+ //\r
+ // Get the first non-zero hex value of the length\r
+ //\r
+ while ((OldAlignment & 0x0F) == 0x00) {\r
+ OldAlignment = RShiftU64 (OldAlignment, 4);\r
+ ShiftBit += 4;\r
+ }\r
+\r
+ //\r
+ // Adjust the alignment to even, quad or double quad boundary\r
+ //\r
+ if (NewAlignment == PCI_BAR_EVEN_ALIGN) {\r
+ if ((OldAlignment & 0x01) != 0) {\r
+ OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);\r
+ }\r
+ } else if (NewAlignment == PCI_BAR_SQUAD_ALIGN) {\r
+ if ((OldAlignment & 0x03) != 0) {\r
+ OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);\r
+ }\r
+ } else if (NewAlignment == PCI_BAR_DQUAD_ALIGN) {\r
+ if ((OldAlignment & 0x07) != 0) {\r
+ OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Update the old value\r
+ //\r
+ NewAlignment = LShiftU64 (OldAlignment, ShiftBit) - 1;\r
+ *Alignment = NewAlignment;\r
+\r
+ return ;\r
+}\r
+\r
+/**\r
+ Parse PCI IOV VF bar information and fill them into PCI device instance.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+ @param Offset Bar offset.\r
+ @param BarIndex Bar index.\r
+\r
+ @return Next bar offset.\r
+\r
+**/\r
+UINTN\r
+PciIovParseVfBar (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINTN Offset,\r
+ IN UINTN BarIndex\r
+ )\r
+{\r
+ UINT32 Value;\r
+ UINT32 OriginalValue;\r
+ UINT32 Mask;\r
+ UINT32 Data;\r
+ UINT8 Index;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Ensure it is called properly\r
+ //\r
+ ASSERT (PciIoDevice->SrIovCapabilityOffset != 0);\r
+ if (PciIoDevice->SrIovCapabilityOffset == 0) {\r
+ return 0;\r
+ }\r
+\r
+ OriginalValue = 0;\r
+ Value = 0;\r
+\r
+ Status = VfBarExisted (\r
+ PciIoDevice,\r
+ Offset,\r
+ &Value,\r
+ &OriginalValue\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;\r
+ PciIoDevice->VfPciBar[BarIndex].Length = 0;\r
+ PciIoDevice->VfPciBar[BarIndex].Alignment = 0;\r
+\r
+ //\r
+ // Scan all the BARs anyway\r
+ //\r
+ PciIoDevice->VfPciBar[BarIndex].Offset = (UINT8) Offset;\r
+ return Offset + 4;\r
+ }\r
+\r
+ PciIoDevice->VfPciBar[BarIndex].Offset = (UINT8) Offset;\r
+ if (Value & 0x01) {\r
+ //\r
+ // Device I/Os. Impossible\r
+ //\r
+ ASSERT (FALSE);\r
+ return Offset + 4;\r
+\r
+ } else {\r
+\r
+ Mask = 0xfffffff0;\r
+\r
+ PciIoDevice->VfPciBar[BarIndex].BaseAddress = OriginalValue & Mask;\r
+\r
+ switch (Value & 0x07) {\r
+\r
+ //\r
+ //memory space; anywhere in 32 bit address space\r
+ //\r
+ case 0x00:\r
+ if (Value & 0x08) {\r
+ PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem32;\r
+ } else {\r
+ PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem32;\r
+ }\r
+\r
+ PciIoDevice->VfPciBar[BarIndex].Length = (~(Value & Mask)) + 1;\r
+ PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;\r
+\r
+ //\r
+ // Adjust Length\r
+ //\r
+ PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);\r
+ //\r
+ // Adjust Alignment\r
+ //\r
+ if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {\r
+ PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;\r
+ }\r
+\r
+ break;\r
+\r
+ //\r
+ // memory space; anywhere in 64 bit address space\r
+ //\r
+ case 0x04:\r
+ if (Value & 0x08) {\r
+ PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem64;\r
+ } else {\r
+ PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem64;\r
+ }\r
+\r
+ //\r
+ // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar\r
+ // is regarded as an extension for the first bar. As a result\r
+ // the sizing will be conducted on combined 64 bit value\r
+ // Here just store the masked first 32bit value for future size\r
+ // calculation\r
+ //\r
+ PciIoDevice->VfPciBar[BarIndex].Length = Value & Mask;\r
+ PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;\r
+\r
+ if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {\r
+ PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;\r
+ }\r
+\r
+ //\r
+ // Increment the offset to point to next DWORD\r
+ //\r
+ Offset += 4;\r
+\r
+ Status = VfBarExisted (\r
+ PciIoDevice,\r
+ Offset,\r
+ &Value,\r
+ &OriginalValue\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Offset + 4;\r
+ }\r
+\r
+ //\r
+ // Fix the length to support some spefic 64 bit BAR\r
+ //\r
+ Data = Value;\r
+ Index = 0;\r
+ for (Data = Value; Data != 0; Data >>= 1) {\r
+ Index ++;\r
+ }\r
+ Value |= ((UINT32)(-1) << Index); \r
+\r
+ //\r
+ // Calculate the size of 64bit bar\r
+ //\r
+ PciIoDevice->VfPciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);\r
+\r
+ PciIoDevice->VfPciBar[BarIndex].Length = PciIoDevice->VfPciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);\r
+ PciIoDevice->VfPciBar[BarIndex].Length = (~(PciIoDevice->VfPciBar[BarIndex].Length)) + 1;\r
+ PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;\r
+\r
+ //\r
+ // Adjust Length\r
+ //\r
+ PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);\r
+ //\r
+ // Adjust Alignment\r
+ //\r
+ if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {\r
+ PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;\r
+ }\r
+\r
+ break;\r
+\r
+ //\r
+ // reserved\r
+ //\r
+ default:\r
+ PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeUnknown;\r
+ PciIoDevice->VfPciBar[BarIndex].Length = (~(Value & Mask)) + 1;\r
+ PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;\r
+\r
+ if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {\r
+ PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;\r
+ }\r
+\r
+ break;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Check the length again so as to keep compatible with some special bars\r
+ //\r
+ if (PciIoDevice->VfPciBar[BarIndex].Length == 0) {\r
+ PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeUnknown;\r
+ PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;\r
+ PciIoDevice->VfPciBar[BarIndex].Alignment = 0;\r
+ }\r
+ \r
+ //\r
+ // Increment number of bar\r
+ //\r
+ return Offset + 4;\r
+}\r
+\r
+/**\r
+ Parse PCI bar information and fill them into PCI device instance.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+ @param Offset Bar offset.\r
+ @param BarIndex Bar index.\r
+\r
+ @return Next bar offset.\r
+\r
+**/\r
+UINTN\r
+PciParseBar (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINTN Offset,\r
+ IN UINTN BarIndex\r
+ )\r
+{\r
+ UINT32 Value;\r
+ UINT32 OriginalValue;\r
+ UINT32 Mask;\r
+ UINT32 Data;\r
+ UINT8 Index;\r
+ EFI_STATUS Status;\r
+\r
+ OriginalValue = 0;\r
+ Value = 0;\r
+\r
+ Status = BarExisted (\r
+ PciIoDevice,\r
+ Offset,\r
+ &Value,\r
+ &OriginalValue\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ PciIoDevice->PciBar[BarIndex].BaseAddress = 0;\r
+ PciIoDevice->PciBar[BarIndex].Length = 0;\r
+ PciIoDevice->PciBar[BarIndex].Alignment = 0;\r
+\r
+ //\r
+ // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway\r
+ //\r
+ PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
+ return Offset + 4;\r
+ }\r
+\r
+ PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
+ if ((Value & 0x01) != 0) {\r
+ //\r
+ // Device I/Os\r
+ //\r
+ Mask = 0xfffffffc;\r
+\r
+ if ((Value & 0xFFFF0000) != 0) {\r
+ //\r
+ // It is a IO32 bar\r
+ //\r
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32;\r
+ PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1);\r
+ PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+\r
+ } else {\r
+ //\r
+ // It is a IO16 bar\r
+ //\r
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16;\r
+ PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1);\r
+ PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+\r
+ }\r
+ //\r
+ // Workaround. Some platforms inplement IO bar with 0 length\r
+ // Need to treat it as no-bar\r
+ //\r
+ if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
+ PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE) 0;\r
+ }\r
+\r
+ PciIoDevice->PciBar[BarIndex].Prefetchable = FALSE;\r
+ PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;\r
+\r
+ } else {\r
+\r
+ Mask = 0xfffffff0;\r
+\r
+ PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;\r
+\r
+ switch (Value & 0x07) {\r
+\r
+ //\r
+ //memory space; anywhere in 32 bit address space\r
+ //\r
+ case 0x00:\r
+ if ((Value & 0x08) != 0) {\r
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;\r
+ } else {\r
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;\r
+ }\r
+\r
+ PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;\r
+ if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {\r
+ //\r
+ // Force minimum 4KByte alignment for Virtualization technology for Directed I/O\r
+ //\r
+ PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);\r
+ } else {\r
+ PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+ }\r
+ break;\r
+\r
+ //\r
+ // memory space; anywhere in 64 bit address space\r
+ //\r
+ case 0x04:\r
+ if ((Value & 0x08) != 0) {\r
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;\r
+ } else {\r
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;\r
+ }\r
+\r
+ //\r
+ // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar\r
+ // is regarded as an extension for the first bar. As a result\r
+ // the sizing will be conducted on combined 64 bit value\r
+ // Here just store the masked first 32bit value for future size\r
+ // calculation\r
+ //\r
+ PciIoDevice->PciBar[BarIndex].Length = Value & Mask;\r
+ PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+\r
+ //\r
+ // Increment the offset to point to next DWORD\r
+ //\r
+ Offset += 4;\r
+\r
+ Status = BarExisted (\r
+ PciIoDevice,\r
+ Offset,\r
+ &Value,\r
+ &OriginalValue\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // the high 32 bit does not claim any BAR, we need to re-check the low 32 bit BAR again\r
+ //\r
+ if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
+ //\r
+ // some device implement MMIO bar with 0 length, need to treat it as no-bar\r
+ //\r
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;\r
+ }\r
+ return Offset + 4;\r
+ }\r
+\r
+ //\r
+ // Fix the length to support some spefic 64 bit BAR\r
+ //\r
+ Data = Value;\r
+ Index = 0;\r
+ for (Data = Value; Data != 0; Data >>= 1) {\r
+ Index ++;\r
+ }\r
+ Value |= ((UINT32)(-1) << Index);\r
+\r
+ //\r
+ // Calculate the size of 64bit bar\r
+ //\r
+ PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);\r
+\r
+ PciIoDevice->PciBar[BarIndex].Length = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);\r
+ PciIoDevice->PciBar[BarIndex].Length = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;\r
+ if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {\r
+ //\r
+ // Force minimum 4KByte alignment for Virtualization technology for Directed I/O\r
+ //\r
+ PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);\r
+ } else {\r
+ PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+ }\r
+\r
+ break;\r
+\r
+ //\r
+ // reserved\r
+ //\r
+ default:\r
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;\r
+ PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;\r
+ if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {\r
+ //\r
+ // Force minimum 4KByte alignment for Virtualization technology for Directed I/O\r
+ //\r
+ PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);\r
+ } else {\r
+ PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+ }\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Check the length again so as to keep compatible with some special bars\r
+ //\r
+ if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;\r
+ PciIoDevice->PciBar[BarIndex].BaseAddress = 0;\r
+ PciIoDevice->PciBar[BarIndex].Alignment = 0;\r
+ }\r
+\r
+ //\r
+ // Increment number of bar\r
+ //\r
+ return Offset + 4;\r
+}\r
+\r
+/**\r
+ This routine is used to initialize the bar of a PCI device.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+\r
+ @note It can be called typically when a device is going to be rejected.\r
+\r
+**/\r
+VOID\r
+InitializePciDevice (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT8 Offset;\r
+\r
+ PciIo = &(PciIoDevice->PciIo);\r
+\r
+ //\r
+ // Put all the resource apertures\r
+ // Resource base is set to all ones so as to indicate its resource\r
+ // has not been alloacted\r
+ //\r
+ for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne);\r
+ }\r
+}\r
+\r
+/**\r
+ This routine is used to initialize the bar of a PCI-PCI Bridge device.\r
+\r
+ @param PciIoDevice PCI-PCI bridge device instance.\r
+\r
+**/\r
+VOID\r
+InitializePpb (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+ PciIo = &(PciIoDevice->PciIo);\r
+\r
+ //\r
+ // Put all the resource apertures including IO16\r
+ // Io32, pMem32, pMem64 to quiescent state\r
+ // Resource base all ones, Resource limit all zeros\r
+ //\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);\r
+\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);\r
+\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);\r
+\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);\r
+\r
+ //\r
+ // Don't support use io32 as for now\r
+ //\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);\r
+\r
+ //\r
+ // Force Interrupt line to zero for cards that come up randomly\r
+ //\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);\r
+}\r
+\r
+/**\r
+ This routine is used to initialize the bar of a PCI Card Bridge device.\r
+\r
+ @param PciIoDevice PCI Card bridge device.\r
+\r
+**/\r
+VOID\r
+InitializeP2C (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+ PciIo = &(PciIoDevice->PciIo);\r
+\r
+ //\r
+ // Put all the resource apertures including IO16\r
+ // Io32, pMem32, pMem64 to quiescent state(\r
+ // Resource base all ones, Resource limit all zeros\r
+ //\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);\r
+\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);\r
+\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);\r
+\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);\r
+\r
+ //\r
+ // Force Interrupt line to zero for cards that come up randomly\r
+ //\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);\r
+}\r
+\r
+/**\r
+ Create and initiliaze general PCI I/O device instance for\r
+ PCI device/bridge device/hotplug bridge device.\r
+\r
+ @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+ @param Pci Input Pci information block.\r
+ @param Bus Device Bus NO.\r
+ @param Device Device device NO.\r
+ @param Func Device func NO.\r
+\r
+ @return Instance of PCI device. NULL means no instance created.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+CreatePciIoDevice (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
+ IN PCI_TYPE00 *Pci,\r
+ IN UINT8 Bus,\r
+ IN UINT8 Device,\r
+ IN UINT8 Func\r
+ )\r
+{\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_STATUS Status;\r
+\r
+ PciIoDevice = AllocateZeroPool (sizeof (PCI_IO_DEVICE));\r
+ if (PciIoDevice == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE;\r
+ PciIoDevice->Handle = NULL;\r
+ PciIoDevice->PciRootBridgeIo = PciRootBridgeIo;\r
+ PciIoDevice->DevicePath = NULL;\r
+ PciIoDevice->BusNumber = Bus;\r
+ PciIoDevice->DeviceNumber = Device;\r
+ PciIoDevice->FunctionNumber = Func;\r
+ PciIoDevice->Decodes = 0;\r
+\r
+ if (gFullEnumeration) {\r
+ PciIoDevice->Allocated = FALSE;\r
+ } else {\r
+ PciIoDevice->Allocated = TRUE;\r
+ }\r
+\r
+ PciIoDevice->Registered = FALSE;\r
+ PciIoDevice->Attributes = 0;\r
+ PciIoDevice->Supports = 0;\r
+ PciIoDevice->BusOverride = FALSE;\r
+ PciIoDevice->AllOpRomProcessed = FALSE;\r
+\r
+ PciIoDevice->IsPciExp = FALSE;\r
+\r
+ CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));\r
+\r
+ //\r
+ // Initialize the PCI I/O instance structure\r
+ //\r
+ InitializePciIoInstance (PciIoDevice);\r
+ InitializePciDriverOverrideInstance (PciIoDevice);\r
+ InitializePciLoadFile2 (PciIoDevice);\r
+ PciIo = &PciIoDevice->PciIo;\r
+\r
+ //\r
+ // Detect if PCI Express Device\r
+ //\r
+ PciIoDevice->PciExpressCapabilityOffset = 0;\r
+ Status = LocateCapabilityRegBlock (\r
+ PciIoDevice,\r
+ EFI_PCI_CAPABILITY_ID_PCIEXP,\r
+ &PciIoDevice->PciExpressCapabilityOffset,\r
+ NULL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ PciIoDevice->IsPciExp = TRUE;\r
+ }\r
+\r
+ //\r
+ // Initialize for PCI IOV\r
+ //\r
+\r
+ //\r
+ // Check ARI for function 0 only\r
+ //\r
+ Status = LocatePciExpressCapabilityRegBlock (\r
+ PciIoDevice,\r
+ EFI_PCIE_CAPABILITY_ID_ARI,\r
+ &PciIoDevice->AriCapabilityOffset,\r
+ NULL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ EFI_D_INFO,\r
+ "PCI-IOV B%x.D%x.F%x - ARI Cap offset - 0x%x\n",\r
+ (UINTN)Bus,\r
+ (UINTN)Device,\r
+ (UINTN)Func,\r
+ (UINTN)PciIoDevice->AriCapabilityOffset\r
+ ));\r
+ }\r
+\r
+ Status = LocatePciExpressCapabilityRegBlock (\r
+ PciIoDevice,\r
+ EFI_PCIE_CAPABILITY_ID_SRIOV,\r
+ &PciIoDevice->SrIovCapabilityOffset,\r
+ NULL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ EFI_D_INFO,\r
+ "PCI-IOV B%x.D%x.F%x - SRIOV Cap offset - 0x%x\n",\r
+ (UINTN)Bus,\r
+ (UINTN)Device,\r
+ (UINTN)Func,\r
+ (UINTN)PciIoDevice->SrIovCapabilityOffset\r
+ ));\r
+ }\r
+\r
+ Status = LocatePciExpressCapabilityRegBlock (\r
+ PciIoDevice,\r
+ EFI_PCIE_CAPABILITY_ID_MRIOV,\r
+ &PciIoDevice->MrIovCapabilityOffset,\r
+ NULL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ EFI_D_INFO,\r
+ "PCI-IOV B%x.D%x.F%x - MRIOV Cap offset - 0x%x\n",\r
+ (UINTN)Bus,\r
+ (UINTN)Device,\r
+ (UINTN)Func,\r
+ (UINTN)PciIoDevice->MrIovCapabilityOffset\r
+ ));\r
+ }\r
+\r
+ //\r
+ // Calculate SystemPageSize\r
+ //\r
+ if ((PciIoDevice->SrIovCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {\r
+\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE,\r
+ 1,\r
+ &PciIoDevice->SystemPageSize\r
+ );\r
+ DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - SupportedPageSize - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, PciIoDevice->SystemPageSize));\r
+\r
+ PciIoDevice->SystemPageSize = (PcdGet32(PcdSrIovSystemPageSize) & PciIoDevice->SystemPageSize);\r
+ ASSERT (PciIoDevice->SystemPageSize != 0);\r
+\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE,\r
+ 1,\r
+ &PciIoDevice->SystemPageSize\r
+ );\r
+ DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - SystemPageSize - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, PciIoDevice->SystemPageSize));\r
+ //\r
+ // Adjust SystemPageSize for Alignment usage later\r
+ //\r
+ PciIoDevice->SystemPageSize <<= 12;\r
+ }\r
+\r
+ // Calculate BusReservation for PCI IOV\r
+ //\r
+ if ((PciIoDevice->SrIovCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {\r
+ UINT16 VFStride;\r
+ UINT16 FirstVFOffset;\r
+ UINT32 PFRID;\r
+ UINT32 LastVF;\r
+\r
+ //\r
+ // Read First FirstVFOffset, InitialVFs, and VFStride\r
+ //\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF,\r
+ 1,\r
+ &FirstVFOffset\r
+ );\r
+ DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - FirstVFOffset - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)FirstVFOffset));\r
+\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS,\r
+ 1,\r
+ &PciIoDevice->InitialVFs\r
+ );\r
+ DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - InitialVFs - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)PciIoDevice->InitialVFs));\r
+\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE,\r
+ 1,\r
+ &VFStride\r
+ );\r
+ DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - VFStride - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)VFStride));\r
+\r
+ //\r
+ // Calculate LastVF\r
+ //\r
+ PFRID = EFI_PCI_RID(Bus, Device, Func);\r
+ LastVF = PFRID + FirstVFOffset + (PciIoDevice->InitialVFs - 1) * VFStride;\r
+\r
+ //\r
+ // Calculate ReservedBusNum for this PF\r
+ //\r
+ PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID (LastVF) - Bus + 1);\r
+ DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - reserved bus number - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)PciIoDevice->ReservedBusNum));\r
+ }\r
+\r
+\r
+ //\r
+ // Initialize the reserved resource list\r
+ //\r
+ InitializeListHead (&PciIoDevice->ReservedResourceList);\r
+\r
+ //\r
+ // Initialize the driver list\r
+ //\r
+ InitializeListHead (&PciIoDevice->OptionRomDriverList);\r
+\r
+ //\r
+ // Initialize the child list\r
+ //\r
+ InitializeListHead (&PciIoDevice->ChildList);\r
+\r
+ return PciIoDevice;\r
+}\r
+\r
+/**\r
+ This routine is used to enumerate entire pci bus system\r
+ in a given platform.\r
+\r
+ It is only called on the second start on the same Root Bridge.\r
+\r
+ @param Controller Parent bridge handler.\r
+\r
+ @retval EFI_SUCCESS PCI enumeration finished successfully.\r
+ @retval other Some error occurred when enumerating the pci bus system.\r
+\r
+**/\r
+EFI_STATUS\r
+PciEnumeratorLight (\r
+ IN EFI_HANDLE Controller\r
+ )\r
+{\r
+\r
+ EFI_STATUS Status;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+ PCI_IO_DEVICE *RootBridgeDev;\r
+ UINT16 MinBus;\r
+ UINT16 MaxBus;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
+\r
+ MinBus = 0;\r
+ MaxBus = PCI_MAX_BUS;\r
+ Descriptors = NULL;\r
+\r
+ //\r
+ // If this root bridge has been already enumerated, then return successfully\r
+ //\r
+ if (GetRootBridgeByHandle (Controller) != NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Open pci root bridge io protocol\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciRootBridgeIoProtocolGuid,\r
+ (VOID **) &PciRootBridgeIo,\r
+ gPciBusDriverBinding.DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {\r
+\r
+ //\r
+ // Create a device node for root bridge device with a NULL host bridge controller handle\r
+ //\r
+ RootBridgeDev = CreateRootBridge (Controller);\r
+\r
+ if (RootBridgeDev == NULL) {\r
+ Descriptors++;\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Record the root bridgeio protocol\r
+ //\r
+ RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;\r
+\r
+ Status = PciPciDeviceInfoCollector (\r
+ RootBridgeDev,\r
+ (UINT8) MinBus\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+\r
+ //\r
+ // Remove those PCI devices which are rejected when full enumeration\r
+ //\r
+ RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev);\r
+\r
+ //\r
+ // Process option rom light\r
+ //\r
+ ProcessOptionRomLight (RootBridgeDev);\r
+\r
+ //\r
+ // Determine attributes for all devices under this root bridge\r
+ //\r
+ DetermineDeviceAttribute (RootBridgeDev);\r
+\r
+ //\r
+ // If successfully, insert the node into device pool\r
+ //\r
+ InsertRootBridge (RootBridgeDev);\r
+ } else {\r
+\r
+ //\r
+ // If unsuccessly, destroy the entire node\r
+ //\r
+ DestroyRootBridge (RootBridgeDev);\r
+ }\r
+\r
+ Descriptors++;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Get bus range from PCI resource descriptor list.\r
+\r
+ @param Descriptors A pointer to the address space descriptor.\r
+ @param MinBus The min bus returned.\r
+ @param MaxBus The max bus returned.\r
+ @param BusRange The bus range returned.\r
+\r
+ @retval EFI_SUCCESS Successfully got bus range.\r
+ @retval EFI_NOT_FOUND Can not find the specific bus.\r
+\r
+**/\r
+EFI_STATUS\r
+PciGetBusRange (\r
+ IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,\r
+ OUT UINT16 *MinBus,\r
+ OUT UINT16 *MaxBus,\r
+ OUT UINT16 *BusRange\r
+ )\r
+{\r
+ while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
+ if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
+ if (MinBus != NULL) {\r
+ *MinBus = (UINT16) (*Descriptors)->AddrRangeMin;\r
+ }\r
+\r
+ if (MaxBus != NULL) {\r
+ *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax;\r
+ }\r
+\r
+ if (BusRange != NULL) {\r
+ *BusRange = (UINT16) (*Descriptors)->AddrLen;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ (*Descriptors)++;\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ This routine can be used to start the root bridge.\r
+\r
+ @param RootBridgeDev Pci device instance.\r
+\r
+ @retval EFI_SUCCESS This device started.\r
+ @retval other Failed to get PCI Root Bridge I/O protocol.\r
+\r
+**/\r
+EFI_STATUS\r
+StartManagingRootBridge (\r
+ IN PCI_IO_DEVICE *RootBridgeDev\r
+ )\r
+{\r
+ EFI_HANDLE RootBridgeHandle;\r
+ EFI_STATUS Status;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+\r
+ //\r
+ // Get the root bridge handle\r
+ //\r
+ RootBridgeHandle = RootBridgeDev->Handle;\r
+ PciRootBridgeIo = NULL;\r
+\r
+ //\r
+ // Get the pci root bridge io protocol\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ RootBridgeHandle,\r
+ &gEfiPciRootBridgeIoProtocolGuid,\r
+ (VOID **) &PciRootBridgeIo,\r
+ gPciBusDriverBinding.DriverBindingHandle,\r
+ RootBridgeHandle,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+\r
+ if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Store the PciRootBridgeIo protocol into root bridge private data\r
+ //\r
+ RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+ This routine can be used to check whether a PCI device should be rejected when light enumeration.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+\r
+ @retval TRUE This device should be rejected.\r
+ @retval FALSE This device shouldn't be rejected.\r
+\r
+**/\r
+BOOLEAN\r
+IsPciDeviceRejected (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 TestValue;\r
+ UINT32 OldValue;\r
+ UINT32 Mask;\r
+ UINT8 BarOffset;\r
+\r
+ //\r
+ // PPB should be skip!\r
+ //\r
+ if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
+ return FALSE;\r
+ }\r
+\r
+ if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
+ //\r
+ // Only test base registers for P2C\r
+ //\r
+ for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) {\r
+\r
+ Mask = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;\r
+ Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ TestValue = TestValue & Mask;\r
+ if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
+ //\r
+ // The bar isn't programed, so it should be rejected\r
+ //\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+ }\r
+\r
+ for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) {\r
+ //\r
+ // Test PCI devices\r
+ //\r
+ Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ if ((TestValue & 0x01) != 0) {\r
+\r
+ //\r
+ // IO Bar\r
+ //\r
+ Mask = 0xFFFFFFFC;\r
+ TestValue = TestValue & Mask;\r
+ if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
+ return TRUE;\r
+ }\r
+\r
+ } else {\r
+\r
+ //\r
+ // Mem Bar\r
+ //\r
+ Mask = 0xFFFFFFF0;\r
+ TestValue = TestValue & Mask;\r
+\r
+ if ((TestValue & 0x07) == 0x04) {\r
+\r
+ //\r
+ // Mem64 or PMem64\r
+ //\r
+ BarOffset += sizeof (UINT32);\r
+ if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
+\r
+ //\r
+ // Test its high 32-Bit BAR\r
+ //\r
+ Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
+ if (TestValue == OldValue) {\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ } else {\r
+\r
+ //\r
+ // Mem32 or PMem32\r
+ //\r
+ if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
+ return TRUE;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Reset all bus number from specific bridge.\r
+\r
+ @param Bridge Parent specific bridge.\r
+ @param StartBusNumber Start bus number.\r
+\r
+**/\r
+VOID\r
+ResetAllPpbBusNumber (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN UINT8 StartBusNumber\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_TYPE00 Pci;\r
+ UINT8 Device;\r
+ UINT32 Register;\r
+ UINT8 Func;\r
+ UINT64 Address;\r
+ UINT8 SecondaryBus;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+\r
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
+\r
+ for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
+ for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
+\r
+ //\r
+ // Check to see whether a pci device is present\r
+ //\r
+ Status = PciDevicePresent (\r
+ PciRootBridgeIo,\r
+ &Pci,\r
+ StartBusNumber,\r
+ Device,\r
+ Func\r
+ );\r
+\r
+ if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {\r
+\r
+ Register = 0;\r
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);\r
+ Status = PciRootBridgeIo->Pci.Read (\r
+ PciRootBridgeIo,\r
+ EfiPciWidthUint32,\r
+ Address,\r
+ 1,\r
+ &Register\r
+ );\r
+ SecondaryBus = (UINT8)(Register >> 8);\r
+\r
+ if (SecondaryBus != 0) {\r
+ ResetAllPpbBusNumber (Bridge, SecondaryBus);\r
+ }\r
+\r
+ //\r
+ // Reset register 18h, 19h, 1Ah on PCI Bridge\r
+ //\r
+ Register &= 0xFF000000;\r
+ Status = PciRootBridgeIo->Pci.Write (\r
+ PciRootBridgeIo,\r
+ EfiPciWidthUint32,\r
+ Address,\r
+ 1,\r
+ &Register\r
+ );\r
+ }\r
+\r
+ if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
+ //\r
+ // Skip sub functions, this is not a multi function device\r
+ //\r
+ Func = PCI_MAX_FUNC;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ PCI emumeration support functions declaration 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
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_ENUMERATOR_SUPPORT_H_\r
+#define _EFI_PCI_ENUMERATOR_SUPPORT_H_\r
+\r
+/**\r
+ This routine is used to check whether the pci device is present.\r
+\r
+ @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+ @param Pci Output buffer for PCI device configuration space.\r
+ @param Bus PCI bus NO.\r
+ @param Device PCI device NO.\r
+ @param Func PCI Func NO.\r
+\r
+ @retval EFI_NOT_FOUND PCI device not present.\r
+ @retval EFI_SUCCESS PCI device is found.\r
+\r
+**/\r
+EFI_STATUS\r
+PciDevicePresent (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
+ OUT PCI_TYPE00 *Pci,\r
+ IN UINT8 Bus,\r
+ IN UINT8 Device,\r
+ IN UINT8 Func\r
+ );\r
+\r
+/**\r
+ Collect all the resource information under this root bridge.\r
+\r
+ A database that records all the information about pci device subject to this\r
+ root bridge will then be created.\r
+\r
+ @param Bridge Parent bridge instance.\r
+ @param StartBusNumber Bus number of begining.\r
+\r
+ @retval EFI_SUCCESS PCI device is found.\r
+ @retval other Some error occurred when reading PCI bridge information.\r
+\r
+**/\r
+EFI_STATUS\r
+PciPciDeviceInfoCollector (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN UINT8 StartBusNumber\r
+ );\r
+\r
+/**\r
+ Seach required device and create PCI device instance.\r
+\r
+ @param Bridge Parent bridge instance.\r
+ @param Pci Input PCI device information block.\r
+ @param Bus PCI bus NO.\r
+ @param Device PCI device NO.\r
+ @param Func PCI func NO.\r
+ @param PciDevice Output of searched PCI device instance.\r
+\r
+ @retval EFI_SUCCESS Successfully created PCI device instance.\r
+ @retval EFI_OUT_OF_RESOURCES Cannot get PCI device information.\r
+\r
+**/\r
+EFI_STATUS\r
+PciSearchDevice (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN PCI_TYPE00 *Pci,\r
+ IN UINT8 Bus,\r
+ IN UINT8 Device,\r
+ IN UINT8 Func,\r
+ OUT PCI_IO_DEVICE **PciDevice\r
+ );\r
+\r
+/**\r
+ Create PCI device instance for PCI device.\r
+\r
+ @param Bridge Parent bridge instance.\r
+ @param Pci Input PCI device information block.\r
+ @param Bus PCI device Bus NO.\r
+ @param Device PCI device Device NO.\r
+ @param Func PCI device's func NO.\r
+\r
+ @return Created PCI device instance.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+GatherDeviceInfo (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN PCI_TYPE00 *Pci,\r
+ IN UINT8 Bus,\r
+ IN UINT8 Device,\r
+ IN UINT8 Func\r
+ );\r
+\r
+/**\r
+ Create PCI device instance for PCI-PCI bridge.\r
+\r
+ @param Bridge Parent bridge instance.\r
+ @param Pci Input PCI device information block.\r
+ @param Bus PCI device Bus NO.\r
+ @param Device PCI device Device NO.\r
+ @param Func PCI device's func NO.\r
+\r
+ @return Created PCI device instance.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+GatherPpbInfo (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN PCI_TYPE00 *Pci,\r
+ IN UINT8 Bus,\r
+ IN UINT8 Device,\r
+ IN UINT8 Func\r
+ );\r
+\r
+/**\r
+ Create PCI device instance for PCI Card bridge device.\r
+\r
+ @param Bridge Parent bridge instance.\r
+ @param Pci Input PCI device information block.\r
+ @param Bus PCI device Bus NO.\r
+ @param Device PCI device Device NO.\r
+ @param Func PCI device's func NO.\r
+\r
+ @return Created PCI device instance.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+GatherP2CInfo (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN PCI_TYPE00 *Pci,\r
+ IN UINT8 Bus,\r
+ IN UINT8 Device,\r
+ IN UINT8 Func\r
+ );\r
+\r
+/**\r
+ Create device path for pci deivce.\r
+\r
+ @param ParentDevicePath Parent bridge's path.\r
+ @param PciIoDevice Pci device instance.\r
+\r
+ @return device path protocol instance for specific pci device.\r
+\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+CreatePciDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+/**\r
+ Check whether the PCI IOV VF bar is existed or not.\r
+\r
+ @param PciIoDevice A pointer to the PCI_IO_DEVICE.\r
+ @param Offset The offset.\r
+ @param BarLengthValue The bar length value returned.\r
+ @param OriginalBarValue The original bar value returned.\r
+\r
+ @retval EFI_NOT_FOUND The bar doesn't exist.\r
+ @retval EFI_SUCCESS The bar exist.\r
+\r
+**/\r
+EFI_STATUS\r
+VfBarExisted (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINTN Offset,\r
+ OUT UINT32 *BarLengthValue,\r
+ OUT UINT32 *OriginalBarValue\r
+ );\r
+\r
+/**\r
+ Check whether the bar is existed or not.\r
+\r
+ @param PciIoDevice A pointer to the PCI_IO_DEVICE.\r
+ @param Offset The offset.\r
+ @param BarLengthValue The bar length value returned.\r
+ @param OriginalBarValue The original bar value returned.\r
+\r
+ @retval EFI_NOT_FOUND The bar doesn't exist.\r
+ @retval EFI_SUCCESS The bar exist.\r
+\r
+**/\r
+EFI_STATUS\r
+BarExisted (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINTN Offset,\r
+ OUT UINT32 *BarLengthValue,\r
+ OUT UINT32 *OriginalBarValue\r
+ );\r
+\r
+/**\r
+ Test whether the device can support given attributes.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+ @param Command Input command register value, and\r
+ returned supported register value.\r
+ @param BridgeControl Inout bridge control value for PPB or P2C, and\r
+ returned supported bridge control value.\r
+ @param OldCommand Returned and stored old command register offset.\r
+ @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C.\r
+\r
+**/\r
+VOID\r
+PciTestSupportedAttribute (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN OUT UINT16 *Command,\r
+ IN OUT UINT16 *BridgeControl,\r
+ OUT UINT16 *OldCommand,\r
+ OUT UINT16 *OldBridgeControl\r
+ );\r
+\r
+/**\r
+ Set the supported or current attributes of a PCI device.\r
+\r
+ @param PciIoDevice Structure pointer for PCI device.\r
+ @param Command Command register value.\r
+ @param BridgeControl Bridge control value for PPB or P2C.\r
+ @param Option Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.\r
+\r
+**/\r
+VOID\r
+PciSetDeviceAttribute (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINT16 Command,\r
+ IN UINT16 BridgeControl,\r
+ IN UINTN Option\r
+ );\r
+\r
+/**\r
+ Determine if the device can support Fast Back to Back attribute.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+ @param StatusIndex Status register value.\r
+\r
+ @retval EFI_SUCCESS This device support Fast Back to Back attribute.\r
+ @retval EFI_UNSUPPORTED This device doesn't support Fast Back to Back attribute.\r
+\r
+**/\r
+EFI_STATUS\r
+GetFastBackToBackSupport (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINT8 StatusIndex\r
+ );\r
+\r
+/**\r
+ Determine the related attributes of all devices under a Root Bridge.\r
+\r
+ @param PciIoDevice PCI device instance.\r
+\r
+**/\r
+EFI_STATUS\r
+DetermineDeviceAttribute (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+/**\r
+ This routine is used to update the bar information for those incompatible PCI device.\r
+\r
+ @param PciIoDevice Input Pci device instance. Output Pci device instance with updated\r
+ Bar information.\r
+\r
+ @retval EFI_SUCCESS Successfully updated bar information.\r
+ @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.\r
+\r
+**/\r
+EFI_STATUS\r
+UpdatePciInfo (\r
+ IN OUT PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+/**\r
+ This routine will update the alignment with the new alignment.\r
+\r
+ @param Alignment Input Old alignment. Output updated alignment.\r
+ @param NewAlignment New alignment.\r
+\r
+**/\r
+VOID\r
+SetNewAlign (\r
+ IN OUT UINT64 *Alignment,\r
+ IN UINT64 NewAlignment\r
+ );\r
+\r
+/**\r
+ Parse PCI bar information and fill them into PCI device instance.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+ @param Offset Bar offset.\r
+ @param BarIndex Bar index.\r
+\r
+ @return Next bar offset.\r
+\r
+**/\r
+UINTN\r
+PciParseBar (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINTN Offset,\r
+ IN UINTN BarIndex\r
+ );\r
+\r
+/**\r
+ Parse PCI IOV VF bar information and fill them into PCI device instance.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+ @param Offset Bar offset.\r
+ @param BarIndex Bar index.\r
+\r
+ @return Next bar offset.\r
+\r
+**/\r
+UINTN\r
+PciIovParseVfBar (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINTN Offset,\r
+ IN UINTN BarIndex\r
+ );\r
+\r
+/**\r
+ This routine is used to initialize the bar of a PCI device.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+\r
+ @note It can be called typically when a device is going to be rejected.\r
+\r
+**/\r
+VOID\r
+InitializePciDevice (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+/**\r
+ This routine is used to initialize the bar of a PCI-PCI Bridge device.\r
+\r
+ @param PciIoDevice PCI-PCI bridge device instance.\r
+\r
+**/\r
+VOID\r
+InitializePpb (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+/**\r
+ This routine is used to initialize the bar of a PCI Card Bridge device.\r
+\r
+ @param PciIoDevice PCI Card bridge device.\r
+\r
+**/\r
+VOID\r
+InitializeP2C (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+/**\r
+ Create and initiliaze general PCI I/O device instance for\r
+ PCI device/bridge device/hotplug bridge device.\r
+\r
+ @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+ @param Pci Input Pci information block.\r
+ @param Bus Device Bus NO.\r
+ @param Device Device device NO.\r
+ @param Func Device func NO.\r
+\r
+ @return Instance of PCI device. NULL means no instance created.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+CreatePciIoDevice (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
+ IN PCI_TYPE00 *Pci,\r
+ IN UINT8 Bus,\r
+ IN UINT8 Device,\r
+ IN UINT8 Func\r
+ );\r
+\r
+/**\r
+ This routine is used to enumerate entire pci bus system\r
+ in a given platform.\r
+\r
+ It is only called on the second start on the same Root Bridge.\r
+\r
+ @param Controller Parent bridge handler.\r
+\r
+ @retval EFI_SUCCESS PCI enumeration finished successfully.\r
+ @retval other Some error occurred when enumerating the pci bus system.\r
+\r
+**/\r
+EFI_STATUS\r
+PciEnumeratorLight (\r
+ IN EFI_HANDLE Controller\r
+ );\r
+\r
+/**\r
+ Get bus range from PCI resource descriptor list.\r
+\r
+ @param Descriptors A pointer to the address space descriptor.\r
+ @param MinBus The min bus returned.\r
+ @param MaxBus The max bus returned.\r
+ @param BusRange The bus range returned.\r
+\r
+ @retval EFI_SUCCESS Successfully got bus range.\r
+ @retval EFI_NOT_FOUND Can not find the specific bus.\r
+\r
+**/\r
+EFI_STATUS\r
+PciGetBusRange (\r
+ IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,\r
+ OUT UINT16 *MinBus,\r
+ OUT UINT16 *MaxBus,\r
+ OUT UINT16 *BusRange\r
+ );\r
+\r
+/**\r
+ This routine can be used to start the root bridge.\r
+\r
+ @param RootBridgeDev Pci device instance.\r
+\r
+ @retval EFI_SUCCESS This device started.\r
+ @retval other Failed to get PCI Root Bridge I/O protocol.\r
+\r
+**/\r
+EFI_STATUS\r
+StartManagingRootBridge (\r
+ IN PCI_IO_DEVICE *RootBridgeDev\r
+ );\r
+\r
+/**\r
+ This routine can be used to check whether a PCI device should be rejected when light enumeration.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+\r
+ @retval TRUE This device should be rejected.\r
+ @retval FALSE This device shouldn't be rejected.\r
+\r
+**/\r
+BOOLEAN\r
+IsPciDeviceRejected (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+/**\r
+ Reset all bus number from specific bridge.\r
+\r
+ @param Bridge Parent specific bridge.\r
+ @param StartBusNumber Start bus number.\r
+\r
+**/\r
+VOID\r
+ResetAllPpbBusNumber (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN UINT8 StartBusNumber\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ PCI Hot Plug support functions implementation 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
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+EFI_PCI_HOT_PLUG_INIT_PROTOCOL *gPciHotPlugInit = NULL;\r
+EFI_HPC_LOCATION *gPciRootHpcPool = NULL;\r
+UINTN gPciRootHpcCount = 0;\r
+ROOT_HPC_DATA *gPciRootHpcData = NULL;\r
+\r
+\r
+/**\r
+ Event notification function to set Hot Plug controller status.\r
+\r
+ @param Event The event that invoke this function.\r
+ @param Context The calling context, pointer to ROOT_HPC_DATA.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+PciHPCInitialized (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ ROOT_HPC_DATA *HpcData;\r
+\r
+ HpcData = (ROOT_HPC_DATA *) Context;\r
+ HpcData->Initialized = TRUE;\r
+}\r
+\r
+/**\r
+ Compare two device pathes to check if they are exactly same.\r
+\r
+ @param DevicePath1 A pointer to the first device path data structure.\r
+ @param DevicePath2 A pointer to the second device path data structure.\r
+\r
+ @retval TRUE They are same.\r
+ @retval FALSE They are not same.\r
+\r
+**/\r
+BOOLEAN\r
+EfiCompareDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2\r
+ )\r
+{\r
+ UINTN Size1;\r
+ UINTN Size2;\r
+\r
+ Size1 = GetDevicePathSize (DevicePath1);\r
+ Size2 = GetDevicePathSize (DevicePath2);\r
+\r
+ if (Size1 != Size2) {\r
+ return FALSE;\r
+ }\r
+\r
+ if (CompareMem (DevicePath1, DevicePath2, Size1) != 0) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Check hot plug support and initialize root hot plug private data.\r
+\r
+ If Hot Plug is supported by the platform, call PCI Hot Plug Init protocol\r
+ to get PCI Hot Plug controller's information and constructor the root hot plug\r
+ private data structure.\r
+\r
+ @retval EFI_SUCCESS They are same.\r
+ @retval EFI_UNSUPPORTED No PCI Hot Plug controler on the platform.\r
+ @retval EFI_OUT_OF_RESOURCES No memory to constructor root hot plug private\r
+ data structure.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeHotPlugSupport (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HPC_LOCATION *HpcList;\r
+ UINTN HpcCount;\r
+\r
+ //\r
+ // Locate the PciHotPlugInit Protocol\r
+ // If it doesn't exist, that means there is no\r
+ // hot plug controller supported on the platform\r
+ // the PCI Bus driver is running on. HotPlug Support\r
+ // is an optional feature, so absence of the protocol\r
+ // won't incur the penalty.\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiPciHotPlugInitProtocolGuid,\r
+ NULL,\r
+ (VOID **) &gPciHotPlugInit\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = gPciHotPlugInit->GetRootHpcList (\r
+ gPciHotPlugInit,\r
+ &HpcCount,\r
+ &HpcList\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+\r
+ gPciRootHpcPool = HpcList;\r
+ gPciRootHpcCount = HpcCount;\r
+ gPciRootHpcData = AllocateZeroPool (sizeof (ROOT_HPC_DATA) * gPciRootHpcCount);\r
+ if (gPciRootHpcData == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Test whether device path is for root pci hot plug bus.\r
+\r
+ @param HpbDevicePath A pointer to device path data structure to be tested.\r
+ @param HpIndex If HpIndex is not NULL, return the index of root hot\r
+ plug in global array when TRUE is retuned.\r
+\r
+ @retval TRUE The device path is for root pci hot plug bus.\r
+ @retval FALSE The device path is not for root pci hot plug bus.\r
+\r
+**/\r
+BOOLEAN\r
+IsRootPciHotPlugBus (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *HpbDevicePath,\r
+ OUT UINTN *HpIndex OPTIONAL\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ for (Index = 0; Index < gPciRootHpcCount; Index++) {\r
+\r
+ if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpbDevicePath, HpbDevicePath)) {\r
+\r
+ if (HpIndex != NULL) {\r
+ *HpIndex = Index;\r
+ }\r
+\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Test whether device path is for root pci hot plug controller.\r
+\r
+ @param HpcDevicePath A pointer to device path data structure to be tested.\r
+ @param HpIndex If HpIndex is not NULL, return the index of root hot\r
+ plug in global array when TRUE is retuned.\r
+\r
+ @retval TRUE The device path is for root pci hot plug controller.\r
+ @retval FALSE The device path is not for root pci hot plug controller.\r
+\r
+**/\r
+BOOLEAN\r
+IsRootPciHotPlugController (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,\r
+ OUT UINTN *HpIndex\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ for (Index = 0; Index < gPciRootHpcCount; Index++) {\r
+\r
+ if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpcDevicePath, HpcDevicePath)) {\r
+\r
+ if (HpIndex != NULL) {\r
+ *HpIndex = Index;\r
+ }\r
+\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Creating event object for PCI Hot Plug controller.\r
+\r
+ @param HpIndex Index of hot plug device in global array.\r
+ @param Event The retuned event that invoke this function.\r
+\r
+ @return Status of create event invoken.\r
+\r
+**/\r
+EFI_STATUS\r
+CreateEventForHpc (\r
+ IN UINTN HpIndex,\r
+ OUT EFI_EVENT *Event\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ PciHPCInitialized,\r
+ gPciRootHpcData + HpIndex,\r
+ &((gPciRootHpcData + HpIndex)->Event)\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ *Event = (gPciRootHpcData + HpIndex)->Event;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Wait for all root PCI Hot Plug controller finished initializing.\r
+\r
+ @param TimeoutInMicroSeconds Microseconds to wait for all root HPCs' initialization.\r
+\r
+ @retval EFI_SUCCESS All HPCs initialization finished.\r
+ @retval EFI_TIMEOUT Not ALL HPCs initialization finished in Microseconds.\r
+\r
+**/\r
+EFI_STATUS\r
+AllRootHPCInitialized (\r
+ IN UINTN TimeoutInMicroSeconds\r
+ )\r
+{\r
+ UINT32 Delay;\r
+ UINTN Index;\r
+\r
+ Delay = (UINT32) ((TimeoutInMicroSeconds / 30) + 1);\r
+\r
+ do {\r
+ for (Index = 0; Index < gPciRootHpcCount; Index++) {\r
+\r
+ if (!gPciRootHpcData[Index].Initialized) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index == gPciRootHpcCount) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Stall for 30 microseconds..\r
+ //\r
+ gBS->Stall (30);\r
+\r
+ Delay--;\r
+\r
+ } while (Delay > 0);\r
+\r
+ return EFI_TIMEOUT;\r
+}\r
+\r
+/**\r
+ Check whether PCI-PCI bridge has PCI Hot Plug capability register block.\r
+\r
+ @param PciIoDevice A Pointer to the PCI-PCI bridge.\r
+\r
+ @retval TRUE PCI device is HPC.\r
+ @retval FALSE PCI device is not HPC.\r
+\r
+**/\r
+BOOLEAN\r
+IsSHPC (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+\r
+ EFI_STATUS Status;\r
+ UINT8 Offset;\r
+\r
+ if (PciIoDevice == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ Offset = 0;\r
+ Status = LocateCapabilityRegBlock (\r
+ PciIoDevice,\r
+ EFI_PCI_CAPABILITY_ID_HOTPLUG,\r
+ &Offset,\r
+ NULL\r
+ );\r
+\r
+ //\r
+ // If the PCI-PCI bridge has the hot plug controller build-in,\r
+ // then return TRUE;\r
+ //\r
+ if (!EFI_ERROR (Status)) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Get resource padding if the specified PCI bridge is a hot plug bus.\r
+\r
+ @param PciIoDevice PCI bridge instance.\r
+\r
+**/\r
+VOID\r
+GetResourcePaddingForHpb (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HPC_STATE State;\r
+ UINT64 PciAddress;\r
+ EFI_HPC_PADDING_ATTRIBUTES Attributes;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
+\r
+ if (IsPciHotPlugBus (PciIoDevice)) {\r
+ //\r
+ // If PCI-PCI bridge device is PCI Hot Plug bus.\r
+ //\r
+ PciAddress = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);\r
+ Status = gPciHotPlugInit->GetResourcePadding (\r
+ gPciHotPlugInit,\r
+ PciIoDevice->DevicePath,\r
+ PciAddress,\r
+ &State,\r
+ (VOID **) &Descriptors,\r
+ &Attributes\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+\r
+ if ((State & EFI_HPC_STATE_ENABLED) != 0 && (State & EFI_HPC_STATE_INITIALIZED) != 0) {\r
+ PciIoDevice->ResourcePaddingDescriptors = Descriptors;\r
+ PciIoDevice->PaddingAttributes = Attributes;\r
+ }\r
+\r
+ return;\r
+ }\r
+}\r
+\r
+/**\r
+ Test whether PCI device is hot plug bus.\r
+\r
+ @param PciIoDevice PCI device instance.\r
+\r
+ @retval TRUE PCI device is a hot plug bus.\r
+ @retval FALSE PCI device is not a hot plug bus.\r
+\r
+**/\r
+BOOLEAN\r
+IsPciHotPlugBus (\r
+ PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ if (IsSHPC (PciIoDevice)) {\r
+ //\r
+ // If the PPB has the hot plug controller build-in,\r
+ // then return TRUE;\r
+ //\r
+ return TRUE;\r
+ }\r
+\r
+ //\r
+ // Otherwise, see if it is a Root HPC\r
+ //\r
+ if(IsRootPciHotPlugBus (PciIoDevice->DevicePath, NULL)) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ PCI Hot Plug support functions declaration 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
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_HOT_PLUG_SUPPORT_H_\r
+#define _EFI_PCI_HOT_PLUG_SUPPORT_H_\r
+\r
+//\r
+// stall 1 second, its unit is 100ns\r
+//\r
+#define STALL_1_SECOND 1000000\r
+\r
+//\r
+// PCI Hot Plug controller private data\r
+//\r
+typedef struct {\r
+ EFI_EVENT Event;\r
+ BOOLEAN Initialized;\r
+ VOID *Padding;\r
+} ROOT_HPC_DATA;\r
+\r
+//\r
+// Reference of some global variabes\r
+//\r
+extern EFI_PCI_HOT_PLUG_INIT_PROTOCOL *gPciHotPlugInit;\r
+extern EFI_HPC_LOCATION *gPciRootHpcPool;\r
+extern ROOT_HPC_DATA *gPciRootHpcData;\r
+\r
+/**\r
+ Event notification function to set Hot Plug controller status.\r
+\r
+ @param Event The event that invoke this function.\r
+ @param Context The calling context, pointer to ROOT_HPC_DATA.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+PciHPCInitialized (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ );\r
+\r
+/**\r
+ Compare two device pathes to check if they are exactly same.\r
+\r
+ @param DevicePath1 A pointer to the first device path data structure.\r
+ @param DevicePath2 A pointer to the second device path data structure.\r
+\r
+ @retval TRUE They are same.\r
+ @retval FALSE They are not same.\r
+\r
+**/\r
+BOOLEAN\r
+EfiCompareDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2\r
+ );\r
+\r
+/**\r
+ Check hot plug support and initialize root hot plug private data.\r
+\r
+ If Hot Plug is supported by the platform, call PCI Hot Plug Init protocol\r
+ to get PCI Hot Plug controller's information and constructor the root hot plug\r
+ private data structure.\r
+\r
+ @retval EFI_SUCCESS They are same.\r
+ @retval EFI_UNSUPPORTED No PCI Hot Plug controler on the platform.\r
+ @retval EFI_OUT_OF_RESOURCES No memory to constructor root hot plug private\r
+ data structure.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeHotPlugSupport (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Test whether PCI device is hot plug bus.\r
+\r
+ @param PciIoDevice PCI device instance.\r
+\r
+ @retval TRUE PCI device is a hot plug bus.\r
+ @retval FALSE PCI device is not a hot plug bus.\r
+\r
+**/\r
+BOOLEAN\r
+IsPciHotPlugBus (\r
+ PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+/**\r
+ Test whether device path is for root pci hot plug bus.\r
+\r
+ @param HpbDevicePath A pointer to device path data structure to be tested.\r
+ @param HpIndex If HpIndex is not NULL, return the index of root hot\r
+ plug in global array when TRUE is retuned.\r
+\r
+ @retval TRUE The device path is for root pci hot plug bus.\r
+ @retval FALSE The device path is not for root pci hot plug bus.\r
+\r
+**/\r
+BOOLEAN\r
+IsRootPciHotPlugBus (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *HpbDevicePath,\r
+ OUT UINTN *HpIndex OPTIONAL\r
+ );\r
+\r
+/**\r
+ Test whether device path is for root pci hot plug controller.\r
+\r
+ @param HpcDevicePath A pointer to device path data structure to be tested.\r
+ @param HpIndex If HpIndex is not NULL, return the index of root hot\r
+ plug in global array when TRUE is retuned.\r
+\r
+ @retval TRUE The device path is for root pci hot plug controller.\r
+ @retval FALSE The device path is not for root pci hot plug controller.\r
+\r
+**/\r
+BOOLEAN\r
+IsRootPciHotPlugController (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,\r
+ OUT UINTN *HpIndex\r
+ );\r
+\r
+/**\r
+ Creating event object for PCI Hot Plug controller.\r
+\r
+ @param HpIndex Index of hot plug device in global array.\r
+ @param Event The retuned event that invoke this function.\r
+\r
+ @return Status of create event invoken.\r
+\r
+**/\r
+EFI_STATUS\r
+CreateEventForHpc (\r
+ IN UINTN HpIndex,\r
+ OUT EFI_EVENT *Event\r
+ );\r
+\r
+/**\r
+ Wait for all root PCI Hot Plug controller finished initializing.\r
+\r
+ @param TimeoutInMicroSeconds Microseconds to wait for all root HPCs' initialization.\r
+\r
+ @retval EFI_SUCCESS All HPCs initialization finished.\r
+ @retval EFI_TIMEOUT Not ALL HPCs initialization finished in Microseconds.\r
+\r
+**/\r
+EFI_STATUS\r
+AllRootHPCInitialized (\r
+ IN UINTN TimeoutInMicroSeconds\r
+ );\r
+\r
+/**\r
+ Check whether PCI-PCI bridge has PCI Hot Plug capability register block.\r
+\r
+ @param PciIoDevice A Pointer to the PCI-PCI bridge.\r
+\r
+ @retval TRUE PCI device is HPC.\r
+ @retval FALSE PCI device is not HPC.\r
+\r
+**/\r
+BOOLEAN\r
+IsSHPC (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+/**\r
+ Get resource padding if the specified PCI bridge is a hot plug bus.\r
+\r
+ @param PciIoDevice PCI bridge instance.\r
+\r
+**/\r
+VOID\r
+GetResourcePaddingForHpb (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ EFI PCI IO protocol functions implementation 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
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+//\r
+// Pci Io Protocol Interface\r
+//\r
+EFI_PCI_IO_PROTOCOL mPciIoInterface = {\r
+ PciIoPollMem,\r
+ PciIoPollIo,\r
+ {\r
+ PciIoMemRead,\r
+ PciIoMemWrite\r
+ },\r
+ {\r
+ PciIoIoRead,\r
+ PciIoIoWrite\r
+ },\r
+ {\r
+ PciIoConfigRead,\r
+ PciIoConfigWrite\r
+ },\r
+ PciIoCopyMem,\r
+ PciIoMap,\r
+ PciIoUnmap,\r
+ PciIoAllocateBuffer,\r
+ PciIoFreeBuffer,\r
+ PciIoFlush,\r
+ PciIoGetLocation,\r
+ PciIoAttributes,\r
+ PciIoGetBarAttributes,\r
+ PciIoSetBarAttributes,\r
+ 0,\r
+ NULL\r
+};\r
+\r
+/**\r
+ Report a error Status code of PCI bus driver controller.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+ @param Code Status code value.\r
+\r
+**/\r
+EFI_STATUS\r
+ReportErrorStatusCode (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN EFI_STATUS_CODE_VALUE Code\r
+ )\r
+{\r
+ return REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ Code,\r
+ PciIoDevice->DevicePath\r
+ );\r
+}\r
+\r
+/**\r
+ Initializes a PCI I/O Instance.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+\r
+**/\r
+VOID\r
+InitializePciIoInstance (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ CopyMem (&PciIoDevice->PciIo, &mPciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL));\r
+}\r
+\r
+/**\r
+ Verifies access to a PCI Base Address Register (BAR).\r
+\r
+ @param PciIoDevice Pci device instance.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for the memory or I/O operation to perform.\r
+ @param Type Operation type could be memory or I/O.\r
+ @param Width Signifies the width of the memory or I/O operations.\r
+ @param Count The number of memory or I/O operations to perform.\r
+ @param Offset The offset within the PCI configuration space for the PCI controller.\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid Width/BarIndex or Bar type.\r
+ @retval EFI_SUCCESS Successfully verified.\r
+\r
+**/\r
+EFI_STATUS\r
+PciIoVerifyBarAccess (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINT8 BarIndex,\r
+ IN PCI_BAR_TYPE Type,\r
+ IN IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN IN UINTN Count,\r
+ IN UINT64 *Offset\r
+ )\r
+{\r
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BarIndex == EFI_PCI_IO_PASS_THROUGH_BAR) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // BarIndex 0-5 is legal\r
+ //\r
+ if (BarIndex >= PCI_MAX_BAR) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (!CheckBarType (PciIoDevice, BarIndex, Type)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX\r
+ // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX\r
+ //\r
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
+ Count = 1;\r
+ }\r
+\r
+ Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
+\r
+ if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PciIoDevice->PciBar[BarIndex].Length) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *Offset = *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Verifies access to a PCI Configuration Header.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+ @param Width Signifies the width of the memory or I/O operations.\r
+ @param Count The number of memory or I/O operations to perform.\r
+ @param Offset The offset within the PCI configuration space for the PCI controller.\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid Width\r
+ @retval EFI_UNSUPPORTED Offset overflowed.\r
+ @retval EFI_SUCCESS Successfully verified.\r
+\r
+**/\r
+EFI_STATUS\r
+PciIoVerifyConfigAccess (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINTN Count,\r
+ IN UINT64 *Offset\r
+ )\r
+{\r
+ UINT64 ExtendOffset;\r
+\r
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX\r
+ //\r
+ Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
+\r
+ if (PciIoDevice->IsPciExp) {\r
+ if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ ExtendOffset = LShiftU64 (*Offset, 32);\r
+ *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);\r
+ *Offset = (*Offset) | ExtendOffset;\r
+\r
+ } else {\r
+ if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is\r
+ satisfied or after a defined duration.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Width Signifies the width of the memory or I/O operations.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for the memory operation to perform.\r
+ @param Offset The offset within the selected BAR to start the memory operation.\r
+ @param Mask Mask used for the polling criteria.\r
+ @param Value The comparison value used for the polling exit criteria.\r
+ @param Delay The number of 100 ns units to poll.\r
+ @param Result Pointer to the last value read from the memory location.\r
+\r
+ @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.\r
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
+ @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of this PCI controller.\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 lack of resources.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollMem (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, 1, &Offset);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (Width > EfiPciIoWidthUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->PollMem (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Offset,\r
+ Mask,\r
+ Value,\r
+ Delay,\r
+ Result\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is\r
+ satisfied or after a defined duration.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Width Signifies the width of the memory or I/O operations.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for the memory operation to perform.\r
+ @param Offset The offset within the selected BAR to start the memory operation.\r
+ @param Mask Mask used for the polling criteria.\r
+ @param Value The comparison value used for the polling exit criteria.\r
+ @param Delay The number of 100 ns units to poll.\r
+ @param Result Pointer to the last value read from the memory location.\r
+\r
+ @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.\r
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
+ @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of this PCI controller.\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 lack of resources.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollIo (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Width < 0 || Width > EfiPciIoWidthUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, 1, &Offset);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->PollIo (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Offset,\r
+ Mask,\r
+ Value,\r
+ Delay,\r
+ Result\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Width Signifies the width of the memory or I/O operations.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for the memory or I/O operation to perform.\r
+ @param Offset The offset within the selected BAR to start the memory or I/O operation.\r
+ @param Count The number of memory or I/O operations to perform.\r
+ @param Buffer For read operations, the destination buffer to store the results. For write\r
+ operations, the source buffer to write data from.\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
+ @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
+ valid for the PCI BAR specified by BarIndex.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemRead (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->Mem.Read (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Offset,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Width Signifies the width of the memory or I/O operations.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for the memory or I/O operation to perform.\r
+ @param Offset The offset within the selected BAR to start the memory or I/O operation.\r
+ @param Count The number of memory or I/O operations to perform.\r
+ @param Buffer For read operations, the destination buffer to store the results. For write\r
+ operations, the source buffer to write data from.\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
+ @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
+ valid for the PCI BAR specified by BarIndex.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemWrite (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->Mem.Write (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Offset,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Width Signifies the width of the memory or I/O operations.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for the memory or I/O operation to perform.\r
+ @param Offset The offset within the selected BAR to start the memory or I/O operation.\r
+ @param Count The number of memory or I/O operations to perform.\r
+ @param Buffer For read operations, the destination buffer to store the results. For write\r
+ operations, the source buffer to write data from.\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
+ @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
+ valid for the PCI BAR specified by BarIndex.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoRead (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->Io.Read (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Offset,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Width Signifies the width of the memory or I/O operations.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for the memory or I/O operation to perform.\r
+ @param Offset The offset within the selected BAR to start the memory or I/O operation.\r
+ @param Count The number of memory or I/O operations to perform.\r
+ @param Buffer For read operations, the destination buffer to store the results. For write\r
+ operations, the source buffer to write data from.\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
+ @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
+ valid for the PCI BAR specified by BarIndex.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoWrite (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->Io.Write (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Offset,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Enable a PCI driver to access PCI controller registers in PCI configuration space.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Width Signifies the width of the memory operations.\r
+ @param Offset The offset within the PCI configuration space for the PCI controller.\r
+ @param Count The number of PCI configuration operations to perform.\r
+ @param Buffer For read operations, the destination buffer to store the results. For write\r
+ operations, the source buffer to write data from.\r
+\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
+ @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
+ valid for the PCI configuration header of the PCI controller.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigRead (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT32 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ UINT64 Address;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ Address = Offset;\r
+ Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->Pci.Read (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Address,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Enable a PCI driver to access PCI controller registers in PCI configuration space.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Width Signifies the width of the memory operations.\r
+ @param Offset The offset within the PCI configuration space for the PCI controller.\r
+ @param Count The number of PCI configuration operations to perform.\r
+ @param Buffer For read operations, the destination buffer to store the results. For write\r
+ operations, the source buffer to write data from.\r
+\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
+ @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
+ valid for the PCI configuration header of the PCI controller.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigWrite (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT32 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ UINT64 Address;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ Address = Offset;\r
+ Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->Pci.Write (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Address,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Enables a PCI driver to copy one region of PCI memory space to another region of PCI\r
+ memory space.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Width Signifies the width of the memory operations.\r
+ @param DestBarIndex The BAR index in the standard PCI Configuration header to use as the\r
+ base address for the memory operation to perform.\r
+ @param DestOffset The destination offset within the BAR specified by DestBarIndex to\r
+ start the memory writes for the copy operation.\r
+ @param SrcBarIndex The BAR index in the standard PCI Configuration header to use as the\r
+ base address for the memory operation to perform.\r
+ @param SrcOffset The source offset within the BAR specified by SrcBarIndex to start\r
+ the memory reads for the copy operation.\r
+ @param Count The number of memory operations to perform. Bytes moved is Width\r
+ size * Count, starting at DestOffset and SrcOffset.\r
+\r
+ @retval EFI_SUCCESS The data was copied from one memory region to another memory region.\r
+ @retval EFI_UNSUPPORTED DestBarIndex not valid for this PCI controller.\r
+ @retval EFI_UNSUPPORTED SrcBarIndex not valid for this PCI controller.\r
+ @retval EFI_UNSUPPORTED The address range specified by DestOffset, Width, and Count\r
+ is not valid for the PCI BAR specified by DestBarIndex.\r
+ @retval EFI_UNSUPPORTED The address range specified by SrcOffset, Width, and Count is\r
+ not valid for the PCI BAR specified by SrcBarIndex.\r
+ @retval EFI_INVALID_PARAMETER Width is invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoCopyMem (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 DestBarIndex,\r
+ IN UINT64 DestOffset,\r
+ IN UINT8 SrcBarIndex,\r
+ IN UINT64 SrcOffset,\r
+ IN UINTN Count\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Width == EfiPciIoWidthFifoUint8 ||\r
+ Width == EfiPciIoWidthFifoUint16 ||\r
+ Width == EfiPciIoWidthFifoUint32 ||\r
+ Width == EfiPciIoWidthFifoUint64 ||\r
+ Width == EfiPciIoWidthFillUint8 ||\r
+ Width == EfiPciIoWidthFillUint16 ||\r
+ Width == EfiPciIoWidthFillUint32 ||\r
+ Width == EfiPciIoWidthFillUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, PciBarTypeMem, Width, Count, &DestOffset);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem, Width, Count, &SrcOffset);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->CopyMem (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ DestOffset,\r
+ SrcOffset,\r
+ Count\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Provides the PCI controller-specific addresses needed to access system memory.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Operation Indicates if the bus master is going to read or write to system memory.\r
+ @param HostAddress The system memory address to map to the PCI controller.\r
+ @param NumberOfBytes On input the number of bytes to map. On output the number of bytes\r
+ that were mapped.\r
+ @param DeviceAddress The resulting map address for the bus master PCI controller to use to\r
+ access the hosts HostAddress.\r
+ @param Mapping A resulting value to pass to Unmap().\r
+\r
+ @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.\r
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMap (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_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_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Operation < 0 || Operation >= EfiPciIoOperationMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) {\r
+ Operation = (EFI_PCI_IO_PROTOCOL_OPERATION) (Operation + EfiPciOperationBusMasterRead64);\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->Map (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,\r
+ HostAddress,\r
+ NumberOfBytes,\r
+ DeviceAddress,\r
+ Mapping\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Completes the Map() operation and releases any corresponding resources.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Mapping The mapping value returned from Map().\r
+\r
+ @retval EFI_SUCCESS The range was unmapped.\r
+ @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoUnmap (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN VOID *Mapping\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->Unmap (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ Mapping\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Allocates pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer\r
+ mapping.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\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 range.\r
+\r
+ @retval EFI_SUCCESS The requested memory pages were allocated.\r
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are\r
+ MEMORY_WRITE_COMBINE and MEMORY_CACHED.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAllocateBuffer (\r
+ IN EFI_PCI_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
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ if ((Attributes &\r
+ (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) != 0){\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) {\r
+ Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
+ }\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ Type,\r
+ MemoryType,\r
+ Pages,\r
+ HostAddress,\r
+ Attributes\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Frees memory that was allocated with AllocateBuffer().\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\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 Pages\r
+ was not allocated with AllocateBuffer().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFreeBuffer (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN UINTN Pages,\r
+ IN VOID *HostAddress\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->FreeBuffer (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ Pages,\r
+ HostAddress\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Flushes all PCI posted write transactions from a PCI host bridge to system memory.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+\r
+ @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host\r
+ bridge to system memory.\r
+ @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI\r
+ host bridge due to a hardware error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFlush (\r
+ IN EFI_PCI_IO_PROTOCOL *This\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->Flush (\r
+ PciIoDevice->PciRootBridgeIo\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Retrieves this PCI controller's current PCI bus number, device number, and function number.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param SegmentNumber The PCI controller's current PCI segment number.\r
+ @param BusNumber The PCI controller's current PCI bus number.\r
+ @param DeviceNumber The PCI controller's current PCI device number.\r
+ @param FunctionNumber The PCI controller's current PCI function number.\r
+\r
+ @retval EFI_SUCCESS The PCI controller location was returned.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetLocation (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ OUT UINTN *Segment,\r
+ OUT UINTN *Bus,\r
+ OUT UINTN *Device,\r
+ OUT UINTN *Function\r
+ )\r
+{\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *Segment = PciIoDevice->PciRootBridgeIo->SegmentNumber;\r
+ *Bus = PciIoDevice->BusNumber;\r
+ *Device = PciIoDevice->DeviceNumber;\r
+ *Function = PciIoDevice->FunctionNumber;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Check BAR type for PCI resource.\r
+\r
+ @param PciIoDevice PCI device instance.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for the memory or I/O operation to perform.\r
+ @param BarType Memory or I/O.\r
+\r
+ @retval TRUE Pci device's bar type is same with input BarType.\r
+ @retval TRUE Pci device's bar type is not same with input BarType.\r
+\r
+**/\r
+BOOLEAN\r
+CheckBarType (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINT8 BarIndex,\r
+ IN PCI_BAR_TYPE BarType\r
+ )\r
+{\r
+ switch (BarType) {\r
+\r
+ case PciBarTypeMem:\r
+\r
+ if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32 &&\r
+ PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 &&\r
+ PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 &&\r
+ PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64 ) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+\r
+ case PciBarTypeIo:\r
+ if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 &&\r
+ PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Set/Disable new attributes to a Root Bridge.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+ @param Attributes New attribute want to be set.\r
+ @param Operation Set or Disable.\r
+\r
+ @retval EFI_UNSUPPORTED If root bridge does not support change attribute.\r
+ @retval EFI_SUCCESS Successfully set new attributs.\r
+\r
+**/\r
+EFI_STATUS\r
+ModifyRootBridgeAttributes (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINT64 Attributes,\r
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation\r
+ )\r
+{\r
+ UINT64 PciRootBridgeSupports;\r
+ UINT64 PciRootBridgeAttributes;\r
+ UINT64 NewPciRootBridgeAttributes;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Get the current attributes of this PCI device's PCI Root Bridge\r
+ //\r
+ Status = PciIoDevice->PciRootBridgeIo->GetAttributes (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ &PciRootBridgeSupports,\r
+ &PciRootBridgeAttributes\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Record the new attribute of the Root Bridge\r
+ //\r
+ if (Operation == EfiPciIoAttributeOperationEnable) {\r
+ NewPciRootBridgeAttributes = PciRootBridgeAttributes | Attributes;\r
+ } else {\r
+ NewPciRootBridgeAttributes = PciRootBridgeAttributes & (~Attributes);\r
+ }\r
+\r
+ //\r
+ // Call the PCI Root Bridge to attempt to modify the attributes\r
+ //\r
+ if ((NewPciRootBridgeAttributes ^ PciRootBridgeAttributes) != 0) {\r
+\r
+ Status = PciIoDevice->PciRootBridgeIo->SetAttributes (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ NewPciRootBridgeAttributes,\r
+ NULL,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // The PCI Root Bridge could not modify the attributes, so return the error.\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Also update the attributes for this Root Bridge structure\r
+ //\r
+ PciIoDevice->Attributes = NewPciRootBridgeAttributes;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Check whether this device can be enable/disable to snoop.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+ @param Operation Enable/Disable.\r
+\r
+ @retval EFI_UNSUPPORTED Pci device is not GFX device or not support snoop.\r
+ @retval EFI_SUCCESS Snoop can be supported.\r
+\r
+**/\r
+EFI_STATUS\r
+SupportPaletteSnoopAttributes (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation\r
+ )\r
+{\r
+ PCI_IO_DEVICE *Temp;\r
+ UINT16 VGACommand;\r
+\r
+ //\r
+ // Snoop attribute can be only modified by GFX\r
+ //\r
+ if (!IS_PCI_GFX (&PciIoDevice->Pci)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Get the boot VGA on the same segement\r
+ //\r
+ Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);\r
+\r
+ if (Temp == NULL) {\r
+ //\r
+ // If there is no VGA device on the segement, set\r
+ // this graphics card to decode the palette range\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Check these two agents are on the same path\r
+ //\r
+ if (!PciDevicesOnTheSamePath (Temp, PciIoDevice)) {\r
+ //\r
+ // they are not on the same path, so snoop can be enabled or disabled\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Check if they are on the same bus\r
+ //\r
+ if (Temp->Parent == PciIoDevice->Parent) {\r
+\r
+ PCI_READ_COMMAND_REGISTER (Temp, &VGACommand);\r
+\r
+ //\r
+ // If they are on the same bus, either one can\r
+ // be set to snoop, the other set to decode\r
+ //\r
+ if ((VGACommand & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {\r
+ //\r
+ // VGA has set to snoop, so GFX can be only set to disable snoop\r
+ //\r
+ if (Operation == EfiPciIoAttributeOperationEnable) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ } else {\r
+ //\r
+ // VGA has disabled to snoop, so GFX can be only enabled\r
+ //\r
+ if (Operation == EfiPciIoAttributeOperationDisable) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // If they are on the same path but on the different bus\r
+ // The first agent is set to snoop, the second one set to\r
+ // decode\r
+ //\r
+\r
+ if (Temp->BusNumber < PciIoDevice->BusNumber) {\r
+ //\r
+ // GFX should be set to decode\r
+ //\r
+ if (Operation == EfiPciIoAttributeOperationDisable) {\r
+ PCI_ENABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);\r
+ Temp->Attributes |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+ } else {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ } else {\r
+ //\r
+ // GFX should be set to snoop\r
+ //\r
+ if (Operation == EfiPciIoAttributeOperationEnable) {\r
+ PCI_DISABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);\r
+ Temp->Attributes &= (~EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);\r
+ } else {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Performs an operation on the attributes that this PCI controller supports. The operations include\r
+ getting the set of supported attributes, retrieving the current attributes, setting the current\r
+ attributes, enabling attributes, and disabling attributes.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Operation The operation to perform on the attributes for this PCI controller.\r
+ @param Attributes The mask of attributes that are used for Set, Enable, and Disable\r
+ operations.\r
+ @param Result A pointer to the result mask of attributes that are returned for the Get\r
+ and Supported operations.\r
+\r
+ @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+ @retval EFI_UNSUPPORTED one or more of the bits set in\r
+ Attributes are not supported by this PCI controller or one of\r
+ its parent bridges when Operation is Set, Enable or Disable.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAttributes (\r
+ IN EFI_PCI_IO_PROTOCOL * This,\r
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,\r
+ IN UINT64 Attributes,\r
+ OUT UINT64 *Result OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ PCI_IO_DEVICE *UpStreamBridge;\r
+ PCI_IO_DEVICE *Temp;\r
+\r
+ UINT64 Supports;\r
+ UINT64 UpStreamAttributes;\r
+ UINT16 BridgeControl;\r
+ UINT16 Command;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ switch (Operation) {\r
+ case EfiPciIoAttributeOperationGet:\r
+ if (Result == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *Result = PciIoDevice->Attributes;\r
+ return EFI_SUCCESS;\r
+\r
+ case EfiPciIoAttributeOperationSupported:\r
+ if (Result == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *Result = PciIoDevice->Supports;\r
+ return EFI_SUCCESS;\r
+\r
+ case EfiPciIoAttributeOperationSet:\r
+ Status = PciIoDevice->PciIo.Attributes (\r
+ &(PciIoDevice->PciIo),\r
+ EfiPciIoAttributeOperationEnable,\r
+ Attributes,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = PciIoDevice->PciIo.Attributes (\r
+ &(PciIoDevice->PciIo),\r
+ EfiPciIoAttributeOperationDisable,\r
+ (~Attributes) & (PciIoDevice->Supports),\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ case EfiPciIoAttributeOperationEnable:\r
+ case EfiPciIoAttributeOperationDisable:\r
+ break;\r
+\r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Just a trick for ENABLE attribute\r
+ // EFI_PCI_DEVICE_ENABLE is not defined in UEFI spec, which is the internal usage.\r
+ // So, this logic doesn't confrom to UEFI spec, which should be removed.\r
+ // But this trick logic is still kept for some binary drivers that depend on it.\r
+ //\r
+ if ((Attributes & EFI_PCI_DEVICE_ENABLE) == EFI_PCI_DEVICE_ENABLE) {\r
+ Attributes &= (PciIoDevice->Supports);\r
+\r
+ //\r
+ // Raise the EFI_P_PC_ENABLE Status code\r
+ //\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ EFI_IO_BUS_PCI | EFI_P_PC_ENABLE,\r
+ PciIoDevice->DevicePath\r
+ );\r
+ }\r
+\r
+ //\r
+ // If no attributes can be supported, then return.\r
+ // Otherwise, set the attributes that it can support.\r
+ //\r
+ Supports = (PciIoDevice->Supports) & Attributes;\r
+ if (Supports != Attributes) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // For Root Bridge, just call RootBridgeIo to set attributes;\r
+ //\r
+ if (PciIoDevice->Parent == NULL) {\r
+ Status = ModifyRootBridgeAttributes (PciIoDevice, Attributes, Operation);\r
+ return Status;\r
+ }\r
+\r
+ Command = 0;\r
+ BridgeControl = 0;\r
+\r
+ //\r
+ // Check VGA and VGA16, they can not be set at the same time\r
+ //\r
+ if (((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) != 0 &&\r
+ (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO_16) != 0) ||\r
+ ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) != 0 &&\r
+ (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16) != 0) ||\r
+ ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) != 0 &&\r
+ (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO_16) != 0) ||\r
+ ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) != 0 &&\r
+ (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16) != 0) ) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // For PPB & P2C, set relevant attribute bits\r
+ //\r
+ if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
+\r
+ if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) != 0) {\r
+ BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA;\r
+ }\r
+\r
+ if ((Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) != 0) {\r
+ BridgeControl |= EFI_PCI_BRIDGE_CONTROL_ISA;\r
+ }\r
+\r
+ if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) != 0) {\r
+ Command |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;\r
+ }\r
+\r
+ if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) != 0) {\r
+ BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA_16;\r
+ }\r
+\r
+ } else {\r
+ //\r
+ // Do with the attributes on VGA\r
+ // Only for VGA's legacy resource, we just can enable once.\r
+ //\r
+ if ((Attributes &\r
+ (EFI_PCI_IO_ATTRIBUTE_VGA_IO |\r
+ EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 |\r
+ EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY)) != 0) {\r
+ //\r
+ // Check if a VGA has been enabled before enabling a new one\r
+ //\r
+ if (Operation == EfiPciIoAttributeOperationEnable) {\r
+ //\r
+ // Check if there have been an active VGA device on the same segment\r
+ //\r
+ Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);\r
+ if (Temp != NULL && Temp != PciIoDevice) {\r
+ //\r
+ // An active VGA has been detected, so can not enable another\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Do with the attributes on GFX\r
+ //\r
+ if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) != 0) {\r
+\r
+ if (Operation == EfiPciIoAttributeOperationEnable) {\r
+ //\r
+ // Check if snoop can be enabled in current configuration\r
+ //\r
+ Status = SupportPaletteSnoopAttributes (PciIoDevice, Operation);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+\r
+ //\r
+ // Enable operation is forbidden, so mask the bit in attributes\r
+ // so as to keep consistent with the actual Status\r
+ //\r
+ // Attributes &= (~EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);\r
+ //\r
+ //\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+\r
+ }\r
+ }\r
+\r
+ //\r
+ // It can be supported, so get ready to set the bit\r
+ //\r
+ Command |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+ }\r
+ }\r
+\r
+ if ((Attributes & EFI_PCI_IO_ATTRIBUTE_IO) != 0) {\r
+ Command |= EFI_PCI_COMMAND_IO_SPACE;\r
+ }\r
+\r
+ if ((Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) != 0) {\r
+ Command |= EFI_PCI_COMMAND_MEMORY_SPACE;\r
+ }\r
+\r
+ if ((Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) != 0) {\r
+ Command |= EFI_PCI_COMMAND_BUS_MASTER;\r
+ }\r
+ //\r
+ // The upstream bridge should be also set to revelant attribute\r
+ // expect for IO, Mem and BusMaster\r
+ //\r
+ UpStreamAttributes = Attributes &\r
+ (~(EFI_PCI_IO_ATTRIBUTE_IO |\r
+ EFI_PCI_IO_ATTRIBUTE_MEMORY |\r
+ EFI_PCI_IO_ATTRIBUTE_BUS_MASTER\r
+ )\r
+ );\r
+ UpStreamBridge = PciIoDevice->Parent;\r
+\r
+ if (Operation == EfiPciIoAttributeOperationEnable) {\r
+ //\r
+ // Enable relevant attributes to command register and bridge control register\r
+ //\r
+ Status = PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, Command);\r
+ if (BridgeControl != 0) {\r
+ Status = PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);\r
+ }\r
+\r
+ PciIoDevice->Attributes |= Attributes;\r
+\r
+ //\r
+ // Enable attributes of the upstream bridge\r
+ //\r
+ Status = UpStreamBridge->PciIo.Attributes (\r
+ &(UpStreamBridge->PciIo),\r
+ EfiPciIoAttributeOperationEnable,\r
+ UpStreamAttributes,\r
+ NULL\r
+ );\r
+ } else {\r
+\r
+ //\r
+ // Disable relevant attributes to command register and bridge control register\r
+ //\r
+ Status = PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, Command);\r
+ if (BridgeControl != 0) {\r
+ Status = PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);\r
+ }\r
+\r
+ PciIoDevice->Attributes &= (~Attributes);\r
+ Status = EFI_SUCCESS;\r
+\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Gets the attributes that this PCI controller supports setting on a BAR using\r
+ SetBarAttributes(), and retrieves the list of resource descriptors for a BAR.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for resource range. The legal range for this field is 0..5.\r
+ @param Supports A pointer to the mask of attributes that this PCI controller supports\r
+ setting for this BAR with SetBarAttributes().\r
+ @param Resources A pointer to the ACPI 2.0 resource descriptors that describe the current\r
+ configuration of this BAR of the PCI controller.\r
+\r
+ @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI\r
+ controller supports are returned in Supports. If Resources\r
+ is not NULL, then the ACPI 2.0 resource descriptors that the PCI\r
+ controller is currently using are returned in Resources.\r
+ @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.\r
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate\r
+ Resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetBarAttributes (\r
+ IN EFI_PCI_IO_PROTOCOL * This,\r
+ IN UINT8 BarIndex,\r
+ OUT UINT64 *Supports, OPTIONAL\r
+ OUT VOID **Resources OPTIONAL\r
+ )\r
+{\r
+\r
+ UINT8 *Configuration;\r
+ UINT8 NumConfig;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
+ EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;\r
+\r
+ NumConfig = 0;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ if (Supports == NULL && Resources == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BarIndex >= PCI_MAX_BAR) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // This driver does not support modifications to the WRITE_COMBINE or\r
+ // CACHED attributes for BAR ranges.\r
+ //\r
+ if (Supports != NULL) {\r
+ *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;\r
+ }\r
+\r
+ if (Resources != NULL) {\r
+\r
+ if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeUnknown) {\r
+ NumConfig = 1;\r
+ }\r
+\r
+ Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + 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
+\r
+ if (NumConfig == 1) {\r
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+\r
+ Ptr->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress;\r
+ Ptr->AddrLen = PciIoDevice->PciBar[BarIndex].Length;\r
+ Ptr->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment;\r
+\r
+ switch (PciIoDevice->PciBar[BarIndex].BarType) {\r
+ case PciBarTypeIo16:\r
+ case PciBarTypeIo32:\r
+ //\r
+ // Io\r
+ //\r
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
+ break;\r
+\r
+ case PciBarTypeMem32:\r
+ //\r
+ // Mem\r
+ //\r
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ //\r
+ // 32 bit\r
+ //\r
+ Ptr->AddrSpaceGranularity = 32;\r
+ break;\r
+\r
+ case PciBarTypePMem32:\r
+ //\r
+ // Mem\r
+ //\r
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ //\r
+ // prefechable\r
+ //\r
+ Ptr->SpecificFlag = 0x6;\r
+ //\r
+ // 32 bit\r
+ //\r
+ Ptr->AddrSpaceGranularity = 32;\r
+ break;\r
+\r
+ case PciBarTypeMem64:\r
+ //\r
+ // Mem\r
+ //\r
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ //\r
+ // 64 bit\r
+ //\r
+ Ptr->AddrSpaceGranularity = 64;\r
+ break;\r
+\r
+ case PciBarTypePMem64:\r
+ //\r
+ // Mem\r
+ //\r
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ //\r
+ // prefechable\r
+ //\r
+ Ptr->SpecificFlag = 0x6;\r
+ //\r
+ // 64 bit\r
+ //\r
+ Ptr->AddrSpaceGranularity = 64;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
+ }\r
+\r
+ //\r
+ // put the checksum\r
+ //\r
+ PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);\r
+ PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+ PtrEnd->Checksum = 0;\r
+\r
+ *Resources = Configuration;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Sets the attributes for a range of a BAR on a PCI controller.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Attributes The mask of attributes to set for the resource range specified by\r
+ BarIndex, Offset, and Length.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for resource range. The legal range for this field is 0..5.\r
+ @param Offset A pointer to the BAR relative base address of the resource range to be\r
+ modified by the attributes specified by Attributes.\r
+ @param Length A pointer to the length of the resource range to be modified by the\r
+ attributes specified by Attributes.\r
+\r
+ @retval EFI_SUCCESS The set of attributes specified by Attributes for the resource\r
+ range specified by BarIndex, Offset, and Length were\r
+ set on the PCI controller, and the actual resource range is returned\r
+ in Offset and Length.\r
+ @retval EFI_INVALID_PARAMETER Offset or Length is NULL.\r
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the attributes on the\r
+ resource range specified by BarIndex, Offset, and\r
+ Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoSetBarAttributes (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN UINT64 Attributes,\r
+ IN UINT8 BarIndex,\r
+ IN OUT UINT64 *Offset,\r
+ IN OUT UINT64 *Length\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ UINT64 NonRelativeOffset;\r
+ UINT64 Supports;\r
+\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+ //\r
+ // Make sure Offset and Length are not NULL\r
+ //\r
+ if (Offset == NULL || Length == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ //\r
+ // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.\r
+ // If Attributes is not 0, then return EFI_UNSUPPORTED.\r
+ //\r
+ Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;\r
+\r
+ if (Attributes != (Attributes & Supports)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ //\r
+ // Attributes must be supported. Make sure the BAR range describd by BarIndex, Offset, and\r
+ // Length are valid for this PCI device.\r
+ //\r
+ NonRelativeOffset = *Offset;\r
+ Status = PciIoVerifyBarAccess (\r
+ PciIoDevice,\r
+ BarIndex,\r
+ PciBarTypeMem,\r
+ EfiPciIoWidthUint8,\r
+ (UINT32) *Length,\r
+ &NonRelativeOffset\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Program parent bridge's attribute recurrently.\r
+\r
+ @param PciIoDevice Child Pci device instance\r
+ @param Operation The operation to perform on the attributes for this PCI controller.\r
+ @param Attributes The mask of attributes that are used for Set, Enable, and Disable\r
+ operations.\r
+\r
+ @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+ @retval EFI_UNSUPPORTED one or more of the bits set in\r
+ Attributes are not supported by this PCI controller or one of\r
+ its parent bridges when Operation is Set, Enable or Disable.\r
+\r
+**/\r
+EFI_STATUS\r
+UpStreamBridgesAttributes (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,\r
+ IN UINT64 Attributes\r
+ )\r
+{\r
+ PCI_IO_DEVICE *Parent;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+ Parent = PciIoDevice->Parent;\r
+\r
+ while (Parent != NULL && IS_PCI_BRIDGE (&Parent->Pci)) {\r
+\r
+ //\r
+ // Get the PciIo Protocol\r
+ //\r
+ PciIo = &Parent->PciIo;\r
+\r
+ PciIo->Attributes (PciIo, Operation, Attributes, NULL);\r
+\r
+ Parent = Parent->Parent;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Test whether two Pci devices has same parent bridge.\r
+\r
+ @param PciDevice1 The first pci device for testing.\r
+ @param PciDevice2 The second pci device for testing.\r
+\r
+ @retval TRUE Two Pci device has the same parent bridge.\r
+ @retval FALSE Two Pci device has not the same parent bridge.\r
+\r
+**/\r
+BOOLEAN\r
+PciDevicesOnTheSamePath (\r
+ IN PCI_IO_DEVICE *PciDevice1,\r
+ IN PCI_IO_DEVICE *PciDevice2\r
+ )\r
+{\r
+ BOOLEAN Existed1;\r
+ BOOLEAN Existed2;\r
+\r
+ if (PciDevice1->Parent == PciDevice2->Parent) {\r
+ return TRUE;\r
+ }\r
+\r
+ Existed1 = PciDeviceExisted (PciDevice1->Parent, PciDevice2);\r
+ Existed2 = PciDeviceExisted (PciDevice2->Parent, PciDevice1);\r
+\r
+ return (BOOLEAN) (Existed1 || Existed2);\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ EFI PCI IO protocol functions declaration 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
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_IO_PROTOCOL_H_\r
+#define _EFI_PCI_IO_PROTOCOL_H_\r
+\r
+/**\r
+ Initializes a PCI I/O Instance.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+\r
+**/\r
+VOID\r
+InitializePciIoInstance (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+/**\r
+ Verifies access to a PCI Base Address Register (BAR).\r
+\r
+ @param PciIoDevice Pci device instance.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for the memory or I/O operation to perform.\r
+ @param Type Operation type could be memory or I/O.\r
+ @param Width Signifies the width of the memory or I/O operations.\r
+ @param Count The number of memory or I/O operations to perform.\r
+ @param Offset The offset within the PCI configuration space for the PCI controller.\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid Width/BarIndex or Bar type.\r
+ @retval EFI_SUCCESS Successfully verified.\r
+\r
+**/\r
+EFI_STATUS\r
+PciIoVerifyBarAccess (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINT8 BarIndex,\r
+ IN PCI_BAR_TYPE Type,\r
+ IN IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN IN UINTN Count,\r
+ IN UINT64 *Offset\r
+ );\r
+\r
+/**\r
+ Verifies access to a PCI Configuration Header.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+ @param Width Signifies the width of the memory or I/O operations.\r
+ @param Count The number of memory or I/O operations to perform.\r
+ @param Offset The offset within the PCI configuration space for the PCI controller.\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid Width\r
+ @retval EFI_UNSUPPORTED Offset overflowed.\r
+ @retval EFI_SUCCESS Successfully verified.\r
+\r
+**/\r
+EFI_STATUS\r
+PciIoVerifyConfigAccess (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINTN Count,\r
+ IN UINT64 *Offset\r
+ );\r
+\r
+/**\r
+ Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is\r
+ satisfied or after a defined duration.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Width Signifies the width of the memory or I/O operations.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for the memory operation to perform.\r
+ @param Offset The offset within the selected BAR to start the memory operation.\r
+ @param Mask Mask used for the polling criteria.\r
+ @param Value The comparison value used for the polling exit criteria.\r
+ @param Delay The number of 100 ns units to poll.\r
+ @param Result Pointer to the last value read from the memory location.\r
+\r
+ @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.\r
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
+ @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of this PCI controller.\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 lack of resources.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollMem (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+ );\r
+\r
+/**\r
+ Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is\r
+ satisfied or after a defined duration.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Width Signifies the width of the memory or I/O operations.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for the memory operation to perform.\r
+ @param Offset The offset within the selected BAR to start the memory operation.\r
+ @param Mask Mask used for the polling criteria.\r
+ @param Value The comparison value used for the polling exit criteria.\r
+ @param Delay The number of 100 ns units to poll.\r
+ @param Result Pointer to the last value read from the memory location.\r
+\r
+ @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.\r
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
+ @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of this PCI controller.\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 lack of resources.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollIo (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+ );\r
+\r
+/**\r
+ Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Width Signifies the width of the memory or I/O operations.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for the memory or I/O operation to perform.\r
+ @param Offset The offset within the selected BAR to start the memory or I/O operation.\r
+ @param Count The number of memory or I/O operations to perform.\r
+ @param Buffer For read operations, the destination buffer to store the results. For write\r
+ operations, the source buffer to write data from.\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
+ @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
+ valid for the PCI BAR specified by BarIndex.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemRead (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ );\r
+\r
+/**\r
+ Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Width Signifies the width of the memory or I/O operations.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for the memory or I/O operation to perform.\r
+ @param Offset The offset within the selected BAR to start the memory or I/O operation.\r
+ @param Count The number of memory or I/O operations to perform.\r
+ @param Buffer For read operations, the destination buffer to store the results. For write\r
+ operations, the source buffer to write data from.\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
+ @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
+ valid for the PCI BAR specified by BarIndex.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemWrite (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ );\r
+\r
+/**\r
+ Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Width Signifies the width of the memory or I/O operations.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for the memory or I/O operation to perform.\r
+ @param Offset The offset within the selected BAR to start the memory or I/O operation.\r
+ @param Count The number of memory or I/O operations to perform.\r
+ @param Buffer For read operations, the destination buffer to store the results. For write\r
+ operations, the source buffer to write data from.\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
+ @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
+ valid for the PCI BAR specified by BarIndex.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoRead (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ );\r
+\r
+/**\r
+ Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Width Signifies the width of the memory or I/O operations.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for the memory or I/O operation to perform.\r
+ @param Offset The offset within the selected BAR to start the memory or I/O operation.\r
+ @param Count The number of memory or I/O operations to perform.\r
+ @param Buffer For read operations, the destination buffer to store the results. For write\r
+ operations, the source buffer to write data from.\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
+ @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
+ valid for the PCI BAR specified by BarIndex.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoWrite (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 BarIndex,\r
+ IN UINT64 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ );\r
+\r
+/**\r
+ Enable a PCI driver to access PCI controller registers in PCI configuration space.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Width Signifies the width of the memory operations.\r
+ @param Offset The offset within the PCI configuration space for the PCI controller.\r
+ @param Count The number of PCI configuration operations to perform.\r
+ @param Buffer For read operations, the destination buffer to store the results. For write\r
+ operations, the source buffer to write data from.\r
+\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
+ @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
+ valid for the PCI configuration header of the PCI controller.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigRead (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT32 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ );\r
+\r
+/**\r
+ Enable a PCI driver to access PCI controller registers in PCI configuration space.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Width Signifies the width of the memory operations.\r
+ @param Offset The offset within the PCI configuration space for the PCI controller.\r
+ @param Count The number of PCI configuration operations to perform.\r
+ @param Buffer For read operations, the destination buffer to store the results. For write\r
+ operations, the source buffer to write data from.\r
+\r
+\r
+ @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
+ @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
+ valid for the PCI configuration header of the PCI controller.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigWrite (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT32 Offset,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ );\r
+\r
+/**\r
+ Enables a PCI driver to copy one region of PCI memory space to another region of PCI\r
+ memory space.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Width Signifies the width of the memory operations.\r
+ @param DestBarIndex The BAR index in the standard PCI Configuration header to use as the\r
+ base address for the memory operation to perform.\r
+ @param DestOffset The destination offset within the BAR specified by DestBarIndex to\r
+ start the memory writes for the copy operation.\r
+ @param SrcBarIndex The BAR index in the standard PCI Configuration header to use as the\r
+ base address for the memory operation to perform.\r
+ @param SrcOffset The source offset within the BAR specified by SrcBarIndex to start\r
+ the memory reads for the copy operation.\r
+ @param Count The number of memory operations to perform. Bytes moved is Width\r
+ size * Count, starting at DestOffset and SrcOffset.\r
+\r
+ @retval EFI_SUCCESS The data was copied from one memory region to another memory region.\r
+ @retval EFI_UNSUPPORTED DestBarIndex not valid for this PCI controller.\r
+ @retval EFI_UNSUPPORTED SrcBarIndex not valid for this PCI controller.\r
+ @retval EFI_UNSUPPORTED The address range specified by DestOffset, Width, and Count\r
+ is not valid for the PCI BAR specified by DestBarIndex.\r
+ @retval EFI_UNSUPPORTED The address range specified by SrcOffset, Width, and Count is\r
+ not valid for the PCI BAR specified by SrcBarIndex.\r
+ @retval EFI_INVALID_PARAMETER Width is invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoCopyMem (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT8 DestBarIndex,\r
+ IN UINT64 DestOffset,\r
+ IN UINT8 SrcBarIndex,\r
+ IN UINT64 SrcOffset,\r
+ IN UINTN Count\r
+ );\r
+\r
+/**\r
+ Provides the PCI controller-specific addresses needed to access system memory.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Operation Indicates if the bus master is going to read or write to system memory.\r
+ @param HostAddress The system memory address to map to the PCI controller.\r
+ @param NumberOfBytes On input the number of bytes to map. On output the number of bytes\r
+ that were mapped.\r
+ @param DeviceAddress The resulting map address for the bus master PCI controller to use to\r
+ access the hosts HostAddress.\r
+ @param Mapping A resulting value to pass to Unmap().\r
+\r
+ @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.\r
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMap (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN EFI_PCI_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
+ Completes the Map() operation and releases any corresponding resources.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Mapping The mapping value returned from Map().\r
+\r
+ @retval EFI_SUCCESS The range was unmapped.\r
+ @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoUnmap (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN VOID *Mapping\r
+ );\r
+\r
+/**\r
+ Allocates pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer\r
+ mapping.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\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 range.\r
+\r
+ @retval EFI_SUCCESS The requested memory pages were allocated.\r
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are\r
+ MEMORY_WRITE_COMBINE and MEMORY_CACHED.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAllocateBuffer (\r
+ IN EFI_PCI_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
+ Frees memory that was allocated with AllocateBuffer().\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\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 Pages\r
+ was not allocated with AllocateBuffer().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFreeBuffer (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN UINTN Pages,\r
+ IN VOID *HostAddress\r
+ );\r
+\r
+/**\r
+ Flushes all PCI posted write transactions from a PCI host bridge to system memory.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+\r
+ @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host\r
+ bridge to system memory.\r
+ @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI\r
+ host bridge due to a hardware error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFlush (\r
+ IN EFI_PCI_IO_PROTOCOL *This\r
+ );\r
+\r
+/**\r
+ Retrieves this PCI controller's current PCI bus number, device number, and function number.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param SegmentNumber The PCI controller's current PCI segment number.\r
+ @param BusNumber The PCI controller's current PCI bus number.\r
+ @param DeviceNumber The PCI controller's current PCI device number.\r
+ @param FunctionNumber The PCI controller's current PCI function number.\r
+\r
+ @retval EFI_SUCCESS The PCI controller location was returned.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetLocation (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ OUT UINTN *Segment,\r
+ OUT UINTN *Bus,\r
+ OUT UINTN *Device,\r
+ OUT UINTN *Function\r
+ );\r
+\r
+/**\r
+ Check BAR type for PCI resource.\r
+\r
+ @param PciIoDevice PCI device instance.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for the memory or I/O operation to perform.\r
+ @param BarType Memory or I/O.\r
+\r
+ @retval TRUE Pci device's bar type is same with input BarType.\r
+ @retval TRUE Pci device's bar type is not same with input BarType.\r
+\r
+**/\r
+BOOLEAN\r
+CheckBarType (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINT8 BarIndex,\r
+ IN PCI_BAR_TYPE BarType\r
+ );\r
+\r
+/**\r
+ Set/Disable new attributes to a Root Bridge.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+ @param Attributes New attribute want to be set.\r
+ @param Operation Set or Disable.\r
+\r
+ @retval EFI_UNSUPPORTED If root bridge does not support change attribute.\r
+ @retval EFI_SUCCESS Successfully set new attributs.\r
+\r
+**/\r
+EFI_STATUS\r
+ModifyRootBridgeAttributes (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINT64 Attributes,\r
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation\r
+ );\r
+\r
+/**\r
+ Check whether this device can be enable/disable to snoop.\r
+\r
+ @param PciIoDevice Pci device instance.\r
+ @param Operation Enable/Disable.\r
+\r
+ @retval EFI_UNSUPPORTED Pci device is not GFX device or not support snoop.\r
+ @retval EFI_SUCCESS Snoop can be supported.\r
+\r
+**/\r
+EFI_STATUS\r
+SupportPaletteSnoopAttributes (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation\r
+ );\r
+\r
+/**\r
+ Performs an operation on the attributes that this PCI controller supports. The operations include\r
+ getting the set of supported attributes, retrieving the current attributes, setting the current\r
+ attributes, enabling attributes, and disabling attributes.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Operation The operation to perform on the attributes for this PCI controller.\r
+ @param Attributes The mask of attributes that are used for Set, Enable, and Disable\r
+ operations.\r
+ @param Result A pointer to the result mask of attributes that are returned for the Get\r
+ and Supported operations.\r
+\r
+ @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+ @retval EFI_UNSUPPORTED one or more of the bits set in\r
+ Attributes are not supported by this PCI controller or one of\r
+ its parent bridges when Operation is Set, Enable or Disable.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAttributes (\r
+ IN EFI_PCI_IO_PROTOCOL * This,\r
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,\r
+ IN UINT64 Attributes,\r
+ OUT UINT64 *Result OPTIONAL\r
+ );\r
+\r
+/**\r
+ Gets the attributes that this PCI controller supports setting on a BAR using\r
+ SetBarAttributes(), and retrieves the list of resource descriptors for a BAR.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for resource range. The legal range for this field is 0..5.\r
+ @param Supports A pointer to the mask of attributes that this PCI controller supports\r
+ setting for this BAR with SetBarAttributes().\r
+ @param Resources A pointer to the ACPI 2.0 resource descriptors that describe the current\r
+ configuration of this BAR of the PCI controller.\r
+\r
+ @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI\r
+ controller supports are returned in Supports. If Resources\r
+ is not NULL, then the ACPI 2.0 resource descriptors that the PCI\r
+ controller is currently using are returned in Resources.\r
+ @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.\r
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate\r
+ Resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetBarAttributes (\r
+ IN EFI_PCI_IO_PROTOCOL * This,\r
+ IN UINT8 BarIndex,\r
+ OUT UINT64 *Supports, OPTIONAL\r
+ OUT VOID **Resources OPTIONAL\r
+ );\r
+\r
+/**\r
+ Sets the attributes for a range of a BAR on a PCI controller.\r
+\r
+ @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+ @param Attributes The mask of attributes to set for the resource range specified by\r
+ BarIndex, Offset, and Length.\r
+ @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for resource range. The legal range for this field is 0..5.\r
+ @param Offset A pointer to the BAR relative base address of the resource range to be\r
+ modified by the attributes specified by Attributes.\r
+ @param Length A pointer to the length of the resource range to be modified by the\r
+ attributes specified by Attributes.\r
+\r
+ @retval EFI_SUCCESS The set of attributes specified by Attributes for the resource\r
+ range specified by BarIndex, Offset, and Length were\r
+ set on the PCI controller, and the actual resource range is returned\r
+ in Offset and Length.\r
+ @retval EFI_INVALID_PARAMETER Offset or Length is NULL.\r
+ @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the attributes on the\r
+ resource range specified by BarIndex, Offset, and\r
+ Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoSetBarAttributes (\r
+ IN EFI_PCI_IO_PROTOCOL *This,\r
+ IN UINT64 Attributes,\r
+ IN UINT8 BarIndex,\r
+ IN OUT UINT64 *Offset,\r
+ IN OUT UINT64 *Length\r
+ );\r
+\r
+/**\r
+ Program parent bridge's attribute recurrently.\r
+\r
+ @param PciIoDevice Child Pci device instance\r
+ @param Operation The operation to perform on the attributes for this PCI controller.\r
+ @param Attributes The mask of attributes that are used for Set, Enable, and Disable\r
+ operations.\r
+\r
+ @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+ @retval EFI_UNSUPPORTED one or more of the bits set in\r
+ Attributes are not supported by this PCI controller or one of\r
+ its parent bridges when Operation is Set, Enable or Disable.\r
+\r
+**/\r
+EFI_STATUS\r
+UpStreamBridgesAttributes (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,\r
+ IN UINT64 Attributes\r
+ );\r
+\r
+/**\r
+ Test whether two Pci devices has same parent bridge.\r
+\r
+ @param PciDevice1 The first pci device for testing.\r
+ @param PciDevice2 The second pci device for testing.\r
+\r
+ @retval TRUE Two Pci device has the same parent bridge.\r
+ @retval FALSE Two Pci device has not the same parent bridge.\r
+\r
+**/\r
+BOOLEAN\r
+PciDevicesOnTheSamePath (\r
+ IN PCI_IO_DEVICE *PciDevice1,\r
+ IN PCI_IO_DEVICE *PciDevice2\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Internal library implementation 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
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+\r
+/**\r
+ Retrieve the PCI Card device BAR information via PciIo interface.\r
+\r
+ @param PciIoDevice PCI Card device instance.\r
+\r
+**/\r
+VOID\r
+GetBackPcCardBar (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ UINT32 Address;\r
+\r
+ if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Read PciBar information from the bar register\r
+ //\r
+ if (!gFullEnumeration) {\r
+ Address = 0;\r
+ PciIoDevice->PciIo.Pci.Read (\r
+ &(PciIoDevice->PciIo),\r
+ EfiPciIoWidthUint32,\r
+ PCI_CARD_MEMORY_BASE_0,\r
+ 1,\r
+ &Address\r
+ );\r
+\r
+ (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress = (UINT64) (Address);\r
+ (PciIoDevice->PciBar)[P2C_MEM_1].Length = 0x2000000;\r
+ (PciIoDevice->PciBar)[P2C_MEM_1].BarType = PciBarTypeMem32;\r
+\r
+ Address = 0;\r
+ PciIoDevice->PciIo.Pci.Read (\r
+ &(PciIoDevice->PciIo),\r
+ EfiPciIoWidthUint32,\r
+ PCI_CARD_MEMORY_BASE_1,\r
+ 1,\r
+ &Address\r
+ );\r
+ (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress = (UINT64) (Address);\r
+ (PciIoDevice->PciBar)[P2C_MEM_2].Length = 0x2000000;\r
+ (PciIoDevice->PciBar)[P2C_MEM_2].BarType = PciBarTypePMem32;\r
+\r
+ Address = 0;\r
+ PciIoDevice->PciIo.Pci.Read (\r
+ &(PciIoDevice->PciIo),\r
+ EfiPciIoWidthUint32,\r
+ PCI_CARD_IO_BASE_0_LOWER,\r
+ 1,\r
+ &Address\r
+ );\r
+ (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64) (Address);\r
+ (PciIoDevice->PciBar)[P2C_IO_1].Length = 0x100;\r
+ (PciIoDevice->PciBar)[P2C_IO_1].BarType = PciBarTypeIo16;\r
+\r
+ Address = 0;\r
+ PciIoDevice->PciIo.Pci.Read (\r
+ &(PciIoDevice->PciIo),\r
+ EfiPciIoWidthUint32,\r
+ PCI_CARD_IO_BASE_1_LOWER,\r
+ 1,\r
+ &Address\r
+ );\r
+ (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64) (Address);\r
+ (PciIoDevice->PciBar)[P2C_IO_2].Length = 0x100;\r
+ (PciIoDevice->PciBar)[P2C_IO_2].BarType = PciBarTypeIo16;\r
+\r
+ }\r
+\r
+ if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+ GetResourcePaddingForHpb (PciIoDevice);\r
+ }\r
+}\r
+\r
+/**\r
+ Remove rejected pci device from specific root bridge\r
+ handle.\r
+\r
+ @param RootBridgeHandle Specific parent root bridge handle.\r
+ @param Bridge Bridge device instance.\r
+\r
+**/\r
+VOID\r
+RemoveRejectedPciDevices (\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ IN PCI_IO_DEVICE *Bridge\r
+ )\r
+{\r
+ PCI_IO_DEVICE *Temp;\r
+ LIST_ENTRY *CurrentLink;\r
+ LIST_ENTRY *LastLink;\r
+\r
+ if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+ return;\r
+ }\r
+\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+ while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
+\r
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+ if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
+ //\r
+ // Remove rejected devices recusively\r
+ //\r
+ RemoveRejectedPciDevices (RootBridgeHandle, Temp);\r
+ } else {\r
+ //\r
+ // Skip rejection for all PPBs, while detect rejection for others\r
+ //\r
+ if (IsPciDeviceRejected (Temp)) {\r
+\r
+ //\r
+ // For P2C, remove all devices on it\r
+ //\r
+ if (!IsListEmpty (&Temp->ChildList)) {\r
+ RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);\r
+ }\r
+\r
+ //\r
+ // Finally remove itself\r
+ //\r
+ LastLink = CurrentLink->BackLink;\r
+ RemoveEntryList (CurrentLink);\r
+ FreePciDevice (Temp);\r
+\r
+ CurrentLink = LastLink;\r
+ }\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+}\r
+\r
+/**\r
+ Submits the I/O and memory resource requirements for the specified PCI Host Bridge.\r
+\r
+ @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
+\r
+ @retval EFI_SUCCESS Successfully finished resource allocation.\r
+ @retval EFI_NOT_FOUND Cannot get root bridge instance.\r
+ @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources if no hot plug supported.\r
+ @retval other Some error occurred when allocating resources for the PCI Host Bridge.\r
+\r
+ @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeResourceAllocator (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
+ )\r
+{\r
+ PCI_IO_DEVICE *RootBridgeDev;\r
+ EFI_HANDLE RootBridgeHandle;\r
+ VOID *AcpiConfig;\r
+ EFI_STATUS Status;\r
+ UINT64 IoBase;\r
+ UINT64 Mem32Base;\r
+ UINT64 PMem32Base;\r
+ UINT64 Mem64Base;\r
+ UINT64 PMem64Base;\r
+ UINT64 IoResStatus;\r
+ UINT64 Mem32ResStatus;\r
+ UINT64 PMem32ResStatus;\r
+ UINT64 Mem64ResStatus;\r
+ UINT64 PMem64ResStatus;\r
+ UINT64 MaxOptionRomSize;\r
+ PCI_RESOURCE_NODE *IoBridge;\r
+ PCI_RESOURCE_NODE *Mem32Bridge;\r
+ PCI_RESOURCE_NODE *PMem32Bridge;\r
+ PCI_RESOURCE_NODE *Mem64Bridge;\r
+ PCI_RESOURCE_NODE *PMem64Bridge;\r
+ PCI_RESOURCE_NODE IoPool;\r
+ PCI_RESOURCE_NODE Mem32Pool;\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
+ while (TRUE) {\r
+ //\r
+ // Initialize resource pool\r
+ //\r
+ InitializeResourcePool (&IoPool, PciBarTypeIo16);\r
+ InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);\r
+ InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);\r
+ InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);\r
+ InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);\r
+\r
+ RootBridgeDev = NULL;\r
+ RootBridgeHandle = 0;\r
+\r
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
+ //\r
+ // Get Root Bridge Device by handle\r
+ //\r
+ RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
+\r
+ if (RootBridgeDev == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Create the entire system resource map from the information collected by\r
+ // enumerator. Several resource tree was created\r
+ //\r
+\r
+ IoBridge = CreateResourceNode (\r
+ RootBridgeDev,\r
+ 0,\r
+ 0xFFF,\r
+ 0,\r
+ PciBarTypeIo16,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ Mem32Bridge = CreateResourceNode (\r
+ RootBridgeDev,\r
+ 0,\r
+ 0xFFFFF,\r
+ 0,\r
+ PciBarTypeMem32,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ PMem32Bridge = CreateResourceNode (\r
+ RootBridgeDev,\r
+ 0,\r
+ 0xFFFFF,\r
+ 0,\r
+ PciBarTypePMem32,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ Mem64Bridge = CreateResourceNode (\r
+ RootBridgeDev,\r
+ 0,\r
+ 0xFFFFF,\r
+ 0,\r
+ PciBarTypeMem64,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ PMem64Bridge = CreateResourceNode (\r
+ RootBridgeDev,\r
+ 0,\r
+ 0xFFFFF,\r
+ 0,\r
+ PciBarTypePMem64,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ //\r
+ // Create resourcemap by going through all the devices subject to this root bridge\r
+ //\r
+ CreateResourceMap (\r
+ RootBridgeDev,\r
+ IoBridge,\r
+ Mem32Bridge,\r
+ PMem32Bridge,\r
+ Mem64Bridge,\r
+ PMem64Bridge\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
+ // submit the resource aperture to pci host bridge protocol\r
+ //\r
+ Status = ConstructAcpiResourceRequestor (\r
+ RootBridgeDev,\r
+ IoBridge,\r
+ Mem32Bridge,\r
+ PMem32Bridge,\r
+ Mem64Bridge,\r
+ PMem64Bridge,\r
+ &AcpiConfig\r
+ );\r
+\r
+ //\r
+ // Insert these resource nodes into the database\r
+ //\r
+ InsertResourceNode (&IoPool, IoBridge);\r
+ InsertResourceNode (&Mem32Pool, Mem32Bridge);\r
+ InsertResourceNode (&PMem32Pool, PMem32Bridge);\r
+ InsertResourceNode (&Mem64Pool, Mem64Bridge);\r
+ InsertResourceNode (&PMem64Pool, PMem64Bridge);\r
+\r
+ if (Status == EFI_SUCCESS) {\r
+ //\r
+ // Submit the resource requirement\r
+ //\r
+ Status = PciResAlloc->SubmitResources (\r
+ PciResAlloc,\r
+ RootBridgeDev->Handle,\r
+ AcpiConfig\r
+ );\r
+ }\r
+\r
+ //\r
+ // Free acpi resource node\r
+ //\r
+ if (AcpiConfig != NULL) {\r
+ FreePool (AcpiConfig);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Destroy all the resource tree\r
+ //\r
+ DestroyResourceTree (&IoPool);\r
+ DestroyResourceTree (&Mem32Pool);\r
+ DestroyResourceTree (&PMem32Pool);\r
+ DestroyResourceTree (&Mem64Pool);\r
+ DestroyResourceTree (&PMem64Pool);\r
+ return Status;\r
+ }\r
+ }\r
+ //\r
+ // End while, at least one Root Bridge should be found.\r
+ //\r
+ ASSERT (RootBridgeDev != NULL);\r
+\r
+ //\r
+ // Notify platform to start to program the resource\r
+ //\r
+ Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);\r
+ if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+ //\r
+ // If Hot Plug is not supported\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Allocation failed, then return\r
+ //\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Allocation succeed.\r
+ // Get host bridge handle for status report, and then skip the main while\r
+ //\r
+ HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
+\r
+ break;\r
+\r
+ } else {\r
+ //\r
+ // If Hot Plug is supported\r
+ //\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Allocation succeed, then continue the following\r
+ //\r
+ break;\r
+ }\r
+\r
+ //\r
+ // If the resource allocation is unsuccessful, free resources on bridge\r
+ //\r
+\r
+ RootBridgeDev = NULL;\r
+ RootBridgeHandle = 0;\r
+\r
+ IoResStatus = EFI_RESOURCE_SATISFIED;\r
+ Mem32ResStatus = EFI_RESOURCE_SATISFIED;\r
+ PMem32ResStatus = EFI_RESOURCE_SATISFIED;\r
+ Mem64ResStatus = EFI_RESOURCE_SATISFIED;\r
+ PMem64ResStatus = EFI_RESOURCE_SATISFIED;\r
+\r
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
+ //\r
+ // Get RootBridg Device by handle\r
+ //\r
+ RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
+ if (RootBridgeDev == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Get host bridge handle for status report\r
+ //\r
+ HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
+\r
+ //\r
+ // Get acpi resource node for all the resource types\r
+ //\r
+ AcpiConfig = NULL;\r
+\r
+ Status = PciResAlloc->GetProposedResources (\r
+ PciResAlloc,\r
+ RootBridgeDev->Handle,\r
+ &AcpiConfig\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (AcpiConfig != NULL) {\r
+ //\r
+ // Adjust resource allocation policy for each RB\r
+ //\r
+ GetResourceAllocationStatus (\r
+ AcpiConfig,\r
+ &IoResStatus,\r
+ &Mem32ResStatus,\r
+ &PMem32ResStatus,\r
+ &Mem64ResStatus,\r
+ &PMem64ResStatus\r
+ );\r
+ FreePool (AcpiConfig);\r
+ }\r
+ }\r
+ //\r
+ // End while\r
+ //\r
+\r
+ //\r
+ // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
+ //\r
+ //\r
+ // It is very difficult to follow the spec here\r
+ // Device path , Bar index can not be get here\r
+ //\r
+ ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));\r
+\r
+ REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
+ EFI_PROGRESS_CODE,\r
+ EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,\r
+ (VOID *) &AllocFailExtendedData,\r
+ sizeof (AllocFailExtendedData)\r
+ );\r
+\r
+ Status = PciHostBridgeAdjustAllocation (\r
+ &IoPool,\r
+ &Mem32Pool,\r
+ &PMem32Pool,\r
+ &Mem64Pool,\r
+ &PMem64Pool,\r
+ IoResStatus,\r
+ Mem32ResStatus,\r
+ PMem32ResStatus,\r
+ Mem64ResStatus,\r
+ PMem64ResStatus\r
+ );\r
+\r
+ //\r
+ // Destroy all the resource tree\r
+ //\r
+ DestroyResourceTree (&IoPool);\r
+ DestroyResourceTree (&Mem32Pool);\r
+ DestroyResourceTree (&PMem32Pool);\r
+ DestroyResourceTree (&Mem64Pool);\r
+ DestroyResourceTree (&PMem64Pool);\r
+\r
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ ReAllocate = TRUE;\r
+ }\r
+ }\r
+ //\r
+ // End main while\r
+ //\r
+\r
+ //\r
+ // Raise the EFI_IOB_PCI_RES_ALLOC status code\r
+ //\r
+ REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
+ EFI_PROGRESS_CODE,\r
+ EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,\r
+ (VOID *) &HandleExtendedData,\r
+ sizeof (HandleExtendedData)\r
+ );\r
+\r
+ //\r
+ // Notify pci bus driver starts to program the resource\r
+ //\r
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);\r
+\r
+ RootBridgeDev = NULL;\r
+\r
+ RootBridgeHandle = 0;\r
+\r
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
+ //\r
+ // Get RootBridg Device by handle\r
+ //\r
+ RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
+\r
+ if (RootBridgeDev == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Get acpi resource node for all the resource types\r
+ //\r
+ AcpiConfig = NULL;\r
+ Status = PciResAlloc->GetProposedResources (\r
+ PciResAlloc,\r
+ RootBridgeDev->Handle,\r
+ &AcpiConfig\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get the resource base by interpreting acpi resource node\r
+ //\r
+ //\r
+ GetResourceBase (\r
+ AcpiConfig,\r
+ &IoBase,\r
+ &Mem32Base,\r
+ &PMem32Base,\r
+ &Mem64Base,\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
+\r
+ //\r
+ // Program IO resources\r
+ //\r
+ ProgramResource (\r
+ IoBase,\r
+ IoBridge\r
+ );\r
+\r
+ //\r
+ // Program Mem32 resources\r
+ //\r
+ ProgramResource (\r
+ Mem32Base,\r
+ Mem32Bridge\r
+ );\r
+\r
+ //\r
+ // Program PMem32 resources\r
+ //\r
+ ProgramResource (\r
+ PMem32Base,\r
+ PMem32Bridge\r
+ );\r
+\r
+ //\r
+ // Program Mem64 resources\r
+ //\r
+ ProgramResource (\r
+ Mem64Base,\r
+ Mem64Bridge\r
+ );\r
+\r
+ //\r
+ // Program PMem64 resources\r
+ //\r
+ ProgramResource (\r
+ PMem64Base,\r
+ PMem64Bridge\r
+ );\r
+\r
+ FreePool (AcpiConfig);\r
+ }\r
+\r
+ //\r
+ // Destroy all the resource tree\r
+ //\r
+ DestroyResourceTree (&IoPool);\r
+ DestroyResourceTree (&Mem32Pool);\r
+ DestroyResourceTree (&PMem32Pool);\r
+ DestroyResourceTree (&Mem64Pool);\r
+ DestroyResourceTree (&PMem64Pool);\r
+\r
+ //\r
+ // Notify the resource allocation phase is to end\r
+ //\r
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Scan pci bus and assign bus number to the given PCI bus system.\r
+\r
+ @param Bridge Bridge device instance.\r
+ @param StartBusNumber start point.\r
+ @param SubBusNumber Point to sub bus number.\r
+ @param PaddedBusRange Customized bus number.\r
+\r
+ @retval EFI_SUCCESS Successfully scanned and assigned bus number.\r
+ @retval other Some error occurred when scanning pci bus.\r
+\r
+ @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
+\r
+**/\r
+EFI_STATUS\r
+PciScanBus (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN UINT8 StartBusNumber,\r
+ OUT UINT8 *SubBusNumber,\r
+ OUT UINT8 *PaddedBusRange\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_TYPE00 Pci;\r
+ UINT8 Device;\r
+ UINT8 Func;\r
+ UINT64 Address;\r
+ UINTN SecondBus;\r
+ UINT16 Register;\r
+ UINTN HpIndex;\r
+ PCI_IO_DEVICE *PciDevice;\r
+ EFI_EVENT Event;\r
+ EFI_HPC_STATE State;\r
+ UINT64 PciAddress;\r
+ EFI_HPC_PADDING_ATTRIBUTES Attributes;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
+ UINT16 BusRange;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+ BOOLEAN BusPadding;\r
+ UINT32 TempReservedBusNum;\r
+\r
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
+ SecondBus = 0;\r
+ Register = 0;\r
+ State = 0;\r
+ Attributes = (EFI_HPC_PADDING_ATTRIBUTES) 0;\r
+ BusRange = 0;\r
+ BusPadding = FALSE;\r
+ PciDevice = NULL;\r
+ PciAddress = 0;\r
+\r
+ for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
+ TempReservedBusNum = 0;\r
+ for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
+\r
+ //\r
+ // Check to see whether a pci device is present\r
+ //\r
+ Status = PciDevicePresent (\r
+ PciRootBridgeIo,\r
+ &Pci,\r
+ StartBusNumber,\r
+ Device,\r
+ Func\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ if (Func == 0) {\r
+ //\r
+ // Skip sub functions, this is not a multi function device\r
+ //\r
+ Func = PCI_MAX_FUNC;\r
+ }\r
+\r
+ continue;\r
+ }\r
+\r
+ DEBUG((EFI_D_INFO, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber, Device, Func ));\r
+\r
+ if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+ //\r
+ // Get the PCI device information\r
+ //\r
+ Status = PciSearchDevice (\r
+ Bridge,\r
+ &Pci,\r
+ StartBusNumber,\r
+ Device,\r
+ Func,\r
+ &PciDevice\r
+ );\r
+\r
+ ASSERT (!EFI_ERROR (Status));\r
+\r
+ PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);\r
+\r
+ if (!IS_PCI_BRIDGE (&Pci)) {\r
+ //\r
+ // PCI bridges will be called later\r
+ // Here just need for PCI device or PCI to cardbus controller\r
+ // EfiPciBeforeChildBusEnumeration for PCI Device Node\r
+ //\r
+ PreprocessController (\r
+ PciDevice,\r
+ PciDevice->BusNumber,\r
+ PciDevice->DeviceNumber,\r
+ PciDevice->FunctionNumber,\r
+ EfiPciBeforeChildBusEnumeration\r
+ );\r
+ }\r
+\r
+ //\r
+ // For Pci Hotplug controller devcie only\r
+ //\r
+ if (gPciHotPlugInit != NULL) {\r
+ //\r
+ // Check if it is a Hotplug PCI controller\r
+ //\r
+ if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {\r
+\r
+ if (!gPciRootHpcData[HpIndex].Initialized) {\r
+\r
+ Status = CreateEventForHpc (HpIndex, &Event);\r
+\r
+ ASSERT (!EFI_ERROR (Status));\r
+\r
+ Status = gPciHotPlugInit->InitializeRootHpc (\r
+ gPciHotPlugInit,\r
+ gPciRootHpcPool[HpIndex].HpcDevicePath,\r
+ PciAddress,\r
+ Event,\r
+ &State\r
+ );\r
+\r
+ PreprocessController (\r
+ PciDevice,\r
+ PciDevice->BusNumber,\r
+ PciDevice->DeviceNumber,\r
+ PciDevice->FunctionNumber,\r
+ EfiPciBeforeChildBusEnumeration\r
+ );\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {\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
+ //\r
+ // If Hot Plug is supported,\r
+ // Get the bridge information\r
+ //\r
+ BusPadding = FALSE;\r
+ if (gPciHotPlugInit != NULL) {\r
+\r
+ if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {\r
+\r
+ //\r
+ // If it is initialized, get the padded bus range\r
+ //\r
+ Status = gPciHotPlugInit->GetResourcePadding (\r
+ gPciHotPlugInit,\r
+ gPciRootHpcPool[HpIndex].HpbDevicePath,\r
+ PciAddress,\r
+ &State,\r
+ (VOID **) &Descriptors,\r
+ &Attributes\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ BusRange = 0;\r
+ Status = PciGetBusRange (\r
+ &Descriptors,\r
+ NULL,\r
+ NULL,\r
+ &BusRange\r
+ );\r
+\r
+ FreePool (Descriptors);\r
+\r
+ if (EFI_ERROR (Status)) {\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
+ }\r
+\r
+ (*SubBusNumber)++;\r
+ SecondBus = *SubBusNumber;\r
+\r
+ Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);\r
+\r
+ Status = PciRootBridgeIo->Pci.Write (\r
+ PciRootBridgeIo,\r
+ EfiPciWidthUint16,\r
+ Address,\r
+ 1,\r
+ &Register\r
+ );\r
+\r
+\r
+ //\r
+ // If it is PPB, resursively search down this bridge\r
+ //\r
+ if (IS_PCI_BRIDGE (&Pci)) {\r
+\r
+ //\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
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
+ Status = PciRootBridgeIo->Pci.Write (\r
+ PciRootBridgeIo,\r
+ EfiPciWidthUint8,\r
+ Address,\r
+ 1,\r
+ &Register\r
+ );\r
+\r
+ //\r
+ // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige\r
+ //\r
+ PreprocessController (\r
+ PciDevice,\r
+ PciDevice->BusNumber,\r
+ PciDevice->DeviceNumber,\r
+ PciDevice->FunctionNumber,\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
+ SubBusNumber,\r
+ PaddedBusRange\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport) && BusPadding) {\r
+ //\r
+ // Ensure the device is enabled and initialized\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
+ } else {\r
+ *SubBusNumber = (UINT8) ((UINT8) (BusRange) +*SubBusNumber);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Set the current maximum bus number under the PPB\r
+ //\r
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
+\r
+ Status = PciRootBridgeIo->Pci.Write (\r
+ PciRootBridgeIo,\r
+ EfiPciWidthUint8,\r
+ Address,\r
+ 1,\r
+ SubBusNumber\r
+ );\r
+ } else {\r
+ //\r
+ // It is device. Check PCI IOV for Bus reservation\r
+ //\r
+ if (PciDevice == NULL) {\r
+ //\r
+ // No PciDevice found, conitue Scan\r
+ //\r
+ continue;\r
+ }\r
+ //\r
+ // Go through each function, just reserve the MAX ReservedBusNum for one device\r
+ //\r
+ if ((PciDevice->AriCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {\r
+\r
+ if (TempReservedBusNum < PciDevice->ReservedBusNum) {\r
+\r
+ (*SubBusNumber) = (UINT8)((*SubBusNumber) + PciDevice->ReservedBusNum - TempReservedBusNum);\r
+ TempReservedBusNum = PciDevice->ReservedBusNum;\r
+\r
+ if (Func == 0) {\r
+ DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber));\r
+ } else {\r
+ DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber));\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
+\r
+ //\r
+ // Skip sub functions, this is not a multi function device\r
+ //\r
+\r
+ Func = PCI_MAX_FUNC;\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Process Option Rom on the specified root bridge.\r
+\r
+ @param Bridge Pci root bridge device instance.\r
+\r
+ @retval EFI_SUCCESS Success process.\r
+ @retval other Some error occurred when processing Option Rom on the root bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciRootBridgeP2CProcess (\r
+ IN PCI_IO_DEVICE *Bridge\r
+ )\r
+{\r
+ LIST_ENTRY *CurrentLink;\r
+ PCI_IO_DEVICE *Temp;\r
+ EFI_HPC_STATE State;\r
+ UINT64 PciAddress;\r
+ EFI_STATUS Status;\r
+\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+ while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
+\r
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+ if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
+\r
+ if (gPciHotPlugInit != NULL && Temp->Allocated && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+\r
+ //\r
+ // Raise the EFI_IOB_PCI_HPC_INIT status code\r
+ //\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_HPC_INIT,\r
+ Temp->DevicePath\r
+ );\r
+\r
+ PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);\r
+ Status = gPciHotPlugInit->InitializeRootHpc (\r
+ gPciHotPlugInit,\r
+ Temp->DevicePath,\r
+ PciAddress,\r
+ NULL,\r
+ &State\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = PciBridgeEnumerator (Temp);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ continue;\r
+\r
+ }\r
+ }\r
+\r
+ if (!IsListEmpty (&Temp->ChildList)) {\r
+ Status = PciRootBridgeP2CProcess (Temp);\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Process Option Rom on the specified host bridge.\r
+\r
+ @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
+\r
+ @retval EFI_SUCCESS Success process.\r
+ @retval EFI_NOT_FOUND Can not find the root bridge instance.\r
+ @retval other Some error occurred when processing Option Rom on the host bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeP2CProcess (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
+ )\r
+{\r
+ EFI_HANDLE RootBridgeHandle;\r
+ PCI_IO_DEVICE *RootBridgeDev;\r
+ EFI_STATUS Status;\r
+\r
+ if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ RootBridgeHandle = NULL;\r
+\r
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
+\r
+ //\r
+ // Get RootBridg Device by handle\r
+ //\r
+ RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
+\r
+ if (RootBridgeDev == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Status = PciRootBridgeP2CProcess (RootBridgeDev);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function is used to enumerate the entire host bridge\r
+ in a given platform.\r
+\r
+ @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.\r
+\r
+ @retval EFI_SUCCESS Successfully enumerated the host bridge.\r
+ @retval EFI_OUT_OF_RESOURCES No enough memory available.\r
+ @retval other Some error occurred when enumerating the host bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeEnumerator (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
+ )\r
+{\r
+ EFI_HANDLE RootBridgeHandle;\r
+ PCI_IO_DEVICE *RootBridgeDev;\r
+ EFI_STATUS Status;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+ UINT16 MinBus;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
+ UINT8 StartBusNumber;\r
+ LIST_ENTRY RootBridgeList;\r
+ LIST_ENTRY *Link;\r
+\r
+ if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+ InitializeHotPlugSupport ();\r
+ }\r
+\r
+ InitializeListHead (&RootBridgeList);\r
+\r
+ //\r
+ // Notify the bus allocation phase is about to start\r
+ //\r
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
+\r
+ DEBUG((EFI_D_INFO, "PCI Bus First Scanning\n"));\r
+ RootBridgeHandle = NULL;\r
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
+\r
+ //\r
+ // if a root bridge instance is found, create root bridge device for it\r
+ //\r
+\r
+ RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
+\r
+ if (RootBridgeDev == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Enumerate all the buses under this root bridge\r
+ //\r
+ Status = PciRootBridgeEnumerator (\r
+ PciResAlloc,\r
+ RootBridgeDev\r
+ );\r
+\r
+ if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+ InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));\r
+ } else {\r
+ DestroyRootBridge (RootBridgeDev);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Notify the bus allocation phase is finished for the first time\r
+ //\r
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
+\r
+ if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+ //\r
+ // Reset all assigned PCI bus number in all PPB\r
+ //\r
+ RootBridgeHandle = NULL;\r
+ Link = GetFirstNode (&RootBridgeList);\r
+ while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&\r
+ (!IsNull (&RootBridgeList, Link))) {\r
+ RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);\r
+ //\r
+ // Get the Bus information\r
+ //\r
+ Status = PciResAlloc->StartBusEnumeration (\r
+ PciResAlloc,\r
+ RootBridgeHandle,\r
+ (VOID **) &Configuration\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get the bus number to start with\r
+ //\r
+ StartBusNumber = (UINT8) (Configuration->AddrRangeMin);\r
+\r
+ ResetAllPpbBusNumber (\r
+ RootBridgeDev,\r
+ StartBusNumber\r
+ );\r
+\r
+ FreePool (Configuration);\r
+ Link = GetNextNode (&RootBridgeList, Link);\r
+ DestroyRootBridge (RootBridgeDev);\r
+ }\r
+\r
+ //\r
+ // Wait for all HPC initialized\r
+ //\r
+ Status = AllRootHPCInitialized (STALL_1_SECOND * 15);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Notify the bus allocation phase is about to start for the 2nd time\r
+ //\r
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
+\r
+ DEBUG((EFI_D_INFO, "PCI Bus Second Scanning\n"));\r
+ RootBridgeHandle = NULL;\r
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
+\r
+ //\r
+ // if a root bridge instance is found, create root bridge device for it\r
+ //\r
+ RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
+\r
+ if (RootBridgeDev == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Enumerate all the buses under this root bridge\r
+ //\r
+ Status = PciRootBridgeEnumerator (\r
+ PciResAlloc,\r
+ RootBridgeDev\r
+ );\r
+\r
+ DestroyRootBridge (RootBridgeDev);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Notify the bus allocation phase is to end for the 2nd time\r
+ //\r
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
+ }\r
+\r
+ //\r
+ // Notify the resource allocation phase is to start\r
+ //\r
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);\r
+\r
+ RootBridgeHandle = NULL;\r
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
+\r
+ //\r
+ // if a root bridge instance is found, create root bridge device for it\r
+ //\r
+ RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
+\r
+ if (RootBridgeDev == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = StartManagingRootBridge (RootBridgeDev);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;\r
+ Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Determine root bridge attribute by calling interface of Pcihostbridge\r
+ // protocol\r
+ //\r
+ DetermineRootBridgeAttributes (\r
+ PciResAlloc,\r
+ RootBridgeDev\r
+ );\r
+\r
+ //\r
+ // Collect all the resource information under this root bridge\r
+ // A database that records all the information about pci device subject to this\r
+ // root bridge will then be created\r
+ //\r
+ Status = PciPciDeviceInfoCollector (\r
+ RootBridgeDev,\r
+ (UINT8) MinBus\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ InsertRootBridge (RootBridgeDev);\r
+\r
+ //\r
+ // Record the hostbridge handle\r
+ //\r
+ AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+ Internal library declaration 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
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_LIB_H_\r
+#define _EFI_PCI_LIB_H_\r
+\r
+\r
+typedef struct {\r
+ EFI_HANDLE Handle;\r
+} EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD;\r
+\r
+typedef struct {\r
+ UINT32 Bar;\r
+ UINT16 DevicePathSize;\r
+ UINT16 ReqResSize;\r
+ UINT16 AllocResSize;\r
+ UINT8 *DevicePath;\r
+ UINT8 *ReqRes;\r
+ UINT8 *AllocRes;\r
+} EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD;\r
+\r
+\r
+/**\r
+ Retrieve the PCI Card device BAR information via PciIo interface.\r
+\r
+ @param PciIoDevice PCI Card device instance.\r
+\r
+**/\r
+VOID\r
+GetBackPcCardBar (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+/**\r
+ Remove rejected pci device from specific root bridge\r
+ handle.\r
+\r
+ @param RootBridgeHandle Specific parent root bridge handle.\r
+ @param Bridge Bridge device instance.\r
+\r
+**/\r
+VOID\r
+RemoveRejectedPciDevices (\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ IN PCI_IO_DEVICE *Bridge\r
+ );\r
+\r
+/**\r
+ Submits the I/O and memory resource requirements for the specified PCI Host Bridge.\r
+\r
+ @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
+\r
+ @retval EFI_SUCCESS Successfully finished resource allocation.\r
+ @retval EFI_NOT_FOUND Cannot get root bridge instance.\r
+ @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources if no hot plug supported.\r
+ @retval other Some error occurred when allocating resources for the PCI Host Bridge.\r
+\r
+ @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeResourceAllocator (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
+ );\r
+\r
+/**\r
+ Scan pci bus and assign bus number to the given PCI bus system.\r
+\r
+ @param Bridge Bridge device instance.\r
+ @param StartBusNumber start point.\r
+ @param SubBusNumber Point to sub bus number.\r
+ @param PaddedBusRange Customized bus number.\r
+\r
+ @retval EFI_SUCCESS Successfully scanned and assigned bus number.\r
+ @retval other Some error occurred when scanning pci bus.\r
+\r
+ @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
+\r
+**/\r
+EFI_STATUS\r
+PciScanBus (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN UINT8 StartBusNumber,\r
+ OUT UINT8 *SubBusNumber,\r
+ OUT UINT8 *PaddedBusRange\r
+ );\r
+\r
+/**\r
+ Process Option Rom on the specified root bridge.\r
+\r
+ @param Bridge Pci root bridge device instance.\r
+\r
+ @retval EFI_SUCCESS Success process.\r
+ @retval other Some error occurred when processing Option Rom on the root bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciRootBridgeP2CProcess (\r
+ IN PCI_IO_DEVICE *Bridge\r
+ );\r
+\r
+/**\r
+ Process Option Rom on the specified host bridge.\r
+\r
+ @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
+\r
+ @retval EFI_SUCCESS Success process.\r
+ @retval EFI_NOT_FOUND Can not find the root bridge instance.\r
+ @retval other Some error occurred when processing Option Rom on the host bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeP2CProcess (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
+ );\r
+\r
+/**\r
+ This function is used to enumerate the entire host bridge\r
+ in a given platform.\r
+\r
+ @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.\r
+\r
+ @retval EFI_SUCCESS Successfully enumerated the host bridge.\r
+ @retval EFI_OUT_OF_RESOURCES No enough memory available.\r
+ @retval other Some error occurred when enumerating the host bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeEnumerator (\r
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ PCI Rom supporting funtions implementation 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
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+/**\r
+ Load the EFI Image from Option ROM\r
+\r
+ @param PciIoDevice PCI IO device instance.\r
+ @param FilePath The file path of the EFI Image\r
+ @param BufferSize On input the size of Buffer in bytes. On output with a return\r
+ code of EFI_SUCCESS, the amount of data transferred to Buffer.\r
+ On output with a return code of EFI_BUFFER_TOO_SMALL,\r
+ the size of Buffer required to retrieve the requested file.\r
+ @param Buffer The memory buffer to transfer the file to. If Buffer is NULL,\r
+ then no the size of the requested file is returned in BufferSize.\r
+\r
+ @retval EFI_SUCCESS The file was loaded.\r
+ @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or\r
+ BufferSize is NULL.\r
+ @retval EFI_NOT_FOUND Not found PCI Option Rom on PCI device.\r
+ @retval EFI_DEVICE_ERROR Failed to decompress PCI Option Rom image.\r
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.\r
+ BufferSize has been updated with the size needed to complete the request.\r
+**/\r
+EFI_STATUS\r
+LocalLoadFile2 (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+ IN OUT UINTN *BufferSize,\r
+ IN VOID *Buffer OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *EfiOpRomImageNode;\r
+ EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;\r
+ PCI_DATA_STRUCTURE *Pcir;\r
+ UINT32 ImageSize;\r
+ UINT8 *ImageBuffer;\r
+ UINT32 ImageLength;\r
+ UINT32 DestinationSize;\r
+ UINT32 ScratchSize;\r
+ VOID *Scratch;\r
+ EFI_DECOMPRESS_PROTOCOL *Decompress;\r
+\r
+ EfiOpRomImageNode = (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *) FilePath;\r
+ if ((EfiOpRomImageNode == NULL) ||\r
+ (DevicePathType (FilePath) != MEDIA_DEVICE_PATH) ||\r
+ (DevicePathSubType (FilePath) != MEDIA_RELATIVE_OFFSET_RANGE_DP) ||\r
+ (DevicePathNodeLength (FilePath) != sizeof (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH)) ||\r
+ (!IsDevicePathEnd (NextDevicePathNode (FilePath))) ||\r
+ (EfiOpRomImageNode->StartingOffset > EfiOpRomImageNode->EndingOffset) ||\r
+ (EfiOpRomImageNode->EndingOffset >= PciIoDevice->RomSize) ||\r
+ (BufferSize == NULL)\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (\r
+ (UINT8 *) PciIoDevice->PciIo.RomImage + EfiOpRomImageNode->StartingOffset\r
+ );\r
+ if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+\r
+ Pcir = (PCI_DATA_STRUCTURE *) ((UINT8 *) EfiRomHeader + EfiRomHeader->PcirOffset);\r
+\r
+\r
+ if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&\r
+ (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&\r
+ ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||\r
+ (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) &&\r
+ (EfiRomHeader->CompressionType <= EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED)\r
+ ) {\r
+\r
+ ImageSize = (UINT32) EfiRomHeader->InitializationSize * 512;\r
+ ImageBuffer = (UINT8 *) EfiRomHeader + EfiRomHeader->EfiImageHeaderOffset;\r
+ ImageLength = ImageSize - EfiRomHeader->EfiImageHeaderOffset;\r
+\r
+ if (EfiRomHeader->CompressionType != EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
+ //\r
+ // Uncompressed: Copy the EFI Image directly to user's buffer\r
+ //\r
+ if (Buffer == NULL || *BufferSize < ImageLength) {\r
+ *BufferSize = ImageLength;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *BufferSize = ImageLength;\r
+ CopyMem (Buffer, ImageBuffer, ImageLength);\r
+ return EFI_SUCCESS;\r
+\r
+ } else {\r
+ //\r
+ // Compressed: Uncompress before copying\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ Status = Decompress->GetInfo (\r
+ Decompress,\r
+ ImageBuffer,\r
+ ImageLength,\r
+ &DestinationSize,\r
+ &ScratchSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ if (Buffer == NULL || *BufferSize < DestinationSize) {\r
+ *BufferSize = DestinationSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *BufferSize = DestinationSize;\r
+ Scratch = AllocatePool (ScratchSize);\r
+ if (Scratch == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Status = Decompress->Decompress (\r
+ Decompress,\r
+ ImageBuffer,\r
+ ImageLength,\r
+ Buffer,\r
+ DestinationSize,\r
+ Scratch,\r
+ ScratchSize\r
+ );\r
+ FreePool (Scratch);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ Initialize a PCI LoadFile2 instance.\r
+\r
+ @param PciIoDevice PCI IO Device.\r
+\r
+**/\r
+VOID\r
+InitializePciLoadFile2 (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ PciIoDevice->LoadFile2.LoadFile = LoadFile2;\r
+}\r
+\r
+/**\r
+ Causes the driver to load a specified file.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param FilePath The device specific path of the file to load.\r
+ @param BootPolicy Should always be FALSE.\r
+ @param BufferSize On input the size of Buffer in bytes. On output with a return\r
+ code of EFI_SUCCESS, the amount of data transferred to Buffer.\r
+ On output with a return code of EFI_BUFFER_TOO_SMALL,\r
+ the size of Buffer required to retrieve the requested file.\r
+ @param Buffer The memory buffer to transfer the file to. If Buffer is NULL,\r
+ then no the size of the requested file is returned in BufferSize.\r
+\r
+ @retval EFI_SUCCESS The file was loaded.\r
+ @retval EFI_UNSUPPORTED BootPolicy is TRUE.\r
+ @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or\r
+ BufferSize is NULL.\r
+ @retval EFI_NOT_FOUND Not found PCI Option Rom on PCI device.\r
+ @retval EFI_DEVICE_ERROR Failed to decompress PCI Option Rom image.\r
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.\r
+ BufferSize has been updated with the size needed to complete the request.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LoadFile2 (\r
+ IN EFI_LOAD_FILE2_PROTOCOL *This,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+ IN BOOLEAN BootPolicy,\r
+ IN OUT UINTN *BufferSize,\r
+ IN VOID *Buffer OPTIONAL\r
+ )\r
+{\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+\r
+ if (BootPolicy) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_LOAD_FILE2_THIS (This);\r
+\r
+ return LocalLoadFile2 (\r
+ PciIoDevice,\r
+ FilePath,\r
+ BufferSize,\r
+ Buffer\r
+ );\r
+}\r
+\r
+/**\r
+ Get Pci device's oprom information.\r
+\r
+ @param PciIoDevice Input Pci device instance.\r
+ Output Pci device instance with updated OptionRom size.\r
+\r
+ @retval EFI_NOT_FOUND Pci device has not Option Rom.\r
+ @retval EFI_SUCCESS Pci device has Option Rom.\r
+\r
+**/\r
+EFI_STATUS\r
+GetOpRomInfo (\r
+ IN OUT PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ UINT8 RomBarIndex;\r
+ UINT32 AllOnes;\r
+ UINT64 Address;\r
+ EFI_STATUS Status;\r
+ UINT8 Bus;\r
+ UINT8 Device;\r
+ UINT8 Function;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+\r
+ Bus = PciIoDevice->BusNumber;\r
+ Device = PciIoDevice->DeviceNumber;\r
+ Function = PciIoDevice->FunctionNumber;\r
+\r
+ PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;\r
+\r
+ //\r
+ // Offset is 0x30 if is not ppb\r
+ //\r
+\r
+ //\r
+ // 0x30\r
+ //\r
+ RomBarIndex = PCI_EXPANSION_ROM_BASE;\r
+\r
+ if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
+ //\r
+ // If is ppb, 0x38\r
+ //\r
+ RomBarIndex = PCI_BRIDGE_ROMBAR;\r
+ }\r
+ //\r
+ // The bit0 is 0 to prevent the enabling of the Rom address decoder\r
+ //\r
+ AllOnes = 0xfffffffe;\r
+ Address = EFI_PCI_ADDRESS (Bus, Device, Function, RomBarIndex);\r
+\r
+ Status = PciRootBridgeIo->Pci.Write (\r
+ PciRootBridgeIo,\r
+ EfiPciWidthUint32,\r
+ Address,\r
+ 1,\r
+ &AllOnes\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Read back\r
+ //\r
+ Status = PciRootBridgeIo->Pci.Read(\r
+ PciRootBridgeIo,\r
+ EfiPciWidthUint32,\r
+ Address,\r
+ 1,\r
+ &AllOnes\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Bits [1, 10] are reserved\r
+ //\r
+ AllOnes &= 0xFFFFF800;\r
+ if ((AllOnes == 0) || (AllOnes == 0xFFFFF800)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ PciIoDevice->RomSize = (UINT64) ((~AllOnes) + 1);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Check if the RomImage contains EFI Images.\r
+\r
+ @param RomImage The ROM address of Image for check.\r
+ @param RomSize Size of ROM for check.\r
+\r
+ @retval TRUE ROM contain EFI Image.\r
+ @retval FALSE ROM not contain EFI Image.\r
+\r
+**/\r
+BOOLEAN\r
+ContainEfiImage (\r
+ IN VOID *RomImage,\r
+ IN UINT64 RomSize\r
+ )\r
+{\r
+ PCI_EXPANSION_ROM_HEADER *RomHeader;\r
+ PCI_DATA_STRUCTURE *RomPcir;\r
+ BOOLEAN FirstCheck;\r
+\r
+ FirstCheck = TRUE;\r
+ RomHeader = RomImage;\r
+\r
+ while ((UINT8 *) RomHeader < (UINT8 *) RomImage + RomSize) {\r
+ if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
+ if (FirstCheck) {\r
+ return FALSE;\r
+ } else {\r
+ RomHeader = (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) RomHeader + 512);\r
+ continue;\r
+ }\r
+ }\r
+\r
+ FirstCheck = FALSE;\r
+ RomPcir = (PCI_DATA_STRUCTURE *) ((UINT8 *) RomHeader + RomHeader->PcirOffset);\r
+\r
+ if (RomPcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) {\r
+ return TRUE;\r
+ }\r
+\r
+ RomHeader = (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) RomHeader + RomPcir->Length * 512);\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+\r
+/**\r
+ Load Option Rom image for specified PCI device.\r
+\r
+ @param PciDevice Pci device instance.\r
+ @param RomBase Base address of Option Rom.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES No enough memory to hold image.\r
+ @retval EFI_SUCESS Successfully loaded Option Rom.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadOpRomImage (\r
+ IN PCI_IO_DEVICE *PciDevice,\r
+ IN UINT64 RomBase\r
+ )\r
+{\r
+ UINT8 RomBarIndex;\r
+ UINT8 Indicator;\r
+ UINT16 OffsetPcir;\r
+ UINT32 RomBarOffset;\r
+ UINT32 RomBar;\r
+ EFI_STATUS RetStatus;\r
+ BOOLEAN FirstCheck;\r
+ UINT8 *Image;\r
+ PCI_EXPANSION_ROM_HEADER *RomHeader;\r
+ PCI_DATA_STRUCTURE *RomPcir;\r
+ UINT64 RomSize;\r
+ UINT64 RomImageSize;\r
+ UINT8 *RomInMemory;\r
+ UINT8 CodeType;\r
+\r
+ RomSize = PciDevice->RomSize;\r
+\r
+ Indicator = 0;\r
+ RomImageSize = 0;\r
+ RomInMemory = NULL;\r
+ CodeType = 0xFF;\r
+\r
+ //\r
+ // Get the RomBarIndex\r
+ //\r
+\r
+ //\r
+ // 0x30\r
+ //\r
+ RomBarIndex = PCI_EXPANSION_ROM_BASE;\r
+ if (IS_PCI_BRIDGE (&(PciDevice->Pci))) {\r
+ //\r
+ // if is ppb\r
+ //\r
+\r
+ //\r
+ // 0x38\r
+ //\r
+ RomBarIndex = PCI_BRIDGE_ROMBAR;\r
+ }\r
+ //\r
+ // Allocate memory for Rom header and PCIR\r
+ //\r
+ RomHeader = AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER));\r
+ if (RomHeader == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE));\r
+ if (RomPcir == NULL) {\r
+ FreePool (RomHeader);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ RomBar = (UINT32) RomBase;\r
+\r
+ //\r
+ // Enable RomBar\r
+ //\r
+ RomDecode (PciDevice, RomBarIndex, RomBar, TRUE);\r
+\r
+ RomBarOffset = RomBar;\r
+ RetStatus = EFI_NOT_FOUND;\r
+ FirstCheck = TRUE;\r
+\r
+ do {\r
+ PciDevice->PciRootBridgeIo->Mem.Read (\r
+ PciDevice->PciRootBridgeIo,\r
+ EfiPciWidthUint8,\r
+ RomBarOffset,\r
+ sizeof (PCI_EXPANSION_ROM_HEADER),\r
+ (UINT8 *) RomHeader\r
+ );\r
+\r
+ if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
+ RomBarOffset = RomBarOffset + 512;\r
+ if (FirstCheck) {\r
+ break;\r
+ } else {\r
+ RomImageSize = RomImageSize + 512;\r
+ continue;\r
+ }\r
+ }\r
+\r
+ FirstCheck = FALSE;\r
+ OffsetPcir = RomHeader->PcirOffset;\r
+ PciDevice->PciRootBridgeIo->Mem.Read (\r
+ PciDevice->PciRootBridgeIo,\r
+ EfiPciWidthUint8,\r
+ RomBarOffset + OffsetPcir,\r
+ sizeof (PCI_DATA_STRUCTURE),\r
+ (UINT8 *) RomPcir\r
+ );\r
+ if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
+ CodeType = PCI_CODE_TYPE_PCAT_IMAGE;\r
+ }\r
+ Indicator = RomPcir->Indicator;\r
+ RomImageSize = RomImageSize + RomPcir->ImageLength * 512;\r
+ RomBarOffset = RomBarOffset + RomPcir->ImageLength * 512;\r
+ } while (((Indicator & 0x80) == 0x00) && ((RomBarOffset - RomBar) < RomSize));\r
+\r
+ //\r
+ // Some Legacy Cards do not report the correct ImageLength so used the maximum\r
+ // of the legacy length and the PCIR Image Length\r
+ //\r
+ if (CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
+ RomImageSize = MAX(RomImageSize, (((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512 * 512));\r
+ }\r
+\r
+ if (RomImageSize > 0) {\r
+ RetStatus = EFI_SUCCESS;\r
+ Image = AllocatePool ((UINT32) RomImageSize);\r
+ if (Image == NULL) {\r
+ RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);\r
+ FreePool (RomHeader);\r
+ FreePool (RomPcir);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Copy Rom image into memory\r
+ //\r
+ PciDevice->PciRootBridgeIo->Mem.Read (\r
+ PciDevice->PciRootBridgeIo,\r
+ EfiPciWidthUint8,\r
+ RomBar,\r
+ (UINT32) RomImageSize,\r
+ Image\r
+ );\r
+ RomInMemory = Image;\r
+ }\r
+\r
+ RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);\r
+\r
+ PciDevice->PciIo.RomSize = RomImageSize;\r
+ PciDevice->PciIo.RomImage = RomInMemory;\r
+\r
+ //\r
+ // For OpROM read from PCI device:\r
+ // Add the Rom Image to internal database for later PCI light enumeration\r
+ //\r
+ PciRomAddImageMapping (\r
+ NULL,\r
+ PciDevice->PciRootBridgeIo->SegmentNumber,\r
+ PciDevice->BusNumber,\r
+ PciDevice->DeviceNumber,\r
+ PciDevice->FunctionNumber,\r
+ (UINT64) (UINTN) PciDevice->PciIo.RomImage,\r
+ PciDevice->PciIo.RomSize\r
+ );\r
+\r
+ //\r
+ // Free allocated memory\r
+ //\r
+ FreePool (RomHeader);\r
+ FreePool (RomPcir);\r
+\r
+ return RetStatus;\r
+}\r
+\r
+/**\r
+ Enable/Disable Option Rom decode.\r
+\r
+ @param PciDevice Pci device instance.\r
+ @param RomBarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for resource range. The legal range for this field is 0..5.\r
+ @param RomBar Base address of Option Rom.\r
+ @param Enable Flag for enable/disable decode.\r
+\r
+**/\r
+VOID\r
+RomDecode (\r
+ IN PCI_IO_DEVICE *PciDevice,\r
+ IN UINT8 RomBarIndex,\r
+ IN UINT32 RomBar,\r
+ IN BOOLEAN Enable\r
+ )\r
+{\r
+ UINT32 Value32;\r
+ UINT32 Offset;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+ PciIo = &PciDevice->PciIo;\r
+ if (Enable) {\r
+ //\r
+ // Clear all bars\r
+ //\r
+ for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllZero);\r
+ }\r
+\r
+ //\r
+ // set the Rom base address: now is hardcode\r
+ // enable its decoder\r
+ //\r
+ Value32 = RomBar | 0x1;\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,\r
+ RomBarIndex,\r
+ 1,\r
+ &Value32\r
+ );\r
+\r
+ //\r
+ // Programe all upstream bridge\r
+ //\r
+ ProgrameUpstreamBridgeForRom(PciDevice, RomBar, TRUE);\r
+\r
+ //\r
+ // Setting the memory space bit in the function's command register\r
+ //\r
+ PCI_ENABLE_COMMAND_REGISTER(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);\r
+\r
+ } else {\r
+\r
+ //\r
+ // disable command register decode to memory\r
+ //\r
+ PCI_DISABLE_COMMAND_REGISTER(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);\r
+\r
+ //\r
+ // Destroy the programmed bar in all the upstream bridge.\r
+ //\r
+ ProgrameUpstreamBridgeForRom(PciDevice, RomBar, FALSE);\r
+\r
+ //\r
+ // disable rom decode\r
+ //\r
+ Value32 = 0xFFFFFFFE;\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,\r
+ RomBarIndex,\r
+ 1,\r
+ &Value32\r
+ );\r
+\r
+ }\r
+}\r
+\r
+/**\r
+ Load and start the Option Rom image.\r
+\r
+ @param PciDevice Pci device instance.\r
+\r
+ @retval EFI_SUCCESS Successfully loaded and started PCI Option Rom image.\r
+ @retval EFI_NOT_FOUND Failed to process PCI Option Rom image.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessOpRomImage (\r
+ IN PCI_IO_DEVICE *PciDevice\r
+ )\r
+{\r
+ UINT8 Indicator;\r
+ UINT32 ImageSize;\r
+ VOID *RomBar;\r
+ UINT8 *RomBarOffset;\r
+ EFI_HANDLE ImageHandle;\r
+ EFI_STATUS Status;\r
+ EFI_STATUS RetStatus;\r
+ BOOLEAN FirstCheck;\r
+ EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;\r
+ PCI_DATA_STRUCTURE *Pcir;\r
+ EFI_DEVICE_PATH_PROTOCOL *PciOptionRomImageDevicePath;\r
+ MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH EfiOpRomImageNode;\r
+ VOID *Buffer;\r
+ UINTN BufferSize;\r
+\r
+ Indicator = 0;\r
+\r
+ //\r
+ // Get the Address of the Option Rom image\r
+ //\r
+ RomBar = PciDevice->PciIo.RomImage;\r
+ RomBarOffset = (UINT8 *) RomBar;\r
+ RetStatus = EFI_NOT_FOUND;\r
+ FirstCheck = TRUE;\r
+\r
+ do {\r
+ EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset;\r
+ if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
+ RomBarOffset += 512;\r
+ if (FirstCheck) {\r
+ break;\r
+ } else {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ FirstCheck = FALSE;\r
+ Pcir = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset);\r
+ ImageSize = (UINT32) (Pcir->ImageLength * 512);\r
+ Indicator = Pcir->Indicator;\r
+\r
+ //\r
+ // Create Pci Option Rom Image device path header\r
+ //\r
+ EfiOpRomImageNode.Header.Type = MEDIA_DEVICE_PATH;\r
+ EfiOpRomImageNode.Header.SubType = MEDIA_RELATIVE_OFFSET_RANGE_DP;\r
+ SetDevicePathNodeLength (&EfiOpRomImageNode.Header, sizeof (EfiOpRomImageNode));\r
+ EfiOpRomImageNode.StartingOffset = (UINTN) RomBarOffset - (UINTN) RomBar;\r
+ EfiOpRomImageNode.EndingOffset = (UINTN) RomBarOffset + ImageSize - 1 - (UINTN) RomBar;\r
+\r
+ PciOptionRomImageDevicePath = AppendDevicePathNode (PciDevice->DevicePath, &EfiOpRomImageNode.Header);\r
+ ASSERT (PciOptionRomImageDevicePath != NULL);\r
+\r
+ //\r
+ // load image and start image\r
+ //\r
+ BufferSize = 0;\r
+ Buffer = NULL;\r
+ Status = EFI_SUCCESS;\r
+ ImageHandle = NULL;\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->LoadImage (\r
+ FALSE,\r
+ gPciBusDriverBinding.DriverBindingHandle,\r
+ PciOptionRomImageDevicePath,\r
+ Buffer,\r
+ BufferSize,\r
+ &ImageHandle\r
+ );\r
+ }\r
+\r
+ //\r
+ // load image and start image\r
+ //\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->LoadImage (\r
+ FALSE,\r
+ gPciBusDriverBinding.DriverBindingHandle,\r
+ PciOptionRomImageDevicePath,\r
+ Buffer,\r
+ BufferSize,\r
+ &ImageHandle\r
+ );\r
+ }\r
+\r
+ FreePool (PciOptionRomImageDevicePath);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
+ if (!EFI_ERROR (Status)) {\r
+ AddDriver (PciDevice, ImageHandle);\r
+ PciRomAddImageMapping (\r
+ ImageHandle,\r
+ PciDevice->PciRootBridgeIo->SegmentNumber,\r
+ PciDevice->BusNumber,\r
+ PciDevice->DeviceNumber,\r
+ PciDevice->FunctionNumber,\r
+ (UINT64) (UINTN) PciDevice->PciIo.RomImage,\r
+ PciDevice->PciIo.RomSize\r
+ );\r
+ RetStatus = EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ RomBarOffset += ImageSize;\r
+\r
+ } while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize));\r
+\r
+ return RetStatus;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ PCI Rom supporting funtions declaration 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
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_OPTION_ROM_SUPPORT_H_\r
+#define _EFI_PCI_OPTION_ROM_SUPPORT_H_\r
+\r
+\r
+/**\r
+ Initialize a PCI LoadFile2 instance.\r
+\r
+ @param PciIoDevice PCI IO Device.\r
+\r
+**/\r
+VOID\r
+InitializePciLoadFile2 (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+/**\r
+ Causes the driver to load a specified file.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param FilePath The device specific path of the file to load.\r
+ @param BootPolicy Should always be FALSE.\r
+ @param BufferSize On input the size of Buffer in bytes. On output with a return\r
+ code of EFI_SUCCESS, the amount of data transferred to Buffer.\r
+ On output with a return code of EFI_BUFFER_TOO_SMALL,\r
+ the size of Buffer required to retrieve the requested file.\r
+ @param Buffer The memory buffer to transfer the file to. If Buffer is NULL,\r
+ then no the size of the requested file is returned in BufferSize.\r
+\r
+ @retval EFI_SUCCESS The file was loaded.\r
+ @retval EFI_UNSUPPORTED BootPolicy is TRUE.\r
+ @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or\r
+ BufferSize is NULL.\r
+ @retval EFI_NOT_FOUND Not found PCI Option Rom on PCI device.\r
+ @retval EFI_DEVICE_ERROR Failed to decompress PCI Option Rom image.\r
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.\r
+ BufferSize has been updated with the size needed to complete the request.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LoadFile2 (\r
+ IN EFI_LOAD_FILE2_PROTOCOL *This,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+ IN BOOLEAN BootPolicy,\r
+ IN OUT UINTN *BufferSize,\r
+ IN VOID *Buffer OPTIONAL\r
+ );\r
+\r
+/**\r
+ Check if the RomImage contains EFI Images.\r
+\r
+ @param RomImage The ROM address of Image for check.\r
+ @param RomSize Size of ROM for check.\r
+\r
+ @retval TRUE ROM contain EFI Image.\r
+ @retval FALSE ROM not contain EFI Image.\r
+\r
+**/\r
+BOOLEAN\r
+ContainEfiImage (\r
+ IN VOID *RomImage,\r
+ IN UINT64 RomSize\r
+ );\r
+\r
+\r
+/**\r
+ Get Pci device's oprom information.\r
+\r
+ @param PciIoDevice Input Pci device instance.\r
+ Output Pci device instance with updated OptionRom size.\r
+\r
+ @retval EFI_NOT_FOUND Pci device has not Option Rom.\r
+ @retval EFI_SUCCESS Pci device has Option Rom.\r
+\r
+**/\r
+EFI_STATUS\r
+GetOpRomInfo (\r
+ IN OUT PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+/**\r
+ Load Option Rom image for specified PCI device.\r
+\r
+ @param PciDevice Pci device instance.\r
+ @param RomBase Base address of Option Rom.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES No enough memory to hold image.\r
+ @retval EFI_SUCESS Successfully loaded Option Rom.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadOpRomImage (\r
+ IN PCI_IO_DEVICE *PciDevice,\r
+ IN UINT64 RomBase\r
+ );\r
+\r
+/**\r
+ Enable/Disable Option Rom decode.\r
+\r
+ @param PciDevice Pci device instance.\r
+ @param RomBarIndex The BAR index of the standard PCI Configuration header to use as the\r
+ base address for resource range. The legal range for this field is 0..5.\r
+ @param RomBar Base address of Option Rom.\r
+ @param Enable Flag for enable/disable decode.\r
+\r
+**/\r
+VOID\r
+RomDecode (\r
+ IN PCI_IO_DEVICE *PciDevice,\r
+ IN UINT8 RomBarIndex,\r
+ IN UINT32 RomBar,\r
+ IN BOOLEAN Enable\r
+ );\r
+\r
+/**\r
+ Load and start the Option Rom image.\r
+\r
+ @param PciDevice Pci device instance.\r
+\r
+ @retval EFI_SUCCESS Successfully loaded and started PCI Option Rom image.\r
+ @retval EFI_NOT_FOUND Failed to process PCI Option Rom image.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessOpRomImage (\r
+ IN PCI_IO_DEVICE *PciDevice\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Power management support fucntions implementation 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
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+/**\r
+ This function is intended to turn off PWE assertion and\r
+ put the device to D0 state if the device supports\r
+ PCI Power Management.\r
+\r
+ @param PciIoDevice PCI device instance.\r
+\r
+ @retval EFI_UNSUPPORTED PCI Device does not support power management.\r
+ @retval EFI_SUCCESS Turned off PWE successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+ResetPowerManagementFeature (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 PowerManagementRegBlock;\r
+ UINT16 PowerManagementCSR;\r
+\r
+ PowerManagementRegBlock = 0;\r
+\r
+ Status = LocateCapabilityRegBlock (\r
+ PciIoDevice,\r
+ EFI_PCI_CAPABILITY_ID_PMI,\r
+ &PowerManagementRegBlock,\r
+ NULL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Turn off the PWE assertion and put the device into D0 State\r
+ //\r
+ PowerManagementCSR = 0x8000;\r
+\r
+ //\r
+ // Write PMCSR\r
+ //\r
+ PciIoDevice->PciIo.Pci.Write (\r
+ &PciIoDevice->PciIo,\r
+ EfiPciIoWidthUint16,\r
+ PowerManagementRegBlock + 4,\r
+ 1,\r
+ &PowerManagementCSR\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ Power management support fucntions delaration 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
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_POWER_MANAGEMENT_H_\r
+#define _EFI_PCI_POWER_MANAGEMENT_H_\r
+\r
+/**\r
+ This function is intended to turn off PWE assertion and\r
+ put the device to D0 state if the device supports\r
+ PCI Power Management.\r
+\r
+ @param PciIoDevice PCI device instance.\r
+\r
+ @retval EFI_UNSUPPORTED PCI Device does not support power management.\r
+ @retval EFI_SUCCESS Turned off PWE successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+ResetPowerManagementFeature (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ PCI resouces support functions implemntation 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
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+/**\r
+ The function is used to skip VGA range.\r
+\r
+ @param Start Returned start address including VGA range.\r
+ @param Length The length of VGA range.\r
+\r
+**/\r
+VOID\r
+SkipVGAAperture (\r
+ OUT UINT64 *Start,\r
+ IN UINT64 Length\r
+ )\r
+{\r
+ UINT64 Original;\r
+ UINT64 Mask;\r
+ UINT64 StartOffset;\r
+ UINT64 LimitOffset;\r
+\r
+ ASSERT (Start != NULL);\r
+ //\r
+ // For legacy VGA, bit 10 to bit 15 is not decoded\r
+ //\r
+ Mask = 0x3FF;\r
+\r
+ Original = *Start;\r
+ StartOffset = Original & Mask;\r
+ LimitOffset = ((*Start) + Length - 1) & Mask;\r
+ if (LimitOffset >= VGABASE1) {\r
+ *Start = *Start - StartOffset + VGALIMIT2 + 1;\r
+ }\r
+}\r
+\r
+/**\r
+ This function is used to skip ISA aliasing aperture.\r
+\r
+ @param Start Returned start address including ISA aliasing aperture.\r
+ @param Length The length of ISA aliasing aperture.\r
+\r
+**/\r
+VOID\r
+SkipIsaAliasAperture (\r
+ OUT UINT64 *Start,\r
+ IN UINT64 Length\r
+ )\r
+{\r
+\r
+ UINT64 Original;\r
+ UINT64 Mask;\r
+ UINT64 StartOffset;\r
+ UINT64 LimitOffset;\r
+\r
+ ASSERT (Start != NULL);\r
+\r
+ //\r
+ // For legacy ISA, bit 10 to bit 15 is not decoded\r
+ //\r
+ Mask = 0x3FF;\r
+\r
+ Original = *Start;\r
+ StartOffset = Original & Mask;\r
+ LimitOffset = ((*Start) + Length - 1) & Mask;\r
+\r
+ if (LimitOffset >= ISABASE) {\r
+ *Start = *Start - StartOffset + ISALIMIT + 1;\r
+ }\r
+}\r
+\r
+/**\r
+ This function inserts a resource node into the resource list.\r
+ The resource list is sorted in descend order.\r
+\r
+ @param Bridge PCI resource node for bridge.\r
+ @param ResNode Resource node want to be inserted.\r
+\r
+**/\r
+VOID\r
+InsertResourceNode (\r
+ IN OUT PCI_RESOURCE_NODE *Bridge,\r
+ IN PCI_RESOURCE_NODE *ResNode\r
+ )\r
+{\r
+ LIST_ENTRY *CurrentLink;\r
+ PCI_RESOURCE_NODE *Temp;\r
+ UINT64 ResNodeAlignRest;\r
+ UINT64 TempAlignRest;\r
+\r
+ ASSERT (Bridge != NULL);\r
+ ASSERT (ResNode != NULL);\r
+\r
+ InsertHeadList (&Bridge->ChildList, &ResNode->Link);\r
+\r
+ CurrentLink = Bridge->ChildList.ForwardLink->ForwardLink;\r
+ while (CurrentLink != &Bridge->ChildList) {\r
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+ if (ResNode->Alignment > Temp->Alignment) {\r
+ break;\r
+ } else if (ResNode->Alignment == Temp->Alignment) {\r
+ ResNodeAlignRest = ResNode->Length & ResNode->Alignment;\r
+ TempAlignRest = Temp->Length & Temp->Alignment;\r
+ if ((ResNodeAlignRest == 0) || (ResNodeAlignRest >= TempAlignRest)) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ SwapListEntries (&ResNode->Link, CurrentLink);\r
+\r
+ CurrentLink = ResNode->Link.ForwardLink;\r
+ }\r
+}\r
+\r
+/**\r
+ This routine is used to merge two different resource trees in need of\r
+ resoure degradation.\r
+\r
+ For example, if an upstream PPB doesn't support,\r
+ prefetchable memory decoding, the PCI bus driver will choose to call this function\r
+ to merge prefectchable memory resource list into normal memory list.\r
+\r
+ If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource\r
+ type.\r
+ If Dst is NULL or Res is NULL, ASSERT ().\r
+\r
+ @param Dst Point to destination resource tree.\r
+ @param Res Point to source resource tree.\r
+ @param TypeMerge If the TypeMerge is TRUE, Res resource type is changed to the type of\r
+ destination resource type.\r
+\r
+**/\r
+VOID\r
+MergeResourceTree (\r
+ IN PCI_RESOURCE_NODE *Dst,\r
+ IN PCI_RESOURCE_NODE *Res,\r
+ IN BOOLEAN TypeMerge\r
+ )\r
+{\r
+\r
+ LIST_ENTRY *CurrentLink;\r
+ PCI_RESOURCE_NODE *Temp;\r
+\r
+ ASSERT (Dst != NULL);\r
+ ASSERT (Res != NULL);\r
+\r
+ while (!IsListEmpty (&Res->ChildList)) {\r
+ CurrentLink = Res->ChildList.ForwardLink;\r
+\r
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+ if (TypeMerge) {\r
+ Temp->ResType = Dst->ResType;\r
+ }\r
+\r
+ RemoveEntryList (CurrentLink);\r
+ InsertResourceNode (Dst, Temp);\r
+ }\r
+}\r
+\r
+/**\r
+ This function is used to calculate the IO16 aperture\r
+ for a bridge.\r
+\r
+ @param Bridge PCI resource node for bridge.\r
+\r
+**/\r
+VOID\r
+CalculateApertureIo16 (\r
+ IN PCI_RESOURCE_NODE *Bridge\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT64 Aperture;\r
+ LIST_ENTRY *CurrentLink;\r
+ PCI_RESOURCE_NODE *Node;\r
+ UINT64 Offset;\r
+ BOOLEAN IsaEnable;\r
+ BOOLEAN VGAEnable;\r
+ EFI_PCI_PLATFORM_POLICY PciPolicy;\r
+\r
+ //\r
+ // Always assume there is ISA device and VGA device on the platform\r
+ // will be customized later\r
+ //\r
+ IsaEnable = FALSE;\r
+ VGAEnable = FALSE;\r
+\r
+ //\r
+ // Check PciPlatform policy\r
+ //\r
+ if (gPciPlatformProtocol != NULL) {\r
+ Status = gPciPlatformProtocol->GetPlatformPolicy (\r
+ gPciPlatformProtocol,\r
+ &PciPolicy\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {\r
+ IsaEnable = TRUE;\r
+ }\r
+ if ((PciPolicy & EFI_RESERVE_VGA_IO_ALIAS) != 0) {\r
+ VGAEnable = TRUE;\r
+ }\r
+ }\r
+ } else if (gPciOverrideProtocol != NULL) {\r
+ Status = gPciOverrideProtocol->GetPlatformPolicy (\r
+ gPciOverrideProtocol,\r
+ &PciPolicy\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {\r
+ IsaEnable = TRUE;\r
+ }\r
+ if ((PciPolicy & EFI_RESERVE_VGA_IO_ALIAS) != 0) {\r
+ VGAEnable = TRUE;\r
+ }\r
+ }\r
+ }\r
+\r
+ Aperture = 0;\r
+\r
+ if (Bridge == NULL) {\r
+ return ;\r
+ }\r
+\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+ //\r
+ // Assume the bridge is aligned\r
+ //\r
+ while (CurrentLink != &Bridge->ChildList) {\r
+\r
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+ //\r
+ // Consider the aperture alignment\r
+ //\r
+ Offset = Aperture & (Node->Alignment);\r
+\r
+ if (Offset != 0) {\r
+\r
+ Aperture = Aperture + (Node->Alignment + 1) - Offset;\r
+\r
+ }\r
+\r
+ //\r
+ // IsaEnable and VGAEnable can not be implemented now.\r
+ // If both of them are enabled, then the IO resource would\r
+ // become too limited to meet the requirement of most of devices.\r
+ //\r
+ if (IsaEnable || VGAEnable) {\r
+ if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci)) && !IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {\r
+ //\r
+ // Check if there is need to support ISA/VGA decoding\r
+ // If so, we need to avoid isa/vga aliasing range\r
+ //\r
+ if (IsaEnable) {\r
+ SkipIsaAliasAperture (\r
+ &Aperture,\r
+ Node->Length\r
+ );\r
+ Offset = Aperture & (Node->Alignment);\r
+ if (Offset != 0) {\r
+ Aperture = Aperture + (Node->Alignment + 1) - Offset;\r
+ }\r
+ } else if (VGAEnable) {\r
+ SkipVGAAperture (\r
+ &Aperture,\r
+ Node->Length\r
+ );\r
+ Offset = Aperture & (Node->Alignment);\r
+ if (Offset != 0) {\r
+ Aperture = Aperture + (Node->Alignment + 1) - Offset;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ Node->Offset = Aperture;\r
+\r
+ //\r
+ // Increment aperture by the length of node\r
+ //\r
+ Aperture += Node->Length;\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ //\r
+ // At last, adjust the aperture with the bridge's\r
+ // alignment\r
+ //\r
+ Offset = Aperture & (Bridge->Alignment);\r
+\r
+ if (Offset != 0) {\r
+ Aperture = Aperture + (Bridge->Alignment + 1) - Offset;\r
+ }\r
+\r
+ Bridge->Length = Aperture;\r
+ //\r
+ // At last, adjust the bridge's alignment to the first child's alignment\r
+ // if the bridge has at least one child\r
+ //\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+ if (CurrentLink != &Bridge->ChildList) {\r
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+ if (Node->Alignment > Bridge->Alignment) {\r
+ Bridge->Alignment = Node->Alignment;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ This function is used to calculate the resource aperture\r
+ for a given bridge device.\r
+\r
+ @param Bridge PCI resouce node for given bridge device.\r
+\r
+**/\r
+VOID\r
+CalculateResourceAperture (\r
+ IN PCI_RESOURCE_NODE *Bridge\r
+ )\r
+{\r
+ UINT64 Aperture;\r
+ LIST_ENTRY *CurrentLink;\r
+ PCI_RESOURCE_NODE *Node;\r
+\r
+ UINT64 Offset;\r
+\r
+ Aperture = 0;\r
+\r
+ if (Bridge == NULL) {\r
+ return ;\r
+ }\r
+\r
+ if (Bridge->ResType == PciBarTypeIo16) {\r
+\r
+ CalculateApertureIo16 (Bridge);\r
+ return ;\r
+ }\r
+\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+ //\r
+ // Assume the bridge is aligned\r
+ //\r
+ while (CurrentLink != &Bridge->ChildList) {\r
+\r
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+ //\r
+ // Apply padding resource if available\r
+ //\r
+ Offset = Aperture & (Node->Alignment);\r
+\r
+ if (Offset != 0) {\r
+\r
+ Aperture = Aperture + (Node->Alignment + 1) - Offset;\r
+\r
+ }\r
+\r
+ //\r
+ // Recode current aperture as a offset\r
+ // this offset will be used in future real allocation\r
+ //\r
+ Node->Offset = Aperture;\r
+\r
+ //\r
+ // Increment aperture by the length of node\r
+ //\r
+ Aperture += Node->Length;\r
+\r
+ //\r
+ // Consider the aperture alignment\r
+ //\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ //\r
+ // At last, adjust the aperture with the bridge's\r
+ // alignment\r
+ //\r
+ Offset = Aperture & (Bridge->Alignment);\r
+ if (Offset != 0) {\r
+ Aperture = Aperture + (Bridge->Alignment + 1) - Offset;\r
+ }\r
+\r
+ //\r
+ // If the bridge has already padded the resource and the\r
+ // amount of padded resource is larger, then keep the\r
+ // padded resource\r
+ //\r
+ if (Bridge->Length < Aperture) {\r
+ Bridge->Length = Aperture;\r
+ }\r
+\r
+ //\r
+ // At last, adjust the bridge's alignment to the first child's alignment\r
+ // if the bridge has at least one child\r
+ //\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+ if (CurrentLink != &Bridge->ChildList) {\r
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+ if (Node->Alignment > Bridge->Alignment) {\r
+ Bridge->Alignment = Node->Alignment;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Get IO/Memory resource infor for given PCI device.\r
+\r
+ @param PciDev Pci device instance.\r
+ @param IoNode Resource info node for IO .\r
+ @param Mem32Node Resource info node for 32-bit memory.\r
+ @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+ @param Mem64Node Resource info node for 64-bit memory.\r
+ @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+GetResourceFromDevice (\r
+ IN PCI_IO_DEVICE *PciDev,\r
+ IN OUT PCI_RESOURCE_NODE *IoNode,\r
+ IN OUT PCI_RESOURCE_NODE *Mem32Node,\r
+ IN OUT PCI_RESOURCE_NODE *PMem32Node,\r
+ IN OUT PCI_RESOURCE_NODE *Mem64Node,\r
+ IN OUT PCI_RESOURCE_NODE *PMem64Node\r
+ )\r
+{\r
+\r
+ UINT8 Index;\r
+ PCI_RESOURCE_NODE *Node;\r
+ BOOLEAN ResourceRequested;\r
+\r
+ Node = NULL;\r
+ ResourceRequested = FALSE;\r
+\r
+ for (Index = 0; Index < PCI_MAX_BAR; Index++) {\r
+\r
+ switch ((PciDev->PciBar)[Index].BarType) {\r
+\r
+ case PciBarTypeMem32:\r
+\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ (PciDev->PciBar)[Index].Length,\r
+ (PciDev->PciBar)[Index].Alignment,\r
+ Index,\r
+ PciBarTypeMem32,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ InsertResourceNode (\r
+ Mem32Node,\r
+ Node\r
+ );\r
+\r
+ ResourceRequested = TRUE;\r
+ break;\r
+\r
+ case PciBarTypeMem64:\r
+\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ (PciDev->PciBar)[Index].Length,\r
+ (PciDev->PciBar)[Index].Alignment,\r
+ Index,\r
+ PciBarTypeMem64,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ InsertResourceNode (\r
+ Mem64Node,\r
+ Node\r
+ );\r
+\r
+ ResourceRequested = TRUE;\r
+ break;\r
+\r
+ case PciBarTypePMem64:\r
+\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ (PciDev->PciBar)[Index].Length,\r
+ (PciDev->PciBar)[Index].Alignment,\r
+ Index,\r
+ PciBarTypePMem64,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ InsertResourceNode (\r
+ PMem64Node,\r
+ Node\r
+ );\r
+\r
+ ResourceRequested = TRUE;\r
+ break;\r
+\r
+ case PciBarTypePMem32:\r
+\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ (PciDev->PciBar)[Index].Length,\r
+ (PciDev->PciBar)[Index].Alignment,\r
+ Index,\r
+ PciBarTypePMem32,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ InsertResourceNode (\r
+ PMem32Node,\r
+ Node\r
+ );\r
+ ResourceRequested = TRUE;\r
+ break;\r
+\r
+ case PciBarTypeIo16:\r
+ case PciBarTypeIo32:\r
+\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ (PciDev->PciBar)[Index].Length,\r
+ (PciDev->PciBar)[Index].Alignment,\r
+ Index,\r
+ PciBarTypeIo16,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ InsertResourceNode (\r
+ IoNode,\r
+ Node\r
+ );\r
+ ResourceRequested = TRUE;\r
+ break;\r
+\r
+ case PciBarTypeUnknown:\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Add VF resource\r
+ //\r
+ for (Index = 0; Index < PCI_MAX_BAR; Index++) {\r
+\r
+ switch ((PciDev->VfPciBar)[Index].BarType) {\r
+\r
+ case PciBarTypeMem32:\r
+\r
+ Node = CreateVfResourceNode (\r
+ PciDev,\r
+ (PciDev->VfPciBar)[Index].Length,\r
+ (PciDev->VfPciBar)[Index].Alignment,\r
+ Index,\r
+ PciBarTypeMem32,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ InsertResourceNode (\r
+ Mem32Node,\r
+ Node\r
+ );\r
+\r
+ break;\r
+\r
+ case PciBarTypeMem64:\r
+\r
+ Node = CreateVfResourceNode (\r
+ PciDev,\r
+ (PciDev->VfPciBar)[Index].Length,\r
+ (PciDev->VfPciBar)[Index].Alignment,\r
+ Index,\r
+ PciBarTypeMem64,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ InsertResourceNode (\r
+ Mem64Node,\r
+ Node\r
+ );\r
+\r
+ break;\r
+\r
+ case PciBarTypePMem64:\r
+\r
+ Node = CreateVfResourceNode (\r
+ PciDev,\r
+ (PciDev->VfPciBar)[Index].Length,\r
+ (PciDev->VfPciBar)[Index].Alignment,\r
+ Index,\r
+ PciBarTypePMem64,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ InsertResourceNode (\r
+ PMem64Node,\r
+ Node\r
+ );\r
+\r
+ break;\r
+\r
+ case PciBarTypePMem32:\r
+\r
+ Node = CreateVfResourceNode (\r
+ PciDev,\r
+ (PciDev->VfPciBar)[Index].Length,\r
+ (PciDev->VfPciBar)[Index].Alignment,\r
+ Index,\r
+ PciBarTypePMem32,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ InsertResourceNode (\r
+ PMem32Node,\r
+ Node\r
+ );\r
+ break;\r
+\r
+ case PciBarTypeIo16:\r
+ case PciBarTypeIo32:\r
+ break;\r
+\r
+ case PciBarTypeUnknown:\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+ // If there is no resource requested from this device,\r
+ // then we indicate this device has been allocated naturally.\r
+ //\r
+ if (!ResourceRequested) {\r
+ PciDev->Allocated = TRUE;\r
+ }\r
+}\r
+\r
+/**\r
+ This function is used to create a resource node.\r
+\r
+ @param PciDev Pci device instance.\r
+ @param Length Length of Io/Memory resource.\r
+ @param Alignment Alignment of resource.\r
+ @param Bar Bar index.\r
+ @param ResType Type of resource: IO/Memory.\r
+ @param ResUsage Resource usage.\r
+\r
+ @return PCI resource node created for given PCI device.\r
+ NULL means PCI resource node is not created.\r
+\r
+**/\r
+PCI_RESOURCE_NODE *\r
+CreateResourceNode (\r
+ IN PCI_IO_DEVICE *PciDev,\r
+ IN UINT64 Length,\r
+ IN UINT64 Alignment,\r
+ IN UINT8 Bar,\r
+ IN PCI_BAR_TYPE ResType,\r
+ IN PCI_RESOURCE_USAGE ResUsage\r
+ )\r
+{\r
+ PCI_RESOURCE_NODE *Node;\r
+\r
+ Node = NULL;\r
+\r
+ Node = AllocateZeroPool (sizeof (PCI_RESOURCE_NODE));\r
+ ASSERT (Node != NULL);\r
+ if (Node == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Node->Signature = PCI_RESOURCE_SIGNATURE;\r
+ Node->PciDev = PciDev;\r
+ Node->Length = Length;\r
+ Node->Alignment = Alignment;\r
+ Node->Bar = Bar;\r
+ Node->ResType = ResType;\r
+ Node->Reserved = FALSE;\r
+ Node->ResourceUsage = ResUsage;\r
+ InitializeListHead (&Node->ChildList);\r
+\r
+ return Node;\r
+}\r
+\r
+/**\r
+ This function is used to create a IOV VF resource node.\r
+\r
+ @param PciDev Pci device instance.\r
+ @param Length Length of Io/Memory resource.\r
+ @param Alignment Alignment of resource.\r
+ @param Bar Bar index.\r
+ @param ResType Type of resource: IO/Memory.\r
+ @param ResUsage Resource usage.\r
+\r
+ @return PCI resource node created for given VF PCI device.\r
+ NULL means PCI resource node is not created.\r
+\r
+**/\r
+PCI_RESOURCE_NODE *\r
+CreateVfResourceNode (\r
+ IN PCI_IO_DEVICE *PciDev,\r
+ IN UINT64 Length,\r
+ IN UINT64 Alignment,\r
+ IN UINT8 Bar,\r
+ IN PCI_BAR_TYPE ResType,\r
+ IN PCI_RESOURCE_USAGE ResUsage\r
+ )\r
+{\r
+ PCI_RESOURCE_NODE *Node;\r
+\r
+ DEBUG ((\r
+ EFI_D_INFO,\r
+ "PCI-IOV B%x.D%x.F%x - VfResource (Bar - 0x%x) (Type - 0x%x) (Length - 0x%x)\n",\r
+ (UINTN)PciDev->BusNumber,\r
+ (UINTN)PciDev->DeviceNumber,\r
+ (UINTN)PciDev->FunctionNumber,\r
+ (UINTN)Bar,\r
+ (UINTN)ResType,\r
+ (UINTN)Length\r
+ ));\r
+\r
+ Node = CreateResourceNode (PciDev, Length, Alignment, Bar, ResType, ResUsage);\r
+ if (Node == NULL) {\r
+ return Node;\r
+ }\r
+\r
+ Node->Virtual = TRUE;\r
+\r
+ return Node;\r
+}\r
+\r
+/**\r
+ This function is used to extract resource request from\r
+ device node list.\r
+\r
+ @param Bridge Pci device instance.\r
+ @param IoNode Resource info node for IO.\r
+ @param Mem32Node Resource info node for 32-bit memory.\r
+ @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+ @param Mem64Node Resource info node for 64-bit memory.\r
+ @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+CreateResourceMap (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN OUT PCI_RESOURCE_NODE *IoNode,\r
+ IN OUT PCI_RESOURCE_NODE *Mem32Node,\r
+ IN OUT PCI_RESOURCE_NODE *PMem32Node,\r
+ IN OUT PCI_RESOURCE_NODE *Mem64Node,\r
+ IN OUT PCI_RESOURCE_NODE *PMem64Node\r
+ )\r
+{\r
+ PCI_IO_DEVICE *Temp;\r
+ PCI_RESOURCE_NODE *IoBridge;\r
+ PCI_RESOURCE_NODE *Mem32Bridge;\r
+ PCI_RESOURCE_NODE *PMem32Bridge;\r
+ PCI_RESOURCE_NODE *Mem64Bridge;\r
+ PCI_RESOURCE_NODE *PMem64Bridge;\r
+ LIST_ENTRY *CurrentLink;\r
+\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+ while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
+\r
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+ //\r
+ // Create resource nodes for this device by scanning the\r
+ // Bar array in the device private data\r
+ // If the upstream bridge doesn't support this device,\r
+ // no any resource node will be created for this device\r
+ //\r
+ GetResourceFromDevice (\r
+ Temp,\r
+ IoNode,\r
+ Mem32Node,\r
+ PMem32Node,\r
+ Mem64Node,\r
+ PMem64Node\r
+ );\r
+\r
+ if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
+\r
+ //\r
+ // If the device has children, create a bridge resource node for this PPB\r
+ // Note: For PPB, memory aperture is aligned with 1MB and IO aperture\r
+ // is aligned with 4KB\r
+ // This device is typically a bridge device like PPB and P2C\r
+ // Note: 0x1000 aligned\r
+ //\r
+ IoBridge = CreateResourceNode (\r
+ Temp,\r
+ 0,\r
+ 0xFFF,\r
+ PPB_IO_RANGE,\r
+ PciBarTypeIo16,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ Mem32Bridge = CreateResourceNode (\r
+ Temp,\r
+ 0,\r
+ 0xFFFFF,\r
+ PPB_MEM32_RANGE,\r
+ PciBarTypeMem32,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ PMem32Bridge = CreateResourceNode (\r
+ Temp,\r
+ 0,\r
+ 0xFFFFF,\r
+ PPB_PMEM32_RANGE,\r
+ PciBarTypePMem32,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ Mem64Bridge = CreateResourceNode (\r
+ Temp,\r
+ 0,\r
+ 0xFFFFF,\r
+ PPB_MEM64_RANGE,\r
+ PciBarTypeMem64,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ PMem64Bridge = CreateResourceNode (\r
+ Temp,\r
+ 0,\r
+ 0xFFFFF,\r
+ PPB_PMEM64_RANGE,\r
+ PciBarTypePMem64,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ //\r
+ // Recursively create resouce map on this bridge\r
+ //\r
+ CreateResourceMap (\r
+ Temp,\r
+ IoBridge,\r
+ Mem32Bridge,\r
+ PMem32Bridge,\r
+ Mem64Bridge,\r
+ PMem64Bridge\r
+ );\r
+\r
+ if (ResourceRequestExisted (IoBridge)) {\r
+ InsertResourceNode (\r
+ IoNode,\r
+ IoBridge\r
+ );\r
+ } else {\r
+ FreePool (IoBridge);\r
+ IoBridge = NULL;\r
+ }\r
+\r
+ //\r
+ // If there is node under this resource bridge,\r
+ // then calculate bridge's aperture of this type\r
+ // and insert it into the respective resource tree.\r
+ // If no, delete this resource bridge\r
+ //\r
+ if (ResourceRequestExisted (Mem32Bridge)) {\r
+ InsertResourceNode (\r
+ Mem32Node,\r
+ Mem32Bridge\r
+ );\r
+ } else {\r
+ FreePool (Mem32Bridge);\r
+ Mem32Bridge = NULL;\r
+ }\r
+\r
+ //\r
+ // If there is node under this resource bridge,\r
+ // then calculate bridge's aperture of this type\r
+ // and insert it into the respective resource tree.\r
+ // If no, delete this resource bridge\r
+ //\r
+ if (ResourceRequestExisted (PMem32Bridge)) {\r
+ InsertResourceNode (\r
+ PMem32Node,\r
+ PMem32Bridge\r
+ );\r
+ } else {\r
+ FreePool (PMem32Bridge);\r
+ PMem32Bridge = NULL;\r
+ }\r
+\r
+ //\r
+ // If there is node under this resource bridge,\r
+ // then calculate bridge's aperture of this type\r
+ // and insert it into the respective resource tree.\r
+ // If no, delete this resource bridge\r
+ //\r
+ if (ResourceRequestExisted (Mem64Bridge)) {\r
+ InsertResourceNode (\r
+ Mem64Node,\r
+ Mem64Bridge\r
+ );\r
+ } else {\r
+ FreePool (Mem64Bridge);\r
+ Mem64Bridge = NULL;\r
+ }\r
+\r
+ //\r
+ // If there is node under this resource bridge,\r
+ // then calculate bridge's aperture of this type\r
+ // and insert it into the respective resource tree.\r
+ // If no, delete this resource bridge\r
+ //\r
+ if (ResourceRequestExisted (PMem64Bridge)) {\r
+ InsertResourceNode (\r
+ PMem64Node,\r
+ PMem64Bridge\r
+ );\r
+ } else {\r
+ FreePool (PMem64Bridge);\r
+ PMem64Bridge = NULL;\r
+ }\r
+\r
+ }\r
+\r
+ //\r
+ // If it is P2C, apply hard coded resource padding\r
+ //\r
+ if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
+ ResourcePaddingForCardBusBridge (\r
+ Temp,\r
+ IoNode,\r
+ Mem32Node,\r
+ PMem32Node,\r
+ Mem64Node,\r
+ PMem64Node\r
+ );\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ //\r
+ // To do some platform specific resource padding ...\r
+ //\r
+ ResourcePaddingPolicy (\r
+ Bridge,\r
+ IoNode,\r
+ Mem32Node,\r
+ PMem32Node,\r
+ Mem64Node,\r
+ PMem64Node\r
+ );\r
+\r
+ //\r
+ // Degrade resource if necessary\r
+ //\r
+ DegradeResource (\r
+ Bridge,\r
+ Mem32Node,\r
+ PMem32Node,\r
+ Mem64Node,\r
+ PMem64Node\r
+ );\r
+\r
+ //\r
+ // Calculate resource aperture for this bridge device\r
+ //\r
+ CalculateResourceAperture (Mem32Node);\r
+ CalculateResourceAperture (PMem32Node);\r
+ CalculateResourceAperture (Mem64Node);\r
+ CalculateResourceAperture (PMem64Node);\r
+ CalculateResourceAperture (IoNode);\r
+}\r
+\r
+/**\r
+ This function is used to do the resource padding for a specific platform.\r
+\r
+ @param PciDev Pci device instance.\r
+ @param IoNode Resource info node for IO.\r
+ @param Mem32Node Resource info node for 32-bit memory.\r
+ @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+ @param Mem64Node Resource info node for 64-bit memory.\r
+ @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+ResourcePaddingPolicy (\r
+ IN PCI_IO_DEVICE *PciDev,\r
+ IN PCI_RESOURCE_NODE *IoNode,\r
+ IN PCI_RESOURCE_NODE *Mem32Node,\r
+ IN PCI_RESOURCE_NODE *PMem32Node,\r
+ IN PCI_RESOURCE_NODE *Mem64Node,\r
+ IN PCI_RESOURCE_NODE *PMem64Node\r
+ )\r
+{\r
+ //\r
+ // Create padding resource node\r
+ //\r
+ if (PciDev->ResourcePaddingDescriptors != NULL) {\r
+ ApplyResourcePadding (\r
+ PciDev,\r
+ IoNode,\r
+ Mem32Node,\r
+ PMem32Node,\r
+ Mem64Node,\r
+ PMem64Node\r
+ );\r
+ }\r
+}\r
+\r
+/**\r
+ This function is used to degrade resource if the upstream bridge\r
+ doesn't support certain resource. Degradation path is\r
+ PMEM64 -> MEM64 -> MEM32\r
+ PMEM64 -> PMEM32 -> MEM32\r
+ IO32 -> IO16.\r
+\r
+ @param Bridge Pci device instance.\r
+ @param Mem32Node Resource info node for 32-bit memory.\r
+ @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+ @param Mem64Node Resource info node for 64-bit memory.\r
+ @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+DegradeResource (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN PCI_RESOURCE_NODE *Mem32Node,\r
+ IN PCI_RESOURCE_NODE *PMem32Node,\r
+ IN PCI_RESOURCE_NODE *Mem64Node,\r
+ IN PCI_RESOURCE_NODE *PMem64Node\r
+ )\r
+{\r
+ BOOLEAN HasOprom;\r
+ PCI_IO_DEVICE *Temp;\r
+ LIST_ENTRY *CurrentLink;\r
+\r
+ //\r
+ // For RootBridge, PPB , P2C, go recursively to traverse all its children\r
+ // to find if this bridge and downstream has OptionRom.\r
+ //\r
+ HasOprom = FALSE;\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+ while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
+\r
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+ if (Temp->RomSize != 0) {\r
+ HasOprom = TRUE;\r
+ break;\r
+ }\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ //\r
+ // If bridge doesn't support Prefetchable\r
+ // memory64, degrade it to Prefetchable memory32\r
+ //\r
+ if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) {\r
+ MergeResourceTree (\r
+ PMem32Node,\r
+ PMem64Node,\r
+ TRUE\r
+ );\r
+ } else {\r
+ //\r
+ // if no PMem32 request and no OptionRom request, still keep PMem64. Otherwise degrade to PMem32\r
+ //\r
+ if ((PMem32Node != NULL && (PMem32Node->Length != 0 && Bridge->Parent != NULL)) || HasOprom) {\r
+ //\r
+ // Fixed the issue that there is no resource for 64-bit (above 4G)\r
+ //\r
+ MergeResourceTree (\r
+ PMem32Node,\r
+ PMem64Node,\r
+ TRUE\r
+ );\r
+ }\r
+ }\r
+\r
+\r
+ //\r
+ // If bridge doesn't support Mem64\r
+ // degrade it to mem32\r
+ //\r
+ if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) {\r
+ MergeResourceTree (\r
+ Mem32Node,\r
+ Mem64Node,\r
+ TRUE\r
+ );\r
+ }\r
+\r
+ //\r
+ // If bridge doesn't support Pmem32\r
+ // degrade it to mem32\r
+ //\r
+ if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) {\r
+ MergeResourceTree (\r
+ Mem32Node,\r
+ PMem32Node,\r
+ TRUE\r
+ );\r
+ }\r
+\r
+ //\r
+ // if bridge supports combined Pmem Mem decoding\r
+ // merge these two type of resource\r
+ //\r
+ if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) {\r
+ MergeResourceTree (\r
+ Mem32Node,\r
+ PMem32Node,\r
+ FALSE\r
+ );\r
+\r
+ MergeResourceTree (\r
+ Mem64Node,\r
+ PMem64Node,\r
+ FALSE\r
+ );\r
+ }\r
+}\r
+\r
+/**\r
+ Test whether bridge device support decode resource.\r
+\r
+ @param Bridge Bridge device instance.\r
+ @param Decode Decode type according to resource type.\r
+\r
+ @return TRUE The bridge device support decode resource.\r
+ @return FALSE The bridge device don't support decode resource.\r
+\r
+**/\r
+BOOLEAN\r
+BridgeSupportResourceDecode (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN UINT32 Decode\r
+ )\r
+{\r
+ if (((Bridge->Decodes) & Decode) != 0) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ This function is used to program the resource allocated\r
+ for each resource node under specified bridge.\r
+\r
+ @param Base Base address of resource to be progammed.\r
+ @param Bridge PCI resource node for the bridge device.\r
+\r
+ @retval EFI_SUCCESS Successfully to program all resouces\r
+ on given PCI bridge device.\r
+ @retval EFI_OUT_OF_RESOURCES Base is all one.\r
+\r
+**/\r
+EFI_STATUS\r
+ProgramResource (\r
+ IN UINT64 Base,\r
+ IN PCI_RESOURCE_NODE *Bridge\r
+ )\r
+{\r
+ LIST_ENTRY *CurrentLink;\r
+ PCI_RESOURCE_NODE *Node;\r
+ EFI_STATUS Status;\r
+\r
+ if (Base == gAllOne) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+ while (CurrentLink != &Bridge->ChildList) {\r
+\r
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+ if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) {\r
+\r
+ if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {\r
+ //\r
+ // Program the PCI Card Bus device\r
+ //\r
+ ProgramP2C (Base, Node);\r
+ } else {\r
+ //\r
+ // Program the PCI device BAR\r
+ //\r
+ ProgramBar (Base, Node);\r
+ }\r
+ } else {\r
+ //\r
+ // Program the PCI devices under this bridge\r
+ //\r
+ Status = ProgramResource (Base + Node->Offset, Node);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ ProgramPpbApperture (Base, Node);\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Program Bar register for PCI device.\r
+\r
+ @param Base Base address for PCI device resource to be progammed.\r
+ @param Node Point to resoure node structure.\r
+\r
+**/\r
+VOID\r
+ProgramBar (\r
+ IN UINT64 Base,\r
+ IN PCI_RESOURCE_NODE *Node\r
+ )\r
+{\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT64 Address;\r
+ UINT32 Address32;\r
+\r
+ ASSERT (Node->Bar < PCI_MAX_BAR);\r
+\r
+ //\r
+ // Check VF BAR\r
+ //\r
+ if (Node->Virtual) {\r
+ ProgramVfBar (Base, Node);\r
+ }\r
+\r
+ Address = 0;\r
+ PciIo = &(Node->PciDev->PciIo);\r
+\r
+ Address = Base + Node->Offset;\r
+\r
+ //\r
+ // Indicate pci bus driver has allocated\r
+ // resource for this device\r
+ // It might be a temporary solution here since\r
+ // pci device could have multiple bar\r
+ //\r
+ Node->PciDev->Allocated = TRUE;\r
+\r
+ switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {\r
+\r
+ case PciBarTypeIo16:\r
+ case PciBarTypeIo32:\r
+ case PciBarTypeMem32:\r
+ case PciBarTypePMem32:\r
+\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ (Node->PciDev->PciBar[Node->Bar]).Offset,\r
+ 1,\r
+ &Address\r
+ );\r
+\r
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+\r
+ break;\r
+\r
+ case PciBarTypeMem64:\r
+ case PciBarTypePMem64:\r
+\r
+ Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);\r
+\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ (Node->PciDev->PciBar[Node->Bar]).Offset,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Address32 = (UINT32) RShiftU64 (Address, 32);\r
+\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ Program IOV VF Bar register for PCI device.\r
+\r
+ @param Base Base address for PCI device resource to be progammed.\r
+ @param Node Point to resoure node structure.\r
+\r
+**/\r
+EFI_STATUS\r
+ProgramVfBar (\r
+ IN UINT64 Base,\r
+ IN PCI_RESOURCE_NODE *Node\r
+ )\r
+{\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT64 Address;\r
+ UINT32 Address32;\r
+\r
+ ASSERT (Node->Bar < PCI_MAX_BAR);\r
+ ASSERT (Node->Virtual);\r
+\r
+ Address = 0;\r
+ PciIo = &(Node->PciDev->PciIo);\r
+\r
+ Address = Base + Node->Offset;\r
+\r
+ //\r
+ // Indicate pci bus driver has allocated\r
+ // resource for this device\r
+ // It might be a temporary solution here since\r
+ // pci device could have multiple bar\r
+ //\r
+ Node->PciDev->Allocated = TRUE;\r
+\r
+ switch ((Node->PciDev->VfPciBar[Node->Bar]).BarType) {\r
+\r
+ case PciBarTypeMem32:\r
+ case PciBarTypePMem32:\r
+\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ (Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
+ 1,\r
+ &Address\r
+ );\r
+\r
+ Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;\r
+\r
+ DEBUG ((\r
+ EFI_D_INFO,\r
+ "PCI-IOV B%x.D%x.F%x - VF Bar (Offset - 0x%x) 32Mem (Address - 0x%x)\n",\r
+ (UINTN)Node->PciDev->BusNumber,\r
+ (UINTN)Node->PciDev->DeviceNumber,\r
+ (UINTN)Node->PciDev->FunctionNumber,\r
+ (UINTN)(Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
+ (UINTN)Address\r
+ ));\r
+\r
+ break;\r
+\r
+ case PciBarTypeMem64:\r
+ case PciBarTypePMem64:\r
+\r
+ Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);\r
+\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ (Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Address32 = (UINT32) RShiftU64 (Address, 32);\r
+\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ ((Node->PciDev->VfPciBar[Node->Bar]).Offset + 4),\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;\r
+\r
+ DEBUG ((\r
+ EFI_D_INFO,\r
+ "PCI-IOV B%x.D%x.F%x - VF Bar (Offset - 0x%x) 64Mem (Address - 0x%lx)\n",\r
+ (UINTN)Node->PciDev->BusNumber,\r
+ (UINTN)Node->PciDev->DeviceNumber,\r
+ (UINTN)Node->PciDev->FunctionNumber,\r
+ (UINTN)(Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
+ (UINT64)Address\r
+ ));\r
+\r
+ break;\r
+\r
+ case PciBarTypeIo16:\r
+ case PciBarTypeIo32:\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Program PCI-PCI bridge apperture.\r
+\r
+ @param Base Base address for resource.\r
+ @param Node Point to resoure node structure.\r
+\r
+**/\r
+VOID\r
+ProgramPpbApperture (\r
+ IN UINT64 Base,\r
+ IN PCI_RESOURCE_NODE *Node\r
+ )\r
+{\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT64 Address;\r
+ UINT32 Address32;\r
+\r
+ Address = 0;\r
+ //\r
+ // If no device resource of this PPB, return anyway\r
+ // Apperture is set default in the initialization code\r
+ //\r
+ if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) {\r
+ //\r
+ // For padding resource node, just ignore when programming\r
+ //\r
+ return ;\r
+ }\r
+\r
+ PciIo = &(Node->PciDev->PciIo);\r
+ Address = Base + Node->Offset;\r
+\r
+ //\r
+ // Indicate the PPB resource has been allocated\r
+ //\r
+ Node->PciDev->Allocated = TRUE;\r
+\r
+ switch (Node->Bar) {\r
+\r
+ case PPB_BAR_0:\r
+ case PPB_BAR_1:\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ (Node->PciDev->PciBar[Node->Bar]).Offset,\r
+ 1,\r
+ &Address\r
+ );\r
+\r
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
+\r
+ break;\r
+\r
+ case PPB_IO_RANGE:\r
+\r
+ Address32 = ((UINT32) (Address)) >> 8;\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ 0x1C,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Address32 >>= 8;\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x30,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Address32 = (UINT32) (Address + Node->Length - 1);\r
+ Address32 = ((UINT32) (Address32)) >> 8;\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ 0x1D,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Address32 >>= 8;\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x32,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
+ break;\r
+\r
+ case PPB_MEM32_RANGE:\r
+\r
+ Address32 = ((UINT32) (Address)) >> 16;\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x20,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Address32 = (UINT32) (Address + Node->Length - 1);\r
+ Address32 = ((UINT32) (Address32)) >> 16;\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x22,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
+ break;\r
+\r
+ case PPB_PMEM32_RANGE:\r
+ case PPB_PMEM64_RANGE:\r
+\r
+ Address32 = ((UINT32) (Address)) >> 16;\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x24,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Address32 = (UINT32) (Address + Node->Length - 1);\r
+ Address32 = ((UINT32) (Address32)) >> 16;\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x26,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Address32 = (UINT32) RShiftU64 (Address, 32);\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0x28,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Address32 = (UINT32) RShiftU64 ((Address + Node->Length - 1), 32);\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0x2C,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ Program parent bridge for Option Rom.\r
+\r
+ @param PciDevice Pci deivce instance.\r
+ @param OptionRomBase Base address for Optiona Rom.\r
+ @param Enable Enable or disable PCI memory.\r
+\r
+**/\r
+VOID\r
+ProgrameUpstreamBridgeForRom (\r
+ IN PCI_IO_DEVICE *PciDevice,\r
+ IN UINT32 OptionRomBase,\r
+ IN BOOLEAN Enable\r
+ )\r
+{\r
+ PCI_IO_DEVICE *Parent;\r
+ PCI_RESOURCE_NODE Node;\r
+ //\r
+ // For root bridge, just return.\r
+ //\r
+ Parent = PciDevice->Parent;\r
+ ZeroMem (&Node, sizeof (Node));\r
+ while (Parent != NULL) {\r
+ if (!IS_PCI_BRIDGE (&Parent->Pci)) {\r
+ break;\r
+ }\r
+\r
+ Node.PciDev = Parent;\r
+ Node.Length = PciDevice->RomSize;\r
+ Node.Alignment = 0;\r
+ Node.Bar = PPB_MEM32_RANGE;\r
+ Node.ResType = PciBarTypeMem32;\r
+ Node.Offset = 0;\r
+\r
+ //\r
+ // Program PPB to only open a single <= 16MB apperture\r
+ //\r
+ if (Enable) {\r
+ ProgramPpbApperture (OptionRomBase, &Node);\r
+ PCI_ENABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
+ } else {\r
+ InitializePpb (Parent);\r
+ PCI_DISABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
+ }\r
+\r
+ Parent = Parent->Parent;\r
+ }\r
+}\r
+\r
+/**\r
+ Test whether resource exists for a bridge.\r
+\r
+ @param Bridge Point to resource node for a bridge.\r
+\r
+ @retval TRUE There is resource on the given bridge.\r
+ @retval FALSE There isn't resource on the given bridge.\r
+\r
+**/\r
+BOOLEAN\r
+ResourceRequestExisted (\r
+ IN PCI_RESOURCE_NODE *Bridge\r
+ )\r
+{\r
+ if (Bridge != NULL) {\r
+ if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) {\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Initialize resource pool structure.\r
+\r
+ @param ResourcePool Point to resource pool structure. This pool\r
+ is reset to all zero when returned.\r
+ @param ResourceType Type of resource.\r
+\r
+**/\r
+VOID\r
+InitializeResourcePool (\r
+ IN OUT PCI_RESOURCE_NODE *ResourcePool,\r
+ IN PCI_BAR_TYPE ResourceType\r
+ )\r
+{\r
+ ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));\r
+ ResourcePool->ResType = ResourceType;\r
+ ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;\r
+ InitializeListHead (&ResourcePool->ChildList);\r
+}\r
+\r
+\r
+/**\r
+ Get all resource information for given Pci device.\r
+\r
+ @param PciDev Pci device instance.\r
+ @param IoBridge Io resource node.\r
+ @param Mem32Bridge 32-bit memory node.\r
+ @param PMem32Bridge 32-bit Pmemory node.\r
+ @param Mem64Bridge 64-bit memory node.\r
+ @param PMem64Bridge 64-bit PMemory node.\r
+ @param IoPool Link list header for Io resource.\r
+ @param Mem32Pool Link list header for 32-bit memory.\r
+ @param PMem32Pool Link list header for 32-bit Prefetchable memory.\r
+ @param Mem64Pool Link list header for 64-bit memory.\r
+ @param PMem64Pool Link list header for 64-bit Prefetchable memory.\r
+\r
+**/\r
+VOID\r
+GetResourceMap (\r
+ IN PCI_IO_DEVICE *PciDev,\r
+ IN PCI_RESOURCE_NODE **IoBridge,\r
+ IN PCI_RESOURCE_NODE **Mem32Bridge,\r
+ IN PCI_RESOURCE_NODE **PMem32Bridge,\r
+ IN PCI_RESOURCE_NODE **Mem64Bridge,\r
+ IN PCI_RESOURCE_NODE **PMem64Bridge,\r
+ IN PCI_RESOURCE_NODE *IoPool,\r
+ IN PCI_RESOURCE_NODE *Mem32Pool,\r
+ IN PCI_RESOURCE_NODE *PMem32Pool,\r
+ IN PCI_RESOURCE_NODE *Mem64Pool,\r
+ IN PCI_RESOURCE_NODE *PMem64Pool\r
+ )\r
+{\r
+\r
+ PCI_RESOURCE_NODE *Temp;\r
+ LIST_ENTRY *CurrentLink;\r
+\r
+ CurrentLink = IoPool->ChildList.ForwardLink;\r
+\r
+ //\r
+ // Get Io resource map\r
+ //\r
+ while (CurrentLink != &IoPool->ChildList) {\r
+\r
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+ if (Temp->PciDev == PciDev) {\r
+ *IoBridge = Temp;\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ //\r
+ // Get Mem32 resource map\r
+ //\r
+ CurrentLink = Mem32Pool->ChildList.ForwardLink;\r
+\r
+ while (CurrentLink != &Mem32Pool->ChildList) {\r
+\r
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+ if (Temp->PciDev == PciDev) {\r
+ *Mem32Bridge = Temp;\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ //\r
+ // Get Pmem32 resource map\r
+ //\r
+ CurrentLink = PMem32Pool->ChildList.ForwardLink;\r
+\r
+ while (CurrentLink != &PMem32Pool->ChildList) {\r
+\r
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+ if (Temp->PciDev == PciDev) {\r
+ *PMem32Bridge = Temp;\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ //\r
+ // Get Mem64 resource map\r
+ //\r
+ CurrentLink = Mem64Pool->ChildList.ForwardLink;\r
+\r
+ while (CurrentLink != &Mem64Pool->ChildList) {\r
+\r
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+ if (Temp->PciDev == PciDev) {\r
+ *Mem64Bridge = Temp;\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ //\r
+ // Get Pmem64 resource map\r
+ //\r
+ CurrentLink = PMem64Pool->ChildList.ForwardLink;\r
+\r
+ while (CurrentLink != &PMem64Pool->ChildList) {\r
+\r
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+ if (Temp->PciDev == PciDev) {\r
+ *PMem64Bridge = Temp;\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+}\r
+\r
+/**\r
+ Destory given resource tree.\r
+\r
+ @param Bridge PCI resource root node of resource tree.\r
+\r
+**/\r
+VOID\r
+DestroyResourceTree (\r
+ IN PCI_RESOURCE_NODE *Bridge\r
+ )\r
+{\r
+ PCI_RESOURCE_NODE *Temp;\r
+ LIST_ENTRY *CurrentLink;\r
+\r
+ while (!IsListEmpty (&Bridge->ChildList)) {\r
+\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+ ASSERT (Temp);\r
+\r
+ RemoveEntryList (CurrentLink);\r
+\r
+ if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {\r
+ DestroyResourceTree (Temp);\r
+ }\r
+\r
+ FreePool (Temp);\r
+ }\r
+}\r
+\r
+/**\r
+ Insert resource padding for P2C.\r
+\r
+ @param PciDev Pci device instance.\r
+ @param IoNode Resource info node for IO.\r
+ @param Mem32Node Resource info node for 32-bit memory.\r
+ @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+ @param Mem64Node Resource info node for 64-bit memory.\r
+ @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+ResourcePaddingForCardBusBridge (\r
+ IN PCI_IO_DEVICE *PciDev,\r
+ IN PCI_RESOURCE_NODE *IoNode,\r
+ IN PCI_RESOURCE_NODE *Mem32Node,\r
+ IN PCI_RESOURCE_NODE *PMem32Node,\r
+ IN PCI_RESOURCE_NODE *Mem64Node,\r
+ IN PCI_RESOURCE_NODE *PMem64Node\r
+ )\r
+{\r
+ PCI_RESOURCE_NODE *Node;\r
+\r
+ Node = NULL;\r
+\r
+ //\r
+ // Memory Base/Limit Register 0\r
+ // Bar 1 denodes memory range 0\r
+ //\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ 0x2000000,\r
+ 0x1ffffff,\r
+ 1,\r
+ PciBarTypeMem32,\r
+ PciResUsagePadding\r
+ );\r
+\r
+ InsertResourceNode (\r
+ Mem32Node,\r
+ Node\r
+ );\r
+\r
+ //\r
+ // Memory Base/Limit Register 1\r
+ // Bar 2 denodes memory range1\r
+ //\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ 0x2000000,\r
+ 0x1ffffff,\r
+ 2,\r
+ PciBarTypePMem32,\r
+ PciResUsagePadding\r
+ );\r
+\r
+ InsertResourceNode (\r
+ PMem32Node,\r
+ Node\r
+ );\r
+\r
+ //\r
+ // Io Base/Limit\r
+ // Bar 3 denodes io range 0\r
+ //\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ 0x100,\r
+ 0xff,\r
+ 3,\r
+ PciBarTypeIo16,\r
+ PciResUsagePadding\r
+ );\r
+\r
+ InsertResourceNode (\r
+ IoNode,\r
+ Node\r
+ );\r
+\r
+ //\r
+ // Io Base/Limit\r
+ // Bar 4 denodes io range 0\r
+ //\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ 0x100,\r
+ 0xff,\r
+ 4,\r
+ PciBarTypeIo16,\r
+ PciResUsagePadding\r
+ );\r
+\r
+ InsertResourceNode (\r
+ IoNode,\r
+ Node\r
+ );\r
+}\r
+\r
+/**\r
+ Program PCI Card device register for given resource node.\r
+\r
+ @param Base Base address of PCI Card device to be programmed.\r
+ @param Node Given resource node.\r
+\r
+**/\r
+VOID\r
+ProgramP2C (\r
+ IN UINT64 Base,\r
+ IN PCI_RESOURCE_NODE *Node\r
+ )\r
+{\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT64 Address;\r
+ UINT64 TempAddress;\r
+ UINT16 BridgeControl;\r
+\r
+ Address = 0;\r
+ PciIo = &(Node->PciDev->PciIo);\r
+\r
+ Address = Base + Node->Offset;\r
+\r
+ //\r
+ // Indicate pci bus driver has allocated\r
+ // resource for this device\r
+ // It might be a temporary solution here since\r
+ // pci device could have multiple bar\r
+ //\r
+ Node->PciDev->Allocated = TRUE;\r
+\r
+ switch (Node->Bar) {\r
+\r
+ case P2C_BAR_0:\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ (Node->PciDev->PciBar[Node->Bar]).Offset,\r
+ 1,\r
+ &Address\r
+ );\r
+\r
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
+ break;\r
+\r
+ case P2C_MEM_1:\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ PCI_CARD_MEMORY_BASE_0,\r
+ 1,\r
+ &Address\r
+ );\r
+\r
+ TempAddress = Address + Node->Length - 1;\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ PCI_CARD_MEMORY_LIMIT_0,\r
+ 1,\r
+ &TempAddress\r
+ );\r
+\r
+ if (Node->ResType == PciBarTypeMem32) {\r
+ //\r
+ // Set non-prefetchable bit\r
+ //\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ PCI_CARD_BRIDGE_CONTROL,\r
+ 1,\r
+ &BridgeControl\r
+ );\r
+\r
+ BridgeControl &= (UINT16) ~PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ PCI_CARD_BRIDGE_CONTROL,\r
+ 1,\r
+ &BridgeControl\r
+ );\r
+\r
+ } else {\r
+ //\r
+ // Set pre-fetchable bit\r
+ //\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ PCI_CARD_BRIDGE_CONTROL,\r
+ 1,\r
+ &BridgeControl\r
+ );\r
+\r
+ BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ PCI_CARD_BRIDGE_CONTROL,\r
+ 1,\r
+ &BridgeControl\r
+ );\r
+ }\r
+\r
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
+ Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;\r
+\r
+ break;\r
+\r
+ case P2C_MEM_2:\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ PCI_CARD_MEMORY_BASE_1,\r
+ 1,\r
+ &Address\r
+ );\r
+\r
+ TempAddress = Address + Node->Length - 1;\r
+\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ PCI_CARD_MEMORY_LIMIT_1,\r
+ 1,\r
+ &TempAddress\r
+ );\r
+\r
+ if (Node->ResType == PciBarTypeMem32) {\r
+\r
+ //\r
+ // Set non-prefetchable bit\r
+ //\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ PCI_CARD_BRIDGE_CONTROL,\r
+ 1,\r
+ &BridgeControl\r
+ );\r
+\r
+ BridgeControl &= (UINT16) ~(PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE);\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ PCI_CARD_BRIDGE_CONTROL,\r
+ 1,\r
+ &BridgeControl\r
+ );\r
+\r
+ } else {\r
+\r
+ //\r
+ // Set pre-fetchable bit\r
+ //\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ PCI_CARD_BRIDGE_CONTROL,\r
+ 1,\r
+ &BridgeControl\r
+ );\r
+\r
+ BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE;\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ PCI_CARD_BRIDGE_CONTROL,\r
+ 1,\r
+ &BridgeControl\r
+ );\r
+ }\r
+\r
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
+ Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;\r
+ break;\r
+\r
+ case P2C_IO_1:\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ PCI_CARD_IO_BASE_0_LOWER,\r
+ 1,\r
+ &Address\r
+ );\r
+\r
+ TempAddress = Address + Node->Length - 1;\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ PCI_CARD_IO_LIMIT_0_LOWER,\r
+ 1,\r
+ &TempAddress\r
+ );\r
+\r
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
+ Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;\r
+\r
+ break;\r
+\r
+ case P2C_IO_2:\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ PCI_CARD_IO_BASE_1_LOWER,\r
+ 1,\r
+ &Address\r
+ );\r
+\r
+ TempAddress = Address + Node->Length - 1;\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ PCI_CARD_IO_LIMIT_1_LOWER,\r
+ 1,\r
+ &TempAddress\r
+ );\r
+\r
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
+ Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ Create padding resource node.\r
+\r
+ @param PciDev Pci device instance.\r
+ @param IoNode Resource info node for IO.\r
+ @param Mem32Node Resource info node for 32-bit memory.\r
+ @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+ @param Mem64Node Resource info node for 64-bit memory.\r
+ @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+ApplyResourcePadding (\r
+ IN PCI_IO_DEVICE *PciDev,\r
+ IN PCI_RESOURCE_NODE *IoNode,\r
+ IN PCI_RESOURCE_NODE *Mem32Node,\r
+ IN PCI_RESOURCE_NODE *PMem32Node,\r
+ IN PCI_RESOURCE_NODE *Mem64Node,\r
+ IN PCI_RESOURCE_NODE *PMem64Node\r
+ )\r
+{\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
+ PCI_RESOURCE_NODE *Node;\r
+ UINT8 DummyBarIndex;\r
+\r
+ DummyBarIndex = 0;\r
+ Ptr = PciDev->ResourcePaddingDescriptors;\r
+\r
+ while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
+\r
+ if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {\r
+ if (Ptr->AddrLen != 0) {\r
+\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ Ptr->AddrLen,\r
+ Ptr->AddrRangeMax,\r
+ DummyBarIndex,\r
+ PciBarTypeIo16,\r
+ PciResUsagePadding\r
+ );\r
+ InsertResourceNode (\r
+ IoNode,\r
+ Node\r
+ );\r
+ }\r
+\r
+ Ptr++;\r
+ continue;\r
+ }\r
+\r
+ if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
+\r
+ if (Ptr->AddrSpaceGranularity == 32) {\r
+\r
+ //\r
+ // prefechable\r
+ //\r
+ if (Ptr->SpecificFlag == 0x6) {\r
+ if (Ptr->AddrLen != 0) {\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ Ptr->AddrLen,\r
+ Ptr->AddrRangeMax,\r
+ DummyBarIndex,\r
+ PciBarTypePMem32,\r
+ PciResUsagePadding\r
+ );\r
+ InsertResourceNode (\r
+ PMem32Node,\r
+ Node\r
+ );\r
+ }\r
+\r
+ Ptr++;\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Non-prefechable\r
+ //\r
+ if (Ptr->SpecificFlag == 0) {\r
+ if (Ptr->AddrLen != 0) {\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ Ptr->AddrLen,\r
+ Ptr->AddrRangeMax,\r
+ DummyBarIndex,\r
+ PciBarTypeMem32,\r
+ PciResUsagePadding\r
+ );\r
+ InsertResourceNode (\r
+ Mem32Node,\r
+ Node\r
+ );\r
+ }\r
+\r
+ Ptr++;\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (Ptr->AddrSpaceGranularity == 64) {\r
+\r
+ //\r
+ // prefechable\r
+ //\r
+ if (Ptr->SpecificFlag == 0x6) {\r
+ if (Ptr->AddrLen != 0) {\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ Ptr->AddrLen,\r
+ Ptr->AddrRangeMax,\r
+ DummyBarIndex,\r
+ PciBarTypePMem64,\r
+ PciResUsagePadding\r
+ );\r
+ InsertResourceNode (\r
+ PMem64Node,\r
+ Node\r
+ );\r
+ }\r
+\r
+ Ptr++;\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Non-prefechable\r
+ //\r
+ if (Ptr->SpecificFlag == 0) {\r
+ if (Ptr->AddrLen != 0) {\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ Ptr->AddrLen,\r
+ Ptr->AddrRangeMax,\r
+ DummyBarIndex,\r
+ PciBarTypeMem64,\r
+ PciResUsagePadding\r
+ );\r
+ InsertResourceNode (\r
+ Mem64Node,\r
+ Node\r
+ );\r
+ }\r
+\r
+ Ptr++;\r
+ continue;\r
+ }\r
+ }\r
+ }\r
+\r
+ Ptr++;\r
+ }\r
+}\r
+\r
+/**\r
+ Get padding resource for PCI-PCI bridge.\r
+\r
+ @param PciIoDevice PCI-PCI bridge device instance.\r
+\r
+ @note Feature flag PcdPciBusHotplugDeviceSupport determines\r
+ whether need to pad resource for them.\r
+**/\r
+VOID\r
+GetResourcePaddingPpb (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+ if (PciIoDevice->ResourcePaddingDescriptors == NULL) {\r
+ GetResourcePaddingForHpb (PciIoDevice);\r
+ }\r
+ }\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ PCI resouces support functions declaration 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
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_RESOURCE_SUPPORT_H_\r
+#define _EFI_PCI_RESOURCE_SUPPORT_H_\r
+\r
+typedef enum {\r
+ PciResUsageTypical = 0,\r
+ PciResUsagePadding,\r
+ PciResUsageOptionRomProcessing\r
+} PCI_RESOURCE_USAGE;\r
+\r
+#define PCI_RESOURCE_SIGNATURE SIGNATURE_32 ('p', 'c', 'r', 'c')\r
+\r
+typedef struct {\r
+ UINT32 Signature;\r
+ LIST_ENTRY Link;\r
+ LIST_ENTRY ChildList;\r
+ PCI_IO_DEVICE *PciDev;\r
+ UINT64 Alignment;\r
+ UINT64 Offset;\r
+ UINT8 Bar;\r
+ PCI_BAR_TYPE ResType;\r
+ UINT64 Length;\r
+ BOOLEAN Reserved;\r
+ PCI_RESOURCE_USAGE ResourceUsage;\r
+ BOOLEAN Virtual;\r
+} PCI_RESOURCE_NODE;\r
+\r
+#define RESOURCE_NODE_FROM_LINK(a) \\r
+ CR (a, PCI_RESOURCE_NODE, Link, PCI_RESOURCE_SIGNATURE)\r
+\r
+/**\r
+ The function is used to skip VGA range.\r
+\r
+ @param Start Returned start address including VGA range.\r
+ @param Length The length of VGA range.\r
+\r
+**/\r
+VOID\r
+SkipVGAAperture (\r
+ OUT UINT64 *Start,\r
+ IN UINT64 Length\r
+ );\r
+\r
+/**\r
+ This function is used to skip ISA aliasing aperture.\r
+\r
+ @param Start Returned start address including ISA aliasing aperture.\r
+ @param Length The length of ISA aliasing aperture.\r
+\r
+**/\r
+VOID\r
+SkipIsaAliasAperture (\r
+ OUT UINT64 *Start,\r
+ IN UINT64 Length\r
+ );\r
+\r
+/**\r
+ This function inserts a resource node into the resource list.\r
+ The resource list is sorted in descend order.\r
+\r
+ @param Bridge PCI resource node for bridge.\r
+ @param ResNode Resource node want to be inserted.\r
+\r
+**/\r
+VOID\r
+InsertResourceNode (\r
+ IN OUT PCI_RESOURCE_NODE *Bridge,\r
+ IN PCI_RESOURCE_NODE *ResNode\r
+ );\r
+\r
+/**\r
+ This routine is used to merge two different resource trees in need of\r
+ resoure degradation.\r
+\r
+ For example, if an upstream PPB doesn't support,\r
+ prefetchable memory decoding, the PCI bus driver will choose to call this function\r
+ to merge prefectchable memory resource list into normal memory list.\r
+\r
+ If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource\r
+ type.\r
+ If Dst is NULL or Res is NULL, ASSERT ().\r
+\r
+ @param Dst Point to destination resource tree.\r
+ @param Res Point to source resource tree.\r
+ @param TypeMerge If the TypeMerge is TRUE, Res resource type is changed to the type of\r
+ destination resource type.\r
+\r
+**/\r
+VOID\r
+MergeResourceTree (\r
+ IN PCI_RESOURCE_NODE *Dst,\r
+ IN PCI_RESOURCE_NODE *Res,\r
+ IN BOOLEAN TypeMerge\r
+ );\r
+\r
+/**\r
+ This function is used to calculate the IO16 aperture\r
+ for a bridge.\r
+\r
+ @param Bridge PCI resource node for bridge.\r
+\r
+**/\r
+VOID\r
+CalculateApertureIo16 (\r
+ IN PCI_RESOURCE_NODE *Bridge\r
+ );\r
+\r
+/**\r
+ This function is used to calculate the resource aperture\r
+ for a given bridge device.\r
+\r
+ @param Bridge PCI resouce node for given bridge device.\r
+\r
+**/\r
+VOID\r
+CalculateResourceAperture (\r
+ IN PCI_RESOURCE_NODE *Bridge\r
+ );\r
+\r
+/**\r
+ Get IO/Memory resource infor for given PCI device.\r
+\r
+ @param PciDev Pci device instance.\r
+ @param IoNode Resource info node for IO .\r
+ @param Mem32Node Resource info node for 32-bit memory.\r
+ @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+ @param Mem64Node Resource info node for 64-bit memory.\r
+ @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+GetResourceFromDevice (\r
+ IN PCI_IO_DEVICE *PciDev,\r
+ IN OUT PCI_RESOURCE_NODE *IoNode,\r
+ IN OUT PCI_RESOURCE_NODE *Mem32Node,\r
+ IN OUT PCI_RESOURCE_NODE *PMem32Node,\r
+ IN OUT PCI_RESOURCE_NODE *Mem64Node,\r
+ IN OUT PCI_RESOURCE_NODE *PMem64Node\r
+ );\r
+\r
+/**\r
+ This function is used to create a resource node.\r
+\r
+ @param PciDev Pci device instance.\r
+ @param Length Length of Io/Memory resource.\r
+ @param Alignment Alignment of resource.\r
+ @param Bar Bar index.\r
+ @param ResType Type of resource: IO/Memory.\r
+ @param ResUsage Resource usage.\r
+\r
+ @return PCI resource node created for given PCI device.\r
+ NULL means PCI resource node is not created.\r
+\r
+**/\r
+PCI_RESOURCE_NODE *\r
+CreateResourceNode (\r
+ IN PCI_IO_DEVICE *PciDev,\r
+ IN UINT64 Length,\r
+ IN UINT64 Alignment,\r
+ IN UINT8 Bar,\r
+ IN PCI_BAR_TYPE ResType,\r
+ IN PCI_RESOURCE_USAGE ResUsage\r
+ );\r
+\r
+/**\r
+ This function is used to extract resource request from\r
+ IOV VF device node list.\r
+\r
+ @param Bridge Pci device instance.\r
+ @param IoNode Resource info node for IO.\r
+ @param Mem32Node Resource info node for 32-bit memory.\r
+ @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+ @param Mem64Node Resource info node for 64-bit memory.\r
+ @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+PCI_RESOURCE_NODE *\r
+CreateVfResourceNode (\r
+ IN PCI_IO_DEVICE *PciDev,\r
+ IN UINT64 Length,\r
+ IN UINT64 Alignment,\r
+ IN UINT8 Bar,\r
+ IN PCI_BAR_TYPE ResType,\r
+ IN PCI_RESOURCE_USAGE ResUsage\r
+ );\r
+\r
+/**\r
+ This function is used to extract resource request from\r
+ device node list.\r
+\r
+ @param Bridge Pci device instance.\r
+ @param IoNode Resource info node for IO.\r
+ @param Mem32Node Resource info node for 32-bit memory.\r
+ @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+ @param Mem64Node Resource info node for 64-bit memory.\r
+ @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+CreateResourceMap (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN OUT PCI_RESOURCE_NODE *IoNode,\r
+ IN OUT PCI_RESOURCE_NODE *Mem32Node,\r
+ IN OUT PCI_RESOURCE_NODE *PMem32Node,\r
+ IN OUT PCI_RESOURCE_NODE *Mem64Node,\r
+ IN OUT PCI_RESOURCE_NODE *PMem64Node\r
+ );\r
+\r
+/**\r
+ This function is used to do the resource padding for a specific platform.\r
+\r
+ @param PciDev Pci device instance.\r
+ @param IoNode Resource info node for IO.\r
+ @param Mem32Node Resource info node for 32-bit memory.\r
+ @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+ @param Mem64Node Resource info node for 64-bit memory.\r
+ @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+ResourcePaddingPolicy (\r
+ IN PCI_IO_DEVICE *PciDev,\r
+ IN PCI_RESOURCE_NODE *IoNode,\r
+ IN PCI_RESOURCE_NODE *Mem32Node,\r
+ IN PCI_RESOURCE_NODE *PMem32Node,\r
+ IN PCI_RESOURCE_NODE *Mem64Node,\r
+ IN PCI_RESOURCE_NODE *PMem64Node\r
+ );\r
+\r
+/**\r
+ This function is used to degrade resource if the upstream bridge\r
+ doesn't support certain resource. Degradation path is\r
+ PMEM64 -> MEM64 -> MEM32\r
+ PMEM64 -> PMEM32 -> MEM32\r
+ IO32 -> IO16.\r
+\r
+ @param Bridge Pci device instance.\r
+ @param Mem32Node Resource info node for 32-bit memory.\r
+ @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+ @param Mem64Node Resource info node for 64-bit memory.\r
+ @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+DegradeResource (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN PCI_RESOURCE_NODE *Mem32Node,\r
+ IN PCI_RESOURCE_NODE *PMem32Node,\r
+ IN PCI_RESOURCE_NODE *Mem64Node,\r
+ IN PCI_RESOURCE_NODE *PMem64Node\r
+ );\r
+\r
+/**\r
+ Test whether bridge device support decode resource.\r
+\r
+ @param Bridge Bridge device instance.\r
+ @param Decode Decode type according to resource type.\r
+\r
+ @return TRUE The bridge device support decode resource.\r
+ @return FALSE The bridge device don't support decode resource.\r
+\r
+**/\r
+BOOLEAN\r
+BridgeSupportResourceDecode (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN UINT32 Decode\r
+ );\r
+\r
+/**\r
+ This function is used to program the resource allocated\r
+ for each resource node under specified bridge.\r
+\r
+ @param Base Base address of resource to be progammed.\r
+ @param Bridge PCI resource node for the bridge device.\r
+\r
+ @retval EFI_SUCCESS Successfully to program all resouces\r
+ on given PCI bridge device.\r
+ @retval EFI_OUT_OF_RESOURCES Base is all one.\r
+\r
+**/\r
+EFI_STATUS\r
+ProgramResource (\r
+ IN UINT64 Base,\r
+ IN PCI_RESOURCE_NODE *Bridge\r
+ );\r
+\r
+/**\r
+ Program Bar register for PCI device.\r
+\r
+ @param Base Base address for PCI device resource to be progammed.\r
+ @param Node Point to resoure node structure.\r
+\r
+**/\r
+VOID\r
+ProgramBar (\r
+ IN UINT64 Base,\r
+ IN PCI_RESOURCE_NODE *Node\r
+ );\r
+\r
+/**\r
+ Program IOV VF Bar register for PCI device.\r
+\r
+ @param Base Base address for PCI device resource to be progammed.\r
+ @param Node Point to resoure node structure.\r
+\r
+**/\r
+EFI_STATUS\r
+ProgramVfBar (\r
+ IN UINT64 Base,\r
+ IN PCI_RESOURCE_NODE *Node\r
+ );\r
+\r
+/**\r
+ Program PCI-PCI bridge apperture.\r
+\r
+ @param Base Base address for resource.\r
+ @param Node Point to resoure node structure.\r
+\r
+**/\r
+VOID\r
+ProgramPpbApperture (\r
+ IN UINT64 Base,\r
+ IN PCI_RESOURCE_NODE *Node\r
+ );\r
+\r
+/**\r
+ Program parent bridge for Option Rom.\r
+\r
+ @param PciDevice Pci deivce instance.\r
+ @param OptionRomBase Base address for Optiona Rom.\r
+ @param Enable Enable or disable PCI memory.\r
+\r
+**/\r
+VOID\r
+ProgrameUpstreamBridgeForRom (\r
+ IN PCI_IO_DEVICE *PciDevice,\r
+ IN UINT32 OptionRomBase,\r
+ IN BOOLEAN Enable\r
+ );\r
+\r
+/**\r
+ Test whether resource exists for a bridge.\r
+\r
+ @param Bridge Point to resource node for a bridge.\r
+\r
+ @retval TRUE There is resource on the given bridge.\r
+ @retval FALSE There isn't resource on the given bridge.\r
+\r
+**/\r
+BOOLEAN\r
+ResourceRequestExisted (\r
+ IN PCI_RESOURCE_NODE *Bridge\r
+ );\r
+\r
+/**\r
+ Initialize resource pool structure.\r
+\r
+ @param ResourcePool Point to resource pool structure. This pool\r
+ is reset to all zero when returned.\r
+ @param ResourceType Type of resource.\r
+\r
+**/\r
+VOID\r
+InitializeResourcePool (\r
+ IN OUT PCI_RESOURCE_NODE *ResourcePool,\r
+ IN PCI_BAR_TYPE ResourceType\r
+ );\r
+\r
+/**\r
+ Get all resource information for given Pci device.\r
+\r
+ @param PciDev Pci device instance.\r
+ @param IoBridge Io resource node.\r
+ @param Mem32Bridge 32-bit memory node.\r
+ @param PMem32Bridge 32-bit Pmemory node.\r
+ @param Mem64Bridge 64-bit memory node.\r
+ @param PMem64Bridge 64-bit PMemory node.\r
+ @param IoPool Link list header for Io resource.\r
+ @param Mem32Pool Link list header for 32-bit memory.\r
+ @param PMem32Pool Link list header for 32-bit Prefetchable memory.\r
+ @param Mem64Pool Link list header for 64-bit memory.\r
+ @param PMem64Pool Link list header for 64-bit Prefetchable memory.\r
+\r
+**/\r
+VOID\r
+GetResourceMap (\r
+ IN PCI_IO_DEVICE *PciDev,\r
+ IN PCI_RESOURCE_NODE **IoBridge,\r
+ IN PCI_RESOURCE_NODE **Mem32Bridge,\r
+ IN PCI_RESOURCE_NODE **PMem32Bridge,\r
+ IN PCI_RESOURCE_NODE **Mem64Bridge,\r
+ IN PCI_RESOURCE_NODE **PMem64Bridge,\r
+ IN PCI_RESOURCE_NODE *IoPool,\r
+ IN PCI_RESOURCE_NODE *Mem32Pool,\r
+ IN PCI_RESOURCE_NODE *PMem32Pool,\r
+ IN PCI_RESOURCE_NODE *Mem64Pool,\r
+ IN PCI_RESOURCE_NODE *PMem64Pool\r
+ );\r
+\r
+/**\r
+ Destory given resource tree.\r
+\r
+ @param Bridge PCI resource root node of resource tree.\r
+\r
+**/\r
+VOID\r
+DestroyResourceTree (\r
+ IN PCI_RESOURCE_NODE *Bridge\r
+ );\r
+\r
+/**\r
+ Insert resource padding for P2C.\r
+\r
+ @param PciDev Pci device instance.\r
+ @param IoNode Resource info node for IO.\r
+ @param Mem32Node Resource info node for 32-bit memory.\r
+ @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+ @param Mem64Node Resource info node for 64-bit memory.\r
+ @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+ResourcePaddingForCardBusBridge (\r
+ IN PCI_IO_DEVICE *PciDev,\r
+ IN PCI_RESOURCE_NODE *IoNode,\r
+ IN PCI_RESOURCE_NODE *Mem32Node,\r
+ IN PCI_RESOURCE_NODE *PMem32Node,\r
+ IN PCI_RESOURCE_NODE *Mem64Node,\r
+ IN PCI_RESOURCE_NODE *PMem64Node\r
+ );\r
+\r
+/**\r
+ Program PCI Card device register for given resource node.\r
+\r
+ @param Base Base address of PCI Card device to be programmed.\r
+ @param Node Given resource node.\r
+\r
+**/\r
+VOID\r
+ProgramP2C (\r
+ IN UINT64 Base,\r
+ IN PCI_RESOURCE_NODE *Node\r
+ );\r
+\r
+/**\r
+ Create padding resource node.\r
+\r
+ @param PciDev Pci device instance.\r
+ @param IoNode Resource info node for IO.\r
+ @param Mem32Node Resource info node for 32-bit memory.\r
+ @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+ @param Mem64Node Resource info node for 64-bit memory.\r
+ @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+ApplyResourcePadding (\r
+ IN PCI_IO_DEVICE *PciDev,\r
+ IN PCI_RESOURCE_NODE *IoNode,\r
+ IN PCI_RESOURCE_NODE *Mem32Node,\r
+ IN PCI_RESOURCE_NODE *PMem32Node,\r
+ IN PCI_RESOURCE_NODE *Mem64Node,\r
+ IN PCI_RESOURCE_NODE *PMem64Node\r
+ );\r
+\r
+/**\r
+ Get padding resource for PCI-PCI bridge.\r
+\r
+ @param PciIoDevice PCI-PCI bridge device instance.\r
+\r
+ @note Feature flag PcdPciBusHotplugDeviceSupport determines\r
+ whether need to pad resource for them.\r
+**/\r
+VOID\r
+GetResourcePaddingPpb (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Set up ROM Table 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
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+//\r
+// PCI ROM image information\r
+//\r
+typedef struct {\r
+ EFI_HANDLE ImageHandle;\r
+ UINTN Seg;\r
+ UINT8 Bus;\r
+ UINT8 Dev;\r
+ UINT8 Func;\r
+ UINT64 RomAddress;\r
+ UINT64 RomLength;\r
+} EFI_PCI_ROM_IMAGE_MAPPING;\r
+\r
+UINTN mNumberOfPciRomImages = 0;\r
+UINTN mMaxNumberOfPciRomImages = 0;\r
+EFI_PCI_ROM_IMAGE_MAPPING *mRomImageTable = NULL;\r
+\r
+/**\r
+ Add the Rom Image to internal database for later PCI light enumeration.\r
+\r
+ @param ImageHandle Option Rom image handle.\r
+ @param Seg Segment of PCI space.\r
+ @param Bus Bus NO of PCI space.\r
+ @param Dev Dev NO of PCI space.\r
+ @param Func Func NO of PCI space.\r
+ @param RomAddress Base address of OptionRom.\r
+ @param RomLength Length of rom image.\r
+\r
+**/\r
+VOID\r
+PciRomAddImageMapping (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN UINTN Seg,\r
+ IN UINT8 Bus,\r
+ IN UINT8 Dev,\r
+ IN UINT8 Func,\r
+ IN UINT64 RomAddress,\r
+ IN UINT64 RomLength\r
+ )\r
+{\r
+ EFI_PCI_ROM_IMAGE_MAPPING *TempMapping;\r
+\r
+ if (mNumberOfPciRomImages >= mMaxNumberOfPciRomImages) {\r
+\r
+ mMaxNumberOfPciRomImages += 0x20;\r
+\r
+ TempMapping = NULL;\r
+ TempMapping = AllocatePool (mMaxNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING));\r
+ if (TempMapping == NULL) {\r
+ return ;\r
+ }\r
+\r
+ CopyMem (TempMapping, mRomImageTable, mNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING));\r
+\r
+ if (mRomImageTable != NULL) {\r
+ FreePool (mRomImageTable);\r
+ }\r
+\r
+ mRomImageTable = TempMapping;\r
+ }\r
+\r
+ mRomImageTable[mNumberOfPciRomImages].ImageHandle = ImageHandle;\r
+ mRomImageTable[mNumberOfPciRomImages].Seg = Seg;\r
+ mRomImageTable[mNumberOfPciRomImages].Bus = Bus;\r
+ mRomImageTable[mNumberOfPciRomImages].Dev = Dev;\r
+ mRomImageTable[mNumberOfPciRomImages].Func = Func;\r
+ mRomImageTable[mNumberOfPciRomImages].RomAddress = RomAddress;\r
+ mRomImageTable[mNumberOfPciRomImages].RomLength = RomLength;\r
+ mNumberOfPciRomImages++;\r
+}\r
+\r
+/**\r
+ Get Option rom driver's mapping for PCI device.\r
+\r
+ @param PciIoDevice Device instance.\r
+\r
+ @retval TRUE Found Image mapping.\r
+ @retval FALSE Cannot found image mapping.\r
+\r
+**/\r
+BOOLEAN\r
+PciRomGetImageMapping (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+ UINTN Index;\r
+ BOOLEAN Found;\r
+\r
+ PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;\r
+ Found = FALSE;\r
+\r
+ for (Index = 0; Index < mNumberOfPciRomImages; Index++) {\r
+ if (mRomImageTable[Index].Seg == PciRootBridgeIo->SegmentNumber &&\r
+ mRomImageTable[Index].Bus == PciIoDevice->BusNumber &&\r
+ mRomImageTable[Index].Dev == PciIoDevice->DeviceNumber &&\r
+ mRomImageTable[Index].Func == PciIoDevice->FunctionNumber ) {\r
+ Found = TRUE;\r
+\r
+ if (mRomImageTable[Index].ImageHandle != NULL) {\r
+ AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle);\r
+ } else {\r
+ PciIoDevice->PciIo.RomImage = (VOID *) (UINTN) mRomImageTable[Index].RomAddress;\r
+ PciIoDevice->PciIo.RomSize = (UINTN) mRomImageTable[Index].RomLength;\r
+ }\r
+ }\r
+ }\r
+\r
+ return Found;\r
+}\r
--- /dev/null
+/** @file\r
+ Set up ROM Table 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
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_ROM_TABLE_H_\r
+#define _EFI_PCI_ROM_TABLE_H_\r
+\r
+/**\r
+ Add the Rom Image to internal database for later PCI light enumeration.\r
+\r
+ @param ImageHandle Option Rom image handle.\r
+ @param Seg Segment of PCI space.\r
+ @param Bus Bus NO of PCI space.\r
+ @param Dev Dev NO of PCI space.\r
+ @param Func Func NO of PCI space.\r
+ @param RomAddress Base address of OptionRom.\r
+ @param RomLength Length of rom image.\r
+\r
+**/\r
+VOID\r
+PciRomAddImageMapping (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN UINTN Seg,\r
+ IN UINT8 Bus,\r
+ IN UINT8 Dev,\r
+ IN UINT8 Func,\r
+ IN UINT64 RomAddress,\r
+ IN UINT64 RomLength\r
+ );\r
+\r
+/**\r
+ Get Option rom driver's mapping for PCI device.\r
+\r
+ @param PciIoDevice Device instance.\r
+\r
+ @retval TRUE Found Image mapping.\r
+ @retval FALSE Cannot found image mapping.\r
+\r
+**/\r
+BOOLEAN\r
+PciRomGetImageMapping (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ );\r
+\r
+#endif\r
# If FALSE, DXE IPL will not support UEFI decompression to save space.\r
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress|TRUE|BOOLEAN|0x0001200c\r
\r
+ ## This PCD specifies whether PciBus supports the hot plug device.\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport|TRUE|BOOLEAN|0x0001003d\r
+\r
+ ## This PCD specifies whether the Single Root I/O virtualization support.\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSupport|TRUE|BOOLEAN|0x10000044\r
+\r
+ ## This PCD specifies whether the Alternative Routing-ID support.\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport|TRUE|BOOLEAN|0x10000045\r
+\r
+ ## This PCD specifies whether the Multi Root I/O virtualization support.\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport|FALSE|BOOLEAN|0x10000046\r
+\r
+\r
[PcdsFeatureFlag.IA32]\r
##\r
# This feature flag specifies whether DxeIpl switches to long mode to enter DXE phase.\r
## FFS filename to find the ACPI tables\r
gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile|{ 0x25, 0x4e, 0x37, 0x7e, 0x01, 0x8e, 0xee, 0x4f, 0x87, 0xf2, 0x39, 0xc, 0x23, 0xc6, 0x6, 0xcd }|VOID*|16\r
\r
+ ## Single root I/O virtualization virtual function memory BAR alignment\r
+ # BITN set indicates 2 of n+12 power\r
+ # BIT0 set indicates 4KB alignment\r
+ # BIT1 set indicates 8KB alignment\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize|0x1|UINT32|0x10000047\r
+\r
[PcdsFixedAtBuild,PcdsPatchableInModule]\r
## Maximun number of performance log entries during PEI phase.\r
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries|40|UINT8|0x0001002f\r
[Components.common]\r
MdeModulePkg/Application/HelloWorld/HelloWorld.inf\r
\r
+ MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf\r
+ MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf\r
MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf\r
MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf\r
MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf\r