+++ /dev/null
-/** @file\r
- The implementation of PCI incompatible device support libary.\r
-\r
-Copyright (c) 2007 Intel Corporation. All rights reserved. <BR>\r
-This software and associated documentation (if any) is furnished\r
-under a license and may only be used or copied in accordance\r
-with the terms of the license. Except as permitted by such\r
-license, no part of this software or documentation may be\r
-reproduced, stored in a retrieval system, or transmitted in any\r
-form or by any means without the express written consent of\r
-Intel Corporation.\r
-\r
-**/\r
-\r
-#include "IncompatiblePciDeviceList.h"\r
-\r
-/**\r
- Check whether two PCI devices matched\r
-\r
- @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.\r
- @param Header A pointer to EFI_PCI_DEVICE_INFO.\r
-\r
- @retval returns EFI_SUCCESS if two PCI device matched.\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-DeviceCheck (\r
- IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,\r
- IN EFI_PCI_DEVICE_INFO *Header\r
- )\r
-{\r
- //\r
- // See if the Header matches the parameters passed in\r
- //\r
- if (Header->VendorID != DEVICE_ID_NOCARE) {\r
- if (PciDeviceInfo->VendorID != Header->VendorID) {\r
- return EFI_UNSUPPORTED;\r
- }\r
- }\r
-\r
- if (Header->DeviceID != DEVICE_ID_NOCARE) {\r
- if (PciDeviceInfo->DeviceID != Header->DeviceID) {\r
- return EFI_UNSUPPORTED;\r
- }\r
- }\r
-\r
- if (Header->RevisionID != DEVICE_ID_NOCARE) {\r
- if (PciDeviceInfo->RevisionID != Header->RevisionID) {\r
- return EFI_UNSUPPORTED;\r
- }\r
- }\r
-\r
- if (Header->SubsystemVendorID != DEVICE_ID_NOCARE) {\r
- if (PciDeviceInfo->SubsystemVendorID != Header->SubsystemVendorID) {\r
- return EFI_UNSUPPORTED;\r
- }\r
- }\r
-\r
- if (Header->SubsystemID != DEVICE_ID_NOCARE) {\r
- if (PciDeviceInfo->SubsystemID != Header->SubsystemID) {\r
- return EFI_UNSUPPORTED;\r
- }\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Check the incompatible device list for ACPI resource update and return\r
- the configuration\r
-\r
- This function searches the incompatible device list according to request\r
- information. If the PCI device belongs to the devices list, corresponding\r
- configuration informtion will be returned, in the meantime return EFI_SUCCESS.\r
-\r
- @param PciDeviceInfo A pointer to PCI device information.\r
- @param Configuration Returned information.\r
-\r
- @retval returns EFI_SUCCESS if check incompatible device ok.\r
- Otherwise return EFI_UNSUPPORTED.\r
-**/\r
-RETURN_STATUS\r
-EFIAPI\r
-PciResourceUpdateCheck (\r
- IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,\r
- OUT VOID *Configuration\r
- )\r
-{\r
- UINT64 Tag;\r
- UINT64 *ListPtr;\r
- UINT64 *TempListPtr;\r
- EFI_PCI_DEVICE_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
- ASSERT (PciDeviceInfo != NULL);\r
-\r
- //\r
- // Initialize the return value to NULL\r
- //\r
- * (VOID **) Configuration = NULL;\r
-\r
- ListPtr = IncompatiblePciDeviceListForResource;\r
- while (*ListPtr != LIST_END_TAG) {\r
-\r
- Tag = *ListPtr;\r
-\r
- switch (Tag) {\r
- case DEVICE_INF_TAG:\r
- Header = (EFI_PCI_DEVICE_INFO *) (ListPtr + 1);\r
- ListPtr = ListPtr + 1 + sizeof (EFI_PCI_DEVICE_INFO) / sizeof (UINT64);\r
-\r
- if (DeviceCheck (PciDeviceInfo, Header) != EFI_SUCCESS) {\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 a acpi resource node\r
- //\r
- if (Index == 0) {\r
- return EFI_ABORTED;\r
- }\r
-\r
- AcpiPtr = AllocateZeroPool (\r
- sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * Index + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
- );\r
-\r
- OldAcpiPtr = AcpiPtr;\r
-\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
-\r
-/**\r
- Check the incompatible device list and return configuraton register mask values.\r
-\r
- This function searches the incompatible device list according to request\r
- information. If the PCI device belongs to the devices list, corresponding\r
- configuration informtion will be returned, in the meantime return EFI_SUCCESS.\r
-\r
- @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.\r
- @param AccessType Access Type, READ or WRITE.\r
- @param Offset The address within the PCI configuration space.\r
- @param Configuration Returned information.\r
-\r
- @retval returns EFI_SUCCESS if check incompatible device ok.\r
- Otherwise return EFI_UNSUPPORTED.\r
-**/\r
-RETURN_STATUS\r
-EFIAPI\r
-PciRegisterUpdateCheck (\r
- IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,\r
- IN UINT64 AccessType,\r
- IN UINT64 Offset,\r
- OUT VOID *Configuration\r
- )\r
-{\r
- EFI_PCI_DEVICE_INFO *Header;\r
- UINT64 Tag;\r
- UINT64 *ListPtr;\r
- EFI_PCI_REGISTER_VALUE_DATA *RegisterPtr;\r
- EFI_PCI_REGISTER_VALUE_DATA *Dsc;\r
-\r
- ASSERT (PciDeviceInfo != NULL);\r
-\r
- ListPtr = IncompatiblePciDeviceListForRegister;\r
-\r
- //\r
- // Initialize the return value to NULL\r
- //\r
- * (VOID **) Configuration = NULL;\r
-\r
- while (*ListPtr != LIST_END_TAG) {\r
-\r
- Tag = *ListPtr;\r
-\r
- switch (Tag) {\r
- case DEVICE_INF_TAG:\r
- Header = (EFI_PCI_DEVICE_INFO *) (ListPtr + 1);\r
- ListPtr = ListPtr + 1 + sizeof (EFI_PCI_DEVICE_INFO) / sizeof (UINT64);\r
-\r
- //\r
- // Check whether the PCI device matches the device in the incompatible devices list?\r
- // If not, ship next\r
- //\r
- if (DeviceCheck (PciDeviceInfo, Header) != EFI_SUCCESS) {\r
- continue;\r
- }\r
-\r
- //\r
- // Matched an item, check whether access matches?\r
- //\r
- for (; *ListPtr == DEVICE_RES_TAG;) {\r
- ListPtr ++;\r
- if (((EFI_PCI_REGISTER_VALUE_DESCRIPTOR *)ListPtr)->Offset == (Offset & 0xfc)) {\r
- if (((EFI_PCI_REGISTER_VALUE_DESCRIPTOR *)ListPtr)->AccessType == AccessType) {\r
-\r
- Dsc = (EFI_PCI_REGISTER_VALUE_DATA *) (ListPtr + 2);\r
- RegisterPtr = AllocateZeroPool (sizeof (EFI_PCI_REGISTER_VALUE_DATA));\r
-\r
- RegisterPtr->AndValue = Dsc->AndValue;\r
- RegisterPtr->OrValue = Dsc->OrValue;\r
-\r
- *(VOID **) Configuration = RegisterPtr;\r
-\r
- return EFI_SUCCESS;\r
- }\r
- }\r
- ListPtr += sizeof (EFI_PCI_REGISTER_VALUE_DESCRIPTOR) / (sizeof (UINT64));\r
- }\r
- return EFI_UNSUPPORTED;\r
-\r
- case DEVICE_RES_TAG:\r
- //\r
- // Adjust the pointer to the next item\r
- //\r
- ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_REGISTER_VALUE_DESCRIPTOR)) / sizeof (UINT64));\r
- break;\r
-\r
- default:\r
- return EFI_UNSUPPORTED;\r
- }\r
- }\r
-\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r
-/**\r
- Check the incompatible device list for access width incompatibility and\r
- return the configuration\r
-\r
- This function searches the incompatible device list for access width\r
- incompatibility according to request information. If the PCI device\r
- belongs to the devices list, corresponding configuration informtion\r
- will be returned, in the meantime return EFI_SUCCESS.\r
-\r
- @param PciDeviceInfo A pointer to PCI device information.\r
- @param AccessType Access type, READ or WRITE.\r
- @param Offset The address within the PCI configuration space.\r
- @param AccessWidth Access width needs to check incompatibility.\r
- @param Configuration Returned information.\r
-\r
- @retval returns EFI_SUCCESS if check incompatible device ok.\r
- Otherwise return EFI_UNSUPPORTED.\r
-**/\r
-RETURN_STATUS\r
-EFIAPI\r
-PciRegisterAccessCheck (\r
- IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,\r
- IN UINT64 AccessType,\r
- IN UINT64 Offset,\r
- IN UINT64 AccessWidth,\r
- OUT VOID *Configuration\r
- )\r
-{\r
- EFI_PCI_DEVICE_INFO *Header;\r
- UINT64 Tag;\r
- UINT64 *ListPtr;\r
- EFI_PCI_REGISTER_ACCESS_DATA *RegisterPtr;\r
- EFI_PCI_REGISTER_ACCESS_DATA *Dsc;\r
-\r
- ASSERT (PciDeviceInfo != NULL);\r
-\r
- ListPtr = DeviceListForAccessWidth;\r
-\r
- //\r
- // Initialize the return value to NULL\r
- //\r
- * (VOID **) Configuration = NULL;\r
-\r
- while (*ListPtr != LIST_END_TAG) {\r
-\r
- Tag = *ListPtr;\r
-\r
- switch (Tag) {\r
- case DEVICE_INF_TAG:\r
- Header = (EFI_PCI_DEVICE_INFO *) (ListPtr + 1);\r
- ListPtr = ListPtr + 1 + sizeof (EFI_PCI_DEVICE_INFO) / sizeof (UINT64);\r
-\r
- //\r
- // Check whether the PCI device matches the device in the incompatible devices list?\r
- // If not, ship next\r
- //\r
- if (DeviceCheck (PciDeviceInfo, Header) != EFI_SUCCESS) {\r
- continue;\r
- }\r
-\r
- //\r
- // Matched an item, check whether access matches?\r
- //\r
- for (; *ListPtr == DEVICE_RES_TAG;) {\r
- ListPtr ++;\r
- if (((EFI_PCI_REGISTER_ACCESS_DESCRIPTOR *) ListPtr)->AccessType == AccessType &&\r
- ((EFI_PCI_REGISTER_ACCESS_DESCRIPTOR *) ListPtr)->AccessWidth == AccessWidth ) {\r
-\r
- Dsc = (EFI_PCI_REGISTER_ACCESS_DATA *) (ListPtr + 2);\r
-\r
- if((Dsc->StartOffset <= Offset) && (Dsc->EndOffset > Offset)) {\r
-\r
- RegisterPtr = AllocateZeroPool (sizeof (EFI_PCI_REGISTER_ACCESS_DATA));\r
-\r
- RegisterPtr->StartOffset = Dsc->StartOffset;\r
- RegisterPtr->EndOffset = Dsc->EndOffset;\r
- RegisterPtr->Width = Dsc->Width;\r
-\r
- *(VOID **) Configuration = RegisterPtr;\r
-\r
- return EFI_SUCCESS;\r
- }\r
- }\r
- ListPtr += sizeof (EFI_PCI_REGISTER_ACCESS_DESCRIPTOR) / (sizeof (UINT64));\r
- }\r
- return EFI_UNSUPPORTED;\r
-\r
- case DEVICE_RES_TAG:\r
- //\r
- // Adjust the pointer to the next item\r
- //\r
- ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_REGISTER_ACCESS_DESCRIPTOR)) / sizeof (UINT64));\r
- break;\r
-\r
- default:\r
- return EFI_UNSUPPORTED;\r
- }\r
- }\r
-\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r