/** @file\r
EFI PCI IO protocol functions implementation for PCI Bus module.\r
\r
-Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>\r
-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
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include "PciBus.h"\r
\r
+extern EDKII_IOMMU_PROTOCOL *mIoMmuProtocol;\r
+\r
//\r
// Pci Io Protocol Interface\r
//\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
IN UINT64 *Offset\r
)\r
{\r
- if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ if ((UINT32)Width >= EfiPciIoWidthMaximum) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
{\r
UINT64 ExtendOffset;\r
\r
- if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ if ((UINT32)Width >= EfiPciIoWidthMaximum) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
\r
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
\r
- if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ if ((UINT32)Width >= EfiPciIoWidthMaximum) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
\r
//\r
// If request is not aligned, then convert request to EfiPciIoWithXXXUint8\r
- // \r
+ //\r
if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {\r
if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {\r
Status = PciIoMemRead (This, Width, BarIndex, Offset, 1, Result);\r
} while (TRUE);\r
}\r
}\r
- \r
+\r
Status = PciIoDevice->PciRootBridgeIo->PollMem (\r
PciIoDevice->PciRootBridgeIo,\r
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
);\r
\r
if (EFI_ERROR (Status)) {\r
- ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,\r
+ PciIoDevice->DevicePath\r
+ );\r
}\r
\r
return Status;\r
\r
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
\r
- if (Width < 0 || Width > EfiPciIoWidthUint64) {\r
+ if ((UINT32)Width > EfiPciIoWidthUint64) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
\r
//\r
// If request is not aligned, then convert request to EfiPciIoWithXXXUint8\r
- // \r
+ //\r
if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {\r
if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {\r
Status = PciIoIoRead (This, Width, BarIndex, Offset, 1, Result);\r
} while (TRUE);\r
}\r
}\r
- \r
+\r
Status = PciIoDevice->PciRootBridgeIo->PollIo (\r
PciIoDevice->PciRootBridgeIo,\r
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
);\r
\r
if (EFI_ERROR (Status)) {\r
- ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,\r
+ PciIoDevice->DevicePath\r
+ );\r
}\r
\r
return Status;\r
\r
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
\r
- if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ if ((UINT32)Width >= EfiPciIoWidthMaximum) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
\r
//\r
// If request is not aligned, then convert request to EfiPciIoWithXXXUint8\r
- // \r
+ //\r
if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {\r
if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {\r
Count *= (UINTN)(1 << (Width & 0x03));\r
Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03));\r
}\r
- } \r
- \r
+ }\r
+\r
\r
Status = PciIoDevice->PciRootBridgeIo->Mem.Read (\r
PciIoDevice->PciRootBridgeIo,\r
);\r
\r
if (EFI_ERROR (Status)) {\r
- ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR,\r
+ PciIoDevice->DevicePath\r
+ );\r
}\r
\r
return Status;\r
\r
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
\r
- if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ if ((UINT32)Width >= EfiPciIoWidthMaximum) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
\r
//\r
// If request is not aligned, then convert request to EfiPciIoWithXXXUint8\r
- // \r
+ //\r
if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {\r
if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {\r
Count *= (UINTN)(1 << (Width & 0x03));\r
);\r
\r
if (EFI_ERROR (Status)) {\r
- ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR,\r
+ PciIoDevice->DevicePath\r
+ );\r
}\r
\r
return Status;\r
\r
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
\r
- if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ if ((UINT32)Width >= EfiPciIoWidthMaximum) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
\r
//\r
// If request is not aligned, then convert request to EfiPciIoWithXXXUint8\r
- // \r
+ //\r
if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {\r
if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {\r
Count *= (UINTN)(1 << (Width & 0x03));\r
Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03));\r
}\r
- } \r
+ }\r
\r
Status = PciIoDevice->PciRootBridgeIo->Io.Read (\r
PciIoDevice->PciRootBridgeIo,\r
);\r
\r
if (EFI_ERROR (Status)) {\r
- ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR,\r
+ PciIoDevice->DevicePath\r
+ );\r
}\r
\r
return Status;\r
\r
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
\r
- if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ if ((UINT32)Width >= EfiPciIoWidthMaximum) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
\r
//\r
// If request is not aligned, then convert request to EfiPciIoWithXXXUint8\r
- // \r
+ //\r
if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {\r
if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {\r
Count *= (UINTN)(1 << (Width & 0x03));\r
Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03));\r
}\r
- } \r
+ }\r
\r
Status = PciIoDevice->PciRootBridgeIo->Io.Write (\r
PciIoDevice->PciRootBridgeIo,\r
);\r
\r
if (EFI_ERROR (Status)) {\r
- ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR,\r
+ PciIoDevice->DevicePath\r
+ );\r
}\r
\r
return Status;\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- \r
+\r
//\r
// If request is not aligned, then convert request to EfiPciIoWithXXXUint8\r
- // \r
+ //\r
if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {\r
if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {\r
Count *= (UINTN)(1 << (Width & 0x03));\r
Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03));\r
}\r
- } \r
+ }\r
\r
Status = PciIoDevice->PciRootBridgeIo->Pci.Read (\r
PciIoDevice->PciRootBridgeIo,\r
);\r
\r
if (EFI_ERROR (Status)) {\r
- ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR,\r
+ PciIoDevice->DevicePath\r
+ );\r
}\r
\r
return Status;\r
\r
//\r
// If request is not aligned, then convert request to EfiPciIoWithXXXUint8\r
- // \r
+ //\r
if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {\r
if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {\r
Count *= (UINTN)(1 << (Width & 0x03));\r
Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03));\r
}\r
- } \r
- \r
+ }\r
+\r
Status = PciIoDevice->PciRootBridgeIo->Pci.Write (\r
PciIoDevice->PciRootBridgeIo,\r
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
);\r
\r
if (EFI_ERROR (Status)) {\r
- ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR,\r
+ PciIoDevice->DevicePath\r
+ );\r
}\r
\r
return Status;\r
\r
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
\r
- if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+ if ((UINT32)Width >= EfiPciIoWidthMaximum) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
\r
//\r
// If request is not aligned, then convert request to EfiPciIoWithXXXUint8\r
- // \r
+ //\r
if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {\r
if ((SrcOffset & ((1 << (Width & 0x03)) - 1)) != 0 || (DestOffset & ((1 << (Width & 0x03)) - 1)) != 0) {\r
Count *= (UINTN)(1 << (Width & 0x03));\r
Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03));\r
}\r
- } \r
+ }\r
\r
Status = PciIoDevice->PciRootBridgeIo->CopyMem (\r
PciIoDevice->PciRootBridgeIo,\r
);\r
\r
if (EFI_ERROR (Status)) {\r
- ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,\r
+ PciIoDevice->DevicePath\r
+ );\r
}\r
\r
return Status;\r
OUT VOID **Mapping\r
)\r
{\r
- EFI_STATUS Status;\r
- PCI_IO_DEVICE *PciIoDevice;\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ UINT64 IoMmuAttribute;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION RootBridgeIoOperation;\r
\r
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
\r
- if (Operation < 0 || Operation >= EfiPciIoOperationMaximum) {\r
+ if ((UINT32)Operation >= EfiPciIoOperationMaximum) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ RootBridgeIoOperation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION)Operation;\r
if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) {\r
- Operation = (EFI_PCI_IO_PROTOCOL_OPERATION) (Operation + EfiPciOperationBusMasterRead64);\r
+ RootBridgeIoOperation = (EFI_PCI_ROOT_BRIDGE_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
+ RootBridgeIoOperation,\r
HostAddress,\r
NumberOfBytes,\r
DeviceAddress,\r
);\r
\r
if (EFI_ERROR (Status)) {\r
- ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,\r
+ PciIoDevice->DevicePath\r
+ );\r
+ }\r
+\r
+ if (mIoMmuProtocol != NULL) {\r
+ if (!EFI_ERROR (Status)) {\r
+ switch (Operation) {\r
+ case EfiPciIoOperationBusMasterRead:\r
+ IoMmuAttribute = EDKII_IOMMU_ACCESS_READ;\r
+ break;\r
+ case EfiPciIoOperationBusMasterWrite:\r
+ IoMmuAttribute = EDKII_IOMMU_ACCESS_WRITE;\r
+ break;\r
+ case EfiPciIoOperationBusMasterCommonBuffer:\r
+ IoMmuAttribute = EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE;\r
+ break;\r
+ default:\r
+ ASSERT(FALSE);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ mIoMmuProtocol->SetAttribute (\r
+ mIoMmuProtocol,\r
+ PciIoDevice->Handle,\r
+ *Mapping,\r
+ IoMmuAttribute\r
+ );\r
+ }\r
}\r
\r
return Status;\r
\r
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
\r
+ if (mIoMmuProtocol != NULL) {\r
+ mIoMmuProtocol->SetAttribute (\r
+ mIoMmuProtocol,\r
+ PciIoDevice->Handle,\r
+ Mapping,\r
+ 0\r
+ );\r
+ }\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
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,\r
+ PciIoDevice->DevicePath\r
+ );\r
}\r
\r
return Status;\r
\r
/**\r
Allocates pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer\r
- mapping.\r
+ or EfiPciOperationBusMasterCommonBuffer64 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
\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
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED and DUAL_ADDRESS_CYCLE.\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
\r
if (EFI_ERROR (Status)) {\r
- ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,\r
+ PciIoDevice->DevicePath\r
+ );\r
}\r
\r
return Status;\r
);\r
\r
if (EFI_ERROR (Status)) {\r
- ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,\r
+ PciIoDevice->DevicePath\r
+ );\r
}\r
\r
return Status;\r
PciIoDevice->PciRootBridgeIo\r
);\r
if (EFI_ERROR (Status)) {\r
- ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,\r
+ PciIoDevice->DevicePath\r
+ );\r
}\r
\r
return Status;\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
+ @retval EFI_SUCCESS Successfully set new attributes.\r
\r
**/\r
EFI_STATUS\r
}\r
\r
//\r
- // Mask off EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE & \r
- // EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM, which are not supported by PCI root bridge.\r
+ // Mask off attributes not supported by PCI root bridge.\r
//\r
Attributes &= ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |\r
- EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM);\r
+ EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |\r
+ EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE);\r
\r
//\r
// Record the new attribute of the Root Bridge\r
}\r
\r
//\r
- // Get the boot VGA on the same segement\r
+ // Get the boot VGA on the same Host Bridge\r
//\r
- Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);\r
+ Temp = LocateVgaDeviceOnHostBridge (PciIoDevice->PciRootBridgeIo->ParentHandle);\r
\r
if (Temp == NULL) {\r
//\r
- // If there is no VGA device on the segement, set\r
+ // If there is no VGA device on the segment, set\r
// this graphics card to decode the palette range\r
//\r
return EFI_SUCCESS;\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
+ Temp->Attributes &= (~(UINT64)EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);\r
} else {\r
return EFI_UNSUPPORTED;\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
+ // So, this logic doesn't conform 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
);\r
}\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 | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) != 0) {\r
+ if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) != 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
//\r
// If no attributes can be supported, then return.\r
// Otherwise, set the attributes that it can support.\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
//\r
if (Operation == EfiPciIoAttributeOperationEnable) {\r
//\r
- // Check if there have been an active VGA device on the same segment\r
+ // Check if there have been an active VGA device on the same Host Bridge\r
//\r
- Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);\r
+ Temp = LocateVgaDeviceOnHostBridge (PciIoDevice->PciRootBridgeIo->ParentHandle);\r
if (Temp != NULL && Temp != PciIoDevice) {\r
//\r
// An active VGA has been detected, so can not enable another\r
Command |= EFI_PCI_COMMAND_BUS_MASTER;\r
}\r
//\r
- // The upstream bridge should be also set to revelant attribute\r
+ // The upstream bridge should be also set to relevant attribute\r
// expect for IO, Mem and BusMaster\r
//\r
UpStreamAttributes = Attributes &\r
}\r
\r
if (EFI_ERROR (Status)) {\r
- ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,\r
+ PciIoDevice->DevicePath\r
+ );\r
}\r
\r
return Status;\r
}\r
\r
+/**\r
+ Retrieve the AddrTranslationOffset from RootBridgeIo for the\r
+ specified range.\r
+\r
+ @param RootBridgeIo Root Bridge IO instance.\r
+ @param AddrRangeMin The base address of the MMIO.\r
+ @param AddrLen The length of the MMIO.\r
+\r
+ @retval The AddrTranslationOffset from RootBridgeIo for the\r
+ specified range, or (UINT64) -1 if the range is not\r
+ found in RootBridgeIo.\r
+**/\r
+UINT64\r
+GetMmioAddressTranslationOffset (\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *RootBridgeIo,\r
+ UINT64 AddrRangeMin,\r
+ UINT64 AddrLen\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
+\r
+ Status = RootBridgeIo->Configuration (\r
+ RootBridgeIo,\r
+ (VOID **) &Configuration\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return (UINT64) -1;\r
+ }\r
+\r
+ // According to UEFI 2.7, EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL::Configuration()\r
+ // returns host address instead of device address, while AddrTranslationOffset\r
+ // is not zero, and device address = host address + AddrTranslationOffset, so\r
+ // we convert host address to device address for range compare.\r
+ while (Configuration->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
+ if ((Configuration->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) &&\r
+ (Configuration->AddrRangeMin + Configuration->AddrTranslationOffset <= AddrRangeMin) &&\r
+ (Configuration->AddrRangeMin + Configuration->AddrLen + Configuration->AddrTranslationOffset >= AddrRangeMin + AddrLen)\r
+ ) {\r
+ return Configuration->AddrTranslationOffset;\r
+ }\r
+ Configuration++;\r
+ }\r
+\r
+ //\r
+ // The resource occupied by BAR should be in the range reported by RootBridge.\r
+ //\r
+ ASSERT (FALSE);\r
+ return (UINT64) -1;\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
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
+ @param Resources A pointer to the 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
+ is not NULL, then the 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
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
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+ EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
\r
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- if (BarIndex >= PCI_MAX_BAR) {\r
+ if ((BarIndex >= PCI_MAX_BAR) || (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown)) {\r
return EFI_UNSUPPORTED;\r
}\r
\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
+ Descriptor = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
+ if (Descriptor == 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 = (UINT16) (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
+ *Resources = Descriptor;\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
+ Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Descriptor->Len = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);\r
+ Descriptor->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress;\r
+ Descriptor->AddrLen = PciIoDevice->PciBar[BarIndex].Length;\r
+ Descriptor->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment;\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
+ switch (PciIoDevice->PciBar[BarIndex].BarType) {\r
+ case PciBarTypeIo16:\r
+ case PciBarTypeIo32:\r
+ //\r
+ // Io\r
+ //\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\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
+ case PciBarTypePMem32:\r
+ //\r
+ // prefetchable\r
+ //\r
+ Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+ //\r
+ // Fall through\r
+ //\r
+ case PciBarTypeMem32:\r
+ //\r
+ // Mem\r
+ //\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ //\r
+ // 32 bit\r
+ //\r
+ Descriptor->AddrSpaceGranularity = 32;\r
+ break;\r
\r
- default:\r
- break;\r
- }\r
+ case PciBarTypePMem64:\r
+ //\r
+ // prefetchable\r
+ //\r
+ Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+ //\r
+ // Fall through\r
+ //\r
+ case PciBarTypeMem64:\r
+ //\r
+ // Mem\r
+ //\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ //\r
+ // 64 bit\r
+ //\r
+ Descriptor->AddrSpaceGranularity = 64;\r
+ break;\r
\r
- Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
+ default:\r
+ break;\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
+ End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);\r
+ End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+ End->Checksum = 0;\r
+\r
+ //\r
+ // Get the Address Translation Offset\r
+ //\r
+ if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
+ Descriptor->AddrTranslationOffset = GetMmioAddressTranslationOffset (\r
+ PciIoDevice->PciRootBridgeIo,\r
+ Descriptor->AddrRangeMin,\r
+ Descriptor->AddrLen\r
+ );\r
+ if (Descriptor->AddrTranslationOffset == (UINT64) -1) {\r
+ FreePool (Descriptor);\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
\r
- *Resources = Configuration;\r
+ // According to UEFI spec 2.7, we need return host address for\r
+ // PciIo->GetBarAttributes, and host address = device address - translation.\r
+ Descriptor->AddrRangeMin -= Descriptor->AddrTranslationOffset;\r
}\r
\r
return EFI_SUCCESS;\r
return EFI_UNSUPPORTED;\r
}\r
//\r
- // Attributes must be supported. Make sure the BAR range describd by BarIndex, Offset, and\r
+ // Attributes must be supported. Make sure the BAR range described by BarIndex, Offset, and\r
// Length are valid for this PCI device.\r
//\r
NonRelativeOffset = *Offset;\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