--- /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 <FrameworkDxe.h>\r
+\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 Revision;\r
+ UINT64 SubVendorId;\r
+ UINT64 SubDeviceId;\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 Revision,\r
+ IN UINTN SubVendorId,\r
+ IN UINTN SubDeviceId,\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 Revision,\r
+ IN UINTN SubVendorId,\r
+ IN UINTN SubDeviceId,\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->Revision != DEVICE_ID_NOCARE) {\r
+ if (Revision != Header->Revision) {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (Header->SubVendorId != DEVICE_ID_NOCARE) {\r
+ if (SubVendorId != Header->SubVendorId) {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (Header->SubDeviceId != DEVICE_ID_NOCARE) {\r
+ if (SubDeviceId != Header->SubDeviceId) {\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